Commit 5d1ed986 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

[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: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 8d6c0b21
...@@ -426,6 +426,20 @@ static int msp_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq) ...@@ -426,6 +426,20 @@ static int msp_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq)
return 0; return 0;
} }
static int msp_querystd(struct v4l2_subdev *sd, v4l2_std_id *id)
{
struct msp_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
*id &= state->detected_std;
v4l_dbg(2, msp_debug, client,
"detected standard: %s(0x%08Lx)\n",
msp_standard_std_name(state->std), state->detected_std);
return 0;
}
static int msp_s_std(struct v4l2_subdev *sd, v4l2_std_id id) static int msp_s_std(struct v4l2_subdev *sd, v4l2_std_id id)
{ {
struct msp_state *state = to_state(sd); struct msp_state *state = to_state(sd);
...@@ -616,6 +630,10 @@ static const struct v4l2_subdev_core_ops msp_core_ops = { ...@@ -616,6 +630,10 @@ static const struct v4l2_subdev_core_ops msp_core_ops = {
.s_std = msp_s_std, .s_std = msp_s_std,
}; };
static const struct v4l2_subdev_video_ops msp_video_ops = {
.querystd = msp_querystd,
};
static const struct v4l2_subdev_tuner_ops msp_tuner_ops = { static const struct v4l2_subdev_tuner_ops msp_tuner_ops = {
.s_frequency = msp_s_frequency, .s_frequency = msp_s_frequency,
.g_tuner = msp_g_tuner, .g_tuner = msp_g_tuner,
...@@ -630,6 +648,7 @@ static const struct v4l2_subdev_audio_ops msp_audio_ops = { ...@@ -630,6 +648,7 @@ static const struct v4l2_subdev_audio_ops msp_audio_ops = {
static const struct v4l2_subdev_ops msp_ops = { static const struct v4l2_subdev_ops msp_ops = {
.core = &msp_core_ops, .core = &msp_core_ops,
.video = &msp_video_ops,
.tuner = &msp_tuner_ops, .tuner = &msp_tuner_ops,
.audio = &msp_audio_ops, .audio = &msp_audio_ops,
}; };
...@@ -664,6 +683,7 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -664,6 +683,7 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id)
v4l2_i2c_subdev_init(sd, client, &msp_ops); v4l2_i2c_subdev_init(sd, client, &msp_ops);
state->v4l2_std = V4L2_STD_NTSC; state->v4l2_std = V4L2_STD_NTSC;
state->detected_std = V4L2_STD_ALL;
state->audmode = V4L2_TUNER_MODE_STEREO; state->audmode = V4L2_TUNER_MODE_STEREO;
state->input = -1; state->input = -1;
state->i2s_mode = 0; state->i2s_mode = 0;
......
...@@ -75,7 +75,7 @@ struct msp_state { ...@@ -75,7 +75,7 @@ struct msp_state {
int opmode; int opmode;
int std; int std;
int mode; int mode;
v4l2_std_id v4l2_std; v4l2_std_id v4l2_std, detected_std;
int nicam_on; int nicam_on;
int acb; int acb;
int in_scart; int in_scart;
......
...@@ -37,29 +37,49 @@ static struct { ...@@ -37,29 +37,49 @@ static struct {
int retval; int retval;
int main, second; int main, second;
char *name; char *name;
v4l2_std_id std;
} msp_stdlist[] = { } msp_stdlist[] = {
{ 0x0000, 0, 0, "could not detect sound standard" }, { 0x0000, 0, 0, "could not detect sound standard", V4L2_STD_ALL },
{ 0x0001, 0, 0, "autodetect start" }, { 0x0001, 0, 0, "autodetect start", V4L2_STD_ALL },
{ 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72), "4.5/4.72 M Dual FM-Stereo" }, { 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72),
{ 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875), "5.5/5.74 B/G Dual FM-Stereo" }, "4.5/4.72 M Dual FM-Stereo", V4L2_STD_MN },
{ 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125), "6.5/6.25 D/K1 Dual FM-Stereo" }, { 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875),
{ 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875), "6.5/6.74 D/K2 Dual FM-Stereo" }, "5.5/5.74 B/G Dual FM-Stereo", V4L2_STD_BG },
{ 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 D/K FM-Mono (HDEV3)" }, { 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125),
{ 0x0007, MSP_CARRIER(6.5), MSP_CARRIER(5.7421875), "6.5/5.74 D/K3 Dual FM-Stereo" }, "6.5/6.25 D/K1 Dual FM-Stereo", V4L2_STD_DK },
{ 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), "5.5/5.85 B/G NICAM FM" }, { 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875),
{ 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 L NICAM AM" }, "6.5/6.74 D/K2 Dual FM-Stereo", V4L2_STD_DK },
{ 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), "6.0/6.55 I NICAM FM" }, { 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5),
{ 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM" }, "6.5 D/K FM-Mono (HDEV3)", V4L2_STD_DK },
{ 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV2)" }, { 0x0007, MSP_CARRIER(6.5), MSP_CARRIER(5.7421875),
{ 0x000d, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV3)" }, "6.5/5.74 D/K3 Dual FM-Stereo", V4L2_STD_DK },
{ 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Stereo" }, { 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85),
{ 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Mono + SAP" }, "5.5/5.85 B/G NICAM FM", V4L2_STD_BG },
{ 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M EIA-J Japan Stereo" }, { 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
{ 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7), "10.7 FM-Stereo Radio" }, "6.5/5.85 L NICAM AM", V4L2_STD_L },
{ 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 SAT-Mono" }, { 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55),
{ 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20), "7.02/7.20 SAT-Stereo" }, "6.0/6.55 I NICAM FM", V4L2_STD_PAL_I },
{ 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2), "7.2 SAT ADR" }, { 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
{ -1, 0, 0, NULL }, /* EOF */ "6.5/5.85 D/K NICAM FM", V4L2_STD_DK },
{ 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
"6.5/5.85 D/K NICAM FM (HDEV2)", V4L2_STD_DK },
{ 0x000d, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
"6.5/5.85 D/K NICAM FM (HDEV3)", V4L2_STD_DK },
{ 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5),
"4.5 M BTSC-Stereo", V4L2_STD_MTS },
{ 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5),
"4.5 M BTSC-Mono + SAP", V4L2_STD_MTS },
{ 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5),
"4.5 M EIA-J Japan Stereo", V4L2_STD_NTSC_M_JP },
{ 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7),
"10.7 FM-Stereo Radio", V4L2_STD_ALL },
{ 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5),
"6.5 SAT-Mono", V4L2_STD_ALL },
{ 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20),
"7.02/7.20 SAT-Stereo", V4L2_STD_ALL },
{ 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2),
"7.2 SAT ADR", V4L2_STD_ALL },
{ -1, 0, 0, NULL, 0 }, /* EOF */
}; };
static struct msp3400c_init_data_dem { static struct msp3400c_init_data_dem {
...@@ -156,6 +176,16 @@ const char *msp_standard_std_name(int std) ...@@ -156,6 +176,16 @@ const char *msp_standard_std_name(int std)
return "unknown"; return "unknown";
} }
static v4l2_std_id msp_standard_std(int std)
{
int i;
for (i = 0; msp_stdlist[i].name != NULL; i++)
if (msp_stdlist[i].retval == std)
return msp_stdlist[i].std;
return V4L2_STD_ALL;
}
static void msp_set_source(struct i2c_client *client, u16 src) static void msp_set_source(struct i2c_client *client, u16 src)
{ {
struct msp_state *state = to_state(i2c_get_clientdata(client)); struct msp_state *state = to_state(i2c_get_clientdata(client));
...@@ -479,6 +509,7 @@ int msp3400c_thread(void *data) ...@@ -479,6 +509,7 @@ int msp3400c_thread(void *data)
int count, max1, max2, val1, val2, val, i; int count, max1, max2, val1, val2, val, i;
v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n"); v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n");
state->detected_std = V4L2_STD_ALL;
set_freezable(); set_freezable();
for (;;) { for (;;) {
v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n"); v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n");
...@@ -579,6 +610,7 @@ int msp3400c_thread(void *data) ...@@ -579,6 +610,7 @@ int msp3400c_thread(void *data)
state->main = msp3400c_carrier_detect_main[max1].cdo; state->main = msp3400c_carrier_detect_main[max1].cdo;
switch (max1) { switch (max1) {
case 1: /* 5.5 */ case 1: /* 5.5 */
state->detected_std = V4L2_STD_BG | V4L2_STD_PAL_H;
if (max2 == 0) { if (max2 == 0) {
/* B/G FM-stereo */ /* B/G FM-stereo */
state->second = msp3400c_carrier_detect_55[max2].cdo; state->second = msp3400c_carrier_detect_55[max2].cdo;
...@@ -596,6 +628,7 @@ int msp3400c_thread(void *data) ...@@ -596,6 +628,7 @@ int msp3400c_thread(void *data)
break; break;
case 2: /* 6.0 */ case 2: /* 6.0 */
/* PAL I NICAM */ /* PAL I NICAM */
state->detected_std = V4L2_STD_PAL_I;
state->second = MSP_CARRIER(6.552); state->second = MSP_CARRIER(6.552);
msp3400c_set_mode(client, MSP_MODE_FM_NICAM2); msp3400c_set_mode(client, MSP_MODE_FM_NICAM2);
state->nicam_on = 1; state->nicam_on = 1;
...@@ -607,22 +640,26 @@ int msp3400c_thread(void *data) ...@@ -607,22 +640,26 @@ int msp3400c_thread(void *data)
state->second = msp3400c_carrier_detect_65[max2].cdo; state->second = msp3400c_carrier_detect_65[max2].cdo;
msp3400c_set_mode(client, MSP_MODE_FM_TERRA); msp3400c_set_mode(client, MSP_MODE_FM_TERRA);
state->watch_stereo = 1; state->watch_stereo = 1;
state->detected_std = V4L2_STD_DK;
} else if (max2 == 0 && (state->v4l2_std & V4L2_STD_SECAM)) { } else if (max2 == 0 && (state->v4l2_std & V4L2_STD_SECAM)) {
/* L NICAM or AM-mono */ /* L NICAM or AM-mono */
state->second = msp3400c_carrier_detect_65[max2].cdo; state->second = msp3400c_carrier_detect_65[max2].cdo;
msp3400c_set_mode(client, MSP_MODE_AM_NICAM); msp3400c_set_mode(client, MSP_MODE_AM_NICAM);
state->watch_stereo = 1; state->watch_stereo = 1;
state->detected_std = V4L2_STD_L;
} else if (max2 == 0 && state->has_nicam) { } else if (max2 == 0 && state->has_nicam) {
/* D/K NICAM */ /* D/K NICAM */
state->second = msp3400c_carrier_detect_65[max2].cdo; state->second = msp3400c_carrier_detect_65[max2].cdo;
msp3400c_set_mode(client, MSP_MODE_FM_NICAM1); msp3400c_set_mode(client, MSP_MODE_FM_NICAM1);
state->nicam_on = 1; state->nicam_on = 1;
state->watch_stereo = 1; state->watch_stereo = 1;
state->detected_std = V4L2_STD_DK;
} else { } else {
goto no_second; goto no_second;
} }
break; break;
case 0: /* 4.5 */ case 0: /* 4.5 */
state->detected_std = V4L2_STD_MN;
default: default:
no_second: no_second:
state->second = msp3400c_carrier_detect_main[max1].cdo; state->second = msp3400c_carrier_detect_main[max1].cdo;
...@@ -662,6 +699,7 @@ int msp3410d_thread(void *data) ...@@ -662,6 +699,7 @@ int msp3410d_thread(void *data)
int val, i, std, count; int val, i, std, count;
v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n"); v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n");
state->detected_std = V4L2_STD_ALL;
set_freezable(); set_freezable();
for (;;) { for (;;) {
v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n"); v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n");
...@@ -743,6 +781,8 @@ int msp3410d_thread(void *data) ...@@ -743,6 +781,8 @@ int msp3410d_thread(void *data)
msp_stdlist[8].name : "unknown", val); msp_stdlist[8].name : "unknown", val);
state->std = val = 0x0009; state->std = val = 0x0009;
msp_write_dem(client, 0x20, val); msp_write_dem(client, 0x20, val);
} else {
state->detected_std = msp_standard_std(state->std);
} }
/* set stereo */ /* set stereo */
...@@ -957,6 +997,7 @@ int msp34xxg_thread(void *data) ...@@ -957,6 +997,7 @@ int msp34xxg_thread(void *data)
int val, i; int val, i;
v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n"); v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n");
state->detected_std = V4L2_STD_ALL;
set_freezable(); set_freezable();
for (;;) { for (;;) {
v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n"); v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n");
...@@ -1013,6 +1054,7 @@ int msp34xxg_thread(void *data) ...@@ -1013,6 +1054,7 @@ int msp34xxg_thread(void *data)
v4l_dbg(1, msp_debug, client, v4l_dbg(1, msp_debug, client,
"detected standard: %s (0x%04x)\n", "detected standard: %s (0x%04x)\n",
msp_standard_std_name(state->std), state->std); msp_standard_std_name(state->std), state->std);
state->detected_std = msp_standard_std(state->std);
if (state->std == 9) { if (state->std == 9) {
/* AM NICAM mode */ /* AM NICAM mode */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment