aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18/cx18-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/cx18/cx18-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/cx18/cx18-streams.c')
-rw-r--r--drivers/media/video/cx18/cx18-streams.c41
1 files changed, 22 insertions, 19 deletions
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index c752a6a4dbd3..0c8e7542cf60 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -57,7 +57,7 @@ static struct file_operations cx18_v4l2_enc_fops = {
57static struct { 57static struct {
58 const char *name; 58 const char *name;
59 int vfl_type; 59 int vfl_type;
60 int minor_offset; 60 int num_offset;
61 int dma; 61 int dma;
62 enum v4l2_buf_type buf_type; 62 enum v4l2_buf_type buf_type;
63 struct file_operations *fops; 63 struct file_operations *fops;
@@ -144,8 +144,8 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
144{ 144{
145 struct cx18_stream *s = &cx->streams[type]; 145 struct cx18_stream *s = &cx->streams[type];
146 u32 cap = cx->v4l2_cap; 146 u32 cap = cx->v4l2_cap;
147 int minor_offset = cx18_stream_info[type].minor_offset; 147 int num_offset = cx18_stream_info[type].num_offset;
148 int minor; 148 int num = cx->num + cx18_first_minor + num_offset;
149 149
150 /* These four fields are always initialized. If v4l2dev == NULL, then 150 /* These four fields are always initialized. If v4l2dev == NULL, then
151 this stream is not in use. In that case no other fields but these 151 this stream is not in use. In that case no other fields but these
@@ -164,9 +164,6 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
164 !(cap & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE))) 164 !(cap & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE)))
165 return 0; 165 return 0;
166 166
167 /* card number + user defined offset + device offset */
168 minor = cx->num + cx18_first_minor + minor_offset;
169
170 /* User explicitly selected 0 buffers for these streams, so don't 167 /* User explicitly selected 0 buffers for these streams, so don't
171 create them. */ 168 create them. */
172 if (cx18_stream_info[type].dma != PCI_DMA_NONE && 169 if (cx18_stream_info[type].dma != PCI_DMA_NONE &&
@@ -177,7 +174,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
177 174
178 cx18_stream_init(cx, type); 175 cx18_stream_init(cx, type);
179 176
180 if (minor_offset == -1) 177 if (num_offset == -1)
181 return 0; 178 return 0;
182 179
183 /* allocate and initialize the v4l2 video device structure */ 180 /* allocate and initialize the v4l2 video device structure */
@@ -191,7 +188,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
191 snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "cx18-%d", 188 snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "cx18-%d",
192 cx->num); 189 cx->num);
193 190
194 s->v4l2dev->minor = minor; 191 s->v4l2dev->num = num;
195 s->v4l2dev->parent = &cx->dev->dev; 192 s->v4l2dev->parent = &cx->dev->dev;
196 s->v4l2dev->fops = cx18_stream_info[type].fops; 193 s->v4l2dev->fops = cx18_stream_info[type].fops;
197 s->v4l2dev->release = video_device_release; 194 s->v4l2dev->release = video_device_release;
@@ -227,7 +224,7 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
227{ 224{
228 struct cx18_stream *s = &cx->streams[type]; 225 struct cx18_stream *s = &cx->streams[type];
229 int vfl_type = cx18_stream_info[type].vfl_type; 226 int vfl_type = cx18_stream_info[type].vfl_type;
230 int minor; 227 int num;
231 228
232 /* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something? 229 /* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something?
233 * We need a VFL_TYPE_TS defined. 230 * We need a VFL_TYPE_TS defined.
@@ -245,38 +242,44 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
245 if (s->v4l2dev == NULL) 242 if (s->v4l2dev == NULL)
246 return 0; 243 return 0;
247 244
248 minor = s->v4l2dev->minor; 245 num = s->v4l2dev->num;
246 /* card number + user defined offset + device offset */
247 if (type != CX18_ENC_STREAM_TYPE_MPG) {
248 struct cx18_stream *s_mpg = &cx->streams[CX18_ENC_STREAM_TYPE_MPG];
249
250 if (s_mpg->v4l2dev)
251 num = s_mpg->v4l2dev->num + cx18_stream_info[type].num_offset;
252 }
249 253
250 /* Register device. First try the desired minor, then any free one. */ 254 /* Register device. First try the desired minor, then any free one. */
251 if (video_register_device(s->v4l2dev, vfl_type, minor) && 255 if (video_register_device(s->v4l2dev, vfl_type, num)) {
252 video_register_device(s->v4l2dev, vfl_type, -1)) { 256 CX18_ERR("Couldn't register v4l2 device for %s kernel number %d\n",
253 CX18_ERR("Couldn't register v4l2 device for %s minor %d\n", 257 s->name, num);
254 s->name, minor);
255 video_device_release(s->v4l2dev); 258 video_device_release(s->v4l2dev);
256 s->v4l2dev = NULL; 259 s->v4l2dev = NULL;
257 return -ENOMEM; 260 return -ENOMEM;
258 } 261 }
259 minor = s->v4l2dev->minor; 262 num = s->v4l2dev->num;
260 263
261 switch (vfl_type) { 264 switch (vfl_type) {
262 case VFL_TYPE_GRABBER: 265 case VFL_TYPE_GRABBER:
263 CX18_INFO("Registered device video%d for %s (%d MB)\n", 266 CX18_INFO("Registered device video%d for %s (%d MB)\n",
264 minor, s->name, cx->options.megabytes[type]); 267 num, s->name, cx->options.megabytes[type]);
265 break; 268 break;
266 269
267 case VFL_TYPE_RADIO: 270 case VFL_TYPE_RADIO:
268 CX18_INFO("Registered device radio%d for %s\n", 271 CX18_INFO("Registered device radio%d for %s\n",
269 minor - MINOR_VFL_TYPE_RADIO_MIN, s->name); 272 num, s->name);
270 break; 273 break;
271 274
272 case VFL_TYPE_VBI: 275 case VFL_TYPE_VBI:
273 if (cx->options.megabytes[type]) 276 if (cx->options.megabytes[type])
274 CX18_INFO("Registered device vbi%d for %s (%d MB)\n", 277 CX18_INFO("Registered device vbi%d for %s (%d MB)\n",
275 minor - MINOR_VFL_TYPE_VBI_MIN, 278 num,
276 s->name, cx->options.megabytes[type]); 279 s->name, cx->options.megabytes[type]);
277 else 280 else
278 CX18_INFO("Registered device vbi%d for %s\n", 281 CX18_INFO("Registered device vbi%d for %s\n",
279 minor - MINOR_VFL_TYPE_VBI_MIN, s->name); 282 num, s->name);
280 break; 283 break;
281 } 284 }
282 285