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