1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2015 MediaTek Inc.
4 * Author: CK Hu <ck.hu@mediatek.com>
7 #include <drm/drm_atomic.h>
8 #include <drm/drm_atomic_helper.h>
9 #include <drm/drm_fourcc.h>
10 #include <drm/drm_atomic_uapi.h>
11 #include <drm/drm_plane_helper.h>
12 #include <drm/drm_gem_framebuffer_helper.h>
14 #include "mtk_drm_crtc.h"
15 #include "mtk_drm_ddp_comp.h"
16 #include "mtk_drm_drv.h"
17 #include "mtk_drm_gem.h"
18 #include "mtk_drm_plane.h"
20 static const u32 formats
[] = {
34 static void mtk_plane_reset(struct drm_plane
*plane
)
36 struct mtk_plane_state
*state
;
39 __drm_atomic_helper_plane_destroy_state(plane
->state
);
41 state
= to_mtk_plane_state(plane
->state
);
42 memset(state
, 0, sizeof(*state
));
44 state
= kzalloc(sizeof(*state
), GFP_KERNEL
);
47 plane
->state
= &state
->base
;
50 state
->base
.plane
= plane
;
51 state
->pending
.format
= DRM_FORMAT_RGB565
;
54 static struct drm_plane_state
*mtk_plane_duplicate_state(struct drm_plane
*plane
)
56 struct mtk_plane_state
*old_state
= to_mtk_plane_state(plane
->state
);
57 struct mtk_plane_state
*state
;
59 state
= kzalloc(sizeof(*state
), GFP_KERNEL
);
63 __drm_atomic_helper_plane_duplicate_state(plane
, &state
->base
);
65 WARN_ON(state
->base
.plane
!= plane
);
67 state
->pending
= old_state
->pending
;
72 static void mtk_drm_plane_destroy_state(struct drm_plane
*plane
,
73 struct drm_plane_state
*state
)
75 __drm_atomic_helper_plane_destroy_state(state
);
76 kfree(to_mtk_plane_state(state
));
79 static int mtk_plane_atomic_async_check(struct drm_plane
*plane
,
80 struct drm_plane_state
*state
)
82 struct drm_crtc_state
*crtc_state
;
84 if (plane
!= state
->crtc
->cursor
)
90 if (!plane
->state
->fb
)
94 crtc_state
= drm_atomic_get_existing_crtc_state(state
->state
,
96 else /* Special case for asynchronous cursor updates. */
97 crtc_state
= state
->crtc
->state
;
99 return drm_atomic_helper_check_plane_state(plane
->state
, crtc_state
,
100 DRM_PLANE_HELPER_NO_SCALING
,
101 DRM_PLANE_HELPER_NO_SCALING
,
105 static void mtk_plane_atomic_async_update(struct drm_plane
*plane
,
106 struct drm_plane_state
*new_state
)
108 struct mtk_plane_state
*state
= to_mtk_plane_state(plane
->state
);
110 plane
->state
->crtc_x
= new_state
->crtc_x
;
111 plane
->state
->crtc_y
= new_state
->crtc_y
;
112 plane
->state
->crtc_h
= new_state
->crtc_h
;
113 plane
->state
->crtc_w
= new_state
->crtc_w
;
114 plane
->state
->src_x
= new_state
->src_x
;
115 plane
->state
->src_y
= new_state
->src_y
;
116 plane
->state
->src_h
= new_state
->src_h
;
117 plane
->state
->src_w
= new_state
->src_w
;
118 state
->pending
.async_dirty
= true;
120 mtk_drm_crtc_async_update(new_state
->crtc
, plane
, new_state
);
123 static const struct drm_plane_funcs mtk_plane_funcs
= {
124 .update_plane
= drm_atomic_helper_update_plane
,
125 .disable_plane
= drm_atomic_helper_disable_plane
,
126 .destroy
= drm_plane_cleanup
,
127 .reset
= mtk_plane_reset
,
128 .atomic_duplicate_state
= mtk_plane_duplicate_state
,
129 .atomic_destroy_state
= mtk_drm_plane_destroy_state
,
132 static int mtk_plane_atomic_check(struct drm_plane
*plane
,
133 struct drm_plane_state
*state
)
135 struct drm_framebuffer
*fb
= state
->fb
;
136 struct drm_crtc_state
*crtc_state
;
142 if (WARN_ON(!state
->crtc
))
145 ret
= mtk_drm_crtc_plane_check(state
->crtc
, plane
,
146 to_mtk_plane_state(state
));
150 crtc_state
= drm_atomic_get_crtc_state(state
->state
, state
->crtc
);
151 if (IS_ERR(crtc_state
))
152 return PTR_ERR(crtc_state
);
154 return drm_atomic_helper_check_plane_state(state
, crtc_state
,
155 DRM_PLANE_HELPER_NO_SCALING
,
156 DRM_PLANE_HELPER_NO_SCALING
,
160 static void mtk_plane_atomic_update(struct drm_plane
*plane
,
161 struct drm_plane_state
*old_state
)
163 struct mtk_plane_state
*state
= to_mtk_plane_state(plane
->state
);
164 struct drm_crtc
*crtc
= plane
->state
->crtc
;
165 struct drm_framebuffer
*fb
= plane
->state
->fb
;
166 struct drm_gem_object
*gem
;
167 struct mtk_drm_gem_obj
*mtk_gem
;
168 unsigned int pitch
, format
;
171 if (!crtc
|| WARN_ON(!fb
))
175 mtk_gem
= to_mtk_gem_obj(gem
);
176 addr
= mtk_gem
->dma_addr
;
177 pitch
= fb
->pitches
[0];
178 format
= fb
->format
->format
;
180 addr
+= (plane
->state
->src
.x1
>> 16) * fb
->format
->cpp
[0];
181 addr
+= (plane
->state
->src
.y1
>> 16) * pitch
;
183 state
->pending
.enable
= true;
184 state
->pending
.pitch
= pitch
;
185 state
->pending
.format
= format
;
186 state
->pending
.addr
= addr
;
187 state
->pending
.x
= plane
->state
->dst
.x1
;
188 state
->pending
.y
= plane
->state
->dst
.y1
;
189 state
->pending
.width
= drm_rect_width(&plane
->state
->dst
);
190 state
->pending
.height
= drm_rect_height(&plane
->state
->dst
);
191 state
->pending
.rotation
= plane
->state
->rotation
;
192 wmb(); /* Make sure the above parameters are set before update */
193 state
->pending
.dirty
= true;
196 static void mtk_plane_atomic_disable(struct drm_plane
*plane
,
197 struct drm_plane_state
*old_state
)
199 struct mtk_plane_state
*state
= to_mtk_plane_state(plane
->state
);
201 state
->pending
.enable
= false;
202 wmb(); /* Make sure the above parameter is set before update */
203 state
->pending
.dirty
= true;
206 static const struct drm_plane_helper_funcs mtk_plane_helper_funcs
= {
207 .prepare_fb
= drm_gem_fb_prepare_fb
,
208 .atomic_check
= mtk_plane_atomic_check
,
209 .atomic_update
= mtk_plane_atomic_update
,
210 .atomic_disable
= mtk_plane_atomic_disable
,
211 .atomic_async_update
= mtk_plane_atomic_async_update
,
212 .atomic_async_check
= mtk_plane_atomic_async_check
,
215 int mtk_plane_init(struct drm_device
*dev
, struct drm_plane
*plane
,
216 unsigned long possible_crtcs
, enum drm_plane_type type
,
217 unsigned int supported_rotations
)
221 err
= drm_universal_plane_init(dev
, plane
, possible_crtcs
,
222 &mtk_plane_funcs
, formats
,
223 ARRAY_SIZE(formats
), NULL
, type
, NULL
);
225 DRM_ERROR("failed to initialize plane\n");
229 if (supported_rotations
& ~DRM_MODE_ROTATE_0
) {
230 err
= drm_plane_create_rotation_property(plane
,
232 supported_rotations
);
234 DRM_INFO("Create rotation property failed\n");
237 drm_plane_helper_add(plane
, &mtk_plane_helper_funcs
);