📄 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 * 2003-04-10 accel engine fixes, 0.1.7 * 2003-04-12 Mac PowerBook sleep fixes, Benjamin Herrenschmidt, * 0.1.8 * * Other change (--BenH) * * 2003-01-01 - Tweaks for PLL on some iBooks * - Fix SURFACE_CNTL usage on r9000 * 2003-03-23 - Added new Power Management code from ATI * - Added default PLL values for r300 from lkml * - Fix mirror ioctl result code (that ioctl still need some * rework to actually use the second head) * 2003-03-26 - Never set TMDS_PLL_EN, it seem to break more than * just old r300's * 2003-04-02 - Got final word from ATI, TMDS_PLL_EN has to be flipped * depending if we are dealing with an "RV" card or not * - Comsetic changes to sleep code, make it a bit more robust * hopefully * - Fix 800x600-8 mode accel (Daniel Mantione) * - Fix scaling on LCDs (not yet preserving aspect ratio though) * - Properly set scroll mode to SCROLL_YREDRAW when accel * is disabled from fbset * - Add some more radeon PCI IDs & default PLL values * 2003-04-05 - Update the code that retreive the panel infos from the * BIOS to match what XFree is doing * - Avoid a divide by 0 when failing to retreive those infos * 2003-04-07 - Fix the M6 video RAM workaround * - Some bits in the PM code were flipped, fix that. * - RB2D_DSTCACHE_MODE shouldn't be cleared on r300 (and * maybe not on others according to a comment in XFree, but * we keep working code for now). * - Use ROP3_S for rectangle fill * 2003-04-10 - Re-change the pitch workaround. We now align the pitch * when accel is enabled for a given mode, and we don't when * accel is disabled. That should properly deal with all cases * and allows us to remove the "special case" accel code * - Bring in XFree workaround to not write the same value to * the PLL (can cause blanking of some panels) * - Bring in some of Peter Horton fixes (accel reset, cleanups) * still some more to get in though... * - Back to use of ROP3_P for rectangle fill (hrm...) * 2003-04-11 - Properly reset accel engine on each console switch so * we work around switching from XFree leaving it in a weird * state. Also extend the comparison of values causing us to * reload the mode on console switch. * 2003-04-30 - For BIOS returned LCD infos, assume high sync polarity * 2003-07-08 - Fix an oops during boot related to disp not beeing initialized * when modedb called us back for set_var. Remove bogus refs to * RADEON_PM chip, this is really a mach64 chip, not a Radeon. * Add some DFP blanking support * 2003-07-11 - Merged with Ani's 0.1.8 version * * Special thanks to ATI DevRel team for their hardware donations, * and for spending the time to fix the power management code ! * * Note: This driver in in bad need of beeing completely re-organized. * My long term plans, if I ever get enough time for that, is * to split the actual mode setting code so it can properly * work on any head, the probe code, which will be stuffed with * OF parsing on PPC and i2c fallback (look at what XFree does) * and the PM code ought to be in a separate file. --BenH. * * * Known Bugs: * * - Incompatible with ATI FireGL drivers. They are playing with things * like MC_FB_LOCATION behind our back. Not much we can do. This is * becoming a real problem as DRI is also playing with those and the * GATOS CVS as well in a different way. * We should really define _once for all_ the way we want those setup * and do it the same way everywhere or we won't be able to keep * compatibility with radeonfb. * IMHO, the proper setup is what radeon_fixup_apertures() does on * PPC when SET_MC_FB_FROM_APERTURE is defined (not the case currently * because of compatiblity problems with DRI). This is, I think, also * what GATOS does. We shall ask ATI what they do in the FireGL drivers * - We don't preserve aspect ratio on scaled modes on LCDs yet * - The way we retreive the BIOS informations probably doesn't work with * anything but the primary card since we need a "live" BIOS image in * memory to find the tables configured by the BIOS during POST stage. */#define RADEON_VERSION "0.1.8-ben"#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/vt_kern.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>#include <asm/uaccess.h>#ifdef CONFIG_ALL_PPC#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 /* CONFIG_ALL_PPC */#ifdef CONFIG_MTRR#include <asm/mtrr.h>#endif#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"#include <linux/radeonfb.h>#define DEBUG 0#if DEBUG#define RTRACE printk#else#define RTRACE if(0) printk#endifenum 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_QM, RADEON_QW, RADEON_QX, RADEON_Id, RADEON_Ie, RADEON_If, RADEON_Ig, RADEON_Y_, RADEON_Ld, RADEON_Le, RADEON_Lf, RADEON_Lg, RADEON_ND, RADEON_NE, RADEON_NF, RADEON_NG, RADEON_AE, RADEON_AF, RADEON_AD, RADEON_NH, RADEON_NI, RADEON_AP, RADEON_AR,};enum radeon_arch { RADEON_R100, RADEON_M6, RADEON_RV100, RADEON_R200, RADEON_M7, RADEON_RV200, RADEON_M9, RADEON_RV250, RADEON_RV280, RADEON_R300, RADEON_R350, RADEON_RV350,};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 }, { "9100 QM", 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 }, { "9200 Y", RADEON_RV280 }, { "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_R350 }, { "9700 NG", RADEON_R350 }, { "9700 AE", RADEON_R300 }, { "9700 AF", RADEON_R300 }, { "9500 AD", RADEON_R300 }, { "9800 NH", RADEON_R350 }, { "9800 NI", RADEON_R350 }, { "9600 AP", RADEON_RV350 }, { "9600 AR", RADEON_RV350 },};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_QM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_QM}, { 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}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_AE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_AE}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_AF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_AF}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NH, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NH}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NI, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_NI}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Y_, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_Y_}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_AD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_AD}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_AP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_AP}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_AR, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RADEON_AR}, { 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 }};#define COMMON_REGS_SIZE = (sizeof(common_regs)/sizeof(common_regs[0]))#define COMMON_REGS_M6_SIZE = (sizeof(common_regs)/sizeof(common_regs_m6[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 crtc_more_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; /* Dynamic clock control */ u32 vclk_ecp_cntl; /* Endian control */ u32 surface_cntl;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -