aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/msp3400-kthreads.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/msp3400-kthreads.c')
-rw-r--r--drivers/media/video/msp3400-kthreads.c111
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 */
790static 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
814static int msp34xxg_modus(struct i2c_client *client) 787static 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
819static 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
858static 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 */
847static void msp34xxg_reset(struct i2c_client *client) 874static 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)
993static void msp34xxg_set_audmode(struct i2c_client *client) 1021static 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
1029void msp_set_audmode(struct i2c_client *client) 1038void msp_set_audmode(struct i2c_client *client)