msp3400-kthreads.c revision 2eb606db1134ce860cc0cbf8b533b6315d182e21
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> 2949965a80a4c4f5cbe15fb3bb1f8f8b0ec4ef02bcHans Verkuil#include <media/msp3400.h> 307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <linux/kthread.h> 317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <linux/suspend.h> 3249965a80a4c4f5cbe15fb3bb1f8f8b0ec4ef02bcHans Verkuil#include "msp3400-driver.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)" }, 48de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil { 0x0007, MSP_CARRIER(6.5), MSP_CARRIER(5.7421875), "6.5/5.74 D/K3 Dual FM-Stereo" }, 497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), "5.5/5.85 B/G NICAM FM" }, 507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 L NICAM AM" }, 517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), "6.0/6.55 I NICAM FM" }, 527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM" }, 537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV2)" }, 54de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil { 0x000d, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV3)" }, 557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Stereo" }, 567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Mono + SAP" }, 577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M EIA-J Japan Stereo" }, 587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7), "10.7 FM-Stereo Radio" }, 597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 SAT-Mono" }, 607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20), "7.02/7.20 SAT-Stereo" }, 617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2), "7.2 SAT ADR" }, 627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { -1, 0, 0, NULL }, /* EOF */ 637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic struct msp3400c_init_data_dem { 667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int fir1[6]; 677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int fir2[6]; 687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int cdo1; 697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int cdo2; 707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int ad_cv; 717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int mode_reg; 727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int dsp_src; 737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int dsp_matrix; 747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} msp3400c_init_data[] = { 757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { /* AM (for carrier detect / msp3400) */ 767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {75, 19, 36, 35, 39, 40}, 777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {75, 19, 36, 35, 39, 40}, 787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(5.5), MSP_CARRIER(5.5), 797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0500, 0x0020, 0x3000 807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil },{ /* AM (for carrier detect / msp3410) */ 817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-1, -1, -8, 2, 59, 126}, 827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-1, -1, -8, 2, 59, 126}, 837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(5.5), MSP_CARRIER(5.5), 847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0100, 0x0020, 0x3000 857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil },{ /* FM Radio */ 867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-8, -8, 4, 6, 78, 107}, 877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-8, -8, 4, 6, 78, 107}, 887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(10.7), MSP_CARRIER(10.7), 897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0480, 0x0020, 0x3000 907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil },{ /* Terrestial FM-mono + FM-stereo */ 917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {3, 18, 27, 48, 66, 72}, 927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {3, 18, 27, 48, 66, 72}, 937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(5.5), MSP_CARRIER(5.5), 947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0480, 0x0030, 0x3000 957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil },{ /* Sat FM-mono */ 967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 1, 9, 14, 24, 33, 37}, 977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 3, 18, 27, 48, 66, 72}, 987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(6.5), MSP_CARRIER(6.5), 997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00c6, 0x0480, 0x0000, 0x3000 1007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil },{ /* NICAM/FM -- B/G (5.5/5.85), D/K (6.5/5.85) */ 1017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-2, -8, -10, 10, 50, 86}, 1027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {3, 18, 27, 48, 66, 72}, 1037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(5.5), MSP_CARRIER(5.5), 1047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0040, 0x0120, 0x3000 1057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil },{ /* NICAM/FM -- I (6.0/6.552) */ 1067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {2, 4, -6, -4, 40, 94}, 1077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {3, 18, 27, 48, 66, 72}, 1087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(6.0), MSP_CARRIER(6.0), 1097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0040, 0x0120, 0x3000 1107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil },{ /* NICAM/AM -- L (6.5/5.85) */ 1117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-2, -8, -10, 10, 50, 86}, 1127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-4, -12, -9, 23, 79, 126}, 1137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(6.5), MSP_CARRIER(6.5), 1148a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 0x00c6, 0x0140, 0x0120, 0x7c00 1157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil }, 1167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 1177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstruct msp3400c_carrier_detect { 1197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int cdo; 1207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil char *name; 1217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 1227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic struct msp3400c_carrier_detect msp3400c_carrier_detect_main[] = { 1247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* main carrier */ 1257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(4.5), "4.5 NTSC" }, 1267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(5.5), "5.5 PAL B/G" }, 1277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(6.0), "6.0 PAL I" }, 1287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(6.5), "6.5 PAL D/K + SAT + SECAM" } 1297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 1307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic struct msp3400c_carrier_detect msp3400c_carrier_detect_55[] = { 1327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* PAL B/G */ 1337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(5.7421875), "5.742 PAL B/G FM-stereo" }, 1347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(5.85), "5.85 PAL B/G NICAM" } 1357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 1367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic struct msp3400c_carrier_detect msp3400c_carrier_detect_65[] = { 1387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* PAL SAT / SECAM */ 1397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(5.85), "5.85 PAL D/K + SECAM NICAM" }, 1407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(6.2578125), "6.25 PAL D/K1 FM-stereo" }, 1417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(6.7421875), "6.74 PAL D/K2 FM-stereo" }, 1427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(7.02), "7.02 PAL SAT FM-stereo s/b" }, 1437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(7.20), "7.20 PAL SAT FM-stereo s" }, 1447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(7.38), "7.38 PAL SAT FM-stereo b" }, 1457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 1467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* ------------------------------------------------------------------------ */ 1487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1495af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuilconst char *msp_standard_std_name(int std) 1507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 1517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int i; 1527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1535af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil for (i = 0; msp_stdlist[i].name != NULL; i++) 1545af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil if (msp_stdlist[i].retval == std) 1555af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil return msp_stdlist[i].name; 1567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return "unknown"; 1577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 1587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 159044f324f6ea5d55391db62fca6a295b2651cb946Adrian Bunkstatic void msp_set_source(struct i2c_client *client, u16 src) 1608a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil{ 1618a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil struct msp_state *state = i2c_get_clientdata(client); 1628a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 1638a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil if (msp_dolby) { 1648a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x0008, 0x0520); /* I2S1 */ 1658a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x0009, 0x0620); /* I2S2 */ 1668a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil } else { 1678a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x0008, src); 1688a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x0009, src); 1698a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil } 1708a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x000a, src); 1718a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x000b, src); 1728a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x000c, src); 1730020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil if (state->has_scart2_out) 1748a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x0041, src); 1758a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil} 1768a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 1778a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuilvoid msp3400c_set_carrier(struct i2c_client *client, int cdo1, int cdo2) 1787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 1797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x0093, cdo1 & 0xfff); 1807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x009b, cdo1 >> 12); 1817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x00a3, cdo2 & 0xfff); 1827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x00ab, cdo2 >> 12); 1838a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dem(client, 0x0056, 0); /* LOAD_REG_1/2 */ 1847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 1857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1868a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuilvoid msp3400c_set_mode(struct i2c_client *client, int mode) 1877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 1887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 1898a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil struct msp3400c_init_data_dem *data = &msp3400c_init_data[mode]; 1902474ed444b475614ef795523076be7cc8437ae00Hans Verkuil int tuner = (state->routing.input >> 3) & 1; 1917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int i; 1927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1938a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "set_mode: %d\n", mode); 1948a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->mode = mode; 1957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_MONO; 1967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1972474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp_write_dem(client, 0x00bb, data->ad_cv | (tuner ? 0x100 : 0)); 1987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (i = 5; i >= 0; i--) /* fir 1 */ 2008a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dem(client, 0x0001, data->fir1[i]); 2017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x0005, 0x0004); /* fir 2 */ 2037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x0005, 0x0040); 2047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x0005, 0x0000); 2057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (i = 5; i >= 0; i--) 2068a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dem(client, 0x0005, data->fir2[i]); 2077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2088a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dem(client, 0x0083, data->mode_reg); 2097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2108a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, data->cdo1, data->cdo2); 2117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2128a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_set_source(client, data->dsp_src); 213de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* set prescales */ 2147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 215de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* volume prescale for SCART (AM mono input) */ 216de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x000d, 0x1900); 217de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x000e, data->dsp_matrix); 218de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->has_nicam) /* nicam prescale */ 219de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x0010, 0x5a00); 2207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 2217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2228a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil/* Set audio mode. Note that the pre-'G' models do not support BTSC+SAP, 2238a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil nor do they support stereo BTSC. */ 224044f324f6ea5d55391db62fca6a295b2651cb946Adrian Bunkstatic void msp3400c_set_audmode(struct i2c_client *client) 2257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 226301e22d69140898eddd38a9134da711cb5dfc170Hans Verkuil static char *strmode[] = { "mono", "stereo", "lang2", "lang1", "lang1+lang2" }; 2277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 228301e22d69140898eddd38a9134da711cb5dfc170Hans Verkuil char *modestr = (state->audmode >= 0 && state->audmode < 5) ? 2298a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil strmode[state->audmode] : "unknown"; 2308a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil int src = 0; /* channel source: FM/AM, nicam or SCART */ 2317061561e640c2947ab93c4e2a437327657c4482eHans Verkuil int audmode = state->audmode; 2327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->opmode == OPMODE_AUTOSELECT) { 2347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* this method would break everything, let's make sure 2357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * it's never called 2367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 2378a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, 2388a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil "set_audmode called with mode=%d instead of set_source (ignored)\n", 2398a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->audmode); 2407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return; 2417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 2427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2430020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil /* Note: for the C and D revs no NTSC stereo + SAP is possible as 2440020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil the hardware does not support SAP. So the rxsubchans combination 2450020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil of STEREO | LANG2 does not occur. */ 2460020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil 2472eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil if (state->mode != MSP_MODE_EXTERN) { 2482eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil /* switch to mono if only mono is available */ 2492eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil if (state->rxsubchans == V4L2_TUNER_SUB_MONO) 2502eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil audmode = V4L2_TUNER_MODE_MONO; 2512eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil /* if bilingual */ 2522eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil else if (state->rxsubchans & V4L2_TUNER_SUB_LANG2) { 2532eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil /* and mono or stereo, then fallback to lang1 */ 2542eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil if (audmode == V4L2_TUNER_MODE_MONO || 2552eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil audmode == V4L2_TUNER_MODE_STEREO) 2562eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil audmode = V4L2_TUNER_MODE_LANG1; 2572eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil } 2582eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil /* if stereo, and audmode is not mono, then switch to stereo */ 2592eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil else if (audmode != V4L2_TUNER_MODE_MONO) 2602eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil audmode = V4L2_TUNER_MODE_STEREO; 2610020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil } 2627061561e640c2947ab93c4e2a437327657c4482eHans Verkuil 2637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* switch demodulator */ 2647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (state->mode) { 2657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_TERRA: 2668a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "FM set_audmode: %s\n", modestr); 2677061561e640c2947ab93c4e2a437327657c4482eHans Verkuil switch (audmode) { 2687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_STEREO: 2697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x000e, 0x3001); 2707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_MONO: 2727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG1: 2737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG2: 274301e22d69140898eddd38a9134da711cb5dfc170Hans Verkuil case V4L2_TUNER_MODE_LANG1_LANG2: 2757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x000e, 0x3000); 2767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 2787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_SAT: 2808a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "SAT set_audmode: %s\n", modestr); 2817061561e640c2947ab93c4e2a437327657c4482eHans Verkuil switch (audmode) { 2827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_MONO: 2838a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5)); 2847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_STEREO: 286301e22d69140898eddd38a9134da711cb5dfc170Hans Verkuil case V4L2_TUNER_MODE_LANG1_LANG2: 2878a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02)); 2887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG1: 2908a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); 2917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG2: 2938a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); 2947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 2967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_NICAM1: 2987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_NICAM2: 2997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_AM_NICAM: 3008a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "NICAM set_audmode: %s\n",modestr); 3017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->nicam_on) 3028a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil src = 0x0100; /* NICAM */ 3037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_BTSC: 3058a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "BTSC set_audmode: %s\n",modestr); 3067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_EXTERN: 3088a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "extern set_audmode: %s\n",modestr); 3098a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil src = 0x0200; /* SCART */ 3107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_RADIO: 3128a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "FM-Radio set_audmode: %s\n",modestr); 3137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 3158a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "mono set_audmode\n"); 3167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return; 3177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* switch audio */ 3200020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil v4l_dbg(1, msp_debug, client, "set audmode %d\n", audmode); 3217061561e640c2947ab93c4e2a437327657c4482eHans Verkuil switch (audmode) { 3227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_STEREO: 323301e22d69140898eddd38a9134da711cb5dfc170Hans Verkuil case V4L2_TUNER_MODE_LANG1_LANG2: 3248a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil src |= 0x0020; 3257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_MONO: 3277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_AM_NICAM) { 328f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "switching to AM mono\n"); 3297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* AM mono decoding is handled by tuner, not MSP chip */ 3307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* SCART switching control register */ 3317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_scart(client, SCART_MONO, 0); 3327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil src = 0x0200; 3337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3358a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil if (state->rxsubchans & V4L2_TUNER_SUB_STEREO) 3368a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil src = 0x0030; 3378a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil break; 3387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG1: 3397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG2: 3418a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil src |= 0x0010; 3427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3448a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "set_audmode final source/matrix = 0x%x\n", src); 3457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3468a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_set_source(client, src); 3477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 3487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic void msp3400c_print_mode(struct i2c_client *client) 3507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 3517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 3527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->main == state->second) { 354f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "mono sound carrier: %d.%03d MHz\n", 3557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->main / 910000, (state->main / 910) % 1000); 3567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 357f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "main sound carrier: %d.%03d MHz\n", 3587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->main / 910000, (state->main / 910) % 1000); 3597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_FM_NICAM1 || state->mode == MSP_MODE_FM_NICAM2) 361f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "NICAM/FM carrier : %d.%03d MHz\n", 3627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second / 910000, (state->second/910) % 1000); 3637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_AM_NICAM) 364f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "NICAM/AM carrier : %d.%03d MHz\n", 3657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second / 910000, (state->second / 910) % 1000); 3667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_FM_TERRA && state->main != state->second) { 367f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "FM-stereo carrier : %d.%03d MHz\n", 3687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second / 910000, (state->second / 910) % 1000); 3697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 3717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* ----------------------------------------------------------------------- */ 3737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3748a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuilstatic int msp3400c_detect_stereo(struct i2c_client *client) 3757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 3767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 3777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int val; 3787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int rxsubchans = state->rxsubchans; 3798a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil int newnicam = state->nicam_on; 3807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int update = 0; 3817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (state->mode) { 3837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_TERRA: 3847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dsp(client, 0x18); 3857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val > 32767) 3867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val -= 65536; 387f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "stereo detect register: %d\n", val); 3883bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil if (val > 8192) { 3898a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil rxsubchans = V4L2_TUNER_SUB_STEREO; 3907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else if (val < -4096) { 3917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; 3927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 3937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO; 3947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil newnicam = 0; 3967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_NICAM1: 3987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_NICAM2: 3997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_AM_NICAM: 4007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dem(client, 0x23); 401f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "nicam sync=%d, mode=%d\n", 4027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val & 1, (val & 0x1e) >> 1); 4037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val & 1) { 4057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* nicam synced */ 4067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch ((val & 0x1e) >> 1) { 4077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0: 4087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 8: 4097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_STEREO; 4107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 1: 4127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 9: 4138a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO; 4147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 2: 4167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 10: 4178a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; 4187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 4207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO; 4217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil newnicam = 1; 4247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 4257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil newnicam = 0; 4267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO; 4277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (rxsubchans != state->rxsubchans) { 4317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil update = 1; 4328a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "watch: rxsubchans %02x => %02x\n", 4338a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->rxsubchans, rxsubchans); 4347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = rxsubchans; 4357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (newnicam != state->nicam_on) { 4377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil update = 1; 438f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "watch: nicam %d => %d\n", 4398a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->nicam_on, newnicam); 4407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = newnicam; 4417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return update; 4437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 4447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* 4467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * A kernel thread for msp3400 control -- we don't want to block the 4477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * in the ioctl while doing the sound carrier & stereo detect 4487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 4497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* stereo/multilang monitoring */ 4507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic void watch_stereo(struct i2c_client *client) 4517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 4527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 4537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 454de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (msp_detect_stereo(client)) { 455de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_set_audmode(client); 4567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 458f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_once) 4597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 0; 4607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 4617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilint msp3400c_thread(void *data) 4637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 4647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct i2c_client *client = data; 4657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 4667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp3400c_carrier_detect *cd; 4678a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil int count, max1, max2, val1, val2, val, this; 4687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 470f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n"); 4717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (;;) { 472f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n"); 4737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_sleep(state, -1); 474f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp3400 thread: wakeup\n"); 4757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil restart: 4778a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(2, msp_debug, client, "thread: restart scan\n"); 4787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->restart = 0; 4797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (kthread_should_stop()) 4807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4827560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil if (state->radio || MSP_MODE_EXTERN == state->mode) { 4837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* no carrier scan, just unmute */ 484f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n"); 4853bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil state->scan_in_progress = 0; 4862eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_STEREO; 4877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_audio(client); 4887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil continue; 4897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4913bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil /* mute audio */ 4923bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil state->scan_in_progress = 1; 4933bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil msp_set_audio(client); 4940020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil 495de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp3400c_set_mode(client, MSP_MODE_AM_DETECT); 4967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val1 = val2 = 0; 4977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil max1 = max2 = -1; 4987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 0; 4998a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->nicam_on = 0; 5007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5013bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil /* wait for tuner to settle down after a channel change */ 5028a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil if (msp_sleep(state, 200)) 5037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 5047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* carrier detect pass #1 -- main carrier */ 5067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = msp3400c_carrier_detect_main; 5077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = ARRAY_SIZE(msp3400c_carrier_detect_main); 5087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 509f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_amsound && (state->v4l2_std & V4L2_STD_SECAM)) { 5107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* autodetect doesn't work well with AM ... */ 5117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil max1 = 3; 5127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = 0; 513f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "AM sound override\n"); 5147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (this = 0; this < count; this++) { 5178a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, cd[this].cdo, cd[this].cdo); 5187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_sleep(state,100)) 5197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 5207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dsp(client, 0x1b); 5217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val > 32767) 5227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val -= 65536; 5237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val1 < val) 5247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val1 = val, max1 = this; 525f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "carrier1 val: %5d / %s\n", val,cd[this].name); 5267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* carrier detect pass #2 -- second (stereo) carrier */ 5297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (max1) { 5307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 1: /* 5.5 */ 5317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = msp3400c_carrier_detect_55; 5327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = ARRAY_SIZE(msp3400c_carrier_detect_55); 5337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 3: /* 6.5 */ 5357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = msp3400c_carrier_detect_65; 5367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = ARRAY_SIZE(msp3400c_carrier_detect_65); 5377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0: /* 4.5 */ 5397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 2: /* 6.0 */ 5407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 5417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = NULL; 5427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = 0; 5437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 546f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_amsound && (state->v4l2_std & V4L2_STD_SECAM)) { 5477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* autodetect doesn't work well with AM ... */ 5487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = NULL; 5497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = 0; 5507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil max2 = 0; 5517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (this = 0; this < count; this++) { 5538a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, cd[this].cdo, cd[this].cdo); 5547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_sleep(state,100)) 5557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 5567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dsp(client, 0x1b); 5577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val > 32767) 5587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val -= 65536; 5597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val2 < val) 5607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val2 = val, max2 = this; 561f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "carrier2 val: %5d / %s\n", val,cd[this].name); 5627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* program the msp3400 according to the results */ 5658a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->main = msp3400c_carrier_detect_main[max1].cdo; 5667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (max1) { 5677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 1: /* 5.5 */ 5687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (max2 == 0) { 5697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* B/G FM-stereo */ 5707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_55[max2].cdo; 5718a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_TERRA); 5727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 5737560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil } else if (max2 == 1 && state->has_nicam) { 5747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* B/G NICAM */ 5757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_55[max2].cdo; 5768a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_NICAM1); 5777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 5787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 5797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 5807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto no_second; 5817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 2: /* 6.0 */ 5847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* PAL I NICAM */ 5857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = MSP_CARRIER(6.552); 5868a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_NICAM2); 5877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 5887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 5897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 3: /* 6.5 */ 5917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (max2 == 1 || max2 == 2) { 5927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* D/K FM-stereo */ 5937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_65[max2].cdo; 5948a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_TERRA); 5957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 5965af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil } else if (max2 == 0 && (state->v4l2_std & V4L2_STD_SECAM)) { 5977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* L NICAM or AM-mono */ 5987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_65[max2].cdo; 5998a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_AM_NICAM); 6007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 6017560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil } else if (max2 == 0 && state->has_nicam) { 6027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* D/K NICAM */ 6037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_65[max2].cdo; 6048a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_NICAM1); 6057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 6067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 6077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 6087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto no_second; 6097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 6117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0: /* 4.5 */ 6127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 6137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil no_second: 6147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_main[max1].cdo; 6158a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_TERRA); 6167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 6177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6180020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil msp3400c_set_carrier(client, state->second, state->main); 6197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6203bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil /* unmute */ 6213bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil state->scan_in_progress = 0; 6228a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_audmode(client); 6233bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil msp_set_audio(client); 6247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 625f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_debug) 6267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_print_mode(client); 6277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6288a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil /* monitor tv audio mode, the first time don't wait 6298a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil so long to get a quick stereo/bilingual result */ 6303bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil count = 3; 6317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil while (state->watch_stereo) { 6323bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil if (msp_sleep(state, count ? 1000 : 5000)) 6337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 6340020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil if (count) count--; 6353bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil watch_stereo(client); 6367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 638f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: exit\n"); 6397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return 0; 6407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 6417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilint msp3410d_thread(void *data) 6447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 6457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct i2c_client *client = data; 6467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 6470020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil int val, i, std, count; 6487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 649f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n"); 6507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (;;) { 652f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n"); 6537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_sleep(state,-1); 654f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp3410 thread: wakeup\n"); 6557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil restart: 6578a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(2, msp_debug, client, "thread: restart scan\n"); 6587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->restart = 0; 6597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (kthread_should_stop()) 6607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 6617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_EXTERN) { 6637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* no carrier scan needed, just unmute */ 664f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n"); 6653bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil state->scan_in_progress = 0; 6667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_audio(client); 6677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil continue; 6687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6703bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil /* mute audio */ 6713bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil state->scan_in_progress = 1; 6723bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil msp_set_audio(client); 6737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 674de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* start autodetect. Note: autodetect is not supported for 675de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil NTSC-M and radio, hence we force the standard in those cases. */ 6765af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil if (state->radio) 6775af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil std = 0x40; 678d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil else 6795af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil std = (state->v4l2_std & V4L2_STD_NTSC) ? 0x20 : 1; 6807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 0; 6818a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->nicam_on = 0; 6827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6833bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil /* wait for tuner to settle down after a channel change */ 6843bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil if (msp_sleep(state, 200)) 6853bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil goto restart; 6863bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil 687f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_debug) 6888a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(2, msp_debug, client, "setting standard: %s (0x%04x)\n", 6895af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_standard_std_name(std), std); 6907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (std != 1) { 6927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* programmed some specific mode */ 6937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = std; 6947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 6957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* triggered autodetect */ 6965af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_write_dem(client, 0x20, std); 6977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (;;) { 698d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil if (msp_sleep(state, 100)) 6997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 7007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* check results */ 7027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dem(client, 0x7e); 7037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val < 0x07ff) 7047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7058a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(2, msp_debug, client, "detection still in progress\n"); 7067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7085af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil for (i = 0; msp_stdlist[i].name != NULL; i++) 7095af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil if (msp_stdlist[i].retval == val) 7107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 711f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "current standard: %s (0x%04x)\n", 7125af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_standard_std_name(val), val); 7135af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil state->main = msp_stdlist[i].main; 7145af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil state->second = msp_stdlist[i].second; 7155af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil state->std = val; 7163bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_MONO; 7175af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil 718f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_amsound && !state->radio && (state->v4l2_std & V4L2_STD_SECAM) && 7195af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil (val != 0x0009)) { 7207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* autodetection has failed, let backup */ 721f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "autodetection failed," 7225af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil " switching to backup standard: %s (0x%04x)\n", 7235af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_stdlist[8].name ? msp_stdlist[8].name : "unknown",val); 724de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->std = val = 0x0009; 7257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x20, val); 7267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* set stereo */ 7297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (val) { 7307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0008: /* B/G NICAM */ 7317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x000a: /* I NICAM */ 732de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil case 0x000b: /* D/K NICAM */ 733de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (val == 0x000a) 7347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->mode = MSP_MODE_FM_NICAM2; 735de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil else 736de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->mode = MSP_MODE_FM_NICAM1; 7377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* just turn on stereo */ 7387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 7397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 7407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0009: 7427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->mode = MSP_MODE_AM_NICAM; 7437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 7447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 7457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0020: /* BTSC */ 7478a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil /* The pre-'G' models only have BTSC-mono */ 7487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->mode = MSP_MODE_BTSC; 7497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0040: /* FM radio */ 7517560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil state->mode = MSP_MODE_FM_RADIO; 7527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_STEREO; 7537560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil /* not needed in theory if we have radio, but 7547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil short programming enables carrier mute */ 7558a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_RADIO); 7568a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, MSP_CARRIER(10.7), 7577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(10.7)); 7587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 759de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil case 0x0002: 7607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0003: 7617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0004: 7627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0005: 7635af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil state->mode = MSP_MODE_FM_TERRA; 7647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 7657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 768de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* set various prescales */ 769de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x0d, 0x1900); /* scart */ 770de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x0e, 0x3000); /* FM */ 771de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->has_nicam) 772de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x10, 0x5a00); /* nicam */ 773de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil 7745af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil if (state->has_i2s_conf) 7755af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_write_dem(client, 0x40, state->i2s_mode); 7767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7773bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil /* unmute */ 7788a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_audmode(client); 7793bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil state->scan_in_progress = 0; 7803bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil msp_set_audio(client); 7818a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 7828a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil /* monitor tv audio mode, the first time don't wait 7838a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil so long to get a quick stereo/bilingual result */ 7843bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil count = 3; 7857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil while (state->watch_stereo) { 7863bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil if (msp_sleep(state, count ? 1000 : 5000)) 7878a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil goto restart; 7880020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil if (count) count--; 7893bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil watch_stereo(client); 7907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 792f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: exit\n"); 7937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return 0; 7947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 7957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* ----------------------------------------------------------------------- */ 7977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 798de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil/* msp34xxG + (autoselect no-thread) 799de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * this one uses both automatic standard detection and automatic sound 800de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * select which are available in the newer G versions 801de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * struct msp: only norm, acb and source are really used in this mode 802de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil */ 8037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8049a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuilstatic int msp34xxg_modus(struct i2c_client *client) 8059a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil{ 8069a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 8079a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil 8089a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil if (state->radio) { 8099a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil v4l_dbg(1, msp_debug, client, "selected radio modus\n"); 8109a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil return 0x0001; 8119a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil } 8129a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil 8139a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil if (state->v4l2_std & V4L2_STD_PAL) { 8149a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil v4l_dbg(1, msp_debug, client, "selected PAL modus\n"); 8159a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil return 0x7001; 8169a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil } 8179a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil if (state->v4l2_std == V4L2_STD_NTSC_M_JP) { 8189a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil v4l_dbg(1, msp_debug, client, "selected M (EIA-J) modus\n"); 8199a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil return 0x4001; 8209a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil } 8219a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil if (state->v4l2_std == V4L2_STD_NTSC_M_KR) { 8229a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil v4l_dbg(1, msp_debug, client, "selected M (A2) modus\n"); 8239a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil return 0x0001; 8249a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil } 8259a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil if (state->v4l2_std & V4L2_STD_MN) { 8269a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil v4l_dbg(1, msp_debug, client, "selected M (BTSC) modus\n"); 8279a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil return 0x2001; 8289a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil } 8299a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil if (state->v4l2_std & V4L2_STD_SECAM) { 8309a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil v4l_dbg(1, msp_debug, client, "selected SECAM modus\n"); 8319a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil return 0x6001; 8329a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil } 8339a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil return 0x0001; 8349a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil} 8359a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil 8362474ed444b475614ef795523076be7cc8437ae00Hans Verkuilstatic void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in) 8372474ed444b475614ef795523076be7cc8437ae00Hans Verkuil { 8382474ed444b475614ef795523076be7cc8437ae00Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 8392474ed444b475614ef795523076be7cc8437ae00Hans Verkuil int source, matrix; 8402474ed444b475614ef795523076be7cc8437ae00Hans Verkuil 8412474ed444b475614ef795523076be7cc8437ae00Hans Verkuil switch (state->audmode) { 8422474ed444b475614ef795523076be7cc8437ae00Hans Verkuil case V4L2_TUNER_MODE_MONO: 8432474ed444b475614ef795523076be7cc8437ae00Hans Verkuil source = 0; /* mono only */ 8442474ed444b475614ef795523076be7cc8437ae00Hans Verkuil matrix = 0x30; 8452474ed444b475614ef795523076be7cc8437ae00Hans Verkuil break; 8462474ed444b475614ef795523076be7cc8437ae00Hans Verkuil case V4L2_TUNER_MODE_LANG2: 8472474ed444b475614ef795523076be7cc8437ae00Hans Verkuil source = 4; /* stereo or B */ 8482474ed444b475614ef795523076be7cc8437ae00Hans Verkuil matrix = 0x10; 8492474ed444b475614ef795523076be7cc8437ae00Hans Verkuil break; 850301e22d69140898eddd38a9134da711cb5dfc170Hans Verkuil case V4L2_TUNER_MODE_LANG1_LANG2: 8512474ed444b475614ef795523076be7cc8437ae00Hans Verkuil source = 1; /* stereo or A|B */ 8522474ed444b475614ef795523076be7cc8437ae00Hans Verkuil matrix = 0x20; 8532474ed444b475614ef795523076be7cc8437ae00Hans Verkuil break; 8540020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil case V4L2_TUNER_MODE_STEREO: 8550020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil case V4L2_TUNER_MODE_LANG1: 8560020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil default: 8570020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil source = 3; /* stereo or A */ 8580020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil matrix = 0x00; 8590020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil break; 8602474ed444b475614ef795523076be7cc8437ae00Hans Verkuil } 8612474ed444b475614ef795523076be7cc8437ae00Hans Verkuil 86207151724a35e8e70f1aa64ce30a5a3f5c1ad49a3Hans Verkuil if (in == MSP_DSP_IN_TUNER) 8632474ed444b475614ef795523076be7cc8437ae00Hans Verkuil source = (source << 8) | 0x20; 8642474ed444b475614ef795523076be7cc8437ae00Hans Verkuil /* the msp34x2g puts the MAIN_AVC, MAIN and AUX sources in 12, 13, 14 8652474ed444b475614ef795523076be7cc8437ae00Hans Verkuil instead of 11, 12, 13. So we add one for that msp version. */ 86607151724a35e8e70f1aa64ce30a5a3f5c1ad49a3Hans Verkuil else if (in >= MSP_DSP_IN_MAIN_AVC && state->has_dolby_pro_logic) 8672474ed444b475614ef795523076be7cc8437ae00Hans Verkuil source = ((in + 1) << 8) | matrix; 8682474ed444b475614ef795523076be7cc8437ae00Hans Verkuil else 8692474ed444b475614ef795523076be7cc8437ae00Hans Verkuil source = (in << 8) | matrix; 8702474ed444b475614ef795523076be7cc8437ae00Hans Verkuil 8712474ed444b475614ef795523076be7cc8437ae00Hans Verkuil v4l_dbg(1, msp_debug, client, "set source to %d (0x%x) for output %02x\n", 8722474ed444b475614ef795523076be7cc8437ae00Hans Verkuil in, source, reg); 8732474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp_write_dsp(client, reg, source); 8742474ed444b475614ef795523076be7cc8437ae00Hans Verkuil} 8752474ed444b475614ef795523076be7cc8437ae00Hans Verkuil 8762474ed444b475614ef795523076be7cc8437ae00Hans Verkuilstatic void msp34xxg_set_sources(struct i2c_client *client) 8772474ed444b475614ef795523076be7cc8437ae00Hans Verkuil{ 8782474ed444b475614ef795523076be7cc8437ae00Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 8792474ed444b475614ef795523076be7cc8437ae00Hans Verkuil u32 in = state->routing.input; 8802474ed444b475614ef795523076be7cc8437ae00Hans Verkuil 8812474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_source(client, 0x0008, (in >> 4) & 0xf); 8822474ed444b475614ef795523076be7cc8437ae00Hans Verkuil /* quasi-peak detector is set to same input as the loudspeaker (MAIN) */ 8832474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_source(client, 0x000c, (in >> 4) & 0xf); 8842474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_source(client, 0x0009, (in >> 8) & 0xf); 8852474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_source(client, 0x000a, (in >> 12) & 0xf); 8860020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil if (state->has_scart2_out) 8872474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_source(client, 0x0041, (in >> 16) & 0xf); 8882474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_source(client, 0x000b, (in >> 20) & 0xf); 8892474ed444b475614ef795523076be7cc8437ae00Hans Verkuil} 8902474ed444b475614ef795523076be7cc8437ae00Hans Verkuil 891de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil/* (re-)initialize the msp34xxg */ 892de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuilstatic void msp34xxg_reset(struct i2c_client *client) 8937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 8947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 8952474ed444b475614ef795523076be7cc8437ae00Hans Verkuil int tuner = (state->routing.input >> 3) & 1; 896de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil int modus; 8977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 898de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* initialize std to 1 (autodetect) to signal that no standard is 899de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil selected yet. */ 900de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->std = 1; 901de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil 902de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_reset(client); 9037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9045af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil if (state->has_i2s_conf) 9055af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_write_dem(client, 0x40, state->i2s_mode); 9067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* step-by-step initialisation, as described in the manual */ 9089a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil modus = msp34xxg_modus(client); 9092474ed444b475614ef795523076be7cc8437ae00Hans Verkuil modus |= tuner ? 0x100 : 0; 910de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dem(client, 0x30, modus); 9117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* write the dsps that may have an influence on 9137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil standard/audio autodetection right now */ 9142474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_sources(client); 9157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 916de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x0d, 0x1900); /* scart */ 917de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x0e, 0x3000); /* FM */ 918de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->has_nicam) 919de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x10, 0x5a00); /* nicam */ 9207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 921de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* set identification threshold. Personally, I 922de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * I set it to a higher value than the default 923de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * of 0x190 to ignore noisy stereo signals. 924de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * this needs tuning. (recommended range 0x00a0-0x03c0) 925de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * 0x7f0 = forced mono mode 926de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * 927de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * a2 threshold for stereo/bilingual. 928de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * Note: this register is part of the Manual/Compatibility mode. 929de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * It is supported by all 'G'-family chips. 930de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil */ 931de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dem(client, 0x22, msp_stereo_thresh); 9327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 9337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilint msp34xxg_thread(void *data) 9357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 9367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct i2c_client *client = data; 9377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 938de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil int val, i; 9397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 940f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n"); 9417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (;;) { 943f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n"); 9447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_sleep(state, -1); 945f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp34xxg thread: wakeup\n"); 9467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil restart: 948f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: restart scan\n"); 9497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->restart = 0; 9507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (kthread_should_stop()) 9517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 9527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9532eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil if (state->mode == MSP_MODE_EXTERN) { 9542eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil /* no carrier scan needed, just unmute */ 9552eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n"); 9562eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil state->scan_in_progress = 0; 9572eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil msp_set_audio(client); 9582eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil continue; 9592eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil } 9602eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil 9617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* setup the chip*/ 9627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp34xxg_reset(client); 963de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->std = state->radio ? 0x40 : msp_standard; 964de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->std != 1) 9657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto unmute; 966de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* start autodetect */ 967de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dem(client, 0x20, state->std); 9687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* watch autodetect */ 970de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil v4l_dbg(1, msp_debug, client, "started autodetect, waiting for result\n"); 9717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (i = 0; i < 10; i++) { 9727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_sleep(state, 100)) 9737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 9747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* check results */ 9767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dem(client, 0x7e); 9777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val < 0x07ff) { 978de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->std = val; 9797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 9807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 981f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "detection still in progress\n"); 9827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 983de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->std == 1) { 984f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "detection still in progress after 10 tries. giving up.\n"); 9857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil continue; 9867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 9877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil unmute: 989de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil v4l_dbg(1, msp_debug, client, "detected standard: %s (0x%04x)\n", 990de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_standard_std_name(state->std), state->std); 9917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9922eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil if (state->std == 9) { 9932eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil /* AM NICAM mode */ 9942eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil msp_write_dsp(client, 0x0e, 0x7c00); 9952eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil } 9962eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil 9977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* unmute: dispatch sound to scart output, set scart volume */ 9987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_audio(client); 9997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 10007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* restore ACB */ 10017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_write_dsp(client, 0x13, state->acb)) 10027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return -1; 10037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1004de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* the periodic stereo/SAP check is only relevant for 1005de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil the 0x20 standard (BTSC) */ 1006de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->std != 0x20) 1007de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil continue; 1008de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil 1009de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->watch_stereo = 1; 1010de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil 1011de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* monitor tv audio mode, the first time don't wait 1012de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil in order to get a quick stereo/SAP update */ 1013de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil watch_stereo(client); 1014de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil while (state->watch_stereo) { 1015de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil watch_stereo(client); 1016de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (msp_sleep(state, 5000)) 1017de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil goto restart; 1018de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil } 10197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 1020f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: exit\n"); 10217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return 0; 10227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 10237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1024de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuilstatic int msp34xxg_detect_stereo(struct i2c_client *client) 10257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 10267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 10277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int status = msp_read_dem(client, 0x0200); 10287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int is_bilingual = status & 0x100; 10297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int is_stereo = status & 0x40; 1030de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil int oldrx = state->rxsubchans; 10317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 10327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = 0; 10337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (is_stereo) 10348a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->rxsubchans = V4L2_TUNER_SUB_STEREO; 10357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil else 10368a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->rxsubchans = V4L2_TUNER_SUB_MONO; 10377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (is_bilingual) { 1038de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->std == 0x20) 1039de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->rxsubchans |= V4L2_TUNER_SUB_SAP; 1040de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil else 1041de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; 10427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 1043f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n", 10447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil status, is_stereo, is_bilingual, state->rxsubchans); 1045de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil return (oldrx != state->rxsubchans); 10467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 10477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1048044f324f6ea5d55391db62fca6a295b2651cb946Adrian Bunkstatic void msp34xxg_set_audmode(struct i2c_client *client) 10497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 10507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 10517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1052de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->std == 0x20) { 1053de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if ((state->rxsubchans & V4L2_TUNER_SUB_SAP) && 1054cc33668b1eed1eac43f00cec639066047323b01dMauro Carvalho Chehab (state->audmode == V4L2_TUNER_MODE_LANG1_LANG2 || 1055de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->audmode == V4L2_TUNER_MODE_LANG2)) { 1056de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dem(client, 0x20, 0x21); 1057de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil } else { 1058de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dem(client, 0x20, 0x20); 1059de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil } 1060de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil } 1061de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil 10622474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_sources(client); 10637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 10647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 10658a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuilvoid msp_set_audmode(struct i2c_client *client) 10668a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil{ 10678a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil struct msp_state *state = i2c_get_clientdata(client); 10688a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 10698a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil switch (state->opmode) { 10708a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_MANUAL: 10718a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_AUTODETECT: 10728a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_audmode(client); 10738a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil break; 10748a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_AUTOSELECT: 10758a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp34xxg_set_audmode(client); 10768a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil break; 10778a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil } 10788a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil} 10798a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 1080de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuilint msp_detect_stereo(struct i2c_client *client) 10818a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil{ 10828a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil struct msp_state *state = i2c_get_clientdata(client); 10838a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 10848a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil switch (state->opmode) { 10858a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_MANUAL: 10868a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_AUTODETECT: 1087de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil return msp3400c_detect_stereo(client); 10888a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_AUTOSELECT: 1089de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil return msp34xxg_detect_stereo(client); 10908a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil } 1091de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil return 0; 10928a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil} 10938a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 1094