aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18
diff options
context:
space:
mode:
authorAndy Walls <awalls@radix.net>2009-05-03 17:01:57 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-06-16 17:20:54 -0400
commitf4672dffa126afe8c75bf45adc0f06c0a06d08e8 (patch)
treef701f0ae7c28eb879f1ecf70490052d556975365 /drivers/media/video/cx18
parentc7470206de9a879d8b90939a37a0d26ead114bd1 (diff)
V4L/DVB (11703): cx18: Have audio decoder drive SIF gain control, and rework AFE config
Ensure the variable gain amplifier gain for SIF is driven by the audio deocder and not the video decoder. This forced rework of the analog front end (AFE) configuration to not rely on autoconfiguration, but instead set up the AFE mux, AFE parameters, and ADC1 & ADC2 configurations explicitly. Reported-by: Helen Buus <mythtv@hbuus.com> Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx18')
-rw-r--r--drivers/media/video/cx18/cx18-av-core.c234
1 files changed, 165 insertions, 69 deletions
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c
index cf2bd888a429..2b07b156340b 100644
--- a/drivers/media/video/cx18/cx18-av-core.c
+++ b/drivers/media/video/cx18/cx18-av-core.c
@@ -99,9 +99,39 @@ int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 and_mask,
99 or_value); 99 or_value);
100} 100}
101 101
102static void cx18_av_initialize(struct cx18 *cx) 102static int cx18_av_init(struct v4l2_subdev *sd, u32 val)
103{ 103{
104 struct cx18_av_state *state = &cx->av_state; 104 struct cx18 *cx = v4l2_get_subdevdata(sd);
105
106 /*
107 * The crystal freq used in calculations in this driver will be
108 * 28.636360 MHz.
109 * Aim to run the PLLs' VCOs near 400 MHz to minimze errors.
110 */
111
112 /*
113 * VDCLK Integer = 0x0f, Post Divider = 0x04
114 * AIMCLK Integer = 0x0e, Post Divider = 0x16
115 */
116 cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f);
117
118 /* VDCLK Fraction = 0x2be2fe */
119 /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz before post divide */
120 cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe);
121
122 /* AIMCLK Fraction = 0x05227ad */
123 /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz pre post-div*/
124 cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad);
125
126 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */
127 cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56);
128 return 0;
129}
130
131static void cx18_av_initialize(struct v4l2_subdev *sd)
132{
133 struct cx18_av_state *state = to_cx18_av_state(sd);
134 struct cx18 *cx = v4l2_get_subdevdata(sd);
105 u32 v; 135 u32 v;
106 136
107 cx18_av_loadfw(cx); 137 cx18_av_loadfw(cx);
@@ -150,6 +180,26 @@ static void cx18_av_initialize(struct cx18 *cx)
150 cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0x8000); 180 cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0x8000);
151 cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0); 181 cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0);
152 182
183 /*
184 * Disable Video Auto-config of the Analog Front End and Video PLL.
185 *
186 * Since we only use BT.656 pixel mode, which works for both 525 and 625
187 * line systems, it's just easier for us to set registers
188 * 0x102 (CXADEC_CHIP_CTRL), 0x104-0x106 (CXADEC_AFE_CTRL),
189 * 0x108-0x109 (CXADEC_PLL_CTRL1), and 0x10c-0x10f (CXADEC_VID_PLL_FRAC)
190 * ourselves, than to run around cleaning up after the auto-config.
191 *
192 * (Note: my CX23418 chip doesn't seem to let the ACFG_DIS bit
193 * get set to 1, but OTOH, it doesn't seem to do AFE and VID PLL
194 * autoconfig either.)
195 *
196 * As a default, also turn off Dual mode for ADC2 and set ADC2 to CH3.
197 */
198 cx18_av_and_or4(cx, CXADEC_CHIP_CTRL, 0xFFFBFFFF, 0x00120000);
199
200 /* Setup the Video and and Aux/Audio PLLs */
201 cx18_av_init(sd, 0);
202
153 /* set video to auto-detect */ 203 /* set video to auto-detect */
154 /* Clear bits 11-12 to enable slow locking mode. Set autodetect mode */ 204 /* Clear bits 11-12 to enable slow locking mode. Set autodetect mode */
155 /* set the comb notch = 1 */ 205 /* set the comb notch = 1 */
@@ -176,12 +226,23 @@ static void cx18_av_initialize(struct cx18 *cx)
176 /* EncSetSignalStd(dwDevNum, pEnc->dwSigStd); */ 226 /* EncSetSignalStd(dwDevNum, pEnc->dwSigStd); */
177 /* EncSetVideoInput(dwDevNum, pEnc->VidIndSelection); */ 227 /* EncSetVideoInput(dwDevNum, pEnc->VidIndSelection); */
178 228
179 v = cx18_av_read4(cx, CXADEC_AFE_CTRL); 229 /*
180 v &= 0xFFFBFFFF; /* turn OFF bit 18 for droop_comp_ch1 */ 230 * Analog Front End (AFE)
181 v &= 0xFFFF7FFF; /* turn OFF bit 9 for clamp_sel_ch1 */ 231 * Default to luma on ch1/ADC1, chroma on ch2/ADC2, SIF on ch3/ADC2
182 v &= 0xFFFFFFFE; /* turn OFF bit 0 for 12db_ch1 */ 232 * bypass_ch[1-3] use filter
183 /* v |= 0x00000001;*/ /* turn ON bit 0 for 12db_ch1 */ 233 * droop_comp_ch[1-3] disable
184 cx18_av_write4(cx, CXADEC_AFE_CTRL, v); 234 * clamp_en_ch[1-3] disable
235 * aud_in_sel ADC2
236 * luma_in_sel ADC1
237 * chroma_in_sel ADC2
238 * clamp_sel_ch[2-3] midcode
239 * clamp_sel_ch1 video decoder
240 * vga_sel_ch3 audio decoder
241 * vga_sel_ch[1-2] video decoder
242 * half_bw_ch[1-3] disable
243 * +12db_ch[1-3] disable
244 */
245 cx18_av_and_or4(cx, CXADEC_AFE_CTRL, 0xFF000000, 0x00005D00);
185 246
186/* if(dwEnable && dw3DCombAvailable) { */ 247/* if(dwEnable && dw3DCombAvailable) { */
187/* CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x7728021F); */ 248/* CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x7728021F); */
@@ -195,50 +256,18 @@ static void cx18_av_initialize(struct cx18 *cx)
195 256
196static int cx18_av_reset(struct v4l2_subdev *sd, u32 val) 257static int cx18_av_reset(struct v4l2_subdev *sd, u32 val)
197{ 258{
198 struct cx18 *cx = v4l2_get_subdevdata(sd); 259 cx18_av_initialize(sd);
199
200 cx18_av_initialize(cx);
201 return 0;
202}
203
204static int cx18_av_init(struct v4l2_subdev *sd, u32 val)
205{
206 struct cx18 *cx = v4l2_get_subdevdata(sd);
207
208 /*
209 * The crystal freq used in calculations in this driver will be
210 * 28.636360 MHz.
211 * Aim to run the PLLs' VCOs near 400 MHz to minimze errors.
212 */
213
214 /*
215 * VDCLK Integer = 0x0f, Post Divider = 0x04
216 * AIMCLK Integer = 0x0e, Post Divider = 0x16
217 */
218 cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f);
219
220 /* VDCLK Fraction = 0x2be2fe */
221 /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz before post divide */
222 cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe);
223
224 /* AIMCLK Fraction = 0x05227ad */
225 /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz pre post-div*/
226 cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad);
227
228 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */
229 cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56);
230 return 0; 260 return 0;
231} 261}
232 262
233static int cx18_av_load_fw(struct v4l2_subdev *sd) 263static int cx18_av_load_fw(struct v4l2_subdev *sd)
234{ 264{
235 struct cx18_av_state *state = to_cx18_av_state(sd); 265 struct cx18_av_state *state = to_cx18_av_state(sd);
236 struct cx18 *cx = v4l2_get_subdevdata(sd);
237 266
238 if (!state->is_initialized) { 267 if (!state->is_initialized) {
239 /* initialize on first use */ 268 /* initialize on first use */
240 state->is_initialized = 1; 269 state->is_initialized = 1;
241 cx18_av_initialize(cx); 270 cx18_av_initialize(sd);
242 } 271 }
243 return 0; 272 return 0;
244} 273}
@@ -470,16 +499,23 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
470{ 499{
471 struct cx18_av_state *state = &cx->av_state; 500 struct cx18_av_state *state = &cx->av_state;
472 struct v4l2_subdev *sd = &state->sd; 501 struct v4l2_subdev *sd = &state->sd;
473 u8 is_composite = (vid_input >= CX18_AV_COMPOSITE1 && 502
474 vid_input <= CX18_AV_COMPOSITE8); 503 enum analog_signal_type {
475 u8 reg; 504 NONE, CVBS, Y, C, SIF, Pb, Pr
476 u8 v; 505 } ch[3] = {NONE, NONE, NONE};
506
507 u8 afe_mux_cfg;
508 u8 adc2_cfg;
509 u32 afe_cfg;
510 int i;
477 511
478 CX18_DEBUG_INFO_DEV(sd, "decoder set video input %d, audio input %d\n", 512 CX18_DEBUG_INFO_DEV(sd, "decoder set video input %d, audio input %d\n",
479 vid_input, aud_input); 513 vid_input, aud_input);
480 514
481 if (is_composite) { 515 if (vid_input >= CX18_AV_COMPOSITE1 &&
482 reg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1); 516 vid_input <= CX18_AV_COMPOSITE8) {
517 afe_mux_cfg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1);
518 ch[0] = CVBS;
483 } else { 519 } else {
484 int luma = vid_input & 0xf0; 520 int luma = vid_input & 0xf0;
485 int chroma = vid_input & 0xf00; 521 int chroma = vid_input & 0xf00;
@@ -493,26 +529,45 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
493 vid_input); 529 vid_input);
494 return -EINVAL; 530 return -EINVAL;
495 } 531 }
496 reg = 0xf0 + ((luma - CX18_AV_SVIDEO_LUMA1) >> 4); 532 afe_mux_cfg = 0xf0 + ((luma - CX18_AV_SVIDEO_LUMA1) >> 4);
533 ch[0] = Y;
497 if (chroma >= CX18_AV_SVIDEO_CHROMA7) { 534 if (chroma >= CX18_AV_SVIDEO_CHROMA7) {
498 reg &= 0x3f; 535 afe_mux_cfg &= 0x3f;
499 reg |= (chroma - CX18_AV_SVIDEO_CHROMA7) >> 2; 536 afe_mux_cfg |= (chroma - CX18_AV_SVIDEO_CHROMA7) >> 2;
537 ch[2] = C;
500 } else { 538 } else {
501 reg &= 0xcf; 539 afe_mux_cfg &= 0xcf;
502 reg |= (chroma - CX18_AV_SVIDEO_CHROMA4) >> 4; 540 afe_mux_cfg |= (chroma - CX18_AV_SVIDEO_CHROMA4) >> 4;
541 ch[1] = C;
503 } 542 }
504 } 543 }
544 /* TODO: LeadTek WinFast DVR3100 H & WinFast PVR2100 can do Y/Pb/Pr */
505 545
506 switch (aud_input) { 546 switch (aud_input) {
507 case CX18_AV_AUDIO_SERIAL1: 547 case CX18_AV_AUDIO_SERIAL1:
508 case CX18_AV_AUDIO_SERIAL2: 548 case CX18_AV_AUDIO_SERIAL2:
509 /* do nothing, use serial audio input */ 549 /* do nothing, use serial audio input */
510 break; 550 break;
511 case CX18_AV_AUDIO4: reg &= ~0x30; break; 551 case CX18_AV_AUDIO4:
512 case CX18_AV_AUDIO5: reg &= ~0x30; reg |= 0x10; break; 552 afe_mux_cfg &= ~0x30;
513 case CX18_AV_AUDIO6: reg &= ~0x30; reg |= 0x20; break; 553 ch[1] = SIF;
514 case CX18_AV_AUDIO7: reg &= ~0xc0; break; 554 break;
515 case CX18_AV_AUDIO8: reg &= ~0xc0; reg |= 0x40; break; 555 case CX18_AV_AUDIO5:
556 afe_mux_cfg = (afe_mux_cfg & ~0x30) | 0x10;
557 ch[1] = SIF;
558 break;
559 case CX18_AV_AUDIO6:
560 afe_mux_cfg = (afe_mux_cfg & ~0x30) | 0x20;
561 ch[1] = SIF;
562 break;
563 case CX18_AV_AUDIO7:
564 afe_mux_cfg &= ~0xc0;
565 ch[2] = SIF;
566 break;
567 case CX18_AV_AUDIO8:
568 afe_mux_cfg = (afe_mux_cfg & ~0xc0) | 0x40;
569 ch[2] = SIF;
570 break;
516 571
517 default: 572 default:
518 CX18_ERR_DEV(sd, "0x%04x is not a valid audio input!\n", 573 CX18_ERR_DEV(sd, "0x%04x is not a valid audio input!\n",
@@ -520,24 +575,65 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
520 return -EINVAL; 575 return -EINVAL;
521 } 576 }
522 577
523 cx18_av_write_expect(cx, 0x103, reg, reg, 0xf7); 578 /* Set up analog front end multiplexers */
579 cx18_av_write_expect(cx, 0x103, afe_mux_cfg, afe_mux_cfg, 0xf7);
524 /* Set INPUT_MODE to Composite (0) or S-Video (1) */ 580 /* Set INPUT_MODE to Composite (0) or S-Video (1) */
525 cx18_av_and_or(cx, 0x401, ~0x6, is_composite ? 0 : 0x02); 581 cx18_av_and_or(cx, 0x401, ~0x6, ch[0] == CVBS ? 0 : 0x02);
526 582
527 /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ 583 /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
528 v = cx18_av_read(cx, 0x102); 584 adc2_cfg = cx18_av_read(cx, 0x102);
529 if (reg & 0x80) 585 if (ch[2] == NONE)
530 v &= ~0x2; 586 adc2_cfg &= ~0x2; /* No sig on CH3, set ADC2 to CH2 for input */
531 else 587 else
532 v |= 0x2; 588 adc2_cfg |= 0x2; /* Signal on CH3, set ADC2 to CH3 for input */
589
533 /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */ 590 /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */
534 if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30) 591 if (ch[1] != NONE && ch[2] != NONE)
535 v |= 0x4; 592 adc2_cfg |= 0x4; /* Set dual mode */
536 else 593 else
537 v &= ~0x4; 594 adc2_cfg &= ~0x4; /* Clear dual mode */
538 cx18_av_write_expect(cx, 0x102, v, v, 0x17); 595 cx18_av_write_expect(cx, 0x102, adc2_cfg, adc2_cfg, 0x17);
596
597 /* Configure the analog front end */
598 afe_cfg = cx18_av_read4(cx, CXADEC_AFE_CTRL);
599 afe_cfg &= 0xff000000;
600 afe_cfg |= 0x00005000; /* CHROMA_IN, AUD_IN: ADC2; LUMA_IN: ADC1 */
601 if (ch[1] != NONE && ch[2] != NONE)
602 afe_cfg |= 0x00000030; /* half_bw_ch[2-3] since in dual mode */
603
604 for (i = 0; i < 3; i++) {
605 switch (ch[i]) {
606 default:
607 case NONE:
608 /* CLAMP_SEL = Fixed to midcode clamp level */
609 afe_cfg |= (0x00000200 << i);
610 break;
611 case CVBS:
612 case Y:
613 if (i > 0)
614 afe_cfg |= 0x00002000; /* LUMA_IN_SEL: ADC2 */
615 break;
616 case C:
617 case Pb:
618 case Pr:
619 /* CLAMP_SEL = Fixed to midcode clamp level */
620 afe_cfg |= (0x00000200 << i);
621 if (i == 0 && ch[i] == C)
622 afe_cfg &= ~0x00001000; /* CHROMA_IN_SEL ADC1 */
623 break;
624 case SIF:
625 /*
626 * VGA_GAIN_SEL = Audio Decoder
627 * CLAMP_SEL = Fixed to midcode clamp level
628 */
629 afe_cfg |= (0x00000240 << i);
630 if (i == 0)
631 afe_cfg &= ~0x00004000; /* AUD_IN_SEL ADC1 */
632 break;
633 }
634 }
539 635
540 /*cx18_av_and_or4(cx, 0x104, ~0x001b4180, 0x00004180);*/ 636 cx18_av_write4(cx, CXADEC_AFE_CTRL, afe_cfg);
541 637
542 state->vid_input = vid_input; 638 state->vid_input = vid_input;
543 state->aud_input = aud_input; 639 state->aud_input = aud_input;