19 #include <linux/module.h>
21 #include <linux/slab.h>
30 #include <asm/sizes.h>
32 #define EMMAPRP_MODULE_NAME "mem2mem-emmaprp"
48 #define W_ALIGN_YUV420 3
49 #define W_ALIGN_OTHERS 2
53 #define MEM2MEM_CAPTURE (1 << 0)
54 #define MEM2MEM_OUTPUT (1 << 1)
56 #define MEM2MEM_NAME "m2m-emmaprp"
59 #define MEM2MEM_VID_MEM_LIMIT SZ_16M
61 #define dprintk(dev, fmt, arg...) \
62 v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
66 #define PRP_INTR_CNTL 0x04
67 #define PRP_INTRSTATUS 0x08
68 #define PRP_SOURCE_Y_PTR 0x0c
69 #define PRP_SOURCE_CB_PTR 0x10
70 #define PRP_SOURCE_CR_PTR 0x14
71 #define PRP_DEST_RGB1_PTR 0x18
72 #define PRP_DEST_RGB2_PTR 0x1c
73 #define PRP_DEST_Y_PTR 0x20
74 #define PRP_DEST_CB_PTR 0x24
75 #define PRP_DEST_CR_PTR 0x28
76 #define PRP_SRC_FRAME_SIZE 0x2c
77 #define PRP_DEST_CH1_LINE_STRIDE 0x30
78 #define PRP_SRC_PIXEL_FORMAT_CNTL 0x34
79 #define PRP_CH1_PIXEL_FORMAT_CNTL 0x38
80 #define PRP_CH1_OUT_IMAGE_SIZE 0x3c
81 #define PRP_CH2_OUT_IMAGE_SIZE 0x40
82 #define PRP_SRC_LINE_STRIDE 0x44
83 #define PRP_CSC_COEF_012 0x48
84 #define PRP_CSC_COEF_345 0x4c
85 #define PRP_CSC_COEF_678 0x50
86 #define PRP_CH1_RZ_HORI_COEF1 0x54
87 #define PRP_CH1_RZ_HORI_COEF2 0x58
88 #define PRP_CH1_RZ_HORI_VALID 0x5c
89 #define PRP_CH1_RZ_VERT_COEF1 0x60
90 #define PRP_CH1_RZ_VERT_COEF2 0x64
91 #define PRP_CH1_RZ_VERT_VALID 0x68
92 #define PRP_CH2_RZ_HORI_COEF1 0x6c
93 #define PRP_CH2_RZ_HORI_COEF2 0x70
94 #define PRP_CH2_RZ_HORI_VALID 0x74
95 #define PRP_CH2_RZ_VERT_COEF1 0x78
96 #define PRP_CH2_RZ_VERT_COEF2 0x7c
97 #define PRP_CH2_RZ_VERT_VALID 0x80
99 #define PRP_CNTL_CH1EN (1 << 0)
100 #define PRP_CNTL_CH2EN (1 << 1)
101 #define PRP_CNTL_CSIEN (1 << 2)
102 #define PRP_CNTL_DATA_IN_YUV420 (0 << 3)
103 #define PRP_CNTL_DATA_IN_YUV422 (1 << 3)
104 #define PRP_CNTL_DATA_IN_RGB16 (2 << 3)
105 #define PRP_CNTL_DATA_IN_RGB32 (3 << 3)
106 #define PRP_CNTL_CH1_OUT_RGB8 (0 << 5)
107 #define PRP_CNTL_CH1_OUT_RGB16 (1 << 5)
108 #define PRP_CNTL_CH1_OUT_RGB32 (2 << 5)
109 #define PRP_CNTL_CH1_OUT_YUV422 (3 << 5)
110 #define PRP_CNTL_CH2_OUT_YUV420 (0 << 7)
111 #define PRP_CNTL_CH2_OUT_YUV422 (1 << 7)
112 #define PRP_CNTL_CH2_OUT_YUV444 (2 << 7)
113 #define PRP_CNTL_CH1_LEN (1 << 9)
114 #define PRP_CNTL_CH2_LEN (1 << 10)
115 #define PRP_CNTL_SKIP_FRAME (1 << 11)
116 #define PRP_CNTL_SWRST (1 << 12)
117 #define PRP_CNTL_CLKEN (1 << 13)
118 #define PRP_CNTL_WEN (1 << 14)
119 #define PRP_CNTL_CH1BYP (1 << 15)
120 #define PRP_CNTL_IN_TSKIP(x) ((x) << 16)
121 #define PRP_CNTL_CH1_TSKIP(x) ((x) << 19)
122 #define PRP_CNTL_CH2_TSKIP(x) ((x) << 22)
123 #define PRP_CNTL_INPUT_FIFO_LEVEL(x) ((x) << 25)
124 #define PRP_CNTL_RZ_FIFO_LEVEL(x) ((x) << 27)
125 #define PRP_CNTL_CH2B1EN (1 << 29)
126 #define PRP_CNTL_CH2B2EN (1 << 30)
127 #define PRP_CNTL_CH2FEN (1 << 31)
129 #define PRP_SIZE_HEIGHT(x) (x)
130 #define PRP_SIZE_WIDTH(x) ((x) << 16)
133 #define PRP_INTR_RDERR (1 << 0)
134 #define PRP_INTR_CH1WERR (1 << 1)
135 #define PRP_INTR_CH2WERR (1 << 2)
136 #define PRP_INTR_CH1FC (1 << 3)
137 #define PRP_INTR_CH2FC (1 << 5)
138 #define PRP_INTR_LBOVF (1 << 7)
139 #define PRP_INTR_CH2OVF (1 << 8)
141 #define PRP_INTR_ST_RDERR (1 << 0)
142 #define PRP_INTR_ST_CH1WERR (1 << 1)
143 #define PRP_INTR_ST_CH2WERR (1 << 2)
144 #define PRP_INTR_ST_CH2B2CI (1 << 3)
145 #define PRP_INTR_ST_CH2B1CI (1 << 4)
146 #define PRP_INTR_ST_CH1B2CI (1 << 5)
147 #define PRP_INTR_ST_CH1B1CI (1 << 6)
148 #define PRP_INTR_ST_LBOVF (1 << 7)
149 #define PRP_INTR_ST_CH2OVF (1 << 8)
160 .name =
"YUV 4:2:0 Planar",
165 .name =
"4:2:2, packed, YUYV",
184 #define NUM_FORMATS ARRAY_SIZE(formats)
197 if (k == NUM_FORMATS)
244 static void emmaprp_job_abort(
void *
priv)
251 dprintk(pcdev,
"Aborting task\n");
256 static void emmaprp_lock(
void *
priv)
263 static void emmaprp_unlock(
void *
priv)
270 static inline void emmaprp_dump_regs(
struct emmaprp_dev *pcdev)
273 "eMMa-PrP Registers:\n"
274 " SOURCE_Y_PTR = 0x%08X\n"
275 " SRC_FRAME_SIZE = 0x%08X\n"
276 " DEST_Y_PTR = 0x%08X\n"
277 " DEST_CR_PTR = 0x%08X\n"
278 " DEST_CB_PTR = 0x%08X\n"
279 " CH2_OUT_IMAGE_SIZE = 0x%08X\n"
290 static void emmaprp_device_run(
void *
priv)
296 unsigned int s_width, s_height;
297 unsigned int d_width, d_height;
302 src_buf = v4l2_m2m_next_src_buf(ctx->
m2m_ctx);
303 dst_buf = v4l2_m2m_next_dst_buf(ctx->
m2m_ctx);
306 s_width = s_q_data->
width;
307 s_height = s_q_data->
height;
310 d_width = d_q_data->
width;
311 d_height = d_q_data->
height;
312 d_size = d_width * d_height;
314 p_in = vb2_dma_contig_plane_dma_addr(src_buf, 0);
315 p_out = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
316 if (!p_in || !p_out) {
318 "Acquiring kernel pointers to buffers failed\n");
330 writel(p_out + d_size + (d_size >> 2),
342 emmaprp_dump_regs(pcdev);
363 dprintk(pcdev,
"irqst = 0x%08x\n", irqst);
366 if (curr_ctx ==
NULL) {
367 pr_err(
"Instance released before the end of transaction\n");
374 pr_err(
"PrP bus error ocurred, this transfer is probably corrupted\n");
377 src_vb = v4l2_m2m_src_buf_remove(curr_ctx->
m2m_ctx);
378 dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->
m2m_ctx);
383 spin_unlock_irqrestore(&pcdev->
irqlock, flags);
394 static int vidioc_querycap(
struct file *
file,
void *priv,
417 if (formats[i].
types & type) {
427 if (i < NUM_FORMATS) {
439 static int vidioc_enum_fmt_vid_cap(
struct file *
file,
void *priv,
445 static int vidioc_enum_fmt_vid_out(
struct file *
file,
void *priv,
460 q_data = get_q_data(ctx, f->
type);
465 f->
fmt.
pix.pixelformat = q_data->
fmt->fourcc;
475 static int vidioc_g_fmt_vid_out(
struct file *
file,
void *priv,
478 return vidioc_g_fmt(priv, f);
481 static int vidioc_g_fmt_vid_cap(
struct file *
file,
void *priv,
484 return vidioc_g_fmt(priv, f);
521 static int vidioc_try_fmt_vid_cap(
struct file *
file,
void *priv,
527 fmt = find_format(f);
530 "Fourcc format (0x%08x) invalid.\n",
535 return vidioc_try_fmt(f);
538 static int vidioc_try_fmt_vid_out(
struct file *file,
void *priv,
544 fmt = find_format(f);
547 "Fourcc format (0x%08x) invalid.\n",
552 return vidioc_try_fmt(f);
565 q_data = get_q_data(ctx, f->
type);
569 if (vb2_is_busy(vq)) {
570 v4l2_err(&ctx->
dev->v4l2_dev,
"%s queue busy\n", __func__);
574 ret = vidioc_try_fmt(f);
578 q_data->
fmt = find_format(f);
587 "Setting format for type %d, wxh: %dx%d, fmt: %d\n",
593 static int vidioc_s_fmt_vid_cap(
struct file *file,
void *priv,
598 ret = vidioc_try_fmt_vid_cap(file, priv, f);
602 return vidioc_s_fmt(priv, f);
605 static int vidioc_s_fmt_vid_out(
struct file *file,
void *priv,
610 ret = vidioc_try_fmt_vid_out(file, priv, f);
614 return vidioc_s_fmt(priv, f);
617 static int vidioc_reqbufs(
struct file *file,
void *priv,
625 static int vidioc_querybuf(
struct file *file,
void *priv,
633 static int vidioc_qbuf(
struct file *file,
void *priv,
struct v4l2_buffer *
buf)
640 static int vidioc_dqbuf(
struct file *file,
void *priv,
struct v4l2_buffer *
buf)
647 static int vidioc_streamon(
struct file *file,
void *priv,
655 static int vidioc_streamoff(
struct file *file,
void *priv,
690 static int emmaprp_queue_setup(
struct vb2_queue *vq,
692 unsigned int *nbuffers,
unsigned int *nplanes,
693 unsigned int sizes[],
void *alloc_ctxs[])
699 q_data = get_q_data(ctx, vq->
type);
713 alloc_ctxs[0] = ctx->
dev->alloc_ctx;
715 dprintk(ctx->
dev,
"get %d buffer(s) of size %d each.\n", count, size);
720 static int emmaprp_buf_prepare(
struct vb2_buffer *vb)
727 q_data = get_q_data(ctx, vb->
vb2_queue->type);
729 if (vb2_plane_size(vb, 0) < q_data->
sizeimage) {
730 dprintk(ctx->
dev,
"%s data will not fit into plane"
731 "(%lu < %lu)\n", __func__,
732 vb2_plane_size(vb, 0),
737 vb2_set_plane_payload(vb, 0, q_data->
sizeimage);
742 static void emmaprp_buf_queue(
struct vb2_buffer *vb)
748 static struct vb2_ops emmaprp_qops = {
749 .queue_setup = emmaprp_queue_setup,
750 .buf_prepare = emmaprp_buf_prepare,
751 .buf_queue = emmaprp_buf_queue,
754 static int queue_init(
void *priv,
struct vb2_queue *src_vq,
764 src_vq->
ops = &emmaprp_qops;
775 dst_vq->
ops = &emmaprp_qops;
784 static int emmaprp_open(
struct file *file)
804 int ret = PTR_ERR(ctx->
m2m_ctx);
817 dprintk(pcdev,
"Created instance %p, m2m_ctx: %p\n", ctx, ctx->
m2m_ctx);
822 static int emmaprp_release(
struct file *file)
827 dprintk(pcdev,
"Releasing instance %p\n", ctx);
839 static unsigned int emmaprp_poll(
struct file *file,
852 static int emmaprp_mmap(
struct file *file,
struct vm_area_struct *vma)
867 .open = emmaprp_open,
868 .release = emmaprp_release,
869 .poll = emmaprp_poll,
871 .mmap = emmaprp_mmap,
876 .fops = &emmaprp_fops,
877 .ioctl_ops = &emmaprp_ioctl_ops,
884 .device_run = emmaprp_device_run,
885 .job_abort = emmaprp_job_abort,
886 .lock = emmaprp_lock,
887 .unlock = emmaprp_unlock,
915 if (irq_emma < 0 || res_emma ==
NULL) {
916 dev_err(&pdev->
dev,
"Missing platform resources data\n");
933 *vfd = emmaprp_videodev;
936 video_set_drvdata(vfd, pcdev);
940 " Device registered as /dev/video%d\n", vfd->
num);
942 platform_set_drvdata(pdev, pcdev);
953 if (devm_request_irq(&pdev->
dev, pcdev->
irq_emma, emmaprp_irq,
996 struct emmaprp_dev *pcdev = platform_get_drvdata(pdev);
1009 .probe = emmaprp_probe,
1010 .remove = emmaprp_remove,
1017 static void __exit emmaprp_exit(
void)
1022 static int __init emmaprp_init(
void)