Merge branch 'for-2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq
[cascardo/linux.git] / drivers / media / video / cx23885 / cx23885-input.c
index d0b1613..199b996 100644 (file)
  *  02110-1301, USA.
  */
 
-#include <linux/input.h>
 #include <linux/slab.h>
-#include <media/ir-core.h>
+#include <media/rc-core.h>
 #include <media/v4l2-subdev.h>
 
 #include "cx23885.h"
 
 #define MODULE_NAME "cx23885"
 
-static void convert_measurement(u32 x, struct ir_raw_event *y)
-{
-       if (x == V4L2_SUBDEV_IR_PULSE_RX_SEQ_END) {
-               y->pulse = false;
-               y->duration = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS;
-               return;
-       }
-
-       y->pulse = (x & V4L2_SUBDEV_IR_PULSE_LEVEL_MASK) ? true : false;
-       y->duration = x & V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS;
-}
-
 static void cx23885_input_process_measurements(struct cx23885_dev *dev,
                                               bool overrun)
 {
        struct cx23885_kernel_ir *kernel_ir = dev->kernel_ir;
-       struct ir_raw_event kernel_ir_event;
 
-       u32 sd_ir_data[64];
        ssize_t num;
        int count, i;
        bool handle = false;
+       struct ir_raw_event ir_core_event[64];
 
        do {
                num = 0;
-               v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) sd_ir_data,
-                                sizeof(sd_ir_data), &num);
+               v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) ir_core_event,
+                                sizeof(ir_core_event), &num);
 
-               count = num / sizeof(u32);
+               count = num / sizeof(struct ir_raw_event);
 
                for (i = 0; i < count; i++) {
-                       convert_measurement(sd_ir_data[i], &kernel_ir_event);
-                       ir_raw_event_store(kernel_ir->inp_dev,
-                                          &kernel_ir_event);
+                       ir_raw_event_store(kernel_ir->rc,
+                                          &ir_core_event[i]);
                        handle = true;
                }
        } while (num != 0);
 
        if (overrun)
-               ir_raw_event_reset(kernel_ir->inp_dev);
+               ir_raw_event_reset(kernel_ir->rc);
        else if (handle)
-               ir_raw_event_handle(kernel_ir->inp_dev);
+               ir_raw_event_handle(kernel_ir->rc);
 }
 
 void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
@@ -99,8 +84,10 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
        switch (dev->board) {
        case CX23885_BOARD_HAUPPAUGE_HVR1850:
        case CX23885_BOARD_HAUPPAUGE_HVR1290:
+       case CX23885_BOARD_TEVII_S470:
+       case CX23885_BOARD_HAUPPAUGE_HVR1250:
                /*
-                * The only board we handle right now.  However other boards
+                * The only boards we handle right now.  However other boards
                 * using the CX2388x integrated IR controller should be similar
                 */
                break;
@@ -148,6 +135,7 @@ static int cx23885_input_ir_start(struct cx23885_dev *dev)
        switch (dev->board) {
        case CX23885_BOARD_HAUPPAUGE_HVR1850:
        case CX23885_BOARD_HAUPPAUGE_HVR1290:
+       case CX23885_BOARD_HAUPPAUGE_HVR1250:
                /*
                 * The IR controller on this board only returns pulse widths.
                 * Any other mode setting will fail to set up the device.
@@ -170,16 +158,47 @@ static int cx23885_input_ir_start(struct cx23885_dev *dev)
                 * mark is received as low logic level;
                 * falling edges are detected as rising edges; etc.
                 */
-               params.invert = true;
+               params.invert_level = true;
+               break;
+       case CX23885_BOARD_TEVII_S470:
+               /*
+                * The IR controller on this board only returns pulse widths.
+                * Any other mode setting will fail to set up the device.
+                */
+               params.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
+               params.enable = true;
+               params.interrupt_enable = true;
+               params.shutdown = false;
+
+               /* Setup for a standard NEC protocol */
+               params.carrier_freq = 37917; /* Hz, 455 kHz/12 for NEC */
+               params.carrier_range_lower = 33000; /* Hz */
+               params.carrier_range_upper = 43000; /* Hz */
+               params.duty_cycle = 33; /* percent, 33 percent for NEC */
+
+               /*
+                * NEC max pulse width: (64/3)/(455 kHz/12) * 16 nec_units
+                * (64/3)/(455 kHz/12) * 16 nec_units * 1.375 = 12378022 ns
+                */
+               params.max_pulse_width = 12378022; /* ns */
+
+               /*
+                * NEC noise filter min width: (64/3)/(455 kHz/12) * 1 nec_unit
+                * (64/3)/(455 kHz/12) * 1 nec_units * 0.625 = 351648 ns
+                */
+               params.noise_filter_min_width = 351648; /* ns */
+
+               params.modulation = false;
+               params.invert_level = true;
                break;
        }
        v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
        return 0;
 }
 
-static int cx23885_input_ir_open(void *priv)
+static int cx23885_input_ir_open(struct rc_dev *rc)
 {
-       struct cx23885_kernel_ir *kernel_ir = priv;
+       struct cx23885_kernel_ir *kernel_ir = rc->priv;
 
        if (kernel_ir->cx == NULL)
                return -ENODEV;
@@ -210,13 +229,11 @@ static void cx23885_input_ir_stop(struct cx23885_dev *dev)
                v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
                v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
        }
