mga_dac3026.c revision cc92fc76
1/* 2 * Copyright 1994 by Robin Cutshaw <robin@XFree86.org> 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of Robin Cutshaw not be used in 9 * advertising or publicity pertaining to distribution of the software without 10 * specific, written prior permission. Robin Cutshaw makes no representations 11 * about the suitability of this software for any purpose. It is provided 12 * "as is" without express or implied warranty. 13 * 14 * ROBIN CUTSHAW DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL ROBIN CUTSHAW BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 * 22 * 23 * Modified for TVP3026 by Harald Koenig <koenig@tat.physik.uni-tuebingen.de> 24 * 25 * Modified for MGA Millennium by Xavier Ducoin <xavier@rd.lectra.fr> 26 * 27 * Doug Merritt <doug@netcom.com> 28 * 24bpp: fixed high res stripe glitches, clock glitches on all res 29 * 30 */ 31 32#ifdef HAVE_CONFIG_H 33#include "config.h" 34#endif 35 36/* 37 * This is a first cut at a non-accelerated version to work with the 38 * new server design (DHD). 39 */ 40 41/* All drivers should typically include these */ 42#include "xf86.h" 43#include "xf86_OSproc.h" 44 45/* Drivers that need to access the PCI config space directly need this */ 46#include "xf86Pci.h" 47 48#include "mga_reg.h" 49#include "mga.h" 50#include "mga_macros.h" 51 52#include "xf86DDC.h" 53 54/* 55 * Only change these bits in the Option register. Make sure that the 56 * vgaioen bit is never in this mask because it is controlled elsewhere 57 */ 58#define OPTION_MASK 0xFFEFFEFF /* ~(eepromwt | vgaioen) */ 59 60static void MGA3026LoadPalette(ScrnInfoPtr, int, int*, LOCO*, VisualPtr); 61static void MGA3026SavePalette(ScrnInfoPtr, unsigned char*); 62static void MGA3026RestorePalette(ScrnInfoPtr, unsigned char*); 63static void MGA3026RamdacInit(ScrnInfoPtr); 64static void MGA3026Save(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool); 65static void MGA3026Restore(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool); 66static Bool MGA3026Init(ScrnInfoPtr, DisplayModePtr); 67static Bool MGA3026_i2cInit(ScrnInfoPtr pScrn); 68 69 70/* 71 * implementation 72 */ 73 74/* 75 * indexes to ti3026 registers (the order is important) 76 */ 77const static unsigned char MGADACregs[] = { 78 0x0F, 0x18, 0x19, 0x1A, 0x1C, 0x1D, 0x1E, 0x2A, 0x2B, 0x30, 79 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 80 0x06 81}; 82 83/* note: to fix a cursor hw glitch, register 0x37 (blue color key) needs 84 to be set to magic numbers, even though they are "never" used because 85 blue keying disabled in 0x38. 86 87 Matrox sez: 88 89 ...The more precise statement of the software workaround is to insure 90 that bits 7-5 of register 0x37 (Blue Color Key High) and bits 7-5 of 91 register 0x38 (HZOOM)are the same... 92*/ 93 94/* also note: the values of the MUX control register 0x19 (index [2]) can be 95 found in table 2-17 of the 3026 manual. If interlace is set, the values 96 listed here are incremented by one. 97*/ 98 99#define DACREGSIZE sizeof(MGADACregs) 100/* 101 * initial values of ti3026 registers 102 */ 103const static unsigned char MGADACbpp8[DACREGSIZE] = { 104 0x06, 0x80, 0x4b, 0x25, 0x00, 0x00, 0x0C, 0x00, 0x1E, 0xFF, 105 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0, 0x00, 106 0x00 107}; 108const static unsigned char MGADACbpp16[DACREGSIZE] = { 109 0x07, 0x45, 0x53, 0x15, 0x00, 0x00, 0x2C, 0x00, 0x1E, 0xFF, 110 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x10, 0, 0x00, 111 0x00 112}; 113/* 114 * [0] value was 0x07, but changed to 0x06 by Doug Merrit to fix high res 115 * stripe glitches and clock glitches at 24bpp. 116 */ 117/* [0] value is now set inside of MGA3026Init, based on the silicon revision 118 It is still set to 7 or 6 based on the revision, though, since setting to 119 8 as in the documentation makes (some?) revB chips get the colors wrong... 120 maybe BGR instead of RGB? This only applies to 24bpp, since it is the only 121 one documented as depending on revision. 122 */ 123 124const static unsigned char MGADACbpp24[DACREGSIZE] = { 125 0x06, 0x56, 0x5b, 0x25, 0x00, 0x00, 0x2C, 0x00, 0x1E, 0xFF, 126 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x10, 0, 0x00, 127 0x00 128}; 129const static unsigned char MGADACbpp32[DACREGSIZE] = { 130 0x07, 0x46, 0x5b, 0x05, 0x00, 0x00, 0x2C, 0x00, 0x1E, 0xFF, 131 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x10, 0, 0x00, 132 0x00 133}; 134 135 136/* 137 * Read/write to the DAC via MMIO 138 */ 139 140/* 141 * These were functions. Use macros instead to avoid the need to 142 * pass pMga to them. 143 */ 144 145#define inTi3026dreg(reg) INREG8(RAMDAC_OFFSET + (reg)) 146 147#define outTi3026dreg(reg, val) OUTREG8(RAMDAC_OFFSET + (reg), val) 148 149#define inTi3026(reg) \ 150 (outTi3026dreg(TVP3026_INDEX, reg), inTi3026dreg(TVP3026_DATA)) 151 152#define outTi3026(reg, mask, val) \ 153 do { /* note: mask and reg may get evaluated twice */ \ 154 unsigned char tmp = (mask) ? (inTi3026(reg) & (mask)) : 0; \ 155 outTi3026dreg(TVP3026_INDEX, reg); \ 156 outTi3026dreg(TVP3026_DATA, tmp | (val)); \ 157 } while (0) 158 159 160/* 161 * MGATi3026CalcClock - Calculate the PLL settings (m, n, p). 162 * 163 * DESCRIPTION 164 * For more information, refer to the Texas Instruments 165 * "TVP3026 Data Manual" (document SLAS098B). 166 * Section 2.4 "PLL Clock Generators" 167 * Appendix A "Frequency Synthesis PLL Register Settings" 168 * Appendix B "PLL Programming Examples" 169 * 170 * PARAMETERS 171 * f_out IN Desired clock frequency. 172 * f_max IN Maximum allowed clock frequency. 173 * m OUT Value of PLL 'm' register. 174 * n OUT Value of PLL 'n' register. 175 * p OUT Value of PLL 'p' register. 176 * 177 * HISTORY 178 * January 11, 1997 - [aem] Andrew E. Mileski 179 * Split off from MGATi3026SetClock. 180 */ 181 182/* The following values are in kHz */ 183#define TI_MIN_VCO_FREQ 110000 184#define TI_MAX_VCO_FREQ 220000 185#define TI_MAX_MCLK_FREQ 100000 186#define TI_REF_FREQ 14318.18 187 188static double 189MGATi3026CalcClock ( 190 long f_out, long f_max, 191 int *m, int *n, int *p 192){ 193 int best_m = 0, best_n = 0; 194 double f_pll, f_vco; 195 double m_err, inc_m, calc_m; 196 197 /* Make sure that f_min <= f_out <= f_max */ 198 if ( f_out < ( TI_MIN_VCO_FREQ / 8 )) 199 f_out = TI_MIN_VCO_FREQ / 8; 200 if ( f_out > f_max ) 201 f_out = f_max; 202 203 /* 204 * f_pll = f_vco / 2 ^ p 205 * Choose p so that TI_MIN_VCO_FREQ <= f_vco <= TI_MAX_VCO_FREQ 206 * Note that since TI_MAX_VCO_FREQ = 2 * TI_MIN_VCO_FREQ 207 * we don't have to bother checking for this maximum limit. 208 */ 209 f_vco = ( double ) f_out; 210 for ( *p = 0; *p < 3 && f_vco < TI_MIN_VCO_FREQ; ( *p )++ ) 211 f_vco *= 2.0; 212 213 /* 214 * We avoid doing multiplications by ( 65 - n ), 215 * and add an increment instead - this keeps any error small. 216 */ 217 inc_m = f_vco / ( TI_REF_FREQ * 8.0 ); 218 219 /* Initial value of calc_m for the loop */ 220 calc_m = inc_m + inc_m + inc_m; 221 222 /* Initial amount of error for an integer - impossibly large */ 223 m_err = 2.0; 224 225 /* Search for the closest INTEGER value of ( 65 - m ) */ 226 for ( *n = 3; *n <= 25; ( *n )++, calc_m += inc_m ) { 227 228 /* Ignore values of ( 65 - m ) which we can't use */ 229 if ( calc_m < 3.0 || calc_m > 64.0 ) 230 continue; 231 232 /* 233 * Pick the closest INTEGER (has smallest fractional part). 234 * The optimizer should clean this up for us. 235 */ 236 if (( calc_m - ( int ) calc_m ) < m_err ) { 237 m_err = calc_m - ( int ) calc_m; 238 best_m = ( int ) calc_m; 239 best_n = *n; 240 } 241 } 242 243 /* 65 - ( 65 - x ) = x */ 244 *m = 65 - best_m; 245 *n = 65 - best_n; 246 247 /* Now all the calculations can be completed */ 248 f_vco = 8.0 * TI_REF_FREQ * best_m / best_n; 249 f_pll = f_vco / ( 1 << *p ); 250 251#ifdef DEBUG 252 ErrorF( "f_out=%ld f_pll=%.1f f_vco=%.1f n=%d m=%d p=%d\n", 253 f_out, f_pll, f_vco, *n, *m, *p ); 254#endif 255 256 return f_pll; 257} 258 259/* 260 * MGATi3026SetMCLK - Set the memory clock (MCLK) PLL. 261 * 262 * HISTORY 263 * January 11, 1997 - [aem] Andrew E. Mileski 264 * Written and tested. 265 */ 266static void 267MGATi3026SetMCLK( ScrnInfoPtr pScrn, long f_out ) 268{ 269 int mclk_m, mclk_n, mclk_p; 270 int pclk_m, pclk_n, pclk_p; 271 int mclk_ctl; 272 MGAPtr pMga = MGAPTR(pScrn); 273 274 MGATi3026CalcClock(f_out, TI_MAX_MCLK_FREQ, &mclk_m, &mclk_n, &mclk_p); 275 276 /* Save PCLK settings */ 277 outTi3026( TVP3026_PLL_ADDR, 0, 0xfc ); 278 pclk_n = inTi3026( TVP3026_PIX_CLK_DATA ); 279 outTi3026( TVP3026_PLL_ADDR, 0, 0xfd ); 280 pclk_m = inTi3026( TVP3026_PIX_CLK_DATA ); 281 outTi3026( TVP3026_PLL_ADDR, 0, 0xfe ); 282 pclk_p = inTi3026( TVP3026_PIX_CLK_DATA ); 283 284 /* Stop PCLK (PLLEN = 0, PCLKEN = 0) */ 285 outTi3026( TVP3026_PLL_ADDR, 0, 0xfe ); 286 outTi3026( TVP3026_PIX_CLK_DATA, 0, 0x00 ); 287 288 /* Set PCLK to the new MCLK frequency (PLLEN = 1, PCLKEN = 0 ) */ 289 outTi3026( TVP3026_PLL_ADDR, 0, 0xfc ); 290 outTi3026( TVP3026_PIX_CLK_DATA, 0, ( mclk_n & 0x3f ) | 0xc0 ); 291 outTi3026( TVP3026_PIX_CLK_DATA, 0, mclk_m & 0x3f ); 292 outTi3026( TVP3026_PIX_CLK_DATA, 0, ( mclk_p & 0x03 ) | 0xb0 ); 293 294 /* Wait for PCLK PLL to lock on frequency */ 295 while (( inTi3026( TVP3026_PIX_CLK_DATA ) & 0x40 ) == 0 ) { 296 ; 297 } 298 299 /* Output PCLK on MCLK pin */ 300 mclk_ctl = inTi3026( TVP3026_MCLK_CTL ); 301 outTi3026( TVP3026_MCLK_CTL, 0, mclk_ctl & 0xe7 ); 302 outTi3026( TVP3026_MCLK_CTL, 0, ( mclk_ctl & 0xe7 ) | 0x08 ); 303 304 /* Stop MCLK (PLLEN = 0 ) */ 305 outTi3026( TVP3026_PLL_ADDR, 0, 0xfb ); 306 outTi3026( TVP3026_MEM_CLK_DATA, 0, 0x00 ); 307 308 /* Set MCLK to the new frequency (PLLEN = 1) */ 309 outTi3026( TVP3026_PLL_ADDR, 0, 0xf3 ); 310 outTi3026( TVP3026_MEM_CLK_DATA, 0, ( mclk_n & 0x3f ) | 0xc0 ); 311 outTi3026( TVP3026_MEM_CLK_DATA, 0, mclk_m & 0x3f ); 312 outTi3026( TVP3026_MEM_CLK_DATA, 0, ( mclk_p & 0x03 ) | 0xb0 ); 313 314 /* Wait for MCLK PLL to lock on frequency */ 315 while (( inTi3026( TVP3026_MEM_CLK_DATA ) & 0x40 ) == 0 ) { 316 ; 317 } 318 319 /* Output MCLK PLL on MCLK pin */ 320 outTi3026( TVP3026_MCLK_CTL, 0, ( mclk_ctl & 0xe7 ) | 0x10 ); 321 outTi3026( TVP3026_MCLK_CTL, 0, ( mclk_ctl & 0xe7 ) | 0x18 ); 322 323 /* Stop PCLK (PLLEN = 0, PCLKEN = 0 ) */ 324 outTi3026( TVP3026_PLL_ADDR, 0, 0xfe ); 325 outTi3026( TVP3026_PIX_CLK_DATA, 0, 0x00 ); 326 327 /* Restore PCLK (PLLEN = ?, PCLKEN = ?) */ 328 outTi3026( TVP3026_PLL_ADDR, 0, 0xfc ); 329 outTi3026( TVP3026_PIX_CLK_DATA, 0, pclk_n ); 330 outTi3026( TVP3026_PIX_CLK_DATA, 0, pclk_m ); 331 outTi3026( TVP3026_PIX_CLK_DATA, 0, pclk_p ); 332 333 /* Wait for PCLK PLL to lock on frequency */ 334 while (( inTi3026( TVP3026_PIX_CLK_DATA ) & 0x40 ) == 0 ) { 335 ; 336 } 337} 338 339/* 340 * MGATi3026SetPCLK - Set the pixel (PCLK) and loop (LCLK) clocks. 341 * 342 * PARAMETERS 343 * f_pll IN Pixel clock PLL frequencly in kHz. 344 * bpp IN Bytes per pixel. 345 * 346 * HISTORY 347 * January 11, 1997 - [aem] Andrew E. Mileski 348 * Split to simplify code for MCLK (=GCLK) setting. 349 * 350 * December 14, 1996 - [aem] Andrew E. Mileski 351 * Fixed loop clock to be based on the calculated, not requested, 352 * pixel clock. Added f_max = maximum f_vco frequency. 353 * 354 * October 19, 1996 - [aem] Andrew E. Mileski 355 * Commented the loop clock code (wow, I understand everything now), 356 * and simplified it a bit. This should really be two separate functions. 357 * 358 * October 1, 1996 - [aem] Andrew E. Mileski 359 * Optimized the m & n picking algorithm. Added maxClock detection. 360 * Low speed pixel clock fix (per the docs). Documented what I understand. 361 * 362 * ?????, ??, ???? - [???] ???????????? 363 * Based on the TVP3026 code in the S3 driver. 364 */ 365 366static void 367MGATi3026SetPCLK( ScrnInfoPtr pScrn, long f_out, int bpp ) 368{ 369 /* Pixel clock values */ 370 int m, n, p; 371 372 /* Loop clock values */ 373 int lm, ln, lp, lq; 374 double z; 375 376 /* The actual frequency output by the clock */ 377 double f_pll; 378 379 long f_max = TI_MAX_VCO_FREQ; 380 381 MGAPtr pMga = MGAPTR(pScrn); 382 MGARegPtr pReg = &pMga->ModeReg; 383 384 /* Get the maximum pixel clock frequency */ 385 if ( pMga->MaxClock > TI_MAX_VCO_FREQ ) 386 f_max = pMga->MaxClock; 387 388 /* Do the calculations for m, n, and p */ 389 f_pll = MGATi3026CalcClock( f_out, f_max, & m, & n, & p ); 390 391 /* Values for the pixel clock PLL registers */ 392 pReg->DacClk[ 0 ] = ( n & 0x3f ) | 0xc0; 393 pReg->DacClk[ 1 ] = ( m & 0x3f ); 394 pReg->DacClk[ 2 ] = ( p & 0x03 ) | 0xb0; 395 396 /* 397 * Now that the pixel clock PLL is setup, 398 * the loop clock PLL must be setup. 399 */ 400 401 /* 402 * First we figure out lm, ln, and z. 403 * Things are different in packed pixel mode (24bpp) though. 404 */ 405 if ( pMga->CurrentLayout.bitsPerPixel == 24 ) { 406 407 /* ln:lm = ln:3 */ 408 lm = 65 - 3; 409 410 /* Check for interleaved mode */ 411 if ( bpp == 2 ) 412 /* ln:lm = 4:3 */ 413 ln = 65 - 4; 414 else 415 /* ln:lm = 8:3 */ 416 ln = 65 - 8; 417 418 /* Note: this is actually 100 * z for more precision */ 419 z = ( 11000 * ( 65 - ln )) / (( f_pll / 1000 ) * ( 65 - lm )); 420 } 421 else { 422 /* ln:lm = ln:4 */ 423 lm = 65 - 4; 424 425 /* Note: bpp = bytes per pixel */ 426 ln = 65 - 4 * ( 64 / 8 ) / bpp; 427 428 /* Note: this is actually 100 * z for more precision */ 429 z = (( 11000 / 4 ) * ( 65 - ln )) / ( f_pll / 1000 ); 430 } 431 432 /* 433 * Now we choose dividers lp and lq so that the VCO frequency 434 * is within the operating range of 110 MHz to 220 MHz. 435 */ 436 437 /* Assume no lq divider */ 438 lq = 0; 439 440 /* Note: z is actually 100 * z for more precision */ 441 if ( z <= 200.0 ) 442 lp = 0; 443 else if ( z <= 400.0 ) 444 lp = 1; 445 else if ( z <= 800.0 ) 446 lp = 2; 447 else if ( z <= 1600.0 ) 448 lp = 3; 449 else { 450 lp = 3; 451 lq = ( int )( z / 1600.0 ); 452 } 453 454 /* Values for the loop clock PLL registers */ 455 if ( pMga->CurrentLayout.bitsPerPixel == 24 ) { 456 /* Packed pixel mode values */ 457 pReg->DacClk[ 3 ] = ( ln & 0x3f ) | 0x80; 458 pReg->DacClk[ 4 ] = ( lm & 0x3f ) | 0x80; 459 pReg->DacClk[ 5 ] = ( lp & 0x03 ) | 0xf8; 460 } else { 461 /* Non-packed pixel mode values */ 462 pReg->DacClk[ 3 ] = ( ln & 0x3f ) | 0xc0; 463 pReg->DacClk[ 4 ] = ( lm & 0x3f ); 464 pReg->DacClk[ 5 ] = ( lp & 0x03 ) | 0xf0; 465 } 466 pReg->DacRegs[ 18 ] = lq | 0x38; 467 468#ifdef DEBUG 469 ErrorF( "bpp=%d z=%.1f ln=%d lm=%d lp=%d lq=%d\n", 470 bpp, z, ln, lm, lp, lq ); 471#endif 472} 473 474/* 475 * MGA3026Init -- for mga2064 with ti3026 476 * 477 * The 'mode' parameter describes the video mode. The 'mode' structure 478 * as well as the 'vga256InfoRec' structure can be dereferenced for 479 * information that is needed to initialize the mode. The 'new' macro 480 * (see definition above) is used to simply fill in the structure. 481 */ 482static Bool 483MGA3026Init(ScrnInfoPtr pScrn, DisplayModePtr mode) 484{ 485 int hd, hs, he, ht, vd, vs, ve, vt, wd; 486 int i, BppShift, index_1d = 0; 487 const unsigned char* initDAC; 488 MGAPtr pMga = MGAPTR(pScrn); 489 MGARamdacPtr MGAdac = &pMga->Dac; 490 MGAFBLayout *pLayout = &pMga->CurrentLayout; 491 MGARegPtr pReg = &pMga->ModeReg; 492 vgaRegPtr pVga = &VGAHWPTR(pScrn)->ModeReg; 493 494 BppShift = pMga->BppShifts[(pLayout->bitsPerPixel >> 3) - 1]; 495 496 switch(pLayout->bitsPerPixel) 497 { 498 case 8: 499 initDAC = MGADACbpp8; 500 break; 501 case 16: 502 initDAC = MGADACbpp16; 503 break; 504 case 24: 505 initDAC = MGADACbpp24; 506 break; 507 case 32: 508 initDAC = MGADACbpp32; 509 break; 510 default: 511 FatalError("MGA: unsupported bits per pixel\n"); 512 } 513 514 /* Allocate the DacRegs space if not done already */ 515 if (pReg->DacRegs == NULL) { 516 pReg->DacRegs = xnfcalloc(DACREGSIZE, 1); 517 } 518 for (i = 0; i < DACREGSIZE; i++) { 519 pReg->DacRegs[i] = initDAC[i]; 520 if (MGADACregs[i] == 0x1D) 521 index_1d = i; 522 } 523 524 if ( (pLayout->bitsPerPixel == 16) && (pLayout->weight.red == 5) 525 && (pLayout->weight.green == 5) && (pLayout->weight.blue == 5) ) { 526 pReg->DacRegs[1] &= ~0x01; 527 } 528 if (pMga->Interleave ) pReg->DacRegs[2] += 1; 529 530 531 if ( pLayout->bitsPerPixel == 24 ) { 532 int silicon_rev; 533 /* we need to set DacRegs[0] differently based on the silicon 534 * revision of the 3026 RAMDAC, as per page 2-14 of tvp3026.pdf. 535 * If we have rev A silicon, we want 0x07; rev B silicon wants 536 * 0x06. 537 */ 538 silicon_rev = inTi3026(TVP3026_SILICON_REV); 539 540#ifdef DEBUG 541 ErrorF("TVP3026 revision 0x%x (rev %s)\n", 542 silicon_rev, (silicon_rev <= 0x20) ? "A" : "B"); 543#endif 544 545 if(silicon_rev <= 0x20) { 546 /* rev A */ 547 pReg->DacRegs[0] = 0x07; 548 } else { 549 /* rev B */ 550 pReg->DacRegs[0] = 0x06; 551 } 552 } 553 554 /* 555 * This will initialize all of the generic VGA registers. 556 */ 557 if (!vgaHWInit(pScrn, mode)) 558 return(FALSE); 559 560 /* 561 * Here all of the MGA registers get filled in. 562 */ 563 hd = (mode->CrtcHDisplay >> 3) - 1; 564 hs = (mode->CrtcHSyncStart >> 3) - 1; 565 he = (mode->CrtcHSyncEnd >> 3) - 1; 566 ht = (mode->CrtcHTotal >> 3) - 1; 567 vd = mode->CrtcVDisplay - 1; 568 vs = mode->CrtcVSyncStart - 1; 569 ve = mode->CrtcVSyncEnd - 1; 570 vt = mode->CrtcVTotal - 2; 571 572 /* HTOTAL & 0x7 equal to 0x6 in 8bpp or 0x4 in 24bpp causes strange 573 * vertical stripes 574 */ 575 if((ht & 0x07) == 0x06 || (ht & 0x07) == 0x04) 576 ht++; 577 578 if (pLayout->bitsPerPixel == 24) 579 wd = (pLayout->displayWidth * 3) >> (4 - BppShift); 580 else 581 wd = pLayout->displayWidth >> (4 - BppShift); 582 583 pReg->ExtVga[0] = 0; 584 pReg->ExtVga[5] = 0; 585 586 if (mode->Flags & V_INTERLACE) 587 { 588 pReg->ExtVga[0] = 0x80; 589 pReg->ExtVga[5] = (hs + he - ht) >> 1; 590 wd <<= 1; 591 vt &= 0xFFFE; 592 593 /* enable interlaced cursor */ 594 pReg->DacRegs[20] |= 0x20; 595 } 596 597 pReg->ExtVga[0] |= (wd & 0x300) >> 4; 598 pReg->ExtVga[1] = (((ht - 4) & 0x100) >> 8) | 599 ((hd & 0x100) >> 7) | 600 ((hs & 0x100) >> 6) | 601 (ht & 0x40); 602 pReg->ExtVga[2] = ((vt & 0xc00) >> 10) | 603 ((vd & 0x400) >> 8) | 604 ((vd & 0xc00) >> 7) | 605 ((vs & 0xc00) >> 5); 606 if (pLayout->bitsPerPixel == 24) 607 pReg->ExtVga[3] = (((1 << BppShift) * 3) - 1) | 0x80; 608 else 609 pReg->ExtVga[3] = ((1 << BppShift) - 1) | 0x80; 610 611 /* Set viddelay (CRTCEXT3 Bits 3-4). */ 612 pReg->ExtVga[3] |= (pScrn->videoRam == 8192 ? 0x10 613 : pScrn->videoRam == 2048 ? 0x08 : 0x00); 614 615 pReg->ExtVga[4] = 0; 616 617 pVga->CRTC[0] = ht - 4; 618 pVga->CRTC[1] = hd; 619 pVga->CRTC[2] = hd; 620 pVga->CRTC[3] = (ht & 0x1F) | 0x80; 621 pVga->CRTC[4] = hs; 622 pVga->CRTC[5] = ((ht & 0x20) << 2) | (he & 0x1F); 623 pVga->CRTC[6] = vt & 0xFF; 624 pVga->CRTC[7] = ((vt & 0x100) >> 8 ) | 625 ((vd & 0x100) >> 7 ) | 626 ((vs & 0x100) >> 6 ) | 627 ((vd & 0x100) >> 5 ) | 628 0x10 | 629 ((vt & 0x200) >> 4 ) | 630 ((vd & 0x200) >> 3 ) | 631 ((vs & 0x200) >> 2 ); 632 pVga->CRTC[9] = ((vd & 0x200) >> 4) | 0x40; 633 pVga->CRTC[16] = vs & 0xFF; 634 pVga->CRTC[17] = (ve & 0x0F) | 0x20; 635 pVga->CRTC[18] = vd & 0xFF; 636 pVga->CRTC[19] = wd & 0xFF; 637 pVga->CRTC[21] = vd & 0xFF; 638 pVga->CRTC[22] = (vt + 1) & 0xFF; 639 640 if (mode->Flags & V_DBLSCAN) 641 pVga->CRTC[9] |= 0x80; 642 643 /* Per DDK vid.c line 75, sync polarity should be controlled 644 * via the TVP3026 RAMDAC register 1D and so MISC Output Register 645 * should always have bits 6 and 7 set. */ 646 647 pVga->MiscOutReg |= 0xC0; 648 if ((mode->Flags & (V_PHSYNC | V_NHSYNC)) && 649 (mode->Flags & (V_PVSYNC | V_NVSYNC))) 650 { 651 if (mode->Flags & V_PHSYNC) 652 pReg->DacRegs[index_1d] |= 0x01; 653 if (mode->Flags & V_PVSYNC) 654 pReg->DacRegs[index_1d] |= 0x02; 655 } 656 else 657 { 658 int VDisplay = mode->VDisplay; 659 if (mode->Flags & V_DBLSCAN) 660 VDisplay *= 2; 661 if (VDisplay < 400) 662 pReg->DacRegs[index_1d] |= 0x01; /* +hsync -vsync */ 663 else if (VDisplay < 480) 664 pReg->DacRegs[index_1d] |= 0x02; /* -hsync +vsync */ 665 else if (VDisplay < 768) 666 pReg->DacRegs[index_1d] |= 0x00; /* -hsync -vsync */ 667 else 668 pReg->DacRegs[index_1d] |= 0x03; /* +hsync +vsync */ 669 } 670 671 if (pMga->SyncOnGreen) 672 pReg->DacRegs[index_1d] |= 0x20; 673 674 pReg->Option = 0x402C0100; /* fine for 2064 and 2164 */ 675 676 if (pMga->Interleave) 677 pReg->Option |= 0x1000; 678 else 679 pReg->Option &= ~0x1000; 680 681 /* must always have the pci retries on but rely on 682 polling to keep them from occuring */ 683 pReg->Option &= ~0x20000000; 684 685 pVga->MiscOutReg |= 0x0C; 686 /* XXX Need to check the first argument */ 687 MGATi3026SetPCLK( pScrn, mode->Clock, 1 << BppShift ); 688 689 /* this one writes registers rather than writing to the 690 mgaReg->ModeReg and letting Restore write to the hardware 691 but that's no big deal since we will Restore right after 692 this function */ 693 694 MGA_NOT_HAL(MGATi3026SetMCLK(pScrn, MGAdac->MemoryClock)); 695 696#ifdef DEBUG 697 ErrorF("%6ld: %02X %02X %02X %02X %02X %02X %08lX\n", mode->Clock, 698 pReg->DacClk[0], pReg->DacClk[1], pReg->DacClk[2], pReg->DacClk[3], pReg->DacClk[4], pReg->DacClk[5], pReg->Option); 699 for (i=0; i<sizeof(MGADACregs); i++) ErrorF("%02X ", pReg->DacRegs[i]); 700 for (i=0; i<6; i++) ErrorF(" %02X", pReg->ExtVga[i]); 701 ErrorF("\n"); 702#endif 703 704 /* This disables the VGA memory aperture */ 705 pVga->MiscOutReg &= ~0x02; 706 return(TRUE); 707} 708 709/* 710 * MGA3026Restore -- for mga2064 with ti3026 711 * 712 * This function restores a video mode. It basically writes out all of 713 * the registers that have previously been saved in the vgaMGARec data 714 * structure. 715 */ 716static void 717MGA3026Restore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg, 718 Bool restoreFonts) 719{ 720 int i; 721 MGAPtr pMga = MGAPTR(pScrn); 722 723 /* 724 * Code is needed to get things back to bank zero. 725 */ 726 for (i = 0; i < 6; i++) 727 OUTREG16(0x1FDE, (mgaReg->ExtVga[i] << 8) | i); 728 729#ifdef XSERVER_LIBPCIACCESS 730 pci_device_cfg_write_bits(pMga->PciInfo, OPTION_MASK, mgaReg->Option, 731 PCI_OPTION_REG); 732#else 733 pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, OPTION_MASK, 734 mgaReg->Option); 735#endif 736 737 MGA_NOT_HAL( 738 /* select pixel clock PLL as clock source */ 739 outTi3026(TVP3026_CLK_SEL, 0, mgaReg->DacRegs[3]); 740 741 /* set loop and pixel clock PLL PLLEN bits to 0 */ 742 outTi3026(TVP3026_PLL_ADDR, 0, 0x2A); 743 outTi3026(TVP3026_LOAD_CLK_DATA, 0, 0); 744 outTi3026(TVP3026_PIX_CLK_DATA, 0, 0); 745 ); /* MGA_NOT_HAL */ 746 747 /* 748 * This function handles restoring the generic VGA registers. 749 */ 750 vgaHWRestore(pScrn, vgaReg, 751 VGA_SR_MODE | (restoreFonts ? VGA_SR_FONTS : 0)); 752 MGA3026RestorePalette(pScrn, vgaReg->DAC); 753 754 /* 755 * Code to restore SVGA registers that have been saved/modified 756 * goes here. 757 */ 758 759 MGA_NOT_HAL( 760 /* program pixel clock PLL */ 761 outTi3026(TVP3026_PLL_ADDR, 0, 0x00); 762 for (i = 0; i < 3; i++) 763 outTi3026(TVP3026_PIX_CLK_DATA, 0, mgaReg->DacClk[i]); 764 765 if (vgaReg->MiscOutReg & 0x08) { 766 /* poll until pixel clock PLL LOCK bit is set */ 767 outTi3026(TVP3026_PLL_ADDR, 0, 0x3F); 768 while ( ! (inTi3026(TVP3026_PIX_CLK_DATA) & 0x40) ); 769 } 770 771 /* set Q divider for loop clock PLL */ 772 outTi3026(TVP3026_MCLK_CTL, 0, mgaReg->DacRegs[18]); 773 ); /* MGA_NOT_HAL */ 774 775 /* program loop PLL */ 776 outTi3026(TVP3026_PLL_ADDR, 0, 0x00); 777 for (i = 3; i < 6; i++) 778 outTi3026(TVP3026_LOAD_CLK_DATA, 0, mgaReg->DacClk[i]); 779 780 MGA_NOT_HAL( 781 if ((vgaReg->MiscOutReg & 0x08) && ((mgaReg->DacClk[3] & 0xC0) == 0xC0) ) { 782 /* poll until loop PLL LOCK bit is set */ 783 outTi3026(TVP3026_PLL_ADDR, 0, 0x3F); 784 while ( ! (inTi3026(TVP3026_LOAD_CLK_DATA) & 0x40) ); 785 } 786 ); /* MGA_NOT_HAL */ 787 788 /* 789 * restore other DAC registers 790 */ 791 for (i = 0; i < DACREGSIZE; i++) 792 outTi3026(MGADACregs[i], 0, mgaReg->DacRegs[i]); 793 794#ifdef DEBUG 795 ErrorF("PCI retry (0-enabled / 1-disabled): %d\n", 796 !!(mgaReg->Option & 0x20000000)); 797#endif 798} 799 800/* 801 * MGA3026Save -- for mga2064 with ti3026 802 * 803 * This function saves the video state. 804 */ 805static void 806MGA3026Save(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg, 807 Bool saveFonts) 808{ 809 int i; 810 MGAPtr pMga = MGAPTR(pScrn); 811 812 /* Allocate the DacRegs space if not done already */ 813 if (mgaReg->DacRegs == NULL) { 814 mgaReg->DacRegs = xnfcalloc(DACREGSIZE, 1); 815 } 816 817 /* 818 * Code is needed to get back to bank zero. 819 */ 820 OUTREG16(0x1FDE, 0x0004); 821 822 /* 823 * This function will handle creating the data structure and filling 824 * in the generic VGA portion. 825 */ 826 vgaHWSave(pScrn, vgaReg, VGA_SR_MODE | (saveFonts ? VGA_SR_FONTS : 0)); 827 MGA3026SavePalette(pScrn, vgaReg->DAC); 828 829 /* 830 * The port I/O code necessary to read in the extended registers 831 * into the fields of the vgaMGARec structure. 832 */ 833 for (i = 0; i < 6; i++) 834 { 835 OUTREG8(0x1FDE, i); 836 mgaReg->ExtVga[i] = INREG8(0x1FDF); 837 } 838 839 MGA_NOT_HAL( 840 outTi3026(TVP3026_PLL_ADDR, 0, 0x00); 841 for (i = 0; i < 3; i++) 842 outTi3026(TVP3026_PIX_CLK_DATA, 0, mgaReg->DacClk[i] = 843 inTi3026(TVP3026_PIX_CLK_DATA)); 844 845 outTi3026(TVP3026_PLL_ADDR, 0, 0x00); 846 for (i = 3; i < 6; i++) 847 outTi3026(TVP3026_LOAD_CLK_DATA, 0, mgaReg->DacClk[i] = 848 inTi3026(TVP3026_LOAD_CLK_DATA)); 849 ); /* MGA_NOT_HAL */ 850 851 for (i = 0; i < DACREGSIZE; i++) 852 mgaReg->DacRegs[i] = inTi3026(MGADACregs[i]); 853 854#ifdef XSERVER_LIBPCIACCESS 855 pci_device_cfg_read_u32(pMga->PciInfo, & mgaReg->Option, 856 PCI_OPTION_REG); 857#else 858 mgaReg->Option = pciReadLong(pMga->PciTag, PCI_OPTION_REG); 859#endif 860 861#ifdef DEBUG 862 ErrorF("read: %02X %02X %02X %02X %02X %02X %08lX\n", 863 mgaReg->DacClk[0], mgaReg->DacClk[1], mgaReg->DacClk[2], mgaReg->DacClk[3], mgaReg->DacClk[4], mgaReg->DacClk[5], mgaReg->Option); 864 for (i=0; i<sizeof(MGADACregs); i++) ErrorF("%02X ", mgaReg->DacRegs[i]); 865 for (i=0; i<6; i++) ErrorF(" %02X", mgaReg->ExtVga[i]); 866 ErrorF("\n"); 867#endif 868} 869 870 871static void 872MGA3026LoadCursorImage( 873 ScrnInfoPtr pScrn, 874 unsigned char *src 875) 876{ 877 MGAPtr pMga = MGAPTR(pScrn); 878 int i = 1024; 879 880 outTi3026(TVP3026_CURSOR_CTL, 0xf3, 0x00); /* reset A9,A8 */ 881 /* reset cursor RAM load address A7..A0 */ 882 outTi3026dreg(TVP3026_WADR_PAL, 0x00); 883 884 while(i--) { 885 while (INREG8(0x1FDA) & 0x01); 886 while (!(INREG8(0x1FDA) & 0x01)); 887 outTi3026dreg(TVP3026_CUR_RAM, *(src++)); 888 } 889} 890 891 892static void 893MGA3026ShowCursor(ScrnInfoPtr pScrn) 894{ 895 MGAPtr pMga = MGAPTR(pScrn); 896 /* Enable cursor - X11 mode */ 897 outTi3026(TVP3026_CURSOR_CTL, 0x6c, 0x13); 898} 899 900static void 901MGA3026HideCursor(ScrnInfoPtr pScrn) 902{ 903 MGAPtr pMga = MGAPTR(pScrn); 904 /* Disable cursor */ 905 outTi3026(TVP3026_CURSOR_CTL, 0xfc, 0x00); 906} 907 908static void 909MGA3026SetCursorPosition( 910 ScrnInfoPtr pScrn, 911 int x, int y 912) 913{ 914 MGAPtr pMga = MGAPTR(pScrn); 915 x += 64; 916 y += 64; 917 918 /* Output position - "only" 12 bits of location documented */ 919 920 outTi3026dreg(TVP3026_CUR_XLOW, x & 0xFF); 921 outTi3026dreg(TVP3026_CUR_XHI, (x >> 8) & 0x0F); 922 outTi3026dreg(TVP3026_CUR_YLOW, y & 0xFF); 923 outTi3026dreg(TVP3026_CUR_YHI, (y >> 8) & 0x0F); 924} 925 926static void 927MGA3026SetCursorColors( 928 ScrnInfoPtr pScrn, 929 int bg, int fg 930) 931{ 932 MGAPtr pMga = MGAPTR(pScrn); 933 /* The TI 3026 cursor is always 8 bits so shift 8, not 10 */ 934 935 /* Background color */ 936 outTi3026dreg(TVP3026_CUR_COL_ADDR, 1); 937 outTi3026dreg(TVP3026_CUR_COL_DATA, (bg & 0x00FF0000) >> 16); 938 outTi3026dreg(TVP3026_CUR_COL_DATA, (bg & 0x0000FF00) >> 8); 939 outTi3026dreg(TVP3026_CUR_COL_DATA, (bg & 0x000000FF)); 940 941 /* Foreground color */ 942 outTi3026dreg(TVP3026_CUR_COL_ADDR, 2); 943 outTi3026dreg(TVP3026_CUR_COL_DATA, (fg & 0x00FF0000) >> 16); 944 outTi3026dreg(TVP3026_CUR_COL_DATA, (fg & 0x0000FF00) >> 8); 945 outTi3026dreg(TVP3026_CUR_COL_DATA, (fg & 0x000000FF)); 946} 947 948static Bool 949MGA3026UseHWCursor(ScreenPtr pScrn, CursorPtr pCurs) 950{ 951 if( XF86SCRNINFO(pScrn)->currentMode->Flags & V_DBLSCAN ) 952 return FALSE; 953 return TRUE; 954} 955 956static const int DDC_SDA_MASK = 1 << 2; 957static const int DDC_SCL_MASK = 1 << 4; 958 959static unsigned int 960MGA3026_ddc1Read(ScrnInfoPtr pScrn) 961{ 962 MGAPtr pMga = MGAPTR(pScrn); 963 964 /* Define the SDA as an input */ 965 outTi3026(TVP3026_GEN_IO_CTL, 0xfb, 0); 966 967 /* wait for Vsync */ 968 while( INREG( MGAREG_Status ) & 0x08 ); 969 while( ! (INREG( MGAREG_Status ) & 0x08) ); 970 971 /* Get the result */ 972 return (inTi3026(TVP3026_GEN_IO_DATA) & DDC_SDA_MASK) >> 2 ; 973} 974 975static void 976MGA3026_I2CGetBits(I2CBusPtr b, int *clock, int *data) 977{ 978 ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; 979 MGAPtr pMga = MGAPTR(pScrn); 980 unsigned char val; 981 982 /* Get the result. */ 983 val = inTi3026(TVP3026_GEN_IO_DATA); 984 *clock = (val & DDC_SCL_MASK) != 0; 985 *data = (val & DDC_SDA_MASK) != 0; 986 987#ifdef DEBUG 988 ErrorF("MGA3026_I2CGetBits(%p,...) val=0x%x, returns clock %d, data %d\n", b, val, *clock, *data); 989#endif 990} 991 992/* 993 * ATTENTION! - the DATA and CLOCK lines need to be tri-stated when 994 * high. Therefore turn off output driver for the line to set line 995 * to high. High signal is maintained by a 15k Ohm pll-up resistor. 996 */ 997static void 998MGA3026_I2CPutBits(I2CBusPtr b, int clock, int data) 999{ 1000 ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; 1001 MGAPtr pMga = MGAPTR(pScrn); 1002 unsigned char val,drv; 1003 1004 /* Write the values */ 1005 val = (clock ? DDC_SCL_MASK : 0) | (data ? DDC_SDA_MASK : 0); 1006 drv = ((!clock) ? DDC_SCL_MASK : 0) | ((!data) ? DDC_SDA_MASK : 0); 1007 /* Define the SDA (Data) and SCL (clock) as outputs */ 1008 outTi3026(TVP3026_GEN_IO_CTL, ~(DDC_SDA_MASK | DDC_SCL_MASK), drv); 1009 outTi3026(TVP3026_GEN_IO_DATA, ~(DDC_SDA_MASK | DDC_SCL_MASK), val); 1010 1011#ifdef DEBUG 1012 ErrorF("MGA3026_I2CPutBits(%p, %d, %d) val=0x%x\n", b, clock, data, val); 1013#endif 1014 1015} 1016 1017 1018Bool 1019MGA3026_i2cInit(ScrnInfoPtr pScrn) 1020{ 1021 MGAPtr pMga = MGAPTR(pScrn); 1022 I2CBusPtr I2CPtr; 1023 1024 I2CPtr = xf86CreateI2CBusRec(); 1025 if(!I2CPtr) return FALSE; 1026 1027 pMga->DDC_Bus1 = I2CPtr; 1028 1029 I2CPtr->BusName = "DDC"; 1030 I2CPtr->scrnIndex = pScrn->scrnIndex; 1031 I2CPtr->I2CPutBits = MGA3026_I2CPutBits; 1032 I2CPtr->I2CGetBits = MGA3026_I2CGetBits; 1033 1034 /* I2CPutByte is timing out, experimenting with AcknTimeout 1035 * default is 2CPtr->AcknTimeout = 5; 1036 */ 1037 /* I2CPtr->AcknTimeout = 10; */ 1038 1039 if (!xf86I2CBusInit(I2CPtr)) { 1040 return FALSE; 1041 } 1042 return TRUE; 1043} 1044 1045static void 1046MGA3026RamdacInit(ScrnInfoPtr pScrn) 1047{ 1048 MGAPtr pMga; 1049 MGARamdacPtr MGAdac; 1050 1051 pMga = MGAPTR(pScrn); 1052 MGAdac = &pMga->Dac; 1053 1054 MGAdac->isHwCursor = TRUE; 1055 MGAdac->CursorMaxWidth = 64; 1056 MGAdac->CursorMaxHeight = 64; 1057 MGAdac->SetCursorColors = MGA3026SetCursorColors; 1058 MGAdac->SetCursorPosition = MGA3026SetCursorPosition; 1059 MGAdac->LoadCursorImage = MGA3026LoadCursorImage; 1060 MGAdac->HideCursor = MGA3026HideCursor; 1061 MGAdac->ShowCursor = MGA3026ShowCursor; 1062 MGAdac->UseHWCursor = MGA3026UseHWCursor; 1063 MGAdac->CursorFlags = 1064#if X_BYTE_ORDER == X_LITTLE_ENDIAN 1065 HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | 1066#endif 1067 HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 1068 HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED; 1069 1070 MGAdac->LoadPalette = MGA3026LoadPalette; 1071 MGAdac->RestorePalette = MGA3026RestorePalette; 1072 1073 MGAdac->maxPixelClock = pMga->bios.pixel.max_freq; 1074 MGAdac->ClockFrom = X_PROBED; 1075 1076 MGAdac->MemoryClock = pMga->bios.mem_clock; 1077 MGAdac->MemClkFrom = X_PROBED; 1078 MGAdac->SetMemClk = TRUE; 1079 1080 1081 /* safety check */ 1082 if ( (MGAdac->MemoryClock < 40000) || 1083 (MGAdac->MemoryClock > 70000) ) 1084 MGAdac->MemoryClock = 50000; 1085 1086 /* 1087 * Should initialise a sane default when the probed value is 1088 * obviously garbage. 1089 */ 1090 1091 /* Check if interleaving can be used and set the rounding value */ 1092 if (pScrn->videoRam > 2048) 1093 pMga->Interleave = TRUE; 1094 else { 1095 pMga->Interleave = FALSE; 1096 pMga->BppShifts[0]++; 1097 pMga->BppShifts[1]++; 1098 pMga->BppShifts[2]++; 1099 pMga->BppShifts[3]++; 1100 } 1101 1102 pMga->Roundings[0] = 128 >> pMga->BppShifts[0]; 1103 pMga->Roundings[1] = 128 >> pMga->BppShifts[1]; 1104 pMga->Roundings[2] = 128 >> pMga->BppShifts[2]; 1105 pMga->Roundings[3] = 128 >> pMga->BppShifts[3]; 1106 1107 /* Set Fast bitblt flag */ 1108 pMga->HasFBitBlt = pMga->bios.fast_bitblt; 1109} 1110 1111void MGA3026LoadPalette( 1112 ScrnInfoPtr pScrn, 1113 int numColors, 1114 int *indices, 1115 LOCO *colors, 1116 VisualPtr pVisual 1117){ 1118 MGAPtr pMga = MGAPTR(pScrn); 1119 int i, index; 1120 1121 if (pVisual->nplanes == 16) { 1122 for(i = 0; i < numColors; i++) { 1123 index = indices[i]; 1124 outTi3026dreg(MGA1064_WADR_PAL, index << 2); 1125 outTi3026dreg(MGA1064_COL_PAL, colors[index >> 1].red); 1126 outTi3026dreg(MGA1064_COL_PAL, colors[index].green); 1127 outTi3026dreg(MGA1064_COL_PAL, colors[index >> 1].blue); 1128 1129 /* we have to write 2 indices since the pixel X on the 1130 TVP3026 has green colors at different locations from 1131 the red and blue colors */ 1132 if(index <= 31) { 1133 outTi3026dreg(MGA1064_WADR_PAL, index << 3); 1134 outTi3026dreg(MGA1064_COL_PAL, colors[index].red); 1135 outTi3026dreg(MGA1064_COL_PAL, colors[(index << 1) + 1].green); 1136 outTi3026dreg(MGA1064_COL_PAL, colors[index].blue); 1137 } 1138 } 1139 } else { 1140 int shift = (pVisual->nplanes == 15) ? 3 : 0; 1141 1142 for(i = 0; i < numColors; i++) { 1143 index = indices[i]; 1144 outTi3026dreg(MGA1064_WADR_PAL, index << shift); 1145 outTi3026dreg(MGA1064_COL_PAL, colors[index].red); 1146 outTi3026dreg(MGA1064_COL_PAL, colors[index].green); 1147 outTi3026dreg(MGA1064_COL_PAL, colors[index].blue); 1148 } 1149 } 1150} 1151 1152 1153static void 1154MGA3026SavePalette(ScrnInfoPtr pScrn, unsigned char* pntr) 1155{ 1156 MGAPtr pMga = MGAPTR(pScrn); 1157 int i = 768; 1158 1159 outTi3026dreg(TVP3026_RADR_PAL, 0x00); 1160 while(i--) 1161 *(pntr++) = inTi3026dreg(TVP3026_COL_PAL); 1162} 1163 1164static void 1165MGA3026RestorePalette(ScrnInfoPtr pScrn, unsigned char* pntr) 1166{ 1167 MGAPtr pMga = MGAPTR(pScrn); 1168 int i = 768; 1169 1170 outTi3026dreg(TVP3026_WADR_PAL, 0x00); 1171 while(i--) 1172 outTi3026dreg(TVP3026_COL_PAL, *(pntr++)); 1173} 1174 1175 1176void MGA2064SetupFuncs(ScrnInfoPtr pScrn) 1177{ 1178 MGAPtr pMga = MGAPTR(pScrn); 1179 1180 pMga->PreInit = MGA3026RamdacInit; 1181 pMga->Save = MGA3026Save; 1182 pMga->Restore = MGA3026Restore; 1183 pMga->ModeInit = MGA3026Init; 1184 pMga->ddc1Read = MGA3026_ddc1Read; 1185 /* vgaHWddc1SetSpeed will only work if the card is in VGA mode */ 1186 pMga->DDC1SetSpeed = vgaHWddc1SetSpeedWeak(); 1187 pMga->i2cInit = MGA3026_i2cInit; 1188} 1189