xref: /openbmc/linux/drivers/media/i2c/bt819.c (revision aaeb31c0)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  bt819 - BT819A VideoStream Decoder (Rockwell Part)
4  *
5  * Copyright (C) 1999 Mike Bernson <mike@mlb.org>
6  * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
7  *
8  * Modifications for LML33/DC10plus unified driver
9  * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
10  *
11  * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
12  *    - moved over to linux>=2.4.x i2c protocol (9/9/2002)
13  *
14  * This code was modify/ported from the saa7111 driver written
15  * by Dave Perks.
16  */
17 
18 #include <linux/module.h>
19 #include <linux/types.h>
20 #include <linux/ioctl.h>
21 #include <linux/delay.h>
22 #include <linux/i2c.h>
23 #include <linux/videodev2.h>
24 #include <linux/slab.h>
25 #include <media/v4l2-device.h>
26 #include <media/v4l2-ctrls.h>
27 #include <media/i2c/bt819.h>
28 
29 MODULE_DESCRIPTION("Brooktree-819 video decoder driver");
30 MODULE_AUTHOR("Mike Bernson & Dave Perks");
31 MODULE_LICENSE("GPL");
32 
33 static int debug;
34 module_param(debug, int, 0);
35 MODULE_PARM_DESC(debug, "Debug level (0-1)");
36 
37 
38 /* ----------------------------------------------------------------------- */
39 
40 struct bt819 {
41 	struct v4l2_subdev sd;
42 	struct v4l2_ctrl_handler hdl;
43 	unsigned char reg[32];
44 
45 	v4l2_std_id norm;
46 	int input;
47 	int enable;
48 };
49 
to_bt819(struct v4l2_subdev * sd)50 static inline struct bt819 *to_bt819(struct v4l2_subdev *sd)
51 {
52 	return container_of(sd, struct bt819, sd);
53 }
54 
to_sd(struct v4l2_ctrl * ctrl)55 static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
56 {
57 	return &container_of(ctrl->handler, struct bt819, hdl)->sd;
58 }
59 
60 struct timing {
61 	int hactive;
62 	int hdelay;
63 	int vactive;
64 	int vdelay;
65 	int hscale;
66 	int vscale;
67 };
68 
69 /* for values, see the bt819 datasheet */
70 static struct timing timing_data[] = {
71 	{864 - 24, 20, 625 - 2, 1, 0x0504, 0x0000},
72 	{858 - 24, 20, 525 - 2, 1, 0x00f8, 0x0000},
73 };
74 
75 /* ----------------------------------------------------------------------- */
76 
bt819_write(struct bt819 * decoder,u8 reg,u8 value)77 static inline int bt819_write(struct bt819 *decoder, u8 reg, u8 value)
78 {
79 	struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd);
80 
81 	decoder->reg[reg] = value;
82 	return i2c_smbus_write_byte_data(client, reg, value);
83 }
84 
bt819_setbit(struct bt819 * decoder,u8 reg,u8 bit,u8 value)85 static inline int bt819_setbit(struct bt819 *decoder, u8 reg, u8 bit, u8 value)
86 {
87 	return bt819_write(decoder, reg,
88 		(decoder->reg[reg] & ~(1 << bit)) | (value ? (1 << bit) : 0));
89 }
90 
bt819_write_block(struct bt819 * decoder,const u8 * data,unsigned int len)91 static int bt819_write_block(struct bt819 *decoder, const u8 *data, unsigned int len)
92 {
93 	struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd);
94 	int ret = -1;
95 	u8 reg;
96 
97 	/* the bt819 has an autoincrement function, use it if
98 	 * the adapter understands raw I2C */
99 	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
100 		/* do raw I2C, not smbus compatible */
101 		u8 block_data[32];
102 		int block_len;
103 
104 		while (len >= 2) {
105 			block_len = 0;
106 			block_data[block_len++] = reg = data[0];
107 			do {
108 				block_data[block_len++] =
109 				    decoder->reg[reg++] = data[1];
110 				len -= 2;
111 				data += 2;
112 			} while (len >= 2 && data[0] == reg && block_len < 32);
113 			ret = i2c_master_send(client, block_data, block_len);
114 			if (ret < 0)
115 				break;
116 		}
117 	} else {
118 		/* do some slow I2C emulation kind of thing */
119 		while (len >= 2) {
120 			reg = *data++;
121 			ret = bt819_write(decoder, reg, *data++);
122 			if (ret < 0)
123 				break;
124 			len -= 2;
125 		}
126 	}
127 
128 	return ret;
129 }
130 
bt819_read(struct bt819 * decoder,u8 reg)131 static inline int bt819_read(struct bt819 *decoder, u8 reg)
132 {
133 	struct i2c_client *client = v4l2_get_subdevdata(&decoder->sd);
134 
135 	return i2c_smbus_read_byte_data(client, reg);
136 }
137 
bt819_init(struct v4l2_subdev * sd)138 static int bt819_init(struct v4l2_subdev *sd)
139 {
140 	static unsigned char init[] = {
141 		/*0x1f, 0x00,*/     /* Reset */
142 		0x01, 0x59,	/* 0x01 input format */
143 		0x02, 0x00,	/* 0x02 temporal decimation */
144 		0x03, 0x12,	/* 0x03 Cropping msb */
145 		0x04, 0x16,	/* 0x04 Vertical Delay, lsb */
146 		0x05, 0xe0,	/* 0x05 Vertical Active lsb */
147 		0x06, 0x80,	/* 0x06 Horizontal Delay lsb */
148 		0x07, 0xd0,	/* 0x07 Horizontal Active lsb */
149 		0x08, 0x00,	/* 0x08 Horizontal Scaling msb */
150 		0x09, 0xf8,	/* 0x09 Horizontal Scaling lsb */
151 		0x0a, 0x00,	/* 0x0a Brightness control */
152 		0x0b, 0x30,	/* 0x0b Miscellaneous control */
153 		0x0c, 0xd8,	/* 0x0c Luma Gain lsb */
154 		0x0d, 0xfe,	/* 0x0d Chroma Gain (U) lsb */
155 		0x0e, 0xb4,	/* 0x0e Chroma Gain (V) msb */
156 		0x0f, 0x00,	/* 0x0f Hue control */
157 		0x12, 0x04,	/* 0x12 Output Format */
158 		0x13, 0x20,	/* 0x13 Vertical Scaling msb 0x00
159 					   chroma comb OFF, line drop scaling, interlace scaling
160 					   BUG? Why does turning the chroma comb on screw up color?
161 					   Bug in the bt819 stepping on my board?
162 					*/
163 		0x14, 0x00,	/* 0x14 Vertical Scaling lsb */
164 		0x16, 0x07,	/* 0x16 Video Timing Polarity
165 					   ACTIVE=active low
166 					   FIELD: high=odd,
167 					   vreset=active high,
168 					   hreset=active high */
169 		0x18, 0x68,	/* 0x18 AGC Delay */
170 		0x19, 0x5d,	/* 0x19 Burst Gate Delay */
171 		0x1a, 0x80,	/* 0x1a ADC Interface */
172 	};
173 
174 	struct bt819 *decoder = to_bt819(sd);
175 	struct timing *timing = &timing_data[(decoder->norm & V4L2_STD_525_60) ? 1 : 0];
176 
177 	init[0x03 * 2 - 1] =
178 	    (((timing->vdelay >> 8) & 0x03) << 6) |
179 	    (((timing->vactive >> 8) & 0x03) << 4) |
180 	    (((timing->hdelay >> 8) & 0x03) << 2) |
181 	    ((timing->hactive >> 8) & 0x03);
182 	init[0x04 * 2 - 1] = timing->vdelay & 0xff;
183 	init[0x05 * 2 - 1] = timing->vactive & 0xff;
184 	init[0x06 * 2 - 1] = timing->hdelay & 0xff;
185 	init[0x07 * 2 - 1] = timing->hactive & 0xff;
186 	init[0x08 * 2 - 1] = timing->hscale >> 8;
187 	init[0x09 * 2 - 1] = timing->hscale & 0xff;
188 	/* 0x15 in array is address 0x19 */
189 	init[0x15 * 2 - 1] = (decoder->norm & V4L2_STD_625_50) ? 115 : 93;	/* Chroma burst delay */
190 	/* reset */
191 	bt819_write(decoder, 0x1f, 0x00);
192 	mdelay(1);
193 
194 	/* init */
195 	return bt819_write_block(decoder, init, sizeof(init));
196 }
197 
198 /* ----------------------------------------------------------------------- */
199 
bt819_status(struct v4l2_subdev * sd,u32 * pstatus,v4l2_std_id * pstd)200 static int bt819_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd)
201 {
202 	struct bt819 *decoder = to_bt819(sd);
203 	int status = bt819_read(decoder, 0x00);
204 	int res = V4L2_IN_ST_NO_SIGNAL;
205 	v4l2_std_id std = pstd ? *pstd : V4L2_STD_ALL;
206 
207 	if ((status & 0x80))
208 		res = 0;
209 	else
210 		std = V4L2_STD_UNKNOWN;
211 
212 	if ((status & 0x10))
213 		std &= V4L2_STD_PAL;
214 	else
215 		std &= V4L2_STD_NTSC;
216 	if (pstd)
217 		*pstd = std;
218 	if (pstatus)
219 		*pstatus = res;
220 
221 	v4l2_dbg(1, debug, sd, "get status %x\n", status);
222 	return 0;
223 }
224 
bt819_querystd(struct v4l2_subdev * sd,v4l2_std_id * std)225 static int bt819_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
226 {
227 	return bt819_status(sd, NULL, std);
228 }
229 
bt819_g_input_status(struct v4l2_subdev * sd,u32 * status)230 static int bt819_g_input_status(struct v4l2_subdev *sd, u32 *status)
231 {
232 	return bt819_status(sd, status, NULL);
233 }
234 
bt819_s_std(struct v4l2_subdev * sd,v4l2_std_id std)235 static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
236 {
237 	struct bt819 *decoder = to_bt819(sd);
238 	struct timing *timing = NULL;
239 
240 	v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std);
241 
242 	if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL)
243 		v4l2_err(sd, "no notify found!\n");
244 
245 	if (std & V4L2_STD_NTSC) {
246 		v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL);
247 		bt819_setbit(decoder, 0x01, 0, 1);
248 		bt819_setbit(decoder, 0x01, 1, 0);
249 		bt819_setbit(decoder, 0x01, 5, 0);
250 		bt819_write(decoder, 0x18, 0x68);
251 		bt819_write(decoder, 0x19, 0x5d);
252 		/* bt819_setbit(decoder, 0x1a,  5, 1); */
253 		timing = &timing_data[1];
254 	} else if (std & V4L2_STD_PAL) {
255 		v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL);
256 		bt819_setbit(decoder, 0x01, 0, 1);
257 		bt819_setbit(decoder, 0x01, 1, 1);
258 		bt819_setbit(decoder, 0x01, 5, 1);
259 		bt819_write(decoder, 0x18, 0x7f);
260 		bt819_write(decoder, 0x19, 0x72);
261 		/* bt819_setbit(decoder, 0x1a,  5, 0); */
262 		timing = &timing_data[0];
263 	} else {
264 		v4l2_dbg(1, debug, sd, "unsupported norm %llx\n",
265 				(unsigned long long)std);
266 		return -EINVAL;
267 	}
268 	bt819_write(decoder, 0x03,
269 			(((timing->vdelay >> 8) & 0x03) << 6) |
270 			(((timing->vactive >> 8) & 0x03) << 4) |
271 			(((timing->hdelay >> 8) & 0x03) << 2) |
272 			((timing->hactive >> 8) & 0x03));
273 	bt819_write(decoder, 0x04, timing->vdelay & 0xff);
274 	bt819_write(decoder, 0x05, timing->vactive & 0xff);
275 	bt819_write(decoder, 0x06, timing->hdelay & 0xff);
276 	bt819_write(decoder, 0x07, timing->hactive & 0xff);
277 	bt819_write(decoder, 0x08, (timing->hscale >> 8) & 0xff);
278 	bt819_write(decoder, 0x09, timing->hscale & 0xff);
279 	decoder->norm = std;
280 	v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, NULL);
281 	return 0;
282 }
283 
bt819_s_routing(struct v4l2_subdev * sd,u32 input,u32 output,u32 config)284 static int bt819_s_routing(struct v4l2_subdev *sd,
285 			   u32 input, u32 output, u32 config)
286 {
287 	struct bt819 *decoder = to_bt819(sd);
288 
289 	v4l2_dbg(1, debug, sd, "set input %x\n", input);
290 
291 	if (input > 7)
292 		return -EINVAL;
293 
294 	if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL)
295 		v4l2_err(sd, "no notify found!\n");
296 
297 	if (decoder->input != input) {
298 		v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL);
299 		decoder->input = input;
300 		/* select mode */
301 		if (decoder->input == 0) {
302 			bt819_setbit(decoder, 0x0b, 6, 0);
303 			bt819_setbit(decoder, 0x1a, 1, 1);
304 		} else {
305 			bt819_setbit(decoder, 0x0b, 6, 1);
306 			bt819_setbit(decoder, 0x1a, 1, 0);
307 		}
308 		v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, NULL);
309 	}
310 	return 0;
311 }
312 
bt819_s_stream(struct v4l2_subdev * sd,int enable)313 static int bt819_s_stream(struct v4l2_subdev *sd, int enable)
314 {
315 	struct bt819 *decoder = to_bt819(sd);
316 
317 	v4l2_dbg(1, debug, sd, "enable output %x\n", enable);
318 
319 	if (decoder->enable != enable) {
320 		decoder->enable = enable;
321 		bt819_setbit(decoder, 0x16, 7, !enable);
322 	}
323 	return 0;
324 }
325 
bt819_s_ctrl(struct v4l2_ctrl * ctrl)326 static int bt819_s_ctrl(struct v4l2_ctrl *ctrl)
327 {
328 	struct v4l2_subdev *sd = to_sd(ctrl);
329 	struct bt819 *decoder = to_bt819(sd);
330 	int temp;
331 
332 	switch (ctrl->id) {
333 	case V4L2_CID_BRIGHTNESS:
334 		bt819_write(decoder, 0x0a, ctrl->val);
335 		break;
336 
337 	case V4L2_CID_CONTRAST:
338 		bt819_write(decoder, 0x0c, ctrl->val & 0xff);
339 		bt819_setbit(decoder, 0x0b, 2, ((ctrl->val >> 8) & 0x01));
340 		break;
341 
342 	case V4L2_CID_SATURATION:
343 		bt819_write(decoder, 0x0d, (ctrl->val >> 7) & 0xff);
344 		bt819_setbit(decoder, 0x0b, 1, ((ctrl->val >> 15) & 0x01));
345 
346 		/* Ratio between U gain and V gain must stay the same as
347 		   the ratio between the default U and V gain values. */
348 		temp = (ctrl->val * 180) / 254;
349 		bt819_write(decoder, 0x0e, (temp >> 7) & 0xff);
350 		bt819_setbit(decoder, 0x0b, 0, (temp >> 15) & 0x01);
351 		break;
352 
353 	case V4L2_CID_HUE:
354 		bt819_write(decoder, 0x0f, ctrl->val);
355 		break;
356 
357 	default:
358 		return -EINVAL;
359 	}
360 	return 0;
361 }
362 
363 /* ----------------------------------------------------------------------- */
364 
365 static const struct v4l2_ctrl_ops bt819_ctrl_ops = {
366 	.s_ctrl = bt819_s_ctrl,
367 };
368 
369 static const struct v4l2_subdev_video_ops bt819_video_ops = {
370 	.s_std = bt819_s_std,
371 	.s_routing = bt819_s_routing,
372 	.s_stream = bt819_s_stream,
373 	.querystd = bt819_querystd,
374 	.g_input_status = bt819_g_input_status,
375 };
376 
377 static const struct v4l2_subdev_ops bt819_ops = {
378 	.video = &bt819_video_ops,
379 };
380 
381 /* ----------------------------------------------------------------------- */
382 
bt819_probe(struct i2c_client * client)383 static int bt819_probe(struct i2c_client *client)
384 {
385 	int i, ver;
386 	struct bt819 *decoder;
387 	struct v4l2_subdev *sd;
388 	const char *name;
389 
390 	/* Check if the adapter supports the needed features */
391 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
392 		return -ENODEV;
393 
394 	decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);
395 	if (decoder == NULL)
396 		return -ENOMEM;
397 	sd = &decoder->sd;
398 	v4l2_i2c_subdev_init(sd, client, &bt819_ops);
399 
400 	ver = bt819_read(decoder, 0x17);
401 	switch (ver & 0xf0) {
402 	case 0x70:
403 		name = "bt819a";
404 		break;
405 	case 0x60:
406 		name = "bt817a";
407 		break;
408 	case 0x20:
409 		name = "bt815a";
410 		break;
411 	default:
412 		v4l2_dbg(1, debug, sd,
413 			"unknown chip version 0x%02x\n", ver);
414 		return -ENODEV;
415 	}
416 
417 	v4l_info(client, "%s found @ 0x%x (%s)\n", name,
418 			client->addr << 1, client->adapter->name);
419 
420 	decoder->norm = V4L2_STD_NTSC;
421 	decoder->input = 0;
422 	decoder->enable = 1;
423 
424 	i = bt819_init(sd);
425 	if (i < 0)
426 		v4l2_dbg(1, debug, sd, "init status %d\n", i);
427 
428 	v4l2_ctrl_handler_init(&decoder->hdl, 4);
429 	v4l2_ctrl_new_std(&decoder->hdl, &bt819_ctrl_ops,
430 			V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
431 	v4l2_ctrl_new_std(&decoder->hdl, &bt819_ctrl_ops,
432 			V4L2_CID_CONTRAST, 0, 511, 1, 0xd8);
433 	v4l2_ctrl_new_std(&decoder->hdl, &bt819_ctrl_ops,
434 			V4L2_CID_SATURATION, 0, 511, 1, 0xfe);
435 	v4l2_ctrl_new_std(&decoder->hdl, &bt819_ctrl_ops,
436 			V4L2_CID_HUE, -128, 127, 1, 0);
437 	sd->ctrl_handler = &decoder->hdl;
438 	if (decoder->hdl.error) {
439 		int err = decoder->hdl.error;
440 
441 		v4l2_ctrl_handler_free(&decoder->hdl);
442 		return err;
443 	}
444 	v4l2_ctrl_handler_setup(&decoder->hdl);
445 	return 0;
446 }
447 
bt819_remove(struct i2c_client * client)448 static void bt819_remove(struct i2c_client *client)
449 {
450 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
451 	struct bt819 *decoder = to_bt819(sd);
452 
453 	v4l2_device_unregister_subdev(sd);
454 	v4l2_ctrl_handler_free(&decoder->hdl);
455 }
456 
457 /* ----------------------------------------------------------------------- */
458 
459 static const struct i2c_device_id bt819_id[] = {
460 	{ "bt819a", 0 },
461 	{ "bt817a", 0 },
462 	{ "bt815a", 0 },
463 	{ }
464 };
465 MODULE_DEVICE_TABLE(i2c, bt819_id);
466 
467 static struct i2c_driver bt819_driver = {
468 	.driver = {
469 		.name	= "bt819",
470 	},
471 	.probe		= bt819_probe,
472 	.remove		= bt819_remove,
473 	.id_table	= bt819_id,
474 };
475 
476 module_i2c_driver(bt819_driver);
477