drm/nvd0/disp: implement support for colour vibrance control
[platform/kernel/linux-rpi.git] / drivers / gpu / drm / nouveau / nv50_sor.c
1 /*
2  * Copyright (C) 2008 Maarten Maathuis.
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial
15  * portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  *
25  */
26
27 #include <drm/drmP.h>
28 #include <drm/drm_crtc_helper.h>
29
30 #define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO)
31 #include "nouveau_reg.h"
32 #include "nouveau_drm.h"
33 #include "nouveau_dma.h"
34 #include "nouveau_encoder.h"
35 #include "nouveau_connector.h"
36 #include "nouveau_crtc.h"
37 #include "nv50_display.h"
38
39 #include <core/class.h>
40
41 #include <subdev/timer.h>
42
43 static void
44 nv50_sor_disconnect(struct drm_encoder *encoder)
45 {
46         struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
47         struct nouveau_drm *drm = nouveau_drm(encoder->dev);
48         struct drm_device *dev = encoder->dev;
49         struct nouveau_channel *evo = nv50_display(dev)->master;
50         int ret;
51
52         if (!nv_encoder->crtc)
53                 return;
54         nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true);
55
56         NV_DEBUG(drm, "Disconnecting SOR %d\n", nv_encoder->or);
57
58         ret = RING_SPACE(evo, 4);
59         if (ret) {
60                 NV_ERROR(drm, "no space while disconnecting SOR\n");
61                 return;
62         }
63         BEGIN_NV04(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1);
64         OUT_RING  (evo, 0);
65         BEGIN_NV04(evo, 0, NV50_EVO_UPDATE, 1);
66         OUT_RING  (evo, 0);
67
68         nouveau_hdmi_mode_set(encoder, NULL);
69
70         nv_encoder->crtc = NULL;
71         nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
72 }
73
74 static void
75 nv50_sor_dpms(struct drm_encoder *encoder, int mode)
76 {
77         struct nv50_display *priv = nv50_display(encoder->dev);
78         struct nouveau_drm *drm = nouveau_drm(encoder->dev);
79         struct drm_device *dev = encoder->dev;
80         struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
81         struct drm_encoder *enc;
82         int or = nv_encoder->or;
83
84         NV_DEBUG(drm, "or %d type %d mode %d\n", or, nv_encoder->dcb->type, mode);
85
86         nv_encoder->last_dpms = mode;
87         list_for_each_entry(enc, &dev->mode_config.encoder_list, head) {
88                 struct nouveau_encoder *nvenc = nouveau_encoder(enc);
89
90                 if (nvenc == nv_encoder ||
91                     (nvenc->dcb->type != DCB_OUTPUT_TMDS &&
92                      nvenc->dcb->type != DCB_OUTPUT_LVDS &&
93                      nvenc->dcb->type != DCB_OUTPUT_DP) ||
94                     nvenc->dcb->or != nv_encoder->dcb->or)
95                         continue;
96
97                 if (nvenc->last_dpms == DRM_MODE_DPMS_ON)
98                         return;
99         }
100
101         nv_call(priv->core, NV50_DISP_SOR_PWR + or, (mode == DRM_MODE_DPMS_ON));
102
103         if (nv_encoder->dcb->type == DCB_OUTPUT_DP)
104                 nouveau_dp_dpms(encoder, mode, nv_encoder->dp.datarate, priv->core);
105 }
106
107 static void
108 nv50_sor_save(struct drm_encoder *encoder)
109 {
110         struct nouveau_drm *drm = nouveau_drm(encoder->dev);
111         NV_ERROR(drm, "!!\n");
112 }
113
114 static void
115 nv50_sor_restore(struct drm_encoder *encoder)
116 {
117         struct nouveau_drm *drm = nouveau_drm(encoder->dev);
118         NV_ERROR(drm, "!!\n");
119 }
120
121 static bool
122 nv50_sor_mode_fixup(struct drm_encoder *encoder,
123                     const struct drm_display_mode *mode,
124                     struct drm_display_mode *adjusted_mode)
125 {
126         struct nouveau_drm *drm = nouveau_drm(encoder->dev);
127         struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
128         struct nouveau_connector *connector;
129
130         NV_DEBUG(drm, "or %d\n", nv_encoder->or);
131
132         connector = nouveau_encoder_connector_get(nv_encoder);
133         if (!connector) {
134                 NV_ERROR(drm, "Encoder has no connector\n");
135                 return false;
136         }
137
138         if (connector->scaling_mode != DRM_MODE_SCALE_NONE &&
139              connector->native_mode)
140                 drm_mode_copy(adjusted_mode, connector->native_mode);
141
142         return true;
143 }
144
145 static void
146 nv50_sor_prepare(struct drm_encoder *encoder)
147 {
148         struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
149         nv50_sor_disconnect(encoder);
150         if (nv_encoder->dcb->type == DCB_OUTPUT_DP) {
151                 /* avoid race between link training and supervisor intr */
152                 nv50_display_sync(encoder->dev);
153         }
154 }
155
156 static void
157 nv50_sor_commit(struct drm_encoder *encoder)
158 {
159 }
160
161 static void
162 nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
163                   struct drm_display_mode *mode)
164 {
165         struct nouveau_channel *evo = nv50_display(encoder->dev)->master;
166         struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
167         struct nouveau_drm *drm = nouveau_drm(encoder->dev);
168         struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc);
169         struct nouveau_connector *nv_connector;
170         struct nv50_display *disp = nv50_display(encoder->dev);
171         struct nvbios *bios = &drm->vbios;
172         uint32_t mode_ctl = 0, script;
173         int ret;
174
175         NV_DEBUG(drm, "or %d type %d -> crtc %d\n",
176                      nv_encoder->or, nv_encoder->dcb->type, crtc->index);
177         nv_encoder->crtc = encoder->crtc;
178
179         switch (nv_encoder->dcb->type) {
180         case DCB_OUTPUT_TMDS:
181                 if (nv_encoder->dcb->sorconf.link & 1) {
182                         if (mode->clock < 165000)
183                                 mode_ctl = 0x0100;
184                         else
185                                 mode_ctl = 0x0500;
186                 } else
187                         mode_ctl = 0x0200;
188
189                 nouveau_hdmi_mode_set(encoder, mode);
190                 break;
191         case DCB_OUTPUT_LVDS:
192                 script = 0x0000;
193                 if (bios->fp_no_ddc) {
194                         if (bios->fp.dual_link)
195                                 script |= 0x0100;
196                         if (bios->fp.if_is_24bit)
197                                 script |= 0x0200;
198                 } else {
199                         /* determine number of lvds links */
200                         nv_connector = nouveau_encoder_connector_get(nv_encoder);
201                         if (nv_connector && nv_connector->edid &&
202                             nv_connector->type == DCB_CONNECTOR_LVDS_SPWG) {
203                                 /* http://www.spwg.org */
204                                 if (((u8 *)nv_connector->edid)[121] == 2)
205                                         script |= 0x0100;
206                         } else
207                         if (mode->clock >= bios->fp.duallink_transition_clk) {
208                                 script |= 0x0100;
209                         }
210
211                         /* determine panel depth */
212                         if (script & 0x0100) {
213                                 if (bios->fp.strapless_is_24bit & 2)
214                                         script |= 0x0200;
215                         } else {
216                                 if (bios->fp.strapless_is_24bit & 1)
217                                         script |= 0x0200;
218                         }
219
220                         if (nv_connector && nv_connector->edid &&
221                             (nv_connector->edid->revision >= 4) &&
222                             (nv_connector->edid->input & 0x70) >= 0x20)
223                                 script |= 0x0200;
224                 }
225
226                 nv_call(disp->core, NV50_DISP_SOR_LVDS_SCRIPT + nv_encoder->or, script);
227                 break;
228         case DCB_OUTPUT_DP:
229                 nv_connector = nouveau_encoder_connector_get(nv_encoder);
230                 if (nv_connector && nv_connector->base.display_info.bpc == 6) {
231                         nv_encoder->dp.datarate = mode->clock * 18 / 8;
232                         mode_ctl |= 0x00020000;
233                 } else {
234                         nv_encoder->dp.datarate = mode->clock * 24 / 8;
235                         mode_ctl |= 0x00050000;
236                 }
237
238                 if (nv_encoder->dcb->sorconf.link & 1)
239                         mode_ctl |= 0x00000800;
240                 else
241                         mode_ctl |= 0x00000900;
242                 break;
243         default:
244                 break;
245         }
246
247         if (crtc->index == 1)
248                 mode_ctl |= NV50_EVO_SOR_MODE_CTRL_CRTC1;
249         else
250                 mode_ctl |= NV50_EVO_SOR_MODE_CTRL_CRTC0;
251
252         if (mode->flags & DRM_MODE_FLAG_NHSYNC)
253                 mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NHSYNC;
254
255         if (mode->flags & DRM_MODE_FLAG_NVSYNC)
256                 mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NVSYNC;
257
258         nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON);
259
260         ret = RING_SPACE(evo, 2);
261         if (ret) {
262                 NV_ERROR(drm, "no space while connecting SOR\n");
263                 nv_encoder->crtc = NULL;
264                 return;
265         }
266         BEGIN_NV04(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1);
267         OUT_RING(evo, mode_ctl);
268 }
269
270 static struct drm_crtc *
271 nv50_sor_crtc_get(struct drm_encoder *encoder)
272 {
273         return nouveau_encoder(encoder)->crtc;
274 }
275
276 static const struct drm_encoder_helper_funcs nv50_sor_helper_funcs = {
277         .dpms = nv50_sor_dpms,
278         .save = nv50_sor_save,
279         .restore = nv50_sor_restore,
280         .mode_fixup = nv50_sor_mode_fixup,
281         .prepare = nv50_sor_prepare,
282         .commit = nv50_sor_commit,
283         .mode_set = nv50_sor_mode_set,
284         .get_crtc = nv50_sor_crtc_get,
285         .detect = NULL,
286         .disable = nv50_sor_disconnect
287 };
288
289 static void
290 nv50_sor_destroy(struct drm_encoder *encoder)
291 {
292         struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
293
294         drm_encoder_cleanup(encoder);
295         kfree(nv_encoder);
296 }
297
298 static const struct drm_encoder_funcs nv50_sor_encoder_funcs = {
299         .destroy = nv50_sor_destroy,
300 };
301
302 int
303 nv50_sor_create(struct drm_connector *connector, struct dcb_output *entry)
304 {
305         struct nouveau_encoder *nv_encoder = NULL;
306         struct drm_device *dev = connector->dev;
307         struct drm_encoder *encoder;
308         int type;
309
310         switch (entry->type) {
311         case DCB_OUTPUT_TMDS:
312         case DCB_OUTPUT_DP:
313                 type = DRM_MODE_ENCODER_TMDS;
314                 break;
315         case DCB_OUTPUT_LVDS:
316                 type = DRM_MODE_ENCODER_LVDS;
317                 break;
318         default:
319                 return -EINVAL;
320         }
321
322         nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
323         if (!nv_encoder)
324                 return -ENOMEM;
325         encoder = to_drm_encoder(nv_encoder);
326
327         nv_encoder->dcb = entry;
328         nv_encoder->or = ffs(entry->or) - 1;
329         nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
330
331         drm_encoder_init(dev, encoder, &nv50_sor_encoder_funcs, type);
332         drm_encoder_helper_add(encoder, &nv50_sor_helper_funcs);
333
334         encoder->possible_crtcs = entry->heads;
335         encoder->possible_clones = 0;
336
337         drm_mode_connector_attach_encoder(connector, encoder);
338         return 0;
339 }