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 "drmP.h" 28#include "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_drv.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 39static void 40nv50_sor_disconnect(struct drm_encoder *encoder) 41{ 42 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 43 struct drm_device *dev = encoder->dev; 44 struct drm_nouveau_private *dev_priv = dev->dev_private; 45 struct nouveau_channel *evo = dev_priv->evo; 46 int ret; 47 48 if (!nv_encoder->crtc) 49 return; 50 nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true); 51 52 NV_DEBUG_KMS(dev, "Disconnecting SOR %d\n", nv_encoder->or); 53 54 ret = RING_SPACE(evo, 4); 55 if (ret) { 56 NV_ERROR(dev, "no space while disconnecting SOR\n"); 57 return; 58 } 59 BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1); 60 OUT_RING (evo, 0); 61 BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); 62 OUT_RING (evo, 0); 63 64 nv_encoder->crtc = NULL; 65 nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; 66} 67 68static void 69nv50_sor_dpms(struct drm_encoder *encoder, int mode) 70{ 71 struct drm_device *dev = encoder->dev; 72 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 73 struct drm_encoder *enc; 74 uint32_t val; 75 int or = nv_encoder->or; 76 77 NV_DEBUG_KMS(dev, "or %d type %d mode %d\n", or, nv_encoder->dcb->type, mode); 78 79 nv_encoder->last_dpms = mode; 80 list_for_each_entry(enc, &dev->mode_config.encoder_list, head) { 81 struct nouveau_encoder *nvenc = nouveau_encoder(enc); 82 83 if (nvenc == nv_encoder || 84 (nvenc->dcb->type != OUTPUT_TMDS && 85 nvenc->dcb->type != OUTPUT_LVDS && 86 nvenc->dcb->type != OUTPUT_DP) || 87 nvenc->dcb->or != nv_encoder->dcb->or) 88 continue; 89 90 if (nvenc->last_dpms == DRM_MODE_DPMS_ON) 91 return; 92 } 93 94 /* wait for it to be done */ 95 if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_CTRL(or), 96 NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING, 0)) { 97 NV_ERROR(dev, "timeout: SOR_DPMS_CTRL_PENDING(%d) == 0\n", or); 98 NV_ERROR(dev, "SOR_DPMS_CTRL(%d) = 0x%08x\n", or, 99 nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or))); 100 } 101 102 val = nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or)); 103 104 if (mode == DRM_MODE_DPMS_ON) 105 val |= NV50_PDISPLAY_SOR_DPMS_CTRL_ON; 106 else 107 val &= ~NV50_PDISPLAY_SOR_DPMS_CTRL_ON; 108 109 nv_wr32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or), val | 110 NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING); 111 if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_STATE(or), 112 NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) { 113 NV_ERROR(dev, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", or); 114 NV_ERROR(dev, "SOR_DPMS_STATE(%d) = 0x%08x\n", or, 115 nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_STATE(or))); 116 } 117 118 if (nv_encoder->dcb->type == OUTPUT_DP) { 119 struct nouveau_i2c_chan *auxch; 120 121 auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); 122 if (!auxch) 123 return; 124 125 if (mode == DRM_MODE_DPMS_ON) { 126 u8 status = DP_SET_POWER_D0; 127 nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1); 128 nouveau_dp_link_train(encoder); 129 } else { 130 u8 status = DP_SET_POWER_D3; 131 nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1); 132 } 133 } 134} 135 136static void 137nv50_sor_save(struct drm_encoder *encoder) 138{ 139 NV_ERROR(encoder->dev, "!!\n"); 140} 141 142static void 143nv50_sor_restore(struct drm_encoder *encoder) 144{ 145 NV_ERROR(encoder->dev, "!!\n"); 146} 147 148static bool 149nv50_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, 150 struct drm_display_mode *adjusted_mode) 151{ 152 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 153 struct nouveau_connector *connector; 154 155 NV_DEBUG_KMS(encoder->dev, "or %d\n", nv_encoder->or); 156 157 connector = nouveau_encoder_connector_get(nv_encoder); 158 if (!connector) { 159 NV_ERROR(encoder->dev, "Encoder has no connector\n"); 160 return false; 161 } 162 163 if (connector->scaling_mode != DRM_MODE_SCALE_NONE && 164 connector->native_mode) { 165 int id = adjusted_mode->base.id; 166 *adjusted_mode = *connector->native_mode; 167 adjusted_mode->base.id = id; 168 } 169 170 return true; 171} 172 173static void 174nv50_sor_prepare(struct drm_encoder *encoder) 175{ 176} 177 178static void 179nv50_sor_commit(struct drm_encoder *encoder) 180{ 181} 182 183static void 184nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, 185 struct drm_display_mode *adjusted_mode) 186{ 187 struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; 188 struct nouveau_channel *evo = dev_priv->evo; 189 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 190 struct drm_device *dev = encoder->dev; 191 struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); 192 uint32_t mode_ctl = 0; 193 int ret; 194 195 NV_DEBUG_KMS(dev, "or %d type %d -> crtc %d\n", 196 nv_encoder->or, nv_encoder->dcb->type, crtc->index); 197 198 nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON); 199 200 switch (nv_encoder->dcb->type) { 201 case OUTPUT_TMDS: 202 if (nv_encoder->dcb->sorconf.link & 1) { 203 if (adjusted_mode->clock < 165000) 204 mode_ctl = 0x0100; 205 else 206 mode_ctl = 0x0500; 207 } else 208 mode_ctl = 0x0200; 209 break; 210 case OUTPUT_DP: 211 mode_ctl |= (nv_encoder->dp.mc_unknown << 16); 212 if (nv_encoder->dcb->sorconf.link & 1) 213 mode_ctl |= 0x00000800; 214 else 215 mode_ctl |= 0x00000900; 216 break; 217 default: 218 break; 219 } 220 221 if (crtc->index == 1) 222 mode_ctl |= NV50_EVO_SOR_MODE_CTRL_CRTC1; 223 else 224 mode_ctl |= NV50_EVO_SOR_MODE_CTRL_CRTC0; 225 226 if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) 227 mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NHSYNC; 228 229 if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) 230 mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NVSYNC; 231 232 ret = RING_SPACE(evo, 2); 233 if (ret) { 234 NV_ERROR(dev, "no space while connecting SOR\n"); 235 return; 236 } 237 BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1); 238 OUT_RING(evo, mode_ctl); 239 240 nv_encoder->crtc = encoder->crtc; 241} 242 243static struct drm_crtc * 244nv50_sor_crtc_get(struct drm_encoder *encoder) 245{ 246 return nouveau_encoder(encoder)->crtc; 247} 248 249static const struct drm_encoder_helper_funcs nv50_sor_helper_funcs = { 250 .dpms = nv50_sor_dpms, 251 .save = nv50_sor_save, 252 .restore = nv50_sor_restore, 253 .mode_fixup = nv50_sor_mode_fixup, 254 .prepare = nv50_sor_prepare, 255 .commit = nv50_sor_commit, 256 .mode_set = nv50_sor_mode_set, 257 .get_crtc = nv50_sor_crtc_get, 258 .detect = NULL, 259 .disable = nv50_sor_disconnect 260}; 261 262static void 263nv50_sor_destroy(struct drm_encoder *encoder) 264{ 265 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 266 267 if (!encoder) 268 return; 269 270 NV_DEBUG_KMS(encoder->dev, "\n"); 271 272 drm_encoder_cleanup(encoder); 273 274 kfree(nv_encoder); 275} 276 277static const struct drm_encoder_funcs nv50_sor_encoder_funcs = { 278 .destroy = nv50_sor_destroy, 279}; 280 281int 282nv50_sor_create(struct drm_connector *connector, struct dcb_entry *entry) 283{ 284 struct nouveau_encoder *nv_encoder = NULL; 285 struct drm_device *dev = connector->dev; 286 struct drm_encoder *encoder; 287 int type; 288 289 NV_DEBUG_KMS(dev, "\n"); 290 291 switch (entry->type) { 292 case OUTPUT_TMDS: 293 case OUTPUT_DP: 294 type = DRM_MODE_ENCODER_TMDS; 295 break; 296 case OUTPUT_LVDS: 297 type = DRM_MODE_ENCODER_LVDS; 298 break; 299 default: 300 return -EINVAL; 301 } 302 303 nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); 304 if (!nv_encoder) 305 return -ENOMEM; 306 encoder = to_drm_encoder(nv_encoder); 307 308 nv_encoder->dcb = entry; 309 nv_encoder->or = ffs(entry->or) - 1; 310 nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; 311 312 drm_encoder_init(dev, encoder, &nv50_sor_encoder_funcs, type); 313 drm_encoder_helper_add(encoder, &nv50_sor_helper_funcs); 314 315 encoder->possible_crtcs = entry->heads; 316 encoder->possible_clones = 0; 317 318 if (nv_encoder->dcb->type == OUTPUT_DP) { 319 int or = nv_encoder->or, link = !(entry->dpconf.sor.link & 1); 320 uint32_t tmp; 321 322 tmp = nv_rd32(dev, 0x61c700 + (or * 0x800)); 323 324 switch ((tmp & 0x00000f00) >> 8) { 325 case 8: 326 case 9: 327 nv_encoder->dp.mc_unknown = (tmp & 0x000f0000) >> 16; 328 tmp = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); 329 nv_encoder->dp.unk0 = tmp & 0x000001fc; 330 tmp = nv_rd32(dev, NV50_SOR_DP_UNK128(or, link)); 331 nv_encoder->dp.unk1 = tmp & 0x010f7f3f; 332 break; 333 default: 334 break; 335 } 336 337 if (!nv_encoder->dp.mc_unknown) 338 nv_encoder->dp.mc_unknown = 5; 339 } 340 341 drm_mode_connector_attach_encoder(connector, encoder); 342 return 0; 343} 344