📄 radeonfb.c
字号:
};struct radeonfb_info { struct fb_info info; struct radeon_regs state; struct radeon_regs init_state; char name[16]; char ram_type[12]; unsigned long mmio_base_phys; unsigned long fb_base_phys; unsigned long mmio_base; unsigned long fb_base; unsigned long fb_local_base; struct pci_dev *pdev; unsigned char *EDID; unsigned char *bios_seg; struct display disp; int currcon; struct display *currcon_display; struct { u8 red, green, blue, pad; } palette[256]; short chipset; unsigned char arch; int video_ram; u8 rev; int pitch, bpp, depth; int xres, yres, pixclock; int xres_virtual, yres_virtual; int use_default_var; int got_dfpinfo; int hasCRTC2; int crtDisp_type; int dviDisp_type; int panel_xres, panel_yres; int clock; int hOver_plus, hSync_width, hblank; int vOver_plus, vSync_width, vblank; int hAct_high, vAct_high, interlaced; int synct, misc; u32 dp_gui_master_cntl; struct pll_info pll; int pll_output_freq, post_div, fb_div; struct ram_info ram; int mtrr_hdl;#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32) union {#if defined(FBCON_HAS_CFB16) u_int16_t cfb16[16];#endif#if defined(FBCON_HAS_CFB24) u_int32_t cfb24[16];#endif #if defined(FBCON_HAS_CFB32) u_int32_t cfb32[16];#endif } con_cmap;#endif #ifdef CONFIG_PMAC_PBOOK int pm_reg; u32 save_regs[64]; u32 mdll, mdll2;#endif int asleep; struct radeonfb_info *next;};static struct fb_var_screeninfo radeonfb_default_var = { 640, 480, 640, 480, 0, 0, 8, 0, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0, 0, -1, -1, 0, 39721, 40, 24, 32, 11, 96, 2, 0, FB_VMODE_NONINTERLACED};/* * IO macros */#define INREG8(addr) readb((rinfo->mmio_base)+addr)#define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr)#define INREG(addr) readl((rinfo->mmio_base)+addr)#define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr)#define OUTPLL(addr,val) \ do { \ OUTREG8(CLOCK_CNTL_INDEX, (addr & 0x0000003f) | 0x00000080); \ OUTREG(CLOCK_CNTL_DATA, val); \ } while (0) \#define OUTPLLP(addr,val,mask) \ do { \ unsigned int _tmp = INPLL(addr); \ _tmp &= (mask); \ _tmp |= (val); \ OUTPLL(addr, _tmp); \ } while (0)#define OUTREGP(addr,val,mask) \ do { \ unsigned int _tmp = INREG(addr); \ _tmp &= (mask); \ _tmp |= (val); \ OUTREG(addr, _tmp); \ } while (0)static __inline__ u32 _INPLL(struct radeonfb_info *rinfo, u32 addr){ OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000003f); return (INREG(CLOCK_CNTL_DATA));}#define INPLL(addr) _INPLL(rinfo, addr)#define PRIMARY_MONITOR(rinfo) ((rinfo->dviDisp_type != MT_NONE) && \ (rinfo->dviDisp_type != MT_STV) && \ (rinfo->dviDisp_type != MT_CTV) ? \ rinfo->dviDisp_type : rinfo->crtDisp_type)static char *GET_MON_NAME(int type){ char *pret = NULL; switch (type) { case MT_NONE: pret = "no"; break; case MT_CRT: pret = "CRT"; break; case MT_DFP: pret = "DFP"; break; case MT_LCD: pret = "LCD"; 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; u32 host_path_cntl; radeon_engine_flush (rinfo); /* Some ASICs have bugs with dynamic-on feature, which are * ASIC-version dependent, so we force all blocks on for now * -- from XFree86 * We don't do that on macs, things just work here with dynamic * clocking... --BenH */#ifdef CONFIG_ALL_PPC if (_machine != _MACH_Pmac && rinfo->hasCRTC2)#else if (rinfo->hasCRTC2)#endif { u32 tmp; tmp = INPLL(SCLK_CNTL); OUTPLL(SCLK_CNTL, ((tmp & ~DYN_STOP_LAT_MASK) | CP_MAX_DYN_STOP_LAT | SCLK_FORCEON_MASK)); if (rinfo->arch == RADEON_RV200) { tmp = INPLL(SCLK_MORE_CNTL); OUTPLL(SCLK_MORE_CNTL, tmp | SCLK_MORE_FORCEON); } } 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)); host_path_cntl = INREG(HOST_PATH_CNTL); rbbm_soft_reset = INREG(RBBM_SOFT_RESET); if (rinfo->arch == RADEON_R300) { u32 tmp; OUTREG(RBBM_SOFT_RESET, (rbbm_soft_reset | SOFT_RESET_CP | SOFT_RESET_HI | SOFT_RESET_E2)); INREG(RBBM_SOFT_RESET); OUTREG(RBBM_SOFT_RESET, 0); tmp = INREG(RB2D_DSTCACHE_MODE); OUTREG(RB2D_DSTCACHE_MODE, tmp | (1 << 17)); /* FIXME */ } else { 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); } OUTREG(HOST_PATH_CNTL, host_path_cntl | HDP_SOFT_RESET); INREG(HOST_PATH_CNTL); OUTREG(HOST_PATH_CNTL, host_path_cntl); if (rinfo->arch != RADEON_R300) OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset); OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index); OUTPLL(MCLK_CNTL, mclk_cntl); return;}#define radeon_engine_reset() _radeon_engine_reset(rinfo)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 fontname[40] __initdata;static char *mode_option __initdata;static char noaccel = 0;static char mirror = 0;static int panel_yres __initdata = 0;static char force_dfp __initdata = 0;static char force_crt __initdata = 0;static char force_nolcd __initdata = 0;static struct radeonfb_info *board_list = NULL;static char nomtrr __initdata = 0;#ifdef FBCON_HAS_CFB8static struct display_switch fbcon_radeon8;#endif#ifdef FBCON_HAS_CFB16static struct display_switch fbcon_radeon16;#endif#ifdef FBCON_HAS_CFB32static struct display_switch fbcon_radeon32;#endif/* * prototypes */static int radeonfb_get_fix (struct fb_fix_screeninfo *fix, int con, struct fb_info *info);static int radeonfb_get_var (struct fb_var_screeninfo *var, int con, struct fb_info *info);static int radeonfb_set_var (struct fb_var_screeninfo *var, int con, struct fb_info *info);static int radeonfb_get_cmap (struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);static int radeonfb_set_cmap (struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);static int radeonfb_pan_display (struct fb_var_screeninfo *var, int con, struct fb_info *info);static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, int con, struct fb_info *info);static int radeonfb_switch (int con, struct fb_info *info);static int radeonfb_updatevar (int con, struct fb_info *info);static void radeonfb_blank (int blank, struct fb_info *info);static int radeon_get_cmap_len (const struct fb_var_screeninfo *var);static int radeon_getcolreg (unsigned regno, unsigned *red, unsigned *green, unsigned *blue, unsigned *transp, struct fb_info *info);static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info);static void radeon_set_dispsw (struct radeonfb_info *rinfo, struct display *disp);static void radeon_save_state (struct radeonfb_info *rinfo, struct radeon_regs *save);static int radeon_engine_init (struct radeonfb_info *rinfo);static void radeon_load_video_mode (struct radeonfb_info *rinfo, struct fb_var_screeninfo *mode);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 radeonfb_pci_register (struct pci_dev *pdev, const struct pci_device_id *ent);static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev);static int radeon_do_set_var (struct fb_var_screeninfo *var, int con, int real, struct fb_info *info);#ifdef CONFIG_PMAC_PBOOKstatic int 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};static void OUTMC( struct radeonfb_info *rinfo, u8 indx, u32 value);static u32 INMC(struct radeonfb_info *rinfo, u8 indx);static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo);static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -