[PATCH 5/5] rc: img-ir: add philips rc6 decoder module
Add img-ir module for decoding Philips rc6 protocol. Signed-off-by: Sifan Naeem --- drivers/media/rc/img-ir/Kconfig |8 +++ drivers/media/rc/img-ir/Makefile |1 + drivers/media/rc/img-ir/img-ir-hw.c |3 + drivers/media/rc/img-ir/img-ir-hw.h |1 + drivers/media/rc/img-ir/img-ir-rc6.c | 117 ++ 5 files changed, 130 insertions(+) create mode 100644 drivers/media/rc/img-ir/img-ir-rc6.c diff --git a/drivers/media/rc/img-ir/Kconfig b/drivers/media/rc/img-ir/Kconfig index b5b114f..4d3fca9 100644 --- a/drivers/media/rc/img-ir/Kconfig +++ b/drivers/media/rc/img-ir/Kconfig @@ -66,3 +66,11 @@ config IR_IMG_RC5 help Say Y here to enable support for the RC5 protocol in the ImgTec infrared decoder block. + +config IR_IMG_RC6 + bool "Phillips RC6 protocol support" + depends on IR_IMG_HW + help + Say Y here to enable support for the RC6 protocol in the ImgTec + infrared decoder block. + Note: This version only supports mode 0. diff --git a/drivers/media/rc/img-ir/Makefile b/drivers/media/rc/img-ir/Makefile index 898b1b8..8e6d458 100644 --- a/drivers/media/rc/img-ir/Makefile +++ b/drivers/media/rc/img-ir/Makefile @@ -7,6 +7,7 @@ img-ir-$(CONFIG_IR_IMG_SONY)+= img-ir-sony.o img-ir-$(CONFIG_IR_IMG_SHARP) += img-ir-sharp.o img-ir-$(CONFIG_IR_IMG_SANYO) += img-ir-sanyo.o img-ir-$(CONFIG_IR_IMG_RC5)+= img-ir-rc5.o +img-ir-$(CONFIG_IR_IMG_RC6)+= img-ir-rc6.o img-ir-objs:= $(img-ir-y) obj-$(CONFIG_IR_IMG) += img-ir.o diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c index 322cdf8..3b70dc2 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.c +++ b/drivers/media/rc/img-ir/img-ir-hw.c @@ -45,6 +45,9 @@ static struct img_ir_decoder *img_ir_decoders[] = { #ifdef CONFIG_IR_IMG_RC5 &img_ir_rc5, #endif +#ifdef CONFIG_IR_IMG_RC6 + &img_ir_rc6, +#endif NULL }; diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h index f124ec5..c7b6e1a 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.h +++ b/drivers/media/rc/img-ir/img-ir-hw.h @@ -188,6 +188,7 @@ extern struct img_ir_decoder img_ir_sony; extern struct img_ir_decoder img_ir_sharp; extern struct img_ir_decoder img_ir_sanyo; extern struct img_ir_decoder img_ir_rc5; +extern struct img_ir_decoder img_ir_rc6; /** * struct img_ir_reg_timings - Reg values for decoder timings at clock rate. diff --git a/drivers/media/rc/img-ir/img-ir-rc6.c b/drivers/media/rc/img-ir/img-ir-rc6.c new file mode 100644 index 000..bcd0822 --- /dev/null +++ b/drivers/media/rc/img-ir/img-ir-rc6.c @@ -0,0 +1,117 @@ +/* + * ImgTec IR Decoder setup for Phillips RC-6 protocol. + * + * Copyright 2012-2014 Imagination Technologies Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include "img-ir-hw.h" + +/* Convert RC6 data to a scancode */ +static int img_ir_rc6_scancode(int len, u64 raw, u64 enabled_protocols, + struct img_ir_scancode_req *request) +{ + unsigned int addr, cmd, mode, trl1, trl2; + + /* +* Due to a side effect of the decoder handling the double length +* Trailer bit, the header information is a bit scrambled, and the +* raw data is shifted incorrectly. +* This workaround effectively recovers the header bits. +* +* The Header field should look like this: +* +* StartBit ModeBit2 ModeBit1 ModeBit0 TrailerBit +* +* But what we get is: +* +* ModeBit2 ModeBit1 ModeBit0 TrailerBit1 TrailerBit2 +* +* The start bit is not important to recover the scancode. +*/ + + raw >>= 27; + + trl1= (raw >> 17) & 0x01; + trl2= (raw >> 16) & 0x01; + + mode= (raw >> 18) & 0x07; + addr= (raw >> 8) & 0xff; + cmd = raw & 0xff; + + /* +* Due to the above explained irregularity the trailer bits cannot +* have the same value. +*/ + if (trl1 == trl2) + return -EINVAL; + + /* Only mode 0 supported for now */ + if (mode) + return -EINVAL; + + request->protocol = RC_TYPE_RC6_0; + request->scancode = addr << 8 | cmd; + request->toggle = trl2; + return IMG_IR_SCANCODE; +} + +/* Convert RC6 scancode to RC6 data filter */ +static int img_ir_rc6_filter(const struct rc_scancode_filter *in, +struct img_ir_filter *out, u64 protocols) +{ + /* Not supported by the hw. */ +
[PATCH 1/5] rc: img-ir: add scancode requests to a struct
The information being requested of hardware decode callbacks through the img-ir-hw scancode API is mounting up, so combine it into a struct which can be passed in with a single pointer rather than multiple pointer arguments. This allows it to be extended more easily without touching all the hardware decode callbacks. Signed-off-by: Sifan Naeem --- drivers/media/rc/img-ir/img-ir-hw.c| 16 +--- drivers/media/rc/img-ir/img-ir-hw.h| 16 ++-- drivers/media/rc/img-ir/img-ir-jvc.c |8 drivers/media/rc/img-ir/img-ir-nec.c | 24 drivers/media/rc/img-ir/img-ir-sanyo.c |8 drivers/media/rc/img-ir/img-ir-sharp.c |8 drivers/media/rc/img-ir/img-ir-sony.c | 12 ++-- 7 files changed, 53 insertions(+), 39 deletions(-) diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c index ec49f94..61850a6 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.c +++ b/drivers/media/rc/img-ir/img-ir-hw.c @@ -789,20 +789,22 @@ static void img_ir_handle_data(struct img_ir_priv *priv, u32 len, u64 raw) struct img_ir_priv_hw *hw = &priv->hw; const struct img_ir_decoder *dec = hw->decoder; int ret = IMG_IR_SCANCODE; - u32 scancode; - enum rc_type protocol = RC_TYPE_UNKNOWN; + struct img_ir_scancode_req request; + + request.protocol = RC_TYPE_UNKNOWN; if (dec->scancode) - ret = dec->scancode(len, raw, &protocol, &scancode, hw->enabled_protocols); + ret = dec->scancode(len, raw, hw->enabled_protocols, &request); else if (len >= 32) - scancode = (u32)raw; + request.scancode = (u32)raw; else if (len < 32) - scancode = (u32)raw & ((1 << len)-1); + request.scancode = (u32)raw & ((1 << len)-1); dev_dbg(priv->dev, "data (%u bits) = %#llx\n", len, (unsigned long long)raw); if (ret == IMG_IR_SCANCODE) { - dev_dbg(priv->dev, "decoded scan code %#x\n", scancode); - rc_keydown(hw->rdev, protocol, scancode, 0); + dev_dbg(priv->dev, "decoded scan code %#x\n", + request.scancode); + rc_keydown(hw->rdev, request.protocol, request.scancode, 0); img_ir_end_repeat(priv); } else if (ret == IMG_IR_REPEATCODE) { if (hw->mode == IMG_IR_M_REPEATING) { diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h index 8fcc16c..1fc9583 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.h +++ b/drivers/media/rc/img-ir/img-ir-hw.h @@ -133,6 +133,18 @@ struct img_ir_timing_regvals { #define IMG_IR_REPEATCODE 1 /* repeat the previous code */ /** + * struct img_ir_scancode_req - Scancode request data. + * @protocol: Protocol code of received message (defaults to + * RC_TYPE_UNKNOWN). + * @scancode: Scan code of received message (must be written by + * handler if IMG_IR_SCANCODE is returned). + */ +struct img_ir_scancode_req { + enum rc_type protocol; + u32 scancode; +}; + +/** * struct img_ir_decoder - Decoder settings for an IR protocol. * @type: Protocol types bitmap. * @tolerance: Timing tolerance as a percentage (default 10%). @@ -162,8 +174,8 @@ struct img_ir_decoder { struct img_ir_control control; /* scancode logic */ - int (*scancode)(int len, u64 raw, enum rc_type *protocol, - u32 *scancode, u64 enabled_protocols); + int (*scancode)(int len, u64 raw, u64 enabled_protocols, + struct img_ir_scancode_req *request); int (*filter)(const struct rc_scancode_filter *in, struct img_ir_filter *out, u64 protocols); }; diff --git a/drivers/media/rc/img-ir/img-ir-jvc.c b/drivers/media/rc/img-ir/img-ir-jvc.c index a60dda8..d3e2fc0 100644 --- a/drivers/media/rc/img-ir/img-ir-jvc.c +++ b/drivers/media/rc/img-ir/img-ir-jvc.c @@ -12,8 +12,8 @@ #include "img-ir-hw.h" /* Convert JVC data to a scancode */ -static int img_ir_jvc_scancode(int len, u64 raw, enum rc_type *protocol, - u32 *scancode, u64 enabled_protocols) +static int img_ir_jvc_scancode(int len, u64 raw, u64 enabled_protocols, + struct img_ir_scancode_req *request) { unsigned int cust, data; @@ -23,8 +23,8 @@ static int img_ir_jvc_scancode(int len, u64 raw, enum rc_type *protocol, cust = (raw >> 0) & 0xff; data = (raw >> 8) & 0xff; - *protocol = RC_TYPE_JVC; - *scancode = cust << 8 | data; + request->protocol = RC_TYPE_JVC; + request->scancode = cust << 8 | data; return IMG_IR_SCANCODE; } dif
[PATCH 0/5] rc: img-ir: rc5 and rc6 support added
This patch sets adds support for rc5 and rc6 decoder modules along with workarounds for quirks in the hw which surfaces when decoding in biphase mode required by rc5 and rc6. This patch set was based on head of linux-next commit: commit 1ca7c606de868d172afb4eb65e04e290dbdb51ff Author: Stephen Rothwell Date: Thu Dec 4 19:49:10 2014 +1100 Sifan Naeem (5): rc: img-ir: add scancode requests to a struct rc: img-ir: pass toggle bit to the rc driver rc: img-ir: biphase enabled with workaround rc: img-ir: add philips rc5 decoder module rc: img-ir: add philips rc6 decoder module drivers/media/rc/img-ir/Kconfig| 15 drivers/media/rc/img-ir/Makefile |2 + drivers/media/rc/img-ir/img-ir-hw.c| 80 +++--- drivers/media/rc/img-ir/img-ir-hw.h| 22 +- drivers/media/rc/img-ir/img-ir-jvc.c |8 +-- drivers/media/rc/img-ir/img-ir-nec.c | 24 +++ drivers/media/rc/img-ir/img-ir-rc5.c | 88 drivers/media/rc/img-ir/img-ir-rc6.c | 117 drivers/media/rc/img-ir/img-ir-sanyo.c |8 +-- drivers/media/rc/img-ir/img-ir-sharp.c |8 +-- drivers/media/rc/img-ir/img-ir-sony.c | 12 ++-- 11 files changed, 342 insertions(+), 42 deletions(-) create mode 100644 drivers/media/rc/img-ir/img-ir-rc5.c create mode 100644 drivers/media/rc/img-ir/img-ir-rc6.c -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 4/5] rc: img-ir: add philips rc5 decoder module
Add img-ir module for decoding Philips rc5 protocol. Signed-off-by: Sifan Naeem --- drivers/media/rc/img-ir/Kconfig |7 +++ drivers/media/rc/img-ir/Makefile |1 + drivers/media/rc/img-ir/img-ir-hw.c |3 ++ drivers/media/rc/img-ir/img-ir-hw.h |1 + drivers/media/rc/img-ir/img-ir-rc5.c | 88 ++ 5 files changed, 100 insertions(+) create mode 100644 drivers/media/rc/img-ir/img-ir-rc5.c diff --git a/drivers/media/rc/img-ir/Kconfig b/drivers/media/rc/img-ir/Kconfig index 03ba9fc..b5b114f 100644 --- a/drivers/media/rc/img-ir/Kconfig +++ b/drivers/media/rc/img-ir/Kconfig @@ -59,3 +59,10 @@ config IR_IMG_SANYO help Say Y here to enable support for the Sanyo protocol (used by Sanyo, Aiwa, Chinon remotes) in the ImgTec infrared decoder block. + +config IR_IMG_RC5 + bool "Phillips RC5 protocol support" + depends on IR_IMG_HW + help + Say Y here to enable support for the RC5 protocol in the ImgTec + infrared decoder block. diff --git a/drivers/media/rc/img-ir/Makefile b/drivers/media/rc/img-ir/Makefile index 92a459d..898b1b8 100644 --- a/drivers/media/rc/img-ir/Makefile +++ b/drivers/media/rc/img-ir/Makefile @@ -6,6 +6,7 @@ img-ir-$(CONFIG_IR_IMG_JVC) += img-ir-jvc.o img-ir-$(CONFIG_IR_IMG_SONY) += img-ir-sony.o img-ir-$(CONFIG_IR_IMG_SHARP) += img-ir-sharp.o img-ir-$(CONFIG_IR_IMG_SANYO) += img-ir-sanyo.o +img-ir-$(CONFIG_IR_IMG_RC5)+= img-ir-rc5.o img-ir-objs:= $(img-ir-y) obj-$(CONFIG_IR_IMG) += img-ir.o diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c index a977467..322cdf8 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.c +++ b/drivers/media/rc/img-ir/img-ir-hw.c @@ -42,6 +42,9 @@ static struct img_ir_decoder *img_ir_decoders[] = { #ifdef CONFIG_IR_IMG_SANYO &img_ir_sanyo, #endif +#ifdef CONFIG_IR_IMG_RC5 + &img_ir_rc5, +#endif NULL }; diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h index 8578aa7..f124ec5 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.h +++ b/drivers/media/rc/img-ir/img-ir-hw.h @@ -187,6 +187,7 @@ extern struct img_ir_decoder img_ir_jvc; extern struct img_ir_decoder img_ir_sony; extern struct img_ir_decoder img_ir_sharp; extern struct img_ir_decoder img_ir_sanyo; +extern struct img_ir_decoder img_ir_rc5; /** * struct img_ir_reg_timings - Reg values for decoder timings at clock rate. diff --git a/drivers/media/rc/img-ir/img-ir-rc5.c b/drivers/media/rc/img-ir/img-ir-rc5.c new file mode 100644 index 000..e1a0829 --- /dev/null +++ b/drivers/media/rc/img-ir/img-ir-rc5.c @@ -0,0 +1,88 @@ +/* + * ImgTec IR Decoder setup for Phillips RC-5 protocol. + * + * Copyright 2012-2014 Imagination Technologies Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include "img-ir-hw.h" + +/* Convert RC5 data to a scancode */ +static int img_ir_rc5_scancode(int len, u64 raw, u64 enabled_protocols, + struct img_ir_scancode_req *request) +{ + unsigned int addr, cmd, tgl, start; + + /* Quirk in the decoder shifts everything by 2 to the left. */ + raw >>= 2; + + start = (raw >> 13) & 0x01; + tgl = (raw >> 11) & 0x01; + addr= (raw >> 6) & 0x1f; + cmd = raw & 0x3f; + /* +* 12th bit is used to extend the command in extended RC5 and has +* no effect on standard RC5. +*/ + cmd += ((raw >> 12) & 0x01) ? 0 : 0x40; + + if (!start) + return -EINVAL; + + request->protocol = RC_TYPE_RC5; + request->scancode = addr << 8 | cmd; + request->toggle = tgl; + return IMG_IR_SCANCODE; +} + +/* Convert RC5 scancode to RC5 data filter */ +static int img_ir_rc5_filter(const struct rc_scancode_filter *in, +struct img_ir_filter *out, u64 protocols) +{ + /* Not supported by the hw. */ + return -EINVAL; +} + +/* + * RC-5 decoder + * see http://www.sbprojects.com/knowledge/ir/rc5.php + */ +struct img_ir_decoder img_ir_rc5 = { + .type = RC_BIT_RC5, + .control = { + .bitoriend2 = 1, + .code_type = IMG_IR_CODETYPE_BIPHASE, + .decodend2 = 1, + }, + /* main timings */ + .tolerance = 16, + .unit = 88, /* 1/36k*32=888.888microseconds */ + .timings= { + /* 10 symbol */ + .s10 = { + .pulse = { 1 }, +
[PATCH 2/5] rc: img-ir: pass toggle bit to the rc driver
Add toggle bit to struct img_ir_scancode_req so that protocols can provide it to img_ir_handle_data(), and pass that toggle bit up to rc_keydown instead of 0. This is nedded for the upcoming rc-5 and rc-6 patches. Signed-off-by: Sifan Naeem --- drivers/media/rc/img-ir/img-ir-hw.c |8 +--- drivers/media/rc/img-ir/img-ir-hw.h |2 ++ 2 files changed, 7 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 61850a6..4a1407b 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.c +++ b/drivers/media/rc/img-ir/img-ir-hw.c @@ -792,6 +792,7 @@ static void img_ir_handle_data(struct img_ir_priv *priv, u32 len, u64 raw) struct img_ir_scancode_req request; request.protocol = RC_TYPE_UNKNOWN; + request.toggle = 0; if (dec->scancode) ret = dec->scancode(len, raw, hw->enabled_protocols, &request); @@ -802,9 +803,10 @@ static void img_ir_handle_data(struct img_ir_priv *priv, u32 len, u64 raw) dev_dbg(priv->dev, "data (%u bits) = %#llx\n", len, (unsigned long long)raw); if (ret == IMG_IR_SCANCODE) { - dev_dbg(priv->dev, "decoded scan code %#x\n", - request.scancode); - rc_keydown(hw->rdev, request.protocol, request.scancode, 0); + dev_dbg(priv->dev, "decoded scan code %#x, toggle %u\n", + request.scancode, request.toggle); + rc_keydown(hw->rdev, request.protocol, request.scancode, + request.toggle); img_ir_end_repeat(priv); } else if (ret == IMG_IR_REPEATCODE) { if (hw->mode == IMG_IR_M_REPEATING) { diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h index 1fc9583..5e59e8e 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.h +++ b/drivers/media/rc/img-ir/img-ir-hw.h @@ -138,10 +138,12 @@ struct img_ir_timing_regvals { * RC_TYPE_UNKNOWN). * @scancode: Scan code of received message (must be written by * handler if IMG_IR_SCANCODE is returned). + * @toggle:Toggle bit (defaults to 0). */ struct img_ir_scancode_req { enum rc_type protocol; u32 scancode; + u8 toggle; }; /** -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 3/5] 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 --- 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); 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; + + 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. */ + 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)) + 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); + 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)
RE: [PATCH] rc: img-ir: Add and enable sys clock for IR
Hi Mauro, I sent you a v2 of this patch on 4th February: From: Sifan Naeem Sent: 04 February 2015 16:48 To: James Hogan; mche...@osg.samsung.com Cc: linux-kernel@vger.kernel.org; linux-me...@vger.kernel.org; Sifan Naeem Subject: [PATCH v2] rc: img-ir: Add and enable sys clock for img-ir Unfortunately, while trying to improve the commit message in v2 I had changed the last word of the patch name from IR to img-ir. Do you want me to do a diff between the 2 patches and send you a new patch? Sifan > -Original Message- > From: Mauro Carvalho Chehab [mailto:mche...@osg.samsung.com] > Sent: 08 April 2015 12:32 > To: Sifan Naeem > Cc: James Hogan; linux-kernel@vger.kernel.org; linux- > me...@vger.kernel.org > Subject: Re: [PATCH] rc: img-ir: Add and enable sys clock for IR > > Em Tue, 3 Feb 2015 17:30:29 + > Sifan Naeem escreveu: > > > Gets a handle to the system clock, already described in the binding > > document, and calls the appropriate common clock framework functions > > to mark it prepared/enabled, the common clock framework initially > > enables the clock and doesn't disable it at least until the > > device/driver is removed. > > The system clock to IR is needed for the driver to communicate with > > the IR hardware via MMIO accesses on the system bus, so it must not be > > disabled during use or the driver will malfunction. > > Hmm... patchwork has two versions of this patch, but I have only one on my > e-mail. > > Could you please check if I applied the right one? If not, please send me an > email with a fixup patch. > > Thanks! > Mauro > > > > > Signed-off-by: Sifan Naeem > > --- > > drivers/media/rc/img-ir/img-ir-core.c | 13 + > > drivers/media/rc/img-ir/img-ir.h |2 ++ > > 2 files changed, 11 insertions(+), 4 deletions(-) > > > > diff --git a/drivers/media/rc/img-ir/img-ir-core.c > > b/drivers/media/rc/img-ir/img-ir-core.c > > index 77c78de..783dd21 100644 > > --- a/drivers/media/rc/img-ir/img-ir-core.c > > +++ b/drivers/media/rc/img-ir/img-ir-core.c > > @@ -60,6 +60,8 @@ static void img_ir_setup(struct img_ir_priv *priv) > > > > if (!IS_ERR(priv->clk)) > > clk_prepare_enable(priv->clk); > > + if (!IS_ERR(priv->sys_clk)) > > + clk_prepare_enable(priv->sys_clk); > > } > > > > static void img_ir_ident(struct img_ir_priv *priv) @@ -110,10 +112,11 > > @@ static int img_ir_probe(struct platform_device *pdev) > > priv->clk = devm_clk_get(&pdev->dev, "core"); > > if (IS_ERR(priv->clk)) > > dev_warn(&pdev->dev, "cannot get core clock resource\n"); > > - /* > > -* The driver doesn't need to know about the system ("sys") or > power > > -* modulation ("mod") clocks yet > > -*/ > > + > > + /* Get sys clock */ > > + priv->sys_clk = devm_clk_get(&pdev->dev, "sys"); > > + if (IS_ERR(priv->sys_clk)) > > + dev_warn(&pdev->dev, "cannot get sys clock resource\n"); > > > > /* Set up raw & hw decoder */ > > error = img_ir_probe_raw(priv); > > @@ -152,6 +155,8 @@ static int img_ir_remove(struct platform_device > > *pdev) > > > > if (!IS_ERR(priv->clk)) > > clk_disable_unprepare(priv->clk); > > + if (!IS_ERR(priv->sys_clk)) > > + clk_disable_unprepare(priv->sys_clk); > > return 0; > > } > > > > diff --git a/drivers/media/rc/img-ir/img-ir.h > > b/drivers/media/rc/img-ir/img-ir.h > > index 2ddf560..f1387c0 100644 > > --- a/drivers/media/rc/img-ir/img-ir.h > > +++ b/drivers/media/rc/img-ir/img-ir.h > > @@ -138,6 +138,7 @@ struct clk; > > * @dev: Platform device. > > * @irq: IRQ number. > > * @clk: Input clock. > > + * @sys_clk: System clock. > > * @reg_base: Iomem base address of IR register block. > > * @lock: Protects IR registers and variables in this struct. > > * @raw: Driver data for raw decoder. > > @@ -147,6 +148,7 @@ struct img_ir_priv { > > struct device *dev; > > int irq; > > struct clk *clk; > > + struct clk *sys_clk; > > void __iomem*reg_base; > > spinlock_t lock; > > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH] rc: img-ir: Add and enable sys clock for IR
Hi Mauro, Seems like you have applied the correct patch after all. ([v2] rc: img-ir: Add and enable sys clock for img-ir) Thanks, Sifan > -Original Message- > From: Mauro Carvalho Chehab [mailto:mche...@osg.samsung.com] > Sent: 08 April 2015 15:41 > To: Sifan Naeem > Cc: James Hogan; linux-kernel@vger.kernel.org; linux- > me...@vger.kernel.org > Subject: Re: [PATCH] rc: img-ir: Add and enable sys clock for IR > > Em Wed, 08 Apr 2015 13:56:14 + > Sifan Naeem escreveu: > > > Hi Mauro, > > > > I sent you a v2 of this patch on 4th February: > > > > From: Sifan Naeem > > Sent: 04 February 2015 16:48 > > To: James Hogan; mche...@osg.samsung.com > > Cc: linux-kernel@vger.kernel.org; linux-me...@vger.kernel.org; Sifan > > Naeem > > Subject: [PATCH v2] rc: img-ir: Add and enable sys clock for img-ir > > > > > > Unfortunately, while trying to improve the commit message in v2 I had > changed the last word of the patch name from IR to img-ir. > > > > Do you want me to do a diff between the 2 patches and send you a new > patch? > > Yes, please do that, changing the patch name/description to reflect what > changed since v1. > > Regards, > Mauro > > > > > Sifan > > > > > -Original Message- > > > From: Mauro Carvalho Chehab [mailto:mche...@osg.samsung.com] > > > Sent: 08 April 2015 12:32 > > > To: Sifan Naeem > > > Cc: James Hogan; linux-kernel@vger.kernel.org; linux- > > > me...@vger.kernel.org > > > Subject: Re: [PATCH] rc: img-ir: Add and enable sys clock for IR > > > > > > Em Tue, 3 Feb 2015 17:30:29 + > > > Sifan Naeem escreveu: > > > > > > > Gets a handle to the system clock, already described in the > > > > binding document, and calls the appropriate common clock framework > > > > functions to mark it prepared/enabled, the common clock framework > > > > initially enables the clock and doesn't disable it at least until > > > > the device/driver is removed. > > > > The system clock to IR is needed for the driver to communicate > > > > with the IR hardware via MMIO accesses on the system bus, so it > > > > must not be disabled during use or the driver will malfunction. > > > > > > Hmm... patchwork has two versions of this patch, but I have only one > > > on my e-mail. > > > > > > Could you please check if I applied the right one? If not, please > > > send me an email with a fixup patch. > > > > > > Thanks! > > > Mauro > > > > > > > > > > > Signed-off-by: Sifan Naeem > > > > --- > > > > drivers/media/rc/img-ir/img-ir-core.c | 13 + > > > > drivers/media/rc/img-ir/img-ir.h |2 ++ > > > > 2 files changed, 11 insertions(+), 4 deletions(-) > > > > > > > > diff --git a/drivers/media/rc/img-ir/img-ir-core.c > > > > b/drivers/media/rc/img-ir/img-ir-core.c > > > > index 77c78de..783dd21 100644 > > > > --- a/drivers/media/rc/img-ir/img-ir-core.c > > > > +++ b/drivers/media/rc/img-ir/img-ir-core.c > > > > @@ -60,6 +60,8 @@ static void img_ir_setup(struct img_ir_priv > > > > *priv) > > > > > > > > if (!IS_ERR(priv->clk)) > > > > clk_prepare_enable(priv->clk); > > > > + if (!IS_ERR(priv->sys_clk)) > > > > + clk_prepare_enable(priv->sys_clk); > > > > } > > > > > > > > static void img_ir_ident(struct img_ir_priv *priv) @@ -110,10 > > > > +112,11 @@ static int img_ir_probe(struct platform_device *pdev) > > > > priv->clk = devm_clk_get(&pdev->dev, "core"); > > > > if (IS_ERR(priv->clk)) > > > > dev_warn(&pdev->dev, "cannot get core clock > > > > resource\n"); > > > > - /* > > > > -* The driver doesn't need to know about the system ("sys") or > > > power > > > > -* modulation ("mod") clocks yet > > > > -*/ > > > > + > > > > + /* Get sys clock */ > > > > + priv->sys_clk = devm_clk_get(&pdev->dev, "sys"); > > > > + if (IS_ERR(priv->sys_clk)) > > > > + dev_warn(&pdev->dev, "cannot get sys clock resource\n"); > > > > > > >
[PATCH] spi: img-spfi: Same Edge bit set to double supported transfer speed
Same edge bit set in SPFI Control register to double the supported spfi clock speed. According to the TRM setting this bit increases the supported frequency from 1/8 to 1/4 of the Core clock frequency. Without this bit set the maximum speed would be 25MHz on Pistachio. Signed-off-by: Sifan Naeem --- drivers/spi/spi-img-spfi.c |2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index 788e2b1..acce90a 100644 --- a/drivers/spi/spi-img-spfi.c +++ b/drivers/spi/spi-img-spfi.c @@ -40,6 +40,7 @@ #define SPFI_CONTROL_SOFT_RESETBIT(11) #define SPFI_CONTROL_SEND_DMA BIT(10) #define SPFI_CONTROL_GET_DMA BIT(9) +#define SPFI_CONTROL_SEBIT(8) #define SPFI_CONTROL_TMODE_SHIFT 5 #define SPFI_CONTROL_TMODE_MASK0x7 #define SPFI_CONTROL_TMODE_SINGLE 0 @@ -491,6 +492,7 @@ static void img_spfi_config(struct spi_master *master, struct spi_device *spi, else if (xfer->tx_nbits == SPI_NBITS_QUAD && xfer->rx_nbits == SPI_NBITS_QUAD) val |= SPFI_CONTROL_TMODE_QUAD << SPFI_CONTROL_TMODE_SHIFT; + val |= SPFI_CONTROL_SE; spfi_writel(spfi, val, SPFI_CONTROL); } -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2] spi: img-spfi: Same Edge bit set to double supported transfer speed
Same edge bit set in SPFI Control register to double the supported spfi clock speed. Setting this bit increases the supported spfi frequency from 1/8 to 1/4 of the core clock frequency. Without this bit set the maximum speed supported was 25MHz on Pistachio. Change-Id: I26782ea88ac3567e72dac11e46c5b5f5f52c5e3d Signed-off-by: Sifan Naeem --- drivers/spi/spi-img-spfi.c |2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index 788e2b1..acce90a 100644 --- a/drivers/spi/spi-img-spfi.c +++ b/drivers/spi/spi-img-spfi.c @@ -40,6 +40,7 @@ #define SPFI_CONTROL_SOFT_RESETBIT(11) #define SPFI_CONTROL_SEND_DMA BIT(10) #define SPFI_CONTROL_GET_DMA BIT(9) +#define SPFI_CONTROL_SEBIT(8) #define SPFI_CONTROL_TMODE_SHIFT 5 #define SPFI_CONTROL_TMODE_MASK0x7 #define SPFI_CONTROL_TMODE_SINGLE 0 @@ -491,6 +492,7 @@ static void img_spfi_config(struct spi_master *master, struct spi_device *spi, else if (xfer->tx_nbits == SPI_NBITS_QUAD && xfer->rx_nbits == SPI_NBITS_QUAD) val |= SPFI_CONTROL_TMODE_QUAD << SPFI_CONTROL_TMODE_SHIFT; + val |= SPFI_CONTROL_SE; spfi_writel(spfi, val, SPFI_CONTROL); } -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3] spi: img-spfi: Same Edge bit set to double supported transfer speed
Same edge bit set in SPFI Control register to double the supported spfi clock speed. Setting this bit increases the supported spfi frequency from 1/8 to 1/4 of the core clock frequency. Without this bit set the maximum speed supported was 25MHz on Pistachio. Signed-off-by: Sifan Naeem --- changes from v2: Gerrit Change-Id removed from commit message drivers/spi/spi-img-spfi.c |2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index 788e2b1..acce90a 100644 --- a/drivers/spi/spi-img-spfi.c +++ b/drivers/spi/spi-img-spfi.c @@ -40,6 +40,7 @@ #define SPFI_CONTROL_SOFT_RESETBIT(11) #define SPFI_CONTROL_SEND_DMA BIT(10) #define SPFI_CONTROL_GET_DMA BIT(9) +#define SPFI_CONTROL_SEBIT(8) #define SPFI_CONTROL_TMODE_SHIFT 5 #define SPFI_CONTROL_TMODE_MASK0x7 #define SPFI_CONTROL_TMODE_SINGLE 0 @@ -491,6 +492,7 @@ static void img_spfi_config(struct spi_master *master, struct spi_device *spi, else if (xfer->tx_nbits == SPI_NBITS_QUAD && xfer->rx_nbits == SPI_NBITS_QUAD) val |= SPFI_CONTROL_TMODE_QUAD << SPFI_CONTROL_TMODE_SHIFT; + val |= SPFI_CONTROL_SE; spfi_writel(spfi, val, SPFI_CONTROL); } -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH v2] spi: img-spfi: Same Edge bit set to double supported transfer speed
Hi Jonas, > -Original Message- > From: Jonas Gorski [mailto:j...@openwrt.org] > Sent: 17 June 2015 13:12 > To: Sifan Naeem > Cc: Mark Brown; linux-...@vger.kernel.org; linux-kernel@vger.kernel.org; > Andrew Bresticker > Subject: Re: [PATCH v2] spi: img-spfi: Same Edge bit set to double supported > transfer speed > > Hi, > > On Wed, Jun 17, 2015 at 12:01 PM, Sifan Naeem > wrote: > > Same edge bit set in SPFI Control register to double the supported > > spfi clock speed. Setting this bit increases the supported spfi > > frequency from 1/8 to 1/4 of the core clock frequency. > > > > Without this bit set the maximum speed supported was 25MHz on > > Pistachio. > > > > Change-Id: I26782ea88ac3567e72dac11e46c5b5f5f52c5e3d > > Signed-off-by: Sifan Naeem > > --- > > drivers/spi/spi-img-spfi.c |2 ++ > > 1 file changed, 2 insertions(+) > > > > diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c > > index 788e2b1..acce90a 100644 > > --- a/drivers/spi/spi-img-spfi.c > > +++ b/drivers/spi/spi-img-spfi.c > > @@ -40,6 +40,7 @@ > > #define SPFI_CONTROL_SOFT_RESETBIT(11) > > #define SPFI_CONTROL_SEND_DMA BIT(10) > > #define SPFI_CONTROL_GET_DMA BIT(9) > > +#define SPFI_CONTROL_SEBIT(8) > > #define SPFI_CONTROL_TMODE_SHIFT 5 > > #define SPFI_CONTROL_TMODE_MASK0x7 > > #define SPFI_CONTROL_TMODE_SINGLE 0 > > @@ -491,6 +492,7 @@ static void img_spfi_config(struct spi_master > *master, struct spi_device *spi, > > else if (xfer->tx_nbits == SPI_NBITS_QUAD && > > xfer->rx_nbits == SPI_NBITS_QUAD) > > val |= SPFI_CONTROL_TMODE_QUAD << > > SPFI_CONTROL_TMODE_SHIFT; > > + val |= SPFI_CONTROL_SE; > > spfi_writel(spfi, val, SPFI_CONTROL); } > > Don't you also need to update master->max_speed_hz? And if it doubles the > clock speed, don't you need to reflect that in the calculation for the > devider? > Currently it looks like it would just cause all transfers to go with the > doubled > requested rate. But maybe I'm missing something. > max_speed_hz is already set to 1/4 of the Core clock. So I don't think we need to change that. In Pistachio SoC the max speed of SPFI block is limited to 1/4 of the core clock or to 50Mhz, to achieve these values the change suggested in this patch should have always been set. In the device tree node for SPFI we have to mention the limit of 50Mhz as spi-max-frequency = <5000>; Thanks, Sifan > > Regards > Jonas
RE: [PATCH v2] spi: img-spfi: Same Edge bit set to double supported transfer speed
Hi Jonas, > -Original Message- > From: Jonas Gorski [mailto:j...@openwrt.org] > Sent: 17 June 2015 15:31 > To: Sifan Naeem > Cc: Mark Brown; linux-...@vger.kernel.org; linux-kernel@vger.kernel.org; > Andrew Bresticker > Subject: Re: [PATCH v2] spi: img-spfi: Same Edge bit set to double supported > transfer speed > > Hi, > > On Wed, Jun 17, 2015 at 3:36 PM, Sifan Naeem > wrote: > > Hi Jonas, > > > >> -Original Message- > >> From: Jonas Gorski [mailto:j...@openwrt.org] > >> Sent: 17 June 2015 13:12 > >> To: Sifan Naeem > >> Cc: Mark Brown; linux-...@vger.kernel.org; > >> linux-kernel@vger.kernel.org; Andrew Bresticker > >> Subject: Re: [PATCH v2] spi: img-spfi: Same Edge bit set to double > >> supported transfer speed > >> > >> Hi, > >> > >> On Wed, Jun 17, 2015 at 12:01 PM, Sifan Naeem > >> > >> wrote: > >> > Same edge bit set in SPFI Control register to double the supported > >> > spfi clock speed. Setting this bit increases the supported spfi > >> > frequency from 1/8 to 1/4 of the core clock frequency. > >> > > >> > Without this bit set the maximum speed supported was 25MHz on > >> > Pistachio. > >> > > >> > Change-Id: I26782ea88ac3567e72dac11e46c5b5f5f52c5e3d > >> > Signed-off-by: Sifan Naeem > >> > --- > >> > drivers/spi/spi-img-spfi.c |2 ++ > >> > 1 file changed, 2 insertions(+) > >> > > >> > diff --git a/drivers/spi/spi-img-spfi.c > >> > b/drivers/spi/spi-img-spfi.c index 788e2b1..acce90a 100644 > >> > --- a/drivers/spi/spi-img-spfi.c > >> > +++ b/drivers/spi/spi-img-spfi.c > >> > @@ -40,6 +40,7 @@ > >> > #define SPFI_CONTROL_SOFT_RESETBIT(11) > >> > #define SPFI_CONTROL_SEND_DMA BIT(10) > >> > #define SPFI_CONTROL_GET_DMA BIT(9) > >> > +#define SPFI_CONTROL_SEBIT(8) > >> > #define SPFI_CONTROL_TMODE_SHIFT 5 > >> > #define SPFI_CONTROL_TMODE_MASK0x7 > >> > #define SPFI_CONTROL_TMODE_SINGLE 0 > >> > @@ -491,6 +492,7 @@ static void img_spfi_config(struct spi_master > >> *master, struct spi_device *spi, > >> > else if (xfer->tx_nbits == SPI_NBITS_QUAD && > >> > xfer->rx_nbits == SPI_NBITS_QUAD) > >> > val |= SPFI_CONTROL_TMODE_QUAD << > >> > SPFI_CONTROL_TMODE_SHIFT; > >> > + val |= SPFI_CONTROL_SE; > >> > spfi_writel(spfi, val, SPFI_CONTROL); } > >> > >> Don't you also need to update master->max_speed_hz? And if it doubles > >> the clock speed, don't you need to reflect that in the calculation for the > devider? > >> Currently it looks like it would just cause all transfers to go with > >> the doubled requested rate. But maybe I'm missing something. > >> > > max_speed_hz is already set to 1/4 of the Core clock. So I don't think we > need to change that. > > In Pistachio SoC the max speed of SPFI block is limited to 1/4 of the > > core clock or to 50Mhz, to achieve these values the change suggested > > in this patch should have always been set. In the device tree node for > > SPFI we have to mention the limit of 50Mhz as spi-max-frequency = > > <5000>; > > So it calculated the wrong divisor before, and the resulting speed was half of > that and setting this bit actually fixes it? Or does the block just treat > speeds > > 25 MHz as 25 MHz when this bit is set? I'm still trying to wrap my head around > that setting a single bit in a register allows going from 0~25 MHz to 0~50 MHz > without needing to update the calculation of the divisor. > Yes, if the requested speed is 50Mhz without the SE bit set, the divisor calculated would still request 50Mhz from the spfi block, which is correct, but the transfer would fail as SE bit is not set and the maximum speed supported would be 25Mhz. Thanks, Sifan > > Regards > Jonas
[PATCH] spi: img-spfi: check for max speed supported by the spfi block
Maximum speed supported by spfi is limited to 1/4 of the input clock. But in some SoCs the maximum speed supported by the spfi block can be limited to less than 1/4 of the input clock. In such cases we have to define the limit in the device tree so that the driver can pick it up. Signed-off-by: Sifan Naeem --- .../devicetree/bindings/spi/spi-img-spfi.txt |1 + drivers/spi/spi-img-spfi.c | 15 +++ 2 files changed, 16 insertions(+) diff --git a/Documentation/devicetree/bindings/spi/spi-img-spfi.txt b/Documentation/devicetree/bindings/spi/spi-img-spfi.txt index e02fbf1..494db60 100644 --- a/Documentation/devicetree/bindings/spi/spi-img-spfi.txt +++ b/Documentation/devicetree/bindings/spi/spi-img-spfi.txt @@ -21,6 +21,7 @@ Required properties: Optional properties: - img,supports-quad-mode: Should be set if the interface supports quad mode SPI transfers. +- spfi-max-frequency: Maximum speed supported by the spfi block. Example: diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index acce90a..1e8178f 100644 --- a/drivers/spi/spi-img-spfi.c +++ b/drivers/spi/spi-img-spfi.c @@ -548,6 +548,7 @@ static int img_spfi_probe(struct platform_device *pdev) struct img_spfi *spfi; struct resource *res; int ret; + u32 max_speed_hz; master = spi_alloc_master(&pdev->dev, sizeof(*spfi)); if (!master) @@ -612,6 +613,20 @@ static int img_spfi_probe(struct platform_device *pdev) master->max_speed_hz = clk_get_rate(spfi->spfi_clk) / 4; master->min_speed_hz = clk_get_rate(spfi->spfi_clk) / 512; + /* +* Maximum speed supported by spfi is limited to the lower value +* between 1/4 of the input clock or to "spfi-max-frequency" +* defined in the device tree. +* If no value is defined in the device tree assume the maximum +* speed supported to be 1/4 of the input clock rate. +*/ + if (!of_property_read_u32(spfi->dev->of_node, "spfi-max-frequency", + &max_speed_hz)) + { + if (master->max_speed_hz > max_speed_hz) + master->max_speed_hz = max_speed_hz; + } + master->setup = img_spfi_setup; master->cleanup = img_spfi_cleanup; master->transfer_one = img_spfi_transfer_one; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2] spi: img-spfi: check for max speed supported by the spfi block
Maximum speed supported by spfi is limited to 1/4 of the spfi clock. But in some SoCs the maximum speed supported by the spfi block can be limited to less than 1/4 of the spfi clock. In such cases we have to define the limit in the device tree so that the driver can pick it up. Signed-off-by: Sifan Naeem --- changes from v1: coding style fix. .../devicetree/bindings/spi/spi-img-spfi.txt |1 + drivers/spi/spi-img-spfi.c | 14 ++ 2 files changed, 15 insertions(+) diff --git a/Documentation/devicetree/bindings/spi/spi-img-spfi.txt b/Documentation/devicetree/bindings/spi/spi-img-spfi.txt index e02fbf1..494db60 100644 --- a/Documentation/devicetree/bindings/spi/spi-img-spfi.txt +++ b/Documentation/devicetree/bindings/spi/spi-img-spfi.txt @@ -21,6 +21,7 @@ Required properties: Optional properties: - img,supports-quad-mode: Should be set if the interface supports quad mode SPI transfers. +- spfi-max-frequency: Maximum speed supported by the spfi block. Example: diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index acce90a..00f1ac3 100644 --- a/drivers/spi/spi-img-spfi.c +++ b/drivers/spi/spi-img-spfi.c @@ -548,6 +548,7 @@ static int img_spfi_probe(struct platform_device *pdev) struct img_spfi *spfi; struct resource *res; int ret; + u32 max_speed_hz; master = spi_alloc_master(&pdev->dev, sizeof(*spfi)); if (!master) @@ -612,6 +613,19 @@ static int img_spfi_probe(struct platform_device *pdev) master->max_speed_hz = clk_get_rate(spfi->spfi_clk) / 4; master->min_speed_hz = clk_get_rate(spfi->spfi_clk) / 512; + /* +* Maximum speed supported by spfi is limited to the lower value +* between 1/4 of the SPFI clock or to "spfi-max-frequency" +* defined in the device tree. +* If no value is defined in the device tree assume the maximum +* speed supported to be 1/4 of the SPFI clock. +*/ + if (!of_property_read_u32(spfi->dev->of_node, "spfi-max-frequency", + &max_speed_hz)) { + if (master->max_speed_hz > max_speed_hz) + master->max_speed_hz = max_speed_hz; + } + master->setup = img_spfi_setup; master->cleanup = img_spfi_cleanup; master->transfer_one = img_spfi_transfer_one; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] spi: img-spfi: fix support for speeds up to 1/4th input clock
Setting the Same Edge bit indicates to the spfi block to receive and transmit data on the same edge of the spfi clock, which in turn doubles the operating frequency of spfi. The maximum supported frequency is limited to 1/4th of the spfi input clock, but without this bit set the maximum would be 1/8th of the input clock. The current driver calculates the divisor with maximum speed at 1/4th of the input clock, this would fail if the requested frequency is higher than 1/8 of the input clock. Any requests for 1/8th of the input clock would still pass. Signed-off-by: Sifan Naeem Fixes: 8543d0e72d43 ("spi: img-spfi: Limit bit clock to 1/4th of input clock") Cc: # 3.19+ --- drivers/spi/spi-img-spfi.c |2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index 1eb107f..a277faf 100644 --- a/drivers/spi/spi-img-spfi.c +++ b/drivers/spi/spi-img-spfi.c @@ -40,6 +40,7 @@ #define SPFI_CONTROL_SOFT_RESETBIT(11) #define SPFI_CONTROL_SEND_DMA BIT(10) #define SPFI_CONTROL_GET_DMA BIT(9) +#define SPFI_CONTROL_SEBIT(8) #define SPFI_CONTROL_TMODE_SHIFT 5 #define SPFI_CONTROL_TMODE_MASK0x7 #define SPFI_CONTROL_TMODE_SINGLE 0 @@ -491,6 +492,7 @@ static void img_spfi_config(struct spi_master *master, struct spi_device *spi, else if (xfer->tx_nbits == SPI_NBITS_QUAD && xfer->rx_nbits == SPI_NBITS_QUAD) val |= SPFI_CONTROL_TMODE_QUAD << SPFI_CONTROL_TMODE_SHIFT; + val |= SPFI_CONTROL_SE; spfi_writel(spfi, val, SPFI_CONTROL); } -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH v3] spi: img-spfi: Same Edge bit set to double supported transfer speed
Please ignore this patch. I have posted a new patch as a fix after the discussion with Jonas Gorski. https://patchwork.kernel.org/patch/6636761/ spi: img-spfi: fix support for speeds up to 1/4th input clock Thanks, Sifan > -Original Message- > From: Sifan Naeem > Sent: 17 June 2015 11:48 > To: broo...@kernel.org > Cc: linux-...@vger.kernel.org; linux-kernel@vger.kernel.org; > abres...@chromium.org; Sifan Naeem > Subject: [PATCH v3] spi: img-spfi: Same Edge bit set to double supported > transfer speed > > Same edge bit set in SPFI Control register to double the supported spfi clock > speed. Setting this bit increases the supported spfi frequency from 1/8 to 1/4 > of the core clock frequency. > > Without this bit set the maximum speed supported was 25MHz on Pistachio. > > Signed-off-by: Sifan Naeem > --- > changes from v2: Gerrit Change-Id removed from commit message > drivers/spi/spi-img-spfi.c |2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index > 788e2b1..acce90a 100644 > --- a/drivers/spi/spi-img-spfi.c > +++ b/drivers/spi/spi-img-spfi.c > @@ -40,6 +40,7 @@ > #define SPFI_CONTROL_SOFT_RESET BIT(11) > #define SPFI_CONTROL_SEND_DMABIT(10) > #define SPFI_CONTROL_GET_DMA BIT(9) > +#define SPFI_CONTROL_SE BIT(8) > #define SPFI_CONTROL_TMODE_SHIFT 5 > #define SPFI_CONTROL_TMODE_MASK 0x7 > #define SPFI_CONTROL_TMODE_SINGLE0 > @@ -491,6 +492,7 @@ static void img_spfi_config(struct spi_master > *master, struct spi_device *spi, > else if (xfer->tx_nbits == SPI_NBITS_QUAD && >xfer->rx_nbits == SPI_NBITS_QUAD) > val |= SPFI_CONTROL_TMODE_QUAD << > SPFI_CONTROL_TMODE_SHIFT; > + val |= SPFI_CONTROL_SE; > spfi_writel(spfi, val, SPFI_CONTROL); > } > > -- > 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] rc: img-ir: fix error in parameters passed to irq_free()
img_ir_remove() passes a pointer to the ISR function as the 2nd parameter to irq_free() instead of a pointer to the device data structure. This issue causes unloading img-ir module to fail with the below warning after building and loading img-ir as a module. WARNING: CPU: 2 PID: 155 at ../kernel/irq/manage.c:1278 __free_irq+0xb4/0x214() Trying to free already-free IRQ 58 Modules linked in: img_ir(-) CPU: 2 PID: 155 Comm: rmmod Not tainted 3.14.0 #55 ... Call Trace: ... [<8048d420>] __free_irq+0xb4/0x214 [<8048d6b4>] free_irq+0xac/0xf4 [] img_ir_remove+0x54/0xd4 [img_ir] [<8073ded0>] platform_drv_remove+0x30/0x54 ... Signed-off-by: Sifan Naeem Fixes: 160a8f8aec4d ("[media] rc: img-ir: add base driver") Cc: # 3.15+ --- drivers/media/rc/img-ir/img-ir-core.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/rc/img-ir/img-ir-core.c b/drivers/media/rc/img-ir/img-ir-core.c index 77c78de..7020659 100644 --- a/drivers/media/rc/img-ir/img-ir-core.c +++ b/drivers/media/rc/img-ir/img-ir-core.c @@ -146,7 +146,7 @@ static int img_ir_remove(struct platform_device *pdev) { struct img_ir_priv *priv = platform_get_drvdata(pdev); - free_irq(priv->irq, img_ir_isr); + free_irq(priv->irq, priv); img_ir_remove_hw(priv); img_ir_remove_raw(priv); -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2] rc: img-ir: Add and enable sys clock for img-ir
Gets a handle to the system clock, already described in the binding document, and calls the appropriate common clock framework functions to mark it prepared/enabled, the common clock framework initially enables the clock and doesn't disable it at least until the device/driver is removed. It's important the systen clock is enabled before register interface is accessed by the driver. The system clock to IR is needed for the driver to communicate with the IR hardware via MMIO accesses on the system bus, so it must not be disabled during use or the driver will malfunction. Signed-off-by: Sifan Naeem --- Changes from v1: System clock enabled in probe function before any hardware is accessed. Error handling in probe function ensures ISR doesn't get called with system clock disabled. drivers/media/rc/img-ir/img-ir-core.c | 29 + drivers/media/rc/img-ir/img-ir.h |2 ++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/drivers/media/rc/img-ir/img-ir-core.c b/drivers/media/rc/img-ir/img-ir-core.c index 77c78de..a10d666 100644 --- a/drivers/media/rc/img-ir/img-ir-core.c +++ b/drivers/media/rc/img-ir/img-ir-core.c @@ -110,16 +110,32 @@ static int img_ir_probe(struct platform_device *pdev) priv->clk = devm_clk_get(&pdev->dev, "core"); if (IS_ERR(priv->clk)) dev_warn(&pdev->dev, "cannot get core clock resource\n"); + + /* Get sys clock */ + priv->sys_clk = devm_clk_get(&pdev->dev, "sys"); + if (IS_ERR(priv->sys_clk)) + dev_warn(&pdev->dev, "cannot get sys clock resource\n"); /* -* The driver doesn't need to know about the system ("sys") or power -* modulation ("mod") clocks yet +* Enabling the system clock before the register interface is +* accessed. ISR shouldn't get called with Sys Clock disabled, +* hence exiting probe with an error. */ + if (!IS_ERR(priv->sys_clk)) { + error = clk_prepare_enable(priv->sys_clk); + if (error) { + dev_err(&pdev->dev, "cannot enable sys clock\n"); + return error; + } + } /* Set up raw & hw decoder */ error = img_ir_probe_raw(priv); error2 = img_ir_probe_hw(priv); - if (error && error2) - return (error == -ENODEV) ? error2 : error; + if (error && error2) { + if (error == -ENODEV) + error = error2; + goto err_probe; + } /* Get the IRQ */ priv->irq = irq; @@ -139,6 +155,9 @@ static int img_ir_probe(struct platform_device *pdev) err_irq: img_ir_remove_hw(priv); img_ir_remove_raw(priv); +err_probe: + if (!IS_ERR(priv->sys_clk)) + clk_disable_unprepare(priv->sys_clk); return error; } @@ -152,6 +171,8 @@ static int img_ir_remove(struct platform_device *pdev) if (!IS_ERR(priv->clk)) clk_disable_unprepare(priv->clk); + if (!IS_ERR(priv->sys_clk)) + clk_disable_unprepare(priv->sys_clk); return 0; } diff --git a/drivers/media/rc/img-ir/img-ir.h b/drivers/media/rc/img-ir/img-ir.h index 2ddf560..f1387c0 100644 --- a/drivers/media/rc/img-ir/img-ir.h +++ b/drivers/media/rc/img-ir/img-ir.h @@ -138,6 +138,7 @@ struct clk; * @dev: Platform device. * @irq: IRQ number. * @clk: Input clock. + * @sys_clk: System clock. * @reg_base: Iomem base address of IR register block. * @lock: Protects IR registers and variables in this struct. * @raw: Driver data for raw decoder. @@ -147,6 +148,7 @@ struct img_ir_priv { struct device *dev; int irq; struct clk *clk; + struct clk *sys_clk; void __iomem*reg_base; spinlock_t lock; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] rc: img-ir: Add and enable sys clock for IR
Gets a handle to the system clock, already described in the binding document, and calls the appropriate common clock framework functions to mark it prepared/enabled, the common clock framework initially enables the clock and doesn't disable it at least until the device/driver is removed. The system clock to IR is needed for the driver to communicate with the IR hardware via MMIO accesses on the system bus, so it must not be disabled during use or the driver will malfunction. Signed-off-by: Sifan Naeem --- drivers/media/rc/img-ir/img-ir-core.c | 13 + drivers/media/rc/img-ir/img-ir.h |2 ++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/media/rc/img-ir/img-ir-core.c b/drivers/media/rc/img-ir/img-ir-core.c index 77c78de..783dd21 100644 --- a/drivers/media/rc/img-ir/img-ir-core.c +++ b/drivers/media/rc/img-ir/img-ir-core.c @@ -60,6 +60,8 @@ static void img_ir_setup(struct img_ir_priv *priv) if (!IS_ERR(priv->clk)) clk_prepare_enable(priv->clk); + if (!IS_ERR(priv->sys_clk)) + clk_prepare_enable(priv->sys_clk); } static void img_ir_ident(struct img_ir_priv *priv) @@ -110,10 +112,11 @@ static int img_ir_probe(struct platform_device *pdev) priv->clk = devm_clk_get(&pdev->dev, "core"); if (IS_ERR(priv->clk)) dev_warn(&pdev->dev, "cannot get core clock resource\n"); - /* -* The driver doesn't need to know about the system ("sys") or power -* modulation ("mod") clocks yet -*/ + + /* Get sys clock */ + priv->sys_clk = devm_clk_get(&pdev->dev, "sys"); + if (IS_ERR(priv->sys_clk)) + dev_warn(&pdev->dev, "cannot get sys clock resource\n"); /* Set up raw & hw decoder */ error = img_ir_probe_raw(priv); @@ -152,6 +155,8 @@ static int img_ir_remove(struct platform_device *pdev) if (!IS_ERR(priv->clk)) clk_disable_unprepare(priv->clk); + if (!IS_ERR(priv->sys_clk)) + clk_disable_unprepare(priv->sys_clk); return 0; } diff --git a/drivers/media/rc/img-ir/img-ir.h b/drivers/media/rc/img-ir/img-ir.h index 2ddf560..f1387c0 100644 --- a/drivers/media/rc/img-ir/img-ir.h +++ b/drivers/media/rc/img-ir/img-ir.h @@ -138,6 +138,7 @@ struct clk; * @dev: Platform device. * @irq: IRQ number. * @clk: Input clock. + * @sys_clk: System clock. * @reg_base: Iomem base address of IR register block. * @lock: Protects IR registers and variables in this struct. * @raw: Driver data for raw decoder. @@ -147,6 +148,7 @@ struct img_ir_priv { struct device *dev; int irq; struct clk *clk; + struct clk *sys_clk; void __iomem*reg_base; spinlock_t lock; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] spi: img-spfi: same edge bit set to double spfi speeds
Setting the same edge bit is required for operating at full bitrate programmed into the SPFI control register. Without this bit set the max operating bitrate supported would be half the maximum bitrate supported by the img-spfi block. It's safe to set this bit for all transactions. Signed-off-by: Sifan Naeem --- drivers/spi/spi-img-spfi.c |4 1 file changed, 4 insertions(+) diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index c01567d..e6f77b8 100644 --- a/drivers/spi/spi-img-spfi.c +++ b/drivers/spi/spi-img-spfi.c @@ -39,6 +39,7 @@ #define SPFI_CONTROL_SOFT_RESETBIT(11) #define SPFI_CONTROL_SEND_DMA BIT(10) #define SPFI_CONTROL_GET_DMA BIT(9) +#define SPFI_CONTROL_SEBIT(8) #define SPFI_CONTROL_TMODE_SHIFT 5 #define SPFI_CONTROL_TMODE_MASK0x7 #define SPFI_CONTROL_TMODE_SINGLE 0 @@ -435,6 +436,9 @@ static void img_spfi_config(struct spi_master *master, struct spi_device *spi, val |= SPFI_CONTROL_CONTINUE; spfi_writel(spfi, val, SPFI_CONTROL); + /* Double the transfer speed by setting Same Edge. */ + val |= SPFI_CONTROL_SE; + val = spfi_readl(spfi, SPFI_PORT_STATE); if (spi->mode & SPI_CPHA) val |= SPFI_PORT_STATE_CK_PHASE(spi->chip_select); -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] spi: img-spfi: Verify max spfi transfer length
Maximum transfer length supported by SPFI is 65535, this is limited by the number of bits available in SPFI TSize register to represent the transfer size. For transfer requests larger than the maximum supported the driver will return an invalid argument error. Signed-off-by: Sifan Naeem Reviewed-by: Andrew Bresticker --- drivers/spi/spi-img-spfi.c |7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index c01567d..e649bc7 100644 --- a/drivers/spi/spi-img-spfi.c +++ b/drivers/spi/spi-img-spfi.c @@ -459,6 +459,13 @@ static int img_spfi_transfer_one(struct spi_master *master, unsigned long flags; int ret; + if (xfer->len > SPFI_TRANSACTION_TSIZE_MASK) { + dev_err(spfi->dev, + "Transfer length (%d) is greater than the max supported (%d)", + xfer->len, SPFI_TRANSACTION_TSIZE_MASK); + return -EINVAL; + } + /* * Stop all DMA and reset the controller if the previous transaction * timed-out and never completed it's DMA. -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] spi: img-spfi: Remove udelay in soft reset
Removing the udelay between setting and clearing the soft reset bit in the spfi control register as it is not required. Signed-off-by: Sifan Naeem Reviewed-by: Andrew Bresticker --- drivers/spi/spi-img-spfi.c |1 - 1 file changed, 1 deletion(-) diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index c01567d..fde4b5d 100644 --- a/drivers/spi/spi-img-spfi.c +++ b/drivers/spi/spi-img-spfi.c @@ -134,7 +134,6 @@ static inline void spfi_stop(struct img_spfi *spfi) static inline void spfi_reset(struct img_spfi *spfi) { spfi_writel(spfi, SPFI_CONTROL_SOFT_RESET, SPFI_CONTROL); - udelay(1); spfi_writel(spfi, 0, SPFI_CONTROL); } -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: [PATCH 3/5] rc: img-ir: biphase enabled with workaround
> -Original Message- > From: James Hogan > Sent: 08 December 2014 17:18 > To: Sifan Naeem; mche...@osg.samsung.com > Cc: linux-kernel@vger.kernel.org; linux-me...@vger.kernel.org; James > Hartley; Ezequiel Garcia > Subject: Re: [PATCH 3/5] rc: img-ir: biphase enabled with workaround > > 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 > > --- > > 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. > Yes, I'll rebase and resend the patch. > > 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. > done > > + 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). > Ok > 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. > don't have to clear it for this work around to work, so will remove. > > + 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_statu
[PATCH v2 1/5] rc: img-ir: add scancode requests to a struct
The information being requested of hardware decode callbacks through the img-ir-hw scancode API is mounting up, so combine it into a struct which can be passed in with a single pointer rather than multiple pointer arguments. This allows it to be extended more easily without touching all the hardware decode callbacks. Signed-off-by: Sifan Naeem --- drivers/media/rc/img-ir/img-ir-hw.c| 16 +--- drivers/media/rc/img-ir/img-ir-hw.h| 16 ++-- drivers/media/rc/img-ir/img-ir-jvc.c |8 drivers/media/rc/img-ir/img-ir-nec.c | 24 drivers/media/rc/img-ir/img-ir-sanyo.c |8 drivers/media/rc/img-ir/img-ir-sharp.c |8 drivers/media/rc/img-ir/img-ir-sony.c | 12 ++-- 7 files changed, 53 insertions(+), 39 deletions(-) diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c index 2fd47c9..88fada5 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.c +++ b/drivers/media/rc/img-ir/img-ir-hw.c @@ -806,20 +806,22 @@ static void img_ir_handle_data(struct img_ir_priv *priv, u32 len, u64 raw) struct img_ir_priv_hw *hw = &priv->hw; const struct img_ir_decoder *dec = hw->decoder; int ret = IMG_IR_SCANCODE; - u32 scancode; - enum rc_type protocol = RC_TYPE_UNKNOWN; + struct img_ir_scancode_req request; + + request.protocol = RC_TYPE_UNKNOWN; if (dec->scancode) - ret = dec->scancode(len, raw, &protocol, &scancode, hw->enabled_protocols); + ret = dec->scancode(len, raw, hw->enabled_protocols, &request); else if (len >= 32) - scancode = (u32)raw; + request.scancode = (u32)raw; else if (len < 32) - scancode = (u32)raw & ((1 << len)-1); + request.scancode = (u32)raw & ((1 << len)-1); dev_dbg(priv->dev, "data (%u bits) = %#llx\n", len, (unsigned long long)raw); if (ret == IMG_IR_SCANCODE) { - dev_dbg(priv->dev, "decoded scan code %#x\n", scancode); - rc_keydown(hw->rdev, protocol, scancode, 0); + dev_dbg(priv->dev, "decoded scan code %#x\n", + request.scancode); + rc_keydown(hw->rdev, request.protocol, request.scancode, 0); img_ir_end_repeat(priv); } else if (ret == IMG_IR_REPEATCODE) { if (hw->mode == IMG_IR_M_REPEATING) { diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h index 5c2b216..aeef3d1 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.h +++ b/drivers/media/rc/img-ir/img-ir-hw.h @@ -133,6 +133,18 @@ struct img_ir_timing_regvals { #define IMG_IR_REPEATCODE 1 /* repeat the previous code */ /** + * struct img_ir_scancode_req - Scancode request data. + * @protocol: Protocol code of received message (defaults to + * RC_TYPE_UNKNOWN). + * @scancode: Scan code of received message (must be written by + * handler if IMG_IR_SCANCODE is returned). + */ +struct img_ir_scancode_req { + enum rc_type protocol; + u32 scancode; +}; + +/** * struct img_ir_decoder - Decoder settings for an IR protocol. * @type: Protocol types bitmap. * @tolerance: Timing tolerance as a percentage (default 10%). @@ -162,8 +174,8 @@ struct img_ir_decoder { struct img_ir_control control; /* scancode logic */ - int (*scancode)(int len, u64 raw, enum rc_type *protocol, - u32 *scancode, u64 enabled_protocols); + int (*scancode)(int len, u64 raw, u64 enabled_protocols, + struct img_ir_scancode_req *request); int (*filter)(const struct rc_scancode_filter *in, struct img_ir_filter *out, u64 protocols); }; diff --git a/drivers/media/rc/img-ir/img-ir-jvc.c b/drivers/media/rc/img-ir/img-ir-jvc.c index a60dda8..d3e2fc0 100644 --- a/drivers/media/rc/img-ir/img-ir-jvc.c +++ b/drivers/media/rc/img-ir/img-ir-jvc.c @@ -12,8 +12,8 @@ #include "img-ir-hw.h" /* Convert JVC data to a scancode */ -static int img_ir_jvc_scancode(int len, u64 raw, enum rc_type *protocol, - u32 *scancode, u64 enabled_protocols) +static int img_ir_jvc_scancode(int len, u64 raw, u64 enabled_protocols, + struct img_ir_scancode_req *request) { unsigned int cust, data; @@ -23,8 +23,8 @@ static int img_ir_jvc_scancode(int len, u64 raw, enum rc_type *protocol, cust = (raw >> 0) & 0xff; data = (raw >> 8) & 0xff; - *protocol = RC_TYPE_JVC; - *scancode = cust << 8 | data; + request->protocol = RC_TYPE_JVC; + request->scancode = cust << 8 | data; return IMG_IR_SCANCODE; } dif
[PATCH v2 3/5] 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. Changes from v1: * rebased due to conflict with "img-ir/hw: Fix potential deadlock stopping timer" * spinlock taken in img_ir_suspend_timer * check for hw->stopping before handling quirks in img_ir_isr_hw * new memeber added to img_ir_priv_hw to save irq status over suspend Signed-off-by: Sifan Naeem --- drivers/media/rc/img-ir/img-ir-hw.c | 60 +-- drivers/media/rc/img-ir/img-ir-hw.h |4 +++ 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 9cecda7..5c32f05 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 */ @@ -542,6 +547,7 @@ static void img_ir_set_decoder(struct img_ir_priv *priv, */ spin_unlock_irq(&priv->lock); del_timer_sync(&hw->end_timer); + del_timer_sync(&hw->suspend_timer); spin_lock_irq(&priv->lock); hw->stopping = false; @@ -861,6 +867,29 @@ 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; + + spin_lock_irq(&priv->lock); + /* +* Don't overwrite enabled valid/match IRQs if they have already been +* changed by e.g. a filter change. +*/ + if ((priv->hw.quirk_suspend_irq & IMG_IR_IRQ_EDGE) == + img_ir_read(priv, IMG_IR_IRQ_ENABLE)) + img_ir_write(priv, IMG_IR_IRQ_ENABLE, + priv->hw.quirk_suspend_irq); + /* enable */ + img_ir_write(priv, IMG_IR_CONTROL, priv->hw.reg_timings.ctrl); + spin_unlock_irq(&priv->lock); +} + #ifdef CONFIG_COMMON_CLK static void img_ir_change_frequency(struct img_ir_priv *priv, struct clk_notifier_data *change) @@ -926,15 +955,38 @@ 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) || + hw->stopping) + 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->quirk_suspend_irq = img_ir_read(priv, IMG_IR_IRQ_ENABLE); + img_ir_write(priv, IMG_IR_IRQ_ENABLE, +hw->quirk_suspend_irq & 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; @@ -976,7 +1028,7 @@ static void img_
[PATCH v2 5/5] rc: img-ir: add philips rc6 decoder module
Add img-ir module for decoding Philips rc6 protocol. Changes from v1: * Phillips renamed to Philips Signed-off-by: Sifan Naeem --- drivers/media/rc/img-ir/Kconfig |8 +++ drivers/media/rc/img-ir/Makefile |1 + drivers/media/rc/img-ir/img-ir-hw.c |3 + drivers/media/rc/img-ir/img-ir-hw.h |1 + drivers/media/rc/img-ir/img-ir-rc6.c | 117 ++ 5 files changed, 130 insertions(+) create mode 100644 drivers/media/rc/img-ir/img-ir-rc6.c diff --git a/drivers/media/rc/img-ir/Kconfig b/drivers/media/rc/img-ir/Kconfig index b20b3e9..a896d3c 100644 --- a/drivers/media/rc/img-ir/Kconfig +++ b/drivers/media/rc/img-ir/Kconfig @@ -67,3 +67,11 @@ config IR_IMG_RC5 help Say Y here to enable support for the RC5 protocol in the ImgTec infrared decoder block. + +config IR_IMG_RC6 + bool "Philips RC6 protocol support" + depends on IR_IMG_HW + help + Say Y here to enable support for the RC6 protocol in the ImgTec + infrared decoder block. + Note: This version only supports mode 0. diff --git a/drivers/media/rc/img-ir/Makefile b/drivers/media/rc/img-ir/Makefile index 898b1b8..8e6d458 100644 --- a/drivers/media/rc/img-ir/Makefile +++ b/drivers/media/rc/img-ir/Makefile @@ -7,6 +7,7 @@ img-ir-$(CONFIG_IR_IMG_SONY)+= img-ir-sony.o img-ir-$(CONFIG_IR_IMG_SHARP) += img-ir-sharp.o img-ir-$(CONFIG_IR_IMG_SANYO) += img-ir-sanyo.o img-ir-$(CONFIG_IR_IMG_RC5)+= img-ir-rc5.o +img-ir-$(CONFIG_IR_IMG_RC6)+= img-ir-rc6.o img-ir-objs:= $(img-ir-y) obj-$(CONFIG_IR_IMG) += img-ir.o diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c index 13f0b1e..7bb71bc 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.c +++ b/drivers/media/rc/img-ir/img-ir-hw.c @@ -45,6 +45,9 @@ static struct img_ir_decoder *img_ir_decoders[] = { #ifdef CONFIG_IR_IMG_RC5 &img_ir_rc5, #endif +#ifdef CONFIG_IR_IMG_RC6 + &img_ir_rc6, +#endif NULL }; diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h index b9e799d5..91a2977 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.h +++ b/drivers/media/rc/img-ir/img-ir-hw.h @@ -188,6 +188,7 @@ extern struct img_ir_decoder img_ir_sony; extern struct img_ir_decoder img_ir_sharp; extern struct img_ir_decoder img_ir_sanyo; extern struct img_ir_decoder img_ir_rc5; +extern struct img_ir_decoder img_ir_rc6; /** * struct img_ir_reg_timings - Reg values for decoder timings at clock rate. diff --git a/drivers/media/rc/img-ir/img-ir-rc6.c b/drivers/media/rc/img-ir/img-ir-rc6.c new file mode 100644 index 000..de1e275 --- /dev/null +++ b/drivers/media/rc/img-ir/img-ir-rc6.c @@ -0,0 +1,117 @@ +/* + * ImgTec IR Decoder setup for Philips RC-6 protocol. + * + * Copyright 2012-2014 Imagination Technologies Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include "img-ir-hw.h" + +/* Convert RC6 data to a scancode */ +static int img_ir_rc6_scancode(int len, u64 raw, u64 enabled_protocols, + struct img_ir_scancode_req *request) +{ + unsigned int addr, cmd, mode, trl1, trl2; + + /* +* Due to a side effect of the decoder handling the double length +* Trailer bit, the header information is a bit scrambled, and the +* raw data is shifted incorrectly. +* This workaround effectively recovers the header bits. +* +* The Header field should look like this: +* +* StartBit ModeBit2 ModeBit1 ModeBit0 TrailerBit +* +* But what we get is: +* +* ModeBit2 ModeBit1 ModeBit0 TrailerBit1 TrailerBit2 +* +* The start bit is not important to recover the scancode. +*/ + + raw >>= 27; + + trl1= (raw >> 17) & 0x01; + trl2= (raw >> 16) & 0x01; + + mode= (raw >> 18) & 0x07; + addr= (raw >> 8) & 0xff; + cmd = raw & 0xff; + + /* +* Due to the above explained irregularity the trailer bits cannot +* have the same value. +*/ + if (trl1 == trl2) + return -EINVAL; + + /* Only mode 0 supported for now */ + if (mode) + return -EINVAL; + + request->protocol = RC_TYPE_RC6_0; + request->scancode = addr << 8 | cmd; + request->toggle = trl2; + return IMG_IR_SCANCODE; +} + +/* Convert RC6 scancode to RC6 data filter */ +static int img_ir_rc6_filter(const struct rc_scancode_filter *in, +struct img_ir_filter *out, u64 protocols
[PATCH v2 0/5] rc: img-ir: rc5 and rc6 support added
This patch sets adds support for rc5 and rc6 decoder modules along with workarounds for quirks in the hw which surfaces when decoding in biphase mode required by rc5 and rc6. Changes from v1: * Typo Corrected in the commit message * Rebased due to conflict with "img-ir/hw: Fix potential deadlock stopping timer" * spinlock taken in img_ir_suspend_timer * Check for hw->stopping before handling quirks in img_ir_isr_hw * New member added to img_ir_priv_hw to save irq status over suspend * Phillips renamed to Philips Sifan Naeem (5): rc: img-ir: add scancode requests to a struct rc: img-ir: pass toggle bit to the rc driver rc: img-ir: biphase enabled with workaround rc: img-ir: add philips rc5 decoder module rc: img-ir: add philips rc6 decoder module drivers/media/rc/img-ir/Kconfig| 15 drivers/media/rc/img-ir/Makefile |2 + drivers/media/rc/img-ir/img-ir-hw.c| 84 --- drivers/media/rc/img-ir/img-ir-hw.h| 24 ++- drivers/media/rc/img-ir/img-ir-jvc.c |8 +-- drivers/media/rc/img-ir/img-ir-nec.c | 24 +++ drivers/media/rc/img-ir/img-ir-rc5.c | 88 drivers/media/rc/img-ir/img-ir-rc6.c | 117 drivers/media/rc/img-ir/img-ir-sanyo.c |8 +-- drivers/media/rc/img-ir/img-ir-sharp.c |8 +-- drivers/media/rc/img-ir/img-ir-sony.c | 12 ++-- 11 files changed, 348 insertions(+), 42 deletions(-) create mode 100644 drivers/media/rc/img-ir/img-ir-rc5.c create mode 100644 drivers/media/rc/img-ir/img-ir-rc6.c -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 2/5] rc: img-ir: pass toggle bit to the rc driver
Add toggle bit to struct img_ir_scancode_req so that protocols can provide it to img_ir_handle_data(), and pass that toggle bit up to rc_keydown instead of 0. This is needed for the upcoming rc-5 and rc-6 patches. Change from v1: * Typo Corrected in the commit message. Signed-off-by: Sifan Naeem --- drivers/media/rc/img-ir/img-ir-hw.c |8 +--- drivers/media/rc/img-ir/img-ir-hw.h |2 ++ 2 files changed, 7 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 88fada5..9cecda7 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.c +++ b/drivers/media/rc/img-ir/img-ir-hw.c @@ -809,6 +809,7 @@ static void img_ir_handle_data(struct img_ir_priv *priv, u32 len, u64 raw) struct img_ir_scancode_req request; request.protocol = RC_TYPE_UNKNOWN; + request.toggle = 0; if (dec->scancode) ret = dec->scancode(len, raw, hw->enabled_protocols, &request); @@ -819,9 +820,10 @@ static void img_ir_handle_data(struct img_ir_priv *priv, u32 len, u64 raw) dev_dbg(priv->dev, "data (%u bits) = %#llx\n", len, (unsigned long long)raw); if (ret == IMG_IR_SCANCODE) { - dev_dbg(priv->dev, "decoded scan code %#x\n", - request.scancode); - rc_keydown(hw->rdev, request.protocol, request.scancode, 0); + dev_dbg(priv->dev, "decoded scan code %#x, toggle %u\n", + request.scancode, request.toggle); + rc_keydown(hw->rdev, request.protocol, request.scancode, + request.toggle); img_ir_end_repeat(priv); } else if (ret == IMG_IR_REPEATCODE) { if (hw->mode == IMG_IR_M_REPEATING) { diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h index aeef3d1..beac3a6 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.h +++ b/drivers/media/rc/img-ir/img-ir-hw.h @@ -138,10 +138,12 @@ struct img_ir_timing_regvals { * RC_TYPE_UNKNOWN). * @scancode: Scan code of received message (must be written by * handler if IMG_IR_SCANCODE is returned). + * @toggle:Toggle bit (defaults to 0). */ struct img_ir_scancode_req { enum rc_type protocol; u32 scancode; + u8 toggle; }; /** -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 4/5] rc: img-ir: add philips rc5 decoder module
Add img-ir module for decoding Philips rc5 protocol. Changes from v1: * Phillips renamed to Philips Signed-off-by: Sifan Naeem --- drivers/media/rc/img-ir/Kconfig |7 +++ drivers/media/rc/img-ir/Makefile |1 + drivers/media/rc/img-ir/img-ir-hw.c |3 ++ drivers/media/rc/img-ir/img-ir-hw.h |1 + drivers/media/rc/img-ir/img-ir-rc5.c | 88 ++ 5 files changed, 100 insertions(+) create mode 100644 drivers/media/rc/img-ir/img-ir-rc5.c diff --git a/drivers/media/rc/img-ir/Kconfig b/drivers/media/rc/img-ir/Kconfig index 580715c..b20b3e9 100644 --- a/drivers/media/rc/img-ir/Kconfig +++ b/drivers/media/rc/img-ir/Kconfig @@ -60,3 +60,10 @@ config IR_IMG_SANYO help Say Y here to enable support for the Sanyo protocol (used by Sanyo, Aiwa, Chinon remotes) in the ImgTec infrared decoder block. + +config IR_IMG_RC5 + bool "Philips RC5 protocol support" + depends on IR_IMG_HW + help + Say Y here to enable support for the RC5 protocol in the ImgTec + infrared decoder block. diff --git a/drivers/media/rc/img-ir/Makefile b/drivers/media/rc/img-ir/Makefile index 92a459d..898b1b8 100644 --- a/drivers/media/rc/img-ir/Makefile +++ b/drivers/media/rc/img-ir/Makefile @@ -6,6 +6,7 @@ img-ir-$(CONFIG_IR_IMG_JVC) += img-ir-jvc.o img-ir-$(CONFIG_IR_IMG_SONY) += img-ir-sony.o img-ir-$(CONFIG_IR_IMG_SHARP) += img-ir-sharp.o img-ir-$(CONFIG_IR_IMG_SANYO) += img-ir-sanyo.o +img-ir-$(CONFIG_IR_IMG_RC5)+= img-ir-rc5.o img-ir-objs:= $(img-ir-y) obj-$(CONFIG_IR_IMG) += img-ir.o diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c index 5c32f05..13f0b1e 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.c +++ b/drivers/media/rc/img-ir/img-ir-hw.c @@ -42,6 +42,9 @@ static struct img_ir_decoder *img_ir_decoders[] = { #ifdef CONFIG_IR_IMG_SANYO &img_ir_sanyo, #endif +#ifdef CONFIG_IR_IMG_RC5 + &img_ir_rc5, +#endif NULL }; diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h index b31ffc9..b9e799d5 100644 --- a/drivers/media/rc/img-ir/img-ir-hw.h +++ b/drivers/media/rc/img-ir/img-ir-hw.h @@ -187,6 +187,7 @@ extern struct img_ir_decoder img_ir_jvc; extern struct img_ir_decoder img_ir_sony; extern struct img_ir_decoder img_ir_sharp; extern struct img_ir_decoder img_ir_sanyo; +extern struct img_ir_decoder img_ir_rc5; /** * struct img_ir_reg_timings - Reg values for decoder timings at clock rate. diff --git a/drivers/media/rc/img-ir/img-ir-rc5.c b/drivers/media/rc/img-ir/img-ir-rc5.c new file mode 100644 index 000..a8a28a3 --- /dev/null +++ b/drivers/media/rc/img-ir/img-ir-rc5.c @@ -0,0 +1,88 @@ +/* + * ImgTec IR Decoder setup for Philips RC-5 protocol. + * + * Copyright 2012-2014 Imagination Technologies Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include "img-ir-hw.h" + +/* Convert RC5 data to a scancode */ +static int img_ir_rc5_scancode(int len, u64 raw, u64 enabled_protocols, + struct img_ir_scancode_req *request) +{ + unsigned int addr, cmd, tgl, start; + + /* Quirk in the decoder shifts everything by 2 to the left. */ + raw >>= 2; + + start = (raw >> 13) & 0x01; + tgl = (raw >> 11) & 0x01; + addr= (raw >> 6) & 0x1f; + cmd = raw & 0x3f; + /* +* 12th bit is used to extend the command in extended RC5 and has +* no effect on standard RC5. +*/ + cmd += ((raw >> 12) & 0x01) ? 0 : 0x40; + + if (!start) + return -EINVAL; + + request->protocol = RC_TYPE_RC5; + request->scancode = addr << 8 | cmd; + request->toggle = tgl; + return IMG_IR_SCANCODE; +} + +/* Convert RC5 scancode to RC5 data filter */ +static int img_ir_rc5_filter(const struct rc_scancode_filter *in, +struct img_ir_filter *out, u64 protocols) +{ + /* Not supported by the hw. */ + return -EINVAL; +} + +/* + * RC-5 decoder + * see http://www.sbprojects.com/knowledge/ir/rc5.php + */ +struct img_ir_decoder img_ir_rc5 = { + .type = RC_BIT_RC5, + .control = { + .bitoriend2 = 1, + .code_type = IMG_IR_CODETYPE_BIPHASE, + .decodend2 = 1, + }, + /* main timings */ + .tolerance = 16, + .unit = 88, /* 1/36k*32=888.888microseconds */ + .timings= { + /* 10 symbol */ + .s10 = { + .pulse = { 1
RE: [PATCH 3/5] rc: img-ir: biphase enabled with workaround
> -Original Message- > From: James Hogan > Sent: 12 December 2014 10:56 > To: Sifan Naeem; mche...@osg.samsung.com > Cc: linux-kernel@vger.kernel.org; linux-me...@vger.kernel.org; James > Hartley; Ezequiel Garcia > Subject: Re: [PATCH 3/5] rc: img-ir: biphase enabled with workaround > > Hi Sifan, > > On 11/12/14 18:54, Sifan Naeem wrote: > >>> +/* > >>> + * 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; > >>> + > >>> + 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. */ > >> > >> 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. > >> > > don't have to clear it for this work around to work, so will remove. > > > >>> + 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); } > > To clarify, I was only referring to the case where the irq mask has changed > unexpectedly. If it hasn't changed then it would seem to make sense to clear > pending interrupts (i.e. the ones we've been intentionally ignoring) before > re-enabling them. > > When you say it works without, do you mean there never are pending > interrupts (if you don't press any other buttons on the remote)? > Nope, with the change I submitted in v2 (removed the clearing IRQ) there are no pending interrupts at the end. But as before it goes through the workaround couple of times for each interrupt before settling down. Thanks, Sifan > Cheers > James -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/