1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include <media/v4l2-chip-ident.h>
26#include "cx18-driver.h"
27#include "cx18-io.h"
28#include "cx18-cards.h"
29
30int cx18_av_write(struct cx18 *cx, u16 addr, u8 value)
31{
32 u32 reg = 0xc40000 + (addr & ~3);
33 u32 mask = 0xff;
34 int shift = (addr & 3) * 8;
35 u32 x = cx18_read_reg(cx, reg);
36
37 x = (x & ~(mask << shift)) | ((u32)value << shift);
38 cx18_write_reg(cx, x, reg);
39 return 0;
40}
41
42int cx18_av_write_expect(struct cx18 *cx, u16 addr, u8 value, u8 eval, u8 mask)
43{
44 u32 reg = 0xc40000 + (addr & ~3);
45 int shift = (addr & 3) * 8;
46 u32 x = cx18_read_reg(cx, reg);
47
48 x = (x & ~((u32)0xff << shift)) | ((u32)value << shift);
49 cx18_write_reg_expect(cx, x, reg,
50 ((u32)eval << shift), ((u32)mask << shift));
51 return 0;
52}
53
54int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value)
55{
56 cx18_write_reg(cx, value, 0xc40000 + addr);
57 return 0;
58}
59
60int
61cx18_av_write4_expect(struct cx18 *cx, u16 addr, u32 value, u32 eval, u32 mask)
62{
63 cx18_write_reg_expect(cx, value, 0xc40000 + addr, eval, mask);
64 return 0;
65}
66
67int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value)
68{
69 cx18_write_reg_noretry(cx, value, 0xc40000 + addr);
70 return 0;
71}
72
73u8 cx18_av_read(struct cx18 *cx, u16 addr)
74{
75 u32 x = cx18_read_reg(cx, 0xc40000 + (addr & ~3));
76 int shift = (addr & 3) * 8;
77
78 return (x >> shift) & 0xff;
79}
80
81u32 cx18_av_read4(struct cx18 *cx, u16 addr)
82{
83 return cx18_read_reg(cx, 0xc40000 + addr);
84}
85
86int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned and_mask,
87 u8 or_value)
88{
89 return cx18_av_write(cx, addr,
90 (cx18_av_read(cx, addr) & and_mask) |
91 or_value);
92}
93
94int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 and_mask,
95 u32 or_value)
96{
97 return cx18_av_write4(cx, addr,
98 (cx18_av_read4(cx, addr) & and_mask) |
99 or_value);
100}
101
102static void cx18_av_init(struct cx18 *cx)
103{
104
105
106
107
108
109
110
111
112
113
114 cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f);
115
116
117
118 cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe);
119
120
121
122 cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad);
123
124
125 cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56);
126}
127
128static void cx18_av_initialize(struct v4l2_subdev *sd)
129{
130 struct cx18_av_state *state = to_cx18_av_state(sd);
131 struct cx18 *cx = v4l2_get_subdevdata(sd);
132 u32 v;
133
134 cx18_av_loadfw(cx);
135
136 cx18_av_write4_expect(cx, CXADEC_DL_CTL, 0x03000000,
137 0x03000000, 0x13000000);
138
139
140 v = cx18_av_read4(cx, CXADEC_HOST_REG1);
141
142 cx18_av_write4_expect(cx, CXADEC_HOST_REG1, v | 1, v, 0xfffe);
143
144 cx18_av_write4_expect(cx, CXADEC_HOST_REG1, v & 0xfffe,
145 v & 0xfffe, 0xffff);
146
147
148 v = cx18_av_read4(cx, CXADEC_DLL1_DIAG_CTRL) & 0xE1FFFEFF;
149
150 cx18_av_write4(cx, CXADEC_DLL1_DIAG_CTRL, v);
151
152 cx18_av_write4(cx, CXADEC_DLL1_DIAG_CTRL, v | 0x10000100);
153
154 v = cx18_av_read4(cx, CXADEC_DLL2_DIAG_CTRL) & 0xE1FFFEFF;
155
156 cx18_av_write4(cx, CXADEC_DLL2_DIAG_CTRL, v);
157
158 cx18_av_write4(cx, CXADEC_DLL2_DIAG_CTRL, v | 0x06000100);
159
160
161 cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL1, 0x000A1802);
162
163 v = cx18_av_read4(cx, CXADEC_AFE_DIAG_CTRL3) | 1;
164
165 cx18_av_write4_expect(cx, CXADEC_AFE_DIAG_CTRL3, v, v, 0x03009F0F);
166
167 cx18_av_write4_expect(cx, CXADEC_AFE_DIAG_CTRL3,
168 v & 0xFFFFFFFE, v & 0xFFFFFFFE, 0x03009F0F);
169
170
171 cx18_av_and_or4(cx, CXADEC_PIN_CTRL1, ~0, 0x040C00);
172
173
174 cx18_av_and_or4(cx, CXADEC_PIN_CTRL2, ~0, 0x2);
175
176
177 cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0x8000);
178 cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0);
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195 cx18_av_and_or4(cx, CXADEC_CHIP_CTRL, 0xFFFBFFFF, 0x00120000);
196
197
198 cx18_av_init(cx);
199
200
201
202
203 cx18_av_and_or4(cx, CXADEC_MODE_CTRL, 0xFFF7E7F0, 0x02040800);
204
205
206
207 cx18_av_and_or4(cx, CXADEC_CRUSH_CTRL, ~0, 0x00500000);
208
209
210 cx18_av_and_or4(cx, CXADEC_DFE_CTRL2, 0xFFFF00FF, 0x00002000);
211
212
213
214
215
216
217
218
219 cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4013252e);
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242 cx18_av_and_or4(cx, CXADEC_AFE_CTRL, 0xFF000000, 0x00005D00);
243
244
245
246
247
248
249 cx18_av_write4(cx, CXADEC_SRC_COMB_CFG, 0x6628021F);
250 state->default_volume = 228 - cx18_av_read(cx, 0x8d4);
251 state->default_volume = ((state->default_volume / 2) + 23) << 9;
252}
253
254static int cx18_av_reset(struct v4l2_subdev *sd, u32 val)
255{
256 cx18_av_initialize(sd);
257 return 0;
258}
259
260static int cx18_av_load_fw(struct v4l2_subdev *sd)
261{
262 struct cx18_av_state *state = to_cx18_av_state(sd);
263
264 if (!state->is_initialized) {
265
266 state->is_initialized = 1;
267 cx18_av_initialize(sd);
268 }
269 return 0;
270}
271
272void cx18_av_std_setup(struct cx18 *cx)
273{
274 struct cx18_av_state *state = &cx->av_state;
275 struct v4l2_subdev *sd = &state->sd;
276 v4l2_std_id std = state->std;
277
278
279
280
281
282 const int src_decimation = 0x21f;
283
284 int hblank, hactive, burst, vblank, vactive, sc;
285 int vblank656;
286 int luma_lpf, uv_lpf, comb;
287 u32 pll_int, pll_frac, pll_post;
288
289
290 if (std & ~V4L2_STD_NTSC)
291 cx18_av_write(cx, 0x49f, 0x11);
292 else
293 cx18_av_write(cx, 0x49f, 0x14);
294
295
296
297
298
299
300
301
302
303 if (std & V4L2_STD_625_50) {
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335 vblank656 = 48;
336 vblank = 38;
337 vactive = 579;
338
339
340
341
342
343
344
345
346 hblank = 132;
347 hactive = 720;
348
349
350
351
352
353
354
355
356 burst = 93;
357 luma_lpf = 2;
358 if (std & V4L2_STD_PAL) {
359 uv_lpf = 1;
360 comb = 0x20;
361
362 sc = 688700;
363 } else if (std == V4L2_STD_PAL_Nc) {
364 uv_lpf = 1;
365 comb = 0x20;
366
367 sc = 556422;
368 } else {
369 uv_lpf = 0;
370 comb = 0;
371
372
373 sc = 672314;
374 }
375 } else {
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395 vblank656 = 38;
396 vblank = 26;
397 vactive = 481;
398
399
400
401
402
403
404
405
406 hactive = 720;
407 hblank = 122;
408 luma_lpf = 1;
409 uv_lpf = 1;
410
411
412
413
414
415
416
417
418 if (std == V4L2_STD_PAL_60) {
419 burst = 90;
420 luma_lpf = 2;
421 comb = 0x20;
422
423 sc = 688700;
424 } else if (std == V4L2_STD_PAL_M) {
425
426 burst = 97;
427 comb = 0x20;
428
429 sc = 555421;
430 } else {
431 burst = 90;
432 comb = 0x66;
433
434 sc = 556032;
435 }
436 }
437
438
439 pll_int = cx18_av_read(cx, 0x108);
440 pll_frac = cx18_av_read4(cx, 0x10c) & 0x1ffffff;
441 pll_post = cx18_av_read(cx, 0x109);
442 CX18_DEBUG_INFO_DEV(sd, "PLL regs = int: %u, frac: %u, post: %u\n",
443 pll_int, pll_frac, pll_post);
444
445 if (pll_post) {
446 int fsc, pll;
447 u64 tmp;
448
449 pll = (28636360L * ((((u64)pll_int) << 25) + pll_frac)) >> 25;
450 pll /= pll_post;
451 CX18_DEBUG_INFO_DEV(sd, "Video PLL = %d.%06d MHz\n",
452 pll / 1000000, pll % 1000000);
453 CX18_DEBUG_INFO_DEV(sd, "Pixel rate = %d.%06d Mpixel/sec\n",
454 pll / 8000000, (pll / 8) % 1000000);
455
456 CX18_DEBUG_INFO_DEV(sd, "ADC XTAL/pixel clock decimation ratio "
457 "= %d.%03d\n", src_decimation / 256,
458 ((src_decimation % 256) * 1000) / 256);
459
460 tmp = 28636360 * (u64) sc;
461 do_div(tmp, src_decimation);
462 fsc = tmp >> 13;
463 CX18_DEBUG_INFO_DEV(sd,
464 "Chroma sub-carrier initial freq = %d.%06d "
465 "MHz\n", fsc / 1000000, fsc % 1000000);
466
467 CX18_DEBUG_INFO_DEV(sd, "hblank %i, hactive %i, vblank %i, "
468 "vactive %i, vblank656 %i, src_dec %i, "
469 "burst 0x%02x, luma_lpf %i, uv_lpf %i, "
470 "comb 0x%02x, sc 0x%06x\n",
471 hblank, hactive, vblank, vactive, vblank656,
472 src_decimation, burst, luma_lpf, uv_lpf,
473 comb, sc);
474 }
475
476
477 cx18_av_write(cx, 0x470, hblank);
478 cx18_av_write(cx, 0x471, 0xff & (((hblank >> 8) & 0x3) |
479 (hactive << 4)));
480 cx18_av_write(cx, 0x472, hactive >> 4);
481
482
483 cx18_av_write(cx, 0x473, burst);
484
485
486 cx18_av_write(cx, 0x474, vblank);
487 cx18_av_write(cx, 0x475, 0xff & (((vblank >> 8) & 0x3) |
488 (vactive << 4)));
489 cx18_av_write(cx, 0x476, vactive >> 4);
490 cx18_av_write(cx, 0x477, vblank656);
491
492
493 cx18_av_write(cx, 0x478, 0xff & src_decimation);
494 cx18_av_write(cx, 0x479, 0xff & (src_decimation >> 8));
495
496
497 cx18_av_write(cx, 0x47a, luma_lpf << 6 | ((uv_lpf << 4) & 0x30));
498
499
500 cx18_av_write(cx, 0x47b, comb);
501
502
503 cx18_av_write(cx, 0x47c, sc);
504 cx18_av_write(cx, 0x47d, 0xff & sc >> 8);
505 cx18_av_write(cx, 0x47e, 0xff & sc >> 16);
506
507 if (std & V4L2_STD_625_50) {
508 state->slicer_line_delay = 1;
509 state->slicer_line_offset = (6 + state->slicer_line_delay - 2);
510 } else {
511 state->slicer_line_delay = 0;
512 state->slicer_line_offset = (10 + state->slicer_line_delay - 2);
513 }
514 cx18_av_write(cx, 0x47f, state->slicer_line_delay);
515}
516
517static void input_change(struct cx18 *cx)
518{
519 struct cx18_av_state *state = &cx->av_state;
520 v4l2_std_id std = state->std;
521 u8 v;
522
523
524 cx18_av_write(cx, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11);
525 cx18_av_and_or(cx, 0x401, ~0x60, 0);
526 cx18_av_and_or(cx, 0x401, ~0x60, 0x60);
527
528 if (std & V4L2_STD_525_60) {
529 if (std == V4L2_STD_NTSC_M_JP) {
530
531 cx18_av_write_expect(cx, 0x808, 0xf7, 0xf7, 0xff);
532 cx18_av_write_expect(cx, 0x80b, 0x02, 0x02, 0x3f);
533 } else if (std == V4L2_STD_NTSC_M_KR) {
534
535 cx18_av_write_expect(cx, 0x808, 0xf8, 0xf8, 0xff);
536 cx18_av_write_expect(cx, 0x80b, 0x03, 0x03, 0x3f);
537 } else {
538
539 cx18_av_write_expect(cx, 0x808, 0xf6, 0xf6, 0xff);
540 cx18_av_write_expect(cx, 0x80b, 0x01, 0x01, 0x3f);
541 }
542 } else if (std & V4L2_STD_PAL) {
543
544 cx18_av_write_expect(cx, 0x808, 0xff, 0xff, 0xff);
545 cx18_av_write_expect(cx, 0x80b, 0x03, 0x03, 0x3f);
546 } else if (std & V4L2_STD_SECAM) {
547
548 cx18_av_write_expect(cx, 0x808, 0xff, 0xff, 0xff);
549 cx18_av_write_expect(cx, 0x80b, 0x03, 0x03, 0x3f);
550 }
551
552 v = cx18_av_read(cx, 0x803);
553 if (v & 0x10) {
554
555 v &= ~0x10;
556 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
557 v |= 0x10;
558 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
559 }
560}
561
562static int cx18_av_s_frequency(struct v4l2_subdev *sd,
563 struct v4l2_frequency *freq)
564{
565 struct cx18 *cx = v4l2_get_subdevdata(sd);
566 input_change(cx);
567 return 0;
568}
569
570static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
571 enum cx18_av_audio_input aud_input)
572{
573 struct cx18_av_state *state = &cx->av_state;
574 struct v4l2_subdev *sd = &state->sd;
575
576 enum analog_signal_type {
577 NONE, CVBS, Y, C, SIF, Pb, Pr
578 } ch[3] = {NONE, NONE, NONE};
579
580 u8 afe_mux_cfg;
581 u8 adc2_cfg;
582 u8 input_mode;
583 u32 afe_cfg;
584 int i;
585
586 CX18_DEBUG_INFO_DEV(sd, "decoder set video input %d, audio input %d\n",
587 vid_input, aud_input);
588
589 if (vid_input >= CX18_AV_COMPOSITE1 &&
590 vid_input <= CX18_AV_COMPOSITE8) {
591 afe_mux_cfg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1);
592 ch[0] = CVBS;
593 input_mode = 0x0;
594 } else if (vid_input >= CX18_AV_COMPONENT_LUMA1) {
595 int luma = vid_input & 0xf000;
596 int r_chroma = vid_input & 0xf0000;
597 int b_chroma = vid_input & 0xf00000;
598
599 if ((vid_input & ~0xfff000) ||
600 luma < CX18_AV_COMPONENT_LUMA1 ||
601 luma > CX18_AV_COMPONENT_LUMA8 ||
602 r_chroma < CX18_AV_COMPONENT_R_CHROMA4 ||
603 r_chroma > CX18_AV_COMPONENT_R_CHROMA6 ||
604 b_chroma < CX18_AV_COMPONENT_B_CHROMA7 ||
605 b_chroma > CX18_AV_COMPONENT_B_CHROMA8) {
606 CX18_ERR_DEV(sd, "0x%06x is not a valid video input!\n",
607 vid_input);
608 return -EINVAL;
609 }
610 afe_mux_cfg = (luma - CX18_AV_COMPONENT_LUMA1) >> 12;
611 ch[0] = Y;
612 afe_mux_cfg |= (r_chroma - CX18_AV_COMPONENT_R_CHROMA4) >> 12;
613 ch[1] = Pr;
614 afe_mux_cfg |= (b_chroma - CX18_AV_COMPONENT_B_CHROMA7) >> 14;
615 ch[2] = Pb;
616 input_mode = 0x6;
617 } else {
618 int luma = vid_input & 0xf0;
619 int chroma = vid_input & 0xf00;
620
621 if ((vid_input & ~0xff0) ||
622 luma < CX18_AV_SVIDEO_LUMA1 ||
623 luma > CX18_AV_SVIDEO_LUMA8 ||
624 chroma < CX18_AV_SVIDEO_CHROMA4 ||
625 chroma > CX18_AV_SVIDEO_CHROMA8) {
626 CX18_ERR_DEV(sd, "0x%06x is not a valid video input!\n",
627 vid_input);
628 return -EINVAL;
629 }
630 afe_mux_cfg = 0xf0 + ((luma - CX18_AV_SVIDEO_LUMA1) >> 4);
631 ch[0] = Y;
632 if (chroma >= CX18_AV_SVIDEO_CHROMA7) {
633 afe_mux_cfg &= 0x3f;
634 afe_mux_cfg |= (chroma - CX18_AV_SVIDEO_CHROMA7) >> 2;
635 ch[2] = C;
636 } else {
637 afe_mux_cfg &= 0xcf;
638 afe_mux_cfg |= (chroma - CX18_AV_SVIDEO_CHROMA4) >> 4;
639 ch[1] = C;
640 }
641 input_mode = 0x2;
642 }
643
644 switch (aud_input) {
645 case CX18_AV_AUDIO_SERIAL1:
646 case CX18_AV_AUDIO_SERIAL2:
647
648 break;
649 case CX18_AV_AUDIO4:
650 afe_mux_cfg &= ~0x30;
651 ch[1] = SIF;
652 break;
653 case CX18_AV_AUDIO5:
654 afe_mux_cfg = (afe_mux_cfg & ~0x30) | 0x10;
655 ch[1] = SIF;
656 break;
657 case CX18_AV_AUDIO6:
658 afe_mux_cfg = (afe_mux_cfg & ~0x30) | 0x20;
659 ch[1] = SIF;
660 break;
661 case CX18_AV_AUDIO7:
662 afe_mux_cfg &= ~0xc0;
663 ch[2] = SIF;
664 break;
665 case CX18_AV_AUDIO8:
666 afe_mux_cfg = (afe_mux_cfg & ~0xc0) | 0x40;
667 ch[2] = SIF;
668 break;
669
670 default:
671 CX18_ERR_DEV(sd, "0x%04x is not a valid audio input!\n",
672 aud_input);
673 return -EINVAL;
674 }
675
676
677 cx18_av_write_expect(cx, 0x103, afe_mux_cfg, afe_mux_cfg, 0xf7);
678
679 cx18_av_and_or(cx, 0x401, ~0x6, input_mode);
680
681
682 adc2_cfg = cx18_av_read(cx, 0x102);
683 if (ch[2] == NONE)
684 adc2_cfg &= ~0x2;
685 else
686 adc2_cfg |= 0x2;
687
688
689 if (ch[1] != NONE && ch[2] != NONE)
690 adc2_cfg |= 0x4;
691 else
692 adc2_cfg &= ~0x4;
693 cx18_av_write_expect(cx, 0x102, adc2_cfg, adc2_cfg, 0x17);
694
695
696 afe_cfg = cx18_av_read4(cx, CXADEC_AFE_CTRL);
697 afe_cfg &= 0xff000000;
698 afe_cfg |= 0x00005000;
699 if (ch[1] != NONE && ch[2] != NONE)
700 afe_cfg |= 0x00000030;
701
702 for (i = 0; i < 3; i++) {
703 switch (ch[i]) {
704 default:
705 case NONE:
706
707 afe_cfg |= (0x00000200 << i);
708 break;
709 case CVBS:
710 case Y:
711 if (i > 0)
712 afe_cfg |= 0x00002000;
713 break;
714 case C:
715 case Pb:
716 case Pr:
717
718 afe_cfg |= (0x00000200 << i);
719 if (i == 0 && ch[i] == C)
720 afe_cfg &= ~0x00001000;
721 break;
722 case SIF:
723
724
725
726
727 afe_cfg |= (0x00000240 << i);
728 if (i == 0)
729 afe_cfg &= ~0x00004000;
730 break;
731 }
732 }
733
734 cx18_av_write4(cx, CXADEC_AFE_CTRL, afe_cfg);
735
736 state->vid_input = vid_input;
737 state->aud_input = aud_input;
738 cx18_av_audio_set_path(cx);
739 input_change(cx);
740 return 0;
741}
742
743static int cx18_av_s_video_routing(struct v4l2_subdev *sd,
744 u32 input, u32 output, u32 config)
745{
746 struct cx18_av_state *state = to_cx18_av_state(sd);
747 struct cx18 *cx = v4l2_get_subdevdata(sd);
748 return set_input(cx, input, state->aud_input);
749}
750
751static int cx18_av_s_audio_routing(struct v4l2_subdev *sd,
752 u32 input, u32 output, u32 config)
753{
754 struct cx18_av_state *state = to_cx18_av_state(sd);
755 struct cx18 *cx = v4l2_get_subdevdata(sd);
756 return set_input(cx, state->vid_input, input);
757}
758
759static int cx18_av_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
760{
761 struct cx18_av_state *state = to_cx18_av_state(sd);
762 struct cx18 *cx = v4l2_get_subdevdata(sd);
763 u8 vpres;
764 u8 mode;
765 int val = 0;
766
767 if (state->radio)
768 return 0;
769
770 vpres = cx18_av_read(cx, 0x40e) & 0x20;
771 vt->signal = vpres ? 0xffff : 0x0;
772
773 vt->capability |=
774 V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
775 V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
776
777 mode = cx18_av_read(cx, 0x804);
778
779
780 if ((mode & 0xf) == 1)
781 val |= V4L2_TUNER_SUB_STEREO;
782 else
783 val |= V4L2_TUNER_SUB_MONO;
784
785 if (mode == 2 || mode == 4)
786 val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
787
788 if (mode & 0x10)
789 val |= V4L2_TUNER_SUB_SAP;
790
791 vt->rxsubchans = val;
792 vt->audmode = state->audmode;
793 return 0;
794}
795
796static int cx18_av_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
797{
798 struct cx18_av_state *state = to_cx18_av_state(sd);
799 struct cx18 *cx = v4l2_get_subdevdata(sd);
800 u8 v;
801
802 if (state->radio)
803 return 0;
804
805 v = cx18_av_read(cx, 0x809);
806 v &= ~0xf;
807
808 switch (vt->audmode) {
809 case V4L2_TUNER_MODE_MONO:
810
811
812
813 break;
814 case V4L2_TUNER_MODE_STEREO:
815 case V4L2_TUNER_MODE_LANG1:
816
817
818
819 v |= 0x4;
820 break;
821 case V4L2_TUNER_MODE_LANG1_LANG2:
822
823
824
825 v |= 0x7;
826 break;
827 case V4L2_TUNER_MODE_LANG2:
828
829
830
831 v |= 0x1;
832 break;
833 default:
834 return -EINVAL;
835 }
836 cx18_av_write_expect(cx, 0x809, v, v, 0xff);
837 state->audmode = vt->audmode;
838 return 0;
839}
840
841static int cx18_av_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
842{
843 struct cx18_av_state *state = to_cx18_av_state(sd);
844 struct cx18 *cx = v4l2_get_subdevdata(sd);
845
846 u8 fmt = 0;
847 u8 pal_m = 0;
848
849 if (state->radio == 0 && state->std == norm)
850 return 0;
851
852 state->radio = 0;
853 state->std = norm;
854
855
856 if (state->std == V4L2_STD_NTSC_M_JP) {
857 fmt = 0x2;
858 } else if (state->std == V4L2_STD_NTSC_443) {
859 fmt = 0x3;
860 } else if (state->std == V4L2_STD_PAL_M) {
861 pal_m = 1;
862 fmt = 0x5;
863 } else if (state->std == V4L2_STD_PAL_N) {
864 fmt = 0x6;
865 } else if (state->std == V4L2_STD_PAL_Nc) {
866 fmt = 0x7;
867 } else if (state->std == V4L2_STD_PAL_60) {
868 fmt = 0x8;
869 } else {
870
871 if (state->std & V4L2_STD_NTSC)
872 fmt = 0x1;
873 else if (state->std & V4L2_STD_PAL)
874 fmt = 0x4;
875 else if (state->std & V4L2_STD_SECAM)
876 fmt = 0xc;
877 }
878
879 CX18_DEBUG_INFO_DEV(sd, "changing video std to fmt %i\n", fmt);
880
881
882
883
884 if (fmt >= 4 && fmt < 8) {
885
886 cx18_av_and_or(cx, 0x400, ~0xf, 1);
887
888 cx18_av_and_or(cx, 0x47b, ~6, 0);
889 }
890 cx18_av_and_or(cx, 0x400, ~0x2f, fmt | 0x20);
891 cx18_av_and_or(cx, 0x403, ~0x3, pal_m);
892 cx18_av_std_setup(cx);
893 input_change(cx);
894 return 0;
895}
896
897static int cx18_av_s_radio(struct v4l2_subdev *sd)
898{
899 struct cx18_av_state *state = to_cx18_av_state(sd);
900 state->radio = 1;
901 return 0;
902}
903
904static int cx18_av_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
905{
906 struct cx18 *cx = v4l2_get_subdevdata(sd);
907
908 switch (ctrl->id) {
909 case V4L2_CID_BRIGHTNESS:
910 if (ctrl->value < 0 || ctrl->value > 255) {
911 CX18_ERR_DEV(sd, "invalid brightness setting %d\n",
912 ctrl->value);
913 return -ERANGE;
914 }
915
916 cx18_av_write(cx, 0x414, ctrl->value - 128);
917 break;
918
919 case V4L2_CID_CONTRAST:
920 if (ctrl->value < 0 || ctrl->value > 127) {
921 CX18_ERR_DEV(sd, "invalid contrast setting %d\n",
922 ctrl->value);
923 return -ERANGE;
924 }
925
926 cx18_av_write(cx, 0x415, ctrl->value << 1);
927 break;
928
929 case V4L2_CID_SATURATION:
930 if (ctrl->value < 0 || ctrl->value > 127) {
931 CX18_ERR_DEV(sd, "invalid saturation setting %d\n",
932 ctrl->value);
933 return -ERANGE;
934 }
935
936 cx18_av_write(cx, 0x420, ctrl->value << 1);
937 cx18_av_write(cx, 0x421, ctrl->value << 1);
938 break;
939
940 case V4L2_CID_HUE:
941 if (ctrl->value < -128 || ctrl->value > 127) {
942 CX18_ERR_DEV(sd, "invalid hue setting %d\n",
943 ctrl->value);
944 return -ERANGE;
945 }
946
947 cx18_av_write(cx, 0x422, ctrl->value);
948 break;
949
950 case V4L2_CID_AUDIO_VOLUME:
951 case V4L2_CID_AUDIO_BASS:
952 case V4L2_CID_AUDIO_TREBLE:
953 case V4L2_CID_AUDIO_BALANCE:
954 case V4L2_CID_AUDIO_MUTE:
955 return cx18_av_audio_s_ctrl(cx, ctrl);
956
957 default:
958 return -EINVAL;
959 }
960 return 0;
961}
962
963static int cx18_av_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
964{
965 struct cx18 *cx = v4l2_get_subdevdata(sd);
966
967 switch (ctrl->id) {
968 case V4L2_CID_BRIGHTNESS:
969 ctrl->value = (s8)cx18_av_read(cx, 0x414) + 128;
970 break;
971 case V4L2_CID_CONTRAST:
972 ctrl->value = cx18_av_read(cx, 0x415) >> 1;
973 break;
974 case V4L2_CID_SATURATION:
975 ctrl->value = cx18_av_read(cx, 0x420) >> 1;
976 break;
977 case V4L2_CID_HUE:
978 ctrl->value = (s8)cx18_av_read(cx, 0x422);
979 break;
980 case V4L2_CID_AUDIO_VOLUME:
981 case V4L2_CID_AUDIO_BASS:
982 case V4L2_CID_AUDIO_TREBLE:
983 case V4L2_CID_AUDIO_BALANCE:
984 case V4L2_CID_AUDIO_MUTE:
985 return cx18_av_audio_g_ctrl(cx, ctrl);
986 default:
987 return -EINVAL;
988 }
989 return 0;
990}
991
992static int cx18_av_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
993{
994 struct cx18_av_state *state = to_cx18_av_state(sd);
995
996 switch (qc->id) {
997 case V4L2_CID_BRIGHTNESS:
998 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
999 case V4L2_CID_CONTRAST:
1000 case V4L2_CID_SATURATION:
1001 return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64);
1002 case V4L2_CID_HUE:
1003 return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
1004 default:
1005 break;
1006 }
1007
1008 switch (qc->id) {
1009 case V4L2_CID_AUDIO_VOLUME:
1010 return v4l2_ctrl_query_fill(qc, 0, 65535,
1011 65535 / 100, state->default_volume);
1012 case V4L2_CID_AUDIO_MUTE:
1013 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
1014 case V4L2_CID_AUDIO_BALANCE:
1015 case V4L2_CID_AUDIO_BASS:
1016 case V4L2_CID_AUDIO_TREBLE:
1017 return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768);
1018 default:
1019 return -EINVAL;
1020 }
1021 return -EINVAL;
1022}
1023
1024static int cx18_av_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
1025{
1026 struct cx18_av_state *state = to_cx18_av_state(sd);
1027 struct cx18 *cx = v4l2_get_subdevdata(sd);
1028 int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
1029 int is_50Hz = !(state->std & V4L2_STD_525_60);
1030
1031 if (fmt->code != V4L2_MBUS_FMT_FIXED)
1032 return -EINVAL;
1033
1034 fmt->field = V4L2_FIELD_INTERLACED;
1035 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
1036
1037 Vsrc = (cx18_av_read(cx, 0x476) & 0x3f) << 4;
1038 Vsrc |= (cx18_av_read(cx, 0x475) & 0xf0) >> 4;
1039
1040 Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4;
1041 Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4;
1042
1043
1044
1045
1046
1047
1048
1049
1050 Vlines = fmt->height + (is_50Hz ? 3 : 1);
1051
1052
1053
1054
1055
1056
1057
1058
1059 if ((fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) ||
1060 (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
1061 CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n",
1062 fmt->width, fmt->height);
1063 return -ERANGE;
1064 }
1065
1066 HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20);
1067 VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
1068 VSC &= 0x1fff;
1069
1070 if (fmt->width >= 385)
1071 filter = 0;
1072 else if (fmt->width > 192)
1073 filter = 1;
1074 else if (fmt->width > 96)
1075 filter = 2;
1076 else
1077 filter = 3;
1078
1079 CX18_DEBUG_INFO_DEV(sd,
1080 "decoder set size %dx%d -> scale %ux%u\n",
1081 fmt->width, fmt->height, HSC, VSC);
1082
1083
1084 cx18_av_write(cx, 0x418, HSC & 0xff);
1085 cx18_av_write(cx, 0x419, (HSC >> 8) & 0xff);
1086 cx18_av_write(cx, 0x41a, HSC >> 16);
1087
1088 cx18_av_write(cx, 0x41c, VSC & 0xff);
1089 cx18_av_write(cx, 0x41d, VSC >> 8);
1090
1091 cx18_av_write(cx, 0x41e, 0x8 | filter);
1092 return 0;
1093}
1094
1095static int cx18_av_s_stream(struct v4l2_subdev *sd, int enable)
1096{
1097 struct cx18 *cx = v4l2_get_subdevdata(sd);
1098
1099 CX18_DEBUG_INFO_DEV(sd, "%s output\n", enable ? "enable" : "disable");
1100 if (enable) {
1101 cx18_av_write(cx, 0x115, 0x8c);
1102 cx18_av_write(cx, 0x116, 0x07);
1103 } else {
1104 cx18_av_write(cx, 0x115, 0x00);
1105 cx18_av_write(cx, 0x116, 0x00);
1106 }
1107 return 0;
1108}
1109
1110static void log_video_status(struct cx18 *cx)
1111{
1112 static const char *const fmt_strs[] = {
1113 "0x0",
1114 "NTSC-M", "NTSC-J", "NTSC-4.43",
1115 "PAL-BDGHI", "PAL-M", "PAL-N", "PAL-Nc", "PAL-60",
1116 "0x9", "0xA", "0xB",
1117 "SECAM",
1118 "0xD", "0xE", "0xF"
1119 };
1120
1121 struct cx18_av_state *state = &cx->av_state;
1122 struct v4l2_subdev *sd = &state->sd;
1123 u8 vidfmt_sel = cx18_av_read(cx, 0x400) & 0xf;
1124 u8 gen_stat1 = cx18_av_read(cx, 0x40d);
1125 u8 gen_stat2 = cx18_av_read(cx, 0x40e);
1126 int vid_input = state->vid_input;
1127
1128 CX18_INFO_DEV(sd, "Video signal: %spresent\n",
1129 (gen_stat2 & 0x20) ? "" : "not ");
1130 CX18_INFO_DEV(sd, "Detected format: %s\n",
1131 fmt_strs[gen_stat1 & 0xf]);
1132
1133 CX18_INFO_DEV(sd, "Specified standard: %s\n",
1134 vidfmt_sel ? fmt_strs[vidfmt_sel]
1135 : "automatic detection");
1136
1137 if (vid_input >= CX18_AV_COMPOSITE1 &&
1138 vid_input <= CX18_AV_COMPOSITE8) {
1139 CX18_INFO_DEV(sd, "Specified video input: Composite %d\n",
1140 vid_input - CX18_AV_COMPOSITE1 + 1);
1141 } else {
1142 CX18_INFO_DEV(sd, "Specified video input: "
1143 "S-Video (Luma In%d, Chroma In%d)\n",
1144 (vid_input & 0xf0) >> 4,
1145 (vid_input & 0xf00) >> 8);
1146 }
1147
1148 CX18_INFO_DEV(sd, "Specified audioclock freq: %d Hz\n",
1149 state->audclk_freq);
1150}
1151
1152static void log_audio_status(struct cx18 *cx)
1153{
1154 struct cx18_av_state *state = &cx->av_state;
1155 struct v4l2_subdev *sd = &state->sd;
1156 u8 download_ctl = cx18_av_read(cx, 0x803);
1157 u8 mod_det_stat0 = cx18_av_read(cx, 0x804);
1158 u8 mod_det_stat1 = cx18_av_read(cx, 0x805);
1159 u8 audio_config = cx18_av_read(cx, 0x808);
1160 u8 pref_mode = cx18_av_read(cx, 0x809);
1161 u8 afc0 = cx18_av_read(cx, 0x80b);
1162 u8 mute_ctl = cx18_av_read(cx, 0x8d3);
1163 int aud_input = state->aud_input;
1164 char *p;
1165
1166 switch (mod_det_stat0) {
1167 case 0x00: p = "mono"; break;
1168 case 0x01: p = "stereo"; break;
1169 case 0x02: p = "dual"; break;
1170 case 0x04: p = "tri"; break;
1171 case 0x10: p = "mono with SAP"; break;
1172 case 0x11: p = "stereo with SAP"; break;
1173 case 0x12: p = "dual with SAP"; break;
1174 case 0x14: p = "tri with SAP"; break;
1175 case 0xfe: p = "forced mode"; break;
1176 default: p = "not defined"; break;
1177 }
1178 CX18_INFO_DEV(sd, "Detected audio mode: %s\n", p);
1179
1180 switch (mod_det_stat1) {
1181 case 0x00: p = "not defined"; break;
1182 case 0x01: p = "EIAJ"; break;
1183 case 0x02: p = "A2-M"; break;
1184 case 0x03: p = "A2-BG"; break;
1185 case 0x04: p = "A2-DK1"; break;
1186 case 0x05: p = "A2-DK2"; break;
1187 case 0x06: p = "A2-DK3"; break;
1188 case 0x07: p = "A1 (6.0 MHz FM Mono)"; break;
1189 case 0x08: p = "AM-L"; break;
1190 case 0x09: p = "NICAM-BG"; break;
1191 case 0x0a: p = "NICAM-DK"; break;
1192 case 0x0b: p = "NICAM-I"; break;
1193 case 0x0c: p = "NICAM-L"; break;
1194 case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break;
1195 case 0x0e: p = "IF FM Radio"; break;
1196 case 0x0f: p = "BTSC"; break;
1197 case 0x10: p = "detected chrominance"; break;
1198 case 0xfd: p = "unknown audio standard"; break;
1199 case 0xfe: p = "forced audio standard"; break;
1200 case 0xff: p = "no detected audio standard"; break;
1201 default: p = "not defined"; break;
1202 }
1203 CX18_INFO_DEV(sd, "Detected audio standard: %s\n", p);
1204 CX18_INFO_DEV(sd, "Audio muted: %s\n",
1205 (mute_ctl & 0x2) ? "yes" : "no");
1206 CX18_INFO_DEV(sd, "Audio microcontroller: %s\n",
1207 (download_ctl & 0x10) ? "running" : "stopped");
1208
1209 switch (audio_config >> 4) {
1210 case 0x00: p = "undefined"; break;
1211 case 0x01: p = "BTSC"; break;
1212 case 0x02: p = "EIAJ"; break;
1213 case 0x03: p = "A2-M"; break;
1214 case 0x04: p = "A2-BG"; break;
1215 case 0x05: p = "A2-DK1"; break;
1216 case 0x06: p = "A2-DK2"; break;
1217 case 0x07: p = "A2-DK3"; break;
1218 case 0x08: p = "A1 (6.0 MHz FM Mono)"; break;
1219 case 0x09: p = "AM-L"; break;
1220 case 0x0a: p = "NICAM-BG"; break;
1221 case 0x0b: p = "NICAM-DK"; break;
1222 case 0x0c: p = "NICAM-I"; break;
1223 case 0x0d: p = "NICAM-L"; break;
1224 case 0x0e: p = "FM radio"; break;
1225 case 0x0f: p = "automatic detection"; break;
1226 default: p = "undefined"; break;
1227 }
1228 CX18_INFO_DEV(sd, "Configured audio standard: %s\n", p);
1229
1230 if ((audio_config >> 4) < 0xF) {
1231 switch (audio_config & 0xF) {
1232 case 0x00: p = "MONO1 (LANGUAGE A/Mono L+R channel for BTSC, EIAJ, A2)"; break;
1233 case 0x01: p = "MONO2 (LANGUAGE B)"; break;
1234 case 0x02: p = "MONO3 (STEREO forced MONO)"; break;
1235 case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break;
1236 case 0x04: p = "STEREO"; break;
1237 case 0x05: p = "DUAL1 (AC)"; break;
1238 case 0x06: p = "DUAL2 (BC)"; break;
1239 case 0x07: p = "DUAL3 (AB)"; break;
1240 default: p = "undefined";
1241 }
1242 CX18_INFO_DEV(sd, "Configured audio mode: %s\n", p);
1243 } else {
1244 switch (audio_config & 0xF) {
1245 case 0x00: p = "BG"; break;
1246 case 0x01: p = "DK1"; break;
1247 case 0x02: p = "DK2"; break;
1248 case 0x03: p = "DK3"; break;
1249 case 0x04: p = "I"; break;
1250 case 0x05: p = "L"; break;
1251 case 0x06: p = "BTSC"; break;
1252 case 0x07: p = "EIAJ"; break;
1253 case 0x08: p = "A2-M"; break;
1254 case 0x09: p = "FM Radio (4.5 MHz)"; break;
1255 case 0x0a: p = "FM Radio (5.5 MHz)"; break;
1256 case 0x0b: p = "S-Video"; break;
1257 case 0x0f: p = "automatic standard and mode detection"; break;
1258 default: p = "undefined"; break;
1259 }
1260 CX18_INFO_DEV(sd, "Configured audio system: %s\n", p);
1261 }
1262
1263 if (aud_input)
1264 CX18_INFO_DEV(sd, "Specified audio input: Tuner (In%d)\n",
1265 aud_input);
1266 else
1267 CX18_INFO_DEV(sd, "Specified audio input: External\n");
1268
1269 switch (pref_mode & 0xf) {
1270 case 0: p = "mono/language A"; break;
1271 case 1: p = "language B"; break;
1272 case 2: p = "language C"; break;
1273 case 3: p = "analog fallback"; break;
1274 case 4: p = "stereo"; break;
1275 case 5: p = "language AC"; break;
1276 case 6: p = "language BC"; break;
1277 case 7: p = "language AB"; break;
1278 default: p = "undefined"; break;
1279 }
1280 CX18_INFO_DEV(sd, "Preferred audio mode: %s\n", p);
1281
1282 if ((audio_config & 0xf) == 0xf) {
1283 switch ((afc0 >> 3) & 0x1) {
1284 case 0: p = "system DK"; break;
1285 case 1: p = "system L"; break;
1286 }
1287 CX18_INFO_DEV(sd, "Selected 65 MHz format: %s\n", p);
1288
1289 switch (afc0 & 0x7) {
1290 case 0: p = "Chroma"; break;
1291 case 1: p = "BTSC"; break;
1292 case 2: p = "EIAJ"; break;
1293 case 3: p = "A2-M"; break;
1294 case 4: p = "autodetect"; break;
1295 default: p = "undefined"; break;
1296 }
1297 CX18_INFO_DEV(sd, "Selected 45 MHz format: %s\n", p);
1298 }
1299}
1300
1301static int cx18_av_log_status(struct v4l2_subdev *sd)
1302{
1303 struct cx18 *cx = v4l2_get_subdevdata(sd);
1304 log_video_status(cx);
1305 log_audio_status(cx);
1306 return 0;
1307}
1308
1309static inline int cx18_av_dbg_match(const struct v4l2_dbg_match *match)
1310{
1311 return match->type == V4L2_CHIP_MATCH_HOST && match->addr == 1;
1312}
1313
1314static int cx18_av_g_chip_ident(struct v4l2_subdev *sd,
1315 struct v4l2_dbg_chip_ident *chip)
1316{
1317 struct cx18_av_state *state = to_cx18_av_state(sd);
1318
1319 if (cx18_av_dbg_match(&chip->match)) {
1320 chip->ident = state->id;
1321 chip->revision = state->rev;
1322 }
1323 return 0;
1324}
1325
1326#ifdef CONFIG_VIDEO_ADV_DEBUG
1327static int cx18_av_g_register(struct v4l2_subdev *sd,
1328 struct v4l2_dbg_register *reg)
1329{
1330 struct cx18 *cx = v4l2_get_subdevdata(sd);
1331
1332 if (!cx18_av_dbg_match(®->match))
1333 return -EINVAL;
1334 if ((reg->reg & 0x3) != 0)
1335 return -EINVAL;
1336 if (!capable(CAP_SYS_ADMIN))
1337 return -EPERM;
1338 reg->size = 4;
1339 reg->val = cx18_av_read4(cx, reg->reg & 0x00000ffc);
1340 return 0;
1341}
1342
1343static int cx18_av_s_register(struct v4l2_subdev *sd,
1344 struct v4l2_dbg_register *reg)
1345{
1346 struct cx18 *cx = v4l2_get_subdevdata(sd);
1347
1348 if (!cx18_av_dbg_match(®->match))
1349 return -EINVAL;
1350 if ((reg->reg & 0x3) != 0)
1351 return -EINVAL;
1352 if (!capable(CAP_SYS_ADMIN))
1353 return -EPERM;
1354 cx18_av_write4(cx, reg->reg & 0x00000ffc, reg->val);
1355 return 0;
1356}
1357#endif
1358
1359static const struct v4l2_subdev_core_ops cx18_av_general_ops = {
1360 .g_chip_ident = cx18_av_g_chip_ident,
1361 .log_status = cx18_av_log_status,
1362 .load_fw = cx18_av_load_fw,
1363 .reset = cx18_av_reset,
1364 .queryctrl = cx18_av_queryctrl,
1365 .g_ctrl = cx18_av_g_ctrl,
1366 .s_ctrl = cx18_av_s_ctrl,
1367 .s_std = cx18_av_s_std,
1368#ifdef CONFIG_VIDEO_ADV_DEBUG
1369 .g_register = cx18_av_g_register,
1370 .s_register = cx18_av_s_register,
1371#endif
1372};
1373
1374static const struct v4l2_subdev_tuner_ops cx18_av_tuner_ops = {
1375 .s_radio = cx18_av_s_radio,
1376 .s_frequency = cx18_av_s_frequency,
1377 .g_tuner = cx18_av_g_tuner,
1378 .s_tuner = cx18_av_s_tuner,
1379};
1380
1381static const struct v4l2_subdev_audio_ops cx18_av_audio_ops = {
1382 .s_clock_freq = cx18_av_s_clock_freq,
1383 .s_routing = cx18_av_s_audio_routing,
1384};
1385
1386static const struct v4l2_subdev_video_ops cx18_av_video_ops = {
1387 .s_routing = cx18_av_s_video_routing,
1388 .s_stream = cx18_av_s_stream,
1389 .s_mbus_fmt = cx18_av_s_mbus_fmt,
1390};
1391
1392static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = {
1393 .decode_vbi_line = cx18_av_decode_vbi_line,
1394 .g_sliced_fmt = cx18_av_g_sliced_fmt,
1395 .s_sliced_fmt = cx18_av_s_sliced_fmt,
1396 .s_raw_fmt = cx18_av_s_raw_fmt,
1397};
1398
1399static const struct v4l2_subdev_ops cx18_av_ops = {
1400 .core = &cx18_av_general_ops,
1401 .tuner = &cx18_av_tuner_ops,
1402 .audio = &cx18_av_audio_ops,
1403 .video = &cx18_av_video_ops,
1404 .vbi = &cx18_av_vbi_ops,
1405};
1406
1407int cx18_av_probe(struct cx18 *cx)
1408{
1409 struct cx18_av_state *state = &cx->av_state;
1410 struct v4l2_subdev *sd;
1411 int err;
1412
1413 state->rev = cx18_av_read4(cx, CXADEC_CHIP_CTRL) & 0xffff;
1414 state->id = ((state->rev >> 4) == CXADEC_CHIP_TYPE_MAKO)
1415 ? V4L2_IDENT_CX23418_843 : V4L2_IDENT_UNKNOWN;
1416
1417 state->vid_input = CX18_AV_COMPOSITE7;
1418 state->aud_input = CX18_AV_AUDIO8;
1419 state->audclk_freq = 48000;
1420 state->audmode = V4L2_TUNER_MODE_LANG1;
1421 state->slicer_line_delay = 0;
1422 state->slicer_line_offset = (10 + state->slicer_line_delay - 2);
1423
1424 sd = &state->sd;
1425 v4l2_subdev_init(sd, &cx18_av_ops);
1426 v4l2_set_subdevdata(sd, cx);
1427 snprintf(sd->name, sizeof(sd->name),
1428 "%s %03x", cx->v4l2_dev.name, (state->rev >> 4));
1429 sd->grp_id = CX18_HW_418_AV;
1430 err = v4l2_device_register_subdev(&cx->v4l2_dev, sd);
1431 if (!err)
1432 cx18_av_init(cx);
1433 return err;
1434}
1435