2 * Copyright (c) 2015 MediaTek Inc.
3 * Author: CK Hu <ck.hu@mediatek.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
16 #include <drm/drm_atomic.h>
17 #include <drm/drm_atomic_helper.h>
18 #include <drm/drm_plane_helper.h>
20 #include "mtk_drm_crtc.h"
21 #include "mtk_drm_ddp_comp.h"
22 #include "mtk_drm_drv.h"
23 #include "mtk_drm_fb.h"
24 #include "mtk_drm_gem.h"
25 #include "mtk_drm_plane.h"
27 static const u32 formats
[] = {
33 static void mtk_plane_enable(struct drm_plane
*plane
,
36 struct mtk_plane_state
*state
= to_mtk_plane_state(plane
->state
);
37 unsigned int pitch
, format
;
40 if (WARN_ON(!plane
->state
))
43 enable
= state
->base
.visible
;
45 if (WARN_ON(enable
&& !plane
->state
->fb
))
48 if (plane
->state
->fb
) {
49 pitch
= plane
->state
->fb
->pitches
[0];
50 format
= plane
->state
->fb
->pixel_format
;
53 format
= DRM_FORMAT_RGBA8888
;
56 addr
+= (state
->base
.src
.x1
>> 16) * 4;
57 addr
+= (state
->base
.src
.y1
>> 16) * pitch
;
59 state
->pending
.enable
= enable
;
60 state
->pending
.pitch
= pitch
;
61 state
->pending
.format
= format
;
62 state
->pending
.addr
= addr
;
63 state
->pending
.x
= state
->base
.dst
.x1
;
64 state
->pending
.y
= state
->base
.dst
.y1
;
65 state
->pending
.width
= drm_rect_width(&state
->base
.dst
);
66 state
->pending
.height
= drm_rect_height(&state
->base
.dst
);
67 wmb(); /* Make sure the above parameters are set before update */
68 state
->pending
.dirty
= true;
71 static void mtk_plane_reset(struct drm_plane
*plane
)
73 struct mtk_plane_state
*state
;
77 drm_framebuffer_unreference(plane
->state
->fb
);
79 state
= to_mtk_plane_state(plane
->state
);
80 memset(state
, 0, sizeof(*state
));
82 state
= kzalloc(sizeof(*state
), GFP_KERNEL
);
85 plane
->state
= &state
->base
;
88 state
->base
.plane
= plane
;
89 state
->pending
.format
= DRM_FORMAT_RGB565
;
92 static struct drm_plane_state
*mtk_plane_duplicate_state(struct drm_plane
*plane
)
94 struct mtk_plane_state
*old_state
= to_mtk_plane_state(plane
->state
);
95 struct mtk_plane_state
*state
;
97 state
= kzalloc(sizeof(*state
), GFP_KERNEL
);
101 __drm_atomic_helper_plane_duplicate_state(plane
, &state
->base
);
103 WARN_ON(state
->base
.plane
!= plane
);
105 state
->pending
= old_state
->pending
;
110 static void mtk_drm_plane_destroy_state(struct drm_plane
*plane
,
111 struct drm_plane_state
*state
)
113 __drm_atomic_helper_plane_destroy_state(state
);
114 kfree(to_mtk_plane_state(state
));
117 static const struct drm_plane_funcs mtk_plane_funcs
= {
118 .update_plane
= drm_atomic_helper_update_plane
,
119 .disable_plane
= drm_atomic_helper_disable_plane
,
120 .destroy
= drm_plane_cleanup
,
121 .reset
= mtk_plane_reset
,
122 .atomic_duplicate_state
= mtk_plane_duplicate_state
,
123 .atomic_destroy_state
= mtk_drm_plane_destroy_state
,
126 static int mtk_plane_atomic_check(struct drm_plane
*plane
,
127 struct drm_plane_state
*state
)
129 struct drm_framebuffer
*fb
= state
->fb
;
130 struct drm_crtc_state
*crtc_state
;
131 struct drm_rect clip
= { 0, };
136 if (!mtk_fb_get_gem_obj(fb
)) {
137 DRM_DEBUG_KMS("buffer is null\n");
144 crtc_state
= drm_atomic_get_crtc_state(state
->state
, state
->crtc
);
145 if (IS_ERR(crtc_state
))
146 return PTR_ERR(crtc_state
);
148 clip
.x2
= crtc_state
->mode
.hdisplay
;
149 clip
.y2
= crtc_state
->mode
.vdisplay
;
151 return drm_plane_helper_check_state(state
, &clip
,
152 DRM_PLANE_HELPER_NO_SCALING
,
153 DRM_PLANE_HELPER_NO_SCALING
,
157 static void mtk_plane_atomic_update(struct drm_plane
*plane
,
158 struct drm_plane_state
*old_state
)
160 struct mtk_plane_state
*state
= to_mtk_plane_state(plane
->state
);
161 struct drm_crtc
*crtc
= state
->base
.crtc
;
162 struct drm_gem_object
*gem
;
163 struct mtk_drm_gem_obj
*mtk_gem
;
168 gem
= mtk_fb_get_gem_obj(state
->base
.fb
);
169 mtk_gem
= to_mtk_gem_obj(gem
);
170 mtk_plane_enable(plane
, mtk_gem
->dma_addr
);
173 static void mtk_plane_atomic_disable(struct drm_plane
*plane
,
174 struct drm_plane_state
*old_state
)
176 struct mtk_plane_state
*state
= to_mtk_plane_state(plane
->state
);
178 state
->pending
.enable
= false;
179 wmb(); /* Make sure the above parameter is set before update */
180 state
->pending
.dirty
= true;
183 static const struct drm_plane_helper_funcs mtk_plane_helper_funcs
= {
184 .atomic_check
= mtk_plane_atomic_check
,
185 .atomic_update
= mtk_plane_atomic_update
,
186 .atomic_disable
= mtk_plane_atomic_disable
,
189 int mtk_plane_init(struct drm_device
*dev
, struct drm_plane
*plane
,
190 unsigned long possible_crtcs
, enum drm_plane_type type
)
194 err
= drm_universal_plane_init(dev
, plane
, possible_crtcs
,
195 &mtk_plane_funcs
, formats
,
196 ARRAY_SIZE(formats
), type
, NULL
);
198 DRM_ERROR("failed to initialize plane\n");
202 drm_plane_helper_add(plane
, &mtk_plane_helper_funcs
);