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_plane_helper.h>
23 #include "video/imx-ipu-v3.h"
24 #include "ipuv3-plane.h"
26 struct ipu_plane_state
{
27 struct drm_plane_state base
;
31 static inline struct ipu_plane_state
*
32 to_ipu_plane_state(struct drm_plane_state
*p
)
34 return container_of(p
, struct ipu_plane_state
, base
);
37 static inline struct ipu_plane
*to_ipu_plane(struct drm_plane
*p
)
39 return container_of(p
, struct ipu_plane
, base
);
42 static const uint32_t ipu_plane_formats
[] = {
75 DRM_FORMAT_RGBX8888_A8
,
76 DRM_FORMAT_BGRX8888_A8
,
79 int ipu_plane_irq(struct ipu_plane
*ipu_plane
)
81 return ipu_idmac_channel_irq(ipu_plane
->ipu
, ipu_plane
->ipu_ch
,
85 static inline unsigned long
86 drm_plane_state_to_eba(struct drm_plane_state
*state
, int plane
)
88 struct drm_framebuffer
*fb
= state
->fb
;
89 struct drm_gem_cma_object
*cma_obj
;
90 int x
= state
->src
.x1
>> 16;
91 int y
= state
->src
.y1
>> 16;
93 cma_obj
= drm_fb_cma_get_gem_obj(fb
, plane
);
96 return cma_obj
->paddr
+ fb
->offsets
[plane
] + fb
->pitches
[plane
] * y
+
97 fb
->format
->cpp
[plane
] * x
;
100 static inline unsigned long
101 drm_plane_state_to_ubo(struct drm_plane_state
*state
)
103 struct drm_framebuffer
*fb
= state
->fb
;
104 struct drm_gem_cma_object
*cma_obj
;
105 unsigned long eba
= drm_plane_state_to_eba(state
, 0);
106 int x
= state
->src
.x1
>> 16;
107 int y
= state
->src
.y1
>> 16;
109 cma_obj
= drm_fb_cma_get_gem_obj(fb
, 1);
112 x
/= drm_format_horz_chroma_subsampling(fb
->format
->format
);
113 y
/= drm_format_vert_chroma_subsampling(fb
->format
->format
);
115 return cma_obj
->paddr
+ fb
->offsets
[1] + fb
->pitches
[1] * y
+
116 fb
->format
->cpp
[1] * x
- eba
;
119 static inline unsigned long
120 drm_plane_state_to_vbo(struct drm_plane_state
*state
)
122 struct drm_framebuffer
*fb
= state
->fb
;
123 struct drm_gem_cma_object
*cma_obj
;
124 unsigned long eba
= drm_plane_state_to_eba(state
, 0);
125 int x
= state
->src
.x1
>> 16;
126 int y
= state
->src
.y1
>> 16;
128 cma_obj
= drm_fb_cma_get_gem_obj(fb
, 2);
131 x
/= drm_format_horz_chroma_subsampling(fb
->format
->format
);
132 y
/= drm_format_vert_chroma_subsampling(fb
->format
->format
);
134 return cma_obj
->paddr
+ fb
->offsets
[2] + fb
->pitches
[2] * y
+
135 fb
->format
->cpp
[2] * x
- eba
;
138 void ipu_plane_put_resources(struct ipu_plane
*ipu_plane
)
140 if (!IS_ERR_OR_NULL(ipu_plane
->dp
))
141 ipu_dp_put(ipu_plane
->dp
);
142 if (!IS_ERR_OR_NULL(ipu_plane
->dmfc
))
143 ipu_dmfc_put(ipu_plane
->dmfc
);
144 if (!IS_ERR_OR_NULL(ipu_plane
->ipu_ch
))
145 ipu_idmac_put(ipu_plane
->ipu_ch
);
146 if (!IS_ERR_OR_NULL(ipu_plane
->alpha_ch
))
147 ipu_idmac_put(ipu_plane
->alpha_ch
);
150 int ipu_plane_get_resources(struct ipu_plane
*ipu_plane
)
155 ipu_plane
->ipu_ch
= ipu_idmac_get(ipu_plane
->ipu
, ipu_plane
->dma
);
156 if (IS_ERR(ipu_plane
->ipu_ch
)) {
157 ret
= PTR_ERR(ipu_plane
->ipu_ch
);
158 DRM_ERROR("failed to get idmac channel: %d\n", ret
);
162 alpha_ch
= ipu_channel_alpha_channel(ipu_plane
->dma
);
164 ipu_plane
->alpha_ch
= ipu_idmac_get(ipu_plane
->ipu
, alpha_ch
);
165 if (IS_ERR(ipu_plane
->alpha_ch
)) {
166 ret
= PTR_ERR(ipu_plane
->alpha_ch
);
167 DRM_ERROR("failed to get alpha idmac channel %d: %d\n",
173 ipu_plane
->dmfc
= ipu_dmfc_get(ipu_plane
->ipu
, ipu_plane
->dma
);
174 if (IS_ERR(ipu_plane
->dmfc
)) {
175 ret
= PTR_ERR(ipu_plane
->dmfc
);
176 DRM_ERROR("failed to get dmfc: ret %d\n", ret
);
180 if (ipu_plane
->dp_flow
>= 0) {
181 ipu_plane
->dp
= ipu_dp_get(ipu_plane
->ipu
, ipu_plane
->dp_flow
);
182 if (IS_ERR(ipu_plane
->dp
)) {
183 ret
= PTR_ERR(ipu_plane
->dp
);
184 DRM_ERROR("failed to get dp flow: %d\n", ret
);
191 ipu_plane_put_resources(ipu_plane
);
196 static bool ipu_plane_separate_alpha(struct ipu_plane
*ipu_plane
)
198 switch (ipu_plane
->base
.state
->fb
->format
->format
) {
199 case DRM_FORMAT_RGB565_A8
:
200 case DRM_FORMAT_BGR565_A8
:
201 case DRM_FORMAT_RGB888_A8
:
202 case DRM_FORMAT_BGR888_A8
:
203 case DRM_FORMAT_RGBX8888_A8
:
204 case DRM_FORMAT_BGRX8888_A8
:
211 static void ipu_plane_enable(struct ipu_plane
*ipu_plane
)
214 ipu_dp_enable(ipu_plane
->ipu
);
215 ipu_dmfc_enable_channel(ipu_plane
->dmfc
);
216 ipu_idmac_enable_channel(ipu_plane
->ipu_ch
);
217 if (ipu_plane_separate_alpha(ipu_plane
))
218 ipu_idmac_enable_channel(ipu_plane
->alpha_ch
);
220 ipu_dp_enable_channel(ipu_plane
->dp
);
223 void ipu_plane_disable(struct ipu_plane
*ipu_plane
, bool disable_dp_channel
)
225 DRM_DEBUG_KMS("[%d] %s\n", __LINE__
, __func__
);
227 ipu_idmac_wait_busy(ipu_plane
->ipu_ch
, 50);
229 if (ipu_plane
->dp
&& disable_dp_channel
)
230 ipu_dp_disable_channel(ipu_plane
->dp
, false);
231 ipu_idmac_disable_channel(ipu_plane
->ipu_ch
);
232 if (ipu_plane
->alpha_ch
)
233 ipu_idmac_disable_channel(ipu_plane
->alpha_ch
);
234 ipu_dmfc_disable_channel(ipu_plane
->dmfc
);
236 ipu_dp_disable(ipu_plane
->ipu
);
237 if (ipu_prg_present(ipu_plane
->ipu
))
238 ipu_prg_channel_disable(ipu_plane
->ipu_ch
);
241 void ipu_plane_disable_deferred(struct drm_plane
*plane
)
243 struct ipu_plane
*ipu_plane
= to_ipu_plane(plane
);
245 if (ipu_plane
->disabling
) {
246 ipu_plane
->disabling
= false;
247 ipu_plane_disable(ipu_plane
, false);
250 EXPORT_SYMBOL_GPL(ipu_plane_disable_deferred
);
252 static void ipu_plane_destroy(struct drm_plane
*plane
)
254 struct ipu_plane
*ipu_plane
= to_ipu_plane(plane
);
256 DRM_DEBUG_KMS("[%d] %s\n", __LINE__
, __func__
);
258 drm_plane_cleanup(plane
);
262 void ipu_plane_state_reset(struct drm_plane
*plane
)
264 struct ipu_plane_state
*ipu_state
;
267 ipu_state
= to_ipu_plane_state(plane
->state
);
268 __drm_atomic_helper_plane_destroy_state(plane
->state
);
272 ipu_state
= kzalloc(sizeof(*ipu_state
), GFP_KERNEL
);
275 ipu_state
->base
.plane
= plane
;
276 ipu_state
->base
.rotation
= DRM_MODE_ROTATE_0
;
279 plane
->state
= &ipu_state
->base
;
282 struct drm_plane_state
*ipu_plane_duplicate_state(struct drm_plane
*plane
)
284 struct ipu_plane_state
*state
;
286 if (WARN_ON(!plane
->state
))
289 state
= kmalloc(sizeof(*state
), GFP_KERNEL
);
291 __drm_atomic_helper_plane_duplicate_state(plane
, &state
->base
);
296 void ipu_plane_destroy_state(struct drm_plane
*plane
,
297 struct drm_plane_state
*state
)
299 struct ipu_plane_state
*ipu_state
= to_ipu_plane_state(state
);
301 __drm_atomic_helper_plane_destroy_state(state
);
305 static const struct drm_plane_funcs ipu_plane_funcs
= {
306 .update_plane
= drm_atomic_helper_update_plane
,
307 .disable_plane
= drm_atomic_helper_disable_plane
,
308 .destroy
= ipu_plane_destroy
,
309 .reset
= ipu_plane_state_reset
,
310 .atomic_duplicate_state
= ipu_plane_duplicate_state
,
311 .atomic_destroy_state
= ipu_plane_destroy_state
,
314 static int ipu_plane_atomic_check(struct drm_plane
*plane
,
315 struct drm_plane_state
*state
)
317 struct drm_plane_state
*old_state
= plane
->state
;
318 struct drm_crtc_state
*crtc_state
;
319 struct device
*dev
= plane
->dev
->dev
;
320 struct drm_framebuffer
*fb
= state
->fb
;
321 struct drm_framebuffer
*old_fb
= old_state
->fb
;
322 unsigned long eba
, ubo
, vbo
, old_ubo
, old_vbo
, alpha_eba
;
323 bool can_position
= (plane
->type
== DRM_PLANE_TYPE_OVERLAY
);
324 struct drm_rect clip
;
336 drm_atomic_get_existing_crtc_state(state
->state
, state
->crtc
);
337 if (WARN_ON(!crtc_state
))
342 clip
.x2
= crtc_state
->adjusted_mode
.hdisplay
;
343 clip
.y2
= crtc_state
->adjusted_mode
.vdisplay
;
344 ret
= drm_plane_helper_check_state(state
, &clip
,
345 DRM_PLANE_HELPER_NO_SCALING
,
346 DRM_PLANE_HELPER_NO_SCALING
,
351 /* CRTC should be enabled */
352 if (!crtc_state
->enable
)
355 switch (plane
->type
) {
356 case DRM_PLANE_TYPE_PRIMARY
:
357 /* full plane minimum width is 13 pixels */
358 if (drm_rect_width(&state
->dst
) < 13)
361 case DRM_PLANE_TYPE_OVERLAY
:
364 dev_warn(dev
, "Unsupported plane type %d\n", plane
->type
);
368 if (drm_rect_height(&state
->dst
) < 2)
372 * We support resizing active plane or changing its format by
373 * forcing CRTC mode change in plane's ->atomic_check callback
374 * and disabling all affected active planes in CRTC's ->atomic_disable
375 * callback. The planes will be reenabled in plane's ->atomic_update
379 (drm_rect_width(&state
->dst
) != drm_rect_width(&old_state
->dst
) ||
380 drm_rect_height(&state
->dst
) != drm_rect_height(&old_state
->dst
) ||
381 fb
->format
!= old_fb
->format
))
382 crtc_state
->mode_changed
= true;
384 eba
= drm_plane_state_to_eba(state
, 0);
389 if (fb
->pitches
[0] < 1 || fb
->pitches
[0] > 16384)
392 if (old_fb
&& fb
->pitches
[0] != old_fb
->pitches
[0])
393 crtc_state
->mode_changed
= true;
395 switch (fb
->format
->format
) {
396 case DRM_FORMAT_YUV420
:
397 case DRM_FORMAT_YVU420
:
398 case DRM_FORMAT_YUV422
:
399 case DRM_FORMAT_YVU422
:
400 case DRM_FORMAT_YUV444
:
401 case DRM_FORMAT_YVU444
:
403 * Multiplanar formats have to meet the following restrictions:
404 * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO
405 * - EBA, UBO and VBO are a multiple of 8
406 * - UBO and VBO are unsigned and not larger than 0xfffff8
407 * - Only EBA may be changed while scanout is active
408 * - The strides of U and V planes must be identical.
410 vbo
= drm_plane_state_to_vbo(state
);
412 if (vbo
& 0x7 || vbo
> 0xfffff8)
415 if (old_fb
&& (fb
->format
== old_fb
->format
)) {
416 old_vbo
= drm_plane_state_to_vbo(old_state
);
418 crtc_state
->mode_changed
= true;
421 if (fb
->pitches
[1] != fb
->pitches
[2])
425 case DRM_FORMAT_NV12
:
426 case DRM_FORMAT_NV16
:
427 ubo
= drm_plane_state_to_ubo(state
);
429 if (ubo
& 0x7 || ubo
> 0xfffff8)
432 if (old_fb
&& (fb
->format
== old_fb
->format
)) {
433 old_ubo
= drm_plane_state_to_ubo(old_state
);
435 crtc_state
->mode_changed
= true;
438 if (fb
->pitches
[1] < 1 || fb
->pitches
[1] > 16384)
441 if (old_fb
&& old_fb
->pitches
[1] != fb
->pitches
[1])
442 crtc_state
->mode_changed
= true;
445 * The x/y offsets must be even in case of horizontal/vertical
446 * chroma subsampling.
448 hsub
= drm_format_horz_chroma_subsampling(fb
->format
->format
);
449 vsub
= drm_format_vert_chroma_subsampling(fb
->format
->format
);
450 if (((state
->src
.x1
>> 16) & (hsub
- 1)) ||
451 ((state
->src
.y1
>> 16) & (vsub
- 1)))
454 case DRM_FORMAT_RGB565_A8
:
455 case DRM_FORMAT_BGR565_A8
:
456 case DRM_FORMAT_RGB888_A8
:
457 case DRM_FORMAT_BGR888_A8
:
458 case DRM_FORMAT_RGBX8888_A8
:
459 case DRM_FORMAT_BGRX8888_A8
:
460 alpha_eba
= drm_plane_state_to_eba(state
, 1);
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;
475 static void ipu_plane_atomic_disable(struct drm_plane
*plane
,
476 struct drm_plane_state
*old_state
)
478 struct ipu_plane
*ipu_plane
= to_ipu_plane(plane
);
481 ipu_dp_disable_channel(ipu_plane
->dp
, true);
482 ipu_plane
->disabling
= true;
485 static int ipu_chan_assign_axi_id(int ipu_chan
)
488 case IPUV3_CHANNEL_MEM_BG_SYNC
:
490 case IPUV3_CHANNEL_MEM_FG_SYNC
:
492 case IPUV3_CHANNEL_MEM_DC_SYNC
:
499 static void ipu_plane_atomic_update(struct drm_plane
*plane
,
500 struct drm_plane_state
*old_state
)
502 struct ipu_plane
*ipu_plane
= to_ipu_plane(plane
);
503 struct drm_plane_state
*state
= plane
->state
;
504 struct ipu_plane_state
*ipu_state
= to_ipu_plane_state(state
);
505 struct drm_crtc_state
*crtc_state
= state
->crtc
->state
;
506 struct drm_framebuffer
*fb
= state
->fb
;
507 struct drm_rect
*dst
= &state
->dst
;
508 unsigned long eba
, ubo
, vbo
;
509 unsigned long alpha_eba
= 0;
510 enum ipu_color_space ics
;
511 unsigned int axi_id
= 0;
514 if (ipu_plane
->dp_flow
== IPU_DP_FLOW_SYNC_FG
)
515 ipu_dp_set_window_pos(ipu_plane
->dp
, dst
->x1
, dst
->y1
);
517 eba
= drm_plane_state_to_eba(state
, 0);
520 * Configure PRG channel and attached PRE, this changes the EBA to an
521 * internal SRAM location.
523 if (ipu_state
->use_pre
) {
524 axi_id
= ipu_chan_assign_axi_id(ipu_plane
->dma
);
525 ipu_prg_channel_configure(ipu_plane
->ipu_ch
, axi_id
,
526 drm_rect_width(&state
->src
) >> 16,
527 drm_rect_height(&state
->src
) >> 16,
528 state
->fb
->pitches
[0],
529 state
->fb
->format
->format
, &eba
);
532 if (old_state
->fb
&& !drm_atomic_crtc_needs_modeset(crtc_state
)) {
533 /* nothing to do if PRE is used */
534 if (ipu_state
->use_pre
)
536 active
= ipu_idmac_get_current_buffer(ipu_plane
->ipu_ch
);
537 ipu_cpmem_set_buffer(ipu_plane
->ipu_ch
, !active
, eba
);
538 ipu_idmac_select_buffer(ipu_plane
->ipu_ch
, !active
);
539 if (ipu_plane_separate_alpha(ipu_plane
)) {
540 active
= ipu_idmac_get_current_buffer(ipu_plane
->alpha_ch
);
541 ipu_cpmem_set_buffer(ipu_plane
->alpha_ch
, !active
,
543 ipu_idmac_select_buffer(ipu_plane
->alpha_ch
, !active
);
548 switch (ipu_plane
->dp_flow
) {
549 case IPU_DP_FLOW_SYNC_BG
:
550 ipu_dp_setup_channel(ipu_plane
->dp
,
551 IPUV3_COLORSPACE_RGB
,
552 IPUV3_COLORSPACE_RGB
);
553 ipu_dp_set_global_alpha(ipu_plane
->dp
, true, 0, true);
555 case IPU_DP_FLOW_SYNC_FG
:
556 ics
= ipu_drm_fourcc_to_colorspace(state
->fb
->format
->format
);
557 ipu_dp_setup_channel(ipu_plane
->dp
, ics
,
558 IPUV3_COLORSPACE_UNKNOWN
);
559 /* Enable local alpha on partial plane */
560 switch (state
->fb
->format
->format
) {
561 case DRM_FORMAT_ARGB1555
:
562 case DRM_FORMAT_ABGR1555
:
563 case DRM_FORMAT_RGBA5551
:
564 case DRM_FORMAT_BGRA5551
:
565 case DRM_FORMAT_ARGB4444
:
566 case DRM_FORMAT_ARGB8888
:
567 case DRM_FORMAT_ABGR8888
:
568 case DRM_FORMAT_RGBA8888
:
569 case DRM_FORMAT_BGRA8888
:
570 case DRM_FORMAT_RGB565_A8
:
571 case DRM_FORMAT_BGR565_A8
:
572 case DRM_FORMAT_RGB888_A8
:
573 case DRM_FORMAT_BGR888_A8
:
574 case DRM_FORMAT_RGBX8888_A8
:
575 case DRM_FORMAT_BGRX8888_A8
:
576 ipu_dp_set_global_alpha(ipu_plane
->dp
, false, 0, false);
579 ipu_dp_set_global_alpha(ipu_plane
->dp
, true, 0, true);
584 ipu_dmfc_config_wait4eot(ipu_plane
->dmfc
, drm_rect_width(dst
));
586 ipu_cpmem_zero(ipu_plane
->ipu_ch
);
587 ipu_cpmem_set_resolution(ipu_plane
->ipu_ch
,
588 drm_rect_width(&state
->src
) >> 16,
589 drm_rect_height(&state
->src
) >> 16);
590 ipu_cpmem_set_fmt(ipu_plane
->ipu_ch
, state
->fb
->format
->format
);
591 ipu_cpmem_set_high_priority(ipu_plane
->ipu_ch
);
592 ipu_idmac_set_double_buffer(ipu_plane
->ipu_ch
, 1);
593 ipu_cpmem_set_stride(ipu_plane
->ipu_ch
, state
->fb
->pitches
[0]);
594 ipu_cpmem_set_axi_id(ipu_plane
->ipu_ch
, axi_id
);
595 switch (fb
->format
->format
) {
596 case DRM_FORMAT_YUV420
:
597 case DRM_FORMAT_YVU420
:
598 case DRM_FORMAT_YUV422
:
599 case DRM_FORMAT_YVU422
:
600 case DRM_FORMAT_YUV444
:
601 case DRM_FORMAT_YVU444
:
602 ubo
= drm_plane_state_to_ubo(state
);
603 vbo
= drm_plane_state_to_vbo(state
);
604 if (fb
->format
->format
== DRM_FORMAT_YVU420
||
605 fb
->format
->format
== DRM_FORMAT_YVU422
||
606 fb
->format
->format
== DRM_FORMAT_YVU444
)
609 ipu_cpmem_set_yuv_planar_full(ipu_plane
->ipu_ch
,
610 fb
->pitches
[1], ubo
, vbo
);
612 dev_dbg(ipu_plane
->base
.dev
->dev
,
613 "phy = %lu %lu %lu, x = %d, y = %d", eba
, ubo
, vbo
,
614 state
->src
.x1
>> 16, state
->src
.y1
>> 16);
616 case DRM_FORMAT_NV12
:
617 case DRM_FORMAT_NV16
:
618 ubo
= drm_plane_state_to_ubo(state
);
620 ipu_cpmem_set_yuv_planar_full(ipu_plane
->ipu_ch
,
621 fb
->pitches
[1], ubo
, ubo
);
623 dev_dbg(ipu_plane
->base
.dev
->dev
,
624 "phy = %lu %lu, x = %d, y = %d", eba
, ubo
,
625 state
->src
.x1
>> 16, state
->src
.y1
>> 16);
627 case DRM_FORMAT_RGB565_A8
:
628 case DRM_FORMAT_BGR565_A8
:
629 case DRM_FORMAT_RGB888_A8
:
630 case DRM_FORMAT_BGR888_A8
:
631 case DRM_FORMAT_RGBX8888_A8
:
632 case DRM_FORMAT_BGRX8888_A8
:
633 alpha_eba
= drm_plane_state_to_eba(state
, 1);
635 dev_dbg(ipu_plane
->base
.dev
->dev
, "phys = %lu %lu, x = %d, y = %d",
636 eba
, alpha_eba
, state
->src
.x1
>> 16, state
->src
.y1
>> 16);
638 ipu_cpmem_set_burstsize(ipu_plane
->ipu_ch
, 16);
640 ipu_cpmem_zero(ipu_plane
->alpha_ch
);
641 ipu_cpmem_set_resolution(ipu_plane
->alpha_ch
,
642 drm_rect_width(&state
->src
) >> 16,
643 drm_rect_height(&state
->src
) >> 16);
644 ipu_cpmem_set_format_passthrough(ipu_plane
->alpha_ch
, 8);
645 ipu_cpmem_set_high_priority(ipu_plane
->alpha_ch
);
646 ipu_idmac_set_double_buffer(ipu_plane
->alpha_ch
, 1);
647 ipu_cpmem_set_stride(ipu_plane
->alpha_ch
,
648 state
->fb
->pitches
[1]);
649 ipu_cpmem_set_burstsize(ipu_plane
->alpha_ch
, 16);
650 ipu_cpmem_set_buffer(ipu_plane
->alpha_ch
, 0, alpha_eba
);
651 ipu_cpmem_set_buffer(ipu_plane
->alpha_ch
, 1, alpha_eba
);
654 dev_dbg(ipu_plane
->base
.dev
->dev
, "phys = %lu, x = %d, y = %d",
655 eba
, state
->src
.x1
>> 16, state
->src
.y1
>> 16);
658 ipu_cpmem_set_buffer(ipu_plane
->ipu_ch
, 0, eba
);
659 ipu_cpmem_set_buffer(ipu_plane
->ipu_ch
, 1, eba
);
660 ipu_plane_enable(ipu_plane
);
663 static const struct drm_plane_helper_funcs ipu_plane_helper_funcs
= {
664 .prepare_fb
= drm_fb_cma_prepare_fb
,
665 .atomic_check
= ipu_plane_atomic_check
,
666 .atomic_disable
= ipu_plane_atomic_disable
,
667 .atomic_update
= ipu_plane_atomic_update
,
670 int ipu_planes_assign_pre(struct drm_device
*dev
,
671 struct drm_atomic_state
*state
)
673 struct drm_plane_state
*plane_state
;
674 struct drm_plane
*plane
;
675 int available_pres
= ipu_prg_max_active_channels();
678 for_each_plane_in_state(state
, plane
, plane_state
, i
) {
679 struct ipu_plane_state
*ipu_state
=
680 to_ipu_plane_state(plane_state
);
681 struct ipu_plane
*ipu_plane
= to_ipu_plane(plane
);
683 if (ipu_prg_present(ipu_plane
->ipu
) && available_pres
&&
685 ipu_prg_format_supported(ipu_plane
->ipu
,
686 plane_state
->fb
->format
->format
,
687 plane_state
->fb
->modifier
)) {
688 ipu_state
->use_pre
= true;
691 ipu_state
->use_pre
= false;
697 EXPORT_SYMBOL_GPL(ipu_planes_assign_pre
);
699 struct ipu_plane
*ipu_plane_init(struct drm_device
*dev
, struct ipu_soc
*ipu
,
700 int dma
, int dp
, unsigned int possible_crtcs
,
701 enum drm_plane_type type
)
703 struct ipu_plane
*ipu_plane
;
706 DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n",
707 dma
, dp
, possible_crtcs
);
709 ipu_plane
= kzalloc(sizeof(*ipu_plane
), GFP_KERNEL
);
711 DRM_ERROR("failed to allocate plane\n");
712 return ERR_PTR(-ENOMEM
);
715 ipu_plane
->ipu
= ipu
;
716 ipu_plane
->dma
= dma
;
717 ipu_plane
->dp_flow
= dp
;
719 ret
= drm_universal_plane_init(dev
, &ipu_plane
->base
, possible_crtcs
,
720 &ipu_plane_funcs
, ipu_plane_formats
,
721 ARRAY_SIZE(ipu_plane_formats
), type
,
724 DRM_ERROR("failed to initialize plane\n");
729 drm_plane_helper_add(&ipu_plane
->base
, &ipu_plane_helper_funcs
);