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