2 * i.MX IPUv3 DP Overlay Planes
4 * Copyright (C) 2013 Philipp Zabel, Pengutronix
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.
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>
24 #include "video/imx-ipu-v3.h"
26 #include "ipuv3-plane.h"
28 struct ipu_plane_state
{
29 struct drm_plane_state base
;
33 static inline struct ipu_plane_state
*
34 to_ipu_plane_state(struct drm_plane_state
*p
)
36 return container_of(p
, struct ipu_plane_state
, base
);
39 static inline struct ipu_plane
*to_ipu_plane(struct drm_plane
*p
)
41 return container_of(p
, struct ipu_plane
, base
);
44 static const uint32_t ipu_plane_formats
[] = {
77 DRM_FORMAT_RGBX8888_A8
,
78 DRM_FORMAT_BGRX8888_A8
,
81 static const uint64_t ipu_format_modifiers
[] = {
82 DRM_FORMAT_MOD_LINEAR
,
83 DRM_FORMAT_MOD_INVALID
86 static const uint64_t pre_format_modifiers
[] = {
87 DRM_FORMAT_MOD_LINEAR
,
88 DRM_FORMAT_MOD_VIVANTE_TILED
,
89 DRM_FORMAT_MOD_VIVANTE_SUPER_TILED
,
90 DRM_FORMAT_MOD_INVALID
93 int ipu_plane_irq(struct ipu_plane
*ipu_plane
)
95 return ipu_idmac_channel_irq(ipu_plane
->ipu
, ipu_plane
->ipu_ch
,
99 static inline unsigned long
100 drm_plane_state_to_eba(struct drm_plane_state
*state
, int plane
)
102 struct drm_framebuffer
*fb
= state
->fb
;
103 struct drm_gem_cma_object
*cma_obj
;
104 int x
= state
->src
.x1
>> 16;
105 int y
= state
->src
.y1
>> 16;
107 cma_obj
= drm_fb_cma_get_gem_obj(fb
, plane
);
110 return cma_obj
->paddr
+ fb
->offsets
[plane
] + fb
->pitches
[plane
] * y
+
111 fb
->format
->cpp
[plane
] * x
;
114 static inline unsigned long
115 drm_plane_state_to_ubo(struct drm_plane_state
*state
)
117 struct drm_framebuffer
*fb
= state
->fb
;
118 struct drm_gem_cma_object
*cma_obj
;
119 unsigned long eba
= drm_plane_state_to_eba(state
, 0);
120 int x
= state
->src
.x1
>> 16;
121 int y
= state
->src
.y1
>> 16;
123 cma_obj
= drm_fb_cma_get_gem_obj(fb
, 1);
126 x
/= drm_format_horz_chroma_subsampling(fb
->format
->format
);
127 y
/= drm_format_vert_chroma_subsampling(fb
->format
->format
);
129 return cma_obj
->paddr
+ fb
->offsets
[1] + fb
->pitches
[1] * y
+
130 fb
->format
->cpp
[1] * x
- eba
;
133 static inline unsigned long
134 drm_plane_state_to_vbo(struct drm_plane_state
*state
)
136 struct drm_framebuffer
*fb
= state
->fb
;
137 struct drm_gem_cma_object
*cma_obj
;
138 unsigned long eba
= drm_plane_state_to_eba(state
, 0);
139 int x
= state
->src
.x1
>> 16;
140 int y
= state
->src
.y1
>> 16;
142 cma_obj
= drm_fb_cma_get_gem_obj(fb
, 2);
145 x
/= drm_format_horz_chroma_subsampling(fb
->format
->format
);
146 y
/= drm_format_vert_chroma_subsampling(fb
->format
->format
);
148 return cma_obj
->paddr
+ fb
->offsets
[2] + fb
->pitches
[2] * y
+
149 fb
->format
->cpp
[2] * x
- eba
;
152 void ipu_plane_put_resources(struct ipu_plane
*ipu_plane
)
154 if (!IS_ERR_OR_NULL(ipu_plane
->dp
))
155 ipu_dp_put(ipu_plane
->dp
);
156 if (!IS_ERR_OR_NULL(ipu_plane
->dmfc
))
157 ipu_dmfc_put(ipu_plane
->dmfc
);
158 if (!IS_ERR_OR_NULL(ipu_plane
->ipu_ch
))
159 ipu_idmac_put(ipu_plane
->ipu_ch
);
160 if (!IS_ERR_OR_NULL(ipu_plane
->alpha_ch
))
161 ipu_idmac_put(ipu_plane
->alpha_ch
);
164 int ipu_plane_get_resources(struct ipu_plane
*ipu_plane
)
169 ipu_plane
->ipu_ch
= ipu_idmac_get(ipu_plane
->ipu
, ipu_plane
->dma
);
170 if (IS_ERR(ipu_plane
->ipu_ch
)) {
171 ret
= PTR_ERR(ipu_plane
->ipu_ch
);
172 DRM_ERROR("failed to get idmac channel: %d\n", ret
);
176 alpha_ch
= ipu_channel_alpha_channel(ipu_plane
->dma
);
178 ipu_plane
->alpha_ch
= ipu_idmac_get(ipu_plane
->ipu
, alpha_ch
);
179 if (IS_ERR(ipu_plane
->alpha_ch
)) {
180 ret
= PTR_ERR(ipu_plane
->alpha_ch
);
181 DRM_ERROR("failed to get alpha idmac channel %d: %d\n",
187 ipu_plane
->dmfc
= ipu_dmfc_get(ipu_plane
->ipu
, ipu_plane
->dma
);
188 if (IS_ERR(ipu_plane
->dmfc
)) {
189 ret
= PTR_ERR(ipu_plane
->dmfc
);
190 DRM_ERROR("failed to get dmfc: ret %d\n", ret
);
194 if (ipu_plane
->dp_flow
>= 0) {
195 ipu_plane
->dp
= ipu_dp_get(ipu_plane
->ipu
, ipu_plane
->dp_flow
);
196 if (IS_ERR(ipu_plane
->dp
)) {
197 ret
= PTR_ERR(ipu_plane
->dp
);
198 DRM_ERROR("failed to get dp flow: %d\n", ret
);
205 ipu_plane_put_resources(ipu_plane
);
210 static bool ipu_plane_separate_alpha(struct ipu_plane
*ipu_plane
)
212 switch (ipu_plane
->base
.state
->fb
->format
->format
) {
213 case DRM_FORMAT_RGB565_A8
:
214 case DRM_FORMAT_BGR565_A8
:
215 case DRM_FORMAT_RGB888_A8
:
216 case DRM_FORMAT_BGR888_A8
:
217 case DRM_FORMAT_RGBX8888_A8
:
218 case DRM_FORMAT_BGRX8888_A8
:
225 static void ipu_plane_enable(struct ipu_plane
*ipu_plane
)
228 ipu_dp_enable(ipu_plane
->ipu
);
229 ipu_dmfc_enable_channel(ipu_plane
->dmfc
);
230 ipu_idmac_enable_channel(ipu_plane
->ipu_ch
);
231 if (ipu_plane_separate_alpha(ipu_plane
))
232 ipu_idmac_enable_channel(ipu_plane
->alpha_ch
);
234 ipu_dp_enable_channel(ipu_plane
->dp
);
237 void ipu_plane_disable(struct ipu_plane
*ipu_plane
, bool disable_dp_channel
)
239 DRM_DEBUG_KMS("[%d] %s\n", __LINE__
, __func__
);
241 ipu_idmac_wait_busy(ipu_plane
->ipu_ch
, 50);
243 if (ipu_plane
->dp
&& disable_dp_channel
)
244 ipu_dp_disable_channel(ipu_plane
->dp
, false);
245 ipu_idmac_disable_channel(ipu_plane
->ipu_ch
);
246 if (ipu_plane
->alpha_ch
)
247 ipu_idmac_disable_channel(ipu_plane
->alpha_ch
);
248 ipu_dmfc_disable_channel(ipu_plane
->dmfc
);
250 ipu_dp_disable(ipu_plane
->ipu
);
251 if (ipu_prg_present(ipu_plane
->ipu
))
252 ipu_prg_channel_disable(ipu_plane
->ipu_ch
);
255 void ipu_plane_disable_deferred(struct drm_plane
*plane
)
257 struct ipu_plane
*ipu_plane
= to_ipu_plane(plane
);
259 if (ipu_plane
->disabling
) {
260 ipu_plane
->disabling
= false;
261 ipu_plane_disable(ipu_plane
, false);
264 EXPORT_SYMBOL_GPL(ipu_plane_disable_deferred
);
266 static void ipu_plane_destroy(struct drm_plane
*plane
)
268 struct ipu_plane
*ipu_plane
= to_ipu_plane(plane
);
270 DRM_DEBUG_KMS("[%d] %s\n", __LINE__
, __func__
);
272 drm_plane_cleanup(plane
);
276 static void ipu_plane_state_reset(struct drm_plane
*plane
)
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
);
286 ipu_state
= kzalloc(sizeof(*ipu_state
), GFP_KERNEL
);
289 ipu_state
->base
.plane
= plane
;
290 ipu_state
->base
.rotation
= DRM_MODE_ROTATE_0
;
293 plane
->state
= &ipu_state
->base
;
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
);
367 drm_atomic_get_existing_crtc_state(state
->state
, state
->crtc
);
368 if (WARN_ON(!crtc_state
))
371 ret
= drm_atomic_helper_check_plane_state(state
, crtc_state
,
372 DRM_PLANE_HELPER_NO_SCALING
,
373 DRM_PLANE_HELPER_NO_SCALING
,
378 /* nothing to check when disabling or disabled */
379 if (!crtc_state
->enable
)
382 switch (plane
->type
) {
383 case DRM_PLANE_TYPE_PRIMARY
:
384 /* full plane minimum width is 13 pixels */
385 if (drm_rect_width(&state
->dst
) < 13)
388 case DRM_PLANE_TYPE_OVERLAY
:
391 dev_warn(dev
, "Unsupported plane type %d\n", plane
->type
);
395 if (drm_rect_height(&state
->dst
) < 2)
399 * We support resizing active plane or changing its format by
400 * forcing CRTC mode change in plane's ->atomic_check callback
401 * and disabling all affected active planes in CRTC's ->atomic_disable
402 * callback. The planes will be reenabled in plane's ->atomic_update
406 (drm_rect_width(&state
->dst
) != drm_rect_width(&old_state
->dst
) ||
407 drm_rect_height(&state
->dst
) != drm_rect_height(&old_state
->dst
) ||
408 fb
->format
!= old_fb
->format
))
409 crtc_state
->mode_changed
= true;
411 eba
= drm_plane_state_to_eba(state
, 0);
416 if (fb
->pitches
[0] < 1 || fb
->pitches
[0] > 16384)
419 if (old_fb
&& fb
->pitches
[0] != old_fb
->pitches
[0])
420 crtc_state
->mode_changed
= true;
422 switch (fb
->format
->format
) {
423 case DRM_FORMAT_YUV420
:
424 case DRM_FORMAT_YVU420
:
425 case DRM_FORMAT_YUV422
:
426 case DRM_FORMAT_YVU422
:
427 case DRM_FORMAT_YUV444
:
428 case DRM_FORMAT_YVU444
:
430 * Multiplanar formats have to meet the following restrictions:
431 * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO
432 * - EBA, UBO and VBO are a multiple of 8
433 * - UBO and VBO are unsigned and not larger than 0xfffff8
434 * - Only EBA may be changed while scanout is active
435 * - The strides of U and V planes must be identical.
437 vbo
= drm_plane_state_to_vbo(state
);
439 if (vbo
& 0x7 || vbo
> 0xfffff8)
442 if (old_fb
&& (fb
->format
== old_fb
->format
)) {
443 old_vbo
= drm_plane_state_to_vbo(old_state
);
445 crtc_state
->mode_changed
= true;
448 if (fb
->pitches
[1] != fb
->pitches
[2])
452 case DRM_FORMAT_NV12
:
453 case DRM_FORMAT_NV16
:
454 ubo
= drm_plane_state_to_ubo(state
);
456 if (ubo
& 0x7 || ubo
> 0xfffff8)
459 if (old_fb
&& (fb
->format
== old_fb
->format
)) {
460 old_ubo
= drm_plane_state_to_ubo(old_state
);
462 crtc_state
->mode_changed
= true;
465 if (fb
->pitches
[1] < 1 || fb
->pitches
[1] > 16384)
468 if (old_fb
&& old_fb
->pitches
[1] != fb
->pitches
[1])
469 crtc_state
->mode_changed
= true;
472 * The x/y offsets must be even in case of horizontal/vertical
473 * chroma subsampling.
475 hsub
= drm_format_horz_chroma_subsampling(fb
->format
->format
);
476 vsub
= drm_format_vert_chroma_subsampling(fb
->format
->format
);
477 if (((state
->src
.x1
>> 16) & (hsub
- 1)) ||
478 ((state
->src
.y1
>> 16) & (vsub
- 1)))
481 case DRM_FORMAT_RGB565_A8
:
482 case DRM_FORMAT_BGR565_A8
:
483 case DRM_FORMAT_RGB888_A8
:
484 case DRM_FORMAT_BGR888_A8
:
485 case DRM_FORMAT_RGBX8888_A8
:
486 case DRM_FORMAT_BGRX8888_A8
:
487 alpha_eba
= drm_plane_state_to_eba(state
, 1);
491 if (fb
->pitches
[1] < 1 || fb
->pitches
[1] > 16384)
494 if (old_fb
&& old_fb
->pitches
[1] != fb
->pitches
[1])
495 crtc_state
->mode_changed
= true;
502 static void ipu_plane_atomic_disable(struct drm_plane
*plane
,
503 struct drm_plane_state
*old_state
)
505 struct ipu_plane
*ipu_plane
= to_ipu_plane(plane
);
508 ipu_dp_disable_channel(ipu_plane
->dp
, true);
509 ipu_plane
->disabling
= true;
512 static int ipu_chan_assign_axi_id(int ipu_chan
)
515 case IPUV3_CHANNEL_MEM_BG_SYNC
:
517 case IPUV3_CHANNEL_MEM_FG_SYNC
:
519 case IPUV3_CHANNEL_MEM_DC_SYNC
:
526 static void ipu_calculate_bursts(u32 width
, u32 cpp
, u32 stride
,
527 u8
*burstsize
, u8
*num_bursts
)
529 const unsigned int width_bytes
= width
* cpp
;
530 unsigned int npb
, bursts
;
532 /* Maximum number of pixels per burst without overshooting stride */
533 for (npb
= 64 / cpp
; npb
> 0; --npb
) {
534 if (round_up(width_bytes
, npb
* cpp
) <= stride
)
539 /* Maximum number of consecutive bursts without overshooting stride */
540 for (bursts
= 8; bursts
> 1; bursts
/= 2) {
541 if (round_up(width_bytes
, npb
* cpp
* bursts
) <= stride
)
544 *num_bursts
= bursts
;
547 static void ipu_plane_atomic_update(struct drm_plane
*plane
,
548 struct drm_plane_state
*old_state
)
550 struct ipu_plane
*ipu_plane
= to_ipu_plane(plane
);
551 struct drm_plane_state
*state
= plane
->state
;
552 struct ipu_plane_state
*ipu_state
= to_ipu_plane_state(state
);
553 struct drm_crtc_state
*crtc_state
= state
->crtc
->state
;
554 struct drm_framebuffer
*fb
= state
->fb
;
555 struct drm_rect
*dst
= &state
->dst
;
556 unsigned long eba
, ubo
, vbo
;
557 unsigned long alpha_eba
= 0;
558 enum ipu_color_space ics
;
559 unsigned int axi_id
= 0;
560 const struct drm_format_info
*info
;
561 u8 burstsize
, num_bursts
;
565 if (ipu_plane
->dp_flow
== IPU_DP_FLOW_SYNC_FG
)
566 ipu_dp_set_window_pos(ipu_plane
->dp
, dst
->x1
, dst
->y1
);
568 eba
= drm_plane_state_to_eba(state
, 0);
571 * Configure PRG channel and attached PRE, this changes the EBA to an
572 * internal SRAM location.
574 if (ipu_state
->use_pre
) {
575 axi_id
= ipu_chan_assign_axi_id(ipu_plane
->dma
);
576 ipu_prg_channel_configure(ipu_plane
->ipu_ch
, axi_id
,
577 drm_rect_width(&state
->src
) >> 16,
578 drm_rect_height(&state
->src
) >> 16,
579 fb
->pitches
[0], fb
->format
->format
,
583 if (old_state
->fb
&& !drm_atomic_crtc_needs_modeset(crtc_state
)) {
584 /* nothing to do if PRE is used */
585 if (ipu_state
->use_pre
)
587 active
= ipu_idmac_get_current_buffer(ipu_plane
->ipu_ch
);
588 ipu_cpmem_set_buffer(ipu_plane
->ipu_ch
, !active
, eba
);
589 ipu_idmac_select_buffer(ipu_plane
->ipu_ch
, !active
);
590 if (ipu_plane_separate_alpha(ipu_plane
)) {
591 active
= ipu_idmac_get_current_buffer(ipu_plane
->alpha_ch
);
592 ipu_cpmem_set_buffer(ipu_plane
->alpha_ch
, !active
,
594 ipu_idmac_select_buffer(ipu_plane
->alpha_ch
, !active
);
599 ics
= ipu_drm_fourcc_to_colorspace(fb
->format
->format
);
600 switch (ipu_plane
->dp_flow
) {
601 case IPU_DP_FLOW_SYNC_BG
:
602 ipu_dp_setup_channel(ipu_plane
->dp
, ics
, IPUV3_COLORSPACE_RGB
);
603 ipu_dp_set_global_alpha(ipu_plane
->dp
, true, 0, true);
605 case IPU_DP_FLOW_SYNC_FG
:
606 ipu_dp_setup_channel(ipu_plane
->dp
, ics
,
607 IPUV3_COLORSPACE_UNKNOWN
);
608 /* Enable local alpha on partial plane */
609 switch (fb
->format
->format
) {
610 case DRM_FORMAT_ARGB1555
:
611 case DRM_FORMAT_ABGR1555
:
612 case DRM_FORMAT_RGBA5551
:
613 case DRM_FORMAT_BGRA5551
:
614 case DRM_FORMAT_ARGB4444
:
615 case DRM_FORMAT_ARGB8888
:
616 case DRM_FORMAT_ABGR8888
:
617 case DRM_FORMAT_RGBA8888
:
618 case DRM_FORMAT_BGRA8888
:
619 case DRM_FORMAT_RGB565_A8
:
620 case DRM_FORMAT_BGR565_A8
:
621 case DRM_FORMAT_RGB888_A8
:
622 case DRM_FORMAT_BGR888_A8
:
623 case DRM_FORMAT_RGBX8888_A8
:
624 case DRM_FORMAT_BGRX8888_A8
:
625 ipu_dp_set_global_alpha(ipu_plane
->dp
, false, 0, false);
628 ipu_dp_set_global_alpha(ipu_plane
->dp
, true, 0, true);
633 ipu_dmfc_config_wait4eot(ipu_plane
->dmfc
, drm_rect_width(dst
));
635 width
= drm_rect_width(&state
->src
) >> 16;
636 height
= drm_rect_height(&state
->src
) >> 16;
637 info
= drm_format_info(fb
->format
->format
);
638 ipu_calculate_bursts(width
, info
->cpp
[0], fb
->pitches
[0],
639 &burstsize
, &num_bursts
);
641 ipu_cpmem_zero(ipu_plane
->ipu_ch
);
642 ipu_cpmem_set_resolution(ipu_plane
->ipu_ch
, width
, height
);
643 ipu_cpmem_set_fmt(ipu_plane
->ipu_ch
, fb
->format
->format
);
644 ipu_cpmem_set_burstsize(ipu_plane
->ipu_ch
, burstsize
);
645 ipu_cpmem_set_high_priority(ipu_plane
->ipu_ch
);
646 ipu_idmac_set_double_buffer(ipu_plane
->ipu_ch
, 1);
647 ipu_cpmem_set_stride(ipu_plane
->ipu_ch
, fb
->pitches
[0]);
648 ipu_cpmem_set_axi_id(ipu_plane
->ipu_ch
, axi_id
);
650 switch (fb
->format
->format
) {
651 case DRM_FORMAT_YUV420
:
652 case DRM_FORMAT_YVU420
:
653 case DRM_FORMAT_YUV422
:
654 case DRM_FORMAT_YVU422
:
655 case DRM_FORMAT_YUV444
:
656 case DRM_FORMAT_YVU444
:
657 ubo
= drm_plane_state_to_ubo(state
);
658 vbo
= drm_plane_state_to_vbo(state
);
659 if (fb
->format
->format
== DRM_FORMAT_YVU420
||
660 fb
->format
->format
== DRM_FORMAT_YVU422
||
661 fb
->format
->format
== DRM_FORMAT_YVU444
)
664 ipu_cpmem_set_yuv_planar_full(ipu_plane
->ipu_ch
,
665 fb
->pitches
[1], ubo
, vbo
);
667 dev_dbg(ipu_plane
->base
.dev
->dev
,
668 "phy = %lu %lu %lu, x = %d, y = %d", eba
, ubo
, vbo
,
669 state
->src
.x1
>> 16, state
->src
.y1
>> 16);
671 case DRM_FORMAT_NV12
:
672 case DRM_FORMAT_NV16
:
673 ubo
= drm_plane_state_to_ubo(state
);
675 ipu_cpmem_set_yuv_planar_full(ipu_plane
->ipu_ch
,
676 fb
->pitches
[1], ubo
, ubo
);
678 dev_dbg(ipu_plane
->base
.dev
->dev
,
679 "phy = %lu %lu, x = %d, y = %d", eba
, ubo
,
680 state
->src
.x1
>> 16, state
->src
.y1
>> 16);
682 case DRM_FORMAT_RGB565_A8
:
683 case DRM_FORMAT_BGR565_A8
:
684 case DRM_FORMAT_RGB888_A8
:
685 case DRM_FORMAT_BGR888_A8
:
686 case DRM_FORMAT_RGBX8888_A8
:
687 case DRM_FORMAT_BGRX8888_A8
:
688 alpha_eba
= drm_plane_state_to_eba(state
, 1);
691 dev_dbg(ipu_plane
->base
.dev
->dev
, "phys = %lu %lu, x = %d, y = %d",
692 eba
, alpha_eba
, state
->src
.x1
>> 16, state
->src
.y1
>> 16);
694 ipu_cpmem_set_burstsize(ipu_plane
->ipu_ch
, 16);
696 ipu_cpmem_zero(ipu_plane
->alpha_ch
);
697 ipu_cpmem_set_resolution(ipu_plane
->alpha_ch
,
698 drm_rect_width(&state
->src
) >> 16,
699 drm_rect_height(&state
->src
) >> 16);
700 ipu_cpmem_set_format_passthrough(ipu_plane
->alpha_ch
, 8);
701 ipu_cpmem_set_high_priority(ipu_plane
->alpha_ch
);
702 ipu_idmac_set_double_buffer(ipu_plane
->alpha_ch
, 1);
703 ipu_cpmem_set_stride(ipu_plane
->alpha_ch
, fb
->pitches
[1]);
704 ipu_cpmem_set_burstsize(ipu_plane
->alpha_ch
, 16);
705 ipu_cpmem_set_buffer(ipu_plane
->alpha_ch
, 0, alpha_eba
);
706 ipu_cpmem_set_buffer(ipu_plane
->alpha_ch
, 1, alpha_eba
);
709 dev_dbg(ipu_plane
->base
.dev
->dev
, "phys = %lu, x = %d, y = %d",
710 eba
, state
->src
.x1
>> 16, state
->src
.y1
>> 16);
713 ipu_cpmem_set_buffer(ipu_plane
->ipu_ch
, 0, eba
);
714 ipu_cpmem_set_buffer(ipu_plane
->ipu_ch
, 1, eba
);
715 ipu_idmac_lock_enable(ipu_plane
->ipu_ch
, num_bursts
);
716 ipu_plane_enable(ipu_plane
);
719 static const struct drm_plane_helper_funcs ipu_plane_helper_funcs
= {
720 .prepare_fb
= drm_gem_fb_prepare_fb
,
721 .atomic_check
= ipu_plane_atomic_check
,
722 .atomic_disable
= ipu_plane_atomic_disable
,
723 .atomic_update
= ipu_plane_atomic_update
,
726 int ipu_planes_assign_pre(struct drm_device
*dev
,
727 struct drm_atomic_state
*state
)
729 struct drm_crtc_state
*old_crtc_state
, *crtc_state
;
730 struct drm_plane_state
*plane_state
;
731 struct ipu_plane_state
*ipu_state
;
732 struct ipu_plane
*ipu_plane
;
733 struct drm_plane
*plane
;
734 struct drm_crtc
*crtc
;
735 int available_pres
= ipu_prg_max_active_channels();
738 for_each_oldnew_crtc_in_state(state
, crtc
, old_crtc_state
, crtc_state
, i
) {
739 ret
= drm_atomic_add_affected_planes(state
, crtc
);
745 * We are going over the planes in 2 passes: first we assign PREs to
746 * planes with a tiling modifier, which need the PREs to resolve into
747 * linear. Any failure to assign a PRE there is fatal. In the second
748 * pass we try to assign PREs to linear FBs, to improve memory access
749 * patterns for them. Failure at this point is non-fatal, as we can
750 * scan out linear FBs without a PRE.
752 for_each_new_plane_in_state(state
, plane
, plane_state
, i
) {
753 ipu_state
= to_ipu_plane_state(plane_state
);
754 ipu_plane
= to_ipu_plane(plane
);
756 if (!plane_state
->fb
) {
757 ipu_state
->use_pre
= false;
761 if (!(plane_state
->fb
->flags
& DRM_MODE_FB_MODIFIERS
) ||
762 plane_state
->fb
->modifier
== DRM_FORMAT_MOD_LINEAR
)
765 if (!ipu_prg_present(ipu_plane
->ipu
) || !available_pres
)
768 if (!ipu_prg_format_supported(ipu_plane
->ipu
,
769 plane_state
->fb
->format
->format
,
770 plane_state
->fb
->modifier
))
773 ipu_state
->use_pre
= true;
777 for_each_new_plane_in_state(state
, plane
, plane_state
, i
) {
778 ipu_state
= to_ipu_plane_state(plane_state
);
779 ipu_plane
= to_ipu_plane(plane
);
781 if (!plane_state
->fb
) {
782 ipu_state
->use_pre
= false;
786 if ((plane_state
->fb
->flags
& DRM_MODE_FB_MODIFIERS
) &&
787 plane_state
->fb
->modifier
!= DRM_FORMAT_MOD_LINEAR
)
790 /* make sure that modifier is initialized */
791 plane_state
->fb
->modifier
= DRM_FORMAT_MOD_LINEAR
;
793 if (ipu_prg_present(ipu_plane
->ipu
) && available_pres
&&
794 ipu_prg_format_supported(ipu_plane
->ipu
,
795 plane_state
->fb
->format
->format
,
796 plane_state
->fb
->modifier
)) {
797 ipu_state
->use_pre
= true;
800 ipu_state
->use_pre
= false;
806 EXPORT_SYMBOL_GPL(ipu_planes_assign_pre
);
808 struct ipu_plane
*ipu_plane_init(struct drm_device
*dev
, struct ipu_soc
*ipu
,
809 int dma
, int dp
, unsigned int possible_crtcs
,
810 enum drm_plane_type type
)
812 struct ipu_plane
*ipu_plane
;
813 const uint64_t *modifiers
= ipu_format_modifiers
;
816 DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n",
817 dma
, dp
, possible_crtcs
);
819 ipu_plane
= kzalloc(sizeof(*ipu_plane
), GFP_KERNEL
);
821 DRM_ERROR("failed to allocate plane\n");
822 return ERR_PTR(-ENOMEM
);
825 ipu_plane
->ipu
= ipu
;
826 ipu_plane
->dma
= dma
;
827 ipu_plane
->dp_flow
= dp
;
829 if (ipu_prg_present(ipu
))
830 modifiers
= pre_format_modifiers
;
832 ret
= drm_universal_plane_init(dev
, &ipu_plane
->base
, possible_crtcs
,
833 &ipu_plane_funcs
, ipu_plane_formats
,
834 ARRAY_SIZE(ipu_plane_formats
),
835 modifiers
, type
, NULL
);
837 DRM_ERROR("failed to initialize plane\n");
842 drm_plane_helper_add(&ipu_plane
->base
, &ipu_plane_helper_funcs
);