1 // SPDX-License-Identifier: GPL-2.0+
3 * i.MX IPUv3 DP Overlay Planes
5 * Copyright (C) 2013 Philipp Zabel, Pengutronix
8 #include <drm/drm_atomic.h>
9 #include <drm/drm_atomic_helper.h>
10 #include <drm/drm_fb_cma_helper.h>
11 #include <drm/drm_fourcc.h>
12 #include <drm/drm_gem_cma_helper.h>
13 #include <drm/drm_gem_framebuffer_helper.h>
14 #include <drm/drm_plane_helper.h>
16 #include <video/imx-ipu-v3.h>
19 #include "ipuv3-plane.h"
21 struct ipu_plane_state
{
22 struct drm_plane_state base
;
26 static inline struct ipu_plane_state
*
27 to_ipu_plane_state(struct drm_plane_state
*p
)
29 return container_of(p
, struct ipu_plane_state
, base
);
32 static inline struct ipu_plane
*to_ipu_plane(struct drm_plane
*p
)
34 return container_of(p
, struct ipu_plane
, base
);
37 static const uint32_t ipu_plane_formats
[] = {
70 DRM_FORMAT_RGBX8888_A8
,
71 DRM_FORMAT_BGRX8888_A8
,
74 static const uint64_t ipu_format_modifiers
[] = {
75 DRM_FORMAT_MOD_LINEAR
,
76 DRM_FORMAT_MOD_INVALID
79 static const uint64_t pre_format_modifiers
[] = {
80 DRM_FORMAT_MOD_LINEAR
,
81 DRM_FORMAT_MOD_VIVANTE_TILED
,
82 DRM_FORMAT_MOD_VIVANTE_SUPER_TILED
,
83 DRM_FORMAT_MOD_INVALID
86 int ipu_plane_irq(struct ipu_plane
*ipu_plane
)
88 return ipu_idmac_channel_irq(ipu_plane
->ipu
, ipu_plane
->ipu_ch
,
92 static inline unsigned long
93 drm_plane_state_to_eba(struct drm_plane_state
*state
, int plane
)
95 struct drm_framebuffer
*fb
= state
->fb
;
96 struct drm_gem_cma_object
*cma_obj
;
97 int x
= state
->src
.x1
>> 16;
98 int y
= state
->src
.y1
>> 16;
100 cma_obj
= drm_fb_cma_get_gem_obj(fb
, plane
);
103 return cma_obj
->paddr
+ fb
->offsets
[plane
] + fb
->pitches
[plane
] * y
+
104 fb
->format
->cpp
[plane
] * x
;
107 static inline unsigned long
108 drm_plane_state_to_ubo(struct drm_plane_state
*state
)
110 struct drm_framebuffer
*fb
= state
->fb
;
111 struct drm_gem_cma_object
*cma_obj
;
112 unsigned long eba
= drm_plane_state_to_eba(state
, 0);
113 int x
= state
->src
.x1
>> 16;
114 int y
= state
->src
.y1
>> 16;
116 cma_obj
= drm_fb_cma_get_gem_obj(fb
, 1);
119 x
/= fb
->format
->hsub
;
120 y
/= fb
->format
->vsub
;
122 return cma_obj
->paddr
+ fb
->offsets
[1] + fb
->pitches
[1] * y
+
123 fb
->format
->cpp
[1] * x
- eba
;
126 static inline unsigned long
127 drm_plane_state_to_vbo(struct drm_plane_state
*state
)
129 struct drm_framebuffer
*fb
= state
->fb
;
130 struct drm_gem_cma_object
*cma_obj
;
131 unsigned long eba
= drm_plane_state_to_eba(state
, 0);
132 int x
= state
->src
.x1
>> 16;
133 int y
= state
->src
.y1
>> 16;
135 cma_obj
= drm_fb_cma_get_gem_obj(fb
, 2);
138 x
/= fb
->format
->hsub
;
139 y
/= fb
->format
->vsub
;
141 return cma_obj
->paddr
+ fb
->offsets
[2] + fb
->pitches
[2] * y
+
142 fb
->format
->cpp
[2] * x
- eba
;
145 void ipu_plane_put_resources(struct ipu_plane
*ipu_plane
)
147 if (!IS_ERR_OR_NULL(ipu_plane
->dp
))
148 ipu_dp_put(ipu_plane
->dp
);
149 if (!IS_ERR_OR_NULL(ipu_plane
->dmfc
))
150 ipu_dmfc_put(ipu_plane
->dmfc
);
151 if (!IS_ERR_OR_NULL(ipu_plane
->ipu_ch
))
152 ipu_idmac_put(ipu_plane
->ipu_ch
);
153 if (!IS_ERR_OR_NULL(ipu_plane
->alpha_ch
))
154 ipu_idmac_put(ipu_plane
->alpha_ch
);
157 int ipu_plane_get_resources(struct ipu_plane
*ipu_plane
)
162 ipu_plane
->ipu_ch
= ipu_idmac_get(ipu_plane
->ipu
, ipu_plane
->dma
);
163 if (IS_ERR(ipu_plane
->ipu_ch
)) {
164 ret
= PTR_ERR(ipu_plane
->ipu_ch
);
165 DRM_ERROR("failed to get idmac channel: %d\n", ret
);
169 alpha_ch
= ipu_channel_alpha_channel(ipu_plane
->dma
);
171 ipu_plane
->alpha_ch
= ipu_idmac_get(ipu_plane
->ipu
, alpha_ch
);
172 if (IS_ERR(ipu_plane
->alpha_ch
)) {
173 ret
= PTR_ERR(ipu_plane
->alpha_ch
);
174 DRM_ERROR("failed to get alpha idmac channel %d: %d\n",
180 ipu_plane
->dmfc
= ipu_dmfc_get(ipu_plane
->ipu
, ipu_plane
->dma
);
181 if (IS_ERR(ipu_plane
->dmfc
)) {
182 ret
= PTR_ERR(ipu_plane
->dmfc
);
183 DRM_ERROR("failed to get dmfc: ret %d\n", ret
);
187 if (ipu_plane
->dp_flow
>= 0) {
188 ipu_plane
->dp
= ipu_dp_get(ipu_plane
->ipu
, ipu_plane
->dp_flow
);
189 if (IS_ERR(ipu_plane
->dp
)) {
190 ret
= PTR_ERR(ipu_plane
->dp
);
191 DRM_ERROR("failed to get dp flow: %d\n", ret
);
198 ipu_plane_put_resources(ipu_plane
);
203 static bool ipu_plane_separate_alpha(struct ipu_plane
*ipu_plane
)
205 switch (ipu_plane
->base
.state
->fb
->format
->format
) {
206 case DRM_FORMAT_RGB565_A8
:
207 case DRM_FORMAT_BGR565_A8
:
208 case DRM_FORMAT_RGB888_A8
:
209 case DRM_FORMAT_BGR888_A8
:
210 case DRM_FORMAT_RGBX8888_A8
:
211 case DRM_FORMAT_BGRX8888_A8
:
218 static void ipu_plane_enable(struct ipu_plane
*ipu_plane
)
221 ipu_dp_enable(ipu_plane
->ipu
);
222 ipu_dmfc_enable_channel(ipu_plane
->dmfc
);
223 ipu_idmac_enable_channel(ipu_plane
->ipu_ch
);
224 if (ipu_plane_separate_alpha(ipu_plane
))
225 ipu_idmac_enable_channel(ipu_plane
->alpha_ch
);
227 ipu_dp_enable_channel(ipu_plane
->dp
);
230 void ipu_plane_disable(struct ipu_plane
*ipu_plane
, bool disable_dp_channel
)
234 DRM_DEBUG_KMS("[%d] %s\n", __LINE__
, __func__
);
236 ret
= ipu_idmac_wait_busy(ipu_plane
->ipu_ch
, 50);
237 if (ret
== -ETIMEDOUT
) {
238 DRM_ERROR("[PLANE:%d] IDMAC timeout\n",
239 ipu_plane
->base
.base
.id
);
242 if (ipu_plane
->dp
&& disable_dp_channel
)
243 ipu_dp_disable_channel(ipu_plane
->dp
, false);
244 ipu_idmac_disable_channel(ipu_plane
->ipu_ch
);
245 if (ipu_plane
->alpha_ch
)
246 ipu_idmac_disable_channel(ipu_plane
->alpha_ch
);
247 ipu_dmfc_disable_channel(ipu_plane
->dmfc
);
249 ipu_dp_disable(ipu_plane
->ipu
);
250 if (ipu_prg_present(ipu_plane
->ipu
))
251 ipu_prg_channel_disable(ipu_plane
->ipu_ch
);
254 void ipu_plane_disable_deferred(struct drm_plane
*plane
)
256 struct ipu_plane
*ipu_plane
= to_ipu_plane(plane
);
258 if (ipu_plane
->disabling
) {
259 ipu_plane
->disabling
= false;
260 ipu_plane_disable(ipu_plane
, false);
263 EXPORT_SYMBOL_GPL(ipu_plane_disable_deferred
);
265 static void ipu_plane_destroy(struct drm_plane
*plane
)
267 struct ipu_plane
*ipu_plane
= to_ipu_plane(plane
);
269 DRM_DEBUG_KMS("[%d] %s\n", __LINE__
, __func__
);
271 drm_plane_cleanup(plane
);
275 static void ipu_plane_state_reset(struct drm_plane
*plane
)
277 unsigned int zpos
= (plane
->type
== DRM_PLANE_TYPE_PRIMARY
) ? 0 : 1;
278 struct ipu_plane_state
*ipu_state
;
281 ipu_state
= to_ipu_plane_state(plane
->state
);
282 __drm_atomic_helper_plane_destroy_state(plane
->state
);
287 ipu_state
= kzalloc(sizeof(*ipu_state
), GFP_KERNEL
);
290 __drm_atomic_helper_plane_reset(plane
, &ipu_state
->base
);
291 ipu_state
->base
.zpos
= zpos
;
292 ipu_state
->base
.normalized_zpos
= zpos
;
296 static struct drm_plane_state
*
297 ipu_plane_duplicate_state(struct drm_plane
*plane
)
299 struct ipu_plane_state
*state
;
301 if (WARN_ON(!plane
->state
))
304 state
= kmalloc(sizeof(*state
), GFP_KERNEL
);
306 __drm_atomic_helper_plane_duplicate_state(plane
, &state
->base
);
311 static void ipu_plane_destroy_state(struct drm_plane
*plane
,
312 struct drm_plane_state
*state
)
314 struct ipu_plane_state
*ipu_state
= to_ipu_plane_state(state
);
316 __drm_atomic_helper_plane_destroy_state(state
);
320 static bool ipu_plane_format_mod_supported(struct drm_plane
*plane
,
321 uint32_t format
, uint64_t modifier
)
323 struct ipu_soc
*ipu
= to_ipu_plane(plane
)->ipu
;
325 /* linear is supported for all planes and formats */
326 if (modifier
== DRM_FORMAT_MOD_LINEAR
)
329 /* without a PRG there are no supported modifiers */
330 if (!ipu_prg_present(ipu
))
333 return ipu_prg_format_supported(ipu
, format
, modifier
);
336 static const struct drm_plane_funcs ipu_plane_funcs
= {
337 .update_plane
= drm_atomic_helper_update_plane
,
338 .disable_plane
= drm_atomic_helper_disable_plane
,
339 .destroy
= ipu_plane_destroy
,
340 .reset
= ipu_plane_state_reset
,
341 .atomic_duplicate_state
= ipu_plane_duplicate_state
,
342 .atomic_destroy_state
= ipu_plane_destroy_state
,
343 .format_mod_supported
= ipu_plane_format_mod_supported
,
346 static int ipu_plane_atomic_check(struct drm_plane
*plane
,
347 struct drm_plane_state
*state
)
349 struct drm_plane_state
*old_state
= plane
->state
;
350 struct drm_crtc_state
*crtc_state
;
351 struct device
*dev
= plane
->dev
->dev
;
352 struct drm_framebuffer
*fb
= state
->fb
;
353 struct drm_framebuffer
*old_fb
= old_state
->fb
;
354 unsigned long eba
, ubo
, vbo
, old_ubo
, old_vbo
, alpha_eba
;
355 bool can_position
= (plane
->type
== DRM_PLANE_TYPE_OVERLAY
);
366 drm_atomic_get_existing_crtc_state(state
->state
, state
->crtc
);
367 if (WARN_ON(!crtc_state
))
370 ret
= drm_atomic_helper_check_plane_state(state
, crtc_state
,
371 DRM_PLANE_HELPER_NO_SCALING
,
372 DRM_PLANE_HELPER_NO_SCALING
,
377 /* nothing to check when disabling or disabled */
378 if (!crtc_state
->enable
)
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)
387 case DRM_PLANE_TYPE_OVERLAY
:
390 dev_warn(dev
, "Unsupported plane type %d\n", plane
->type
);
394 if (drm_rect_height(&state
->dst
) < 2)
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
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;
410 eba
= drm_plane_state_to_eba(state
, 0);
415 if (fb
->pitches
[0] < 1 || fb
->pitches
[0] > 16384)
418 if (old_fb
&& fb
->pitches
[0] != old_fb
->pitches
[0])
419 crtc_state
->mode_changed
= true;
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
:
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.
436 vbo
= drm_plane_state_to_vbo(state
);
438 if (vbo
& 0x7 || vbo
> 0xfffff8)
441 if (old_fb
&& (fb
->format
== old_fb
->format
)) {
442 old_vbo
= drm_plane_state_to_vbo(old_state
);
444 crtc_state
->mode_changed
= true;
447 if (fb
->pitches
[1] != fb
->pitches
[2])
451 case DRM_FORMAT_NV12
:
452 case DRM_FORMAT_NV16
:
453 ubo
= drm_plane_state_to_ubo(state
);
455 if (ubo
& 0x7 || ubo
> 0xfffff8)
458 if (old_fb
&& (fb
->format
== old_fb
->format
)) {
459 old_ubo
= drm_plane_state_to_ubo(old_state
);
461 crtc_state
->mode_changed
= true;
464 if (fb
->pitches
[1] < 1 || fb
->pitches
[1] > 16384)
467 if (old_fb
&& old_fb
->pitches
[1] != fb
->pitches
[1])
468 crtc_state
->mode_changed
= true;
471 * The x/y offsets must be even in case of horizontal/vertical
472 * chroma subsampling.
474 if (((state
->src
.x1
>> 16) & (fb
->format
->hsub
- 1)) ||
475 ((state
->src
.y1
>> 16) & (fb
->format
->vsub
- 1)))
478 case DRM_FORMAT_RGB565_A8
:
479 case DRM_FORMAT_BGR565_A8
:
480 case DRM_FORMAT_RGB888_A8
:
481 case DRM_FORMAT_BGR888_A8
:
482 case DRM_FORMAT_RGBX8888_A8
:
483 case DRM_FORMAT_BGRX8888_A8
:
484 alpha_eba
= drm_plane_state_to_eba(state
, 1);
488 if (fb
->pitches
[1] < 1 || fb
->pitches
[1] > 16384)
491 if (old_fb
&& old_fb
->pitches
[1] != fb
->pitches
[1])
492 crtc_state
->mode_changed
= true;
499 static void ipu_plane_atomic_disable(struct drm_plane
*plane
,
500 struct drm_plane_state
*old_state
)
502 struct ipu_plane
*ipu_plane
= to_ipu_plane(plane
);
505 ipu_dp_disable_channel(ipu_plane
->dp
, true);
506 ipu_plane
->disabling
= true;
509 static int ipu_chan_assign_axi_id(int ipu_chan
)
512 case IPUV3_CHANNEL_MEM_BG_SYNC
:
514 case IPUV3_CHANNEL_MEM_FG_SYNC
:
516 case IPUV3_CHANNEL_MEM_DC_SYNC
:
523 static void ipu_calculate_bursts(u32 width
, u32 cpp
, u32 stride
,
524 u8
*burstsize
, u8
*num_bursts
)
526 const unsigned int width_bytes
= width
* cpp
;
527 unsigned int npb
, bursts
;
529 /* Maximum number of pixels per burst without overshooting stride */
530 for (npb
= 64 / cpp
; npb
> 0; --npb
) {
531 if (round_up(width_bytes
, npb
* cpp
) <= stride
)
536 /* Maximum number of consecutive bursts without overshooting stride */
537 for (bursts
= 8; bursts
> 1; bursts
/= 2) {
538 if (round_up(width_bytes
, npb
* cpp
* bursts
) <= stride
)
541 *num_bursts
= bursts
;
544 static void ipu_plane_atomic_update(struct drm_plane
*plane
,
545 struct drm_plane_state
*old_state
)
547 struct ipu_plane
*ipu_plane
= to_ipu_plane(plane
);
548 struct drm_plane_state
*state
= plane
->state
;
549 struct ipu_plane_state
*ipu_state
= to_ipu_plane_state(state
);
550 struct drm_crtc_state
*crtc_state
= state
->crtc
->state
;
551 struct drm_framebuffer
*fb
= state
->fb
;
552 struct drm_rect
*dst
= &state
->dst
;
553 unsigned long eba
, ubo
, vbo
;
554 unsigned long alpha_eba
= 0;
555 enum ipu_color_space ics
;
556 unsigned int axi_id
= 0;
557 const struct drm_format_info
*info
;
558 u8 burstsize
, num_bursts
;
562 if (ipu_plane
->dp_flow
== IPU_DP_FLOW_SYNC_FG
)
563 ipu_dp_set_window_pos(ipu_plane
->dp
, dst
->x1
, dst
->y1
);
565 switch (ipu_plane
->dp_flow
) {
566 case IPU_DP_FLOW_SYNC_BG
:
567 if (state
->normalized_zpos
== 1) {
568 ipu_dp_set_global_alpha(ipu_plane
->dp
,
569 !fb
->format
->has_alpha
, 0xff,
572 ipu_dp_set_global_alpha(ipu_plane
->dp
, true, 0, true);
575 case IPU_DP_FLOW_SYNC_FG
:
576 if (state
->normalized_zpos
== 1) {
577 ipu_dp_set_global_alpha(ipu_plane
->dp
,
578 !fb
->format
->has_alpha
, 0xff,
584 eba
= drm_plane_state_to_eba(state
, 0);
587 * Configure PRG channel and attached PRE, this changes the EBA to an
588 * internal SRAM location.
590 if (ipu_state
->use_pre
) {
591 axi_id
= ipu_chan_assign_axi_id(ipu_plane
->dma
);
592 ipu_prg_channel_configure(ipu_plane
->ipu_ch
, axi_id
,
593 drm_rect_width(&state
->src
) >> 16,
594 drm_rect_height(&state
->src
) >> 16,
595 fb
->pitches
[0], fb
->format
->format
,
599 if (old_state
->fb
&& !drm_atomic_crtc_needs_modeset(crtc_state
)) {
600 /* nothing to do if PRE is used */
601 if (ipu_state
->use_pre
)
603 active
= ipu_idmac_get_current_buffer(ipu_plane
->ipu_ch
);
604 ipu_cpmem_set_buffer(ipu_plane
->ipu_ch
, !active
, eba
);
605 ipu_idmac_select_buffer(ipu_plane
->ipu_ch
, !active
);
606 if (ipu_plane_separate_alpha(ipu_plane
)) {
607 active
= ipu_idmac_get_current_buffer(ipu_plane
->alpha_ch
);
608 ipu_cpmem_set_buffer(ipu_plane
->alpha_ch
, !active
,
610 ipu_idmac_select_buffer(ipu_plane
->alpha_ch
, !active
);
615 ics
= ipu_drm_fourcc_to_colorspace(fb
->format
->format
);
616 switch (ipu_plane
->dp_flow
) {
617 case IPU_DP_FLOW_SYNC_BG
:
618 ipu_dp_setup_channel(ipu_plane
->dp
, ics
, IPUV3_COLORSPACE_RGB
);
620 case IPU_DP_FLOW_SYNC_FG
:
621 ipu_dp_setup_channel(ipu_plane
->dp
, ics
,
622 IPUV3_COLORSPACE_UNKNOWN
);
626 ipu_dmfc_config_wait4eot(ipu_plane
->dmfc
, drm_rect_width(dst
));
628 width
= drm_rect_width(&state
->src
) >> 16;
629 height
= drm_rect_height(&state
->src
) >> 16;
630 info
= drm_format_info(fb
->format
->format
);
631 ipu_calculate_bursts(width
, info
->cpp
[0], fb
->pitches
[0],
632 &burstsize
, &num_bursts
);
634 ipu_cpmem_zero(ipu_plane
->ipu_ch
);
635 ipu_cpmem_set_resolution(ipu_plane
->ipu_ch
, width
, height
);
636 ipu_cpmem_set_fmt(ipu_plane
->ipu_ch
, fb
->format
->format
);
637 ipu_cpmem_set_burstsize(ipu_plane
->ipu_ch
, burstsize
);
638 ipu_cpmem_set_high_priority(ipu_plane
->ipu_ch
);
639 ipu_idmac_enable_watermark(ipu_plane
->ipu_ch
, true);
640 ipu_idmac_set_double_buffer(ipu_plane
->ipu_ch
, 1);
641 ipu_cpmem_set_stride(ipu_plane
->ipu_ch
, fb
->pitches
[0]);
642 ipu_cpmem_set_axi_id(ipu_plane
->ipu_ch
, axi_id
);
644 switch (fb
->format
->format
) {
645 case DRM_FORMAT_YUV420
:
646 case DRM_FORMAT_YVU420
:
647 case DRM_FORMAT_YUV422
:
648 case DRM_FORMAT_YVU422
:
649 case DRM_FORMAT_YUV444
:
650 case DRM_FORMAT_YVU444
:
651 ubo
= drm_plane_state_to_ubo(state
);
652 vbo
= drm_plane_state_to_vbo(state
);
653 if (fb
->format
->format
== DRM_FORMAT_YVU420
||
654 fb
->format
->format
== DRM_FORMAT_YVU422
||
655 fb
->format
->format
== DRM_FORMAT_YVU444
)
658 ipu_cpmem_set_yuv_planar_full(ipu_plane
->ipu_ch
,
659 fb
->pitches
[1], ubo
, vbo
);
661 dev_dbg(ipu_plane
->base
.dev
->dev
,
662 "phy = %lu %lu %lu, x = %d, y = %d", eba
, ubo
, vbo
,
663 state
->src
.x1
>> 16, state
->src
.y1
>> 16);
665 case DRM_FORMAT_NV12
:
666 case DRM_FORMAT_NV16
:
667 ubo
= drm_plane_state_to_ubo(state
);
669 ipu_cpmem_set_yuv_planar_full(ipu_plane
->ipu_ch
,
670 fb
->pitches
[1], ubo
, ubo
);
672 dev_dbg(ipu_plane
->base
.dev
->dev
,
673 "phy = %lu %lu, x = %d, y = %d", eba
, ubo
,
674 state
->src
.x1
>> 16, state
->src
.y1
>> 16);
676 case DRM_FORMAT_RGB565_A8
:
677 case DRM_FORMAT_BGR565_A8
:
678 case DRM_FORMAT_RGB888_A8
:
679 case DRM_FORMAT_BGR888_A8
:
680 case DRM_FORMAT_RGBX8888_A8
:
681 case DRM_FORMAT_BGRX8888_A8
:
682 alpha_eba
= drm_plane_state_to_eba(state
, 1);
685 dev_dbg(ipu_plane
->base
.dev
->dev
, "phys = %lu %lu, x = %d, y = %d",
686 eba
, alpha_eba
, state
->src
.x1
>> 16, state
->src
.y1
>> 16);
688 ipu_cpmem_set_burstsize(ipu_plane
->ipu_ch
, 16);
690 ipu_cpmem_zero(ipu_plane
->alpha_ch
);
691 ipu_cpmem_set_resolution(ipu_plane
->alpha_ch
,
692 drm_rect_width(&state
->src
) >> 16,
693 drm_rect_height(&state
->src
) >> 16);
694 ipu_cpmem_set_format_passthrough(ipu_plane
->alpha_ch
, 8);
695 ipu_cpmem_set_high_priority(ipu_plane
->alpha_ch
);
696 ipu_idmac_set_double_buffer(ipu_plane
->alpha_ch
, 1);
697 ipu_cpmem_set_stride(ipu_plane
->alpha_ch
, fb
->pitches
[1]);
698 ipu_cpmem_set_burstsize(ipu_plane
->alpha_ch
, 16);
699 ipu_cpmem_set_buffer(ipu_plane
->alpha_ch
, 0, alpha_eba
);
700 ipu_cpmem_set_buffer(ipu_plane
->alpha_ch
, 1, alpha_eba
);
703 dev_dbg(ipu_plane
->base
.dev
->dev
, "phys = %lu, x = %d, y = %d",
704 eba
, state
->src
.x1
>> 16, state
->src
.y1
>> 16);
707 ipu_cpmem_set_buffer(ipu_plane
->ipu_ch
, 0, eba
);
708 ipu_cpmem_set_buffer(ipu_plane
->ipu_ch
, 1, eba
);
709 ipu_idmac_lock_enable(ipu_plane
->ipu_ch
, num_bursts
);
710 ipu_plane_enable(ipu_plane
);
713 static const struct drm_plane_helper_funcs ipu_plane_helper_funcs
= {
714 .prepare_fb
= drm_gem_fb_prepare_fb
,
715 .atomic_check
= ipu_plane_atomic_check
,
716 .atomic_disable
= ipu_plane_atomic_disable
,
717 .atomic_update
= ipu_plane_atomic_update
,
720 bool ipu_plane_atomic_update_pending(struct drm_plane
*plane
)
722 struct ipu_plane
*ipu_plane
= to_ipu_plane(plane
);
723 struct drm_plane_state
*state
= plane
->state
;
724 struct ipu_plane_state
*ipu_state
= to_ipu_plane_state(state
);
726 /* disabled crtcs must not block the update */
730 if (ipu_state
->use_pre
)
731 return ipu_prg_channel_configure_pending(ipu_plane
->ipu_ch
);
734 * Pretend no update is pending in the non-PRE/PRG case. For this to
735 * happen, an atomic update would have to be deferred until after the
736 * start of the next frame and simultaneously interrupt latency would
737 * have to be high enough to let the atomic update finish and issue an
738 * event before the previous end of frame interrupt handler can be
743 int ipu_planes_assign_pre(struct drm_device
*dev
,
744 struct drm_atomic_state
*state
)
746 struct drm_crtc_state
*old_crtc_state
, *crtc_state
;
747 struct drm_plane_state
*plane_state
;
748 struct ipu_plane_state
*ipu_state
;
749 struct ipu_plane
*ipu_plane
;
750 struct drm_plane
*plane
;
751 struct drm_crtc
*crtc
;
752 int available_pres
= ipu_prg_max_active_channels();
755 for_each_oldnew_crtc_in_state(state
, crtc
, old_crtc_state
, crtc_state
, i
) {
756 ret
= drm_atomic_add_affected_planes(state
, crtc
);
762 * We are going over the planes in 2 passes: first we assign PREs to
763 * planes with a tiling modifier, which need the PREs to resolve into
764 * linear. Any failure to assign a PRE there is fatal. In the second
765 * pass we try to assign PREs to linear FBs, to improve memory access
766 * patterns for them. Failure at this point is non-fatal, as we can
767 * scan out linear FBs without a PRE.
769 for_each_new_plane_in_state(state
, plane
, plane_state
, i
) {
770 ipu_state
= to_ipu_plane_state(plane_state
);
771 ipu_plane
= to_ipu_plane(plane
);
773 if (!plane_state
->fb
) {
774 ipu_state
->use_pre
= false;
778 if (!(plane_state
->fb
->flags
& DRM_MODE_FB_MODIFIERS
) ||
779 plane_state
->fb
->modifier
== DRM_FORMAT_MOD_LINEAR
)
782 if (!ipu_prg_present(ipu_plane
->ipu
) || !available_pres
)
785 if (!ipu_prg_format_supported(ipu_plane
->ipu
,
786 plane_state
->fb
->format
->format
,
787 plane_state
->fb
->modifier
))
790 ipu_state
->use_pre
= true;
794 for_each_new_plane_in_state(state
, plane
, plane_state
, i
) {
795 ipu_state
= to_ipu_plane_state(plane_state
);
796 ipu_plane
= to_ipu_plane(plane
);
798 if (!plane_state
->fb
) {
799 ipu_state
->use_pre
= false;
803 if ((plane_state
->fb
->flags
& DRM_MODE_FB_MODIFIERS
) &&
804 plane_state
->fb
->modifier
!= DRM_FORMAT_MOD_LINEAR
)
807 /* make sure that modifier is initialized */
808 plane_state
->fb
->modifier
= DRM_FORMAT_MOD_LINEAR
;
810 if (ipu_prg_present(ipu_plane
->ipu
) && available_pres
&&
811 ipu_prg_format_supported(ipu_plane
->ipu
,
812 plane_state
->fb
->format
->format
,
813 plane_state
->fb
->modifier
)) {
814 ipu_state
->use_pre
= true;
817 ipu_state
->use_pre
= false;
823 EXPORT_SYMBOL_GPL(ipu_planes_assign_pre
);
825 struct ipu_plane
*ipu_plane_init(struct drm_device
*dev
, struct ipu_soc
*ipu
,
826 int dma
, int dp
, unsigned int possible_crtcs
,
827 enum drm_plane_type type
)
829 struct ipu_plane
*ipu_plane
;
830 const uint64_t *modifiers
= ipu_format_modifiers
;
831 unsigned int zpos
= (type
== DRM_PLANE_TYPE_PRIMARY
) ? 0 : 1;
834 DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n",
835 dma
, dp
, possible_crtcs
);
837 ipu_plane
= kzalloc(sizeof(*ipu_plane
), GFP_KERNEL
);
839 DRM_ERROR("failed to allocate plane\n");
840 return ERR_PTR(-ENOMEM
);
843 ipu_plane
->ipu
= ipu
;
844 ipu_plane
->dma
= dma
;
845 ipu_plane
->dp_flow
= dp
;
847 if (ipu_prg_present(ipu
))
848 modifiers
= pre_format_modifiers
;
850 ret
= drm_universal_plane_init(dev
, &ipu_plane
->base
, possible_crtcs
,
851 &ipu_plane_funcs
, ipu_plane_formats
,
852 ARRAY_SIZE(ipu_plane_formats
),
853 modifiers
, type
, NULL
);
855 DRM_ERROR("failed to initialize plane\n");
860 drm_plane_helper_add(&ipu_plane
->base
, &ipu_plane_helper_funcs
);
862 if (dp
== IPU_DP_FLOW_SYNC_BG
|| dp
== IPU_DP_FLOW_SYNC_FG
)
863 drm_plane_create_zpos_property(&ipu_plane
->base
, zpos
, 0, 1);
865 drm_plane_create_zpos_immutable_property(&ipu_plane
->base
, 0);