1 /* saa7115 - Philips SAA7114/SAA7115 video decoder driver
3 * Based on saa7114 driver by Maxim Yevtyushkin, which is based on
4 * the saa7111 driver by Dave Perks.
6 * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
7 * Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com>
9 * Slight changes for video timing and attachment output by
10 * Wolfgang Scherr <scherr@net4you.net>
12 * Moved over to the linux >= 2.4.x i2c protocol (1/1/2003)
13 * by Ronald Bultje <rbultje@ronald.bitfreak.net>
15 * Added saa7115 support by Kevin Thayer <nufan_wfk at yahoo.com>
18 * VBI support (2004) and cleanups (2005) by Hans Verkuil <hverkuil@xs4all.nl>
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.
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.
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.
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 #include <asm/div64.h>
44 MODULE_DESCRIPTION("Philips SAA7114/SAA7115 video decoder driver");
45 MODULE_AUTHOR("Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, Hans Verkuil");
46 MODULE_LICENSE("GPL");
49 module_param(debug, int, 0644);
51 MODULE_PARM_DESC(debug, "Debug level (0-1)");
53 #define saa7115_dbg(fmt,arg...) \
56 printk(KERN_INFO "%s debug %d-%04x: " fmt, \
57 client->driver->driver.name, \
58 i2c_adapter_id(client->adapter), client->addr , ## arg); \
61 #define saa7115_err(fmt, arg...) do { \
62 printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \
63 i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
64 #define saa7115_info(fmt, arg...) do { \
65 printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \
66 i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
68 static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END };
73 struct saa7115_state {
82 enum v4l2_chip_ident ident;
86 /* ----------------------------------------------------------------------- */
88 static inline int saa7115_write(struct i2c_client *client, u8 reg, u8 value)
90 return i2c_smbus_write_byte_data(client, reg, value);
93 static int saa7115_writeregs(struct i2c_client *client, const unsigned char *regs)
95 unsigned char reg, data;
97 while (*regs != 0x00) {
100 if (saa7115_write(client, reg, data) < 0)
106 static inline int saa7115_read(struct i2c_client *client, u8 reg)
108 return i2c_smbus_read_byte_data(client, reg);
111 /* ----------------------------------------------------------------------- */
113 /* If a value differs from the Hauppauge driver values, then the comment starts with
114 'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the
115 Hauppauge driver sets. */
117 static const unsigned char saa7115_init_auto_input[] = {
118 0x01, 0x48, /* white peak control disabled */
119 0x03, 0x20, /* was 0x30. 0x20: long vertical blanking */
120 0x04, 0x90, /* analog gain set to 0 */
121 0x05, 0x90, /* analog gain set to 0 */
122 0x06, 0xeb, /* horiz sync begin = -21 */
123 0x07, 0xe0, /* horiz sync stop = -17 */
124 0x0a, 0x80, /* was 0x88. decoder brightness, 0x80 is itu standard */
125 0x0b, 0x44, /* was 0x48. decoder contrast, 0x44 is itu standard */
126 0x0c, 0x40, /* was 0x47. decoder saturation, 0x40 is itu standard */
127 0x0d, 0x00, /* chrominance hue control */
128 0x0f, 0x00, /* chrominance gain control: use automicatic mode */
129 0x10, 0x06, /* chrominance/luminance control: active adaptive combfilter */
130 0x11, 0x00, /* delay control */
131 0x12, 0x9d, /* RTS0 output control: VGATE */
132 0x13, 0x80, /* X-port output control: ITU656 standard mode, RTCO output enable RTCE */
133 0x14, 0x00, /* analog/ADC/auto compatibility control */
134 0x18, 0x40, /* raw data gain 0x00 = nominal */
135 0x19, 0x80, /* raw data offset 0x80 = 0 LSB */
136 0x1a, 0x77, /* color killer level control 0x77 = recommended */
137 0x1b, 0x42, /* misc chroma control 0x42 = recommended */
138 0x1c, 0xa9, /* combfilter control 0xA9 = recommended */
139 0x1d, 0x01, /* combfilter control 0x01 = recommended */
140 0x88, 0xd0, /* reset device */
141 0x88, 0xf0, /* set device programmed, all in operational mode */
145 static const unsigned char saa7115_cfg_reset_scaler[] = {
146 0x87, 0x00, /* disable I-port output */
147 0x88, 0xd0, /* reset scaler */
148 0x88, 0xf0, /* activate scaler */
149 0x87, 0x01, /* enable I-port output */
153 /* ============== SAA7715 VIDEO templates ============= */
155 static const unsigned char saa7115_cfg_60hz_fullres_x[] = {
156 0xcc, 0xd0, /* hsize low (output), hor. output window size = 0x2d0 = 720 */
157 0xcd, 0x02, /* hsize hi (output) */
159 /* Why not in 60hz-Land, too? */
160 0xd0, 0x01, /* downscale = 1 */
161 0xd8, 0x00, /* hor lum scaling 0x0400 = 1 */
163 0xdc, 0x00, /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */
164 0xdd, 0x02, /* H-scaling incr chroma */
168 static const unsigned char saa7115_cfg_60hz_fullres_y[] = {
169 0xce, 0xf8, /* vsize low (output), ver. output window size = 248 (but 60hz is 240?) */
170 0xcf, 0x00, /* vsize hi (output) */
172 /* Why not in 60hz-Land, too? */
173 0xd5, 0x40, /* Lum contrast, nominal value = 0x40 */
174 0xd6, 0x40, /* Chroma satur. nominal value = 0x80 */
176 0xe0, 0x00, /* V-scaling incr luma low */
177 0xe1, 0x04, /* " hi */
178 0xe2, 0x00, /* V-scaling incr chroma low */
179 0xe3, 0x04, /* " hi */
184 static const unsigned char saa7115_cfg_60hz_video[] = {
185 0x80, 0x00, /* reset tasks */
186 0x88, 0xd0, /* reset scaler */
188 0x15, 0x03, /* VGATE pulse start */
189 0x16, 0x11, /* VGATE pulse stop */
190 0x17, 0x9c, /* VGATE MSB and other values */
192 0x08, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */
193 0x0e, 0x07, /* lots of different stuff... video autodetection is on */
195 0x5a, 0x06, /* Vertical offset, standard 60hz value for ITU656 line counting */
198 0x90, 0x80, /* Task Handling Control */
199 0x91, 0x48, /* X-port formats/config */
200 0x92, 0x40, /* Input Ref. signal Def. */
201 0x93, 0x84, /* I-port config */
202 0x94, 0x01, /* hoffset low (input), 0x0002 is minimum */
203 0x95, 0x00, /* hoffset hi (input) */
204 0x96, 0xd0, /* hsize low (input), 0x02d0 = 720 */
205 0x97, 0x02, /* hsize hi (input) */
206 0x98, 0x05, /* voffset low (input) */
207 0x99, 0x00, /* voffset hi (input) */
208 0x9a, 0x0c, /* vsize low (input), 0x0c = 12 */
209 0x9b, 0x00, /* vsize hi (input) */
210 0x9c, 0xa0, /* hsize low (output), 0x05a0 = 1440 */
211 0x9d, 0x05, /* hsize hi (output) */
212 0x9e, 0x0c, /* vsize low (output), 0x0c = 12 */
213 0x9f, 0x00, /* vsize hi (output) */
216 0xc0, 0x00, /* Task Handling Control */
217 0xc1, 0x08, /* X-port formats/config */
218 0xc2, 0x00, /* Input Ref. signal Def. */
219 0xc3, 0x80, /* I-port config */
220 0xc4, 0x02, /* hoffset low (input), 0x0002 is minimum */
221 0xc5, 0x00, /* hoffset hi (input) */
222 0xc6, 0xd0, /* hsize low (input), 0x02d0 = 720 */
223 0xc7, 0x02, /* hsize hi (input) */
224 0xc8, 0x12, /* voffset low (input), 0x12 = 18 */
225 0xc9, 0x00, /* voffset hi (input) */
226 0xca, 0xf8, /* vsize low (input), 0xf8 = 248 */
227 0xcb, 0x00, /* vsize hi (input) */
228 0xcc, 0xd0, /* hsize low (output), 0x02d0 = 720 */
229 0xcd, 0x02, /* hsize hi (output) */
231 0xf0, 0xad, /* Set PLL Register. 60hz 525 lines per frame, 27 MHz */
232 0xf1, 0x05, /* low bit with 0xF0 */
233 0xf5, 0xad, /* Set pulse generator register */
236 0x87, 0x00, /* Disable I-port output */
237 0x88, 0xd0, /* reset scaler */
238 0x80, 0x20, /* Activate only task "B", continuous mode (was 0xA0) */
239 0x88, 0xf0, /* activate scaler */
240 0x87, 0x01, /* Enable I-port output */
244 static const unsigned char saa7115_cfg_50hz_fullres_x[] = {
245 0xcc, 0xd0, /* hsize low (output), 720 same as 60hz */
246 0xcd, 0x02, /* hsize hi (output) */
248 0xd0, 0x01, /* down scale = 1 */
249 0xd8, 0x00, /* hor lum scaling 0x0400 = 1 */
251 0xdc, 0x00, /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */
252 0xdd, 0x02, /* H-scaling incr chroma */
256 static const unsigned char saa7115_cfg_50hz_fullres_y[] = {
257 0xce, 0x20, /* vsize low (output), 0x0120 = 288 */
258 0xcf, 0x01, /* vsize hi (output) */
260 0xd5, 0x40, /* Lum contrast, nominal value = 0x40 */
261 0xd6, 0x40, /* Chroma satur. nominal value = 0x80 */
263 0xe0, 0x00, /* V-scaling incr luma low */
264 0xe1, 0x04, /* " hi */
265 0xe2, 0x00, /* V-scaling incr chroma low */
266 0xe3, 0x04, /* " hi */
271 static const unsigned char saa7115_cfg_50hz_video[] = {
272 0x80, 0x00, /* reset tasks */
273 0x88, 0xd0, /* reset scaler */
275 0x15, 0x37, /* VGATE start */
276 0x16, 0x16, /* VGATE stop */
277 0x17, 0x99, /* VGATE MSB and other values */
279 0x08, 0x28, /* 0x28 = PAL */
280 0x0e, 0x07, /* chrominance control 1 */
282 0x5a, 0x03, /* Vertical offset, standard 50hz value */
285 0x90, 0x81, /* Task Handling Control */
286 0x91, 0x48, /* X-port formats/config */
287 0x92, 0x40, /* Input Ref. signal Def. */
288 0x93, 0x84, /* I-port config */
289 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
290 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
291 0x94, 0x00, /* hoffset low (input), 0x0002 is minimum */
292 0x95, 0x00, /* hoffset hi (input) */
293 0x96, 0xd0, /* hsize low (input), 0x02d0 = 720 */
294 0x97, 0x02, /* hsize hi (input) */
295 0x98, 0x03, /* voffset low (input) */
296 0x99, 0x00, /* voffset hi (input) */
297 0x9a, 0x12, /* vsize low (input), 0x12 = 18 */
298 0x9b, 0x00, /* vsize hi (input) */
299 0x9c, 0xa0, /* hsize low (output), 0x05a0 = 1440 */
300 0x9d, 0x05, /* hsize hi (output) */
301 0x9e, 0x12, /* vsize low (output), 0x12 = 18 */
302 0x9f, 0x00, /* vsize hi (output) */
305 0xc0, 0x00, /* Task Handling Control */
306 0xc1, 0x08, /* X-port formats/config */
307 0xc2, 0x00, /* Input Ref. signal Def. */
308 0xc3, 0x80, /* I-port config */
309 0xc4, 0x00, /* hoffset low (input), 0x0002 is minimum. See comment at 0x94 above. */
310 0xc5, 0x00, /* hoffset hi (input) */
311 0xc6, 0xd0, /* hsize low (input), 0x02d0 = 720 */
312 0xc7, 0x02, /* hsize hi (input) */
313 0xc8, 0x16, /* voffset low (input), 0x16 = 22 */
314 0xc9, 0x00, /* voffset hi (input) */
315 0xca, 0x20, /* vsize low (input), 0x0120 = 288 */
316 0xcb, 0x01, /* vsize hi (input) */
317 0xcc, 0xd0, /* hsize low (output), 0x02d0 = 720 */
318 0xcd, 0x02, /* hsize hi (output) */
319 0xce, 0x20, /* vsize low (output), 0x0120 = 288 */
320 0xcf, 0x01, /* vsize hi (output) */
322 0xf0, 0xb0, /* Set PLL Register. 50hz 625 lines per frame, 27 MHz */
323 0xf1, 0x05, /* low bit with 0xF0, (was 0x05) */
324 0xf5, 0xb0, /* Set pulse generator register */
327 0x87, 0x00, /* Disable I-port output */
328 0x88, 0xd0, /* reset scaler (was 0xD0) */
329 0x80, 0x20, /* Activate only task "B" */
330 0x88, 0xf0, /* activate scaler */
331 0x87, 0x01, /* Enable I-port output */
335 /* ============== SAA7715 VIDEO templates (end) ======= */
337 static const unsigned char saa7115_cfg_vbi_on[] = {
338 0x80, 0x00, /* reset tasks */
339 0x88, 0xd0, /* reset scaler */
340 0x80, 0x30, /* Activate both tasks */
341 0x88, 0xf0, /* activate scaler */
342 0x87, 0x01, /* Enable I-port output */
346 static const unsigned char saa7115_cfg_vbi_off[] = {
347 0x80, 0x00, /* reset tasks */
348 0x88, 0xd0, /* reset scaler */
349 0x80, 0x20, /* Activate only task "B" */
350 0x88, 0xf0, /* activate scaler */
351 0x87, 0x01, /* Enable I-port output */
355 static const unsigned char saa7115_init_misc[] = {
356 0x38, 0x03, /* audio stuff */
360 0x81, 0x01, /* reg 0x15,0x16 define blanking window */
362 0x83, 0x01, /* I port settings */
369 0xa0, 0x01, /* down scale = 1 */
370 0xa1, 0x00, /* prescale accumulation length = 1 */
371 0xa2, 0x00, /* dc gain and fir prefilter control */
372 0xa4, 0x80, /* Lum Brightness, nominal value = 0x80 */
373 0xa5, 0x40, /* Lum contrast, nominal value = 0x40 */
374 0xa6, 0x40, /* Chroma satur. nominal value = 0x80 */
375 0xa8, 0x00, /* hor lum scaling 0x0200 = 2 zoom */
376 0xa9, 0x02, /* note: 2 x zoom ensures that VBI lines have same length as video lines. */
377 0xaa, 0x00, /* H-phase offset Luma = 0 */
378 0xac, 0x00, /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */
379 0xad, 0x01, /* H-scaling incr chroma */
380 0xae, 0x00, /* H-phase offset chroma. must be offset luma / 2 */
382 0xb0, 0x00, /* V-scaling incr luma low */
383 0xb1, 0x04, /* " hi */
384 0xb2, 0x00, /* V-scaling incr chroma low */
385 0xb3, 0x04, /* " hi */
386 0xb4, 0x01, /* V-scaling mode control */
387 0xb8, 0x00, /* V-phase offset chroma 00 */
388 0xb9, 0x00, /* V-phase offset chroma 01 */
389 0xba, 0x00, /* V-phase offset chroma 10 */
390 0xbb, 0x00, /* V-phase offset chroma 11 */
391 0xbc, 0x00, /* V-phase offset luma 00 */
392 0xbd, 0x00, /* V-phase offset luma 01 */
393 0xbe, 0x00, /* V-phase offset luma 10 */
394 0xbf, 0x00, /* V-phase offset luma 11 */
397 0xd0, 0x01, /* down scale = 1 */
398 0xd1, 0x00, /* prescale accumulation length = 1 */
399 0xd2, 0x00, /* dc gain and fir prefilter control */
400 0xd4, 0x80, /* Lum Brightness, nominal value = 0x80 */
401 0xd5, 0x40, /* Lum contrast, nominal value = 0x40 */
402 0xd6, 0x40, /* Chroma satur. nominal value = 0x80 */
403 0xd8, 0x00, /* hor lum scaling 0x0400 = 1 */
405 0xda, 0x00, /* H-phase offset Luma = 0 */
406 0xdc, 0x00, /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */
407 0xdd, 0x02, /* H-scaling incr chroma */
408 0xde, 0x00, /* H-phase offset chroma. must be offset luma / 2 */
410 0xe0, 0x00, /* V-scaling incr luma low */
411 0xe1, 0x04, /* " hi */
412 0xe2, 0x00, /* V-scaling incr chroma low */
413 0xe3, 0x04, /* " hi */
414 0xe4, 0x01, /* V-scaling mode control */
415 0xe8, 0x00, /* V-phase offset chroma 00 */
416 0xe9, 0x00, /* V-phase offset chroma 01 */
417 0xea, 0x00, /* V-phase offset chroma 10 */
418 0xeb, 0x00, /* V-phase offset chroma 11 */
419 0xec, 0x00, /* V-phase offset luma 00 */
420 0xed, 0x00, /* V-phase offset luma 01 */
421 0xee, 0x00, /* V-phase offset luma 10 */
422 0xef, 0x00, /* V-phase offset luma 11 */
424 0xf2, 0x50, /* crystal clock = 24.576 MHz, target = 27MHz */
427 0xf7, 0x4b, /* not the recommended settings! */
432 0xff, 0x88, /* PLL2 lock detection settings: 71 lines 50% phase error */
435 0x40, 0x20, /* No framing code errors allowed. */
465 0x02, 0x84, /* input tuner -> input 4, amplifier active */
466 0x09, 0x53, /* 0x53, was 0x56 for 60hz. luminance control */
468 0x80, 0x20, /* enable task B */
474 static int saa7115_odd_parity(u8 c)
483 static int saa7115_decode_vps(u8 * dst, u8 * p)
485 static const u8 biphase_tbl[] = {
486 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
487 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
488 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
489 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
490 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
491 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
492 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
493 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
494 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
495 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
496 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
497 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
498 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
499 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
500 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
501 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
502 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
503 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
504 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
505 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
506 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
507 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
508 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
509 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
510 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
511 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
512 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
513 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
514 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
515 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
516 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
517 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
522 for (i = 0; i < 2 * 13; i += 2) {
523 err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
524 c = (biphase_tbl[p[i + 1]] & 0xf) | ((biphase_tbl[p[i]] & 0xf) << 4);
530 static int saa7115_decode_wss(u8 * p)
532 static const int wss_bits[8] = {
533 0, 0, 0, 1, 0, 1, 1, 1
535 unsigned char parity;
539 for (i = 0; i < 16; i++) {
540 int b1 = wss_bits[p[i] & 7];
541 int b2 = wss_bits[(p[i] >> 3) & 7];
548 parity ^= parity >> 2;
549 parity ^= parity >> 1;
558 static int saa7115_set_audio_clock_freq(struct i2c_client *client, u32 freq)
560 struct saa7115_state *state = i2c_get_clientdata(client);
566 saa7115_dbg("set audio clock freq: %d\n", freq);
569 if (freq < 32000 || freq > 48000)
572 /* hz is the refresh rate times 100 */
573 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
574 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
575 acpf = (25600 * freq) / hz;
576 /* acni = (256 * freq * 2^23) / crystal_frequency =
577 (freq * 2^(8+23)) / crystal_frequency =
578 (freq << 31) / 32.11 MHz */
584 saa7115_write(client, 0x30, acpf & 0xff);
585 saa7115_write(client, 0x31, (acpf >> 8) & 0xff);
586 saa7115_write(client, 0x32, (acpf >> 16) & 0x03);
587 saa7115_write(client, 0x34, acni & 0xff);
588 saa7115_write(client, 0x35, (acni >> 8) & 0xff);
589 saa7115_write(client, 0x36, (acni >> 16) & 0x3f);
590 state->audclk_freq = freq;
594 static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
596 struct saa7115_state *state = i2c_get_clientdata(client);
599 case V4L2_CID_BRIGHTNESS:
600 if (ctrl->value < 0 || ctrl->value > 255) {
601 saa7115_err("invalid brightness setting %d\n", ctrl->value);
605 state->bright = ctrl->value;
606 saa7115_write(client, 0x0a, state->bright);
609 case V4L2_CID_CONTRAST:
610 if (ctrl->value < 0 || ctrl->value > 127) {
611 saa7115_err("invalid contrast setting %d\n", ctrl->value);
615 state->contrast = ctrl->value;
616 saa7115_write(client, 0x0b, state->contrast);
619 case V4L2_CID_SATURATION:
620 if (ctrl->value < 0 || ctrl->value > 127) {
621 saa7115_err("invalid saturation setting %d\n", ctrl->value);
625 state->sat = ctrl->value;
626 saa7115_write(client, 0x0c, state->sat);
630 if (ctrl->value < -127 || ctrl->value > 127) {
631 saa7115_err("invalid hue setting %d\n", ctrl->value);
635 state->hue = ctrl->value;
636 saa7115_write(client, 0x0d, state->hue);
646 static int saa7115_get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
648 struct saa7115_state *state = i2c_get_clientdata(client);
651 case V4L2_CID_BRIGHTNESS:
652 ctrl->value = state->bright;
654 case V4L2_CID_CONTRAST:
655 ctrl->value = state->contrast;
657 case V4L2_CID_SATURATION:
658 ctrl->value = state->sat;
661 ctrl->value = state->hue;
670 static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
672 struct saa7115_state *state = i2c_get_clientdata(client);
673 int taskb = saa7115_read(client, 0x80) & 0x10;
675 /* Prevent unnecessary standard changes. During a standard
676 change the I-Port is temporarily disabled. Any devices
677 reading from that port can get confused.
678 Note that VIDIOC_S_STD is also used to switch from
679 radio to TV mode, so if a VIDIOC_S_STD is broadcast to
680 all I2C devices then you do not want to have an unwanted
682 if (std == state->std)
685 // This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
686 if (std & V4L2_STD_525_60) {
687 saa7115_dbg("decoder set standard 60 Hz\n");
688 saa7115_writeregs(client, saa7115_cfg_60hz_video);
690 saa7115_dbg("decoder set standard 50 Hz\n");
691 saa7115_writeregs(client, saa7115_cfg_50hz_video);
696 /* restart task B if needed */
697 if (taskb && state->ident == V4L2_IDENT_SAA7114) {
698 saa7115_writeregs(client, saa7115_cfg_vbi_on);
701 /* switch audio mode too! */
702 saa7115_set_audio_clock_freq(client, state->audclk_freq);
705 static v4l2_std_id saa7115_get_v4lstd(struct i2c_client *client)
707 struct saa7115_state *state = i2c_get_clientdata(client);
712 static void saa7115_log_status(struct i2c_client *client)
714 struct saa7115_state *state = i2c_get_clientdata(client);
719 saa7115_info("Audio frequency: %d Hz\n", state->audclk_freq);
720 if (client->name[6] == '4') {
721 /* status for the saa7114 */
722 reg1f = saa7115_read(client, 0x1f);
723 signalOk = (reg1f & 0xc1) == 0x81;
724 saa7115_info("Video signal: %s\n", signalOk ? "ok" : "bad");
725 saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
729 /* status for the saa7115 */
730 reg1e = saa7115_read(client, 0x1e);
731 reg1f = saa7115_read(client, 0x1f);
733 signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
734 vcr = !(reg1f & 0x10);
736 if (state->input >= 6) {
737 saa7115_info("Input: S-Video %d\n", state->input - 6);
739 saa7115_info("Input: Composite %d\n", state->input);
741 saa7115_info("Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
742 saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
744 switch (reg1e & 0x03) {
746 saa7115_info("Detected format: NTSC\n");
749 saa7115_info("Detected format: PAL\n");
752 saa7115_info("Detected format: SECAM\n");
755 saa7115_info("Detected format: BW/No color\n");
760 /* setup the sliced VBI lcr registers according to the sliced VBI format */
761 static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_format *fmt)
763 struct saa7115_state *state = i2c_get_clientdata(client);
764 int is_50hz = (state->std & V4L2_STD_625_50);
768 /* saa7114 doesn't yet support VBI */
769 if (state->ident == V4L2_IDENT_SAA7114)
772 for (i = 0; i <= 23; i++)
775 if (fmt->service_set == 0) {
778 for (i = 6; i <= 23; i++)
781 for (i = 10; i <= 21; i++)
785 /* first clear lines that cannot be captured */
787 for (i = 0; i <= 5; i++)
788 fmt->service_lines[0][i] =
789 fmt->service_lines[1][i] = 0;
792 for (i = 0; i <= 9; i++)
793 fmt->service_lines[0][i] =
794 fmt->service_lines[1][i] = 0;
795 for (i = 22; i <= 23; i++)
796 fmt->service_lines[0][i] =
797 fmt->service_lines[1][i] = 0;
800 /* Now set the lcr values according to the specified service */
801 for (i = 6; i <= 23; i++) {
803 for (x = 0; x <= 1; x++) {
804 switch (fmt->service_lines[1-x][i]) {
806 lcr[i] |= 0xf << (4 * x);
808 case V4L2_SLICED_TELETEXT_B:
809 lcr[i] |= 1 << (4 * x);
811 case V4L2_SLICED_CAPTION_525:
812 lcr[i] |= 4 << (4 * x);
814 case V4L2_SLICED_WSS_625:
815 lcr[i] |= 5 << (4 * x);
817 case V4L2_SLICED_VPS:
818 lcr[i] |= 7 << (4 * x);
825 /* write the lcr registers */
826 for (i = 2; i <= 23; i++) {
827 saa7115_write(client, i - 2 + 0x41, lcr[i]);
830 /* enable/disable raw VBI capturing */
831 saa7115_writeregs(client, fmt->service_set == 0 ? saa7115_cfg_vbi_on : saa7115_cfg_vbi_off);
834 static int saa7115_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
836 static u16 lcr2vbi[] = {
837 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
838 0, V4L2_SLICED_CAPTION_525, /* 4 */
839 V4L2_SLICED_WSS_625, 0, /* 5 */
840 V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */
843 struct v4l2_sliced_vbi_format *sliced = &fmt->fmt.sliced;
846 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
848 memset(sliced, 0, sizeof(*sliced));
849 /* done if using raw VBI */
850 if (saa7115_read(client, 0x80) & 0x10)
852 for (i = 2; i <= 23; i++) {
853 u8 v = saa7115_read(client, i - 2 + 0x41);
855 sliced->service_lines[0][i] = lcr2vbi[v >> 4];
856 sliced->service_lines[1][i] = lcr2vbi[v & 0xf];
857 sliced->service_set |=
858 sliced->service_lines[0][i] | sliced->service_lines[1][i];
863 static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
865 struct saa7115_state *state = i2c_get_clientdata(client);
866 struct v4l2_pix_format *pix;
869 int is_50hz = state->std & V4L2_STD_625_50;
871 if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
872 saa7115_set_lcr(client, &fmt->fmt.sliced);
875 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
878 pix = &(fmt->fmt.pix);
880 saa7115_dbg("decoder set size\n");
882 /* FIXME need better bounds checking here */
883 if ((pix->width < 1) || (pix->width > 1440))
885 if ((pix->height < 1) || (pix->height > 960))
888 /* probably have a valid size, let's set it */
889 /* Set output width/height */
891 saa7115_write(client, 0xcc, (u8) (pix->width & 0xff));
892 saa7115_write(client, 0xcd, (u8) ((pix->width >> 8) & 0xff));
894 saa7115_write(client, 0xce, (u8) (pix->height & 0xff));
895 saa7115_write(client, 0xcf, (u8) ((pix->height >> 8) & 0xff));
897 /* Scaling settings */
898 /* Hprescaler is floor(inres/outres) */
899 /* FIXME hardcoding input res */
900 if (pix->width != 720) {
901 HPSC = (int)(720 / pix->width);
902 /* 0 is not allowed (div. by zero) */
903 HPSC = HPSC ? HPSC : 1;
904 HFSC = (int)((1024 * 720) / (HPSC * pix->width));
906 saa7115_dbg("Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
907 /* FIXME hardcodes to "Task B"
908 * write H prescaler integer */
909 saa7115_write(client, 0xd0, (u8) (HPSC & 0x3f));
911 /* write H fine-scaling (luminance) */
912 saa7115_write(client, 0xd8, (u8) (HFSC & 0xff));
913 saa7115_write(client, 0xd9, (u8) ((HFSC >> 8) & 0xff));
914 /* write H fine-scaling (chrominance)
915 * must be lum/2, so i'll just bitshift :) */
916 saa7115_write(client, 0xDC, (u8) ((HFSC >> 1) & 0xff));
917 saa7115_write(client, 0xDD, (u8) ((HFSC >> 9) & 0xff));
920 saa7115_dbg("Setting full 50hz width\n");
921 saa7115_writeregs(client, saa7115_cfg_50hz_fullres_x);
923 saa7115_dbg("Setting full 60hz width\n");
924 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x);
928 Vsrc = is_50hz ? 576 : 480;
930 if (pix->height != Vsrc) {
931 VSCY = (int)((1024 * Vsrc) / pix->height);
932 saa7115_dbg("Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
934 /* Correct Contrast and Luminance */
935 saa7115_write(client, 0xd5, (u8) (64 * 1024 / VSCY));
936 saa7115_write(client, 0xd6, (u8) (64 * 1024 / VSCY));
938 /* write V fine-scaling (luminance) */
939 saa7115_write(client, 0xe0, (u8) (VSCY & 0xff));
940 saa7115_write(client, 0xe1, (u8) ((VSCY >> 8) & 0xff));
941 /* write V fine-scaling (chrominance) */
942 saa7115_write(client, 0xe2, (u8) (VSCY & 0xff));
943 saa7115_write(client, 0xe3, (u8) ((VSCY >> 8) & 0xff));
946 saa7115_dbg("Setting full 50Hz height\n");
947 saa7115_writeregs(client, saa7115_cfg_50hz_fullres_y);
949 saa7115_dbg("Setting full 60hz height\n");
950 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y);
954 saa7115_writeregs(client, saa7115_cfg_reset_scaler);
958 /* Decode the sliced VBI data stream as created by the saa7115.
959 The format is described in the saa7115 datasheet in Tables 25 and 26
961 The current implementation uses SAV/EAV codes and not the ancillary data
962 headers. The vbi->p pointer points to the SDID byte right after the SAV
964 static void saa7115_decode_vbi_line(struct i2c_client *client,
965 struct v4l2_decode_vbi_line *vbi)
967 static const char vbi_no_data_pattern[] = {
968 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0
970 struct saa7115_state *state = i2c_get_clientdata(client);
973 int id1, id2; /* the ID1 and ID2 bytes from the internal header */
975 vbi->type = 0; /* mark result as a failure */
978 /* Note: the field bit is inverted for 60 Hz video */
979 if (state->std & V4L2_STD_525_60)
982 /* Skip internal header, p now points to the start of the payload */
986 /* calculate field and line number of the VBI packet (1-23) */
987 vbi->is_second_field = ((id1 & 0x40) != 0);
988 vbi->line = (id1 & 0x3f) << 3;
989 vbi->line |= (id2 & 0x70) >> 4;
991 /* Obtain data type */
994 /* If the VBI slicer does not detect any signal it will fill up
995 the payload buffer with 0xa0 bytes. */
996 if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern)))
999 /* decode payloads */
1002 vbi->type = V4L2_SLICED_TELETEXT_B;
1005 if (!saa7115_odd_parity(p[0]) || !saa7115_odd_parity(p[1]))
1007 vbi->type = V4L2_SLICED_CAPTION_525;
1010 wss = saa7115_decode_wss(p);
1015 vbi->type = V4L2_SLICED_WSS_625;
1018 if (saa7115_decode_vps(p, p) != 0)
1020 vbi->type = V4L2_SLICED_VPS;
1027 /* ============ SAA7115 AUDIO settings (end) ============= */
1029 static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg)
1031 struct saa7115_state *state = i2c_get_clientdata(client);
1034 /* ioctls to allow direct access to the saa7115 registers for testing */
1037 return saa7115_set_v4lfmt(client, (struct v4l2_format *)arg);
1040 return saa7115_get_v4lfmt(client, (struct v4l2_format *)arg);
1042 case VIDIOC_INT_AUDIO_CLOCK_FREQ:
1043 return saa7115_set_audio_clock_freq(client, *(u32 *)arg);
1045 case VIDIOC_G_TUNER:
1047 struct v4l2_tuner *vt = arg;
1052 status = saa7115_read(client, 0x1f);
1054 saa7115_dbg("status: 0x%02x\n", status);
1055 vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
1059 case VIDIOC_LOG_STATUS:
1060 saa7115_log_status(client);
1064 return saa7115_get_v4lctrl(client, (struct v4l2_control *)arg);
1067 return saa7115_set_v4lctrl(client, (struct v4l2_control *)arg);
1070 *(v4l2_std_id *)arg = saa7115_get_v4lstd(client);
1075 saa7115_set_v4lstd(client, *(v4l2_std_id *)arg);
1078 case AUDC_SET_RADIO:
1082 case VIDIOC_G_INPUT:
1083 *(int *)arg = state->input;
1086 case VIDIOC_S_INPUT:
1087 saa7115_dbg("decoder set input %d\n", *iarg);
1088 /* inputs from 0-9 are available */
1089 if (*iarg < 0 || *iarg > 9) {
1093 if (state->input == *iarg)
1095 saa7115_dbg("now setting %s input\n",
1096 *iarg >= 6 ? "S-Video" : "Composite");
1097 state->input = *iarg;
1100 saa7115_write(client, 0x02,
1101 (saa7115_read(client, 0x02) & 0xf0) |
1104 /* bypass chrominance trap for modes 6..9 */
1105 saa7115_write(client, 0x09,
1106 (saa7115_read(client, 0x09) & 0x7f) |
1107 (state->input < 6 ? 0x0 : 0x80));
1110 case VIDIOC_STREAMON:
1111 case VIDIOC_STREAMOFF:
1112 saa7115_dbg("%s output\n",
1113 (cmd == VIDIOC_STREAMON) ? "enable" : "disable");
1115 if (state->enable != (cmd == VIDIOC_STREAMON)) {
1116 state->enable = (cmd == VIDIOC_STREAMON);
1117 saa7115_write(client, 0x87, state->enable);
1121 case VIDIOC_INT_DECODE_VBI_LINE:
1122 saa7115_decode_vbi_line(client, arg);
1125 case VIDIOC_INT_RESET:
1126 saa7115_dbg("decoder RESET\n");
1127 saa7115_writeregs(client, saa7115_cfg_reset_scaler);
1130 case VIDIOC_INT_G_VBI_DATA:
1132 struct v4l2_sliced_vbi_data *data = arg;
1135 case V4L2_SLICED_WSS_625:
1136 if (saa7115_read(client, 0x6b) & 0xc0)
1138 data->data[0] = saa7115_read(client, 0x6c);
1139 data->data[1] = saa7115_read(client, 0x6d);
1141 case V4L2_SLICED_CAPTION_525:
1142 if (data->field == 0) {
1144 if (saa7115_read(client, 0x66) & 0xc0)
1146 data->data[0] = saa7115_read(client, 0x67);
1147 data->data[1] = saa7115_read(client, 0x68);
1151 if (saa7115_read(client, 0x66) & 0x30)
1153 data->data[0] = saa7115_read(client, 0x69);
1154 data->data[1] = saa7115_read(client, 0x6a);
1162 #ifdef CONFIG_VIDEO_ADV_DEBUG
1163 case VIDIOC_INT_G_REGISTER:
1165 struct v4l2_register *reg = arg;
1167 if (reg->i2c_id != I2C_DRIVERID_SAA711X)
1169 reg->val = saa7115_read(client, reg->reg & 0xff);
1173 case VIDIOC_INT_S_REGISTER:
1175 struct v4l2_register *reg = arg;
1177 if (reg->i2c_id != I2C_DRIVERID_SAA711X)
1179 if (!capable(CAP_SYS_ADMIN))
1181 saa7115_write(client, reg->reg & 0xff, reg->val & 0xff);
1186 case VIDIOC_INT_G_CHIP_IDENT:
1187 *iarg = state->ident;
1197 /* ----------------------------------------------------------------------- */
1199 static struct i2c_driver i2c_driver_saa7115;
1201 static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
1203 struct i2c_client *client;
1204 struct saa7115_state *state;
1207 /* Check if the adapter supports the needed features */
1208 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
1211 client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
1214 memset(client, 0, sizeof(struct i2c_client));
1215 client->addr = address;
1216 client->adapter = adapter;
1217 client->driver = &i2c_driver_saa7115;
1218 snprintf(client->name, sizeof(client->name) - 1, "saa7115");
1220 saa7115_dbg("detecting saa7115 client on address 0x%x\n", address << 1);
1222 saa7115_write(client, 0, 5);
1223 chip_id = saa7115_read(client, 0) & 0x0f;
1224 if (chip_id != 4 && chip_id != 5) {
1225 saa7115_dbg("saa7115 not found\n");
1230 snprintf(client->name, sizeof(client->name) - 1, "saa7114");
1232 saa7115_info("saa711%d found @ 0x%x (%s)\n", chip_id, address << 1, adapter->name);
1234 state = kmalloc(sizeof(struct saa7115_state), GFP_KERNEL);
1235 i2c_set_clientdata(client, state);
1236 if (state == NULL) {
1240 memset(state, 0, sizeof(struct saa7115_state));
1241 state->std = V4L2_STD_NTSC;
1245 state->bright = 128;
1246 state->contrast = 64;
1249 state->ident = (chip_id == 4) ? V4L2_IDENT_SAA7114 : V4L2_IDENT_SAA7115;
1250 state->audclk_freq = 48000;
1252 saa7115_dbg("writing init values\n");
1254 /* init to 60hz/48khz */
1255 saa7115_writeregs(client, saa7115_init_auto_input);
1256 saa7115_writeregs(client, saa7115_init_misc);
1257 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x);
1258 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y);
1259 saa7115_writeregs(client, saa7115_cfg_60hz_video);
1260 saa7115_set_audio_clock_freq(client, state->audclk_freq);
1261 saa7115_writeregs(client, saa7115_cfg_reset_scaler);
1263 i2c_attach_client(client);
1265 saa7115_dbg("status: (1E) 0x%02x, (1F) 0x%02x\n",
1266 saa7115_read(client, 0x1e), saa7115_read(client, 0x1f));
1271 static int saa7115_probe(struct i2c_adapter *adapter)
1273 if (adapter->class & I2C_CLASS_TV_ANALOG)
1274 return i2c_probe(adapter, &addr_data, &saa7115_attach);
1278 static int saa7115_detach(struct i2c_client *client)
1280 struct saa7115_state *state = i2c_get_clientdata(client);
1283 err = i2c_detach_client(client);
1293 /* ----------------------------------------------------------------------- */
1295 /* i2c implementation */
1296 static struct i2c_driver i2c_driver_saa7115 = {
1300 .id = I2C_DRIVERID_SAA711X,
1301 .attach_adapter = saa7115_probe,
1302 .detach_client = saa7115_detach,
1303 .command = saa7115_command,
1307 static int __init saa7115_init_module(void)
1309 return i2c_add_driver(&i2c_driver_saa7115);
1312 static void __exit saa7115_cleanup_module(void)
1314 i2c_del_driver(&i2c_driver_saa7115);
1317 module_init(saa7115_init_module);
1318 module_exit(saa7115_cleanup_module);