Commit 18103c57 authored by Mike Isely's avatar Mike Isely Committed by Mauro Carvalho Chehab

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: default avatarMike Isely <isely@pobox.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent af78a48b
...@@ -31,7 +31,6 @@ struct pvr2_msp3400_handler { ...@@ -31,7 +31,6 @@ struct pvr2_msp3400_handler {
struct pvr2_hdw *hdw; struct pvr2_hdw *hdw;
struct pvr2_i2c_client *client; struct pvr2_i2c_client *client;
struct pvr2_i2c_handler i2c_handler; struct pvr2_i2c_handler i2c_handler;
struct pvr2_audio_stat astat;
unsigned long stale_mask; unsigned long stale_mask;
}; };
...@@ -126,27 +125,9 @@ static void msp3400_update(struct pvr2_msp3400_handler *ctxt) ...@@ -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) static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt)
{ {
ctxt->client->handler = NULL; ctxt->client->handler = NULL;
ctxt->hdw->audio_stat = NULL;
kfree(ctxt); kfree(ctxt);
} }
...@@ -169,7 +150,6 @@ static const struct pvr2_i2c_handler_functions msp3400_funcs = { ...@@ -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) int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
{ {
struct pvr2_msp3400_handler *ctxt; struct pvr2_msp3400_handler *ctxt;
if (hdw->audio_stat) return 0;
if (cp->handler) return 0; if (cp->handler) return 0;
ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL); ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
...@@ -180,13 +160,9 @@ int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) ...@@ -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->i2c_handler.func_table = &msp3400_funcs;
ctxt->client = cp; ctxt->client = cp;
ctxt->hdw = hdw; 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)/ ctxt->stale_mask = (1 << (sizeof(msp3400_ops)/
sizeof(msp3400_ops[0]))) - 1; sizeof(msp3400_ops[0]))) - 1;
cp->handler = &ctxt->i2c_handler; cp->handler = &ctxt->i2c_handler;
hdw->audio_stat = &ctxt->astat;
pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x msp3400 V4L2 handler set up", pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x msp3400 V4L2 handler set up",
cp->client->addr); cp->client->addr);
return !0; return !0;
......
...@@ -199,18 +199,6 @@ static int decoder_detect(struct pvr2_i2c_client *cp) ...@@ -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, static unsigned int decoder_describe(struct pvr2_v4l_cx2584x *ctxt,
char *buf,unsigned int cnt) char *buf,unsigned int cnt)
{ {
...@@ -252,7 +240,6 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw, ...@@ -252,7 +240,6 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw,
ctxt->ctrl.ctxt = ctxt; ctxt->ctrl.ctxt = ctxt;
ctxt->ctrl.detach = (void (*)(void *))decoder_detach; ctxt->ctrl.detach = (void (*)(void *))decoder_detach;
ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable; 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->ctrl.force_reset = (void (*)(void*))decoder_reset;
ctxt->client = cp; ctxt->client = cp;
ctxt->hdw = hdw; ctxt->hdw = hdw;
......
...@@ -137,17 +137,10 @@ struct pvr2_ctrl { ...@@ -137,17 +137,10 @@ struct pvr2_ctrl {
}; };
struct pvr2_audio_stat {
void *ctxt;
void (*detach)(void *);
int (*status)(void *);
};
struct pvr2_decoder_ctrl { struct pvr2_decoder_ctrl {
void *ctxt; void *ctxt;
void (*detach)(void *); void (*detach)(void *);
void (*enable)(void *,int); void (*enable)(void *,int);
int (*tuned)(void *);
void (*force_reset)(void *); void (*force_reset)(void *);
}; };
...@@ -266,6 +259,10 @@ struct pvr2_hdw { ...@@ -266,6 +259,10 @@ struct pvr2_hdw {
unsigned int freqSelector; /* 0=radio 1=television */ unsigned int freqSelector; /* 0=radio 1=television */
int freqDirty; 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 */ /* Video standard handling */
v4l2_std_id std_mask_eeprom; // Hardware supported selections v4l2_std_id std_mask_eeprom; // Hardware supported selections
v4l2_std_id std_mask_avail; // Which standards we may select from v4l2_std_id std_mask_avail; // Which standards we may select from
...@@ -297,11 +294,6 @@ struct pvr2_hdw { ...@@ -297,11 +294,6 @@ struct pvr2_hdw {
enum pvr2_config config; 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 */ /* Control state needed for cx2341x module */
struct cx2341x_mpeg_params enc_cur_state; struct cx2341x_mpeg_params enc_cur_state;
struct cx2341x_mpeg_params enc_ctl_state; struct cx2341x_mpeg_params enc_ctl_state;
......
...@@ -264,7 +264,6 @@ static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long); ...@@ -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_cmd_usbstream(struct pvr2_hdw *hdw,int runFl);
static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw); static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw);
static int pvr2_hdw_get_eeprom_addr(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_find_stdenum(struct pvr2_hdw *hdw);
static void pvr2_hdw_internal_set_std_avail(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); 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) ...@@ -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) static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp)
{ {
*vp = ((pvr2_hdw_get_signal_status_internal(cptr->hdw) & struct pvr2_hdw *hdw = cptr->hdw;
PVR2_SIGNAL_OK) ? 1 : 0); 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; return 0;
} }
...@@ -898,7 +923,20 @@ static const struct pvr2_ctl_info control_defs[] = { ...@@ -898,7 +923,20 @@ static const struct pvr2_ctl_info control_defs[] = {
.desc = "Signal Present", .desc = "Signal Present",
.name = "signal_present", .name = "signal_present",
.get_value = ctrl_signal_get, .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", .desc = "Video Standards Available Mask",
.name = "video_standard_mask_available", .name = "video_standard_mask_available",
...@@ -1957,6 +1995,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, ...@@ -1957,6 +1995,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
hdw,pvr2_device_names[hdw_type]); hdw,pvr2_device_names[hdw_type]);
if (!hdw) goto fail; if (!hdw) goto fail;
memset(hdw,0,sizeof(*hdw)); memset(hdw,0,sizeof(*hdw));
hdw->tuner_signal_stale = !0;
cx2341x_fill_defaults(&hdw->enc_ctl_state); cx2341x_fill_defaults(&hdw->enc_ctl_state);
hdw->control_cnt = CTRLDEF_COUNT; hdw->control_cnt = CTRLDEF_COUNT;
...@@ -2179,9 +2218,6 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) ...@@ -2179,9 +2218,6 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
pvr2_stream_destroy(hdw->vid_stream); pvr2_stream_destroy(hdw->vid_stream);
hdw->vid_stream = NULL; hdw->vid_stream = NULL;
} }
if (hdw->audio_stat) {
hdw->audio_stat->detach(hdw->audio_stat->ctxt);
}
if (hdw->decoder_ctrl) { if (hdw->decoder_ctrl) {
hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt); hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt);
} }
...@@ -2547,34 +2583,6 @@ const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw) ...@@ -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 pvr2_hdw_is_hsm(struct pvr2_hdw *hdw)
{ {
int result; int result;
...@@ -2590,14 +2598,25 @@ int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw) ...@@ -2590,14 +2598,25 @@ int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw)
} }
/* Return bit mask indicating signal status */ /* Execute poll of tuner status */
unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *hdw) void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw)
{ {
unsigned int msk = 0;
LOCK_TAKE(hdw->big_lock); do { 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); } 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;
} }
......
...@@ -44,12 +44,6 @@ ...@@ -44,12 +44,6 @@
#define PVR2_CVAL_INPUT_COMPOSITE 2 #define PVR2_CVAL_INPUT_COMPOSITE 2
#define PVR2_CVAL_INPUT_RADIO 3 #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 /* Subsystem definitions - these are various pieces that can be
independently stopped / started. Usually you don't want to mess with independently stopped / started. Usually you don't want to mess with
this directly (let the driver handle things itself), but it is useful this directly (let the driver handle things itself), but it is useful
...@@ -155,8 +149,11 @@ int pvr2_hdw_commit_ctl(struct pvr2_hdw *); ...@@ -155,8 +149,11 @@ int pvr2_hdw_commit_ctl(struct pvr2_hdw *);
/* Return name for this driver instance */ /* Return name for this driver instance */
const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *); const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *);
/* Return PVR2_SIGNAL_XXXX bit mask indicating signal status */ /* Mark tuner status stale so that it will be re-fetched */
unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *); 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 */ /* Query device and see if it thinks it is on a high-speed USB link */
int pvr2_hdw_is_hsm(struct pvr2_hdw *); int pvr2_hdw_is_hsm(struct pvr2_hdw *);
......
...@@ -59,6 +59,7 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) ...@@ -59,6 +59,7 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
(1 << OP_FREQ) | (1 << OP_FREQ) |
(1 << OP_SIZE) | (1 << OP_SIZE) |
(1 << OP_LOG)); (1 << OP_LOG));
cp->status_poll = pvr2_v4l2_cmd_status_poll;
if (id == I2C_DRIVERID_MSP3400) { if (id == I2C_DRIVERID_MSP3400) {
if (pvr2_i2c_msp3400_setup(hdw,cp)) { if (pvr2_i2c_msp3400_setup(hdw,cp)) {
......
...@@ -37,6 +37,7 @@ static void set_standard(struct pvr2_hdw *hdw) ...@@ -37,6 +37,7 @@ static void set_standard(struct pvr2_hdw *hdw)
vs = hdw->std_mask_cur; vs = hdw->std_mask_cur;
pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs); 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) ...@@ -145,13 +146,21 @@ static void set_frequency(struct pvr2_hdw *hdw)
struct v4l2_frequency freq; struct v4l2_frequency freq;
fv = pvr2_hdw_get_cur_freq(hdw); fv = pvr2_hdw_get_cur_freq(hdw);
pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_freq(%lu)",fv); 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)); 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) // ((fv * 1000) / 62500)
freq.frequency = (fv * 2) / 125; freq.frequency = (fv * 2) / 125;
freq.type = V4L2_TUNER_RADIO;
} else { } else {
freq.frequency = fv / 62500; 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.type = V4L2_TUNER_ANALOG_TV;
} }
freq.tuner = 0; freq.tuner = 0;
...@@ -230,6 +239,12 @@ void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *cp,int fl) ...@@ -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: Stuff for Emacs to see, in order to encourage consistent editing style:
*** Local Variables: *** *** Local Variables: ***
......
...@@ -34,6 +34,7 @@ extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size; ...@@ -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; 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_stream(struct pvr2_i2c_client *,int);
void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *);
#endif /* __PVRUSB2_CMD_V4L2_H */ #endif /* __PVRUSB2_CMD_V4L2_H */
......
...@@ -590,6 +590,27 @@ static int handler_check(struct pvr2_i2c_client *cp) ...@@ -590,6 +590,27 @@ static int handler_check(struct pvr2_i2c_client *cp)
#define BUFSIZE 500 #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) void pvr2_i2c_core_sync(struct pvr2_hdw *hdw)
{ {
unsigned long msk; unsigned long msk;
...@@ -876,6 +897,7 @@ static int pvr2_i2c_attach_inform(struct i2c_client *client) ...@@ -876,6 +897,7 @@ static int pvr2_i2c_attach_inform(struct i2c_client *client)
client->addr,cp); client->addr,cp);
if (!cp) return -ENOMEM; if (!cp) return -ENOMEM;
memset(cp,0,sizeof(*cp)); memset(cp,0,sizeof(*cp));
cp->hdw = hdw;
INIT_LIST_HEAD(&cp->list); INIT_LIST_HEAD(&cp->list);
cp->client = client; cp->client = client;
mutex_lock(&hdw->i2c_list_lock); do { mutex_lock(&hdw->i2c_list_lock); do {
......
...@@ -35,10 +35,12 @@ struct pvr2_i2c_client { ...@@ -35,10 +35,12 @@ struct pvr2_i2c_client {
struct i2c_client *client; struct i2c_client *client;
struct pvr2_i2c_handler *handler; struct pvr2_i2c_handler *handler;
struct list_head list; struct list_head list;
struct pvr2_hdw *hdw;
int detected_flag; int detected_flag;
int recv_enable; int recv_enable;
unsigned long pend_mask; unsigned long pend_mask;
unsigned long ctl_mask; unsigned long ctl_mask;
void (*status_poll)(struct pvr2_i2c_client *);
}; };
struct pvr2_i2c_handler { struct pvr2_i2c_handler {
...@@ -67,6 +69,7 @@ int pvr2_i2c_core_cmd(struct pvr2_hdw *,unsigned int cmd,void *arg); ...@@ -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 *); int pvr2_i2c_core_check_stale(struct pvr2_hdw *);
void pvr2_i2c_core_sync(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); unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen);
#define PVR2_I2C_DETAIL_DEBUG 0x0001 #define PVR2_I2C_DETAIL_DEBUG 0x0001
#define PVR2_I2C_DETAIL_HANDLER 0x0002 #define PVR2_I2C_DETAIL_HANDLER 0x0002
......
...@@ -95,25 +95,6 @@ static struct v4l2_capability pvr_capability ={ ...@@ -95,25 +95,6 @@ static struct v4l2_capability pvr_capability ={
.reserved = {0,0,0,0} .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 [] = { static struct v4l2_fmtdesc pvr_fmtdesc [] = {
{ {
.index = 0, .index = 0,
...@@ -358,34 +339,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, ...@@ -358,34 +339,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_G_TUNER: case VIDIOC_G_TUNER:
{ {
struct v4l2_tuner *vt = (struct v4l2_tuner *)arg; struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
unsigned int status_mask; pvr2_hdw_execute_tuner_poll(hdw);
int val; ret = pvr2_hdw_get_tuner_status(hdw,vt);
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;
break; break;
} }
...@@ -405,8 +360,27 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, ...@@ -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; const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
unsigned long fv; 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 (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; fv = (fv * 125) / 2;
} else { } else {
fv = fv * 62500; fv = fv * 62500;
...@@ -420,7 +394,10 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, ...@@ -420,7 +394,10 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
{ {
struct v4l2_frequency *vf = (struct v4l2_frequency *)arg; struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
int val = 0; 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( ret = pvr2_ctrl_get_value(
pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY), pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
&val); &val);
...@@ -429,14 +406,16 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, ...@@ -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), pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
&cur_input); &cur_input);
if (cur_input == PVR2_CVAL_INPUT_RADIO) { if (cur_input == PVR2_CVAL_INPUT_RADIO) {
val = (val * 2) / 125;
vf->frequency = val;
vf->type = V4L2_TUNER_RADIO; vf->type = V4L2_TUNER_RADIO;
} else { } else {
val /= 62500;
vf->frequency = val;
vf->type = V4L2_TUNER_ANALOG_TV; vf->type = V4L2_TUNER_ANALOG_TV;
} }
if (vt.capability & V4L2_TUNER_CAP_LOW) {
val = (val * 2) / 125;
} else {
val /= 62500;
}
vf->frequency = val;
break; break;
} }
......
...@@ -183,18 +183,6 @@ static void decoder_enable(struct pvr2_v4l_decoder *ctxt,int fl) ...@@ -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) static unsigned int decoder_describe(struct pvr2_v4l_decoder *ctxt,char *buf,unsigned int cnt)
{ {
return scnprintf(buf,cnt,"handler: pvrusb2-video-v4l"); return scnprintf(buf,cnt,"handler: pvrusb2-video-v4l");
...@@ -227,7 +215,6 @@ int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *hdw, ...@@ -227,7 +215,6 @@ int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *hdw,
ctxt->ctrl.ctxt = ctxt; ctxt->ctrl.ctxt = ctxt;
ctxt->ctrl.detach = (void (*)(void *))decoder_detach; ctxt->ctrl.detach = (void (*)(void *))decoder_detach;
ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable; ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable;
ctxt->ctrl.tuned = (int (*)(void *))decoder_is_tuned;
ctxt->client = cp; ctxt->client = cp;
ctxt->hdw = hdw; ctxt->hdw = hdw;
ctxt->stale_mask = (1 << (sizeof(decoder_ops)/ ctxt->stale_mask = (1 << (sizeof(decoder_ops)/
......
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