bt819.c 13.2 KB
Newer Older
1
/*
L
Linus Torvalds 已提交
2 3 4 5 6 7 8
 *  bt819 - BT819A VideoStream Decoder (Rockwell Part)
 *
 * Copyright (C) 1999 Mike Bernson <mike@mlb.org>
 * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
 *
 * Modifications for LML33/DC10plus unified driver
 * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
9
 *
L
Linus Torvalds 已提交
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
 * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
 *    - moved over to linux>=2.4.x i2c protocol (9/9/2002)
 *
 * This code was modify/ported from the saa7111 driver written
 * by Dave Perks.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#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/videodev2.h>
37
#include <linux/slab.h>
38
#include <media/v4l2-device.h>
39
#include <media/v4l2-ctrls.h>
40
#include <media/bt819.h>
L
Linus Torvalds 已提交
41 42 43 44 45

MODULE_DESCRIPTION("Brooktree-819 video decoder driver");
MODULE_AUTHOR("Mike Bernson & Dave Perks");
MODULE_LICENSE("GPL");

46
static int debug;
L
Linus Torvalds 已提交
47 48 49
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0-1)");

50

L
Linus Torvalds 已提交
51 52 53
/* ----------------------------------------------------------------------- */

struct bt819 {
54
	struct v4l2_subdev sd;
55
	struct v4l2_ctrl_handler hdl;
L
Linus Torvalds 已提交
56 57
	unsigned char reg[32];

58
	v4l2_std_id norm;
L
Linus Torvalds 已提交
59 60 61 62
	int input;
	int enable;
};

63 64 65 66 67
static inline struct bt819 *to_bt819(struct v4l2_subdev *sd)
{
	return container_of(sd, struct bt819, sd);
}

68 69 70 71 72
static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
{
	return &container_of(ctrl->handler, struct bt819, hdl)->sd;
}

L
Linus Torvalds 已提交
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
struct timing {
	int hactive;
	int hdelay;
	int vactive;
	int vdelay;
	int hscale;
	int vscale;
};

/* for values, see the bt819 datasheet */
static struct timing timing_data[] = {
	{864 - 24, 20, 625 - 2, 1, 0x0504, 0x0000},
	{858 - 24, 20, 525 - 2, 1, 0x00f8, 0x0000},
};

/* ----------------------------------------------------------------------- */

90
static inline int bt819_write(struct bt819 *decoder, u8 reg, u8 value)
L
Linus Torvalds 已提交
91
{
92
	struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd);
L
Linus Torvalds 已提交
93 94 95 96 97

	decoder->reg[reg] = value;
	return i2c_smbus_write_byte_data(client, reg, value);
}

98
static inline int bt819_setbit(struct bt819 *decoder, u8 reg, u8 bit, u8 value)
L
Linus Torvalds 已提交
99
{
100
	return bt819_write(decoder, reg,
101
		(decoder->reg[reg] & ~(1 << bit)) | (value ? (1 << bit) : 0));
L
Linus Torvalds 已提交
102 103
}

104
static int bt819_write_block(struct bt819 *decoder, const u8 *data, unsigned int len)
L
Linus Torvalds 已提交
105
{
106
	struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd);
L
Linus Torvalds 已提交
107 108 109 110 111 112 113 114
	int ret = -1;
	u8 reg;

	/* the bt819 has an autoincrement function, use it if
	 * the adapter understands raw I2C */
	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		/* do raw I2C, not smbus compatible */
		u8 block_data[32];
115
		int block_len;
L
Linus Torvalds 已提交
116 117

		while (len >= 2) {
118 119
			block_len = 0;
			block_data[block_len++] = reg = data[0];
L
Linus Torvalds 已提交
120
			do {
121
				block_data[block_len++] =
L
Linus Torvalds 已提交
122 123 124
				    decoder->reg[reg++] = data[1];
				len -= 2;
				data += 2;
125 126 127
			} while (len >= 2 && data[0] == reg && block_len < 32);
			ret = i2c_master_send(client, block_data, block_len);
			if (ret < 0)
L
Linus Torvalds 已提交
128 129 130 131 132 133
				break;
		}
	} else {
		/* do some slow I2C emulation kind of thing */
		while (len >= 2) {
			reg = *data++;
134 135
			ret = bt819_write(decoder, reg, *data++);
			if (ret < 0)
L
Linus Torvalds 已提交
136 137 138 139 140 141 142 143
				break;
			len -= 2;
		}
	}

	return ret;
}

144
static inline int bt819_read(struct bt819 *decoder, u8 reg)
L
Linus Torvalds 已提交
145
{
146 147
	struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd);

L
Linus Torvalds 已提交
148 149 150
	return i2c_smbus_read_byte_data(client, reg);
}

151
static int bt819_init(struct v4l2_subdev *sd)
L
Linus Torvalds 已提交
152 153
{
	static unsigned char init[] = {
154
		/*0x1f, 0x00,*/     /* Reset */
L
Linus Torvalds 已提交
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
		0x01, 0x59,	/* 0x01 input format */
		0x02, 0x00,	/* 0x02 temporal decimation */
		0x03, 0x12,	/* 0x03 Cropping msb */
		0x04, 0x16,	/* 0x04 Vertical Delay, lsb */
		0x05, 0xe0,	/* 0x05 Vertical Active lsb */
		0x06, 0x80,	/* 0x06 Horizontal Delay lsb */
		0x07, 0xd0,	/* 0x07 Horizontal Active lsb */
		0x08, 0x00,	/* 0x08 Horizontal Scaling msb */
		0x09, 0xf8,	/* 0x09 Horizontal Scaling lsb */
		0x0a, 0x00,	/* 0x0a Brightness control */
		0x0b, 0x30,	/* 0x0b Miscellaneous control */
		0x0c, 0xd8,	/* 0x0c Luma Gain lsb */
		0x0d, 0xfe,	/* 0x0d Chroma Gain (U) lsb */
		0x0e, 0xb4,	/* 0x0e Chroma Gain (V) msb */
		0x0f, 0x00,	/* 0x0f Hue control */
		0x12, 0x04,	/* 0x12 Output Format */
		0x13, 0x20,	/* 0x13 Vertial Scaling msb 0x00
					   chroma comb OFF, line drop scaling, interlace scaling
					   BUG? Why does turning the chroma comb on fuck up color?
					   Bug in the bt819 stepping on my board?
					*/
		0x14, 0x00,	/* 0x14 Vertial Scaling lsb */
177
		0x16, 0x07,	/* 0x16 Video Timing Polarity
L
Linus Torvalds 已提交
178
					   ACTIVE=active low
179
					   FIELD: high=odd,
L
Linus Torvalds 已提交
180 181 182 183 184 185 186
					   vreset=active high,
					   hreset=active high */
		0x18, 0x68,	/* 0x18 AGC Delay */
		0x19, 0x5d,	/* 0x19 Burst Gate Delay */
		0x1a, 0x80,	/* 0x1a ADC Interface */
	};

187
	struct bt819 *decoder = to_bt819(sd);
188
	struct timing *timing = &timing_data[(decoder->norm & V4L2_STD_525_60) ? 1 : 0];
L
Linus Torvalds 已提交
189 190

	init[0x03 * 2 - 1] =
191 192 193 194
	    (((timing->vdelay >> 8) & 0x03) << 6) |
	    (((timing->vactive >> 8) & 0x03) << 4) |
	    (((timing->hdelay >> 8) & 0x03) << 2) |
	    ((timing->hactive >> 8) & 0x03);
L
Linus Torvalds 已提交
195 196 197 198 199 200 201
	init[0x04 * 2 - 1] = timing->vdelay & 0xff;
	init[0x05 * 2 - 1] = timing->vactive & 0xff;
	init[0x06 * 2 - 1] = timing->hdelay & 0xff;
	init[0x07 * 2 - 1] = timing->hactive & 0xff;
	init[0x08 * 2 - 1] = timing->hscale >> 8;
	init[0x09 * 2 - 1] = timing->hscale & 0xff;
	/* 0x15 in array is address 0x19 */
202
	init[0x15 * 2 - 1] = (decoder->norm & V4L2_STD_625_50) ? 115 : 93;	/* Chroma burst delay */
L
Linus Torvalds 已提交
203
	/* reset */
204
	bt819_write(decoder, 0x1f, 0x00);
L
Linus Torvalds 已提交
205 206 207
	mdelay(1);

	/* init */
208
	return bt819_write_block(decoder, init, sizeof(init));
L
Linus Torvalds 已提交
209 210 211 212
}

