diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-10-04 08:44:02 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-10-08 07:01:34 -0400 |
commit | 5d1ed98683abafef595b8e3a237f845b82152606 (patch) | |
tree | 823d8b53ddadc9c45308ee357e2fafb033d8be5e /drivers/media/video | |
parent | 8d6c0b216fd9a7f4b34aca6bd822756b9ef5690b (diff) |
[media] msp3400: Add standards detection to the driver
As msp3400 allows standards detection, add support for it. That
efectivelly means that devices with msp3400 can now implement
VIDIOC_QUERYSTD, and it will provide very good detection for
the standard, specially if combined with a video decoder detection.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/msp3400-driver.c | 20 | ||||
-rw-r--r-- | drivers/media/video/msp3400-driver.h | 2 | ||||
-rw-r--r-- | drivers/media/video/msp3400-kthreads.c | 86 |
3 files changed, 85 insertions, 23 deletions
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index c43c81f5f978..d0f538857285 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c | |||
@@ -426,6 +426,20 @@ static int msp_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq) | |||
426 | return 0; | 426 | return 0; |
427 | } | 427 | } |
428 | 428 | ||
429 | static int msp_querystd(struct v4l2_subdev *sd, v4l2_std_id *id) | ||
430 | { | ||
431 | struct msp_state *state = to_state(sd); | ||
432 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
433 | |||
434 | *id &= state->detected_std; | ||
435 | |||
436 | v4l_dbg(2, msp_debug, client, | ||
437 | "detected standard: %s(0x%08Lx)\n", | ||
438 | msp_standard_std_name(state->std), state->detected_std); | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | |||
429 | static int msp_s_std(struct v4l2_subdev *sd, v4l2_std_id id) | 443 | static int msp_s_std(struct v4l2_subdev *sd, v4l2_std_id id) |
430 | { | 444 | { |
431 | struct msp_state *state = to_state(sd); | 445 | struct msp_state *state = to_state(sd); |
@@ -616,6 +630,10 @@ static const struct v4l2_subdev_core_ops msp_core_ops = { | |||
616 | .s_std = msp_s_std, | 630 | .s_std = msp_s_std, |
617 | }; | 631 | }; |
618 | 632 | ||
633 | static const struct v4l2_subdev_video_ops msp_video_ops = { | ||
634 | .querystd = msp_querystd, | ||
635 | }; | ||
636 | |||
619 | static const struct v4l2_subdev_tuner_ops msp_tuner_ops = { | 637 | static const struct v4l2_subdev_tuner_ops msp_tuner_ops = { |
620 | .s_frequency = msp_s_frequency, | 638 | .s_frequency = msp_s_frequency, |
621 | .g_tuner = msp_g_tuner, | 639 | .g_tuner = msp_g_tuner, |
@@ -630,6 +648,7 @@ static const struct v4l2_subdev_audio_ops msp_audio_ops = { | |||
630 | 648 | ||
631 | static const struct v4l2_subdev_ops msp_ops = { | 649 | static const struct v4l2_subdev_ops msp_ops = { |
632 | .core = &msp_core_ops, | 650 | .core = &msp_core_ops, |
651 | .video = &msp_video_ops, | ||
633 | .tuner = &msp_tuner_ops, | 652 | .tuner = &msp_tuner_ops, |
634 | .audio = &msp_audio_ops, | 653 | .audio = &msp_audio_ops, |
635 | }; | 654 | }; |
@@ -664,6 +683,7 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
664 | v4l2_i2c_subdev_init(sd, client, &msp_ops); | 683 | v4l2_i2c_subdev_init(sd, client, &msp_ops); |
665 | 684 | ||
666 | state->v4l2_std = V4L2_STD_NTSC; | 685 | state->v4l2_std = V4L2_STD_NTSC; |
686 | state->detected_std = V4L2_STD_ALL; | ||
667 | state->audmode = V4L2_TUNER_MODE_STEREO; | 687 | state->audmode = V4L2_TUNER_MODE_STEREO; |
668 | state->input = -1; | 688 | state->input = -1; |
669 | state->i2s_mode = 0; | 689 | state->i2s_mode = 0; |
diff --git a/drivers/media/video/msp3400-driver.h b/drivers/media/video/msp3400-driver.h index 32a478e532f3..831e8db4368c 100644 --- a/drivers/media/video/msp3400-driver.h +++ b/drivers/media/video/msp3400-driver.h | |||
@@ -75,7 +75,7 @@ struct msp_state { | |||
75 | int opmode; | 75 | int opmode; |
76 | int std; | 76 | int std; |
77 | int mode; | 77 | int mode; |
78 | v4l2_std_id v4l2_std; | 78 | v4l2_std_id v4l2_std, detected_std; |
79 | int nicam_on; | 79 | int nicam_on; |
80 | int acb; | 80 | int acb; |
81 | int in_scart; | 81 | int in_scart; |
diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c index 80387e2c3eca..f8b51714f2f9 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/video/msp3400-kthreads.c | |||
@@ -37,29 +37,49 @@ static struct { | |||
37 | int retval; | 37 | int retval; |
38 | int main, second; | 38 | int main, second; |
39 | char *name; | 39 | char *name; |
40 | v4l2_std_id std; | ||
40 | } msp_stdlist[] = { | 41 | } msp_stdlist[] = { |
41 | { 0x0000, 0, 0, "could not detect sound standard" }, | 42 | { 0x0000, 0, 0, "could not detect sound standard", V4L2_STD_ALL }, |
42 | { 0x0001, 0, 0, "autodetect start" }, | 43 | { 0x0001, 0, 0, "autodetect start", V4L2_STD_ALL }, |
43 | { 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72), "4.5/4.72 M Dual FM-Stereo" }, | 44 | { 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72), |
44 | { 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875), "5.5/5.74 B/G Dual FM-Stereo" }, | 45 | "4.5/4.72 M Dual FM-Stereo", V4L2_STD_MN }, |
45 | { 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125), "6.5/6.25 D/K1 Dual FM-Stereo" }, | 46 | { 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875), |
46 | { 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875), "6.5/6.74 D/K2 Dual FM-Stereo" }, | 47 | "5.5/5.74 B/G Dual FM-Stereo", V4L2_STD_BG }, |
47 | { 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 D/K FM-Mono (HDEV3)" }, | 48 | { 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125), |
48 | { 0x0007, MSP_CARRIER(6.5), MSP_CARRIER(5.7421875), "6.5/5.74 D/K3 Dual FM-Stereo" }, | 49 | "6.5/6.25 D/K1 Dual FM-Stereo", V4L2_STD_DK }, |
49 | { 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), "5.5/5.85 B/G NICAM FM" }, | 50 | { 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875), |
50 | { 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 L NICAM AM" }, | 51 | "6.5/6.74 D/K2 Dual FM-Stereo", V4L2_STD_DK }, |
51 | { 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), "6.0/6.55 I NICAM FM" }, | 52 | { 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5), |
52 | { 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM" }, | 53 | "6.5 D/K FM-Mono (HDEV3)", V4L2_STD_DK }, |
53 | { 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV2)" }, | 54 | { 0x0007, MSP_CARRIER(6.5), MSP_CARRIER(5.7421875), |
54 | { 0x000d, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV3)" }, | 55 | "6.5/5.74 D/K3 Dual FM-Stereo", V4L2_STD_DK }, |
55 | { 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Stereo" }, | 56 | { 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), |
56 | { 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Mono + SAP" }, | 57 | "5.5/5.85 B/G NICAM FM", V4L2_STD_BG }, |
57 | { 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M EIA-J Japan Stereo" }, | 58 | { 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), |
58 | { 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7), "10.7 FM-Stereo Radio" }, | 59 | "6.5/5.85 L NICAM AM", V4L2_STD_L }, |
59 | { 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 SAT-Mono" }, | 60 | { 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), |
60 | { 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20), "7.02/7.20 SAT-Stereo" }, | 61 | "6.0/6.55 I NICAM FM", V4L2_STD_PAL_I }, |
61 | { 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2), "7.2 SAT ADR" }, | 62 | { 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), |
62 | { -1, 0, 0, NULL }, /* EOF */ | 63 | "6.5/5.85 D/K NICAM FM", V4L2_STD_DK }, |
64 | { 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), | ||
65 | "6.5/5.85 D/K NICAM FM (HDEV2)", V4L2_STD_DK }, | ||
66 | { 0x000d, MSP_CARRIER(6.5), MSP_CARRIER(5.85), | ||
67 | "6.5/5.85 D/K NICAM FM (HDEV3)", V4L2_STD_DK }, | ||
68 | { 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), | ||
69 | "4.5 M BTSC-Stereo", V4L2_STD_MTS }, | ||
70 | { 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), | ||
71 | "4.5 M BTSC-Mono + SAP", V4L2_STD_MTS }, | ||
72 | { 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), | ||
73 | "4.5 M EIA-J Japan Stereo", V4L2_STD_NTSC_M_JP }, | ||
74 | { 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7), | ||
75 | "10.7 FM-Stereo Radio", V4L2_STD_ALL }, | ||
76 | { 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5), | ||
77 | "6.5 SAT-Mono", V4L2_STD_ALL }, | ||
78 | { 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20), | ||
79 | "7.02/7.20 SAT-Stereo", V4L2_STD_ALL }, | ||
80 | { 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2), | ||
81 | "7.2 SAT ADR", V4L2_STD_ALL }, | ||
82 | { -1, 0, 0, NULL, 0 }, /* EOF */ | ||
63 | }; | 83 | }; |
64 | 84 | ||
65 | static struct msp3400c_init_data_dem { | 85 | static struct msp3400c_init_data_dem { |
@@ -156,6 +176,16 @@ const char *msp_standard_std_name(int std) | |||
156 | return "unknown"; | 176 | return "unknown"; |
157 | } | 177 | } |
158 | 178 | ||
179 | static v4l2_std_id msp_standard_std(int std) | ||
180 | { | ||
181 | int i; | ||
182 | |||
183 | for (i = 0; msp_stdlist[i].name != NULL; i++) | ||
184 | if (msp_stdlist[i].retval == std) | ||
185 | return msp_stdlist[i].std; | ||
186 | return V4L2_STD_ALL; | ||
187 | } | ||
188 | |||
159 | static void msp_set_source(struct i2c_client *client, u16 src) | 189 | static void msp_set_source(struct i2c_client *client, u16 src) |
160 | { | 190 | { |
161 | struct msp_state *state = to_state(i2c_get_clientdata(client)); | 191 | struct msp_state *state = to_state(i2c_get_clientdata(client)); |
@@ -479,6 +509,7 @@ int msp3400c_thread(void *data) | |||
479 | int count, max1, max2, val1, val2, val, i; | 509 | int count, max1, max2, val1, val2, val, i; |
480 | 510 | ||
481 | v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n"); | 511 | v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n"); |
512 | state->detected_std = V4L2_STD_ALL; | ||
482 | set_freezable(); | 513 | set_freezable(); |
483 | for (;;) { | 514 | for (;;) { |
484 | v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n"); | 515 | v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n"); |
@@ -579,6 +610,7 @@ restart: | |||
579 | state->main = msp3400c_carrier_detect_main[max1].cdo; | 610 | state->main = msp3400c_carrier_detect_main[max1].cdo; |
580 | switch (max1) { | 611 | switch (max1) { |
581 | case 1: /* 5.5 */ | 612 | case 1: /* 5.5 */ |
613 | state->detected_std = V4L2_STD_BG | V4L2_STD_PAL_H; | ||
582 | if (max2 == 0) { | 614 | if (max2 == 0) { |
583 | /* B/G FM-stereo */ | 615 | /* B/G FM-stereo */ |
584 | state->second = msp3400c_carrier_detect_55[max2].cdo; | 616 | state->second = msp3400c_carrier_detect_55[max2].cdo; |
@@ -596,6 +628,7 @@ restart: | |||
596 | break; | 628 | break; |
597 | case 2: /* 6.0 */ | 629 | case 2: /* 6.0 */ |
598 | /* PAL I NICAM */ | 630 | /* PAL I NICAM */ |
631 | state->detected_std = V4L2_STD_PAL_I; | ||
599 | state->second = MSP_CARRIER(6.552); | 632 | state->second = MSP_CARRIER(6.552); |
600 | msp3400c_set_mode(client, MSP_MODE_FM_NICAM2); | 633 | msp3400c_set_mode(client, MSP_MODE_FM_NICAM2); |
601 | state->nicam_on = 1; | 634 | state->nicam_on = 1; |
@@ -607,22 +640,26 @@ restart: | |||
607 | state->second = msp3400c_carrier_detect_65[max2].cdo; | 640 | state->second = msp3400c_carrier_detect_65[max2].cdo; |
608 | msp3400c_set_mode(client, MSP_MODE_FM_TERRA); | 641 | msp3400c_set_mode(client, MSP_MODE_FM_TERRA); |
609 | state->watch_stereo = 1; | 642 | state->watch_stereo = 1; |
643 | state->detected_std = V4L2_STD_DK; | ||
610 | } else if (max2 == 0 && (state->v4l2_std & V4L2_STD_SECAM)) { | 644 | } else if (max2 == 0 && (state->v4l2_std & V4L2_STD_SECAM)) { |
611 | /* L NICAM or AM-mono */ | 645 | /* L NICAM or AM-mono */ |
612 | state->second = msp3400c_carrier_detect_65[max2].cdo; | 646 | state->second = msp3400c_carrier_detect_65[max2].cdo; |
613 | msp3400c_set_mode(client, MSP_MODE_AM_NICAM); | 647 | msp3400c_set_mode(client, MSP_MODE_AM_NICAM); |
614 | state->watch_stereo = 1; | 648 | state->watch_stereo = 1; |
649 | state->detected_std = V4L2_STD_L; | ||
615 | } else if (max2 == 0 && state->has_nicam) { | 650 | } else if (max2 == 0 && state->has_nicam) { |
616 | /* D/K NICAM */ | 651 | /* D/K NICAM */ |
617 | state->second = msp3400c_carrier_detect_65[max2].cdo; | 652 | state->second = msp3400c_carrier_detect_65[max2].cdo; |
618 | msp3400c_set_mode(client, MSP_MODE_FM_NICAM1); | 653 | msp3400c_set_mode(client, MSP_MODE_FM_NICAM1); |
619 | state->nicam_on = 1; | 654 | state->nicam_on = 1; |
620 | state->watch_stereo = 1; | 655 | state->watch_stereo = 1; |
656 | state->detected_std = V4L2_STD_DK; | ||
621 | } else { | 657 | } else { |
622 | goto no_second; | 658 | goto no_second; |
623 | } | 659 | } |
624 | break; | 660 | break; |
625 | case 0: /* 4.5 */ | 661 | case 0: /* 4.5 */ |
662 | state->detected_std = V4L2_STD_MN; | ||
626 | default: | 663 | default: |
627 | no_second: | 664 | no_second: |
628 | state->second = msp3400c_carrier_detect_main[max1].cdo; | 665 | state->second = msp3400c_carrier_detect_main[max1].cdo; |
@@ -662,6 +699,7 @@ int msp3410d_thread(void *data) | |||
662 | int val, i, std, count; | 699 | int val, i, std, count; |
663 | 700 | ||
664 | v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n"); | 701 | v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n"); |
702 | state->detected_std = V4L2_STD_ALL; | ||
665 | set_freezable(); | 703 | set_freezable(); |
666 | for (;;) { | 704 | for (;;) { |
667 | v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n"); | 705 | v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n"); |
@@ -743,6 +781,8 @@ restart: | |||
743 | msp_stdlist[8].name : "unknown", val); | 781 | msp_stdlist[8].name : "unknown", val); |
744 | state->std = val = 0x0009; | 782 | state->std = val = 0x0009; |
745 | msp_write_dem(client, 0x20, val); | 783 | msp_write_dem(client, 0x20, val); |
784 | } else { | ||
785 | state->detected_std = msp_standard_std(state->std); | ||
746 | } | 786 | } |
747 | 787 | ||
748 | /* set stereo */ | 788 | /* set stereo */ |
@@ -957,6 +997,7 @@ int msp34xxg_thread(void *data) | |||
957 | int val, i; | 997 | int val, i; |
958 | 998 | ||
959 | v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n"); | 999 | v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n"); |
1000 | state->detected_std = V4L2_STD_ALL; | ||
960 | set_freezable(); | 1001 | set_freezable(); |
961 | for (;;) { | 1002 | for (;;) { |
962 | v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n"); | 1003 | v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n"); |
@@ -1013,6 +1054,7 @@ unmute: | |||
1013 | v4l_dbg(1, msp_debug, client, | 1054 | v4l_dbg(1, msp_debug, client, |
1014 | "detected standard: %s (0x%04x)\n", | 1055 | "detected standard: %s (0x%04x)\n", |
1015 | msp_standard_std_name(state->std), state->std); | 1056 | msp_standard_std_name(state->std), state->std); |
1057 | state->detected_std = msp_standard_std(state->std); | ||
1016 | 1058 | ||
1017 | if (state->std == 9) { | 1059 | if (state->std == 9) { |
1018 | /* AM NICAM mode */ | 1060 | /* AM NICAM mode */ |