aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ivtv/ivtv-streams.c
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2008-10-04 07:36:54 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-10-12 07:37:16 -0400
commitdd89601d47e2eeab7c17b25f2549444751bcffe4 (patch)
treeda21e8b17e49d175f5b8cbd14a772bf00f7fb63a /drivers/media/video/ivtv/ivtv-streams.c
parente86a93dc3c870c412592c1f298c1425d80c58c6e (diff)
V4L/DVB (9133): v4l: disconnect kernel number from minor
The v4l core creates four different video devices (video, vbi, radio, vtx) and each has its own range of minor numbers. However, modern devices keep increasing the number of devices that they need so a maximum of 64 video devices will not be enough in the future. In addition this scheme makes it very hard to add new device types. This patch disconnects the kernel number allocation (e.g. video0, video1, etc.) from the actual minor number (just pick the first free minor). This allows for much more flexibility in the future. However, it does require the use of udev. For those who cannot use udev a new CONFIG option was created that changes the allocation scheme back to the old behavior. Thanks to Greg KH for suggesting this approach during the 2008 LPC. In addition, several bugs were fixed in the ivtv and cx18 drivers: these drivers try to allocate specific kernel numbers but that scheme contained a bug which caused what should have been e.g. video17 to appear as e.g. video2. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/ivtv/ivtv-streams.c')
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.c40
1 files changed, 22 insertions, 18 deletions
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index 730e85d86fc8..24273fbea470 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -75,7 +75,7 @@ static const struct file_operations ivtv_v4l2_dec_fops = {
75static struct { 75static struct {
76 const char *name; 76 const char *name;
77 int vfl_type; 77 int vfl_type;
78 int minor_offset; 78 int num_offset;
79 int dma, pio; 79 int dma, pio;
80 enum v4l2_buf_type buf_type; 80 enum v4l2_buf_type buf_type;
81 const struct file_operations *fops; 81 const struct file_operations *fops;
@@ -171,8 +171,8 @@ static void ivtv_stream_init(struct ivtv *itv, int type)
171static int ivtv_prep_dev(struct ivtv *itv, int type) 171static int ivtv_prep_dev(struct ivtv *itv, int type)
172{ 172{
173 struct ivtv_stream *s = &itv->streams[type]; 173 struct ivtv_stream *s = &itv->streams[type];
174 int minor_offset = ivtv_stream_info[type].minor_offset; 174 int num_offset = ivtv_stream_info[type].num_offset;
175 int minor; 175 int num = itv->num + ivtv_first_minor + num_offset;
176 176
177 /* These four fields are always initialized. If v4l2dev == NULL, then 177 /* These four fields are always initialized. If v4l2dev == NULL, then
178 this stream is not in use. In that case no other fields but these 178 this stream is not in use. In that case no other fields but these
@@ -188,9 +188,6 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
188 if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) 188 if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
189 return 0; 189 return 0;
190 190
191 /* card number + user defined offset + device offset */
192 minor = itv->num + ivtv_first_minor + minor_offset;
193
194 /* User explicitly selected 0 buffers for these streams, so don't 191 /* User explicitly selected 0 buffers for these streams, so don't
195 create them. */ 192 create them. */
196 if (ivtv_stream_info[type].dma != PCI_DMA_NONE && 193 if (ivtv_stream_info[type].dma != PCI_DMA_NONE &&
@@ -211,7 +208,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
211 snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "ivtv%d %s", 208 snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "ivtv%d %s",
212 itv->num, s->name); 209 itv->num, s->name);
213 210
214 s->v4l2dev->minor = minor; 211 s->v4l2dev->num = num;
215 s->v4l2dev->parent = &itv->dev->dev; 212 s->v4l2dev->parent = &itv->dev->dev;
216 s->v4l2dev->fops = ivtv_stream_info[type].fops; 213 s->v4l2dev->fops = ivtv_stream_info[type].fops;
217 s->v4l2dev->release = video_device_release; 214 s->v4l2dev->release = video_device_release;
@@ -250,39 +247,46 @@ static int ivtv_reg_dev(struct ivtv *itv, int type)
250{ 247{
251 struct ivtv_stream *s = &itv->streams[type]; 248 struct ivtv_stream *s = &itv->streams[type];
252 int vfl_type = ivtv_stream_info[type].vfl_type; 249 int vfl_type = ivtv_stream_info[type].vfl_type;
253 int minor; 250 int num;
254 251
255 if (s->v4l2dev == NULL) 252 if (s->v4l2dev == NULL)
256 return 0; 253 return 0;
257 254
258 minor = s->v4l2dev->minor; 255 num = s->v4l2dev->num;
256 /* card number + user defined offset + device offset */
257 if (type != IVTV_ENC_STREAM_TYPE_MPG) {
258 struct ivtv_stream *s_mpg = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG];
259
260 if (s_mpg->v4l2dev)
261 num = s_mpg->v4l2dev->num + ivtv_stream_info[type].num_offset;
262 }
263
259 /* Register device. First try the desired minor, then any free one. */ 264 /* Register device. First try the desired minor, then any free one. */
260 if (video_register_device(s->v4l2dev, vfl_type, minor) && 265 if (video_register_device(s->v4l2dev, vfl_type, num)) {
261 video_register_device(s->v4l2dev, vfl_type, -1)) { 266 IVTV_ERR("Couldn't register v4l2 device for %s kernel number %d\n",
262 IVTV_ERR("Couldn't register v4l2 device for %s minor %d\n", 267 s->name, num);
263 s->name, minor);
264 video_device_release(s->v4l2dev); 268 video_device_release(s->v4l2dev);
265 s->v4l2dev = NULL; 269 s->v4l2dev = NULL;
266 return -ENOMEM; 270 return -ENOMEM;
267 } 271 }
272 num = s->v4l2dev->num;
268 273
269 switch (vfl_type) { 274 switch (vfl_type) {
270 case VFL_TYPE_GRABBER: 275 case VFL_TYPE_GRABBER:
271 IVTV_INFO("Registered device video%d for %s (%d kB)\n", 276 IVTV_INFO("Registered device video%d for %s (%d kB)\n",
272 s->v4l2dev->minor, s->name, itv->options.kilobytes[type]); 277 num, s->name, itv->options.kilobytes[type]);
273 break; 278 break;
274 case VFL_TYPE_RADIO: 279 case VFL_TYPE_RADIO:
275 IVTV_INFO("Registered device radio%d for %s\n", 280 IVTV_INFO("Registered device radio%d for %s\n",
276 s->v4l2dev->minor - MINOR_VFL_TYPE_RADIO_MIN, s->name); 281 num, s->name);
277 break; 282 break;
278 case VFL_TYPE_VBI: 283 case VFL_TYPE_VBI:
279 if (itv->options.kilobytes[type]) 284 if (itv->options.kilobytes[type])
280 IVTV_INFO("Registered device vbi%d for %s (%d kB)\n", 285 IVTV_INFO("Registered device vbi%d for %s (%d kB)\n",
281 s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN, 286 num, s->name, itv->options.kilobytes[type]);
282 s->name, itv->options.kilobytes[type]);
283 else 287 else
284 IVTV_INFO("Registered device vbi%d for %s\n", 288 IVTV_INFO("Registered device vbi%d for %s\n",
285 s->v4l2dev->minor - MINOR_VFL_TYPE_VBI_MIN, s->name); 289 num, s->name);
286 break; 290 break;
287 } 291 }
288 return 0; 292 return 0;