diff options
Diffstat (limited to 'drivers/media/platform/vivi.c')
-rw-r--r-- | drivers/media/platform/vivi.c | 224 |
1 files changed, 173 insertions, 51 deletions
diff --git a/drivers/media/platform/vivi.c b/drivers/media/platform/vivi.c index 0d59b9db83cb..8a33a712f480 100644 --- a/drivers/media/platform/vivi.c +++ b/drivers/media/platform/vivi.c | |||
@@ -36,9 +36,17 @@ | |||
36 | 36 | ||
37 | #define VIVI_MODULE_NAME "vivi" | 37 | #define VIVI_MODULE_NAME "vivi" |
38 | 38 | ||
39 | /* Wake up at about 30 fps */ | 39 | /* Maximum allowed frame rate |
40 | #define WAKE_NUMERATOR 30 | 40 | * |
41 | #define WAKE_DENOMINATOR 1001 | 41 | * Vivi will allow setting timeperframe in [1/FPS_MAX - FPS_MAX/1] range. |
42 | * | ||
43 | * Ideally FPS_MAX should be infinity, i.e. practically UINT_MAX, but that | ||
44 | * might hit application errors when they manipulate these values. | ||
45 | * | ||
46 | * Besides, for tpf < 1ms image-generation logic should be changed, to avoid | ||
47 | * producing frames with equal content. | ||
48 | */ | ||
49 | #define FPS_MAX 1000 | ||
42 | 50 | ||
43 | #define MAX_WIDTH 1920 | 51 | #define MAX_WIDTH 1920 |
44 | #define MAX_HEIGHT 1200 | 52 | #define MAX_HEIGHT 1200 |
@@ -69,6 +77,12 @@ MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); | |||
69 | /* Global font descriptor */ | 77 | /* Global font descriptor */ |
70 | static const u8 *font8x16; | 78 | static const u8 *font8x16; |
71 | 79 | ||
80 | /* timeperframe: min/max and default */ | ||
81 | static const struct v4l2_fract | ||
82 | tpf_min = {.numerator = 1, .denominator = FPS_MAX}, | ||
83 | tpf_max = {.numerator = FPS_MAX, .denominator = 1}, | ||
84 | tpf_default = {.numerator = 1001, .denominator = 30000}; /* NTSC */ | ||
85 | |||
72 | #define dprintk(dev, level, fmt, arg...) \ | 86 | #define dprintk(dev, level, fmt, arg...) \ |
73 | v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg) | 87 | v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg) |
74 | 88 | ||
@@ -77,13 +91,13 @@ static const u8 *font8x16; | |||
77 | ------------------------------------------------------------------*/ | 91 | ------------------------------------------------------------------*/ |
78 | 92 | ||
79 | struct vivi_fmt { | 93 | struct vivi_fmt { |
80 | char *name; | 94 | const char *name; |
81 | u32 fourcc; /* v4l2 format id */ | 95 | u32 fourcc; /* v4l2 format id */ |
82 | u8 depth; | 96 | u8 depth; |
83 | bool is_yuv; | 97 | bool is_yuv; |
84 | }; | 98 | }; |
85 | 99 | ||
86 | static struct vivi_fmt formats[] = { | 100 | static const struct vivi_fmt formats[] = { |
87 | { | 101 | { |
88 | .name = "4:2:2, packed, YUYV", | 102 | .name = "4:2:2, packed, YUYV", |
89 | .fourcc = V4L2_PIX_FMT_YUYV, | 103 | .fourcc = V4L2_PIX_FMT_YUYV, |
@@ -150,14 +164,14 @@ static struct vivi_fmt formats[] = { | |||
150 | }, | 164 | }, |
151 | }; | 165 | }; |
152 | 166 | ||
153 | static struct vivi_fmt *get_format(struct v4l2_format *f) | 167 | static const struct vivi_fmt *__get_format(u32 pixelformat) |
154 | { | 168 | { |
155 | struct vivi_fmt *fmt; | 169 | const struct vivi_fmt *fmt; |
156 | unsigned int k; | 170 | unsigned int k; |
157 | 171 | ||
158 | for (k = 0; k < ARRAY_SIZE(formats); k++) { | 172 | for (k = 0; k < ARRAY_SIZE(formats); k++) { |
159 | fmt = &formats[k]; | 173 | fmt = &formats[k]; |
160 | if (fmt->fourcc == f->fmt.pix.pixelformat) | 174 | if (fmt->fourcc == pixelformat) |
161 | break; | 175 | break; |
162 | } | 176 | } |
163 | 177 | ||
@@ -167,12 +181,17 @@ static struct vivi_fmt *get_format(struct v4l2_format *f) | |||
167 | return &formats[k]; | 181 | return &formats[k]; |
168 | } | 182 | } |
169 | 183 | ||
184 | static const struct vivi_fmt *get_format(struct v4l2_format *f) | ||
185 | { | ||
186 | return __get_format(f->fmt.pix.pixelformat); | ||
187 | } | ||
188 | |||
170 | /* buffer for one video frame */ | 189 | /* buffer for one video frame */ |
171 | struct vivi_buffer { | 190 | struct vivi_buffer { |
172 | /* common v4l buffer stuff -- must be first */ | 191 | /* common v4l buffer stuff -- must be first */ |
173 | struct vb2_buffer vb; | 192 | struct vb2_buffer vb; |
174 | struct list_head list; | 193 | struct list_head list; |
175 | struct vivi_fmt *fmt; | 194 | const struct vivi_fmt *fmt; |
176 | }; | 195 | }; |
177 | 196 | ||
178 | struct vivi_dmaqueue { | 197 | struct vivi_dmaqueue { |
@@ -231,15 +250,17 @@ struct vivi_dev { | |||
231 | int input; | 250 | int input; |
232 | 251 | ||
233 | /* video capture */ | 252 | /* video capture */ |
234 | struct vivi_fmt *fmt; | 253 | const struct vivi_fmt *fmt; |
254 | struct v4l2_fract timeperframe; | ||
235 | unsigned int width, height; | 255 | unsigned int width, height; |
236 | struct vb2_queue vb_vidq; | 256 | struct vb2_queue vb_vidq; |
237 | unsigned int field_count; | 257 | unsigned int field_count; |
238 | 258 | ||
239 | u8 bars[9][3]; | 259 | u8 bars[9][3]; |
240 | u8 line[MAX_WIDTH * 8]; | 260 | u8 line[MAX_WIDTH * 8] __attribute__((__aligned__(4))); |
241 | unsigned int pixelsize; | 261 | unsigned int pixelsize; |
242 | u8 alpha_component; | 262 | u8 alpha_component; |
263 | u32 textfg, textbg; | ||
243 | }; | 264 | }; |
244 | 265 | ||
245 | /* ------------------------------------------------------------------ | 266 | /* ------------------------------------------------------------------ |
@@ -276,7 +297,7 @@ struct bar_std { | |||
276 | 297 | ||
277 | /* Maximum number of bars are 10 - otherwise, the input print code | 298 | /* Maximum number of bars are 10 - otherwise, the input print code |
278 | should be modified */ | 299 | should be modified */ |
279 | static struct bar_std bars[] = { | 300 | static const struct bar_std bars[] = { |
280 | { /* Standard ITU-R color bar sequence */ | 301 | { /* Standard ITU-R color bar sequence */ |
281 | { COLOR_WHITE, COLOR_AMBER, COLOR_CYAN, COLOR_GREEN, | 302 | { COLOR_WHITE, COLOR_AMBER, COLOR_CYAN, COLOR_GREEN, |
282 | COLOR_MAGENTA, COLOR_RED, COLOR_BLUE, COLOR_BLACK, COLOR_BLACK } | 303 | COLOR_MAGENTA, COLOR_RED, COLOR_BLUE, COLOR_BLACK, COLOR_BLACK } |
@@ -511,66 +532,100 @@ static void gen_twopix(struct vivi_dev *dev, u8 *buf, int colorpos, bool odd) | |||
511 | 532 | ||
512 | static void precalculate_line(struct vivi_dev *dev) | 533 | static void precalculate_line(struct vivi_dev *dev) |
513 | { | 534 | { |
514 | int w; | 535 | unsigned pixsize = dev->pixelsize; |
515 | 536 | unsigned pixsize2 = 2*pixsize; | |
516 | for (w = 0; w < dev->width * 2; w++) { | 537 | int colorpos; |
517 | int colorpos = w / (dev->width / 8) % 8; | 538 | u8 *pos; |
518 | 539 | ||
519 | gen_twopix(dev, dev->line + w * dev->pixelsize, colorpos, w & 1); | 540 | for (colorpos = 0; colorpos < 16; ++colorpos) { |
541 | u8 pix[8]; | ||
542 | int wstart = colorpos * dev->width / 8; | ||
543 | int wend = (colorpos+1) * dev->width / 8; | ||
544 | int w; | ||
545 | |||
546 | gen_twopix(dev, &pix[0], colorpos % 8, 0); | ||
547 | gen_twopix(dev, &pix[pixsize], colorpos % 8, 1); | ||
548 | |||
549 | for (w = wstart/2*2, pos = dev->line + w*pixsize; w < wend; w += 2, pos += pixsize2) | ||
550 | memcpy(pos, pix, pixsize2); | ||
520 | } | 551 | } |
521 | } | 552 | } |
522 | 553 | ||
554 | /* need this to do rgb24 rendering */ | ||
555 | typedef struct { u16 __; u8 _; } __attribute__((packed)) x24; | ||
556 | |||
523 | static void gen_text(struct vivi_dev *dev, char *basep, | 557 | static void gen_text(struct vivi_dev *dev, char *basep, |
524 | int y, int x, char *text) | 558 | int y, int x, char *text) |
525 | { | 559 | { |
526 | int line; | 560 | int line; |
561 | unsigned int width = dev->width; | ||
527 | 562 | ||
528 | /* Checks if it is possible to show string */ | 563 | /* Checks if it is possible to show string */ |
529 | if (y + 16 >= dev->height || x + strlen(text) * 8 >= dev->width) | 564 | if (y + 16 >= dev->height || x + strlen(text) * 8 >= width) |
530 | return; | 565 | return; |
531 | 566 | ||
532 | /* Print stream time */ | 567 | /* Print stream time */ |
533 | for (line = y; line < y + 16; line++) { | 568 | #define PRINTSTR(PIXTYPE) do { \ |
534 | int j = 0; | 569 | PIXTYPE fg; \ |
535 | char *pos = basep + line * dev->width * dev->pixelsize + x * dev->pixelsize; | 570 | PIXTYPE bg; \ |
536 | char *s; | 571 | memcpy(&fg, &dev->textfg, sizeof(PIXTYPE)); \ |
537 | 572 | memcpy(&bg, &dev->textbg, sizeof(PIXTYPE)); \ | |
538 | for (s = text; *s; s++) { | 573 | \ |
539 | u8 chr = font8x16[*s * 16 + line - y]; | 574 | for (line = 0; line < 16; line++) { \ |
540 | int i; | 575 | PIXTYPE *pos = (PIXTYPE *)( basep + ((y + line) * width + x) * sizeof(PIXTYPE) ); \ |
541 | 576 | u8 *s; \ | |
542 | for (i = 0; i < 7; i++, j++) { | 577 | \ |
543 | /* Draw white font on black background */ | 578 | for (s = text; *s; s++) { \ |
544 | if (chr & (1 << (7 - i))) | 579 | u8 chr = font8x16[*s * 16 + line]; \ |
545 | gen_twopix(dev, pos + j * dev->pixelsize, WHITE, (x+y) & 1); | 580 | \ |
546 | else | 581 | pos[0] = (chr & (0x01 << 7) ? fg : bg); \ |
547 | gen_twopix(dev, pos + j * dev->pixelsize, TEXT_BLACK, (x+y) & 1); | 582 | pos[1] = (chr & (0x01 << 6) ? fg : bg); \ |
548 | } | 583 | pos[2] = (chr & (0x01 << 5) ? fg : bg); \ |
549 | } | 584 | pos[3] = (chr & (0x01 << 4) ? fg : bg); \ |
585 | pos[4] = (chr & (0x01 << 3) ? fg : bg); \ | ||
586 | pos[5] = (chr & (0x01 << 2) ? fg : bg); \ | ||
587 | pos[6] = (chr & (0x01 << 1) ? fg : bg); \ | ||
588 | pos[7] = (chr & (0x01 << 0) ? fg : bg); \ | ||
589 | \ | ||
590 | pos += 8; \ | ||
591 | } \ | ||
592 | } \ | ||
593 | } while (0) | ||
594 | |||
595 | switch (dev->pixelsize) { | ||
596 | case 2: | ||
597 | PRINTSTR(u16); break; | ||
598 | case 4: | ||
599 | PRINTSTR(u32); break; | ||
600 | case 3: | ||
601 | PRINTSTR(x24); break; | ||
550 | } | 602 | } |
551 | } | 603 | } |
552 | 604 | ||
553 | static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) | 605 | static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) |
554 | { | 606 | { |
555 | int wmax = dev->width; | 607 | int stride = dev->width * dev->pixelsize; |
556 | int hmax = dev->height; | 608 | int hmax = dev->height; |
557 | struct timeval ts; | ||
558 | void *vbuf = vb2_plane_vaddr(&buf->vb, 0); | 609 | void *vbuf = vb2_plane_vaddr(&buf->vb, 0); |
559 | unsigned ms; | 610 | unsigned ms; |
560 | char str[100]; | 611 | char str[100]; |
561 | int h, line = 1; | 612 | int h, line = 1; |
613 | u8 *linestart; | ||
562 | s32 gain; | 614 | s32 gain; |
563 | 615 | ||
564 | if (!vbuf) | 616 | if (!vbuf) |
565 | return; | 617 | return; |
566 | 618 | ||
619 | linestart = dev->line + (dev->mv_count % dev->width) * dev->pixelsize; | ||
620 | |||
567 | for (h = 0; h < hmax; h++) | 621 | for (h = 0; h < hmax; h++) |
568 | memcpy(vbuf + h * wmax * dev->pixelsize, | 622 | memcpy(vbuf + h * stride, linestart, stride); |
569 | dev->line + (dev->mv_count % wmax) * dev->pixelsize, | ||
570 | wmax * dev->pixelsize); | ||
571 | 623 | ||
572 | /* Updates stream time */ | 624 | /* Updates stream time */ |
573 | 625 | ||
626 | gen_twopix(dev, (u8 *)&dev->textbg, TEXT_BLACK, /*odd=*/ 0); | ||
627 | gen_twopix(dev, (u8 *)&dev->textfg, WHITE, /*odd=*/ 0); | ||
628 | |||
574 | dev->ms += jiffies_to_msecs(jiffies - dev->jiffies); | 629 | dev->ms += jiffies_to_msecs(jiffies - dev->jiffies); |
575 | dev->jiffies = jiffies; | 630 | dev->jiffies = jiffies; |
576 | ms = dev->ms; | 631 | ms = dev->ms; |
@@ -622,8 +677,7 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) | |||
622 | buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; | 677 | buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; |
623 | dev->field_count++; | 678 | dev->field_count++; |
624 | buf->vb.v4l2_buf.sequence = dev->field_count >> 1; | 679 | buf->vb.v4l2_buf.sequence = dev->field_count >> 1; |
625 | do_gettimeofday(&ts); | 680 | v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); |
626 | buf->vb.v4l2_buf.timestamp = ts; | ||
627 | } | 681 | } |
628 | 682 | ||
629 | static void vivi_thread_tick(struct vivi_dev *dev) | 683 | static void vivi_thread_tick(struct vivi_dev *dev) |
@@ -645,7 +699,7 @@ static void vivi_thread_tick(struct vivi_dev *dev) | |||
645 | list_del(&buf->list); | 699 | list_del(&buf->list); |
646 | spin_unlock_irqrestore(&dev->slock, flags); | 700 | spin_unlock_irqrestore(&dev->slock, flags); |
647 | 701 | ||
648 | do_gettimeofday(&buf->vb.v4l2_buf.timestamp); | 702 | v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); |
649 | 703 | ||
650 | /* Fill buffer */ | 704 | /* Fill buffer */ |
651 | vivi_fillbuff(dev, buf); | 705 | vivi_fillbuff(dev, buf); |
@@ -655,8 +709,8 @@ static void vivi_thread_tick(struct vivi_dev *dev) | |||
655 | dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index); | 709 | dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index); |
656 | } | 710 | } |
657 | 711 | ||
658 | #define frames_to_ms(frames) \ | 712 | #define frames_to_ms(dev, frames) \ |
659 | ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR) | 713 | ((frames * dev->timeperframe.numerator * 1000) / dev->timeperframe.denominator) |
660 | 714 | ||
661 | static void vivi_sleep(struct vivi_dev *dev) | 715 | static void vivi_sleep(struct vivi_dev *dev) |
662 | { | 716 | { |
@@ -672,7 +726,7 @@ static void vivi_sleep(struct vivi_dev *dev) | |||
672 | goto stop_task; | 726 | goto stop_task; |
673 | 727 | ||
674 | /* Calculate time to wake up */ | 728 | /* Calculate time to wake up */ |
675 | timeout = msecs_to_jiffies(frames_to_ms(1)); | 729 | timeout = msecs_to_jiffies(frames_to_ms(dev, 1)); |
676 | 730 | ||
677 | vivi_thread_tick(dev); | 731 | vivi_thread_tick(dev); |
678 | 732 | ||
@@ -872,7 +926,7 @@ static void vivi_unlock(struct vb2_queue *vq) | |||
872 | } | 926 | } |
873 | 927 | ||
874 | 928 | ||
875 | static struct vb2_ops vivi_video_qops = { | 929 | static const struct vb2_ops vivi_video_qops = { |
876 | .queue_setup = queue_setup, | 930 | .queue_setup = queue_setup, |
877 | .buf_prepare = buffer_prepare, | 931 | .buf_prepare = buffer_prepare, |
878 | .buf_queue = buffer_queue, | 932 | .buf_queue = buffer_queue, |
@@ -903,7 +957,7 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
903 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | 957 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, |
904 | struct v4l2_fmtdesc *f) | 958 | struct v4l2_fmtdesc *f) |
905 | { | 959 | { |
906 | struct vivi_fmt *fmt; | 960 | const struct vivi_fmt *fmt; |
907 | 961 | ||
908 | if (f->index >= ARRAY_SIZE(formats)) | 962 | if (f->index >= ARRAY_SIZE(formats)) |
909 | return -EINVAL; | 963 | return -EINVAL; |
@@ -939,7 +993,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
939 | struct v4l2_format *f) | 993 | struct v4l2_format *f) |
940 | { | 994 | { |
941 | struct vivi_dev *dev = video_drvdata(file); | 995 | struct vivi_dev *dev = video_drvdata(file); |
942 | struct vivi_fmt *fmt; | 996 | const struct vivi_fmt *fmt; |
943 | 997 | ||
944 | fmt = get_format(f); | 998 | fmt = get_format(f); |
945 | if (!fmt) { | 999 | if (!fmt) { |
@@ -1044,6 +1098,70 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | |||
1044 | return 0; | 1098 | return 0; |
1045 | } | 1099 | } |
1046 | 1100 | ||
1101 | /* timeperframe is arbitrary and continous */ | ||
1102 | static int vidioc_enum_frameintervals(struct file *file, void *priv, | ||
1103 | struct v4l2_frmivalenum *fival) | ||
1104 | { | ||
1105 | const struct vivi_fmt *fmt; | ||
1106 | |||
1107 | if (fival->index) | ||
1108 | return -EINVAL; | ||
1109 | |||
1110 | fmt = __get_format(fival->pixel_format); | ||
1111 | if (!fmt) | ||
1112 | return -EINVAL; | ||
1113 | |||
1114 | /* regarding width & height - we support any */ | ||
1115 | |||
1116 | fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS; | ||
1117 | |||
1118 | /* fill in stepwise (step=1.0 is requred by V4L2 spec) */ | ||
1119 | fival->stepwise.min = tpf_min; | ||
1120 | fival->stepwise.max = tpf_max; | ||
1121 | fival->stepwise.step = (struct v4l2_fract) {1, 1}; | ||
1122 | |||
1123 | return 0; | ||
1124 | } | ||
1125 | |||
1126 | static int vidioc_g_parm(struct file *file, void *priv, | ||
1127 | struct v4l2_streamparm *parm) | ||
1128 | { | ||
1129 | struct vivi_dev *dev = video_drvdata(file); | ||
1130 | |||
1131 | if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1132 | return -EINVAL; | ||
1133 | |||
1134 | parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; | ||
1135 | parm->parm.capture.timeperframe = dev->timeperframe; | ||
1136 | parm->parm.capture.readbuffers = 1; | ||
1137 | return 0; | ||
1138 | } | ||
1139 | |||
1140 | #define FRACT_CMP(a, OP, b) \ | ||
1141 | ((u64)(a).numerator * (b).denominator OP (u64)(b).numerator * (a).denominator) | ||
1142 | |||
1143 | static int vidioc_s_parm(struct file *file, void *priv, | ||
1144 | struct v4l2_streamparm *parm) | ||
1145 | { | ||
1146 | struct vivi_dev *dev = video_drvdata(file); | ||
1147 | struct v4l2_fract tpf; | ||
1148 | |||
1149 | if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1150 | return -EINVAL; | ||
1151 | |||
1152 | tpf = parm->parm.capture.timeperframe; | ||
1153 | |||
1154 | /* tpf: {*, 0} resets timing; clip to [min, max]*/ | ||
1155 | tpf = tpf.denominator ? tpf : tpf_default; | ||
1156 | tpf = FRACT_CMP(tpf, <, tpf_min) ? tpf_min : tpf; | ||
1157 | tpf = FRACT_CMP(tpf, >, tpf_max) ? tpf_max : tpf; | ||
1158 | |||
1159 | dev->timeperframe = tpf; | ||
1160 | parm->parm.capture.timeperframe = tpf; | ||
1161 | parm->parm.capture.readbuffers = 1; | ||
1162 | return 0; | ||
1163 | } | ||
1164 | |||
1047 | /* --- controls ---------------------------------------------- */ | 1165 | /* --- controls ---------------------------------------------- */ |
1048 | 1166 | ||
1049 | static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | 1167 | static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl) |
@@ -1202,6 +1320,9 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = { | |||
1202 | .vidioc_enum_input = vidioc_enum_input, | 1320 | .vidioc_enum_input = vidioc_enum_input, |
1203 | .vidioc_g_input = vidioc_g_input, | 1321 | .vidioc_g_input = vidioc_g_input, |
1204 | .vidioc_s_input = vidioc_s_input, | 1322 | .vidioc_s_input = vidioc_s_input, |
1323 | .vidioc_enum_frameintervals = vidioc_enum_frameintervals, | ||
1324 | .vidioc_g_parm = vidioc_g_parm, | ||
1325 | .vidioc_s_parm = vidioc_s_parm, | ||
1205 | .vidioc_streamon = vb2_ioctl_streamon, | 1326 | .vidioc_streamon = vb2_ioctl_streamon, |
1206 | .vidioc_streamoff = vb2_ioctl_streamoff, | 1327 | .vidioc_streamoff = vb2_ioctl_streamoff, |
1207 | .vidioc_log_status = v4l2_ctrl_log_status, | 1328 | .vidioc_log_status = v4l2_ctrl_log_status, |
@@ -1209,7 +1330,7 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = { | |||
1209 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | 1330 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, |
1210 | }; | 1331 | }; |
1211 | 1332 | ||
1212 | static struct video_device vivi_template = { | 1333 | static const struct video_device vivi_template = { |
1213 | .name = "vivi", | 1334 | .name = "vivi", |
1214 | .fops = &vivi_fops, | 1335 | .fops = &vivi_fops, |
1215 | .ioctl_ops = &vivi_ioctl_ops, | 1336 | .ioctl_ops = &vivi_ioctl_ops, |
@@ -1260,6 +1381,7 @@ static int __init vivi_create_instance(int inst) | |||
1260 | goto free_dev; | 1381 | goto free_dev; |
1261 | 1382 | ||
1262 | dev->fmt = &formats[0]; | 1383 | dev->fmt = &formats[0]; |
1384 | dev->timeperframe = tpf_default; | ||
1263 | dev->width = 640; | 1385 | dev->width = 640; |
1264 | dev->height = 480; | 1386 | dev->height = 480; |
1265 | dev->pixelsize = dev->fmt->depth / 8; | 1387 | dev->pixelsize = dev->fmt->depth / 8; |