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 */
36 static const struct of_device_id e5010_of_match[];
37
38 static const struct v4l2_file_operations e5010_fops;
39
40 static const struct v4l2_ioctl_ops e5010_ioctl_ops;
41
42 static const struct vb2_ops e5010_video_ops;
43
44 static const struct v4l2_m2m_ops e5010_m2m_ops;
45
46 static 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
131 static unsigned int debug;
132 module_param(debug, uint, 0644);
133 MODULE_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
138 static const struct v4l2_event e5010_eos_event = {
139 .type = V4L2_EVENT_EOS
140 };
141
type_name(enum v4l2_buf_type type)142 static 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
get_queue(struct e5010_context * ctx,enum v4l2_buf_type type)154 static 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
calculate_qp_tables(struct e5010_context * ctx)159 static 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
update_qp_tables(struct e5010_context * ctx)190 static 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
e5010_set_input_subsampling(void __iomem * core_base,int subsampling)219 static 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
e5010_querycap(struct file * file,void * priv,struct v4l2_capability * cap)231 static 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
find_format(struct v4l2_format * f)239 static 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
e5010_enum_fmt(struct file * file,void * priv,struct v4l2_fmtdesc * f)252 static 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
e5010_g_fmt(struct file * file,void * priv,struct v4l2_format * f)280 static 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
e5010_jpeg_try_fmt(struct v4l2_format * f,struct e5010_context * ctx)318 static 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
e5010_try_fmt(struct file * file,void * priv,struct v4l2_format * f)381 static 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
e5010_s_fmt(struct file * file,void * priv,struct v4l2_format * f)388 static 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
e5010_enum_framesizes(struct file * file,void * priv,struct v4l2_frmsizeenum * fsize)435 static 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
e5010_g_selection(struct file * file,void * fh,struct v4l2_selection * s)461 static 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
e5010_s_selection(struct file * file,void * fh,struct v4l2_selection * s)489 static 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
e5010_subscribe_event(struct v4l2_fh * fh,const struct v4l2_event_subscription * sub)561 static 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
queue_init(void * priv,struct vb2_queue * src_vq,struct vb2_queue * dst_vq)575 static 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
e5010_s_ctrl(struct v4l2_ctrl * ctrl)618 static 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
637 static const struct v4l2_ctrl_ops e5010_ctrl_ops = {
638 .s_ctrl = e5010_s_ctrl,
639 };
640
e5010_encode_ctrls(struct e5010_context * ctx)641 static 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
e5010_ctrls_setup(struct e5010_context * ctx)647 static 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
e5010_jpeg_set_default_params(struct e5010_context * ctx)669 static 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
e5010_open(struct file * file)724 static 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_obj(*ctx);
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
765 err_ctrls_setup:
766 v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
767 exit:
768 v4l2_fh_del(&ctx->fh, file);
769 v4l2_fh_exit(&ctx->fh);
770 mutex_unlock(&e5010->mutex);
771 free:
772 kfree(ctx);
773 return ret;
774 }
775
e5010_release(struct file * file)776 static 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
header_write(struct e5010_context * ctx,u8 * addr,unsigned int * offset,unsigned int no_bytes,unsigned long bits)793 static 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
encode_marker_segment(struct e5010_context * ctx,void * addr,unsigned int * offset)811 static 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
encode_frame_header(struct e5010_context * ctx,void * addr,unsigned int * offset)854 static 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
jpg_encode_sos_header(struct e5010_context * ctx,void * addr,unsigned int * offset)883 static 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
write_header(struct e5010_context * ctx,void * addr)905 static 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
e5010_irq(int irq,void * data)914 static 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
980 job_unlock:
981 spin_unlock(&e5010->hw_lock);
982 return IRQ_HANDLED;
983 }
984
e5010_init_device(struct e5010_dev * e5010)985 static 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
e5010_probe(struct platform_device * pdev)1017 static 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
1115 fail_after_video_register_device:
1116 v4l2_m2m_release(e5010->m2m_dev);
1117 fail_after_v4l2_register:
1118 v4l2_device_unregister(&e5010->v4l2_dev);
1119 fail_after_video_device_alloc:
1120 video_device_release(e5010->vdev);
1121 return ret;
1122 }
1123
e5010_remove(struct platform_device * pdev)1124 static 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
e5010_vb2_buffers_return(struct vb2_queue * q,enum vb2_buffer_state state)1134 static 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
e5010_queue_setup(struct vb2_queue * vq,unsigned int * nbuffers,unsigned int * nplanes,unsigned int sizes[],struct device * alloc_devs[])1155 static 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
e5010_buf_finish(struct vb2_buffer * vb)1185 static 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
e5010_buf_out_validate(struct vb2_buffer * vb)1197 static 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
e5010_buf_prepare(struct vb2_buffer * vb)1210 static 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
e5010_buf_queue(struct vb2_buffer * vb)1238 static 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
e5010_encoder_cmd(struct file * file,void * priv,struct v4l2_encoder_cmd * cmd)1257 static 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
e5010_start_streaming(struct vb2_queue * q,unsigned int count)1289 static 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
1313 fail:
1314 e5010_vb2_buffers_return(q, VB2_BUF_STATE_QUEUED);
1315
1316 return ret;
1317 }
1318
e5010_stop_streaming(struct vb2_queue * q)1319 static 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
e5010_device_run(void * priv)1336 static 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
1473 device_busy_err:
1474 e5010_reset(e5010->dev, e5010->core_base, e5010->mmu_base);
1475
1476 no_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
e5010_runtime_resume(struct device * dev)1493 static 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
e5010_runtime_suspend(struct device * dev)1507 static 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
e5010_suspend(struct device * dev)1518 static 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
e5010_resume(struct device * dev)1527 static 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
1548 static 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
1554 static 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
1590 static 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
1600 static 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
1609 static const struct v4l2_m2m_ops e5010_m2m_ops = {
1610 .device_run = e5010_device_run,
1611 };
1612
1613 static const struct of_device_id e5010_of_match[] = {
1614 {.compatible = "img,e5010-jpeg-enc"}, { /* end */},
1615 };
1616 MODULE_DEVICE_TABLE(of, e5010_of_match);
1617
1618 static 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 };
1627 module_platform_driver(e5010_driver);
1628
1629 MODULE_LICENSE("GPL");
1630 MODULE_DESCRIPTION("Imagination E5010 JPEG encoder driver");
1631