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_blend.h>
11 #include <drm/drm_fb_cma_helper.h>
12 #include <drm/drm_fourcc.h>
13 #include <drm/drm_framebuffer.h>
14 #include <drm/drm_gem_atomic_helper.h>
15 #include <drm/drm_gem_cma_helper.h>
16 #include <drm/drm_managed.h>
17 #include <drm/drm_plane_helper.h>
19 #include <video/imx-ipu-v3.h>
22 #include "ipuv3-plane.h"
24 struct ipu_plane_state {
25 struct drm_plane_state base;
29 static inline struct ipu_plane_state *
30 to_ipu_plane_state(struct drm_plane_state *p)
32 return container_of(p, struct ipu_plane_state, base);
35 static unsigned int ipu_src_rect_width(const struct drm_plane_state *state)
37 return ALIGN(drm_rect_width(&state->src) >> 16, 8);
40 static inline struct ipu_plane *to_ipu_plane(struct drm_plane *p)
42 return container_of(p, struct ipu_plane, base);
45 static const uint32_t ipu_plane_all_formats[] = {
78 DRM_FORMAT_RGBX8888_A8,
79 DRM_FORMAT_BGRX8888_A8,
82 static const uint32_t ipu_plane_rgb_formats[] = {
100 DRM_FORMAT_BGR565_A8,
101 DRM_FORMAT_RGB888_A8,
102 DRM_FORMAT_BGR888_A8,
103 DRM_FORMAT_RGBX8888_A8,
104 DRM_FORMAT_BGRX8888_A8,
107 static const uint64_t ipu_format_modifiers[] = {
108 DRM_FORMAT_MOD_LINEAR,
109 DRM_FORMAT_MOD_INVALID
112 static const uint64_t pre_format_modifiers[] = {
113 DRM_FORMAT_MOD_LINEAR,
114 DRM_FORMAT_MOD_VIVANTE_TILED,
115 DRM_FORMAT_MOD_VIVANTE_SUPER_TILED,
116 DRM_FORMAT_MOD_INVALID
119 int ipu_plane_irq(struct ipu_plane *ipu_plane)
121 return ipu_idmac_channel_irq(ipu_plane->ipu, ipu_plane->ipu_ch,
125 static inline unsigned long
126 drm_plane_state_to_eba(struct drm_plane_state *state, int plane)
128 struct drm_framebuffer *fb = state->fb;
129 struct drm_gem_cma_object *cma_obj;
130 int x = state->src.x1 >> 16;
131 int y = state->src.y1 >> 16;
133 cma_obj = drm_fb_cma_get_gem_obj(fb, plane);
136 return cma_obj->paddr + fb->offsets[plane] + fb->pitches[plane] * y +
137 fb->format->cpp[plane] * x;
140 static inline unsigned long
141 drm_plane_state_to_ubo(struct drm_plane_state *state)
143 struct drm_framebuffer *fb = state->fb;
144 struct drm_gem_cma_object *cma_obj;
145 unsigned long eba = drm_plane_state_to_eba(state, 0);
146 int x = state->src.x1 >> 16;
147 int y = state->src.y1 >> 16;
149 cma_obj = drm_fb_cma_get_gem_obj(fb, 1);
152 x /= fb->format->hsub;
153 y /= fb->format->vsub;
155 return cma_obj->paddr + fb->offsets[1] + fb->pitches[1] * y +
156 fb->format->cpp[1] * x - eba;
159 static inline unsigned long
160 drm_plane_state_to_vbo(struct drm_plane_state *state)
162 struct drm_framebuffer *fb = state->fb;
163 struct drm_gem_cma_object *cma_obj;
164 unsigned long eba = drm_plane_state_to_eba(state, 0);
165 int x = state->src.x1 >> 16;
166 int y = state->src.y1 >> 16;
168 cma_obj = drm_fb_cma_get_gem_obj(fb, 2);
171 x /= fb->format->hsub;
172 y /= fb->format->vsub;
174 return cma_obj->paddr + fb->offsets[2] + fb->pitches[2] * y +
175 fb->format->cpp[2] * x - eba;
178 static void ipu_plane_put_resources(struct drm_device *dev, void *ptr)
180 struct ipu_plane *ipu_plane = ptr;
182 if (!IS_ERR_OR_NULL(ipu_plane->dp))
183 ipu_dp_put(ipu_plane->dp);
184 if (!IS_ERR_OR_NULL(ipu_plane->dmfc))
185 ipu_dmfc_put(ipu_plane->dmfc);
186 if (!IS_ERR_OR_NULL(ipu_plane->ipu_ch))
187 ipu_idmac_put(ipu_plane->ipu_ch);
188 if (!IS_ERR_OR_NULL(ipu_plane->alpha_ch))
189 ipu_idmac_put(ipu_plane->alpha_ch);
192 static int ipu_plane_get_resources(struct drm_device *dev,
193 struct ipu_plane *ipu_plane)
198 ipu_plane->ipu_ch = ipu_idmac_get(ipu_plane->ipu, ipu_plane->dma);
199 if (IS_ERR(ipu_plane->ipu_ch)) {
200 ret = PTR_ERR(ipu_plane->ipu_ch);
201 DRM_ERROR("failed to get idmac channel: %d\n", ret);
205 ret = drmm_add_action_or_reset(dev, ipu_plane_put_resources, ipu_plane);
209 alpha_ch = ipu_channel_alpha_channel(ipu_plane->dma);
211 ipu_plane->alpha_ch = ipu_idmac_get(ipu_plane->ipu, alpha_ch);
212 if (IS_ERR(ipu_plane->alpha_ch)) {
213 ret = PTR_ERR(ipu_plane->alpha_ch);
214 DRM_ERROR("failed to get alpha idmac channel %d: %d\n",
220 ipu_plane->dmfc = ipu_dmfc_get(ipu_plane->ipu, ipu_plane->dma);
221 if (IS_ERR(ipu_plane->dmfc)) {
222 ret = PTR_ERR(ipu_plane->dmfc);
223 DRM_ERROR("failed to get dmfc: ret %d\n", ret);
227 if (ipu_plane->dp_flow >= 0) {
228 ipu_plane->dp = ipu_dp_get(ipu_plane->ipu, ipu_plane->dp_flow);
229 if (IS_ERR(ipu_plane->dp)) {
230 ret = PTR_ERR(ipu_plane->dp);
231 DRM_ERROR("failed to get dp flow: %d\n", ret);
239 static bool ipu_plane_separate_alpha(struct ipu_plane *ipu_plane)
241 switch (ipu_plane->base.state->fb->format->format) {
242 case DRM_FORMAT_RGB565_A8:
243 case DRM_FORMAT_BGR565_A8:
244 case DRM_FORMAT_RGB888_A8:
245 case DRM_FORMAT_BGR888_A8:
246 case DRM_FORMAT_RGBX8888_A8:
247 case DRM_FORMAT_BGRX8888_A8:
254 static void ipu_plane_enable(struct ipu_plane *ipu_plane)
257 ipu_dp_enable(ipu_plane->ipu);
258 ipu_dmfc_enable_channel(ipu_plane->dmfc);
259 ipu_idmac_enable_channel(ipu_plane->ipu_ch);
260 if (ipu_plane_separate_alpha(ipu_plane))
261 ipu_idmac_enable_channel(ipu_plane->alpha_ch);
263 ipu_dp_enable_channel(ipu_plane->dp);
266 void ipu_plane_disable(struct ipu_plane *ipu_plane, bool disable_dp_channel)
270 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
272 ret = ipu_idmac_wait_busy(ipu_plane->ipu_ch, 50);
273 if (ret == -ETIMEDOUT) {
274 DRM_ERROR("[PLANE:%d] IDMAC timeout\n",
275 ipu_plane->base.base.id);
278 if (ipu_plane->dp && disable_dp_channel)
279 ipu_dp_disable_channel(ipu_plane->dp, false);
280 ipu_idmac_disable_channel(ipu_plane->ipu_ch);
281 if (ipu_plane->alpha_ch)
282 ipu_idmac_disable_channel(ipu_plane->alpha_ch);
283 ipu_dmfc_disable_channel(ipu_plane->dmfc);
285 ipu_dp_disable(ipu_plane->ipu);
286 if (ipu_prg_present(ipu_plane->ipu))
287 ipu_prg_channel_disable(ipu_plane->ipu_ch);
290 void ipu_plane_disable_deferred(struct drm_plane *plane)
292 struct ipu_plane *ipu_plane = to_ipu_plane(plane);
294 if (ipu_plane->disabling) {
295 ipu_plane->disabling = false;
296 ipu_plane_disable(ipu_plane, false);
300 static void ipu_plane_state_reset(struct drm_plane *plane)
302 struct ipu_plane_state *ipu_state;
305 ipu_state = to_ipu_plane_state(plane->state);
306 __drm_atomic_helper_plane_destroy_state(plane->state);
311 ipu_state = kzalloc(sizeof(*ipu_state), GFP_KERNEL);
314 __drm_atomic_helper_plane_reset(plane, &ipu_state->base);
317 static struct drm_plane_state *
318 ipu_plane_duplicate_state(struct drm_plane *plane)
320 struct ipu_plane_state *state;
322 if (WARN_ON(!plane->state))
325 state = kmalloc(sizeof(*state), GFP_KERNEL);
327 __drm_atomic_helper_plane_duplicate_state(plane, &state->base);
332 static void ipu_plane_destroy_state(struct drm_plane *plane,
333 struct drm_plane_state *state)
335 struct ipu_plane_state *ipu_state = to_ipu_plane_state(state);
337 __drm_atomic_helper_plane_destroy_state(state);
341 static bool ipu_plane_format_mod_supported(struct drm_plane *plane,
342 uint32_t format, uint64_t modifier)
344 struct ipu_soc *ipu = to_ipu_plane(plane)->ipu;
346 /* linear is supported for all planes and formats */
347 if (modifier == DRM_FORMAT_MOD_LINEAR)
351 * Without a PRG the possible modifiers list only includes the linear
352 * modifier, so we always take the early return from this function and
353 * only end up here if the PRG is present.
355 return ipu_prg_format_supported(ipu, format, modifier);
358 static const struct drm_plane_funcs ipu_plane_funcs = {
359 .update_plane = drm_atomic_helper_update_plane,
360 .disable_plane = drm_atomic_helper_disable_plane,
361 .reset = ipu_plane_state_reset,
362 .atomic_duplicate_state = ipu_plane_duplicate_state,
363 .atomic_destroy_state = ipu_plane_destroy_state,
364 .format_mod_supported = ipu_plane_format_mod_supported,
367 static int ipu_plane_atomic_check(struct drm_plane *plane,
368 struct drm_atomic_state *state)
370 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
372 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
374 struct drm_crtc_state *crtc_state;
375 struct device *dev = plane->dev->dev;
376 struct drm_framebuffer *fb = new_state->fb;
377 struct drm_framebuffer *old_fb = old_state->fb;
378 unsigned long eba, ubo, vbo, old_ubo, old_vbo, alpha_eba;
379 bool can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY);
386 if (WARN_ON(!new_state->crtc))
390 drm_atomic_get_existing_crtc_state(state,
392 if (WARN_ON(!crtc_state))
395 ret = drm_atomic_helper_check_plane_state(new_state, crtc_state,
396 DRM_PLANE_HELPER_NO_SCALING,
397 DRM_PLANE_HELPER_NO_SCALING,
402 /* nothing to check when disabling or disabled */
403 if (!crtc_state->enable)
406 switch (plane->type) {
407 case DRM_PLANE_TYPE_PRIMARY:
408 /* full plane minimum width is 13 pixels */
409 if (drm_rect_width(&new_state->dst) < 13)
412 case DRM_PLANE_TYPE_OVERLAY:
415 dev_warn(dev, "Unsupported plane type %d\n", plane->type);
419 if (drm_rect_height(&new_state->dst) < 2)
423 * We support resizing active plane or changing its format by
424 * forcing CRTC mode change in plane's ->atomic_check callback
425 * and disabling all affected active planes in CRTC's ->atomic_disable
426 * callback. The planes will be reenabled in plane's ->atomic_update
430 (drm_rect_width(&new_state->dst) != drm_rect_width(&old_state->dst) ||
431 drm_rect_height(&new_state->dst) != drm_rect_height(&old_state->dst) ||
432 fb->format != old_fb->format))
433 crtc_state->mode_changed = true;
435 eba = drm_plane_state_to_eba(new_state, 0);
440 if (fb->pitches[0] < 1 || fb->pitches[0] > 16384)
443 if (old_fb && fb->pitches[0] != old_fb->pitches[0])
444 crtc_state->mode_changed = true;
446 if (ALIGN(fb->width, 8) * fb->format->cpp[0] >
447 fb->pitches[0] + fb->offsets[0]) {
448 dev_warn(dev, "pitch is not big enough for 8 pixels alignment");
452 switch (fb->format->format) {
453 case DRM_FORMAT_YUV420:
454 case DRM_FORMAT_YVU420:
455 case DRM_FORMAT_YUV422:
456 case DRM_FORMAT_YVU422:
457 case DRM_FORMAT_YUV444:
458 case DRM_FORMAT_YVU444:
460 * Multiplanar formats have to meet the following restrictions:
461 * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO
462 * - EBA, UBO and VBO are a multiple of 8
463 * - UBO and VBO are unsigned and not larger than 0xfffff8
464 * - Only EBA may be changed while scanout is active
465 * - The strides of U and V planes must be identical.
467 vbo = drm_plane_state_to_vbo(new_state);
469 if (vbo & 0x7 || vbo > 0xfffff8)
472 if (old_fb && (fb->format == old_fb->format)) {
473 old_vbo = drm_plane_state_to_vbo(old_state);
475 crtc_state->mode_changed = true;
478 if (fb->pitches[1] != fb->pitches[2])
482 case DRM_FORMAT_NV12:
483 case DRM_FORMAT_NV16:
484 ubo = drm_plane_state_to_ubo(new_state);
486 if (ubo & 0x7 || ubo > 0xfffff8)
489 if (old_fb && (fb->format == old_fb->format)) {
490 old_ubo = drm_plane_state_to_ubo(old_state);
492 crtc_state->mode_changed = true;
495 if (fb->pitches[1] < 1 || fb->pitches[1] > 16384)
498 if (old_fb && old_fb->pitches[1] != fb->pitches[1])
499 crtc_state->mode_changed = true;
502 * The x/y offsets must be even in case of horizontal/vertical
503 * chroma subsampling.
505 if (((new_state->src.x1 >> 16) & (fb->format->hsub - 1)) ||
506 ((new_state->src.y1 >> 16) & (fb->format->vsub - 1)))
509 case DRM_FORMAT_RGB565_A8:
510 case DRM_FORMAT_BGR565_A8:
511 case DRM_FORMAT_RGB888_A8:
512 case DRM_FORMAT_BGR888_A8:
513 case DRM_FORMAT_RGBX8888_A8:
514 case DRM_FORMAT_BGRX8888_A8:
515 alpha_eba = drm_plane_state_to_eba(new_state, 1);
519 if (fb->pitches[1] < 1 || fb->pitches[1] > 16384)
522 if (old_fb && old_fb->pitches[1] != fb->pitches[1])
523 crtc_state->mode_changed = true;
530 static void ipu_plane_atomic_disable(struct drm_plane *plane,
531 struct drm_atomic_state *state)
533 struct ipu_plane *ipu_plane = to_ipu_plane(plane);
536 ipu_dp_disable_channel(ipu_plane->dp, true);
537 ipu_plane->disabling = true;
540 static int ipu_chan_assign_axi_id(int ipu_chan)
543 case IPUV3_CHANNEL_MEM_BG_SYNC:
545 case IPUV3_CHANNEL_MEM_FG_SYNC:
547 case IPUV3_CHANNEL_MEM_DC_SYNC:
554 static void ipu_calculate_bursts(u32 width, u32 cpp, u32 stride,
555 u8 *burstsize, u8 *num_bursts)
557 const unsigned int width_bytes = width * cpp;
558 unsigned int npb, bursts;
560 /* Maximum number of pixels per burst without overshooting stride */
561 for (npb = 64 / cpp; npb > 0; --npb) {
562 if (round_up(width_bytes, npb * cpp) <= stride)
567 /* Maximum number of consecutive bursts without overshooting stride */
568 for (bursts = 8; bursts > 1; bursts /= 2) {
569 if (round_up(width_bytes, npb * cpp * bursts) <= stride)
572 *num_bursts = bursts;
575 static void ipu_plane_atomic_update(struct drm_plane *plane,
576 struct drm_atomic_state *state)
578 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
580 struct ipu_plane *ipu_plane = to_ipu_plane(plane);
581 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
583 struct ipu_plane_state *ipu_state = to_ipu_plane_state(new_state);
584 struct drm_crtc_state *crtc_state = new_state->crtc->state;
585 struct drm_framebuffer *fb = new_state->fb;
586 struct drm_rect *dst = &new_state->dst;
587 unsigned long eba, ubo, vbo;
588 unsigned long alpha_eba = 0;
589 enum ipu_color_space ics;
590 unsigned int axi_id = 0;
591 const struct drm_format_info *info;
592 u8 burstsize, num_bursts;
596 if (ipu_plane->dp_flow == IPU_DP_FLOW_SYNC_FG)
597 ipu_dp_set_window_pos(ipu_plane->dp, dst->x1, dst->y1);
599 switch (ipu_plane->dp_flow) {
600 case IPU_DP_FLOW_SYNC_BG:
601 if (new_state->normalized_zpos == 1) {
602 ipu_dp_set_global_alpha(ipu_plane->dp,
603 !fb->format->has_alpha, 0xff,
606 ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true);
609 case IPU_DP_FLOW_SYNC_FG:
610 if (new_state->normalized_zpos == 1) {
611 ipu_dp_set_global_alpha(ipu_plane->dp,
612 !fb->format->has_alpha, 0xff,
618 eba = drm_plane_state_to_eba(new_state, 0);
621 * Configure PRG channel and attached PRE, this changes the EBA to an
622 * internal SRAM location.
624 if (ipu_state->use_pre) {
625 axi_id = ipu_chan_assign_axi_id(ipu_plane->dma);
626 ipu_prg_channel_configure(ipu_plane->ipu_ch, axi_id,
627 ipu_src_rect_width(new_state),
628 drm_rect_height(&new_state->src) >> 16,
629 fb->pitches[0], fb->format->format,
633 if (!old_state->fb ||
634 old_state->fb->format->format != fb->format->format ||
635 old_state->color_encoding != new_state->color_encoding ||
636 old_state->color_range != new_state->color_range) {
637 ics = ipu_drm_fourcc_to_colorspace(fb->format->format);
638 switch (ipu_plane->dp_flow) {
639 case IPU_DP_FLOW_SYNC_BG:
640 ipu_dp_setup_channel(ipu_plane->dp, new_state->color_encoding,
641 new_state->color_range, ics,
642 IPUV3_COLORSPACE_RGB);
644 case IPU_DP_FLOW_SYNC_FG:
645 ipu_dp_setup_channel(ipu_plane->dp, new_state->color_encoding,
646 new_state->color_range, ics,
647 IPUV3_COLORSPACE_UNKNOWN);
652 if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) {
653 /* nothing to do if PRE is used */
654 if (ipu_state->use_pre)
656 active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch);
657 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba);
658 ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active);
659 if (ipu_plane_separate_alpha(ipu_plane)) {
660 active = ipu_idmac_get_current_buffer(ipu_plane->alpha_ch);
661 ipu_cpmem_set_buffer(ipu_plane->alpha_ch, !active,
663 ipu_idmac_select_buffer(ipu_plane->alpha_ch, !active);
668 ics = ipu_drm_fourcc_to_colorspace(fb->format->format);
669 switch (ipu_plane->dp_flow) {
670 case IPU_DP_FLOW_SYNC_BG:
671 ipu_dp_setup_channel(ipu_plane->dp, DRM_COLOR_YCBCR_BT601,
672 DRM_COLOR_YCBCR_LIMITED_RANGE, ics,
673 IPUV3_COLORSPACE_RGB);
675 case IPU_DP_FLOW_SYNC_FG:
676 ipu_dp_setup_channel(ipu_plane->dp, DRM_COLOR_YCBCR_BT601,
677 DRM_COLOR_YCBCR_LIMITED_RANGE, ics,
678 IPUV3_COLORSPACE_UNKNOWN);
682 ipu_dmfc_config_wait4eot(ipu_plane->dmfc, ALIGN(drm_rect_width(dst), 8));
684 width = ipu_src_rect_width(new_state);
685 height = drm_rect_height(&new_state->src) >> 16;
686 info = drm_format_info(fb->format->format);
687 ipu_calculate_bursts(width, info->cpp[0], fb->pitches[0],
688 &burstsize, &num_bursts);
690 ipu_cpmem_zero(ipu_plane->ipu_ch);
691 ipu_cpmem_set_resolution(ipu_plane->ipu_ch, width, height);
692 ipu_cpmem_set_fmt(ipu_plane->ipu_ch, fb->format->format);
693 ipu_cpmem_set_burstsize(ipu_plane->ipu_ch, burstsize);
694 ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);
695 ipu_idmac_enable_watermark(ipu_plane->ipu_ch, true);
696 ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1);
697 ipu_cpmem_set_stride(ipu_plane->ipu_ch, fb->pitches[0]);
698 ipu_cpmem_set_axi_id(ipu_plane->ipu_ch, axi_id);
700 switch (fb->format->format) {
701 case DRM_FORMAT_YUV420:
702 case DRM_FORMAT_YVU420:
703 case DRM_FORMAT_YUV422:
704 case DRM_FORMAT_YVU422:
705 case DRM_FORMAT_YUV444:
706 case DRM_FORMAT_YVU444:
707 ubo = drm_plane_state_to_ubo(new_state);
708 vbo = drm_plane_state_to_vbo(new_state);
709 if (fb->format->format == DRM_FORMAT_YVU420 ||
710 fb->format->format == DRM_FORMAT_YVU422 ||
711 fb->format->format == DRM_FORMAT_YVU444)
714 ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
715 fb->pitches[1], ubo, vbo);
717 dev_dbg(ipu_plane->base.dev->dev,
718 "phy = %lu %lu %lu, x = %d, y = %d", eba, ubo, vbo,
719 new_state->src.x1 >> 16, new_state->src.y1 >> 16);
721 case DRM_FORMAT_NV12:
722 case DRM_FORMAT_NV16:
723 ubo = drm_plane_state_to_ubo(new_state);
725 ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
726 fb->pitches[1], ubo, ubo);
728 dev_dbg(ipu_plane->base.dev->dev,
729 "phy = %lu %lu, x = %d, y = %d", eba, ubo,
730 new_state->src.x1 >> 16, new_state->src.y1 >> 16);
732 case DRM_FORMAT_RGB565_A8:
733 case DRM_FORMAT_BGR565_A8:
734 case DRM_FORMAT_RGB888_A8:
735 case DRM_FORMAT_BGR888_A8:
736 case DRM_FORMAT_RGBX8888_A8:
737 case DRM_FORMAT_BGRX8888_A8:
738 alpha_eba = drm_plane_state_to_eba(new_state, 1);
741 dev_dbg(ipu_plane->base.dev->dev, "phys = %lu %lu, x = %d, y = %d",
742 eba, alpha_eba, new_state->src.x1 >> 16,
743 new_state->src.y1 >> 16);
745 ipu_cpmem_set_burstsize(ipu_plane->ipu_ch, 16);
747 ipu_cpmem_zero(ipu_plane->alpha_ch);
748 ipu_cpmem_set_resolution(ipu_plane->alpha_ch,
749 ipu_src_rect_width(new_state),
750 drm_rect_height(&new_state->src) >> 16);
751 ipu_cpmem_set_format_passthrough(ipu_plane->alpha_ch, 8);
752 ipu_cpmem_set_high_priority(ipu_plane->alpha_ch);
753 ipu_idmac_set_double_buffer(ipu_plane->alpha_ch, 1);
754 ipu_cpmem_set_stride(ipu_plane->alpha_ch, fb->pitches[1]);
755 ipu_cpmem_set_burstsize(ipu_plane->alpha_ch, 16);
756 ipu_cpmem_set_buffer(ipu_plane->alpha_ch, 0, alpha_eba);
757 ipu_cpmem_set_buffer(ipu_plane->alpha_ch, 1, alpha_eba);
760 dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d",
761 eba, new_state->src.x1 >> 16, new_state->src.y1 >> 16);
764 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba);
765 ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba);
766 ipu_idmac_lock_enable(ipu_plane->ipu_ch, num_bursts);
767 ipu_plane_enable(ipu_plane);
770 static const struct drm_plane_helper_funcs ipu_plane_helper_funcs = {
771 .atomic_check = ipu_plane_atomic_check,
772 .atomic_disable = ipu_plane_atomic_disable,
773 .atomic_update = ipu_plane_atomic_update,
776 bool ipu_plane_atomic_update_pending(struct drm_plane *plane)
778 struct ipu_plane *ipu_plane = to_ipu_plane(plane);
779 struct drm_plane_state *state = plane->state;
780 struct ipu_plane_state *ipu_state = to_ipu_plane_state(state);
782 /* disabled crtcs must not block the update */
786 if (ipu_state->use_pre)
787 return ipu_prg_channel_configure_pending(ipu_plane->ipu_ch);
790 * Pretend no update is pending in the non-PRE/PRG case. For this to
791 * happen, an atomic update would have to be deferred until after the
792 * start of the next frame and simultaneously interrupt latency would
793 * have to be high enough to let the atomic update finish and issue an
794 * event before the previous end of frame interrupt handler can be
799 int ipu_planes_assign_pre(struct drm_device *dev,
800 struct drm_atomic_state *state)
802 struct drm_crtc_state *old_crtc_state, *crtc_state;
803 struct drm_plane_state *plane_state;
804 struct ipu_plane_state *ipu_state;
805 struct ipu_plane *ipu_plane;
806 struct drm_plane *plane;
807 struct drm_crtc *crtc;
808 int available_pres = ipu_prg_max_active_channels();
811 for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, crtc_state, i) {
812 ret = drm_atomic_add_affected_planes(state, crtc);
818 * We are going over the planes in 2 passes: first we assign PREs to
819 * planes with a tiling modifier, which need the PREs to resolve into
820 * linear. Any failure to assign a PRE there is fatal. In the second
821 * pass we try to assign PREs to linear FBs, to improve memory access
822 * patterns for them. Failure at this point is non-fatal, as we can
823 * scan out linear FBs without a PRE.
825 for_each_new_plane_in_state(state, plane, plane_state, i) {
826 ipu_state = to_ipu_plane_state(plane_state);
827 ipu_plane = to_ipu_plane(plane);
829 if (!plane_state->fb) {
830 ipu_state->use_pre = false;
834 if (!(plane_state->fb->flags & DRM_MODE_FB_MODIFIERS) ||
835 plane_state->fb->modifier == DRM_FORMAT_MOD_LINEAR)
838 if (!ipu_prg_present(ipu_plane->ipu) || !available_pres)
841 if (!ipu_prg_format_supported(ipu_plane->ipu,
842 plane_state->fb->format->format,
843 plane_state->fb->modifier))
846 ipu_state->use_pre = true;
850 for_each_new_plane_in_state(state, plane, plane_state, i) {
851 ipu_state = to_ipu_plane_state(plane_state);
852 ipu_plane = to_ipu_plane(plane);
854 if (!plane_state->fb) {
855 ipu_state->use_pre = false;
859 if ((plane_state->fb->flags & DRM_MODE_FB_MODIFIERS) &&
860 plane_state->fb->modifier != DRM_FORMAT_MOD_LINEAR)
863 /* make sure that modifier is initialized */
864 plane_state->fb->modifier = DRM_FORMAT_MOD_LINEAR;
866 if (ipu_prg_present(ipu_plane->ipu) && available_pres &&
867 ipu_prg_format_supported(ipu_plane->ipu,
868 plane_state->fb->format->format,
869 plane_state->fb->modifier)) {
870 ipu_state->use_pre = true;
873 ipu_state->use_pre = false;
880 struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
881 int dma, int dp, unsigned int possible_crtcs,
882 enum drm_plane_type type)
884 struct ipu_plane *ipu_plane;
885 const uint64_t *modifiers = ipu_format_modifiers;
886 unsigned int zpos = (type == DRM_PLANE_TYPE_PRIMARY) ? 0 : 1;
887 unsigned int format_count;
888 const uint32_t *formats;
891 DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n",
892 dma, dp, possible_crtcs);
894 if (dp == IPU_DP_FLOW_SYNC_BG || dp == IPU_DP_FLOW_SYNC_FG) {
895 formats = ipu_plane_all_formats;
896 format_count = ARRAY_SIZE(ipu_plane_all_formats);
898 formats = ipu_plane_rgb_formats;
899 format_count = ARRAY_SIZE(ipu_plane_rgb_formats);
902 if (ipu_prg_present(ipu))
903 modifiers = pre_format_modifiers;
905 ipu_plane = drmm_universal_plane_alloc(dev, struct ipu_plane, base,
906 possible_crtcs, &ipu_plane_funcs,
907 formats, format_count, modifiers,
909 if (IS_ERR(ipu_plane)) {
910 DRM_ERROR("failed to allocate and initialize %s plane\n",
911 zpos ? "overlay" : "primary");
915 ipu_plane->ipu = ipu;
916 ipu_plane->dma = dma;
917 ipu_plane->dp_flow = dp;
919 drm_plane_helper_add(&ipu_plane->base, &ipu_plane_helper_funcs);
921 if (dp == IPU_DP_FLOW_SYNC_BG || dp == IPU_DP_FLOW_SYNC_FG)
922 ret = drm_plane_create_zpos_property(&ipu_plane->base, zpos, 0,
925 ret = drm_plane_create_zpos_immutable_property(&ipu_plane->base,
930 ret = drm_plane_create_color_properties(&ipu_plane->base,
931 BIT(DRM_COLOR_YCBCR_BT601) |
932 BIT(DRM_COLOR_YCBCR_BT709),
933 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
934 DRM_COLOR_YCBCR_BT601,
935 DRM_COLOR_YCBCR_LIMITED_RANGE);
939 ret = ipu_plane_get_resources(dev, ipu_plane);
941 DRM_ERROR("failed to get %s plane resources: %pe\n",
942 zpos ? "overlay" : "primary", &ret);