📄 radeonfb.c
字号:
break; case MT_CTV: pret = "CTV"; break; case MT_STV: pret = "STV"; break; } return pret;}/* * 2D engine routines */static __inline__ void radeon_engine_flush (struct radeonfb_info *rinfo){ int i; /* initiate flush */ OUTREGP(RB2D_DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL, ~RB2D_DC_FLUSH_ALL); for (i=0; i < 2000000; i++) { if (!(INREG(RB2D_DSTCACHE_CTLSTAT) & RB2D_DC_BUSY)) break; }}static __inline__ void _radeon_fifo_wait (struct radeonfb_info *rinfo, int entries){ int i; for (i=0; i<2000000; i++) if ((INREG(RBBM_STATUS) & 0x7f) >= entries) return;}static __inline__ void _radeon_engine_idle (struct radeonfb_info *rinfo){ int i; /* ensure FIFO is empty before waiting for idle */ _radeon_fifo_wait (rinfo, 64); for (i=0; i<2000000; i++) { if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) { radeon_engine_flush (rinfo); return; } }}#define radeon_engine_idle() _radeon_engine_idle(rinfo)#define radeon_fifo_wait(entries) _radeon_fifo_wait(rinfo,entries)/* * helper routines */static __inline__ u32 radeon_get_dstbpp(u16 depth){ switch (depth) { case 8: return DST_8BPP; case 15: return DST_15BPP; case 16: return DST_16BPP; case 32: return DST_32BPP; default: return 0; }}static inline int var_to_depth(const struct fb_var_screeninfo *var){ if (var->bits_per_pixel != 16) return var->bits_per_pixel; return (var->green.length == 6) ? 16 : 15;}static void _radeon_engine_reset(struct radeonfb_info *rinfo){ u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset; radeon_engine_flush (rinfo); clock_cntl_index = INREG(CLOCK_CNTL_INDEX); mclk_cntl = INPLL(MCLK_CNTL); OUTPLL(MCLK_CNTL, (mclk_cntl | FORCEON_MCLKA | FORCEON_MCLKB | FORCEON_YCLKA | FORCEON_YCLKB | FORCEON_MC | FORCEON_AIC)); rbbm_soft_reset = INREG(RBBM_SOFT_RESET); OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset | SOFT_RESET_CP | SOFT_RESET_HI | SOFT_RESET_SE | SOFT_RESET_RE | SOFT_RESET_PP | SOFT_RESET_E2 | SOFT_RESET_RB); INREG(RBBM_SOFT_RESET); OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (u32) ~(SOFT_RESET_CP | SOFT_RESET_HI | SOFT_RESET_SE | SOFT_RESET_RE | SOFT_RESET_PP | SOFT_RESET_E2 | SOFT_RESET_RB)); INREG(RBBM_SOFT_RESET); OUTPLL(MCLK_CNTL, mclk_cntl); OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index); OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset); return;}#define radeon_engine_reset() _radeon_engine_reset(rinfo)static __inline__ u8 radeon_get_post_div_bitval(int post_div){ switch (post_div) { case 1: return 0x00; case 2: return 0x01; case 3: return 0x04; case 4: return 0x02; case 6: return 0x06; case 8: return 0x03; case 12: return 0x07; default: return 0x02; }}static __inline__ int round_div(int num, int den){ return (num + (den / 2)) / den;}static __inline__ int min_bits_req(int val){ int bits_req = 0; if (val == 0) bits_req = 1; while (val) { val >>= 1; bits_req++; } return (bits_req);}static __inline__ int _max(int val1, int val2){ if (val1 >= val2) return val1; else return val2;} /* * globals */ static char *mode_option __initdata;static char noaccel = 1;static char mirror = 0;static int panel_yres __initdata = 0;static char force_dfp __initdata = 0;static struct radeonfb_info *board_list = NULL;static char nomtrr __initdata = 0;/* * prototypes */static void radeon_save_state (struct radeonfb_info *rinfo, struct radeon_regs *save);static void radeon_engine_init (struct radeonfb_info *rinfo);static void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode);static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo);static int __devinit radeon_init_disp (struct radeonfb_info *rinfo);static int radeon_init_disp_var (struct radeonfb_info *rinfo, struct fb_var_screeninfo *var);static char *radeon_find_rom(struct radeonfb_info *rinfo);static void radeon_get_pllinfo(struct radeonfb_info *rinfo, char *bios_seg);static void radeon_get_moninfo (struct radeonfb_info *rinfo);static int radeon_get_dfpinfo (struct radeonfb_info *rinfo);static int radeon_get_dfpinfo_BIOS(struct radeonfb_info *rinfo);static void radeon_get_EDID(struct radeonfb_info *rinfo);static int radeon_dfp_parse_EDID(struct radeonfb_info *rinfo);static void radeon_update_default_var(struct radeonfb_info *rinfo);#ifdef CONFIG_ALL_PPCstatic int radeon_read_OF (struct radeonfb_info *rinfo);static int radeon_get_EDID_OF(struct radeonfb_info *rinfo);extern struct device_node *pci_device_to_OF_node(struct pci_dev *dev);#ifdef CONFIG_PMAC_PBOOKint radeon_sleep_notify(struct pmu_sleep_notifier *self, int when);static struct pmu_sleep_notifier radeon_sleep_notifier = { radeon_sleep_notify, SLEEP_LEVEL_VIDEO,};#endif /* CONFIG_PMAC_PBOOK */#ifdef CONFIG_PMAC_BACKLIGHTstatic int radeon_set_backlight_enable(int on, int level, void *data);static int radeon_set_backlight_level(int level, void *data);static struct backlight_controller radeon_backlight_controller = { radeon_set_backlight_enable, radeon_set_backlight_level};#endif /* CONFIG_PMAC_BACKLIGHT */#endif /* CONFIG_ALL_PPC */static char *radeon_find_rom(struct radeonfb_info *rinfo){ #if defined(__i386__) u32 segstart; char *rom_base; char *rom; int stage; int i,j; char aty_rom_sig[] = "761295520"; char *radeon_sig[] = { "RG6", "RADEON" }; for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) { stage = 1; rom_base = (char *)ioremap(segstart, 0x1000); if ((*rom_base == 0x55) && (((*(rom_base + 1)) & 0xff) == 0xaa)) stage = 2; if (stage != 2) { iounmap(rom_base); continue; } rom = rom_base; for (i = 0; (i < 128 - strlen(aty_rom_sig)) && (stage != 3); i++) { if (aty_rom_sig[0] == *rom) if (strncmp(aty_rom_sig, rom, strlen(aty_rom_sig)) == 0) stage = 3; rom++; } if (stage != 3) { iounmap(rom_base); continue; } rom = rom_base; for (i = 0; (i < 512) && (stage != 4); i++) { for(j = 0;j < sizeof(radeon_sig)/sizeof(char *);j++) { if (radeon_sig[j][0] == *rom) if (strncmp(radeon_sig[j], rom, strlen(radeon_sig[j])) == 0) { stage = 4; break; } } rom++; } if (stage != 4) { iounmap(rom_base); continue; } return rom_base; }#endif return NULL;}static void radeon_get_pllinfo(struct radeonfb_info *rinfo, char *bios_seg){ void *bios_header; void *header_ptr; u16 bios_header_offset, pll_info_offset; PLL_BLOCK pll; if (bios_seg) { bios_header = bios_seg + 0x48L; header_ptr = bios_header; bios_header_offset = readw(header_ptr); bios_header = bios_seg + bios_header_offset; bios_header += 0x30; header_ptr = bios_header; pll_info_offset = readw(header_ptr); header_ptr = bios_seg + pll_info_offset; memcpy_fromio(&pll, header_ptr, 50); rinfo->pll.xclk = (u32)pll.XCLK; rinfo->pll.ref_clk = (u32)pll.PCLK_ref_freq; rinfo->pll.ref_div = (u32)pll.PCLK_ref_divider; rinfo->pll.ppll_min = pll.PCLK_min_freq; rinfo->pll.ppll_max = pll.PCLK_max_freq; printk("radeonfb: ref_clk=%d, ref_div=%d, xclk=%d from BIOS\n", rinfo->pll.ref_clk, rinfo->pll.ref_div, rinfo->pll.xclk); } else {#ifdef CONFIG_ALL_PPC if (radeon_read_OF(rinfo)) { unsigned int tmp, Nx, M, ref_div, xclk; tmp = INPLL(M_SPLL_REF_FB_DIV); ref_div = INPLL(PPLL_REF_DIV) & 0x3ff; Nx = (tmp & 0xff00) >> 8; M = (tmp & 0xff); xclk = ((((2 * Nx * rinfo->pll.ref_clk) + (M)) / (2 * M))); rinfo->pll.xclk = xclk; rinfo->pll.ref_div = ref_div; rinfo->pll.ppll_min = 12000; rinfo->pll.ppll_max = 35000; printk("radeonfb: ref_clk=%d, ref_div=%d, xclk=%d from OF\n", rinfo->pll.ref_clk, rinfo->pll.ref_div, rinfo->pll.xclk); return; }#endif /* no BIOS or BIOS not found, use defaults */ switch (rinfo->chipset) { case PCI_DEVICE_ID_ATI_RADEON_QW: case PCI_DEVICE_ID_ATI_RADEON_QX: rinfo->pll.ppll_max = 35000; rinfo->pll.ppll_min = 12000; rinfo->pll.xclk = 23000; rinfo->pll.ref_div = 12; rinfo->pll.ref_clk = 2700; break; case PCI_DEVICE_ID_ATI_RADEON_QL: case PCI_DEVICE_ID_ATI_RADEON_QN: case PCI_DEVICE_ID_ATI_RADEON_QO: case PCI_DEVICE_ID_ATI_RADEON_Ql: case PCI_DEVICE_ID_ATI_RADEON_BB: rinfo->pll.ppll_max = 35000; rinfo->pll.ppll_min = 12000; rinfo->pll.xclk = 27500; rinfo->pll.ref_div = 12; rinfo->pll.ref_clk = 2700; break; case PCI_DEVICE_ID_ATI_RADEON_Id: case PCI_DEVICE_ID_ATI_RADEON_Ie: case PCI_DEVICE_ID_ATI_RADEON_If: case PCI_DEVICE_ID_ATI_RADEON_Ig: rinfo->pll.ppll_max = 35000; rinfo->pll.ppll_min = 12000; rinfo->pll.xclk = 25000; rinfo->pll.ref_div = 12; rinfo->pll.ref_clk = 2700; break; case PCI_DEVICE_ID_ATI_RADEON_QD: case PCI_DEVICE_ID_ATI_RADEON_QE: case PCI_DEVICE_ID_ATI_RADEON_QF: case PCI_DEVICE_ID_ATI_RADEON_QG: default: rinfo->pll.ppll_max = 35000; rinfo->pll.ppll_min = 12000; rinfo->pll.xclk = 16600; rinfo->pll.ref_div = 67; rinfo->pll.ref_clk = 2700; break; } printk("radeonfb: ref_clk=%d, ref_div=%d, xclk=%d defaults\n", rinfo->pll.ref_clk, rinfo->pll.ref_div, rinfo->pll.xclk); }}static void radeon_get_moninfo (struct radeonfb_info *rinfo){ unsigned int tmp; if (force_dfp) { rinfo->dviDisp_type = MT_DFP; return; } tmp = INREG(RADEON_BIOS_4_SCRATCH); printk(KERN_DEBUG "radeon_get_moninfo: bios 4 scratch = %x\n", tmp); if (rinfo->hasCRTC2) { /* primary DVI port */ if (tmp & 0x08) rinfo->dviDisp_type = MT_DFP; else if (tmp & 0x4) rinfo->dviDisp_type = MT_LCD; else if (tmp & 0x200) rinfo->dviDisp_type = MT_CRT; else if (tmp & 0x10) rinfo->dviDisp_type = MT_CTV; else if (tmp & 0x20) rinfo->dviDisp_type = MT_STV; /* secondary CRT port */ if (tmp & 0x2) rinfo->crtDisp_type = MT_CRT; else if (tmp & 0x800) rinfo->crtDisp_type = MT_DFP; else if (tmp & 0x400) rinfo->crtDisp_type = MT_LCD; else if (tmp & 0x1000) rinfo->crtDisp_type = MT_CTV; else if (tmp & 0x2000) rinfo->crtDisp_type = MT_STV; } else { rinfo->dviDisp_type = MT_NONE; tmp = INREG(FP_GEN_CNTL); if (tmp & FP_EN_TMDS) rinfo->crtDisp_type = MT_DFP; else rinfo->crtDisp_type = MT_CRT; }}static void radeon_get_EDID(struct radeonfb_info *rinfo){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -