aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/v4l2-dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/v4l2-dev.c')
-rw-r--r--drivers/media/video/v4l2-dev.c96
1 files changed, 65 insertions, 31 deletions
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index 7addf2fd55de..ccd6566a515e 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -65,6 +65,7 @@ static struct device_attribute video_device_attrs[] = {
65 */ 65 */
66static struct video_device *video_device[VIDEO_NUM_DEVICES]; 66static struct video_device *video_device[VIDEO_NUM_DEVICES];
67static DEFINE_MUTEX(videodev_lock); 67static DEFINE_MUTEX(videodev_lock);
68static DECLARE_BITMAP(video_nums[VFL_TYPE_MAX], VIDEO_NUM_DEVICES);
68 69
69struct video_device *video_device_alloc(void) 70struct video_device *video_device_alloc(void)
70{ 71{
@@ -99,6 +100,7 @@ static void v4l2_chardev_release(struct kobject *kobj)
99 100
100 /* Free up this device for reuse */ 101 /* Free up this device for reuse */
101 video_device[vfd->minor] = NULL; 102 video_device[vfd->minor] = NULL;
103 clear_bit(vfd->num, video_nums[vfd->vfl_type]);
102 mutex_unlock(&videodev_lock); 104 mutex_unlock(&videodev_lock);
103 105
104 /* Release the character device */ 106 /* Release the character device */
@@ -217,10 +219,10 @@ int video_register_device_index(struct video_device *vfd, int type, int nr,
217 int index) 219 int index)
218{ 220{
219 int i = 0; 221 int i = 0;
220 int base;
221 int end;
222 int ret; 222 int ret;
223 char *name_base; 223 int minor_offset = 0;
224 int minor_cnt = VIDEO_NUM_DEVICES;
225 const char *name_base;
224 void *priv = video_get_drvdata(vfd); 226 void *priv = video_get_drvdata(vfd);
225 227
226 /* the release callback MUST be present */ 228 /* the release callback MUST be present */
@@ -231,23 +233,15 @@ int video_register_device_index(struct video_device *vfd, int type, int nr,
231 233
232 switch (type) { 234 switch (type) {
233 case VFL_TYPE_GRABBER: 235 case VFL_TYPE_GRABBER:
234 base = MINOR_VFL_TYPE_GRABBER_MIN;
235 end = MINOR_VFL_TYPE_GRABBER_MAX+1;
236 name_base = "video"; 236 name_base = "video";
237 break; 237 break;
238 case VFL_TYPE_VTX: 238 case VFL_TYPE_VTX:
239 base = MINOR_VFL_TYPE_VTX_MIN;
240 end = MINOR_VFL_TYPE_VTX_MAX+1;
241 name_base = "vtx"; 239 name_base = "vtx";
242 break; 240 break;
243 case VFL_TYPE_VBI: 241 case VFL_TYPE_VBI:
244 base = MINOR_VFL_TYPE_VBI_MIN;
245 end = MINOR_VFL_TYPE_VBI_MAX+1;
246 name_base = "vbi"; 242 name_base = "vbi";
247 break; 243 break;
248 case VFL_TYPE_RADIO: 244 case VFL_TYPE_RADIO:
249 base = MINOR_VFL_TYPE_RADIO_MIN;
250 end = MINOR_VFL_TYPE_RADIO_MAX+1;
251 name_base = "radio"; 245 name_base = "radio";
252 break; 246 break;
253 default: 247 default:
@@ -256,31 +250,70 @@ int video_register_device_index(struct video_device *vfd, int type, int nr,
256 return -EINVAL; 250 return -EINVAL;
257 } 251 }
258 252
253 vfd->vfl_type = type;
254
255#ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES
256 /* Keep the ranges for the first four types for historical
257 * reasons.
258 * Newer devices (not yet in place) should use the range
259 * of 128-191 and just pick the first free minor there
260 * (new style). */
261 switch (type) {
262 case VFL_TYPE_GRABBER:
263 minor_offset = 0;
264 minor_cnt = 64;
265 break;
266 case VFL_TYPE_RADIO:
267 minor_offset = 64;
268 minor_cnt = 64;
269 break;
270 case VFL_TYPE_VTX:
271 minor_offset = 192;
272 minor_cnt = 32;
273 break;
274 case VFL_TYPE_VBI:
275 minor_offset = 224;
276 minor_cnt = 32;
277 break;
278 default:
279 minor_offset = 128;
280 minor_cnt = 64;
281 break;
282 }
283#endif
284
259 /* Initialize the character device */ 285 /* Initialize the character device */
260 cdev_init(&vfd->cdev, vfd->fops); 286 cdev_init(&vfd->cdev, vfd->fops);
261 vfd->cdev.owner = vfd->fops->owner; 287 vfd->cdev.owner = vfd->fops->owner;
262 /* pick a minor number */ 288 /* pick a minor number */
263 mutex_lock(&videodev_lock); 289 mutex_lock(&videodev_lock);
264 if (nr >= 0 && nr < end-base) { 290 nr = find_next_zero_bit(video_nums[type], minor_cnt, nr == -1 ? 0 : nr);
265 /* use the one the driver asked for */ 291 if (nr == minor_cnt)
266 i = base + nr; 292 nr = find_first_zero_bit(video_nums[type], minor_cnt);
267 if (NULL != video_device[i]) { 293 if (nr == minor_cnt) {
268 mutex_unlock(&videodev_lock); 294 printk(KERN_ERR "could not get a free kernel number\n");
269 return -ENFILE; 295 mutex_unlock(&videodev_lock);
270 } 296 return -ENFILE;
271 } else {
272 /* use first free */
273 for (i = base; i < end; i++)
274 if (NULL == video_device[i])
275 break;
276 if (i == end) {
277 mutex_unlock(&videodev_lock);
278 return -ENFILE;
279 }
280 } 297 }
281 video_device[i] = vfd; 298#ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES
282 vfd->vfl_type = type; 299 /* 1-on-1 mapping of kernel number to minor number */
283 vfd->minor = i; 300 i = nr;
301#else
302 /* The kernel number and minor numbers are independent */
303 for (i = 0; i < VIDEO_NUM_DEVICES; i++)
304 if (video_device[i] == NULL)
305 break;
306 if (i == VIDEO_NUM_DEVICES) {
307 mutex_unlock(&videodev_lock);
308 printk(KERN_ERR "could not get a free minor\n");
309 return -ENFILE;
310 }
311#endif
312 vfd->minor = i + minor_offset;
313 vfd->num = nr;
314 set_bit(nr, video_nums[type]);
315 BUG_ON(video_device[vfd->minor]);
316 video_device[vfd->minor] = vfd;
284 317
285 ret = get_index(vfd, index); 318 ret = get_index(vfd, index);
286 vfd->index = ret; 319 vfd->index = ret;
@@ -306,7 +339,7 @@ int video_register_device_index(struct video_device *vfd, int type, int nr,
306 vfd->dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor); 339 vfd->dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor);
307 if (vfd->parent) 340 if (vfd->parent)
308 vfd->dev.parent = vfd->parent; 341 vfd->dev.parent = vfd->parent;
309 sprintf(vfd->dev.bus_id, "%s%d", name_base, i - base); 342 sprintf(vfd->dev.bus_id, "%s%d", name_base, nr);
310 ret = device_register(&vfd->dev); 343 ret = device_register(&vfd->dev);
311 if (ret < 0) { 344 if (ret < 0) {
312 printk(KERN_ERR "%s: device_register failed\n", __func__); 345 printk(KERN_ERR "%s: device_register failed\n", __func__);
@@ -324,6 +357,7 @@ del_cdev:
324fail_minor: 357fail_minor:
325 mutex_lock(&videodev_lock); 358 mutex_lock(&videodev_lock);
326 video_device[vfd->minor] = NULL; 359 video_device[vfd->minor] = NULL;
360 clear_bit(vfd->num, video_nums[type]);
327 mutex_unlock(&videodev_lock); 361 mutex_unlock(&videodev_lock);
328 vfd->minor = -1; 362 vfd->minor = -1;
329 return ret; 363 return ret;