aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx23885/cx23888-ir.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/cx23885/cx23888-ir.c')
-rw-r--r--drivers/media/video/cx23885/cx23888-ir.c142
1 files changed, 88 insertions, 54 deletions
diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c
index f63d378257a7..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
@@ -60,6 +61,8 @@ MODULE_PARM_DESC(ir_888_debug, "enable debug messages [CX23888 IR controller]");
60#define CNTRL_CPL 0x00001000 61#define CNTRL_CPL 0x00001000
61#define CNTRL_LBM 0x00002000 62#define CNTRL_LBM 0x00002000
62#define CNTRL_R 0x00004000 63#define CNTRL_R 0x00004000
64/* CX23888 specific control flag */
65#define CNTRL_IVO 0x00008000
63 66
64#define CX23888_IR_TXCLK_REG 0x170004 67#define CX23888_IR_TXCLK_REG 0x170004
65#define TXCLK_TCD 0x0000FFFF 68#define TXCLK_TCD 0x0000FFFF
@@ -111,8 +114,18 @@ MODULE_PARM_DESC(ir_888_debug, "enable debug messages [CX23888 IR controller]");
111#define CX23888_VIDCLK_FREQ 108000000 /* 108 MHz, BT.656 */ 114#define CX23888_VIDCLK_FREQ 108000000 /* 108 MHz, BT.656 */
112#define CX23888_IR_REFCLK_FREQ (CX23888_VIDCLK_FREQ / 2) 115#define CX23888_IR_REFCLK_FREQ (CX23888_VIDCLK_FREQ / 2)
113 116
114#define CX23888_IR_RX_KFIFO_SIZE (512 * sizeof(u32)) 117/*
115#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 */
122union 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))
116 129
117struct cx23888_ir_state { 130struct cx23888_ir_state {
118 struct v4l2_subdev sd; 131 struct v4l2_subdev sd;
@@ -423,6 +436,13 @@ static inline void control_tx_polarity_invert(struct cx23885_dev *dev,
423 invert ? CNTRL_CPL : 0); 436 invert ? CNTRL_CPL : 0);
424} 437}
425 438
439static inline void control_tx_level_invert(struct cx23885_dev *dev,
440 bool invert)
441{
442 cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_IVO,
443 invert ? CNTRL_IVO : 0);
444}
445
426/* 446/*
427 * IR Rx & Tx Clock Register helpers 447 * IR Rx & Tx Clock Register helpers
428 */ 448 */
@@ -449,8 +469,8 @@ static u32 txclk_tx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns,
449{ 469{
450 u64 pulse_clocks; 470 u64 pulse_clocks;
451 471
452 if (ns > V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS) 472 if (ns > IR_MAX_DURATION)
453 ns = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS; 473 ns = IR_MAX_DURATION;
454 pulse_clocks = ns_to_pulse_clocks(ns); 474 pulse_clocks = ns_to_pulse_clocks(ns);
455 *divider = pulse_clocks_to_clock_divider(pulse_clocks); 475 *divider = pulse_clocks_to_clock_divider(pulse_clocks);
456 cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider); 476 cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider);
@@ -462,8 +482,8 @@ static u32 rxclk_rx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns,
462{ 482{
463 u64 pulse_clocks; 483 u64 pulse_clocks;
464 484
465 if (ns > V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS) 485 if (ns > IR_MAX_DURATION)
466 ns = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS; 486 ns = IR_MAX_DURATION;
467 pulse_clocks = ns_to_pulse_clocks(ns); 487 pulse_clocks = ns_to_pulse_clocks(ns);
468 *divider = pulse_clocks_to_clock_divider(pulse_clocks); 488 *divider = pulse_clocks_to_clock_divider(pulse_clocks);
469 cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider); 489 cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider);
@@ -526,8 +546,8 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status,
526 u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG); 546 u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG);
527 u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG); 547 u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG);
528 548
529 u32 rx_data[FIFO_RX_DEPTH]; 549 union cx23888_ir_fifo_rec rx_data[FIFO_RX_DEPTH];
530 int i, j, k; 550 unsigned int i, j, k;
531 u32 events, v; 551 u32 events, v;
532 int tsr, rsr, rto, ror, tse, rse, rte, roe, kror; 552 int tsr, rsr, rto, ror, tse, rse, rte, roe, kror;
533 553
@@ -588,11 +608,12 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status,
588 for (j = 0; 608 for (j = 0;
589 (v & FIFO_RX_NDV) && j < FIFO_RX_DEPTH; j++) { 609 (v & FIFO_RX_NDV) && j < FIFO_RX_DEPTH; j++) {
590 v = cx23888_ir_read4(dev, CX23888_IR_FIFO_REG); 610 v = cx23888_ir_read4(dev, CX23888_IR_FIFO_REG);
591 rx_data[i++] = v & ~FIFO_RX_NDV; 611 rx_data[i].hw_fifo_data = v & ~FIFO_RX_NDV;
612 i++;
592 } 613 }
593 if (i == 0) 614 if (i == 0)
594 break; 615 break;
595 j = i * sizeof(u32); 616 j = i * sizeof(union cx23888_ir_fifo_rec);
596 k = kfifo_in_locked(&state->rx_kfifo, 617 k = kfifo_in_locked(&state->rx_kfifo,
597 (unsigned char *) rx_data, j, 618 (unsigned char *) rx_data, j,
598 &state->rx_kfifo_lock); 619 &state->rx_kfifo_lock);
@@ -651,10 +672,11 @@ static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
651 u16 divider = (u16) atomic_read(&state->rxclk_divider); 672 u16 divider = (u16) atomic_read(&state->rxclk_divider);
652 673
653 unsigned int i, n; 674 unsigned int i, n;
654 u32 *p; 675 union cx23888_ir_fifo_rec *p;
655 u32 u, v; 676 unsigned u, v;
656 677
657 n = count / sizeof(u32) * sizeof(u32); 678 n = count / sizeof(union cx23888_ir_fifo_rec)
679 * sizeof(union cx23888_ir_fifo_rec);
658 if (n == 0) { 680 if (n == 0) {
659 *num = 0; 681 *num = 0;
660 return 0; 682 return 0;
@@ -662,26 +684,28 @@ static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
662 684
663 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);
664 686
665 n /= sizeof(u32); 687 n /= sizeof(union cx23888_ir_fifo_rec);
666 *num = n * sizeof(u32); 688 *num = n * sizeof(union cx23888_ir_fifo_rec);
689
690 for (p = (union cx23888_ir_fifo_rec *) buf, i = 0; i < n; p++, i++) {
667 691
668 for (p = (u32 *) buf, i = 0; i < n; p++, i++) { 692 if ((p->hw_fifo_data & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
669 if ((*p & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) { 693 /* Assume RTO was because of no IR light input */
670 *p = V4L2_SUBDEV_IR_PULSE_RX_SEQ_END; 694 u = 0;
671 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");
672 continue; 696 } else {
697 u = (p->hw_fifo_data & FIFO_RXTX_LVL) ? 1 : 0;
698 if (invert)
699 u = u ? 0 : 1;
673 } 700 }
674 701
675 u = (*p & FIFO_RXTX_LVL) ? V4L2_SUBDEV_IR_PULSE_LEVEL_MASK : 0; 702 v = (unsigned) pulse_width_count_to_ns(
676 if (invert) 703 (u16) (p->hw_fifo_data & FIFO_RXTX), divider);
677 u = u ? 0 : V4L2_SUBDEV_IR_PULSE_LEVEL_MASK; 704 if (v > IR_MAX_DURATION)
705 v = IR_MAX_DURATION;
678 706
679 v = (u32) pulse_width_count_to_ns((u16) (*p & FIFO_RXTX), 707 p->ir_core_data.pulse = u;
680 divider); 708 p->ir_core_data.duration = v;
681 if (v >= V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS)
682 v = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS - 1;
683
684 *p = u | v;
685 709
686 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",
687 v, u ? "mark" : "space"); 711 v, u ? "mark" : "space");
@@ -740,7 +764,8 @@ static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd,
740 764
741 o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH; 765 o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
742 766
743 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);
744 769
745 /* Before we tweak the hardware, we have to disable the receiver */ 770 /* Before we tweak the hardware, we have to disable the receiver */
746 irqenable_rx(dev, 0); 771 irqenable_rx(dev, 0);
@@ -762,12 +787,15 @@ static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd,
762 &p->carrier_range_upper); 787 &p->carrier_range_upper);
763 o->carrier_range_lower = p->carrier_range_lower; 788 o->carrier_range_lower = p->carrier_range_lower;
764 o->carrier_range_upper = p->carrier_range_upper; 789 o->carrier_range_upper = p->carrier_range_upper;
790
791 p->max_pulse_width =
792 (u32) pulse_width_count_to_ns(FIFO_RXTX, rxclk_divider);
765 } else { 793 } else {
766 p->max_pulse_width = 794 p->max_pulse_width =
767 rxclk_rx_s_max_pulse_width(dev, p->max_pulse_width, 795 rxclk_rx_s_max_pulse_width(dev, p->max_pulse_width,
768 &rxclk_divider); 796 &rxclk_divider);
769 o->max_pulse_width = p->max_pulse_width;
770 } 797 }
798 o->max_pulse_width = p->max_pulse_width;
771 atomic_set(&state->rxclk_divider, rxclk_divider); 799 atomic_set(&state->rxclk_divider, rxclk_divider);
772 800
773 p->noise_filter_min_width = 801 p->noise_filter_min_width =
@@ -782,8 +810,8 @@ static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd,
782 810
783 control_rx_s_edge_detection(dev, CNTRL_EDG_BOTH); 811 control_rx_s_edge_detection(dev, CNTRL_EDG_BOTH);
784 812
785 o->invert = p->invert; 813 o->invert_level = p->invert_level;
786 atomic_set(&state->rx_invert, p->invert); 814 atomic_set(&state->rx_invert, p->invert_level);
787 815
788 o->interrupt_enable = p->interrupt_enable; 816 o->interrupt_enable = p->interrupt_enable;
789 o->enable = p->enable; 817 o->enable = p->enable;
@@ -864,7 +892,8 @@ static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd,
864 892
865 o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH; 893 o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
866 894
867 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);
868 897
869 /* Before we tweak the hardware, we have to disable the transmitter */ 898 /* Before we tweak the hardware, we have to disable the transmitter */
870 irqenable_tx(dev, 0); 899 irqenable_tx(dev, 0);
@@ -880,12 +909,15 @@ static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd,
880 909
881 p->duty_cycle = cduty_tx_s_duty_cycle(dev, p->duty_cycle); 910 p->duty_cycle = cduty_tx_s_duty_cycle(dev, p->duty_cycle);
882 o->duty_cycle = p->duty_cycle; 911 o->duty_cycle = p->duty_cycle;
912
913 p->max_pulse_width =
914 (u32) pulse_width_count_to_ns(FIFO_RXTX, txclk_divider);
883 } else { 915 } else {
884 p->max_pulse_width = 916 p->max_pulse_width =
885 txclk_tx_s_max_pulse_width(dev, p->max_pulse_width, 917 txclk_tx_s_max_pulse_width(dev, p->max_pulse_width,
886 &txclk_divider); 918 &txclk_divider);
887 o->max_pulse_width = p->max_pulse_width;
888 } 919 }
920 o->max_pulse_width = p->max_pulse_width;
889 atomic_set(&state->txclk_divider, txclk_divider); 921 atomic_set(&state->txclk_divider, txclk_divider);
890 922
891 p->resolution = clock_divider_to_resolution(txclk_divider); 923 p->resolution = clock_divider_to_resolution(txclk_divider);
@@ -894,8 +926,11 @@ static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd,
894 /* FIXME - make this dependent on resolution for better performance */ 926 /* FIXME - make this dependent on resolution for better performance */
895 control_tx_irq_watermark(dev, TX_FIFO_HALF_EMPTY); 927 control_tx_irq_watermark(dev, TX_FIFO_HALF_EMPTY);
896 928
897 control_tx_polarity_invert(dev, p->invert); 929 control_tx_polarity_invert(dev, p->invert_carrier_sense);
898 o->invert = p->invert; 930 o->invert_carrier_sense = p->invert_carrier_sense;
931
932 control_tx_level_invert(dev, p->invert_level);
933 o->invert_level = p->invert_level;
899 934
900 o->interrupt_enable = p->interrupt_enable; 935 o->interrupt_enable = p->interrupt_enable;
901 o->enable = p->enable; 936 o->enable = p->enable;
@@ -988,12 +1023,10 @@ static int cx23888_ir_log_status(struct v4l2_subdev *sd)
988 "-%1d/+%1d, %u to %u Hz\n", i, j, 1023 "-%1d/+%1d, %u to %u Hz\n", i, j,
989 clock_divider_to_freq(rxclk, 16 + j), 1024 clock_divider_to_freq(rxclk, 16 + j),
990 clock_divider_to_freq(rxclk, 16 - i)); 1025 clock_divider_to_freq(rxclk, 16 - i));
991 } else {
992 v4l2_info(sd, "\tMax measurable pulse width: %u us, "
993 "%llu ns\n",
994 pulse_width_count_to_us(FIFO_RXTX, rxclk),
995 pulse_width_count_to_ns(FIFO_RXTX, rxclk));
996 } 1026 }
1027 v4l2_info(sd, "\tMax measurable pulse width: %u us, %llu ns\n",
1028 pulse_width_count_to_us(FIFO_RXTX, rxclk),
1029 pulse_width_count_to_ns(FIFO_RXTX, rxclk));
997 v4l2_info(sd, "\tLow pass filter: %s\n", 1030 v4l2_info(sd, "\tLow pass filter: %s\n",
998 filtr ? "enabled" : "disabled"); 1031 filtr ? "enabled" : "disabled");
999 if (filtr) 1032 if (filtr)
@@ -1025,19 +1058,20 @@ static int cx23888_ir_log_status(struct v4l2_subdev *sd)
1025 cntrl & CNTRL_TFE ? "enabled" : "disabled"); 1058 cntrl & CNTRL_TFE ? "enabled" : "disabled");
1026 v4l2_info(sd, "\tFIFO interrupt watermark: %s\n", 1059 v4l2_info(sd, "\tFIFO interrupt watermark: %s\n",
1027 cntrl & CNTRL_TIC ? "not empty" : "half full or less"); 1060 cntrl & CNTRL_TIC ? "not empty" : "half full or less");
1028 v4l2_info(sd, "\tSignal polarity: %s\n", 1061 v4l2_info(sd, "\tOutput pin level inversion %s\n",
1029 cntrl & CNTRL_CPL ? "0:mark 1:space" : "0:space 1:mark"); 1062 cntrl & CNTRL_IVO ? "yes" : "no");
1063 v4l2_info(sd, "\tCarrier polarity: %s\n",
1064 cntrl & CNTRL_CPL ? "space:burst mark:noburst"
1065 : "space:noburst mark:burst");
1030 if (cntrl & CNTRL_MOD) { 1066 if (cntrl & CNTRL_MOD) {
1031 v4l2_info(sd, "\tCarrier (16 clocks): %u Hz\n", 1067 v4l2_info(sd, "\tCarrier (16 clocks): %u Hz\n",
1032 clock_divider_to_carrier_freq(txclk)); 1068 clock_divider_to_carrier_freq(txclk));
1033 v4l2_info(sd, "\tCarrier duty cycle: %2u/16\n", 1069 v4l2_info(sd, "\tCarrier duty cycle: %2u/16\n",
1034 cduty + 1); 1070 cduty + 1);
1035 } else {
1036 v4l2_info(sd, "\tMax pulse width: %u us, "
1037 "%llu ns\n",
1038 pulse_width_count_to_us(FIFO_RXTX, txclk),
1039 pulse_width_count_to_ns(FIFO_RXTX, txclk));
1040 } 1071 }
1072 v4l2_info(sd, "\tMax pulse width: %u us, %llu ns\n",
1073 pulse_width_count_to_us(FIFO_RXTX, txclk),
1074 pulse_width_count_to_ns(FIFO_RXTX, txclk));
1041 v4l2_info(sd, "\tBusy: %s\n", 1075 v4l2_info(sd, "\tBusy: %s\n",
1042 stats & STATS_TBY ? "yes" : "no"); 1076 stats & STATS_TBY ? "yes" : "no");
1043 v4l2_info(sd, "\tFIFO service requested: %s\n", 1077 v4l2_info(sd, "\tFIFO service requested: %s\n",
@@ -1111,11 +1145,10 @@ static const struct v4l2_subdev_core_ops cx23888_ir_core_ops = {
1111 .g_register = cx23888_ir_g_register, 1145 .g_register = cx23888_ir_g_register,
1112 .s_register = cx23888_ir_s_register, 1146 .s_register = cx23888_ir_s_register,
1113#endif 1147#endif
1148 .interrupt_service_routine = cx23888_ir_irq_handler,
1114}; 1149};
1115 1150
1116static const struct v4l2_subdev_ir_ops cx23888_ir_ir_ops = { 1151static const struct v4l2_subdev_ir_ops cx23888_ir_ir_ops = {
1117 .interrupt_service_routine = cx23888_ir_irq_handler,
1118
1119 .rx_read = cx23888_ir_rx_read, 1152 .rx_read = cx23888_ir_rx_read,
1120 .rx_g_parameters = cx23888_ir_rx_g_parameters, 1153 .rx_g_parameters = cx23888_ir_rx_g_parameters,
1121 .rx_s_parameters = cx23888_ir_rx_s_parameters, 1154 .rx_s_parameters = cx23888_ir_rx_s_parameters,
@@ -1131,7 +1164,7 @@ static const struct v4l2_subdev_ops cx23888_ir_controller_ops = {
1131}; 1164};
1132 1165
1133static const struct v4l2_subdev_ir_parameters default_rx_params = { 1166static const struct v4l2_subdev_ir_parameters default_rx_params = {
1134 .bytes_per_data_element = sizeof(u32), 1167 .bytes_per_data_element = sizeof(union cx23888_ir_fifo_rec),
1135 .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH, 1168 .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
1136 1169
1137 .enable = false, 1170 .enable = false,
@@ -1146,11 +1179,11 @@ static const struct v4l2_subdev_ir_parameters default_rx_params = {
1146 .noise_filter_min_width = 333333, /* ns */ 1179 .noise_filter_min_width = 333333, /* ns */
1147 .carrier_range_lower = 35000, 1180 .carrier_range_lower = 35000,
1148 .carrier_range_upper = 37000, 1181 .carrier_range_upper = 37000,
1149 .invert = false, 1182 .invert_level = false,
1150}; 1183};
1151 1184
1152static const struct v4l2_subdev_ir_parameters default_tx_params = { 1185static const struct v4l2_subdev_ir_parameters default_tx_params = {
1153 .bytes_per_data_element = sizeof(u32), 1186 .bytes_per_data_element = sizeof(union cx23888_ir_fifo_rec),
1154 .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH, 1187 .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
1155 1188
1156 .enable = false, 1189 .enable = false,
@@ -1160,7 +1193,8 @@ static const struct v4l2_subdev_ir_parameters default_tx_params = {
1160 .modulation = true, 1193 .modulation = true,
1161 .carrier_freq = 36000, /* 36 kHz - RC-5 carrier */ 1194 .carrier_freq = 36000, /* 36 kHz - RC-5 carrier */
1162 .duty_cycle = 25, /* 25 % - RC-5 carrier */ 1195 .duty_cycle = 25, /* 25 % - RC-5 carrier */
1163 .invert = false, 1196 .invert_level = false,
1197 .invert_carrier_sense = false,
1164}; 1198};
1165 1199
1166int cx23888_ir_probe(struct cx23885_dev *dev) 1200int cx23888_ir_probe(struct cx23885_dev *dev)