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