diff options
Diffstat (limited to 'src/mga_dac3026.c')
-rw-r--r-- | src/mga_dac3026.c | 833 |
1 files changed, 8 insertions, 825 deletions
diff --git a/src/mga_dac3026.c b/src/mga_dac3026.c index 1eddefd..a108e22 100644 --- a/src/mga_dac3026.c +++ b/src/mga_dac3026.c @@ -55,828 +55,14 @@ #include "xf86DDC.h" -/* - * Only change these bits in the Option register. Make sure that the - * vgaioen bit is never in this mask because it is controlled elsewhere - */ -#define OPTION_MASK 0xFFEFFEFF /* ~(eepromwt | vgaioen) */ +#include "mga_dac3026.h" -static void MGA3026LoadPalette(ScrnInfoPtr, int, int*, LOCO*, VisualPtr); -static void MGA3026SavePalette(ScrnInfoPtr, unsigned char*); -static void MGA3026RestorePalette(ScrnInfoPtr, unsigned char*); static void MGA3026RamdacInit(ScrnInfoPtr); -static void MGA3026Save(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool); -static void MGA3026Restore(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool); -static Bool MGA3026Init(ScrnInfoPtr, DisplayModePtr); static Bool MGA3026_i2cInit(ScrnInfoPtr pScrn); - /* * implementation */ - -/* - * indexes to ti3026 registers (the order is important) - */ -const static unsigned char MGADACregs[] = { - 0x0F, 0x18, 0x19, 0x1A, 0x1C, 0x1D, 0x1E, 0x2A, 0x2B, 0x30, - 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, - 0x06 -}; - -/* note: to fix a cursor hw glitch, register 0x37 (blue color key) needs - to be set to magic numbers, even though they are "never" used because - blue keying disabled in 0x38. - - Matrox sez: - - ...The more precise statement of the software workaround is to insure - that bits 7-5 of register 0x37 (Blue Color Key High) and bits 7-5 of - register 0x38 (HZOOM)are the same... -*/ - -/* also note: the values of the MUX control register 0x19 (index [2]) can be - found in table 2-17 of the 3026 manual. If interlace is set, the values - listed here are incremented by one. -*/ - -#define DACREGSIZE sizeof(MGADACregs) -/* - * initial values of ti3026 registers - */ -const static unsigned char MGADACbpp8[DACREGSIZE] = { - 0x06, 0x80, 0x4b, 0x25, 0x00, 0x00, 0x0C, 0x00, 0x1E, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0, 0x00, - 0x00 -}; -const static unsigned char MGADACbpp16[DACREGSIZE] = { - 0x07, 0x45, 0x53, 0x15, 0x00, 0x00, 0x2C, 0x00, 0x1E, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x10, 0, 0x00, - 0x00 -}; -/* - * [0] value was 0x07, but changed to 0x06 by Doug Merrit to fix high res - * stripe glitches and clock glitches at 24bpp. - */ -/* [0] value is now set inside of MGA3026Init, based on the silicon revision - It is still set to 7 or 6 based on the revision, though, since setting to - 8 as in the documentation makes (some?) revB chips get the colors wrong... - maybe BGR instead of RGB? This only applies to 24bpp, since it is the only - one documented as depending on revision. - */ - -const static unsigned char MGADACbpp24[DACREGSIZE] = { - 0x06, 0x56, 0x5b, 0x25, 0x00, 0x00, 0x2C, 0x00, 0x1E, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x10, 0, 0x00, - 0x00 -}; -const static unsigned char MGADACbpp32[DACREGSIZE] = { - 0x07, 0x46, 0x5b, 0x05, 0x00, 0x00, 0x2C, 0x00, 0x1E, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x10, 0, 0x00, - 0x00 -}; - -/* on at least some 2064Ws, the PSEL line flips at 4MB or so, so PSEL keying - has to be off in register 0x1e -> bit4 clear */ - -const static unsigned char MGADACbpp8plus24[DACREGSIZE] = { - 0x07, 0x06, 0x5b, 0x05, 0x00, 0x00, 0x2C, 0x00, 0x1E, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x00, 0x00, - 0x00 -}; - -/* - * Read/write to the DAC via MMIO - */ - -/* - * These were functions. Use macros instead to avoid the need to - * pass pMga to them. - */ - -#define inTi3026dreg(reg) INREG8(RAMDAC_OFFSET + (reg)) - -#define outTi3026dreg(reg, val) OUTREG8(RAMDAC_OFFSET + (reg), val) - -#define inTi3026(reg) \ - (outTi3026dreg(TVP3026_INDEX, reg), inTi3026dreg(TVP3026_DATA)) - -#define outTi3026(reg, mask, val) \ - do { /* note: mask and reg may get evaluated twice */ \ - unsigned char tmp = (mask) ? (inTi3026(reg) & (mask)) : 0; \ - outTi3026dreg(TVP3026_INDEX, reg); \ - outTi3026dreg(TVP3026_DATA, tmp | (val)); \ - } while (0) - - -/* - * MGATi3026CalcClock - Calculate the PLL settings (m, n, p). - * - * DESCRIPTION - * For more information, refer to the Texas Instruments - * "TVP3026 Data Manual" (document SLAS098B). - * Section 2.4 "PLL Clock Generators" - * Appendix A "Frequency Synthesis PLL Register Settings" - * Appendix B "PLL Programming Examples" - * - * PARAMETERS - * f_out IN Desired clock frequency. - * f_max IN Maximum allowed clock frequency. - * m OUT Value of PLL 'm' register. - * n OUT Value of PLL 'n' register. - * p OUT Value of PLL 'p' register. - * - * HISTORY - * January 11, 1997 - [aem] Andrew E. Mileski - * Split off from MGATi3026SetClock. - */ - -/* The following values are in kHz */ -#define TI_MIN_VCO_FREQ 110000 -#define TI_MAX_VCO_FREQ 220000 -#define TI_MAX_MCLK_FREQ 100000 -#define TI_REF_FREQ 14318.18 - -static double -MGATi3026CalcClock ( - long f_out, long f_max, - int *m, int *n, int *p -){ - int best_m = 0, best_n = 0; - double f_pll, f_vco; - double m_err, inc_m, calc_m; - - /* Make sure that f_min <= f_out <= f_max */ - if ( f_out < ( TI_MIN_VCO_FREQ / 8 )) - f_out = TI_MIN_VCO_FREQ / 8; - if ( f_out > f_max ) - f_out = f_max; - - /* - * f_pll = f_vco / 2 ^ p - * Choose p so that TI_MIN_VCO_FREQ <= f_vco <= TI_MAX_VCO_FREQ - * Note that since TI_MAX_VCO_FREQ = 2 * TI_MIN_VCO_FREQ - * we don't have to bother checking for this maximum limit. - */ - f_vco = ( double ) f_out; - for ( *p = 0; *p < 3 && f_vco < TI_MIN_VCO_FREQ; ( *p )++ ) - f_vco *= 2.0; - - /* - * We avoid doing multiplications by ( 65 - n ), - * and add an increment instead - this keeps any error small. - */ - inc_m = f_vco / ( TI_REF_FREQ * 8.0 ); - - /* Initial value of calc_m for the loop */ - calc_m = inc_m + inc_m + inc_m; - - /* Initial amount of error for an integer - impossibly large */ - m_err = 2.0; - - /* Search for the closest INTEGER value of ( 65 - m ) */ - for ( *n = 3; *n <= 25; ( *n )++, calc_m += inc_m ) { - - /* Ignore values of ( 65 - m ) which we can't use */ - if ( calc_m < 3.0 || calc_m > 64.0 ) - continue; - - /* - * Pick the closest INTEGER (has smallest fractional part). - * The optimizer should clean this up for us. - */ - if (( calc_m - ( int ) calc_m ) < m_err ) { - m_err = calc_m - ( int ) calc_m; - best_m = ( int ) calc_m; - best_n = *n; - } - } - - /* 65 - ( 65 - x ) = x */ - *m = 65 - best_m; - *n = 65 - best_n; - - /* Now all the calculations can be completed */ - f_vco = 8.0 * TI_REF_FREQ * best_m / best_n; - f_pll = f_vco / ( 1 << *p ); - -#ifdef DEBUG - ErrorF( "f_out=%ld f_pll=%.1f f_vco=%.1f n=%d m=%d p=%d\n", - f_out, f_pll, f_vco, *n, *m, *p ); -#endif - - return f_pll; -} - -/* - * MGATi3026SetMCLK - Set the memory clock (MCLK) PLL. - * - * HISTORY - * January 11, 1997 - [aem] Andrew E. Mileski - * Written and tested. - */ -static void -MGATi3026SetMCLK( ScrnInfoPtr pScrn, long f_out ) -{ - int mclk_m, mclk_n, mclk_p; - int pclk_m, pclk_n, pclk_p; - int mclk_ctl; - MGAPtr pMga = MGAPTR(pScrn); - - MGATi3026CalcClock(f_out, TI_MAX_MCLK_FREQ, &mclk_m, &mclk_n, &mclk_p); - - /* Save PCLK settings */ - outTi3026( TVP3026_PLL_ADDR, 0, 0xfc ); - pclk_n = inTi3026( TVP3026_PIX_CLK_DATA ); - outTi3026( TVP3026_PLL_ADDR, 0, 0xfd ); - pclk_m = inTi3026( TVP3026_PIX_CLK_DATA ); - outTi3026( TVP3026_PLL_ADDR, 0, 0xfe ); - pclk_p = inTi3026( TVP3026_PIX_CLK_DATA ); - - /* Stop PCLK (PLLEN = 0, PCLKEN = 0) */ - outTi3026( TVP3026_PLL_ADDR, 0, 0xfe ); - outTi3026( TVP3026_PIX_CLK_DATA, 0, 0x00 ); - - /* Set PCLK to the new MCLK frequency (PLLEN = 1, PCLKEN = 0 ) */ - outTi3026( TVP3026_PLL_ADDR, 0, 0xfc ); - outTi3026( TVP3026_PIX_CLK_DATA, 0, ( mclk_n & 0x3f ) | 0xc0 ); - outTi3026( TVP3026_PIX_CLK_DATA, 0, mclk_m & 0x3f ); - outTi3026( TVP3026_PIX_CLK_DATA, 0, ( mclk_p & 0x03 ) | 0xb0 ); - - /* Wait for PCLK PLL to lock on frequency */ - while (( inTi3026( TVP3026_PIX_CLK_DATA ) & 0x40 ) == 0 ) { - ; - } - - /* Output PCLK on MCLK pin */ - mclk_ctl = inTi3026( TVP3026_MCLK_CTL ); - outTi3026( TVP3026_MCLK_CTL, 0, mclk_ctl & 0xe7 ); - outTi3026( TVP3026_MCLK_CTL, 0, ( mclk_ctl & 0xe7 ) | 0x08 ); - - /* Stop MCLK (PLLEN = 0 ) */ - outTi3026( TVP3026_PLL_ADDR, 0, 0xfb ); - outTi3026( TVP3026_MEM_CLK_DATA, 0, 0x00 ); - - /* Set MCLK to the new frequency (PLLEN = 1) */ - outTi3026( TVP3026_PLL_ADDR, 0, 0xf3 ); - outTi3026( TVP3026_MEM_CLK_DATA, 0, ( mclk_n & 0x3f ) | 0xc0 ); - outTi3026( TVP3026_MEM_CLK_DATA, 0, mclk_m & 0x3f ); - outTi3026( TVP3026_MEM_CLK_DATA, 0, ( mclk_p & 0x03 ) | 0xb0 ); - - /* Wait for MCLK PLL to lock on frequency */ - while (( inTi3026( TVP3026_MEM_CLK_DATA ) & 0x40 ) == 0 ) { - ; - } - - /* Output MCLK PLL on MCLK pin */ - outTi3026( TVP3026_MCLK_CTL, 0, ( mclk_ctl & 0xe7 ) | 0x10 ); - outTi3026( TVP3026_MCLK_CTL, 0, ( mclk_ctl & 0xe7 ) | 0x18 ); - - /* Stop PCLK (PLLEN = 0, PCLKEN = 0 ) */ - outTi3026( TVP3026_PLL_ADDR, 0, 0xfe ); - outTi3026( TVP3026_PIX_CLK_DATA, 0, 0x00 ); - - /* Restore PCLK (PLLEN = ?, PCLKEN = ?) */ - outTi3026( TVP3026_PLL_ADDR, 0, 0xfc ); - outTi3026( TVP3026_PIX_CLK_DATA, 0, pclk_n ); - outTi3026( TVP3026_PIX_CLK_DATA, 0, pclk_m ); - outTi3026( TVP3026_PIX_CLK_DATA, 0, pclk_p ); - - /* Wait for PCLK PLL to lock on frequency */ - while (( inTi3026( TVP3026_PIX_CLK_DATA ) & 0x40 ) == 0 ) { - ; - } -} - -/* - * MGATi3026SetPCLK - Set the pixel (PCLK) and loop (LCLK) clocks. - * - * PARAMETERS - * f_pll IN Pixel clock PLL frequencly in kHz. - * bpp IN Bytes per pixel. - * - * HISTORY - * January 11, 1997 - [aem] Andrew E. Mileski - * Split to simplify code for MCLK (=GCLK) setting. - * - * December 14, 1996 - [aem] Andrew E. Mileski - * Fixed loop clock to be based on the calculated, not requested, - * pixel clock. Added f_max = maximum f_vco frequency. - * - * October 19, 1996 - [aem] Andrew E. Mileski - * Commented the loop clock code (wow, I understand everything now), - * and simplified it a bit. This should really be two separate functions. - * - * October 1, 1996 - [aem] Andrew E. Mileski - * Optimized the m & n picking algorithm. Added maxClock detection. - * Low speed pixel clock fix (per the docs). Documented what I understand. - * - * ?????, ??, ???? - [???] ???????????? - * Based on the TVP3026 code in the S3 driver. - */ - -static void -MGATi3026SetPCLK( ScrnInfoPtr pScrn, long f_out, int bpp ) -{ - /* Pixel clock values */ - int m, n, p; - - /* Loop clock values */ - int lm, ln, lp, lq; - double z; - - /* The actual frequency output by the clock */ - double f_pll; - - long f_max = TI_MAX_VCO_FREQ; - - MGAPtr pMga = MGAPTR(pScrn); - MGARegPtr pReg = &pMga->ModeReg; - - /* Get the maximum pixel clock frequency */ - if ( pMga->MaxClock > TI_MAX_VCO_FREQ ) - f_max = pMga->MaxClock; - - /* Do the calculations for m, n, and p */ - f_pll = MGATi3026CalcClock( f_out, f_max, & m, & n, & p ); - - /* Values for the pixel clock PLL registers */ - pReg->DacClk[ 0 ] = ( n & 0x3f ) | 0xc0; - pReg->DacClk[ 1 ] = ( m & 0x3f ); - pReg->DacClk[ 2 ] = ( p & 0x03 ) | 0xb0; - - /* - * Now that the pixel clock PLL is setup, - * the loop clock PLL must be setup. - */ - - /* - * First we figure out lm, ln, and z. - * Things are different in packed pixel mode (24bpp) though. - */ - if ( pMga->CurrentLayout.bitsPerPixel == 24 ) { - - /* ln:lm = ln:3 */ - lm = 65 - 3; - - /* Check for interleaved mode */ - if ( bpp == 2 ) - /* ln:lm = 4:3 */ - ln = 65 - 4; - else - /* ln:lm = 8:3 */ - ln = 65 - 8; - - /* Note: this is actually 100 * z for more precision */ - z = ( 11000 * ( 65 - ln )) / (( f_pll / 1000 ) * ( 65 - lm )); - } - else { - /* ln:lm = ln:4 */ - lm = 65 - 4; - - /* Note: bpp = bytes per pixel */ - ln = 65 - 4 * ( 64 / 8 ) / bpp; - - /* Note: this is actually 100 * z for more precision */ - z = (( 11000 / 4 ) * ( 65 - ln )) / ( f_pll / 1000 ); - } - - /* - * Now we choose dividers lp and lq so that the VCO frequency - * is within the operating range of 110 MHz to 220 MHz. - */ - - /* Assume no lq divider */ - lq = 0; - - /* Note: z is actually 100 * z for more precision */ - if ( z <= 200.0 ) - lp = 0; - else if ( z <= 400.0 ) - lp = 1; - else if ( z <= 800.0 ) - lp = 2; - else if ( z <= 1600.0 ) - lp = 3; - else { - lp = 3; - lq = ( int )( z / 1600.0 ); - } - - /* Values for the loop clock PLL registers */ - if ( pMga->CurrentLayout.bitsPerPixel == 24 ) { - /* Packed pixel mode values */ - pReg->DacClk[ 3 ] = ( ln & 0x3f ) | 0x80; - pReg->DacClk[ 4 ] = ( lm & 0x3f ) | 0x80; - pReg->DacClk[ 5 ] = ( lp & 0x03 ) | 0xf8; - } else { - /* Non-packed pixel mode values */ - pReg->DacClk[ 3 ] = ( ln & 0x3f ) | 0xc0; - pReg->DacClk[ 4 ] = ( lm & 0x3f ); - pReg->DacClk[ 5 ] = ( lp & 0x03 ) | 0xf0; - } - pReg->DacRegs[ 18 ] = lq | 0x38; - -#ifdef DEBUG - ErrorF( "bpp=%d z=%.1f ln=%d lm=%d lp=%d lq=%d\n", - bpp, z, ln, lm, lp, lq ); -#endif -} - -/* - * MGA3026Init -- for mga2064 with ti3026 - * - * The 'mode' parameter describes the video mode. The 'mode' structure - * as well as the 'vga256InfoRec' structure can be dereferenced for - * information that is needed to initialize the mode. The 'new' macro - * (see definition above) is used to simply fill in the structure. - */ -static Bool -MGA3026Init(ScrnInfoPtr pScrn, DisplayModePtr mode) -{ - int hd, hs, he, ht, vd, vs, ve, vt, wd; - int i, BppShift, index_1d = 0; - const unsigned char* initDAC; - MGAPtr pMga = MGAPTR(pScrn); - MGARamdacPtr MGAdac = &pMga->Dac; - MGAFBLayout *pLayout = &pMga->CurrentLayout; - MGARegPtr pReg = &pMga->ModeReg; - vgaRegPtr pVga = &VGAHWPTR(pScrn)->ModeReg; - - BppShift = pMga->BppShifts[(pLayout->bitsPerPixel >> 3) - 1]; - - switch(pLayout->bitsPerPixel) - { - case 8: - initDAC = MGADACbpp8; - break; - case 16: - initDAC = MGADACbpp16; - break; - case 24: - initDAC = MGADACbpp24; - break; - case 32: - if(pLayout->Overlay8Plus24) - initDAC = MGADACbpp8plus24; - else - initDAC = MGADACbpp32; - break; - default: - FatalError("MGA: unsupported bits per pixel\n"); - } - - /* Allocate the DacRegs space if not done already */ - if (pReg->DacRegs == NULL) { - pReg->DacRegs = xnfcalloc(DACREGSIZE, 1); - } - for (i = 0; i < DACREGSIZE; i++) { - pReg->DacRegs[i] = initDAC[i]; - if (MGADACregs[i] == 0x1D) - index_1d = i; - } - - if((pLayout->bitsPerPixel == 32) && pLayout->Overlay8Plus24) { - pReg->DacRegs[9] = pMga->colorKey; - pReg->DacRegs[10] = pMga->colorKey; - } - - if ( (pLayout->bitsPerPixel == 16) && (pLayout->weight.red == 5) - && (pLayout->weight.green == 5) && (pLayout->weight.blue == 5) ) { - pReg->DacRegs[1] &= ~0x01; - } - if (pMga->Interleave ) pReg->DacRegs[2] += 1; - - - if ( pLayout->bitsPerPixel == 24 ) { - int silicon_rev; - /* we need to set DacRegs[0] differently based on the silicon - * revision of the 3026 RAMDAC, as per page 2-14 of tvp3026.pdf. - * If we have rev A silicon, we want 0x07; rev B silicon wants - * 0x06. - */ - silicon_rev = inTi3026(TVP3026_SILICON_REV); - -#ifdef DEBUG - ErrorF("TVP3026 revision 0x%x (rev %s)\n", - silicon_rev, (silicon_rev <= 0x20) ? "A" : "B"); -#endif - - if(silicon_rev <= 0x20) { - /* rev A */ - pReg->DacRegs[0] = 0x07; - } else { - /* rev B */ - pReg->DacRegs[0] = 0x06; - } - } - - /* - * This will initialize all of the generic VGA registers. - */ - if (!vgaHWInit(pScrn, mode)) - return(FALSE); - - /* - * Here all of the MGA registers get filled in. - */ - hd = (mode->CrtcHDisplay >> 3) - 1; - hs = (mode->CrtcHSyncStart >> 3) - 1; - he = (mode->CrtcHSyncEnd >> 3) - 1; - ht = (mode->CrtcHTotal >> 3) - 1; - vd = mode->CrtcVDisplay - 1; - vs = mode->CrtcVSyncStart - 1; - ve = mode->CrtcVSyncEnd - 1; - vt = mode->CrtcVTotal - 2; - - /* HTOTAL & 0x7 equal to 0x6 in 8bpp or 0x4 in 24bpp causes strange - * vertical stripes - */ - if((ht & 0x07) == 0x06 || (ht & 0x07) == 0x04) - ht++; - - if (pLayout->bitsPerPixel == 24) - wd = (pLayout->displayWidth * 3) >> (4 - BppShift); - else - wd = pLayout->displayWidth >> (4 - BppShift); - - pReg->ExtVga[0] = 0; - pReg->ExtVga[5] = 0; - - if (mode->Flags & V_INTERLACE) - { - pReg->ExtVga[0] = 0x80; - pReg->ExtVga[5] = (hs + he - ht) >> 1; - wd <<= 1; - vt &= 0xFFFE; - - /* enable interlaced cursor */ - pReg->DacRegs[20] |= 0x20; - } - - pReg->ExtVga[0] |= (wd & 0x300) >> 4; - pReg->ExtVga[1] = (((ht - 4) & 0x100) >> 8) | - ((hd & 0x100) >> 7) | - ((hs & 0x100) >> 6) | - (ht & 0x40); - pReg->ExtVga[2] = ((vt & 0xc00) >> 10) | - ((vd & 0x400) >> 8) | - ((vd & 0xc00) >> 7) | - ((vs & 0xc00) >> 5); - if (pLayout->bitsPerPixel == 24) - pReg->ExtVga[3] = (((1 << BppShift) * 3) - 1) | 0x80; - else - pReg->ExtVga[3] = ((1 << BppShift) - 1) | 0x80; - - /* Set viddelay (CRTCEXT3 Bits 3-4). */ - pReg->ExtVga[3] |= (pScrn->videoRam == 8192 ? 0x10 - : pScrn->videoRam == 2048 ? 0x08 : 0x00); - - pReg->ExtVga[4] = 0; - - pVga->CRTC[0] = ht - 4; - pVga->CRTC[1] = hd; - pVga->CRTC[2] = hd; - pVga->CRTC[3] = (ht & 0x1F) | 0x80; - pVga->CRTC[4] = hs; - pVga->CRTC[5] = ((ht & 0x20) << 2) | (he & 0x1F); - pVga->CRTC[6] = vt & 0xFF; - pVga->CRTC[7] = ((vt & 0x100) >> 8 ) | - ((vd & 0x100) >> 7 ) | - ((vs & 0x100) >> 6 ) | - ((vd & 0x100) >> 5 ) | - 0x10 | - ((vt & 0x200) >> 4 ) | - ((vd & 0x200) >> 3 ) | - ((vs & 0x200) >> 2 ); - pVga->CRTC[9] = ((vd & 0x200) >> 4) | 0x40; - pVga->CRTC[16] = vs & 0xFF; - pVga->CRTC[17] = (ve & 0x0F) | 0x20; - pVga->CRTC[18] = vd & 0xFF; - pVga->CRTC[19] = wd & 0xFF; - pVga->CRTC[21] = vd & 0xFF; - pVga->CRTC[22] = (vt + 1) & 0xFF; - - if (mode->Flags & V_DBLSCAN) - pVga->CRTC[9] |= 0x80; - - /* Per DDK vid.c line 75, sync polarity should be controlled - * via the TVP3026 RAMDAC register 1D and so MISC Output Register - * should always have bits 6 and 7 set. */ - - pVga->MiscOutReg |= 0xC0; - if ((mode->Flags & (V_PHSYNC | V_NHSYNC)) && - (mode->Flags & (V_PVSYNC | V_NVSYNC))) - { - if (mode->Flags & V_PHSYNC) - pReg->DacRegs[index_1d] |= 0x01; - if (mode->Flags & V_PVSYNC) - pReg->DacRegs[index_1d] |= 0x02; - } - else - { - int VDisplay = mode->VDisplay; - if (mode->Flags & V_DBLSCAN) - VDisplay *= 2; - if (VDisplay < 400) - pReg->DacRegs[index_1d] |= 0x01; /* +hsync -vsync */ - else if (VDisplay < 480) - pReg->DacRegs[index_1d] |= 0x02; /* -hsync +vsync */ - else if (VDisplay < 768) - pReg->DacRegs[index_1d] |= 0x00; /* -hsync -vsync */ - else - pReg->DacRegs[index_1d] |= 0x03; /* +hsync +vsync */ - } - - if (pMga->SyncOnGreen) - pReg->DacRegs[index_1d] |= 0x20; - - pReg->Option = 0x402C0100; /* fine for 2064 and 2164 */ - - if (pMga->Interleave) - pReg->Option |= 0x1000; - else - pReg->Option &= ~0x1000; - - /* must always have the pci retries on but rely on - polling to keep them from occuring */ - pReg->Option &= ~0x20000000; - - pVga->MiscOutReg |= 0x0C; - /* XXX Need to check the first argument */ - MGATi3026SetPCLK( pScrn, mode->Clock, 1 << BppShift ); - - /* this one writes registers rather than writing to the - mgaReg->ModeReg and letting Restore write to the hardware - but that's no big deal since we will Restore right after - this function */ - - MGA_NOT_HAL(MGATi3026SetMCLK(pScrn, MGAdac->MemoryClock)); - -#ifdef DEBUG - ErrorF("%6ld: %02X %02X %02X %02X %02X %02X %08lX\n", mode->Clock, - pReg->DacClk[0], pReg->DacClk[1], pReg->DacClk[2], pReg->DacClk[3], pReg->DacClk[4], pReg->DacClk[5], pReg->Option); - for (i=0; i<sizeof(MGADACregs); i++) ErrorF("%02X ", pReg->DacRegs[i]); - for (i=0; i<6; i++) ErrorF(" %02X", pReg->ExtVga[i]); - ErrorF("\n"); -#endif - - /* This disables the VGA memory aperture */ - pVga->MiscOutReg &= ~0x02; - return(TRUE); -} - -/* - * MGA3026Restore -- for mga2064 with ti3026 - * - * This function restores a video mode. It basically writes out all of - * the registers that have previously been saved in the vgaMGARec data - * structure. - */ -static void -MGA3026Restore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg, - Bool restoreFonts) -{ - int i; - MGAPtr pMga = MGAPTR(pScrn); - - /* - * Code is needed to get things back to bank zero. - */ - for (i = 0; i < 6; i++) - OUTREG16(0x1FDE, (mgaReg->ExtVga[i] << 8) | i); - - pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, OPTION_MASK, - mgaReg->Option); - - MGA_NOT_HAL( - /* select pixel clock PLL as clock source */ - outTi3026(TVP3026_CLK_SEL, 0, mgaReg->DacRegs[3]); - - /* set loop and pixel clock PLL PLLEN bits to 0 */ - outTi3026(TVP3026_PLL_ADDR, 0, 0x2A); - outTi3026(TVP3026_LOAD_CLK_DATA, 0, 0); - outTi3026(TVP3026_PIX_CLK_DATA, 0, 0); - ); /* MGA_NOT_HAL */ - - /* - * This function handles restoring the generic VGA registers. - */ - vgaHWRestore(pScrn, vgaReg, - VGA_SR_MODE | (restoreFonts ? VGA_SR_FONTS : 0)); - MGA3026RestorePalette(pScrn, vgaReg->DAC); - - /* - * Code to restore SVGA registers that have been saved/modified - * goes here. - */ - - MGA_NOT_HAL( - /* program pixel clock PLL */ - outTi3026(TVP3026_PLL_ADDR, 0, 0x00); - for (i = 0; i < 3; i++) - outTi3026(TVP3026_PIX_CLK_DATA, 0, mgaReg->DacClk[i]); - - if (vgaReg->MiscOutReg & 0x08) { - /* poll until pixel clock PLL LOCK bit is set */ - outTi3026(TVP3026_PLL_ADDR, 0, 0x3F); - while ( ! (inTi3026(TVP3026_PIX_CLK_DATA) & 0x40) ); - } - - /* set Q divider for loop clock PLL */ - outTi3026(TVP3026_MCLK_CTL, 0, mgaReg->DacRegs[18]); - ); /* MGA_NOT_HAL */ - - /* program loop PLL */ - outTi3026(TVP3026_PLL_ADDR, 0, 0x00); - for (i = 3; i < 6; i++) - outTi3026(TVP3026_LOAD_CLK_DATA, 0, mgaReg->DacClk[i]); - - MGA_NOT_HAL( - if ((vgaReg->MiscOutReg & 0x08) && ((mgaReg->DacClk[3] & 0xC0) == 0xC0) ) { - /* poll until loop PLL LOCK bit is set */ - outTi3026(TVP3026_PLL_ADDR, 0, 0x3F); - while ( ! (inTi3026(TVP3026_LOAD_CLK_DATA) & 0x40) ); - } - ); /* MGA_NOT_HAL */ - - /* - * restore other DAC registers - */ - for (i = 0; i < DACREGSIZE; i++) - outTi3026(MGADACregs[i], 0, mgaReg->DacRegs[i]); - -#ifdef DEBUG - ErrorF("PCI retry (0-enabled / 1-disabled): %d\n", - !!(mgaReg->Option & 0x20000000)); -#endif -} - -/* - * MGA3026Save -- for mga2064 with ti3026 - * - * This function saves the video state. - */ -static void -MGA3026Save(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg, - Bool saveFonts) -{ - int i; - MGAPtr pMga = MGAPTR(pScrn); - - /* Allocate the DacRegs space if not done already */ - if (mgaReg->DacRegs == NULL) { - mgaReg->DacRegs = xnfcalloc(DACREGSIZE, 1); - } - - /* - * Code is needed to get back to bank zero. - */ - OUTREG16(0x1FDE, 0x0004); - - /* - * This function will handle creating the data structure and filling - * in the generic VGA portion. - */ - vgaHWSave(pScrn, vgaReg, VGA_SR_MODE | (saveFonts ? VGA_SR_FONTS : 0)); - MGA3026SavePalette(pScrn, vgaReg->DAC); - - /* - * The port I/O code necessary to read in the extended registers - * into the fields of the vgaMGARec structure. - */ - for (i = 0; i < 6; i++) - { - OUTREG8(0x1FDE, i); - mgaReg->ExtVga[i] = INREG8(0x1FDF); - } - - MGA_NOT_HAL( - outTi3026(TVP3026_PLL_ADDR, 0, 0x00); - for (i = 0; i < 3; i++) - outTi3026(TVP3026_PIX_CLK_DATA, 0, mgaReg->DacClk[i] = - inTi3026(TVP3026_PIX_CLK_DATA)); - - outTi3026(TVP3026_PLL_ADDR, 0, 0x00); - for (i = 3; i < 6; i++) - outTi3026(TVP3026_LOAD_CLK_DATA, 0, mgaReg->DacClk[i] = - inTi3026(TVP3026_LOAD_CLK_DATA)); - ); /* MGA_NOT_HAL */ - - for (i = 0; i < DACREGSIZE; i++) - mgaReg->DacRegs[i] = inTi3026(MGADACregs[i]); - - mgaReg->Option = pciReadLong(pMga->PciTag, PCI_OPTION_REG); - -#ifdef DEBUG - ErrorF("read: %02X %02X %02X %02X %02X %02X %08lX\n", - mgaReg->DacClk[0], mgaReg->DacClk[1], mgaReg->DacClk[2], mgaReg->DacClk[3], mgaReg->DacClk[4], mgaReg->DacClk[5], mgaReg->Option); - for (i=0; i<sizeof(MGADACregs); i++) ErrorF("%02X ", mgaReg->DacRegs[i]); - for (i=0; i<6; i++) ErrorF(" %02X", mgaReg->ExtVga[i]); - ErrorF("\n"); -#endif -} - static void MGA3026LoadCursorImage( @@ -1025,7 +211,7 @@ MGA3026_I2CPutBits(I2CBusPtr b, int clock, int data) } -Bool +static Bool MGA3026_i2cInit(ScrnInfoPtr pScrn) { MGAPtr pMga = MGAPTR(pScrn); @@ -1034,8 +220,6 @@ MGA3026_i2cInit(ScrnInfoPtr pScrn) I2CPtr = xf86CreateI2CBusRec(); if(!I2CPtr) return FALSE; - pMga->DDC_Bus1 = I2CPtr; - I2CPtr->BusName = "DDC"; I2CPtr->scrnIndex = pScrn->scrnIndex; I2CPtr->I2CPutBits = MGA3026_I2CPutBits; @@ -1047,9 +231,12 @@ MGA3026_i2cInit(ScrnInfoPtr pScrn) /* I2CPtr->AcknTimeout = 10; */ if (!xf86I2CBusInit(I2CPtr)) { + xf86DestroyI2CBusRec(I2CPtr, TRUE, TRUE); return FALSE; + } else { + pMga->DDC_Bus1 = I2CPtr; + return TRUE; } - return TRUE; } static void @@ -1162,8 +349,7 @@ void MGA3026LoadPalette( } } - -static void +void MGA3026SavePalette(ScrnInfoPtr pScrn, unsigned char* pntr) { MGAPtr pMga = MGAPTR(pScrn); @@ -1174,7 +360,7 @@ MGA3026SavePalette(ScrnInfoPtr pScrn, unsigned char* pntr) *(pntr++) = inTi3026dreg(TVP3026_COL_PAL); } -static void +void MGA3026RestorePalette(ScrnInfoPtr pScrn, unsigned char* pntr) { MGAPtr pMga = MGAPTR(pScrn); @@ -1191,9 +377,6 @@ void MGA2064SetupFuncs(ScrnInfoPtr pScrn) MGAPtr pMga = MGAPTR(pScrn); pMga->PreInit = MGA3026RamdacInit; - pMga->Save = MGA3026Save; - pMga->Restore = MGA3026Restore; - pMga->ModeInit = MGA3026Init; pMga->ddc1Read = MGA3026_ddc1Read; /* vgaHWddc1SetSpeed will only work if the card is in VGA mode */ pMga->DDC1SetSpeed = vgaHWddc1SetSpeedWeak(); |