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