File: /usr/src/linux/drivers/media/video/saa7110.c
1 /*
2 saa7110 - Philips SAA7110(A) video decoder driver
3
4 Copyright (C) 1998 Pauline Middelink <middelin@polyware.nl>
5
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.
10
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.
15
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.
19 */
20
21 #include <linux/module.h>
22 #include <linux/init.h>
23 #include <linux/types.h>
24 #include <linux/delay.h>
25 #include <linux/slab.h>
26 #include <asm/io.h>
27 #include <asm/uaccess.h>
28
29 #include <linux/i2c-old.h>
30 #include <linux/videodev.h>
31 #include "linux/video_decoder.h"
32
33 #define DEBUG(x...) /* remove when no long debugging */
34
35 #define SAA7110_MAX_INPUT 9 /* 6 CVBS, 3 SVHS */
36 #define SAA7110_MAX_OUTPUT 0 /* its a decoder only */
37
38 #define I2C_SAA7110 0x9C /* or 0x9E */
39
40 #define I2C_DELAY 10 /* 10 us or 100khz */
41
42 struct saa7110 {
43 struct i2c_bus *bus;
44 int addr;
45 unsigned char reg[36];
46
47 int norm;
48 int input;
49 int enable;
50 int bright;
51 int contrast;
52 int hue;
53 int sat;
54 };
55
56 /* ----------------------------------------------------------------------- */
57 /* I2C support functions */
58 /* ----------------------------------------------------------------------- */
59 static
60 int saa7110_write(struct saa7110 *decoder, unsigned char subaddr, unsigned char data)
61 {
62 int ack;
63
64 LOCK_I2C_BUS(decoder->bus);
65 i2c_start(decoder->bus);
66 i2c_sendbyte(decoder->bus, decoder->addr, I2C_DELAY);
67 i2c_sendbyte(decoder->bus, subaddr, I2C_DELAY);
68 ack = i2c_sendbyte(decoder->bus, data, I2C_DELAY);
69 i2c_stop(decoder->bus);
70 decoder->reg[subaddr] = data;
71 UNLOCK_I2C_BUS(decoder->bus);
72 return ack;
73 }
74
75 static
76 int saa7110_write_block(struct saa7110* decoder, unsigned const char *data, unsigned int len)
77 {
78 unsigned subaddr = *data;
79
80 LOCK_I2C_BUS(decoder->bus);
81 i2c_start(decoder->bus);
82 i2c_sendbyte(decoder->bus,decoder->addr,I2C_DELAY);
83 while (len-- > 0) {
84 if (i2c_sendbyte(decoder->bus,*data,0)) {
85 i2c_stop(decoder->bus);
86 return -EAGAIN;
87 }
88 decoder->reg[subaddr++] = *data++;
89 }
90 i2c_stop(decoder->bus);
91 UNLOCK_I2C_BUS(decoder->bus);
92
93 return 0;
94 }
95
96 static
97 int saa7110_read(struct saa7110* decoder)
98 {
99 int data;
100
101 LOCK_I2C_BUS(decoder->bus);
102 i2c_start(decoder->bus);
103 i2c_sendbyte(decoder->bus, decoder->addr, I2C_DELAY);
104 i2c_start(decoder->bus);
105 i2c_sendbyte(decoder->bus, decoder->addr | 1, I2C_DELAY);
106 data = i2c_readbyte(decoder->bus, 1);
107 i2c_stop(decoder->bus);
108 UNLOCK_I2C_BUS(decoder->bus);
109 return data;
110 }
111
112 /* ----------------------------------------------------------------------- */
113 /* SAA7110 functions */
114 /* ----------------------------------------------------------------------- */
115 static
116 int saa7110_selmux(struct i2c_device *device, int chan)
117 {
118 static const unsigned char modes[9][8] = {
119 /* mode 0 */ { 0x00, 0xD9, 0x17, 0x40, 0x03, 0x44, 0x75, 0x16 },
120 /* mode 1 */ { 0x00, 0xD8, 0x17, 0x40, 0x03, 0x44, 0x75, 0x16 },
121 /* mode 2 */ { 0x00, 0xBA, 0x07, 0x91, 0x03, 0x60, 0xB5, 0x05 },
122 /* mode 3 */ { 0x00, 0xB8, 0x07, 0x91, 0x03, 0x60, 0xB5, 0x05 },
123 /* mode 4 */ { 0x00, 0x7C, 0x07, 0xD2, 0x83, 0x60, 0xB5, 0x03 },
124 /* mode 5 */ { 0x00, 0x78, 0x07, 0xD2, 0x83, 0x60, 0xB5, 0x03 },
125 /* mode 6 */ { 0x80, 0x59, 0x17, 0x42, 0xA3, 0x44, 0x75, 0x12 },
126 /* mode 7 */ { 0x80, 0x9A, 0x17, 0xB1, 0x13, 0x60, 0xB5, 0x14 },
127 /* mode 8 */ { 0x80, 0x3C, 0x27, 0xC1, 0x23, 0x44, 0x75, 0x21 } };
128 struct saa7110* decoder = device->data;
129 const unsigned char* ptr = modes[chan];
130
131 saa7110_write(decoder,0x06,ptr[0]); /* Luminance control */
132 saa7110_write(decoder,0x20,ptr[1]); /* Analog Control #1 */
133 saa7110_write(decoder,0x21,ptr[2]); /* Analog Control #2 */
134 saa7110_write(decoder,0x22,ptr[3]); /* Mixer Control #1 */
135 saa7110_write(decoder,0x2C,ptr[4]); /* Mixer Control #2 */
136 saa7110_write(decoder,0x30,ptr[5]); /* ADCs gain control */
137 saa7110_write(decoder,0x31,ptr[6]); /* Mixer Control #3 */
138 saa7110_write(decoder,0x21,ptr[7]); /* Analog Control #2 */
139
140 return 0;
141 }
142
143 static
144 int determine_norm(struct i2c_device* dev)
145 {
146 struct saa7110* decoder = dev->data;
147 int status;
148
149 /* mode changed, start automatic detection */
150 status = saa7110_read(decoder);
151 if ((status & 3) == 0) {
152 saa7110_write(decoder,0x06,0x80);
153 if (status & 0x20) {
154 DEBUG(printk(KERN_INFO "%s: norm=bw60\n",dev->name));
155 saa7110_write(decoder,0x2E,0x81);
156 return VIDEO_MODE_NTSC;
157 }
158 DEBUG(printk(KERN_INFO "%s: norm=bw50\n",dev->name));
159 saa7110_write(decoder,0x2E,0x9A);
160 return VIDEO_MODE_PAL;
161 }
162
163 saa7110_write(decoder,0x06,0x00);
164 if (status & 0x20) { /* 60Hz */
165 DEBUG(printk(KERN_INFO "%s: norm=ntsc\n",dev->name));
166 saa7110_write(decoder,0x0D,0x06);
167 saa7110_write(decoder,0x11,0x2C);
168 saa7110_write(decoder,0x2E,0x81);
169 return VIDEO_MODE_NTSC;
170 }
171
172 /* 50Hz -> PAL/SECAM */
173 saa7110_write(decoder,0x0D,0x06);
174 saa7110_write(decoder,0x11,0x59);
175 saa7110_write(decoder,0x2E,0x9A);
176
177 mdelay(150); /* pause 150 ms */
178
179 status = saa7110_read(decoder);
180 if ((status & 0x03) == 0x01) {
181 DEBUG(printk(KERN_INFO "%s: norm=secam\n",dev->name));
182 saa7110_write(decoder,0x0D,0x07);
183 return VIDEO_MODE_SECAM;
184 }
185 DEBUG(printk(KERN_INFO "%s: norm=pal\n",dev->name));
186 return VIDEO_MODE_PAL;
187 }
188
189 static
190 int saa7110_attach(struct i2c_device *device)
191 {
192 static const unsigned char initseq[] = {
193 0, 0x4C, 0x3C, 0x0D, 0xEF, 0xBD, 0xF0, 0x00, 0x00,
194 0xF8, 0xF8, 0x60, 0x60, 0x00, 0x06, 0x18, 0x90,
195 0x00, 0x2C, 0x40, 0x46, 0x42, 0x1A, 0xFF, 0xDA,
196 0xF0, 0x8B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 0xD9, 0x17, 0x40, 0x41, 0x80, 0x41, 0x80, 0x4F,
198 0xFE, 0x01, 0xCF, 0x0F, 0x03, 0x01, 0x81, 0x03,
199 0x40, 0x75, 0x01, 0x8C, 0x03};
200 struct saa7110* decoder;
201 int rv;
202
203 device->data = decoder = kmalloc(sizeof(struct saa7110), GFP_KERNEL);
204 if (device->data == 0)
205 return -ENOMEM;
206
207 MOD_INC_USE_COUNT;
208
209 /* clear our private data */
210 memset(decoder, 0, sizeof(struct saa7110));
211 strcpy(device->name, "saa7110");
212 decoder->bus = device->bus;
213 decoder->addr = device->addr;
214 decoder->norm = VIDEO_MODE_PAL;
215 decoder->input = 0;
216 decoder->enable = 1;
217 decoder->bright = 32768;
218 decoder->contrast = 32768;
219 decoder->hue = 32768;
220 decoder->sat = 32768;
221
222 rv = saa7110_write_block(decoder, initseq, sizeof(initseq));
223 if (rv < 0)
224 printk(KERN_ERR "%s_attach: init status %d\n", device->name, rv);
225 else {
226 saa7110_write(decoder,0x21,0x16);
227 saa7110_write(decoder,0x0D,0x04);
228 DEBUG(printk(KERN_INFO "%s_attach: chip version %x\n", device->name, saa7110_read(decoder)));
229 saa7110_write(decoder,0x0D,0x06);
230 }
231
232 /* setup and implicit mode 0 select has been performed */
233 return 0;
234 }
235
236 static
237 int saa7110_detach(struct i2c_device *device)
238 {
239 struct saa7110* decoder = device->data;
240
241 DEBUG(printk(KERN_INFO "%s_detach\n",device->name));
242
243 /* stop further output */
244 saa7110_write(decoder,0x0E,0x00);
245
246 kfree(device->data);
247
248 MOD_DEC_USE_COUNT;
249 return 0;
250 }
251
252 static
253 int saa7110_command(struct i2c_device *device, unsigned int cmd, void *arg)
254 {
255 struct saa7110* decoder = device->data;
256 int v;
257
258 switch (cmd) {
259 case DECODER_GET_CAPABILITIES:
260 {
261 struct video_decoder_capability *dc = arg;
262 dc->flags = VIDEO_DECODER_PAL
263 | VIDEO_DECODER_NTSC
264 | VIDEO_DECODER_SECAM
265 | VIDEO_DECODER_AUTO
266 | VIDEO_DECODER_CCIR;
267 dc->inputs = SAA7110_MAX_INPUT;
268 dc->outputs = SAA7110_MAX_OUTPUT;
269 }
270 break;
271
272 case DECODER_GET_STATUS:
273 {
274 struct saa7110* decoder = device->data;
275 int status;
276 int res = 0;
277
278 status = i2c_read(device->bus,device->addr|1);
279 if (status & 0x40)
280 res |= DECODER_STATUS_GOOD;
281 if (status & 0x03)
282 res |= DECODER_STATUS_COLOR;
283
284 switch (decoder->norm) {
285 case VIDEO_MODE_NTSC:
286 res |= DECODER_STATUS_NTSC;
287 break;
288 case VIDEO_MODE_PAL:
289 res |= DECODER_STATUS_PAL;
290 break;
291 case VIDEO_MODE_SECAM:
292 res |= DECODER_STATUS_SECAM;
293 break;
294 }
295 *(int*)arg = res;
296 }
297 break;
298
299 case DECODER_SET_NORM:
300 v = *(int*)arg;
301 if (decoder->norm != v) {
302 decoder->norm = v;
303 saa7110_write(decoder, 0x06, 0x00);
304 switch (v) {
305 case VIDEO_MODE_NTSC:
306 saa7110_write(decoder, 0x0D, 0x06);
307 saa7110_write(decoder, 0x11, 0x2C);
308 saa7110_write(decoder, 0x30, 0x81);
309 saa7110_write(decoder, 0x2A, 0xDF);
310 break;
311 case VIDEO_MODE_PAL:
312 saa7110_write(decoder, 0x0D, 0x06);
313 saa7110_write(decoder, 0x11, 0x59);
314 saa7110_write(decoder, 0x2E, 0x9A);
315 break;
316 case VIDEO_MODE_SECAM:
317 saa7110_write(decoder, 0x0D, 0x07);
318 saa7110_write(decoder, 0x11, 0x59);
319 saa7110_write(decoder, 0x2E, 0x9A);
320 break;
321 case VIDEO_MODE_AUTO:
322 *(int*)arg = determine_norm(device);
323 break;
324 default:
325 return -EPERM;
326 }
327 }
328 break;
329
330 case DECODER_SET_INPUT:
331 v = *(int*)arg;
332 if (v<0 || v>SAA7110_MAX_INPUT)
333 return -EINVAL;
334 if (decoder->input != v) {
335 decoder->input = v;
336 saa7110_selmux(device, v);
337 }
338 break;
339
340 case DECODER_SET_OUTPUT:
341 v = *(int*)arg;
342 /* not much choice of outputs */
343 if (v != 0)
344 return -EINVAL;
345 break;
346
347 case DECODER_ENABLE_OUTPUT:
348 v = *(int*)arg;
349 if (decoder->enable != v) {
350 decoder->enable = v;
351 saa7110_write(decoder,0x0E, v ? 0x18 : 0x00);
352 }
353 break;
354
355 case DECODER_SET_PICTURE:
356 {
357 struct video_picture *pic = arg;
358
359 if (decoder->bright != pic->brightness) {
360 /* We want 0 to 255 we get 0-65535 */
361 decoder->bright = pic->brightness;
362 saa7110_write(decoder, 0x19, decoder->bright >> 8);
363 }
364 if (decoder->contrast != pic->contrast) {
365 /* We want 0 to 127 we get 0-65535 */
366 decoder->contrast = pic->contrast;
367 saa7110_write(decoder, 0x13, decoder->contrast >> 9);
368 }
369 if (decoder->sat != pic->colour) {
370 /* We want 0 to 127 we get 0-65535 */
371 decoder->sat = pic->colour;
372 saa7110_write(decoder, 0x12, decoder->sat >> 9);
373 }
374 if (decoder->hue != pic->hue) {
375 /* We want -128 to 127 we get 0-65535 */
376 decoder->hue = pic->hue;
377 saa7110_write(decoder, 0x07, (decoder->hue>>8)-128);
378 }
379 }
380 break;
381
382 case DECODER_DUMP:
383 for (v=0; v<34; v+=16) {
384 int j;
385 DEBUG(printk(KERN_INFO "%s: %03x\n",device->name,v));
386 for (j=0; j<16; j++) {
387 DEBUG(printk(KERN_INFO " %02x",decoder->reg[v+j]));
388 }
389 DEBUG(printk(KERN_INFO "\n"));
390 }
391 break;
392
393 default:
394 DEBUG(printk(KERN_INFO "unknown saa7110_command??(%d)\n",cmd));
395 return -EINVAL;
396 }
397 return 0;
398 }
399
400 /* ----------------------------------------------------------------------- */
401
402 static struct i2c_driver i2c_driver_saa7110 =
403 {
404 "saa7110", /* name */
405
406 I2C_DRIVERID_VIDEODECODER, /* in i2c.h */
407 I2C_SAA7110, I2C_SAA7110+1, /* Addr range */
408
409 saa7110_attach,
410 saa7110_detach,
411 saa7110_command
412 };
413
414 EXPORT_NO_SYMBOLS;
415
416 static int saa7110_init(void)
417 {
418 return i2c_register_driver(&i2c_driver_saa7110);
419 }
420
421 static void saa7110_exit(void)
422 {
423 i2c_unregister_driver(&i2c_driver_saa7110);
424 }
425
426
427 module_init(saa7110_init);
428 module_exit(saa7110_exit);
429