/* ----------------------------------------------------------------------- */

213
static int bt819_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd)
L
Linus Torvalds 已提交
214
{
215 216 217
	struct bt819 *decoder = to_bt819(sd);
	int status = bt819_read(decoder, 0x00);
	int res = V4L2_IN_ST_NO_SIGNAL;
H
Hans Verkuil 已提交
218
	v4l2_std_id std = pstd ? *pstd : V4L2_STD_ALL;
219 220 221

	if ((status & 0x80))
		res = 0;
H
Hans Verkuil 已提交
222 223
	else
		std = V4L2_STD_UNKNOWN;
224 225

	if ((status & 0x10))
H
Hans Verkuil 已提交
226
		std &= V4L2_STD_PAL;
227
	else
H
Hans Verkuil 已提交
228
		std &= V4L2_STD_NTSC;
229 230 231
	if (pstd)
		*pstd = std;
	if (pstatus)
232
		*pstatus = res;
233 234 235 236

	v4l2_dbg(1, debug, sd, "get status %x\n", status);
	return 0;
}
L
Linus Torvalds 已提交
237

238 239 240 241
static int bt819_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
{
	return bt819_status(sd, NULL, std);
}
L
Linus Torvalds 已提交
242

243 244 245 246 247 248 249 250 251 252
static int bt819_g_input_status(struct v4l2_subdev *sd, u32 *status)
{
	return bt819_status(sd, status, NULL);
}

static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
{
	struct bt819 *decoder = to_bt819(sd);
	struct timing *timing = NULL;

253
	v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std);
254

255 256 257
	if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL)
		v4l2_err(sd, "no notify found!\n");

258
	if (std & V4L2_STD_NTSC) {
259
		v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL);
260 261 262 263 264 265 266 267
		bt819_setbit(decoder, 0x01, 0, 1);
		bt819_setbit(decoder, 0x01, 1, 0);
		bt819_setbit(decoder, 0x01, 5, 0);
		bt819_write(decoder, 0x18, 0x68);
		bt819_write(decoder, 0x19, 0x5d);
		/* bt819_setbit(decoder, 0x1a,  5, 1); */
		timing = &timing_data[1];
	} else if (std & V4L2_STD_PAL) {
268
		v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL);
269 270 271 272 273 274 275 276
		bt819_setbit(decoder, 0x01, 0, 1);
		bt819_setbit(decoder, 0x01, 1, 1);
		bt819_setbit(decoder, 0x01, 5, 1);
		bt819_write(decoder, 0x18, 0x7f);
		bt819_write(decoder, 0x19, 0x72);
		/* bt819_setbit(decoder, 0x1a,  5, 0); */
		timing = &timing_data[0];
	} else {
277 278
		v4l2_dbg(1, debug, sd, "unsupported norm %llx\n",
				(unsigned long long)std);
279
		return -EINVAL;
L
Linus Torvalds 已提交
280
	}
281 282 283 284 285 286 287 288 289 290 291 292
	bt819_write(decoder, 0x03,
			(((timing->vdelay >> 8) & 0x03) << 6) |
			(((timing->vactive >> 8) & 0x03) << 4) |
			(((timing->hdelay >> 8) & 0x03) << 2) |
			((timing->hactive >> 8) & 0x03));
	bt819_write(decoder, 0x04, timing->vdelay & 0xff);
	bt819_write(decoder, 0x05, timing->vactive & 0xff);
	bt819_write(decoder, 0x06, timing->hdelay & 0xff);
	bt819_write(decoder, 0x07, timing->hactive & 0xff);
	bt819_write(decoder, 0x08, (timing->hscale >> 8) & 0xff);
	bt819_write(decoder, 0x09, timing->hscale & 0xff);
	decoder->norm = std;
