📄 stifb.c
字号:
/* * linux/drivers/video/sti/stifb.c - * Frame buffer driver for HP workstations with STI (standard text interface) * video firmware. * * Copyright (C) 2001 Helge Deller <deller@gmx.de> * Portions Copyright (C) 2001 Thomas Bogendoerfer <tsbogend@alpha.franken.de> * * Based on: * - linux/drivers/video/artistfb.c -- Artist frame buffer driver * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> * - based on skeletonfb, which was * Created 28 Dec 1997 by Geert Uytterhoeven * - HP Xhp cfb-based X11 window driver for XFree86 * (c)Copyright 1992 Hewlett-Packard Co. * * * The following graphics display devices (NGLE family) are supported by this driver: * * HPA4070A known as "HCRX", a 1280x1024 color device with 8 planes * HPA4071A known as "HCRX24", a 1280x1024 color device with 24 planes, * optionally available with a hardware accelerator as HPA4071A_Z * HPA1659A known as "CRX", a 1280x1024 color device with 8 planes * HPA1439A known as "CRX24", a 1280x1024 color device with 24 planes, * optionally available with a hardware accelerator. * HPA1924A known as "GRX", a 1280x1024 grayscale device with 8 planes * HPA2269A known as "Dual CRX", a 1280x1024 color device with 8 planes, * implements support for two displays on a single graphics card. * HP710C internal graphics support optionally available on the HP9000s710 SPU, * supports 1280x1024 color displays with 8 planes. * HP710G same as HP710C, 1280x1024 grayscale only * HP710L same as HP710C, 1024x768 color only * HP712 internal graphics support on HP9000s712 SPU, supports 640x480, * 1024x768 or 1280x1024 color displays on 8 planes (Artist) * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive * for more details. *//* TODO: * - Artist gfx is the only supported chip atm, * - remove the static fb_info to support multiple cards * - remove the completely untested 1bpp mode * - add support for h/w acceleration * - add hardware cursor * - *//* on supported graphic devices you may: * #define FALLBACK_TO_1BPP to fall back to 1 bpp, or * #undef FALLBACK_TO_1BPP to reject support for unsupported cards */#undef FALLBACK_TO_1BPP#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/init.h>#include <linux/selection.h>#include <linux/ioport.h>#include <linux/pci.h>#include <video/fbcon.h>#include <video/fbcon-cfb8.h>#include <video/fbcon-cfb32.h>#include <asm/grfioctl.h> /* for HP-UX compatibility */#include "sticore.h"extern struct display_switch fbcon_sti; /* fbcon-sti.c */#ifdef __LP64__/* return virtual address */#define REGION_BASE(fb_info, index) \ (fb_info->sti->glob_cfg->region_ptrs[index] | 0xffffffff00000000)#else/* return virtual address */#define REGION_BASE(fb_info, index) \ fb_info->sti->glob_cfg->region_ptrs[index]#endif#define NGLEDEVDEPROM_CRT_REGION 1typedef struct { __s32 video_config_reg; __s32 misc_video_start; __s32 horiz_timing_fmt; __s32 serr_timing_fmt; __s32 vert_timing_fmt; __s32 horiz_state; __s32 vert_state; __s32 vtg_state_elements; __s32 pipeline_delay; __s32 misc_video_end;} video_setup_t;typedef struct { __s16 sizeof_ngle_data; __s16 x_size_visible; /* visible screen dim in pixels */ __s16 y_size_visible; __s16 pad2[15]; __s16 cursor_pipeline_delay; __s16 video_interleaves; __s32 pad3[11];} ngle_rom_t;struct stifb_info { struct fb_info info; struct fb_var_screeninfo var; struct fb_fix_screeninfo fix; struct display disp; struct sti_struct *sti; unsigned int id, real_id; int currcon; int cmap_reload:1; int deviceSpecificConfig; ngle_rom_t ngle_rom; struct { u8 red, green, blue; } palette[256];#ifdef FBCON_HAS_CFB32 union { u32 cfb32[16]; } fbcon_cmap;#endif };static int stifb_force_bpp[MAX_STI_ROMS];/* ------------------- chipset specific functions -------------------------- *//* offsets to graphic-chip internal registers */#define REG_1 0x000118#define REG_2 0x000480#define REG_3 0x0004a0#define REG_4 0x000600#define REG_6 0x000800#define REG_8 0x000820#define REG_9 0x000a04#define REG_10 0x018000#define REG_11 0x018004#define REG_12 0x01800c#define REG_13 0x018018#define REG_14 0x01801c#define REG_15 0x200000#define REG_15b0 0x200000#define REG_16b1 0x200005#define REG_16b3 0x200007#define REG_21 0x200218#define REG_22 0x0005a0#define REG_23 0x0005c0#define REG_26 0x200118#define REG_27 0x200308#define REG_32 0x21003c#define REG_33 0x210040#define REG_34 0x200008#define REG_35 0x018010#define REG_38 0x210020#define REG_39 0x210120#define REG_40 0x210130#define REG_42 0x210028#define REG_43 0x21002c#define REG_44 0x210030#define REG_45 0x210034#define READ_BYTE(fb,reg) __raw_readb((fb)->fix.mmio_start + (reg))#define READ_WORD(fb,reg) __raw_readl((fb)->fix.mmio_start + (reg))#define WRITE_BYTE(value,fb,reg) __raw_writeb((value),(fb)->fix.mmio_start + (reg))#define WRITE_WORD(value,fb,reg) __raw_writel((value),(fb)->fix.mmio_start + (reg))#define ENABLE 1 /* for enabling/disabling screen */ #define DISABLE 0#define NGLE_LOCK(fb_info) do { } while (0) #define NGLE_UNLOCK(fb_info) do { } while (0)static voidSETUP_HW(struct stifb_info *fb){ char stat; do { stat = READ_BYTE(fb, REG_15b0); if (!stat) stat = READ_BYTE(fb, REG_15b0); } while (stat);}static voidSETUP_FB(struct stifb_info *fb){ unsigned int reg10_value = 0; SETUP_HW(fb); switch (fb->id) { case CRT_ID_VISUALIZE_EG: case S9000_ID_ARTIST: case S9000_ID_A1659A: reg10_value = 0x13601000; break; case S9000_ID_A1439A: if (fb->var.bits_per_pixel == 32) reg10_value = 0xBBA0A000; else reg10_value = 0x13601000; break; case S9000_ID_HCRX: if (fb->var.bits_per_pixel == 32) reg10_value = 0xBBA0A000; else reg10_value = 0x13602000; break; case S9000_ID_TIMBER: case CRX24_OVERLAY_PLANES: reg10_value = 0x13602000; break; } if (reg10_value) WRITE_WORD(reg10_value, fb, REG_10); WRITE_WORD(0x83000300, fb, REG_14); SETUP_HW(fb); WRITE_BYTE(1, fb, REG_16b1);}static voidSTART_IMAGE_COLORMAP_ACCESS(struct stifb_info *fb){ SETUP_HW(fb); WRITE_WORD(0xBBE0F000, fb, REG_10); WRITE_WORD(0x03000300, fb, REG_14); WRITE_WORD(~0, fb, REG_13);}static voidWRITE_IMAGE_COLOR(struct stifb_info *fb, int index, int color) { SETUP_HW(fb); WRITE_WORD(((0x100+index)<<2), fb, REG_3); WRITE_WORD(color, fb, REG_4);}static voidFINISH_IMAGE_COLORMAP_ACCESS(struct stifb_info *fb) { WRITE_WORD(0x400, fb, REG_2); if (fb->var.bits_per_pixel == 32) { WRITE_WORD(0x83000100, fb, REG_1); } else { if (fb->id == S9000_ID_ARTIST || fb->id == CRT_ID_VISUALIZE_EG) WRITE_WORD(0x80000100, fb, REG_26); else WRITE_WORD(0x80000100, fb, REG_1); } SETUP_FB(fb);}static voidSETUP_RAMDAC(struct stifb_info *fb) { SETUP_HW(fb); WRITE_WORD(0x04000000, fb, 0x1020); WRITE_WORD(0xff000000, fb, 0x1028);}static void CRX24_SETUP_RAMDAC(struct stifb_info *fb) { SETUP_HW(fb); WRITE_WORD(0x04000000, fb, 0x1000); WRITE_WORD(0x02000000, fb, 0x1004); WRITE_WORD(0xff000000, fb, 0x1008); WRITE_WORD(0x05000000, fb, 0x1000); WRITE_WORD(0x02000000, fb, 0x1004); WRITE_WORD(0x03000000, fb, 0x1008);}#if 0static void HCRX_SETUP_RAMDAC(struct stifb_info *fb){ WRITE_WORD(0xffffffff, fb, REG_32);}#endifstatic void CRX24_SET_OVLY_MASK(struct stifb_info *fb){ SETUP_HW(fb); WRITE_WORD(0x13a02000, fb, REG_11); WRITE_WORD(0x03000300, fb, REG_14); WRITE_WORD(0x000017f0, fb, REG_3); WRITE_WORD(0xffffffff, fb, REG_13); WRITE_WORD(0xffffffff, fb, REG_22); WRITE_WORD(0x00000000, fb, REG_23);}static voidENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable){ unsigned int value = enable ? 0x43000000 : 0x03000000; SETUP_HW(fb); WRITE_WORD(0x06000000, fb, 0x1030); WRITE_WORD(value, fb, 0x1038);}static void CRX24_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable){ unsigned int value = enable ? 0x10000000 : 0x30000000; SETUP_HW(fb); WRITE_WORD(0x01000000, fb, 0x1000); WRITE_WORD(0x02000000, fb, 0x1004); WRITE_WORD(value, fb, 0x1008);}static voidARTIST_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable) { u32 DregsMiscVideo = REG_21; u32 DregsMiscCtl = REG_27; SETUP_HW(fb); if (enable) { WRITE_WORD(READ_WORD(fb, DregsMiscVideo) | 0x0A000000, fb, DregsMiscVideo); WRITE_WORD(READ_WORD(fb, DregsMiscCtl) | 0x00800000, fb, DregsMiscCtl); } else { WRITE_WORD(READ_WORD(fb, DregsMiscVideo) & ~0x0A000000, fb, DregsMiscVideo); WRITE_WORD(READ_WORD(fb, DregsMiscCtl) & ~0x00800000, fb, DregsMiscCtl); }}#define GET_ROMTABLE_INDEX(fb) \ (READ_BYTE(fb, REG_16b3) - 1)#define HYPER_CONFIG_PLANES_24 0x00000100 #define IS_24_DEVICE(fb) \ (fb->deviceSpecificConfig & HYPER_CONFIG_PLANES_24)#define IS_888_DEVICE(fb) \ (!(IS_24_DEVICE(fb)))#define GET_FIFO_SLOTS(fb, cnt, numslots) \{ while (cnt < numslots) \ cnt = READ_WORD(fb, REG_34); \ cnt -= numslots; \}#define IndexedDcd 0 /* Pixel data is indexed (pseudo) color */#define Otc04 2 /* Pixels in each longword transfer (4) */#define Otc32 5 /* Pixels in each longword transfer (32) */#define Ots08 3 /* Each pixel is size (8)d transfer (1) */#define OtsIndirect 6 /* Each bit goes through FG/BG color(8) */#define AddrLong 5 /* FB address is Long aligned (pixel) */#define BINovly 0x2 /* 8 bit overlay */#define BINapp0I 0x0 /* Application Buffer 0, Indexed */#define BINapp1I 0x1 /* Application Buffer 1, Indexed */#define BINapp0F8 0xa /* Application Buffer 0, Fractional 8-8-8 */#define BINattr 0xd /* Attribute Bitmap */#define RopSrc 0x3#define BitmapExtent08 3 /* Each write hits ( 8) bits in depth */#define BitmapExtent32 5 /* Each write hits (32) bits in depth */#define DataDynamic 0 /* Data register reloaded by direct access */#define MaskDynamic 1 /* Mask register reloaded by direct access */#define MaskOtc 0 /* Mask contains Object Count valid bits */#define MaskAddrOffset(offset) (offset)#define StaticReg(en) (en)#define BGx(en) (en)#define FGx(en) (en)#define BAJustPoint(offset) (offset)#define BAIndexBase(base) (base)#define BA(F,C,S,A,J,B,I) \ (((F)<<31)|((C)<<27)|((S)<<24)|((A)<<21)|((J)<<16)|((B)<<12)|(I))#define IBOvals(R,M,X,S,D,L,B,F) \ (((R)<<8)|((M)<<16)|((X)<<24)|((S)<<29)|((D)<<28)|((L)<<31)|((B)<<1)|(F))#define NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb, val) \ WRITE_WORD(val, fb, REG_14)#define NGLE_QUICK_SET_DST_BM_ACCESS(fb, val) \ WRITE_WORD(val, fb, REG_11)#define NGLE_QUICK_SET_CTL_PLN_REG(fb, val) \ WRITE_WORD(val, fb, REG_12)#define NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, plnmsk32) \ WRITE_WORD(plnmsk32, fb, REG_13)#define NGLE_REALLY_SET_IMAGE_FG_COLOR(fb, fg32) \ WRITE_WORD(fg32, fb, REG_35)#define NGLE_SET_TRANSFERDATA(fb, val) \ WRITE_WORD(val, fb, REG_8)#define NGLE_SET_DSTXY(fb, val) \ WRITE_WORD(val, fb, REG_6)#define NGLE_LONG_FB_ADDRESS(fbaddrbase, x, y) ( \ (u32) (fbaddrbase) + \ ( (unsigned int) ( (y) << 13 ) | \ (unsigned int) ( (x) << 2 ) ) \ )#define NGLE_BINC_SET_DSTADDR(fb, addr) \ WRITE_WORD(addr, fb, REG_3)#define NGLE_BINC_SET_SRCADDR(fb, addr) \ WRITE_WORD(addr, fb, REG_2)#define NGLE_BINC_SET_DSTMASK(fb, mask) \ WRITE_WORD(mask, fb, REG_22)#define NGLE_BINC_WRITE32(fb, data32) \ WRITE_WORD(data32, fb, REG_23)#define START_COLORMAPLOAD(fb, cmapBltCtlData32) \ WRITE_WORD((cmapBltCtlData32), fb, REG_38)#define SET_LENXY_START_RECFILL(fb, lenxy) \ WRITE_WORD(lenxy, fb, REG_9)static voidHYPER_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable){ u32 DregsHypMiscVideo = REG_33; unsigned int value; SETUP_HW(fb); value = READ_WORD(fb, DregsHypMiscVideo); if (enable) value |= 0x0A000000; else value &= ~0x0A000000; WRITE_WORD(value, fb, DregsHypMiscVideo);}/* BufferNumbers used by SETUP_ATTR_ACCESS() */#define BUFF0_CMAP0 0x00001e02#define BUFF1_CMAP0 0x02001e02#define BUFF1_CMAP3 0x0c001e02#define ARTIST_CMAP0 0x00000102#define HYPER_CMAP8 0x00000100#define HYPER_CMAP24 0x00000800static voidSETUP_ATTR_ACCESS(struct stifb_info *fb, unsigned BufferNumber){ SETUP_HW(fb); WRITE_WORD(0x2EA0D000, fb, REG_11); WRITE_WORD(0x23000302, fb, REG_14); WRITE_WORD(BufferNumber, fb, REG_12); WRITE_WORD(0xffffffff, fb, REG_8);}static voidSET_ATTR_SIZE(struct stifb_info *fb, int width, int height) { WRITE_WORD(0x00000000, fb, REG_6); WRITE_WORD((width<<16) | height, fb, REG_9); WRITE_WORD(0x05000000, fb, REG_6); WRITE_WORD(0x00040001, fb, REG_9);}static voidFINISH_ATTR_ACCESS(struct stifb_info *fb) { SETUP_HW(fb); WRITE_WORD(0x00000000, fb, REG_12);}static voidelkSetupPlanes(struct stifb_info *fb){ SETUP_RAMDAC(fb); SETUP_FB(fb);}static void ngleSetupAttrPlanes(struct stifb_info *fb, int BufferNumber){ SETUP_ATTR_ACCESS(fb, BufferNumber); SET_ATTR_SIZE(fb, fb->var.xres, fb->var.yres); FINISH_ATTR_ACCESS(fb); SETUP_FB(fb);}static voidrattlerSetupPlanes(struct stifb_info *fb){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -