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