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