summaryrefslogtreecommitdiff
path: root/target/linux/mediatek/patches-4.9/0024-media-rc-add-driver-for-IR-remote-receiver-on-MT7623.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/mediatek/patches-4.9/0024-media-rc-add-driver-for-IR-remote-receiver-on-MT7623.patch')
-rw-r--r--target/linux/mediatek/patches-4.9/0024-media-rc-add-driver-for-IR-remote-receiver-on-MT7623.patch1034
1 files changed, 1034 insertions, 0 deletions
diff --git a/target/linux/mediatek/patches-4.9/0024-media-rc-add-driver-for-IR-remote-receiver-on-MT7623.patch b/target/linux/mediatek/patches-4.9/0024-media-rc-add-driver-for-IR-remote-receiver-on-MT7623.patch
new file mode 100644
index 0000000..fbdfbe9
--- /dev/null
+++ b/target/linux/mediatek/patches-4.9/0024-media-rc-add-driver-for-IR-remote-receiver-on-MT7623.patch
@@ -0,0 +1,1034 @@
+From 6e0336d1660725c06b6ab4f5361873538dbaa9f9 Mon Sep 17 00:00:00 2001
+From: Sean Wang <sean.wang@mediatek.com>
+Date: Fri, 13 Jan 2017 15:35:39 +0800
+Subject: [PATCH 24/57] media: rc: add driver for IR remote receiver on MT7623
+ SoC
+
+This patch adds driver for IR controller on MT7623 SoC.
+and should also work on similar Mediatek SoC. Currently
+testing successfully on NEC and SONY remote controller
+only but it should work on others (lirc, rc-5 and rc-6).
+
+Signed-off-by: Sean Wang <sean.wang@mediatek.com>
+Reviewed-by: Sean Young <sean@mess.org>
+---
+ drivers/media/rc/Kconfig | 11 ++
+ drivers/media/rc/mtk-cir.c | 329 +++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 340 insertions(+)
+ create mode 100644 drivers/media/rc/mtk-cir.c
+
+--- a/drivers/media/rc/Kconfig
++++ b/drivers/media/rc/Kconfig
+@@ -235,6 +235,17 @@ config IR_MESON
+ To compile this driver as a module, choose M here: the
+ module will be called meson-ir.
+
++config IR_MTK
++ tristate "Mediatek IR remote receiver"
++ depends on RC_CORE
++ depends on ARCH_MEDIATEK || COMPILE_TEST
++ ---help---
++ Say Y if you want to use the IR remote receiver available
++ on Mediatek SoCs.
++
++ To compile this driver as a module, choose M here: the
++ module will be called mtk-cir.
++
+ config IR_NUVOTON
+ tristate "Nuvoton w836x7hg Consumer Infrared Transceiver"
+ depends on PNP
+--- /dev/null
++++ b/drivers/media/rc/mtk-cir.c
+@@ -0,0 +1,329 @@
++/*
++ * Driver for Mediatek IR Receiver Controller
++ *
++ * Copyright (C) 2017 Sean Wang <sean.wang@mediatek.com>
++ *
++ * 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.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/clk.h>
++#include <linux/interrupt.h>
++#include <linux/module.h>
++#include <linux/of_platform.h>
++#include <linux/reset.h>
++#include <media/rc-core.h>
++
++#define MTK_IR_DEV KBUILD_MODNAME
++
++/* Register to enable PWM and IR */
++#define MTK_CONFIG_HIGH_REG 0x0c
++/* Enable IR pulse width detection */
++#define MTK_PWM_EN BIT(13)
++/* Enable IR hardware function */
++#define MTK_IR_EN BIT(0)
++
++/* Register to setting sample period */
++#define MTK_CONFIG_LOW_REG 0x10
++/* Field to set sample period */
++#define CHK_PERIOD DIV_ROUND_CLOSEST(MTK_IR_SAMPLE, \
++ MTK_IR_CLK_PERIOD)
++#define MTK_CHK_PERIOD (((CHK_PERIOD) << 8) & (GENMASK(20, 8)))
++#define MTK_CHK_PERIOD_MASK (GENMASK(20, 8))
++
++/* Register to clear state of state machine */
++#define MTK_IRCLR_REG 0x20
++/* Bit to restart IR receiving */
++#define MTK_IRCLR BIT(0)
++
++/* Register containing pulse width data */
++#define MTK_CHKDATA_REG(i) (0x88 + 4 * (i))
++#define MTK_WIDTH_MASK (GENMASK(7, 0))
++
++/* Register to enable IR interrupt */
++#define MTK_IRINT_EN_REG 0xcc
++/* Bit to enable interrupt */
++#define MTK_IRINT_EN BIT(0)
++
++/* Register to ack IR interrupt */
++#define MTK_IRINT_CLR_REG 0xd0
++/* Bit to clear interrupt status */
++#define MTK_IRINT_CLR BIT(0)
++
++/* Maximum count of samples */
++#define MTK_MAX_SAMPLES 0xff
++/* Indicate the end of IR message */
++#define MTK_IR_END(v, p) ((v) == MTK_MAX_SAMPLES && (p) == 0)
++/* Number of registers to record the pulse width */
++#define MTK_CHKDATA_SZ 17
++/* Source clock frequency */
++#define MTK_IR_BASE_CLK 273000000
++/* Frequency after IR internal divider */
++#define MTK_IR_CLK_FREQ (MTK_IR_BASE_CLK / 4)
++/* Period for MTK_IR_CLK in ns*/
++#define MTK_IR_CLK_PERIOD DIV_ROUND_CLOSEST(1000000000ul, \
++ MTK_IR_CLK_FREQ)
++/* Sample period in ns */
++#define MTK_IR_SAMPLE (MTK_IR_CLK_PERIOD * 0xc00)
++
++/* struct mtk_ir - This is the main datasructure for holding the state
++ * of the driver
++ * @dev: The device pointer
++ * @rc: The rc instrance
++ * @irq: The IRQ that we are using
++ * @base: The mapped register i/o base
++ * @clk: The clock that we are using
++ */
++struct mtk_ir {
++ struct device *dev;
++ struct rc_dev *rc;
++ void __iomem *base;
++ int irq;
++ struct clk *clk;
++};
++
++static void mtk_w32_mask(struct mtk_ir *ir, u32 val, u32 mask, unsigned int reg)
++{
++ u32 tmp;
++
++ tmp = __raw_readl(ir->base + reg);
++ tmp = (tmp & ~mask) | val;
++ __raw_writel(tmp, ir->base + reg);
++}
++
++static void mtk_w32(struct mtk_ir *ir, u32 val, unsigned int reg)
++{
++ __raw_writel(val, ir->base + reg);
++}
++
++static u32 mtk_r32(struct mtk_ir *ir, unsigned int reg)
++{
++ return __raw_readl(ir->base + reg);
++}
++
++static inline void mtk_irq_disable(struct mtk_ir *ir, u32 mask)
++{
++ u32 val;
++
++ val = mtk_r32(ir, MTK_IRINT_EN_REG);
++ mtk_w32(ir, val & ~mask, MTK_IRINT_EN_REG);
++}
++
++static inline void mtk_irq_enable(struct mtk_ir *ir, u32 mask)
++{
++ u32 val;
++
++ val = mtk_r32(ir, MTK_IRINT_EN_REG);
++ mtk_w32(ir, val | mask, MTK_IRINT_EN_REG);
++}
++
++static irqreturn_t mtk_ir_irq(int irqno, void *dev_id)
++{
++ struct mtk_ir *ir = dev_id;
++ u8 wid = 0;
++ u32 i, j, val;
++ DEFINE_IR_RAW_EVENT(rawir);
++
++ /* Reset decoder state machine explicitly is required
++ * because 1) the longest duration for space MTK IR hardware
++ * could record is not safely long. e.g 12ms if rx resolution
++ * is 46us by default. There is still the risk to satisfying
++ * every decoder to reset themselves through long enough
++ * trailing spaces and 2) the IRQ handler guarantees that
++ * start of IR message is always contained in and starting
++ * from register MTK_CHKDATA_REG(0).
++ */
++ ir_raw_event_reset(ir->rc);
++
++ /* First message must be pulse */
++ rawir.pulse = false;
++
++ /* Handle all pulse and space IR controller captures */
++ for (i = 0 ; i < MTK_CHKDATA_SZ ; i++) {
++ val = mtk_r32(ir, MTK_CHKDATA_REG(i));
++ dev_dbg(ir->dev, "@reg%d=0x%08x\n", i, val);
++
++ for (j = 0 ; j < 4 ; j++) {
++ wid = (val & (MTK_WIDTH_MASK << j * 8)) >> j * 8;
++ rawir.pulse = !rawir.pulse;
++ rawir.duration = wid * (MTK_IR_SAMPLE + 1);
++ ir_raw_event_store_with_filter(ir->rc, &rawir);
++ }
++ }
++
++ /* The maximum number of edges the IR controller can
++ * hold is MTK_CHKDATA_SZ * 4. So if received IR messages
++ * is over the limit, the last incomplete IR message would
++ * be appended trailing space and still would be sent into
++ * ir-rc-raw to decode. That helps it is possible that it
++ * has enough information to decode a scancode even if the
++ * trailing end of the message is missing.
++ */
++ if (!MTK_IR_END(wid, rawir.pulse)) {
++ rawir.pulse = false;
++ rawir.duration = MTK_MAX_SAMPLES * (MTK_IR_SAMPLE + 1);
++ ir_raw_event_store_with_filter(ir->rc, &rawir);
++ }
++
++ ir_raw_event_handle(ir->rc);
++
++ /* Restart controller for the next receive that would
++ * clear up all CHKDATA registers
++ */
++ mtk_w32_mask(ir, 0x1, MTK_IRCLR, MTK_IRCLR_REG);
++
++ /* Clear interrupt status */
++ mtk_w32_mask(ir, 0x1, MTK_IRINT_CLR, MTK_IRINT_CLR_REG);
++
++ return IRQ_HANDLED;
++}
++
++static int mtk_ir_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct device_node *dn = dev->of_node;
++ struct resource *res;
++ struct mtk_ir *ir;
++ u32 val;
++ int ret = 0;
++ const char *map_name;
++
++ ir = devm_kzalloc(dev, sizeof(struct mtk_ir), GFP_KERNEL);
++ if (!ir)
++ return -ENOMEM;
++
++ ir->dev = dev;
++
++ if (!of_device_is_compatible(dn, "mediatek,mt7623-cir"))
++ return -ENODEV;
++
++ ir->clk = devm_clk_get(dev, "clk");
++ if (IS_ERR(ir->clk)) {
++ dev_err(dev, "failed to get a ir clock.\n");
++ return PTR_ERR(ir->clk);
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ ir->base = devm_ioremap_resource(dev, res);
++ if (IS_ERR(ir->base)) {
++ dev_err(dev, "failed to map registers\n");
++ return PTR_ERR(ir->base);
++ }
++
++ ir->rc = devm_rc_allocate_device(dev, RC_DRIVER_IR_RAW);
++ if (!ir->rc) {
++ dev_err(dev, "failed to allocate device\n");
++ return -ENOMEM;
++ }
++
++ ir->rc->priv = ir;
++ ir->rc->input_name = MTK_IR_DEV;
++ ir->rc->input_phys = MTK_IR_DEV "/input0";
++ ir->rc->input_id.bustype = BUS_HOST;
++ ir->rc->input_id.vendor = 0x0001;
++ ir->rc->input_id.product = 0x0001;
++ ir->rc->input_id.version = 0x0001;
++ map_name = of_get_property(dn, "linux,rc-map-name", NULL);
++ ir->rc->map_name = map_name ?: RC_MAP_EMPTY;
++ ir->rc->dev.parent = dev;
++ ir->rc->driver_name = MTK_IR_DEV;
++ ir->rc->allowed_protocols = RC_BIT_ALL;
++ ir->rc->rx_resolution = MTK_IR_SAMPLE;
++ ir->rc->timeout = MTK_MAX_SAMPLES * (MTK_IR_SAMPLE + 1);
++
++ ret = devm_rc_register_device(dev, ir->rc);
++ if (ret) {
++ dev_err(dev, "failed to register rc device\n");
++ return ret;
++ }
++
++ platform_set_drvdata(pdev, ir);
++
++ ir->irq = platform_get_irq(pdev, 0);
++ if (ir->irq < 0) {
++ dev_err(dev, "no irq resource\n");
++ return -ENODEV;
++ }
++
++ /* Enable interrupt after proper hardware
++ * setup and IRQ handler registration
++ */
++ if (clk_prepare_enable(ir->clk)) {
++ dev_err(dev, "try to enable ir_clk failed\n");
++ ret = -EINVAL;
++ goto exit_clkdisable_clk;
++ }
++
++ mtk_irq_disable(ir, MTK_IRINT_EN);
++
++ ret = devm_request_irq(dev, ir->irq, mtk_ir_irq, 0, MTK_IR_DEV, ir);
++ if (ret) {
++ dev_err(dev, "failed request irq\n");
++ goto exit_clkdisable_clk;
++ }
++
++ /* Enable IR and PWM */
++ val = mtk_r32(ir, MTK_CONFIG_HIGH_REG);
++ val |= MTK_PWM_EN | MTK_IR_EN;
++ mtk_w32(ir, val, MTK_CONFIG_HIGH_REG);
++
++ /* Setting sample period */
++ mtk_w32_mask(ir, MTK_CHK_PERIOD, MTK_CHK_PERIOD_MASK,
++ MTK_CONFIG_LOW_REG);
++
++ mtk_irq_enable(ir, MTK_IRINT_EN);
++
++ dev_info(dev, "Initialized MT7623 IR driver, sample period = %luus\n",
++ DIV_ROUND_CLOSEST(MTK_IR_SAMPLE, 1000));
++
++ return 0;
++
++exit_clkdisable_clk:
++ clk_disable_unprepare(ir->clk);
++
++ return ret;
++}
++
++static int mtk_ir_remove(struct platform_device *pdev)
++{
++ struct mtk_ir *ir = platform_get_drvdata(pdev);
++
++ /* Avoid contention between remove handler and
++ * IRQ handler so that disabling IR interrupt and
++ * waiting for pending IRQ handler to complete
++ */
++ mtk_irq_disable(ir, MTK_IRINT_EN);
++ synchronize_irq(ir->irq);
++
++ clk_disable_unprepare(ir->clk);
++
++ return 0;
++}
++
++static const struct of_device_id mtk_ir_match[] = {
++ { .compatible = "mediatek,mt7623-cir" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, mtk_ir_match);
++
++static struct platform_driver mtk_ir_driver = {
++ .probe = mtk_ir_probe,
++ .remove = mtk_ir_remove,
++ .driver = {
++ .name = MTK_IR_DEV,
++ .of_match_table = mtk_ir_match,
++ },
++};
++
++module_platform_driver(mtk_ir_driver);
++
++MODULE_DESCRIPTION("Mediatek IR Receiver Controller Driver");
++MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
++MODULE_LICENSE("GPL");
+--- a/drivers/media/rc/Makefile
++++ b/drivers/media/rc/Makefile
+@@ -37,3 +37,4 @@ obj-$(CONFIG_IR_TTUSBIR) += ttusbir.o
+ obj-$(CONFIG_RC_ST) += st_rc.o
+ obj-$(CONFIG_IR_SUNXI) += sunxi-cir.o
+ obj-$(CONFIG_IR_IMG) += img-ir/
++obj-$(CONFIG_IR_MTK) += mtk-cir.o
+--- a/drivers/media/rc/rc-main.c
++++ b/drivers/media/rc/rc-main.c
+@@ -1355,7 +1355,7 @@ static struct device_type rc_dev_type =
+ .uevent = rc_dev_uevent,
+ };
+
+-struct rc_dev *rc_allocate_device(void)
++struct rc_dev *rc_allocate_device(enum rc_driver_type type)
+ {
+ struct rc_dev *dev;
+
+@@ -1382,6 +1382,8 @@ struct rc_dev *rc_allocate_device(void)
+ dev->dev.class = &rc_class;
+ device_initialize(&dev->dev);
+
++ dev->driver_type = type;
++
+ __module_get(THIS_MODULE);
+ return dev;
+ }
+@@ -1403,6 +1405,35 @@ void rc_free_device(struct rc_dev *dev)
+ }
+ EXPORT_SYMBOL_GPL(rc_free_device);
+
++static void devm_rc_alloc_release(struct device *dev, void *res)
++{
++ rc_free_device(*(struct rc_dev **)res);
++}
++
++struct rc_dev *devm_rc_allocate_device(struct device *dev,
++ enum rc_driver_type type)
++{
++ struct rc_dev **dr, *rc;
++
++ dr = devres_alloc(devm_rc_alloc_release, sizeof(*dr), GFP_KERNEL);
++ if (!dr)
++ return NULL;
++
++ rc = rc_allocate_device(type);
++ if (!rc) {
++ devres_free(dr);
++ return NULL;
++ }
++
++ rc->dev.parent = dev;
++ rc->managed_alloc = true;
++ *dr = rc;
++ devres_add(dev, dr);
++
++ return rc;
++}
++EXPORT_SYMBOL_GPL(devm_rc_allocate_device);
++
+ int rc_register_device(struct rc_dev *dev)
+ {
+ static bool raw_init = false; /* raw decoders loaded? */
+@@ -1536,6 +1567,33 @@ out_unlock:
+ }
+ EXPORT_SYMBOL_GPL(rc_register_device);
+
++static void devm_rc_release(struct device *dev, void *res)
++{
++ rc_unregister_device(*(struct rc_dev **)res);
++}
++
++int devm_rc_register_device(struct device *parent, struct rc_dev *dev)
++{
++ struct rc_dev **dr;
++ int ret;
++
++ dr = devres_alloc(devm_rc_release, sizeof(*dr), GFP_KERNEL);
++ if (!dr)
++ return -ENOMEM;
++
++ ret = rc_register_device(dev);
++ if (ret) {
++ devres_free(dr);
++ return ret;
++ }
++
++ *dr = dev;
++ devres_add(parent, dr);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(devm_rc_register_device);
++
+ void rc_unregister_device(struct rc_dev *dev)
+ {
+ if (!dev)
+@@ -1557,7 +1615,8 @@ void rc_unregister_device(struct rc_dev
+
+ ida_simple_remove(&rc_ida, dev->minor);
+
+- rc_free_device(dev);
++ if (!dev->managed_alloc)
++ rc_free_device(dev);
+ }
+
+ EXPORT_SYMBOL_GPL(rc_unregister_device);
+--- a/include/media/rc-core.h
++++ b/include/media/rc-core.h
+@@ -68,6 +68,7 @@ enum rc_filter_type {
+ * struct rc_dev - represents a remote control device
+ * @dev: driver model's view of this device
+ * @initialized: 1 if the device init has completed, 0 otherwise
++ * @managed_alloc: devm_rc_allocate_device was used to create rc_dev
+ * @sysfs_groups: sysfs attribute groups
+ * @input_name: name of the input child device
+ * @input_phys: physical path to the input child device
+@@ -131,6 +132,7 @@ enum rc_filter_type {
+ struct rc_dev {
+ struct device dev;
+ atomic_t initialized;
++ bool managed_alloc;
+ const struct attribute_group *sysfs_groups[5];
+ const char *input_name;
+ const char *input_phys;
+@@ -198,9 +200,19 @@ struct rc_dev {
+ /**
+ * rc_allocate_device - Allocates a RC device
+ *
++ * @rc_driver_type: specifies the type of the RC output to be allocated
+ * returns a pointer to struct rc_dev.
+ */
+-struct rc_dev *rc_allocate_device(void);
++struct rc_dev *rc_allocate_device(enum rc_driver_type);
++
++/**
++ * devm_rc_allocate_device - Managed RC device allocation
++ *
++ * @dev: pointer to struct device
++ * @rc_driver_type: specifies the type of the RC output to be allocated
++ * returns a pointer to struct rc_dev.
++ */
++struct rc_dev *devm_rc_allocate_device(struct device *dev, enum rc_driver_type);
+
+ /**
+ * rc_free_device - Frees a RC device
+@@ -217,6 +229,14 @@ void rc_free_device(struct rc_dev *dev);
+ int rc_register_device(struct rc_dev *dev);
+
+ /**
++ * devm_rc_register_device - Manageded registering of a RC device
++ *
++ * @parent: pointer to struct device.
++ * @dev: pointer to struct rc_dev.
++ */
++int devm_rc_register_device(struct device *parent, struct rc_dev *dev);
++
++/**
+ * rc_unregister_device - Unregisters a RC device
+ *
+ * @dev: pointer to struct rc_dev.
+--- a/drivers/media/common/siano/smsir.c
++++ b/drivers/media/common/siano/smsir.c
+@@ -58,7 +58,7 @@ int sms_ir_init(struct smscore_device_t
+ struct rc_dev *dev;
+
+ pr_debug("Allocating rc device\n");
+- dev = rc_allocate_device();
++ dev = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!dev)
+ return -ENOMEM;
+
+--- a/drivers/media/i2c/ir-kbd-i2c.c
++++ b/drivers/media/i2c/ir-kbd-i2c.c
+@@ -428,7 +428,7 @@ static int ir_probe(struct i2c_client *c
+ * If platform_data doesn't specify rc_dev, initialize it
+ * internally
+ */
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!rc)
+ return -ENOMEM;
+ }
+--- a/drivers/media/pci/bt8xx/bttv-input.c
++++ b/drivers/media/pci/bt8xx/bttv-input.c
+@@ -424,7 +424,7 @@ int bttv_input_init(struct bttv *btv)
+ return -ENODEV;
+
+ ir = kzalloc(sizeof(*ir),GFP_KERNEL);
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!ir || !rc)
+ goto err_out_free;
+
+--- a/drivers/media/pci/cx23885/cx23885-input.c
++++ b/drivers/media/pci/cx23885/cx23885-input.c
+@@ -267,7 +267,6 @@ int cx23885_input_init(struct cx23885_de
+ struct cx23885_kernel_ir *kernel_ir;
+ struct rc_dev *rc;
+ char *rc_map;
+- enum rc_driver_type driver_type;
+ u64 allowed_protos;
+
+ int ret;
+@@ -352,7 +351,7 @@ int cx23885_input_init(struct cx23885_de
+ pci_name(dev->pci));
+
+ /* input device */
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!rc) {
+ ret = -ENOMEM;
+ goto err_out_free;
+@@ -371,7 +370,6 @@ int cx23885_input_init(struct cx23885_de
+ rc->input_id.product = dev->pci->device;
+ }
+ rc->dev.parent = &dev->pci->dev;
+- rc->driver_type = driver_type;
+ rc->allowed_protocols = allowed_protos;
+ rc->priv = kernel_ir;
+ rc->open = cx23885_input_ir_open;
+--- a/drivers/media/pci/cx88/cx88-input.c
++++ b/drivers/media/pci/cx88/cx88-input.c
+@@ -272,7 +272,7 @@ int cx88_ir_init(struct cx88_core *core,
+ */
+
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+- dev = rc_allocate_device();
++ dev = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!ir || !dev)
+ goto err_out_free;
+
+@@ -482,7 +482,6 @@ int cx88_ir_init(struct cx88_core *core,
+ dev->scancode_mask = hardware_mask;
+
+ if (ir->sampling) {
+- dev->driver_type = RC_DRIVER_IR_RAW;
+ dev->timeout = 10 * 1000 * 1000; /* 10 ms */
+ } else {
+ dev->driver_type = RC_DRIVER_SCANCODE;
+--- a/drivers/media/pci/dm1105/dm1105.c
++++ b/drivers/media/pci/dm1105/dm1105.c
+@@ -744,7 +744,7 @@ static int dm1105_ir_init(struct dm1105_
+ struct rc_dev *dev;
+ int err = -ENOMEM;
+
+- dev = rc_allocate_device();
++ dev = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!dev)
+ return -ENOMEM;
+
+@@ -753,7 +753,6 @@ static int dm1105_ir_init(struct dm1105_
+
+ dev->driver_name = MODULE_NAME;
+ dev->map_name = RC_MAP_DM1105_NEC;
+- dev->driver_type = RC_DRIVER_SCANCODE;
+ dev->input_name = "DVB on-card IR receiver";
+ dev->input_phys = dm1105->ir.input_phys;
+ dev->input_id.bustype = BUS_PCI;
+--- a/drivers/media/pci/mantis/mantis_input.c
++++ b/drivers/media/pci/mantis/mantis_input.c
+@@ -39,7 +39,7 @@ int mantis_input_init(struct mantis_pci
+ struct rc_dev *dev;
+ int err;
+
+- dev = rc_allocate_device();
++ dev = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!dev) {
+ dprintk(MANTIS_ERROR, 1, "Remote device allocation failed");
+ err = -ENOMEM;
+--- a/drivers/media/pci/saa7134/saa7134-input.c
++++ b/drivers/media/pci/saa7134/saa7134-input.c
+@@ -849,7 +849,7 @@ int saa7134_input_init1(struct saa7134_d
+ }
+
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!ir || !rc) {
+ err = -ENOMEM;
+ goto err_out_free;
+--- a/drivers/media/pci/smipcie/smipcie-ir.c
++++ b/drivers/media/pci/smipcie/smipcie-ir.c
+@@ -183,7 +183,7 @@ int smi_ir_init(struct smi_dev *dev)
+ struct rc_dev *rc_dev;
+ struct smi_rc *ir = &dev->ir;
+
+- rc_dev = rc_allocate_device();
++ rc_dev = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!rc_dev)
+ return -ENOMEM;
+
+@@ -202,7 +202,6 @@ int smi_ir_init(struct smi_dev *dev)
+ rc_dev->input_id.product = dev->pci_dev->subsystem_device;
+ rc_dev->dev.parent = &dev->pci_dev->dev;
+
+- rc_dev->driver_type = RC_DRIVER_SCANCODE;
+ rc_dev->map_name = dev->info->rc_map;
+
+ ir->rc_dev = rc_dev;
+--- a/drivers/media/pci/ttpci/budget-ci.c
++++ b/drivers/media/pci/ttpci/budget-ci.c
+@@ -177,7 +177,7 @@ static int msp430_ir_init(struct budget_
+ struct rc_dev *dev;
+ int error;
+
+- dev = rc_allocate_device();
++ dev = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!dev) {
+ printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");
+ return -ENOMEM;
+--- a/drivers/media/rc/ati_remote.c
++++ b/drivers/media/rc/ati_remote.c
+@@ -765,7 +765,6 @@ static void ati_remote_rc_init(struct at
+ struct rc_dev *rdev = ati_remote->rdev;
+
+ rdev->priv = ati_remote;
+- rdev->driver_type = RC_DRIVER_SCANCODE;
+ rdev->allowed_protocols = RC_BIT_OTHER;
+ rdev->driver_name = "ati_remote";
+
+@@ -852,7 +851,7 @@ static int ati_remote_probe(struct usb_i
+ }
+
+ ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL);
+- rc_dev = rc_allocate_device();
++ rc_dev = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!ati_remote || !rc_dev)
+ goto exit_free_dev_rdev;
+
+--- a/drivers/media/rc/ene_ir.c
++++ b/drivers/media/rc/ene_ir.c
+@@ -1012,7 +1012,7 @@ static int ene_probe(struct pnp_dev *pnp
+
+ /* allocate memory */
+ dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL);
+- rdev = rc_allocate_device();
++ rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!dev || !rdev)
+ goto exit_free_dev_rdev;
+
+--- a/drivers/media/rc/fintek-cir.c
++++ b/drivers/media/rc/fintek-cir.c
+@@ -496,7 +496,7 @@ static int fintek_probe(struct pnp_dev *
+ return ret;
+
+ /* input device for IR remote (and tx) */
+- rdev = rc_allocate_device();
++ rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!rdev)
+ goto exit_free_dev_rdev;
+
+--- a/drivers/media/rc/gpio-ir-recv.c
++++ b/drivers/media/rc/gpio-ir-recv.c
+@@ -143,14 +143,13 @@ static int gpio_ir_recv_probe(struct pla
+ if (!gpio_dev)
+ return -ENOMEM;
+
+- rcdev = rc_allocate_device();
++ rcdev = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!rcdev) {
+ rc = -ENOMEM;
+ goto err_allocate_device;
+ }
+
+ rcdev->priv = gpio_dev;
+- rcdev->driver_type = RC_DRIVER_IR_RAW;
+ rcdev->input_name = GPIO_IR_DEVICE_NAME;
+ rcdev->input_phys = GPIO_IR_DEVICE_NAME "/input0";
+ rcdev->input_id.bustype = BUS_HOST;
+--- a/drivers/media/rc/igorplugusb.c
++++ b/drivers/media/rc/igorplugusb.c
+@@ -190,7 +190,7 @@ static int igorplugusb_probe(struct usb_
+
+ usb_make_path(udev, ir->phys, sizeof(ir->phys));
+
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!rc)
+ goto fail;
+
+@@ -198,7 +198,6 @@ static int igorplugusb_probe(struct usb_
+ rc->input_phys = ir->phys;
+ usb_to_input_id(udev, &rc->input_id);
+ rc->dev.parent = &intf->dev;
+- rc->driver_type = RC_DRIVER_IR_RAW;
+ /*
+ * This device can only store 36 pulses + spaces, which is not enough
+ * for the NEC protocol and many others.
+--- a/drivers/media/rc/iguanair.c
++++ b/drivers/media/rc/iguanair.c
+@@ -431,7 +431,7 @@ static int iguanair_probe(struct usb_int
+ struct usb_host_interface *idesc;
+
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!ir || !rc) {
+ ret = -ENOMEM;
+ goto out;
+--- a/drivers/media/rc/img-ir/img-ir-hw.c
++++ b/drivers/media/rc/img-ir/img-ir-hw.c
+@@ -1071,7 +1071,7 @@ int img_ir_probe_hw(struct img_ir_priv *
+ }
+
+ /* Allocate hardware decoder */
+- hw->rdev = rdev = rc_allocate_device();
++ hw->rdev = rdev = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!rdev) {
+ dev_err(priv->dev, "cannot allocate input device\n");
+ error = -ENOMEM;
+--- a/drivers/media/rc/img-ir/img-ir-raw.c
++++ b/drivers/media/rc/img-ir/img-ir-raw.c
+@@ -110,7 +110,7 @@ int img_ir_probe_raw(struct img_ir_priv
+ setup_timer(&raw->timer, img_ir_echo_timer, (unsigned long)priv);
+
+ /* Allocate raw decoder */
+- raw->rdev = rdev = rc_allocate_device();
++ raw->rdev = rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!rdev) {
+ dev_err(priv->dev, "cannot allocate raw input device\n");
+ return -ENOMEM;
+@@ -118,7 +118,6 @@ int img_ir_probe_raw(struct img_ir_priv
+ rdev->priv = priv;
+ rdev->map_name = RC_MAP_EMPTY;
+ rdev->input_name = "IMG Infrared Decoder Raw";
+- rdev->driver_type = RC_DRIVER_IR_RAW;
+
+ /* Register raw decoder */
+ error = rc_register_device(rdev);
+--- a/drivers/media/rc/imon.c
++++ b/drivers/media/rc/imon.c
+@@ -1951,7 +1951,7 @@ static struct rc_dev *imon_init_rdev(str
+ const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x88 };
+
+- rdev = rc_allocate_device();
++ rdev = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!rdev) {
+ dev_err(ictx->dev, "remote control dev allocation failed\n");
+ goto out;
+@@ -1969,7 +1969,6 @@ static struct rc_dev *imon_init_rdev(str
+ rdev->dev.parent = ictx->dev;
+
+ rdev->priv = ictx;
+- rdev->driver_type = RC_DRIVER_SCANCODE;
+ rdev->allowed_protocols = RC_BIT_OTHER | RC_BIT_RC6_MCE; /* iMON PAD or MCE */
+ rdev->change_protocol = imon_ir_change_protocol;
+ rdev->driver_name = MOD_NAME;
+--- a/drivers/media/rc/ir-hix5hd2.c
++++ b/drivers/media/rc/ir-hix5hd2.c
+@@ -222,7 +222,7 @@ static int hix5hd2_ir_probe(struct platf
+ return priv->irq;
+ }
+
+- rdev = rc_allocate_device();
++ rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!rdev)
+ return -ENOMEM;
+
+--- a/drivers/media/rc/ite-cir.c
++++ b/drivers/media/rc/ite-cir.c
+@@ -1472,7 +1472,7 @@ static int ite_probe(struct pnp_dev *pde
+ return ret;
+
+ /* input device for IR remote (and tx) */
+- rdev = rc_allocate_device();
++ rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!rdev)
+ goto exit_free_dev_rdev;
+ itdev->rdev = rdev;
+--- a/drivers/media/rc/mceusb.c
++++ b/drivers/media/rc/mceusb.c
+@@ -1220,7 +1220,7 @@ static struct rc_dev *mceusb_init_rc_dev
+ struct rc_dev *rc;
+ int ret;
+
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!rc) {
+ dev_err(dev, "remote dev allocation failed");
+ goto out;
+--- a/drivers/media/rc/meson-ir.c
++++ b/drivers/media/rc/meson-ir.c
+@@ -131,7 +131,7 @@ static int meson_ir_probe(struct platfor
+ return ir->irq;
+ }
+
+- ir->rc = rc_allocate_device();
++ ir->rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!ir->rc) {
+ dev_err(dev, "failed to allocate rc device\n");
+ return -ENOMEM;
+--- a/drivers/media/rc/rc-loopback.c
++++ b/drivers/media/rc/rc-loopback.c
+@@ -181,7 +181,7 @@ static int __init loop_init(void)
+ struct rc_dev *rc;
+ int ret;
+
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!rc) {
+ printk(KERN_ERR DRIVER_NAME ": rc_dev allocation failed\n");
+ return -ENOMEM;
+--- a/drivers/media/rc/st_rc.c
++++ b/drivers/media/rc/st_rc.c
+@@ -235,7 +235,7 @@ static int st_rc_probe(struct platform_d
+ if (!rc_dev)
+ return -ENOMEM;
+
+- rdev = rc_allocate_device();
++ rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
+
+ if (!rdev)
+ return -ENOMEM;
+--- a/drivers/media/rc/streamzap.c
++++ b/drivers/media/rc/streamzap.c
+@@ -291,7 +291,7 @@ static struct rc_dev *streamzap_init_rc_
+ struct device *dev = sz->dev;
+ int ret;
+
+- rdev = rc_allocate_device();
++ rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!rdev) {
+ dev_err(dev, "remote dev allocation failed\n");
+ goto out;
+--- a/drivers/media/rc/sunxi-cir.c
++++ b/drivers/media/rc/sunxi-cir.c
+@@ -212,7 +212,7 @@ static int sunxi_ir_probe(struct platfor
+ goto exit_clkdisable_clk;
+ }
+
+- ir->rc = rc_allocate_device();
++ ir->rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!ir->rc) {
+ dev_err(dev, "failed to allocate device\n");
+ ret = -ENOMEM;
+--- a/drivers/media/rc/ttusbir.c
++++ b/drivers/media/rc/ttusbir.c
+@@ -205,7 +205,7 @@ static int ttusbir_probe(struct usb_inte
+ int altsetting = -1;
+
+ tt = kzalloc(sizeof(*tt), GFP_KERNEL);
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!tt || !rc) {
+ ret = -ENOMEM;
+ goto out;
+--- a/drivers/media/rc/winbond-cir.c
++++ b/drivers/media/rc/winbond-cir.c
+@@ -1062,13 +1062,12 @@ wbcir_probe(struct pnp_dev *device, cons
+ if (err)
+ goto exit_free_data;
+
+- data->dev = rc_allocate_device();
++ data->dev = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!data->dev) {
+ err = -ENOMEM;
+ goto exit_unregister_led;
+ }
+
+- data->dev->driver_type = RC_DRIVER_IR_RAW;
+ data->dev->driver_name = DRVNAME;
+ data->dev->input_name = WBCIR_NAME;
+ data->dev->input_phys = "wbcir/cir0";
+--- a/drivers/media/usb/au0828/au0828-input.c
++++ b/drivers/media/usb/au0828/au0828-input.c
+@@ -298,7 +298,7 @@ int au0828_rc_register(struct au0828_dev
+ return -ENODEV;
+
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+ if (!ir || !rc)
+ goto error;
+
+@@ -343,7 +343,6 @@ int au0828_rc_register(struct au0828_dev
+ rc->input_id.product = le16_to_cpu(dev->usbdev->descriptor.idProduct);
+ rc->dev.parent = &dev->usbdev->dev;
+ rc->driver_name = "au0828-input";
+- rc->driver_type = RC_DRIVER_IR_RAW;
+ rc->allowed_protocols = RC_BIT_NEC | RC_BIT_NECX | RC_BIT_NEC32 |
+ RC_BIT_RC5;
+
+--- a/drivers/media/usb/cx231xx/cx231xx-input.c
++++ b/drivers/media/usb/cx231xx/cx231xx-input.c
+@@ -72,7 +72,7 @@ int cx231xx_ir_init(struct cx231xx *dev)
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ memset(&dev->init_data, 0, sizeof(dev->init_data));
+- dev->init_data.rc_dev = rc_allocate_device();
++ dev->init_data.rc_dev = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!dev->init_data.rc_dev)
+ return -ENOMEM;
+
+--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
++++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+@@ -147,7 +147,7 @@ static int dvb_usbv2_remote_init(struct
+ if (!d->rc.map_name)
+ return 0;
+
+- dev = rc_allocate_device();
++ dev = rc_allocate_device(d->rc.driver_type);
+ if (!dev) {
+ ret = -ENOMEM;
+ goto err;
+@@ -162,7 +162,6 @@ static int dvb_usbv2_remote_init(struct
+ /* TODO: likely RC-core should took const char * */
+ dev->driver_name = (char *) d->props->driver_name;
+ dev->map_name = d->rc.map_name;
+- dev->driver_type = d->rc.driver_type;
+ dev->allowed_protocols = d->rc.allowed_protos;
+ dev->change_protocol = d->rc.change_protocol;
+ dev->priv = d;
+--- a/drivers/media/usb/dvb-usb/dvb-usb-remote.c
++++ b/drivers/media/usb/dvb-usb/dvb-usb-remote.c
+@@ -265,7 +265,7 @@ static int rc_core_dvb_usb_remote_init(s
+ int err, rc_interval;
+ struct rc_dev *dev;
+
+- dev = rc_allocate_device();
++ dev = rc_allocate_device(d->props.rc.core.driver_type);
+ if (!dev)
+ return -ENOMEM;
+
+@@ -273,7 +273,6 @@ static int rc_core_dvb_usb_remote_init(s
+ dev->map_name = d->props.rc.core.rc_codes;
+ dev->change_protocol = d->props.rc.core.change_protocol;
+ dev->allowed_protocols = 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";
+ dev->input_phys = d->rc_phys;
+--- a/drivers/media/usb/em28xx/em28xx-input.c
++++ b/drivers/media/usb/em28xx/em28xx-input.c
+@@ -713,7 +713,7 @@ static int em28xx_ir_init(struct em28xx
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+ if (!ir)
+ return -ENOMEM;
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!rc)
+ goto error;
+
+--- a/drivers/media/usb/tm6000/tm6000-input.c
++++ b/drivers/media/usb/tm6000/tm6000-input.c
+@@ -429,7 +429,7 @@ int tm6000_ir_init(struct tm6000_core *d
+ return 0;
+
+ ir = kzalloc(sizeof(*ir), GFP_ATOMIC);
+- rc = rc_allocate_device();
++ rc = rc_allocate_device(RC_DRIVER_SCANCODE);
+ if (!ir || !rc)
+ goto out;
+
+@@ -456,7 +456,6 @@ int tm6000_ir_init(struct tm6000_core *d
+ ir->polling = 50;
+ INIT_DELAYED_WORK(&ir->work, tm6000_ir_handle_key);
+ }
+- rc->driver_type = RC_DRIVER_SCANCODE;
+
+ snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)",
+ dev->name);