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