diff options
Diffstat (limited to 'drivers/media/video/cx25840/cx25840-ir.c')
-rw-r--r-- | drivers/media/video/cx25840/cx25840-ir.c | 71 |
1 files changed, 42 insertions, 29 deletions
diff --git a/drivers/media/video/cx25840/cx25840-ir.c b/drivers/media/video/cx25840/cx25840-ir.c index be23c5b37a2f..34e284b06dfa 100644 --- a/drivers/media/video/cx25840/cx25840-ir.c +++ b/drivers/media/video/cx25840/cx25840-ir.c @@ -24,6 +24,7 @@ #include <linux/slab.h> #include <linux/kfifo.h> #include <media/cx25840.h> +#include <media/ir-core.h> #include "cx25840-core.h" @@ -94,8 +95,18 @@ MODULE_PARM_DESC(ir_debug, "enable integrated IR debug messages"); #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; @@ -435,8 +446,8 @@ static u32 txclk_tx_s_max_pulse_width(struct i2c_client *c, u32 ns, { 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); @@ -448,8 +459,8 @@ static u32 rxclk_rx_s_max_pulse_width(struct i2c_client *c, u32 ns, { 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); @@ -516,8 +527,8 @@ int cx25840_ir_irq_handler(struct v4l2_subdev *sd, u32 status, bool *handled) 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; @@ -594,11 +605,12 @@ int cx25840_ir_irq_handler(struct v4l2_subdev *sd, u32 status, bool *handled) 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); @@ -655,8 +667,8 @@ static int cx25840_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count, 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; @@ -664,7 +676,8 @@ static int cx25840_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count, 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; @@ -673,28 +686,28 @@ static int cx25840_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count, 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"); @@ -769,7 +782,7 @@ static int cx25840_ir_rx_s_parameters(struct v4l2_subdev *sd, 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 */ @@ -958,7 +971,7 @@ static int cx25840_ir_tx_s_parameters(struct v4l2_subdev *sd, 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 */ @@ -1172,7 +1185,7 @@ const struct v4l2_subdev_ir_ops cx25840_ir_ops = { 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, @@ -1191,7 +1204,7 @@ static const struct v4l2_subdev_ir_parameters default_rx_params = { }; 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, |