Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/penberg...
[linux-2.6] / drivers / media / video / saa717x.c
1 /*
2  * saa717x - Philips SAA717xHL video decoder driver
3  *
4  * Based on the saa7115 driver
5  *
6  * Changes by Ohta Kyuma <alpha292@bremen.or.jp>
7  *    - Apply to SAA717x,NEC uPD64031,uPD64083. (1/31/2004)
8  *
9  * Changes by T.Adachi (tadachi@tadachi-net.com)
10  *    - support audio, video scaler etc, and checked the initialize sequence.
11  *
12  * Cleaned up by Hans Verkuil <hverkuil@xs4all.nl>
13  *
14  * Note: this is a reversed engineered driver based on captures from
15  * the I2C bus under Windows. This chip is very similar to the saa7134,
16  * though. Unfortunately, this driver is currently only working for NTSC.
17  *
18  * This program is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License as published by
20  * the Free Software Foundation; either version 2 of the License, or
21  * (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program; if not, write to the Free Software
30  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31  */
32
33 #include <linux/version.h>
34 #include <linux/module.h>
35 #include <linux/kernel.h>
36 #include <linux/sched.h>
37
38 #include <linux/videodev.h>
39 #include <linux/videodev2.h>
40 #include <linux/i2c.h>
41 #include <media/v4l2-common.h>
42 #include <media/v4l2-i2c-drv.h>
43
44 MODULE_DESCRIPTION("Philips SAA717x audio/video decoder driver");
45 MODULE_AUTHOR("K. Ohta, T. Adachi, Hans Verkuil");
46 MODULE_LICENSE("GPL");
47
48 static int debug;
49 module_param(debug, int, 0644);
50 MODULE_PARM_DESC(debug, "Debug level (0-1)");
51
52 /*
53  * Generic i2c probe
54  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
55  */
56
57 struct saa717x_state {
58         v4l2_std_id std;
59         int input;
60         int enable;
61         int radio;
62         int bright;
63         int contrast;
64         int hue;
65         int sat;
66         int playback;
67         int audio;
68         int tuner_audio_mode;
69         int audio_main_mute;
70         int audio_main_vol_r;
71         int audio_main_vol_l;
72         u16 audio_main_bass;
73         u16 audio_main_treble;
74         u16 audio_main_volume;
75         u16 audio_main_balance;
76         int audio_input;
77 };
78
79 /* ----------------------------------------------------------------------- */
80
81 /* for audio mode */
82 #define TUNER_AUDIO_MONO        0  /* LL */
83 #define TUNER_AUDIO_STEREO      1  /* LR */
84 #define TUNER_AUDIO_LANG1       2  /* LL */
85 #define TUNER_AUDIO_LANG2       3  /* RR */
86
87 #define SAA717X_NTSC_WIDTH      (704)
88 #define SAA717X_NTSC_HEIGHT     (480)
89
90 /* ----------------------------------------------------------------------- */
91
92 static int saa717x_write(struct i2c_client *client, u32 reg, u32 value)
93 {
94         struct i2c_adapter *adap = client->adapter;
95         int fw_addr = reg == 0x454 || (reg >= 0x464 && reg <= 0x478) || reg == 0x480 || reg == 0x488;
96         unsigned char mm1[6];
97         struct i2c_msg msg;
98
99         msg.flags = 0;
100         msg.addr = client->addr;
101         mm1[0] = (reg >> 8) & 0xff;
102         mm1[1] = reg & 0xff;
103
104         if (fw_addr) {
105                 mm1[4] = (value >> 16) & 0xff;
106                 mm1[3] = (value >> 8) & 0xff;
107                 mm1[2] = value & 0xff;
108         } else {
109                 mm1[2] = value & 0xff;
110         }
111         msg.len = fw_addr ? 5 : 3; /* Long Registers have *only* three bytes! */
112         msg.buf = mm1;
113         v4l_dbg(2, debug, client, "wrote:  reg 0x%03x=%08x\n", reg, value);
114         return i2c_transfer(adap, &msg, 1) == 1;
115 }
116
117 static void saa717x_write_regs(struct i2c_client *client, u32 *data)
118 {
119         while (data[0] || data[1]) {
120                 saa717x_write(client, data[0], data[1]);
121                 data += 2;
122         }
123 }
124
125 static u32 saa717x_read(struct i2c_client *client, u32 reg)
126 {
127         struct i2c_adapter *adap = client->adapter;
128         int fw_addr = (reg >= 0x404 && reg <= 0x4b8) || reg == 0x528;
129         unsigned char mm1[2];
130         unsigned char mm2[4] = { 0, 0, 0, 0 };
131         struct i2c_msg msgs[2];
132         u32 value;
133
134         msgs[0].flags = 0;
135         msgs[1].flags = I2C_M_RD;
136         msgs[0].addr = msgs[1].addr = client->addr;
137         mm1[0] = (reg >> 8) & 0xff;
138         mm1[1] = reg & 0xff;
139         msgs[0].len = 2;
140         msgs[0].buf = mm1;
141         msgs[1].len = fw_addr ? 3 : 1; /* Multibyte Registers contains *only* 3 bytes */
142         msgs[1].buf = mm2;
143         i2c_transfer(adap, msgs, 2);
144
145         if (fw_addr)
146                 value = (mm2[2] & 0xff)  | ((mm2[1] & 0xff) >> 8) | ((mm2[0] & 0xff) >> 16);
147         else
148                 value = mm2[0] & 0xff;
149
150         v4l_dbg(2, debug, client, "read:  reg 0x%03x=0x%08x\n", reg, value);
151         return value;
152 }
153
154 /* ----------------------------------------------------------------------- */
155
156 static u32 reg_init_initialize[] =
157 {
158         /* from linux driver */
159         0x101, 0x008, /* Increment delay */
160
161         0x103, 0x000, /* Analog input control 2 */
162         0x104, 0x090, /* Analog input control 3 */
163         0x105, 0x090, /* Analog input control 4 */
164         0x106, 0x0eb, /* Horizontal sync start */
165         0x107, 0x0e0, /* Horizontal sync stop */
166         0x109, 0x055, /* Luminance control */
167
168         0x10f, 0x02a, /* Chroma gain control */
169         0x110, 0x000, /* Chroma control 2 */
170
171         0x114, 0x045, /* analog/ADC */
172
173         0x118, 0x040, /* RAW data gain */
174         0x119, 0x080, /* RAW data offset */
175
176         0x044, 0x000, /* VBI horizontal input window start (L) TASK A */
177         0x045, 0x000, /* VBI horizontal input window start (H) TASK A */
178         0x046, 0x0cf, /* VBI horizontal input window stop (L) TASK A */
179         0x047, 0x002, /* VBI horizontal input window stop (H) TASK A */
180
181         0x049, 0x000, /* VBI vertical input window start (H) TASK A */
182
183         0x04c, 0x0d0, /* VBI horizontal output length (L) TASK A */
184         0x04d, 0x002, /* VBI horizontal output length (H) TASK A */
185
186         0x064, 0x080, /* Lumina brightness TASK A */
187         0x065, 0x040, /* Luminance contrast TASK A */
188         0x066, 0x040, /* Chroma saturation TASK A */
189         /* 067H: Reserved */
190         0x068, 0x000, /* VBI horizontal scaling increment (L) TASK A */
191         0x069, 0x004, /* VBI horizontal scaling increment (H) TASK A */
192         0x06a, 0x000, /* VBI phase offset TASK A */
193
194         0x06e, 0x000, /* Horizontal phase offset Luma TASK A */
195         0x06f, 0x000, /* Horizontal phase offset Chroma TASK A */
196
197         0x072, 0x000, /* Vertical filter mode TASK A */
198
199         0x084, 0x000, /* VBI horizontal input window start (L) TAKS B */
200         0x085, 0x000, /* VBI horizontal input window start (H) TAKS B */
201         0x086, 0x0cf, /* VBI horizontal input window stop (L) TAKS B */
202         0x087, 0x002, /* VBI horizontal input window stop (H) TAKS B */
203
204         0x089, 0x000, /* VBI vertical input window start (H) TAKS B */
205
206         0x08c, 0x0d0, /* VBI horizontal output length (L) TASK B */
207         0x08d, 0x002, /* VBI horizontal output length (H) TASK B */
208
209         0x0a4, 0x080, /* Lumina brightness TASK B */
210         0x0a5, 0x040, /* Luminance contrast TASK B */
211         0x0a6, 0x040, /* Chroma saturation TASK B */
212         /* 0A7H reserved */
213         0x0a8, 0x000, /* VBI horizontal scaling increment (L) TASK B */
214         0x0a9, 0x004, /* VBI horizontal scaling increment (H) TASK B */
215         0x0aa, 0x000, /* VBI phase offset TASK B */
216
217         0x0ae, 0x000, /* Horizontal phase offset Luma TASK B */
218         0x0af, 0x000, /*Horizontal phase offset Chroma TASK B */
219
220         0x0b2, 0x000, /* Vertical filter mode TASK B */
221
222         0x00c, 0x000, /* Start point GREEN path */
223         0x00d, 0x000, /* Start point BLUE path */
224         0x00e, 0x000, /* Start point RED path */
225
226         0x010, 0x010, /* GREEN path gamma curve --- */
227         0x011, 0x020,
228         0x012, 0x030,
229         0x013, 0x040,
230         0x014, 0x050,
231         0x015, 0x060,
232         0x016, 0x070,
233         0x017, 0x080,
234         0x018, 0x090,
235         0x019, 0x0a0,
236         0x01a, 0x0b0,
237         0x01b, 0x0c0,
238         0x01c, 0x0d0,
239         0x01d, 0x0e0,
240         0x01e, 0x0f0,
241         0x01f, 0x0ff, /* --- GREEN path gamma curve */
242
243         0x020, 0x010, /* BLUE path gamma curve --- */
244         0x021, 0x020,
245         0x022, 0x030,
246         0x023, 0x040,
247         0x024, 0x050,
248         0x025, 0x060,
249         0x026, 0x070,
250         0x027, 0x080,
251         0x028, 0x090,
252         0x029, 0x0a0,
253         0x02a, 0x0b0,
254         0x02b, 0x0c0,
255         0x02c, 0x0d0,
256         0x02d, 0x0e0,
257         0x02e, 0x0f0,
258         0x02f, 0x0ff, /* --- BLUE path gamma curve */
259
260         0x030, 0x010, /* RED path gamma curve --- */
261         0x031, 0x020,
262         0x032, 0x030,
263         0x033, 0x040,
264         0x034, 0x050,
265         0x035, 0x060,
266         0x036, 0x070,
267         0x037, 0x080,
268         0x038, 0x090,
269         0x039, 0x0a0,
270         0x03a, 0x0b0,
271         0x03b, 0x0c0,
272         0x03c, 0x0d0,
273         0x03d, 0x0e0,
274         0x03e, 0x0f0,
275         0x03f, 0x0ff, /* --- RED path gamma curve */
276
277         0x109, 0x085, /* Luminance control  */
278
279         /**** from app start ****/
280         0x584, 0x000, /* AGC gain control */
281         0x585, 0x000, /* Program count */
282         0x586, 0x003, /* Status reset */
283         0x588, 0x0ff, /* Number of audio samples (L) */
284         0x589, 0x00f, /* Number of audio samples (M) */
285         0x58a, 0x000, /* Number of audio samples (H) */
286         0x58b, 0x000, /* Audio select */
287         0x58c, 0x010, /* Audio channel assign1 */
288         0x58d, 0x032, /* Audio channel assign2 */
289         0x58e, 0x054, /* Audio channel assign3 */
290         0x58f, 0x023, /* Audio format */
291         0x590, 0x000, /* SIF control */
292
293         0x595, 0x000, /* ?? */
294         0x596, 0x000, /* ?? */
295         0x597, 0x000, /* ?? */
296
297         0x464, 0x00, /* Digital input crossbar1 */
298
299         0x46c, 0xbbbb10, /* Digital output selection1-3 */
300         0x470, 0x101010, /* Digital output selection4-6 */
301
302         0x478, 0x00, /* Sound feature control */
303
304         0x474, 0x18, /* Softmute control */
305
306         0x454, 0x0425b9, /* Sound Easy programming(reset) */
307         0x454, 0x042539, /* Sound Easy programming(reset) */
308
309
310         /**** common setting( of DVD play, including scaler commands) ****/
311         0x042, 0x003, /* Data path configuration for VBI (TASK A) */
312
313         0x082, 0x003, /* Data path configuration for VBI (TASK B) */
314
315         0x108, 0x0f8, /* Sync control */
316         0x2a9, 0x0fd, /* ??? */
317         0x102, 0x089, /* select video input "mode 9" */
318         0x111, 0x000, /* Mode/delay control */
319
320         0x10e, 0x00a, /* Chroma control 1 */
321
322         0x594, 0x002, /* SIF, analog I/O select */
323
324         0x454, 0x0425b9, /* Sound  */
325         0x454, 0x042539,
326
327         0x111, 0x000,
328         0x10e, 0x00a,
329         0x464, 0x000,
330         0x300, 0x000,
331         0x301, 0x006,
332         0x302, 0x000,
333         0x303, 0x006,
334         0x308, 0x040,
335         0x309, 0x000,
336         0x30a, 0x000,
337         0x30b, 0x000,
338         0x000, 0x002,
339         0x001, 0x000,
340         0x002, 0x000,
341         0x003, 0x000,
342         0x004, 0x033,
343         0x040, 0x01d,
344         0x041, 0x001,
345         0x042, 0x004,
346         0x043, 0x000,
347         0x080, 0x01e,
348         0x081, 0x001,
349         0x082, 0x004,
350         0x083, 0x000,
351         0x190, 0x018,
352         0x115, 0x000,
353         0x116, 0x012,
354         0x117, 0x018,
355         0x04a, 0x011,
356         0x08a, 0x011,
357         0x04b, 0x000,
358         0x08b, 0x000,
359         0x048, 0x000,
360         0x088, 0x000,
361         0x04e, 0x012,
362         0x08e, 0x012,
363         0x058, 0x012,
364         0x098, 0x012,
365         0x059, 0x000,
366         0x099, 0x000,
367         0x05a, 0x003,
368         0x09a, 0x003,
369         0x05b, 0x001,
370         0x09b, 0x001,
371         0x054, 0x008,
372         0x094, 0x008,
373         0x055, 0x000,
374         0x095, 0x000,
375         0x056, 0x0c7,
376         0x096, 0x0c7,
377         0x057, 0x002,
378         0x097, 0x002,
379         0x0ff, 0x0ff,
380         0x060, 0x001,
381         0x0a0, 0x001,
382         0x061, 0x000,
383         0x0a1, 0x000,
384         0x062, 0x000,
385         0x0a2, 0x000,
386         0x063, 0x000,
387         0x0a3, 0x000,
388         0x070, 0x000,
389         0x0b0, 0x000,
390         0x071, 0x004,
391         0x0b1, 0x004,
392         0x06c, 0x0e9,
393         0x0ac, 0x0e9,
394         0x06d, 0x003,
395         0x0ad, 0x003,
396         0x05c, 0x0d0,
397         0x09c, 0x0d0,
398         0x05d, 0x002,
399         0x09d, 0x002,
400         0x05e, 0x0f2,
401         0x09e, 0x0f2,
402         0x05f, 0x000,
403         0x09f, 0x000,
404         0x074, 0x000,
405         0x0b4, 0x000,
406         0x075, 0x000,
407         0x0b5, 0x000,
408         0x076, 0x000,
409         0x0b6, 0x000,
410         0x077, 0x000,
411         0x0b7, 0x000,
412         0x195, 0x008,
413         0x0ff, 0x0ff,
414         0x108, 0x0f8,
415         0x111, 0x000,
416         0x10e, 0x00a,
417         0x2a9, 0x0fd,
418         0x464, 0x001,
419         0x454, 0x042135,
420         0x598, 0x0e7,
421         0x599, 0x07d,
422         0x59a, 0x018,
423         0x59c, 0x066,
424         0x59d, 0x090,
425         0x59e, 0x001,
426         0x584, 0x000,
427         0x585, 0x000,
428         0x586, 0x003,
429         0x588, 0x0ff,
430         0x589, 0x00f,
431         0x58a, 0x000,
432         0x58b, 0x000,
433         0x58c, 0x010,
434         0x58d, 0x032,
435         0x58e, 0x054,
436         0x58f, 0x023,
437         0x590, 0x000,
438         0x595, 0x000,
439         0x596, 0x000,
440         0x597, 0x000,
441         0x464, 0x000,
442         0x46c, 0xbbbb10,
443         0x470, 0x101010,
444
445
446         0x478, 0x000,
447         0x474, 0x018,
448         0x454, 0x042135,
449         0x598, 0x0e7,
450         0x599, 0x07d,
451         0x59a, 0x018,
452         0x59c, 0x066,
453         0x59d, 0x090,
454         0x59e, 0x001,
455         0x584, 0x000,
456         0x585, 0x000,
457         0x586, 0x003,
458         0x588, 0x0ff,
459         0x589, 0x00f,
460         0x58a, 0x000,
461         0x58b, 0x000,
462         0x58c, 0x010,
463         0x58d, 0x032,
464         0x58e, 0x054,
465         0x58f, 0x023,
466         0x590, 0x000,
467         0x595, 0x000,
468         0x596, 0x000,
469         0x597, 0x000,
470         0x464, 0x000,
471         0x46c, 0xbbbb10,
472         0x470, 0x101010,
473
474         0x478, 0x000,
475         0x474, 0x018,
476         0x454, 0x042135,
477         0x598, 0x0e7,
478         0x599, 0x07d,
479         0x59a, 0x018,
480         0x59c, 0x066,
481         0x59d, 0x090,
482         0x59e, 0x001,
483         0x584, 0x000,
484         0x585, 0x000,
485         0x586, 0x003,
486         0x588, 0x0ff,
487         0x589, 0x00f,
488         0x58a, 0x000,
489         0x58b, 0x000,
490         0x58c, 0x010,
491         0x58d, 0x032,
492         0x58e, 0x054,
493         0x58f, 0x023,
494         0x590, 0x000,
495         0x595, 0x000,
496         0x596, 0x000,
497         0x597, 0x000,
498         0x464, 0x000,
499         0x46c, 0xbbbb10,
500         0x470, 0x101010,
501         0x478, 0x000,
502         0x474, 0x018,
503         0x454, 0x042135,
504         0x193, 0x000,
505         0x300, 0x000,
506         0x301, 0x006,
507         0x302, 0x000,
508         0x303, 0x006,
509         0x308, 0x040,
510         0x309, 0x000,
511         0x30a, 0x000,
512         0x30b, 0x000,
513         0x000, 0x002,
514         0x001, 0x000,
515         0x002, 0x000,
516         0x003, 0x000,
517         0x004, 0x033,
518         0x040, 0x01d,
519         0x041, 0x001,
520         0x042, 0x004,
521         0x043, 0x000,
522         0x080, 0x01e,
523         0x081, 0x001,
524         0x082, 0x004,
525         0x083, 0x000,
526         0x190, 0x018,
527         0x115, 0x000,
528         0x116, 0x012,
529         0x117, 0x018,
530         0x04a, 0x011,
531         0x08a, 0x011,
532         0x04b, 0x000,
533         0x08b, 0x000,
534         0x048, 0x000,
535         0x088, 0x000,
536         0x04e, 0x012,
537         0x08e, 0x012,
538         0x058, 0x012,
539         0x098, 0x012,
540         0x059, 0x000,
541         0x099, 0x000,
542         0x05a, 0x003,
543         0x09a, 0x003,
544         0x05b, 0x001,
545         0x09b, 0x001,
546         0x054, 0x008,
547         0x094, 0x008,
548         0x055, 0x000,
549         0x095, 0x000,
550         0x056, 0x0c7,
551         0x096, 0x0c7,
552         0x057, 0x002,
553         0x097, 0x002,
554         0x060, 0x001,
555         0x0a0, 0x001,
556         0x061, 0x000,
557         0x0a1, 0x000,
558         0x062, 0x000,
559         0x0a2, 0x000,
560         0x063, 0x000,
561         0x0a3, 0x000,
562         0x070, 0x000,
563         0x0b0, 0x000,
564         0x071, 0x004,
565         0x0b1, 0x004,
566         0x06c, 0x0e9,
567         0x0ac, 0x0e9,
568         0x06d, 0x003,
569         0x0ad, 0x003,
570         0x05c, 0x0d0,
571         0x09c, 0x0d0,
572         0x05d, 0x002,
573         0x09d, 0x002,
574         0x05e, 0x0f2,
575         0x09e, 0x0f2,
576         0x05f, 0x000,
577         0x09f, 0x000,
578         0x074, 0x000,
579         0x0b4, 0x000,
580         0x075, 0x000,
581         0x0b5, 0x000,
582         0x076, 0x000,
583         0x0b6, 0x000,
584         0x077, 0x000,
585         0x0b7, 0x000,
586         0x195, 0x008,
587         0x598, 0x0e7,
588         0x599, 0x07d,
589         0x59a, 0x018,
590         0x59c, 0x066,
591         0x59d, 0x090,
592         0x59e, 0x001,
593         0x584, 0x000,
594         0x585, 0x000,
595         0x586, 0x003,
596         0x588, 0x0ff,
597         0x589, 0x00f,
598         0x58a, 0x000,
599         0x58b, 0x000,
600         0x58c, 0x010,
601         0x58d, 0x032,
602         0x58e, 0x054,
603         0x58f, 0x023,
604         0x590, 0x000,
605         0x595, 0x000,
606         0x596, 0x000,
607         0x597, 0x000,
608         0x464, 0x000,
609         0x46c, 0xbbbb10,
610         0x470, 0x101010,
611         0x478, 0x000,
612         0x474, 0x018,
613         0x454, 0x042135,
614         0x193, 0x0a6,
615         0x108, 0x0f8,
616         0x042, 0x003,
617         0x082, 0x003,
618         0x454, 0x0425b9,
619         0x454, 0x042539,
620         0x193, 0x000,
621         0x193, 0x0a6,
622         0x464, 0x000,
623
624         0, 0
625 };
626
627 /* Tuner */
628 static u32 reg_init_tuner_input[] = {
629         0x108, 0x0f8, /* Sync control */
630         0x111, 0x000, /* Mode/delay control */
631         0x10e, 0x00a, /* Chroma control 1 */
632         0, 0
633 };
634
635 /* Composite */
636 static u32 reg_init_composite_input[] = {
637         0x108, 0x0e8, /* Sync control */
638         0x111, 0x000, /* Mode/delay control */
639         0x10e, 0x04a, /* Chroma control 1 */
640         0, 0
641 };
642
643 /* S-Video */
644 static u32 reg_init_svideo_input[] = {
645         0x108, 0x0e8, /* Sync control */
646         0x111, 0x000, /* Mode/delay control */
647         0x10e, 0x04a, /* Chroma control 1 */
648         0, 0
649 };
650
651 static u32 reg_set_audio_template[4][2] =
652 {
653         { /* for MONO
654                 tadachi 6/29 DMA audio output select?
655                 Register 0x46c
656                 7-4: DMA2, 3-0: DMA1 ch. DMA4, DMA3 DMA2, DMA1
657                 0: MAIN left,  1: MAIN right
658                 2: AUX1 left,  3: AUX1 right
659                 4: AUX2 left,  5: AUX2 right
660                 6: DPL left,   7: DPL  right
661                 8: DPL center, 9: DPL surround
662                 A: monitor output, B: digital sense */
663                 0xbbbb00,
664
665                 /* tadachi 6/29 DAC and I2S output select?
666                    Register 0x470
667                    7-4:DAC right ch. 3-0:DAC left ch.
668                    I2S1 right,left  I2S2 right,left */
669                 0x00,
670         },
671         { /* for STEREO */
672                 0xbbbb10, 0x101010,
673         },
674         { /* for LANG1 */
675                 0xbbbb00, 0x00,
676         },
677         { /* for LANG2/SAP */
678                 0xbbbb11, 0x111111,
679         }
680 };
681
682
683 /* Get detected audio flags (from saa7134 driver) */
684 static void get_inf_dev_status(struct i2c_client *client,
685                 int *dual_flag, int *stereo_flag)
686 {
687         u32 reg_data3;
688
689         static char *stdres[0x20] = {
690                 [0x00] = "no standard detected",
691                 [0x01] = "B/G (in progress)",
692                 [0x02] = "D/K (in progress)",
693                 [0x03] = "M (in progress)",
694
695                 [0x04] = "B/G A2",
696                 [0x05] = "B/G NICAM",
697                 [0x06] = "D/K A2 (1)",
698                 [0x07] = "D/K A2 (2)",
699                 [0x08] = "D/K A2 (3)",
700                 [0x09] = "D/K NICAM",
701                 [0x0a] = "L NICAM",
702                 [0x0b] = "I NICAM",
703
704                 [0x0c] = "M Korea",
705                 [0x0d] = "M BTSC ",
706                 [0x0e] = "M EIAJ",
707
708                 [0x0f] = "FM radio / IF 10.7 / 50 deemp",
709                 [0x10] = "FM radio / IF 10.7 / 75 deemp",
710                 [0x11] = "FM radio / IF sel / 50 deemp",
711                 [0x12] = "FM radio / IF sel / 75 deemp",
712
713                 [0x13 ... 0x1e] = "unknown",
714                 [0x1f] = "??? [in progress]",
715         };
716
717
718         *dual_flag = *stereo_flag = 0;
719
720         /* (demdec status: 0x528) */
721
722         /* read current status */
723         reg_data3 = saa717x_read(client, 0x0528);
724
725         v4l_dbg(1, debug, client, "tvaudio thread status: 0x%x [%s%s%s]\n",
726                 reg_data3, stdres[reg_data3 & 0x1f],
727                 (reg_data3 & 0x000020) ? ",stereo" : "",
728                 (reg_data3 & 0x000040) ? ",dual"   : "");
729         v4l_dbg(1, debug, client, "detailed status: "
730                 "%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n",
731                 (reg_data3 & 0x000080) ? " A2/EIAJ pilot tone "     : "",
732                 (reg_data3 & 0x000100) ? " A2/EIAJ dual "           : "",
733                 (reg_data3 & 0x000200) ? " A2/EIAJ stereo "         : "",
734                 (reg_data3 & 0x000400) ? " A2/EIAJ noise mute "     : "",
735
736                 (reg_data3 & 0x000800) ? " BTSC/FM radio pilot "    : "",
737                 (reg_data3 & 0x001000) ? " SAP carrier "            : "",
738                 (reg_data3 & 0x002000) ? " BTSC stereo noise mute " : "",
739                 (reg_data3 & 0x004000) ? " SAP noise mute "         : "",
740                 (reg_data3 & 0x008000) ? " VDSP "                   : "",
741
742                 (reg_data3 & 0x010000) ? " NICST "                  : "",
743                 (reg_data3 & 0x020000) ? " NICDU "                  : "",
744                 (reg_data3 & 0x040000) ? " NICAM muted "            : "",
745                 (reg_data3 & 0x080000) ? " NICAM reserve sound "    : "",
746
747                 (reg_data3 & 0x100000) ? " init done "              : "");
748
749         if (reg_data3 & 0x000220) {
750                 v4l_dbg(1, debug, client, "ST!!!\n");
751                 *stereo_flag = 1;
752         }
753
754         if (reg_data3 & 0x000140) {
755                 v4l_dbg(1, debug, client, "DUAL!!!\n");
756                 *dual_flag = 1;
757         }
758 }
759
760 /* regs write to set audio mode */
761 static void set_audio_mode(struct i2c_client *client, int audio_mode)
762 {
763         v4l_dbg(1, debug, client, "writing registers to set audio mode by set %d\n",
764                         audio_mode);
765
766         saa717x_write(client, 0x46c, reg_set_audio_template[audio_mode][0]);
767         saa717x_write(client, 0x470, reg_set_audio_template[audio_mode][1]);
768 }
769
770 /* write regs to video output level (bright,contrast,hue,sat) */
771 static void set_video_output_level_regs(struct i2c_client *client,
772                 struct saa717x_state *decoder)
773 {
774         /* brightness ffh (bright) - 80h (ITU level) - 00h (dark) */
775         saa717x_write(client, 0x10a, decoder->bright);
776
777         /* contrast 7fh (max: 1.984) - 44h (ITU) - 40h (1.0) -
778            0h (luminance off) 40: i2c dump
779            c0h (-1.0 inverse chrominance)
780            80h (-2.0 inverse chrominance) */
781         saa717x_write(client, 0x10b, decoder->contrast);
782
783         /* saturation? 7fh(max)-40h(ITU)-0h(color off)
784            c0h (-1.0 inverse chrominance)
785            80h (-2.0 inverse chrominance) */
786         saa717x_write(client, 0x10c, decoder->sat);
787
788         /* color hue (phase) control
789            7fh (+178.6) - 0h (0 normal) - 80h (-180.0) */
790         saa717x_write(client, 0x10d, decoder->hue);
791 }
792
793 /* write regs to set audio volume, bass and treble */
794 static int set_audio_regs(struct i2c_client *client,
795                 struct saa717x_state *decoder)
796 {
797         u8 mute = 0xac; /* -84 dB */
798         u32 val;
799         unsigned int work_l, work_r;
800
801         /* set SIF analog I/O select */
802         saa717x_write(client, 0x0594, decoder->audio_input);
803         v4l_dbg(1, debug, client, "set audio input %d\n",
804                         decoder->audio_input);
805
806         /* normalize ( 65535 to 0 -> 24 to -40 (not -84)) */
807         work_l = (min(65536 - decoder->audio_main_balance, 32768) * decoder->audio_main_volume) / 32768;
808         work_r = (min(decoder->audio_main_balance, (u16)32768) * decoder->audio_main_volume) / 32768;
809         decoder->audio_main_vol_l = (long)work_l * (24 - (-40)) / 65535 - 40;
810         decoder->audio_main_vol_r = (long)work_r * (24 - (-40)) / 65535 - 40;
811
812         /* set main volume */
813         /* main volume L[7-0],R[7-0],0x00  24=24dB,-83dB, -84(mute) */
814         /*    def:0dB->6dB(MPG600GR) */
815         /* if mute is on, set mute */
816         if (decoder->audio_main_mute) {
817                 val = mute | (mute << 8);
818         } else {
819                 val = (u8)decoder->audio_main_vol_l |
820                         ((u8)decoder->audio_main_vol_r << 8);
821         }
822
823         saa717x_write(client, 0x480, val);
824
825         /* bass and treble; go to another function */
826         /* set bass and treble */
827         val = decoder->audio_main_bass | (decoder->audio_main_treble << 8);
828         saa717x_write(client, 0x488, val);
829         return 0;
830 }
831
832 /********** scaling staff ***********/
833 static void set_h_prescale(struct i2c_client *client,
834                 int task, int prescale)
835 {
836         static const struct {
837                 int xpsc;
838                 int xacl;
839                 int xc2_1;
840                 int xdcg;
841                 int vpfy;
842         } vals[] = {
843                 /* XPSC XACL XC2_1 XDCG VPFY */
844                 {    1,   0,    0,    0,   0 },
845                 {    2,   2,    1,    2,   2 },
846                 {    3,   4,    1,    3,   2 },
847                 {    4,   8,    1,    4,   2 },
848                 {    5,   8,    1,    4,   2 },
849                 {    6,   8,    1,    4,   3 },
850                 {    7,   8,    1,    4,   3 },
851                 {    8,  15,    0,    4,   3 },
852                 {    9,  15,    0,    4,   3 },
853                 {   10,  16,    1,    5,   3 },
854         };
855         static const int count = ARRAY_SIZE(vals);
856         int i, task_shift;
857
858         task_shift = task * 0x40;
859         for (i = 0; i < count; i++)
860                 if (vals[i].xpsc == prescale)
861                         break;
862         if (i == count)
863                 return;
864
865         /* horizonal prescaling */
866         saa717x_write(client, 0x60 + task_shift, vals[i].xpsc);
867         /* accumulation length */
868         saa717x_write(client, 0x61 + task_shift, vals[i].xacl);
869         /* level control */
870         saa717x_write(client, 0x62 + task_shift,
871                         (vals[i].xc2_1 << 3) | vals[i].xdcg);
872         /*FIR prefilter control */
873         saa717x_write(client, 0x63 + task_shift,
874                         (vals[i].vpfy << 2) | vals[i].vpfy);
875 }
876
877 /********** scaling staff ***********/
878 static void set_v_scale(struct i2c_client *client, int task, int yscale)
879 {
880         int task_shift;
881
882         task_shift = task * 0x40;
883         /* Vertical scaling ratio (LOW) */
884         saa717x_write(client, 0x70 + task_shift, yscale & 0xff);
885         /* Vertical scaling ratio (HI) */
886         saa717x_write(client, 0x71 + task_shift, yscale >> 8);
887 }
888
889 static int saa717x_set_audio_clock_freq(struct i2c_client *client, u32 freq)
890 {
891         /* not yet implament, so saa717x_cfg_??hz_??_audio is not defined. */
892         return 0;
893 }
894
895 static int saa717x_set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
896 {
897         struct saa717x_state *state = i2c_get_clientdata(client);
898
899         switch (ctrl->id) {
900         case V4L2_CID_BRIGHTNESS:
901                 if (ctrl->value < 0 || ctrl->value > 255) {
902                         v4l_err(client, "invalid brightness setting %d\n", ctrl->value);
903                         return -ERANGE;
904                 }
905
906                 state->bright = ctrl->value;
907                 v4l_dbg(1, debug, client, "bright:%d\n", state->bright);
908                 saa717x_write(client, 0x10a, state->bright);
909                 break;
910
911         case V4L2_CID_CONTRAST:
912                 if (ctrl->value < 0 || ctrl->value > 127) {
913                         v4l_err(client, "invalid contrast setting %d\n", ctrl->value);
914                         return -ERANGE;
915                 }
916
917                 state->contrast = ctrl->value;
918                 v4l_dbg(1, debug, client, "contrast:%d\n", state->contrast);
919                 saa717x_write(client, 0x10b, state->contrast);
920                 break;
921
922         case V4L2_CID_SATURATION:
923                 if (ctrl->value < 0 || ctrl->value > 127) {
924                         v4l_err(client, "invalid saturation setting %d\n", ctrl->value);
925                         return -ERANGE;
926                 }
927
928                 state->sat = ctrl->value;
929                 v4l_dbg(1, debug, client, "sat:%d\n", state->sat);
930                 saa717x_write(client, 0x10c, state->sat);
931                 break;
932
933         case V4L2_CID_HUE:
934                 if (ctrl->value < -127 || ctrl->value > 127) {
935                         v4l_err(client, "invalid hue setting %d\n", ctrl->value);
936                         return -ERANGE;
937                 }
938
939                 state->hue = ctrl->value;
940                 v4l_dbg(1, debug, client, "hue:%d\n", state->hue);
941                 saa717x_write(client, 0x10d, state->hue);
942                 break;
943
944         case V4L2_CID_AUDIO_MUTE:
945                 state->audio_main_mute = ctrl->value;
946                 set_audio_regs(client, state);
947                 break;
948
949         case V4L2_CID_AUDIO_VOLUME:
950                 state->audio_main_volume = ctrl->value;
951                 set_audio_regs(client, state);
952                 break;
953
954         case V4L2_CID_AUDIO_BALANCE:
955                 state->audio_main_balance = ctrl->value;
956                 set_audio_regs(client, state);
957                 break;
958
959         case V4L2_CID_AUDIO_TREBLE:
960                 state->audio_main_treble = ctrl->value;
961                 set_audio_regs(client, state);
962                 break;
963
964         case V4L2_CID_AUDIO_BASS:
965                 state->audio_main_bass = ctrl->value;
966                 set_audio_regs(client, state);
967                 break;
968
969         default:
970                 return -EINVAL;
971         }
972
973         return 0;
974 }
975
976 static int saa717x_get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
977 {
978         struct saa717x_state *state = i2c_get_clientdata(client);
979
980         switch (ctrl->id) {
981         case V4L2_CID_BRIGHTNESS:
982                 ctrl->value = state->bright;
983                 break;
984
985         case V4L2_CID_CONTRAST:
986                 ctrl->value = state->contrast;
987                 break;
988
989         case V4L2_CID_SATURATION:
990                 ctrl->value = state->sat;
991                 break;
992
993         case V4L2_CID_HUE:
994                 ctrl->value = state->hue;
995                 break;
996
997         case V4L2_CID_AUDIO_MUTE:
998                 ctrl->value = state->audio_main_mute;
999                 break;
1000
1001         case V4L2_CID_AUDIO_VOLUME:
1002                 ctrl->value = state->audio_main_volume;
1003                 break;
1004
1005         case V4L2_CID_AUDIO_BALANCE:
1006                 ctrl->value = state->audio_main_balance;
1007                 break;
1008
1009         case V4L2_CID_AUDIO_TREBLE:
1010                 ctrl->value = state->audio_main_treble;
1011                 break;
1012
1013         case V4L2_CID_AUDIO_BASS:
1014                 ctrl->value = state->audio_main_bass;
1015                 break;
1016
1017         default:
1018                 return -EINVAL;
1019         }
1020
1021         return 0;
1022 }
1023
1024 static struct v4l2_queryctrl saa717x_qctrl[] = {
1025         {
1026                 .id            = V4L2_CID_BRIGHTNESS,
1027                 .type          = V4L2_CTRL_TYPE_INTEGER,
1028                 .name          = "Brightness",
1029                 .minimum       = 0,
1030                 .maximum       = 255,
1031                 .step          = 1,
1032                 .default_value = 128,
1033                 .flags         = 0,
1034         }, {
1035                 .id            = V4L2_CID_CONTRAST,
1036                 .type          = V4L2_CTRL_TYPE_INTEGER,
1037                 .name          = "Contrast",
1038                 .minimum       = 0,
1039                 .maximum       = 255,
1040                 .step          = 1,
1041                 .default_value = 64,
1042                 .flags         = 0,
1043         }, {
1044                 .id            = V4L2_CID_SATURATION,
1045                 .type          = V4L2_CTRL_TYPE_INTEGER,
1046                 .name          = "Saturation",
1047                 .minimum       = 0,
1048                 .maximum       = 255,
1049                 .step          = 1,
1050                 .default_value = 64,
1051                 .flags         = 0,
1052         }, {
1053                 .id            = V4L2_CID_HUE,
1054                 .type          = V4L2_CTRL_TYPE_INTEGER,
1055                 .name          = "Hue",
1056                 .minimum       = -128,
1057                 .maximum       = 127,
1058                 .step          = 1,
1059                 .default_value = 0,
1060                 .flags         = 0,
1061         }, {
1062                 .id            = V4L2_CID_AUDIO_VOLUME,
1063                 .type          = V4L2_CTRL_TYPE_INTEGER,
1064                 .name          = "Volume",
1065                 .minimum       = 0,
1066                 .maximum       = 65535,
1067                 .step          = 65535 / 100,
1068                 .default_value = 58880,
1069                 .flags         = 0,
1070         }, {
1071                 .id            = V4L2_CID_AUDIO_BALANCE,
1072                 .type          = V4L2_CTRL_TYPE_INTEGER,
1073                 .name          = "Balance",
1074                 .minimum       = 0,
1075                 .maximum       = 65535,
1076                 .step          = 65535 / 100,
1077                 .default_value = 32768,
1078                 .flags         = 0,
1079         }, {
1080                 .id            = V4L2_CID_AUDIO_MUTE,
1081                 .type          = V4L2_CTRL_TYPE_BOOLEAN,
1082                 .name          = "Mute",
1083                 .minimum       = 0,
1084                 .maximum       = 1,
1085                 .step          = 1,
1086                 .default_value = 1,
1087                 .flags         = 0,
1088         }, {
1089                 .id            = V4L2_CID_AUDIO_BASS,
1090                 .type          = V4L2_CTRL_TYPE_INTEGER,
1091                 .name          = "Bass",
1092                 .minimum       = 0,
1093                 .maximum       = 65535,
1094                 .step          = 65535 / 100,
1095                 .default_value = 32768,
1096         }, {
1097                 .id            = V4L2_CID_AUDIO_TREBLE,
1098                 .type          = V4L2_CTRL_TYPE_INTEGER,
1099                 .name          = "Treble",
1100                 .minimum       = 0,
1101                 .maximum       = 65535,
1102                 .step          = 65535 / 100,
1103                 .default_value = 32768,
1104         },
1105 };
1106
1107 static int saa717x_set_video_input(struct i2c_client *client, struct saa717x_state *decoder, int inp)
1108 {
1109         int is_tuner = inp & 0x80;  /* tuner input flag */
1110
1111         inp &= 0x7f;
1112
1113         v4l_dbg(1, debug, client, "decoder set input (%d)\n", inp);
1114         /* inputs from 0-9 are available*/
1115         /* saa717x have mode0-mode9 but mode5 is reserved. */
1116         if (inp < 0 || inp > 9 || inp == 5)
1117                 return -EINVAL;
1118
1119         if (decoder->input != inp) {
1120                 int input_line = inp;
1121
1122                 decoder->input = input_line;
1123                 v4l_dbg(1, debug, client,  "now setting %s input %d\n",
1124                                 input_line >= 6 ? "S-Video" : "Composite",
1125                                 input_line);
1126
1127                 /* select mode */
1128                 saa717x_write(client, 0x102,
1129                                 (saa717x_read(client, 0x102) & 0xf0) |
1130                                 input_line);
1131
1132                 /* bypass chrominance trap for modes 6..9 */
1133                 saa717x_write(client, 0x109,
1134                                 (saa717x_read(client, 0x109) & 0x7f) |
1135                                 (input_line < 6 ? 0x0 : 0x80));
1136
1137                 /* change audio_mode */
1138                 if (is_tuner) {
1139                         /* tuner */
1140                         set_audio_mode(client, decoder->tuner_audio_mode);
1141                 } else {
1142                         /* Force to STEREO mode if Composite or
1143                          * S-Video were chosen */
1144                         set_audio_mode(client, TUNER_AUDIO_STEREO);
1145                 }
1146                 /* change initialize procedure (Composite/S-Video) */
1147                 if (is_tuner)
1148                         saa717x_write_regs(client, reg_init_tuner_input);
1149                 else if (input_line >= 6)
1150                         saa717x_write_regs(client, reg_init_svideo_input);
1151                 else
1152                         saa717x_write_regs(client, reg_init_composite_input);
1153         }
1154
1155         return 0;
1156 }
1157
1158 static int saa717x_command(struct i2c_client *client, unsigned cmd, void *arg)
1159 {
1160         struct saa717x_state *decoder = i2c_get_clientdata(client);
1161
1162         v4l_dbg(1, debug, client, "IOCTL: %08x\n", cmd);
1163
1164         switch (cmd) {
1165         case VIDIOC_INT_AUDIO_CLOCK_FREQ:
1166                 return saa717x_set_audio_clock_freq(client, *(u32 *)arg);
1167
1168         case VIDIOC_G_CTRL:
1169                 return saa717x_get_v4lctrl(client, (struct v4l2_control *)arg);
1170
1171         case VIDIOC_S_CTRL:
1172                 return saa717x_set_v4lctrl(client, (struct v4l2_control *)arg);
1173
1174         case VIDIOC_QUERYCTRL: {
1175                 struct v4l2_queryctrl *qc = arg;
1176                 int i;
1177
1178                 for (i = 0; i < ARRAY_SIZE(saa717x_qctrl); i++)
1179                         if (qc->id && qc->id == saa717x_qctrl[i].id) {
1180                                 memcpy(qc, &saa717x_qctrl[i], sizeof(*qc));
1181                                 return 0;
1182                         }
1183                 return -EINVAL;
1184         }
1185
1186 #ifdef CONFIG_VIDEO_ADV_DEBUG
1187         case VIDIOC_DBG_G_REGISTER: {
1188                 struct v4l2_register *reg = arg;
1189
1190                 if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))
1191                         return -EINVAL;
1192                 if (!capable(CAP_SYS_ADMIN))
1193                         return -EPERM;
1194                 reg->val = saa717x_read(client, reg->reg);
1195                 break;
1196         }
1197
1198         case VIDIOC_DBG_S_REGISTER: {
1199                 struct v4l2_register *reg = arg;
1200                 u16 addr = reg->reg & 0xffff;
1201                 u8 val = reg->val & 0xff;
1202
1203                 if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))
1204                         return -EINVAL;
1205                 if (!capable(CAP_SYS_ADMIN))
1206                         return -EPERM;
1207                 saa717x_write(client, addr, val);
1208                 break;
1209         }
1210 #endif
1211
1212         case VIDIOC_S_FMT: {
1213                 struct v4l2_format *fmt = (struct v4l2_format *)arg;
1214                 struct v4l2_pix_format *pix;
1215                 int prescale, h_scale, v_scale;
1216
1217                 pix = &fmt->fmt.pix;
1218                 v4l_dbg(1, debug, client, "decoder set size\n");
1219
1220                 /* FIXME need better bounds checking here */
1221                 if (pix->width < 1 || pix->width > 1440)
1222                         return -EINVAL;
1223                 if (pix->height < 1 || pix->height > 960)
1224                         return -EINVAL;
1225
1226                 /* scaling setting */
1227                 /* NTSC and interlace only */
1228                 prescale = SAA717X_NTSC_WIDTH / pix->width;
1229                 if (prescale == 0)
1230                         prescale = 1;
1231                 h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / pix->width;
1232                 /* interlace */
1233                 v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / pix->height;
1234
1235                 /* Horizontal prescaling etc */
1236                 set_h_prescale(client, 0, prescale);
1237                 set_h_prescale(client, 1, prescale);
1238
1239                 /* Horizontal scaling increment */
1240                 /* TASK A */
1241                 saa717x_write(client, 0x6C, (u8)(h_scale & 0xFF));
1242                 saa717x_write(client, 0x6D, (u8)((h_scale >> 8) & 0xFF));
1243                 /* TASK B */
1244                 saa717x_write(client, 0xAC, (u8)(h_scale & 0xFF));
1245                 saa717x_write(client, 0xAD, (u8)((h_scale >> 8) & 0xFF));
1246
1247                 /* Vertical prescaling etc */
1248                 set_v_scale(client, 0, v_scale);
1249                 set_v_scale(client, 1, v_scale);
1250
1251                 /* set video output size */
1252                 /* video number of pixels at output */
1253                 /* TASK A */
1254                 saa717x_write(client, 0x5C, (u8)(pix->width & 0xFF));
1255                 saa717x_write(client, 0x5D, (u8)((pix->width >> 8) & 0xFF));
1256                 /* TASK B */
1257                 saa717x_write(client, 0x9C, (u8)(pix->width & 0xFF));
1258                 saa717x_write(client, 0x9D, (u8)((pix->width >> 8) & 0xFF));
1259
1260                 /* video number of lines at output */
1261                 /* TASK A */
1262                 saa717x_write(client, 0x5E, (u8)(pix->height & 0xFF));
1263                 saa717x_write(client, 0x5F, (u8)((pix->height >> 8) & 0xFF));
1264                 /* TASK B */
1265                 saa717x_write(client, 0x9E, (u8)(pix->height & 0xFF));
1266                 saa717x_write(client, 0x9F, (u8)((pix->height >> 8) & 0xFF));
1267                 break;
1268         }
1269
1270         case AUDC_SET_RADIO:
1271                 decoder->radio = 1;
1272                 break;
1273
1274         case VIDIOC_S_STD: {
1275                 v4l2_std_id std = *(v4l2_std_id *) arg;
1276
1277                 v4l_dbg(1, debug, client, "decoder set norm ");
1278                 v4l_dbg(1, debug, client, "(not yet implementd)\n");
1279
1280                 decoder->radio = 0;
1281                 decoder->std = std;
1282                 break;
1283         }
1284
1285         case VIDIOC_INT_G_AUDIO_ROUTING: {
1286                 struct v4l2_routing *route = arg;
1287
1288                 route->input = decoder->audio_input;
1289                 route->output = 0;
1290                 break;
1291         }
1292
1293         case VIDIOC_INT_S_AUDIO_ROUTING: {
1294                 struct v4l2_routing *route = arg;
1295
1296                 if (route->input < 3) { /* FIXME! --tadachi */
1297                         decoder->audio_input = route->input;
1298                         v4l_dbg(1, debug, client,
1299                                 "set decoder audio input to %d\n",
1300                                 decoder->audio_input);
1301                         set_audio_regs(client, decoder);
1302                         break;
1303                 }
1304                 return -ERANGE;
1305         }
1306
1307         case VIDIOC_INT_S_VIDEO_ROUTING: {
1308                 struct v4l2_routing *route = arg;
1309                 int inp = route->input;
1310
1311                 return saa717x_set_video_input(client, decoder, inp);
1312         }
1313
1314         case VIDIOC_STREAMON: {
1315                 v4l_dbg(1, debug, client, "decoder enable output\n");
1316                 decoder->enable = 1;
1317                 saa717x_write(client, 0x193, 0xa6);
1318                 break;
1319         }
1320
1321         case VIDIOC_STREAMOFF: {
1322                 v4l_dbg(1, debug, client, "decoder disable output\n");
1323                 decoder->enable = 0;
1324                 saa717x_write(client, 0x193, 0x26); /* right? FIXME!--tadachi */
1325                 break;
1326         }
1327
1328                 /* change audio mode */
1329         case VIDIOC_S_TUNER: {
1330                 struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
1331                 int audio_mode;
1332                 char *mes[4] = {
1333                         "MONO", "STEREO", "LANG1", "LANG2/SAP"
1334                 };
1335
1336                 audio_mode = V4L2_TUNER_MODE_STEREO;
1337
1338                 switch (vt->audmode) {
1339                 case V4L2_TUNER_MODE_MONO:
1340                         audio_mode = TUNER_AUDIO_MONO;
1341                         break;
1342                 case V4L2_TUNER_MODE_STEREO:
1343                         audio_mode = TUNER_AUDIO_STEREO;
1344                         break;
1345                 case V4L2_TUNER_MODE_LANG2:
1346                         audio_mode = TUNER_AUDIO_LANG2;
1347                         break;
1348                 case V4L2_TUNER_MODE_LANG1:
1349                         audio_mode = TUNER_AUDIO_LANG1;
1350                         break;
1351                 }
1352
1353                 v4l_dbg(1, debug, client, "change audio mode to %s\n",
1354                                 mes[audio_mode]);
1355                 decoder->tuner_audio_mode = audio_mode;
1356                 /* The registers are not changed here. */
1357                 /* See DECODER_ENABLE_OUTPUT section. */
1358                 set_audio_mode(client, decoder->tuner_audio_mode);
1359                 break;
1360         }
1361
1362         case VIDIOC_G_TUNER: {
1363                 struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
1364                 int dual_f, stereo_f;
1365
1366                 if (decoder->radio)
1367                         break;
1368                 get_inf_dev_status(client, &dual_f, &stereo_f);
1369
1370                 v4l_dbg(1, debug, client, "DETECT==st:%d dual:%d\n",
1371                                 stereo_f, dual_f);
1372
1373                 /* mono */
1374                 if ((dual_f == 0) && (stereo_f == 0)) {
1375                         vt->rxsubchans = V4L2_TUNER_SUB_MONO;
1376                         v4l_dbg(1, debug, client, "DETECT==MONO\n");
1377                 }
1378
1379                 /* stereo */
1380                 if (stereo_f == 1) {
1381                         if (vt->audmode == V4L2_TUNER_MODE_STEREO ||
1382                             vt->audmode == V4L2_TUNER_MODE_LANG1) {
1383                                 vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
1384                                 v4l_dbg(1, debug, client, "DETECT==ST(ST)\n");
1385                         } else {
1386                                 vt->rxsubchans = V4L2_TUNER_SUB_MONO;
1387                                 v4l_dbg(1, debug, client, "DETECT==ST(MONO)\n");
1388                         }
1389                 }
1390
1391                 /* dual */
1392                 if (dual_f == 1) {
1393                         if (vt->audmode == V4L2_TUNER_MODE_LANG2) {
1394                                 vt->rxsubchans = V4L2_TUNER_SUB_LANG2 | V4L2_TUNER_SUB_MONO;
1395                                 v4l_dbg(1, debug, client, "DETECT==DUAL1\n");
1396                         } else {
1397                                 vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_MONO;
1398                                 v4l_dbg(1, debug, client, "DETECT==DUAL2\n");
1399                         }
1400                 }
1401                 break;
1402         }
1403
1404         case VIDIOC_LOG_STATUS:
1405                 /* not yet implemented */
1406                 break;
1407
1408         default:
1409                 return -EINVAL;
1410         }
1411
1412         return 0;
1413 }
1414
1415 /* ----------------------------------------------------------------------- */
1416
1417
1418 /* i2c implementation */
1419
1420 /* ----------------------------------------------------------------------- */
1421 static int saa717x_probe(struct i2c_client *client,
1422                          const struct i2c_device_id *did)
1423 {
1424         struct saa717x_state *decoder;
1425         u8 id = 0;
1426         char *p = "";
1427
1428         /* Check if the adapter supports the needed features */
1429         if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
1430                 return -EIO;
1431
1432         if (saa717x_write(client, 0x5a4, 0xfe) &&
1433                         saa717x_write(client, 0x5a5, 0x0f) &&
1434                         saa717x_write(client, 0x5a6, 0x00) &&
1435                         saa717x_write(client, 0x5a7, 0x01))
1436                 id = saa717x_read(client, 0x5a0);
1437         if (id != 0xc2 && id != 0x32 && id != 0xf2 && id != 0x6c) {
1438                 v4l_dbg(1, debug, client, "saa717x not found (id=%02x)\n", id);
1439                 return -ENODEV;
1440         }
1441         if (id == 0xc2)
1442                 p = "saa7173";
1443         else if (id == 0x32)
1444                 p = "saa7174A";
1445         else if (id == 0x6c)
1446                 p = "saa7174HL";
1447         else
1448                 p = "saa7171";
1449         v4l_info(client, "%s found @ 0x%x (%s)\n", p,
1450                         client->addr << 1, client->adapter->name);
1451
1452         decoder = kzalloc(sizeof(struct saa717x_state), GFP_KERNEL);
1453         i2c_set_clientdata(client, decoder);
1454
1455         if (decoder == NULL)
1456                 return -ENOMEM;
1457         decoder->std = V4L2_STD_NTSC;
1458         decoder->input = -1;
1459         decoder->enable = 1;
1460
1461         /* tune these parameters */
1462         decoder->bright = 0x80;
1463         decoder->contrast = 0x44;
1464         decoder->sat = 0x40;
1465         decoder->hue = 0x00;
1466
1467         /* FIXME!! */
1468         decoder->playback = 0;  /* initially capture mode used */
1469         decoder->audio = 1; /* DECODER_AUDIO_48_KHZ */
1470
1471         decoder->audio_input = 2; /* FIXME!! */
1472
1473         decoder->tuner_audio_mode = TUNER_AUDIO_STEREO;
1474         /* set volume, bass and treble */
1475         decoder->audio_main_vol_l = 6;
1476         decoder->audio_main_vol_r = 6;
1477         decoder->audio_main_bass = 0;
1478         decoder->audio_main_treble = 0;
1479         decoder->audio_main_mute = 0;
1480         decoder->audio_main_balance = 32768;
1481         /* normalize (24 to -40 (not -84) -> 65535 to 0) */
1482         decoder->audio_main_volume =
1483                 (decoder->audio_main_vol_r + 41) * 65535 / (24 - (-40));
1484
1485         v4l_dbg(1, debug, client, "writing init values\n");
1486
1487         /* FIXME!! */
1488         saa717x_write_regs(client, reg_init_initialize);
1489         set_video_output_level_regs(client, decoder);
1490         /* set bass,treble to 0db 20041101 K.Ohta */
1491         decoder->audio_main_bass = 0;
1492         decoder->audio_main_treble = 0;
1493         set_audio_regs(client, decoder);
1494
1495         set_current_state(TASK_INTERRUPTIBLE);
1496         schedule_timeout(2*HZ);
1497         return 0;
1498 }
1499
1500 static int saa717x_remove(struct i2c_client *client)
1501 {
1502         kfree(i2c_get_clientdata(client));
1503         return 0;
1504 }
1505
1506 /* ----------------------------------------------------------------------- */
1507
1508 static const struct i2c_device_id saa717x_id[] = {
1509         { "saa717x", 0 },
1510         { }
1511 };
1512 MODULE_DEVICE_TABLE(i2c, saa717x_id);
1513
1514 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
1515         .name = "saa717x",
1516         .driverid = I2C_DRIVERID_SAA717X,
1517         .command = saa717x_command,
1518         .probe = saa717x_probe,
1519         .remove = saa717x_remove,
1520         .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL,
1521         .id_table = saa717x_id,
1522 };