aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/vivi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/vivi.c')
-rw-r--r--drivers/media/platform/vivi.c224
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 */
70static const u8 *font8x16; 78static const u8 *font8x16;
71 79
80/* timeperframe: min/max and default */
81static 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
79struct vivi_fmt { 93struct 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
86static struct vivi_fmt formats[] = { 100static 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
153static struct vivi_fmt *get_format(struct v4l2_format *f) 167static 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
184static 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 */
171struct vivi_buffer { 190struct 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
178struct vivi_dmaqueue { 197struct 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 */
279static struct bar_std bars[] = { 300static 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
512static void precalculate_line(struct vivi_dev *dev) 533static 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 */
555typedef struct { u16 __; u8 _; } __attribute__((packed)) x24;
556
523static void gen_text(struct vivi_dev *dev, char *basep, 557static 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
553static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) 605static 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
629static void vivi_thread_tick(struct vivi_dev *dev) 683static 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
661static void vivi_sleep(struct vivi_dev *dev) 715static 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
875static struct vb2_ops vivi_video_qops = { 929static 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,
903static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, 957static 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 */
1102static 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
1126static 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
1143static 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
1049static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl) 1167static 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
1212static struct video_device vivi_template = { 1333static 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;