1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Allwinner sun8i deinterlacer with scaler driver
4 *
5 * Copyright (C) 2019 Jernej Skrabec <jernej.skrabec@siol.net>
6 *
7 * Based on vim2m driver.
8 */
9
10#include <linux/clk.h>
11#include <linux/interrupt.h>
12#include <linux/io.h>
13#include <linux/iopoll.h>
14#include <linux/module.h>
15#include <linux/of.h>
16#include <linux/of_device.h>
17#include <linux/pm_runtime.h>
18#include <linux/reset.h>
19
20#include <media/v4l2-device.h>
21#include <media/v4l2-ioctl.h>
22#include <media/v4l2-mem2mem.h>
23
24#include "sun8i-di.h"
25
26#define FLAG_SIZE (DEINTERLACE_MAX_WIDTH * DEINTERLACE_MAX_HEIGHT / 4)
27
28static u32 deinterlace_formats[] = {
29	V4L2_PIX_FMT_NV12,
30	V4L2_PIX_FMT_NV21,
31};
32
33static inline u32 deinterlace_read(struct deinterlace_dev *dev, u32 reg)
34{
35	return readl(dev->base + reg);
36}
37
38static inline void deinterlace_write(struct deinterlace_dev *dev,
39				     u32 reg, u32 value)
40{
41	writel(value, dev->base + reg);
42}
43
44static inline void deinterlace_set_bits(struct deinterlace_dev *dev,
45					u32 reg, u32 bits)
46{
47	writel(readl(dev->base + reg) | bits, dev->base + reg);
48}
49
50static inline void deinterlace_clr_set_bits(struct deinterlace_dev *dev,
51					    u32 reg, u32 clr, u32 set)
52{
53	u32 val = readl(dev->base + reg);
54
55	val &= ~clr;
56	val |= set;
57
58	writel(val, dev->base + reg);
59}
60
61static void deinterlace_device_run(void *priv)
62{
63	struct deinterlace_ctx *ctx = priv;
64	struct deinterlace_dev *dev = ctx->dev;
65	u32 size, stride, width, height, val;
66	struct vb2_v4l2_buffer *src, *dst;
67	unsigned int hstep, vstep;
68	dma_addr_t addr;
69
70	src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
71	dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
72
73	v4l2_m2m_buf_copy_metadata(src, dst, true);
74
75	deinterlace_write(dev, DEINTERLACE_MOD_ENABLE,
76			  DEINTERLACE_MOD_ENABLE_EN);
77
78	if (ctx->field) {
79		deinterlace_write(dev, DEINTERLACE_TILE_FLAG0,
80				  ctx->flag1_buf_dma);
81		deinterlace_write(dev, DEINTERLACE_TILE_FLAG1,
82				  ctx->flag2_buf_dma);
83	} else {
84		deinterlace_write(dev, DEINTERLACE_TILE_FLAG0,
85				  ctx->flag2_buf_dma);
86		deinterlace_write(dev, DEINTERLACE_TILE_FLAG1,
87				  ctx->flag1_buf_dma);
88	}
89	deinterlace_write(dev, DEINTERLACE_FLAG_LINE_STRIDE, 0x200);
90
91	width = ctx->src_fmt.width;
92	height = ctx->src_fmt.height;
93	stride = ctx->src_fmt.bytesperline;
94	size = stride * height;
95
96	addr = vb2_dma_contig_plane_dma_addr(&src->vb2_buf, 0);
97	deinterlace_write(dev, DEINTERLACE_BUF_ADDR0, addr);
98	deinterlace_write(dev, DEINTERLACE_BUF_ADDR1, addr + size);
99	deinterlace_write(dev, DEINTERLACE_BUF_ADDR2, 0);
100
101	deinterlace_write(dev, DEINTERLACE_LINE_STRIDE0, stride);
102	deinterlace_write(dev, DEINTERLACE_LINE_STRIDE1, stride);
103
104	deinterlace_write(dev, DEINTERLACE_CH0_IN_SIZE,
105			  DEINTERLACE_SIZE(width, height));
106	deinterlace_write(dev, DEINTERLACE_CH1_IN_SIZE,
107			  DEINTERLACE_SIZE(width / 2, height / 2));
108
109	val = DEINTERLACE_IN_FMT_FMT(DEINTERLACE_IN_FMT_YUV420) |
110	      DEINTERLACE_IN_FMT_MOD(DEINTERLACE_MODE_UV_COMBINED);
111	switch (ctx->src_fmt.pixelformat) {
112	case V4L2_PIX_FMT_NV12:
113		val |= DEINTERLACE_IN_FMT_PS(DEINTERLACE_PS_UVUV);
114		break;
115	case V4L2_PIX_FMT_NV21:
116		val |= DEINTERLACE_IN_FMT_PS(DEINTERLACE_PS_VUVU);
117		break;
118	}
119	deinterlace_write(dev, DEINTERLACE_IN_FMT, val);
120
121	if (ctx->prev)
122		addr = vb2_dma_contig_plane_dma_addr(&ctx->prev->vb2_buf, 0);
123
124	deinterlace_write(dev, DEINTERLACE_PRELUMA, addr);
125	deinterlace_write(dev, DEINTERLACE_PRECHROMA, addr + size);
126
127	val = DEINTERLACE_OUT_FMT_FMT(DEINTERLACE_OUT_FMT_YUV420SP);
128	switch (ctx->src_fmt.pixelformat) {
129	case V4L2_PIX_FMT_NV12:
130		val |= DEINTERLACE_OUT_FMT_PS(DEINTERLACE_PS_UVUV);
131		break;
132	case V4L2_PIX_FMT_NV21:
133		val |= DEINTERLACE_OUT_FMT_PS(DEINTERLACE_PS_VUVU);
134		break;
135	}
136	deinterlace_write(dev, DEINTERLACE_OUT_FMT, val);
137
138	width = ctx->dst_fmt.width;
139	height = ctx->dst_fmt.height;
140	stride = ctx->dst_fmt.bytesperline;
141	size = stride * height;
142
143	deinterlace_write(dev, DEINTERLACE_CH0_OUT_SIZE,
144			  DEINTERLACE_SIZE(width, height));
145	deinterlace_write(dev, DEINTERLACE_CH1_OUT_SIZE,
146			  DEINTERLACE_SIZE(width / 2, height / 2));
147
148	deinterlace_write(dev, DEINTERLACE_WB_LINE_STRIDE0, stride);
149	deinterlace_write(dev, DEINTERLACE_WB_LINE_STRIDE1, stride);
150
151	addr = vb2_dma_contig_plane_dma_addr(&dst->vb2_buf, 0);
152	deinterlace_write(dev, DEINTERLACE_WB_ADDR0, addr);
153	deinterlace_write(dev, DEINTERLACE_WB_ADDR1, addr + size);
154	deinterlace_write(dev, DEINTERLACE_WB_ADDR2, 0);
155
156	hstep = (ctx->src_fmt.width << 16) / ctx->dst_fmt.width;
157	vstep = (ctx->src_fmt.height << 16) / ctx->dst_fmt.height;
158	deinterlace_write(dev, DEINTERLACE_CH0_HORZ_FACT, hstep);
159	deinterlace_write(dev, DEINTERLACE_CH0_VERT_FACT, vstep);
160	deinterlace_write(dev, DEINTERLACE_CH1_HORZ_FACT, hstep);
161	deinterlace_write(dev, DEINTERLACE_CH1_VERT_FACT, vstep);
162
163	deinterlace_clr_set_bits(dev, DEINTERLACE_FIELD_CTRL,
164				 DEINTERLACE_FIELD_CTRL_FIELD_CNT_MSK,
165				 DEINTERLACE_FIELD_CTRL_FIELD_CNT(ctx->field));
166
167	deinterlace_set_bits(dev, DEINTERLACE_FRM_CTRL,
168			     DEINTERLACE_FRM_CTRL_START);
169
170	deinterlace_set_bits(dev, DEINTERLACE_FRM_CTRL,
171			     DEINTERLACE_FRM_CTRL_REG_READY);
172
173	deinterlace_set_bits(dev, DEINTERLACE_INT_ENABLE,
174			     DEINTERLACE_INT_ENABLE_WB_EN);
175
176	deinterlace_set_bits(dev, DEINTERLACE_FRM_CTRL,
177			     DEINTERLACE_FRM_CTRL_WB_EN);
178}
179
180static int deinterlace_job_ready(void *priv)
181{
182	struct deinterlace_ctx *ctx = priv;
183
184	return v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) >= 1 &&
185	       v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) >= 2;
186}
187
188static void deinterlace_job_abort(void *priv)
189{
190	struct deinterlace_ctx *ctx = priv;
191
192	/* Will cancel the transaction in the next interrupt handler */
193	ctx->aborting = 1;
194}
195
196static irqreturn_t deinterlace_irq(int irq, void *data)
197{
198	struct deinterlace_dev *dev = data;
199	struct vb2_v4l2_buffer *src, *dst;
200	enum vb2_buffer_state state;
201	struct deinterlace_ctx *ctx;
202	unsigned int val;
203
204	ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
205	if (!ctx) {
206		v4l2_err(&dev->v4l2_dev,
207			 "Instance released before the end of transaction\n");
208		return IRQ_NONE;
209	}
210
211	val = deinterlace_read(dev, DEINTERLACE_INT_STATUS);
212	if (!(val & DEINTERLACE_INT_STATUS_WRITEBACK))
213		return IRQ_NONE;
214
215	deinterlace_write(dev, DEINTERLACE_INT_ENABLE, 0);
216	deinterlace_set_bits(dev, DEINTERLACE_INT_STATUS,
217			     DEINTERLACE_INT_STATUS_WRITEBACK);
218	deinterlace_write(dev, DEINTERLACE_MOD_ENABLE, 0);
219	deinterlace_clr_set_bits(dev, DEINTERLACE_FRM_CTRL,
220				 DEINTERLACE_FRM_CTRL_START, 0);
221
222	val = deinterlace_read(dev, DEINTERLACE_STATUS);
223	if (val & DEINTERLACE_STATUS_WB_ERROR)
224		state = VB2_BUF_STATE_ERROR;
225	else
226		state = VB2_BUF_STATE_DONE;
227
228	dst = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
229	v4l2_m2m_buf_done(dst, state);
230
231	if (ctx->field != ctx->first_field || ctx->aborting) {
232		ctx->field = ctx->first_field;
233
234		src = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
235		if (ctx->prev)
236			v4l2_m2m_buf_done(ctx->prev, state);
237		ctx->prev = src;
238
239		v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
240	} else {
241		ctx->field = !ctx->first_field;
242		deinterlace_device_run(ctx);
243	}
244
245	return IRQ_HANDLED;
246}
247
248static void deinterlace_init(struct deinterlace_dev *dev)
249{
250	u32 val;
251	int i;
252
253	deinterlace_write(dev, DEINTERLACE_BYPASS,
254			  DEINTERLACE_BYPASS_CSC);
255	deinterlace_write(dev, DEINTERLACE_WB_LINE_STRIDE_CTRL,
256			  DEINTERLACE_WB_LINE_STRIDE_CTRL_EN);
257	deinterlace_set_bits(dev, DEINTERLACE_FRM_CTRL,
258			     DEINTERLACE_FRM_CTRL_OUT_CTRL);
259	deinterlace_write(dev, DEINTERLACE_AGTH_SEL,
260			  DEINTERLACE_AGTH_SEL_LINEBUF);
261
262	val = DEINTERLACE_CTRL_EN |
263	      DEINTERLACE_CTRL_MODE_MIXED |
264	      DEINTERLACE_CTRL_DIAG_INTP_EN |
265	      DEINTERLACE_CTRL_TEMP_DIFF_EN;
266	deinterlace_write(dev, DEINTERLACE_CTRL, val);
267
268	deinterlace_clr_set_bits(dev, DEINTERLACE_LUMA_TH,
269				 DEINTERLACE_LUMA_TH_MIN_LUMA_MSK,
270				 DEINTERLACE_LUMA_TH_MIN_LUMA(4));
271
272	deinterlace_clr_set_bits(dev, DEINTERLACE_SPAT_COMP,
273				 DEINTERLACE_SPAT_COMP_TH2_MSK,
274				 DEINTERLACE_SPAT_COMP_TH2(5));
275
276	deinterlace_clr_set_bits(dev, DEINTERLACE_TEMP_DIFF,
277				 DEINTERLACE_TEMP_DIFF_AMBIGUITY_TH_MSK,
278				 DEINTERLACE_TEMP_DIFF_AMBIGUITY_TH(5));
279
280	val = DEINTERLACE_DIAG_INTP_TH0(60) |
281	      DEINTERLACE_DIAG_INTP_TH1(0) |
282	      DEINTERLACE_DIAG_INTP_TH3(30);
283	deinterlace_write(dev, DEINTERLACE_DIAG_INTP, val);
284
285	deinterlace_clr_set_bits(dev, DEINTERLACE_CHROMA_DIFF,
286				 DEINTERLACE_CHROMA_DIFF_TH_MSK,
287				 DEINTERLACE_CHROMA_DIFF_TH(5));
288
289	/* neutral filter coefficients */
290	deinterlace_set_bits(dev, DEINTERLACE_FRM_CTRL,
291			     DEINTERLACE_FRM_CTRL_COEF_ACCESS);
292	readl_poll_timeout(dev->base + DEINTERLACE_STATUS, val,
293			   val & DEINTERLACE_STATUS_COEF_STATUS, 2, 40);
294
295	for (i = 0; i < 32; i++) {
296		deinterlace_write(dev, DEINTERLACE_CH0_HORZ_COEF0 + i * 4,
297				  DEINTERLACE_IDENTITY_COEF);
298		deinterlace_write(dev, DEINTERLACE_CH0_VERT_COEF + i * 4,
299				  DEINTERLACE_IDENTITY_COEF);
300		deinterlace_write(dev, DEINTERLACE_CH1_HORZ_COEF0 + i * 4,
301				  DEINTERLACE_IDENTITY_COEF);
302		deinterlace_write(dev, DEINTERLACE_CH1_VERT_COEF + i * 4,
303				  DEINTERLACE_IDENTITY_COEF);
304	}
305
306	deinterlace_clr_set_bits(dev, DEINTERLACE_FRM_CTRL,
307				 DEINTERLACE_FRM_CTRL_COEF_ACCESS, 0);
308}
309
310static inline struct deinterlace_ctx *deinterlace_file2ctx(struct file *file)
311{
312	return container_of(file->private_data, struct deinterlace_ctx, fh);
313}
314
315static bool deinterlace_check_format(u32 pixelformat)
316{
317	unsigned int i;
318
319	for (i = 0; i < ARRAY_SIZE(deinterlace_formats); i++)
320		if (deinterlace_formats[i] == pixelformat)
321			return true;
322
323	return false;
324}
325
326static void deinterlace_prepare_format(struct v4l2_pix_format *pix_fmt)
327{
328	unsigned int height = pix_fmt->height;
329	unsigned int width = pix_fmt->width;
330	unsigned int bytesperline;
331	unsigned int sizeimage;
332
333	width = clamp(width, DEINTERLACE_MIN_WIDTH,
334		      DEINTERLACE_MAX_WIDTH);
335	height = clamp(height, DEINTERLACE_MIN_HEIGHT,
336		       DEINTERLACE_MAX_HEIGHT);
337
338	bytesperline = ALIGN(width, 2);
339	/* luma */
340	sizeimage = bytesperline * height;
341	/* chroma */
342	sizeimage += bytesperline * height / 2;
343
344	pix_fmt->width = width;
345	pix_fmt->height = height;
346	pix_fmt->bytesperline = bytesperline;
347	pix_fmt->sizeimage = sizeimage;
348}
349
350static int deinterlace_querycap(struct file *file, void *priv,
351				struct v4l2_capability *cap)
352{
353	strscpy(cap->driver, DEINTERLACE_NAME, sizeof(cap->driver));
354	strscpy(cap->card, DEINTERLACE_NAME, sizeof(cap->card));
355	snprintf(cap->bus_info, sizeof(cap->bus_info),
356		 "platform:%s", DEINTERLACE_NAME);
357
358	return 0;
359}
360
361static int deinterlace_enum_fmt(struct file *file, void *priv,
362				struct v4l2_fmtdesc *f)
363{
364	if (f->index < ARRAY_SIZE(deinterlace_formats)) {
365		f->pixelformat = deinterlace_formats[f->index];
366
367		return 0;
368	}
369
370	return -EINVAL;
371}
372
373static int deinterlace_enum_framesizes(struct file *file, void *priv,
374				       struct v4l2_frmsizeenum *fsize)
375{
376	if (fsize->index != 0)
377		return -EINVAL;
378
379	if (!deinterlace_check_format(fsize->pixel_format))
380		return -EINVAL;
381
382	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
383	fsize->stepwise.min_width = DEINTERLACE_MIN_WIDTH;
384	fsize->stepwise.min_height = DEINTERLACE_MIN_HEIGHT;
385	fsize->stepwise.max_width = DEINTERLACE_MAX_WIDTH;
386	fsize->stepwise.max_height = DEINTERLACE_MAX_HEIGHT;
387	fsize->stepwise.step_width = 2;
388	fsize->stepwise.step_height = 1;
389
390	return 0;
391}
392
393static int deinterlace_g_fmt_vid_cap(struct file *file, void *priv,
394				     struct v4l2_format *f)
395{
396	struct deinterlace_ctx *ctx = deinterlace_file2ctx(file);
397
398	f->fmt.pix = ctx->dst_fmt;
399
400	return 0;
401}
402
403static int deinterlace_g_fmt_vid_out(struct file *file, void *priv,
404				     struct v4l2_format *f)
405{
406	struct deinterlace_ctx *ctx = deinterlace_file2ctx(file);
407
408	f->fmt.pix = ctx->src_fmt;
409
410	return 0;
411}
412
413static int deinterlace_try_fmt_vid_cap(struct file *file, void *priv,
414				       struct v4l2_format *f)
415{
416	if (!deinterlace_check_format(f->fmt.pix.pixelformat))
417		f->fmt.pix.pixelformat = deinterlace_formats[0];
418
419	if (f->fmt.pix.field != V4L2_FIELD_NONE)
420		f->fmt.pix.field = V4L2_FIELD_NONE;
421
422	deinterlace_prepare_format(&f->fmt.pix);
423
424	return 0;
425}
426
427static int deinterlace_try_fmt_vid_out(struct file *file, void *priv,
428				       struct v4l2_format *f)
429{
430	if (!deinterlace_check_format(f->fmt.pix.pixelformat))
431		f->fmt.pix.pixelformat = deinterlace_formats[0];
432
433	if (f->fmt.pix.field != V4L2_FIELD_INTERLACED_TB &&
434	    f->fmt.pix.field != V4L2_FIELD_INTERLACED_BT &&
435	    f->fmt.pix.field != V4L2_FIELD_INTERLACED)
436		f->fmt.pix.field = V4L2_FIELD_INTERLACED;
437
438	deinterlace_prepare_format(&f->fmt.pix);
439
440	return 0;
441}
442
443static int deinterlace_s_fmt_vid_cap(struct file *file, void *priv,
444				     struct v4l2_format *f)
445{
446	struct deinterlace_ctx *ctx = deinterlace_file2ctx(file);
447	struct vb2_queue *vq;
448	int ret;
449
450	ret = deinterlace_try_fmt_vid_cap(file, priv, f);
451	if (ret)
452		return ret;
453
454	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
455	if (vb2_is_busy(vq))
456		return -EBUSY;
457
458	ctx->dst_fmt = f->fmt.pix;
459
460	return 0;
461}
462
463static int deinterlace_s_fmt_vid_out(struct file *file, void *priv,
464				     struct v4l2_format *f)
465{
466	struct deinterlace_ctx *ctx = deinterlace_file2ctx(file);
467	struct vb2_queue *vq;
468	int ret;
469
470	ret = deinterlace_try_fmt_vid_out(file, priv, f);
471	if (ret)
472		return ret;
473
474	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
475	if (vb2_is_busy(vq))
476		return -EBUSY;
477
478	ctx->src_fmt = f->fmt.pix;
479
480	/* Propagate colorspace information to capture. */
481	ctx->dst_fmt.colorspace = f->fmt.pix.colorspace;
482	ctx->dst_fmt.xfer_func = f->fmt.pix.xfer_func;
483	ctx->dst_fmt.ycbcr_enc = f->fmt.pix.ycbcr_enc;
484	ctx->dst_fmt.quantization = f->fmt.pix.quantization;
485
486	return 0;
487}
488
489static const struct v4l2_ioctl_ops deinterlace_ioctl_ops = {
490	.vidioc_querycap		= deinterlace_querycap,
491
492	.vidioc_enum_framesizes		= deinterlace_enum_framesizes,
493
494	.vidioc_enum_fmt_vid_cap	= deinterlace_enum_fmt,
495	.vidioc_g_fmt_vid_cap		= deinterlace_g_fmt_vid_cap,
496	.vidioc_try_fmt_vid_cap		= deinterlace_try_fmt_vid_cap,
497	.vidioc_s_fmt_vid_cap		= deinterlace_s_fmt_vid_cap,
498
499	.vidioc_enum_fmt_vid_out	= deinterlace_enum_fmt,
500	.vidioc_g_fmt_vid_out		= deinterlace_g_fmt_vid_out,
501	.vidioc_try_fmt_vid_out		= deinterlace_try_fmt_vid_out,
502	.vidioc_s_fmt_vid_out		= deinterlace_s_fmt_vid_out,
503
504	.vidioc_reqbufs			= v4l2_m2m_ioctl_reqbufs,
505	.vidioc_querybuf		= v4l2_m2m_ioctl_querybuf,
506	.vidioc_qbuf			= v4l2_m2m_ioctl_qbuf,
507	.vidioc_dqbuf			= v4l2_m2m_ioctl_dqbuf,
508	.vidioc_prepare_buf		= v4l2_m2m_ioctl_prepare_buf,
509	.vidioc_create_bufs		= v4l2_m2m_ioctl_create_bufs,
510	.vidioc_expbuf			= v4l2_m2m_ioctl_expbuf,
511
512	.vidioc_streamon		= v4l2_m2m_ioctl_streamon,
513	.vidioc_streamoff		= v4l2_m2m_ioctl_streamoff,
514};
515
516static int deinterlace_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
517				   unsigned int *nplanes, unsigned int sizes[],
518				   struct device *alloc_devs[])
519{
520	struct deinterlace_ctx *ctx = vb2_get_drv_priv(vq);
521	struct v4l2_pix_format *pix_fmt;
522
523	if (V4L2_TYPE_IS_OUTPUT(vq->type))
524		pix_fmt = &ctx->src_fmt;
525	else
526		pix_fmt = &ctx->dst_fmt;
527
528	if (*nplanes) {
529		if (sizes[0] < pix_fmt->sizeimage)
530			return -EINVAL;
531	} else {
532		sizes[0] = pix_fmt->sizeimage;
533		*nplanes = 1;
534	}
535
536	return 0;
537}
538
539static int deinterlace_buf_prepare(struct vb2_buffer *vb)
540{
541	struct vb2_queue *vq = vb->vb2_queue;
542	struct deinterlace_ctx *ctx = vb2_get_drv_priv(vq);
543	struct v4l2_pix_format *pix_fmt;
544
545	if (V4L2_TYPE_IS_OUTPUT(vq->type))
546		pix_fmt = &ctx->src_fmt;
547	else
548		pix_fmt = &ctx->dst_fmt;
549
550	if (vb2_plane_size(vb, 0) < pix_fmt->sizeimage)
551		return -EINVAL;
552
553	vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage);
554
555	return 0;
556}
557
558static void deinterlace_buf_queue(struct vb2_buffer *vb)
559{
560	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
561	struct deinterlace_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
562
563	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
564}
565
566static void deinterlace_queue_cleanup(struct vb2_queue *vq, u32 state)
567{
568	struct deinterlace_ctx *ctx = vb2_get_drv_priv(vq);
569	struct vb2_v4l2_buffer *vbuf;
570
571	do {
572		if (V4L2_TYPE_IS_OUTPUT(vq->type))
573			vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
574		else
575			vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
576
577		if (vbuf)
578			v4l2_m2m_buf_done(vbuf, state);
579	} while (vbuf);
580
581	if (V4L2_TYPE_IS_OUTPUT(vq->type) && ctx->prev)
582		v4l2_m2m_buf_done(ctx->prev, state);
583}
584
585static int deinterlace_start_streaming(struct vb2_queue *vq, unsigned int count)
586{
587	struct deinterlace_ctx *ctx = vb2_get_drv_priv(vq);
588	struct device *dev = ctx->dev->dev;
589	int ret;
590
591	if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
592		ret = pm_runtime_resume_and_get(dev);
593		if (ret < 0) {
594			dev_err(dev, "Failed to enable module\n");
595
596			goto err_runtime_get;
597		}
598
599		ctx->first_field =
600			ctx->src_fmt.field == V4L2_FIELD_INTERLACED_BT;
601		ctx->field = ctx->first_field;
602
603		ctx->prev = NULL;
604		ctx->aborting = 0;
605
606		ctx->flag1_buf = dma_alloc_coherent(dev, FLAG_SIZE,
607						    &ctx->flag1_buf_dma,
608						    GFP_KERNEL);
609		if (!ctx->flag1_buf) {
610			ret = -ENOMEM;
611
612			goto err_no_mem1;
613		}
614
615		ctx->flag2_buf = dma_alloc_coherent(dev, FLAG_SIZE,
616						    &ctx->flag2_buf_dma,
617						    GFP_KERNEL);
618		if (!ctx->flag2_buf) {
619			ret = -ENOMEM;
620
621			goto err_no_mem2;
622		}
623	}
624
625	return 0;
626
627err_no_mem2:
628	dma_free_coherent(dev, FLAG_SIZE, ctx->flag1_buf,
629			  ctx->flag1_buf_dma);
630err_no_mem1:
631	pm_runtime_put(dev);
632err_runtime_get:
633	deinterlace_queue_cleanup(vq, VB2_BUF_STATE_QUEUED);
634
635	return ret;
636}
637
638static void deinterlace_stop_streaming(struct vb2_queue *vq)
639{
640	struct deinterlace_ctx *ctx = vb2_get_drv_priv(vq);
641
642	if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
643		struct device *dev = ctx->dev->dev;
644
645		dma_free_coherent(dev, FLAG_SIZE, ctx->flag1_buf,
646				  ctx->flag1_buf_dma);
647		dma_free_coherent(dev, FLAG_SIZE, ctx->flag2_buf,
648				  ctx->flag2_buf_dma);
649
650		pm_runtime_put(dev);
651	}
652
653	deinterlace_queue_cleanup(vq, VB2_BUF_STATE_ERROR);
654}
655
656static const struct vb2_ops deinterlace_qops = {
657	.queue_setup		= deinterlace_queue_setup,
658	.buf_prepare		= deinterlace_buf_prepare,
659	.buf_queue		= deinterlace_buf_queue,
660	.start_streaming	= deinterlace_start_streaming,
661	.stop_streaming		= deinterlace_stop_streaming,
662	.wait_prepare		= vb2_ops_wait_prepare,
663	.wait_finish		= vb2_ops_wait_finish,
664};
665
666static int deinterlace_queue_init(void *priv, struct vb2_queue *src_vq,
667				  struct vb2_queue *dst_vq)
668{
669	struct deinterlace_ctx *ctx = priv;
670	int ret;
671
672	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
673	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
674	src_vq->drv_priv = ctx;
675	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
676	src_vq->min_buffers_needed = 1;
677	src_vq->ops = &deinterlace_qops;
678	src_vq->mem_ops = &vb2_dma_contig_memops;
679	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
680	src_vq->lock = &ctx->dev->dev_mutex;
681	src_vq->dev = ctx->dev->dev;
682
683	ret = vb2_queue_init(src_vq);
684	if (ret)
685		return ret;
686
687	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
688	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
689	dst_vq->drv_priv = ctx;
690	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
691	dst_vq->min_buffers_needed = 2;
692	dst_vq->ops = &deinterlace_qops;
693	dst_vq->mem_ops = &vb2_dma_contig_memops;
694	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
695	dst_vq->lock = &ctx->dev->dev_mutex;
696	dst_vq->dev = ctx->dev->dev;
697
698	ret = vb2_queue_init(dst_vq);
699	if (ret)
700		return ret;
701
702	return 0;
703}
704
705static int deinterlace_open(struct file *file)
706{
707	struct deinterlace_dev *dev = video_drvdata(file);
708	struct deinterlace_ctx *ctx = NULL;
709	int ret;
710
711	if (mutex_lock_interruptible(&dev->dev_mutex))
712		return -ERESTARTSYS;
713
714	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
715	if (!ctx) {
716		mutex_unlock(&dev->dev_mutex);
717		return -ENOMEM;
718	}
719
720	/* default output format */
721	ctx->src_fmt.pixelformat = deinterlace_formats[0];
722	ctx->src_fmt.field = V4L2_FIELD_INTERLACED;
723	ctx->src_fmt.width = 640;
724	ctx->src_fmt.height = 480;
725	deinterlace_prepare_format(&ctx->src_fmt);
726
727	/* default capture format */
728	ctx->dst_fmt.pixelformat = deinterlace_formats[0];
729	ctx->dst_fmt.field = V4L2_FIELD_NONE;
730	ctx->dst_fmt.width = 640;
731	ctx->dst_fmt.height = 480;
732	deinterlace_prepare_format(&ctx->dst_fmt);
733
734	v4l2_fh_init(&ctx->fh, video_devdata(file));
735	file->private_data = &ctx->fh;
736	ctx->dev = dev;
737
738	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx,
739					    &deinterlace_queue_init);
740	if (IS_ERR(ctx->fh.m2m_ctx)) {
741		ret = PTR_ERR(ctx->fh.m2m_ctx);
742		goto err_free;
743	}
744
745	v4l2_fh_add(&ctx->fh);
746
747	mutex_unlock(&dev->dev_mutex);
748
749	return 0;
750
751err_free:
752	kfree(ctx);
753	mutex_unlock(&dev->dev_mutex);
754
755	return ret;
756}
757
758static int deinterlace_release(struct file *file)
759{
760	struct deinterlace_dev *dev = video_drvdata(file);
761	struct deinterlace_ctx *ctx = container_of(file->private_data,
762						   struct deinterlace_ctx, fh);
763
764	mutex_lock(&dev->dev_mutex);
765
766	v4l2_fh_del(&ctx->fh);
767	v4l2_fh_exit(&ctx->fh);
768	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
769
770	kfree(ctx);
771
772	mutex_unlock(&dev->dev_mutex);
773
774	return 0;
775}
776
777static const struct v4l2_file_operations deinterlace_fops = {
778	.owner		= THIS_MODULE,
779	.open		= deinterlace_open,
780	.release	= deinterlace_release,
781	.poll		= v4l2_m2m_fop_poll,
782	.unlocked_ioctl	= video_ioctl2,
783	.mmap		= v4l2_m2m_fop_mmap,
784};
785
786static const struct video_device deinterlace_video_device = {
787	.name		= DEINTERLACE_NAME,
788	.vfl_dir	= VFL_DIR_M2M,
789	.fops		= &deinterlace_fops,
790	.ioctl_ops	= &deinterlace_ioctl_ops,
791	.minor		= -1,
792	.release	= video_device_release_empty,
793	.device_caps	= V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING,
794};
795
796static const struct v4l2_m2m_ops deinterlace_m2m_ops = {
797	.device_run	= deinterlace_device_run,
798	.job_ready	= deinterlace_job_ready,
799	.job_abort	= deinterlace_job_abort,
800};
801
802static int deinterlace_probe(struct platform_device *pdev)
803{
804	struct deinterlace_dev *dev;
805	struct video_device *vfd;
806	struct resource *res;
807	int irq, ret;
808
809	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
810	if (!dev)
811		return -ENOMEM;
812
813	dev->vfd = deinterlace_video_device;
814	dev->dev = &pdev->dev;
815
816	irq = platform_get_irq(pdev, 0);
817	if (irq <= 0)
818		return irq;
819
820	ret = devm_request_irq(dev->dev, irq, deinterlace_irq,
821			       0, dev_name(dev->dev), dev);
822	if (ret) {
823		dev_err(dev->dev, "Failed to request IRQ\n");
824
825		return ret;
826	}
827
828	ret = of_dma_configure(dev->dev, dev->dev->of_node, true);
829	if (ret)
830		return ret;
831
832	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
833	dev->base = devm_ioremap_resource(&pdev->dev, res);
834	if (IS_ERR(dev->base))
835		return PTR_ERR(dev->base);
836
837	dev->bus_clk = devm_clk_get(dev->dev, "bus");
838	if (IS_ERR(dev->bus_clk)) {
839		dev_err(dev->dev, "Failed to get bus clock\n");
840
841		return PTR_ERR(dev->bus_clk);
842	}
843
844	dev->mod_clk = devm_clk_get(dev->dev, "mod");
845	if (IS_ERR(dev->mod_clk)) {
846		dev_err(dev->dev, "Failed to get mod clock\n");
847
848		return PTR_ERR(dev->mod_clk);
849	}
850
851	dev->ram_clk = devm_clk_get(dev->dev, "ram");
852	if (IS_ERR(dev->ram_clk)) {
853		dev_err(dev->dev, "Failed to get ram clock\n");
854
855		return PTR_ERR(dev->ram_clk);
856	}
857
858	dev->rstc = devm_reset_control_get(dev->dev, NULL);
859	if (IS_ERR(dev->rstc)) {
860		dev_err(dev->dev, "Failed to get reset control\n");
861
862		return PTR_ERR(dev->rstc);
863	}
864
865	mutex_init(&dev->dev_mutex);
866
867	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
868	if (ret) {
869		dev_err(dev->dev, "Failed to register V4L2 device\n");
870
871		return ret;
872	}
873
874	vfd = &dev->vfd;
875	vfd->lock = &dev->dev_mutex;
876	vfd->v4l2_dev = &dev->v4l2_dev;
877
878	snprintf(vfd->name, sizeof(vfd->name), "%s",
879		 deinterlace_video_device.name);
880	video_set_drvdata(vfd, dev);
881
882	ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
883	if (ret) {
884		v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
885
886		goto err_v4l2;
887	}
888
889	v4l2_info(&dev->v4l2_dev,
890		  "Device registered as /dev/video%d\n", vfd->num);
891
892	dev->m2m_dev = v4l2_m2m_init(&deinterlace_m2m_ops);
893	if (IS_ERR(dev->m2m_dev)) {
894		v4l2_err(&dev->v4l2_dev,
895			 "Failed to initialize V4L2 M2M device\n");
896		ret = PTR_ERR(dev->m2m_dev);
897
898		goto err_video;
899	}
900
901	platform_set_drvdata(pdev, dev);
902
903	pm_runtime_enable(dev->dev);
904
905	return 0;
906
907err_video:
908	video_unregister_device(&dev->vfd);
909err_v4l2:
910	v4l2_device_unregister(&dev->v4l2_dev);
911
912	return ret;
913}
914
915static int deinterlace_remove(struct platform_device *pdev)
916{
917	struct deinterlace_dev *dev = platform_get_drvdata(pdev);
918
919	v4l2_m2m_release(dev->m2m_dev);
920	video_unregister_device(&dev->vfd);
921	v4l2_device_unregister(&dev->v4l2_dev);
922
923	pm_runtime_force_suspend(&pdev->dev);
924
925	return 0;
926}
927
928static int deinterlace_runtime_resume(struct device *device)
929{
930	struct deinterlace_dev *dev = dev_get_drvdata(device);
931	int ret;
932
933	ret = clk_set_rate_exclusive(dev->mod_clk, 300000000);
934	if (ret) {
935		dev_err(dev->dev, "Failed to set exclusive mod clock rate\n");
936
937		return ret;
938	}
939
940	ret = clk_prepare_enable(dev->bus_clk);
941	if (ret) {
942		dev_err(dev->dev, "Failed to enable bus clock\n");
943
944		goto err_exclusive_rate;
945	}
946
947	ret = clk_prepare_enable(dev->mod_clk);
948	if (ret) {
949		dev_err(dev->dev, "Failed to enable mod clock\n");
950
951		goto err_bus_clk;
952	}
953
954	ret = clk_prepare_enable(dev->ram_clk);
955	if (ret) {
956		dev_err(dev->dev, "Failed to enable ram clock\n");
957
958		goto err_mod_clk;
959	}
960
961	ret = reset_control_deassert(dev->rstc);
962	if (ret) {
963		dev_err(dev->dev, "Failed to apply reset\n");
964
965		goto err_ram_clk;
966	}
967
968	deinterlace_init(dev);
969
970	return 0;
971
972err_ram_clk:
973	clk_disable_unprepare(dev->ram_clk);
974err_mod_clk:
975	clk_disable_unprepare(dev->mod_clk);
976err_bus_clk:
977	clk_disable_unprepare(dev->bus_clk);
978err_exclusive_rate:
979	clk_rate_exclusive_put(dev->mod_clk);
980
981	return ret;
982}
983
984static int deinterlace_runtime_suspend(struct device *device)
985{
986	struct deinterlace_dev *dev = dev_get_drvdata(device);
987
988	reset_control_assert(dev->rstc);
989
990	clk_disable_unprepare(dev->ram_clk);
991	clk_disable_unprepare(dev->mod_clk);
992	clk_disable_unprepare(dev->bus_clk);
993	clk_rate_exclusive_put(dev->mod_clk);
994
995	return 0;
996}
997
998static const struct of_device_id deinterlace_dt_match[] = {
999	{ .compatible = "allwinner,sun8i-h3-deinterlace" },
1000	{ /* sentinel */ }
1001};
1002MODULE_DEVICE_TABLE(of, deinterlace_dt_match);
1003
1004static const struct dev_pm_ops deinterlace_pm_ops = {
1005	.runtime_resume		= deinterlace_runtime_resume,
1006	.runtime_suspend	= deinterlace_runtime_suspend,
1007};
1008
1009static struct platform_driver deinterlace_driver = {
1010	.probe		= deinterlace_probe,
1011	.remove		= deinterlace_remove,
1012	.driver		= {
1013		.name		= DEINTERLACE_NAME,
1014		.of_match_table	= deinterlace_dt_match,
1015		.pm		= &deinterlace_pm_ops,
1016	},
1017};
1018module_platform_driver(deinterlace_driver);
1019
1020MODULE_LICENSE("GPL v2");
1021MODULE_AUTHOR("Jernej Skrabec <jernej.skrabec@siol.net>");
1022MODULE_DESCRIPTION("Allwinner Deinterlace driver");
1023