aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/rc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/rc')
-rw-r--r--drivers/media/rc/Kconfig17
-rw-r--r--drivers/media/rc/Makefile1
-rw-r--r--drivers/media/rc/ati_remote.c3
-rw-r--r--drivers/media/rc/ene_ir.c3
-rw-r--r--drivers/media/rc/fintek-cir.c6
-rw-r--r--drivers/media/rc/imon.c61
-rw-r--r--drivers/media/rc/ir-hix5hd2.c25
-rw-r--r--drivers/media/rc/ir-sanyo-decoder.c3
-rw-r--r--drivers/media/rc/ite-cir.c11
-rw-r--r--drivers/media/rc/lirc_dev.c29
-rw-r--r--drivers/media/rc/mceusb.c102
-rw-r--r--drivers/media/rc/meson-ir.c1
-rw-r--r--drivers/media/rc/nuvoton-cir.c143
-rw-r--r--drivers/media/rc/nuvoton-cir.h4
-rw-r--r--drivers/media/rc/rc-ir-raw.c17
-rw-r--r--drivers/media/rc/rc-main.c70
-rw-r--r--drivers/media/rc/redrat3.c327
-rw-r--r--drivers/media/rc/serial_ir.c844
-rw-r--r--drivers/media/rc/streamzap.c11
-rw-r--r--drivers/media/rc/winbond-cir.c13
20 files changed, 1284 insertions, 407 deletions
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index 370e16e07867..629e8ca15ab3 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -389,4 +389,21 @@ config IR_SUNXI
To compile this driver as a module, choose M here: the module will
be called sunxi-ir.
+config IR_SERIAL
+ tristate "Homebrew Serial Port Receiver"
+ depends on RC_CORE
+ ---help---
+ Say Y if you want to use Homebrew Serial Port Receivers and
+ Transceivers.
+
+ To compile this driver as a module, choose M here: the module will
+ be called serial-ir.
+
+config IR_SERIAL_TRANSMITTER
+ bool "Serial Port Transmitter"
+ default y
+ depends on IR_SERIAL
+ ---help---
+ Serial Port Transmitter support
+
endif #RC_DEVICES
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index 379a5c0f1379..3a984ee301e2 100644
--- 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_SERIAL) += serial_ir.o
diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c
index 9f5b59706741..0884b7dc0e71 100644
--- a/drivers/media/rc/ati_remote.c
+++ b/drivers/media/rc/ati_remote.c
@@ -527,8 +527,7 @@ static void ati_remote_input_report(struct urb *urb)
remote_num = (data[3] >> 4) & 0x0f;
if (channel_mask & (1 << (remote_num + 1))) {
dbginfo(&ati_remote->interface->dev,
- "Masked input from channel 0x%02x: data %02x, "
- "mask= 0x%02lx\n",
+ "Masked input from channel 0x%02x: data %02x, mask= 0x%02lx\n",
remote_num, data[2], channel_mask);
return;
}
diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c
index d1c61cd035f6..bd5512e64aea 100644
--- a/drivers/media/rc/ene_ir.c
+++ b/drivers/media/rc/ene_ir.c
@@ -1210,8 +1210,7 @@ MODULE_PARM_DESC(txsim,
MODULE_DEVICE_TABLE(pnp, ene_ids);
MODULE_DESCRIPTION
- ("Infrared input driver for KB3926B/C/D/E/F "
- "(aka ENE0100/ENE0200/ENE0201/ENE0202) CIR port");
+ ("Infrared input driver for KB3926B/C/D/E/F (aka ENE0100/ENE0200/ENE0201/ENE0202) CIR port");
MODULE_AUTHOR("Maxim Levitsky");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c
index bd7b3bdb1a88..ecab69ea3d51 100644
--- a/drivers/media/rc/fintek-cir.c
+++ b/drivers/media/rc/fintek-cir.c
@@ -104,11 +104,7 @@ static inline void fintek_cir_reg_write(struct fintek_dev *fintek, u8 val, u8 of
/* read val from cir config register */
static u8 fintek_cir_reg_read(struct fintek_dev *fintek, u8 offset)
{
- u8 val;
-
- val = inb(fintek->cir_addr + offset);
-
- return val;
+ return inb(fintek->cir_addr + offset);
}
/* dump current cir register contents */
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
index 86cc70fe2534..0785a24af8fc 100644
--- a/drivers/media/rc/imon.c
+++ b/drivers/media/rc/imon.c
@@ -441,13 +441,11 @@ MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes (default: no)");
/* lcd, vfd, vga or none? should be auto-detected, but can be overridden... */
static int display_type;
module_param(display_type, int, S_IRUGO);
-MODULE_PARM_DESC(display_type, "Type of attached display. 0=autodetect, "
- "1=vfd, 2=lcd, 3=vga, 4=none (default: autodetect)");
+MODULE_PARM_DESC(display_type, "Type of attached display. 0=autodetect, 1=vfd, 2=lcd, 3=vga, 4=none (default: autodetect)");
static int pad_stabilize = 1;
module_param(pad_stabilize, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(pad_stabilize, "Apply stabilization algorithm to iMON PAD "
- "presses in arrow key mode. 0=disable, 1=enable (default).");
+MODULE_PARM_DESC(pad_stabilize, "Apply stabilization algorithm to iMON PAD presses in arrow key mode. 0=disable, 1=enable (default).");
/*
* In certain use cases, mouse mode isn't really helpful, and could actually
@@ -455,14 +453,12 @@ MODULE_PARM_DESC(pad_stabilize, "Apply stabilization algorithm to iMON PAD "
*/
static bool nomouse;
module_param(nomouse, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(nomouse, "Disable mouse input device mode when IR device is "
- "open. 0=don't disable, 1=disable. (default: don't disable)");
+MODULE_PARM_DESC(nomouse, "Disable mouse input device mode when IR device is open. 0=don't disable, 1=disable. (default: don't disable)");
/* threshold at which a pad push registers as an arrow key in kbd mode */
static int pad_thresh;
module_param(pad_thresh, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(pad_thresh, "Threshold at which a pad push registers as an "
- "arrow key in kbd mode (default: 28)");
+MODULE_PARM_DESC(pad_thresh, "Threshold at which a pad push registers as an arrow key in kbd mode (default: 28)");
static void free_imon_context(struct imon_context *ictx)
@@ -611,7 +607,7 @@ static int send_packet(struct imon_context *ictx)
ictx->tx_urb->actual_length = 0;
}
- init_completion(&ictx->tx.finished);
+ reinit_completion(&ictx->tx.finished);
ictx->tx.busy = true;
smp_rmb(); /* ensure later readers know we're busy */
@@ -785,9 +781,7 @@ static ssize_t show_associate_remote(struct device *d,
else
strcpy(buf, "closed\n");
- dev_info(d, "Visit http://www.lirc.org/html/imon-24g.html for "
- "instructions on how to associate your iMON 2.4G DT/LT "
- "remote\n");
+ dev_info(d, "Visit http://www.lirc.org/html/imon-24g.html for instructions on how to associate your iMON 2.4G DT/LT remote\n");
mutex_unlock(&ictx->lock);
return strlen(buf);
}
@@ -1115,8 +1109,7 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 *rc_type)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 };
if (*rc_type && !(*rc_type & rc->allowed_protocols))
- dev_warn(dev, "Looks like you're trying to use an IR protocol "
- "this device does not support\n");
+ dev_warn(dev, "Looks like you're trying to use an IR protocol this device does not support\n");
if (*rc_type & RC_BIT_RC6_MCE) {
dev_dbg(dev, "Configuring IR receiver for MCE protocol\n");
@@ -1129,8 +1122,7 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 *rc_type)
/* ir_proto_packet[0] = 0x00; // already the default */
*rc_type = RC_BIT_OTHER;
} else {
- dev_warn(dev, "Unsupported IR protocol specified, overriding "
- "to iMON IR protocol\n");
+ dev_warn(dev, "Unsupported IR protocol specified, overriding to iMON IR protocol\n");
if (!pad_stabilize)
dev_dbg(dev, "PAD stabilize functionality disabled\n");
/* ir_proto_packet[0] = 0x00; // already the default */
@@ -1593,7 +1585,6 @@ static void imon_incoming_packet(struct imon_context *ictx,
struct device *dev = ictx->dev;
unsigned long flags;
u32 kc;
- int i;
u64 scancode;
int press_type = 0;
int msec;
@@ -1664,10 +1655,8 @@ static void imon_incoming_packet(struct imon_context *ictx,
}
if (debug) {
- printk(KERN_INFO "intf%d decoded packet: ", intf);
- for (i = 0; i < len; ++i)
- printk("%02x ", buf[i]);
- printk("\n");
+ printk(KERN_INFO "intf%d decoded packet: %*ph\n",
+ intf, len, buf);
}
press_type = imon_parse_press_type(ictx, buf, ktype);
@@ -1722,8 +1711,8 @@ static void imon_incoming_packet(struct imon_context *ictx,
not_input_data:
if (len != 8) {
- dev_warn(dev, "imon %s: invalid incoming packet "
- "size (len = %d, intf%d)\n", __func__, len, intf);
+ dev_warn(dev, "imon %s: invalid incoming packet size (len = %d, intf%d)\n",
+ __func__, len, intf);
return;
}
@@ -1879,8 +1868,7 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
allowed_protos = RC_BIT_RC6_MCE;
break;
default:
- dev_info(ictx->dev, "Unknown 0xffdc device, "
- "defaulting to VFD and iMON IR");
+ dev_info(ictx->dev, "Unknown 0xffdc device, defaulting to VFD and iMON IR");
detected_display_type = IMON_DISPLAY_TYPE_VFD;
/* We don't know which one it is, allow user to set the
* RC6 one from userspace if OTHER wasn't correct. */
@@ -1937,8 +1925,8 @@ static void imon_set_display_type(struct imon_context *ictx)
ictx->display_supported = false;
else
ictx->display_supported = true;
- dev_info(ictx->dev, "%s: overriding display type to %d via "
- "modparam\n", __func__, display_type);
+ dev_info(ictx->dev, "%s: overriding display type to %d via modparam\n",
+ __func__, display_type);
}
ictx->display_type = configured_display_type;
@@ -2159,8 +2147,8 @@ static bool imon_find_endpoints(struct imon_context *ictx,
if (!display_ep_found) {
tx_control = true;
display_ep_found = true;
- dev_dbg(ictx->dev, "%s: device uses control endpoint, not "
- "interface OUT endpoint\n", __func__);
+ dev_dbg(ictx->dev, "%s: device uses control endpoint, not interface OUT endpoint\n",
+ __func__);
}
/*
@@ -2228,6 +2216,8 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf,
ictx->tx_urb = tx_urb;
ictx->rf_device = false;
+ init_completion(&ictx->tx.finished);
+
ictx->vendor = le16_to_cpu(ictx->usbdev_intf0->descriptor.idVendor);
ictx->product = le16_to_cpu(ictx->usbdev_intf0->descriptor.idProduct);
@@ -2369,8 +2359,8 @@ static void imon_init_display(struct imon_context *ictx,
/* set up sysfs entry for built-in clock */
ret = sysfs_create_group(&intf->dev.kobj, &imon_display_attr_group);
if (ret)
- dev_err(ictx->dev, "Could not create display sysfs "
- "entries(%d)", ret);
+ dev_err(ictx->dev, "Could not create display sysfs entries(%d)",
+ ret);
if (ictx->display_type == IMON_DISPLAY_TYPE_LCD)
ret = usb_register_dev(intf, &imon_lcd_class);
@@ -2378,8 +2368,7 @@ static void imon_init_display(struct imon_context *ictx,
ret = usb_register_dev(intf, &imon_vfd_class);
if (ret)
/* Not a fatal error, so ignore */
- dev_info(ictx->dev, "could not get a minor number for "
- "display\n");
+ dev_info(ictx->dev, "could not get a minor number for display\n");
}
@@ -2459,8 +2448,8 @@ static int imon_probe(struct usb_interface *interface,
mutex_unlock(&ictx->lock);
}
- dev_info(dev, "iMON device (%04x:%04x, intf%d) on "
- "usb<%d:%d> initialized\n", vendor, product, ifnum,
+ dev_info(dev, "iMON device (%04x:%04x, intf%d) on usb<%d:%d> initialized\n",
+ vendor, product, ifnum,
usbdev->bus->busnum, usbdev->devnum);
mutex_unlock(&driver_lock);
@@ -2504,7 +2493,7 @@ static void imon_disconnect(struct usb_interface *interface)
/* Abort ongoing write */
if (ictx->tx.busy) {
usb_kill_urb(ictx->tx_urb);
- complete_all(&ictx->tx.finished);
+ complete(&ictx->tx.finished);
}
if (ifnum == 0) {
diff --git a/drivers/media/rc/ir-hix5hd2.c b/drivers/media/rc/ir-hix5hd2.c
index d0549fba711c..d26907e684dc 100644
--- a/drivers/media/rc/ir-hix5hd2.c
+++ b/drivers/media/rc/ir-hix5hd2.c
@@ -75,15 +75,22 @@ static void hix5hd2_ir_enable(struct hix5hd2_ir_priv *dev, bool on)
{
u32 val;
- regmap_read(dev->regmap, IR_CLK, &val);
- if (on) {
- val &= ~IR_CLK_RESET;
- val |= IR_CLK_ENABLE;
+ if (dev->regmap) {
+ regmap_read(dev->regmap, IR_CLK, &val);
+ if (on) {
+ val &= ~IR_CLK_RESET;
+ val |= IR_CLK_ENABLE;
+ } else {
+ val &= ~IR_CLK_ENABLE;
+ val |= IR_CLK_RESET;
+ }
+ regmap_write(dev->regmap, IR_CLK, val);
} else {
- val &= ~IR_CLK_ENABLE;
- val |= IR_CLK_RESET;
+ if (on)
+ clk_prepare_enable(dev->clock);
+ else
+ clk_disable_unprepare(dev->clock);
}
- regmap_write(dev->regmap, IR_CLK, val);
}
static int hix5hd2_ir_config(struct hix5hd2_ir_priv *priv)
@@ -207,8 +214,8 @@ static int hix5hd2_ir_probe(struct platform_device *pdev)
priv->regmap = syscon_regmap_lookup_by_phandle(node,
"hisilicon,power-syscon");
if (IS_ERR(priv->regmap)) {
- dev_err(dev, "no power-reg\n");
- return -EINVAL;
+ dev_info(dev, "no power-reg\n");
+ priv->regmap = NULL;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c
index 7331e5e7c497..b07d9caebeb1 100644
--- a/drivers/media/rc/ir-sanyo-decoder.c
+++ b/drivers/media/rc/ir-sanyo-decoder.c
@@ -56,7 +56,8 @@ static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev)
{
struct sanyo_dec *data = &dev->raw->sanyo;
u32 scancode;
- u8 address, command, not_command;
+ u16 address;
+ u8 command, not_command;
if (!is_timing_event(ev)) {
if (ev.reset) {
diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
index 0f301903aa6f..367b28bed627 100644
--- a/drivers/media/rc/ite-cir.c
+++ b/drivers/media/rc/ite-cir.c
@@ -55,14 +55,12 @@ MODULE_PARM_DESC(debug, "Enable debugging output");
/* low limit for RX carrier freq, Hz, 0 for no RX demodulation */
static int rx_low_carrier_freq;
module_param(rx_low_carrier_freq, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(rx_low_carrier_freq, "Override low RX carrier frequency, Hz, "
- "0 for no RX demodulation");
+MODULE_PARM_DESC(rx_low_carrier_freq, "Override low RX carrier frequency, Hz, 0 for no RX demodulation");
/* high limit for RX carrier freq, Hz, 0 for no RX demodulation */
static int rx_high_carrier_freq;
module_param(rx_high_carrier_freq, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(rx_high_carrier_freq, "Override high RX carrier frequency, "
- "Hz, 0 for no RX demodulation");
+MODULE_PARM_DESC(rx_high_carrier_freq, "Override high RX carrier frequency, Hz, 0 for no RX demodulation");
/* override tx carrier frequency */
static int tx_carrier_freq;
@@ -263,6 +261,8 @@ static void ite_set_carrier_params(struct ite_dev *dev)
if (allowance > ITE_RXDCR_MAX)
allowance = ITE_RXDCR_MAX;
+
+ use_demodulator = true;
}
}
@@ -1484,8 +1484,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
if (model_number >= 0 && model_number < ARRAY_SIZE(ite_dev_descs)) {
model_no = model_number;
- ite_pr(KERN_NOTICE, "The model has been fixed by a module "
- "parameter.");
+ ite_pr(KERN_NOTICE, "The model has been fixed by a module parameter.");
}
ite_pr(KERN_NOTICE, "Using model: %s\n", ite_dev_descs[model_no].model);
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 91f9bb87ce68..3854809e8531 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -150,9 +150,6 @@ static const struct file_operations lirc_dev_fops = {
.write = lirc_dev_fop_write,
.poll = lirc_dev_fop_poll,
.unlocked_ioctl = lirc_dev_fop_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = lirc_dev_fop_ioctl,
-#endif
.open = lirc_dev_fop_open,
.release = lirc_dev_fop_close,
.llseek = noop_llseek,
@@ -160,19 +157,19 @@ static const struct file_operations lirc_dev_fops = {
static int lirc_cdev_add(struct irctl *ir)
{
- int retval = -ENOMEM;
struct lirc_driver *d = &ir->d;
struct cdev *cdev;
+ int retval;
- cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
+ cdev = cdev_alloc();
if (!cdev)
- goto err_out;
+ return -ENOMEM;
if (d->fops) {
- cdev_init(cdev, d->fops);
+ cdev->ops = d->fops;
cdev->owner = d->owner;
} else {
- cdev_init(cdev, &lirc_dev_fops);
+ cdev->ops = &lirc_dev_fops;
cdev->owner = THIS_MODULE;
}
retval = kobject_set_name(&cdev->kobj, "lirc%d", d->minor);
@@ -180,17 +177,15 @@ static int lirc_cdev_add(struct irctl *ir)
goto err_out;
retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
- if (retval) {
- kobject_put(&cdev->kobj);
+ if (retval)
goto err_out;
- }
ir->cdev = cdev;
return 0;
err_out:
- kfree(cdev);
+ cdev_del(cdev);
return retval;
}
@@ -420,7 +415,6 @@ int lirc_unregister_driver(int minor)
} else {
lirc_irctl_cleanup(ir);
cdev_del(cdev);
- kfree(cdev);
kfree(ir);
irctls[minor] = NULL;
}
@@ -521,7 +515,6 @@ int lirc_dev_fop_close(struct inode *inode, struct file *file)
lirc_irctl_cleanup(ir);
cdev_del(cdev);
irctls[ir->d.minor] = NULL;
- kfree(cdev);
kfree(ir);
}
@@ -684,7 +677,6 @@ ssize_t lirc_dev_fop_read(struct file *file,
* between while condition checking and scheduling)
*/
add_wait_queue(&ir->buf->wait_poll, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
/*
* while we didn't provide 'length' bytes, device is opened in blocking
@@ -709,19 +701,19 @@ ssize_t lirc_dev_fop_read(struct file *file,
}
mutex_unlock(&ir->irctl_lock);
- schedule();
set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ set_current_state(TASK_RUNNING);
if (mutex_lock_interruptible(&ir->irctl_lock)) {
ret = -ERESTARTSYS;
remove_wait_queue(&ir->buf->wait_poll, &wait);
- set_current_state(TASK_RUNNING);
goto out_unlocked;
}
if (!ir->attached) {
ret = -ENODEV;
- break;
+ goto out_locked;
}
} else {
lirc_buffer_read(ir->buf, buf);
@@ -735,7 +727,6 @@ ssize_t lirc_dev_fop_read(struct file *file,
}
remove_wait_queue(&ir->buf->wait_poll, &wait);
- set_current_state(TASK_RUNNING);
out_locked:
mutex_unlock(&ir->irctl_lock);
diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index 4f8c7effdcee..9bf69179eee0 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -153,15 +153,6 @@
#define MCE_COMMAND_IRDATA 0x80
#define MCE_PACKET_LENGTH_MASK 0x1f /* Packet length mask */
-/* general constants */
-#define SEND_FLAG_IN_PROGRESS 1
-#define SEND_FLAG_COMPLETE 2
-#define RECV_FLAG_IN_PROGRESS 3
-#define RECV_FLAG_COMPLETE 4
-
-#define MCEUSB_RX 1
-#define MCEUSB_TX 2
-
#define VENDOR_PHILIPS 0x0471
#define VENDOR_SMK 0x0609
#define VENDOR_TATUNG 0x1460
@@ -422,7 +413,6 @@ struct mceusb_dev {
struct rc_dev *rc;
/* optional features we can enable */
- bool carrier_report_enabled;
bool learning_enabled;
/* core device bits */
@@ -455,7 +445,6 @@ struct mceusb_dev {
} flags;
/* transmit support */
- int send_flags;
u32 carrier;
unsigned char tx_mask;
@@ -604,9 +593,7 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
break;
case MCE_RSP_EQWAKEVERSION:
if (!out)
- dev_dbg(dev, "Wake version, proto: 0x%02x, "
- "payload: 0x%02x, address: 0x%02x, "
- "version: 0x%02x",
+ dev_dbg(dev, "Wake version, proto: 0x%02x, payload: 0x%02x, address: 0x%02x, version: 0x%02x",
data1, data2, data3, data4);
break;
case MCE_RSP_GETPORTSTATUS:
@@ -740,52 +727,40 @@ static void mce_async_callback(struct urb *urb)
/* request incoming or send outgoing usb packet - used to initialize remote */
static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data,
- int size, int urb_type)
+ int size)
{
int res, pipe;
struct urb *async_urb;
struct device *dev = ir->dev;
unsigned char *async_buf;
- if (urb_type == MCEUSB_TX) {
- async_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (unlikely(!async_urb)) {
- dev_err(dev, "Error, couldn't allocate urb!\n");
- return;
- }
-
- async_buf = kzalloc(size, GFP_KERNEL);
- if (!async_buf) {
- dev_err(dev, "Error, couldn't allocate buf!\n");
- usb_free_urb(async_urb);
- return;
- }
-
- /* outbound data */
- if (usb_endpoint_xfer_int(ir->usb_ep_out)) {
- pipe = usb_sndintpipe(ir->usbdev,
- ir->usb_ep_out->bEndpointAddress);
- usb_fill_int_urb(async_urb, ir->usbdev, pipe, async_buf,
- size, mce_async_callback, ir,
- ir->usb_ep_out->bInterval);
- } else {
- pipe = usb_sndbulkpipe(ir->usbdev,
- ir->usb_ep_out->bEndpointAddress);
- usb_fill_bulk_urb(async_urb, ir->usbdev, pipe,
- async_buf, size, mce_async_callback,
- ir);
- }
- memcpy(async_buf, data, size);
+ async_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (unlikely(!async_urb)) {
+ dev_err(dev, "Error, couldn't allocate urb!\n");
+ return;
+ }
- } else if (urb_type == MCEUSB_RX) {
- /* standard request */
- async_urb = ir->urb_in;
- ir->send_flags = RECV_FLAG_IN_PROGRESS;
+ async_buf = kmalloc(size, GFP_KERNEL);
+ if (!async_buf) {
+ usb_free_urb(async_urb);
+ return;
+ }
+ /* outbound data */
+ if (usb_endpoint_xfer_int(ir->usb_ep_out)) {
+ pipe = usb_sndintpipe(ir->usbdev,
+ ir->usb_ep_out->bEndpointAddress);
+ usb_fill_int_urb(async_urb, ir->usbdev, pipe, async_buf,
+ size, mce_async_callback, ir,
+ ir->usb_ep_out->bInterval);
} else {
- dev_err(dev, "Error! Unknown urb type %d\n", urb_type);
- return;
+ pipe = usb_sndbulkpipe(ir->usbdev,
+ ir->usb_ep_out->bEndpointAddress);
+ usb_fill_bulk_urb(async_urb, ir->usbdev, pipe,
+ async_buf, size, mce_async_callback,
+ ir);
}
+ memcpy(async_buf, data, size);
dev_dbg(dev, "receive request called (size=%#x)", size);
@@ -806,19 +781,14 @@ static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size)
if (ir->need_reset) {
ir->need_reset = false;
- mce_request_packet(ir, DEVICE_RESUME, rsize, MCEUSB_TX);
+ mce_request_packet(ir, DEVICE_RESUME, rsize);
msleep(10);
}
- mce_request_packet(ir, data, size, MCEUSB_TX);
+ mce_request_packet(ir, data, size);
msleep(10);
}
-static void mce_flush_rx_buffer(struct mceusb_dev *ir, int size)
-{
- mce_request_packet(ir, NULL, size, MCEUSB_RX);
-}
-
/* Send data out the IR blaster port(s) */
static int mceusb_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count)
{
@@ -1062,7 +1032,6 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
static void mceusb_dev_recv(struct urb *urb)
{
struct mceusb_dev *ir;
- int buf_len;
if (!urb)
return;
@@ -1073,18 +1042,10 @@ static void mceusb_dev_recv(struct urb *urb)
return;
}
- buf_len = urb->actual_length;
-
- if (ir->send_flags == RECV_FLAG_IN_PROGRESS) {
- ir->send_flags = SEND_FLAG_COMPLETE;
- dev_dbg(ir->dev, "setup answer received %d bytes\n",
- buf_len);
- }
-
switch (urb->status) {
/* success */
case 0:
- mceusb_process_ir_data(ir, buf_len);
+ mceusb_process_ir_data(ir, urb->actual_length);
break;
case -ECONNRESET:
@@ -1285,7 +1246,7 @@ static int mceusb_dev_probe(struct usb_interface *intf,
struct usb_endpoint_descriptor *ep_in = NULL;
struct usb_endpoint_descriptor *ep_out = NULL;
struct mceusb_dev *ir = NULL;
- int pipe, maxp, i;
+ int pipe, maxp, i, res;
char buf[63], name[128] = "";
enum mceusb_model_type model = id->driver_info;
bool is_gen3;
@@ -1388,7 +1349,9 @@ static int mceusb_dev_probe(struct usb_interface *intf,
/* flush buffers on the device */
dev_dbg(&intf->dev, "Flushing receive buffers\n");
- mce_flush_rx_buffer(ir, maxp);
+ res = usb_submit_urb(ir->urb_in, GFP_KERNEL);
+ if (res)
+ dev_err(&intf->dev, "failed to flush buffers: %d\n", res);
/* figure out which firmware/emulator version this hardware has */
mceusb_get_emulator_version(ir);
@@ -1423,6 +1386,7 @@ static int mceusb_dev_probe(struct usb_interface *intf,
/* Error-handling path */
rc_dev_fail:
usb_put_dev(ir->usbdev);
+ usb_kill_urb(ir->urb_in);
usb_free_urb(ir->urb_in);
urb_in_alloc_fail:
usb_free_coherent(dev, maxp, ir->buf_in, ir->dma_in);
diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c
index 003fff07ade2..7eb3f4f1ddcd 100644
--- a/drivers/media/rc/meson-ir.c
+++ b/drivers/media/rc/meson-ir.c
@@ -218,6 +218,7 @@ static const struct of_device_id meson_ir_match[] = {
{ .compatible = "amlogic,meson-gxbb-ir" },
{ },
};
+MODULE_DEVICE_TABLE(of, meson_ir_match);
static struct platform_driver meson_ir_driver = {
.probe = meson_ir_probe,
diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 04fedaa75612..4b78c891eb77 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -48,6 +48,11 @@ static const struct nvt_chip nvt_chips[] = {
{ "NCT6779D", NVT_6779D },
};
+static inline struct device *nvt_get_dev(const struct nvt_dev *nvt)
+{
+ return nvt->rdev->dev.parent;
+}
+
static inline bool is_w83667hg(struct nvt_dev *nvt)
{
return nvt->chip_ver == NVT_W83667HG;
@@ -182,7 +187,7 @@ static ssize_t wakeup_data_show(struct device *dev,
ssize_t buf_len = 0;
int i;
- spin_lock_irqsave(&nvt->nvt_lock, flags);
+ spin_lock_irqsave(&nvt->lock, flags);
fifo_len = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT);
fifo_len = min(fifo_len, WAKEUP_MAX_SIZE);
@@ -199,7 +204,7 @@ static ssize_t wakeup_data_show(struct device *dev,
}
buf_len += snprintf(buf + buf_len, PAGE_SIZE - buf_len, "\n");
- spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+ spin_unlock_irqrestore(&nvt->lock, flags);
return buf_len;
}
@@ -243,7 +248,7 @@ static ssize_t wakeup_data_store(struct device *dev,
/* hardcode the tolerance to 10% */
tolerance = DIV_ROUND_UP(count, 10);
- spin_lock_irqsave(&nvt->nvt_lock, flags);
+ spin_lock_irqsave(&nvt->lock, flags);
nvt_clear_cir_wake_fifo(nvt);
nvt_cir_wake_reg_write(nvt, count, CIR_WAKE_FIFO_CMP_DEEP);
@@ -260,7 +265,7 @@ static ssize_t wakeup_data_store(struct device *dev,
nvt_cir_wake_reg_write(nvt, config, CIR_WAKE_IRCON);
- spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+ spin_unlock_irqrestore(&nvt->lock, flags);
ret = len;
out:
@@ -385,6 +390,7 @@ static inline const char *nvt_find_chip(struct nvt_dev *nvt, int id)
/* detect hardware features */
static int nvt_hw_detect(struct nvt_dev *nvt)
{
+ struct device *dev = nvt_get_dev(nvt);
const char *chip_name;
int chip_id;
@@ -405,8 +411,7 @@ static int nvt_hw_detect(struct nvt_dev *nvt)
chip_id = nvt->chip_major << 8 | nvt->chip_minor;
if (chip_id == NVT_INVALID) {
- dev_err(&nvt->pdev->dev,
- "No device found on either EFM port\n");
+ dev_err(dev, "No device found on either EFM port\n");
return -ENODEV;
}
@@ -414,12 +419,11 @@ static int nvt_hw_detect(struct nvt_dev *nvt)
/* warn, but still let the driver load, if we don't know this chip */
if (!chip_name)
- dev_warn(&nvt->pdev->dev,
+ dev_warn(dev,
"unknown chip, id: 0x%02x 0x%02x, it may not work...",
nvt->chip_major, nvt->chip_minor);
else
- dev_info(&nvt->pdev->dev,
- "found %s or compatible: chip id: 0x%02x 0x%02x",
+ dev_info(dev, "found %s or compatible: chip id: 0x%02x 0x%02x",
chip_name, nvt->chip_major, nvt->chip_minor);
return 0;
@@ -586,7 +590,7 @@ static void nvt_enable_wake(struct nvt_dev *nvt)
nvt_efm_disable(nvt);
- spin_lock_irqsave(&nvt->nvt_lock, flags);
+ spin_lock_irqsave(&nvt->lock, flags);
nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN |
CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV |
@@ -595,11 +599,11 @@ static void nvt_enable_wake(struct nvt_dev *nvt)
nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS);
nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN);
- spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+ spin_unlock_irqrestore(&nvt->lock, flags);
}
#if 0 /* Currently unused */
-/* rx carrier detect only works in learning mode, must be called w/nvt_lock */
+/* rx carrier detect only works in learning mode, must be called w/lock */
static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt)
{
u32 count, carrier, duration = 0;
@@ -616,7 +620,7 @@ static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt)
duration *= SAMPLE_PERIOD;
if (!count || !duration) {
- dev_notice(&nvt->pdev->dev,
+ dev_notice(nvt_get_dev(nvt),
"Unable to determine carrier! (c:%u, d:%u)",
count, duration);
return 0;
@@ -684,7 +688,7 @@ static int nvt_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned n)
u8 iren;
int ret;
- spin_lock_irqsave(&nvt->tx.lock, flags);
+ spin_lock_irqsave(&nvt->lock, flags);
ret = min((unsigned)(TX_BUF_LEN / sizeof(unsigned)), n);
nvt->tx.buf_count = (ret * sizeof(unsigned));
@@ -708,13 +712,13 @@ static int nvt_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned n)
for (i = 0; i < 9; i++)
nvt_cir_reg_write(nvt, 0x01, CIR_STXFIFO);
- spin_unlock_irqrestore(&nvt->tx.lock, flags);
+ spin_unlock_irqrestore(&nvt->lock, flags);
wait_event(nvt->tx.queue, nvt->tx.tx_state == ST_TX_REQUEST);
- spin_lock_irqsave(&nvt->tx.lock, flags);
+ spin_lock_irqsave(&nvt->lock, flags);
nvt->tx.tx_state = ST_TX_NONE;
- spin_unlock_irqrestore(&nvt->tx.lock, flags);
+ spin_unlock_irqrestore(&nvt->lock, flags);
/* restore enabled interrupts to prior state */
nvt_cir_reg_write(nvt, iren, CIR_IREN);
@@ -781,7 +785,7 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
static void nvt_handle_rx_fifo_overrun(struct nvt_dev *nvt)
{
- dev_warn(&nvt->pdev->dev, "RX FIFO overrun detected, flushing data!");
+ dev_warn(nvt_get_dev(nvt), "RX FIFO overrun detected, flushing data!");
nvt->pkts = 0;
nvt_clear_cir_fifo(nvt);
@@ -828,14 +832,7 @@ static void nvt_cir_log_irqs(u8 status, u8 iren)
static bool nvt_cir_tx_inactive(struct nvt_dev *nvt)
{
- unsigned long flags;
- u8 tx_state;
-
- spin_lock_irqsave(&nvt->tx.lock, flags);
- tx_state = nvt->tx.tx_state;
- spin_unlock_irqrestore(&nvt->tx.lock, flags);
-
- return tx_state == ST_TX_NONE;
+ return nvt->tx.tx_state == ST_TX_NONE;
}
/* interrupt service routine for incoming and outgoing CIR data */
@@ -843,11 +840,10 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
{
struct nvt_dev *nvt = data;
u8 status, iren;
- unsigned long flags;
nvt_dbg_verbose("%s firing", __func__);
- spin_lock_irqsave(&nvt->nvt_lock, flags);
+ spin_lock(&nvt->lock);
/*
* Get IR Status register contents. Write 1 to ack/clear
@@ -869,7 +865,7 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
* logical device is being disabled.
*/
if (status == 0xff && iren == 0xff) {
- spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+ spin_unlock(&nvt->lock);
nvt_dbg_verbose("Spurious interrupt detected");
return IRQ_HANDLED;
}
@@ -878,7 +874,7 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
* status bit whether the related interrupt source is enabled
*/
if (!(status & iren)) {
- spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+ spin_unlock(&nvt->lock);
nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__);
return IRQ_NONE;
}
@@ -898,8 +894,6 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
nvt_get_rx_ir_data(nvt);
}
- spin_unlock_irqrestore(&nvt->nvt_lock, flags);
-
if (status & CIR_IRSTS_TE)
nvt_clear_tx_fifo(nvt);
@@ -907,8 +901,6 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
unsigned int pos, count;
u8 tmp;
- spin_lock_irqsave(&nvt->tx.lock, flags);
-
pos = nvt->tx.cur_buf_num;
count = nvt->tx.buf_count;
@@ -921,20 +913,17 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
tmp = nvt_cir_reg_read(nvt, CIR_IREN);
nvt_cir_reg_write(nvt, tmp & ~CIR_IREN_TTR, CIR_IREN);
}
-
- spin_unlock_irqrestore(&nvt->tx.lock, flags);
-
}
if (status & CIR_IRSTS_TFU) {
- spin_lock_irqsave(&nvt->tx.lock, flags);
if (nvt->tx.tx_state == ST_TX_REPLY) {
nvt->tx.tx_state = ST_TX_REQUEST;
wake_up(&nvt->tx.queue);
}
- spin_unlock_irqrestore(&nvt->tx.lock, flags);
}
+ spin_unlock(&nvt->lock);
+
nvt_dbg_verbose("%s done", __func__);
return IRQ_HANDLED;
}
@@ -943,7 +932,7 @@ static void nvt_disable_cir(struct nvt_dev *nvt)
{
unsigned long flags;
- spin_lock_irqsave(&nvt->nvt_lock, flags);
+ spin_lock_irqsave(&nvt->lock, flags);
/* disable CIR interrupts */
nvt_cir_reg_write(nvt, 0, CIR_IREN);
@@ -958,7 +947,7 @@ static void nvt_disable_cir(struct nvt_dev *nvt)
nvt_clear_cir_fifo(nvt);
nvt_clear_tx_fifo(nvt);
- spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+ spin_unlock_irqrestore(&nvt->lock, flags);
/* disable the CIR logical device */
nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR);
@@ -969,7 +958,7 @@ static int nvt_open(struct rc_dev *dev)
struct nvt_dev *nvt = dev->priv;
unsigned long flags;
- spin_lock_irqsave(&nvt->nvt_lock, flags);
+ spin_lock_irqsave(&nvt->lock, flags);
/* set function enable flags */
nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN |
@@ -982,7 +971,7 @@ static int nvt_open(struct rc_dev *dev)
/* enable interrupts */
nvt_set_cir_iren(nvt);
- spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+ spin_unlock_irqrestore(&nvt->lock, flags);
/* enable the CIR logical device */
nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR);
@@ -1002,40 +991,41 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
{
struct nvt_dev *nvt;
struct rc_dev *rdev;
- int ret = -ENOMEM;
+ int ret;
nvt = devm_kzalloc(&pdev->dev, sizeof(struct nvt_dev), GFP_KERNEL);
if (!nvt)
- return ret;
+ return -ENOMEM;
/* input device for IR remote (and tx) */
- rdev = rc_allocate_device();
- if (!rdev)
- goto exit_free_dev_rdev;
+ nvt->rdev = devm_rc_allocate_device(&pdev->dev);
+ if (!nvt->rdev)
+ return -ENOMEM;
+ rdev = nvt->rdev;
- ret = -ENODEV;
/* activate pnp device */
- if (pnp_activate_dev(pdev) < 0) {
+ ret = pnp_activate_dev(pdev);
+ if (ret) {
dev_err(&pdev->dev, "Could not activate PNP device!\n");
- goto exit_free_dev_rdev;
+ return ret;
}
/* validate pnp resources */
if (!pnp_port_valid(pdev, 0) ||
pnp_port_len(pdev, 0) < CIR_IOREG_LENGTH) {
dev_err(&pdev->dev, "IR PNP Port not valid!\n");
- goto exit_free_dev_rdev;
+ return -EINVAL;
}
if (!pnp_irq_valid(pdev, 0)) {
dev_err(&pdev->dev, "PNP IRQ not valid!\n");
- goto exit_free_dev_rdev;
+ return -EINVAL;
}
if (!pnp_port_valid(pdev, 1) ||
pnp_port_len(pdev, 1) < CIR_IOREG_LENGTH) {
dev_err(&pdev->dev, "Wake PNP Port not valid!\n");
- goto exit_free_dev_rdev;
+ return -EINVAL;
}
nvt->cir_addr = pnp_port_start(pdev, 0);
@@ -1046,17 +1036,15 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
nvt->cr_efir = CR_EFIR;
nvt->cr_efdr = CR_EFDR;
- spin_lock_init(&nvt->nvt_lock);
- spin_lock_init(&nvt->tx.lock);
+ spin_lock_init(&nvt->lock);
pnp_set_drvdata(pdev, nvt);
- nvt->pdev = pdev;
init_waitqueue_head(&nvt->tx.queue);
ret = nvt_hw_detect(nvt);
if (ret)
- goto exit_free_dev_rdev;
+ return ret;
/* Initialize CIR & CIR Wake Logical Devices */
nvt_efm_enable(nvt);
@@ -1085,7 +1073,6 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
rdev->input_id.vendor = PCI_VENDOR_ID_WINBOND2;
rdev->input_id.product = nvt->chip_major;
rdev->input_id.version = nvt->chip_minor;
- rdev->dev.parent = &pdev->dev;
rdev->driver_name = NVT_DRIVER_NAME;
rdev->map_name = RC_MAP_RC6_MCE;
rdev->timeout = MS_TO_NS(100);
@@ -1097,29 +1084,27 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
/* tx bits */
rdev->tx_resolution = XYZ;
#endif
- nvt->rdev = rdev;
-
- ret = rc_register_device(rdev);
+ ret = devm_rc_register_device(&pdev->dev, rdev);
if (ret)
- goto exit_free_dev_rdev;
+ return ret;
- ret = -EBUSY;
/* now claim resources */
if (!devm_request_region(&pdev->dev, nvt->cir_addr,
CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
- goto exit_unregister_device;
+ return -EBUSY;
- if (devm_request_irq(&pdev->dev, nvt->cir_irq, nvt_cir_isr,
- IRQF_SHARED, NVT_DRIVER_NAME, (void *)nvt))
- goto exit_unregister_device;
+ ret = devm_request_irq(&pdev->dev, nvt->cir_irq, nvt_cir_isr,
+ IRQF_SHARED, NVT_DRIVER_NAME, nvt);
+ if (ret)
+ return ret;
if (!devm_request_region(&pdev->dev, nvt->cir_wake_addr,
CIR_IOREG_LENGTH, NVT_DRIVER_NAME "-wake"))
- goto exit_unregister_device;
+ return -EBUSY;
ret = device_create_file(&rdev->dev, &dev_attr_wakeup_data);
if (ret)
- goto exit_unregister_device;
+ return ret;
device_init_wakeup(&pdev->dev, true);
@@ -1130,14 +1115,6 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
}
return 0;
-
-exit_unregister_device:
- rc_unregister_device(rdev);
- rdev = NULL;
-exit_free_dev_rdev:
- rc_free_device(rdev);
-
- return ret;
}
static void nvt_remove(struct pnp_dev *pdev)
@@ -1150,8 +1127,6 @@ static void nvt_remove(struct pnp_dev *pdev)
/* enable CIR Wake (for IR power-on) */
nvt_enable_wake(nvt);
-
- rc_unregister_device(nvt->rdev);
}
static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state)
@@ -1161,16 +1136,14 @@ static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state)
nvt_dbg("%s called", __func__);
- spin_lock_irqsave(&nvt->tx.lock, flags);
- nvt->tx.tx_state = ST_TX_NONE;
- spin_unlock_irqrestore(&nvt->tx.lock, flags);
+ spin_lock_irqsave(&nvt->lock, flags);
- spin_lock_irqsave(&nvt->nvt_lock, flags);
+ nvt->tx.tx_state = ST_TX_NONE;
/* disable all CIR interrupts */
nvt_cir_reg_write(nvt, 0, CIR_IREN);
- spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+ spin_unlock_irqrestore(&nvt->lock, flags);
/* disable cir logical dev */
nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR);
diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h
index acf735fc7170..c41c5765e1d2 100644
--- a/drivers/media/rc/nuvoton-cir.h
+++ b/drivers/media/rc/nuvoton-cir.h
@@ -78,17 +78,15 @@ struct nvt_chip {
};
struct nvt_dev {
- struct pnp_dev *pdev;
struct rc_dev *rdev;
- spinlock_t nvt_lock;
+ spinlock_t lock;
/* for rx */
u8 buf[RX_BUF_LEN];
unsigned int pkts;
struct {
- spinlock_t lock;
u8 buf[TX_BUF_LEN];
unsigned int buf_count;
unsigned int cur_buf_num;
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 205ecc602e34..1c42a9f2f290 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -26,8 +26,7 @@ static LIST_HEAD(ir_raw_client_list);
/* Used to handle IR raw handler extensions */
static DEFINE_MUTEX(ir_raw_handler_lock);
static LIST_HEAD(ir_raw_handler_list);
-static DEFINE_MUTEX(available_protocols_lock);
-static u64 available_protocols;
+static atomic64_t available_protocols = ATOMIC64_INIT(0);
static int ir_raw_event_thread(void *data)
{
@@ -234,11 +233,7 @@ EXPORT_SYMBOL_GPL(ir_raw_event_handle);
u64
ir_raw_get_allowed_protocols(void)
{
- u64 protocols;
- mutex_lock(&available_protocols_lock);
- protocols = available_protocols;
- mutex_unlock(&available_protocols_lock);
- return protocols;
+ return atomic64_read(&available_protocols);
}
static int change_protocol(struct rc_dev *dev, u64 *rc_type)
@@ -331,9 +326,7 @@ int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler)
if (ir_raw_handler->raw_register)
list_for_each_entry(raw, &ir_raw_client_list, list)
ir_raw_handler->raw_register(raw->dev);
- mutex_lock(&available_protocols_lock);
- available_protocols |= ir_raw_handler->protocols;
- mutex_unlock(&available_protocols_lock);
+ atomic64_or(ir_raw_handler->protocols, &available_protocols);
mutex_unlock(&ir_raw_handler_lock);
return 0;
@@ -352,9 +345,7 @@ void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler)
if (ir_raw_handler->raw_unregister)
ir_raw_handler->raw_unregister(raw->dev);
}
- mutex_lock(&available_protocols_lock);
- available_protocols &= ~protocols;
- mutex_unlock(&available_protocols_lock);
+ atomic64_andnot(protocols, &available_protocols);
mutex_unlock(&ir_raw_handler_lock);
}
EXPORT_SYMBOL(ir_raw_handler_unregister);
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index d9c1f2ff7119..dedaf38c5ff6 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -12,6 +12,8 @@
* GNU General Public License for more details.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <media/rc-core.h>
#include <linux/atomic.h>
#include <linux/spinlock.h>
@@ -66,7 +68,7 @@ struct rc_map *rc_map_get(const char *name)
if (!map) {
int rc = request_module("%s", name);
if (rc < 0) {
- printk(KERN_ERR "Couldn't load IR keymap %s\n", name);
+ pr_err("Couldn't load IR keymap %s\n", name);
return NULL;
}
msleep(20); /* Give some time for IR to register */
@@ -75,7 +77,7 @@ struct rc_map *rc_map_get(const char *name)
}
#endif
if (!map) {
- printk(KERN_ERR "IR keymap %s not found\n", name);
+ pr_err("IR keymap %s not found\n", name);
return NULL;
}
@@ -159,6 +161,7 @@ static void ir_free_table(struct rc_map *rc_map)
{
rc_map->size = 0;
kfree(rc_map->name);
+ rc_map->name = NULL;
kfree(rc_map->scan);
rc_map->scan = NULL;
}
@@ -660,8 +663,7 @@ static void ir_do_keydown(struct rc_dev *dev, enum rc_type protocol,
dev->last_toggle = toggle;
dev->last_keycode = keycode;
- IR_dprintk(1, "%s: key down event, "
- "key 0x%04x, protocol 0x%04x, scancode 0x%08x\n",
+ IR_dprintk(1, "%s: key down event, key 0x%04x, protocol 0x%04x, scancode 0x%08x\n",
dev->input_name, keycode, protocol, scancode);
input_report_key(dev->input_dev, keycode, 1);
@@ -1403,6 +1405,34 @@ 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)
+{
+ struct rc_dev **dr, *rc;
+
+ dr = devres_alloc(devm_rc_alloc_release, sizeof(*dr), GFP_KERNEL);
+ if (!dr)
+ return NULL;
+
+ rc = rc_allocate_device();
+ 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? */
@@ -1531,6 +1561,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)
@@ -1552,7 +1609,8 @@ void rc_unregister_device(struct rc_dev *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);
@@ -1565,7 +1623,7 @@ static int __init rc_core_init(void)
{
int rc = class_register(&rc_class);
if (rc) {
- printk(KERN_ERR "rc_core: unable to register rc class\n");
+ pr_err("rc_core: unable to register rc class\n");
return rc;
}
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index 05ba47bc0b61..2784f5dae398 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -81,6 +81,8 @@
#define RR3_RC_DET_ENABLE 0xbb
/* Stop capture with the RC receiver */
#define RR3_RC_DET_DISABLE 0xbc
+/* Start capture with the wideband receiver */
+#define RR3_MODSIG_CAPTURE 0xb2
/* Return the status of RC detector capture */
#define RR3_RC_DET_STATUS 0xbd
/* Reset redrat */
@@ -105,11 +107,13 @@
#define RR3_CLK_PER_COUNT 12
/* (RR3_CLK / RR3_CLK_PER_COUNT) */
#define RR3_CLK_CONV_FACTOR 2000000
-/* USB bulk-in IR data endpoint address */
-#define RR3_BULK_IN_EP_ADDR 0x82
+/* USB bulk-in wideband IR data endpoint address */
+#define RR3_WIDE_IN_EP_ADDR 0x81
+/* USB bulk-in narrowband IR data endpoint address */
+#define RR3_NARROW_IN_EP_ADDR 0x82
/* Size of the fixed-length portion of the signal */
-#define RR3_DRIVER_MAXLENS 128
+#define RR3_DRIVER_MAXLENS 255
#define RR3_MAX_SIG_SIZE 512
#define RR3_TIME_UNIT 50
#define RR3_END_OF_SIGNAL 0x7f
@@ -207,15 +211,22 @@ struct redrat3_dev {
struct urb *flash_urb;
u8 flash_in_buf;
+ /* learning */
+ bool wideband;
+ struct usb_ctrlrequest learn_control;
+ struct urb *learn_urb;
+ u8 learn_buf;
+
/* save off the usb device pointer */
struct usb_device *udev;
/* the receive endpoint */
- struct usb_endpoint_descriptor *ep_in;
+ struct usb_endpoint_descriptor *ep_narrow;
/* the buffer to receive data */
void *bulk_in_buf;
/* urb used to read ir data */
- struct urb *read_urb;
+ struct urb *narrow_urb;
+ struct urb *wide_urb;
/* the send endpoint */
struct usb_endpoint_descriptor *ep_out;
@@ -236,23 +247,6 @@ struct redrat3_dev {
char phys[64];
};
-/*
- * redrat3_issue_async
- *
- * Issues an async read to the ir data in port..
- * sets the callback to be redrat3_handle_async
- */
-static void redrat3_issue_async(struct redrat3_dev *rr3)
-{
- int res;
-
- res = usb_submit_urb(rr3->read_urb, GFP_ATOMIC);
- if (res)
- dev_dbg(rr3->dev,
- "%s: receive request FAILED! (res %d, len %d)\n",
- __func__, res, rr3->read_urb->transfer_buffer_length);
-}
-
static void redrat3_dump_fw_error(struct redrat3_dev *rr3, int code)
{
if (!rr3->transmitting && (code != 0x40))
@@ -265,8 +259,7 @@ static void redrat3_dump_fw_error(struct redrat3_dev *rr3, int code)
/* Codes 0x20 through 0x2f are IR Firmware Errors */
case 0x20:
- pr_cont("Initial signal pulse not long enough "
- "to measure carrier frequency\n");
+ pr_cont("Initial signal pulse not long enough to measure carrier frequency\n");
break;
case 0x21:
pr_cont("Not enough length values allocated for signal\n");
@@ -278,18 +271,15 @@ static void redrat3_dump_fw_error(struct redrat3_dev *rr3, int code)
pr_cont("Too many signal repeats\n");
break;
case 0x28:
- pr_cont("Insufficient memory available for IR signal "
- "data memory allocation\n");
+ pr_cont("Insufficient memory available for IR signal data memory allocation\n");
break;
case 0x29:
- pr_cont("Insufficient memory available "
- "for IrDa signal data memory allocation\n");
+ pr_cont("Insufficient memory available for IrDa signal data memory allocation\n");
break;
/* Codes 0x30 through 0x3f are USB Firmware Errors */
case 0x30:
- pr_cont("Insufficient memory available for bulk "
- "transfer structure\n");
+ pr_cont("Insufficient memory available for bulk transfer structure\n");
break;
/*
@@ -301,8 +291,7 @@ static void redrat3_dump_fw_error(struct redrat3_dev *rr3, int code)
pr_cont("Signal capture has been terminated\n");
break;
case 0x41:
- pr_cont("Attempt to set/get and unknown signal I/O "
- "algorithm parameter\n");
+ pr_cont("Attempt to set/get and unknown signal I/O algorithm parameter\n");
break;
case 0x42:
pr_cont("Signal capture already started\n");
@@ -368,15 +357,18 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3)
unsigned int i, sig_size, single_len, offset, val;
u32 mod_freq;
- if (!rr3) {
- pr_err("%s called with no context!\n", __func__);
- return;
- }
-
dev = rr3->dev;
mod_freq = redrat3_val_to_mod_freq(&rr3->irdata);
dev_dbg(dev, "Got mod_freq of %u\n", mod_freq);
+ if (mod_freq && rr3->wideband) {
+ DEFINE_IR_RAW_EVENT(ev);
+
+ ev.carrier_report = 1;
+ ev.carrier = mod_freq;
+
+ ir_raw_event_store(rr3->rc, &ev);
+ }
/* process each rr3 encoded byte into an int */
sig_size = be16_to_cpu(rr3->irdata.sig_size);
@@ -459,19 +451,31 @@ static int redrat3_enable_detector(struct redrat3_dev *rr3)
return -EIO;
}
- redrat3_issue_async(rr3);
+ ret = usb_submit_urb(rr3->narrow_urb, GFP_KERNEL);
+ if (ret) {
+ dev_err(rr3->dev, "narrow band urb failed: %d", ret);
+ return ret;
+ }
+
+ ret = usb_submit_urb(rr3->wide_urb, GFP_KERNEL);
+ if (ret)
+ dev_err(rr3->dev, "wide band urb failed: %d", ret);
- return 0;
+ return ret;
}
static inline void redrat3_delete(struct redrat3_dev *rr3,
struct usb_device *udev)
{
- usb_kill_urb(rr3->read_urb);
+ usb_kill_urb(rr3->narrow_urb);
+ usb_kill_urb(rr3->wide_urb);
usb_kill_urb(rr3->flash_urb);
- usb_free_urb(rr3->read_urb);
+ usb_kill_urb(rr3->learn_urb);
+ usb_free_urb(rr3->narrow_urb);
+ usb_free_urb(rr3->wide_urb);
usb_free_urb(rr3->flash_urb);
- usb_free_coherent(udev, le16_to_cpu(rr3->ep_in->wMaxPacketSize),
+ usb_free_urb(rr3->learn_urb);
+ usb_free_coherent(udev, le16_to_cpu(rr3->ep_narrow->wMaxPacketSize),
rr3->bulk_in_buf, rr3->dma_in);
kfree(rr3);
@@ -485,10 +489,8 @@ static u32 redrat3_get_timeout(struct redrat3_dev *rr3)
len = sizeof(*tmp);
tmp = kzalloc(len, GFP_KERNEL);
- if (!tmp) {
- dev_warn(rr3->dev, "Memory allocation faillure\n");
+ if (!tmp)
return timeout;
- }
pipe = usb_rcvctrlpipe(rr3->udev, 0);
ret = usb_control_msg(rr3->udev, pipe, RR3_GET_IR_PARAM,
@@ -543,16 +545,14 @@ static void redrat3_reset(struct redrat3_dev *rr3)
struct device *dev = rr3->dev;
int rc, rxpipe, txpipe;
u8 *val;
- int len = sizeof(u8);
+ size_t const len = sizeof(*val);
rxpipe = usb_rcvctrlpipe(udev, 0);
txpipe = usb_sndctrlpipe(udev, 0);
val = kmalloc(len, GFP_KERNEL);
- if (!val) {
- dev_err(dev, "Memory allocation failure\n");
+ if (!val)
return;
- }
*val = 0x01;
rc = usb_control_msg(udev, rxpipe, RR3_RESET,
@@ -590,14 +590,12 @@ static void redrat3_reset(struct redrat3_dev *rr3)
static void redrat3_get_firmware_rev(struct redrat3_dev *rr3)
{
- int rc = 0;
+ int rc;
char *buffer;
- buffer = kzalloc(sizeof(char) * (RR3_FW_VERSION_LEN + 1), GFP_KERNEL);
- if (!buffer) {
- dev_err(rr3->dev, "Memory allocation failure\n");
+ buffer = kcalloc(RR3_FW_VERSION_LEN + 1, sizeof(*buffer), GFP_KERNEL);
+ if (!buffer)
return;
- }
rc = usb_control_msg(rr3->udev, usb_rcvctrlpipe(rr3->udev, 0),
RR3_FW_VERSION,
@@ -704,25 +702,25 @@ out:
/* callback function from USB when async USB request has completed */
static void redrat3_handle_async(struct urb *urb)
{
- struct redrat3_dev *rr3;
+ struct redrat3_dev *rr3 = urb->context;
int ret;
- if (!urb)
- return;
-
- rr3 = urb->context;
- if (!rr3) {
- pr_err("%s called with invalid context!\n", __func__);
- usb_unlink_urb(urb);
- return;
- }
-
switch (urb->status) {
case 0:
ret = redrat3_get_ir_data(rr3, urb->actual_length);
+ if (!ret && rr3->wideband && !rr3->learn_urb->hcpriv) {
+ ret = usb_submit_urb(rr3->learn_urb, GFP_ATOMIC);
+ if (ret)
+ dev_err(rr3->dev, "Failed to submit learning urb: %d",
+ ret);
+ }
+
if (!ret) {
/* no error, prepare to read more */
- redrat3_issue_async(rr3);
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret)
+ dev_err(rr3->dev, "Failed to resubmit urb: %d",
+ ret);
}
break;
@@ -785,11 +783,11 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf,
/* rr3 will disable rc detector on transmit */
rr3->transmitting = true;
- sample_lens = kzalloc(sizeof(int) * RR3_DRIVER_MAXLENS, GFP_KERNEL);
- if (!sample_lens) {
- ret = -ENOMEM;
- goto out;
- }
+ sample_lens = kcalloc(RR3_DRIVER_MAXLENS,
+ sizeof(*sample_lens),
+ GFP_KERNEL);
+ if (!sample_lens)
+ return -ENOMEM;
irdata = kzalloc(sizeof(*irdata), GFP_KERNEL);
if (!irdata) {
@@ -857,8 +855,8 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf,
ret = count;
out:
- kfree(sample_lens);
kfree(irdata);
+ kfree(sample_lens);
rr3->transmitting = false;
/* rr3 re-enables rc detector because it was enabled before */
@@ -882,6 +880,42 @@ static void redrat3_brightness_set(struct led_classdev *led_dev, enum
}
}
+static int redrat3_wideband_receiver(struct rc_dev *rcdev, int enable)
+{
+ struct redrat3_dev *rr3 = rcdev->priv;
+ int ret = 0;
+
+ rr3->wideband = enable != 0;
+
+ if (enable) {
+ ret = usb_submit_urb(rr3->learn_urb, GFP_KERNEL);
+ if (ret)
+ dev_err(rr3->dev, "Failed to submit learning urb: %d",
+ ret);
+ }
+
+ return ret;
+}
+
+static void redrat3_learn_complete(struct urb *urb)
+{
+ struct redrat3_dev *rr3 = urb->context;
+
+ switch (urb->status) {
+ case 0:
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ usb_unlink_urb(urb);
+ return;
+ case -EPIPE:
+ default:
+ dev_err(rr3->dev, "Error: learn urb status = %d", urb->status);
+ break;
+ }
+}
+
static void redrat3_led_complete(struct urb *urb)
{
struct redrat3_dev *rr3 = urb->context;
@@ -908,19 +942,16 @@ static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3)
{
struct device *dev = rr3->dev;
struct rc_dev *rc;
- int ret = -ENODEV;
+ int ret;
u16 prod = le16_to_cpu(rr3->udev->descriptor.idProduct);
rc = rc_allocate_device();
- if (!rc) {
- dev_err(dev, "remote input dev allocation failed\n");
- goto out;
- }
+ if (!rc)
+ return NULL;
- snprintf(rr3->name, sizeof(rr3->name), "RedRat3%s "
- "Infrared Remote Transceiver (%04x:%04x)",
- prod == USB_RR3IIUSB_PRODUCT_ID ? "-II" : "",
- le16_to_cpu(rr3->udev->descriptor.idVendor), prod);
+ snprintf(rr3->name, sizeof(rr3->name),
+ "RedRat3%s Infrared Remote Transceiver",
+ prod == USB_RR3IIUSB_PRODUCT_ID ? "-II" : "");
usb_make_path(rr3->udev, rr3->phys, sizeof(rr3->phys));
@@ -937,6 +968,7 @@ static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3)
rc->s_timeout = redrat3_set_timeout;
rc->tx_ir = redrat3_transmit_ir;
rc->s_tx_carrier = redrat3_set_tx_carrier;
+ rc->s_carrier_report = redrat3_wideband_receiver;
rc->driver_name = DRIVER_NAME;
rc->rx_resolution = US_TO_NS(2);
rc->map_name = RC_MAP_HAUPPAUGE;
@@ -962,7 +994,8 @@ static int redrat3_dev_probe(struct usb_interface *intf,
struct usb_host_interface *uhi;
struct redrat3_dev *rr3;
struct usb_endpoint_descriptor *ep;
- struct usb_endpoint_descriptor *ep_in = NULL;
+ struct usb_endpoint_descriptor *ep_narrow = NULL;
+ struct usb_endpoint_descriptor *ep_wide = NULL;
struct usb_endpoint_descriptor *ep_out = NULL;
u8 addr, attrs;
int pipe, i;
@@ -976,15 +1009,16 @@ static int redrat3_dev_probe(struct usb_interface *intf,
addr = ep->bEndpointAddress;
attrs = ep->bmAttributes;
- if ((ep_in == NULL) &&
- ((addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
+ if (((addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
((attrs & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK)) {
dev_dbg(dev, "found bulk-in endpoint at 0x%02x\n",
ep->bEndpointAddress);
- /* data comes in on 0x82, 0x81 is for other data... */
- if (ep->bEndpointAddress == RR3_BULK_IN_EP_ADDR)
- ep_in = ep;
+ /* data comes in on 0x82, 0x81 is for learning */
+ if (ep->bEndpointAddress == RR3_NARROW_IN_EP_ADDR)
+ ep_narrow = ep;
+ if (ep->bEndpointAddress == RR3_WIDE_IN_EP_ADDR)
+ ep_wide = ep;
}
if ((ep_out == NULL) &&
@@ -997,68 +1031,76 @@ static int redrat3_dev_probe(struct usb_interface *intf,
}
}
- if (!ep_in || !ep_out) {
- dev_err(dev, "Couldn't find both in and out endpoints\n");
+ if (!ep_narrow || !ep_out || !ep_wide) {
+ dev_err(dev, "Couldn't find all endpoints\n");
retval = -ENODEV;
goto no_endpoints;
}
/* allocate memory for our device state and initialize it */
rr3 = kzalloc(sizeof(*rr3), GFP_KERNEL);
- if (rr3 == NULL) {
- dev_err(dev, "Memory allocation failure\n");
+ if (!rr3)
goto no_endpoints;
- }
rr3->dev = &intf->dev;
+ rr3->ep_narrow = ep_narrow;
+ rr3->ep_out = ep_out;
+ rr3->udev = udev;
/* set up bulk-in endpoint */
- rr3->read_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!rr3->read_urb)
- goto error;
+ rr3->narrow_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!rr3->narrow_urb)
+ goto redrat_free;
- rr3->ep_in = ep_in;
- rr3->bulk_in_buf = usb_alloc_coherent(udev,
- le16_to_cpu(ep_in->wMaxPacketSize), GFP_KERNEL, &rr3->dma_in);
- if (!rr3->bulk_in_buf) {
- dev_err(dev, "Read buffer allocation failure\n");
- goto error;
- }
-
- pipe = usb_rcvbulkpipe(udev, ep_in->bEndpointAddress);
- usb_fill_bulk_urb(rr3->read_urb, udev, pipe, rr3->bulk_in_buf,
- le16_to_cpu(ep_in->wMaxPacketSize), redrat3_handle_async, rr3);
- rr3->read_urb->transfer_dma = rr3->dma_in;
- rr3->read_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ rr3->wide_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!rr3->wide_urb)
+ goto redrat_free;
- rr3->ep_out = ep_out;
- rr3->udev = udev;
+ rr3->bulk_in_buf = usb_alloc_coherent(udev,
+ le16_to_cpu(ep_narrow->wMaxPacketSize),
+ GFP_KERNEL, &rr3->dma_in);
+ if (!rr3->bulk_in_buf)
+ goto redrat_free;
+
+ pipe = usb_rcvbulkpipe(udev, ep_narrow->bEndpointAddress);
+ usb_fill_bulk_urb(rr3->narrow_urb, udev, pipe, rr3->bulk_in_buf,
+ le16_to_cpu(ep_narrow->wMaxPacketSize),
+ redrat3_handle_async, rr3);
+ rr3->narrow_urb->transfer_dma = rr3->dma_in;
+ rr3->narrow_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ pipe = usb_rcvbulkpipe(udev, ep_wide->bEndpointAddress);
+ usb_fill_bulk_urb(rr3->wide_urb, udev, pipe, rr3->bulk_in_buf,
+ le16_to_cpu(ep_narrow->wMaxPacketSize),
+ redrat3_handle_async, rr3);
+ rr3->wide_urb->transfer_dma = rr3->dma_in;
+ rr3->wide_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
redrat3_reset(rr3);
redrat3_get_firmware_rev(rr3);
- /* might be all we need to do? */
- retval = redrat3_enable_detector(rr3);
- if (retval < 0)
- goto error;
-
/* default.. will get overridden by any sends with a freq defined */
rr3->carrier = 38000;
- /* led control */
- rr3->led.name = "redrat3:red:feedback";
- rr3->led.default_trigger = "rc-feedback";
- rr3->led.brightness_set = redrat3_brightness_set;
- retval = led_classdev_register(&intf->dev, &rr3->led);
- if (retval)
- goto error;
-
atomic_set(&rr3->flash, 0);
rr3->flash_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!rr3->flash_urb) {
- retval = -ENOMEM;
- goto led_free_error;
- }
+ if (!rr3->flash_urb)
+ goto redrat_free;
+
+ /* learn urb */
+ rr3->learn_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!rr3->learn_urb)
+ goto redrat_free;
+
+ /* setup packet is 'c0 b2 0000 0000 0001' */
+ rr3->learn_control.bRequestType = 0xc0;
+ rr3->learn_control.bRequest = RR3_MODSIG_CAPTURE;
+ rr3->learn_control.wLength = cpu_to_le16(1);
+
+ usb_fill_control_urb(rr3->learn_urb, udev, usb_rcvctrlpipe(udev, 0),
+ (unsigned char *)&rr3->learn_control,
+ &rr3->learn_buf, sizeof(rr3->learn_buf),
+ redrat3_learn_complete, rr3);
/* setup packet is 'c0 b9 0000 0000 0001' */
rr3->flash_control.bRequestType = 0xc0;
@@ -1070,25 +1112,36 @@ static int redrat3_dev_probe(struct usb_interface *intf,
&rr3->flash_in_buf, sizeof(rr3->flash_in_buf),
redrat3_led_complete, rr3);
+ /* led control */
+ rr3->led.name = "redrat3:red:feedback";
+ rr3->led.default_trigger = "rc-feedback";
+ rr3->led.brightness_set = redrat3_brightness_set;
+ retval = led_classdev_register(&intf->dev, &rr3->led);
+ if (retval)
+ goto redrat_free;
+
rr3->rc = redrat3_init_rc_dev(rr3);
if (!rr3->rc) {
retval = -ENOMEM;
- goto led_free_error;
+ goto led_free;
}
+ /* might be all we need to do? */
+ retval = redrat3_enable_detector(rr3);
+ if (retval < 0)
+ goto led_free;
+
/* we can register the device now, as it is ready */
usb_set_intfdata(intf, rr3);
return 0;
-led_free_error:
+led_free:
led_classdev_unregister(&rr3->led);
-error:
+redrat_free:
redrat3_delete(rr3, rr3->udev);
no_endpoints:
- dev_err(dev, "%s: retval = %x", __func__, retval);
-
return retval;
}
@@ -1097,9 +1150,6 @@ static void redrat3_dev_disconnect(struct usb_interface *intf)
struct usb_device *udev = interface_to_usbdev(intf);
struct redrat3_dev *rr3 = usb_get_intfdata(intf);
- if (!rr3)
- return;
-
usb_set_intfdata(intf, NULL);
rc_unregister_device(rr3->rc);
led_classdev_unregister(&rr3->led);
@@ -1111,7 +1161,8 @@ static int redrat3_dev_suspend(struct usb_interface *intf, pm_message_t message)
struct redrat3_dev *rr3 = usb_get_intfdata(intf);
led_classdev_suspend(&rr3->led);
- usb_kill_urb(rr3->read_urb);
+ usb_kill_urb(rr3->narrow_urb);
+ usb_kill_urb(rr3->wide_urb);
usb_kill_urb(rr3->flash_urb);
return 0;
}
@@ -1120,7 +1171,9 @@ static int redrat3_dev_resume(struct usb_interface *intf)
{
struct redrat3_dev *rr3 = usb_get_intfdata(intf);
- if (usb_submit_urb(rr3->read_urb, GFP_ATOMIC))
+ if (usb_submit_urb(rr3->narrow_urb, GFP_ATOMIC))
+ return -EIO;
+ if (usb_submit_urb(rr3->wide_urb, GFP_ATOMIC))
return -EIO;
led_classdev_resume(&rr3->led);
return 0;
diff --git a/drivers/media/rc/serial_ir.c b/drivers/media/rc/serial_ir.c
new file mode 100644
index 000000000000..436bd58b5f05
--- /dev/null
+++ b/drivers/media/rc/serial_ir.c
@@ -0,0 +1,844 @@
+/*
+ * serial_ir.c
+ *
+ * serial_ir - Device driver that records pulse- and pause-lengths
+ * (space-lengths) between DDCD event on a serial port.
+ *
+ * Copyright (C) 1996,97 Ralph Metzler <rjkm@thp.uni-koeln.de>
+ * Copyright (C) 1998 Trent Piepho <xyzzy@u.washington.edu>
+ * Copyright (C) 1998 Ben Pfaff <blp@gnu.org>
+ * Copyright (C) 1999 Christoph Bartelmus <lirc@bartelmus.de>
+ * Copyright (C) 2007 Andrei Tanas <andrei@tanas.ca> (suspend/resume support)
+ * Copyright (C) 2016 Sean Young <sean@mess.org> (port to rc-core)
+ * 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/serial_reg.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <media/rc-core.h>
+
+struct serial_ir_hw {
+ int signal_pin;
+ int signal_pin_change;
+ u8 on;
+ u8 off;
+ unsigned set_send_carrier:1;
+ unsigned set_duty_cycle:1;
+ void (*send_pulse)(unsigned int length, ktime_t edge);
+ void (*send_space)(void);
+ spinlock_t lock;
+};
+
+#define IR_HOMEBREW 0
+#define IR_IRDEO 1
+#define IR_IRDEO_REMOTE 2
+#define IR_ANIMAX 3
+#define IR_IGOR 4
+
+/* module parameters */
+static int type;
+static int io;
+static int irq;
+static bool iommap;
+static int ioshift;
+static bool softcarrier = true;
+static bool share_irq;
+static int sense = -1; /* -1 = auto, 0 = active high, 1 = active low */
+static bool txsense; /* 0 = active high, 1 = active low */
+
+/* forward declarations */
+static void send_pulse_irdeo(unsigned int length, ktime_t edge);
+static void send_space_irdeo(void);
+#ifdef CONFIG_IR_SERIAL_TRANSMITTER
+static void send_pulse_homebrew(unsigned int length, ktime_t edge);
+static void send_space_homebrew(void);
+#endif
+
+static struct serial_ir_hw hardware[] = {
+ [IR_HOMEBREW] = {
+ .lock = __SPIN_LOCK_UNLOCKED(hardware[IR_HOMEBREW].lock),
+ .signal_pin = UART_MSR_DCD,
+ .signal_pin_change = UART_MSR_DDCD,
+ .on = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR),
+ .off = (UART_MCR_RTS | UART_MCR_OUT2),
+#ifdef CONFIG_IR_SERIAL_TRANSMITTER
+ .send_pulse = send_pulse_homebrew,
+ .send_space = send_space_homebrew,
+ .set_send_carrier = true,
+ .set_duty_cycle = true,
+#endif
+ },
+
+ [IR_IRDEO] = {
+ .lock = __SPIN_LOCK_UNLOCKED(hardware[IR_IRDEO].lock),
+ .signal_pin = UART_MSR_DSR,
+ .signal_pin_change = UART_MSR_DDSR,
+ .on = UART_MCR_OUT2,
+ .off = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2),
+ .send_pulse = send_pulse_irdeo,
+ .send_space = send_space_irdeo,
+ .set_duty_cycle = true,
+ },
+
+ [IR_IRDEO_REMOTE] = {
+ .lock = __SPIN_LOCK_UNLOCKED(hardware[IR_IRDEO_REMOTE].lock),
+ .signal_pin = UART_MSR_DSR,
+ .signal_pin_change = UART_MSR_DDSR,
+ .on = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2),
+ .off = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2),
+ .send_pulse = send_pulse_irdeo,
+ .send_space = send_space_irdeo,
+ .set_duty_cycle = true,
+ },
+
+ [IR_ANIMAX] = {
+ .lock = __SPIN_LOCK_UNLOCKED(hardware[IR_ANIMAX].lock),
+ .signal_pin = UART_MSR_DCD,
+ .signal_pin_change = UART_MSR_DDCD,
+ .on = 0,
+ .off = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2),
+ },
+
+ [IR_IGOR] = {
+ .lock = __SPIN_LOCK_UNLOCKED(hardware[IR_IGOR].lock),
+ .signal_pin = UART_MSR_DSR,
+ .signal_pin_change = UART_MSR_DDSR,
+ .on = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR),
+ .off = (UART_MCR_RTS | UART_MCR_OUT2),
+#ifdef CONFIG_IR_SERIAL_TRANSMITTER
+ .send_pulse = send_pulse_homebrew,
+ .send_space = send_space_homebrew,
+ .set_send_carrier = true,
+ .set_duty_cycle = true,
+#endif
+ },
+};
+
+#define RS_ISR_PASS_LIMIT 256
+
+struct serial_ir {
+ ktime_t lastkt;
+ struct rc_dev *rcdev;
+ struct platform_device *pdev;
+
+ unsigned int freq;
+ unsigned int duty_cycle;
+
+ unsigned int pulse_width, space_width;
+};
+
+static struct serial_ir serial_ir;
+
+/* fetch serial input packet (1 byte) from register offset */
+static u8 sinp(int offset)
+{
+ if (iommap)
+ /* the register is memory-mapped */
+ offset <<= ioshift;
+
+ return inb(io + offset);
+}
+
+/* write serial output packet (1 byte) of value to register offset */
+static void soutp(int offset, u8 value)
+{
+ if (iommap)
+ /* the register is memory-mapped */
+ offset <<= ioshift;
+
+ outb(value, io + offset);
+}
+
+static void on(void)
+{
+ if (txsense)
+ soutp(UART_MCR, hardware[type].off);
+ else
+ soutp(UART_MCR, hardware[type].on);
+}
+
+static void off(void)
+{
+ if (txsense)
+ soutp(UART_MCR, hardware[type].on);
+ else
+ soutp(UART_MCR, hardware[type].off);
+}
+
+static void init_timing_params(unsigned int new_duty_cycle,
+ unsigned int new_freq)
+{
+ serial_ir.duty_cycle = new_duty_cycle;
+ serial_ir.freq = new_freq;
+
+ serial_ir.pulse_width = DIV_ROUND_CLOSEST(
+ new_duty_cycle * NSEC_PER_SEC, new_freq * 100l);
+ serial_ir.space_width = DIV_ROUND_CLOSEST(
+ (100l - new_duty_cycle) * NSEC_PER_SEC, new_freq * 100l);
+}
+
+static void send_pulse_irdeo(unsigned int length, ktime_t target)
+{
+ long rawbits;
+ int i;
+ unsigned char output;
+ unsigned char chunk, shifted;
+
+ /* how many bits have to be sent ? */
+ rawbits = length * 1152 / 10000;
+ if (serial_ir.duty_cycle > 50)
+ chunk = 3;
+ else
+ chunk = 1;
+ for (i = 0, output = 0x7f; rawbits > 0; rawbits -= 3) {
+ shifted = chunk << (i * 3);
+ shifted >>= 1;
+ output &= (~shifted);
+ i++;
+ if (i == 3) {
+ soutp(UART_TX, output);
+ while (!(sinp(UART_LSR) & UART_LSR_THRE))
+ ;
+ output = 0x7f;
+ i = 0;
+ }
+ }
+ if (i != 0) {
+ soutp(UART_TX, output);
+ while (!(sinp(UART_LSR) & UART_LSR_TEMT))
+ ;
+ }
+}
+
+static void send_space_irdeo(void)
+{
+}
+
+#ifdef CONFIG_IR_SERIAL_TRANSMITTER
+static void send_pulse_homebrew_softcarrier(unsigned int length, ktime_t edge)
+{
+ ktime_t now, target = ktime_add_us(edge, length);
+ /*
+ * delta should never exceed 4 seconds and on m68k
+ * ndelay(s64) does not compile; so use s32 rather than s64.
+ */
+ s32 delta;
+
+ for (;;) {
+ now = ktime_get();
+ if (ktime_compare(now, target) >= 0)
+ break;
+ on();
+ edge = ktime_add_ns(edge, serial_ir.pulse_width);
+ delta = ktime_to_ns(ktime_sub(edge, now));
+ if (delta > 0)
+ ndelay(delta);
+ now = ktime_get();
+ off();
+ if (ktime_compare(now, target) >= 0)
+ break;
+ edge = ktime_add_ns(edge, serial_ir.space_width);
+ delta = ktime_to_ns(ktime_sub(edge, now));
+ if (delta > 0)
+ ndelay(delta);
+ }
+}
+
+static void send_pulse_homebrew(unsigned int length, ktime_t edge)
+{
+ if (softcarrier)
+ send_pulse_homebrew_softcarrier(length, edge);
+ else
+ on();
+}
+
+static void send_space_homebrew(void)
+{
+ off();
+}
+#endif
+
+static void frbwrite(unsigned int l, bool is_pulse)
+{
+ /* simple noise filter */
+ static unsigned int ptr, pulse, space;
+ DEFINE_IR_RAW_EVENT(ev);
+
+ if (ptr > 0 && is_pulse) {
+ pulse += l;
+ if (pulse > 250000) {
+ ev.duration = space;
+ ev.pulse = false;
+ ir_raw_event_store_with_filter(serial_ir.rcdev, &ev);
+ ev.duration = pulse;
+ ev.pulse = true;
+ ir_raw_event_store_with_filter(serial_ir.rcdev, &ev);
+ ptr = 0;
+ pulse = 0;
+ }
+ return;
+ }
+ if (!is_pulse) {
+ if (ptr == 0) {
+ if (l > 20000000) {
+ space = l;
+ ptr++;
+ return;
+ }
+ } else {
+ if (l > 20000000) {
+ space += pulse;
+ if (space > IR_MAX_DURATION)
+ space = IR_MAX_DURATION;
+ space += l;
+ if (space > IR_MAX_DURATION)
+ space = IR_MAX_DURATION;
+ pulse = 0;
+ return;
+ }
+
+ ev.duration = space;
+ ev.pulse = false;
+ ir_raw_event_store_with_filter(serial_ir.rcdev, &ev);
+ ev.duration = pulse;
+ ev.pulse = true;
+ ir_raw_event_store_with_filter(serial_ir.rcdev, &ev);
+ ptr = 0;
+ pulse = 0;
+ }
+ }
+
+ ev.duration = l;
+ ev.pulse = is_pulse;
+ ir_raw_event_store_with_filter(serial_ir.rcdev, &ev);
+}
+
+static irqreturn_t serial_ir_irq_handler(int i, void *blah)
+{
+ ktime_t kt;
+ int counter, dcd;
+ u8 status;
+ ktime_t delkt;
+ unsigned int data;
+ static int last_dcd = -1;
+
+ if ((sinp(UART_IIR) & UART_IIR_NO_INT)) {
+ /* not our interrupt */
+ return IRQ_NONE;
+ }
+
+ counter = 0;
+ do {
+ counter++;
+ status = sinp(UART_MSR);
+ if (counter > RS_ISR_PASS_LIMIT) {
+ dev_err(&serial_ir.pdev->dev, "Trapped in interrupt");
+ break;
+ }
+ if ((status & hardware[type].signal_pin_change) &&
+ sense != -1) {
+ /* get current time */
+ kt = ktime_get();
+
+ /*
+ * The driver needs to know if your receiver is
+ * active high or active low, or the space/pulse
+ * sense could be inverted.
+ */
+
+ /* calc time since last interrupt in nanoseconds */
+ dcd = (status & hardware[type].signal_pin) ? 1 : 0;
+
+ if (dcd == last_dcd) {
+ dev_err(&serial_ir.pdev->dev,
+ "ignoring spike: %d %d %lldns %lldns\n",
+ dcd, sense, ktime_to_ns(kt),
+ ktime_to_ns(serial_ir.lastkt));
+ continue;
+ }
+
+ delkt = ktime_sub(kt, serial_ir.lastkt);
+ if (ktime_compare(delkt, ktime_set(15, 0)) > 0) {
+ data = IR_MAX_DURATION; /* really long time */
+ if (!(dcd ^ sense)) {
+ /* sanity check */
+ dev_err(&serial_ir.pdev->dev,
+ "dcd unexpected: %d %d %lldns %lldns\n",
+ dcd, sense, ktime_to_ns(kt),
+ ktime_to_ns(serial_ir.lastkt));
+ /*
+ * detecting pulse while this
+ * MUST be a space!
+ */
+ sense = sense ? 0 : 1;
+ }
+ } else {
+ data = ktime_to_ns(delkt);
+ }
+ frbwrite(data, !(dcd ^ sense));
+ serial_ir.lastkt = kt;
+ last_dcd = dcd;
+ ir_raw_event_handle(serial_ir.rcdev);
+ }
+ } while (!(sinp(UART_IIR) & UART_IIR_NO_INT)); /* still pending ? */
+ return IRQ_HANDLED;
+}
+
+static int hardware_init_port(void)
+{
+ u8 scratch, scratch2, scratch3;
+
+ /*
+ * This is a simple port existence test, borrowed from the autoconfig
+ * function in drivers/tty/serial/8250/8250_port.c
+ */
+ scratch = sinp(UART_IER);
+ soutp(UART_IER, 0);
+#ifdef __i386__
+ outb(0xff, 0x080);
+#endif
+ scratch2 = sinp(UART_IER) & 0x0f;
+ soutp(UART_IER, 0x0f);
+#ifdef __i386__
+ outb(0x00, 0x080);
+#endif
+ scratch3 = sinp(UART_IER) & 0x0f;
+ soutp(UART_IER, scratch);
+ if (scratch2 != 0 || scratch3 != 0x0f) {
+ /* we fail, there's nothing here */
+ pr_err("port existence test failed, cannot continue\n");
+ return -ENODEV;
+ }
+
+ /* Set DLAB 0. */
+ soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
+
+ /* First of all, disable all interrupts */
+ soutp(UART_IER, sinp(UART_IER) &
+ (~(UART_IER_MSI | UART_IER_RLSI | UART_IER_THRI | UART_IER_RDI)));
+
+ /* Clear registers. */
+ sinp(UART_LSR);
+ sinp(UART_RX);
+ sinp(UART_IIR);
+ sinp(UART_MSR);
+
+ /* Set line for power source */
+ off();
+
+ /* Clear registers again to be sure. */
+ sinp(UART_LSR);
+ sinp(UART_RX);
+ sinp(UART_IIR);
+ sinp(UART_MSR);
+
+ switch (type) {
+ case IR_IRDEO:
+ case IR_IRDEO_REMOTE:
+ /* setup port to 7N1 @ 115200 Baud */
+ /* 7N1+start = 9 bits at 115200 ~ 3 bits at 38kHz */
+
+ /* Set DLAB 1. */
+ soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB);
+ /* Set divisor to 1 => 115200 Baud */
+ soutp(UART_DLM, 0);
+ soutp(UART_DLL, 1);
+ /* Set DLAB 0 + 7N1 */
+ soutp(UART_LCR, UART_LCR_WLEN7);
+ /* THR interrupt already disabled at this point */
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int serial_ir_probe(struct platform_device *dev)
+{
+ int i, nlow, nhigh, result;
+
+ result = devm_request_irq(&dev->dev, irq, serial_ir_irq_handler,
+ share_irq ? IRQF_SHARED : 0,
+ KBUILD_MODNAME, &hardware);
+ if (result < 0) {
+ if (result == -EBUSY)
+ dev_err(&dev->dev, "IRQ %d busy\n", irq);
+ else if (result == -EINVAL)
+ dev_err(&dev->dev, "Bad irq number or handler\n");
+ return result;
+ }
+
+ /* Reserve io region. */
+ if ((iommap &&
+ (devm_request_mem_region(&dev->dev, iommap, 8 << ioshift,
+ KBUILD_MODNAME) == NULL)) ||
+ (!iommap && (devm_request_region(&dev->dev, io, 8,
+ KBUILD_MODNAME) == NULL))) {
+ dev_err(&dev->dev, "port %04x already in use\n", io);
+ dev_warn(&dev->dev, "use 'setserial /dev/ttySX uart none'\n");
+ dev_warn(&dev->dev,
+ "or compile the serial port driver as module and\n");
+ dev_warn(&dev->dev, "make sure this module is loaded first\n");
+ return -EBUSY;
+ }
+
+ result = hardware_init_port();
+ if (result < 0)
+ return result;
+
+ /* Initialize pulse/space widths */
+ init_timing_params(50, 38000);
+
+ /* If pin is high, then this must be an active low receiver. */
+ if (sense == -1) {
+ /* wait 1/2 sec for the power supply */
+ msleep(500);
+
+ /*
+ * probe 9 times every 0.04s, collect "votes" for
+ * active high/low
+ */
+ nlow = 0;
+ nhigh = 0;
+ for (i = 0; i < 9; i++) {
+ if (sinp(UART_MSR) & hardware[type].signal_pin)
+ nlow++;
+ else
+ nhigh++;
+ msleep(40);
+ }
+ sense = nlow >= nhigh ? 1 : 0;
+ dev_info(&dev->dev, "auto-detected active %s receiver\n",
+ sense ? "low" : "high");
+ } else
+ dev_info(&dev->dev, "Manually using active %s receiver\n",
+ sense ? "low" : "high");
+
+ dev_dbg(&dev->dev, "Interrupt %d, port %04x obtained\n", irq, io);
+ return 0;
+}
+
+static int serial_ir_open(struct rc_dev *rcdev)
+{
+ unsigned long flags;
+
+ /* initialize timestamp */
+ serial_ir.lastkt = ktime_get();
+
+ spin_lock_irqsave(&hardware[type].lock, flags);
+
+ /* Set DLAB 0. */
+ soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
+
+ soutp(UART_IER, sinp(UART_IER) | UART_IER_MSI);
+
+ spin_unlock_irqrestore(&hardware[type].lock, flags);
+
+ return 0;
+}
+
+static void serial_ir_close(struct rc_dev *rcdev)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&hardware[type].lock, flags);
+
+ /* Set DLAB 0. */
+ soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
+
+ /* First of all, disable all interrupts */
+ soutp(UART_IER, sinp(UART_IER) &
+ (~(UART_IER_MSI | UART_IER_RLSI | UART_IER_THRI | UART_IER_RDI)));
+ spin_unlock_irqrestore(&hardware[type].lock, flags);
+}
+
+static int serial_ir_tx(struct rc_dev *dev, unsigned int *txbuf,
+ unsigned int count)
+{
+ unsigned long flags;
+ ktime_t edge;
+ s64 delta;
+ int i;
+
+ spin_lock_irqsave(&hardware[type].lock, flags);
+ if (type == IR_IRDEO) {
+ /* DTR, RTS down */
+ on();
+ }
+
+ edge = ktime_get();
+ for (i = 0; i < count; i++) {
+ if (i % 2)
+ hardware[type].send_space();
+ else
+ hardware[type].send_pulse(txbuf[i], edge);
+
+ edge = ktime_add_us(edge, txbuf[i]);
+ delta = ktime_us_delta(edge, ktime_get());
+ if (delta > 25) {
+ spin_unlock_irqrestore(&hardware[type].lock, flags);
+ usleep_range(delta - 25, delta + 25);
+ spin_lock_irqsave(&hardware[type].lock, flags);
+ } else if (delta > 0) {
+ udelay(delta);
+ }
+ }
+ off();
+ spin_unlock_irqrestore(&hardware[type].lock, flags);
+ return count;
+}
+
+static int serial_ir_tx_duty_cycle(struct rc_dev *dev, u32 cycle)
+{
+ init_timing_params(cycle, serial_ir.freq);
+ return 0;
+}
+
+static int serial_ir_tx_carrier(struct rc_dev *dev, u32 carrier)
+{
+ if (carrier > 500000 || carrier < 20000)
+ return -EINVAL;
+
+ init_timing_params(serial_ir.duty_cycle, carrier);
+ return 0;
+}
+
+static int serial_ir_suspend(struct platform_device *dev,
+ pm_message_t state)
+{
+ /* Set DLAB 0. */
+ soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
+
+ /* Disable all interrupts */
+ soutp(UART_IER, sinp(UART_IER) &
+ (~(UART_IER_MSI | UART_IER_RLSI | UART_IER_THRI | UART_IER_RDI)));
+
+ /* Clear registers. */
+ sinp(UART_LSR);
+ sinp(UART_RX);
+ sinp(UART_IIR);
+ sinp(UART_MSR);
+
+ return 0;
+}
+
+static int serial_ir_resume(struct platform_device *dev)
+{
+ unsigned long flags;
+ int result;
+
+ result = hardware_init_port();
+ if (result < 0)
+ return result;
+
+ spin_lock_irqsave(&hardware[type].lock, flags);
+ /* Enable Interrupt */
+ serial_ir.lastkt = ktime_get();
+ soutp(UART_IER, sinp(UART_IER) | UART_IER_MSI);
+ off();
+
+ spin_unlock_irqrestore(&hardware[type].lock, flags);
+
+ return 0;
+}
+
+static struct platform_driver serial_ir_driver = {
+ .probe = serial_ir_probe,
+ .suspend = serial_ir_suspend,
+ .resume = serial_ir_resume,
+ .driver = {
+ .name = "serial_ir",
+ },
+};
+
+static int __init serial_ir_init(void)
+{
+ int result;
+
+ result = platform_driver_register(&serial_ir_driver);
+ if (result)
+ return result;
+
+ serial_ir.pdev = platform_device_alloc("serial_ir", 0);
+ if (!serial_ir.pdev) {
+ result = -ENOMEM;
+ goto exit_driver_unregister;
+ }
+
+ result = platform_device_add(serial_ir.pdev);
+ if (result)
+ goto exit_device_put;
+
+ return 0;
+
+exit_device_put:
+ platform_device_put(serial_ir.pdev);
+exit_driver_unregister:
+ platform_driver_unregister(&serial_ir_driver);
+ return result;
+}
+
+static void serial_ir_exit(void)
+{
+ platform_device_unregister(serial_ir.pdev);
+ platform_driver_unregister(&serial_ir_driver);
+}
+
+static int __init serial_ir_init_module(void)
+{
+ struct rc_dev *rcdev;
+ int result;
+
+ switch (type) {
+ case IR_HOMEBREW:
+ case IR_IRDEO:
+ case IR_IRDEO_REMOTE:
+ case IR_ANIMAX:
+ case IR_IGOR:
+ /* if nothing specified, use ttyS0/com1 and irq 4 */
+ io = io ? io : 0x3f8;
+ irq = irq ? irq : 4;
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (!softcarrier) {
+ switch (type) {
+ case IR_HOMEBREW:
+ case IR_IGOR:
+ hardware[type].set_send_carrier = false;
+ hardware[type].set_duty_cycle = false;
+ break;
+ }
+ }
+
+ /* make sure sense is either -1, 0, or 1 */
+ if (sense != -1)
+ sense = !!sense;
+
+ result = serial_ir_init();
+ if (result)
+ return result;
+
+ rcdev = devm_rc_allocate_device(&serial_ir.pdev->dev);
+ if (!rcdev) {
+ result = -ENOMEM;
+ goto serial_cleanup;
+ }
+
+ if (hardware[type].send_pulse && hardware[type].send_space)
+ rcdev->tx_ir = serial_ir_tx;
+ if (hardware[type].set_send_carrier)
+ rcdev->s_tx_carrier = serial_ir_tx_carrier;
+ if (hardware[type].set_duty_cycle)
+ rcdev->s_tx_duty_cycle = serial_ir_tx_duty_cycle;
+
+ switch (type) {
+ case IR_HOMEBREW:
+ rcdev->input_name = "Serial IR type home-brew";
+ break;
+ case IR_IRDEO:
+ rcdev->input_name = "Serial IR type IRdeo";
+ break;
+ case IR_IRDEO_REMOTE:
+ rcdev->input_name = "Serial IR type IRdeo remote";
+ break;
+ case IR_ANIMAX:
+ rcdev->input_name = "Serial IR type AnimaX";
+ break;
+ case IR_IGOR:
+ rcdev->input_name = "Serial IR type IgorPlug";
+ break;
+ }
+
+ rcdev->input_phys = KBUILD_MODNAME "/input0";
+ rcdev->input_id.bustype = BUS_HOST;
+ rcdev->input_id.vendor = 0x0001;
+ rcdev->input_id.product = 0x0001;
+ rcdev->input_id.version = 0x0100;
+ rcdev->open = serial_ir_open;
+ rcdev->close = serial_ir_close;
+ rcdev->dev.parent = &serial_ir.pdev->dev;
+ rcdev->driver_type = RC_DRIVER_IR_RAW;
+ rcdev->allowed_protocols = RC_BIT_ALL;
+ rcdev->driver_name = KBUILD_MODNAME;
+ rcdev->map_name = RC_MAP_RC6_MCE;
+ rcdev->timeout = IR_DEFAULT_TIMEOUT;
+ rcdev->rx_resolution = 250000;
+
+ serial_ir.rcdev = rcdev;
+
+ result = rc_register_device(rcdev);
+
+ if (!result)
+ return 0;
+serial_cleanup:
+ serial_ir_exit();
+ return result;
+}
+
+static void __exit serial_ir_exit_module(void)
+{
+ rc_unregister_device(serial_ir.rcdev);
+ serial_ir_exit();
+}
+
+module_init(serial_ir_init_module);
+module_exit(serial_ir_exit_module);
+
+MODULE_DESCRIPTION("Infra-red receiver driver for serial ports.");
+MODULE_AUTHOR("Ralph Metzler, Trent Piepho, Ben Pfaff, Christoph Bartelmus, Andrei Tanas");
+MODULE_LICENSE("GPL");
+
+module_param(type, int, 0444);
+MODULE_PARM_DESC(type, "Hardware type (0 = home-brew, 1 = IRdeo, 2 = IRdeo Remote, 3 = AnimaX, 4 = IgorPlug");
+
+module_param(io, int, 0444);
+MODULE_PARM_DESC(io, "I/O address base (0x3f8 or 0x2f8)");
+
+/* some architectures (e.g. intel xscale) have memory mapped registers */
+module_param(iommap, bool, 0444);
+MODULE_PARM_DESC(iommap, "physical base for memory mapped I/O (0 = no memory mapped io)");
+
+/*
+ * some architectures (e.g. intel xscale) align the 8bit serial registers
+ * on 32bit word boundaries.
+ * See linux-kernel/drivers/tty/serial/8250/8250.c serial_in()/out()
+ */
+module_param(ioshift, int, 0444);
+MODULE_PARM_DESC(ioshift, "shift I/O register offset (0 = no shift)");
+
+module_param(irq, int, 0444);
+MODULE_PARM_DESC(irq, "Interrupt (4 or 3)");
+
+module_param(share_irq, bool, 0444);
+MODULE_PARM_DESC(share_irq, "Share interrupts (0 = off, 1 = on)");
+
+module_param(sense, int, 0444);
+MODULE_PARM_DESC(sense, "Override autodetection of IR receiver circuit (0 = active high, 1 = active low )");
+
+#ifdef CONFIG_IR_SERIAL_TRANSMITTER
+module_param(txsense, bool, 0444);
+MODULE_PARM_DESC(txsense, "Sense of transmitter circuit (0 = active high, 1 = active low )");
+#endif
+
+module_param(softcarrier, bool, 0444);
+MODULE_PARM_DESC(softcarrier, "Software carrier (0 = off, 1 = on, default on)");
diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
index 4004260a7c69..53f9b0af358a 100644
--- a/drivers/media/rc/streamzap.c
+++ b/drivers/media/rc/streamzap.c
@@ -297,8 +297,7 @@ static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz)
goto out;
}
- snprintf(sz->name, sizeof(sz->name), "Streamzap PC Remote Infrared "
- "Receiver (%04x:%04x)",
+ snprintf(sz->name, sizeof(sz->name), "Streamzap PC Remote Infrared Receiver (%04x:%04x)",
le16_to_cpu(sz->usbdev->descriptor.idVendor),
le16_to_cpu(sz->usbdev->descriptor.idProduct));
usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys));
@@ -364,15 +363,15 @@ static int streamzap_probe(struct usb_interface *intf,
sz->endpoint = &(iface_host->endpoint[0].desc);
if (!usb_endpoint_dir_in(sz->endpoint)) {
- dev_err(&intf->dev, "%s: endpoint doesn't match input device "
- "02%02x\n", __func__, sz->endpoint->bEndpointAddress);
+ dev_err(&intf->dev, "%s: endpoint doesn't match input device 02%02x\n",
+ __func__, sz->endpoint->bEndpointAddress);
retval = -ENODEV;
goto free_sz;
}
if (!usb_endpoint_xfer_int(sz->endpoint)) {
- dev_err(&intf->dev, "%s: endpoint attributes don't match xfer "
- "02%02x\n", __func__, sz->endpoint->bmAttributes);
+ dev_err(&intf->dev, "%s: endpoint attributes don't match xfer 02%02x\n",
+ __func__, sz->endpoint->bmAttributes);
retval = -ENODEV;
goto free_sz;
}
diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c
index 95ae60e659a1..78491ed48d92 100644
--- a/drivers/media/rc/winbond-cir.c
+++ b/drivers/media/rc/winbond-cir.c
@@ -227,8 +227,7 @@ struct wbcir_data {
static enum wbcir_protocol protocol = IR_PROTOCOL_RC6;
module_param(protocol, uint, 0444);
-MODULE_PARM_DESC(protocol, "IR protocol to use for the power-on command "
- "(0 = RC5, 1 = NEC, 2 = RC6A, default)");
+MODULE_PARM_DESC(protocol, "IR protocol to use for the power-on command (0 = RC5, 1 = NEC, 2 = RC6A, default)");
static bool invert; /* default = 0 */
module_param(invert, bool, 0444);
@@ -244,8 +243,7 @@ MODULE_PARM_DESC(wake_sc, "Scancode of the power-on IR command");
static unsigned int wake_rc6mode = 6;
module_param(wake_rc6mode, uint, 0644);
-MODULE_PARM_DESC(wake_rc6mode, "RC6 mode for the power-on command "
- "(0 = 0, 6 = 6A, default)");
+MODULE_PARM_DESC(wake_rc6mode, "RC6 mode for the power-on command (0 = 0, 6 = 6A, default)");
@@ -660,7 +658,7 @@ wbcir_tx(struct rc_dev *dev, unsigned *b, unsigned count)
unsigned i;
unsigned long flags;
- buf = kmalloc(count * sizeof(*b), GFP_KERNEL);
+ buf = kmalloc_array(count, sizeof(*b), GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -1050,8 +1048,7 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
goto exit_free_data;
}
- dev_dbg(&device->dev, "Found device "
- "(w: 0x%lX, e: 0x%lX, s: 0x%lX, i: %u)\n",
+ dev_dbg(&device->dev, "Found device (w: 0x%lX, e: 0x%lX, s: 0x%lX, i: %u)\n",
data->wbase, data->ebase, data->sbase, data->irq);
data->led.name = "cir::activity";
@@ -1188,7 +1185,7 @@ static const struct pnp_device_id wbcir_ids[] = {
MODULE_DEVICE_TABLE(pnp, wbcir_ids);
static struct pnp_driver wbcir_driver = {
- .name = WBCIR_NAME,
+ .name = DRVNAME,
.id_table = wbcir_ids,
.probe = wbcir_probe,
.remove = wbcir_remove,