File Index
Files and directories
Sign in
FILE

sun8i-di.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c C
   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/mod_devicetable.h>
  15#include <linux/module.h>
  16#include <linux/platform_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	int i;
  70
  71	src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
  72	dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
  73
  74	v4l2_m2m_buf_copy_metadata(src, dst);
  75
  76	deinterlace_write(dev, DEINTERLACE_MOD_ENABLE,
  77			  DEINTERLACE_MOD_ENABLE_EN);
  78
  79	if (ctx->field) {
  80		deinterlace_write(dev, DEINTERLACE_TILE_FLAG0,
  81				  ctx->flag1_buf_dma);
  82		deinterlace_write(dev, DEINTERLACE_TILE_FLAG1,
  83				  ctx->flag2_buf_dma);
  84	} else {
  85		deinterlace_write(dev, DEINTERLACE_TILE_FLAG0,
  86				  ctx->flag2_buf_dma);
  87		deinterlace_write(dev, DEINTERLACE_TILE_FLAG1,
  88				  ctx->flag1_buf_dma);
  89	}
  90	deinterlace_write(dev, DEINTERLACE_FLAG_LINE_STRIDE, 0x200);
  91
  92	width = ctx->src_fmt.width;
  93	height = ctx->src_fmt.height;
  94	stride = ctx->src_fmt.bytesperline;
  95	size = stride * height;
  96
  97	addr = vb2_dma_contig_plane_dma_addr(&src->vb2_buf, 0);
  98	deinterlace_write(dev, DEINTERLACE_BUF_ADDR0, addr);
  99	deinterlace_write(dev, DEINTERLACE_BUF_ADDR1, addr + size);
 100	deinterlace_write(dev, DEINTERLACE_BUF_ADDR2, 0);
 101
 102	deinterlace_write(dev, DEINTERLACE_LINE_STRIDE0, stride);
 103	deinterlace_write(dev, DEINTERLACE_LINE_STRIDE1, stride);
 104
 105	deinterlace_write(dev, DEINTERLACE_CH0_IN_SIZE,
 106			  DEINTERLACE_SIZE(width, height));
 107	deinterlace_write(dev, DEINTERLACE_CH1_IN_SIZE,
 108			  DEINTERLACE_SIZE(width / 2, height / 2));
 109
 110	val = DEINTERLACE_IN_FMT_FMT(DEINTERLACE_IN_FMT_YUV420) |
 111	      DEINTERLACE_IN_FMT_MOD(DEINTERLACE_MODE_UV_COMBINED);
 112	switch (ctx->src_fmt.pixelformat) {
 113	case V4L2_PIX_FMT_NV12:
 114		val |= DEINTERLACE_IN_FMT_PS(DEINTERLACE_PS_UVUV);
 115		break;
 116	case V4L2_PIX_FMT_NV21:
 117		val |= DEINTERLACE_IN_FMT_PS(DEINTERLACE_PS_VUVU);
 118		break;
 119	}
 120	deinterlace_write(dev, DEINTERLACE_IN_FMT, val);
 121
 122	if (ctx->prev)
 123		addr = vb2_dma_contig_plane_dma_addr(&ctx->prev->vb2_buf, 0);
 124
 125	deinterlace_write(dev, DEINTERLACE_PRELUMA, addr);
 126	deinterlace_write(dev, DEINTERLACE_PRECHROMA, addr + size);
 127
 128	val = DEINTERLACE_OUT_FMT_FMT(DEINTERLACE_OUT_FMT_YUV420SP);
 129	switch (ctx->src_fmt.pixelformat) {
 130	case V4L2_PIX_FMT_NV12:
 131		val |= DEINTERLACE_OUT_FMT_PS(DEINTERLACE_PS_UVUV);
 132		break;
 133	case V4L2_PIX_FMT_NV21:
 134		val |= DEINTERLACE_OUT_FMT_PS(DEINTERLACE_PS_VUVU);
 135		break;
 136	}
 137	deinterlace_write(dev, DEINTERLACE_OUT_FMT, val);
 138
 139	width = ctx->dst_fmt.width;
 140	height = ctx->dst_fmt.height;
 141	stride = ctx->dst_fmt.bytesperline;
 142	size = stride * height;
 143
 144	deinterlace_write(dev, DEINTERLACE_CH0_OUT_SIZE,
 145			  DEINTERLACE_SIZE(width, height));
 146	deinterlace_write(dev, DEINTERLACE_CH1_OUT_SIZE,
 147			  DEINTERLACE_SIZE(width / 2, height / 2));
 148
 149	deinterlace_write(dev, DEINTERLACE_WB_LINE_STRIDE0, stride);
 150	deinterlace_write(dev, DEINTERLACE_WB_LINE_STRIDE1, stride);
 151
 152	addr = vb2_dma_contig_plane_dma_addr(&dst->vb2_buf, 0);
 153	deinterlace_write(dev, DEINTERLACE_WB_ADDR0, addr);
 154	deinterlace_write(dev, DEINTERLACE_WB_ADDR1, addr + size);
 155	deinterlace_write(dev, DEINTERLACE_WB_ADDR2, 0);
 156
 157	hstep = (ctx->src_fmt.width << 16) / ctx->dst_fmt.width;
 158	vstep = (ctx->src_fmt.height << 16) / ctx->dst_fmt.height;
 159	deinterlace_write(dev, DEINTERLACE_CH0_HORZ_FACT, hstep);
 160	deinterlace_write(dev, DEINTERLACE_CH0_VERT_FACT, vstep);
 161	deinterlace_write(dev, DEINTERLACE_CH1_HORZ_FACT, hstep);
 162	deinterlace_write(dev, DEINTERLACE_CH1_VERT_FACT, vstep);
 163
 164	/* neutral filter coefficients */
 165	deinterlace_set_bits(dev, DEINTERLACE_FRM_CTRL,
 166			     DEINTERLACE_FRM_CTRL_COEF_ACCESS);
 167	readl_poll_timeout(dev->base + DEINTERLACE_STATUS, val,
 168			   val & DEINTERLACE_STATUS_COEF_STATUS, 2, 40);
 169
 170	for (i = 0; i < 32; i++) {
 171		deinterlace_write(dev, DEINTERLACE_CH0_HORZ_COEF0 + i * 4,
 172				  DEINTERLACE_IDENTITY_COEF);
 173		deinterlace_write(dev, DEINTERLACE_CH0_VERT_COEF + i * 4,
 174				  DEINTERLACE_IDENTITY_COEF);
 175		deinterlace_write(dev, DEINTERLACE_CH1_HORZ_COEF0 + i * 4,
 176				  DEINTERLACE_IDENTITY_COEF);
 177		deinterlace_write(dev, DEINTERLACE_CH1_VERT_COEF + i * 4,
 178				  DEINTERLACE_IDENTITY_COEF);
 179	}
 180
 181	deinterlace_clr_set_bits(dev, DEINTERLACE_FRM_CTRL,
 182				 DEINTERLACE_FRM_CTRL_COEF_ACCESS, 0);
 183
 184	deinterlace_clr_set_bits(dev, DEINTERLACE_FIELD_CTRL,
 185				 DEINTERLACE_FIELD_CTRL_FIELD_CNT_MSK,
 186				 DEINTERLACE_FIELD_CTRL_FIELD_CNT(ctx->field));
 187
 188	deinterlace_set_bits(dev, DEINTERLACE_FRM_CTRL,
 189			     DEINTERLACE_FRM_CTRL_START);
 190
 191	deinterlace_set_bits(dev, DEINTERLACE_FRM_CTRL,
 192			     DEINTERLACE_FRM_CTRL_REG_READY);
 193
 194	deinterlace_set_bits(dev, DEINTERLACE_INT_ENABLE,
 195			     DEINTERLACE_INT_ENABLE_WB_EN);
 196
 197	deinterlace_set_bits(dev, DEINTERLACE_FRM_CTRL,
 198			     DEINTERLACE_FRM_CTRL_WB_EN);
 199}
 200
 201static int deinterlace_job_ready(void *priv)
 202{
 203	struct deinterlace_ctx *ctx = priv;
 204
 205	return v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) >= 1 &&
 206	       v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) >= 2;
 207}
 208
 209static void deinterlace_job_abort(void *priv)
 210{
 211	struct deinterlace_ctx *ctx = priv;
 212
 213	/* Will cancel the transaction in the next interrupt handler */
 214	ctx->aborting = 1;
 215}
 216
 217static irqreturn_t deinterlace_irq(int irq, void *data)
 218{
 219	struct deinterlace_dev *dev = data;
 220	struct vb2_v4l2_buffer *src, *dst;
 221	enum vb2_buffer_state state;
 222	struct deinterlace_ctx *ctx;
 223	unsigned int val;
 224
 225	ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
 226	if (!ctx) {
 227		v4l2_err(&dev->v4l2_dev,
 228			 "Instance released before the end of transaction\n");
 229		return IRQ_NONE;
 230	}
 231
 232	val = deinterlace_read(dev, DEINTERLACE_INT_STATUS);
 233	if (!(val & DEINTERLACE_INT_STATUS_WRITEBACK))
 234		return IRQ_NONE;
 235
 236	deinterlace_write(dev, DEINTERLACE_INT_ENABLE, 0);
 237	deinterlace_set_bits(dev, DEINTERLACE_INT_STATUS,
 238			     DEINTERLACE_INT_STATUS_WRITEBACK);
 239	deinterlace_write(dev, DEINTERLACE_MOD_ENABLE, 0);
 240	deinterlace_clr_set_bits(dev, DEINTERLACE_FRM_CTRL,
 241				 DEINTERLACE_FRM_CTRL_START, 0);
 242
 243	val = deinterlace_read(dev, DEINTERLACE_STATUS);
 244	if (val & DEINTERLACE_STATUS_WB_ERROR)
 245		state = VB2_BUF_STATE_ERROR;
 246	else
 247		state = VB2_BUF_STATE_DONE;
 248
 249	dst = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 250	v4l2_m2m_buf_done(dst, state);
 251
 252	if (ctx->field != ctx->first_field || ctx->aborting) {
 253		ctx->field = ctx->first_field;
 254
 255		src = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
 256		if (ctx->prev)
 257			v4l2_m2m_buf_done(ctx->prev, state);
 258		ctx->prev = src;
 259
 260		v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
 261	} else {
 262		ctx->field = !ctx->first_field;
 263		deinterlace_device_run(ctx);
 264	}
 265
 266	return IRQ_HANDLED;
 267}
 268
 269static void deinterlace_init(struct deinterlace_dev *dev)
 270{
 271	u32 val;
 272
 273	deinterlace_write(dev, DEINTERLACE_BYPASS,
 274			  DEINTERLACE_BYPASS_CSC);
 275	deinterlace_write(dev, DEINTERLACE_WB_LINE_STRIDE_CTRL,
 276			  DEINTERLACE_WB_LINE_STRIDE_CTRL_EN);
 277	deinterlace_set_bits(dev, DEINTERLACE_FRM_CTRL,
 278			     DEINTERLACE_FRM_CTRL_OUT_CTRL);
 279	deinterlace_write(dev, DEINTERLACE_AGTH_SEL,
 280			  DEINTERLACE_AGTH_SEL_LINEBUF);
 281
 282	val = DEINTERLACE_CTRL_EN |
 283	      DEINTERLACE_CTRL_MODE_MIXED |
 284	      DEINTERLACE_CTRL_DIAG_INTP_EN |
 285	      DEINTERLACE_CTRL_TEMP_DIFF_EN;
 286	deinterlace_write(dev, DEINTERLACE_CTRL, val);
 287
 288	deinterlace_clr_set_bits(dev, DEINTERLACE_LUMA_TH,
 289				 DEINTERLACE_LUMA_TH_MIN_LUMA_MSK,
 290				 DEINTERLACE_LUMA_TH_MIN_LUMA(4));
 291
 292	deinterlace_clr_set_bits(dev, DEINTERLACE_SPAT_COMP,
 293				 DEINTERLACE_SPAT_COMP_TH2_MSK,
 294				 DEINTERLACE_SPAT_COMP_TH2(5));
 295
 296	deinterlace_clr_set_bits(dev, DEINTERLACE_TEMP_DIFF,
 297				 DEINTERLACE_TEMP_DIFF_AMBIGUITY_TH_MSK,
 298				 DEINTERLACE_TEMP_DIFF_AMBIGUITY_TH(5));
 299
 300	val = DEINTERLACE_DIAG_INTP_TH0(60) |
 301	      DEINTERLACE_DIAG_INTP_TH1(0) |
 302	      DEINTERLACE_DIAG_INTP_TH3(30);
 303	deinterlace_write(dev, DEINTERLACE_DIAG_INTP, val);
 304
 305	deinterlace_clr_set_bits(dev, DEINTERLACE_CHROMA_DIFF,
 306				 DEINTERLACE_CHROMA_DIFF_TH_MSK,
 307				 DEINTERLACE_CHROMA_DIFF_TH(31));
 308}
 309
 310static inline struct deinterlace_ctx *deinterlace_file2ctx(struct file *file)
 311{
 312	return container_of(file_to_v4l2_fh(file), 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};
 663
 664static int deinterlace_queue_init(void *priv, struct vb2_queue *src_vq,
 665				  struct vb2_queue *dst_vq)
 666{
 667	struct deinterlace_ctx *ctx = priv;
 668	int ret;
 669
 670	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 671	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
 672	src_vq->drv_priv = ctx;
 673	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 674	src_vq->min_queued_buffers = 1;
 675	src_vq->ops = &deinterlace_qops;
 676	src_vq->mem_ops = &vb2_dma_contig_memops;
 677	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 678	src_vq->lock = &ctx->dev->dev_mutex;
 679	src_vq->dev = ctx->dev->dev;
 680
 681	ret = vb2_queue_init(src_vq);
 682	if (ret)
 683		return ret;
 684
 685	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 686	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
 687	dst_vq->drv_priv = ctx;
 688	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 689	dst_vq->min_queued_buffers = 2;
 690	dst_vq->ops = &deinterlace_qops;
 691	dst_vq->mem_ops = &vb2_dma_contig_memops;
 692	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 693	dst_vq->lock = &ctx->dev->dev_mutex;
 694	dst_vq->dev = ctx->dev->dev;
 695
 696	ret = vb2_queue_init(dst_vq);
 697	if (ret)
 698		return ret;
 699
 700	return 0;
 701}
 702
 703static int deinterlace_open(struct file *file)
 704{
 705	struct deinterlace_dev *dev = video_drvdata(file);
 706	struct deinterlace_ctx *ctx = NULL;
 707	int ret;
 708
 709	if (mutex_lock_interruptible(&dev->dev_mutex))
 710		return -ERESTARTSYS;
 711
 712	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
 713	if (!ctx) {
 714		mutex_unlock(&dev->dev_mutex);
 715		return -ENOMEM;
 716	}
 717
 718	/* default output format */
 719	ctx->src_fmt.pixelformat = deinterlace_formats[0];
 720	ctx->src_fmt.field = V4L2_FIELD_INTERLACED;
 721	ctx->src_fmt.width = 640;
 722	ctx->src_fmt.height = 480;
 723	deinterlace_prepare_format(&ctx->src_fmt);
 724
 725	/* default capture format */
 726	ctx->dst_fmt.pixelformat = deinterlace_formats[0];
 727	ctx->dst_fmt.field = V4L2_FIELD_NONE;
 728	ctx->dst_fmt.width = 640;
 729	ctx->dst_fmt.height = 480;
 730	deinterlace_prepare_format(&ctx->dst_fmt);
 731
 732	v4l2_fh_init(&ctx->fh, video_devdata(file));
 733	ctx->dev = dev;
 734
 735	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx,
 736					    &deinterlace_queue_init);
 737	if (IS_ERR(ctx->fh.m2m_ctx)) {
 738		ret = PTR_ERR(ctx->fh.m2m_ctx);
 739		goto err_free;
 740	}
 741
 742	v4l2_fh_add(&ctx->fh, file);
 743
 744	mutex_unlock(&dev->dev_mutex);
 745
 746	return 0;
 747
 748err_free:
 749	kfree(ctx);
 750	mutex_unlock(&dev->dev_mutex);
 751
 752	return ret;
 753}
 754
 755static int deinterlace_release(struct file *file)
 756{
 757	struct deinterlace_dev *dev = video_drvdata(file);
 758	struct deinterlace_ctx *ctx = deinterlace_file2ctx(file);
 759
 760	mutex_lock(&dev->dev_mutex);
 761
 762	v4l2_fh_del(&ctx->fh, file);
 763	v4l2_fh_exit(&ctx->fh);
 764	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
 765
 766	kfree(ctx);
 767
 768	mutex_unlock(&dev->dev_mutex);
 769
 770	return 0;
 771}
 772
 773static const struct v4l2_file_operations deinterlace_fops = {
 774	.owner		= THIS_MODULE,
 775	.open		= deinterlace_open,
 776	.release	= deinterlace_release,
 777	.poll		= v4l2_m2m_fop_poll,
 778	.unlocked_ioctl	= video_ioctl2,
 779	.mmap		= v4l2_m2m_fop_mmap,
 780};
 781
 782static const struct video_device deinterlace_video_device = {
 783	.name		= DEINTERLACE_NAME,
 784	.vfl_dir	= VFL_DIR_M2M,
 785	.fops		= &deinterlace_fops,
 786	.ioctl_ops	= &deinterlace_ioctl_ops,
 787	.minor		= -1,
 788	.release	= video_device_release_empty,
 789	.device_caps	= V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING,
 790};
 791
 792static const struct v4l2_m2m_ops deinterlace_m2m_ops = {
 793	.device_run	= deinterlace_device_run,
 794	.job_ready	= deinterlace_job_ready,
 795	.job_abort	= deinterlace_job_abort,
 796};
 797
 798static int deinterlace_probe(struct platform_device *pdev)
 799{
 800	struct deinterlace_dev *dev;
 801	struct video_device *vfd;
 802	int irq, ret;
 803
 804	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
 805	if (!dev)
 806		return -ENOMEM;
 807
 808	dev->vfd = deinterlace_video_device;
 809	dev->dev = &pdev->dev;
 810
 811	irq = platform_get_irq(pdev, 0);
 812	if (irq <= 0)
 813		return irq;
 814
 815	ret = devm_request_irq(dev->dev, irq, deinterlace_irq,
 816			       0, dev_name(dev->dev), dev);
 817	if (ret) {
 818		dev_err(dev->dev, "Failed to request IRQ\n");
 819
 820		return ret;
 821	}
 822
 823	dev->base = devm_platform_ioremap_resource(pdev, 0);
 824	if (IS_ERR(dev->base))
 825		return PTR_ERR(dev->base);
 826
 827	dev->bus_clk = devm_clk_get(dev->dev, "bus");
 828	if (IS_ERR(dev->bus_clk)) {
 829		dev_err(dev->dev, "Failed to get bus clock\n");
 830
 831		return PTR_ERR(dev->bus_clk);
 832	}
 833
 834	dev->mod_clk = devm_clk_get(dev->dev, "mod");
 835	if (IS_ERR(dev->mod_clk)) {
 836		dev_err(dev->dev, "Failed to get mod clock\n");
 837
 838		return PTR_ERR(dev->mod_clk);
 839	}
 840
 841	dev->ram_clk = devm_clk_get(dev->dev, "ram");
 842	if (IS_ERR(dev->ram_clk)) {
 843		dev_err(dev->dev, "Failed to get ram clock\n");
 844
 845		return PTR_ERR(dev->ram_clk);
 846	}
 847
 848	dev->rstc = devm_reset_control_get(dev->dev, NULL);
 849	if (IS_ERR(dev->rstc)) {
 850		dev_err(dev->dev, "Failed to get reset control\n");
 851
 852		return PTR_ERR(dev->rstc);
 853	}
 854
 855	mutex_init(&dev->dev_mutex);
 856
 857	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
 858	if (ret) {
 859		dev_err(dev->dev, "Failed to register V4L2 device\n");
 860
 861		return ret;
 862	}
 863
 864	vfd = &dev->vfd;
 865	vfd->lock = &dev->dev_mutex;
 866	vfd->v4l2_dev = &dev->v4l2_dev;
 867
 868	snprintf(vfd->name, sizeof(vfd->name), "%s",
 869		 deinterlace_video_device.name);
 870	video_set_drvdata(vfd, dev);
 871
 872	ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
 873	if (ret) {
 874		v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
 875
 876		goto err_v4l2;
 877	}
 878
 879	v4l2_info(&dev->v4l2_dev,
 880		  "Device registered as /dev/video%d\n", vfd->num);
 881
 882	dev->m2m_dev = v4l2_m2m_init(&deinterlace_m2m_ops);
 883	if (IS_ERR(dev->m2m_dev)) {
 884		v4l2_err(&dev->v4l2_dev,
 885			 "Failed to initialize V4L2 M2M device\n");
 886		ret = PTR_ERR(dev->m2m_dev);
 887
 888		goto err_video;
 889	}
 890
 891	platform_set_drvdata(pdev, dev);
 892
 893	pm_runtime_enable(dev->dev);
 894
 895	return 0;
 896
 897err_video:
 898	video_unregister_device(&dev->vfd);
 899err_v4l2:
 900	v4l2_device_unregister(&dev->v4l2_dev);
 901
 902	return ret;
 903}
 904
 905static void deinterlace_remove(struct platform_device *pdev)
 906{
 907	struct deinterlace_dev *dev = platform_get_drvdata(pdev);
 908
 909	v4l2_m2m_release(dev->m2m_dev);
 910	video_unregister_device(&dev->vfd);
 911	v4l2_device_unregister(&dev->v4l2_dev);
 912
 913	pm_runtime_force_suspend(&pdev->dev);
 914}
 915
 916static int deinterlace_runtime_resume(struct device *device)
 917{
 918	struct deinterlace_dev *dev = dev_get_drvdata(device);
 919	int ret;
 920
 921	ret = clk_set_rate_exclusive(dev->mod_clk, 300000000);
 922	if (ret) {
 923		dev_err(dev->dev, "Failed to set exclusive mod clock rate\n");
 924
 925		return ret;
 926	}
 927
 928	ret = reset_control_deassert(dev->rstc);
 929	if (ret) {
 930		dev_err(dev->dev, "Failed to apply reset\n");
 931
 932		goto err_exclusive_rate;
 933	}
 934
 935	ret = clk_prepare_enable(dev->bus_clk);
 936	if (ret) {
 937		dev_err(dev->dev, "Failed to enable bus clock\n");
 938
 939		goto err_rst;
 940	}
 941
 942	ret = clk_prepare_enable(dev->mod_clk);
 943	if (ret) {
 944		dev_err(dev->dev, "Failed to enable mod clock\n");
 945
 946		goto err_bus_clk;
 947	}
 948
 949	ret = clk_prepare_enable(dev->ram_clk);
 950	if (ret) {
 951		dev_err(dev->dev, "Failed to enable ram clock\n");
 952
 953		goto err_mod_clk;
 954	}
 955
 956	deinterlace_init(dev);
 957
 958	return 0;
 959
 960err_mod_clk:
 961	clk_disable_unprepare(dev->mod_clk);
 962err_bus_clk:
 963	clk_disable_unprepare(dev->bus_clk);
 964err_rst:
 965	reset_control_assert(dev->rstc);
 966err_exclusive_rate:
 967	clk_rate_exclusive_put(dev->mod_clk);
 968
 969	return ret;
 970}
 971
 972static int deinterlace_runtime_suspend(struct device *device)
 973{
 974	struct deinterlace_dev *dev = dev_get_drvdata(device);
 975
 976	clk_disable_unprepare(dev->ram_clk);
 977	clk_disable_unprepare(dev->mod_clk);
 978	clk_disable_unprepare(dev->bus_clk);
 979
 980	reset_control_assert(dev->rstc);
 981
 982	clk_rate_exclusive_put(dev->mod_clk);
 983
 984	return 0;
 985}
 986
 987static const struct of_device_id deinterlace_dt_match[] = {
 988	{ .compatible = "allwinner,sun8i-h3-deinterlace" },
 989	{ /* sentinel */ }
 990};
 991MODULE_DEVICE_TABLE(of, deinterlace_dt_match);
 992
 993static const struct dev_pm_ops deinterlace_pm_ops = {
 994	.runtime_resume		= deinterlace_runtime_resume,
 995	.runtime_suspend	= deinterlace_runtime_suspend,
 996};
 997
 998static struct platform_driver deinterlace_driver = {
 999	.probe		= deinterlace_probe,
1000	.remove		= deinterlace_remove,
1001	.driver		= {
1002		.name		= DEINTERLACE_NAME,
1003		.of_match_table	= deinterlace_dt_match,
1004		.pm		= &deinterlace_pm_ops,
1005	},
1006};
1007module_platform_driver(deinterlace_driver);
1008
1009MODULE_LICENSE("GPL v2");
1010MODULE_AUTHOR("Jernej Skrabec <jernej.skrabec@siol.net>");
1011MODULE_DESCRIPTION("Allwinner Deinterlace driver");
~/ Read-only file preview.