Merge tag 'pidfd-updates-v5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/braun...
[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 /= drm_format_horz_chroma_subsampling(fb->format->format);
119         y /= drm_format_vert_chroma_subsampling(fb->format->format);
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 /= drm_format_horz_chroma_subsampling(fb->format->format);
138         y /= drm_format_vert_chroma_subsampling(fb->format->format);
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 hsub, vsub;
356         int ret;
357
358         /* Ok to disable */
359         if (!fb)
360                 return 0;
361
362         if (!state->crtc)
363                 return -EINVAL;
364
365         crtc_state =
366                 drm_atomic_get_existing_crtc_state(state->state, state->crtc);
367         if (WARN_ON(!crtc_state))
368                 return -EINVAL;
369
370         ret = drm_atomic_helper_check_plane_state(state, crtc_state,
371                                                   DRM_PLANE_HELPER_NO_SCALING,
372                                                   DRM_PLANE_HELPER_NO_SCALING,
373                                                   can_position, true);
374         if (ret)
375                 return ret;
376
377         /* nothing to check when disabling or disabled */
378         if (!crtc_state->enable)
379                 return 0;
380
381         switch (plane->type) {
382         case DRM_PLANE_TYPE_PRIMARY:
383                 /* full plane minimum width is 13 pixels */
384                 if (drm_rect_width(&state->dst) < 13)
385                         return -EINVAL;
386                 break;
387         case DRM_PLANE_TYPE_OVERLAY:
388                 break;
389         default:
390                 dev_warn(dev, "Unsupported plane type %d\n", plane->type);
391                 return -EINVAL;
392         }
393
394         if (drm_rect_height(&state->dst) < 2)
395                 return -EINVAL;
396
397         /*
398          * We support resizing active plane or changing its format by
399          * forcing CRTC mode change in plane's ->atomic_check callback
400          * and disabling all affected active planes in CRTC's ->atomic_disable
401          * callback.  The planes will be reenabled in plane's ->atomic_update
402          * callback.
403          */
404         if (old_fb &&
405             (drm_rect_width(&state->dst) != drm_rect_width(&old_state->dst) ||
406              drm_rect_height(&state->dst) != drm_rect_height(&old_state->dst) ||
407              fb->format != old_fb->format))
408                 crtc_state->mode_changed = true;
409
410         eba = drm_plane_state_to_eba(state, 0);
411
412         if (eba & 0x7)
413                 return -EINVAL;
414
415         if (fb->pitches[0] < 1 || fb->pitches[0] > 16384)
416                 return -EINVAL;
417
418         if (old_fb && fb->pitches[0] != old_fb->pitches[0])
419                 crtc_state->mode_changed = true;
420
421         switch (fb->format->format) {
422         case DRM_FORMAT_YUV420:
423         case DRM_FORMAT_YVU420:
424         case DRM_FORMAT_YUV422:
425         case DRM_FORMAT_YVU422:
426         case DRM_FORMAT_YUV444:
427         case DRM_FORMAT_YVU444:
428                 /*
429                  * Multiplanar formats have to meet the following restrictions:
430                  * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO
431                  * - EBA, UBO and VBO are a multiple of 8
432                  * - UBO and VBO are unsigned and not larger than 0xfffff8
433                  * - Only EBA may be changed while scanout is active
434                  * - The strides of U and V planes must be identical.
435                  */
436                 vbo = drm_plane_state_to_vbo(state);
437
438                 if (vbo & 0x7 || vbo > 0xfffff8)
439                         return -EINVAL;
440
441                 if (old_fb && (fb->format == old_fb->format)) {
442                         old_vbo = drm_plane_state_to_vbo(old_state);
443                         if (vbo != old_vbo)
444                                 crtc_state->mode_changed = true;
445                 }
446
447                 if (fb->pitches[1] != fb->pitches[2])
448                         return -EINVAL;
449
450                 /* fall-through */
451         case DRM_FORMAT_NV12:
452         case DRM_FORMAT_NV16:
453                 ubo = drm_plane_state_to_ubo(state);
454
455                 if (ubo & 0x7 || ubo > 0xfffff8)
456                         return -EINVAL;
457
458                 if (old_fb && (fb->format == old_fb->format)) {
459                         old_ubo = drm_plane_state_to_ubo(old_state);
460                         if (ubo != old_ubo)
461                                 crtc_state->mode_changed = true;
462                 }
463
464                 if (fb->pitches[1] < 1 || fb->pitches[1] > 16384)
465                         return -EINVAL;
466
467                 if (old_fb && old_fb->pitches[1] != fb->pitches[1])
468                         crtc_state->mode_changed = true;
469
470                 /*
471                  * The x/y offsets must be even in case of horizontal/vertical
472                  * chroma subsampling.
473                  */
474                 hsub = drm_format_horz_chroma_subsampling(fb->format->format);
475                 vsub = drm_format_vert_chroma_subsampling(fb->format->format);
476                 if (((state->src.x1 >> 16) & (hsub - 1)) ||
477                     ((state->src.y1 >> 16) & (vsub - 1)))
478                         return -EINVAL;
479                 break;
480         case DRM_FORMAT_RGB565_A8:
481         case DRM_FORMAT_BGR565_A8:
482         case DRM_FORMAT_RGB888_A8:
483         case DRM_FORMAT_BGR888_A8:
484         case DRM_FORMAT_RGBX8888_A8:
485         case DRM_FORMAT_BGRX8888_A8:
486                 alpha_eba = drm_plane_state_to_eba(state, 1);
487                 if (alpha_eba & 0x7)
488                         return -EINVAL;
489
490                 if (fb->pitches[1] < 1 || fb->pitches[1] > 16384)
491                         return -EINVAL;
492
493                 if (old_fb && old_fb->pitches[1] != fb->pitches[1])
494                         crtc_state->mode_changed = true;
495                 break;
496         }
497
498         return 0;
499 }
500
501 static void ipu_plane_atomic_disable(struct drm_plane *plane,
502                                      struct drm_plane_state *old_state)
503 {
504         struct ipu_plane *ipu_plane = to_ipu_plane(plane);
505
506         if (ipu_plane->dp)
507                 ipu_dp_disable_channel(ipu_plane->dp, true);
508         ipu_plane->disabling = true;
509 }
510
511 static int ipu_chan_assign_axi_id(int ipu_chan)
512 {
513         switch (ipu_chan) {
514         case IPUV3_CHANNEL_MEM_BG_SYNC:
515                 return 1;
516         case IPUV3_CHANNEL_MEM_FG_SYNC:
517                 return 2;
518         case IPUV3_CHANNEL_MEM_DC_SYNC:
519                 return 3;
520         default:
521                 return 0;
522         }
523 }
524
525 static void ipu_calculate_bursts(u32 width, u32 cpp, u32 stride,
526                                  u8 *burstsize, u8 *num_bursts)
527 {
528         const unsigned int width_bytes = width * cpp;
529         unsigned int npb, bursts;
530
531         /* Maximum number of pixels per burst without overshooting stride */
532         for (npb = 64 / cpp; npb > 0; --npb) {
533                 if (round_up(width_bytes, npb * cpp) <= stride)
534                         break;
535         }
536         *burstsize = npb;
537
538         /* Maximum number of consecutive bursts without overshooting stride */
539         for (bursts = 8; bursts > 1; bursts /= 2) {
540                 if (round_up(width_bytes, npb * cpp * bursts) <= stride)
541                         break;
542         }
543         *num_bursts = bursts;
544 }
545
546 static void ipu_plane_atomic_update(struct drm_plane *plane,
547                                     struct drm_plane_state *old_state)
548 {
549         struct ipu_plane *ipu_plane = to_ipu_plane(plane);
550         struct drm_plane_state *state = plane->state;
551         struct ipu_plane_state *ipu_state = to_ipu_plane_state(state);
552         struct drm_crtc_state *crtc_state = state->crtc->state;
553         struct drm_framebuffer *fb = state->fb;
554         struct drm_rect *dst = &state->dst;
555         unsigned long eba, ubo, vbo;
556         unsigned long alpha_eba = 0;
557         enum ipu_color_space ics;
558         unsigned int axi_id = 0;
559         const struct drm_format_info *info;
560         u8 burstsize, num_bursts;
561         u32 width, height;
562         int active;
563
564         if (ipu_plane->dp_flow == IPU_DP_FLOW_SYNC_FG)
565                 ipu_dp_set_window_pos(ipu_plane->dp, dst->x1, dst->y1);
566
567         switch (ipu_plane->dp_flow) {
568         case IPU_DP_FLOW_SYNC_BG:
569                 if (state->normalized_zpos == 1) {
570                         ipu_dp_set_global_alpha(ipu_plane->dp,
571                                                 !fb->format->has_alpha, 0xff,
572                                                 true);
573                 } else {
574                         ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true);
575                 }
576                 break;
577         case IPU_DP_FLOW_SYNC_FG:
578                 if (state->normalized_zpos == 1) {
579                         ipu_dp_set_global_alpha(ipu_plane->dp,
580                                                 !fb->format->has_alpha, 0xff,
581                                                 false);
582                 }
583                 break;
584         }
585
586         eba = drm_plane_state_to_eba(state, 0);
587
588         /*
589          * Configure PRG channel and attached PRE, this changes the EBA to an
590          * internal SRAM location.
591          */
592         if (ipu_state->use_pre) {
593                 axi_id = ipu_chan_assign_axi_id(ipu_plane->dma);
594                 ipu_prg_channel_configure(ipu_plane->ipu_ch, axi_id,
595                                           drm_rect_width(&state->src) >> 16,
596                                           drm_rect_height(&state->src) >> 16,
597                                           fb->pitches[0], fb->format->format,
598                                           fb->modifier, &eba);
599         }
600
601         if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) {
602                 /* nothing to do if PRE is used */
603                 if (ipu_state->use_pre)
604                         return;
605                 active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch);
606                 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba);
607                 ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active);
608                 if (ipu_plane_separate_alpha(ipu_plane)) {
609                         active = ipu_idmac_get_current_buffer(ipu_plane->alpha_ch);
610                         ipu_cpmem_set_buffer(ipu_plane->alpha_ch, !active,
611                                              alpha_eba);
612                         ipu_idmac_select_buffer(ipu_plane->alpha_ch, !active);
613                 }
614                 return;
615         }
616
617         ics = ipu_drm_fourcc_to_colorspace(fb->format->format);
618         switch (ipu_plane->dp_flow) {
619         case IPU_DP_FLOW_SYNC_BG:
620                 ipu_dp_setup_channel(ipu_plane->dp, ics, IPUV3_COLORSPACE_RGB);
621                 break;
622         case IPU_DP_FLOW_SYNC_FG:
623                 ipu_dp_setup_channel(ipu_plane->dp, ics,
624                                         IPUV3_COLORSPACE_UNKNOWN);
625                 break;
626         }
627
628         ipu_dmfc_config_wait4eot(ipu_plane->dmfc, drm_rect_width(dst));
629
630         width = drm_rect_width(&state->src) >> 16;
631         height = drm_rect_height(&state->src) >> 16;
632         info = drm_format_info(fb->format->format);
633         ipu_calculate_bursts(width, info->cpp[0], fb->pitches[0],
634                              &burstsize, &num_bursts);
635
636         ipu_cpmem_zero(ipu_plane->ipu_ch);
637         ipu_cpmem_set_resolution(ipu_plane->ipu_ch, width, height);
638         ipu_cpmem_set_fmt(ipu_plane->ipu_ch, fb->format->format);
639         ipu_cpmem_set_burstsize(ipu_plane->ipu_ch, burstsize);
640         ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);
641         ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1);
642         ipu_cpmem_set_stride(ipu_plane->ipu_ch, fb->pitches[0]);
643         ipu_cpmem_set_axi_id(ipu_plane->ipu_ch, axi_id);
644
645         switch (fb->format->format) {
646         case DRM_FORMAT_YUV420:
647         case DRM_FORMAT_YVU420:
648         case DRM_FORMAT_YUV422:
649         case DRM_FORMAT_YVU422:
650         case DRM_FORMAT_YUV444:
651         case DRM_FORMAT_YVU444:
652                 ubo = drm_plane_state_to_ubo(state);
653                 vbo = drm_plane_state_to_vbo(state);
654                 if (fb->format->format == DRM_FORMAT_YVU420 ||
655                     fb->format->format == DRM_FORMAT_YVU422 ||
656                     fb->format->format == DRM_FORMAT_YVU444)
657                         swap(ubo, vbo);
658
659                 ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
660                                               fb->pitches[1], ubo, vbo);
661
662                 dev_dbg(ipu_plane->base.dev->dev,
663                         "phy = %lu %lu %lu, x = %d, y = %d", eba, ubo, vbo,
664                         state->src.x1 >> 16, state->src.y1 >> 16);
665                 break;
666         case DRM_FORMAT_NV12:
667         case DRM_FORMAT_NV16:
668                 ubo = drm_plane_state_to_ubo(state);
669
670                 ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
671                                               fb->pitches[1], ubo, ubo);
672
673                 dev_dbg(ipu_plane->base.dev->dev,
674                         "phy = %lu %lu, x = %d, y = %d", eba, ubo,
675                         state->src.x1 >> 16, state->src.y1 >> 16);
676                 break;
677         case DRM_FORMAT_RGB565_A8:
678         case DRM_FORMAT_BGR565_A8:
679         case DRM_FORMAT_RGB888_A8:
680         case DRM_FORMAT_BGR888_A8:
681         case DRM_FORMAT_RGBX8888_A8:
682         case DRM_FORMAT_BGRX8888_A8:
683                 alpha_eba = drm_plane_state_to_eba(state, 1);
684                 num_bursts = 0;
685
686                 dev_dbg(ipu_plane->base.dev->dev, "phys = %lu %lu, x = %d, y = %d",
687                         eba, alpha_eba, state->src.x1 >> 16, state->src.y1 >> 16);
688
689                 ipu_cpmem_set_burstsize(ipu_plane->ipu_ch, 16);
690
691                 ipu_cpmem_zero(ipu_plane->alpha_ch);
692                 ipu_cpmem_set_resolution(ipu_plane->alpha_ch,
693                                          drm_rect_width(&state->src) >> 16,
694                                          drm_rect_height(&state->src) >> 16);
695                 ipu_cpmem_set_format_passthrough(ipu_plane->alpha_ch, 8);
696                 ipu_cpmem_set_high_priority(ipu_plane->alpha_ch);
697                 ipu_idmac_set_double_buffer(ipu_plane->alpha_ch, 1);
698                 ipu_cpmem_set_stride(ipu_plane->alpha_ch, fb->pitches[1]);
699                 ipu_cpmem_set_burstsize(ipu_plane->alpha_ch, 16);
700                 ipu_cpmem_set_buffer(ipu_plane->alpha_ch, 0, alpha_eba);
701                 ipu_cpmem_set_buffer(ipu_plane->alpha_ch, 1, alpha_eba);
702                 break;
703         default:
704                 dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d",
705                         eba, state->src.x1 >> 16, state->src.y1 >> 16);
706                 break;
707         }
708         ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba);
709         ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba);
710         ipu_idmac_lock_enable(ipu_plane->ipu_ch, num_bursts);
711         ipu_plane_enable(ipu_plane);
712 }
713
714 static const struct drm_plane_helper_funcs ipu_plane_helper_funcs = {
715         .prepare_fb = drm_gem_fb_prepare_fb,
716         .atomic_check = ipu_plane_atomic_check,
717         .atomic_disable = ipu_plane_atomic_disable,
718         .atomic_update = ipu_plane_atomic_update,
719 };
720
721 bool ipu_plane_atomic_update_pending(struct drm_plane *plane)
722 {
723         struct ipu_plane *ipu_plane = to_ipu_plane(plane);
724         struct drm_plane_state *state = plane->state;
725         struct ipu_plane_state *ipu_state = to_ipu_plane_state(state);
726
727         /* disabled crtcs must not block the update */
728         if (!state->crtc)
729                 return false;
730
731         if (ipu_state->use_pre)
732                 return ipu_prg_channel_configure_pending(ipu_plane->ipu_ch);
733
734         /*
735          * Pretend no update is pending in the non-PRE/PRG case. For this to
736          * happen, an atomic update would have to be deferred until after the
737          * start of the next frame and simultaneously interrupt latency would
738          * have to be high enough to let the atomic update finish and issue an
739          * event before the previous end of frame interrupt handler can be
740          * executed.
741          */
742         return false;
743 }
744 int ipu_planes_assign_pre(struct drm_device *dev,
745                           struct drm_atomic_state *state)
746 {
747         struct drm_crtc_state *old_crtc_state, *crtc_state;
748         struct drm_plane_state *plane_state;
749         struct ipu_plane_state *ipu_state;
750         struct ipu_plane *ipu_plane;
751         struct drm_plane *plane;
752         struct drm_crtc *crtc;
753         int available_pres = ipu_prg_max_active_channels();
754         int ret, i;
755
756         for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, crtc_state, i) {
757                 ret = drm_atomic_add_affected_planes(state, crtc);
758                 if (ret)
759                         return ret;
760         }
761
762         /*
763          * We are going over the planes in 2 passes: first we assign PREs to
764          * planes with a tiling modifier, which need the PREs to resolve into
765          * linear. Any failure to assign a PRE there is fatal. In the second
766          * pass we try to assign PREs to linear FBs, to improve memory access
767          * patterns for them. Failure at this point is non-fatal, as we can
768          * scan out linear FBs without a PRE.
769          */
770         for_each_new_plane_in_state(state, plane, plane_state, i) {
771                 ipu_state = to_ipu_plane_state(plane_state);
772                 ipu_plane = to_ipu_plane(plane);
773
774                 if (!plane_state->fb) {
775                         ipu_state->use_pre = false;
776                         continue;
777                 }
778
779                 if (!(plane_state->fb->flags & DRM_MODE_FB_MODIFIERS) ||
780                     plane_state->fb->modifier == DRM_FORMAT_MOD_LINEAR)
781                         continue;
782
783                 if (!ipu_prg_present(ipu_plane->ipu) || !available_pres)
784                         return -EINVAL;
785
786                 if (!ipu_prg_format_supported(ipu_plane->ipu,
787                                               plane_state->fb->format->format,
788                                               plane_state->fb->modifier))
789                         return -EINVAL;
790
791                 ipu_state->use_pre = true;
792                 available_pres--;
793         }
794
795         for_each_new_plane_in_state(state, plane, plane_state, i) {
796                 ipu_state = to_ipu_plane_state(plane_state);
797                 ipu_plane = to_ipu_plane(plane);
798
799                 if (!plane_state->fb) {
800                         ipu_state->use_pre = false;
801                         continue;
802                 }
803
804                 if ((plane_state->fb->flags & DRM_MODE_FB_MODIFIERS) &&
805                     plane_state->fb->modifier != DRM_FORMAT_MOD_LINEAR)
806                         continue;
807
808                 /* make sure that modifier is initialized */
809                 plane_state->fb->modifier = DRM_FORMAT_MOD_LINEAR;
810
811                 if (ipu_prg_present(ipu_plane->ipu) && available_pres &&
812                     ipu_prg_format_supported(ipu_plane->ipu,
813                                              plane_state->fb->format->format,
814                                              plane_state->fb->modifier)) {
815                         ipu_state->use_pre = true;
816                         available_pres--;
817                 } else {
818                         ipu_state->use_pre = false;
819                 }
820         }
821
822         return 0;
823 }
824 EXPORT_SYMBOL_GPL(ipu_planes_assign_pre);
825
826 struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
827                                  int dma, int dp, unsigned int possible_crtcs,
828                                  enum drm_plane_type type)
829 {
830         struct ipu_plane *ipu_plane;
831         const uint64_t *modifiers = ipu_format_modifiers;
832         unsigned int zpos = (type == DRM_PLANE_TYPE_PRIMARY) ? 0 : 1;
833         int ret;
834
835         DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n",
836                       dma, dp, possible_crtcs);
837
838         ipu_plane = kzalloc(sizeof(*ipu_plane), GFP_KERNEL);
839         if (!ipu_plane) {
840                 DRM_ERROR("failed to allocate plane\n");
841                 return ERR_PTR(-ENOMEM);
842         }
843
844         ipu_plane->ipu = ipu;
845         ipu_plane->dma = dma;
846         ipu_plane->dp_flow = dp;
847
848         if (ipu_prg_present(ipu))
849                 modifiers = pre_format_modifiers;
850
851         ret = drm_universal_plane_init(dev, &ipu_plane->base, possible_crtcs,
852                                        &ipu_plane_funcs, ipu_plane_formats,
853                                        ARRAY_SIZE(ipu_plane_formats),
854                                        modifiers, type, NULL);
855         if (ret) {
856                 DRM_ERROR("failed to initialize plane\n");
857                 kfree(ipu_plane);
858                 return ERR_PTR(ret);
859         }
860
861         drm_plane_helper_add(&ipu_plane->base, &ipu_plane_helper_funcs);
862
863         if (dp == IPU_DP_FLOW_SYNC_BG || dp == IPU_DP_FLOW_SYNC_FG)
864                 drm_plane_create_zpos_property(&ipu_plane->base, zpos, 0, 1);
865         else
866                 drm_plane_create_zpos_immutable_property(&ipu_plane->base, 0);
867
868         return ipu_plane;
869 }