293
	v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, NULL);
294 295
	return 0;
}
L
Linus Torvalds 已提交
296

297 298
static int bt819_s_routing(struct v4l2_subdev *sd,
			   u32 input, u32 output, u32 config)
299 300
{
	struct bt819 *decoder = to_bt819(sd);
L
Linus Torvalds 已提交
301

302
	v4l2_dbg(1, debug, sd, "set input %x\n", input);
L
Linus Torvalds 已提交
303

304
	if (input > 7)
305
		return -EINVAL;
L
Linus Torvalds 已提交
306

307 308 309
	if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL)
		v4l2_err(sd, "no notify found!\n");

310
	if (decoder->input != input) {
311
		v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL);
312
		decoder->input = input;
313 314 315 316 317 318 319
		/* select mode */
		if (decoder->input == 0) {
			bt819_setbit(decoder, 0x0b, 6, 0);
			bt819_setbit(decoder, 0x1a, 1, 1);
		} else {
			bt819_setbit(decoder, 0x0b, 6, 1);
			bt819_setbit(decoder, 0x1a, 1, 0);
L
Linus Torvalds 已提交
320
		}
321
		v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, NULL);
322
	}
323 324
	return 0;
}
L
Linus Torvalds 已提交
325

326 327 328
static int bt819_s_stream(struct v4l2_subdev *sd, int enable)
{
	struct bt819 *decoder = to_bt819(sd);
L
Linus Torvalds 已提交
329

330
	v4l2_dbg(1, debug, sd, "enable output %x\n", enable);
L
Linus Torvalds 已提交
331

332 333 334
	if (decoder->enable != enable) {
		decoder->enable = enable;
		bt819_setbit(decoder, 0x16, 7, !enable);
335
	}
336 337
	return 0;
}
L
Linus Torvalds 已提交
338

339
static int bt819_s_ctrl(struct v4l2_ctrl *ctrl)
340
{
341
	struct v4l2_subdev *sd = to_sd(ctrl);
342 343
	struct bt819 *decoder = to_bt819(sd);
	int temp;
L
Linus Torvalds 已提交
344

345 346
	switch (ctrl->id) {
	case V4L2_CID_BRIGHTNESS:
347
		bt819_write(decoder, 0x0a, ctrl->val);
348
		break;
L
Linus Torvalds 已提交
349

350
	case V4L2_CID_CONTRAST:
351 352
		bt819_write(decoder, 0x0c, ctrl->val & 0xff);
		bt819_setbit(decoder, 0x0b, 2, ((ctrl->val >> 8) & 0x01));
353
		break;
L
Linus Torvalds 已提交
354

355
	case V4L2_CID_SATURATION:
356 357
		bt819_write(decoder, 0x0d, (ctrl->val >> 7) & 0xff);
		bt819_setbit(decoder, 0x0b, 1, ((ctrl->val >> 15) & 0x01));
358 359 360

		/* Ratio between U gain and V gain must stay the same as
		   the ratio between the default U and V gain values. */
361
		temp = (ctrl->val * 180) / 254;
362 363 364
		bt819_write(decoder, 0x0e, (temp >> 7) & 0xff);
		bt819_setbit(decoder, 0x0b, 0, (temp >> 15) & 0x01);
		break;
L
Linus Torvalds 已提交
365

366
	case V4L2_CID_HUE:
367
		bt819_write(decoder, 0x0f, ctrl->val);
368
		break;
369 370 371

	default:
		return -EINVAL;
372
	}
373 374
	return 0;
}
L
Linus Torvalds 已提交
375 376 377

/* ----------------------------------------------------------------------- */

378 379 380 381
static const struct v4l2_ctrl_ops bt819_ctrl_ops = {
	.s_ctrl = bt819_s_ctrl,
};

382
static const struct v4l2_subdev_video_ops bt819_video_ops = {
383
	.s_std = bt819_s_std,
384 385 386 387 388 389 390 391 392 393 394
	.s_routing = bt819_s_routing,
	.s_stream = bt819_s_stream,
	.querystd = bt819_querystd,
	.g_input_status = bt819_g_input_status,
};

