1 /* exynos_drm_crtc.c
2  *
3  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4  * Authors:
5  *	Inki Dae <inki.dae@samsung.com>
6  *	Joonyoung Shim <jy0922.shim@samsung.com>
7  *	Seung-Woo Kim <sw0312.kim@samsung.com>
8  *
9  * This program is free software; you can redistribute  it and/or modify it
10  * under  the terms of  the GNU General  Public License as published by the
11  * Free Software Foundation;  either version 2 of the  License, or (at your
12  * option) any later version.
13  */
14 
15 #include <drm/drmP.h>
16 #include <drm/drm_crtc_helper.h>
17 
18 #include "exynos_drm_crtc.h"
19 #include "exynos_drm_drv.h"
20 #include "exynos_drm_encoder.h"
21 #include "exynos_drm_plane.h"
22 
23 static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
24 {
25 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
26 
27 	DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
28 
29 	if (exynos_crtc->dpms == mode) {
30 		DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
31 		return;
32 	}
33 
34 	if (mode > DRM_MODE_DPMS_ON) {
35 		/* wait for the completion of page flip. */
36 		if (!wait_event_timeout(exynos_crtc->pending_flip_queue,
37 				(exynos_crtc->event == NULL), HZ/20))
38 			exynos_crtc->event = NULL;
39 		drm_crtc_vblank_off(crtc);
40 	}
41 
42 	if (exynos_crtc->ops->dpms)
43 		exynos_crtc->ops->dpms(exynos_crtc, mode);
44 
45 	exynos_crtc->dpms = mode;
46 
47 	if (mode == DRM_MODE_DPMS_ON)
48 		drm_crtc_vblank_on(crtc);
49 }
50 
51 static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
52 {
53 	/* drm framework doesn't check NULL. */
54 }
55 
56 static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
57 {
58 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
59 	struct exynos_drm_plane *exynos_plane = to_exynos_plane(crtc->primary);
60 
61 	exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
62 
63 	if (exynos_crtc->ops->win_commit)
64 		exynos_crtc->ops->win_commit(exynos_crtc, exynos_plane->zpos);
65 
66 	if (exynos_crtc->ops->commit)
67 		exynos_crtc->ops->commit(exynos_crtc);
68 }
69 
70 static bool
71 exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc,
72 			    const struct drm_display_mode *mode,
73 			    struct drm_display_mode *adjusted_mode)
74 {
75 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
76 
77 	if (exynos_crtc->ops->mode_fixup)
78 		return exynos_crtc->ops->mode_fixup(exynos_crtc, mode,
79 						    adjusted_mode);
80 
81 	return true;
82 }
83 
84 static int
85 exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
86 			  struct drm_display_mode *adjusted_mode, int x, int y,
87 			  struct drm_framebuffer *old_fb)
88 {
89 	struct drm_framebuffer *fb = crtc->primary->fb;
90 	unsigned int crtc_w;
91 	unsigned int crtc_h;
92 	int ret;
93 
94 	/*
95 	 * copy the mode data adjusted by mode_fixup() into crtc->mode
96 	 * so that hardware can be seet to proper mode.
97 	 */
98 	memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode));
99 
100 	ret = exynos_check_plane(crtc->primary, fb);
101 	if (ret < 0)
102 		return ret;
103 
104 	crtc_w = fb->width - x;
105 	crtc_h = fb->height - y;
106 	exynos_plane_mode_set(crtc->primary, crtc, fb, 0, 0,
107 			      crtc_w, crtc_h, x, y, crtc_w, crtc_h);
108 
109 	return 0;
110 }
111 
112 static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
113 					  struct drm_framebuffer *old_fb)
114 {
115 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
116 	struct drm_framebuffer *fb = crtc->primary->fb;
117 	unsigned int crtc_w;
118 	unsigned int crtc_h;
119 
120 	/* when framebuffer changing is requested, crtc's dpms should be on */
121 	if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) {
122 		DRM_ERROR("failed framebuffer changing request.\n");
123 		return -EPERM;
124 	}
125 
126 	crtc_w = fb->width - x;
127 	crtc_h = fb->height - y;
128 
129 	return exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
130 				   crtc_w, crtc_h, x, y, crtc_w, crtc_h);
131 }
132 
133 static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
134 {
135 	struct drm_plane *plane;
136 	int ret;
137 
138 	exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
139 
140 	drm_for_each_legacy_plane(plane, &crtc->dev->mode_config.plane_list) {
141 		if (plane->crtc != crtc)
142 			continue;
143 
144 		ret = plane->funcs->disable_plane(plane);
145 		if (ret)
146 			DRM_ERROR("Failed to disable plane %d\n", ret);
147 	}
148 }
149 
150 static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
151 	.dpms		= exynos_drm_crtc_dpms,
152 	.prepare	= exynos_drm_crtc_prepare,
153 	.commit		= exynos_drm_crtc_commit,
154 	.mode_fixup	= exynos_drm_crtc_mode_fixup,
155 	.mode_set	= exynos_drm_crtc_mode_set,
156 	.mode_set_base	= exynos_drm_crtc_mode_set_base,
157 	.disable	= exynos_drm_crtc_disable,
158 };
159 
160 static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
161 				     struct drm_framebuffer *fb,
162 				     struct drm_pending_vblank_event *event,
163 				     uint32_t page_flip_flags)
164 {
165 	struct drm_device *dev = crtc->dev;
166 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
167 	struct drm_framebuffer *old_fb = crtc->primary->fb;
168 	unsigned int crtc_w, crtc_h;
169 	int ret;
170 
171 	/* when the page flip is requested, crtc's dpms should be on */
172 	if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) {
173 		DRM_ERROR("failed page flip request.\n");
174 		return -EINVAL;
175 	}
176 
177 	if (!event)
178 		return -EINVAL;
179 
180 	spin_lock_irq(&dev->event_lock);
181 	if (exynos_crtc->event) {
182 		ret = -EBUSY;
183 		goto out;
184 	}
185 
186 	ret = drm_vblank_get(dev, exynos_crtc->pipe);
187 	if (ret) {
188 		DRM_DEBUG("failed to acquire vblank counter\n");
189 		goto out;
190 	}
191 
192 	exynos_crtc->event = event;
193 	spin_unlock_irq(&dev->event_lock);
194 
195 	/*
196 	 * the pipe from user always is 0 so we can set pipe number
197 	 * of current owner to event.
198 	 */
199 	event->pipe = exynos_crtc->pipe;
200 
201 	crtc->primary->fb = fb;
202 	crtc_w = fb->width - crtc->x;
203 	crtc_h = fb->height - crtc->y;
204 	ret = exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
205 				  crtc_w, crtc_h, crtc->x, crtc->y,
206 				  crtc_w, crtc_h);
207 	if (ret) {
208 		crtc->primary->fb = old_fb;
209 		spin_lock_irq(&dev->event_lock);
210 		exynos_crtc->event = NULL;
211 		drm_vblank_put(dev, exynos_crtc->pipe);
212 		spin_unlock_irq(&dev->event_lock);
213 		return ret;
214 	}
215 
216 	return 0;
217 
218 out:
219 	spin_unlock_irq(&dev->event_lock);
220 	return ret;
221 }
222 
223 static void exynos_drm_crtc_destroy(struct drm_crtc *crtc)
224 {
225 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
226 	struct exynos_drm_private *private = crtc->dev->dev_private;
227 
228 	private->crtc[exynos_crtc->pipe] = NULL;
229 
230 	drm_crtc_cleanup(crtc);
231 	kfree(exynos_crtc);
232 }
233 
234 static struct drm_crtc_funcs exynos_crtc_funcs = {
235 	.set_config	= drm_crtc_helper_set_config,
236 	.page_flip	= exynos_drm_crtc_page_flip,
237 	.destroy	= exynos_drm_crtc_destroy,
238 };
239 
240 struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
241 					       struct drm_plane *plane,
242 					       int pipe,
243 					       enum exynos_drm_output_type type,
244 					       struct exynos_drm_crtc_ops *ops,
245 					       void *ctx)
246 {
247 	struct exynos_drm_crtc *exynos_crtc;
248 	struct exynos_drm_private *private = drm_dev->dev_private;
249 	struct drm_crtc *crtc;
250 	int ret;
251 
252 	exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL);
253 	if (!exynos_crtc)
254 		return ERR_PTR(-ENOMEM);
255 
256 	init_waitqueue_head(&exynos_crtc->pending_flip_queue);
257 
258 	exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
259 	exynos_crtc->pipe = pipe;
260 	exynos_crtc->type = type;
261 	exynos_crtc->ops = ops;
262 	exynos_crtc->ctx = ctx;
263 
264 	crtc = &exynos_crtc->base;
265 
266 	private->crtc[pipe] = crtc;
267 
268 	ret = drm_crtc_init_with_planes(drm_dev, crtc, plane, NULL,
269 					&exynos_crtc_funcs);
270 	if (ret < 0)
271 		goto err_crtc;
272 
273 	drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs);
274 
275 	return exynos_crtc;
276 
277 err_crtc:
278 	plane->funcs->destroy(plane);
279 	kfree(exynos_crtc);
280 	return ERR_PTR(ret);
281 }
282 
283 int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe)
284 {
285 	struct exynos_drm_private *private = dev->dev_private;
286 	struct exynos_drm_crtc *exynos_crtc =
287 		to_exynos_crtc(private->crtc[pipe]);
288 
289 	if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
290 		return -EPERM;
291 
292 	if (exynos_crtc->ops->enable_vblank)
293 		exynos_crtc->ops->enable_vblank(exynos_crtc);
294 
295 	return 0;
296 }
297 
298 void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe)
299 {
300 	struct exynos_drm_private *private = dev->dev_private;
301 	struct exynos_drm_crtc *exynos_crtc =
302 		to_exynos_crtc(private->crtc[pipe]);
303 
304 	if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
305 		return;
306 
307 	if (exynos_crtc->ops->disable_vblank)
308 		exynos_crtc->ops->disable_vblank(exynos_crtc);
309 }
310 
311 void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe)
312 {
313 	struct exynos_drm_private *dev_priv = dev->dev_private;
314 	struct drm_crtc *drm_crtc = dev_priv->crtc[pipe];
315 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(drm_crtc);
316 	unsigned long flags;
317 
318 	spin_lock_irqsave(&dev->event_lock, flags);
319 	if (exynos_crtc->event) {
320 
321 		drm_send_vblank_event(dev, -1, exynos_crtc->event);
322 		drm_vblank_put(dev, pipe);
323 		wake_up(&exynos_crtc->pending_flip_queue);
324 
325 	}
326 
327 	exynos_crtc->event = NULL;
328 	spin_unlock_irqrestore(&dev->event_lock, flags);
329 }
330 
331 void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb)
332 {
333 	struct exynos_drm_crtc *exynos_crtc;
334 	struct drm_device *dev = fb->dev;
335 	struct drm_crtc *crtc;
336 
337 	/*
338 	 * make sure that overlay data are updated to real hardware
339 	 * for all encoders.
340 	 */
341 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
342 		exynos_crtc = to_exynos_crtc(crtc);
343 
344 		/*
345 		 * wait for vblank interrupt
346 		 * - this makes sure that overlay data are updated to
347 		 *	real hardware.
348 		 */
349 		if (exynos_crtc->ops->wait_for_vblank)
350 			exynos_crtc->ops->wait_for_vblank(exynos_crtc);
351 	}
352 }
353 
354 int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
355 					unsigned int out_type)
356 {
357 	struct drm_crtc *crtc;
358 
359 	list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head) {
360 		struct exynos_drm_crtc *exynos_crtc;
361 
362 		exynos_crtc = to_exynos_crtc(crtc);
363 		if (exynos_crtc->type == out_type)
364 			return exynos_crtc->pipe;
365 	}
366 
367 	return -EPERM;
368 }
369 
370 void exynos_drm_crtc_te_handler(struct drm_crtc *crtc)
371 {
372 	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
373 
374 	if (exynos_crtc->ops->te_handler)
375 		exynos_crtc->ops->te_handler(exynos_crtc);
376 }
377