Portability cleanup as required by Linus.
[linux-2.6/linux-mips.git] / drivers / char / saa7110.c
blob6146b84b9af56998141ab52b81e9d70800697334
1 /*
2 saa7110 - Philips SAA7110(A) video decoder driver
4 Copyright (C) 1998 Pauline Middelink <middelin@polyware.nl>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <linux/module.h>
22 #include <linux/types.h>
23 #include <linux/delay.h>
24 #include <linux/slab.h>
25 #include <asm/io.h>
26 #include <asm/uaccess.h>
28 #include <linux/i2c-old.h>
29 #include <linux/videodev.h>
30 #include "linux/video_decoder.h"
32 #define DEBUG(x...) /* remove when no long debugging */
34 #define SAA7110_MAX_INPUT 9 /* 6 CVBS, 3 SVHS */
35 #define SAA7110_MAX_OUTPUT 0 /* its a decoder only */
37 #define I2C_SAA7110 0x9C /* or 0x9E */
39 #define I2C_DELAY 10 /* 10 us or 100khz */
41 struct saa7110 {
42 struct i2c_bus *bus;
43 int addr;
44 unsigned char reg[36];
46 int norm;
47 int input;
48 int enable;
49 int bright;
50 int contrast;
51 int hue;
52 int sat;
55 /* ----------------------------------------------------------------------- */
56 /* I2C support functions */
57 /* ----------------------------------------------------------------------- */
58 static
59 int saa7110_write(struct saa7110 *decoder, unsigned char subaddr, unsigned char data)
61 int ack;
63 LOCK_I2C_BUS(decoder->bus);
64 i2c_start(decoder->bus);
65 i2c_sendbyte(decoder->bus, decoder->addr, I2C_DELAY);
66 i2c_sendbyte(decoder->bus, subaddr, I2C_DELAY);
67 ack = i2c_sendbyte(decoder->bus, data, I2C_DELAY);
68 i2c_stop(decoder->bus);
69 decoder->reg[subaddr] = data;
70 UNLOCK_I2C_BUS(decoder->bus);
71 return ack;
74 static
75 int saa7110_write_block(struct saa7110* decoder, unsigned const char *data, unsigned int len)
77 unsigned subaddr = *data;
79 LOCK_I2C_BUS(decoder->bus);
80 i2c_start(decoder->bus);
81 i2c_sendbyte(decoder->bus,decoder->addr,I2C_DELAY);
82 while (len-- > 0) {
83 if (i2c_sendbyte(decoder->bus,*data,0)) {
84 i2c_stop(decoder->bus);
85 return -EAGAIN;
87 decoder->reg[subaddr++] = *data++;
89 i2c_stop(decoder->bus);
90 UNLOCK_I2C_BUS(decoder->bus);
92 return 0;
95 static
96 int saa7110_read(struct saa7110* decoder)
98 int data;
100 LOCK_I2C_BUS(decoder->bus);
101 i2c_start(decoder->bus);
102 i2c_sendbyte(decoder->bus, decoder->addr, I2C_DELAY);
103 i2c_start(decoder->bus);
104 i2c_sendbyte(decoder->bus, decoder->addr | 1, I2C_DELAY);
105 data = i2c_readbyte(decoder->bus, 1);
106 i2c_stop(decoder->bus);
107 UNLOCK_I2C_BUS(decoder->bus);
108 return data;
111 /* ----------------------------------------------------------------------- */
112 /* SAA7110 functions */
113 /* ----------------------------------------------------------------------- */
114 static
115 int saa7110_selmux(struct i2c_device *device, int chan)
117 static const unsigned char modes[9][8] = {
118 /* mode 0 */ { 0x00, 0xD9, 0x17, 0x40, 0x03, 0x44, 0x75, 0x16 },
119 /* mode 1 */ { 0x00, 0xD8, 0x17, 0x40, 0x03, 0x44, 0x75, 0x16 },
120 /* mode 2 */ { 0x00, 0xBA, 0x07, 0x91, 0x03, 0x60, 0xB5, 0x05 },
121 /* mode 3 */ { 0x00, 0xB8, 0x07, 0x91, 0x03, 0x60, 0xB5, 0x05 },
122 /* mode 4 */ { 0x00, 0x7C, 0x07, 0xD2, 0x83, 0x60, 0xB5, 0x03 },
123 /* mode 5 */ { 0x00, 0x78, 0x07, 0xD2, 0x83, 0x60, 0xB5, 0x03 },
124 /* mode 6 */ { 0x80, 0x59, 0x17, 0x42, 0xA3, 0x44, 0x75, 0x12 },
125 /* mode 7 */ { 0x80, 0x9A, 0x17, 0xB1, 0x13, 0x60, 0xB5, 0x14 },
126 /* mode 8 */ { 0x80, 0x3C, 0x27, 0xC1, 0x23, 0x44, 0x75, 0x21 } };
127 struct saa7110* decoder = device->data;
128 const unsigned char* ptr = modes[chan];
130 saa7110_write(decoder,0x06,ptr[0]); /* Luminance control */
131 saa7110_write(decoder,0x20,ptr[1]); /* Analog Control #1 */
132 saa7110_write(decoder,0x21,ptr[2]); /* Analog Control #2 */
133 saa7110_write(decoder,0x22,ptr[3]); /* Mixer Control #1 */
134 saa7110_write(decoder,0x2C,ptr[4]); /* Mixer Control #2 */
135 saa7110_write(decoder,0x30,ptr[5]); /* ADCs gain control */
136 saa7110_write(decoder,0x31,ptr[6]); /* Mixer Control #3 */
137 saa7110_write(decoder,0x21,ptr[7]); /* Analog Control #2 */
139 return 0;
142 static
143 int determine_norm(struct i2c_device* dev)
145 struct saa7110* decoder = dev->data;
146 int status;
148 /* mode changed, start automatic detection */
149 status = saa7110_read(decoder);
150 if ((status & 3) == 0) {
151 saa7110_write(decoder,0x06,0x80);
152 if (status & 0x20) {
153 DEBUG(printk(KERN_INFO "%s: norm=bw60\n",dev->name));
154 saa7110_write(decoder,0x2E,0x81);
155 return VIDEO_MODE_NTSC;
157 DEBUG(printk(KERN_INFO "%s: norm=bw50\n",dev->name));
158 saa7110_write(decoder,0x2E,0x9A);
159 return VIDEO_MODE_PAL;
162 saa7110_write(decoder,0x06,0x00);
163 if (status & 0x20) { /* 60Hz */
164 DEBUG(printk(KERN_INFO "%s: norm=ntsc\n",dev->name));
165 saa7110_write(decoder,0x0D,0x06);
166 saa7110_write(decoder,0x11,0x2C);
167 saa7110_write(decoder,0x2E,0x81);
168 return VIDEO_MODE_NTSC;
171 /* 50Hz -> PAL/SECAM */
172 saa7110_write(decoder,0x0D,0x06);
173 saa7110_write(decoder,0x11,0x59);
174 saa7110_write(decoder,0x2E,0x9A);
176 mdelay(150); /* pause 150 ms */
178 status = saa7110_read(decoder);
179 if ((status & 0x03) == 0x01) {
180 DEBUG(printk(KERN_INFO "%s: norm=secam\n",dev->name));
181 saa7110_write(decoder,0x0D,0x07);
182 return VIDEO_MODE_SECAM;
184 DEBUG(printk(KERN_INFO "%s: norm=pal\n",dev->name));
185 return VIDEO_MODE_PAL;
188 static
189 int saa7110_attach(struct i2c_device *device)
191 static const unsigned char initseq[] = {
192 0, 0x4C, 0x3C, 0x0D, 0xEF, 0xBD, 0xF0, 0x00, 0x00,
193 0xF8, 0xF8, 0x60, 0x60, 0x00, 0x06, 0x18, 0x90,
194 0x00, 0x2C, 0x40, 0x46, 0x42, 0x1A, 0xFF, 0xDA,
195 0xF0, 0x8B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196 0xD9, 0x17, 0x40, 0x41, 0x80, 0x41, 0x80, 0x4F,
197 0xFE, 0x01, 0xCF, 0x0F, 0x03, 0x01, 0x81, 0x03,
198 0x40, 0x75, 0x01, 0x8C, 0x03};
199 struct saa7110* decoder;
200 int rv;
202 device->data = decoder = kmalloc(sizeof(struct saa7110), GFP_KERNEL);
203 if (device->data == 0)
204 return -ENOMEM;
206 MOD_INC_USE_COUNT;
208 /* clear our private data */
209 memset(decoder, 0, sizeof(struct saa7110));
210 strcpy(device->name, "saa7110");
211 decoder->bus = device->bus;
212 decoder->addr = device->addr;
213 decoder->norm = VIDEO_MODE_PAL;
214 decoder->input = 0;
215 decoder->enable = 1;
216 decoder->bright = 32768;
217 decoder->contrast = 32768;
218 decoder->hue = 32768;
219 decoder->sat = 32768;
221 rv = saa7110_write_block(decoder, initseq, sizeof(initseq));
222 if (rv < 0)
223 printk(KERN_ERR "%s_attach: init status %d\n", device->name, rv);
224 else {
225 saa7110_write(decoder,0x21,0x16);
226 saa7110_write(decoder,0x0D,0x04);
227 DEBUG(printk(KERN_INFO "%s_attach: chip version %x\n", device->name, saa7110_read(decoder)));
228 saa7110_write(decoder,0x0D,0x06);
231 /* setup and implicit mode 0 select has been performed */
232 return 0;
235 static
236 int saa7110_detach(struct i2c_device *device)
238 struct saa7110* decoder = device->data;
240 DEBUG(printk(KERN_INFO "%s_detach\n",device->name));
242 /* stop further output */
243 saa7110_write(decoder,0x0E,0x00);
245 kfree(device->data);
247 MOD_DEC_USE_COUNT;
248 return 0;
251 static
252 int saa7110_command(struct i2c_device *device, unsigned int cmd, void *arg)
254 struct saa7110* decoder = device->data;
255 int v;
257 switch (cmd) {
258 case DECODER_GET_CAPABILITIES:
260 struct video_decoder_capability *dc = arg;
261 dc->flags = VIDEO_DECODER_PAL
262 | VIDEO_DECODER_NTSC
263 | VIDEO_DECODER_SECAM
264 | VIDEO_DECODER_AUTO
265 | VIDEO_DECODER_CCIR;
266 dc->inputs = SAA7110_MAX_INPUT;
267 dc->outputs = SAA7110_MAX_OUTPUT;
269 break;
271 case DECODER_GET_STATUS:
273 struct saa7110* decoder = device->data;
274 int status;
275 int res = 0;
277 status = i2c_read(device->bus,device->addr|1);
278 if (status & 0x40)
279 res |= DECODER_STATUS_GOOD;
280 if (status & 0x03)
281 res |= DECODER_STATUS_COLOR;
283 switch (decoder->norm) {
284 case VIDEO_MODE_NTSC:
285 res |= DECODER_STATUS_NTSC;
286 break;
287 case VIDEO_MODE_PAL:
288 res |= DECODER_STATUS_PAL;
289 break;
290 case VIDEO_MODE_SECAM:
291 res |= DECODER_STATUS_SECAM;
292 break;
294 *(int*)arg = res;
296 break;
298 case DECODER_SET_NORM:
299 v = *(int*)arg;
300 if (decoder->norm != v) {
301 decoder->norm = v;
302 saa7110_write(decoder, 0x06, 0x00);
303 switch (v) {
304 case VIDEO_MODE_NTSC:
305 saa7110_write(decoder, 0x0D, 0x06);
306 saa7110_write(decoder, 0x11, 0x2C);
307 saa7110_write(decoder, 0x30, 0x81);
308 saa7110_write(decoder, 0x2A, 0xDF);
309 break;
310 case VIDEO_MODE_PAL:
311 saa7110_write(decoder, 0x0D, 0x06);
312 saa7110_write(decoder, 0x11, 0x59);
313 saa7110_write(decoder, 0x2E, 0x9A);
314 break;
315 case VIDEO_MODE_SECAM:
316 saa7110_write(decoder, 0x0D, 0x07);
317 saa7110_write(decoder, 0x11, 0x59);
318 saa7110_write(decoder, 0x2E, 0x9A);
319 break;
320 case VIDEO_MODE_AUTO:
321 *(int*)arg = determine_norm(device);
322 break;
323 default:
324 return -EPERM;
327 break;
329 case DECODER_SET_INPUT:
330 v = *(int*)arg;
331 if (v<0 || v>SAA7110_MAX_INPUT)
332 return -EINVAL;
333 if (decoder->input != v) {
334 decoder->input = v;
335 saa7110_selmux(device, v);
337 break;
339 case DECODER_SET_OUTPUT:
340 v = *(int*)arg;
341 /* not much choice of outputs */
342 if (v != 0)
343 return -EINVAL;
344 break;
346 case DECODER_ENABLE_OUTPUT:
347 v = *(int*)arg;
348 if (decoder->enable != v) {
349 decoder->enable = v;
350 saa7110_write(decoder,0x0E, v ? 0x18 : 0x00);
352 break;
354 case DECODER_SET_PICTURE:
356 struct video_picture *pic = arg;
358 if (decoder->bright != pic->brightness) {
359 /* We want 0 to 255 we get 0-65535 */
360 decoder->bright = pic->brightness;
361 saa7110_write(decoder, 0x19, decoder->bright >> 8);
363 if (decoder->contrast != pic->contrast) {
364 /* We want 0 to 127 we get 0-65535 */
365 decoder->contrast = pic->contrast;
366 saa7110_write(decoder, 0x13, decoder->contrast >> 9);
368 if (decoder->sat != pic->colour) {
369 /* We want 0 to 127 we get 0-65535 */
370 decoder->sat = pic->colour;
371 saa7110_write(decoder, 0x12, decoder->sat >> 9);
373 if (decoder->hue != pic->hue) {
374 /* We want -128 to 127 we get 0-65535 */
375 decoder->hue = pic->hue;
376 saa7110_write(decoder, 0x07, (decoder->hue>>8)-128);
379 break;
381 case DECODER_DUMP:
382 for (v=0; v<34; v+=16) {
383 int j;
384 DEBUG(printk(KERN_INFO "%s: %03x\n",device->name,v));
385 for (j=0; j<16; j++) {
386 DEBUG(printk(KERN_INFO " %02x",decoder->reg[v+j]));
388 DEBUG(printk(KERN_INFO "\n"));
390 break;
392 default:
393 DEBUG(printk(KERN_INFO "unknown saa7110_command??(%d)\n",cmd));
394 return -EINVAL;
396 return 0;
399 /* ----------------------------------------------------------------------- */
401 struct i2c_driver i2c_driver_saa7110 =
403 "saa7110", /* name */
405 I2C_DRIVERID_VIDEODECODER, /* in i2c.h */
406 I2C_SAA7110, I2C_SAA7110+1, /* Addr range */
408 saa7110_attach,
409 saa7110_detach,
410 saa7110_command
413 EXPORT_NO_SYMBOLS;
415 #ifdef MODULE
416 int init_module(void)
417 #else
418 int saa7110_init(void)
419 #endif
421 return i2c_register_driver(&i2c_driver_saa7110);
424 #ifdef MODULE
425 void cleanup_module(void)
427 i2c_unregister_driver(&i2c_driver_saa7110);
429 #endif