📄 radeonfb.c
字号:
/* * drivers/video/radeonfb.c * framebuffer driver for ATI Radeon chipset video boards * * Copyright 2000 Ani Joshi <ajoshi@kernel.crashing.org> * * * 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 * 2002-06-02 console switching, mode set fixes, accel fixes * 2002-06-03 MTRR support, Peter Horton, 0.1.5 * 2002-09-21 rv250, r300, m9 initial support, * added mirror option, 0.1.6 * * Special thanks to ATI DevRel team for their hardware donations. * */#define RADEON_VERSION "0.1.6"#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/ioport.h>#include <linux/init.h>#include <linux/pci.h>#include <linux/vmalloc.h>#include <asm/io.h>#include <asm/uaccess.h>#if defined(__powerpc__)#include <asm/prom.h>#include <asm/pci-bridge.h>#include "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__ */#ifdef CONFIG_MTRR#include <asm/mtrr.h>#endif#include <video/radeon.h>#include <linux/radeonfb.h>#define DEBUG 1#if DEBUG#define RTRACE printk#else#define RTRACE if(0) printk#endif// XXX#undef CONFIG_PMAC_PBOOKenum radeon_chips { RADEON_QD, RADEON_QE, RADEON_QF, RADEON_QG, RADEON_QY, RADEON_QZ, RADEON_LW, RADEON_LX, RADEON_LY, RADEON_LZ, RADEON_QL, RADEON_QN, RADEON_QO, RADEON_Ql, RADEON_BB, RADEON_QW, RADEON_QX, RADEON_Id, RADEON_Ie, RADEON_If, RADEON_Ig, RADEON_Ld, RADEON_Le, RADEON_Lf, RADEON_Lg, RADEON_ND, RADEON_NE, RADEON_NF, RADEON_NG};enum radeon_arch { RADEON_R100, RADEON_RV100, RADEON_R200, RADEON_RV200, RADEON_RV250, RADEON_R300, RADEON_M6, RADEON_M7, RADEON_M9};static struct radeon_chip_info { const char *name; unsigned char arch;} radeon_chip_info[] __devinitdata = { { "QD", RADEON_R100 }, { "QE", RADEON_R100 }, { "QF", RADEON_R100 }, { "QG", RADEON_R100 }, { "VE QY", RADEON_RV100 }, { "VE QZ", RADEON_RV100 }, { "M7 LW", RADEON_M7 }, { "M7 LX", RADEON_M7 }, { "M6 LY", RADEON_M6 }, { "M6 LZ", RADEON_M6 }, { "8500 QL", RADEON_R200 }, { "8500 QN", RADEON_R200 }, { "8500 QO", RADEON_R200 }, { "8500 Ql", RADEON_R200 }, { "8500 BB", RADEON_R200 }, { "7500 QW", RADEON_RV200 }, { "7500 QX", RADEON_RV200 }, { "9000 Id", RADEON_RV250 }, { "9000 Ie", RADEON_RV250 }, { "9000 If", RADEON_RV250 }, { "9000 Ig", RADEON_RV250 }, { "M9 Ld", RADEON_M9 }, { "M9 Le", RADEON_M9 }, { "M9 Lf", RADEON_M9 }, { "M9 Lg", RADEON_M9 }, { "9700 ND", RADEON_R300 }, { "9700 NE", RADEON_R300 }, { "9700 NF", RADEON_R300 }, { "9700 NG", RADEON_R300 }};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_ATI_RADEON_QD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QD}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QE}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QF}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QG, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QG}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QY, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QY}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QZ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QZ}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_LW, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LW}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_LX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LX}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_LY, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LY}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_LZ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_LZ}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QL, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QL}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QN, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QN}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QO}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ql, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Ql}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_BB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_BB}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QW, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QW}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QX}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Id}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ie, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Ie}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_If, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_If}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ig, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Ig}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ld, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Ld}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Le, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Le}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Lf, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Lf}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Lg, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Lg}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_ND, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_ND}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NE}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NF}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NG, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NG}, { 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 },};reg_val common_regs_m6[] = { { OVR_CLR, 0 }, { OVR_WID_LEFT_RIGHT, 0 }, { OVR_WID_TOP_BOTTOM, 0 }, { OV0_SCALE_CNTL, 0 }, { SUBPIC_CNTL, 0 }, { GEN_INT_CNTL, 0 }, { CAP0_TRIG_CNTL, 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; u32 vclk_ecp_cntl; /* 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[32]; char ram_type[12]; unsigned long mmio_base_phys; unsigned long fb_base_phys; unsigned long mmio_base; unsigned long fb_base; struct pci_dev *pdev; unsigned char *EDID; unsigned char *bios_seg; u32 pseudo_palette[17]; struct { u8 red, green, blue, pad; } palette[256]; int chipset; unsigned char arch; int video_ram; u8 rev; int pitch, bpp, depth; int xres, yres, pixclock; int xres_virtual, yres_virtual; u32 accel_flags; 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;#ifdef CONFIG_PMAC_PBOOK int pm_reg; u32 save_regs[64]; u32 mdll, mdll2;#endif /* CONFIG_PMAC_PBOOK */ 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";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -