#define MODULE_NAME "cx23885"
 
-static void convert_measurement(u32 x, struct ir_raw_event *y)
-{
-       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_core_event[i]);
                        handle = true;
                }
        } while (num != 0);
 
 
 #include <media/v4l2-device.h>
 #include <media/v4l2-chip-ident.h>
+#include <media/ir-core.h>
 
 #include "cx23885.h"
 
 #define CX23888_VIDCLK_FREQ    108000000 /* 108 MHz, BT.656 */
 #define CX23888_IR_REFCLK_FREQ (CX23888_VIDCLK_FREQ / 2)
 
-#define CX23888_IR_RX_KFIFO_SIZE       (512 * sizeof(u32))
-#define CX23888_IR_TX_KFIFO_SIZE       (512 * sizeof(u32))
+/*
+ * We use this union internally for convenience, but callers to tx_write
+ * and rx_read will be expecting records of type struct ir_raw_event.
+ * Always ensure the size of this union is dictated by struct ir_raw_event.
+ */
+union cx23888_ir_fifo_rec {
+       u32 hw_fifo_data;
+       struct ir_raw_event ir_core_data;
+};
+
+#define CX23888_IR_RX_KFIFO_SIZE    (256 * sizeof(union cx23888_ir_fifo_rec))
+#define CX23888_IR_TX_KFIFO_SIZE    (256 * sizeof(union cx23888_ir_fifo_rec))
 
 struct cx23888_ir_state {
        struct v4l2_subdev sd;
 {
        u64 pulse_clocks;
 
-       if (ns > V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS)
-               ns = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS;
+       if (ns > IR_MAX_DURATION)
+               ns = IR_MAX_DURATION;
        pulse_clocks = ns_to_pulse_clocks(ns);
        *divider = pulse_clocks_to_clock_divider(pulse_clocks);
        cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider);
 {
        u64 pulse_clocks;
 
-       if (ns > V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS)
-               ns = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS;
+       if (ns > IR_MAX_DURATION)
+               ns = IR_MAX_DURATION;
        pulse_clocks = ns_to_pulse_clocks(ns);
        *divider = pulse_clocks_to_clock_divider(pulse_clocks);
        cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider);
        u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG);
        u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG);
 
-       u32 rx_data[FIFO_RX_DEPTH];
-       int i, j, k;
+       union cx23888_ir_fifo_rec rx_data[FIFO_RX_DEPTH];
+       unsigned int i, j, k;
        u32 events, v;
        int tsr, rsr, rto, ror, tse, rse, rte, roe, kror;
 
                        for (j = 0;
                             (v & FIFO_RX_NDV) && j < FIFO_RX_DEPTH; j++) {
                                v = cx23888_ir_read4(dev, CX23888_IR_FIFO_REG);
-                               rx_data[i++] = v & ~FIFO_RX_NDV;
+                               rx_data[i].hw_fifo_data = v & ~FIFO_RX_NDV;
+                               i++;
                        }
                        if (i == 0)
                                break;
-                       j = i * sizeof(u32);
+                       j = i * sizeof(union cx23888_ir_fifo_rec);
                        k = kfifo_in_locked(&state->rx_kfifo,
                                      (unsigned char *) rx_data, j,
                                      &state->rx_kfifo_lock);
        u16 divider = (u16) atomic_read(&state->rxclk_divider);
 
        unsigned int i, n;
-       u32 *p;
-       u32 u, v;
+       union cx23888_ir_fifo_rec *p;
+       unsigned u, v;
 
