2 * Copyright (C) 2008 Maarten Maathuis.
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:
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.
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.
28 #include <drm/drm_crtc_helper.h>
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"
39 #include <core/class.h>
41 #include <subdev/timer.h>
44 nv50_sor_disconnect(struct drm_encoder *encoder)
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;
52 if (!nv_encoder->crtc)
54 nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true);
56 NV_DEBUG(drm, "Disconnecting SOR %d\n", nv_encoder->or);
58 ret = RING_SPACE(evo, 4);
60 NV_ERROR(drm, "no space while disconnecting SOR\n");
63 BEGIN_NV04(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1);
65 BEGIN_NV04(evo, 0, NV50_EVO_UPDATE, 1);
68 nouveau_hdmi_mode_set(encoder, NULL);
70 nv_encoder->crtc = NULL;
71 nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
75 nv50_sor_dpms(struct drm_encoder *encoder, int mode)
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;
84 NV_DEBUG(drm, "or %d type %d mode %d\n", or, nv_encoder->dcb->type, mode);
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);
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)
97 if (nvenc->last_dpms == DRM_MODE_DPMS_ON)
101 nv_call(priv->core, NV50_DISP_SOR_PWR + or, (mode == DRM_MODE_DPMS_ON));
103 if (nv_encoder->dcb->type == DCB_OUTPUT_DP)
104 nouveau_dp_dpms(encoder, mode, nv_encoder->dp.datarate, priv->core);
108 nv50_sor_save(struct drm_encoder *encoder)
110 struct nouveau_drm *drm = nouveau_drm(encoder->dev);
111 NV_ERROR(drm, "!!\n");
115 nv50_sor_restore(struct drm_encoder *encoder)
117 struct nouveau_drm *drm = nouveau_drm(encoder->dev);
118 NV_ERROR(drm, "!!\n");
122 nv50_sor_mode_fixup(struct drm_encoder *encoder,
123 const struct drm_display_mode *mode,
124 struct drm_display_mode *adjusted_mode)
126 struct nouveau_drm *drm = nouveau_drm(encoder->dev);
127 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
128 struct nouveau_connector *connector;
130 NV_DEBUG(drm, "or %d\n", nv_encoder->or);
132 connector = nouveau_encoder_connector_get(nv_encoder);
134 NV_ERROR(drm, "Encoder has no connector\n");
138 if (connector->scaling_mode != DRM_MODE_SCALE_NONE &&
139 connector->native_mode)
140 drm_mode_copy(adjusted_mode, connector->native_mode);
146 nv50_sor_prepare(struct drm_encoder *encoder)
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);
157 nv50_sor_commit(struct drm_encoder *encoder)
162 nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
163 struct drm_display_mode *mode)
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;
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;
179 switch (nv_encoder->dcb->type) {
180 case DCB_OUTPUT_TMDS:
181 if (nv_encoder->dcb->sorconf.link & 1) {
182 if (mode->clock < 165000)
189 nouveau_hdmi_mode_set(encoder, mode);
191 case DCB_OUTPUT_LVDS:
193 if (bios->fp_no_ddc) {
194 if (bios->fp.dual_link)
196 if (bios->fp.if_is_24bit)
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)
207 if (mode->clock >= bios->fp.duallink_transition_clk) {
211 /* determine panel depth */
212 if (script & 0x0100) {
213 if (bios->fp.strapless_is_24bit & 2)
216 if (bios->fp.strapless_is_24bit & 1)
220 if (nv_connector && nv_connector->edid &&
221 (nv_connector->edid->revision >= 4) &&
222 (nv_connector->edid->input & 0x70) >= 0x20)
226 nv_call(disp->core, NV50_DISP_SOR_LVDS_SCRIPT + nv_encoder->or, script);
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;
234 nv_encoder->dp.datarate = mode->clock * 24 / 8;
235 mode_ctl |= 0x00050000;
238 if (nv_encoder->dcb->sorconf.link & 1)
239 mode_ctl |= 0x00000800;
241 mode_ctl |= 0x00000900;
247 if (crtc->index == 1)
248 mode_ctl |= NV50_EVO_SOR_MODE_CTRL_CRTC1;
250 mode_ctl |= NV50_EVO_SOR_MODE_CTRL_CRTC0;
252 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
253 mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NHSYNC;
255 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
256 mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NVSYNC;
258 nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON);
260 ret = RING_SPACE(evo, 2);
262 NV_ERROR(drm, "no space while connecting SOR\n");
263 nv_encoder->crtc = NULL;
266 BEGIN_NV04(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1);
267 OUT_RING(evo, mode_ctl);
270 static struct drm_crtc *
271 nv50_sor_crtc_get(struct drm_encoder *encoder)
273 return nouveau_encoder(encoder)->crtc;
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,
286 .disable = nv50_sor_disconnect
290 nv50_sor_destroy(struct drm_encoder *encoder)
292 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
294 drm_encoder_cleanup(encoder);
298 static const struct drm_encoder_funcs nv50_sor_encoder_funcs = {
299 .destroy = nv50_sor_destroy,
303 nv50_sor_create(struct drm_connector *connector, struct dcb_output *entry)
305 struct nouveau_encoder *nv_encoder = NULL;
306 struct drm_device *dev = connector->dev;
307 struct drm_encoder *encoder;
310 switch (entry->type) {
311 case DCB_OUTPUT_TMDS:
313 type = DRM_MODE_ENCODER_TMDS;
315 case DCB_OUTPUT_LVDS:
316 type = DRM_MODE_ENCODER_LVDS;
322 nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
325 encoder = to_drm_encoder(nv_encoder);
327 nv_encoder->dcb = entry;
328 nv_encoder->or = ffs(entry->or) - 1;
329 nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
331 drm_encoder_init(dev, encoder, &nv50_sor_encoder_funcs, type);
332 drm_encoder_helper_add(encoder, &nv50_sor_helper_funcs);
334 encoder->possible_crtcs = entry->heads;
335 encoder->possible_clones = 0;
337 drm_mode_connector_attach_encoder(connector, encoder);