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