msp3400-kthreads.c revision 044f324f6ea5d55391db62fca6a295b2651cb946
17e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* 27e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * Programming the mspx4xx sound processor family 37e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * 47e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * (c) 1997-2001 Gerd Knorr <kraxel@bytesex.org> 57e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * 67e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * This program is free software; you can redistribute it and/or 77e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * modify it under the terms of the GNU General Public License 87e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * as published by the Free Software Foundation; either version 2 97e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * of the License, or (at your option) any later version. 107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * 117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * This program is distributed in the hope that it will be useful, 127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * but WITHOUT ANY WARRANTY; without even the implied warranty of 137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * GNU General Public License for more details. 157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * 167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * You should have received a copy of the GNU General Public License 177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * along with this program; if not, write to the Free Software 187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <linux/kernel.h> 237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <linux/module.h> 247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <linux/slab.h> 257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <linux/i2c.h> 267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <linux/videodev.h> 277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <linux/videodev2.h> 287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <media/v4l2-common.h> 297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <media/audiochip.h> 307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <linux/kthread.h> 317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <linux/suspend.h> 327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include "msp3400.h" 337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* this one uses the automatic sound standard detection of newer msp34xx 357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil chip versions */ 367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic struct { 377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int retval; 387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int main, second; 397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil char *name; 405af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil} msp_stdlist[] = { 417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0000, 0, 0, "could not detect sound standard" }, 427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0001, 0, 0, "autodetect start" }, 437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72), "4.5/4.72 M Dual FM-Stereo" }, 447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875), "5.5/5.74 B/G Dual FM-Stereo" }, 457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125), "6.5/6.25 D/K1 Dual FM-Stereo" }, 467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875), "6.5/6.74 D/K2 Dual FM-Stereo" }, 477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 D/K FM-Mono (HDEV3)" }, 487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), "5.5/5.85 B/G NICAM FM" }, 497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 L NICAM AM" }, 507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), "6.0/6.55 I NICAM FM" }, 517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM" }, 527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV2)" }, 537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Stereo" }, 547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Mono + SAP" }, 557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M EIA-J Japan Stereo" }, 567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7), "10.7 FM-Stereo Radio" }, 577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 SAT-Mono" }, 587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20), "7.02/7.20 SAT-Stereo" }, 597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2), "7.2 SAT ADR" }, 607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { -1, 0, 0, NULL }, /* EOF */ 617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic struct msp3400c_init_data_dem { 647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int fir1[6]; 657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int fir2[6]; 667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int cdo1; 677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int cdo2; 687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int ad_cv; 697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int mode_reg; 707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int dsp_src; 717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int dsp_matrix; 727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} msp3400c_init_data[] = { 737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { /* AM (for carrier detect / msp3400) */ 747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {75, 19, 36, 35, 39, 40}, 757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {75, 19, 36, 35, 39, 40}, 767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(5.5), MSP_CARRIER(5.5), 777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0500, 0x0020, 0x3000 787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil },{ /* AM (for carrier detect / msp3410) */ 797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-1, -1, -8, 2, 59, 126}, 807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-1, -1, -8, 2, 59, 126}, 817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(5.5), MSP_CARRIER(5.5), 827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0100, 0x0020, 0x3000 837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil },{ /* FM Radio */ 847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-8, -8, 4, 6, 78, 107}, 857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-8, -8, 4, 6, 78, 107}, 867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(10.7), MSP_CARRIER(10.7), 877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0480, 0x0020, 0x3000 887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil },{ /* Terrestial FM-mono + FM-stereo */ 897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {3, 18, 27, 48, 66, 72}, 907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {3, 18, 27, 48, 66, 72}, 917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(5.5), MSP_CARRIER(5.5), 927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0480, 0x0030, 0x3000 937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil },{ /* Sat FM-mono */ 947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 1, 9, 14, 24, 33, 37}, 957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 3, 18, 27, 48, 66, 72}, 967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(6.5), MSP_CARRIER(6.5), 977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00c6, 0x0480, 0x0000, 0x3000 987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil },{ /* NICAM/FM -- B/G (5.5/5.85), D/K (6.5/5.85) */ 997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-2, -8, -10, 10, 50, 86}, 1007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {3, 18, 27, 48, 66, 72}, 1017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(5.5), MSP_CARRIER(5.5), 1027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0040, 0x0120, 0x3000 1037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil },{ /* NICAM/FM -- I (6.0/6.552) */ 1047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {2, 4, -6, -4, 40, 94}, 1057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {3, 18, 27, 48, 66, 72}, 1067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(6.0), MSP_CARRIER(6.0), 1077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0040, 0x0120, 0x3000 1087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil },{ /* NICAM/AM -- L (6.5/5.85) */ 1097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-2, -8, -10, 10, 50, 86}, 1107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-4, -12, -9, 23, 79, 126}, 1117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(6.5), MSP_CARRIER(6.5), 1128a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 0x00c6, 0x0140, 0x0120, 0x7c00 1137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil }, 1147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 1157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstruct msp3400c_carrier_detect { 1177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int cdo; 1187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil char *name; 1197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 1207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic struct msp3400c_carrier_detect msp3400c_carrier_detect_main[] = { 1227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* main carrier */ 1237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(4.5), "4.5 NTSC" }, 1247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(5.5), "5.5 PAL B/G" }, 1257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(6.0), "6.0 PAL I" }, 1267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(6.5), "6.5 PAL D/K + SAT + SECAM" } 1277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 1287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic struct msp3400c_carrier_detect msp3400c_carrier_detect_55[] = { 1307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* PAL B/G */ 1317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(5.7421875), "5.742 PAL B/G FM-stereo" }, 1327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(5.85), "5.85 PAL B/G NICAM" } 1337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 1347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic struct msp3400c_carrier_detect msp3400c_carrier_detect_65[] = { 1367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* PAL SAT / SECAM */ 1377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(5.85), "5.85 PAL D/K + SECAM NICAM" }, 1387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(6.2578125), "6.25 PAL D/K1 FM-stereo" }, 1397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(6.7421875), "6.74 PAL D/K2 FM-stereo" }, 1407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(7.02), "7.02 PAL SAT FM-stereo s/b" }, 1417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(7.20), "7.20 PAL SAT FM-stereo s" }, 1427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(7.38), "7.38 PAL SAT FM-stereo b" }, 1437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 1447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* ------------------------------------------------------------------------ */ 1467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1475af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuilconst char *msp_standard_std_name(int std) 1487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 1497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int i; 1507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1515af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil for (i = 0; msp_stdlist[i].name != NULL; i++) 1525af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil if (msp_stdlist[i].retval == std) 1535af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil return msp_stdlist[i].name; 1547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return "unknown"; 1557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 1567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 157044f324f6ea5d55391db62fca6a295b2651cb946Adrian Bunkstatic void msp_set_source(struct i2c_client *client, u16 src) 1588a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil{ 1598a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil struct msp_state *state = i2c_get_clientdata(client); 1608a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 1618a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil if (msp_dolby) { 1628a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x0008, 0x0520); /* I2S1 */ 1638a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x0009, 0x0620); /* I2S2 */ 1648a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil } else { 1658a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x0008, src); 1668a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x0009, src); 1678a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil } 1688a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x000a, src); 1698a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x000b, src); 1708a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x000c, src); 1718a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil if (state->has_scart23_in_scart2_out) 1728a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x0041, src); 1738a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil} 1748a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 1758a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuilvoid msp3400c_set_carrier(struct i2c_client *client, int cdo1, int cdo2) 1767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 1777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x0093, cdo1 & 0xfff); 1787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x009b, cdo1 >> 12); 1797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x00a3, cdo2 & 0xfff); 1807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x00ab, cdo2 >> 12); 1818a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dem(client, 0x0056, 0); /* LOAD_REG_1/2 */ 1827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 1837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1848a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuilvoid msp3400c_set_mode(struct i2c_client *client, int mode) 1857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 1867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 1878a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil struct msp3400c_init_data_dem *data = &msp3400c_init_data[mode]; 1887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int i; 1897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1908a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "set_mode: %d\n", mode); 1918a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->mode = mode; 1927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_MONO; 1937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1948a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dem(client, 0x00bb, data->ad_cv); 1957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (i = 5; i >= 0; i--) /* fir 1 */ 1978a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dem(client, 0x0001, data->fir1[i]); 1987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x0005, 0x0004); /* fir 2 */ 2007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x0005, 0x0040); 2017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x0005, 0x0000); 2027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (i = 5; i >= 0; i--) 2038a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dem(client, 0x0005, data->fir2[i]); 2047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2058a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dem(client, 0x0083, data->mode_reg); 2067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2078a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, data->cdo1, data->cdo2); 2087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2098a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_set_source(client, data->dsp_src); 2108a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x000e, data->dsp_matrix); 2117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2127560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil if (state->has_nicam) { 2137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* nicam prescale */ 2147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x0010, 0x5a00); /* was: 0x3000 */ 2157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 2167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 2177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2188a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil/* Set audio mode. Note that the pre-'G' models do not support BTSC+SAP, 2198a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil nor do they support stereo BTSC. */ 220044f324f6ea5d55391db62fca6a295b2651cb946Adrian Bunkstatic void msp3400c_set_audmode(struct i2c_client *client) 2217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 222d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil static char *strmode[] = { "mono", "stereo", "lang2", "lang1" }; 2237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 2248a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil char *modestr = (state->audmode >= 0 && state->audmode < 4) ? 2258a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil strmode[state->audmode] : "unknown"; 2268a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil int src = 0; /* channel source: FM/AM, nicam or SCART */ 2277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->opmode == OPMODE_AUTOSELECT) { 2297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* this method would break everything, let's make sure 2307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * it's never called 2317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 2328a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, 2338a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil "set_audmode called with mode=%d instead of set_source (ignored)\n", 2348a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->audmode); 2357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return; 2367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 2377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* switch demodulator */ 2397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (state->mode) { 2407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_TERRA: 2418a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "FM set_audmode: %s\n", modestr); 2428a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil switch (state->audmode) { 2437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_STEREO: 2447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x000e, 0x3001); 2457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_MONO: 2477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG1: 2487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG2: 2497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x000e, 0x3000); 2507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 2527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_SAT: 2548a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "SAT set_audmode: %s\n", modestr); 2558a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil switch (state->audmode) { 2567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_MONO: 2578a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5)); 2587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_STEREO: 2608a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02)); 2617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG1: 2638a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); 2647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG2: 2668a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); 2677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 2697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_NICAM1: 2717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_NICAM2: 2727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_AM_NICAM: 2738a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "NICAM set_audmode: %s\n",modestr); 2748a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, state->second, state->main); 2757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->nicam_on) 2768a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil src = 0x0100; /* NICAM */ 2777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_BTSC: 2798a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "BTSC set_audmode: %s\n",modestr); 2807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_EXTERN: 2828a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "extern set_audmode: %s\n",modestr); 2838a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil src = 0x0200; /* SCART */ 2847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_RADIO: 2868a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "FM-Radio set_audmode: %s\n",modestr); 2877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 2898a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "mono set_audmode\n"); 2907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return; 2917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 2927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* switch audio */ 2948a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil switch (state->audmode) { 2957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_STEREO: 2968a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil src |= 0x0020; 2977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_MONO: 2997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_AM_NICAM) { 300f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "switching to AM mono\n"); 3017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* AM mono decoding is handled by tuner, not MSP chip */ 3027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* SCART switching control register */ 3037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_scart(client, SCART_MONO, 0); 3047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil src = 0x0200; 3057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3078a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil if (state->rxsubchans & V4L2_TUNER_SUB_STEREO) 3088a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil src = 0x0030; 3098a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil break; 3107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG1: 3118a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil /* switch to stereo for stereo transmission, otherwise 3128a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil keep first language */ 3138a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil if (state->rxsubchans & V4L2_TUNER_SUB_STEREO) 3148a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil src |= 0x0020; 3157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG2: 3178a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil src |= 0x0010; 3187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3208a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "set_audmode final source/matrix = 0x%x\n", src); 3217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3228a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_set_source(client, src); 3237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 3247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic void msp3400c_print_mode(struct i2c_client *client) 3267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 3277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 3287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->main == state->second) { 330f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "mono sound carrier: %d.%03d MHz\n", 3317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->main / 910000, (state->main / 910) % 1000); 3327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 333f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "main sound carrier: %d.%03d MHz\n", 3347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->main / 910000, (state->main / 910) % 1000); 3357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_FM_NICAM1 || state->mode == MSP_MODE_FM_NICAM2) 337f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "NICAM/FM carrier : %d.%03d MHz\n", 3387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second / 910000, (state->second/910) % 1000); 3397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_AM_NICAM) 340f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "NICAM/AM carrier : %d.%03d MHz\n", 3417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second / 910000, (state->second / 910) % 1000); 3427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_FM_TERRA && state->main != state->second) { 343f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "FM-stereo carrier : %d.%03d MHz\n", 3447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second / 910000, (state->second / 910) % 1000); 3457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 3477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* ----------------------------------------------------------------------- */ 3497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3508a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuilstatic int msp3400c_detect_stereo(struct i2c_client *client) 3517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 3527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 3537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int val; 3547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int rxsubchans = state->rxsubchans; 3558a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil int newnicam = state->nicam_on; 3567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int update = 0; 3577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (state->mode) { 3597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_TERRA: 3607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dsp(client, 0x18); 3617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val > 32767) 3627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val -= 65536; 363f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "stereo detect register: %d\n", val); 3647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val > 4096) { 3658a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil rxsubchans = V4L2_TUNER_SUB_STEREO; 3667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else if (val < -4096) { 3677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; 3687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 3697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO; 3707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil newnicam = 0; 3727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_NICAM1: 3747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_NICAM2: 3757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_AM_NICAM: 3767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dem(client, 0x23); 377f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "nicam sync=%d, mode=%d\n", 3787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val & 1, (val & 0x1e) >> 1); 3797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val & 1) { 3817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* nicam synced */ 3827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch ((val & 0x1e) >> 1) { 3837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0: 3847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 8: 3857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_STEREO; 3867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 1: 3887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 9: 3898a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO; 3907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 2: 3927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 10: 3938a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; 3947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 3967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO; 3977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil newnicam = 1; 4007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 4017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil newnicam = 0; 4027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO; 4037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (rxsubchans != state->rxsubchans) { 4077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil update = 1; 4088a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "watch: rxsubchans %02x => %02x\n", 4098a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->rxsubchans, rxsubchans); 4107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = rxsubchans; 4117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (newnicam != state->nicam_on) { 4137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil update = 1; 414f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "watch: nicam %d => %d\n", 4158a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->nicam_on, newnicam); 4167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = newnicam; 4177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return update; 4197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 4207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* 4227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * A kernel thread for msp3400 control -- we don't want to block the 4237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * in the ioctl while doing the sound carrier & stereo detect 4247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 4257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* stereo/multilang monitoring */ 4267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic void watch_stereo(struct i2c_client *client) 4277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 4287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 4297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4308a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil if (msp3400c_detect_stereo(client)) { 4318a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_audmode(client); 4327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 434f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_once) 4357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 0; 4367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 4377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilint msp3400c_thread(void *data) 4397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 4407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct i2c_client *client = data; 4417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 4427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp3400c_carrier_detect *cd; 4438a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil int count, max1, max2, val1, val2, val, this; 4447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 446f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n"); 4477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (;;) { 448f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n"); 4497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_sleep(state, -1); 450f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp3400 thread: wakeup\n"); 4517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil restart: 4538a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(2, msp_debug, client, "thread: restart scan\n"); 4547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->restart = 0; 4557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (kthread_should_stop()) 4567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4587560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil if (state->radio || MSP_MODE_EXTERN == state->mode) { 4597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* no carrier scan, just unmute */ 460f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n"); 4617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_audio(client); 4627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil continue; 4637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* mute */ 4667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_mute(client); 4678a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_AM_DETECT /* +1 */ ); 4687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val1 = val2 = 0; 4697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil max1 = max2 = -1; 4707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 0; 4718a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->nicam_on = 0; 4727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* some time for the tuner to sync */ 4748a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil if (msp_sleep(state, 200)) 4757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 4767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* carrier detect pass #1 -- main carrier */ 4787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = msp3400c_carrier_detect_main; 4797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = ARRAY_SIZE(msp3400c_carrier_detect_main); 4807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 481f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_amsound && (state->v4l2_std & V4L2_STD_SECAM)) { 4827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* autodetect doesn't work well with AM ... */ 4837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil max1 = 3; 4847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = 0; 485f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "AM sound override\n"); 4867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (this = 0; this < count; this++) { 4898a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, cd[this].cdo, cd[this].cdo); 4907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_sleep(state,100)) 4917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 4927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dsp(client, 0x1b); 4937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val > 32767) 4947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val -= 65536; 4957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val1 < val) 4967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val1 = val, max1 = this; 497f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "carrier1 val: %5d / %s\n", val,cd[this].name); 4987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* carrier detect pass #2 -- second (stereo) carrier */ 5017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (max1) { 5027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 1: /* 5.5 */ 5037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = msp3400c_carrier_detect_55; 5047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = ARRAY_SIZE(msp3400c_carrier_detect_55); 5057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 3: /* 6.5 */ 5077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = msp3400c_carrier_detect_65; 5087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = ARRAY_SIZE(msp3400c_carrier_detect_65); 5097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0: /* 4.5 */ 5117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 2: /* 6.0 */ 5127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 5137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = NULL; 5147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = 0; 5157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 518f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_amsound && (state->v4l2_std & V4L2_STD_SECAM)) { 5197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* autodetect doesn't work well with AM ... */ 5207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = NULL; 5217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = 0; 5227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil max2 = 0; 5237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (this = 0; this < count; this++) { 5258a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, cd[this].cdo, cd[this].cdo); 5267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_sleep(state,100)) 5277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 5287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dsp(client, 0x1b); 5297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val > 32767) 5307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val -= 65536; 5317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val2 < val) 5327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val2 = val, max2 = this; 533f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "carrier2 val: %5d / %s\n", val,cd[this].name); 5347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* program the msp3400 according to the results */ 5378a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->main = msp3400c_carrier_detect_main[max1].cdo; 5387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (max1) { 5397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 1: /* 5.5 */ 5407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (max2 == 0) { 5417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* B/G FM-stereo */ 5427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_55[max2].cdo; 5438a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_TERRA); 5447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 5457560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil } else if (max2 == 1 && state->has_nicam) { 5467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* B/G NICAM */ 5477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_55[max2].cdo; 5488a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_NICAM1); 5498a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, state->second, state->main); 5507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 5517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 5527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 5537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto no_second; 5547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 2: /* 6.0 */ 5577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* PAL I NICAM */ 5587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = MSP_CARRIER(6.552); 5598a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_NICAM2); 5608a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, state->second, state->main); 5617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 5627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 5637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 3: /* 6.5 */ 5657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (max2 == 1 || max2 == 2) { 5667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* D/K FM-stereo */ 5677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_65[max2].cdo; 5688a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_TERRA); 5697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 5705af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil } else if (max2 == 0 && (state->v4l2_std & V4L2_STD_SECAM)) { 5717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* L NICAM or AM-mono */ 5727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_65[max2].cdo; 5738a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_AM_NICAM); 5748a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, state->second, state->main); 5757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* volume prescale for SCART (AM mono input) */ 5767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x000d, 0x1900); 5777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 5787560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil } else if (max2 == 0 && state->has_nicam) { 5797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* D/K NICAM */ 5807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_65[max2].cdo; 5818a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_NICAM1); 5828a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, state->second, state->main); 5837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 5847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 5857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 5867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto no_second; 5877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0: /* 4.5 */ 5907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 5917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil no_second: 5927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_main[max1].cdo; 5938a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_TERRA); 5948a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, state->second, state->main); 5957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_MONO; 5967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* unmute */ 6007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_audio(client); 6018a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_audmode(client); 6027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 603f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_debug) 6047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_print_mode(client); 6057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6068a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil /* monitor tv audio mode, the first time don't wait 6078a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil so long to get a quick stereo/bilingual result */ 6088a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil if (msp_sleep(state, 1000)) 6098a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil goto restart; 6107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil while (state->watch_stereo) { 6118a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil if (msp_sleep(state, 5000)) 6127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 6137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil watch_stereo(client); 6147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 616f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: exit\n"); 6177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return 0; 6187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 6197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilint msp3410d_thread(void *data) 6227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 6237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct i2c_client *client = data; 6247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 625d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil int val, i, std; 6267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 627f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n"); 6287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (;;) { 630f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n"); 6317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_sleep(state,-1); 632f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp3410 thread: wakeup\n"); 6337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil restart: 6358a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(2, msp_debug, client, "thread: restart scan\n"); 6367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->restart = 0; 6377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (kthread_should_stop()) 6387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 6397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_EXTERN) { 6417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* no carrier scan needed, just unmute */ 642f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n"); 6437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_audio(client); 6447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil continue; 6457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* put into sane state (and mute) */ 6487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_reset(client); 6497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* some time for the tuner to sync */ 6517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_sleep(state,200)) 6527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 6537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* start autodetect */ 6555af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil if (state->radio) 6565af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil std = 0x40; 657d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil else 6585af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil std = (state->v4l2_std & V4L2_STD_NTSC) ? 0x20 : 1; 6597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 0; 6608a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->nicam_on = 0; 6617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 662f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_debug) 6638a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(2, msp_debug, client, "setting standard: %s (0x%04x)\n", 6645af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_standard_std_name(std), std); 6657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (std != 1) { 6677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* programmed some specific mode */ 6687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = std; 6697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 6707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* triggered autodetect */ 6715af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_write_dem(client, 0x20, std); 6727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (;;) { 673d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil if (msp_sleep(state, 100)) 6747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 6757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* check results */ 6777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dem(client, 0x7e); 6787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val < 0x07ff) 6797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 6808a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(2, msp_debug, client, "detection still in progress\n"); 6817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6835af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil for (i = 0; msp_stdlist[i].name != NULL; i++) 6845af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil if (msp_stdlist[i].retval == val) 6857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 686f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "current standard: %s (0x%04x)\n", 6875af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_standard_std_name(val), val); 6885af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil state->main = msp_stdlist[i].main; 6895af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil state->second = msp_stdlist[i].second; 6905af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil state->std = val; 6915af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil 692f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_amsound && !state->radio && (state->v4l2_std & V4L2_STD_SECAM) && 6935af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil (val != 0x0009)) { 6947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* autodetection has failed, let backup */ 695f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "autodetection failed," 6965af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil " switching to backup standard: %s (0x%04x)\n", 6975af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_stdlist[8].name ? msp_stdlist[8].name : "unknown",val); 6987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = 0x0009; 6997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x20, val); 7007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* set various prescales */ 7037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x0d, 0x1900); /* scart */ 7047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x0e, 0x2403); /* FM */ 7057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x10, 0x5a00); /* nicam */ 7067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* set stereo */ 7087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (val) { 7097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0008: /* B/G NICAM */ 7107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x000a: /* I NICAM */ 7117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val == 0x0008) 7127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->mode = MSP_MODE_FM_NICAM1; 7137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil else 7147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->mode = MSP_MODE_FM_NICAM2; 7157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* just turn on stereo */ 7167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_STEREO; 7177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 7187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 7197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0009: 7217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->mode = MSP_MODE_AM_NICAM; 7227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_MONO; 7237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 7247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 7257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0020: /* BTSC */ 7278a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil /* The pre-'G' models only have BTSC-mono */ 7287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->mode = MSP_MODE_BTSC; 7298a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->rxsubchans = V4L2_TUNER_SUB_MONO; 7307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0040: /* FM radio */ 7327560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil state->mode = MSP_MODE_FM_RADIO; 7337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_STEREO; 7347560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil /* not needed in theory if we have radio, but 7357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil short programming enables carrier mute */ 7368a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_RADIO); 7378a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, MSP_CARRIER(10.7), 7387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(10.7)); 7398a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil /* scart routing (this doesn't belong here I think) */ 7407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_scart(client,SCART_IN2,0); 7417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0003: 7437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0004: 7447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0005: 7455af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil state->mode = MSP_MODE_FM_TERRA; 7467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_MONO; 7477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 7487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* unmute, restore misc registers */ 7527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_audio(client); 7537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x13, state->acb); 7545af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil if (state->has_i2s_conf) 7555af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_write_dem(client, 0x40, state->i2s_mode); 7567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7578a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_audmode(client); 7588a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 7598a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil /* monitor tv audio mode, the first time don't wait 7608a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil so long to get a quick stereo/bilingual result */ 7618a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil if (msp_sleep(state, 1000)) 7628a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil goto restart; 7637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil while (state->watch_stereo) { 7647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil watch_stereo(client); 7658a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil if (msp_sleep(state, 5000)) 7668a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil goto restart; 7677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 769f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: exit\n"); 7707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return 0; 7717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 7727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* ----------------------------------------------------------------------- */ 7747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 775f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab/* msp34xxG + (autoselect no-thread) */ 7767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* this one uses both automatic standard detection and automatic sound */ 7777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* select which are available in the newer G versions */ 7787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* struct msp: only norm, acb and source are really used in this mode */ 7797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* set the same 'source' for the loudspeaker, scart and quasi-peak detector 7817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * the value for source is the same as bit 15:8 of DSP registers 0x08, 7827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * 0x0a and 0x0c: 0=mono, 1=stereo or A|B, 2=SCART, 3=stereo or A, 4=stereo or B 7837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * 7848a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil * this function replaces msp3400c_set_audmode 7857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 7867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic void msp34xxg_set_source(struct i2c_client *client, int source) 7877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 7887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 7897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* fix matrix mode to stereo and let the msp choose what 7917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * to output according to 'source', as recommended 7927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * for MONO (source==0) downmixing set bit[7:0] to 0x30 7937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 7947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int value = (source & 0x07) << 8 | (source == 0 ? 0x30 : 0x20); 7957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 796f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "set source to %d (0x%x)\n", source, value); 7978a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_set_source(client, value); 7987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* 7997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * set identification threshold. Personally, I 8007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * I set it to a higher value that the default 8017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * of 0x190 to ignore noisy stereo signals. 8027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * this needs tuning. (recommended range 0x00a0-0x03c0) 8037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * 0x7f0 = forced mono mode 8047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 8057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* a2 threshold for stereo/bilingual */ 806f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab msp_write_dem(client, 0x22, msp_stereo_thresh); 8077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->source = source; 8087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 8097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* (re-)initialize the msp34xxg, according to the current norm in state->norm 8117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * return 0 if it worked, -1 if it failed 8127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 8137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic int msp34xxg_reset(struct i2c_client *client) 8147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 8157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 8167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int modus, std; 8177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_reset(client)) 8197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return -1; 8207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* make sure that input/output is muted (paranoid mode) */ 8227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* ACB, mute DSP input, mute SCART 1 */ 8237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_write_dsp(client, 0x13, 0x0f20)) 8247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return -1; 8257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8265af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil if (state->has_i2s_conf) 8275af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_write_dem(client, 0x40, state->i2s_mode); 8287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* step-by-step initialisation, as described in the manual */ 8307560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil modus = msp_modus(client); 8317560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil if (state->radio) 8327560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil std = 0x40; 8337560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil else 8345af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil std = (state->v4l2_std & V4L2_STD_NTSC) ? 0x20 : 1; 8357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil modus &= ~0x03; /* STATUS_CHANGE = 0 */ 8367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil modus |= 0x01; /* AUTOMATIC_SOUND_DETECTION = 1 */ 8377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_write_dem(client, 0x30, modus)) 8387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return -1; 8397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_write_dem(client, 0x20, std)) 8407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return -1; 8417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* write the dsps that may have an influence on 8437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil standard/audio autodetection right now */ 8447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp34xxg_set_source(client, state->source); 8457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* AM/FM Prescale [15:8] 75khz deviation */ 8477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_write_dsp(client, 0x0e, 0x3000)) 8487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return -1; 8497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* NICAM Prescale 9db gain (as recommended) */ 8517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_write_dsp(client, 0x10, 0x5a00)) 8527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return -1; 8537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return 0; 8557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 8567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilint msp34xxg_thread(void *data) 8587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 8597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct i2c_client *client = data; 8607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 8617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int val, std, i; 8627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 863f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n"); 8647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->source = 1; /* default */ 8667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (;;) { 867f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n"); 8687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_sleep(state, -1); 869f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp34xxg thread: wakeup\n"); 8707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil restart: 872f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: restart scan\n"); 8737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->restart = 0; 8747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (kthread_should_stop()) 8757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 8767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* setup the chip*/ 8787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp34xxg_reset(client); 879f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab std = msp_standard; 8807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (std != 0x01) 8817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto unmute; 8827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* watch autodetect */ 884f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "triggered autodetect, waiting for result\n"); 8857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (i = 0; i < 10; i++) { 8867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_sleep(state, 100)) 8877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 8887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* check results */ 8907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dem(client, 0x7e); 8917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val < 0x07ff) { 8927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil std = val; 8937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 8947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 895f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "detection still in progress\n"); 8967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 8977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (std == 1) { 898f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "detection still in progress after 10 tries. giving up.\n"); 8997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil continue; 9007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 9017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil unmute: 9035af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil state->std = std; 904f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "current standard: %s (0x%04x)\n", 9055af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_standard_std_name(std), std); 9067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* unmute: dispatch sound to scart output, set scart volume */ 9087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_audio(client); 9097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* restore ACB */ 9117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_write_dsp(client, 0x13, state->acb)) 9127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return -1; 9137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9148a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil if (state->has_i2s_conf) 9158a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dem(client, 0x40, state->i2s_mode); 9167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 917f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: exit\n"); 9187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return 0; 9197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 9207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9218a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuilstatic void msp34xxg_detect_stereo(struct i2c_client *client) 9227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 9237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 9247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int status = msp_read_dem(client, 0x0200); 9267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int is_bilingual = status & 0x100; 9277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int is_stereo = status & 0x40; 9287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = 0; 9307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (is_stereo) 9318a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->rxsubchans = V4L2_TUNER_SUB_STEREO; 9327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil else 9338a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->rxsubchans = V4L2_TUNER_SUB_MONO; 9347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (is_bilingual) { 9358a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; 9367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* I'm supposed to check whether it's SAP or not 9377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * and set only LANG2/SAP in this case. Yet, the MSP 9387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * does a lot of work to hide this and handle everything 9397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * the same way. I don't want to work around it so unless 9407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * this is a problem, I'll handle SAP just like lang1/lang2. 9417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 9427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 943f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n", 9447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil status, is_stereo, is_bilingual, state->rxsubchans); 9457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 9467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 947044f324f6ea5d55391db62fca6a295b2651cb946Adrian Bunkstatic void msp34xxg_set_audmode(struct i2c_client *client) 9487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 9497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 9507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int source; 9517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9528a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil switch (state->audmode) { 9537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_MONO: 9547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil source = 0; /* mono only */ 9557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 9567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_STEREO: 9577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil source = 1; /* stereo or A|B, see comment in msp34xxg_get_v4l2_stereo() */ 9587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* problem: that could also mean 2 (scart input) */ 9597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 9607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG1: 9617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil source = 3; /* stereo or A */ 9627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 9637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG2: 9647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil source = 4; /* stereo or B */ 9657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 9667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 9677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil source = 1; 9687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 9697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 9707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp34xxg_set_source(client, source); 9717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 9727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9738a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuilvoid msp_set_audmode(struct i2c_client *client) 9748a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil{ 9758a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil struct msp_state *state = i2c_get_clientdata(client); 9768a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 9778a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil switch (state->opmode) { 9788a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_MANUAL: 9798a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_AUTODETECT: 9808a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->watch_stereo = 0; 9818a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_audmode(client); 9828a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil break; 9838a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_AUTOSELECT: 9848a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp34xxg_set_audmode(client); 9858a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil break; 9868a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil } 9878a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil} 9888a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 9898a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuilvoid msp_detect_stereo(struct i2c_client *client) 9908a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil{ 9918a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil struct msp_state *state = i2c_get_clientdata(client); 9928a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 9938a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil switch (state->opmode) { 9948a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_MANUAL: 9958a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_AUTODETECT: 9968a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_detect_stereo(client); 9978a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil break; 9988a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_AUTOSELECT: 9998a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp34xxg_detect_stereo(client); 10008a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil break; 10018a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil } 10028a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil} 10038a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 1004