diff options
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 69 |
1 files changed, 37 insertions, 32 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index b415141b2859..087a18245560 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | |||
@@ -57,6 +57,9 @@ 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 | /* Map contiguous ordinal value to input id */ | ||
61 | unsigned char *input_map; | ||
62 | unsigned int input_cnt; | ||
60 | }; | 63 | }; |
61 | 64 | ||
62 | struct pvr2_v4l2 { | 65 | struct pvr2_v4l2 { |
@@ -66,10 +69,6 @@ struct pvr2_v4l2 { | |||
66 | 69 | ||
67 | struct v4l2_prio_state prio; | 70 | struct v4l2_prio_state prio; |
68 | 71 | ||
69 | /* Map contiguous ordinal value to input id */ | ||
70 | unsigned char *input_map; | ||
71 | unsigned int input_cnt; | ||
72 | |||
73 | /* streams - Note that these must be separately, individually, | 72 | /* streams - Note that these must be separately, individually, |
74 | * allocated pointers. This is because the v4l core is going to | 73 | * allocated pointers. This is because the v4l core is going to |
75 | * manage their deletion - separately, individually... */ | 74 | * manage their deletion - separately, individually... */ |
@@ -269,11 +268,11 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
269 | memset(&tmp,0,sizeof(tmp)); | 268 | memset(&tmp,0,sizeof(tmp)); |
270 | tmp.index = vi->index; | 269 | tmp.index = vi->index; |
271 | ret = 0; | 270 | ret = 0; |
272 | if ((vi->index < 0) || (vi->index >= vp->input_cnt)) { | 271 | if ((vi->index < 0) || (vi->index >= fh->input_cnt)) { |
273 | ret = -EINVAL; | 272 | ret = -EINVAL; |
274 | break; | 273 | break; |
275 | } | 274 | } |
276 | val = vp->input_map[vi->index]; | 275 | val = fh->input_map[vi->index]; |
277 | switch (val) { | 276 | switch (val) { |
278 | case PVR2_CVAL_INPUT_TV: | 277 | case PVR2_CVAL_INPUT_TV: |
279 | case PVR2_CVAL_INPUT_DTV: | 278 | case PVR2_CVAL_INPUT_DTV: |
@@ -321,8 +320,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
321 | val = 0; | 320 | val = 0; |
322 | ret = pvr2_ctrl_get_value(cptr,&val); | 321 | ret = pvr2_ctrl_get_value(cptr,&val); |
323 | vi->index = 0; | 322 | vi->index = 0; |
324 | for (idx = 0; idx < vp->input_cnt; idx++) { | 323 | for (idx = 0; idx < fh->input_cnt; idx++) { |
325 | if (vp->input_map[idx] == val) { | 324 | if (fh->input_map[idx] == val) { |
326 | vi->index = idx; | 325 | vi->index = idx; |
327 | break; | 326 | break; |
328 | } | 327 | } |
@@ -333,13 +332,13 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
333 | case VIDIOC_S_INPUT: | 332 | case VIDIOC_S_INPUT: |
334 | { | 333 | { |
335 | struct v4l2_input *vi = (struct v4l2_input *)arg; | 334 | struct v4l2_input *vi = (struct v4l2_input *)arg; |
336 | if ((vi->index < 0) || (vi->index >= vp->input_cnt)) { | 335 | if ((vi->index < 0) || (vi->index >= fh->input_cnt)) { |
337 | ret = -ERANGE; | 336 | ret = -ERANGE; |
338 | break; | 337 | break; |
339 | } | 338 | } |
340 | ret = pvr2_ctrl_set_value( | 339 | ret = pvr2_ctrl_set_value( |
341 | pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT), | 340 | pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT), |
342 | vp->input_map[vi->index]); | 341 | fh->input_map[vi->index]); |
343 | break; | 342 | break; |
344 | } | 343 | } |
345 | 344 | ||
@@ -838,10 +837,6 @@ static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp) | |||
838 | pvr2_v4l2_dev_destroy(vp->dev_radio); | 837 | pvr2_v4l2_dev_destroy(vp->dev_radio); |
839 | vp->dev_radio = NULL; | 838 | vp->dev_radio = NULL; |
840 | } | 839 | } |
841 | if (vp->input_map) { | ||
842 | kfree(vp->input_map); | ||
843 | vp->input_map = NULL; | ||
844 | } | ||
845 | 840 | ||
846 | pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp); | 841 | pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp); |
847 | pvr2_channel_done(&vp->channel); | 842 | pvr2_channel_done(&vp->channel); |
@@ -915,6 +910,10 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file) | |||
915 | pvr2_channel_done(&fhp->channel); | 910 | pvr2_channel_done(&fhp->channel); |
916 | pvr2_trace(PVR2_TRACE_STRUCT, | 911 | pvr2_trace(PVR2_TRACE_STRUCT, |
917 | "Destroying pvr_v4l2_fh id=%p",fhp); | 912 | "Destroying pvr_v4l2_fh id=%p",fhp); |
913 | if (fhp->input_map) { | ||
914 | kfree(fhp->input_map); | ||
915 | fhp->input_map = NULL; | ||
916 | } | ||
918 | kfree(fhp); | 917 | kfree(fhp); |
919 | if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) { | 918 | if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) { |
920 | pvr2_v4l2_destroy_no_lock(vp); | 919 | pvr2_v4l2_destroy_no_lock(vp); |
@@ -930,6 +929,7 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) | |||
930 | struct pvr2_v4l2 *vp; | 929 | struct pvr2_v4l2 *vp; |
931 | struct pvr2_hdw *hdw; | 930 | struct pvr2_hdw *hdw; |
932 | unsigned int input_mask = 0; | 931 | unsigned int input_mask = 0; |
932 | unsigned int input_cnt,idx; | ||
933 | int ret = 0; | 933 | int ret = 0; |
934 | 934 | ||
935 | dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase); | 935 | dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase); |
@@ -979,6 +979,27 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) | |||
979 | return ret; | 979 | return ret; |
980 | } | 980 | } |
981 | 981 | ||
982 | input_mask &= pvr2_hdw_get_input_available(hdw); | ||
983 | input_cnt = 0; | ||
984 | for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) { | ||
985 | if (input_mask & (1 << idx)) input_cnt++; | ||
986 | } | ||
987 | fhp->input_cnt = input_cnt; | ||
988 | fhp->input_map = kzalloc(input_cnt,GFP_KERNEL); | ||
989 | if (!fhp->input_map) { | ||
990 | pvr2_channel_done(&fhp->channel); | ||
991 | pvr2_trace(PVR2_TRACE_STRUCT, | ||
992 | "Destroying pvr_v4l2_fh id=%p (input map failure)", | ||
993 | fhp); | ||
994 | kfree(fhp); | ||
995 | return -ENOMEM; | ||
996 | } | ||
997 | input_cnt = 0; | ||
998 | for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) { | ||
999 | if (!(input_mask & (1 << idx))) continue; | ||
1000 | fhp->input_map[input_cnt++] = idx; | ||
1001 | } | ||
1002 | |||
982 | fhp->vnext = NULL; | 1003 | fhp->vnext = NULL; |
983 | fhp->vprev = vp->vlast; | 1004 | fhp->vprev = vp->vlast; |
984 | if (vp->vlast) { | 1005 | if (vp->vlast) { |
@@ -1217,8 +1238,6 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, | |||
1217 | struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp) | 1238 | struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp) |
1218 | { | 1239 | { |
1219 | struct pvr2_v4l2 *vp; | 1240 | struct pvr2_v4l2 *vp; |
1220 | struct pvr2_hdw *hdw; | ||
1221 | unsigned int input_mask,input_cnt,idx; | ||
1222 | 1241 | ||
1223 | vp = kzalloc(sizeof(*vp),GFP_KERNEL); | 1242 | vp = kzalloc(sizeof(*vp),GFP_KERNEL); |
1224 | if (!vp) return vp; | 1243 | if (!vp) return vp; |
@@ -1227,26 +1246,12 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp) | |||
1227 | 1246 | ||
1228 | vp->channel.check_func = pvr2_v4l2_internal_check; | 1247 | vp->channel.check_func = pvr2_v4l2_internal_check; |
1229 | 1248 | ||
1230 | hdw = vp->channel.mc_head->hdw; | ||
1231 | input_mask = pvr2_hdw_get_input_available(hdw); | ||
1232 | input_cnt = 0; | ||
1233 | for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) { | ||
1234 | if (input_mask & (1 << idx)) input_cnt++; | ||
1235 | } | ||
1236 | vp->input_cnt = input_cnt; | ||
1237 | vp->input_map = kzalloc(input_cnt,GFP_KERNEL); | ||
1238 | if (!vp->input_map) goto fail; | ||
1239 | input_cnt = 0; | ||
1240 | for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) { | ||
1241 | if (!(input_mask & (1 << idx))) continue; | ||
1242 | vp->input_map[input_cnt++] = idx; | ||
1243 | } | ||
1244 | |||
1245 | /* register streams */ | 1249 | /* register streams */ |
1246 | vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL); | 1250 | vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL); |
1247 | if (!vp->dev_video) goto fail; | 1251 | if (!vp->dev_video) goto fail; |
1248 | pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER); | 1252 | pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER); |
1249 | if (input_mask & (1 << PVR2_CVAL_INPUT_RADIO)) { | 1253 | if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) & |
1254 | (1 << PVR2_CVAL_INPUT_RADIO)) { | ||
1250 | vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL); | 1255 | vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL); |
1251 | if (!vp->dev_radio) goto fail; | 1256 | if (!vp->dev_radio) goto fail; |
1252 | pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO); | 1257 | pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO); |