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