476a204dcf9051866655a8475ac459cc9137577f
[safe/jmp/linux-2.6] / drivers / media / video / vpx3220.c
1 /*
2  * vpx3220a, vpx3216b & vpx3214c video decoder driver version 0.0.1
3  *
4  * Copyright (C) 2001 Laurent Pinchart <lpinchart@freegates.be>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include <linux/module.h>
22 #include <linux/init.h>
23 #include <linux/delay.h>
24 #include <linux/types.h>
25 #include <asm/uaccess.h>
26 #include <linux/i2c.h>
27 #include <linux/videodev2.h>
28 #include <media/v4l2-device.h>
29 #include <media/v4l2-chip-ident.h>
30 #include <media/v4l2-i2c-drv-legacy.h>
31
32 MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver");
33 MODULE_AUTHOR("Laurent Pinchart");
34 MODULE_LICENSE("GPL");
35
36 static int debug;
37 module_param(debug, int, 0);
38 MODULE_PARM_DESC(debug, "Debug level (0-1)");
39
40 static unsigned short normal_i2c[] = { 0x86 >> 1, 0x8e >> 1, I2C_CLIENT_END };
41
42 I2C_CLIENT_INSMOD;
43
44 #define VPX_TIMEOUT_COUNT  10
45
46 /* ----------------------------------------------------------------------- */
47
48 struct vpx3220 {
49         struct v4l2_subdev sd;
50         unsigned char reg[255];
51
52         v4l2_std_id norm;
53         int ident;
54         int input;
55         int enable;
56         int bright;
57         int contrast;
58         int hue;
59         int sat;
60 };
61
62 static inline struct vpx3220 *to_vpx3220(struct v4l2_subdev *sd)
63 {
64         return container_of(sd, struct vpx3220, sd);
65 }
66
67 static char *inputs[] = { "internal", "composite", "svideo" };
68
69 /* ----------------------------------------------------------------------- */
70
71 static inline int vpx3220_write(struct v4l2_subdev *sd, u8 reg, u8 value)
72 {
73         struct i2c_client *client = v4l2_get_subdevdata(sd);
74         struct vpx3220 *decoder = i2c_get_clientdata(client);
75
76         decoder->reg[reg] = value;
77         return i2c_smbus_write_byte_data(client, reg, value);
78 }
79
80 static inline int vpx3220_read(struct v4l2_subdev *sd, u8 reg)
81 {
82         struct i2c_client *client = v4l2_get_subdevdata(sd);
83
84         return i2c_smbus_read_byte_data(client, reg);
85 }
86
87 static int vpx3220_fp_status(struct v4l2_subdev *sd)
88 {
89         unsigned char status;
90         unsigned int i;
91
92         for (i = 0; i < VPX_TIMEOUT_COUNT; i++) {
93                 status = vpx3220_read(sd, 0x29);
94
95                 if (!(status & 4))
96                         return 0;
97
98                 udelay(10);
99
100                 if (need_resched())
101                         cond_resched();
102         }
103
104         return -1;
105 }
106
107 static int vpx3220_fp_write(struct v4l2_subdev *sd, u8 fpaddr, u16 data)
108 {
109         struct i2c_client *client = v4l2_get_subdevdata(sd);
110
111         /* Write the 16-bit address to the FPWR register */
112         if (i2c_smbus_write_word_data(client, 0x27, swab16(fpaddr)) == -1) {
113                 v4l2_dbg(1, debug, sd, "%s: failed\n", __func__);
114                 return -1;
115         }
116
117         if (vpx3220_fp_status(sd) < 0)
118                 return -1;
119
120         /* Write the 16-bit data to the FPDAT register */
121         if (i2c_smbus_write_word_data(client, 0x28, swab16(data)) == -1) {
122                 v4l2_dbg(1, debug, sd, "%s: failed\n", __func__);
123                 return -1;
124         }
125
126         return 0;
127 }
128
129 static u16 vpx3220_fp_read(struct v4l2_subdev *sd, u16 fpaddr)
130 {
131         struct i2c_client *client = v4l2_get_subdevdata(sd);
132         s16 data;
133
134         /* Write the 16-bit address to the FPRD register */
135         if (i2c_smbus_write_word_data(client, 0x26, swab16(fpaddr)) == -1) {
136                 v4l2_dbg(1, debug, sd, "%s: failed\n", __func__);
137                 return -1;
138         }
139
140         if (vpx3220_fp_status(sd) < 0)
141                 return -1;
142
143         /* Read the 16-bit data from the FPDAT register */
144         data = i2c_smbus_read_word_data(client, 0x28);
145         if (data == -1) {
146                 v4l2_dbg(1, debug, sd, "%s: failed\n", __func__);
147                 return -1;
148         }
149
150         return swab16(data);
151 }
152
153 static int vpx3220_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len)
154 {
155         u8 reg;
156         int ret = -1;
157
158         while (len >= 2) {
159                 reg = *data++;
160                 ret = vpx3220_write(sd, reg, *data++);
161                 if (ret < 0)
162                         break;
163                 len -= 2;
164         }
165
166         return ret;
167 }
168
169 static int vpx3220_write_fp_block(struct v4l2_subdev *sd,
170                 const u16 *data, unsigned int len)
171 {
172         u8 reg;
173         int ret = 0;
174
175         while (len > 1) {
176                 reg = *data++;
177                 ret |= vpx3220_fp_write(sd, reg, *data++);
178                 len -= 2;
179         }
180
181         return ret;
182 }
183
184 /* ---------------------------------------------------------------------- */
185
186 static const unsigned short init_ntsc[] = {
187         0x1c, 0x00,             /* NTSC tint angle */
188         0x88, 17,               /* Window 1 vertical */
189         0x89, 240,              /* Vertical lines in */
190         0x8a, 240,              /* Vertical lines out */
191         0x8b, 000,              /* Horizontal begin */
192         0x8c, 640,              /* Horizontal length */
193         0x8d, 640,              /* Number of pixels */
194         0x8f, 0xc00,            /* Disable window 2 */
195         0xf0, 0x73,             /* 13.5 MHz transport, Forced
196                                  * mode, latch windows */
197         0xf2, 0x13,             /* NTSC M, composite input */
198         0xe7, 0x1e1,            /* Enable vertical standard
199                                  * locking @ 240 lines */
200 };
201
202 static const unsigned short init_pal[] = {
203         0x88, 23,               /* Window 1 vertical begin */
204         0x89, 288,              /* Vertical lines in (16 lines
205                                  * skipped by the VFE) */
206         0x8a, 288,              /* Vertical lines out (16 lines
207                                  * skipped by the VFE) */
208         0x8b, 16,               /* Horizontal begin */
209         0x8c, 768,              /* Horizontal length */
210         0x8d, 784,              /* Number of pixels
211                                  * Must be >= Horizontal begin + Horizontal length */
212         0x8f, 0xc00,            /* Disable window 2 */
213         0xf0, 0x77,             /* 13.5 MHz transport, Forced
214                                  * mode, latch windows */
215         0xf2, 0x3d1,            /* PAL B,G,H,I, composite input */
216         0xe7, 0x241,            /* PAL/SECAM set to 288 lines */
217 };
218
219 static const unsigned short init_secam[] = {
220         0x88, 23,               /* Window 1 vertical begin */
221         0x89, 288,              /* Vertical lines in (16 lines
222                                  * skipped by the VFE) */
223         0x8a, 288,              /* Vertical lines out (16 lines
224                                  * skipped by the VFE) */
225         0x8b, 16,               /* Horizontal begin */
226         0x8c, 768,              /* Horizontal length */
227         0x8d, 784,              /* Number of pixels
228                                  * Must be >= Horizontal begin + Horizontal length */
229         0x8f, 0xc00,            /* Disable window 2 */
230         0xf0, 0x77,             /* 13.5 MHz transport, Forced
231                                  * mode, latch windows */
232         0xf2, 0x3d5,            /* SECAM, composite input */
233         0xe7, 0x241,            /* PAL/SECAM set to 288 lines */
234 };
235
236 static const unsigned char init_common[] = {
237         0xf2, 0x00,             /* Disable all outputs */
238         0x33, 0x0d,             /* Luma : VIN2, Chroma : CIN
239                                  * (clamp off) */
240         0xd8, 0xa8,             /* HREF/VREF active high, VREF
241                                  * pulse = 2, Odd/Even flag */
242         0x20, 0x03,             /* IF compensation 0dB/oct */
243         0xe0, 0xff,             /* Open up all comparators */
244         0xe1, 0x00,
245         0xe2, 0x7f,
246         0xe3, 0x80,
247         0xe4, 0x7f,
248         0xe5, 0x80,
249         0xe6, 0x00,             /* Brightness set to 0 */
250         0xe7, 0xe0,             /* Contrast to 1.0, noise shaping
251                                  * 10 to 8 2-bit error diffusion */
252         0xe8, 0xf8,             /* YUV422, CbCr binary offset,
253                                  * ... (p.32) */
254         0xea, 0x18,             /* LLC2 connected, output FIFO
255                                  * reset with VACTintern */
256         0xf0, 0x8a,             /* Half full level to 10, bus
257                                  * shuffler [7:0, 23:16, 15:8] */
258         0xf1, 0x18,             /* Single clock, sync mode, no
259                                  * FE delay, no HLEN counter */
260         0xf8, 0x12,             /* Port A, PIXCLK, HF# & FE#
261                                  * strength to 2 */
262         0xf9, 0x24,             /* Port B, HREF, VREF, PREF &
263                                  * ALPHA strength to 4 */
264 };
265
266 static const unsigned short init_fp[] = {
267         0x59, 0,
268         0xa0, 2070,             /* ACC reference */
269         0xa3, 0,
270         0xa4, 0,
271         0xa8, 30,
272         0xb2, 768,
273         0xbe, 27,
274         0x58, 0,
275         0x26, 0,
276         0x4b, 0x298,            /* PLL gain */
277 };
278
279
280 static int vpx3220_init(struct v4l2_subdev *sd, u32 val)
281 {
282         struct vpx3220 *decoder = to_vpx3220(sd);
283
284         vpx3220_write_block(sd, init_common, sizeof(init_common));
285         vpx3220_write_fp_block(sd, init_fp, sizeof(init_fp) >> 1);
286         if (decoder->norm & V4L2_STD_NTSC)
287                 vpx3220_write_fp_block(sd, init_ntsc, sizeof(init_ntsc) >> 1);
288         else if (decoder->norm & V4L2_STD_PAL)
289                 vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1);
290         else if (decoder->norm & V4L2_STD_SECAM)
291                 vpx3220_write_fp_block(sd, init_secam, sizeof(init_secam) >> 1);
292         else
293                 vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1);
294         return 0;
295 }
296
297 static int vpx3220_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd)
298 {
299         int res = V4L2_IN_ST_NO_SIGNAL, status;
300         v4l2_std_id std = 0;
301
302         v4l2_dbg(1, debug, sd, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n");
303
304         status = vpx3220_fp_read(sd, 0x0f3);
305
306         v4l2_dbg(1, debug, sd, "status: 0x%04x\n", status);
307
308         if (status < 0)
309                 return status;
310
311         if ((status & 0x20) == 0) {
312                 res = 0;
313
314                 switch (status & 0x18) {
315                 case 0x00:
316                 case 0x10:
317                 case 0x14:
318                 case 0x18:
319                         std = V4L2_STD_PAL;
320                         break;
321
322                 case 0x08:
323                         std = V4L2_STD_SECAM;
324                         break;
325
326                 case 0x04:
327                 case 0x0c:
328                 case 0x1c:
329                         std = V4L2_STD_NTSC;
330                         break;
331                 }
332         }
333         if (pstd)
334                 *pstd = std;
335         if (pstatus)
336                 *pstatus = status;
337         return 0;
338 }
339
340 static int vpx3220_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
341 {
342         return vpx3220_status(sd, NULL, std);
343 }
344
345 static int vpx3220_g_input_status(struct v4l2_subdev *sd, u32 *status)
346 {
347         return vpx3220_status(sd, status, NULL);
348 }
349
350 static int vpx3220_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
351 {
352         struct vpx3220 *decoder = to_vpx3220(sd);
353         int temp_input;
354
355         /* Here we back up the input selection because it gets
356            overwritten when we fill the registers with the
357            choosen video norm */
358         temp_input = vpx3220_fp_read(sd, 0xf2);
359
360         v4l2_dbg(1, debug, sd, "VIDIOC_S_STD %llx\n", std);
361         if (std & V4L2_STD_NTSC) {
362                 vpx3220_write_fp_block(sd, init_ntsc, sizeof(init_ntsc) >> 1);
363                 v4l2_dbg(1, debug, sd, "norm switched to NTSC\n");
364         } else if (std & V4L2_STD_PAL) {
365                 vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1);
366                 v4l2_dbg(1, debug, sd, "norm switched to PAL\n");
367         } else if (std & V4L2_STD_SECAM) {
368                 vpx3220_write_fp_block(sd, init_secam, sizeof(init_secam) >> 1);
369                 v4l2_dbg(1, debug, sd, "norm switched to SECAM\n");
370         } else {
371                 return -EINVAL;
372         }
373
374         decoder->norm = std;
375
376         /* And here we set the backed up video input again */
377         vpx3220_fp_write(sd, 0xf2, temp_input | 0x0010);
378         udelay(10);
379         return 0;
380 }
381
382 static int vpx3220_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
383 {
384         int data;
385
386         /* RJ:   route->input = 0: ST8 (PCTV) input
387                  route->input = 1: COMPOSITE  input
388                  route->input = 2: SVHS       input  */
389
390         const int input[3][2] = {
391                 {0x0c, 0},
392                 {0x0d, 0},
393                 {0x0e, 1}
394         };
395
396         if (route->input < 0 || route->input > 2)
397                 return -EINVAL;
398
399         v4l2_dbg(1, debug, sd, "input switched to %s\n", inputs[route->input]);
400
401         vpx3220_write(sd, 0x33, input[route->input][0]);
402
403         data = vpx3220_fp_read(sd, 0xf2) & ~(0x0020);
404         if (data < 0)
405                 return data;
406         /* 0x0010 is required to latch the setting */
407         vpx3220_fp_write(sd, 0xf2,
408                         data | (input[route->input][1] << 5) | 0x0010);
409
410         udelay(10);
411         return 0;
412 }
413
414 static int vpx3220_s_stream(struct v4l2_subdev *sd, int enable)
415 {
416         v4l2_dbg(1, debug, sd, "VIDIOC_STREAM%s\n", enable ? "ON" : "OFF");
417
418         vpx3220_write(sd, 0xf2, (enable ? 0x1b : 0x00));
419         return 0;
420 }
421
422 static int vpx3220_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
423 {
424         switch (qc->id) {
425         case V4L2_CID_BRIGHTNESS:
426                 v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
427                 break;
428
429         case V4L2_CID_CONTRAST:
430                 v4l2_ctrl_query_fill(qc, 0, 63, 1, 32);
431                 break;
432
433         case V4L2_CID_SATURATION:
434                 v4l2_ctrl_query_fill(qc, 0, 4095, 1, 2048);
435                 break;
436
437         case V4L2_CID_HUE:
438                 v4l2_ctrl_query_fill(qc, -512, 511, 1, 0);
439                 break;
440
441         default:
442                 return -EINVAL;
443         }
444         return 0;
445 }
446
447 static int vpx3220_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
448 {
449         struct vpx3220 *decoder = to_vpx3220(sd);
450
451         switch (ctrl->id) {
452         case V4L2_CID_BRIGHTNESS:
453                 ctrl->value = decoder->bright;
454                 break;
455         case V4L2_CID_CONTRAST:
456                 ctrl->value = decoder->contrast;
457                 break;
458         case V4L2_CID_SATURATION:
459                 ctrl->value = decoder->sat;
460                 break;
461         case V4L2_CID_HUE:
462                 ctrl->value = decoder->hue;
463                 break;
464         default:
465                 return -EINVAL;
466         }
467         return 0;
468 }
469
470 static int vpx3220_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
471 {
472         struct vpx3220 *decoder = to_vpx3220(sd);
473
474         switch (ctrl->id) {
475         case V4L2_CID_BRIGHTNESS:
476                 if (decoder->bright != ctrl->value) {
477                         decoder->bright = ctrl->value;
478                         vpx3220_write(sd, 0xe6, decoder->bright);
479                 }
480                 break;
481         case V4L2_CID_CONTRAST:
482                 if (decoder->contrast != ctrl->value) {
483                         /* Bit 7 and 8 is for noise shaping */
484                         decoder->contrast = ctrl->value;
485                         vpx3220_write(sd, 0xe7, decoder->contrast + 192);
486                 }
487                 break;
488         case V4L2_CID_SATURATION:
489                 if (decoder->sat != ctrl->value) {
490                         decoder->sat = ctrl->value;
491                         vpx3220_fp_write(sd, 0xa0, decoder->sat);
492                 }
493                 break;
494         case V4L2_CID_HUE:
495                 if (decoder->hue != ctrl->value) {
496                         decoder->hue = ctrl->value;
497                         vpx3220_fp_write(sd, 0x1c, decoder->hue);
498                 }
499                 break;
500         default:
501                 return -EINVAL;
502         }
503         return 0;
504 }
505
506 static int vpx3220_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
507 {
508         struct vpx3220 *decoder = to_vpx3220(sd);
509         struct i2c_client *client = v4l2_get_subdevdata(sd);
510
511         return v4l2_chip_ident_i2c_client(client, chip, decoder->ident, 0);
512 }
513
514 static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg)
515 {
516         return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
517 }
518
519 /* ----------------------------------------------------------------------- */
520
521 static const struct v4l2_subdev_core_ops vpx3220_core_ops = {
522         .g_chip_ident = vpx3220_g_chip_ident,
523         .init = vpx3220_init,
524         .g_ctrl = vpx3220_g_ctrl,
525         .s_ctrl = vpx3220_s_ctrl,
526         .queryctrl = vpx3220_queryctrl,
527 };
528
529 static const struct v4l2_subdev_tuner_ops vpx3220_tuner_ops = {
530         .s_std = vpx3220_s_std,
531 };
532
533 static const struct v4l2_subdev_video_ops vpx3220_video_ops = {
534         .s_routing = vpx3220_s_routing,
535         .s_stream = vpx3220_s_stream,
536         .querystd = vpx3220_querystd,
537         .g_input_status = vpx3220_g_input_status,
538 };
539
540 static const struct v4l2_subdev_ops vpx3220_ops = {
541         .core = &vpx3220_core_ops,
542         .tuner = &vpx3220_tuner_ops,
543         .video = &vpx3220_video_ops,
544 };
545
546 /* -----------------------------------------------------------------------
547  * Client management code
548  */
549
550 static int vpx3220_probe(struct i2c_client *client,
551                         const struct i2c_device_id *id)
552 {
553         struct vpx3220 *decoder;
554         struct v4l2_subdev *sd;
555         const char *name = NULL;
556         u8 ver;
557         u16 pn;
558
559         /* Check if the adapter supports the needed features */
560         if (!i2c_check_functionality(client->adapter,
561                 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
562                 return -ENODEV;
563
564         decoder = kzalloc(sizeof(struct vpx3220), GFP_KERNEL);
565         if (decoder == NULL)
566                 return -ENOMEM;
567         sd = &decoder->sd;
568         v4l2_i2c_subdev_init(sd, client, &vpx3220_ops);
569         decoder->norm = V4L2_STD_PAL;
570         decoder->input = 0;
571         decoder->enable = 1;
572         decoder->bright = 32768;
573         decoder->contrast = 32768;
574         decoder->hue = 32768;
575         decoder->sat = 32768;
576
577         ver = i2c_smbus_read_byte_data(client, 0x00);
578         pn = (i2c_smbus_read_byte_data(client, 0x02) << 8) +
579                 i2c_smbus_read_byte_data(client, 0x01);
580         decoder->ident = V4L2_IDENT_VPX3220A;
581         if (ver == 0xec) {
582                 switch (pn) {
583                 case 0x4680:
584                         name = "vpx3220a";
585                         break;
586                 case 0x4260:
587                         name = "vpx3216b";
588                         decoder->ident = V4L2_IDENT_VPX3216B;
589                         break;
590                 case 0x4280:
591                         name = "vpx3214c";
592                         decoder->ident = V4L2_IDENT_VPX3214C;
593                         break;
594                 }
595         }
596         if (name)
597                 v4l2_info(sd, "%s found @ 0x%x (%s)\n", name,
598                         client->addr << 1, client->adapter->name);
599         else
600                 v4l2_info(sd, "chip (%02x:%04x) found @ 0x%x (%s)\n",
601                         ver, pn, client->addr << 1, client->adapter->name);
602
603         vpx3220_write_block(sd, init_common, sizeof(init_common));
604         vpx3220_write_fp_block(sd, init_fp, sizeof(init_fp) >> 1);
605         /* Default to PAL */
606         vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1);
607         return 0;
608 }
609
610 static int vpx3220_remove(struct i2c_client *client)
611 {
612         struct v4l2_subdev *sd = i2c_get_clientdata(client);
613
614         v4l2_device_unregister_subdev(sd);
615         kfree(to_vpx3220(sd));
616         return 0;
617 }
618
619 static const struct i2c_device_id vpx3220_id[] = {
620         { "vpx3220a", 0 },
621         { "vpx3216b", 0 },
622         { "vpx3214c", 0 },
623         { }
624 };
625 MODULE_DEVICE_TABLE(i2c, vpx3220_id);
626
627 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
628         .name = "vpx3220",
629         .driverid = I2C_DRIVERID_VPX3220,
630         .command = vpx3220_command,
631         .probe = vpx3220_probe,
632         .remove = vpx3220_remove,
633         .id_table = vpx3220_id,
634 };