File Index
Files and directories
Sign in
FILE

e5010-jpeg-enc.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/platform/imagination/e5010-jpeg-enc.c C
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Imagination E5010 JPEG Encoder driver.
   4 *
   5 * TODO: Add MMU and memory tiling support
   6 *
   7 * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
   8 *
   9 * Author: David Huang <d-huang@ti.com>
  10 * Author: Devarsh Thakkar <devarsht@ti.com>
  11 */
  12
  13#include <linux/clk.h>
  14#include <linux/dma-mapping.h>
  15#include <linux/err.h>
  16#include <linux/interrupt.h>
  17#include <linux/ioctl.h>
  18#include <linux/module.h>
  19#include <linux/of_device.h>
  20#include <linux/pm_runtime.h>
  21#include <media/jpeg.h>
  22#include <media/v4l2-common.h>
  23#include <media/v4l2-ctrls.h>
  24#include <media/v4l2-device.h>
  25#include <media/v4l2-event.h>
  26#include <media/v4l2-ioctl.h>
  27#include <media/v4l2-jpeg.h>
  28#include <media/v4l2-rect.h>
  29#include <media/v4l2-mem2mem.h>
  30#include <media/videobuf2-dma-contig.h>
  31#include <media/videobuf2-v4l2.h>
  32#include "e5010-jpeg-enc.h"
  33#include "e5010-jpeg-enc-hw.h"
  34
  35/* forward declarations */
  36static const struct of_device_id e5010_of_match[];
  37
  38static const struct v4l2_file_operations e5010_fops;
  39
  40static const struct v4l2_ioctl_ops e5010_ioctl_ops;
  41
  42static const struct vb2_ops e5010_video_ops;
  43
  44static const struct v4l2_m2m_ops e5010_m2m_ops;
  45
  46static struct e5010_fmt e5010_formats[] = {
  47	{
  48		.fourcc = V4L2_PIX_FMT_NV12,
  49		.num_planes = 1,
  50		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
  51		.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
  52		.chroma_order = CHROMA_ORDER_CB_CR,
  53		.frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64,
  54			     MIN_DIMENSION, MAX_DIMENSION, 8 },
  55	},
  56	{
  57		.fourcc = V4L2_PIX_FMT_NV12M,
  58		.num_planes = 2,
  59		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
  60		.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
  61		.chroma_order = CHROMA_ORDER_CB_CR,
  62		.frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64,
  63			     MIN_DIMENSION, MAX_DIMENSION, 8 },
  64	},
  65	{
  66		.fourcc = V4L2_PIX_FMT_NV21,
  67		.num_planes = 1,
  68		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
  69		.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
  70		.chroma_order = CHROMA_ORDER_CR_CB,
  71		.frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64,
  72			     MIN_DIMENSION, MAX_DIMENSION, 8 },
  73	},
  74	{
  75		.fourcc = V4L2_PIX_FMT_NV21M,
  76		.num_planes = 2,
  77		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
  78		.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
  79		.chroma_order = CHROMA_ORDER_CR_CB,
  80		.frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64,
  81			     MIN_DIMENSION, MAX_DIMENSION, 8 },
  82	},
  83	{
  84		.fourcc = V4L2_PIX_FMT_NV16,
  85		.num_planes = 1,
  86		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
  87		.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
  88		.chroma_order = CHROMA_ORDER_CB_CR,
  89		.frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64,
  90			     MIN_DIMENSION, MAX_DIMENSION, 8 },
  91	},
  92	{
  93		.fourcc = V4L2_PIX_FMT_NV16M,
  94		.num_planes = 2,
  95		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
  96		.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
  97		.chroma_order = CHROMA_ORDER_CB_CR,
  98		.frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64,
  99			     MIN_DIMENSION, MAX_DIMENSION, 8 },
 100
 101	},
 102	{
 103		.fourcc = V4L2_PIX_FMT_NV61,
 104		.num_planes = 1,
 105		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
 106		.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
 107		.chroma_order = CHROMA_ORDER_CR_CB,
 108		.frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64,
 109			     MIN_DIMENSION, MAX_DIMENSION, 8 },
 110	},
 111	{
 112		.fourcc = V4L2_PIX_FMT_NV61M,
 113		.num_planes = 2,
 114		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
 115		.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
 116		.chroma_order = CHROMA_ORDER_CR_CB,
 117		.frmsize = { MIN_DIMENSION, MAX_DIMENSION, 64,
 118			     MIN_DIMENSION, MAX_DIMENSION, 8 },
 119	},
 120	{
 121		.fourcc = V4L2_PIX_FMT_JPEG,
 122		.num_planes = 1,
 123		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
 124		.subsampling = 0,
 125		.chroma_order = 0,
 126		.frmsize = { MIN_DIMENSION, MAX_DIMENSION, 16,
 127			     MIN_DIMENSION, MAX_DIMENSION, 8 },
 128	},
 129};
 130
 131static unsigned int debug;
 132module_param(debug, uint, 0644);
 133MODULE_PARM_DESC(debug, "debug level");
 134
 135#define dprintk(dev, lvl, fmt, arg...) \
 136	v4l2_dbg(lvl, debug, &(dev)->v4l2_dev, "%s: " fmt, __func__, ## arg)
 137
 138static const struct v4l2_event e5010_eos_event = {
 139	.type = V4L2_EVENT_EOS
 140};
 141
 142static const char *type_name(enum v4l2_buf_type type)
 143{
 144	switch (type) {
 145	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 146		return "Output";
 147	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 148		return "Capture";
 149	default:
 150		return "Invalid";
 151	}
 152}
 153
 154static struct e5010_q_data *get_queue(struct e5010_context *ctx, enum v4l2_buf_type type)
 155{
 156	return (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? &ctx->out_queue : &ctx->cap_queue;
 157}
 158
 159static void calculate_qp_tables(struct e5010_context *ctx)
 160{
 161	long long luminosity, contrast;
 162	int quality, i;
 163
 164	quality = 50 - ctx->quality;
 165
 166	luminosity = LUMINOSITY * quality / 50;
 167	contrast = CONTRAST * quality / 50;
 168
 169	if (quality > 0) {
 170		luminosity *= INCREASE;
 171		contrast *= INCREASE;
 172	}
 173
 174	for (i = 0; i < V4L2_JPEG_PIXELS_IN_BLOCK; i++) {
 175		long long delta = v4l2_jpeg_ref_table_chroma_qt[i] * contrast + luminosity;
 176		int val = (int)(v4l2_jpeg_ref_table_chroma_qt[i] + delta);
 177
 178		clamp(val, 1, 255);
 179		ctx->chroma_qp[i] = quality == -50 ? 1 : val;
 180
 181		delta = v4l2_jpeg_ref_table_luma_qt[i] * contrast + luminosity;
 182		val = (int)(v4l2_jpeg_ref_table_luma_qt[i] + delta);
 183		clamp(val, 1, 255);
 184		ctx->luma_qp[i] = quality == -50 ? 1 : val;
 185	}
 186
 187	ctx->update_qp = true;
 188}
 189
 190static int update_qp_tables(struct e5010_context *ctx)
 191{
 192	struct e5010_dev *e5010 = ctx->e5010;
 193	int i, ret = 0;
 194	u32 lvalue, cvalue;
 195
 196	lvalue = 0;
 197	cvalue = 0;
 198
 199	for (i = 0; i < QP_TABLE_SIZE; i++) {
 200		lvalue |= ctx->luma_qp[i] << (8 * (i % 4));
 201		cvalue |= ctx->chroma_qp[i] << (8 * (i % 4));
 202		if (i % 4 == 3) {
 203			ret |= e5010_hw_set_qpvalue(e5010->core_base,
 204							JASPER_LUMA_QUANTIZATION_TABLE0_OFFSET
 205							+ QP_TABLE_FIELD_OFFSET * ((i - 3) / 4),
 206							lvalue);
 207			ret |= e5010_hw_set_qpvalue(e5010->core_base,
 208							JASPER_CHROMA_QUANTIZATION_TABLE0_OFFSET
 209							+ QP_TABLE_FIELD_OFFSET * ((i - 3) / 4),
 210							cvalue);
 211			lvalue = 0;
 212			cvalue = 0;
 213		}
 214	}
 215
 216	return ret;
 217}
 218
 219static int e5010_set_input_subsampling(void __iomem *core_base, int subsampling)
 220{
 221	switch (subsampling) {
 222	case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
 223		return e5010_hw_set_input_subsampling(core_base, SUBSAMPLING_420);
 224	case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
 225		return e5010_hw_set_input_subsampling(core_base, SUBSAMPLING_422);
 226	default:
 227		return -EINVAL;
 228	};
 229}
 230
 231static int e5010_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
 232{
 233	strscpy(cap->driver, E5010_MODULE_NAME, sizeof(cap->driver));
 234	strscpy(cap->card, E5010_MODULE_NAME, sizeof(cap->card));
 235
 236	return 0;
 237}
 238
 239static struct e5010_fmt *find_format(struct v4l2_format *f)
 240{
 241	int i;
 242
 243	for (i = 0; i < ARRAY_SIZE(e5010_formats); ++i) {
 244		if (e5010_formats[i].fourcc == f->fmt.pix_mp.pixelformat &&
 245		    e5010_formats[i].type == f->type)
 246			return &e5010_formats[i];
 247	}
 248
 249	return NULL;
 250}
 251
 252static int e5010_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f)
 253{
 254	int i, index = 0;
 255	struct e5010_fmt *fmt = NULL;
 256	struct e5010_context *ctx = to_e5010_context(file);
 257
 258	if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
 259		v4l2_err(&ctx->e5010->v4l2_dev, "ENUMFMT with Invalid type: %d\n", f->type);
 260		return -EINVAL;
 261	}
 262
 263	for (i = 0; i < ARRAY_SIZE(e5010_formats); ++i) {
 264		if (e5010_formats[i].type == f->type) {
 265			if (index == f->index) {
 266				fmt = &e5010_formats[i];
 267				break;
 268			}
 269			index++;
 270		}
 271	}
 272
 273	if (!fmt)
 274		return -EINVAL;
 275
 276	f->pixelformat = fmt->fourcc;
 277	return 0;
 278}
 279
 280static int e5010_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
 281{
 282	struct e5010_context *ctx = to_e5010_context(file);
 283	struct e5010_q_data *queue;
 284	int i;
 285	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
 286	struct v4l2_plane_pix_format *plane_fmt = pix_mp->plane_fmt;
 287
 288	queue = get_queue(ctx, f->type);
 289
 290	pix_mp->flags = 0;
 291	pix_mp->field = V4L2_FIELD_NONE;
 292	pix_mp->pixelformat = queue->fmt->fourcc;
 293	pix_mp->width = queue->width_adjusted;
 294	pix_mp->height = queue->height_adjusted;
 295	pix_mp->num_planes = queue->fmt->num_planes;
 296
 297	if (V4L2_TYPE_IS_OUTPUT(f->type)) {
 298		if (!pix_mp->colorspace)
 299			pix_mp->colorspace = V4L2_COLORSPACE_SRGB;
 300
 301		for (i = 0; i < queue->fmt->num_planes; i++) {
 302			plane_fmt[i].sizeimage = queue->sizeimage[i];
 303			plane_fmt[i].bytesperline = queue->bytesperline[i];
 304		}
 305
 306	} else {
 307		pix_mp->colorspace = V4L2_COLORSPACE_JPEG;
 308		plane_fmt[0].bytesperline = 0;
 309		plane_fmt[0].sizeimage = queue->sizeimage[0];
 310	}
 311	pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
 312	pix_mp->xfer_func = V4L2_XFER_FUNC_DEFAULT;
 313	pix_mp->quantization = V4L2_QUANTIZATION_DEFAULT;
 314
 315	return 0;
 316}
 317
 318static int e5010_jpeg_try_fmt(struct v4l2_format *f, struct e5010_context *ctx)
 319{
 320	struct e5010_fmt *fmt;
 321	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
 322	struct v4l2_plane_pix_format *plane_fmt = pix_mp->plane_fmt;
 323
 324	fmt = find_format(f);
 325	if (!fmt) {
 326		if (V4L2_TYPE_IS_OUTPUT(f->type))
 327			pix_mp->pixelformat = V4L2_PIX_FMT_NV12;
 328		else
 329			pix_mp->pixelformat = V4L2_PIX_FMT_JPEG;
 330		fmt = find_format(f);
 331		if (!fmt)
 332			return -EINVAL;
 333	}
 334
 335	if (V4L2_TYPE_IS_OUTPUT(f->type)) {
 336		if (!pix_mp->colorspace)
 337			pix_mp->colorspace = V4L2_COLORSPACE_JPEG;
 338		if (!pix_mp->ycbcr_enc)
 339			pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
 340		if (!pix_mp->quantization)
 341			pix_mp->quantization = V4L2_QUANTIZATION_DEFAULT;
 342		if (!pix_mp->xfer_func)
 343			pix_mp->xfer_func = V4L2_XFER_FUNC_DEFAULT;
 344
 345		v4l2_apply_frmsize_constraints(&pix_mp->width,
 346					       &pix_mp->height,
 347					       &fmt->frmsize);
 348
 349		v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat,
 350				    pix_mp->width, pix_mp->height);
 351
 352	} else {
 353		pix_mp->colorspace = V4L2_COLORSPACE_JPEG;
 354		pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
 355		pix_mp->quantization = V4L2_QUANTIZATION_DEFAULT;
 356		pix_mp->xfer_func = V4L2_XFER_FUNC_DEFAULT;
 357		v4l2_apply_frmsize_constraints(&pix_mp->width,
 358					       &pix_mp->height,
 359					       &fmt->frmsize);
 360		plane_fmt[0].sizeimage = pix_mp->width * pix_mp->height * JPEG_MAX_BYTES_PER_PIXEL;
 361		plane_fmt[0].sizeimage += HEADER_SIZE;
 362		plane_fmt[0].bytesperline = 0;
 363		pix_mp->pixelformat = fmt->fourcc;
 364		pix_mp->num_planes = fmt->num_planes;
 365	}
 366	pix_mp->flags = 0;
 367	pix_mp->field = V4L2_FIELD_NONE;
 368
 369	dprintk(ctx->e5010, 2,
 370		"ctx: 0x%p: format type %s:, wxh: %dx%d (plane0 : %d bytes, plane1 : %d bytes),fmt: %c%c%c%c\n",
 371		ctx, type_name(f->type), pix_mp->width, pix_mp->height,
 372		plane_fmt[0].sizeimage, plane_fmt[1].sizeimage,
 373		(fmt->fourcc & 0xff),
 374		(fmt->fourcc >>  8) & 0xff,
 375		(fmt->fourcc >> 16) & 0xff,
 376		(fmt->fourcc >> 24) & 0xff);
 377
 378	return 0;
 379}
 380
 381static int e5010_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
 382{
 383	struct e5010_context *ctx = to_e5010_context(file);
 384
 385	return e5010_jpeg_try_fmt(f, ctx);
 386}
 387
 388static int e5010_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
 389{
 390	struct e5010_context *ctx = to_e5010_context(file);
 391	struct vb2_queue *vq;
 392	int ret = 0, i = 0;
 393	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
 394	struct v4l2_plane_pix_format *plane_fmt = pix_mp->plane_fmt;
 395	struct e5010_q_data *queue;
 396	struct e5010_fmt *fmt;
 397
 398	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
 399
 400	if (vb2_is_busy(vq)) {
 401		v4l2_err(&ctx->e5010->v4l2_dev, "queue busy\n");
 402		return -EBUSY;
 403	}
 404
 405	ret = e5010_jpeg_try_fmt(f, ctx);
 406	if (ret)
 407		return ret;
 408
 409	fmt = find_format(f);
 410	queue = get_queue(ctx, f->type);
 411
 412	queue->fmt = fmt;
 413	queue->width = pix_mp->width;
 414	queue->height = pix_mp->height;
 415
 416	if (V4L2_TYPE_IS_OUTPUT(f->type)) {
 417		for (i = 0; i < fmt->num_planes; i++) {
 418			queue->bytesperline[i] = plane_fmt[i].bytesperline;
 419			queue->sizeimage[i] = plane_fmt[i].sizeimage;
 420		}
 421		queue->crop.left = 0;
 422		queue->crop.top = 0;
 423		queue->crop.width = queue->width;
 424		queue->crop.height = queue->height;
 425	} else {
 426		queue->sizeimage[0] = plane_fmt[0].sizeimage;
 427		queue->sizeimage[1] = 0;
 428		queue->bytesperline[0] = 0;
 429		queue->bytesperline[1] = 0;
 430	}
 431
 432	return 0;
 433}
 434
 435static int e5010_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize)
 436{
 437	struct v4l2_format f;
 438	struct e5010_fmt *fmt;
 439
 440	if (fsize->index != 0)
 441		return -EINVAL;
 442
 443	f.fmt.pix_mp.pixelformat = fsize->pixel_format;
 444	if (f.fmt.pix_mp.pixelformat ==  V4L2_PIX_FMT_JPEG)
 445		f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
 446	else
 447		f.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
 448
 449	fmt = find_format(&f);
 450	if (!fmt)
 451		return -EINVAL;
 452
 453	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
 454	fsize->stepwise = fmt->frmsize;
 455	fsize->reserved[0] = 0;
 456	fsize->reserved[1] = 0;
 457
 458	return 0;
 459}
 460
 461static int e5010_g_selection(struct file *file, void *fh, struct v4l2_selection *s)
 462{
 463	struct e5010_context *ctx = to_e5010_context(file);
 464	struct e5010_q_data *queue;
 465
 466	if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
 467		return -EINVAL;
 468
 469	queue = get_queue(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 470
 471	switch (s->target) {
 472	case V4L2_SEL_TGT_CROP_DEFAULT:
 473	case V4L2_SEL_TGT_CROP_BOUNDS:
 474		s->r.left = 0;
 475		s->r.top = 0;
 476		s->r.width = queue->width;
 477		s->r.height = queue->height;
 478		break;
 479	case V4L2_SEL_TGT_CROP:
 480		memcpy(&s->r, &queue->crop, sizeof(s->r));
 481		break;
 482	default:
 483		return -EINVAL;
 484	}
 485
 486	return 0;
 487}
 488
 489static int e5010_s_selection(struct file *file, void *fh, struct v4l2_selection *s)
 490{
 491	struct e5010_context *ctx = to_e5010_context(file);
 492	struct e5010_q_data *queue;
 493	struct vb2_queue *vq;
 494	struct v4l2_rect base_rect;
 495
 496	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, s->type);
 497
 498	if (vb2_is_streaming(vq))
 499		return -EBUSY;
 500
 501	if (s->target != V4L2_SEL_TGT_CROP ||
 502	    s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
 503		return -EINVAL;
 504
 505	queue = get_queue(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 506	base_rect.top = 0;
 507	base_rect.left = 0;
 508	base_rect.width = queue->width;
 509	base_rect.height = queue->height;
 510
 511	switch (s->flags) {
 512	case 0:
 513		s->r.width = round_down(s->r.width, queue->fmt->frmsize.step_width);
 514		s->r.height = round_down(s->r.height, queue->fmt->frmsize.step_height);
 515		s->r.left = round_down(s->r.left, queue->fmt->frmsize.step_width);
 516		s->r.top = round_down(s->r.top, 2);
 517
 518		if (s->r.left + s->r.width > queue->width)
 519			s->r.width = round_down(s->r.width + s->r.left - queue->width,
 520						queue->fmt->frmsize.step_width);
 521		if (s->r.top + s->r.height > queue->height)
 522			s->r.top = round_down(s->r.top + s->r.height - queue->height, 2);
 523		break;
 524	case V4L2_SEL_FLAG_GE:
 525		s->r.width = round_up(s->r.width, queue->fmt->frmsize.step_width);
 526		s->r.height = round_up(s->r.height, queue->fmt->frmsize.step_height);
 527		s->r.left = round_up(s->r.left, queue->fmt->frmsize.step_width);
 528		s->r.top = round_up(s->r.top, 2);
 529		break;
 530	case V4L2_SEL_FLAG_LE:
 531		s->r.width = round_down(s->r.width, queue->fmt->frmsize.step_width);
 532		s->r.height = round_down(s->r.height, queue->fmt->frmsize.step_height);
 533		s->r.left = round_down(s->r.left, queue->fmt->frmsize.step_width);
 534		s->r.top = round_down(s->r.top, 2);
 535		break;
 536	case V4L2_SEL_FLAG_LE | V4L2_SEL_FLAG_GE:
 537		if (!IS_ALIGNED(s->r.width, queue->fmt->frmsize.step_width) ||
 538		    !IS_ALIGNED(s->r.height, queue->fmt->frmsize.step_height) ||
 539		    !IS_ALIGNED(s->r.left, queue->fmt->frmsize.step_width) ||
 540		    !IS_ALIGNED(s->r.top, 2))
 541			return -ERANGE;
 542		break;
 543	default:
 544		return -EINVAL;
 545	}
 546
 547	if (!v4l2_rect_enclosed(&s->r, &base_rect))
 548		return -ERANGE;
 549
 550	memcpy(&queue->crop, &s->r, sizeof(s->r));
 551
 552	if (!v4l2_rect_equal(&s->r, &base_rect))
 553		queue->crop_set = true;
 554
 555	dprintk(ctx->e5010, 2, "ctx: 0x%p: crop rectangle: w: %d, h : %d, l : %d, t : %d\n",
 556		ctx, queue->crop.width, queue->crop.height, queue->crop.left, queue->crop.top);
 557
 558	return 0;
 559}
 560
 561static int e5010_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)
 562{
 563	switch (sub->type) {
 564	case V4L2_EVENT_EOS:
 565		return v4l2_event_subscribe(fh, sub, 0, NULL);
 566	case V4L2_EVENT_CTRL:
 567		return v4l2_ctrl_subscribe_event(fh, sub);
 568	default:
 569		return -EINVAL;
 570	}
 571
 572	return 0;
 573}
 574
 575static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
 576{
 577	struct e5010_context *ctx = priv;
 578	struct e5010_dev *e5010 = ctx->e5010;
 579	int ret = 0;
 580
 581	/* src_vq */
 582	memset(src_vq, 0, sizeof(*src_vq));
 583	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
 584	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
 585	src_vq->drv_priv = ctx;
 586	src_vq->buf_struct_size = sizeof(struct e5010_buffer);
 587	src_vq->ops = &e5010_video_ops;
 588	src_vq->mem_ops = &vb2_dma_contig_memops;
 589	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 590	src_vq->lock = &e5010->mutex;
 591	src_vq->dev = e5010->v4l2_dev.dev;
 592
 593	ret = vb2_queue_init(src_vq);
 594	if (ret)
 595		return ret;
 596
 597	/* dst_vq */
 598	memset(dst_vq, 0, sizeof(*dst_vq));
 599	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
 600	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
 601	dst_vq->drv_priv = ctx;
 602	dst_vq->buf_struct_size = sizeof(struct e5010_buffer);
 603	dst_vq->ops = &e5010_video_ops;
 604	dst_vq->mem_ops = &vb2_dma_contig_memops;
 605	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 606	dst_vq->lock = &e5010->mutex;
 607	dst_vq->dev = e5010->v4l2_dev.dev;
 608
 609	ret = vb2_queue_init(dst_vq);
 610	if (ret) {
 611		vb2_queue_release(src_vq);
 612		return ret;
 613	}
 614
 615	return 0;
 616}
 617
 618static int e5010_s_ctrl(struct v4l2_ctrl *ctrl)
 619{
 620	struct e5010_context *ctx =
 621		container_of(ctrl->handler, struct e5010_context, ctrl_handler);
 622
 623	switch (ctrl->id) {
 624	case V4L2_CID_JPEG_COMPRESSION_QUALITY:
 625		ctx->quality = ctrl->val;
 626		calculate_qp_tables(ctx);
 627		dprintk(ctx->e5010, 2, "ctx: 0x%p compression quality set to : %d\n", ctx,
 628			ctx->quality);
 629		break;
 630	default:
 631		return -EINVAL;
 632	}
 633
 634	return 0;
 635}
 636
 637static const struct v4l2_ctrl_ops e5010_ctrl_ops = {
 638	.s_ctrl = e5010_s_ctrl,
 639};
 640
 641static void e5010_encode_ctrls(struct e5010_context *ctx)
 642{
 643	v4l2_ctrl_new_std(&ctx->ctrl_handler, &e5010_ctrl_ops,
 644			  V4L2_CID_JPEG_COMPRESSION_QUALITY, 1, 100, 1, 75);
 645}
 646
 647static int e5010_ctrls_setup(struct e5010_context *ctx)
 648{
 649	int err;
 650
 651	v4l2_ctrl_handler_init(&ctx->ctrl_handler, 1);
 652
 653	e5010_encode_ctrls(ctx);
 654
 655	if (ctx->ctrl_handler.error) {
 656		err = ctx->ctrl_handler.error;
 657		v4l2_ctrl_handler_free(&ctx->ctrl_handler);
 658
 659		return err;
 660	}
 661
 662	err = v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
 663	if (err)
 664		v4l2_ctrl_handler_free(&ctx->ctrl_handler);
 665
 666	return err;
 667}
 668
 669static void e5010_jpeg_set_default_params(struct e5010_context *ctx)
 670{
 671	struct e5010_q_data *queue;
 672	struct v4l2_format f;
 673	struct e5010_fmt *fmt;
 674	struct v4l2_pix_format_mplane *pix_mp = &f.fmt.pix_mp;
 675	struct v4l2_plane_pix_format *plane_fmt = pix_mp->plane_fmt;
 676	int i = 0;
 677
 678	f.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
 679	f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12;
 680	fmt = find_format(&f);
 681	queue = &ctx->out_queue;
 682	queue->fmt = fmt;
 683	queue->width = DEFAULT_WIDTH;
 684	queue->height = DEFAULT_HEIGHT;
 685	pix_mp->width = queue->width;
 686	pix_mp->height = queue->height;
 687	queue->crop.left = 0;
 688	queue->crop.top = 0;
 689	queue->crop.width = queue->width;
 690	queue->crop.height = queue->height;
 691	v4l2_apply_frmsize_constraints(&pix_mp->width,
 692				       &pix_mp->height,
 693				       &fmt->frmsize);
 694	v4l2_fill_pixfmt_mp(pix_mp, pix_mp->pixelformat,
 695			    pix_mp->width, pix_mp->height);
 696	for (i = 0; i < fmt->num_planes; i++) {
 697		queue->bytesperline[i] = plane_fmt[i].bytesperline;
 698		queue->sizeimage[i] = plane_fmt[i].sizeimage;
 699	}
 700	queue->width_adjusted = pix_mp->width;
 701	queue->height_adjusted = pix_mp->height;
 702
 703	f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
 704	f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_JPEG;
 705	fmt = find_format(&f);
 706	queue = &ctx->cap_queue;
 707	queue->fmt = fmt;
 708	queue->width = DEFAULT_WIDTH;
 709	queue->height = DEFAULT_HEIGHT;
 710	pix_mp->width = queue->width;
 711	pix_mp->height = queue->height;
 712	v4l2_apply_frmsize_constraints(&pix_mp->width,
 713				       &pix_mp->height,
 714				       &fmt->frmsize);
 715	queue->sizeimage[0] = pix_mp->width * pix_mp->height * JPEG_MAX_BYTES_PER_PIXEL;
 716	queue->sizeimage[0] += HEADER_SIZE;
 717	queue->sizeimage[1] = 0;
 718	queue->bytesperline[0] = 0;
 719	queue->bytesperline[1] = 0;
 720	queue->width_adjusted = pix_mp->width;
 721	queue->height_adjusted = pix_mp->height;
 722}
 723
 724static int e5010_open(struct file *file)
 725{
 726	struct e5010_dev *e5010 = video_drvdata(file);
 727	struct video_device *vdev = video_devdata(file);
 728	struct e5010_context *ctx;
 729	int ret = 0;
 730
 731	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
 732	if (!ctx)
 733		return -ENOMEM;
 734
 735	if (mutex_lock_interruptible(&e5010->mutex)) {
 736		ret = -ERESTARTSYS;
 737		goto free;
 738	}
 739
 740	v4l2_fh_init(&ctx->fh, vdev);
 741	v4l2_fh_add(&ctx->fh, file);
 742
 743	ctx->e5010 = e5010;
 744	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(e5010->m2m_dev, ctx, queue_init);
 745	if (IS_ERR(ctx->fh.m2m_ctx)) {
 746		v4l2_err(&e5010->v4l2_dev, "failed to init m2m ctx\n");
 747		ret = PTR_ERR(ctx->fh.m2m_ctx);
 748		goto exit;
 749	}
 750
 751	ret = e5010_ctrls_setup(ctx);
 752	if (ret) {
 753		v4l2_err(&e5010->v4l2_dev, "failed to setup e5010 jpeg controls\n");
 754		goto err_ctrls_setup;
 755	}
 756	ctx->fh.ctrl_handler = &ctx->ctrl_handler;
 757
 758	e5010_jpeg_set_default_params(ctx);
 759
 760	dprintk(e5010, 1, "Created instance: 0x%p, m2m_ctx: 0x%p\n", ctx, ctx->fh.m2m_ctx);
 761
 762	mutex_unlock(&e5010->mutex);
 763	return 0;
 764
 765err_ctrls_setup:
 766	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
 767exit:
 768	v4l2_fh_del(&ctx->fh, file);
 769	v4l2_fh_exit(&ctx->fh);
 770	mutex_unlock(&e5010->mutex);
 771free:
 772	kfree(ctx);
 773	return ret;
 774}
 775
 776static int e5010_release(struct file *file)
 777{
 778	struct e5010_dev *e5010 = video_drvdata(file);
 779	struct e5010_context *ctx = to_e5010_context(file);
 780
 781	dprintk(e5010, 1, "Releasing instance: 0x%p, m2m_ctx: 0x%p\n", ctx, ctx->fh.m2m_ctx);
 782	mutex_lock(&e5010->mutex);
 783	v4l2_ctrl_handler_free(&ctx->ctrl_handler);
 784	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
 785	v4l2_fh_del(&ctx->fh, file);
 786	v4l2_fh_exit(&ctx->fh);
 787	kfree(ctx);
 788	mutex_unlock(&e5010->mutex);
 789
 790	return 0;
 791}
 792
 793static void header_write(struct e5010_context *ctx, u8 *addr, unsigned int *offset,
 794			 unsigned int no_bytes, unsigned long bits)
 795{
 796	u8 *w_addr = addr + *offset;
 797	int i;
 798
 799	if ((*offset + no_bytes) > HEADER_SIZE) {
 800		v4l2_warn(&ctx->e5010->v4l2_dev, "%s: %s: %d: Problem writing header. %d > HEADER_SIZE %d\n",
 801			  __FILE__, __func__, __LINE__, *offset + no_bytes, HEADER_SIZE);
 802		return;
 803	}
 804
 805	for (i = no_bytes - 1; i >= 0; i--)
 806		*(w_addr++) = ((u8 *)&bits)[i];
 807
 808	*offset += no_bytes;
 809}
 810
 811static void encode_marker_segment(struct e5010_context *ctx, void *addr, unsigned int *offset)
 812{
 813	u8 *buffer = (u8 *)addr;
 814	int i;
 815
 816	header_write(ctx, buffer, offset, 2, START_OF_IMAGE);
 817	header_write(ctx, buffer, offset, 2, DQT_MARKER);
 818	header_write(ctx, buffer, offset, 3, LQPQ << 4);
 819	for (i = 0; i < V4L2_JPEG_PIXELS_IN_BLOCK; i++)
 820		header_write(ctx, buffer, offset, 1, ctx->luma_qp[v4l2_jpeg_zigzag_scan_index[i]]);
 821
 822	header_write(ctx, buffer, offset, 2, DQT_MARKER);
 823	header_write(ctx, buffer, offset, 3, (LQPQ << 4) | 1);
 824	for (i = 0; i < V4L2_JPEG_PIXELS_IN_BLOCK; i++)
 825		header_write(ctx, buffer, offset, 1,
 826			     ctx->chroma_qp[v4l2_jpeg_zigzag_scan_index[i]]);
 827
 828	/* Huffman tables */
 829	header_write(ctx, buffer, offset, 2, DHT_MARKER);
 830	header_write(ctx, buffer, offset, 2, LH_DC);
 831	header_write(ctx, buffer, offset, 1, V4L2_JPEG_LUM_HT | V4L2_JPEG_DC_HT);
 832	for (i = 0 ; i < V4L2_JPEG_REF_HT_DC_LEN; i++)
 833		header_write(ctx, buffer, offset, 1, v4l2_jpeg_ref_table_luma_dc_ht[i]);
 834
 835	header_write(ctx, buffer, offset, 2, DHT_MARKER);
 836	header_write(ctx, buffer, offset, 2, LH_AC);
 837	header_write(ctx, buffer, offset, 1, V4L2_JPEG_LUM_HT | V4L2_JPEG_AC_HT);
 838	for (i = 0 ; i < V4L2_JPEG_REF_HT_AC_LEN; i++)
 839		header_write(ctx, buffer, offset, 1, v4l2_jpeg_ref_table_luma_ac_ht[i]);
 840
 841	header_write(ctx, buffer, offset, 2, DHT_MARKER);
 842	header_write(ctx, buffer, offset, 2, LH_DC);
 843	header_write(ctx, buffer, offset, 1, V4L2_JPEG_CHR_HT | V4L2_JPEG_DC_HT);
 844	for (i = 0 ; i < V4L2_JPEG_REF_HT_DC_LEN; i++)
 845		header_write(ctx, buffer, offset, 1, v4l2_jpeg_ref_table_chroma_dc_ht[i]);
 846
 847	header_write(ctx, buffer, offset, 2, DHT_MARKER);
 848	header_write(ctx, buffer, offset, 2, LH_AC);
 849	header_write(ctx, buffer, offset, 1, V4L2_JPEG_CHR_HT | V4L2_JPEG_AC_HT);
 850	for (i = 0 ; i < V4L2_JPEG_REF_HT_AC_LEN; i++)
 851		header_write(ctx, buffer, offset, 1, v4l2_jpeg_ref_table_chroma_ac_ht[i]);
 852}
 853
 854static void encode_frame_header(struct e5010_context *ctx, void *addr, unsigned int *offset)
 855{
 856	u8 *buffer = (u8 *)addr;
 857
 858	header_write(ctx, buffer, offset, 2, SOF_BASELINE_DCT);
 859	header_write(ctx, buffer, offset, 2, 8 + (3 * UC_NUM_COMP));
 860	header_write(ctx, buffer, offset, 1, PRECISION);
 861	header_write(ctx, buffer, offset, 2, ctx->out_queue.crop.height);
 862	header_write(ctx, buffer, offset, 2, ctx->out_queue.crop.width);
 863	header_write(ctx, buffer, offset, 1, UC_NUM_COMP);
 864
 865	/* Luma details */
 866	header_write(ctx, buffer, offset, 1, 1);
 867	if (ctx->out_queue.fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_422)
 868		header_write(ctx, buffer, offset, 1,
 869			     HORZ_SAMPLING_FACTOR | (VERT_SAMPLING_FACTOR_422));
 870	else
 871		header_write(ctx, buffer, offset, 1,
 872			     HORZ_SAMPLING_FACTOR | (VERT_SAMPLING_FACTOR_420));
 873	header_write(ctx, buffer, offset, 1, 0);
 874	/* Chroma details */
 875	header_write(ctx, buffer, offset, 1, 2);
 876	header_write(ctx, buffer, offset, 1, (HORZ_SAMPLING_FACTOR >> 1) | 1);
 877	header_write(ctx, buffer, offset, 1, 1);
 878	header_write(ctx, buffer, offset, 1, 3);
 879	header_write(ctx, buffer, offset, 1, (HORZ_SAMPLING_FACTOR >> 1) | 1);
 880	header_write(ctx, buffer, offset, 1, 1);
 881}
 882
 883static void jpg_encode_sos_header(struct e5010_context *ctx, void *addr, unsigned int *offset)
 884{
 885	u8 *buffer = (u8 *)addr;
 886	int i;
 887
 888	header_write(ctx, buffer, offset, 2, START_OF_SCAN);
 889	header_write(ctx, buffer, offset, 2, 6 + (COMPONENTS_IN_SCAN << 1));
 890	header_write(ctx, buffer, offset, 1, COMPONENTS_IN_SCAN);
 891
 892	for (i = 0; i < COMPONENTS_IN_SCAN; i++) {
 893		header_write(ctx, buffer, offset, 1, i + 1);
 894		if (i == 0)
 895			header_write(ctx, buffer, offset, 1, 0);
 896		else
 897			header_write(ctx, buffer, offset, 1, 17);
 898	}
 899
 900	header_write(ctx, buffer, offset, 1, 0);
 901	header_write(ctx, buffer, offset, 1, 63);
 902	header_write(ctx, buffer, offset, 1, 0);
 903}
 904
 905static void write_header(struct e5010_context *ctx, void *addr)
 906{
 907	unsigned int offset = 0;
 908
 909	encode_marker_segment(ctx, addr, &offset);
 910	encode_frame_header(ctx, addr, &offset);
 911	jpg_encode_sos_header(ctx, addr, &offset);
 912}
 913
 914static irqreturn_t e5010_irq(int irq, void *data)
 915{
 916	struct e5010_dev *e5010 = data;
 917	struct e5010_context *ctx;
 918	int output_size;
 919	struct vb2_v4l2_buffer *src_buf, *dst_buf;
 920	bool pic_done, out_addr_err;
 921
 922	spin_lock(&e5010->hw_lock);
 923	pic_done = e5010_hw_pic_done_irq(e5010->core_base);
 924	out_addr_err = e5010_hw_output_address_irq(e5010->core_base);
 925
 926	if (!pic_done && !out_addr_err) {
 927		spin_unlock(&e5010->hw_lock);
 928		return IRQ_NONE;
 929	}
 930
 931	ctx = v4l2_m2m_get_curr_priv(e5010->m2m_dev);
 932	if (WARN_ON(!ctx))
 933		goto job_unlock;
 934
 935	dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 936	src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
 937	if (!dst_buf || !src_buf) {
 938		v4l2_err(&e5010->v4l2_dev, "ctx: 0x%p No source or destination buffer\n", ctx);
 939		goto job_unlock;
 940	}
 941
 942	if (out_addr_err) {
 943		e5010_hw_clear_output_error(e5010->core_base, 1);
 944		v4l2_warn(&e5010->v4l2_dev,
 945			  "ctx: 0x%p Output bitstream size exceeded max size\n", ctx);
 946		v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
 947		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, dst_buf->planes[0].length);
 948		v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
 949		if (v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx, src_buf)) {
 950			dst_buf->flags |= V4L2_BUF_FLAG_LAST;
 951			v4l2_m2m_mark_stopped(ctx->fh.m2m_ctx);
 952			v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event);
 953			dprintk(e5010, 2, "ctx: 0x%p Sending EOS\n", ctx);
 954		}
 955	}
 956
 957	if (pic_done) {
 958		e5010_hw_clear_picture_done(e5010->core_base, 1);
 959		dprintk(e5010, 3, "ctx: 0x%p Got output bitstream of size %d bytes\n",
 960			ctx, readl(e5010->core_base + JASPER_OUTPUT_SIZE_OFFSET));
 961
 962		if (v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx, src_buf)) {
 963			dst_buf->flags |= V4L2_BUF_FLAG_LAST;
 964			v4l2_m2m_mark_stopped(ctx->fh.m2m_ctx);
 965			v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event);
 966			dprintk(e5010, 2, "ctx: 0x%p Sending EOS\n", ctx);
 967		}
 968		v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
 969		output_size = e5010_hw_get_output_size(e5010->core_base);
 970		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, output_size + HEADER_SIZE);
 971		v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
 972		dprintk(e5010, 3,
 973			"ctx: 0x%p frame done for dst_buf->sequence: %d src_buf->sequence: %d\n",
 974			ctx, dst_buf->sequence, src_buf->sequence);
 975	}
 976
 977	v4l2_m2m_job_finish(e5010->m2m_dev, ctx->fh.m2m_ctx);
 978	dprintk(e5010, 3, "ctx: 0x%p Finish job\n", ctx);
 979
 980job_unlock:
 981	spin_unlock(&e5010->hw_lock);
 982	return IRQ_HANDLED;
 983}
 984
 985static int e5010_init_device(struct e5010_dev *e5010)
 986{
 987	int ret = 0;
 988
 989	/*TODO: Set MMU in bypass mode until support for the same is added in driver*/
 990	e5010_hw_bypass_mmu(e5010->mmu_base, 1);
 991
 992	if (e5010_hw_enable_auto_clock_gating(e5010->core_base, 1))
 993		v4l2_warn(&e5010->v4l2_dev, "failed to enable auto clock gating\n");
 994
 995	if (e5010_hw_enable_manual_clock_gating(e5010->core_base, 0))
 996		v4l2_warn(&e5010->v4l2_dev, "failed to disable manual clock gating\n");
 997
 998	if (e5010_hw_enable_crc_check(e5010->core_base, 0))
 999		v4l2_warn(&e5010->v4l2_dev, "failed to disable CRC check\n");
1000
1001	if (e5010_hw_enable_output_address_error_irq(e5010->core_base, 1))
1002		v4l2_err(&e5010->v4l2_dev, "failed to enable Output Address Error interrupts\n");
1003
1004	ret = e5010_hw_set_input_source_to_memory(e5010->core_base, 1);
1005	if (ret) {
1006		v4l2_err(&e5010->v4l2_dev, "failed to set input source to memory\n");
1007		return ret;
1008	}
1009
1010	ret = e5010_hw_enable_picture_done_irq(e5010->core_base, 1);
1011	if (ret)
1012		v4l2_err(&e5010->v4l2_dev, "failed to enable Picture Done interrupts\n");
1013
1014	return ret;
1015}
1016
1017static int e5010_probe(struct platform_device *pdev)
1018{
1019	struct e5010_dev *e5010;
1020	int irq, ret = 0;
1021	struct device *dev = &pdev->dev;
1022
1023	ret = dma_set_mask(dev, DMA_BIT_MASK(32));
1024	if (ret)
1025		return dev_err_probe(dev, ret, "32-bit consistent DMA enable failed\n");
1026
1027	e5010 = devm_kzalloc(dev, sizeof(*e5010), GFP_KERNEL);
1028	if (!e5010)
1029		return -ENOMEM;
1030
1031	platform_set_drvdata(pdev, e5010);
1032
1033	e5010->dev = dev;
1034
1035	mutex_init(&e5010->mutex);
1036	spin_lock_init(&e5010->hw_lock);
1037
1038	e5010->vdev = video_device_alloc();
1039	if (!e5010->vdev) {
1040		dev_err(dev, "failed to allocate video device\n");
1041		return -ENOMEM;
1042	}
1043
1044	snprintf(e5010->vdev->name, sizeof(e5010->vdev->name), "%s", E5010_MODULE_NAME);
1045	e5010->vdev->fops = &e5010_fops;
1046	e5010->vdev->ioctl_ops = &e5010_ioctl_ops;
1047	e5010->vdev->minor = -1;
1048	e5010->vdev->release = video_device_release;
1049	e5010->vdev->vfl_dir = VFL_DIR_M2M;
1050	e5010->vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
1051	e5010->vdev->v4l2_dev = &e5010->v4l2_dev;
1052	e5010->vdev->lock = &e5010->mutex;
1053
1054	ret = v4l2_device_register(dev, &e5010->v4l2_dev);
1055	if (ret) {
1056		dev_err_probe(dev, ret, "failed to register v4l2 device\n");
1057		goto fail_after_video_device_alloc;
1058	}
1059
1060
1061	e5010->m2m_dev = v4l2_m2m_init(&e5010_m2m_ops);
1062	if (IS_ERR(e5010->m2m_dev)) {
1063		ret = PTR_ERR(e5010->m2m_dev);
1064		e5010->m2m_dev = NULL;
1065		dev_err_probe(dev, ret, "failed to init mem2mem device\n");
1066		goto fail_after_v4l2_register;
1067	}
1068
1069	video_set_drvdata(e5010->vdev, e5010);
1070
1071	e5010->core_base = devm_platform_ioremap_resource_byname(pdev, "core");
1072	if (IS_ERR(e5010->core_base)) {
1073		ret = PTR_ERR(e5010->core_base);
1074		dev_err_probe(dev, ret, "Missing 'core' resources area\n");
1075		goto fail_after_v4l2_register;
1076	}
1077
1078	e5010->mmu_base = devm_platform_ioremap_resource_byname(pdev, "mmu");
1079	if (IS_ERR(e5010->mmu_base)) {
1080		ret = PTR_ERR(e5010->mmu_base);
1081		dev_err_probe(dev, ret, "Missing 'mmu' resources area\n");
1082		goto fail_after_v4l2_register;
1083	}
1084
1085	e5010->last_context_run = NULL;
1086
1087	irq = platform_get_irq(pdev, 0);
1088	ret = devm_request_irq(dev, irq, e5010_irq, 0,
1089			       E5010_MODULE_NAME, e5010);
1090	if (ret) {
1091		dev_err_probe(dev, ret, "failed to register IRQ %d\n", irq);
1092		goto fail_after_v4l2_register;
1093	}
1094
1095	e5010->clk = devm_clk_get(dev, NULL);
1096	if (IS_ERR(e5010->clk)) {
1097		ret = PTR_ERR(e5010->clk);
1098		dev_err_probe(dev, ret, "failed to get clock\n");
1099		goto fail_after_v4l2_register;
1100	}
1101
1102	pm_runtime_enable(dev);
1103
1104	ret = video_register_device(e5010->vdev, VFL_TYPE_VIDEO, 0);
1105	if (ret) {
1106		dev_err_probe(dev, ret, "failed to register video device\n");
1107		goto fail_after_video_register_device;
1108	}
1109
1110	v4l2_info(&e5010->v4l2_dev, "Device registered as /dev/video%d\n",
1111		  e5010->vdev->num);
1112
1113	return 0;
1114
1115fail_after_video_register_device:
1116	v4l2_m2m_release(e5010->m2m_dev);
1117fail_after_v4l2_register:
1118	v4l2_device_unregister(&e5010->v4l2_dev);
1119fail_after_video_device_alloc:
1120	video_device_release(e5010->vdev);
1121	return ret;
1122}
1123
1124static void e5010_remove(struct platform_device *pdev)
1125{
1126	struct e5010_dev *e5010 = platform_get_drvdata(pdev);
1127
1128	pm_runtime_disable(e5010->dev);
1129	video_unregister_device(e5010->vdev);
1130	v4l2_m2m_release(e5010->m2m_dev);
1131	v4l2_device_unregister(&e5010->v4l2_dev);
1132}
1133
1134static void e5010_vb2_buffers_return(struct vb2_queue *q, enum vb2_buffer_state state)
1135{
1136	struct vb2_v4l2_buffer *vbuf;
1137	struct e5010_context *ctx = vb2_get_drv_priv(q);
1138
1139	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
1140		while ((vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx))) {
1141			dprintk(ctx->e5010, 2, "ctx: 0x%p, buf type %s | index %d\n",
1142				ctx, type_name(vbuf->vb2_buf.type), vbuf->vb2_buf.index);
1143			v4l2_m2m_buf_done(vbuf, state);
1144		}
1145	} else {
1146		while ((vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx))) {
1147			dprintk(ctx->e5010, 2, "ctx: 0x%p, buf type %s | index %d\n",
1148				ctx, type_name(vbuf->vb2_buf.type), vbuf->vb2_buf.index);
1149			vb2_set_plane_payload(&vbuf->vb2_buf, 0, 0);
1150			v4l2_m2m_buf_done(vbuf, state);
1151		}
1152	}
1153}
1154
1155static int e5010_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes,
1156			     unsigned int sizes[], struct device *alloc_devs[])
1157{
1158	struct e5010_context *ctx = vb2_get_drv_priv(vq);
1159	struct e5010_q_data *queue;
1160	int i;
1161
1162	queue = get_queue(ctx, vq->type);
1163
1164	if (*nplanes) {
1165		if (*nplanes != queue->fmt->num_planes)
1166			return -EINVAL;
1167		for (i = 0; i < *nplanes; i++) {
1168			if (sizes[i] < queue->sizeimage[i])
1169				return -EINVAL;
1170		}
1171		return 0;
1172	}
1173
1174	*nplanes = queue->fmt->num_planes;
1175	for (i = 0; i < *nplanes; i++)
1176		sizes[i] = queue->sizeimage[i];
1177
1178	dprintk(ctx->e5010, 2,
1179		"ctx: 0x%p, type %s, buffer(s): %d, planes %d, plane1: bytes %d plane2: %d bytes\n",
1180		ctx, type_name(vq->type), *nbuffers, *nplanes, sizes[0], sizes[1]);
1181
1182	return 0;
1183}
1184
1185static void e5010_buf_finish(struct vb2_buffer *vb)
1186{
1187	struct e5010_context *ctx = vb2_get_drv_priv(vb->vb2_queue);
1188	void *d_addr;
1189
1190	if (vb->state != VB2_BUF_STATE_DONE || V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type))
1191		return;
1192
1193	d_addr = vb2_plane_vaddr(vb, 0);
1194	write_header(ctx, d_addr);
1195}
1196
1197static int e5010_buf_out_validate(struct vb2_buffer *vb)
1198{
1199	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1200	struct e5010_context *ctx = vb2_get_drv_priv(vb->vb2_queue);
1201
1202	if (vbuf->field != V4L2_FIELD_NONE)
1203		dprintk(ctx->e5010, 1, "ctx: 0x%p, field isn't supported\n", ctx);
1204
1205	vbuf->field = V4L2_FIELD_NONE;
1206
1207	return 0;
1208}
1209
1210static int e5010_buf_prepare(struct vb2_buffer *vb)
1211{
1212	struct e5010_context *ctx = vb2_get_drv_priv(vb->vb2_queue);
1213	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1214	struct e5010_q_data *queue;
1215	int i;
1216
1217	vbuf->field = V4L2_FIELD_NONE;
1218
1219	queue = get_queue(ctx, vb->vb2_queue->type);
1220
1221	for (i = 0; i < queue->fmt->num_planes; i++) {
1222		if (vb2_plane_size(vb, i) < (unsigned long)queue->sizeimage[i]) {
1223			v4l2_err(&ctx->e5010->v4l2_dev, "plane %d too small (%lu < %lu)", i,
1224				 vb2_plane_size(vb, i), (unsigned long)queue->sizeimage[i]);
1225
1226			return -EINVAL;
1227		}
1228	}
1229
1230	if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type)) {
1231		vb2_set_plane_payload(vb, 0, 0);
1232		vb2_set_plane_payload(vb, 1, 0);
1233	}
1234
1235	return 0;
1236}
1237
1238static void e5010_buf_queue(struct vb2_buffer *vb)
1239{
1240	struct e5010_context *ctx = vb2_get_drv_priv(vb->vb2_queue);
1241	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1242
1243	if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type) &&
1244	    vb2_is_streaming(vb->vb2_queue) &&
1245	    v4l2_m2m_dst_buf_is_last(ctx->fh.m2m_ctx)) {
1246		struct e5010_q_data *queue = get_queue(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
1247
1248		vbuf->sequence = queue->sequence++;
1249		v4l2_m2m_last_buffer_done(ctx->fh.m2m_ctx, vbuf);
1250		v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event);
1251		return;
1252	}
1253
1254	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
1255}
1256
1257static int e5010_encoder_cmd(struct file *file, void *priv,
1258			     struct v4l2_encoder_cmd *cmd)
1259{
1260	struct e5010_context *ctx = to_e5010_context(file);
1261	int ret;
1262	struct vb2_queue *cap_vq;
1263
1264	cap_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
1265
1266	ret = v4l2_m2m_ioctl_try_encoder_cmd(file, &ctx->fh, cmd);
1267	if (ret < 0)
1268		return ret;
1269
1270	if (!vb2_is_streaming(v4l2_m2m_get_src_vq(ctx->fh.m2m_ctx)) ||
1271	    !vb2_is_streaming(v4l2_m2m_get_dst_vq(ctx->fh.m2m_ctx)))
1272		return 0;
1273
1274	ret = v4l2_m2m_ioctl_encoder_cmd(file, &ctx->fh, cmd);
1275	if (ret < 0)
1276		return ret;
1277
1278	if (cmd->cmd == V4L2_ENC_CMD_STOP &&
1279	    v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
1280		v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event);
1281
1282	if (cmd->cmd == V4L2_ENC_CMD_START &&
1283	    v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
1284		vb2_clear_last_buffer_dequeued(cap_vq);
1285
1286	return 0;
1287}
1288
1289static int e5010_start_streaming(struct vb2_queue *q, unsigned int count)
1290{
1291	struct e5010_context *ctx = vb2_get_drv_priv(q);
1292	int ret;
1293
1294	struct e5010_q_data *queue = get_queue(ctx, q->type);
1295
1296	v4l2_m2m_update_start_streaming_state(ctx->fh.m2m_ctx, q);
1297	queue->sequence = 0;
1298
1299	ret = pm_runtime_resume_and_get(ctx->e5010->dev);
1300	if (ret < 0) {
1301		v4l2_err(&ctx->e5010->v4l2_dev, "failed to power up jpeg\n");
1302		goto fail;
1303	}
1304
1305	ret = e5010_init_device(ctx->e5010);
1306	if (ret) {
1307		v4l2_err(&ctx->e5010->v4l2_dev, "failed to Enable e5010 device\n");
1308		goto fail;
1309	}
1310
1311	return 0;
1312
1313fail:
1314	e5010_vb2_buffers_return(q, VB2_BUF_STATE_QUEUED);
1315
1316	return ret;
1317}
1318
1319static void e5010_stop_streaming(struct vb2_queue *q)
1320{
1321	struct e5010_context *ctx = vb2_get_drv_priv(q);
1322
1323	e5010_vb2_buffers_return(q, VB2_BUF_STATE_ERROR);
1324
1325	if (V4L2_TYPE_IS_OUTPUT(q->type))
1326		v4l2_m2m_update_stop_streaming_state(ctx->fh.m2m_ctx, q);
1327
1328	if (V4L2_TYPE_IS_OUTPUT(q->type) &&
1329	    v4l2_m2m_has_stopped(ctx->fh.m2m_ctx)) {
1330		v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event);
1331	}
1332
1333	pm_runtime_put_sync(ctx->e5010->dev);
1334}
1335
1336static void e5010_device_run(void *priv)
1337{
1338	struct e5010_context *ctx = priv;
1339	struct e5010_dev *e5010 = ctx->e5010;
1340	struct vb2_v4l2_buffer *s_vb, *d_vb;
1341	u32 reg = 0;
1342	int ret = 0, luma_crop_offset = 0, chroma_crop_offset = 0;
1343	unsigned long flags;
1344	int num_planes = ctx->out_queue.fmt->num_planes;
1345
1346	spin_lock_irqsave(&e5010->hw_lock, flags);
1347	s_vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
1348	WARN_ON(!s_vb);
1349	d_vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
1350	WARN_ON(!d_vb);
1351	if (!s_vb || !d_vb)
1352		goto no_ready_buf_err;
1353
1354	s_vb->sequence = ctx->out_queue.sequence++;
1355	d_vb->sequence = ctx->cap_queue.sequence++;
1356
1357	v4l2_m2m_buf_copy_metadata(s_vb, d_vb);
1358
1359	if (ctx != e5010->last_context_run || ctx->update_qp) {
1360		dprintk(e5010, 1, "ctx updated: 0x%p -> 0x%p, updating qp tables\n",
1361			e5010->last_context_run, ctx);
1362		ret = update_qp_tables(ctx);
1363	}
1364
1365	if (ret) {
1366		ctx->update_qp = true;
1367		v4l2_err(&e5010->v4l2_dev, "failed to update QP tables\n");
1368		goto device_busy_err;
1369	} else {
1370		e5010->last_context_run = ctx;
1371		ctx->update_qp = false;
1372	}
1373
1374	/* Set I/O Buffer addresses */
1375	reg = (u32)vb2_dma_contig_plane_dma_addr(&s_vb->vb2_buf, 0);
1376
1377	if (ctx->out_queue.crop_set) {
1378		luma_crop_offset = ctx->out_queue.bytesperline[0] * ctx->out_queue.crop.top +
1379				   ctx->out_queue.crop.left;
1380
1381		if (ctx->out_queue.fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_422) {
1382			chroma_crop_offset =
1383				ctx->out_queue.bytesperline[0] * ctx->out_queue.crop.top
1384				+ ctx->out_queue.crop.left;
1385		} else {
1386			chroma_crop_offset =
1387				ctx->out_queue.bytesperline[0] * ctx->out_queue.crop.top / 2
1388				+ ctx->out_queue.crop.left;
1389		}
1390
1391		dprintk(e5010, 1, "Luma crop offset : %x, chroma crop offset : %x\n",
1392			luma_crop_offset, chroma_crop_offset);
1393	}
1394
1395	ret = e5010_hw_set_input_luma_addr(e5010->core_base, reg + luma_crop_offset);
1396	if (ret || !reg) {
1397		v4l2_err(&e5010->v4l2_dev, "failed to set input luma address\n");
1398		goto device_busy_err;
1399	}
1400
1401	if (num_planes == 1)
1402		reg += (ctx->out_queue.bytesperline[0]) * (ctx->out_queue.height);
1403	else
1404		reg = (u32)vb2_dma_contig_plane_dma_addr(&s_vb->vb2_buf, 1);
1405
1406	dprintk(e5010, 3,
1407		"ctx: 0x%p, luma_addr: 0x%x, chroma_addr: 0x%x, out_addr: 0x%x\n",
1408		ctx, (u32)vb2_dma_contig_plane_dma_addr(&s_vb->vb2_buf, 0) + luma_crop_offset,
1409		reg + chroma_crop_offset, (u32)vb2_dma_contig_plane_dma_addr(&d_vb->vb2_buf, 0));
1410
1411	dprintk(e5010, 3,
1412		"ctx: 0x%p, buf indices: src_index: %d, dst_index: %d\n",
1413		ctx, s_vb->vb2_buf.index, d_vb->vb2_buf.index);
1414
1415	ret = e5010_hw_set_input_chroma_addr(e5010->core_base, reg + chroma_crop_offset);
1416	if (ret || !reg) {
1417		v4l2_err(&e5010->v4l2_dev, "failed to set input chroma address\n");
1418		goto device_busy_err;
1419	}
1420
1421	reg = (u32)vb2_dma_contig_plane_dma_addr(&d_vb->vb2_buf, 0);
1422	reg += HEADER_SIZE;
1423	ret = e5010_hw_set_output_base_addr(e5010->core_base, reg);
1424	if (ret || !reg) {
1425		v4l2_err(&e5010->v4l2_dev, "failed to set output base address\n");
1426		goto device_busy_err;
1427	}
1428
1429	/* Set input settings */
1430	ret = e5010_hw_set_horizontal_size(e5010->core_base, ctx->out_queue.crop.width - 1);
1431	if (ret) {
1432		v4l2_err(&e5010->v4l2_dev, "failed to set input width\n");
1433		goto device_busy_err;
1434	}
1435
1436	ret = e5010_hw_set_vertical_size(e5010->core_base, ctx->out_queue.crop.height - 1);
1437	if (ret) {
1438		v4l2_err(&e5010->v4l2_dev, "failed to set input width\n");
1439		goto device_busy_err;
1440	}
1441
1442	ret = e5010_hw_set_luma_stride(e5010->core_base, ctx->out_queue.bytesperline[0]);
1443	if (ret) {
1444		v4l2_err(&e5010->v4l2_dev, "failed to set luma stride\n");
1445		goto device_busy_err;
1446	}
1447
1448	ret = e5010_hw_set_chroma_stride(e5010->core_base, ctx->out_queue.bytesperline[0]);
1449	if (ret) {
1450		v4l2_err(&e5010->v4l2_dev, "failed to set chroma stride\n");
1451		goto device_busy_err;
1452	}
1453
1454	ret = e5010_set_input_subsampling(e5010->core_base, ctx->out_queue.fmt->subsampling);
1455	if (ret) {
1456		v4l2_err(&e5010->v4l2_dev, "failed to set input subsampling\n");
1457		goto device_busy_err;
1458	}
1459
1460	ret = e5010_hw_set_chroma_order(e5010->core_base, ctx->out_queue.fmt->chroma_order);
1461	if (ret) {
1462		v4l2_err(&e5010->v4l2_dev, "failed to set chroma order\n");
1463		goto device_busy_err;
1464	}
1465
1466	e5010_hw_set_output_max_size(e5010->core_base, d_vb->planes[0].length);
1467	e5010_hw_encode_start(e5010->core_base, 1);
1468
1469	spin_unlock_irqrestore(&e5010->hw_lock, flags);
1470
1471	return;
1472
1473device_busy_err:
1474	e5010_reset(e5010->dev, e5010->core_base, e5010->mmu_base);
1475
1476no_ready_buf_err:
1477	if (s_vb) {
1478		v4l2_m2m_src_buf_remove_by_buf(ctx->fh.m2m_ctx, s_vb);
1479		v4l2_m2m_buf_done(s_vb, VB2_BUF_STATE_ERROR);
1480	}
1481
1482	if (d_vb) {
1483		v4l2_m2m_dst_buf_remove_by_buf(ctx->fh.m2m_ctx, d_vb);
1484		/* Payload set to 1 since 0 payload can trigger EOS */
1485		vb2_set_plane_payload(&d_vb->vb2_buf, 0, 1);
1486		v4l2_m2m_buf_done(d_vb, VB2_BUF_STATE_ERROR);
1487	}
1488	v4l2_m2m_job_finish(e5010->m2m_dev, ctx->fh.m2m_ctx);
1489	spin_unlock_irqrestore(&e5010->hw_lock, flags);
1490}
1491
1492#ifdef CONFIG_PM
1493static int e5010_runtime_resume(struct device *dev)
1494{
1495	struct e5010_dev *e5010 = dev_get_drvdata(dev);
1496	int ret;
1497
1498	ret = clk_prepare_enable(e5010->clk);
1499	if (ret < 0) {
1500		v4l2_err(&e5010->v4l2_dev, "failed to enable clock\n");
1501		return ret;
1502	}
1503
1504	return 0;
1505}
1506
1507static int e5010_runtime_suspend(struct device *dev)
1508{
1509	struct e5010_dev *e5010 = dev_get_drvdata(dev);
1510
1511	clk_disable_unprepare(e5010->clk);
1512
1513	return 0;
1514}
1515#endif
1516
1517#ifdef CONFIG_PM_SLEEP
1518static int e5010_suspend(struct device *dev)
1519{
1520	struct e5010_dev *e5010 = dev_get_drvdata(dev);
1521
1522	v4l2_m2m_suspend(e5010->m2m_dev);
1523
1524	return pm_runtime_force_suspend(dev);
1525}
1526
1527static int e5010_resume(struct device *dev)
1528{
1529	struct e5010_dev *e5010 = dev_get_drvdata(dev);
1530	int ret;
1531
1532	ret = pm_runtime_force_resume(dev);
1533	if (ret < 0)
1534		return ret;
1535
1536	ret = e5010_init_device(e5010);
1537	if (ret) {
1538		dev_err(dev, "Failed to re-enable e5010 device\n");
1539		return ret;
1540	}
1541
1542	v4l2_m2m_resume(e5010->m2m_dev);
1543
1544	return ret;
1545}
1546#endif
1547
1548static const struct dev_pm_ops	e5010_pm_ops = {
1549	SET_RUNTIME_PM_OPS(e5010_runtime_suspend,
1550			   e5010_runtime_resume, NULL)
1551	SET_SYSTEM_SLEEP_PM_OPS(e5010_suspend, e5010_resume)
1552};
1553
1554static const struct v4l2_ioctl_ops e5010_ioctl_ops = {
1555	.vidioc_querycap = e5010_querycap,
1556
1557	.vidioc_enum_fmt_vid_cap = e5010_enum_fmt,
1558	.vidioc_g_fmt_vid_cap_mplane = e5010_g_fmt,
1559	.vidioc_try_fmt_vid_cap_mplane = e5010_try_fmt,
1560	.vidioc_s_fmt_vid_cap_mplane = e5010_s_fmt,
1561
1562	.vidioc_enum_fmt_vid_out = e5010_enum_fmt,
1563	.vidioc_g_fmt_vid_out_mplane = e5010_g_fmt,
1564	.vidioc_try_fmt_vid_out_mplane = e5010_try_fmt,
1565	.vidioc_s_fmt_vid_out_mplane = e5010_s_fmt,
1566
1567	.vidioc_g_selection = e5010_g_selection,
1568	.vidioc_s_selection = e5010_s_selection,
1569
1570	.vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
1571	.vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
1572	.vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
1573	.vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
1574	.vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
1575	.vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
1576	.vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
1577
1578	.vidioc_streamon = v4l2_m2m_ioctl_streamon,
1579	.vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
1580	.vidioc_log_status = v4l2_ctrl_log_status,
1581
1582	.vidioc_subscribe_event = e5010_subscribe_event,
1583	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1584	.vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd,
1585	.vidioc_encoder_cmd = e5010_encoder_cmd,
1586
1587	.vidioc_enum_framesizes = e5010_enum_framesizes,
1588};
1589
1590static const struct vb2_ops e5010_video_ops = {
1591	.queue_setup = e5010_queue_setup,
1592	.buf_queue = e5010_buf_queue,
1593	.buf_finish = e5010_buf_finish,
1594	.buf_prepare = e5010_buf_prepare,
1595	.buf_out_validate = e5010_buf_out_validate,
1596	.start_streaming = e5010_start_streaming,
1597	.stop_streaming = e5010_stop_streaming,
1598};
1599
1600static const struct v4l2_file_operations e5010_fops = {
1601	.owner = THIS_MODULE,
1602	.open = e5010_open,
1603	.release = e5010_release,
1604	.poll = v4l2_m2m_fop_poll,
1605	.unlocked_ioctl = video_ioctl2,
1606	.mmap = v4l2_m2m_fop_mmap,
1607};
1608
1609static const struct v4l2_m2m_ops e5010_m2m_ops = {
1610	.device_run = e5010_device_run,
1611};
1612
1613static const struct of_device_id e5010_of_match[] = {
1614	{.compatible = "img,e5010-jpeg-enc"},   { /* end */},
1615};
1616MODULE_DEVICE_TABLE(of, e5010_of_match);
1617
1618static struct platform_driver e5010_driver = {
1619	.probe = e5010_probe,
1620	.remove = e5010_remove,
1621	.driver = {
1622		.name = E5010_MODULE_NAME,
1623		.of_match_table = e5010_of_match,
1624		.pm = &e5010_pm_ops,
1625	},
1626};
1627module_platform_driver(e5010_driver);
1628
1629MODULE_LICENSE("GPL");
1630MODULE_DESCRIPTION("Imagination E5010 JPEG encoder driver");
~/ Read-only file preview.