Merge tag 'csky-for-linus-4.21' of git://github.com/c-sky/csky-linux
[sfrench/cifs-2.6.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         struct ipu_plane_state *ipu_state;
277
278         if (plane->state) {
279                 ipu_state = to_ipu_plane_state(plane->state);
280                 __drm_atomic_helper_plane_destroy_state(plane->state);
281                 kfree(ipu_state);
282                 plane->state = NULL;
283         }
284
285         ipu_state = kzalloc(sizeof(*ipu_state), GFP_KERNEL);
286
287         if (ipu_state)
288                 __drm_atomic_helper_plane_reset(plane, &ipu_state->base);
289 }
290
291 static struct drm_plane_state *
292 ipu_plane_duplicate_state(struct drm_plane *plane)
293 {
294         struct ipu_plane_state *state;
295
296         if (WARN_ON(!plane->state))
297                 return NULL;
298
299         state = kmalloc(sizeof(*state), GFP_KERNEL);
300         if (state)
301                 __drm_atomic_helper_plane_duplicate_state(plane, &state->base);
302
303         return &state->base;
304 }
305
306 static void ipu_plane_destroy_state(struct drm_plane *plane,
307                                     struct drm_plane_state *state)
308 {
309         struct ipu_plane_state *ipu_state = to_ipu_plane_state(state);
310
311         __drm_atomic_helper_plane_destroy_state(state);
312         kfree(ipu_state);
313 }
314
315 static bool ipu_plane_format_mod_supported(struct drm_plane *plane,
316                                            uint32_t format, uint64_t modifier)
317 {
318         struct ipu_soc *ipu = to_ipu_plane(plane)->ipu;
319
320         /* linear is supported for all planes and formats */
321         if (modifier == DRM_FORMAT_MOD_LINEAR)
322                 return true;
323
324         /* without a PRG there are no supported modifiers */
325         if (!ipu_prg_present(ipu))
326                 return false;
327
328         return ipu_prg_format_supported(ipu, format, modifier);
329 }
330
331 static const struct drm_plane_funcs ipu_plane_funcs = {
332         .update_plane   = drm_atomic_helper_update_plane,
333         .disable_plane  = drm_atomic_helper_disable_plane,
334         .destroy        = ipu_plane_destroy,
335         .reset          = ipu_plane_state_reset,
336         .atomic_duplicate_state = ipu_plane_duplicate_state,
337         .atomic_destroy_state   = ipu_plane_destroy_state,
338         .format_mod_supported = ipu_plane_format_mod_supported,
339 };
340
341 static int ipu_plane_atomic_check(struct drm_plane *plane,
342                                   struct drm_plane_state *state)
343 {
344         struct drm_plane_state *old_state = plane->state;
345         struct drm_crtc_state *crtc_state;
346         struct device *dev = plane->dev->dev;
347         struct drm_framebuffer *fb = state->fb;
348         struct drm_framebuffer *old_fb = old_state->fb;
349         unsigned long eba, ubo, vbo, old_ubo, old_vbo, alpha_eba;
350         bool can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY);
351         int hsub, vsub;
352         int ret;
353
354         /* Ok to disable */
355         if (!fb)
356                 return 0;
357
358         if (!state->crtc)
359                 return -EINVAL;
360
361         crtc_state =
362                 drm_atomic_get_existing_crtc_state(state->state, state->crtc);
363         if (WARN_ON(!crtc_state))
364                 return -EINVAL;
365
366         ret = drm_atomic_helper_check_plane_state(state, crtc_state,
367                                                   DRM_PLANE_HELPER_NO_SCALING,
368                                                   DRM_PLANE_HELPER_NO_SCALING,
369                                                   can_position, true);
370         if (ret)
371                 return ret;
372
373         /* CRTC should be enabled */
374         if (!crtc_state->enable)
375                 return -EINVAL;
376
377         switch (plane->type) {
378         case DRM_PLANE_TYPE_PRIMARY:
379                 /* full plane minimum width is 13 pixels */
380                 if (drm_rect_width(&state->dst) < 13)
381                         return -EINVAL;
382                 break;
383         case DRM_PLANE_TYPE_OVERLAY:
384                 break;
385         default:
386                 dev_warn(dev, "Unsupported plane type %d\n", plane->type);
387                 return -EINVAL;
388         }
389
390         if (drm_rect_height(&state->dst) < 2)
391                 return -EINVAL;
392
393         /*
394          * We support resizing active plane or changing its format by
395          * forcing CRTC mode change in plane's ->atomic_check callback
396          * and disabling all affected active planes in CRTC's ->atomic_disable
397          * callback.  The planes will be reenabled in plane's ->atomic_update
398          * callback.
399          */
400         if (old_fb &&
401             (drm_rect_width(&state->dst) != drm_rect_width(&old_state->dst) ||
402              drm_rect_height(&state->dst) != drm_rect_height(&old_state->dst) ||
403              fb->format != old_fb->format))
404                 crtc_state->mode_changed = true;
405
406         eba = drm_plane_state_to_eba(state, 0);
407
408         if (eba & 0x7)
409                 return -EINVAL;
410
411         if (fb->pitches[0] < 1 || fb->pitches[0] > 16384)
412                 return -EINVAL;
413
414         if (old_fb && fb->pitches[0] != old_fb->pitches[0])
415                 crtc_state->mode_changed = true;
416
417         switch (fb->format->format) {
418         case DRM_FORMAT_YUV420:
419         case DRM_FORMAT_YVU420:
420         case DRM_FORMAT_YUV422:
421         case DRM_FORMAT_YVU422:
422         case DRM_FORMAT_YUV444:
423         case DRM_FORMAT_YVU444:
424                 /*
425                  * Multiplanar formats have to meet the following restrictions:
426                  * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO
427                  * - EBA, UBO and VBO are a multiple of 8
428                  * - UBO and VBO are unsigned and not larger than 0xfffff8
429                  * - Only EBA may be changed while scanout is active
430                  * - The strides of U and V planes must be identical.
431                  */
432                 vbo = drm_plane_state_to_vbo(state);
433
434                 if (vbo & 0x7 || vbo > 0xfffff8)
435                         return -EINVAL;
436
437                 if (old_fb && (fb->format == old_fb->format)) {
438                         old_vbo = drm_plane_state_to_vbo(old_state);
439                         if (vbo != old_vbo)
440                                 crtc_state->mode_changed = true;
441                 }
442
443                 if (fb->pitches[1] != fb->pitches[2])
444                         return -EINVAL;
445
446                 /* fall-through */
447         case DRM_FORMAT_NV12:
448         case DRM_FORMAT_NV16:
449                 ubo = drm_plane_state_to_ubo(state);
450
451                 if (ubo & 0x7 || ubo > 0xfffff8)
452                         return -EINVAL;
453
454                 if (old_fb && (fb->format == old_fb->format)) {
455                         old_ubo = drm_plane_state_to_ubo(old_state);
456                         if (ubo != old_ubo)
457                                 crtc_state->mode_changed = true;
458                 }
459
460                 if (fb->pitches[1] < 1 || fb->pitches[1] > 16384)
461                         return -EINVAL;
462
463                 if (old_fb && old_fb->pitches[1] != fb->pitches[1])
464                         crtc_state->mode_changed = true;
465
466                 /*
467                  * The x/y offsets must be even in case of horizontal/vertical
468                  * chroma subsampling.
469                  */
470                 hsub = drm_format_horz_chroma_subsampling(fb->format->format);
471                 vsub = drm_format_vert_chroma_subsampling(fb->format->format);
472                 if (((state->src.x1 >> 16) & (hsub - 1)) ||
473                     ((state->src.y1 >> 16) & (vsub - 1)))
474                         return -EINVAL;
475                 break;
476         case DRM_FORMAT_RGB565_A8:
477         case DRM_FORMAT_BGR565_A8:
478         case DRM_FORMAT_RGB888_A8:
479         case DRM_FORMAT_BGR888_A8:
480         case DRM_FORMAT_RGBX8888_A8:
481         case DRM_FORMAT_BGRX8888_A8:
482                 alpha_eba = drm_plane_state_to_eba(state, 1);
483                 if (alpha_eba & 0x7)
484                         return -EINVAL;
485
486                 if (fb->pitches[1] < 1 || fb->pitches[1] > 16384)
487                         return -EINVAL;
488
489                 if (old_fb && old_fb->pitches[1] != fb->pitches[1])
490                         crtc_state->mode_changed = true;
491                 break;
492         }
493
494         return 0;
495 }
496
497 static void ipu_plane_atomic_disable(struct drm_plane *plane,
498                                      struct drm_plane_state *old_state)
499 {
500         struct ipu_plane *ipu_plane = to_ipu_plane(plane);
501
502         if (ipu_plane->dp)
503                 ipu_dp_disable_channel(ipu_plane->dp, true);
504         ipu_plane->disabling = true;
505 }
506
507 static int ipu_chan_assign_axi_id(int ipu_chan)
508 {
509         switch (ipu_chan) {
510         case IPUV3_CHANNEL_MEM_BG_SYNC:
511                 return 1;
512         case IPUV3_CHANNEL_MEM_FG_SYNC:
513                 return 2;
514         case IPUV3_CHANNEL_MEM_DC_SYNC:
515                 return 3;
516         default:
517                 return 0;
518         }
519 }
520
521 static void ipu_calculate_bursts(u32 width, u32 cpp, u32 stride,
522                                  u8 *burstsize, u8 *num_bursts)
523 {
524         const unsigned int width_bytes = width * cpp;
525         unsigned int npb, bursts;
526
527         /* Maximum number of pixels per burst without overshooting stride */
528         for (npb = 64 / cpp; npb > 0; --npb) {
529                 if (round_up(width_bytes, npb * cpp) <= stride)
530                         break;
531         }
532         *burstsize = npb;
533
534         /* Maximum number of consecutive bursts without overshooting stride */
535         for (bursts = 8; bursts > 1; bursts /= 2) {
536                 if (round_up(width_bytes, npb * cpp * bursts) <= stride)
537                         break;
538         }
539         *num_bursts = bursts;
540 }
541
542 static void ipu_plane_atomic_update(struct drm_plane *plane,
543                                     struct drm_plane_state *old_state)
544 {
545         struct ipu_plane *ipu_plane = to_ipu_plane(plane);
546         struct drm_plane_state *state = plane->state;
547         struct ipu_plane_state *ipu_state = to_ipu_plane_state(state);
548         struct drm_crtc_state *crtc_state = state->crtc->state;
549         struct drm_framebuffer *fb = state->fb;
550         struct drm_rect *dst = &state->dst;
551         unsigned long eba, ubo, vbo;
552         unsigned long alpha_eba = 0;
553         enum ipu_color_space ics;
554         unsigned int axi_id = 0;
555         const struct drm_format_info *info;
556         u8 burstsize, num_bursts;
557         u32 width, height;
558         int active;
559
560         if (ipu_plane->dp_flow == IPU_DP_FLOW_SYNC_FG)
561                 ipu_dp_set_window_pos(ipu_plane->dp, dst->x1, dst->y1);
562
563         eba = drm_plane_state_to_eba(state, 0);
564
565         /*
566          * Configure PRG channel and attached PRE, this changes the EBA to an
567          * internal SRAM location.
568          */
569         if (ipu_state->use_pre) {
570                 axi_id = ipu_chan_assign_axi_id(ipu_plane->dma);
571                 ipu_prg_channel_configure(ipu_plane->ipu_ch, axi_id,
572                                           drm_rect_width(&state->src) >> 16,
573                                           drm_rect_height(&state->src) >> 16,
574                                           fb->pitches[0], fb->format->format,
575                                           fb->modifier, &eba);
576         }
577
578         if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) {
579                 /* nothing to do if PRE is used */
580                 if (ipu_state->use_pre)
581                         return;
582                 active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch);
583                 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba);
584                 ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active);
585                 if (ipu_plane_separate_alpha(ipu_plane)) {
586                         active = ipu_idmac_get_current_buffer(ipu_plane->alpha_ch);
587                         ipu_cpmem_set_buffer(ipu_plane->alpha_ch, !active,
588                                              alpha_eba);
589                         ipu_idmac_select_buffer(ipu_plane->alpha_ch, !active);
590                 }
591                 return;
592         }
593
594         ics = ipu_drm_fourcc_to_colorspace(fb->format->format);
595         switch (ipu_plane->dp_flow) {
596         case IPU_DP_FLOW_SYNC_BG:
597                 ipu_dp_setup_channel(ipu_plane->dp, ics, IPUV3_COLORSPACE_RGB);
598                 ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true);
599                 break;
600         case IPU_DP_FLOW_SYNC_FG:
601                 ipu_dp_setup_channel(ipu_plane->dp, ics,
602                                         IPUV3_COLORSPACE_UNKNOWN);
603                 /* Enable local alpha on partial plane */
604                 switch (fb->format->format) {
605                 case DRM_FORMAT_ARGB1555:
606                 case DRM_FORMAT_ABGR1555:
607                 case DRM_FORMAT_RGBA5551:
608                 case DRM_FORMAT_BGRA5551:
609                 case DRM_FORMAT_ARGB4444:
610                 case DRM_FORMAT_ARGB8888:
611                 case DRM_FORMAT_ABGR8888:
612                 case DRM_FORMAT_RGBA8888:
613                 case DRM_FORMAT_BGRA8888:
614                 case DRM_FORMAT_RGB565_A8:
615                 case DRM_FORMAT_BGR565_A8:
616                 case DRM_FORMAT_RGB888_A8:
617                 case DRM_FORMAT_BGR888_A8:
618                 case DRM_FORMAT_RGBX8888_A8:
619                 case DRM_FORMAT_BGRX8888_A8:
620                         ipu_dp_set_global_alpha(ipu_plane->dp, false, 0, false);
621                         break;
622                 default:
623                         ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true);
624                         break;
625                 }
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 int ipu_planes_assign_pre(struct drm_device *dev,
722                           struct drm_atomic_state *state)
723 {
724         struct drm_crtc_state *old_crtc_state, *crtc_state;
725         struct drm_plane_state *plane_state;
726         struct ipu_plane_state *ipu_state;
727         struct ipu_plane *ipu_plane;
728         struct drm_plane *plane;
729         struct drm_crtc *crtc;
730         int available_pres = ipu_prg_max_active_channels();
731         int ret, i;
732
733         for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, crtc_state, i) {
734                 ret = drm_atomic_add_affected_planes(state, crtc);
735                 if (ret)
736                         return ret;
737         }
738
739         /*
740          * We are going over the planes in 2 passes: first we assign PREs to
741          * planes with a tiling modifier, which need the PREs to resolve into
742          * linear. Any failure to assign a PRE there is fatal. In the second
743          * pass we try to assign PREs to linear FBs, to improve memory access
744          * patterns for them. Failure at this point is non-fatal, as we can
745          * scan out linear FBs without a PRE.
746          */
747         for_each_new_plane_in_state(state, plane, plane_state, i) {
748                 ipu_state = to_ipu_plane_state(plane_state);
749                 ipu_plane = to_ipu_plane(plane);
750
751                 if (!plane_state->fb) {
752                         ipu_state->use_pre = false;
753                         continue;
754                 }
755
756                 if (!(plane_state->fb->flags & DRM_MODE_FB_MODIFIERS) ||
757                     plane_state->fb->modifier == DRM_FORMAT_MOD_LINEAR)
758                         continue;
759
760                 if (!ipu_prg_present(ipu_plane->ipu) || !available_pres)
761                         return -EINVAL;
762
763                 if (!ipu_prg_format_supported(ipu_plane->ipu,
764                                               plane_state->fb->format->format,
765                                               plane_state->fb->modifier))
766                         return -EINVAL;
767
768                 ipu_state->use_pre = true;
769                 available_pres--;
770         }
771
772         for_each_new_plane_in_state(state, plane, plane_state, i) {
773                 ipu_state = to_ipu_plane_state(plane_state);
774                 ipu_plane = to_ipu_plane(plane);
775
776                 if (!plane_state->fb) {
777                         ipu_state->use_pre = false;
778                         continue;
779                 }
780
781                 if ((plane_state->fb->flags & DRM_MODE_FB_MODIFIERS) &&
782                     plane_state->fb->modifier != DRM_FORMAT_MOD_LINEAR)
783                         continue;
784
785                 /* make sure that modifier is initialized */
786                 plane_state->fb->modifier = DRM_FORMAT_MOD_LINEAR;
787
788                 if (ipu_prg_present(ipu_plane->ipu) && available_pres &&
789                     ipu_prg_format_supported(ipu_plane->ipu,
790                                              plane_state->fb->format->format,
791                                              plane_state->fb->modifier)) {
792                         ipu_state->use_pre = true;
793                         available_pres--;
794                 } else {
795                         ipu_state->use_pre = false;
796                 }
797         }
798
799         return 0;
800 }
801 EXPORT_SYMBOL_GPL(ipu_planes_assign_pre);
802
803 struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
804                                  int dma, int dp, unsigned int possible_crtcs,
805                                  enum drm_plane_type type)
806 {
807         struct ipu_plane *ipu_plane;
808         const uint64_t *modifiers = ipu_format_modifiers;
809         int ret;
810
811         DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n",
812                       dma, dp, possible_crtcs);
813
814         ipu_plane = kzalloc(sizeof(*ipu_plane), GFP_KERNEL);
815         if (!ipu_plane) {
816                 DRM_ERROR("failed to allocate plane\n");
817                 return ERR_PTR(-ENOMEM);
818         }
819
820         ipu_plane->ipu = ipu;
821         ipu_plane->dma = dma;
822         ipu_plane->dp_flow = dp;
823
824         if (ipu_prg_present(ipu))
825                 modifiers = pre_format_modifiers;
826
827         ret = drm_universal_plane_init(dev, &ipu_plane->base, possible_crtcs,
828                                        &ipu_plane_funcs, ipu_plane_formats,
829                                        ARRAY_SIZE(ipu_plane_formats),
830                                        modifiers, type, NULL);
831         if (ret) {
832                 DRM_ERROR("failed to initialize plane\n");
833                 kfree(ipu_plane);
834                 return ERR_PTR(ret);
835         }
836
837         drm_plane_helper_add(&ipu_plane->base, &ipu_plane_helper_funcs);
838
839         return ipu_plane;
840 }