13 #include <linux/module.h>
14 #include <linux/slab.h>
24 #define MEM2MEM_TEST_MODULE_NAME "mem2mem-deinterlace"
31 static bool debug =
true;
35 #define MEM2MEM_CAPTURE (1 << 0)
36 #define MEM2MEM_OUTPUT (1 << 1)
38 #define MEM2MEM_NAME "m2m-deinterlace"
40 #define dprintk(dev, fmt, arg...) \
41 v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
52 .name =
"YUV 4:2:0 Planar",
63 #define NUM_FORMATS ARRAY_SIZE(formats)
122 if (k == NUM_FORMATS)
156 static int deinterlace_job_ready(
void *
priv)
161 if ((v4l2_m2m_num_src_bufs_ready(ctx->
m2m_ctx) > 0)
162 && (v4l2_m2m_num_dst_bufs_ready(ctx->
m2m_ctx) > 0)
164 dprintk(pcdev,
"Task ready\n");
168 dprintk(pcdev,
"Task not ready to run\n");
173 static void deinterlace_job_abort(
void *
priv)
180 dprintk(pcdev,
"Aborting task\n");
185 static void deinterlace_lock(
void *
priv)
192 static void deinterlace_unlock(
void *
priv)
199 static void dma_callback(
void *
data)
207 src_vb = v4l2_m2m_src_buf_remove(curr_ctx->
m2m_ctx);
208 dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->
m2m_ctx);
215 dprintk(pcdev,
"dma transfers completed.\n");
227 unsigned int s_width, s_height;
228 unsigned int d_width, d_height;
229 unsigned int d_size,
s_size;
233 src_buf = v4l2_m2m_next_src_buf(ctx->
m2m_ctx);
234 dst_buf = v4l2_m2m_next_dst_buf(ctx->
m2m_ctx);
237 s_width = s_q_data->
width;
238 s_height = s_q_data->
height;
239 s_size = s_width * s_height;
242 d_width = d_q_data->
width;
243 d_height = d_q_data->
height;
244 d_size = d_width * d_height;
246 p_in = (
dma_addr_t)vb2_dma_contig_plane_dma_addr(src_buf, 0);
247 p_out = (
dma_addr_t)vb2_dma_contig_plane_dma_addr(dst_buf, 0);
248 if (!p_in || !p_out) {
250 "Acquiring kernel pointers to buffers failed\n");
256 ctx->
xt->numf = s_height / 2;
257 ctx->
xt->sgl[0].size = s_width;
258 ctx->
xt->sgl[0].icg = s_width;
259 ctx->
xt->src_start = p_in;
260 ctx->
xt->dst_start = p_out;
263 ctx->
xt->numf = s_height / 2;
264 ctx->
xt->sgl[0].size = s_width;
265 ctx->
xt->sgl[0].icg = s_width;
266 ctx->
xt->src_start = p_in + s_size / 2;
267 ctx->
xt->dst_start = p_out + s_width;
270 ctx->
xt->numf = s_height / 4;
271 ctx->
xt->sgl[0].size = s_width / 2;
272 ctx->
xt->sgl[0].icg = s_width / 2;
274 ctx->
xt->dst_start = p_out +
s_size;
277 ctx->
xt->numf = s_height / 4;
278 ctx->
xt->sgl[0].size = s_width / 2;
279 ctx->
xt->sgl[0].icg = s_width / 2;
280 ctx->
xt->src_start = p_in + (9 *
s_size) / 8;
281 ctx->
xt->dst_start = p_out + s_size + s_width / 2;
284 ctx->
xt->numf = s_height / 4;
285 ctx->
xt->sgl[0].size = s_width / 2;
286 ctx->
xt->sgl[0].icg = s_width / 2;
287 ctx->
xt->src_start = p_in + (5 *
s_size) / 4;
288 ctx->
xt->dst_start = p_out + (5 *
s_size) / 4;
291 ctx->
xt->numf = s_height / 4;
292 ctx->
xt->sgl[0].size = s_width / 2;
293 ctx->
xt->sgl[0].icg = s_width / 2;
294 ctx->
xt->src_start = p_in + (11 *
s_size) / 8;
295 ctx->
xt->dst_start = p_out + (5 *
s_size) / 4 + s_width / 2;
298 ctx->
xt->numf = s_height / 2;
299 ctx->
xt->sgl[0].size = s_width;
300 ctx->
xt->sgl[0].icg = s_width;
301 ctx->
xt->src_start = p_in;
302 ctx->
xt->dst_start = p_out + s_width;
305 ctx->
xt->numf = s_height / 4;
306 ctx->
xt->sgl[0].size = s_width / 2;
307 ctx->
xt->sgl[0].icg = s_width / 2;
309 ctx->
xt->dst_start = p_out + s_size + s_width / 2;
312 ctx->
xt->numf = s_height / 4;
313 ctx->
xt->sgl[0].size = s_width / 2;
314 ctx->
xt->sgl[0].icg = s_width / 2;
315 ctx->
xt->src_start = p_in + (5 *
s_size) / 4;
316 ctx->
xt->dst_start = p_out + (5 *
s_size) / 4 + s_width / 2;
319 ctx->
xt->numf = s_height / 2;
320 ctx->
xt->sgl[0].size = s_width * 2;
321 ctx->
xt->sgl[0].icg = s_width * 2;
322 ctx->
xt->src_start = p_in;
323 ctx->
xt->dst_start = p_out;
326 ctx->
xt->numf = s_height / 2;
327 ctx->
xt->sgl[0].size = s_width * 2;
328 ctx->
xt->sgl[0].icg = s_width * 2;
330 ctx->
xt->dst_start = p_out + s_width * 2;
334 ctx->
xt->numf = s_height / 2;
335 ctx->
xt->sgl[0].size = s_width * 2;
336 ctx->
xt->sgl[0].icg = s_width * 2;
337 ctx->
xt->src_start = p_in;
338 ctx->
xt->dst_start = p_out + s_width * 2;
343 ctx->
xt->frame_size = 1;
345 ctx->
xt->src_sgl =
false;
346 ctx->
xt->dst_sgl =
true;
361 ctx->
cookie = dmaengine_submit(tx);
364 "DMA submit error %d with src=0x%x dst=0x%x len=0x%x\n",
365 ctx->
cookie, (
unsigned)p_in, (
unsigned)p_out,
370 dma_async_issue_pending(chan);
373 static void deinterlace_device_run(
void *
priv)
380 dprintk(ctx->
dev,
"%s: DMA try issue.\n", __func__);
399 switch (dst_q_data->
fmt->fourcc) {
401 switch (dst_q_data->
field) {
404 dprintk(ctx->
dev,
"%s: yuv420 interlaced tb.\n",
415 dprintk(ctx->
dev,
"%s: yuv420 interlaced line doubling.\n",
428 switch (dst_q_data->
field) {
431 dprintk(ctx->
dev,
"%s: yuyv interlaced_tb.\n",
438 dprintk(ctx->
dev,
"%s: yuyv interlaced line doubling.\n",
447 dprintk(ctx->
dev,
"%s: DMA issue done.\n", __func__);
453 static int vidioc_querycap(
struct file *
file,
void *priv,
479 if (formats[i].
types & type) {
489 if (i < NUM_FORMATS) {
501 static int vidioc_enum_fmt_vid_cap(
struct file *
file,
void *priv,
507 static int vidioc_enum_fmt_vid_out(
struct file *
file,
void *priv,
522 q_data = get_q_data(f->
type);
527 f->
fmt.
pix.pixelformat = q_data->
fmt->fourcc;
529 switch (q_data->
fmt->fourcc) {
544 static int vidioc_g_fmt_vid_out(
struct file *
file,
void *priv,
547 return vidioc_g_fmt(priv, f);
550 static int vidioc_g_fmt_vid_cap(
struct file *
file,
void *priv,
553 return vidioc_g_fmt(priv, f);
558 switch (f->
fmt.
pix.pixelformat) {
571 static int vidioc_try_fmt_vid_cap(
struct file *
file,
void *priv,
577 fmt = find_format(f);
588 return vidioc_try_fmt(f, fmt);
591 static int vidioc_try_fmt_vid_out(
struct file *file,
void *priv,
596 fmt = find_format(f);
600 if (!f->
fmt.
pix.colorspace)
607 return vidioc_try_fmt(f, fmt);
619 q_data = get_q_data(f->
type);
623 if (vb2_is_busy(vq)) {
624 v4l2_err(&ctx->
dev->v4l2_dev,
"%s queue busy\n", __func__);
628 q_data->
fmt = find_format(f);
631 "Couldn't set format type %d, wxh: %dx%d. fmt: %d, field: %d\n",
641 switch (f->
fmt.
pix.pixelformat) {
653 "Setting format for type %d, wxh: %dx%d, fmt: %d, field: %d\n",
660 static int vidioc_s_fmt_vid_cap(
struct file *file,
void *priv,
665 ret = vidioc_try_fmt_vid_cap(file, priv, f);
668 return vidioc_s_fmt(priv, f);
671 static int vidioc_s_fmt_vid_out(
struct file *file,
void *priv,
677 ret = vidioc_try_fmt_vid_out(file, priv, f);
681 ret = vidioc_s_fmt(priv, f);
688 static int vidioc_reqbufs(
struct file *file,
void *priv,
696 static int vidioc_querybuf(
struct file *file,
void *priv,
704 static int vidioc_qbuf(
struct file *file,
void *priv,
struct v4l2_buffer *
buf)
711 static int vidioc_dqbuf(
struct file *file,
void *priv,
struct v4l2_buffer *
buf)
718 static int vidioc_streamon(
struct file *file,
void *priv,
728 if (s_q_data->
fmt->fourcc != d_q_data->
fmt->fourcc) {
730 "src and dst formats don't match.\n");
735 switch (s_q_data->
field) {
740 "src and dst field conversion [(%d)->(%d)] not supported.\n",
749 "src and dst field conversion [(%d)->(%d)] not supported.\n",
761 static int vidioc_streamoff(
struct file *file,
void *priv,
800 static int deinterlace_queue_setup(
struct vb2_queue *vq,
802 unsigned int *nbuffers,
unsigned int *nplanes,
803 unsigned int sizes[],
void *alloc_ctxs[])
809 q_data = get_q_data(vq->
type);
811 switch (q_data->
fmt->fourcc) {
824 alloc_ctxs[0] = ctx->
dev->alloc_ctx;
826 dprintk(ctx->
dev,
"get %d buffer(s) of size %d each.\n", count, size);
831 static int deinterlace_buf_prepare(
struct vb2_buffer *vb)
838 q_data = get_q_data(vb->
vb2_queue->type);
840 if (vb2_plane_size(vb, 0) < q_data->
sizeimage) {
841 dprintk(ctx->
dev,
"%s data will not fit into plane (%lu < %lu)\n",
842 __func__, vb2_plane_size(vb, 0), (
long)q_data->
sizeimage);
846 vb2_set_plane_payload(vb, 0, q_data->
sizeimage);
851 static void deinterlace_buf_queue(
struct vb2_buffer *vb)
857 static struct vb2_ops deinterlace_qops = {
858 .queue_setup = deinterlace_queue_setup,
859 .buf_prepare = deinterlace_buf_prepare,
860 .buf_queue = deinterlace_buf_queue,
863 static int queue_init(
void *priv,
struct vb2_queue *src_vq,
873 src_vq->
ops = &deinterlace_qops;
889 dst_vq->
ops = &deinterlace_qops;
903 static int deinterlace_open(
struct file *file)
917 int ret = PTR_ERR(ctx->
m2m_ctx);
926 int ret = PTR_ERR(ctx->
xt);
934 dprintk(pcdev,
"Created instance %p, m2m_ctx: %p\n", ctx, ctx->
m2m_ctx);
939 static int deinterlace_release(
struct file *file)
944 dprintk(pcdev,
"Releasing instance %p\n", ctx);
953 static unsigned int deinterlace_poll(
struct file *file,
959 deinterlace_lock(ctx);
961 deinterlace_unlock(ctx);
966 static int deinterlace_mmap(
struct file *file,
struct vm_area_struct *vma)
975 .open = deinterlace_open,
976 .release = deinterlace_release,
977 .poll = deinterlace_poll,
979 .mmap = deinterlace_mmap,
984 .fops = &deinterlace_fops,
985 .ioctl_ops = &deinterlace_ioctl_ops,
992 .device_run = deinterlace_device_run,
993 .job_ready = deinterlace_job_ready,
994 .job_abort = deinterlace_job_abort,
995 .lock = deinterlace_lock,
996 .unlock = deinterlace_unlock,
1037 *vfd = deinterlace_videodev;
1046 video_set_drvdata(vfd, pcdev);
1050 " Device registered as /dev/video%d\n", vfd->
num);
1052 platform_set_drvdata(pdev, pcdev);
1064 ret = PTR_ERR(pcdev->
m2m_dev);
1104 .probe = deinterlace_probe,
1105 .remove = deinterlace_remove,
1112 static void __exit deinterlace_exit(
void)
1117 static int __init deinterlace_init(
void)