GNU Linux-libre 4.14.332-gnu1
[releases.git] / drivers / media / platform / vsp1 / vsp1_wpf.c
1 /*
2  * vsp1_wpf.c  --  R-Car VSP1 Write Pixel Formatter
3  *
4  * Copyright (C) 2013-2014 Renesas Electronics Corporation
5  *
6  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  */
13
14 #include <linux/device.h>
15
16 #include <media/v4l2-subdev.h>
17
18 #include "vsp1.h"
19 #include "vsp1_dl.h"
20 #include "vsp1_pipe.h"
21 #include "vsp1_rwpf.h"
22 #include "vsp1_video.h"
23
24 #define WPF_GEN2_MAX_WIDTH                      2048U
25 #define WPF_GEN2_MAX_HEIGHT                     2048U
26 #define WPF_GEN3_MAX_WIDTH                      8190U
27 #define WPF_GEN3_MAX_HEIGHT                     8190U
28
29 /* -----------------------------------------------------------------------------
30  * Device Access
31  */
32
33 static inline void vsp1_wpf_write(struct vsp1_rwpf *wpf,
34                                   struct vsp1_dl_list *dl, u32 reg, u32 data)
35 {
36         vsp1_dl_list_write(dl, reg + wpf->entity.index * VI6_WPF_OFFSET, data);
37 }
38
39 /* -----------------------------------------------------------------------------
40  * Controls
41  */
42
43 enum wpf_flip_ctrl {
44         WPF_CTRL_VFLIP = 0,
45         WPF_CTRL_HFLIP = 1,
46 };
47
48 static int vsp1_wpf_set_rotation(struct vsp1_rwpf *wpf, unsigned int rotation)
49 {
50         struct vsp1_video *video = wpf->video;
51         struct v4l2_mbus_framefmt *sink_format;
52         struct v4l2_mbus_framefmt *source_format;
53         bool rotate;
54         int ret = 0;
55
56         /*
57          * Only consider the 0°/180° from/to 90°/270° modifications, the rest
58          * is taken care of by the flipping configuration.
59          */
60         rotate = rotation == 90 || rotation == 270;
61         if (rotate == wpf->flip.rotate)
62                 return 0;
63
64         /* Changing rotation isn't allowed when buffers are allocated. */
65         mutex_lock(&video->lock);
66
67         if (vb2_is_busy(&video->queue)) {
68                 ret = -EBUSY;
69                 goto done;
70         }
71
72         sink_format = vsp1_entity_get_pad_format(&wpf->entity,
73                                                  wpf->entity.config,
74                                                  RWPF_PAD_SINK);
75         source_format = vsp1_entity_get_pad_format(&wpf->entity,
76                                                    wpf->entity.config,
77                                                    RWPF_PAD_SOURCE);
78
79         mutex_lock(&wpf->entity.lock);
80
81         if (rotate) {
82                 source_format->width = sink_format->height;
83                 source_format->height = sink_format->width;
84         } else {
85                 source_format->width = sink_format->width;
86                 source_format->height = sink_format->height;
87         }
88
89         wpf->flip.rotate = rotate;
90
91         mutex_unlock(&wpf->entity.lock);
92
93 done:
94         mutex_unlock(&video->lock);
95         return ret;
96 }
97
98 static int vsp1_wpf_s_ctrl(struct v4l2_ctrl *ctrl)
99 {
100         struct vsp1_rwpf *wpf =
101                 container_of(ctrl->handler, struct vsp1_rwpf, ctrls);
102         unsigned int rotation;
103         u32 flip = 0;
104         int ret;
105
106         /* Update the rotation. */
107         rotation = wpf->flip.ctrls.rotate ? wpf->flip.ctrls.rotate->val : 0;
108         ret = vsp1_wpf_set_rotation(wpf, rotation);
109         if (ret < 0)
110                 return ret;
111
112         /*
113          * Compute the flip value resulting from all three controls, with
114          * rotation by 180° flipping the image in both directions. Store the
115          * result in the pending flip field for the next frame that will be
116          * processed.
117          */
118         if (wpf->flip.ctrls.vflip->val)
119                 flip |= BIT(WPF_CTRL_VFLIP);
120
121         if (wpf->flip.ctrls.hflip && wpf->flip.ctrls.hflip->val)
122                 flip |= BIT(WPF_CTRL_HFLIP);
123
124         if (rotation == 180 || rotation == 270)
125                 flip ^= BIT(WPF_CTRL_VFLIP) | BIT(WPF_CTRL_HFLIP);
126
127         spin_lock_irq(&wpf->flip.lock);
128         wpf->flip.pending = flip;
129         spin_unlock_irq(&wpf->flip.lock);
130
131         return 0;
132 }
133
134 static const struct v4l2_ctrl_ops vsp1_wpf_ctrl_ops = {
135         .s_ctrl = vsp1_wpf_s_ctrl,
136 };
137
138 static int wpf_init_controls(struct vsp1_rwpf *wpf)
139 {
140         struct vsp1_device *vsp1 = wpf->entity.vsp1;
141         unsigned int num_flip_ctrls;
142
143         spin_lock_init(&wpf->flip.lock);
144
145         if (wpf->entity.index != 0) {
146                 /* Only WPF0 supports flipping. */
147                 num_flip_ctrls = 0;
148         } else if (vsp1->info->features & VSP1_HAS_WPF_HFLIP) {
149                 /*
150                  * When horizontal flip is supported the WPF implements three
151                  * controls (horizontal flip, vertical flip and rotation).
152                  */
153                 num_flip_ctrls = 3;
154         } else if (vsp1->info->features & VSP1_HAS_WPF_VFLIP) {
155                 /*
156                  * When only vertical flip is supported the WPF implements a
157                  * single control (vertical flip).
158                  */
159                 num_flip_ctrls = 1;
160         } else {
161                 /* Otherwise flipping is not supported. */
162                 num_flip_ctrls = 0;
163         }
164
165         vsp1_rwpf_init_ctrls(wpf, num_flip_ctrls);
166
167         if (num_flip_ctrls >= 1) {
168                 wpf->flip.ctrls.vflip =
169                         v4l2_ctrl_new_std(&wpf->ctrls, &vsp1_wpf_ctrl_ops,
170                                           V4L2_CID_VFLIP, 0, 1, 1, 0);
171         }
172
173         if (num_flip_ctrls == 3) {
174                 wpf->flip.ctrls.hflip =
175                         v4l2_ctrl_new_std(&wpf->ctrls, &vsp1_wpf_ctrl_ops,
176                                           V4L2_CID_HFLIP, 0, 1, 1, 0);
177                 wpf->flip.ctrls.rotate =
178                         v4l2_ctrl_new_std(&wpf->ctrls, &vsp1_wpf_ctrl_ops,
179                                           V4L2_CID_ROTATE, 0, 270, 90, 0);
180                 v4l2_ctrl_cluster(3, &wpf->flip.ctrls.vflip);
181         }
182
183         if (wpf->ctrls.error) {
184                 dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n",
185                         wpf->entity.index);
186                 return wpf->ctrls.error;
187         }
188
189         return 0;
190 }
191
192 /* -----------------------------------------------------------------------------
193  * V4L2 Subdevice Core Operations
194  */
195
196 static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
197 {
198         struct vsp1_rwpf *wpf = to_rwpf(subdev);
199         struct vsp1_device *vsp1 = wpf->entity.vsp1;
200
201         if (enable)
202                 return 0;
203
204         /*
205          * Write to registers directly when stopping the stream as there will be
206          * no pipeline run to apply the display list.
207          */
208         vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0);
209         vsp1_write(vsp1, wpf->entity.index * VI6_WPF_OFFSET +
210                    VI6_WPF_SRCRPF, 0);
211
212         return 0;
213 }
214
215 /* -----------------------------------------------------------------------------
216  * V4L2 Subdevice Operations
217  */
218
219 static const struct v4l2_subdev_video_ops wpf_video_ops = {
220         .s_stream = wpf_s_stream,
221 };
222
223 static const struct v4l2_subdev_ops wpf_ops = {
224         .video  = &wpf_video_ops,
225         .pad    = &vsp1_rwpf_pad_ops,
226 };
227
228 /* -----------------------------------------------------------------------------
229  * VSP1 Entity Operations
230  */
231
232 static void vsp1_wpf_destroy(struct vsp1_entity *entity)
233 {
234         struct vsp1_rwpf *wpf = entity_to_rwpf(entity);
235
236         vsp1_dlm_destroy(wpf->dlm);
237 }
238
239 static void wpf_configure(struct vsp1_entity *entity,
240                           struct vsp1_pipeline *pipe,
241                           struct vsp1_dl_list *dl,
242                           enum vsp1_entity_params params)
243 {
244         struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev);
245         struct vsp1_device *vsp1 = wpf->entity.vsp1;
246         const struct v4l2_mbus_framefmt *source_format;
247         const struct v4l2_mbus_framefmt *sink_format;
248         unsigned int i;
249         u32 outfmt = 0;
250         u32 srcrpf = 0;
251
252         if (params == VSP1_ENTITY_PARAMS_RUNTIME) {
253                 const unsigned int mask = BIT(WPF_CTRL_VFLIP)
254                                         | BIT(WPF_CTRL_HFLIP);
255                 unsigned long flags;
256
257                 spin_lock_irqsave(&wpf->flip.lock, flags);
258                 wpf->flip.active = (wpf->flip.active & ~mask)
259                                  | (wpf->flip.pending & mask);
260                 spin_unlock_irqrestore(&wpf->flip.lock, flags);
261
262                 outfmt = (wpf->alpha << VI6_WPF_OUTFMT_PDV_SHIFT) | wpf->outfmt;
263
264                 if (wpf->flip.active & BIT(WPF_CTRL_VFLIP))
265                         outfmt |= VI6_WPF_OUTFMT_FLP;
266                 if (wpf->flip.active & BIT(WPF_CTRL_HFLIP))
267                         outfmt |= VI6_WPF_OUTFMT_HFLP;
268
269                 vsp1_wpf_write(wpf, dl, VI6_WPF_OUTFMT, outfmt);
270                 return;
271         }
272
273         sink_format = vsp1_entity_get_pad_format(&wpf->entity,
274                                                  wpf->entity.config,
275                                                  RWPF_PAD_SINK);
276         source_format = vsp1_entity_get_pad_format(&wpf->entity,
277                                                    wpf->entity.config,
278                                                    RWPF_PAD_SOURCE);
279
280         if (params == VSP1_ENTITY_PARAMS_PARTITION) {
281                 const struct v4l2_pix_format_mplane *format = &wpf->format;
282                 const struct vsp1_format_info *fmtinfo = wpf->fmtinfo;
283                 struct vsp1_rwpf_memory mem = wpf->mem;
284                 unsigned int flip = wpf->flip.active;
285                 unsigned int width = sink_format->width;
286                 unsigned int height = sink_format->height;
287                 unsigned int offset;
288
289                 /*
290                  * Cropping. The partition algorithm can split the image into
291                  * multiple slices.
292                  */
293                 if (pipe->partitions > 1)
294                         width = pipe->partition->wpf.width;
295
296                 vsp1_wpf_write(wpf, dl, VI6_WPF_HSZCLIP, VI6_WPF_SZCLIP_EN |
297                                (0 << VI6_WPF_SZCLIP_OFST_SHIFT) |
298                                (width << VI6_WPF_SZCLIP_SIZE_SHIFT));
299                 vsp1_wpf_write(wpf, dl, VI6_WPF_VSZCLIP, VI6_WPF_SZCLIP_EN |
300                                (0 << VI6_WPF_SZCLIP_OFST_SHIFT) |
301                                (height << VI6_WPF_SZCLIP_SIZE_SHIFT));
302
303                 if (pipe->lif)
304                         return;
305
306                 /*
307                  * Update the memory offsets based on flipping configuration.
308                  * The destination addresses point to the locations where the
309                  * VSP starts writing to memory, which can be any corner of the
310                  * image depending on the combination of flipping and rotation.
311                  */
312
313                 /*
314                  * First take the partition left coordinate into account.
315                  * Compute the offset to order the partitions correctly on the
316                  * output based on whether flipping is enabled. Consider
317                  * horizontal flipping when rotation is disabled but vertical
318                  * flipping when rotation is enabled, as rotating the image
319                  * switches the horizontal and vertical directions. The offset
320                  * is applied horizontally or vertically accordingly.
321                  */
322                 if (flip & BIT(WPF_CTRL_HFLIP) && !wpf->flip.rotate)
323                         offset = format->width - pipe->partition->wpf.left
324                                 - pipe->partition->wpf.width;
325                 else if (flip & BIT(WPF_CTRL_VFLIP) && wpf->flip.rotate)
326                         offset = format->height - pipe->partition->wpf.left
327                                 - pipe->partition->wpf.width;
328                 else
329                         offset = pipe->partition->wpf.left;
330
331                 for (i = 0; i < format->num_planes; ++i) {
332                         unsigned int hsub = i > 0 ? fmtinfo->hsub : 1;
333                         unsigned int vsub = i > 0 ? fmtinfo->vsub : 1;
334
335                         if (wpf->flip.rotate)
336                                 mem.addr[i] += offset / vsub
337                                              * format->plane_fmt[i].bytesperline;
338                         else
339                                 mem.addr[i] += offset / hsub
340                                              * fmtinfo->bpp[i] / 8;
341                 }
342
343                 if (flip & BIT(WPF_CTRL_VFLIP)) {
344                         /*
345                          * When rotating the output (after rotation) image
346                          * height is equal to the partition width (before
347                          * rotation). Otherwise it is equal to the output
348                          * image height.
349                          */
350                         if (wpf->flip.rotate)
351                                 height = pipe->partition->wpf.width;
352                         else
353                                 height = format->height;
354
355                         mem.addr[0] += (height - 1)
356                                      * format->plane_fmt[0].bytesperline;
357
358                         if (format->num_planes > 1) {
359                                 offset = (height / fmtinfo->vsub - 1)
360                                        * format->plane_fmt[1].bytesperline;
361                                 mem.addr[1] += offset;
362                                 mem.addr[2] += offset;
363                         }
364                 }
365
366                 if (wpf->flip.rotate && !(flip & BIT(WPF_CTRL_HFLIP))) {
367                         unsigned int hoffset = max(0, (int)format->width - 16);
368
369                         /*
370                          * Compute the output coordinate. The partition
371                          * horizontal (left) offset becomes a vertical offset.
372                          */
373                         for (i = 0; i < format->num_planes; ++i) {
374                                 unsigned int hsub = i > 0 ? fmtinfo->hsub : 1;
375
376                                 mem.addr[i] += hoffset / hsub
377                                              * fmtinfo->bpp[i] / 8;
378                         }
379                 }
380
381                 /*
382                  * On Gen3 hardware the SPUVS bit has no effect on 3-planar
383                  * formats. Swap the U and V planes manually in that case.
384                  */
385                 if (vsp1->info->gen == 3 && format->num_planes == 3 &&
386                     fmtinfo->swap_uv)
387                         swap(mem.addr[1], mem.addr[2]);
388
389                 vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_Y, mem.addr[0]);
390                 vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C0, mem.addr[1]);
391                 vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_ADDR_C1, mem.addr[2]);
392                 return;
393         }
394
395         /* Format */
396         if (!pipe->lif) {
397                 const struct v4l2_pix_format_mplane *format = &wpf->format;
398                 const struct vsp1_format_info *fmtinfo = wpf->fmtinfo;
399
400                 outfmt = fmtinfo->hwfmt << VI6_WPF_OUTFMT_WRFMT_SHIFT;
401
402                 if (wpf->flip.rotate)
403                         outfmt |= VI6_WPF_OUTFMT_ROT;
404
405                 if (fmtinfo->alpha)
406                         outfmt |= VI6_WPF_OUTFMT_PXA;
407                 if (fmtinfo->swap_yc)
408                         outfmt |= VI6_WPF_OUTFMT_SPYCS;
409                 if (fmtinfo->swap_uv)
410                         outfmt |= VI6_WPF_OUTFMT_SPUVS;
411
412                 /* Destination stride and byte swapping. */
413                 vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_STRIDE_Y,
414                                format->plane_fmt[0].bytesperline);
415                 if (format->num_planes > 1)
416                         vsp1_wpf_write(wpf, dl, VI6_WPF_DSTM_STRIDE_C,
417                                        format->plane_fmt[1].bytesperline);
418
419                 vsp1_wpf_write(wpf, dl, VI6_WPF_DSWAP, fmtinfo->swap);
420
421                 if (vsp1->info->features & VSP1_HAS_WPF_HFLIP &&
422                     wpf->entity.index == 0)
423                         vsp1_wpf_write(wpf, dl, VI6_WPF_ROT_CTRL,
424                                        VI6_WPF_ROT_CTRL_LN16 |
425                                        (256 << VI6_WPF_ROT_CTRL_LMEM_WD_SHIFT));
426         }
427
428         if (sink_format->code != source_format->code)
429                 outfmt |= VI6_WPF_OUTFMT_CSC;
430
431         wpf->outfmt = outfmt;
432
433         vsp1_dl_list_write(dl, VI6_DPR_WPF_FPORCH(wpf->entity.index),
434                            VI6_DPR_WPF_FPORCH_FP_WPFN);
435
436         vsp1_dl_list_write(dl, VI6_WPF_WRBCK_CTRL, 0);
437
438         /*
439          * Sources. If the pipeline has a single input and BRU is not used,
440          * configure it as the master layer. Otherwise configure all
441          * inputs as sub-layers and select the virtual RPF as the master
442          * layer.
443          */
444         for (i = 0; i < vsp1->info->rpf_count; ++i) {
445                 struct vsp1_rwpf *input = pipe->inputs[i];
446
447                 if (!input)
448                         continue;
449
450                 srcrpf |= (!pipe->bru && pipe->num_inputs == 1)
451                         ? VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index)
452                         : VI6_WPF_SRCRPF_RPF_ACT_SUB(input->entity.index);
453         }
454
455         if (pipe->bru)
456                 srcrpf |= pipe->bru->type == VSP1_ENTITY_BRU
457                         ? VI6_WPF_SRCRPF_VIRACT_MST
458                         : VI6_WPF_SRCRPF_VIRACT2_MST;
459
460         vsp1_wpf_write(wpf, dl, VI6_WPF_SRCRPF, srcrpf);
461
462         /* Enable interrupts */
463         vsp1_dl_list_write(dl, VI6_WPF_IRQ_STA(wpf->entity.index), 0);
464         vsp1_dl_list_write(dl, VI6_WPF_IRQ_ENB(wpf->entity.index),
465                            VI6_WFP_IRQ_ENB_DFEE);
466 }
467
468 static unsigned int wpf_max_width(struct vsp1_entity *entity,
469                                   struct vsp1_pipeline *pipe)
470 {
471         struct vsp1_rwpf *wpf = to_rwpf(&entity->subdev);
472
473         return wpf->flip.rotate ? 256 : wpf->max_width;
474 }
475
476 static void wpf_partition(struct vsp1_entity *entity,
477                           struct vsp1_pipeline *pipe,
478                           struct vsp1_partition *partition,
479                           unsigned int partition_idx,
480                           struct vsp1_partition_window *window)
481 {
482         partition->wpf = *window;
483 }
484
485 static const struct vsp1_entity_operations wpf_entity_ops = {
486         .destroy = vsp1_wpf_destroy,
487         .configure = wpf_configure,
488         .max_width = wpf_max_width,
489         .partition = wpf_partition,
490 };
491
492 /* -----------------------------------------------------------------------------
493  * Initialization and Cleanup
494  */
495
496 struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
497 {
498         struct vsp1_rwpf *wpf;
499         char name[6];
500         int ret;
501
502         wpf = devm_kzalloc(vsp1->dev, sizeof(*wpf), GFP_KERNEL);
503         if (wpf == NULL)
504                 return ERR_PTR(-ENOMEM);
505
506         if (vsp1->info->gen == 2) {
507                 wpf->max_width = WPF_GEN2_MAX_WIDTH;
508                 wpf->max_height = WPF_GEN2_MAX_HEIGHT;
509         } else {
510                 wpf->max_width = WPF_GEN3_MAX_WIDTH;
511                 wpf->max_height = WPF_GEN3_MAX_HEIGHT;
512         }
513
514         wpf->entity.ops = &wpf_entity_ops;
515         wpf->entity.type = VSP1_ENTITY_WPF;
516         wpf->entity.index = index;
517
518         sprintf(name, "wpf.%u", index);
519         ret = vsp1_entity_init(vsp1, &wpf->entity, name, 2, &wpf_ops,
520                                MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER);
521         if (ret < 0)
522                 return ERR_PTR(ret);
523
524         /* Initialize the display list manager. */
525         wpf->dlm = vsp1_dlm_create(vsp1, index, 64);
526         if (!wpf->dlm) {
527                 ret = -ENOMEM;
528                 goto error;
529         }
530
531         /* Initialize the control handler. */
532         ret = wpf_init_controls(wpf);
533         if (ret < 0) {
534                 dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n",
535                         index);
536                 goto error;
537         }
538
539         v4l2_ctrl_handler_setup(&wpf->ctrls);
540
541         return wpf;
542
543 error:
544         vsp1_entity_destroy(&wpf->entity);
545         return ERR_PTR(ret);
546 }