2 saa7111 - Philips SAA7111A video decoder driver version 0.0.3
4 Copyright (C) 1998 Dave Perks <dperks@ibm.net>
6 Slight changes for video timing and attachment output by
7 Wolfgang Scherr <scherr@net4you.net>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include <linux/module.h>
25 #include <linux/init.h>
26 #include <linux/delay.h>
27 #include <linux/errno.h>
29 #include <linux/kernel.h>
30 #include <linux/major.h>
31 #include <linux/slab.h>
33 #include <linux/sched.h>
35 #include <linux/videodev.h>
36 #include <linux/version.h>
37 #include <linux/i2c.h>
39 #include <linux/video_decoder.h>
41 #define DEBUG(x) /* Debug driver */
43 /* ----------------------------------------------------------------------- */
46 struct i2c_client *client;
48 struct semaphore lock;
49 unsigned char reg[32];
60 static unsigned short normal_i2c[] = { 0x24, 0x25, I2C_CLIENT_END };
61 static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
65 static struct i2c_client client_template;
67 /* ----------------------------------------------------------------------- */
69 static int saa7111_attach(struct i2c_adapter *adap, int addr, int kind)
72 struct saa7111 *decoder;
73 struct i2c_client *client;
75 /* who wrote this? init[] is used for i2c_master_send() which expects an array that
76 will be used for the 'buf' part of an i2c message unchanged. so, the first byte
77 needs to be the subaddress to start with, then follow the data bytes... */
78 static const unsigned char init[] = {
79 0x00, /* start address */
81 0x00, /* 00 - ID byte */
82 0x00, /* 01 - reserved */
85 0xd0, /* 02 - FUSE=3, GUDL=2, MODE=0 */
86 0x23, /* 03 - HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */
87 0x00, /* 04 - GAI1=256 */
88 0x00, /* 05 - GAI2=256 */
91 0xf3, /* 06 - HSB at 13(50Hz) / 17(60Hz) pixels after end of last line */
92 0x13, /* 07 - HSS at 113(50Hz) / 117(60Hz) pixels after end of last line */
93 0xc8, /* 08 - AUFD=1, FSEL=1, EXFIL=0, VTRC=1, HPLL=0, VNOI=0 */
94 0x01, /* 09 - BYPS=0, PREF=0, BPSS=0, VBLB=0, UPTCV=0, APER=1 */
95 0x80, /* 0a - BRIG=128 */
96 0x47, /* 0b - CONT=1.109 */
97 0x40, /* 0c - SATN=1.0 */
98 0x00, /* 0d - HUE=0 */
99 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */
100 0x00, /* 0f - reserved */
101 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
102 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1, OEYC=1, OEHV=1, VIPB=0, COLO=0 */
103 0x00, /* 12 - output control 2 */
104 0x00, /* 13 - output control 3 */
105 0x00, /* 14 - reserved */
110 client = kmalloc(sizeof(*client), GFP_KERNEL);
113 client_template.adapter = adap;
114 client_template.addr = addr;
115 memcpy(client, &client_template, sizeof(*client));
117 decoder = kmalloc(sizeof(*decoder), GFP_KERNEL);
124 memset(decoder, 0, sizeof(*decoder));
125 strlcpy(client->dev.name, "saa7111", DEVICE_NAME_SIZE);
126 decoder->client = client;
127 i2c_set_clientdata(client, decoder);
128 decoder->addr = addr;
129 decoder->norm = VIDEO_MODE_NTSC;
132 decoder->bright = 32768;
133 decoder->contrast = 32768;
134 decoder->hue = 32768;
135 decoder->sat = 32768;
137 i = i2c_master_send(client, init, sizeof(init));
139 printk(KERN_ERR "%s_attach: init status %d\n",
140 client->dev.name, i);
142 printk(KERN_INFO "%s_attach: chip version %x @ 0x%08x\n",
143 client->dev.name, i2c_smbus_read_byte_data(client, 0x00) >> 4,addr);
146 init_MUTEX(&decoder->lock);
147 i2c_attach_client(client);
151 static int saa7111_probe(struct i2c_adapter *adap)
153 /* probing unknown devices on any Matrox i2c-bus takes ages due to the
154 slow bit banging algorithm used. because of the fact a saa7111(a)
155 is *never* present on a Matrox gfx card, we can skip such adapters
157 if( 0 != (adap->id & I2C_HW_B_G400)) {
161 printk("saa7111: probing %s i2c adapter [id=0x%x]\n",
162 adap->dev.name,adap->id);
163 return i2c_probe(adap, &addr_data, saa7111_attach);
166 static int saa7111_detach(struct i2c_client *client)
168 struct saa7111 *decoder = i2c_get_clientdata(client);
169 i2c_detach_client(client);
176 static int saa7111_command(struct i2c_client *client, unsigned int cmd,
179 struct saa7111 *decoder = i2c_get_clientdata(client);
183 #if defined(DECODER_DUMP)
188 for (i = 0; i < 32; i += 16) {
191 printk("KERN_DEBUG %s: %03x", client->dev.name,
193 for (j = 0; j < 16; ++j) {
195 i2c_smbus_read_byte_data(client,
202 #endif /* defined(DECODER_DUMP) */
204 case DECODER_GET_CAPABILITIES:
206 struct video_decoder_capability *cap = arg;
211 | VIDEO_DECODER_AUTO | VIDEO_DECODER_CCIR;
217 case DECODER_GET_STATUS:
223 status = i2c_smbus_read_byte_data(client, 0x1f);
225 if ((status & (1 << 6)) == 0) {
226 res |= DECODER_STATUS_GOOD;
228 switch (decoder->norm) {
229 case VIDEO_MODE_NTSC:
230 res |= DECODER_STATUS_NTSC;
233 res |= DECODER_STATUS_PAL;
236 case VIDEO_MODE_AUTO:
237 if ((status & (1 << 5)) != 0) {
238 res |= DECODER_STATUS_NTSC;
240 res |= DECODER_STATUS_PAL;
244 if ((status & (1 << 0)) != 0) {
245 res |= DECODER_STATUS_COLOR;
251 case DECODER_SET_NORM:
257 case VIDEO_MODE_NTSC:
258 i2c_smbus_write_byte_data(client, 0x08,
260 reg[0x08] & 0x3f) | 0x40);
264 i2c_smbus_write_byte_data(client, 0x08,
266 reg[0x08] & 0x3f) | 0x00);
269 case VIDEO_MODE_AUTO:
270 i2c_smbus_write_byte_data(client, 0x08,
272 reg[0x08] & 0x3f) | 0x80);
279 decoder->norm = *iarg;
283 case DECODER_SET_INPUT:
287 if (*iarg < 0 || *iarg > 7) {
291 if (decoder->input != *iarg) {
292 decoder->input = *iarg;
294 i2c_smbus_write_byte_data(client, 0x02,
298 /* bypass chrominance trap for modes 4..7 */
299 i2c_smbus_write_byte_data(client, 0x09,
308 case DECODER_SET_OUTPUT:
312 /* not much choice of outputs */
319 case DECODER_ENABLE_OUTPUT:
322 int enable = (*iarg != 0);
324 if (decoder->enable != enable) {
325 decoder->enable = enable;
327 // RJ: If output should be disabled (for playing videos), we also need a open PLL.
328 // The input is set to 0 (where no input source is connected), although this
331 // If output should be enabled, we have to reverse the above.
333 if (decoder->enable) {
334 i2c_smbus_write_byte_data(client, 0x02,
338 i2c_smbus_write_byte_data(client, 0x08,
341 i2c_smbus_write_byte_data(client, 0x11,
346 i2c_smbus_write_byte_data(client, 0x02,
349 i2c_smbus_write_byte_data(client, 0x08,
353 i2c_smbus_write_byte_data(client, 0x11,
361 case DECODER_SET_PICTURE:
363 struct video_picture *pic = arg;
365 if (decoder->bright != pic->brightness) {
366 /* We want 0 to 255 we get 0-65535 */
367 decoder->bright = pic->brightness;
368 i2c_smbus_write_byte_data(client, 0x0a,
369 decoder->bright >> 8);
371 if (decoder->contrast != pic->contrast) {
372 /* We want 0 to 127 we get 0-65535 */
373 decoder->contrast = pic->contrast;
374 i2c_smbus_write_byte_data(client, 0x0b,
375 decoder->contrast >> 9);
377 if (decoder->sat != pic->colour) {
378 /* We want 0 to 127 we get 0-65535 */
379 decoder->sat = pic->colour;
380 i2c_smbus_write_byte_data(client, 0x0c,
383 if (decoder->hue != pic->hue) {
384 /* We want -128 to 127 we get 0-65535 */
385 decoder->hue = pic->hue;
386 i2c_smbus_write_byte_data(client, 0x0d,
387 (decoder->hue - 32768) >> 8);
399 /* ----------------------------------------------------------------------- */
401 static struct i2c_driver i2c_driver_saa7111 = {
402 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,54)
403 .owner = THIS_MODULE,
405 .name = "saa7111", /* name */
406 .id = I2C_DRIVERID_SAA7111A, /* ID */
407 .flags = I2C_DF_NOTIFY,
408 .attach_adapter = saa7111_probe,
409 .detach_client = saa7111_detach,
410 .command = saa7111_command
413 static struct i2c_client client_template = {
415 .driver = &i2c_driver_saa7111,
417 .name = "saa7111_client",
421 static int saa7111_init(void)
423 return i2c_add_driver(&i2c_driver_saa7111);
426 static void saa7111_exit(void)
428 i2c_del_driver(&i2c_driver_saa7111);
431 module_init(saa7111_init);
432 module_exit(saa7111_exit);
433 MODULE_LICENSE("GPL");