diff options
-rw-r--r-- | drivers/media/video/saa7111.c | 224 |
1 files changed, 58 insertions, 166 deletions
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c index 96c3d4357722..a4738a2fb4d3 100644 --- a/drivers/media/video/saa7111.c +++ b/drivers/media/video/saa7111.c | |||
@@ -28,43 +28,24 @@ | |||
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/init.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/errno.h> | ||
34 | #include <linux/fs.h> | ||
35 | #include <linux/kernel.h> | ||
36 | #include <linux/major.h> | ||
37 | #include <linux/slab.h> | ||
38 | #include <linux/mm.h> | ||
39 | #include <linux/signal.h> | ||
40 | #include <linux/types.h> | 31 | #include <linux/types.h> |
41 | #include <linux/i2c.h> | 32 | #include <linux/ioctl.h> |
42 | #include <asm/io.h> | ||
43 | #include <asm/pgtable.h> | ||
44 | #include <asm/page.h> | ||
45 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
46 | 34 | #include <linux/i2c.h> | |
35 | #include <linux/i2c-id.h> | ||
47 | #include <linux/videodev.h> | 36 | #include <linux/videodev.h> |
48 | #include <linux/video_decoder.h> | 37 | #include <linux/video_decoder.h> |
38 | #include <media/v4l2-common.h> | ||
39 | #include <media/v4l2-i2c-drv-legacy.h> | ||
49 | 40 | ||
50 | MODULE_DESCRIPTION("Philips SAA7111 video decoder driver"); | 41 | MODULE_DESCRIPTION("Philips SAA7111 video decoder driver"); |
51 | MODULE_AUTHOR("Dave Perks"); | 42 | MODULE_AUTHOR("Dave Perks"); |
52 | MODULE_LICENSE("GPL"); | 43 | MODULE_LICENSE("GPL"); |
53 | 44 | ||
54 | |||
55 | #define I2C_NAME(s) (s)->name | ||
56 | |||
57 | |||
58 | static int debug; | 45 | static int debug; |
59 | module_param(debug, int, 0644); | 46 | module_param(debug, int, 0644); |
60 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); | 47 | MODULE_PARM_DESC(debug, "Debug level (0-1)"); |
61 | 48 | ||
62 | #define dprintk(num, format, args...) \ | ||
63 | do { \ | ||
64 | if (debug >= num) \ | ||
65 | printk(format, ##args); \ | ||
66 | } while (0) | ||
67 | |||
68 | /* ----------------------------------------------------------------------- */ | 49 | /* ----------------------------------------------------------------------- */ |
69 | 50 | ||
70 | #define SAA7111_NR_REG 0x18 | 51 | #define SAA7111_NR_REG 0x18 |
@@ -77,14 +58,9 @@ struct saa7111 { | |||
77 | int enable; | 58 | int enable; |
78 | }; | 59 | }; |
79 | 60 | ||
80 | #define I2C_SAA7111 0x48 | ||
81 | |||
82 | /* ----------------------------------------------------------------------- */ | 61 | /* ----------------------------------------------------------------------- */ |
83 | 62 | ||
84 | static inline int | 63 | static inline int saa7111_write(struct i2c_client *client, u8 reg, u8 value) |
85 | saa7111_write (struct i2c_client *client, | ||
86 | u8 reg, | ||
87 | u8 value) | ||
88 | { | 64 | { |
89 | struct saa7111 *decoder = i2c_get_clientdata(client); | 65 | struct saa7111 *decoder = i2c_get_clientdata(client); |
90 | 66 | ||
@@ -92,8 +68,7 @@ saa7111_write (struct i2c_client *client, | |||
92 | return i2c_smbus_write_byte_data(client, reg, value); | 68 | return i2c_smbus_write_byte_data(client, reg, value); |
93 | } | 69 | } |
94 | 70 | ||
95 | static inline void | 71 | static inline void saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value) |
96 | saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value) | ||
97 | { | 72 | { |
98 | struct saa7111 *decoder = i2c_get_clientdata(client); | 73 | struct saa7111 *decoder = i2c_get_clientdata(client); |
99 | 74 | ||
@@ -103,10 +78,7 @@ saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value) | |||
103 | } | 78 | } |
104 | } | 79 | } |
105 | 80 | ||
106 | static int | 81 | static int saa7111_write_block(struct i2c_client *client, const u8 *data, unsigned int len) |
107 | saa7111_write_block (struct i2c_client *client, | ||
108 | const u8 *data, | ||
109 | unsigned int len) | ||
110 | { | 82 | { |
111 | int ret = -1; | 83 | int ret = -1; |
112 | u8 reg; | 84 | u8 reg; |
@@ -127,18 +99,17 @@ saa7111_write_block (struct i2c_client *client, | |||
127 | decoder->reg[reg++] = data[1]; | 99 | decoder->reg[reg++] = data[1]; |
128 | len -= 2; | 100 | len -= 2; |
129 | data += 2; | 101 | data += 2; |
130 | } while (len >= 2 && data[0] == reg && | 102 | } while (len >= 2 && data[0] == reg && block_len < 32); |
131 | block_len < 32); | 103 | ret = i2c_master_send(client, block_data, block_len); |
132 | if ((ret = i2c_master_send(client, block_data, | 104 | if (ret < 0) |
133 | block_len)) < 0) | ||
134 | break; | 105 | break; |
135 | } | 106 | } |
136 | } else { | 107 | } else { |
137 | /* do some slow I2C emulation kind of thing */ | 108 | /* do some slow I2C emulation kind of thing */ |
138 | while (len >= 2) { | 109 | while (len >= 2) { |
139 | reg = *data++; | 110 | reg = *data++; |
140 | if ((ret = saa7111_write(client, reg, | 111 | ret = saa7111_write(client, reg, *data++); |
141 | *data++)) < 0) | 112 | if (ret < 0) |
142 | break; | 113 | break; |
143 | len -= 2; | 114 | len -= 2; |
144 | } | 115 | } |
@@ -147,16 +118,13 @@ saa7111_write_block (struct i2c_client *client, | |||
147 | return ret; | 118 | return ret; |
148 | } | 119 | } |
149 | 120 | ||
150 | static int | 121 | static int saa7111_init_decoder(struct i2c_client *client, |
151 | saa7111_init_decoder (struct i2c_client *client, | 122 | struct video_decoder_init *init) |
152 | struct video_decoder_init *init) | ||
153 | { | 123 | { |
154 | return saa7111_write_block(client, init->data, init->len); | 124 | return saa7111_write_block(client, init->data, init->len); |
155 | } | 125 | } |
156 | 126 | ||
157 | static inline int | 127 | static inline int saa7111_read(struct i2c_client *client, u8 reg) |
158 | saa7111_read (struct i2c_client *client, | ||
159 | u8 reg) | ||
160 | { | 128 | { |
161 | return i2c_smbus_read_byte_data(client, reg); | 129 | return i2c_smbus_read_byte_data(client, reg); |
162 | } | 130 | } |
@@ -203,28 +171,23 @@ static const unsigned char saa7111_i2c_init[] = { | |||
203 | 0x17, 0x00, /* 17 - VBI */ | 171 | 0x17, 0x00, /* 17 - VBI */ |
204 | }; | 172 | }; |
205 | 173 | ||
206 | static int | 174 | static int saa7111_command(struct i2c_client *client, unsigned cmd, void *arg) |
207 | saa7111_command (struct i2c_client *client, | ||
208 | unsigned int cmd, | ||
209 | void *arg) | ||
210 | { | 175 | { |
211 | struct saa7111 *decoder = i2c_get_clientdata(client); | 176 | struct saa7111 *decoder = i2c_get_clientdata(client); |
212 | 177 | ||
213 | switch (cmd) { | 178 | switch (cmd) { |
214 | |||
215 | case 0: | 179 | case 0: |
216 | break; | 180 | break; |
217 | case DECODER_INIT: | 181 | case DECODER_INIT: |
218 | { | 182 | { |
219 | struct video_decoder_init *init = arg; | 183 | struct video_decoder_init *init = arg; |
184 | struct video_decoder_init vdi; | ||
185 | |||
220 | if (NULL != init) | 186 | if (NULL != init) |
221 | return saa7111_init_decoder(client, init); | 187 | return saa7111_init_decoder(client, init); |
222 | else { | 188 | vdi.data = saa7111_i2c_init; |
223 | struct video_decoder_init vdi; | 189 | vdi.len = sizeof(saa7111_i2c_init); |
224 | vdi.data = saa7111_i2c_init; | 190 | return saa7111_init_decoder(client, &vdi); |
225 | vdi.len = sizeof(saa7111_i2c_init); | ||
226 | return saa7111_init_decoder(client, &vdi); | ||
227 | } | ||
228 | } | 191 | } |
229 | 192 | ||
230 | case DECODER_DUMP: | 193 | case DECODER_DUMP: |
@@ -234,15 +197,15 @@ saa7111_command (struct i2c_client *client, | |||
234 | for (i = 0; i < SAA7111_NR_REG; i += 16) { | 197 | for (i = 0; i < SAA7111_NR_REG; i += 16) { |
235 | int j; | 198 | int j; |
236 | 199 | ||
237 | printk(KERN_DEBUG "%s: %03x", I2C_NAME(client), i); | 200 | v4l_info(client, "%03x", i); |
238 | for (j = 0; j < 16 && i + j < SAA7111_NR_REG; ++j) { | 201 | for (j = 0; j < 16 && i + j < SAA7111_NR_REG; ++j) { |
239 | printk(" %02x", | 202 | printk(KERN_CONT " %02x", |
240 | saa7111_read(client, i + j)); | 203 | saa7111_read(client, i + j)); |
241 | } | 204 | } |
242 | printk("\n"); | 205 | printk(KERN_CONT "\n"); |
243 | } | 206 | } |
244 | } | ||
245 | break; | 207 | break; |
208 | } | ||
246 | 209 | ||
247 | case DECODER_GET_CAPABILITIES: | 210 | case DECODER_GET_CAPABILITIES: |
248 | { | 211 | { |
@@ -255,8 +218,8 @@ saa7111_command (struct i2c_client *client, | |||
255 | VIDEO_DECODER_CCIR; | 218 | VIDEO_DECODER_CCIR; |
256 | cap->inputs = 8; | 219 | cap->inputs = 8; |
257 | cap->outputs = 1; | 220 | cap->outputs = 1; |
258 | } | ||
259 | break; | 221 | break; |
222 | } | ||
260 | 223 | ||
261 | case DECODER_GET_STATUS: | 224 | case DECODER_GET_STATUS: |
262 | { | 225 | { |
@@ -265,8 +228,7 @@ saa7111_command (struct i2c_client *client, | |||
265 | int res; | 228 | int res; |
266 | 229 | ||
267 | status = saa7111_read(client, 0x1f); | 230 | status = saa7111_read(client, 0x1f); |
268 | dprintk(1, KERN_DEBUG "%s status: 0x%02x\n", I2C_NAME(client), | 231 | v4l_dbg(1, debug, client, "status: 0x%02x\n", status); |
269 | status); | ||
270 | res = 0; | 232 | res = 0; |
271 | if ((status & (1 << 6)) == 0) { | 233 | if ((status & (1 << 6)) == 0) { |
272 | res |= DECODER_STATUS_GOOD; | 234 | res |= DECODER_STATUS_GOOD; |
@@ -294,8 +256,8 @@ saa7111_command (struct i2c_client *client, | |||
294 | res |= DECODER_STATUS_COLOR; | 256 | res |= DECODER_STATUS_COLOR; |
295 | } | 257 | } |
296 | *iarg = res; | 258 | *iarg = res; |
297 | } | ||
298 | break; | 259 | break; |
260 | } | ||
299 | 261 | ||
300 | case DECODER_SET_GPIO: | 262 | case DECODER_SET_GPIO: |
301 | { | 263 | { |
@@ -362,8 +324,8 @@ saa7111_command (struct i2c_client *client, | |||
362 | 324 | ||
363 | } | 325 | } |
364 | decoder->norm = *iarg; | 326 | decoder->norm = *iarg; |
365 | } | ||
366 | break; | 327 | break; |
328 | } | ||
367 | 329 | ||
368 | case DECODER_SET_INPUT: | 330 | case DECODER_SET_INPUT: |
369 | { | 331 | { |
@@ -387,8 +349,8 @@ saa7111_command (struct i2c_client *client, | |||
387 | 3) ? 0x80 : | 349 | 3) ? 0x80 : |
388 | 0)); | 350 | 0)); |
389 | } | 351 | } |
390 | } | ||
391 | break; | 352 | break; |
353 | } | ||
392 | 354 | ||
393 | case DECODER_SET_OUTPUT: | 355 | case DECODER_SET_OUTPUT: |
394 | { | 356 | { |
@@ -398,8 +360,8 @@ saa7111_command (struct i2c_client *client, | |||
398 | if (*iarg != 0) { | 360 | if (*iarg != 0) { |
399 | return -EINVAL; | 361 | return -EINVAL; |
400 | } | 362 | } |
401 | } | ||
402 | break; | 363 | break; |
364 | } | ||
403 | 365 | ||
404 | case DECODER_ENABLE_OUTPUT: | 366 | case DECODER_ENABLE_OUTPUT: |
405 | { | 367 | { |
@@ -439,8 +401,8 @@ saa7111_command (struct i2c_client *client, | |||
439 | (decoder->reg[0x11] & 0xf3)); | 401 | (decoder->reg[0x11] & 0xf3)); |
440 | } | 402 | } |
441 | } | 403 | } |
442 | } | ||
443 | break; | 404 | break; |
405 | } | ||
444 | 406 | ||
445 | case DECODER_SET_PICTURE: | 407 | case DECODER_SET_PICTURE: |
446 | { | 408 | { |
@@ -454,8 +416,8 @@ saa7111_command (struct i2c_client *client, | |||
454 | saa7111_write(client, 0x0c, pic->colour >> 9); | 416 | saa7111_write(client, 0x0c, pic->colour >> 9); |
455 | /* We want -128 to 127 we get 0-65535 */ | 417 | /* We want -128 to 127 we get 0-65535 */ |
456 | saa7111_write(client, 0x0d, (pic->hue - 32768) >> 8); | 418 | saa7111_write(client, 0x0d, (pic->hue - 32768) >> 8); |
457 | } | ||
458 | break; | 419 | break; |
420 | } | ||
459 | 421 | ||
460 | default: | 422 | default: |
461 | return -EINVAL; | 423 | return -EINVAL; |
@@ -466,48 +428,23 @@ saa7111_command (struct i2c_client *client, | |||
466 | 428 | ||
467 | /* ----------------------------------------------------------------------- */ | 429 | /* ----------------------------------------------------------------------- */ |
468 | 430 | ||
469 | /* | 431 | static unsigned short normal_i2c[] = { 0x48 >> 1, I2C_CLIENT_END }; |
470 | * Generic i2c probe | ||
471 | * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' | ||
472 | */ | ||
473 | static unsigned short normal_i2c[] = { I2C_SAA7111 >> 1, I2C_CLIENT_END }; | ||
474 | |||
475 | static unsigned short ignore = I2C_CLIENT_END; | ||
476 | |||
477 | static struct i2c_client_address_data addr_data = { | ||
478 | .normal_i2c = normal_i2c, | ||
479 | .probe = &ignore, | ||
480 | .ignore = &ignore, | ||
481 | }; | ||
482 | 432 | ||
483 | static struct i2c_driver i2c_driver_saa7111; | 433 | I2C_CLIENT_INSMOD; |
484 | 434 | ||
485 | static int | 435 | static int saa7111_probe(struct i2c_client *client, |
486 | saa7111_detect_client (struct i2c_adapter *adapter, | 436 | const struct i2c_device_id *id) |
487 | int address, | ||
488 | int kind) | ||
489 | { | 437 | { |
490 | int i; | 438 | int i; |
491 | struct i2c_client *client; | ||
492 | struct saa7111 *decoder; | 439 | struct saa7111 *decoder; |
493 | struct video_decoder_init vdi; | 440 | struct video_decoder_init vdi; |
494 | 441 | ||
495 | dprintk(1, | ||
496 | KERN_INFO | ||
497 | "saa7111.c: detecting saa7111 client on address 0x%x\n", | ||
498 | address << 1); | ||
499 | |||
500 | /* Check if the adapter supports the needed features */ | 442 | /* Check if the adapter supports the needed features */ |
501 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 443 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
502 | return 0; | 444 | return -ENODEV; |
503 | 445 | ||
504 | client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); | 446 | v4l_info(client, "chip found @ 0x%x (%s)\n", |
505 | if (!client) | 447 | client->addr << 1, client->adapter->name); |
506 | return -ENOMEM; | ||
507 | client->addr = address; | ||
508 | client->adapter = adapter; | ||
509 | client->driver = &i2c_driver_saa7111; | ||
510 | strlcpy(I2C_NAME(client), "saa7111", sizeof(I2C_NAME(client))); | ||
511 | 448 | ||
512 | decoder = kzalloc(sizeof(struct saa7111), GFP_KERNEL); | 449 | decoder = kzalloc(sizeof(struct saa7111), GFP_KERNEL); |
513 | if (decoder == NULL) { | 450 | if (decoder == NULL) { |
@@ -519,82 +456,37 @@ saa7111_detect_client (struct i2c_adapter *adapter, | |||
519 | decoder->enable = 1; | 456 | decoder->enable = 1; |
520 | i2c_set_clientdata(client, decoder); | 457 | i2c_set_clientdata(client, decoder); |
521 | 458 | ||
522 | i = i2c_attach_client(client); | ||
523 | if (i) { | ||
524 | kfree(client); | ||
525 | kfree(decoder); | ||
526 | return i; | ||
527 | } | ||
528 | |||
529 | vdi.data = saa7111_i2c_init; | 459 | vdi.data = saa7111_i2c_init; |
530 | vdi.len = sizeof(saa7111_i2c_init); | 460 | vdi.len = sizeof(saa7111_i2c_init); |
531 | i = saa7111_init_decoder(client, &vdi); | 461 | i = saa7111_init_decoder(client, &vdi); |
532 | if (i < 0) { | 462 | if (i < 0) { |
533 | dprintk(1, KERN_ERR "%s_attach error: init status %d\n", | 463 | v4l_dbg(1, debug, client, "init status %d\n", i); |
534 | I2C_NAME(client), i); | ||
535 | } else { | 464 | } else { |
536 | dprintk(1, | 465 | v4l_dbg(1, debug, client, "revision %x\n", |
537 | KERN_INFO | 466 | saa7111_read(client, 0x00) >> 4); |
538 | "%s_attach: chip version %x at address 0x%x\n", | ||
539 | I2C_NAME(client), saa7111_read(client, 0x00) >> 4, | ||
540 | client->addr << 1); | ||
541 | } | 467 | } |
542 | |||
543 | return 0; | 468 | return 0; |
544 | } | 469 | } |
545 | 470 | ||
546 | static int | 471 | static int saa7111_remove(struct i2c_client *client) |
547 | saa7111_attach_adapter (struct i2c_adapter *adapter) | ||
548 | { | 472 | { |
549 | dprintk(1, | 473 | kfree(i2c_get_clientdata(client)); |
550 | KERN_INFO | ||
551 | "saa7111.c: starting probe for adapter %s (0x%x)\n", | ||
552 | I2C_NAME(adapter), adapter->id); | ||
553 | return i2c_probe(adapter, &addr_data, &saa7111_detect_client); | ||
554 | } | ||
555 | |||
556 | static int | ||
557 | saa7111_detach_client (struct i2c_client *client) | ||
558 | { | ||
559 | struct saa7111 *decoder = i2c_get_clientdata(client); | ||
560 | int err; | ||
561 | |||
562 | err = i2c_detach_client(client); | ||
563 | if (err) { | ||
564 | return err; | ||
565 | } | ||
566 | |||
567 | kfree(decoder); | ||
568 | kfree(client); | ||
569 | |||
570 | return 0; | 474 | return 0; |
571 | } | 475 | } |
572 | 476 | ||
573 | /* ----------------------------------------------------------------------- */ | 477 | /* ----------------------------------------------------------------------- */ |
574 | 478 | ||
575 | static struct i2c_driver i2c_driver_saa7111 = { | 479 | static const struct i2c_device_id saa7111_id[] = { |
576 | .driver = { | 480 | { "saa7111_old", 0 }, /* "saa7111" maps to the saa7115 driver */ |
577 | .name = "saa7111", | 481 | { } |
578 | }, | 482 | }; |
579 | 483 | MODULE_DEVICE_TABLE(i2c, saa7111_id); | |
580 | .id = I2C_DRIVERID_SAA7111A, | ||
581 | 484 | ||
582 | .attach_adapter = saa7111_attach_adapter, | 485 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
583 | .detach_client = saa7111_detach_client, | 486 | .name = "saa7111", |
487 | .driverid = I2C_DRIVERID_SAA7111A, | ||
584 | .command = saa7111_command, | 488 | .command = saa7111_command, |
489 | .probe = saa7111_probe, | ||
490 | .remove = saa7111_remove, | ||
491 | .id_table = saa7111_id, | ||
585 | }; | 492 | }; |
586 | |||
587 | static int __init | ||
588 | saa7111_init (void) | ||
589 | { | ||
590 | return i2c_add_driver(&i2c_driver_saa7111); | ||
591 | } | ||
592 | |||
593 | static void __exit | ||
594 | saa7111_exit (void) | ||
595 | { | ||
596 | i2c_del_driver(&i2c_driver_saa7111); | ||
597 | } | ||
598 | |||
599 | module_init(saa7111_init); | ||
600 | module_exit(saa7111_exit); | ||