2 * saa7191.c - Philips SAA7191 video decoder driver
4 * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
5 * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/delay.h>
13 #include <linux/errno.h>
15 #include <linux/init.h>
16 #include <linux/kernel.h>
17 #include <linux/major.h>
18 #include <linux/module.h>
20 #include <linux/sched.h>
21 #include <linux/slab.h>
23 #include <linux/videodev.h>
24 #include <linux/video_decoder.h>
25 #include <linux/i2c.h>
29 #define SAA7191_MODULE_VERSION "0.0.3"
31 MODULE_DESCRIPTION("Philips SAA7191 video decoder driver");
32 MODULE_VERSION(SAA7191_MODULE_VERSION
);
33 MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
34 MODULE_LICENSE("GPL");
37 struct i2c_client
*client
;
39 /* the register values are stored here as the actual
40 * I2C-registers are write-only */
41 unsigned char reg
[25];
47 static struct i2c_driver i2c_driver_saa7191
;
49 static const unsigned char initseq
[] = {
51 0x50, /* SAA7191_REG_IDEL */
52 0x30, /* SAA7191_REG_HSYB */
53 0x00, /* SAA7191_REG_HSYS */
54 0xe8, /* SAA7191_REG_HCLB */
55 0xb6, /* SAA7191_REG_HCLS */
56 0xf4, /* SAA7191_REG_HPHI */
57 0x01, /* SAA7191_REG_LUMA - chrominance trap active (CVBS) */
58 0x00, /* SAA7191_REG_HUEC */
59 0xf8, /* SAA7191_REG_CKTQ */
60 0xf8, /* SAA7191_REG_CKTS */
61 0x90, /* SAA7191_REG_PLSE */
62 0x90, /* SAA7191_REG_SESE */
63 0x00, /* SAA7191_REG_GAIN */
64 0x0c, /* SAA7191_REG_STDC - not SECAM, slow time constant */
65 0x78, /* SAA7191_REG_IOCK - chrominance from CVBS, GPSW1 & 2 off */
66 0x99, /* SAA7191_REG_CTL3 - automatic field detection */
67 0x00, /* SAA7191_REG_CTL4 */
68 0x2c, /* SAA7191_REG_CHCV */
71 0x34, /* SAA7191_REG_HS6B */
72 0x0a, /* SAA7191_REG_HS6S */
73 0xf4, /* SAA7191_REG_HC6B */
74 0xce, /* SAA7191_REG_HC6S */
75 0xf4, /* SAA7191_REG_HP6I */
78 /* SAA7191 register handling */
80 static unsigned char saa7191_read_reg(struct i2c_client
*client
,
83 return ((struct saa7191
*)i2c_get_clientdata(client
))->reg
[reg
];
86 static int saa7191_read_status(struct i2c_client
*client
,
91 ret
= i2c_master_recv(client
, value
, 1);
93 printk(KERN_ERR
"SAA7191: saa7191_read_status(): read failed");
101 static int saa7191_write_reg(struct i2c_client
*client
, unsigned char reg
,
105 ((struct saa7191
*)i2c_get_clientdata(client
))->reg
[reg
] = value
;
106 return i2c_smbus_write_byte_data(client
, reg
, value
);
109 /* the first byte of data must be the first subaddress number (register) */
110 static int saa7191_write_block(struct i2c_client
*client
,
111 unsigned char length
, unsigned char *data
)
116 struct saa7191
*decoder
= (struct saa7191
*)i2c_get_clientdata(client
);
117 for (i
= 0; i
< (length
- 1); i
++) {
118 decoder
->reg
[data
[0] + i
] = data
[i
+ 1];
121 ret
= i2c_master_send(client
, data
, length
);
123 printk(KERN_ERR
"SAA7191: saa7191_write_block(): "
131 /* Helper functions */
133 static int saa7191_set_input(struct i2c_client
*client
, int input
)
135 unsigned char luma
= saa7191_read_reg(client
, SAA7191_REG_LUMA
);
136 unsigned char iock
= saa7191_read_reg(client
, SAA7191_REG_IOCK
);
140 case SAA7191_INPUT_COMPOSITE
: /* Set Composite input */
141 iock
&= ~(SAA7191_IOCK_CHRS
| SAA7191_IOCK_GPSW1
142 | SAA7191_IOCK_GPSW2
);
143 /* Chrominance trap active */
144 luma
&= ~SAA7191_LUMA_BYPS
;
146 case SAA7191_INPUT_SVIDEO
: /* Set S-Video input */
147 iock
|= SAA7191_IOCK_CHRS
| SAA7191_IOCK_GPSW2
;
148 /* Chrominance trap bypassed */
149 luma
|= SAA7191_LUMA_BYPS
;
155 err
= saa7191_write_reg(client
, SAA7191_REG_LUMA
, luma
);
158 err
= saa7191_write_reg(client
, SAA7191_REG_IOCK
, iock
);
165 static int saa7191_set_norm(struct i2c_client
*client
, int norm
)
167 struct saa7191
*decoder
= i2c_get_clientdata(client
);
168 unsigned char stdc
= saa7191_read_reg(client
, SAA7191_REG_STDC
);
169 unsigned char ctl3
= saa7191_read_reg(client
, SAA7191_REG_CTL3
);
170 unsigned char chcv
= saa7191_read_reg(client
, SAA7191_REG_CHCV
);
174 case SAA7191_NORM_AUTO
: {
175 unsigned char status
;
177 // does status depend on current norm ?
178 if (saa7191_read_status(client
, &status
))
181 stdc
&= ~SAA7191_STDC_SECS
;
182 ctl3
&= ~SAA7191_CTL3_FSEL
;
183 ctl3
|= SAA7191_CTL3_AUFD
;
184 chcv
= (status
& SAA7191_STATUS_FIDT
)
185 ? SAA7191_CHCV_NTSC
: SAA7191_CHCV_PAL
;
188 case SAA7191_NORM_PAL
:
189 stdc
&= ~SAA7191_STDC_SECS
;
190 ctl3
&= ~(SAA7191_CTL3_AUFD
| SAA7191_CTL3_FSEL
);
191 chcv
= SAA7191_CHCV_PAL
;
193 case SAA7191_NORM_NTSC
:
194 stdc
&= ~SAA7191_STDC_SECS
;
195 ctl3
&= ~SAA7191_CTL3_AUFD
;
196 ctl3
|= SAA7191_CTL3_FSEL
;
197 chcv
= SAA7191_CHCV_NTSC
;
199 case SAA7191_NORM_SECAM
:
200 stdc
|= SAA7191_STDC_SECS
;
201 ctl3
&= ~(SAA7191_CTL3_AUFD
| SAA7191_CTL3_FSEL
);
202 chcv
= SAA7191_CHCV_PAL
;
208 err
= saa7191_write_reg(client
, SAA7191_REG_CTL3
, ctl3
);
211 err
= saa7191_write_reg(client
, SAA7191_REG_STDC
, stdc
);
214 err
= saa7191_write_reg(client
, SAA7191_REG_CHCV
, chcv
);
218 decoder
->norm
= norm
;
223 static int saa7191_get_controls(struct i2c_client
*client
,
224 struct saa7191_control
*ctrl
)
226 unsigned char hue
= saa7191_read_reg(client
, SAA7191_REG_HUEC
);
227 unsigned char stdc
= saa7191_read_reg(client
, SAA7191_REG_STDC
);
236 ctrl
->vtrc
= (stdc
& SAA7191_STDC_VTRC
)
237 ? SAA7191_VALUE_ENABLED
: SAA7191_VALUE_DISABLED
;
242 static int saa7191_set_controls(struct i2c_client
*client
,
243 struct saa7191_control
*ctrl
)
247 if (ctrl
->hue
>= 0) {
248 unsigned char hue
= ctrl
->hue
& 0xff;
254 err
= saa7191_write_reg(client
, SAA7191_REG_HUEC
, hue
);
258 if (ctrl
->vtrc
>= 0) {
260 saa7191_read_reg(client
, SAA7191_REG_STDC
);
263 stdc
|= SAA7191_STDC_VTRC
;
265 stdc
&= ~SAA7191_STDC_VTRC
;
268 err
= saa7191_write_reg(client
, SAA7191_REG_STDC
, stdc
);
278 static int saa7191_attach(struct i2c_adapter
*adap
, int addr
, int kind
)
281 struct saa7191
*decoder
;
282 struct i2c_client
*client
;
284 printk(KERN_INFO
"Philips SAA7191 driver version %s\n",
285 SAA7191_MODULE_VERSION
);
287 client
= kmalloc(sizeof(*client
), GFP_KERNEL
);
290 decoder
= kmalloc(sizeof(*decoder
), GFP_KERNEL
);
293 goto out_free_client
;
296 memset(client
, 0, sizeof(struct i2c_client
));
297 memset(decoder
, 0, sizeof(struct saa7191
));
300 client
->adapter
= adap
;
301 client
->driver
= &i2c_driver_saa7191
;
303 strcpy(client
->name
, "saa7191 client");
304 i2c_set_clientdata(client
, decoder
);
306 decoder
->client
= client
;
308 err
= i2c_attach_client(client
);
310 goto out_free_decoder
;
312 decoder
->input
= SAA7191_INPUT_COMPOSITE
;
313 decoder
->norm
= SAA7191_NORM_AUTO
;
315 err
= saa7191_write_block(client
, sizeof(initseq
),
316 (unsigned char *)initseq
);
318 printk(KERN_ERR
"SAA7191 initialization failed\n");
319 goto out_detach_client
;
322 printk(KERN_INFO
"SAA7191 initialized\n");
327 i2c_detach_client(client
);
335 static int saa7191_probe(struct i2c_adapter
*adap
)
337 /* Always connected to VINO */
338 if (adap
->id
== I2C_HW_SGI_VINO
)
339 return saa7191_attach(adap
, SAA7191_ADDR
, 0);
340 /* Feel free to add probe here :-) */
344 static int saa7191_detach(struct i2c_client
*client
)
346 struct saa7191
*decoder
= i2c_get_clientdata(client
);
348 i2c_detach_client(client
);
354 static int saa7191_command(struct i2c_client
*client
, unsigned int cmd
,
357 struct saa7191
*decoder
= i2c_get_clientdata(client
);
360 case DECODER_GET_CAPABILITIES
: {
361 struct video_decoder_capability
*cap
= arg
;
363 cap
->flags
= VIDEO_DECODER_PAL
| VIDEO_DECODER_NTSC
|
364 VIDEO_DECODER_SECAM
| VIDEO_DECODER_AUTO
;
365 cap
->inputs
= (client
->adapter
->id
== I2C_HW_SGI_VINO
) ? 2 : 1;
369 case DECODER_GET_STATUS
: {
371 unsigned char status
;
374 if (saa7191_read_status(client
, &status
)) {
377 if ((status
& SAA7191_STATUS_HLCK
) == 0)
378 res
|= DECODER_STATUS_GOOD
;
379 if (status
& SAA7191_STATUS_CODE
)
380 res
|= DECODER_STATUS_COLOR
;
381 switch (decoder
->norm
) {
382 case SAA7191_NORM_NTSC
:
383 res
|= DECODER_STATUS_NTSC
;
385 case SAA7191_NORM_PAL
:
386 res
|= DECODER_STATUS_PAL
;
388 case SAA7191_NORM_SECAM
:
389 res
|= DECODER_STATUS_SECAM
;
391 case SAA7191_NORM_AUTO
:
393 if (status
& SAA7191_STATUS_FIDT
)
394 res
|= DECODER_STATUS_NTSC
;
396 res
|= DECODER_STATUS_PAL
;
402 case DECODER_SET_NORM
: {
406 case VIDEO_MODE_AUTO
:
407 return saa7191_set_norm(client
, SAA7191_NORM_AUTO
);
409 return saa7191_set_norm(client
, SAA7191_NORM_PAL
);
410 case VIDEO_MODE_NTSC
:
411 return saa7191_set_norm(client
, SAA7191_NORM_NTSC
);
412 case VIDEO_MODE_SECAM
:
413 return saa7191_set_norm(client
, SAA7191_NORM_SECAM
);
419 case DECODER_SET_INPUT
: {
422 switch (client
->adapter
->id
) {
423 case I2C_HW_SGI_VINO
:
424 return saa7191_set_input(client
, *iarg
);
431 case DECODER_SET_OUTPUT
: {
434 /* not much choice of outputs */
439 case DECODER_ENABLE_OUTPUT
: {
443 case DECODER_SET_PICTURE
: {
444 struct video_picture
*pic
= arg
;
448 val
= (pic
->hue
>> 8) - 0x80;
449 err
= saa7191_write_reg(client
, SAA7191_REG_HUEC
, val
);
454 case DECODER_SAA7191_GET_STATUS
: {
455 struct saa7191_status
*status
= arg
;
456 unsigned char status_reg
;
458 if (saa7191_read_status(client
, &status_reg
))
460 status
->signal
= ((status_reg
& SAA7191_STATUS_HLCK
) == 0)
461 ? SAA7191_VALUE_ENABLED
: SAA7191_VALUE_DISABLED
;
462 status
->ntsc
= (status_reg
& SAA7191_STATUS_FIDT
)
463 ? SAA7191_VALUE_ENABLED
: SAA7191_VALUE_DISABLED
;
464 status
->color
= (status_reg
& SAA7191_STATUS_CODE
)
465 ? SAA7191_VALUE_ENABLED
: SAA7191_VALUE_DISABLED
;
467 status
->input
= decoder
->input
;
468 status
->norm
= decoder
->norm
;
470 case DECODER_SAA7191_SET_NORM
: {
472 return saa7191_set_norm(client
, *norm
);
474 case DECODER_SAA7191_GET_CONTROLS
: {
475 struct saa7191_control
*ctrl
= arg
;
476 return saa7191_get_controls(client
, ctrl
);
478 case DECODER_SAA7191_SET_CONTROLS
: {
479 struct saa7191_control
*ctrl
= arg
;
480 return saa7191_set_controls(client
, ctrl
);
489 static struct i2c_driver i2c_driver_saa7191
= {
490 .owner
= THIS_MODULE
,
492 .id
= I2C_DRIVERID_SAA7191
,
493 .flags
= I2C_DF_NOTIFY
,
494 .attach_adapter
= saa7191_probe
,
495 .detach_client
= saa7191_detach
,
496 .command
= saa7191_command
499 static int saa7191_init(void)
501 return i2c_add_driver(&i2c_driver_saa7191
);
504 static void saa7191_exit(void)
506 i2c_del_driver(&i2c_driver_saa7191
);
509 module_init(saa7191_init
);
510 module_exit(saa7191_exit
);