aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMike Isely <isely@pobox.com>2008-04-21 02:47:43 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-04-24 13:09:49 -0400
commit1cb03b76d09d20accfa5c1664c16ba6566f539a0 (patch)
tree8c58f23151ab54f71472b80f6d0d29df25ddbb9f /drivers
parentd3f8d8fb304a8b9a81eae16ff7b50f5379f2437e (diff)
V4L/DVB (7719): pvrusb2: Implement input selection enforcement
In the pvrusb2 driver, different interfaces (e.g. V4L, DVB) have Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-context.c69
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-context.h3
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-dvb.c47
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h4
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c132
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.h13
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-v4l2.c52
7 files changed, 246 insertions, 74 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c
index a2ce022c515a..b5db6a5bab31 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-context.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-context.c
@@ -245,6 +245,22 @@ struct pvr2_context *pvr2_context_create(
245} 245}
246 246
247 247
248static void pvr2_context_reset_input_limits(struct pvr2_context *mp)
249{
250 unsigned int tmsk,mmsk;
251 struct pvr2_channel *cp;
252 struct pvr2_hdw *hdw = mp->hdw;
253 mmsk = pvr2_hdw_get_input_available(hdw);
254 tmsk = mmsk;
255 for (cp = mp->mc_first; cp; cp = cp->mc_next) {
256 if (!cp->input_mask) continue;
257 tmsk &= cp->input_mask;
258 }
259 pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk);
260 pvr2_hdw_commit_ctl(hdw);
261}
262
263
248static void pvr2_context_enter(struct pvr2_context *mp) 264static void pvr2_context_enter(struct pvr2_context *mp)
249{ 265{
250 mutex_lock(&mp->mutex); 266 mutex_lock(&mp->mutex);
@@ -300,7 +316,9 @@ void pvr2_channel_done(struct pvr2_channel *cp)
300{ 316{
301 struct pvr2_context *mp = cp->mc_head; 317 struct pvr2_context *mp = cp->mc_head;
302 pvr2_context_enter(mp); 318 pvr2_context_enter(mp);
319 cp->input_mask = 0;
303 pvr2_channel_disclaim_stream(cp); 320 pvr2_channel_disclaim_stream(cp);
321 pvr2_context_reset_input_limits(mp);
304 if (cp->mc_next) { 322 if (cp->mc_next) {
305 cp->mc_next->mc_prev = cp->mc_prev; 323 cp->mc_next->mc_prev = cp->mc_prev;
306 } else { 324 } else {
@@ -316,6 +334,57 @@ void pvr2_channel_done(struct pvr2_channel *cp)
316} 334}
317 335
318 336
337int pvr2_channel_limit_inputs(struct pvr2_channel *cp,unsigned int cmsk)
338{
339 unsigned int tmsk,mmsk;
340 int ret = 0;
341 struct pvr2_channel *p2;
342 struct pvr2_hdw *hdw = cp->hdw;
343
344 mmsk = pvr2_hdw_get_input_available(hdw);
345 cmsk &= mmsk;
346 if (cmsk == cp->input_mask) {
347 /* No change; nothing to do */
348 return 0;
349 }
350
351 pvr2_context_enter(cp->mc_head);
352 do {
353 if (!cmsk) {
354 cp->input_mask = 0;
355 pvr2_context_reset_input_limits(cp->mc_head);
356 break;
357 }
358 tmsk = mmsk;
359 for (p2 = cp->mc_head->mc_first; p2; p2 = p2->mc_next) {
360 if (p2 == cp) continue;
361 if (!p2->input_mask) continue;
362 tmsk &= p2->input_mask;
363 }
364 if (!(tmsk & cmsk)) {
365 ret = -EPERM;
366 break;
367 }
368 tmsk &= cmsk;
369 if ((ret = pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk)) != 0) {
370 /* Internal failure changing allowed list; probably
371 should not happen, but react if it does. */
372 break;
373 }
374 cp->input_mask = cmsk;
375 pvr2_hdw_commit_ctl(hdw);
376 } while (0);
377 pvr2_context_exit(cp->mc_head);
378 return ret;
379}
380
381
382unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *cp)
383{
384 return cp->input_mask;
385}
386
387
319int pvr2_channel_claim_stream(struct pvr2_channel *cp, 388int pvr2_channel_claim_stream(struct pvr2_channel *cp,
320 struct pvr2_context_stream *sp) 389 struct pvr2_context_stream *sp)
321{ 390{
diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.h b/drivers/media/video/pvrusb2/pvrusb2-context.h
index 6fb6ab022851..745e270233c2 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-context.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-context.h
@@ -62,6 +62,7 @@ struct pvr2_channel {
62 struct pvr2_channel *mc_prev; 62 struct pvr2_channel *mc_prev;
63 struct pvr2_context_stream *stream; 63 struct pvr2_context_stream *stream;
64 struct pvr2_hdw *hdw; 64 struct pvr2_hdw *hdw;
65 unsigned int input_mask;
65 void (*check_func)(struct pvr2_channel *); 66 void (*check_func)(struct pvr2_channel *);
66}; 67};
67 68
@@ -72,6 +73,8 @@ void pvr2_context_disconnect(struct pvr2_context *);
72 73
73void pvr2_channel_init(struct pvr2_channel *,struct pvr2_context *); 74void pvr2_channel_init(struct pvr2_channel *,struct pvr2_context *);
74void pvr2_channel_done(struct pvr2_channel *); 75void pvr2_channel_done(struct pvr2_channel *);
76int pvr2_channel_limit_inputs(struct pvr2_channel *,unsigned int);
77unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *);
75int pvr2_channel_claim_stream(struct pvr2_channel *, 78int pvr2_channel_claim_stream(struct pvr2_channel *,
76 struct pvr2_context_stream *); 79 struct pvr2_context_stream *);
77struct pvr2_ioread *pvr2_channel_create_mpeg_stream( 80struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c
index c20eef0f077e..2e64f98d1241 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c
@@ -244,13 +244,10 @@ static int pvr2_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
244 244
245static int pvr2_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) 245static int pvr2_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
246{ 246{
247 /* TO DO: This function will call into the core and request for 247 struct pvr2_dvb_adapter *adap = fe->dvb->priv;
248 * input to be set to 'dtv' if (acquire) and if it isn't set already. 248 return pvr2_channel_limit_inputs(
249 * 249 &adap->channel,
250 * If (!acquire) then we should do nothing -- don't switch inputs 250 (acquire ? (1 << PVR2_CVAL_INPUT_DTV) : 0));
251 * again unless the analog side of the driver requests the bus.
252 */
253 return 0;
254} 251}
255 252
256static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap) 253static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap)
@@ -320,32 +317,26 @@ static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
320{ 317{
321 struct pvr2_hdw *hdw = adap->channel.hdw; 318 struct pvr2_hdw *hdw = adap->channel.hdw;
322 struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props; 319 struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props;
323 int ret; 320 int ret = 0;
324 321
325 if (dvb_props == NULL) { 322 if (dvb_props == NULL) {
326 err("fe_props not defined!"); 323 err("fe_props not defined!");
327 return -EINVAL; 324 return -EINVAL;
328 } 325 }
329 326
330 /* FIXME: This code should be moved into the core, 327 ret = pvr2_channel_limit_inputs(
331 * and should only be called if we don't already have 328 &adap->channel,
332 * control of the bus. 329 (1 << PVR2_CVAL_INPUT_DTV));
333 * 330 if (ret) {
334 * We can't call "pvr2_dvb_bus_ctrl(adap->fe, 1)" from here, 331 err("failed to grab control of dtv input (code=%d)",
335 * because adap->fe isn't defined yet. 332 ret);
336 */
337 ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_by_id(hdw,
338 PVR2_CID_INPUT),
339 PVR2_CVAL_INPUT_DTV);
340 if (ret != 0)
341 return ret; 333 return ret;
342 334 }
343 pvr2_hdw_commit_ctl(hdw);
344
345 335
346 if (dvb_props->frontend_attach == NULL) { 336 if (dvb_props->frontend_attach == NULL) {
347 err("frontend_attach not defined!"); 337 err("frontend_attach not defined!");
348 return -EINVAL; 338 ret = -EINVAL;
339 goto done;
349 } 340 }
350 341
351 if ((dvb_props->frontend_attach(adap) == 0) && (adap->fe)) { 342 if ((dvb_props->frontend_attach(adap) == 0) && (adap->fe)) {
@@ -354,7 +345,8 @@ static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
354 err("frontend registration failed!"); 345 err("frontend registration failed!");
355 dvb_frontend_detach(adap->fe); 346 dvb_frontend_detach(adap->fe);
356 adap->fe = NULL; 347 adap->fe = NULL;
357 return -ENODEV; 348 ret = -ENODEV;
349 goto done;
358 } 350 }
359 351
360 if (dvb_props->tuner_attach) 352 if (dvb_props->tuner_attach)
@@ -368,10 +360,13 @@ static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
368 360
369 } else { 361 } else {
370 err("no frontend was attached!"); 362 err("no frontend was attached!");
371 return -ENODEV; 363 ret = -ENODEV;
364 return ret;
372 } 365 }
373 366
374 return 0; 367 done:
368 pvr2_channel_limit_inputs(&adap->channel, 0);
369 return ret;
375} 370}
376 371
377static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap) 372static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap)
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
index a67dcf84b596..a3fe251d6fd9 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
@@ -336,8 +336,10 @@ struct pvr2_hdw {
336 int v4l_minor_number_vbi; 336 int v4l_minor_number_vbi;
337 int v4l_minor_number_radio; 337 int v4l_minor_number_radio;
338 338
339 /* Bit mask of PVR2_CVAL_INPUT choices which are valid */ 339 /* Bit mask of PVR2_CVAL_INPUT choices which are valid for the hardware */
340 unsigned int input_avail_mask; 340 unsigned int input_avail_mask;
341 /* Bit mask of PVR2_CVAL_INPUT choices which are currenly allowed */
342 unsigned int input_allowed_mask;
341 343
342 /* Location of eeprom or a negative number if none */ 344 /* Location of eeprom or a negative number if none */
343 int eeprom_addr; 345 int eeprom_addr;
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
252static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v);
252static void pvr2_hdw_state_sched(struct pvr2_hdw *); 253static void pvr2_hdw_state_sched(struct pvr2_hdw *);
253static int pvr2_hdw_state_eval(struct pvr2_hdw *); 254static int pvr2_hdw_state_eval(struct pvr2_hdw *);
254static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long); 255static 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
405static int ctrl_check_input(struct pvr2_ctrl *cptr,int v) 406static 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
410static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v) 411static 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
433static int ctrl_isdirty_input(struct pvr2_ctrl *cptr) 416static 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
3935static 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
3951static const char *pvr2_pathway_state_name(int id) 3953static 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
4237unsigned int pvr2_hdw_get_input_allowed(struct pvr2_hdw *hdw)
4238{
4239 return hdw->input_allowed_mask;
4240}
4241
4242
4243static 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
4265int 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 */
4214static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw) 4306static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
4215{ 4307{
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
index 74c2503f8e3f..20295e0c1995 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
@@ -149,6 +149,19 @@ int pvr2_hdw_commit_ctl(struct pvr2_hdw *);
149 * will be according to PVR_CVAL_INPUT_xxxx definitions. */ 149 * will be according to PVR_CVAL_INPUT_xxxx definitions. */
150unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *); 150unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *);
151 151
152/* Return a bit mask of allowed input selections for this device. Mask bits
153 * will be according to PVR_CVAL_INPUT_xxxx definitions. */
154unsigned int pvr2_hdw_get_input_allowed(struct pvr2_hdw *);
155
156/* Change the set of allowed input selections for this device. Both
157 change_mask and change_valu are mask bits according to
158 PVR_CVAL_INPUT_xxxx definitions. The change_mask parameter indicate
159 which settings are being changed and the change_val parameter indicates
160 whether corresponding settings are being set or cleared. */
161int pvr2_hdw_set_input_allowed(struct pvr2_hdw *,
162 unsigned int change_mask,
163 unsigned int change_val);
164
152/* Return name for this driver instance */ 165/* Return name for this driver instance */
153const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *); 166const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *);
154 167
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index 249d7488e482..b415141b2859 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -57,7 +57,6 @@ struct pvr2_v4l2_fh {
57 struct pvr2_v4l2_fh *vprev; 57 struct pvr2_v4l2_fh *vprev;
58 wait_queue_head_t wait_data; 58 wait_queue_head_t wait_data;
59 int fw_mode_flag; 59 int fw_mode_flag;
60 int prev_input_val;
61}; 60};
62 61
63struct pvr2_v4l2 { 62struct pvr2_v4l2 {
@@ -900,20 +899,6 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file)
900 v4l2_prio_close(&vp->prio, &fhp->prio); 899 v4l2_prio_close(&vp->prio, &fhp->prio);
901 file->private_data = NULL; 900 file->private_data = NULL;
902 901
903 /* Restore the previous input selection, if it makes sense
904 to do so. */
905 if (fhp->dev_info->v4l_type == VFL_TYPE_RADIO) {
906 struct pvr2_ctrl *cp;
907 int pval;
908 cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
909 pvr2_ctrl_get_value(cp,&pval);
910 /* Only restore if we're still selecting the radio */
911 if (pval == PVR2_CVAL_INPUT_RADIO) {
912 pvr2_ctrl_set_value(cp,fhp->prev_input_val);
913 pvr2_hdw_commit_ctl(hdw);
914 }
915 }
916
917 if (fhp->vnext) { 902 if (fhp->vnext) {
918 fhp->vnext->vprev = fhp->vprev; 903 fhp->vnext->vprev = fhp->vprev;
919 } else { 904 } else {
@@ -944,6 +929,8 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file)
944 struct pvr2_v4l2_fh *fhp; 929 struct pvr2_v4l2_fh *fhp;
945 struct pvr2_v4l2 *vp; 930 struct pvr2_v4l2 *vp;
946 struct pvr2_hdw *hdw; 931 struct pvr2_hdw *hdw;
932 unsigned int input_mask = 0;
933 int ret = 0;
947 934
948 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase); 935 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
949 936
@@ -969,6 +956,29 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file)
969 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp); 956 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
970 pvr2_channel_init(&fhp->channel,vp->channel.mc_head); 957 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
971 958
959 if (dip->v4l_type == VFL_TYPE_RADIO) {
960 /* Opening device as a radio, legal input selection subset
961 is just the radio. */
962 input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
963 } else {
964 /* Opening the main V4L device, legal input selection
965 subset includes all analog inputs. */
966 input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
967 (1 << PVR2_CVAL_INPUT_TV) |
968 (1 << PVR2_CVAL_INPUT_COMPOSITE) |
969 (1 << PVR2_CVAL_INPUT_SVIDEO));
970 }
971 ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
972 if (ret) {
973 pvr2_channel_done(&fhp->channel);
974 pvr2_trace(PVR2_TRACE_STRUCT,
975 "Destroying pvr_v4l2_fh id=%p (input mask error)",
976 fhp);
977
978 kfree(fhp);
979 return ret;
980 }
981
972 fhp->vnext = NULL; 982 fhp->vnext = NULL;
973 fhp->vprev = vp->vlast; 983 fhp->vprev = vp->vlast;
974 if (vp->vlast) { 984 if (vp->vlast) {
@@ -979,18 +989,6 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file)
979 vp->vlast = fhp; 989 vp->vlast = fhp;
980 fhp->vhead = vp; 990 fhp->vhead = vp;
981 991
982 /* Opening the /dev/radioX device implies a mode switch.
983 So execute that here. Note that you can get the
984 IDENTICAL effect merely by opening the normal video
985 device and setting the input appropriately. */
986 if (dip->v4l_type == VFL_TYPE_RADIO) {
987 struct pvr2_ctrl *cp;
988 cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
989 pvr2_ctrl_get_value(cp,&fhp->prev_input_val);
990 pvr2_ctrl_set_value(cp,PVR2_CVAL_INPUT_RADIO);
991 pvr2_hdw_commit_ctl(hdw);
992 }
993
994 fhp->file = file; 992 fhp->file = file;
995 file->private_data = fhp; 993 file->private_data = fhp;
996 v4l2_prio_open(&vp->prio,&fhp->prio); 994 v4l2_prio_open(&vp->prio,&fhp->prio);