aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx23885
diff options
context:
space:
mode:
authorAndy Walls <awalls@radix.net>2009-09-27 17:31:37 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-12-05 15:40:20 -0500
commit1a0b9d89c62ddf0aed12798686fe452e7e97de42 (patch)
tree44cf19886ba11465d8dd78e267d5b56229985495 /drivers/media/video/cx23885
parent1d986add96a06f311cfef377b36602514db54507 (diff)
V4L/DVB (13097): cx23885: Complete CX23888 IR subdev implementation for Rx & almost for Tx
This change completes the v4l2_subdev implementation for IR receive for the IR controller built into the CX23888. This changes almost completes the IR transmit side also, but doesn't. Instead notes in the comments describe what needs to be done for IR Tx to work in the subdevice implementation. The current Tx behavior is skeletal and benign. If left alone, it does nothing. It will only ever generate a Tx interrupt on Tx init by a caller or when the tx_write() method is called. The ISR, when called, will then disable the Tx FIFO service interrupt. Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx23885')
-rw-r--r--drivers/media/video/cx23885/cx23888-ir.c1063
1 files changed, 1034 insertions, 29 deletions
diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c
index 12df0e3a2354..e8d949ae06b9 100644
--- a/drivers/media/video/cx23885/cx23888-ir.c
+++ b/drivers/media/video/cx23885/cx23888-ir.c
@@ -21,25 +21,79 @@
21 * 02110-1301, USA. 21 * 02110-1301, USA.
22 */ 22 */
23 23
24#include <linux/kfifo.h>
25
24#include <media/v4l2-device.h> 26#include <media/v4l2-device.h>
25#include <media/v4l2-chip-ident.h> 27#include <media/v4l2-chip-ident.h>
26 28
27#include "cx23885.h" 29#include "cx23885.h"
28 30
31static unsigned int ir_888_debug;
32module_param(ir_888_debug, int, 0644);
33MODULE_PARM_DESC(ir_888_debug, "enable debug messages [CX23888 IR controller]");
34
29#define CX23888_IR_REG_BASE 0x170000 35#define CX23888_IR_REG_BASE 0x170000
30/* 36/*
31 * These CX23888 register offsets have a straightforward one to one mapping 37 * These CX23888 register offsets have a straightforward one to one mapping
32 * to the CX23885 register offsets of 0x200 through 0x218 38 * to the CX23885 register offsets of 0x200 through 0x218
33 */ 39 */
34#define CX23888_IR_CNTRL_REG 0x170000 40#define CX23888_IR_CNTRL_REG 0x170000
41#define CNTRL_WIN_3_3 0x00000000
42#define CNTRL_WIN_4_3 0x00000001
43#define CNTRL_WIN_3_4 0x00000002
44#define CNTRL_WIN_4_4 0x00000003
45#define CNTRL_WIN 0x00000003
46#define CNTRL_EDG_NONE 0x00000000
47#define CNTRL_EDG_FALL 0x00000004
48#define CNTRL_EDG_RISE 0x00000008
49#define CNTRL_EDG_BOTH 0x0000000C
50#define CNTRL_EDG 0x0000000C
51#define CNTRL_DMD 0x00000010
52#define CNTRL_MOD 0x00000020
53#define CNTRL_RFE 0x00000040
54#define CNTRL_TFE 0x00000080
55#define CNTRL_RXE 0x00000100
56#define CNTRL_TXE 0x00000200
57#define CNTRL_RIC 0x00000400
58#define CNTRL_TIC 0x00000800
59#define CNTRL_CPL 0x00001000
60#define CNTRL_LBM 0x00002000
61#define CNTRL_R 0x00004000
62
35#define CX23888_IR_TXCLK_REG 0x170004 63#define CX23888_IR_TXCLK_REG 0x170004
64#define TXCLK_TCD 0x0000FFFF
65
36#define CX23888_IR_RXCLK_REG 0x170008 66#define CX23888_IR_RXCLK_REG 0x170008
67#define RXCLK_RCD 0x0000FFFF
68
37#define CX23888_IR_CDUTY_REG 0x17000C 69#define CX23888_IR_CDUTY_REG 0x17000C
70#define CDUTY_CDC 0x0000000F
71
38#define CX23888_IR_STATS_REG 0x170010 72#define CX23888_IR_STATS_REG 0x170010
73#define STATS_RTO 0x00000001
74#define STATS_ROR 0x00000002
75#define STATS_RBY 0x00000004
76#define STATS_TBY 0x00000008
77#define STATS_RSR 0x00000010
78#define STATS_TSR 0x00000020
79
39#define CX23888_IR_IRQEN_REG 0x170014 80#define CX23888_IR_IRQEN_REG 0x170014
81#define IRQEN_RTE 0x00000001
82#define IRQEN_ROE 0x00000002
83#define IRQEN_RSE 0x00000010
84#define IRQEN_TSE 0x00000020
85
40#define CX23888_IR_FILTR_REG 0x170018 86#define CX23888_IR_FILTR_REG 0x170018
87#define FILTR_LPF 0x0000FFFF
88
41/* This register doesn't follow the pattern; it's 0x23C on a CX23885 */ 89/* This register doesn't follow the pattern; it's 0x23C on a CX23885 */
42#define CX23888_IR_FIFO_REG 0x170040 90#define CX23888_IR_FIFO_REG 0x170040
91#define FIFO_RXTX 0x0000FFFF
92#define FIFO_RXTX_LVL 0x00010000
93#define FIFO_RXTX_RTO 0x0001FFFF
94#define FIFO_RX_NDV 0x00020000
95#define FIFO_RX_DEPTH 8
96#define FIFO_TX_DEPTH 8
43 97
44/* CX23888 unique registers */ 98/* CX23888 unique registers */
45#define CX23888_IR_SEEDP_REG 0x17001C 99#define CX23888_IR_SEEDP_REG 0x17001C
@@ -53,12 +107,32 @@
53#define CX23888_IR_DPIPG_REG 0x17003C 107#define CX23888_IR_DPIPG_REG 0x17003C
54#define CX23888_IR_LEARN_REG 0x170044 108#define CX23888_IR_LEARN_REG 0x170044
55 109
110#define CX23888_VIDCLK_FREQ 108000000 /* 108 MHz, BT.656 */
111#define CX23888_IR_REFCLK_FREQ (CX23888_VIDCLK_FREQ/2)
112
113#define CX23888_IR_RX_KFIFO_SIZE (512 * sizeof(u32))
114#define CX23888_IR_TX_KFIFO_SIZE (512 * sizeof(u32))
56 115
57struct cx23888_ir_state { 116struct cx23888_ir_state {
58 struct v4l2_subdev sd; 117 struct v4l2_subdev sd;
59 struct cx23885_dev *dev; 118 struct cx23885_dev *dev;
60 u32 id; 119 u32 id;
61 u32 rev; 120 u32 rev;
121
122 struct v4l2_subdev_ir_parameters rx_params;
123 struct mutex rx_params_lock;
124 atomic_t rxclk_divider;
125 atomic_t rx_invert;
126
127 struct kfifo *rx_kfifo;
128 spinlock_t rx_kfifo_lock;
129
130 struct v4l2_subdev_ir_parameters tx_params;
131 struct mutex tx_params_lock;
132 atomic_t txclk_divider;
133
134 struct kfifo *tx_kfifo;
135 spinlock_t tx_kfifo_lock;
62}; 136};
63 137
64static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd) 138static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd)
@@ -66,59 +140,903 @@ static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd)
66 return v4l2_get_subdevdata(sd); 140 return v4l2_get_subdevdata(sd);
67} 141}
68 142
69static int cx23888_ir_write(struct cx23885_dev *dev, u32 addr, u8 value) 143/*
144 * IR register block read and write functions
145 */
146static
147inline int cx23888_ir_write4(struct cx23885_dev *dev, u32 addr, u32 value)
70{ 148{
71 u32 reg = (addr & ~3); 149 cx_write(addr, value);
72 int shift = (addr & 3) * 8; 150 return 0;
73 u32 x = cx_read(reg); 151}
152
153static inline u32 cx23888_ir_read4(struct cx23885_dev *dev, u32 addr)
154{
155 return cx_read(addr);
156}
74 157
75 x = (x & ~(0xff << shift)) | ((u32)value << shift); 158static inline int cx23888_ir_and_or4(struct cx23885_dev *dev, u32 addr,
76 cx_write(reg, x); 159 u32 and_mask, u32 or_value)
160{
161 cx_andor(addr, ~and_mask, or_value);
77 return 0; 162 return 0;
78} 163}
79 164
80static 165/*
81inline int cx23888_ir_write4(struct cx23885_dev *dev, u32 addr, u32 value) 166 * Rx and Tx Clock Divider register computations
167 *
168 * Note the largest clock divider value of 0xffff corresponds to:
169 * (0xffff + 1) * 1000 / 108/2 MHz = 1,213,629.629... ns
170 * which fits in 21 bits, so we'll use unsigned int for time arguments.
171 */
172static inline u16 count_to_clock_divider(unsigned int d)
82{ 173{
83 cx_write(addr, value); 174 if (d > RXCLK_RCD+1)
175 d = RXCLK_RCD;
176 else if (d < 2)
177 d = 1;
178 else
179 d--;
180 return (u16) d;
181}
182
183static inline u16 ns_to_clock_divider(unsigned int ns)
184{
185 return count_to_clock_divider(
186 DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ/1000000 * ns, 1000));
187}
188
189static inline unsigned int clock_divider_to_ns(unsigned int divider)
190{
191 /* Period of the Rx or Tx clock in ns */
192 return DIV_ROUND_CLOSEST((divider + 1) * 1000,
193 CX23888_IR_REFCLK_FREQ/1000000);
194}
195
196static inline u16 carrier_freq_to_clock_divider(unsigned int freq)
197{
198 return count_to_clock_divider(
199 DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, freq * 16));
200}
201
202static inline unsigned int clock_divider_to_carrier_freq(unsigned int divider)
203{
204 return DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, (divider + 1) * 16);
205}
206
207static inline u16 freq_to_clock_divider(unsigned int freq,
208 unsigned int rollovers)
209{
210 return count_to_clock_divider(
211 DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, freq * rollovers));
212}
213
214static inline unsigned int clock_divider_to_freq(unsigned int divider,
215 unsigned int rollovers)
216{
217 return DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ,
218 (divider + 1) * rollovers);
219}
220
221/*
222 * Low Pass Filter register calculations
223 *
224 * Note the largest count value of 0xffff corresponds to:
225 * 0xffff * 1000 / 108/2 MHz = 1,213,611.11... ns
226 * which fits in 21 bits, so we'll use unsigned int for time arguments.
227 */
228static inline u16 count_to_lpf_count(unsigned int d)
229{
230 if (d > FILTR_LPF)
231 d = FILTR_LPF;
232 else if (d < 4)
233 d = 0;
234 return (u16) d;
235}
236
237static inline u16 ns_to_lpf_count(unsigned int ns)
238{
239 return count_to_lpf_count(
240 DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ/1000000 * ns, 1000));
241}
242
243static inline unsigned int lpf_count_to_ns(unsigned int count)
244{
245 /* Duration of the Low Pass Filter rejection window in ns */
246 return DIV_ROUND_CLOSEST(count * 1000, CX23888_IR_REFCLK_FREQ/1000000);
247}
248
249static inline unsigned int lpf_count_to_us(unsigned int count)
250{
251 /* Duration of the Low Pass Filter rejection window in us */
252 return DIV_ROUND_CLOSEST(count, CX23888_IR_REFCLK_FREQ/1000000);
253}
254
255/*
256 * FIFO register pulse width count compuations
257 */
258static u32 clock_divider_to_resolution(u16 divider)
259{
260 /*
261 * Resolution is the duration of 1 tick of the readable portion of
262 * of the pulse width counter as read from the FIFO. The two lsb's are
263 * not readable, hence the << 2. This function returns ns.
264 */
265 return DIV_ROUND_CLOSEST((1 << 2) * ((u32) divider + 1) * 1000,
266 CX23888_IR_REFCLK_FREQ/1000000);
267}
268
269static u64 pulse_width_count_to_ns(u16 count, u16 divider)
270{
271 u64 n;
272 u32 rem;
273
274 /*
275 * The 2 lsb's of the pulse width timer count are not readable, hence
276 * the (count << 2) | 0x3
277 */
278 n = (((u64) count << 2) | 0x3) * (divider + 1) * 1000; /* millicycles */
279 rem = do_div(n, CX23888_IR_REFCLK_FREQ/1000000); /* / MHz => ns */
280 if (rem >= CX23888_IR_REFCLK_FREQ/1000000/2)
281 n++;
282 return n;
283}
284
285static unsigned int pulse_width_count_to_us(u16 count, u16 divider)
286{
287 u64 n;
288 u32 rem;
289
290 /*
291 * The 2 lsb's of the pulse width timer count are not readable, hence
292 * the (count << 2) | 0x3
293 */
294 n = (((u64) count << 2) | 0x3) * (divider + 1); /* cycles */
295 rem = do_div(n, CX23888_IR_REFCLK_FREQ/1000000); /* / MHz => us */
296 if (rem >= CX23888_IR_REFCLK_FREQ/1000000/2)
297 n++;
298 return (unsigned int) n;
299}
300
301/*
302 * Pulse Clocks computations: Combined Pulse Width Count & Rx Clock Counts
303 *
304 * The total pulse clock count is an 18 bit pulse width timer count as the most
305 * significant part and (up to) 16 bit clock divider count as a modulus.
306 * When the Rx clock divider ticks down to 0, it increments the 18 bit pulse
307 * width timer count's least significant bit.
308 */
309static u64 ns_to_pulse_clocks(u32 ns)
310{
311 u64 clocks;
312 u32 rem;
313 clocks = CX23888_IR_REFCLK_FREQ/1000000 * (u64) ns; /* millicycles */
314 rem = do_div(clocks, 1000); /* /1000 = cycles */
315 if (rem >= 1000/2)
316 clocks++;
317 return clocks;
318}
319
320static u16 pulse_clocks_to_clock_divider(u64 count)
321{
322 u32 rem;
323
324 rem = do_div(count, (FIFO_RXTX << 2) | 0x3);
325
326 /* net result needs to be rounded down and decremented by 1 */
327 if (count > RXCLK_RCD+1)
328 count = RXCLK_RCD;
329 else if (count < 2)
330 count = 1;
331 else
332 count--;
333 return (u16) count;
334}
335
336/*
337 * IR Control Register helpers
338 */
339enum tx_fifo_watermark {
340 TX_FIFO_HALF_EMPTY = 0,
341 TX_FIFO_EMPTY = CNTRL_TIC,
342};
343
344enum rx_fifo_watermark {
345 RX_FIFO_HALF_FULL = 0,
346 RX_FIFO_NOT_EMPTY = CNTRL_RIC,
347};
348
349static inline void control_tx_irq_watermark(struct cx23885_dev *dev,
350 enum tx_fifo_watermark level)
351{
352 cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_TIC, level);
353}
354
355static inline void control_rx_irq_watermark(struct cx23885_dev *dev,
356 enum rx_fifo_watermark level)
357{
358 cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_RIC, level);
359}
360
361static inline void control_tx_enable(struct cx23885_dev *dev, bool enable)
362{
363 cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~(CNTRL_TXE | CNTRL_TFE),
364 enable ? (CNTRL_TXE | CNTRL_TFE) : 0);
365}
366
367static inline void control_rx_enable(struct cx23885_dev *dev, bool enable)
368{
369 cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~(CNTRL_RXE | CNTRL_RFE),
370 enable ? (CNTRL_RXE | CNTRL_RFE) : 0);
371}
372
373static inline void control_tx_modulation_enable(struct cx23885_dev *dev,
374 bool enable)
375{
376 cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_MOD,
377 enable ? CNTRL_MOD : 0);
378}
379
380static inline void control_rx_demodulation_enable(struct cx23885_dev *dev,
381 bool enable)
382{
383 cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_DMD,
384 enable ? CNTRL_DMD : 0);
385}
386
387static inline void control_rx_s_edge_detection(struct cx23885_dev *dev,
388 u32 edge_types)
389{
390 cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_EDG_BOTH,
391 edge_types & CNTRL_EDG_BOTH);
392}
393
394static void control_rx_s_carrier_window(struct cx23885_dev *dev,
395 unsigned int carrier,
396 unsigned int *carrier_range_low,
397 unsigned int *carrier_range_high)
398{
399 u32 v;
400 unsigned int c16 = carrier * 16;
401
402 if (*carrier_range_low < DIV_ROUND_CLOSEST(c16, 16 + 3)) {
403 v = CNTRL_WIN_3_4;
404 *carrier_range_low = DIV_ROUND_CLOSEST(c16, 16 + 4);
405 } else {
406 v = CNTRL_WIN_3_3;
407 *carrier_range_low = DIV_ROUND_CLOSEST(c16, 16 + 3);
408 }
409
410 if (*carrier_range_high > DIV_ROUND_CLOSEST(c16, 16 - 3)) {
411 v |= CNTRL_WIN_4_3;
412 *carrier_range_high = DIV_ROUND_CLOSEST(c16, 16 - 4);
413 } else {
414 v |= CNTRL_WIN_3_3;
415 *carrier_range_high = DIV_ROUND_CLOSEST(c16, 16 - 3);
416 }
417 cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_WIN, v);
418}
419
420static inline void control_tx_polarity_invert(struct cx23885_dev *dev,
421 bool invert)
422{
423 cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_CPL,
424 invert ? CNTRL_CPL : 0);
425}
426
427/*
428 * IR Rx & Tx Clock Register helpers
429 */
430static unsigned int txclk_tx_s_carrier(struct cx23885_dev *dev,
431 unsigned int freq,
432 u16 *divider)
433{
434 *divider = carrier_freq_to_clock_divider(freq);
435 cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider);
436 return clock_divider_to_carrier_freq(*divider);
437}
438
439static unsigned int rxclk_rx_s_carrier(struct cx23885_dev *dev,
440 unsigned int freq,
441 u16 *divider)
442{
443 *divider = carrier_freq_to_clock_divider(freq);
444 cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider);
445 return clock_divider_to_carrier_freq(*divider);
446}
447
448static u32 txclk_tx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns,
449 u16 *divider)
450{
451 u64 pulse_clocks;
452
453 if (ns > V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS)
454 ns = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS;
455 pulse_clocks = ns_to_pulse_clocks(ns);
456 *divider = pulse_clocks_to_clock_divider(pulse_clocks);
457 cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider);
458 return (u32) pulse_width_count_to_ns(FIFO_RXTX, *divider);
459}
460
461static u32 rxclk_rx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns,
462 u16 *divider)
463{
464 u64 pulse_clocks;
465
466 if (ns > V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS)
467 ns = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS;
468 pulse_clocks = ns_to_pulse_clocks(ns);
469 *divider = pulse_clocks_to_clock_divider(pulse_clocks);
470 cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider);
471 return (u32) pulse_width_count_to_ns(FIFO_RXTX, *divider);
472}
473
474/*
475 * IR Tx Carrier Duty Cycle register helpers
476 */
477static unsigned int cduty_tx_s_duty_cycle(struct cx23885_dev *dev,
478 unsigned int duty_cycle)
479{
480 u32 n;
481 n = DIV_ROUND_CLOSEST(duty_cycle * 100, 625); /* 16ths of 100% */
482 if (n != 0)
483 n--;
484 if (n > 15)
485 n = 15;
486 cx23888_ir_write4(dev, CX23888_IR_CDUTY_REG, n);
487 return DIV_ROUND_CLOSEST((n+1) * 100, 16);
488}
489
490/*
491 * IR Filter Register helpers
492 */
493static u32 filter_rx_s_min_width(struct cx23885_dev *dev, u32 min_width_ns)
494{
495 u32 count = ns_to_lpf_count(min_width_ns);
496 cx23888_ir_write4(dev, CX23888_IR_FILTR_REG, count);
497 return lpf_count_to_ns(count);
498}
499
500/*
501 * IR IRQ Enable Register helpers
502 */
503static inline void irqenable_rx(struct cx23885_dev *dev, u32 mask)
504{
505 mask &= (IRQEN_RTE | IRQEN_ROE | IRQEN_RSE);
506 cx23888_ir_and_or4(dev, CX23888_IR_IRQEN_REG,
507 ~(IRQEN_RTE | IRQEN_ROE | IRQEN_RSE), mask);
508}
509
510static inline void irqenable_tx(struct cx23885_dev *dev, u32 mask)
511{
512 mask &= IRQEN_TSE;
513 cx23888_ir_and_or4(dev, CX23888_IR_IRQEN_REG, ~IRQEN_TSE, mask);
514}
515
516/*
517 * V4L2 Subdevice IR Ops
518 */
519static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status,
520 bool *handled)
521{
522 struct cx23888_ir_state *state = to_state(sd);
523 struct cx23885_dev *dev = state->dev;
524
525 u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG);
526 u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG);
527 u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG);
528
529 u32 rx_data[FIFO_RX_DEPTH];
530 int i, j, k;
531 u32 events, v;
532 int tsr, rsr, rto, ror, tse, rse, rte, roe, kror;
533
534 tsr = stats & STATS_TSR; /* Tx FIFO Service Request */
535 rsr = stats & STATS_RSR; /* Rx FIFO Service Request */
536 rto = stats & STATS_RTO; /* Rx Pulse Width Timer Time Out */
537 ror = stats & STATS_ROR; /* Rx FIFO Over Run */
538
539 tse = irqen & IRQEN_TSE; /* Tx FIFO Service Request IRQ Enable */
540 rse = irqen & IRQEN_RSE; /* Rx FIFO Service Reuqest IRQ Enable */
541 rte = irqen & IRQEN_RTE; /* Rx Pulse Width Timer Time Out IRQ Enable */
542 roe = irqen & IRQEN_ROE; /* Rx FIFO Over Run IRQ Enable */
543
544 *handled = false;
545 v4l2_dbg(2, ir_888_debug, sd, "IRQ Status: %s %s %s %s %s %s\n",
546 tsr ? "tsr" : " ", rsr ? "rsr" : " ",
547 rto ? "rto" : " ", ror ? "ror" : " ",
548 stats & STATS_TBY ? "tby" : " ",
549 stats & STATS_RBY ? "rby" : " ");
550
551 v4l2_dbg(2, ir_888_debug, sd, "IRQ Enables: %s %s %s %s\n",
552 tse ? "tse" : " ", rse ? "rse" : " ",
553 rte ? "rte" : " ", roe ? "roe" : " ");
554
555 /*
556 * Transmitter interrupt service
557 */
558 if (tse && tsr) {
559 /*
560 * TODO:
561 * Check the watermark threshold setting
562 * Pull FIFO_TX_DEPTH or FIFO_TX_DEPTH/2 entries from tx_kfifo
563 * Push the data to the hardware FIFO.
564 * If there was nothing more to send in the tx_kfifo, disable
565 * the TSR IRQ and notify the v4l2_device.
566 * If there was something in the tx_kfifo, check the tx_kfifo
567 * level and notify the v4l2_device, if it is low.
568 */
569 /* For now, inhibit TSR interrupt until Tx is implemented */
570 irqenable_tx(dev, 0);
571 events = V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ;
572 v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_TX_NOTIFY, &events);
573 *handled = true;
574 }
575
576 /*
577 * Receiver interrupt service
578 */
579 kror = 0;
580 if ((rse && rsr) || (rte && rto)) {
581 /*
582 * Receive data on RSR to clear the STATS_RSR.
583 * Receive data on RTO, since we may not have yet hit the RSR
584 * watermark when we receive the RTO.
585 */
586 for (i = 0, v = FIFO_RX_NDV;
587 (v & FIFO_RX_NDV) && !kror; i = 0) {
588 for (j = 0;
589 (v & FIFO_RX_NDV) && j < FIFO_RX_DEPTH; j++) {
590 v = cx23888_ir_read4(dev, CX23888_IR_FIFO_REG);
591 rx_data[i++] = v & ~FIFO_RX_NDV;
592 }
593 if (i == 0)
594 break;
595 j = i * sizeof(u32);
596 k = kfifo_put(state->rx_kfifo,
597 (unsigned char *) rx_data, j);
598 if (k != j)
599 kror++; /* rx_kfifo over run */
600 }
601 *handled = true;
602 }
603
604 events = 0;
605 v = 0;
606 if (kror) {
607 events |= V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN;
608 v4l2_err(sd, "IR receiver software FIFO overrun\n");
609 }
610 if (roe && ror) {
611 /*
612 * The RX FIFO Enable (CNTRL_RFE) must be toggled to clear
613 * the Rx FIFO Over Run status (STATS_ROR)
614 */
615 v |= CNTRL_RFE;
616 events |= V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN;
617 v4l2_err(sd, "IR receiver hardware FIFO overrun\n");
618 }
619 if (rte && rto) {
620 /*
621 * The IR Receiver Enable (CNTRL_RXE) must be toggled to clear
622 * the Rx Pulse Width Timer Time Out (STATS_RTO)
623 */
624 v |= CNTRL_RXE;
625 events |= V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED;
626 }
627 if (v) {
628 /* Clear STATS_ROR & STATS_RTO as needed by reseting hardware */
629 cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl & ~v);
630 cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl);
631 *handled = true;
632 }
633 if (kfifo_len(state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE/2)
634 events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ;
635
636 if (events)
637 v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_RX_NOTIFY, &events);
84 return 0; 638 return 0;
85} 639}
86 640
87static u8 cx23888_ir_read(struct cx23885_dev *dev, u32 addr) 641/* Receiver */
642static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
643 ssize_t *num)
88{ 644{
89 u32 x = cx_read((addr & ~3)); 645 struct cx23888_ir_state *state = to_state(sd);
90 int shift = (addr & 3) * 8; 646 bool invert = (bool) atomic_read(&state->rx_invert);
647 u16 divider = (u16) atomic_read(&state->rxclk_divider);
648
649 unsigned int i, n;
650 u32 *p;
651 u32 u, v;
652
653 n = count / sizeof(u32) * sizeof(u32);
654 if (n == 0) {
655 *num = 0;
656 return 0;
657 }
658
659 n = kfifo_get(state->rx_kfifo, buf, n);
660
661 n /= sizeof(u32);
662 *num = n * sizeof(u32);
663
664 for (p = (u32 *) buf, i = 0; i < n; p++, i++) {
665 if ((*p & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
666 *p = V4L2_SUBDEV_IR_PULSE_RX_SEQ_END;
667 v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n");
668 continue;
669 }
670
671 u = (*p & FIFO_RXTX_LVL) ? V4L2_SUBDEV_IR_PULSE_LEVEL_MASK : 0;
672 if (invert)
673 u = u ? 0 : V4L2_SUBDEV_IR_PULSE_LEVEL_MASK;
91 674
92 return (x >> shift) & 0xff; 675 v = (u32) pulse_width_count_to_ns((u16) (*p & FIFO_RXTX),
676 divider);
677 if (v >= V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS)
678 v = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS - 1;
679
680 *p = u | v;
681
682 v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns %s\n",
683 v, u ? "mark" : "space");
684 }
685 return 0;
93} 686}
94 687
95static inline u32 cx23888_ir_read4(struct cx23885_dev *dev, u32 addr) 688static int cx23888_ir_rx_g_parameters(struct v4l2_subdev *sd,
689 struct v4l2_subdev_ir_parameters *p)
96{ 690{
97 return cx_read(addr); 691 struct cx23888_ir_state *state = to_state(sd);
692 mutex_lock(&state->rx_params_lock);
693 memcpy(p, &state->rx_params, sizeof(struct v4l2_subdev_ir_parameters));
694 mutex_unlock(&state->rx_params_lock);
695 return 0;
98} 696}
99 697
100static int cx23888_ir_and_or(struct cx23885_dev *dev, u32 addr, 698static int cx23888_ir_rx_shutdown(struct v4l2_subdev *sd)
101 unsigned and_mask, u8 or_value)
102{ 699{
103 return cx23888_ir_write(dev, addr, 700 struct cx23888_ir_state *state = to_state(sd);
104 (cx23888_ir_read(dev, addr) & and_mask) | 701 struct cx23885_dev *dev = state->dev;
105 or_value); 702
703 mutex_lock(&state->rx_params_lock);
704
705 /* Disable or slow down all IR Rx circuits and counters */
706 irqenable_rx(dev, 0);
707 control_rx_enable(dev, false);
708 control_rx_demodulation_enable(dev, false);
709 control_rx_s_edge_detection(dev, CNTRL_EDG_NONE);
710 filter_rx_s_min_width(dev, 0);
711 cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, RXCLK_RCD);
712
713 state->rx_params.shutdown = true;
714
715 mutex_unlock(&state->rx_params_lock);
716 return 0;
106} 717}
107 718
108static inline int cx23888_ir_and_or4(struct cx23885_dev *dev, u32 addr, 719static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd,
109 u32 and_mask, u32 or_value) 720 struct v4l2_subdev_ir_parameters *p)
110{ 721{
111 cx_andor(addr, and_mask, or_value); 722 struct cx23888_ir_state *state = to_state(sd);
723 struct cx23885_dev *dev = state->dev;
724 struct v4l2_subdev_ir_parameters *o = &state->rx_params;
725 u16 rxclk_divider;
726
727 if (p->shutdown)
728 return cx23888_ir_rx_shutdown(sd);
729
730 if (p->mode != V4L2_SUBDEV_IR_MODE_PULSE_WIDTH)
731 return -ENOSYS;
732
733 mutex_lock(&state->rx_params_lock);
734
735 o->shutdown = p->shutdown;
736
737 o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
738
739 o->bytes_per_data_element = p->bytes_per_data_element = sizeof(u32);
740
741 /* Before we tweak the hardware, we have to disable the receiver */
742 irqenable_rx(dev, 0);
743 control_rx_enable(dev, false);
744
745 control_rx_demodulation_enable(dev, p->modulation);
746 o->modulation = p->modulation;
747
748 if (p->modulation) {
749 p->carrier_freq = rxclk_rx_s_carrier(dev, p->carrier_freq,
750 &rxclk_divider);
751
752 o->carrier_freq = p->carrier_freq;
753
754 o->duty_cycle = p->duty_cycle = 50;
755
756 control_rx_s_carrier_window(dev, p->carrier_freq,
757 &p->carrier_range_lower,
758 &p->carrier_range_upper);
759 o->carrier_range_lower = p->carrier_range_lower;
760 o->carrier_range_upper = p->carrier_range_upper;
761 } else {
762 p->max_pulse_width =
763 rxclk_rx_s_max_pulse_width(dev, p->max_pulse_width,
764 &rxclk_divider);
765 o->max_pulse_width = p->max_pulse_width;
766 }
767 atomic_set(&state->rxclk_divider, rxclk_divider);
768
769 p->noise_filter_min_width =
770 filter_rx_s_min_width(dev, p->noise_filter_min_width);
771 o->noise_filter_min_width = p->noise_filter_min_width;
772
773 p->resolution = clock_divider_to_resolution(rxclk_divider);
774 o->resolution = p->resolution;
775
776 /* FIXME - make this dependent on resolution for better performance */
777 control_rx_irq_watermark(dev, RX_FIFO_HALF_FULL);
778
779 control_rx_s_edge_detection(dev, CNTRL_EDG_BOTH);
780
781 o->invert = p->invert;
782 atomic_set(&state->rx_invert, p->invert);
783
784 o->interrupt_enable = p->interrupt_enable;
785 o->enable = p->enable;
786 if (p->enable) {
787 kfifo_reset(state->rx_kfifo);
788 if (p->interrupt_enable)
789 irqenable_rx(dev, IRQEN_RSE | IRQEN_RTE | IRQEN_ROE);
790 control_rx_enable(dev, p->enable);
791 }
792
793 mutex_unlock(&state->rx_params_lock);
794 return 0;
795}
796
797/* Transmitter */
798static int cx23888_ir_tx_write(struct v4l2_subdev *sd, u8 *buf, size_t count,
799 ssize_t *num)
800{
801 struct cx23888_ir_state *state = to_state(sd);
802 struct cx23885_dev *dev = state->dev;
803 /* For now enable the Tx FIFO Service interrupt & pretend we did work */
804 irqenable_tx(dev, IRQEN_TSE);
805 *num = count;
806 return 0;
807}
808
809static int cx23888_ir_tx_g_parameters(struct v4l2_subdev *sd,
810 struct v4l2_subdev_ir_parameters *p)
811{
812 struct cx23888_ir_state *state = to_state(sd);
813 mutex_lock(&state->tx_params_lock);
814 memcpy(p, &state->tx_params, sizeof(struct v4l2_subdev_ir_parameters));
815 mutex_unlock(&state->tx_params_lock);
112 return 0; 816 return 0;
113} 817}
114 818
819static int cx23888_ir_tx_shutdown(struct v4l2_subdev *sd)
820{
821 struct cx23888_ir_state *state = to_state(sd);
822 struct cx23885_dev *dev = state->dev;
823
824 mutex_lock(&state->tx_params_lock);
825
826 /* Disable or slow down all IR Tx circuits and counters */
827 irqenable_tx(dev, 0);
828 control_tx_enable(dev, false);
829 control_tx_modulation_enable(dev, false);
830 cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, TXCLK_TCD);
831
832 state->tx_params.shutdown = true;
833
834 mutex_unlock(&state->tx_params_lock);
835 return 0;
836}
837
838static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd,
839 struct v4l2_subdev_ir_parameters *p)
840{
841 struct cx23888_ir_state *state = to_state(sd);
842 struct cx23885_dev *dev = state->dev;
843 struct v4l2_subdev_ir_parameters *o = &state->tx_params;
844 u16 txclk_divider;
845
846 if (p->shutdown)
847 return cx23888_ir_tx_shutdown(sd);
848
849 if (p->mode != V4L2_SUBDEV_IR_MODE_PULSE_WIDTH)
850 return -ENOSYS;
851
852 mutex_lock(&state->tx_params_lock);
853
854 o->shutdown = p->shutdown;
855
856 o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
857
858 o->bytes_per_data_element = p->bytes_per_data_element = sizeof(u32);
859
860 /* Before we tweak the hardware, we have to disable the transmitter */
861 irqenable_tx(dev, 0);
862 control_tx_enable(dev, false);
863
864 control_tx_modulation_enable(dev, p->modulation);
865 o->modulation = p->modulation;
866
867 if (p->modulation) {
868 p->carrier_freq = txclk_tx_s_carrier(dev, p->carrier_freq,
869 &txclk_divider);
870 o->carrier_freq = p->carrier_freq;
871
872 p->duty_cycle = cduty_tx_s_duty_cycle(dev, p->duty_cycle);
873 o->duty_cycle = p->duty_cycle;
874 } else {
875 p->max_pulse_width =
876 txclk_tx_s_max_pulse_width(dev, p->max_pulse_width,
877 &txclk_divider);
878 o->max_pulse_width = p->max_pulse_width;
879 }
880 atomic_set(&state->txclk_divider, txclk_divider);
881
882 p->resolution = clock_divider_to_resolution(txclk_divider);
883 o->resolution = p->resolution;
884
885 /* FIXME - make this dependent on resolution for better performance */
886 control_tx_irq_watermark(dev, TX_FIFO_HALF_EMPTY);
887
888 control_tx_polarity_invert(dev, p->invert);
889 o->invert = p->invert;
890
891 o->interrupt_enable = p->interrupt_enable;
892 o->enable = p->enable;
893 if (p->enable) {
894 kfifo_reset(state->tx_kfifo);
895 if (p->interrupt_enable)
896 irqenable_tx(dev, IRQEN_TSE);
897 control_tx_enable(dev, p->enable);
898 }
899
900 mutex_unlock(&state->tx_params_lock);
901 return 0;
902}
903
904
905/*
906 * V4L2 Subdevice Core Ops
907 */
115static int cx23888_ir_log_status(struct v4l2_subdev *sd) 908static int cx23888_ir_log_status(struct v4l2_subdev *sd)
116{ 909{
117 struct cx23888_ir_state *state = to_state(sd); 910 struct cx23888_ir_state *state = to_state(sd);
118 struct cx23885_dev *dev = state->dev; 911 struct cx23885_dev *dev = state->dev;
119 u8 cntrl = cx23888_ir_read(dev, CX23888_IR_CNTRL_REG+1); 912 char *s;
120 v4l2_info(sd, "receiver %sabled\n", cntrl & 0x1 ? "en" : "dis"); 913 int i, j;
121 v4l2_info(sd, "transmitter %sabled\n", cntrl & 0x2 ? "en" : "dis"); 914
915 u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG);
916 u32 txclk = cx23888_ir_read4(dev, CX23888_IR_TXCLK_REG) & TXCLK_TCD;
917 u32 rxclk = cx23888_ir_read4(dev, CX23888_IR_RXCLK_REG) & RXCLK_RCD;
918 u32 cduty = cx23888_ir_read4(dev, CX23888_IR_CDUTY_REG) & CDUTY_CDC;
919 u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG);
920 u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG);
921 u32 filtr = cx23888_ir_read4(dev, CX23888_IR_FILTR_REG) & FILTR_LPF;
922
923 v4l2_info(sd, "IR Receiver:\n");
924 v4l2_info(sd, "\tEnabled: %s\n",
925 cntrl & CNTRL_RXE ? "yes" : "no");
926 v4l2_info(sd, "\tDemodulation from a carrier: %s\n",
927 cntrl & CNTRL_DMD ? "enabled" : "disabled");
928 v4l2_info(sd, "\tFIFO: %s\n",
929 cntrl & CNTRL_RFE ? "enabled" : "disabled");
930 switch (cntrl & CNTRL_EDG) {
931 case CNTRL_EDG_NONE:
932 s = "disabled";
933 break;
934 case CNTRL_EDG_FALL:
935 s = "falling edge";
936 break;
937 case CNTRL_EDG_RISE:
938 s = "rising edge";
939 break;
940 case CNTRL_EDG_BOTH:
941 s = "rising & falling edges";
942 break;
943 default:
944 s = "??? edge";
945 break;
946 }
947 v4l2_info(sd, "\tPulse timers' start/stop trigger: %s\n", s);
948 v4l2_info(sd, "\tFIFO data on pulse timer overflow: %s\n",
949 cntrl & CNTRL_R ? "not loaded" : "overflow marker");
950 v4l2_info(sd, "\tFIFO interrupt watermark: %s\n",
951 cntrl & CNTRL_RIC ? "not empty" : "half full or greater");
952 v4l2_info(sd, "\tLoopback mode: %s\n",
953 cntrl & CNTRL_LBM ? "loopback active" : "normal receive");
954 if (cntrl & CNTRL_DMD) {
955 v4l2_info(sd, "\tExpected carrier (16 clocks): %u Hz\n",
956 clock_divider_to_carrier_freq(rxclk));
957 switch (cntrl & CNTRL_WIN) {
958 case CNTRL_WIN_3_3:
959 i = 3;
960 j = 3;
961 break;
962 case CNTRL_WIN_4_3:
963 i = 4;
964 j = 3;
965 break;
966 case CNTRL_WIN_3_4:
967 i = 3;
968 j = 4;
969 break;
970 case CNTRL_WIN_4_4:
971 i = 4;
972 j = 4;
973 break;
974 default:
975 i = 0;
976 j = 0;
977 break;
978 }
979 v4l2_info(sd, "\tNext carrier edge window: 16 clocks "
980 "-%1d/+%1d, %u to %u Hz\n", i, j,
981 clock_divider_to_freq(rxclk, 16 + j),
982 clock_divider_to_freq(rxclk, 16 - i));
983 } else {
984 v4l2_info(sd, "\tMax measurable pulse width: %u us, "
985 "%llu ns\n",
986 pulse_width_count_to_us(FIFO_RXTX, rxclk),
987 pulse_width_count_to_ns(FIFO_RXTX, rxclk));
988 }
989 v4l2_info(sd, "\tLow pass filter: %s\n",
990 filtr ? "enabled" : "disabled");
991 if (filtr)
992 v4l2_info(sd, "\tMin acceptable pulse width (LPF): %u us, "
993 "%u ns\n",
994 lpf_count_to_us(filtr),
995 lpf_count_to_ns(filtr));
996 v4l2_info(sd, "\tPulse width timer timed-out: %s\n",
997 stats & STATS_RTO ? "yes" : "no");
998 v4l2_info(sd, "\tPulse width timer time-out intr: %s\n",
999 irqen & IRQEN_RTE ? "enabled" : "disabled");
1000 v4l2_info(sd, "\tFIFO overrun: %s\n",
1001 stats & STATS_ROR ? "yes" : "no");
1002 v4l2_info(sd, "\tFIFO overrun interrupt: %s\n",
1003 irqen & IRQEN_ROE ? "enabled" : "disabled");
1004 v4l2_info(sd, "\tBusy: %s\n",
1005 stats & STATS_RBY ? "yes" : "no");
1006 v4l2_info(sd, "\tFIFO service requested: %s\n",
1007 stats & STATS_RSR ? "yes" : "no");
1008 v4l2_info(sd, "\tFIFO service request interrupt: %s\n",
1009 irqen & IRQEN_RSE ? "enabled" : "disabled");
1010
1011 v4l2_info(sd, "IR Transmitter:\n");
1012 v4l2_info(sd, "\tEnabled: %s\n",
1013 cntrl & CNTRL_TXE ? "yes" : "no");
1014 v4l2_info(sd, "\tModulation onto a carrier: %s\n",
1015 cntrl & CNTRL_MOD ? "enabled" : "disabled");
1016 v4l2_info(sd, "\tFIFO: %s\n",
1017 cntrl & CNTRL_TFE ? "enabled" : "disabled");
1018 v4l2_info(sd, "\tFIFO interrupt watermark: %s\n",
1019 cntrl & CNTRL_TIC ? "not empty" : "half full or less");
1020 v4l2_info(sd, "\tSignal polarity: %s\n",
1021 cntrl & CNTRL_CPL ? "0:mark 1:space" : "0:space 1:mark");
1022 if (cntrl & CNTRL_MOD) {
1023 v4l2_info(sd, "\tCarrier (16 clocks): %u Hz\n",
1024 clock_divider_to_carrier_freq(txclk));
1025 v4l2_info(sd, "\tCarrier duty cycle: %2u/16\n",
1026 cduty + 1);
1027 } else {
1028 v4l2_info(sd, "\tMax pulse width: %u us, "
1029 "%llu ns\n",
1030 pulse_width_count_to_us(FIFO_RXTX, txclk),
1031 pulse_width_count_to_ns(FIFO_RXTX, txclk));
1032 }
1033 v4l2_info(sd, "\tBusy: %s\n",
1034 stats & STATS_TBY ? "yes" : "no");
1035 v4l2_info(sd, "\tFIFO service requested: %s\n",
1036 stats & STATS_TSR ? "yes" : "no");
1037 v4l2_info(sd, "\tFIFO service request interrupt: %s\n",
1038 irqen & IRQEN_TSE ? "enabled" : "disabled");
1039
122 return 0; 1040 return 0;
123} 1041}
124 1042
@@ -187,19 +1105,81 @@ static const struct v4l2_subdev_core_ops cx23888_ir_core_ops = {
187#endif 1105#endif
188}; 1106};
189 1107
1108static const struct v4l2_subdev_ir_ops cx23888_ir_ir_ops = {
1109 .interrupt_service_routine = cx23888_ir_irq_handler,
1110
1111 .rx_read = cx23888_ir_rx_read,
1112 .rx_g_parameters = cx23888_ir_rx_g_parameters,
1113 .rx_s_parameters = cx23888_ir_rx_s_parameters,
1114
1115 .tx_write = cx23888_ir_tx_write,
1116 .tx_g_parameters = cx23888_ir_tx_g_parameters,
1117 .tx_s_parameters = cx23888_ir_tx_s_parameters,
1118};
1119
190static const struct v4l2_subdev_ops cx23888_ir_controller_ops = { 1120static const struct v4l2_subdev_ops cx23888_ir_controller_ops = {
191 .core = &cx23888_ir_core_ops, 1121 .core = &cx23888_ir_core_ops,
1122 .ir = &cx23888_ir_ir_ops,
1123};
1124
1125static const struct v4l2_subdev_ir_parameters default_rx_params = {
1126 .bytes_per_data_element = sizeof(u32),
1127 .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
1128
1129 .enable = false,
1130 .interrupt_enable = false,
1131 .shutdown = true,
1132
1133 .modulation = true,
1134 .carrier_freq = 36000, /* 36 kHz - RC-5, RC-6, and RC-6A carrier */
1135
1136 /* RC-5: 666,667 ns = 1/36 kHz * 32 cycles * 1 mark * 0.75 */
1137 /* RC-6A: 333,333 ns = 1/36 kHz * 16 cycles * 1 mark * 0.75 */
1138 .noise_filter_min_width = 333333, /* ns */
1139 .carrier_range_lower = 35000,
1140 .carrier_range_upper = 37000,
1141 .invert = false,
1142};
1143
1144static const struct v4l2_subdev_ir_parameters default_tx_params = {
1145 .bytes_per_data_element = sizeof(u32),
1146 .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
1147
1148 .enable = false,
1149 .interrupt_enable = false,
1150 .shutdown = true,
1151
1152 .modulation = true,
1153 .carrier_freq = 36000, /* 36 kHz - RC-5 carrier */
1154 .duty_cycle = 25, /* 25 % - RC-5 carrier */
1155 .invert = false,
192}; 1156};
193 1157
194int cx23888_ir_probe(struct cx23885_dev *dev) 1158int cx23888_ir_probe(struct cx23885_dev *dev)
195{ 1159{
196 struct cx23888_ir_state *state; 1160 struct cx23888_ir_state *state;
197 struct v4l2_subdev *sd; 1161 struct v4l2_subdev *sd;
1162 struct v4l2_subdev_ir_parameters default_params;
1163 int ret;
198 1164
199 state = kzalloc(sizeof(struct cx23888_ir_state), GFP_KERNEL); 1165 state = kzalloc(sizeof(struct cx23888_ir_state), GFP_KERNEL);
200 if (state == NULL) 1166 if (state == NULL)
201 return -ENOMEM; 1167 return -ENOMEM;
202 1168
1169 spin_lock_init(&state->rx_kfifo_lock);
1170 state->rx_kfifo = kfifo_alloc(CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL,
1171 &state->rx_kfifo_lock);
1172 if (state->rx_kfifo == NULL)
1173 return -ENOMEM;
1174
1175 spin_lock_init(&state->tx_kfifo_lock);
1176 state->tx_kfifo = kfifo_alloc(CX23888_IR_TX_KFIFO_SIZE, GFP_KERNEL,
1177 &state->tx_kfifo_lock);
1178 if (state->tx_kfifo == NULL) {
1179 kfifo_free(state->rx_kfifo);
1180 return -ENOMEM;
1181 }
1182
203 state->dev = dev; 1183 state->dev = dev;
204 state->id = V4L2_IDENT_CX23888_IR; 1184 state->id = V4L2_IDENT_CX23888_IR;
205 state->rev = 0; 1185 state->rev = 0;
@@ -210,7 +1190,30 @@ int cx23888_ir_probe(struct cx23885_dev *dev)
210 /* FIXME - fix the formatting of dev->v4l2_dev.name and use it */ 1190 /* FIXME - fix the formatting of dev->v4l2_dev.name and use it */
211 snprintf(sd->name, sizeof(sd->name), "%s/888-ir", dev->name); 1191 snprintf(sd->name, sizeof(sd->name), "%s/888-ir", dev->name);
212 sd->grp_id = CX23885_HW_888_IR; 1192 sd->grp_id = CX23885_HW_888_IR;
213 return v4l2_device_register_subdev(&dev->v4l2_dev, sd); 1193
1194 ret = v4l2_device_register_subdev(&dev->v4l2_dev, sd);
1195 if (ret == 0) {
1196 /*
1197 * Ensure no interrupts arrive from '888 specific conditions,
1198 * since we ignore them in this driver to have commonality with
1199 * similar IR controller cores.
1200 */
1201 cx23888_ir_write4(dev, CX23888_IR_IRQEN_REG, 0);
1202
1203 mutex_init(&state->rx_params_lock);
1204 memcpy(&default_params, &default_rx_params,
1205 sizeof(struct v4l2_subdev_ir_parameters));
1206 v4l2_subdev_call(sd, ir, rx_s_parameters, &default_params);
1207
1208 mutex_init(&state->tx_params_lock);
1209 memcpy(&default_params, &default_tx_params,
1210 sizeof(struct v4l2_subdev_ir_parameters));
1211 v4l2_subdev_call(sd, ir, tx_s_parameters, &default_params);
1212 } else {
1213 kfifo_free(state->rx_kfifo);
1214 kfifo_free(state->tx_kfifo);
1215 }
1216 return ret;
214} 1217}
215 1218
216int cx23888_ir_remove(struct cx23885_dev *dev) 1219int cx23888_ir_remove(struct cx23885_dev *dev)
@@ -222,11 +1225,13 @@ int cx23888_ir_remove(struct cx23885_dev *dev)
222 if (sd == NULL) 1225 if (sd == NULL)
223 return -ENODEV; 1226 return -ENODEV;
224 1227
225 /* Disable receiver and transmitter */ 1228 cx23888_ir_rx_shutdown(sd);
226 cx23888_ir_and_or(dev, CX23888_IR_CNTRL_REG+1, 0xfc, 0); 1229 cx23888_ir_tx_shutdown(sd);
227 1230
228 state = to_state(sd); 1231 state = to_state(sd);
229 v4l2_device_unregister_subdev(sd); 1232 v4l2_device_unregister_subdev(sd);
1233 kfifo_free(state->rx_kfifo);
1234 kfifo_free(state->tx_kfifo);
230 kfree(state); 1235 kfree(state);
231 /* Nothing more to free() as state held the actual v4l2_subdev object */ 1236 /* Nothing more to free() as state held the actual v4l2_subdev object */
232 return 0; 1237 return 0;