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