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