diff options
Diffstat (limited to 'drivers/media/video/msp3400-kthreads.c')
-rw-r--r-- | drivers/media/video/msp3400-kthreads.c | 111 |
1 files changed, 60 insertions, 51 deletions
diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c index 9ee8dc216d7f..1c794c3b9f21 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/video/msp3400-kthreads.c | |||
@@ -187,13 +187,14 @@ void msp3400c_set_mode(struct i2c_client *client, int mode) | |||
187 | { | 187 | { |
188 | struct msp_state *state = i2c_get_clientdata(client); | 188 | struct msp_state *state = i2c_get_clientdata(client); |
189 | struct msp3400c_init_data_dem *data = &msp3400c_init_data[mode]; | 189 | struct msp3400c_init_data_dem *data = &msp3400c_init_data[mode]; |
190 | int tuner = (state->routing.input >> 3) & 1; | ||
190 | int i; | 191 | int i; |
191 | 192 | ||
192 | v4l_dbg(1, msp_debug, client, "set_mode: %d\n", mode); | 193 | v4l_dbg(1, msp_debug, client, "set_mode: %d\n", mode); |
193 | state->mode = mode; | 194 | state->mode = mode; |
194 | state->rxsubchans = V4L2_TUNER_SUB_MONO; | 195 | state->rxsubchans = V4L2_TUNER_SUB_MONO; |
195 | 196 | ||
196 | msp_write_dem(client, 0x00bb, data->ad_cv); | 197 | msp_write_dem(client, 0x00bb, data->ad_cv | (tuner ? 0x100 : 0)); |
197 | 198 | ||
198 | for (i = 5; i >= 0; i--) /* fir 1 */ | 199 | for (i = 5; i >= 0; i--) /* fir 1 */ |
199 | msp_write_dem(client, 0x0001, data->fir1[i]); | 200 | msp_write_dem(client, 0x0001, data->fir1[i]); |
@@ -783,34 +784,6 @@ int msp3410d_thread(void *data) | |||
783 | * struct msp: only norm, acb and source are really used in this mode | 784 | * struct msp: only norm, acb and source are really used in this mode |
784 | */ | 785 | */ |
785 | 786 | ||
786 | /* set the same 'source' for the loudspeaker, scart and quasi-peak detector | ||
787 | * the value for source is the same as bit 15:8 of DSP registers 0x08, | ||
788 | * 0x0a and 0x0c: 0=mono, 1=stereo or A|B, 2=SCART, 3=stereo or A, 4=stereo or B | ||
789 | */ | ||
790 | static void msp34xxg_set_source(struct i2c_client *client, int source) | ||
791 | { | ||
792 | struct msp_state *state = i2c_get_clientdata(client); | ||
793 | |||
794 | /* fix matrix mode to stereo and let the msp choose what | ||
795 | * to output according to 'source', as recommended | ||
796 | * for MONO (source==0) downmixing set bit[7:0] to 0x30 | ||
797 | */ | ||
798 | int value = (source & 0x07) << 8 | (source == 0 ? 0x30 : 0x20); | ||
799 | |||
800 | v4l_dbg(1, msp_debug, client, "set source to %d (0x%x)\n", source, value); | ||
801 | msp_set_source(client, value); | ||
802 | /* | ||
803 | * set identification threshold. Personally, I | ||
804 | * I set it to a higher value that the default | ||
805 | * of 0x190 to ignore noisy stereo signals. | ||
806 | * this needs tuning. (recommended range 0x00a0-0x03c0) | ||
807 | * 0x7f0 = forced mono mode | ||
808 | */ | ||
809 | /* a2 threshold for stereo/bilingual */ | ||
810 | msp_write_dem(client, 0x22, msp_stereo_thresh); | ||
811 | state->source = source; | ||
812 | } | ||
813 | |||
814 | static int msp34xxg_modus(struct i2c_client *client) | 787 | static int msp34xxg_modus(struct i2c_client *client) |
815 | { | 788 | { |
816 | struct msp_state *state = i2c_get_clientdata(client); | 789 | struct msp_state *state = i2c_get_clientdata(client); |
@@ -843,10 +816,65 @@ static int msp34xxg_modus(struct i2c_client *client) | |||
843 | return 0x0001; | 816 | return 0x0001; |
844 | } | 817 | } |
845 | 818 | ||
819 | static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in) | ||
820 | { | ||
821 | struct msp_state *state = i2c_get_clientdata(client); | ||
822 | int source, matrix; | ||
823 | |||
824 | switch (state->audmode) { | ||
825 | case V4L2_TUNER_MODE_MONO: | ||
826 | source = 0; /* mono only */ | ||
827 | matrix = 0x30; | ||
828 | break; | ||
829 | case V4L2_TUNER_MODE_LANG1: | ||
830 | source = 3; /* stereo or A */ | ||
831 | matrix = 0x00; | ||
832 | break; | ||
833 | case V4L2_TUNER_MODE_LANG2: | ||
834 | source = 4; /* stereo or B */ | ||
835 | matrix = 0x10; | ||
836 | break; | ||
837 | case V4L2_TUNER_MODE_STEREO: | ||
838 | default: | ||
839 | source = 1; /* stereo or A|B */ | ||
840 | matrix = 0x20; | ||
841 | break; | ||
842 | } | ||
843 | |||
844 | if (in == MSP_DSP_OUT_TUNER) | ||
845 | source = (source << 8) | 0x20; | ||
846 | /* the msp34x2g puts the MAIN_AVC, MAIN and AUX sources in 12, 13, 14 | ||
847 | instead of 11, 12, 13. So we add one for that msp version. */ | ||
848 | else if (in >= MSP_DSP_OUT_MAIN_AVC && state->has_dolby_pro_logic) | ||
849 | source = ((in + 1) << 8) | matrix; | ||
850 | else | ||
851 | source = (in << 8) | matrix; | ||
852 | |||
853 | v4l_dbg(1, msp_debug, client, "set source to %d (0x%x) for output %02x\n", | ||
854 | in, source, reg); | ||
855 | msp_write_dsp(client, reg, source); | ||
856 | } | ||
857 | |||
858 | static void msp34xxg_set_sources(struct i2c_client *client) | ||
859 | { | ||
860 | struct msp_state *state = i2c_get_clientdata(client); | ||
861 | u32 in = state->routing.input; | ||
862 | |||
863 | msp34xxg_set_source(client, 0x0008, (in >> 4) & 0xf); | ||
864 | /* quasi-peak detector is set to same input as the loudspeaker (MAIN) */ | ||
865 | msp34xxg_set_source(client, 0x000c, (in >> 4) & 0xf); | ||
866 | msp34xxg_set_source(client, 0x0009, (in >> 8) & 0xf); | ||
867 | msp34xxg_set_source(client, 0x000a, (in >> 12) & 0xf); | ||
868 | if (state->has_scart23_in_scart2_out) | ||
869 | msp34xxg_set_source(client, 0x0041, (in >> 16) & 0xf); | ||
870 | msp34xxg_set_source(client, 0x000b, (in >> 20) & 0xf); | ||
871 | } | ||
872 | |||
846 | /* (re-)initialize the msp34xxg */ | 873 | /* (re-)initialize the msp34xxg */ |
847 | static void msp34xxg_reset(struct i2c_client *client) | 874 | static void msp34xxg_reset(struct i2c_client *client) |
848 | { | 875 | { |
849 | struct msp_state *state = i2c_get_clientdata(client); | 876 | struct msp_state *state = i2c_get_clientdata(client); |
877 | int tuner = (state->routing.input >> 3) & 1; | ||
850 | int modus; | 878 | int modus; |
851 | 879 | ||
852 | /* initialize std to 1 (autodetect) to signal that no standard is | 880 | /* initialize std to 1 (autodetect) to signal that no standard is |
@@ -864,11 +892,12 @@ static void msp34xxg_reset(struct i2c_client *client) | |||
864 | 892 | ||
865 | /* step-by-step initialisation, as described in the manual */ | 893 | /* step-by-step initialisation, as described in the manual */ |
866 | modus = msp34xxg_modus(client); | 894 | modus = msp34xxg_modus(client); |
895 | modus |= tuner ? 0x100 : 0; | ||
867 | msp_write_dem(client, 0x30, modus); | 896 | msp_write_dem(client, 0x30, modus); |
868 | 897 | ||
869 | /* write the dsps that may have an influence on | 898 | /* write the dsps that may have an influence on |
870 | standard/audio autodetection right now */ | 899 | standard/audio autodetection right now */ |
871 | msp34xxg_set_source(client, state->source); | 900 | msp34xxg_set_sources(client); |
872 | 901 | ||
873 | msp_write_dsp(client, 0x0d, 0x1900); /* scart */ | 902 | msp_write_dsp(client, 0x0d, 0x1900); /* scart */ |
874 | msp_write_dsp(client, 0x0e, 0x3000); /* FM */ | 903 | msp_write_dsp(client, 0x0e, 0x3000); /* FM */ |
@@ -896,7 +925,6 @@ int msp34xxg_thread(void *data) | |||
896 | 925 | ||
897 | v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n"); | 926 | v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n"); |
898 | 927 | ||
899 | state->source = 1; /* default */ | ||
900 | for (;;) { | 928 | for (;;) { |
901 | v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n"); | 929 | v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n"); |
902 | msp_sleep(state, -1); | 930 | msp_sleep(state, -1); |
@@ -993,7 +1021,6 @@ static int msp34xxg_detect_stereo(struct i2c_client *client) | |||
993 | static void msp34xxg_set_audmode(struct i2c_client *client) | 1021 | static void msp34xxg_set_audmode(struct i2c_client *client) |
994 | { | 1022 | { |
995 | struct msp_state *state = i2c_get_clientdata(client); | 1023 | struct msp_state *state = i2c_get_clientdata(client); |
996 | int source; | ||
997 | 1024 | ||
998 | if (state->std == 0x20) { | 1025 | if (state->std == 0x20) { |
999 | if ((state->rxsubchans & V4L2_TUNER_SUB_SAP) && | 1026 | if ((state->rxsubchans & V4L2_TUNER_SUB_SAP) && |
@@ -1005,25 +1032,7 @@ static void msp34xxg_set_audmode(struct i2c_client *client) | |||
1005 | } | 1032 | } |
1006 | } | 1033 | } |
1007 | 1034 | ||
1008 | switch (state->audmode) { | 1035 | msp34xxg_set_sources(client); |
1009 | case V4L2_TUNER_MODE_MONO: | ||
1010 | source = 0; /* mono only */ | ||
1011 | break; | ||
1012 | case V4L2_TUNER_MODE_STEREO: | ||
1013 | source = 1; /* stereo or A|B, see comment in msp34xxg_get_v4l2_stereo() */ | ||
1014 | /* problem: that could also mean 2 (scart input) */ | ||
1015 | break; | ||
1016 | case V4L2_TUNER_MODE_LANG1: | ||
1017 | source = 3; /* stereo or A */ | ||
1018 | break; | ||
1019 | case V4L2_TUNER_MODE_LANG2: | ||
1020 | source = 4; /* stereo or B */ | ||
1021 | break; | ||
1022 | default: | ||
1023 | source = 1; | ||
1024 | break; | ||
1025 | } | ||
1026 | msp34xxg_set_source(client, source); | ||
1027 | } | 1036 | } |
1028 | 1037 | ||
1029 | void msp_set_audmode(struct i2c_client *client) | 1038 | void msp_set_audmode(struct i2c_client *client) |