📄 mach64_gx.c
字号:
aty_StrobeClock(par); aty_ICS2595_put1bit(1, par); /* Send start bits */ aty_ICS2595_put1bit(0, par); /* Start bit */ aty_ICS2595_put1bit(0, par); /* Read / ~Write */ for (i = 0; i < 5; i++) { /* Location 0..4 */ aty_ICS2595_put1bit(locationAddr & 1, par); locationAddr >>= 1; } for (i = 0; i < 8 + 1 + 2 + 2; i++) { aty_ICS2595_put1bit(program_bits & 1, par); program_bits >>= 1; } mdelay(1); /* delay for 1 ms */ (void) aty_ld_8(DAC_REGS, par); /* Clear DAC Counter */ aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par); aty_st_8(CLOCK_CNTL + par->clk_wr_offset, old_clock_cntl | CLOCK_STROBE, par); mdelay(50); /* delay for 50 (15) ms */ aty_st_8(CLOCK_CNTL + par->clk_wr_offset, ((pll->ics2595.locationAddr & 0x0F) | CLOCK_STROBE), par); 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,}; /* * STG 1703 Clock Chip */static int aty_var_to_pll_1703(const struct fb_info *info, u32 vclk_per, u32 bpp, 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 *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 *info, const union aty_pll *pll){ struct atyfb_par *par = (struct atyfb_par *) info->par; u32 program_bits; u32 locationAddr; char old_crtc_ext_disp; old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par); aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par); program_bits = pll->ics2595.program_bits; locationAddr = pll->ics2595.locationAddr; /* Program clock */ aty_dac_waste4(par); (void) aty_ld_8(DAC_REGS + 2, par); aty_st_8(DAC_REGS + 2, (locationAddr << 1) + 0x20, par); aty_st_8(DAC_REGS + 2, 0, par); aty_st_8(DAC_REGS + 2, (program_bits & 0xFF00) >> 8, par); aty_st_8(DAC_REGS + 2, (program_bits & 0xFF), par); (void) aty_ld_8(DAC_REGS, par); /* Clear DAC Counter */ aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par); 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,}; /* * Chrontel 8398 Clock Chip */static int aty_var_to_pll_8398(const struct fb_info *info, u32 vclk_per, u32 bpp, 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 = 938356; /* 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 *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 *info, const union aty_pll *pll){ struct atyfb_par *par = (struct atyfb_par *) info->par; u32 program_bits; u32 locationAddr; char old_crtc_ext_disp; char tmp; old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, par); aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par); program_bits = pll->ics2595.program_bits; locationAddr = pll->ics2595.locationAddr; /* Program clock */ tmp = aty_ld_8(DAC_CNTL, par); aty_st_8(DAC_CNTL, tmp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, par); aty_st_8(DAC_REGS, locationAddr, par); aty_st_8(DAC_REGS + 1, (program_bits & 0xff00) >> 8, par); aty_st_8(DAC_REGS + 1, (program_bits & 0xff), par); tmp = aty_ld_8(DAC_CNTL, par); aty_st_8(DAC_CNTL, (tmp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3, par); (void) aty_ld_8(DAC_REGS, par); /* Clear DAC Counter */ aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par); 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,}; /* * AT&T 20C408 Clock Chip */static int aty_var_to_pll_408(const struct fb_info *info, u32 vclk_per, u32 bpp, 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 *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 *info, const union aty_pll *pll){ struct atyfb_par *par = (struct atyfb_par *) info->par; 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, par); aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), par); program_bits = pll->ics2595.program_bits; locationAddr = pll->ics2595.locationAddr; /* Program clock */ aty_dac_waste4(par); tmpB = aty_ld_8(DAC_REGS + 2, par) | 1; aty_dac_waste4(par); aty_st_8(DAC_REGS + 2, tmpB, par); tmpA = tmpB; tmpC = tmpA; tmpA |= 8; tmpB = 1; aty_st_8(DAC_REGS, tmpB, par); aty_st_8(DAC_REGS + 2, tmpA, par); udelay(400); /* delay for 400 us */ locationAddr = (locationAddr << 2) + 0x40; tmpB = locationAddr; tmpA = program_bits >> 8; aty_st_8(DAC_REGS, tmpB, par); aty_st_8(DAC_REGS + 2, tmpA, par); tmpB = locationAddr + 1; tmpA = (u8) program_bits; aty_st_8(DAC_REGS, tmpB, par); aty_st_8(DAC_REGS + 2, tmpA, par); tmpB = locationAddr + 2; tmpA = 0x77; aty_st_8(DAC_REGS, tmpB, par); aty_st_8(DAC_REGS + 2, tmpA, par); udelay(400); /* delay for 400 us */ tmpA = tmpC & (~(1 | 8)); tmpB = 1; aty_st_8(DAC_REGS, tmpB, par); aty_st_8(DAC_REGS + 2, tmpA, par); (void) aty_ld_8(DAC_REGS, par); /* Clear DAC Counter */ aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, par); 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,}; /* * Unsupported DAC and Clock Chip */static int aty_set_dac_unsupported(const struct fb_info *info, const union aty_pll *pll, u32 bpp, u32 accel){ struct atyfb_par *par = (struct atyfb_par *) info->par; aty_st_le32(BUS_CNTL, 0x890e20f1, par); aty_st_le32(DAC_CNTL, 0x47052100, par); /* new in 2.2.3p1 from Geert. ???????? */ aty_st_le32(BUS_CNTL, 0x590e10ff, par); aty_st_le32(DAC_CNTL, 0x47012100, par); return 0;}static int dummy(void){ 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,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -