2014-12-11 20:05:56

by Sifan Naeem

[permalink] [raw]
Subject: [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


2014-12-11 20:06:00

by Sifan Naeem

[permalink] [raw]
Subject: [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 <[email protected]>
---
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;
}

diff --git a/drivers/media/rc/img-ir/img-ir-nec.c b/drivers/media/rc/img-ir/img-ir-nec.c
index 7398975..27a7ea8 100644
--- a/drivers/media/rc/img-ir/img-ir-nec.c
+++ b/drivers/media/rc/img-ir/img-ir-nec.c
@@ -13,8 +13,8 @@
#include <linux/bitrev.h>

/* Convert NEC data to a scancode */
-static int img_ir_nec_scancode(int len, u64 raw, enum rc_type *protocol,
- u32 *scancode, u64 enabled_protocols)
+static int img_ir_nec_scancode(int len, u64 raw, u64 enabled_protocols,
+ struct img_ir_scancode_req *request)
{
unsigned int addr, addr_inv, data, data_inv;
/* a repeat code has no data */
@@ -30,23 +30,23 @@ static int img_ir_nec_scancode(int len, u64 raw, enum rc_type *protocol,
if ((data_inv ^ data) != 0xff) {
/* 32-bit NEC (used by Apple and TiVo remotes) */
/* scan encoding: as transmitted, MSBit = first received bit */
- *scancode = bitrev8(addr) << 24 |
- bitrev8(addr_inv) << 16 |
- bitrev8(data) << 8 |
- bitrev8(data_inv);
+ request->scancode = bitrev8(addr) << 24 |
+ bitrev8(addr_inv) << 16 |
+ bitrev8(data) << 8 |
+ bitrev8(data_inv);
} else if ((addr_inv ^ addr) != 0xff) {
/* Extended NEC */
/* scan encoding: AAaaDD */
- *scancode = addr << 16 |
- addr_inv << 8 |
- data;
+ request->scancode = addr << 16 |
+ addr_inv << 8 |
+ data;
} else {
/* Normal NEC */
/* scan encoding: AADD */
- *scancode = addr << 8 |
- data;
+ request->scancode = addr << 8 |
+ data;
}
- *protocol = RC_TYPE_NEC;
+ request->protocol = RC_TYPE_NEC;
return IMG_IR_SCANCODE;
}

diff --git a/drivers/media/rc/img-ir/img-ir-sanyo.c b/drivers/media/rc/img-ir/img-ir-sanyo.c
index 6b0653e..f394994 100644
--- a/drivers/media/rc/img-ir/img-ir-sanyo.c
+++ b/drivers/media/rc/img-ir/img-ir-sanyo.c
@@ -23,8 +23,8 @@
#include "img-ir-hw.h"

/* Convert Sanyo data to a scancode */
-static int img_ir_sanyo_scancode(int len, u64 raw, enum rc_type *protocol,
- u32 *scancode, u64 enabled_protocols)
+static int img_ir_sanyo_scancode(int len, u64 raw, u64 enabled_protocols,
+ struct img_ir_scancode_req *request)
{
unsigned int addr, addr_inv, data, data_inv;
/* a repeat code has no data */
@@ -44,8 +44,8 @@ static int img_ir_sanyo_scancode(int len, u64 raw, enum rc_type *protocol,
return -EINVAL;

/* Normal Sanyo */
- *protocol = RC_TYPE_SANYO;
- *scancode = addr << 8 | data;
+ request->protocol = RC_TYPE_SANYO;
+ request->scancode = addr << 8 | data;
return IMG_IR_SCANCODE;
}

diff --git a/drivers/media/rc/img-ir/img-ir-sharp.c b/drivers/media/rc/img-ir/img-ir-sharp.c
index 3300a38..fe5acc4 100644
--- a/drivers/media/rc/img-ir/img-ir-sharp.c
+++ b/drivers/media/rc/img-ir/img-ir-sharp.c
@@ -12,8 +12,8 @@
#include "img-ir-hw.h"

/* Convert Sharp data to a scancode */
-static int img_ir_sharp_scancode(int len, u64 raw, enum rc_type *protocol,
- u32 *scancode, u64 enabled_protocols)
+static int img_ir_sharp_scancode(int len, u64 raw, u64 enabled_protocols,
+ struct img_ir_scancode_req *request)
{
unsigned int addr, cmd, exp, chk;

@@ -32,8 +32,8 @@ static int img_ir_sharp_scancode(int len, u64 raw, enum rc_type *protocol,
/* probably the second half of the message */
return -EINVAL;

- *protocol = RC_TYPE_SHARP;
- *scancode = addr << 8 | cmd;
+ request->protocol = RC_TYPE_SHARP;
+ request->scancode = addr << 8 | cmd;
return IMG_IR_SCANCODE;
}

diff --git a/drivers/media/rc/img-ir/img-ir-sony.c b/drivers/media/rc/img-ir/img-ir-sony.c
index 3a0f17b..7f7375f 100644
--- a/drivers/media/rc/img-ir/img-ir-sony.c
+++ b/drivers/media/rc/img-ir/img-ir-sony.c
@@ -12,8 +12,8 @@
#include "img-ir-hw.h"

/* Convert Sony data to a scancode */
-static int img_ir_sony_scancode(int len, u64 raw, enum rc_type *protocol,
- u32 *scancode, u64 enabled_protocols)
+static int img_ir_sony_scancode(int len, u64 raw, u64 enabled_protocols,
+ struct img_ir_scancode_req *request)
{
unsigned int dev, subdev, func;

@@ -25,7 +25,7 @@ static int img_ir_sony_scancode(int len, u64 raw, enum rc_type *protocol,
raw >>= 7;
dev = raw & 0x1f; /* next 5 bits */
subdev = 0;
- *protocol = RC_TYPE_SONY12;
+ request->protocol = RC_TYPE_SONY12;
break;
case 15:
if (!(enabled_protocols & RC_BIT_SONY15))
@@ -34,7 +34,7 @@ static int img_ir_sony_scancode(int len, u64 raw, enum rc_type *protocol,
raw >>= 7;
dev = raw & 0xff; /* next 8 bits */
subdev = 0;
- *protocol = RC_TYPE_SONY15;
+ request->protocol = RC_TYPE_SONY15;
break;
case 20:
if (!(enabled_protocols & RC_BIT_SONY20))
@@ -44,12 +44,12 @@ static int img_ir_sony_scancode(int len, u64 raw, enum rc_type *protocol,
dev = raw & 0x1f; /* next 5 bits */
raw >>= 5;
subdev = raw & 0xff; /* next 8 bits */
- *protocol = RC_TYPE_SONY20;
+ request->protocol = RC_TYPE_SONY20;
break;
default:
return -EINVAL;
}
- *scancode = dev << 16 | subdev << 8 | func;
+ request->scancode = dev << 16 | subdev << 8 | func;
return IMG_IR_SCANCODE;
}

--
1.7.9.5

2014-12-11 20:06:13

by Sifan Naeem

[permalink] [raw]
Subject: [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 <[email protected]>
---
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 0000000..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)
+{
+ /* Not supported by the hw. */
+ return -EINVAL;
+}
+
+/*
+ * RC-6 decoder
+ * see http://www.sbprojects.com/knowledge/ir/rc6.php
+ */
+struct img_ir_decoder img_ir_rc6 = {
+ .type = RC_BIT_RC6_0,
+ .control = {
+ .bitorien = 1,
+ .code_type = IMG_IR_CODETYPE_BIPHASE,
+ .decoden = 1,
+ .decodinpol = 1,
+ },
+ /* main timings */
+ .tolerance = 20,
+ /*
+ * Due to a quirk in the img-ir decoder, default header values do
+ * not work, the values described below were extracted from
+ * successful RTL test cases.
+ */
+ .timings = {
+ /* leader symbol */
+ .ldr = {
+ .pulse = { 650 },
+ .space = { 660 },
+ },
+ /* 0 symbol */
+ .s00 = {
+ .pulse = { 370 },
+ .space = { 370 },
+ },
+ /* 01 symbol */
+ .s01 = {
+ .pulse = { 370 },
+ .space = { 370 },
+ },
+ /* free time */
+ .ft = {
+ .minlen = 21,
+ .maxlen = 21,
+ .ft_min = 2666, /* 2.666 ms */
+ },
+ },
+
+ /* scancode logic */
+ .scancode = img_ir_rc6_scancode,
+ .filter = img_ir_rc6_filter,
+};
--
1.7.9.5

2014-12-11 20:06:35

by Sifan Naeem

[permalink] [raw]
Subject: [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 <[email protected]>
---
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_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;
}
@@ -995,6 +1047,8 @@ int img_ir_probe_hw(struct img_ir_priv *priv)

/* Set up the end timer */
setup_timer(&hw->end_timer, img_ir_end_timer, (unsigned long)priv);
+ setup_timer(&hw->suspend_timer, img_ir_suspend_timer,
+ (unsigned long)priv);

/* Register a clock notifier */
if (!IS_ERR(priv->clk)) {
diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h
index beac3a6..b31ffc9 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 {
* @rdev: Remote control device
* @clk_nb: Notifier block for clock notify events.
* @end_timer: Timer until repeat timeout.
+ * @suspend_timer: Timer to re-enable protocol.
* @decoder: Current decoder settings.
* @enabled_protocols: Currently enabled protocols.
* @clk_hz: Current core clock rate in Hz.
@@ -228,12 +229,14 @@ enum img_ir_mode {
* @stopping: Indicates that decoder is being taken down and timers
* should not be restarted.
* @suspend_irqen: Saved IRQ enable mask over suspend.
+ * @quirk_suspend_irq: Saved IRQ enable mask over quirk suspend timer.
*/
struct img_ir_priv_hw {
unsigned int ct_quirks[4];
struct rc_dev *rdev;
struct notifier_block clk_nb;
struct timer_list end_timer;
+ struct timer_list suspend_timer;
const struct img_ir_decoder *decoder;
u64 enabled_protocols;
unsigned long clk_hz;
@@ -244,6 +247,7 @@ struct img_ir_priv_hw {
enum img_ir_mode mode;
bool stopping;
u32 suspend_irqen;
+ u32 quirk_suspend_irq;
};

static inline bool img_ir_hw_enabled(struct img_ir_priv_hw *hw)
--
1.7.9.5

2014-12-11 20:06:52

by Sifan Naeem

[permalink] [raw]
Subject: [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 <[email protected]>
---
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 0000000..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 = 888888, /* 1/36k*32=888.888microseconds */
+ .timings = {
+ /* 10 symbol */
+ .s10 = {
+ .pulse = { 1 },
+ .space = { 1 },
+ },
+
+ /* 11 symbol */
+ .s11 = {
+ .pulse = { 1 },
+ .space = { 1 },
+ },
+
+ /* free time */
+ .ft = {
+ .minlen = 14,
+ .maxlen = 14,
+ .ft_min = 5,
+ },
+ },
+
+ /* scancode logic */
+ .scancode = img_ir_rc5_scancode,
+ .filter = img_ir_rc5_filter,
+};
--
1.7.9.5

2014-12-11 20:07:37

by Sifan Naeem

[permalink] [raw]
Subject: [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 <[email protected]>
---
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

2014-12-12 12:07:36

by James Hogan

[permalink] [raw]
Subject: Re: [PATCH v2 3/5] rc: img-ir: biphase enabled with workaround

Hi Sifan,

On 11/12/14 20:06, 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.
>
> 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

For future reference, the list of changes between patchset versions is
usually put after a "---" so that it doesn't get included in the final
git commit message. You can also add any Acked-by/Reviewed-by tags
you've been given to new versions of patchset, assuming nothing
significant has changed in that patch (maintainers generally add
relevant tags for you, that are sent in response to the patches being
applied).

Anyway, the whole patchset looks okay to me, aside from the one question
I just asked on patch 3 of v1, which I'm not so sure about. I'll let you
decide whether that needs changing since you have the hardware to verify it.

So for the whole patchset feel free to add my:
Acked-by: James Hogan <[email protected]>

Thanks
James

>
> Signed-off-by: Sifan Naeem <[email protected]>
> ---
> 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_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;
> }
> @@ -995,6 +1047,8 @@ int img_ir_probe_hw(struct img_ir_priv *priv)
>
> /* Set up the end timer */
> setup_timer(&hw->end_timer, img_ir_end_timer, (unsigned long)priv);
> + setup_timer(&hw->suspend_timer, img_ir_suspend_timer,
> + (unsigned long)priv);
>
> /* Register a clock notifier */
> if (!IS_ERR(priv->clk)) {
> diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h
> index beac3a6..b31ffc9 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 {
> * @rdev: Remote control device
> * @clk_nb: Notifier block for clock notify events.
> * @end_timer: Timer until repeat timeout.
> + * @suspend_timer: Timer to re-enable protocol.
> * @decoder: Current decoder settings.
> * @enabled_protocols: Currently enabled protocols.
> * @clk_hz: Current core clock rate in Hz.
> @@ -228,12 +229,14 @@ enum img_ir_mode {
> * @stopping: Indicates that decoder is being taken down and timers
> * should not be restarted.
> * @suspend_irqen: Saved IRQ enable mask over suspend.
> + * @quirk_suspend_irq: Saved IRQ enable mask over quirk suspend timer.
> */
> struct img_ir_priv_hw {
> unsigned int ct_quirks[4];
> struct rc_dev *rdev;
> struct notifier_block clk_nb;
> struct timer_list end_timer;
> + struct timer_list suspend_timer;
> const struct img_ir_decoder *decoder;
> u64 enabled_protocols;
> unsigned long clk_hz;
> @@ -244,6 +247,7 @@ struct img_ir_priv_hw {
> enum img_ir_mode mode;
> bool stopping;
> u32 suspend_irqen;
> + u32 quirk_suspend_irq;
> };
>
> static inline bool img_ir_hw_enabled(struct img_ir_priv_hw *hw)
>


Attachments:
signature.asc (819.00 B)
OpenPGP digital signature

2014-12-12 13:55:39

by James Hogan

[permalink] [raw]
Subject: Re: [PATCH v2 3/5] rc: img-ir: biphase enabled with workaround

On 12/12/14 12:07, James Hogan wrote:
> Hi Sifan,
>
> On 11/12/14 20:06, 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.
>>
>> 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
>
> For future reference, the list of changes between patchset versions is
> usually put after a "---" so that it doesn't get included in the final
> git commit message. You can also add any Acked-by/Reviewed-by tags
> you've been given to new versions of patchset, assuming nothing
> significant has changed in that patch (maintainers generally add
> relevant tags for you, that are sent in response to the patches being
> applied).
>
> Anyway, the whole patchset looks okay to me, aside from the one question
> I just asked on patch 3 of v1, which I'm not so sure about. I'll let you
> decide whether that needs changing since you have the hardware to verify it.
>
> So for the whole patchset feel free to add my:
> Acked-by: James Hogan <[email protected]>

Mauro: Assuming no other changes are requested in this patchset, do you
want these resent with the moving of changelogs out of the main commit
messages?

Cheers
James


Attachments:
signature.asc (819.00 B)
OpenPGP digital signature