📄 mach64_gx.c
字号:
aty_ICS2595_put1bit(locationAddr & 1, info); locationAddr >>= 1; } for (i = 0; i < 8 + 1 + 2 + 2; i++) { aty_ICS2595_put1bit(program_bits & 1, info); program_bits >>= 1; } mdelay(1); /* delay for 1 ms */ (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */ aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info); aty_st_8(CLOCK_CNTL + info->clk_wr_offset, old_clock_cntl | CLOCK_STROBE, info); mdelay(50); /* delay for 50 (15) ms */ aty_st_8(CLOCK_CNTL + info->clk_wr_offset, ((pll->ics2595.locationAddr & 0x0F) | CLOCK_STROBE), info); return;}const struct aty_pll_ops aty_pll_ati18818_1 = { var_to_pll: aty_var_to_pll_18818, pll_to_var: aty_pll_18818_to_var, set_pll: aty_set_pll18818, init_pll: (void *)dummy}; /* * STG 1703 Clock Chip */static int aty_var_to_pll_1703(const struct fb_info_aty *info, u32 vclk_per, u8 bpp, u32 xres, union aty_pll *pll){ u32 mhz100; /* in 0.01 MHz */ u32 program_bits; /* u32 post_divider; */ u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq; u32 temp, tempB; u16 remainder, preRemainder; short divider = 0, tempA; /* Calculate the programming word */ mhz100 = 100000000 / vclk_per; mach64MinFreq = MIN_FREQ_2595; mach64MaxFreq = MAX_FREQ_2595; mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */ /* Calculate program word */ if (mhz100 == 0) program_bits = 0xE0; else { if (mhz100 < mach64MinFreq) mhz100 = mach64MinFreq; if (mhz100 > mach64MaxFreq) mhz100 = mach64MaxFreq; divider = 0; while (mhz100 < (mach64MinFreq << 3)) { mhz100 <<= 1; divider += 0x20; } temp = (unsigned int)(mhz100); temp = (unsigned int)(temp * (MIN_N_1703 + 2)); temp -= (short)(mach64RefFreq << 1); tempA = MIN_N_1703; preRemainder = 0xffff; do { tempB = temp; remainder = tempB % mach64RefFreq; tempB = tempB / mach64RefFreq; if ((tempB & 0xffff) <= 127 && (remainder <= preRemainder)) { preRemainder = remainder; divider &= ~0x1f; divider |= tempA; divider = (divider & 0x00ff) + ((tempB & 0xff) << 8); } temp += mhz100; tempA++; } while (tempA <= (MIN_N_1703 << 1)); program_bits = divider; } pll->ics2595.program_bits = program_bits; pll->ics2595.locationAddr = 0; pll->ics2595.post_divider = divider; /* fuer nix */ pll->ics2595.period_in_ps = vclk_per; return 0;}static u32 aty_pll_1703_to_var(const struct fb_info_aty *info, const union aty_pll *pll){ return(pll->ics2595.period_in_ps); /* default for now */}static void aty_set_pll_1703(const struct fb_info_aty *info, const union aty_pll *pll){ u32 program_bits; u32 locationAddr; char old_crtc_ext_disp; old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info); aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), info); program_bits = pll->ics2595.program_bits; locationAddr = pll->ics2595.locationAddr; /* Program clock */ aty_dac_waste4(info); (void)aty_ld_8(DAC_REGS + 2, info); aty_st_8(DAC_REGS+2, (locationAddr << 1) + 0x20, info); aty_st_8(DAC_REGS+2, 0, info); aty_st_8(DAC_REGS+2, (program_bits & 0xFF00) >> 8, info); aty_st_8(DAC_REGS+2, (program_bits & 0xFF), info); (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */ aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info); return;}const struct aty_pll_ops aty_pll_stg1703 = { var_to_pll: aty_var_to_pll_1703, pll_to_var: aty_pll_1703_to_var, set_pll: aty_set_pll_1703, init_pll: (void *)dummy}; /* * Chrontel 8398 Clock Chip */static int aty_var_to_pll_8398(const struct fb_info_aty *info, u32 vclk_per, u8 bpp, u32 xres, union aty_pll *pll){ u32 tempA, tempB, fOut, longMHz100, diff, preDiff; u32 mhz100; /* in 0.01 MHz */ u32 program_bits; /* u32 post_divider; */ u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq; u16 m, n, k=0, save_m, save_n, twoToKth; /* Calculate the programming word */ mhz100 = 100000000 / vclk_per; mach64MinFreq = MIN_FREQ_2595; mach64MaxFreq = MAX_FREQ_2595; mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */ save_m = 0; save_n = 0; /* Calculate program word */ if (mhz100 == 0) program_bits = 0xE0; else { if (mhz100 < mach64MinFreq) mhz100 = mach64MinFreq; if (mhz100 > mach64MaxFreq) mhz100 = mach64MaxFreq; longMHz100 = mhz100 * 256 / 100; /* 8 bit scale this */ while (mhz100 < (mach64MinFreq << 3)) { mhz100 <<= 1; k++; } twoToKth = 1 << k; diff = 0; preDiff = 0xFFFFFFFF; for (m = MIN_M; m <= MAX_M; m++) { for (n = MIN_N; n <= MAX_N; n++) { tempA = (14.31818 * 65536); tempA *= (n + 8); /* 43..256 */ tempB = twoToKth * 256; tempB *= (m + 2); /* 4..32 */ fOut = tempA / tempB; /* 8 bit scale */ if (longMHz100 > fOut) diff = longMHz100 - fOut; else diff = fOut - longMHz100; if (diff < preDiff) { save_m = m; save_n = n; preDiff = diff; } } } program_bits = (k << 6) + (save_m) + (save_n << 8); } pll->ics2595.program_bits = program_bits; pll->ics2595.locationAddr = 0; pll->ics2595.post_divider = 0; pll->ics2595.period_in_ps = vclk_per; return 0;}static u32 aty_pll_8398_to_var(const struct fb_info_aty *info, const union aty_pll *pll){ return(pll->ics2595.period_in_ps); /* default for now */}static void aty_set_pll_8398(const struct fb_info_aty *info, const union aty_pll *pll){ u32 program_bits; u32 locationAddr; char old_crtc_ext_disp; char tmp; old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info); aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), info); program_bits = pll->ics2595.program_bits; locationAddr = pll->ics2595.locationAddr; /* Program clock */ tmp = aty_ld_8(DAC_CNTL, info); aty_st_8(DAC_CNTL, tmp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, info); aty_st_8(DAC_REGS, locationAddr, info); aty_st_8(DAC_REGS+1, (program_bits & 0xff00) >> 8, info); aty_st_8(DAC_REGS+1, (program_bits & 0xff), info); tmp = aty_ld_8(DAC_CNTL, info); aty_st_8(DAC_CNTL, (tmp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3, info); (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */ aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info); return;}const struct aty_pll_ops aty_pll_ch8398 = { var_to_pll: aty_var_to_pll_8398, pll_to_var: aty_pll_8398_to_var, set_pll: aty_set_pll_8398, init_pll: (void *)dummy}; /* * AT&T 20C408 Clock Chip */static int aty_var_to_pll_408(const struct fb_info_aty *info, u32 vclk_per, u8 bpp, u32 xres, union aty_pll *pll){ u32 mhz100; /* in 0.01 MHz */ u32 program_bits; /* u32 post_divider; */ u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq; u32 temp, tempB; u16 remainder, preRemainder; short divider = 0, tempA; /* Calculate the programming word */ mhz100 = 100000000 / vclk_per; mach64MinFreq = MIN_FREQ_2595; mach64MaxFreq = MAX_FREQ_2595; mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */ /* Calculate program word */ if (mhz100 == 0) program_bits = 0xFF; else { if (mhz100 < mach64MinFreq) mhz100 = mach64MinFreq; if (mhz100 > mach64MaxFreq) mhz100 = mach64MaxFreq; while (mhz100 < (mach64MinFreq << 3)) { mhz100 <<= 1; divider += 0x40; } temp = (unsigned int)mhz100; temp = (unsigned int)(temp * (MIN_N_408 + 2)); temp -= ((short)(mach64RefFreq << 1)); tempA = MIN_N_408; preRemainder = 0xFFFF; do { tempB = temp; remainder = tempB % mach64RefFreq; tempB = tempB / mach64RefFreq; if (((tempB & 0xFFFF) <= 255) && (remainder <= preRemainder)) { preRemainder = remainder; divider &= ~0x3f; divider |= tempA; divider = (divider & 0x00FF) + ((tempB & 0xFF) << 8); } temp += mhz100; tempA++; } while(tempA <= 32); program_bits = divider; } pll->ics2595.program_bits = program_bits; pll->ics2595.locationAddr = 0; pll->ics2595.post_divider = divider; /* fuer nix */ pll->ics2595.period_in_ps = vclk_per; return 0;}static u32 aty_pll_408_to_var(const struct fb_info_aty *info, const union aty_pll *pll){ return(pll->ics2595.period_in_ps); /* default for now */}static void aty_set_pll_408(const struct fb_info_aty *info, const union aty_pll *pll){ u32 program_bits; u32 locationAddr; u8 tmpA, tmpB, tmpC; char old_crtc_ext_disp; old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info); aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), info); program_bits = pll->ics2595.program_bits; locationAddr = pll->ics2595.locationAddr; /* Program clock */ aty_dac_waste4(info); tmpB = aty_ld_8(DAC_REGS + 2, info) | 1; aty_dac_waste4(info); aty_st_8(DAC_REGS + 2, tmpB, info); tmpA = tmpB; tmpC = tmpA; tmpA |= 8; tmpB = 1; aty_st_8(DAC_REGS, tmpB, info); aty_st_8(DAC_REGS + 2, tmpA, info); udelay(400); /* delay for 400 us */ locationAddr = (locationAddr << 2) + 0x40; tmpB = locationAddr; tmpA = program_bits >> 8; aty_st_8(DAC_REGS, tmpB, info); aty_st_8(DAC_REGS + 2, tmpA, info); tmpB = locationAddr + 1; tmpA = (u8)program_bits; aty_st_8(DAC_REGS, tmpB, info); aty_st_8(DAC_REGS + 2, tmpA, info); tmpB = locationAddr + 2; tmpA = 0x77; aty_st_8(DAC_REGS, tmpB, info); aty_st_8(DAC_REGS + 2, tmpA, info); udelay(400); /* delay for 400 us */ tmpA = tmpC & (~(1 | 8)); tmpB = 1; aty_st_8(DAC_REGS, tmpB, info); aty_st_8(DAC_REGS + 2, tmpA, info); (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */ aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info); return;}const struct aty_pll_ops aty_pll_att20c408 = { var_to_pll: aty_var_to_pll_408, pll_to_var: aty_pll_408_to_var, set_pll: aty_set_pll_408, init_pll: (void *)dummy}; /* * Unsupported DAC and Clock Chip */static int aty_set_dac_unsupported(const struct fb_info_aty *info, const union aty_pll *pll, u32 bpp, u32 accel){ aty_st_le32(BUS_CNTL, 0x890e20f1, info); aty_st_le32(DAC_CNTL, 0x47052100, info); /* new in 2.2.3p1 from Geert. ???????? */ aty_st_le32(BUS_CNTL, 0x590e10ff, info); aty_st_le32(DAC_CNTL, 0x47012100, info); return 0;}const struct aty_dac_ops aty_dac_unsupported = { set_dac: aty_set_dac_unsupported,};const struct aty_pll_ops aty_pll_unsupported = { var_to_pll: (void *)dummy, pll_to_var: (void *)dummy, set_pll: (void *)dummy, init_pll: (void *)dummy};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -