diff options
Diffstat (limited to 'drivers/media/video/cx23885/cx23888-ir.c')
-rw-r--r-- | drivers/media/video/cx23885/cx23888-ir.c | 73 |
1 files changed, 44 insertions, 29 deletions
diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c index 684d23db98a7..2502a0a67097 100644 --- a/drivers/media/video/cx23885/cx23888-ir.c +++ b/drivers/media/video/cx23885/cx23888-ir.c | |||
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | #include <media/v4l2-device.h> | 27 | #include <media/v4l2-device.h> |
28 | #include <media/v4l2-chip-ident.h> | 28 | #include <media/v4l2-chip-ident.h> |
29 | #include <media/ir-core.h> | ||
29 | 30 | ||
30 | #include "cx23885.h" | 31 | #include "cx23885.h" |
31 | 32 | ||
@@ -113,8 +114,18 @@ MODULE_PARM_DESC(ir_888_debug, "enable debug messages [CX23888 IR controller]"); | |||
113 | #define CX23888_VIDCLK_FREQ 108000000 /* 108 MHz, BT.656 */ | 114 | #define CX23888_VIDCLK_FREQ 108000000 /* 108 MHz, BT.656 */ |
114 | #define CX23888_IR_REFCLK_FREQ (CX23888_VIDCLK_FREQ / 2) | 115 | #define CX23888_IR_REFCLK_FREQ (CX23888_VIDCLK_FREQ / 2) |
115 | 116 | ||
116 | #define CX23888_IR_RX_KFIFO_SIZE (512 * sizeof(u32)) | 117 | /* |
117 | #define CX23888_IR_TX_KFIFO_SIZE (512 * sizeof(u32)) | 118 | * We use this union internally for convenience, but callers to tx_write |
119 | * and rx_read will be expecting records of type struct ir_raw_event. | ||
120 | * Always ensure the size of this union is dictated by struct ir_raw_event. | ||
121 | */ | ||
122 | union cx23888_ir_fifo_rec { | ||
123 | u32 hw_fifo_data; | ||
124 | struct ir_raw_event ir_core_data; | ||
125 | }; | ||
126 | |||
127 | #define CX23888_IR_RX_KFIFO_SIZE (256 * sizeof(union cx23888_ir_fifo_rec)) | ||
128 | #define CX23888_IR_TX_KFIFO_SIZE (256 * sizeof(union cx23888_ir_fifo_rec)) | ||
118 | 129 | ||
119 | struct cx23888_ir_state { | 130 | struct cx23888_ir_state { |
120 | struct v4l2_subdev sd; | 131 | struct v4l2_subdev sd; |
@@ -458,8 +469,8 @@ static u32 txclk_tx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns, | |||
458 | { | 469 | { |
459 | u64 pulse_clocks; | 470 | u64 pulse_clocks; |
460 | 471 | ||
461 | if (ns > V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS) | 472 | if (ns > IR_MAX_DURATION) |
462 | ns = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS; | 473 | ns = IR_MAX_DURATION; |
463 | pulse_clocks = ns_to_pulse_clocks(ns); | 474 | pulse_clocks = ns_to_pulse_clocks(ns); |
464 | *divider = pulse_clocks_to_clock_divider(pulse_clocks); | 475 | *divider = pulse_clocks_to_clock_divider(pulse_clocks); |
465 | cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider); | 476 | cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider); |
@@ -471,8 +482,8 @@ static u32 rxclk_rx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns, | |||
471 | { | 482 | { |
472 | u64 pulse_clocks; | 483 | u64 pulse_clocks; |
473 | 484 | ||
474 | if (ns > V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS) | 485 | if (ns > IR_MAX_DURATION) |
475 | ns = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS; | 486 | ns = IR_MAX_DURATION; |
476 | pulse_clocks = ns_to_pulse_clocks(ns); | 487 | pulse_clocks = ns_to_pulse_clocks(ns); |
477 | *divider = pulse_clocks_to_clock_divider(pulse_clocks); | 488 | *divider = pulse_clocks_to_clock_divider(pulse_clocks); |
478 | cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider); | 489 | cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider); |
@@ -535,8 +546,8 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status, | |||
535 | u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG); | 546 | u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG); |
536 | u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG); | 547 | u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG); |
537 | 548 | ||
538 | u32 rx_data[FIFO_RX_DEPTH]; | 549 | union cx23888_ir_fifo_rec rx_data[FIFO_RX_DEPTH]; |
539 | int i, j, k; | 550 | unsigned int i, j, k; |
540 | u32 events, v; | 551 | u32 events, v; |
541 | int tsr, rsr, rto, ror, tse, rse, rte, roe, kror; | 552 | int tsr, rsr, rto, ror, tse, rse, rte, roe, kror; |
542 | 553 | ||
@@ -597,11 +608,12 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status, | |||
597 | for (j = 0; | 608 | for (j = 0; |
598 | (v & FIFO_RX_NDV) && j < FIFO_RX_DEPTH; j++) { | 609 | (v & FIFO_RX_NDV) && j < FIFO_RX_DEPTH; j++) { |
599 | v = cx23888_ir_read4(dev, CX23888_IR_FIFO_REG); | 610 | v = cx23888_ir_read4(dev, CX23888_IR_FIFO_REG); |
600 | rx_data[i++] = v & ~FIFO_RX_NDV; | 611 | rx_data[i].hw_fifo_data = v & ~FIFO_RX_NDV; |
612 | i++; | ||
601 | } | 613 | } |
602 | if (i == 0) | 614 | if (i == 0) |
603 | break; | 615 | break; |
604 | j = i * sizeof(u32); | 616 | j = i * sizeof(union cx23888_ir_fifo_rec); |
605 | k = kfifo_in_locked(&state->rx_kfifo, | 617 | k = kfifo_in_locked(&state->rx_kfifo, |
606 | (unsigned char *) rx_data, j, | 618 | (unsigned char *) rx_data, j, |
607 | &state->rx_kfifo_lock); | 619 | &state->rx_kfifo_lock); |
@@ -660,10 +672,11 @@ static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count, | |||
660 | u16 divider = (u16) atomic_read(&state->rxclk_divider); | 672 | u16 divider = (u16) atomic_read(&state->rxclk_divider); |
661 | 673 | ||
662 | unsigned int i, n; | 674 | unsigned int i, n; |
663 | u32 *p; | 675 | union cx23888_ir_fifo_rec *p; |
664 | u32 u, v; | 676 | unsigned u, v; |
665 | 677 | ||
666 | n = count / sizeof(u32) * sizeof(u32); | 678 | n = count / sizeof(union cx23888_ir_fifo_rec) |
679 | * sizeof(union cx23888_ir_fifo_rec); | ||
667 | if (n == 0) { | 680 | if (n == 0) { |
668 | *num = 0; | 681 | *num = 0; |
669 | return 0; | 682 | return 0; |
@@ -671,28 +684,28 @@ static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count, | |||
671 | 684 | ||
672 | n = kfifo_out_locked(&state->rx_kfifo, buf, n, &state->rx_kfifo_lock); | 685 | n = kfifo_out_locked(&state->rx_kfifo, buf, n, &state->rx_kfifo_lock); |
673 | 686 | ||
674 | n /= sizeof(u32); | 687 | n /= sizeof(union cx23888_ir_fifo_rec); |
675 | *num = n * sizeof(u32); | 688 | *num = n * sizeof(union cx23888_ir_fifo_rec); |
676 | 689 | ||
677 | for (p = (u32 *) buf, i = 0; i < n; p++, i++) { | 690 | for (p = (union cx23888_ir_fifo_rec *) buf, i = 0; i < n; p++, i++) { |
678 | 691 | ||
679 | if ((*p & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) { | 692 | if ((p->hw_fifo_data & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) { |
680 | /* Assume RTO was because of no IR light input */ | 693 | /* Assume RTO was because of no IR light input */ |
681 | u = 0; | 694 | u = 0; |
682 | v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n"); | 695 | v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n"); |
683 | } else { | 696 | } else { |
684 | u = (*p & FIFO_RXTX_LVL) | 697 | u = (p->hw_fifo_data & FIFO_RXTX_LVL) ? 1 : 0; |
685 | ? V4L2_SUBDEV_IR_PULSE_LEVEL_MASK : 0; | ||
686 | if (invert) | 698 | if (invert) |
687 | u = u ? 0 : V4L2_SUBDEV_IR_PULSE_LEVEL_MASK; | 699 | u = u ? 0 : 1; |
688 | } | 700 | } |
689 | 701 | ||
690 | v = (u32) pulse_width_count_to_ns((u16) (*p & FIFO_RXTX), | 702 | v = (unsigned) pulse_width_count_to_ns( |
691 | divider); | 703 | (u16) (p->hw_fifo_data & FIFO_RXTX), divider); |
692 | if (v >= V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS) | 704 | if (v > IR_MAX_DURATION) |
693 | v = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS - 1; | 705 | v = IR_MAX_DURATION; |
694 | 706 | ||
695 | *p = u | v; | 707 | p->ir_core_data.pulse = u; |
708 | p->ir_core_data.duration = v; | ||
696 | 709 | ||
697 | v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns %s\n", | 710 | v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns %s\n", |
698 | v, u ? "mark" : "space"); | 711 | v, u ? "mark" : "space"); |
@@ -751,7 +764,8 @@ static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd, | |||
751 | 764 | ||
752 | o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH; | 765 | o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH; |
753 | 766 | ||
754 | o->bytes_per_data_element = p->bytes_per_data_element = sizeof(u32); | 767 | o->bytes_per_data_element = p->bytes_per_data_element |
768 | = sizeof(union cx23888_ir_fifo_rec); | ||
755 | 769 | ||
756 | /* Before we tweak the hardware, we have to disable the receiver */ | 770 | /* Before we tweak the hardware, we have to disable the receiver */ |
757 | irqenable_rx(dev, 0); | 771 | irqenable_rx(dev, 0); |
@@ -878,7 +892,8 @@ static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd, | |||
878 | 892 | ||
879 | o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH; | 893 | o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH; |
880 | 894 | ||
881 | o->bytes_per_data_element = p->bytes_per_data_element = sizeof(u32); | 895 | o->bytes_per_data_element = p->bytes_per_data_element |
896 | = sizeof(union cx23888_ir_fifo_rec); | ||
882 | 897 | ||
883 | /* Before we tweak the hardware, we have to disable the transmitter */ | 898 | /* Before we tweak the hardware, we have to disable the transmitter */ |
884 | irqenable_tx(dev, 0); | 899 | irqenable_tx(dev, 0); |
@@ -1149,7 +1164,7 @@ static const struct v4l2_subdev_ops cx23888_ir_controller_ops = { | |||
1149 | }; | 1164 | }; |
1150 | 1165 | ||
1151 | static const struct v4l2_subdev_ir_parameters default_rx_params = { | 1166 | static const struct v4l2_subdev_ir_parameters default_rx_params = { |
1152 | .bytes_per_data_element = sizeof(u32), | 1167 | .bytes_per_data_element = sizeof(union cx23888_ir_fifo_rec), |
1153 | .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH, | 1168 | .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH, |
1154 | 1169 | ||
1155 | .enable = false, | 1170 | .enable = false, |
@@ -1168,7 +1183,7 @@ static const struct v4l2_subdev_ir_parameters default_rx_params = { | |||
1168 | }; | 1183 | }; |
1169 | 1184 | ||
1170 | static const struct v4l2_subdev_ir_parameters default_tx_params = { | 1185 | static const struct v4l2_subdev_ir_parameters default_tx_params = { |
1171 | .bytes_per_data_element = sizeof(u32), | 1186 | .bytes_per_data_element = sizeof(union cx23888_ir_fifo_rec), |
1172 | .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH, | 1187 | .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH, |
1173 | 1188 | ||
1174 | .enable = false, | 1189 | .enable = false, |