diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2010-04-10 03:13:53 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-05-19 11:57:59 -0400 |
commit | 730947bc141b7e8feb091dcf3ee8e6a7b9379512 (patch) | |
tree | dc61a06d5a7aed48b6c115054de127500773882a /drivers/media/video/vivi.c | |
parent | 474675ad8006834be996c046b47436d8ca7a5105 (diff) |
V4L/DVB: vivi: clean up and a major overhaul
- Clean up the code
- Use the kernel's built-in vga8x16 font instead of our own.
- Drop exclusive open: now multiple users can open the device as per the V4L2 spec.
- Move the format description to the vivi device instead of keeping it in the file
handle. Again as per the spec.
- Streamline and simplify the drawing code. It is now easy to add text on top of
the colorbar pattern.
- Upgrade the max resolution to 1920x1200.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/vivi.c')
-rw-r--r-- | drivers/media/video/vivi.c | 809 |
1 files changed, 324 insertions, 485 deletions
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 5a736b8a5a33..d5e30b85c559 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
@@ -13,29 +13,22 @@ | |||
13 | * License, or (at your option) any later version | 13 | * License, or (at your option) any later version |
14 | */ | 14 | */ |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/delay.h> | ||
17 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
18 | #include <linux/fs.h> | ||
19 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
20 | #include <linux/slab.h> | ||
21 | #include <linux/mm.h> | ||
22 | #include <linux/ioport.h> | ||
23 | #include <linux/init.h> | 18 | #include <linux/init.h> |
24 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
25 | #include <linux/pci.h> | 20 | #include <linux/font.h> |
26 | #include <linux/random.h> | ||
27 | #include <linux/version.h> | 21 | #include <linux/version.h> |
28 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
29 | #include <linux/videodev2.h> | 23 | #include <linux/videodev2.h> |
30 | #include <linux/dma-mapping.h> | ||
31 | #include <linux/interrupt.h> | ||
32 | #include <linux/kthread.h> | 24 | #include <linux/kthread.h> |
33 | #include <linux/highmem.h> | 25 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) |
34 | #include <linux/freezer.h> | 26 | #include <linux/freezer.h> |
27 | #endif | ||
35 | #include <media/videobuf-vmalloc.h> | 28 | #include <media/videobuf-vmalloc.h> |
36 | #include <media/v4l2-device.h> | 29 | #include <media/v4l2-device.h> |
37 | #include <media/v4l2-ioctl.h> | 30 | #include <media/v4l2-ioctl.h> |
38 | #include "font.h" | 31 | #include <media/v4l2-common.h> |
39 | 32 | ||
40 | #define VIVI_MODULE_NAME "vivi" | 33 | #define VIVI_MODULE_NAME "vivi" |
41 | 34 | ||
@@ -44,8 +37,11 @@ | |||
44 | #define WAKE_DENOMINATOR 1001 | 37 | #define WAKE_DENOMINATOR 1001 |
45 | #define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */ | 38 | #define BUFFER_TIMEOUT msecs_to_jiffies(500) /* 0.5 seconds */ |
46 | 39 | ||
40 | #define MAX_WIDTH 1920 | ||
41 | #define MAX_HEIGHT 1200 | ||
42 | |||
47 | #define VIVI_MAJOR_VERSION 0 | 43 | #define VIVI_MAJOR_VERSION 0 |
48 | #define VIVI_MINOR_VERSION 6 | 44 | #define VIVI_MINOR_VERSION 7 |
49 | #define VIVI_RELEASE 0 | 45 | #define VIVI_RELEASE 0 |
50 | #define VIVI_VERSION \ | 46 | #define VIVI_VERSION \ |
51 | KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE) | 47 | KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE) |
@@ -70,56 +66,8 @@ static unsigned int vid_limit = 16; | |||
70 | module_param(vid_limit, uint, 0644); | 66 | module_param(vid_limit, uint, 0644); |
71 | MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); | 67 | MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); |
72 | 68 | ||
73 | 69 | /* Global font descriptor */ | |
74 | /* supported controls */ | 70 | static const u8 *font8x16; |
75 | static struct v4l2_queryctrl vivi_qctrl[] = { | ||
76 | { | ||
77 | .id = V4L2_CID_AUDIO_VOLUME, | ||
78 | .name = "Volume", | ||
79 | .minimum = 0, | ||
80 | .maximum = 65535, | ||
81 | .step = 65535/100, | ||
82 | .default_value = 65535, | ||
83 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
84 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
85 | }, { | ||
86 | .id = V4L2_CID_BRIGHTNESS, | ||
87 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
88 | .name = "Brightness", | ||
89 | .minimum = 0, | ||
90 | .maximum = 255, | ||
91 | .step = 1, | ||
92 | .default_value = 127, | ||
93 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
94 | }, { | ||
95 | .id = V4L2_CID_CONTRAST, | ||
96 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
97 | .name = "Contrast", | ||
98 | .minimum = 0, | ||
99 | .maximum = 255, | ||
100 | .step = 0x1, | ||
101 | .default_value = 0x10, | ||
102 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
103 | }, { | ||
104 | .id = V4L2_CID_SATURATION, | ||
105 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
106 | .name = "Saturation", | ||
107 | .minimum = 0, | ||
108 | .maximum = 255, | ||
109 | .step = 0x1, | ||
110 | .default_value = 127, | ||
111 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
112 | }, { | ||
113 | .id = V4L2_CID_HUE, | ||
114 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
115 | .name = "Hue", | ||
116 | .minimum = -128, | ||
117 | .maximum = 127, | ||
118 | .step = 0x1, | ||
119 | .default_value = 0, | ||
120 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
121 | } | ||
122 | }; | ||
123 | 71 | ||
124 | #define dprintk(dev, level, fmt, arg...) \ | 72 | #define dprintk(dev, level, fmt, arg...) \ |
125 | v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg) | 73 | v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg) |
@@ -214,41 +162,38 @@ struct vivi_dev { | |||
214 | struct list_head vivi_devlist; | 162 | struct list_head vivi_devlist; |
215 | struct v4l2_device v4l2_dev; | 163 | struct v4l2_device v4l2_dev; |
216 | 164 | ||
165 | /* controls */ | ||
166 | int brightness; | ||
167 | int contrast; | ||
168 | int saturation; | ||
169 | int hue; | ||
170 | int volume; | ||
171 | |||
217 | spinlock_t slock; | 172 | spinlock_t slock; |
218 | struct mutex mutex; | 173 | struct mutex mutex; |
219 | 174 | ||
220 | int users; | ||
221 | |||
222 | /* various device info */ | 175 | /* various device info */ |
223 | struct video_device *vfd; | 176 | struct video_device *vfd; |
224 | 177 | ||
225 | struct vivi_dmaqueue vidq; | 178 | struct vivi_dmaqueue vidq; |
226 | 179 | ||
227 | /* Several counters */ | 180 | /* Several counters */ |
228 | int h, m, s, ms; | 181 | unsigned ms; |
229 | unsigned long jiffies; | 182 | unsigned long jiffies; |
230 | char timestr[13]; | ||
231 | 183 | ||
232 | int mv_count; /* Controls bars movement */ | 184 | int mv_count; /* Controls bars movement */ |
233 | 185 | ||
234 | /* Input Number */ | 186 | /* Input Number */ |
235 | int input; | 187 | int input; |
236 | 188 | ||
237 | /* Control 'registers' */ | ||
238 | int qctl_regs[ARRAY_SIZE(vivi_qctrl)]; | ||
239 | }; | ||
240 | |||
241 | struct vivi_fh { | ||
242 | struct vivi_dev *dev; | ||
243 | |||
244 | /* video capture */ | 189 | /* video capture */ |
245 | struct vivi_fmt *fmt; | 190 | struct vivi_fmt *fmt; |
246 | unsigned int width, height; | 191 | unsigned int width, height; |
247 | struct videobuf_queue vb_vidq; | 192 | struct videobuf_queue vb_vidq; |
248 | 193 | ||
249 | enum v4l2_buf_type type; | 194 | unsigned long generating; |
250 | unsigned char bars[8][3]; | 195 | u8 bars[9][3]; |
251 | int input; /* Input Number on bars */ | 196 | u8 line[MAX_WIDTH * 4]; |
252 | }; | 197 | }; |
253 | 198 | ||
254 | /* ------------------------------------------------------------------ | 199 | /* ------------------------------------------------------------------ |
@@ -259,19 +204,20 @@ struct vivi_fh { | |||
259 | 204 | ||
260 | enum colors { | 205 | enum colors { |
261 | WHITE, | 206 | WHITE, |
262 | AMBAR, | 207 | AMBER, |
263 | CYAN, | 208 | CYAN, |
264 | GREEN, | 209 | GREEN, |
265 | MAGENTA, | 210 | MAGENTA, |
266 | RED, | 211 | RED, |
267 | BLUE, | 212 | BLUE, |
268 | BLACK, | 213 | BLACK, |
214 | TEXT_BLACK, | ||
269 | }; | 215 | }; |
270 | 216 | ||
271 | /* R G B */ | 217 | /* R G B */ |
272 | #define COLOR_WHITE {204, 204, 204} | 218 | #define COLOR_WHITE {204, 204, 204} |
273 | #define COLOR_AMBAR {208, 208, 0} | 219 | #define COLOR_AMBER {208, 208, 0} |
274 | #define COLOR_CIAN { 0, 206, 206} | 220 | #define COLOR_CYAN { 0, 206, 206} |
275 | #define COLOR_GREEN { 0, 239, 0} | 221 | #define COLOR_GREEN { 0, 239, 0} |
276 | #define COLOR_MAGENTA {239, 0, 239} | 222 | #define COLOR_MAGENTA {239, 0, 239} |
277 | #define COLOR_RED {205, 0, 0} | 223 | #define COLOR_RED {205, 0, 0} |
@@ -279,56 +225,24 @@ enum colors { | |||
279 | #define COLOR_BLACK { 0, 0, 0} | 225 | #define COLOR_BLACK { 0, 0, 0} |
280 | 226 | ||
281 | struct bar_std { | 227 | struct bar_std { |
282 | u8 bar[8][3]; | 228 | u8 bar[9][3]; |
283 | }; | 229 | }; |
284 | 230 | ||
285 | /* Maximum number of bars are 10 - otherwise, the input print code | 231 | /* Maximum number of bars are 10 - otherwise, the input print code |
286 | should be modified */ | 232 | should be modified */ |
287 | static struct bar_std bars[] = { | 233 | static struct bar_std bars[] = { |
288 | { /* Standard ITU-R color bar sequence */ | 234 | { /* Standard ITU-R color bar sequence */ |
289 | { | 235 | { COLOR_WHITE, COLOR_AMBER, COLOR_CYAN, COLOR_GREEN, |
290 | COLOR_WHITE, | 236 | COLOR_MAGENTA, COLOR_RED, COLOR_BLUE, COLOR_BLACK, COLOR_BLACK } |
291 | COLOR_AMBAR, | ||
292 | COLOR_CIAN, | ||
293 | COLOR_GREEN, | ||
294 | COLOR_MAGENTA, | ||
295 | COLOR_RED, | ||
296 | COLOR_BLUE, | ||
297 | COLOR_BLACK, | ||
298 | } | ||
299 | }, { | 237 | }, { |
300 | { | 238 | { COLOR_WHITE, COLOR_AMBER, COLOR_BLACK, COLOR_WHITE, |
301 | COLOR_WHITE, | 239 | COLOR_AMBER, COLOR_BLACK, COLOR_WHITE, COLOR_AMBER, COLOR_BLACK } |
302 | COLOR_AMBAR, | ||
303 | COLOR_BLACK, | ||
304 | COLOR_WHITE, | ||
305 | COLOR_AMBAR, | ||
306 | COLOR_BLACK, | ||
307 | COLOR_WHITE, | ||
308 | COLOR_AMBAR, | ||
309 | } | ||
310 | }, { | 240 | }, { |
311 | { | 241 | { COLOR_WHITE, COLOR_CYAN, COLOR_BLACK, COLOR_WHITE, |
312 | COLOR_WHITE, | 242 | COLOR_CYAN, COLOR_BLACK, COLOR_WHITE, COLOR_CYAN, COLOR_BLACK } |
313 | COLOR_CIAN, | ||
314 | COLOR_BLACK, | ||
315 | COLOR_WHITE, | ||
316 | COLOR_CIAN, | ||
317 | COLOR_BLACK, | ||
318 | COLOR_WHITE, | ||
319 | COLOR_CIAN, | ||
320 | } | ||
321 | }, { | 243 | }, { |
322 | { | 244 | { COLOR_WHITE, COLOR_GREEN, COLOR_BLACK, COLOR_WHITE, |
323 | COLOR_WHITE, | 245 | COLOR_GREEN, COLOR_BLACK, COLOR_WHITE, COLOR_GREEN, COLOR_BLACK } |
324 | COLOR_GREEN, | ||
325 | COLOR_BLACK, | ||
326 | COLOR_WHITE, | ||
327 | COLOR_GREEN, | ||
328 | COLOR_BLACK, | ||
329 | COLOR_WHITE, | ||
330 | COLOR_GREEN, | ||
331 | } | ||
332 | }, | 246 | }, |
333 | }; | 247 | }; |
334 | 248 | ||
@@ -344,21 +258,18 @@ static struct bar_std bars[] = { | |||
344 | (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128) | 258 | (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128) |
345 | 259 | ||
346 | /* precalculate color bar values to speed up rendering */ | 260 | /* precalculate color bar values to speed up rendering */ |
347 | static void precalculate_bars(struct vivi_fh *fh) | 261 | static void precalculate_bars(struct vivi_dev *dev) |
348 | { | 262 | { |
349 | struct vivi_dev *dev = fh->dev; | 263 | u8 r, g, b; |
350 | unsigned char r, g, b; | ||
351 | int k, is_yuv; | 264 | int k, is_yuv; |
352 | 265 | ||
353 | fh->input = dev->input; | 266 | for (k = 0; k < 9; k++) { |
354 | 267 | r = bars[dev->input].bar[k][0]; | |
355 | for (k = 0; k < 8; k++) { | 268 | g = bars[dev->input].bar[k][1]; |
356 | r = bars[fh->input].bar[k][0]; | 269 | b = bars[dev->input].bar[k][2]; |
357 | g = bars[fh->input].bar[k][1]; | ||
358 | b = bars[fh->input].bar[k][2]; | ||
359 | is_yuv = 0; | 270 | is_yuv = 0; |
360 | 271 | ||
361 | switch (fh->fmt->fourcc) { | 272 | switch (dev->fmt->fourcc) { |
362 | case V4L2_PIX_FMT_YUYV: | 273 | case V4L2_PIX_FMT_YUYV: |
363 | case V4L2_PIX_FMT_UYVY: | 274 | case V4L2_PIX_FMT_UYVY: |
364 | is_yuv = 1; | 275 | is_yuv = 1; |
@@ -378,16 +289,15 @@ static void precalculate_bars(struct vivi_fh *fh) | |||
378 | } | 289 | } |
379 | 290 | ||
380 | if (is_yuv) { | 291 | if (is_yuv) { |
381 | fh->bars[k][0] = TO_Y(r, g, b); /* Luma */ | 292 | dev->bars[k][0] = TO_Y(r, g, b); /* Luma */ |
382 | fh->bars[k][1] = TO_U(r, g, b); /* Cb */ | 293 | dev->bars[k][1] = TO_U(r, g, b); /* Cb */ |
383 | fh->bars[k][2] = TO_V(r, g, b); /* Cr */ | 294 | dev->bars[k][2] = TO_V(r, g, b); /* Cr */ |
384 | } else { | 295 | } else { |
385 | fh->bars[k][0] = r; | 296 | dev->bars[k][0] = r; |
386 | fh->bars[k][1] = g; | 297 | dev->bars[k][1] = g; |
387 | fh->bars[k][2] = b; | 298 | dev->bars[k][2] = b; |
388 | } | 299 | } |
389 | } | 300 | } |
390 | |||
391 | } | 301 | } |
392 | 302 | ||
393 | #define TSTAMP_MIN_Y 24 | 303 | #define TSTAMP_MIN_Y 24 |
@@ -395,20 +305,20 @@ static void precalculate_bars(struct vivi_fh *fh) | |||
395 | #define TSTAMP_INPUT_X 10 | 305 | #define TSTAMP_INPUT_X 10 |
396 | #define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X) | 306 | #define TSTAMP_MIN_X (54 + TSTAMP_INPUT_X) |
397 | 307 | ||
398 | static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos) | 308 | static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos) |
399 | { | 309 | { |
400 | unsigned char r_y, g_u, b_v; | 310 | u8 r_y, g_u, b_v; |
401 | unsigned char *p; | ||
402 | int color; | 311 | int color; |
312 | u8 *p; | ||
403 | 313 | ||
404 | r_y = fh->bars[colorpos][0]; /* R or precalculated Y */ | 314 | r_y = dev->bars[colorpos][0]; /* R or precalculated Y */ |
405 | g_u = fh->bars[colorpos][1]; /* G or precalculated U */ | 315 | g_u = dev->bars[colorpos][1]; /* G or precalculated U */ |
406 | b_v = fh->bars[colorpos][2]; /* B or precalculated V */ | 316 | b_v = dev->bars[colorpos][2]; /* B or precalculated V */ |
407 | 317 | ||
408 | for (color = 0; color < 4; color++) { | 318 | for (color = 0; color < 4; color++) { |
409 | p = buf + color; | 319 | p = buf + color; |
410 | 320 | ||
411 | switch (fh->fmt->fourcc) { | 321 | switch (dev->fmt->fourcc) { |
412 | case V4L2_PIX_FMT_YUYV: | 322 | case V4L2_PIX_FMT_YUYV: |
413 | switch (color) { | 323 | switch (color) { |
414 | case 0: | 324 | case 0: |
@@ -489,123 +399,88 @@ static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos) | |||
489 | } | 399 | } |
490 | } | 400 | } |
491 | 401 | ||
492 | static void gen_line(struct vivi_fh *fh, char *basep, int inipos, int wmax, | 402 | static void precalculate_line(struct vivi_dev *dev) |
493 | int hmax, int line, int count, char *timestr) | ||
494 | { | 403 | { |
495 | int w, i, j; | 404 | int w; |
496 | int pos = inipos; | ||
497 | char *s; | ||
498 | u8 chr; | ||
499 | |||
500 | /* We will just duplicate the second pixel at the packet */ | ||
501 | wmax /= 2; | ||
502 | 405 | ||
503 | /* Generate a standard color bar pattern */ | 406 | for (w = 0; w < dev->width * 2; w += 2) { |
504 | for (w = 0; w < wmax; w++) { | 407 | int colorpos = (w / (dev->width / 8) % 8); |
505 | int colorpos = ((w + count) * 8/(wmax + 1)) % 8; | ||
506 | 408 | ||
507 | gen_twopix(fh, basep + pos, colorpos); | 409 | gen_twopix(dev, dev->line + w * 2, colorpos); |
508 | pos += 4; /* only 16 bpp supported for now */ | ||
509 | } | 410 | } |
411 | } | ||
510 | 412 | ||
511 | /* Prints input entry number */ | 413 | static void gen_text(struct vivi_dev *dev, char *basep, |
512 | 414 | int y, int x, char *text) | |
513 | /* Checks if it is possible to input number */ | 415 | { |
514 | if (TSTAMP_MAX_Y >= hmax) | 416 | int line; |
515 | goto end; | ||
516 | |||
517 | if (TSTAMP_INPUT_X + strlen(timestr) >= wmax) | ||
518 | goto end; | ||
519 | |||
520 | if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) { | ||
521 | chr = rom8x16_bits[fh->input * 16 + line - TSTAMP_MIN_Y]; | ||
522 | pos = TSTAMP_INPUT_X; | ||
523 | for (i = 0; i < 7; i++) { | ||
524 | /* Draw white font on black background */ | ||
525 | if (chr & 1 << (7 - i)) | ||
526 | gen_twopix(fh, basep + pos, WHITE); | ||
527 | else | ||
528 | gen_twopix(fh, basep + pos, BLACK); | ||
529 | pos += 2; | ||
530 | } | ||
531 | } | ||
532 | 417 | ||
533 | /* Checks if it is possible to show timestamp */ | 418 | /* Checks if it is possible to show string */ |
534 | if (TSTAMP_MIN_X + strlen(timestr) >= wmax) | 419 | if (y + 16 >= dev->height || x + strlen(text) * 8 >= dev->width) |
535 | goto end; | 420 | return; |
536 | 421 | ||
537 | /* Print stream time */ | 422 | /* Print stream time */ |
538 | if (line >= TSTAMP_MIN_Y && line <= TSTAMP_MAX_Y) { | 423 | for (line = y; line < y + 16; line++) { |
539 | j = TSTAMP_MIN_X; | 424 | int j = 0; |
540 | for (s = timestr; *s; s++) { | 425 | char *pos = basep + line * dev->width * 2 + x * 2; |
541 | chr = rom8x16_bits[(*s-0x30)*16+line-TSTAMP_MIN_Y]; | 426 | char *s; |
542 | for (i = 0; i < 7; i++) { | 427 | |
543 | pos = inipos + j * 2; | 428 | for (s = text; *s; s++) { |
429 | u8 chr = font8x16[*s * 16 + line - y]; | ||
430 | int i; | ||
431 | |||
432 | for (i = 0; i < 7; i++, j++) { | ||
544 | /* Draw white font on black background */ | 433 | /* Draw white font on black background */ |
545 | if (chr & 1 << (7 - i)) | 434 | if (chr & (1 << (7 - i))) |
546 | gen_twopix(fh, basep + pos, WHITE); | 435 | gen_twopix(dev, pos + j * 2, WHITE); |
547 | else | 436 | else |
548 | gen_twopix(fh, basep + pos, BLACK); | 437 | gen_twopix(dev, pos + j * 2, TEXT_BLACK); |
549 | j++; | ||
550 | } | 438 | } |
551 | } | 439 | } |
552 | } | 440 | } |
553 | |||
554 | end: | ||
555 | return; | ||
556 | } | 441 | } |
557 | 442 | ||
558 | static void vivi_fillbuff(struct vivi_fh *fh, struct vivi_buffer *buf) | 443 | static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) |
559 | { | 444 | { |
560 | struct vivi_dev *dev = fh->dev; | 445 | int hmax = buf->vb.height; |
561 | int h , pos = 0; | 446 | int wmax = buf->vb.width; |
562 | int hmax = buf->vb.height; | ||
563 | int wmax = buf->vb.width; | ||
564 | struct timeval ts; | 447 | struct timeval ts; |
565 | char *tmpbuf; | ||
566 | void *vbuf = videobuf_to_vmalloc(&buf->vb); | 448 | void *vbuf = videobuf_to_vmalloc(&buf->vb); |
449 | unsigned ms; | ||
450 | char str[100]; | ||
451 | int h, line = 1; | ||
567 | 452 | ||
568 | if (!vbuf) | 453 | if (!vbuf) |
569 | return; | 454 | return; |
570 | 455 | ||
571 | tmpbuf = kmalloc(wmax * 2, GFP_ATOMIC); | 456 | for (h = 0; h < hmax; h++) |
572 | if (!tmpbuf) | 457 | memcpy(vbuf + h * wmax * 2, dev->line + (dev->mv_count % wmax) * 2, wmax * 2); |
573 | return; | ||
574 | |||
575 | for (h = 0; h < hmax; h++) { | ||
576 | gen_line(fh, tmpbuf, 0, wmax, hmax, h, dev->mv_count, | ||
577 | dev->timestr); | ||
578 | memcpy(vbuf + pos, tmpbuf, wmax * 2); | ||
579 | pos += wmax*2; | ||
580 | } | ||
581 | |||
582 | dev->mv_count++; | ||
583 | |||
584 | kfree(tmpbuf); | ||
585 | 458 | ||
586 | /* Updates stream time */ | 459 | /* Updates stream time */ |
587 | 460 | ||
588 | dev->ms += jiffies_to_msecs(jiffies-dev->jiffies); | 461 | dev->ms += jiffies_to_msecs(jiffies - dev->jiffies); |
589 | dev->jiffies = jiffies; | 462 | dev->jiffies = jiffies; |
590 | if (dev->ms >= 1000) { | 463 | ms = dev->ms; |
591 | dev->ms -= 1000; | 464 | snprintf(str, sizeof(str), " %02d:%02d:%02d:%03d ", |
592 | dev->s++; | 465 | (ms / (60 * 60 * 1000)) % 24, |
593 | if (dev->s >= 60) { | 466 | (ms / (60 * 1000)) % 60, |
594 | dev->s -= 60; | 467 | (ms / 1000) % 60, |
595 | dev->m++; | 468 | ms % 1000); |
596 | if (dev->m > 60) { | 469 | gen_text(dev, vbuf, line++ * 16, 16, str); |
597 | dev->m -= 60; | 470 | snprintf(str, sizeof(str), " %dx%d, input %d ", |
598 | dev->h++; | 471 | dev->width, dev->height, dev->input); |
599 | if (dev->h > 24) | 472 | gen_text(dev, vbuf, line++ * 16, 16, str); |
600 | dev->h -= 24; | 473 | |
601 | } | 474 | snprintf(str, sizeof(str), " brightness %3d, contrast %3d, saturation %3d, hue %d ", |
602 | } | 475 | dev->brightness, |
603 | } | 476 | dev->contrast, |
604 | sprintf(dev->timestr, "%02d:%02d:%02d:%03d", | 477 | dev->saturation, |
605 | dev->h, dev->m, dev->s, dev->ms); | 478 | dev->hue); |
606 | 479 | gen_text(dev, vbuf, line++ * 16, 16, str); | |
607 | dprintk(dev, 2, "vivifill at %s: Buffer 0x%08lx size= %d\n", | 480 | snprintf(str, sizeof(str), " volume %3d ", dev->volume); |
608 | dev->timestr, (unsigned long)tmpbuf, pos); | 481 | gen_text(dev, vbuf, line++ * 16, 16, str); |
482 | |||
483 | dev->mv_count += 2; | ||
609 | 484 | ||
610 | /* Advice that buffer was filled */ | 485 | /* Advice that buffer was filled */ |
611 | buf->vb.field_count++; | 486 | buf->vb.field_count++; |
@@ -614,12 +489,10 @@ static void vivi_fillbuff(struct vivi_fh *fh, struct vivi_buffer *buf) | |||
614 | buf->vb.state = VIDEOBUF_DONE; | 489 | buf->vb.state = VIDEOBUF_DONE; |
615 | } | 490 | } |
616 | 491 | ||
617 | static void vivi_thread_tick(struct vivi_fh *fh) | 492 | static void vivi_thread_tick(struct vivi_dev *dev) |
618 | { | 493 | { |
619 | struct vivi_buffer *buf; | ||
620 | struct vivi_dev *dev = fh->dev; | ||
621 | struct vivi_dmaqueue *dma_q = &dev->vidq; | 494 | struct vivi_dmaqueue *dma_q = &dev->vidq; |
622 | 495 | struct vivi_buffer *buf; | |
623 | unsigned long flags = 0; | 496 | unsigned long flags = 0; |
624 | 497 | ||
625 | dprintk(dev, 1, "Thread tick\n"); | 498 | dprintk(dev, 1, "Thread tick\n"); |
@@ -642,22 +515,20 @@ static void vivi_thread_tick(struct vivi_fh *fh) | |||
642 | do_gettimeofday(&buf->vb.ts); | 515 | do_gettimeofday(&buf->vb.ts); |
643 | 516 | ||
644 | /* Fill buffer */ | 517 | /* Fill buffer */ |
645 | vivi_fillbuff(fh, buf); | 518 | vivi_fillbuff(dev, buf); |
646 | dprintk(dev, 1, "filled buffer %p\n", buf); | 519 | dprintk(dev, 1, "filled buffer %p\n", buf); |
647 | 520 | ||
648 | wake_up(&buf->vb.done); | 521 | wake_up(&buf->vb.done); |
649 | dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i); | 522 | dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i); |
650 | unlock: | 523 | unlock: |
651 | spin_unlock_irqrestore(&dev->slock, flags); | 524 | spin_unlock_irqrestore(&dev->slock, flags); |
652 | return; | ||
653 | } | 525 | } |
654 | 526 | ||
655 | #define frames_to_ms(frames) \ | 527 | #define frames_to_ms(frames) \ |
656 | ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR) | 528 | ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR) |
657 | 529 | ||
658 | static void vivi_sleep(struct vivi_fh *fh) | 530 | static void vivi_sleep(struct vivi_dev *dev) |
659 | { | 531 | { |
660 | struct vivi_dev *dev = fh->dev; | ||
661 | struct vivi_dmaqueue *dma_q = &dev->vidq; | 532 | struct vivi_dmaqueue *dma_q = &dev->vidq; |
662 | int timeout; | 533 | int timeout; |
663 | DECLARE_WAITQUEUE(wait, current); | 534 | DECLARE_WAITQUEUE(wait, current); |
@@ -672,7 +543,7 @@ static void vivi_sleep(struct vivi_fh *fh) | |||
672 | /* Calculate time to wake up */ | 543 | /* Calculate time to wake up */ |
673 | timeout = msecs_to_jiffies(frames_to_ms(1)); | 544 | timeout = msecs_to_jiffies(frames_to_ms(1)); |
674 | 545 | ||
675 | vivi_thread_tick(fh); | 546 | vivi_thread_tick(dev); |
676 | 547 | ||
677 | schedule_timeout_interruptible(timeout); | 548 | schedule_timeout_interruptible(timeout); |
678 | 549 | ||
@@ -683,15 +554,14 @@ stop_task: | |||
683 | 554 | ||
684 | static int vivi_thread(void *data) | 555 | static int vivi_thread(void *data) |
685 | { | 556 | { |
686 | struct vivi_fh *fh = data; | 557 | struct vivi_dev *dev = data; |
687 | struct vivi_dev *dev = fh->dev; | ||
688 | 558 | ||
689 | dprintk(dev, 1, "thread started\n"); | 559 | dprintk(dev, 1, "thread started\n"); |
690 | 560 | ||
691 | set_freezable(); | 561 | set_freezable(); |
692 | 562 | ||
693 | for (;;) { | 563 | for (;;) { |
694 | vivi_sleep(fh); | 564 | vivi_sleep(dev); |
695 | 565 | ||
696 | if (kthread_should_stop()) | 566 | if (kthread_should_stop()) |
697 | break; | 567 | break; |
@@ -700,39 +570,61 @@ static int vivi_thread(void *data) | |||
700 | return 0; | 570 | return 0; |
701 | } | 571 | } |
702 | 572 | ||
703 | static int vivi_start_thread(struct vivi_fh *fh) | 573 | static void vivi_start_generating(struct file *file) |
704 | { | 574 | { |
705 | struct vivi_dev *dev = fh->dev; | 575 | struct vivi_dev *dev = video_drvdata(file); |
706 | struct vivi_dmaqueue *dma_q = &dev->vidq; | 576 | struct vivi_dmaqueue *dma_q = &dev->vidq; |
707 | 577 | ||
708 | dma_q->frame = 0; | ||
709 | dma_q->ini_jiffies = jiffies; | ||
710 | |||
711 | dprintk(dev, 1, "%s\n", __func__); | 578 | dprintk(dev, 1, "%s\n", __func__); |
712 | 579 | ||
713 | dma_q->kthread = kthread_run(vivi_thread, fh, "vivi"); | 580 | if (test_and_set_bit(0, &dev->generating)) |
581 | return; | ||
582 | file->private_data = dev; | ||
583 | |||
584 | /* Resets frame counters */ | ||
585 | dev->ms = 0; | ||
586 | dev->mv_count = 0; | ||
587 | dev->jiffies = jiffies; | ||
588 | |||
589 | dma_q->frame = 0; | ||
590 | dma_q->ini_jiffies = jiffies; | ||
591 | dma_q->kthread = kthread_run(vivi_thread, dev, dev->v4l2_dev.name); | ||
714 | 592 | ||
715 | if (IS_ERR(dma_q->kthread)) { | 593 | if (IS_ERR(dma_q->kthread)) { |
716 | v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n"); | 594 | v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n"); |
717 | return PTR_ERR(dma_q->kthread); | 595 | clear_bit(0, &dev->generating); |
596 | return; | ||
718 | } | 597 | } |
719 | /* Wakes thread */ | 598 | /* Wakes thread */ |
720 | wake_up_interruptible(&dma_q->wq); | 599 | wake_up_interruptible(&dma_q->wq); |
721 | 600 | ||
722 | dprintk(dev, 1, "returning from %s\n", __func__); | 601 | dprintk(dev, 1, "returning from %s\n", __func__); |
723 | return 0; | ||
724 | } | 602 | } |
725 | 603 | ||
726 | static void vivi_stop_thread(struct vivi_dmaqueue *dma_q) | 604 | static void vivi_stop_generating(struct file *file) |
727 | { | 605 | { |
728 | struct vivi_dev *dev = container_of(dma_q, struct vivi_dev, vidq); | 606 | struct vivi_dev *dev = video_drvdata(file); |
607 | struct vivi_dmaqueue *dma_q = &dev->vidq; | ||
729 | 608 | ||
730 | dprintk(dev, 1, "%s\n", __func__); | 609 | dprintk(dev, 1, "%s\n", __func__); |
610 | |||
611 | if (!file->private_data) | ||
612 | return; | ||
613 | if (!test_and_clear_bit(0, &dev->generating)) | ||
614 | return; | ||
615 | |||
731 | /* shutdown control thread */ | 616 | /* shutdown control thread */ |
732 | if (dma_q->kthread) { | 617 | if (dma_q->kthread) { |
733 | kthread_stop(dma_q->kthread); | 618 | kthread_stop(dma_q->kthread); |
734 | dma_q->kthread = NULL; | 619 | dma_q->kthread = NULL; |
735 | } | 620 | } |
621 | videobuf_stop(&dev->vb_vidq); | ||
622 | videobuf_mmap_free(&dev->vb_vidq); | ||
623 | } | ||
624 | |||
625 | static int vivi_is_generating(struct vivi_dev *dev) | ||
626 | { | ||
627 | return test_bit(0, &dev->generating); | ||
736 | } | 628 | } |
737 | 629 | ||
738 | /* ------------------------------------------------------------------ | 630 | /* ------------------------------------------------------------------ |
@@ -741,16 +633,15 @@ static void vivi_stop_thread(struct vivi_dmaqueue *dma_q) | |||
741 | static int | 633 | static int |
742 | buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) | 634 | buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) |
743 | { | 635 | { |
744 | struct vivi_fh *fh = vq->priv_data; | 636 | struct vivi_dev *dev = vq->priv_data; |
745 | struct vivi_dev *dev = fh->dev; | ||
746 | 637 | ||
747 | *size = fh->width*fh->height*2; | 638 | *size = dev->width * dev->height * 2; |
748 | 639 | ||
749 | if (0 == *count) | 640 | if (0 == *count) |
750 | *count = 32; | 641 | *count = 32; |
751 | 642 | ||
752 | if (*size * *count > vid_limit * 1024 * 1024) | 643 | while (*size * *count > vid_limit * 1024 * 1024) |
753 | *count = (vid_limit * 1024 * 1024) / *size; | 644 | (*count)--; |
754 | 645 | ||
755 | dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__, | 646 | dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__, |
756 | *count, *size); | 647 | *count, *size); |
@@ -760,49 +651,43 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) | |||
760 | 651 | ||
761 | static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf) | 652 | static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf) |
762 | { | 653 | { |
763 | struct vivi_fh *fh = vq->priv_data; | 654 | struct vivi_dev *dev = vq->priv_data; |
764 | struct vivi_dev *dev = fh->dev; | ||
765 | 655 | ||
766 | dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state); | 656 | dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state); |
767 | 657 | ||
768 | if (in_interrupt()) | ||
769 | BUG(); | ||
770 | |||
771 | videobuf_vmalloc_free(&buf->vb); | 658 | videobuf_vmalloc_free(&buf->vb); |
772 | dprintk(dev, 1, "free_buffer: freed\n"); | 659 | dprintk(dev, 1, "free_buffer: freed\n"); |
773 | buf->vb.state = VIDEOBUF_NEEDS_INIT; | 660 | buf->vb.state = VIDEOBUF_NEEDS_INIT; |
774 | } | 661 | } |
775 | 662 | ||
776 | #define norm_maxw() 1024 | ||
777 | #define norm_maxh() 768 | ||
778 | static int | 663 | static int |
779 | buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, | 664 | buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, |
780 | enum v4l2_field field) | 665 | enum v4l2_field field) |
781 | { | 666 | { |
782 | struct vivi_fh *fh = vq->priv_data; | 667 | struct vivi_dev *dev = vq->priv_data; |
783 | struct vivi_dev *dev = fh->dev; | ||
784 | struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); | 668 | struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); |
785 | int rc; | 669 | int rc; |
786 | 670 | ||
787 | dprintk(dev, 1, "%s, field=%d\n", __func__, field); | 671 | dprintk(dev, 1, "%s, field=%d\n", __func__, field); |
788 | 672 | ||
789 | BUG_ON(NULL == fh->fmt); | 673 | BUG_ON(NULL == dev->fmt); |
790 | 674 | ||
791 | if (fh->width < 48 || fh->width > norm_maxw() || | 675 | if (dev->width < 48 || dev->width > MAX_WIDTH || |
792 | fh->height < 32 || fh->height > norm_maxh()) | 676 | dev->height < 32 || dev->height > MAX_HEIGHT) |
793 | return -EINVAL; | 677 | return -EINVAL; |
794 | 678 | ||
795 | buf->vb.size = fh->width*fh->height*2; | 679 | buf->vb.size = dev->width * dev->height * 2; |
796 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) | 680 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) |
797 | return -EINVAL; | 681 | return -EINVAL; |
798 | 682 | ||
799 | /* These properties only change when queue is idle, see s_fmt */ | 683 | /* These properties only change when queue is idle, see s_fmt */ |
800 | buf->fmt = fh->fmt; | 684 | buf->fmt = dev->fmt; |
801 | buf->vb.width = fh->width; | 685 | buf->vb.width = dev->width; |
802 | buf->vb.height = fh->height; | 686 | buf->vb.height = dev->height; |
803 | buf->vb.field = field; | 687 | buf->vb.field = field; |
804 | 688 | ||
805 | precalculate_bars(fh); | 689 | precalculate_bars(dev); |
690 | precalculate_line(dev); | ||
806 | 691 | ||
807 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | 692 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { |
808 | rc = videobuf_iolock(vq, &buf->vb, NULL); | 693 | rc = videobuf_iolock(vq, &buf->vb, NULL); |
@@ -811,7 +696,6 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, | |||
811 | } | 696 | } |
812 | 697 | ||
813 | buf->vb.state = VIDEOBUF_PREPARED; | 698 | buf->vb.state = VIDEOBUF_PREPARED; |
814 | |||
815 | return 0; | 699 | return 0; |
816 | 700 | ||
817 | fail: | 701 | fail: |
@@ -822,9 +706,8 @@ fail: | |||
822 | static void | 706 | static void |
823 | buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | 707 | buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) |
824 | { | 708 | { |
825 | struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); | 709 | struct vivi_dev *dev = vq->priv_data; |
826 | struct vivi_fh *fh = vq->priv_data; | 710 | struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); |
827 | struct vivi_dev *dev = fh->dev; | ||
828 | struct vivi_dmaqueue *vidq = &dev->vidq; | 711 | struct vivi_dmaqueue *vidq = &dev->vidq; |
829 | 712 | ||
830 | dprintk(dev, 1, "%s\n", __func__); | 713 | dprintk(dev, 1, "%s\n", __func__); |
@@ -836,9 +719,8 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | |||
836 | static void buffer_release(struct videobuf_queue *vq, | 719 | static void buffer_release(struct videobuf_queue *vq, |
837 | struct videobuf_buffer *vb) | 720 | struct videobuf_buffer *vb) |
838 | { | 721 | { |
839 | struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); | 722 | struct vivi_dev *dev = vq->priv_data; |
840 | struct vivi_fh *fh = vq->priv_data; | 723 | struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb); |
841 | struct vivi_dev *dev = (struct vivi_dev *)fh->dev; | ||
842 | 724 | ||
843 | dprintk(dev, 1, "%s\n", __func__); | 725 | dprintk(dev, 1, "%s\n", __func__); |
844 | 726 | ||
@@ -858,16 +740,14 @@ static struct videobuf_queue_ops vivi_video_qops = { | |||
858 | static int vidioc_querycap(struct file *file, void *priv, | 740 | static int vidioc_querycap(struct file *file, void *priv, |
859 | struct v4l2_capability *cap) | 741 | struct v4l2_capability *cap) |
860 | { | 742 | { |
861 | struct vivi_fh *fh = priv; | 743 | struct vivi_dev *dev = video_drvdata(file); |
862 | struct vivi_dev *dev = fh->dev; | ||
863 | 744 | ||
864 | strcpy(cap->driver, "vivi"); | 745 | strcpy(cap->driver, "vivi"); |
865 | strcpy(cap->card, "vivi"); | 746 | strcpy(cap->card, "vivi"); |
866 | strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); | 747 | strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); |
867 | cap->version = VIVI_VERSION; | 748 | cap->version = VIVI_VERSION; |
868 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | | 749 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \ |
869 | V4L2_CAP_STREAMING | | 750 | V4L2_CAP_READWRITE; |
870 | V4L2_CAP_READWRITE; | ||
871 | return 0; | 751 | return 0; |
872 | } | 752 | } |
873 | 753 | ||
@@ -889,28 +769,25 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | |||
889 | static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | 769 | static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, |
890 | struct v4l2_format *f) | 770 | struct v4l2_format *f) |
891 | { | 771 | { |
892 | struct vivi_fh *fh = priv; | 772 | struct vivi_dev *dev = video_drvdata(file); |
893 | 773 | ||
894 | f->fmt.pix.width = fh->width; | 774 | f->fmt.pix.width = dev->width; |
895 | f->fmt.pix.height = fh->height; | 775 | f->fmt.pix.height = dev->height; |
896 | f->fmt.pix.field = fh->vb_vidq.field; | 776 | f->fmt.pix.field = dev->vb_vidq.field; |
897 | f->fmt.pix.pixelformat = fh->fmt->fourcc; | 777 | f->fmt.pix.pixelformat = dev->fmt->fourcc; |
898 | f->fmt.pix.bytesperline = | 778 | f->fmt.pix.bytesperline = |
899 | (f->fmt.pix.width * fh->fmt->depth) >> 3; | 779 | (f->fmt.pix.width * dev->fmt->depth) >> 3; |
900 | f->fmt.pix.sizeimage = | 780 | f->fmt.pix.sizeimage = |
901 | f->fmt.pix.height * f->fmt.pix.bytesperline; | 781 | f->fmt.pix.height * f->fmt.pix.bytesperline; |
902 | 782 | return 0; | |
903 | return (0); | ||
904 | } | 783 | } |
905 | 784 | ||
906 | static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | 785 | static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, |
907 | struct v4l2_format *f) | 786 | struct v4l2_format *f) |
908 | { | 787 | { |
909 | struct vivi_fh *fh = priv; | 788 | struct vivi_dev *dev = video_drvdata(file); |
910 | struct vivi_dev *dev = fh->dev; | ||
911 | struct vivi_fmt *fmt; | 789 | struct vivi_fmt *fmt; |
912 | enum v4l2_field field; | 790 | enum v4l2_field field; |
913 | unsigned int maxw, maxh; | ||
914 | 791 | ||
915 | fmt = get_format(f); | 792 | fmt = get_format(f); |
916 | if (!fmt) { | 793 | if (!fmt) { |
@@ -928,113 +805,109 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
928 | return -EINVAL; | 805 | return -EINVAL; |
929 | } | 806 | } |
930 | 807 | ||
931 | maxw = norm_maxw(); | ||
932 | maxh = norm_maxh(); | ||
933 | |||
934 | f->fmt.pix.field = field; | 808 | f->fmt.pix.field = field; |
935 | v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, | 809 | v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 2, |
936 | &f->fmt.pix.height, 32, maxh, 0, 0); | 810 | &f->fmt.pix.height, 32, MAX_HEIGHT, 0, 0); |
937 | f->fmt.pix.bytesperline = | 811 | f->fmt.pix.bytesperline = |
938 | (f->fmt.pix.width * fmt->depth) >> 3; | 812 | (f->fmt.pix.width * fmt->depth) >> 3; |
939 | f->fmt.pix.sizeimage = | 813 | f->fmt.pix.sizeimage = |
940 | f->fmt.pix.height * f->fmt.pix.bytesperline; | 814 | f->fmt.pix.height * f->fmt.pix.bytesperline; |
941 | |||
942 | return 0; | 815 | return 0; |
943 | } | 816 | } |
944 | 817 | ||
945 | /*FIXME: This seems to be generic enough to be at videodev2 */ | ||
946 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | 818 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
947 | struct v4l2_format *f) | 819 | struct v4l2_format *f) |
948 | { | 820 | { |
949 | struct vivi_fh *fh = priv; | 821 | struct vivi_dev *dev = video_drvdata(file); |
950 | struct videobuf_queue *q = &fh->vb_vidq; | 822 | struct videobuf_queue *q = &dev->vb_vidq; |
951 | 823 | ||
952 | int ret = vidioc_try_fmt_vid_cap(file, fh, f); | 824 | int ret = vidioc_try_fmt_vid_cap(file, priv, f); |
953 | if (ret < 0) | 825 | if (ret < 0) |
954 | return ret; | 826 | return ret; |
955 | 827 | ||
956 | mutex_lock(&q->vb_lock); | 828 | mutex_lock(&q->vb_lock); |
957 | 829 | ||
958 | if (videobuf_queue_is_busy(&fh->vb_vidq)) { | 830 | if (vivi_is_generating(dev)) { |
959 | dprintk(fh->dev, 1, "%s queue busy\n", __func__); | 831 | dprintk(dev, 1, "%s device busy\n", __func__); |
960 | ret = -EBUSY; | 832 | ret = -EBUSY; |
961 | goto out; | 833 | goto out; |
962 | } | 834 | } |
963 | 835 | ||
964 | fh->fmt = get_format(f); | 836 | dev->fmt = get_format(f); |
965 | fh->width = f->fmt.pix.width; | 837 | dev->width = f->fmt.pix.width; |
966 | fh->height = f->fmt.pix.height; | 838 | dev->height = f->fmt.pix.height; |
967 | fh->vb_vidq.field = f->fmt.pix.field; | 839 | dev->vb_vidq.field = f->fmt.pix.field; |
968 | fh->type = f->type; | ||
969 | |||
970 | ret = 0; | 840 | ret = 0; |
971 | out: | 841 | out: |
972 | mutex_unlock(&q->vb_lock); | 842 | mutex_unlock(&q->vb_lock); |
973 | |||
974 | return ret; | 843 | return ret; |
975 | } | 844 | } |
976 | 845 | ||
977 | static int vidioc_reqbufs(struct file *file, void *priv, | 846 | static int vidioc_reqbufs(struct file *file, void *priv, |
978 | struct v4l2_requestbuffers *p) | 847 | struct v4l2_requestbuffers *p) |
979 | { | 848 | { |
980 | struct vivi_fh *fh = priv; | 849 | struct vivi_dev *dev = video_drvdata(file); |
981 | 850 | ||
982 | return (videobuf_reqbufs(&fh->vb_vidq, p)); | 851 | return videobuf_reqbufs(&dev->vb_vidq, p); |
983 | } | 852 | } |
984 | 853 | ||
985 | static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) | 854 | static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) |
986 | { | 855 | { |
987 | struct vivi_fh *fh = priv; | 856 | struct vivi_dev *dev = video_drvdata(file); |
988 | 857 | ||
989 | return (videobuf_querybuf(&fh->vb_vidq, p)); | 858 | return videobuf_querybuf(&dev->vb_vidq, p); |
990 | } | 859 | } |
991 | 860 | ||
992 | static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) | 861 | static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) |
993 | { | 862 | { |
994 | struct vivi_fh *fh = priv; | 863 | struct vivi_dev *dev = video_drvdata(file); |
995 | 864 | ||
996 | return (videobuf_qbuf(&fh->vb_vidq, p)); | 865 | return videobuf_qbuf(&dev->vb_vidq, p); |
997 | } | 866 | } |
998 | 867 | ||
999 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | 868 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) |
1000 | { | 869 | { |
1001 | struct vivi_fh *fh = priv; | 870 | struct vivi_dev *dev = video_drvdata(file); |
1002 | 871 | ||
1003 | return (videobuf_dqbuf(&fh->vb_vidq, p, | 872 | return videobuf_dqbuf(&dev->vb_vidq, p, |
1004 | file->f_flags & O_NONBLOCK)); | 873 | file->f_flags & O_NONBLOCK); |
1005 | } | 874 | } |
1006 | 875 | ||
1007 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 876 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
1008 | static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) | 877 | static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) |
1009 | { | 878 | { |
1010 | struct vivi_fh *fh = priv; | 879 | struct vivi_dev *dev = video_drvdata(file); |
1011 | 880 | ||
1012 | return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8); | 881 | return videobuf_cgmbuf(&dev->vb_vidq, mbuf, 8); |
1013 | } | 882 | } |
1014 | #endif | 883 | #endif |
1015 | 884 | ||
1016 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | 885 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) |
1017 | { | 886 | { |
1018 | struct vivi_fh *fh = priv; | 887 | struct vivi_dev *dev = video_drvdata(file); |
888 | int ret; | ||
1019 | 889 | ||
1020 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 890 | if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1021 | return -EINVAL; | ||
1022 | if (i != fh->type) | ||
1023 | return -EINVAL; | 891 | return -EINVAL; |
892 | ret = videobuf_streamon(&dev->vb_vidq); | ||
893 | if (ret) | ||
894 | return ret; | ||
1024 | 895 | ||
1025 | return videobuf_streamon(&fh->vb_vidq); | 896 | vivi_start_generating(file); |
897 | return 0; | ||
1026 | } | 898 | } |
1027 | 899 | ||
1028 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | 900 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) |
1029 | { | 901 | { |
1030 | struct vivi_fh *fh = priv; | 902 | struct vivi_dev *dev = video_drvdata(file); |
903 | int ret; | ||
1031 | 904 | ||
1032 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 905 | if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1033 | return -EINVAL; | ||
1034 | if (i != fh->type) | ||
1035 | return -EINVAL; | 906 | return -EINVAL; |
1036 | 907 | ret = videobuf_streamoff(&dev->vb_vidq); | |
1037 | return videobuf_streamoff(&fh->vb_vidq); | 908 | if (!ret) |
909 | vivi_stop_generating(file); | ||
910 | return ret; | ||
1038 | } | 911 | } |
1039 | 912 | ||
1040 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) | 913 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) |
@@ -1052,80 +925,104 @@ static int vidioc_enum_input(struct file *file, void *priv, | |||
1052 | inp->type = V4L2_INPUT_TYPE_CAMERA; | 925 | inp->type = V4L2_INPUT_TYPE_CAMERA; |
1053 | inp->std = V4L2_STD_525_60; | 926 | inp->std = V4L2_STD_525_60; |
1054 | sprintf(inp->name, "Camera %u", inp->index); | 927 | sprintf(inp->name, "Camera %u", inp->index); |
1055 | 928 | return 0; | |
1056 | return (0); | ||
1057 | } | 929 | } |
1058 | 930 | ||
1059 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) | 931 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) |
1060 | { | 932 | { |
1061 | struct vivi_fh *fh = priv; | 933 | struct vivi_dev *dev = video_drvdata(file); |
1062 | struct vivi_dev *dev = fh->dev; | ||
1063 | 934 | ||
1064 | *i = dev->input; | 935 | *i = dev->input; |
1065 | 936 | return 0; | |
1066 | return (0); | ||
1067 | } | 937 | } |
938 | |||
1068 | static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | 939 | static int vidioc_s_input(struct file *file, void *priv, unsigned int i) |
1069 | { | 940 | { |
1070 | struct vivi_fh *fh = priv; | 941 | struct vivi_dev *dev = video_drvdata(file); |
1071 | struct vivi_dev *dev = fh->dev; | ||
1072 | 942 | ||
1073 | if (i >= NUM_INPUTS) | 943 | if (i >= NUM_INPUTS) |
1074 | return -EINVAL; | 944 | return -EINVAL; |
1075 | 945 | ||
1076 | dev->input = i; | 946 | dev->input = i; |
1077 | precalculate_bars(fh); | 947 | precalculate_bars(dev); |
1078 | 948 | precalculate_line(dev); | |
1079 | return (0); | 949 | return 0; |
1080 | } | 950 | } |
1081 | 951 | ||
1082 | /* --- controls ---------------------------------------------- */ | 952 | /* --- controls ---------------------------------------------- */ |
1083 | static int vidioc_queryctrl(struct file *file, void *priv, | 953 | static int vidioc_queryctrl(struct file *file, void *priv, |
1084 | struct v4l2_queryctrl *qc) | 954 | struct v4l2_queryctrl *qc) |
1085 | { | 955 | { |
1086 | int i; | 956 | switch (qc->id) { |
1087 | 957 | case V4L2_CID_AUDIO_VOLUME: | |
1088 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) | 958 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 200); |
1089 | if (qc->id && qc->id == vivi_qctrl[i].id) { | 959 | case V4L2_CID_BRIGHTNESS: |
1090 | memcpy(qc, &(vivi_qctrl[i]), | 960 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 127); |
1091 | sizeof(*qc)); | 961 | case V4L2_CID_CONTRAST: |
1092 | return (0); | 962 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 16); |
1093 | } | 963 | case V4L2_CID_SATURATION: |
1094 | 964 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 127); | |
965 | case V4L2_CID_HUE: | ||
966 | return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0); | ||
967 | } | ||
1095 | return -EINVAL; | 968 | return -EINVAL; |
1096 | } | 969 | } |
1097 | 970 | ||
1098 | static int vidioc_g_ctrl(struct file *file, void *priv, | 971 | static int vidioc_g_ctrl(struct file *file, void *priv, |
1099 | struct v4l2_control *ctrl) | 972 | struct v4l2_control *ctrl) |
1100 | { | 973 | { |
1101 | struct vivi_fh *fh = priv; | 974 | struct vivi_dev *dev = video_drvdata(file); |
1102 | struct vivi_dev *dev = fh->dev; | ||
1103 | int i; | ||
1104 | |||
1105 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) | ||
1106 | if (ctrl->id == vivi_qctrl[i].id) { | ||
1107 | ctrl->value = dev->qctl_regs[i]; | ||
1108 | return 0; | ||
1109 | } | ||
1110 | 975 | ||
976 | switch (ctrl->id) { | ||
977 | case V4L2_CID_AUDIO_VOLUME: | ||
978 | ctrl->value = dev->volume; | ||
979 | return 0; | ||
980 | case V4L2_CID_BRIGHTNESS: | ||
981 | ctrl->value = dev->brightness; | ||
982 | return 0; | ||
983 | case V4L2_CID_CONTRAST: | ||
984 | ctrl->value = dev->contrast; | ||
985 | return 0; | ||
986 | case V4L2_CID_SATURATION: | ||
987 | ctrl->value = dev->saturation; | ||
988 | return 0; | ||
989 | case V4L2_CID_HUE: | ||
990 | ctrl->value = dev->hue; | ||
991 | return 0; | ||
992 | } | ||
1111 | return -EINVAL; | 993 | return -EINVAL; |
1112 | } | 994 | } |
995 | |||
1113 | static int vidioc_s_ctrl(struct file *file, void *priv, | 996 | static int vidioc_s_ctrl(struct file *file, void *priv, |
1114 | struct v4l2_control *ctrl) | 997 | struct v4l2_control *ctrl) |
1115 | { | 998 | { |
1116 | struct vivi_fh *fh = priv; | 999 | struct vivi_dev *dev = video_drvdata(file); |
1117 | struct vivi_dev *dev = fh->dev; | 1000 | struct v4l2_queryctrl qc; |
1118 | int i; | 1001 | int err; |
1119 | 1002 | ||
1120 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) | 1003 | qc.id = ctrl->id; |
1121 | if (ctrl->id == vivi_qctrl[i].id) { | 1004 | err = vidioc_queryctrl(file, priv, &qc); |
1122 | if (ctrl->value < vivi_qctrl[i].minimum || | 1005 | if (err < 0) |
1123 | ctrl->value > vivi_qctrl[i].maximum) { | 1006 | return err; |
1124 | return -ERANGE; | 1007 | if (ctrl->value < qc.minimum || ctrl->value > qc.maximum) |
1125 | } | 1008 | return -ERANGE; |
1126 | dev->qctl_regs[i] = ctrl->value; | 1009 | switch (ctrl->id) { |
1127 | return 0; | 1010 | case V4L2_CID_AUDIO_VOLUME: |
1128 | } | 1011 | dev->volume = ctrl->value; |
1012 | return 0; | ||
1013 | case V4L2_CID_BRIGHTNESS: | ||
1014 | dev->brightness = ctrl->value; | ||
1015 | return 0; | ||
1016 | case V4L2_CID_CONTRAST: | ||
1017 | dev->contrast = ctrl->value; | ||
1018 | return 0; | ||
1019 | case V4L2_CID_SATURATION: | ||
1020 | dev->saturation = ctrl->value; | ||
1021 | return 0; | ||
1022 | case V4L2_CID_HUE: | ||
1023 | dev->hue = ctrl->value; | ||
1024 | return 0; | ||
1025 | } | ||
1129 | return -EINVAL; | 1026 | return -EINVAL; |
1130 | } | 1027 | } |
1131 | 1028 | ||
@@ -1133,134 +1030,58 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
1133 | File operations for the device | 1030 | File operations for the device |
1134 | ------------------------------------------------------------------*/ | 1031 | ------------------------------------------------------------------*/ |
1135 | 1032 | ||
1136 | static int vivi_open(struct file *file) | ||
1137 | { | ||
1138 | struct vivi_dev *dev = video_drvdata(file); | ||
1139 | struct vivi_fh *fh = NULL; | ||
1140 | int retval = 0; | ||
1141 | |||
1142 | mutex_lock(&dev->mutex); | ||
1143 | dev->users++; | ||
1144 | |||
1145 | if (dev->users > 1) { | ||
1146 | dev->users--; | ||
1147 | mutex_unlock(&dev->mutex); | ||
1148 | return -EBUSY; | ||
1149 | } | ||
1150 | |||
1151 | dprintk(dev, 1, "open %s type=%s users=%d\n", | ||
1152 | video_device_node_name(dev->vfd), | ||
1153 | v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users); | ||
1154 | |||
1155 | /* allocate + initialize per filehandle data */ | ||
1156 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
1157 | if (NULL == fh) { | ||
1158 | dev->users--; | ||
1159 | retval = -ENOMEM; | ||
1160 | } | ||
1161 | mutex_unlock(&dev->mutex); | ||
1162 | |||
1163 | if (retval) | ||
1164 | return retval; | ||
1165 | |||
1166 | file->private_data = fh; | ||
1167 | fh->dev = dev; | ||
1168 | |||
1169 | fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1170 | fh->fmt = &formats[0]; | ||
1171 | fh->width = 640; | ||
1172 | fh->height = 480; | ||
1173 | |||
1174 | /* Resets frame counters */ | ||
1175 | dev->h = 0; | ||
1176 | dev->m = 0; | ||
1177 | dev->s = 0; | ||
1178 | dev->ms = 0; | ||
1179 | dev->mv_count = 0; | ||
1180 | dev->jiffies = jiffies; | ||
1181 | sprintf(dev->timestr, "%02d:%02d:%02d:%03d", | ||
1182 | dev->h, dev->m, dev->s, dev->ms); | ||
1183 | |||
1184 | videobuf_queue_vmalloc_init(&fh->vb_vidq, &vivi_video_qops, | ||
1185 | NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED, | ||
1186 | sizeof(struct vivi_buffer), fh); | ||
1187 | |||
1188 | vivi_start_thread(fh); | ||
1189 | |||
1190 | return 0; | ||
1191 | } | ||
1192 | |||
1193 | static ssize_t | 1033 | static ssize_t |
1194 | vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | 1034 | vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos) |
1195 | { | 1035 | { |
1196 | struct vivi_fh *fh = file->private_data; | 1036 | struct vivi_dev *dev = video_drvdata(file); |
1197 | 1037 | ||
1198 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1038 | vivi_start_generating(file); |
1199 | return videobuf_read_stream(&fh->vb_vidq, data, count, ppos, 0, | 1039 | return videobuf_read_stream(&dev->vb_vidq, data, count, ppos, 0, |
1200 | file->f_flags & O_NONBLOCK); | 1040 | file->f_flags & O_NONBLOCK); |
1201 | } | ||
1202 | return 0; | ||
1203 | } | 1041 | } |
1204 | 1042 | ||
1205 | static unsigned int | 1043 | static unsigned int |
1206 | vivi_poll(struct file *file, struct poll_table_struct *wait) | 1044 | vivi_poll(struct file *file, struct poll_table_struct *wait) |
1207 | { | 1045 | { |
1208 | struct vivi_fh *fh = file->private_data; | 1046 | struct vivi_dev *dev = video_drvdata(file); |
1209 | struct vivi_dev *dev = fh->dev; | 1047 | struct videobuf_queue *q = &dev->vb_vidq; |
1210 | struct videobuf_queue *q = &fh->vb_vidq; | ||
1211 | 1048 | ||
1212 | dprintk(dev, 1, "%s\n", __func__); | 1049 | dprintk(dev, 1, "%s\n", __func__); |
1213 | 1050 | ||
1214 | if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) | 1051 | vivi_start_generating(file); |
1215 | return POLLERR; | ||
1216 | |||
1217 | return videobuf_poll_stream(file, q, wait); | 1052 | return videobuf_poll_stream(file, q, wait); |
1218 | } | 1053 | } |
1219 | 1054 | ||
1220 | static int vivi_close(struct file *file) | 1055 | static int vivi_close(struct file *file) |
1221 | { | 1056 | { |
1222 | struct vivi_fh *fh = file->private_data; | ||
1223 | struct vivi_dev *dev = fh->dev; | ||
1224 | struct vivi_dmaqueue *vidq = &dev->vidq; | ||
1225 | struct video_device *vdev = video_devdata(file); | 1057 | struct video_device *vdev = video_devdata(file); |
1058 | struct vivi_dev *dev = video_drvdata(file); | ||
1226 | 1059 | ||
1227 | vivi_stop_thread(vidq); | 1060 | vivi_stop_generating(file); |
1228 | videobuf_stop(&fh->vb_vidq); | ||
1229 | videobuf_mmap_free(&fh->vb_vidq); | ||
1230 | |||
1231 | kfree(fh); | ||
1232 | |||
1233 | mutex_lock(&dev->mutex); | ||
1234 | dev->users--; | ||
1235 | mutex_unlock(&dev->mutex); | ||
1236 | |||
1237 | dprintk(dev, 1, "close called (dev=%s, users=%d)\n", | ||
1238 | video_device_node_name(vdev), dev->users); | ||
1239 | 1061 | ||
1062 | dprintk(dev, 1, "close called (dev=%s)\n", | ||
1063 | video_device_node_name(vdev)); | ||
1240 | return 0; | 1064 | return 0; |
1241 | } | 1065 | } |
1242 | 1066 | ||
1243 | static int vivi_mmap(struct file *file, struct vm_area_struct *vma) | 1067 | static int vivi_mmap(struct file *file, struct vm_area_struct *vma) |
1244 | { | 1068 | { |
1245 | struct vivi_fh *fh = file->private_data; | 1069 | struct vivi_dev *dev = video_drvdata(file); |
1246 | struct vivi_dev *dev = fh->dev; | ||
1247 | int ret; | 1070 | int ret; |
1248 | 1071 | ||
1249 | dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma); | 1072 | dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma); |
1250 | 1073 | ||
1251 | ret = videobuf_mmap_mapper(&fh->vb_vidq, vma); | 1074 | ret = videobuf_mmap_mapper(&dev->vb_vidq, vma); |
1252 | 1075 | ||
1253 | dprintk(dev, 1, "vma start=0x%08lx, size=%ld, ret=%d\n", | 1076 | dprintk(dev, 1, "vma start=0x%08lx, size=%ld, ret=%d\n", |
1254 | (unsigned long)vma->vm_start, | 1077 | (unsigned long)vma->vm_start, |
1255 | (unsigned long)vma->vm_end-(unsigned long)vma->vm_start, | 1078 | (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, |
1256 | ret); | 1079 | ret); |
1257 | |||
1258 | return ret; | 1080 | return ret; |
1259 | } | 1081 | } |
1260 | 1082 | ||
1261 | static const struct v4l2_file_operations vivi_fops = { | 1083 | static const struct v4l2_file_operations vivi_fops = { |
1262 | .owner = THIS_MODULE, | 1084 | .owner = THIS_MODULE, |
1263 | .open = vivi_open, | ||
1264 | .release = vivi_close, | 1085 | .release = vivi_close, |
1265 | .read = vivi_read, | 1086 | .read = vivi_read, |
1266 | .poll = vivi_poll, | 1087 | .poll = vivi_poll, |
@@ -1282,11 +1103,11 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = { | |||
1282 | .vidioc_enum_input = vidioc_enum_input, | 1103 | .vidioc_enum_input = vidioc_enum_input, |
1283 | .vidioc_g_input = vidioc_g_input, | 1104 | .vidioc_g_input = vidioc_g_input, |
1284 | .vidioc_s_input = vidioc_s_input, | 1105 | .vidioc_s_input = vidioc_s_input, |
1106 | .vidioc_streamon = vidioc_streamon, | ||
1107 | .vidioc_streamoff = vidioc_streamoff, | ||
1285 | .vidioc_queryctrl = vidioc_queryctrl, | 1108 | .vidioc_queryctrl = vidioc_queryctrl, |
1286 | .vidioc_g_ctrl = vidioc_g_ctrl, | 1109 | .vidioc_g_ctrl = vidioc_g_ctrl, |
1287 | .vidioc_s_ctrl = vidioc_s_ctrl, | 1110 | .vidioc_s_ctrl = vidioc_s_ctrl, |
1288 | .vidioc_streamon = vidioc_streamon, | ||
1289 | .vidioc_streamoff = vidioc_streamoff, | ||
1290 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 1111 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
1291 | .vidiocgmbuf = vidiocgmbuf, | 1112 | .vidiocgmbuf = vidiocgmbuf, |
1292 | #endif | 1113 | #endif |
@@ -1330,7 +1151,7 @@ static int __init vivi_create_instance(int inst) | |||
1330 | { | 1151 | { |
1331 | struct vivi_dev *dev; | 1152 | struct vivi_dev *dev; |
1332 | struct video_device *vfd; | 1153 | struct video_device *vfd; |
1333 | int ret, i; | 1154 | int ret; |
1334 | 1155 | ||
1335 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 1156 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
1336 | if (!dev) | 1157 | if (!dev) |
@@ -1342,6 +1163,20 @@ static int __init vivi_create_instance(int inst) | |||
1342 | if (ret) | 1163 | if (ret) |
1343 | goto free_dev; | 1164 | goto free_dev; |
1344 | 1165 | ||
1166 | dev->fmt = &formats[0]; | ||
1167 | dev->width = 640; | ||
1168 | dev->height = 480; | ||
1169 | dev->volume = 200; | ||
1170 | dev->brightness = 127; | ||
1171 | dev->contrast = 16; | ||
1172 | dev->saturation = 127; | ||
1173 | dev->hue = 0; | ||
1174 | |||
1175 | videobuf_queue_vmalloc_init(&dev->vb_vidq, &vivi_video_qops, | ||
1176 | NULL, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
1177 | V4L2_FIELD_INTERLACED, | ||
1178 | sizeof(struct vivi_buffer), dev); | ||
1179 | |||
1345 | /* init video dma queues */ | 1180 | /* init video dma queues */ |
1346 | INIT_LIST_HEAD(&dev->vidq.active); | 1181 | INIT_LIST_HEAD(&dev->vidq.active); |
1347 | init_waitqueue_head(&dev->vidq.wq); | 1182 | init_waitqueue_head(&dev->vidq.wq); |
@@ -1357,6 +1192,7 @@ static int __init vivi_create_instance(int inst) | |||
1357 | 1192 | ||
1358 | *vfd = vivi_template; | 1193 | *vfd = vivi_template; |
1359 | vfd->debug = debug; | 1194 | vfd->debug = debug; |
1195 | vfd->v4l2_dev = &dev->v4l2_dev; | ||
1360 | 1196 | ||
1361 | ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); | 1197 | ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); |
1362 | if (ret < 0) | 1198 | if (ret < 0) |
@@ -1364,10 +1200,6 @@ static int __init vivi_create_instance(int inst) | |||
1364 | 1200 | ||
1365 | video_set_drvdata(vfd, dev); | 1201 | video_set_drvdata(vfd, dev); |
1366 | 1202 | ||
1367 | /* Set all controls to their default value. */ | ||
1368 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) | ||
1369 | dev->qctl_regs[i] = vivi_qctrl[i].default_value; | ||
1370 | |||
1371 | /* Now that everything is fine, let's add it to device list */ | 1203 | /* Now that everything is fine, let's add it to device list */ |
1372 | list_add_tail(&dev->vivi_devlist, &vivi_devlist); | 1204 | list_add_tail(&dev->vivi_devlist, &vivi_devlist); |
1373 | 1205 | ||
@@ -1396,8 +1228,15 @@ free_dev: | |||
1396 | */ | 1228 | */ |
1397 | static int __init vivi_init(void) | 1229 | static int __init vivi_init(void) |
1398 | { | 1230 | { |
1231 | const struct font_desc *font = find_font("VGA8x16"); | ||
1399 | int ret = 0, i; | 1232 | int ret = 0, i; |
1400 | 1233 | ||
1234 | if (font == NULL) { | ||
1235 | printk(KERN_ERR "vivi: could not find font\n"); | ||
1236 | return -ENODEV; | ||
1237 | } | ||
1238 | font8x16 = font->data; | ||
1239 | |||
1401 | if (n_devs <= 0) | 1240 | if (n_devs <= 0) |
1402 | n_devs = 1; | 1241 | n_devs = 1; |
1403 | 1242 | ||
@@ -1412,7 +1251,7 @@ static int __init vivi_init(void) | |||
1412 | } | 1251 | } |
1413 | 1252 | ||
1414 | if (ret < 0) { | 1253 | if (ret < 0) { |
1415 | printk(KERN_INFO "Error %d while loading vivi driver\n", ret); | 1254 | printk(KERN_ERR "vivi: error %d while loading driver\n", ret); |
1416 | return ret; | 1255 | return ret; |
1417 | } | 1256 | } |
1418 | 1257 | ||