2 * sh-mobile VEU mem2mem driver
4 * Copyright (C) 2012 Renesas Electronics Corporation
5 * Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de>
6 * Copyright (C) 2008 Magnus Damm
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the version 2 of the GNU General Public License as
10 * published by the Free Software Foundation
13 #include <linux/err.h>
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/interrupt.h>
19 #include <linux/platform_device.h>
20 #include <linux/pm_runtime.h>
21 #include <linux/slab.h>
22 #include <linux/types.h>
23 #include <linux/videodev2.h>
25 #include <media/v4l2-dev.h>
26 #include <media/v4l2-device.h>
27 #include <media/v4l2-ioctl.h>
28 #include <media/v4l2-mem2mem.h>
29 #include <media/videobuf2-dma-contig.h>
31 #define VEU_STR 0x00 /* start register */
32 #define VEU_SWR 0x10 /* src: line length */
33 #define VEU_SSR 0x14 /* src: image size */
34 #define VEU_SAYR 0x18 /* src: y/rgb plane address */
35 #define VEU_SACR 0x1c /* src: c plane address */
36 #define VEU_BSSR 0x20 /* bundle mode register */
37 #define VEU_EDWR 0x30 /* dst: line length */
38 #define VEU_DAYR 0x34 /* dst: y/rgb plane address */
39 #define VEU_DACR 0x38 /* dst: c plane address */
40 #define VEU_TRCR 0x50 /* transform control */
41 #define VEU_RFCR 0x54 /* resize scale */
42 #define VEU_RFSR 0x58 /* resize clip */
43 #define VEU_ENHR 0x5c /* enhance */
44 #define VEU_FMCR 0x70 /* filter mode */
45 #define VEU_VTCR 0x74 /* lowpass vertical */
46 #define VEU_HTCR 0x78 /* lowpass horizontal */
47 #define VEU_APCR 0x80 /* color match */
48 #define VEU_ECCR 0x84 /* color replace */
49 #define VEU_AFXR 0x90 /* fixed mode */
50 #define VEU_SWPR 0x94 /* swap */
51 #define VEU_EIER 0xa0 /* interrupt mask */
52 #define VEU_EVTR 0xa4 /* interrupt event */
53 #define VEU_STAR 0xb0 /* status */
54 #define VEU_BSRR 0xb4 /* reset */
56 #define VEU_MCR00 0x200 /* color conversion matrix coefficient 00 */
57 #define VEU_MCR01 0x204 /* color conversion matrix coefficient 01 */
58 #define VEU_MCR02 0x208 /* color conversion matrix coefficient 02 */
59 #define VEU_MCR10 0x20c /* color conversion matrix coefficient 10 */
60 #define VEU_MCR11 0x210 /* color conversion matrix coefficient 11 */
61 #define VEU_MCR12 0x214 /* color conversion matrix coefficient 12 */
62 #define VEU_MCR20 0x218 /* color conversion matrix coefficient 20 */
63 #define VEU_MCR21 0x21c /* color conversion matrix coefficient 21 */
64 #define VEU_MCR22 0x220 /* color conversion matrix coefficient 22 */
65 #define VEU_COFFR 0x224 /* color conversion offset */
66 #define VEU_CBR 0x228 /* color conversion clip */
69 * 4092x4092 max size is the normal case. In some cases it can be reduced to
70 * 2048x2048, in other cases it can be 4092x8188 or even 8188x8188.
78 /* 3 buffers of 2048 x 1536 - 3 megapixels @ 16bpp */
79 #define VIDEO_MEM_LIMIT ALIGN(2048 * 1536 * 2 * 3, 1024 * 1024)
81 #define MEM2MEM_DEF_TRANSLEN 1
86 struct sh_veu_dev
*veu_dev
;
90 struct sh_veu_format
{
97 /* video data format */
99 /* Replace with v4l2_rect */
100 struct v4l2_rect frame
;
101 unsigned int bytesperline
;
102 unsigned int offset_y
;
103 unsigned int offset_c
;
104 const struct sh_veu_format
*fmt
;
108 struct v4l2_device v4l2_dev
;
109 struct video_device vdev
;
110 struct v4l2_m2m_dev
*m2m_dev
;
112 struct v4l2_m2m_ctx
*m2m_ctx
;
113 struct sh_veu_vfmt vfmt_out
;
114 struct sh_veu_vfmt vfmt_in
;
115 /* Only single user per direction so far */
116 struct sh_veu_file
*capture
;
117 struct sh_veu_file
*output
;
118 struct mutex fop_lock
;
120 struct vb2_alloc_ctx
*alloc_ctx
;
123 unsigned int xaction
;
127 enum sh_veu_fmt_idx
{
138 #define VGA_WIDTH 640
139 #define VGA_HEIGHT 480
141 #define DEFAULT_IN_WIDTH VGA_WIDTH
142 #define DEFAULT_IN_HEIGHT VGA_HEIGHT
143 #define DEFAULT_IN_FMTIDX SH_VEU_FMT_NV12
144 #define DEFAULT_OUT_WIDTH VGA_WIDTH
145 #define DEFAULT_OUT_HEIGHT VGA_HEIGHT
146 #define DEFAULT_OUT_FMTIDX SH_VEU_FMT_RGB565
149 * Alignment: Y-plane should be 4-byte aligned for NV12 and NV16, and 8-byte
152 static const struct sh_veu_format sh_veu_fmt
[] = {
153 [SH_VEU_FMT_NV12
] = { .ydepth
= 8, .depth
= 12, .name
= "NV12", .fourcc
= V4L2_PIX_FMT_NV12
},
154 [SH_VEU_FMT_NV16
] = { .ydepth
= 8, .depth
= 16, .name
= "NV16", .fourcc
= V4L2_PIX_FMT_NV16
},
155 [SH_VEU_FMT_NV24
] = { .ydepth
= 8, .depth
= 24, .name
= "NV24", .fourcc
= V4L2_PIX_FMT_NV24
},
156 [SH_VEU_FMT_RGB332
] = { .ydepth
= 8, .depth
= 8, .name
= "RGB332", .fourcc
= V4L2_PIX_FMT_RGB332
},
157 [SH_VEU_FMT_RGB444
] = { .ydepth
= 16, .depth
= 16, .name
= "RGB444", .fourcc
= V4L2_PIX_FMT_RGB444
},
158 [SH_VEU_FMT_RGB565
] = { .ydepth
= 16, .depth
= 16, .name
= "RGB565", .fourcc
= V4L2_PIX_FMT_RGB565
},
159 [SH_VEU_FMT_RGB666
] = { .ydepth
= 32, .depth
= 32, .name
= "BGR666", .fourcc
= V4L2_PIX_FMT_BGR666
},
160 [SH_VEU_FMT_RGB24
] = { .ydepth
= 24, .depth
= 24, .name
= "RGB24", .fourcc
= V4L2_PIX_FMT_RGB24
},
163 #define DEFAULT_IN_VFMT (struct sh_veu_vfmt){ \
165 .width = VGA_WIDTH, \
166 .height = VGA_HEIGHT, \
168 .bytesperline = (VGA_WIDTH * sh_veu_fmt[DEFAULT_IN_FMTIDX].ydepth) >> 3, \
169 .fmt = &sh_veu_fmt[DEFAULT_IN_FMTIDX], \
172 #define DEFAULT_OUT_VFMT (struct sh_veu_vfmt){ \
174 .width = VGA_WIDTH, \
175 .height = VGA_HEIGHT, \
177 .bytesperline = (VGA_WIDTH * sh_veu_fmt[DEFAULT_OUT_FMTIDX].ydepth) >> 3, \
178 .fmt = &sh_veu_fmt[DEFAULT_OUT_FMTIDX], \
182 * TODO: add support for further output formats:
192 static const int sh_veu_fmt_out
[] = {
197 * TODO: add support for further input formats:
204 static const int sh_veu_fmt_in
[] = {
208 static enum v4l2_colorspace
sh_veu_4cc2cspace(u32 fourcc
)
213 case V4L2_PIX_FMT_NV12
:
214 case V4L2_PIX_FMT_NV16
:
215 case V4L2_PIX_FMT_NV24
:
216 return V4L2_COLORSPACE_JPEG
;
217 case V4L2_PIX_FMT_RGB332
:
218 case V4L2_PIX_FMT_RGB444
:
219 case V4L2_PIX_FMT_RGB565
:
220 case V4L2_PIX_FMT_BGR666
:
221 case V4L2_PIX_FMT_RGB24
:
222 return V4L2_COLORSPACE_SRGB
;
226 static u32
sh_veu_reg_read(struct sh_veu_dev
*veu
, unsigned int reg
)
228 return ioread32(veu
->base
+ reg
);
231 static void sh_veu_reg_write(struct sh_veu_dev
*veu
, unsigned int reg
,
234 iowrite32(value
, veu
->base
+ reg
);
237 /* ========== mem2mem callbacks ========== */
239 static void sh_veu_job_abort(void *priv
)
241 struct sh_veu_dev
*veu
= priv
;
243 /* Will cancel the transaction in the next interrupt handler */
244 veu
->aborting
= true;
247 static void sh_veu_lock(void *priv
)
249 struct sh_veu_dev
*veu
= priv
;
251 mutex_lock(&veu
->fop_lock
);
254 static void sh_veu_unlock(void *priv
)
256 struct sh_veu_dev
*veu
= priv
;
258 mutex_unlock(&veu
->fop_lock
);
261 static void sh_veu_process(struct sh_veu_dev
*veu
,
262 struct vb2_buffer
*src_buf
,
263 struct vb2_buffer
*dst_buf
)
265 dma_addr_t addr
= vb2_dma_contig_plane_dma_addr(dst_buf
, 0);
267 sh_veu_reg_write(veu
, VEU_DAYR
, addr
+ veu
->vfmt_out
.offset_y
);
268 sh_veu_reg_write(veu
, VEU_DACR
, veu
->vfmt_out
.offset_c
?
269 addr
+ veu
->vfmt_out
.offset_c
: 0);
270 dev_dbg(veu
->dev
, "%s(): dst base %lx, y: %x, c: %x\n", __func__
,
272 veu
->vfmt_out
.offset_y
, veu
->vfmt_out
.offset_c
);
274 addr
= vb2_dma_contig_plane_dma_addr(src_buf
, 0);
275 sh_veu_reg_write(veu
, VEU_SAYR
, addr
+ veu
->vfmt_in
.offset_y
);
276 sh_veu_reg_write(veu
, VEU_SACR
, veu
->vfmt_in
.offset_c
?
277 addr
+ veu
->vfmt_in
.offset_c
: 0);
278 dev_dbg(veu
->dev
, "%s(): src base %lx, y: %x, c: %x\n", __func__
,
280 veu
->vfmt_in
.offset_y
, veu
->vfmt_in
.offset_c
);
282 sh_veu_reg_write(veu
, VEU_STR
, 1);
284 sh_veu_reg_write(veu
, VEU_EIER
, 1); /* enable interrupt in VEU */
288 * sh_veu_device_run() - prepares and starts the device
290 * This will be called by the framework when it decides to schedule a particular
293 static void sh_veu_device_run(void *priv
)
295 struct sh_veu_dev
*veu
= priv
;
296 struct vb2_buffer
*src_buf
, *dst_buf
;
298 src_buf
= v4l2_m2m_next_src_buf(veu
->m2m_ctx
);
299 dst_buf
= v4l2_m2m_next_dst_buf(veu
->m2m_ctx
);
301 if (src_buf
&& dst_buf
)
302 sh_veu_process(veu
, src_buf
, dst_buf
);
305 /* ========== video ioctls ========== */
307 static bool sh_veu_is_streamer(struct sh_veu_dev
*veu
, struct sh_veu_file
*veu_file
,
308 enum v4l2_buf_type type
)
310 return (type
== V4L2_BUF_TYPE_VIDEO_CAPTURE
&&
311 veu_file
== veu
->capture
) ||
312 (type
== V4L2_BUF_TYPE_VIDEO_OUTPUT
&&
313 veu_file
== veu
->output
);
316 static int sh_veu_queue_init(void *priv
, struct vb2_queue
*src_vq
,
317 struct vb2_queue
*dst_vq
);
320 * It is not unusual to have video nodes open()ed multiple times. While some
321 * V4L2 operations are non-intrusive, like querying formats and various
322 * parameters, others, like setting formats, starting and stopping streaming,
323 * queuing and dequeuing buffers, directly affect hardware configuration and /
324 * or execution. This function verifies availability of the requested interface
325 * and, if available, reserves it for the requesting user.
327 static int sh_veu_stream_init(struct sh_veu_dev
*veu
, struct sh_veu_file
*veu_file
,
328 enum v4l2_buf_type type
)
330 struct sh_veu_file
**stream
;
333 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
334 stream
= &veu
->capture
;
336 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
337 stream
= &veu
->output
;
343 if (*stream
== veu_file
)
354 static int sh_veu_context_init(struct sh_veu_dev
*veu
)
359 veu
->m2m_ctx
= v4l2_m2m_ctx_init(veu
->m2m_dev
, veu
,
362 return PTR_ERR_OR_ZERO(veu
->m2m_ctx
);
365 static int sh_veu_querycap(struct file
*file
, void *priv
,
366 struct v4l2_capability
*cap
)
368 strlcpy(cap
->driver
, "sh-veu", sizeof(cap
->driver
));
369 strlcpy(cap
->card
, "sh-mobile VEU", sizeof(cap
->card
));
370 strlcpy(cap
->bus_info
, "platform:sh-veu", sizeof(cap
->bus_info
));
371 cap
->device_caps
= V4L2_CAP_VIDEO_M2M
| V4L2_CAP_STREAMING
;
372 cap
->capabilities
= cap
->device_caps
| V4L2_CAP_DEVICE_CAPS
;
377 static int sh_veu_enum_fmt(struct v4l2_fmtdesc
*f
, const int *fmt
, int fmt_num
)
379 if (f
->index
>= fmt_num
)
382 strlcpy(f
->description
, sh_veu_fmt
[fmt
[f
->index
]].name
, sizeof(f
->description
));
383 f
->pixelformat
= sh_veu_fmt
[fmt
[f
->index
]].fourcc
;
387 static int sh_veu_enum_fmt_vid_cap(struct file
*file
, void *priv
,
388 struct v4l2_fmtdesc
*f
)
390 return sh_veu_enum_fmt(f
, sh_veu_fmt_out
, ARRAY_SIZE(sh_veu_fmt_out
));
393 static int sh_veu_enum_fmt_vid_out(struct file
*file
, void *priv
,
394 struct v4l2_fmtdesc
*f
)
396 return sh_veu_enum_fmt(f
, sh_veu_fmt_in
, ARRAY_SIZE(sh_veu_fmt_in
));
399 static struct sh_veu_vfmt
*sh_veu_get_vfmt(struct sh_veu_dev
*veu
,
400 enum v4l2_buf_type type
)
403 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
404 return &veu
->vfmt_out
;
405 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
406 return &veu
->vfmt_in
;
412 static int sh_veu_g_fmt(struct sh_veu_file
*veu_file
, struct v4l2_format
*f
)
414 struct v4l2_pix_format
*pix
= &f
->fmt
.pix
;
415 struct sh_veu_dev
*veu
= veu_file
->veu_dev
;
416 struct sh_veu_vfmt
*vfmt
;
418 vfmt
= sh_veu_get_vfmt(veu
, f
->type
);
420 pix
->width
= vfmt
->frame
.width
;
421 pix
->height
= vfmt
->frame
.height
;
422 pix
->field
= V4L2_FIELD_NONE
;
423 pix
->pixelformat
= vfmt
->fmt
->fourcc
;
424 pix
->colorspace
= sh_veu_4cc2cspace(pix
->pixelformat
);
425 pix
->bytesperline
= vfmt
->bytesperline
;
426 pix
->sizeimage
= vfmt
->bytesperline
* pix
->height
*
427 vfmt
->fmt
->depth
/ vfmt
->fmt
->ydepth
;
429 dev_dbg(veu
->dev
, "%s(): type: %d, size %u @ %ux%u, fmt %x\n", __func__
,
430 f
->type
, pix
->sizeimage
, pix
->width
, pix
->height
, pix
->pixelformat
);
435 static int sh_veu_g_fmt_vid_out(struct file
*file
, void *priv
,
436 struct v4l2_format
*f
)
438 return sh_veu_g_fmt(priv
, f
);
441 static int sh_veu_g_fmt_vid_cap(struct file
*file
, void *priv
,
442 struct v4l2_format
*f
)
444 return sh_veu_g_fmt(priv
, f
);
447 static int sh_veu_try_fmt(struct v4l2_format
*f
, const struct sh_veu_format
*fmt
)
449 struct v4l2_pix_format
*pix
= &f
->fmt
.pix
;
450 unsigned int y_bytes_used
;
453 * V4L2 specification suggests, that the driver should correct the
454 * format struct if any of the dimensions is unsupported
456 switch (pix
->field
) {
459 pix
->field
= V4L2_FIELD_NONE
;
460 /* fall through: continue handling V4L2_FIELD_NONE */
461 case V4L2_FIELD_NONE
:
465 v4l_bound_align_image(&pix
->width
, MIN_W
, MAX_W
, ALIGN_W
,
466 &pix
->height
, MIN_H
, MAX_H
, 0, 0);
468 y_bytes_used
= (pix
->width
* fmt
->ydepth
) >> 3;
470 if (pix
->bytesperline
< y_bytes_used
)
471 pix
->bytesperline
= y_bytes_used
;
472 pix
->sizeimage
= pix
->height
* pix
->bytesperline
* fmt
->depth
/ fmt
->ydepth
;
474 pix
->pixelformat
= fmt
->fourcc
;
475 pix
->colorspace
= sh_veu_4cc2cspace(pix
->pixelformat
);
478 pr_debug("%s(): type: %d, size %u\n", __func__
, f
->type
, pix
->sizeimage
);
483 static const struct sh_veu_format
*sh_veu_find_fmt(const struct v4l2_format
*f
)
488 pr_debug("%s(%d;%d)\n", __func__
, f
->type
, f
->fmt
.pix
.field
);
491 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
492 fmt
= sh_veu_fmt_out
;
493 n
= ARRAY_SIZE(sh_veu_fmt_out
);
494 dflt
= DEFAULT_OUT_FMTIDX
;
496 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
499 n
= ARRAY_SIZE(sh_veu_fmt_in
);
500 dflt
= DEFAULT_IN_FMTIDX
;
504 for (i
= 0; i
< n
; i
++)
505 if (sh_veu_fmt
[fmt
[i
]].fourcc
== f
->fmt
.pix
.pixelformat
)
506 return &sh_veu_fmt
[fmt
[i
]];
508 return &sh_veu_fmt
[dflt
];
511 static int sh_veu_try_fmt_vid_cap(struct file
*file
, void *priv
,
512 struct v4l2_format
*f
)
514 const struct sh_veu_format
*fmt
;
516 fmt
= sh_veu_find_fmt(f
);
518 /* wrong buffer type */
521 return sh_veu_try_fmt(f
, fmt
);
524 static int sh_veu_try_fmt_vid_out(struct file
*file
, void *priv
,
525 struct v4l2_format
*f
)
527 const struct sh_veu_format
*fmt
;
529 fmt
= sh_veu_find_fmt(f
);
531 /* wrong buffer type */
534 return sh_veu_try_fmt(f
, fmt
);
537 static void sh_veu_colour_offset(struct sh_veu_dev
*veu
, struct sh_veu_vfmt
*vfmt
)
539 /* dst_left and dst_top validity will be verified in CROP / COMPOSE */
540 unsigned int left
= vfmt
->frame
.left
& ~0x03;
541 unsigned int top
= vfmt
->frame
.top
;
542 dma_addr_t offset
= ((left
* veu
->vfmt_out
.fmt
->depth
) >> 3) +
543 top
* veu
->vfmt_out
.bytesperline
;
546 vfmt
->offset_y
= offset
;
548 switch (vfmt
->fmt
->fourcc
) {
549 case V4L2_PIX_FMT_NV12
:
550 case V4L2_PIX_FMT_NV16
:
551 case V4L2_PIX_FMT_NV24
:
552 y_line
= ALIGN(vfmt
->frame
.width
, 16);
553 vfmt
->offset_c
= offset
+ y_line
* vfmt
->frame
.height
;
555 case V4L2_PIX_FMT_RGB332
:
556 case V4L2_PIX_FMT_RGB444
:
557 case V4L2_PIX_FMT_RGB565
:
558 case V4L2_PIX_FMT_BGR666
:
559 case V4L2_PIX_FMT_RGB24
:
567 static int sh_veu_s_fmt(struct sh_veu_file
*veu_file
, struct v4l2_format
*f
)
569 struct v4l2_pix_format
*pix
= &f
->fmt
.pix
;
570 struct sh_veu_dev
*veu
= veu_file
->veu_dev
;
571 struct sh_veu_vfmt
*vfmt
;
572 struct vb2_queue
*vq
;
573 int ret
= sh_veu_context_init(veu
);
577 vq
= v4l2_m2m_get_vq(veu
->m2m_ctx
, f
->type
);
581 if (vb2_is_busy(vq
)) {
582 v4l2_err(&veu_file
->veu_dev
->v4l2_dev
, "%s queue busy\n", __func__
);
586 vfmt
= sh_veu_get_vfmt(veu
, f
->type
);
587 /* called after try_fmt(), hence vfmt != NULL. Implicit BUG_ON() below */
589 vfmt
->fmt
= sh_veu_find_fmt(f
);
590 /* vfmt->fmt != NULL following the same argument as above */
591 vfmt
->frame
.width
= pix
->width
;
592 vfmt
->frame
.height
= pix
->height
;
593 vfmt
->bytesperline
= pix
->bytesperline
;
595 sh_veu_colour_offset(veu
, vfmt
);
598 * We could also verify and require configuration only if any parameters
599 * actually have changed, but it is unlikely, that the user requests the
600 * same configuration several times without closing the device.
602 veu_file
->cfg_needed
= true;
605 "Setting format for type %d, wxh: %dx%d, fmt: %x\n",
606 f
->type
, pix
->width
, pix
->height
, vfmt
->fmt
->fourcc
);
611 static int sh_veu_s_fmt_vid_cap(struct file
*file
, void *priv
,
612 struct v4l2_format
*f
)
614 int ret
= sh_veu_try_fmt_vid_cap(file
, priv
, f
);
618 return sh_veu_s_fmt(priv
, f
);
621 static int sh_veu_s_fmt_vid_out(struct file
*file
, void *priv
,
622 struct v4l2_format
*f
)
624 int ret
= sh_veu_try_fmt_vid_out(file
, priv
, f
);
628 return sh_veu_s_fmt(priv
, f
);
631 static int sh_veu_reqbufs(struct file
*file
, void *priv
,
632 struct v4l2_requestbuffers
*reqbufs
)
634 struct sh_veu_file
*veu_file
= priv
;
635 struct sh_veu_dev
*veu
= veu_file
->veu_dev
;
636 int ret
= sh_veu_context_init(veu
);
640 ret
= sh_veu_stream_init(veu
, veu_file
, reqbufs
->type
);
644 return v4l2_m2m_reqbufs(file
, veu
->m2m_ctx
, reqbufs
);
647 static int sh_veu_querybuf(struct file
*file
, void *priv
,
648 struct v4l2_buffer
*buf
)
650 struct sh_veu_file
*veu_file
= priv
;
652 if (!sh_veu_is_streamer(veu_file
->veu_dev
, veu_file
, buf
->type
))
655 return v4l2_m2m_querybuf(file
, veu_file
->veu_dev
->m2m_ctx
, buf
);
658 static int sh_veu_qbuf(struct file
*file
, void *priv
, struct v4l2_buffer
*buf
)
660 struct sh_veu_file
*veu_file
= priv
;
662 dev_dbg(veu_file
->veu_dev
->dev
, "%s(%d)\n", __func__
, buf
->type
);
663 if (!sh_veu_is_streamer(veu_file
->veu_dev
, veu_file
, buf
->type
))
666 return v4l2_m2m_qbuf(file
, veu_file
->veu_dev
->m2m_ctx
, buf
);
669 static int sh_veu_dqbuf(struct file
*file
, void *priv
, struct v4l2_buffer
*buf
)
671 struct sh_veu_file
*veu_file
= priv
;
673 dev_dbg(veu_file
->veu_dev
->dev
, "%s(%d)\n", __func__
, buf
->type
);
674 if (!sh_veu_is_streamer(veu_file
->veu_dev
, veu_file
, buf
->type
))
677 return v4l2_m2m_dqbuf(file
, veu_file
->veu_dev
->m2m_ctx
, buf
);
680 static void sh_veu_calc_scale(struct sh_veu_dev
*veu
,
681 int size_in
, int size_out
, int crop_out
,
682 u32
*mant
, u32
*frac
, u32
*rep
)
686 /* calculate FRAC and MANT */
687 *rep
= *mant
= *frac
= 0;
689 if (size_in
== size_out
) {
690 if (crop_out
!= size_out
)
691 *mant
= 1; /* needed for cropping */
695 /* VEU2H special upscale */
696 if (veu
->is_2h
&& size_out
> size_in
) {
697 u32 fixpoint
= (4096 * size_in
) / size_out
;
698 *mant
= fixpoint
/ 4096;
699 *frac
= (fixpoint
- (*mant
* 4096)) & ~0x07;
716 fixpoint
= (4096 * (size_in
- 1)) / (size_out
+ 1);
717 *mant
= fixpoint
/ 4096;
718 *frac
= fixpoint
- (*mant
* 4096);
722 * FIXME: do we really have to round down twice in the
726 if (size_out
> size_in
)
727 *frac
-= 8; /* round down if scaling up */
729 *frac
+= 8; /* round up if scaling down */
733 static unsigned long sh_veu_scale_v(struct sh_veu_dev
*veu
,
734 int size_in
, int size_out
, int crop_out
)
736 u32 mant
, frac
, value
, rep
;
738 sh_veu_calc_scale(veu
, size_in
, size_out
, crop_out
, &mant
, &frac
, &rep
);
741 value
= (sh_veu_reg_read(veu
, VEU_RFCR
) & ~0xffff0000) |
742 (((mant
<< 12) | frac
) << 16);
744 sh_veu_reg_write(veu
, VEU_RFCR
, value
);
747 value
= (sh_veu_reg_read(veu
, VEU_RFSR
) & ~0xffff0000) |
748 (((rep
<< 12) | crop_out
) << 16);
750 sh_veu_reg_write(veu
, VEU_RFSR
, value
);
752 return ALIGN((size_in
* crop_out
) / size_out
, 4);
755 static unsigned long sh_veu_scale_h(struct sh_veu_dev
*veu
,
756 int size_in
, int size_out
, int crop_out
)
758 u32 mant
, frac
, value
, rep
;
760 sh_veu_calc_scale(veu
, size_in
, size_out
, crop_out
, &mant
, &frac
, &rep
);
763 value
= (sh_veu_reg_read(veu
, VEU_RFCR
) & ~0xffff) |
766 sh_veu_reg_write(veu
, VEU_RFCR
, value
);
769 value
= (sh_veu_reg_read(veu
, VEU_RFSR
) & ~0xffff) |
770 (rep
<< 12) | crop_out
;
772 sh_veu_reg_write(veu
, VEU_RFSR
, value
);
774 return ALIGN((size_in
* crop_out
) / size_out
, 4);
777 static void sh_veu_configure(struct sh_veu_dev
*veu
)
779 u32 src_width
, src_stride
, src_height
;
780 u32 dst_width
, dst_stride
, dst_height
;
784 sh_veu_reg_write(veu
, VEU_BSRR
, 0x100);
786 src_width
= veu
->vfmt_in
.frame
.width
;
787 src_height
= veu
->vfmt_in
.frame
.height
;
788 src_stride
= ALIGN(veu
->vfmt_in
.frame
.width
, 16);
790 dst_width
= real_w
= veu
->vfmt_out
.frame
.width
;
791 dst_height
= real_h
= veu
->vfmt_out
.frame
.height
;
792 /* Datasheet is unclear - whether it's always number of bytes or not */
793 dst_stride
= veu
->vfmt_out
.bytesperline
;
796 * So far real_w == dst_width && real_h == dst_height, but it wasn't
797 * necessarily the case in the original vidix driver, so, it may change
798 * here in the future too.
800 src_width
= sh_veu_scale_h(veu
, src_width
, real_w
, dst_width
);
801 src_height
= sh_veu_scale_v(veu
, src_height
, real_h
, dst_height
);
803 sh_veu_reg_write(veu
, VEU_SWR
, src_stride
);
804 sh_veu_reg_write(veu
, VEU_SSR
, src_width
| (src_height
<< 16));
805 sh_veu_reg_write(veu
, VEU_BSSR
, 0); /* not using bundle mode */
807 sh_veu_reg_write(veu
, VEU_EDWR
, dst_stride
);
808 sh_veu_reg_write(veu
, VEU_DACR
, 0); /* unused for RGB */
810 sh_veu_reg_write(veu
, VEU_SWPR
, 0x67);
811 sh_veu_reg_write(veu
, VEU_TRCR
, (6 << 16) | (0 << 14) | 2 | 4);
814 sh_veu_reg_write(veu
, VEU_MCR00
, 0x0cc5);
815 sh_veu_reg_write(veu
, VEU_MCR01
, 0x0950);
816 sh_veu_reg_write(veu
, VEU_MCR02
, 0x0000);
818 sh_veu_reg_write(veu
, VEU_MCR10
, 0x397f);
819 sh_veu_reg_write(veu
, VEU_MCR11
, 0x0950);
820 sh_veu_reg_write(veu
, VEU_MCR12
, 0x3ccd);
822 sh_veu_reg_write(veu
, VEU_MCR20
, 0x0000);
823 sh_veu_reg_write(veu
, VEU_MCR21
, 0x0950);
824 sh_veu_reg_write(veu
, VEU_MCR22
, 0x1023);
826 sh_veu_reg_write(veu
, VEU_COFFR
, 0x00800010);
830 static int sh_veu_streamon(struct file
*file
, void *priv
,
831 enum v4l2_buf_type type
)
833 struct sh_veu_file
*veu_file
= priv
;
835 if (!sh_veu_is_streamer(veu_file
->veu_dev
, veu_file
, type
))
838 if (veu_file
->cfg_needed
) {
839 struct sh_veu_dev
*veu
= veu_file
->veu_dev
;
840 veu_file
->cfg_needed
= false;
841 sh_veu_configure(veu_file
->veu_dev
);
843 veu
->aborting
= false;
846 return v4l2_m2m_streamon(file
, veu_file
->veu_dev
->m2m_ctx
, type
);
849 static int sh_veu_streamoff(struct file
*file
, void *priv
,
850 enum v4l2_buf_type type
)
852 struct sh_veu_file
*veu_file
= priv
;
854 if (!sh_veu_is_streamer(veu_file
->veu_dev
, veu_file
, type
))
857 return v4l2_m2m_streamoff(file
, veu_file
->veu_dev
->m2m_ctx
, type
);
860 static const struct v4l2_ioctl_ops sh_veu_ioctl_ops
= {
861 .vidioc_querycap
= sh_veu_querycap
,
863 .vidioc_enum_fmt_vid_cap
= sh_veu_enum_fmt_vid_cap
,
864 .vidioc_g_fmt_vid_cap
= sh_veu_g_fmt_vid_cap
,
865 .vidioc_try_fmt_vid_cap
= sh_veu_try_fmt_vid_cap
,
866 .vidioc_s_fmt_vid_cap
= sh_veu_s_fmt_vid_cap
,
868 .vidioc_enum_fmt_vid_out
= sh_veu_enum_fmt_vid_out
,
869 .vidioc_g_fmt_vid_out
= sh_veu_g_fmt_vid_out
,
870 .vidioc_try_fmt_vid_out
= sh_veu_try_fmt_vid_out
,
871 .vidioc_s_fmt_vid_out
= sh_veu_s_fmt_vid_out
,
873 .vidioc_reqbufs
= sh_veu_reqbufs
,
874 .vidioc_querybuf
= sh_veu_querybuf
,
876 .vidioc_qbuf
= sh_veu_qbuf
,
877 .vidioc_dqbuf
= sh_veu_dqbuf
,
879 .vidioc_streamon
= sh_veu_streamon
,
880 .vidioc_streamoff
= sh_veu_streamoff
,
883 /* ========== Queue operations ========== */
885 static int sh_veu_queue_setup(struct vb2_queue
*vq
,
886 const struct v4l2_format
*f
,
887 unsigned int *nbuffers
, unsigned int *nplanes
,
888 unsigned int sizes
[], void *alloc_ctxs
[])
890 struct sh_veu_dev
*veu
= vb2_get_drv_priv(vq
);
891 struct sh_veu_vfmt
*vfmt
;
892 unsigned int size
, count
= *nbuffers
;
895 const struct v4l2_pix_format
*pix
= &f
->fmt
.pix
;
896 const struct sh_veu_format
*fmt
= sh_veu_find_fmt(f
);
897 struct v4l2_format ftmp
= *f
;
899 if (fmt
->fourcc
!= pix
->pixelformat
)
901 sh_veu_try_fmt(&ftmp
, fmt
);
902 if (ftmp
.fmt
.pix
.width
!= pix
->width
||
903 ftmp
.fmt
.pix
.height
!= pix
->height
)
905 size
= pix
->bytesperline
? pix
->bytesperline
* pix
->height
* fmt
->depth
/ fmt
->ydepth
:
906 pix
->width
* pix
->height
* fmt
->depth
/ fmt
->ydepth
;
908 vfmt
= sh_veu_get_vfmt(veu
, vq
->type
);
909 size
= vfmt
->bytesperline
* vfmt
->frame
.height
* vfmt
->fmt
->depth
/ vfmt
->fmt
->ydepth
;
913 *nbuffers
= count
= 2;
915 if (size
* count
> VIDEO_MEM_LIMIT
) {
916 count
= VIDEO_MEM_LIMIT
/ size
;
922 alloc_ctxs
[0] = veu
->alloc_ctx
;
924 dev_dbg(veu
->dev
, "get %d buffer(s) of size %d each.\n", count
, size
);
929 static int sh_veu_buf_prepare(struct vb2_buffer
*vb
)
931 struct sh_veu_dev
*veu
= vb2_get_drv_priv(vb
->vb2_queue
);
932 struct sh_veu_vfmt
*vfmt
;
933 unsigned int sizeimage
;
935 vfmt
= sh_veu_get_vfmt(veu
, vb
->vb2_queue
->type
);
936 sizeimage
= vfmt
->bytesperline
* vfmt
->frame
.height
*
937 vfmt
->fmt
->depth
/ vfmt
->fmt
->ydepth
;
939 if (vb2_plane_size(vb
, 0) < sizeimage
) {
940 dev_dbg(veu
->dev
, "%s data will not fit into plane (%lu < %u)\n",
941 __func__
, vb2_plane_size(vb
, 0), sizeimage
);
945 vb2_set_plane_payload(vb
, 0, sizeimage
);
950 static void sh_veu_buf_queue(struct vb2_buffer
*vb
)
952 struct sh_veu_dev
*veu
= vb2_get_drv_priv(vb
->vb2_queue
);
953 dev_dbg(veu
->dev
, "%s(%d)\n", __func__
, vb
->v4l2_buf
.type
);
954 v4l2_m2m_buf_queue(veu
->m2m_ctx
, vb
);
957 static void sh_veu_wait_prepare(struct vb2_queue
*q
)
959 sh_veu_unlock(vb2_get_drv_priv(q
));
962 static void sh_veu_wait_finish(struct vb2_queue
*q
)
964 sh_veu_lock(vb2_get_drv_priv(q
));
967 static const struct vb2_ops sh_veu_qops
= {
968 .queue_setup
= sh_veu_queue_setup
,
969 .buf_prepare
= sh_veu_buf_prepare
,
970 .buf_queue
= sh_veu_buf_queue
,
971 .wait_prepare
= sh_veu_wait_prepare
,
972 .wait_finish
= sh_veu_wait_finish
,
975 static int sh_veu_queue_init(void *priv
, struct vb2_queue
*src_vq
,
976 struct vb2_queue
*dst_vq
)
980 memset(src_vq
, 0, sizeof(*src_vq
));
981 src_vq
->type
= V4L2_BUF_TYPE_VIDEO_OUTPUT
;
982 src_vq
->io_modes
= VB2_MMAP
| VB2_USERPTR
;
983 src_vq
->drv_priv
= priv
;
984 src_vq
->buf_struct_size
= sizeof(struct v4l2_m2m_buffer
);
985 src_vq
->ops
= &sh_veu_qops
;
986 src_vq
->mem_ops
= &vb2_dma_contig_memops
;
988 ret
= vb2_queue_init(src_vq
);
992 memset(dst_vq
, 0, sizeof(*dst_vq
));
993 dst_vq
->type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
994 dst_vq
->io_modes
= VB2_MMAP
| VB2_USERPTR
;
995 dst_vq
->drv_priv
= priv
;
996 dst_vq
->buf_struct_size
= sizeof(struct v4l2_m2m_buffer
);
997 dst_vq
->ops
= &sh_veu_qops
;
998 dst_vq
->mem_ops
= &vb2_dma_contig_memops
;
1000 return vb2_queue_init(dst_vq
);
1003 /* ========== File operations ========== */
1005 static int sh_veu_open(struct file
*file
)
1007 struct sh_veu_dev
*veu
= video_drvdata(file
);
1008 struct sh_veu_file
*veu_file
;
1010 veu_file
= kzalloc(sizeof(*veu_file
), GFP_KERNEL
);
1014 veu_file
->veu_dev
= veu
;
1015 veu_file
->cfg_needed
= true;
1017 file
->private_data
= veu_file
;
1019 pm_runtime_get_sync(veu
->dev
);
1021 dev_dbg(veu
->dev
, "Created instance %p\n", veu_file
);
1026 static int sh_veu_release(struct file
*file
)
1028 struct sh_veu_dev
*veu
= video_drvdata(file
);
1029 struct sh_veu_file
*veu_file
= file
->private_data
;
1031 dev_dbg(veu
->dev
, "Releasing instance %p\n", veu_file
);
1033 if (veu_file
== veu
->capture
) {
1034 veu
->capture
= NULL
;
1035 vb2_queue_release(v4l2_m2m_get_vq(veu
->m2m_ctx
, V4L2_BUF_TYPE_VIDEO_CAPTURE
));
1038 if (veu_file
== veu
->output
) {
1040 vb2_queue_release(v4l2_m2m_get_vq(veu
->m2m_ctx
, V4L2_BUF_TYPE_VIDEO_OUTPUT
));
1043 if (!veu
->output
&& !veu
->capture
&& veu
->m2m_ctx
) {
1044 v4l2_m2m_ctx_release(veu
->m2m_ctx
);
1045 veu
->m2m_ctx
= NULL
;
1048 pm_runtime_put(veu
->dev
);
1055 static unsigned int sh_veu_poll(struct file
*file
,
1056 struct poll_table_struct
*wait
)
1058 struct sh_veu_file
*veu_file
= file
->private_data
;
1060 return v4l2_m2m_poll(file
, veu_file
->veu_dev
->m2m_ctx
, wait
);
1063 static int sh_veu_mmap(struct file
*file
, struct vm_area_struct
*vma
)
1065 struct sh_veu_file
*veu_file
= file
->private_data
;
1067 return v4l2_m2m_mmap(file
, veu_file
->veu_dev
->m2m_ctx
, vma
);
1070 static const struct v4l2_file_operations sh_veu_fops
= {
1071 .owner
= THIS_MODULE
,
1072 .open
= sh_veu_open
,
1073 .release
= sh_veu_release
,
1074 .poll
= sh_veu_poll
,
1075 .unlocked_ioctl
= video_ioctl2
,
1076 .mmap
= sh_veu_mmap
,
1079 static const struct video_device sh_veu_videodev
= {
1081 .fops
= &sh_veu_fops
,
1082 .ioctl_ops
= &sh_veu_ioctl_ops
,
1084 .release
= video_device_release_empty
,
1085 .vfl_dir
= VFL_DIR_M2M
,
1088 static const struct v4l2_m2m_ops sh_veu_m2m_ops
= {
1089 .device_run
= sh_veu_device_run
,
1090 .job_abort
= sh_veu_job_abort
,
1093 static irqreturn_t
sh_veu_bh(int irq
, void *dev_id
)
1095 struct sh_veu_dev
*veu
= dev_id
;
1097 if (veu
->xaction
== MEM2MEM_DEF_TRANSLEN
|| veu
->aborting
) {
1098 v4l2_m2m_job_finish(veu
->m2m_dev
, veu
->m2m_ctx
);
1101 sh_veu_device_run(veu
);
1107 static irqreturn_t
sh_veu_isr(int irq
, void *dev_id
)
1109 struct sh_veu_dev
*veu
= dev_id
;
1110 struct vb2_buffer
*dst
;
1111 struct vb2_buffer
*src
;
1112 u32 status
= sh_veu_reg_read(veu
, VEU_EVTR
);
1114 /* bundle read mode not used */
1118 /* disable interrupt in VEU */
1119 sh_veu_reg_write(veu
, VEU_EIER
, 0);
1120 /* halt operation */
1121 sh_veu_reg_write(veu
, VEU_STR
, 0);
1122 /* ack int, write 0 to clear bits */
1123 sh_veu_reg_write(veu
, VEU_EVTR
, status
& ~1);
1125 /* conversion completed */
1126 dst
= v4l2_m2m_dst_buf_remove(veu
->m2m_ctx
);
1127 src
= v4l2_m2m_src_buf_remove(veu
->m2m_ctx
);
1131 spin_lock(&veu
->lock
);
1132 v4l2_m2m_buf_done(src
, VB2_BUF_STATE_DONE
);
1133 v4l2_m2m_buf_done(dst
, VB2_BUF_STATE_DONE
);
1134 spin_unlock(&veu
->lock
);
1138 return IRQ_WAKE_THREAD
;
1141 static int sh_veu_probe(struct platform_device
*pdev
)
1143 struct sh_veu_dev
*veu
;
1144 struct resource
*reg_res
;
1145 struct video_device
*vdev
;
1148 reg_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
1149 irq
= platform_get_irq(pdev
, 0);
1151 if (!reg_res
|| irq
<= 0) {
1152 dev_err(&pdev
->dev
, "Insufficient VEU platform information.\n");
1156 veu
= devm_kzalloc(&pdev
->dev
, sizeof(*veu
), GFP_KERNEL
);
1160 veu
->is_2h
= resource_size(reg_res
) == 0x22c;
1162 veu
->base
= devm_ioremap_resource(&pdev
->dev
, reg_res
);
1163 if (IS_ERR(veu
->base
))
1164 return PTR_ERR(veu
->base
);
1166 ret
= devm_request_threaded_irq(&pdev
->dev
, irq
, sh_veu_isr
, sh_veu_bh
,
1171 ret
= v4l2_device_register(&pdev
->dev
, &veu
->v4l2_dev
);
1173 dev_err(&pdev
->dev
, "Error registering v4l2 device\n");
1179 veu
->alloc_ctx
= vb2_dma_contig_init_ctx(&pdev
->dev
);
1180 if (IS_ERR(veu
->alloc_ctx
)) {
1181 ret
= PTR_ERR(veu
->alloc_ctx
);
1185 *vdev
= sh_veu_videodev
;
1186 spin_lock_init(&veu
->lock
);
1187 mutex_init(&veu
->fop_lock
);
1188 vdev
->lock
= &veu
->fop_lock
;
1190 video_set_drvdata(vdev
, veu
);
1192 veu
->dev
= &pdev
->dev
;
1193 veu
->vfmt_out
= DEFAULT_OUT_VFMT
;
1194 veu
->vfmt_in
= DEFAULT_IN_VFMT
;
1196 veu
->m2m_dev
= v4l2_m2m_init(&sh_veu_m2m_ops
);
1197 if (IS_ERR(veu
->m2m_dev
)) {
1198 ret
= PTR_ERR(veu
->m2m_dev
);
1199 v4l2_err(&veu
->v4l2_dev
, "Failed to init mem2mem device: %d\n", ret
);
1203 pm_runtime_enable(&pdev
->dev
);
1204 pm_runtime_resume(&pdev
->dev
);
1206 ret
= video_register_device(vdev
, VFL_TYPE_GRABBER
, -1);
1207 pm_runtime_suspend(&pdev
->dev
);
1214 pm_runtime_disable(&pdev
->dev
);
1215 v4l2_m2m_release(veu
->m2m_dev
);
1217 vb2_dma_contig_cleanup_ctx(veu
->alloc_ctx
);
1219 v4l2_device_unregister(&veu
->v4l2_dev
);
1223 static int sh_veu_remove(struct platform_device
*pdev
)
1225 struct v4l2_device
*v4l2_dev
= platform_get_drvdata(pdev
);
1226 struct sh_veu_dev
*veu
= container_of(v4l2_dev
,
1227 struct sh_veu_dev
, v4l2_dev
);
1229 video_unregister_device(&veu
->vdev
);
1230 pm_runtime_disable(&pdev
->dev
);
1231 v4l2_m2m_release(veu
->m2m_dev
);
1232 vb2_dma_contig_cleanup_ctx(veu
->alloc_ctx
);
1233 v4l2_device_unregister(&veu
->v4l2_dev
);
1238 static struct platform_driver __refdata sh_veu_pdrv
= {
1239 .remove
= sh_veu_remove
,
1242 .owner
= THIS_MODULE
,
1246 module_platform_driver_probe(sh_veu_pdrv
, sh_veu_probe
);
1248 MODULE_DESCRIPTION("sh-mobile VEU mem2mem driver");
1249 MODULE_AUTHOR("Guennadi Liakhovetski, <g.liakhovetski@gmx.de>");
1250 MODULE_LICENSE("GPL v2");