📄 imsttfb.c
字号:
/* * drivers/video/imsttfb.c -- frame buffer device for IMS TwinTurbo * * This file is derived from the powermac console "imstt" driver: * Copyright (C) 1997 Sigurdur Asgeirsson * With additional hacking by Jeffrey Kuskin (jsk@mojave.stanford.edu) * Modified by Danilo Beuche 1998 * Some register values added by Damien Doligez, INRIA Rocquencourt * Various cleanups by Paul Mundt (lethal@chaoticdreams.org) * * This file was written by Ryan Nielsen (ran@krazynet.com) * Most of the frame buffer device stuff was copied from atyfb.c * * 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. */#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/vmalloc.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/fb.h>#include <linux/console.h>#include <linux/selection.h>#include <linux/init.h>#include <linux/pci.h>#include <asm/io.h>#include <asm/uaccess.h>#if defined(CONFIG_PPC)#include <linux/nvram.h>#include <asm/prom.h>#include <asm/pci-bridge.h>#include <video/macmodes.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>#ifndef __powerpc__#define eieio() /* Enforce In-order Execution of I/O */#endif/* TwinTurbo (Cosmo) registers */enum { S1SA = 0, /* 0x00 */ S2SA = 1, /* 0x04 */ SP = 2, /* 0x08 */ DSA = 3, /* 0x0C */ CNT = 4, /* 0x10 */ DP_OCTL = 5, /* 0x14 */ CLR = 6, /* 0x18 */ BI = 8, /* 0x20 */ MBC = 9, /* 0x24 */ BLTCTL = 10, /* 0x28 */ /* Scan Timing Generator Registers */ HES = 12, /* 0x30 */ HEB = 13, /* 0x34 */ HSB = 14, /* 0x38 */ HT = 15, /* 0x3C */ VES = 16, /* 0x40 */ VEB = 17, /* 0x44 */ VSB = 18, /* 0x48 */ VT = 19, /* 0x4C */ HCIV = 20, /* 0x50 */ VCIV = 21, /* 0x54 */ TCDR = 22, /* 0x58 */ VIL = 23, /* 0x5C */ STGCTL = 24, /* 0x60 */ /* Screen Refresh Generator Registers */ SSR = 25, /* 0x64 */ HRIR = 26, /* 0x68 */ SPR = 27, /* 0x6C */ CMR = 28, /* 0x70 */ SRGCTL = 29, /* 0x74 */ /* RAM Refresh Generator Registers */ RRCIV = 30, /* 0x78 */ RRSC = 31, /* 0x7C */ RRCR = 34, /* 0x88 */ /* System Registers */ GIOE = 32, /* 0x80 */ GIO = 33, /* 0x84 */ SCR = 35, /* 0x8C */ SSTATUS = 36, /* 0x90 */ PRC = 37, /* 0x94 */#if 0 /* PCI Registers */ DVID = 0x00000000L, SC = 0x00000004L, CCR = 0x00000008L, OG = 0x0000000CL, BARM = 0x00000010L, BARER = 0x00000030L,#endif};/* IBM 624 RAMDAC Direct Registers */enum { PADDRW = 0x00, PDATA = 0x04, PPMASK = 0x08, PADDRR = 0x0c, PIDXLO = 0x10, PIDXHI = 0x14, PIDXDATA= 0x18, PIDXCTL = 0x1c};/* IBM 624 RAMDAC Indirect Registers */enum { CLKCTL = 0x02, /* (0x01) Miscellaneous Clock Control */ SYNCCTL = 0x03, /* (0x00) Sync Control */ HSYNCPOS = 0x04, /* (0x00) Horizontal Sync Position */ PWRMNGMT = 0x05, /* (0x00) Power Management */ DACOP = 0x06, /* (0x02) DAC Operation */ PALETCTL = 0x07, /* (0x00) Palette Control */ SYSCLKCTL = 0x08, /* (0x01) System Clock Control */ PIXFMT = 0x0a, /* () Pixel Format [bpp >> 3 + 2] */ BPP8 = 0x0b, /* () 8 Bits/Pixel Control */ BPP16 = 0x0c, /* () 16 Bits/Pixel Control [bit 1=1 for 565] */ BPP24 = 0x0d, /* () 24 Bits/Pixel Control */ BPP32 = 0x0e, /* () 32 Bits/Pixel Control */ PIXCTL1 = 0x10, /* (0x05) Pixel PLL Control 1 */ PIXCTL2 = 0x11, /* (0x00) Pixel PLL Control 2 */ SYSCLKN = 0x15, /* () System Clock N (System PLL Reference Divider) */ SYSCLKM = 0x16, /* () System Clock M (System PLL VCO Divider) */ SYSCLKP = 0x17, /* () System Clock P */ SYSCLKC = 0x18, /* () System Clock C */ /* * Dot clock rate is 20MHz * (m + 1) / ((n + 1) * (p ? 2 * p : 1) * c is charge pump bias which depends on the VCO frequency */ PIXM0 = 0x20, /* () Pixel M 0 */ PIXN0 = 0x21, /* () Pixel N 0 */ PIXP0 = 0x22, /* () Pixel P 0 */ PIXC0 = 0x23, /* () Pixel C 0 */ CURSCTL = 0x30, /* (0x00) Cursor Control */ CURSXLO = 0x31, /* () Cursor X position, low 8 bits */ CURSXHI = 0x32, /* () Cursor X position, high 8 bits */ CURSYLO = 0x33, /* () Cursor Y position, low 8 bits */ CURSYHI = 0x34, /* () Cursor Y position, high 8 bits */ CURSHOTX = 0x35, /* () Cursor Hot Spot X */ CURSHOTY = 0x36, /* () Cursor Hot Spot Y */ CURSACCTL = 0x37, /* () Advanced Cursor Control Enable */ CURSACATTR = 0x38, /* () Advanced Cursor Attribute */ CURS1R = 0x40, /* () Cursor 1 Red */ CURS1G = 0x41, /* () Cursor 1 Green */ CURS1B = 0x42, /* () Cursor 1 Blue */ CURS2R = 0x43, /* () Cursor 2 Red */ CURS2G = 0x44, /* () Cursor 2 Green */ CURS2B = 0x45, /* () Cursor 2 Blue */ CURS3R = 0x46, /* () Cursor 3 Red */ CURS3G = 0x47, /* () Cursor 3 Green */ CURS3B = 0x48, /* () Cursor 3 Blue */ BORDR = 0x60, /* () Border Color Red */ BORDG = 0x61, /* () Border Color Green */ BORDB = 0x62, /* () Border Color Blue */ MISCTL1 = 0x70, /* (0x00) Miscellaneous Control 1 */ MISCTL2 = 0x71, /* (0x00) Miscellaneous Control 2 */ MISCTL3 = 0x72, /* (0x00) Miscellaneous Control 3 */ KEYCTL = 0x78 /* (0x00) Key Control/DB Operation */};/* TI TVP 3030 RAMDAC Direct Registers */enum { TVPADDRW = 0x00, /* 0 Palette/Cursor RAM Write Address/Index */ TVPPDATA = 0x04, /* 1 Palette Data RAM Data */ TVPPMASK = 0x08, /* 2 Pixel Read-Mask */ TVPPADRR = 0x0c, /* 3 Palette/Cursor RAM Read Address */ TVPCADRW = 0x10, /* 4 Cursor/Overscan Color Write Address */ TVPCDATA = 0x14, /* 5 Cursor/Overscan Color Data */ /* 6 reserved */ TVPCADRR = 0x1c, /* 7 Cursor/Overscan Color Read Address */ /* 8 reserved */ TVPDCCTL = 0x24, /* 9 Direct Cursor Control */ TVPIDATA = 0x28, /* 10 Index Data */ TVPCRDAT = 0x2c, /* 11 Cursor RAM Data */ TVPCXPOL = 0x30, /* 12 Cursor-Position X LSB */ TVPCXPOH = 0x34, /* 13 Cursor-Position X MSB */ TVPCYPOL = 0x38, /* 14 Cursor-Position Y LSB */ TVPCYPOH = 0x3c, /* 15 Cursor-Position Y MSB */};/* TI TVP 3030 RAMDAC Indirect Registers */enum { TVPIRREV = 0x01, /* Silicon Revision [RO] */ TVPIRICC = 0x06, /* Indirect Cursor Control (0x00) */ TVPIRBRC = 0x07, /* Byte Router Control (0xe4) */ TVPIRLAC = 0x0f, /* Latch Control (0x06) */ TVPIRTCC = 0x18, /* True Color Control (0x80) */ TVPIRMXC = 0x19, /* Multiplex Control (0x98) */ TVPIRCLS = 0x1a, /* Clock Selection (0x07) */ TVPIRPPG = 0x1c, /* Palette Page (0x00) */ TVPIRGEC = 0x1d, /* General Control (0x00) */ TVPIRMIC = 0x1e, /* Miscellaneous Control (0x00) */ TVPIRPLA = 0x2c, /* PLL Address */ TVPIRPPD = 0x2d, /* Pixel Clock PLL Data */ TVPIRMPD = 0x2e, /* Memory Clock PLL Data */ TVPIRLPD = 0x2f, /* Loop Clock PLL Data */ TVPIRCKL = 0x30, /* Color-Key Overlay Low */ TVPIRCKH = 0x31, /* Color-Key Overlay High */ TVPIRCRL = 0x32, /* Color-Key Red Low */ TVPIRCRH = 0x33, /* Color-Key Red High */ TVPIRCGL = 0x34, /* Color-Key Green Low */ TVPIRCGH = 0x35, /* Color-Key Green High */ TVPIRCBL = 0x36, /* Color-Key Blue Low */ TVPIRCBH = 0x37, /* Color-Key Blue High */ TVPIRCKC = 0x38, /* Color-Key Control (0x00) */ TVPIRMLC = 0x39, /* MCLK/Loop Clock Control (0x18) */ TVPIRSEN = 0x3a, /* Sense Test (0x00) */ TVPIRTMD = 0x3b, /* Test Mode Data */ TVPIRRML = 0x3c, /* CRC Remainder LSB [RO] */ TVPIRRMM = 0x3d, /* CRC Remainder MSB [RO] */ TVPIRRMS = 0x3e, /* CRC Bit Select [WO] */ TVPIRDID = 0x3f, /* Device ID [RO] (0x30) */ TVPIRRES = 0xff /* Software Reset [WO] */};struct initvalues { __u8 addr, value;};static struct initvalues ibm_initregs[] __initdata = { { CLKCTL, 0x21 }, { SYNCCTL, 0x00 }, { HSYNCPOS, 0x00 }, { PWRMNGMT, 0x00 }, { DACOP, 0x02 }, { PALETCTL, 0x00 }, { SYSCLKCTL, 0x01 }, /* * Note that colors in X are correct only if all video data is * passed through the palette in the DAC. That is, "indirect * color" must be configured. This is the case for the IBM DAC * used in the 2MB and 4MB cards, at least. */ { BPP8, 0x00 }, { BPP16, 0x01 }, { BPP24, 0x00 }, { BPP32, 0x00 }, { PIXCTL1, 0x05 }, { PIXCTL2, 0x00 }, { SYSCLKN, 0x08 }, { SYSCLKM, 0x4f }, { SYSCLKP, 0x00 }, { SYSCLKC, 0x00 }, { CURSCTL, 0x00 }, { CURSACCTL, 0x01 }, { CURSACATTR, 0xa8 }, { CURS1R, 0xff }, { CURS1G, 0xff }, { CURS1B, 0xff }, { CURS2R, 0xff }, { CURS2G, 0xff }, { CURS2B, 0xff }, { CURS3R, 0xff }, { CURS3G, 0xff }, { CURS3B, 0xff }, { BORDR, 0xff }, { BORDG, 0xff }, { BORDB, 0xff }, { MISCTL1, 0x01 }, { MISCTL2, 0x45 }, { MISCTL3, 0x00 }, { KEYCTL, 0x00 }};static struct initvalues tvp_initregs[] __initdata = { { TVPIRICC, 0x00 }, { TVPIRBRC, 0xe4 }, { TVPIRLAC, 0x06 }, { TVPIRTCC, 0x80 }, { TVPIRMXC, 0x4d }, { TVPIRCLS, 0x05 }, { TVPIRPPG, 0x00 }, { TVPIRGEC, 0x00 }, { TVPIRMIC, 0x08 }, { TVPIRCKL, 0xff }, { TVPIRCKH, 0xff }, { TVPIRCRL, 0xff }, { TVPIRCRH, 0xff }, { TVPIRCGL, 0xff }, { TVPIRCGH, 0xff }, { TVPIRCBL, 0xff }, { TVPIRCBH, 0xff }, { TVPIRCKC, 0x00 }, { TVPIRPLA, 0x00 }, { TVPIRPPD, 0xc0 }, { TVPIRPPD, 0xd5 }, { TVPIRPPD, 0xea }, { TVPIRPLA, 0x00 }, { TVPIRMPD, 0xb9 }, { TVPIRMPD, 0x3a }, { TVPIRMPD, 0xb1 }, { TVPIRPLA, 0x00 }, { TVPIRLPD, 0xc1 }, { TVPIRLPD, 0x3d }, { TVPIRLPD, 0xf3 },};struct imstt_regvals { __u32 pitch; __u16 hes, heb, hsb, ht, ves, veb, vsb, vt, vil; __u8 pclk_m, pclk_n, pclk_p; /* Values of the tvp which change depending on colormode x resolution */ __u8 mlc[3]; /* Memory Loop Config 0x39 */ __u8 lckl_p[3]; /* P value of LCKL PLL */};struct imstt_cursor { struct timer_list timer; int enable; int on; int vbl_cnt; int blink_rate; __u16 x, y, width, height;};struct fb_info_imstt { struct fb_info info; struct fb_fix_screeninfo fix; struct display disp; struct display_switch dispsw; union {#ifdef FBCON_HAS_CFB16 __u16 cfb16[16];#endif#ifdef FBCON_HAS_CFB24 __u32 cfb24[16];#endif#ifdef FBCON_HAS_CFB32 __u32 cfb32[16];#endif } fbcon_cmap; struct { __u8 red, green, blue; } palette[256]; struct imstt_regvals init; struct imstt_cursor cursor; unsigned long frame_buffer_phys; unsigned long board_size; __u8 *frame_buffer; unsigned long dc_regs_phys; __u32 *dc_regs; unsigned long cmap_regs_phys; __u8 *cmap_regs; __u32 total_vram; __u32 ramdac;};enum { IBM = 0, TVP = 1};#define INIT_BPP 8#define INIT_XRES 640#define INIT_YRES 480#define CURSOR_BLINK_RATE 20#define CURSOR_DRAW_DELAY 2static int currcon = 0;static int inverse = 0;static char fontname[40] __initdata = { 0 };static char curblink __initdata = 1;static char noaccel __initdata = 0;#if defined(CONFIG_PPC)static signed char init_vmode __initdata = VMODE_NVRAM;static signed char init_cmode __initdata = CMODE_NVRAM;#endifstatic struct imstt_regvals tvp_reg_init_2 = { 512, 0x0002, 0x0006, 0x0026, 0x0028, 0x0003, 0x0016, 0x0196, 0x0197, 0x0196, 0xec, 0x2a, 0xf3, { 0x3c, 0x3b, 0x39 }, { 0xf3, 0xf3, 0xf3 }};static struct imstt_regvals tvp_reg_init_6 = { 640, 0x0004, 0x0009, 0x0031, 0x0036, 0x0003, 0x002a, 0x020a, 0x020d, 0x020a, 0xef, 0x2e, 0xb2, { 0x39, 0x39, 0x38 }, { 0xf3, 0xf3, 0xf3 }};static struct imstt_regvals tvp_reg_init_12 = { 800, 0x0005, 0x000e, 0x0040, 0x0042, 0x0003, 0x018, 0x270, 0x271, 0x270, 0xf6, 0x2e, 0xf2, { 0x3a, 0x39, 0x38 }, { 0xf3, 0xf3, 0xf3 }};static struct imstt_regvals tvp_reg_init_13 = { 832, 0x0004, 0x0011, 0x0045, 0x0048, 0x0003, 0x002a, 0x029a, 0x029b, 0x0000, 0xfe, 0x3e, 0xf1, { 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }};static struct imstt_regvals tvp_reg_init_17 = { 1024, 0x0006, 0x0210, 0x0250, 0x0053, 0x1003, 0x0021, 0x0321, 0x0324, 0x0000, 0xfc, 0x3a, 0xf1, { 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }};static struct imstt_regvals tvp_reg_init_18 = { 1152, 0x0009, 0x0011, 0x059, 0x5b, 0x0003, 0x0031, 0x0397, 0x039a, 0x0000, 0xfd, 0x3a, 0xf1, { 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }};static struct imstt_regvals tvp_reg_init_19 = { 1280, 0x0009, 0x0016, 0x0066, 0x0069, 0x0003, 0x0027, 0x03e7, 0x03e8, 0x03e7, 0xf7, 0x36, 0xf0, { 0x38, 0x38, 0x38 }, { 0xf3, 0xf2, 0xf1 }};static struct imstt_regvals tvp_reg_init_20 = { 1280, 0x0009, 0x0018, 0x0068, 0x006a, 0x0003, 0x0029, 0x0429, 0x042a, 0x0000, 0xf0, 0x2d, 0xf0, { 0x38, 0x38, 0x38 }, { 0xf3, 0xf2, 0xf1 }};/* * PCI driver prototypes */static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);static void imsttfb_remove(struct pci_dev *pdev);static __u32getclkMHz (struct fb_info_imstt *p){ __u32 clk_m, clk_n, clk_p; clk_m = p->init.pclk_m; clk_n = p->init.pclk_n; clk_p = p->init.pclk_p; return 20 * (clk_m + 1) / ((clk_n + 1) * (clk_p ? 2 * clk_p : 1));}static voidsetclkMHz (struct fb_info_imstt *p, __u32 MHz){ __u32 clk_m, clk_n, clk_p, x, stage, spilled; clk_m = clk_n = clk_p = 0; stage = spilled = 0; for (;;) { switch (stage) { case 0: clk_m++; break; case 1: clk_n++; break; } x = 20 * (clk_m + 1) / ((clk_n + 1) * (clk_p ? 2 * clk_p : 1)); if (x == MHz) break; if (x > MHz) { spilled = 1; stage = 1; } else if (spilled && x < MHz) { stage = 0; } } p->init.pclk_m = clk_m; p->init.pclk_n = clk_n; p->init.pclk_p = clk_p;}static struct imstt_regvals *compute_imstt_regvals_ibm (struct fb_info_imstt *p, int xres, int yres){ struct imstt_regvals *init = &p->init; __u32 MHz, hes, heb, veb, htp, vtp; switch (xres) { case 640: hes = 0x0008; heb = 0x0012; veb = 0x002a; htp = 10; vtp = 2; MHz = 30 /* .25 */ ; break; case 832: hes = 0x0005; heb = 0x0020; veb = 0x0028; htp = 8; vtp = 3; MHz = 57 /* .27_ */ ; break; case 1024: hes = 0x000a; heb = 0x001c; veb = 0x0020; htp = 8; vtp = 3; MHz = 80;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -