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/module.h>
13 #include <linux/init.h>
14 #include <linux/delay.h>
15 #include <linux/errno.h>
17 #include <linux/kernel.h>
18 #include <linux/major.h>
19 #include <linux/slab.h>
21 #include <linux/sched.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");
36 #define VINO_ADAPTER (I2C_ALGO_SGI | I2C_HW_SGI_VINO)
39 struct i2c_client *client;
41 /* the register values are stored here as the actual
42 * I2C-registers are write-only */
43 unsigned char reg[25];
49 static struct i2c_driver i2c_driver_saa7191;
51 static const unsigned char initseq[] = {
53 0x50, /* SAA7191_REG_IDEL */
54 0x30, /* SAA7191_REG_HSYB */
55 0x00, /* SAA7191_REG_HSYS */
56 0xe8, /* SAA7191_REG_HCLB */
57 0xb6, /* SAA7191_REG_HCLS */
58 0xf4, /* SAA7191_REG_HPHI */
59 0x01, /* SAA7191_REG_LUMA - chrominance trap active (CVBS) */
60 0x00, /* SAA7191_REG_HUEC */
61 0xf8, /* SAA7191_REG_CKTQ */
62 0xf8, /* SAA7191_REG_CKTS */
63 0x90, /* SAA7191_REG_PLSE */
64 0x90, /* SAA7191_REG_SESE */
65 0x00, /* SAA7191_REG_GAIN */
66 0x0c, /* SAA7191_REG_STDC - not SECAM, slow time constant */
67 0x78, /* SAA7191_REG_IOCK - chrominance from CVBS, GPSW1 & 2 off */
68 0x99, /* SAA7191_REG_CTL3 - automatic field detection */
69 0x00, /* SAA7191_REG_CTL4 */
70 0x2c, /* SAA7191_REG_CHCV */
73 0x34, /* SAA7191_REG_HS6B */
74 0x0a, /* SAA7191_REG_HS6S */
75 0xf4, /* SAA7191_REG_HC6B */
76 0xce, /* SAA7191_REG_HC6S */
77 0xf4, /* SAA7191_REG_HP6I */
80 /* SAA7191 register handling */
82 static unsigned char saa7191_read_reg(struct i2c_client *client,
85 return ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg];
88 static int saa7191_read_status(struct i2c_client *client,
93 ret = i2c_master_recv(client, value, 1);
95 printk(KERN_ERR "SAA7191: saa7191_read_status(): read failed");
103 static int saa7191_write_reg(struct i2c_client *client, unsigned char reg,
107 ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg] = value;
108 return i2c_smbus_write_byte_data(client, reg, value);
111 /* the first byte of data must be the first subaddress number (register) */
112 static int saa7191_write_block(struct i2c_client *client,
113 unsigned char length, unsigned char *data)
118 struct saa7191 *decoder = (struct saa7191 *)i2c_get_clientdata(client);
119 for (i = 0; i < (length - 1); i++) {
120 decoder->reg[data[0] + i] = data[i + 1];
123 ret = i2c_master_send(client, data, length);
125 printk(KERN_ERR "SAA7191: saa7191_write_block(): "
133 /* Helper functions */
135 static int saa7191_set_input(struct i2c_client *client, int input)
137 unsigned char luma = saa7191_read_reg(client, SAA7191_REG_LUMA);
138 unsigned char iock = saa7191_read_reg(client, SAA7191_REG_IOCK);
142 case SAA7191_INPUT_COMPOSITE: /* Set Composite input */
143 iock &= ~(SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW1
144 | SAA7191_IOCK_GPSW2);
145 /* Chrominance trap active */
146 luma &= ~SAA7191_LUMA_BYPS;
148 case SAA7191_INPUT_SVIDEO: /* Set S-Video input */
149 iock |= SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW2;
150 /* Chrominance trap bypassed */
151 luma |= SAA7191_LUMA_BYPS;
157 err = saa7191_write_reg(client, SAA7191_REG_LUMA, luma);
160 err = saa7191_write_reg(client, SAA7191_REG_IOCK, iock);
167 static int saa7191_set_norm(struct i2c_client *client, int norm)
169 struct saa7191 *decoder = i2c_get_clientdata(client);
170 unsigned char stdc = saa7191_read_reg(client, SAA7191_REG_STDC);
171 unsigned char ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3);
172 unsigned char chcv = saa7191_read_reg(client, SAA7191_REG_CHCV);
176 case SAA7191_NORM_AUTO: {
177 unsigned char status;
179 // does status depend on current norm ?
180 if (saa7191_read_status(client, &status))
183 stdc &= ~SAA7191_STDC_SECS;
184 ctl3 &= ~SAA7191_CTL3_FSEL;
185 ctl3 |= SAA7191_CTL3_AUFD;
186 chcv = (status & SAA7191_STATUS_FIDT)
187 ? SAA7191_CHCV_NTSC : SAA7191_CHCV_PAL;
190 case SAA7191_NORM_PAL:
191 stdc &= ~SAA7191_STDC_SECS;
192 ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
193 chcv = SAA7191_CHCV_PAL;
195 case SAA7191_NORM_NTSC:
196 stdc &= ~SAA7191_STDC_SECS;
197 ctl3 &= ~SAA7191_CTL3_AUFD;
198 ctl3 |= SAA7191_CTL3_FSEL;
199 chcv = SAA7191_CHCV_NTSC;
201 case SAA7191_NORM_SECAM:
202 stdc |= SAA7191_STDC_SECS;
203 ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
204 chcv = SAA7191_CHCV_PAL;
210 err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3);
213 err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc);
216 err = saa7191_write_reg(client, SAA7191_REG_CHCV, chcv);
220 decoder->norm = norm;
225 static int saa7191_get_controls(struct i2c_client *client,
226 struct saa7191_control *ctrl)
228 unsigned char hue = saa7191_read_reg(client, SAA7191_REG_HUEC);
229 unsigned char stdc = saa7191_read_reg(client, SAA7191_REG_STDC);
238 ctrl->vtrc = (stdc & SAA7191_STDC_VTRC)
239 ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED;
244 static int saa7191_set_controls(struct i2c_client *client,
245 struct saa7191_control *ctrl)
249 if (ctrl->hue >= 0) {
250 unsigned char hue = ctrl->hue & 0xff;
256 err = saa7191_write_reg(client, SAA7191_REG_HUEC, hue);
260 if (ctrl->vtrc >= 0) {
262 saa7191_read_reg(client, SAA7191_REG_STDC);
265 stdc |= SAA7191_STDC_VTRC;
267 stdc &= ~SAA7191_STDC_VTRC;
270 err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc);
280 static int saa7191_attach(struct i2c_adapter *adap, int addr, int kind)
283 struct saa7191 *decoder;
284 struct i2c_client *client;
286 printk(KERN_INFO "Philips SAA7191 driver version %s\n",
287 SAA7191_MODULE_VERSION);
289 client = kmalloc(sizeof(*client), GFP_KERNEL);
292 decoder = kmalloc(sizeof(*decoder), GFP_KERNEL);
295 goto out_free_client;
298 memset(client, 0, sizeof(struct i2c_client));
299 memset(decoder, 0, sizeof(struct saa7191));
302 client->adapter = adap;
303 client->driver = &i2c_driver_saa7191;
305 strcpy(client->name, "saa7191 client");
306 i2c_set_clientdata(client, decoder);
308 decoder->client = client;
310 err = i2c_attach_client(client);
312 goto out_free_decoder;
314 decoder->input = SAA7191_INPUT_COMPOSITE;
315 decoder->norm = SAA7191_NORM_AUTO;
317 err = saa7191_write_block(client, sizeof(initseq),
318 (unsigned char *)initseq);
320 printk(KERN_ERR "SAA7191 initialization failed\n");
321 goto out_detach_client;
324 printk(KERN_INFO "SAA7191 initialized\n");
329 i2c_detach_client(client);
337 static int saa7191_probe(struct i2c_adapter *adap)
339 /* Always connected to VINO */
340 if (adap->id == VINO_ADAPTER)
341 return saa7191_attach(adap, SAA7191_ADDR, 0);
342 /* Feel free to add probe here :-) */
346 static int saa7191_detach(struct i2c_client *client)
348 struct saa7191 *decoder = i2c_get_clientdata(client);
350 i2c_detach_client(client);
356 static int saa7191_command(struct i2c_client *client, unsigned int cmd,
359 struct saa7191 *decoder = i2c_get_clientdata(client);
362 case DECODER_GET_CAPABILITIES: {
363 struct video_decoder_capability *cap = arg;
365 cap->flags = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC |
366 VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO;
367 cap->inputs = (client->adapter->id == VINO_ADAPTER) ? 2 : 1;
371 case DECODER_GET_STATUS: {
373 unsigned char status;
376 if (saa7191_read_status(client, &status)) {
379 if ((status & SAA7191_STATUS_HLCK) == 0)
380 res |= DECODER_STATUS_GOOD;
381 if (status & SAA7191_STATUS_CODE)
382 res |= DECODER_STATUS_COLOR;
383 switch (decoder->norm) {
384 case SAA7191_NORM_NTSC:
385 res |= DECODER_STATUS_NTSC;
387 case SAA7191_NORM_PAL:
388 res |= DECODER_STATUS_PAL;
390 case SAA7191_NORM_SECAM:
391 res |= DECODER_STATUS_SECAM;
393 case SAA7191_NORM_AUTO:
395 if (status & SAA7191_STATUS_FIDT)
396 res |= DECODER_STATUS_NTSC;
398 res |= DECODER_STATUS_PAL;
404 case DECODER_SET_NORM: {
408 case VIDEO_MODE_AUTO:
409 return saa7191_set_norm(client, SAA7191_NORM_AUTO);
411 return saa7191_set_norm(client, SAA7191_NORM_PAL);
412 case VIDEO_MODE_NTSC:
413 return saa7191_set_norm(client, SAA7191_NORM_NTSC);
414 case VIDEO_MODE_SECAM:
415 return saa7191_set_norm(client, SAA7191_NORM_SECAM);
421 case DECODER_SET_INPUT: {
424 switch (client->adapter->id) {
426 return saa7191_set_input(client, *iarg);
433 case DECODER_SET_OUTPUT: {
436 /* not much choice of outputs */
441 case DECODER_ENABLE_OUTPUT: {
445 case DECODER_SET_PICTURE: {
446 struct video_picture *pic = arg;
450 val = (pic->hue >> 8) - 0x80;
451 err = saa7191_write_reg(client, SAA7191_REG_HUEC, val);
456 case DECODER_SAA7191_GET_STATUS: {
457 struct saa7191_status *status = arg;
458 unsigned char status_reg;
460 if (saa7191_read_status(client, &status_reg))
462 status->signal = ((status_reg & SAA7191_STATUS_HLCK) == 0)
463 ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED;
464 status->ntsc = (status_reg & SAA7191_STATUS_FIDT)
465 ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED;
466 status->color = (status_reg & SAA7191_STATUS_CODE)
467 ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED;
469 status->input = decoder->input;
470 status->norm = decoder->norm;
472 case DECODER_SAA7191_SET_NORM: {
474 return saa7191_set_norm(client, *norm);
476 case DECODER_SAA7191_GET_CONTROLS: {
477 struct saa7191_control *ctrl = arg;
478 return saa7191_get_controls(client, ctrl);
480 case DECODER_SAA7191_SET_CONTROLS: {
481 struct saa7191_control *ctrl = arg;
482 return saa7191_set_controls(client, ctrl);
491 static struct i2c_driver i2c_driver_saa7191 = {
492 .owner = THIS_MODULE,
494 .id = I2C_DRIVERID_SAA7191,
495 .flags = I2C_DF_NOTIFY,
496 .attach_adapter = saa7191_probe,
497 .detach_client = saa7191_detach,
498 .command = saa7191_command
501 static int saa7191_init(void)
503 return i2c_add_driver(&i2c_driver_saa7191);
506 static void saa7191_exit(void)
508 i2c_del_driver(&i2c_driver_saa7191);
511 module_init(saa7191_init);
512 module_exit(saa7191_exit);