aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/sunxi/patches-3.14/284-ir-backports-from-3.15.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/sunxi/patches-3.14/284-ir-backports-from-3.15.patch')
-rw-r--r--target/linux/sunxi/patches-3.14/284-ir-backports-from-3.15.patch1478
1 files changed, 575 insertions, 903 deletions
diff --git a/target/linux/sunxi/patches-3.14/284-ir-backports-from-3.15.patch b/target/linux/sunxi/patches-3.14/284-ir-backports-from-3.15.patch
index 37ccffce7e..9e703e7dce 100644
--- a/target/linux/sunxi/patches-3.14/284-ir-backports-from-3.15.patch
+++ b/target/linux/sunxi/patches-3.14/284-ir-backports-from-3.15.patch
@@ -31,233 +31,6 @@ Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
include/media/rc-core.h | 29 +++++++
3 files changed, 223 insertions(+)
-diff --git a/Documentation/ABI/testing/sysfs-class-rc b/Documentation/ABI/testing/sysfs-class-rc
-index 52bc057..c0e1d14 100644
-diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
-index f1b67db..fa8b957 100644
---- a/drivers/media/rc/rc-main.c
-+++ b/drivers/media/rc/rc-main.c
-@@ -969,6 +969,130 @@ static ssize_t store_protocols(struct device *device,
- return ret;
- }
-
-+/**
-+ * struct rc_filter_attribute - Device attribute relating to a filter type.
-+ * @attr: Device attribute.
-+ * @type: Filter type.
-+ * @mask: false for filter value, true for filter mask.
-+ */
-+struct rc_filter_attribute {
-+ struct device_attribute attr;
-+ enum rc_filter_type type;
-+ bool mask;
-+};
-+#define to_rc_filter_attr(a) container_of(a, struct rc_filter_attribute, attr)
-+
-+#define RC_FILTER_ATTR(_name, _mode, _show, _store, _type, _mask) \
-+ struct rc_filter_attribute dev_attr_##_name = { \
-+ .attr = __ATTR(_name, _mode, _show, _store), \
-+ .type = (_type), \
-+ .mask = (_mask), \
-+ }
-+
-+/**
-+ * show_filter() - shows the current scancode filter value or mask
-+ * @device: the device descriptor
-+ * @attr: the device attribute struct
-+ * @buf: a pointer to the output buffer
-+ *
-+ * This routine is a callback routine to read a scancode filter value or mask.
-+ * It is trigged by reading /sys/class/rc/rc?/[wakeup_]filter[_mask].
-+ * It prints the current scancode filter value or mask of the appropriate filter
-+ * type in hexadecimal into @buf and returns the size of the buffer.
-+ *
-+ * Bits of the filter value corresponding to set bits in the filter mask are
-+ * compared against input scancodes and non-matching scancodes are discarded.
-+ *
-+ * dev->lock is taken to guard against races between device registration,
-+ * store_filter and show_filter.
-+ */
-+static ssize_t show_filter(struct device *device,
-+ struct device_attribute *attr,
-+ char *buf)
-+{
-+ struct rc_dev *dev = to_rc_dev(device);
-+ struct rc_filter_attribute *fattr = to_rc_filter_attr(attr);
-+ u32 val;
-+
-+ /* Device is being removed */
-+ if (!dev)
-+ return -EINVAL;
-+
-+ mutex_lock(&dev->lock);
-+ if (!dev->s_filter)
-+ val = 0;
-+ else if (fattr->mask)
-+ val = dev->scancode_filters[fattr->type].mask;
-+ else
-+ val = dev->scancode_filters[fattr->type].data;
-+ mutex_unlock(&dev->lock);
-+
-+ return sprintf(buf, "%#x\n", val);
-+}
-+
-+/**
-+ * store_filter() - changes the scancode filter value
-+ * @device: the device descriptor
-+ * @attr: the device attribute struct
-+ * @buf: a pointer to the input buffer
-+ * @len: length of the input buffer
-+ *
-+ * This routine is for changing a scancode filter value or mask.
-+ * It is trigged by writing to /sys/class/rc/rc?/[wakeup_]filter[_mask].
-+ * Returns -EINVAL if an invalid filter value for the current protocol was
-+ * specified or if scancode filtering is not supported by the driver, otherwise
-+ * returns @len.
-+ *
-+ * Bits of the filter value corresponding to set bits in the filter mask are
-+ * compared against input scancodes and non-matching scancodes are discarded.
-+ *
-+ * dev->lock is taken to guard against races between device registration,
-+ * store_filter and show_filter.
-+ */
-+static ssize_t store_filter(struct device *device,
-+ struct device_attribute *attr,
-+ const char *buf,
-+ size_t count)
-+{
-+ struct rc_dev *dev = to_rc_dev(device);
-+ struct rc_filter_attribute *fattr = to_rc_filter_attr(attr);
-+ struct rc_scancode_filter local_filter, *filter;
-+ int ret;
-+ unsigned long val;
-+
-+ /* Device is being removed */
-+ if (!dev)
-+ return -EINVAL;
-+
-+ ret = kstrtoul(buf, 0, &val);
-+ if (ret < 0)
-+ return ret;
-+
-+ /* Scancode filter not supported (but still accept 0) */
-+ if (!dev->s_filter)
-+ return val ? -EINVAL : count;
-+
-+ mutex_lock(&dev->lock);
-+
-+ /* Tell the driver about the new filter */
-+ filter = &dev->scancode_filters[fattr->type];
-+ local_filter = *filter;
-+ if (fattr->mask)
-+ local_filter.mask = val;
-+ else
-+ local_filter.data = val;
-+ ret = dev->s_filter(dev, fattr->type, &local_filter);
-+ if (ret < 0)
-+ goto unlock;
-+
-+ /* Success, commit the new filter */
-+ *filter = local_filter;
-+
-+unlock:
-+ mutex_unlock(&dev->lock);
-+ return count;
-+}
-+
- static void rc_dev_release(struct device *device)
- {
- }
-@@ -1000,9 +1124,21 @@ static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env)
- */
- static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR,
- show_protocols, store_protocols);
-+static RC_FILTER_ATTR(filter, S_IRUGO|S_IWUSR,
-+ show_filter, store_filter, RC_FILTER_NORMAL, false);
-+static RC_FILTER_ATTR(filter_mask, S_IRUGO|S_IWUSR,
-+ show_filter, store_filter, RC_FILTER_NORMAL, true);
-+static RC_FILTER_ATTR(wakeup_filter, S_IRUGO|S_IWUSR,
-+ show_filter, store_filter, RC_FILTER_WAKEUP, false);
-+static RC_FILTER_ATTR(wakeup_filter_mask, S_IRUGO|S_IWUSR,
-+ show_filter, store_filter, RC_FILTER_WAKEUP, true);
-
- static struct attribute *rc_dev_attrs[] = {
- &dev_attr_protocols.attr,
-+ &dev_attr_filter.attr.attr,
-+ &dev_attr_filter_mask.attr.attr,
-+ &dev_attr_wakeup_filter.attr.attr,
-+ &dev_attr_wakeup_filter_mask.attr.attr,
- NULL,
- };
-
-diff --git a/include/media/rc-core.h b/include/media/rc-core.h
-index 2f6f1f7..4a72176 100644
---- a/include/media/rc-core.h
-+++ b/include/media/rc-core.h
-@@ -35,6 +35,29 @@ enum rc_driver_type {
- };
-
- /**
-+ * struct rc_scancode_filter - Filter scan codes.
-+ * @data: Scancode data to match.
-+ * @mask: Mask of bits of scancode to compare.
-+ */
-+struct rc_scancode_filter {
-+ u32 data;
-+ u32 mask;
-+};
-+
-+/**
-+ * enum rc_filter_type - Filter type constants.
-+ * @RC_FILTER_NORMAL: Filter for normal operation.
-+ * @RC_FILTER_WAKEUP: Filter for waking from suspend.
-+ * @RC_FILTER_MAX: Number of filter types.
-+ */
-+enum rc_filter_type {
-+ RC_FILTER_NORMAL = 0,
-+ RC_FILTER_WAKEUP,
-+
-+ RC_FILTER_MAX
-+};
-+
-+/**
- * struct rc_dev - represents a remote control device
- * @dev: driver model's view of this device
- * @input_name: name of the input child device
-@@ -70,6 +93,7 @@ enum rc_driver_type {
- * @max_timeout: maximum timeout supported by device
- * @rx_resolution : resolution (in ns) of input sampler
- * @tx_resolution: resolution (in ns) of output sampler
-+ * @scancode_filters: scancode filters (indexed by enum rc_filter_type)
- * @change_protocol: allow changing the protocol used on hardware decoders
- * @open: callback to allow drivers to enable polling/irq when IR input device
- * is opened.
-@@ -84,6 +108,7 @@ enum rc_driver_type {
- * device doesn't interrupt host until it sees IR pulses
- * @s_learning_mode: enable wide band receiver used for learning
- * @s_carrier_report: enable carrier reports
-+ * @s_filter: set the scancode filter of a given type
- */
- struct rc_dev {
- struct device dev;
-@@ -116,6 +141,7 @@ struct rc_dev {
- u32 max_timeout;
- u32 rx_resolution;
- u32 tx_resolution;
-+ struct rc_scancode_filter scancode_filters[RC_FILTER_MAX];
- int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
- int (*open)(struct rc_dev *dev);
- void (*close)(struct rc_dev *dev);
-@@ -127,6 +153,9 @@ struct rc_dev {
- void (*s_idle)(struct rc_dev *dev, bool enable);
- int (*s_learning_mode)(struct rc_dev *dev, int enable);
- int (*s_carrier_report) (struct rc_dev *dev, int enable);
-+ int (*s_filter)(struct rc_dev *dev,
-+ enum rc_filter_type type,
-+ struct rc_scancode_filter *filter);
- };
-
- #define to_rc_dev(d) container_of(d, struct rc_dev, dev)
From 7b802ce7e8c67510389fdbbe29edd87a75df3a93 Mon Sep 17 00:00:00 2001
From: James Hogan <james.hogan@imgtec.com>
Date: Mon, 10 Feb 2014 18:31:56 -0300
@@ -281,19 +54,6 @@ Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
drivers/media/rc/rc-main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
-diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
-index 2ec60f8..6448128 100644
---- a/drivers/media/rc/rc-main.c
-+++ b/drivers/media/rc/rc-main.c
-@@ -1090,7 +1090,7 @@ static ssize_t store_filter(struct device *device,
-
- unlock:
- mutex_unlock(&dev->lock);
-- return count;
-+ return (ret < 0) ? ret : count;
- }
-
- static void rc_dev_release(struct device *device)
From b8c7d915087c97a21fa415fa0e860e59739da202 Mon Sep 17 00:00:00 2001
From: James Hogan <james.hogan@imgtec.com>
Date: Fri, 28 Feb 2014 20:17:02 -0300
@@ -315,65 +75,6 @@ Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
drivers/media/rc/rc-main.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
-diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
-index 6448128..0a4f680f 100644
---- a/drivers/media/rc/rc-main.c
-+++ b/drivers/media/rc/rc-main.c
-@@ -633,6 +633,7 @@ EXPORT_SYMBOL_GPL(rc_repeat);
- static void ir_do_keydown(struct rc_dev *dev, int scancode,
- u32 keycode, u8 toggle)
- {
-+ struct rc_scancode_filter *filter;
- bool new_event = !dev->keypressed ||
- dev->last_scancode != scancode ||
- dev->last_toggle != toggle;
-@@ -640,6 +641,11 @@ static void ir_do_keydown(struct rc_dev *dev, int scancode,
- if (new_event && dev->keypressed)
- ir_do_keyup(dev, false);
-
-+ /* Generic scancode filtering */
-+ filter = &dev->scancode_filters[RC_FILTER_NORMAL];
-+ if (filter->mask && ((scancode ^ filter->data) & filter->mask))
-+ return;
-+
- input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode);
-
- if (new_event && keycode != KEY_RESERVED) {
-@@ -1019,9 +1025,7 @@ static ssize_t show_filter(struct device *device,
- return -EINVAL;
-
- mutex_lock(&dev->lock);
-- if (!dev->s_filter)
-- val = 0;
-- else if (fattr->mask)
-+ if (fattr->mask)
- val = dev->scancode_filters[fattr->type].mask;
- else
- val = dev->scancode_filters[fattr->type].data;
-@@ -1069,7 +1073,7 @@ static ssize_t store_filter(struct device *device,
- return ret;
-
- /* Scancode filter not supported (but still accept 0) */
-- if (!dev->s_filter)
-+ if (!dev->s_filter && fattr->type != RC_FILTER_NORMAL)
- return val ? -EINVAL : count;
-
- mutex_lock(&dev->lock);
-@@ -1081,9 +1085,11 @@ static ssize_t store_filter(struct device *device,
- local_filter.mask = val;
- else
- local_filter.data = val;
-- ret = dev->s_filter(dev, fattr->type, &local_filter);
-- if (ret < 0)
-- goto unlock;
-+ if (dev->s_filter) {
-+ ret = dev->s_filter(dev, fattr->type, &local_filter);
-+ if (ret < 0)
-+ goto unlock;
-+ }
-
- /* Success, commit the new filter */
- *filter = local_filter;
From 1a1934fab0c920f0d3bceeb60c9fe2dae8a56be9 Mon Sep 17 00:00:00 2001
From: James Hogan <james.hogan@imgtec.com>
Date: Fri, 28 Feb 2014 20:17:03 -0300
@@ -429,11 +130,114 @@ Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
include/media/rc-core.h | 22 ++++++++++++++++++++++
36 files changed, 73 insertions(+), 50 deletions(-)
-diff --git a/drivers/hid/hid-picolcd_cir.c b/drivers/hid/hid-picolcd_cir.c
-index 59d5eb1..cf1a9f1 100644
+From acff5f24732acc8a55d0a0f0ee1d19442267df63 Mon Sep 17 00:00:00 2001
+From: James Hogan <james.hogan@imgtec.com>
+Date: Fri, 28 Feb 2014 20:17:04 -0300
+Subject: [PATCH] [media] rc: add allowed/enabled wakeup protocol masks
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Only a single allowed and enabled protocol mask currently exists in
+struct rc_dev, however to support a separate wakeup filter protocol two
+of each are needed, ideally as an array.
+
+Therefore make both rc_dev::allowed_protos and rc_dev::enabled_protocols
+arrays, update all users to reference the first element
+(RC_FILTER_NORMAL), and add a couple more helper functions for drivers
+to use for setting the allowed and enabled wakeup protocols.
+
+We also rename allowed_protos to allowed_protocols while we're at it,
+which is more consistent with enabled_protocols.
+
+Signed-off-by: James Hogan <james.hogan@imgtec.com>
+Reviewed-by: Antti Seppälä <a.seppala@gmail.com>
+Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
+---
+ drivers/media/rc/rc-main.c | 10 +++++-----
+ include/media/rc-core.h | 32 ++++++++++++++++++++++++--------
+ 2 files changed, 29 insertions(+), 13 deletions(-)
+
+From ab88c66deace78989aa71cb139284cf7fb227ba4 Mon Sep 17 00:00:00 2001
+From: James Hogan <james.hogan@imgtec.com>
+Date: Fri, 28 Feb 2014 20:17:05 -0300
+Subject: [PATCH] [media] rc: add wakeup_protocols sysfs file
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add a wakeup_protocols sysfs file which controls the new
+rc_dev::enabled_protocols[RC_FILTER_WAKEUP], which is the mask of
+protocols that are used for the wakeup filter.
+
+A new RC driver callback change_wakeup_protocol() is called to change
+the wakeup protocol mask.
+
+Signed-off-by: James Hogan <james.hogan@imgtec.com>
+Reviewed-by: Antti Seppälä <a.seppala@gmail.com>
+Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
+---
+ Documentation/ABI/testing/sysfs-class-rc | 23 +++++-
+ .../DocBook/media/v4l/remote_controllers.xml | 20 +++++-
+ drivers/media/rc/rc-main.c | 82 +++++++++++++---------
+ include/media/rc-core.h | 3 +
+ 4 files changed, 90 insertions(+), 38 deletions(-)
+
+From 6bea25af147fcddcd8fd4557f4184c847c5c6ffd Mon Sep 17 00:00:00 2001
+From: James Hogan <james.hogan@imgtec.com>
+Date: Fri, 28 Feb 2014 20:17:06 -0300
+Subject: [PATCH] [media] rc-main: automatically refresh filter on protocol
+ change
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When either of the normal or wakeup filter protocols are changed,
+refresh the corresponding scancode filter, i.e. try and set the same
+scancode filter with the new protocol. If that fails clear the filter
+instead.
+
+If no protocol was selected the filter is just cleared, and if no
+s_filter callback exists the filter is left unmodified.
+
+Similarly clear the filter mask when the filter is set if no protocol is
+currently selected.
+
+This simplifies driver code which no longer has to explicitly worry
+about modifying the filter on a protocol change. This also allows the
+change_wakeup_protocol callback to be omitted entirely if there is only
+a single available wakeup protocol at a time, since selecting no
+protocol will automatically clear the wakeup filter, disabling wakeup.
+
+Signed-off-by: James Hogan <james.hogan@imgtec.com>
+Reviewed-by: Antti Seppälä <a.seppala@gmail.com>
+Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
+---
+ drivers/media/rc/rc-main.c | 41 +++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 39 insertions(+), 2 deletions(-)
+
+From 262912335c823a2bbcc87003ee55d62cc27f4e48 Mon Sep 17 00:00:00 2001
+From: James Hogan <james.hogan@imgtec.com>
+Date: Sat, 1 Mar 2014 19:52:25 -0300
+Subject: [PATCH] [media] rc-main: fix missing unlock if no devno left
+
+While playing with make coccicheck I noticed this message:
+drivers/media/rc/rc-main.c:1245:3-9: preceding lock on line 1238
+
+It was introduced by commit 587d1b06e07b ([media] rc-core: reuse device
+numbers) which returns -ENOMEM after a mutex_lock without first
+unlocking it when there are no more device numbers left. The added code
+doesn't depend on the device lock, so move it before the lock is taken.
+
+Signed-off-by: James Hogan <james.hogan@imgtec.com>
+Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
+---
+ drivers/media/rc/rc-main.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
--- a/drivers/hid/hid-picolcd_cir.c
+++ b/drivers/hid/hid-picolcd_cir.c
-@@ -114,7 +114,7 @@ int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report)
+@@ -114,7 +114,7 @@ int picolcd_init_cir(struct picolcd_data
rdev->priv = data;
rdev->driver_type = RC_DRIVER_IR_RAW;
@@ -442,11 +246,9 @@ index 59d5eb1..cf1a9f1 100644
rdev->open = picolcd_cir_open;
rdev->close = picolcd_cir_close;
rdev->input_name = data->hdev->name;
-diff --git a/drivers/media/common/siano/smsir.c b/drivers/media/common/siano/smsir.c
-index b8c5cad..6d7c0c8 100644
--- a/drivers/media/common/siano/smsir.c
+++ b/drivers/media/common/siano/smsir.c
-@@ -88,7 +88,7 @@ int sms_ir_init(struct smscore_device_t *coredev)
+@@ -88,7 +88,7 @@ int sms_ir_init(struct smscore_device_t
dev->priv = coredev;
dev->driver_type = RC_DRIVER_IR_RAW;
@@ -455,11 +257,9 @@ index b8c5cad..6d7c0c8 100644
dev->map_name = sms_get_board(board_id)->rc_codes;
dev->driver_name = MODULE_NAME;
-diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
-index 99ee456..c8fe135 100644
--- a/drivers/media/i2c/ir-kbd-i2c.c
+++ b/drivers/media/i2c/ir-kbd-i2c.c
-@@ -431,8 +431,8 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
+@@ -431,8 +431,8 @@ static int ir_probe(struct i2c_client *c
* Initialize the other fields of rc_dev
*/
rc->map_name = ir->ir_codes;
@@ -470,11 +270,9 @@ index 99ee456..c8fe135 100644
if (!rc->driver_name)
rc->driver_name = MODULE_NAME;
-diff --git a/drivers/media/pci/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c
-index 8a49e7c..097d0a0 100644
--- a/drivers/media/pci/cx23885/cx23885-input.c
+++ b/drivers/media/pci/cx23885/cx23885-input.c
-@@ -346,7 +346,7 @@ int cx23885_input_init(struct cx23885_dev *dev)
+@@ -346,7 +346,7 @@ int cx23885_input_init(struct cx23885_de
}
rc->dev.parent = &dev->pci->dev;
rc->driver_type = driver_type;
@@ -483,11 +281,9 @@ index 8a49e7c..097d0a0 100644
rc->priv = kernel_ir;
rc->open = cx23885_input_ir_open;
rc->close = cx23885_input_ir_close;
-diff --git a/drivers/media/pci/cx88/cx88-input.c b/drivers/media/pci/cx88/cx88-input.c
-index f29e18c..f991696 100644
--- a/drivers/media/pci/cx88/cx88-input.c
+++ b/drivers/media/pci/cx88/cx88-input.c
-@@ -469,7 +469,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
+@@ -469,7 +469,7 @@ int cx88_ir_init(struct cx88_core *core,
dev->timeout = 10 * 1000 * 1000; /* 10 ms */
} else {
dev->driver_type = RC_DRIVER_SCANCODE;
@@ -496,11 +292,9 @@ index f29e18c..f991696 100644
}
ir->core = core;
-diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c
-index 4d6a63f..2df7c55 100644
--- a/drivers/media/rc/ati_remote.c
+++ b/drivers/media/rc/ati_remote.c
-@@ -784,7 +784,7 @@ static void ati_remote_rc_init(struct ati_remote *ati_remote)
+@@ -784,7 +784,7 @@ static void ati_remote_rc_init(struct at
rdev->priv = ati_remote;
rdev->driver_type = RC_DRIVER_SCANCODE;
@@ -509,11 +303,9 @@ index 4d6a63f..2df7c55 100644
rdev->driver_name = "ati_remote";
rdev->open = ati_remote_rc_open;
-diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c
-index c1444f8..fc9d23f 100644
--- a/drivers/media/rc/ene_ir.c
+++ b/drivers/media/rc/ene_ir.c
-@@ -1059,7 +1059,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
+@@ -1059,7 +1059,7 @@ static int ene_probe(struct pnp_dev *pnp
learning_mode_force = false;
rdev->driver_type = RC_DRIVER_IR_RAW;
@@ -522,11 +314,9 @@ index c1444f8..fc9d23f 100644
rdev->priv = dev;
rdev->open = ene_open;
rdev->close = ene_close;
-diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c
-index d6fa441..46b66e5 100644
--- a/drivers/media/rc/fintek-cir.c
+++ b/drivers/media/rc/fintek-cir.c
-@@ -541,7 +541,7 @@ static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id
+@@ -541,7 +541,7 @@ static int fintek_probe(struct pnp_dev *
/* Set up the rc device */
rdev->priv = fintek;
rdev->driver_type = RC_DRIVER_IR_RAW;
@@ -535,11 +325,9 @@ index d6fa441..46b66e5 100644
rdev->open = fintek_open;
rdev->close = fintek_close;
rdev->input_name = FINTEK_DESCRIPTION;
-diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c
-index 80c611c..29b5f89 100644
--- a/drivers/media/rc/gpio-ir-recv.c
+++ b/drivers/media/rc/gpio-ir-recv.c
-@@ -145,9 +145,9 @@ static int gpio_ir_recv_probe(struct platform_device *pdev)
+@@ -145,9 +145,9 @@ static int gpio_ir_recv_probe(struct pla
rcdev->dev.parent = &pdev->dev;
rcdev->driver_name = GPIO_IR_DRIVER_NAME;
if (pdata->allowed_protos)
@@ -551,11 +339,9 @@ index 80c611c..29b5f89 100644
rcdev->map_name = pdata->map_name ?: RC_MAP_EMPTY;
gpio_dev->rcdev = rcdev;
-diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c
-index a83519a..627ddfd 100644
--- a/drivers/media/rc/iguanair.c
+++ b/drivers/media/rc/iguanair.c
-@@ -495,7 +495,7 @@ static int iguanair_probe(struct usb_interface *intf,
+@@ -494,7 +494,7 @@ static int iguanair_probe(struct usb_int
usb_to_input_id(ir->udev, &rc->input_id);
rc->dev.parent = &intf->dev;
rc->driver_type = RC_DRIVER_IR_RAW;
@@ -564,11 +350,9 @@ index a83519a..627ddfd 100644
rc->priv = ir;
rc->open = iguanair_open;
rc->close = iguanair_close;
-diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
-index 822b9f4..6f24e77 100644
--- a/drivers/media/rc/imon.c
+++ b/drivers/media/rc/imon.c
-@@ -1017,7 +1017,7 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 *rc_type)
+@@ -1017,7 +1017,7 @@ static int imon_ir_change_protocol(struc
unsigned char ir_proto_packet[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 };
@@ -577,7 +361,7 @@ index 822b9f4..6f24e77 100644
dev_warn(dev, "Looks like you're trying to use an IR protocol "
"this device does not support\n");
-@@ -1867,7 +1867,8 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx)
+@@ -1867,7 +1867,8 @@ static struct rc_dev *imon_init_rdev(str
rdev->priv = ictx;
rdev->driver_type = RC_DRIVER_SCANCODE;
@@ -587,7 +371,7 @@ index 822b9f4..6f24e77 100644
rdev->change_protocol = imon_ir_change_protocol;
rdev->driver_name = MOD_NAME;
-@@ -1880,7 +1881,7 @@ static struct rc_dev *imon_init_rdev(struct imon_context *ictx)
+@@ -1880,7 +1881,7 @@ static struct rc_dev *imon_init_rdev(str
if (ictx->product == 0xffdc) {
imon_get_ffdc_type(ictx);
@@ -596,11 +380,9 @@ index 822b9f4..6f24e77 100644
}
imon_set_display_type(ictx);
-diff --git a/drivers/media/rc/ir-jvc-decoder.c b/drivers/media/rc/ir-jvc-decoder.c
-index 3948138..4ea62a1 100644
--- a/drivers/media/rc/ir-jvc-decoder.c
+++ b/drivers/media/rc/ir-jvc-decoder.c
-@@ -47,7 +47,7 @@ static int ir_jvc_decode(struct rc_dev *dev, struct ir_raw_event ev)
+@@ -47,7 +47,7 @@ static int ir_jvc_decode(struct rc_dev *
{
struct jvc_dec *data = &dev->raw->jvc;
@@ -609,11 +391,9 @@ index 3948138..4ea62a1 100644
return 0;
if (!is_timing_event(ev)) {
-diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
-index ed2c8a1..d731da6 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
-@@ -35,7 +35,7 @@ static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev)
+@@ -35,7 +35,7 @@ static int ir_lirc_decode(struct rc_dev
struct lirc_codec *lirc = &dev->raw->lirc;
int sample;
@@ -622,11 +402,9 @@ index ed2c8a1..d731da6 100644
return 0;
if (!dev->raw->lirc.drv || !dev->raw->lirc.drv->rbuf)
-diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c
-index 9f3c9b5..0c55f79 100644
--- a/drivers/media/rc/ir-mce_kbd-decoder.c
+++ b/drivers/media/rc/ir-mce_kbd-decoder.c
-@@ -216,7 +216,7 @@ static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
+@@ -216,7 +216,7 @@ static int ir_mce_kbd_decode(struct rc_d
u32 scancode;
unsigned long delay;
@@ -635,11 +413,9 @@ index 9f3c9b5..0c55f79 100644
return 0;
if (!is_timing_event(ev)) {
-diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c
-index e687a42..9de1791 100644
--- a/drivers/media/rc/ir-nec-decoder.c
+++ b/drivers/media/rc/ir-nec-decoder.c
-@@ -52,7 +52,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
+@@ -52,7 +52,7 @@ static int ir_nec_decode(struct rc_dev *
u8 address, not_address, command, not_command;
bool send_32bits = false;
@@ -648,11 +424,9 @@ index e687a42..9de1791 100644
return 0;
if (!is_timing_event(ev)) {
-diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c
-index f0656fa..763c9d1 100644
--- a/drivers/media/rc/ir-raw.c
+++ b/drivers/media/rc/ir-raw.c
-@@ -256,7 +256,7 @@ int ir_raw_event_register(struct rc_dev *dev)
+@@ -256,7 +256,7 @@ int ir_raw_event_register(struct rc_dev
return -ENOMEM;
dev->raw->dev = dev;
@@ -661,11 +435,9 @@ index f0656fa..763c9d1 100644
rc = kfifo_alloc(&dev->raw->kfifo,
sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE,
GFP_KERNEL);
-diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c
-index 1085e17..4295d9b2 100644
--- a/drivers/media/rc/ir-rc5-decoder.c
+++ b/drivers/media/rc/ir-rc5-decoder.c
-@@ -52,7 +52,7 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)
+@@ -52,7 +52,7 @@ static int ir_rc5_decode(struct rc_dev *
u8 toggle;
u32 scancode;
@@ -674,7 +446,7 @@ index 1085e17..4295d9b2 100644
return 0;
if (!is_timing_event(ev)) {
-@@ -128,7 +128,7 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)
+@@ -128,7 +128,7 @@ again:
if (data->wanted_bits == RC5X_NBITS) {
/* RC5X */
u8 xdata, command, system;
@@ -683,7 +455,7 @@ index 1085e17..4295d9b2 100644
data->state = STATE_INACTIVE;
return 0;
}
-@@ -145,7 +145,7 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)
+@@ -145,7 +145,7 @@ again:
} else {
/* RC5 */
u8 command, system;
@@ -692,11 +464,9 @@ index 1085e17..4295d9b2 100644
data->state = STATE_INACTIVE;
return 0;
}
-diff --git a/drivers/media/rc/ir-rc5-sz-decoder.c b/drivers/media/rc/ir-rc5-sz-decoder.c
-index 984e5b9..dc18b74 100644
--- a/drivers/media/rc/ir-rc5-sz-decoder.c
+++ b/drivers/media/rc/ir-rc5-sz-decoder.c
-@@ -48,7 +48,7 @@ static int ir_rc5_sz_decode(struct rc_dev *dev, struct ir_raw_event ev)
+@@ -48,7 +48,7 @@ static int ir_rc5_sz_decode(struct rc_de
u8 toggle, command, system;
u32 scancode;
@@ -705,11 +475,9 @@ index 984e5b9..dc18b74 100644
return 0;
if (!is_timing_event(ev)) {
-diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c
-index 7cba7d3..cfbd64e 100644
--- a/drivers/media/rc/ir-rc6-decoder.c
+++ b/drivers/media/rc/ir-rc6-decoder.c
-@@ -89,9 +89,9 @@ static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev)
+@@ -89,9 +89,9 @@ static int ir_rc6_decode(struct rc_dev *
u32 scancode;
u8 toggle;
@@ -722,11 +490,9 @@ index 7cba7d3..cfbd64e 100644
return 0;
if (!is_timing_event(ev)) {
-diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c
-index e1351ed..eb715f0 100644
--- a/drivers/media/rc/ir-sanyo-decoder.c
+++ b/drivers/media/rc/ir-sanyo-decoder.c
-@@ -58,7 +58,7 @@ static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev)
+@@ -58,7 +58,7 @@ static int ir_sanyo_decode(struct rc_dev
u32 scancode;
u8 address, command, not_command;
@@ -735,13 +501,9 @@ index e1351ed..eb715f0 100644
return 0;
if (!is_timing_event(ev)) {
-diff --git a/drivers/media/rc/ir-sharp-decoder.c b/drivers/media/rc/ir-sharp-decoder.c
-index 4895bc7..66d2039 100644
-diff --git a/drivers/media/rc/ir-sony-decoder.c b/drivers/media/rc/ir-sony-decoder.c
-index 29ab9c2..599c19a 100644
--- a/drivers/media/rc/ir-sony-decoder.c
+++ b/drivers/media/rc/ir-sony-decoder.c
-@@ -45,8 +45,8 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
+@@ -45,8 +45,8 @@ static int ir_sony_decode(struct rc_dev
u32 scancode;
u8 device, subdevice, function;
@@ -752,7 +514,7 @@ index 29ab9c2..599c19a 100644
return 0;
if (!is_timing_event(ev)) {
-@@ -124,7 +124,7 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
+@@ -124,7 +124,7 @@ static int ir_sony_decode(struct rc_dev
switch (data->count) {
case 12:
@@ -761,7 +523,7 @@ index 29ab9c2..599c19a 100644
data->state = STATE_INACTIVE;
return 0;
}
-@@ -133,7 +133,7 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
+@@ -133,7 +133,7 @@ static int ir_sony_decode(struct rc_dev
function = bitrev8((data->bits >> 4) & 0xFE);
break;
case 15:
@@ -770,7 +532,7 @@ index 29ab9c2..599c19a 100644
data->state = STATE_INACTIVE;
return 0;
}
-@@ -142,7 +142,7 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
+@@ -142,7 +142,7 @@ static int ir_sony_decode(struct rc_dev
function = bitrev8((data->bits >> 7) & 0xFE);
break;
case 20:
@@ -779,11 +541,9 @@ index 29ab9c2..599c19a 100644
data->state = STATE_INACTIVE;
return 0;
}
-diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
-index 63b4225..ab24cc6 100644
--- a/drivers/media/rc/ite-cir.c
+++ b/drivers/media/rc/ite-cir.c
-@@ -1563,7 +1563,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
+@@ -1563,7 +1563,7 @@ static int ite_probe(struct pnp_dev *pde
/* set up ir-core props */
rdev->priv = itdev;
rdev->driver_type = RC_DRIVER_IR_RAW;
@@ -792,11 +552,9 @@ index 63b4225..ab24cc6 100644
rdev->open = ite_open;
rdev->close = ite_close;
rdev->s_idle = ite_s_idle;
-diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
-index c01b4c1..5d8f3d4 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
-@@ -1211,7 +1211,7 @@ static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
+@@ -1217,7 +1217,7 @@ static struct rc_dev *mceusb_init_rc_dev
rc->dev.parent = dev;
rc->priv = ir;
rc->driver_type = RC_DRIVER_IR_RAW;
@@ -805,11 +563,9 @@ index c01b4c1..5d8f3d4 100644
rc->timeout = MS_TO_NS(100);
if (!ir->flags.no_tx) {
rc->s_tx_mask = mceusb_set_tx_mask;
-diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
-index b81325d..d244e1a 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
-@@ -1044,7 +1044,7 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
+@@ -1042,7 +1042,7 @@ static int nvt_probe(struct pnp_dev *pde
/* Set up the rc device */
rdev->priv = nvt;
rdev->driver_type = RC_DRIVER_IR_RAW;
@@ -818,8 +574,6 @@ index b81325d..d244e1a 100644
rdev->open = nvt_open;
rdev->close = nvt_close;
rdev->tx_ir = nvt_tx_ir;
-diff --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c
-index 53d0282..0a88e0c 100644
--- a/drivers/media/rc/rc-loopback.c
+++ b/drivers/media/rc/rc-loopback.c
@@ -195,7 +195,7 @@ static int __init loop_init(void)
@@ -831,352 +585,29 @@ index 53d0282..0a88e0c 100644
rc->timeout = 100 * 1000 * 1000; /* 100 ms */
rc->min_timeout = 1;
rc->max_timeout = UINT_MAX;
-diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
-index a5d4f88..47cd373 100644
---- a/drivers/media/rc/redrat3.c
-+++ b/drivers/media/rc/redrat3.c
-@@ -922,7 +922,7 @@ static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3)
- rc->dev.parent = dev;
- rc->priv = rr3;
- rc->driver_type = RC_DRIVER_IR_RAW;
-- rc->allowed_protos = RC_BIT_ALL;
-+ rc_set_allowed_protocols(rc, RC_BIT_ALL);
- rc->timeout = US_TO_NS(2750);
- rc->tx_ir = redrat3_transmit_ir;
- rc->s_tx_carrier = redrat3_set_tx_carrier;
-diff --git a/drivers/media/rc/st_rc.c b/drivers/media/rc/st_rc.c
-index 8f0cddb..22e4c1f 100644
---- a/drivers/media/rc/st_rc.c
-+++ b/drivers/media/rc/st_rc.c
-@@ -287,7 +287,7 @@ static int st_rc_probe(struct platform_device *pdev)
- st_rc_hardware_init(rc_dev);
-
- rdev->driver_type = RC_DRIVER_IR_RAW;
-- rdev->allowed_protos = RC_BIT_ALL;
-+ rc_set_allowed_protocols(rdev, RC_BIT_ALL);
- /* rx sampling rate is 10Mhz */
- rdev->rx_resolution = 100;
- rdev->timeout = US_TO_NS(MAX_SYMB_TIME);
-diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
-index d7b11e6..f4e0bc3 100644
---- a/drivers/media/rc/streamzap.c
-+++ b/drivers/media/rc/streamzap.c
-@@ -322,7 +322,7 @@ static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz)
- rdev->dev.parent = dev;
- rdev->priv = sz;
- rdev->driver_type = RC_DRIVER_IR_RAW;
-- rdev->allowed_protos = RC_BIT_ALL;
-+ rc_set_allowed_protocols(rdev, RC_BIT_ALL);
- rdev->driver_name = DRIVER_NAME;
- rdev->map_name = RC_MAP_STREAMZAP;
-
-diff --git a/drivers/media/rc/ttusbir.c b/drivers/media/rc/ttusbir.c
-index d8de205..c5be38e 100644
---- a/drivers/media/rc/ttusbir.c
-+++ b/drivers/media/rc/ttusbir.c
-@@ -318,7 +318,7 @@ static int ttusbir_probe(struct usb_interface *intf,
- usb_to_input_id(tt->udev, &rc->input_id);
- rc->dev.parent = &intf->dev;
- rc->driver_type = RC_DRIVER_IR_RAW;
-- rc->allowed_protos = RC_BIT_ALL;
-+ rc_set_allowed_protocols(rc, RC_BIT_ALL);
- rc->priv = tt;
- rc->driver_name = DRIVER_NAME;
- rc->map_name = RC_MAP_TT_1500;
-diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c
-index 904baf4..a8b981f 100644
---- a/drivers/media/rc/winbond-cir.c
-+++ b/drivers/media/rc/winbond-cir.c
-@@ -1082,7 +1082,7 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
- data->dev->dev.parent = &device->dev;
- data->dev->timeout = MS_TO_NS(100);
- data->dev->rx_resolution = US_TO_NS(2);
-- data->dev->allowed_protos = RC_BIT_ALL;
-+ rc_set_allowed_protocols(data->dev, RC_BIT_ALL);
-
- err = rc_register_device(data->dev);
- if (err)
-diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
-index 8a054d6..de02db8 100644
---- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
-+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
-@@ -164,7 +164,7 @@ static int dvb_usbv2_remote_init(struct dvb_usb_device *d)
- dev->driver_name = (char *) d->props->driver_name;
- dev->map_name = d->rc.map_name;
- dev->driver_type = d->rc.driver_type;
-- dev->allowed_protos = d->rc.allowed_protos;
-+ rc_set_allowed_protocols(dev, d->rc.allowed_protos);
- dev->change_protocol = d->rc.change_protocol;
- dev->priv = d;
-
-diff --git a/drivers/media/usb/dvb-usb/dvb-usb-remote.c b/drivers/media/usb/dvb-usb/dvb-usb-remote.c
-index 41bacff..4058aea 100644
---- a/drivers/media/usb/dvb-usb/dvb-usb-remote.c
-+++ b/drivers/media/usb/dvb-usb/dvb-usb-remote.c
-@@ -272,7 +272,7 @@ static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d)
- dev->driver_name = d->props.rc.core.module_name;
- dev->map_name = d->props.rc.core.rc_codes;
- dev->change_protocol = d->props.rc.core.change_protocol;
-- dev->allowed_protos = d->props.rc.core.allowed_protos;
-+ rc_set_allowed_protocols(dev, d->props.rc.core.allowed_protos);
- dev->driver_type = d->props.rc.core.driver_type;
- usb_to_input_id(d->udev, &dev->input_id);
- dev->input_name = "IR-receiver inside an USB DVB receiver";
-diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c
-index 2a9bf66..56ef49d 100644
---- a/drivers/media/usb/em28xx/em28xx-input.c
-+++ b/drivers/media/usb/em28xx/em28xx-input.c
-@@ -727,7 +727,7 @@ static int em28xx_ir_init(struct em28xx *dev)
- case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2:
- rc->map_name = RC_MAP_HAUPPAUGE;
- ir->get_key_i2c = em28xx_get_key_em_haup;
-- rc->allowed_protos = RC_BIT_RC5;
-+ rc_set_allowed_protocols(rc, RC_BIT_RC5);
- break;
- case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE:
- rc->map_name = RC_MAP_WINFAST_USBII_DELUXE;
-@@ -743,7 +743,7 @@ static int em28xx_ir_init(struct em28xx *dev)
- switch (dev->chip_id) {
- case CHIP_ID_EM2860:
- case CHIP_ID_EM2883:
-- rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC;
-+ rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC);
- ir->get_key = default_polling_getkey;
- break;
- case CHIP_ID_EM2884:
-@@ -751,8 +751,8 @@ static int em28xx_ir_init(struct em28xx *dev)
- case CHIP_ID_EM28174:
- case CHIP_ID_EM28178:
- ir->get_key = em2874_polling_getkey;
-- rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC |
-- RC_BIT_RC6_0;
-+ rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC |
-+ RC_BIT_RC6_0);
- break;
- default:
- err = -ENODEV;
-diff --git a/drivers/media/usb/tm6000/tm6000-input.c b/drivers/media/usb/tm6000/tm6000-input.c
-index 8a6bbf1..d1af543 100644
---- a/drivers/media/usb/tm6000/tm6000-input.c
-+++ b/drivers/media/usb/tm6000/tm6000-input.c
-@@ -422,7 +422,7 @@ int tm6000_ir_init(struct tm6000_core *dev)
- ir->rc = rc;
-
- /* input setup */
-- rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC;
-+ rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC);
- /* Neded, in order to support NEC remotes with 24 or 32 bits */
- rc->scanmask = 0xffff;
- rc->priv = ir;
-diff --git a/include/media/rc-core.h b/include/media/rc-core.h
-index 5e7197e..6f3c3d9 100644
---- a/include/media/rc-core.h
-+++ b/include/media/rc-core.h
-@@ -160,6 +160,28 @@ struct rc_dev {
-
- #define to_rc_dev(d) container_of(d, struct rc_dev, dev)
-
-+static inline bool rc_protocols_allowed(struct rc_dev *rdev, u64 protos)
-+{
-+ return rdev->allowed_protos & protos;
-+}
-+
-+/* should be called prior to registration or with mutex held */
-+static inline void rc_set_allowed_protocols(struct rc_dev *rdev, u64 protos)
-+{
-+ rdev->allowed_protos = protos;
-+}
-+
-+static inline bool rc_protocols_enabled(struct rc_dev *rdev, u64 protos)
-+{
-+ return rdev->enabled_protocols & protos;
-+}
-+
-+/* should be called prior to registration or with mutex held */
-+static inline void rc_set_enabled_protocols(struct rc_dev *rdev, u64 protos)
-+{
-+ rdev->enabled_protocols = protos;
-+}
-+
- /*
- * From rc-main.c
- * Those functions can be used on any type of Remote Controller. They
-From acff5f24732acc8a55d0a0f0ee1d19442267df63 Mon Sep 17 00:00:00 2001
-From: James Hogan <james.hogan@imgtec.com>
-Date: Fri, 28 Feb 2014 20:17:04 -0300
-Subject: [PATCH] [media] rc: add allowed/enabled wakeup protocol masks
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Only a single allowed and enabled protocol mask currently exists in
-struct rc_dev, however to support a separate wakeup filter protocol two
-of each are needed, ideally as an array.
-
-Therefore make both rc_dev::allowed_protos and rc_dev::enabled_protocols
-arrays, update all users to reference the first element
-(RC_FILTER_NORMAL), and add a couple more helper functions for drivers
-to use for setting the allowed and enabled wakeup protocols.
-
-We also rename allowed_protos to allowed_protocols while we're at it,
-which is more consistent with enabled_protocols.
-
-Signed-off-by: James Hogan <james.hogan@imgtec.com>
-Reviewed-by: Antti Seppälä <a.seppala@gmail.com>
-Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
----
- drivers/media/rc/rc-main.c | 10 +++++-----
- include/media/rc-core.h | 32 ++++++++++++++++++++++++--------
- 2 files changed, 29 insertions(+), 13 deletions(-)
-
-diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
-index 0a4f680f..309d791 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
-@@ -830,9 +830,9 @@ static ssize_t show_protocols(struct device *device,
-
- mutex_lock(&dev->lock);
-
-- enabled = dev->enabled_protocols;
-+ enabled = dev->enabled_protocols[RC_FILTER_NORMAL];
- if (dev->driver_type == RC_DRIVER_SCANCODE)
-- allowed = dev->allowed_protos;
-+ allowed = dev->allowed_protocols[RC_FILTER_NORMAL];
- else if (dev->raw)
- allowed = ir_raw_get_allowed_protocols();
- else {
-@@ -906,7 +906,7 @@ static ssize_t store_protocols(struct device *device,
- ret = -EINVAL;
- goto out;
- }
-- type = dev->enabled_protocols;
-+ type = dev->enabled_protocols[RC_FILTER_NORMAL];
-
- while ((tmp = strsep((char **) &data, " \n")) != NULL) {
- if (!*tmp)
-@@ -964,7 +964,7 @@ static ssize_t store_protocols(struct device *device,
- }
- }
-
-- dev->enabled_protocols = type;
-+ dev->enabled_protocols[RC_FILTER_NORMAL] = type;
- IR_dprintk(1, "Current protocol(s): 0x%llx\n",
- (long long)type);
-
-@@ -1316,7 +1316,7 @@ int rc_register_device(struct rc_dev *dev)
- rc = dev->change_protocol(dev, &rc_type);
- if (rc < 0)
- goto out_raw;
-- dev->enabled_protocols = rc_type;
-+ dev->enabled_protocols[RC_FILTER_NORMAL] = rc_type;
- }
-
- mutex_unlock(&dev->lock);
-diff --git a/include/media/rc-core.h b/include/media/rc-core.h
-index 6f3c3d9..f165115 100644
---- a/include/media/rc-core.h
-+++ b/include/media/rc-core.h
-@@ -73,8 +73,10 @@ enum rc_filter_type {
- * @input_dev: the input child device used to communicate events to userspace
- * @driver_type: specifies if protocol decoding is done in hardware or software
- * @idle: used to keep track of RX state
-- * @allowed_protos: bitmask with the supported RC_BIT_* protocols
-- * @enabled_protocols: bitmask with the enabled RC_BIT_* protocols
-+ * @allowed_protocols: bitmask with the supported RC_BIT_* protocols for each
-+ * filter type
-+ * @enabled_protocols: bitmask with the enabled RC_BIT_* protocols for each
-+ * filter type
- * @scanmask: some hardware decoders are not capable of providing the full
- * scancode to the application. As this is a hardware limit, we can't do
- * anything with it. Yet, as the same keycode table can be used with other
-@@ -124,8 +126,8 @@ struct rc_dev {
- struct input_dev *input_dev;
- enum rc_driver_type driver_type;
- bool idle;
-- u64 allowed_protos;
-- u64 enabled_protocols;
-+ u64 allowed_protocols[RC_FILTER_MAX];
-+ u64 enabled_protocols[RC_FILTER_MAX];
- u32 users;
- u32 scanmask;
- void *priv;
-@@ -162,24 +164,38 @@ struct rc_dev {
-
- static inline bool rc_protocols_allowed(struct rc_dev *rdev, u64 protos)
- {
-- return rdev->allowed_protos & protos;
-+ return rdev->allowed_protocols[RC_FILTER_NORMAL] & protos;
- }
-
- /* should be called prior to registration or with mutex held */
- static inline void rc_set_allowed_protocols(struct rc_dev *rdev, u64 protos)
- {
-- rdev->allowed_protos = protos;
-+ rdev->allowed_protocols[RC_FILTER_NORMAL] = protos;
- }
-
- static inline bool rc_protocols_enabled(struct rc_dev *rdev, u64 protos)
+@@ -633,6 +633,7 @@ EXPORT_SYMBOL_GPL(rc_repeat);
+ static void ir_do_keydown(struct rc_dev *dev, int scancode,
+ u32 keycode, u8 toggle)
{
-- return rdev->enabled_protocols & protos;
-+ return rdev->enabled_protocols[RC_FILTER_NORMAL] & protos;
- }
++ struct rc_scancode_filter *filter;
+ bool new_event = !dev->keypressed ||
+ dev->last_scancode != scancode ||
+ dev->last_toggle != toggle;
+@@ -640,6 +641,11 @@ static void ir_do_keydown(struct rc_dev
+ if (new_event && dev->keypressed)
+ ir_do_keyup(dev, false);
- /* should be called prior to registration or with mutex held */
- static inline void rc_set_enabled_protocols(struct rc_dev *rdev, u64 protos)
- {
-- rdev->enabled_protocols = protos;
-+ rdev->enabled_protocols[RC_FILTER_NORMAL] = protos;
-+}
-+
-+/* should be called prior to registration or with mutex held */
-+static inline void rc_set_allowed_wakeup_protocols(struct rc_dev *rdev,
-+ u64 protos)
-+{
-+ rdev->allowed_protocols[RC_FILTER_WAKEUP] = protos;
-+}
++ /* Generic scancode filtering */
++ filter = &dev->scancode_filters[RC_FILTER_NORMAL];
++ if (filter->mask && ((scancode ^ filter->data) & filter->mask))
++ return;
+
-+/* should be called prior to registration or with mutex held */
-+static inline void rc_set_enabled_wakeup_protocols(struct rc_dev *rdev,
-+ u64 protos)
-+{
-+ rdev->enabled_protocols[RC_FILTER_WAKEUP] = protos;
- }
+ input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode);
- /*
-From ab88c66deace78989aa71cb139284cf7fb227ba4 Mon Sep 17 00:00:00 2001
-From: James Hogan <james.hogan@imgtec.com>
-Date: Fri, 28 Feb 2014 20:17:05 -0300
-Subject: [PATCH] [media] rc: add wakeup_protocols sysfs file
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Add a wakeup_protocols sysfs file which controls the new
-rc_dev::enabled_protocols[RC_FILTER_WAKEUP], which is the mask of
-protocols that are used for the wakeup filter.
-
-A new RC driver callback change_wakeup_protocol() is called to change
-the wakeup protocol mask.
-
-Signed-off-by: James Hogan <james.hogan@imgtec.com>
-Reviewed-by: Antti Seppälä <a.seppala@gmail.com>
-Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
----
- Documentation/ABI/testing/sysfs-class-rc | 23 +++++-
- .../DocBook/media/v4l/remote_controllers.xml | 20 +++++-
- drivers/media/rc/rc-main.c | 82 +++++++++++++---------
- include/media/rc-core.h | 3 +
- 4 files changed, 90 insertions(+), 38 deletions(-)
-
-diff --git a/Documentation/ABI/testing/sysfs-class-rc b/Documentation/ABI/testing/sysfs-class-rc
-index c0e1d14..b65674d 100644
-diff --git a/Documentation/DocBook/media/v4l/remote_controllers.xml b/Documentation/DocBook/media/v4l/remote_controllers.xml
-index c440a81..5124a6c 100644
-diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
-index 309d791..e6e3ec7 100644
---- a/drivers/media/rc/rc-main.c
-+++ b/drivers/media/rc/rc-main.c
-@@ -803,13 +803,38 @@ static struct {
+ if (new_event && keycode != KEY_RESERVED) {
+@@ -795,13 +801,38 @@ static struct {
};
/**
@@ -1217,7 +648,7 @@ index 309d791..e6e3ec7 100644
* It returns the protocol names of supported protocols.
* Enabled protocols are printed in brackets.
*
-@@ -820,6 +845,7 @@ static ssize_t show_protocols(struct device *device,
+@@ -812,6 +843,7 @@ static ssize_t show_protocols(struct dev
struct device_attribute *mattr, char *buf)
{
struct rc_dev *dev = to_rc_dev(device);
@@ -1225,13 +656,13 @@ index 309d791..e6e3ec7 100644
u64 allowed, enabled;
char *tmp = buf;
int i;
-@@ -830,9 +856,10 @@ static ssize_t show_protocols(struct device *device,
+@@ -822,9 +854,10 @@ static ssize_t show_protocols(struct dev
mutex_lock(&dev->lock);
-- enabled = dev->enabled_protocols[RC_FILTER_NORMAL];
+- enabled = dev->enabled_protocols;
- if (dev->driver_type == RC_DRIVER_SCANCODE)
-- allowed = dev->allowed_protocols[RC_FILTER_NORMAL];
+- allowed = dev->allowed_protos;
+ enabled = dev->enabled_protocols[fattr->type];
+ if (dev->driver_type == RC_DRIVER_SCANCODE ||
+ fattr->type == RC_FILTER_WAKEUP)
@@ -1239,7 +670,7 @@ index 309d791..e6e3ec7 100644
else if (dev->raw)
allowed = ir_raw_get_allowed_protocols();
else {
-@@ -864,14 +891,14 @@ static ssize_t show_protocols(struct device *device,
+@@ -856,14 +889,14 @@ static ssize_t show_protocols(struct dev
}
/**
@@ -1256,31 +687,34 @@ index 309d791..e6e3ec7 100644
* Writing "+proto" will add a protocol to the list of enabled protocols.
* Writing "-proto" will remove a protocol from the list of enabled protocols.
* Writing "proto" will enable only "proto".
-@@ -888,12 +915,14 @@ static ssize_t store_protocols(struct device *device,
+@@ -880,12 +913,15 @@ static ssize_t store_protocols(struct de
size_t len)
{
struct rc_dev *dev = to_rc_dev(device);
+ struct rc_filter_attribute *fattr = to_rc_filter_attr(mattr);
bool enable, disable;
const char *tmp;
- u64 type;
+- u64 type;
++ u64 old_type, type;
u64 mask;
int rc, i, count = 0;
ssize_t ret;
+ int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
++ struct rc_scancode_filter local_filter, *filter;
/* Device is being removed */
if (!dev)
-@@ -906,7 +935,7 @@ static ssize_t store_protocols(struct device *device,
+@@ -898,7 +934,8 @@ static ssize_t store_protocols(struct de
ret = -EINVAL;
goto out;
}
-- type = dev->enabled_protocols[RC_FILTER_NORMAL];
-+ type = dev->enabled_protocols[fattr->type];
+- type = dev->enabled_protocols;
++ old_type = dev->enabled_protocols[fattr->type];
++ type = old_type;
while ((tmp = strsep((char **) &data, " \n")) != NULL) {
if (!*tmp)
-@@ -954,8 +983,10 @@ static ssize_t store_protocols(struct device *device,
+@@ -946,8 +983,10 @@ static ssize_t store_protocols(struct de
goto out;
}
@@ -1293,151 +727,15 @@ index 309d791..e6e3ec7 100644
if (rc < 0) {
IR_dprintk(1, "Error setting protocols to 0x%llx\n",
(long long)type);
-@@ -964,7 +995,7 @@ static ssize_t store_protocols(struct device *device,
+@@ -956,10 +995,40 @@ static ssize_t store_protocols(struct de
}
}
-- dev->enabled_protocols[RC_FILTER_NORMAL] = type;
+- dev->enabled_protocols = type;
+ dev->enabled_protocols[fattr->type] = type;
IR_dprintk(1, "Current protocol(s): 0x%llx\n",
(long long)type);
-@@ -976,26 +1007,6 @@ static ssize_t store_protocols(struct device *device,
- }
-
- /**
-- * struct rc_filter_attribute - Device attribute relating to a filter type.
-- * @attr: Device attribute.
-- * @type: Filter type.
-- * @mask: false for filter value, true for filter mask.
-- */
--struct rc_filter_attribute {
-- struct device_attribute attr;
-- enum rc_filter_type type;
-- bool mask;
--};
--#define to_rc_filter_attr(a) container_of(a, struct rc_filter_attribute, attr)
--
--#define RC_FILTER_ATTR(_name, _mode, _show, _store, _type, _mask) \
-- struct rc_filter_attribute dev_attr_##_name = { \
-- .attr = __ATTR(_name, _mode, _show, _store), \
-- .type = (_type), \
-- .mask = (_mask), \
-- }
--
--/**
- * show_filter() - shows the current scancode filter value or mask
- * @device: the device descriptor
- * @attr: the device attribute struct
-@@ -1128,8 +1139,10 @@ static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env)
- /*
- * Static device attribute struct with the sysfs attributes for IR's
- */
--static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR,
-- show_protocols, store_protocols);
-+static RC_PROTO_ATTR(protocols, S_IRUGO | S_IWUSR,
-+ show_protocols, store_protocols, RC_FILTER_NORMAL);
-+static RC_PROTO_ATTR(wakeup_protocols, S_IRUGO | S_IWUSR,
-+ show_protocols, store_protocols, RC_FILTER_WAKEUP);
- static RC_FILTER_ATTR(filter, S_IRUGO|S_IWUSR,
- show_filter, store_filter, RC_FILTER_NORMAL, false);
- static RC_FILTER_ATTR(filter_mask, S_IRUGO|S_IWUSR,
-@@ -1140,7 +1153,8 @@ static RC_FILTER_ATTR(wakeup_filter_mask, S_IRUGO|S_IWUSR,
- show_filter, store_filter, RC_FILTER_WAKEUP, true);
-
- static struct attribute *rc_dev_attrs[] = {
-- &dev_attr_protocols.attr,
-+ &dev_attr_protocols.attr.attr,
-+ &dev_attr_wakeup_protocols.attr.attr,
- &dev_attr_filter.attr.attr,
- &dev_attr_filter_mask.attr.attr,
- &dev_attr_wakeup_filter.attr.attr,
-diff --git a/include/media/rc-core.h b/include/media/rc-core.h
-index f165115..0b9f890 100644
---- a/include/media/rc-core.h
-+++ b/include/media/rc-core.h
-@@ -97,6 +97,8 @@ enum rc_filter_type {
- * @tx_resolution: resolution (in ns) of output sampler
- * @scancode_filters: scancode filters (indexed by enum rc_filter_type)
- * @change_protocol: allow changing the protocol used on hardware decoders
-+ * @change_wakeup_protocol: allow changing the protocol used for wakeup
-+ * filtering
- * @open: callback to allow drivers to enable polling/irq when IR input device
- * is opened.
- * @close: callback to allow drivers to disable polling/irq when IR input device
-@@ -145,6 +147,7 @@ struct rc_dev {
- u32 tx_resolution;
- struct rc_scancode_filter scancode_filters[RC_FILTER_MAX];
- int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
-+ int (*change_wakeup_protocol)(struct rc_dev *dev, u64 *rc_type);
- int (*open)(struct rc_dev *dev);
- void (*close)(struct rc_dev *dev);
- int (*s_tx_mask)(struct rc_dev *dev, u32 mask);
-From 6bea25af147fcddcd8fd4557f4184c847c5c6ffd Mon Sep 17 00:00:00 2001
-From: James Hogan <james.hogan@imgtec.com>
-Date: Fri, 28 Feb 2014 20:17:06 -0300
-Subject: [PATCH] [media] rc-main: automatically refresh filter on protocol
- change
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-When either of the normal or wakeup filter protocols are changed,
-refresh the corresponding scancode filter, i.e. try and set the same
-scancode filter with the new protocol. If that fails clear the filter
-instead.
-
-If no protocol was selected the filter is just cleared, and if no
-s_filter callback exists the filter is left unmodified.
-
-Similarly clear the filter mask when the filter is set if no protocol is
-currently selected.
-
-This simplifies driver code which no longer has to explicitly worry
-about modifying the filter on a protocol change. This also allows the
-change_wakeup_protocol callback to be omitted entirely if there is only
-a single available wakeup protocol at a time, since selecting no
-protocol will automatically clear the wakeup filter, disabling wakeup.
-
-Signed-off-by: James Hogan <james.hogan@imgtec.com>
-Reviewed-by: Antti Seppälä <a.seppala@gmail.com>
-Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
----
- drivers/media/rc/rc-main.c | 41 +++++++++++++++++++++++++++++++++++++++--
- 1 file changed, 39 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
-index e6e3ec7..b1a6900 100644
---- a/drivers/media/rc/rc-main.c
-+++ b/drivers/media/rc/rc-main.c
-@@ -918,11 +918,12 @@ static ssize_t store_protocols(struct device *device,
- struct rc_filter_attribute *fattr = to_rc_filter_attr(mattr);
- bool enable, disable;
- const char *tmp;
-- u64 type;
-+ u64 old_type, type;
- u64 mask;
- int rc, i, count = 0;
- ssize_t ret;
- int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
-+ struct rc_scancode_filter local_filter, *filter;
-
- /* Device is being removed */
- if (!dev)
-@@ -935,7 +936,8 @@ static ssize_t store_protocols(struct device *device,
- ret = -EINVAL;
- goto out;
- }
-- type = dev->enabled_protocols[fattr->type];
-+ old_type = dev->enabled_protocols[fattr->type];
-+ type = old_type;
-
- while ((tmp = strsep((char **) &data, " \n")) != NULL) {
- if (!*tmp)
-@@ -999,6 +1001,36 @@ static ssize_t store_protocols(struct device *device,
- IR_dprintk(1, "Current protocol(s): 0x%llx\n",
- (long long)type);
-
+ /*
+ * If the protocol is changed the filter needs updating.
+ * Try setting the same filter with the new protocol (if any).
@@ -1471,42 +769,153 @@ index e6e3ec7..b1a6900 100644
ret = len;
out:
-@@ -1096,6 +1128,11 @@ static ssize_t store_filter(struct device *device,
- local_filter.mask = val;
- else
- local_filter.data = val;
+@@ -967,6 +1036,115 @@ out:
+ return ret;
+ }
+
++/**
++ * show_filter() - shows the current scancode filter value or mask
++ * @device: the device descriptor
++ * @attr: the device attribute struct
++ * @buf: a pointer to the output buffer
++ *
++ * This routine is a callback routine to read a scancode filter value or mask.
++ * It is trigged by reading /sys/class/rc/rc?/[wakeup_]filter[_mask].
++ * It prints the current scancode filter value or mask of the appropriate filter
++ * type in hexadecimal into @buf and returns the size of the buffer.
++ *
++ * Bits of the filter value corresponding to set bits in the filter mask are
++ * compared against input scancodes and non-matching scancodes are discarded.
++ *
++ * dev->lock is taken to guard against races between device registration,
++ * store_filter and show_filter.
++ */
++static ssize_t show_filter(struct device *device,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct rc_dev *dev = to_rc_dev(device);
++ struct rc_filter_attribute *fattr = to_rc_filter_attr(attr);
++ u32 val;
++
++ /* Device is being removed */
++ if (!dev)
++ return -EINVAL;
++
++ mutex_lock(&dev->lock);
++ if (fattr->mask)
++ val = dev->scancode_filters[fattr->type].mask;
++ else
++ val = dev->scancode_filters[fattr->type].data;
++ mutex_unlock(&dev->lock);
++
++ return sprintf(buf, "%#x\n", val);
++}
++
++/**
++ * store_filter() - changes the scancode filter value
++ * @device: the device descriptor
++ * @attr: the device attribute struct
++ * @buf: a pointer to the input buffer
++ * @len: length of the input buffer
++ *
++ * This routine is for changing a scancode filter value or mask.
++ * It is trigged by writing to /sys/class/rc/rc?/[wakeup_]filter[_mask].
++ * Returns -EINVAL if an invalid filter value for the current protocol was
++ * specified or if scancode filtering is not supported by the driver, otherwise
++ * returns @len.
++ *
++ * Bits of the filter value corresponding to set bits in the filter mask are
++ * compared against input scancodes and non-matching scancodes are discarded.
++ *
++ * dev->lock is taken to guard against races between device registration,
++ * store_filter and show_filter.
++ */
++static ssize_t store_filter(struct device *device,
++ struct device_attribute *attr,
++ const char *buf,
++ size_t count)
++{
++ struct rc_dev *dev = to_rc_dev(device);
++ struct rc_filter_attribute *fattr = to_rc_filter_attr(attr);
++ struct rc_scancode_filter local_filter, *filter;
++ int ret;
++ unsigned long val;
++
++ /* Device is being removed */
++ if (!dev)
++ return -EINVAL;
++
++ ret = kstrtoul(buf, 0, &val);
++ if (ret < 0)
++ return ret;
++
++ /* Scancode filter not supported (but still accept 0) */
++ if (!dev->s_filter && fattr->type != RC_FILTER_NORMAL)
++ return val ? -EINVAL : count;
++
++ mutex_lock(&dev->lock);
++
++ /* Tell the driver about the new filter */
++ filter = &dev->scancode_filters[fattr->type];
++ local_filter = *filter;
++ if (fattr->mask)
++ local_filter.mask = val;
++ else
++ local_filter.data = val;
+ if (!dev->enabled_protocols[fattr->type] && local_filter.mask) {
+ /* refuse to set a filter unless a protocol is enabled */
+ ret = -EINVAL;
+ goto unlock;
+ }
- if (dev->s_filter) {
- ret = dev->s_filter(dev, fattr->type, &local_filter);
- if (ret < 0)
-From 262912335c823a2bbcc87003ee55d62cc27f4e48 Mon Sep 17 00:00:00 2001
-From: James Hogan <james.hogan@imgtec.com>
-Date: Sat, 1 Mar 2014 19:52:25 -0300
-Subject: [PATCH] [media] rc-main: fix missing unlock if no devno left
-
-While playing with make coccicheck I noticed this message:
-drivers/media/rc/rc-main.c:1245:3-9: preceding lock on line 1238
-
-It was introduced by commit 587d1b06e07b ([media] rc-core: reuse device
-numbers) which returns -ENOMEM after a mutex_lock without first
-unlocking it when there are no more device numbers left. The added code
-doesn't depend on the device lock, so move it before the lock is taken.
-
-Signed-off-by: James Hogan <james.hogan@imgtec.com>
-Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
----
- drivers/media/rc/rc-main.c | 16 ++++++++--------
- 1 file changed, 8 insertions(+), 8 deletions(-)
-
-diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
-index b1a6900..f87e0f0 100644
---- a/drivers/media/rc/rc-main.c
-+++ b/drivers/media/rc/rc-main.c
-@@ -1286,14 +1286,6 @@ int rc_register_device(struct rc_dev *dev)
++ if (dev->s_filter) {
++ ret = dev->s_filter(dev, fattr->type, &local_filter);
++ if (ret < 0)
++ goto unlock;
++ }
++
++ /* Success, commit the new filter */
++ *filter = local_filter;
++
++unlock:
++ mutex_unlock(&dev->lock);
++ return (ret < 0) ? ret : count;
++}
++
+ static void rc_dev_release(struct device *device)
+ {
+ }
+@@ -996,11 +1174,26 @@ static int rc_dev_uevent(struct device *
+ /*
+ * Static device attribute struct with the sysfs attributes for IR's
+ */
+-static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR,
+- show_protocols, store_protocols);
++static RC_PROTO_ATTR(protocols, S_IRUGO | S_IWUSR,
++ show_protocols, store_protocols, RC_FILTER_NORMAL);
++static RC_PROTO_ATTR(wakeup_protocols, S_IRUGO | S_IWUSR,
++ show_protocols, store_protocols, RC_FILTER_WAKEUP);
++static RC_FILTER_ATTR(filter, S_IRUGO|S_IWUSR,
++ show_filter, store_filter, RC_FILTER_NORMAL, false);
++static RC_FILTER_ATTR(filter_mask, S_IRUGO|S_IWUSR,
++ show_filter, store_filter, RC_FILTER_NORMAL, true);
++static RC_FILTER_ATTR(wakeup_filter, S_IRUGO|S_IWUSR,
++ show_filter, store_filter, RC_FILTER_WAKEUP, false);
++static RC_FILTER_ATTR(wakeup_filter_mask, S_IRUGO|S_IWUSR,
++ show_filter, store_filter, RC_FILTER_WAKEUP, true);
+
+ static struct attribute *rc_dev_attrs[] = {
+- &dev_attr_protocols.attr,
++ &dev_attr_protocols.attr.attr,
++ &dev_attr_wakeup_protocols.attr.attr,
++ &dev_attr_filter.attr.attr,
++ &dev_attr_filter_mask.attr.attr,
++ &dev_attr_wakeup_filter.attr.attr,
++ &dev_attr_wakeup_filter_mask.attr.attr,
+ NULL,
+ };
+
+@@ -1091,14 +1284,6 @@ int rc_register_device(struct rc_dev *de
if (dev->close)
dev->input_dev->close = ir_close;
@@ -1521,7 +930,7 @@ index b1a6900..f87e0f0 100644
do {
devno = find_first_zero_bit(ir_core_dev_number,
IRRCV_NUM_DEVICES);
-@@ -1302,6 +1294,14 @@ int rc_register_device(struct rc_dev *dev)
+@@ -1107,6 +1292,14 @@ int rc_register_device(struct rc_dev *de
return -ENOMEM;
} while (test_and_set_bit(devno, ir_core_dev_number));
@@ -1536,3 +945,266 @@ index b1a6900..f87e0f0 100644
dev->devno = devno;
dev_set_name(&dev->dev, "rc%ld", dev->devno);
dev_set_drvdata(&dev->dev, dev);
+@@ -1172,7 +1365,7 @@ int rc_register_device(struct rc_dev *de
+ rc = dev->change_protocol(dev, &rc_type);
+ if (rc < 0)
+ goto out_raw;
+- dev->enabled_protocols = rc_type;
++ dev->enabled_protocols[RC_FILTER_NORMAL] = rc_type;
+ }
+
+ mutex_unlock(&dev->lock);
+--- a/drivers/media/rc/redrat3.c
++++ b/drivers/media/rc/redrat3.c
+@@ -922,7 +922,7 @@ static struct rc_dev *redrat3_init_rc_de
+ rc->dev.parent = dev;
+ rc->priv = rr3;
+ rc->driver_type = RC_DRIVER_IR_RAW;
+- rc->allowed_protos = RC_BIT_ALL;
++ rc_set_allowed_protocols(rc, RC_BIT_ALL);
+ rc->timeout = US_TO_NS(2750);
+ rc->tx_ir = redrat3_transmit_ir;
+ rc->s_tx_carrier = redrat3_set_tx_carrier;
+--- a/drivers/media/rc/st_rc.c
++++ b/drivers/media/rc/st_rc.c
+@@ -287,7 +287,7 @@ static int st_rc_probe(struct platform_d
+ st_rc_hardware_init(rc_dev);
+
+ rdev->driver_type = RC_DRIVER_IR_RAW;
+- rdev->allowed_protos = RC_BIT_ALL;
++ rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+ /* rx sampling rate is 10Mhz */
+ rdev->rx_resolution = 100;
+ rdev->timeout = US_TO_NS(MAX_SYMB_TIME);
+--- a/drivers/media/rc/streamzap.c
++++ b/drivers/media/rc/streamzap.c
+@@ -322,7 +322,7 @@ static struct rc_dev *streamzap_init_rc_
+ rdev->dev.parent = dev;
+ rdev->priv = sz;
+ rdev->driver_type = RC_DRIVER_IR_RAW;
+- rdev->allowed_protos = RC_BIT_ALL;
++ rc_set_allowed_protocols(rdev, RC_BIT_ALL);
+ rdev->driver_name = DRIVER_NAME;
+ rdev->map_name = RC_MAP_STREAMZAP;
+
+--- a/drivers/media/rc/ttusbir.c
++++ b/drivers/media/rc/ttusbir.c
+@@ -318,7 +318,7 @@ static int ttusbir_probe(struct usb_inte
+ usb_to_input_id(tt->udev, &rc->input_id);
+ rc->dev.parent = &intf->dev;
+ rc->driver_type = RC_DRIVER_IR_RAW;
+- rc->allowed_protos = RC_BIT_ALL;
++ rc_set_allowed_protocols(rc, RC_BIT_ALL);
+ rc->priv = tt;
+ rc->driver_name = DRIVER_NAME;
+ rc->map_name = RC_MAP_TT_1500;
+--- a/drivers/media/rc/winbond-cir.c
++++ b/drivers/media/rc/winbond-cir.c
+@@ -1082,7 +1082,7 @@ wbcir_probe(struct pnp_dev *device, cons
+ data->dev->dev.parent = &device->dev;
+ data->dev->timeout = MS_TO_NS(100);
+ data->dev->rx_resolution = US_TO_NS(2);
+- data->dev->allowed_protos = RC_BIT_ALL;
++ rc_set_allowed_protocols(data->dev, RC_BIT_ALL);
+
+ err = rc_register_device(data->dev);
+ if (err)
+--- a/drivers/media/usb/dvb-usb/dvb-usb-remote.c
++++ b/drivers/media/usb/dvb-usb/dvb-usb-remote.c
+@@ -272,7 +272,7 @@ static int rc_core_dvb_usb_remote_init(s
+ dev->driver_name = d->props.rc.core.module_name;
+ dev->map_name = d->props.rc.core.rc_codes;
+ dev->change_protocol = d->props.rc.core.change_protocol;
+- dev->allowed_protos = d->props.rc.core.allowed_protos;
++ rc_set_allowed_protocols(dev, d->props.rc.core.allowed_protos);
+ dev->driver_type = d->props.rc.core.driver_type;
+ usb_to_input_id(d->udev, &dev->input_id);
+ dev->input_name = "IR-receiver inside an USB DVB receiver";
+--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
++++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+@@ -164,7 +164,7 @@ static int dvb_usbv2_remote_init(struct
+ dev->driver_name = (char *) d->props->driver_name;
+ dev->map_name = d->rc.map_name;
+ dev->driver_type = d->rc.driver_type;
+- dev->allowed_protos = d->rc.allowed_protos;
++ rc_set_allowed_protocols(dev, d->rc.allowed_protos);
+ dev->change_protocol = d->rc.change_protocol;
+ dev->priv = d;
+
+--- a/drivers/media/usb/em28xx/em28xx-input.c
++++ b/drivers/media/usb/em28xx/em28xx-input.c
+@@ -725,7 +725,7 @@ static int em28xx_ir_init(struct em28xx
+ case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2:
+ rc->map_name = RC_MAP_HAUPPAUGE;
+ ir->get_key_i2c = em28xx_get_key_em_haup;
+- rc->allowed_protos = RC_BIT_RC5;
++ rc_set_allowed_protocols(rc, RC_BIT_RC5);
+ break;
+ case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE:
+ rc->map_name = RC_MAP_WINFAST_USBII_DELUXE;
+@@ -741,7 +741,7 @@ static int em28xx_ir_init(struct em28xx
+ switch (dev->chip_id) {
+ case CHIP_ID_EM2860:
+ case CHIP_ID_EM2883:
+- rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC;
++ rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC);
+ ir->get_key = default_polling_getkey;
+ break;
+ case CHIP_ID_EM2884:
+@@ -749,8 +749,8 @@ static int em28xx_ir_init(struct em28xx
+ case CHIP_ID_EM28174:
+ case CHIP_ID_EM28178:
+ ir->get_key = em2874_polling_getkey;
+- rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC |
+- RC_BIT_RC6_0;
++ rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC |
++ RC_BIT_RC6_0);
+ break;
+ default:
+ err = -ENODEV;
+--- a/drivers/media/usb/tm6000/tm6000-input.c
++++ b/drivers/media/usb/tm6000/tm6000-input.c
+@@ -422,7 +422,7 @@ int tm6000_ir_init(struct tm6000_core *d
+ ir->rc = rc;
+
+ /* input setup */
+- rc->allowed_protos = RC_BIT_RC5 | RC_BIT_NEC;
++ rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC);
+ /* Neded, in order to support NEC remotes with 24 or 32 bits */
+ rc->scanmask = 0xffff;
+ rc->priv = ir;
+--- a/include/media/rc-core.h
++++ b/include/media/rc-core.h
+@@ -35,6 +35,29 @@ enum rc_driver_type {
+ };
+
+ /**
++ * struct rc_scancode_filter - Filter scan codes.
++ * @data: Scancode data to match.
++ * @mask: Mask of bits of scancode to compare.
++ */
++struct rc_scancode_filter {
++ u32 data;
++ u32 mask;
++};
++
++/**
++ * enum rc_filter_type - Filter type constants.
++ * @RC_FILTER_NORMAL: Filter for normal operation.
++ * @RC_FILTER_WAKEUP: Filter for waking from suspend.
++ * @RC_FILTER_MAX: Number of filter types.
++ */
++enum rc_filter_type {
++ RC_FILTER_NORMAL = 0,
++ RC_FILTER_WAKEUP,
++
++ RC_FILTER_MAX
++};
++
++/**
+ * struct rc_dev - represents a remote control device
+ * @dev: driver model's view of this device
+ * @input_name: name of the input child device
+@@ -50,8 +73,10 @@ enum rc_driver_type {
+ * @input_dev: the input child device used to communicate events to userspace
+ * @driver_type: specifies if protocol decoding is done in hardware or software
+ * @idle: used to keep track of RX state
+- * @allowed_protos: bitmask with the supported RC_BIT_* protocols
+- * @enabled_protocols: bitmask with the enabled RC_BIT_* protocols
++ * @allowed_protocols: bitmask with the supported RC_BIT_* protocols for each
++ * filter type
++ * @enabled_protocols: bitmask with the enabled RC_BIT_* protocols for each
++ * filter type
+ * @scanmask: some hardware decoders are not capable of providing the full
+ * scancode to the application. As this is a hardware limit, we can't do
+ * anything with it. Yet, as the same keycode table can be used with other
+@@ -70,7 +95,10 @@ enum rc_driver_type {
+ * @max_timeout: maximum timeout supported by device
+ * @rx_resolution : resolution (in ns) of input sampler
+ * @tx_resolution: resolution (in ns) of output sampler
++ * @scancode_filters: scancode filters (indexed by enum rc_filter_type)
+ * @change_protocol: allow changing the protocol used on hardware decoders
++ * @change_wakeup_protocol: allow changing the protocol used for wakeup
++ * filtering
+ * @open: callback to allow drivers to enable polling/irq when IR input device
+ * is opened.
+ * @close: callback to allow drivers to disable polling/irq when IR input device
+@@ -84,6 +112,7 @@ enum rc_driver_type {
+ * device doesn't interrupt host until it sees IR pulses
+ * @s_learning_mode: enable wide band receiver used for learning
+ * @s_carrier_report: enable carrier reports
++ * @s_filter: set the scancode filter of a given type
+ */
+ struct rc_dev {
+ struct device dev;
+@@ -99,8 +128,8 @@ struct rc_dev {
+ struct input_dev *input_dev;
+ enum rc_driver_type driver_type;
+ bool idle;
+- u64 allowed_protos;
+- u64 enabled_protocols;
++ u64 allowed_protocols[RC_FILTER_MAX];
++ u64 enabled_protocols[RC_FILTER_MAX];
+ u32 users;
+ u32 scanmask;
+ void *priv;
+@@ -116,7 +145,9 @@ struct rc_dev {
+ u32 max_timeout;
+ u32 rx_resolution;
+ u32 tx_resolution;
++ struct rc_scancode_filter scancode_filters[RC_FILTER_MAX];
+ int (*change_protocol)(struct rc_dev *dev, u64 *rc_type);
++ int (*change_wakeup_protocol)(struct rc_dev *dev, u64 *rc_type);
+ int (*open)(struct rc_dev *dev);
+ void (*close)(struct rc_dev *dev);
+ int (*s_tx_mask)(struct rc_dev *dev, u32 mask);
+@@ -127,10 +158,49 @@ struct rc_dev {
+ void (*s_idle)(struct rc_dev *dev, bool enable);
+ int (*s_learning_mode)(struct rc_dev *dev, int enable);
+ int (*s_carrier_report) (struct rc_dev *dev, int enable);
++ int (*s_filter)(struct rc_dev *dev,
++ enum rc_filter_type type,
++ struct rc_scancode_filter *filter);
+ };
+
+ #define to_rc_dev(d) container_of(d, struct rc_dev, dev)
+
++static inline bool rc_protocols_allowed(struct rc_dev *rdev, u64 protos)
++{
++ return rdev->allowed_protocols[RC_FILTER_NORMAL] & protos;
++}
++
++/* should be called prior to registration or with mutex held */
++static inline void rc_set_allowed_protocols(struct rc_dev *rdev, u64 protos)
++{
++ rdev->allowed_protocols[RC_FILTER_NORMAL] = protos;
++}
++
++static inline bool rc_protocols_enabled(struct rc_dev *rdev, u64 protos)
++{
++ return rdev->enabled_protocols[RC_FILTER_NORMAL] & protos;
++}
++
++/* should be called prior to registration or with mutex held */
++static inline void rc_set_enabled_protocols(struct rc_dev *rdev, u64 protos)
++{
++ rdev->enabled_protocols[RC_FILTER_NORMAL] = protos;
++}
++
++/* should be called prior to registration or with mutex held */
++static inline void rc_set_allowed_wakeup_protocols(struct rc_dev *rdev,
++ u64 protos)
++{
++ rdev->allowed_protocols[RC_FILTER_WAKEUP] = protos;
++}
++
++/* should be called prior to registration or with mutex held */
++static inline void rc_set_enabled_wakeup_protocols(struct rc_dev *rdev,
++ u64 protos)
++{
++ rdev->enabled_protocols[RC_FILTER_WAKEUP] = protos;
++}
++
+ /*
+ * From rc-main.c
+ * Those functions can be used on any type of Remote Controller. They