aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx25840/cx25840-core.c
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2006-01-09 12:25:42 -0500
committerMauro Carvalho Chehab <mchehab@brturbo.com.br>2006-01-09 12:25:42 -0500
commita8bbf12ad8a8ad532cea0b67f0127ad90d336b04 (patch)
treebd8d9fb0888a7fe28b4795d7567c01ccf72b3c38 /drivers/media/video/cx25840/cx25840-core.c
parent3578d3dd0b1e468a44a76a83efe90476a854625d (diff)
V4L/DVB (3249): Generalized cx25840 video/audio input handling
- Added VIDIOC_S_AUDIO to set the audio inputs separately. - Removed AUDC_SET_INPUT. - Made the video inputs much more general. - Removed cardtype CID and replaced with a CID to enable the PVR150 workaround. The cardtype is no longer necessary with the general video input change. - Update VIDIOC_LOG_STATUS output to show the video and audio inputs separately. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
Diffstat (limited to 'drivers/media/video/cx25840/cx25840-core.c')
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c180
1 files changed, 93 insertions, 87 deletions
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index c2c1e856aa60..a897d6b7d708 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -115,8 +115,8 @@ int cx25840_and_or(struct i2c_client *client, u16 addr, u8 and_mask,
115 115
116/* ----------------------------------------------------------------------- */ 116/* ----------------------------------------------------------------------- */
117 117
118static int set_input(struct i2c_client *, enum cx25840_input); 118static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input,
119static void input_change(struct i2c_client *); 119 enum cx25840_audio_input aud_input);
120static void log_status(struct i2c_client *client); 120static void log_status(struct i2c_client *client);
121 121
122/* ----------------------------------------------------------------------- */ 122/* ----------------------------------------------------------------------- */
@@ -195,10 +195,8 @@ static void cx25840_initialize(struct i2c_client *client, int loadfw)
195 /* AC97 shift */ 195 /* AC97 shift */
196 cx25840_write(client, 0x8cf, 0x0f); 196 cx25840_write(client, 0x8cf, 0x0f);
197 197
198 /* (re)set video input */ 198 /* (re)set input */
199 set_input(client, state->input); 199 set_input(client, state->vid_input, state->aud_input);
200 /* (re)set audio input */
201 cx25840_audio(client, AUDC_SET_INPUT, &state->audio_input);
202 200
203 /* start microcontroller */ 201 /* start microcontroller */
204 cx25840_and_or(client, 0x803, ~0x10, 0x10); 202 cx25840_and_or(client, 0x803, ~0x10, 0x10);
@@ -223,7 +221,7 @@ static void input_change(struct i2c_client *client)
223 cx25840_write(client, 0x80b, 0x10); 221 cx25840_write(client, 0x80b, 0x10);
224 } else if (std & V4L2_STD_NTSC) { 222 } else if (std & V4L2_STD_NTSC) {
225 /* NTSC */ 223 /* NTSC */
226 if (state->cardtype == CARDTYPE_PVR150_WORKAROUND) { 224 if (state->pvr150_workaround) {
227 /* Certain Hauppauge PVR150 models have a hardware bug 225 /* Certain Hauppauge PVR150 models have a hardware bug
228 that causes audio to drop out. For these models the 226 that causes audio to drop out. For these models the
229 audio standard must be set explicitly. 227 audio standard must be set explicitly.
@@ -259,72 +257,68 @@ static void input_change(struct i2c_client *client)
259 } 257 }
260} 258}
261 259
262static int set_input(struct i2c_client *client, enum cx25840_input input) 260static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input,
261 enum cx25840_audio_input aud_input)
263{ 262{
264 struct cx25840_state *state = i2c_get_clientdata(client); 263 struct cx25840_state *state = i2c_get_clientdata(client);
264 u8 is_composite = (vid_input >= CX25840_COMPOSITE1 &&
265 vid_input <= CX25840_COMPOSITE8);
266 u8 reg;
265 267
266 cx25840_dbg("decoder set input (%d)\n", input); 268 cx25840_dbg("decoder set video input %d, audio input %d\n",
269 vid_input, aud_input);
267 270
268 switch (input) { 271 if (is_composite) {
269 case CX25840_TUNER: 272 reg = 0xf0 + (vid_input - CX25840_COMPOSITE1);
270 cx25840_dbg("now setting Tuner input\n"); 273 } else {
271 274 int luma = vid_input & 0xf0;
272 if (state->cardtype == CARDTYPE_PVR150 || 275 int chroma = vid_input & 0xf00;
273 state->cardtype == CARDTYPE_PVR150_WORKAROUND) {
274 /* CH_SEL_ADC2=1 */
275 cx25840_and_or(client, 0x102, ~0x2, 0x02);
276 }
277
278 /* Video Input Control */
279 if (state->cardtype == CARDTYPE_PG600) {
280 cx25840_write(client, 0x103, 0x11);
281 } else {
282 cx25840_write(client, 0x103, 0x46);
283 }
284
285 /* INPUT_MODE=0 */
286 cx25840_and_or(client, 0x401, ~0x6, 0x00);
287 break;
288
289 case CX25840_COMPOSITE0:
290 case CX25840_COMPOSITE1:
291 cx25840_dbg("now setting Composite input\n");
292 276
293 /* Video Input Control */ 277 if ((vid_input & ~0xff0) ||
294 if (state->cardtype == CARDTYPE_PG600) { 278 luma < CX25840_SVIDEO_LUMA1 || luma > CX25840_SVIDEO_LUMA4 ||
295 cx25840_write(client, 0x103, 0x00); 279 chroma < CX25840_SVIDEO_CHROMA4 || chroma > CX25840_SVIDEO_CHROMA8) {
296 } else { 280 cx25840_err("0x%04x is not a valid video input!\n", vid_input);
297 cx25840_write(client, 0x103, 0x02); 281 return -EINVAL;
298 } 282 }
299 283 reg = 0xf0 + ((luma - CX25840_SVIDEO_LUMA1) >> 4);
300 /* INPUT_MODE=0 */ 284 if (chroma >= CX25840_SVIDEO_CHROMA7) {
301 cx25840_and_or(client, 0x401, ~0x6, 0x00); 285 reg &= 0x3f;
302 break; 286 reg |= (chroma - CX25840_SVIDEO_CHROMA7) >> 2;
303
304 case CX25840_SVIDEO0:
305 case CX25840_SVIDEO1:
306 cx25840_dbg("now setting S-Video input\n");
307
308 /* CH_SEL_ADC2=0 */
309 cx25840_and_or(client, 0x102, ~0x2, 0x00);
310
311 /* Video Input Control */
312 if (state->cardtype == CARDTYPE_PG600) {
313 cx25840_write(client, 0x103, 0x02);
314 } else { 287 } else {
315 cx25840_write(client, 0x103, 0x10); 288 reg &= 0xcf;
289 reg |= (chroma - CX25840_SVIDEO_CHROMA4) >> 4;
316 } 290 }
291 }
317 292
318 /* INPUT_MODE=1 */ 293 switch (aud_input) {
319 cx25840_and_or(client, 0x401, ~0x6, 0x02); 294 case CX25840_AUDIO_SERIAL:
295 /* do nothing, use serial audio input */
320 break; 296 break;
297 case CX25840_AUDIO4: reg &= ~0x30; break;
298 case CX25840_AUDIO5: reg &= ~0x30; reg |= 0x10; break;
299 case CX25840_AUDIO6: reg &= ~0x30; reg |= 0x20; break;
300 case CX25840_AUDIO7: reg &= ~0xc0; break;
301 case CX25840_AUDIO8: reg &= ~0xc0; reg |= 0x40; break;
321 302
322 default: 303 default:
323 cx25840_err("%d is not a valid input!\n", input); 304 cx25840_err("0x%04x is not a valid audio input!\n", aud_input);
324 return -EINVAL; 305 return -EINVAL;
325 } 306 }
326 307
327 state->input = input; 308 cx25840_write(client, 0x103, reg);
309 /* Set INPUT_MODE to Composite (0) or S-Video (1) */
310 cx25840_and_or(client, 0x401, ~0x6, is_composite ? 0 : 0x02);
311 /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
312 cx25840_and_or(client, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0);
313 /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */
314 if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30)
315 cx25840_and_or(client, 0x102, ~0x4, 4);
316 else
317 cx25840_and_or(client, 0x102, ~0x4, 0);
318
319 state->vid_input = vid_input;
320 state->aud_input = aud_input;
321 cx25840_audio_set_path(client);
328 input_change(client); 322 input_change(client);
329 return 0; 323 return 0;
330} 324}
@@ -395,18 +389,9 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
395 struct cx25840_state *state = i2c_get_clientdata(client); 389 struct cx25840_state *state = i2c_get_clientdata(client);
396 390
397 switch (ctrl->id) { 391 switch (ctrl->id) {
398 case CX25840_CID_CARDTYPE: 392 case CX25840_CID_ENABLE_PVR150_WORKAROUND:
399 switch (ctrl->value) { 393 state->pvr150_workaround = ctrl->value;
400 case CARDTYPE_PVR150: 394 set_input(client, state->vid_input, state->aud_input);
401 case CARDTYPE_PVR150_WORKAROUND:
402 case CARDTYPE_PG600:
403 state->cardtype = ctrl->value;
404 break;
405 default:
406 return -ERANGE;
407 }
408
409 set_input(client, state->input);
410 break; 395 break;
411 396
412 case V4L2_CID_BRIGHTNESS: 397 case V4L2_CID_BRIGHTNESS:
@@ -465,8 +450,8 @@ static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
465 struct cx25840_state *state = i2c_get_clientdata(client); 450 struct cx25840_state *state = i2c_get_clientdata(client);
466 451
467 switch (ctrl->id) { 452 switch (ctrl->id) {
468 case CX25840_CID_CARDTYPE: 453 case CX25840_CID_ENABLE_PVR150_WORKAROUND:
469 ctrl->value = state->cardtype; 454 ctrl->value = state->pvr150_workaround;
470 break; 455 break;
471 case V4L2_CID_BRIGHTNESS: 456 case V4L2_CID_BRIGHTNESS:
472 ctrl->value = cx25840_read(client, 0x414) + 128; 457 ctrl->value = cx25840_read(client, 0x414) + 128;
@@ -615,7 +600,6 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
615 return cx25840_vbi(client, cmd, arg); 600 return cx25840_vbi(client, cmd, arg);
616 601
617 case VIDIOC_INT_AUDIO_CLOCK_FREQ: 602 case VIDIOC_INT_AUDIO_CLOCK_FREQ:
618 case AUDC_SET_INPUT:
619 result = cx25840_audio(client, cmd, arg); 603 result = cx25840_audio(client, cmd, arg);
620 break; 604 break;
621 605
@@ -652,13 +636,30 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
652 break; 636 break;
653 637
654 case VIDIOC_G_INPUT: 638 case VIDIOC_G_INPUT:
655 *(int *)arg = state->input; 639 *(int *)arg = state->vid_input;
656 break; 640 break;
657 641
658 case VIDIOC_S_INPUT: 642 case VIDIOC_S_INPUT:
659 result = set_input(client, *(int *)arg); 643 result = set_input(client, *(enum cx25840_video_input *)arg, state->aud_input);
660 break; 644 break;
661 645
646 case VIDIOC_S_AUDIO:
647 {
648 struct v4l2_audio *input = arg;
649
650 result = set_input(client, state->vid_input, input->index);
651 break;
652 }
653
654 case VIDIOC_G_AUDIO:
655 {
656 struct v4l2_audio *input = arg;
657
658 memset(input, 0, sizeof(*input));
659 input->index = state->aud_input;
660 break;
661 }
662
662 case VIDIOC_S_FREQUENCY: 663 case VIDIOC_S_FREQUENCY:
663 input_change(client); 664 input_change(client);
664 break; 665 break;
@@ -801,10 +802,10 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
801 802
802 i2c_set_clientdata(client, state); 803 i2c_set_clientdata(client, state);
803 memset(state, 0, sizeof(struct cx25840_state)); 804 memset(state, 0, sizeof(struct cx25840_state));
804 state->input = CX25840_TUNER; 805 state->vid_input = CX25840_COMPOSITE7;
806 state->aud_input = CX25840_AUDIO8;
805 state->audclk_freq = 48000; 807 state->audclk_freq = 48000;
806 state->audio_input = AUDIO_TUNER; 808 state->pvr150_workaround = 0;
807 state->cardtype = CARDTYPE_PVR150;
808 809
809 cx25840_initialize(client, 1); 810 cx25840_initialize(client, 1);
810 811
@@ -888,6 +889,8 @@ static void log_status(struct i2c_client *client)
888 u8 pref_mode = cx25840_read(client, 0x809); 889 u8 pref_mode = cx25840_read(client, 0x809);
889 u8 afc0 = cx25840_read(client, 0x80b); 890 u8 afc0 = cx25840_read(client, 0x80b);
890 u8 mute_ctl = cx25840_read(client, 0x8d3); 891 u8 mute_ctl = cx25840_read(client, 0x8d3);
892 int vid_input = state->vid_input;
893 int aud_input = state->aud_input;
891 char *p; 894 char *p;
892 895
893 cx25840_info("Video signal: %spresent\n", 896 cx25840_info("Video signal: %spresent\n",
@@ -997,16 +1000,19 @@ static void log_status(struct i2c_client *client)
997 cx25840_info("Specified standard: %s\n", 1000 cx25840_info("Specified standard: %s\n",
998 vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection"); 1001 vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection");
999 1002
1000 switch (state->input) { 1003 if (vid_input >= CX25840_COMPOSITE1 &&
1001 case CX25840_COMPOSITE0: p = "Composite 0"; break; 1004 vid_input <= CX25840_COMPOSITE8) {
1002 case CX25840_COMPOSITE1: p = "Composite 1"; break; 1005 cx25840_info("Specified video input: Composite %d\n",
1003 case CX25840_SVIDEO0: p = "S-Video 0"; break; 1006 vid_input - CX25840_COMPOSITE1 + 1);
1004 case CX25840_SVIDEO1: p = "S-Video 1"; break; 1007 } else {
1005 case CX25840_TUNER: p = "Tuner"; break; 1008 cx25840_info("Specified video input: S-Video (Luma In%d, Chroma In%d)\n",
1009 (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8);
1010 }
1011 if (aud_input) {
1012 cx25840_info("Specified audio input: Tuner (In%d)\n", aud_input);
1013 } else {
1014 cx25840_info("Specified audio input: External\n");
1006 } 1015 }
1007 cx25840_info("Specified input: %s\n", p);
1008 cx25840_info("Specified audio input: %s\n",
1009 state->audio_input == 0 ? "Tuner" : "External");
1010 1016
1011 cx25840_info("Specified audioclock freq: %d Hz\n", state->audclk_freq); 1017 cx25840_info("Specified audioclock freq: %d Hz\n", state->audclk_freq);
1012 1018