drm/exynos: update crtc to plane safely
[platform/kernel/linux-starfive.git] / drivers / gpu / drm / exynos / exynos_drm_encoder.c
1 /* exynos_drm_encoder.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  * Permission is hereby granted, free of charge, to any person obtaining a
10  * copy of this software and associated documentation files (the "Software"),
11  * to deal in the Software without restriction, including without limitation
12  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13  * and/or sell copies of the Software, and to permit persons to whom the
14  * Software is furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice (including the next
17  * paragraph) shall be included in all copies or substantial portions of the
18  * Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26  * OTHER DEALINGS IN THE SOFTWARE.
27  */
28
29 #include "drmP.h"
30 #include "drm_crtc_helper.h"
31
32 #include "exynos_drm_drv.h"
33 #include "exynos_drm_encoder.h"
34 #include "exynos_drm_connector.h"
35
36 #define to_exynos_encoder(x)    container_of(x, struct exynos_drm_encoder,\
37                                 drm_encoder)
38
39 /*
40  * exynos specific encoder structure.
41  *
42  * @drm_encoder: encoder object.
43  * @manager: specific encoder has its own manager to control a hardware
44  *      appropriately and we can access a hardware drawing on this manager.
45  * @dpms: store the encoder dpms value.
46  */
47 struct exynos_drm_encoder {
48         struct drm_crtc                 *old_crtc;
49         struct drm_encoder              drm_encoder;
50         struct exynos_drm_manager       *manager;
51         int dpms;
52 };
53
54 static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode)
55 {
56         struct drm_device *dev = encoder->dev;
57         struct drm_connector *connector;
58
59         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
60                 if (connector->encoder == encoder) {
61                         DRM_DEBUG_KMS("connector[%d] dpms[%d]\n",
62                                         connector->base.id, mode);
63
64                         exynos_drm_display_power(connector, mode);
65                 }
66         }
67 }
68
69 static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
70 {
71         struct drm_device *dev = encoder->dev;
72         struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
73         struct exynos_drm_manager_ops *manager_ops = manager->ops;
74         struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
75
76         DRM_DEBUG_KMS("%s, encoder dpms: %d\n", __FILE__, mode);
77
78         if (exynos_encoder->dpms == mode) {
79                 DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
80                 return;
81         }
82
83         mutex_lock(&dev->struct_mutex);
84
85         switch (mode) {
86         case DRM_MODE_DPMS_ON:
87                 if (manager_ops && manager_ops->apply)
88                         manager_ops->apply(manager->dev);
89                 exynos_drm_connector_power(encoder, mode);
90                 exynos_encoder->dpms = mode;
91                 break;
92         case DRM_MODE_DPMS_STANDBY:
93         case DRM_MODE_DPMS_SUSPEND:
94         case DRM_MODE_DPMS_OFF:
95                 exynos_drm_connector_power(encoder, mode);
96                 exynos_encoder->dpms = mode;
97                 break;
98         default:
99                 DRM_ERROR("unspecified mode %d\n", mode);
100                 break;
101         }
102
103         mutex_unlock(&dev->struct_mutex);
104 }
105
106 static bool
107 exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder,
108                                const struct drm_display_mode *mode,
109                                struct drm_display_mode *adjusted_mode)
110 {
111         struct drm_device *dev = encoder->dev;
112         struct drm_connector *connector;
113         struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
114         struct exynos_drm_manager_ops *manager_ops = manager->ops;
115
116         DRM_DEBUG_KMS("%s\n", __FILE__);
117
118         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
119                 if (connector->encoder == encoder)
120                         if (manager_ops && manager_ops->mode_fixup)
121                                 manager_ops->mode_fixup(manager->dev, connector,
122                                                         mode, adjusted_mode);
123         }
124
125         return true;
126 }
127
128 static void disable_plane_to_crtc(struct drm_device *dev,
129                                                 struct drm_crtc *old_crtc,
130                                                 struct drm_crtc *new_crtc)
131 {
132         struct drm_plane *plane;
133
134         /*
135          * if old_crtc isn't same as encoder->crtc then it means that
136          * user changed crtc id to another one so the plane to old_crtc
137          * should be disabled and plane->crtc should be set to new_crtc
138          * (encoder->crtc)
139          */
140         list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
141                 if (plane->crtc == old_crtc) {
142                         /*
143                          * do not change below call order.
144                          *
145                          * plane->funcs->disable_plane call checks
146                          * if encoder->crtc is same as plane->crtc and if same
147                          * then overlay_ops->disable callback will be called
148                          * to diasble current hw overlay so plane->crtc should
149                          * have new_crtc because new_crtc was set to
150                          * encoder->crtc in advance.
151                          */
152                         plane->crtc = new_crtc;
153                         plane->funcs->disable_plane(plane);
154                 }
155         }
156 }
157
158 static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
159                                          struct drm_display_mode *mode,
160                                          struct drm_display_mode *adjusted_mode)
161 {
162         struct drm_device *dev = encoder->dev;
163         struct drm_connector *connector;
164         struct exynos_drm_manager *manager;
165         struct exynos_drm_manager_ops *manager_ops;
166
167         DRM_DEBUG_KMS("%s\n", __FILE__);
168
169         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
170                 if (connector->encoder == encoder) {
171                         struct exynos_drm_encoder *exynos_encoder;
172
173                         exynos_encoder = to_exynos_encoder(encoder);
174
175                         if (exynos_encoder->old_crtc != encoder->crtc &&
176                                         exynos_encoder->old_crtc) {
177
178                                 /*
179                                  * disable a plane to old crtc and change
180                                  * crtc of the plane to new one.
181                                  */
182                                 disable_plane_to_crtc(dev,
183                                                 exynos_encoder->old_crtc,
184                                                 encoder->crtc);
185                         }
186
187                         manager = exynos_drm_get_manager(encoder);
188                         manager_ops = manager->ops;
189
190                         if (manager_ops && manager_ops->mode_set)
191                                 manager_ops->mode_set(manager->dev,
192                                                         adjusted_mode);
193
194                         exynos_encoder->old_crtc = encoder->crtc;
195                 }
196         }
197 }
198
199 static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
200 {
201         DRM_DEBUG_KMS("%s\n", __FILE__);
202
203         /* drm framework doesn't check NULL. */
204 }
205
206 static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
207 {
208         struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
209         struct exynos_drm_manager_ops *manager_ops = manager->ops;
210
211         DRM_DEBUG_KMS("%s\n", __FILE__);
212
213         if (manager_ops && manager_ops->commit)
214                 manager_ops->commit(manager->dev);
215 }
216
217 static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = {
218         .dpms           = exynos_drm_encoder_dpms,
219         .mode_fixup     = exynos_drm_encoder_mode_fixup,
220         .mode_set       = exynos_drm_encoder_mode_set,
221         .prepare        = exynos_drm_encoder_prepare,
222         .commit         = exynos_drm_encoder_commit,
223 };
224
225 static void exynos_drm_encoder_destroy(struct drm_encoder *encoder)
226 {
227         struct exynos_drm_encoder *exynos_encoder =
228                 to_exynos_encoder(encoder);
229
230         DRM_DEBUG_KMS("%s\n", __FILE__);
231
232         exynos_encoder->manager->pipe = -1;
233
234         drm_encoder_cleanup(encoder);
235         kfree(exynos_encoder);
236 }
237
238 static struct drm_encoder_funcs exynos_encoder_funcs = {
239         .destroy = exynos_drm_encoder_destroy,
240 };
241
242 static unsigned int exynos_drm_encoder_clones(struct drm_encoder *encoder)
243 {
244         struct drm_encoder *clone;
245         struct drm_device *dev = encoder->dev;
246         struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
247         struct exynos_drm_display_ops *display_ops =
248                                 exynos_encoder->manager->display_ops;
249         unsigned int clone_mask = 0;
250         int cnt = 0;
251
252         list_for_each_entry(clone, &dev->mode_config.encoder_list, head) {
253                 switch (display_ops->type) {
254                 case EXYNOS_DISPLAY_TYPE_LCD:
255                 case EXYNOS_DISPLAY_TYPE_HDMI:
256                 case EXYNOS_DISPLAY_TYPE_VIDI:
257                         clone_mask |= (1 << (cnt++));
258                         break;
259                 default:
260                         continue;
261                 }
262         }
263
264         return clone_mask;
265 }
266
267 void exynos_drm_encoder_setup(struct drm_device *dev)
268 {
269         struct drm_encoder *encoder;
270
271         DRM_DEBUG_KMS("%s\n", __FILE__);
272
273         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
274                 encoder->possible_clones = exynos_drm_encoder_clones(encoder);
275 }
276
277 struct drm_encoder *
278 exynos_drm_encoder_create(struct drm_device *dev,
279                            struct exynos_drm_manager *manager,
280                            unsigned int possible_crtcs)
281 {
282         struct drm_encoder *encoder;
283         struct exynos_drm_encoder *exynos_encoder;
284
285         DRM_DEBUG_KMS("%s\n", __FILE__);
286
287         if (!manager || !possible_crtcs)
288                 return NULL;
289
290         if (!manager->dev)
291                 return NULL;
292
293         exynos_encoder = kzalloc(sizeof(*exynos_encoder), GFP_KERNEL);
294         if (!exynos_encoder) {
295                 DRM_ERROR("failed to allocate encoder\n");
296                 return NULL;
297         }
298
299         exynos_encoder->dpms = DRM_MODE_DPMS_OFF;
300         exynos_encoder->manager = manager;
301         encoder = &exynos_encoder->drm_encoder;
302         encoder->possible_crtcs = possible_crtcs;
303
304         DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
305
306         drm_encoder_init(dev, encoder, &exynos_encoder_funcs,
307                         DRM_MODE_ENCODER_TMDS);
308
309         drm_encoder_helper_add(encoder, &exynos_encoder_helper_funcs);
310
311         DRM_DEBUG_KMS("encoder has been created\n");
312
313         return encoder;
314 }
315
316 struct exynos_drm_manager *exynos_drm_get_manager(struct drm_encoder *encoder)
317 {
318         return to_exynos_encoder(encoder)->manager;
319 }
320
321 void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data,
322                             void (*fn)(struct drm_encoder *, void *))
323 {
324         struct drm_device *dev = crtc->dev;
325         struct drm_encoder *encoder;
326         struct exynos_drm_private *private = dev->dev_private;
327         struct exynos_drm_manager *manager;
328
329         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
330                 /*
331                  * if crtc is detached from encoder, check pipe,
332                  * otherwise check crtc attached to encoder
333                  */
334                 if (!encoder->crtc) {
335                         manager = to_exynos_encoder(encoder)->manager;
336                         if (manager->pipe < 0 ||
337                                         private->crtc[manager->pipe] != crtc)
338                                 continue;
339                 } else {
340                         if (encoder->crtc != crtc)
341                                 continue;
342                 }
343
344                 fn(encoder, data);
345         }
346 }
347
348 void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data)
349 {
350         struct exynos_drm_manager *manager =
351                 to_exynos_encoder(encoder)->manager;
352         struct exynos_drm_manager_ops *manager_ops = manager->ops;
353         int crtc = *(int *)data;
354
355         if (manager->pipe != crtc)
356                 return;
357
358         if (manager_ops->enable_vblank)
359                 manager_ops->enable_vblank(manager->dev);
360 }
361
362 void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data)
363 {
364         struct exynos_drm_manager *manager =
365                 to_exynos_encoder(encoder)->manager;
366         struct exynos_drm_manager_ops *manager_ops = manager->ops;
367         int crtc = *(int *)data;
368
369         if (manager->pipe != crtc)
370                 return;
371
372         if (manager_ops->disable_vblank)
373                 manager_ops->disable_vblank(manager->dev);
374 }
375
376 void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
377 {
378         struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
379         struct exynos_drm_manager *manager = exynos_encoder->manager;
380         struct exynos_drm_manager_ops *manager_ops = manager->ops;
381         int mode = *(int *)data;
382
383         DRM_DEBUG_KMS("%s\n", __FILE__);
384
385         if (manager_ops && manager_ops->dpms)
386                 manager_ops->dpms(manager->dev, mode);
387
388         /*
389          * set current mode to new one so that data aren't updated into
390          * registers by drm_helper_connector_dpms two times.
391          *
392          * in case that drm_crtc_helper_set_mode() is called,
393          * overlay_ops->commit() and manager_ops->commit() callbacks
394          * can be called two times, first at drm_crtc_helper_set_mode()
395          * and second at drm_helper_connector_dpms().
396          * so with this setting, when drm_helper_connector_dpms() is called
397          * encoder->funcs->dpms() will be ignored.
398          */
399         exynos_encoder->dpms = mode;
400
401         /*
402          * if this condition is ok then it means that the crtc is already
403          * detached from encoder and last function for detaching is properly
404          * done, so clear pipe from manager to prevent repeated call.
405          */
406         if (mode > DRM_MODE_DPMS_ON) {
407                 if (!encoder->crtc)
408                         manager->pipe = -1;
409         }
410 }
411
412 void exynos_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data)
413 {
414         struct exynos_drm_manager *manager =
415                 to_exynos_encoder(encoder)->manager;
416         int pipe = *(int *)data;
417
418         DRM_DEBUG_KMS("%s\n", __FILE__);
419
420         /*
421          * when crtc is detached from encoder, this pipe is used
422          * to select manager operation
423          */
424         manager->pipe = pipe;
425 }
426
427 void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data)
428 {
429         struct exynos_drm_manager *manager =
430                 to_exynos_encoder(encoder)->manager;
431         struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
432         struct exynos_drm_overlay *overlay = data;
433
434         DRM_DEBUG_KMS("%s\n", __FILE__);
435
436         if (overlay_ops && overlay_ops->mode_set)
437                 overlay_ops->mode_set(manager->dev, overlay);
438 }
439
440 void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data)
441 {
442         struct exynos_drm_manager *manager =
443                 to_exynos_encoder(encoder)->manager;
444         struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
445         int zpos = DEFAULT_ZPOS;
446
447         DRM_DEBUG_KMS("%s\n", __FILE__);
448
449         if (data)
450                 zpos = *(int *)data;
451
452         if (overlay_ops && overlay_ops->commit)
453                 overlay_ops->commit(manager->dev, zpos);
454 }
455
456 void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data)
457 {
458         struct exynos_drm_manager *manager =
459                 to_exynos_encoder(encoder)->manager;
460         struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
461         int zpos = DEFAULT_ZPOS;
462
463         DRM_DEBUG_KMS("%s\n", __FILE__);
464
465         if (data)
466                 zpos = *(int *)data;
467
468         if (overlay_ops && overlay_ops->enable)
469                 overlay_ops->enable(manager->dev, zpos);
470 }
471
472 void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data)
473 {
474         struct exynos_drm_manager *manager =
475                 to_exynos_encoder(encoder)->manager;
476         struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
477         int zpos = DEFAULT_ZPOS;
478
479         DRM_DEBUG_KMS("%s\n", __FILE__);
480
481         if (data)
482                 zpos = *(int *)data;
483
484         if (overlay_ops && overlay_ops->disable)
485                 overlay_ops->disable(manager->dev, zpos);
486
487         /*
488          * wait for vblank interrupt
489          * - this makes sure that hardware overlay is disabled to avoid
490          * for the dma accesses to memory after gem buffer was released
491          * because the setting for disabling the overlay will be updated
492          * at vsync.
493          */
494         if (overlay_ops->wait_for_vblank)
495                 overlay_ops->wait_for_vblank(manager->dev);
496 }