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