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 occurring */ 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("%6d: %02X %02X %02X %02X %02X %02X %08X\n", mode->Clock, 698 pReg->DacClk[0], pReg->DacClk[1], pReg->DacClk[2], pReg->DacClk[3], pReg->DacClk[4], pReg->DacClk[5], (unsigned)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 { 856 uint32_t Option; 857 pci_device_cfg_read_u32(pMga->PciInfo, & Option, 858 PCI_OPTION_REG); 859 mgaReg->Option = Option; 860 } 861#else 862 mgaReg->Option = pciReadLong(pMga->PciTag, PCI_OPTION_REG); 863#endif 864 865#ifdef DEBUG 866 ErrorF("read: %02X %02X %02X %02X %02X %02X %08X\n", 867 mgaReg->DacClk[0], mgaReg->DacClk[1], mgaReg->DacClk[2], mgaReg->DacClk[3], mgaReg->DacClk[4], mgaReg->DacClk[5], (unsigned)mgaReg->Option); 868 for (i=0; i<sizeof(MGADACregs); i++) ErrorF("%02X ", mgaReg->DacRegs[i]); 869 for (i=0; i<6; i++) ErrorF(" %02X", mgaReg->ExtVga[i]); 870 ErrorF("\n"); 871#endif 872} 873 874 875static void 876MGA3026LoadCursorImage( 877 ScrnInfoPtr pScrn, 878 unsigned char *src 879) 880{ 881 MGAPtr pMga = MGAPTR(pScrn); 882 int i = 1024; 883 884 outTi3026(TVP3026_CURSOR_CTL, 0xf3, 0x00); /* reset A9,A8 */ 885 /* reset cursor RAM load address A7..A0 */ 886 outTi3026dreg(TVP3026_WADR_PAL, 0x00); 887 888 while(i--) { 889 while (INREG8(0x1FDA) & 0x01); 890 while (!(INREG8(0x1FDA) & 0x01)); 891 outTi3026dreg(TVP3026_CUR_RAM, *(src++)); 892 } 893} 894 895 896static void 897MGA3026ShowCursor(ScrnInfoPtr pScrn) 898{ 899 MGAPtr pMga = MGAPTR(pScrn); 900 /* Enable cursor - X11 mode */ 901 outTi3026(TVP3026_CURSOR_CTL, 0x6c, 0x13); 902} 903 904static void 905MGA3026HideCursor(ScrnInfoPtr pScrn) 906{ 907 MGAPtr pMga = MGAPTR(pScrn); 908 /* Disable cursor */ 909 outTi3026(TVP3026_CURSOR_CTL, 0xfc, 0x00); 910} 911 912static void 913MGA3026SetCursorPosition( 914 ScrnInfoPtr pScrn, 915 int x, int y 916) 917{ 918 MGAPtr pMga = MGAPTR(pScrn); 919 x += 64; 920 y += 64; 921 922 /* Output position - "only" 12 bits of location documented */ 923 924 outTi3026dreg(TVP3026_CUR_XLOW, x & 0xFF); 925 outTi3026dreg(TVP3026_CUR_XHI, (x >> 8) & 0x0F); 926 outTi3026dreg(TVP3026_CUR_YLOW, y & 0xFF); 927 outTi3026dreg(TVP3026_CUR_YHI, (y >> 8) & 0x0F); 928} 929 930static void 931MGA3026SetCursorColors( 932 ScrnInfoPtr pScrn, 933 int bg, int fg 934) 935{ 936 MGAPtr pMga = MGAPTR(pScrn); 937 /* The TI 3026 cursor is always 8 bits so shift 8, not 10 */ 938 939 /* Background color */ 940 outTi3026dreg(TVP3026_CUR_COL_ADDR, 1); 941 outTi3026dreg(TVP3026_CUR_COL_DATA, (bg & 0x00FF0000) >> 16); 942 outTi3026dreg(TVP3026_CUR_COL_DATA, (bg & 0x0000FF00) >> 8); 943 outTi3026dreg(TVP3026_CUR_COL_DATA, (bg & 0x000000FF)); 944 945 /* Foreground color */ 946 outTi3026dreg(TVP3026_CUR_COL_ADDR, 2); 947 outTi3026dreg(TVP3026_CUR_COL_DATA, (fg & 0x00FF0000) >> 16); 948 outTi3026dreg(TVP3026_CUR_COL_DATA, (fg & 0x0000FF00) >> 8); 949 outTi3026dreg(TVP3026_CUR_COL_DATA, (fg & 0x000000FF)); 950} 951 952static Bool 953MGA3026UseHWCursor(ScreenPtr pScrn, CursorPtr pCurs) 954{ 955 if( XF86SCRNINFO(pScrn)->currentMode->Flags & V_DBLSCAN ) 956 return FALSE; 957 return TRUE; 958} 959 960static const int DDC_SDA_MASK = 1 << 2; 961static const int DDC_SCL_MASK = 1 << 4; 962 963static unsigned int 964MGA3026_ddc1Read(ScrnInfoPtr pScrn) 965{ 966 MGAPtr pMga = MGAPTR(pScrn); 967 968 /* Define the SDA as an input */ 969 outTi3026(TVP3026_GEN_IO_CTL, 0xfb, 0); 970 971 /* wait for Vsync */ 972 while( INREG( MGAREG_Status ) & 0x08 ); 973 while( ! (INREG( MGAREG_Status ) & 0x08) ); 974 975 /* Get the result */ 976 return (inTi3026(TVP3026_GEN_IO_DATA) & DDC_SDA_MASK) >> 2 ; 977} 978 979static void 980MGA3026_I2CGetBits(I2CBusPtr b, int *clock, int *data) 981{ 982 ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; 983 MGAPtr pMga = MGAPTR(pScrn); 984 unsigned char val; 985 986 /* Get the result. */ 987 val = inTi3026(TVP3026_GEN_IO_DATA); 988 *clock = (val & DDC_SCL_MASK) != 0; 989 *data = (val & DDC_SDA_MASK) != 0; 990 991#ifdef DEBUG 992 ErrorF("MGA3026_I2CGetBits(%p,...) val=0x%x, returns clock %d, data %d\n", b, val, *clock, *data); 993#endif 994} 995 996/* 997 * ATTENTION! - the DATA and CLOCK lines need to be tri-stated when 998 * high. Therefore turn off output driver for the line to set line 999 * to high. High signal is maintained by a 15k Ohm pll-up resistor. 1000 */ 1001static void 1002MGA3026_I2CPutBits(I2CBusPtr b, int clock, int data) 1003{ 1004 ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; 1005 MGAPtr pMga = MGAPTR(pScrn); 1006 unsigned char val,drv; 1007 1008 /* Write the values */ 1009 val = (clock ? DDC_SCL_MASK : 0) | (data ? DDC_SDA_MASK : 0); 1010 drv = ((!clock) ? DDC_SCL_MASK : 0) | ((!data) ? DDC_SDA_MASK : 0); 1011 /* Define the SDA (Data) and SCL (clock) as outputs */ 1012 outTi3026(TVP3026_GEN_IO_CTL, ~(DDC_SDA_MASK | DDC_SCL_MASK), drv); 1013 outTi3026(TVP3026_GEN_IO_DATA, ~(DDC_SDA_MASK | DDC_SCL_MASK), val); 1014 1015#ifdef DEBUG 1016 ErrorF("MGA3026_I2CPutBits(%p, %d, %d) val=0x%x\n", b, clock, data, val); 1017#endif 1018 1019} 1020 1021 1022Bool 1023MGA3026_i2cInit(ScrnInfoPtr pScrn) 1024{ 1025 MGAPtr pMga = MGAPTR(pScrn); 1026 I2CBusPtr I2CPtr; 1027 1028 I2CPtr = xf86CreateI2CBusRec(); 1029 if(!I2CPtr) return FALSE; 1030 1031 pMga->DDC_Bus1 = I2CPtr; 1032 1033 I2CPtr->BusName = "DDC"; 1034 I2CPtr->scrnIndex = pScrn->scrnIndex; 1035 I2CPtr->I2CPutBits = MGA3026_I2CPutBits; 1036 I2CPtr->I2CGetBits = MGA3026_I2CGetBits; 1037 1038 /* I2CPutByte is timing out, experimenting with AcknTimeout 1039 * default is 2CPtr->AcknTimeout = 5; 1040 */ 1041 /* I2CPtr->AcknTimeout = 10; */ 1042 1043 if (!xf86I2CBusInit(I2CPtr)) { 1044 return FALSE; 1045 } 1046 return TRUE; 1047} 1048 1049static void 1050MGA3026RamdacInit(ScrnInfoPtr pScrn) 1051{ 1052 MGAPtr pMga; 1053 MGARamdacPtr MGAdac; 1054 1055 pMga = MGAPTR(pScrn); 1056 MGAdac = &pMga->Dac; 1057 1058 MGAdac->isHwCursor = TRUE; 1059 MGAdac->CursorMaxWidth = 64; 1060 MGAdac->CursorMaxHeight = 64; 1061 MGAdac->SetCursorColors = MGA3026SetCursorColors; 1062 MGAdac->SetCursorPosition = MGA3026SetCursorPosition; 1063 MGAdac->LoadCursorImage = MGA3026LoadCursorImage; 1064 MGAdac->HideCursor = MGA3026HideCursor; 1065 MGAdac->ShowCursor = MGA3026ShowCursor; 1066 MGAdac->UseHWCursor = MGA3026UseHWCursor; 1067 MGAdac->CursorFlags = 1068#if X_BYTE_ORDER == X_LITTLE_ENDIAN 1069 HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | 1070#endif 1071 HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 1072 HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED; 1073 1074 MGAdac->LoadPalette = MGA3026LoadPalette; 1075 MGAdac->RestorePalette = MGA3026RestorePalette; 1076 1077 MGAdac->maxPixelClock = pMga->bios.pixel.max_freq; 1078 MGAdac->ClockFrom = X_PROBED; 1079 1080 MGAdac->MemoryClock = pMga->bios.mem_clock; 1081 MGAdac->MemClkFrom = X_PROBED; 1082 MGAdac->SetMemClk = TRUE; 1083 1084 1085 /* safety check */ 1086 if ( (MGAdac->MemoryClock < 40000) || 1087 (MGAdac->MemoryClock > 70000) ) 1088 MGAdac->MemoryClock = 50000; 1089 1090 /* 1091 * Should initialise a sane default when the probed value is 1092 * obviously garbage. 1093 */ 1094 1095 /* Check if interleaving can be used and set the rounding value */ 1096 if (pScrn->videoRam > 2048) 1097 pMga->Interleave = TRUE; 1098 else { 1099 pMga->Interleave = FALSE; 1100 pMga->BppShifts[0]++; 1101 pMga->BppShifts[1]++; 1102 pMga->BppShifts[2]++; 1103 pMga->BppShifts[3]++; 1104 } 1105 1106 pMga->Roundings[0] = 128 >> pMga->BppShifts[0]; 1107 pMga->Roundings[1] = 128 >> pMga->BppShifts[1]; 1108 pMga->Roundings[2] = 128 >> pMga->BppShifts[2]; 1109 pMga->Roundings[3] = 128 >> pMga->BppShifts[3]; 1110 1111 /* Set Fast bitblt flag */ 1112 pMga->HasFBitBlt = pMga->bios.fast_bitblt; 1113} 1114 1115void MGA3026LoadPalette( 1116 ScrnInfoPtr pScrn, 1117 int numColors, 1118 int *indices, 1119 LOCO *colors, 1120 VisualPtr pVisual 1121){ 1122 MGAPtr pMga = MGAPTR(pScrn); 1123 int i, index; 1124 1125 if (pVisual->nplanes == 16) { 1126 for(i = 0; i < numColors; i++) { 1127 index = indices[i]; 1128 outTi3026dreg(MGA1064_WADR_PAL, index << 2); 1129 outTi3026dreg(MGA1064_COL_PAL, colors[index >> 1].red); 1130 outTi3026dreg(MGA1064_COL_PAL, colors[index].green); 1131 outTi3026dreg(MGA1064_COL_PAL, colors[index >> 1].blue); 1132 1133 /* we have to write 2 indices since the pixel X on the 1134 TVP3026 has green colors at different locations from 1135 the red and blue colors */ 1136 if(index <= 31) { 1137 outTi3026dreg(MGA1064_WADR_PAL, index << 3); 1138 outTi3026dreg(MGA1064_COL_PAL, colors[index].red); 1139 outTi3026dreg(MGA1064_COL_PAL, colors[(index << 1) + 1].green); 1140 outTi3026dreg(MGA1064_COL_PAL, colors[index].blue); 1141 } 1142 } 1143 } else { 1144 int shift = (pVisual->nplanes == 15) ? 3 : 0; 1145 1146 for(i = 0; i < numColors; i++) { 1147 index = indices[i]; 1148 outTi3026dreg(MGA1064_WADR_PAL, index << shift); 1149 outTi3026dreg(MGA1064_COL_PAL, colors[index].red); 1150 outTi3026dreg(MGA1064_COL_PAL, colors[index].green); 1151 outTi3026dreg(MGA1064_COL_PAL, colors[index].blue); 1152 } 1153 } 1154} 1155 1156 1157static void 1158MGA3026SavePalette(ScrnInfoPtr pScrn, unsigned char* pntr) 1159{ 1160 MGAPtr pMga = MGAPTR(pScrn); 1161 int i = 768; 1162 1163 outTi3026dreg(TVP3026_RADR_PAL, 0x00); 1164 while(i--) 1165 *(pntr++) = inTi3026dreg(TVP3026_COL_PAL); 1166} 1167 1168static void 1169MGA3026RestorePalette(ScrnInfoPtr pScrn, unsigned char* pntr) 1170{ 1171 MGAPtr pMga = MGAPTR(pScrn); 1172 int i = 768; 1173 1174 outTi3026dreg(TVP3026_WADR_PAL, 0x00); 1175 while(i--) 1176 outTi3026dreg(TVP3026_COL_PAL, *(pntr++)); 1177} 1178 1179 1180void MGA2064SetupFuncs(ScrnInfoPtr pScrn) 1181{ 1182 MGAPtr pMga = MGAPTR(pScrn); 1183 1184 pMga->PreInit = MGA3026RamdacInit; 1185 pMga->Save = MGA3026Save; 1186 pMga->Restore = MGA3026Restore; 1187 pMga->ModeInit = MGA3026Init; 1188 pMga->ddc1Read = MGA3026_ddc1Read; 1189 /* vgaHWddc1SetSpeed will only work if the card is in VGA mode */ 1190 pMga->DDC1SetSpeed = vgaHWddc1SetSpeedWeak(); 1191 pMga->i2cInit = MGA3026_i2cInit; 1192} 1193