-       n = count / sizeof(u32) * sizeof(u32);
+       n = count / sizeof(union cx23888_ir_fifo_rec)
+               * sizeof(union cx23888_ir_fifo_rec);
        if (n == 0) {
                *num = 0;
                return 0;
 
        n = kfifo_out_locked(&state->rx_kfifo, buf, n, &state->rx_kfifo_lock);
 
-       n /= sizeof(u32);
-       *num = n * sizeof(u32);
+       n /= sizeof(union cx23888_ir_fifo_rec);
+       *num = n * sizeof(union cx23888_ir_fifo_rec);
 
-       for (p = (u32 *) buf, i = 0; i < n; p++, i++) {
+       for (p = (union cx23888_ir_fifo_rec *) buf, i = 0; i < n; p++, i++) {
 
-               if ((*p & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
+               if ((p->hw_fifo_data & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
                        /* Assume RTO was because of no IR light input */
                        u = 0;
                        v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n");
                } else {
-                       u = (*p & FIFO_RXTX_LVL)
-                                         ? V4L2_SUBDEV_IR_PULSE_LEVEL_MASK : 0;
+                       u = (p->hw_fifo_data & FIFO_RXTX_LVL) ? 1 : 0;
                        if (invert)
-                               u = u ? 0 : V4L2_SUBDEV_IR_PULSE_LEVEL_MASK;
+                               u = u ? 0 : 1;
                }
 
-               v = (u32) pulse_width_count_to_ns((u16) (*p & FIFO_RXTX),
-                                                 divider);
-               if (v >= V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS)
-                       v = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS - 1;
+               v = (unsigned) pulse_width_count_to_ns(
+                                 (u16) (p->hw_fifo_data & FIFO_RXTX), divider);
+               if (v > IR_MAX_DURATION)
+                       v = IR_MAX_DURATION;
 
-               *p = u | v;
+               p->ir_core_data.pulse = u;
+               p->ir_core_data.duration = v;
 
                v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns  %s\n",
                         v, u ? "mark" : "space");
 
        o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
 
-       o->bytes_per_data_element = p->bytes_per_data_element = sizeof(u32);
+       o->bytes_per_data_element = p->bytes_per_data_element
+                                 = sizeof(union cx23888_ir_fifo_rec);
 
        /* Before we tweak the hardware, we have to disable the receiver */
        irqenable_rx(dev, 0);
 
        o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
 
-       o->bytes_per_data_element = p->bytes_per_data_element = sizeof(u32);
+       o->bytes_per_data_element = p->bytes_per_data_element
+                                 = sizeof(union cx23888_ir_fifo_rec);
 
        /* Before we tweak the hardware, we have to disable the transmitter */
        irqenable_tx(dev, 0);
 };
 
 static const struct v4l2_subdev_ir_parameters default_rx_params = {
-       .bytes_per_data_element = sizeof(u32),
+       .bytes_per_data_element = sizeof(union cx23888_ir_fifo_rec),
        .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
 
        .enable = false,
 };
 
 static const struct v4l2_subdev_ir_parameters default_tx_params = {
-       .bytes_per_data_element = sizeof(u32),
+       .bytes_per_data_element = sizeof(union cx23888_ir_fifo_rec),
        .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
 
        .enable = false,
 
 #include <linux/slab.h>
 #include <linux/kfifo.h>
 #include <media/cx25840.h>
+#include <media/ir-core.h>
 
 #include "cx25840-core.h"
 
 #define CX25840_VIDCLK_FREQ    108000000 /* 108 MHz, BT.656 */
 #define CX25840_IR_REFCLK_FREQ (CX25840_VIDCLK_FREQ / 2)
 
-#define CX25840_IR_RX_KFIFO_SIZE       (512 * sizeof(u32))
-#define CX25840_IR_TX_KFIFO_SIZE       (512 * sizeof(u32))
+/*
+ * We use this union internally for convenience, but callers to tx_write
+ * and rx_read will be expecting records of type struct ir_raw_event.
+ * Always ensure the size of this union is dictated by struct ir_raw_event.
+ */
+union cx25840_ir_fifo_rec {
+       u32 hw_fifo_data;
+       struct ir_raw_event ir_core_data;
+};
+
+#define CX25840_IR_RX_KFIFO_SIZE    (256 * sizeof(union cx25840_ir_fifo_rec))
+#define CX25840_IR_TX_KFIFO_SIZE    (256 * sizeof(union cx25840_ir_fifo_rec))
 
 struct cx25840_ir_state {
        struct i2c_client *c;
 {
        u64 pulse_clocks;
 
-       if (ns > V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS)
-               ns = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS;
+       if (ns > IR_MAX_DURATION)
+               ns = IR_MAX_DURATION;
        pulse_clocks = ns_to_pulse_clocks(ns);
        *divider = pulse_clocks_to_clock_divider(pulse_clocks);
        cx25840_write4(c, CX25840_IR_TXCLK_REG, *divider);
 {
        u64 pulse_clocks;
 
-       if (ns > V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS)
-               ns = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS;
+       if (ns > IR_MAX_DURATION)
+               ns = IR_MAX_DURATION;
        pulse_clocks = ns_to_pulse_clocks(ns);
        *divider = pulse_clocks_to_clock_divider(pulse_clocks);
        cx25840_write4(c, CX25840_IR_RXCLK_REG, *divider);
        struct i2c_client *c = NULL;
        unsigned long flags;
 
-       u32 rx_data[FIFO_RX_DEPTH];
-       int i, j, k;
+       union cx25840_ir_fifo_rec rx_data[FIFO_RX_DEPTH];
+       unsigned int i, j, k;
        u32 events, v;
        int tsr, rsr, rto, ror, tse, rse, rte, roe, kror;
        u32 cntrl, irqen, stats;
                        for (j = 0;
                             (v & FIFO_RX_NDV) && j < FIFO_RX_DEPTH; j++) {
                                v = cx25840_read4(c, CX25840_IR_FIFO_REG);
-                               rx_data[i++] = v & ~FIFO_RX_NDV;
+                               rx_data[i].hw_fifo_data = v & ~FIFO_RX_NDV;
+                               i++;
                        }
                        if (i == 0)
                                break;
-                       j = i * sizeof(u32);
+                       j = i * sizeof(union cx25840_ir_fifo_rec);
                        k = kfifo_in_locked(&ir_state->rx_kfifo,
                                            (unsigned char *) rx_data, j,
                                            &ir_state->rx_kfifo_lock);
        bool invert;
        u16 divider;
        unsigned int i, n;
-       u32 *p;
-       u32 u, v;
+       union cx25840_ir_fifo_rec *p;
+       unsigned u, v;
 
        if (ir_state == NULL)
                return -ENODEV;
        invert = (bool) atomic_read(&ir_state->rx_invert);
        divider = (u16) atomic_read(&ir_state->rxclk_divider);
 
-       n = count / sizeof(u32) * sizeof(u32);
+       n = count / sizeof(union cx25840_ir_fifo_rec)
+               * sizeof(union cx25840_ir_fifo_rec);
        if (n == 0) {
                *num = 0;
                return 0;
        n = kfifo_out_locked(&ir_state->rx_kfifo, buf, n,
                             &ir_state->rx_kfifo_lock);
 
-       n /= sizeof(u32);
-       *num = n * sizeof(u32);
+       n /= sizeof(union cx25840_ir_fifo_rec);
+       *num = n * sizeof(union cx25840_ir_fifo_rec);
 
-       for (p = (u32 *) buf, i = 0; i < n; p++, i++) {
+       for (p = (union cx25840_ir_fifo_rec *) buf, i = 0; i < n; p++, i++) {
 
-               if ((*p & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
+               if ((p->hw_fifo_data & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
                        /* Assume RTO was because of no IR light input */
                        u = 0;
                        v4l2_dbg(2, ir_debug, sd, "rx read: end of rx\n");
                } else {
-                       u = (*p & FIFO_RXTX_LVL)
-                                         ? V4L2_SUBDEV_IR_PULSE_LEVEL_MASK : 0;
+                       u = (p->hw_fifo_data & FIFO_RXTX_LVL) ? 1 : 0;
                        if (invert)
-                               u = u ? 0 : V4L2_SUBDEV_IR_PULSE_LEVEL_MASK;
+                               u = u ? 0 : 1;
                }
 
-               v = (u32) pulse_width_count_to_ns((u16) (*p & FIFO_RXTX),
-                                                 divider);
-               if (v >= V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS)
-                       v = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS - 1;
+               v = (unsigned) pulse_width_count_to_ns(
+                                 (u16) (p->hw_fifo_data & FIFO_RXTX), divider);
+               if (v > IR_MAX_DURATION)
+                       v = IR_MAX_DURATION;
 
-               *p = u | v;
+               p->ir_core_data.pulse = u;
+               p->ir_core_data.duration = v;
 
                v4l2_dbg(2, ir_debug, sd, "rx read: %10u ns  %s\n",
                         v, u ? "mark" : "space");
        p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
        o->mode = p->mode;
 
-       p->bytes_per_data_element = sizeof(u32);
+       p->bytes_per_data_element = sizeof(union cx25840_ir_fifo_rec);
        o->bytes_per_data_element = p->bytes_per_data_element;
 
        /* Before we tweak the hardware, we have to disable the receiver */
        p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
        o->mode = p->mode;
 
-       p->bytes_per_data_element = sizeof(u32);
+       p->bytes_per_data_element = sizeof(union cx25840_ir_fifo_rec);
        o->bytes_per_data_element = p->bytes_per_data_element;
 
        /* Before we tweak the hardware, we have to disable the transmitter */
 
 
 static const struct v4l2_subdev_ir_parameters default_rx_params = {
-       .bytes_per_data_element = sizeof(u32),
+       .bytes_per_data_element = sizeof(union cx25840_ir_fifo_rec),
        .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
 
        .enable = false,
 };
 
 static const struct v4l2_subdev_ir_parameters default_tx_params = {
-       .bytes_per_data_element = sizeof(u32),
+       .bytes_per_data_element = sizeof(union cx25840_ir_fifo_rec),
        .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
 
        .enable = false,