msp3400-kthreads.c revision 3bbe5a83996c0a669250d91421eef054f3a30595
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 2470020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil /* switch to mono if only mono is available */ 2480020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil if (state->rxsubchans == V4L2_TUNER_SUB_MONO) 2490020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil audmode = V4L2_TUNER_MODE_MONO; 2500020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil /* if bilingual */ 2510020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil else if (state->rxsubchans & V4L2_TUNER_SUB_LANG2) { 2520020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil /* and mono or stereo, then fallback to lang1 */ 2530020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil if (audmode == V4L2_TUNER_MODE_MONO || 2540020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil audmode == V4L2_TUNER_MODE_STEREO) 2550020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil audmode = V4L2_TUNER_MODE_LANG1; 2560020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil } 2570020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil /* if stereo, and audmode is not mono, then switch to stereo */ 2580020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil else if (audmode != V4L2_TUNER_MODE_MONO) 2597061561e640c2947ab93c4e2a437327657c4482eHans Verkuil audmode = V4L2_TUNER_MODE_STEREO; 2607061561e640c2947ab93c4e2a437327657c4482eHans Verkuil 2617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* switch demodulator */ 2627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (state->mode) { 2637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_TERRA: 2648a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "FM set_audmode: %s\n", modestr); 2657061561e640c2947ab93c4e2a437327657c4482eHans Verkuil switch (audmode) { 2667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_STEREO: 2677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x000e, 0x3001); 2687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_MONO: 2707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG1: 2717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG2: 272301e22d69140898eddd38a9134da711cb5dfc170Hans Verkuil case V4L2_TUNER_MODE_LANG1_LANG2: 2737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x000e, 0x3000); 2747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 2767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_SAT: 2788a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "SAT set_audmode: %s\n", modestr); 2797061561e640c2947ab93c4e2a437327657c4482eHans Verkuil switch (audmode) { 2807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_MONO: 2818a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5)); 2827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_STEREO: 284301e22d69140898eddd38a9134da711cb5dfc170Hans Verkuil case V4L2_TUNER_MODE_LANG1_LANG2: 2858a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02)); 2867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG1: 2888a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); 2897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG2: 2918a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); 2927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 2947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 2957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_NICAM1: 2967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_NICAM2: 2977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_AM_NICAM: 2988a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "NICAM set_audmode: %s\n",modestr); 2997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->nicam_on) 3008a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil src = 0x0100; /* NICAM */ 3017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_BTSC: 3038a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "BTSC set_audmode: %s\n",modestr); 3047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_EXTERN: 3068a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "extern set_audmode: %s\n",modestr); 3078a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil src = 0x0200; /* SCART */ 3087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_RADIO: 3108a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "FM-Radio set_audmode: %s\n",modestr); 3117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 3138a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "mono set_audmode\n"); 3147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return; 3157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* switch audio */ 3180020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil v4l_dbg(1, msp_debug, client, "set audmode %d\n", audmode); 3197061561e640c2947ab93c4e2a437327657c4482eHans Verkuil switch (audmode) { 3207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_STEREO: 321301e22d69140898eddd38a9134da711cb5dfc170Hans Verkuil case V4L2_TUNER_MODE_LANG1_LANG2: 3228a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil src |= 0x0020; 3237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_MONO: 3257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_AM_NICAM) { 326f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "switching to AM mono\n"); 3277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* AM mono decoding is handled by tuner, not MSP chip */ 3287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* SCART switching control register */ 3297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_scart(client, SCART_MONO, 0); 3307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil src = 0x0200; 3317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3338a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil if (state->rxsubchans & V4L2_TUNER_SUB_STEREO) 3348a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil src = 0x0030; 3358a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil break; 3367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG1: 3377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG2: 3398a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil src |= 0x0010; 3407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3428a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "set_audmode final source/matrix = 0x%x\n", src); 3437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3448a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_set_source(client, src); 3457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 3467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic void msp3400c_print_mode(struct i2c_client *client) 3487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 3497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 3507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->main == state->second) { 352f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "mono sound carrier: %d.%03d MHz\n", 3537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->main / 910000, (state->main / 910) % 1000); 3547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 355f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "main sound carrier: %d.%03d MHz\n", 3567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->main / 910000, (state->main / 910) % 1000); 3577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_FM_NICAM1 || state->mode == MSP_MODE_FM_NICAM2) 359f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "NICAM/FM carrier : %d.%03d MHz\n", 3607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second / 910000, (state->second/910) % 1000); 3617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_AM_NICAM) 362f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "NICAM/AM carrier : %d.%03d MHz\n", 3637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second / 910000, (state->second / 910) % 1000); 3647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_FM_TERRA && state->main != state->second) { 365f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "FM-stereo carrier : %d.%03d MHz\n", 3667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second / 910000, (state->second / 910) % 1000); 3677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 3697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* ----------------------------------------------------------------------- */ 3717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3728a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuilstatic int msp3400c_detect_stereo(struct i2c_client *client) 3737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 3747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 3757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int val; 3767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int rxsubchans = state->rxsubchans; 3778a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil int newnicam = state->nicam_on; 3787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int update = 0; 3797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (state->mode) { 3817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_TERRA: 3827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dsp(client, 0x18); 3837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val > 32767) 3847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val -= 65536; 385f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "stereo detect register: %d\n", val); 3863bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil if (val > 8192) { 3878a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil rxsubchans = V4L2_TUNER_SUB_STEREO; 3887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else if (val < -4096) { 3897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; 3907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 3917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO; 3927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil newnicam = 0; 3947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_NICAM1: 3967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_NICAM2: 3977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_AM_NICAM: 3987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dem(client, 0x23); 399f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "nicam sync=%d, mode=%d\n", 4007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val & 1, (val & 0x1e) >> 1); 4017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val & 1) { 4037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* nicam synced */ 4047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch ((val & 0x1e) >> 1) { 4057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0: 4067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 8: 4077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_STEREO; 4087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 1: 4107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 9: 4118a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO; 4127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 2: 4147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 10: 4158a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; 4167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 4187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO; 4197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil newnicam = 1; 4227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 4237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil newnicam = 0; 4247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO; 4257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (rxsubchans != state->rxsubchans) { 4297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil update = 1; 4308a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "watch: rxsubchans %02x => %02x\n", 4318a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->rxsubchans, rxsubchans); 4327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = rxsubchans; 4337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (newnicam != state->nicam_on) { 4357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil update = 1; 436f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "watch: nicam %d => %d\n", 4378a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->nicam_on, newnicam); 4387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = newnicam; 4397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return update; 4417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 4427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* 4447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * A kernel thread for msp3400 control -- we don't want to block the 4457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * in the ioctl while doing the sound carrier & stereo detect 4467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 4477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* stereo/multilang monitoring */ 4487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic void watch_stereo(struct i2c_client *client) 4497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 4507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 4517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 452de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (msp_detect_stereo(client)) { 453de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_set_audmode(client); 4547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 456f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_once) 4577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 0; 4587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 4597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilint msp3400c_thread(void *data) 4617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 4627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct i2c_client *client = data; 4637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 4647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp3400c_carrier_detect *cd; 4658a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil int count, max1, max2, val1, val2, val, this; 4667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 468f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n"); 4697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (;;) { 470f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n"); 4717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_sleep(state, -1); 472f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp3400 thread: wakeup\n"); 4737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil restart: 4758a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(2, msp_debug, client, "thread: restart scan\n"); 4767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->restart = 0; 4777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (kthread_should_stop()) 4787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4807560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil if (state->radio || MSP_MODE_EXTERN == state->mode) { 4817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* no carrier scan, just unmute */ 482f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n"); 4833bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil state->scan_in_progress = 0; 4847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_audio(client); 4857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil continue; 4867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4883bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil /* mute audio */ 4893bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil state->scan_in_progress = 1; 4903bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil msp_set_audio(client); 4910020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil 492de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp3400c_set_mode(client, MSP_MODE_AM_DETECT); 4937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val1 = val2 = 0; 4947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil max1 = max2 = -1; 4957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 0; 4968a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->nicam_on = 0; 4977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4983bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil /* wait for tuner to settle down after a channel change */ 4998a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil if (msp_sleep(state, 200)) 5007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 5017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* carrier detect pass #1 -- main carrier */ 5037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = msp3400c_carrier_detect_main; 5047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = ARRAY_SIZE(msp3400c_carrier_detect_main); 5057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 506f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_amsound && (state->v4l2_std & V4L2_STD_SECAM)) { 5077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* autodetect doesn't work well with AM ... */ 5087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil max1 = 3; 5097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = 0; 510f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "AM sound override\n"); 5117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (this = 0; this < count; this++) { 5148a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, cd[this].cdo, cd[this].cdo); 5157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_sleep(state,100)) 5167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 5177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dsp(client, 0x1b); 5187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val > 32767) 5197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val -= 65536; 5207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val1 < val) 5217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val1 = val, max1 = this; 522f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "carrier1 val: %5d / %s\n", val,cd[this].name); 5237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* carrier detect pass #2 -- second (stereo) carrier */ 5267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (max1) { 5277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 1: /* 5.5 */ 5287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = msp3400c_carrier_detect_55; 5297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = ARRAY_SIZE(msp3400c_carrier_detect_55); 5307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 3: /* 6.5 */ 5327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = msp3400c_carrier_detect_65; 5337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = ARRAY_SIZE(msp3400c_carrier_detect_65); 5347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0: /* 4.5 */ 5367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 2: /* 6.0 */ 5377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 5387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = NULL; 5397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = 0; 5407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 543f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_amsound && (state->v4l2_std & V4L2_STD_SECAM)) { 5447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* autodetect doesn't work well with AM ... */ 5457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = NULL; 5467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = 0; 5477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil max2 = 0; 5487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (this = 0; this < count; this++) { 5508a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, cd[this].cdo, cd[this].cdo); 5517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_sleep(state,100)) 5527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 5537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dsp(client, 0x1b); 5547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val > 32767) 5557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val -= 65536; 5567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val2 < val) 5577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val2 = val, max2 = this; 558f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "carrier2 val: %5d / %s\n", val,cd[this].name); 5597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* program the msp3400 according to the results */ 5628a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->main = msp3400c_carrier_detect_main[max1].cdo; 5637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (max1) { 5647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 1: /* 5.5 */ 5657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (max2 == 0) { 5667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* B/G FM-stereo */ 5677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_55[max2].cdo; 5688a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_TERRA); 5697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 5707560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil } else if (max2 == 1 && state->has_nicam) { 5717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* B/G NICAM */ 5727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_55[max2].cdo; 5738a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_NICAM1); 5747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 5757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 5767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 5777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto no_second; 5787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 2: /* 6.0 */ 5817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* PAL I NICAM */ 5827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = MSP_CARRIER(6.552); 5838a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_NICAM2); 5847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 5857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 5867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 3: /* 6.5 */ 5887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (max2 == 1 || max2 == 2) { 5897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* D/K FM-stereo */ 5907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_65[max2].cdo; 5918a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_TERRA); 5927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 5935af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil } else if (max2 == 0 && (state->v4l2_std & V4L2_STD_SECAM)) { 5947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* L NICAM or AM-mono */ 5957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_65[max2].cdo; 5968a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_AM_NICAM); 5977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 5987560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil } else if (max2 == 0 && state->has_nicam) { 5997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* D/K NICAM */ 6007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_65[max2].cdo; 6018a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_NICAM1); 6027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 6037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 6047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 6057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto no_second; 6067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 6087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0: /* 4.5 */ 6097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 6107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil no_second: 6117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_main[max1].cdo; 6128a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_TERRA); 6137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 6147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6150020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil msp3400c_set_carrier(client, state->second, state->main); 6167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6173bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil /* unmute */ 6183bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil state->scan_in_progress = 0; 6198a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_audmode(client); 6203bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil msp_set_audio(client); 6217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 622f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_debug) 6237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_print_mode(client); 6247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6258a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil /* monitor tv audio mode, the first time don't wait 6268a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil so long to get a quick stereo/bilingual result */ 6273bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil count = 3; 6287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil while (state->watch_stereo) { 6293bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil if (msp_sleep(state, count ? 1000 : 5000)) 6307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 6310020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil if (count) count--; 6323bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil watch_stereo(client); 6337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 635f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: exit\n"); 6367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return 0; 6377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 6387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilint msp3410d_thread(void *data) 6417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 6427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct i2c_client *client = data; 6437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 6440020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil int val, i, std, count; 6457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 646f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n"); 6477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (;;) { 649f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n"); 6507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_sleep(state,-1); 651f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp3410 thread: wakeup\n"); 6527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil restart: 6548a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(2, msp_debug, client, "thread: restart scan\n"); 6557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->restart = 0; 6567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (kthread_should_stop()) 6577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 6587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_EXTERN) { 6607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* no carrier scan needed, just unmute */ 661f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n"); 6623bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil state->scan_in_progress = 0; 6637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_audio(client); 6647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil continue; 6657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6673bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil /* mute audio */ 6683bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil state->scan_in_progress = 1; 6693bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil msp_set_audio(client); 6707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 671de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* start autodetect. Note: autodetect is not supported for 672de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil NTSC-M and radio, hence we force the standard in those cases. */ 6735af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil if (state->radio) 6745af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil std = 0x40; 675d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil else 6765af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil std = (state->v4l2_std & V4L2_STD_NTSC) ? 0x20 : 1; 6777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 0; 6788a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->nicam_on = 0; 6797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6803bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil /* wait for tuner to settle down after a channel change */ 6813bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil if (msp_sleep(state, 200)) 6823bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil goto restart; 6833bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil 684f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_debug) 6858a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(2, msp_debug, client, "setting standard: %s (0x%04x)\n", 6865af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_standard_std_name(std), std); 6877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (std != 1) { 6897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* programmed some specific mode */ 6907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = std; 6917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 6927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* triggered autodetect */ 6935af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_write_dem(client, 0x20, std); 6947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (;;) { 695d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil if (msp_sleep(state, 100)) 6967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 6977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* check results */ 6997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dem(client, 0x7e); 7007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val < 0x07ff) 7017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7028a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(2, msp_debug, client, "detection still in progress\n"); 7037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7055af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil for (i = 0; msp_stdlist[i].name != NULL; i++) 7065af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil if (msp_stdlist[i].retval == val) 7077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 708f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "current standard: %s (0x%04x)\n", 7095af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_standard_std_name(val), val); 7105af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil state->main = msp_stdlist[i].main; 7115af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil state->second = msp_stdlist[i].second; 7125af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil state->std = val; 7133bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_MONO; 7145af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil 715f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_amsound && !state->radio && (state->v4l2_std & V4L2_STD_SECAM) && 7165af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil (val != 0x0009)) { 7177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* autodetection has failed, let backup */ 718f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "autodetection failed," 7195af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil " switching to backup standard: %s (0x%04x)\n", 7205af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_stdlist[8].name ? msp_stdlist[8].name : "unknown",val); 721de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->std = val = 0x0009; 7227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x20, val); 7237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* set stereo */ 7267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (val) { 7277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0008: /* B/G NICAM */ 7287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x000a: /* I NICAM */ 729de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil case 0x000b: /* D/K NICAM */ 730de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (val == 0x000a) 7317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->mode = MSP_MODE_FM_NICAM2; 732de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil else 733de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->mode = MSP_MODE_FM_NICAM1; 7347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* just turn on stereo */ 7357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 7367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 7377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0009: 7397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->mode = MSP_MODE_AM_NICAM; 7407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 7417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 7427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0020: /* BTSC */ 7448a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil /* The pre-'G' models only have BTSC-mono */ 7457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->mode = MSP_MODE_BTSC; 7467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0040: /* FM radio */ 7487560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil state->mode = MSP_MODE_FM_RADIO; 7497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_STEREO; 7507560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil /* not needed in theory if we have radio, but 7517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil short programming enables carrier mute */ 7528a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_RADIO); 7538a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, MSP_CARRIER(10.7), 7547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(10.7)); 7557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 756de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil case 0x0002: 7577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0003: 7587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0004: 7597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0005: 7605af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil state->mode = MSP_MODE_FM_TERRA; 7617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 7627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 765de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* set various prescales */ 766de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x0d, 0x1900); /* scart */ 767de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x0e, 0x3000); /* FM */ 768de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->has_nicam) 769de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x10, 0x5a00); /* nicam */ 770de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil 7715af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil if (state->has_i2s_conf) 7725af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_write_dem(client, 0x40, state->i2s_mode); 7737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7743bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil /* unmute */ 7758a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_audmode(client); 7763bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil state->scan_in_progress = 0; 7773bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil msp_set_audio(client); 7788a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 7798a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil /* monitor tv audio mode, the first time don't wait 7808a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil so long to get a quick stereo/bilingual result */ 7813bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil count = 3; 7827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil while (state->watch_stereo) { 7833bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil if (msp_sleep(state, count ? 1000 : 5000)) 7848a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil goto restart; 7850020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil if (count) count--; 7863bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil watch_stereo(client); 7877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 789f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: exit\n"); 7907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return 0; 7917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 7927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* ----------------------------------------------------------------------- */ 7947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 795de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil/* msp34xxG + (autoselect no-thread) 796de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * this one uses both automatic standard detection and automatic sound 797de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * select which are available in the newer G versions 798de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * struct msp: only norm, acb and source are really used in this mode 799de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil */ 8007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8019a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuilstatic int msp34xxg_modus(struct i2c_client *client) 8029a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil{ 8039a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 8049a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil 8059a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil if (state->radio) { 8069a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil v4l_dbg(1, msp_debug, client, "selected radio modus\n"); 8079a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil return 0x0001; 8089a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil } 8099a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil 8109a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil if (state->v4l2_std & V4L2_STD_PAL) { 8119a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil v4l_dbg(1, msp_debug, client, "selected PAL modus\n"); 8129a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil return 0x7001; 8139a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil } 8149a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil if (state->v4l2_std == V4L2_STD_NTSC_M_JP) { 8159a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil v4l_dbg(1, msp_debug, client, "selected M (EIA-J) modus\n"); 8169a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil return 0x4001; 8179a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil } 8189a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil if (state->v4l2_std == V4L2_STD_NTSC_M_KR) { 8199a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil v4l_dbg(1, msp_debug, client, "selected M (A2) modus\n"); 8209a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil return 0x0001; 8219a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil } 8229a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil if (state->v4l2_std & V4L2_STD_MN) { 8239a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil v4l_dbg(1, msp_debug, client, "selected M (BTSC) modus\n"); 8249a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil return 0x2001; 8259a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil } 8269a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil if (state->v4l2_std & V4L2_STD_SECAM) { 8279a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil v4l_dbg(1, msp_debug, client, "selected SECAM modus\n"); 8289a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil return 0x6001; 8299a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil } 8309a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil return 0x0001; 8319a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil} 8329a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil 8332474ed444b475614ef795523076be7cc8437ae00Hans Verkuilstatic void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in) 8342474ed444b475614ef795523076be7cc8437ae00Hans Verkuil { 8352474ed444b475614ef795523076be7cc8437ae00Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 8362474ed444b475614ef795523076be7cc8437ae00Hans Verkuil int source, matrix; 8372474ed444b475614ef795523076be7cc8437ae00Hans Verkuil 8382474ed444b475614ef795523076be7cc8437ae00Hans Verkuil switch (state->audmode) { 8392474ed444b475614ef795523076be7cc8437ae00Hans Verkuil case V4L2_TUNER_MODE_MONO: 8402474ed444b475614ef795523076be7cc8437ae00Hans Verkuil source = 0; /* mono only */ 8412474ed444b475614ef795523076be7cc8437ae00Hans Verkuil matrix = 0x30; 8422474ed444b475614ef795523076be7cc8437ae00Hans Verkuil break; 8432474ed444b475614ef795523076be7cc8437ae00Hans Verkuil case V4L2_TUNER_MODE_LANG2: 8442474ed444b475614ef795523076be7cc8437ae00Hans Verkuil source = 4; /* stereo or B */ 8452474ed444b475614ef795523076be7cc8437ae00Hans Verkuil matrix = 0x10; 8462474ed444b475614ef795523076be7cc8437ae00Hans Verkuil break; 847301e22d69140898eddd38a9134da711cb5dfc170Hans Verkuil case V4L2_TUNER_MODE_LANG1_LANG2: 8482474ed444b475614ef795523076be7cc8437ae00Hans Verkuil source = 1; /* stereo or A|B */ 8492474ed444b475614ef795523076be7cc8437ae00Hans Verkuil matrix = 0x20; 8502474ed444b475614ef795523076be7cc8437ae00Hans Verkuil break; 8510020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil case V4L2_TUNER_MODE_STEREO: 8520020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil case V4L2_TUNER_MODE_LANG1: 8530020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil default: 8540020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil source = 3; /* stereo or A */ 8550020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil matrix = 0x00; 8560020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil break; 8572474ed444b475614ef795523076be7cc8437ae00Hans Verkuil } 8582474ed444b475614ef795523076be7cc8437ae00Hans Verkuil 8592474ed444b475614ef795523076be7cc8437ae00Hans Verkuil if (in == MSP_DSP_OUT_TUNER) 8602474ed444b475614ef795523076be7cc8437ae00Hans Verkuil source = (source << 8) | 0x20; 8612474ed444b475614ef795523076be7cc8437ae00Hans Verkuil /* the msp34x2g puts the MAIN_AVC, MAIN and AUX sources in 12, 13, 14 8622474ed444b475614ef795523076be7cc8437ae00Hans Verkuil instead of 11, 12, 13. So we add one for that msp version. */ 8632474ed444b475614ef795523076be7cc8437ae00Hans Verkuil else if (in >= MSP_DSP_OUT_MAIN_AVC && state->has_dolby_pro_logic) 8642474ed444b475614ef795523076be7cc8437ae00Hans Verkuil source = ((in + 1) << 8) | matrix; 8652474ed444b475614ef795523076be7cc8437ae00Hans Verkuil else 8662474ed444b475614ef795523076be7cc8437ae00Hans Verkuil source = (in << 8) | matrix; 8672474ed444b475614ef795523076be7cc8437ae00Hans Verkuil 8682474ed444b475614ef795523076be7cc8437ae00Hans Verkuil v4l_dbg(1, msp_debug, client, "set source to %d (0x%x) for output %02x\n", 8692474ed444b475614ef795523076be7cc8437ae00Hans Verkuil in, source, reg); 8702474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp_write_dsp(client, reg, source); 8712474ed444b475614ef795523076be7cc8437ae00Hans Verkuil} 8722474ed444b475614ef795523076be7cc8437ae00Hans Verkuil 8732474ed444b475614ef795523076be7cc8437ae00Hans Verkuilstatic void msp34xxg_set_sources(struct i2c_client *client) 8742474ed444b475614ef795523076be7cc8437ae00Hans Verkuil{ 8752474ed444b475614ef795523076be7cc8437ae00Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 8762474ed444b475614ef795523076be7cc8437ae00Hans Verkuil u32 in = state->routing.input; 8772474ed444b475614ef795523076be7cc8437ae00Hans Verkuil 8782474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_source(client, 0x0008, (in >> 4) & 0xf); 8792474ed444b475614ef795523076be7cc8437ae00Hans Verkuil /* quasi-peak detector is set to same input as the loudspeaker (MAIN) */ 8802474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_source(client, 0x000c, (in >> 4) & 0xf); 8812474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_source(client, 0x0009, (in >> 8) & 0xf); 8822474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_source(client, 0x000a, (in >> 12) & 0xf); 8830020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil if (state->has_scart2_out) 8842474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_source(client, 0x0041, (in >> 16) & 0xf); 8852474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_source(client, 0x000b, (in >> 20) & 0xf); 8862474ed444b475614ef795523076be7cc8437ae00Hans Verkuil} 8872474ed444b475614ef795523076be7cc8437ae00Hans Verkuil 888de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil/* (re-)initialize the msp34xxg */ 889de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuilstatic void msp34xxg_reset(struct i2c_client *client) 8907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 8917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 8922474ed444b475614ef795523076be7cc8437ae00Hans Verkuil int tuner = (state->routing.input >> 3) & 1; 893de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil int modus; 8947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 895de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* initialize std to 1 (autodetect) to signal that no standard is 896de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil selected yet. */ 897de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->std = 1; 898de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil 899de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_reset(client); 9007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9015af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil if (state->has_i2s_conf) 9025af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_write_dem(client, 0x40, state->i2s_mode); 9037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* step-by-step initialisation, as described in the manual */ 9059a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil modus = msp34xxg_modus(client); 9062474ed444b475614ef795523076be7cc8437ae00Hans Verkuil modus |= tuner ? 0x100 : 0; 907de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dem(client, 0x30, modus); 9087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* write the dsps that may have an influence on 9107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil standard/audio autodetection right now */ 9112474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_sources(client); 9127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 913de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x0d, 0x1900); /* scart */ 914de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x0e, 0x3000); /* FM */ 915de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->has_nicam) 916de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x10, 0x5a00); /* nicam */ 9177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 918de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* set identification threshold. Personally, I 919de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * I set it to a higher value than the default 920de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * of 0x190 to ignore noisy stereo signals. 921de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * this needs tuning. (recommended range 0x00a0-0x03c0) 922de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * 0x7f0 = forced mono mode 923de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * 924de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * a2 threshold for stereo/bilingual. 925de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * Note: this register is part of the Manual/Compatibility mode. 926de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * It is supported by all 'G'-family chips. 927de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil */ 928de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dem(client, 0x22, msp_stereo_thresh); 9297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 9307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilint msp34xxg_thread(void *data) 9327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 9337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct i2c_client *client = data; 9347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 935de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil int val, i; 9367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 937f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n"); 9387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (;;) { 940f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n"); 9417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_sleep(state, -1); 942f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp34xxg thread: wakeup\n"); 9437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil restart: 945f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: restart scan\n"); 9467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->restart = 0; 9477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (kthread_should_stop()) 9487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 9497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* setup the chip*/ 9517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp34xxg_reset(client); 952de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->std = state->radio ? 0x40 : msp_standard; 953de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->std != 1) 9547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto unmute; 955de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* start autodetect */ 956de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dem(client, 0x20, state->std); 9577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* watch autodetect */ 959de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil v4l_dbg(1, msp_debug, client, "started autodetect, waiting for result\n"); 9607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (i = 0; i < 10; i++) { 9617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_sleep(state, 100)) 9627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 9637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* check results */ 9657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dem(client, 0x7e); 9667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val < 0x07ff) { 967de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->std = val; 9687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 9697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 970f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "detection still in progress\n"); 9717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 972de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->std == 1) { 973f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "detection still in progress after 10 tries. giving up.\n"); 9747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil continue; 9757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 9767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil unmute: 978de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil v4l_dbg(1, msp_debug, client, "detected standard: %s (0x%04x)\n", 979de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_standard_std_name(state->std), state->std); 9807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* unmute: dispatch sound to scart output, set scart volume */ 9827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_audio(client); 9837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* restore ACB */ 9857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_write_dsp(client, 0x13, state->acb)) 9867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return -1; 9877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 988de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* the periodic stereo/SAP check is only relevant for 989de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil the 0x20 standard (BTSC) */ 990de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->std != 0x20) 991de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil continue; 992de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil 993de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->watch_stereo = 1; 994de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil 995de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* monitor tv audio mode, the first time don't wait 996de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil in order to get a quick stereo/SAP update */ 997de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil watch_stereo(client); 998de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil while (state->watch_stereo) { 999de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil watch_stereo(client); 1000de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (msp_sleep(state, 5000)) 1001de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil goto restart; 1002de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil } 10037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 1004f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: exit\n"); 10057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return 0; 10067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 10077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1008de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuilstatic int msp34xxg_detect_stereo(struct i2c_client *client) 10097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 10107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 10117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int status = msp_read_dem(client, 0x0200); 10127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int is_bilingual = status & 0x100; 10137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int is_stereo = status & 0x40; 1014de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil int oldrx = state->rxsubchans; 10157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 10167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = 0; 10177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (is_stereo) 10188a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->rxsubchans = V4L2_TUNER_SUB_STEREO; 10197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil else 10208a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->rxsubchans = V4L2_TUNER_SUB_MONO; 10217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (is_bilingual) { 1022de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->std == 0x20) 1023de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->rxsubchans |= V4L2_TUNER_SUB_SAP; 1024de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil else 1025de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; 10267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 1027f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n", 10287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil status, is_stereo, is_bilingual, state->rxsubchans); 1029de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil return (oldrx != state->rxsubchans); 10307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 10317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1032044f324f6ea5d55391db62fca6a295b2651cb946Adrian Bunkstatic void msp34xxg_set_audmode(struct i2c_client *client) 10337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 10347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp_state *state = i2c_get_clientdata(client); 10357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1036de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->std == 0x20) { 1037de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if ((state->rxsubchans & V4L2_TUNER_SUB_SAP) && 1038cc33668b1eed1eac43f00cec639066047323b01dMauro Carvalho Chehab (state->audmode == V4L2_TUNER_MODE_LANG1_LANG2 || 1039de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->audmode == V4L2_TUNER_MODE_LANG2)) { 1040de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dem(client, 0x20, 0x21); 1041de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil } else { 1042de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dem(client, 0x20, 0x20); 1043de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil } 1044de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil } 1045de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil 10462474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_sources(client); 10477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 10487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 10498a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuilvoid msp_set_audmode(struct i2c_client *client) 10508a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil{ 10518a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil struct msp_state *state = i2c_get_clientdata(client); 10528a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 10538a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil switch (state->opmode) { 10548a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_MANUAL: 10558a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_AUTODETECT: 10568a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_audmode(client); 10578a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil break; 10588a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_AUTOSELECT: 10598a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp34xxg_set_audmode(client); 10608a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil break; 10618a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil } 10628a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil} 10638a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 1064de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuilint msp_detect_stereo(struct i2c_client *client) 10658a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil{ 10668a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil struct msp_state *state = i2c_get_clientdata(client); 10678a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 10688a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil switch (state->opmode) { 10698a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_MANUAL: 10708a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_AUTODETECT: 1071de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil return msp3400c_detect_stereo(client); 10728a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_AUTOSELECT: 1073de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil return msp34xxg_detect_stereo(client); 10748a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil } 1075de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil return 0; 10768a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil} 10778a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 1078