📄 s3ramdacs.c
字号:
} else { outb(vgaCRIndex, 0x5C); saveCR5C = inb(vgaCRReg); /* clear 0x20 (RS4) for 3020 mode */ outb(vgaCRReg, saveCR5C & 0xDF); saveTIndx2 = inb(TI_INDEX_REG); /* already twiddled CR55 above */ outb(TI_INDEX_REG, TI_CURS_CONTROL); saveTIdata = inb(TI_DATA_REG); /* clear TI_PLANAR_ACCESS bit */ outb(TI_DATA_REG, saveTIdata & 0x7F); outb(TI_INDEX_REG, TI_ID); if (inb(TI_DATA_REG) == TI_VIEWPOINT25_ID) { /* * Found TI ViewPoint 3025 DAC */ found = TI3025_DAC; saveCR43 &= ~0x02; saveCR45 &= ~0x20; } /* restore this mess */ outb(TI_INDEX_REG, TI_CURS_CONTROL); outb(TI_DATA_REG, saveTIdata); outb(TI_INDEX_REG, saveTIndx2); outb(vgaCRIndex, 0x5C); outb(vgaCRReg, saveCR5C); } outb(TI_INDEX_REG, saveTIndx); outb(vgaCRIndex, 0x55); outb(vgaCRReg, saveCR55); outb(vgaCRIndex, 0x45); outb(vgaCRReg, saveCR45); outb(vgaCRIndex, 0x43); outb(vgaCRReg, saveCR43); return (found == type);}static Bool TI3020_Probe(){ if (!S3_928_ONLY(s3ChipId) && !S3_964_SERIES(s3ChipId)) return FALSE; else if (TI3020_3025_Probe(TI3020_DAC)) { ErrorF("%s %s: Detected a TI ViewPoint 3020 RAMDAC\n", XCONFIG_PROBED, s3InfoRec.name); return TRUE; } else return FALSE; }static Bool TI3025_Probe(){ if (!S3_964_SERIES(s3ChipId)) return FALSE; else if(TI3020_3025_Probe(TI3025_DAC)) { ErrorF("%s %s: Detected a TI ViewPoint 3025 RAMDAC\n", XCONFIG_PROBED, s3InfoRec.name); return TRUE; } else return FALSE;}static int TI3020_3025_PreInit(){ /* Verify that depth is supported by ramdac */ /* all are supported */ /* Set cursor options */ if (OFLG_ISSET(OPTION_NO_TI3020_CURS, &s3InfoRec.options)) { ErrorF("%s %s: Use of Ti3020/25 cursor disabled in XF86Config\n", XCONFIG_GIVEN, s3InfoRec.name); OFLG_CLR(OPTION_TI3020_CURS, &s3InfoRec.options); } else { /* use the ramdac cursor by default */ ErrorF("%s %s: Using hardware cursor from Ti3020/25 RAMDAC\n", OFLG_ISSET(OPTION_TI3020_CURS, &s3InfoRec.options) ? XCONFIG_GIVEN : XCONFIG_PROBED, s3InfoRec.name); OFLG_SET(OPTION_TI3020_CURS, &s3InfoRec.options); } /* Check if PixMux is supported and set the PixMux related flags and variables */ pixMuxPossible = TRUE; allowPixMuxInterlace = FALSE; allowPixMuxSwitching = FALSE; nonMuxMaxClock = 70000; pixMuxLimitedWidths = FALSE; if (S3_964_SERIES(s3ChipId)) { nonMuxMaxClock = 0; /* 964 can only be in pixmux mode when */ pixMuxMinWidth = 0; /* working in enhanced mode */ } /* If there is an internal clock, set s3ClockSelectFunc, maxRawClock numClocks and whatever options need to be set. For external clocks, pass the job to OtherClocksSetup() */ if (DAC_IS_TI3025 && !OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE, &s3InfoRec.clockOptions)) { OFLG_SET(CLOCK_OPTION_TI3025, &s3InfoRec.clockOptions); OFLG_SET(CLOCK_OPTION_PROGRAMABLE, &s3InfoRec.clockOptions); clockchip_probed = XCONFIG_PROBED; } if (OFLG_ISSET(CLOCK_OPTION_TI3025, &s3InfoRec.clockOptions)) { int mclk, m, n, p, mcc, cr5c; s3ClockSelectFunc = ti3025ClockSelect; numClocks = 3; maxRawClock = s3InfoRec.dacSpeeds[0]; outb(vgaCRIndex, 0x5c); cr5c = inb(vgaCRReg); outb(vgaCRReg, cr5c & 0xdf); /* clear RS4 - use 3020 mode */ s3OutTiIndReg(TI_PLL_CONTROL, 0x00, 0x00); n = s3InTiIndReg(TI_MCLK_PLL_DATA) & 0x7f; s3OutTiIndReg(TI_PLL_CONTROL, 0x00, 0x01); m = s3InTiIndReg(TI_MCLK_PLL_DATA) & 0x7f; s3OutTiIndReg(TI_PLL_CONTROL, 0x00, 0x02); p = s3InTiIndReg(TI_MCLK_PLL_DATA) & 0x03; mcc = s3InTiIndReg(TI_MCLK_DCLK_CONTROL); if (mcc & 0x08) mcc = (mcc & 0x07) * 2 + 2; else mcc = 1; mclk = ((1431818 * ((m+2) * 8)) / (n+2) / (1 << p) / mcc + 50) / 100; if (xf86Verbose) ErrorF("%s %s: Using TI 3025 programmable clock (MCLK %1.3f MHz)\n", clockchip_probed, s3InfoRec.name, mclk / 1000.0); if (OFLG_ISSET(OPTION_NUMBER_NINE, &s3InfoRec.options)) { mclk = 55000; if (xf86Verbose) ErrorF("%s %s: Setting MCLK to %1.3f MHz for #9GXE64 Pro\n", XCONFIG_PROBED, s3InfoRec.name, mclk / 1000.0); Ti3025SetClock(2 * mclk, TI_MCLK_PLL_DATA, s3ProgramTi3025Clock); mcc = s3InTiIndReg(TI_MCLK_DCLK_CONTROL); s3OutTiIndReg(TI_MCLK_DCLK_CONTROL,0x00, (mcc & 0xf0) | 0x08); } if (!s3InfoRec.s3MClk) s3InfoRec.s3MClk = mclk; outb(vgaCRIndex, 0x5c); outb(vgaCRReg, cr5c); } /* Ti3020 will have an external clock */ else OtherClocksSetup(); /* external clocks */ /* Make any necessary clock alterations due to multiplexing, clock doubling, etc... s3Probe will do some last minute clock sanity checks when we return */ clockDoublingPossible = TRUE; s3InfoRec.maxClock = s3InfoRec.dacSpeeds[0]; return 1;}static void TI3020_3025_Restore(){ s3OutTiIndReg(TI_MUX_CONTROL_1, 0x00, s3DacRegs[TI_MUX_CONTROL_1]); s3OutTiIndReg(TI_MUX_CONTROL_2, 0x00, s3DacRegs[TI_MUX_CONTROL_2]); s3OutTiIndReg(TI_INPUT_CLOCK_SELECT, 0x00, s3DacRegs[TI_INPUT_CLOCK_SELECT]); s3OutTiIndReg(TI_OUTPUT_CLOCK_SELECT, 0x00, s3DacRegs[TI_OUTPUT_CLOCK_SELECT]); s3OutTiIndReg(TI_GENERAL_CONTROL, 0x00, s3DacRegs[TI_GENERAL_CONTROL]); s3OutTiIndReg(TI_AUXILIARY_CONTROL, 0x00, s3DacRegs[TI_AUXILIARY_CONTROL]); s3OutTiIndReg(TI_GENERAL_IO_CONTROL, 0x00, 0x1f); s3OutTiIndReg(TI_GENERAL_IO_DATA, 0x00, s3DacRegs[TI_GENERAL_IO_DATA]); if (DAC_IS_TI3025) { s3OutTiIndReg(TI_PLL_CONTROL, 0x00, 0x00); s3OutTiIndReg(TI_PIXEL_CLOCK_PLL_DATA, 0x00, s3DacRegs[0 + 0x40]); /* N */ s3OutTiIndReg(TI_PIXEL_CLOCK_PLL_DATA, 0x00, s3DacRegs[1 + 0x40]); /* M */ s3OutTiIndReg(TI_PIXEL_CLOCK_PLL_DATA, 0x00, s3DacRegs[2 + 0x40]); /* P */ s3OutTiIndReg(TI_MCLK_PLL_DATA, 0x00, s3DacRegs[3 + 0x40]); /* N */ s3OutTiIndReg(TI_MCLK_PLL_DATA, 0x00, s3DacRegs[4 + 0x40]); /* M */ s3OutTiIndReg(TI_MCLK_PLL_DATA, 0x00, s3DacRegs[5 + 0x40] | 0x80 ); /* P */ s3OutTiIndReg(TI_LOOP_CLOCK_PLL_DATA, 0x00, s3DacRegs[6 + 0x40]); /* N */ s3OutTiIndReg(TI_LOOP_CLOCK_PLL_DATA, 0x00, s3DacRegs[7 + 0x40]); /* M */ s3OutTiIndReg(TI_LOOP_CLOCK_PLL_DATA, 0x00, s3DacRegs[8 + 0x40]); /* P */ s3OutTiIndReg(TI_TRUE_COLOR_CONTROL, 0x00, s3DacRegs[TI_TRUE_COLOR_CONTROL]); s3OutTiIndReg(TI_MISC_CONTROL, 0x00, s3DacRegs[TI_MISC_CONTROL]); } s3OutTiIndReg(TI_CURS_CONTROL, 0x00, s3DacRegs[TI_CURS_CONTROL]);}static void TI3020_3025_Save(){ if (DAC_IS_TI3025) { unsigned char CR5C; /* switch the ramdac from bt485 to ti3020 mode clearing RS4 */ outb(vgaCRIndex, 0x5C); CR5C = inb(vgaCRReg); outb(vgaCRReg, CR5C & 0xDF); s3DacRegs[TI_CURS_CONTROL] = s3InTiIndReg(TI_CURS_CONTROL); /* clear TI_PLANAR_ACCESS bit */ s3OutTiIndReg(TI_CURS_CONTROL, 0x7F, 0x00); } s3DacRegs[TI_MUX_CONTROL_1] = s3InTiIndReg(TI_MUX_CONTROL_1); s3DacRegs[TI_MUX_CONTROL_2] = s3InTiIndReg(TI_MUX_CONTROL_2); s3DacRegs[TI_INPUT_CLOCK_SELECT] = s3InTiIndReg(TI_INPUT_CLOCK_SELECT); s3DacRegs[TI_OUTPUT_CLOCK_SELECT] = s3InTiIndReg(TI_OUTPUT_CLOCK_SELECT); s3DacRegs[TI_GENERAL_CONTROL] = s3InTiIndReg(TI_GENERAL_CONTROL); s3DacRegs[TI_AUXILIARY_CONTROL] = s3InTiIndReg(TI_AUXILIARY_CONTROL); s3OutTiIndReg(TI_GENERAL_IO_CONTROL, 0x00, 0x1f); s3DacRegs[TI_GENERAL_IO_DATA] = s3InTiIndReg(TI_GENERAL_IO_DATA); if (DAC_IS_TI3025) { s3DacRegs[TI_TRUE_COLOR_CONTROL] = s3InTiIndReg(TI_TRUE_COLOR_CONTROL); s3DacRegs[TI_MISC_CONTROL] = s3InTiIndReg(TI_MISC_CONTROL); s3OutTiIndReg(TI_PLL_CONTROL, 0x00, 0x00); s3DacRegs[0 + 0x40] = s3InTiIndReg(TI_PIXEL_CLOCK_PLL_DATA); /* N */ s3OutTiIndReg(TI_PIXEL_CLOCK_PLL_DATA, 0x00, s3DacRegs[0 + 0x40]); s3DacRegs[1 + 0x40] = s3InTiIndReg(TI_PIXEL_CLOCK_PLL_DATA); /* M */ s3OutTiIndReg(TI_PIXEL_CLOCK_PLL_DATA, 0x00, s3DacRegs[1 + 0x40]); s3DacRegs[2 + 0x40] = s3InTiIndReg(TI_PIXEL_CLOCK_PLL_DATA); /* P */ s3OutTiIndReg(TI_PIXEL_CLOCK_PLL_DATA, 0x00, s3DacRegs[2 + 0x40]); s3DacRegs[3 + 0x40] = s3InTiIndReg(TI_MCLK_PLL_DATA); /* N */ s3OutTiIndReg(TI_MCLK_PLL_DATA, 0x00, s3DacRegs[3 + 0x40]); s3DacRegs[4 + 0x40] = s3InTiIndReg(TI_MCLK_PLL_DATA); /* M */ s3OutTiIndReg(TI_MCLK_PLL_DATA, 0x00, s3DacRegs[4 + 0x40]); s3DacRegs[5 + 0x40] = s3InTiIndReg(TI_MCLK_PLL_DATA); /* P */ s3OutTiIndReg(TI_MCLK_PLL_DATA, 0x00, s3DacRegs[5 + 0x40]); s3DacRegs[6 + 0x40] = s3InTiIndReg(TI_LOOP_CLOCK_PLL_DATA); /* N */ s3OutTiIndReg(TI_LOOP_CLOCK_PLL_DATA, 0x00, s3DacRegs[6 + 0x40]); s3DacRegs[7 + 0x40] = s3InTiIndReg(TI_LOOP_CLOCK_PLL_DATA); /* M */ s3OutTiIndReg(TI_LOOP_CLOCK_PLL_DATA, 0x00, s3DacRegs[7 + 0x40]); s3DacRegs[8 + 0x40] = s3InTiIndReg(TI_LOOP_CLOCK_PLL_DATA); /* P */ s3OutTiIndReg(TI_LOOP_CLOCK_PLL_DATA, 0x00, s3DacRegs[8 + 0x40]); }}static int TI3020_3025_Init(DisplayModePtr mode){ unsigned char tmp, tmp1, tmp2; outb(0x3C4, 1); tmp2 = inb(0x3C5); outb(0x3C5, tmp2 | 0x20); /* blank the screen */ /* change polarity on S3 to pass through control to the 3020 */ tmp = new->MiscOutReg; /* BUG tmp = inb(0x3CC); */ new->MiscOutReg |= 0xC0; tmp1 = 0x00; if (!(tmp & 0x80)) tmp1 |= 0x02; /* invert bits for the 3020 */ if (!(tmp & 0x40)) tmp1 |= 0x01; if (s3DACSyncOnGreen) tmp1 |= 0x20; /* add IOG sync */ s3OutTiIndReg(TI_GENERAL_CONTROL, 0x00, tmp1); s3OutTiIndReg(TI_TRUE_COLOR_CONTROL, 0x00, 0x00); if (DAC_IS_TI3020) { /* the 3025 clock programming code sets the input clock select */ if (mode->Flags & V_DBLCLK) s3OutTiIndReg(TI_INPUT_CLOCK_SELECT, 0x00, TI_ICLK_CLK1_DOUBLE); else s3OutTiIndReg(TI_INPUT_CLOCK_SELECT, 0x00, TI_ICLK_CLK1); } outb(vgaCRIndex, 0x65); if (DAC_IS_TI3025) { if (OFLG_ISSET(OPTION_NUMBER_NINE,&s3InfoRec.options)) { outb(vgaCRReg, 0x82); } else { outb(vgaCRReg, 0); } } else { /* set s3 reg65 for some unknown reason */ if (s3InfoRec.bitsPerPixel == 32) outb(vgaCRReg, 0x80); else if (s3InfoRec.bitsPerPixel == 16) outb(vgaCRReg, 0x40); else outb(vgaCRReg, 0x00); } if (s3PixelMultiplexing) { /* fun timing mods for pixel-multiplexing! */ if (OFLG_ISSET(OPTION_ELSA_W2000PRO,&s3InfoRec.options)) { /* set CR40 acording to Bernhard Bender */ outb(vgaCRIndex, 0x40); outb(vgaCRReg, 0xd1); } else if (DAC_IS_TI3025) { outb(vgaCRIndex, 0x40); outb(vgaCRReg, 0x11); outb(vgaCRIndex, 0x55); outb(vgaCRReg, 0x00); } else { /* set s3 reg53 to parallel addressing by or'ing 0x20 */ outb(vgaCRIndex, 0x53); tmp = inb(vgaCRReg); outb(vgaCRReg, tmp | 0x20); /* set s3 reg55 to external serial by or'ing 0x08 */ outb(vgaCRIndex, 0x55); tmp = inb(vgaCRReg); outb(vgaCRReg, tmp | 0x08); } /* the input clock is already set to clk1 or clk1double (s3.c) */ if (DAC_IS_TI3025) { if (s3InfoRec.bitsPerPixel > 8) s3OutTiIndReg(TI_AUXILIARY_CONTROL, 0, 0x00); else s3OutTiIndReg(TI_AUXILIARY_CONTROL, 0, TI_AUX_W_CMPL); } else { /* set aux control to self clocked, window function complement */ if (s3InfoRec.bitsPerPixel > 8) s3OutTiIndReg(TI_AUXILIARY_CONTROL, 0, TI_AUX_SELF_CLOCK); else s3OutTiIndReg(TI_AUXILIARY_CONTROL, 0, TI_AUX_SELF_CLOCK | TI_AUX_W_CMPL); } if (OFLG_ISSET(OPTION_ELSA_W2000PRO,&s3InfoRec.options)) { int vclock,rclock; /* * The 964 needs different VCLK division depending on the * clock frequenzy used. VCLK/1 for 0-60MHz, VCLK/2 for * 60-120MHz and VCLK/4 for 120-175MHz (or -200MHz, depending * on the RAMDAC actually used) * the RCLK output is tied to the LCLK input which is the same * as SCLK but with no blanking. SCLK is the actual pixel * shift clock for the pixel bus. * RCLK/8 is used because of the 8:1 pixel-multiplexing below. * (964 uses always 8:1 in 256 color modes) */ if (s3InfoRec.clock[mode->Clock] > 120000) { vclock = TI_OCLK_V4; } else if (s3InfoRec.clock[mode->Clock] > 60000){ vclock = TI_OCLK_V2; } else { vclock = TI_OCLK_V1; } if (s3InfoRec.bitsPerPixel == 32) { /* 24bpp */ rclock = TI_OCLK_R2; } else if ((s3InfoRec.bitsPerPixel == 16) || (s3InfoRec.bitsPerPixel == 15)) { /* 15/16bpp */ rclock = TI_OCLK_R4; } else { rclock = TI_OCLK_R8; } s3OutTiIndReg(TI_OUTPUT_CLOCK_SELECT, 0x00, TI_OCLK_S | vclock | rclock); outb(vgaCRIndex, 0x66); tmp = inb(vgaCRReg); outb(vgaCRReg, (tmp & 0xf8) | ((rclock - (vclock >> 3)) & 7)); } else if (DAC_IS_TI3025) { if (s3InfoRec.bitsPerPixel == 32) { /* 24bpp */ s3OutTiIndReg(TI_OUTPUT_CLOCK_SELECT, 0x00, TI_OCLK_S_V2_R2); outb(vgaCRIndex, 0x66); tmp = inb(vgaCRReg); if (mode->Flags & V_DBLCLK) outb(vgaCRReg, (tmp & 0xf8) | 0x00); else outb(vgaCRReg, (tmp & 0xf8) | 0x01); } else if (s3InfoRec.bitsPerPixel == 16) { /* 5-6-5 */ s3OutTiIndReg(TI_OUTPUT_CLOCK_SELECT, 0x00, TI_OCLK_S_V2_R4); outb(vgaCRIndex, 0x66); tmp = inb(vgaCRReg); if (mode->Flags & V_DBLCLK) outb(vgaCRReg, (tmp & 0xf8) | 0x01); else outb(vgaCRReg, (tmp & 0xf8) | 0x02); } else { s3OutTiIndReg(TI_OUTPUT_CLOCK_SELECT, 0x00, TI_OCLK_S_V2_R8); outb(vgaCRIndex, 0x66); tmp = inb(vgaCRReg); if (mode->Flags & V_DBLCLK) outb(vgaCRReg, (tmp & 0xf8) | 0x02); else outb(vgaCRReg, (tmp & 0xf8) | 0x03); } } else { /* * for all other boards with Ti3020 (only #9 level 14/16 ?) * set output clocking to VCLK/4, RCLK/8 like the fixed Bt485. * RCLK/8 is used because of the 8:1 pixel-multiplexing below. */ if (s3InfoRec.bitsPerPixel == 32) { /* 24bpp */ s3OutTiIndReg(TI_OUTPUT_CLOCK_SELECT, 0x00, TI_OCLK_S_V1_R2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -