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