Merge tag 'drm/tegra/for-3.19-rc1' of git://people.freedesktop.org/~tagr/linux into...
[deliverable/linux.git] / drivers / gpu / drm / sti / sti_drm_crtc.c
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
9 #include <linux/clk.h>
10
11 #include <drm/drmP.h>
12 #include <drm/drm_crtc_helper.h>
13 #include <drm/drm_plane_helper.h>
14
15 #include "sti_compositor.h"
16 #include "sti_drm_drv.h"
17 #include "sti_drm_crtc.h"
18 #include "sti_vtg.h"
19
20 static void sti_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
21 {
22 DRM_DEBUG_KMS("\n");
23 }
24
25 static void sti_drm_crtc_prepare(struct drm_crtc *crtc)
26 {
27 struct sti_mixer *mixer = to_sti_mixer(crtc);
28 struct device *dev = mixer->dev;
29 struct sti_compositor *compo = dev_get_drvdata(dev);
30
31 compo->enable = true;
32
33 /* Prepare and enable the compo IP clock */
34 if (mixer->id == STI_MIXER_MAIN) {
35 if (clk_prepare_enable(compo->clk_compo_main))
36 DRM_INFO("Failed to prepare/enable compo_main clk\n");
37 } else {
38 if (clk_prepare_enable(compo->clk_compo_aux))
39 DRM_INFO("Failed to prepare/enable compo_aux clk\n");
40 }
41 }
42
43 static void sti_drm_crtc_commit(struct drm_crtc *crtc)
44 {
45 struct sti_mixer *mixer = to_sti_mixer(crtc);
46 struct device *dev = mixer->dev;
47 struct sti_compositor *compo = dev_get_drvdata(dev);
48 struct sti_layer *layer;
49
50 if ((!mixer || !compo)) {
51 DRM_ERROR("Can not find mixer or compositor)\n");
52 return;
53 }
54
55 /* get GDP which is reserved to the CRTC FB */
56 layer = to_sti_layer(crtc->primary);
57 if (layer)
58 sti_layer_commit(layer);
59 else
60 DRM_ERROR("Can not find CRTC dedicated plane (GDP0)\n");
61
62 /* Enable layer on mixer */
63 if (sti_mixer_set_layer_status(mixer, layer, true))
64 DRM_ERROR("Can not enable layer at mixer\n");
65 }
66
67 static bool sti_drm_crtc_mode_fixup(struct drm_crtc *crtc,
68 const struct drm_display_mode *mode,
69 struct drm_display_mode *adjusted_mode)
70 {
71 /* accept the provided drm_display_mode, do not fix it up */
72 return true;
73 }
74
75 static int
76 sti_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
77 struct drm_display_mode *adjusted_mode, int x, int y,
78 struct drm_framebuffer *old_fb)
79 {
80 struct sti_mixer *mixer = to_sti_mixer(crtc);
81 struct device *dev = mixer->dev;
82 struct sti_compositor *compo = dev_get_drvdata(dev);
83 struct sti_layer *layer;
84 struct clk *clk;
85 int rate = mode->clock * 1000;
86 int res;
87 unsigned int w, h;
88
89 DRM_DEBUG_KMS("CRTC:%d (%s) fb:%d mode:%d (%s)\n",
90 crtc->base.id, sti_mixer_to_str(mixer),
91 crtc->primary->fb->base.id, mode->base.id, mode->name);
92
93 DRM_DEBUG_KMS("%d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n",
94 mode->vrefresh, mode->clock,
95 mode->hdisplay,
96 mode->hsync_start, mode->hsync_end,
97 mode->htotal,
98 mode->vdisplay,
99 mode->vsync_start, mode->vsync_end,
100 mode->vtotal, mode->type, mode->flags);
101
102 /* Set rate and prepare/enable pixel clock */
103 if (mixer->id == STI_MIXER_MAIN)
104 clk = compo->clk_pix_main;
105 else
106 clk = compo->clk_pix_aux;
107
108 res = clk_set_rate(clk, rate);
109 if (res < 0) {
110 DRM_ERROR("Cannot set rate (%dHz) for pix clk\n", rate);
111 return -EINVAL;
112 }
113 if (clk_prepare_enable(clk)) {
114 DRM_ERROR("Failed to prepare/enable pix clk\n");
115 return -EINVAL;
116 }
117
118 sti_vtg_set_config(mixer->id == STI_MIXER_MAIN ?
119 compo->vtg_main : compo->vtg_aux, &crtc->mode);
120
121 /* a GDP is reserved to the CRTC FB */
122 layer = to_sti_layer(crtc->primary);
123 if (!layer) {
124 DRM_ERROR("Can not find GDP0)\n");
125 return -EINVAL;
126 }
127
128 /* copy the mode data adjusted by mode_fixup() into crtc->mode
129 * so that hardware can be set to proper mode
130 */
131 memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode));
132
133 res = sti_mixer_set_layer_depth(mixer, layer);
134 if (res) {
135 DRM_ERROR("Can not set layer depth\n");
136 return -EINVAL;
137 }
138 res = sti_mixer_active_video_area(mixer, &crtc->mode);
139 if (res) {
140 DRM_ERROR("Can not set active video area\n");
141 return -EINVAL;
142 }
143
144 w = crtc->primary->fb->width - x;
145 h = crtc->primary->fb->height - y;
146
147 return sti_layer_prepare(layer, crtc->primary->fb, &crtc->mode,
148 mixer->id, 0, 0, w, h, x, y, w, h);
149 }
150
151 static int sti_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
152 struct drm_framebuffer *old_fb)
153 {
154 struct sti_mixer *mixer = to_sti_mixer(crtc);
155 struct sti_layer *layer;
156 unsigned int w, h;
157 int ret;
158
159 DRM_DEBUG_KMS("CRTC:%d (%s) fb:%d (%d,%d)\n",
160 crtc->base.id, sti_mixer_to_str(mixer),
161 crtc->primary->fb->base.id, x, y);
162
163 /* GDP is reserved to the CRTC FB */
164 layer = to_sti_layer(crtc->primary);
165 if (!layer) {
166 DRM_ERROR("Can not find GDP0)\n");
167 ret = -EINVAL;
168 goto out;
169 }
170
171 w = crtc->primary->fb->width - crtc->x;
172 h = crtc->primary->fb->height - crtc->y;
173
174 ret = sti_layer_prepare(layer, crtc->primary->fb, &crtc->mode,
175 mixer->id, 0, 0, w, h,
176 crtc->x, crtc->y, w, h);
177 if (ret) {
178 DRM_ERROR("Can not prepare layer\n");
179 goto out;
180 }
181
182 sti_drm_crtc_commit(crtc);
183 out:
184 return ret;
185 }
186
187 static void sti_drm_crtc_load_lut(struct drm_crtc *crtc)
188 {
189 /* do nothing */
190 }
191
192 static void sti_drm_crtc_disable(struct drm_crtc *crtc)
193 {
194 struct sti_mixer *mixer = to_sti_mixer(crtc);
195 struct device *dev = mixer->dev;
196 struct sti_compositor *compo = dev_get_drvdata(dev);
197 struct sti_layer *layer;
198
199 if (!compo->enable)
200 return;
201
202 DRM_DEBUG_KMS("CRTC:%d (%s)\n", crtc->base.id, sti_mixer_to_str(mixer));
203
204 /* Disable Background */
205 sti_mixer_set_background_status(mixer, false);
206
207 /* Disable GDP */
208 layer = to_sti_layer(crtc->primary);
209 if (!layer) {
210 DRM_ERROR("Cannot find GDP0\n");
211 return;
212 }
213
214 /* Disable layer at mixer level */
215 if (sti_mixer_set_layer_status(mixer, layer, false))
216 DRM_ERROR("Can not disable %s layer at mixer\n",
217 sti_layer_to_str(layer));
218
219 /* Wait a while to be sure that a Vsync event is received */
220 msleep(WAIT_NEXT_VSYNC_MS);
221
222 /* Then disable layer itself */
223 sti_layer_disable(layer);
224
225 drm_vblank_off(crtc->dev, mixer->id);
226
227 /* Disable pixel clock and compo IP clocks */
228 if (mixer->id == STI_MIXER_MAIN) {
229 clk_disable_unprepare(compo->clk_pix_main);
230 clk_disable_unprepare(compo->clk_compo_main);
231 } else {
232 clk_disable_unprepare(compo->clk_pix_aux);
233 clk_disable_unprepare(compo->clk_compo_aux);
234 }
235
236 compo->enable = false;
237 }
238
239 static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
240 .dpms = sti_drm_crtc_dpms,
241 .prepare = sti_drm_crtc_prepare,
242 .commit = sti_drm_crtc_commit,
243 .mode_fixup = sti_drm_crtc_mode_fixup,
244 .mode_set = sti_drm_crtc_mode_set,
245 .mode_set_base = sti_drm_crtc_mode_set_base,
246 .load_lut = sti_drm_crtc_load_lut,
247 .disable = sti_drm_crtc_disable,
248 };
249
250 static int sti_drm_crtc_page_flip(struct drm_crtc *crtc,
251 struct drm_framebuffer *fb,
252 struct drm_pending_vblank_event *event,
253 uint32_t page_flip_flags)
254 {
255 struct drm_device *drm_dev = crtc->dev;
256 struct drm_framebuffer *old_fb;
257 struct sti_mixer *mixer = to_sti_mixer(crtc);
258 unsigned long flags;
259 int ret;
260
261 DRM_DEBUG_KMS("fb %d --> fb %d\n",
262 crtc->primary->fb->base.id, fb->base.id);
263
264 mutex_lock(&drm_dev->struct_mutex);
265
266 old_fb = crtc->primary->fb;
267 crtc->primary->fb = fb;
268 ret = sti_drm_crtc_mode_set_base(crtc, crtc->x, crtc->y, old_fb);
269 if (ret) {
270 DRM_ERROR("failed\n");
271 crtc->primary->fb = old_fb;
272 goto out;
273 }
274
275 if (event) {
276 event->pipe = mixer->id;
277
278 ret = drm_vblank_get(drm_dev, event->pipe);
279 if (ret) {
280 DRM_ERROR("Cannot get vblank\n");
281 goto out;
282 }
283
284 spin_lock_irqsave(&drm_dev->event_lock, flags);
285 if (mixer->pending_event) {
286 drm_vblank_put(drm_dev, event->pipe);
287 ret = -EBUSY;
288 } else {
289 mixer->pending_event = event;
290 }
291 spin_unlock_irqrestore(&drm_dev->event_lock, flags);
292 }
293 out:
294 mutex_unlock(&drm_dev->struct_mutex);
295 return ret;
296 }
297
298 static void sti_drm_crtc_destroy(struct drm_crtc *crtc)
299 {
300 DRM_DEBUG_KMS("\n");
301 drm_crtc_cleanup(crtc);
302 }
303
304 static int sti_drm_crtc_set_property(struct drm_crtc *crtc,
305 struct drm_property *property,
306 uint64_t val)
307 {
308 DRM_DEBUG_KMS("\n");
309 return 0;
310 }
311
312 int sti_drm_crtc_vblank_cb(struct notifier_block *nb,
313 unsigned long event, void *data)
314 {
315 struct drm_device *drm_dev;
316 struct sti_compositor *compo =
317 container_of(nb, struct sti_compositor, vtg_vblank_nb);
318 int *crtc = data;
319 unsigned long flags;
320 struct sti_drm_private *priv;
321
322 drm_dev = compo->mixer[*crtc]->drm_crtc.dev;
323 priv = drm_dev->dev_private;
324
325 if ((event != VTG_TOP_FIELD_EVENT) &&
326 (event != VTG_BOTTOM_FIELD_EVENT)) {
327 DRM_ERROR("unknown event: %lu\n", event);
328 return -EINVAL;
329 }
330
331 drm_handle_vblank(drm_dev, *crtc);
332
333 spin_lock_irqsave(&drm_dev->event_lock, flags);
334 if (compo->mixer[*crtc]->pending_event) {
335 drm_send_vblank_event(drm_dev, -1,
336 compo->mixer[*crtc]->pending_event);
337 drm_vblank_put(drm_dev, *crtc);
338 compo->mixer[*crtc]->pending_event = NULL;
339 }
340 spin_unlock_irqrestore(&drm_dev->event_lock, flags);
341
342 return 0;
343 }
344
345 int sti_drm_crtc_enable_vblank(struct drm_device *dev, int crtc)
346 {
347 struct sti_drm_private *dev_priv = dev->dev_private;
348 struct sti_compositor *compo = dev_priv->compo;
349 struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
350
351 if (sti_vtg_register_client(crtc == STI_MIXER_MAIN ?
352 compo->vtg_main : compo->vtg_aux,
353 vtg_vblank_nb, crtc)) {
354 DRM_ERROR("Cannot register VTG notifier\n");
355 return -EINVAL;
356 }
357
358 return 0;
359 }
360 EXPORT_SYMBOL(sti_drm_crtc_enable_vblank);
361
362 void sti_drm_crtc_disable_vblank(struct drm_device *dev, int crtc)
363 {
364 struct sti_drm_private *priv = dev->dev_private;
365 struct sti_compositor *compo = priv->compo;
366 struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
367 unsigned long flags;
368
369 DRM_DEBUG_DRIVER("\n");
370
371 if (sti_vtg_unregister_client(crtc == STI_MIXER_MAIN ?
372 compo->vtg_main : compo->vtg_aux, vtg_vblank_nb))
373 DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n");
374
375 /* free the resources of the pending requests */
376 spin_lock_irqsave(&dev->event_lock, flags);
377 if (compo->mixer[crtc]->pending_event) {
378 drm_vblank_put(dev, crtc);
379 compo->mixer[crtc]->pending_event = NULL;
380 }
381 spin_unlock_irqrestore(&dev->event_lock, flags);
382
383 }
384 EXPORT_SYMBOL(sti_drm_crtc_disable_vblank);
385
386 static struct drm_crtc_funcs sti_crtc_funcs = {
387 .set_config = drm_crtc_helper_set_config,
388 .page_flip = sti_drm_crtc_page_flip,
389 .destroy = sti_drm_crtc_destroy,
390 .set_property = sti_drm_crtc_set_property,
391 };
392
393 bool sti_drm_crtc_is_main(struct drm_crtc *crtc)
394 {
395 struct sti_mixer *mixer = to_sti_mixer(crtc);
396
397 if (mixer->id == STI_MIXER_MAIN)
398 return true;
399
400 return false;
401 }
402
403 int sti_drm_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
404 struct drm_plane *primary, struct drm_plane *cursor)
405 {
406 struct drm_crtc *crtc = &mixer->drm_crtc;
407 int res;
408
409 res = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor,
410 &sti_crtc_funcs);
411 if (res) {
412 DRM_ERROR("Can not initialze CRTC\n");
413 return -EINVAL;
414 }
415
416 drm_crtc_helper_add(crtc, &sti_crtc_helper_funcs);
417
418 DRM_DEBUG_DRIVER("drm CRTC:%d mapped to %s\n",
419 crtc->base.id, sti_mixer_to_str(mixer));
420
421 return 0;
422 }
This page took 0.040691 seconds and 6 git commands to generate.