drm/sti: code clean up
[deliverable/linux.git] / drivers / gpu / drm / sti / sti_drm_plane.c
CommitLineData
9bbf86fe
BG
1/*
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
7 */
8
de4b00b0
BG
9#include <drm/drmP.h>
10#include <drm/drm_atomic_helper.h>
871bcdfe
VA
11#include <drm/drm_gem_cma_helper.h>
12#include <drm/drm_fb_cma_helper.h>
de4b00b0
BG
13#include <drm/drm_plane_helper.h>
14
9bbf86fe
BG
15#include "sti_compositor.h"
16#include "sti_drm_drv.h"
17#include "sti_drm_plane.h"
18#include "sti_vtg.h"
19
871bcdfe
VA
20/* (Background) < GDP0 < GDP1 < HQVDP0 < GDP2 < GDP3 < (ForeGround) */
21enum sti_plane_desc sti_plane_default_zorder[] = {
9bbf86fe 22 STI_GDP_0,
9bbf86fe 23 STI_GDP_1,
871bcdfe 24 STI_HQVDP_0,
9bbf86fe
BG
25 STI_GDP_2,
26 STI_GDP_3,
27};
28
871bcdfe 29const char *sti_plane_to_str(struct sti_plane *plane)
9bbf86fe 30{
871bcdfe
VA
31 switch (plane->desc) {
32 case STI_GDP_0:
33 return "GDP0";
34 case STI_GDP_1:
35 return "GDP1";
36 case STI_GDP_2:
37 return "GDP2";
38 case STI_GDP_3:
39 return "GDP3";
40 case STI_HQVDP_0:
41 return "HQVDP0";
42 case STI_CURSOR:
43 return "CURSOR";
44 default:
45 return "<UNKNOWN PLANE>";
46 }
47}
48EXPORT_SYMBOL(sti_plane_to_str);
49
50static int sti_plane_prepare(struct sti_plane *plane,
51 struct drm_crtc *crtc,
52 struct drm_framebuffer *fb,
53 struct drm_display_mode *mode, int mixer_id,
54 int dest_x, int dest_y, int dest_w, int dest_h,
55 int src_x, int src_y, int src_w, int src_h)
56{
57 struct drm_gem_cma_object *cma_obj;
58 unsigned int i;
9bbf86fe
BG
59 int res;
60
871bcdfe
VA
61 if (!plane || !fb || !mode) {
62 DRM_ERROR("Null fb, plane or mode\n");
63 return 1;
64 }
9bbf86fe 65
871bcdfe
VA
66 cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
67 if (!cma_obj) {
68 DRM_ERROR("Can't get CMA GEM object for fb\n");
69 return 1;
9bbf86fe
BG
70 }
71
871bcdfe
VA
72 plane->fb = fb;
73 plane->mode = mode;
74 plane->mixer_id = mixer_id;
75 plane->dst_x = dest_x;
76 plane->dst_y = dest_y;
77 plane->dst_w = clamp_val(dest_w, 0, mode->crtc_hdisplay - dest_x);
78 plane->dst_h = clamp_val(dest_h, 0, mode->crtc_vdisplay - dest_y);
79 plane->src_x = src_x;
80 plane->src_y = src_y;
81 plane->src_w = src_w;
82 plane->src_h = src_h;
83 plane->format = fb->pixel_format;
84 plane->vaddr = cma_obj->vaddr;
85 plane->paddr = cma_obj->paddr;
86 for (i = 0; i < 4; i++) {
87 plane->pitches[i] = fb->pitches[i];
88 plane->offsets[i] = fb->offsets[i];
9bbf86fe
BG
89 }
90
871bcdfe
VA
91 DRM_DEBUG_DRIVER("%s is associated with mixer_id %d\n",
92 sti_plane_to_str(plane),
93 plane->mixer_id);
94 DRM_DEBUG_DRIVER("%s dst=(%dx%d)@(%d,%d) - src=(%dx%d)@(%d,%d)\n",
95 sti_plane_to_str(plane),
96 plane->dst_w, plane->dst_h, plane->dst_x, plane->dst_y,
97 plane->src_w, plane->src_h, plane->src_x,
98 plane->src_y);
99
100 DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id,
101 (char *)&plane->format, (unsigned long)plane->paddr);
102
103 if (!plane->ops->prepare) {
104 DRM_ERROR("Cannot prepare\n");
105 return 1;
9bbf86fe
BG
106 }
107
871bcdfe 108 res = plane->ops->prepare(plane, !plane->enabled);
9bbf86fe 109 if (res) {
871bcdfe 110 DRM_ERROR("Plane prepare failed\n");
9bbf86fe
BG
111 return res;
112 }
113
871bcdfe
VA
114 plane->enabled = true;
115
9bbf86fe
BG
116 return 0;
117}
118
871bcdfe 119static int sti_plane_commit(struct sti_plane *plane)
9bbf86fe 120{
871bcdfe
VA
121 if (!plane)
122 return 1;
9bbf86fe 123
871bcdfe
VA
124 if (!plane->ops->commit) {
125 DRM_ERROR("Cannot commit\n");
126 return 1;
9bbf86fe 127 }
9bbf86fe 128
871bcdfe
VA
129 return plane->ops->commit(plane);
130}
9bbf86fe 131
871bcdfe
VA
132static int sti_plane_disable(struct sti_plane *plane)
133{
134 int res;
9bbf86fe 135
871bcdfe
VA
136 DRM_DEBUG_DRIVER("%s\n", sti_plane_to_str(plane));
137 if (!plane)
138 return 1;
9bbf86fe 139
871bcdfe
VA
140 if (!plane->enabled)
141 return 0;
9bbf86fe 142
871bcdfe
VA
143 if (!plane->ops->disable) {
144 DRM_ERROR("Cannot disable\n");
145 return 1;
146 }
147
148 res = plane->ops->disable(plane);
149 if (res) {
150 DRM_ERROR("Plane disable failed\n");
151 return res;
152 }
153
154 plane->enabled = false;
9bbf86fe
BG
155
156 return 0;
157}
158
871bcdfe 159static void sti_drm_plane_destroy(struct drm_plane *drm_plane)
9bbf86fe
BG
160{
161 DRM_DEBUG_DRIVER("\n");
162
871bcdfe
VA
163 drm_plane_helper_disable(drm_plane);
164 drm_plane_cleanup(drm_plane);
9bbf86fe
BG
165}
166
871bcdfe 167static int sti_drm_plane_set_property(struct drm_plane *drm_plane,
9bbf86fe
BG
168 struct drm_property *property,
169 uint64_t val)
170{
871bcdfe 171 struct drm_device *dev = drm_plane->dev;
9bbf86fe 172 struct sti_drm_private *private = dev->dev_private;
871bcdfe 173 struct sti_plane *plane = to_sti_plane(drm_plane);
9bbf86fe
BG
174
175 DRM_DEBUG_DRIVER("\n");
176
177 if (property == private->plane_zorder_property) {
871bcdfe 178 plane->zorder = val;
9bbf86fe
BG
179 return 0;
180 }
181
182 return -EINVAL;
183}
184
185static struct drm_plane_funcs sti_drm_plane_funcs = {
de4b00b0
BG
186 .update_plane = drm_atomic_helper_update_plane,
187 .disable_plane = drm_atomic_helper_disable_plane,
9bbf86fe
BG
188 .destroy = sti_drm_plane_destroy,
189 .set_property = sti_drm_plane_set_property,
de4b00b0
BG
190 .reset = drm_atomic_helper_plane_reset,
191 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
192 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
193};
194
871bcdfe 195static int sti_drm_plane_atomic_check(struct drm_plane *drm_plane,
de4b00b0
BG
196 struct drm_plane_state *state)
197{
198 return 0;
199}
200
871bcdfe 201static void sti_drm_plane_atomic_update(struct drm_plane *drm_plane,
de4b00b0
BG
202 struct drm_plane_state *oldstate)
203{
871bcdfe
VA
204 struct drm_plane_state *state = drm_plane->state;
205 struct sti_plane *plane = to_sti_plane(drm_plane);
206 struct sti_mixer *mixer = to_sti_mixer(state->crtc);
207 int res;
208
209 DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
210 state->crtc->base.id, sti_mixer_to_str(mixer),
211 drm_plane->base.id, sti_plane_to_str(plane));
212 DRM_DEBUG_KMS("(%dx%d)@(%d,%d)\n",
213 state->crtc_w, state->crtc_h,
214 state->crtc_x, state->crtc_y);
215
216 res = sti_mixer_set_plane_depth(mixer, plane);
217 if (res) {
218 DRM_ERROR("Cannot set plane depth\n");
219 return;
220 }
de4b00b0 221
871bcdfe
VA
222 /* src_x are in 16.16 format */
223 res = sti_plane_prepare(plane, state->crtc, state->fb,
224 &state->crtc->mode, mixer->id,
225 state->crtc_x, state->crtc_y,
226 state->crtc_w, state->crtc_h,
227 state->src_x >> 16, state->src_y >> 16,
228 state->src_w >> 16, state->src_h >> 16);
229 if (res) {
230 DRM_ERROR("Plane prepare failed\n");
231 return;
232 }
233
234 res = sti_plane_commit(plane);
235 if (res) {
236 DRM_ERROR("Plane commit failed\n");
237 return;
238 }
239
240 res = sti_mixer_set_plane_status(mixer, plane, true);
241 if (res) {
242 DRM_ERROR("Cannot enable plane at mixer\n");
243 return;
244 }
de4b00b0
BG
245}
246
871bcdfe 247static void sti_drm_plane_atomic_disable(struct drm_plane *drm_plane,
de4b00b0
BG
248 struct drm_plane_state *oldstate)
249{
871bcdfe
VA
250 struct sti_plane *plane = to_sti_plane(drm_plane);
251 struct sti_mixer *mixer = to_sti_mixer(drm_plane->crtc);
252 int res;
253
254 if (!drm_plane->crtc) {
255 DRM_DEBUG_DRIVER("drm plane:%d not enabled\n",
256 drm_plane->base.id);
257 return;
258 }
259
260 DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n",
261 drm_plane->crtc->base.id, sti_mixer_to_str(mixer),
262 drm_plane->base.id, sti_plane_to_str(plane));
263
264 /* Disable plane at mixer level */
265 res = sti_mixer_set_plane_status(mixer, plane, false);
266 if (res) {
267 DRM_ERROR("Cannot disable plane at mixer\n");
268 return;
269 }
270
271 /* Wait a while to be sure that a Vsync event is received */
272 msleep(WAIT_NEXT_VSYNC_MS);
273
274 /* Then disable plane itself */
275 res = sti_plane_disable(plane);
276 if (res) {
277 DRM_ERROR("Plane disable failed\n");
278 return;
279 }
de4b00b0
BG
280}
281
282static const struct drm_plane_helper_funcs sti_drm_plane_helpers_funcs = {
de4b00b0
BG
283 .atomic_check = sti_drm_plane_atomic_check,
284 .atomic_update = sti_drm_plane_atomic_update,
285 .atomic_disable = sti_drm_plane_atomic_disable,
9bbf86fe
BG
286};
287
871bcdfe 288static void sti_drm_plane_attach_zorder_property(struct drm_plane *drm_plane)
9bbf86fe 289{
871bcdfe 290 struct drm_device *dev = drm_plane->dev;
9bbf86fe 291 struct sti_drm_private *private = dev->dev_private;
871bcdfe 292 struct sti_plane *plane = to_sti_plane(drm_plane);
9bbf86fe 293 struct drm_property *prop;
9bbf86fe
BG
294
295 prop = private->plane_zorder_property;
296 if (!prop) {
bf60b29f
VA
297 prop = drm_property_create_range(dev, 0, "zpos", 1,
298 GAM_MIXER_NB_DEPTH_LEVEL);
9bbf86fe
BG
299 if (!prop)
300 return;
301
302 private->plane_zorder_property = prop;
303 }
304
871bcdfe 305 drm_object_attach_property(&drm_plane->base, prop, plane->zorder);
9bbf86fe
BG
306}
307
308struct drm_plane *sti_drm_plane_init(struct drm_device *dev,
871bcdfe
VA
309 struct sti_plane *plane,
310 unsigned int possible_crtcs,
311 enum drm_plane_type type)
9bbf86fe
BG
312{
313 int err, i;
9bbf86fe 314
871bcdfe
VA
315 err = drm_universal_plane_init(dev, &plane->drm_plane,
316 possible_crtcs,
317 &sti_drm_plane_funcs,
318 plane->ops->get_formats(plane),
319 plane->ops->get_nb_formats(plane),
320 type);
9bbf86fe 321 if (err) {
871bcdfe 322 DRM_ERROR("Failed to initialize universal plane\n");
9bbf86fe
BG
323 return NULL;
324 }
325
871bcdfe
VA
326 drm_plane_helper_add(&plane->drm_plane,
327 &sti_drm_plane_helpers_funcs);
de4b00b0 328
871bcdfe
VA
329 for (i = 0; i < ARRAY_SIZE(sti_plane_default_zorder); i++)
330 if (sti_plane_default_zorder[i] == plane->desc)
9bbf86fe
BG
331 break;
332
871bcdfe 333 plane->zorder = i + 1;
9bbf86fe
BG
334
335 if (type == DRM_PLANE_TYPE_OVERLAY)
871bcdfe 336 sti_drm_plane_attach_zorder_property(&plane->drm_plane);
9bbf86fe 337
871bcdfe
VA
338 DRM_DEBUG_DRIVER("drm plane:%d mapped to %s with zorder:%d\n",
339 plane->drm_plane.base.id,
340 sti_plane_to_str(plane), plane->zorder);
9bbf86fe 341
871bcdfe 342 return &plane->drm_plane;
9bbf86fe 343}
4e0cd681 344EXPORT_SYMBOL(sti_drm_plane_init);
This page took 0.07716 seconds and 5 git commands to generate.