📄 cyberfb.c
字号:
volatile unsigned char *addr; static unsigned char cvportbits = 0; /* Mirror port bits here */ DPRINTK("ENTER\n"); addr = base + 0x40001; if (bits & 0x8000) { cvportbits |= bits & 0xff; /* Set bits */ DPRINTK("Set bits: %04x\n", bits); } else { bits = bits & 0xff; bits = (~bits) & 0xff; cvportbits &= bits; /* Clear bits */ DPRINTK("Clear bits: %04x\n", bits); } *addr = cvportbits; DPRINTK("EXIT\n");}/* * Monitor switch on CyberVision board * * toggle: * 0 = CyberVision Signal * 1 = Amiga Signal * board = board addr * */inline void cvscreen (int toggle, volatile unsigned char *board){ DPRINTK("ENTER\n"); if (toggle == 1) { DPRINTK("Show Amiga video\n"); cv64_write_port (0x10, board); } else { DPRINTK("Show CyberVision video\n"); cv64_write_port (0x8010, board); } DPRINTK("EXIT\n");}/* Control screen display *//* toggle: 0 = on, 1 = off *//* board = registerbase */inline void gfx_on_off(int toggle, volatile unsigned char *regs){ int r; DPRINTK("ENTER\n"); toggle &= 0x1; toggle = toggle << 5; DPRINTK("Turn display %s\n", (toggle ? "off" : "on")); r = (int) RSeq(regs, SEQ_ID_CLOCKING_MODE); r &= 0xdf; /* Set bit 5 to 0 */ WSeq (regs, SEQ_ID_CLOCKING_MODE, r | toggle); DPRINTK("EXIT\n");}/* * Computes M, N, and R values from * given input frequency. It uses a table of * precomputed values, to keep CPU time low. * * The return value consist of: * lower byte: Bits 4-0: N Divider Value * Bits 5-6: R Value for e.g. SR10 or SR12 * higher byte: Bits 0-6: M divider value for e.g. SR11 or SR13 */static unsigned short cv64_compute_clock(unsigned long freq){ static unsigned char *mnr, *save; /* M, N + R vals */ unsigned long work_freq, r; unsigned short erg; long diff, d2; DPRINTK("ENTER\n"); if (freq < 12500000 || freq > MAXPIXELCLOCK) { printk("CV64 driver: Illegal clock frequency %ld, using 25MHz\n", freq); freq = 25000000; } DPRINTK("Freq = %ld\n", freq); mnr = clocks; /* there the vals are stored */ d2 = 0x7fffffff; while (*mnr) { /* mnr vals are 0-terminated */ work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2); r = (mnr[1] >> 5) & 0x03; if (r != 0) { work_freq = work_freq >> r; /* r is the freq divider */ } work_freq *= 0x3E8; /* 2nd part of OSC */ diff = abs(freq - work_freq); if (d2 >= diff) { d2 = diff; /* In save are the vals for minimal diff */ save = mnr; } mnr += 2; } erg = *((unsigned short *)save); DPRINTK("EXIT\n"); return (erg);}static int cv_has_4mb (volatile unsigned char *fb){ volatile unsigned long *tr, *tw; DPRINTK("ENTER\n"); /* write patterns in memory and test if they can be read */ tw = (volatile unsigned long *) fb; tr = (volatile unsigned long *) (fb + 0x02000000); *tw = 0x87654321; if (*tr != 0x87654321) { DPRINTK("EXIT - <4MB\n"); return (0); } /* upper memory region */ tw = (volatile unsigned long *) (fb + 0x00200000); tr = (volatile unsigned long *) (fb + 0x02200000); *tw = 0x87654321; if (*tr != 0x87654321) { DPRINTK("EXIT - <4MB\n"); return (0); } *tw = 0xAAAAAAAA; if (*tr != 0xAAAAAAAA) { DPRINTK("EXIT - <4MB\n"); return (0); } *tw = 0x55555555; if (*tr != 0x55555555) { DPRINTK("EXIT - <4MB\n"); return (0); } DPRINTK("EXIT\n"); return (1);}static void cv64_board_init (void){ volatile unsigned char *regs = CyberRegs; int i; unsigned int clockpar; unsigned char test; DPRINTK("ENTER\n"); /* * Special CyberVision 64 board operations */ /* Reset board */ for (i = 0; i < 6; i++) { cv64_write_port (0xff, CyberBase); } /* Return to operational mode */ cv64_write_port (0x8004, CyberBase); /* * Generic (?) S3 chip wakeup */ /* Disable I/O & memory decoders, video in setup mode */ wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x10); /* Video responds to cmds, addrs & data */ wb_64 (regs, SREG_OPTION_SELECT, 0x1); /* Enable I/O & memory decoders, video in operational mode */ wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x8); /* VGA color emulation, enable cpu access to display mem */ wb_64 (regs, GREG_MISC_OUTPUT_W, 0x03); /* Unlock S3 VGA regs */ WCrt (regs, CRT_ID_REGISTER_LOCK_1, 0x48); /* Unlock system control & extension registers */ WCrt (regs, CRT_ID_REGISTER_LOCK_2, 0xA5);/* GRF - Enable interrupts */ /* Enable enhanced regs access, Ready cntl 0 wait states */ test = RCrt (regs, CRT_ID_SYSTEM_CONFIG); test = test | 0x01; /* enable enhanced register access */ test = test & 0xEF; /* clear bit 4, 0 wait state */ WCrt (regs, CRT_ID_SYSTEM_CONFIG, test); /* * bit 0=1: Enable enhaced mode functions * bit 2=0: Enhanced mode 8+ bits/pixel * bit 4=1: Enable linear addressing * bit 5=1: Enable MMIO */ wb_64 (regs, ECR_ADV_FUNC_CNTL, 0x31); /* * bit 0=1: Color emulation * bit 1=1: Enable CPU access to display memory * bit 5=1: Select high 64K memory page *//* GRF - 0xE3 */ wb_64 (regs, GREG_MISC_OUTPUT_W, 0x23); /* Cpu base addr */ WCrt (regs, CRT_ID_EXT_SYS_CNTL_4, 0x0); /* Reset. This does nothing on Trio, but standard VGA practice */ /* WSeq (CyberRegs, SEQ_ID_RESET, 0x03); */ /* Character clocks 8 dots wide */ WSeq (regs, SEQ_ID_CLOCKING_MODE, 0x01); /* Enable cpu write to all color planes */ WSeq (regs, SEQ_ID_MAP_MASK, 0x0F); /* Font table in 1st 8k of plane 2, font A=B disables swtich */ WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x0); /* Allow mem access to 256kb */ WSeq (regs, SEQ_ID_MEMORY_MODE, 0x2); /* Unlock S3 extensions to VGA Sequencer regs */ WSeq (regs, SEQ_ID_UNLOCK_EXT, 0x6); /* Enable 4MB fast page mode */ test = RSeq (regs, SEQ_ID_BUS_REQ_CNTL); test = test | 1 << 6; WSeq (regs, SEQ_ID_BUS_REQ_CNTL, test); /* Faster LUT write: 1 DCLK LUT write cycle, RAMDAC clk doubled */ WSeq (regs, SEQ_ID_RAMDAC_CNTL, 0xC0); /* Clear immediate clock load bit */ test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2); test = test & 0xDF; /* If > 55MHz, enable 2 cycle memory write */ if (cv64_memclk >= 55000000) { test |= 0x80; } WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test); /* Set MCLK value */ clockpar = cv64_compute_clock (cv64_memclk); test = (clockpar & 0xFF00) >> 8; WSeq (regs, SEQ_ID_MCLK_HI, test); test = clockpar & 0xFF; WSeq (regs, SEQ_ID_MCLK_LO, test); /* Chip rev specific: Not in my Trio manual!!! */ if (RCrt (regs, CRT_ID_REVISION) == 0x10) WSeq (regs, SEQ_ID_MORE_MAGIC, test); /* We now load an 25 MHz, 31kHz, 640x480 standard VGA Mode. */ /* Set DCLK value */ WSeq (regs, SEQ_ID_DCLK_HI, 0x13); WSeq (regs, SEQ_ID_DCLK_LO, 0x41); /* Load DCLK (and MCLK?) immediately */ test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2); test = test | 0x22; WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test); /* Enable loading of DCLK */ test = rb_64(regs, GREG_MISC_OUTPUT_R); test = test | 0x0C; wb_64 (regs, GREG_MISC_OUTPUT_W, test); /* Turn off immediate xCLK load */ WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, 0x2); /* Horizontal character clock counts */ /* 8 LSB of 9 bits = total line - 5 */ WCrt (regs, CRT_ID_HOR_TOTAL, 0x5F); /* Active display line */ WCrt (regs, CRT_ID_HOR_DISP_ENA_END, 0x4F); /* Blank assertion start */ WCrt (regs, CRT_ID_START_HOR_BLANK, 0x50); /* Blank assertion end */ WCrt (regs, CRT_ID_END_HOR_BLANK, 0x82); /* HSYNC assertion start */ WCrt (regs, CRT_ID_START_HOR_RETR, 0x54); /* HSYNC assertion end */ WCrt (regs, CRT_ID_END_HOR_RETR, 0x80); WCrt (regs, CRT_ID_VER_TOTAL, 0xBF); WCrt (regs, CRT_ID_OVERFLOW, 0x1F); WCrt (regs, CRT_ID_PRESET_ROW_SCAN, 0x0); WCrt (regs, CRT_ID_MAX_SCAN_LINE, 0x40); WCrt (regs, CRT_ID_CURSOR_START, 0x00); WCrt (regs, CRT_ID_CURSOR_END, 0x00); WCrt (regs, CRT_ID_START_ADDR_HIGH, 0x00); WCrt (regs, CRT_ID_START_ADDR_LOW, 0x00); WCrt (regs, CRT_ID_CURSOR_LOC_HIGH, 0x00); WCrt (regs, CRT_ID_CURSOR_LOC_LOW, 0x00); WCrt (regs, CRT_ID_START_VER_RETR, 0x9C); WCrt (regs, CRT_ID_END_VER_RETR, 0x0E); WCrt (regs, CRT_ID_VER_DISP_ENA_END, 0x8F); WCrt (regs, CRT_ID_SCREEN_OFFSET, 0x50); WCrt (regs, CRT_ID_UNDERLINE_LOC, 0x00); WCrt (regs, CRT_ID_START_VER_BLANK, 0x96); WCrt (regs, CRT_ID_END_VER_BLANK, 0xB9); WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3); WCrt (regs, CRT_ID_LINE_COMPARE, 0xFF); WCrt (regs, CRT_ID_BACKWAD_COMP_3, 0x10); /* FIFO enabled */ WCrt (regs, CRT_ID_MISC_1, 0x35); WCrt (regs, CRT_ID_DISPLAY_FIFO, 0x5A); WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, 0x70); WCrt (regs, CRT_ID_LAW_POS_LO, 0x40); WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, 0xFF); WGfx (regs, GCT_ID_SET_RESET, 0x0); WGfx (regs, GCT_ID_ENABLE_SET_RESET, 0x0); WGfx (regs, GCT_ID_COLOR_COMPARE, 0x0); WGfx (regs, GCT_ID_DATA_ROTATE, 0x0); WGfx (regs, GCT_ID_READ_MAP_SELECT, 0x0); WGfx (regs, GCT_ID_GRAPHICS_MODE, 0x40); WGfx (regs, GCT_ID_MISC, 0x01); WGfx (regs, GCT_ID_COLOR_XCARE, 0x0F); WGfx (regs, GCT_ID_BITMASK, 0xFF); /* Colors for text mode */ for (i = 0; i < 0xf; i++) WAttr (regs, i, i); WAttr (regs, ACT_ID_ATTR_MODE_CNTL, 0x41); WAttr (regs, ACT_ID_OVERSCAN_COLOR, 0x01); WAttr (regs, ACT_ID_COLOR_PLANE_ENA, 0x0F); WAttr (regs, ACT_ID_HOR_PEL_PANNING, 0x0); WAttr (regs, ACT_ID_COLOR_SELECT, 0x0); wb_64 (regs, VDAC_MASK, 0xFF); *((unsigned long *) (regs + ECR_FRGD_COLOR)) = 0xFF; *((unsigned long *) (regs + ECR_BKGD_COLOR)) = 0; /* Colors initially set to grayscale */ wb_64 (regs, VDAC_ADDRESS_W, 0); for (i = 255; i >= 0; i--) { wb_64(regs, VDAC_DATA, i); wb_64(regs, VDAC_DATA, i); wb_64(regs, VDAC_DATA, i); } /* GFx hardware cursor off */ WCrt (regs, CRT_ID_HWGC_MODE, 0x00); /* Set first to 4MB, so test will work */ WCrt (regs, CRT_ID_LAW_CNTL, 0x13); /* Find "correct" size of fbmem of Z3 board */ if (cv_has_4mb (CyberMem)) { CyberSize = 1024 * 1024 * 4; WCrt (regs, CRT_ID_LAW_CNTL, 0x13); DPRINTK("4MB board\n"); } else { CyberSize = 1024 * 1024 * 2; WCrt (regs, CRT_ID_LAW_CNTL, 0x12); DPRINTK("2MB board\n"); } /* Initialize graphics engine */ Cyber_WaitBlit(); vgaw16 (regs, ECR_FRGD_MIX, 0x27); vgaw16 (regs, ECR_BKGD_MIX, 0x07); vgaw16 (regs, ECR_READ_REG_DATA, 0x1000); udelay(200); vgaw16 (regs, ECR_READ_REG_DATA, 0x2000); Cyber_WaitBlit(); vgaw16 (regs, ECR_READ_REG_DATA, 0x3FFF); Cyber_WaitBlit(); udelay(200); vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF); Cyber_WaitBlit(); vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, ~0); Cyber_WaitBlit(); vgaw16 (regs, ECR_READ_REG_DATA, 0xE000); vgaw16 (regs, ECR_CURRENT_Y_POS2, 0x00); vgaw16 (regs, ECR_CURRENT_X_POS2, 0x00); vgaw16 (regs, ECR_READ_REG_DATA, 0xA000); vgaw16 (regs, ECR_DEST_Y__AX_STEP, 0x00); vgaw16 (regs, ECR_DEST_Y2__AX_STEP2, 0x00); vgaw16 (regs, ECR_DEST_X__DIA_STEP, 0x00); vgaw16 (regs, ECR_DEST_X2__DIA_STEP2, 0x00); vgaw16 (regs, ECR_SHORT_STROKE, 0x00); vgaw16 (regs, ECR_DRAW_CMD, 0x01); Cyber_WaitBlit(); vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF); vgaw16 (regs, ECR_BKGD_COLOR, 0x01); vgaw16 (regs, ECR_FRGD_COLOR, 0x00); /* Enable video display (set bit 5) *//* ARB - Would also seem to write to AR13. * May want to use parts of WAttr to set JUST bit 5 */ WAttr (regs, 0x33, 0); /* GRF - function code ended here */ /* Turn gfx on again */ gfx_on_off (0, regs); /* Pass-through */ cvscreen (0, CyberBase); DPRINTK("EXIT\n");}static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode){ volatile unsigned char *regs = CyberRegs; int fx, fy; unsigned short mnr; unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, VSE, VT; char LACE, DBLSCAN, TEXT, CONSOLE; int cr50, sr15, sr18, clock_mode, test; int m, n; int tfillm, temptym; int hmul; /* ---------------- */ int xres, hfront, hsync, hback; int yres, vfront, vsync, vback; int bpp;#if 0 float freq_f;#endif long freq; /* ---------------- */ DPRINTK("ENTER\n"); TEXT = 0; /* if depth == 4 */ CONSOLE = 0; /* mode num == 255 (console) */ fx = fy = 8; /* force 8x8 font *//* GRF - Disable interrupts */ gfx_on_off (1, regs); switch (video_mode->bits_per_pixel) { case 15: case 16: hmul = 2; break; default: hmul = 1; break; } bpp = video_mode->bits_per_pixel; xres = video_mode->xres; hfront = video_mode->right_margin; hsync = video_mode->hsync_len; hback = video_mode->left_margin; LACE = 0; DBLSCAN = 0; if (video_mode->vmode & FB_VMODE_DOUBLE) { yres = video_mode->yres * 2; vfront = video_mode->lower_margin * 2; vsync = video_mode->vsync_len * 2; vback = video_mode->upper_margin * 2; DBLSCAN = 1; } else if (video_mode->vmode & FB_VMODE_INTERLACED) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -