From 18103c57b0168ebc0401702d483fe131f0aecc7a Mon Sep 17 00:00:00 2001 From: Mike Isely Date: Sat, 20 Jan 2007 00:09:47 -0300 Subject: [PATCH] V4L/DVB (5081): Pvrusb2: VIDIOC_G_TUNER cleanup Clean up use of VIDIOC_G_TUNER; we now correctly gather info from all the I2C client modules. Also abide by V4L2_TUNER_CAP_LOW appropriately. Signed-off-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-audio.c | 24 ----- .../media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | 13 --- .../video/pvrusb2/pvrusb2-hdw-internal.h | 16 +-- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 99 +++++++++++-------- drivers/media/video/pvrusb2/pvrusb2-hdw.h | 13 +-- .../video/pvrusb2/pvrusb2-i2c-chips-v4l2.c | 1 + .../video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c | 19 +++- .../video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h | 1 + .../media/video/pvrusb2/pvrusb2-i2c-core.c | 22 +++++ .../media/video/pvrusb2/pvrusb2-i2c-core.h | 3 + drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 85 ++++++---------- .../media/video/pvrusb2/pvrusb2-video-v4l.c | 13 --- 12 files changed, 144 insertions(+), 165 deletions(-) diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.c b/drivers/media/video/pvrusb2/pvrusb2-audio.c index 122496f36845..5d30c9366144 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ b/drivers/media/video/pvrusb2/pvrusb2-audio.c @@ -31,7 +31,6 @@ struct pvr2_msp3400_handler { struct pvr2_hdw *hdw; struct pvr2_i2c_client *client; struct pvr2_i2c_handler i2c_handler; - struct pvr2_audio_stat astat; unsigned long stale_mask; }; @@ -126,27 +125,9 @@ static void msp3400_update(struct pvr2_msp3400_handler *ctxt) } -/* This reads back the current signal type */ -static int get_audio_status(struct pvr2_msp3400_handler *ctxt) -{ - struct v4l2_tuner vt; - int stat; - - memset(&vt,0,sizeof(vt)); - stat = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt); - if (stat < 0) return stat; - - ctxt->hdw->flag_stereo = (vt.audmode & V4L2_TUNER_MODE_STEREO) != 0; - ctxt->hdw->flag_bilingual = - (vt.audmode & V4L2_TUNER_MODE_LANG2) != 0; - return 0; -} - - static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt) { ctxt->client->handler = NULL; - ctxt->hdw->audio_stat = NULL; kfree(ctxt); } @@ -169,7 +150,6 @@ static const struct pvr2_i2c_handler_functions msp3400_funcs = { int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) { struct pvr2_msp3400_handler *ctxt; - if (hdw->audio_stat) return 0; if (cp->handler) return 0; ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL); @@ -180,13 +160,9 @@ int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) ctxt->i2c_handler.func_table = &msp3400_funcs; ctxt->client = cp; ctxt->hdw = hdw; - ctxt->astat.ctxt = ctxt; - ctxt->astat.status = (int (*)(void *))get_audio_status; - ctxt->astat.detach = (void (*)(void *))pvr2_msp3400_detach; ctxt->stale_mask = (1 << (sizeof(msp3400_ops)/ sizeof(msp3400_ops[0]))) - 1; cp->handler = &ctxt->i2c_handler; - hdw->audio_stat = &ctxt->astat; pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x msp3400 V4L2 handler set up", cp->client->addr); return !0; diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index c2a154e4ec59..a3357bf2a1af 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -199,18 +199,6 @@ static int decoder_detect(struct pvr2_i2c_client *cp) } -static int decoder_is_tuned(struct pvr2_v4l_cx2584x *ctxt) -{ - struct v4l2_tuner vt; - int ret; - - memset(&vt,0,sizeof(vt)); - ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt); - if (ret < 0) return -EINVAL; - return vt.signal ? 1 : 0; -} - - static unsigned int decoder_describe(struct pvr2_v4l_cx2584x *ctxt, char *buf,unsigned int cnt) { @@ -252,7 +240,6 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw, ctxt->ctrl.ctxt = ctxt; ctxt->ctrl.detach = (void (*)(void *))decoder_detach; ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable; - ctxt->ctrl.tuned = (int (*)(void *))decoder_is_tuned; ctxt->ctrl.force_reset = (void (*)(void*))decoder_reset; ctxt->client = cp; ctxt->hdw = hdw; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index b9df52c882a8..bc911ff75306 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -137,17 +137,10 @@ struct pvr2_ctrl { }; -struct pvr2_audio_stat { - void *ctxt; - void (*detach)(void *); - int (*status)(void *); -}; - struct pvr2_decoder_ctrl { void *ctxt; void (*detach)(void *); void (*enable)(void *,int); - int (*tuned)(void *); void (*force_reset)(void *); }; @@ -266,6 +259,10 @@ struct pvr2_hdw { unsigned int freqSelector; /* 0=radio 1=television */ int freqDirty; + /* Current tuner info - this information is polled from the I2C bus */ + struct v4l2_tuner tuner_signal_info; + int tuner_signal_stale; + /* Video standard handling */ v4l2_std_id std_mask_eeprom; // Hardware supported selections v4l2_std_id std_mask_avail; // Which standards we may select from @@ -297,11 +294,6 @@ struct pvr2_hdw { enum pvr2_config config; - /* Information about what audio signal we're hearing */ - int flag_stereo; - int flag_bilingual; - struct pvr2_audio_stat *audio_stat; - /* Control state needed for cx2341x module */ struct cx2341x_mpeg_params enc_cur_state; struct cx2341x_mpeg_params enc_ctl_state; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 2de595112224..4672199ae92d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -264,7 +264,6 @@ static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long); static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl); static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw); static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw); -static unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw); static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw); static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw); static void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw); @@ -623,8 +622,34 @@ static void ctrl_stdcur_clear_dirty(struct pvr2_ctrl *cptr) static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp) { - *vp = ((pvr2_hdw_get_signal_status_internal(cptr->hdw) & - PVR2_SIGNAL_OK) ? 1 : 0); + struct pvr2_hdw *hdw = cptr->hdw; + pvr2_i2c_core_status_poll(hdw); + *vp = hdw->tuner_signal_info.signal; + return 0; +} + +static int ctrl_audio_modes_present_get(struct pvr2_ctrl *cptr,int *vp) +{ + int val = 0; + unsigned int subchan; + struct pvr2_hdw *hdw = cptr->hdw; + if (hdw->tuner_signal_stale) { + pvr2_i2c_core_status_poll(hdw); + } + subchan = hdw->tuner_signal_info.rxsubchans; + if (subchan & V4L2_TUNER_SUB_MONO) { + val |= (1 << V4L2_TUNER_MODE_MONO); + } + if (subchan & V4L2_TUNER_SUB_STEREO) { + val |= (1 << V4L2_TUNER_MODE_STEREO); + } + if (subchan & V4L2_TUNER_SUB_LANG1) { + val |= (1 << V4L2_TUNER_MODE_LANG1); + } + if (subchan & V4L2_TUNER_SUB_LANG2) { + val |= (1 << V4L2_TUNER_MODE_LANG2); + } + *vp = val; return 0; } @@ -898,7 +923,20 @@ static const struct pvr2_ctl_info control_defs[] = { .desc = "Signal Present", .name = "signal_present", .get_value = ctrl_signal_get, - DEFBOOL, + DEFINT(0,65535), + },{ + .desc = "Audio Modes Present", + .name = "audio_modes_present", + .get_value = ctrl_audio_modes_present_get, + /* For this type we "borrow" the V4L2_TUNER_MODE enum from + v4l. Nothing outside of this module cares about this, + but I reuse it in order to also reuse the + control_values_audiomode string table. */ + DEFMASK(((1 << V4L2_TUNER_MODE_MONO)| + (1 << V4L2_TUNER_MODE_STEREO)| + (1 << V4L2_TUNER_MODE_LANG1)| + (1 << V4L2_TUNER_MODE_LANG2)), + control_values_audiomode), },{ .desc = "Video Standards Available Mask", .name = "video_standard_mask_available", @@ -1957,6 +1995,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw,pvr2_device_names[hdw_type]); if (!hdw) goto fail; memset(hdw,0,sizeof(*hdw)); + hdw->tuner_signal_stale = !0; cx2341x_fill_defaults(&hdw->enc_ctl_state); hdw->control_cnt = CTRLDEF_COUNT; @@ -2179,9 +2218,6 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) pvr2_stream_destroy(hdw->vid_stream); hdw->vid_stream = NULL; } - if (hdw->audio_stat) { - hdw->audio_stat->detach(hdw->audio_stat->ctxt); - } if (hdw->decoder_ctrl) { hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt); } @@ -2547,34 +2583,6 @@ const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw) } -/* Return bit mask indicating signal status */ -static unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw) -{ - unsigned int msk = 0; - switch (hdw->input_val) { - case PVR2_CVAL_INPUT_TV: - case PVR2_CVAL_INPUT_RADIO: - if (hdw->decoder_ctrl && - hdw->decoder_ctrl->tuned(hdw->decoder_ctrl->ctxt)) { - msk |= PVR2_SIGNAL_OK; - if (hdw->audio_stat && - hdw->audio_stat->status(hdw->audio_stat->ctxt)) { - if (hdw->flag_stereo) { - msk |= PVR2_SIGNAL_STEREO; - } - if (hdw->flag_bilingual) { - msk |= PVR2_SIGNAL_SAP; - } - } - } - break; - default: - msk |= PVR2_SIGNAL_OK | PVR2_SIGNAL_STEREO; - } - return msk; -} - - int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw) { int result; @@ -2590,14 +2598,25 @@ int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw) } -/* Return bit mask indicating signal status */ -unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *hdw) +/* Execute poll of tuner status */ +void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw) { - unsigned int msk = 0; LOCK_TAKE(hdw->big_lock); do { - msk = pvr2_hdw_get_signal_status_internal(hdw); + pvr2_i2c_core_status_poll(hdw); } while (0); LOCK_GIVE(hdw->big_lock); - return msk; +} + + +/* Return information about the tuner */ +int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp) +{ + LOCK_TAKE(hdw->big_lock); do { + if (hdw->tuner_signal_stale) { + pvr2_i2c_core_status_poll(hdw); + } + memcpy(vtp,&hdw->tuner_signal_info,sizeof(struct v4l2_tuner)); + } while (0); LOCK_GIVE(hdw->big_lock); + return 0; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index d803f24cc9e0..dc7a3ba8dd18 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -44,12 +44,6 @@ #define PVR2_CVAL_INPUT_COMPOSITE 2 #define PVR2_CVAL_INPUT_RADIO 3 -/* Values that pvr2_hdw_get_signal_status() returns */ -#define PVR2_SIGNAL_OK 0x0001 -#define PVR2_SIGNAL_STEREO 0x0002 -#define PVR2_SIGNAL_SAP 0x0004 - - /* Subsystem definitions - these are various pieces that can be independently stopped / started. Usually you don't want to mess with this directly (let the driver handle things itself), but it is useful @@ -155,8 +149,11 @@ int pvr2_hdw_commit_ctl(struct pvr2_hdw *); /* Return name for this driver instance */ const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *); -/* Return PVR2_SIGNAL_XXXX bit mask indicating signal status */ -unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *); +/* Mark tuner status stale so that it will be re-fetched */ +void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *); + +/* Return information about the tuner */ +int pvr2_hdw_get_tuner_status(struct pvr2_hdw *,struct v4l2_tuner *); /* Query device and see if it thinks it is on a high-speed USB link */ int pvr2_hdw_is_hsm(struct pvr2_hdw *); diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c index 05121666b9ba..16fa075a1eec 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c @@ -59,6 +59,7 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) (1 << OP_FREQ) | (1 << OP_SIZE) | (1 << OP_LOG)); + cp->status_poll = pvr2_v4l2_cmd_status_poll; if (id == I2C_DRIVERID_MSP3400) { if (pvr2_i2c_msp3400_setup(hdw,cp)) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c index 51da8945efe4..b1f6809625e8 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c @@ -37,6 +37,7 @@ static void set_standard(struct pvr2_hdw *hdw) vs = hdw->std_mask_cur; pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs); } + hdw->tuner_signal_stale = !0; } @@ -145,13 +146,21 @@ static void set_frequency(struct pvr2_hdw *hdw) struct v4l2_frequency freq; fv = pvr2_hdw_get_cur_freq(hdw); pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_freq(%lu)",fv); + if (hdw->tuner_signal_stale) { + pvr2_i2c_core_status_poll(hdw); + } memset(&freq,0,sizeof(freq)); - if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { + if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) { // ((fv * 1000) / 62500) freq.frequency = (fv * 2) / 125; - freq.type = V4L2_TUNER_RADIO; } else { freq.frequency = fv / 62500; + } + /* tuner-core currently doesn't seem to care about this, but + let's set it anyway for completeness. */ + if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { + freq.type = V4L2_TUNER_RADIO; + } else { freq.type = V4L2_TUNER_ANALOG_TV; } freq.tuner = 0; @@ -230,6 +239,12 @@ void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *cp,int fl) } +void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp) +{ + pvr2_i2c_client_cmd(cp,VIDIOC_G_TUNER,&cp->hdw->tuner_signal_info); +} + + /* Stuff for Emacs to see, in order to encourage consistent editing style: *** Local Variables: *** diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h index 894de610893b..6a9bb46d0654 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h @@ -34,6 +34,7 @@ extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size; extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log; void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *,int); +void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *); #endif /* __PVRUSB2_CMD_V4L2_H */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 62a7cfca837d..35a06652a60c 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -590,6 +590,27 @@ static int handler_check(struct pvr2_i2c_client *cp) #define BUFSIZE 500 + +void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw) +{ + struct list_head *item; + struct pvr2_i2c_client *cp; + mutex_lock(&hdw->i2c_list_lock); do { + struct v4l2_tuner *vtp = &hdw->tuner_signal_info; + memset(vtp,0,sizeof(vtp)); + list_for_each(item,&hdw->i2c_clients) { + cp = list_entry(item,struct pvr2_i2c_client,list); + if (!cp->detected_flag) continue; + if (!cp->status_poll) continue; + cp->status_poll(cp); + } + hdw->tuner_signal_stale = 0; + } while (0); mutex_unlock(&hdw->i2c_list_lock); +} + + +/* Issue various I2C operations to bring chip-level drivers into sync with + state stored in this driver. */ void pvr2_i2c_core_sync(struct pvr2_hdw *hdw) { unsigned long msk; @@ -876,6 +897,7 @@ static int pvr2_i2c_attach_inform(struct i2c_client *client) client->addr,cp); if (!cp) return -ENOMEM; memset(cp,0,sizeof(*cp)); + cp->hdw = hdw; INIT_LIST_HEAD(&cp->list); cp->client = client; mutex_lock(&hdw->i2c_list_lock); do { diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h index 6d7e25247576..bd0807b905bb 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h @@ -35,10 +35,12 @@ struct pvr2_i2c_client { struct i2c_client *client; struct pvr2_i2c_handler *handler; struct list_head list; + struct pvr2_hdw *hdw; int detected_flag; int recv_enable; unsigned long pend_mask; unsigned long ctl_mask; + void (*status_poll)(struct pvr2_i2c_client *); }; struct pvr2_i2c_handler { @@ -67,6 +69,7 @@ int pvr2_i2c_core_cmd(struct pvr2_hdw *,unsigned int cmd,void *arg); int pvr2_i2c_core_check_stale(struct pvr2_hdw *); void pvr2_i2c_core_sync(struct pvr2_hdw *); +void pvr2_i2c_core_status_poll(struct pvr2_hdw *); unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen); #define PVR2_I2C_DETAIL_DEBUG 0x0001 #define PVR2_I2C_DETAIL_HANDLER 0x0002 diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 655a722289ed..2a6763865266 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -95,25 +95,6 @@ static struct v4l2_capability pvr_capability ={ .reserved = {0,0,0,0} }; -static struct v4l2_tuner pvr_v4l2_tuners[]= { - { - .index = 0, - .name = "TV Tuner", - .type = V4L2_TUNER_ANALOG_TV, - .capability = (V4L2_TUNER_CAP_NORM | - V4L2_TUNER_CAP_STEREO | - V4L2_TUNER_CAP_LANG1 | - V4L2_TUNER_CAP_LANG2), - .rangelow = 0, - .rangehigh = 0, - .rxsubchans = V4L2_TUNER_SUB_STEREO, - .audmode = V4L2_TUNER_MODE_STEREO, - .signal = 0, - .afc = 0, - .reserved = {0,0,0,0} - } -}; - static struct v4l2_fmtdesc pvr_fmtdesc [] = { { .index = 0, @@ -358,34 +339,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_G_TUNER: { struct v4l2_tuner *vt = (struct v4l2_tuner *)arg; - unsigned int status_mask; - int val; - if (vt->index !=0) break; - - status_mask = pvr2_hdw_get_signal_status(hdw); - - memcpy(vt, &pvr_v4l2_tuners[vt->index], - sizeof(struct v4l2_tuner)); - - vt->signal = 0; - if (status_mask & PVR2_SIGNAL_OK) { - if (status_mask & PVR2_SIGNAL_STEREO) { - vt->rxsubchans = V4L2_TUNER_SUB_STEREO; - } else { - vt->rxsubchans = V4L2_TUNER_SUB_MONO; - } - if (status_mask & PVR2_SIGNAL_SAP) { - vt->rxsubchans |= (V4L2_TUNER_SUB_LANG1 | - V4L2_TUNER_SUB_LANG2); - } - vt->signal = 65535; - } - - val = 0; - ret = pvr2_ctrl_get_value( - pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE), - &val); - vt->audmode = val; + pvr2_hdw_execute_tuner_poll(hdw); + ret = pvr2_hdw_get_tuner_status(hdw,vt); break; } @@ -405,8 +360,27 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, { const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg; unsigned long fv; - fv = vf->frequency; + struct v4l2_tuner vt; + int cur_input; + struct pvr2_ctrl *ctrlp; + ret = pvr2_hdw_get_tuner_status(hdw,&vt); + if (ret != 0) break; + ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT); + ret = pvr2_ctrl_get_value(ctrlp,&cur_input); + if (ret != 0) break; if (vf->type == V4L2_TUNER_RADIO) { + if (cur_input != PVR2_CVAL_INPUT_RADIO) { + pvr2_ctrl_set_value(ctrlp, + PVR2_CVAL_INPUT_RADIO); + } + } else { + if (cur_input == PVR2_CVAL_INPUT_RADIO) { + pvr2_ctrl_set_value(ctrlp, + PVR2_CVAL_INPUT_TV); + } + } + fv = vf->frequency; + if (vt.capability & V4L2_TUNER_CAP_LOW) { fv = (fv * 125) / 2; } else { fv = fv * 62500; @@ -420,7 +394,10 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, { struct v4l2_frequency *vf = (struct v4l2_frequency *)arg; int val = 0; - int cur_input = PVR2_CVAL_INPUT_TV; + int cur_input; + struct v4l2_tuner vt; + ret = pvr2_hdw_get_tuner_status(hdw,&vt); + if (ret != 0) break; ret = pvr2_ctrl_get_value( pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY), &val); @@ -429,14 +406,16 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT), &cur_input); if (cur_input == PVR2_CVAL_INPUT_RADIO) { - val = (val * 2) / 125; - vf->frequency = val; vf->type = V4L2_TUNER_RADIO; } else { - val /= 62500; - vf->frequency = val; vf->type = V4L2_TUNER_ANALOG_TV; } + if (vt.capability & V4L2_TUNER_CAP_LOW) { + val = (val * 2) / 125; + } else { + val /= 62500; + } + vf->frequency = val; break; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c index 2a826464911a..8b37748cfcba 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c @@ -183,18 +183,6 @@ static void decoder_enable(struct pvr2_v4l_decoder *ctxt,int fl) } -static int decoder_is_tuned(struct pvr2_v4l_decoder *ctxt) -{ - struct v4l2_tuner vt; - int ret; - - memset(&vt,0,sizeof(vt)); - ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt); - if (ret < 0) return -EINVAL; - return vt.signal ? 1 : 0; -} - - static unsigned int decoder_describe(struct pvr2_v4l_decoder *ctxt,char *buf,unsigned int cnt) { return scnprintf(buf,cnt,"handler: pvrusb2-video-v4l"); @@ -227,7 +215,6 @@ int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *hdw, ctxt->ctrl.ctxt = ctxt; ctxt->ctrl.detach = (void (*)(void *))decoder_detach; ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable; - ctxt->ctrl.tuned = (int (*)(void *))decoder_is_tuned; ctxt->client = cp; ctxt->hdw = hdw; ctxt->stale_mask = (1 << (sizeof(decoder_ops)/