📄 radeonfb.c
字号:
/* * drivers/video/radeonfb.c * framebuffer driver for ATI Radeon chipset video boards * * Copyright 2000 Ani Joshi <ajoshi@unixbox.com> * * * ChangeLog: * 2000-08-03 initial version 0.0.1 * 2000-09-10 more bug fixes, public release 0.0.5 * 2001-02-19 mode bug fixes, 0.0.7 * 2001-07-05 fixed scrolling issues, engine initialization, * and minor mode tweaking, 0.0.9 * 2001-09-07 Radeon VE support, Nick Kurshev * blanking, pan_display, and cmap fixes, 0.1.0 * 2001-10-10 Radeon 7500 and 8500 support, and experimental * flat panel support, 0.1.1 * 2001-11-17 Radeon M6 (ppc) support, Daniel Berlin, 0.1.2 * 2001-11-18 DFP fixes, Kevin Hendricks, 0.1.3 * 2001-11-29 more cmap, backlight fixes, Benjamin Herrenschmidt * 2002-01-18 DFP panel detection via BIOS, Michael Clark, 0.1.4 * * Special thanks to ATI DevRel team for their hardware donations. * */#define RADEON_VERSION "0.1.4"#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/tty.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/fb.h>#include <linux/console.h>#include <linux/selection.h>#include <linux/ioport.h>#include <linux/init.h>#include <linux/pci.h>#include <linux/vmalloc.h>#include <asm/io.h>#if defined(__powerpc__)#include <asm/prom.h>#include <asm/pci-bridge.h>#include <video/macmodes.h>#ifdef CONFIG_NVRAM#include <linux/nvram.h>#endif#ifdef CONFIG_PMAC_BACKLIGHT#include <asm/backlight.h>#endif#ifdef CONFIG_BOOTX_TEXT#include <asm/btext.h>#endif#ifdef CONFIG_ADB_PMU#include <linux/adb.h>#include <linux/pmu.h>#endif#endif /* __powerpc__ */#include <video/fbcon.h> #include <video/fbcon-cfb8.h>#include <video/fbcon-cfb16.h>#include <video/fbcon-cfb24.h>#include <video/fbcon-cfb32.h>#include "radeon.h"#define DEBUG 0#if DEBUG#define RTRACE printk#else#define RTRACE if(0) printk#endifenum radeon_chips { RADEON_QD, /* Radeon R100 */ RADEON_QE, /* Radeon R100 */ RADEON_QF, /* Radeon R100 */ RADEON_QG, /* Radeon R100 */ RADEON_QY, /* Radeon RV100 (VE) */ RADEON_QZ, /* Radeon RV100 (VE) */ RADEON_QL, /* Radeon R200 (8500) */ RADEON_QW, /* Radeon RV200 (7500) */ RADEON_LW, /* Radeon Mobility M7 */ RADEON_LY, /* Radeon Mobility M6 */ RADEON_LZ /* Radeon Mobility M6 */};enum radeon_montype{ MT_NONE, MT_CRT, /* CRT */ MT_LCD, /* LCD */ MT_DFP, /* DVI */ MT_CTV, /* composite TV */ MT_STV /* S-Video out */};static struct pci_device_id radeonfb_pci_table[] __devinitdata = { { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QD}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QE}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QF}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QG, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QG}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QY, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QY}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QZ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QZ}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QL, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QL}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_QW, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QW}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_LW, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LW}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_LY, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LY}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_RADEON_LZ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LZ}, { 0, }};MODULE_DEVICE_TABLE(pci, radeonfb_pci_table);typedef struct { u16 reg; u32 val;} reg_val;/* these common regs are cleared before mode setting so they do not * interfere with anything */reg_val common_regs[] = { { OVR_CLR, 0 }, { OVR_WID_LEFT_RIGHT, 0 }, { OVR_WID_TOP_BOTTOM, 0 }, { OV0_SCALE_CNTL, 0 }, { SUBPIC_CNTL, 0 }, { VIPH_CONTROL, 0 }, { I2C_CNTL_1, 0 }, { GEN_INT_CNTL, 0 }, { CAP0_TRIG_CNTL, 0 },};#define COMMON_REGS_SIZE = (sizeof(common_regs)/sizeof(common_regs[0]))typedef struct { u8 clock_chip_type; u8 struct_size; u8 accelerator_entry; u8 VGA_entry; u16 VGA_table_offset; u16 POST_table_offset; u16 XCLK; u16 MCLK; u8 num_PLL_blocks; u8 size_PLL_blocks; u16 PCLK_ref_freq; u16 PCLK_ref_divider; u32 PCLK_min_freq; u32 PCLK_max_freq; u16 MCLK_ref_freq; u16 MCLK_ref_divider; u32 MCLK_min_freq; u32 MCLK_max_freq; u16 XCLK_ref_freq; u16 XCLK_ref_divider; u32 XCLK_min_freq; u32 XCLK_max_freq;} __attribute__ ((packed)) PLL_BLOCK;struct pll_info { int ppll_max; int ppll_min; int xclk; int ref_div; int ref_clk;};struct ram_info { int ml; int mb; int trcd; int trp; int twr; int cl; int tr2w; int loop_latency; int rloop;};struct radeon_regs { /* CRTC regs */ u32 crtc_h_total_disp; u32 crtc_h_sync_strt_wid; u32 crtc_v_total_disp; u32 crtc_v_sync_strt_wid; u32 crtc_pitch; u32 crtc_gen_cntl; u32 crtc_ext_cntl; u32 dac_cntl; u32 flags; u32 pix_clock; int xres, yres; /* DDA regs */ u32 dda_config; u32 dda_on_off; /* PLL regs */ u32 ppll_div_3; u32 ppll_ref_div; /* Flat panel regs */ u32 fp_crtc_h_total_disp; u32 fp_crtc_v_total_disp; u32 fp_gen_cntl; u32 fp_h_sync_strt_wid; u32 fp_horz_stretch; u32 fp_panel_cntl; u32 fp_v_sync_strt_wid; u32 fp_vert_stretch; u32 lvds_gen_cntl; u32 lvds_pll_cntl; u32 tmds_crc; u32 tmds_transmitter_cntl;#if defined(__BIG_ENDIAN) u32 surface_cntl;#endif};struct radeonfb_info { struct fb_info info; struct radeon_regs state; struct radeon_regs init_state; char name[17]; char ram_type[12]; u32 mmio_base_phys; u32 fb_base_phys; u32 mmio_base; u32 fb_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]; int chipset; int video_ram; u8 rev; int pitch, bpp, depth; int xres, yres, pixclock; 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; u32 hack_crtc_ext_cntl; u32 hack_crtc_v_sync_strt_wid;#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 unsigned char *save_framebuffer; int pm_reg;#endif 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) OUTREG8(CLOCK_CNTL_INDEX, (addr & 0x0000001f) | 0x00000080); \ OUTREG(CLOCK_CNTL_DATA, val)#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 & 0x0000001f); 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -