diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2008-10-04 07:36:54 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-10-12 07:37:16 -0400 |
commit | dd89601d47e2eeab7c17b25f2549444751bcffe4 (patch) | |
tree | da21e8b17e49d175f5b8cbd14a772bf00f7fb63a /drivers/media/video/ivtv/ivtv-streams.c | |
parent | e86a93dc3c870c412592c1f298c1425d80c58c6e (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.c | 40 |
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 = { | |||
75 | static struct { | 75 | static 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) | |||
171 | static int ivtv_prep_dev(struct ivtv *itv, int type) | 171 | static 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; |