diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2008-08-08 11:43:59 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-10-12 07:36:48 -0400 |
commit | e281db5862743dbe1dab7f8fb423e699537036ee (patch) | |
tree | ef1e74bc538cd820d5ae2f64728a7388f7666a69 /drivers/media/video/saa7134 | |
parent | 1e55126666944c83bf98243564e25302f363e2a4 (diff) |
V4L/DVB (8639): saa6752hs: cleanup and add AC-3 support
Cleaned up the saa6752hs i2c driver.
Add AC-3 support.
Add VIDIOC_CHIP_IDENT support.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/saa7134')
-rw-r--r-- | drivers/media/video/saa7134/saa6752hs.c | 265 | ||||
-rw-r--r-- | drivers/media/video/saa7134/saa7134-empress.c | 22 |
2 files changed, 185 insertions, 102 deletions
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index 707be175509d..ca725a74ce6a 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c | |||
@@ -1,3 +1,27 @@ | |||
1 | /* | ||
2 | saa6752hs - i2c-driver for the saa6752hs by Philips | ||
3 | |||
4 | Copyright (C) 2004 Andrew de Quincey | ||
5 | |||
6 | AC-3 support: | ||
7 | |||
8 | Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl> | ||
9 | |||
10 | This program is free software; you can redistribute it and/or modify | ||
11 | it under the terms of the GNU General Public License vs published by | ||
12 | the Free Software Foundation; either version 2 of the License, or | ||
13 | (at your option) any later version. | ||
14 | |||
15 | This program is distributed in the hope that it will be useful, | ||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | GNU General Public License for more details. | ||
19 | |||
20 | You should have received a copy of the GNU General Public License | ||
21 | along with this program; if not, write to the Free Software | ||
22 | Foundation, Inc., 675 Mvss Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
1 | #include <linux/module.h> | 25 | #include <linux/module.h> |
2 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
3 | #include <linux/string.h> | 27 | #include <linux/string.h> |
@@ -10,6 +34,8 @@ | |||
10 | #include <linux/types.h> | 34 | #include <linux/types.h> |
11 | #include <linux/videodev2.h> | 35 | #include <linux/videodev2.h> |
12 | #include <media/v4l2-common.h> | 36 | #include <media/v4l2-common.h> |
37 | #include <media/v4l2-chip-ident.h> | ||
38 | #include <media/v4l2-i2c-drv-legacy.h> | ||
13 | #include <linux/init.h> | 39 | #include <linux/init.h> |
14 | #include <linux/crc32.h> | 40 | #include <linux/crc32.h> |
15 | 41 | ||
@@ -27,9 +53,6 @@ MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder"); | |||
27 | MODULE_AUTHOR("Andrew de Quincey"); | 53 | MODULE_AUTHOR("Andrew de Quincey"); |
28 | MODULE_LICENSE("GPL"); | 54 | MODULE_LICENSE("GPL"); |
29 | 55 | ||
30 | static struct i2c_driver driver; | ||
31 | static struct i2c_client client_template; | ||
32 | |||
33 | enum saa6752hs_videoformat { | 56 | enum saa6752hs_videoformat { |
34 | SAA6752HS_VF_D1 = 0, /* standard D1 video format: 720x576 */ | 57 | SAA6752HS_VF_D1 = 0, /* standard D1 video format: 720x576 */ |
35 | SAA6752HS_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */ | 58 | SAA6752HS_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */ |
@@ -46,7 +69,9 @@ struct saa6752hs_mpeg_params { | |||
46 | __u16 ts_pid_pcr; | 69 | __u16 ts_pid_pcr; |
47 | 70 | ||
48 | /* audio */ | 71 | /* audio */ |
49 | enum v4l2_mpeg_audio_l2_bitrate au_l2_bitrate; | 72 | enum v4l2_mpeg_audio_encoding au_encoding; |
73 | enum v4l2_mpeg_audio_l2_bitrate au_l2_bitrate; | ||
74 | enum v4l2_mpeg_audio_ac3_bitrate au_ac3_bitrate; | ||
50 | 75 | ||
51 | /* video */ | 76 | /* video */ |
52 | enum v4l2_mpeg_video_aspect vi_aspect; | 77 | enum v4l2_mpeg_video_aspect vi_aspect; |
@@ -70,7 +95,9 @@ static const struct v4l2_format v4l2_format_table[] = | |||
70 | }; | 95 | }; |
71 | 96 | ||
72 | struct saa6752hs_state { | 97 | struct saa6752hs_state { |
73 | struct i2c_client client; | 98 | int chip; |
99 | u32 revision; | ||
100 | int has_ac3; | ||
74 | struct saa6752hs_mpeg_params params; | 101 | struct saa6752hs_mpeg_params params; |
75 | enum saa6752hs_videoformat video_format; | 102 | enum saa6752hs_videoformat video_format; |
76 | v4l2_std_id standard; | 103 | v4l2_std_id standard; |
@@ -157,7 +184,9 @@ static struct saa6752hs_mpeg_params param_defaults = | |||
157 | .vi_bitrate_peak = 6000, | 184 | .vi_bitrate_peak = 6000, |
158 | .vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, | 185 | .vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, |
159 | 186 | ||
187 | .au_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2, | ||
160 | .au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_256K, | 188 | .au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_256K, |
189 | .au_ac3_bitrate = V4L2_MPEG_AUDIO_AC3_BITRATE_384K, | ||
161 | }; | 190 | }; |
162 | 191 | ||
163 | /* ---------------------------------------------------------------------- */ | 192 | /* ---------------------------------------------------------------------- */ |
@@ -230,8 +259,9 @@ static int saa6752hs_chip_command(struct i2c_client* client, | |||
230 | 259 | ||
231 | 260 | ||
232 | static int saa6752hs_set_bitrate(struct i2c_client* client, | 261 | static int saa6752hs_set_bitrate(struct i2c_client* client, |
233 | struct saa6752hs_mpeg_params* params) | 262 | struct saa6752hs_state *h) |
234 | { | 263 | { |
264 | struct saa6752hs_mpeg_params *params = &h->params; | ||
235 | u8 buf[3]; | 265 | u8 buf[3]; |
236 | int tot_bitrate; | 266 | int tot_bitrate; |
237 | 267 | ||
@@ -263,11 +293,22 @@ static int saa6752hs_set_bitrate(struct i2c_client* client, | |||
263 | tot_bitrate = params->vi_bitrate; | 293 | tot_bitrate = params->vi_bitrate; |
264 | } | 294 | } |
265 | 295 | ||
296 | /* set the audio encoding */ | ||
297 | buf[0] = 0x93; | ||
298 | if (params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) | ||
299 | buf[1] = 1; | ||
300 | else | ||
301 | buf[1] = 0; | ||
302 | i2c_master_send(client, buf, 2); | ||
303 | |||
266 | /* set the audio bitrate */ | 304 | /* set the audio bitrate */ |
267 | buf[0] = 0x94; | 305 | buf[0] = 0x94; |
268 | buf[1] = (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 0 : 1; | 306 | if (params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) |
307 | buf[1] = V4L2_MPEG_AUDIO_AC3_BITRATE_384K == params->au_ac3_bitrate; | ||
308 | else | ||
309 | buf[1] = V4L2_MPEG_AUDIO_L2_BITRATE_384K == params->au_l2_bitrate; | ||
310 | tot_bitrate += buf[1] ? 384 : 256; | ||
269 | i2c_master_send(client, buf, 2); | 311 | i2c_master_send(client, buf, 2); |
270 | tot_bitrate += (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 256 : 384; | ||
271 | 312 | ||
272 | /* Note: the total max bitrate is determined by adding the video and audio | 313 | /* Note: the total max bitrate is determined by adding the video and audio |
273 | bitrates together and also adding an extra 768kbit/s to stay on the | 314 | bitrates together and also adding an extra 768kbit/s to stay on the |
@@ -332,7 +373,7 @@ static void saa6752hs_set_subsampling(struct i2c_client* client, | |||
332 | } | 373 | } |
333 | 374 | ||
334 | 375 | ||
335 | static int handle_ctrl(struct saa6752hs_mpeg_params *params, | 376 | static int handle_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params, |
336 | struct v4l2_ext_control *ctrl, unsigned int cmd) | 377 | struct v4l2_ext_control *ctrl, unsigned int cmd) |
337 | { | 378 | { |
338 | int old = 0, new; | 379 | int old = 0, new; |
@@ -379,8 +420,9 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params, | |||
379 | params->ts_pid_pcr = new; | 420 | params->ts_pid_pcr = new; |
380 | break; | 421 | break; |
381 | case V4L2_CID_MPEG_AUDIO_ENCODING: | 422 | case V4L2_CID_MPEG_AUDIO_ENCODING: |
382 | old = V4L2_MPEG_AUDIO_ENCODING_LAYER_2; | 423 | old = params->au_encoding; |
383 | if (set && new != old) | 424 | if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 && |
425 | (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3)) | ||
384 | return -ERANGE; | 426 | return -ERANGE; |
385 | new = old; | 427 | new = old; |
386 | break; | 428 | break; |
@@ -395,6 +437,19 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params, | |||
395 | new = V4L2_MPEG_AUDIO_L2_BITRATE_384K; | 437 | new = V4L2_MPEG_AUDIO_L2_BITRATE_384K; |
396 | params->au_l2_bitrate = new; | 438 | params->au_l2_bitrate = new; |
397 | break; | 439 | break; |
440 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: | ||
441 | if (!has_ac3) | ||
442 | return -EINVAL; | ||
443 | old = params->au_ac3_bitrate; | ||
444 | if (set && new != V4L2_MPEG_AUDIO_AC3_BITRATE_256K && | ||
445 | new != V4L2_MPEG_AUDIO_AC3_BITRATE_384K) | ||
446 | return -ERANGE; | ||
447 | if (new <= V4L2_MPEG_AUDIO_AC3_BITRATE_256K) | ||
448 | new = V4L2_MPEG_AUDIO_AC3_BITRATE_256K; | ||
449 | else | ||
450 | new = V4L2_MPEG_AUDIO_AC3_BITRATE_384K; | ||
451 | params->au_ac3_bitrate = new; | ||
452 | break; | ||
398 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | 453 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: |
399 | old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; | 454 | old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; |
400 | if (set && new != old) | 455 | if (set && new != old) |
@@ -448,17 +503,19 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params, | |||
448 | return 0; | 503 | return 0; |
449 | } | 504 | } |
450 | 505 | ||
451 | static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params, | 506 | static int saa6752hs_qctrl(struct saa6752hs_state *h, |
452 | struct v4l2_queryctrl *qctrl) | 507 | struct v4l2_queryctrl *qctrl) |
453 | { | 508 | { |
509 | struct saa6752hs_mpeg_params *params = &h->params; | ||
454 | int err; | 510 | int err; |
455 | 511 | ||
456 | switch (qctrl->id) { | 512 | switch (qctrl->id) { |
457 | case V4L2_CID_MPEG_AUDIO_ENCODING: | 513 | case V4L2_CID_MPEG_AUDIO_ENCODING: |
458 | return v4l2_ctrl_query_fill(qctrl, | 514 | return v4l2_ctrl_query_fill(qctrl, |
459 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, | 515 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, |
460 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1, | 516 | h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 : |
461 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2); | 517 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, |
518 | 1, V4L2_MPEG_AUDIO_ENCODING_LAYER_2); | ||
462 | 519 | ||
463 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: | 520 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: |
464 | return v4l2_ctrl_query_fill(qctrl, | 521 | return v4l2_ctrl_query_fill(qctrl, |
@@ -466,6 +523,14 @@ static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params, | |||
466 | V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, | 523 | V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, |
467 | V4L2_MPEG_AUDIO_L2_BITRATE_256K); | 524 | V4L2_MPEG_AUDIO_L2_BITRATE_256K); |
468 | 525 | ||
526 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: | ||
527 | if (!h->has_ac3) | ||
528 | return -EINVAL; | ||
529 | return v4l2_ctrl_query_fill(qctrl, | ||
530 | V4L2_MPEG_AUDIO_AC3_BITRATE_256K, | ||
531 | V4L2_MPEG_AUDIO_AC3_BITRATE_384K, 1, | ||
532 | V4L2_MPEG_AUDIO_AC3_BITRATE_256K); | ||
533 | |||
469 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | 534 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: |
470 | return v4l2_ctrl_query_fill(qctrl, | 535 | return v4l2_ctrl_query_fill(qctrl, |
471 | V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, | 536 | V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, |
@@ -512,38 +577,50 @@ static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params, | |||
512 | return -EINVAL; | 577 | return -EINVAL; |
513 | } | 578 | } |
514 | 579 | ||
515 | static int saa6752hs_qmenu(struct saa6752hs_mpeg_params *params, | 580 | static int saa6752hs_qmenu(struct saa6752hs_state *h, |
516 | struct v4l2_querymenu *qmenu) | 581 | struct v4l2_querymenu *qmenu) |
517 | { | 582 | { |
518 | static const char *mpeg_audio_l2_bitrate[] = { | 583 | static const u32 mpeg_audio_encoding[] = { |
519 | "", | 584 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, |
520 | "", | 585 | V4L2_CTRL_MENU_IDS_END |
521 | "", | 586 | }; |
522 | "", | 587 | static const u32 mpeg_audio_ac3_encoding[] = { |
523 | "", | 588 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, |
524 | "", | 589 | V4L2_MPEG_AUDIO_ENCODING_AC3, |
525 | "", | 590 | V4L2_CTRL_MENU_IDS_END |
526 | "", | 591 | }; |
527 | "", | 592 | static u32 mpeg_audio_l2_bitrate[] = { |
528 | "", | 593 | V4L2_MPEG_AUDIO_L2_BITRATE_256K, |
529 | "", | 594 | V4L2_MPEG_AUDIO_L2_BITRATE_384K, |
530 | "256 kbps", | 595 | V4L2_CTRL_MENU_IDS_END |
531 | "", | 596 | }; |
532 | "384 kbps", | 597 | static u32 mpeg_audio_ac3_bitrate[] = { |
533 | NULL | 598 | V4L2_MPEG_AUDIO_AC3_BITRATE_256K, |
599 | V4L2_MPEG_AUDIO_AC3_BITRATE_384K, | ||
600 | V4L2_CTRL_MENU_IDS_END | ||
534 | }; | 601 | }; |
535 | struct v4l2_queryctrl qctrl; | 602 | struct v4l2_queryctrl qctrl; |
536 | int err; | 603 | int err; |
537 | 604 | ||
538 | qctrl.id = qmenu->id; | 605 | qctrl.id = qmenu->id; |
539 | err = saa6752hs_qctrl(params, &qctrl); | 606 | err = saa6752hs_qctrl(h, &qctrl); |
540 | if (err) | 607 | if (err) |
541 | return err; | 608 | return err; |
542 | if (qmenu->id == V4L2_CID_MPEG_AUDIO_L2_BITRATE) | 609 | switch (qmenu->id) { |
543 | return v4l2_ctrl_query_menu(qmenu, &qctrl, | 610 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: |
611 | return v4l2_ctrl_query_menu_valid_items(qmenu, | ||
544 | mpeg_audio_l2_bitrate); | 612 | mpeg_audio_l2_bitrate); |
545 | return v4l2_ctrl_query_menu(qmenu, &qctrl, | 613 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: |
546 | v4l2_ctrl_get_menu(qmenu->id)); | 614 | if (!h->has_ac3) |
615 | return -EINVAL; | ||
616 | return v4l2_ctrl_query_menu_valid_items(qmenu, | ||
617 | mpeg_audio_ac3_bitrate); | ||
618 | case V4L2_CID_MPEG_AUDIO_ENCODING: | ||
619 | return v4l2_ctrl_query_menu_valid_items(qmenu, | ||
620 | h->has_ac3 ? mpeg_audio_ac3_encoding : | ||
621 | mpeg_audio_encoding); | ||
622 | } | ||
623 | return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL); | ||
547 | } | 624 | } |
548 | 625 | ||
549 | static int saa6752hs_init(struct i2c_client* client) | 626 | static int saa6752hs_init(struct i2c_client* client) |
@@ -569,7 +646,7 @@ static int saa6752hs_init(struct i2c_client* client) | |||
569 | i2c_master_send(client, buf, 2); | 646 | i2c_master_send(client, buf, 2); |
570 | 647 | ||
571 | /* set bitrate */ | 648 | /* set bitrate */ |
572 | saa6752hs_set_bitrate(client, &h->params); | 649 | saa6752hs_set_bitrate(client, h); |
573 | 650 | ||
574 | /* Set GOP structure {3, 13} */ | 651 | /* Set GOP structure {3, 13} */ |
575 | buf[0] = 0x72; | 652 | buf[0] = 0x72; |
@@ -688,45 +765,6 @@ static int saa6752hs_init(struct i2c_client* client) | |||
688 | return 0; | 765 | return 0; |
689 | } | 766 | } |
690 | 767 | ||
691 | static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind) | ||
692 | { | ||
693 | struct saa6752hs_state *h; | ||
694 | |||
695 | |||
696 | if (NULL == (h = kzalloc(sizeof(*h), GFP_KERNEL))) | ||
697 | return -ENOMEM; | ||
698 | h->client = client_template; | ||
699 | h->params = param_defaults; | ||
700 | h->client.adapter = adap; | ||
701 | h->client.addr = addr; | ||
702 | |||
703 | /* Assume 625 input lines */ | ||
704 | h->standard = 0; | ||
705 | |||
706 | i2c_set_clientdata(&h->client, h); | ||
707 | i2c_attach_client(&h->client); | ||
708 | |||
709 | v4l_info(&h->client,"saa6752hs: chip found @ 0x%x\n", addr<<1); | ||
710 | return 0; | ||
711 | } | ||
712 | |||
713 | static int saa6752hs_probe(struct i2c_adapter *adap) | ||
714 | { | ||
715 | if (adap->class & I2C_CLASS_TV_ANALOG) | ||
716 | return i2c_probe(adap, &addr_data, saa6752hs_attach); | ||
717 | return 0; | ||
718 | } | ||
719 | |||
720 | static int saa6752hs_detach(struct i2c_client *client) | ||
721 | { | ||
722 | struct saa6752hs_state *h; | ||
723 | |||
724 | h = i2c_get_clientdata(client); | ||
725 | i2c_detach_client(client); | ||
726 | kfree(h); | ||
727 | return 0; | ||
728 | } | ||
729 | |||
730 | static int | 768 | static int |
731 | saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) | 769 | saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) |
732 | { | 770 | { |
@@ -752,7 +790,8 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
752 | return -EINVAL; | 790 | return -EINVAL; |
753 | params = h->params; | 791 | params = h->params; |
754 | for (i = 0; i < ctrls->count; i++) { | 792 | for (i = 0; i < ctrls->count; i++) { |
755 | if ((err = handle_ctrl(¶ms, ctrls->controls + i, cmd))) { | 793 | err = handle_ctrl(h->has_ac3, ¶ms, ctrls->controls + i, cmd); |
794 | if (err) { | ||
756 | ctrls->error_idx = i; | 795 | ctrls->error_idx = i; |
757 | return err; | 796 | return err; |
758 | } | 797 | } |
@@ -760,9 +799,9 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
760 | h->params = params; | 799 | h->params = params; |
761 | break; | 800 | break; |
762 | case VIDIOC_QUERYCTRL: | 801 | case VIDIOC_QUERYCTRL: |
763 | return saa6752hs_qctrl(&h->params, arg); | 802 | return saa6752hs_qctrl(h, arg); |
764 | case VIDIOC_QUERYMENU: | 803 | case VIDIOC_QUERYMENU: |
765 | return saa6752hs_qmenu(&h->params, arg); | 804 | return saa6752hs_qmenu(h, arg); |
766 | case VIDIOC_G_FMT: | 805 | case VIDIOC_G_FMT: |
767 | { | 806 | { |
768 | struct v4l2_format *f = arg; | 807 | struct v4l2_format *f = arg; |
@@ -785,6 +824,11 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
785 | case VIDIOC_S_STD: | 824 | case VIDIOC_S_STD: |
786 | h->standard = *((v4l2_std_id *) arg); | 825 | h->standard = *((v4l2_std_id *) arg); |
787 | break; | 826 | break; |
827 | |||
828 | case VIDIOC_G_CHIP_IDENT: | ||
829 | return v4l2_chip_ident_i2c_client(client, | ||
830 | arg, h->chip, h->revision); | ||
831 | |||
788 | default: | 832 | default: |
789 | /* nothing */ | 833 | /* nothing */ |
790 | break; | 834 | break; |
@@ -793,36 +837,55 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
793 | return err; | 837 | return err; |
794 | } | 838 | } |
795 | 839 | ||
796 | /* ----------------------------------------------------------------------- */ | 840 | static int saa6752hs_probe(struct i2c_client *client, |
841 | const struct i2c_device_id *id) | ||
842 | { | ||
843 | struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL); | ||
844 | u8 addr = 0x13; | ||
845 | u8 data[12]; | ||
797 | 846 | ||
798 | static struct i2c_driver driver = { | 847 | v4l_info(client, "chip found @ 0x%x (%s)\n", |
799 | .driver = { | 848 | client->addr << 1, client->adapter->name); |
800 | .name = "saa6752hs", | 849 | if (h == NULL) |
801 | }, | 850 | return -ENOMEM; |
802 | .id = I2C_DRIVERID_SAA6752HS, | ||
803 | .attach_adapter = saa6752hs_probe, | ||
804 | .detach_client = saa6752hs_detach, | ||
805 | .command = saa6752hs_command, | ||
806 | }; | ||
807 | 851 | ||
808 | static struct i2c_client client_template = | 852 | i2c_master_send(client, &addr, 1); |
809 | { | 853 | i2c_master_recv(client, data, sizeof(data)); |
810 | .name = "saa6752hs", | 854 | h->chip = V4L2_IDENT_SAA6752HS; |
811 | .driver = &driver, | 855 | h->revision = (data[8] << 8) | data[9]; |
812 | }; | 856 | h->has_ac3 = 0; |
857 | if (h->revision == 0x0206) { | ||
858 | h->chip = V4L2_IDENT_SAA6752HS_AC3; | ||
859 | h->has_ac3 = 1; | ||
860 | v4l_info(client, "support AC-3\n"); | ||
861 | } | ||
862 | h->params = param_defaults; | ||
863 | h->standard = 0; /* Assume 625 input lines */ | ||
813 | 864 | ||
814 | static int __init saa6752hs_init_module(void) | 865 | i2c_set_clientdata(client, h); |
815 | { | 866 | return 0; |
816 | return i2c_add_driver(&driver); | ||
817 | } | 867 | } |
818 | 868 | ||
819 | static void __exit saa6752hs_cleanup_module(void) | 869 | static int saa6752hs_remove(struct i2c_client *client) |
820 | { | 870 | { |
821 | i2c_del_driver(&driver); | 871 | kfree(i2c_get_clientdata(client)); |
872 | return 0; | ||
822 | } | 873 | } |
823 | 874 | ||
824 | module_init(saa6752hs_init_module); | 875 | static const struct i2c_device_id saa6752hs_id[] = { |
825 | module_exit(saa6752hs_cleanup_module); | 876 | { "saa6752hs", 0 }, |
877 | { } | ||
878 | }; | ||
879 | MODULE_DEVICE_TABLE(i2c, saa6752hs_id); | ||
880 | |||
881 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | ||
882 | .name = "saa6752hs", | ||
883 | .driverid = I2C_DRIVERID_SAA6752HS, | ||
884 | .command = saa6752hs_command, | ||
885 | .probe = saa6752hs_probe, | ||
886 | .remove = saa6752hs_remove, | ||
887 | .id_table = saa6752hs_id, | ||
888 | }; | ||
826 | 889 | ||
827 | /* | 890 | /* |
828 | * Overrides for Emacs so that we follow Linus's tabbing style. | 891 | * Overrides for Emacs so that we follow Linus's tabbing style. |
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 6f423d116fb4..f5a186a13db2 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c | |||
@@ -29,6 +29,7 @@ | |||
29 | 29 | ||
30 | #include <media/saa6752hs.h> | 30 | #include <media/saa6752hs.h> |
31 | #include <media/v4l2-common.h> | 31 | #include <media/v4l2-common.h> |
32 | #include <media/v4l2-chip-ident.h> | ||
32 | 33 | ||
33 | /* ------------------------------------------------------------------ */ | 34 | /* ------------------------------------------------------------------ */ |
34 | 35 | ||
@@ -403,6 +404,25 @@ static int empress_querymenu(struct file *file, void *priv, | |||
403 | return saa7134_i2c_call_saa6752(dev, VIDIOC_QUERYMENU, c); | 404 | return saa7134_i2c_call_saa6752(dev, VIDIOC_QUERYMENU, c); |
404 | } | 405 | } |
405 | 406 | ||
407 | static int empress_g_chip_ident(struct file *file, void *fh, | ||
408 | struct v4l2_chip_ident *chip) | ||
409 | { | ||
410 | struct saa7134_dev *dev = file->private_data; | ||
411 | |||
412 | chip->ident = V4L2_IDENT_NONE; | ||
413 | chip->revision = 0; | ||
414 | if (dev->mpeg_i2c_client == NULL) | ||
415 | return -EINVAL; | ||
416 | if (chip->match_type == V4L2_CHIP_MATCH_I2C_DRIVER && | ||
417 | chip->match_chip == I2C_DRIVERID_SAA6752HS) | ||
418 | return saa7134_i2c_call_saa6752(dev, VIDIOC_G_CHIP_IDENT, chip); | ||
419 | if (chip->match_type == V4L2_CHIP_MATCH_I2C_ADDR && | ||
420 | chip->match_chip == dev->mpeg_i2c_client->addr) | ||
421 | return saa7134_i2c_call_saa6752(dev, VIDIOC_G_CHIP_IDENT, chip); | ||
422 | return -EINVAL; | ||
423 | } | ||
424 | |||
425 | |||
406 | static const struct file_operations ts_fops = | 426 | static const struct file_operations ts_fops = |
407 | { | 427 | { |
408 | .owner = THIS_MODULE, | 428 | .owner = THIS_MODULE, |
@@ -431,11 +451,11 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = { | |||
431 | .vidioc_enum_input = empress_enum_input, | 451 | .vidioc_enum_input = empress_enum_input, |
432 | .vidioc_g_input = empress_g_input, | 452 | .vidioc_g_input = empress_g_input, |
433 | .vidioc_s_input = empress_s_input, | 453 | .vidioc_s_input = empress_s_input, |
434 | |||
435 | .vidioc_queryctrl = empress_queryctrl, | 454 | .vidioc_queryctrl = empress_queryctrl, |
436 | .vidioc_querymenu = empress_querymenu, | 455 | .vidioc_querymenu = empress_querymenu, |
437 | .vidioc_g_ctrl = empress_g_ctrl, | 456 | .vidioc_g_ctrl = empress_g_ctrl, |
438 | .vidioc_s_ctrl = empress_s_ctrl, | 457 | .vidioc_s_ctrl = empress_s_ctrl, |
458 | .vidioc_g_chip_ident = empress_g_chip_ident, | ||
439 | }; | 459 | }; |
440 | 460 | ||
441 | /* ----------------------------------------------------------- */ | 461 | /* ----------------------------------------------------------- */ |