tracing: Add __string_src() helper to help compilers not to get confused
[sfrench/cifs-2.6.git] / drivers / staging / media / imx / imx-media-csc-scaler.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * i.MX IPUv3 IC PP mem2mem CSC/Scaler driver
4  *
5  * Copyright (C) 2011 Pengutronix, Sascha Hauer
6  * Copyright (C) 2018 Pengutronix, Philipp Zabel
7  */
8 #include <linux/module.h>
9 #include <linux/delay.h>
10 #include <linux/fs.h>
11 #include <linux/sched.h>
12 #include <linux/slab.h>
13 #include <video/imx-ipu-v3.h>
14 #include <video/imx-ipu-image-convert.h>
15
16 #include <media/media-device.h>
17 #include <media/v4l2-ctrls.h>
18 #include <media/v4l2-event.h>
19 #include <media/v4l2-mem2mem.h>
20 #include <media/v4l2-device.h>
21 #include <media/v4l2-ioctl.h>
22 #include <media/videobuf2-dma-contig.h>
23
24 #include "imx-media.h"
25
26 #define fh_to_ctx(__fh) container_of(__fh, struct ipu_csc_scaler_ctx, fh)
27
28 #define IMX_CSC_SCALER_NAME "imx-csc-scaler"
29
30 enum {
31         V4L2_M2M_SRC = 0,
32         V4L2_M2M_DST = 1,
33 };
34
35 struct ipu_csc_scaler_priv {
36         struct imx_media_video_dev      vdev;
37
38         struct v4l2_m2m_dev             *m2m_dev;
39         struct device                   *dev;
40
41         struct imx_media_dev            *md;
42
43         struct mutex                    mutex;  /* mem2mem device mutex */
44 };
45
46 #define vdev_to_priv(v) container_of(v, struct ipu_csc_scaler_priv, vdev)
47
48 /* Per-queue, driver-specific private data */
49 struct ipu_csc_scaler_q_data {
50         struct v4l2_pix_format          cur_fmt;
51         struct v4l2_rect                rect;
52 };
53
54 struct ipu_csc_scaler_ctx {
55         struct ipu_csc_scaler_priv      *priv;
56
57         struct v4l2_fh                  fh;
58         struct ipu_csc_scaler_q_data    q_data[2];
59         struct ipu_image_convert_ctx    *icc;
60
61         struct v4l2_ctrl_handler        ctrl_hdlr;
62         int                             rotate;
63         bool                            hflip;
64         bool                            vflip;
65         enum ipu_rotate_mode            rot_mode;
66         unsigned int                    sequence;
67 };
68
69 static struct ipu_csc_scaler_q_data *get_q_data(struct ipu_csc_scaler_ctx *ctx,
70                                                 enum v4l2_buf_type type)
71 {
72         if (V4L2_TYPE_IS_OUTPUT(type))
73                 return &ctx->q_data[V4L2_M2M_SRC];
74         else
75                 return &ctx->q_data[V4L2_M2M_DST];
76 }
77
78 /*
79  * mem2mem callbacks
80  */
81
82 static void job_abort(void *_ctx)
83 {
84         struct ipu_csc_scaler_ctx *ctx = _ctx;
85
86         if (ctx->icc)
87                 ipu_image_convert_abort(ctx->icc);
88 }
89
90 static void ipu_ic_pp_complete(struct ipu_image_convert_run *run, void *_ctx)
91 {
92         struct ipu_csc_scaler_ctx *ctx = _ctx;
93         struct ipu_csc_scaler_priv *priv = ctx->priv;
94         struct vb2_v4l2_buffer *src_buf, *dst_buf;
95
96         src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
97         dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
98
99         v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, true);
100
101         src_buf->sequence = ctx->sequence++;
102         dst_buf->sequence = src_buf->sequence;
103
104         v4l2_m2m_buf_done(src_buf, run->status ? VB2_BUF_STATE_ERROR :
105                                                  VB2_BUF_STATE_DONE);
106         v4l2_m2m_buf_done(dst_buf, run->status ? VB2_BUF_STATE_ERROR :
107                                                  VB2_BUF_STATE_DONE);
108
109         v4l2_m2m_job_finish(priv->m2m_dev, ctx->fh.m2m_ctx);
110         kfree(run);
111 }
112
113 static void device_run(void *_ctx)
114 {
115         struct ipu_csc_scaler_ctx *ctx = _ctx;
116         struct ipu_csc_scaler_priv *priv = ctx->priv;
117         struct vb2_v4l2_buffer *src_buf, *dst_buf;
118         struct ipu_image_convert_run *run;
119         int ret;
120
121         src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
122         dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
123
124         run = kzalloc(sizeof(*run), GFP_KERNEL);
125         if (!run)
126                 goto err;
127
128         run->ctx = ctx->icc;
129         run->in_phys = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
130         run->out_phys = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
131
132         ret = ipu_image_convert_queue(run);
133         if (ret < 0) {
134                 v4l2_err(ctx->priv->vdev.vfd->v4l2_dev,
135                          "%s: failed to queue: %d\n", __func__, ret);
136                 goto err;
137         }
138
139         return;
140
141 err:
142         v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
143         v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
144         v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
145         v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
146         v4l2_m2m_job_finish(priv->m2m_dev, ctx->fh.m2m_ctx);
147 }
148
149 /*
150  * Video ioctls
151  */
152 static int ipu_csc_scaler_querycap(struct file *file, void *priv,
153                                    struct v4l2_capability *cap)
154 {
155         strscpy(cap->driver, IMX_CSC_SCALER_NAME, sizeof(cap->driver));
156         strscpy(cap->card, IMX_CSC_SCALER_NAME, sizeof(cap->card));
157         snprintf(cap->bus_info, sizeof(cap->bus_info),
158                  "platform:%s", IMX_CSC_SCALER_NAME);
159
160         return 0;
161 }
162
163 static int ipu_csc_scaler_enum_fmt(struct file *file, void *fh,
164                                    struct v4l2_fmtdesc *f)
165 {
166         u32 fourcc;
167         int ret;
168
169         ret = imx_media_enum_pixel_formats(&fourcc, f->index,
170                                            PIXFMT_SEL_YUV_RGB, 0);
171         if (ret)
172                 return ret;
173
174         f->pixelformat = fourcc;
175
176         return 0;
177 }
178
179 static int ipu_csc_scaler_g_fmt(struct file *file, void *priv,
180                                 struct v4l2_format *f)
181 {
182         struct ipu_csc_scaler_ctx *ctx = fh_to_ctx(priv);
183         struct ipu_csc_scaler_q_data *q_data;
184
185         q_data = get_q_data(ctx, f->type);
186
187         f->fmt.pix = q_data->cur_fmt;
188
189         return 0;
190 }
191
192 static int ipu_csc_scaler_try_fmt(struct file *file, void *priv,
193                                   struct v4l2_format *f)
194 {
195         struct ipu_csc_scaler_ctx *ctx = fh_to_ctx(priv);
196         struct ipu_csc_scaler_q_data *q_data = get_q_data(ctx, f->type);
197         struct ipu_image test_in, test_out;
198         enum v4l2_field field;
199
200         field = f->fmt.pix.field;
201         if (field == V4L2_FIELD_ANY)
202                 field = V4L2_FIELD_NONE;
203         else if (field != V4L2_FIELD_NONE)
204                 return -EINVAL;
205
206         if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
207                 struct ipu_csc_scaler_q_data *q_data_in =
208                         get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
209
210                 test_out.pix = f->fmt.pix;
211                 test_in.pix = q_data_in->cur_fmt;
212         } else {
213                 struct ipu_csc_scaler_q_data *q_data_out =
214                         get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
215
216                 test_in.pix = f->fmt.pix;
217                 test_out.pix = q_data_out->cur_fmt;
218         }
219
220         ipu_image_convert_adjust(&test_in, &test_out, ctx->rot_mode);
221
222         f->fmt.pix = (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ?
223                 test_out.pix : test_in.pix;
224
225         if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
226                 f->fmt.pix.colorspace = q_data->cur_fmt.colorspace;
227                 f->fmt.pix.ycbcr_enc = q_data->cur_fmt.ycbcr_enc;
228                 f->fmt.pix.xfer_func = q_data->cur_fmt.xfer_func;
229                 f->fmt.pix.quantization = q_data->cur_fmt.quantization;
230         } else if (f->fmt.pix.colorspace == V4L2_COLORSPACE_DEFAULT) {
231                 f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
232                 f->fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
233                 f->fmt.pix.xfer_func = V4L2_XFER_FUNC_DEFAULT;
234                 f->fmt.pix.quantization = V4L2_QUANTIZATION_DEFAULT;
235         }
236
237         return 0;
238 }
239
240 static int ipu_csc_scaler_s_fmt(struct file *file, void *priv,
241                                 struct v4l2_format *f)
242 {
243         struct ipu_csc_scaler_q_data *q_data;
244         struct ipu_csc_scaler_ctx *ctx = fh_to_ctx(priv);
245         struct vb2_queue *vq;
246         int ret;
247
248         vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
249         if (vb2_is_busy(vq)) {
250                 v4l2_err(ctx->priv->vdev.vfd->v4l2_dev, "%s: queue busy\n",
251                          __func__);
252                 return -EBUSY;
253         }
254
255         q_data = get_q_data(ctx, f->type);
256
257         ret = ipu_csc_scaler_try_fmt(file, priv, f);
258         if (ret < 0)
259                 return ret;
260
261         q_data->cur_fmt.width = f->fmt.pix.width;
262         q_data->cur_fmt.height = f->fmt.pix.height;
263         q_data->cur_fmt.pixelformat = f->fmt.pix.pixelformat;
264         q_data->cur_fmt.field = f->fmt.pix.field;
265         q_data->cur_fmt.bytesperline = f->fmt.pix.bytesperline;
266         q_data->cur_fmt.sizeimage = f->fmt.pix.sizeimage;
267
268         /* Reset cropping/composing rectangle */
269         q_data->rect.left = 0;
270         q_data->rect.top = 0;
271         q_data->rect.width = q_data->cur_fmt.width;
272         q_data->rect.height = q_data->cur_fmt.height;
273
274         if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
275                 /* Set colorimetry on the output queue */
276                 q_data->cur_fmt.colorspace = f->fmt.pix.colorspace;
277                 q_data->cur_fmt.ycbcr_enc = f->fmt.pix.ycbcr_enc;
278                 q_data->cur_fmt.xfer_func = f->fmt.pix.xfer_func;
279                 q_data->cur_fmt.quantization = f->fmt.pix.quantization;
280                 /* Propagate colorimetry to the capture queue */
281                 q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
282                 q_data->cur_fmt.colorspace = f->fmt.pix.colorspace;
283                 q_data->cur_fmt.ycbcr_enc = f->fmt.pix.ycbcr_enc;
284                 q_data->cur_fmt.xfer_func = f->fmt.pix.xfer_func;
285                 q_data->cur_fmt.quantization = f->fmt.pix.quantization;
286         }
287
288         /*
289          * TODO: Setting colorimetry on the capture queue is currently not
290          * supported by the V4L2 API
291          */
292
293         return 0;
294 }
295
296 static int ipu_csc_scaler_g_selection(struct file *file, void *priv,
297                                       struct v4l2_selection *s)
298 {
299         struct ipu_csc_scaler_ctx *ctx = fh_to_ctx(priv);
300         struct ipu_csc_scaler_q_data *q_data;
301
302         switch (s->target) {
303         case V4L2_SEL_TGT_CROP:
304         case V4L2_SEL_TGT_CROP_DEFAULT:
305         case V4L2_SEL_TGT_CROP_BOUNDS:
306                 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
307                         return -EINVAL;
308                 q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
309                 break;
310         case V4L2_SEL_TGT_COMPOSE:
311         case V4L2_SEL_TGT_COMPOSE_DEFAULT:
312         case V4L2_SEL_TGT_COMPOSE_BOUNDS:
313                 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
314                         return -EINVAL;
315                 q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
316                 break;
317         default:
318                 return -EINVAL;
319         }
320
321         if (s->target == V4L2_SEL_TGT_CROP ||
322             s->target == V4L2_SEL_TGT_COMPOSE) {
323                 s->r = q_data->rect;
324         } else {
325                 s->r.left = 0;
326                 s->r.top = 0;
327                 s->r.width = q_data->cur_fmt.width;
328                 s->r.height = q_data->cur_fmt.height;
329         }
330
331         return 0;
332 }
333
334 static int ipu_csc_scaler_s_selection(struct file *file, void *priv,
335                                       struct v4l2_selection *s)
336 {
337         struct ipu_csc_scaler_ctx *ctx = fh_to_ctx(priv);
338         struct ipu_csc_scaler_q_data *q_data;
339
340         switch (s->target) {
341         case V4L2_SEL_TGT_CROP:
342                 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
343                         return -EINVAL;
344                 break;
345         case V4L2_SEL_TGT_COMPOSE:
346                 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
347                         return -EINVAL;
348                 break;
349         default:
350                 return -EINVAL;
351         }
352
353         if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
354             s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
355                 return -EINVAL;
356
357         q_data = get_q_data(ctx, s->type);
358
359         /* The input's frame width to the IC must be a multiple of 8 pixels
360          * When performing resizing the frame width must be multiple of burst
361          * size - 8 or 16 pixels as defined by CB#_BURST_16 parameter.
362          */
363         if (s->flags & V4L2_SEL_FLAG_GE)
364                 s->r.width = round_up(s->r.width, 8);
365         if (s->flags & V4L2_SEL_FLAG_LE)
366                 s->r.width = round_down(s->r.width, 8);
367         s->r.width = clamp_t(unsigned int, s->r.width, 8,
368                              round_down(q_data->cur_fmt.width, 8));
369         s->r.height = clamp_t(unsigned int, s->r.height, 1,
370                               q_data->cur_fmt.height);
371         s->r.left = clamp_t(unsigned int, s->r.left, 0,
372                             q_data->cur_fmt.width - s->r.width);
373         s->r.top = clamp_t(unsigned int, s->r.top, 0,
374                            q_data->cur_fmt.height - s->r.height);
375
376         /* V4L2_SEL_FLAG_KEEP_CONFIG is only valid for subdevices */
377         q_data->rect = s->r;
378
379         return 0;
380 }
381
382 static const struct v4l2_ioctl_ops ipu_csc_scaler_ioctl_ops = {
383         .vidioc_querycap                = ipu_csc_scaler_querycap,
384
385         .vidioc_enum_fmt_vid_cap        = ipu_csc_scaler_enum_fmt,
386         .vidioc_g_fmt_vid_cap           = ipu_csc_scaler_g_fmt,
387         .vidioc_try_fmt_vid_cap         = ipu_csc_scaler_try_fmt,
388         .vidioc_s_fmt_vid_cap           = ipu_csc_scaler_s_fmt,
389
390         .vidioc_enum_fmt_vid_out        = ipu_csc_scaler_enum_fmt,
391         .vidioc_g_fmt_vid_out           = ipu_csc_scaler_g_fmt,
392         .vidioc_try_fmt_vid_out         = ipu_csc_scaler_try_fmt,
393         .vidioc_s_fmt_vid_out           = ipu_csc_scaler_s_fmt,
394
395         .vidioc_g_selection             = ipu_csc_scaler_g_selection,
396         .vidioc_s_selection             = ipu_csc_scaler_s_selection,
397
398         .vidioc_reqbufs                 = v4l2_m2m_ioctl_reqbufs,
399         .vidioc_querybuf                = v4l2_m2m_ioctl_querybuf,
400
401         .vidioc_qbuf                    = v4l2_m2m_ioctl_qbuf,
402         .vidioc_expbuf                  = v4l2_m2m_ioctl_expbuf,
403         .vidioc_dqbuf                   = v4l2_m2m_ioctl_dqbuf,
404         .vidioc_create_bufs             = v4l2_m2m_ioctl_create_bufs,
405         .vidioc_prepare_buf             = v4l2_m2m_ioctl_prepare_buf,
406
407         .vidioc_streamon                = v4l2_m2m_ioctl_streamon,
408         .vidioc_streamoff               = v4l2_m2m_ioctl_streamoff,
409
410         .vidioc_subscribe_event         = v4l2_ctrl_subscribe_event,
411         .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
412 };
413
414 /*
415  * Queue operations
416  */
417
418 static int ipu_csc_scaler_queue_setup(struct vb2_queue *vq,
419                                       unsigned int *nbuffers,
420                                       unsigned int *nplanes,
421                                       unsigned int sizes[],
422                                       struct device *alloc_devs[])
423 {
424         struct ipu_csc_scaler_ctx *ctx = vb2_get_drv_priv(vq);
425         struct ipu_csc_scaler_q_data *q_data;
426         unsigned int size, count = *nbuffers;
427
428         q_data = get_q_data(ctx, vq->type);
429
430         size = q_data->cur_fmt.sizeimage;
431
432         *nbuffers = count;
433
434         if (*nplanes)
435                 return sizes[0] < size ? -EINVAL : 0;
436
437         *nplanes = 1;
438         sizes[0] = size;
439
440         dev_dbg(ctx->priv->dev, "get %d buffer(s) of size %d each.\n",
441                 count, size);
442
443         return 0;
444 }
445
446 static int ipu_csc_scaler_buf_prepare(struct vb2_buffer *vb)
447 {
448         struct vb2_queue *vq = vb->vb2_queue;
449         struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
450         struct ipu_csc_scaler_ctx *ctx = vb2_get_drv_priv(vq);
451         struct ipu_csc_scaler_q_data *q_data;
452         unsigned long size;
453
454         dev_dbg(ctx->priv->dev, "type: %d\n", vq->type);
455
456         if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
457                 if (vbuf->field == V4L2_FIELD_ANY)
458                         vbuf->field = V4L2_FIELD_NONE;
459                 if (vbuf->field != V4L2_FIELD_NONE) {
460                         dev_dbg(ctx->priv->dev, "%s: field isn't supported\n",
461                                 __func__);
462                         return -EINVAL;
463                 }
464         }
465
466         q_data = get_q_data(ctx, vq->type);
467         size = q_data->cur_fmt.sizeimage;
468
469         if (vb2_plane_size(vb, 0) < size) {
470                 dev_dbg(ctx->priv->dev,
471                         "%s: data will not fit into plane (%lu < %lu)\n",
472                         __func__, vb2_plane_size(vb, 0), size);
473                 return -EINVAL;
474         }
475
476         vb2_set_plane_payload(vb, 0, size);
477
478         return 0;
479 }
480
481 static void ipu_csc_scaler_buf_queue(struct vb2_buffer *vb)
482 {
483         struct ipu_csc_scaler_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
484
485         v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, to_vb2_v4l2_buffer(vb));
486 }
487
488 static void ipu_image_from_q_data(struct ipu_image *im,
489                                   struct ipu_csc_scaler_q_data *q_data)
490 {
491         struct v4l2_pix_format *fmt = &q_data->cur_fmt;
492
493         im->pix = *fmt;
494         if (fmt->ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT)
495                 im->pix.ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
496         if (fmt->quantization == V4L2_QUANTIZATION_DEFAULT)
497                 im->pix.ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
498         im->rect = q_data->rect;
499 }
500
501 static int ipu_csc_scaler_start_streaming(struct vb2_queue *q,
502                                           unsigned int count)
503 {
504         const enum ipu_ic_task ic_task = IC_TASK_POST_PROCESSOR;
505         struct ipu_csc_scaler_ctx *ctx = vb2_get_drv_priv(q);
506         struct ipu_csc_scaler_priv *priv = ctx->priv;
507         struct ipu_soc *ipu = priv->md->ipu[0];
508         struct ipu_csc_scaler_q_data *q_data;
509         struct vb2_queue *other_q;
510         struct ipu_image in, out;
511
512         other_q = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
513                                   (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ?
514                                   V4L2_BUF_TYPE_VIDEO_OUTPUT :
515                                   V4L2_BUF_TYPE_VIDEO_CAPTURE);
516         if (!vb2_is_streaming(other_q))
517                 return 0;
518
519         if (ctx->icc) {
520                 v4l2_warn(ctx->priv->vdev.vfd->v4l2_dev, "removing old ICC\n");
521                 ipu_image_convert_unprepare(ctx->icc);
522         }
523
524         q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
525         ipu_image_from_q_data(&in, q_data);
526
527         q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
528         ipu_image_from_q_data(&out, q_data);
529
530         ctx->icc = ipu_image_convert_prepare(ipu, ic_task, &in, &out,
531                                              ctx->rot_mode,
532                                              ipu_ic_pp_complete, ctx);
533         if (IS_ERR(ctx->icc)) {
534                 struct vb2_v4l2_buffer *buf;
535                 int ret = PTR_ERR(ctx->icc);
536
537                 ctx->icc = NULL;
538                 v4l2_err(ctx->priv->vdev.vfd->v4l2_dev, "%s: error %d\n",
539                          __func__, ret);
540                 while ((buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx)))
541                         v4l2_m2m_buf_done(buf, VB2_BUF_STATE_QUEUED);
542                 while ((buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx)))
543                         v4l2_m2m_buf_done(buf, VB2_BUF_STATE_QUEUED);
544                 return ret;
545         }
546
547         return 0;
548 }
549
550 static void ipu_csc_scaler_stop_streaming(struct vb2_queue *q)
551 {
552         struct ipu_csc_scaler_ctx *ctx = vb2_get_drv_priv(q);
553         struct vb2_v4l2_buffer *buf;
554
555         if (ctx->icc) {
556                 ipu_image_convert_unprepare(ctx->icc);
557                 ctx->icc = NULL;
558         }
559
560         ctx->sequence = 0;
561
562         if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
563                 while ((buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx)))
564                         v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR);
565         } else {
566                 while ((buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx)))
567                         v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR);
568         }
569 }
570
571 static const struct vb2_ops ipu_csc_scaler_qops = {
572         .queue_setup            = ipu_csc_scaler_queue_setup,
573         .buf_prepare            = ipu_csc_scaler_buf_prepare,
574         .buf_queue              = ipu_csc_scaler_buf_queue,
575         .wait_prepare           = vb2_ops_wait_prepare,
576         .wait_finish            = vb2_ops_wait_finish,
577         .start_streaming        = ipu_csc_scaler_start_streaming,
578         .stop_streaming         = ipu_csc_scaler_stop_streaming,
579 };
580
581 static int ipu_csc_scaler_queue_init(void *priv, struct vb2_queue *src_vq,
582                                      struct vb2_queue *dst_vq)
583 {
584         struct ipu_csc_scaler_ctx *ctx = priv;
585         int ret;
586
587         memset(src_vq, 0, sizeof(*src_vq));
588         src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
589         src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
590         src_vq->drv_priv = ctx;
591         src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
592         src_vq->ops = &ipu_csc_scaler_qops;
593         src_vq->mem_ops = &vb2_dma_contig_memops;
594         src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
595         src_vq->lock = &ctx->priv->mutex;
596         src_vq->dev = ctx->priv->dev;
597
598         ret = vb2_queue_init(src_vq);
599         if (ret)
600                 return ret;
601
602         memset(dst_vq, 0, sizeof(*dst_vq));
603         dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
604         dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
605         dst_vq->drv_priv = ctx;
606         dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
607         dst_vq->ops = &ipu_csc_scaler_qops;
608         dst_vq->mem_ops = &vb2_dma_contig_memops;
609         dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
610         dst_vq->lock = &ctx->priv->mutex;
611         dst_vq->dev = ctx->priv->dev;
612
613         return vb2_queue_init(dst_vq);
614 }
615
616 static int ipu_csc_scaler_s_ctrl(struct v4l2_ctrl *ctrl)
617 {
618         struct ipu_csc_scaler_ctx *ctx = container_of(ctrl->handler,
619                                                       struct ipu_csc_scaler_ctx,
620                                                       ctrl_hdlr);
621         enum ipu_rotate_mode rot_mode;
622         int rotate;
623         bool hflip, vflip;
624         int ret = 0;
625
626         rotate = ctx->rotate;
627         hflip = ctx->hflip;
628         vflip = ctx->vflip;
629
630         switch (ctrl->id) {
631         case V4L2_CID_HFLIP:
632                 hflip = ctrl->val;
633                 break;
634         case V4L2_CID_VFLIP:
635                 vflip = ctrl->val;
636                 break;
637         case V4L2_CID_ROTATE:
638                 rotate = ctrl->val;
639                 break;
640         default:
641                 return -EINVAL;
642         }
643
644         ret = ipu_degrees_to_rot_mode(&rot_mode, rotate, hflip, vflip);
645         if (ret)
646                 return ret;
647
648         if (rot_mode != ctx->rot_mode) {
649                 struct v4l2_pix_format *in_fmt, *out_fmt;
650                 struct ipu_image test_in, test_out;
651
652                 in_fmt = &ctx->q_data[V4L2_M2M_SRC].cur_fmt;
653                 out_fmt = &ctx->q_data[V4L2_M2M_DST].cur_fmt;
654
655                 test_in.pix = *in_fmt;
656                 test_out.pix = *out_fmt;
657
658                 if (ipu_rot_mode_is_irt(rot_mode) !=
659                     ipu_rot_mode_is_irt(ctx->rot_mode)) {
660                         /* Switch width & height to keep aspect ratio intact */
661                         test_out.pix.width = out_fmt->height;
662                         test_out.pix.height = out_fmt->width;
663                 }
664
665                 ipu_image_convert_adjust(&test_in, &test_out, ctx->rot_mode);
666
667                 /* Check if output format needs to be changed */
668                 if (test_in.pix.width != in_fmt->width ||
669                     test_in.pix.height != in_fmt->height ||
670                     test_in.pix.bytesperline != in_fmt->bytesperline ||
671                     test_in.pix.sizeimage != in_fmt->sizeimage) {
672                         struct vb2_queue *out_q;
673
674                         out_q = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
675                                                 V4L2_BUF_TYPE_VIDEO_OUTPUT);
676                         if (vb2_is_busy(out_q))
677                                 return -EBUSY;
678                 }
679
680                 /* Check if capture format needs to be changed */
681                 if (test_out.pix.width != out_fmt->width ||
682                     test_out.pix.height != out_fmt->height ||
683                     test_out.pix.bytesperline != out_fmt->bytesperline ||
684                     test_out.pix.sizeimage != out_fmt->sizeimage) {
685                         struct vb2_queue *cap_q;
686
687                         cap_q = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
688                                                 V4L2_BUF_TYPE_VIDEO_CAPTURE);
689                         if (vb2_is_busy(cap_q))
690                                 return -EBUSY;
691                 }
692
693                 *in_fmt = test_in.pix;
694                 *out_fmt = test_out.pix;
695
696                 ctx->rot_mode = rot_mode;
697                 ctx->rotate = rotate;
698                 ctx->hflip = hflip;
699                 ctx->vflip = vflip;
700         }
701
702         return 0;
703 }
704
705 static const struct v4l2_ctrl_ops ipu_csc_scaler_ctrl_ops = {
706         .s_ctrl = ipu_csc_scaler_s_ctrl,
707 };
708
709 static int ipu_csc_scaler_init_controls(struct ipu_csc_scaler_ctx *ctx)
710 {
711         struct v4l2_ctrl_handler *hdlr = &ctx->ctrl_hdlr;
712
713         v4l2_ctrl_handler_init(hdlr, 3);
714
715         v4l2_ctrl_new_std(hdlr, &ipu_csc_scaler_ctrl_ops, V4L2_CID_HFLIP,
716                           0, 1, 1, 0);
717         v4l2_ctrl_new_std(hdlr, &ipu_csc_scaler_ctrl_ops, V4L2_CID_VFLIP,
718                           0, 1, 1, 0);
719         v4l2_ctrl_new_std(hdlr, &ipu_csc_scaler_ctrl_ops, V4L2_CID_ROTATE,
720                           0, 270, 90, 0);
721
722         if (hdlr->error) {
723                 v4l2_ctrl_handler_free(hdlr);
724                 return hdlr->error;
725         }
726
727         v4l2_ctrl_handler_setup(hdlr);
728         return 0;
729 }
730
731 #define DEFAULT_WIDTH   720
732 #define DEFAULT_HEIGHT  576
733 static const struct ipu_csc_scaler_q_data ipu_csc_scaler_q_data_default = {
734         .cur_fmt = {
735                 .width = DEFAULT_WIDTH,
736                 .height = DEFAULT_HEIGHT,
737                 .pixelformat = V4L2_PIX_FMT_YUV420,
738                 .field = V4L2_FIELD_NONE,
739                 .bytesperline = DEFAULT_WIDTH,
740                 .sizeimage = DEFAULT_WIDTH * DEFAULT_HEIGHT * 3 / 2,
741                 .colorspace = V4L2_COLORSPACE_SRGB,
742         },
743         .rect = {
744                 .width = DEFAULT_WIDTH,
745                 .height = DEFAULT_HEIGHT,
746         },
747 };
748
749 /*
750  * File operations
751  */
752 static int ipu_csc_scaler_open(struct file *file)
753 {
754         struct ipu_csc_scaler_priv *priv = video_drvdata(file);
755         struct ipu_csc_scaler_ctx *ctx = NULL;
756         int ret;
757
758         ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
759         if (!ctx)
760                 return -ENOMEM;
761
762         ctx->rot_mode = IPU_ROTATE_NONE;
763
764         v4l2_fh_init(&ctx->fh, video_devdata(file));
765         file->private_data = &ctx->fh;
766         v4l2_fh_add(&ctx->fh);
767         ctx->priv = priv;
768
769         ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(priv->m2m_dev, ctx,
770                                             &ipu_csc_scaler_queue_init);
771         if (IS_ERR(ctx->fh.m2m_ctx)) {
772                 ret = PTR_ERR(ctx->fh.m2m_ctx);
773                 goto err_ctx;
774         }
775
776         ret = ipu_csc_scaler_init_controls(ctx);
777         if (ret)
778                 goto err_ctrls;
779
780         ctx->fh.ctrl_handler = &ctx->ctrl_hdlr;
781
782         ctx->q_data[V4L2_M2M_SRC] = ipu_csc_scaler_q_data_default;
783         ctx->q_data[V4L2_M2M_DST] = ipu_csc_scaler_q_data_default;
784
785         dev_dbg(priv->dev, "Created instance %p, m2m_ctx: %p\n", ctx,
786                 ctx->fh.m2m_ctx);
787
788         return 0;
789
790 err_ctrls:
791         v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
792 err_ctx:
793         v4l2_fh_del(&ctx->fh);
794         v4l2_fh_exit(&ctx->fh);
795         kfree(ctx);
796         return ret;
797 }
798
799 static int ipu_csc_scaler_release(struct file *file)
800 {
801         struct ipu_csc_scaler_priv *priv = video_drvdata(file);
802         struct ipu_csc_scaler_ctx *ctx = fh_to_ctx(file->private_data);
803
804         dev_dbg(priv->dev, "Releasing instance %p\n", ctx);
805
806         v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
807         v4l2_fh_del(&ctx->fh);
808         v4l2_fh_exit(&ctx->fh);
809         kfree(ctx);
810
811         return 0;
812 }
813
814 static const struct v4l2_file_operations ipu_csc_scaler_fops = {
815         .owner          = THIS_MODULE,
816         .open           = ipu_csc_scaler_open,
817         .release        = ipu_csc_scaler_release,
818         .poll           = v4l2_m2m_fop_poll,
819         .unlocked_ioctl = video_ioctl2,
820         .mmap           = v4l2_m2m_fop_mmap,
821 };
822
823 static const struct v4l2_m2m_ops m2m_ops = {
824         .device_run     = device_run,
825         .job_abort      = job_abort,
826 };
827
828 static void ipu_csc_scaler_video_device_release(struct video_device *vdev)
829 {
830         struct ipu_csc_scaler_priv *priv = video_get_drvdata(vdev);
831
832         v4l2_m2m_release(priv->m2m_dev);
833         video_device_release(vdev);
834         kfree(priv);
835 }
836
837 static const struct video_device ipu_csc_scaler_videodev_template = {
838         .name           = "ipu_ic_pp csc/scaler",
839         .fops           = &ipu_csc_scaler_fops,
840         .ioctl_ops      = &ipu_csc_scaler_ioctl_ops,
841         .minor          = -1,
842         .release        = ipu_csc_scaler_video_device_release,
843         .vfl_dir        = VFL_DIR_M2M,
844         .device_caps    = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING,
845 };
846
847 int imx_media_csc_scaler_device_register(struct imx_media_video_dev *vdev)
848 {
849         struct ipu_csc_scaler_priv *priv = vdev_to_priv(vdev);
850         struct video_device *vfd = vdev->vfd;
851         int ret;
852
853         vfd->v4l2_dev = &priv->md->v4l2_dev;
854
855         ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1);
856         if (ret) {
857                 v4l2_err(vfd->v4l2_dev, "Failed to register video device\n");
858                 return ret;
859         }
860
861         v4l2_info(vfd->v4l2_dev, "Registered %s as /dev/%s\n", vfd->name,
862                   video_device_node_name(vfd));
863
864         return 0;
865 }
866
867 void imx_media_csc_scaler_device_unregister(struct imx_media_video_dev *vdev)
868 {
869         struct ipu_csc_scaler_priv *priv = vdev_to_priv(vdev);
870         struct video_device *vfd = priv->vdev.vfd;
871
872         video_unregister_device(vfd);
873 }
874
875 struct imx_media_video_dev *
876 imx_media_csc_scaler_device_init(struct imx_media_dev *md)
877 {
878         struct ipu_csc_scaler_priv *priv;
879         struct video_device *vfd;
880         int ret;
881
882         priv = kzalloc(sizeof(*priv), GFP_KERNEL);
883         if (!priv)
884                 return ERR_PTR(-ENOMEM);
885
886         priv->md = md;
887         priv->dev = md->md.dev;
888
889         mutex_init(&priv->mutex);
890
891         vfd = video_device_alloc();
892         if (!vfd) {
893                 ret = -ENOMEM;
894                 goto err_vfd;
895         }
896
897         *vfd = ipu_csc_scaler_videodev_template;
898         vfd->lock = &priv->mutex;
899         priv->vdev.vfd = vfd;
900
901         INIT_LIST_HEAD(&priv->vdev.list);
902
903         video_set_drvdata(vfd, priv);
904
905         priv->m2m_dev = v4l2_m2m_init(&m2m_ops);
906         if (IS_ERR(priv->m2m_dev)) {
907                 ret = PTR_ERR(priv->m2m_dev);
908                 v4l2_err(&md->v4l2_dev, "Failed to init mem2mem device: %d\n",
909                          ret);
910                 goto err_m2m;
911         }
912
913         return &priv->vdev;
914
915 err_m2m:
916         video_set_drvdata(vfd, NULL);
917 err_vfd:
918         kfree(priv);
919         return ERR_PTR(ret);
920 }
921
922 MODULE_DESCRIPTION("i.MX IPUv3 mem2mem scaler/CSC driver");
923 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
924 MODULE_LICENSE("GPL");