• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/media/video/
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/types.h>
33#include <linux/ioctl.h>
34#include <linux/delay.h>
35#include <linux/i2c.h>
36#include <linux/i2c-id.h>
37#include <linux/videodev2.h>
38#include <linux/slab.h>
39#include <media/v4l2-device.h>
40#include <media/v4l2-chip-ident.h>
41#include <media/v4l2-i2c-drv.h>
42#include <media/bt819.h>
43
44MODULE_DESCRIPTION("Brooktree-819 video decoder driver");
45MODULE_AUTHOR("Mike Bernson & Dave Perks");
46MODULE_LICENSE("GPL");
47
48static int debug;
49module_param(debug, int, 0);
50MODULE_PARM_DESC(debug, "Debug level (0-1)");
51
52
53/* ----------------------------------------------------------------------- */
54
55struct bt819 {
56	struct v4l2_subdev sd;
57	unsigned char reg[32];
58
59	v4l2_std_id norm;
60	int ident;
61	int input;
62	int enable;
63	int bright;
64	int contrast;
65	int hue;
66	int sat;
67};
68
69static inline struct bt819 *to_bt819(struct v4l2_subdev *sd)
70{
71	return container_of(sd, struct bt819, sd);
72}
73
74struct timing {
75	int hactive;
76	int hdelay;
77	int vactive;
78	int vdelay;
79	int hscale;
80	int vscale;
81};
82
83/* for values, see the bt819 datasheet */
84static struct timing timing_data[] = {
85	{864 - 24, 20, 625 - 2, 1, 0x0504, 0x0000},
86	{858 - 24, 20, 525 - 2, 1, 0x00f8, 0x0000},
87};
88
89/* ----------------------------------------------------------------------- */
90
91static inline int bt819_write(struct bt819 *decoder, u8 reg, u8 value)
92{
93	struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd);
94
95	decoder->reg[reg] = value;
96	return i2c_smbus_write_byte_data(client, reg, value);
97}
98
99static inline int bt819_setbit(struct bt819 *decoder, u8 reg, u8 bit, u8 value)
100{
101	return bt819_write(decoder, reg,
102		(decoder->reg[reg] & ~(1 << bit)) | (value ? (1 << bit) : 0));
103}
104
105static int bt819_write_block(struct bt819 *decoder, const u8 *data, unsigned int len)
106{
107	struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd);
108	int ret = -1;
109	u8 reg;
110
111	/* the bt819 has an autoincrement function, use it if
112	 * the adapter understands raw I2C */
113	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
114		/* do raw I2C, not smbus compatible */
115		u8 block_data[32];
116		int block_len;
117
118		while (len >= 2) {
119			block_len = 0;
120			block_data[block_len++] = reg = data[0];
121			do {
122				block_data[block_len++] =
123				    decoder->reg[reg++] = data[1];
124				len -= 2;
125				data += 2;
126			} while (len >= 2 && data[0] == reg && block_len < 32);
127			ret = i2c_master_send(client, block_data, block_len);
128			if (ret < 0)
129				break;
130		}
131	} else {
132		/* do some slow I2C emulation kind of thing */
133		while (len >= 2) {
134			reg = *data++;
135			ret = bt819_write(decoder, reg, *data++);
136			if (ret < 0)
137				break;
138			len -= 2;
139		}
140	}
141
142	return ret;
143}
144
145static inline int bt819_read(struct bt819 *decoder, u8 reg)
146{
147	struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd);
148
149	return i2c_smbus_read_byte_data(client, reg);
150}
151
152static int bt819_init(struct v4l2_subdev *sd)
153{
154	static unsigned char init[] = {
155		/*0x1f, 0x00,*/     /* Reset */
156		0x01, 0x59,	/* 0x01 input format */
157		0x02, 0x00,	/* 0x02 temporal decimation */
158		0x03, 0x12,	/* 0x03 Cropping msb */
159		0x04, 0x16,	/* 0x04 Vertical Delay, lsb */
160		0x05, 0xe0,	/* 0x05 Vertical Active lsb */
161		0x06, 0x80,	/* 0x06 Horizontal Delay lsb */
162		0x07, 0xd0,	/* 0x07 Horizontal Active lsb */
163		0x08, 0x00,	/* 0x08 Horizontal Scaling msb */
164		0x09, 0xf8,	/* 0x09 Horizontal Scaling lsb */
165		0x0a, 0x00,	/* 0x0a Brightness control */
166		0x0b, 0x30,	/* 0x0b Miscellaneous control */
167		0x0c, 0xd8,	/* 0x0c Luma Gain lsb */
168		0x0d, 0xfe,	/* 0x0d Chroma Gain (U) lsb */
169		0x0e, 0xb4,	/* 0x0e Chroma Gain (V) msb */
170		0x0f, 0x00,	/* 0x0f Hue control */
171		0x12, 0x04,	/* 0x12 Output Format */
172		0x13, 0x20,	/* 0x13 Vertial Scaling msb 0x00
173					   chroma comb OFF, line drop scaling, interlace scaling
174					   BUG? Why does turning the chroma comb on fuck up color?
175					   Bug in the bt819 stepping on my board?
176					*/
177		0x14, 0x00,	/* 0x14 Vertial Scaling lsb */
178		0x16, 0x07,	/* 0x16 Video Timing Polarity
179					   ACTIVE=active low
180					   FIELD: high=odd,
181					   vreset=active high,
182					   hreset=active high */
183		0x18, 0x68,	/* 0x18 AGC Delay */
184		0x19, 0x5d,	/* 0x19 Burst Gate Delay */
185		0x1a, 0x80,	/* 0x1a ADC Interface */
186	};
187
188	struct bt819 *decoder = to_bt819(sd);
189	struct timing *timing = &timing_data[(decoder->norm & V4L2_STD_525_60) ? 1 : 0];
190
191	init[0x03 * 2 - 1] =
192	    (((timing->vdelay >> 8) & 0x03) << 6) |
193	    (((timing->vactive >> 8) & 0x03) << 4) |
194	    (((timing->hdelay >> 8) & 0x03) << 2) |
195	    ((timing->hactive >> 8) & 0x03);
196	init[0x04 * 2 - 1] = timing->vdelay & 0xff;
197	init[0x05 * 2 - 1] = timing->vactive & 0xff;
198	init[0x06 * 2 - 1] = timing->hdelay & 0xff;
199	init[0x07 * 2 - 1] = timing->hactive & 0xff;
200	init[0x08 * 2 - 1] = timing->hscale >> 8;
201	init[0x09 * 2 - 1] = timing->hscale & 0xff;
202	/* 0x15 in array is address 0x19 */
203	init[0x15 * 2 - 1] = (decoder->norm & V4L2_STD_625_50) ? 115 : 93;	/* Chroma burst delay */
204	/* reset */
205	bt819_write(decoder, 0x1f, 0x00);
206	mdelay(1);
207
208	/* init */
209	return bt819_write_block(decoder, init, sizeof(init));
210}
211
212/* ----------------------------------------------------------------------- */
213
214static int bt819_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd)
215{
216	struct bt819 *decoder = to_bt819(sd);
217	int status = bt819_read(decoder, 0x00);
218	int res = V4L2_IN_ST_NO_SIGNAL;
219	v4l2_std_id std;
220
221	if ((status & 0x80))
222		res = 0;
223
224	if ((status & 0x10))
225		std = V4L2_STD_PAL;
226	else
227		std = V4L2_STD_NTSC;
228	if (pstd)
229		*pstd = std;
230	if (pstatus)
231		*pstatus = status;
232
233	v4l2_dbg(1, debug, sd, "get status %x\n", status);
234	return 0;
235}
236
237static int bt819_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
238{
239	return bt819_status(sd, NULL, std);
240}
241
242static int bt819_g_input_status(struct v4l2_subdev *sd, u32 *status)
243{
244	return bt819_status(sd, status, NULL);
245}
246
247static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
248{
249	struct bt819 *decoder = to_bt819(sd);
250	struct timing *timing = NULL;
251
252	v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std);
253
254	if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL)
255		v4l2_err(sd, "no notify found!\n");
256
257	if (std & V4L2_STD_NTSC) {
258		v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL);
259		bt819_setbit(decoder, 0x01, 0, 1);
260		bt819_setbit(decoder, 0x01, 1, 0);
261		bt819_setbit(decoder, 0x01, 5, 0);
262		bt819_write(decoder, 0x18, 0x68);
263		bt819_write(decoder, 0x19, 0x5d);
264		/* bt819_setbit(decoder, 0x1a,  5, 1); */
265		timing = &timing_data[1];
266	} else if (std & V4L2_STD_PAL) {
267		v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL);
268		bt819_setbit(decoder, 0x01, 0, 1);
269		bt819_setbit(decoder, 0x01, 1, 1);
270		bt819_setbit(decoder, 0x01, 5, 1);
271		bt819_write(decoder, 0x18, 0x7f);
272		bt819_write(decoder, 0x19, 0x72);
273		/* bt819_setbit(decoder, 0x1a,  5, 0); */
274		timing = &timing_data[0];
275	} else {
276		v4l2_dbg(1, debug, sd, "unsupported norm %llx\n",
277				(unsigned long long)std);
278		return -EINVAL;
279	}
280	bt819_write(decoder, 0x03,
281			(((timing->vdelay >> 8) & 0x03) << 6) |
282			(((timing->vactive >> 8) & 0x03) << 4) |
283			(((timing->hdelay >> 8) & 0x03) << 2) |
284			((timing->hactive >> 8) & 0x03));
285	bt819_write(decoder, 0x04, timing->vdelay & 0xff);
286	bt819_write(decoder, 0x05, timing->vactive & 0xff);
287	bt819_write(decoder, 0x06, timing->hdelay & 0xff);
288	bt819_write(decoder, 0x07, timing->hactive & 0xff);
289	bt819_write(decoder, 0x08, (timing->hscale >> 8) & 0xff);
290	bt819_write(decoder, 0x09, timing->hscale & 0xff);
291	decoder->norm = std;
292	v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, NULL);
293	return 0;
294}
295
296static int bt819_s_routing(struct v4l2_subdev *sd,
297			   u32 input, u32 output, u32 config)
298{
299	struct bt819 *decoder = to_bt819(sd);
300
301	v4l2_dbg(1, debug, sd, "set input %x\n", input);
302
303	if (input > 7)
304		return -EINVAL;
305
306	if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL)
307		v4l2_err(sd, "no notify found!\n");
308
309	if (decoder->input != input) {
310		v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL);
311		decoder->input = input;
312		/* select mode */
313		if (decoder->input == 0) {
314			bt819_setbit(decoder, 0x0b, 6, 0);
315			bt819_setbit(decoder, 0x1a, 1, 1);
316		} else {
317			bt819_setbit(decoder, 0x0b, 6, 1);
318			bt819_setbit(decoder, 0x1a, 1, 0);
319		}
320		v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, NULL);
321	}
322	return 0;
323}
324
325static int bt819_s_stream(struct v4l2_subdev *sd, int enable)
326{
327	struct bt819 *decoder = to_bt819(sd);
328
329	v4l2_dbg(1, debug, sd, "enable output %x\n", enable);
330
331	if (decoder->enable != enable) {
332		decoder->enable = enable;
333		bt819_setbit(decoder, 0x16, 7, !enable);
334	}
335	return 0;
336}
337
338static int bt819_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
339{
340	switch (qc->id) {
341	case V4L2_CID_BRIGHTNESS:
342		v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
343		break;
344
345	case V4L2_CID_CONTRAST:
346		v4l2_ctrl_query_fill(qc, 0, 511, 1, 256);
347		break;
348
349	case V4L2_CID_SATURATION:
350		v4l2_ctrl_query_fill(qc, 0, 511, 1, 256);
351		break;
352
353	case V4L2_CID_HUE:
354		v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
355		break;
356
357	default:
358		return -EINVAL;
359	}
360	return 0;
361}
362
363static int bt819_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
364{
365	struct bt819 *decoder = to_bt819(sd);
366	int temp;
367
368	switch (ctrl->id) {
369	case V4L2_CID_BRIGHTNESS:
370		if (decoder->bright == ctrl->value)
371			break;
372		decoder->bright = ctrl->value;
373		bt819_write(decoder, 0x0a, decoder->bright);
374		break;
375
376	case V4L2_CID_CONTRAST:
377		if (decoder->contrast == ctrl->value)
378			break;
379		decoder->contrast = ctrl->value;
380		bt819_write(decoder, 0x0c, decoder->contrast & 0xff);
381		bt819_setbit(decoder, 0x0b, 2, ((decoder->contrast >> 8) & 0x01));
382		break;
383
384	case V4L2_CID_SATURATION:
385		if (decoder->sat == ctrl->value)
386			break;
387		decoder->sat = ctrl->value;
388		bt819_write(decoder, 0x0d, (decoder->sat >> 7) & 0xff);
389		bt819_setbit(decoder, 0x0b, 1, ((decoder->sat >> 15) & 0x01));
390
391		/* Ratio between U gain and V gain must stay the same as
392		   the ratio between the default U and V gain values. */
393		temp = (decoder->sat * 180) / 254;
394		bt819_write(decoder, 0x0e, (temp >> 7) & 0xff);
395		bt819_setbit(decoder, 0x0b, 0, (temp >> 15) & 0x01);
396		break;
397
398	case V4L2_CID_HUE:
399		if (decoder->hue == ctrl->value)
400			break;
401		decoder->hue = ctrl->value;
402		bt819_write(decoder, 0x0f, decoder->hue);
403		break;
404
405	default:
406		return -EINVAL;
407	}
408	return 0;
409}
410
411static int bt819_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
412{
413	struct bt819 *decoder = to_bt819(sd);
414
415	switch (ctrl->id) {
416	case V4L2_CID_BRIGHTNESS:
417		ctrl->value = decoder->bright;
418		break;
419	case V4L2_CID_CONTRAST:
420		ctrl->value = decoder->contrast;
421		break;
422	case V4L2_CID_SATURATION:
423		ctrl->value = decoder->sat;
424		break;
425	case V4L2_CID_HUE:
426		ctrl->value = decoder->hue;
427		break;
428	default:
429		return -EINVAL;
430	}
431	return 0;
432}
433
434static int bt819_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
435{
436	struct bt819 *decoder = to_bt819(sd);
437	struct i2c_client *client = v4l2_get_subdevdata(sd);
438
439	return v4l2_chip_ident_i2c_client(client, chip, decoder->ident, 0);
440}
441
442/* ----------------------------------------------------------------------- */
443
444static const struct v4l2_subdev_core_ops bt819_core_ops = {
445	.g_chip_ident = bt819_g_chip_ident,
446	.g_ctrl = bt819_g_ctrl,
447	.s_ctrl = bt819_s_ctrl,
448	.queryctrl = bt819_queryctrl,
449	.s_std = bt819_s_std,
450};
451
452static const struct v4l2_subdev_video_ops bt819_video_ops = {
453	.s_routing = bt819_s_routing,
454	.s_stream = bt819_s_stream,
455	.querystd = bt819_querystd,
456	.g_input_status = bt819_g_input_status,
457};
458
459static const struct v4l2_subdev_ops bt819_ops = {
460	.core = &bt819_core_ops,
461	.video = &bt819_video_ops,
462};
463
464/* ----------------------------------------------------------------------- */
465
466static int bt819_probe(struct i2c_client *client,
467			const struct i2c_device_id *id)
468{
469	int i, ver;
470	struct bt819 *decoder;
471	struct v4l2_subdev *sd;
472	const char *name;
473
474	/* Check if the adapter supports the needed features */
475	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
476		return -ENODEV;
477
478	decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL);
479	if (decoder == NULL)
480		return -ENOMEM;
481	sd = &decoder->sd;
482	v4l2_i2c_subdev_init(sd, client, &bt819_ops);
483
484	ver = bt819_read(decoder, 0x17);
485	switch (ver & 0xf0) {
486	case 0x70:
487		name = "bt819a";
488		decoder->ident = V4L2_IDENT_BT819A;
489		break;
490	case 0x60:
491		name = "bt817a";
492		decoder->ident = V4L2_IDENT_BT817A;
493		break;
494	case 0x20:
495		name = "bt815a";
496		decoder->ident = V4L2_IDENT_BT815A;
497		break;
498	default:
499		v4l2_dbg(1, debug, sd,
500			"unknown chip version 0x%02x\n", ver);
501		return -ENODEV;
502	}
503
504	v4l_info(client, "%s found @ 0x%x (%s)\n", name,
505			client->addr << 1, client->adapter->name);
506
507	decoder->norm = V4L2_STD_NTSC;
508	decoder->input = 0;
509	decoder->enable = 1;
510	decoder->bright = 0;
511	decoder->contrast = 0xd8;	/* 100% of original signal */
512	decoder->hue = 0;
513	decoder->sat = 0xfe;		/* 100% of original signal */
514
515	i = bt819_init(sd);
516	if (i < 0)
517		v4l2_dbg(1, debug, sd, "init status %d\n", i);
518	return 0;
519}
520
521static int bt819_remove(struct i2c_client *client)
522{
523	struct v4l2_subdev *sd = i2c_get_clientdata(client);
524
525	v4l2_device_unregister_subdev(sd);
526	kfree(to_bt819(sd));
527	return 0;
528}
529
530/* ----------------------------------------------------------------------- */
531
532static const struct i2c_device_id bt819_id[] = {
533	{ "bt819a", 0 },
534	{ "bt817a", 0 },
535	{ "bt815a", 0 },
536	{ }
537};
538MODULE_DEVICE_TABLE(i2c, bt819_id);
539
540static struct v4l2_i2c_driver_data v4l2_i2c_data = {
541	.name = "bt819",
542	.probe = bt819_probe,
543	.remove = bt819_remove,
544	.id_table = bt819_id,
545};
546