diff options
Diffstat (limited to 'drivers/media/video/pvrusb2/pvrusb2-hdw.c')
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-hdw.c | 132 |
1 files changed, 112 insertions, 20 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 63d0af759ed8..72e9056557bd 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
@@ -249,6 +249,7 @@ static const struct pvr2_fx2cmd_descdef pvr2_fx2cmd_desc[] = { | |||
249 | }; | 249 | }; |
250 | 250 | ||
251 | 251 | ||
252 | static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v); | ||
252 | static void pvr2_hdw_state_sched(struct pvr2_hdw *); | 253 | static void pvr2_hdw_state_sched(struct pvr2_hdw *); |
253 | static int pvr2_hdw_state_eval(struct pvr2_hdw *); | 254 | static int pvr2_hdw_state_eval(struct pvr2_hdw *); |
254 | static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long); | 255 | static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long); |
@@ -404,30 +405,12 @@ static int ctrl_get_input(struct pvr2_ctrl *cptr,int *vp) | |||
404 | 405 | ||
405 | static int ctrl_check_input(struct pvr2_ctrl *cptr,int v) | 406 | static int ctrl_check_input(struct pvr2_ctrl *cptr,int v) |
406 | { | 407 | { |
407 | return ((1 << v) & cptr->hdw->input_avail_mask) != 0; | 408 | return ((1 << v) & cptr->hdw->input_allowed_mask) != 0; |
408 | } | 409 | } |
409 | 410 | ||
410 | static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v) | 411 | static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v) |
411 | { | 412 | { |
412 | struct pvr2_hdw *hdw = cptr->hdw; | 413 | return pvr2_hdw_set_input(cptr->hdw,v); |
413 | |||
414 | if (hdw->input_val != v) { | ||
415 | hdw->input_val = v; | ||
416 | hdw->input_dirty = !0; | ||
417 | } | ||
418 | |||
419 | /* Handle side effects - if we switch to a mode that needs the RF | ||
420 | tuner, then select the right frequency choice as well and mark | ||
421 | it dirty. */ | ||
422 | if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { | ||
423 | hdw->freqSelector = 0; | ||
424 | hdw->freqDirty = !0; | ||
425 | } else if ((hdw->input_val == PVR2_CVAL_INPUT_TV) || | ||
426 | (hdw->input_val == PVR2_CVAL_INPUT_DTV)) { | ||
427 | hdw->freqSelector = 1; | ||
428 | hdw->freqDirty = !0; | ||
429 | } | ||
430 | return 0; | ||
431 | } | 414 | } |
432 | 415 | ||
433 | static int ctrl_isdirty_input(struct pvr2_ctrl *cptr) | 416 | static int ctrl_isdirty_input(struct pvr2_ctrl *cptr) |
@@ -1916,6 +1899,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
1916 | if (hdw_desc->flag_has_composite) m |= 1 << PVR2_CVAL_INPUT_COMPOSITE; | 1899 | if (hdw_desc->flag_has_composite) m |= 1 << PVR2_CVAL_INPUT_COMPOSITE; |
1917 | if (hdw_desc->flag_has_fmradio) m |= 1 << PVR2_CVAL_INPUT_RADIO; | 1900 | if (hdw_desc->flag_has_fmradio) m |= 1 << PVR2_CVAL_INPUT_RADIO; |
1918 | hdw->input_avail_mask = m; | 1901 | hdw->input_avail_mask = m; |
1902 | hdw->input_allowed_mask = hdw->input_avail_mask; | ||
1919 | 1903 | ||
1920 | /* If not a hybrid device, pathway_state never changes. So | 1904 | /* If not a hybrid device, pathway_state never changes. So |
1921 | initialize it here to what it should forever be. */ | 1905 | initialize it here to what it should forever be. */ |
@@ -3948,6 +3932,24 @@ static int pvr2_hdw_state_update(struct pvr2_hdw *hdw) | |||
3948 | } | 3932 | } |
3949 | 3933 | ||
3950 | 3934 | ||
3935 | static unsigned int print_input_mask(unsigned int msk, | ||
3936 | char *buf,unsigned int acnt) | ||
3937 | { | ||
3938 | unsigned int idx,ccnt; | ||
3939 | unsigned int tcnt = 0; | ||
3940 | for (idx = 0; idx < ARRAY_SIZE(control_values_input); idx++) { | ||
3941 | if (!((1 << idx) & msk)) continue; | ||
3942 | ccnt = scnprintf(buf+tcnt, | ||
3943 | acnt-tcnt, | ||
3944 | "%s%s", | ||
3945 | (tcnt ? ", " : ""), | ||
3946 | control_values_input[idx]); | ||
3947 | tcnt += ccnt; | ||
3948 | } | ||
3949 | return tcnt; | ||
3950 | } | ||
3951 | |||
3952 | |||
3951 | static const char *pvr2_pathway_state_name(int id) | 3953 | static const char *pvr2_pathway_state_name(int id) |
3952 | { | 3954 | { |
3953 | switch (id) { | 3955 | switch (id) { |
@@ -4016,6 +4018,28 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, | |||
4016 | "state: %s", | 4018 | "state: %s", |
4017 | pvr2_get_state_name(hdw->master_state)); | 4019 | pvr2_get_state_name(hdw->master_state)); |
4018 | case 4: { | 4020 | case 4: { |
4021 | unsigned int tcnt = 0; | ||
4022 | unsigned int ccnt; | ||
4023 | |||
4024 | ccnt = scnprintf(buf, | ||
4025 | acnt, | ||
4026 | "Hardware supported inputs: "); | ||
4027 | tcnt += ccnt; | ||
4028 | tcnt += print_input_mask(hdw->input_avail_mask, | ||
4029 | buf+tcnt, | ||
4030 | acnt-tcnt); | ||
4031 | if (hdw->input_avail_mask != hdw->input_allowed_mask) { | ||
4032 | ccnt = scnprintf(buf+tcnt, | ||
4033 | acnt-tcnt, | ||
4034 | "; allowed inputs: "); | ||
4035 | tcnt += ccnt; | ||
4036 | tcnt += print_input_mask(hdw->input_allowed_mask, | ||
4037 | buf+tcnt, | ||
4038 | acnt-tcnt); | ||
4039 | } | ||
4040 | return tcnt; | ||
4041 | } | ||
4042 | case 5: { | ||
4019 | struct pvr2_stream_stats stats; | 4043 | struct pvr2_stream_stats stats; |
4020 | if (!hdw->vid_stream) break; | 4044 | if (!hdw->vid_stream) break; |
4021 | pvr2_stream_get_stats(hdw->vid_stream, | 4045 | pvr2_stream_get_stats(hdw->vid_stream, |
@@ -4210,6 +4234,74 @@ unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *hdw) | |||
4210 | } | 4234 | } |
4211 | 4235 | ||
4212 | 4236 | ||
4237 | unsigned int pvr2_hdw_get_input_allowed(struct pvr2_hdw *hdw) | ||
4238 | { | ||
4239 | return hdw->input_allowed_mask; | ||
4240 | } | ||
4241 | |||
4242 | |||
4243 | static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v) | ||
4244 | { | ||
4245 | if (hdw->input_val != v) { | ||
4246 | hdw->input_val = v; | ||
4247 | hdw->input_dirty = !0; | ||
4248 | } | ||
4249 | |||
4250 | /* Handle side effects - if we switch to a mode that needs the RF | ||
4251 | tuner, then select the right frequency choice as well and mark | ||
4252 | it dirty. */ | ||
4253 | if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { | ||
4254 | hdw->freqSelector = 0; | ||
4255 | hdw->freqDirty = !0; | ||
4256 | } else if ((hdw->input_val == PVR2_CVAL_INPUT_TV) || | ||
4257 | (hdw->input_val == PVR2_CVAL_INPUT_DTV)) { | ||
4258 | hdw->freqSelector = 1; | ||
4259 | hdw->freqDirty = !0; | ||
4260 | } | ||
4261 | return 0; | ||
4262 | } | ||
4263 | |||
4264 | |||
4265 | int pvr2_hdw_set_input_allowed(struct pvr2_hdw *hdw, | ||
4266 | unsigned int change_mask, | ||
4267 | unsigned int change_val) | ||
4268 | { | ||
4269 | int ret = 0; | ||
4270 | unsigned int nv,m,idx; | ||
4271 | LOCK_TAKE(hdw->big_lock); | ||
4272 | do { | ||
4273 | nv = hdw->input_allowed_mask & ~change_mask; | ||
4274 | nv |= (change_val & change_mask); | ||
4275 | nv &= hdw->input_avail_mask; | ||
4276 | if (!nv) { | ||
4277 | /* No legal modes left; return error instead. */ | ||
4278 | ret = -EPERM; | ||
4279 | break; | ||
4280 | } | ||
4281 | hdw->input_allowed_mask = nv; | ||
4282 | if ((1 << hdw->input_val) & hdw->input_allowed_mask) { | ||
4283 | /* Current mode is still in the allowed mask, so | ||
4284 | we're done. */ | ||
4285 | break; | ||
4286 | } | ||
4287 | /* Select and switch to a mode that is still in the allowed | ||
4288 | mask */ | ||
4289 | if (!hdw->input_allowed_mask) { | ||
4290 | /* Nothing legal; give up */ | ||
4291 | break; | ||
4292 | } | ||
4293 | m = hdw->input_allowed_mask; | ||
4294 | for (idx = 0; idx < (sizeof(m) << 3); idx++) { | ||
4295 | if (!((1 << idx) & m)) continue; | ||
4296 | pvr2_hdw_set_input(hdw,idx); | ||
4297 | break; | ||
4298 | } | ||
4299 | } while (0); | ||
4300 | LOCK_GIVE(hdw->big_lock); | ||
4301 | return ret; | ||
4302 | } | ||
4303 | |||
4304 | |||
4213 | /* Find I2C address of eeprom */ | 4305 | /* Find I2C address of eeprom */ |
4214 | static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw) | 4306 | static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw) |
4215 | { | 4307 | { |