2 * Copyright (C) STMicroelectronics SA 2014
3 * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
4 * Fabien Dessenne <fabien.dessenne@st.com>
5 * for STMicroelectronics.
6 * License terms: GNU General Public License (GPL), version 2
10 #include <drm/drm_atomic_helper.h>
11 #include <drm/drm_plane_helper.h>
13 #include "sti_compositor.h"
14 #include "sti_drm_drv.h"
15 #include "sti_drm_plane.h"
18 enum sti_layer_desc sti_layer_default_zorder
[] = {
27 /* (Background) < GDP0 < VID0 < GDP1 < VID1 < GDP2 < GDP3 < (ForeGround) */
30 sti_drm_update_plane(struct drm_plane
*plane
, struct drm_crtc
*crtc
,
31 struct drm_framebuffer
*fb
, int crtc_x
, int crtc_y
,
32 unsigned int crtc_w
, unsigned int crtc_h
,
33 uint32_t src_x
, uint32_t src_y
,
34 uint32_t src_w
, uint32_t src_h
)
36 struct sti_layer
*layer
= to_sti_layer(plane
);
37 struct sti_mixer
*mixer
= to_sti_mixer(crtc
);
40 DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
41 crtc
->base
.id
, sti_mixer_to_str(mixer
),
42 plane
->base
.id
, sti_layer_to_str(layer
));
43 DRM_DEBUG_KMS("(%dx%d)@(%d,%d)\n", crtc_w
, crtc_h
, crtc_x
, crtc_y
);
45 res
= sti_mixer_set_layer_depth(mixer
, layer
);
47 DRM_ERROR("Can not set layer depth\n");
51 /* src_x are in 16.16 format. */
52 res
= sti_layer_prepare(layer
, crtc
, fb
,
53 &crtc
->mode
, mixer
->id
,
54 crtc_x
, crtc_y
, crtc_w
, crtc_h
,
55 src_x
>> 16, src_y
>> 16,
56 src_w
>> 16, src_h
>> 16);
58 DRM_ERROR("Layer prepare failed\n");
62 res
= sti_layer_commit(layer
);
64 DRM_ERROR("Layer commit failed\n");
68 res
= sti_mixer_set_layer_status(mixer
, layer
, true);
70 DRM_ERROR("Can not enable layer at mixer\n");
77 static int sti_drm_disable_plane(struct drm_plane
*plane
)
79 struct sti_layer
*layer
;
80 struct sti_mixer
*mixer
;
84 DRM_DEBUG_DRIVER("drm plane:%d not enabled\n", plane
->base
.id
);
87 layer
= to_sti_layer(plane
);
88 mixer
= to_sti_mixer(plane
->crtc
);
90 DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n",
91 plane
->crtc
->base
.id
, sti_mixer_to_str(mixer
),
92 plane
->base
.id
, sti_layer_to_str(layer
));
94 /* Disable layer at mixer level */
95 mix_res
= sti_mixer_set_layer_status(mixer
, layer
, false);
97 DRM_ERROR("Can not disable layer at mixer\n");
99 /* Wait a while to be sure that a Vsync event is received */
100 msleep(WAIT_NEXT_VSYNC_MS
);
102 /* Then disable layer itself */
103 lay_res
= sti_layer_disable(layer
);
105 DRM_ERROR("Layer disable failed\n");
107 if (lay_res
|| mix_res
)
113 static void sti_drm_plane_destroy(struct drm_plane
*plane
)
115 DRM_DEBUG_DRIVER("\n");
117 drm_plane_helper_disable(plane
);
118 drm_plane_cleanup(plane
);
121 static int sti_drm_plane_set_property(struct drm_plane
*plane
,
122 struct drm_property
*property
,
125 struct drm_device
*dev
= plane
->dev
;
126 struct sti_drm_private
*private = dev
->dev_private
;
127 struct sti_layer
*layer
= to_sti_layer(plane
);
129 DRM_DEBUG_DRIVER("\n");
131 if (property
== private->plane_zorder_property
) {
139 static struct drm_plane_funcs sti_drm_plane_funcs
= {
140 .update_plane
= drm_atomic_helper_update_plane
,
141 .disable_plane
= drm_atomic_helper_disable_plane
,
142 .destroy
= sti_drm_plane_destroy
,
143 .set_property
= sti_drm_plane_set_property
,
144 .reset
= drm_atomic_helper_plane_reset
,
145 .atomic_duplicate_state
= drm_atomic_helper_plane_duplicate_state
,
146 .atomic_destroy_state
= drm_atomic_helper_plane_destroy_state
,
149 static int sti_drm_plane_prepare_fb(struct drm_plane
*plane
,
150 struct drm_framebuffer
*fb
,
151 const struct drm_plane_state
*new_state
)
156 static void sti_drm_plane_cleanup_fb(struct drm_plane
*plane
,
157 struct drm_framebuffer
*fb
,
158 const struct drm_plane_state
*old_fb
)
162 static int sti_drm_plane_atomic_check(struct drm_plane
*plane
,
163 struct drm_plane_state
*state
)
168 static void sti_drm_plane_atomic_update(struct drm_plane
*plane
,
169 struct drm_plane_state
*oldstate
)
171 struct drm_plane_state
*state
= plane
->state
;
173 sti_drm_update_plane(plane
, state
->crtc
, state
->fb
,
174 state
->crtc_x
, state
->crtc_y
,
175 state
->crtc_w
, state
->crtc_h
,
176 state
->src_x
, state
->src_y
,
177 state
->src_w
, state
->src_h
);
180 static void sti_drm_plane_atomic_disable(struct drm_plane
*plane
,
181 struct drm_plane_state
*oldstate
)
183 sti_drm_disable_plane(plane
);
186 static const struct drm_plane_helper_funcs sti_drm_plane_helpers_funcs
= {
187 .prepare_fb
= sti_drm_plane_prepare_fb
,
188 .cleanup_fb
= sti_drm_plane_cleanup_fb
,
189 .atomic_check
= sti_drm_plane_atomic_check
,
190 .atomic_update
= sti_drm_plane_atomic_update
,
191 .atomic_disable
= sti_drm_plane_atomic_disable
,
194 static void sti_drm_plane_attach_zorder_property(struct drm_plane
*plane
,
195 uint64_t default_val
)
197 struct drm_device
*dev
= plane
->dev
;
198 struct sti_drm_private
*private = dev
->dev_private
;
199 struct drm_property
*prop
;
200 struct sti_layer
*layer
= to_sti_layer(plane
);
202 prop
= private->plane_zorder_property
;
204 prop
= drm_property_create_range(dev
, 0, "zpos", 0,
205 GAM_MIXER_NB_DEPTH_LEVEL
- 1);
209 private->plane_zorder_property
= prop
;
212 drm_object_attach_property(&plane
->base
, prop
, default_val
);
213 layer
->zorder
= default_val
;
216 struct drm_plane
*sti_drm_plane_init(struct drm_device
*dev
,
217 struct sti_layer
*layer
,
218 unsigned int possible_crtcs
,
219 enum drm_plane_type type
)
222 uint64_t default_zorder
= 0;
224 err
= drm_universal_plane_init(dev
, &layer
->plane
, possible_crtcs
,
225 &sti_drm_plane_funcs
,
226 sti_layer_get_formats(layer
),
227 sti_layer_get_nb_formats(layer
), type
);
229 DRM_ERROR("Failed to initialize plane\n");
233 drm_plane_helper_add(&layer
->plane
, &sti_drm_plane_helpers_funcs
);
235 for (i
= 0; i
< ARRAY_SIZE(sti_layer_default_zorder
); i
++)
236 if (sti_layer_default_zorder
[i
] == layer
->desc
)
239 default_zorder
= i
+ 1;
241 if (type
== DRM_PLANE_TYPE_OVERLAY
)
242 sti_drm_plane_attach_zorder_property(&layer
->plane
,
245 DRM_DEBUG_DRIVER("drm plane:%d mapped to %s with zorder:%llu\n",
246 layer
->plane
.base
.id
,
247 sti_layer_to_str(layer
), default_zorder
);
249 return &layer
->plane
;
251 EXPORT_SYMBOL(sti_drm_plane_init
);