aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2008-09-07 07:01:39 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-10-17 16:20:13 -0400
commit23848b655ab5fc2fe88ef99e90ad8e4c41304d76 (patch)
treeae755bfdc215a2b09163ca0f0c226db4a98cc644 /drivers/media
parent0afb351e62f855b1c3584fb54bc6b91b54b32a9a (diff)
V4L/DVB (9208): vpx3220: convert i2c driver for new i2c API
- Convert to use v4l2-i2c-drv-legacy.h to be able to handle the new i2c API - Cleanups - Use v4l_dbg/v4l_info to have uniform kernel messages Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/vpx3220.c328
1 files changed, 91 insertions, 237 deletions
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
index 45be9ec8edc4..67aa0db4b81a 100644
--- a/drivers/media/video/vpx3220.c
+++ b/drivers/media/video/vpx3220.c
@@ -22,32 +22,21 @@
22#include <linux/init.h> 22#include <linux/init.h>
23#include <linux/delay.h> 23#include <linux/delay.h>
24#include <linux/types.h> 24#include <linux/types.h>
25#include <linux/slab.h>
26
27#include <asm/io.h>
28#include <asm/uaccess.h> 25#include <asm/uaccess.h>
29
30#include <linux/i2c.h> 26#include <linux/i2c.h>
31
32#define I2C_NAME(x) (x)->name
33
34#include <linux/videodev.h>
35#include <media/v4l2-common.h> 27#include <media/v4l2-common.h>
28#include <media/v4l2-i2c-drv-legacy.h>
29#include <linux/videodev.h>
36#include <linux/video_decoder.h> 30#include <linux/video_decoder.h>
37 31
38#define I2C_VPX3220 0x86 32MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver");
39#define VPX3220_DEBUG KERN_DEBUG "vpx3220: " 33MODULE_AUTHOR("Laurent Pinchart");
34MODULE_LICENSE("GPL");
40 35
41static int debug; 36static int debug;
42module_param(debug, int, 0); 37module_param(debug, int, 0);
43MODULE_PARM_DESC(debug, "Debug level (0-1)"); 38MODULE_PARM_DESC(debug, "Debug level (0-1)");
44 39
45#define dprintk(num, format, args...) \
46 do { \
47 if (debug >= num) \
48 printk(format, ##args); \
49 } while (0)
50
51#define VPX_TIMEOUT_COUNT 10 40#define VPX_TIMEOUT_COUNT 10
52 41
53/* ----------------------------------------------------------------------- */ 42/* ----------------------------------------------------------------------- */
@@ -67,10 +56,8 @@ struct vpx3220 {
67static char *inputs[] = { "internal", "composite", "svideo" }; 56static char *inputs[] = { "internal", "composite", "svideo" };
68 57
69/* ----------------------------------------------------------------------- */ 58/* ----------------------------------------------------------------------- */
70static inline int 59
71vpx3220_write (struct i2c_client *client, 60static inline int vpx3220_write(struct i2c_client *client, u8 reg, u8 value)
72 u8 reg,
73 u8 value)
74{ 61{
75 struct vpx3220 *decoder = i2c_get_clientdata(client); 62 struct vpx3220 *decoder = i2c_get_clientdata(client);
76 63
@@ -78,15 +65,12 @@ vpx3220_write (struct i2c_client *client,
78 return i2c_smbus_write_byte_data(client, reg, value); 65 return i2c_smbus_write_byte_data(client, reg, value);
79} 66}
80 67
81static inline int 68static inline int vpx3220_read(struct i2c_client *client, u8 reg)
82vpx3220_read (struct i2c_client *client,
83 u8 reg)
84{ 69{
85 return i2c_smbus_read_byte_data(client, reg); 70 return i2c_smbus_read_byte_data(client, reg);
86} 71}
87 72
88static int 73static int vpx3220_fp_status(struct i2c_client *client)
89vpx3220_fp_status (struct i2c_client *client)
90{ 74{
91 unsigned char status; 75 unsigned char status;
92 unsigned int i; 76 unsigned int i;
@@ -106,14 +90,11 @@ vpx3220_fp_status (struct i2c_client *client)
106 return -1; 90 return -1;
107} 91}
108 92
109static int 93static int vpx3220_fp_write(struct i2c_client *client, u8 fpaddr, u16 data)
110vpx3220_fp_write (struct i2c_client *client,
111 u8 fpaddr,
112 u16 data)
113{ 94{
114 /* Write the 16-bit address to the FPWR register */ 95 /* Write the 16-bit address to the FPWR register */
115 if (i2c_smbus_write_word_data(client, 0x27, swab16(fpaddr)) == -1) { 96 if (i2c_smbus_write_word_data(client, 0x27, swab16(fpaddr)) == -1) {
116 dprintk(1, VPX3220_DEBUG "%s: failed\n", __func__); 97 v4l_dbg(1, debug, client, "%s: failed\n", __func__);
117 return -1; 98 return -1;
118 } 99 }
119 100
@@ -122,22 +103,20 @@ vpx3220_fp_write (struct i2c_client *client,
122 103
123 /* Write the 16-bit data to the FPDAT register */ 104 /* Write the 16-bit data to the FPDAT register */
124 if (i2c_smbus_write_word_data(client, 0x28, swab16(data)) == -1) { 105 if (i2c_smbus_write_word_data(client, 0x28, swab16(data)) == -1) {
125 dprintk(1, VPX3220_DEBUG "%s: failed\n", __func__); 106 v4l_dbg(1, debug, client, "%s: failed\n", __func__);
126 return -1; 107 return -1;
127 } 108 }
128 109
129 return 0; 110 return 0;
130} 111}
131 112
132static u16 113static u16 vpx3220_fp_read(struct i2c_client *client, u16 fpaddr)
133vpx3220_fp_read (struct i2c_client *client,
134 u16 fpaddr)
135{ 114{
136 s16 data; 115 s16 data;
137 116
138 /* Write the 16-bit address to the FPRD register */ 117 /* Write the 16-bit address to the FPRD register */
139 if (i2c_smbus_write_word_data(client, 0x26, swab16(fpaddr)) == -1) { 118 if (i2c_smbus_write_word_data(client, 0x26, swab16(fpaddr)) == -1) {
140 dprintk(1, VPX3220_DEBUG "%s: failed\n", __func__); 119 v4l_dbg(1, debug, client, "%s: failed\n", __func__);
141 return -1; 120 return -1;
142 } 121 }
143 122
@@ -147,25 +126,22 @@ vpx3220_fp_read (struct i2c_client *client,
147 /* Read the 16-bit data from the FPDAT register */ 126 /* Read the 16-bit data from the FPDAT register */
148 data = i2c_smbus_read_word_data(client, 0x28); 127 data = i2c_smbus_read_word_data(client, 0x28);
149 if (data == -1) { 128 if (data == -1) {
150 dprintk(1, VPX3220_DEBUG "%s: failed\n", __func__); 129 v4l_dbg(1, debug, client, "%s: failed\n", __func__);
151 return -1; 130 return -1;
152 } 131 }
153 132
154 return swab16(data); 133 return swab16(data);
155} 134}
156 135
157static int 136static int vpx3220_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
158vpx3220_write_block (struct i2c_client *client,
159 const u8 *data,
160 unsigned int len)
161{ 137{
162 u8 reg; 138 u8 reg;
163 int ret = -1; 139 int ret = -1;
164 140
165 while (len >= 2) { 141 while (len >= 2) {
166 reg = *data++; 142 reg = *data++;
167 if ((ret = 143 ret = vpx3220_write(client, reg, *data++);
168 vpx3220_write(client, reg, *data++)) < 0) 144 if (ret < 0)
169 break; 145 break;
170 len -= 2; 146 len -= 2;
171 } 147 }
@@ -173,10 +149,8 @@ vpx3220_write_block (struct i2c_client *client,
173 return ret; 149 return ret;
174} 150}
175 151
176static int 152static int vpx3220_write_fp_block(struct i2c_client *client,
177vpx3220_write_fp_block (struct i2c_client *client, 153 const u16 *data, unsigned int len)
178 const u16 *data,
179 unsigned int len)
180{ 154{
181 u8 reg; 155 u8 reg;
182 int ret = 0; 156 int ret = 0;
@@ -285,25 +259,20 @@ static const unsigned short init_fp[] = {
285 0x4b, 0x298, /* PLL gain */ 259 0x4b, 0x298, /* PLL gain */
286}; 260};
287 261
288static void 262static void vpx3220_dump_i2c(struct i2c_client *client)
289vpx3220_dump_i2c (struct i2c_client *client)
290{ 263{
291 int len = sizeof(init_common); 264 int len = sizeof(init_common);
292 const unsigned char *data = init_common; 265 const unsigned char *data = init_common;
293 266
294 while (len > 1) { 267 while (len > 1) {
295 dprintk(1, 268 v4l_dbg(1, debug, client, "i2c reg 0x%02x data 0x%02x\n",
296 KERN_DEBUG "vpx3216b i2c reg 0x%02x data 0x%02x\n",
297 *data, vpx3220_read(client, *data)); 269 *data, vpx3220_read(client, *data));
298 data += 2; 270 data += 2;
299 len -= 2; 271 len -= 2;
300 } 272 }
301} 273}
302 274
303static int 275static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg)
304vpx3220_command (struct i2c_client *client,
305 unsigned int cmd,
306 void *arg)
307{ 276{
308 struct vpx3220 *decoder = i2c_get_clientdata(client); 277 struct vpx3220 *decoder = i2c_get_clientdata(client);
309 278
@@ -315,7 +284,6 @@ vpx3220_command (struct i2c_client *client,
315 vpx3220_write_fp_block(client, init_fp, 284 vpx3220_write_fp_block(client, init_fp,
316 sizeof(init_fp) >> 1); 285 sizeof(init_fp) >> 1);
317 switch (decoder->norm) { 286 switch (decoder->norm) {
318
319 case VIDEO_MODE_NTSC: 287 case VIDEO_MODE_NTSC:
320 vpx3220_write_fp_block(client, init_ntsc, 288 vpx3220_write_fp_block(client, init_ntsc,
321 sizeof(init_ntsc) >> 1); 289 sizeof(init_ntsc) >> 1);
@@ -334,21 +302,20 @@ vpx3220_command (struct i2c_client *client,
334 sizeof(init_pal) >> 1); 302 sizeof(init_pal) >> 1);
335 break; 303 break;
336 } 304 }
337 }
338 break; 305 break;
306 }
339 307
340 case DECODER_DUMP: 308 case DECODER_DUMP:
341 { 309 {
342 vpx3220_dump_i2c(client); 310 vpx3220_dump_i2c(client);
343 }
344 break; 311 break;
312 }
345 313
346 case DECODER_GET_CAPABILITIES: 314 case DECODER_GET_CAPABILITIES:
347 { 315 {
348 struct video_decoder_capability *cap = arg; 316 struct video_decoder_capability *cap = arg;
349 317
350 dprintk(1, KERN_DEBUG "%s: DECODER_GET_CAPABILITIES\n", 318 v4l_dbg(1, debug, client, "DECODER_GET_CAPABILITIES\n");
351 I2C_NAME(client));
352 319
353 cap->flags = VIDEO_DECODER_PAL | 320 cap->flags = VIDEO_DECODER_PAL |
354 VIDEO_DECODER_NTSC | 321 VIDEO_DECODER_NTSC |
@@ -357,20 +324,18 @@ vpx3220_command (struct i2c_client *client,
357 VIDEO_DECODER_CCIR; 324 VIDEO_DECODER_CCIR;
358 cap->inputs = 3; 325 cap->inputs = 3;
359 cap->outputs = 1; 326 cap->outputs = 1;
360 }
361 break; 327 break;
328 }
362 329
363 case DECODER_GET_STATUS: 330 case DECODER_GET_STATUS:
364 { 331 {
365 int res = 0, status; 332 int res = 0, status;
366 333
367 dprintk(1, KERN_INFO "%s: DECODER_GET_STATUS\n", 334 v4l_dbg(1, debug, client, "DECODER_GET_STATUS\n");
368 I2C_NAME(client));
369 335
370 status = vpx3220_fp_read(client, 0x0f3); 336 status = vpx3220_fp_read(client, 0x0f3);
371 337
372 dprintk(1, KERN_INFO "%s: status: 0x%04x\n", I2C_NAME(client), 338 v4l_dbg(1, debug, client, "status: 0x%04x\n", status);
373 status);
374 339
375 if (status < 0) 340 if (status < 0)
376 return status; 341 return status;
@@ -379,7 +344,6 @@ vpx3220_command (struct i2c_client *client,
379 res |= DECODER_STATUS_GOOD | DECODER_STATUS_COLOR; 344 res |= DECODER_STATUS_GOOD | DECODER_STATUS_COLOR;
380 345
381 switch (status & 0x18) { 346 switch (status & 0x18) {
382
383 case 0x00: 347 case 0x00:
384 case 0x10: 348 case 0x10:
385 case 0x14: 349 case 0x14:
@@ -400,8 +364,8 @@ vpx3220_command (struct i2c_client *client,
400 } 364 }
401 365
402 *(int *) arg = res; 366 *(int *) arg = res;
403 }
404 break; 367 break;
368 }
405 369
406 case DECODER_SET_NORM: 370 case DECODER_SET_NORM:
407 { 371 {
@@ -413,50 +377,43 @@ vpx3220_command (struct i2c_client *client,
413 choosen video norm */ 377 choosen video norm */
414 temp_input = vpx3220_fp_read(client, 0xf2); 378 temp_input = vpx3220_fp_read(client, 0xf2);
415 379
416 dprintk(1, KERN_DEBUG "%s: DECODER_SET_NORM %d\n", 380 v4l_dbg(1, debug, client, "DECODER_SET_NORM %d\n", *iarg);
417 I2C_NAME(client), *iarg);
418 switch (*iarg) { 381 switch (*iarg) {
419
420 case VIDEO_MODE_NTSC: 382 case VIDEO_MODE_NTSC:
421 vpx3220_write_fp_block(client, init_ntsc, 383 vpx3220_write_fp_block(client, init_ntsc,
422 sizeof(init_ntsc) >> 1); 384 sizeof(init_ntsc) >> 1);
423 dprintk(1, KERN_INFO "%s: norm switched to NTSC\n", 385 v4l_dbg(1, debug, client, "norm switched to NTSC\n");
424 I2C_NAME(client));
425 break; 386 break;
426 387
427 case VIDEO_MODE_PAL: 388 case VIDEO_MODE_PAL:
428 vpx3220_write_fp_block(client, init_pal, 389 vpx3220_write_fp_block(client, init_pal,
429 sizeof(init_pal) >> 1); 390 sizeof(init_pal) >> 1);
430 dprintk(1, KERN_INFO "%s: norm switched to PAL\n", 391 v4l_dbg(1, debug, client, "norm switched to PAL\n");
431 I2C_NAME(client));
432 break; 392 break;
433 393
434 case VIDEO_MODE_SECAM: 394 case VIDEO_MODE_SECAM:
435 vpx3220_write_fp_block(client, init_secam, 395 vpx3220_write_fp_block(client, init_secam,
436 sizeof(init_secam) >> 1); 396 sizeof(init_secam) >> 1);
437 dprintk(1, KERN_INFO "%s: norm switched to SECAM\n", 397 v4l_dbg(1, debug, client, "norm switched to SECAM\n");
438 I2C_NAME(client));
439 break; 398 break;
440 399
441 case VIDEO_MODE_AUTO: 400 case VIDEO_MODE_AUTO:
442 /* FIXME This is only preliminary support */ 401 /* FIXME This is only preliminary support */
443 data = vpx3220_fp_read(client, 0xf2) & 0x20; 402 data = vpx3220_fp_read(client, 0xf2) & 0x20;
444 vpx3220_fp_write(client, 0xf2, 0x00c0 | data); 403 vpx3220_fp_write(client, 0xf2, 0x00c0 | data);
445 dprintk(1, KERN_INFO "%s: norm switched to Auto\n", 404 v4l_dbg(1, debug, client, "norm switched to AUTO\n");
446 I2C_NAME(client));
447 break; 405 break;
448 406
449 default: 407 default:
450 return -EINVAL; 408 return -EINVAL;
451
452 } 409 }
453 decoder->norm = *iarg; 410 decoder->norm = *iarg;
454 411
455 /* And here we set the backed up video input again */ 412 /* And here we set the backed up video input again */
456 vpx3220_fp_write(client, 0xf2, temp_input | 0x0010); 413 vpx3220_fp_write(client, 0xf2, temp_input | 0x0010);
457 udelay(10); 414 udelay(10);
458 }
459 break; 415 break;
416 }
460 417
461 case DECODER_SET_INPUT: 418 case DECODER_SET_INPUT:
462 { 419 {
@@ -475,8 +432,7 @@ vpx3220_command (struct i2c_client *client,
475 if (*iarg < 0 || *iarg > 2) 432 if (*iarg < 0 || *iarg > 2)
476 return -EINVAL; 433 return -EINVAL;
477 434
478 dprintk(1, KERN_INFO "%s: input switched to %s\n", 435 v4l_dbg(1, debug, client, "input switched to %s\n", inputs[*iarg]);
479 I2C_NAME(client), inputs[*iarg]);
480 436
481 vpx3220_write(client, 0x33, input[*iarg][0]); 437 vpx3220_write(client, 0x33, input[*iarg][0]);
482 438
@@ -488,8 +444,8 @@ vpx3220_command (struct i2c_client *client,
488 data | (input[*iarg][1] << 5) | 0x0010); 444 data | (input[*iarg][1] << 5) | 0x0010);
489 445
490 udelay(10); 446 udelay(10);
491 }
492 break; 447 break;
448 }
493 449
494 case DECODER_SET_OUTPUT: 450 case DECODER_SET_OUTPUT:
495 { 451 {
@@ -499,19 +455,18 @@ vpx3220_command (struct i2c_client *client,
499 if (*iarg != 0) { 455 if (*iarg != 0) {
500 return -EINVAL; 456 return -EINVAL;
501 } 457 }
502 }
503 break; 458 break;
459 }
504 460
505 case DECODER_ENABLE_OUTPUT: 461 case DECODER_ENABLE_OUTPUT:
506 { 462 {
507 int *iarg = arg; 463 int *iarg = arg;
508 464
509 dprintk(1, KERN_DEBUG "%s: DECODER_ENABLE_OUTPUT %d\n", 465 v4l_dbg(1, debug, client, "DECODER_ENABLE_OUTPUT %d\n", *iarg);
510 I2C_NAME(client), *iarg);
511 466
512 vpx3220_write(client, 0xf2, (*iarg ? 0x1b : 0x00)); 467 vpx3220_write(client, 0xf2, (*iarg ? 0x1b : 0x00));
513 }
514 break; 468 break;
469 }
515 470
516 case DECODER_SET_PICTURE: 471 case DECODER_SET_PICTURE:
517 { 472 {
@@ -542,8 +497,8 @@ vpx3220_command (struct i2c_client *client,
542 vpx3220_fp_write(client, 0x1c, 497 vpx3220_fp_write(client, 0x1c,
543 ((decoder->hue - 32768) >> 6) & 0xFFF); 498 ((decoder->hue - 32768) >> 6) & 0xFFF);
544 } 499 }
545 }
546 break; 500 break;
501 }
547 502
548 default: 503 default:
549 return -EINVAL; 504 return -EINVAL;
@@ -552,8 +507,7 @@ vpx3220_command (struct i2c_client *client,
552 return 0; 507 return 0;
553} 508}
554 509
555static int 510static int vpx3220_init_client(struct i2c_client *client)
556vpx3220_init_client (struct i2c_client *client)
557{ 511{
558 vpx3220_write_block(client, init_common, sizeof(init_common)); 512 vpx3220_write_block(client, init_common, sizeof(init_common));
559 vpx3220_write_fp_block(client, init_fp, sizeof(init_fp) >> 1); 513 vpx3220_write_fp_block(client, init_fp, sizeof(init_fp) >> 1);
@@ -567,115 +521,26 @@ vpx3220_init_client (struct i2c_client *client)
567 * Client management code 521 * Client management code
568 */ 522 */
569 523
570/* 524static unsigned short normal_i2c[] = { 0x86 >> 1, 0x8e >> 1, I2C_CLIENT_END };
571 * Generic i2c probe
572 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
573 */
574static unsigned short normal_i2c[] =
575 { I2C_VPX3220 >> 1, (I2C_VPX3220 >> 1) + 4,
576 I2C_CLIENT_END
577};
578
579static unsigned short ignore = I2C_CLIENT_END;
580 525
581static struct i2c_client_address_data addr_data = { 526I2C_CLIENT_INSMOD;
582 .normal_i2c = normal_i2c,
583 .probe = &ignore,
584 .ignore = &ignore,
585};
586
587static struct i2c_driver vpx3220_i2c_driver;
588
589static int
590vpx3220_detach_client (struct i2c_client *client)
591{
592 struct vpx3220 *decoder = i2c_get_clientdata(client);
593 int err;
594
595 err = i2c_detach_client(client);
596 if (err) {
597 return err;
598 }
599
600 kfree(decoder);
601 kfree(client);
602
603 return 0;
604}
605 527
606static int 528static int vpx3220_probe(struct i2c_client *client,
607vpx3220_detect_client (struct i2c_adapter *adapter, 529 const struct i2c_device_id *id)
608 int address,
609 int kind)
610{ 530{
611 int err;
612 struct i2c_client *client;
613 struct vpx3220 *decoder; 531 struct vpx3220 *decoder;
614 532 const char *name = NULL;
615 dprintk(1, VPX3220_DEBUG "%s\n", __func__); 533 u8 ver;
534 u16 pn;
616 535
617 /* Check if the adapter supports the needed features */ 536 /* Check if the adapter supports the needed features */
618 if (!i2c_check_functionality 537 if (!i2c_check_functionality(client->adapter,
619 (adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) 538 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
620 return 0; 539 return -ENODEV;
621
622 client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
623 if (client == NULL) {
624 return -ENOMEM;
625 }
626
627 client->addr = address;
628 client->adapter = adapter;
629 client->driver = &vpx3220_i2c_driver;
630
631 /* Check for manufacture ID and part number */
632 if (kind < 0) {
633 u8 id;
634 u16 pn;
635
636 id = vpx3220_read(client, 0x00);
637 if (id != 0xec) {
638 dprintk(1,
639 KERN_INFO
640 "vpx3220_attach: Wrong manufacturer ID (0x%02x)\n",
641 id);
642 kfree(client);
643 return 0;
644 }
645
646 pn = (vpx3220_read(client, 0x02) << 8) +
647 vpx3220_read(client, 0x01);
648 switch (pn) {
649 case 0x4680:
650 strlcpy(I2C_NAME(client), "vpx3220a",
651 sizeof(I2C_NAME(client)));
652 break;
653 case 0x4260:
654 strlcpy(I2C_NAME(client), "vpx3216b",
655 sizeof(I2C_NAME(client)));
656 break;
657 case 0x4280:
658 strlcpy(I2C_NAME(client), "vpx3214c",
659 sizeof(I2C_NAME(client)));
660 break;
661 default:
662 dprintk(1,
663 KERN_INFO
664 "%s: Wrong part number (0x%04x)\n",
665 __func__, pn);
666 kfree(client);
667 return 0;
668 }
669 } else {
670 strlcpy(I2C_NAME(client), "forced vpx32xx",
671 sizeof(I2C_NAME(client)));
672 }
673 540
674 decoder = kzalloc(sizeof(struct vpx3220), GFP_KERNEL); 541 decoder = kzalloc(sizeof(struct vpx3220), GFP_KERNEL);
675 if (decoder == NULL) { 542 if (decoder == NULL)
676 kfree(client);
677 return -ENOMEM; 543 return -ENOMEM;
678 }
679 decoder->norm = VIDEO_MODE_PAL; 544 decoder->norm = VIDEO_MODE_PAL;
680 decoder->input = 0; 545 decoder->input = 0;
681 decoder->enable = 1; 546 decoder->enable = 1;
@@ -685,63 +550,52 @@ vpx3220_detect_client (struct i2c_adapter *adapter,
685 decoder->sat = 32768; 550 decoder->sat = 32768;
686 i2c_set_clientdata(client, decoder); 551 i2c_set_clientdata(client, decoder);
687 552
688 err = i2c_attach_client(client); 553 ver = i2c_smbus_read_byte_data(client, 0x00);
689 if (err) { 554 pn = (i2c_smbus_read_byte_data(client, 0x02) << 8) +
690 kfree(client); 555 i2c_smbus_read_byte_data(client, 0x01);
691 kfree(decoder); 556 if (ver == 0xec) {
692 return err; 557 switch (pn) {
558 case 0x4680:
559 name = "vpx3220a";
560 break;
561 case 0x4260:
562 name = "vpx3216b";
563 break;
564 case 0x4280:
565 name = "vpx3214c";
566 break;
567 }
693 } 568 }
694 569 if (name)
695 dprintk(1, KERN_INFO "%s: vpx32xx client found at address 0x%02x\n", 570 v4l_info(client, "%s found @ 0x%x (%s)\n", name,
696 I2C_NAME(client), client->addr << 1); 571 client->addr << 1, client->adapter->name);
572 else
573 v4l_info(client, "chip (%02x:%04x) found @ 0x%x (%s)\n",
574 ver, pn, client->addr << 1, client->adapter->name);
697 575
698 vpx3220_init_client(client); 576 vpx3220_init_client(client);
699
700 return 0; 577 return 0;
701} 578}
702 579
703static int 580static int vpx3220_remove(struct i2c_client *client)
704vpx3220_attach_adapter (struct i2c_adapter *adapter)
705{ 581{
706 int ret; 582 kfree(i2c_get_clientdata(client));
707 583 return 0;
708 ret = i2c_probe(adapter, &addr_data, &vpx3220_detect_client);
709 dprintk(1, VPX3220_DEBUG "%s: i2c_probe returned %d\n",
710 __func__, ret);
711 return ret;
712} 584}
713 585
714/* ----------------------------------------------------------------------- 586static const struct i2c_device_id vpx3220_id[] = {
715 * Driver initialization and cleanup code 587 { "vpx3220a", 0 },
716 */ 588 { "vpx3216b", 0 },
717 589 { "vpx3214c", 0 },
718static struct i2c_driver vpx3220_i2c_driver = { 590 { }
719 .driver = { 591};
720 .name = "vpx3220", 592MODULE_DEVICE_TABLE(i2c, vpx3220_id);
721 },
722
723 .id = I2C_DRIVERID_VPX3220,
724 593
725 .attach_adapter = vpx3220_attach_adapter, 594static struct v4l2_i2c_driver_data v4l2_i2c_data = {
726 .detach_client = vpx3220_detach_client, 595 .name = "vpx3220",
596 .driverid = I2C_DRIVERID_VPX3220,
727 .command = vpx3220_command, 597 .command = vpx3220_command,
598 .probe = vpx3220_probe,
599 .remove = vpx3220_remove,
600 .id_table = vpx3220_id,
728}; 601};
729
730static int __init
731vpx3220_init (void)
732{
733 return i2c_add_driver(&vpx3220_i2c_driver);
734}
735
736static void __exit
737vpx3220_cleanup (void)
738{
739 i2c_del_driver(&vpx3220_i2c_driver);
740}
741
742module_init(vpx3220_init);
743module_exit(vpx3220_cleanup);
744
745MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver");
746MODULE_AUTHOR("Laurent Pinchart");
747MODULE_LICENSE("GPL");