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_dac_disconnect(struct drm_encoder *encoder) 41{ 42 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 43 struct drm_device *dev = encoder->dev; 44 struct nouveau_channel *evo = nv50_display(dev)->master; 45 int ret; 46 47 if (!nv_encoder->crtc) 48 return; 49 nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true); 50 51 NV_DEBUG_KMS(dev, "Disconnecting DAC %d\n", nv_encoder->or); 52 53 ret = RING_SPACE(evo, 4); 54 if (ret) { 55 NV_ERROR(dev, "no space while disconnecting DAC\n"); 56 return; 57 } 58 BEGIN_RING(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 1); 59 OUT_RING (evo, 0); 60 BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); 61 OUT_RING (evo, 0); 62 63 nv_encoder->crtc = NULL; 64} 65 66static enum drm_connector_status 67nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) 68{ 69 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 70 struct drm_device *dev = encoder->dev; 71 struct drm_nouveau_private *dev_priv = dev->dev_private; 72 enum drm_connector_status status = connector_status_disconnected; 73 uint32_t dpms_state, load_pattern, load_state; 74 int or = nv_encoder->or; 75 76 nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(or), 0x00000001); 77 dpms_state = nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or)); 78 79 nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), 80 0x00150000 | NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); 81 if (!nv_wait(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), 82 NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) { 83 NV_ERROR(dev, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or); 84 NV_ERROR(dev, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or, 85 nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or))); 86 return status; 87 } 88 89 /* Use bios provided value if possible. */ 90 if (dev_priv->vbios.dactestval) { 91 load_pattern = dev_priv->vbios.dactestval; 92 NV_DEBUG_KMS(dev, "Using bios provided load_pattern of %d\n", 93 load_pattern); 94 } else { 95 load_pattern = 340; 96 NV_DEBUG_KMS(dev, "Using default load_pattern of %d\n", 97 load_pattern); 98 } 99 100 nv_wr32(dev, NV50_PDISPLAY_DAC_LOAD_CTRL(or), 101 NV50_PDISPLAY_DAC_LOAD_CTRL_ACTIVE | load_pattern); 102 mdelay(45); /* give it some time to process */ 103 load_state = nv_rd32(dev, NV50_PDISPLAY_DAC_LOAD_CTRL(or)); 104 105 nv_wr32(dev, NV50_PDISPLAY_DAC_LOAD_CTRL(or), 0); 106 nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), dpms_state | 107 NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); 108 109 if ((load_state & NV50_PDISPLAY_DAC_LOAD_CTRL_PRESENT) == 110 NV50_PDISPLAY_DAC_LOAD_CTRL_PRESENT) 111 status = connector_status_connected; 112 113 if (status == connector_status_connected) 114 NV_DEBUG_KMS(dev, "Load was detected on output with or %d\n", or); 115 else 116 NV_DEBUG_KMS(dev, "Load was not detected on output with or %d\n", or); 117 118 return status; 119} 120 121static void 122nv50_dac_dpms(struct drm_encoder *encoder, int mode) 123{ 124 struct drm_device *dev = encoder->dev; 125 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 126 uint32_t val; 127 int or = nv_encoder->or; 128 129 NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode); 130 131 /* wait for it to be done */ 132 if (!nv_wait(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), 133 NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) { 134 NV_ERROR(dev, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or); 135 NV_ERROR(dev, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or, 136 nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or))); 137 return; 138 } 139 140 val = nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or)) & ~0x7F; 141 142 if (mode != DRM_MODE_DPMS_ON) 143 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_BLANKED; 144 145 switch (mode) { 146 case DRM_MODE_DPMS_STANDBY: 147 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_HSYNC_OFF; 148 break; 149 case DRM_MODE_DPMS_SUSPEND: 150 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_VSYNC_OFF; 151 break; 152 case DRM_MODE_DPMS_OFF: 153 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_OFF; 154 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_HSYNC_OFF; 155 val |= NV50_PDISPLAY_DAC_DPMS_CTRL_VSYNC_OFF; 156 break; 157 default: 158 break; 159 } 160 161 nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), val | 162 NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); 163} 164 165static void 166nv50_dac_save(struct drm_encoder *encoder) 167{ 168 NV_ERROR(encoder->dev, "!!\n"); 169} 170 171static void 172nv50_dac_restore(struct drm_encoder *encoder) 173{ 174 NV_ERROR(encoder->dev, "!!\n"); 175} 176 177static bool 178nv50_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, 179 struct drm_display_mode *adjusted_mode) 180{ 181 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 182 struct nouveau_connector *connector; 183 184 NV_DEBUG_KMS(encoder->dev, "or %d\n", nv_encoder->or); 185 186 connector = nouveau_encoder_connector_get(nv_encoder); 187 if (!connector) { 188 NV_ERROR(encoder->dev, "Encoder has no connector\n"); 189 return false; 190 } 191 192 if (connector->scaling_mode != DRM_MODE_SCALE_NONE && 193 connector->native_mode) 194 drm_mode_copy(adjusted_mode, connector->native_mode); 195 196 return true; 197} 198 199static void 200nv50_dac_commit(struct drm_encoder *encoder) 201{ 202} 203 204static void 205nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, 206 struct drm_display_mode *adjusted_mode) 207{ 208 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 209 struct drm_device *dev = encoder->dev; 210 struct nouveau_channel *evo = nv50_display(dev)->master; 211 struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); 212 uint32_t mode_ctl = 0, mode_ctl2 = 0; 213 int ret; 214 215 NV_DEBUG_KMS(dev, "or %d type %d crtc %d\n", 216 nv_encoder->or, nv_encoder->dcb->type, crtc->index); 217 218 nv50_dac_dpms(encoder, DRM_MODE_DPMS_ON); 219 220 if (crtc->index == 1) 221 mode_ctl |= NV50_EVO_DAC_MODE_CTRL_CRTC1; 222 else 223 mode_ctl |= NV50_EVO_DAC_MODE_CTRL_CRTC0; 224 225 /* Lacking a working tv-out, this is not a 100% sure. */ 226 if (nv_encoder->dcb->type == OUTPUT_ANALOG) 227 mode_ctl |= 0x40; 228 else 229 if (nv_encoder->dcb->type == OUTPUT_TV) 230 mode_ctl |= 0x100; 231 232 if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) 233 mode_ctl2 |= NV50_EVO_DAC_MODE_CTRL2_NHSYNC; 234 235 if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) 236 mode_ctl2 |= NV50_EVO_DAC_MODE_CTRL2_NVSYNC; 237 238 ret = RING_SPACE(evo, 3); 239 if (ret) { 240 NV_ERROR(dev, "no space while connecting DAC\n"); 241 return; 242 } 243 BEGIN_RING(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 2); 244 OUT_RING(evo, mode_ctl); 245 OUT_RING(evo, mode_ctl2); 246 247 nv_encoder->crtc = encoder->crtc; 248} 249 250static struct drm_crtc * 251nv50_dac_crtc_get(struct drm_encoder *encoder) 252{ 253 return nouveau_encoder(encoder)->crtc; 254} 255 256static const struct drm_encoder_helper_funcs nv50_dac_helper_funcs = { 257 .dpms = nv50_dac_dpms, 258 .save = nv50_dac_save, 259 .restore = nv50_dac_restore, 260 .mode_fixup = nv50_dac_mode_fixup, 261 .prepare = nv50_dac_disconnect, 262 .commit = nv50_dac_commit, 263 .mode_set = nv50_dac_mode_set, 264 .get_crtc = nv50_dac_crtc_get, 265 .detect = nv50_dac_detect, 266 .disable = nv50_dac_disconnect 267}; 268 269static void 270nv50_dac_destroy(struct drm_encoder *encoder) 271{ 272 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 273 274 if (!encoder) 275 return; 276 277 NV_DEBUG_KMS(encoder->dev, "\n"); 278 279 drm_encoder_cleanup(encoder); 280 kfree(nv_encoder); 281} 282 283static const struct drm_encoder_funcs nv50_dac_encoder_funcs = { 284 .destroy = nv50_dac_destroy, 285}; 286 287int 288nv50_dac_create(struct drm_connector *connector, struct dcb_entry *entry) 289{ 290 struct nouveau_encoder *nv_encoder; 291 struct drm_encoder *encoder; 292 293 nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); 294 if (!nv_encoder) 295 return -ENOMEM; 296 encoder = to_drm_encoder(nv_encoder); 297 298 nv_encoder->dcb = entry; 299 nv_encoder->or = ffs(entry->or) - 1; 300 301 drm_encoder_init(connector->dev, encoder, &nv50_dac_encoder_funcs, 302 DRM_MODE_ENCODER_DAC); 303 drm_encoder_helper_add(encoder, &nv50_dac_helper_funcs); 304 305 encoder->possible_crtcs = entry->heads; 306 encoder->possible_clones = 0; 307 308 drm_mode_connector_attach_encoder(connector, encoder); 309 return 0; 310} 311 312