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
[] = {
35 static void mtk_plane_reset(struct drm_plane
*plane
)
37 struct mtk_plane_state
*state
;
40 __drm_atomic_helper_plane_destroy_state(plane
->state
);
42 state
= to_mtk_plane_state(plane
->state
);
43 memset(state
, 0, sizeof(*state
));
45 state
= kzalloc(sizeof(*state
), GFP_KERNEL
);
48 plane
->state
= &state
->base
;
51 state
->base
.plane
= plane
;
52 state
->pending
.format
= DRM_FORMAT_RGB565
;
55 static struct drm_plane_state
*mtk_plane_duplicate_state(struct drm_plane
*plane
)
57 struct mtk_plane_state
*old_state
= to_mtk_plane_state(plane
->state
);
58 struct mtk_plane_state
*state
;
60 state
= kzalloc(sizeof(*state
), GFP_KERNEL
);
64 __drm_atomic_helper_plane_duplicate_state(plane
, &state
->base
);
66 WARN_ON(state
->base
.plane
!= plane
);
68 state
->pending
= old_state
->pending
;
73 static void mtk_drm_plane_destroy_state(struct drm_plane
*plane
,
74 struct drm_plane_state
*state
)
76 __drm_atomic_helper_plane_destroy_state(state
);
77 kfree(to_mtk_plane_state(state
));
80 static const struct drm_plane_funcs mtk_plane_funcs
= {
81 .update_plane
= drm_atomic_helper_update_plane
,
82 .disable_plane
= drm_atomic_helper_disable_plane
,
83 .destroy
= drm_plane_cleanup
,
84 .reset
= mtk_plane_reset
,
85 .atomic_duplicate_state
= mtk_plane_duplicate_state
,
86 .atomic_destroy_state
= mtk_drm_plane_destroy_state
,
89 static int mtk_plane_atomic_check(struct drm_plane
*plane
,
90 struct drm_plane_state
*state
)
92 struct drm_framebuffer
*fb
= state
->fb
;
93 struct drm_crtc_state
*crtc_state
;
94 struct drm_rect clip
= { 0, };
99 if (!mtk_fb_get_gem_obj(fb
)) {
100 DRM_DEBUG_KMS("buffer is null\n");
107 crtc_state
= drm_atomic_get_crtc_state(state
->state
, state
->crtc
);
108 if (IS_ERR(crtc_state
))
109 return PTR_ERR(crtc_state
);
111 clip
.x2
= crtc_state
->mode
.hdisplay
;
112 clip
.y2
= crtc_state
->mode
.vdisplay
;
114 return drm_plane_helper_check_state(state
, &clip
,
115 DRM_PLANE_HELPER_NO_SCALING
,
116 DRM_PLANE_HELPER_NO_SCALING
,
120 static void mtk_plane_atomic_update(struct drm_plane
*plane
,
121 struct drm_plane_state
*old_state
)
123 struct mtk_plane_state
*state
= to_mtk_plane_state(plane
->state
);
124 struct drm_crtc
*crtc
= plane
->state
->crtc
;
125 struct drm_framebuffer
*fb
= plane
->state
->fb
;
126 struct drm_gem_object
*gem
;
127 struct mtk_drm_gem_obj
*mtk_gem
;
128 unsigned int pitch
, format
;
131 if (!crtc
|| WARN_ON(!fb
))
134 gem
= mtk_fb_get_gem_obj(fb
);
135 mtk_gem
= to_mtk_gem_obj(gem
);
136 addr
= mtk_gem
->dma_addr
;
137 pitch
= fb
->pitches
[0];
138 format
= fb
->format
->format
;
140 addr
+= (plane
->state
->src
.x1
>> 16) * fb
->format
->cpp
[0];
141 addr
+= (plane
->state
->src
.y1
>> 16) * pitch
;
143 state
->pending
.enable
= true;
144 state
->pending
.pitch
= pitch
;
145 state
->pending
.format
= format
;
146 state
->pending
.addr
= addr
;
147 state
->pending
.x
= plane
->state
->dst
.x1
;
148 state
->pending
.y
= plane
->state
->dst
.y1
;
149 state
->pending
.width
= drm_rect_width(&plane
->state
->dst
);
150 state
->pending
.height
= drm_rect_height(&plane
->state
->dst
);
151 wmb(); /* Make sure the above parameters are set before update */
152 state
->pending
.dirty
= true;
155 static void mtk_plane_atomic_disable(struct drm_plane
*plane
,
156 struct drm_plane_state
*old_state
)
158 struct mtk_plane_state
*state
= to_mtk_plane_state(plane
->state
);
160 state
->pending
.enable
= false;
161 wmb(); /* Make sure the above parameter is set before update */
162 state
->pending
.dirty
= true;
165 static const struct drm_plane_helper_funcs mtk_plane_helper_funcs
= {
166 .atomic_check
= mtk_plane_atomic_check
,
167 .atomic_update
= mtk_plane_atomic_update
,
168 .atomic_disable
= mtk_plane_atomic_disable
,
171 int mtk_plane_init(struct drm_device
*dev
, struct drm_plane
*plane
,
172 unsigned long possible_crtcs
, enum drm_plane_type type
)
176 err
= drm_universal_plane_init(dev
, plane
, possible_crtcs
,
177 &mtk_plane_funcs
, formats
,
178 ARRAY_SIZE(formats
), type
, NULL
);
180 DRM_ERROR("failed to initialize plane\n");
184 drm_plane_helper_add(plane
, &mtk_plane_helper_funcs
);