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