From: James Hogan <james.hogan@imgtec.com>
To: Sifan Naeem <sifan.naeem@imgtec.com>, <mchehab@osg.samsung.com>
Cc: <linux-kernel@vger.kernel.org>, <linux-media@vger.kernel.org>,
<james.hartley@imgtec.com>, <ezequiel.garcia@imgtec.com>
Subject: Re: [PATCH 3/5] rc: img-ir: biphase enabled with workaround
Date: Mon, 8 Dec 2014 17:17:52 +0000 [thread overview]
Message-ID: <5485DD40.60500@imgtec.com> (raw)
In-Reply-To: <1417707523-7730-4-git-send-email-sifan.naeem@imgtec.com>
[-- Attachment #1: Type: text/plain, Size: 7083 bytes --]
On 04/12/14 15:38, Sifan Naeem wrote:
> Biphase decoding in the current img-ir has got a quirk, where multiple
> Interrupts are generated when an incomplete IR code is received by the
> decoder.
>
> Patch adds a work around for the quirk and enables biphase decoding.
>
> Signed-off-by: Sifan Naeem <sifan.naeem@imgtec.com>
> ---
> drivers/media/rc/img-ir/img-ir-hw.c | 56 +++++++++++++++++++++++++++++++++--
> drivers/media/rc/img-ir/img-ir-hw.h | 2 ++
> 2 files changed, 55 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c
> index 4a1407b..a977467 100644
> --- a/drivers/media/rc/img-ir/img-ir-hw.c
> +++ b/drivers/media/rc/img-ir/img-ir-hw.c
> @@ -52,6 +52,11 @@ static struct img_ir_decoder *img_ir_decoders[] = {
>
> #define IMG_IR_QUIRK_CODE_BROKEN 0x1 /* Decode is broken */
> #define IMG_IR_QUIRK_CODE_LEN_INCR 0x2 /* Bit length needs increment */
> +/*
> + * The decoder generates rapid interrupts without actually having
> + * received any new data after an incomplete IR code is decoded.
> + */
> +#define IMG_IR_QUIRK_CODE_IRQ 0x4
>
> /* functions for preprocessing timings, ensuring max is set */
>
> @@ -547,6 +552,7 @@ static void img_ir_set_decoder(struct img_ir_priv *priv,
>
> /* stop the end timer and switch back to normal mode */
> del_timer_sync(&hw->end_timer);
> + del_timer_sync(&hw->suspend_timer);
FYI, this'll need rebasing due to conflicting with "img-ir/hw: Fix
potential deadlock stopping timer". The new del_timer_sync will need to
be when spin lock isn't held, i.e. still next to the other one, and
don't forget to ensure that suspend_timer doesn't get started if
hw->stopping.
> hw->mode = IMG_IR_M_NORMAL;
>
> /* clear the wakeup scancode filter */
> @@ -843,6 +849,26 @@ static void img_ir_end_timer(unsigned long arg)
> spin_unlock_irq(&priv->lock);
> }
>
> +/*
> + * Timer function to re-enable the current protocol after it had been
> + * cleared when invalid interrupts were generated due to a quirk in the
> + * img-ir decoder.
> + */
> +static void img_ir_suspend_timer(unsigned long arg)
> +{
> + struct img_ir_priv *priv = (struct img_ir_priv *)arg;
> +
You should take the spin lock for most of this function now that
"img-ir/hw: Fix potential deadlock stopping timer" is applied and it is
safe to do so.
> + img_ir_write(priv, IMG_IR_IRQ_CLEAR,
> + IMG_IR_IRQ_ALL & ~IMG_IR_IRQ_EDGE);
> +
> + /* Don't set IRQ if it has changed in a different context. */
Wouldn't hurt to clarify this while you're at it (it confused me for a
moment thinking it was concerned about the enabled raw event IRQs
(IMG_IR_IRQ_EDGE) changing).
Maybe "Don't overwrite enabled valid/match IRQs if they have already
been changed by e.g. a filter change".
Should you even be clearing IRQs in that case? Maybe safer to just treat
that case as a "return immediately without touching anything" sort of
situation.
> + if ((priv->hw.suspend_irqen & IMG_IR_IRQ_EDGE) ==
> + img_ir_read(priv, IMG_IR_IRQ_ENABLE))
> + img_ir_write(priv, IMG_IR_IRQ_ENABLE, priv->hw.suspend_irqen);
> + /* enable */
> + img_ir_write(priv, IMG_IR_CONTROL, priv->hw.reg_timings.ctrl);
> +}
> +
> #ifdef CONFIG_COMMON_CLK
> static void img_ir_change_frequency(struct img_ir_priv *priv,
> struct clk_notifier_data *change)
> @@ -908,15 +934,37 @@ void img_ir_isr_hw(struct img_ir_priv *priv, u32 irq_status)
> if (!hw->decoder)
> return;
>
> + ct = hw->decoder->control.code_type;
> +
> ir_status = img_ir_read(priv, IMG_IR_STATUS);
> - if (!(ir_status & (IMG_IR_RXDVAL | IMG_IR_RXDVALD2)))
> + if (!(ir_status & (IMG_IR_RXDVAL | IMG_IR_RXDVALD2))) {
> + if (!(priv->hw.ct_quirks[ct] & IMG_IR_QUIRK_CODE_IRQ))
(I suggest adding "|| hw->stopping" to this case)
> + return;
> + /*
> + * The below functionality is added as a work around to stop
> + * multiple Interrupts generated when an incomplete IR code is
> + * received by the decoder.
> + * The decoder generates rapid interrupts without actually
> + * having received any new data. After a single interrupt it's
> + * expected to clear up, but instead multiple interrupts are
> + * rapidly generated. only way to get out of this loop is to
> + * reset the control register after a short delay.
> + */
> + img_ir_write(priv, IMG_IR_CONTROL, 0);
> + hw->suspend_irqen = img_ir_read(priv, IMG_IR_IRQ_ENABLE);
You're reusing hw->suspend_irqen. What if you get this workaround being
activated between img_ir_enable_wake() and img_ir_disable_wake()? I
suggest just using a new img_ir_priv_hw member.
The rest looks reasonable to me, even if unfortunate that it is
necessary in the first place.
Thanks for the hard work!
Cheers
James
> + img_ir_write(priv, IMG_IR_IRQ_ENABLE,
> + hw->suspend_irqen & IMG_IR_IRQ_EDGE);
> +
> + /* Timer activated to re-enable the protocol. */
> + mod_timer(&hw->suspend_timer,
> + jiffies + msecs_to_jiffies(5));
> return;
> + }
> ir_status &= ~(IMG_IR_RXDVAL | IMG_IR_RXDVALD2);
> img_ir_write(priv, IMG_IR_STATUS, ir_status);
>
> len = (ir_status & IMG_IR_RXDLEN) >> IMG_IR_RXDLEN_SHIFT;
> /* some versions report wrong length for certain code types */
> - ct = hw->decoder->control.code_type;
> if (hw->ct_quirks[ct] & IMG_IR_QUIRK_CODE_LEN_INCR)
> ++len;
>
> @@ -958,7 +1006,7 @@ static void img_ir_probe_hw_caps(struct img_ir_priv *priv)
> hw->ct_quirks[IMG_IR_CODETYPE_PULSELEN]
> |= IMG_IR_QUIRK_CODE_LEN_INCR;
> hw->ct_quirks[IMG_IR_CODETYPE_BIPHASE]
> - |= IMG_IR_QUIRK_CODE_BROKEN;
> + |= IMG_IR_QUIRK_CODE_IRQ;
> hw->ct_quirks[IMG_IR_CODETYPE_2BITPULSEPOS]
> |= IMG_IR_QUIRK_CODE_BROKEN;
> }
> @@ -977,6 +1025,8 @@ int img_ir_probe_hw(struct img_ir_priv *priv)
>
> /* Set up the end timer */
> setup_timer(&hw->end_timer, img_ir_end_timer, (unsigned long)priv);
> + setup_timer(&hw->suspend_timer, img_ir_suspend_timer,
> + (unsigned long)priv);
>
> /* Register a clock notifier */
> if (!IS_ERR(priv->clk)) {
> diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h
> index 5e59e8e..8578aa7 100644
> --- a/drivers/media/rc/img-ir/img-ir-hw.h
> +++ b/drivers/media/rc/img-ir/img-ir-hw.h
> @@ -221,6 +221,7 @@ enum img_ir_mode {
> * @rdev: Remote control device
> * @clk_nb: Notifier block for clock notify events.
> * @end_timer: Timer until repeat timeout.
> + * @suspend_timer: Timer to re-enable protocol.
> * @decoder: Current decoder settings.
> * @enabled_protocols: Currently enabled protocols.
> * @clk_hz: Current core clock rate in Hz.
> @@ -235,6 +236,7 @@ struct img_ir_priv_hw {
> struct rc_dev *rdev;
> struct notifier_block clk_nb;
> struct timer_list end_timer;
> + struct timer_list suspend_timer;
> const struct img_ir_decoder *decoder;
> u64 enabled_protocols;
> unsigned long clk_hz;
>
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
next prev parent reply other threads:[~2014-12-08 17:17 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-12-04 15:38 [PATCH 0/5] rc: img-ir: rc5 and rc6 support added Sifan Naeem
2014-12-04 15:38 ` [PATCH 1/5] rc: img-ir: add scancode requests to a struct Sifan Naeem
2014-12-08 16:47 ` James Hogan
2014-12-04 15:38 ` [PATCH 2/5] rc: img-ir: pass toggle bit to the rc driver Sifan Naeem
2014-12-08 16:49 ` James Hogan
2014-12-04 15:38 ` [PATCH 3/5] rc: img-ir: biphase enabled with workaround Sifan Naeem
2014-12-08 17:17 ` James Hogan [this message]
2014-12-11 18:54 ` Sifan Naeem
2014-12-12 10:55 ` James Hogan
2014-12-12 12:35 ` Sifan Naeem
2014-12-04 15:38 ` [PATCH 4/5] rc: img-ir: add philips rc5 decoder module Sifan Naeem
2014-12-08 17:41 ` James Hogan
2014-12-04 15:38 ` [PATCH 5/5] rc: img-ir: add philips rc6 " Sifan Naeem
2014-12-08 17:45 ` James Hogan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5485DD40.60500@imgtec.com \
--to=james.hogan@imgtec.com \
--cc=ezequiel.garcia@imgtec.com \
--cc=james.hartley@imgtec.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=mchehab@osg.samsung.com \
--cc=sifan.naeem@imgtec.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.