Mercurial > mplayer.hg
changeset 1911:89313cfc8fec
Initial import of Ani Joshi's radeonfb-0.0.9
author | nick |
---|---|
date | Tue, 18 Sep 2001 16:12:34 +0000 |
parents | 06fa415119bc |
children | 33afcb62fc64 |
files | drivers/radeon/radeon.h drivers/radeon/radeonfb.c |
diffstat | 2 files changed, 2580 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/radeon/radeon.h Tue Sep 18 16:12:34 2001 +0000 @@ -0,0 +1,664 @@ +#ifndef _RADEON_H +#define _RADEON_H + + +/* radeon PCI ids */ +#define PCI_DEVICE_ID_RADEON_QD 0x5144 +#define PCI_DEVICE_ID_RADEON_QE 0x5145 +#define PCI_DEVICE_ID_RADEON_QF 0x5146 +#define PCI_DEVICE_ID_RADEON_QG 0x5147 + +#define RADEON_REGSIZE 0x4000 + + +#define MM_INDEX 0x0000 +#define MM_DATA 0x0004 +#define BUS_CNTL 0x0030 +#define HI_STAT 0x004C +#define BUS_CNTL1 0x0034 +#define I2C_CNTL_1 0x0094 +#define CONFIG_CNTL 0x00E0 +#define CONFIG_MEMSIZE 0x00F8 +#define CONFIG_APER_0_BASE 0x0100 +#define CONFIG_APER_1_BASE 0x0104 +#define CONFIG_APER_SIZE 0x0108 +#define CONFIG_REG_1_BASE 0x010C +#define CONFIG_REG_APER_SIZE 0x0110 +#define PAD_AGPINPUT_DELAY 0x0164 +#define PAD_CTLR_STRENGTH 0x0168 +#define PAD_CTLR_UPDATE 0x016C +#define AGP_CNTL 0x0174 +#define BM_STATUS 0x0160 +#define CAP0_TRIG_CNTL 0x0950 +#define VIPH_CONTROL 0x0C40 +#define VENDOR_ID 0x0F00 +#define DEVICE_ID 0x0F02 +#define COMMAND 0x0F04 +#define STATUS 0x0F06 +#define REVISION_ID 0x0F08 +#define REGPROG_INF 0x0F09 +#define SUB_CLASS 0x0F0A +#define BASE_CODE 0x0F0B +#define CACHE_LINE 0x0F0C +#define LATENCY 0x0F0D +#define HEADER 0x0F0E +#define BIST 0x0F0F +#define REG_MEM_BASE 0x0F10 +#define REG_IO_BASE 0x0F14 +#define REG_REG_BASE 0x0F18 +#define ADAPTER_ID 0x0F2C +#define BIOS_ROM 0x0F30 +#define CAPABILITIES_PTR 0x0F34 +#define INTERRUPT_LINE 0x0F3C +#define INTERRUPT_PIN 0x0F3D +#define MIN_GRANT 0x0F3E +#define MAX_LATENCY 0x0F3F +#define ADAPTER_ID_W 0x0F4C +#define PMI_CAP_ID 0x0F50 +#define PMI_NXT_CAP_PTR 0x0F51 +#define PMI_PMC_REG 0x0F52 +#define PM_STATUS 0x0F54 +#define PMI_DATA 0x0F57 +#define AGP_CAP_ID 0x0F58 +#define AGP_STATUS 0x0F5C +#define AGP_COMMAND 0x0F60 +#define AIC_CTRL 0x01D0 +#define AIC_STAT 0x01D4 +#define AIC_PT_BASE 0x01D8 +#define AIC_LO_ADDR 0x01DC +#define AIC_HI_ADDR 0x01E0 +#define AIC_TLB_ADDR 0x01E4 +#define AIC_TLB_DATA 0x01E8 +#define DAC_CNTL 0x0058 +#define CRTC_GEN_CNTL 0x0050 +#define MEM_CNTL 0x0140 +#define EXT_MEM_CNTL 0x0144 +#define MC_AGP_LOCATION 0x014C +#define MEM_IO_CNTL_A0 0x0178 +#define MEM_INIT_LATENCY_TIMER 0x0154 +#define MEM_SDRAM_MODE_REG 0x0158 +#define AGP_BASE 0x0170 +#define MEM_IO_CNTL_A1 0x017C +#define MEM_IO_CNTL_B0 0x0180 +#define MEM_IO_CNTL_B1 0x0184 +#define MC_DEBUG 0x0188 +#define MC_STATUS 0x0150 +#define MEM_IO_OE_CNTL 0x018C +#define MC_FB_LOCATION 0x0148 +#define HOST_PATH_CNTL 0x0130 +#define MEM_VGA_WP_SEL 0x0038 +#define MEM_VGA_RP_SEL 0x003C +#define HDP_DEBUG 0x0138 +#define SW_SEMAPHORE 0x013C +#define SURFACE_CNTL 0x0B00 +#define SURFACE0_LOWER_BOUND 0x0B04 +#define SURFACE1_LOWER_BOUND 0x0B14 +#define SURFACE2_LOWER_BOUND 0x0B24 +#define SURFACE3_LOWER_BOUND 0x0B34 +#define SURFACE4_LOWER_BOUND 0x0B44 +#define SURFACE5_LOWER_BOUND 0x0B54 +#define SURFACE6_LOWER_BOUND 0x0B64 +#define SURFACE7_LOWER_BOUND 0x0B74 +#define SURFACE0_UPPER_BOUND 0x0B08 +#define SURFACE1_UPPER_BOUND 0x0B18 +#define SURFACE2_UPPER_BOUND 0x0B28 +#define SURFACE3_UPPER_BOUND 0x0B38 +#define SURFACE4_UPPER_BOUND 0x0B48 +#define SURFACE5_UPPER_BOUND 0x0B58 +#define SURFACE6_UPPER_BOUND 0x0B68 +#define SURFACE7_UPPER_BOUND 0x0B78 +#define SURFACE0_INFO 0x0B0C +#define SURFACE1_INFO 0x0B1C +#define SURFACE2_INFO 0x0B2C +#define SURFACE3_INFO 0x0B3C +#define SURFACE4_INFO 0x0B4C +#define SURFACE5_INFO 0x0B5C +#define SURFACE6_INFO 0x0B6C +#define SURFACE7_INFO 0x0B7C +#define SURFACE_ACCESS_FLAGS 0x0BF8 +#define SURFACE_ACCESS_CLR 0x0BFC +#define GEN_INT_CNTL 0x0040 +#define GEN_INT_STATUS 0x0044 +#define CRTC_EXT_CNTL 0x0054 +#define RB3D_CNTL 0x1C3C +#define WAIT_UNTIL 0x1720 +#define ISYNC_CNTL 0x1724 +#define RBBM_GUICNTL 0x172C +#define RBBM_STATUS 0x0E40 +#define RBBM_STATUS_alt_1 0x1740 +#define RBBM_CNTL 0x00EC +#define RBBM_CNTL_alt_1 0x0E44 +#define RBBM_SOFT_RESET 0x00F0 +#define RBBM_SOFT_RESET_alt_1 0x0E48 +#define NQWAIT_UNTIL 0x0E50 +#define RBBM_DEBUG 0x0E6C +#define RBBM_CMDFIFO_ADDR 0x0E70 +#define RBBM_CMDFIFO_DATAL 0x0E74 +#define RBBM_CMDFIFO_DATAH 0x0E78 +#define RBBM_CMDFIFO_STAT 0x0E7C +#define CRTC_STATUS 0x005C +#define GPIO_VGA_DDC 0x0060 +#define GPIO_DVI_DDC 0x0064 +#define GPIO_MONID 0x0068 +#define PALETTE_INDEX 0x00B0 +#define PALETTE_DATA 0x00B4 +#define PALETTE_30_DATA 0x00B8 +#define CRTC_H_TOTAL_DISP 0x0200 +#define CRTC_H_SYNC_STRT_WID 0x0204 +#define CRTC_V_TOTAL_DISP 0x0208 +#define CRTC_V_SYNC_STRT_WID 0x020C +#define CRTC_VLINE_CRNT_VLINE 0x0210 +#define CRTC_CRNT_FRAME 0x0214 +#define CRTC_GUI_TRIG_VLINE 0x0218 +#define CRTC_DEBUG 0x021C +#define CRTC_OFFSET_RIGHT 0x0220 +#define CRTC_OFFSET 0x0224 +#define CRTC_OFFSET_CNTL 0x0228 +#define CRTC_PITCH 0x022C +#define OVR_CLR 0x0230 +#define OVR_WID_LEFT_RIGHT 0x0234 +#define OVR_WID_TOP_BOTTOM 0x0238 +#define DISPLAY_BASE_ADDR 0x023C +#define SNAPSHOT_VH_COUNTS 0x0240 +#define SNAPSHOT_F_COUNT 0x0244 +#define N_VIF_COUNT 0x0248 +#define SNAPSHOT_VIF_COUNT 0x024C +#define FP_CRTC_H_TOTAL_DISP 0x0250 +#define FP_CRTC_V_TOTAL_DISP 0x0254 +#define CRT_CRTC_H_SYNC_STRT_WID 0x0258 +#define CRT_CRTC_V_SYNC_STRT_WID 0x025C +#define CUR_OFFSET 0x0260 +#define CUR_HORZ_VERT_POSN 0x0264 +#define CUR_HORZ_VERT_OFF 0x0268 +#define CUR_CLR0 0x026C +#define CUR_CLR1 0x0270 +#define FP_HORZ_VERT_ACTIVE 0x0278 +#define CRTC_MORE_CNTL 0x027C +#define DAC_EXT_CNTL 0x0280 +#define FP_GEN_CNTL 0x0284 +#define FP_HORZ_STRETCH 0x028C +#define FP_VERT_STRETCH 0x0290 +#define FP_H_SYNC_STRT_WID 0x02C4 +#define FP_V_SYNC_STRT_WID 0x02C8 +#define AUX_WINDOW_HORZ_CNTL 0x02D8 +#define AUX_WINDOW_VERT_CNTL 0x02DC +#define DDA_CONFIG 0x02e0 +#define DDA_ON_OFF 0x02e4 +#define GRPH_BUFFER_CNTL 0x02F0 +#define VGA_BUFFER_CNTL 0x02F4 +#define OV0_Y_X_START 0x0400 +#define OV0_Y_X_END 0x0404 +#define OV0_PIPELINE_CNTL 0x0408 +#define OV0_REG_LOAD_CNTL 0x0410 +#define OV0_SCALE_CNTL 0x0420 +#define OV0_V_INC 0x0424 +#define OV0_P1_V_ACCUM_INIT 0x0428 +#define OV0_P23_V_ACCUM_INIT 0x042C +#define OV0_P1_BLANK_LINES_AT_TOP 0x0430 +#define OV0_P23_BLANK_LINES_AT_TOP 0x0434 +#define OV0_BASE_ADDR 0x043C +#define OV0_VID_BUF0_BASE_ADRS 0x0440 +#define OV0_VID_BUF1_BASE_ADRS 0x0444 +#define OV0_VID_BUF2_BASE_ADRS 0x0448 +#define OV0_VID_BUF3_BASE_ADRS 0x044C +#define OV0_VID_BUF4_BASE_ADRS 0x0450 +#define OV0_VID_BUF5_BASE_ADRS 0x0454 +#define OV0_VID_BUF_PITCH0_VALUE 0x0460 +#define OV0_VID_BUF_PITCH1_VALUE 0x0464 +#define OV0_AUTO_FLIP_CNTRL 0x0470 +#define OV0_DEINTERLACE_PATTERN 0x0474 +#define OV0_SUBMIT_HISTORY 0x0478 +#define OV0_H_INC 0x0480 +#define OV0_STEP_BY 0x0484 +#define OV0_P1_H_ACCUM_INIT 0x0488 +#define OV0_P23_H_ACCUM_INIT 0x048C +#define OV0_P1_X_START_END 0x0494 +#define OV0_P2_X_START_END 0x0498 +#define OV0_P3_X_START_END 0x049C +#define OV0_FILTER_CNTL 0x04A0 +#define OV0_FOUR_TAP_COEF_0 0x04B0 +#define OV0_FOUR_TAP_COEF_1 0x04B4 +#define OV0_FOUR_TAP_COEF_2 0x04B8 +#define OV0_FOUR_TAP_COEF_3 0x04BC +#define OV0_FOUR_TAP_COEF_4 0x04C0 +#define OV0_FLAG_CNTRL 0x04DC +#define OV0_SLICE_CNTL 0x04E0 +#define OV0_VID_KEY_CLR_LOW 0x04E4 +#define OV0_VID_KEY_CLR_HIGH 0x04E8 +#define OV0_GRPH_KEY_CLR_LOW 0x04EC +#define OV0_GRPH_KEY_CLR_HIGH 0x04F0 +#define OV0_KEY_CNTL 0x04F4 +#define OV0_TEST 0x04F8 +#define SUBPIC_CNTL 0x0540 +#define SUBPIC_DEFCOLCON 0x0544 +#define SUBPIC_Y_X_START 0x054C +#define SUBPIC_Y_X_END 0x0550 +#define SUBPIC_V_INC 0x0554 +#define SUBPIC_H_INC 0x0558 +#define SUBPIC_BUF0_OFFSET 0x055C +#define SUBPIC_BUF1_OFFSET 0x0560 +#define SUBPIC_LC0_OFFSET 0x0564 +#define SUBPIC_LC1_OFFSET 0x0568 +#define SUBPIC_PITCH 0x056C +#define SUBPIC_BTN_HLI_COLCON 0x0570 +#define SUBPIC_BTN_HLI_Y_X_START 0x0574 +#define SUBPIC_BTN_HLI_Y_X_END 0x0578 +#define SUBPIC_PALETTE_INDEX 0x057C +#define SUBPIC_PALETTE_DATA 0x0580 +#define SUBPIC_H_ACCUM_INIT 0x0584 +#define SUBPIC_V_ACCUM_INIT 0x0588 +#define DISP_MISC_CNTL 0x0D00 +#define DAC_MACRO_CNTL 0x0D04 +#define DISP_PWR_MAN 0x0D08 +#define DISP_TEST_DEBUG_CNTL 0x0D10 +#define DISP_HW_DEBUG 0x0D14 +#define DAC_CRC_SIG1 0x0D18 +#define DAC_CRC_SIG2 0x0D1C +#define OV0_LIN_TRANS_A 0x0D20 +#define OV0_LIN_TRANS_B 0x0D24 +#define OV0_LIN_TRANS_C 0x0D28 +#define OV0_LIN_TRANS_D 0x0D2C +#define OV0_LIN_TRANS_E 0x0D30 +#define OV0_LIN_TRANS_F 0x0D34 +#define OV0_GAMMA_0_F 0x0D40 +#define OV0_GAMMA_10_1F 0x0D44 +#define OV0_GAMMA_20_3F 0x0D48 +#define OV0_GAMMA_40_7F 0x0D4C +#define OV0_GAMMA_380_3BF 0x0D50 +#define OV0_GAMMA_3C0_3FF 0x0D54 +#define DISP_MERGE_CNTL 0x0D60 +#define DISP_OUTPUT_CNTL 0x0D64 +#define DISP_LIN_TRANS_GRPH_A 0x0D80 +#define DISP_LIN_TRANS_GRPH_B 0x0D84 +#define DISP_LIN_TRANS_GRPH_C 0x0D88 +#define DISP_LIN_TRANS_GRPH_D 0x0D8C +#define DISP_LIN_TRANS_GRPH_E 0x0D90 +#define DISP_LIN_TRANS_GRPH_F 0x0D94 +#define DISP_LIN_TRANS_VID_A 0x0D98 +#define DISP_LIN_TRANS_VID_B 0x0D9C +#define DISP_LIN_TRANS_VID_C 0x0DA0 +#define DISP_LIN_TRANS_VID_D 0x0DA4 +#define DISP_LIN_TRANS_VID_E 0x0DA8 +#define DISP_LIN_TRANS_VID_F 0x0DAC +#define RMX_HORZ_FILTER_0TAP_COEF 0x0DB0 +#define RMX_HORZ_FILTER_1TAP_COEF 0x0DB4 +#define RMX_HORZ_FILTER_2TAP_COEF 0x0DB8 +#define RMX_HORZ_PHASE 0x0DBC +#define DAC_EMBEDDED_SYNC_CNTL 0x0DC0 +#define DAC_BROAD_PULSE 0x0DC4 +#define DAC_SKEW_CLKS 0x0DC8 +#define DAC_INCR 0x0DCC +#define DAC_NEG_SYNC_LEVEL 0x0DD0 +#define DAC_POS_SYNC_LEVEL 0x0DD4 +#define DAC_BLANK_LEVEL 0x0DD8 +#define CLOCK_CNTL_INDEX 0x0008 +#define CLOCK_CNTL_DATA 0x000C +#define CP_RB_CNTL 0x0704 +#define CP_RB_BASE 0x0700 +#define CP_RB_RPTR_ADDR 0x070C +#define CP_RB_RPTR 0x0710 +#define CP_RB_WPTR 0x0714 +#define CP_RB_WPTR_DELAY 0x0718 +#define CP_IB_BASE 0x0738 +#define CP_IB_BUFSZ 0x073C +#define SCRATCH_REG0 0x15E0 +#define GUI_SCRATCH_REG0 0x15E0 +#define SCRATCH_REG1 0x15E4 +#define GUI_SCRATCH_REG1 0x15E4 +#define SCRATCH_REG2 0x15E8 +#define GUI_SCRATCH_REG2 0x15E8 +#define SCRATCH_REG3 0x15EC +#define GUI_SCRATCH_REG3 0x15EC +#define SCRATCH_REG4 0x15F0 +#define GUI_SCRATCH_REG4 0x15F0 +#define SCRATCH_REG5 0x15F4 +#define GUI_SCRATCH_REG5 0x15F4 +#define SCRATCH_UMSK 0x0770 +#define SCRATCH_ADDR 0x0774 +#define DP_BRUSH_FRGD_CLR 0x147C +#define DP_BRUSH_BKGD_CLR 0x1478 +#define DST_LINE_START 0x1600 +#define DST_LINE_END 0x1604 +#define SRC_OFFSET 0x15AC +#define SRC_PITCH 0x15B0 +#define SRC_TILE 0x1704 +#define SRC_PITCH_OFFSET 0x1428 +#define SRC_X 0x1414 +#define SRC_Y 0x1418 +#define SRC_X_Y 0x1590 +#define SRC_Y_X 0x1434 +#define DST_Y_X 0x1438 +#define DST_WIDTH_HEIGHT 0x1598 +#define DST_HEIGHT_WIDTH 0x143c +#define SRC_CLUT_ADDRESS 0x1780 +#define SRC_CLUT_DATA 0x1784 +#define SRC_CLUT_DATA_RD 0x1788 +#define HOST_DATA0 0x17C0 +#define HOST_DATA1 0x17C4 +#define HOST_DATA2 0x17C8 +#define HOST_DATA3 0x17CC +#define HOST_DATA4 0x17D0 +#define HOST_DATA5 0x17D4 +#define HOST_DATA6 0x17D8 +#define HOST_DATA7 0x17DC +#define HOST_DATA_LAST 0x17E0 +#define DP_SRC_ENDIAN 0x15D4 +#define DP_SRC_FRGD_CLR 0x15D8 +#define DP_SRC_BKGD_CLR 0x15DC +#define SC_LEFT 0x1640 +#define SC_RIGHT 0x1644 +#define SC_TOP 0x1648 +#define SC_BOTTOM 0x164C +#define SRC_SC_RIGHT 0x1654 +#define SRC_SC_BOTTOM 0x165C +#define DP_CNTL 0x16C0 +#define DP_CNTL_XDIR_YDIR_YMAJOR 0x16D0 +#define DP_DATATYPE 0x16C4 +#define DP_MIX 0x16C8 +#define DP_WRITE_MSK 0x16CC +#define DP_XOP 0x17F8 +#define CLR_CMP_CLR_SRC 0x15C4 +#define CLR_CMP_CLR_DST 0x15C8 +#define CLR_CMP_CNTL 0x15C0 +#define CLR_CMP_MSK 0x15CC +#define DSTCACHE_MODE 0x1710 +#define DSTCACHE_CTLSTAT 0x1714 +#define DEFAULT_PITCH_OFFSET 0x16E0 +#define DEFAULT_SC_BOTTOM_RIGHT 0x16E8 +#define DP_GUI_MASTER_CNTL 0x146C +#define SC_TOP_LEFT 0x16EC +#define SC_BOTTOM_RIGHT 0x16F0 +#define SRC_SC_BOTTOM_RIGHT 0x16F4 +#define RB2D_DSTCACHE_CTLSTAT 0x342C + + +#define CLK_PIN_CNTL 0x0001 +#define PPLL_CNTL 0x0002 +#define PPLL_REF_DIV 0x0003 +#define PPLL_DIV_0 0x0004 +#define PPLL_DIV_1 0x0005 +#define PPLL_DIV_2 0x0006 +#define PPLL_DIV_3 0x0007 +#define VCLK_ECP_CNTL 0x0008 +#define HTOTAL_CNTL 0x0009 +#define M_SPLL_REF_FB_DIV 0x000a +#define AGP_PLL_CNTL 0x000b +#define SPLL_CNTL 0x000c +#define SCLK_CNTL 0x000d +#define MPLL_CNTL 0x000e +#define MCLK_CNTL 0x0012 +#define AGP_PLL_CNTL 0x000b +#define PLL_TEST_CNTL 0x0013 + + +/* MCLK_CNTL bit constants */ +#define FORCEON_MCLKA (1 << 16) +#define FORCEON_MCLKB (1 << 17) +#define FORCEON_YCLKA (1 << 18) +#define FORCEON_YCLKB (1 << 19) +#define FORCEON_MC (1 << 20) +#define FORCEON_AIC (1 << 21) + + +/* BUS_CNTL bit constants */ +#define BUS_DBL_RESYNC 0x00000001 +#define BUS_MSTR_RESET 0x00000002 +#define BUS_FLUSH_BUF 0x00000004 +#define BUS_STOP_REQ_DIS 0x00000008 +#define BUS_ROTATION_DIS 0x00000010 +#define BUS_MASTER_DIS 0x00000040 +#define BUS_ROM_WRT_EN 0x00000080 +#define BUS_DIS_ROM 0x00001000 +#define BUS_PCI_READ_RETRY_EN 0x00002000 +#define BUS_AGP_AD_STEPPING_EN 0x00004000 +#define BUS_PCI_WRT_RETRY_EN 0x00008000 +#define BUS_MSTR_RD_MULT 0x00100000 +#define BUS_MSTR_RD_LINE 0x00200000 +#define BUS_SUSPEND 0x00400000 +#define LAT_16X 0x00800000 +#define BUS_RD_DISCARD_EN 0x01000000 +#define BUS_RD_ABORT_EN 0x02000000 +#define BUS_MSTR_WS 0x04000000 +#define BUS_PARKING_DIS 0x08000000 +#define BUS_MSTR_DISCONNECT_EN 0x10000000 +#define BUS_WRT_BURST 0x20000000 +#define BUS_READ_BURST 0x40000000 +#define BUS_RDY_READ_DLY 0x80000000 + + +/* CLOCK_CNTL_INDEX bit constants */ +#define PLL_WR_EN 0x00000080 + +/* CONFIG_CNTL bit constants */ +#define CFG_VGA_RAM_EN 0x00000100 + +/* CRTC_EXT_CNTL bit constants */ +#define VGA_ATI_LINEAR 0x00000008 +#define VGA_128KAP_PAGING 0x00000010 +#define XCRT_CNT_EN (1 << 6) +#define CRTC_HSYNC_DIS (1 << 8) +#define CRTC_VSYNC_DIS (1 << 9) +#define CRTC_DISPLAY_DIS (1 << 10) + + +/* DSTCACHE_CTLSTAT bit constants */ +#define RB2D_DC_FLUSH (3 << 0) +#define RB2D_DC_FLUSH_ALL 0xf +#define RB2D_DC_BUSY (1 << 31) + + +/* CRTC_GEN_CNTL bit constants */ +#define CRTC_DBL_SCAN_EN 0x00000001 +#define CRTC_CUR_EN 0x00010000 +#define CRTC_EXT_DISP_EN (1 << 24) +#define CRTC_EN (1 << 25) + +/* CRTC_STATUS bit constants */ +#define CRTC_VBLANK 0x00000001 + +/* CUR_OFFSET, CUR_HORZ_VERT_POSN, CUR_HORZ_VERT_OFF bit constants */ +#define CUR_LOCK 0x80000000 + +/* DAC_CNTL bit constants */ +#define DAC_8BIT_EN 0x00000100 +#define DAC_4BPP_PIX_ORDER 0x00000200 +#define DAC_CRC_EN 0x00080000 +#define DAC_MASK_ALL (0xff << 24) +#define DAC_VGA_ADR_EN (1 << 13) +#define DAC_RANGE_CNTL (3 << 0) +#define DAC_BLANKING (1 << 2) + +/* GEN_RESET_CNTL bit constants */ +#define SOFT_RESET_GUI 0x00000001 +#define SOFT_RESET_VCLK 0x00000100 +#define SOFT_RESET_PCLK 0x00000200 +#define SOFT_RESET_ECP 0x00000400 +#define SOFT_RESET_DISPENG_XCLK 0x00000800 + +/* MEM_CNTL bit constants */ +#define MEM_CTLR_STATUS_IDLE 0x00000000 +#define MEM_CTLR_STATUS_BUSY 0x00100000 +#define MEM_SEQNCR_STATUS_IDLE 0x00000000 +#define MEM_SEQNCR_STATUS_BUSY 0x00200000 +#define MEM_ARBITER_STATUS_IDLE 0x00000000 +#define MEM_ARBITER_STATUS_BUSY 0x00400000 +#define MEM_REQ_UNLOCK 0x00000000 +#define MEM_REQ_LOCK 0x00800000 + + +/* RBBM_SOFT_RESET bit constants */ +#define SOFT_RESET_CP (1 << 0) +#define SOFT_RESET_HI (1 << 1) +#define SOFT_RESET_SE (1 << 2) +#define SOFT_RESET_RE (1 << 3) +#define SOFT_RESET_PP (1 << 4) +#define SOFT_RESET_E2 (1 << 5) +#define SOFT_RESET_RB (1 << 6) +#define SOFT_RESET_HDP (1 << 7) + + +/* DEFAULT_SC_BOTTOM_RIGHT bit constants */ +#define DEFAULT_SC_RIGHT_MAX (0x1fff << 0) +#define DEFAULT_SC_BOTTOM_MAX (0x1fff << 16) + +/* MM_INDEX bit constants */ +#define MM_APER 0x80000000 + +/* CLR_CMP_CNTL bit constants */ +#define COMPARE_SRC_FALSE 0x00000000 +#define COMPARE_SRC_TRUE 0x00000001 +#define COMPARE_SRC_NOT_EQUAL 0x00000004 +#define COMPARE_SRC_EQUAL 0x00000005 +#define COMPARE_SRC_EQUAL_FLIP 0x00000007 +#define COMPARE_DST_FALSE 0x00000000 +#define COMPARE_DST_TRUE 0x00000100 +#define COMPARE_DST_NOT_EQUAL 0x00000400 +#define COMPARE_DST_EQUAL 0x00000500 +#define COMPARE_DESTINATION 0x00000000 +#define COMPARE_SOURCE 0x01000000 +#define COMPARE_SRC_AND_DST 0x02000000 + + +/* DP_CNTL bit constants */ +#define DST_X_RIGHT_TO_LEFT 0x00000000 +#define DST_X_LEFT_TO_RIGHT 0x00000001 +#define DST_Y_BOTTOM_TO_TOP 0x00000000 +#define DST_Y_TOP_TO_BOTTOM 0x00000002 +#define DST_X_MAJOR 0x00000000 +#define DST_Y_MAJOR 0x00000004 +#define DST_X_TILE 0x00000008 +#define DST_Y_TILE 0x00000010 +#define DST_LAST_PEL 0x00000020 +#define DST_TRAIL_X_RIGHT_TO_LEFT 0x00000000 +#define DST_TRAIL_X_LEFT_TO_RIGHT 0x00000040 +#define DST_TRAP_FILL_RIGHT_TO_LEFT 0x00000000 +#define DST_TRAP_FILL_LEFT_TO_RIGHT 0x00000080 +#define DST_BRES_SIGN 0x00000100 +#define DST_HOST_BIG_ENDIAN_EN 0x00000200 +#define DST_POLYLINE_NONLAST 0x00008000 +#define DST_RASTER_STALL 0x00010000 +#define DST_POLY_EDGE 0x00040000 + + +/* DP_CNTL_YDIR_XDIR_YMAJOR bit constants (short version of DP_CNTL) */ +#define DST_X_MAJOR_S 0x00000000 +#define DST_Y_MAJOR_S 0x00000001 +#define DST_Y_BOTTOM_TO_TOP_S 0x00000000 +#define DST_Y_TOP_TO_BOTTOM_S 0x00008000 +#define DST_X_RIGHT_TO_LEFT_S 0x00000000 +#define DST_X_LEFT_TO_RIGHT_S 0x80000000 + + +/* DP_DATATYPE bit constants */ +#define DST_8BPP 0x00000002 +#define DST_15BPP 0x00000003 +#define DST_16BPP 0x00000004 +#define DST_24BPP 0x00000005 +#define DST_32BPP 0x00000006 +#define DST_8BPP_RGB332 0x00000007 +#define DST_8BPP_Y8 0x00000008 +#define DST_8BPP_RGB8 0x00000009 +#define DST_16BPP_VYUY422 0x0000000b +#define DST_16BPP_YVYU422 0x0000000c +#define DST_32BPP_AYUV444 0x0000000e +#define DST_16BPP_ARGB4444 0x0000000f +#define BRUSH_SOLIDCOLOR 0x00000d00 +#define SRC_MONO 0x00000000 +#define SRC_MONO_LBKGD 0x00010000 +#define SRC_DSTCOLOR 0x00030000 +#define BYTE_ORDER_MSB_TO_LSB 0x00000000 +#define BYTE_ORDER_LSB_TO_MSB 0x40000000 +#define DP_CONVERSION_TEMP 0x80000000 +#define HOST_BIG_ENDIAN_EN (1 << 29) + + +/* DP_GUI_MASTER_CNTL bit constants */ +#define GMC_SRC_PITCH_OFFSET_DEFAULT 0x00000000 +#define GMC_SRC_PITCH_OFFSET_LEAVE 0x00000001 +#define GMC_DST_PITCH_OFFSET_DEFAULT 0x00000000 +#define GMC_DST_PITCH_OFFSET_LEAVE 0x00000002 +#define GMC_SRC_CLIP_DEFAULT 0x00000000 +#define GMC_SRC_CLIP_LEAVE 0x00000004 +#define GMC_DST_CLIP_DEFAULT 0x00000000 +#define GMC_DST_CLIP_LEAVE 0x00000008 +#define GMC_BRUSH_8x8MONO 0x00000000 +#define GMC_BRUSH_8x8MONO_LBKGD 0x00000010 +#define GMC_BRUSH_8x1MONO 0x00000020 +#define GMC_BRUSH_8x1MONO_LBKGD 0x00000030 +#define GMC_BRUSH_1x8MONO 0x00000040 +#define GMC_BRUSH_1x8MONO_LBKGD 0x00000050 +#define GMC_BRUSH_32x1MONO 0x00000060 +#define GMC_BRUSH_32x1MONO_LBKGD 0x00000070 +#define GMC_BRUSH_32x32MONO 0x00000080 +#define GMC_BRUSH_32x32MONO_LBKGD 0x00000090 +#define GMC_BRUSH_8x8COLOR 0x000000a0 +#define GMC_BRUSH_8x1COLOR 0x000000b0 +#define GMC_BRUSH_1x8COLOR 0x000000c0 +#define GMC_BRUSH_SOLID_COLOR 0x000000d0 +#define GMC_DST_8BPP 0x00000200 +#define GMC_DST_15BPP 0x00000300 +#define GMC_DST_16BPP 0x00000400 +#define GMC_DST_24BPP 0x00000500 +#define GMC_DST_32BPP 0x00000600 +#define GMC_DST_8BPP_RGB332 0x00000700 +#define GMC_DST_8BPP_Y8 0x00000800 +#define GMC_DST_8BPP_RGB8 0x00000900 +#define GMC_DST_16BPP_VYUY422 0x00000b00 +#define GMC_DST_16BPP_YVYU422 0x00000c00 +#define GMC_DST_32BPP_AYUV444 0x00000e00 +#define GMC_DST_16BPP_ARGB4444 0x00000f00 +#define GMC_SRC_MONO 0x00000000 +#define GMC_SRC_MONO_LBKGD 0x00001000 +#define GMC_SRC_DSTCOLOR 0x00003000 +#define GMC_BYTE_ORDER_MSB_TO_LSB 0x00000000 +#define GMC_BYTE_ORDER_LSB_TO_MSB 0x00004000 +#define GMC_DP_CONVERSION_TEMP_9300 0x00008000 +#define GMC_DP_CONVERSION_TEMP_6500 0x00000000 +#define GMC_DP_SRC_RECT 0x02000000 +#define GMC_DP_SRC_HOST 0x03000000 +#define GMC_DP_SRC_HOST_BYTEALIGN 0x04000000 +#define GMC_3D_FCN_EN_CLR 0x00000000 +#define GMC_3D_FCN_EN_SET 0x08000000 +#define GMC_DST_CLR_CMP_FCN_LEAVE 0x00000000 +#define GMC_DST_CLR_CMP_FCN_CLEAR 0x10000000 +#define GMC_AUX_CLIP_LEAVE 0x00000000 +#define GMC_AUX_CLIP_CLEAR 0x20000000 +#define GMC_WRITE_MASK_LEAVE 0x00000000 +#define GMC_WRITE_MASK_SET 0x40000000 +#define GMC_CLR_CMP_CNTL_DIS (1 << 28) +#define GMC_SRC_DATATYPE_COLOR (3 << 12) +#define ROP3_S 0x00cc0000 +#define ROP3_P 0x00f00000 +#define DP_SRC_SOURCE_MASK (7 << 24) +#define GMC_BRUSH_NONE (15 << 4) +#define DP_SRC_SOURCE_MEMORY (2 << 24) +#define GMC_BRUSH_SOLIDCOLOR 0x000000d0 + +/* DP_MIX bit constants */ +#define DP_SRC_RECT 0x00000200 +#define DP_SRC_HOST 0x00000300 +#define DP_SRC_HOST_BYTEALIGN 0x00000400 + +#define ROP3_PATCOPY 0x00f00000 + +/* masks */ + +#define CONFIG_MEMSIZE_MASK 0x1f000000 +#define MEM_CFG_TYPE 0x40000000 +#define DST_OFFSET_MASK 0x003fffff +#define DST_PITCH_MASK 0x3fc00000 +#define DEFAULT_TILE_MASK 0xc0000000 +#define PPLL_DIV_SEL_MASK 0x00000300 +#define PPLL_RESET 0x00000001 +#define PPLL_ATOMIC_UPDATE_EN 0x00010000 +#define PPLL_REF_DIV_MASK 0x000003ff +#define PPLL_FB3_DIV_MASK 0x000007ff +#define PPLL_POST3_DIV_MASK 0x00070000 +#define PPLL_ATOMIC_UPDATE_R 0x00008000 +#define PPLL_ATOMIC_UPDATE_W 0x00008000 +#define PPLL_VGA_ATOMIC_UPDATE_EN 0x00020000 + +#define GUI_ACTIVE 0x80000000 + +#endif /* _RADEON_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/radeon/radeonfb.c Tue Sep 18 16:12:34 2001 +0000 @@ -0,0 +1,1916 @@ +/* + * 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 + * + * + * Special thanks to ATI DevRel team for their hardware donations. + * + */ + + +#define RADEON_VERSION "0.0.9" + + +#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/malloc.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 <asm/io.h> + +#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 +#endif + + + +enum radeon_chips { + RADEON_QD, + RADEON_QE, + RADEON_QF, + RADEON_QG +}; + + +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}, + { 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 { + 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 flags; + u32 pix_clock; + int xres, yres; + int bpp; + u32 crtc_gen_cntl; + u32 crtc_ext_cntl; + u32 dac_cntl; + u32 dda_config; + u32 dda_on_off; + u32 ppll_div_3; + u32 ppll_ref_div; +}; + + +struct radeonfb_info { + struct fb_info info; + + struct radeon_regs state; + struct radeon_regs init_state; + + char name[10]; + char ram_type[12]; + + u32 mmio_base_phys; + u32 fb_base_phys; + + u32 mmio_base; + u32 fb_base; + + struct pci_dev *pdev; + + 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; + + u32 dp_gui_master_cntl; + + struct pll_info pll; + int pll_output_freq, post_div, fb_div; + + struct ram_info ram; + +#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_CFB32) + u_int32_t cfb32[16]; +#endif + } con_cmap; +#endif +}; + + +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) + + +/* + * 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 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 | + SOFT_RESET_HDP); + 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 | + SOFT_RESET_HDP)); + 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 fontname[40] __initdata; +static char *mode_option __initdata; +static char noaccel __initdata = 0; + +#ifdef FBCON_HAS_CFB8 +static struct display_switch fbcon_radeon8; +#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); +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_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 radeon_init_disp_var (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 char *radeon_find_rom(struct radeonfb_info *rinfo); +static void radeon_get_pllinfo(struct radeonfb_info *rinfo, char *bios_seg); + + +static struct fb_ops radeon_fb_ops = { + fb_get_fix: radeonfb_get_fix, + fb_get_var: radeonfb_get_var, + fb_set_var: radeonfb_set_var, + fb_get_cmap: radeonfb_get_cmap, + fb_set_cmap: radeonfb_set_cmap, + fb_pan_display: radeonfb_pan_display, + fb_ioctl: radeonfb_ioctl, +}; + + +static struct pci_driver radeonfb_driver = { + name: "radeonfb", + id_table: radeonfb_pci_table, + probe: radeonfb_pci_register, + remove: radeonfb_pci_unregister, +}; + + +int __init radeonfb_init (void) +{ + return pci_module_init (&radeonfb_driver); +} + + +void __exit radeonfb_exit (void) +{ + pci_unregister_driver (&radeonfb_driver); +} + + +int __init radeonfb_setup (char *options) +{ + char *this_opt; + + if (!options || !*options) + return 0; + + for (this_opt = strtok (options, ","); this_opt; + this_opt = strtok (NULL, ",")) { + if (!strncmp (this_opt, "font:", 5)) { + char *p; + int i; + + p = this_opt + 5; + for (i=0; i<sizeof (fontname) - 1; i++) + if (!*p || *p == ' ' || *p == ',') + break; + memcpy(fontname, this_opt + 5, i); + } else if (!strncmp(this_opt, "noaccel", 7)) { + noaccel = 1; + } + else mode_option = this_opt; + } + + return 0; +} + +#ifdef MODULE +module_init(radeonfb_init); +module_exit(radeonfb_exit); +#endif + + +MODULE_AUTHOR("Ani Joshi"); +MODULE_DESCRIPTION("framebuffer driver for ATI Radeon chipset"); + + + +static int radeonfb_pci_register (struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct radeonfb_info *rinfo; + u32 tmp; + int i, j; + char *bios_seg = NULL; + + rinfo = kmalloc (sizeof (struct radeonfb_info), GFP_KERNEL); + if (!rinfo) { + printk ("radeonfb: could not allocate memory\n"); + return -ENODEV; + } + + memset (rinfo, 0, sizeof (struct radeonfb_info)); + + /* enable device */ + { + int err; + + if ((err = pci_enable_device(pdev))) { + printk("radeonfb: cannot enable device\n"); + kfree (rinfo); + return -ENODEV; + } + } + + /* set base addrs */ + rinfo->fb_base_phys = pci_resource_start (pdev, 0); + rinfo->mmio_base_phys = pci_resource_start (pdev, 2); + + /* request the mem regions */ + if (!request_mem_region (rinfo->fb_base_phys, + pci_resource_len(pdev, 0), "radeonfb")) { + printk ("radeonfb: cannot reserve FB region\n"); + kfree (rinfo); + return -ENODEV; + } + + if (!request_mem_region (rinfo->mmio_base_phys, + pci_resource_len(pdev, 2), "radeonfb")) { + printk ("radeonfb: cannot reserve MMIO region\n"); + release_mem_region (rinfo->fb_base_phys, + pci_resource_len(pdev, 0)); + kfree (rinfo); + return -ENODEV; + } + + /* map the regions */ + rinfo->mmio_base = (u32) ioremap (rinfo->mmio_base_phys, + RADEON_REGSIZE); + if (!rinfo->mmio_base) { + printk ("radeonfb: cannot map MMIO\n"); + release_mem_region (rinfo->mmio_base_phys, + pci_resource_len(pdev, 2)); + release_mem_region (rinfo->fb_base_phys, + pci_resource_len(pdev, 0)); + kfree (rinfo); + return -ENODEV; + } + + /* chipset */ + switch (pdev->device) { + case PCI_DEVICE_ID_RADEON_QD: + strcpy(rinfo->name, "Radeon QD "); + break; + case PCI_DEVICE_ID_RADEON_QE: + strcpy(rinfo->name, "Radeon QE "); + break; + case PCI_DEVICE_ID_RADEON_QF: + strcpy(rinfo->name, "Radeon QF "); + break; + case PCI_DEVICE_ID_RADEON_QG: + strcpy(rinfo->name, "Radeon QG "); + break; + default: + return -ENODEV; + } + + /* framebuffer size */ + tmp = INREG(CONFIG_MEMSIZE); + + /* mem size is bits [28:0], mask off the rest */ + rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK; + + /* ram type */ + tmp = INREG(MEM_SDRAM_MODE_REG); + switch ((MEM_CFG_TYPE & tmp) >> 30) { + case 0: + /* SDR SGRAM (2:1) */ + strcpy(rinfo->ram_type, "SDR SGRAM"); + rinfo->ram.ml = 4; + rinfo->ram.mb = 4; + rinfo->ram.trcd = 1; + rinfo->ram.trp = 2; + rinfo->ram.twr = 1; + rinfo->ram.cl = 2; + rinfo->ram.loop_latency = 16; + rinfo->ram.rloop = 16; + + break; + case 1: + /* DDR SGRAM */ + strcpy(rinfo->ram_type, "DDR SGRAM"); + rinfo->ram.ml = 4; + rinfo->ram.mb = 4; + rinfo->ram.trcd = 3; + rinfo->ram.trp = 3; + rinfo->ram.twr = 2; + rinfo->ram.cl = 3; + rinfo->ram.tr2w = 1; + rinfo->ram.loop_latency = 16; + rinfo->ram.rloop = 16; + + break; + default: + /* 64-bit SDR SGRAM */ + strcpy(rinfo->ram_type, "SDR SGRAM 64"); + rinfo->ram.ml = 4; + rinfo->ram.mb = 8; + rinfo->ram.trcd = 3; + rinfo->ram.trp = 3; + rinfo->ram.twr = 1; + rinfo->ram.cl = 3; + rinfo->ram.tr2w = 1; + rinfo->ram.loop_latency = 17; + rinfo->ram.rloop = 17; + + break; + } + + bios_seg = radeon_find_rom(rinfo); + radeon_get_pllinfo(rinfo, bios_seg); + + printk("radeonfb: ref_clk=%d, ref_div=%d, xclk=%d\n", + rinfo->pll.ref_clk, rinfo->pll.ref_div, rinfo->pll.xclk); + + RTRACE("radeonfb: probed %s %dk videoram\n", (rinfo->ram_type), (rinfo->video_ram/1024)); + + rinfo->fb_base = (u32) ioremap (rinfo->fb_base_phys, + rinfo->video_ram); + if (!rinfo->fb_base) { + printk ("radeonfb: cannot map FB\n"); + iounmap ((void*)rinfo->mmio_base); + release_mem_region (rinfo->mmio_base_phys, + pci_resource_len(pdev, 2)); + release_mem_region (rinfo->fb_base_phys, + pci_resource_len(pdev, 0)); + kfree (rinfo); + return -ENODEV; + } + + /* XXX turn off accel for now, blts aren't working right */ + noaccel = 1; + + /* set all the vital stuff */ + radeon_set_fbinfo (rinfo); + + /* save current mode regs before we switch into the new one + * so we can restore this upon __exit + */ + radeon_save_state (rinfo, &rinfo->init_state); + + /* init palette */ + for (i=0; i<16; i++) { + j = color_table[i]; + rinfo->palette[i].red = default_red[j]; + rinfo->palette[i].green = default_grn[j]; + rinfo->palette[i].blue = default_blu[j]; + } + + pdev->driver_data = rinfo; + + if (register_framebuffer ((struct fb_info *) rinfo) < 0) { + printk ("radeonfb: could not register framebuffer\n"); + iounmap ((void*)rinfo->fb_base); + iounmap ((void*)rinfo->mmio_base); + release_mem_region (rinfo->mmio_base_phys, + pci_resource_len(pdev, 2)); + release_mem_region (rinfo->fb_base_phys, + pci_resource_len(pdev, 0)); + kfree (rinfo); + return -ENODEV; + } + + if (!noaccel) { + /* initialize the engine */ + radeon_engine_init (rinfo); + } + + printk ("radeonfb: ATI Radeon %s %d MB\n", rinfo->ram_type, + (rinfo->video_ram/(1024*1024))); + + return 0; +} + + + +static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev) +{ + struct radeonfb_info *rinfo = pdev->driver_data; + + if (!rinfo) + return; + + /* restore original state */ + radeon_write_mode (rinfo, &rinfo->init_state); + + unregister_framebuffer ((struct fb_info *) rinfo); + + iounmap ((void*)rinfo->mmio_base); + iounmap ((void*)rinfo->fb_base); + + release_mem_region (rinfo->mmio_base_phys, + pci_resource_len(pdev, 2)); + release_mem_region (rinfo->fb_base_phys, + pci_resource_len(pdev, 0)); + + kfree (rinfo); +} + + + +static char *radeon_find_rom(struct radeonfb_info *rinfo) +{ + u32 segstart; + char *rom_base; + char *rom; + int stage; + int i; + char aty_rom_sig[] = "761295520"; + char radeon_sig[] = "RG6"; + +#if defined(__i386__) + 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++) { + if (radeon_sig[0] == *rom) + if (strncmp(radeon_sig, rom, + strlen(radeon_sig)) == 0) + stage = 4; + 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; + } else { + /* no BIOS or BIOS not found, use defaults */ + + rinfo->pll.ppll_max = 35000; + rinfo->pll.ppll_min = 12000; + rinfo->pll.xclk = 16600; + rinfo->pll.ref_div = 67; + rinfo->pll.ref_clk = 2700; + } +} + +static void radeon_engine_init (struct radeonfb_info *rinfo) +{ + u32 temp; + + /* disable 3D engine */ + OUTREG(RB3D_CNTL, 0); + + radeon_engine_reset (); + + radeon_fifo_wait (1); + OUTREG(DSTCACHE_MODE, 0); + + /* XXX */ + rinfo->pitch = ((rinfo->xres * (rinfo->depth / 8) + 0x3f)) >> 6; + + radeon_fifo_wait (1); + temp = INREG(DEFAULT_PITCH_OFFSET); + OUTREG(DEFAULT_PITCH_OFFSET, ((temp & 0xc0000000) | + (rinfo->pitch << 0x16))); + + radeon_fifo_wait (1); + OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN); + + radeon_fifo_wait (1); + OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX | + DEFAULT_SC_BOTTOM_MAX)); + + temp = radeon_get_dstbpp(rinfo->depth); + rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS); + radeon_fifo_wait (1); + OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl | + GMC_BRUSH_SOLID_COLOR | + GMC_SRC_DATATYPE_COLOR)); + + radeon_fifo_wait (7); + + /* clear line drawing regs */ + OUTREG(DST_LINE_START, 0); + OUTREG(DST_LINE_END, 0); + + /* set brush color regs */ + OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff); + OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000); + + /* set source color regs */ + OUTREG(DP_SRC_FRGD_CLR, 0xffffffff); + OUTREG(DP_SRC_BKGD_CLR, 0x00000000); + + /* default write mask */ + OUTREG(DP_WRITE_MSK, 0xffffffff); + + radeon_engine_idle (); +} + + + +static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo) +{ + struct fb_info *info; + + info = &rinfo->info; + + strcpy (info->modename, rinfo->name); + info->node = -1; + info->flags = FBINFO_FLAG_DEFAULT; + info->fbops = &radeon_fb_ops; + info->display_fg = NULL; + strncpy (info->fontname, fontname, sizeof (info->fontname)); + info->fontname[sizeof (info->fontname) - 1] = 0; + info->changevar = NULL; + info->switch_con = radeonfb_switch; + info->updatevar = radeonfb_updatevar; + info->blank = radeonfb_blank; + + if (radeon_init_disp (rinfo) < 0) + return -1; + + return 0; +} + + + +static int __devinit radeon_init_disp (struct radeonfb_info *rinfo) +{ + struct fb_info *info; + struct display *disp; + + info = &rinfo->info; + disp = &rinfo->disp; + + disp->var = radeonfb_default_var; + info->disp = disp; + + radeon_set_dispsw (rinfo); + + if (noaccel) + disp->scrollmode = SCROLL_YREDRAW; + else + disp->scrollmode = 0; + + rinfo->currcon_display = disp; + + if ((radeon_init_disp_var (rinfo)) < 0) + return -1; + + return 0; +} + + + +static int radeon_init_disp_var (struct radeonfb_info *rinfo) +{ +#ifndef MODULE + if (mode_option) + fb_find_mode (&rinfo->disp.var, &rinfo->info, mode_option, + NULL, 0, NULL, 8); + else +#endif + fb_find_mode (&rinfo->disp.var, &rinfo->info, "640x480-8@60", + NULL, 0, NULL, 0); + + if (noaccel) + rinfo->disp.var.accel_flags &= ~FB_ACCELF_TEXT; + else + rinfo->disp.var.accel_flags |= FB_ACCELF_TEXT; + + return 0; +} + + + +static void radeon_set_dispsw (struct radeonfb_info *rinfo) +{ + struct display *disp = &rinfo->disp; + int accel; + + accel = disp->var.accel_flags & FB_ACCELF_TEXT; + + disp->dispsw_data = NULL; + + disp->screen_base = (char*)rinfo->fb_base; + disp->type = FB_TYPE_PACKED_PIXELS; + disp->type_aux = 0; + disp->ypanstep = 1; + disp->ywrapstep = 0; + disp->can_soft_blank = 1; + disp->inverse = 0; + + rinfo->depth = disp->var.bits_per_pixel; + switch (disp->var.bits_per_pixel) { +#ifdef FBCON_HAS_CFB8 + case 8: + disp->dispsw = accel ? &fbcon_radeon8 : &fbcon_cfb8; + disp->visual = FB_VISUAL_PSEUDOCOLOR; + disp->line_length = disp->var.xres_virtual; + break; +#endif +#ifdef FBCON_HAS_CFB16 + case 16: + disp->dispsw = &fbcon_cfb16; + disp->dispsw_data = &rinfo->con_cmap.cfb16; + disp->visual = FB_VISUAL_DIRECTCOLOR; + disp->line_length = disp->var.xres_virtual * 2; + break; +#endif +#ifdef FBCON_HAS_CFB32 + case 32: + disp->dispsw = &fbcon_cfb32; + disp->dispsw_data = &rinfo->con_cmap.cfb32; + disp->visual = FB_VISUAL_DIRECTCOLOR; + disp->line_length = disp->var.xres_virtual * 4; + break; +#endif + default: + printk ("radeonfb: setting fbcon_dummy renderer\n"); + disp->dispsw = &fbcon_dummy; + } + + return; +} + + + +/* + * fb ops + */ + +static int radeonfb_get_fix (struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) +{ + struct radeonfb_info *rinfo = (struct radeonfb_info *) info; + struct display *disp; + + disp = (con < 0) ? rinfo->info.disp : &fb_display[con]; + + memset (fix, 0, sizeof (struct fb_fix_screeninfo)); + strcpy (fix->id, rinfo->name); + + fix->smem_start = rinfo->fb_base_phys; + fix->smem_len = rinfo->video_ram; + + fix->type = disp->type; + fix->type_aux = disp->type_aux; + fix->visual = disp->visual; + + fix->xpanstep = 1; + fix->ypanstep = 1; + fix->ywrapstep = 0; + + fix->line_length = disp->line_length; + + fix->mmio_start = rinfo->mmio_base_phys; + fix->mmio_len = RADEON_REGSIZE; + if (noaccel) + fix->accel = FB_ACCEL_NONE; + else + fix->accel = 40; /* XXX */ + + return 0; +} + + + +static int radeonfb_get_var (struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct radeonfb_info *rinfo = (struct radeonfb_info *) info; + + *var = (con < 0) ? rinfo->disp.var : fb_display[con].var; + + return 0; +} + + + +static int radeonfb_set_var (struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct radeonfb_info *rinfo = (struct radeonfb_info *) info; + struct display *disp; + struct fb_var_screeninfo v; + int nom, den, i, accel; + unsigned chgvar = 0; + static struct { + int xres, yres; + } modes[] = { + { + 1600, 1280}, { + 1280, 1024}, { + 1024, 768}, { + 800, 600}, { + 640, 480}, { + -1, -1} + }; + + disp = (con < 0) ? rinfo->info.disp : &fb_display[con]; + + accel = var->accel_flags & FB_ACCELF_TEXT; + + if (con >= 0) { + chgvar = ((disp->var.xres != var->xres) || + (disp->var.yres != var->yres) || + (disp->var.xres_virtual != var->xres_virtual) || + (disp->var.yres_virtual != var->yres_virtual) || + memcmp (&disp->var.red, &var->red, sizeof (var->red)) || + memcmp (&disp->var.green, &var->green, sizeof (var->green)) || + memcmp (&disp->var.blue, &var->blue, sizeof (var->blue))); + } + + memcpy (&v, var, sizeof (v)); + + switch (v.bits_per_pixel) { +#ifdef FBCON_HAS_CFB8 + case 8: + v.bits_per_pixel = 8; + disp->dispsw = accel ? &fbcon_radeon8 : &fbcon_cfb8; + nom = den = 1; + disp->line_length = v.xres_virtual; + disp->visual = FB_VISUAL_PSEUDOCOLOR; + v.red.offset = v.green.offset = v.blue.offset = 0; + v.red.length = v.green.length = v.blue.length = 8; + break; +#endif + +#ifdef FBCON_HAS_CFB16 + case 16: + v.bits_per_pixel = 16; + disp->dispsw = &fbcon_cfb16; + disp->dispsw_data = &rinfo->con_cmap.cfb16; + nom = 2; + den = 1; + disp->line_length = v.xres_virtual * 2; + disp->visual = FB_VISUAL_DIRECTCOLOR; + v.red.offset = 11; + v.green.offset = 5; + v.blue.offset = 0; + v.red.length = 5; + v.green.length = 6; + v.blue.length = 5; + break; +#endif + +#ifdef FBCON_HAS_CFB32 + case 32: + v.bits_per_pixel = 32; + disp->dispsw = &fbcon_cfb32; + disp->dispsw_data = rinfo->con_cmap.cfb32; + nom = 4; + den = 1; + disp->line_length = v.xres_virtual * 4; + disp->visual = FB_VISUAL_DIRECTCOLOR; + v.red.offset = 16; + v.green.offset = 8; + v.blue.offset = 0; + v.red.length = v.blue.length = v.green.length = 8; + break; +#endif + default: + printk ("radeonfb: mode %dx%dx%d rejected, color depth invalid\n", + var->xres, var->yres, var->bits_per_pixel); + return -EINVAL; + } + + if (v.xres * nom / den * v.yres > (rinfo->video_ram)) { + printk ("radeonfb: mode %dx%dx%d rejected, not enough video ram\n", + var->xres, var->yres, var->bits_per_pixel); + return -EINVAL; + } + + if (v.xres_virtual == -1 && v.yres_virtual == -1) { + printk ("radeonfb: using maximum available virtual resolution\n"); + for (i = 0; modes[i].xres != -1; i++) { + if (modes[i].xres * nom / den * modes[i].yres < (rinfo->video_ram/2)) + break; + } + if (modes[i].xres == -1) { + printk ("radeonfb: could not find a virtual res\n"); + return -EINVAL; + } + v.xres_virtual = modes[i].xres; + v.yres_virtual = modes[i].yres; + + printk ("radeonfb: virtual resolution set to maximum of %dx%d\n", + v.xres_virtual, v.yres_virtual); + } + + if (v.xoffset < 0) + v.xoffset = 0; + if (v.yoffset < 0) + v.yoffset = 0; + + if (v.xoffset > v.xres_virtual - v.xres) + v.xoffset = v.xres_virtual - v.xres - 1; + + if (v.yoffset > v.yres_virtual - v.yres) + v.yoffset = v.yres_virtual - v.yres - 1; + + v.red.msb_right = v.green.msb_right = v.blue.msb_right = + v.transp.offset = v.transp.length = + v.transp.msb_right = 0; + + switch (v.activate & FB_ACTIVATE_MASK) { + case FB_ACTIVATE_TEST: + return 0; + case FB_ACTIVATE_NXTOPEN: + case FB_ACTIVATE_NOW: + break; + default: + return -EINVAL; + } + + disp->type = FB_TYPE_PACKED_PIXELS; + + memcpy (&disp->var, &v, sizeof (v)); + + radeon_load_video_mode (rinfo, &v); + + if (chgvar && info && info->changevar) + info->changevar (con); + + return 0; +} + + + +static int radeonfb_get_cmap (struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + struct radeonfb_info *rinfo = (struct radeonfb_info *) info; + struct display *disp; + + disp = (con < 0) ? rinfo->info.disp : &fb_display[con]; + + if (con == rinfo->currcon) { + int rc = fb_get_cmap (cmap, kspc, radeon_getcolreg, info); + return rc; + } else if (disp->cmap.len) + fb_copy_cmap (&disp->cmap, cmap, kspc ? 0 : 2); + else + fb_copy_cmap (fb_default_cmap (radeon_get_cmap_len (&disp->var)), + cmap, kspc ? 0 : 2); + + return 0; +} + + + +static int radeonfb_set_cmap (struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + struct radeonfb_info *rinfo = (struct radeonfb_info *) info; + struct display *disp; + unsigned int cmap_len; + + disp = (con < 0) ? rinfo->info.disp : &fb_display[con]; + + cmap_len = radeon_get_cmap_len (&disp->var); + if (disp->cmap.len != cmap_len) { + int err = fb_alloc_cmap (&disp->cmap, cmap_len, 0); + if (err) + return err; + } + + if (con == rinfo->currcon) { + int rc = fb_set_cmap (cmap, kspc, radeon_setcolreg, info); + return rc; + } else + fb_copy_cmap (cmap, &disp->cmap, kspc ? 0 : 1); + + return 0; +} + + + +static int radeonfb_pan_display (struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct radeonfb_info *rinfo = (struct radeonfb_info *) info; + struct display *disp; + unsigned int base; + + disp = (con < 0) ? rinfo->info.disp : &fb_display[con]; + + if (var->xoffset > (var->xres_virtual - var->xres)) + return -EINVAL; + if (var->yoffset > (var->yres_virtual - var->yres)) + return -EINVAL; + + if (var->vmode & FB_VMODE_YWRAP) { + if (var->yoffset < 0 || + var->yoffset >= disp->var.yres_virtual || + var->xoffset ) + return -EINVAL; + } else { + if (var->xoffset + disp->var.xres > disp->var.xres_virtual || + var->yoffset + disp->var.yres > disp->var.yres_virtual) + return -EINVAL; + } + + base = var->yoffset * disp->line_length + var->xoffset; + + disp->var.xoffset = var->xoffset; + disp->var.yoffset = var->yoffset; + + if (var->vmode & FB_VMODE_YWRAP) + disp->var.vmode |= FB_VMODE_YWRAP; + else + disp->var.vmode &= ~FB_VMODE_YWRAP; + + return 0; +} + + + +static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, int con, struct fb_info *info) +{ + return -EINVAL; +} + + + +static int radeonfb_switch (int con, struct fb_info *info) +{ + struct radeonfb_info *rinfo = (struct radeonfb_info *) info; + struct display *disp; + struct fb_cmap *cmap; + int switchcon = 0; + + disp = (con < 0) ? rinfo->info.disp : &fb_display[con]; + + if (rinfo->currcon >= 0) { + cmap = &(rinfo->currcon_display->cmap); + if (cmap->len) + fb_get_cmap (cmap, 1, radeon_getcolreg, info); + } + + if ((disp->var.xres != rinfo->xres) || + (disp->var.yres != rinfo->yres) || + (disp->var.pixclock != rinfo->pixclock) || + (disp->var.bits_per_pixel != rinfo->depth)) + switchcon = 1; + + if (switchcon) { + rinfo->currcon = con; + rinfo->currcon_display = disp; + disp->var.activate = FB_ACTIVATE_NOW; + + radeonfb_set_var (&disp->var, con, info); + radeon_set_dispsw (rinfo); + } + + return 0; +} + + + +static int radeonfb_updatevar (int con, struct fb_info *info) +{ + int rc; + + rc = (con < 0) ? -EINVAL : radeonfb_pan_display (&fb_display[con].var, + con, info); + + return rc; +} + +static void radeonfb_blank (int blank, struct fb_info *info) +{ + struct radeonfb_info *rinfo = (struct radeonfb_info *) info; + u8 mode = 0; + + switch (blank) { + case 0: + /* unblank */ + mode = 0; + break; + case 1: + /* blank */ + mode = ((INREG8(CRTC_EXT_CNTL + 1) & 3) | 4); + break; + case 2: + case 3: + case 4: + mode = blank | 4; + break; + } + + OUTREG8(CRTC_EXT_CNTL + 1, mode); +} + + + +static int radeon_get_cmap_len (const struct fb_var_screeninfo *var) +{ + int rc = 16; /* reasonable default */ + + switch (var->bits_per_pixel) { + case 8: + rc = 256; + break; + case 16: + rc = 64; + break; + default: + rc = 32; + break; + } + + return rc; +} + + + +static int radeon_getcolreg (unsigned regno, unsigned *red, unsigned *green, + unsigned *blue, unsigned *transp, + struct fb_info *info) +{ + struct radeonfb_info *rinfo = (struct radeonfb_info *) info; + + if (regno > 255) + return 1; + + *red = (rinfo->palette[regno].red<<8) | rinfo->palette[regno].red; + *green = (rinfo->palette[regno].green<<8) | rinfo->palette[regno].green; + *blue = (rinfo->palette[regno].blue<<8) | rinfo->palette[regno].blue; + *transp = 0; + + return 0; +} + + + +static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, struct fb_info *info) +{ + struct radeonfb_info *rinfo = (struct radeonfb_info *) info; + u32 pindex, col; + + if (regno > 255) + return 1; + + red >>= 8; + green >>= 8; + blue >>= 8; + rinfo->palette[regno].red = red; + rinfo->palette[regno].green = green; + rinfo->palette[regno].blue = blue; + + /* init gamma for hicolor */ + if ((rinfo->depth > 8) && (regno == 0)) { + int i; + u32 tmp; + + for (i=0; i<255; i++) { + OUTREG(PALETTE_INDEX, i); + tmp = (i << 16) | (i << 8) | i; + radeon_fifo_wait(32); + OUTREG(PALETTE_DATA, tmp); + } + } + + /* default */ + pindex = regno; + col = (red << 16) | (green << 8) | blue; + + if (rinfo->depth == 16) { + pindex = regno << 3; + + if ((rinfo->depth == 16) && (regno >= 32)) { + pindex -= 252; + + col = (rinfo->palette[regno >> 1].red << 16) | + (green << 8) | + (rinfo->palette[regno >> 1].blue); + } else { + col = (red << 16) | (green << 8) | blue; + } + } + + OUTREG8(PALETTE_INDEX, pindex); + radeon_fifo_wait(32); + OUTREG(PALETTE_DATA, col); + +#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32) + if (regno < 32) { + switch (rinfo->depth) { +#ifdef FBCON_HAS_CFB16 + case 16: + rinfo->con_cmap.cfb16[regno] = (regno << 10) | (regno << 5) | + regno; + break; +#endif +#ifdef FBCON_HAS_CFB32 + case 32: { + u32 i; + + i = (regno << 8) | regno; + rinfo->con_cmap.cfb32[regno] = (i << 16) | i; + break; + } +#endif + } + } +#endif + return 0; +} + + + +static void radeon_save_state (struct radeonfb_info *rinfo, + struct radeon_regs *save) +{ + save->crtc_gen_cntl = INREG(CRTC_GEN_CNTL); + save->crtc_ext_cntl = INREG(CRTC_EXT_CNTL); + save->dac_cntl = INREG(DAC_CNTL); + save->crtc_h_total_disp = INREG(CRTC_H_TOTAL_DISP); + save->crtc_h_sync_strt_wid = INREG(CRTC_H_SYNC_STRT_WID); + save->crtc_v_total_disp = INREG(CRTC_V_TOTAL_DISP); + save->crtc_v_sync_strt_wid = INREG(CRTC_V_SYNC_STRT_WID); + save->crtc_pitch = INREG(CRTC_PITCH); +} + + + +static void radeon_load_video_mode (struct radeonfb_info *rinfo, + struct fb_var_screeninfo *mode) +{ + struct radeon_regs newmode; + int hTotal, vTotal, hSyncStart, hSyncEnd, + hSyncPol, vSyncStart, vSyncEnd, vSyncPol, cSync; + u8 hsync_adj_tab[] = {0, 0x12, 9, 9, 6, 5}; + u32 dotClock = 1000000000 / mode->pixclock, + sync, h_sync_pol, v_sync_pol; + int freq = dotClock / 10; /* x 100 */ + int xclk_freq, vclk_freq, xclk_per_trans, xclk_per_trans_precise; + int useable_precision, roff, ron; + int min_bits, format = 0; + int hsync_start, hsync_fudge, bytpp, hsync_wid, vsync_wid; + + rinfo->xres = mode->xres; + rinfo->yres = mode->yres; + rinfo->pixclock = mode->pixclock; + + hSyncStart = mode->xres + mode->right_margin; + hSyncEnd = hSyncStart + mode->hsync_len; + hTotal = hSyncEnd + mode->left_margin; + + vSyncStart = mode->yres + mode->lower_margin; + vSyncEnd = vSyncStart + mode->vsync_len; + vTotal = vSyncEnd + mode->upper_margin; + + sync = mode->sync; + h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1; + v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1; + + RTRACE("hStart = %d, hEnd = %d, hTotal = %d\n", + hSyncStart, hSyncEnd, hTotal); + RTRACE("vStart = %d, vEnd = %d, vTotal = %d\n", + vSyncStart, vSyncEnd, vTotal); + + hsync_wid = (hSyncEnd - hSyncStart) / 8; + vsync_wid = vSyncEnd - vSyncStart; + if (hsync_wid == 0) + hsync_wid = 1; + else if (hsync_wid > 0x3f) /* max */ + hsync_wid = 0x3f; + + if (vsync_wid == 0) + vsync_wid = 1; + else if (vsync_wid > 0x1f) /* max */ + vsync_wid = 0x1f; + + if (mode->sync & FB_SYNC_HOR_HIGH_ACT) + hSyncPol = 1; + else + hSyncPol = 0; + + if (mode->sync & FB_SYNC_VERT_HIGH_ACT) + vSyncPol = 1; + else + vSyncPol = 0; + + cSync = mode->sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0; + + switch (mode->bits_per_pixel) { + case 8: + format = DST_8BPP; + bytpp = 1; + break; + case 16: + format = DST_16BPP; + bytpp = 2; + break; + case 24: + format = DST_24BPP; + bytpp = 3; + break; + case 32: + format = DST_32BPP; + bytpp = 4; + break; + } + + hsync_fudge = hsync_adj_tab[format-1]; + hsync_start = hSyncStart - 8 + hsync_fudge; + + newmode.crtc_gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN | + (format << 8); + + newmode.crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN; + + newmode.dac_cntl = INREG(DAC_CNTL) | DAC_MASK_ALL | DAC_VGA_ADR_EN | + DAC_8BIT_EN; + + newmode.crtc_h_total_disp = ((((hTotal / 8) - 1) & 0xffff) | + (((mode->xres / 8) - 1) << 16)); + + newmode.crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) | + (hsync_wid << 16) | (hSyncPol << 23)); + + newmode.crtc_v_total_disp = ((vTotal - 1) & 0xffff) | + ((mode->yres - 1) << 16); + + newmode.crtc_v_sync_strt_wid = (((vSyncStart - 1) & 0xfff) | + (vsync_wid << 16) | (vSyncPol << 23)); + + newmode.crtc_pitch = (mode->xres >> 3); + + rinfo->pitch = ((mode->xres * ((mode->bits_per_pixel + 1) / 8) + 0x3f) + & ~(0x3f)) / 64; + + RTRACE("h_total_disp = 0x%x\t hsync_strt_wid = 0x%x\n", + newmode.crtc_h_total_disp, newmode.crtc_h_sync_strt_wid); + RTRACE("v_total_disp = 0x%x\t vsync_strt_wid = 0x%x\n", + newmode.crtc_v_total_disp, newmode.crtc_v_sync_strt_wid); + + newmode.xres = mode->xres; + newmode.yres = mode->yres; + + rinfo->bpp = mode->bits_per_pixel; + + if (freq > rinfo->pll.ppll_max) + freq = rinfo->pll.ppll_max; + if (freq*12 < rinfo->pll.ppll_min) + freq = rinfo->pll.ppll_min / 12; + + { + struct { + int divider; + int bitvalue; + } *post_div, + post_divs[] = { + { 1, 0 }, + { 2, 1 }, + { 4, 2 }, + { 8, 3 }, + { 3, 4 }, + { 16, 5 }, + { 6, 6 }, + { 12, 7 }, + { 0, 0 }, + }; + + for (post_div = &post_divs[0]; post_div->divider; ++post_div) { + rinfo->pll_output_freq = post_div->divider * freq; + if (rinfo->pll_output_freq >= rinfo->pll.ppll_min && + rinfo->pll_output_freq <= rinfo->pll.ppll_max) + break; + } + + rinfo->post_div = post_div->divider; + rinfo->fb_div = round_div(rinfo->pll.ref_div*rinfo->pll_output_freq, + rinfo->pll.ref_clk); + newmode.ppll_ref_div = rinfo->pll.ref_div; + newmode.ppll_div_3 = rinfo->fb_div | (post_div->bitvalue << 16); + } + + RTRACE("post div = 0x%x\n", rinfo->post_div); + RTRACE("fb_div = 0x%x\n", rinfo->fb_div); + RTRACE("ppll_div_3 = 0x%x\n", newmode.ppll_div_3); + + /* DDA */ + vclk_freq = round_div(rinfo->pll.ref_clk * rinfo->fb_div, + rinfo->pll.ref_div * rinfo->post_div); + xclk_freq = rinfo->pll.xclk; + + xclk_per_trans = round_div(xclk_freq * 128, vclk_freq * mode->bits_per_pixel); + + min_bits = min_bits_req(xclk_per_trans); + useable_precision = min_bits + 1; + + xclk_per_trans_precise = round_div((xclk_freq * 128) << (11 - useable_precision), + vclk_freq * mode->bits_per_pixel); + + ron = (4 * rinfo->ram.mb + 3 * _max(rinfo->ram.trcd - 2, 0) + + 2 * rinfo->ram.trp + rinfo->ram.twr + rinfo->ram.cl + rinfo->ram.tr2w + + xclk_per_trans) << (11 - useable_precision); + roff = xclk_per_trans_precise * (32 - 4); + + RTRACE("ron = %d, roff = %d\n", ron, roff); + RTRACE("vclk_freq = %d, per = %d\n", vclk_freq, xclk_per_trans_precise); + + if ((ron + rinfo->ram.rloop) >= roff) { + printk("radeonfb: error ron out of range\n"); + return; + } + + newmode.dda_config = (xclk_per_trans_precise | + (useable_precision << 16) | + (rinfo->ram.rloop << 20)); + newmode.dda_on_off = (ron << 16) | roff; + + /* do it! */ + radeon_write_mode (rinfo, &newmode); + + return; +} + + + +static void radeon_write_mode (struct radeonfb_info *rinfo, + struct radeon_regs *mode) +{ + int i; + + /* blank screen */ + OUTREG8(CRTC_EXT_CNTL + 1, 4); + + for (i=0; i<9; i++) + OUTREG(common_regs[i].reg, common_regs[i].val); + + OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl); + OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl, + CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS); + OUTREGP(DAC_CNTL, mode->dac_cntl, DAC_RANGE_CNTL | DAC_BLANKING); + OUTREG(CRTC_H_TOTAL_DISP, mode->crtc_h_total_disp); + OUTREG(CRTC_H_SYNC_STRT_WID, mode->crtc_h_sync_strt_wid); + OUTREG(CRTC_V_TOTAL_DISP, mode->crtc_v_total_disp); + OUTREG(CRTC_V_SYNC_STRT_WID, mode->crtc_v_sync_strt_wid); + OUTREG(CRTC_OFFSET, 0); + OUTREG(CRTC_OFFSET_CNTL, 0); + OUTREG(CRTC_PITCH, mode->crtc_pitch); + + while ((INREG(CLOCK_CNTL_INDEX) & PPLL_DIV_SEL_MASK) != + PPLL_DIV_SEL_MASK) { + OUTREGP(CLOCK_CNTL_INDEX, PPLL_DIV_SEL_MASK, 0xffff); + } + + OUTPLLP(PPLL_CNTL, PPLL_RESET, 0xffff); + + while ((INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK) != + (mode->ppll_ref_div & PPLL_REF_DIV_MASK)) { + OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, ~PPLL_REF_DIV_MASK); + } + + while ((INPLL(PPLL_DIV_3) & PPLL_FB3_DIV_MASK) != + (mode->ppll_div_3 & PPLL_FB3_DIV_MASK)) { + OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_FB3_DIV_MASK); + } + + while ((INPLL(PPLL_DIV_3) & PPLL_POST3_DIV_MASK) != + (mode->ppll_div_3 & PPLL_POST3_DIV_MASK)) { + OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_POST3_DIV_MASK); + } + + OUTPLL(HTOTAL_CNTL, 0); + + OUTPLLP(PPLL_CNTL, 0, ~PPLL_RESET); + + OUTREG(DDA_CONFIG, mode->dda_config); + OUTREG(DDA_ON_OFF, mode->dda_on_off); + + /* unblank screen */ + OUTREG8(CRTC_EXT_CNTL + 1, 0); + + return; +} + + + +/* + * text console acceleration + */ + + +static void fbcon_radeon_bmove(struct display *p, int srcy, int srcx, + int dsty, int dstx, int height, int width) +{ + struct radeonfb_info *rinfo = (struct radeonfb_info *)(p->fb_info); + u32 dp_cntl = DST_LAST_PEL; + + srcx *= fontwidth(p); + srcy *= fontheight(p); + dstx *= fontwidth(p); + dsty *= fontheight(p); + width *= fontwidth(p); + height *= fontheight(p); + + if (srcy < dsty) { + srcy += height - 1; + dsty += height - 1; + } else + dp_cntl |= DST_Y_TOP_TO_BOTTOM; + + if (srcx < dstx) { + srcx += width - 1; + dstx += width - 1; + } else + dp_cntl |= DST_X_LEFT_TO_RIGHT; + + radeon_fifo_wait(6); + OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl | + GMC_BRUSH_NONE | + GMC_SRC_DATATYPE_COLOR | + ROP3_S | + DP_SRC_SOURCE_MEMORY)); + OUTREG(DP_WRITE_MSK, 0xffffffff); + OUTREG(DP_CNTL, dp_cntl); + OUTREG(SRC_Y_X, (srcy << 16) | srcx); + OUTREG(DST_Y_X, (dsty << 16) | dstx); + OUTREG(DST_HEIGHT_WIDTH, (height << 16) | width); +} + + + +static void fbcon_radeon_clear(struct vc_data *conp, struct display *p, + int srcy, int srcx, int height, int width) +{ + struct radeonfb_info *rinfo = (struct radeonfb_info *)(p->fb_info); + u32 clr; + u32 temp; + + clr = attr_bgcol_ec(p, conp); + clr |= (clr << 8); + clr |= (clr << 16); + + srcx *= fontwidth(p); + srcy *= fontheight(p); + width *= fontwidth(p); + height *= fontheight(p); + + radeon_fifo_wait(6); + OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl | + GMC_BRUSH_SOLID_COLOR | + GMC_SRC_DATATYPE_COLOR | + ROP3_P)); + OUTREG(DP_BRUSH_FRGD_CLR, clr); + OUTREG(DP_WRITE_MSK, 0xffffffff); + OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM)); + OUTREG(DST_Y_X, (srcy << 16) | srcx); + OUTREG(DST_WIDTH_HEIGHT, (width << 16) | height); +} + + + + +#ifdef FBCON_HAS_CFB8 +static struct display_switch fbcon_radeon8 = { + setup: fbcon_cfb8_setup, + bmove: fbcon_radeon_bmove, + clear: fbcon_cfb8_clear, + putc: fbcon_cfb8_putc, + putcs: fbcon_cfb8_putcs, + revc: fbcon_cfb8_revc, + clear_margins: fbcon_cfb8_clear_margins, + fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) +}; +#endif