[go: nahoru, domu]

153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/*
253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * Programming the mspx4xx sound processor family
353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *
453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * (c) 1997-2001 Gerd Knorr <kraxel@bytesex.org>
553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *
653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * what works and what doesn't:
753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *
853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *  AM-Mono
953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *      Support for Hauppauge cards added (decoding handled by tuner) added by
1053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *      Frederic Crozat <fcrozat@mail.dotcom.fr>
1153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *
1253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *  FM-Mono
1353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *      should work. The stereo modes are backward compatible to FM-mono,
1453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *      therefore FM-Mono should be allways available.
1553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *
1653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *  FM-Stereo (B/G, used in germany)
1753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *      should work, with autodetect
1853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *
1953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *  FM-Stereo (satellite)
2053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *      should work, no autodetect (i.e. default is mono, but you can
2153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *      switch to stereo -- untested)
2253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *
2353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *  NICAM (B/G, L , used in UK, Scandinavia, Spain and France)
2453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *      should work, with autodetect. Support for NICAM was added by
2553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *      Pekka Pietikainen <pp@netppl.fi>
2653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *
2753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * TODO:
2853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *   - better SAT support
2953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *
3053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * 980623  Thomas Sailer (sailer@ife.ee.ethz.ch)
3153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *         using soundcore instead of OSS
3253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *
3353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * This program is free software; you can redistribute it and/or
3453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * modify it under the terms of the GNU General Public License
3553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * as published by the Free Software Foundation; either version 2
3653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * of the License, or (at your option) any later version.
3753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *
3853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * This program is distributed in the hope that it will be useful,
3953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * but WITHOUT ANY WARRANTY; without even the implied warranty of
4053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * GNU General Public License for more details.
4253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *
4353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * You should have received a copy of the GNU General Public License
4453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * along with this program; if not, write to the Free Software
45d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
46d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil * 02110-1301, USA.
4753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil */
4853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
4953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
5053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil#include <linux/kernel.h>
5153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil#include <linux/module.h>
5253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil#include <linux/slab.h>
5353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil#include <linux/i2c.h>
5476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil#include <linux/kthread.h>
5576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil#include <linux/freezer.h>
562c26976d726838878eb8dd1bc91f84df38a05143Mauro Carvalho Chehab#include <linux/videodev2.h>
5776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil#include <media/v4l2-device.h>
5835ea11ff84719b1bfab2909903a9640a86552fd1Hans Verkuil#include <media/v4l2-ioctl.h>
5949965a80a4c4f5cbe15fb3bb1f8f8b0ec4ef02bcHans Verkuil#include <media/msp3400.h>
6076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil#include <media/tvaudio.h>
6149965a80a4c4f5cbe15fb3bb1f8f8b0ec4ef02bcHans Verkuil#include "msp3400-driver.h"
6253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
6353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* ---------------------------------------------------------------------- */
6453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
6553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans VerkuilMODULE_DESCRIPTION("device driver for msp34xx TV sound processor");
6653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans VerkuilMODULE_AUTHOR("Gerd Knorr");
6753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans VerkuilMODULE_LICENSE("GPL");
6853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
6953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* module parameters */
7053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilstatic int opmode   = OPMODE_AUTO;
71a5ed425cd30c0c2abac4039ae11b38520aa130c2Mauro Carvalho Chehabint msp_debug;		 /* msp_debug output */
7290ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellbool msp_once;		 /* no continuous stereo monitoring */
7390ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellbool msp_amsound;	 /* hard-wire AM sound at 6.5 Hz (france),
74a5ed425cd30c0c2abac4039ae11b38520aa130c2Mauro Carvalho Chehab			    the autoscan seems work well only with FM... */
75d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuilint msp_standard = 1;    /* Override auto detect of audio msp_standard,
76d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil			    if needed. */
7790ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellbool msp_dolby;
7853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
79f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehabint msp_stereo_thresh = 0x190; /* a2 threshold for stereo/bilingual
8053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil					(msp34xxg only) 0x00a0-0x03c0 */
8153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
8253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* read-only */
8353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilmodule_param(opmode,           int, 0444);
8453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
8553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* read-write */
86d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuilmodule_param_named(once, msp_once,                      bool, 0644);
87d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuilmodule_param_named(debug, msp_debug,                    int,  0644);
88d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuilmodule_param_named(stereo_threshold, msp_stereo_thresh, int,  0644);
89d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuilmodule_param_named(standard, msp_standard,              int,  0644);
90d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuilmodule_param_named(amsound, msp_amsound,                bool, 0644);
91d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuilmodule_param_named(dolby, msp_dolby,                    bool, 0644);
9253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
9353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans VerkuilMODULE_PARM_DESC(opmode, "Forces a MSP3400 opmode. 0=Manual, 1=Autodetect, 2=Autodetect and autoselect");
9453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans VerkuilMODULE_PARM_DESC(once, "No continuous stereo monitoring");
9553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans VerkuilMODULE_PARM_DESC(debug, "Enable debug messages [0-3]");
9653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans VerkuilMODULE_PARM_DESC(stereo_threshold, "Sets signal threshold to activate stereo");
9753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans VerkuilMODULE_PARM_DESC(standard, "Specify audio standard: 32 = NTSC, 64 = radio, Default: Autodetect");
9853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans VerkuilMODULE_PARM_DESC(amsound, "Hardwire AM sound at 6.5Hz (France), FM can autoscan");
9970f23fd66bc821a0e99647f70a809e277cc93c4cJustin P. MattockMODULE_PARM_DESC(dolby, "Activates Dolby processing");
10053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
10153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* ---------------------------------------------------------------------- */
10253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
10353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* control subaddress */
10453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil#define I2C_MSP_CONTROL 0x00
10553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* demodulator unit subaddress */
10653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil#define I2C_MSP_DEM     0x10
10753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* DSP unit subaddress */
10853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil#define I2C_MSP_DSP     0x12
10953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
11053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
11153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* ----------------------------------------------------------------------- */
11253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* functions for talking to the MSP3400C Sound processor                   */
11353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
11453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilint msp_reset(struct i2c_client *client)
11553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{
11653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	/* reset and read revision code */
11753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	static u8 reset_off[3] = { I2C_MSP_CONTROL, 0x80, 0x00 };
11853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	static u8 reset_on[3]  = { I2C_MSP_CONTROL, 0x00, 0x00 };
11953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	static u8 write[3]     = { I2C_MSP_DSP + 1, 0x00, 0x1e };
12053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	u8 read[2];
12153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	struct i2c_msg reset[2] = {
1221215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D		{
1231215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.addr = client->addr,
1241215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.flags = I2C_M_IGNORE_NAK,
1251215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.len = 3,
1261215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.buf = reset_off
1271215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D		},
1281215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D		{
1291215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.addr = client->addr,
1301215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.flags = I2C_M_IGNORE_NAK,
1311215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.len = 3,
1321215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.buf = reset_on
1331215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D		},
13453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	};
13553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	struct i2c_msg test[2] = {
1361215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D		{
1371215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.addr = client->addr,
1381215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.len = 3,
1391215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.buf = write
1401215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D		},
1411215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D		{
1421215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.addr = client->addr,
1431215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.flags = I2C_M_RD,
1441215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.len = 2,
1451215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.buf = read
1461215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D		},
14753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	};
14853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
149f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab	v4l_dbg(3, msp_debug, client, "msp_reset\n");
15053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	if (i2c_transfer(client->adapter, &reset[0], 1) != 1 ||
15153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	    i2c_transfer(client->adapter, &reset[1], 1) != 1 ||
15253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	    i2c_transfer(client->adapter, test, 2) != 2) {
1537e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil		v4l_err(client, "chip reset failed\n");
15453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		return -1;
15553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	}
15653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	return 0;
15753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil}
15853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
15953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilstatic int msp_read(struct i2c_client *client, int dev, int addr)
16053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{
16153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	int err, retval;
16253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	u8 write[3];
16353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	u8 read[2];
16453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	struct i2c_msg msgs[2] = {
1651215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D		{
1661215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.addr = client->addr,
1671215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.len = 3,
1681215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.buf = write
1691215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D		},
1701215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D		{
1711215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.addr = client->addr,
1721215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.flags = I2C_M_RD,
1731215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.len = 2,
1741215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D			.buf = read
1751215af48366ff1e2401a0afcedfd3dcdff5f13fdShubhrajyoti D		}
17653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	};
17753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
17853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	write[0] = dev + 1;
17953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	write[1] = addr >> 8;
18053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	write[2] = addr & 0xff;
18153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
18253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	for (err = 0; err < 3; err++) {
18353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		if (i2c_transfer(client->adapter, msgs, 2) == 2)
18453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil			break;
1857e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil		v4l_warn(client, "I/O error #%d (read 0x%02x/0x%02x)\n", err,
18653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		       dev, addr);
187f3a43d3082cd9c2308612e0331ad3b1b9d3a7a33Robert P. J. Day		schedule_timeout_interruptible(msecs_to_jiffies(10));
18853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	}
18953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	if (err == 3) {
190d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		v4l_warn(client, "resetting chip, sound will go off.\n");
19153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		msp_reset(client);
19253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		return -1;
19353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	}
19453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	retval = read[0] << 8 | read[1];
195d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	v4l_dbg(3, msp_debug, client, "msp_read(0x%x, 0x%x): 0x%x\n",
196d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil			dev, addr, retval);
19753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	return retval;
19853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil}
19953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
20053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilint msp_read_dem(struct i2c_client *client, int addr)
20153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{
20253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	return msp_read(client, I2C_MSP_DEM, addr);
20353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil}
20453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
20553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilint msp_read_dsp(struct i2c_client *client, int addr)
20653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{
20753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	return msp_read(client, I2C_MSP_DSP, addr);
20853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil}
20953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
21053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilstatic int msp_write(struct i2c_client *client, int dev, int addr, int val)
21153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{
21253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	int err;
21353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	u8 buffer[5];
21453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
21553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	buffer[0] = dev;
21653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	buffer[1] = addr >> 8;
21753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	buffer[2] = addr &  0xff;
21853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	buffer[3] = val  >> 8;
21953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	buffer[4] = val  &  0xff;
22053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
221d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	v4l_dbg(3, msp_debug, client, "msp_write(0x%x, 0x%x, 0x%x)\n",
222d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil			dev, addr, val);
22353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	for (err = 0; err < 3; err++) {
22453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		if (i2c_master_send(client, buffer, 5) == 5)
22553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil			break;
2267e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil		v4l_warn(client, "I/O error #%d (write 0x%02x/0x%02x)\n", err,
22753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		       dev, addr);
228f3a43d3082cd9c2308612e0331ad3b1b9d3a7a33Robert P. J. Day		schedule_timeout_interruptible(msecs_to_jiffies(10));
22953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	}
23053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	if (err == 3) {
231d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		v4l_warn(client, "resetting chip, sound will go off.\n");
23253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		msp_reset(client);
23353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		return -1;
23453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	}
23553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	return 0;
23653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil}
23753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
23853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilint msp_write_dem(struct i2c_client *client, int addr, int val)
23953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{
24053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	return msp_write(client, I2C_MSP_DEM, addr, val);
24153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil}
24253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
24353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilint msp_write_dsp(struct i2c_client *client, int addr, int val)
24453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{
24553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	return msp_write(client, I2C_MSP_DSP, addr, val);
24653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil}
24753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
24853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* ----------------------------------------------------------------------- *
24953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * bits  9  8  5 - SCART DSP input Select:
25053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *       0  0  0 - SCART 1 to DSP input (reset position)
25153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *       0  1  0 - MONO to DSP input
25253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *       1  0  0 - SCART 2 to DSP input
25353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *       1  1  1 - Mute DSP input
25453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *
25553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * bits 11 10  6 - SCART 1 Output Select:
25653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *       0  0  0 - undefined (reset position)
25753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *       0  1  0 - SCART 2 Input to SCART 1 Output (for devices with 2 SCARTS)
25853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *       1  0  0 - MONO input to SCART 1 Output
25953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *       1  1  0 - SCART 1 DA to SCART 1 Output
26053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *       0  0  1 - SCART 2 DA to SCART 1 Output
26153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *       0  1  1 - SCART 1 Input to SCART 1 Output
26253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *       1  1  1 - Mute SCART 1 Output
26353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *
26453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * bits 13 12  7 - SCART 2 Output Select (for devices with 2 Output SCART):
26553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *       0  0  0 - SCART 1 DA to SCART 2 Output (reset position)
26653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *       0  1  0 - SCART 1 Input to SCART 2 Output
26753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *       1  0  0 - MONO input to SCART 2 Output
26853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *       0  0  1 - SCART 2 DA to SCART 2 Output
26953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *       0  1  1 - SCART 2 Input to SCART 2 Output
27053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *       1  1  0 - Mute SCART 2 Output
27153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil *
27253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * Bits 4 to 0 should be zero.
27353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * ----------------------------------------------------------------------- */
27453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
27553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilstatic int scarts[3][9] = {
276b930e1d851c3ffbf82127bd0e4d72ffe94d4b7f2Michael Krufky	/* MASK   IN1     IN2     IN3     IN4     IN1_DA  IN2_DA  MONO    MUTE   */
27753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	/* SCART DSP Input select */
278b930e1d851c3ffbf82127bd0e4d72ffe94d4b7f2Michael Krufky	{ 0x0320, 0x0000, 0x0200, 0x0300, 0x0020, -1,     -1,     0x0100, 0x0320 },
27953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	/* SCART1 Output select */
280b930e1d851c3ffbf82127bd0e4d72ffe94d4b7f2Michael Krufky	{ 0x0c40, 0x0440, 0x0400, 0x0000, 0x0840, 0x0c00, 0x0040, 0x0800, 0x0c40 },
28153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	/* SCART2 Output select */
282b930e1d851c3ffbf82127bd0e4d72ffe94d4b7f2Michael Krufky	{ 0x3080, 0x1000, 0x1080, 0x2080, 0x3080, 0x0000, 0x0080, 0x2000, 0x3000 },
28353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil};
28453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
28553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilstatic char *scart_names[] = {
286b930e1d851c3ffbf82127bd0e4d72ffe94d4b7f2Michael Krufky	"in1", "in2", "in3", "in4", "in1 da", "in2 da", "mono", "mute"
28753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil};
28853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
28953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilvoid msp_set_scart(struct i2c_client *client, int in, int out)
29053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{
29176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	struct msp_state *state = to_state(i2c_get_clientdata(client));
29253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
293427725748b38997628d95ffdf8501bcc176cf631Hans Verkuil	state->in_scart = in;
29453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
295427725748b38997628d95ffdf8501bcc176cf631Hans Verkuil	if (in >= 0 && in <= 7 && out >= 0 && out <= 2) {
296427725748b38997628d95ffdf8501bcc176cf631Hans Verkuil		if (-1 == scarts[out][in + 1])
29753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil			return;
29853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
299427725748b38997628d95ffdf8501bcc176cf631Hans Verkuil		state->acb &= ~scarts[out][0];
300427725748b38997628d95ffdf8501bcc176cf631Hans Verkuil		state->acb |=  scarts[out][in + 1];
30153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	} else
30253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		state->acb = 0xf60; /* Mute Input and SCART 1 Output */
30353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
304f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab	v4l_dbg(1, msp_debug, client, "scart switch: %s => %d (ACB=0x%04x)\n",
305d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil					scart_names[in], out, state->acb);
30653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	msp_write_dsp(client, 0x13, state->acb);
30753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
30853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	/* Sets I2S speed 0 = 1.024 Mbps, 1 = 2.048 Mbps */
309dc555aa63c798af097f5c303bcf72a8390b03da5Hans Verkuil	if (state->has_i2s_conf)
310dc555aa63c798af097f5c303bcf72a8390b03da5Hans Verkuil		msp_write_dem(client, 0x40, state->i2s_mode);
31153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil}
31253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
31353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* ------------------------------------------------------------------------ */
31453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
31553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilstatic void msp_wake_thread(struct i2c_client *client)
31653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{
31776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	struct msp_state *state = to_state(i2c_get_clientdata(client));
31853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
31953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	if (NULL == state->kthread)
32053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		return;
32153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	state->watch_stereo = 0;
32253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	state->restart = 1;
32353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	wake_up_interruptible(&state->wq);
32453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil}
32553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
32653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuilint msp_sleep(struct msp_state *state, int timeout)
32753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{
32853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	DECLARE_WAITQUEUE(wait, current);
32953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
33053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	add_wait_queue(&state->wq, &wait);
33153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	if (!kthread_should_stop()) {
33253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		if (timeout < 0) {
33353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil			set_current_state(TASK_INTERRUPTIBLE);
33453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil			schedule();
33553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		} else {
33653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil			schedule_timeout_interruptible
33753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil						(msecs_to_jiffies(timeout));
33853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		}
33953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	}
34053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
34153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	remove_wait_queue(&state->wq, &wait);
34253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	try_to_freeze();
34353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	return state->restart;
34453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil}
34553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
34653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* ------------------------------------------------------------------------ */
34753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
348ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuilstatic int msp_s_ctrl(struct v4l2_ctrl *ctrl)
34953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{
350ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	struct msp_state *state = ctrl_to_state(ctrl);
351ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	struct i2c_client *client = v4l2_get_subdevdata(&state->sd);
352ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	int val = ctrl->val;
35353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
35453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	switch (ctrl->id) {
355ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	case V4L2_CID_AUDIO_VOLUME: {
356ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		/* audio volume cluster */
357ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		int reallymuted = state->muted->val | state->scan_in_progress;
358ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil
359ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		if (!reallymuted)
360ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil			val = (val * 0x7f / 65535) << 8;
361ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil
362ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		v4l_dbg(1, msp_debug, client, "mute=%s scanning=%s volume=%d\n",
363ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil				state->muted->val ? "on" : "off",
364ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil				state->scan_in_progress ? "yes" : "no",
365ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil				state->volume->val);
366ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil
367ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		msp_write_dsp(client, 0x0000, val);
368ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		msp_write_dsp(client, 0x0007, reallymuted ? 0x1 : (val | 0x1));
369ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		if (state->has_scart2_out_volume)
370ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil			msp_write_dsp(client, 0x0040, reallymuted ? 0x1 : (val | 0x1));
371ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		if (state->has_headphones)
372ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil			msp_write_dsp(client, 0x0006, val);
37353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		break;
37453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	}
37553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
37653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	case V4L2_CID_AUDIO_BASS:
377ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		val = ((val - 32768) * 0x60 / 65535) << 8;
378ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		msp_write_dsp(client, 0x0002, val);
379ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		if (state->has_headphones)
380ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil			msp_write_dsp(client, 0x0031, val);
38153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		break;
38253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
38353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	case V4L2_CID_AUDIO_TREBLE:
384ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		val = ((val - 32768) * 0x60 / 65535) << 8;
385ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		msp_write_dsp(client, 0x0003, val);
386ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		if (state->has_headphones)
387ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil			msp_write_dsp(client, 0x0032, val);
38853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		break;
38953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
390d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil	case V4L2_CID_AUDIO_LOUDNESS:
391ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		val = val ? ((5 * 4) << 8) : 0;
392ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		msp_write_dsp(client, 0x0004, val);
393ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		if (state->has_headphones)
394ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil			msp_write_dsp(client, 0x0033, val);
39553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		break;
39653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
397d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil	case V4L2_CID_AUDIO_BALANCE:
398ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		val = (u8)((val / 256) - 128);
399ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		msp_write_dsp(client, 0x0001, val << 8);
400ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		if (state->has_headphones)
401ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil			msp_write_dsp(client, 0x0030, val << 8);
40253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		break;
40353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
40453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	default:
40553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		return -EINVAL;
40653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	}
40753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	return 0;
40853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil}
40953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
410ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuilvoid msp_update_volume(struct msp_state *state)
411ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil{
4120310871d8f71da4ad8643687fbc40f219a0dac4dHans Verkuil	/* Force an update of the volume/mute cluster */
4130310871d8f71da4ad8643687fbc40f219a0dac4dHans Verkuil	v4l2_ctrl_lock(state->volume);
4140310871d8f71da4ad8643687fbc40f219a0dac4dHans Verkuil	state->volume->val = state->volume->cur.val;
4150310871d8f71da4ad8643687fbc40f219a0dac4dHans Verkuil	state->muted->val = state->muted->cur.val;
4160310871d8f71da4ad8643687fbc40f219a0dac4dHans Verkuil	msp_s_ctrl(state->volume);
4170310871d8f71da4ad8643687fbc40f219a0dac4dHans Verkuil	v4l2_ctrl_unlock(state->volume);
418ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil}
419ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil
42076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil/* --- v4l2 ioctls --- */
42176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuilstatic int msp_s_radio(struct v4l2_subdev *sd)
42276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil{
42376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	struct msp_state *state = to_state(sd);
42476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	struct i2c_client *client = v4l2_get_subdevdata(sd);
42553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
42676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	if (state->radio)
42753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		return 0;
42876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	state->radio = 1;
42976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	v4l_dbg(1, msp_debug, client, "switching to radio mode\n");
43076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	state->watch_stereo = 0;
43176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	switch (state->opmode) {
43276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	case OPMODE_MANUAL:
43376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil		/* set msp3400 to FM radio mode */
43476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil		msp3400c_set_mode(client, MSP_MODE_FM_RADIO);
43576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil		msp3400c_set_carrier(client, MSP_CARRIER(10.7),
43676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil				MSP_CARRIER(10.7));
437ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		msp_update_volume(state);
43876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil		break;
43976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	case OPMODE_AUTODETECT:
44076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	case OPMODE_AUTOSELECT:
44176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil		/* the thread will do for us */
44276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil		msp_wake_thread(client);
44376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil		break;
44453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	}
44576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	return 0;
44676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil}
44753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
448b530a447bb588fdf43fdf4eb909e4ee1921d47acHans Verkuilstatic int msp_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *freq)
44976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil{
45076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	struct i2c_client *client = v4l2_get_subdevdata(sd);
45153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
45276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	/* new channel -- kick audio carrier scan */
45376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	msp_wake_thread(client);
45476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	return 0;
45576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil}
4562474ed444b475614ef795523076be7cc8437ae00Hans Verkuil
4575d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehabstatic int msp_querystd(struct v4l2_subdev *sd, v4l2_std_id *id)
4585d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab{
4595d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab	struct msp_state *state = to_state(sd);
4605d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab	struct i2c_client *client = v4l2_get_subdevdata(sd);
4615d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab
4625d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab	*id &= state->detected_std;
4635d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab
4645d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab	v4l_dbg(2, msp_debug, client,
4655d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab		"detected standard: %s(0x%08Lx)\n",
4665d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab		msp_standard_std_name(state->std), state->detected_std);
4675d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab
4685d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab	return 0;
4695d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab}
4705d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab
47176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuilstatic int msp_s_std(struct v4l2_subdev *sd, v4l2_std_id id)
47276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil{
47376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	struct msp_state *state = to_state(sd);
47476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	struct i2c_client *client = v4l2_get_subdevdata(sd);
47576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	int update = state->radio || state->v4l2_std != id;
47676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil
47776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	state->v4l2_std = id;
47876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	state->radio = 0;
47976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	if (update)
4802eb606db1134ce860cc0cbf8b533b6315d182e21Hans Verkuil		msp_wake_thread(client);
48176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	return 0;
48276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil}
48376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil
4845325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuilstatic int msp_s_routing(struct v4l2_subdev *sd,
4855325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil			 u32 input, u32 output, u32 config)
48676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil{
48776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	struct msp_state *state = to_state(sd);
48876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	struct i2c_client *client = v4l2_get_subdevdata(sd);
4895325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	int tuner = (input >> 3) & 1;
4905325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	int sc_in = input & 0x7;
4915325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	int sc1_out = output & 0xf;
4925325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	int sc2_out = (output >> 4) & 0xf;
49376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	u16 val, reg;
49476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	int i;
49576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	int extern_input = 1;
49676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil
4975325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	if (state->route_in == input && state->route_out == output)
49876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil		return 0;
4995325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	state->route_in = input;
5005325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	state->route_out = output;
50176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	/* check if the tuner input is used */
50276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	for (i = 0; i < 5; i++) {
5035325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		if (((input >> (4 + i * 4)) & 0xf) == 0)
50476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil			extern_input = 0;
50553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	}
50676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	state->mode = extern_input ? MSP_MODE_EXTERN : MSP_MODE_AM_DETECT;
50776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	state->rxsubchans = V4L2_TUNER_SUB_STEREO;
50876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	msp_set_scart(client, sc_in, 0);
50976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	msp_set_scart(client, sc1_out, 1);
51076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	msp_set_scart(client, sc2_out, 2);
51176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	msp_set_audmode(client);
51276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	reg = (state->opmode == OPMODE_AUTOSELECT) ? 0x30 : 0xbb;
51376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	val = msp_read_dem(client, reg);
51476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	msp_write_dem(client, reg, (val & ~0x100) | (tuner << 8));
51576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	/* wake thread when a new input is chosen */
51676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	msp_wake_thread(client);
51776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	return 0;
51876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil}
51953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
52076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuilstatic int msp_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
52176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil{
52276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	struct msp_state *state = to_state(sd);
52376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	struct i2c_client *client = v4l2_get_subdevdata(sd);
52453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
525ddc6ff31cc22720c46c1547a5310ea260a968ae9Hans Verkuil	if (vt->type != V4L2_TUNER_ANALOG_TV)
52676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil		return 0;
527ddc6ff31cc22720c46c1547a5310ea260a968ae9Hans Verkuil	if (!state->radio) {
528ddc6ff31cc22720c46c1547a5310ea260a968ae9Hans Verkuil		if (state->opmode == OPMODE_AUTOSELECT)
529ddc6ff31cc22720c46c1547a5310ea260a968ae9Hans Verkuil			msp_detect_stereo(client);
530ddc6ff31cc22720c46c1547a5310ea260a968ae9Hans Verkuil		vt->rxsubchans = state->rxsubchans;
531ddc6ff31cc22720c46c1547a5310ea260a968ae9Hans Verkuil	}
532ddc6ff31cc22720c46c1547a5310ea260a968ae9Hans Verkuil	vt->audmode = state->audmode;
53376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	vt->capability |= V4L2_TUNER_CAP_STEREO |
53476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil		V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
53576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	return 0;
53676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil}
53753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
5382f73c7c582a685b3198b974cd6d964d0338f8ab5Hans Verkuilstatic int msp_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
53976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil{
54076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	struct msp_state *state = to_state(sd);
54176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	struct i2c_client *client = v4l2_get_subdevdata(sd);
54253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
54376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	if (state->radio)  /* TODO: add mono/stereo support for radio */
54476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil		return 0;
54576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	if (state->audmode == vt->audmode)
54676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil		return 0;
54776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	state->audmode = vt->audmode;
54876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	/* only set audmode */
54976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	msp_set_audmode(client);
55076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	return 0;
55176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil}
55253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
55376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuilstatic int msp_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq)
55476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil{
55576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	struct msp_state *state = to_state(sd);
55676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	struct i2c_client *client = v4l2_get_subdevdata(sd);
55753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
55876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	v4l_dbg(1, msp_debug, client, "Setting I2S speed to %d\n", freq);
55953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
56076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	switch (freq) {
561d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		case 1024000:
562d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil			state->i2s_mode = 0;
563d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil			break;
564d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		case 2048000:
565d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil			state->i2s_mode = 1;
566d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil			break;
567d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		default:
568d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil			return -EINVAL;
56953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	}
57076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	return 0;
57176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil}
57253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
57376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuilstatic int msp_log_status(struct v4l2_subdev *sd)
57476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil{
57576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	struct msp_state *state = to_state(sd);
57676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	struct i2c_client *client = v4l2_get_subdevdata(sd);
57776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	const char *p;
578ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	char prefix[V4L2_SUBDEV_NAME_SIZE + 20];
57976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil
58076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	if (state->opmode == OPMODE_AUTOSELECT)
58176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil		msp_detect_stereo(client);
58276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n",
58376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil			client->name, state->rev1, state->rev2);
584ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	snprintf(prefix, sizeof(prefix), "%s: Audio:    ", sd->name);
585ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	v4l2_ctrl_handler_log_status(&state->hdl, prefix);
58676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	switch (state->mode) {
5875af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil		case MSP_MODE_AM_DETECT: p = "AM (for carrier detect)"; break;
5885af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil		case MSP_MODE_FM_RADIO: p = "FM Radio"; break;
58925985edcedea6396277003854657b5f3cb31a628Lucas De Marchi		case MSP_MODE_FM_TERRA: p = "Terrestrial FM-mono/stereo"; break;
5905af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil		case MSP_MODE_FM_SAT: p = "Satellite FM-mono"; break;
5915af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil		case MSP_MODE_FM_NICAM1: p = "NICAM/FM (B/G, D/K)"; break;
5925af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil		case MSP_MODE_FM_NICAM2: p = "NICAM/FM (I)"; break;
5935af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil		case MSP_MODE_AM_NICAM: p = "NICAM/AM (L)"; break;
5945af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil		case MSP_MODE_BTSC: p = "BTSC"; break;
5955af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil		case MSP_MODE_EXTERN: p = "External input"; break;
5965af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil		default: p = "unknown"; break;
59776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	}
59876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	if (state->mode == MSP_MODE_EXTERN) {
59976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil		v4l_info(client, "Mode:     %s\n", p);
60076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	} else if (state->opmode == OPMODE_MANUAL) {
60176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil		v4l_info(client, "Mode:     %s (%s%s)\n", p,
6025af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil				(state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono",
6035af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil				(state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : "");
60476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	} else {
60576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil		if (state->opmode == OPMODE_AUTODETECT)
60676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil			v4l_info(client, "Mode:     %s\n", p);
60776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil		v4l_info(client, "Standard: %s (%s%s)\n",
6085af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil				msp_standard_std_name(state->std),
6095af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil				(state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono",
6105af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil				(state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : "");
61153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	}
61276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	v4l_info(client, "Audmode:  0x%04x\n", state->audmode);
61376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	v4l_info(client, "Routing:  0x%08x (input) 0x%08x (output)\n",
6145325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil			state->route_in, state->route_out);
61576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	v4l_info(client, "ACB:      0x%04x\n", state->acb);
61653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	return 0;
61753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil}
61853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
6195cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brown#ifdef CONFIG_PM_SLEEP
6205cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brownstatic int msp_suspend(struct device *dev)
62153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{
6225cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brown	struct i2c_client *client = to_i2c_client(dev);
623f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab	v4l_dbg(1, msp_debug, client, "suspend\n");
62453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	msp_reset(client);
62553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	return 0;
62653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil}
62753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
6285cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brownstatic int msp_resume(struct device *dev)
62953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{
6305cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brown	struct i2c_client *client = to_i2c_client(dev);
631f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab	v4l_dbg(1, msp_debug, client, "resume\n");
63253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	msp_wake_thread(client);
63353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	return 0;
63453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil}
6355cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brown#endif
63653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
63776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil/* ----------------------------------------------------------------------- */
63876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil
639ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuilstatic const struct v4l2_ctrl_ops msp_ctrl_ops = {
640ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	.s_ctrl = msp_s_ctrl,
641ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil};
642ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil
64376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuilstatic const struct v4l2_subdev_core_ops msp_core_ops = {
64476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	.log_status = msp_log_status,
645ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
646ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
647ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
648ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	.g_ctrl = v4l2_subdev_g_ctrl,
649ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	.s_ctrl = v4l2_subdev_s_ctrl,
650ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	.queryctrl = v4l2_subdev_queryctrl,
651ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	.querymenu = v4l2_subdev_querymenu,
65276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil};
65376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil
6545d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehabstatic const struct v4l2_subdev_video_ops msp_video_ops = {
6558774bed9ce832d8d9ccb79e92800b808aa2d2ad2Laurent Pinchart	.s_std = msp_s_std,
6565d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab	.querystd = msp_querystd,
6575d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab};
6585d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab
65976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuilstatic const struct v4l2_subdev_tuner_ops msp_tuner_ops = {
66076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	.s_frequency = msp_s_frequency,
66176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	.g_tuner = msp_g_tuner,
66276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	.s_tuner = msp_s_tuner,
66376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	.s_radio = msp_s_radio,
66476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil};
66576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil
66676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuilstatic const struct v4l2_subdev_audio_ops msp_audio_ops = {
66776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	.s_routing = msp_s_routing,
66876efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	.s_i2s_clock_freq = msp_s_i2s_clock_freq,
66976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil};
67076efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil
67176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuilstatic const struct v4l2_subdev_ops msp_ops = {
67276efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	.core = &msp_core_ops,
6735d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab	.video = &msp_video_ops,
67476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	.tuner = &msp_tuner_ops,
67576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	.audio = &msp_audio_ops,
67676efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil};
67776efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil
67853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* ----------------------------------------------------------------------- */
67953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
680d2653e92732bd3911feff6bee5e23dbf959381dbJean Delvarestatic int msp_probe(struct i2c_client *client, const struct i2c_device_id *id)
68153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{
68253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	struct msp_state *state;
68376efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	struct v4l2_subdev *sd;
684ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	struct v4l2_ctrl_handler *hdl;
68553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	int (*thread_func)(void *data) = NULL;
6867560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil	int msp_hard;
6877560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil	int msp_family;
6887560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil	int msp_revision;
6897560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil	int msp_product, msp_prod_hi, msp_prod_lo;
6907560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil	int msp_rom;
69153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
692af294867a52bf718df835a688e8c786d550bee26Jean Delvare	if (!id)
693af294867a52bf718df835a688e8c786d550bee26Jean Delvare		strlcpy(client->name, "msp3400", sizeof(client->name));
69453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
69553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	if (msp_reset(client) == -1) {
696f167cb4e6ee07914b66eb85fc0bf006a409b6838Mauro Carvalho Chehab		v4l_dbg(1, msp_debug, client, "msp3400 not found\n");
697188f3457c21ac7869005021b56b4578293c644bbHans Verkuil		return -ENODEV;
69853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	}
69953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
700c02b211df6fc54e51ee554c27a6736a11255a764Laurent Pinchart	state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
701d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	if (!state)
70253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		return -ENOMEM;
703b2a657603e7285bf05b86ad198111b5403c57b41Mariusz Kozlowski
70476efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	sd = &state->sd;
70576efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	v4l2_i2c_subdev_init(sd, client, &msp_ops);
70653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
7075af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil	state->v4l2_std = V4L2_STD_NTSC;
7085d1ed98683abafef595b8e3a237f845b82152606Mauro Carvalho Chehab	state->detected_std = V4L2_STD_ALL;
7090020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil	state->audmode = V4L2_TUNER_MODE_STEREO;
71053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	state->input = -1;
71153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	state->i2s_mode = 0;
71253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	init_waitqueue_head(&state->wq);
7132474ed444b475614ef795523076be7cc8437ae00Hans Verkuil	/* These are the reset input/output positions */
7145325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	state->route_in = MSP_INPUT_DEFAULT;
7155325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	state->route_out = MSP_OUTPUT_DEFAULT;
71653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
71753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	state->rev1 = msp_read_dsp(client, 0x1e);
71853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	if (state->rev1 != -1)
71953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		state->rev2 = msp_read_dsp(client, 0x1f);
720d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	v4l_dbg(1, msp_debug, client, "rev1=0x%04x, rev2=0x%04x\n",
721d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil			state->rev1, state->rev2);
72253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	if (state->rev1 == -1 || (state->rev1 == 0 && state->rev2 == 0)) {
723d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		v4l_dbg(1, msp_debug, client,
724d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil				"not an msp3400 (cannot read chip version)\n");
725188f3457c21ac7869005021b56b4578293c644bbHans Verkuil		return -ENODEV;
72653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	}
72753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
7287560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil	msp_family = ((state->rev1 >> 4) & 0x0f) + 3;
7297560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil	msp_product = (state->rev2 >> 8) & 0xff;
7307560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil	msp_prod_hi = msp_product / 10;
7317560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil	msp_prod_lo = msp_product % 10;
7327560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil	msp_revision = (state->rev1 & 0x0f) + '@';
7337560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil	msp_hard = ((state->rev1 >> 8) & 0xff) + '@';
7347560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil	msp_rom = state->rev2 & 0x1f;
73574cab31c413c8615efe818d44ff4ac83e2a138beHans Verkuil	/* Rev B=2, C=3, D=4, G=7 */
736d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	state->ident = msp_family * 10000 + 4000 + msp_product * 10 +
737d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil			msp_revision - '@';
7387560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil
7397560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil	/* Has NICAM support: all mspx41x and mspx45x products have NICAM */
740d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	state->has_nicam =
741d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		msp_prod_hi == 1 || msp_prod_hi == 5;
7427560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil	/* Has radio support: was added with revision G */
743d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	state->has_radio =
744d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		msp_revision >= 'G';
7457560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil	/* Has headphones output: not for stripped down products */
746d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	state->has_headphones =
747d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		msp_prod_lo < 5;
7480020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil	/* Has scart2 input: not in stripped down products of the '3' family */
749d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	state->has_scart2 =
750d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		msp_family >= 4 || msp_prod_lo < 7;
7510020d3ef915fc01a0184bc96eeb3c240bded5d8eHans Verkuil	/* Has scart3 input: not in stripped down products of the '3' family */
752d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	state->has_scart3 =
753d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		msp_family >= 4 || msp_prod_lo < 5;
7547560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil	/* Has scart4 input: not in pre D revisions, not in stripped D revs */
755d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	state->has_scart4 =
756d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		msp_family >= 4 || (msp_revision >= 'D' && msp_prod_lo < 5);
757d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	/* Has scart2 output: not in stripped down products of
758d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	 * the '3' family */
759d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	state->has_scart2_out =
760d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		msp_family >= 4 || msp_prod_lo < 5;
761d312a46e5340be6a89c662ac483230c0737148c9Hans Verkuil	/* Has scart2 a volume control? Not in pre-D revisions. */
762d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	state->has_scart2_out_volume =
763d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		msp_revision > 'C' && state->has_scart2_out;
7645af0c8f6a09534ebc6c56b4e5d79d0d521364750Hans Verkuil	/* Has a configurable i2s out? */
765d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	state->has_i2s_conf =
766d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		msp_revision >= 'G' && msp_prod_lo < 7;
767d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	/* Has subwoofer output: not in pre-D revs and not in stripped down
768d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	 * products */
769d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	state->has_subwoofer =
770d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		msp_revision >= 'D' && msp_prod_lo < 5;
771d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	/* Has soundprocessing (bass/treble/balance/loudness/equalizer):
772d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	 *  not in stripped down products */
773d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	state->has_sound_processing =
774d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		msp_prod_lo < 7;
7757560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil	/* Has Virtual Dolby Surround: only in msp34x1 */
776d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	state->has_virtual_dolby_surround =
777d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		msp_revision == 'G' && msp_prod_lo == 1;
7787560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil	/* Has Virtual Dolby Surround & Dolby Pro Logic: only in msp34x2 */
779d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	state->has_dolby_pro_logic =
780d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		msp_revision == 'G' && msp_prod_lo == 2;
781d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	/* The msp343xG supports BTSC only and cannot do Automatic Standard
782d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	 * Detection. */
783d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	state->force_btsc =
784d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		msp_family == 3 && msp_revision == 'G' && msp_prod_hi == 3;
78553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
78653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	state->opmode = opmode;
78753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	if (state->opmode == OPMODE_AUTO) {
78853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		/* MSP revision G and up have both autodetect and autoselect */
7897560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil		if (msp_revision >= 'G')
79053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil			state->opmode = OPMODE_AUTOSELECT;
79153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		/* MSP revision D and up have autodetect */
7927560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil		else if (msp_revision >= 'D')
79353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil			state->opmode = OPMODE_AUTODETECT;
79453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		else
79553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil			state->opmode = OPMODE_MANUAL;
79653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	}
79753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
798ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	hdl = &state->hdl;
799ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	v4l2_ctrl_handler_init(hdl, 6);
800ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	if (state->has_sound_processing) {
801ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		v4l2_ctrl_new_std(hdl, &msp_ctrl_ops,
802ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil			V4L2_CID_AUDIO_BASS, 0, 65535, 65535 / 100, 32768);
803ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		v4l2_ctrl_new_std(hdl, &msp_ctrl_ops,
804ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil			V4L2_CID_AUDIO_TREBLE, 0, 65535, 65535 / 100, 32768);
805ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		v4l2_ctrl_new_std(hdl, &msp_ctrl_ops,
806ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil			V4L2_CID_AUDIO_LOUDNESS, 0, 1, 1, 0);
807ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	}
808ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	state->volume = v4l2_ctrl_new_std(hdl, &msp_ctrl_ops,
809ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil			V4L2_CID_AUDIO_VOLUME, 0, 65535, 65535 / 100, 58880);
810ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	v4l2_ctrl_new_std(hdl, &msp_ctrl_ops,
811ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil			V4L2_CID_AUDIO_BALANCE, 0, 65535, 65535 / 100, 32768);
812ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	state->muted = v4l2_ctrl_new_std(hdl, &msp_ctrl_ops,
813ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
814ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	sd->ctrl_handler = hdl;
815ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	if (hdl->error) {
816ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		int err = hdl->error;
817ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil
818ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		v4l2_ctrl_handler_free(hdl);
819ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil		return err;
820ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	}
821ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil
822ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	v4l2_ctrl_cluster(2, &state->volume);
823ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	v4l2_ctrl_handler_setup(hdl);
824ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil
82553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	/* hello world :-) */
826af294867a52bf718df835a688e8c786d550bee26Jean Delvare	v4l_info(client, "MSP%d4%02d%c-%c%d found @ 0x%x (%s)\n",
827af294867a52bf718df835a688e8c786d550bee26Jean Delvare			msp_family, msp_product,
828af294867a52bf718df835a688e8c786d550bee26Jean Delvare			msp_revision, msp_hard, msp_rom,
829d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil			client->addr << 1, client->adapter->name);
8307e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil	v4l_info(client, "%s ", client->name);
8317560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil	if (state->has_nicam && state->has_radio)
832d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		printk(KERN_CONT "supports nicam and radio, ");
8337560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil	else if (state->has_nicam)
834d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		printk(KERN_CONT "supports nicam, ");
8357560d7a4f9add362d60d4513033cf522c37adeeaHans Verkuil	else if (state->has_radio)
836d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		printk(KERN_CONT "supports radio, ");
837d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	printk(KERN_CONT "mode is ");
83853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
83953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	/* version-specific initialization */
84053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	switch (state->opmode) {
84153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	case OPMODE_MANUAL:
842d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		printk(KERN_CONT "manual");
84353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		thread_func = msp3400c_thread;
84453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		break;
84553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	case OPMODE_AUTODETECT:
846d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		printk(KERN_CONT "autodetect");
84753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		thread_func = msp3410d_thread;
84853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		break;
84953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	case OPMODE_AUTOSELECT:
850d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil		printk(KERN_CONT "autodetect and autoselect");
85153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		thread_func = msp34xxg_thread;
85253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		break;
85353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	}
854d52c7385ec8d4d2081b0db47e309723ce3eae816Hans Verkuil	printk(KERN_CONT "\n");
85553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
85653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	/* startup control thread if needed */
85753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	if (thread_func) {
85853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		state->kthread = kthread_run(thread_func, client, "msp34xx");
85953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
86025821400359d2b3daacfb93303944211b8411ac3Akinobu Mita		if (IS_ERR(state->kthread))
8617e8b09ea1636e360a8fabebeaeb91c17f64e01b5Hans Verkuil			v4l_warn(client, "kernel_thread() failed\n");
86253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		msp_wake_thread(client);
86353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	}
86453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	return 0;
86553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil}
86653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
86779518dafd59a812bb390f201c6f18a8f875fcffbHans Verkuilstatic int msp_remove(struct i2c_client *client)
86853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil{
86976efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	struct msp_state *state = to_state(i2c_get_clientdata(client));
87053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
87176efd62f1546c6fab2116d3ba832403387bd3d4aHans Verkuil	v4l2_device_unregister_subdev(&state->sd);
87253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	/* shutdown control thread */
87353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	if (state->kthread) {
87453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		state->restart = 1;
87553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil		kthread_stop(state->kthread);
87653b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	}
87753b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	msp_reset(client);
87853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
879ebc3bba5833e7021336f09767347a52448a60bc5Hans Verkuil	v4l2_ctrl_handler_free(&state->hdl);
88053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil	return 0;
88153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil}
88253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
88353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/* ----------------------------------------------------------------------- */
88453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
8855cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brownstatic const struct dev_pm_ops msp3400_pm_ops = {
8865cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brown	SET_SYSTEM_SLEEP_PM_OPS(msp_suspend, msp_resume)
8875cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brown};
8885cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brown
889af294867a52bf718df835a688e8c786d550bee26Jean Delvarestatic const struct i2c_device_id msp_id[] = {
890af294867a52bf718df835a688e8c786d550bee26Jean Delvare	{ "msp3400", 0 },
891af294867a52bf718df835a688e8c786d550bee26Jean Delvare	{ }
892af294867a52bf718df835a688e8c786d550bee26Jean Delvare};
893af294867a52bf718df835a688e8c786d550bee26Jean DelvareMODULE_DEVICE_TABLE(i2c, msp_id);
894af294867a52bf718df835a688e8c786d550bee26Jean Delvare
89561a489c8ba33c8ef11e3a8b55c22afe834bdf1d4Hans Verkuilstatic struct i2c_driver msp_driver = {
89661a489c8ba33c8ef11e3a8b55c22afe834bdf1d4Hans Verkuil	.driver = {
89761a489c8ba33c8ef11e3a8b55c22afe834bdf1d4Hans Verkuil		.owner	= THIS_MODULE,
89861a489c8ba33c8ef11e3a8b55c22afe834bdf1d4Hans Verkuil		.name	= "msp3400",
8995cbd28df305ab29b7e43bd8e901e7824f7ed9417Mark Brown		.pm	= &msp3400_pm_ops,
90061a489c8ba33c8ef11e3a8b55c22afe834bdf1d4Hans Verkuil	},
90161a489c8ba33c8ef11e3a8b55c22afe834bdf1d4Hans Verkuil	.probe		= msp_probe,
90261a489c8ba33c8ef11e3a8b55c22afe834bdf1d4Hans Verkuil	.remove		= msp_remove,
90361a489c8ba33c8ef11e3a8b55c22afe834bdf1d4Hans Verkuil	.id_table	= msp_id,
90453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil};
90553b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil
906c6e8d86fffd8edf1bfccbd441b1812ee919fe3d5Axel Linmodule_i2c_driver(msp_driver);
90761a489c8ba33c8ef11e3a8b55c22afe834bdf1d4Hans Verkuil
90853b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil/*
90953b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * Overrides for Emacs so that we follow Linus's tabbing style.
91053b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * ---------------------------------------------------------------------------
91153b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * Local variables:
91253b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * c-basic-offset: 8
91353b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil * End:
91453b0a1c60bcc167534b31f56adfbbe2919e6f80bHans Verkuil */
915