aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-v4l2.c69
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
62struct pvr2_v4l2 { 65struct 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,
1217struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp) 1238struct 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);