1/* 2 * Copyright 2009 Red Hat Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Author: Ben Skeggs 23 */ 24 25#include "drmP.h" 26#include "drm.h" 27#include "drm_crtc_helper.h" 28 29#include "nouveau_drv.h" 30#include "nouveau_fb.h" 31#include "nouveau_hw.h" 32#include "nouveau_encoder.h" 33#include "nouveau_connector.h" 34 35static void 36nv04_display_store_initial_head_owner(struct drm_device *dev) 37{ 38 struct drm_nouveau_private *dev_priv = dev->dev_private; 39 40 if (dev_priv->chipset != 0x11) { 41 dev_priv->crtc_owner = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44); 42 return; 43 } 44 45 /* reading CR44 is broken on nv11, so we attempt to infer it */ 46 if (nvReadMC(dev, NV_PBUS_DEBUG_1) & (1 << 28)) /* heads tied, restore both */ 47 dev_priv->crtc_owner = 0x4; 48 else { 49 uint8_t slaved_on_A, slaved_on_B; 50 bool tvA = false; 51 bool tvB = false; 52 53 slaved_on_B = NVReadVgaCrtc(dev, 1, NV_CIO_CRE_PIXEL_INDEX) & 54 0x80; 55 if (slaved_on_B) 56 tvB = !(NVReadVgaCrtc(dev, 1, NV_CIO_CRE_LCD__INDEX) & 57 MASK(NV_CIO_CRE_LCD_LCD_SELECT)); 58 59 slaved_on_A = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_PIXEL_INDEX) & 60 0x80; 61 if (slaved_on_A) 62 tvA = !(NVReadVgaCrtc(dev, 0, NV_CIO_CRE_LCD__INDEX) & 63 MASK(NV_CIO_CRE_LCD_LCD_SELECT)); 64 65 if (slaved_on_A && !tvA) 66 dev_priv->crtc_owner = 0x0; 67 else if (slaved_on_B && !tvB) 68 dev_priv->crtc_owner = 0x3; 69 else if (slaved_on_A) 70 dev_priv->crtc_owner = 0x0; 71 else if (slaved_on_B) 72 dev_priv->crtc_owner = 0x3; 73 else 74 dev_priv->crtc_owner = 0x0; 75 } 76} 77 78int 79nv04_display_early_init(struct drm_device *dev) 80{ 81 /* Make the I2C buses accessible. */ 82 if (!nv_gf4_disp_arch(dev)) { 83 uint32_t pmc_enable = nv_rd32(dev, NV03_PMC_ENABLE); 84 85 if (!(pmc_enable & 1)) 86 nv_wr32(dev, NV03_PMC_ENABLE, pmc_enable | 1); 87 } 88 89 /* Unlock the VGA CRTCs. */ 90 NVLockVgaCrtcs(dev, false); 91 92 /* Make sure the CRTCs aren't in slaved mode. */ 93 if (nv_two_heads(dev)) { 94 nv04_display_store_initial_head_owner(dev); 95 NVSetOwner(dev, 0); 96 } 97 98 return 0; 99} 100 101void 102nv04_display_late_takedown(struct drm_device *dev) 103{ 104 struct drm_nouveau_private *dev_priv = dev->dev_private; 105 106 if (nv_two_heads(dev)) 107 NVSetOwner(dev, dev_priv->crtc_owner); 108 109 NVLockVgaCrtcs(dev, true); 110} 111 112int 113nv04_display_create(struct drm_device *dev) 114{ 115 struct drm_nouveau_private *dev_priv = dev->dev_private; 116 struct dcb_table *dcb = &dev_priv->vbios.dcb; 117 struct drm_connector *connector, *ct; 118 struct drm_encoder *encoder; 119 struct drm_crtc *crtc; 120 int i, ret; 121 122 NV_DEBUG_KMS(dev, "\n"); 123 124 nouveau_hw_save_vga_fonts(dev, 1); 125 126 drm_mode_config_init(dev); 127 drm_mode_create_scaling_mode_property(dev); 128 drm_mode_create_dithering_property(dev); 129 130 dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs; 131 132 dev->mode_config.min_width = 0; 133 dev->mode_config.min_height = 0; 134 switch (dev_priv->card_type) { 135 case NV_04: 136 dev->mode_config.max_width = 2048; 137 dev->mode_config.max_height = 2048; 138 break; 139 default: 140 dev->mode_config.max_width = 4096; 141 dev->mode_config.max_height = 4096; 142 break; 143 } 144 145 dev->mode_config.fb_base = dev_priv->fb_phys; 146 147 nv04_crtc_create(dev, 0); 148 if (nv_two_heads(dev)) 149 nv04_crtc_create(dev, 1); 150 151 for (i = 0; i < dcb->entries; i++) { 152 struct dcb_entry *dcbent = &dcb->entry[i]; 153 154 connector = nouveau_connector_create(dev, dcbent->connector); 155 if (IS_ERR(connector)) 156 continue; 157 158 switch (dcbent->type) { 159 case OUTPUT_ANALOG: 160 ret = nv04_dac_create(connector, dcbent); 161 break; 162 case OUTPUT_LVDS: 163 case OUTPUT_TMDS: 164 ret = nv04_dfp_create(connector, dcbent); 165 break; 166 case OUTPUT_TV: 167 if (dcbent->location == DCB_LOC_ON_CHIP) 168 ret = nv17_tv_create(connector, dcbent); 169 else 170 ret = nv04_tv_create(connector, dcbent); 171 break; 172 default: 173 NV_WARN(dev, "DCB type %d not known\n", dcbent->type); 174 continue; 175 } 176 177 if (ret) 178 continue; 179 } 180 181 list_for_each_entry_safe(connector, ct, 182 &dev->mode_config.connector_list, head) { 183 if (!connector->encoder_ids[0]) { 184 NV_WARN(dev, "%s has no encoders, removing\n", 185 drm_get_connector_name(connector)); 186 connector->funcs->destroy(connector); 187 } 188 } 189 190 /* Save previous state */ 191 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 192 crtc->funcs->save(crtc); 193 194 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 195 struct drm_encoder_helper_funcs *func = encoder->helper_private; 196 197 func->save(encoder); 198 } 199 200 return 0; 201} 202 203void 204nv04_display_destroy(struct drm_device *dev) 205{ 206 struct drm_encoder *encoder; 207 struct drm_crtc *crtc; 208 209 NV_DEBUG_KMS(dev, "\n"); 210 211 /* Turn every CRTC off. */ 212 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 213 struct drm_mode_set modeset = { 214 .crtc = crtc, 215 }; 216 217 crtc->funcs->set_config(&modeset); 218 } 219 220 /* Restore state */ 221 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 222 struct drm_encoder_helper_funcs *func = encoder->helper_private; 223 224 func->restore(encoder); 225 } 226 227 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 228 crtc->funcs->restore(crtc); 229 230 drm_mode_config_cleanup(dev); 231 232 nouveau_hw_save_vga_fonts(dev, 0); 233} 234 235int 236nv04_display_init(struct drm_device *dev) 237{ 238 struct drm_encoder *encoder; 239 struct drm_crtc *crtc; 240 241 /* meh.. modeset apparently doesn't setup all the regs and depends 242 * on pre-existing state, for now load the state of the card *before* 243 * nouveau was loaded, and then do a modeset. 244 * 245 * best thing to do probably is to make save/restore routines not 246 * save/restore "pre-load" state, but more general so we can save 247 * on suspend too. 248 */ 249 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 250 struct drm_encoder_helper_funcs *func = encoder->helper_private; 251 252 func->restore(encoder); 253 } 254 255 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 256 crtc->funcs->restore(crtc); 257 258 return 0; 259} 260