mga_dh.c revision fe5e51b7
1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dh.c,v 1.4tsi Exp $ */ 2/********************************************************************* 3* G450: This is for Dual Head. 4* Matrox Graphics 5* Author : Luugi Marsan 6**********************************************************************/ 7 8#ifdef HAVE_CONFIG_H 9#include "config.h" 10#endif 11 12/* All drivers should typically include these */ 13#include "xf86.h" 14#include "xf86_OSproc.h" 15 16/* Drivers for PCI hardware need this */ 17#include "xf86PciInfo.h" 18 19/* Drivers that need to access the PCI config space directly need this */ 20#include "xf86Pci.h" 21 22#include "mga_reg.h" 23#include "mga.h" 24 25#define MNP_TABLE_SIZE 64 26#define CLKSEL_MGA 0x0c 27#define PLLLOCK 0x40 28 29/* Misc field*/ 30#define IOADDSEL 0x01 31#define RAMMAPEN 0x02 32#define CLKSEL_25175 0x00 33#define CLKSEL_28322 0x04 34#define CLKSEL_MGA 0x0c 35#define VIDEODIS 0x10 36#define HPGODDEV 0x20 37#define HSYNCPOL 0x40 38#define VSYNCPOL 0x80 39 40/* XSYNCCTRL field */ 41#define XSYNCCTRL_DAC1HSPOL_SHIFT 2 42#define XSYNCCTRL_DAC1HSPOL_MASK (1 << XSYNCCTRL_DAC1HSPOL_SHIFT) 43#define XSYNCCTRL_DAC1HSPOL_NEG (1 << XSYNCCTRL_DAC1HSPOL_SHIFT) 44#define XSYNCCTRL_DAC1HSPOL_POS 0 45#define XSYNCCTRL_DAC1VSPOL_SHIFT 3 46#define XSYNCCTRL_DAC1VSPOL_MASK (1 << XSYNCCTRL_DAC1VSPOL_SHIFT) 47#define XSYNCCTRL_DAC1VSPOL_NEG (1 << XSYNCCTRL_DAC1VSPOL_SHIFT) 48#define XSYNCCTRL_DAC1VSPOL_POS 0 49#define XSYNCCTRL_DAC2HSPOL_SHIFT 6 50#define XSYNCCTRL_DAC2HSPOL_MASK (1 << XSYNCCTRL_DAC2HSPOL_SHIFT) 51#define XSYNCCTRL_DAC2HSPOL_NEG (1 << XSYNCCTRL_DAC2HSPOL_SHIFT) 52#define XSYNCCTRL_DAC2HSPOL_POS 0 53#define XSYNCCTRL_DAC2VSPOL_SHIFT 7 54#define XSYNCCTRL_DAC2VSPOL_MASK (1 << XSYNCCTRL_DAC2VSPOL_SHIFT) 55#define XSYNCCTRL_DAC2VSPOL_NEG (1 << XSYNCCTRL_DAC2VSPOL_SHIFT) 56#define XSYNCCTRL_DAC2VSPOL_POS 0 57#define XSYNCCTRL_DAC1HSOFF_SHIFT 0 58#define XSYNCCTRL_DAC1HSOFF_MASK (1 << XSYNCCTRL_DAC1HSOFF_SHIFT) 59#define XSYNCCTRL_DAC1HSOFF_OFF (1 << XSYNCCTRL_DAC1HSOFF_SHIFT) 60#define XSYNCCTRL_DAC1HSOFF_ON 1 61#define XSYNCCTRL_DAC1VSOFF_SHIFT 1 62#define XSYNCCTRL_DAC1VSOFF_MASK (1 << XSYNCCTRL_DAC1VSOFF_SHIFT) 63#define XSYNCCTRL_DAC1VSOFF_OFF (1 << XSYNCCTRL_DAC1VSOFF_SHIFT) 64#define XSYNCCTRL_DAC1VSOFF_ON 0 65#define XSYNCCTRL_DAC2HSOFF_SHIFT 4 66#define XSYNCCTRL_DAC2HSOFF_MASK (1 << XSYNCCTRL_DAC2HSOFF_SHIFT) 67#define XSYNCCTRL_DAC2HSOFF_OFF (1 << XSYNCCTRL_DAC2HSOFF_SHIFT) 68#define XSYNCCTRL_DAC2HSOFF_ON 0 69#define XSYNCCTRL_DAC2VSOFF_SHIFT 5 70#define XSYNCCTRL_DAC2VSOFF_MASK (1 << XSYNCCTRL_DAC2VSOFF_SHIFT) 71#define XSYNCCTRL_DAC2VSOFF_OFF (1 << XSYNCCTRL_DAC2VSOFF_SHIFT) 72#define XSYNCCTRL_DAC2VSOFF_ON 0 73 74#define POS_HSYNC 0x00000004 75#define POS_VSYNC 0x00000008 76 77 78/* Set CRTC 2*/ 79/* Uses the mode given by xfree86 to setup the registry */ 80/* Does not write to the hard yet */ 81void MGACRTC2Get(ScrnInfoPtr pScrn, xMODEINFO *pModeInfo) 82{ 83 84 85 MGAPtr pMga = MGAPTR(pScrn); 86 MGARegPtr pReg = &pMga->ModeReg; 87 88 xMODEINFO tmpModeInfo; 89 CARD32 ulHTotal; 90 CARD32 ulHDispEnd; 91 CARD32 ulHBlkStr; 92 CARD32 ulHSyncStr; 93 CARD32 ulHSyncEnd; 94 CARD32 ulVTotal; 95 CARD32 ulVDispEnd; 96 CARD32 ulVBlkStr; 97 CARD32 ulVSyncStr; 98 CARD32 ulVSyncEnd; 99 CARD32 ulOffset; 100 CARD32 ulCtl2; 101 CARD32 ulDataCtl2; 102 CARD32 ulDispHeight = pModeInfo->ulDispHeight; 103 104#ifdef DEBUG 105 ErrorF("ENTER MGACRTC2Get\n"); 106#endif 107 108 tmpModeInfo = *pModeInfo; 109 110 111 /* First compute the Values */ 112 113 ulHTotal = tmpModeInfo.ulDispWidth + 114 tmpModeInfo.ulHFPorch + 115 tmpModeInfo.ulHBPorch + 116 tmpModeInfo.ulHSync; 117 118 ulHDispEnd = tmpModeInfo.ulDispWidth; 119 ulHBlkStr = ulHDispEnd; 120 ulHSyncStr = ulHBlkStr + tmpModeInfo.ulHFPorch; 121 ulHSyncEnd = ulHSyncStr + tmpModeInfo.ulHSync; 122 123 ulVTotal = ulDispHeight + 124 tmpModeInfo.ulVFPorch + 125 tmpModeInfo.ulVBPorch + 126 tmpModeInfo.ulVSync; 127 128 129 ulVDispEnd = ulDispHeight; 130 ulVBlkStr = ulVDispEnd; 131 ulVSyncStr = ulVBlkStr + tmpModeInfo.ulVFPorch; 132 ulVSyncEnd = ulVSyncStr + tmpModeInfo.ulVSync; 133 134 ulOffset = tmpModeInfo.ulFBPitch; 135 136 137 138 ulCtl2 = INREG(MGAREG_C2CTL); 139 ulDataCtl2 = INREG(MGAREG_C2DATACTL); 140 141 ulCtl2 &= 0xFF1FFFFF; 142 ulDataCtl2 &= 0xFFFFFF00; 143 144 switch (tmpModeInfo.ulBpp) 145 { 146 case 15: ulCtl2 |= 0x00200000; 147 ulOffset <<= 1; 148 break; 149 case 16: ulCtl2 |= 0x00400000; 150 ulOffset <<= 1; 151 break; 152 case 32: ulCtl2 |= 0x00800000; 153 ulOffset <<= 2; 154 break; 155 } 156 157 158 pReg->crtc2[ MGAREG2_C2CTL ] = ulCtl2; 159 pReg->crtc2[ MGAREG2_C2DATACTL ] = ulDataCtl2; 160 161 /* Horizontal Value*/ 162 pReg->crtc2[MGAREG2_C2HPARAM] = (((ulHDispEnd-8) << 16) | (ulHTotal-8)) ; 163 pReg->crtc2[MGAREG2_C2HSYNC] = (((ulHSyncEnd-8) << 16) | (ulHSyncStr-8)) ; 164 165 166 /*Vertical Value*/ 167 pReg->crtc2[MGAREG2_C2VPARAM] = (((ulVDispEnd-1) << 16) | (ulVTotal-1)) ; 168 pReg->crtc2[MGAREG2_C2VSYNC] = (((ulVSyncEnd-1) << 16) | (ulVSyncStr-1)) ; 169 170 /** Offset value*/ 171 172 pReg->crtc2[MGAREG2_C2OFFSET] = ulOffset; 173 174#ifdef DEBUG 175 ErrorF("EXIT MGACRTC2Get\n"); 176#endif 177 178} 179 180/* Set CRTC 2*/ 181/* Writes to the hardware */ 182void MGACRTC2Set(ScrnInfoPtr pScrn, xMODEINFO *pModeInfo) 183{ 184 185 186 MGAPtr pMga = MGAPTR(pScrn); 187 MGARegPtr pReg = &pMga->ModeReg; 188 189#ifdef DEBUG 190 ErrorF("ENTER MGACRTC2Set\n"); 191#endif 192 193 194 /* This writes to the registers manually */ 195 OUTREG(MGAREG_C2CTL, pReg->crtc2[MGAREG2_C2CTL]); 196 OUTREG(MGAREG_C2DATACTL,pReg->crtc2[MGAREG2_C2DATACTL]); 197 198 199 /* Horizontal Value*/ 200 OUTREG(MGAREG_C2HPARAM, pReg->crtc2[MGAREG2_C2HPARAM]); 201 OUTREG(MGAREG_C2HSYNC, pReg->crtc2[MGAREG2_C2HSYNC]); 202 203 204 /*Vertical Value*/ 205 OUTREG(MGAREG_C2VPARAM, pReg->crtc2[MGAREG2_C2VPARAM]); 206 OUTREG(MGAREG_C2VSYNC, pReg->crtc2[MGAREG2_C2VSYNC]); 207 208 /** Offset value*/ 209 210 OUTREG(MGAREG_C2OFFSET, pReg->crtc2[MGAREG2_C2OFFSET]); 211#ifdef DEBUG 212 ErrorF("EXIT MGACRTC2Set\n"); 213#endif 214 215} 216 217 218/* Set CRTC2 on the right output */ 219void MGAEnableSecondOutPut(ScrnInfoPtr pScrn, xMODEINFO *pModeInfo) 220{ 221 CARD8 ucByte, ucXDispCtrl; 222 CARD32 ulC2CTL; 223 MGAPtr pMga = MGAPTR(pScrn); 224 MGARegPtr pReg; 225 pReg = &pMga->ModeReg; 226#ifdef DEBUG 227 ErrorF("ENTER MGAEnableSecondOutPut\n"); 228#endif 229 230 231 /* Route Video PLL on second CRTC */ 232 ulC2CTL = INREG( MGAREG_C2CTL); 233 234 /*--- Disable Pixel clock oscillations On Crtc1 */ 235 OUTREG( MGAREG_C2CTL, ulC2CTL | MGAREG_C2CTL_PIXCLKDIS_MASK); 236 /*--- Have to wait minimum time (2 acces will be ok) */ 237 (void) INREG( MGAREG_Status); 238 (void) INREG( MGAREG_Status); 239 240 241 ulC2CTL &= ~MGAREG_C2CTL_PIXCLKSEL_MASK; 242 ulC2CTL &= ~MGAREG_C2CTL_PIXCLKSELH_MASK; 243 244 ulC2CTL |= MGAREG_C2CTL_PIXCLKSEL_VIDEOPLL; 245 246 247 OUTREG( MGAREG_C2CTL, ulC2CTL); 248 249 /*--- Enable Pixel clock oscillations on CRTC2*/ 250 ulC2CTL &= ~MGAREG_C2CTL_PIXCLKDIS_MASK; 251 OUTREG( MGAREG_C2CTL, ulC2CTL); 252 253 254 /* We don't use MISC synch pol, must be 0*/ 255 ucByte = inMGAdreg( MGAREG_MISC_READ); 256 257 OUTREG8(MGAREG_MISC_WRITE, (CARD8)(ucByte & ~(HSYNCPOL| VSYNCPOL) )); 258 259 260 261 262 /* Set Rset to 0.7 V*/ 263 ucByte = inMGAdac(MGA1064_GEN_IO_CTL); 264 ucByte &= ~0x40; 265 pReg->DacRegs[MGA1064_GEN_IO_CTL] = ucByte; 266 outMGAdac (MGA1064_GEN_IO_CTL, ucByte); 267 268 ucByte = inMGAdac( MGA1064_GEN_IO_DATA); 269 ucByte &= ~0x40; 270 pReg->DacRegs[MGA1064_GEN_IO_DATA]= ucByte; 271 outMGAdac (MGA1064_GEN_IO_DATA, ucByte); 272 273 /* Since G550 can swap outputs at BIOS initialisation, we must check which 274 * DAC is 'logically' used as the secondary (don't assume its DAC2 anymore) */ 275 276 ulC2CTL = INREG(MGAREG_C2CTL); 277 ucXDispCtrl = inMGAdac(MGA1064_DISP_CTL); 278 279 ucXDispCtrl &= ~MGA1064_DISP_CTL_DAC2OUTSEL_MASK; 280 281 if (!pMga->SecondOutput) { 282 /* Route Crtc2 on Output1 */ 283 ucXDispCtrl |= MGA1064_DISP_CTL_DAC2OUTSEL_CRTC1; 284 ulC2CTL |= MGAREG_C2CTL_CRTCDACSEL_CRTC2; 285 } 286 else { 287 /* Route Crtc2 on Output2*/ 288 ucXDispCtrl |= MGA1064_DISP_CTL_DAC2OUTSEL_CRTC2; 289 ulC2CTL &= ~MGAREG_C2CTL_CRTCDACSEL_MASK; 290 } 291 292 /* Enable CRTC2*/ 293 ulC2CTL |= MGAREG_C2CTL_C2_EN; 294 295 pReg->dac2[ MGA1064_DISP_CTL - 0x80] = ucXDispCtrl; 296 297 298 299 OUTREG( MGAREG_C2CTL, ulC2CTL); 300 301 /* Set DAC2 Synch polarity*/ 302 ucByte = inMGAdac( MGA1064_SYNC_CTL); 303 ucByte &= ~(XSYNCCTRL_DAC2HSPOL_MASK | XSYNCCTRL_DAC2VSPOL_MASK); 304 if ( !(pModeInfo->flSignalMode & POS_HSYNC) ) 305 { 306 ucByte |= XSYNCCTRL_DAC2HSPOL_NEG; 307 } 308 if ( !(pModeInfo->flSignalMode & POS_VSYNC) ) 309 { 310 ucByte |= XSYNCCTRL_DAC2VSPOL_NEG; 311 } 312 313 /* Enable synch output*/ 314 ucByte &= ~(XSYNCCTRL_DAC2HSOFF_MASK | XSYNCCTRL_DAC2VSOFF_MASK); 315 pReg->dac2[ MGA1064_SYNC_CTL - 0x80] = ucByte; 316 317 /* Power up DAC2, Fifo. 318 * The TMDS is powered down here, which is likely wrong. 319 */ 320 pReg->dac2[MGA1064_PWR_CTL - 0x80] = 321 MGA1064_PWR_CTL_DAC2_EN | 322 MGA1064_PWR_CTL_VID_PLL_EN | 323 MGA1064_PWR_CTL_RFIFO_EN | 324 MGA1064_PWR_CTL_CFIFO_EN; 325 326 327#ifdef DEBUG 328 ErrorF("EXIT MGAEnableSecondOutPut\n"); 329#endif 330} 331 332 333 334 335 336void MGACRTC2GetPitch (ScrnInfoPtr pScrn, xMODEINFO *pModeInfo) 337{ 338 CARD32 ulOffset; 339 MGAPtr pMga = MGAPTR(pScrn); 340 MGARegPtr pReg; 341 342 pReg = &pMga->ModeReg; 343#ifdef DEBUG 344 ErrorF("ENTER MGACRTC2GetPitch\n"); 345#endif 346 347 348 switch(pModeInfo->ulBpp) 349 { 350 case 15: 351 case 16: 352 ulOffset = pModeInfo->ulFBPitch * 2; 353 break; 354 case 32: 355 ulOffset = pModeInfo->ulFBPitch * 4; 356 break; 357 default: /* Muffle compiler */ 358 ulOffset = pModeInfo->ulFBPitch; 359 break; 360 } 361 362 pReg->crtc2[MGAREG2_C2OFFSET] = ulOffset; 363 364#ifdef DEBUG 365 ErrorF("EXIT MGACRTC2GetPitch\n"); 366#endif 367 368} 369 370void MGACRTC2SetPitch (ScrnInfoPtr pScrn, xMODEINFO *pModeInfo) 371{ 372 373 MGAPtr pMga = MGAPTR(pScrn); 374 MGARegPtr pReg; 375 pReg = &pMga->ModeReg; 376 377#ifdef DEBUG 378 ErrorF("ENTER CRCT2SetPitch\n"); 379#endif 380 381 382 OUTREG(MGAREG_C2OFFSET, pReg->crtc2[MGAREG2_C2OFFSET]); 383#ifdef DEBUG 384 ErrorF("EXIT CRCT2SetPitch\n"); 385#endif 386 387} 388 389 390 /* Set Display Start*/ 391 /* base in bytes*/ 392void MGACRTC2GetDisplayStart (ScrnInfoPtr pScrn, xMODEINFO *pModeInfo, CARD32 base, CARD32 ulX, CARD32 ulY) 393{ 394 395 CARD32 ulAddress; 396 MGAPtr pMga = MGAPTR(pScrn); 397 MGARegPtr pReg; 398 pReg = &pMga->ModeReg; 399 400#ifdef DEBUG 401 ErrorF("ENTER MGACRTC2GetDisplayStart\n"); 402#endif 403 404 405 pReg = &pMga->ModeReg; 406 407 ulAddress = (pModeInfo->ulFBPitch * ulY + ulX); 408 switch(pModeInfo->ulBpp) 409 { 410 case 15: 411 case 16: 412 ulAddress <<= 1; 413 break; 414 case 32: 415 ulAddress <<= 2; 416 break; 417 } 418 419 pReg->crtc2[MGAREG2_C2STARTADD0] = ulAddress + base; 420#ifdef DEBUG 421 ErrorF("EXIT MGACRTC2GetDisplayStart\n"); 422#endif 423 424} 425 426void MGACRTC2SetDisplayStart (ScrnInfoPtr pScrn, xMODEINFO *pModeInfo, CARD32 base, CARD32 ulX, CARD32 ulY) 427{ 428 MGAPtr pMga = MGAPTR(pScrn); 429 MGARegPtr pReg; 430 pReg = &pMga->ModeReg; 431#ifdef DEBUG 432 ErrorF("ENTER MGACRTC2SetDisplayStart\n"); 433#endif 434 435 OUTREG(MGAREG_C2STARTADD0, pReg->crtc2[MGAREG2_C2STARTADD0]); 436#ifdef DEBUG 437 ErrorF("EXIT MGACRTC2SetDisplayStart\n"); 438#endif 439 440} 441 442 443 444 445 446 447 448 449 450 451 452