aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/saa7114.c
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2009-02-18 15:26:06 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 11:42:57 -0400
commit107063c6156a0cbf055e771baafc28a3e3c0fb9b (patch)
tree813a2dc2c1426521167f2f289d7a106aaf2f24ec /drivers/media/video/saa7114.c
parent84c1b09495ea366276726b0df2dcd7898cda9d0f (diff)
V4L/DVB (10714): zoran et al: convert zoran i2c modules to V4L2.
The zoran i2c modules were still using V4L1 internally. Replace this with V4L2. Also deleted saa7111.c and saa7114.c, we use saa7115.c instead. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> [mchehab@redhat.com: fix v4l2_ctrl_query_fill_std merge conflict] Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/saa7114.c')
-rw-r--r--drivers/media/video/saa7114.c1068
1 files changed, 0 insertions, 1068 deletions
diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
deleted file mode 100644
index 7ca709fda5f4..000000000000
--- a/drivers/media/video/saa7114.c
+++ /dev/null
@@ -1,1068 +0,0 @@
1/*
2 * saa7114 - Philips SAA7114H video decoder driver version 0.0.1
3 *
4 * Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com>
5 *
6 * Based on saa7111 driver by Dave Perks
7 *
8 * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
9 *
10 * Slight changes for video timing and attachment output by
11 * Wolfgang Scherr <scherr@net4you.net>
12 *
13 * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
14 * - moved over to linux>=2.4.x i2c protocol (1/1/2003)
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 */
30
31#include <linux/module.h>
32#include <linux/types.h>
33#include <linux/ioctl.h>
34#include <asm/uaccess.h>
35#include <linux/i2c.h>
36#include <linux/i2c-id.h>
37#include <linux/videodev.h>
38#include <linux/video_decoder.h>
39#include <media/v4l2-common.h>
40#include <media/v4l2-i2c-drv-legacy.h>
41
42MODULE_DESCRIPTION("Philips SAA7114H video decoder driver");
43MODULE_AUTHOR("Maxim Yevtyushkin");
44MODULE_LICENSE("GPL");
45
46static int debug;
47module_param(debug, int, 0);
48MODULE_PARM_DESC(debug, "Debug level (0-1)");
49
50/* ----------------------------------------------------------------------- */
51
52struct saa7114 {
53 unsigned char reg[0xf0 * 2];
54
55 int norm;
56 int input;
57 int enable;
58 int bright;
59 int contrast;
60 int hue;
61 int sat;
62 int playback;
63};
64
65#define I2C_DELAY 10
66
67
68//#define SAA_7114_NTSC_HSYNC_START (-3)
69//#define SAA_7114_NTSC_HSYNC_STOP (-18)
70
71#define SAA_7114_NTSC_HSYNC_START (-17)
72#define SAA_7114_NTSC_HSYNC_STOP (-32)
73
74//#define SAA_7114_NTSC_HOFFSET (5)
75#define SAA_7114_NTSC_HOFFSET (6)
76#define SAA_7114_NTSC_VOFFSET (10)
77#define SAA_7114_NTSC_WIDTH (720)
78#define SAA_7114_NTSC_HEIGHT (250)
79
80#define SAA_7114_SECAM_HSYNC_START (-17)
81#define SAA_7114_SECAM_HSYNC_STOP (-32)
82
83#define SAA_7114_SECAM_HOFFSET (2)
84#define SAA_7114_SECAM_VOFFSET (10)
85#define SAA_7114_SECAM_WIDTH (720)
86#define SAA_7114_SECAM_HEIGHT (300)
87
88#define SAA_7114_PAL_HSYNC_START (-17)
89#define SAA_7114_PAL_HSYNC_STOP (-32)
90
91#define SAA_7114_PAL_HOFFSET (2)
92#define SAA_7114_PAL_VOFFSET (10)
93#define SAA_7114_PAL_WIDTH (720)
94#define SAA_7114_PAL_HEIGHT (300)
95
96
97
98#define SAA_7114_VERTICAL_CHROMA_OFFSET 0 //0x50504040
99#define SAA_7114_VERTICAL_LUMA_OFFSET 0
100
101#define REG_ADDR(x) (((x) << 1) + 1)
102#define LOBYTE(x) ((unsigned char)((x) & 0xff))
103#define HIBYTE(x) ((unsigned char)(((x) >> 8) & 0xff))
104#define LOWORD(x) ((unsigned short int)((x) & 0xffff))
105#define HIWORD(x) ((unsigned short int)(((x) >> 16) & 0xffff))
106
107
108/* ----------------------------------------------------------------------- */
109
110static inline int saa7114_write(struct i2c_client *client, u8 reg, u8 value)
111{
112 return i2c_smbus_write_byte_data(client, reg, value);
113}
114
115static int saa7114_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
116{
117 int ret = -1;
118 u8 reg;
119
120 /* the saa7114 has an autoincrement function, use it if
121 * the adapter understands raw I2C */
122 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
123 /* do raw I2C, not smbus compatible */
124 u8 block_data[32];
125 int block_len;
126
127 while (len >= 2) {
128 block_len = 0;
129 block_data[block_len++] = reg = data[0];
130 do {
131 block_data[block_len++] = data[1];
132 reg++;
133 len -= 2;
134 data += 2;
135 } while (len >= 2 && data[0] == reg && block_len < 32);
136 ret = i2c_master_send(client, block_data, block_len);
137 if (ret < 0)
138 break;
139 }
140 } else {
141 /* do some slow I2C emulation kind of thing */
142 while (len >= 2) {
143 reg = *data++;
144 ret = saa7114_write(client, reg, *data++);
145 if (ret < 0)
146 break;
147 len -= 2;
148 }
149 }
150
151 return ret;
152}
153
154static inline int saa7114_read(struct i2c_client *client, u8 reg)
155{
156 return i2c_smbus_read_byte_data(client, reg);
157}
158
159/* ----------------------------------------------------------------------- */
160
161// initially set NTSC, composite
162
163
164static const unsigned char init[] = {
165 0x00, 0x00, /* 00 - ID byte , chip version,
166 * read only */
167 0x01, 0x08, /* 01 - X,X,X,X, IDEL3 to IDEL0 -
168 * horizontal increment delay,
169 * recommended position */
170 0x02, 0x00, /* 02 - FUSE=3, GUDL=2, MODE=0 ;
171 * input control */
172 0x03, 0x10, /* 03 - HLNRS=0, VBSL=1, WPOFF=0,
173 * HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */
174 0x04, 0x90, /* 04 - GAI1=256 */
175 0x05, 0x90, /* 05 - GAI2=256 */
176 0x06, SAA_7114_NTSC_HSYNC_START, /* 06 - HSB: hsync start,
177 * depends on the video standard */
178 0x07, SAA_7114_NTSC_HSYNC_STOP, /* 07 - HSS: hsync stop, depends
179 *on the video standard */
180 0x08, 0xb8, /* 08 - AUFD=1, FSEL=1, EXFIL=0, VTRC=1,
181 * HPLL: free running in playback, locked
182 * in capture, VNOI=0 */
183 0x09, 0x80, /* 09 - BYPS=0, PREF=0, BPSS=0, VBLB=0,
184 * UPTCV=0, APER=1; depends from input */
185 0x0a, 0x80, /* 0a - BRIG=128 */
186 0x0b, 0x44, /* 0b - CONT=1.109 */
187 0x0c, 0x40, /* 0c - SATN=1.0 */
188 0x0d, 0x00, /* 0d - HUE=0 */
189 0x0e, 0x84, /* 0e - CDTO, CSTD2 to 0, DCVF, FCTC,
190 * CCOMB; depends from video standard */
191 0x0f, 0x24, /* 0f - ACGC,CGAIN6 to CGAIN0; depends
192 * from video standard */
193 0x10, 0x03, /* 10 - OFFU1 to 0, OFFV1 to 0, CHBW,
194 * LCBW2 to 0 */
195 0x11, 0x59, /* 11 - COLO, RTP1, HEDL1 to 0, RTP0,
196 * YDEL2 to 0 */
197 0x12, 0xc9, /* 12 - RT signal control RTSE13 to 10
198 * and 03 to 00 */
199 0x13, 0x80, /* 13 - RT/X port output control */
200 0x14, 0x00, /* 14 - analog, ADC, compatibility control */
201 0x15, 0x00, /* 15 - VGATE start FID change */
202 0x16, 0xfe, /* 16 - VGATE stop */
203 0x17, 0x00, /* 17 - Misc., VGATE MSBs */
204 0x18, 0x40, /* RAWG */
205 0x19, 0x80, /* RAWO */
206 0x1a, 0x00,
207 0x1b, 0x00,
208 0x1c, 0x00,
209 0x1d, 0x00,
210 0x1e, 0x00,
211 0x1f, 0x00, /* status byte, read only */
212 0x20, 0x00, /* video decoder reserved part */
213 0x21, 0x00,
214 0x22, 0x00,
215 0x23, 0x00,
216 0x24, 0x00,
217 0x25, 0x00,
218 0x26, 0x00,
219 0x27, 0x00,
220 0x28, 0x00,
221 0x29, 0x00,
222 0x2a, 0x00,
223 0x2b, 0x00,
224 0x2c, 0x00,
225 0x2d, 0x00,
226 0x2e, 0x00,
227 0x2f, 0x00,
228 0x30, 0xbc, /* audio clock generator */
229 0x31, 0xdf,
230 0x32, 0x02,
231 0x33, 0x00,
232 0x34, 0xcd,
233 0x35, 0xcc,
234 0x36, 0x3a,
235 0x37, 0x00,
236 0x38, 0x03,
237 0x39, 0x10,
238 0x3a, 0x00,
239 0x3b, 0x00,
240 0x3c, 0x00,
241 0x3d, 0x00,
242 0x3e, 0x00,
243 0x3f, 0x00,
244 0x40, 0x00, /* VBI data slicer */
245 0x41, 0xff,
246 0x42, 0xff,
247 0x43, 0xff,
248 0x44, 0xff,
249 0x45, 0xff,
250 0x46, 0xff,
251 0x47, 0xff,
252 0x48, 0xff,
253 0x49, 0xff,
254 0x4a, 0xff,
255 0x4b, 0xff,
256 0x4c, 0xff,
257 0x4d, 0xff,
258 0x4e, 0xff,
259 0x4f, 0xff,
260 0x50, 0xff,
261 0x51, 0xff,
262 0x52, 0xff,
263 0x53, 0xff,
264 0x54, 0xff,
265 0x55, 0xff,
266 0x56, 0xff,
267 0x57, 0xff,
268 0x58, 0x40, // framing code
269 0x59, 0x47, // horizontal offset
270 0x5a, 0x06, // vertical offset
271 0x5b, 0x83, // field offset
272 0x5c, 0x00, // reserved
273 0x5d, 0x3e, // header and data
274 0x5e, 0x00, // sliced data
275 0x5f, 0x00, // reserved
276 0x60, 0x00, /* video decoder reserved part */
277 0x61, 0x00,
278 0x62, 0x00,
279 0x63, 0x00,
280 0x64, 0x00,
281 0x65, 0x00,
282 0x66, 0x00,
283 0x67, 0x00,
284 0x68, 0x00,
285 0x69, 0x00,
286 0x6a, 0x00,
287 0x6b, 0x00,
288 0x6c, 0x00,
289 0x6d, 0x00,
290 0x6e, 0x00,
291 0x6f, 0x00,
292 0x70, 0x00, /* video decoder reserved part */
293 0x71, 0x00,
294 0x72, 0x00,
295 0x73, 0x00,
296 0x74, 0x00,
297 0x75, 0x00,
298 0x76, 0x00,
299 0x77, 0x00,
300 0x78, 0x00,
301 0x79, 0x00,
302 0x7a, 0x00,
303 0x7b, 0x00,
304 0x7c, 0x00,
305 0x7d, 0x00,
306 0x7e, 0x00,
307 0x7f, 0x00,
308 0x80, 0x00, /* X-port, I-port and scaler */
309 0x81, 0x00,
310 0x82, 0x00,
311 0x83, 0x00,
312 0x84, 0xc5,
313 0x85, 0x0d, // hsync and vsync ?
314 0x86, 0x40,
315 0x87, 0x01,
316 0x88, 0x00,
317 0x89, 0x00,
318 0x8a, 0x00,
319 0x8b, 0x00,
320 0x8c, 0x00,
321 0x8d, 0x00,
322 0x8e, 0x00,
323 0x8f, 0x00,
324 0x90, 0x03, /* Task A definition */
325 0x91, 0x08,
326 0x92, 0x00,
327 0x93, 0x40,
328 0x94, 0x00, // window settings
329 0x95, 0x00,
330 0x96, 0x00,
331 0x97, 0x00,
332 0x98, 0x00,
333 0x99, 0x00,
334 0x9a, 0x00,
335 0x9b, 0x00,
336 0x9c, 0x00,
337 0x9d, 0x00,
338 0x9e, 0x00,
339 0x9f, 0x00,
340 0xa0, 0x01, /* horizontal integer prescaling ratio */
341 0xa1, 0x00, /* horizontal prescaler accumulation
342 * sequence length */
343 0xa2, 0x00, /* UV FIR filter, Y FIR filter, prescaler
344 * DC gain */
345 0xa3, 0x00,
346 0xa4, 0x80, // luminance brightness
347 0xa5, 0x40, // luminance gain
348 0xa6, 0x40, // chrominance saturation
349 0xa7, 0x00,
350 0xa8, 0x00, // horizontal luminance scaling increment
351 0xa9, 0x04,
352 0xaa, 0x00, // horizontal luminance phase offset
353 0xab, 0x00,
354 0xac, 0x00, // horizontal chrominance scaling increment
355 0xad, 0x02,
356 0xae, 0x00, // horizontal chrominance phase offset
357 0xaf, 0x00,
358 0xb0, 0x00, // vertical luminance scaling increment
359 0xb1, 0x04,
360 0xb2, 0x00, // vertical chrominance scaling increment
361 0xb3, 0x04,
362 0xb4, 0x00,
363 0xb5, 0x00,
364 0xb6, 0x00,
365 0xb7, 0x00,
366 0xb8, 0x00,
367 0xb9, 0x00,
368 0xba, 0x00,
369 0xbb, 0x00,
370 0xbc, 0x00,
371 0xbd, 0x00,
372 0xbe, 0x00,
373 0xbf, 0x00,
374 0xc0, 0x02, // Task B definition
375 0xc1, 0x08,
376 0xc2, 0x00,
377 0xc3, 0x40,
378 0xc4, 0x00, // window settings
379 0xc5, 0x00,
380 0xc6, 0x00,
381 0xc7, 0x00,
382 0xc8, 0x00,
383 0xc9, 0x00,
384 0xca, 0x00,
385 0xcb, 0x00,
386 0xcc, 0x00,
387 0xcd, 0x00,
388 0xce, 0x00,
389 0xcf, 0x00,
390 0xd0, 0x01, // horizontal integer prescaling ratio
391 0xd1, 0x00, // horizontal prescaler accumulation sequence length
392 0xd2, 0x00, // UV FIR filter, Y FIR filter, prescaler DC gain
393 0xd3, 0x00,
394 0xd4, 0x80, // luminance brightness
395 0xd5, 0x40, // luminance gain
396 0xd6, 0x40, // chrominance saturation
397 0xd7, 0x00,
398 0xd8, 0x00, // horizontal luminance scaling increment
399 0xd9, 0x04,
400 0xda, 0x00, // horizontal luminance phase offset
401 0xdb, 0x00,
402 0xdc, 0x00, // horizontal chrominance scaling increment
403 0xdd, 0x02,
404 0xde, 0x00, // horizontal chrominance phase offset
405 0xdf, 0x00,
406 0xe0, 0x00, // vertical luminance scaling increment
407 0xe1, 0x04,
408 0xe2, 0x00, // vertical chrominance scaling increment
409 0xe3, 0x04,
410 0xe4, 0x00,
411 0xe5, 0x00,
412 0xe6, 0x00,
413 0xe7, 0x00,
414 0xe8, 0x00,
415 0xe9, 0x00,
416 0xea, 0x00,
417 0xeb, 0x00,
418 0xec, 0x00,
419 0xed, 0x00,
420 0xee, 0x00,
421 0xef, 0x00
422};
423
424static int saa7114_command(struct i2c_client *client, unsigned cmd, void *arg)
425{
426 struct saa7114 *decoder = i2c_get_clientdata(client);
427
428 switch (cmd) {
429 case 0:
430 //dprintk(1, KERN_INFO "%s: writing init\n", I2C_NAME(client));
431 //saa7114_write_block(client, init, sizeof(init));
432 break;
433
434 case DECODER_DUMP:
435 {
436 int i;
437
438 if (!debug)
439 break;
440 v4l_info(client, "decoder dump\n");
441
442 for (i = 0; i < 32; i += 16) {
443 int j;
444
445 v4l_info(client, "%03x", i);
446 for (j = 0; j < 16; ++j) {
447 printk(KERN_CONT " %02x",
448 saa7114_read(client, i + j));
449 }
450 printk(KERN_CONT "\n");
451 }
452 break;
453 }
454
455 case DECODER_GET_CAPABILITIES:
456 {
457 struct video_decoder_capability *cap = arg;
458
459 v4l_dbg(1, debug, client, "get capabilities\n");
460
461 cap->flags = VIDEO_DECODER_PAL |
462 VIDEO_DECODER_NTSC |
463 VIDEO_DECODER_AUTO |
464 VIDEO_DECODER_CCIR;
465 cap->inputs = 8;
466 cap->outputs = 1;
467 break;
468 }
469
470 case DECODER_GET_STATUS:
471 {
472 int *iarg = arg;
473 int status;
474 int res;
475
476 status = saa7114_read(client, 0x1f);
477
478 v4l_dbg(1, debug, client, "status: 0x%02x\n", status);
479 res = 0;
480 if ((status & (1 << 6)) == 0) {
481 res |= DECODER_STATUS_GOOD;
482 }
483 switch (decoder->norm) {
484 case VIDEO_MODE_NTSC:
485 res |= DECODER_STATUS_NTSC;
486 break;
487 case VIDEO_MODE_PAL:
488 res |= DECODER_STATUS_PAL;
489 break;
490 case VIDEO_MODE_SECAM:
491 res |= DECODER_STATUS_SECAM;
492 break;
493 default:
494 case VIDEO_MODE_AUTO:
495 if ((status & (1 << 5)) != 0) {
496 res |= DECODER_STATUS_NTSC;
497 } else {
498 res |= DECODER_STATUS_PAL;
499 }
500 break;
501 }
502 if ((status & (1 << 0)) != 0) {
503 res |= DECODER_STATUS_COLOR;
504 }
505 *iarg = res;
506 break;
507 }
508
509 case DECODER_SET_NORM:
510 {
511 int *iarg = arg;
512
513 short int hoff = 0, voff = 0, w = 0, h = 0;
514
515 v4l_dbg(1, debug, client, "set norm\n");
516
517 switch (*iarg) {
518 case VIDEO_MODE_NTSC:
519 v4l_dbg(1, debug, client, "NTSC\n");
520 decoder->reg[REG_ADDR(0x06)] =
521 SAA_7114_NTSC_HSYNC_START;
522 decoder->reg[REG_ADDR(0x07)] =
523 SAA_7114_NTSC_HSYNC_STOP;
524
525 decoder->reg[REG_ADDR(0x08)] = decoder->playback ? 0x7c : 0xb8; // PLL free when playback, PLL close when capture
526
527 decoder->reg[REG_ADDR(0x0e)] = 0x85;
528 decoder->reg[REG_ADDR(0x0f)] = 0x24;
529
530 hoff = SAA_7114_NTSC_HOFFSET;
531 voff = SAA_7114_NTSC_VOFFSET;
532 w = SAA_7114_NTSC_WIDTH;
533 h = SAA_7114_NTSC_HEIGHT;
534
535 break;
536
537 case VIDEO_MODE_PAL:
538 v4l_dbg(1, debug, client, "PAL\n");
539 decoder->reg[REG_ADDR(0x06)] =
540 SAA_7114_PAL_HSYNC_START;
541 decoder->reg[REG_ADDR(0x07)] =
542 SAA_7114_PAL_HSYNC_STOP;
543
544 decoder->reg[REG_ADDR(0x08)] = decoder->playback ? 0x7c : 0xb8; // PLL free when playback, PLL close when capture
545
546 decoder->reg[REG_ADDR(0x0e)] = 0x81;
547 decoder->reg[REG_ADDR(0x0f)] = 0x24;
548
549 hoff = SAA_7114_PAL_HOFFSET;
550 voff = SAA_7114_PAL_VOFFSET;
551 w = SAA_7114_PAL_WIDTH;
552 h = SAA_7114_PAL_HEIGHT;
553
554 break;
555
556 default:
557 v4l_dbg(1, debug, client, "Unknown video mode\n");
558 return -EINVAL;
559 }
560
561
562 decoder->reg[REG_ADDR(0x94)] = LOBYTE(hoff); // hoffset low
563 decoder->reg[REG_ADDR(0x95)] = HIBYTE(hoff) & 0x0f; // hoffset high
564 decoder->reg[REG_ADDR(0x96)] = LOBYTE(w); // width low
565 decoder->reg[REG_ADDR(0x97)] = HIBYTE(w) & 0x0f; // width high
566 decoder->reg[REG_ADDR(0x98)] = LOBYTE(voff); // voffset low
567 decoder->reg[REG_ADDR(0x99)] = HIBYTE(voff) & 0x0f; // voffset high
568 decoder->reg[REG_ADDR(0x9a)] = LOBYTE(h + 2); // height low
569 decoder->reg[REG_ADDR(0x9b)] = HIBYTE(h + 2) & 0x0f; // height high
570 decoder->reg[REG_ADDR(0x9c)] = LOBYTE(w); // out width low
571 decoder->reg[REG_ADDR(0x9d)] = HIBYTE(w) & 0x0f; // out width high
572 decoder->reg[REG_ADDR(0x9e)] = LOBYTE(h); // out height low
573 decoder->reg[REG_ADDR(0x9f)] = HIBYTE(h) & 0x0f; // out height high
574
575 decoder->reg[REG_ADDR(0xc4)] = LOBYTE(hoff); // hoffset low
576 decoder->reg[REG_ADDR(0xc5)] = HIBYTE(hoff) & 0x0f; // hoffset high
577 decoder->reg[REG_ADDR(0xc6)] = LOBYTE(w); // width low
578 decoder->reg[REG_ADDR(0xc7)] = HIBYTE(w) & 0x0f; // width high
579 decoder->reg[REG_ADDR(0xc8)] = LOBYTE(voff); // voffset low
580 decoder->reg[REG_ADDR(0xc9)] = HIBYTE(voff) & 0x0f; // voffset high
581 decoder->reg[REG_ADDR(0xca)] = LOBYTE(h + 2); // height low
582 decoder->reg[REG_ADDR(0xcb)] = HIBYTE(h + 2) & 0x0f; // height high
583 decoder->reg[REG_ADDR(0xcc)] = LOBYTE(w); // out width low
584 decoder->reg[REG_ADDR(0xcd)] = HIBYTE(w) & 0x0f; // out width high
585 decoder->reg[REG_ADDR(0xce)] = LOBYTE(h); // out height low
586 decoder->reg[REG_ADDR(0xcf)] = HIBYTE(h) & 0x0f; // out height high
587
588
589 saa7114_write(client, 0x80, 0x06); // i-port and scaler back end clock selection, task A&B off
590 saa7114_write(client, 0x88, 0xd8); // sw reset scaler
591 saa7114_write(client, 0x88, 0xf8); // sw reset scaler release
592
593 saa7114_write_block(client, decoder->reg + (0x06 << 1),
594 3 << 1);
595 saa7114_write_block(client, decoder->reg + (0x0e << 1),
596 2 << 1);
597 saa7114_write_block(client, decoder->reg + (0x5a << 1),
598 2 << 1);
599
600 saa7114_write_block(client, decoder->reg + (0x94 << 1),
601 (0x9f + 1 - 0x94) << 1);
602 saa7114_write_block(client, decoder->reg + (0xc4 << 1),
603 (0xcf + 1 - 0xc4) << 1);
604
605 saa7114_write(client, 0x88, 0xd8); // sw reset scaler
606 saa7114_write(client, 0x88, 0xf8); // sw reset scaler release
607 saa7114_write(client, 0x80, 0x36); // i-port and scaler back end clock selection
608
609 decoder->norm = *iarg;
610 break;
611 }
612
613 case DECODER_SET_INPUT:
614 {
615 int *iarg = arg;
616
617 v4l_dbg(1, debug, client, "set input (%d)\n", *iarg);
618 if (*iarg < 0 || *iarg > 7) {
619 return -EINVAL;
620 }
621
622 if (decoder->input != *iarg) {
623 v4l_dbg(1, debug, client, "now setting %s input\n",
624 *iarg >= 6 ? "S-Video" : "Composite");
625 decoder->input = *iarg;
626
627 /* select mode */
628 decoder->reg[REG_ADDR(0x02)] =
629 (decoder->
630 reg[REG_ADDR(0x02)] & 0xf0) | (decoder->
631 input <
632 6 ? 0x0 : 0x9);
633 saa7114_write(client, 0x02,
634 decoder->reg[REG_ADDR(0x02)]);
635
636 /* bypass chrominance trap for modes 6..9 */
637 decoder->reg[REG_ADDR(0x09)] =
638 (decoder->
639 reg[REG_ADDR(0x09)] & 0x7f) | (decoder->
640 input <
641 6 ? 0x0 :
642 0x80);
643 saa7114_write(client, 0x09,
644 decoder->reg[REG_ADDR(0x09)]);
645
646 decoder->reg[REG_ADDR(0x0e)] =
647 decoder->input <
648 6 ? decoder->
649 reg[REG_ADDR(0x0e)] | 1 : decoder->
650 reg[REG_ADDR(0x0e)] & ~1;
651 saa7114_write(client, 0x0e,
652 decoder->reg[REG_ADDR(0x0e)]);
653 }
654 break;
655 }
656
657 case DECODER_SET_OUTPUT:
658 {
659 int *iarg = arg;
660
661 v4l_dbg(1, debug, client, "set output\n");
662
663 /* not much choice of outputs */
664 if (*iarg != 0) {
665 return -EINVAL;
666 }
667 break;
668 }
669
670 case DECODER_ENABLE_OUTPUT:
671 {
672 int *iarg = arg;
673 int enable = (*iarg != 0);
674
675 v4l_dbg(1, debug, client, "%s output\n",
676 enable ? "enable" : "disable");
677
678 decoder->playback = !enable;
679
680 if (decoder->enable != enable) {
681 decoder->enable = enable;
682
683 /* RJ: If output should be disabled (for
684 * playing videos), we also need a open PLL.
685 * The input is set to 0 (where no input
686 * source is connected), although this
687 * is not necessary.
688 *
689 * If output should be enabled, we have to
690 * reverse the above.
691 */
692
693 if (decoder->enable) {
694 decoder->reg[REG_ADDR(0x08)] = 0xb8;
695 decoder->reg[REG_ADDR(0x12)] = 0xc9;
696 decoder->reg[REG_ADDR(0x13)] = 0x80;
697 decoder->reg[REG_ADDR(0x87)] = 0x01;
698 } else {
699 decoder->reg[REG_ADDR(0x08)] = 0x7c;
700 decoder->reg[REG_ADDR(0x12)] = 0x00;
701 decoder->reg[REG_ADDR(0x13)] = 0x00;
702 decoder->reg[REG_ADDR(0x87)] = 0x00;
703 }
704
705 saa7114_write_block(client,
706 decoder->reg + (0x12 << 1),
707 2 << 1);
708 saa7114_write(client, 0x08,
709 decoder->reg[REG_ADDR(0x08)]);
710 saa7114_write(client, 0x87,
711 decoder->reg[REG_ADDR(0x87)]);
712 saa7114_write(client, 0x88, 0xd8); // sw reset scaler
713 saa7114_write(client, 0x88, 0xf8); // sw reset scaler release
714 saa7114_write(client, 0x80, 0x36);
715
716 }
717 break;
718 }
719
720 case DECODER_SET_PICTURE:
721 {
722 struct video_picture *pic = arg;
723
724 v4l_dbg(1, debug, client,
725 "decoder set picture bright=%d contrast=%d saturation=%d hue=%d\n",
726 pic->brightness, pic->contrast, pic->colour, pic->hue);
727
728 if (decoder->bright != pic->brightness) {
729 /* We want 0 to 255 we get 0-65535 */
730 decoder->bright = pic->brightness;
731 saa7114_write(client, 0x0a, decoder->bright >> 8);
732 }
733 if (decoder->contrast != pic->contrast) {
734 /* We want 0 to 127 we get 0-65535 */
735 decoder->contrast = pic->contrast;
736 saa7114_write(client, 0x0b,
737 decoder->contrast >> 9);
738 }
739 if (decoder->sat != pic->colour) {
740 /* We want 0 to 127 we get 0-65535 */
741 decoder->sat = pic->colour;
742 saa7114_write(client, 0x0c, decoder->sat >> 9);
743 }
744 if (decoder->hue != pic->hue) {
745 /* We want -128 to 127 we get 0-65535 */
746 decoder->hue = pic->hue;
747 saa7114_write(client, 0x0d,
748 (decoder->hue - 32768) >> 8);
749 }
750 break;
751 }
752
753 default:
754 return -EINVAL;
755 }
756
757 return 0;
758}
759
760/* ----------------------------------------------------------------------- */
761
762static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END };
763
764I2C_CLIENT_INSMOD;
765
766static int saa7114_probe(struct i2c_client *client,
767 const struct i2c_device_id *id)
768{
769 int i, err[30];
770 short int hoff = SAA_7114_NTSC_HOFFSET;
771 short int voff = SAA_7114_NTSC_VOFFSET;
772 short int w = SAA_7114_NTSC_WIDTH;
773 short int h = SAA_7114_NTSC_HEIGHT;
774 struct saa7114 *decoder;
775
776 /* Check if the adapter supports the needed features */
777 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
778 return -ENODEV;
779
780 v4l_info(client, "chip found @ 0x%x (%s)\n",
781 client->addr << 1, client->adapter->name);
782
783 decoder = kzalloc(sizeof(struct saa7114), GFP_KERNEL);
784 if (decoder == NULL)
785 return -ENOMEM;
786 decoder->norm = VIDEO_MODE_NTSC;
787 decoder->input = -1;
788 decoder->enable = 1;
789 decoder->bright = 32768;
790 decoder->contrast = 32768;
791 decoder->hue = 32768;
792 decoder->sat = 32768;
793 decoder->playback = 0; // initially capture mode useda
794 i2c_set_clientdata(client, decoder);
795
796 memcpy(decoder->reg, init, sizeof(init));
797
798 decoder->reg[REG_ADDR(0x94)] = LOBYTE(hoff); // hoffset low
799 decoder->reg[REG_ADDR(0x95)] = HIBYTE(hoff) & 0x0f; // hoffset high
800 decoder->reg[REG_ADDR(0x96)] = LOBYTE(w); // width low
801 decoder->reg[REG_ADDR(0x97)] = HIBYTE(w) & 0x0f; // width high
802 decoder->reg[REG_ADDR(0x98)] = LOBYTE(voff); // voffset low
803 decoder->reg[REG_ADDR(0x99)] = HIBYTE(voff) & 0x0f; // voffset high
804 decoder->reg[REG_ADDR(0x9a)] = LOBYTE(h + 2); // height low
805 decoder->reg[REG_ADDR(0x9b)] = HIBYTE(h + 2) & 0x0f; // height high
806 decoder->reg[REG_ADDR(0x9c)] = LOBYTE(w); // out width low
807 decoder->reg[REG_ADDR(0x9d)] = HIBYTE(w) & 0x0f; // out width high
808 decoder->reg[REG_ADDR(0x9e)] = LOBYTE(h); // out height low
809 decoder->reg[REG_ADDR(0x9f)] = HIBYTE(h) & 0x0f; // out height high
810
811 decoder->reg[REG_ADDR(0xc4)] = LOBYTE(hoff); // hoffset low
812 decoder->reg[REG_ADDR(0xc5)] = HIBYTE(hoff) & 0x0f; // hoffset high
813 decoder->reg[REG_ADDR(0xc6)] = LOBYTE(w); // width low
814 decoder->reg[REG_ADDR(0xc7)] = HIBYTE(w) & 0x0f; // width high
815 decoder->reg[REG_ADDR(0xc8)] = LOBYTE(voff); // voffset low
816 decoder->reg[REG_ADDR(0xc9)] = HIBYTE(voff) & 0x0f; // voffset high
817 decoder->reg[REG_ADDR(0xca)] = LOBYTE(h + 2); // height low
818 decoder->reg[REG_ADDR(0xcb)] = HIBYTE(h + 2) & 0x0f; // height high
819 decoder->reg[REG_ADDR(0xcc)] = LOBYTE(w); // out width low
820 decoder->reg[REG_ADDR(0xcd)] = HIBYTE(w) & 0x0f; // out width high
821 decoder->reg[REG_ADDR(0xce)] = LOBYTE(h); // out height low
822 decoder->reg[REG_ADDR(0xcf)] = HIBYTE(h) & 0x0f; // out height high
823
824 decoder->reg[REG_ADDR(0xb8)] =
825 LOBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
826 decoder->reg[REG_ADDR(0xb9)] =
827 HIBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
828 decoder->reg[REG_ADDR(0xba)] =
829 LOBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
830 decoder->reg[REG_ADDR(0xbb)] =
831 HIBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
832
833 decoder->reg[REG_ADDR(0xbc)] =
834 LOBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
835 decoder->reg[REG_ADDR(0xbd)] =
836 HIBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
837 decoder->reg[REG_ADDR(0xbe)] =
838 LOBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
839 decoder->reg[REG_ADDR(0xbf)] =
840 HIBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
841
842 decoder->reg[REG_ADDR(0xe8)] =
843 LOBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
844 decoder->reg[REG_ADDR(0xe9)] =
845 HIBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
846 decoder->reg[REG_ADDR(0xea)] =
847 LOBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
848 decoder->reg[REG_ADDR(0xeb)] =
849 HIBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
850
851 decoder->reg[REG_ADDR(0xec)] =
852 LOBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
853 decoder->reg[REG_ADDR(0xed)] =
854 HIBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
855 decoder->reg[REG_ADDR(0xee)] =
856 LOBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
857 decoder->reg[REG_ADDR(0xef)] =
858 HIBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
859
860
861 decoder->reg[REG_ADDR(0x13)] = 0x80; // RTC0 on
862 decoder->reg[REG_ADDR(0x87)] = 0x01; // I-Port
863 decoder->reg[REG_ADDR(0x12)] = 0xc9; // RTS0
864
865 decoder->reg[REG_ADDR(0x02)] = 0xc0; // set composite1 input, aveasy
866 decoder->reg[REG_ADDR(0x09)] = 0x00; // chrominance trap
867 decoder->reg[REG_ADDR(0x0e)] |= 1; // combfilter on
868
869
870 v4l_dbg(1, debug, client, "starting init\n");
871
872 err[0] =
873 saa7114_write_block(client, decoder->reg + (0x20 << 1),
874 0x10 << 1);
875 err[1] =
876 saa7114_write_block(client, decoder->reg + (0x30 << 1),
877 0x10 << 1);
878 err[2] =
879 saa7114_write_block(client, decoder->reg + (0x63 << 1),
880 (0x7f + 1 - 0x63) << 1);
881 err[3] =
882 saa7114_write_block(client, decoder->reg + (0x89 << 1),
883 6 << 1);
884 err[4] =
885 saa7114_write_block(client, decoder->reg + (0xb8 << 1),
886 8 << 1);
887 err[5] =
888 saa7114_write_block(client, decoder->reg + (0xe8 << 1),
889 8 << 1);
890
891
892 for (i = 0; i <= 5; i++) {
893 if (err[i] < 0) {
894 v4l_dbg(1, debug, client,
895 "init error %d at stage %d, leaving attach.\n",
896 i, err[i]);
897 kfree(decoder);
898 return -EIO;
899 }
900 }
901
902 for (i = 6; i < 8; i++) {
903 v4l_dbg(1, debug, client,
904 "reg[0x%02x] = 0x%02x (0x%02x)\n",
905 i, saa7114_read(client, i),
906 decoder->reg[REG_ADDR(i)]);
907 }
908
909 v4l_dbg(1, debug, client,
910 "performing decoder reset sequence\n");
911
912 err[6] = saa7114_write(client, 0x80, 0x06); // i-port and scaler backend clock selection, task A&B off
913 err[7] = saa7114_write(client, 0x88, 0xd8); // sw reset scaler
914 err[8] = saa7114_write(client, 0x88, 0xf8); // sw reset scaler release
915
916 for (i = 6; i <= 8; i++) {
917 if (err[i] < 0) {
918 v4l_dbg(1, debug, client,
919 "init error %d at stage %d, leaving attach.\n",
920 i, err[i]);
921 kfree(decoder);
922 return -EIO;
923 }
924 }
925
926 v4l_dbg(1, debug, client, "performing the rest of init\n");
927
928 err[9] = saa7114_write(client, 0x01, decoder->reg[REG_ADDR(0x01)]);
929 err[10] = saa7114_write_block(client, decoder->reg + (0x03 << 1), (0x1e + 1 - 0x03) << 1); // big seq
930 err[11] = saa7114_write_block(client, decoder->reg + (0x40 << 1), (0x5f + 1 - 0x40) << 1); // slicer
931 err[12] = saa7114_write_block(client, decoder->reg + (0x81 << 1), 2 << 1); // ?
932 err[13] = saa7114_write_block(client, decoder->reg + (0x83 << 1), 5 << 1); // ?
933 err[14] = saa7114_write_block(client, decoder->reg + (0x90 << 1), 4 << 1); // Task A
934 err[15] =
935 saa7114_write_block(client, decoder->reg + (0x94 << 1),
936 12 << 1);
937 err[16] =
938 saa7114_write_block(client, decoder->reg + (0xa0 << 1),
939 8 << 1);
940 err[17] =
941 saa7114_write_block(client, decoder->reg + (0xa8 << 1),
942 8 << 1);
943 err[18] =
944 saa7114_write_block(client, decoder->reg + (0xb0 << 1),
945 8 << 1);
946 err[19] = saa7114_write_block(client, decoder->reg + (0xc0 << 1), 4 << 1); // Task B
947 err[15] =
948 saa7114_write_block(client, decoder->reg + (0xc4 << 1),
949 12 << 1);
950 err[16] =
951 saa7114_write_block(client, decoder->reg + (0xd0 << 1),
952 8 << 1);
953 err[17] =
954 saa7114_write_block(client, decoder->reg + (0xd8 << 1),
955 8 << 1);
956 err[18] =
957 saa7114_write_block(client, decoder->reg + (0xe0 << 1),
958 8 << 1);
959
960 for (i = 9; i <= 18; i++) {
961 if (err[i] < 0) {
962 v4l_dbg(1, debug, client,
963 "init error %d at stage %d, leaving attach.\n",
964 i, err[i]);
965 kfree(decoder);
966 return -EIO;
967 }
968 }
969
970
971 for (i = 6; i < 8; i++) {
972 v4l_dbg(1, debug, client,
973 "reg[0x%02x] = 0x%02x (0x%02x)\n",
974 i, saa7114_read(client, i),
975 decoder->reg[REG_ADDR(i)]);
976 }
977
978
979 for (i = 0x11; i <= 0x13; i++) {
980 v4l_dbg(1, debug, client,
981 "reg[0x%02x] = 0x%02x (0x%02x)\n",
982 i, saa7114_read(client, i),
983 decoder->reg[REG_ADDR(i)]);
984 }
985
986
987 v4l_dbg(1, debug, client, "setting video input\n");
988
989 err[19] =
990 saa7114_write(client, 0x02, decoder->reg[REG_ADDR(0x02)]);
991 err[20] =
992 saa7114_write(client, 0x09, decoder->reg[REG_ADDR(0x09)]);
993 err[21] =
994 saa7114_write(client, 0x0e, decoder->reg[REG_ADDR(0x0e)]);
995
996 for (i = 19; i <= 21; i++) {
997 if (err[i] < 0) {
998 v4l_dbg(1, debug, client,
999 "init error %d at stage %d, leaving attach.\n",
1000 i, err[i]);
1001 kfree(decoder);
1002 return -EIO;
1003 }
1004 }
1005
1006 v4l_dbg(1, debug, client, "performing decoder reset sequence\n");
1007
1008 err[22] = saa7114_write(client, 0x88, 0xd8); // sw reset scaler
1009 err[23] = saa7114_write(client, 0x88, 0xf8); // sw reset scaler release
1010 err[24] = saa7114_write(client, 0x80, 0x36); // i-port and scaler backend clock selection, task A&B off
1011
1012
1013 for (i = 22; i <= 24; i++) {
1014 if (err[i] < 0) {
1015 v4l_dbg(1, debug, client,
1016 "init error %d at stage %d, leaving attach.\n",
1017 i, err[i]);
1018 kfree(decoder);
1019 return -EIO;
1020 }
1021 }
1022
1023 err[25] = saa7114_write(client, 0x06, init[REG_ADDR(0x06)]);
1024 err[26] = saa7114_write(client, 0x07, init[REG_ADDR(0x07)]);
1025 err[27] = saa7114_write(client, 0x10, init[REG_ADDR(0x10)]);
1026
1027 v4l_dbg(1, debug, client, "chip version %x, decoder status 0x%02x\n",
1028 saa7114_read(client, 0x00) >> 4,
1029 saa7114_read(client, 0x1f));
1030 v4l_dbg(1, debug, client,
1031 "power save control: 0x%02x, scaler status: 0x%02x\n",
1032 saa7114_read(client, 0x88),
1033 saa7114_read(client, 0x8f));
1034
1035
1036 for (i = 0x94; i < 0x96; i++) {
1037 v4l_dbg(1, debug, client,
1038 "reg[0x%02x] = 0x%02x (0x%02x)\n",
1039 i, saa7114_read(client, i),
1040 decoder->reg[REG_ADDR(i)]);
1041 }
1042
1043 //i = saa7114_write_block(client, init, sizeof(init));
1044 return 0;
1045}
1046
1047static int saa7114_remove(struct i2c_client *client)
1048{
1049 kfree(i2c_get_clientdata(client));
1050 return 0;
1051}
1052
1053/* ----------------------------------------------------------------------- */
1054
1055static const struct i2c_device_id saa7114_id[] = {
1056 { "saa7114_old", 0 }, /* "saa7114" maps to the saa7115 driver */
1057 { }
1058};
1059MODULE_DEVICE_TABLE(i2c, saa7114_id);
1060
1061static struct v4l2_i2c_driver_data v4l2_i2c_data = {
1062 .name = "saa7114",
1063 .driverid = I2C_DRIVERID_SAA7114,
1064 .command = saa7114_command,
1065 .probe = saa7114_probe,
1066 .remove = saa7114_remove,
1067 .id_table = saa7114_id,
1068};