[PATCH] v4l: (948) adds support for saa7115 video decoder
[linux-2.6] / drivers / media / video / saa7115.c
1 /* saa7115 - Philips SAA7114/SAA7115 video decoder driver
2  *
3  * Based on saa7114 driver by Maxim Yevtyushkin, which is based on
4  * the saa7111 driver by Dave Perks.
5  *
6  * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
7  * Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com>
8  *
9  * Slight changes for video timing and attachment output by
10  * Wolfgang Scherr <scherr@net4you.net>
11  *
12  * Moved over to the linux >= 2.4.x i2c protocol (1/1/2003)
13  * by Ronald Bultje <rbultje@ronald.bitfreak.net>
14  *
15  * Added saa7115 support by Kevin Thayer <nufan_wfk at yahoo.com>
16  * (2/17/2003)
17  *
18  * VBI support (2004) and cleanups (2005) by Hans Verkuil <hverkuil@xs4all.nl>
19  *
20  * This program is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU General Public License
22  * as published by the Free Software Foundation; either version 2
23  * of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28  * GNU General Public License for more details.
29  *
30  * You should have received a copy of the GNU General Public License
31  * along with this program; if not, write to the Free Software
32  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
33  */
34
35
36 #include <linux/kernel.h>
37 #include <linux/module.h>
38 #include <linux/slab.h>
39 #include <linux/i2c.h>
40 #include <linux/videodev2.h>
41 #include <media/i2c-compat.h>
42 #include <media/v4l2-common.h>
43
44 MODULE_DESCRIPTION("Philips SAA7114/SAA7115 video decoder driver");
45 MODULE_AUTHOR("Maxim Yevtyushkin <max@linuxmedialabs.com>");
46 MODULE_AUTHOR("Kevin Thayer <nufan_wfk@yahoo.com>");
47 MODULE_AUTHOR("Chris Kennedy <c@groovy.org>");
48 MODULE_AUTHOR("Hans Verkuil <hverkuil@xs4all.nl>");
49 MODULE_LICENSE("GPL");
50
51 static int debug = 0;
52 module_param(debug, int, 0644);
53
54 MODULE_PARM_DESC(debug, "Debug level (0-1)");
55
56 #define saa7115_dbg(fmt,arg...) \
57         do { \
58                 if (debug) \
59                         printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \
60                                i2c_adapter_id(client->adapter), client->addr , ## arg); \
61         } while (0)
62
63 #define saa7115_err(fmt, arg...) do { \
64         printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \
65                i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
66 #define saa7115_info(fmt, arg...) do { \
67         printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \
68                i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
69
70 static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END };
71
72
73 I2C_CLIENT_INSMOD;
74
75 struct saa7115_state {
76         v4l2_std_id std;
77         int input;
78         int enable;
79         int bright;
80         int contrast;
81         int hue;
82         int sat;
83         enum v4l2_chip_ident ident;
84         enum v4l2_audio_clock_freq audclk_freq;
85 };
86
87 /* ----------------------------------------------------------------------- */
88
89 static inline int saa7115_write(struct i2c_client *client, u8 reg, u8 value)
90 {
91         return i2c_smbus_write_byte_data(client, reg, value);
92 }
93
94 static int saa7115_writeregs(struct i2c_client *client, const unsigned char *regs)
95 {
96         unsigned char reg, data;
97
98         while (*regs != 0x00) {
99                 reg = *(regs++);
100                 data = *(regs++);
101                 if (saa7115_write(client, reg, data) < 0)
102                         return -1;
103         }
104         return 0;
105 }
106
107 static inline int saa7115_read(struct i2c_client *client, u8 reg)
108 {
109         return i2c_smbus_read_byte_data(client, reg);
110 }
111
112 /* ----------------------------------------------------------------------- */
113
114 /* If a value differs from the Hauppauge driver values, then the comment starts with
115    'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the
116    Hauppauge driver sets. */
117
118 static const unsigned char saa7115_init_auto_input[] = {
119         0x01, 0x48,             /* white peak control disabled */
120         0x03, 0x20,             /* was 0x30. 0x20: long vertical blanking */
121         0x04, 0x90,             /* analog gain set to 0 */
122         0x05, 0x90,             /* analog gain set to 0 */
123         0x06, 0xeb,             /* horiz sync begin = -21 */
124         0x07, 0xe0,             /* horiz sync stop = -17 */
125         0x0a, 0x80,             /* was 0x88. decoder brightness, 0x80 is itu standard */
126         0x0b, 0x44,             /* was 0x48. decoder contrast, 0x44 is itu standard */
127         0x0c, 0x40,             /* was 0x47. decoder saturation, 0x40 is itu standard */
128         0x0d, 0x00,             /* chrominance hue control */
129         0x0f, 0x00,             /* chrominance gain control: use automicatic mode */
130         0x10, 0x06,             /* chrominance/luminance control: active adaptive combfilter */
131         0x11, 0x00,             /* delay control */
132         0x12, 0x9d,             /* RTS0 output control: VGATE */
133         0x13, 0x80,             /* X-port output control: ITU656 standard mode, RTCO output enable RTCE */
134         0x14, 0x00,             /* analog/ADC/auto compatibility control */
135         0x18, 0x40,             /* raw data gain 0x00 = nominal */
136         0x19, 0x80,             /* raw data offset 0x80 = 0 LSB */
137         0x1a, 0x77,             /* color killer level control 0x77 = recommended */
138         0x1b, 0x42,             /* misc chroma control 0x42 = recommended */
139         0x1c, 0xa9,             /* combfilter control 0xA9 = recommended */
140         0x1d, 0x01,             /* combfilter control 0x01 = recommended */
141         0x88, 0xd0,             /* reset device */
142         0x88, 0xf0,             /* set device programmed, all in operational mode */
143         0x00, 0x00
144 };
145
146 static const unsigned char saa7115_cfg_reset_scaler[] = {
147         0x87, 0x00,             /* disable I-port output */
148         0x88, 0xd0,             /* reset scaler */
149         0x88, 0xf0,             /* activate scaler */
150         0x87, 0x01,             /* enable I-port output */
151         0x00, 0x00
152 };
153
154 /* ============== SAA7715 VIDEO templates =============  */
155
156 static const unsigned char saa7115_cfg_60hz_fullres_x[] = {
157         0xcc, 0xd0,             /* hsize low (output), hor. output window size = 0x2d0 = 720 */
158         0xcd, 0x02,             /* hsize hi (output) */
159
160         /* Why not in 60hz-Land, too? */
161         0xd0, 0x01,             /* downscale = 1 */
162         0xd8, 0x00,             /* hor lum scaling 0x0400 = 1 */
163         0xd9, 0x04,
164         0xdc, 0x00,             /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */
165         0xdd, 0x02,             /* H-scaling incr chroma */
166
167         0x00, 0x00
168 };
169 static const unsigned char saa7115_cfg_60hz_fullres_y[] = {
170         0xce, 0xf8,             /* vsize low (output), ver. output window size = 248 (but 60hz is 240?) */
171         0xcf, 0x00,             /* vsize hi (output) */
172
173         /* Why not in 60hz-Land, too? */
174         0xd5, 0x40,             /* Lum contrast, nominal value = 0x40 */
175         0xd6, 0x40,             /* Chroma satur. nominal value = 0x80 */
176
177         0xe0, 0x00,             /* V-scaling incr luma low */
178         0xe1, 0x04,             /* " hi */
179         0xe2, 0x00,             /* V-scaling incr chroma low */
180         0xe3, 0x04,             /* " hi */
181
182         0x00, 0x00
183 };
184
185 static const unsigned char saa7115_cfg_60hz_video[] = {
186         0x80, 0x00,             /* reset tasks */
187         0x88, 0xd0,             /* reset scaler */
188
189         0x15, 0x03,             /* VGATE pulse start */
190         0x16, 0x11,             /* VGATE pulse stop */
191         0x17, 0x9c,             /* VGATE MSB and other values */
192
193         0x08, 0x68,             /* 0xBO: auto detection, 0x68 = NTSC */
194         0x0e, 0x07,             /* lots of different stuff... video autodetection is on */
195
196         0x5a, 0x06,             /* Vertical offset, standard 60hz value for ITU656 line counting */
197
198         /* Task A */
199         0x90, 0x80,             /* Task Handling Control */
200         0x91, 0x48,             /* X-port formats/config */
201         0x92, 0x40,             /* Input Ref. signal Def. */
202         0x93, 0x84,             /* I-port config */
203         0x94, 0x01,             /* hoffset low (input), 0x0002 is minimum */
204         0x95, 0x00,             /* hoffset hi (input) */
205         0x96, 0xd0,             /* hsize low (input), 0x02d0 = 720 */
206         0x97, 0x02,             /* hsize hi (input) */
207         0x98, 0x05,             /* voffset low (input) */
208         0x99, 0x00,             /* voffset hi (input) */
209         0x9a, 0x0c,             /* vsize low (input), 0x0c = 12 */
210         0x9b, 0x00,             /* vsize hi (input) */
211         0x9c, 0xa0,             /* hsize low (output), 0x05a0 = 1440 */
212         0x9d, 0x05,             /* hsize hi (output) */
213         0x9e, 0x0c,             /* vsize low (output), 0x0c = 12 */
214         0x9f, 0x00,             /* vsize hi (output) */
215
216         /* Task B */
217         0xc0, 0x00,             /* Task Handling Control */
218         0xc1, 0x08,             /* X-port formats/config */
219         0xc2, 0x00,             /* Input Ref. signal Def. */
220         0xc3, 0x80,             /* I-port config */
221         0xc4, 0x02,             /* hoffset low (input), 0x0002 is minimum */
222         0xc5, 0x00,             /* hoffset hi (input) */
223         0xc6, 0xd0,             /* hsize low (input), 0x02d0 = 720 */
224         0xc7, 0x02,             /* hsize hi (input) */
225         0xc8, 0x12,             /* voffset low (input), 0x12 = 18 */
226         0xc9, 0x00,             /* voffset hi (input) */
227         0xca, 0xf8,             /* vsize low (input), 0xf8 = 248 */
228         0xcb, 0x00,             /* vsize hi (input) */
229         0xcc, 0xd0,             /* hsize low (output), 0x02d0 = 720 */
230         0xcd, 0x02,             /* hsize hi (output) */
231
232         0xf0, 0xad,             /* Set PLL Register. 60hz 525 lines per frame, 27 MHz */
233         0xf1, 0x05,             /* low bit with 0xF0 */
234         0xf5, 0xad,             /* Set pulse generator register */
235         0xf6, 0x01,
236
237         0x87, 0x00,             /* Disable I-port output */
238         0x88, 0xd0,             /* reset scaler */
239         0x80, 0x20,             /* Activate only task "B", continuous mode (was 0xA0) */
240         0x88, 0xf0,             /* activate scaler */
241         0x87, 0x01,             /* Enable I-port output */
242         0x00, 0x00
243 };
244
245 static const unsigned char saa7115_cfg_50hz_fullres_x[] = {
246         0xcc, 0xd0,             /* hsize low (output), 720 same as 60hz */
247         0xcd, 0x02,             /* hsize hi (output) */
248
249         0xd0, 0x01,             /* down scale = 1 */
250         0xd8, 0x00,             /* hor lum scaling 0x0400 = 1 */
251         0xd9, 0x04,
252         0xdc, 0x00,             /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */
253         0xdd, 0x02,             /* H-scaling incr chroma */
254
255         0x00, 0x00
256 };
257 static const unsigned char saa7115_cfg_50hz_fullres_y[] = {
258         0xce, 0x20,             /* vsize low (output), 0x0120 = 288 */
259         0xcf, 0x01,             /* vsize hi (output) */
260
261         0xd5, 0x40,             /* Lum contrast, nominal value = 0x40 */
262         0xd6, 0x40,             /* Chroma satur. nominal value = 0x80 */
263
264         0xe0, 0x00,             /* V-scaling incr luma low */
265         0xe1, 0x04,             /* " hi */
266         0xe2, 0x00,             /* V-scaling incr chroma low */
267         0xe3, 0x04,             /* " hi */
268
269         0x00, 0x00
270 };
271
272 static const unsigned char saa7115_cfg_50hz_video[] = {
273         0x80, 0x00,             /* reset tasks */
274         0x88, 0xd0,             /* reset scaler */
275
276         0x15, 0x37,             /* VGATE start */
277         0x16, 0x16,             /* VGATE stop */
278         0x17, 0x99,             /* VGATE MSB and other values */
279
280         0x08, 0x28,             /* 0x28 = PAL */
281         0x0e, 0x07,             /* chrominance control 1 */
282
283         0x5a, 0x03,             /* Vertical offset, standard 50hz value */
284
285         /* Task A */
286         0x90, 0x81,             /* Task Handling Control */
287         0x91, 0x48,             /* X-port formats/config */
288         0x92, 0x40,             /* Input Ref. signal Def. */
289         0x93, 0x84,             /* I-port config */
290         /* This is weird: the datasheet says that you should use 2 as the minimum value, */
291         /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
292         0x94, 0x00,             /* hoffset low (input), 0x0002 is minimum */
293         0x95, 0x00,             /* hoffset hi (input) */
294         0x96, 0xd0,             /* hsize low (input), 0x02d0 = 720 */
295         0x97, 0x02,             /* hsize hi (input) */
296         0x98, 0x03,             /* voffset low (input) */
297         0x99, 0x00,             /* voffset hi (input) */
298         0x9a, 0x12,             /* vsize low (input), 0x12 = 18 */
299         0x9b, 0x00,             /* vsize hi (input) */
300         0x9c, 0xa0,             /* hsize low (output), 0x05a0 = 1440 */
301         0x9d, 0x05,             /* hsize hi (output) */
302         0x9e, 0x12,             /* vsize low (output), 0x12 = 18 */
303         0x9f, 0x00,             /* vsize hi (output) */
304
305         /* Task B */
306         0xc0, 0x00,             /* Task Handling Control */
307         0xc1, 0x08,             /* X-port formats/config */
308         0xc2, 0x00,             /* Input Ref. signal Def. */
309         0xc3, 0x80,             /* I-port config */
310         0xc4, 0x00,             /* hoffset low (input), 0x0002 is minimum. See comment at 0x94 above. */
311         0xc5, 0x00,             /* hoffset hi (input) */
312         0xc6, 0xd0,             /* hsize low (input), 0x02d0 = 720 */
313         0xc7, 0x02,             /* hsize hi (input) */
314         0xc8, 0x16,             /* voffset low (input), 0x16 = 22 */
315         0xc9, 0x00,             /* voffset hi (input) */
316         0xca, 0x20,             /* vsize low (input), 0x0120 = 288 */
317         0xcb, 0x01,             /* vsize hi (input) */
318         0xcc, 0xd0,             /* hsize low (output), 0x02d0 = 720 */
319         0xcd, 0x02,             /* hsize hi (output) */
320         0xce, 0x20,             /* vsize low (output), 0x0120 = 288 */
321         0xcf, 0x01,             /* vsize hi (output) */
322
323         0xf0, 0xb0,             /* Set PLL Register. 50hz 625 lines per frame, 27 MHz */
324         0xf1, 0x05,             /* low bit with 0xF0, (was 0x05) */
325         0xf5, 0xb0,             /* Set pulse generator register */
326         0xf6, 0x01,
327
328         0x87, 0x00,             /* Disable I-port output */
329         0x88, 0xd0,             /* reset scaler (was 0xD0) */
330         0x80, 0x20,             /* Activate only task "B" */
331         0x88, 0xf0,             /* activate scaler */
332         0x87, 0x01,             /* Enable I-port output */
333         0x00, 0x00
334 };
335
336 /* ============== SAA7715 VIDEO templates (end) =======  */
337
338 static const unsigned char saa7115_cfg_vbi_on[] = {
339         0x80, 0x00,             /* reset tasks */
340         0x88, 0xd0,             /* reset scaler */
341         0x80, 0x30,             /* Activate both tasks */
342         0x88, 0xf0,             /* activate scaler */
343         0x87, 0x01,             /* Enable I-port output */
344         0x00, 0x00
345 };
346
347 static const unsigned char saa7115_cfg_vbi_off[] = {
348         0x80, 0x00,             /* reset tasks */
349         0x88, 0xd0,             /* reset scaler */
350         0x80, 0x20,             /* Activate only task "B" */
351         0x88, 0xf0,             /* activate scaler */
352         0x87, 0x01,             /* Enable I-port output */
353         0x00, 0x00
354 };
355
356 static const unsigned char saa7115_init_misc[] = {
357         0x38, 0x03,             /* audio stuff */
358         0x39, 0x10,
359         0x3a, 0x08,
360
361         0x81, 0x01,             /* reg 0x15,0x16 define blanking window */
362         0x82, 0x00,
363         0x83, 0x01,             /* I port settings */
364         0x84, 0x20,
365         0x85, 0x21,
366         0x86, 0xc5,
367         0x87, 0x01,
368
369         /* Task A */
370         0xa0, 0x01,             /* down scale = 1 */
371         0xa1, 0x00,             /* prescale accumulation length = 1 */
372         0xa2, 0x00,             /* dc gain and fir prefilter control */
373         0xa4, 0x80,             /* Lum Brightness, nominal value = 0x80 */
374         0xa5, 0x40,             /* Lum contrast, nominal value = 0x40 */
375         0xa6, 0x40,             /* Chroma satur. nominal value = 0x80 */
376         0xa8, 0x00,             /* hor lum scaling 0x0200 = 2 zoom */
377         0xa9, 0x02,             /* note: 2 x zoom ensures that VBI lines have same length as video lines. */
378         0xaa, 0x00,             /* H-phase offset Luma = 0 */
379         0xac, 0x00,             /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */
380         0xad, 0x01,             /* H-scaling incr chroma */
381         0xae, 0x00,             /* H-phase offset chroma. must be offset luma / 2 */
382
383         0xb0, 0x00,             /* V-scaling incr luma low */
384         0xb1, 0x04,             /* " hi */
385         0xb2, 0x00,             /* V-scaling incr chroma low */
386         0xb3, 0x04,             /* " hi */
387         0xb4, 0x01,             /* V-scaling mode control */
388         0xb8, 0x00,             /* V-phase offset chroma 00 */
389         0xb9, 0x00,             /* V-phase offset chroma 01 */
390         0xba, 0x00,             /* V-phase offset chroma 10 */
391         0xbb, 0x00,             /* V-phase offset chroma 11 */
392         0xbc, 0x00,             /* V-phase offset luma 00 */
393         0xbd, 0x00,             /* V-phase offset luma 01 */
394         0xbe, 0x00,             /* V-phase offset luma 10 */
395         0xbf, 0x00,             /* V-phase offset luma 11 */
396
397         /* Task B */
398         0xd0, 0x01,             /* down scale = 1 */
399         0xd1, 0x00,             /* prescale accumulation length = 1 */
400         0xd2, 0x00,             /* dc gain and fir prefilter control */
401         0xd4, 0x80,             /* Lum Brightness, nominal value = 0x80 */
402         0xd5, 0x40,             /* Lum contrast, nominal value = 0x40 */
403         0xd6, 0x40,             /* Chroma satur. nominal value = 0x80 */
404         0xd8, 0x00,             /* hor lum scaling 0x0400 = 1 */
405         0xd9, 0x04,
406         0xda, 0x00,             /* H-phase offset Luma = 0 */
407         0xdc, 0x00,             /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */
408         0xdd, 0x02,             /* H-scaling incr chroma */
409         0xde, 0x00,             /* H-phase offset chroma. must be offset luma / 2 */
410
411         0xe0, 0x00,             /* V-scaling incr luma low */
412         0xe1, 0x04,             /* " hi */
413         0xe2, 0x00,             /* V-scaling incr chroma low */
414         0xe3, 0x04,             /* " hi */
415         0xe4, 0x01,             /* V-scaling mode control */
416         0xe8, 0x00,             /* V-phase offset chroma 00 */
417         0xe9, 0x00,             /* V-phase offset chroma 01 */
418         0xea, 0x00,             /* V-phase offset chroma 10 */
419         0xeb, 0x00,             /* V-phase offset chroma 11 */
420         0xec, 0x00,             /* V-phase offset luma 00 */
421         0xed, 0x00,             /* V-phase offset luma 01 */
422         0xee, 0x00,             /* V-phase offset luma 10 */
423         0xef, 0x00,             /* V-phase offset luma 11 */
424
425         0xf2, 0x50,             /* crystal clock = 24.576 MHz, target = 27MHz */
426         0xf3, 0x46,
427         0xf4, 0x00,
428         0xf7, 0x4b,             /* not the recommended settings! */
429         0xf8, 0x00,
430         0xf9, 0x4b,
431         0xfa, 0x00,
432         0xfb, 0x4b,
433         0xff, 0x88,             /* PLL2 lock detection settings: 71 lines 50% phase error */
434
435         /* Turn off VBI */
436         0x40, 0x20,             /* No framing code errors allowed. */
437         0x41, 0xff,
438         0x42, 0xff,
439         0x43, 0xff,
440         0x44, 0xff,
441         0x45, 0xff,
442         0x46, 0xff,
443         0x47, 0xff,
444         0x48, 0xff,
445         0x49, 0xff,
446         0x4a, 0xff,
447         0x4b, 0xff,
448         0x4c, 0xff,
449         0x4d, 0xff,
450         0x4e, 0xff,
451         0x4f, 0xff,
452         0x50, 0xff,
453         0x51, 0xff,
454         0x52, 0xff,
455         0x53, 0xff,
456         0x54, 0xff,
457         0x55, 0xff,
458         0x56, 0xff,
459         0x57, 0xff,
460         0x58, 0x40,
461         0x59, 0x47,
462         0x5b, 0x83,
463         0x5d, 0xbd,
464         0x5e, 0x35,
465
466         0x02, 0x84,             /* input tuner -> input 4, amplifier active */
467         0x09, 0x53,             /* 0x53, was 0x56 for 60hz. luminance control */
468
469         0x80, 0x20,             /* enable task B */
470         0x88, 0xd0,
471         0x88, 0xf0,
472         0x00, 0x00
473 };
474
475 /* ============== SAA7715 AUDIO settings ============= */
476
477 /* 48.0 kHz */
478 static const unsigned char saa7115_cfg_48_audio[] = {
479         0x34, 0xce,
480         0x35, 0xfb,
481         0x36, 0x30,
482         0x00, 0x00
483 };
484
485 /* 44.1 kHz */
486 static const unsigned char saa7115_cfg_441_audio[] = {
487         0x34, 0xf2,
488         0x35, 0x00,
489         0x36, 0x2d,
490         0x00, 0x00
491 };
492
493 /* 32.0 kHz */
494 static const unsigned char saa7115_cfg_32_audio[] = {
495         0x34, 0xdf,
496         0x35, 0xa7,
497         0x36, 0x20,
498         0x00, 0x00
499 };
500
501 /* 48.0 kHz 60hz */
502 static const unsigned char saa7115_cfg_60hz_48_audio[] = {
503         0x30, 0xcd,
504         0x31, 0x20,
505         0x32, 0x03,
506         0x00, 0x00
507 };
508
509 /* 48.0 kHz 50hz */
510 static const unsigned char saa7115_cfg_50hz_48_audio[] = {
511         0x30, 0x00,
512         0x31, 0xc0,
513         0x32, 0x03,
514         0x00, 0x00
515 };
516
517 /* 44.1 kHz 60hz */
518 static const unsigned char saa7115_cfg_60hz_441_audio[] = {
519         0x30, 0xbc,
520         0x31, 0xdf,
521         0x32, 0x02,
522         0x00, 0x00
523 };
524
525 /* 44.1 kHz 50hz */
526 static const unsigned char saa7115_cfg_50hz_441_audio[] = {
527         0x30, 0x00,
528         0x31, 0x72,
529         0x32, 0x03,
530         0x00, 0x00
531 };
532
533 /* 32.0 kHz 60hz */
534 static const unsigned char saa7115_cfg_60hz_32_audio[] = {
535         0x30, 0xde,
536         0x31, 0x15,
537         0x32, 0x02,
538         0x00, 0x00
539 };
540
541 /* 32.0 kHz 50hz */
542 static const unsigned char saa7115_cfg_50hz_32_audio[] = {
543         0x30, 0x00,
544         0x31, 0x80,
545         0x32, 0x02,
546         0x00, 0x00
547 };
548
549 static int saa7115_odd_parity(u8 c)
550 {
551         c ^= (c >> 4);
552         c ^= (c >> 2);
553         c ^= (c >> 1);
554
555         return c & 1;
556 }
557
558 static int saa7115_decode_vps(u8 * dst, u8 * p)
559 {
560         static const u8 biphase_tbl[] = {
561                 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
562                 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
563                 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
564                 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
565                 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
566                 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
567                 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
568                 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
569                 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
570                 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
571                 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
572                 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
573                 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
574                 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
575                 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
576                 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
577                 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
578                 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
579                 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
580                 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
581                 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
582                 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
583                 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
584                 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
585                 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
586                 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
587                 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
588                 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
589                 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
590                 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
591                 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
592                 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
593         };
594         int i;
595         u8 c, err = 0;
596
597         for (i = 0; i < 2 * 13; i += 2) {
598                 err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
599                 c = (biphase_tbl[p[i + 1]] & 0xf) | ((biphase_tbl[p[i]] & 0xf) << 4);
600                 dst[i / 2] = c;
601         }
602         return err & 0xf0;
603 }
604
605 static int saa7115_decode_wss(u8 * p)
606 {
607         static const int wss_bits[8] = {
608                 0, 0, 0, 1, 0, 1, 1, 1
609         };
610         unsigned char parity;
611         int wss = 0;
612         int i;
613
614         for (i = 0; i < 16; i++) {
615                 int b1 = wss_bits[p[i] & 7];
616                 int b2 = wss_bits[(p[i] >> 3) & 7];
617
618                 if (b1 == b2)
619                         return -1;
620                 wss |= b2 << i;
621         }
622         parity = wss & 15;
623         parity ^= parity >> 2;
624         parity ^= parity >> 1;
625
626         if (!(parity & 1))
627                 return -1;
628
629         return wss;
630 }
631
632
633 static int saa7115_set_audio_clock_freq(struct i2c_client *client, enum v4l2_audio_clock_freq freq)
634 {
635         struct saa7115_state *state = i2c_get_clientdata(client);
636
637         saa7115_dbg("set audio clock freq: %d\n", freq);
638         switch (freq) {
639                 case V4L2_AUDCLK_32_KHZ:
640                         saa7115_writeregs(client, saa7115_cfg_32_audio);
641                         if (state->std & V4L2_STD_525_60) {
642                                 saa7115_writeregs(client, saa7115_cfg_60hz_32_audio);
643                         } else {
644                                 saa7115_writeregs(client, saa7115_cfg_50hz_32_audio);
645                         }
646                         break;
647                 case V4L2_AUDCLK_441_KHZ:
648                         saa7115_writeregs(client, saa7115_cfg_441_audio);
649                         if (state->std & V4L2_STD_525_60) {
650                                 saa7115_writeregs(client, saa7115_cfg_60hz_441_audio);
651                         } else {
652                                 saa7115_writeregs(client, saa7115_cfg_50hz_441_audio);
653                         }
654                         break;
655                 case V4L2_AUDCLK_48_KHZ:
656                         saa7115_writeregs(client, saa7115_cfg_48_audio);
657                         if (state->std & V4L2_STD_525_60) {
658                                 saa7115_writeregs(client, saa7115_cfg_60hz_48_audio);
659                         } else {
660                                 saa7115_writeregs(client, saa7115_cfg_50hz_48_audio);
661                         }
662                         break;
663                 default:
664                         saa7115_dbg("invalid audio setting %d\n", freq);
665                         return -EINVAL;
666         }
667         state->audclk_freq = freq;
668         return 0;
669 }
670
671 static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
672 {
673         struct saa7115_state *state = i2c_get_clientdata(client);
674
675         switch (ctrl->id) {
676         case V4L2_CID_BRIGHTNESS:
677                 if (ctrl->value < 0 || ctrl->value > 255) {
678                         saa7115_err("invalid brightness setting %d\n", ctrl->value);
679                         return -ERANGE;
680                 }
681
682                 state->bright = ctrl->value;
683                 saa7115_write(client, 0x0a, state->bright);
684                 break;
685
686         case V4L2_CID_CONTRAST:
687                 if (ctrl->value < 0 || ctrl->value > 127) {
688                         saa7115_err("invalid contrast setting %d\n", ctrl->value);
689                         return -ERANGE;
690                 }
691
692                 state->contrast = ctrl->value;
693                 saa7115_write(client, 0x0b, state->contrast);
694                 break;
695
696         case V4L2_CID_SATURATION:
697                 if (ctrl->value < 0 || ctrl->value > 127) {
698                         saa7115_err("invalid saturation setting %d\n", ctrl->value);
699                         return -ERANGE;
700                 }
701
702                 state->sat = ctrl->value;
703                 saa7115_write(client, 0x0c, state->sat);
704                 break;
705
706         case V4L2_CID_HUE:
707                 if (ctrl->value < -127 || ctrl->value > 127) {
708                         saa7115_err("invalid hue setting %d\n", ctrl->value);
709                         return -ERANGE;
710                 }
711
712                 state->hue = ctrl->value;
713                 saa7115_write(client, 0x0d, state->hue);
714                 break;
715         }
716
717         return 0;
718 }
719
720 static int saa7115_get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
721 {
722         struct saa7115_state *state = i2c_get_clientdata(client);
723
724         switch (ctrl->id) {
725         case V4L2_CID_BRIGHTNESS:
726                 ctrl->value = state->bright;
727                 break;
728         case V4L2_CID_CONTRAST:
729                 ctrl->value = state->contrast;
730                 break;
731         case V4L2_CID_SATURATION:
732                 ctrl->value = state->sat;
733                 break;
734         case V4L2_CID_HUE:
735                 ctrl->value = state->hue;
736                 break;
737         default:
738                 return -EINVAL;
739         }
740
741         return 0;
742 }
743
744 static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
745 {
746         struct saa7115_state *state = i2c_get_clientdata(client);
747         int taskb = saa7115_read(client, 0x80) & 0x10;
748
749         // This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
750         if (std & V4L2_STD_525_60) {
751                 saa7115_dbg("decoder set standard 60 Hz\n");
752                 saa7115_writeregs(client, saa7115_cfg_60hz_video);
753         } else {
754                 saa7115_dbg("decoder set standard 50 Hz\n");
755                 saa7115_writeregs(client, saa7115_cfg_50hz_video);
756         }
757
758         state->std = std;
759
760         /* restart task B if needed */
761         if (taskb && state->ident == V4L2_IDENT_SAA7114) {
762                 saa7115_writeregs(client, saa7115_cfg_vbi_on);
763         }
764
765         /* switch audio mode too! */
766         saa7115_set_audio_clock_freq(client, state->audclk_freq);
767 }
768
769 static v4l2_std_id saa7115_get_v4lstd(struct i2c_client *client)
770 {
771         struct saa7115_state *state = i2c_get_clientdata(client);
772
773         return state->std;
774 }
775
776 static void saa7115_log_status(struct i2c_client *client)
777 {
778         static const char * const audclk_freq_strs[] = {
779                 "44.1 kHz",
780                 "48 kHz",
781                 "32 kHz"
782         };
783         struct saa7115_state *state = i2c_get_clientdata(client);
784         int reg1e, reg1f;
785         int signalOk;
786         int vcr;
787
788         saa7115_info("Audio frequency: %s\n", audclk_freq_strs[state->audclk_freq]);
789         if (client->name[6] == '4') {
790                 /* status for the saa7114 */
791                 reg1f = saa7115_read(client, 0x1f);
792                 signalOk = (reg1f & 0xc1) == 0x81;
793                 saa7115_info("Video signal:    %s\n", signalOk ? "ok" : "bad");
794                 saa7115_info("Frequency:       %s\n", (reg1f & 0x20) ? "60Hz" : "50Hz");
795                 return;
796         }
797
798         /* status for the saa7115 */
799         reg1e = saa7115_read(client, 0x1e);
800         reg1f = saa7115_read(client, 0x1f);
801
802         signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
803         vcr = !(reg1f & 0x10);
804
805         saa7115_info("Video signal:    %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
806         saa7115_info("Frequency:       %s\n", (reg1f & 0x20) ? "60Hz" : "50Hz");
807
808         switch (reg1e & 0x03) {
809                 case 1:
810                         saa7115_info("Detected format: NTSC\n");
811                         break;
812                 case 2:
813                         saa7115_info("Detected format: PAL\n");
814                         break;
815                 case 3:
816                         saa7115_info("Detected format: SECAM\n");
817                         break;
818                 default:
819                         saa7115_info("Detected format: BW/No color\n");
820                         break;
821         }
822 }
823
824 /* setup the sliced VBI lcr registers according to the sliced VBI format */
825 static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_format *fmt)
826 {
827         struct saa7115_state *state = i2c_get_clientdata(client);
828         int is_50hz = (state->std & V4L2_STD_625_50);
829         u8 lcr[24];
830         int i, x;
831
832         /* saa7114 doesn't yet support VBI */
833         if (state->ident == V4L2_IDENT_SAA7114)
834                 return;
835
836         for (i = 0; i <= 23; i++)
837                 lcr[i] = 0xff;
838
839         if (fmt->service_set == 0) {
840                 /* raw VBI */
841                 if (is_50hz)
842                         for (i = 6; i <= 23; i++)
843                                 lcr[i] = 0xdd;
844                 else
845                         for (i = 10; i <= 21; i++)
846                                 lcr[i] = 0xdd;
847         } else {
848                 /* sliced VBI */
849                 /* first clear lines that cannot be captured */
850                 if (is_50hz) {
851                         for (i = 0; i <= 5; i++)
852                                 fmt->service_lines[0][i] =
853                                         fmt->service_lines[1][i] = 0;
854                 }
855                 else {
856                         for (i = 0; i <= 9; i++)
857                                 fmt->service_lines[0][i] =
858                                         fmt->service_lines[1][i] = 0;
859                         for (i = 22; i <= 23; i++)
860                                 fmt->service_lines[0][i] =
861                                         fmt->service_lines[1][i] = 0;
862                 }
863
864                 /* Now set the lcr values according to the specified service */
865                 for (i = 6; i <= 23; i++) {
866                         lcr[i] = 0;
867                         for (x = 0; x <= 1; x++) {
868                                 switch (fmt->service_lines[1-x][i]) {
869                                         case 0:
870                                                 lcr[i] |= 0xf << (4 * x);
871                                                 break;
872                                         case V4L2_SLICED_TELETEXT_B:
873                                                 lcr[i] |= 1 << (4 * x);
874                                                 break;
875                                         case V4L2_SLICED_CAPTION_525:
876                                                 lcr[i] |= 4 << (4 * x);
877                                                 break;
878                                         case V4L2_SLICED_WSS_625:
879                                                 lcr[i] |= 5 << (4 * x);
880                                                 break;
881                                         case V4L2_SLICED_VPS:
882                                                 lcr[i] |= 7 << (4 * x);
883                                                 break;
884                                 }
885                         }
886                 }
887         }
888
889         /* write the lcr registers */
890         for (i = 2; i <= 23; i++) {
891                 saa7115_write(client, i - 2 + 0x41, lcr[i]);
892         }
893
894         /* enable/disable raw VBI capturing */
895         saa7115_writeregs(client, fmt->service_set == 0 ? saa7115_cfg_vbi_on : saa7115_cfg_vbi_off);
896 }
897
898 static int saa7115_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
899 {
900         static u16 lcr2vbi[] = {
901                 0, V4L2_SLICED_TELETEXT_B, 0,   /* 1 */
902                 0, V4L2_SLICED_CAPTION_525,     /* 4 */
903                 V4L2_SLICED_WSS_625, 0,         /* 5 */
904                 V4L2_SLICED_VPS, 0, 0, 0, 0,    /* 7 */
905                 0, 0, 0, 0
906         };
907         struct v4l2_sliced_vbi_format *sliced = &fmt->fmt.sliced;
908         int i;
909
910         if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
911                 return -EINVAL;
912         memset(sliced, 0, sizeof(*sliced));
913         /* done if using raw VBI */
914         if (saa7115_read(client, 0x80) & 0x10)
915                 return 0;
916         for (i = 2; i <= 23; i++) {
917                 u8 v = saa7115_read(client, i - 2 + 0x41);
918
919                 sliced->service_lines[0][i] = lcr2vbi[v >> 4];
920                 sliced->service_lines[1][i] = lcr2vbi[v & 0xf];
921                 sliced->service_set |=
922                         sliced->service_lines[0][i] | sliced->service_lines[1][i];
923         }
924         return 0;
925 }
926
927 static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
928 {
929         struct saa7115_state *state = i2c_get_clientdata(client);
930         struct v4l2_pix_format *pix;
931         int HPSC, HFSC;
932         int VSCY, Vsrc;
933         int is_50hz = state->std & V4L2_STD_625_50;
934
935         if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
936                 saa7115_set_lcr(client, &fmt->fmt.sliced);
937                 return 0;
938         }
939         if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
940                 return -EINVAL;
941
942         pix = &(fmt->fmt.pix);
943
944         saa7115_dbg("decoder set size\n");
945
946         /* FIXME need better bounds checking here */
947         if ((pix->width < 1) || (pix->width > 1440))
948                 return -EINVAL;
949         if ((pix->height < 1) || (pix->height > 960))
950                 return -EINVAL;
951
952         /* probably have a valid size, let's set it */
953         /* Set output width/height */
954         /* width */
955         saa7115_write(client, 0xcc, (u8) (pix->width & 0xff));
956         saa7115_write(client, 0xcd, (u8) ((pix->width >> 8) & 0xff));
957         /* height */
958         saa7115_write(client, 0xce, (u8) (pix->height & 0xff));
959         saa7115_write(client, 0xcf, (u8) ((pix->height >> 8) & 0xff));
960
961         /* Scaling settings */
962         /* Hprescaler is floor(inres/outres) */
963         /* FIXME hardcoding input res */
964         if (pix->width != 720) {
965                 HPSC = (int)(720 / pix->width);
966                 /* 0 is not allowed (div. by zero) */
967                 HPSC = HPSC ? HPSC : 1;
968                 HFSC = (int)((1024 * 720) / (HPSC * pix->width));
969
970                 saa7115_dbg("Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
971                 /* FIXME hardcodes to "Task B"
972                  * write H prescaler integer */
973                 saa7115_write(client, 0xd0, (u8) (HPSC & 0x3f));
974
975                 /* write H fine-scaling (luminance) */
976                 saa7115_write(client, 0xd8, (u8) (HFSC & 0xff));
977                 saa7115_write(client, 0xd9, (u8) ((HFSC >> 8) & 0xff));
978                 /* write H fine-scaling (chrominance)
979                  * must be lum/2, so i'll just bitshift :) */
980                 saa7115_write(client, 0xDC, (u8) ((HFSC >> 1) & 0xff));
981                 saa7115_write(client, 0xDD, (u8) ((HFSC >> 9) & 0xff));
982         } else {
983                 if (is_50hz) {
984                         saa7115_dbg("Setting full 50hz width\n");
985                         saa7115_writeregs(client, saa7115_cfg_50hz_fullres_x);
986                 } else {
987                         saa7115_dbg("Setting full 60hz width\n");
988                         saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x);
989                 }
990         }
991
992         Vsrc = is_50hz ? 576 : 480;
993
994         if (pix->height != Vsrc) {
995                 VSCY = (int)((1024 * Vsrc) / pix->height);
996                 saa7115_dbg("Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
997
998                 /* Correct Contrast and Luminance */
999                 saa7115_write(client, 0xd5, (u8) (64 * 1024 / VSCY));
1000                 saa7115_write(client, 0xd6, (u8) (64 * 1024 / VSCY));
1001
1002                 /* write V fine-scaling (luminance) */
1003                 saa7115_write(client, 0xe0, (u8) (VSCY & 0xff));
1004                 saa7115_write(client, 0xe1, (u8) ((VSCY >> 8) & 0xff));
1005                 /* write V fine-scaling (chrominance) */
1006                 saa7115_write(client, 0xe2, (u8) (VSCY & 0xff));
1007                 saa7115_write(client, 0xe3, (u8) ((VSCY >> 8) & 0xff));
1008         } else {
1009                 if (is_50hz) {
1010                         saa7115_dbg("Setting full 50Hz height\n");
1011                         saa7115_writeregs(client, saa7115_cfg_50hz_fullres_y);
1012                 } else {
1013                         saa7115_dbg("Setting full 60hz height\n");
1014                         saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y);
1015                 }
1016         }
1017
1018         saa7115_writeregs(client, saa7115_cfg_reset_scaler);
1019         return 0;
1020 }
1021
1022 /* Decode the sliced VBI data stream as created by the saa7115.
1023    The format is described in the saa7115 datasheet in Tables 25 and 26
1024    and in Figure 33.
1025    The current implementation uses SAV/EAV codes and not the ancillary data
1026    headers. The vbi->p pointer points to the SDID byte right after the SAV
1027    code. */
1028 static void saa7115_decode_vbi_line(struct i2c_client *client,
1029                                     struct v4l2_decode_vbi_line *vbi)
1030 {
1031         static const char vbi_no_data_pattern[] = {
1032                 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0
1033         };
1034         struct saa7115_state *state = i2c_get_clientdata(client);
1035         u8 *p = vbi->p;
1036         u32 wss;
1037         int id1, id2;   /* the ID1 and ID2 bytes from the internal header */
1038
1039         vbi->type = 0;  /* mark result as a failure */
1040         id1 = p[2];
1041         id2 = p[3];
1042         /* Note: the field bit is inverted for 60 Hz video */
1043         if (state->std & V4L2_STD_525_60)
1044                 id1 ^= 0x40;
1045
1046         /* Skip internal header, p now points to the start of the payload */
1047         p += 4;
1048         vbi->p = p;
1049
1050         /* calculate field and line number of the VBI packet (1-23) */
1051         vbi->is_second_field = ((id1 & 0x40) != 0);
1052         vbi->line = (id1 & 0x3f) << 3;
1053         vbi->line |= (id2 & 0x70) >> 4;
1054
1055         /* Obtain data type */
1056         id2 &= 0xf;
1057
1058         /* If the VBI slicer does not detect any signal it will fill up
1059            the payload buffer with 0xa0 bytes. */
1060         if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern)))
1061                 return;
1062
1063         /* decode payloads */
1064         switch (id2) {
1065         case 1:
1066                 vbi->type = V4L2_SLICED_TELETEXT_B;
1067                 break;
1068         case 4:
1069                 if (!saa7115_odd_parity(p[0]) || !saa7115_odd_parity(p[1]))
1070                         return;
1071                 vbi->type = V4L2_SLICED_CAPTION_525;
1072                 break;
1073         case 5:
1074                 wss = saa7115_decode_wss(p);
1075                 if (wss == -1)
1076                         return;
1077                 p[0] = wss & 0xff;
1078                 p[1] = wss >> 8;
1079                 vbi->type = V4L2_SLICED_WSS_625;
1080                 break;
1081         case 7:
1082                 if (saa7115_decode_vps(p, p) != 0)
1083                         return;
1084                 vbi->type = V4L2_SLICED_VPS;
1085                 break;
1086         default:
1087                 return;
1088         }
1089 }
1090
1091 /* ============ SAA7115 AUDIO settings (end) ============= */
1092
1093 static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg)
1094 {
1095         struct saa7115_state *state = i2c_get_clientdata(client);
1096         int *iarg = arg;
1097
1098         /* ioctls to allow direct access to the saa7115 registers for testing */
1099         switch (cmd) {
1100         case VIDIOC_S_FMT:
1101                 return saa7115_set_v4lfmt(client, (struct v4l2_format *)arg);
1102
1103         case VIDIOC_G_FMT:
1104                 return saa7115_get_v4lfmt(client, (struct v4l2_format *)arg);
1105
1106         case VIDIOC_INT_AUDIO_CLOCK_FREQ:
1107                 return saa7115_set_audio_clock_freq(client, *(enum v4l2_audio_clock_freq *)arg);
1108
1109         case VIDIOC_G_TUNER:
1110         {
1111                 struct v4l2_tuner *vt = arg;
1112                 int status;
1113
1114                 status = saa7115_read(client, 0x1f);
1115
1116                 saa7115_dbg("status: 0x%02x\n", status);
1117                 vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
1118                 break;
1119         }
1120
1121         case VIDIOC_LOG_STATUS:
1122                 saa7115_log_status(client);
1123                 break;
1124
1125         case VIDIOC_G_CTRL:
1126                 return saa7115_get_v4lctrl(client, (struct v4l2_control *)arg);
1127
1128         case VIDIOC_S_CTRL:
1129                 return saa7115_set_v4lctrl(client, (struct v4l2_control *)arg);
1130
1131         case VIDIOC_G_STD:
1132                 *(v4l2_std_id *)arg = saa7115_get_v4lstd(client);
1133                 break;
1134
1135         case VIDIOC_S_STD:
1136                 saa7115_set_v4lstd(client, *(v4l2_std_id *)arg);
1137                 break;
1138
1139         case VIDIOC_G_INPUT:
1140                 *(int *)arg = state->input;
1141                 break;
1142
1143         case VIDIOC_S_INPUT:
1144                 saa7115_dbg("decoder set input %d\n", *iarg);
1145                 /* inputs from 0-9 are available */
1146                 if (*iarg < 0 || *iarg > 9) {
1147                         return -EINVAL;
1148                 }
1149
1150                 if (state->input == *iarg)
1151                         break;
1152                 saa7115_dbg("now setting %s input\n",
1153                         *iarg >= 6 ? "S-Video" : "Composite");
1154                 state->input = *iarg;
1155
1156                 /* select mode */
1157                 saa7115_write(client, 0x02,
1158                               (saa7115_read(client, 0x02) & 0xf0) |
1159                                state->input);
1160
1161                 /* bypass chrominance trap for modes 6..9 */
1162                 saa7115_write(client, 0x09,
1163                               (saa7115_read(client, 0x09) & 0x7f) |
1164                                (state->input < 6 ? 0x0 : 0x80));
1165                 break;
1166
1167         case VIDIOC_STREAMON:
1168         case VIDIOC_STREAMOFF:
1169                 saa7115_dbg("%s output\n",
1170                         (cmd == VIDIOC_STREAMON) ? "enable" : "disable");
1171
1172                 if (state->enable != (cmd == VIDIOC_STREAMON)) {
1173                         state->enable = (cmd == VIDIOC_STREAMON);
1174                         saa7115_write(client, 0x87, state->enable);
1175                 }
1176                 break;
1177
1178         case VIDIOC_INT_DECODE_VBI_LINE:
1179                 saa7115_decode_vbi_line(client, arg);
1180                 break;
1181
1182         case VIDIOC_INT_RESET:
1183                 saa7115_dbg("decoder RESET\n");
1184                 saa7115_writeregs(client, saa7115_cfg_reset_scaler);
1185                 break;
1186
1187         case VIDIOC_INT_G_VBI_DATA:
1188         {
1189                 struct v4l2_sliced_vbi_data *data = arg;
1190
1191                 switch (data->id) {
1192                 case V4L2_SLICED_WSS_625:
1193                         if (saa7115_read(client, 0x6b) & 0xc0)
1194                                 return -EIO;
1195                         data->data[0] = saa7115_read(client, 0x6c);
1196                         data->data[1] = saa7115_read(client, 0x6d);
1197                         return 0;
1198                 case V4L2_SLICED_CAPTION_525:
1199                         if (data->field == 0) {
1200                                 /* CC */
1201                                 if (saa7115_read(client, 0x66) & 0xc0)
1202                                         return -EIO;
1203                                 data->data[0] = saa7115_read(client, 0x67);
1204                                 data->data[1] = saa7115_read(client, 0x68);
1205                                 return 0;
1206                         }
1207                         /* XDS */
1208                         if (saa7115_read(client, 0x66) & 0x30)
1209                                 return -EIO;
1210                         data->data[0] = saa7115_read(client, 0x69);
1211                         data->data[1] = saa7115_read(client, 0x6a);
1212                         return 0;
1213                 default:
1214                         return -EINVAL;
1215                 }
1216                 break;
1217         }
1218
1219 #ifdef CONFIG_VIDEO_ADV_DEBUG
1220         case VIDIOC_INT_G_REGISTER:
1221         {
1222                 struct v4l2_register *reg = arg;
1223
1224                 if (reg->i2c_id != I2C_DRIVERID_SAA711X)
1225                         return -EINVAL;
1226                 reg->val = saa7115_read(client, reg->reg & 0xff);
1227                 break;
1228         }
1229
1230         case VIDIOC_INT_S_REGISTER:
1231         {
1232                 struct v4l2_register *reg = arg;
1233
1234                 if (reg->i2c_id != I2C_DRIVERID_SAA711X)
1235                         return -EINVAL;
1236                 if (!capable(CAP_SYS_ADMIN))
1237                         return -EPERM;
1238                 saa7115_write(client, reg->reg & 0xff, reg->val & 0xff);
1239                 break;
1240         }
1241 #endif
1242
1243         case VIDIOC_INT_G_CHIP_IDENT:
1244                 *iarg = state->ident;
1245                 break;
1246
1247         default:
1248                 return -EINVAL;
1249         }
1250
1251         return 0;
1252 }
1253
1254 /* ----------------------------------------------------------------------- */
1255
1256 static struct i2c_driver i2c_driver_saa7115;
1257
1258 static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
1259 {
1260         struct i2c_client *client;
1261         struct saa7115_state *state;
1262         u8 chip_id;
1263
1264         /* Check if the adapter supports the needed features */
1265         if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
1266                 return 0;
1267
1268         client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
1269         if (client == 0)
1270                 return -ENOMEM;
1271         memset(client, 0, sizeof(struct i2c_client));
1272         client->addr = address;
1273         client->adapter = adapter;
1274         client->driver = &i2c_driver_saa7115;
1275         client->flags = I2C_CLIENT_ALLOW_USE;
1276         snprintf(client->name, sizeof(client->name) - 1, "saa7115");
1277
1278         saa7115_dbg("detecting saa7115 client on address 0x%x\n", address << 1);
1279
1280         saa7115_write(client, 0, 5);
1281         chip_id = saa7115_read(client, 0) & 0x0f;
1282         if (chip_id != 4 && chip_id != 5) {
1283                 saa7115_dbg("saa7115 not found\n");
1284                 kfree(client);
1285                 return 0;
1286         }
1287         if (chip_id == 4) {
1288                 snprintf(client->name, sizeof(client->name) - 1, "saa7114");
1289         }
1290         saa7115_info("saa711%d found @ 0x%x (%s)\n", chip_id, address << 1, adapter->name);
1291
1292         state = kmalloc(sizeof(struct saa7115_state), GFP_KERNEL);
1293         i2c_set_clientdata(client, state);
1294         if (state == NULL) {
1295                 kfree(client);
1296                 return -ENOMEM;
1297         }
1298         memset(state, 0, sizeof(struct saa7115_state));
1299         state->std = V4L2_STD_NTSC;
1300         state->input = -1;
1301         state->enable = 1;
1302         state->bright = 128;
1303         state->contrast = 64;
1304         state->hue = 0;
1305         state->sat = 64;
1306         state->ident = (chip_id == 4) ? V4L2_IDENT_SAA7114 : V4L2_IDENT_SAA7115;
1307         state->audclk_freq = V4L2_AUDCLK_48_KHZ;
1308
1309         saa7115_dbg("writing init values\n");
1310
1311         /* init to 60hz/48khz */
1312         saa7115_writeregs(client, saa7115_init_auto_input);
1313         saa7115_writeregs(client, saa7115_init_misc);
1314         saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x);
1315         saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y);
1316         saa7115_writeregs(client, saa7115_cfg_60hz_video);
1317         saa7115_writeregs(client, saa7115_cfg_48_audio);
1318         saa7115_writeregs(client, saa7115_cfg_60hz_48_audio);
1319         saa7115_writeregs(client, saa7115_cfg_reset_scaler);
1320
1321         i2c_attach_client(client);
1322
1323         saa7115_dbg("status: (1E) 0x%02x, (1F) 0x%02x\n",
1324                 saa7115_read(client, 0x1e), saa7115_read(client, 0x1f));
1325
1326         return 0;
1327 }
1328
1329 static int saa7115_probe(struct i2c_adapter *adapter)
1330 {
1331 #ifdef I2C_CLASS_TV_ANALOG
1332         if (adapter->class & I2C_CLASS_TV_ANALOG)
1333 #else
1334         if (adapter->id == I2C_HW_B_BT848)
1335 #endif
1336                 return i2c_probe(adapter, &addr_data, &saa7115_attach);
1337         return 0;
1338 }
1339
1340 static int saa7115_detach(struct i2c_client *client)
1341 {
1342         struct saa7115_state *state = i2c_get_clientdata(client);
1343         int err;
1344
1345         err = i2c_detach_client(client);
1346         if (err) {
1347                 return err;
1348         }
1349
1350         kfree(state);
1351         kfree(client);
1352         return 0;
1353 }
1354
1355 /* ----------------------------------------------------------------------- */
1356
1357 /* i2c implementation */
1358 static struct i2c_driver i2c_driver_saa7115 = {
1359         .name = "saa7115",
1360         .id = I2C_DRIVERID_SAA711X,
1361         .flags = I2C_DF_NOTIFY,
1362         .attach_adapter = saa7115_probe,
1363         .detach_client = saa7115_detach,
1364         .command = saa7115_command,
1365         .owner = THIS_MODULE,
1366 };
1367
1368
1369 static int __init saa7115_init_module(void)
1370 {
1371         return i2c_add_driver(&i2c_driver_saa7115);
1372 }
1373
1374 static void __exit saa7115_cleanup_module(void)
1375 {
1376         i2c_del_driver(&i2c_driver_saa7115);
1377 }
1378
1379 module_init(saa7115_init_module);
1380 module_exit(saa7115_cleanup_module);