cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sun8i-di.c (26141B)


      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	int irq, ret;
    807
    808	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
    809	if (!dev)
    810		return -ENOMEM;
    811
    812	dev->vfd = deinterlace_video_device;
    813	dev->dev = &pdev->dev;
    814
    815	irq = platform_get_irq(pdev, 0);
    816	if (irq <= 0)
    817		return irq;
    818
    819	ret = devm_request_irq(dev->dev, irq, deinterlace_irq,
    820			       0, dev_name(dev->dev), dev);
    821	if (ret) {
    822		dev_err(dev->dev, "Failed to request IRQ\n");
    823
    824		return ret;
    825	}
    826
    827	dev->base = devm_platform_ioremap_resource(pdev, 0);
    828	if (IS_ERR(dev->base))
    829		return PTR_ERR(dev->base);
    830
    831	dev->bus_clk = devm_clk_get(dev->dev, "bus");
    832	if (IS_ERR(dev->bus_clk)) {
    833		dev_err(dev->dev, "Failed to get bus clock\n");
    834
    835		return PTR_ERR(dev->bus_clk);
    836	}
    837
    838	dev->mod_clk = devm_clk_get(dev->dev, "mod");
    839	if (IS_ERR(dev->mod_clk)) {
    840		dev_err(dev->dev, "Failed to get mod clock\n");
    841
    842		return PTR_ERR(dev->mod_clk);
    843	}
    844
    845	dev->ram_clk = devm_clk_get(dev->dev, "ram");
    846	if (IS_ERR(dev->ram_clk)) {
    847		dev_err(dev->dev, "Failed to get ram clock\n");
    848
    849		return PTR_ERR(dev->ram_clk);
    850	}
    851
    852	dev->rstc = devm_reset_control_get(dev->dev, NULL);
    853	if (IS_ERR(dev->rstc)) {
    854		dev_err(dev->dev, "Failed to get reset control\n");
    855
    856		return PTR_ERR(dev->rstc);
    857	}
    858
    859	mutex_init(&dev->dev_mutex);
    860
    861	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
    862	if (ret) {
    863		dev_err(dev->dev, "Failed to register V4L2 device\n");
    864
    865		return ret;
    866	}
    867
    868	vfd = &dev->vfd;
    869	vfd->lock = &dev->dev_mutex;
    870	vfd->v4l2_dev = &dev->v4l2_dev;
    871
    872	snprintf(vfd->name, sizeof(vfd->name), "%s",
    873		 deinterlace_video_device.name);
    874	video_set_drvdata(vfd, dev);
    875
    876	ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
    877	if (ret) {
    878		v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
    879
    880		goto err_v4l2;
    881	}
    882
    883	v4l2_info(&dev->v4l2_dev,
    884		  "Device registered as /dev/video%d\n", vfd->num);
    885
    886	dev->m2m_dev = v4l2_m2m_init(&deinterlace_m2m_ops);
    887	if (IS_ERR(dev->m2m_dev)) {
    888		v4l2_err(&dev->v4l2_dev,
    889			 "Failed to initialize V4L2 M2M device\n");
    890		ret = PTR_ERR(dev->m2m_dev);
    891
    892		goto err_video;
    893	}
    894
    895	platform_set_drvdata(pdev, dev);
    896
    897	pm_runtime_enable(dev->dev);
    898
    899	return 0;
    900
    901err_video:
    902	video_unregister_device(&dev->vfd);
    903err_v4l2:
    904	v4l2_device_unregister(&dev->v4l2_dev);
    905
    906	return ret;
    907}
    908
    909static int deinterlace_remove(struct platform_device *pdev)
    910{
    911	struct deinterlace_dev *dev = platform_get_drvdata(pdev);
    912
    913	v4l2_m2m_release(dev->m2m_dev);
    914	video_unregister_device(&dev->vfd);
    915	v4l2_device_unregister(&dev->v4l2_dev);
    916
    917	pm_runtime_force_suspend(&pdev->dev);
    918
    919	return 0;
    920}
    921
    922static int deinterlace_runtime_resume(struct device *device)
    923{
    924	struct deinterlace_dev *dev = dev_get_drvdata(device);
    925	int ret;
    926
    927	ret = clk_set_rate_exclusive(dev->mod_clk, 300000000);
    928	if (ret) {
    929		dev_err(dev->dev, "Failed to set exclusive mod clock rate\n");
    930
    931		return ret;
    932	}
    933
    934	ret = clk_prepare_enable(dev->bus_clk);
    935	if (ret) {
    936		dev_err(dev->dev, "Failed to enable bus clock\n");
    937
    938		goto err_exclusive_rate;
    939	}
    940
    941	ret = clk_prepare_enable(dev->mod_clk);
    942	if (ret) {
    943		dev_err(dev->dev, "Failed to enable mod clock\n");
    944
    945		goto err_bus_clk;
    946	}
    947
    948	ret = clk_prepare_enable(dev->ram_clk);
    949	if (ret) {
    950		dev_err(dev->dev, "Failed to enable ram clock\n");
    951
    952		goto err_mod_clk;
    953	}
    954
    955	ret = reset_control_deassert(dev->rstc);
    956	if (ret) {
    957		dev_err(dev->dev, "Failed to apply reset\n");
    958
    959		goto err_ram_clk;
    960	}
    961
    962	deinterlace_init(dev);
    963
    964	return 0;
    965
    966err_ram_clk:
    967	clk_disable_unprepare(dev->ram_clk);
    968err_mod_clk:
    969	clk_disable_unprepare(dev->mod_clk);
    970err_bus_clk:
    971	clk_disable_unprepare(dev->bus_clk);
    972err_exclusive_rate:
    973	clk_rate_exclusive_put(dev->mod_clk);
    974
    975	return ret;
    976}
    977
    978static int deinterlace_runtime_suspend(struct device *device)
    979{
    980	struct deinterlace_dev *dev = dev_get_drvdata(device);
    981
    982	reset_control_assert(dev->rstc);
    983
    984	clk_disable_unprepare(dev->ram_clk);
    985	clk_disable_unprepare(dev->mod_clk);
    986	clk_disable_unprepare(dev->bus_clk);
    987	clk_rate_exclusive_put(dev->mod_clk);
    988
    989	return 0;
    990}
    991
    992static const struct of_device_id deinterlace_dt_match[] = {
    993	{ .compatible = "allwinner,sun8i-h3-deinterlace" },
    994	{ /* sentinel */ }
    995};
    996MODULE_DEVICE_TABLE(of, deinterlace_dt_match);
    997
    998static const struct dev_pm_ops deinterlace_pm_ops = {
    999	.runtime_resume		= deinterlace_runtime_resume,
   1000	.runtime_suspend	= deinterlace_runtime_suspend,
   1001};
   1002
   1003static struct platform_driver deinterlace_driver = {
   1004	.probe		= deinterlace_probe,
   1005	.remove		= deinterlace_remove,
   1006	.driver		= {
   1007		.name		= DEINTERLACE_NAME,
   1008		.of_match_table	= deinterlace_dt_match,
   1009		.pm		= &deinterlace_pm_ops,
   1010	},
   1011};
   1012module_platform_driver(deinterlace_driver);
   1013
   1014MODULE_LICENSE("GPL v2");
   1015MODULE_AUTHOR("Jernej Skrabec <jernej.skrabec@siol.net>");
   1016MODULE_DESCRIPTION("Allwinner Deinterlace driver");