xref: /OK3568_Linux_fs/kernel/drivers/media/i2c/tvaudio.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Driver for simple i2c audio chips.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (c) 2000 Gerd Knorr
5*4882a593Smuzhiyun  * based on code by:
6*4882a593Smuzhiyun  *   Eric Sandeen (eric_sandeen@bigfoot.com)
7*4882a593Smuzhiyun  *   Steve VanDeBogart (vandebo@uclink.berkeley.edu)
8*4882a593Smuzhiyun  *   Greg Alexander (galexand@acm.org)
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * For the TDA9875 part:
11*4882a593Smuzhiyun  * Copyright (c) 2000 Guillaume Delvit based on Gerd Knorr source
12*4882a593Smuzhiyun  * and Eric Sandeen
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * Copyright(c) 2005-2008 Mauro Carvalho Chehab
15*4882a593Smuzhiyun  *	- Some cleanups, code fixes, etc
16*4882a593Smuzhiyun  *	- Convert it to V4L2 API
17*4882a593Smuzhiyun  *
18*4882a593Smuzhiyun  * This code is placed under the terms of the GNU General Public License
19*4882a593Smuzhiyun  *
20*4882a593Smuzhiyun  * OPTIONS:
21*4882a593Smuzhiyun  *   debug - set to 1 if you'd like to see debug messages
22*4882a593Smuzhiyun  *
23*4882a593Smuzhiyun  */
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #include <linux/module.h>
26*4882a593Smuzhiyun #include <linux/kernel.h>
27*4882a593Smuzhiyun #include <linux/sched.h>
28*4882a593Smuzhiyun #include <linux/string.h>
29*4882a593Smuzhiyun #include <linux/timer.h>
30*4882a593Smuzhiyun #include <linux/delay.h>
31*4882a593Smuzhiyun #include <linux/errno.h>
32*4882a593Smuzhiyun #include <linux/slab.h>
33*4882a593Smuzhiyun #include <linux/videodev2.h>
34*4882a593Smuzhiyun #include <linux/i2c.h>
35*4882a593Smuzhiyun #include <linux/init.h>
36*4882a593Smuzhiyun #include <linux/kthread.h>
37*4882a593Smuzhiyun #include <linux/freezer.h>
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun #include <media/i2c/tvaudio.h>
40*4882a593Smuzhiyun #include <media/v4l2-device.h>
41*4882a593Smuzhiyun #include <media/v4l2-ctrls.h>
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
44*4882a593Smuzhiyun /* insmod args                                                            */
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun static int debug;	/* insmod parameter */
47*4882a593Smuzhiyun module_param(debug, int, 0644);
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun MODULE_DESCRIPTION("device driver for various i2c TV sound decoder / audiomux chips");
50*4882a593Smuzhiyun MODULE_AUTHOR("Eric Sandeen, Steve VanDeBogart, Greg Alexander, Gerd Knorr");
51*4882a593Smuzhiyun MODULE_LICENSE("GPL");
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun #define UNSET    (-1U)
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
56*4882a593Smuzhiyun /* our structs                                                            */
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun #define MAXREGS 256
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun struct CHIPSTATE;
61*4882a593Smuzhiyun typedef int  (*getvalue)(int);
62*4882a593Smuzhiyun typedef int  (*checkit)(struct CHIPSTATE*);
63*4882a593Smuzhiyun typedef int  (*initialize)(struct CHIPSTATE*);
64*4882a593Smuzhiyun typedef int  (*getrxsubchans)(struct CHIPSTATE *);
65*4882a593Smuzhiyun typedef void (*setaudmode)(struct CHIPSTATE*, int mode);
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun /* i2c command */
68*4882a593Smuzhiyun typedef struct AUDIOCMD {
69*4882a593Smuzhiyun 	int             count;             /* # of bytes to send */
70*4882a593Smuzhiyun 	unsigned char   bytes[MAXREGS+1];  /* addr, data, data, ... */
71*4882a593Smuzhiyun } audiocmd;
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun /* chip description */
74*4882a593Smuzhiyun struct CHIPDESC {
75*4882a593Smuzhiyun 	char       *name;             /* chip name         */
76*4882a593Smuzhiyun 	int        addr_lo, addr_hi;  /* i2c address range */
77*4882a593Smuzhiyun 	int        registers;         /* # of registers    */
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	int        *insmodopt;
80*4882a593Smuzhiyun 	checkit    checkit;
81*4882a593Smuzhiyun 	initialize initialize;
82*4882a593Smuzhiyun 	int        flags;
83*4882a593Smuzhiyun #define CHIP_HAS_VOLUME      1
84*4882a593Smuzhiyun #define CHIP_HAS_BASSTREBLE  2
85*4882a593Smuzhiyun #define CHIP_HAS_INPUTSEL    4
86*4882a593Smuzhiyun #define CHIP_NEED_CHECKMODE  8
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	/* various i2c command sequences */
89*4882a593Smuzhiyun 	audiocmd   init;
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	/* which register has which value */
92*4882a593Smuzhiyun 	int    leftreg, rightreg, treblereg, bassreg;
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	/* initialize with (defaults to 65535/32768/32768 */
95*4882a593Smuzhiyun 	int    volinit, trebleinit, bassinit;
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	/* functions to convert the values (v4l -> chip) */
98*4882a593Smuzhiyun 	getvalue volfunc, treblefunc, bassfunc;
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun 	/* get/set mode */
101*4882a593Smuzhiyun 	getrxsubchans	getrxsubchans;
102*4882a593Smuzhiyun 	setaudmode	setaudmode;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	/* input switch register + values for v4l inputs */
105*4882a593Smuzhiyun 	int  inputreg;
106*4882a593Smuzhiyun 	int  inputmap[4];
107*4882a593Smuzhiyun 	int  inputmute;
108*4882a593Smuzhiyun 	int  inputmask;
109*4882a593Smuzhiyun };
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun /* current state of the chip */
112*4882a593Smuzhiyun struct CHIPSTATE {
113*4882a593Smuzhiyun 	struct v4l2_subdev sd;
114*4882a593Smuzhiyun 	struct v4l2_ctrl_handler hdl;
115*4882a593Smuzhiyun 	struct {
116*4882a593Smuzhiyun 		/* volume/balance cluster */
117*4882a593Smuzhiyun 		struct v4l2_ctrl *volume;
118*4882a593Smuzhiyun 		struct v4l2_ctrl *balance;
119*4882a593Smuzhiyun 	};
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	/* chip-specific description - should point to
122*4882a593Smuzhiyun 	   an entry at CHIPDESC table */
123*4882a593Smuzhiyun 	struct CHIPDESC *desc;
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	/* shadow register set */
126*4882a593Smuzhiyun 	audiocmd   shadow;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	/* current settings */
129*4882a593Smuzhiyun 	u16 muted;
130*4882a593Smuzhiyun 	int prevmode;
131*4882a593Smuzhiyun 	int radio;
132*4882a593Smuzhiyun 	int input;
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	/* thread */
135*4882a593Smuzhiyun 	struct task_struct   *thread;
136*4882a593Smuzhiyun 	struct timer_list    wt;
137*4882a593Smuzhiyun 	int		     audmode;
138*4882a593Smuzhiyun };
139*4882a593Smuzhiyun 
to_state(struct v4l2_subdev * sd)140*4882a593Smuzhiyun static inline struct CHIPSTATE *to_state(struct v4l2_subdev *sd)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun 	return container_of(sd, struct CHIPSTATE, sd);
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun 
to_sd(struct v4l2_ctrl * ctrl)145*4882a593Smuzhiyun static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun 	return &container_of(ctrl->handler, struct CHIPSTATE, hdl)->sd;
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
152*4882a593Smuzhiyun /* i2c I/O functions                                                      */
153*4882a593Smuzhiyun 
chip_write(struct CHIPSTATE * chip,int subaddr,int val)154*4882a593Smuzhiyun static int chip_write(struct CHIPSTATE *chip, int subaddr, int val)
155*4882a593Smuzhiyun {
156*4882a593Smuzhiyun 	struct v4l2_subdev *sd = &chip->sd;
157*4882a593Smuzhiyun 	struct i2c_client *c = v4l2_get_subdevdata(sd);
158*4882a593Smuzhiyun 	unsigned char buffer[2];
159*4882a593Smuzhiyun 	int rc;
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	if (subaddr < 0) {
162*4882a593Smuzhiyun 		v4l2_dbg(1, debug, sd, "chip_write: 0x%x\n", val);
163*4882a593Smuzhiyun 		chip->shadow.bytes[1] = val;
164*4882a593Smuzhiyun 		buffer[0] = val;
165*4882a593Smuzhiyun 		rc = i2c_master_send(c, buffer, 1);
166*4882a593Smuzhiyun 		if (rc != 1) {
167*4882a593Smuzhiyun 			v4l2_warn(sd, "I/O error (write 0x%x)\n", val);
168*4882a593Smuzhiyun 			if (rc < 0)
169*4882a593Smuzhiyun 				return rc;
170*4882a593Smuzhiyun 			return -EIO;
171*4882a593Smuzhiyun 		}
172*4882a593Smuzhiyun 	} else {
173*4882a593Smuzhiyun 		if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) {
174*4882a593Smuzhiyun 			v4l2_info(sd,
175*4882a593Smuzhiyun 				"Tried to access a non-existent register: %d\n",
176*4882a593Smuzhiyun 				subaddr);
177*4882a593Smuzhiyun 			return -EINVAL;
178*4882a593Smuzhiyun 		}
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 		v4l2_dbg(1, debug, sd, "chip_write: reg%d=0x%x\n",
181*4882a593Smuzhiyun 			subaddr, val);
182*4882a593Smuzhiyun 		chip->shadow.bytes[subaddr+1] = val;
183*4882a593Smuzhiyun 		buffer[0] = subaddr;
184*4882a593Smuzhiyun 		buffer[1] = val;
185*4882a593Smuzhiyun 		rc = i2c_master_send(c, buffer, 2);
186*4882a593Smuzhiyun 		if (rc != 2) {
187*4882a593Smuzhiyun 			v4l2_warn(sd, "I/O error (write reg%d=0x%x)\n",
188*4882a593Smuzhiyun 				subaddr, val);
189*4882a593Smuzhiyun 			if (rc < 0)
190*4882a593Smuzhiyun 				return rc;
191*4882a593Smuzhiyun 			return -EIO;
192*4882a593Smuzhiyun 		}
193*4882a593Smuzhiyun 	}
194*4882a593Smuzhiyun 	return 0;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun 
chip_write_masked(struct CHIPSTATE * chip,int subaddr,int val,int mask)197*4882a593Smuzhiyun static int chip_write_masked(struct CHIPSTATE *chip,
198*4882a593Smuzhiyun 			     int subaddr, int val, int mask)
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun 	struct v4l2_subdev *sd = &chip->sd;
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 	if (mask != 0) {
203*4882a593Smuzhiyun 		if (subaddr < 0) {
204*4882a593Smuzhiyun 			val = (chip->shadow.bytes[1] & ~mask) | (val & mask);
205*4882a593Smuzhiyun 		} else {
206*4882a593Smuzhiyun 			if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) {
207*4882a593Smuzhiyun 				v4l2_info(sd,
208*4882a593Smuzhiyun 					"Tried to access a non-existent register: %d\n",
209*4882a593Smuzhiyun 					subaddr);
210*4882a593Smuzhiyun 				return -EINVAL;
211*4882a593Smuzhiyun 			}
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 			val = (chip->shadow.bytes[subaddr+1] & ~mask) | (val & mask);
214*4882a593Smuzhiyun 		}
215*4882a593Smuzhiyun 	}
216*4882a593Smuzhiyun 	return chip_write(chip, subaddr, val);
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun 
chip_read(struct CHIPSTATE * chip)219*4882a593Smuzhiyun static int chip_read(struct CHIPSTATE *chip)
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun 	struct v4l2_subdev *sd = &chip->sd;
222*4882a593Smuzhiyun 	struct i2c_client *c = v4l2_get_subdevdata(sd);
223*4882a593Smuzhiyun 	unsigned char buffer;
224*4882a593Smuzhiyun 	int rc;
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	rc = i2c_master_recv(c, &buffer, 1);
227*4882a593Smuzhiyun 	if (rc != 1) {
228*4882a593Smuzhiyun 		v4l2_warn(sd, "I/O error (read)\n");
229*4882a593Smuzhiyun 		if (rc < 0)
230*4882a593Smuzhiyun 			return rc;
231*4882a593Smuzhiyun 		return -EIO;
232*4882a593Smuzhiyun 	}
233*4882a593Smuzhiyun 	v4l2_dbg(1, debug, sd, "chip_read: 0x%x\n", buffer);
234*4882a593Smuzhiyun 	return buffer;
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun 
chip_read2(struct CHIPSTATE * chip,int subaddr)237*4882a593Smuzhiyun static int chip_read2(struct CHIPSTATE *chip, int subaddr)
238*4882a593Smuzhiyun {
239*4882a593Smuzhiyun 	struct v4l2_subdev *sd = &chip->sd;
240*4882a593Smuzhiyun 	struct i2c_client *c = v4l2_get_subdevdata(sd);
241*4882a593Smuzhiyun 	int rc;
242*4882a593Smuzhiyun 	unsigned char write[1];
243*4882a593Smuzhiyun 	unsigned char read[1];
244*4882a593Smuzhiyun 	struct i2c_msg msgs[2] = {
245*4882a593Smuzhiyun 		{
246*4882a593Smuzhiyun 			.addr = c->addr,
247*4882a593Smuzhiyun 			.len = 1,
248*4882a593Smuzhiyun 			.buf = write
249*4882a593Smuzhiyun 		},
250*4882a593Smuzhiyun 		{
251*4882a593Smuzhiyun 			.addr = c->addr,
252*4882a593Smuzhiyun 			.flags = I2C_M_RD,
253*4882a593Smuzhiyun 			.len = 1,
254*4882a593Smuzhiyun 			.buf = read
255*4882a593Smuzhiyun 		}
256*4882a593Smuzhiyun 	};
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	write[0] = subaddr;
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	rc = i2c_transfer(c->adapter, msgs, 2);
261*4882a593Smuzhiyun 	if (rc != 2) {
262*4882a593Smuzhiyun 		v4l2_warn(sd, "I/O error (read2)\n");
263*4882a593Smuzhiyun 		if (rc < 0)
264*4882a593Smuzhiyun 			return rc;
265*4882a593Smuzhiyun 		return -EIO;
266*4882a593Smuzhiyun 	}
267*4882a593Smuzhiyun 	v4l2_dbg(1, debug, sd, "chip_read2: reg%d=0x%x\n",
268*4882a593Smuzhiyun 		subaddr, read[0]);
269*4882a593Smuzhiyun 	return read[0];
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun 
chip_cmd(struct CHIPSTATE * chip,char * name,audiocmd * cmd)272*4882a593Smuzhiyun static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun 	struct v4l2_subdev *sd = &chip->sd;
275*4882a593Smuzhiyun 	struct i2c_client *c = v4l2_get_subdevdata(sd);
276*4882a593Smuzhiyun 	int i, rc;
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	if (0 == cmd->count)
279*4882a593Smuzhiyun 		return 0;
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	if (cmd->count + cmd->bytes[0] - 1 >= ARRAY_SIZE(chip->shadow.bytes)) {
282*4882a593Smuzhiyun 		v4l2_info(sd,
283*4882a593Smuzhiyun 			 "Tried to access a non-existent register range: %d to %d\n",
284*4882a593Smuzhiyun 			 cmd->bytes[0] + 1, cmd->bytes[0] + cmd->count - 1);
285*4882a593Smuzhiyun 		return -EINVAL;
286*4882a593Smuzhiyun 	}
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	/* FIXME: it seems that the shadow bytes are wrong below !*/
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 	/* update our shadow register set; print bytes if (debug > 0) */
291*4882a593Smuzhiyun 	v4l2_dbg(1, debug, sd, "chip_cmd(%s): reg=%d, data:",
292*4882a593Smuzhiyun 		name, cmd->bytes[0]);
293*4882a593Smuzhiyun 	for (i = 1; i < cmd->count; i++) {
294*4882a593Smuzhiyun 		if (debug)
295*4882a593Smuzhiyun 			printk(KERN_CONT " 0x%x", cmd->bytes[i]);
296*4882a593Smuzhiyun 		chip->shadow.bytes[i+cmd->bytes[0]] = cmd->bytes[i];
297*4882a593Smuzhiyun 	}
298*4882a593Smuzhiyun 	if (debug)
299*4882a593Smuzhiyun 		printk(KERN_CONT "\n");
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun 	/* send data to the chip */
302*4882a593Smuzhiyun 	rc = i2c_master_send(c, cmd->bytes, cmd->count);
303*4882a593Smuzhiyun 	if (rc != cmd->count) {
304*4882a593Smuzhiyun 		v4l2_warn(sd, "I/O error (%s)\n", name);
305*4882a593Smuzhiyun 		if (rc < 0)
306*4882a593Smuzhiyun 			return rc;
307*4882a593Smuzhiyun 		return -EIO;
308*4882a593Smuzhiyun 	}
309*4882a593Smuzhiyun 	return 0;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
313*4882a593Smuzhiyun /* kernel thread for doing i2c stuff asyncronly
314*4882a593Smuzhiyun  *   right now it is used only to check the audio mode (mono/stereo/whatever)
315*4882a593Smuzhiyun  *   some time after switching to another TV channel, then turn on stereo
316*4882a593Smuzhiyun  *   if available, ...
317*4882a593Smuzhiyun  */
318*4882a593Smuzhiyun 
chip_thread_wake(struct timer_list * t)319*4882a593Smuzhiyun static void chip_thread_wake(struct timer_list *t)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun 	struct CHIPSTATE *chip = from_timer(chip, t, wt);
322*4882a593Smuzhiyun 	wake_up_process(chip->thread);
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun 
chip_thread(void * data)325*4882a593Smuzhiyun static int chip_thread(void *data)
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun 	struct CHIPSTATE *chip = data;
328*4882a593Smuzhiyun 	struct CHIPDESC  *desc = chip->desc;
329*4882a593Smuzhiyun 	struct v4l2_subdev *sd = &chip->sd;
330*4882a593Smuzhiyun 	int mode, selected;
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	v4l2_dbg(1, debug, sd, "thread started\n");
333*4882a593Smuzhiyun 	set_freezable();
334*4882a593Smuzhiyun 	for (;;) {
335*4882a593Smuzhiyun 		set_current_state(TASK_INTERRUPTIBLE);
336*4882a593Smuzhiyun 		if (!kthread_should_stop())
337*4882a593Smuzhiyun 			schedule();
338*4882a593Smuzhiyun 		set_current_state(TASK_RUNNING);
339*4882a593Smuzhiyun 		try_to_freeze();
340*4882a593Smuzhiyun 		if (kthread_should_stop())
341*4882a593Smuzhiyun 			break;
342*4882a593Smuzhiyun 		v4l2_dbg(1, debug, sd, "thread wakeup\n");
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 		/* don't do anything for radio */
345*4882a593Smuzhiyun 		if (chip->radio)
346*4882a593Smuzhiyun 			continue;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 		/* have a look what's going on */
349*4882a593Smuzhiyun 		mode = desc->getrxsubchans(chip);
350*4882a593Smuzhiyun 		if (mode == chip->prevmode)
351*4882a593Smuzhiyun 			continue;
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 		/* chip detected a new audio mode - set it */
354*4882a593Smuzhiyun 		v4l2_dbg(1, debug, sd, "thread checkmode\n");
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 		chip->prevmode = mode;
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 		selected = V4L2_TUNER_MODE_MONO;
359*4882a593Smuzhiyun 		switch (chip->audmode) {
360*4882a593Smuzhiyun 		case V4L2_TUNER_MODE_MONO:
361*4882a593Smuzhiyun 			if (mode & V4L2_TUNER_SUB_LANG1)
362*4882a593Smuzhiyun 				selected = V4L2_TUNER_MODE_LANG1;
363*4882a593Smuzhiyun 			break;
364*4882a593Smuzhiyun 		case V4L2_TUNER_MODE_STEREO:
365*4882a593Smuzhiyun 		case V4L2_TUNER_MODE_LANG1:
366*4882a593Smuzhiyun 			if (mode & V4L2_TUNER_SUB_LANG1)
367*4882a593Smuzhiyun 				selected = V4L2_TUNER_MODE_LANG1;
368*4882a593Smuzhiyun 			else if (mode & V4L2_TUNER_SUB_STEREO)
369*4882a593Smuzhiyun 				selected = V4L2_TUNER_MODE_STEREO;
370*4882a593Smuzhiyun 			break;
371*4882a593Smuzhiyun 		case V4L2_TUNER_MODE_LANG2:
372*4882a593Smuzhiyun 			if (mode & V4L2_TUNER_SUB_LANG2)
373*4882a593Smuzhiyun 				selected = V4L2_TUNER_MODE_LANG2;
374*4882a593Smuzhiyun 			else if (mode & V4L2_TUNER_SUB_STEREO)
375*4882a593Smuzhiyun 				selected = V4L2_TUNER_MODE_STEREO;
376*4882a593Smuzhiyun 			break;
377*4882a593Smuzhiyun 		case V4L2_TUNER_MODE_LANG1_LANG2:
378*4882a593Smuzhiyun 			if (mode & V4L2_TUNER_SUB_LANG2)
379*4882a593Smuzhiyun 				selected = V4L2_TUNER_MODE_LANG1_LANG2;
380*4882a593Smuzhiyun 			else if (mode & V4L2_TUNER_SUB_STEREO)
381*4882a593Smuzhiyun 				selected = V4L2_TUNER_MODE_STEREO;
382*4882a593Smuzhiyun 		}
383*4882a593Smuzhiyun 		desc->setaudmode(chip, selected);
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 		/* schedule next check */
386*4882a593Smuzhiyun 		mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000));
387*4882a593Smuzhiyun 	}
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	v4l2_dbg(1, debug, sd, "thread exiting\n");
390*4882a593Smuzhiyun 	return 0;
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
394*4882a593Smuzhiyun /* audio chip descriptions - defines+functions for tda9840                */
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun #define TDA9840_SW         0x00
397*4882a593Smuzhiyun #define TDA9840_LVADJ      0x02
398*4882a593Smuzhiyun #define TDA9840_STADJ      0x03
399*4882a593Smuzhiyun #define TDA9840_TEST       0x04
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun #define TDA9840_MONO       0x10
402*4882a593Smuzhiyun #define TDA9840_STEREO     0x2a
403*4882a593Smuzhiyun #define TDA9840_DUALA      0x12
404*4882a593Smuzhiyun #define TDA9840_DUALB      0x1e
405*4882a593Smuzhiyun #define TDA9840_DUALAB     0x1a
406*4882a593Smuzhiyun #define TDA9840_DUALBA     0x16
407*4882a593Smuzhiyun #define TDA9840_EXTERNAL   0x7a
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun #define TDA9840_DS_DUAL    0x20 /* Dual sound identified          */
410*4882a593Smuzhiyun #define TDA9840_ST_STEREO  0x40 /* Stereo sound identified        */
411*4882a593Smuzhiyun #define TDA9840_PONRES     0x80 /* Power-on reset detected if = 1 */
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun #define TDA9840_TEST_INT1SN 0x1 /* Integration time 0.5s when set */
414*4882a593Smuzhiyun #define TDA9840_TEST_INTFU 0x02 /* Disables integrator function */
415*4882a593Smuzhiyun 
tda9840_getrxsubchans(struct CHIPSTATE * chip)416*4882a593Smuzhiyun static int tda9840_getrxsubchans(struct CHIPSTATE *chip)
417*4882a593Smuzhiyun {
418*4882a593Smuzhiyun 	struct v4l2_subdev *sd = &chip->sd;
419*4882a593Smuzhiyun 	int val, mode;
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	mode = V4L2_TUNER_SUB_MONO;
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	val = chip_read(chip);
424*4882a593Smuzhiyun 	if (val < 0)
425*4882a593Smuzhiyun 		return mode;
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun 	if (val & TDA9840_DS_DUAL)
428*4882a593Smuzhiyun 		mode |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
429*4882a593Smuzhiyun 	if (val & TDA9840_ST_STEREO)
430*4882a593Smuzhiyun 		mode = V4L2_TUNER_SUB_STEREO;
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 	v4l2_dbg(1, debug, sd,
433*4882a593Smuzhiyun 		"tda9840_getrxsubchans(): raw chip read: %d, return: %d\n",
434*4882a593Smuzhiyun 		val, mode);
435*4882a593Smuzhiyun 	return mode;
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun 
tda9840_setaudmode(struct CHIPSTATE * chip,int mode)438*4882a593Smuzhiyun static void tda9840_setaudmode(struct CHIPSTATE *chip, int mode)
439*4882a593Smuzhiyun {
440*4882a593Smuzhiyun 	int update = 1;
441*4882a593Smuzhiyun 	int t = chip->shadow.bytes[TDA9840_SW + 1] & ~0x7e;
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	switch (mode) {
444*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_MONO:
445*4882a593Smuzhiyun 		t |= TDA9840_MONO;
446*4882a593Smuzhiyun 		break;
447*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_STEREO:
448*4882a593Smuzhiyun 		t |= TDA9840_STEREO;
449*4882a593Smuzhiyun 		break;
450*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_LANG1:
451*4882a593Smuzhiyun 		t |= TDA9840_DUALA;
452*4882a593Smuzhiyun 		break;
453*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_LANG2:
454*4882a593Smuzhiyun 		t |= TDA9840_DUALB;
455*4882a593Smuzhiyun 		break;
456*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_LANG1_LANG2:
457*4882a593Smuzhiyun 		t |= TDA9840_DUALAB;
458*4882a593Smuzhiyun 		break;
459*4882a593Smuzhiyun 	default:
460*4882a593Smuzhiyun 		update = 0;
461*4882a593Smuzhiyun 	}
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 	if (update)
464*4882a593Smuzhiyun 		chip_write(chip, TDA9840_SW, t);
465*4882a593Smuzhiyun }
466*4882a593Smuzhiyun 
tda9840_checkit(struct CHIPSTATE * chip)467*4882a593Smuzhiyun static int tda9840_checkit(struct CHIPSTATE *chip)
468*4882a593Smuzhiyun {
469*4882a593Smuzhiyun 	int rc;
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun 	rc = chip_read(chip);
472*4882a593Smuzhiyun 	if (rc < 0)
473*4882a593Smuzhiyun 		return 0;
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	/* lower 5 bits should be 0 */
477*4882a593Smuzhiyun 	return ((rc & 0x1f) == 0) ? 1 : 0;
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun 
480*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
481*4882a593Smuzhiyun /* audio chip descriptions - defines+functions for tda985x                */
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun /* subaddresses for TDA9855 */
484*4882a593Smuzhiyun #define TDA9855_VR	0x00 /* Volume, right */
485*4882a593Smuzhiyun #define TDA9855_VL	0x01 /* Volume, left */
486*4882a593Smuzhiyun #define TDA9855_BA	0x02 /* Bass */
487*4882a593Smuzhiyun #define TDA9855_TR	0x03 /* Treble */
488*4882a593Smuzhiyun #define TDA9855_SW	0x04 /* Subwoofer - not connected on DTV2000 */
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun /* subaddresses for TDA9850 */
491*4882a593Smuzhiyun #define TDA9850_C4	0x04 /* Control 1 for TDA9850 */
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun /* subaddesses for both chips */
494*4882a593Smuzhiyun #define TDA985x_C5	0x05 /* Control 2 for TDA9850, Control 1 for TDA9855 */
495*4882a593Smuzhiyun #define TDA985x_C6	0x06 /* Control 3 for TDA9850, Control 2 for TDA9855 */
496*4882a593Smuzhiyun #define TDA985x_C7	0x07 /* Control 4 for TDA9850, Control 3 for TDA9855 */
497*4882a593Smuzhiyun #define TDA985x_A1	0x08 /* Alignment 1 for both chips */
498*4882a593Smuzhiyun #define TDA985x_A2	0x09 /* Alignment 2 for both chips */
499*4882a593Smuzhiyun #define TDA985x_A3	0x0a /* Alignment 3 for both chips */
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun /* Masks for bits in TDA9855 subaddresses */
502*4882a593Smuzhiyun /* 0x00 - VR in TDA9855 */
503*4882a593Smuzhiyun /* 0x01 - VL in TDA9855 */
504*4882a593Smuzhiyun /* lower 7 bits control gain from -71dB (0x28) to 16dB (0x7f)
505*4882a593Smuzhiyun  * in 1dB steps - mute is 0x27 */
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun /* 0x02 - BA in TDA9855 */
509*4882a593Smuzhiyun /* lower 5 bits control bass gain from -12dB (0x06) to 16.5dB (0x19)
510*4882a593Smuzhiyun  * in .5dB steps - 0 is 0x0E */
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun /* 0x03 - TR in TDA9855 */
514*4882a593Smuzhiyun /* 4 bits << 1 control treble gain from -12dB (0x3) to 12dB (0xb)
515*4882a593Smuzhiyun  * in 3dB steps - 0 is 0x7 */
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun /* Masks for bits in both chips' subaddresses */
518*4882a593Smuzhiyun /* 0x04 - SW in TDA9855, C4/Control 1 in TDA9850 */
519*4882a593Smuzhiyun /* Unique to TDA9855: */
520*4882a593Smuzhiyun /* 4 bits << 2 control subwoofer/surround gain from -14db (0x1) to 14db (0xf)
521*4882a593Smuzhiyun  * in 3dB steps - mute is 0x0 */
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun /* Unique to TDA9850: */
524*4882a593Smuzhiyun /* lower 4 bits control stereo noise threshold, over which stereo turns off
525*4882a593Smuzhiyun  * set to values of 0x00 through 0x0f for Ster1 through Ster16 */
526*4882a593Smuzhiyun 
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun /* 0x05 - C5 - Control 1 in TDA9855 , Control 2 in TDA9850*/
529*4882a593Smuzhiyun /* Unique to TDA9855: */
530*4882a593Smuzhiyun #define TDA9855_MUTE	1<<7 /* GMU, Mute at outputs */
531*4882a593Smuzhiyun #define TDA9855_AVL	1<<6 /* AVL, Automatic Volume Level */
532*4882a593Smuzhiyun #define TDA9855_LOUD	1<<5 /* Loudness, 1==off */
533*4882a593Smuzhiyun #define TDA9855_SUR	1<<3 /* Surround / Subwoofer 1==.5(L-R) 0==.5(L+R) */
534*4882a593Smuzhiyun 			     /* Bits 0 to 3 select various combinations
535*4882a593Smuzhiyun 			      * of line in and line out, only the
536*4882a593Smuzhiyun 			      * interesting ones are defined */
537*4882a593Smuzhiyun #define TDA9855_EXT	1<<2 /* Selects inputs LIR and LIL.  Pins 41 & 12 */
538*4882a593Smuzhiyun #define TDA9855_INT	0    /* Selects inputs LOR and LOL.  (internal) */
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun /* Unique to TDA9850:  */
541*4882a593Smuzhiyun /* lower 4 bits control SAP noise threshold, over which SAP turns off
542*4882a593Smuzhiyun  * set to values of 0x00 through 0x0f for SAP1 through SAP16 */
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun 
545*4882a593Smuzhiyun /* 0x06 - C6 - Control 2 in TDA9855, Control 3 in TDA9850 */
546*4882a593Smuzhiyun /* Common to TDA9855 and TDA9850: */
547*4882a593Smuzhiyun #define TDA985x_SAP	3<<6 /* Selects SAP output, mute if not received */
548*4882a593Smuzhiyun #define TDA985x_MONOSAP	2<<6 /* Selects Mono on left, SAP on right */
549*4882a593Smuzhiyun #define TDA985x_STEREO	1<<6 /* Selects Stereo output, mono if not received */
550*4882a593Smuzhiyun #define TDA985x_MONO	0    /* Forces Mono output */
551*4882a593Smuzhiyun #define TDA985x_LMU	1<<3 /* Mute (LOR/LOL for 9855, OUTL/OUTR for 9850) */
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun /* Unique to TDA9855: */
554*4882a593Smuzhiyun #define TDA9855_TZCM	1<<5 /* If set, don't mute till zero crossing */
555*4882a593Smuzhiyun #define TDA9855_VZCM	1<<4 /* If set, don't change volume till zero crossing*/
556*4882a593Smuzhiyun #define TDA9855_LINEAR	0    /* Linear Stereo */
557*4882a593Smuzhiyun #define TDA9855_PSEUDO	1    /* Pseudo Stereo */
558*4882a593Smuzhiyun #define TDA9855_SPAT_30	2    /* Spatial Stereo, 30% anti-phase crosstalk */
559*4882a593Smuzhiyun #define TDA9855_SPAT_50	3    /* Spatial Stereo, 52% anti-phase crosstalk */
560*4882a593Smuzhiyun #define TDA9855_E_MONO	7    /* Forced mono - mono select elseware, so useless*/
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun /* 0x07 - C7 - Control 3 in TDA9855, Control 4 in TDA9850 */
563*4882a593Smuzhiyun /* Common to both TDA9855 and TDA9850: */
564*4882a593Smuzhiyun /* lower 4 bits control input gain from -3.5dB (0x0) to 4dB (0xF)
565*4882a593Smuzhiyun  * in .5dB steps -  0dB is 0x7 */
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun /* 0x08, 0x09 - A1 and A2 (read/write) */
568*4882a593Smuzhiyun /* Common to both TDA9855 and TDA9850: */
569*4882a593Smuzhiyun /* lower 5 bites are wideband and spectral expander alignment
570*4882a593Smuzhiyun  * from 0x00 to 0x1f - nominal at 0x0f and 0x10 (read/write) */
571*4882a593Smuzhiyun #define TDA985x_STP	1<<5 /* Stereo Pilot/detect (read-only) */
572*4882a593Smuzhiyun #define TDA985x_SAPP	1<<6 /* SAP Pilot/detect (read-only) */
573*4882a593Smuzhiyun #define TDA985x_STS	1<<7 /* Stereo trigger 1= <35mV 0= <30mV (write-only)*/
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun /* 0x0a - A3 */
576*4882a593Smuzhiyun /* Common to both TDA9855 and TDA9850: */
577*4882a593Smuzhiyun /* lower 3 bits control timing current for alignment: -30% (0x0), -20% (0x1),
578*4882a593Smuzhiyun  * -10% (0x2), nominal (0x3), +10% (0x6), +20% (0x5), +30% (0x4) */
579*4882a593Smuzhiyun #define TDA985x_ADJ	1<<7 /* Stereo adjust on/off (wideband and spectral */
580*4882a593Smuzhiyun 
tda9855_volume(int val)581*4882a593Smuzhiyun static int tda9855_volume(int val) { return val/0x2e8+0x27; }
tda9855_bass(int val)582*4882a593Smuzhiyun static int tda9855_bass(int val)   { return val/0xccc+0x06; }
tda9855_treble(int val)583*4882a593Smuzhiyun static int tda9855_treble(int val) { return (val/0x1c71+0x3)<<1; }
584*4882a593Smuzhiyun 
tda985x_getrxsubchans(struct CHIPSTATE * chip)585*4882a593Smuzhiyun static int  tda985x_getrxsubchans(struct CHIPSTATE *chip)
586*4882a593Smuzhiyun {
587*4882a593Smuzhiyun 	int mode, val;
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun 	/* Add mono mode regardless of SAP and stereo */
590*4882a593Smuzhiyun 	/* Allows forced mono */
591*4882a593Smuzhiyun 	mode = V4L2_TUNER_SUB_MONO;
592*4882a593Smuzhiyun 	val = chip_read(chip);
593*4882a593Smuzhiyun 	if (val < 0)
594*4882a593Smuzhiyun 		return mode;
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun 	if (val & TDA985x_STP)
597*4882a593Smuzhiyun 		mode = V4L2_TUNER_SUB_STEREO;
598*4882a593Smuzhiyun 	if (val & TDA985x_SAPP)
599*4882a593Smuzhiyun 		mode |= V4L2_TUNER_SUB_SAP;
600*4882a593Smuzhiyun 	return mode;
601*4882a593Smuzhiyun }
602*4882a593Smuzhiyun 
tda985x_setaudmode(struct CHIPSTATE * chip,int mode)603*4882a593Smuzhiyun static void tda985x_setaudmode(struct CHIPSTATE *chip, int mode)
604*4882a593Smuzhiyun {
605*4882a593Smuzhiyun 	int update = 1;
606*4882a593Smuzhiyun 	int c6 = chip->shadow.bytes[TDA985x_C6+1] & 0x3f;
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun 	switch (mode) {
609*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_MONO:
610*4882a593Smuzhiyun 		c6 |= TDA985x_MONO;
611*4882a593Smuzhiyun 		break;
612*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_STEREO:
613*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_LANG1:
614*4882a593Smuzhiyun 		c6 |= TDA985x_STEREO;
615*4882a593Smuzhiyun 		break;
616*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_SAP:
617*4882a593Smuzhiyun 		c6 |= TDA985x_SAP;
618*4882a593Smuzhiyun 		break;
619*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_LANG1_LANG2:
620*4882a593Smuzhiyun 		c6 |= TDA985x_MONOSAP;
621*4882a593Smuzhiyun 		break;
622*4882a593Smuzhiyun 	default:
623*4882a593Smuzhiyun 		update = 0;
624*4882a593Smuzhiyun 	}
625*4882a593Smuzhiyun 	if (update)
626*4882a593Smuzhiyun 		chip_write(chip,TDA985x_C6,c6);
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
631*4882a593Smuzhiyun /* audio chip descriptions - defines+functions for tda9873h               */
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun /* Subaddresses for TDA9873H */
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun #define TDA9873_SW	0x00 /* Switching                    */
636*4882a593Smuzhiyun #define TDA9873_AD	0x01 /* Adjust                       */
637*4882a593Smuzhiyun #define TDA9873_PT	0x02 /* Port                         */
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun /* Subaddress 0x00: Switching Data
640*4882a593Smuzhiyun  * B7..B0:
641*4882a593Smuzhiyun  *
642*4882a593Smuzhiyun  * B1, B0: Input source selection
643*4882a593Smuzhiyun  *  0,  0  internal
644*4882a593Smuzhiyun  *  1,  0  external stereo
645*4882a593Smuzhiyun  *  0,  1  external mono
646*4882a593Smuzhiyun  */
647*4882a593Smuzhiyun #define TDA9873_INP_MASK    3
648*4882a593Smuzhiyun #define TDA9873_INTERNAL    0
649*4882a593Smuzhiyun #define TDA9873_EXT_STEREO  2
650*4882a593Smuzhiyun #define TDA9873_EXT_MONO    1
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun /*    B3, B2: output signal select
653*4882a593Smuzhiyun  * B4    : transmission mode
654*4882a593Smuzhiyun  *  0, 0, 1   Mono
655*4882a593Smuzhiyun  *  1, 0, 0   Stereo
656*4882a593Smuzhiyun  *  1, 1, 1   Stereo (reversed channel)
657*4882a593Smuzhiyun  *  0, 0, 0   Dual AB
658*4882a593Smuzhiyun  *  0, 0, 1   Dual AA
659*4882a593Smuzhiyun  *  0, 1, 0   Dual BB
660*4882a593Smuzhiyun  *  0, 1, 1   Dual BA
661*4882a593Smuzhiyun  */
662*4882a593Smuzhiyun 
663*4882a593Smuzhiyun #define TDA9873_TR_MASK     (7 << 2)
664*4882a593Smuzhiyun #define TDA9873_TR_MONO     4
665*4882a593Smuzhiyun #define TDA9873_TR_STEREO   1 << 4
666*4882a593Smuzhiyun #define TDA9873_TR_REVERSE  ((1 << 3) | (1 << 2))
667*4882a593Smuzhiyun #define TDA9873_TR_DUALA    1 << 2
668*4882a593Smuzhiyun #define TDA9873_TR_DUALB    1 << 3
669*4882a593Smuzhiyun #define TDA9873_TR_DUALAB   0
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun /* output level controls
672*4882a593Smuzhiyun  * B5:  output level switch (0 = reduced gain, 1 = normal gain)
673*4882a593Smuzhiyun  * B6:  mute                (1 = muted)
674*4882a593Smuzhiyun  * B7:  auto-mute           (1 = auto-mute enabled)
675*4882a593Smuzhiyun  */
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun #define TDA9873_GAIN_NORMAL 1 << 5
678*4882a593Smuzhiyun #define TDA9873_MUTE        1 << 6
679*4882a593Smuzhiyun #define TDA9873_AUTOMUTE    1 << 7
680*4882a593Smuzhiyun 
681*4882a593Smuzhiyun /* Subaddress 0x01:  Adjust/standard */
682*4882a593Smuzhiyun 
683*4882a593Smuzhiyun /* Lower 4 bits (C3..C0) control stereo adjustment on R channel (-0.6 - +0.7 dB)
684*4882a593Smuzhiyun  * Recommended value is +0 dB
685*4882a593Smuzhiyun  */
686*4882a593Smuzhiyun 
687*4882a593Smuzhiyun #define	TDA9873_STEREO_ADJ	0x06 /* 0dB gain */
688*4882a593Smuzhiyun 
689*4882a593Smuzhiyun /* Bits C6..C4 control FM stantard
690*4882a593Smuzhiyun  * C6, C5, C4
691*4882a593Smuzhiyun  *  0,  0,  0   B/G (PAL FM)
692*4882a593Smuzhiyun  *  0,  0,  1   M
693*4882a593Smuzhiyun  *  0,  1,  0   D/K(1)
694*4882a593Smuzhiyun  *  0,  1,  1   D/K(2)
695*4882a593Smuzhiyun  *  1,  0,  0   D/K(3)
696*4882a593Smuzhiyun  *  1,  0,  1   I
697*4882a593Smuzhiyun  */
698*4882a593Smuzhiyun #define TDA9873_BG		0
699*4882a593Smuzhiyun #define TDA9873_M       1
700*4882a593Smuzhiyun #define TDA9873_DK1     2
701*4882a593Smuzhiyun #define TDA9873_DK2     3
702*4882a593Smuzhiyun #define TDA9873_DK3     4
703*4882a593Smuzhiyun #define TDA9873_I       5
704*4882a593Smuzhiyun 
705*4882a593Smuzhiyun /* C7 controls identification response time (1=fast/0=normal)
706*4882a593Smuzhiyun  */
707*4882a593Smuzhiyun #define TDA9873_IDR_NORM 0
708*4882a593Smuzhiyun #define TDA9873_IDR_FAST 1 << 7
709*4882a593Smuzhiyun 
710*4882a593Smuzhiyun 
711*4882a593Smuzhiyun /* Subaddress 0x02: Port data */
712*4882a593Smuzhiyun 
713*4882a593Smuzhiyun /* E1, E0   free programmable ports P1/P2
714*4882a593Smuzhiyun     0,  0   both ports low
715*4882a593Smuzhiyun     0,  1   P1 high
716*4882a593Smuzhiyun     1,  0   P2 high
717*4882a593Smuzhiyun     1,  1   both ports high
718*4882a593Smuzhiyun */
719*4882a593Smuzhiyun 
720*4882a593Smuzhiyun #define TDA9873_PORTS    3
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun /* E2: test port */
723*4882a593Smuzhiyun #define TDA9873_TST_PORT 1 << 2
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun /* E5..E3 control mono output channel (together with transmission mode bit B4)
726*4882a593Smuzhiyun  *
727*4882a593Smuzhiyun  * E5 E4 E3 B4     OUTM
728*4882a593Smuzhiyun  *  0  0  0  0     mono
729*4882a593Smuzhiyun  *  0  0  1  0     DUAL B
730*4882a593Smuzhiyun  *  0  1  0  1     mono (from stereo decoder)
731*4882a593Smuzhiyun  */
732*4882a593Smuzhiyun #define TDA9873_MOUT_MONO   0
733*4882a593Smuzhiyun #define TDA9873_MOUT_FMONO  0
734*4882a593Smuzhiyun #define TDA9873_MOUT_DUALA  0
735*4882a593Smuzhiyun #define TDA9873_MOUT_DUALB  1 << 3
736*4882a593Smuzhiyun #define TDA9873_MOUT_ST     1 << 4
737*4882a593Smuzhiyun #define TDA9873_MOUT_EXTM   ((1 << 4) | (1 << 3))
738*4882a593Smuzhiyun #define TDA9873_MOUT_EXTL   1 << 5
739*4882a593Smuzhiyun #define TDA9873_MOUT_EXTR   ((1 << 5) | (1 << 3))
740*4882a593Smuzhiyun #define TDA9873_MOUT_EXTLR  ((1 << 5) | (1 << 4))
741*4882a593Smuzhiyun #define TDA9873_MOUT_MUTE   ((1 << 5) | (1 << 4) | (1 << 3))
742*4882a593Smuzhiyun 
743*4882a593Smuzhiyun /* Status bits: (chip read) */
744*4882a593Smuzhiyun #define TDA9873_PONR        0 /* Power-on reset detected if = 1 */
745*4882a593Smuzhiyun #define TDA9873_STEREO      2 /* Stereo sound is identified     */
746*4882a593Smuzhiyun #define TDA9873_DUAL        4 /* Dual sound is identified       */
747*4882a593Smuzhiyun 
tda9873_getrxsubchans(struct CHIPSTATE * chip)748*4882a593Smuzhiyun static int tda9873_getrxsubchans(struct CHIPSTATE *chip)
749*4882a593Smuzhiyun {
750*4882a593Smuzhiyun 	struct v4l2_subdev *sd = &chip->sd;
751*4882a593Smuzhiyun 	int val,mode;
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun 	mode = V4L2_TUNER_SUB_MONO;
754*4882a593Smuzhiyun 
755*4882a593Smuzhiyun 	val = chip_read(chip);
756*4882a593Smuzhiyun 	if (val < 0)
757*4882a593Smuzhiyun 		return mode;
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun 	if (val & TDA9873_STEREO)
760*4882a593Smuzhiyun 		mode = V4L2_TUNER_SUB_STEREO;
761*4882a593Smuzhiyun 	if (val & TDA9873_DUAL)
762*4882a593Smuzhiyun 		mode |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
763*4882a593Smuzhiyun 	v4l2_dbg(1, debug, sd,
764*4882a593Smuzhiyun 		"tda9873_getrxsubchans(): raw chip read: %d, return: %d\n",
765*4882a593Smuzhiyun 		val, mode);
766*4882a593Smuzhiyun 	return mode;
767*4882a593Smuzhiyun }
768*4882a593Smuzhiyun 
tda9873_setaudmode(struct CHIPSTATE * chip,int mode)769*4882a593Smuzhiyun static void tda9873_setaudmode(struct CHIPSTATE *chip, int mode)
770*4882a593Smuzhiyun {
771*4882a593Smuzhiyun 	struct v4l2_subdev *sd = &chip->sd;
772*4882a593Smuzhiyun 	int sw_data  = chip->shadow.bytes[TDA9873_SW+1] & ~ TDA9873_TR_MASK;
773*4882a593Smuzhiyun 	/*	int adj_data = chip->shadow.bytes[TDA9873_AD+1] ; */
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun 	if ((sw_data & TDA9873_INP_MASK) != TDA9873_INTERNAL) {
776*4882a593Smuzhiyun 		v4l2_dbg(1, debug, sd,
777*4882a593Smuzhiyun 			 "tda9873_setaudmode(): external input\n");
778*4882a593Smuzhiyun 		return;
779*4882a593Smuzhiyun 	}
780*4882a593Smuzhiyun 
781*4882a593Smuzhiyun 	v4l2_dbg(1, debug, sd,
782*4882a593Smuzhiyun 		 "tda9873_setaudmode(): chip->shadow.bytes[%d] = %d\n",
783*4882a593Smuzhiyun 		 TDA9873_SW+1, chip->shadow.bytes[TDA9873_SW+1]);
784*4882a593Smuzhiyun 	v4l2_dbg(1, debug, sd, "tda9873_setaudmode(): sw_data  = %d\n",
785*4882a593Smuzhiyun 		 sw_data);
786*4882a593Smuzhiyun 
787*4882a593Smuzhiyun 	switch (mode) {
788*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_MONO:
789*4882a593Smuzhiyun 		sw_data |= TDA9873_TR_MONO;
790*4882a593Smuzhiyun 		break;
791*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_STEREO:
792*4882a593Smuzhiyun 		sw_data |= TDA9873_TR_STEREO;
793*4882a593Smuzhiyun 		break;
794*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_LANG1:
795*4882a593Smuzhiyun 		sw_data |= TDA9873_TR_DUALA;
796*4882a593Smuzhiyun 		break;
797*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_LANG2:
798*4882a593Smuzhiyun 		sw_data |= TDA9873_TR_DUALB;
799*4882a593Smuzhiyun 		break;
800*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_LANG1_LANG2:
801*4882a593Smuzhiyun 		sw_data |= TDA9873_TR_DUALAB;
802*4882a593Smuzhiyun 		break;
803*4882a593Smuzhiyun 	default:
804*4882a593Smuzhiyun 		return;
805*4882a593Smuzhiyun 	}
806*4882a593Smuzhiyun 
807*4882a593Smuzhiyun 	chip_write(chip, TDA9873_SW, sw_data);
808*4882a593Smuzhiyun 	v4l2_dbg(1, debug, sd,
809*4882a593Smuzhiyun 		"tda9873_setaudmode(): req. mode %d; chip_write: %d\n",
810*4882a593Smuzhiyun 		mode, sw_data);
811*4882a593Smuzhiyun }
812*4882a593Smuzhiyun 
tda9873_checkit(struct CHIPSTATE * chip)813*4882a593Smuzhiyun static int tda9873_checkit(struct CHIPSTATE *chip)
814*4882a593Smuzhiyun {
815*4882a593Smuzhiyun 	int rc;
816*4882a593Smuzhiyun 
817*4882a593Smuzhiyun 	rc = chip_read2(chip, 254);
818*4882a593Smuzhiyun 	if (rc < 0)
819*4882a593Smuzhiyun 		return 0;
820*4882a593Smuzhiyun 	return (rc & ~0x1f) == 0x80;
821*4882a593Smuzhiyun }
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun 
824*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
825*4882a593Smuzhiyun /* audio chip description - defines+functions for tda9874h and tda9874a   */
826*4882a593Smuzhiyun /* Dariusz Kowalewski <darekk@automex.pl>                                 */
827*4882a593Smuzhiyun 
828*4882a593Smuzhiyun /* Subaddresses for TDA9874H and TDA9874A (slave rx) */
829*4882a593Smuzhiyun #define TDA9874A_AGCGR		0x00	/* AGC gain */
830*4882a593Smuzhiyun #define TDA9874A_GCONR		0x01	/* general config */
831*4882a593Smuzhiyun #define TDA9874A_MSR		0x02	/* monitor select */
832*4882a593Smuzhiyun #define TDA9874A_C1FRA		0x03	/* carrier 1 freq. */
833*4882a593Smuzhiyun #define TDA9874A_C1FRB		0x04	/* carrier 1 freq. */
834*4882a593Smuzhiyun #define TDA9874A_C1FRC		0x05	/* carrier 1 freq. */
835*4882a593Smuzhiyun #define TDA9874A_C2FRA		0x06	/* carrier 2 freq. */
836*4882a593Smuzhiyun #define TDA9874A_C2FRB		0x07	/* carrier 2 freq. */
837*4882a593Smuzhiyun #define TDA9874A_C2FRC		0x08	/* carrier 2 freq. */
838*4882a593Smuzhiyun #define TDA9874A_DCR		0x09	/* demodulator config */
839*4882a593Smuzhiyun #define TDA9874A_FMER		0x0a	/* FM de-emphasis */
840*4882a593Smuzhiyun #define TDA9874A_FMMR		0x0b	/* FM dematrix */
841*4882a593Smuzhiyun #define TDA9874A_C1OLAR		0x0c	/* ch.1 output level adj. */
842*4882a593Smuzhiyun #define TDA9874A_C2OLAR		0x0d	/* ch.2 output level adj. */
843*4882a593Smuzhiyun #define TDA9874A_NCONR		0x0e	/* NICAM config */
844*4882a593Smuzhiyun #define TDA9874A_NOLAR		0x0f	/* NICAM output level adj. */
845*4882a593Smuzhiyun #define TDA9874A_NLELR		0x10	/* NICAM lower error limit */
846*4882a593Smuzhiyun #define TDA9874A_NUELR		0x11	/* NICAM upper error limit */
847*4882a593Smuzhiyun #define TDA9874A_AMCONR		0x12	/* audio mute control */
848*4882a593Smuzhiyun #define TDA9874A_SDACOSR	0x13	/* stereo DAC output select */
849*4882a593Smuzhiyun #define TDA9874A_AOSR		0x14	/* analog output select */
850*4882a593Smuzhiyun #define TDA9874A_DAICONR	0x15	/* digital audio interface config */
851*4882a593Smuzhiyun #define TDA9874A_I2SOSR		0x16	/* I2S-bus output select */
852*4882a593Smuzhiyun #define TDA9874A_I2SOLAR	0x17	/* I2S-bus output level adj. */
853*4882a593Smuzhiyun #define TDA9874A_MDACOSR	0x18	/* mono DAC output select (tda9874a) */
854*4882a593Smuzhiyun #define TDA9874A_ESP		0xFF	/* easy standard progr. (tda9874a) */
855*4882a593Smuzhiyun 
856*4882a593Smuzhiyun /* Subaddresses for TDA9874H and TDA9874A (slave tx) */
857*4882a593Smuzhiyun #define TDA9874A_DSR		0x00	/* device status */
858*4882a593Smuzhiyun #define TDA9874A_NSR		0x01	/* NICAM status */
859*4882a593Smuzhiyun #define TDA9874A_NECR		0x02	/* NICAM error count */
860*4882a593Smuzhiyun #define TDA9874A_DR1		0x03	/* add. data LSB */
861*4882a593Smuzhiyun #define TDA9874A_DR2		0x04	/* add. data MSB */
862*4882a593Smuzhiyun #define TDA9874A_LLRA		0x05	/* monitor level read-out LSB */
863*4882a593Smuzhiyun #define TDA9874A_LLRB		0x06	/* monitor level read-out MSB */
864*4882a593Smuzhiyun #define TDA9874A_SIFLR		0x07	/* SIF level */
865*4882a593Smuzhiyun #define TDA9874A_TR2		252	/* test reg. 2 */
866*4882a593Smuzhiyun #define TDA9874A_TR1		253	/* test reg. 1 */
867*4882a593Smuzhiyun #define TDA9874A_DIC		254	/* device id. code */
868*4882a593Smuzhiyun #define TDA9874A_SIC		255	/* software id. code */
869*4882a593Smuzhiyun 
870*4882a593Smuzhiyun 
871*4882a593Smuzhiyun static int tda9874a_mode = 1;		/* 0: A2, 1: NICAM */
872*4882a593Smuzhiyun static int tda9874a_GCONR = 0xc0;	/* default config. input pin: SIFSEL=0 */
873*4882a593Smuzhiyun static int tda9874a_NCONR = 0x01;	/* default NICAM config.: AMSEL=0,AMUTE=1 */
874*4882a593Smuzhiyun static int tda9874a_ESP = 0x07;		/* default standard: NICAM D/K */
875*4882a593Smuzhiyun static int tda9874a_dic = -1;		/* device id. code */
876*4882a593Smuzhiyun 
877*4882a593Smuzhiyun /* insmod options for tda9874a */
878*4882a593Smuzhiyun static unsigned int tda9874a_SIF   = UNSET;
879*4882a593Smuzhiyun static unsigned int tda9874a_AMSEL = UNSET;
880*4882a593Smuzhiyun static unsigned int tda9874a_STD   = UNSET;
881*4882a593Smuzhiyun module_param(tda9874a_SIF, int, 0444);
882*4882a593Smuzhiyun module_param(tda9874a_AMSEL, int, 0444);
883*4882a593Smuzhiyun module_param(tda9874a_STD, int, 0444);
884*4882a593Smuzhiyun 
885*4882a593Smuzhiyun /*
886*4882a593Smuzhiyun  * initialization table for tda9874 decoder:
887*4882a593Smuzhiyun  *  - carrier 1 freq. registers (3 bytes)
888*4882a593Smuzhiyun  *  - carrier 2 freq. registers (3 bytes)
889*4882a593Smuzhiyun  *  - demudulator config register
890*4882a593Smuzhiyun  *  - FM de-emphasis register (slow identification mode)
891*4882a593Smuzhiyun  * Note: frequency registers must be written in single i2c transfer.
892*4882a593Smuzhiyun  */
893*4882a593Smuzhiyun static struct tda9874a_MODES {
894*4882a593Smuzhiyun 	char *name;
895*4882a593Smuzhiyun 	audiocmd cmd;
896*4882a593Smuzhiyun } tda9874a_modelist[9] = {
897*4882a593Smuzhiyun   {	"A2, B/G", /* default */
898*4882a593Smuzhiyun 	{ 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x77,0xA0,0x00, 0x00,0x00 }} },
899*4882a593Smuzhiyun   {	"A2, M (Korea)",
900*4882a593Smuzhiyun 	{ 9, { TDA9874A_C1FRA, 0x5D,0xC0,0x00, 0x62,0x6A,0xAA, 0x20,0x22 }} },
901*4882a593Smuzhiyun   {	"A2, D/K (1)",
902*4882a593Smuzhiyun 	{ 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x82,0x60,0x00, 0x00,0x00 }} },
903*4882a593Smuzhiyun   {	"A2, D/K (2)",
904*4882a593Smuzhiyun 	{ 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x8C,0x75,0x55, 0x00,0x00 }} },
905*4882a593Smuzhiyun   {	"A2, D/K (3)",
906*4882a593Smuzhiyun 	{ 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x77,0xA0,0x00, 0x00,0x00 }} },
907*4882a593Smuzhiyun   {	"NICAM, I",
908*4882a593Smuzhiyun 	{ 9, { TDA9874A_C1FRA, 0x7D,0x00,0x00, 0x88,0x8A,0xAA, 0x08,0x33 }} },
909*4882a593Smuzhiyun   {	"NICAM, B/G",
910*4882a593Smuzhiyun 	{ 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x79,0xEA,0xAA, 0x08,0x33 }} },
911*4882a593Smuzhiyun   {	"NICAM, D/K",
912*4882a593Smuzhiyun 	{ 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x08,0x33 }} },
913*4882a593Smuzhiyun   {	"NICAM, L",
914*4882a593Smuzhiyun 	{ 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x09,0x33 }} }
915*4882a593Smuzhiyun };
916*4882a593Smuzhiyun 
tda9874a_setup(struct CHIPSTATE * chip)917*4882a593Smuzhiyun static int tda9874a_setup(struct CHIPSTATE *chip)
918*4882a593Smuzhiyun {
919*4882a593Smuzhiyun 	struct v4l2_subdev *sd = &chip->sd;
920*4882a593Smuzhiyun 
921*4882a593Smuzhiyun 	chip_write(chip, TDA9874A_AGCGR, 0x00); /* 0 dB */
922*4882a593Smuzhiyun 	chip_write(chip, TDA9874A_GCONR, tda9874a_GCONR);
923*4882a593Smuzhiyun 	chip_write(chip, TDA9874A_MSR, (tda9874a_mode) ? 0x03:0x02);
924*4882a593Smuzhiyun 	if(tda9874a_dic == 0x11) {
925*4882a593Smuzhiyun 		chip_write(chip, TDA9874A_FMMR, 0x80);
926*4882a593Smuzhiyun 	} else { /* dic == 0x07 */
927*4882a593Smuzhiyun 		chip_cmd(chip,"tda9874_modelist",&tda9874a_modelist[tda9874a_STD].cmd);
928*4882a593Smuzhiyun 		chip_write(chip, TDA9874A_FMMR, 0x00);
929*4882a593Smuzhiyun 	}
930*4882a593Smuzhiyun 	chip_write(chip, TDA9874A_C1OLAR, 0x00); /* 0 dB */
931*4882a593Smuzhiyun 	chip_write(chip, TDA9874A_C2OLAR, 0x00); /* 0 dB */
932*4882a593Smuzhiyun 	chip_write(chip, TDA9874A_NCONR, tda9874a_NCONR);
933*4882a593Smuzhiyun 	chip_write(chip, TDA9874A_NOLAR, 0x00); /* 0 dB */
934*4882a593Smuzhiyun 	/* Note: If signal quality is poor you may want to change NICAM */
935*4882a593Smuzhiyun 	/* error limit registers (NLELR and NUELR) to some greater values. */
936*4882a593Smuzhiyun 	/* Then the sound would remain stereo, but won't be so clear. */
937*4882a593Smuzhiyun 	chip_write(chip, TDA9874A_NLELR, 0x14); /* default */
938*4882a593Smuzhiyun 	chip_write(chip, TDA9874A_NUELR, 0x50); /* default */
939*4882a593Smuzhiyun 
940*4882a593Smuzhiyun 	if(tda9874a_dic == 0x11) {
941*4882a593Smuzhiyun 		chip_write(chip, TDA9874A_AMCONR, 0xf9);
942*4882a593Smuzhiyun 		chip_write(chip, TDA9874A_SDACOSR, (tda9874a_mode) ? 0x81:0x80);
943*4882a593Smuzhiyun 		chip_write(chip, TDA9874A_AOSR, 0x80);
944*4882a593Smuzhiyun 		chip_write(chip, TDA9874A_MDACOSR, (tda9874a_mode) ? 0x82:0x80);
945*4882a593Smuzhiyun 		chip_write(chip, TDA9874A_ESP, tda9874a_ESP);
946*4882a593Smuzhiyun 	} else { /* dic == 0x07 */
947*4882a593Smuzhiyun 		chip_write(chip, TDA9874A_AMCONR, 0xfb);
948*4882a593Smuzhiyun 		chip_write(chip, TDA9874A_SDACOSR, (tda9874a_mode) ? 0x81:0x80);
949*4882a593Smuzhiyun 		chip_write(chip, TDA9874A_AOSR, 0x00); /* or 0x10 */
950*4882a593Smuzhiyun 	}
951*4882a593Smuzhiyun 	v4l2_dbg(1, debug, sd, "tda9874a_setup(): %s [0x%02X].\n",
952*4882a593Smuzhiyun 		tda9874a_modelist[tda9874a_STD].name,tda9874a_STD);
953*4882a593Smuzhiyun 	return 1;
954*4882a593Smuzhiyun }
955*4882a593Smuzhiyun 
tda9874a_getrxsubchans(struct CHIPSTATE * chip)956*4882a593Smuzhiyun static int tda9874a_getrxsubchans(struct CHIPSTATE *chip)
957*4882a593Smuzhiyun {
958*4882a593Smuzhiyun 	struct v4l2_subdev *sd = &chip->sd;
959*4882a593Smuzhiyun 	int dsr,nsr,mode;
960*4882a593Smuzhiyun 	int necr; /* just for debugging */
961*4882a593Smuzhiyun 
962*4882a593Smuzhiyun 	mode = V4L2_TUNER_SUB_MONO;
963*4882a593Smuzhiyun 
964*4882a593Smuzhiyun 	dsr = chip_read2(chip, TDA9874A_DSR);
965*4882a593Smuzhiyun 	if (dsr < 0)
966*4882a593Smuzhiyun 		return mode;
967*4882a593Smuzhiyun 	nsr = chip_read2(chip, TDA9874A_NSR);
968*4882a593Smuzhiyun 	if (nsr < 0)
969*4882a593Smuzhiyun 		return mode;
970*4882a593Smuzhiyun 	necr = chip_read2(chip, TDA9874A_NECR);
971*4882a593Smuzhiyun 	if (necr < 0)
972*4882a593Smuzhiyun 		return mode;
973*4882a593Smuzhiyun 
974*4882a593Smuzhiyun 	/* need to store dsr/nsr somewhere */
975*4882a593Smuzhiyun 	chip->shadow.bytes[MAXREGS-2] = dsr;
976*4882a593Smuzhiyun 	chip->shadow.bytes[MAXREGS-1] = nsr;
977*4882a593Smuzhiyun 
978*4882a593Smuzhiyun 	if(tda9874a_mode) {
979*4882a593Smuzhiyun 		/* Note: DSR.RSSF and DSR.AMSTAT bits are also checked.
980*4882a593Smuzhiyun 		 * If NICAM auto-muting is enabled, DSR.AMSTAT=1 indicates
981*4882a593Smuzhiyun 		 * that sound has (temporarily) switched from NICAM to
982*4882a593Smuzhiyun 		 * mono FM (or AM) on 1st sound carrier due to high NICAM bit
983*4882a593Smuzhiyun 		 * error count. So in fact there is no stereo in this case :-(
984*4882a593Smuzhiyun 		 * But changing the mode to V4L2_TUNER_MODE_MONO would switch
985*4882a593Smuzhiyun 		 * external 4052 multiplexer in audio_hook().
986*4882a593Smuzhiyun 		 */
987*4882a593Smuzhiyun 		if(nsr & 0x02) /* NSR.S/MB=1 */
988*4882a593Smuzhiyun 			mode = V4L2_TUNER_SUB_STEREO;
989*4882a593Smuzhiyun 		if(nsr & 0x01) /* NSR.D/SB=1 */
990*4882a593Smuzhiyun 			mode |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
991*4882a593Smuzhiyun 	} else {
992*4882a593Smuzhiyun 		if(dsr & 0x02) /* DSR.IDSTE=1 */
993*4882a593Smuzhiyun 			mode = V4L2_TUNER_SUB_STEREO;
994*4882a593Smuzhiyun 		if(dsr & 0x04) /* DSR.IDDUA=1 */
995*4882a593Smuzhiyun 			mode |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
996*4882a593Smuzhiyun 	}
997*4882a593Smuzhiyun 
998*4882a593Smuzhiyun 	v4l2_dbg(1, debug, sd,
999*4882a593Smuzhiyun 		 "tda9874a_getrxsubchans(): DSR=0x%X, NSR=0x%X, NECR=0x%X, return: %d.\n",
1000*4882a593Smuzhiyun 		 dsr, nsr, necr, mode);
1001*4882a593Smuzhiyun 	return mode;
1002*4882a593Smuzhiyun }
1003*4882a593Smuzhiyun 
tda9874a_setaudmode(struct CHIPSTATE * chip,int mode)1004*4882a593Smuzhiyun static void tda9874a_setaudmode(struct CHIPSTATE *chip, int mode)
1005*4882a593Smuzhiyun {
1006*4882a593Smuzhiyun 	struct v4l2_subdev *sd = &chip->sd;
1007*4882a593Smuzhiyun 
1008*4882a593Smuzhiyun 	/* Disable/enable NICAM auto-muting (based on DSR.RSSF status bit). */
1009*4882a593Smuzhiyun 	/* If auto-muting is disabled, we can hear a signal of degrading quality. */
1010*4882a593Smuzhiyun 	if (tda9874a_mode) {
1011*4882a593Smuzhiyun 		if(chip->shadow.bytes[MAXREGS-2] & 0x20) /* DSR.RSSF=1 */
1012*4882a593Smuzhiyun 			tda9874a_NCONR &= 0xfe; /* enable */
1013*4882a593Smuzhiyun 		else
1014*4882a593Smuzhiyun 			tda9874a_NCONR |= 0x01; /* disable */
1015*4882a593Smuzhiyun 		chip_write(chip, TDA9874A_NCONR, tda9874a_NCONR);
1016*4882a593Smuzhiyun 	}
1017*4882a593Smuzhiyun 
1018*4882a593Smuzhiyun 	/* Note: TDA9874A supports automatic FM dematrixing (FMMR register)
1019*4882a593Smuzhiyun 	 * and has auto-select function for audio output (AOSR register).
1020*4882a593Smuzhiyun 	 * Old TDA9874H doesn't support these features.
1021*4882a593Smuzhiyun 	 * TDA9874A also has additional mono output pin (OUTM), which
1022*4882a593Smuzhiyun 	 * on same (all?) tv-cards is not used, anyway (as well as MONOIN).
1023*4882a593Smuzhiyun 	 */
1024*4882a593Smuzhiyun 	if(tda9874a_dic == 0x11) {
1025*4882a593Smuzhiyun 		int aosr = 0x80;
1026*4882a593Smuzhiyun 		int mdacosr = (tda9874a_mode) ? 0x82:0x80;
1027*4882a593Smuzhiyun 
1028*4882a593Smuzhiyun 		switch(mode) {
1029*4882a593Smuzhiyun 		case V4L2_TUNER_MODE_MONO:
1030*4882a593Smuzhiyun 		case V4L2_TUNER_MODE_STEREO:
1031*4882a593Smuzhiyun 			break;
1032*4882a593Smuzhiyun 		case V4L2_TUNER_MODE_LANG1:
1033*4882a593Smuzhiyun 			aosr = 0x80; /* auto-select, dual A/A */
1034*4882a593Smuzhiyun 			mdacosr = (tda9874a_mode) ? 0x82:0x80;
1035*4882a593Smuzhiyun 			break;
1036*4882a593Smuzhiyun 		case V4L2_TUNER_MODE_LANG2:
1037*4882a593Smuzhiyun 			aosr = 0xa0; /* auto-select, dual B/B */
1038*4882a593Smuzhiyun 			mdacosr = (tda9874a_mode) ? 0x83:0x81;
1039*4882a593Smuzhiyun 			break;
1040*4882a593Smuzhiyun 		case V4L2_TUNER_MODE_LANG1_LANG2:
1041*4882a593Smuzhiyun 			aosr = 0x00; /* always route L to L and R to R */
1042*4882a593Smuzhiyun 			mdacosr = (tda9874a_mode) ? 0x82:0x80;
1043*4882a593Smuzhiyun 			break;
1044*4882a593Smuzhiyun 		default:
1045*4882a593Smuzhiyun 			return;
1046*4882a593Smuzhiyun 		}
1047*4882a593Smuzhiyun 		chip_write(chip, TDA9874A_AOSR, aosr);
1048*4882a593Smuzhiyun 		chip_write(chip, TDA9874A_MDACOSR, mdacosr);
1049*4882a593Smuzhiyun 
1050*4882a593Smuzhiyun 		v4l2_dbg(1, debug, sd,
1051*4882a593Smuzhiyun 			"tda9874a_setaudmode(): req. mode %d; AOSR=0x%X, MDACOSR=0x%X.\n",
1052*4882a593Smuzhiyun 			mode, aosr, mdacosr);
1053*4882a593Smuzhiyun 
1054*4882a593Smuzhiyun 	} else { /* dic == 0x07 */
1055*4882a593Smuzhiyun 		int fmmr,aosr;
1056*4882a593Smuzhiyun 
1057*4882a593Smuzhiyun 		switch(mode) {
1058*4882a593Smuzhiyun 		case V4L2_TUNER_MODE_MONO:
1059*4882a593Smuzhiyun 			fmmr = 0x00; /* mono */
1060*4882a593Smuzhiyun 			aosr = 0x10; /* A/A */
1061*4882a593Smuzhiyun 			break;
1062*4882a593Smuzhiyun 		case V4L2_TUNER_MODE_STEREO:
1063*4882a593Smuzhiyun 			if(tda9874a_mode) {
1064*4882a593Smuzhiyun 				fmmr = 0x00;
1065*4882a593Smuzhiyun 				aosr = 0x00; /* handled by NICAM auto-mute */
1066*4882a593Smuzhiyun 			} else {
1067*4882a593Smuzhiyun 				fmmr = (tda9874a_ESP == 1) ? 0x05 : 0x04; /* stereo */
1068*4882a593Smuzhiyun 				aosr = 0x00;
1069*4882a593Smuzhiyun 			}
1070*4882a593Smuzhiyun 			break;
1071*4882a593Smuzhiyun 		case V4L2_TUNER_MODE_LANG1:
1072*4882a593Smuzhiyun 			fmmr = 0x02; /* dual */
1073*4882a593Smuzhiyun 			aosr = 0x10; /* dual A/A */
1074*4882a593Smuzhiyun 			break;
1075*4882a593Smuzhiyun 		case V4L2_TUNER_MODE_LANG2:
1076*4882a593Smuzhiyun 			fmmr = 0x02; /* dual */
1077*4882a593Smuzhiyun 			aosr = 0x20; /* dual B/B */
1078*4882a593Smuzhiyun 			break;
1079*4882a593Smuzhiyun 		case V4L2_TUNER_MODE_LANG1_LANG2:
1080*4882a593Smuzhiyun 			fmmr = 0x02; /* dual */
1081*4882a593Smuzhiyun 			aosr = 0x00; /* dual A/B */
1082*4882a593Smuzhiyun 			break;
1083*4882a593Smuzhiyun 		default:
1084*4882a593Smuzhiyun 			return;
1085*4882a593Smuzhiyun 		}
1086*4882a593Smuzhiyun 		chip_write(chip, TDA9874A_FMMR, fmmr);
1087*4882a593Smuzhiyun 		chip_write(chip, TDA9874A_AOSR, aosr);
1088*4882a593Smuzhiyun 
1089*4882a593Smuzhiyun 		v4l2_dbg(1, debug, sd,
1090*4882a593Smuzhiyun 			"tda9874a_setaudmode(): req. mode %d; FMMR=0x%X, AOSR=0x%X.\n",
1091*4882a593Smuzhiyun 			mode, fmmr, aosr);
1092*4882a593Smuzhiyun 	}
1093*4882a593Smuzhiyun }
1094*4882a593Smuzhiyun 
tda9874a_checkit(struct CHIPSTATE * chip)1095*4882a593Smuzhiyun static int tda9874a_checkit(struct CHIPSTATE *chip)
1096*4882a593Smuzhiyun {
1097*4882a593Smuzhiyun 	struct v4l2_subdev *sd = &chip->sd;
1098*4882a593Smuzhiyun 	int dic,sic;	/* device id. and software id. codes */
1099*4882a593Smuzhiyun 
1100*4882a593Smuzhiyun 	dic = chip_read2(chip, TDA9874A_DIC);
1101*4882a593Smuzhiyun 	if (dic < 0)
1102*4882a593Smuzhiyun 		return 0;
1103*4882a593Smuzhiyun 	sic = chip_read2(chip, TDA9874A_SIC);
1104*4882a593Smuzhiyun 	if (sic < 0)
1105*4882a593Smuzhiyun 		return 0;
1106*4882a593Smuzhiyun 
1107*4882a593Smuzhiyun 	v4l2_dbg(1, debug, sd, "tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic);
1108*4882a593Smuzhiyun 
1109*4882a593Smuzhiyun 	if((dic == 0x11)||(dic == 0x07)) {
1110*4882a593Smuzhiyun 		v4l2_info(sd, "found tda9874%s.\n", (dic == 0x11) ? "a" : "h");
1111*4882a593Smuzhiyun 		tda9874a_dic = dic;	/* remember device id. */
1112*4882a593Smuzhiyun 		return 1;
1113*4882a593Smuzhiyun 	}
1114*4882a593Smuzhiyun 	return 0;	/* not found */
1115*4882a593Smuzhiyun }
1116*4882a593Smuzhiyun 
tda9874a_initialize(struct CHIPSTATE * chip)1117*4882a593Smuzhiyun static int tda9874a_initialize(struct CHIPSTATE *chip)
1118*4882a593Smuzhiyun {
1119*4882a593Smuzhiyun 	if (tda9874a_SIF > 2)
1120*4882a593Smuzhiyun 		tda9874a_SIF = 1;
1121*4882a593Smuzhiyun 	if (tda9874a_STD >= ARRAY_SIZE(tda9874a_modelist))
1122*4882a593Smuzhiyun 		tda9874a_STD = 0;
1123*4882a593Smuzhiyun 	if(tda9874a_AMSEL > 1)
1124*4882a593Smuzhiyun 		tda9874a_AMSEL = 0;
1125*4882a593Smuzhiyun 
1126*4882a593Smuzhiyun 	if(tda9874a_SIF == 1)
1127*4882a593Smuzhiyun 		tda9874a_GCONR = 0xc0;	/* sound IF input 1 */
1128*4882a593Smuzhiyun 	else
1129*4882a593Smuzhiyun 		tda9874a_GCONR = 0xc1;	/* sound IF input 2 */
1130*4882a593Smuzhiyun 
1131*4882a593Smuzhiyun 	tda9874a_ESP = tda9874a_STD;
1132*4882a593Smuzhiyun 	tda9874a_mode = (tda9874a_STD < 5) ? 0 : 1;
1133*4882a593Smuzhiyun 
1134*4882a593Smuzhiyun 	if(tda9874a_AMSEL == 0)
1135*4882a593Smuzhiyun 		tda9874a_NCONR = 0x01; /* auto-mute: analog mono input */
1136*4882a593Smuzhiyun 	else
1137*4882a593Smuzhiyun 		tda9874a_NCONR = 0x05; /* auto-mute: 1st carrier FM or AM */
1138*4882a593Smuzhiyun 
1139*4882a593Smuzhiyun 	tda9874a_setup(chip);
1140*4882a593Smuzhiyun 	return 0;
1141*4882a593Smuzhiyun }
1142*4882a593Smuzhiyun 
1143*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
1144*4882a593Smuzhiyun /* audio chip description - defines+functions for tda9875                 */
1145*4882a593Smuzhiyun /* The TDA9875 is made by Philips Semiconductor
1146*4882a593Smuzhiyun  * http://www.semiconductors.philips.com
1147*4882a593Smuzhiyun  * TDA9875: I2C-bus controlled DSP audio processor, FM demodulator
1148*4882a593Smuzhiyun  *
1149*4882a593Smuzhiyun  */
1150*4882a593Smuzhiyun 
1151*4882a593Smuzhiyun /* subaddresses for TDA9875 */
1152*4882a593Smuzhiyun #define TDA9875_MUT         0x12  /*General mute  (value --> 0b11001100*/
1153*4882a593Smuzhiyun #define TDA9875_CFG         0x01  /* Config register (value --> 0b00000000 */
1154*4882a593Smuzhiyun #define TDA9875_DACOS       0x13  /*DAC i/o select (ADC) 0b0000100*/
1155*4882a593Smuzhiyun #define TDA9875_LOSR        0x16  /*Line output select regirter 0b0100 0001*/
1156*4882a593Smuzhiyun 
1157*4882a593Smuzhiyun #define TDA9875_CH1V        0x0c  /*Channel 1 volume (mute)*/
1158*4882a593Smuzhiyun #define TDA9875_CH2V        0x0d  /*Channel 2 volume (mute)*/
1159*4882a593Smuzhiyun #define TDA9875_SC1         0x14  /*SCART 1 in (mono)*/
1160*4882a593Smuzhiyun #define TDA9875_SC2         0x15  /*SCART 2 in (mono)*/
1161*4882a593Smuzhiyun 
1162*4882a593Smuzhiyun #define TDA9875_ADCIS       0x17  /*ADC input select (mono) 0b0110 000*/
1163*4882a593Smuzhiyun #define TDA9875_AER         0x19  /*Audio effect (AVL+Pseudo) 0b0000 0110*/
1164*4882a593Smuzhiyun #define TDA9875_MCS         0x18  /*Main channel select (DAC) 0b0000100*/
1165*4882a593Smuzhiyun #define TDA9875_MVL         0x1a  /* Main volume gauche */
1166*4882a593Smuzhiyun #define TDA9875_MVR         0x1b  /* Main volume droite */
1167*4882a593Smuzhiyun #define TDA9875_MBA         0x1d  /* Main Basse */
1168*4882a593Smuzhiyun #define TDA9875_MTR         0x1e  /* Main treble */
1169*4882a593Smuzhiyun #define TDA9875_ACS         0x1f  /* Auxiliary channel select (FM) 0b0000000*/
1170*4882a593Smuzhiyun #define TDA9875_AVL         0x20  /* Auxiliary volume gauche */
1171*4882a593Smuzhiyun #define TDA9875_AVR         0x21  /* Auxiliary volume droite */
1172*4882a593Smuzhiyun #define TDA9875_ABA         0x22  /* Auxiliary Basse */
1173*4882a593Smuzhiyun #define TDA9875_ATR         0x23  /* Auxiliary treble */
1174*4882a593Smuzhiyun 
1175*4882a593Smuzhiyun #define TDA9875_MSR         0x02  /* Monitor select register */
1176*4882a593Smuzhiyun #define TDA9875_C1MSB       0x03  /* Carrier 1 (FM) frequency register MSB */
1177*4882a593Smuzhiyun #define TDA9875_C1MIB       0x04  /* Carrier 1 (FM) frequency register (16-8]b */
1178*4882a593Smuzhiyun #define TDA9875_C1LSB       0x05  /* Carrier 1 (FM) frequency register LSB */
1179*4882a593Smuzhiyun #define TDA9875_C2MSB       0x06  /* Carrier 2 (nicam) frequency register MSB */
1180*4882a593Smuzhiyun #define TDA9875_C2MIB       0x07  /* Carrier 2 (nicam) frequency register (16-8]b */
1181*4882a593Smuzhiyun #define TDA9875_C2LSB       0x08  /* Carrier 2 (nicam) frequency register LSB */
1182*4882a593Smuzhiyun #define TDA9875_DCR         0x09  /* Demodulateur configuration regirter*/
1183*4882a593Smuzhiyun #define TDA9875_DEEM        0x0a  /* FM de-emphasis regirter*/
1184*4882a593Smuzhiyun #define TDA9875_FMAT        0x0b  /* FM Matrix regirter*/
1185*4882a593Smuzhiyun 
1186*4882a593Smuzhiyun /* values */
1187*4882a593Smuzhiyun #define TDA9875_MUTE_ON	    0xff /* general mute */
1188*4882a593Smuzhiyun #define TDA9875_MUTE_OFF    0xcc /* general no mute */
1189*4882a593Smuzhiyun 
tda9875_initialize(struct CHIPSTATE * chip)1190*4882a593Smuzhiyun static int tda9875_initialize(struct CHIPSTATE *chip)
1191*4882a593Smuzhiyun {
1192*4882a593Smuzhiyun 	chip_write(chip, TDA9875_CFG, 0xd0); /*reg de config 0 (reset)*/
1193*4882a593Smuzhiyun 	chip_write(chip, TDA9875_MSR, 0x03);    /* Monitor 0b00000XXX*/
1194*4882a593Smuzhiyun 	chip_write(chip, TDA9875_C1MSB, 0x00);  /*Car1(FM) MSB XMHz*/
1195*4882a593Smuzhiyun 	chip_write(chip, TDA9875_C1MIB, 0x00);  /*Car1(FM) MIB XMHz*/
1196*4882a593Smuzhiyun 	chip_write(chip, TDA9875_C1LSB, 0x00);  /*Car1(FM) LSB XMHz*/
1197*4882a593Smuzhiyun 	chip_write(chip, TDA9875_C2MSB, 0x00);  /*Car2(NICAM) MSB XMHz*/
1198*4882a593Smuzhiyun 	chip_write(chip, TDA9875_C2MIB, 0x00);  /*Car2(NICAM) MIB XMHz*/
1199*4882a593Smuzhiyun 	chip_write(chip, TDA9875_C2LSB, 0x00);  /*Car2(NICAM) LSB XMHz*/
1200*4882a593Smuzhiyun 	chip_write(chip, TDA9875_DCR, 0x00);    /*Demod config 0x00*/
1201*4882a593Smuzhiyun 	chip_write(chip, TDA9875_DEEM, 0x44);   /*DE-Emph 0b0100 0100*/
1202*4882a593Smuzhiyun 	chip_write(chip, TDA9875_FMAT, 0x00);   /*FM Matrix reg 0x00*/
1203*4882a593Smuzhiyun 	chip_write(chip, TDA9875_SC1, 0x00);    /* SCART 1 (SC1)*/
1204*4882a593Smuzhiyun 	chip_write(chip, TDA9875_SC2, 0x01);    /* SCART 2 (sc2)*/
1205*4882a593Smuzhiyun 
1206*4882a593Smuzhiyun 	chip_write(chip, TDA9875_CH1V, 0x10);  /* Channel volume 1 mute*/
1207*4882a593Smuzhiyun 	chip_write(chip, TDA9875_CH2V, 0x10);  /* Channel volume 2 mute */
1208*4882a593Smuzhiyun 	chip_write(chip, TDA9875_DACOS, 0x02); /* sig DAC i/o(in:nicam)*/
1209*4882a593Smuzhiyun 	chip_write(chip, TDA9875_ADCIS, 0x6f); /* sig ADC input(in:mono)*/
1210*4882a593Smuzhiyun 	chip_write(chip, TDA9875_LOSR, 0x00);  /* line out (in:mono)*/
1211*4882a593Smuzhiyun 	chip_write(chip, TDA9875_AER, 0x00);   /*06 Effect (AVL+PSEUDO) */
1212*4882a593Smuzhiyun 	chip_write(chip, TDA9875_MCS, 0x44);   /* Main ch select (DAC) */
1213*4882a593Smuzhiyun 	chip_write(chip, TDA9875_MVL, 0x03);   /* Vol Main left 10dB */
1214*4882a593Smuzhiyun 	chip_write(chip, TDA9875_MVR, 0x03);   /* Vol Main right 10dB*/
1215*4882a593Smuzhiyun 	chip_write(chip, TDA9875_MBA, 0x00);   /* Main Bass Main 0dB*/
1216*4882a593Smuzhiyun 	chip_write(chip, TDA9875_MTR, 0x00);   /* Main Treble Main 0dB*/
1217*4882a593Smuzhiyun 	chip_write(chip, TDA9875_ACS, 0x44);   /* Aux chan select (dac)*/
1218*4882a593Smuzhiyun 	chip_write(chip, TDA9875_AVL, 0x00);   /* Vol Aux left 0dB*/
1219*4882a593Smuzhiyun 	chip_write(chip, TDA9875_AVR, 0x00);   /* Vol Aux right 0dB*/
1220*4882a593Smuzhiyun 	chip_write(chip, TDA9875_ABA, 0x00);   /* Aux Bass Main 0dB*/
1221*4882a593Smuzhiyun 	chip_write(chip, TDA9875_ATR, 0x00);   /* Aux Aigus Main 0dB*/
1222*4882a593Smuzhiyun 
1223*4882a593Smuzhiyun 	chip_write(chip, TDA9875_MUT, 0xcc);   /* General mute  */
1224*4882a593Smuzhiyun 	return 0;
1225*4882a593Smuzhiyun }
1226*4882a593Smuzhiyun 
tda9875_volume(int val)1227*4882a593Smuzhiyun static int tda9875_volume(int val) { return (unsigned char)(val / 602 - 84); }
tda9875_bass(int val)1228*4882a593Smuzhiyun static int tda9875_bass(int val) { return (unsigned char)(max(-12, val / 2115 - 15)); }
tda9875_treble(int val)1229*4882a593Smuzhiyun static int tda9875_treble(int val) { return (unsigned char)(val / 2622 - 12); }
1230*4882a593Smuzhiyun 
1231*4882a593Smuzhiyun /* ----------------------------------------------------------------------- */
1232*4882a593Smuzhiyun 
1233*4882a593Smuzhiyun 
1234*4882a593Smuzhiyun /* *********************** *
1235*4882a593Smuzhiyun  * i2c interface functions *
1236*4882a593Smuzhiyun  * *********************** */
1237*4882a593Smuzhiyun 
tda9875_checkit(struct CHIPSTATE * chip)1238*4882a593Smuzhiyun static int tda9875_checkit(struct CHIPSTATE *chip)
1239*4882a593Smuzhiyun {
1240*4882a593Smuzhiyun 	struct v4l2_subdev *sd = &chip->sd;
1241*4882a593Smuzhiyun 	int dic, rev;
1242*4882a593Smuzhiyun 
1243*4882a593Smuzhiyun 	dic = chip_read2(chip, 254);
1244*4882a593Smuzhiyun 	if (dic < 0)
1245*4882a593Smuzhiyun 		return 0;
1246*4882a593Smuzhiyun 	rev = chip_read2(chip, 255);
1247*4882a593Smuzhiyun 	if (rev < 0)
1248*4882a593Smuzhiyun 		return 0;
1249*4882a593Smuzhiyun 
1250*4882a593Smuzhiyun 	if (dic == 0 || dic == 2) { /* tda9875 and tda9875A */
1251*4882a593Smuzhiyun 		v4l2_info(sd, "found tda9875%s rev. %d.\n",
1252*4882a593Smuzhiyun 			dic == 0 ? "" : "A", rev);
1253*4882a593Smuzhiyun 		return 1;
1254*4882a593Smuzhiyun 	}
1255*4882a593Smuzhiyun 	return 0;
1256*4882a593Smuzhiyun }
1257*4882a593Smuzhiyun 
1258*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
1259*4882a593Smuzhiyun /* audio chip descriptions - defines+functions for tea6420                */
1260*4882a593Smuzhiyun 
1261*4882a593Smuzhiyun #define TEA6300_VL         0x00  /* volume left */
1262*4882a593Smuzhiyun #define TEA6300_VR         0x01  /* volume right */
1263*4882a593Smuzhiyun #define TEA6300_BA         0x02  /* bass */
1264*4882a593Smuzhiyun #define TEA6300_TR         0x03  /* treble */
1265*4882a593Smuzhiyun #define TEA6300_FA         0x04  /* fader control */
1266*4882a593Smuzhiyun #define TEA6300_S          0x05  /* switch register */
1267*4882a593Smuzhiyun 				 /* values for those registers: */
1268*4882a593Smuzhiyun #define TEA6300_S_SA       0x01  /* stereo A input */
1269*4882a593Smuzhiyun #define TEA6300_S_SB       0x02  /* stereo B */
1270*4882a593Smuzhiyun #define TEA6300_S_SC       0x04  /* stereo C */
1271*4882a593Smuzhiyun #define TEA6300_S_GMU      0x80  /* general mute */
1272*4882a593Smuzhiyun 
1273*4882a593Smuzhiyun #define TEA6320_V          0x00  /* volume (0-5)/loudness off (6)/zero crossing mute(7) */
1274*4882a593Smuzhiyun #define TEA6320_FFR        0x01  /* fader front right (0-5) */
1275*4882a593Smuzhiyun #define TEA6320_FFL        0x02  /* fader front left (0-5) */
1276*4882a593Smuzhiyun #define TEA6320_FRR        0x03  /* fader rear right (0-5) */
1277*4882a593Smuzhiyun #define TEA6320_FRL        0x04  /* fader rear left (0-5) */
1278*4882a593Smuzhiyun #define TEA6320_BA         0x05  /* bass (0-4) */
1279*4882a593Smuzhiyun #define TEA6320_TR         0x06  /* treble (0-4) */
1280*4882a593Smuzhiyun #define TEA6320_S          0x07  /* switch register */
1281*4882a593Smuzhiyun 				 /* values for those registers: */
1282*4882a593Smuzhiyun #define TEA6320_S_SA       0x07  /* stereo A input */
1283*4882a593Smuzhiyun #define TEA6320_S_SB       0x06  /* stereo B */
1284*4882a593Smuzhiyun #define TEA6320_S_SC       0x05  /* stereo C */
1285*4882a593Smuzhiyun #define TEA6320_S_SD       0x04  /* stereo D */
1286*4882a593Smuzhiyun #define TEA6320_S_GMU      0x80  /* general mute */
1287*4882a593Smuzhiyun 
1288*4882a593Smuzhiyun #define TEA6420_S_SA       0x00  /* stereo A input */
1289*4882a593Smuzhiyun #define TEA6420_S_SB       0x01  /* stereo B */
1290*4882a593Smuzhiyun #define TEA6420_S_SC       0x02  /* stereo C */
1291*4882a593Smuzhiyun #define TEA6420_S_SD       0x03  /* stereo D */
1292*4882a593Smuzhiyun #define TEA6420_S_SE       0x04  /* stereo E */
1293*4882a593Smuzhiyun #define TEA6420_S_GMU      0x05  /* general mute */
1294*4882a593Smuzhiyun 
tea6300_shift10(int val)1295*4882a593Smuzhiyun static int tea6300_shift10(int val) { return val >> 10; }
tea6300_shift12(int val)1296*4882a593Smuzhiyun static int tea6300_shift12(int val) { return val >> 12; }
1297*4882a593Smuzhiyun 
1298*4882a593Smuzhiyun /* Assumes 16bit input (values 0x3f to 0x0c are unique, values less than */
1299*4882a593Smuzhiyun /* 0x0c mirror those immediately higher) */
tea6320_volume(int val)1300*4882a593Smuzhiyun static int tea6320_volume(int val) { return (val / (65535/(63-12)) + 12) & 0x3f; }
tea6320_shift11(int val)1301*4882a593Smuzhiyun static int tea6320_shift11(int val) { return val >> 11; }
tea6320_initialize(struct CHIPSTATE * chip)1302*4882a593Smuzhiyun static int tea6320_initialize(struct CHIPSTATE * chip)
1303*4882a593Smuzhiyun {
1304*4882a593Smuzhiyun 	chip_write(chip, TEA6320_FFR, 0x3f);
1305*4882a593Smuzhiyun 	chip_write(chip, TEA6320_FFL, 0x3f);
1306*4882a593Smuzhiyun 	chip_write(chip, TEA6320_FRR, 0x3f);
1307*4882a593Smuzhiyun 	chip_write(chip, TEA6320_FRL, 0x3f);
1308*4882a593Smuzhiyun 
1309*4882a593Smuzhiyun 	return 0;
1310*4882a593Smuzhiyun }
1311*4882a593Smuzhiyun 
1312*4882a593Smuzhiyun 
1313*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
1314*4882a593Smuzhiyun /* audio chip descriptions - defines+functions for tda8425                */
1315*4882a593Smuzhiyun 
1316*4882a593Smuzhiyun #define TDA8425_VL         0x00  /* volume left */
1317*4882a593Smuzhiyun #define TDA8425_VR         0x01  /* volume right */
1318*4882a593Smuzhiyun #define TDA8425_BA         0x02  /* bass */
1319*4882a593Smuzhiyun #define TDA8425_TR         0x03  /* treble */
1320*4882a593Smuzhiyun #define TDA8425_S1         0x08  /* switch functions */
1321*4882a593Smuzhiyun 				 /* values for those registers: */
1322*4882a593Smuzhiyun #define TDA8425_S1_OFF     0xEE  /* audio off (mute on) */
1323*4882a593Smuzhiyun #define TDA8425_S1_CH1     0xCE  /* audio channel 1 (mute off) - "linear stereo" mode */
1324*4882a593Smuzhiyun #define TDA8425_S1_CH2     0xCF  /* audio channel 2 (mute off) - "linear stereo" mode */
1325*4882a593Smuzhiyun #define TDA8425_S1_MU      0x20  /* mute bit */
1326*4882a593Smuzhiyun #define TDA8425_S1_STEREO  0x18  /* stereo bits */
1327*4882a593Smuzhiyun #define TDA8425_S1_STEREO_SPATIAL 0x18 /* spatial stereo */
1328*4882a593Smuzhiyun #define TDA8425_S1_STEREO_LINEAR  0x08 /* linear stereo */
1329*4882a593Smuzhiyun #define TDA8425_S1_STEREO_PSEUDO  0x10 /* pseudo stereo */
1330*4882a593Smuzhiyun #define TDA8425_S1_STEREO_MONO    0x00 /* forced mono */
1331*4882a593Smuzhiyun #define TDA8425_S1_ML      0x06        /* language selector */
1332*4882a593Smuzhiyun #define TDA8425_S1_ML_SOUND_A 0x02     /* sound a */
1333*4882a593Smuzhiyun #define TDA8425_S1_ML_SOUND_B 0x04     /* sound b */
1334*4882a593Smuzhiyun #define TDA8425_S1_ML_STEREO  0x06     /* stereo */
1335*4882a593Smuzhiyun #define TDA8425_S1_IS      0x01        /* channel selector */
1336*4882a593Smuzhiyun 
1337*4882a593Smuzhiyun 
tda8425_shift10(int val)1338*4882a593Smuzhiyun static int tda8425_shift10(int val) { return (val >> 10) | 0xc0; }
tda8425_shift12(int val)1339*4882a593Smuzhiyun static int tda8425_shift12(int val) { return (val >> 12) | 0xf0; }
1340*4882a593Smuzhiyun 
tda8425_setaudmode(struct CHIPSTATE * chip,int mode)1341*4882a593Smuzhiyun static void tda8425_setaudmode(struct CHIPSTATE *chip, int mode)
1342*4882a593Smuzhiyun {
1343*4882a593Smuzhiyun 	int s1 = chip->shadow.bytes[TDA8425_S1+1] & 0xe1;
1344*4882a593Smuzhiyun 
1345*4882a593Smuzhiyun 	switch (mode) {
1346*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_LANG1:
1347*4882a593Smuzhiyun 		s1 |= TDA8425_S1_ML_SOUND_A;
1348*4882a593Smuzhiyun 		s1 |= TDA8425_S1_STEREO_PSEUDO;
1349*4882a593Smuzhiyun 		break;
1350*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_LANG2:
1351*4882a593Smuzhiyun 		s1 |= TDA8425_S1_ML_SOUND_B;
1352*4882a593Smuzhiyun 		s1 |= TDA8425_S1_STEREO_PSEUDO;
1353*4882a593Smuzhiyun 		break;
1354*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_LANG1_LANG2:
1355*4882a593Smuzhiyun 		s1 |= TDA8425_S1_ML_STEREO;
1356*4882a593Smuzhiyun 		s1 |= TDA8425_S1_STEREO_LINEAR;
1357*4882a593Smuzhiyun 		break;
1358*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_MONO:
1359*4882a593Smuzhiyun 		s1 |= TDA8425_S1_ML_STEREO;
1360*4882a593Smuzhiyun 		s1 |= TDA8425_S1_STEREO_MONO;
1361*4882a593Smuzhiyun 		break;
1362*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_STEREO:
1363*4882a593Smuzhiyun 		s1 |= TDA8425_S1_ML_STEREO;
1364*4882a593Smuzhiyun 		s1 |= TDA8425_S1_STEREO_SPATIAL;
1365*4882a593Smuzhiyun 		break;
1366*4882a593Smuzhiyun 	default:
1367*4882a593Smuzhiyun 		return;
1368*4882a593Smuzhiyun 	}
1369*4882a593Smuzhiyun 	chip_write(chip,TDA8425_S1,s1);
1370*4882a593Smuzhiyun }
1371*4882a593Smuzhiyun 
1372*4882a593Smuzhiyun 
1373*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
1374*4882a593Smuzhiyun /* audio chip descriptions - defines+functions for pic16c54 (PV951)       */
1375*4882a593Smuzhiyun 
1376*4882a593Smuzhiyun /* the registers of 16C54, I2C sub address. */
1377*4882a593Smuzhiyun #define PIC16C54_REG_KEY_CODE     0x01	       /* Not use. */
1378*4882a593Smuzhiyun #define PIC16C54_REG_MISC         0x02
1379*4882a593Smuzhiyun 
1380*4882a593Smuzhiyun /* bit definition of the RESET register, I2C data. */
1381*4882a593Smuzhiyun #define PIC16C54_MISC_RESET_REMOTE_CTL 0x01 /* bit 0, Reset to receive the key */
1382*4882a593Smuzhiyun 					    /*        code of remote controller */
1383*4882a593Smuzhiyun #define PIC16C54_MISC_MTS_MAIN         0x02 /* bit 1 */
1384*4882a593Smuzhiyun #define PIC16C54_MISC_MTS_SAP          0x04 /* bit 2 */
1385*4882a593Smuzhiyun #define PIC16C54_MISC_MTS_BOTH         0x08 /* bit 3 */
1386*4882a593Smuzhiyun #define PIC16C54_MISC_SND_MUTE         0x10 /* bit 4, Mute Audio(Line-in and Tuner) */
1387*4882a593Smuzhiyun #define PIC16C54_MISC_SND_NOTMUTE      0x20 /* bit 5 */
1388*4882a593Smuzhiyun #define PIC16C54_MISC_SWITCH_TUNER     0x40 /* bit 6	, Switch to Line-in */
1389*4882a593Smuzhiyun #define PIC16C54_MISC_SWITCH_LINE      0x80 /* bit 7	, Switch to Tuner */
1390*4882a593Smuzhiyun 
1391*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
1392*4882a593Smuzhiyun /* audio chip descriptions - defines+functions for TA8874Z                */
1393*4882a593Smuzhiyun 
1394*4882a593Smuzhiyun /* write 1st byte */
1395*4882a593Smuzhiyun #define TA8874Z_LED_STE	0x80
1396*4882a593Smuzhiyun #define TA8874Z_LED_BIL	0x40
1397*4882a593Smuzhiyun #define TA8874Z_LED_EXT	0x20
1398*4882a593Smuzhiyun #define TA8874Z_MONO_SET	0x10
1399*4882a593Smuzhiyun #define TA8874Z_MUTE	0x08
1400*4882a593Smuzhiyun #define TA8874Z_F_MONO	0x04
1401*4882a593Smuzhiyun #define TA8874Z_MODE_SUB	0x02
1402*4882a593Smuzhiyun #define TA8874Z_MODE_MAIN	0x01
1403*4882a593Smuzhiyun 
1404*4882a593Smuzhiyun /* write 2nd byte */
1405*4882a593Smuzhiyun /*#define TA8874Z_TI	0x80  */ /* test mode */
1406*4882a593Smuzhiyun #define TA8874Z_SEPARATION	0x3f
1407*4882a593Smuzhiyun #define TA8874Z_SEPARATION_DEFAULT	0x10
1408*4882a593Smuzhiyun 
1409*4882a593Smuzhiyun /* read */
1410*4882a593Smuzhiyun #define TA8874Z_B1	0x80
1411*4882a593Smuzhiyun #define TA8874Z_B0	0x40
1412*4882a593Smuzhiyun #define TA8874Z_CHAG_FLAG	0x20
1413*4882a593Smuzhiyun 
1414*4882a593Smuzhiyun /*
1415*4882a593Smuzhiyun  *        B1 B0
1416*4882a593Smuzhiyun  * mono    L  H
1417*4882a593Smuzhiyun  * stereo  L  L
1418*4882a593Smuzhiyun  * BIL     H  L
1419*4882a593Smuzhiyun  */
ta8874z_getrxsubchans(struct CHIPSTATE * chip)1420*4882a593Smuzhiyun static int ta8874z_getrxsubchans(struct CHIPSTATE *chip)
1421*4882a593Smuzhiyun {
1422*4882a593Smuzhiyun 	int val, mode;
1423*4882a593Smuzhiyun 
1424*4882a593Smuzhiyun 	mode = V4L2_TUNER_SUB_MONO;
1425*4882a593Smuzhiyun 
1426*4882a593Smuzhiyun 	val = chip_read(chip);
1427*4882a593Smuzhiyun 	if (val < 0)
1428*4882a593Smuzhiyun 		return mode;
1429*4882a593Smuzhiyun 
1430*4882a593Smuzhiyun 	if (val & TA8874Z_B1){
1431*4882a593Smuzhiyun 		mode |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
1432*4882a593Smuzhiyun 	}else if (!(val & TA8874Z_B0)){
1433*4882a593Smuzhiyun 		mode = V4L2_TUNER_SUB_STEREO;
1434*4882a593Smuzhiyun 	}
1435*4882a593Smuzhiyun 	/* v4l2_dbg(1, debug, &chip->sd,
1436*4882a593Smuzhiyun 		 "ta8874z_getrxsubchans(): raw chip read: 0x%02x, return: 0x%02x\n",
1437*4882a593Smuzhiyun 		 val, mode); */
1438*4882a593Smuzhiyun 	return mode;
1439*4882a593Smuzhiyun }
1440*4882a593Smuzhiyun 
1441*4882a593Smuzhiyun static audiocmd ta8874z_stereo = { 2, {0, TA8874Z_SEPARATION_DEFAULT}};
1442*4882a593Smuzhiyun static audiocmd ta8874z_mono = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}};
1443*4882a593Smuzhiyun static audiocmd ta8874z_main = {2, { 0, TA8874Z_SEPARATION_DEFAULT}};
1444*4882a593Smuzhiyun static audiocmd ta8874z_sub = {2, { TA8874Z_MODE_SUB, TA8874Z_SEPARATION_DEFAULT}};
1445*4882a593Smuzhiyun static audiocmd ta8874z_both = {2, { TA8874Z_MODE_MAIN | TA8874Z_MODE_SUB, TA8874Z_SEPARATION_DEFAULT}};
1446*4882a593Smuzhiyun 
ta8874z_setaudmode(struct CHIPSTATE * chip,int mode)1447*4882a593Smuzhiyun static void ta8874z_setaudmode(struct CHIPSTATE *chip, int mode)
1448*4882a593Smuzhiyun {
1449*4882a593Smuzhiyun 	struct v4l2_subdev *sd = &chip->sd;
1450*4882a593Smuzhiyun 	int update = 1;
1451*4882a593Smuzhiyun 	audiocmd *t = NULL;
1452*4882a593Smuzhiyun 
1453*4882a593Smuzhiyun 	v4l2_dbg(1, debug, sd, "ta8874z_setaudmode(): mode: 0x%02x\n", mode);
1454*4882a593Smuzhiyun 
1455*4882a593Smuzhiyun 	switch(mode){
1456*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_MONO:
1457*4882a593Smuzhiyun 		t = &ta8874z_mono;
1458*4882a593Smuzhiyun 		break;
1459*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_STEREO:
1460*4882a593Smuzhiyun 		t = &ta8874z_stereo;
1461*4882a593Smuzhiyun 		break;
1462*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_LANG1:
1463*4882a593Smuzhiyun 		t = &ta8874z_main;
1464*4882a593Smuzhiyun 		break;
1465*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_LANG2:
1466*4882a593Smuzhiyun 		t = &ta8874z_sub;
1467*4882a593Smuzhiyun 		break;
1468*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_LANG1_LANG2:
1469*4882a593Smuzhiyun 		t = &ta8874z_both;
1470*4882a593Smuzhiyun 		break;
1471*4882a593Smuzhiyun 	default:
1472*4882a593Smuzhiyun 		update = 0;
1473*4882a593Smuzhiyun 	}
1474*4882a593Smuzhiyun 
1475*4882a593Smuzhiyun 	if(update)
1476*4882a593Smuzhiyun 		chip_cmd(chip, "TA8874Z", t);
1477*4882a593Smuzhiyun }
1478*4882a593Smuzhiyun 
ta8874z_checkit(struct CHIPSTATE * chip)1479*4882a593Smuzhiyun static int ta8874z_checkit(struct CHIPSTATE *chip)
1480*4882a593Smuzhiyun {
1481*4882a593Smuzhiyun 	int rc;
1482*4882a593Smuzhiyun 
1483*4882a593Smuzhiyun 	rc = chip_read(chip);
1484*4882a593Smuzhiyun 	if (rc < 0)
1485*4882a593Smuzhiyun 		return rc;
1486*4882a593Smuzhiyun 
1487*4882a593Smuzhiyun 	return ((rc & 0x1f) == 0x1f) ? 1 : 0;
1488*4882a593Smuzhiyun }
1489*4882a593Smuzhiyun 
1490*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
1491*4882a593Smuzhiyun /* audio chip descriptions - struct CHIPDESC                              */
1492*4882a593Smuzhiyun 
1493*4882a593Smuzhiyun /* insmod options to enable/disable individual audio chips */
1494*4882a593Smuzhiyun static int tda8425  = 1;
1495*4882a593Smuzhiyun static int tda9840  = 1;
1496*4882a593Smuzhiyun static int tda9850  = 1;
1497*4882a593Smuzhiyun static int tda9855  = 1;
1498*4882a593Smuzhiyun static int tda9873  = 1;
1499*4882a593Smuzhiyun static int tda9874a = 1;
1500*4882a593Smuzhiyun static int tda9875  = 1;
1501*4882a593Smuzhiyun static int tea6300;	/* default 0 - address clash with msp34xx */
1502*4882a593Smuzhiyun static int tea6320;	/* default 0 - address clash with msp34xx */
1503*4882a593Smuzhiyun static int tea6420  = 1;
1504*4882a593Smuzhiyun static int pic16c54 = 1;
1505*4882a593Smuzhiyun static int ta8874z;	/* default 0 - address clash with tda9840 */
1506*4882a593Smuzhiyun 
1507*4882a593Smuzhiyun module_param(tda8425, int, 0444);
1508*4882a593Smuzhiyun module_param(tda9840, int, 0444);
1509*4882a593Smuzhiyun module_param(tda9850, int, 0444);
1510*4882a593Smuzhiyun module_param(tda9855, int, 0444);
1511*4882a593Smuzhiyun module_param(tda9873, int, 0444);
1512*4882a593Smuzhiyun module_param(tda9874a, int, 0444);
1513*4882a593Smuzhiyun module_param(tda9875, int, 0444);
1514*4882a593Smuzhiyun module_param(tea6300, int, 0444);
1515*4882a593Smuzhiyun module_param(tea6320, int, 0444);
1516*4882a593Smuzhiyun module_param(tea6420, int, 0444);
1517*4882a593Smuzhiyun module_param(pic16c54, int, 0444);
1518*4882a593Smuzhiyun module_param(ta8874z, int, 0444);
1519*4882a593Smuzhiyun 
1520*4882a593Smuzhiyun static struct CHIPDESC chiplist[] = {
1521*4882a593Smuzhiyun 	{
1522*4882a593Smuzhiyun 		.name       = "tda9840",
1523*4882a593Smuzhiyun 		.insmodopt  = &tda9840,
1524*4882a593Smuzhiyun 		.addr_lo    = I2C_ADDR_TDA9840 >> 1,
1525*4882a593Smuzhiyun 		.addr_hi    = I2C_ADDR_TDA9840 >> 1,
1526*4882a593Smuzhiyun 		.registers  = 5,
1527*4882a593Smuzhiyun 		.flags      = CHIP_NEED_CHECKMODE,
1528*4882a593Smuzhiyun 
1529*4882a593Smuzhiyun 		/* callbacks */
1530*4882a593Smuzhiyun 		.checkit    = tda9840_checkit,
1531*4882a593Smuzhiyun 		.getrxsubchans = tda9840_getrxsubchans,
1532*4882a593Smuzhiyun 		.setaudmode = tda9840_setaudmode,
1533*4882a593Smuzhiyun 
1534*4882a593Smuzhiyun 		.init       = { 2, { TDA9840_TEST, TDA9840_TEST_INT1SN
1535*4882a593Smuzhiyun 				/* ,TDA9840_SW, TDA9840_MONO */} }
1536*4882a593Smuzhiyun 	},
1537*4882a593Smuzhiyun 	{
1538*4882a593Smuzhiyun 		.name       = "tda9873h",
1539*4882a593Smuzhiyun 		.insmodopt  = &tda9873,
1540*4882a593Smuzhiyun 		.addr_lo    = I2C_ADDR_TDA985x_L >> 1,
1541*4882a593Smuzhiyun 		.addr_hi    = I2C_ADDR_TDA985x_H >> 1,
1542*4882a593Smuzhiyun 		.registers  = 3,
1543*4882a593Smuzhiyun 		.flags      = CHIP_HAS_INPUTSEL | CHIP_NEED_CHECKMODE,
1544*4882a593Smuzhiyun 
1545*4882a593Smuzhiyun 		/* callbacks */
1546*4882a593Smuzhiyun 		.checkit    = tda9873_checkit,
1547*4882a593Smuzhiyun 		.getrxsubchans = tda9873_getrxsubchans,
1548*4882a593Smuzhiyun 		.setaudmode = tda9873_setaudmode,
1549*4882a593Smuzhiyun 
1550*4882a593Smuzhiyun 		.init       = { 4, { TDA9873_SW, 0xa4, 0x06, 0x03 } },
1551*4882a593Smuzhiyun 		.inputreg   = TDA9873_SW,
1552*4882a593Smuzhiyun 		.inputmute  = TDA9873_MUTE | TDA9873_AUTOMUTE,
1553*4882a593Smuzhiyun 		.inputmap   = {0xa0, 0xa2, 0xa0, 0xa0},
1554*4882a593Smuzhiyun 		.inputmask  = TDA9873_INP_MASK|TDA9873_MUTE|TDA9873_AUTOMUTE,
1555*4882a593Smuzhiyun 
1556*4882a593Smuzhiyun 	},
1557*4882a593Smuzhiyun 	{
1558*4882a593Smuzhiyun 		.name       = "tda9874h/a",
1559*4882a593Smuzhiyun 		.insmodopt  = &tda9874a,
1560*4882a593Smuzhiyun 		.addr_lo    = I2C_ADDR_TDA9874 >> 1,
1561*4882a593Smuzhiyun 		.addr_hi    = I2C_ADDR_TDA9874 >> 1,
1562*4882a593Smuzhiyun 		.flags      = CHIP_NEED_CHECKMODE,
1563*4882a593Smuzhiyun 
1564*4882a593Smuzhiyun 		/* callbacks */
1565*4882a593Smuzhiyun 		.initialize = tda9874a_initialize,
1566*4882a593Smuzhiyun 		.checkit    = tda9874a_checkit,
1567*4882a593Smuzhiyun 		.getrxsubchans = tda9874a_getrxsubchans,
1568*4882a593Smuzhiyun 		.setaudmode = tda9874a_setaudmode,
1569*4882a593Smuzhiyun 	},
1570*4882a593Smuzhiyun 	{
1571*4882a593Smuzhiyun 		.name       = "tda9875",
1572*4882a593Smuzhiyun 		.insmodopt  = &tda9875,
1573*4882a593Smuzhiyun 		.addr_lo    = I2C_ADDR_TDA9875 >> 1,
1574*4882a593Smuzhiyun 		.addr_hi    = I2C_ADDR_TDA9875 >> 1,
1575*4882a593Smuzhiyun 		.flags      = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE,
1576*4882a593Smuzhiyun 
1577*4882a593Smuzhiyun 		/* callbacks */
1578*4882a593Smuzhiyun 		.initialize = tda9875_initialize,
1579*4882a593Smuzhiyun 		.checkit    = tda9875_checkit,
1580*4882a593Smuzhiyun 		.volfunc    = tda9875_volume,
1581*4882a593Smuzhiyun 		.bassfunc   = tda9875_bass,
1582*4882a593Smuzhiyun 		.treblefunc = tda9875_treble,
1583*4882a593Smuzhiyun 		.leftreg    = TDA9875_MVL,
1584*4882a593Smuzhiyun 		.rightreg   = TDA9875_MVR,
1585*4882a593Smuzhiyun 		.bassreg    = TDA9875_MBA,
1586*4882a593Smuzhiyun 		.treblereg  = TDA9875_MTR,
1587*4882a593Smuzhiyun 		.volinit    = 58880,
1588*4882a593Smuzhiyun 	},
1589*4882a593Smuzhiyun 	{
1590*4882a593Smuzhiyun 		.name       = "tda9850",
1591*4882a593Smuzhiyun 		.insmodopt  = &tda9850,
1592*4882a593Smuzhiyun 		.addr_lo    = I2C_ADDR_TDA985x_L >> 1,
1593*4882a593Smuzhiyun 		.addr_hi    = I2C_ADDR_TDA985x_H >> 1,
1594*4882a593Smuzhiyun 		.registers  = 11,
1595*4882a593Smuzhiyun 
1596*4882a593Smuzhiyun 		.getrxsubchans = tda985x_getrxsubchans,
1597*4882a593Smuzhiyun 		.setaudmode = tda985x_setaudmode,
1598*4882a593Smuzhiyun 
1599*4882a593Smuzhiyun 		.init       = { 8, { TDA9850_C4, 0x08, 0x08, TDA985x_STEREO, 0x07, 0x10, 0x10, 0x03 } }
1600*4882a593Smuzhiyun 	},
1601*4882a593Smuzhiyun 	{
1602*4882a593Smuzhiyun 		.name       = "tda9855",
1603*4882a593Smuzhiyun 		.insmodopt  = &tda9855,
1604*4882a593Smuzhiyun 		.addr_lo    = I2C_ADDR_TDA985x_L >> 1,
1605*4882a593Smuzhiyun 		.addr_hi    = I2C_ADDR_TDA985x_H >> 1,
1606*4882a593Smuzhiyun 		.registers  = 11,
1607*4882a593Smuzhiyun 		.flags      = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE,
1608*4882a593Smuzhiyun 
1609*4882a593Smuzhiyun 		.leftreg    = TDA9855_VL,
1610*4882a593Smuzhiyun 		.rightreg   = TDA9855_VR,
1611*4882a593Smuzhiyun 		.bassreg    = TDA9855_BA,
1612*4882a593Smuzhiyun 		.treblereg  = TDA9855_TR,
1613*4882a593Smuzhiyun 
1614*4882a593Smuzhiyun 		/* callbacks */
1615*4882a593Smuzhiyun 		.volfunc    = tda9855_volume,
1616*4882a593Smuzhiyun 		.bassfunc   = tda9855_bass,
1617*4882a593Smuzhiyun 		.treblefunc = tda9855_treble,
1618*4882a593Smuzhiyun 		.getrxsubchans = tda985x_getrxsubchans,
1619*4882a593Smuzhiyun 		.setaudmode = tda985x_setaudmode,
1620*4882a593Smuzhiyun 
1621*4882a593Smuzhiyun 		.init       = { 12, { 0, 0x6f, 0x6f, 0x0e, 0x07<<1, 0x8<<2,
1622*4882a593Smuzhiyun 				    TDA9855_MUTE | TDA9855_AVL | TDA9855_LOUD | TDA9855_INT,
1623*4882a593Smuzhiyun 				    TDA985x_STEREO | TDA9855_LINEAR | TDA9855_TZCM | TDA9855_VZCM,
1624*4882a593Smuzhiyun 				    0x07, 0x10, 0x10, 0x03 }}
1625*4882a593Smuzhiyun 	},
1626*4882a593Smuzhiyun 	{
1627*4882a593Smuzhiyun 		.name       = "tea6300",
1628*4882a593Smuzhiyun 		.insmodopt  = &tea6300,
1629*4882a593Smuzhiyun 		.addr_lo    = I2C_ADDR_TEA6300 >> 1,
1630*4882a593Smuzhiyun 		.addr_hi    = I2C_ADDR_TEA6300 >> 1,
1631*4882a593Smuzhiyun 		.registers  = 6,
1632*4882a593Smuzhiyun 		.flags      = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE | CHIP_HAS_INPUTSEL,
1633*4882a593Smuzhiyun 
1634*4882a593Smuzhiyun 		.leftreg    = TEA6300_VR,
1635*4882a593Smuzhiyun 		.rightreg   = TEA6300_VL,
1636*4882a593Smuzhiyun 		.bassreg    = TEA6300_BA,
1637*4882a593Smuzhiyun 		.treblereg  = TEA6300_TR,
1638*4882a593Smuzhiyun 
1639*4882a593Smuzhiyun 		/* callbacks */
1640*4882a593Smuzhiyun 		.volfunc    = tea6300_shift10,
1641*4882a593Smuzhiyun 		.bassfunc   = tea6300_shift12,
1642*4882a593Smuzhiyun 		.treblefunc = tea6300_shift12,
1643*4882a593Smuzhiyun 
1644*4882a593Smuzhiyun 		.inputreg   = TEA6300_S,
1645*4882a593Smuzhiyun 		.inputmap   = { TEA6300_S_SA, TEA6300_S_SB, TEA6300_S_SC },
1646*4882a593Smuzhiyun 		.inputmute  = TEA6300_S_GMU,
1647*4882a593Smuzhiyun 	},
1648*4882a593Smuzhiyun 	{
1649*4882a593Smuzhiyun 		.name       = "tea6320",
1650*4882a593Smuzhiyun 		.insmodopt  = &tea6320,
1651*4882a593Smuzhiyun 		.addr_lo    = I2C_ADDR_TEA6300 >> 1,
1652*4882a593Smuzhiyun 		.addr_hi    = I2C_ADDR_TEA6300 >> 1,
1653*4882a593Smuzhiyun 		.registers  = 8,
1654*4882a593Smuzhiyun 		.flags      = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE | CHIP_HAS_INPUTSEL,
1655*4882a593Smuzhiyun 
1656*4882a593Smuzhiyun 		.leftreg    = TEA6320_V,
1657*4882a593Smuzhiyun 		.rightreg   = TEA6320_V,
1658*4882a593Smuzhiyun 		.bassreg    = TEA6320_BA,
1659*4882a593Smuzhiyun 		.treblereg  = TEA6320_TR,
1660*4882a593Smuzhiyun 
1661*4882a593Smuzhiyun 		/* callbacks */
1662*4882a593Smuzhiyun 		.initialize = tea6320_initialize,
1663*4882a593Smuzhiyun 		.volfunc    = tea6320_volume,
1664*4882a593Smuzhiyun 		.bassfunc   = tea6320_shift11,
1665*4882a593Smuzhiyun 		.treblefunc = tea6320_shift11,
1666*4882a593Smuzhiyun 
1667*4882a593Smuzhiyun 		.inputreg   = TEA6320_S,
1668*4882a593Smuzhiyun 		.inputmap   = { TEA6320_S_SA, TEA6420_S_SB, TEA6300_S_SC, TEA6320_S_SD },
1669*4882a593Smuzhiyun 		.inputmute  = TEA6300_S_GMU,
1670*4882a593Smuzhiyun 	},
1671*4882a593Smuzhiyun 	{
1672*4882a593Smuzhiyun 		.name       = "tea6420",
1673*4882a593Smuzhiyun 		.insmodopt  = &tea6420,
1674*4882a593Smuzhiyun 		.addr_lo    = I2C_ADDR_TEA6420 >> 1,
1675*4882a593Smuzhiyun 		.addr_hi    = I2C_ADDR_TEA6420 >> 1,
1676*4882a593Smuzhiyun 		.registers  = 1,
1677*4882a593Smuzhiyun 		.flags      = CHIP_HAS_INPUTSEL,
1678*4882a593Smuzhiyun 
1679*4882a593Smuzhiyun 		.inputreg   = -1,
1680*4882a593Smuzhiyun 		.inputmap   = { TEA6420_S_SA, TEA6420_S_SB, TEA6420_S_SC },
1681*4882a593Smuzhiyun 		.inputmute  = TEA6420_S_GMU,
1682*4882a593Smuzhiyun 		.inputmask  = 0x07,
1683*4882a593Smuzhiyun 	},
1684*4882a593Smuzhiyun 	{
1685*4882a593Smuzhiyun 		.name       = "tda8425",
1686*4882a593Smuzhiyun 		.insmodopt  = &tda8425,
1687*4882a593Smuzhiyun 		.addr_lo    = I2C_ADDR_TDA8425 >> 1,
1688*4882a593Smuzhiyun 		.addr_hi    = I2C_ADDR_TDA8425 >> 1,
1689*4882a593Smuzhiyun 		.registers  = 9,
1690*4882a593Smuzhiyun 		.flags      = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE | CHIP_HAS_INPUTSEL,
1691*4882a593Smuzhiyun 
1692*4882a593Smuzhiyun 		.leftreg    = TDA8425_VL,
1693*4882a593Smuzhiyun 		.rightreg   = TDA8425_VR,
1694*4882a593Smuzhiyun 		.bassreg    = TDA8425_BA,
1695*4882a593Smuzhiyun 		.treblereg  = TDA8425_TR,
1696*4882a593Smuzhiyun 
1697*4882a593Smuzhiyun 		/* callbacks */
1698*4882a593Smuzhiyun 		.volfunc    = tda8425_shift10,
1699*4882a593Smuzhiyun 		.bassfunc   = tda8425_shift12,
1700*4882a593Smuzhiyun 		.treblefunc = tda8425_shift12,
1701*4882a593Smuzhiyun 		.setaudmode = tda8425_setaudmode,
1702*4882a593Smuzhiyun 
1703*4882a593Smuzhiyun 		.inputreg   = TDA8425_S1,
1704*4882a593Smuzhiyun 		.inputmap   = { TDA8425_S1_CH1, TDA8425_S1_CH1, TDA8425_S1_CH1 },
1705*4882a593Smuzhiyun 		.inputmute  = TDA8425_S1_OFF,
1706*4882a593Smuzhiyun 
1707*4882a593Smuzhiyun 	},
1708*4882a593Smuzhiyun 	{
1709*4882a593Smuzhiyun 		.name       = "pic16c54 (PV951)",
1710*4882a593Smuzhiyun 		.insmodopt  = &pic16c54,
1711*4882a593Smuzhiyun 		.addr_lo    = I2C_ADDR_PIC16C54 >> 1,
1712*4882a593Smuzhiyun 		.addr_hi    = I2C_ADDR_PIC16C54>> 1,
1713*4882a593Smuzhiyun 		.registers  = 2,
1714*4882a593Smuzhiyun 		.flags      = CHIP_HAS_INPUTSEL,
1715*4882a593Smuzhiyun 
1716*4882a593Smuzhiyun 		.inputreg   = PIC16C54_REG_MISC,
1717*4882a593Smuzhiyun 		.inputmap   = {PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_TUNER,
1718*4882a593Smuzhiyun 			     PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_LINE,
1719*4882a593Smuzhiyun 			     PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_LINE,
1720*4882a593Smuzhiyun 			     PIC16C54_MISC_SND_MUTE},
1721*4882a593Smuzhiyun 		.inputmute  = PIC16C54_MISC_SND_MUTE,
1722*4882a593Smuzhiyun 	},
1723*4882a593Smuzhiyun 	{
1724*4882a593Smuzhiyun 		.name       = "ta8874z",
1725*4882a593Smuzhiyun 		.checkit    = ta8874z_checkit,
1726*4882a593Smuzhiyun 		.insmodopt  = &ta8874z,
1727*4882a593Smuzhiyun 		.addr_lo    = I2C_ADDR_TDA9840 >> 1,
1728*4882a593Smuzhiyun 		.addr_hi    = I2C_ADDR_TDA9840 >> 1,
1729*4882a593Smuzhiyun 		.registers  = 2,
1730*4882a593Smuzhiyun 
1731*4882a593Smuzhiyun 		/* callbacks */
1732*4882a593Smuzhiyun 		.getrxsubchans = ta8874z_getrxsubchans,
1733*4882a593Smuzhiyun 		.setaudmode = ta8874z_setaudmode,
1734*4882a593Smuzhiyun 
1735*4882a593Smuzhiyun 		.init       = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}},
1736*4882a593Smuzhiyun 	},
1737*4882a593Smuzhiyun 	{ .name = NULL } /* EOF */
1738*4882a593Smuzhiyun };
1739*4882a593Smuzhiyun 
1740*4882a593Smuzhiyun 
1741*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
1742*4882a593Smuzhiyun 
tvaudio_s_ctrl(struct v4l2_ctrl * ctrl)1743*4882a593Smuzhiyun static int tvaudio_s_ctrl(struct v4l2_ctrl *ctrl)
1744*4882a593Smuzhiyun {
1745*4882a593Smuzhiyun 	struct v4l2_subdev *sd = to_sd(ctrl);
1746*4882a593Smuzhiyun 	struct CHIPSTATE *chip = to_state(sd);
1747*4882a593Smuzhiyun 	struct CHIPDESC *desc = chip->desc;
1748*4882a593Smuzhiyun 
1749*4882a593Smuzhiyun 	switch (ctrl->id) {
1750*4882a593Smuzhiyun 	case V4L2_CID_AUDIO_MUTE:
1751*4882a593Smuzhiyun 		chip->muted = ctrl->val;
1752*4882a593Smuzhiyun 		if (chip->muted)
1753*4882a593Smuzhiyun 			chip_write_masked(chip,desc->inputreg,desc->inputmute,desc->inputmask);
1754*4882a593Smuzhiyun 		else
1755*4882a593Smuzhiyun 			chip_write_masked(chip,desc->inputreg,
1756*4882a593Smuzhiyun 					desc->inputmap[chip->input],desc->inputmask);
1757*4882a593Smuzhiyun 		return 0;
1758*4882a593Smuzhiyun 	case V4L2_CID_AUDIO_VOLUME: {
1759*4882a593Smuzhiyun 		u32 volume, balance;
1760*4882a593Smuzhiyun 		u32 left, right;
1761*4882a593Smuzhiyun 
1762*4882a593Smuzhiyun 		volume = chip->volume->val;
1763*4882a593Smuzhiyun 		balance = chip->balance->val;
1764*4882a593Smuzhiyun 		left = (min(65536U - balance, 32768U) * volume) / 32768U;
1765*4882a593Smuzhiyun 		right = (min(balance, 32768U) * volume) / 32768U;
1766*4882a593Smuzhiyun 
1767*4882a593Smuzhiyun 		chip_write(chip, desc->leftreg, desc->volfunc(left));
1768*4882a593Smuzhiyun 		chip_write(chip, desc->rightreg, desc->volfunc(right));
1769*4882a593Smuzhiyun 		return 0;
1770*4882a593Smuzhiyun 	}
1771*4882a593Smuzhiyun 	case V4L2_CID_AUDIO_BASS:
1772*4882a593Smuzhiyun 		chip_write(chip, desc->bassreg, desc->bassfunc(ctrl->val));
1773*4882a593Smuzhiyun 		return 0;
1774*4882a593Smuzhiyun 	case V4L2_CID_AUDIO_TREBLE:
1775*4882a593Smuzhiyun 		chip_write(chip, desc->treblereg, desc->treblefunc(ctrl->val));
1776*4882a593Smuzhiyun 		return 0;
1777*4882a593Smuzhiyun 	}
1778*4882a593Smuzhiyun 	return -EINVAL;
1779*4882a593Smuzhiyun }
1780*4882a593Smuzhiyun 
1781*4882a593Smuzhiyun 
1782*4882a593Smuzhiyun /* ---------------------------------------------------------------------- */
1783*4882a593Smuzhiyun /* video4linux interface                                                  */
1784*4882a593Smuzhiyun 
tvaudio_s_radio(struct v4l2_subdev * sd)1785*4882a593Smuzhiyun static int tvaudio_s_radio(struct v4l2_subdev *sd)
1786*4882a593Smuzhiyun {
1787*4882a593Smuzhiyun 	struct CHIPSTATE *chip = to_state(sd);
1788*4882a593Smuzhiyun 
1789*4882a593Smuzhiyun 	chip->radio = 1;
1790*4882a593Smuzhiyun 	/* del_timer(&chip->wt); */
1791*4882a593Smuzhiyun 	return 0;
1792*4882a593Smuzhiyun }
1793*4882a593Smuzhiyun 
tvaudio_s_routing(struct v4l2_subdev * sd,u32 input,u32 output,u32 config)1794*4882a593Smuzhiyun static int tvaudio_s_routing(struct v4l2_subdev *sd,
1795*4882a593Smuzhiyun 			     u32 input, u32 output, u32 config)
1796*4882a593Smuzhiyun {
1797*4882a593Smuzhiyun 	struct CHIPSTATE *chip = to_state(sd);
1798*4882a593Smuzhiyun 	struct CHIPDESC *desc = chip->desc;
1799*4882a593Smuzhiyun 
1800*4882a593Smuzhiyun 	if (!(desc->flags & CHIP_HAS_INPUTSEL))
1801*4882a593Smuzhiyun 		return 0;
1802*4882a593Smuzhiyun 	if (input >= 4)
1803*4882a593Smuzhiyun 		return -EINVAL;
1804*4882a593Smuzhiyun 	/* There are four inputs: tuner, radio, extern and intern. */
1805*4882a593Smuzhiyun 	chip->input = input;
1806*4882a593Smuzhiyun 	if (chip->muted)
1807*4882a593Smuzhiyun 		return 0;
1808*4882a593Smuzhiyun 	chip_write_masked(chip, desc->inputreg,
1809*4882a593Smuzhiyun 			desc->inputmap[chip->input], desc->inputmask);
1810*4882a593Smuzhiyun 	return 0;
1811*4882a593Smuzhiyun }
1812*4882a593Smuzhiyun 
tvaudio_s_tuner(struct v4l2_subdev * sd,const struct v4l2_tuner * vt)1813*4882a593Smuzhiyun static int tvaudio_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
1814*4882a593Smuzhiyun {
1815*4882a593Smuzhiyun 	struct CHIPSTATE *chip = to_state(sd);
1816*4882a593Smuzhiyun 	struct CHIPDESC *desc = chip->desc;
1817*4882a593Smuzhiyun 
1818*4882a593Smuzhiyun 	if (!desc->setaudmode)
1819*4882a593Smuzhiyun 		return 0;
1820*4882a593Smuzhiyun 	if (chip->radio)
1821*4882a593Smuzhiyun 		return 0;
1822*4882a593Smuzhiyun 
1823*4882a593Smuzhiyun 	switch (vt->audmode) {
1824*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_MONO:
1825*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_STEREO:
1826*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_LANG1:
1827*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_LANG2:
1828*4882a593Smuzhiyun 	case V4L2_TUNER_MODE_LANG1_LANG2:
1829*4882a593Smuzhiyun 		break;
1830*4882a593Smuzhiyun 	default:
1831*4882a593Smuzhiyun 		return -EINVAL;
1832*4882a593Smuzhiyun 	}
1833*4882a593Smuzhiyun 	chip->audmode = vt->audmode;
1834*4882a593Smuzhiyun 
1835*4882a593Smuzhiyun 	if (chip->thread)
1836*4882a593Smuzhiyun 		wake_up_process(chip->thread);
1837*4882a593Smuzhiyun 	else
1838*4882a593Smuzhiyun 		desc->setaudmode(chip, vt->audmode);
1839*4882a593Smuzhiyun 
1840*4882a593Smuzhiyun 	return 0;
1841*4882a593Smuzhiyun }
1842*4882a593Smuzhiyun 
tvaudio_g_tuner(struct v4l2_subdev * sd,struct v4l2_tuner * vt)1843*4882a593Smuzhiyun static int tvaudio_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
1844*4882a593Smuzhiyun {
1845*4882a593Smuzhiyun 	struct CHIPSTATE *chip = to_state(sd);
1846*4882a593Smuzhiyun 	struct CHIPDESC *desc = chip->desc;
1847*4882a593Smuzhiyun 
1848*4882a593Smuzhiyun 	if (!desc->getrxsubchans)
1849*4882a593Smuzhiyun 		return 0;
1850*4882a593Smuzhiyun 	if (chip->radio)
1851*4882a593Smuzhiyun 		return 0;
1852*4882a593Smuzhiyun 
1853*4882a593Smuzhiyun 	vt->audmode = chip->audmode;
1854*4882a593Smuzhiyun 	vt->rxsubchans = desc->getrxsubchans(chip);
1855*4882a593Smuzhiyun 	vt->capability |= V4L2_TUNER_CAP_STEREO |
1856*4882a593Smuzhiyun 		V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
1857*4882a593Smuzhiyun 
1858*4882a593Smuzhiyun 	return 0;
1859*4882a593Smuzhiyun }
1860*4882a593Smuzhiyun 
tvaudio_s_std(struct v4l2_subdev * sd,v4l2_std_id std)1861*4882a593Smuzhiyun static int tvaudio_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1862*4882a593Smuzhiyun {
1863*4882a593Smuzhiyun 	struct CHIPSTATE *chip = to_state(sd);
1864*4882a593Smuzhiyun 
1865*4882a593Smuzhiyun 	chip->radio = 0;
1866*4882a593Smuzhiyun 	return 0;
1867*4882a593Smuzhiyun }
1868*4882a593Smuzhiyun 
tvaudio_s_frequency(struct v4l2_subdev * sd,const struct v4l2_frequency * freq)1869*4882a593Smuzhiyun static int tvaudio_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *freq)
1870*4882a593Smuzhiyun {
1871*4882a593Smuzhiyun 	struct CHIPSTATE *chip = to_state(sd);
1872*4882a593Smuzhiyun 	struct CHIPDESC *desc = chip->desc;
1873*4882a593Smuzhiyun 
1874*4882a593Smuzhiyun 	/* For chips that provide getrxsubchans and setaudmode, and doesn't
1875*4882a593Smuzhiyun 	   automatically follows the stereo carrier, a kthread is
1876*4882a593Smuzhiyun 	   created to set the audio standard. In this case, when then
1877*4882a593Smuzhiyun 	   the video channel is changed, tvaudio starts on MONO mode.
1878*4882a593Smuzhiyun 	   After waiting for 2 seconds, the kernel thread is called,
1879*4882a593Smuzhiyun 	   to follow whatever audio standard is pointed by the
1880*4882a593Smuzhiyun 	   audio carrier.
1881*4882a593Smuzhiyun 	 */
1882*4882a593Smuzhiyun 	if (chip->thread) {
1883*4882a593Smuzhiyun 		desc->setaudmode(chip, V4L2_TUNER_MODE_MONO);
1884*4882a593Smuzhiyun 		chip->prevmode = -1; /* reset previous mode */
1885*4882a593Smuzhiyun 		mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000));
1886*4882a593Smuzhiyun 	}
1887*4882a593Smuzhiyun 	return 0;
1888*4882a593Smuzhiyun }
1889*4882a593Smuzhiyun 
tvaudio_log_status(struct v4l2_subdev * sd)1890*4882a593Smuzhiyun static int tvaudio_log_status(struct v4l2_subdev *sd)
1891*4882a593Smuzhiyun {
1892*4882a593Smuzhiyun 	struct CHIPSTATE *chip = to_state(sd);
1893*4882a593Smuzhiyun 	struct CHIPDESC *desc = chip->desc;
1894*4882a593Smuzhiyun 
1895*4882a593Smuzhiyun 	v4l2_info(sd, "Chip: %s\n", desc->name);
1896*4882a593Smuzhiyun 	v4l2_ctrl_handler_log_status(&chip->hdl, sd->name);
1897*4882a593Smuzhiyun 	return 0;
1898*4882a593Smuzhiyun }
1899*4882a593Smuzhiyun 
1900*4882a593Smuzhiyun /* ----------------------------------------------------------------------- */
1901*4882a593Smuzhiyun 
1902*4882a593Smuzhiyun static const struct v4l2_ctrl_ops tvaudio_ctrl_ops = {
1903*4882a593Smuzhiyun 	.s_ctrl = tvaudio_s_ctrl,
1904*4882a593Smuzhiyun };
1905*4882a593Smuzhiyun 
1906*4882a593Smuzhiyun static const struct v4l2_subdev_core_ops tvaudio_core_ops = {
1907*4882a593Smuzhiyun 	.log_status = tvaudio_log_status,
1908*4882a593Smuzhiyun };
1909*4882a593Smuzhiyun 
1910*4882a593Smuzhiyun static const struct v4l2_subdev_tuner_ops tvaudio_tuner_ops = {
1911*4882a593Smuzhiyun 	.s_radio = tvaudio_s_radio,
1912*4882a593Smuzhiyun 	.s_frequency = tvaudio_s_frequency,
1913*4882a593Smuzhiyun 	.s_tuner = tvaudio_s_tuner,
1914*4882a593Smuzhiyun 	.g_tuner = tvaudio_g_tuner,
1915*4882a593Smuzhiyun };
1916*4882a593Smuzhiyun 
1917*4882a593Smuzhiyun static const struct v4l2_subdev_audio_ops tvaudio_audio_ops = {
1918*4882a593Smuzhiyun 	.s_routing = tvaudio_s_routing,
1919*4882a593Smuzhiyun };
1920*4882a593Smuzhiyun 
1921*4882a593Smuzhiyun static const struct v4l2_subdev_video_ops tvaudio_video_ops = {
1922*4882a593Smuzhiyun 	.s_std = tvaudio_s_std,
1923*4882a593Smuzhiyun };
1924*4882a593Smuzhiyun 
1925*4882a593Smuzhiyun static const struct v4l2_subdev_ops tvaudio_ops = {
1926*4882a593Smuzhiyun 	.core = &tvaudio_core_ops,
1927*4882a593Smuzhiyun 	.tuner = &tvaudio_tuner_ops,
1928*4882a593Smuzhiyun 	.audio = &tvaudio_audio_ops,
1929*4882a593Smuzhiyun 	.video = &tvaudio_video_ops,
1930*4882a593Smuzhiyun };
1931*4882a593Smuzhiyun 
1932*4882a593Smuzhiyun /* ----------------------------------------------------------------------- */
1933*4882a593Smuzhiyun 
1934*4882a593Smuzhiyun 
1935*4882a593Smuzhiyun /* i2c registration                                                       */
1936*4882a593Smuzhiyun 
tvaudio_probe(struct i2c_client * client,const struct i2c_device_id * id)1937*4882a593Smuzhiyun static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id *id)
1938*4882a593Smuzhiyun {
1939*4882a593Smuzhiyun 	struct CHIPSTATE *chip;
1940*4882a593Smuzhiyun 	struct CHIPDESC  *desc;
1941*4882a593Smuzhiyun 	struct v4l2_subdev *sd;
1942*4882a593Smuzhiyun 
1943*4882a593Smuzhiyun 	if (debug) {
1944*4882a593Smuzhiyun 		printk(KERN_INFO "tvaudio: TV audio decoder + audio/video mux driver\n");
1945*4882a593Smuzhiyun 		printk(KERN_INFO "tvaudio: known chips: ");
1946*4882a593Smuzhiyun 		for (desc = chiplist; desc->name != NULL; desc++)
1947*4882a593Smuzhiyun 			printk(KERN_CONT "%s%s",
1948*4882a593Smuzhiyun 			       (desc == chiplist) ? "" : ", ", desc->name);
1949*4882a593Smuzhiyun 		printk(KERN_CONT "\n");
1950*4882a593Smuzhiyun 	}
1951*4882a593Smuzhiyun 
1952*4882a593Smuzhiyun 	chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
1953*4882a593Smuzhiyun 	if (!chip)
1954*4882a593Smuzhiyun 		return -ENOMEM;
1955*4882a593Smuzhiyun 	sd = &chip->sd;
1956*4882a593Smuzhiyun 	v4l2_i2c_subdev_init(sd, client, &tvaudio_ops);
1957*4882a593Smuzhiyun 
1958*4882a593Smuzhiyun 	/* find description for the chip */
1959*4882a593Smuzhiyun 	v4l2_dbg(1, debug, sd, "chip found @ 0x%x\n", client->addr<<1);
1960*4882a593Smuzhiyun 	for (desc = chiplist; desc->name != NULL; desc++) {
1961*4882a593Smuzhiyun 		if (0 == *(desc->insmodopt))
1962*4882a593Smuzhiyun 			continue;
1963*4882a593Smuzhiyun 		if (client->addr < desc->addr_lo ||
1964*4882a593Smuzhiyun 		    client->addr > desc->addr_hi)
1965*4882a593Smuzhiyun 			continue;
1966*4882a593Smuzhiyun 		if (desc->checkit && !desc->checkit(chip))
1967*4882a593Smuzhiyun 			continue;
1968*4882a593Smuzhiyun 		break;
1969*4882a593Smuzhiyun 	}
1970*4882a593Smuzhiyun 	if (desc->name == NULL) {
1971*4882a593Smuzhiyun 		v4l2_dbg(1, debug, sd, "no matching chip description found\n");
1972*4882a593Smuzhiyun 		return -EIO;
1973*4882a593Smuzhiyun 	}
1974*4882a593Smuzhiyun 	v4l2_info(sd, "%s found @ 0x%x (%s)\n", desc->name, client->addr<<1, client->adapter->name);
1975*4882a593Smuzhiyun 	if (desc->flags) {
1976*4882a593Smuzhiyun 		v4l2_dbg(1, debug, sd, "matches:%s%s%s.\n",
1977*4882a593Smuzhiyun 			(desc->flags & CHIP_HAS_VOLUME)     ? " volume"      : "",
1978*4882a593Smuzhiyun 			(desc->flags & CHIP_HAS_BASSTREBLE) ? " bass/treble" : "",
1979*4882a593Smuzhiyun 			(desc->flags & CHIP_HAS_INPUTSEL)   ? " audiomux"    : "");
1980*4882a593Smuzhiyun 	}
1981*4882a593Smuzhiyun 
1982*4882a593Smuzhiyun 	/* fill required data structures */
1983*4882a593Smuzhiyun 	if (!id)
1984*4882a593Smuzhiyun 		strscpy(client->name, desc->name, I2C_NAME_SIZE);
1985*4882a593Smuzhiyun 	chip->desc = desc;
1986*4882a593Smuzhiyun 	chip->shadow.count = desc->registers+1;
1987*4882a593Smuzhiyun 	chip->prevmode = -1;
1988*4882a593Smuzhiyun 	chip->audmode = V4L2_TUNER_MODE_LANG1;
1989*4882a593Smuzhiyun 
1990*4882a593Smuzhiyun 	/* initialization  */
1991*4882a593Smuzhiyun 	if (desc->initialize != NULL)
1992*4882a593Smuzhiyun 		desc->initialize(chip);
1993*4882a593Smuzhiyun 	else
1994*4882a593Smuzhiyun 		chip_cmd(chip, "init", &desc->init);
1995*4882a593Smuzhiyun 
1996*4882a593Smuzhiyun 	v4l2_ctrl_handler_init(&chip->hdl, 5);
1997*4882a593Smuzhiyun 	if (desc->flags & CHIP_HAS_INPUTSEL)
1998*4882a593Smuzhiyun 		v4l2_ctrl_new_std(&chip->hdl, &tvaudio_ctrl_ops,
1999*4882a593Smuzhiyun 			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
2000*4882a593Smuzhiyun 	if (desc->flags & CHIP_HAS_VOLUME) {
2001*4882a593Smuzhiyun 		if (!desc->volfunc) {
2002*4882a593Smuzhiyun 			/* This shouldn't be happen. Warn user, but keep working
2003*4882a593Smuzhiyun 			   without volume controls
2004*4882a593Smuzhiyun 			 */
2005*4882a593Smuzhiyun 			v4l2_info(sd, "volume callback undefined!\n");
2006*4882a593Smuzhiyun 			desc->flags &= ~CHIP_HAS_VOLUME;
2007*4882a593Smuzhiyun 		} else {
2008*4882a593Smuzhiyun 			chip->volume = v4l2_ctrl_new_std(&chip->hdl,
2009*4882a593Smuzhiyun 				&tvaudio_ctrl_ops, V4L2_CID_AUDIO_VOLUME,
2010*4882a593Smuzhiyun 				0, 65535, 65535 / 100,
2011*4882a593Smuzhiyun 				desc->volinit ? desc->volinit : 65535);
2012*4882a593Smuzhiyun 			chip->balance = v4l2_ctrl_new_std(&chip->hdl,
2013*4882a593Smuzhiyun 				&tvaudio_ctrl_ops, V4L2_CID_AUDIO_BALANCE,
2014*4882a593Smuzhiyun 				0, 65535, 65535 / 100, 32768);
2015*4882a593Smuzhiyun 			v4l2_ctrl_cluster(2, &chip->volume);
2016*4882a593Smuzhiyun 		}
2017*4882a593Smuzhiyun 	}
2018*4882a593Smuzhiyun 	if (desc->flags & CHIP_HAS_BASSTREBLE) {
2019*4882a593Smuzhiyun 		if (!desc->bassfunc || !desc->treblefunc) {
2020*4882a593Smuzhiyun 			/* This shouldn't be happen. Warn user, but keep working
2021*4882a593Smuzhiyun 			   without bass/treble controls
2022*4882a593Smuzhiyun 			 */
2023*4882a593Smuzhiyun 			v4l2_info(sd, "bass/treble callbacks undefined!\n");
2024*4882a593Smuzhiyun 			desc->flags &= ~CHIP_HAS_BASSTREBLE;
2025*4882a593Smuzhiyun 		} else {
2026*4882a593Smuzhiyun 			v4l2_ctrl_new_std(&chip->hdl,
2027*4882a593Smuzhiyun 				&tvaudio_ctrl_ops, V4L2_CID_AUDIO_BASS,
2028*4882a593Smuzhiyun 				0, 65535, 65535 / 100,
2029*4882a593Smuzhiyun 				desc->bassinit ? desc->bassinit : 32768);
2030*4882a593Smuzhiyun 			v4l2_ctrl_new_std(&chip->hdl,
2031*4882a593Smuzhiyun 				&tvaudio_ctrl_ops, V4L2_CID_AUDIO_TREBLE,
2032*4882a593Smuzhiyun 				0, 65535, 65535 / 100,
2033*4882a593Smuzhiyun 				desc->trebleinit ? desc->trebleinit : 32768);
2034*4882a593Smuzhiyun 		}
2035*4882a593Smuzhiyun 	}
2036*4882a593Smuzhiyun 
2037*4882a593Smuzhiyun 	sd->ctrl_handler = &chip->hdl;
2038*4882a593Smuzhiyun 	if (chip->hdl.error) {
2039*4882a593Smuzhiyun 		int err = chip->hdl.error;
2040*4882a593Smuzhiyun 
2041*4882a593Smuzhiyun 		v4l2_ctrl_handler_free(&chip->hdl);
2042*4882a593Smuzhiyun 		return err;
2043*4882a593Smuzhiyun 	}
2044*4882a593Smuzhiyun 	/* set controls to the default values */
2045*4882a593Smuzhiyun 	v4l2_ctrl_handler_setup(&chip->hdl);
2046*4882a593Smuzhiyun 
2047*4882a593Smuzhiyun 	chip->thread = NULL;
2048*4882a593Smuzhiyun 	timer_setup(&chip->wt, chip_thread_wake, 0);
2049*4882a593Smuzhiyun 	if (desc->flags & CHIP_NEED_CHECKMODE) {
2050*4882a593Smuzhiyun 		if (!desc->getrxsubchans || !desc->setaudmode) {
2051*4882a593Smuzhiyun 			/* This shouldn't be happen. Warn user, but keep working
2052*4882a593Smuzhiyun 			   without kthread
2053*4882a593Smuzhiyun 			 */
2054*4882a593Smuzhiyun 			v4l2_info(sd, "set/get mode callbacks undefined!\n");
2055*4882a593Smuzhiyun 			return 0;
2056*4882a593Smuzhiyun 		}
2057*4882a593Smuzhiyun 		/* start async thread */
2058*4882a593Smuzhiyun 		chip->thread = kthread_run(chip_thread, chip, "%s",
2059*4882a593Smuzhiyun 					   client->name);
2060*4882a593Smuzhiyun 		if (IS_ERR(chip->thread)) {
2061*4882a593Smuzhiyun 			v4l2_warn(sd, "failed to create kthread\n");
2062*4882a593Smuzhiyun 			chip->thread = NULL;
2063*4882a593Smuzhiyun 		}
2064*4882a593Smuzhiyun 	}
2065*4882a593Smuzhiyun 	return 0;
2066*4882a593Smuzhiyun }
2067*4882a593Smuzhiyun 
tvaudio_remove(struct i2c_client * client)2068*4882a593Smuzhiyun static int tvaudio_remove(struct i2c_client *client)
2069*4882a593Smuzhiyun {
2070*4882a593Smuzhiyun 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
2071*4882a593Smuzhiyun 	struct CHIPSTATE *chip = to_state(sd);
2072*4882a593Smuzhiyun 
2073*4882a593Smuzhiyun 	del_timer_sync(&chip->wt);
2074*4882a593Smuzhiyun 	if (chip->thread) {
2075*4882a593Smuzhiyun 		/* shutdown async thread */
2076*4882a593Smuzhiyun 		kthread_stop(chip->thread);
2077*4882a593Smuzhiyun 		chip->thread = NULL;
2078*4882a593Smuzhiyun 	}
2079*4882a593Smuzhiyun 
2080*4882a593Smuzhiyun 	v4l2_device_unregister_subdev(sd);
2081*4882a593Smuzhiyun 	v4l2_ctrl_handler_free(&chip->hdl);
2082*4882a593Smuzhiyun 	return 0;
2083*4882a593Smuzhiyun }
2084*4882a593Smuzhiyun 
2085*4882a593Smuzhiyun /* This driver supports many devices and the idea is to let the driver
2086*4882a593Smuzhiyun    detect which device is present. So rather than listing all supported
2087*4882a593Smuzhiyun    devices here, we pretend to support a single, fake device type. */
2088*4882a593Smuzhiyun static const struct i2c_device_id tvaudio_id[] = {
2089*4882a593Smuzhiyun 	{ "tvaudio", 0 },
2090*4882a593Smuzhiyun 	{ }
2091*4882a593Smuzhiyun };
2092*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, tvaudio_id);
2093*4882a593Smuzhiyun 
2094*4882a593Smuzhiyun static struct i2c_driver tvaudio_driver = {
2095*4882a593Smuzhiyun 	.driver = {
2096*4882a593Smuzhiyun 		.name	= "tvaudio",
2097*4882a593Smuzhiyun 	},
2098*4882a593Smuzhiyun 	.probe		= tvaudio_probe,
2099*4882a593Smuzhiyun 	.remove		= tvaudio_remove,
2100*4882a593Smuzhiyun 	.id_table	= tvaudio_id,
2101*4882a593Smuzhiyun };
2102*4882a593Smuzhiyun 
2103*4882a593Smuzhiyun module_i2c_driver(tvaudio_driver);
2104