bf6e597d3d2d1df7959fada8c680fefa97b47c50
[cascardo/linux.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_crtc.h"
34 #include "exynos_drm_encoder.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_encoder              drm_encoder;
49         struct exynos_drm_manager       *manager;
50         int dpms;
51 };
52
53 static void exynos_drm_display_power(struct drm_encoder *encoder, int mode)
54 {
55         struct drm_device *dev = encoder->dev;
56         struct drm_connector *connector;
57         struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
58         struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
59
60         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
61                 if (connector->encoder == encoder) {
62                         struct exynos_drm_display_ops *display_ops =
63                                                         manager->display_ops;
64
65                         DRM_DEBUG_KMS("connector[%d] dpms[%d]\n",
66                                         connector->base.id, mode);
67                         if (display_ops && display_ops->power_on)
68                                 display_ops->power_on(manager->dev, mode);
69                         exynos_encoder->dpms = mode;
70                 }
71         }
72 }
73
74 static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
75 {
76         struct drm_device *dev = encoder->dev;
77         struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
78         struct exynos_drm_manager_ops *manager_ops = manager->ops;
79         struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
80
81         DRM_DEBUG_KMS("%s, encoder dpms: %d\n", __FILE__, mode);
82
83         mutex_lock(&dev->struct_mutex);
84
85         if (exynos_encoder->dpms == mode) {
86                 DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
87                 mutex_unlock(&dev->struct_mutex);
88                 return;
89         }
90
91         switch (mode) {
92         case DRM_MODE_DPMS_ON:
93                 if (manager_ops && manager_ops->apply)
94                         manager_ops->apply(manager->dev);
95                 exynos_drm_display_power(encoder, mode);
96                 break;
97         case DRM_MODE_DPMS_STANDBY:
98         case DRM_MODE_DPMS_SUSPEND:
99         case DRM_MODE_DPMS_OFF:
100                 exynos_drm_display_power(encoder, mode);
101                 break;
102         default:
103                 DRM_ERROR("unspecified mode %d\n", mode);
104                 break;
105         }
106
107         mutex_unlock(&dev->struct_mutex);
108 }
109
110 static bool
111 exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder,
112                                struct drm_display_mode *mode,
113                                struct drm_display_mode *adjusted_mode)
114 {
115         struct drm_device *dev = encoder->dev;
116         struct drm_connector *connector;
117         struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
118         struct exynos_drm_manager_ops *manager_ops = manager->ops;
119
120         DRM_DEBUG_KMS("%s\n", __FILE__);
121
122         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
123                 if (connector->encoder == encoder)
124                         if (manager_ops && manager_ops->mode_fixup)
125                                 manager_ops->mode_fixup(manager->dev, connector,
126                                                         mode, adjusted_mode);
127         }
128
129         return true;
130 }
131
132 static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
133                                          struct drm_display_mode *mode,
134                                          struct drm_display_mode *adjusted_mode)
135 {
136         struct drm_device *dev = encoder->dev;
137         struct drm_connector *connector;
138         struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
139         struct exynos_drm_manager_ops *manager_ops = manager->ops;
140         struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
141         struct exynos_drm_overlay *overlay = get_exynos_drm_overlay(dev,
142                                                 encoder->crtc);
143
144         DRM_DEBUG_KMS("%s\n", __FILE__);
145
146         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
147                 if (connector->encoder == encoder) {
148                         if (manager_ops && manager_ops->mode_set)
149                                 manager_ops->mode_set(manager->dev,
150                                                         adjusted_mode);
151
152                         if (overlay_ops && overlay_ops->mode_set)
153                                 overlay_ops->mode_set(manager->dev, overlay);
154                 }
155         }
156 }
157
158 static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
159 {
160         DRM_DEBUG_KMS("%s\n", __FILE__);
161
162         /* drm framework doesn't check NULL. */
163 }
164
165 static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
166 {
167         struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
168         struct exynos_drm_manager_ops *manager_ops = manager->ops;
169
170         DRM_DEBUG_KMS("%s\n", __FILE__);
171
172         if (manager_ops && manager_ops->commit)
173                 manager_ops->commit(manager->dev);
174 }
175
176 static struct drm_crtc *
177 exynos_drm_encoder_get_crtc(struct drm_encoder *encoder)
178 {
179         return encoder->crtc;
180 }
181
182 static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = {
183         .dpms           = exynos_drm_encoder_dpms,
184         .mode_fixup     = exynos_drm_encoder_mode_fixup,
185         .mode_set       = exynos_drm_encoder_mode_set,
186         .prepare        = exynos_drm_encoder_prepare,
187         .commit         = exynos_drm_encoder_commit,
188         .get_crtc       = exynos_drm_encoder_get_crtc,
189 };
190
191 static void exynos_drm_encoder_destroy(struct drm_encoder *encoder)
192 {
193         struct exynos_drm_encoder *exynos_encoder =
194                 to_exynos_encoder(encoder);
195
196         DRM_DEBUG_KMS("%s\n", __FILE__);
197
198         exynos_encoder->manager->pipe = -1;
199
200         drm_encoder_cleanup(encoder);
201         kfree(exynos_encoder);
202 }
203
204 static struct drm_encoder_funcs exynos_encoder_funcs = {
205         .destroy = exynos_drm_encoder_destroy,
206 };
207
208 static unsigned int exynos_drm_encoder_clones(struct drm_encoder *encoder)
209 {
210         struct drm_encoder *clone;
211         struct drm_device *dev = encoder->dev;
212         struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
213         struct exynos_drm_display_ops *display_ops =
214                                 exynos_encoder->manager->display_ops;
215         unsigned int clone_mask = 0;
216         int cnt = 0;
217
218         list_for_each_entry(clone, &dev->mode_config.encoder_list, head) {
219                 switch (display_ops->type) {
220                 case EXYNOS_DISPLAY_TYPE_LCD:
221                 case EXYNOS_DISPLAY_TYPE_HDMI:
222                 case EXYNOS_DISPLAY_TYPE_VIDI:
223                         clone_mask |= (1 << (cnt++));
224                         break;
225                 default:
226                         continue;
227                 }
228         }
229
230         return clone_mask;
231 }
232
233 void exynos_drm_encoder_setup(struct drm_device *dev)
234 {
235         struct drm_encoder *encoder;
236
237         DRM_DEBUG_KMS("%s\n", __FILE__);
238
239         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
240                 encoder->possible_clones = exynos_drm_encoder_clones(encoder);
241 }
242
243 struct drm_encoder *
244 exynos_drm_encoder_create(struct drm_device *dev,
245                            struct exynos_drm_manager *manager,
246                            unsigned int possible_crtcs)
247 {
248         struct drm_encoder *encoder;
249         struct exynos_drm_encoder *exynos_encoder;
250
251         DRM_DEBUG_KMS("%s\n", __FILE__);
252
253         if (!manager || !possible_crtcs)
254                 return NULL;
255
256         if (!manager->dev)
257                 return NULL;
258
259         exynos_encoder = kzalloc(sizeof(*exynos_encoder), GFP_KERNEL);
260         if (!exynos_encoder) {
261                 DRM_ERROR("failed to allocate encoder\n");
262                 return NULL;
263         }
264
265         exynos_encoder->dpms = DRM_MODE_DPMS_OFF;
266         exynos_encoder->manager = manager;
267         encoder = &exynos_encoder->drm_encoder;
268         encoder->possible_crtcs = possible_crtcs;
269
270         DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
271
272         drm_encoder_init(dev, encoder, &exynos_encoder_funcs,
273                         DRM_MODE_ENCODER_TMDS);
274
275         drm_encoder_helper_add(encoder, &exynos_encoder_helper_funcs);
276
277         DRM_DEBUG_KMS("encoder has been created\n");
278
279         return encoder;
280 }
281
282 struct exynos_drm_manager *exynos_drm_get_manager(struct drm_encoder *encoder)
283 {
284         return to_exynos_encoder(encoder)->manager;
285 }
286
287 void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data,
288                             void (*fn)(struct drm_encoder *, void *))
289 {
290         struct drm_device *dev = crtc->dev;
291         struct drm_encoder *encoder;
292         struct exynos_drm_private *private = dev->dev_private;
293         struct exynos_drm_manager *manager;
294
295         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
296                 /*
297                  * if crtc is detached from encoder, check pipe,
298                  * otherwise check crtc attached to encoder
299                  */
300                 if (!encoder->crtc) {
301                         manager = to_exynos_encoder(encoder)->manager;
302                         if (manager->pipe < 0 ||
303                                         private->crtc[manager->pipe] != crtc)
304                                 continue;
305                 } else {
306                         if (encoder->crtc != crtc)
307                                 continue;
308                 }
309
310                 fn(encoder, data);
311         }
312 }
313
314 void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data)
315 {
316         struct exynos_drm_manager *manager =
317                 to_exynos_encoder(encoder)->manager;
318         struct exynos_drm_manager_ops *manager_ops = manager->ops;
319         int crtc = *(int *)data;
320
321         if (manager->pipe == -1)
322                 manager->pipe = crtc;
323
324         if (manager_ops->enable_vblank)
325                 manager_ops->enable_vblank(manager->dev);
326 }
327
328 void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data)
329 {
330         struct exynos_drm_manager *manager =
331                 to_exynos_encoder(encoder)->manager;
332         struct exynos_drm_manager_ops *manager_ops = manager->ops;
333         int crtc = *(int *)data;
334
335         if (manager->pipe == -1)
336                 manager->pipe = crtc;
337
338         if (manager_ops->disable_vblank)
339                 manager_ops->disable_vblank(manager->dev);
340 }
341
342 void exynos_drm_encoder_crtc_plane_commit(struct drm_encoder *encoder,
343                                           void *data)
344 {
345         struct exynos_drm_manager *manager =
346                 to_exynos_encoder(encoder)->manager;
347         struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
348         int zpos = DEFAULT_ZPOS;
349
350         if (data)
351                 zpos = *(int *)data;
352
353         if (overlay_ops && overlay_ops->commit)
354                 overlay_ops->commit(manager->dev, zpos);
355 }
356
357 void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data)
358 {
359         struct exynos_drm_manager *manager =
360                 to_exynos_encoder(encoder)->manager;
361         int crtc = *(int *)data;
362         int zpos = DEFAULT_ZPOS;
363
364         DRM_DEBUG_KMS("%s\n", __FILE__);
365
366         /*
367          * when crtc is detached from encoder, this pipe is used
368          * to select manager operation
369          */
370         manager->pipe = crtc;
371
372         exynos_drm_encoder_crtc_plane_commit(encoder, &zpos);
373 }
374
375 void exynos_drm_encoder_dpms_from_crtc(struct drm_encoder *encoder, void *data)
376 {
377         int mode = *(int *)data;
378
379         DRM_DEBUG_KMS("%s\n", __FILE__);
380
381         exynos_drm_encoder_dpms(encoder, mode);
382 }
383
384 void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
385 {
386         struct drm_device *dev = encoder->dev;
387         struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
388         struct exynos_drm_manager *manager = exynos_encoder->manager;
389         struct exynos_drm_manager_ops *manager_ops = manager->ops;
390         struct drm_connector *connector;
391         int mode = *(int *)data;
392
393         DRM_DEBUG_KMS("%s\n", __FILE__);
394
395         if (manager_ops && manager_ops->dpms)
396                 manager_ops->dpms(manager->dev, mode);
397
398         /*
399          * set current dpms mode to the connector connected to
400          * current encoder. connector->dpms would be checked
401          * at drm_helper_connector_dpms()
402          */
403         list_for_each_entry(connector, &dev->mode_config.connector_list, head)
404                 if (connector->encoder == encoder)
405                         connector->dpms = mode;
406
407         /*
408          * if this condition is ok then it means that the crtc is already
409          * detached from encoder and last function for detaching is properly
410          * done, so clear pipe from manager to prevent repeated call.
411          */
412         if (mode > DRM_MODE_DPMS_ON) {
413                 if (!encoder->crtc)
414                         manager->pipe = -1;
415         }
416 }
417
418 void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data)
419 {
420         struct exynos_drm_manager *manager =
421                 to_exynos_encoder(encoder)->manager;
422         struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
423         struct exynos_drm_overlay *overlay = data;
424
425         if (overlay_ops && overlay_ops->mode_set)
426                 overlay_ops->mode_set(manager->dev, overlay);
427 }
428
429 void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data)
430 {
431         struct exynos_drm_manager *manager =
432                 to_exynos_encoder(encoder)->manager;
433         struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
434         int zpos = DEFAULT_ZPOS;
435
436         DRM_DEBUG_KMS("\n");
437
438         if (data)
439                 zpos = *(int *)data;
440
441         if (overlay_ops && overlay_ops->disable)
442                 overlay_ops->disable(manager->dev, zpos);
443 }
444
445 void exynos_drm_encoder_crtc_page_flip(struct drm_encoder *encoder, void *data)
446 {
447         struct exynos_drm_manager *manager =
448                 to_exynos_encoder(encoder)->manager;
449         struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
450         struct exynos_drm_overlay *overlay = data;
451
452         if (overlay_ops && overlay_ops->page_flip)
453                 overlay_ops->page_flip(manager->dev, overlay);
454 }