aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSifan Naeem <sifan.naeem@imgtec.com>2014-12-11 15:06:24 -0500
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2014-12-23 12:15:26 -0500
commit02744c8c9a11a64bce740528077cf5223ab60e31 (patch)
treec8399b84b64f3807feef2711843c9f7b665cc4b8
parent33e01833268d2f006e599b863a21d4e219f96bd7 (diff)
[media] rc: img-ir: biphase enabled with workaround
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> Acked-by: James Hogan <james.hogan@imgtec.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
-rw-r--r--drivers/media/rc/img-ir/img-ir-hw.c60
-rw-r--r--drivers/media/rc/img-ir/img-ir-hw.h4
2 files changed, 61 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 9cecda73f980..5c32f05b32ec 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[] = {
52 52
53#define IMG_IR_QUIRK_CODE_BROKEN 0x1 /* Decode is broken */ 53#define IMG_IR_QUIRK_CODE_BROKEN 0x1 /* Decode is broken */
54#define IMG_IR_QUIRK_CODE_LEN_INCR 0x2 /* Bit length needs increment */ 54#define IMG_IR_QUIRK_CODE_LEN_INCR 0x2 /* Bit length needs increment */
55/*
56 * The decoder generates rapid interrupts without actually having
57 * received any new data after an incomplete IR code is decoded.
58 */
59#define IMG_IR_QUIRK_CODE_IRQ 0x4
55 60
56/* functions for preprocessing timings, ensuring max is set */ 61/* functions for preprocessing timings, ensuring max is set */
57 62
@@ -542,6 +547,7 @@ static void img_ir_set_decoder(struct img_ir_priv *priv,
542 */ 547 */
543 spin_unlock_irq(&priv->lock); 548 spin_unlock_irq(&priv->lock);
544 del_timer_sync(&hw->end_timer); 549 del_timer_sync(&hw->end_timer);
550 del_timer_sync(&hw->suspend_timer);
545 spin_lock_irq(&priv->lock); 551 spin_lock_irq(&priv->lock);
546 552
547 hw->stopping = false; 553 hw->stopping = false;
@@ -861,6 +867,29 @@ static void img_ir_end_timer(unsigned long arg)
861 spin_unlock_irq(&priv->lock); 867 spin_unlock_irq(&priv->lock);
862} 868}
863 869
870/*
871 * Timer function to re-enable the current protocol after it had been
872 * cleared when invalid interrupts were generated due to a quirk in the
873 * img-ir decoder.
874 */
875static void img_ir_suspend_timer(unsigned long arg)
876{
877 struct img_ir_priv *priv = (struct img_ir_priv *)arg;
878
879 spin_lock_irq(&priv->lock);
880 /*
881 * Don't overwrite enabled valid/match IRQs if they have already been
882 * changed by e.g. a filter change.
883 */
884 if ((priv->hw.quirk_suspend_irq & IMG_IR_IRQ_EDGE) ==
885 img_ir_read(priv, IMG_IR_IRQ_ENABLE))
886 img_ir_write(priv, IMG_IR_IRQ_ENABLE,
887 priv->hw.quirk_suspend_irq);
888 /* enable */
889 img_ir_write(priv, IMG_IR_CONTROL, priv->hw.reg_timings.ctrl);
890 spin_unlock_irq(&priv->lock);
891}
892
864#ifdef CONFIG_COMMON_CLK 893#ifdef CONFIG_COMMON_CLK
865static void img_ir_change_frequency(struct img_ir_priv *priv, 894static void img_ir_change_frequency(struct img_ir_priv *priv,
866 struct clk_notifier_data *change) 895 struct clk_notifier_data *change)
@@ -926,15 +955,38 @@ void img_ir_isr_hw(struct img_ir_priv *priv, u32 irq_status)
926 if (!hw->decoder) 955 if (!hw->decoder)
927 return; 956 return;
928 957
958 ct = hw->decoder->control.code_type;
959
929 ir_status = img_ir_read(priv, IMG_IR_STATUS); 960 ir_status = img_ir_read(priv, IMG_IR_STATUS);
930 if (!(ir_status & (IMG_IR_RXDVAL | IMG_IR_RXDVALD2))) 961 if (!(ir_status & (IMG_IR_RXDVAL | IMG_IR_RXDVALD2))) {
962 if (!(priv->hw.ct_quirks[ct] & IMG_IR_QUIRK_CODE_IRQ) ||
963 hw->stopping)
964 return;
965 /*
966 * The below functionality is added as a work around to stop
967 * multiple Interrupts generated when an incomplete IR code is
968 * received by the decoder.
969 * The decoder generates rapid interrupts without actually
970 * having received any new data. After a single interrupt it's
971 * expected to clear up, but instead multiple interrupts are
972 * rapidly generated. only way to get out of this loop is to
973 * reset the control register after a short delay.
974 */
975 img_ir_write(priv, IMG_IR_CONTROL, 0);
976 hw->quirk_suspend_irq = img_ir_read(priv, IMG_IR_IRQ_ENABLE);
977 img_ir_write(priv, IMG_IR_IRQ_ENABLE,
978 hw->quirk_suspend_irq & IMG_IR_IRQ_EDGE);
979
980 /* Timer activated to re-enable the protocol. */
981 mod_timer(&hw->suspend_timer,
982 jiffies + msecs_to_jiffies(5));
931 return; 983 return;
984 }
932 ir_status &= ~(IMG_IR_RXDVAL | IMG_IR_RXDVALD2); 985 ir_status &= ~(IMG_IR_RXDVAL | IMG_IR_RXDVALD2);
933 img_ir_write(priv, IMG_IR_STATUS, ir_status); 986 img_ir_write(priv, IMG_IR_STATUS, ir_status);
934 987
935 len = (ir_status & IMG_IR_RXDLEN) >> IMG_IR_RXDLEN_SHIFT; 988 len = (ir_status & IMG_IR_RXDLEN) >> IMG_IR_RXDLEN_SHIFT;
936 /* some versions report wrong length for certain code types */ 989 /* some versions report wrong length for certain code types */
937 ct = hw->decoder->control.code_type;
938 if (hw->ct_quirks[ct] & IMG_IR_QUIRK_CODE_LEN_INCR) 990 if (hw->ct_quirks[ct] & IMG_IR_QUIRK_CODE_LEN_INCR)
939 ++len; 991 ++len;
940 992
@@ -976,7 +1028,7 @@ static void img_ir_probe_hw_caps(struct img_ir_priv *priv)
976 hw->ct_quirks[IMG_IR_CODETYPE_PULSELEN] 1028 hw->ct_quirks[IMG_IR_CODETYPE_PULSELEN]
977 |= IMG_IR_QUIRK_CODE_LEN_INCR; 1029 |= IMG_IR_QUIRK_CODE_LEN_INCR;
978 hw->ct_quirks[IMG_IR_CODETYPE_BIPHASE] 1030 hw->ct_quirks[IMG_IR_CODETYPE_BIPHASE]
979 |= IMG_IR_QUIRK_CODE_BROKEN; 1031 |= IMG_IR_QUIRK_CODE_IRQ;
980 hw->ct_quirks[IMG_IR_CODETYPE_2BITPULSEPOS] 1032 hw->ct_quirks[IMG_IR_CODETYPE_2BITPULSEPOS]
981 |= IMG_IR_QUIRK_CODE_BROKEN; 1033 |= IMG_IR_QUIRK_CODE_BROKEN;
982} 1034}
@@ -995,6 +1047,8 @@ int img_ir_probe_hw(struct img_ir_priv *priv)
995 1047
996 /* Set up the end timer */ 1048 /* Set up the end timer */
997 setup_timer(&hw->end_timer, img_ir_end_timer, (unsigned long)priv); 1049 setup_timer(&hw->end_timer, img_ir_end_timer, (unsigned long)priv);
1050 setup_timer(&hw->suspend_timer, img_ir_suspend_timer,
1051 (unsigned long)priv);
998 1052
999 /* Register a clock notifier */ 1053 /* Register a clock notifier */
1000 if (!IS_ERR(priv->clk)) { 1054 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 beac3a6c4660..b31ffc947e41 100644
--- a/drivers/media/rc/img-ir/img-ir-hw.h
+++ b/drivers/media/rc/img-ir/img-ir-hw.h
@@ -218,6 +218,7 @@ enum img_ir_mode {
218 * @rdev: Remote control device 218 * @rdev: Remote control device
219 * @clk_nb: Notifier block for clock notify events. 219 * @clk_nb: Notifier block for clock notify events.
220 * @end_timer: Timer until repeat timeout. 220 * @end_timer: Timer until repeat timeout.
221 * @suspend_timer: Timer to re-enable protocol.
221 * @decoder: Current decoder settings. 222 * @decoder: Current decoder settings.
222 * @enabled_protocols: Currently enabled protocols. 223 * @enabled_protocols: Currently enabled protocols.
223 * @clk_hz: Current core clock rate in Hz. 224 * @clk_hz: Current core clock rate in Hz.
@@ -228,12 +229,14 @@ enum img_ir_mode {
228 * @stopping: Indicates that decoder is being taken down and timers 229 * @stopping: Indicates that decoder is being taken down and timers
229 * should not be restarted. 230 * should not be restarted.
230 * @suspend_irqen: Saved IRQ enable mask over suspend. 231 * @suspend_irqen: Saved IRQ enable mask over suspend.
232 * @quirk_suspend_irq: Saved IRQ enable mask over quirk suspend timer.
231 */ 233 */
232struct img_ir_priv_hw { 234struct img_ir_priv_hw {
233 unsigned int ct_quirks[4]; 235 unsigned int ct_quirks[4];
234 struct rc_dev *rdev; 236 struct rc_dev *rdev;
235 struct notifier_block clk_nb; 237 struct notifier_block clk_nb;
236 struct timer_list end_timer; 238 struct timer_list end_timer;
239 struct timer_list suspend_timer;
237 const struct img_ir_decoder *decoder; 240 const struct img_ir_decoder *decoder;
238 u64 enabled_protocols; 241 u64 enabled_protocols;
239 unsigned long clk_hz; 242 unsigned long clk_hz;
@@ -244,6 +247,7 @@ struct img_ir_priv_hw {
244 enum img_ir_mode mode; 247 enum img_ir_mode mode;
245 bool stopping; 248 bool stopping;
246 u32 suspend_irqen; 249 u32 suspend_irqen;
250 u32 quirk_suspend_irq;
247}; 251};
248 252
249static inline bool img_ir_hw_enabled(struct img_ir_priv_hw *hw) 253static inline bool img_ir_hw_enabled(struct img_ir_priv_hw *hw)