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