aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2011-10-04 08:44:02 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-10-08 07:01:34 -0400
commit5d1ed98683abafef595b8e3a237f845b82152606 (patch)
tree823d8b53ddadc9c45308ee357e2fafb033d8be5e /drivers/media/video
parent8d6c0b216fd9a7f4b34aca6bd822756b9ef5690b (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.c20
-rw-r--r--drivers/media/video/msp3400-driver.h2
-rw-r--r--drivers/media/video/msp3400-kthreads.c86
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
429static 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
429static int msp_s_std(struct v4l2_subdev *sd, v4l2_std_id id) 443static 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
633static const struct v4l2_subdev_video_ops msp_video_ops = {
634 .querystd = msp_querystd,
635};
636
619static const struct v4l2_subdev_tuner_ops msp_tuner_ops = { 637static 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
631static const struct v4l2_subdev_ops msp_ops = { 649static 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
65static struct msp3400c_init_data_dem { 85static 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
179static 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
159static void msp_set_source(struct i2c_client *client, u16 src) 189static 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:
627no_second: 664no_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 */