diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2006-03-30 17:50:34 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-04-02 03:56:06 -0400 |
commit | 0020d3ef915fc01a0184bc96eeb3c240bded5d8e (patch) | |
tree | 89685985691405ae3c407b699a1f8cefa19425ce /drivers/media | |
parent | 9bc7400a9d01b1fe05c7f0200e7384e17794f6e4 (diff) |
V4L/DVB (3693): Fix msp3400c and bttv stereo/mono/bilingual detection/handling
- msp3400c did not detect the second carrier, thus being always mono.
- properly mute the msp3400c while detecting the carrier.
- fix checks on the presence of scart2/3 inputs and scart 2 output.
- implement proper audio mode fallbacks for msp3400c/d, identical to the
way msp3400g works.
- MODE_STEREO no longer produces dual languages when set for a bilingual
transmission, instead it falls back to LANG1. Use LANG1_LANG2 to hear
both languages of a bilingual transmission. This is much more intuitive
for the user and is in accordance with the preferred usage in the v4l2
specification.
- bttv tried to implement v4l2 calls with v4l1 calls to the i2c devices,
completely mangling the audmode/rxsubchans handling. v4l2 calls now do
v4l2 calls to the i2c devices.
- fixed broken i2c_vidiocschan in bttv.
- add start/end lines to LOG_STATUS.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/bt8xx/bttv-driver.c | 147 | ||||
-rw-r--r-- | drivers/media/video/msp3400-driver.c | 54 | ||||
-rw-r--r-- | drivers/media/video/msp3400-driver.h | 5 | ||||
-rw-r--r-- | drivers/media/video/msp3400-kthreads.c | 71 |
4 files changed, 138 insertions, 139 deletions
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 74def9c23952..7913e2ec7a5b 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c | |||
@@ -1023,14 +1023,12 @@ audio_input(struct bttv *btv, int input) | |||
1023 | static void | 1023 | static void |
1024 | i2c_vidiocschan(struct bttv *btv) | 1024 | i2c_vidiocschan(struct bttv *btv) |
1025 | { | 1025 | { |
1026 | struct video_channel c; | 1026 | v4l2_std_id std = bttv_tvnorms[btv->tvnorm].v4l2_id; |
1027 | 1027 | ||
1028 | memset(&c,0,sizeof(c)); | 1028 | bttv_call_i2c_clients(btv, VIDIOC_S_INPUT, &btv->input); |
1029 | c.norm = btv->tvnorm; | 1029 | bttv_call_i2c_clients(btv, VIDIOC_S_STD, &std); |
1030 | c.channel = btv->input; | ||
1031 | bttv_call_i2c_clients(btv,VIDIOCSCHAN,&c); | ||
1032 | if (btv->c.type == BTTV_BOARD_VOODOOTV_FM) | 1030 | if (btv->c.type == BTTV_BOARD_VOODOOTV_FM) |
1033 | bttv_tda9880_setnorm(btv,c.norm); | 1031 | bttv_tda9880_setnorm(btv,btv->tvnorm); |
1034 | } | 1032 | } |
1035 | 1033 | ||
1036 | static int | 1034 | static int |
@@ -1184,11 +1182,27 @@ static int get_control(struct bttv *btv, struct v4l2_control *c) | |||
1184 | break; | 1182 | break; |
1185 | if (i == BTTV_CTLS) | 1183 | if (i == BTTV_CTLS) |
1186 | return -EINVAL; | 1184 | return -EINVAL; |
1187 | if (i >= 4 && i <= 8) { | 1185 | if (btv->audio_hook && i >= 4 && i <= 8) { |
1188 | memset(&va,0,sizeof(va)); | 1186 | memset(&va,0,sizeof(va)); |
1189 | bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); | 1187 | btv->audio_hook(btv,&va,0); |
1190 | if (btv->audio_hook) | 1188 | switch (c->id) { |
1191 | btv->audio_hook(btv,&va,0); | 1189 | case V4L2_CID_AUDIO_MUTE: |
1190 | c->value = (VIDEO_AUDIO_MUTE & va.flags) ? 1 : 0; | ||
1191 | break; | ||
1192 | case V4L2_CID_AUDIO_VOLUME: | ||
1193 | c->value = va.volume; | ||
1194 | break; | ||
1195 | case V4L2_CID_AUDIO_BALANCE: | ||
1196 | c->value = va.balance; | ||
1197 | break; | ||
1198 | case V4L2_CID_AUDIO_BASS: | ||
1199 | c->value = va.bass; | ||
1200 | break; | ||
1201 | case V4L2_CID_AUDIO_TREBLE: | ||
1202 | c->value = va.treble; | ||
1203 | break; | ||
1204 | } | ||
1205 | return 0; | ||
1192 | } | 1206 | } |
1193 | switch (c->id) { | 1207 | switch (c->id) { |
1194 | case V4L2_CID_BRIGHTNESS: | 1208 | case V4L2_CID_BRIGHTNESS: |
@@ -1205,19 +1219,11 @@ static int get_control(struct bttv *btv, struct v4l2_control *c) | |||
1205 | break; | 1219 | break; |
1206 | 1220 | ||
1207 | case V4L2_CID_AUDIO_MUTE: | 1221 | case V4L2_CID_AUDIO_MUTE: |
1208 | c->value = (VIDEO_AUDIO_MUTE & va.flags) ? 1 : 0; | ||
1209 | break; | ||
1210 | case V4L2_CID_AUDIO_VOLUME: | 1222 | case V4L2_CID_AUDIO_VOLUME: |
1211 | c->value = va.volume; | ||
1212 | break; | ||
1213 | case V4L2_CID_AUDIO_BALANCE: | 1223 | case V4L2_CID_AUDIO_BALANCE: |
1214 | c->value = va.balance; | ||
1215 | break; | ||
1216 | case V4L2_CID_AUDIO_BASS: | 1224 | case V4L2_CID_AUDIO_BASS: |
1217 | c->value = va.bass; | ||
1218 | break; | ||
1219 | case V4L2_CID_AUDIO_TREBLE: | 1225 | case V4L2_CID_AUDIO_TREBLE: |
1220 | c->value = va.treble; | 1226 | bttv_call_i2c_clients(btv,VIDIOC_G_CTRL,c); |
1221 | break; | 1227 | break; |
1222 | 1228 | ||
1223 | case V4L2_CID_PRIVATE_CHROMA_AGC: | 1229 | case V4L2_CID_PRIVATE_CHROMA_AGC: |
@@ -1269,11 +1275,35 @@ static int set_control(struct bttv *btv, struct v4l2_control *c) | |||
1269 | break; | 1275 | break; |
1270 | if (i == BTTV_CTLS) | 1276 | if (i == BTTV_CTLS) |
1271 | return -EINVAL; | 1277 | return -EINVAL; |
1272 | if (i >= 4 && i <= 8) { | 1278 | if (btv->audio_hook && i >= 4 && i <= 8) { |
1273 | memset(&va,0,sizeof(va)); | 1279 | memset(&va,0,sizeof(va)); |
1274 | bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); | 1280 | btv->audio_hook(btv,&va,0); |
1275 | if (btv->audio_hook) | 1281 | switch (c->id) { |
1276 | btv->audio_hook(btv,&va,0); | 1282 | case V4L2_CID_AUDIO_MUTE: |
1283 | if (c->value) { | ||
1284 | va.flags |= VIDEO_AUDIO_MUTE; | ||
1285 | audio_mute(btv, 1); | ||
1286 | } else { | ||
1287 | va.flags &= ~VIDEO_AUDIO_MUTE; | ||
1288 | audio_mute(btv, 0); | ||
1289 | } | ||
1290 | break; | ||
1291 | |||
1292 | case V4L2_CID_AUDIO_VOLUME: | ||
1293 | va.volume = c->value; | ||
1294 | break; | ||
1295 | case V4L2_CID_AUDIO_BALANCE: | ||
1296 | va.balance = c->value; | ||
1297 | break; | ||
1298 | case V4L2_CID_AUDIO_BASS: | ||
1299 | va.bass = c->value; | ||
1300 | break; | ||
1301 | case V4L2_CID_AUDIO_TREBLE: | ||
1302 | va.treble = c->value; | ||
1303 | break; | ||
1304 | } | ||
1305 | btv->audio_hook(btv,&va,1); | ||
1306 | return 0; | ||
1277 | } | 1307 | } |
1278 | switch (c->id) { | 1308 | switch (c->id) { |
1279 | case V4L2_CID_BRIGHTNESS: | 1309 | case V4L2_CID_BRIGHTNESS: |
@@ -1289,26 +1319,13 @@ static int set_control(struct bttv *btv, struct v4l2_control *c) | |||
1289 | bt848_sat(btv,c->value); | 1319 | bt848_sat(btv,c->value); |
1290 | break; | 1320 | break; |
1291 | case V4L2_CID_AUDIO_MUTE: | 1321 | case V4L2_CID_AUDIO_MUTE: |
1292 | if (c->value) { | 1322 | audio_mute(btv, c->value); |
1293 | va.flags |= VIDEO_AUDIO_MUTE; | 1323 | /* fall through */ |
1294 | audio_mute(btv, 1); | ||
1295 | } else { | ||
1296 | va.flags &= ~VIDEO_AUDIO_MUTE; | ||
1297 | audio_mute(btv, 0); | ||
1298 | } | ||
1299 | break; | ||
1300 | |||
1301 | case V4L2_CID_AUDIO_VOLUME: | 1324 | case V4L2_CID_AUDIO_VOLUME: |
1302 | va.volume = c->value; | ||
1303 | break; | ||
1304 | case V4L2_CID_AUDIO_BALANCE: | 1325 | case V4L2_CID_AUDIO_BALANCE: |
1305 | va.balance = c->value; | ||
1306 | break; | ||
1307 | case V4L2_CID_AUDIO_BASS: | 1326 | case V4L2_CID_AUDIO_BASS: |
1308 | va.bass = c->value; | ||
1309 | break; | ||
1310 | case V4L2_CID_AUDIO_TREBLE: | 1327 | case V4L2_CID_AUDIO_TREBLE: |
1311 | va.treble = c->value; | 1328 | bttv_call_i2c_clients(btv,VIDIOC_S_CTRL,c); |
1312 | break; | 1329 | break; |
1313 | 1330 | ||
1314 | case V4L2_CID_PRIVATE_CHROMA_AGC: | 1331 | case V4L2_CID_PRIVATE_CHROMA_AGC: |
@@ -1364,11 +1381,6 @@ static int set_control(struct bttv *btv, struct v4l2_control *c) | |||
1364 | default: | 1381 | default: |
1365 | return -EINVAL; | 1382 | return -EINVAL; |
1366 | } | 1383 | } |
1367 | if (i >= 4 && i <= 8) { | ||
1368 | bttv_call_i2c_clients(btv, VIDIOCSAUDIO, &va); | ||
1369 | if (btv->audio_hook) | ||
1370 | btv->audio_hook(btv,&va,1); | ||
1371 | } | ||
1372 | return 0; | 1384 | return 0; |
1373 | } | 1385 | } |
1374 | 1386 | ||
@@ -1827,33 +1839,26 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) | |||
1827 | return -EINVAL; | 1839 | return -EINVAL; |
1828 | mutex_lock(&btv->lock); | 1840 | mutex_lock(&btv->lock); |
1829 | memset(t,0,sizeof(*t)); | 1841 | memset(t,0,sizeof(*t)); |
1842 | t->rxsubchans = V4L2_TUNER_SUB_MONO; | ||
1843 | bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); | ||
1830 | strcpy(t->name, "Television"); | 1844 | strcpy(t->name, "Television"); |
1831 | t->type = V4L2_TUNER_ANALOG_TV; | ||
1832 | t->capability = V4L2_TUNER_CAP_NORM; | 1845 | t->capability = V4L2_TUNER_CAP_NORM; |
1833 | t->rxsubchans = V4L2_TUNER_SUB_MONO; | 1846 | t->type = V4L2_TUNER_ANALOG_TV; |
1834 | if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) | 1847 | if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) |
1835 | t->signal = 0xffff; | 1848 | t->signal = 0xffff; |
1836 | { | 1849 | |
1837 | struct video_tuner tuner; | 1850 | if (btv->audio_hook) { |
1838 | |||
1839 | memset(&tuner, 0, sizeof (tuner)); | ||
1840 | tuner.rangehigh = 0xffffffffUL; | ||
1841 | bttv_call_i2c_clients(btv, VIDIOCGTUNER, &tuner); | ||
1842 | t->rangelow = tuner.rangelow; | ||
1843 | t->rangehigh = tuner.rangehigh; | ||
1844 | } | ||
1845 | { | ||
1846 | /* Hmmm ... */ | 1851 | /* Hmmm ... */ |
1847 | struct video_audio va; | 1852 | struct video_audio va; |
1848 | memset(&va, 0, sizeof(struct video_audio)); | 1853 | memset(&va, 0, sizeof(struct video_audio)); |
1849 | bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); | 1854 | btv->audio_hook(btv,&va,0); |
1850 | if (btv->audio_hook) | 1855 | t->audmode = V4L2_TUNER_MODE_MONO; |
1851 | btv->audio_hook(btv,&va,0); | 1856 | t->rxsubchans = V4L2_TUNER_SUB_MONO; |
1852 | if(va.mode & VIDEO_SOUND_STEREO) { | 1857 | if(va.mode & VIDEO_SOUND_STEREO) { |
1853 | t->audmode = V4L2_TUNER_MODE_STEREO; | 1858 | t->audmode = V4L2_TUNER_MODE_STEREO; |
1854 | t->rxsubchans |= V4L2_TUNER_SUB_STEREO; | 1859 | t->rxsubchans = V4L2_TUNER_SUB_STEREO; |
1855 | } | 1860 | } |
1856 | if(va.mode & VIDEO_SOUND_LANG1) { | 1861 | if(va.mode & VIDEO_SOUND_LANG2) { |
1857 | t->audmode = V4L2_TUNER_MODE_LANG1; | 1862 | t->audmode = V4L2_TUNER_MODE_LANG1; |
1858 | t->rxsubchans = V4L2_TUNER_SUB_LANG1 | 1863 | t->rxsubchans = V4L2_TUNER_SUB_LANG1 |
1859 | | V4L2_TUNER_SUB_LANG2; | 1864 | | V4L2_TUNER_SUB_LANG2; |
@@ -1872,10 +1877,10 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) | |||
1872 | if (0 != t->index) | 1877 | if (0 != t->index) |
1873 | return -EINVAL; | 1878 | return -EINVAL; |
1874 | mutex_lock(&btv->lock); | 1879 | mutex_lock(&btv->lock); |
1875 | { | 1880 | bttv_call_i2c_clients(btv, VIDIOC_S_TUNER, t); |
1881 | if (btv->audio_hook) { | ||
1876 | struct video_audio va; | 1882 | struct video_audio va; |
1877 | memset(&va, 0, sizeof(struct video_audio)); | 1883 | memset(&va, 0, sizeof(struct video_audio)); |
1878 | bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); | ||
1879 | if (t->audmode == V4L2_TUNER_MODE_MONO) | 1884 | if (t->audmode == V4L2_TUNER_MODE_MONO) |
1880 | va.mode = VIDEO_SOUND_MONO; | 1885 | va.mode = VIDEO_SOUND_MONO; |
1881 | else if (t->audmode == V4L2_TUNER_MODE_STEREO || | 1886 | else if (t->audmode == V4L2_TUNER_MODE_STEREO || |
@@ -1885,9 +1890,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) | |||
1885 | va.mode = VIDEO_SOUND_LANG1; | 1890 | va.mode = VIDEO_SOUND_LANG1; |
1886 | else if (t->audmode == V4L2_TUNER_MODE_LANG2) | 1891 | else if (t->audmode == V4L2_TUNER_MODE_LANG2) |
1887 | va.mode = VIDEO_SOUND_LANG2; | 1892 | va.mode = VIDEO_SOUND_LANG2; |
1888 | bttv_call_i2c_clients(btv, VIDIOCSAUDIO, &va); | 1893 | btv->audio_hook(btv,&va,1); |
1889 | if (btv->audio_hook) | ||
1890 | btv->audio_hook(btv,&va,1); | ||
1891 | } | 1894 | } |
1892 | mutex_unlock(&btv->lock); | 1895 | mutex_unlock(&btv->lock); |
1893 | return 0; | 1896 | return 0; |
@@ -1912,7 +1915,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) | |||
1912 | return -EINVAL; | 1915 | return -EINVAL; |
1913 | mutex_lock(&btv->lock); | 1916 | mutex_lock(&btv->lock); |
1914 | btv->freq = f->frequency; | 1917 | btv->freq = f->frequency; |
1915 | bttv_call_i2c_clients(btv,VIDIOCSFREQ,&btv->freq); | 1918 | bttv_call_i2c_clients(btv,VIDIOC_S_FREQUENCY,f); |
1916 | if (btv->has_matchbox && btv->radio_user) | 1919 | if (btv->has_matchbox && btv->radio_user) |
1917 | tea5757_set_freq(btv,btv->freq); | 1920 | tea5757_set_freq(btv,btv->freq); |
1918 | mutex_unlock(&btv->lock); | 1921 | mutex_unlock(&btv->lock); |
@@ -1920,7 +1923,9 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) | |||
1920 | } | 1923 | } |
1921 | case VIDIOC_LOG_STATUS: | 1924 | case VIDIOC_LOG_STATUS: |
1922 | { | 1925 | { |
1926 | printk(KERN_INFO "bttv%d: ================= START STATUS CARD #%d =================\n", btv->c.nr, btv->c.nr); | ||
1923 | bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL); | 1927 | bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL); |
1928 | printk(KERN_INFO "bttv%d: ================== END STATUS CARD #%d ==================\n", btv->c.nr, btv->c.nr); | ||
1924 | return 0; | 1929 | return 0; |
1925 | } | 1930 | } |
1926 | 1931 | ||
@@ -2870,12 +2875,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, | |||
2870 | return 0; | 2875 | return 0; |
2871 | } | 2876 | } |
2872 | *c = bttv_ctls[i]; | 2877 | *c = bttv_ctls[i]; |
2873 | if (i >= 4 && i <= 8) { | 2878 | if (btv->audio_hook && i >= 4 && i <= 8) { |
2874 | struct video_audio va; | 2879 | struct video_audio va; |
2875 | memset(&va,0,sizeof(va)); | 2880 | memset(&va,0,sizeof(va)); |
2876 | bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); | 2881 | btv->audio_hook(btv,&va,0); |
2877 | if (btv->audio_hook) | ||
2878 | btv->audio_hook(btv,&va,0); | ||
2879 | switch (bttv_ctls[i].id) { | 2882 | switch (bttv_ctls[i].id) { |
2880 | case V4L2_CID_AUDIO_VOLUME: | 2883 | case V4L2_CID_AUDIO_VOLUME: |
2881 | if (!(va.flags & VIDEO_AUDIO_VOLUME)) | 2884 | if (!(va.flags & VIDEO_AUDIO_VOLUME)) |
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index 12a83ec7872c..027c3d35eaa5 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c | |||
@@ -283,19 +283,6 @@ void msp_set_scart(struct i2c_client *client, int in, int out) | |||
283 | msp_write_dem(client, 0x40, state->i2s_mode); | 283 | msp_write_dem(client, 0x40, state->i2s_mode); |
284 | } | 284 | } |
285 | 285 | ||
286 | void msp_set_mute(struct i2c_client *client) | ||
287 | { | ||
288 | struct msp_state *state = i2c_get_clientdata(client); | ||
289 | |||
290 | v4l_dbg(1, msp_debug, client, "mute audio\n"); | ||
291 | msp_write_dsp(client, 0x0000, 0); | ||
292 | msp_write_dsp(client, 0x0007, 1); | ||
293 | if (state->has_scart2_out_volume) | ||
294 | msp_write_dsp(client, 0x0040, 1); | ||
295 | if (state->has_headphones) | ||
296 | msp_write_dsp(client, 0x0006, 0); | ||
297 | } | ||
298 | |||
299 | void msp_set_audio(struct i2c_client *client) | 286 | void msp_set_audio(struct i2c_client *client) |
300 | { | 287 | { |
301 | struct msp_state *state = i2c_get_clientdata(client); | 288 | struct msp_state *state = i2c_get_clientdata(client); |
@@ -347,7 +334,6 @@ static void msp_wake_thread(struct i2c_client *client) | |||
347 | 334 | ||
348 | if (NULL == state->kthread) | 335 | if (NULL == state->kthread) |
349 | return; | 336 | return; |
350 | msp_set_mute(client); | ||
351 | state->watch_stereo = 0; | 337 | state->watch_stereo = 0; |
352 | state->restart = 1; | 338 | state->restart = 1; |
353 | wake_up_interruptible(&state->wq); | 339 | wake_up_interruptible(&state->wq); |
@@ -375,19 +361,15 @@ int msp_sleep(struct msp_state *state, int timeout) | |||
375 | 361 | ||
376 | /* ------------------------------------------------------------------------ */ | 362 | /* ------------------------------------------------------------------------ */ |
377 | 363 | ||
378 | static int msp_mode_v4l2_to_v4l1(int rxsubchans) | 364 | static int msp_mode_v4l2_to_v4l1(int rxsubchans, int audmode) |
379 | { | 365 | { |
380 | int mode = 0; | 366 | if (rxsubchans == V4L2_TUNER_SUB_MONO) |
381 | 367 | return VIDEO_SOUND_MONO; | |
382 | if (rxsubchans & V4L2_TUNER_SUB_STEREO) | 368 | if (rxsubchans == V4L2_TUNER_SUB_STEREO) |
383 | mode |= VIDEO_SOUND_STEREO; | 369 | return VIDEO_SOUND_STEREO; |
384 | if (rxsubchans & V4L2_TUNER_SUB_LANG2) | 370 | if (audmode == V4L2_TUNER_MODE_LANG2) |
385 | mode |= VIDEO_SOUND_LANG2 | VIDEO_SOUND_STEREO; | 371 | return VIDEO_SOUND_LANG2; |
386 | if (rxsubchans & V4L2_TUNER_SUB_LANG1) | 372 | return VIDEO_SOUND_LANG1; |
387 | mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_STEREO; | ||
388 | if (mode == 0) | ||
389 | mode |= VIDEO_SOUND_MONO; | ||
390 | return mode; | ||
391 | } | 373 | } |
392 | 374 | ||
393 | static int msp_mode_v4l1_to_v4l2(int mode) | 375 | static int msp_mode_v4l1_to_v4l2(int mode) |
@@ -606,7 +588,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
606 | break; | 588 | break; |
607 | if (state->opmode == OPMODE_AUTOSELECT) | 589 | if (state->opmode == OPMODE_AUTOSELECT) |
608 | msp_detect_stereo(client); | 590 | msp_detect_stereo(client); |
609 | va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans); | 591 | va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans, state->audmode); |
610 | break; | 592 | break; |
611 | } | 593 | } |
612 | 594 | ||
@@ -621,7 +603,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
621 | state->treble = va->treble; | 603 | state->treble = va->treble; |
622 | msp_set_audio(client); | 604 | msp_set_audio(client); |
623 | 605 | ||
624 | if (va->mode != 0 && state->radio == 0) { | 606 | if (va->mode != 0 && state->radio == 0 && |
607 | state->audmode != msp_mode_v4l1_to_v4l2(va->mode)) { | ||
625 | state->audmode = msp_mode_v4l1_to_v4l2(va->mode); | 608 | state->audmode = msp_mode_v4l1_to_v4l2(va->mode); |
626 | msp_set_audmode(client); | 609 | msp_set_audmode(client); |
627 | } | 610 | } |
@@ -727,6 +710,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
727 | 710 | ||
728 | if (state->radio) /* TODO: add mono/stereo support for radio */ | 711 | if (state->radio) /* TODO: add mono/stereo support for radio */ |
729 | break; | 712 | break; |
713 | if (state->audmode == vt->audmode) | ||
714 | break; | ||
730 | state->audmode = vt->audmode; | 715 | state->audmode = vt->audmode; |
731 | /* only set audmode */ | 716 | /* only set audmode */ |
732 | msp_set_audmode(client); | 717 | msp_set_audmode(client); |
@@ -888,7 +873,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) | |||
888 | 873 | ||
889 | memset(state, 0, sizeof(*state)); | 874 | memset(state, 0, sizeof(*state)); |
890 | state->v4l2_std = V4L2_STD_NTSC; | 875 | state->v4l2_std = V4L2_STD_NTSC; |
891 | state->audmode = V4L2_TUNER_MODE_LANG1; | 876 | state->audmode = V4L2_TUNER_MODE_STEREO; |
892 | state->volume = 58880; /* 0db gain */ | 877 | state->volume = 58880; /* 0db gain */ |
893 | state->balance = 32768; /* 0db gain */ | 878 | state->balance = 32768; /* 0db gain */ |
894 | state->bass = 32768; | 879 | state->bass = 32768; |
@@ -932,13 +917,16 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) | |||
932 | state->has_radio = msp_revision >= 'G'; | 917 | state->has_radio = msp_revision >= 'G'; |
933 | /* Has headphones output: not for stripped down products */ | 918 | /* Has headphones output: not for stripped down products */ |
934 | state->has_headphones = msp_prod_lo < 5; | 919 | state->has_headphones = msp_prod_lo < 5; |
920 | /* Has scart2 input: not in stripped down products of the '3' family */ | ||
921 | state->has_scart2 = msp_family >= 4 || msp_prod_lo < 7; | ||
922 | /* Has scart3 input: not in stripped down products of the '3' family */ | ||
923 | state->has_scart3 = msp_family >= 4 || msp_prod_lo < 5; | ||
935 | /* Has scart4 input: not in pre D revisions, not in stripped D revs */ | 924 | /* Has scart4 input: not in pre D revisions, not in stripped D revs */ |
936 | state->has_scart4 = msp_family >= 4 || (msp_revision >= 'D' && msp_prod_lo < 5); | 925 | state->has_scart4 = msp_family >= 4 || (msp_revision >= 'D' && msp_prod_lo < 5); |
937 | /* Has scart2 and scart3 inputs and scart2 output: not in stripped | 926 | /* Has scart2 output: not in stripped down products of the '3' family */ |
938 | down products of the '3' family */ | 927 | state->has_scart2_out = msp_family >= 4 || msp_prod_lo < 5; |
939 | state->has_scart23_in_scart2_out = msp_family >= 4 || msp_prod_lo < 5; | ||
940 | /* Has scart2 a volume control? Not in pre-D revisions. */ | 928 | /* Has scart2 a volume control? Not in pre-D revisions. */ |
941 | state->has_scart2_out_volume = msp_revision > 'C' && state->has_scart23_in_scart2_out; | 929 | state->has_scart2_out_volume = msp_revision > 'C' && state->has_scart2_out; |
942 | /* Has a configurable i2s out? */ | 930 | /* Has a configurable i2s out? */ |
943 | state->has_i2s_conf = msp_revision >= 'G' && msp_prod_lo < 7; | 931 | state->has_i2s_conf = msp_revision >= 'G' && msp_prod_lo < 7; |
944 | /* Has subwoofer output: not in pre-D revs and not in stripped down products */ | 932 | /* Has subwoofer output: not in pre-D revs and not in stripped down products */ |
diff --git a/drivers/media/video/msp3400-driver.h b/drivers/media/video/msp3400-driver.h index 1940748bb633..b5834938df7d 100644 --- a/drivers/media/video/msp3400-driver.h +++ b/drivers/media/video/msp3400-driver.h | |||
@@ -54,8 +54,10 @@ struct msp_state { | |||
54 | u8 has_radio; | 54 | u8 has_radio; |
55 | u8 has_headphones; | 55 | u8 has_headphones; |
56 | u8 has_ntsc_jp_d_k3; | 56 | u8 has_ntsc_jp_d_k3; |
57 | u8 has_scart2; | ||
58 | u8 has_scart3; | ||
57 | u8 has_scart4; | 59 | u8 has_scart4; |
58 | u8 has_scart23_in_scart2_out; | 60 | u8 has_scart2_out; |
59 | u8 has_scart2_out_volume; | 61 | u8 has_scart2_out_volume; |
60 | u8 has_i2s_conf; | 62 | u8 has_i2s_conf; |
61 | u8 has_subwoofer; | 63 | u8 has_subwoofer; |
@@ -98,7 +100,6 @@ int msp_read_dem(struct i2c_client *client, int addr); | |||
98 | int msp_read_dsp(struct i2c_client *client, int addr); | 100 | int msp_read_dsp(struct i2c_client *client, int addr); |
99 | int msp_reset(struct i2c_client *client); | 101 | int msp_reset(struct i2c_client *client); |
100 | void msp_set_scart(struct i2c_client *client, int in, int out); | 102 | void msp_set_scart(struct i2c_client *client, int in, int out); |
101 | void msp_set_mute(struct i2c_client *client); | ||
102 | void msp_set_audio(struct i2c_client *client); | 103 | void msp_set_audio(struct i2c_client *client); |
103 | int msp_sleep(struct msp_state *state, int timeout); | 104 | int msp_sleep(struct msp_state *state, int timeout); |
104 | 105 | ||
diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c index 1a4564a7e92f..926095c6d826 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/video/msp3400-kthreads.c | |||
@@ -170,7 +170,7 @@ static void msp_set_source(struct i2c_client *client, u16 src) | |||
170 | msp_write_dsp(client, 0x000a, src); | 170 | msp_write_dsp(client, 0x000a, src); |
171 | msp_write_dsp(client, 0x000b, src); | 171 | msp_write_dsp(client, 0x000b, src); |
172 | msp_write_dsp(client, 0x000c, src); | 172 | msp_write_dsp(client, 0x000c, src); |
173 | if (state->has_scart23_in_scart2_out) | 173 | if (state->has_scart2_out) |
174 | msp_write_dsp(client, 0x0041, src); | 174 | msp_write_dsp(client, 0x0041, src); |
175 | } | 175 | } |
176 | 176 | ||
@@ -240,15 +240,22 @@ static void msp3400c_set_audmode(struct i2c_client *client) | |||
240 | return; | 240 | return; |
241 | } | 241 | } |
242 | 242 | ||
243 | /* If no second language is available, switch to the first language */ | 243 | /* Note: for the C and D revs no NTSC stereo + SAP is possible as |
244 | if ((audmode == V4L2_TUNER_MODE_LANG2 || | 244 | the hardware does not support SAP. So the rxsubchans combination |
245 | audmode == V4L2_TUNER_MODE_LANG1_LANG2) && | 245 | of STEREO | LANG2 does not occur. */ |
246 | !(state->rxsubchans & V4L2_TUNER_SUB_LANG2)) | 246 | |
247 | audmode = V4L2_TUNER_MODE_LANG1; | 247 | /* switch to mono if only mono is available */ |
248 | /* switch to stereo for stereo transmission, otherwise | 248 | if (state->rxsubchans == V4L2_TUNER_SUB_MONO) |
249 | keep first language */ | 249 | audmode = V4L2_TUNER_MODE_MONO; |
250 | if (audmode == V4L2_TUNER_MODE_LANG1 && | 250 | /* if bilingual */ |
251 | (state->rxsubchans & V4L2_TUNER_SUB_STEREO)) | 251 | else if (state->rxsubchans & V4L2_TUNER_SUB_LANG2) { |
252 | /* and mono or stereo, then fallback to lang1 */ | ||
253 | if (audmode == V4L2_TUNER_MODE_MONO || | ||
254 | audmode == V4L2_TUNER_MODE_STEREO) | ||
255 | audmode = V4L2_TUNER_MODE_LANG1; | ||
256 | } | ||
257 | /* if stereo, and audmode is not mono, then switch to stereo */ | ||
258 | else if (audmode != V4L2_TUNER_MODE_MONO) | ||
252 | audmode = V4L2_TUNER_MODE_STEREO; | 259 | audmode = V4L2_TUNER_MODE_STEREO; |
253 | 260 | ||
254 | /* switch demodulator */ | 261 | /* switch demodulator */ |
@@ -308,6 +315,7 @@ static void msp3400c_set_audmode(struct i2c_client *client) | |||
308 | } | 315 | } |
309 | 316 | ||
310 | /* switch audio */ | 317 | /* switch audio */ |
318 | v4l_dbg(1, msp_debug, client, "set audmode %d\n", audmode); | ||
311 | switch (audmode) { | 319 | switch (audmode) { |
312 | case V4L2_TUNER_MODE_STEREO: | 320 | case V4L2_TUNER_MODE_STEREO: |
313 | case V4L2_TUNER_MODE_LANG1_LANG2: | 321 | case V4L2_TUNER_MODE_LANG1_LANG2: |
@@ -476,8 +484,9 @@ int msp3400c_thread(void *data) | |||
476 | continue; | 484 | continue; |
477 | } | 485 | } |
478 | 486 | ||
479 | /* mute */ | 487 | /* put into sane state (and mute) */ |
480 | msp_set_mute(client); | 488 | msp_reset(client); |
489 | |||
481 | msp3400c_set_mode(client, MSP_MODE_AM_DETECT); | 490 | msp3400c_set_mode(client, MSP_MODE_AM_DETECT); |
482 | val1 = val2 = 0; | 491 | val1 = val2 = 0; |
483 | max1 = max2 = -1; | 492 | max1 = max2 = -1; |
@@ -560,7 +569,6 @@ int msp3400c_thread(void *data) | |||
560 | /* B/G NICAM */ | 569 | /* B/G NICAM */ |
561 | state->second = msp3400c_carrier_detect_55[max2].cdo; | 570 | state->second = msp3400c_carrier_detect_55[max2].cdo; |
562 | msp3400c_set_mode(client, MSP_MODE_FM_NICAM1); | 571 | msp3400c_set_mode(client, MSP_MODE_FM_NICAM1); |
563 | msp3400c_set_carrier(client, state->second, state->main); | ||
564 | state->nicam_on = 1; | 572 | state->nicam_on = 1; |
565 | state->watch_stereo = 1; | 573 | state->watch_stereo = 1; |
566 | } else { | 574 | } else { |
@@ -571,7 +579,6 @@ int msp3400c_thread(void *data) | |||
571 | /* PAL I NICAM */ | 579 | /* PAL I NICAM */ |
572 | state->second = MSP_CARRIER(6.552); | 580 | state->second = MSP_CARRIER(6.552); |
573 | msp3400c_set_mode(client, MSP_MODE_FM_NICAM2); | 581 | msp3400c_set_mode(client, MSP_MODE_FM_NICAM2); |
574 | msp3400c_set_carrier(client, state->second, state->main); | ||
575 | state->nicam_on = 1; | 582 | state->nicam_on = 1; |
576 | state->watch_stereo = 1; | 583 | state->watch_stereo = 1; |
577 | break; | 584 | break; |
@@ -585,13 +592,11 @@ int msp3400c_thread(void *data) | |||
585 | /* L NICAM or AM-mono */ | 592 | /* L NICAM or AM-mono */ |
586 | state->second = msp3400c_carrier_detect_65[max2].cdo; | 593 | state->second = msp3400c_carrier_detect_65[max2].cdo; |
587 | msp3400c_set_mode(client, MSP_MODE_AM_NICAM); | 594 | msp3400c_set_mode(client, MSP_MODE_AM_NICAM); |
588 | msp3400c_set_carrier(client, state->second, state->main); | ||
589 | state->watch_stereo = 1; | 595 | state->watch_stereo = 1; |
590 | } else if (max2 == 0 && state->has_nicam) { | 596 | } else if (max2 == 0 && state->has_nicam) { |
591 | /* D/K NICAM */ | 597 | /* D/K NICAM */ |
592 | state->second = msp3400c_carrier_detect_65[max2].cdo; | 598 | state->second = msp3400c_carrier_detect_65[max2].cdo; |
593 | msp3400c_set_mode(client, MSP_MODE_FM_NICAM1); | 599 | msp3400c_set_mode(client, MSP_MODE_FM_NICAM1); |
594 | msp3400c_set_carrier(client, state->second, state->main); | ||
595 | state->nicam_on = 1; | 600 | state->nicam_on = 1; |
596 | state->watch_stereo = 1; | 601 | state->watch_stereo = 1; |
597 | } else { | 602 | } else { |
@@ -603,13 +608,15 @@ int msp3400c_thread(void *data) | |||
603 | no_second: | 608 | no_second: |
604 | state->second = msp3400c_carrier_detect_main[max1].cdo; | 609 | state->second = msp3400c_carrier_detect_main[max1].cdo; |
605 | msp3400c_set_mode(client, MSP_MODE_FM_TERRA); | 610 | msp3400c_set_mode(client, MSP_MODE_FM_TERRA); |
606 | msp3400c_set_carrier(client, state->second, state->main); | ||
607 | state->rxsubchans = V4L2_TUNER_SUB_MONO; | 611 | state->rxsubchans = V4L2_TUNER_SUB_MONO; |
608 | break; | 612 | break; |
609 | } | 613 | } |
614 | msp3400c_set_carrier(client, state->second, state->main); | ||
610 | 615 | ||
611 | /* unmute */ | 616 | /* unmute, restore misc registers */ |
612 | msp_set_audio(client); | 617 | msp_set_audio(client); |
618 | |||
619 | msp_write_dsp(client, 0x13, state->acb); | ||
613 | msp3400c_set_audmode(client); | 620 | msp3400c_set_audmode(client); |
614 | 621 | ||
615 | if (msp_debug) | 622 | if (msp_debug) |
@@ -617,12 +624,12 @@ int msp3400c_thread(void *data) | |||
617 | 624 | ||
618 | /* monitor tv audio mode, the first time don't wait | 625 | /* monitor tv audio mode, the first time don't wait |
619 | so long to get a quick stereo/bilingual result */ | 626 | so long to get a quick stereo/bilingual result */ |
620 | if (msp_sleep(state, 1000)) | 627 | count = 20; |
621 | goto restart; | ||
622 | while (state->watch_stereo) { | 628 | while (state->watch_stereo) { |
623 | watch_stereo(client); | 629 | watch_stereo(client); |
624 | if (msp_sleep(state, 5000)) | 630 | if (msp_sleep(state, count ? 200 : 5000)) |
625 | goto restart; | 631 | goto restart; |
632 | if (count) count--; | ||
626 | } | 633 | } |
627 | } | 634 | } |
628 | v4l_dbg(1, msp_debug, client, "thread: exit\n"); | 635 | v4l_dbg(1, msp_debug, client, "thread: exit\n"); |
@@ -634,7 +641,7 @@ int msp3410d_thread(void *data) | |||
634 | { | 641 | { |
635 | struct i2c_client *client = data; | 642 | struct i2c_client *client = data; |
636 | struct msp_state *state = i2c_get_clientdata(client); | 643 | struct msp_state *state = i2c_get_clientdata(client); |
637 | int val, i, std; | 644 | int val, i, std, count; |
638 | 645 | ||
639 | v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n"); | 646 | v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n"); |
640 | 647 | ||
@@ -775,12 +782,12 @@ int msp3410d_thread(void *data) | |||
775 | 782 | ||
776 | /* monitor tv audio mode, the first time don't wait | 783 | /* monitor tv audio mode, the first time don't wait |
777 | so long to get a quick stereo/bilingual result */ | 784 | so long to get a quick stereo/bilingual result */ |
778 | if (msp_sleep(state, 1000)) | 785 | count = 20; |
779 | goto restart; | ||
780 | while (state->watch_stereo) { | 786 | while (state->watch_stereo) { |
781 | watch_stereo(client); | 787 | watch_stereo(client); |
782 | if (msp_sleep(state, 5000)) | 788 | if (msp_sleep(state, count ? 200 : 5000)) |
783 | goto restart; | 789 | goto restart; |
790 | if (count) count--; | ||
784 | } | 791 | } |
785 | } | 792 | } |
786 | v4l_dbg(1, msp_debug, client, "thread: exit\n"); | 793 | v4l_dbg(1, msp_debug, client, "thread: exit\n"); |
@@ -837,20 +844,20 @@ static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in) | |||
837 | source = 0; /* mono only */ | 844 | source = 0; /* mono only */ |
838 | matrix = 0x30; | 845 | matrix = 0x30; |
839 | break; | 846 | break; |
840 | case V4L2_TUNER_MODE_LANG1: | ||
841 | source = 3; /* stereo or A */ | ||
842 | matrix = 0x00; | ||
843 | break; | ||
844 | case V4L2_TUNER_MODE_LANG2: | 847 | case V4L2_TUNER_MODE_LANG2: |
845 | source = 4; /* stereo or B */ | 848 | source = 4; /* stereo or B */ |
846 | matrix = 0x10; | 849 | matrix = 0x10; |
847 | break; | 850 | break; |
848 | case V4L2_TUNER_MODE_STEREO: | ||
849 | case V4L2_TUNER_MODE_LANG1_LANG2: | 851 | case V4L2_TUNER_MODE_LANG1_LANG2: |
850 | default: | ||
851 | source = 1; /* stereo or A|B */ | 852 | source = 1; /* stereo or A|B */ |
852 | matrix = 0x20; | 853 | matrix = 0x20; |
853 | break; | 854 | break; |
855 | case V4L2_TUNER_MODE_STEREO: | ||
856 | case V4L2_TUNER_MODE_LANG1: | ||
857 | default: | ||
858 | source = 3; /* stereo or A */ | ||
859 | matrix = 0x00; | ||
860 | break; | ||
854 | } | 861 | } |
855 | 862 | ||
856 | if (in == MSP_DSP_OUT_TUNER) | 863 | if (in == MSP_DSP_OUT_TUNER) |
@@ -877,7 +884,7 @@ static void msp34xxg_set_sources(struct i2c_client *client) | |||
877 | msp34xxg_set_source(client, 0x000c, (in >> 4) & 0xf); | 884 | msp34xxg_set_source(client, 0x000c, (in >> 4) & 0xf); |
878 | msp34xxg_set_source(client, 0x0009, (in >> 8) & 0xf); | 885 | msp34xxg_set_source(client, 0x0009, (in >> 8) & 0xf); |
879 | msp34xxg_set_source(client, 0x000a, (in >> 12) & 0xf); | 886 | msp34xxg_set_source(client, 0x000a, (in >> 12) & 0xf); |
880 | if (state->has_scart23_in_scart2_out) | 887 | if (state->has_scart2_out) |
881 | msp34xxg_set_source(client, 0x0041, (in >> 16) & 0xf); | 888 | msp34xxg_set_source(client, 0x0041, (in >> 16) & 0xf); |
882 | msp34xxg_set_source(client, 0x000b, (in >> 20) & 0xf); | 889 | msp34xxg_set_source(client, 0x000b, (in >> 20) & 0xf); |
883 | } | 890 | } |