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
saa7110_write(struct saa7110 * decoder,unsigned char subaddr,unsigned char data)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
saa7110_write_block(struct saa7110 * decoder,unsigned const char * data,unsigned int len)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
saa7110_read(struct saa7110 * decoder)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
saa7110_selmux(struct i2c_device * device,int chan)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
determine_norm(struct i2c_device * dev)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
saa7110_attach(struct i2c_device * device)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
saa7110_detach(struct i2c_device * device)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
saa7110_command(struct i2c_device * device,unsigned int cmd,void * arg)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 
saa7110_init(void)417 static int saa7110_init(void)
418 {
419 	return i2c_register_driver(&i2c_driver_saa7110);
420 }
421 
saa7110_exit(void)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");
431