• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  bt819 - BT819A VideoStream Decoder (Rockwell Part)
3  *
4  * Copyright (C) 1999 Mike Bernson <mike@mlb.org>
5  * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
6  *
7  * Modifications for LML33/DC10plus unified driver
8  * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
9  *
10  * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
11  *    - moved over to linux>=2.4.x i2c protocol (9/9/2002)
12  *
13  * This code was modify/ported from the saa7111 driver written
14  * by Dave Perks.
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 2 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29  */
30 
31 #include <linux/module.h>
32 #include <linux/delay.h>
33 #include <linux/types.h>
34 #include <linux/ioctl.h>
35 #include <asm/uaccess.h>
36 #include <linux/i2c.h>
37 #include <linux/i2c-id.h>
38 #include <linux/videodev.h>
39 #include <linux/video_decoder.h>
40 #include <media/v4l2-common.h>
41 #include <media/v4l2-i2c-drv-legacy.h>
42 
43 MODULE_DESCRIPTION("Brooktree-819 video decoder driver");
44 MODULE_AUTHOR("Mike Bernson & Dave Perks");
45 MODULE_LICENSE("GPL");
46 
47 static int debug;
48 module_param(debug, int, 0);
49 MODULE_PARM_DESC(debug, "Debug level (0-1)");
50 
51 /* ----------------------------------------------------------------------- */
52 
53 struct bt819 {
54 	unsigned char reg[32];
55 
56 	int initialized;
57 	int norm;
58 	int input;
59 	int enable;
60 	int bright;
61 	int contrast;
62 	int hue;
63 	int sat;
64 };
65 
66 struct timing {
67 	int hactive;
68 	int hdelay;
69 	int vactive;
70 	int vdelay;
71 	int hscale;
72 	int vscale;
73 };
74 
75 /* for values, see the bt819 datasheet */
76 static struct timing timing_data[] = {
77 	{864 - 24, 20, 625 - 2, 1, 0x0504, 0x0000},
78 	{858 - 24, 20, 525 - 2, 1, 0x00f8, 0x0000},
79 };
80 
81 /* ----------------------------------------------------------------------- */
82 
bt819_write(struct i2c_client * client,u8 reg,u8 value)83 static inline int bt819_write(struct i2c_client *client, u8 reg, u8 value)
84 {
85 	struct bt819 *decoder = i2c_get_clientdata(client);
86 
87 	decoder->reg[reg] = value;
88 	return i2c_smbus_write_byte_data(client, reg, value);
89 }
90 
bt819_setbit(struct i2c_client * client,u8 reg,u8 bit,u8 value)91 static inline int bt819_setbit(struct i2c_client *client, u8 reg, u8 bit, u8 value)
92 {
93 	struct bt819 *decoder = i2c_get_clientdata(client);
94 
95 	return bt819_write(client, reg,
96 		(decoder->reg[reg] & ~(1 << bit)) | (value ? (1 << bit) : 0));
97 }
98 
bt819_write_block(struct i2c_client * client,const u8 * data,unsigned int len)99 static int bt819_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
100 {
101 	int ret = -1;
102 	u8 reg;
103 
104 	/* the bt819 has an autoincrement function, use it if
105 	 * the adapter understands raw I2C */
106 	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
107 		/* do raw I2C, not smbus compatible */
108 		struct bt819 *decoder = i2c_get_clientdata(client);
109 		u8 block_data[32];
110 		int block_len;
111 
112 		while (len >= 2) {
113 			block_len = 0;
114 			block_data[block_len++] = reg = data[0];
115 			do {
116 				block_data[block_len++] =
117 				    decoder->reg[reg++] = data[1];
118 				len -= 2;
119 				data += 2;
120 			} while (len >= 2 && data[0] == reg && block_len < 32);
121 			ret = i2c_master_send(client, block_data, block_len);
122 			if (ret < 0)
123 				break;
124 		}
125 	} else {
126 		/* do some slow I2C emulation kind of thing */
127 		while (len >= 2) {
128 			reg = *data++;
129 			if ((ret = bt819_write(client, reg, *data++)) < 0)
130 				break;
131 			len -= 2;
132 		}
133 	}
134 
135 	return ret;
136 }
137 
bt819_read(struct i2c_client * client,u8 reg)138 static inline int bt819_read(struct i2c_client *client, u8 reg)
139 {
140 	return i2c_smbus_read_byte_data(client, reg);
141 }
142 
bt819_init(struct i2c_client * client)143 static int bt819_init(struct i2c_client *client)
144 {
145 	struct bt819 *decoder = i2c_get_clientdata(client);
146 
147 	static unsigned char init[] = {
148 		/*0x1f, 0x00,*/     /* Reset */
149 		0x01, 0x59,	/* 0x01 input format */
150 		0x02, 0x00,	/* 0x02 temporal decimation */
151 		0x03, 0x12,	/* 0x03 Cropping msb */
152 		0x04, 0x16,	/* 0x04 Vertical Delay, lsb */
153 		0x05, 0xe0,	/* 0x05 Vertical Active lsb */
154 		0x06, 0x80,	/* 0x06 Horizontal Delay lsb */
155 		0x07, 0xd0,	/* 0x07 Horizontal Active lsb */
156 		0x08, 0x00,	/* 0x08 Horizontal Scaling msb */
157 		0x09, 0xf8,	/* 0x09 Horizontal Scaling lsb */
158 		0x0a, 0x00,	/* 0x0a Brightness control */
159 		0x0b, 0x30,	/* 0x0b Miscellaneous control */
160 		0x0c, 0xd8,	/* 0x0c Luma Gain lsb */
161 		0x0d, 0xfe,	/* 0x0d Chroma Gain (U) lsb */
162 		0x0e, 0xb4,	/* 0x0e Chroma Gain (V) msb */
163 		0x0f, 0x00,	/* 0x0f Hue control */
164 		0x12, 0x04,	/* 0x12 Output Format */
165 		0x13, 0x20,	/* 0x13 Vertial Scaling msb 0x00
166 					   chroma comb OFF, line drop scaling, interlace scaling
167 					   BUG? Why does turning the chroma comb on fuck up color?
168 					   Bug in the bt819 stepping on my board?
169 					*/
170 		0x14, 0x00,	/* 0x14 Vertial Scaling lsb */
171 		0x16, 0x07,	/* 0x16 Video Timing Polarity
172 					   ACTIVE=active low
173 					   FIELD: high=odd,
174 					   vreset=active high,
175 					   hreset=active high */
176 		0x18, 0x68,	/* 0x18 AGC Delay */
177 		0x19, 0x5d,	/* 0x19 Burst Gate Delay */
178 		0x1a, 0x80,	/* 0x1a ADC Interface */
179 	};
180 
181 	struct timing *timing = &timing_data[decoder->norm];
182 
183 	init[0x03 * 2 - 1] =
184 	    (((timing->vdelay >> 8) & 0x03) << 6) |
185 	    (((timing->vactive >> 8) & 0x03) << 4) |
186 	    (((timing->hdelay >> 8) & 0x03) << 2) |
187 	    ((timing->hactive >> 8) & 0x03);
188 	init[0x04 * 2 - 1] = timing->vdelay & 0xff;
189 	init[0x05 * 2 - 1] = timing->vactive & 0xff;
190 	init[0x06 * 2 - 1] = timing->hdelay & 0xff;
191 	init[0x07 * 2 - 1] = timing->hactive & 0xff;
192 	init[0x08 * 2 - 1] = timing->hscale >> 8;
193 	init[0x09 * 2 - 1] = timing->hscale & 0xff;
194 	/* 0x15 in array is address 0x19 */
195 	init[0x15 * 2 - 1] = (decoder->norm == 0) ? 115 : 93;	/* Chroma burst delay */
196 	/* reset */
197 	bt819_write(client, 0x1f, 0x00);
198 	mdelay(1);
199 
200 	/* init */
201 	return bt819_write_block(client, init, sizeof(init));
202 }
203 
204 /* ----------------------------------------------------------------------- */
205 
bt819_command(struct i2c_client * client,unsigned cmd,void * arg)206 static int bt819_command(struct i2c_client *client, unsigned cmd, void *arg)
207 {
208 	int temp;
209 
210 	struct bt819 *decoder = i2c_get_clientdata(client);
211 
212 	if (!decoder->initialized) {	/* First call to bt819_init could be */
213 		bt819_init(client);	/* without #FRST = 0 */
214 		decoder->initialized = 1;
215 	}
216 
217 	switch (cmd) {
218 	case 0:
219 		/* This is just for testing!!! */
220 		bt819_init(client);
221 		break;
222 
223 	case DECODER_GET_CAPABILITIES:
224 	{
225 		struct video_decoder_capability *cap = arg;
226 
227 		cap->flags = VIDEO_DECODER_PAL |
228 			     VIDEO_DECODER_NTSC |
229 			     VIDEO_DECODER_AUTO |
230 			     VIDEO_DECODER_CCIR;
231 		cap->inputs = 8;
232 		cap->outputs = 1;
233 		break;
234 	}
235 
236 	case DECODER_GET_STATUS:
237 	{
238 		int *iarg = arg;
239 		int status;
240 		int res;
241 
242 		status = bt819_read(client, 0x00);
243 		res = 0;
244 		if ((status & 0x80))
245 			res |= DECODER_STATUS_GOOD;
246 
247 		switch (decoder->norm) {
248 		case VIDEO_MODE_NTSC:
249 			res |= DECODER_STATUS_NTSC;
250 			break;
251 		case VIDEO_MODE_PAL:
252 			res |= DECODER_STATUS_PAL;
253 			break;
254 		default:
255 		case VIDEO_MODE_AUTO:
256 			if ((status & 0x10))
257 				res |= DECODER_STATUS_PAL;
258 			else
259 				res |= DECODER_STATUS_NTSC;
260 			break;
261 		}
262 		res |= DECODER_STATUS_COLOR;
263 		*iarg = res;
264 
265 		v4l_dbg(1, debug, client, "get status %x\n", *iarg);
266 		break;
267 	}
268 
269 	case DECODER_SET_NORM:
270 	{
271 		int *iarg = arg;
272 		struct timing *timing = NULL;
273 
274 		v4l_dbg(1, debug, client, "set norm %x\n", *iarg);
275 
276 		switch (*iarg) {
277 		case VIDEO_MODE_NTSC:
278 			bt819_setbit(client, 0x01, 0, 1);
279 			bt819_setbit(client, 0x01, 1, 0);
280 			bt819_setbit(client, 0x01, 5, 0);
281 			bt819_write(client, 0x18, 0x68);
282 			bt819_write(client, 0x19, 0x5d);
283 			/* bt819_setbit(client, 0x1a,  5, 1); */
284 			timing = &timing_data[VIDEO_MODE_NTSC];
285 			break;
286 		case VIDEO_MODE_PAL:
287 			bt819_setbit(client, 0x01, 0, 1);
288 			bt819_setbit(client, 0x01, 1, 1);
289 			bt819_setbit(client, 0x01, 5, 1);
290 			bt819_write(client, 0x18, 0x7f);
291 			bt819_write(client, 0x19, 0x72);
292 			/* bt819_setbit(client, 0x1a,  5, 0); */
293 			timing = &timing_data[VIDEO_MODE_PAL];
294 			break;
295 		case VIDEO_MODE_AUTO:
296 			bt819_setbit(client, 0x01, 0, 0);
297 			bt819_setbit(client, 0x01, 1, 0);
298 			break;
299 		default:
300 			v4l_dbg(1, debug, client, "unsupported norm %x\n", *iarg);
301 			return -EINVAL;
302 		}
303 
304 		if (timing) {
305 			bt819_write(client, 0x03,
306 				    (((timing->vdelay >> 8) & 0x03) << 6) |
307 				    (((timing->vactive >> 8) & 0x03) << 4) |
308 				    (((timing->hdelay >> 8) & 0x03) << 2) |
309 				     ((timing->hactive >> 8) & 0x03) );
310 			bt819_write(client, 0x04, timing->vdelay & 0xff);
311 			bt819_write(client, 0x05, timing->vactive & 0xff);
312 			bt819_write(client, 0x06, timing->hdelay & 0xff);
313 			bt819_write(client, 0x07, timing->hactive & 0xff);
314 			bt819_write(client, 0x08, (timing->hscale >> 8) & 0xff);
315 			bt819_write(client, 0x09, timing->hscale & 0xff);
316 		}
317 
318 		decoder->norm = *iarg;
319 		break;
320 	}
321 
322 	case DECODER_SET_INPUT:
323 	{
324 		int *iarg = arg;
325 
326 		v4l_dbg(1, debug, client, "set input %x\n", *iarg);
327 
328 		if (*iarg < 0 || *iarg > 7)
329 			return -EINVAL;
330 
331 		if (decoder->input != *iarg) {
332 			decoder->input = *iarg;
333 			/* select mode */
334 			if (decoder->input == 0) {
335 				bt819_setbit(client, 0x0b, 6, 0);
336 				bt819_setbit(client, 0x1a, 1, 1);
337 			} else {
338 				bt819_setbit(client, 0x0b, 6, 1);
339 				bt819_setbit(client, 0x1a, 1, 0);
340 			}
341 		}
342 		break;
343 	}
344 
345 	case DECODER_SET_OUTPUT:
346 	{
347 		int *iarg = arg;
348 
349 		v4l_dbg(1, debug, client, "set output %x\n", *iarg);
350 
351 		/* not much choice of outputs */
352 		if (*iarg != 0)
353 			return -EINVAL;
354 		break;
355 	}
356 
357 	case DECODER_ENABLE_OUTPUT:
358 	{
359 		int *iarg = arg;
360 		int enable = (*iarg != 0);
361 
362 		v4l_dbg(1, debug, client, "enable output %x\n", *iarg);
363 
364 		if (decoder->enable != enable) {
365 			decoder->enable = enable;
366 			bt819_setbit(client, 0x16, 7, !enable);
367 		}
368 		break;
369 	}
370 
371 	case DECODER_SET_PICTURE:
372 	{
373 		struct video_picture *pic = arg;
374 
375 		v4l_dbg(1, debug, client,
376 			"set picture brightness %d contrast %d colour %d\n",
377 			pic->brightness, pic->contrast, pic->colour);
378 
379 
380 		if (decoder->bright != pic->brightness) {
381 			/* We want -128 to 127 we get 0-65535 */
382 			decoder->bright = pic->brightness;
383 			bt819_write(client, 0x0a,
384 				    (decoder->bright >> 8) - 128);
385 		}
386 
387 		if (decoder->contrast != pic->contrast) {
388 			/* We want 0 to 511 we get 0-65535 */
389 			decoder->contrast = pic->contrast;
390 			bt819_write(client, 0x0c,
391 				    (decoder->contrast >> 7) & 0xff);
392 			bt819_setbit(client, 0x0b, 2,
393 				     ((decoder->contrast >> 15) & 0x01));
394 		}
395 
396 		if (decoder->sat != pic->colour) {
397 			/* We want 0 to 511 we get 0-65535 */
398 			decoder->sat = pic->colour;
399 			bt819_write(client, 0x0d,
400 				    (decoder->sat >> 7) & 0xff);
401 			bt819_setbit(client, 0x0b, 1,
402 				     ((decoder->sat >> 15) & 0x01));
403 
404 			temp = (decoder->sat * 201) / 237;
405 			bt819_write(client, 0x0e, (temp >> 7) & 0xff);
406 			bt819_setbit(client, 0x0b, 0, (temp >> 15) & 0x01);
407 		}
408 
409 		if (decoder->hue != pic->hue) {
410 			/* We want -128 to 127 we get 0-65535 */
411 			decoder->hue = pic->hue;
412 			bt819_write(client, 0x0f,
413 				    128 - (decoder->hue >> 8));
414 		}
415 		break;
416 	}
417 
418 	default:
419 		return -EINVAL;
420 	}
421 
422 	return 0;
423 }
424 
425 /* ----------------------------------------------------------------------- */
426 
427 static unsigned short normal_i2c[] = { 0x8a >> 1, I2C_CLIENT_END };
428 
429 I2C_CLIENT_INSMOD;
430 
bt819_probe(struct i2c_client * client,const struct i2c_device_id * id)431 static int bt819_probe(struct i2c_client *client,
432 			const struct i2c_device_id *id)
433 {
434 	int i, ver;
435 	struct bt819 *decoder;
436 	const char *name;
437 
438 	/* Check if the adapter supports the needed features */
439 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
440 		return -ENODEV;
441 
442 	ver = bt819_read(client, 0x17);
443 	switch (ver & 0xf0) {
444 	case 0x70:
445 		name = "bt819a";
446 		break;
447 	case 0x60:
448 		name = "bt817a";
449 		break;
450 	case 0x20:
451 		name = "bt815a";
452 		break;
453 	default:
454 		v4l_dbg(1, debug, client,
455 			"unknown chip version 0x%02x\n", ver);
456 		return -ENODEV;
457 	}
458 
459 	v4l_info(client, "%s found @ 0x%x (%s)\n", name,
460 			client->addr << 1, client->adapter->name);
461 
462 	decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL);
463 	if (decoder == NULL)
464 		return -ENOMEM;
465 	decoder->norm = VIDEO_MODE_NTSC;
466 	decoder->input = 0;
467 	decoder->enable = 1;
468 	decoder->bright = 32768;
469 	decoder->contrast = 32768;
470 	decoder->hue = 32768;
471 	decoder->sat = 32768;
472 	decoder->initialized = 0;
473 	i2c_set_clientdata(client, decoder);
474 
475 	i = bt819_init(client);
476 	if (i < 0)
477 		v4l_dbg(1, debug, client, "init status %d\n", i);
478 	return 0;
479 }
480 
bt819_remove(struct i2c_client * client)481 static int bt819_remove(struct i2c_client *client)
482 {
483 	kfree(i2c_get_clientdata(client));
484 	return 0;
485 }
486 
487 /* ----------------------------------------------------------------------- */
488 
489 static const struct i2c_device_id bt819_id[] = {
490 	{ "bt819a", 0 },
491 	{ "bt817a", 0 },
492 	{ "bt815a", 0 },
493 	{ }
494 };
495 MODULE_DEVICE_TABLE(i2c, bt819_id);
496 
497 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
498 	.name = "bt819",
499 	.driverid = I2C_DRIVERID_BT819,
500 	.command = bt819_command,
501 	.probe = bt819_probe,
502 	.remove = bt819_remove,
503 	.id_table = bt819_id,
504 };
505