-
-       flush_scheduled_work();
 }
 
-static void cx23885_input_ir_close(void *priv)
+static void cx23885_input_ir_close(struct rc_dev *rc)
 {
-       struct cx23885_kernel_ir *kernel_ir = priv;
+       struct cx23885_kernel_ir *kernel_ir = rc->priv;
 
        if (kernel_ir->cx != NULL)
                cx23885_input_ir_stop(kernel_ir->cx);
@@ -225,9 +242,7 @@ static void cx23885_input_ir_close(void *priv)
 int cx23885_input_init(struct cx23885_dev *dev)
 {
        struct cx23885_kernel_ir *kernel_ir;
-       struct input_dev *inp_dev;
-       struct ir_dev_props *props;
-
+       struct rc_dev *rc;
        char *rc_map;
        enum rc_driver_type driver_type;
        unsigned long allowed_protos;
@@ -244,12 +259,20 @@ int cx23885_input_init(struct cx23885_dev *dev)
        switch (dev->board) {
        case CX23885_BOARD_HAUPPAUGE_HVR1850:
        case CX23885_BOARD_HAUPPAUGE_HVR1290:
-               /* Integrated CX23888 IR controller */
+       case CX23885_BOARD_HAUPPAUGE_HVR1250:
+               /* Integrated CX2388[58] IR controller */
                driver_type = RC_DRIVER_IR_RAW;
-               allowed_protos = IR_TYPE_ALL;
+               allowed_protos = RC_TYPE_ALL;
                /* The grey Hauppauge RC-5 remote */
                rc_map = RC_MAP_RC5_HAUPPAUGE_NEW;
                break;
+       case CX23885_BOARD_TEVII_S470:
+               /* Integrated CX23885 IR controller */
+               driver_type = RC_DRIVER_IR_RAW;
+               allowed_protos = RC_TYPE_ALL;
+               /* A guess at the remote */
+               rc_map = RC_MAP_TEVII_NEC;
+               break;
        default:
                return -ENODEV;
        }
@@ -266,37 +289,36 @@ int cx23885_input_init(struct cx23885_dev *dev)
                                    pci_name(dev->pci));
 
        /* input device */
-       inp_dev = input_allocate_device();
-       if (inp_dev == NULL) {
+       rc = rc_allocate_device();
+       if (!rc) {
                ret = -ENOMEM;
                goto err_out_free;
        }
 
-       kernel_ir->inp_dev = inp_dev;
-       inp_dev->name = kernel_ir->name;
-       inp_dev->phys = kernel_ir->phys;
-       inp_dev->id.bustype = BUS_PCI;
-       inp_dev->id.version = 1;
+       kernel_ir->rc = rc;
+       rc->input_name = kernel_ir->name;
+       rc->input_phys = kernel_ir->phys;
+       rc->input_id.bustype = BUS_PCI;
+       rc->input_id.version = 1;
        if (dev->pci->subsystem_vendor) {
-               inp_dev->id.vendor  = dev->pci->subsystem_vendor;
-               inp_dev->id.product = dev->pci->subsystem_device;
+               rc->input_id.vendor  = dev->pci->subsystem_vendor;
+               rc->input_id.product = dev->pci->subsystem_device;
        } else {
-               inp_dev->id.vendor  = dev->pci->vendor;
-               inp_dev->id.product = dev->pci->device;
+               rc->input_id.vendor  = dev->pci->vendor;
+               rc->input_id.product = dev->pci->device;
        }
-       inp_dev->dev.parent = &dev->pci->dev;
-
-       /* kernel ir device properties */
-       props = &kernel_ir->props;
-       props->driver_type = driver_type;
-       props->allowed_protos = allowed_protos;
-       props->priv = kernel_ir;
-       props->open = cx23885_input_ir_open;
-       props->close = cx23885_input_ir_close;
+       rc->dev.parent = &dev->pci->dev;
+       rc->driver_type = driver_type;
+       rc->allowed_protos = allowed_protos;
+       rc->priv = kernel_ir;
+       rc->open = cx23885_input_ir_open;
+       rc->close = cx23885_input_ir_close;
+       rc->map_name = rc_map;
+       rc->driver_name = MODULE_NAME;
 
        /* Go */
        dev->kernel_ir = kernel_ir;
-       ret = ir_input_register(inp_dev, rc_map, props, MODULE_NAME);
+       ret = rc_register_device(rc);
        if (ret)
                goto err_out_stop;
 
@@ -305,7 +327,7 @@ int cx23885_input_init(struct cx23885_dev *dev)
 err_out_stop:
        cx23885_input_ir_stop(dev);
        dev->kernel_ir = NULL;
-       /* TODO: double check clean-up of kernel_ir->inp_dev */
+       rc_free_device(rc);
 err_out_free:
        kfree(kernel_ir->phys);
        kfree(kernel_ir->name);
@@ -320,7 +342,7 @@ void cx23885_input_fini(struct cx23885_dev *dev)
 
        if (dev->kernel_ir == NULL)
                return;
-       ir_input_unregister(dev->kernel_ir->inp_dev);
+       rc_unregister_device(dev->kernel_ir->rc);
        kfree(dev->kernel_ir->phys);
        kfree(dev->kernel_ir->name);
        kfree(dev->kernel_ir);