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 <media/audiochip.h>
43 #include <asm/div64.h>
45 MODULE_DESCRIPTION("Philips SAA7114/SAA7115 video decoder driver");
46 MODULE_AUTHOR("Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, Hans Verkuil");
47 MODULE_LICENSE("GPL");
50 module_param(debug, bool, 0644);
52 MODULE_PARM_DESC(debug, "Debug level (0-1)");
54 static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END };
59 struct saa7115_state {
68 enum v4l2_chip_ident ident;
72 /* ----------------------------------------------------------------------- */
74 static inline int saa7115_write(struct i2c_client *client, u8 reg, u8 value)
76 return i2c_smbus_write_byte_data(client, reg, value);
79 static int saa7115_writeregs(struct i2c_client *client, const unsigned char *regs)
81 unsigned char reg, data;
83 while (*regs != 0x00) {
86 if (saa7115_write(client, reg, data) < 0)
92 static inline int saa7115_read(struct i2c_client *client, u8 reg)
94 return i2c_smbus_read_byte_data(client, reg);
97 /* ----------------------------------------------------------------------- */
99 /* If a value differs from the Hauppauge driver values, then the comment starts with
100 'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the
101 Hauppauge driver sets. */
103 static const unsigned char saa7115_init_auto_input[] = {
104 0x01, 0x48, /* white peak control disabled */
105 0x03, 0x20, /* was 0x30. 0x20: long vertical blanking */
106 0x04, 0x90, /* analog gain set to 0 */
107 0x05, 0x90, /* analog gain set to 0 */
108 0x06, 0xeb, /* horiz sync begin = -21 */
109 0x07, 0xe0, /* horiz sync stop = -17 */
110 0x0a, 0x80, /* was 0x88. decoder brightness, 0x80 is itu standard */
111 0x0b, 0x44, /* was 0x48. decoder contrast, 0x44 is itu standard */
112 0x0c, 0x40, /* was 0x47. decoder saturation, 0x40 is itu standard */
113 0x0d, 0x00, /* chrominance hue control */
114 0x0f, 0x00, /* chrominance gain control: use automicatic mode */
115 0x10, 0x06, /* chrominance/luminance control: active adaptive combfilter */
116 0x11, 0x00, /* delay control */
117 0x12, 0x9d, /* RTS0 output control: VGATE */
118 0x13, 0x80, /* X-port output control: ITU656 standard mode, RTCO output enable RTCE */
119 0x14, 0x00, /* analog/ADC/auto compatibility control */
120 0x18, 0x40, /* raw data gain 0x00 = nominal */
121 0x19, 0x80, /* raw data offset 0x80 = 0 LSB */
122 0x1a, 0x77, /* color killer level control 0x77 = recommended */
123 0x1b, 0x42, /* misc chroma control 0x42 = recommended */
124 0x1c, 0xa9, /* combfilter control 0xA9 = recommended */
125 0x1d, 0x01, /* combfilter control 0x01 = recommended */
126 0x88, 0xd0, /* reset device */
127 0x88, 0xf0, /* set device programmed, all in operational mode */
131 static const unsigned char saa7115_cfg_reset_scaler[] = {
132 0x87, 0x00, /* disable I-port output */
133 0x88, 0xd0, /* reset scaler */
134 0x88, 0xf0, /* activate scaler */
135 0x87, 0x01, /* enable I-port output */
139 /* ============== SAA7715 VIDEO templates ============= */
141 static const unsigned char saa7115_cfg_60hz_fullres_x[] = {
142 0xcc, 0xd0, /* hsize low (output), hor. output window size = 0x2d0 = 720 */
143 0xcd, 0x02, /* hsize hi (output) */
145 /* Why not in 60hz-Land, too? */
146 0xd0, 0x01, /* downscale = 1 */
147 0xd8, 0x00, /* hor lum scaling 0x0400 = 1 */
149 0xdc, 0x00, /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */
150 0xdd, 0x02, /* H-scaling incr chroma */
154 static const unsigned char saa7115_cfg_60hz_fullres_y[] = {
155 0xce, 0xf8, /* vsize low (output), ver. output window size = 248 (but 60hz is 240?) */
156 0xcf, 0x00, /* vsize hi (output) */
158 /* Why not in 60hz-Land, too? */
159 0xd5, 0x40, /* Lum contrast, nominal value = 0x40 */
160 0xd6, 0x40, /* Chroma satur. nominal value = 0x80 */
162 0xe0, 0x00, /* V-scaling incr luma low */
163 0xe1, 0x04, /* " hi */
164 0xe2, 0x00, /* V-scaling incr chroma low */
165 0xe3, 0x04, /* " hi */
170 static const unsigned char saa7115_cfg_60hz_video[] = {
171 0x80, 0x00, /* reset tasks */
172 0x88, 0xd0, /* reset scaler */
174 0x15, 0x03, /* VGATE pulse start */
175 0x16, 0x11, /* VGATE pulse stop */
176 0x17, 0x9c, /* VGATE MSB and other values */
178 0x08, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */
179 0x0e, 0x07, /* lots of different stuff... video autodetection is on */
181 0x5a, 0x06, /* Vertical offset, standard 60hz value for ITU656 line counting */
184 0x90, 0x80, /* Task Handling Control */
185 0x91, 0x48, /* X-port formats/config */
186 0x92, 0x40, /* Input Ref. signal Def. */
187 0x93, 0x84, /* I-port config */
188 0x94, 0x01, /* hoffset low (input), 0x0002 is minimum */
189 0x95, 0x00, /* hoffset hi (input) */
190 0x96, 0xd0, /* hsize low (input), 0x02d0 = 720 */
191 0x97, 0x02, /* hsize hi (input) */
192 0x98, 0x05, /* voffset low (input) */
193 0x99, 0x00, /* voffset hi (input) */
194 0x9a, 0x0c, /* vsize low (input), 0x0c = 12 */
195 0x9b, 0x00, /* vsize hi (input) */
196 0x9c, 0xa0, /* hsize low (output), 0x05a0 = 1440 */
197 0x9d, 0x05, /* hsize hi (output) */
198 0x9e, 0x0c, /* vsize low (output), 0x0c = 12 */
199 0x9f, 0x00, /* vsize hi (output) */
202 0xc0, 0x00, /* Task Handling Control */
203 0xc1, 0x08, /* X-port formats/config */
204 0xc2, 0x00, /* Input Ref. signal Def. */
205 0xc3, 0x80, /* I-port config */
206 0xc4, 0x02, /* hoffset low (input), 0x0002 is minimum */
207 0xc5, 0x00, /* hoffset hi (input) */
208 0xc6, 0xd0, /* hsize low (input), 0x02d0 = 720 */
209 0xc7, 0x02, /* hsize hi (input) */
210 0xc8, 0x12, /* voffset low (input), 0x12 = 18 */
211 0xc9, 0x00, /* voffset hi (input) */
212 0xca, 0xf8, /* vsize low (input), 0xf8 = 248 */
213 0xcb, 0x00, /* vsize hi (input) */
214 0xcc, 0xd0, /* hsize low (output), 0x02d0 = 720 */
215 0xcd, 0x02, /* hsize hi (output) */
217 0xf0, 0xad, /* Set PLL Register. 60hz 525 lines per frame, 27 MHz */
218 0xf1, 0x05, /* low bit with 0xF0 */
219 0xf5, 0xad, /* Set pulse generator register */
222 0x87, 0x00, /* Disable I-port output */
223 0x88, 0xd0, /* reset scaler */
224 0x80, 0x20, /* Activate only task "B", continuous mode (was 0xA0) */
225 0x88, 0xf0, /* activate scaler */
226 0x87, 0x01, /* Enable I-port output */
230 static const unsigned char saa7115_cfg_50hz_fullres_x[] = {
231 0xcc, 0xd0, /* hsize low (output), 720 same as 60hz */
232 0xcd, 0x02, /* hsize hi (output) */
234 0xd0, 0x01, /* down scale = 1 */
235 0xd8, 0x00, /* hor lum scaling 0x0400 = 1 */
237 0xdc, 0x00, /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */
238 0xdd, 0x02, /* H-scaling incr chroma */
242 static const unsigned char saa7115_cfg_50hz_fullres_y[] = {
243 0xce, 0x20, /* vsize low (output), 0x0120 = 288 */
244 0xcf, 0x01, /* vsize hi (output) */
246 0xd5, 0x40, /* Lum contrast, nominal value = 0x40 */
247 0xd6, 0x40, /* Chroma satur. nominal value = 0x80 */
249 0xe0, 0x00, /* V-scaling incr luma low */
250 0xe1, 0x04, /* " hi */
251 0xe2, 0x00, /* V-scaling incr chroma low */
252 0xe3, 0x04, /* " hi */
257 static const unsigned char saa7115_cfg_50hz_video[] = {
258 0x80, 0x00, /* reset tasks */
259 0x88, 0xd0, /* reset scaler */
261 0x15, 0x37, /* VGATE start */
262 0x16, 0x16, /* VGATE stop */
263 0x17, 0x99, /* VGATE MSB and other values */
265 0x08, 0x28, /* 0x28 = PAL */
266 0x0e, 0x07, /* chrominance control 1 */
268 0x5a, 0x03, /* Vertical offset, standard 50hz value */
271 0x90, 0x81, /* Task Handling Control */
272 0x91, 0x48, /* X-port formats/config */
273 0x92, 0x40, /* Input Ref. signal Def. */
274 0x93, 0x84, /* I-port config */
275 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
276 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
277 0x94, 0x00, /* hoffset low (input), 0x0002 is minimum */
278 0x95, 0x00, /* hoffset hi (input) */
279 0x96, 0xd0, /* hsize low (input), 0x02d0 = 720 */
280 0x97, 0x02, /* hsize hi (input) */
281 0x98, 0x03, /* voffset low (input) */
282 0x99, 0x00, /* voffset hi (input) */
283 0x9a, 0x12, /* vsize low (input), 0x12 = 18 */
284 0x9b, 0x00, /* vsize hi (input) */
285 0x9c, 0xa0, /* hsize low (output), 0x05a0 = 1440 */
286 0x9d, 0x05, /* hsize hi (output) */
287 0x9e, 0x12, /* vsize low (output), 0x12 = 18 */
288 0x9f, 0x00, /* vsize hi (output) */
291 0xc0, 0x00, /* Task Handling Control */
292 0xc1, 0x08, /* X-port formats/config */
293 0xc2, 0x00, /* Input Ref. signal Def. */
294 0xc3, 0x80, /* I-port config */
295 0xc4, 0x00, /* hoffset low (input), 0x0002 is minimum. See comment at 0x94 above. */
296 0xc5, 0x00, /* hoffset hi (input) */
297 0xc6, 0xd0, /* hsize low (input), 0x02d0 = 720 */
298 0xc7, 0x02, /* hsize hi (input) */
299 0xc8, 0x16, /* voffset low (input), 0x16 = 22 */
300 0xc9, 0x00, /* voffset hi (input) */
301 0xca, 0x20, /* vsize low (input), 0x0120 = 288 */
302 0xcb, 0x01, /* vsize hi (input) */
303 0xcc, 0xd0, /* hsize low (output), 0x02d0 = 720 */
304 0xcd, 0x02, /* hsize hi (output) */
305 0xce, 0x20, /* vsize low (output), 0x0120 = 288 */
306 0xcf, 0x01, /* vsize hi (output) */
308 0xf0, 0xb0, /* Set PLL Register. 50hz 625 lines per frame, 27 MHz */
309 0xf1, 0x05, /* low bit with 0xF0, (was 0x05) */
310 0xf5, 0xb0, /* Set pulse generator register */
313 0x87, 0x00, /* Disable I-port output */
314 0x88, 0xd0, /* reset scaler (was 0xD0) */
315 0x80, 0x20, /* Activate only task "B" */
316 0x88, 0xf0, /* activate scaler */
317 0x87, 0x01, /* Enable I-port output */
321 /* ============== SAA7715 VIDEO templates (end) ======= */
323 static const unsigned char saa7115_cfg_vbi_on[] = {
324 0x80, 0x00, /* reset tasks */
325 0x88, 0xd0, /* reset scaler */
326 0x80, 0x30, /* Activate both tasks */
327 0x88, 0xf0, /* activate scaler */
328 0x87, 0x01, /* Enable I-port output */
332 static const unsigned char saa7115_cfg_vbi_off[] = {
333 0x80, 0x00, /* reset tasks */
334 0x88, 0xd0, /* reset scaler */
335 0x80, 0x20, /* Activate only task "B" */
336 0x88, 0xf0, /* activate scaler */
337 0x87, 0x01, /* Enable I-port output */
341 static const unsigned char saa7115_init_misc[] = {
342 0x38, 0x03, /* audio stuff */
346 0x81, 0x01, /* reg 0x15,0x16 define blanking window */
348 0x83, 0x01, /* I port settings */
355 0xa0, 0x01, /* down scale = 1 */
356 0xa1, 0x00, /* prescale accumulation length = 1 */
357 0xa2, 0x00, /* dc gain and fir prefilter control */
358 0xa4, 0x80, /* Lum Brightness, nominal value = 0x80 */
359 0xa5, 0x40, /* Lum contrast, nominal value = 0x40 */
360 0xa6, 0x40, /* Chroma satur. nominal value = 0x80 */
361 0xa8, 0x00, /* hor lum scaling 0x0200 = 2 zoom */
362 0xa9, 0x02, /* note: 2 x zoom ensures that VBI lines have same length as video lines. */
363 0xaa, 0x00, /* H-phase offset Luma = 0 */
364 0xac, 0x00, /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */
365 0xad, 0x01, /* H-scaling incr chroma */
366 0xae, 0x00, /* H-phase offset chroma. must be offset luma / 2 */
368 0xb0, 0x00, /* V-scaling incr luma low */
369 0xb1, 0x04, /* " hi */
370 0xb2, 0x00, /* V-scaling incr chroma low */
371 0xb3, 0x04, /* " hi */
372 0xb4, 0x01, /* V-scaling mode control */
373 0xb8, 0x00, /* V-phase offset chroma 00 */
374 0xb9, 0x00, /* V-phase offset chroma 01 */
375 0xba, 0x00, /* V-phase offset chroma 10 */
376 0xbb, 0x00, /* V-phase offset chroma 11 */
377 0xbc, 0x00, /* V-phase offset luma 00 */
378 0xbd, 0x00, /* V-phase offset luma 01 */
379 0xbe, 0x00, /* V-phase offset luma 10 */
380 0xbf, 0x00, /* V-phase offset luma 11 */
383 0xd0, 0x01, /* down scale = 1 */
384 0xd1, 0x00, /* prescale accumulation length = 1 */
385 0xd2, 0x00, /* dc gain and fir prefilter control */
386 0xd4, 0x80, /* Lum Brightness, nominal value = 0x80 */
387 0xd5, 0x40, /* Lum contrast, nominal value = 0x40 */
388 0xd6, 0x40, /* Chroma satur. nominal value = 0x80 */
389 0xd8, 0x00, /* hor lum scaling 0x0400 = 1 */
391 0xda, 0x00, /* H-phase offset Luma = 0 */
392 0xdc, 0x00, /* hor chrom scaling 0x0200. must be hor lum scaling / 2 */
393 0xdd, 0x02, /* H-scaling incr chroma */
394 0xde, 0x00, /* H-phase offset chroma. must be offset luma / 2 */
396 0xe0, 0x00, /* V-scaling incr luma low */
397 0xe1, 0x04, /* " hi */
398 0xe2, 0x00, /* V-scaling incr chroma low */
399 0xe3, 0x04, /* " hi */
400 0xe4, 0x01, /* V-scaling mode control */
401 0xe8, 0x00, /* V-phase offset chroma 00 */
402 0xe9, 0x00, /* V-phase offset chroma 01 */
403 0xea, 0x00, /* V-phase offset chroma 10 */
404 0xeb, 0x00, /* V-phase offset chroma 11 */
405 0xec, 0x00, /* V-phase offset luma 00 */
406 0xed, 0x00, /* V-phase offset luma 01 */
407 0xee, 0x00, /* V-phase offset luma 10 */
408 0xef, 0x00, /* V-phase offset luma 11 */
410 0xf2, 0x50, /* crystal clock = 24.576 MHz, target = 27MHz */
413 0xf7, 0x4b, /* not the recommended settings! */
418 0xff, 0x88, /* PLL2 lock detection settings: 71 lines 50% phase error */
421 0x40, 0x20, /* No framing code errors allowed. */
451 0x02, 0x84, /* input tuner -> input 4, amplifier active */
452 0x09, 0x53, /* 0x53, was 0x56 for 60hz. luminance control */
454 0x80, 0x20, /* enable task B */
460 static int saa7115_odd_parity(u8 c)
469 static int saa7115_decode_vps(u8 * dst, u8 * p)
471 static const u8 biphase_tbl[] = {
472 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
473 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
474 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
475 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
476 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
477 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
478 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
479 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
480 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
481 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
482 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
483 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
484 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
485 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
486 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
487 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
488 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
489 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
490 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
491 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
492 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
493 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
494 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
495 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
496 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
497 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
498 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
499 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
500 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
501 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
502 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
503 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
508 for (i = 0; i < 2 * 13; i += 2) {
509 err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
510 c = (biphase_tbl[p[i + 1]] & 0xf) | ((biphase_tbl[p[i]] & 0xf) << 4);
516 static int saa7115_decode_wss(u8 * p)
518 static const int wss_bits[8] = {
519 0, 0, 0, 1, 0, 1, 1, 1
521 unsigned char parity;
525 for (i = 0; i < 16; i++) {
526 int b1 = wss_bits[p[i] & 7];
527 int b2 = wss_bits[(p[i] >> 3) & 7];
534 parity ^= parity >> 2;
535 parity ^= parity >> 1;
544 static int saa7115_set_audio_clock_freq(struct i2c_client *client, u32 freq)
546 struct saa7115_state *state = i2c_get_clientdata(client);
552 v4l_dbg(1, debug, client, "set audio clock freq: %d\n", freq);
555 if (freq < 32000 || freq > 48000)
558 /* hz is the refresh rate times 100 */
559 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
560 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
561 acpf = (25600 * freq) / hz;
562 /* acni = (256 * freq * 2^23) / crystal_frequency =
563 (freq * 2^(8+23)) / crystal_frequency =
564 (freq << 31) / 32.11 MHz */
570 saa7115_write(client, 0x30, acpf & 0xff);
571 saa7115_write(client, 0x31, (acpf >> 8) & 0xff);
572 saa7115_write(client, 0x32, (acpf >> 16) & 0x03);
573 saa7115_write(client, 0x34, acni & 0xff);
574 saa7115_write(client, 0x35, (acni >> 8) & 0xff);
575 saa7115_write(client, 0x36, (acni >> 16) & 0x3f);
576 state->audclk_freq = freq;
580 static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
582 struct saa7115_state *state = i2c_get_clientdata(client);
585 case V4L2_CID_BRIGHTNESS:
586 if (ctrl->value < 0 || ctrl->value > 255) {
587 v4l_err(client, "invalid brightness setting %d\n", ctrl->value);
591 state->bright = ctrl->value;
592 saa7115_write(client, 0x0a, state->bright);
595 case V4L2_CID_CONTRAST:
596 if (ctrl->value < 0 || ctrl->value > 127) {
597 v4l_err(client, "invalid contrast setting %d\n", ctrl->value);
601 state->contrast = ctrl->value;
602 saa7115_write(client, 0x0b, state->contrast);
605 case V4L2_CID_SATURATION:
606 if (ctrl->value < 0 || ctrl->value > 127) {
607 v4l_err(client, "invalid saturation setting %d\n", ctrl->value);
611 state->sat = ctrl->value;
612 saa7115_write(client, 0x0c, state->sat);
616 if (ctrl->value < -127 || ctrl->value > 127) {
617 v4l_err(client, "invalid hue setting %d\n", ctrl->value);
621 state->hue = ctrl->value;
622 saa7115_write(client, 0x0d, state->hue);
632 static int saa7115_get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
634 struct saa7115_state *state = i2c_get_clientdata(client);
637 case V4L2_CID_BRIGHTNESS:
638 ctrl->value = state->bright;
640 case V4L2_CID_CONTRAST:
641 ctrl->value = state->contrast;
643 case V4L2_CID_SATURATION:
644 ctrl->value = state->sat;
647 ctrl->value = state->hue;
656 static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
658 struct saa7115_state *state = i2c_get_clientdata(client);
659 int taskb = saa7115_read(client, 0x80) & 0x10;
661 /* Prevent unnecessary standard changes. During a standard
662 change the I-Port is temporarily disabled. Any devices
663 reading from that port can get confused.
664 Note that VIDIOC_S_STD is also used to switch from
665 radio to TV mode, so if a VIDIOC_S_STD is broadcast to
666 all I2C devices then you do not want to have an unwanted
668 if (std == state->std)
671 // This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
672 if (std & V4L2_STD_525_60) {
673 v4l_dbg(1, debug, client, "decoder set standard 60 Hz\n");
674 saa7115_writeregs(client, saa7115_cfg_60hz_video);
676 v4l_dbg(1, debug, client, "decoder set standard 50 Hz\n");
677 saa7115_writeregs(client, saa7115_cfg_50hz_video);
682 /* restart task B if needed */
683 if (taskb && state->ident == V4L2_IDENT_SAA7114) {
684 saa7115_writeregs(client, saa7115_cfg_vbi_on);
687 /* switch audio mode too! */
688 saa7115_set_audio_clock_freq(client, state->audclk_freq);
691 static v4l2_std_id saa7115_get_v4lstd(struct i2c_client *client)
693 struct saa7115_state *state = i2c_get_clientdata(client);
698 static void saa7115_log_status(struct i2c_client *client)
700 struct saa7115_state *state = i2c_get_clientdata(client);
705 v4l_info(client, "Audio frequency: %d Hz\n", state->audclk_freq);
706 if (client->name[6] == '4') {
707 /* status for the saa7114 */
708 reg1f = saa7115_read(client, 0x1f);
709 signalOk = (reg1f & 0xc1) == 0x81;
710 v4l_info(client, "Video signal: %s\n", signalOk ? "ok" : "bad");
711 v4l_info(client, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
715 /* status for the saa7115 */
716 reg1e = saa7115_read(client, 0x1e);
717 reg1f = saa7115_read(client, 0x1f);
719 signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
720 vcr = !(reg1f & 0x10);
722 if (state->input >= 6) {
723 v4l_info(client, "Input: S-Video %d\n", state->input - 6);
725 v4l_info(client, "Input: Composite %d\n", state->input);
727 v4l_info(client, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
728 v4l_info(client, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
730 switch (reg1e & 0x03) {
732 v4l_info(client, "Detected format: NTSC\n");
735 v4l_info(client, "Detected format: PAL\n");
738 v4l_info(client, "Detected format: SECAM\n");
741 v4l_info(client, "Detected format: BW/No color\n");
746 /* setup the sliced VBI lcr registers according to the sliced VBI format */
747 static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_format *fmt)
749 struct saa7115_state *state = i2c_get_clientdata(client);
750 int is_50hz = (state->std & V4L2_STD_625_50);
754 /* saa7114 doesn't yet support VBI */
755 if (state->ident == V4L2_IDENT_SAA7114)
758 for (i = 0; i <= 23; i++)
761 if (fmt->service_set == 0) {
764 for (i = 6; i <= 23; i++)
767 for (i = 10; i <= 21; i++)
771 /* first clear lines that cannot be captured */
773 for (i = 0; i <= 5; i++)
774 fmt->service_lines[0][i] =
775 fmt->service_lines[1][i] = 0;
778 for (i = 0; i <= 9; i++)
779 fmt->service_lines[0][i] =
780 fmt->service_lines[1][i] = 0;
781 for (i = 22; i <= 23; i++)
782 fmt->service_lines[0][i] =
783 fmt->service_lines[1][i] = 0;
786 /* Now set the lcr values according to the specified service */
787 for (i = 6; i <= 23; i++) {
789 for (x = 0; x <= 1; x++) {
790 switch (fmt->service_lines[1-x][i]) {
792 lcr[i] |= 0xf << (4 * x);
794 case V4L2_SLICED_TELETEXT_B:
795 lcr[i] |= 1 << (4 * x);
797 case V4L2_SLICED_CAPTION_525:
798 lcr[i] |= 4 << (4 * x);
800 case V4L2_SLICED_WSS_625:
801 lcr[i] |= 5 << (4 * x);
803 case V4L2_SLICED_VPS:
804 lcr[i] |= 7 << (4 * x);
811 /* write the lcr registers */
812 for (i = 2; i <= 23; i++) {
813 saa7115_write(client, i - 2 + 0x41, lcr[i]);
816 /* enable/disable raw VBI capturing */
817 saa7115_writeregs(client, fmt->service_set == 0 ? saa7115_cfg_vbi_on : saa7115_cfg_vbi_off);
820 static int saa7115_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
822 static u16 lcr2vbi[] = {
823 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
824 0, V4L2_SLICED_CAPTION_525, /* 4 */
825 V4L2_SLICED_WSS_625, 0, /* 5 */
826 V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */
829 struct v4l2_sliced_vbi_format *sliced = &fmt->fmt.sliced;
832 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
834 memset(sliced, 0, sizeof(*sliced));
835 /* done if using raw VBI */
836 if (saa7115_read(client, 0x80) & 0x10)
838 for (i = 2; i <= 23; i++) {
839 u8 v = saa7115_read(client, i - 2 + 0x41);
841 sliced->service_lines[0][i] = lcr2vbi[v >> 4];
842 sliced->service_lines[1][i] = lcr2vbi[v & 0xf];
843 sliced->service_set |=
844 sliced->service_lines[0][i] | sliced->service_lines[1][i];
849 static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
851 struct saa7115_state *state = i2c_get_clientdata(client);
852 struct v4l2_pix_format *pix;
855 int is_50hz = state->std & V4L2_STD_625_50;
857 if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
858 saa7115_set_lcr(client, &fmt->fmt.sliced);
861 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
864 pix = &(fmt->fmt.pix);
866 v4l_dbg(1, debug, client, "decoder set size\n");
868 /* FIXME need better bounds checking here */
869 if ((pix->width < 1) || (pix->width > 1440))
871 if ((pix->height < 1) || (pix->height > 960))
874 /* probably have a valid size, let's set it */
875 /* Set output width/height */
877 saa7115_write(client, 0xcc, (u8) (pix->width & 0xff));
878 saa7115_write(client, 0xcd, (u8) ((pix->width >> 8) & 0xff));
880 saa7115_write(client, 0xce, (u8) (pix->height & 0xff));
881 saa7115_write(client, 0xcf, (u8) ((pix->height >> 8) & 0xff));
883 /* Scaling settings */
884 /* Hprescaler is floor(inres/outres) */
885 /* FIXME hardcoding input res */
886 if (pix->width != 720) {
887 HPSC = (int)(720 / pix->width);
888 /* 0 is not allowed (div. by zero) */
889 HPSC = HPSC ? HPSC : 1;
890 HFSC = (int)((1024 * 720) / (HPSC * pix->width));
892 v4l_dbg(1, debug, client, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
893 /* FIXME hardcodes to "Task B"
894 * write H prescaler integer */
895 saa7115_write(client, 0xd0, (u8) (HPSC & 0x3f));
897 /* write H fine-scaling (luminance) */
898 saa7115_write(client, 0xd8, (u8) (HFSC & 0xff));
899 saa7115_write(client, 0xd9, (u8) ((HFSC >> 8) & 0xff));
900 /* write H fine-scaling (chrominance)
901 * must be lum/2, so i'll just bitshift :) */
902 saa7115_write(client, 0xDC, (u8) ((HFSC >> 1) & 0xff));
903 saa7115_write(client, 0xDD, (u8) ((HFSC >> 9) & 0xff));
906 v4l_dbg(1, debug, client, "Setting full 50hz width\n");
907 saa7115_writeregs(client, saa7115_cfg_50hz_fullres_x);
909 v4l_dbg(1, debug, client, "Setting full 60hz width\n");
910 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x);
914 Vsrc = is_50hz ? 576 : 480;
916 if (pix->height != Vsrc) {
917 VSCY = (int)((1024 * Vsrc) / pix->height);
918 v4l_dbg(1, debug, client, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
920 /* Correct Contrast and Luminance */
921 saa7115_write(client, 0xd5, (u8) (64 * 1024 / VSCY));
922 saa7115_write(client, 0xd6, (u8) (64 * 1024 / VSCY));
924 /* write V fine-scaling (luminance) */
925 saa7115_write(client, 0xe0, (u8) (VSCY & 0xff));
926 saa7115_write(client, 0xe1, (u8) ((VSCY >> 8) & 0xff));
927 /* write V fine-scaling (chrominance) */
928 saa7115_write(client, 0xe2, (u8) (VSCY & 0xff));
929 saa7115_write(client, 0xe3, (u8) ((VSCY >> 8) & 0xff));
932 v4l_dbg(1, debug, client, "Setting full 50Hz height\n");
933 saa7115_writeregs(client, saa7115_cfg_50hz_fullres_y);
935 v4l_dbg(1, debug, client, "Setting full 60hz height\n");
936 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y);
940 saa7115_writeregs(client, saa7115_cfg_reset_scaler);
944 /* Decode the sliced VBI data stream as created by the saa7115.
945 The format is described in the saa7115 datasheet in Tables 25 and 26
947 The current implementation uses SAV/EAV codes and not the ancillary data
948 headers. The vbi->p pointer points to the SDID byte right after the SAV
950 static void saa7115_decode_vbi_line(struct i2c_client *client,
951 struct v4l2_decode_vbi_line *vbi)
953 static const char vbi_no_data_pattern[] = {
954 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0
956 struct saa7115_state *state = i2c_get_clientdata(client);
959 int id1, id2; /* the ID1 and ID2 bytes from the internal header */
961 vbi->type = 0; /* mark result as a failure */
964 /* Note: the field bit is inverted for 60 Hz video */
965 if (state->std & V4L2_STD_525_60)
968 /* Skip internal header, p now points to the start of the payload */
972 /* calculate field and line number of the VBI packet (1-23) */
973 vbi->is_second_field = ((id1 & 0x40) != 0);
974 vbi->line = (id1 & 0x3f) << 3;
975 vbi->line |= (id2 & 0x70) >> 4;
977 /* Obtain data type */
980 /* If the VBI slicer does not detect any signal it will fill up
981 the payload buffer with 0xa0 bytes. */
982 if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern)))
985 /* decode payloads */
988 vbi->type = V4L2_SLICED_TELETEXT_B;
991 if (!saa7115_odd_parity(p[0]) || !saa7115_odd_parity(p[1]))
993 vbi->type = V4L2_SLICED_CAPTION_525;
996 wss = saa7115_decode_wss(p);
1001 vbi->type = V4L2_SLICED_WSS_625;
1004 if (saa7115_decode_vps(p, p) != 0)
1006 vbi->type = V4L2_SLICED_VPS;
1013 /* ============ SAA7115 AUDIO settings (end) ============= */
1015 static struct v4l2_queryctrl saa7115_qctrl[] = {
1017 .id = V4L2_CID_BRIGHTNESS,
1018 .type = V4L2_CTRL_TYPE_INTEGER,
1019 .name = "Brightness",
1023 .default_value = 128,
1026 .id = V4L2_CID_CONTRAST,
1027 .type = V4L2_CTRL_TYPE_INTEGER,
1032 .default_value = 64,
1035 .id = V4L2_CID_SATURATION,
1036 .type = V4L2_CTRL_TYPE_INTEGER,
1037 .name = "Saturation",
1041 .default_value = 64,
1045 .type = V4L2_CTRL_TYPE_INTEGER,
1055 /* ----------------------------------------------------------------------- */
1057 static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg)
1059 struct saa7115_state *state = i2c_get_clientdata(client);
1062 /* ioctls to allow direct access to the saa7115 registers for testing */
1065 return saa7115_set_v4lfmt(client, (struct v4l2_format *)arg);
1068 return saa7115_get_v4lfmt(client, (struct v4l2_format *)arg);
1070 case VIDIOC_INT_AUDIO_CLOCK_FREQ:
1071 return saa7115_set_audio_clock_freq(client, *(u32 *)arg);
1073 case VIDIOC_G_TUNER:
1075 struct v4l2_tuner *vt = arg;
1080 status = saa7115_read(client, 0x1f);
1082 v4l_dbg(1, debug, client, "status: 0x%02x\n", status);
1083 vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
1087 case VIDIOC_LOG_STATUS:
1088 saa7115_log_status(client);
1092 return saa7115_get_v4lctrl(client, (struct v4l2_control *)arg);
1095 return saa7115_set_v4lctrl(client, (struct v4l2_control *)arg);
1097 case VIDIOC_QUERYCTRL:
1099 struct v4l2_queryctrl *qc = arg;
1102 for (i = 0; i < ARRAY_SIZE(saa7115_qctrl); i++)
1103 if (qc->id && qc->id == saa7115_qctrl[i].id) {
1104 memcpy(qc, &saa7115_qctrl[i], sizeof(*qc));
1111 *(v4l2_std_id *)arg = saa7115_get_v4lstd(client);
1116 saa7115_set_v4lstd(client, *(v4l2_std_id *)arg);
1119 case AUDC_SET_RADIO:
1123 case VIDIOC_G_INPUT:
1124 *(int *)arg = state->input;
1127 case VIDIOC_S_INPUT:
1128 v4l_dbg(1, debug, client, "decoder set input %d\n", *iarg);
1129 /* inputs from 0-9 are available */
1130 if (*iarg < 0 || *iarg > 9) {
1134 if (state->input == *iarg)
1136 v4l_dbg(1, debug, client, "now setting %s input\n",
1137 *iarg >= 6 ? "S-Video" : "Composite");
1138 state->input = *iarg;
1141 saa7115_write(client, 0x02,
1142 (saa7115_read(client, 0x02) & 0xf0) |
1145 /* bypass chrominance trap for modes 6..9 */
1146 saa7115_write(client, 0x09,
1147 (saa7115_read(client, 0x09) & 0x7f) |
1148 (state->input < 6 ? 0x0 : 0x80));
1151 case VIDIOC_STREAMON:
1152 case VIDIOC_STREAMOFF:
1153 v4l_dbg(1, debug, client, "%s output\n",
1154 (cmd == VIDIOC_STREAMON) ? "enable" : "disable");
1156 if (state->enable != (cmd == VIDIOC_STREAMON)) {
1157 state->enable = (cmd == VIDIOC_STREAMON);
1158 saa7115_write(client, 0x87, state->enable);
1162 case VIDIOC_INT_DECODE_VBI_LINE:
1163 saa7115_decode_vbi_line(client, arg);
1166 case VIDIOC_INT_RESET:
1167 v4l_dbg(1, debug, client, "decoder RESET\n");
1168 saa7115_writeregs(client, saa7115_cfg_reset_scaler);
1171 case VIDIOC_INT_G_VBI_DATA:
1173 struct v4l2_sliced_vbi_data *data = arg;
1176 case V4L2_SLICED_WSS_625:
1177 if (saa7115_read(client, 0x6b) & 0xc0)
1179 data->data[0] = saa7115_read(client, 0x6c);
1180 data->data[1] = saa7115_read(client, 0x6d);
1182 case V4L2_SLICED_CAPTION_525:
1183 if (data->field == 0) {
1185 if (saa7115_read(client, 0x66) & 0xc0)
1187 data->data[0] = saa7115_read(client, 0x67);
1188 data->data[1] = saa7115_read(client, 0x68);
1192 if (saa7115_read(client, 0x66) & 0x30)
1194 data->data[0] = saa7115_read(client, 0x69);
1195 data->data[1] = saa7115_read(client, 0x6a);
1203 #ifdef CONFIG_VIDEO_ADV_DEBUG
1204 case VIDIOC_INT_G_REGISTER:
1206 struct v4l2_register *reg = arg;
1208 if (reg->i2c_id != I2C_DRIVERID_SAA711X)
1210 reg->val = saa7115_read(client, reg->reg & 0xff);
1214 case VIDIOC_INT_S_REGISTER:
1216 struct v4l2_register *reg = arg;
1218 if (reg->i2c_id != I2C_DRIVERID_SAA711X)
1220 if (!capable(CAP_SYS_ADMIN))
1222 saa7115_write(client, reg->reg & 0xff, reg->val & 0xff);
1227 case VIDIOC_INT_G_CHIP_IDENT:
1228 *iarg = state->ident;
1238 /* ----------------------------------------------------------------------- */
1240 static struct i2c_driver i2c_driver_saa7115;
1242 static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
1244 struct i2c_client *client;
1245 struct saa7115_state *state;
1248 /* Check if the adapter supports the needed features */
1249 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
1252 client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
1255 client->addr = address;
1256 client->adapter = adapter;
1257 client->driver = &i2c_driver_saa7115;
1258 snprintf(client->name, sizeof(client->name) - 1, "saa7115");
1260 v4l_dbg(1, debug, client, "detecting saa7115 client on address 0x%x\n", address << 1);
1262 saa7115_write(client, 0, 5);
1263 chip_id = saa7115_read(client, 0) & 0x0f;
1264 if (chip_id != 4 && chip_id != 5) {
1265 v4l_dbg(1, debug, client, "saa7115 not found\n");
1270 snprintf(client->name, sizeof(client->name) - 1, "saa7114");
1272 v4l_info(client, "saa711%d found @ 0x%x (%s)\n", chip_id, address << 1, adapter->name);
1274 state = kzalloc(sizeof(struct saa7115_state), GFP_KERNEL);
1275 i2c_set_clientdata(client, state);
1276 if (state == NULL) {
1280 state->std = V4L2_STD_NTSC;
1284 state->bright = 128;
1285 state->contrast = 64;
1288 state->ident = (chip_id == 4) ? V4L2_IDENT_SAA7114 : V4L2_IDENT_SAA7115;
1289 state->audclk_freq = 48000;
1291 v4l_dbg(1, debug, client, "writing init values\n");
1293 /* init to 60hz/48khz */
1294 saa7115_writeregs(client, saa7115_init_auto_input);
1295 saa7115_writeregs(client, saa7115_init_misc);
1296 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x);
1297 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y);
1298 saa7115_writeregs(client, saa7115_cfg_60hz_video);
1299 saa7115_set_audio_clock_freq(client, state->audclk_freq);
1300 saa7115_writeregs(client, saa7115_cfg_reset_scaler);
1302 i2c_attach_client(client);
1304 v4l_dbg(1, debug, client, "status: (1E) 0x%02x, (1F) 0x%02x\n",
1305 saa7115_read(client, 0x1e), saa7115_read(client, 0x1f));
1310 static int saa7115_probe(struct i2c_adapter *adapter)
1312 if (adapter->class & I2C_CLASS_TV_ANALOG)
1313 return i2c_probe(adapter, &addr_data, &saa7115_attach);
1317 static int saa7115_detach(struct i2c_client *client)
1319 struct saa7115_state *state = i2c_get_clientdata(client);
1322 err = i2c_detach_client(client);
1332 /* ----------------------------------------------------------------------- */
1334 /* i2c implementation */
1335 static struct i2c_driver i2c_driver_saa7115 = {
1339 .id = I2C_DRIVERID_SAA711X,
1340 .attach_adapter = saa7115_probe,
1341 .detach_client = saa7115_detach,
1342 .command = saa7115_command,
1346 static int __init saa7115_init_module(void)
1348 return i2c_add_driver(&i2c_driver_saa7115);
1351 static void __exit saa7115_cleanup_module(void)
1353 i2c_del_driver(&i2c_driver_saa7115);
1356 module_init(saa7115_init_module);
1357 module_exit(saa7115_cleanup_module);