提交 3bbe5a83 编写于 作者: H Hans Verkuil 提交者: Mauro Carvalho Chehab

V4L/DVB (3697): More msp3400 and bttv fixes

- remove obsolete VIDIOC_S_INPUT i2c call in bttv
- translate VIDIOCSFREQ to VIDIOC_S_FREQUENCY in i2c call
- improve muting during carrier scan in msp3400
- don't start scan unless really needed.
- no longer reset chip for msp3400c/d.
- remove v4l2 check in tuner-core (radio stops after using the TV)
- add missing VIDIOC_INT_ strings in v4l2-common.c
Signed-off-by: NHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: NMauro Carvalho Chehab <mchehab@infradead.org>
上级 c097b045
......@@ -1025,7 +1025,6 @@ i2c_vidiocschan(struct bttv *btv)
{
v4l2_std_id std = bttv_tvnorms[btv->tvnorm].v4l2_id;
bttv_call_i2c_clients(btv, VIDIOC_S_INPUT, &btv->input);
bttv_call_i2c_clients(btv, VIDIOC_S_STD, &std);
if (btv->c.type == BTTV_BOARD_VOODOOTV_FM)
bttv_tda9880_setnorm(btv,btv->tvnorm);
......@@ -1603,12 +1602,16 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
}
case VIDIOCSFREQ:
{
unsigned long *freq = arg;
struct v4l2_frequency freq;
memset(&freq, 0, sizeof(freq));
freq.frequency = *(unsigned long *)arg;
mutex_lock(&btv->lock);
btv->freq=*freq;
bttv_call_i2c_clients(btv,VIDIOCSFREQ,freq);
freq.type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
btv->freq = *(unsigned long *)arg;
bttv_call_i2c_clients(btv,VIDIOC_S_FREQUENCY,&freq);
if (btv->has_matchbox && btv->radio_user)
tea5757_set_freq(btv,*freq);
tea5757_set_freq(btv,*(unsigned long *)arg);
mutex_unlock(&btv->lock);
return 0;
}
......
......@@ -288,17 +288,19 @@ void msp_set_audio(struct i2c_client *client)
struct msp_state *state = i2c_get_clientdata(client);
int bal = 0, bass, treble, loudness;
int val = 0;
int reallymuted = state->muted | state->scan_in_progress;
if (!state->muted)
if (!reallymuted)
val = (state->volume * 0x7f / 65535) << 8;
v4l_dbg(1, msp_debug, client, "mute=%s volume=%d\n",
state->muted ? "on" : "off", state->volume);
v4l_dbg(1, msp_debug, client, "mute=%s scanning=%s volume=%d\n",
state->muted ? "on" : "off", state->scan_in_progress ? "yes" : "no",
state->volume);
msp_write_dsp(client, 0x0000, val);
msp_write_dsp(client, 0x0007, state->muted ? 0x1 : (val | 0x1));
msp_write_dsp(client, 0x0007, reallymuted ? 0x1 : (val | 0x1));
if (state->has_scart2_out_volume)
msp_write_dsp(client, 0x0040, state->muted ? 0x1 : (val | 0x1));
msp_write_dsp(client, 0x0040, reallymuted ? 0x1 : (val | 0x1));
if (state->has_headphones)
msp_write_dsp(client, 0x0006, val);
if (!state->has_sound_processing)
......@@ -671,21 +673,23 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
int sc_in = rt->input & 0x7;
int sc1_out = rt->output & 0xf;
int sc2_out = (rt->output >> 4) & 0xf;
u16 val;
u16 val, reg;
if (state->routing.input == rt->input &&
state->routing.output == rt->output)
break;
state->routing = *rt;
if (state->opmode == OPMODE_AUTOSELECT) {
val = msp_read_dem(client, 0x30) & ~0x100;
msp_write_dem(client, 0x30, val | (tuner ? 0x100 : 0));
} else {
val = msp_read_dem(client, 0xbb) & ~0x100;
msp_write_dem(client, 0xbb, val | (tuner ? 0x100 : 0));
}
msp_set_scart(client, sc_in, 0);
msp_set_scart(client, sc1_out, 1);
msp_set_scart(client, sc2_out, 2);
msp_set_audmode(client);
msp_wake_thread(client);
reg = (state->opmode == OPMODE_AUTOSELECT) ? 0x30 : 0xbb;
val = msp_read_dem(client, reg);
if (tuner != ((val >> 8) & 1)) {
msp_write_dem(client, reg, (val & ~0x100) | (tuner << 8));
/* wake thread when a new tuner input is chosen */
msp_wake_thread(client);
}
break;
}
......
......@@ -85,6 +85,7 @@ struct msp_state {
int volume, muted;
int balance, loudness;
int bass, treble;
int scan_in_progress;
/* thread */
struct task_struct *kthread;
......
......@@ -383,7 +383,7 @@ static int msp3400c_detect_stereo(struct i2c_client *client)
if (val > 32767)
val -= 65536;
v4l_dbg(2, msp_debug, client, "stereo detect register: %d\n", val);
if (val > 4096) {
if (val > 8192) {
rxsubchans = V4L2_TUNER_SUB_STEREO;
} else if (val < -4096) {
rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
......@@ -480,12 +480,14 @@ int msp3400c_thread(void *data)
if (state->radio || MSP_MODE_EXTERN == state->mode) {
/* no carrier scan, just unmute */
v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n");
state->scan_in_progress = 0;
msp_set_audio(client);
continue;
}
/* put into sane state (and mute) */
msp_reset(client);
/* mute audio */
state->scan_in_progress = 1;
msp_set_audio(client);
msp3400c_set_mode(client, MSP_MODE_AM_DETECT);
val1 = val2 = 0;
......@@ -493,7 +495,7 @@ int msp3400c_thread(void *data)
state->watch_stereo = 0;
state->nicam_on = 0;
/* some time for the tuner to sync */
/* wait for tuner to settle down after a channel change */
if (msp_sleep(state, 200))
goto restart;
......@@ -608,28 +610,26 @@ int msp3400c_thread(void *data)
no_second:
state->second = msp3400c_carrier_detect_main[max1].cdo;
msp3400c_set_mode(client, MSP_MODE_FM_TERRA);
state->rxsubchans = V4L2_TUNER_SUB_MONO;
break;
}
msp3400c_set_carrier(client, state->second, state->main);
/* unmute, restore misc registers */
msp_set_audio(client);
msp_write_dsp(client, 0x13, state->acb);
/* unmute */
state->scan_in_progress = 0;
msp3400c_set_audmode(client);
msp_set_audio(client);
if (msp_debug)
msp3400c_print_mode(client);
/* monitor tv audio mode, the first time don't wait
so long to get a quick stereo/bilingual result */
count = 20;
count = 3;
while (state->watch_stereo) {
watch_stereo(client);
if (msp_sleep(state, count ? 200 : 5000))
if (msp_sleep(state, count ? 1000 : 5000))
goto restart;
if (count) count--;
watch_stereo(client);
}
}
v4l_dbg(1, msp_debug, client, "thread: exit\n");
......@@ -659,16 +659,14 @@ int msp3410d_thread(void *data)
if (state->mode == MSP_MODE_EXTERN) {
/* no carrier scan needed, just unmute */
v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n");
state->scan_in_progress = 0;
msp_set_audio(client);
continue;
}
/* put into sane state (and mute) */
msp_reset(client);
/* some time for the tuner to sync */
if (msp_sleep(state,200))
goto restart;
/* mute audio */
state->scan_in_progress = 1;
msp_set_audio(client);
/* start autodetect. Note: autodetect is not supported for
NTSC-M and radio, hence we force the standard in those cases. */
......@@ -679,6 +677,10 @@ int msp3410d_thread(void *data)
state->watch_stereo = 0;
state->nicam_on = 0;
/* wait for tuner to settle down after a channel change */
if (msp_sleep(state, 200))
goto restart;
if (msp_debug)
v4l_dbg(2, msp_debug, client, "setting standard: %s (0x%04x)\n",
msp_standard_std_name(std), std);
......@@ -708,6 +710,7 @@ int msp3410d_thread(void *data)
state->main = msp_stdlist[i].main;
state->second = msp_stdlist[i].second;
state->std = val;
state->rxsubchans = V4L2_TUNER_SUB_MONO;
if (msp_amsound && !state->radio && (state->v4l2_std & V4L2_STD_SECAM) &&
(val != 0x0009)) {
......@@ -729,20 +732,17 @@ int msp3410d_thread(void *data)
else
state->mode = MSP_MODE_FM_NICAM1;
/* just turn on stereo */
state->rxsubchans = V4L2_TUNER_SUB_STEREO;
state->nicam_on = 1;
state->watch_stereo = 1;
break;
case 0x0009:
state->mode = MSP_MODE_AM_NICAM;
state->rxsubchans = V4L2_TUNER_SUB_MONO;
state->nicam_on = 1;
state->watch_stereo = 1;
break;
case 0x0020: /* BTSC */
/* The pre-'G' models only have BTSC-mono */
state->mode = MSP_MODE_BTSC;
state->rxsubchans = V4L2_TUNER_SUB_MONO;
break;
case 0x0040: /* FM radio */
state->mode = MSP_MODE_FM_RADIO;
......@@ -752,15 +752,12 @@ int msp3410d_thread(void *data)
msp3400c_set_mode(client, MSP_MODE_FM_RADIO);
msp3400c_set_carrier(client, MSP_CARRIER(10.7),
MSP_CARRIER(10.7));
/* scart routing (this doesn't belong here I think) */
msp_set_scart(client,SCART_IN2,0);
break;
case 0x0002:
case 0x0003:
case 0x0004:
case 0x0005:
state->mode = MSP_MODE_FM_TERRA;
state->rxsubchans = V4L2_TUNER_SUB_MONO;
state->watch_stereo = 1;
break;
}
......@@ -774,20 +771,19 @@ int msp3410d_thread(void *data)
if (state->has_i2s_conf)
msp_write_dem(client, 0x40, state->i2s_mode);
/* unmute, restore misc registers */
msp_set_audio(client);
msp_write_dsp(client, 0x13, state->acb);
/* unmute */
msp3400c_set_audmode(client);
state->scan_in_progress = 0;
msp_set_audio(client);
/* monitor tv audio mode, the first time don't wait
so long to get a quick stereo/bilingual result */
count = 20;
count = 3;
while (state->watch_stereo) {
watch_stereo(client);
if (msp_sleep(state, count ? 200 : 5000))
if (msp_sleep(state, count ? 1000 : 5000))
goto restart;
if (count) count--;
watch_stereo(client);
}
}
v4l_dbg(1, msp_debug, client, "thread: exit\n");
......@@ -902,10 +898,6 @@ static void msp34xxg_reset(struct i2c_client *client)
msp_reset(client);
/* make sure that input/output is muted (paranoid mode) */
/* ACB, mute DSP input, mute SCART 1 */
msp_write_dsp(client, 0x13, 0x0f20);
if (state->has_i2s_conf)
msp_write_dem(client, 0x40, state->i2s_mode);
......
......@@ -558,10 +558,10 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode,
static inline int check_v4l2(struct tuner *t)
{
if (t->using_v4l2) {
tuner_dbg ("ignore v4l1 call\n");
return EINVAL;
}
/* bttv still uses both v4l1 and v4l2 calls to the tuner (v4l2 for
TV, v4l1 for radio), until that is fixed this code is disabled.
Otherwise the radio (v4l1) wouldn't tune after using the TV (v4l2)
first. */
return 0;
}
......
......@@ -317,6 +317,7 @@ static const char *v4l2_int_ioctls[] = {
[_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY",
[_IOC_NR(TDA9887_SET_CONFIG)] = "TDA9887_SET_CONFIG",
[_IOC_NR(VIDIOC_INT_S_TUNER_MODE)] = "VIDIOC_INT_S_TUNER_MODE",
[_IOC_NR(VIDIOC_INT_S_REGISTER)] = "VIDIOC_INT_S_REGISTER",
[_IOC_NR(VIDIOC_INT_G_REGISTER)] = "VIDIOC_INT_G_REGISTER",
[_IOC_NR(VIDIOC_INT_RESET)] = "VIDIOC_INT_RESET",
......@@ -325,7 +326,12 @@ static const char *v4l2_int_ioctls[] = {
[_IOC_NR(VIDIOC_INT_S_VBI_DATA)] = "VIDIOC_INT_S_VBI_DATA",
[_IOC_NR(VIDIOC_INT_G_VBI_DATA)] = "VIDIOC_INT_G_VBI_DATA",
[_IOC_NR(VIDIOC_INT_G_CHIP_IDENT)] = "VIDIOC_INT_G_CHIP_IDENT",
[_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)] = "VIDIOC_INT_I2S_CLOCK_FREQ"
[_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)] = "VIDIOC_INT_I2S_CLOCK_FREQ",
[_IOC_NR(VIDIOC_INT_S_STANDBY)] = "VIDIOC_INT_S_STANDBY",
[_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)] = "VIDIOC_INT_S_AUDIO_ROUTING",
[_IOC_NR(VIDIOC_INT_G_AUDIO_ROUTING)] = "VIDIOC_INT_G_AUDIO_ROUTING",
[_IOC_NR(VIDIOC_INT_S_VIDEO_ROUTING)] = "VIDIOC_INT_S_VIDEO_ROUTING",
[_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)] = "VIDIOC_INT_G_VIDEO_ROUTING"
};
#define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册