diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2006-01-23 14:11:09 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@brturbo.com.br> | 2006-01-23 14:11:09 -0500 |
commit | 8a4b275f9c192921797f45c2d4b5e4bc3875500a (patch) | |
tree | da12ba774968078df22718a58221e87b71387fca /drivers/media/video | |
parent | 9aeb4b051b65c0248ea6589096950413c4da9d63 (diff) |
V4L/DVB (3427): audmode and rxsubchans fixes (VIDIOC_G/S_TUNER)
- Audmode and rxsubchans fixes in msp3400, tuner, tvaudio and cx25840.
- msp3400 cleanups
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/cx25840/cx25840-core.c | 46 | ||||
-rw-r--r-- | drivers/media/video/cx25840/cx25840.h | 1 | ||||
-rw-r--r-- | drivers/media/video/msp3400-driver.c | 59 | ||||
-rw-r--r-- | drivers/media/video/msp3400-kthreads.c | 330 | ||||
-rw-r--r-- | drivers/media/video/msp3400.h | 11 | ||||
-rw-r--r-- | drivers/media/video/tuner-core.c | 68 | ||||
-rw-r--r-- | drivers/media/video/tvaudio.c | 26 |
7 files changed, 255 insertions, 286 deletions
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index c66c2c1f4809..3acd587b160c 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c | |||
@@ -753,6 +753,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, | |||
753 | 753 | ||
754 | memset(input, 0, sizeof(*input)); | 754 | memset(input, 0, sizeof(*input)); |
755 | input->index = state->aud_input; | 755 | input->index = state->aud_input; |
756 | input->capability = V4L2_AUDCAP_STEREO; | ||
756 | break; | 757 | break; |
757 | } | 758 | } |
758 | 759 | ||
@@ -763,7 +764,6 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, | |||
763 | case VIDIOC_G_TUNER: | 764 | case VIDIOC_G_TUNER: |
764 | { | 765 | { |
765 | u8 mode = cx25840_read(client, 0x804); | 766 | u8 mode = cx25840_read(client, 0x804); |
766 | u8 pref = cx25840_read(client, 0x809) & 0xf; | ||
767 | u8 vpres = cx25840_read(client, 0x80a) & 0x10; | 767 | u8 vpres = cx25840_read(client, 0x80a) & 0x10; |
768 | int val = 0; | 768 | int val = 0; |
769 | 769 | ||
@@ -783,44 +783,49 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, | |||
783 | val |= V4L2_TUNER_SUB_MONO; | 783 | val |= V4L2_TUNER_SUB_MONO; |
784 | 784 | ||
785 | if (mode == 2 || mode == 4) | 785 | if (mode == 2 || mode == 4) |
786 | val |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; | 786 | val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; |
787 | 787 | ||
788 | if (mode & 0x10) | 788 | if (mode & 0x10) |
789 | val |= V4L2_TUNER_SUB_SAP; | 789 | val |= V4L2_TUNER_SUB_SAP; |
790 | 790 | ||
791 | vt->rxsubchans = val; | 791 | vt->rxsubchans = val; |
792 | 792 | vt->audmode = state->audmode; | |
793 | switch (pref) { | ||
794 | case 0: | ||
795 | vt->audmode = V4L2_TUNER_MODE_MONO; | ||
796 | break; | ||
797 | case 1: | ||
798 | case 2: | ||
799 | vt->audmode = V4L2_TUNER_MODE_LANG2; | ||
800 | break; | ||
801 | case 4: | ||
802 | default: | ||
803 | vt->audmode = V4L2_TUNER_MODE_STEREO; | ||
804 | } | ||
805 | break; | 793 | break; |
806 | } | 794 | } |
807 | 795 | ||
808 | case VIDIOC_S_TUNER: | 796 | case VIDIOC_S_TUNER: |
797 | if (state->radio) | ||
798 | break; | ||
799 | |||
809 | switch (vt->audmode) { | 800 | switch (vt->audmode) { |
810 | case V4L2_TUNER_MODE_MONO: | 801 | case V4L2_TUNER_MODE_MONO: |
811 | case V4L2_TUNER_MODE_LANG1: | 802 | /* mono -> mono |
812 | /* Force PREF_MODE to MONO */ | 803 | stereo -> mono |
804 | bilingual -> lang1 */ | ||
813 | cx25840_and_or(client, 0x809, ~0xf, 0x00); | 805 | cx25840_and_or(client, 0x809, ~0xf, 0x00); |
814 | break; | 806 | break; |
815 | case V4L2_TUNER_MODE_STEREO: | 807 | case V4L2_TUNER_MODE_LANG1: |
816 | /* Force PREF_MODE to STEREO */ | 808 | /* mono -> mono |
809 | stereo -> stereo | ||
810 | bilingual -> lang1 */ | ||
817 | cx25840_and_or(client, 0x809, ~0xf, 0x04); | 811 | cx25840_and_or(client, 0x809, ~0xf, 0x04); |
818 | break; | 812 | break; |
813 | case V4L2_TUNER_MODE_STEREO: | ||
814 | /* mono -> mono | ||
815 | stereo -> stereo | ||
816 | bilingual -> lang1/lang2 */ | ||
817 | cx25840_and_or(client, 0x809, ~0xf, 0x07); | ||
818 | break; | ||
819 | case V4L2_TUNER_MODE_LANG2: | 819 | case V4L2_TUNER_MODE_LANG2: |
820 | /* Force PREF_MODE to LANG2 */ | 820 | /* mono -> mono |
821 | stereo ->stereo | ||
822 | bilingual -> lang2 */ | ||
821 | cx25840_and_or(client, 0x809, ~0xf, 0x01); | 823 | cx25840_and_or(client, 0x809, ~0xf, 0x01); |
822 | break; | 824 | break; |
825 | default: | ||
826 | return -EINVAL; | ||
823 | } | 827 | } |
828 | state->audmode = vt->audmode; | ||
824 | break; | 829 | break; |
825 | 830 | ||
826 | case VIDIOC_G_FMT: | 831 | case VIDIOC_G_FMT: |
@@ -901,6 +906,7 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, | |||
901 | state->aud_input = CX25840_AUDIO8; | 906 | state->aud_input = CX25840_AUDIO8; |
902 | state->audclk_freq = 48000; | 907 | state->audclk_freq = 48000; |
903 | state->pvr150_workaround = 0; | 908 | state->pvr150_workaround = 0; |
909 | state->audmode = V4L2_TUNER_MODE_LANG1; | ||
904 | 910 | ||
905 | cx25840_initialize(client, 1); | 911 | cx25840_initialize(client, 1); |
906 | 912 | ||
diff --git a/drivers/media/video/cx25840/cx25840.h b/drivers/media/video/cx25840/cx25840.h index fd22f30dcc1b..dd70664d1dd9 100644 --- a/drivers/media/video/cx25840/cx25840.h +++ b/drivers/media/video/cx25840/cx25840.h | |||
@@ -78,6 +78,7 @@ struct cx25840_state { | |||
78 | enum cx25840_video_input vid_input; | 78 | enum cx25840_video_input vid_input; |
79 | enum cx25840_audio_input aud_input; | 79 | enum cx25840_audio_input aud_input; |
80 | u32 audclk_freq; | 80 | u32 audclk_freq; |
81 | int audmode; | ||
81 | }; | 82 | }; |
82 | 83 | ||
83 | /* ----------------------------------------------------------------------- */ | 84 | /* ----------------------------------------------------------------------- */ |
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index 994c340f9d02..11ea9765769c 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c | |||
@@ -411,9 +411,9 @@ static int msp_mode_v4l2_to_v4l1(int rxsubchans) | |||
411 | if (rxsubchans & V4L2_TUNER_SUB_STEREO) | 411 | if (rxsubchans & V4L2_TUNER_SUB_STEREO) |
412 | mode |= VIDEO_SOUND_STEREO; | 412 | mode |= VIDEO_SOUND_STEREO; |
413 | if (rxsubchans & V4L2_TUNER_SUB_LANG2) | 413 | if (rxsubchans & V4L2_TUNER_SUB_LANG2) |
414 | mode |= VIDEO_SOUND_LANG2; | 414 | mode |= VIDEO_SOUND_LANG2 | VIDEO_SOUND_STEREO; |
415 | if (rxsubchans & V4L2_TUNER_SUB_LANG1) | 415 | if (rxsubchans & V4L2_TUNER_SUB_LANG1) |
416 | mode |= VIDEO_SOUND_LANG1; | 416 | mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_STEREO; |
417 | if (mode == 0) | 417 | if (mode == 0) |
418 | mode |= VIDEO_SOUND_MONO; | 418 | mode |= VIDEO_SOUND_MONO; |
419 | return mode; | 419 | return mode; |
@@ -430,21 +430,6 @@ static int msp_mode_v4l1_to_v4l2(int mode) | |||
430 | return V4L2_TUNER_MODE_MONO; | 430 | return V4L2_TUNER_MODE_MONO; |
431 | } | 431 | } |
432 | 432 | ||
433 | static void msp_any_detect_stereo(struct i2c_client *client) | ||
434 | { | ||
435 | struct msp_state *state = i2c_get_clientdata(client); | ||
436 | |||
437 | switch (state->opmode) { | ||
438 | case OPMODE_MANUAL: | ||
439 | case OPMODE_AUTODETECT: | ||
440 | autodetect_stereo(client); | ||
441 | break; | ||
442 | case OPMODE_AUTOSELECT: | ||
443 | msp34xxg_detect_stereo(client); | ||
444 | break; | ||
445 | } | ||
446 | } | ||
447 | |||
448 | static struct v4l2_queryctrl msp_qctrl_std[] = { | 433 | static struct v4l2_queryctrl msp_qctrl_std[] = { |
449 | { | 434 | { |
450 | .id = V4L2_CID_AUDIO_VOLUME, | 435 | .id = V4L2_CID_AUDIO_VOLUME, |
@@ -506,22 +491,6 @@ static struct v4l2_queryctrl msp_qctrl_sound_processing[] = { | |||
506 | }; | 491 | }; |
507 | 492 | ||
508 | 493 | ||
509 | static void msp_any_set_audmode(struct i2c_client *client, int audmode) | ||
510 | { | ||
511 | struct msp_state *state = i2c_get_clientdata(client); | ||
512 | |||
513 | switch (state->opmode) { | ||
514 | case OPMODE_MANUAL: | ||
515 | case OPMODE_AUTODETECT: | ||
516 | state->watch_stereo = 0; | ||
517 | msp3400c_setstereo(client, audmode); | ||
518 | break; | ||
519 | case OPMODE_AUTOSELECT: | ||
520 | msp34xxg_set_audmode(client, audmode); | ||
521 | break; | ||
522 | } | ||
523 | } | ||
524 | |||
525 | static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) | 494 | static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) |
526 | { | 495 | { |
527 | struct msp_state *state = i2c_get_clientdata(client); | 496 | struct msp_state *state = i2c_get_clientdata(client); |
@@ -656,7 +625,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
656 | msp_set_scart(client, scart, 0); | 625 | msp_set_scart(client, scart, 0); |
657 | msp_write_dsp(client, 0x000d, 0x1900); | 626 | msp_write_dsp(client, 0x000d, 0x1900); |
658 | if (state->opmode != OPMODE_AUTOSELECT) | 627 | if (state->opmode != OPMODE_AUTOSELECT) |
659 | msp3400c_setstereo(client, state->audmode); | 628 | msp_set_audmode(client); |
660 | } | 629 | } |
661 | msp_wake_thread(client); | 630 | msp_wake_thread(client); |
662 | break; | 631 | break; |
@@ -670,8 +639,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
670 | switch (state->opmode) { | 639 | switch (state->opmode) { |
671 | case OPMODE_MANUAL: | 640 | case OPMODE_MANUAL: |
672 | /* set msp3400 to FM radio mode */ | 641 | /* set msp3400 to FM radio mode */ |
673 | msp3400c_setmode(client, MSP_MODE_FM_RADIO); | 642 | msp3400c_set_mode(client, MSP_MODE_FM_RADIO); |
674 | msp3400c_setcarrier(client, MSP_CARRIER(10.7), | 643 | msp3400c_set_carrier(client, MSP_CARRIER(10.7), |
675 | MSP_CARRIER(10.7)); | 644 | MSP_CARRIER(10.7)); |
676 | msp_set_audio(client); | 645 | msp_set_audio(client); |
677 | break; | 646 | break; |
@@ -705,7 +674,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
705 | if (state->radio) | 674 | if (state->radio) |
706 | break; | 675 | break; |
707 | if (state->opmode == OPMODE_AUTOSELECT) | 676 | if (state->opmode == OPMODE_AUTOSELECT) |
708 | msp_any_detect_stereo(client); | 677 | msp_detect_stereo(client); |
709 | va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans); | 678 | va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans); |
710 | break; | 679 | break; |
711 | } | 680 | } |
@@ -721,8 +690,9 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
721 | state->treble = va->treble; | 690 | state->treble = va->treble; |
722 | msp_set_audio(client); | 691 | msp_set_audio(client); |
723 | 692 | ||
724 | if (va->mode != 0 && state->radio == 0) | 693 | if (va->mode != 0 && state->radio == 0) { |
725 | msp_any_set_audmode(client, msp_mode_v4l1_to_v4l2(va->mode)); | 694 | state->audmode = msp_mode_v4l1_to_v4l2(va->mode); |
695 | } | ||
726 | break; | 696 | break; |
727 | } | 697 | } |
728 | 698 | ||
@@ -864,7 +834,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
864 | msp_set_scart(client, scart, 0); | 834 | msp_set_scart(client, scart, 0); |
865 | msp_write_dsp(client, 0x000d, 0x1900); | 835 | msp_write_dsp(client, 0x000d, 0x1900); |
866 | } | 836 | } |
867 | msp_any_set_audmode(client, state->audmode); | 837 | msp_set_audmode(client); |
868 | msp_wake_thread(client); | 838 | msp_wake_thread(client); |
869 | break; | 839 | break; |
870 | } | 840 | } |
@@ -876,7 +846,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
876 | if (state->radio) | 846 | if (state->radio) |
877 | break; | 847 | break; |
878 | if (state->opmode == OPMODE_AUTOSELECT) | 848 | if (state->opmode == OPMODE_AUTOSELECT) |
879 | msp_any_detect_stereo(client); | 849 | msp_detect_stereo(client); |
880 | vt->audmode = state->audmode; | 850 | vt->audmode = state->audmode; |
881 | vt->rxsubchans = state->rxsubchans; | 851 | vt->rxsubchans = state->rxsubchans; |
882 | vt->capability = V4L2_TUNER_CAP_STEREO | | 852 | vt->capability = V4L2_TUNER_CAP_STEREO | |
@@ -890,8 +860,9 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
890 | 860 | ||
891 | if (state->radio) /* TODO: add mono/stereo support for radio */ | 861 | if (state->radio) /* TODO: add mono/stereo support for radio */ |
892 | break; | 862 | break; |
863 | state->audmode = vt->audmode; | ||
893 | /* only set audmode */ | 864 | /* only set audmode */ |
894 | msp_any_set_audmode(client, vt->audmode); | 865 | msp_set_audmode(client); |
895 | break; | 866 | break; |
896 | } | 867 | } |
897 | 868 | ||
@@ -981,7 +952,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
981 | const char *p; | 952 | const char *p; |
982 | 953 | ||
983 | if (state->opmode == OPMODE_AUTOSELECT) | 954 | if (state->opmode == OPMODE_AUTOSELECT) |
984 | msp_any_detect_stereo(client); | 955 | msp_detect_stereo(client); |
985 | v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n", | 956 | v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n", |
986 | client->name, state->rev1, state->rev2); | 957 | client->name, state->rev1, state->rev2); |
987 | v4l_info(client, "Audio: volume %d%s\n", | 958 | v4l_info(client, "Audio: volume %d%s\n", |
@@ -1082,7 +1053,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) | |||
1082 | 1053 | ||
1083 | memset(state, 0, sizeof(*state)); | 1054 | memset(state, 0, sizeof(*state)); |
1084 | state->v4l2_std = V4L2_STD_NTSC; | 1055 | state->v4l2_std = V4L2_STD_NTSC; |
1085 | state->audmode = V4L2_TUNER_MODE_STEREO; | 1056 | state->audmode = V4L2_TUNER_MODE_LANG1; |
1086 | state->volume = 58880; /* 0db gain */ | 1057 | state->volume = 58880; /* 0db gain */ |
1087 | state->balance = 32768; /* 0db gain */ | 1058 | state->balance = 32768; /* 0db gain */ |
1088 | state->bass = 32768; | 1059 | state->bass = 32768; |
diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c index 3235a15db59f..c4668f4b6e5c 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/video/msp3400-kthreads.c | |||
@@ -109,7 +109,7 @@ static struct msp3400c_init_data_dem { | |||
109 | {-2, -8, -10, 10, 50, 86}, | 109 | {-2, -8, -10, 10, 50, 86}, |
110 | {-4, -12, -9, 23, 79, 126}, | 110 | {-4, -12, -9, 23, 79, 126}, |
111 | MSP_CARRIER(6.5), MSP_CARRIER(6.5), | 111 | MSP_CARRIER(6.5), MSP_CARRIER(6.5), |
112 | 0x00c6, 0x0140, 0x0120, 0x7c03 | 112 | 0x00c6, 0x0140, 0x0120, 0x7c00 |
113 | }, | 113 | }, |
114 | }; | 114 | }; |
115 | 115 | ||
@@ -154,53 +154,60 @@ const char *msp_standard_std_name(int std) | |||
154 | return "unknown"; | 154 | return "unknown"; |
155 | } | 155 | } |
156 | 156 | ||
157 | void msp3400c_setcarrier(struct i2c_client *client, int cdo1, int cdo2) | 157 | void msp_set_source(struct i2c_client *client, u16 src) |
158 | { | ||
159 | struct msp_state *state = i2c_get_clientdata(client); | ||
160 | |||
161 | if (msp_dolby) { | ||
162 | msp_write_dsp(client, 0x0008, 0x0520); /* I2S1 */ | ||
163 | msp_write_dsp(client, 0x0009, 0x0620); /* I2S2 */ | ||
164 | } else { | ||
165 | msp_write_dsp(client, 0x0008, src); | ||
166 | msp_write_dsp(client, 0x0009, src); | ||
167 | } | ||
168 | msp_write_dsp(client, 0x000a, src); | ||
169 | msp_write_dsp(client, 0x000b, src); | ||
170 | msp_write_dsp(client, 0x000c, src); | ||
171 | if (state->has_scart23_in_scart2_out) | ||
172 | msp_write_dsp(client, 0x0041, src); | ||
173 | } | ||
174 | |||
175 | void msp3400c_set_carrier(struct i2c_client *client, int cdo1, int cdo2) | ||
158 | { | 176 | { |
159 | msp_write_dem(client, 0x0093, cdo1 & 0xfff); | 177 | msp_write_dem(client, 0x0093, cdo1 & 0xfff); |
160 | msp_write_dem(client, 0x009b, cdo1 >> 12); | 178 | msp_write_dem(client, 0x009b, cdo1 >> 12); |
161 | msp_write_dem(client, 0x00a3, cdo2 & 0xfff); | 179 | msp_write_dem(client, 0x00a3, cdo2 & 0xfff); |
162 | msp_write_dem(client, 0x00ab, cdo2 >> 12); | 180 | msp_write_dem(client, 0x00ab, cdo2 >> 12); |
163 | msp_write_dem(client, 0x0056, 0); /*LOAD_REG_1/2*/ | 181 | msp_write_dem(client, 0x0056, 0); /* LOAD_REG_1/2 */ |
164 | } | 182 | } |
165 | 183 | ||
166 | void msp3400c_setmode(struct i2c_client *client, int type) | 184 | void msp3400c_set_mode(struct i2c_client *client, int mode) |
167 | { | 185 | { |
168 | struct msp_state *state = i2c_get_clientdata(client); | 186 | struct msp_state *state = i2c_get_clientdata(client); |
187 | struct msp3400c_init_data_dem *data = &msp3400c_init_data[mode]; | ||
169 | int i; | 188 | int i; |
170 | 189 | ||
171 | v4l_dbg(1, msp_debug, client, "setmode: %d\n", type); | 190 | v4l_dbg(1, msp_debug, client, "set_mode: %d\n", mode); |
172 | state->mode = type; | 191 | state->mode = mode; |
173 | state->rxsubchans = V4L2_TUNER_SUB_MONO; | 192 | state->rxsubchans = V4L2_TUNER_SUB_MONO; |
174 | 193 | ||
175 | msp_write_dem(client, 0x00bb, msp3400c_init_data[type].ad_cv); | 194 | msp_write_dem(client, 0x00bb, data->ad_cv); |
176 | 195 | ||
177 | for (i = 5; i >= 0; i--) /* fir 1 */ | 196 | for (i = 5; i >= 0; i--) /* fir 1 */ |
178 | msp_write_dem(client, 0x0001, msp3400c_init_data[type].fir1[i]); | 197 | msp_write_dem(client, 0x0001, data->fir1[i]); |
179 | 198 | ||
180 | msp_write_dem(client, 0x0005, 0x0004); /* fir 2 */ | 199 | msp_write_dem(client, 0x0005, 0x0004); /* fir 2 */ |
181 | msp_write_dem(client, 0x0005, 0x0040); | 200 | msp_write_dem(client, 0x0005, 0x0040); |
182 | msp_write_dem(client, 0x0005, 0x0000); | 201 | msp_write_dem(client, 0x0005, 0x0000); |
183 | for (i = 5; i >= 0; i--) | 202 | for (i = 5; i >= 0; i--) |
184 | msp_write_dem(client, 0x0005, msp3400c_init_data[type].fir2[i]); | 203 | msp_write_dem(client, 0x0005, data->fir2[i]); |
185 | 204 | ||
186 | msp_write_dem(client, 0x0083, msp3400c_init_data[type].mode_reg); | 205 | msp_write_dem(client, 0x0083, data->mode_reg); |
187 | 206 | ||
188 | msp3400c_setcarrier(client, msp3400c_init_data[type].cdo1, | 207 | msp3400c_set_carrier(client, data->cdo1, data->cdo2); |
189 | msp3400c_init_data[type].cdo2); | ||
190 | 208 | ||
191 | msp_write_dem(client, 0x0056, 0); /*LOAD_REG_1/2*/ | 209 | msp_set_source(client, data->dsp_src); |
192 | 210 | msp_write_dsp(client, 0x000e, data->dsp_matrix); | |
193 | if (msp_dolby) { | ||
194 | msp_write_dsp(client, 0x0008, 0x0520); /* I2S1 */ | ||
195 | msp_write_dsp(client, 0x0009, 0x0620); /* I2S2 */ | ||
196 | msp_write_dsp(client, 0x000b, msp3400c_init_data[type].dsp_src); | ||
197 | } else { | ||
198 | msp_write_dsp(client, 0x0008, msp3400c_init_data[type].dsp_src); | ||
199 | msp_write_dsp(client, 0x0009, msp3400c_init_data[type].dsp_src); | ||
200 | msp_write_dsp(client, 0x000b, msp3400c_init_data[type].dsp_src); | ||
201 | } | ||
202 | msp_write_dsp(client, 0x000a, msp3400c_init_data[type].dsp_src); | ||
203 | msp_write_dsp(client, 0x000e, msp3400c_init_data[type].dsp_matrix); | ||
204 | 211 | ||
205 | if (state->has_nicam) { | 212 | if (state->has_nicam) { |
206 | /* nicam prescale */ | 213 | /* nicam prescale */ |
@@ -208,29 +215,31 @@ void msp3400c_setmode(struct i2c_client *client, int type) | |||
208 | } | 215 | } |
209 | } | 216 | } |
210 | 217 | ||
211 | /* turn on/off nicam + stereo */ | 218 | /* Set audio mode. Note that the pre-'G' models do not support BTSC+SAP, |
212 | void msp3400c_setstereo(struct i2c_client *client, int audmode) | 219 | nor do they support stereo BTSC. */ |
220 | void msp3400c_set_audmode(struct i2c_client *client) | ||
213 | { | 221 | { |
214 | static char *strmode[] = { "mono", "stereo", "lang2", "lang1" }; | 222 | static char *strmode[] = { "mono", "stereo", "lang2", "lang1" }; |
215 | struct msp_state *state = i2c_get_clientdata(client); | 223 | struct msp_state *state = i2c_get_clientdata(client); |
216 | int nicam = 0; /* channel source: FM/AM or nicam */ | 224 | char *modestr = (state->audmode >= 0 && state->audmode < 4) ? |
217 | int src = 0; | 225 | strmode[state->audmode] : "unknown"; |
226 | int src = 0; /* channel source: FM/AM, nicam or SCART */ | ||
218 | 227 | ||
219 | if (state->opmode == OPMODE_AUTOSELECT) { | 228 | if (state->opmode == OPMODE_AUTOSELECT) { |
220 | /* this method would break everything, let's make sure | 229 | /* this method would break everything, let's make sure |
221 | * it's never called | 230 | * it's never called |
222 | */ | 231 | */ |
223 | v4l_dbg(1, msp_debug, client, "setstereo called with mode=%d instead of set_source (ignored)\n", | 232 | v4l_dbg(1, msp_debug, client, |
224 | audmode); | 233 | "set_audmode called with mode=%d instead of set_source (ignored)\n", |
234 | state->audmode); | ||
225 | return; | 235 | return; |
226 | } | 236 | } |
227 | 237 | ||
228 | /* switch demodulator */ | 238 | /* switch demodulator */ |
229 | switch (state->mode) { | 239 | switch (state->mode) { |
230 | case MSP_MODE_FM_TERRA: | 240 | case MSP_MODE_FM_TERRA: |
231 | v4l_dbg(1, msp_debug, client, "FM setstereo: %s\n", strmode[audmode]); | 241 | v4l_dbg(1, msp_debug, client, "FM set_audmode: %s\n", modestr); |
232 | msp3400c_setcarrier(client, state->second, state->main); | 242 | switch (state->audmode) { |
233 | switch (audmode) { | ||
234 | case V4L2_TUNER_MODE_STEREO: | 243 | case V4L2_TUNER_MODE_STEREO: |
235 | msp_write_dsp(client, 0x000e, 0x3001); | 244 | msp_write_dsp(client, 0x000e, 0x3001); |
236 | break; | 245 | break; |
@@ -242,50 +251,49 @@ void msp3400c_setstereo(struct i2c_client *client, int audmode) | |||
242 | } | 251 | } |
243 | break; | 252 | break; |
244 | case MSP_MODE_FM_SAT: | 253 | case MSP_MODE_FM_SAT: |
245 | v4l_dbg(1, msp_debug, client, "SAT setstereo: %s\n", strmode[audmode]); | 254 | v4l_dbg(1, msp_debug, client, "SAT set_audmode: %s\n", modestr); |
246 | switch (audmode) { | 255 | switch (state->audmode) { |
247 | case V4L2_TUNER_MODE_MONO: | 256 | case V4L2_TUNER_MODE_MONO: |
248 | msp3400c_setcarrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5)); | 257 | msp3400c_set_carrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5)); |
249 | break; | 258 | break; |
250 | case V4L2_TUNER_MODE_STEREO: | 259 | case V4L2_TUNER_MODE_STEREO: |
251 | msp3400c_setcarrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02)); | 260 | msp3400c_set_carrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02)); |
252 | break; | 261 | break; |
253 | case V4L2_TUNER_MODE_LANG1: | 262 | case V4L2_TUNER_MODE_LANG1: |
254 | msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); | 263 | msp3400c_set_carrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); |
255 | break; | 264 | break; |
256 | case V4L2_TUNER_MODE_LANG2: | 265 | case V4L2_TUNER_MODE_LANG2: |
257 | msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); | 266 | msp3400c_set_carrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); |
258 | break; | 267 | break; |
259 | } | 268 | } |
260 | break; | 269 | break; |
261 | case MSP_MODE_FM_NICAM1: | 270 | case MSP_MODE_FM_NICAM1: |
262 | case MSP_MODE_FM_NICAM2: | 271 | case MSP_MODE_FM_NICAM2: |
263 | case MSP_MODE_AM_NICAM: | 272 | case MSP_MODE_AM_NICAM: |
264 | v4l_dbg(1, msp_debug, client, "NICAM setstereo: %s\n",strmode[audmode]); | 273 | v4l_dbg(1, msp_debug, client, "NICAM set_audmode: %s\n",modestr); |
265 | msp3400c_setcarrier(client,state->second,state->main); | 274 | msp3400c_set_carrier(client, state->second, state->main); |
266 | if (state->nicam_on) | 275 | if (state->nicam_on) |
267 | nicam=0x0100; | 276 | src = 0x0100; /* NICAM */ |
268 | break; | 277 | break; |
269 | case MSP_MODE_BTSC: | 278 | case MSP_MODE_BTSC: |
270 | v4l_dbg(1, msp_debug, client, "BTSC setstereo: %s\n",strmode[audmode]); | 279 | v4l_dbg(1, msp_debug, client, "BTSC set_audmode: %s\n",modestr); |
271 | nicam=0x0300; | ||
272 | break; | 280 | break; |
273 | case MSP_MODE_EXTERN: | 281 | case MSP_MODE_EXTERN: |
274 | v4l_dbg(1, msp_debug, client, "extern setstereo: %s\n",strmode[audmode]); | 282 | v4l_dbg(1, msp_debug, client, "extern set_audmode: %s\n",modestr); |
275 | nicam = 0x0200; | 283 | src = 0x0200; /* SCART */ |
276 | break; | 284 | break; |
277 | case MSP_MODE_FM_RADIO: | 285 | case MSP_MODE_FM_RADIO: |
278 | v4l_dbg(1, msp_debug, client, "FM-Radio setstereo: %s\n",strmode[audmode]); | 286 | v4l_dbg(1, msp_debug, client, "FM-Radio set_audmode: %s\n",modestr); |
279 | break; | 287 | break; |
280 | default: | 288 | default: |
281 | v4l_dbg(1, msp_debug, client, "mono setstereo\n"); | 289 | v4l_dbg(1, msp_debug, client, "mono set_audmode\n"); |
282 | return; | 290 | return; |
283 | } | 291 | } |
284 | 292 | ||
285 | /* switch audio */ | 293 | /* switch audio */ |
286 | switch (audmode) { | 294 | switch (state->audmode) { |
287 | case V4L2_TUNER_MODE_STEREO: | 295 | case V4L2_TUNER_MODE_STEREO: |
288 | src = 0x0020 | nicam; | 296 | src |= 0x0020; |
289 | break; | 297 | break; |
290 | case V4L2_TUNER_MODE_MONO: | 298 | case V4L2_TUNER_MODE_MONO: |
291 | if (state->mode == MSP_MODE_AM_NICAM) { | 299 | if (state->mode == MSP_MODE_AM_NICAM) { |
@@ -296,29 +304,22 @@ void msp3400c_setstereo(struct i2c_client *client, int audmode) | |||
296 | src = 0x0200; | 304 | src = 0x0200; |
297 | break; | 305 | break; |
298 | } | 306 | } |
307 | if (state->rxsubchans & V4L2_TUNER_SUB_STEREO) | ||
308 | src = 0x0030; | ||
309 | break; | ||
299 | case V4L2_TUNER_MODE_LANG1: | 310 | case V4L2_TUNER_MODE_LANG1: |
300 | src = 0x0000 | nicam; | 311 | /* switch to stereo for stereo transmission, otherwise |
312 | keep first language */ | ||
313 | if (state->rxsubchans & V4L2_TUNER_SUB_STEREO) | ||
314 | src |= 0x0020; | ||
301 | break; | 315 | break; |
302 | case V4L2_TUNER_MODE_LANG2: | 316 | case V4L2_TUNER_MODE_LANG2: |
303 | src = 0x0010 | nicam; | 317 | src |= 0x0010; |
304 | break; | 318 | break; |
305 | } | 319 | } |
306 | v4l_dbg(1, msp_debug, client, "setstereo final source/matrix = 0x%x\n", src); | 320 | v4l_dbg(1, msp_debug, client, "set_audmode final source/matrix = 0x%x\n", src); |
307 | 321 | ||
308 | if (msp_dolby) { | 322 | msp_set_source(client, src); |
309 | msp_write_dsp(client, 0x0008, 0x0520); | ||
310 | msp_write_dsp(client, 0x0009, 0x0620); | ||
311 | msp_write_dsp(client, 0x000a, src); | ||
312 | msp_write_dsp(client, 0x000b, src); | ||
313 | } else { | ||
314 | msp_write_dsp(client, 0x0008, src); | ||
315 | msp_write_dsp(client, 0x0009, src); | ||
316 | msp_write_dsp(client, 0x000a, src); | ||
317 | msp_write_dsp(client, 0x000b, src); | ||
318 | msp_write_dsp(client, 0x000c, src); | ||
319 | if (state->has_scart23_in_scart2_out) | ||
320 | msp_write_dsp(client, 0x0041, src); | ||
321 | } | ||
322 | } | 323 | } |
323 | 324 | ||
324 | static void msp3400c_print_mode(struct i2c_client *client) | 325 | static void msp3400c_print_mode(struct i2c_client *client) |
@@ -346,12 +347,12 @@ static void msp3400c_print_mode(struct i2c_client *client) | |||
346 | 347 | ||
347 | /* ----------------------------------------------------------------------- */ | 348 | /* ----------------------------------------------------------------------- */ |
348 | 349 | ||
349 | int autodetect_stereo(struct i2c_client *client) | 350 | static int msp3400c_detect_stereo(struct i2c_client *client) |
350 | { | 351 | { |
351 | struct msp_state *state = i2c_get_clientdata(client); | 352 | struct msp_state *state = i2c_get_clientdata(client); |
352 | int val; | 353 | int val; |
353 | int rxsubchans = state->rxsubchans; | 354 | int rxsubchans = state->rxsubchans; |
354 | int newnicam = state->nicam_on; | 355 | int newnicam = state->nicam_on; |
355 | int update = 0; | 356 | int update = 0; |
356 | 357 | ||
357 | switch (state->mode) { | 358 | switch (state->mode) { |
@@ -361,7 +362,7 @@ int autodetect_stereo(struct i2c_client *client) | |||
361 | val -= 65536; | 362 | val -= 65536; |
362 | v4l_dbg(2, msp_debug, client, "stereo detect register: %d\n", val); | 363 | v4l_dbg(2, msp_debug, client, "stereo detect register: %d\n", val); |
363 | if (val > 4096) { | 364 | if (val > 4096) { |
364 | rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; | 365 | rxsubchans = V4L2_TUNER_SUB_STEREO; |
365 | } else if (val < -4096) { | 366 | } else if (val < -4096) { |
366 | rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; | 367 | rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; |
367 | } else { | 368 | } else { |
@@ -385,14 +386,11 @@ int autodetect_stereo(struct i2c_client *client) | |||
385 | break; | 386 | break; |
386 | case 1: | 387 | case 1: |
387 | case 9: | 388 | case 9: |
388 | rxsubchans = V4L2_TUNER_SUB_MONO | 389 | rxsubchans = V4L2_TUNER_SUB_MONO; |
389 | | V4L2_TUNER_SUB_LANG1; | ||
390 | break; | 390 | break; |
391 | case 2: | 391 | case 2: |
392 | case 10: | 392 | case 10: |
393 | rxsubchans = V4L2_TUNER_SUB_MONO | 393 | rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; |
394 | | V4L2_TUNER_SUB_LANG1 | ||
395 | | V4L2_TUNER_SUB_LANG2; | ||
396 | break; | 394 | break; |
397 | default: | 395 | default: |
398 | rxsubchans = V4L2_TUNER_SUB_MONO; | 396 | rxsubchans = V4L2_TUNER_SUB_MONO; |
@@ -404,30 +402,17 @@ int autodetect_stereo(struct i2c_client *client) | |||
404 | rxsubchans = V4L2_TUNER_SUB_MONO; | 402 | rxsubchans = V4L2_TUNER_SUB_MONO; |
405 | } | 403 | } |
406 | break; | 404 | break; |
407 | case MSP_MODE_BTSC: | ||
408 | val = msp_read_dem(client, 0x200); | ||
409 | v4l_dbg(2, msp_debug, client, "status=0x%x (pri=%s, sec=%s, %s%s%s)\n", | ||
410 | val, | ||
411 | (val & 0x0002) ? "no" : "yes", | ||
412 | (val & 0x0004) ? "no" : "yes", | ||
413 | (val & 0x0040) ? "stereo" : "mono", | ||
414 | (val & 0x0080) ? ", nicam 2nd mono" : "", | ||
415 | (val & 0x0100) ? ", bilingual/SAP" : ""); | ||
416 | rxsubchans = V4L2_TUNER_SUB_MONO; | ||
417 | if (val & 0x0040) rxsubchans |= V4L2_TUNER_SUB_STEREO; | ||
418 | if (val & 0x0100) rxsubchans |= V4L2_TUNER_SUB_LANG1; | ||
419 | break; | ||
420 | } | 405 | } |
421 | if (rxsubchans != state->rxsubchans) { | 406 | if (rxsubchans != state->rxsubchans) { |
422 | update = 1; | 407 | update = 1; |
423 | v4l_dbg(1, msp_debug, client, "watch: rxsubchans %d => %d\n", | 408 | v4l_dbg(1, msp_debug, client, "watch: rxsubchans %02x => %02x\n", |
424 | state->rxsubchans,rxsubchans); | 409 | state->rxsubchans, rxsubchans); |
425 | state->rxsubchans = rxsubchans; | 410 | state->rxsubchans = rxsubchans; |
426 | } | 411 | } |
427 | if (newnicam != state->nicam_on) { | 412 | if (newnicam != state->nicam_on) { |
428 | update = 1; | 413 | update = 1; |
429 | v4l_dbg(1, msp_debug, client, "watch: nicam %d => %d\n", | 414 | v4l_dbg(1, msp_debug, client, "watch: nicam %d => %d\n", |
430 | state->nicam_on,newnicam); | 415 | state->nicam_on, newnicam); |
431 | state->nicam_on = newnicam; | 416 | state->nicam_on = newnicam; |
432 | } | 417 | } |
433 | return update; | 418 | return update; |
@@ -442,13 +427,8 @@ static void watch_stereo(struct i2c_client *client) | |||
442 | { | 427 | { |
443 | struct msp_state *state = i2c_get_clientdata(client); | 428 | struct msp_state *state = i2c_get_clientdata(client); |
444 | 429 | ||
445 | if (autodetect_stereo(client)) { | 430 | if (msp3400c_detect_stereo(client)) { |
446 | if (state->rxsubchans & V4L2_TUNER_SUB_STEREO) | 431 | msp3400c_set_audmode(client); |
447 | msp3400c_setstereo(client, V4L2_TUNER_MODE_STEREO); | ||
448 | else if (state->rxsubchans & V4L2_TUNER_SUB_LANG1) | ||
449 | msp3400c_setstereo(client, V4L2_TUNER_MODE_LANG1); | ||
450 | else | ||
451 | msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); | ||
452 | } | 432 | } |
453 | 433 | ||
454 | if (msp_once) | 434 | if (msp_once) |
@@ -460,7 +440,7 @@ int msp3400c_thread(void *data) | |||
460 | struct i2c_client *client = data; | 440 | struct i2c_client *client = data; |
461 | struct msp_state *state = i2c_get_clientdata(client); | 441 | struct msp_state *state = i2c_get_clientdata(client); |
462 | struct msp3400c_carrier_detect *cd; | 442 | struct msp3400c_carrier_detect *cd; |
463 | int count, max1,max2,val1,val2, val,this; | 443 | int count, max1, max2, val1, val2, val, this; |
464 | 444 | ||
465 | 445 | ||
466 | v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n"); | 446 | v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n"); |
@@ -470,7 +450,7 @@ int msp3400c_thread(void *data) | |||
470 | v4l_dbg(2, msp_debug, client, "msp3400 thread: wakeup\n"); | 450 | v4l_dbg(2, msp_debug, client, "msp3400 thread: wakeup\n"); |
471 | 451 | ||
472 | restart: | 452 | restart: |
473 | v4l_dbg(1, msp_debug, client, "thread: restart scan\n"); | 453 | v4l_dbg(2, msp_debug, client, "thread: restart scan\n"); |
474 | state->restart = 0; | 454 | state->restart = 0; |
475 | if (kthread_should_stop()) | 455 | if (kthread_should_stop()) |
476 | break; | 456 | break; |
@@ -484,13 +464,14 @@ int msp3400c_thread(void *data) | |||
484 | 464 | ||
485 | /* mute */ | 465 | /* mute */ |
486 | msp_set_mute(client); | 466 | msp_set_mute(client); |
487 | msp3400c_setmode(client, MSP_MODE_AM_DETECT /* +1 */ ); | 467 | msp3400c_set_mode(client, MSP_MODE_AM_DETECT /* +1 */ ); |
488 | val1 = val2 = 0; | 468 | val1 = val2 = 0; |
489 | max1 = max2 = -1; | 469 | max1 = max2 = -1; |
490 | state->watch_stereo = 0; | 470 | state->watch_stereo = 0; |
471 | state->nicam_on = 0; | ||
491 | 472 | ||
492 | /* some time for the tuner to sync */ | 473 | /* some time for the tuner to sync */ |
493 | if (msp_sleep(state,200)) | 474 | if (msp_sleep(state, 200)) |
494 | goto restart; | 475 | goto restart; |
495 | 476 | ||
496 | /* carrier detect pass #1 -- main carrier */ | 477 | /* carrier detect pass #1 -- main carrier */ |
@@ -505,7 +486,7 @@ int msp3400c_thread(void *data) | |||
505 | } | 486 | } |
506 | 487 | ||
507 | for (this = 0; this < count; this++) { | 488 | for (this = 0; this < count; this++) { |
508 | msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo); | 489 | msp3400c_set_carrier(client, cd[this].cdo, cd[this].cdo); |
509 | if (msp_sleep(state,100)) | 490 | if (msp_sleep(state,100)) |
510 | goto restart; | 491 | goto restart; |
511 | val = msp_read_dsp(client, 0x1b); | 492 | val = msp_read_dsp(client, 0x1b); |
@@ -541,7 +522,7 @@ int msp3400c_thread(void *data) | |||
541 | max2 = 0; | 522 | max2 = 0; |
542 | } | 523 | } |
543 | for (this = 0; this < count; this++) { | 524 | for (this = 0; this < count; this++) { |
544 | msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo); | 525 | msp3400c_set_carrier(client, cd[this].cdo, cd[this].cdo); |
545 | if (msp_sleep(state,100)) | 526 | if (msp_sleep(state,100)) |
546 | goto restart; | 527 | goto restart; |
547 | val = msp_read_dsp(client, 0x1b); | 528 | val = msp_read_dsp(client, 0x1b); |
@@ -553,22 +534,20 @@ int msp3400c_thread(void *data) | |||
553 | } | 534 | } |
554 | 535 | ||
555 | /* program the msp3400 according to the results */ | 536 | /* program the msp3400 according to the results */ |
556 | state->main = msp3400c_carrier_detect_main[max1].cdo; | 537 | state->main = msp3400c_carrier_detect_main[max1].cdo; |
557 | switch (max1) { | 538 | switch (max1) { |
558 | case 1: /* 5.5 */ | 539 | case 1: /* 5.5 */ |
559 | if (max2 == 0) { | 540 | if (max2 == 0) { |
560 | /* B/G FM-stereo */ | 541 | /* B/G FM-stereo */ |
561 | state->second = msp3400c_carrier_detect_55[max2].cdo; | 542 | state->second = msp3400c_carrier_detect_55[max2].cdo; |
562 | msp3400c_setmode(client, MSP_MODE_FM_TERRA); | 543 | msp3400c_set_mode(client, MSP_MODE_FM_TERRA); |
563 | state->nicam_on = 0; | ||
564 | msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); | ||
565 | state->watch_stereo = 1; | 544 | state->watch_stereo = 1; |
566 | } else if (max2 == 1 && state->has_nicam) { | 545 | } else if (max2 == 1 && state->has_nicam) { |
567 | /* B/G NICAM */ | 546 | /* B/G NICAM */ |
568 | state->second = msp3400c_carrier_detect_55[max2].cdo; | 547 | state->second = msp3400c_carrier_detect_55[max2].cdo; |
569 | msp3400c_setmode(client, MSP_MODE_FM_NICAM1); | 548 | msp3400c_set_mode(client, MSP_MODE_FM_NICAM1); |
549 | msp3400c_set_carrier(client, state->second, state->main); | ||
570 | state->nicam_on = 1; | 550 | state->nicam_on = 1; |
571 | msp3400c_setcarrier(client, state->second, state->main); | ||
572 | state->watch_stereo = 1; | 551 | state->watch_stereo = 1; |
573 | } else { | 552 | } else { |
574 | goto no_second; | 553 | goto no_second; |
@@ -577,35 +556,31 @@ int msp3400c_thread(void *data) | |||
577 | case 2: /* 6.0 */ | 556 | case 2: /* 6.0 */ |
578 | /* PAL I NICAM */ | 557 | /* PAL I NICAM */ |
579 | state->second = MSP_CARRIER(6.552); | 558 | state->second = MSP_CARRIER(6.552); |
580 | msp3400c_setmode(client, MSP_MODE_FM_NICAM2); | 559 | msp3400c_set_mode(client, MSP_MODE_FM_NICAM2); |
560 | msp3400c_set_carrier(client, state->second, state->main); | ||
581 | state->nicam_on = 1; | 561 | state->nicam_on = 1; |
582 | msp3400c_setcarrier(client, state->second, state->main); | ||
583 | state->watch_stereo = 1; | 562 | state->watch_stereo = 1; |
584 | break; | 563 | break; |
585 | case 3: /* 6.5 */ | 564 | case 3: /* 6.5 */ |
586 | if (max2 == 1 || max2 == 2) { | 565 | if (max2 == 1 || max2 == 2) { |
587 | /* D/K FM-stereo */ | 566 | /* D/K FM-stereo */ |
588 | state->second = msp3400c_carrier_detect_65[max2].cdo; | 567 | state->second = msp3400c_carrier_detect_65[max2].cdo; |
589 | msp3400c_setmode(client, MSP_MODE_FM_TERRA); | 568 | msp3400c_set_mode(client, MSP_MODE_FM_TERRA); |
590 | state->nicam_on = 0; | ||
591 | msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); | ||
592 | state->watch_stereo = 1; | 569 | state->watch_stereo = 1; |
593 | } else if (max2 == 0 && (state->v4l2_std & V4L2_STD_SECAM)) { | 570 | } else if (max2 == 0 && (state->v4l2_std & V4L2_STD_SECAM)) { |
594 | /* L NICAM or AM-mono */ | 571 | /* L NICAM or AM-mono */ |
595 | state->second = msp3400c_carrier_detect_65[max2].cdo; | 572 | state->second = msp3400c_carrier_detect_65[max2].cdo; |
596 | msp3400c_setmode(client, MSP_MODE_AM_NICAM); | 573 | msp3400c_set_mode(client, MSP_MODE_AM_NICAM); |
597 | state->nicam_on = 0; | 574 | msp3400c_set_carrier(client, state->second, state->main); |
598 | msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); | ||
599 | msp3400c_setcarrier(client, state->second, state->main); | ||
600 | /* volume prescale for SCART (AM mono input) */ | 575 | /* volume prescale for SCART (AM mono input) */ |
601 | msp_write_dsp(client, 0x000d, 0x1900); | 576 | msp_write_dsp(client, 0x000d, 0x1900); |
602 | state->watch_stereo = 1; | 577 | state->watch_stereo = 1; |
603 | } else if (max2 == 0 && state->has_nicam) { | 578 | } else if (max2 == 0 && state->has_nicam) { |
604 | /* D/K NICAM */ | 579 | /* D/K NICAM */ |
605 | state->second = msp3400c_carrier_detect_65[max2].cdo; | 580 | state->second = msp3400c_carrier_detect_65[max2].cdo; |
606 | msp3400c_setmode(client, MSP_MODE_FM_NICAM1); | 581 | msp3400c_set_mode(client, MSP_MODE_FM_NICAM1); |
582 | msp3400c_set_carrier(client, state->second, state->main); | ||
607 | state->nicam_on = 1; | 583 | state->nicam_on = 1; |
608 | msp3400c_setcarrier(client, state->second, state->main); | ||
609 | state->watch_stereo = 1; | 584 | state->watch_stereo = 1; |
610 | } else { | 585 | } else { |
611 | goto no_second; | 586 | goto no_second; |
@@ -615,23 +590,25 @@ int msp3400c_thread(void *data) | |||
615 | default: | 590 | default: |
616 | no_second: | 591 | no_second: |
617 | state->second = msp3400c_carrier_detect_main[max1].cdo; | 592 | state->second = msp3400c_carrier_detect_main[max1].cdo; |
618 | msp3400c_setmode(client, MSP_MODE_FM_TERRA); | 593 | msp3400c_set_mode(client, MSP_MODE_FM_TERRA); |
619 | state->nicam_on = 0; | 594 | msp3400c_set_carrier(client, state->second, state->main); |
620 | msp3400c_setcarrier(client, state->second, state->main); | ||
621 | state->rxsubchans = V4L2_TUNER_SUB_MONO; | 595 | state->rxsubchans = V4L2_TUNER_SUB_MONO; |
622 | msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); | ||
623 | break; | 596 | break; |
624 | } | 597 | } |
625 | 598 | ||
626 | /* unmute */ | 599 | /* unmute */ |
627 | msp_set_audio(client); | 600 | msp_set_audio(client); |
601 | msp3400c_set_audmode(client); | ||
628 | 602 | ||
629 | if (msp_debug) | 603 | if (msp_debug) |
630 | msp3400c_print_mode(client); | 604 | msp3400c_print_mode(client); |
631 | 605 | ||
632 | /* monitor tv audio mode */ | 606 | /* monitor tv audio mode, the first time don't wait |
607 | so long to get a quick stereo/bilingual result */ | ||
608 | if (msp_sleep(state, 1000)) | ||
609 | goto restart; | ||
633 | while (state->watch_stereo) { | 610 | while (state->watch_stereo) { |
634 | if (msp_sleep(state,5000)) | 611 | if (msp_sleep(state, 5000)) |
635 | goto restart; | 612 | goto restart; |
636 | watch_stereo(client); | 613 | watch_stereo(client); |
637 | } | 614 | } |
@@ -655,7 +632,7 @@ int msp3410d_thread(void *data) | |||
655 | v4l_dbg(2, msp_debug, client, "msp3410 thread: wakeup\n"); | 632 | v4l_dbg(2, msp_debug, client, "msp3410 thread: wakeup\n"); |
656 | 633 | ||
657 | restart: | 634 | restart: |
658 | v4l_dbg(1, msp_debug, client, "thread: restart scan\n"); | 635 | v4l_dbg(2, msp_debug, client, "thread: restart scan\n"); |
659 | state->restart = 0; | 636 | state->restart = 0; |
660 | if (kthread_should_stop()) | 637 | if (kthread_should_stop()) |
661 | break; | 638 | break; |
@@ -680,9 +657,10 @@ int msp3410d_thread(void *data) | |||
680 | else | 657 | else |
681 | std = (state->v4l2_std & V4L2_STD_NTSC) ? 0x20 : 1; | 658 | std = (state->v4l2_std & V4L2_STD_NTSC) ? 0x20 : 1; |
682 | state->watch_stereo = 0; | 659 | state->watch_stereo = 0; |
660 | state->nicam_on = 0; | ||
683 | 661 | ||
684 | if (msp_debug) | 662 | if (msp_debug) |
685 | v4l_dbg(1, msp_debug, client, "setting standard: %s (0x%04x)\n", | 663 | v4l_dbg(2, msp_debug, client, "setting standard: %s (0x%04x)\n", |
686 | msp_standard_std_name(std), std); | 664 | msp_standard_std_name(std), std); |
687 | 665 | ||
688 | if (std != 1) { | 666 | if (std != 1) { |
@@ -699,7 +677,7 @@ int msp3410d_thread(void *data) | |||
699 | val = msp_read_dem(client, 0x7e); | 677 | val = msp_read_dem(client, 0x7e); |
700 | if (val < 0x07ff) | 678 | if (val < 0x07ff) |
701 | break; | 679 | break; |
702 | v4l_dbg(1, msp_debug, client, "detection still in progress\n"); | 680 | v4l_dbg(2, msp_debug, client, "detection still in progress\n"); |
703 | } | 681 | } |
704 | } | 682 | } |
705 | for (i = 0; msp_stdlist[i].name != NULL; i++) | 683 | for (i = 0; msp_stdlist[i].name != NULL; i++) |
@@ -738,46 +716,34 @@ int msp3410d_thread(void *data) | |||
738 | state->rxsubchans = V4L2_TUNER_SUB_STEREO; | 716 | state->rxsubchans = V4L2_TUNER_SUB_STEREO; |
739 | state->nicam_on = 1; | 717 | state->nicam_on = 1; |
740 | state->watch_stereo = 1; | 718 | state->watch_stereo = 1; |
741 | msp3400c_setstereo(client,V4L2_TUNER_MODE_STEREO); | ||
742 | break; | 719 | break; |
743 | case 0x0009: | 720 | case 0x0009: |
744 | state->mode = MSP_MODE_AM_NICAM; | 721 | state->mode = MSP_MODE_AM_NICAM; |
745 | state->rxsubchans = V4L2_TUNER_SUB_MONO; | 722 | state->rxsubchans = V4L2_TUNER_SUB_MONO; |
746 | state->nicam_on = 1; | 723 | state->nicam_on = 1; |
747 | msp3400c_setstereo(client,V4L2_TUNER_MODE_MONO); | ||
748 | state->watch_stereo = 1; | 724 | state->watch_stereo = 1; |
749 | break; | 725 | break; |
750 | case 0x0020: /* BTSC */ | 726 | case 0x0020: /* BTSC */ |
751 | /* just turn on stereo */ | 727 | /* The pre-'G' models only have BTSC-mono */ |
752 | state->mode = MSP_MODE_BTSC; | 728 | state->mode = MSP_MODE_BTSC; |
753 | state->rxsubchans = V4L2_TUNER_SUB_STEREO; | 729 | state->rxsubchans = V4L2_TUNER_SUB_MONO; |
754 | state->nicam_on = 0; | ||
755 | state->watch_stereo = 1; | ||
756 | msp3400c_setstereo(client,V4L2_TUNER_MODE_STEREO); | ||
757 | break; | 730 | break; |
758 | case 0x0040: /* FM radio */ | 731 | case 0x0040: /* FM radio */ |
759 | state->mode = MSP_MODE_FM_RADIO; | 732 | state->mode = MSP_MODE_FM_RADIO; |
760 | state->rxsubchans = V4L2_TUNER_SUB_STEREO; | 733 | state->rxsubchans = V4L2_TUNER_SUB_STEREO; |
761 | state->nicam_on = 0; | ||
762 | state->watch_stereo = 0; | ||
763 | /* not needed in theory if we have radio, but | 734 | /* not needed in theory if we have radio, but |
764 | short programming enables carrier mute */ | 735 | short programming enables carrier mute */ |
765 | msp3400c_setmode(client, MSP_MODE_FM_RADIO); | 736 | msp3400c_set_mode(client, MSP_MODE_FM_RADIO); |
766 | msp3400c_setcarrier(client, MSP_CARRIER(10.7), | 737 | msp3400c_set_carrier(client, MSP_CARRIER(10.7), |
767 | MSP_CARRIER(10.7)); | 738 | MSP_CARRIER(10.7)); |
768 | /* scart routing */ | 739 | /* scart routing (this doesn't belong here I think) */ |
769 | msp_set_scart(client,SCART_IN2,0); | 740 | msp_set_scart(client,SCART_IN2,0); |
770 | /* msp34xx does radio decoding */ | ||
771 | msp_write_dsp(client, 0x08, 0x0020); | ||
772 | msp_write_dsp(client, 0x09, 0x0020); | ||
773 | msp_write_dsp(client, 0x0b, 0x0020); | ||
774 | break; | 741 | break; |
775 | case 0x0003: | 742 | case 0x0003: |
776 | case 0x0004: | 743 | case 0x0004: |
777 | case 0x0005: | 744 | case 0x0005: |
778 | state->mode = MSP_MODE_FM_TERRA; | 745 | state->mode = MSP_MODE_FM_TERRA; |
779 | state->rxsubchans = V4L2_TUNER_SUB_MONO; | 746 | state->rxsubchans = V4L2_TUNER_SUB_MONO; |
780 | state->nicam_on = 0; | ||
781 | state->watch_stereo = 1; | 747 | state->watch_stereo = 1; |
782 | break; | 748 | break; |
783 | } | 749 | } |
@@ -788,11 +754,16 @@ int msp3410d_thread(void *data) | |||
788 | if (state->has_i2s_conf) | 754 | if (state->has_i2s_conf) |
789 | msp_write_dem(client, 0x40, state->i2s_mode); | 755 | msp_write_dem(client, 0x40, state->i2s_mode); |
790 | 756 | ||
791 | /* monitor tv audio mode */ | 757 | msp3400c_set_audmode(client); |
758 | |||
759 | /* monitor tv audio mode, the first time don't wait | ||
760 | so long to get a quick stereo/bilingual result */ | ||
761 | if (msp_sleep(state, 1000)) | ||
762 | goto restart; | ||
792 | while (state->watch_stereo) { | 763 | while (state->watch_stereo) { |
793 | if (msp_sleep(state,5000)) | ||
794 | goto restart; | ||
795 | watch_stereo(client); | 764 | watch_stereo(client); |
765 | if (msp_sleep(state, 5000)) | ||
766 | goto restart; | ||
796 | } | 767 | } |
797 | } | 768 | } |
798 | v4l_dbg(1, msp_debug, client, "thread: exit\n"); | 769 | v4l_dbg(1, msp_debug, client, "thread: exit\n"); |
@@ -810,7 +781,7 @@ int msp3410d_thread(void *data) | |||
810 | * the value for source is the same as bit 15:8 of DSP registers 0x08, | 781 | * the value for source is the same as bit 15:8 of DSP registers 0x08, |
811 | * 0x0a and 0x0c: 0=mono, 1=stereo or A|B, 2=SCART, 3=stereo or A, 4=stereo or B | 782 | * 0x0a and 0x0c: 0=mono, 1=stereo or A|B, 2=SCART, 3=stereo or A, 4=stereo or B |
812 | * | 783 | * |
813 | * this function replaces msp3400c_setstereo | 784 | * this function replaces msp3400c_set_audmode |
814 | */ | 785 | */ |
815 | static void msp34xxg_set_source(struct i2c_client *client, int source) | 786 | static void msp34xxg_set_source(struct i2c_client *client, int source) |
816 | { | 787 | { |
@@ -823,12 +794,7 @@ static void msp34xxg_set_source(struct i2c_client *client, int source) | |||
823 | int value = (source & 0x07) << 8 | (source == 0 ? 0x30 : 0x20); | 794 | int value = (source & 0x07) << 8 | (source == 0 ? 0x30 : 0x20); |
824 | 795 | ||
825 | v4l_dbg(1, msp_debug, client, "set source to %d (0x%x)\n", source, value); | 796 | v4l_dbg(1, msp_debug, client, "set source to %d (0x%x)\n", source, value); |
826 | /* Loudspeaker Output */ | 797 | msp_set_source(client, value); |
827 | msp_write_dsp(client, 0x08, value); | ||
828 | /* SCART1 DA Output */ | ||
829 | msp_write_dsp(client, 0x0a, value); | ||
830 | /* Quasi-peak detector */ | ||
831 | msp_write_dsp(client, 0x0c, value); | ||
832 | /* | 798 | /* |
833 | * set identification threshold. Personally, I | 799 | * set identification threshold. Personally, I |
834 | * I set it to a higher value that the default | 800 | * I set it to a higher value that the default |
@@ -945,13 +911,14 @@ int msp34xxg_thread(void *data) | |||
945 | if (msp_write_dsp(client, 0x13, state->acb)) | 911 | if (msp_write_dsp(client, 0x13, state->acb)) |
946 | return -1; | 912 | return -1; |
947 | 913 | ||
948 | msp_write_dem(client, 0x40, state->i2s_mode); | 914 | if (state->has_i2s_conf) |
915 | msp_write_dem(client, 0x40, state->i2s_mode); | ||
949 | } | 916 | } |
950 | v4l_dbg(1, msp_debug, client, "thread: exit\n"); | 917 | v4l_dbg(1, msp_debug, client, "thread: exit\n"); |
951 | return 0; | 918 | return 0; |
952 | } | 919 | } |
953 | 920 | ||
954 | void msp34xxg_detect_stereo(struct i2c_client *client) | 921 | static void msp34xxg_detect_stereo(struct i2c_client *client) |
955 | { | 922 | { |
956 | struct msp_state *state = i2c_get_clientdata(client); | 923 | struct msp_state *state = i2c_get_clientdata(client); |
957 | 924 | ||
@@ -961,11 +928,11 @@ void msp34xxg_detect_stereo(struct i2c_client *client) | |||
961 | 928 | ||
962 | state->rxsubchans = 0; | 929 | state->rxsubchans = 0; |
963 | if (is_stereo) | 930 | if (is_stereo) |
964 | state->rxsubchans |= V4L2_TUNER_SUB_STEREO; | 931 | state->rxsubchans = V4L2_TUNER_SUB_STEREO; |
965 | else | 932 | else |
966 | state->rxsubchans |= V4L2_TUNER_SUB_MONO; | 933 | state->rxsubchans = V4L2_TUNER_SUB_MONO; |
967 | if (is_bilingual) { | 934 | if (is_bilingual) { |
968 | state->rxsubchans |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; | 935 | state->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; |
969 | /* I'm supposed to check whether it's SAP or not | 936 | /* I'm supposed to check whether it's SAP or not |
970 | * and set only LANG2/SAP in this case. Yet, the MSP | 937 | * and set only LANG2/SAP in this case. Yet, the MSP |
971 | * does a lot of work to hide this and handle everything | 938 | * does a lot of work to hide this and handle everything |
@@ -977,12 +944,12 @@ void msp34xxg_detect_stereo(struct i2c_client *client) | |||
977 | status, is_stereo, is_bilingual, state->rxsubchans); | 944 | status, is_stereo, is_bilingual, state->rxsubchans); |
978 | } | 945 | } |
979 | 946 | ||
980 | void msp34xxg_set_audmode(struct i2c_client *client, int audmode) | 947 | void msp34xxg_set_audmode(struct i2c_client *client) |
981 | { | 948 | { |
982 | struct msp_state *state = i2c_get_clientdata(client); | 949 | struct msp_state *state = i2c_get_clientdata(client); |
983 | int source; | 950 | int source; |
984 | 951 | ||
985 | switch (audmode) { | 952 | switch (state->audmode) { |
986 | case V4L2_TUNER_MODE_MONO: | 953 | case V4L2_TUNER_MODE_MONO: |
987 | source = 0; /* mono only */ | 954 | source = 0; /* mono only */ |
988 | break; | 955 | break; |
@@ -997,11 +964,40 @@ void msp34xxg_set_audmode(struct i2c_client *client, int audmode) | |||
997 | source = 4; /* stereo or B */ | 964 | source = 4; /* stereo or B */ |
998 | break; | 965 | break; |
999 | default: | 966 | default: |
1000 | audmode = 0; | ||
1001 | source = 1; | 967 | source = 1; |
1002 | break; | 968 | break; |
1003 | } | 969 | } |
1004 | state->audmode = audmode; | ||
1005 | msp34xxg_set_source(client, source); | 970 | msp34xxg_set_source(client, source); |
1006 | } | 971 | } |
1007 | 972 | ||
973 | void msp_set_audmode(struct i2c_client *client) | ||
974 | { | ||
975 | struct msp_state *state = i2c_get_clientdata(client); | ||
976 | |||
977 | switch (state->opmode) { | ||
978 | case OPMODE_MANUAL: | ||
979 | case OPMODE_AUTODETECT: | ||
980 | state->watch_stereo = 0; | ||
981 | msp3400c_set_audmode(client); | ||
982 | break; | ||
983 | case OPMODE_AUTOSELECT: | ||
984 | msp34xxg_set_audmode(client); | ||
985 | break; | ||
986 | } | ||
987 | } | ||
988 | |||
989 | void msp_detect_stereo(struct i2c_client *client) | ||
990 | { | ||
991 | struct msp_state *state = i2c_get_clientdata(client); | ||
992 | |||
993 | switch (state->opmode) { | ||
994 | case OPMODE_MANUAL: | ||
995 | case OPMODE_AUTODETECT: | ||
996 | msp3400c_detect_stereo(client); | ||
997 | break; | ||
998 | case OPMODE_AUTOSELECT: | ||
999 | msp34xxg_detect_stereo(client); | ||
1000 | break; | ||
1001 | } | ||
1002 | } | ||
1003 | |||
diff --git a/drivers/media/video/msp3400.h b/drivers/media/video/msp3400.h index a9ac57d0700b..418283002130 100644 --- a/drivers/media/video/msp3400.h +++ b/drivers/media/video/msp3400.h | |||
@@ -104,14 +104,13 @@ int msp_sleep(struct msp_state *state, int timeout); | |||
104 | 104 | ||
105 | /* msp3400-kthreads.c */ | 105 | /* msp3400-kthreads.c */ |
106 | const char *msp_standard_std_name(int std); | 106 | const char *msp_standard_std_name(int std); |
107 | void msp3400c_setcarrier(struct i2c_client *client, int cdo1, int cdo2); | 107 | void msp_set_source(struct i2c_client *client, u16 src); |
108 | void msp3400c_setmode(struct i2c_client *client, int type); | 108 | void msp_set_audmode(struct i2c_client *client); |
109 | void msp3400c_setstereo(struct i2c_client *client, int mode); | 109 | void msp_detect_stereo(struct i2c_client *client); |
110 | int autodetect_stereo(struct i2c_client *client); | ||
111 | int msp3400c_thread(void *data); | 110 | int msp3400c_thread(void *data); |
112 | int msp3410d_thread(void *data); | 111 | int msp3410d_thread(void *data); |
113 | int msp34xxg_thread(void *data); | 112 | int msp34xxg_thread(void *data); |
114 | void msp34xxg_detect_stereo(struct i2c_client *client); | 113 | void msp3400c_set_mode(struct i2c_client *client, int mode); |
115 | void msp34xxg_set_audmode(struct i2c_client *client, int audmode); | 114 | void msp3400c_set_carrier(struct i2c_client *client, int cdo1, int cdo2); |
116 | 115 | ||
117 | #endif /* MSP3400_H */ | 116 | #endif /* MSP3400_H */ |
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 2995b22acb43..af3e7bb13813 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
@@ -398,15 +398,16 @@ static void tuner_status(struct i2c_client *client) | |||
398 | tuner_info("Tuner mode: %s\n", p); | 398 | tuner_info("Tuner mode: %s\n", p); |
399 | tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction); | 399 | tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction); |
400 | tuner_info("Standard: 0x%08llx\n", t->std); | 400 | tuner_info("Standard: 0x%08llx\n", t->std); |
401 | if (t->mode == V4L2_TUNER_RADIO) { | 401 | if (t->mode != V4L2_TUNER_RADIO) |
402 | if (t->has_signal) { | 402 | return; |
403 | tuner_info("Signal strength: %d\n", t->has_signal(client)); | 403 | if (t->has_signal) { |
404 | } | 404 | tuner_info("Signal strength: %d\n", t->has_signal(client)); |
405 | if (t->is_stereo) { | 405 | } |
406 | tuner_info("Stereo: %s\n", t->is_stereo(client) ? "yes" : "no"); | 406 | if (t->is_stereo) { |
407 | } | 407 | tuner_info("Stereo: %s\n", t->is_stereo(client) ? "yes" : "no"); |
408 | } | 408 | } |
409 | } | 409 | } |
410 | |||
410 | /* ---------------------------------------------------------------------- */ | 411 | /* ---------------------------------------------------------------------- */ |
411 | 412 | ||
412 | /* static var Used only in tuner_attach and tuner_probe */ | 413 | /* static var Used only in tuner_attach and tuner_probe */ |
@@ -737,33 +738,29 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
737 | return 0; | 738 | return 0; |
738 | switch_v4l2(); | 739 | switch_v4l2(); |
739 | 740 | ||
740 | if (V4L2_TUNER_RADIO == t->mode) { | 741 | tuner->type = t->mode; |
741 | 742 | if (t->mode != V4L2_TUNER_RADIO) { | |
742 | if (t->has_signal) | ||
743 | tuner->signal = t->has_signal(client); | ||
744 | |||
745 | if (t->is_stereo) { | ||
746 | if (t->is_stereo(client)) { | ||
747 | tuner->rxsubchans = | ||
748 | V4L2_TUNER_SUB_STEREO | | ||
749 | V4L2_TUNER_SUB_MONO; | ||
750 | } else { | ||
751 | tuner->rxsubchans = | ||
752 | V4L2_TUNER_SUB_MONO; | ||
753 | } | ||
754 | } | ||
755 | |||
756 | tuner->capability |= | ||
757 | V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; | ||
758 | |||
759 | tuner->audmode = t->audmode; | ||
760 | |||
761 | tuner->rangelow = radio_range[0] * 16000; | ||
762 | tuner->rangehigh = radio_range[1] * 16000; | ||
763 | } else { | ||
764 | tuner->rangelow = tv_range[0] * 16; | 743 | tuner->rangelow = tv_range[0] * 16; |
765 | tuner->rangehigh = tv_range[1] * 16; | 744 | tuner->rangehigh = tv_range[1] * 16; |
745 | break; | ||
746 | } | ||
747 | |||
748 | /* radio mode */ | ||
749 | if (t->has_signal) | ||
750 | tuner->signal = t->has_signal(client); | ||
751 | |||
752 | tuner->rxsubchans = | ||
753 | V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; | ||
754 | if (t->is_stereo) { | ||
755 | tuner->rxsubchans = t->is_stereo(client) ? | ||
756 | V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; | ||
766 | } | 757 | } |
758 | |||
759 | tuner->capability |= | ||
760 | V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; | ||
761 | tuner->audmode = t->audmode; | ||
762 | tuner->rangelow = radio_range[0] * 16000; | ||
763 | tuner->rangehigh = radio_range[1] * 16000; | ||
767 | break; | 764 | break; |
768 | } | 765 | } |
769 | case VIDIOC_S_TUNER: | 766 | case VIDIOC_S_TUNER: |
@@ -775,10 +772,11 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
775 | 772 | ||
776 | switch_v4l2(); | 773 | switch_v4l2(); |
777 | 774 | ||
778 | if (V4L2_TUNER_RADIO == t->mode) { | 775 | /* do nothing unless we're a radio tuner */ |
779 | t->audmode = tuner->audmode; | 776 | if (t->mode != V4L2_TUNER_RADIO) |
780 | set_radio_freq(client, t->radio_freq); | 777 | break; |
781 | } | 778 | t->audmode = tuner->audmode; |
779 | set_radio_freq(client, t->radio_freq); | ||
782 | break; | 780 | break; |
783 | } | 781 | } |
784 | case VIDIOC_LOG_STATUS: | 782 | case VIDIOC_LOG_STATUS: |
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index c8e5ad0e8185..4efb01bb44ac 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c | |||
@@ -130,6 +130,7 @@ struct CHIPSTATE { | |||
130 | struct timer_list wt; | 130 | struct timer_list wt; |
131 | int done; | 131 | int done; |
132 | int watch_stereo; | 132 | int watch_stereo; |
133 | int audmode; | ||
133 | }; | 134 | }; |
134 | 135 | ||
135 | /* ---------------------------------------------------------------------- */ | 136 | /* ---------------------------------------------------------------------- */ |
@@ -1514,6 +1515,7 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind) | |||
1514 | chip->type = desc-chiplist; | 1515 | chip->type = desc-chiplist; |
1515 | chip->shadow.count = desc->registers+1; | 1516 | chip->shadow.count = desc->registers+1; |
1516 | chip->prevmode = -1; | 1517 | chip->prevmode = -1; |
1518 | chip->audmode = V4L2_TUNER_MODE_LANG1; | ||
1517 | /* register */ | 1519 | /* register */ |
1518 | i2c_attach_client(&chip->c); | 1520 | i2c_attach_client(&chip->c); |
1519 | 1521 | ||
@@ -1671,6 +1673,8 @@ static int chip_command(struct i2c_client *client, | |||
1671 | struct v4l2_tuner *vt = arg; | 1673 | struct v4l2_tuner *vt = arg; |
1672 | int mode = 0; | 1674 | int mode = 0; |
1673 | 1675 | ||
1676 | if (chip->radio) | ||
1677 | break; | ||
1674 | switch (vt->audmode) { | 1678 | switch (vt->audmode) { |
1675 | case V4L2_TUNER_MODE_MONO: | 1679 | case V4L2_TUNER_MODE_MONO: |
1676 | mode = VIDEO_SOUND_MONO; | 1680 | mode = VIDEO_SOUND_MONO; |
@@ -1685,8 +1689,9 @@ static int chip_command(struct i2c_client *client, | |||
1685 | mode = VIDEO_SOUND_LANG2; | 1689 | mode = VIDEO_SOUND_LANG2; |
1686 | break; | 1690 | break; |
1687 | default: | 1691 | default: |
1688 | break; | 1692 | return -EINVAL; |
1689 | } | 1693 | } |
1694 | chip->audmode = vt->audmode; | ||
1690 | 1695 | ||
1691 | if (desc->setmode && mode) { | 1696 | if (desc->setmode && mode) { |
1692 | chip->watch_stereo = 0; | 1697 | chip->watch_stereo = 0; |
@@ -1704,7 +1709,7 @@ static int chip_command(struct i2c_client *client, | |||
1704 | 1709 | ||
1705 | if (chip->radio) | 1710 | if (chip->radio) |
1706 | break; | 1711 | break; |
1707 | vt->audmode = 0; | 1712 | vt->audmode = chip->audmode; |
1708 | vt->rxsubchans = 0; | 1713 | vt->rxsubchans = 0; |
1709 | vt->capability = V4L2_TUNER_CAP_STEREO | | 1714 | vt->capability = V4L2_TUNER_CAP_STEREO | |
1710 | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; | 1715 | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; |
@@ -1716,19 +1721,12 @@ static int chip_command(struct i2c_client *client, | |||
1716 | vt->rxsubchans |= V4L2_TUNER_SUB_MONO; | 1721 | vt->rxsubchans |= V4L2_TUNER_SUB_MONO; |
1717 | if (mode & VIDEO_SOUND_STEREO) | 1722 | if (mode & VIDEO_SOUND_STEREO) |
1718 | vt->rxsubchans |= V4L2_TUNER_SUB_STEREO; | 1723 | vt->rxsubchans |= V4L2_TUNER_SUB_STEREO; |
1724 | /* Note: for SAP it should be mono/lang2 or stereo/lang2. | ||
1725 | When this module is converted fully to v4l2, then this | ||
1726 | should change for those chips that can detect SAP. */ | ||
1719 | if (mode & VIDEO_SOUND_LANG1) | 1727 | if (mode & VIDEO_SOUND_LANG1) |
1720 | vt->rxsubchans |= V4L2_TUNER_SUB_LANG1 | | 1728 | vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | |
1721 | V4L2_TUNER_SUB_LANG2; | 1729 | V4L2_TUNER_SUB_LANG2; |
1722 | |||
1723 | mode = chip->mode; | ||
1724 | if (mode & VIDEO_SOUND_MONO) | ||
1725 | vt->audmode = V4L2_TUNER_MODE_MONO; | ||
1726 | if (mode & VIDEO_SOUND_STEREO) | ||
1727 | vt->audmode = V4L2_TUNER_MODE_STEREO; | ||
1728 | if (mode & VIDEO_SOUND_LANG1) | ||
1729 | vt->audmode = V4L2_TUNER_MODE_LANG1; | ||
1730 | if (mode & VIDEO_SOUND_LANG2) | ||
1731 | vt->audmode = V4L2_TUNER_MODE_LANG2; | ||
1732 | break; | 1730 | break; |
1733 | } | 1731 | } |
1734 | 1732 | ||