~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/media/video/saa7110.c

Version: ~ [ 2.2.5 ] ~ [ 2.4.1 ] ~ [ 2.4.9 ] ~ [ 2.6.17.10 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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/types.h>
 23 #include <linux/delay.h>
 24 #include <linux/slab.h>
 25 #include <asm/io.h>
 26 #include <asm/uaccess.h>
 27 
 28 #include <linux/i2c-old.h>
 29 #include <linux/videodev.h>
 30 #include "linux/video_decoder.h"
 31 
 32 #define DEBUG(x...)                     /* remove when no long debugging */
 33 
 34 #define SAA7110_MAX_INPUT       9       /* 6 CVBS, 3 SVHS */
 35 #define SAA7110_MAX_OUTPUT      0       /* its a decoder only */
 36 
 37 #define I2C_SAA7110             0x9C    /* or 0x9E */
 38 
 39 #define I2C_DELAY               10      /* 10 us or 100khz */
 40 
 41 struct saa7110 {
 42         struct  i2c_bus *bus;
 43         int             addr;
 44         unsigned char   reg[36];
 45 
 46         int             norm;
 47         int             input;
 48         int             enable;
 49         int             bright;
 50         int             contrast;
 51         int             hue;
 52         int             sat;
 53 };
 54 
 55 /* ----------------------------------------------------------------------- */
 56 /* I2C support functions                                                   */
 57 /* ----------------------------------------------------------------------- */
 58 static
 59 int saa7110_write(struct saa7110 *decoder, unsigned char subaddr, unsigned char data)
 60 {
 61         int ack;
 62 
 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;
 72 }
 73 
 74 static
 75 int saa7110_write_block(struct saa7110* decoder, unsigned const char *data, unsigned int len)
 76 {
 77         unsigned subaddr = *data;
 78 
 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;
 86                 }
 87                 decoder->reg[subaddr++] = *data++;
 88         }
 89         i2c_stop(decoder->bus);
 90         UNLOCK_I2C_BUS(decoder->bus);
 91 
 92         return 0;
 93 }
 94 
 95 static
 96 int saa7110_read(struct saa7110* decoder)
 97 {
 98         int data;
 99 
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;
109 }
110 
111 /* ----------------------------------------------------------------------- */
112 /* SAA7110 functions                                                       */
113 /* ----------------------------------------------------------------------- */
114 static
115 int saa7110_selmux(struct i2c_device *device, int chan)
116 {
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];
129 
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    */
138 
139         return 0;
140 }
141 
142 static
143 int determine_norm(struct i2c_device* dev)
144 {
145         struct  saa7110* decoder = dev->data;
146         int     status;
147 
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;
156                 }
157                 DEBUG(printk(KERN_INFO "%s: norm=bw50\n",dev->name));
158                 saa7110_write(decoder,0x2E,0x9A);
159                 return VIDEO_MODE_PAL;
160         }
161 
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;
169         }
170 
171         /* 50Hz -> PAL/SECAM */
172         saa7110_write(decoder,0x0D,0x06);
173         saa7110_write(decoder,0x11,0x59);
174         saa7110_write(decoder,0x2E,0x9A);
175 
176         mdelay(150);    /* pause 150 ms */
177 
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;
183         }
184         DEBUG(printk(KERN_INFO "%s: norm=pal\n",dev->name));
185         return VIDEO_MODE_PAL;
186 }
187 
188 static
189 int saa7110_attach(struct i2c_device *device)
190 {
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;
201 
202         device->data = decoder = kmalloc(sizeof(struct saa7110), GFP_KERNEL);
203         if (device->data == 0)
204                 return -ENOMEM;
205 
206         MOD_INC_USE_COUNT;
207 
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;
220 
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);
229         }
230 
231         /* setup and implicit mode 0 select has been performed */
232         return 0;
233 }
234 
235 static
236 int saa7110_detach(struct i2c_device *device)
237 {
238         struct saa7110* decoder = device->data;
239 
240         DEBUG(printk(KERN_INFO "%s_detach\n",device->name));
241 
242         /* stop further output */
243         saa7110_write(decoder,0x0E,0x00);
244 
245         kfree(device->data);
246 
247         MOD_DEC_USE_COUNT;
248         return 0;
249 }
250 
251 static
252 int saa7110_command(struct i2c_device *device, unsigned int cmd, void *arg)
253 {
254         struct saa7110* decoder = device->data;
255         int     v;
256 
257         switch (cmd) {
258          case DECODER_GET_CAPABILITIES:
259                 {
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;
268                 }
269                 break;
270 
271          case DECODER_GET_STATUS:
272                 {
273                         struct saa7110* decoder = device->data;
274                         int status;
275                         int res = 0;
276 
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;
282 
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;
293                         }
294                         *(int*)arg = res;
295                 }
296                 break;
297 
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;
325                         }
326                 }
327                 break;
328 
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);
336                 }
337                 break;
338 
339          case DECODER_SET_OUTPUT:
340                 v = *(int*)arg;
341                 /* not much choice of outputs */
342                 if (v != 0)
343                         return -EINVAL;
344                 break;
345 
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);
351                 }
352                 break;
353 
354          case DECODER_SET_PICTURE:
355                 {
356                         struct video_picture *pic = arg;
357 
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);
362                         }
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);
367                         }
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);
372                         }
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);
377                         }
378                 }
379                 break;
380 
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]));
387                         }
388                         DEBUG(printk(KERN_INFO "\n"));
389                 }
390                 break;
391 
392          default:
393                 DEBUG(printk(KERN_INFO "unknown saa7110_command??(%d)\n",cmd));
394                 return -EINVAL;
395         }
396         return 0;
397 }
398 
399 /* ----------------------------------------------------------------------- */
400 
401 struct i2c_driver i2c_driver_saa7110 =
402 {
403         "saa7110",                      /* name */
404 
405         I2C_DRIVERID_VIDEODECODER,      /* in i2c.h */
406         I2C_SAA7110, I2C_SAA7110+1,     /* Addr range */
407 
408         saa7110_attach,
409         saa7110_detach,
410         saa7110_command
411 };
412 
413 EXPORT_NO_SYMBOLS;
414 
415 #ifdef MODULE
416 int init_module(void)
417 #else
418 int saa7110_init(void)
419 #endif
420 {
421         return i2c_register_driver(&i2c_driver_saa7110);
422 }
423 
424 #ifdef MODULE
425 void cleanup_module(void)
426 {
427         i2c_unregister_driver(&i2c_driver_saa7110);
428 }
429 #endif
430 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.