提交 8a4b275f 编写于 作者: H Hans Verkuil 提交者: 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: NHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: NMauro Carvalho Chehab <mchehab@infradead.org>
上级 9aeb4b05
......@@ -753,6 +753,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
memset(input, 0, sizeof(*input));
input->index = state->aud_input;
input->capability = V4L2_AUDCAP_STEREO;
break;
}
......@@ -763,7 +764,6 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
case VIDIOC_G_TUNER:
{
u8 mode = cx25840_read(client, 0x804);
u8 pref = cx25840_read(client, 0x809) & 0xf;
u8 vpres = cx25840_read(client, 0x80a) & 0x10;
int val = 0;
......@@ -783,44 +783,49 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
val |= V4L2_TUNER_SUB_MONO;
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)
val |= V4L2_TUNER_SUB_SAP;
vt->rxsubchans = val;
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;
}
vt->audmode = state->audmode;
break;
}
case VIDIOC_S_TUNER:
if (state->radio)
break;
switch (vt->audmode) {
case V4L2_TUNER_MODE_MONO:
case V4L2_TUNER_MODE_LANG1:
/* Force PREF_MODE to MONO */
/* mono -> mono
stereo -> mono
bilingual -> lang1 */
cx25840_and_or(client, 0x809, ~0xf, 0x00);
break;
case V4L2_TUNER_MODE_STEREO:
/* Force PREF_MODE to STEREO */
case V4L2_TUNER_MODE_LANG1:
/* mono -> mono
stereo -> stereo
bilingual -> lang1 */
cx25840_and_or(client, 0x809, ~0xf, 0x04);
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:
/* Force PREF_MODE to LANG2 */
/* mono -> mono
stereo ->stereo
bilingual -> lang2 */
cx25840_and_or(client, 0x809, ~0xf, 0x01);
break;
default:
return -EINVAL;
}
state->audmode = vt->audmode;
break;
case VIDIOC_G_FMT:
......@@ -901,6 +906,7 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
state->aud_input = CX25840_AUDIO8;
state->audclk_freq = 48000;
state->pvr150_workaround = 0;
state->audmode = V4L2_TUNER_MODE_LANG1;
cx25840_initialize(client, 1);
......
......@@ -78,6 +78,7 @@ struct cx25840_state {
enum cx25840_video_input vid_input;
enum cx25840_audio_input aud_input;
u32 audclk_freq;
int audmode;
};
/* ----------------------------------------------------------------------- */
......
......@@ -411,9 +411,9 @@ static int msp_mode_v4l2_to_v4l1(int rxsubchans)
if (rxsubchans & V4L2_TUNER_SUB_STEREO)
mode |= VIDEO_SOUND_STEREO;
if (rxsubchans & V4L2_TUNER_SUB_LANG2)
mode |= VIDEO_SOUND_LANG2;
mode |= VIDEO_SOUND_LANG2 | VIDEO_SOUND_STEREO;
if (rxsubchans & V4L2_TUNER_SUB_LANG1)
mode |= VIDEO_SOUND_LANG1;
mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_STEREO;
if (mode == 0)
mode |= VIDEO_SOUND_MONO;
return mode;
......@@ -430,21 +430,6 @@ static int msp_mode_v4l1_to_v4l2(int mode)
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[] = {
{
.id = V4L2_CID_AUDIO_VOLUME,
......@@ -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)
{
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)
msp_set_scart(client, scart, 0);
msp_write_dsp(client, 0x000d, 0x1900);
if (state->opmode != OPMODE_AUTOSELECT)
msp3400c_setstereo(client, state->audmode);
msp_set_audmode(client);
}
msp_wake_thread(client);
break;
......@@ -670,8 +639,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
switch (state->opmode) {
case OPMODE_MANUAL:
/* set msp3400 to FM radio mode */
msp3400c_setmode(client, MSP_MODE_FM_RADIO);
msp3400c_setcarrier(client, MSP_CARRIER(10.7),
msp3400c_set_mode(client, MSP_MODE_FM_RADIO);
msp3400c_set_carrier(client, MSP_CARRIER(10.7),
MSP_CARRIER(10.7));
msp_set_audio(client);
break;
......@@ -705,7 +674,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (state->radio)
break;
if (state->opmode == OPMODE_AUTOSELECT)
msp_any_detect_stereo(client);
msp_detect_stereo(client);
va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans);
break;
}
......@@ -721,8 +690,9 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
state->treble = va->treble;
msp_set_audio(client);
if (va->mode != 0 && state->radio == 0)
msp_any_set_audmode(client, msp_mode_v4l1_to_v4l2(va->mode));
if (va->mode != 0 && state->radio == 0) {
state->audmode = msp_mode_v4l1_to_v4l2(va->mode);
}
break;
}
......@@ -864,7 +834,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
msp_set_scart(client, scart, 0);
msp_write_dsp(client, 0x000d, 0x1900);
}
msp_any_set_audmode(client, state->audmode);
msp_set_audmode(client);
msp_wake_thread(client);
break;
}
......@@ -876,7 +846,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (state->radio)
break;
if (state->opmode == OPMODE_AUTOSELECT)
msp_any_detect_stereo(client);
msp_detect_stereo(client);
vt->audmode = state->audmode;
vt->rxsubchans = state->rxsubchans;
vt->capability = V4L2_TUNER_CAP_STEREO |
......@@ -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 */
break;
state->audmode = vt->audmode;
/* only set audmode */
msp_any_set_audmode(client, vt->audmode);
msp_set_audmode(client);
break;
}
......@@ -981,7 +952,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
const char *p;
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",
client->name, state->rev1, state->rev2);
v4l_info(client, "Audio: volume %d%s\n",
......@@ -1082,7 +1053,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind)
memset(state, 0, sizeof(*state));
state->v4l2_std = V4L2_STD_NTSC;
state->audmode = V4L2_TUNER_MODE_STEREO;
state->audmode = V4L2_TUNER_MODE_LANG1;
state->volume = 58880; /* 0db gain */
state->balance = 32768; /* 0db gain */
state->bass = 32768;
......
......@@ -104,14 +104,13 @@ int msp_sleep(struct msp_state *state, int timeout);
/* msp3400-kthreads.c */
const char *msp_standard_std_name(int std);
void msp3400c_setcarrier(struct i2c_client *client, int cdo1, int cdo2);
void msp3400c_setmode(struct i2c_client *client, int type);
void msp3400c_setstereo(struct i2c_client *client, int mode);
int autodetect_stereo(struct i2c_client *client);
void msp_set_source(struct i2c_client *client, u16 src);
void msp_set_audmode(struct i2c_client *client);
void msp_detect_stereo(struct i2c_client *client);
int msp3400c_thread(void *data);
int msp3410d_thread(void *data);
int msp34xxg_thread(void *data);
void msp34xxg_detect_stereo(struct i2c_client *client);
void msp34xxg_set_audmode(struct i2c_client *client, int audmode);
void msp3400c_set_mode(struct i2c_client *client, int mode);
void msp3400c_set_carrier(struct i2c_client *client, int cdo1, int cdo2);
#endif /* MSP3400_H */
......@@ -398,15 +398,16 @@ static void tuner_status(struct i2c_client *client)
tuner_info("Tuner mode: %s\n", p);
tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction);
tuner_info("Standard: 0x%08llx\n", t->std);
if (t->mode == V4L2_TUNER_RADIO) {
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->mode != V4L2_TUNER_RADIO)
return;
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");
}
}
/* ---------------------------------------------------------------------- */
/* 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)
return 0;
switch_v4l2();
if (V4L2_TUNER_RADIO == t->mode) {
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->type = t->mode;
if (t->mode != V4L2_TUNER_RADIO) {
tuner->rangelow = tv_range[0] * 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;
}
case VIDIOC_S_TUNER:
......@@ -775,10 +772,11 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
switch_v4l2();
if (V4L2_TUNER_RADIO == t->mode) {
t->audmode = tuner->audmode;
set_radio_freq(client, t->radio_freq);
}
/* do nothing unless we're a radio tuner */
if (t->mode != V4L2_TUNER_RADIO)
break;
t->audmode = tuner->audmode;
set_radio_freq(client, t->radio_freq);
break;
}
case VIDIOC_LOG_STATUS:
......
......@@ -130,6 +130,7 @@ struct CHIPSTATE {
struct timer_list wt;
int done;
int watch_stereo;
int audmode;
};
/* ---------------------------------------------------------------------- */
......@@ -1514,6 +1515,7 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind)
chip->type = desc-chiplist;
chip->shadow.count = desc->registers+1;
chip->prevmode = -1;
chip->audmode = V4L2_TUNER_MODE_LANG1;
/* register */
i2c_attach_client(&chip->c);
......@@ -1671,6 +1673,8 @@ static int chip_command(struct i2c_client *client,
struct v4l2_tuner *vt = arg;
int mode = 0;
if (chip->radio)
break;
switch (vt->audmode) {
case V4L2_TUNER_MODE_MONO:
mode = VIDEO_SOUND_MONO;
......@@ -1685,8 +1689,9 @@ static int chip_command(struct i2c_client *client,
mode = VIDEO_SOUND_LANG2;
break;
default:
break;
return -EINVAL;
}
chip->audmode = vt->audmode;
if (desc->setmode && mode) {
chip->watch_stereo = 0;
......@@ -1704,7 +1709,7 @@ static int chip_command(struct i2c_client *client,
if (chip->radio)
break;
vt->audmode = 0;
vt->audmode = chip->audmode;
vt->rxsubchans = 0;
vt->capability = V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
......@@ -1716,19 +1721,12 @@ static int chip_command(struct i2c_client *client,
vt->rxsubchans |= V4L2_TUNER_SUB_MONO;
if (mode & VIDEO_SOUND_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)
vt->rxsubchans |= V4L2_TUNER_SUB_LANG1 |
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;
vt->rxsubchans = V4L2_TUNER_SUB_LANG1 |
V4L2_TUNER_SUB_LANG2;
break;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册