static const struct v4l2_subdev_ops bt819_ops = {
	.video = &bt819_video_ops,
};

/* ----------------------------------------------------------------------- */
L
Linus Torvalds 已提交
395

396 397
static int bt819_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
L
Linus Torvalds 已提交
398
{
399
	int i, ver;
L
Linus Torvalds 已提交
400
	struct bt819 *decoder;
401
	struct v4l2_subdev *sd;
402
	const char *name;
L
Linus Torvalds 已提交
403 404

	/* Check if the adapter supports the needed features */
405 406
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
		return -ENODEV;
L
Linus Torvalds 已提交
407

408
	decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);
409 410 411 412 413 414
	if (decoder == NULL)
		return -ENOMEM;
	sd = &decoder->sd;
	v4l2_i2c_subdev_init(sd, client, &bt819_ops);

	ver = bt819_read(decoder, 0x17);
415 416 417 418 419 420 421 422 423 424 425
	switch (ver & 0xf0) {
	case 0x70:
		name = "bt819a";
		break;
	case 0x60:
		name = "bt817a";
		break;
	case 0x20:
		name = "bt815a";
		break;
	default:
426
		v4l2_dbg(1, debug, sd,
427 428 429 430 431 432
			"unknown chip version 0x%02x\n", ver);
		return -ENODEV;
	}

	v4l_info(client, "%s found @ 0x%x (%s)\n", name,
			client->addr << 1, client->adapter->name);
L
Linus Torvalds 已提交
433

434
	decoder->norm = V4L2_STD_NTSC;
L
Linus Torvalds 已提交
435 436 437
	decoder->input = 0;
	decoder->enable = 1;

438
	i = bt819_init(sd);
439
	if (i < 0)
440
		v4l2_dbg(1, debug, sd, "init status %d\n", i);
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458

	v4l2_ctrl_handler_init(&decoder->hdl, 4);
	v4l2_ctrl_new_std(&decoder->hdl, &bt819_ctrl_ops,
			V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
	v4l2_ctrl_new_std(&decoder->hdl, &bt819_ctrl_ops,
			V4L2_CID_CONTRAST, 0, 511, 1, 0xd8);
	v4l2_ctrl_new_std(&decoder->hdl, &bt819_ctrl_ops,
			V4L2_CID_SATURATION, 0, 511, 1, 0xfe);
	v4l2_ctrl_new_std(&decoder->hdl, &bt819_ctrl_ops,
			V4L2_CID_HUE, -128, 127, 1, 0);
	sd->ctrl_handler = &decoder->hdl;
	if (decoder->hdl.error) {
		int err = decoder->hdl.error;

		v4l2_ctrl_handler_free(&decoder->hdl);
		return err;
	}
	v4l2_ctrl_handler_setup(&decoder->hdl);
L
Linus Torvalds 已提交
459 460 461
	return 0;
}

462
static int bt819_remove(struct i2c_client *client)
L
Linus Torvalds 已提交
463
{
464
	struct v4l2_subdev *sd = i2c_get_clientdata(client);
465
	struct bt819 *decoder = to_bt819(sd);
466 467

	v4l2_device_unregister_subdev(sd);
468
	v4l2_ctrl_handler_free(&decoder->hdl);
L
Linus Torvalds 已提交
469 470 471 472 473
	return 0;
}

/* ----------------------------------------------------------------------- */

474 475 476 477 478 479 480
static const struct i2c_device_id bt819_id[] = {
	{ "bt819a", 0 },
	{ "bt817a", 0 },
	{ "bt815a", 0 },
	{ }
};
MODULE_DEVICE_TABLE(i2c, bt819_id);
L
Linus Torvalds 已提交
481

482 483 484 485 486 487 488
static struct i2c_driver bt819_driver = {
	.driver = {
		.name	= "bt819",
	},
	.probe		= bt819_probe,
	.remove		= bt819_remove,
	.id_table	= bt819_id,
L
Linus Torvalds 已提交
489
};
490

491
module_i2c_driver(bt819_driver);