Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / 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  * 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_drv.h"
19 #include "exynos_drm_encoder.h"
20
21 #define to_exynos_encoder(x)    container_of(x, struct exynos_drm_encoder,\
22                                 drm_encoder)
23
24 /*
25  * exynos specific encoder structure.
26  *
27  * @drm_encoder: encoder object.
28  * @display: the display structure that maps to this encoder
29  */
30 struct exynos_drm_encoder {
31         struct drm_encoder              drm_encoder;
32         struct exynos_drm_display       *display;
33 };
34
35 static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
36 {
37         struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
38         struct exynos_drm_display *display = exynos_encoder->display;
39
40         DRM_DEBUG_KMS("encoder dpms: %d\n", mode);
41
42         if (display->ops->dpms)
43                 display->ops->dpms(display, mode);
44 }
45
46 static bool
47 exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder,
48                                const struct drm_display_mode *mode,
49                                struct drm_display_mode *adjusted_mode)
50 {
51         struct drm_device *dev = encoder->dev;
52         struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
53         struct exynos_drm_display *display = exynos_encoder->display;
54         struct drm_connector *connector;
55
56         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
57                 if (connector->encoder != encoder)
58                         continue;
59
60                 if (display->ops->mode_fixup)
61                         display->ops->mode_fixup(display, connector, mode,
62                                         adjusted_mode);
63         }
64
65         return true;
66 }
67
68 static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
69                                          struct drm_display_mode *mode,
70                                          struct drm_display_mode *adjusted_mode)
71 {
72         struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
73         struct exynos_drm_display *display = exynos_encoder->display;
74
75         if (display->ops->mode_set)
76                 display->ops->mode_set(display, adjusted_mode);
77 }
78
79 static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
80 {
81         /* drm framework doesn't check NULL. */
82 }
83
84 static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
85 {
86         struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
87         struct exynos_drm_display *display = exynos_encoder->display;
88
89         if (display->ops->dpms)
90                 display->ops->dpms(display, DRM_MODE_DPMS_ON);
91
92         if (display->ops->commit)
93                 display->ops->commit(display);
94 }
95
96 static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
97 {
98         struct drm_plane *plane;
99         struct drm_device *dev = encoder->dev;
100
101         exynos_drm_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
102
103         /* all planes connected to this encoder should be also disabled. */
104         drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) {
105                 if (plane->crtc && (plane->crtc == encoder->crtc))
106                         plane->funcs->disable_plane(plane);
107         }
108 }
109
110 static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = {
111         .dpms           = exynos_drm_encoder_dpms,
112         .mode_fixup     = exynos_drm_encoder_mode_fixup,
113         .mode_set       = exynos_drm_encoder_mode_set,
114         .prepare        = exynos_drm_encoder_prepare,
115         .commit         = exynos_drm_encoder_commit,
116         .disable        = exynos_drm_encoder_disable,
117 };
118
119 static void exynos_drm_encoder_destroy(struct drm_encoder *encoder)
120 {
121         struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
122
123         drm_encoder_cleanup(encoder);
124         kfree(exynos_encoder);
125 }
126
127 static struct drm_encoder_funcs exynos_encoder_funcs = {
128         .destroy = exynos_drm_encoder_destroy,
129 };
130
131 static unsigned int exynos_drm_encoder_clones(struct drm_encoder *encoder)
132 {
133         struct drm_encoder *clone;
134         struct drm_device *dev = encoder->dev;
135         struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
136         struct exynos_drm_display *display = exynos_encoder->display;
137         unsigned int clone_mask = 0;
138         int cnt = 0;
139
140         list_for_each_entry(clone, &dev->mode_config.encoder_list, head) {
141                 switch (display->type) {
142                 case EXYNOS_DISPLAY_TYPE_LCD:
143                 case EXYNOS_DISPLAY_TYPE_HDMI:
144                 case EXYNOS_DISPLAY_TYPE_VIDI:
145                         clone_mask |= (1 << (cnt++));
146                         break;
147                 default:
148                         continue;
149                 }
150         }
151
152         return clone_mask;
153 }
154
155 void exynos_drm_encoder_setup(struct drm_device *dev)
156 {
157         struct drm_encoder *encoder;
158
159         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
160                 encoder->possible_clones = exynos_drm_encoder_clones(encoder);
161 }
162
163 struct drm_encoder *
164 exynos_drm_encoder_create(struct drm_device *dev,
165                            struct exynos_drm_display *display,
166                            unsigned long possible_crtcs)
167 {
168         struct drm_encoder *encoder;
169         struct exynos_drm_encoder *exynos_encoder;
170
171         if (!possible_crtcs)
172                 return NULL;
173
174         exynos_encoder = kzalloc(sizeof(*exynos_encoder), GFP_KERNEL);
175         if (!exynos_encoder)
176                 return NULL;
177
178         exynos_encoder->display = display;
179         encoder = &exynos_encoder->drm_encoder;
180         encoder->possible_crtcs = possible_crtcs;
181
182         DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
183
184         drm_encoder_init(dev, encoder, &exynos_encoder_funcs,
185                         DRM_MODE_ENCODER_TMDS);
186
187         drm_encoder_helper_add(encoder, &exynos_encoder_helper_funcs);
188
189         DRM_DEBUG_KMS("encoder has been created\n");
190
191         return encoder;
192 }
193
194 struct exynos_drm_display *exynos_drm_get_display(struct drm_encoder *encoder)
195 {
196         return to_exynos_encoder(encoder)->display;
197 }