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 18d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil * 02110-1301, USA. 207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <linux/kernel.h> 247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <linux/module.h> 257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil#include <linux/i2c.h> 26831441862956fffa17b9801db37e6ea1650b0f69Rafael J. Wysocki#include <linux/freezer.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; 405d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab v4l2_std_id std; 415af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil} msp_stdlist[] = { 425d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { 0x0000, 0, 0, "could not detect sound standard", V4L2_STD_ALL }, 435d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { 0x0001, 0, 0, "autodetect start", V4L2_STD_ALL }, 445d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72), 455d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab "4.5/4.72 M Dual FM-Stereo", V4L2_STD_MN }, 465d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875), 475d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab "5.5/5.74 B/G Dual FM-Stereo", V4L2_STD_BG }, 485d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125), 495d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab "6.5/6.25 D/K1 Dual FM-Stereo", V4L2_STD_DK }, 505d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875), 515d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab "6.5/6.74 D/K2 Dual FM-Stereo", V4L2_STD_DK }, 525d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5), 535d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab "6.5 D/K FM-Mono (HDEV3)", V4L2_STD_DK }, 545d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { 0x0007, MSP_CARRIER(6.5), MSP_CARRIER(5.7421875), 555d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab "6.5/5.74 D/K3 Dual FM-Stereo", V4L2_STD_DK }, 565d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), 575d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab "5.5/5.85 B/G NICAM FM", V4L2_STD_BG }, 585d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), 595d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab "6.5/5.85 L NICAM AM", V4L2_STD_L }, 605d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), 615d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab "6.0/6.55 I NICAM FM", V4L2_STD_PAL_I }, 625d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), 635d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab "6.5/5.85 D/K NICAM FM", V4L2_STD_DK }, 645d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), 655d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab "6.5/5.85 D/K NICAM FM (HDEV2)", V4L2_STD_DK }, 665d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { 0x000d, MSP_CARRIER(6.5), MSP_CARRIER(5.85), 675d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab "6.5/5.85 D/K NICAM FM (HDEV3)", V4L2_STD_DK }, 685d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), 695d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab "4.5 M BTSC-Stereo", V4L2_STD_MTS }, 705d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), 715d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab "4.5 M BTSC-Mono + SAP", V4L2_STD_MTS }, 725d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), 735d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab "4.5 M EIA-J Japan Stereo", V4L2_STD_NTSC_M_JP }, 745d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7), 755d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab "10.7 FM-Stereo Radio", V4L2_STD_ALL }, 765d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5), 775d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab "6.5 SAT-Mono", V4L2_STD_ALL }, 785d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20), 795d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab "7.02/7.20 SAT-Stereo", V4L2_STD_ALL }, 805d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2), 815d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab "7.2 SAT ADR", V4L2_STD_ALL }, 825d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab { -1, 0, 0, NULL, 0 }, /* EOF */ 837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic struct msp3400c_init_data_dem { 867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int fir1[6]; 877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int fir2[6]; 887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int cdo1; 897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int cdo2; 907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int ad_cv; 917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int mode_reg; 927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int dsp_src; 937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int dsp_matrix; 947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} msp3400c_init_data[] = { 957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { /* AM (for carrier detect / msp3400) */ 967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {75, 19, 36, 35, 39, 40}, 977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {75, 19, 36, 35, 39, 40}, 987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(5.5), MSP_CARRIER(5.5), 997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0500, 0x0020, 0x3000 100d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil }, { /* AM (for carrier detect / msp3410) */ 1017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-1, -1, -8, 2, 59, 126}, 1027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-1, -1, -8, 2, 59, 126}, 1037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(5.5), MSP_CARRIER(5.5), 1047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0100, 0x0020, 0x3000 105d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil }, { /* FM Radio */ 1067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-8, -8, 4, 6, 78, 107}, 1077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-8, -8, 4, 6, 78, 107}, 1087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(10.7), MSP_CARRIER(10.7), 1097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0480, 0x0020, 0x3000 11025985edcedea6396277003854657b5f3cb31a628Lucas De Marchi }, { /* Terrestrial FM-mono + FM-stereo */ 1117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {3, 18, 27, 48, 66, 72}, 1127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {3, 18, 27, 48, 66, 72}, 1137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(5.5), MSP_CARRIER(5.5), 1147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0480, 0x0030, 0x3000 115d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil }, { /* Sat FM-mono */ 1167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 1, 9, 14, 24, 33, 37}, 1177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { 3, 18, 27, 48, 66, 72}, 1187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(6.5), MSP_CARRIER(6.5), 1197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00c6, 0x0480, 0x0000, 0x3000 120d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil }, { /* NICAM/FM -- B/G (5.5/5.85), D/K (6.5/5.85) */ 1217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-2, -8, -10, 10, 50, 86}, 1227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {3, 18, 27, 48, 66, 72}, 1237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(5.5), MSP_CARRIER(5.5), 1247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0040, 0x0120, 0x3000 125d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil }, { /* NICAM/FM -- I (6.0/6.552) */ 1267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {2, 4, -6, -4, 40, 94}, 1277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {3, 18, 27, 48, 66, 72}, 1287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(6.0), MSP_CARRIER(6.0), 1297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 0x00d0, 0x0040, 0x0120, 0x3000 130d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil }, { /* NICAM/AM -- L (6.5/5.85) */ 1317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-2, -8, -10, 10, 50, 86}, 1327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil {-4, -12, -9, 23, 79, 126}, 1337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(6.5), MSP_CARRIER(6.5), 1348a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 0x00c6, 0x0140, 0x0120, 0x7c00 1357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil }, 1367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 1377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstruct msp3400c_carrier_detect { 1397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int cdo; 1407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil char *name; 1417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 1427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic struct msp3400c_carrier_detect msp3400c_carrier_detect_main[] = { 1447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* main carrier */ 1457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(4.5), "4.5 NTSC" }, 1467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(5.5), "5.5 PAL B/G" }, 1477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(6.0), "6.0 PAL I" }, 1487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(6.5), "6.5 PAL D/K + SAT + SECAM" } 1497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 1507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic struct msp3400c_carrier_detect msp3400c_carrier_detect_55[] = { 1527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* PAL B/G */ 1537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(5.7421875), "5.742 PAL B/G FM-stereo" }, 1547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(5.85), "5.85 PAL B/G NICAM" } 1557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 1567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic struct msp3400c_carrier_detect msp3400c_carrier_detect_65[] = { 1587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* PAL SAT / SECAM */ 1597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(5.85), "5.85 PAL D/K + SECAM NICAM" }, 1607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(6.2578125), "6.25 PAL D/K1 FM-stereo" }, 1617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(6.7421875), "6.74 PAL D/K2 FM-stereo" }, 1627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(7.02), "7.02 PAL SAT FM-stereo s/b" }, 1637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(7.20), "7.20 PAL SAT FM-stereo s" }, 1647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil { MSP_CARRIER(7.38), "7.38 PAL SAT FM-stereo b" }, 1657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil}; 1667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* ------------------------------------------------------------------------ */ 1687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1695af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuilconst char *msp_standard_std_name(int std) 1707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 1717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int i; 1727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1735af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil for (i = 0; msp_stdlist[i].name != NULL; i++) 1745af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil if (msp_stdlist[i].retval == std) 1755af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil return msp_stdlist[i].name; 1767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return "unknown"; 1777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 1787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1795d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehabstatic v4l2_std_id msp_standard_std(int std) 1805d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab{ 1815d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab int i; 1825d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab 1835d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab for (i = 0; msp_stdlist[i].name != NULL; i++) 1845d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab if (msp_stdlist[i].retval == std) 1855d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab return msp_stdlist[i].std; 1865d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab return V4L2_STD_ALL; 1875d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab} 1885d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab 189044f324f6ea5d55391db62fca6a295b2651cb946Adrian Bunkstatic void msp_set_source(struct i2c_client *client, u16 src) 1908a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil{ 19176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(i2c_get_clientdata(client)); 1928a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 1938a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil if (msp_dolby) { 1948a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x0008, 0x0520); /* I2S1 */ 1958a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x0009, 0x0620); /* I2S2 */ 1968a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil } else { 1978a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x0008, src); 1988a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x0009, src); 1998a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil } 2008a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x000a, src); 2018a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x000b, src); 2028a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x000c, src); 2030020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil if (state->has_scart2_out) 2048a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dsp(client, 0x0041, src); 2058a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil} 2068a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 2078a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuilvoid msp3400c_set_carrier(struct i2c_client *client, int cdo1, int cdo2) 2087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 2097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x0093, cdo1 & 0xfff); 2107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x009b, cdo1 >> 12); 2117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x00a3, cdo2 & 0xfff); 2127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x00ab, cdo2 >> 12); 2138a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dem(client, 0x0056, 0); /* LOAD_REG_1/2 */ 2147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 2157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2168a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuilvoid msp3400c_set_mode(struct i2c_client *client, int mode) 2177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 21876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(i2c_get_clientdata(client)); 2198a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil struct msp3400c_init_data_dem *data = &msp3400c_init_data[mode]; 2205325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil int tuner = (state->route_in >> 3) & 1; 2217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int i; 2227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2238a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "set_mode: %d\n", mode); 2248a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->mode = mode; 2257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_MONO; 2267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2272474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp_write_dem(client, 0x00bb, data->ad_cv | (tuner ? 0x100 : 0)); 2287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (i = 5; i >= 0; i--) /* fir 1 */ 2308a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dem(client, 0x0001, data->fir1[i]); 2317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x0005, 0x0004); /* fir 2 */ 2337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x0005, 0x0040); 2347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x0005, 0x0000); 2357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (i = 5; i >= 0; i--) 2368a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dem(client, 0x0005, data->fir2[i]); 2377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2388a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_write_dem(client, 0x0083, data->mode_reg); 2397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2408a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, data->cdo1, data->cdo2); 2417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2428a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_set_source(client, data->dsp_src); 243de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* set prescales */ 2447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 245de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* volume prescale for SCART (AM mono input) */ 246de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x000d, 0x1900); 247de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x000e, data->dsp_matrix); 248de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->has_nicam) /* nicam prescale */ 249de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x0010, 0x5a00); 2507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 2517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2528a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil/* Set audio mode. Note that the pre-'G' models do not support BTSC+SAP, 2538a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil nor do they support stereo BTSC. */ 254044f324f6ea5d55391db62fca6a295b2651cb946Adrian Bunkstatic void msp3400c_set_audmode(struct i2c_client *client) 2557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 256d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil static char *strmode[] = { 257d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "mono", "stereo", "lang2", "lang1", "lang1+lang2" 258d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil }; 25976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(i2c_get_clientdata(client)); 260301e22d69140898eddd38a9134da711cb5dfc170Hans Verkuil char *modestr = (state->audmode >= 0 && state->audmode < 5) ? 2618a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil strmode[state->audmode] : "unknown"; 2628a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil int src = 0; /* channel source: FM/AM, nicam or SCART */ 2637061561e640c2947ab93c4e2a437327657c4482eHans Verkuil int audmode = state->audmode; 2647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->opmode == OPMODE_AUTOSELECT) { 2667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* this method would break everything, let's make sure 2677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * it's never called 2687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 2698a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, 2708a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil "set_audmode called with mode=%d instead of set_source (ignored)\n", 2718a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->audmode); 2727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return; 2737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 2747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 2750020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil /* Note: for the C and D revs no NTSC stereo + SAP is possible as 2760020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil the hardware does not support SAP. So the rxsubchans combination 2770020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil of STEREO | LANG2 does not occur. */ 2780020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil 2792eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil if (state->mode != MSP_MODE_EXTERN) { 2802eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil /* switch to mono if only mono is available */ 2812eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil if (state->rxsubchans == V4L2_TUNER_SUB_MONO) 2822eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil audmode = V4L2_TUNER_MODE_MONO; 2832eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil /* if bilingual */ 2842eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil else if (state->rxsubchans & V4L2_TUNER_SUB_LANG2) { 2852eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil /* and mono or stereo, then fallback to lang1 */ 2862eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil if (audmode == V4L2_TUNER_MODE_MONO || 2872eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil audmode == V4L2_TUNER_MODE_STEREO) 2882eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil audmode = V4L2_TUNER_MODE_LANG1; 2892eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil } 2902eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil /* if stereo, and audmode is not mono, then switch to stereo */ 2912eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil else if (audmode != V4L2_TUNER_MODE_MONO) 2922eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil audmode = V4L2_TUNER_MODE_STEREO; 2930020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil } 2947061561e640c2947ab93c4e2a437327657c4482eHans Verkuil 2957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* switch demodulator */ 2967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (state->mode) { 2977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_TERRA: 2988a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "FM set_audmode: %s\n", modestr); 2997061561e640c2947ab93c4e2a437327657c4482eHans Verkuil switch (audmode) { 3007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_STEREO: 3017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x000e, 0x3001); 3027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_MONO: 3047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG1: 3057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG2: 306301e22d69140898eddd38a9134da711cb5dfc170Hans Verkuil case V4L2_TUNER_MODE_LANG1_LANG2: 3077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dsp(client, 0x000e, 0x3000); 3087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_SAT: 3128a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "SAT set_audmode: %s\n", modestr); 3137061561e640c2947ab93c4e2a437327657c4482eHans Verkuil switch (audmode) { 3147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_MONO: 3158a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5)); 3167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_STEREO: 318301e22d69140898eddd38a9134da711cb5dfc170Hans Verkuil case V4L2_TUNER_MODE_LANG1_LANG2: 3198a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02)); 3207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG1: 3228a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); 3237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG2: 3258a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02)); 3267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_NICAM1: 3307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_NICAM2: 3317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_AM_NICAM: 332d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 333d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "NICAM set_audmode: %s\n", modestr); 3347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->nicam_on) 3358a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil src = 0x0100; /* NICAM */ 3367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_BTSC: 338d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 339d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "BTSC set_audmode: %s\n", modestr); 3407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_EXTERN: 342d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 343d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "extern set_audmode: %s\n", modestr); 3448a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil src = 0x0200; /* SCART */ 3457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_RADIO: 347d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 348d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "FM-Radio set_audmode: %s\n", modestr); 3497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 3518a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(1, msp_debug, client, "mono set_audmode\n"); 3527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return; 3537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* switch audio */ 3560020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil v4l_dbg(1, msp_debug, client, "set audmode %d\n", audmode); 3577061561e640c2947ab93c4e2a437327657c4482eHans Verkuil switch (audmode) { 3587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_STEREO: 359301e22d69140898eddd38a9134da711cb5dfc170Hans Verkuil case V4L2_TUNER_MODE_LANG1_LANG2: 3608a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil src |= 0x0020; 3617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_MONO: 3637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_AM_NICAM) { 364f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "switching to AM mono\n"); 3657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* AM mono decoding is handled by tuner, not MSP chip */ 3667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* SCART switching control register */ 3677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_set_scart(client, SCART_MONO, 0); 3687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil src = 0x0200; 3697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 3718a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil if (state->rxsubchans & V4L2_TUNER_SUB_STEREO) 3728a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil src = 0x0030; 3738a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil break; 3747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG1: 3757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case V4L2_TUNER_MODE_LANG2: 3778a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil src |= 0x0010; 3787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 3797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 380d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 381d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "set_audmode final source/matrix = 0x%x\n", src); 3827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3838a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp_set_source(client, src); 3847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 3857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 3867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic void msp3400c_print_mode(struct i2c_client *client) 3877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 38876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(i2c_get_clientdata(client)); 3897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 390d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil if (state->main == state->second) 391d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 392d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "mono sound carrier: %d.%03d MHz\n", 393d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->main / 910000, (state->main / 910) % 1000); 394d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil else 395d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 396d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "main sound carrier: %d.%03d MHz\n", 397d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->main / 910000, (state->main / 910) % 1000); 3987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_FM_NICAM1 || state->mode == MSP_MODE_FM_NICAM2) 399d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 400d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "NICAM/FM carrier : %d.%03d MHz\n", 401d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->second / 910000, (state->second/910) % 1000); 4027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_AM_NICAM) 403d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 404d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "NICAM/AM carrier : %d.%03d MHz\n", 405d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->second / 910000, (state->second / 910) % 1000); 4067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_FM_TERRA && state->main != state->second) { 407d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 408d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "FM-stereo carrier : %d.%03d MHz\n", 409d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->second / 910000, (state->second / 910) % 1000); 4107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 4127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* ----------------------------------------------------------------------- */ 4147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4158a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuilstatic int msp3400c_detect_stereo(struct i2c_client *client) 4167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 41776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(i2c_get_clientdata(client)); 4187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int val; 4197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int rxsubchans = state->rxsubchans; 4208a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil int newnicam = state->nicam_on; 4217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int update = 0; 4227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (state->mode) { 4247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_TERRA: 4257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dsp(client, 0x18); 4267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val > 32767) 4277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val -= 65536; 428d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(2, msp_debug, client, 429d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "stereo detect register: %d\n", val); 4303bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil if (val > 8192) { 4318a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil rxsubchans = V4L2_TUNER_SUB_STEREO; 4327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else if (val < -4096) { 4337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; 4347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 4357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO; 4367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil newnicam = 0; 4387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_NICAM1: 4407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_FM_NICAM2: 4417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case MSP_MODE_AM_NICAM: 4427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dem(client, 0x23); 443f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "nicam sync=%d, mode=%d\n", 4447e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val & 1, (val & 0x1e) >> 1); 4457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val & 1) { 4477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* nicam synced */ 4487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch ((val & 0x1e) >> 1) { 4497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0: 4507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 8: 4517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_STEREO; 4527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 1: 4547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 9: 4558a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO; 4567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 2: 4587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 10: 4598a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; 4607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 4627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO; 4637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil newnicam = 1; 4667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 4677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil newnicam = 0; 4687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil rxsubchans = V4L2_TUNER_SUB_MONO; 4697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 4717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (rxsubchans != state->rxsubchans) { 4737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil update = 1; 474d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 475d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "watch: rxsubchans %02x => %02x\n", 4768a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->rxsubchans, rxsubchans); 4777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = rxsubchans; 4787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (newnicam != state->nicam_on) { 4807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil update = 1; 481f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "watch: nicam %d => %d\n", 4828a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->nicam_on, newnicam); 4837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = newnicam; 4847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 4857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return update; 4867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 4877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 4887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* 4897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * A kernel thread for msp3400 control -- we don't want to block the 4907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil * in the ioctl while doing the sound carrier & stereo detect 4917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil */ 4927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* stereo/multilang monitoring */ 4937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilstatic void watch_stereo(struct i2c_client *client) 4947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 49576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(i2c_get_clientdata(client)); 4967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 497d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil if (msp_detect_stereo(client)) 498de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_set_audmode(client); 4997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 500f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_once) 5017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 0; 5027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 5037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilint msp3400c_thread(void *data) 5057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 5067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct i2c_client *client = data; 50776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(i2c_get_clientdata(client)); 5087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct msp3400c_carrier_detect *cd; 509d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil int count, max1, max2, val1, val2, val, i; 5107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 511f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n"); 5125d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab state->detected_std = V4L2_STD_ALL; 513831441862956fffa17b9801db37e6ea1650b0f69Rafael J. Wysocki set_freezable(); 5147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (;;) { 515f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n"); 5167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_sleep(state, -1); 517f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp3400 thread: wakeup\n"); 5187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 519d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuilrestart: 5208a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(2, msp_debug, client, "thread: restart scan\n"); 5217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->restart = 0; 5227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (kthread_should_stop()) 5237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5257560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil if (state->radio || MSP_MODE_EXTERN == state->mode) { 5267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* no carrier scan, just unmute */ 527d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 528d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "thread: no carrier scan\n"); 5293bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil state->scan_in_progress = 0; 530ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil msp_update_volume(state); 5317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil continue; 5327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5337e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5343bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil /* mute audio */ 5353bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil state->scan_in_progress = 1; 536ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil msp_update_volume(state); 5370020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil 538de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp3400c_set_mode(client, MSP_MODE_AM_DETECT); 5397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val1 = val2 = 0; 5407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil max1 = max2 = -1; 5417e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 0; 5428a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->nicam_on = 0; 5437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5443bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil /* wait for tuner to settle down after a channel change */ 5458a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil if (msp_sleep(state, 200)) 5467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 5477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* carrier detect pass #1 -- main carrier */ 5497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = msp3400c_carrier_detect_main; 5507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = ARRAY_SIZE(msp3400c_carrier_detect_main); 5517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 552f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_amsound && (state->v4l2_std & V4L2_STD_SECAM)) { 5537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* autodetect doesn't work well with AM ... */ 5547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil max1 = 3; 5557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = 0; 556f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "AM sound override\n"); 5577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 559d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil for (i = 0; i < count; i++) { 560d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil msp3400c_set_carrier(client, cd[i].cdo, cd[i].cdo); 561d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil if (msp_sleep(state, 100)) 5627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 5637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dsp(client, 0x1b); 5647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val > 32767) 5657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val -= 65536; 5667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val1 < val) 567d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil val1 = val, max1 = i; 568d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 569d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "carrier1 val: %5d / %s\n", val, cd[i].name); 5707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 5727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* carrier detect pass #2 -- second (stereo) carrier */ 5737e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (max1) { 5747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 1: /* 5.5 */ 5757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = msp3400c_carrier_detect_55; 5767e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = ARRAY_SIZE(msp3400c_carrier_detect_55); 5777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 3: /* 6.5 */ 5797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = msp3400c_carrier_detect_65; 5807e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = ARRAY_SIZE(msp3400c_carrier_detect_65); 5817e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0: /* 4.5 */ 5837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 2: /* 6.0 */ 5847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 5857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = NULL; 5867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = 0; 5877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 5887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 5897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 590f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_amsound && (state->v4l2_std & V4L2_STD_SECAM)) { 5917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* autodetect doesn't work well with AM ... */ 5927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil cd = NULL; 5937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil count = 0; 5947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil max2 = 0; 5957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 596d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil for (i = 0; i < count; i++) { 597d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil msp3400c_set_carrier(client, cd[i].cdo, cd[i].cdo); 598d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil if (msp_sleep(state, 100)) 5997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 6007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dsp(client, 0x1b); 6017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val > 32767) 6027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val -= 65536; 6037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val2 < val) 604d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil val2 = val, max2 = i; 605d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 606d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "carrier2 val: %5d / %s\n", val, cd[i].name); 6077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* program the msp3400 according to the results */ 6108a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->main = msp3400c_carrier_detect_main[max1].cdo; 6117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (max1) { 6127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 1: /* 5.5 */ 6135d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab state->detected_std = V4L2_STD_BG | V4L2_STD_PAL_H; 6147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (max2 == 0) { 6157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* B/G FM-stereo */ 6167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_55[max2].cdo; 6178a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_TERRA); 6187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 6197560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil } else if (max2 == 1 && state->has_nicam) { 6207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* B/G NICAM */ 6217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_55[max2].cdo; 6228a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_NICAM1); 6237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 6247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 6257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 6267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto no_second; 6277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6287e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 6297e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 2: /* 6.0 */ 6307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* PAL I NICAM */ 6315d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab state->detected_std = V4L2_STD_PAL_I; 6327e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = MSP_CARRIER(6.552); 6338a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_NICAM2); 6347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 6357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 6367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 6377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 3: /* 6.5 */ 6387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (max2 == 1 || max2 == 2) { 6397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* D/K FM-stereo */ 6407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_65[max2].cdo; 6418a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_TERRA); 6427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 6435d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab state->detected_std = V4L2_STD_DK; 6445af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil } else if (max2 == 0 && (state->v4l2_std & V4L2_STD_SECAM)) { 6457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* L NICAM or AM-mono */ 6467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_65[max2].cdo; 6478a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_AM_NICAM); 6487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 6495d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab state->detected_std = V4L2_STD_L; 6507560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil } else if (max2 == 0 && state->has_nicam) { 6517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* D/K NICAM */ 6527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_65[max2].cdo; 6538a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_NICAM1); 6547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 6557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 6565d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab state->detected_std = V4L2_STD_DK; 6577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 6587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto no_second; 6597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 6617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0: /* 4.5 */ 6625d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab state->detected_std = V4L2_STD_MN; 6637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil default: 664d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuilno_second: 6657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->second = msp3400c_carrier_detect_main[max1].cdo; 6668a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_TERRA); 6677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 6687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6690020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil msp3400c_set_carrier(client, state->second, state->main); 6707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6713bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil /* unmute */ 6723bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil state->scan_in_progress = 0; 6738a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_audmode(client); 674ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil msp_update_volume(state); 6757e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 676f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_debug) 6777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp3400c_print_mode(client); 6787e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6798a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil /* monitor tv audio mode, the first time don't wait 6808a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil so long to get a quick stereo/bilingual result */ 6813bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil count = 3; 6827e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil while (state->watch_stereo) { 6833bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil if (msp_sleep(state, count ? 1000 : 5000)) 6847e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 685d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil if (count) 686d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil count--; 6873bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil watch_stereo(client); 6887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 6897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 690f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: exit\n"); 6917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return 0; 6927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 6937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 6957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilint msp3410d_thread(void *data) 6967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 6977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct i2c_client *client = data; 69876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(i2c_get_clientdata(client)); 6990020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil int val, i, std, count; 7007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 701f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n"); 7025d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab state->detected_std = V4L2_STD_ALL; 703831441862956fffa17b9801db37e6ea1650b0f69Rafael J. Wysocki set_freezable(); 7047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (;;) { 705f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n"); 706d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil msp_sleep(state, -1); 707f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp3410 thread: wakeup\n"); 7087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 709d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuilrestart: 7108a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil v4l_dbg(2, msp_debug, client, "thread: restart scan\n"); 7117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->restart = 0; 7127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (kthread_should_stop()) 7137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 7147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7157e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (state->mode == MSP_MODE_EXTERN) { 7167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* no carrier scan needed, just unmute */ 717d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 718d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "thread: no carrier scan\n"); 7193bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil state->scan_in_progress = 0; 720ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil msp_update_volume(state); 7217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil continue; 7227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7243bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil /* mute audio */ 7253bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil state->scan_in_progress = 1; 726ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil msp_update_volume(state); 7277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 728de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* start autodetect. Note: autodetect is not supported for 729d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil NTSC-M and radio, hence we force the standard in those 730d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil cases. */ 7315af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil if (state->radio) 7325af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil std = 0x40; 733d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil else 7345af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil std = (state->v4l2_std & V4L2_STD_NTSC) ? 0x20 : 1; 7357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 0; 7368a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->nicam_on = 0; 7377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7383bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil /* wait for tuner to settle down after a channel change */ 7393bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil if (msp_sleep(state, 200)) 7403bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil goto restart; 7413bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil 742f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab if (msp_debug) 743d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(2, msp_debug, client, 744d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "setting standard: %s (0x%04x)\n", 745d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil msp_standard_std_name(std), std); 7467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7477e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (std != 1) { 7487e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* programmed some specific mode */ 7497e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = std; 7507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } else { 7517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* triggered autodetect */ 7525af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_write_dem(client, 0x20, std); 7537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (;;) { 754d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil if (msp_sleep(state, 100)) 7557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 7567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* check results */ 7587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dem(client, 0x7e); 7597e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val < 0x07ff) 7607e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 761d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(2, msp_debug, client, 762d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "detection still in progress\n"); 7637e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7655af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil for (i = 0; msp_stdlist[i].name != NULL; i++) 7665af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil if (msp_stdlist[i].retval == val) 7677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 768f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "current standard: %s (0x%04x)\n", 7695af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_standard_std_name(val), val); 7705af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil state->main = msp_stdlist[i].main; 7715af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil state->second = msp_stdlist[i].second; 7725af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil state->std = val; 7733bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_MONO; 7745af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil 775d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil if (msp_amsound && !state->radio && 776d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil (state->v4l2_std & V4L2_STD_SECAM) && (val != 0x0009)) { 7777e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* autodetection has failed, let backup */ 778f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "autodetection failed," 7795af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil " switching to backup standard: %s (0x%04x)\n", 780d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil msp_stdlist[8].name ? 781d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil msp_stdlist[8].name : "unknown", val); 782de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->std = val = 0x0009; 7837e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_write_dem(client, 0x20, val); 7845d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab } else { 7855d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab state->detected_std = msp_standard_std(state->std); 7867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 7877e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 7887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* set stereo */ 7897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil switch (val) { 7907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0008: /* B/G NICAM */ 7917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x000a: /* I NICAM */ 792de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil case 0x000b: /* D/K NICAM */ 793de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (val == 0x000a) 7947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->mode = MSP_MODE_FM_NICAM2; 795de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil else 796de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->mode = MSP_MODE_FM_NICAM1; 7977e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* just turn on stereo */ 7987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 7997e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 8007e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 8017e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0009: 8027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->mode = MSP_MODE_AM_NICAM; 8037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->nicam_on = 1; 8047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 8057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 8067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0020: /* BTSC */ 8078a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil /* The pre-'G' models only have BTSC-mono */ 8087e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->mode = MSP_MODE_BTSC; 8097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 8107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0040: /* FM radio */ 8117560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil state->mode = MSP_MODE_FM_RADIO; 8127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = V4L2_TUNER_SUB_STEREO; 8137560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil /* not needed in theory if we have radio, but 8147e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil short programming enables carrier mute */ 8158a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_mode(client, MSP_MODE_FM_RADIO); 8168a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_carrier(client, MSP_CARRIER(10.7), 8177e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil MSP_CARRIER(10.7)); 8187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 819de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil case 0x0002: 8207e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0003: 8217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0004: 8227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil case 0x0005: 8235af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil state->mode = MSP_MODE_FM_TERRA; 8247e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->watch_stereo = 1; 8257e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 8267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 8277e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 828de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* set various prescales */ 829de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x0d, 0x1900); /* scart */ 830de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x0e, 0x3000); /* FM */ 831de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->has_nicam) 832de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x10, 0x5a00); /* nicam */ 833de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil 8345af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil if (state->has_i2s_conf) 8355af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_write_dem(client, 0x40, state->i2s_mode); 8367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8373bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil /* unmute */ 8388a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_audmode(client); 8393bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil state->scan_in_progress = 0; 840ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil msp_update_volume(state); 8418a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 8428a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil /* monitor tv audio mode, the first time don't wait 8438a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil so long to get a quick stereo/bilingual result */ 8443bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil count = 3; 8457e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil while (state->watch_stereo) { 8463bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil if (msp_sleep(state, count ? 1000 : 5000)) 8478a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil goto restart; 848d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil if (count) 849d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil count--; 8503bbe5a83996c0a669250d91421eef054f3a30595Hans Verkuil watch_stereo(client); 8517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 8527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 853f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: exit\n"); 8547e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return 0; 8557e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 8567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8577e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil/* ----------------------------------------------------------------------- */ 8587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 859de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil/* msp34xxG + (autoselect no-thread) 860de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * this one uses both automatic standard detection and automatic sound 861de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * select which are available in the newer G versions 862de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * struct msp: only norm, acb and source are really used in this mode 863de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil */ 8647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 8659a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuilstatic int msp34xxg_modus(struct i2c_client *client) 8669a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil{ 86776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(i2c_get_clientdata(client)); 8689a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil 8699a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil if (state->radio) { 8709a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil v4l_dbg(1, msp_debug, client, "selected radio modus\n"); 8719a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil return 0x0001; 8729a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil } 8739a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil if (state->v4l2_std == V4L2_STD_NTSC_M_JP) { 8749a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil v4l_dbg(1, msp_debug, client, "selected M (EIA-J) modus\n"); 8759a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil return 0x4001; 8769a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil } 8779a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil if (state->v4l2_std == V4L2_STD_NTSC_M_KR) { 8789a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil v4l_dbg(1, msp_debug, client, "selected M (A2) modus\n"); 8799a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil return 0x0001; 8809a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil } 8812fd3c14cf53c379602d1a8a1a0aed7737a48c5c6Hans Verkuil if (state->v4l2_std == V4L2_STD_SECAM_L) { 8822fd3c14cf53c379602d1a8a1a0aed7737a48c5c6Hans Verkuil v4l_dbg(1, msp_debug, client, "selected SECAM-L modus\n"); 8832fd3c14cf53c379602d1a8a1a0aed7737a48c5c6Hans Verkuil return 0x6001; 8842fd3c14cf53c379602d1a8a1a0aed7737a48c5c6Hans Verkuil } 8859a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil if (state->v4l2_std & V4L2_STD_MN) { 8869a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil v4l_dbg(1, msp_debug, client, "selected M (BTSC) modus\n"); 8879a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil return 0x2001; 8889a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil } 8892fd3c14cf53c379602d1a8a1a0aed7737a48c5c6Hans Verkuil return 0x7001; 8909a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil} 8919a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil 8922474ed444b475614ef795523076be7cc8437ae00Hans Verkuilstatic void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in) 8932474ed444b475614ef795523076be7cc8437ae00Hans Verkuil { 89476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(i2c_get_clientdata(client)); 8952474ed444b475614ef795523076be7cc8437ae00Hans Verkuil int source, matrix; 8962474ed444b475614ef795523076be7cc8437ae00Hans Verkuil 8972474ed444b475614ef795523076be7cc8437ae00Hans Verkuil switch (state->audmode) { 8982474ed444b475614ef795523076be7cc8437ae00Hans Verkuil case V4L2_TUNER_MODE_MONO: 8992474ed444b475614ef795523076be7cc8437ae00Hans Verkuil source = 0; /* mono only */ 9002474ed444b475614ef795523076be7cc8437ae00Hans Verkuil matrix = 0x30; 9012474ed444b475614ef795523076be7cc8437ae00Hans Verkuil break; 9022474ed444b475614ef795523076be7cc8437ae00Hans Verkuil case V4L2_TUNER_MODE_LANG2: 9032474ed444b475614ef795523076be7cc8437ae00Hans Verkuil source = 4; /* stereo or B */ 9042474ed444b475614ef795523076be7cc8437ae00Hans Verkuil matrix = 0x10; 9052474ed444b475614ef795523076be7cc8437ae00Hans Verkuil break; 906301e22d69140898eddd38a9134da711cb5dfc170Hans Verkuil case V4L2_TUNER_MODE_LANG1_LANG2: 9072474ed444b475614ef795523076be7cc8437ae00Hans Verkuil source = 1; /* stereo or A|B */ 9082474ed444b475614ef795523076be7cc8437ae00Hans Verkuil matrix = 0x20; 9092474ed444b475614ef795523076be7cc8437ae00Hans Verkuil break; 9100020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil case V4L2_TUNER_MODE_LANG1: 9110020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil source = 3; /* stereo or A */ 9120020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil matrix = 0x00; 9130020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil break; 914b331def2d382d7a51c379f336fe80ef87d6674e3Hans Verkuil case V4L2_TUNER_MODE_STEREO: 915b331def2d382d7a51c379f336fe80ef87d6674e3Hans Verkuil default: 916b331def2d382d7a51c379f336fe80ef87d6674e3Hans Verkuil source = 3; /* stereo or A */ 917b331def2d382d7a51c379f336fe80ef87d6674e3Hans Verkuil matrix = 0x20; 918b331def2d382d7a51c379f336fe80ef87d6674e3Hans Verkuil break; 9192474ed444b475614ef795523076be7cc8437ae00Hans Verkuil } 9202474ed444b475614ef795523076be7cc8437ae00Hans Verkuil 92107151724a35e8e70f1aa64ce30a5a3f5c1ad49a3Hans Verkuil if (in == MSP_DSP_IN_TUNER) 9222474ed444b475614ef795523076be7cc8437ae00Hans Verkuil source = (source << 8) | 0x20; 9232474ed444b475614ef795523076be7cc8437ae00Hans Verkuil /* the msp34x2g puts the MAIN_AVC, MAIN and AUX sources in 12, 13, 14 9242474ed444b475614ef795523076be7cc8437ae00Hans Verkuil instead of 11, 12, 13. So we add one for that msp version. */ 92507151724a35e8e70f1aa64ce30a5a3f5c1ad49a3Hans Verkuil else if (in >= MSP_DSP_IN_MAIN_AVC && state->has_dolby_pro_logic) 9262474ed444b475614ef795523076be7cc8437ae00Hans Verkuil source = ((in + 1) << 8) | matrix; 9272474ed444b475614ef795523076be7cc8437ae00Hans Verkuil else 9282474ed444b475614ef795523076be7cc8437ae00Hans Verkuil source = (in << 8) | matrix; 9292474ed444b475614ef795523076be7cc8437ae00Hans Verkuil 930d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 931d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "set source to %d (0x%x) for output %02x\n", in, source, reg); 9322474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp_write_dsp(client, reg, source); 9332474ed444b475614ef795523076be7cc8437ae00Hans Verkuil} 9342474ed444b475614ef795523076be7cc8437ae00Hans Verkuil 9352474ed444b475614ef795523076be7cc8437ae00Hans Verkuilstatic void msp34xxg_set_sources(struct i2c_client *client) 9362474ed444b475614ef795523076be7cc8437ae00Hans Verkuil{ 93776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(i2c_get_clientdata(client)); 9385325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil u32 in = state->route_in; 9392474ed444b475614ef795523076be7cc8437ae00Hans Verkuil 9402474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_source(client, 0x0008, (in >> 4) & 0xf); 9412474ed444b475614ef795523076be7cc8437ae00Hans Verkuil /* quasi-peak detector is set to same input as the loudspeaker (MAIN) */ 9422474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_source(client, 0x000c, (in >> 4) & 0xf); 9432474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_source(client, 0x0009, (in >> 8) & 0xf); 9442474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_source(client, 0x000a, (in >> 12) & 0xf); 9450020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil if (state->has_scart2_out) 9462474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_source(client, 0x0041, (in >> 16) & 0xf); 9472474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_source(client, 0x000b, (in >> 20) & 0xf); 9482474ed444b475614ef795523076be7cc8437ae00Hans Verkuil} 9492474ed444b475614ef795523076be7cc8437ae00Hans Verkuil 950de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil/* (re-)initialize the msp34xxg */ 951de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuilstatic void msp34xxg_reset(struct i2c_client *client) 9527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 95376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(i2c_get_clientdata(client)); 9545325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil int tuner = (state->route_in >> 3) & 1; 955de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil int modus; 9567e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 957de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* initialize std to 1 (autodetect) to signal that no standard is 958de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil selected yet. */ 959de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->std = 1; 960de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil 961de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_reset(client); 9627e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9635af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil if (state->has_i2s_conf) 9645af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil msp_write_dem(client, 0x40, state->i2s_mode); 9657e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* step-by-step initialisation, as described in the manual */ 9679a80a93da738c631de644175fbd669ab9a9cb624Hans Verkuil modus = msp34xxg_modus(client); 9682474ed444b475614ef795523076be7cc8437ae00Hans Verkuil modus |= tuner ? 0x100 : 0; 969de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dem(client, 0x30, modus); 9707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9717e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* write the dsps that may have an influence on 9727e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil standard/audio autodetection right now */ 9732474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_sources(client); 9747e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 975de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x0d, 0x1900); /* scart */ 976de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x0e, 0x3000); /* FM */ 977de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->has_nicam) 978de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dsp(client, 0x10, 0x5a00); /* nicam */ 9797e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 980de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* set identification threshold. Personally, I 981de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * I set it to a higher value than the default 982de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * of 0x190 to ignore noisy stereo signals. 983de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * this needs tuning. (recommended range 0x00a0-0x03c0) 984de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * 0x7f0 = forced mono mode 985de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * 986de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * a2 threshold for stereo/bilingual. 987de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * Note: this register is part of the Manual/Compatibility mode. 988de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil * It is supported by all 'G'-family chips. 989de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil */ 990de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dem(client, 0x22, msp_stereo_thresh); 9917e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 9927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 9937e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuilint msp34xxg_thread(void *data) 9947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 9957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil struct i2c_client *client = data; 99676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(i2c_get_clientdata(client)); 997de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil int val, i; 9987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 999f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n"); 10005d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab state->detected_std = V4L2_STD_ALL; 1001831441862956fffa17b9801db37e6ea1650b0f69Rafael J. Wysocki set_freezable(); 10027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (;;) { 1003f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n"); 10047e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp_sleep(state, -1); 1005f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(2, msp_debug, client, "msp34xxg thread: wakeup\n"); 10067e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1007d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuilrestart: 1008f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: restart scan\n"); 10097e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->restart = 0; 10107e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (kthread_should_stop()) 10117e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 10127e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 10132eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil if (state->mode == MSP_MODE_EXTERN) { 10142eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil /* no carrier scan needed, just unmute */ 1015d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 1016d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "thread: no carrier scan\n"); 10172eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil state->scan_in_progress = 0; 1018ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil msp_update_volume(state); 10192eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil continue; 10202eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil } 10212eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil 10227e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* setup the chip*/ 10237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil msp34xxg_reset(client); 1024de98cdaf7ead419fe8b0a0a636ffb175489958feHans Verkuil state->std = state->radio ? 0x40 : 1025de98cdaf7ead419fe8b0a0a636ffb175489958feHans Verkuil (state->force_btsc && msp_standard == 1) ? 32 : msp_standard; 1026de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dem(client, 0x20, state->std); 1027de98cdaf7ead419fe8b0a0a636ffb175489958feHans Verkuil /* start autodetect */ 1028e335fada5afef0658038b6bec432d37f332da9fcHans Verkuil if (state->std != 1) 1029e335fada5afef0658038b6bec432d37f332da9fcHans Verkuil goto unmute; 10307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 10317e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* watch autodetect */ 1032d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 1033d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "started autodetect, waiting for result\n"); 10347e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil for (i = 0; i < 10; i++) { 10357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_sleep(state, 100)) 10367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil goto restart; 10377e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 10387e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* check results */ 10397e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil val = msp_read_dem(client, 0x7e); 10407e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (val < 0x07ff) { 1041de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->std = val; 10427e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil break; 10437e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 1044d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(2, msp_debug, client, 1045d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "detection still in progress\n"); 10467e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 1047de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->std == 1) { 1048d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 1049d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "detection still in progress after 10 tries. giving up.\n"); 10507e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil continue; 10517e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 10527e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1053d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuilunmute: 1054d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 1055d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "detected standard: %s (0x%04x)\n", 1056de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_standard_std_name(state->std), state->std); 10575d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab state->detected_std = msp_standard_std(state->std); 10587e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 10592eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil if (state->std == 9) { 10602eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil /* AM NICAM mode */ 10612eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil msp_write_dsp(client, 0x0e, 0x7c00); 10622eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil } 10632eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil 10647e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* unmute: dispatch sound to scart output, set scart volume */ 1065ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil msp_update_volume(state); 10667e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 10677e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil /* restore ACB */ 10687e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (msp_write_dsp(client, 0x13, state->acb)) 10697e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return -1; 10707e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1071de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* the periodic stereo/SAP check is only relevant for 1072de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil the 0x20 standard (BTSC) */ 1073de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->std != 0x20) 1074de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil continue; 1075de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil 1076de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->watch_stereo = 1; 1077de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil 1078de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil /* monitor tv audio mode, the first time don't wait 1079de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil in order to get a quick stereo/SAP update */ 1080de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil watch_stereo(client); 1081de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil while (state->watch_stereo) { 1082de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil watch_stereo(client); 1083de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (msp_sleep(state, 5000)) 1084de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil goto restart; 1085de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil } 10867e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 1087f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab v4l_dbg(1, msp_debug, client, "thread: exit\n"); 10887e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil return 0; 10897e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 10907e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1091de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuilstatic int msp34xxg_detect_stereo(struct i2c_client *client) 10927e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 109376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(i2c_get_clientdata(client)); 10947e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int status = msp_read_dem(client, 0x0200); 10957e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int is_bilingual = status & 0x100; 10967e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil int is_stereo = status & 0x40; 1097de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil int oldrx = state->rxsubchans; 10987e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1099b331def2d382d7a51c379f336fe80ef87d6674e3Hans Verkuil if (state->mode == MSP_MODE_EXTERN) 1100b331def2d382d7a51c379f336fe80ef87d6674e3Hans Verkuil return 0; 1101b331def2d382d7a51c379f336fe80ef87d6674e3Hans Verkuil 11027e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil state->rxsubchans = 0; 11037e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (is_stereo) 11048a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->rxsubchans = V4L2_TUNER_SUB_STEREO; 11057e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil else 11068a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil state->rxsubchans = V4L2_TUNER_SUB_MONO; 11077e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil if (is_bilingual) { 1108de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->std == 0x20) 1109de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->rxsubchans |= V4L2_TUNER_SUB_SAP; 1110de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil else 1111d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil state->rxsubchans = 1112d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; 11137e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil } 1114d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil v4l_dbg(1, msp_debug, client, 1115d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil "status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n", 11167e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil status, is_stereo, is_bilingual, state->rxsubchans); 1117de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil return (oldrx != state->rxsubchans); 11187e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 11197e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1120044f324f6ea5d55391db62fca6a295b2651cb946Adrian Bunkstatic void msp34xxg_set_audmode(struct i2c_client *client) 11217e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil{ 112276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(i2c_get_clientdata(client)); 11237e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 1124de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if (state->std == 0x20) { 1125de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil if ((state->rxsubchans & V4L2_TUNER_SUB_SAP) && 1126cc33668b1eed1eac43f00cec639066047323b01dMauro Carvalho Chehab (state->audmode == V4L2_TUNER_MODE_LANG1_LANG2 || 1127de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil state->audmode == V4L2_TUNER_MODE_LANG2)) { 1128de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dem(client, 0x20, 0x21); 1129de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil } else { 1130de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil msp_write_dem(client, 0x20, 0x20); 1131de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil } 1132de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil } 1133de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil 11342474ed444b475614ef795523076be7cc8437ae00Hans Verkuil msp34xxg_set_sources(client); 11357e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil} 11367e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil 11378a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuilvoid msp_set_audmode(struct i2c_client *client) 11388a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil{ 113976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(i2c_get_clientdata(client)); 11408a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 11418a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil switch (state->opmode) { 11428a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_MANUAL: 11438a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_AUTODETECT: 11448a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp3400c_set_audmode(client); 11458a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil break; 11468a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_AUTOSELECT: 11478a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil msp34xxg_set_audmode(client); 11488a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil break; 11498a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil } 11508a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil} 11518a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 1152de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuilint msp_detect_stereo(struct i2c_client *client) 11538a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil{ 115476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil struct msp_state *state = to_state(i2c_get_clientdata(client)); 11558a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 11568a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil switch (state->opmode) { 11578a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_MANUAL: 11588a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_AUTODETECT: 1159de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil return msp3400c_detect_stereo(client); 11608a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil case OPMODE_AUTOSELECT: 1161de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil return msp34xxg_detect_stereo(client); 11628a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil } 1163de533ccf8dd51f38ef3c1751f9eb5ad3f2fcfad9Hans Verkuil return 0; 11648a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil} 11658a4b275f9c192921797f45c2d4b5e4bc3875500aHans Verkuil 1166