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_reset(struct drm_plane
*plane
)
35 struct mtk_plane_state
*state
;
38 __drm_atomic_helper_plane_destroy_state(plane
->state
);
40 state
= to_mtk_plane_state(plane
->state
);
41 memset(state
, 0, sizeof(*state
));
43 state
= kzalloc(sizeof(*state
), GFP_KERNEL
);
46 plane
->state
= &state
->base
;
49 state
->base
.plane
= plane
;
50 state
->pending
.format
= DRM_FORMAT_RGB565
;
53 static struct drm_plane_state
*mtk_plane_duplicate_state(struct drm_plane
*plane
)
55 struct mtk_plane_state
*old_state
= to_mtk_plane_state(plane
->state
);
56 struct mtk_plane_state
*state
;
58 state
= kzalloc(sizeof(*state
), GFP_KERNEL
);
62 __drm_atomic_helper_plane_duplicate_state(plane
, &state
->base
);
64 WARN_ON(state
->base
.plane
!= plane
);
66 state
->pending
= old_state
->pending
;
71 static void mtk_drm_plane_destroy_state(struct drm_plane
*plane
,
72 struct drm_plane_state
*state
)
74 __drm_atomic_helper_plane_destroy_state(state
);
75 kfree(to_mtk_plane_state(state
));
78 static const struct drm_plane_funcs mtk_plane_funcs
= {
79 .update_plane
= drm_atomic_helper_update_plane
,
80 .disable_plane
= drm_atomic_helper_disable_plane
,
81 .destroy
= drm_plane_cleanup
,
82 .reset
= mtk_plane_reset
,
83 .atomic_duplicate_state
= mtk_plane_duplicate_state
,
84 .atomic_destroy_state
= mtk_drm_plane_destroy_state
,
87 static int mtk_plane_atomic_check(struct drm_plane
*plane
,
88 struct drm_plane_state
*state
)
90 struct drm_framebuffer
*fb
= state
->fb
;
91 struct drm_crtc_state
*crtc_state
;
92 struct drm_rect clip
= { 0, };
97 if (!mtk_fb_get_gem_obj(fb
)) {
98 DRM_DEBUG_KMS("buffer is null\n");
105 crtc_state
= drm_atomic_get_crtc_state(state
->state
, state
->crtc
);
106 if (IS_ERR(crtc_state
))
107 return PTR_ERR(crtc_state
);
109 clip
.x2
= crtc_state
->mode
.hdisplay
;
110 clip
.y2
= crtc_state
->mode
.vdisplay
;
112 return drm_plane_helper_check_state(state
, &clip
,
113 DRM_PLANE_HELPER_NO_SCALING
,
114 DRM_PLANE_HELPER_NO_SCALING
,
118 static void mtk_plane_atomic_update(struct drm_plane
*plane
,
119 struct drm_plane_state
*old_state
)
121 struct mtk_plane_state
*state
= to_mtk_plane_state(plane
->state
);
122 struct drm_crtc
*crtc
= plane
->state
->crtc
;
123 struct drm_framebuffer
*fb
= plane
->state
->fb
;
124 struct drm_gem_object
*gem
;
125 struct mtk_drm_gem_obj
*mtk_gem
;
126 unsigned int pitch
, format
;
129 if (!crtc
|| WARN_ON(!fb
))
132 gem
= mtk_fb_get_gem_obj(fb
);
133 mtk_gem
= to_mtk_gem_obj(gem
);
134 addr
= mtk_gem
->dma_addr
;
135 pitch
= fb
->pitches
[0];
136 format
= fb
->pixel_format
;
138 addr
+= (plane
->state
->src
.x1
>> 16) * drm_format_plane_cpp(format
, 0);
139 addr
+= (plane
->state
->src
.y1
>> 16) * pitch
;
141 state
->pending
.enable
= true;
142 state
->pending
.pitch
= pitch
;
143 state
->pending
.format
= format
;
144 state
->pending
.addr
= addr
;
145 state
->pending
.x
= plane
->state
->dst
.x1
;
146 state
->pending
.y
= plane
->state
->dst
.y1
;
147 state
->pending
.width
= drm_rect_width(&plane
->state
->dst
);
148 state
->pending
.height
= drm_rect_height(&plane
->state
->dst
);
149 wmb(); /* Make sure the above parameters are set before update */
150 state
->pending
.dirty
= true;
153 static void mtk_plane_atomic_disable(struct drm_plane
*plane
,
154 struct drm_plane_state
*old_state
)
156 struct mtk_plane_state
*state
= to_mtk_plane_state(plane
->state
);
158 state
->pending
.enable
= false;
159 wmb(); /* Make sure the above parameter is set before update */
160 state
->pending
.dirty
= true;
163 static const struct drm_plane_helper_funcs mtk_plane_helper_funcs
= {
164 .atomic_check
= mtk_plane_atomic_check
,
165 .atomic_update
= mtk_plane_atomic_update
,
166 .atomic_disable
= mtk_plane_atomic_disable
,
169 int mtk_plane_init(struct drm_device
*dev
, struct drm_plane
*plane
,
170 unsigned long possible_crtcs
, enum drm_plane_type type
)
174 err
= drm_universal_plane_init(dev
, plane
, possible_crtcs
,
175 &mtk_plane_funcs
, formats
,
176 ARRAY_SIZE(formats
), type
, NULL
);
178 DRM_ERROR("failed to initialize plane\n");
182 drm_plane_helper_add(plane
, &mtk_plane_helper_funcs
);