Commit 8a4b275f authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

V4L/DVB (3427): audmode and rxsubchans fixes (VIDIOC_G/S_TUNER)


- Audmode and rxsubchans fixes in msp3400, tuner, tvaudio and cx25840.
- msp3400 cleanups
Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 9aeb4b05
...@@ -753,6 +753,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, ...@@ -753,6 +753,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
memset(input, 0, sizeof(*input)); memset(input, 0, sizeof(*input));
input->index = state->aud_input; input->index = state->aud_input;
input->capability = V4L2_AUDCAP_STEREO;
break; break;
} }
...@@ -763,7 +764,6 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, ...@@ -763,7 +764,6 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
case VIDIOC_G_TUNER: case VIDIOC_G_TUNER:
{ {
u8 mode = cx25840_read(client, 0x804); u8 mode = cx25840_read(client, 0x804);
u8 pref = cx25840_read(client, 0x809) & 0xf;
u8 vpres = cx25840_read(client, 0x80a) & 0x10; u8 vpres = cx25840_read(client, 0x80a) & 0x10;
int val = 0; int val = 0;
...@@ -783,44 +783,49 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, ...@@ -783,44 +783,49 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
val |= V4L2_TUNER_SUB_MONO; val |= V4L2_TUNER_SUB_MONO;
if (mode == 2 || mode == 4) if (mode == 2 || mode == 4)
val |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
if (mode & 0x10) if (mode & 0x10)
val |= V4L2_TUNER_SUB_SAP; val |= V4L2_TUNER_SUB_SAP;
vt->rxsubchans = val; vt->rxsubchans = val;
vt->audmode = state->audmode;
switch (pref) {
case 0:
vt->audmode = V4L2_TUNER_MODE_MONO;
break;
case 1:
case 2:
vt->audmode = V4L2_TUNER_MODE_LANG2;
break;
case 4:
default:
vt->audmode = V4L2_TUNER_MODE_STEREO;
}
break; break;
} }
case VIDIOC_S_TUNER: case VIDIOC_S_TUNER:
if (state->radio)
break;
switch (vt->audmode) { switch (vt->audmode) {
case V4L2_TUNER_MODE_MONO: case V4L2_TUNER_MODE_MONO:
case V4L2_TUNER_MODE_LANG1: /* mono -> mono
/* Force PREF_MODE to MONO */ stereo -> mono
bilingual -> lang1 */
cx25840_and_or(client, 0x809, ~0xf, 0x00); cx25840_and_or(client, 0x809, ~0xf, 0x00);
break; break;
case V4L2_TUNER_MODE_STEREO: case V4L2_TUNER_MODE_LANG1:
/* Force PREF_MODE to STEREO */ /* mono -> mono
stereo -> stereo
bilingual -> lang1 */
cx25840_and_or(client, 0x809, ~0xf, 0x04); cx25840_and_or(client, 0x809, ~0xf, 0x04);
break; break;
case V4L2_TUNER_MODE_STEREO:
/* mono -> mono
stereo -> stereo
bilingual -> lang1/lang2 */
cx25840_and_or(client, 0x809, ~0xf, 0x07);
break;
case V4L2_TUNER_MODE_LANG2: case V4L2_TUNER_MODE_LANG2:
/* Force PREF_MODE to LANG2 */ /* mono -> mono
stereo ->stereo
bilingual -> lang2 */
cx25840_and_or(client, 0x809, ~0xf, 0x01); cx25840_and_or(client, 0x809, ~0xf, 0x01);
break; break;
default:
return -EINVAL;
} }
state->audmode = vt->audmode;
break; break;
case VIDIOC_G_FMT: case VIDIOC_G_FMT:
...@@ -901,6 +906,7 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, ...@@ -901,6 +906,7 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
state->aud_input = CX25840_AUDIO8; state->aud_input = CX25840_AUDIO8;
state->audclk_freq = 48000; state->audclk_freq = 48000;
state->pvr150_workaround = 0; state->pvr150_workaround = 0;
state->audmode = V4L2_TUNER_MODE_LANG1;
cx25840_initialize(client, 1); cx25840_initialize(client, 1);
......
...@@ -78,6 +78,7 @@ struct cx25840_state { ...@@ -78,6 +78,7 @@ struct cx25840_state {
enum cx25840_video_input vid_input; enum cx25840_video_input vid_input;
enum cx25840_audio_input aud_input; enum cx25840_audio_input aud_input;
u32 audclk_freq; u32 audclk_freq;
int audmode;
}; };
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
......
...@@ -411,9 +411,9 @@ static int msp_mode_v4l2_to_v4l1(int rxsubchans) ...@@ -411,9 +411,9 @@ static int msp_mode_v4l2_to_v4l1(int rxsubchans)
if (rxsubchans & V4L2_TUNER_SUB_STEREO) if (rxsubchans & V4L2_TUNER_SUB_STEREO)
mode |= VIDEO_SOUND_STEREO; mode |= VIDEO_SOUND_STEREO;
if (rxsubchans & V4L2_TUNER_SUB_LANG2) if (rxsubchans & V4L2_TUNER_SUB_LANG2)
mode |= VIDEO_SOUND_LANG2; mode |= VIDEO_SOUND_LANG2 | VIDEO_SOUND_STEREO;
if (rxsubchans & V4L2_TUNER_SUB_LANG1) if (rxsubchans & V4L2_TUNER_SUB_LANG1)
mode |= VIDEO_SOUND_LANG1; mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_STEREO;
if (mode == 0) if (mode == 0)
mode |= VIDEO_SOUND_MONO; mode |= VIDEO_SOUND_MONO;
return mode; return mode;
...@@ -430,21 +430,6 @@ static int msp_mode_v4l1_to_v4l2(int mode) ...@@ -430,21 +430,6 @@ static int msp_mode_v4l1_to_v4l2(int mode)
return V4L2_TUNER_MODE_MONO; return V4L2_TUNER_MODE_MONO;
} }
static void msp_any_detect_stereo(struct i2c_client *client)
{
struct msp_state *state = i2c_get_clientdata(client);
switch (state->opmode) {
case OPMODE_MANUAL:
case OPMODE_AUTODETECT:
autodetect_stereo(client);
break;
case OPMODE_AUTOSELECT:
msp34xxg_detect_stereo(client);
break;
}
}
static struct v4l2_queryctrl msp_qctrl_std[] = { static struct v4l2_queryctrl msp_qctrl_std[] = {
{ {
.id = V4L2_CID_AUDIO_VOLUME, .id = V4L2_CID_AUDIO_VOLUME,
...@@ -506,22 +491,6 @@ static struct v4l2_queryctrl msp_qctrl_sound_processing[] = { ...@@ -506,22 +491,6 @@ static struct v4l2_queryctrl msp_qctrl_sound_processing[] = {
}; };
static void msp_any_set_audmode(struct i2c_client *client, int audmode)
{
struct msp_state *state = i2c_get_clientdata(client);
switch (state->opmode) {
case OPMODE_MANUAL:
case OPMODE_AUTODETECT:
state->watch_stereo = 0;
msp3400c_setstereo(client, audmode);
break;
case OPMODE_AUTOSELECT:
msp34xxg_set_audmode(client, audmode);
break;
}
}
static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
{ {
struct msp_state *state = i2c_get_clientdata(client); struct msp_state *state = i2c_get_clientdata(client);
...@@ -656,7 +625,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) ...@@ -656,7 +625,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
msp_set_scart(client, scart, 0); msp_set_scart(client, scart, 0);
msp_write_dsp(client, 0x000d, 0x1900); msp_write_dsp(client, 0x000d, 0x1900);
if (state->opmode != OPMODE_AUTOSELECT) if (state->opmode != OPMODE_AUTOSELECT)
msp3400c_setstereo(client, state->audmode); msp_set_audmode(client);
} }
msp_wake_thread(client); msp_wake_thread(client);
break; break;
...@@ -670,8 +639,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) ...@@ -670,8 +639,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
switch (state->opmode) { switch (state->opmode) {
case OPMODE_MANUAL: case OPMODE_MANUAL:
/* set msp3400 to FM radio mode */ /* set msp3400 to FM radio mode */
msp3400c_setmode(client, MSP_MODE_FM_RADIO); msp3400c_set_mode(client, MSP_MODE_FM_RADIO);
msp3400c_setcarrier(client, MSP_CARRIER(10.7), msp3400c_set_carrier(client, MSP_CARRIER(10.7),
MSP_CARRIER(10.7)); MSP_CARRIER(10.7));
msp_set_audio(client); msp_set_audio(client);
break; break;
...@@ -705,7 +674,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) ...@@ -705,7 +674,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (state->radio) if (state->radio)
break; break;
if (state->opmode == OPMODE_AUTOSELECT) if (state->opmode == OPMODE_AUTOSELECT)
msp_any_detect_stereo(client); msp_detect_stereo(client);
va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans); va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans);
break; break;
} }
...@@ -721,8 +690,9 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) ...@@ -721,8 +690,9 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
state->treble = va->treble; state->treble = va->treble;
msp_set_audio(client); msp_set_audio(client);
if (va->mode != 0 && state->radio == 0) if (va->mode != 0 && state->radio == 0) {
msp_any_set_audmode(client, msp_mode_v4l1_to_v4l2(va->mode)); state->audmode = msp_mode_v4l1_to_v4l2(va->mode);
}
break; break;
} }
...@@ -864,7 +834,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) ...@@ -864,7 +834,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
msp_set_scart(client, scart, 0); msp_set_scart(client, scart, 0);
msp_write_dsp(client, 0x000d, 0x1900); msp_write_dsp(client, 0x000d, 0x1900);
} }
msp_any_set_audmode(client, state->audmode); msp_set_audmode(client);
msp_wake_thread(client); msp_wake_thread(client);
break; break;
} }
...@@ -876,7 +846,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) ...@@ -876,7 +846,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (state->radio) if (state->radio)
break; break;
if (state->opmode == OPMODE_AUTOSELECT) if (state->opmode == OPMODE_AUTOSELECT)
msp_any_detect_stereo(client); msp_detect_stereo(client);
vt->audmode = state->audmode; vt->audmode = state->audmode;
vt->rxsubchans = state->rxsubchans; vt->rxsubchans = state->rxsubchans;
vt->capability = V4L2_TUNER_CAP_STEREO | vt->capability = V4L2_TUNER_CAP_STEREO |
...@@ -890,8 +860,9 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) ...@@ -890,8 +860,9 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (state->radio) /* TODO: add mono/stereo support for radio */ if (state->radio) /* TODO: add mono/stereo support for radio */
break; break;
state->audmode = vt->audmode;
/* only set audmode */ /* only set audmode */
msp_any_set_audmode(client, vt->audmode); msp_set_audmode(client);
break; break;
} }
...@@ -981,7 +952,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) ...@@ -981,7 +952,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
const char *p; const char *p;
if (state->opmode == OPMODE_AUTOSELECT) if (state->opmode == OPMODE_AUTOSELECT)
msp_any_detect_stereo(client); msp_detect_stereo(client);
v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n", v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n",
client->name, state->rev1, state->rev2); client->name, state->rev1, state->rev2);
v4l_info(client, "Audio: volume %d%s\n", v4l_info(client, "Audio: volume %d%s\n",
...@@ -1082,7 +1053,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) ...@@ -1082,7 +1053,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind)
memset(state, 0, sizeof(*state)); memset(state, 0, sizeof(*state));
state->v4l2_std = V4L2_STD_NTSC; state->v4l2_std = V4L2_STD_NTSC;
state->audmode = V4L2_TUNER_MODE_STEREO; state->audmode = V4L2_TUNER_MODE_LANG1;
state->volume = 58880; /* 0db gain */ state->volume = 58880; /* 0db gain */
state->balance = 32768; /* 0db gain */ state->balance = 32768; /* 0db gain */
state->bass = 32768; state->bass = 32768;
......
This diff is collapsed.
...@@ -104,14 +104,13 @@ int msp_sleep(struct msp_state *state, int timeout); ...@@ -104,14 +104,13 @@ int msp_sleep(struct msp_state *state, int timeout);
/* msp3400-kthreads.c */ /* msp3400-kthreads.c */
const char *msp_standard_std_name(int std); const char *msp_standard_std_name(int std);
void msp3400c_setcarrier(struct i2c_client *client, int cdo1, int cdo2); void msp_set_source(struct i2c_client *client, u16 src);
void msp3400c_setmode(struct i2c_client *client, int type); void msp_set_audmode(struct i2c_client *client);
void msp3400c_setstereo(struct i2c_client *client, int mode); void msp_detect_stereo(struct i2c_client *client);
int autodetect_stereo(struct i2c_client *client);
int msp3400c_thread(void *data); int msp3400c_thread(void *data);
int msp3410d_thread(void *data); int msp3410d_thread(void *data);
int msp34xxg_thread(void *data); int msp34xxg_thread(void *data);
void msp34xxg_detect_stereo(struct i2c_client *client); void msp3400c_set_mode(struct i2c_client *client, int mode);
void msp34xxg_set_audmode(struct i2c_client *client, int audmode); void msp3400c_set_carrier(struct i2c_client *client, int cdo1, int cdo2);
#endif /* MSP3400_H */ #endif /* MSP3400_H */
...@@ -398,15 +398,16 @@ static void tuner_status(struct i2c_client *client) ...@@ -398,15 +398,16 @@ static void tuner_status(struct i2c_client *client)
tuner_info("Tuner mode: %s\n", p); tuner_info("Tuner mode: %s\n", p);
tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction); tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction);
tuner_info("Standard: 0x%08llx\n", t->std); tuner_info("Standard: 0x%08llx\n", t->std);
if (t->mode == V4L2_TUNER_RADIO) { if (t->mode != V4L2_TUNER_RADIO)
if (t->has_signal) { return;
tuner_info("Signal strength: %d\n", t->has_signal(client)); if (t->has_signal) {
} tuner_info("Signal strength: %d\n", t->has_signal(client));
if (t->is_stereo) { }
tuner_info("Stereo: %s\n", t->is_stereo(client) ? "yes" : "no"); if (t->is_stereo) {
} tuner_info("Stereo: %s\n", t->is_stereo(client) ? "yes" : "no");
} }
} }
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
/* static var Used only in tuner_attach and tuner_probe */ /* static var Used only in tuner_attach and tuner_probe */
...@@ -737,33 +738,29 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) ...@@ -737,33 +738,29 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0; return 0;
switch_v4l2(); switch_v4l2();
if (V4L2_TUNER_RADIO == t->mode) { tuner->type = t->mode;
if (t->mode != V4L2_TUNER_RADIO) {
if (t->has_signal)
tuner->signal = t->has_signal(client);
if (t->is_stereo) {
if (t->is_stereo(client)) {
tuner->rxsubchans =
V4L2_TUNER_SUB_STEREO |
V4L2_TUNER_SUB_MONO;
} else {
tuner->rxsubchans =
V4L2_TUNER_SUB_MONO;
}
}
tuner->capability |=
V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
tuner->audmode = t->audmode;
tuner->rangelow = radio_range[0] * 16000;
tuner->rangehigh = radio_range[1] * 16000;
} else {
tuner->rangelow = tv_range[0] * 16; tuner->rangelow = tv_range[0] * 16;
tuner->rangehigh = tv_range[1] * 16; tuner->rangehigh = tv_range[1] * 16;
break;
}
/* radio mode */
if (t->has_signal)
tuner->signal = t->has_signal(client);
tuner->rxsubchans =
V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
if (t->is_stereo) {
tuner->rxsubchans = t->is_stereo(client) ?
V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
} }
tuner->capability |=
V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
tuner->audmode = t->audmode;
tuner->rangelow = radio_range[0] * 16000;
tuner->rangehigh = radio_range[1] * 16000;
break; break;
} }
case VIDIOC_S_TUNER: case VIDIOC_S_TUNER:
...@@ -775,10 +772,11 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) ...@@ -775,10 +772,11 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
switch_v4l2(); switch_v4l2();
if (V4L2_TUNER_RADIO == t->mode) { /* do nothing unless we're a radio tuner */
t->audmode = tuner->audmode; if (t->mode != V4L2_TUNER_RADIO)
set_radio_freq(client, t->radio_freq); break;
} t->audmode = tuner->audmode;
set_radio_freq(client, t->radio_freq);
break; break;
} }
case VIDIOC_LOG_STATUS: case VIDIOC_LOG_STATUS:
......
...@@ -130,6 +130,7 @@ struct CHIPSTATE { ...@@ -130,6 +130,7 @@ struct CHIPSTATE {
struct timer_list wt; struct timer_list wt;
int done; int done;
int watch_stereo; int watch_stereo;
int audmode;
}; };
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
...@@ -1514,6 +1515,7 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind) ...@@ -1514,6 +1515,7 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind)
chip->type = desc-chiplist; chip->type = desc-chiplist;
chip->shadow.count = desc->registers+1; chip->shadow.count = desc->registers+1;
chip->prevmode = -1; chip->prevmode = -1;
chip->audmode = V4L2_TUNER_MODE_LANG1;
/* register */ /* register */
i2c_attach_client(&chip->c); i2c_attach_client(&chip->c);
...@@ -1671,6 +1673,8 @@ static int chip_command(struct i2c_client *client, ...@@ -1671,6 +1673,8 @@ static int chip_command(struct i2c_client *client,
struct v4l2_tuner *vt = arg; struct v4l2_tuner *vt = arg;
int mode = 0; int mode = 0;
if (chip->radio)
break;
switch (vt->audmode) { switch (vt->audmode) {
case V4L2_TUNER_MODE_MONO: case V4L2_TUNER_MODE_MONO:
mode = VIDEO_SOUND_MONO; mode = VIDEO_SOUND_MONO;
...@@ -1685,8 +1689,9 @@ static int chip_command(struct i2c_client *client, ...@@ -1685,8 +1689,9 @@ static int chip_command(struct i2c_client *client,
mode = VIDEO_SOUND_LANG2; mode = VIDEO_SOUND_LANG2;
break; break;
default: default:
break; return -EINVAL;
} }
chip->audmode = vt->audmode;
if (desc->setmode && mode) { if (desc->setmode && mode) {
chip->watch_stereo = 0; chip->watch_stereo = 0;
...@@ -1704,7 +1709,7 @@ static int chip_command(struct i2c_client *client, ...@@ -1704,7 +1709,7 @@ static int chip_command(struct i2c_client *client,
if (chip->radio) if (chip->radio)
break; break;
vt->audmode = 0; vt->audmode = chip->audmode;
vt->rxsubchans = 0; vt->rxsubchans = 0;
vt->capability = V4L2_TUNER_CAP_STEREO | vt->capability = V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
...@@ -1716,19 +1721,12 @@ static int chip_command(struct i2c_client *client, ...@@ -1716,19 +1721,12 @@ static int chip_command(struct i2c_client *client,
vt->rxsubchans |= V4L2_TUNER_SUB_MONO; vt->rxsubchans |= V4L2_TUNER_SUB_MONO;
if (mode & VIDEO_SOUND_STEREO) if (mode & VIDEO_SOUND_STEREO)
vt->rxsubchans |= V4L2_TUNER_SUB_STEREO; vt->rxsubchans |= V4L2_TUNER_SUB_STEREO;
/* Note: for SAP it should be mono/lang2 or stereo/lang2.
When this module is converted fully to v4l2, then this
should change for those chips that can detect SAP. */
if (mode & VIDEO_SOUND_LANG1) if (mode & VIDEO_SOUND_LANG1)
vt->rxsubchans |= V4L2_TUNER_SUB_LANG1 | vt->rxsubchans = V4L2_TUNER_SUB_LANG1 |
V4L2_TUNER_SUB_LANG2; V4L2_TUNER_SUB_LANG2;
mode = chip->mode;
if (mode & VIDEO_SOUND_MONO)
vt->audmode = V4L2_TUNER_MODE_MONO;
if (mode & VIDEO_SOUND_STEREO)
vt->audmode = V4L2_TUNER_MODE_STEREO;
if (mode & VIDEO_SOUND_LANG1)
vt->audmode = V4L2_TUNER_MODE_LANG1;
if (mode & VIDEO_SOUND_LANG2)
vt->audmode = V4L2_TUNER_MODE_LANG2;
break; break;
} }
......
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