aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/msp3400-driver.c
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2006-01-09 15:21:36 -0500
committerMauro Carvalho Chehab <mchehab@brturbo.com.br>2006-01-09 15:21:36 -0500
commitd312a46e5340be6a89c662ac483230c0737148c9 (patch)
tree4d458407ce0baaf613360c4b0866e9f96b5d5df3 /drivers/media/video/msp3400-driver.c
parent1157020d542684e273242663d0befb58e284ade7 (diff)
V4L/DVB (3324): msp3400 audio handling bug fixes.
- Check capabilities for audio settings (volume, balance, bass, treble, loudness, mute) - added loudness support - added missing VIDEO_AUDIO_BALANCE flags for v4l1 compatibility - do not call msp_any_detect_stereo for non-autoselect chips to retrieve the current stereo setting: that will temporarily mute the sound. It is only needed when the stereo mode might be changed, and for autoselect msp processors that do not periodically need to update their stereo setting. - do not wake up the thread if the standard did not change. Prevents temporary audio drop-out if the standard is set to the same value. - fix confused stereo detect code where V4L2_TUNER_SUB_STEREO and V4L2_TUNER_MODE_STEREO values were used incorrectly. - stereo mode reporting was broken (v4l2 value used to index a string array expecting v4l1 mode values). - do not set dsp register 0x30 in the 3410d thread: that register does not exist for pre-'G' revision msp chips. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
Diffstat (limited to 'drivers/media/video/msp3400-driver.c')
-rw-r--r--drivers/media/video/msp3400-driver.c190
1 files changed, 138 insertions, 52 deletions
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
index 0c2ab7e9d1cc..04a05d7dd470 100644
--- a/drivers/media/video/msp3400-driver.c
+++ b/drivers/media/video/msp3400-driver.c
@@ -283,33 +283,57 @@ void msp_set_scart(struct i2c_client *client, int in, int out)
283 283
284void msp_set_mute(struct i2c_client *client) 284void msp_set_mute(struct i2c_client *client)
285{ 285{
286 struct msp_state *state = i2c_get_clientdata(client);
287
286 v4l_dbg(1, client, "mute audio\n"); 288 v4l_dbg(1, client, "mute audio\n");
287 msp_write_dsp(client, 0x0000, 0); /* loudspeaker */ 289 msp_write_dsp(client, 0x0000, 0);
288 msp_write_dsp(client, 0x0006, 0); /* headphones */ 290 msp_write_dsp(client, 0x0007, 1);
291 if (state->has_scart2_out_volume)
292 msp_write_dsp(client, 0x0040, 1);
293 if (state->has_headphones)
294 msp_write_dsp(client, 0x0006, 0);
289} 295}
290 296
291void msp_set_audio(struct i2c_client *client) 297void msp_set_audio(struct i2c_client *client)
292{ 298{
293 struct msp_state *state = i2c_get_clientdata(client); 299 struct msp_state *state = i2c_get_clientdata(client);
294 int val = 0, bal = 0, bass, treble; 300 int bal = 0, bass, treble, loudness;
301 int val = 0;
295 302
296 if (!state->muted) 303 if (!state->muted)
297 val = (state->volume * 0x7f / 65535) << 8; 304 val = (state->volume * 0x7f / 65535) << 8;
305
306 v4l_dbg(1, client, "mute=%s volume=%d\n",
307 state->muted ? "on" : "off", state->volume);
308
309 msp_write_dsp(client, 0x0000, val);
310 msp_write_dsp(client, 0x0007, state->muted ? 0x1 : (val | 0x1));
311 if (state->has_scart2_out_volume)
312 msp_write_dsp(client, 0x0040, state->muted ? 0x1 : (val | 0x1));
313 if (state->has_headphones)
314 msp_write_dsp(client, 0x0006, val);
315 if (!state->has_sound_processing)
316 return;
317
298 if (val) 318 if (val)
299 bal = (state->balance / 256) - 128; 319 bal = (u8)((state->balance / 256) - 128);
300 bass = ((state->bass - 32768) * 0x60 / 65535) << 8; 320 bass = ((state->bass - 32768) * 0x60 / 65535) << 8;
301 treble = ((state->treble - 32768) * 0x60 / 65535) << 8; 321 treble = ((state->treble - 32768) * 0x60 / 65535) << 8;
322 loudness = state->loudness ? ((5 * 4) << 8) : 0;
302 323
303 v4l_dbg(1, client, "mute=%s volume=%d balance=%d bass=%d treble=%d\n", 324 v4l_dbg(1, client, "balance=%d bass=%d treble=%d loudness=%d\n",
304 state->muted ? "on" : "off", state->volume, state->balance, 325 state->balance, state->bass, state->treble, state->loudness);
305 state->bass, state->treble);
306 326
307 msp_write_dsp(client, 0x0000, val); /* loudspeaker */
308 msp_write_dsp(client, 0x0006, val); /* headphones */
309 msp_write_dsp(client, 0x0007, state->muted ? 0x1 : (val | 0x1));
310 msp_write_dsp(client, 0x0001, bal << 8); 327 msp_write_dsp(client, 0x0001, bal << 8);
311 msp_write_dsp(client, 0x0002, bass); /* loudspeaker */ 328 msp_write_dsp(client, 0x0002, bass);
312 msp_write_dsp(client, 0x0003, treble); /* loudspeaker */ 329 msp_write_dsp(client, 0x0003, treble);
330 msp_write_dsp(client, 0x0004, loudness);
331 if (!state->has_headphones)
332 return;
333 msp_write_dsp(client, 0x0030, bal << 8);
334 msp_write_dsp(client, 0x0031, bass);
335 msp_write_dsp(client, 0x0032, treble);
336 msp_write_dsp(client, 0x0033, loudness);
313} 337}
314 338
315int msp_modus(struct i2c_client *client) 339int msp_modus(struct i2c_client *client)
@@ -421,7 +445,7 @@ static void msp_any_detect_stereo(struct i2c_client *client)
421 } 445 }
422} 446}
423 447
424static struct v4l2_queryctrl msp_qctrl[] = { 448static struct v4l2_queryctrl msp_qctrl_std[] = {
425 { 449 {
426 .id = V4L2_CID_AUDIO_VOLUME, 450 .id = V4L2_CID_AUDIO_VOLUME,
427 .name = "Volume", 451 .name = "Volume",
@@ -432,15 +456,6 @@ static struct v4l2_queryctrl msp_qctrl[] = {
432 .flags = 0, 456 .flags = 0,
433 .type = V4L2_CTRL_TYPE_INTEGER, 457 .type = V4L2_CTRL_TYPE_INTEGER,
434 },{ 458 },{
435 .id = V4L2_CID_AUDIO_BALANCE,
436 .name = "Balance",
437 .minimum = 0,
438 .maximum = 65535,
439 .step = 65535/100,
440 .default_value = 32768,
441 .flags = 0,
442 .type = V4L2_CTRL_TYPE_INTEGER,
443 },{
444 .id = V4L2_CID_AUDIO_MUTE, 459 .id = V4L2_CID_AUDIO_MUTE,
445 .name = "Mute", 460 .name = "Mute",
446 .minimum = 0, 461 .minimum = 0,
@@ -449,6 +464,19 @@ static struct v4l2_queryctrl msp_qctrl[] = {
449 .default_value = 1, 464 .default_value = 1,
450 .flags = 0, 465 .flags = 0,
451 .type = V4L2_CTRL_TYPE_BOOLEAN, 466 .type = V4L2_CTRL_TYPE_BOOLEAN,
467 },
468};
469
470static struct v4l2_queryctrl msp_qctrl_sound_processing[] = {
471 {
472 .id = V4L2_CID_AUDIO_BALANCE,
473 .name = "Balance",
474 .minimum = 0,
475 .maximum = 65535,
476 .step = 65535/100,
477 .default_value = 32768,
478 .flags = 0,
479 .type = V4L2_CTRL_TYPE_INTEGER,
452 },{ 480 },{
453 .id = V4L2_CID_AUDIO_BASS, 481 .id = V4L2_CID_AUDIO_BASS,
454 .name = "Bass", 482 .name = "Bass",
@@ -465,6 +493,15 @@ static struct v4l2_queryctrl msp_qctrl[] = {
465 .step = 65535/100, 493 .step = 65535/100,
466 .default_value = 32768, 494 .default_value = 32768,
467 .type = V4L2_CTRL_TYPE_INTEGER, 495 .type = V4L2_CTRL_TYPE_INTEGER,
496 },{
497 .id = V4L2_CID_AUDIO_LOUDNESS,
498 .name = "Loudness",
499 .minimum = 0,
500 .maximum = 1,
501 .step = 1,
502 .default_value = 1,
503 .flags = 0,
504 .type = V4L2_CTRL_TYPE_BOOLEAN,
468 }, 505 },
469}; 506};
470 507
@@ -490,24 +527,36 @@ static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
490 struct msp_state *state = i2c_get_clientdata(client); 527 struct msp_state *state = i2c_get_clientdata(client);
491 528
492 switch (ctrl->id) { 529 switch (ctrl->id) {
530 case V4L2_CID_AUDIO_VOLUME:
531 ctrl->value = state->volume;
532 break;
533
493 case V4L2_CID_AUDIO_MUTE: 534 case V4L2_CID_AUDIO_MUTE:
494 ctrl->value = state->muted; 535 ctrl->value = state->muted;
495 break; 536 break;
496 537
497 case V4L2_CID_AUDIO_BALANCE: 538 case V4L2_CID_AUDIO_BALANCE:
539 if (!state->has_sound_processing)
540 return -EINVAL;
498 ctrl->value = state->balance; 541 ctrl->value = state->balance;
499 break; 542 break;
500 543
501 case V4L2_CID_AUDIO_BASS: 544 case V4L2_CID_AUDIO_BASS:
545 if (!state->has_sound_processing)
546 return -EINVAL;
502 ctrl->value = state->bass; 547 ctrl->value = state->bass;
503 break; 548 break;
504 549
505 case V4L2_CID_AUDIO_TREBLE: 550 case V4L2_CID_AUDIO_TREBLE:
551 if (!state->has_sound_processing)
552 return -EINVAL;
506 ctrl->value = state->treble; 553 ctrl->value = state->treble;
507 break; 554 break;
508 555
509 case V4L2_CID_AUDIO_VOLUME: 556 case V4L2_CID_AUDIO_LOUDNESS:
510 ctrl->value = state->volume; 557 if (!state->has_sound_processing)
558 return -EINVAL;
559 ctrl->value = state->loudness;
511 break; 560 break;
512 561
513 default: 562 default:
@@ -521,6 +570,12 @@ static int msp_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
521 struct msp_state *state = i2c_get_clientdata(client); 570 struct msp_state *state = i2c_get_clientdata(client);
522 571
523 switch (ctrl->id) { 572 switch (ctrl->id) {
573 case V4L2_CID_AUDIO_VOLUME:
574 state->volume = ctrl->value;
575 if (state->volume == 0)
576 state->balance = 32768;
577 break;
578
524 case V4L2_CID_AUDIO_MUTE: 579 case V4L2_CID_AUDIO_MUTE:
525 if (ctrl->value < 0 || ctrl->value >= 2) 580 if (ctrl->value < 0 || ctrl->value >= 2)
526 return -ERANGE; 581 return -ERANGE;
@@ -528,21 +583,27 @@ static int msp_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
528 break; 583 break;
529 584
530 case V4L2_CID_AUDIO_BASS: 585 case V4L2_CID_AUDIO_BASS:
586 if (!state->has_sound_processing)
587 return -EINVAL;
531 state->bass = ctrl->value; 588 state->bass = ctrl->value;
532 break; 589 break;
533 590
534 case V4L2_CID_AUDIO_TREBLE: 591 case V4L2_CID_AUDIO_TREBLE:
592 if (!state->has_sound_processing)
593 return -EINVAL;
535 state->treble = ctrl->value; 594 state->treble = ctrl->value;
536 break; 595 break;
537 596
538 case V4L2_CID_AUDIO_BALANCE: 597 case V4L2_CID_AUDIO_LOUDNESS:
539 state->balance = ctrl->value; 598 if (!state->has_sound_processing)
599 return -EINVAL;
600 state->loudness = ctrl->value;
540 break; 601 break;
541 602
542 case V4L2_CID_AUDIO_VOLUME: 603 case V4L2_CID_AUDIO_BALANCE:
543 state->volume = ctrl->value; 604 if (!state->has_sound_processing)
544 if (state->volume == 0) 605 return -EINVAL;
545 state->balance = 32768; 606 state->balance = ctrl->value;
546 break; 607 break;
547 608
548 default: 609 default:
@@ -628,13 +689,11 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
628 { 689 {
629 struct video_audio *va = arg; 690 struct video_audio *va = arg;
630 691
631 va->flags |= VIDEO_AUDIO_VOLUME | 692 va->flags |= VIDEO_AUDIO_VOLUME | VIDEO_AUDIO_MUTABLE;
632 VIDEO_AUDIO_BASS | 693 if (state->has_sound_processing)
633 VIDEO_AUDIO_TREBLE | 694 va->flags |= VIDEO_AUDIO_BALANCE |
634 VIDEO_AUDIO_MUTABLE; 695 VIDEO_AUDIO_BASS |
635 if (state->muted) 696 VIDEO_AUDIO_TREBLE;
636 va->flags |= VIDEO_AUDIO_MUTE;
637
638 if (state->muted) 697 if (state->muted)
639 va->flags |= VIDEO_AUDIO_MUTE; 698 va->flags |= VIDEO_AUDIO_MUTE;
640 va->volume = state->volume; 699 va->volume = state->volume;
@@ -642,7 +701,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
642 va->bass = state->bass; 701 va->bass = state->bass;
643 va->treble = state->treble; 702 va->treble = state->treble;
644 703
645 msp_any_detect_stereo(client); 704 if (state->opmode == OPMODE_AUTOSELECT)
705 msp_any_detect_stereo(client);
646 va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans); 706 va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans);
647 break; 707 break;
648 } 708 }
@@ -666,15 +726,24 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
666 case VIDIOCSCHAN: 726 case VIDIOCSCHAN:
667 { 727 {
668 struct video_channel *vc = arg; 728 struct video_channel *vc = arg;
729 int update = 0;
730 v4l2_std_id std;
669 731
732 if (state->radio)
733 update = 1;
670 state->radio = 0; 734 state->radio = 0;
671 if (vc->norm == VIDEO_MODE_PAL) 735 if (vc->norm == VIDEO_MODE_PAL)
672 state->std = V4L2_STD_PAL; 736 std = V4L2_STD_PAL;
673 else if (vc->norm == VIDEO_MODE_SECAM) 737 else if (vc->norm == VIDEO_MODE_SECAM)
674 state->std = V4L2_STD_SECAM; 738 std = V4L2_STD_SECAM;
675 else 739 else
676 state->std = V4L2_STD_NTSC; 740 std = V4L2_STD_NTSC;
677 msp_wake_thread(client); 741 if (std != state->std) {
742 state->std = std;
743 update = 1;
744 }
745 if (update)
746 msp_wake_thread(client);
678 break; 747 break;
679 } 748 }
680 749
@@ -699,10 +768,12 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
699 case VIDIOC_S_STD: 768 case VIDIOC_S_STD:
700 { 769 {
701 v4l2_std_id *id = arg; 770 v4l2_std_id *id = arg;
771 int update = state->radio || state->std != *id;
702 772
703 state->std = *id; 773 state->std = *id;
704 state->radio = 0; 774 state->radio = 0;
705 msp_wake_thread(client); 775 if (update)
776 msp_wake_thread(client);
706 return 0; 777 return 0;
707 } 778 }
708 779
@@ -808,7 +879,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
808 { 879 {
809 struct v4l2_tuner *vt = arg; 880 struct v4l2_tuner *vt = arg;
810 881
811 msp_any_detect_stereo(client); 882 if (state->opmode == OPMODE_AUTOSELECT)
883 msp_any_detect_stereo(client);
812 vt->audmode = state->audmode; 884 vt->audmode = state->audmode;
813 vt->rxsubchans = state->rxsubchans; 885 vt->rxsubchans = state->rxsubchans;
814 vt->capability = V4L2_TUNER_CAP_STEREO | 886 vt->capability = V4L2_TUNER_CAP_STEREO |
@@ -887,9 +959,16 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
887 struct v4l2_queryctrl *qc = arg; 959 struct v4l2_queryctrl *qc = arg;
888 int i; 960 int i;
889 961
890 for (i = 0; i < ARRAY_SIZE(msp_qctrl); i++) 962 for (i = 0; i < ARRAY_SIZE(msp_qctrl_std); i++)
891 if (qc->id && qc->id == msp_qctrl[i].id) { 963 if (qc->id && qc->id == msp_qctrl_std[i].id) {
892 memcpy(qc, &msp_qctrl[i], sizeof(*qc)); 964 memcpy(qc, &msp_qctrl_std[i], sizeof(*qc));
965 return 0;
966 }
967 if (!state->has_sound_processing)
968 return -EINVAL;
969 for (i = 0; i < ARRAY_SIZE(msp_qctrl_sound_processing); i++)
970 if (qc->id && qc->id == msp_qctrl_sound_processing[i].id) {
971 memcpy(qc, &msp_qctrl_sound_processing[i], sizeof(*qc));
893 return 0; 972 return 0;
894 } 973 }
895 return -EINVAL; 974 return -EINVAL;
@@ -902,13 +981,17 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
902 return msp_set_ctrl(client, arg); 981 return msp_set_ctrl(client, arg);
903 982
904 case VIDIOC_LOG_STATUS: 983 case VIDIOC_LOG_STATUS:
905 msp_any_detect_stereo(client); 984 if (state->opmode == OPMODE_AUTOSELECT)
985 msp_any_detect_stereo(client);
906 v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n", 986 v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n",
907 client->name, state->rev1, state->rev2); 987 client->name, state->rev1, state->rev2);
908 v4l_info(client, "Audio: volume %d balance %d bass %d treble %d%s\n", 988 v4l_info(client, "Audio: volume %d%s\n",
909 state->volume, state->balance, 989 state->volume, state->muted ? " (muted)" : "");
910 state->bass, state->treble, 990 if (state->has_sound_processing) {
911 state->muted ? " (muted)" : ""); 991 v4l_info(client, "Audio: balance %d bass %d treble %d loudness %s\n",
992 state->balance, state->bass, state->treble,
993 state->loudness ? "on" : "off");
994 }
912 v4l_info(client, "Mode: %s (%s%s)\n", msp_standard_mode_name(state->mode), 995 v4l_info(client, "Mode: %s (%s%s)\n", msp_standard_mode_name(state->mode),
913 (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono", 996 (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono",
914 (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : ""); 997 (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : "");
@@ -983,6 +1066,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind)
983 state->balance = 32768; /* 0db gain */ 1066 state->balance = 32768; /* 0db gain */
984 state->bass = 32768; 1067 state->bass = 32768;
985 state->treble = 32768; 1068 state->treble = 32768;
1069 state->loudness = 0;
986 state->input = -1; 1070 state->input = -1;
987 state->muted = 0; 1071 state->muted = 0;
988 state->i2s_mode = 0; 1072 state->i2s_mode = 0;
@@ -1023,6 +1107,8 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind)
1023 /* Has scart2 and scart3 inputs and scart2 output: not in stripped 1107 /* Has scart2 and scart3 inputs and scart2 output: not in stripped
1024 down products of the '3' family */ 1108 down products of the '3' family */
1025 state->has_scart23_in_scart2_out = msp_family >= 4 || msp_prod_lo < 5; 1109 state->has_scart23_in_scart2_out = msp_family >= 4 || msp_prod_lo < 5;
1110 /* Has scart2 a volume control? Not in pre-D revisions. */
1111 state->has_scart2_out_volume = msp_revision > 'C' && state->has_scart23_in_scart2_out;
1026 /* Has subwoofer output: not in pre-D revs and not in stripped down products */ 1112 /* Has subwoofer output: not in pre-D revs and not in stripped down products */
1027 state->has_subwoofer = msp_revision >= 'D' && msp_prod_lo < 5; 1113 state->has_subwoofer = msp_revision >= 'D' && msp_prod_lo < 5;
1028 /* Has soundprocessing (bass/treble/balance/loudness/equalizer): not in 1114 /* Has soundprocessing (bass/treble/balance/loudness/equalizer): not in