aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-v4l2.c103
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
37struct pvr2_v4l2_dev; 35struct pvr2_v4l2_dev;
38struct pvr2_v4l2_fh; 36struct pvr2_v4l2_fh;
39struct pvr2_v4l2; 37struct 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
72static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1}; 73static 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
716static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) 717static 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
731static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp) 771static 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}