diff options
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 103 |
1 files changed, 74 insertions, 29 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 28187fbb5414..d5a54e8b72d5 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | |||
@@ -32,8 +32,6 @@ | |||
32 | #include <media/v4l2-dev.h> | 32 | #include <media/v4l2-dev.h> |
33 | #include <media/v4l2-common.h> | 33 | #include <media/v4l2-common.h> |
34 | 34 | ||
35 | #define PVR2_NR_STREAMS 3 | ||
36 | |||
37 | struct pvr2_v4l2_dev; | 35 | struct pvr2_v4l2_dev; |
38 | struct pvr2_v4l2_fh; | 36 | struct pvr2_v4l2_fh; |
39 | struct pvr2_v4l2; | 37 | struct pvr2_v4l2; |
@@ -65,8 +63,11 @@ struct pvr2_v4l2 { | |||
65 | 63 | ||
66 | struct v4l2_prio_state prio; | 64 | struct v4l2_prio_state prio; |
67 | 65 | ||
68 | /* streams */ | 66 | /* streams - Note that these must be separately, individually, |
69 | struct pvr2_v4l2_dev *vdev; | 67 | * allocated pointers. This is because the v4l core is going to |
68 | * manage their deletion - separately, individually... */ | ||
69 | struct pvr2_v4l2_dev *dev_video; | ||
70 | struct pvr2_v4l2_dev *dev_radio; | ||
70 | }; | 71 | }; |
71 | 72 | ||
72 | static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1}; | 73 | static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1}; |
@@ -715,8 +716,26 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
715 | 716 | ||
716 | static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) | 717 | static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) |
717 | { | 718 | { |
718 | printk(KERN_INFO "pvrusb2: unregistering device video%d [%s]\n", | 719 | enum pvr2_config cfg = dip->config; |
719 | dip->devbase.minor,pvr2_config_get_name(dip->config)); | 720 | int minor_id = dip->devbase.minor; |
721 | enum pvr2_v4l_type pvt; | ||
722 | struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw; | ||
723 | |||
724 | switch (cfg) { | ||
725 | case pvr2_config_mpeg: | ||
726 | pvt = pvr2_v4l_type_video; | ||
727 | break; | ||
728 | case pvr2_config_vbi: | ||
729 | pvt = pvr2_v4l_type_vbi; | ||
730 | break; | ||
731 | case pvr2_config_radio: | ||
732 | pvt = pvr2_v4l_type_radio; | ||
733 | break; | ||
734 | default: /* paranoia */ | ||
735 | pvt = pvr2_v4l_type_video; | ||
736 | break; | ||
737 | } | ||
738 | pvr2_hdw_v4l_store_minor_number(hdw,pvt,-1); | ||
720 | 739 | ||
721 | /* Paranoia */ | 740 | /* Paranoia */ |
722 | dip->v4lp = NULL; | 741 | dip->v4lp = NULL; |
@@ -725,18 +744,40 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) | |||
725 | /* Actual deallocation happens later when all internal references | 744 | /* Actual deallocation happens later when all internal references |
726 | are gone. */ | 745 | are gone. */ |
727 | video_unregister_device(&dip->devbase); | 746 | video_unregister_device(&dip->devbase); |
747 | |||
748 | switch (cfg) { | ||
749 | case pvr2_config_mpeg: | ||
750 | printk(KERN_INFO "pvrusb2: unregistered device video%d [%s]\n", | ||
751 | minor_id & 0x1f, | ||
752 | pvr2_config_get_name(cfg)); | ||
753 | break; | ||
754 | case pvr2_config_radio: | ||
755 | printk(KERN_INFO "pvrusb2: unregistered device radio%d [%s]\n", | ||
756 | minor_id & 0x1f, | ||
757 | pvr2_config_get_name(cfg)); | ||
758 | break; | ||
759 | case pvr2_config_vbi: | ||
760 | printk(KERN_INFO "pvrusb2: unregistered device vbi%d [%s]\n", | ||
761 | minor_id & 0x1f, | ||
762 | pvr2_config_get_name(cfg)); | ||
763 | break; | ||
764 | default: | ||
765 | break; | ||
766 | } | ||
767 | |||
728 | } | 768 | } |
729 | 769 | ||
730 | 770 | ||
731 | static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp) | 771 | static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp) |
732 | { | 772 | { |
733 | pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw, | 773 | if (vp->dev_video) { |
734 | pvr2_v4l_type_video,-1); | 774 | pvr2_v4l2_dev_destroy(vp->dev_video); |
735 | pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw, | 775 | vp->dev_video = 0; |
736 | pvr2_v4l_type_vbi,-1); | 776 | } |
737 | pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw, | 777 | if (vp->dev_radio) { |
738 | pvr2_v4l_type_radio,-1); | 778 | pvr2_v4l2_dev_destroy(vp->dev_radio); |
739 | pvr2_v4l2_dev_destroy(vp->vdev); | 779 | vp->dev_radio = 0; |
780 | } | ||
740 | 781 | ||
741 | pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp); | 782 | pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp); |
742 | pvr2_channel_done(&vp->channel); | 783 | pvr2_channel_done(&vp->channel); |
@@ -1085,7 +1126,7 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, | |||
1085 | dip->config = cfg; | 1126 | dip->config = cfg; |
1086 | 1127 | ||
1087 | 1128 | ||
1088 | switch (cfg) { | 1129 | switch (dip->config) { |
1089 | case pvr2_config_mpeg: | 1130 | case pvr2_config_mpeg: |
1090 | v4l_type = VFL_TYPE_GRABBER; | 1131 | v4l_type = VFL_TYPE_GRABBER; |
1091 | pvt = pvr2_v4l_type_video; | 1132 | pvt = pvr2_v4l_type_video; |
@@ -1107,7 +1148,7 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, | |||
1107 | } | 1148 | } |
1108 | 1149 | ||
1109 | /* radio device doesn 't need its own stream */ | 1150 | /* radio device doesn 't need its own stream */ |
1110 | if (!dip->stream && cfg != pvr2_config_radio) { | 1151 | if (!dip->stream && dip->config != pvr2_config_radio) { |
1111 | err("Failed to set up pvrusb2 v4l dev" | 1152 | err("Failed to set up pvrusb2 v4l dev" |
1112 | " due to missing stream instance"); | 1153 | " due to missing stream instance"); |
1113 | return; | 1154 | return; |
@@ -1136,24 +1177,24 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, | |||
1136 | (video_register_device(&dip->devbase, v4l_type, -1) < 0)) { | 1177 | (video_register_device(&dip->devbase, v4l_type, -1) < 0)) { |
1137 | err("Failed to register pvrusb2 v4l device"); | 1178 | err("Failed to register pvrusb2 v4l device"); |
1138 | } | 1179 | } |
1139 | switch (cfg) { | 1180 | switch (dip->config) { |
1140 | case pvr2_config_mpeg: | 1181 | case pvr2_config_mpeg: |
1141 | printk(KERN_INFO "pvrusb2: registered device video%d [%s]\n", | 1182 | printk(KERN_INFO "pvrusb2: registered device video%d [%s]\n", |
1142 | dip->devbase.minor & 0x1f, | 1183 | dip->devbase.minor & 0x1f, |
1143 | pvr2_config_get_name(dip->config)); | 1184 | pvr2_config_get_name(dip->config)); |
1144 | break; | 1185 | break; |
1145 | case pvr2_config_vbi: | ||
1146 | printk(KERN_INFO "pvrusb2: registered device vbi%d [%s]\n", | ||
1147 | dip->devbase.minor & 0x1f, | ||
1148 | pvr2_config_get_name(dip->config)); | ||
1149 | break; | ||
1150 | case pvr2_config_radio: | 1186 | case pvr2_config_radio: |
1151 | printk(KERN_INFO "pvrusb2: registered device radio%d [%s]\n", | 1187 | printk(KERN_INFO "pvrusb2: registered device radio%d [%s]\n", |
1152 | dip->devbase.minor & 0x1f, | 1188 | dip->devbase.minor & 0x1f, |
1153 | pvr2_config_get_name(dip->config)); | 1189 | pvr2_config_get_name(dip->config)); |
1154 | break; | 1190 | break; |
1191 | case pvr2_config_vbi: | ||
1192 | printk(KERN_INFO "pvrusb2: registered device vbi%d [%s]\n", | ||
1193 | dip->devbase.minor & 0x1f, | ||
1194 | pvr2_config_get_name(dip->config)); | ||
1195 | break; | ||
1155 | default: | 1196 | default: |
1156 | break; | 1197 | break; |
1157 | } | 1198 | } |
1158 | 1199 | ||
1159 | pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw, | 1200 | pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw, |
@@ -1168,20 +1209,24 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp) | |||
1168 | vp = kmalloc(sizeof(*vp),GFP_KERNEL); | 1209 | vp = kmalloc(sizeof(*vp),GFP_KERNEL); |
1169 | if (!vp) return vp; | 1210 | if (!vp) return vp; |
1170 | memset(vp,0,sizeof(*vp)); | 1211 | memset(vp,0,sizeof(*vp)); |
1171 | vp->vdev = kmalloc(sizeof(*vp->vdev)*PVR2_NR_STREAMS,GFP_KERNEL); | 1212 | vp->dev_video = kmalloc(sizeof(*vp->dev_video),GFP_KERNEL); |
1172 | if (!vp->vdev) { | 1213 | vp->dev_radio = kmalloc(sizeof(*vp->dev_radio),GFP_KERNEL); |
1214 | if (!(vp->dev_video && vp->dev_radio)) { | ||
1215 | if (vp->dev_video) kfree(vp->dev_video); | ||
1216 | if (vp->dev_radio) kfree(vp->dev_radio); | ||
1173 | kfree(vp); | 1217 | kfree(vp); |
1174 | return NULL; | 1218 | return NULL; |
1175 | } | 1219 | } |
1176 | memset(vp->vdev,0,sizeof(*vp->vdev)*PVR2_NR_STREAMS); | 1220 | memset(vp->dev_video,0,sizeof(*vp->dev_video)); |
1221 | memset(vp->dev_radio,0,sizeof(*vp->dev_radio)); | ||
1177 | pvr2_channel_init(&vp->channel,mnp); | 1222 | pvr2_channel_init(&vp->channel,mnp); |
1178 | pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp); | 1223 | pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp); |
1179 | 1224 | ||
1180 | vp->channel.check_func = pvr2_v4l2_internal_check; | 1225 | vp->channel.check_func = pvr2_v4l2_internal_check; |
1181 | 1226 | ||
1182 | /* register streams */ | 1227 | /* register streams */ |
1183 | pvr2_v4l2_dev_init(&vp->vdev[0],vp,pvr2_config_mpeg); | 1228 | pvr2_v4l2_dev_init(vp->dev_video,vp,pvr2_config_mpeg); |
1184 | pvr2_v4l2_dev_init(&vp->vdev[2],vp,pvr2_config_radio); | 1229 | pvr2_v4l2_dev_init(vp->dev_radio,vp,pvr2_config_radio); |
1185 | 1230 | ||
1186 | return vp; | 1231 | return vp; |
1187 | } | 1232 | } |