Merge tag 'acpi-5.3-rc1-3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[linux-2.6-block.git] / drivers / gpu / drm / imx / ipuv3-plane.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * i.MX IPUv3 DP Overlay Planes
4  *
5  * Copyright (C) 2013 Philipp Zabel, Pengutronix
6  */
7
8 #include <drm/drmP.h>
9 #include <drm/drm_atomic.h>
10 #include <drm/drm_atomic_helper.h>
11 #include <drm/drm_fb_cma_helper.h>
12 #include <drm/drm_gem_cma_helper.h>
13 #include <drm/drm_gem_framebuffer_helper.h>
14 #include <drm/drm_plane_helper.h>
15
16 #include "video/imx-ipu-v3.h"
17 #include "imx-drm.h"
18 #include "ipuv3-plane.h"
19
20 struct ipu_plane_state {
21         struct drm_plane_state base;
22         bool use_pre;
23 };
24
25 static inline struct ipu_plane_state *
26 to_ipu_plane_state(struct drm_plane_state *p)
27 {
28         return container_of(p, struct ipu_plane_state, base);
29 }
30
31 static inline struct ipu_plane *to_ipu_plane(struct drm_plane *p)
32 {
33         return container_of(p, struct ipu_plane, base);
34 }
35
36 static const uint32_t ipu_plane_formats[] = {
37         DRM_FORMAT_ARGB1555,
38         DRM_FORMAT_XRGB1555,
39         DRM_FORMAT_ABGR1555,
40         DRM_FORMAT_XBGR1555,
41         DRM_FORMAT_RGBA5551,
42         DRM_FORMAT_BGRA5551,
43         DRM_FORMAT_ARGB4444,
44         DRM_FORMAT_ARGB8888,
45         DRM_FORMAT_XRGB8888,
46         DRM_FORMAT_ABGR8888,
47         DRM_FORMAT_XBGR8888,
48         DRM_FORMAT_RGBA8888,
49         DRM_FORMAT_RGBX8888,
50         DRM_FORMAT_BGRA8888,
51         DRM_FORMAT_BGRX8888,
52         DRM_FORMAT_UYVY,
53         DRM_FORMAT_VYUY,
54         DRM_FORMAT_YUYV,
55         DRM_FORMAT_YVYU,
56         DRM_FORMAT_YUV420,
57         DRM_FORMAT_YVU420,
58         DRM_FORMAT_YUV422,
59         DRM_FORMAT_YVU422,
60         DRM_FORMAT_YUV444,
61         DRM_FORMAT_YVU444,
62         DRM_FORMAT_NV12,
63         DRM_FORMAT_NV16,
64         DRM_FORMAT_RGB565,
65         DRM_FORMAT_RGB565_A8,
66         DRM_FORMAT_BGR565_A8,
67         DRM_FORMAT_RGB888_A8,
68         DRM_FORMAT_BGR888_A8,
69         DRM_FORMAT_RGBX8888_A8,
70         DRM_FORMAT_BGRX8888_A8,
71 };
72
73 static const uint64_t ipu_format_modifiers[] = {
74         DRM_FORMAT_MOD_LINEAR,
75         DRM_FORMAT_MOD_INVALID
76 };
77
78 static const uint64_t pre_format_modifiers[] = {
79         DRM_FORMAT_MOD_LINEAR,
80         DRM_FORMAT_MOD_VIVANTE_TILED,
81         DRM_FORMAT_MOD_VIVANTE_SUPER_TILED,
82         DRM_FORMAT_MOD_INVALID
83 };
84
85 int ipu_plane_irq(struct ipu_plane *ipu_plane)
86 {
87         return ipu_idmac_channel_irq(ipu_plane->ipu, ipu_plane->ipu_ch,
88                                      IPU_IRQ_EOF);
89 }
90
91 static inline unsigned long
92 drm_plane_state_to_eba(struct drm_plane_state *state, int plane)
93 {
94         struct drm_framebuffer *fb = state->fb;
95         struct drm_gem_cma_object *cma_obj;
96         int x = state->src.x1 >> 16;
97         int y = state->src.y1 >> 16;
98
99         cma_obj = drm_fb_cma_get_gem_obj(fb, plane);
100         BUG_ON(!cma_obj);
101
102         return cma_obj->paddr + fb->offsets[plane] + fb->pitches[plane] * y +
103                fb->format->cpp[plane] * x;
104 }
105
106 static inline unsigned long
107 drm_plane_state_to_ubo(struct drm_plane_state *state)
108 {
109         struct drm_framebuffer *fb = state->fb;
110         struct drm_gem_cma_object *cma_obj;
111         unsigned long eba = drm_plane_state_to_eba(state, 0);
112         int x = state->src.x1 >> 16;
113         int y = state->src.y1 >> 16;
114
115         cma_obj = drm_fb_cma_get_gem_obj(fb, 1);
116         BUG_ON(!cma_obj);
117
118         x /= fb->format->hsub;
119         y /= fb->format->vsub;
120
121         return cma_obj->paddr + fb->offsets[1] + fb->pitches[1] * y +
122                fb->format->cpp[1] * x - eba;
123 }
124
125 static inline unsigned long
126 drm_plane_state_to_vbo(struct drm_plane_state *state)
127 {
128         struct drm_framebuffer *fb = state->fb;
129         struct drm_gem_cma_object *cma_obj;
130         unsigned long eba = drm_plane_state_to_eba(state, 0);
131         int x = state->src.x1 >> 16;
132         int y = state->src.y1 >> 16;
133
134         cma_obj = drm_fb_cma_get_gem_obj(fb, 2);
135         BUG_ON(!cma_obj);
136
137         x /= fb->format->hsub;
138         y /= fb->format->vsub;
139
140         return cma_obj->paddr + fb->offsets[2] + fb->pitches[2] * y +
141                fb->format->cpp[2] * x - eba;
142 }
143
144 void ipu_plane_put_resources(struct ipu_plane *ipu_plane)
145 {
146         if (!IS_ERR_OR_NULL(ipu_plane->dp))
147                 ipu_dp_put(ipu_plane->dp);
148         if (!IS_ERR_OR_NULL(ipu_plane->dmfc))
149                 ipu_dmfc_put(ipu_plane->dmfc);
150         if (!IS_ERR_OR_NULL(ipu_plane->ipu_ch))
151                 ipu_idmac_put(ipu_plane->ipu_ch);
152         if (!IS_ERR_OR_NULL(ipu_plane->alpha_ch))
153                 ipu_idmac_put(ipu_plane->alpha_ch);
154 }
155
156 int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
157 {
158         int ret;
159         int alpha_ch;
160
161         ipu_plane->ipu_ch = ipu_idmac_get(ipu_plane->ipu, ipu_plane->dma);
162         if (IS_ERR(ipu_plane->ipu_ch)) {
163                 ret = PTR_ERR(ipu_plane->ipu_ch);
164                 DRM_ERROR("failed to get idmac channel: %d\n", ret);
165                 return ret;
166         }
167
168         alpha_ch = ipu_channel_alpha_channel(ipu_plane->dma);
169         if (alpha_ch >= 0) {
170                 ipu_plane->alpha_ch = ipu_idmac_get(ipu_plane->ipu, alpha_ch);
171                 if (IS_ERR(ipu_plane->alpha_ch)) {
172                         ret = PTR_ERR(ipu_plane->alpha_ch);
173                         DRM_ERROR("failed to get alpha idmac channel %d: %d\n",
174                                   alpha_ch, ret);
175                         return ret;
176                 }
177         }
178
179         ipu_plane->dmfc = ipu_dmfc_get(ipu_plane->ipu, ipu_plane->dma);
180         if (IS_ERR(ipu_plane->dmfc)) {
181                 ret = PTR_ERR(ipu_plane->dmfc);
182                 DRM_ERROR("failed to get dmfc: ret %d\n", ret);
183                 goto err_out;
184         }
185
186         if (ipu_plane->dp_flow >= 0) {
187                 ipu_plane->dp = ipu_dp_get(ipu_plane->ipu, ipu_plane->dp_flow);
188                 if (IS_ERR(ipu_plane->dp)) {
189                         ret = PTR_ERR(ipu_plane->dp);
190                         DRM_ERROR("failed to get dp flow: %d\n", ret);
191                         goto err_out;
192                 }
193         }
194
195         return 0;
196 err_out:
197         ipu_plane_put_resources(ipu_plane);
198
199         return ret;
200 }
201
202 static bool ipu_plane_separate_alpha(struct ipu_plane *ipu_plane)
203 {
204         switch (ipu_plane->base.state->fb->format->format) {
205         case DRM_FORMAT_RGB565_A8:
206         case DRM_FORMAT_BGR565_A8:
207         case DRM_FORMAT_RGB888_A8:
208         case DRM_FORMAT_BGR888_A8:
209         case DRM_FORMAT_RGBX8888_A8:
210         case DRM_FORMAT_BGRX8888_A8:
211                 return true;
212         default:
213                 return false;
214         }
215 }
216
217 static void ipu_plane_enable(struct ipu_plane *ipu_plane)
218 {
219         if (ipu_plane->dp)
220                 ipu_dp_enable(ipu_plane->ipu);
221         ipu_dmfc_enable_channel(ipu_plane->dmfc);
222         ipu_idmac_enable_channel(ipu_plane->ipu_ch);
223         if (ipu_plane_separate_alpha(ipu_plane))
224                 ipu_idmac_enable_channel(ipu_plane->alpha_ch);
225         if (ipu_plane->dp)
226                 ipu_dp_enable_channel(ipu_plane->dp);
227 }
228
229 void ipu_plane_disable(struct ipu_plane *ipu_plane, bool disable_dp_channel)
230 {
231         int ret;
232
233         DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
234
235         ret = ipu_idmac_wait_busy(ipu_plane->ipu_ch, 50);
236         if (ret == -ETIMEDOUT) {
237                 DRM_ERROR("[PLANE:%d] IDMAC timeout\n",
238                           ipu_plane->base.base.id);
239         }
240
241         if (ipu_plane->dp && disable_dp_channel)
242                 ipu_dp_disable_channel(ipu_plane->dp, false);
243         ipu_idmac_disable_channel(ipu_plane->ipu_ch);
244         if (ipu_plane->alpha_ch)
245                 ipu_idmac_disable_channel(ipu_plane->alpha_ch);
246         ipu_dmfc_disable_channel(ipu_plane->dmfc);
247         if (ipu_plane->dp)
248                 ipu_dp_disable(ipu_plane->ipu);
249         if (ipu_prg_present(ipu_plane->ipu))
250                 ipu_prg_channel_disable(ipu_plane->ipu_ch);
251 }
252
253 void ipu_plane_disable_deferred(struct drm_plane *plane)
254 {
255         struct ipu_plane *ipu_plane = to_ipu_plane(plane);
256
257         if (ipu_plane->disabling) {
258                 ipu_plane->disabling = false;
259                 ipu_plane_disable(ipu_plane, false);
260         }
261 }
262 EXPORT_SYMBOL_GPL(ipu_plane_disable_deferred);
263
264 static void ipu_plane_destroy(struct drm_plane *plane)
265 {
266         struct ipu_plane *ipu_plane = to_ipu_plane(plane);
267
268         DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
269
270         drm_plane_cleanup(plane);
271         kfree(ipu_plane);
272 }
273
274 static void ipu_plane_state_reset(struct drm_plane *plane)
275 {
276         unsigned int zpos = (plane->type == DRM_PLANE_TYPE_PRIMARY) ? 0 : 1;
277         struct ipu_plane_state *ipu_state;
278
279         if (plane->state) {
280                 ipu_state = to_ipu_plane_state(plane->state);
281                 __drm_atomic_helper_plane_destroy_state(plane->state);
282                 kfree(ipu_state);
283                 plane->state = NULL;
284         }
285
286         ipu_state = kzalloc(sizeof(*ipu_state), GFP_KERNEL);
287
288         if (ipu_state) {
289                 __drm_atomic_helper_plane_reset(plane, &ipu_state->base);
290                 ipu_state->base.zpos = zpos;
291                 ipu_state->base.normalized_zpos = zpos;
292         }
293 }
294
295 static struct drm_plane_state *
296 ipu_plane_duplicate_state(struct drm_plane *plane)
297 {
298         struct ipu_plane_state *state;
299
300         if (WARN_ON(!plane->state))
301                 return NULL;
302
303         state = kmalloc(sizeof(*state), GFP_KERNEL);
304         if (state)
305                 __drm_atomic_helper_plane_duplicate_state(plane, &state->base);
306
307         return &state->base;
308 }
309
310 static void ipu_plane_destroy_state(struct drm_plane *plane,
311                                     struct drm_plane_state *state)
312 {
313         struct ipu_plane_state *ipu_state = to_ipu_plane_state(state);
314
315         __drm_atomic_helper_plane_destroy_state(state);
316         kfree(ipu_state);
317 }
318
319 static bool ipu_plane_format_mod_supported(struct drm_plane *plane,
320                                            uint32_t format, uint64_t modifier)
321 {
322         struct ipu_soc *ipu = to_ipu_plane(plane)->ipu;
323
324         /* linear is supported for all planes and formats */
325         if (modifier == DRM_FORMAT_MOD_LINEAR)
326                 return true;
327
328         /* without a PRG there are no supported modifiers */
329         if (!ipu_prg_present(ipu))
330                 return false;
331
332         return ipu_prg_format_supported(ipu, format, modifier);
333 }
334
335 static const struct drm_plane_funcs ipu_plane_funcs = {
336         .update_plane   = drm_atomic_helper_update_plane,
337         .disable_plane  = drm_atomic_helper_disable_plane,
338         .destroy        = ipu_plane_destroy,
339         .reset          = ipu_plane_state_reset,
340         .atomic_duplicate_state = ipu_plane_duplicate_state,
341         .atomic_destroy_state   = ipu_plane_destroy_state,
342         .format_mod_supported = ipu_plane_format_mod_supported,
343 };
344
345 static int ipu_plane_atomic_check(struct drm_plane *plane,
346                                   struct drm_plane_state *state)
347 {
348         struct drm_plane_state *old_state = plane->state;
349         struct drm_crtc_state *crtc_state;
350         struct device *dev = plane->dev->dev;
351         struct drm_framebuffer *fb = state->fb;
352         struct drm_framebuffer *old_fb = old_state->fb;
353         unsigned long eba, ubo, vbo, old_ubo, old_vbo, alpha_eba;
354         bool can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY);
355         int ret;
356
357         /* Ok to disable */
358         if (!fb)
359                 return 0;
360
361         if (!state->crtc)
362                 return -EINVAL;
363
364         crtc_state =
365                 drm_atomic_get_existing_crtc_state(state->state, state->crtc);
366         if (WARN_ON(!crtc_state))
367                 return -EINVAL;
368
369         ret = drm_atomic_helper_check_plane_state(state, crtc_state,
370                                                   DRM_PLANE_HELPER_NO_SCALING,
371                                                   DRM_PLANE_HELPER_NO_SCALING,
372                                                   can_position, true);
373         if (ret)
374                 return ret;
375
376         /* nothing to check when disabling or disabled */
377         if (!crtc_state->enable)
378                 return 0;
379
380         switch (plane->type) {
381         case DRM_PLANE_TYPE_PRIMARY:
382                 /* full plane minimum width is 13 pixels */
383                 if (drm_rect_width(&state->dst) < 13)
384                         return -EINVAL;
385                 break;
386         case DRM_PLANE_TYPE_OVERLAY:
387                 break;
388         default:
389                 dev_warn(dev, "Unsupported plane type %d\n", plane->type);
390                 return -EINVAL;
391         }
392
393         if (drm_rect_height(&state->dst) < 2)
394                 return -EINVAL;
395
396         /*
397          * We support resizing active plane or changing its format by
398          * forcing CRTC mode change in plane's ->atomic_check callback
399          * and disabling all affected active planes in CRTC's ->atomic_disable
400          * callback.  The planes will be reenabled in plane's ->atomic_update
401          * callback.
402          */
403         if (old_fb &&
404             (drm_rect_width(&state->dst) != drm_rect_width(&old_state->dst) ||
405              drm_rect_height(&state->dst) != drm_rect_height(&old_state->dst) ||
406              fb->format != old_fb->format))
407                 crtc_state->mode_changed = true;
408
409         eba = drm_plane_state_to_eba(state, 0);
410
411         if (eba & 0x7)
412                 return -EINVAL;
413
414         if (fb->pitches[0] < 1 || fb->pitches[0] > 16384)
415                 return -EINVAL;
416
417         if (old_fb && fb->pitches[0] != old_fb->pitches[0])
418                 crtc_state->mode_changed = true;
419
420         switch (fb->format->format) {
421         case DRM_FORMAT_YUV420:
422         case DRM_FORMAT_YVU420:
423         case DRM_FORMAT_YUV422:
424         case DRM_FORMAT_YVU422:
425         case DRM_FORMAT_YUV444:
426         case DRM_FORMAT_YVU444:
427                 /*
428                  * Multiplanar formats have to meet the following restrictions:
429                  * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO
430                  * - EBA, UBO and VBO are a multiple of 8
431                  * - UBO and VBO are unsigned and not larger than 0xfffff8
432                  * - Only EBA may be changed while scanout is active
433                  * - The strides of U and V planes must be identical.
434                  */
435                 vbo = drm_plane_state_to_vbo(state);
436
437                 if (vbo & 0x7 || vbo > 0xfffff8)
438                         return -EINVAL;
439
440                 if (old_fb && (fb->format == old_fb->format)) {
441                         old_vbo = drm_plane_state_to_vbo(old_state);
442                         if (vbo != old_vbo)
443                                 crtc_state->mode_changed = true;
444                 }
445
446                 if (fb->pitches[1] != fb->pitches[2])
447                         return -EINVAL;
448
449                 /* fall-through */
450         case DRM_FORMAT_NV12:
451         case DRM_FORMAT_NV16:
452                 ubo = drm_plane_state_to_ubo(state);
453
454                 if (ubo & 0x7 || ubo > 0xfffff8)
455                         return -EINVAL;
456
457                 if (old_fb && (fb->format == old_fb->format)) {
458                         old_ubo = drm_plane_state_to_ubo(old_state);
459                         if (ubo != old_ubo)
460                                 crtc_state->mode_changed = true;
461                 }
462
463                 if (fb->pitches[1] < 1 || fb->pitches[1] > 16384)
464                         return -EINVAL;
465
466                 if (old_fb && old_fb->pitches[1] != fb->pitches[1])
467                         crtc_state->mode_changed = true;
468
469                 /*
470                  * The x/y offsets must be even in case of horizontal/vertical
471                  * chroma subsampling.
472                  */
473                 if (((state->src.x1 >> 16) & (fb->format->hsub - 1)) ||
474                     ((state->src.y1 >> 16) & (fb->format->vsub - 1)))
475                         return -EINVAL;
476                 break;
477         case DRM_FORMAT_RGB565_A8:
478         case DRM_FORMAT_BGR565_A8:
479         case DRM_FORMAT_RGB888_A8:
480         case DRM_FORMAT_BGR888_A8:
481         case DRM_FORMAT_RGBX8888_A8:
482         case DRM_FORMAT_BGRX8888_A8:
483                 alpha_eba = drm_plane_state_to_eba(state, 1);
484                 if (alpha_eba & 0x7)
485                         return -EINVAL;
486
487                 if (fb->pitches[1] < 1 || fb->pitches[1] > 16384)
488                         return -EINVAL;
489
490                 if (old_fb && old_fb->pitches[1] != fb->pitches[1])
491                         crtc_state->mode_changed = true;
492                 break;
493         }
494
495         return 0;
496 }
497
498 static void ipu_plane_atomic_disable(struct drm_plane *plane,
499                                      struct drm_plane_state *old_state)
500 {
501         struct ipu_plane *ipu_plane = to_ipu_plane(plane);
502
503         if (ipu_plane->dp)
504                 ipu_dp_disable_channel(ipu_plane->dp, true);
505         ipu_plane->disabling = true;
506 }
507
508 static int ipu_chan_assign_axi_id(int ipu_chan)
509 {
510         switch (ipu_chan) {
511         case IPUV3_CHANNEL_MEM_BG_SYNC:
512                 return 1;
513         case IPUV3_CHANNEL_MEM_FG_SYNC:
514                 return 2;
515         case IPUV3_CHANNEL_MEM_DC_SYNC:
516                 return 3;
517         default:
518                 return 0;
519         }
520 }
521
522 static void ipu_calculate_bursts(u32 width, u32 cpp, u32 stride,
523                                  u8 *burstsize, u8 *num_bursts)
524 {
525         const unsigned int width_bytes = width * cpp;
526         unsigned int npb, bursts;
527
528         /* Maximum number of pixels per burst without overshooting stride */
529         for (npb = 64 / cpp; npb > 0; --npb) {
530                 if (round_up(width_bytes, npb * cpp) <= stride)
531                         break;
532         }
533         *burstsize = npb;
534
535         /* Maximum number of consecutive bursts without overshooting stride */
536         for (bursts = 8; bursts > 1; bursts /= 2) {
537                 if (round_up(width_bytes, npb * cpp * bursts) <= stride)
538                         break;
539         }
540         *num_bursts = bursts;
541 }
542
543 static void ipu_plane_atomic_update(struct drm_plane *plane,
544                                     struct drm_plane_state *old_state)
545 {
546         struct ipu_plane *ipu_plane = to_ipu_plane(plane);
547         struct drm_plane_state *state = plane->state;
548         struct ipu_plane_state *ipu_state = to_ipu_plane_state(state);
549         struct drm_crtc_state *crtc_state = state->crtc->state;
550         struct drm_framebuffer *fb = state->fb;
551         struct drm_rect *dst = &state->dst;
552         unsigned long eba, ubo, vbo;
553         unsigned long alpha_eba = 0;
554         enum ipu_color_space ics;
555         unsigned int axi_id = 0;
556         const struct drm_format_info *info;
557         u8 burstsize, num_bursts;
558         u32 width, height;
559         int active;
560
561         if (ipu_plane->dp_flow == IPU_DP_FLOW_SYNC_FG)
562                 ipu_dp_set_window_pos(ipu_plane->dp, dst->x1, dst->y1);
563
564         switch (ipu_plane->dp_flow) {
565         case IPU_DP_FLOW_SYNC_BG:
566                 if (state->normalized_zpos == 1) {
567                         ipu_dp_set_global_alpha(ipu_plane->dp,
568                                                 !fb->format->has_alpha, 0xff,
569                                                 true);
570                 } else {
571                         ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true);
572                 }
573                 break;
574         case IPU_DP_FLOW_SYNC_FG:
575                 if (state->normalized_zpos == 1) {
576                         ipu_dp_set_global_alpha(ipu_plane->dp,
577                                                 !fb->format->has_alpha, 0xff,
578                                                 false);
579                 }
580                 break;
581         }
582
583         eba = drm_plane_state_to_eba(state, 0);
584
585         /*
586          * Configure PRG channel and attached PRE, this changes the EBA to an
587          * internal SRAM location.
588          */
589         if (ipu_state->use_pre) {
590                 axi_id = ipu_chan_assign_axi_id(ipu_plane->dma);
591                 ipu_prg_channel_configure(ipu_plane->ipu_ch, axi_id,
592                                           drm_rect_width(&state->src) >> 16,
593                                           drm_rect_height(&state->src) >> 16,
594                                           fb->pitches[0], fb->format->format,
595                                           fb->modifier, &eba);
596         }
597
598         if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) {
599                 /* nothing to do if PRE is used */
600                 if (ipu_state->use_pre)
601                         return;
602                 active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch);
603                 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba);
604                 ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active);
605                 if (ipu_plane_separate_alpha(ipu_plane)) {
606                         active = ipu_idmac_get_current_buffer(ipu_plane->alpha_ch);
607                         ipu_cpmem_set_buffer(ipu_plane->alpha_ch, !active,
608                                              alpha_eba);
609                         ipu_idmac_select_buffer(ipu_plane->alpha_ch, !active);
610                 }
611                 return;
612         }
613
614         ics = ipu_drm_fourcc_to_colorspace(fb->format->format);
615         switch (ipu_plane->dp_flow) {
616         case IPU_DP_FLOW_SYNC_BG:
617                 ipu_dp_setup_channel(ipu_plane->dp, ics, IPUV3_COLORSPACE_RGB);
618                 break;
619         case IPU_DP_FLOW_SYNC_FG:
620                 ipu_dp_setup_channel(ipu_plane->dp, ics,
621                                         IPUV3_COLORSPACE_UNKNOWN);
622                 break;
623         }
624
625         ipu_dmfc_config_wait4eot(ipu_plane->dmfc, drm_rect_width(dst));
626
627         width = drm_rect_width(&state->src) >> 16;
628         height = drm_rect_height(&state->src) >> 16;
629         info = drm_format_info(fb->format->format);
630         ipu_calculate_bursts(width, info->cpp[0], fb->pitches[0],
631                              &burstsize, &num_bursts);
632
633         ipu_cpmem_zero(ipu_plane->ipu_ch);
634         ipu_cpmem_set_resolution(ipu_plane->ipu_ch, width, height);
635         ipu_cpmem_set_fmt(ipu_plane->ipu_ch, fb->format->format);
636         ipu_cpmem_set_burstsize(ipu_plane->ipu_ch, burstsize);
637         ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);
638         ipu_idmac_enable_watermark(ipu_plane->ipu_ch, true);
639         ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1);
640         ipu_cpmem_set_stride(ipu_plane->ipu_ch, fb->pitches[0]);
641         ipu_cpmem_set_axi_id(ipu_plane->ipu_ch, axi_id);
642
643         switch (fb->format->format) {
644         case DRM_FORMAT_YUV420:
645         case DRM_FORMAT_YVU420:
646         case DRM_FORMAT_YUV422:
647         case DRM_FORMAT_YVU422:
648         case DRM_FORMAT_YUV444:
649         case DRM_FORMAT_YVU444:
650                 ubo = drm_plane_state_to_ubo(state);
651                 vbo = drm_plane_state_to_vbo(state);
652                 if (fb->format->format == DRM_FORMAT_YVU420 ||
653                     fb->format->format == DRM_FORMAT_YVU422 ||
654                     fb->format->format == DRM_FORMAT_YVU444)
655                         swap(ubo, vbo);
656
657                 ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
658                                               fb->pitches[1], ubo, vbo);
659
660                 dev_dbg(ipu_plane->base.dev->dev,
661                         "phy = %lu %lu %lu, x = %d, y = %d", eba, ubo, vbo,
662                         state->src.x1 >> 16, state->src.y1 >> 16);
663                 break;
664         case DRM_FORMAT_NV12:
665         case DRM_FORMAT_NV16:
666                 ubo = drm_plane_state_to_ubo(state);
667
668                 ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
669                                               fb->pitches[1], ubo, ubo);
670
671                 dev_dbg(ipu_plane->base.dev->dev,
672                         "phy = %lu %lu, x = %d, y = %d", eba, ubo,
673                         state->src.x1 >> 16, state->src.y1 >> 16);
674                 break;
675         case DRM_FORMAT_RGB565_A8:
676         case DRM_FORMAT_BGR565_A8:
677         case DRM_FORMAT_RGB888_A8:
678         case DRM_FORMAT_BGR888_A8:
679         case DRM_FORMAT_RGBX8888_A8:
680         case DRM_FORMAT_BGRX8888_A8:
681                 alpha_eba = drm_plane_state_to_eba(state, 1);
682                 num_bursts = 0;
683
684                 dev_dbg(ipu_plane->base.dev->dev, "phys = %lu %lu, x = %d, y = %d",
685                         eba, alpha_eba, state->src.x1 >> 16, state->src.y1 >> 16);
686
687                 ipu_cpmem_set_burstsize(ipu_plane->ipu_ch, 16);
688
689                 ipu_cpmem_zero(ipu_plane->alpha_ch);
690                 ipu_cpmem_set_resolution(ipu_plane->alpha_ch,
691                                          drm_rect_width(&state->src) >> 16,
692                                          drm_rect_height(&state->src) >> 16);
693                 ipu_cpmem_set_format_passthrough(ipu_plane->alpha_ch, 8);
694                 ipu_cpmem_set_high_priority(ipu_plane->alpha_ch);
695                 ipu_idmac_set_double_buffer(ipu_plane->alpha_ch, 1);
696                 ipu_cpmem_set_stride(ipu_plane->alpha_ch, fb->pitches[1]);
697                 ipu_cpmem_set_burstsize(ipu_plane->alpha_ch, 16);
698                 ipu_cpmem_set_buffer(ipu_plane->alpha_ch, 0, alpha_eba);
699                 ipu_cpmem_set_buffer(ipu_plane->alpha_ch, 1, alpha_eba);
700                 break;
701         default:
702                 dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d",
703                         eba, state->src.x1 >> 16, state->src.y1 >> 16);
704                 break;
705         }
706         ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba);
707         ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba);
708         ipu_idmac_lock_enable(ipu_plane->ipu_ch, num_bursts);
709         ipu_plane_enable(ipu_plane);
710 }
711
712 static const struct drm_plane_helper_funcs ipu_plane_helper_funcs = {
713         .prepare_fb = drm_gem_fb_prepare_fb,
714         .atomic_check = ipu_plane_atomic_check,
715         .atomic_disable = ipu_plane_atomic_disable,
716         .atomic_update = ipu_plane_atomic_update,
717 };
718
719 bool ipu_plane_atomic_update_pending(struct drm_plane *plane)
720 {
721         struct ipu_plane *ipu_plane = to_ipu_plane(plane);
722         struct drm_plane_state *state = plane->state;
723         struct ipu_plane_state *ipu_state = to_ipu_plane_state(state);
724
725         /* disabled crtcs must not block the update */
726         if (!state->crtc)
727                 return false;
728
729         if (ipu_state->use_pre)
730                 return ipu_prg_channel_configure_pending(ipu_plane->ipu_ch);
731
732         /*
733          * Pretend no update is pending in the non-PRE/PRG case. For this to
734          * happen, an atomic update would have to be deferred until after the
735          * start of the next frame and simultaneously interrupt latency would
736          * have to be high enough to let the atomic update finish and issue an
737          * event before the previous end of frame interrupt handler can be
738          * executed.
739          */
740         return false;
741 }
742 int ipu_planes_assign_pre(struct drm_device *dev,
743                           struct drm_atomic_state *state)
744 {
745         struct drm_crtc_state *old_crtc_state, *crtc_state;
746         struct drm_plane_state *plane_state;
747         struct ipu_plane_state *ipu_state;
748         struct ipu_plane *ipu_plane;
749         struct drm_plane *plane;
750         struct drm_crtc *crtc;
751         int available_pres = ipu_prg_max_active_channels();
752         int ret, i;
753
754         for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, crtc_state, i) {
755                 ret = drm_atomic_add_affected_planes(state, crtc);
756                 if (ret)
757                         return ret;
758         }
759
760         /*
761          * We are going over the planes in 2 passes: first we assign PREs to
762          * planes with a tiling modifier, which need the PREs to resolve into
763          * linear. Any failure to assign a PRE there is fatal. In the second
764          * pass we try to assign PREs to linear FBs, to improve memory access
765          * patterns for them. Failure at this point is non-fatal, as we can
766          * scan out linear FBs without a PRE.
767          */
768         for_each_new_plane_in_state(state, plane, plane_state, i) {
769                 ipu_state = to_ipu_plane_state(plane_state);
770                 ipu_plane = to_ipu_plane(plane);
771
772                 if (!plane_state->fb) {
773                         ipu_state->use_pre = false;
774                         continue;
775                 }
776
777                 if (!(plane_state->fb->flags & DRM_MODE_FB_MODIFIERS) ||
778                     plane_state->fb->modifier == DRM_FORMAT_MOD_LINEAR)
779                         continue;
780
781                 if (!ipu_prg_present(ipu_plane->ipu) || !available_pres)
782                         return -EINVAL;
783
784                 if (!ipu_prg_format_supported(ipu_plane->ipu,
785                                               plane_state->fb->format->format,
786                                               plane_state->fb->modifier))
787                         return -EINVAL;
788
789                 ipu_state->use_pre = true;
790                 available_pres--;
791         }
792
793         for_each_new_plane_in_state(state, plane, plane_state, i) {
794                 ipu_state = to_ipu_plane_state(plane_state);
795                 ipu_plane = to_ipu_plane(plane);
796
797                 if (!plane_state->fb) {
798                         ipu_state->use_pre = false;
799                         continue;
800                 }
801
802                 if ((plane_state->fb->flags & DRM_MODE_FB_MODIFIERS) &&
803                     plane_state->fb->modifier != DRM_FORMAT_MOD_LINEAR)
804                         continue;
805
806                 /* make sure that modifier is initialized */
807                 plane_state->fb->modifier = DRM_FORMAT_MOD_LINEAR;
808
809                 if (ipu_prg_present(ipu_plane->ipu) && available_pres &&
810                     ipu_prg_format_supported(ipu_plane->ipu,
811                                              plane_state->fb->format->format,
812                                              plane_state->fb->modifier)) {
813                         ipu_state->use_pre = true;
814                         available_pres--;
815                 } else {
816                         ipu_state->use_pre = false;
817                 }
818         }
819
820         return 0;
821 }
822 EXPORT_SYMBOL_GPL(ipu_planes_assign_pre);
823
824 struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
825                                  int dma, int dp, unsigned int possible_crtcs,
826                                  enum drm_plane_type type)
827 {
828         struct ipu_plane *ipu_plane;
829         const uint64_t *modifiers = ipu_format_modifiers;
830         unsigned int zpos = (type == DRM_PLANE_TYPE_PRIMARY) ? 0 : 1;
831         int ret;
832
833         DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n",
834                       dma, dp, possible_crtcs);
835
836         ipu_plane = kzalloc(sizeof(*ipu_plane), GFP_KERNEL);
837         if (!ipu_plane) {
838                 DRM_ERROR("failed to allocate plane\n");
839                 return ERR_PTR(-ENOMEM);
840         }
841
842         ipu_plane->ipu = ipu;
843         ipu_plane->dma = dma;
844         ipu_plane->dp_flow = dp;
845
846         if (ipu_prg_present(ipu))
847                 modifiers = pre_format_modifiers;
848
849         ret = drm_universal_plane_init(dev, &ipu_plane->base, possible_crtcs,
850                                        &ipu_plane_funcs, ipu_plane_formats,
851                                        ARRAY_SIZE(ipu_plane_formats),
852                                        modifiers, type, NULL);
853         if (ret) {
854                 DRM_ERROR("failed to initialize plane\n");
855                 kfree(ipu_plane);
856                 return ERR_PTR(ret);
857         }
858
859         drm_plane_helper_add(&ipu_plane->base, &ipu_plane_helper_funcs);
860
861         if (dp == IPU_DP_FLOW_SYNC_BG || dp == IPU_DP_FLOW_SYNC_FG)
862                 drm_plane_create_zpos_property(&ipu_plane->base, zpos, 0, 1);
863         else
864                 drm_plane_create_zpos_immutable_property(&ipu_plane->base, 0);
865
866         return ipu_plane;
867 }