📄 retz3fb.c
字号:
/* unlock register CRT0..CRT7 */ crt_w(regs, CRT_END_VER_RETR, (data.v_sstop & 0x0f) | 0x20); /* Zuerst zu schreibende Werte nur per printk ausgeben */ DEBUG printk("CRT_HOR_TOTAL: %ld\n", data.h_total); crt_w(regs, CRT_HOR_TOTAL, data.h_total & 0xff); DEBUG printk("CRT_HOR_DISP_ENA_END: %ld\n", data.h_dispend); crt_w(regs, CRT_HOR_DISP_ENA_END, (data.h_dispend) & 0xff); DEBUG printk("CRT_START_HOR_BLANK: %ld\n", data.h_bstart); crt_w(regs, CRT_START_HOR_BLANK, data.h_bstart & 0xff); DEBUG printk("CRT_END_HOR_BLANK: 128+%ld\n", data.h_bstop % 32); crt_w(regs, CRT_END_HOR_BLANK, 0x80 | (data.h_bstop & 0x1f)); DEBUG printk("CRT_START_HOR_RETR: %ld\n", data.h_sstart); crt_w(regs, CRT_START_HOR_RETR, data.h_sstart & 0xff); tmp = (data.h_sstop & 0x1f); if (data.h_bstop & 0x20) tmp |= 0x80; DEBUG printk("CRT_END_HOR_RETR: %d\n", tmp); crt_w(regs, CRT_END_HOR_RETR, tmp); DEBUG printk("CRT_VER_TOTAL: %ld\n", data.v_total & 0xff); crt_w(regs, CRT_VER_TOTAL, (data.v_total & 0xff)); tmp = 0x10; /* LineCompare bit #9 */ if (data.v_total & 256) tmp |= 0x01; if (data.v_dispend & 256) tmp |= 0x02; if (data.v_sstart & 256) tmp |= 0x04; if (data.v_bstart & 256) tmp |= 0x08; if (data.v_total & 512) tmp |= 0x20; if (data.v_dispend & 512) tmp |= 0x40; if (data.v_sstart & 512) tmp |= 0x80; DEBUG printk("CRT_OVERFLOW: %d\n", tmp); crt_w(regs, CRT_OVERFLOW, tmp); crt_w(regs, CRT_PRESET_ROW_SCAN, 0x00); /* not CL !!! */ tmp = 0x40; /* LineCompare bit #8 */ if (data.v_bstart & 512) tmp |= 0x20; if (var->vmode & FB_VMODE_DOUBLE) tmp |= 0x80; DEBUG printk("CRT_MAX_SCAN_LINE: %d\n", tmp); crt_w(regs, CRT_MAX_SCAN_LINE, tmp); crt_w(regs, CRT_CURSOR_START, 0x00); crt_w(regs, CRT_CURSOR_END, 8 & 0x1f); /* font height */ crt_w(regs, CRT_START_ADDR_HIGH, 0x00); crt_w(regs, CRT_START_ADDR_LOW, 0x00); crt_w(regs, CRT_CURSOR_LOC_HIGH, 0x00); crt_w(regs, CRT_CURSOR_LOC_LOW, 0x00); DEBUG printk("CRT_START_VER_RETR: %ld\n", data.v_sstart & 0xff); crt_w(regs, CRT_START_VER_RETR, (data.v_sstart & 0xff));#if 1 /* 5 refresh cycles per scanline */ DEBUG printk("CRT_END_VER_RETR: 64+32+%ld\n", data.v_sstop % 16); crt_w(regs, CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 0x40 | 0x20));#else DEBUG printk("CRT_END_VER_RETR: 128+32+%ld\n", data.v_sstop % 16); crt_w(regs, CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 128 | 32));#endif DEBUG printk("CRT_VER_DISP_ENA_END: %ld\n", data.v_dispend & 0xff); crt_w(regs, CRT_VER_DISP_ENA_END, (data.v_dispend & 0xff)); DEBUG printk("CRT_START_VER_BLANK: %ld\n", data.v_bstart & 0xff); crt_w(regs, CRT_START_VER_BLANK, (data.v_bstart & 0xff)); DEBUG printk("CRT_END_VER_BLANK: %ld\n", data.v_bstop & 0xff); crt_w(regs, CRT_END_VER_BLANK, (data.v_bstop & 0xff)); DEBUG printk("CRT_MODE_CONTROL: 0xe3\n"); crt_w(regs, CRT_MODE_CONTROL, 0xe3); DEBUG printk("CRT_LINE_COMPARE: 0xff\n"); crt_w(regs, CRT_LINE_COMPARE, 0xff); tmp = (var->xres_virtual / 8) * (bpp / 8); crt_w(regs, CRT_OFFSET, tmp); crt_w(regs, CRT_UNDERLINE_LOC, 0x07); /* probably font-height - 1 */ tmp = 0x20; /* Enable extended end bits */ if (data.h_total & 0x100) tmp |= 0x01; if ((data.h_dispend) & 0x100) tmp |= 0x02; if (data.h_bstart & 0x100) tmp |= 0x04; if (data.h_sstart & 0x100) tmp |= 0x08; if (var->vmode & FB_VMODE_INTERLACED) tmp |= 0x10; DEBUG printk("CRT_EXT_HOR_TIMING1: %d\n", tmp); crt_w(regs, CRT_EXT_HOR_TIMING1, tmp); tmp = 0x00; if (((var->xres_virtual / 8) * (bpp / 8)) & 0x100) tmp |= 0x10; crt_w(regs, CRT_EXT_START_ADDR, tmp); tmp = 0x00; if (data.h_total & 0x200) tmp |= 0x01; if ((data.h_dispend) & 0x200) tmp |= 0x02; if (data.h_bstart & 0x200) tmp |= 0x04; if (data.h_sstart & 0x200) tmp |= 0x08; tmp |= ((data.h_bstop & 0xc0) >> 2); tmp |= ((data.h_sstop & 0x60) << 1); crt_w(regs, CRT_EXT_HOR_TIMING2, tmp); DEBUG printk("CRT_EXT_HOR_TIMING2: %d\n", tmp); tmp = 0x10; /* Line compare bit 10 */ if (data.v_total & 0x400) tmp |= 0x01; if ((data.v_dispend) & 0x400) tmp |= 0x02; if (data.v_bstart & 0x400) tmp |= 0x04; if (data.v_sstart & 0x400) tmp |= 0x08; tmp |= ((data.v_bstop & 0x300) >> 3); if (data.v_sstop & 0x10) tmp |= 0x80; crt_w(regs, CRT_EXT_VER_TIMING, tmp); DEBUG printk("CRT_EXT_VER_TIMING: %d\n", tmp); crt_w(regs, CRT_MONITOR_POWER, 0x00); /* * Convert from ps to Hz. */ freq = 2000000000 / var->pixclock; freq = freq * 500; best_freq = find_fq(freq); pll_w(regs, 0x02, best_freq); best_freq = find_fq(61000000); pll_w(regs, 0x0a, best_freq); pll_w(regs, 0x0e, 0x22); gfx_w(regs, GFX_SET_RESET, 0x00); gfx_w(regs, GFX_ENABLE_SET_RESET, 0x00); gfx_w(regs, GFX_COLOR_COMPARE, 0x00); gfx_w(regs, GFX_DATA_ROTATE, 0x00); gfx_w(regs, GFX_READ_MAP_SELECT, 0x00); gfx_w(regs, GFX_GRAPHICS_MODE, 0x00); gfx_w(regs, GFX_MISC, 0x05); gfx_w(regs, GFX_COLOR_XCARE, 0x0f); gfx_w(regs, GFX_BITMASK, 0xff); reg_r(regs, ACT_ADDRESS_RESET); attr_w(regs, ACT_PALETTE0 , 0x00); attr_w(regs, ACT_PALETTE1 , 0x01); attr_w(regs, ACT_PALETTE2 , 0x02); attr_w(regs, ACT_PALETTE3 , 0x03); attr_w(regs, ACT_PALETTE4 , 0x04); attr_w(regs, ACT_PALETTE5 , 0x05); attr_w(regs, ACT_PALETTE6 , 0x06); attr_w(regs, ACT_PALETTE7 , 0x07); attr_w(regs, ACT_PALETTE8 , 0x08); attr_w(regs, ACT_PALETTE9 , 0x09); attr_w(regs, ACT_PALETTE10, 0x0a); attr_w(regs, ACT_PALETTE11, 0x0b); attr_w(regs, ACT_PALETTE12, 0x0c); attr_w(regs, ACT_PALETTE13, 0x0d); attr_w(regs, ACT_PALETTE14, 0x0e); attr_w(regs, ACT_PALETTE15, 0x0f); reg_r(regs, ACT_ADDRESS_RESET); attr_w(regs, ACT_ATTR_MODE_CNTL, 0x09); /* 0x01 for CL */ attr_w(regs, ACT_OVERSCAN_COLOR, 0x00); attr_w(regs, ACT_COLOR_PLANE_ENA, 0x0f); attr_w(regs, ACT_HOR_PEL_PANNING, 0x00); attr_w(regs, ACT_COLOR_SELECT, 0x00); reg_r(regs, ACT_ADDRESS_RESET); reg_w(regs, ACT_DATA, 0x20); reg_w(regs, VDAC_MASK, 0xff); /* * Extended palette addressing ??? */ switch (bpp){ case 8: reg_w(regs, 0x83c6, 0x00); break; case 16: reg_w(regs, 0x83c6, 0x60); break; case 24: reg_w(regs, 0x83c6, 0xe0); break; default: printk(KERN_INFO "Illegal color-depth: %i\n", bpp); } reg_w(regs, VDAC_ADDRESS, 0x00); seq_w(regs, SEQ_MAP_MASK, 0x0f ); return 0;}/* * This function should fill in the `fix' structure based on the * values in the `par' structure. */static int retz3_encode_fix(struct fb_info *info, struct fb_fix_screeninfo *fix, struct retz3fb_par *par){ struct retz3_fb_info *zinfo = retz3info(info); memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, retz3fb_name); fix->smem_start = zinfo->physfbmem; fix->smem_len = zinfo->fbsize; fix->mmio_start = zinfo->physregs; fix->mmio_len = 0x00c00000; fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; if (par->bpp == 8) fix->visual = FB_VISUAL_PSEUDOCOLOR; else fix->visual = FB_VISUAL_TRUECOLOR; fix->xpanstep = 0; fix->ypanstep = 0; fix->ywrapstep = 0; fix->line_length = 0; fix->accel = FB_ACCEL_NCR_77C32BLT; return 0;}/* * Get the video params out of `var'. If a value doesn't fit, round * it up, if it's too big, return -EINVAL. */static int retz3_decode_var(struct fb_var_screeninfo *var, struct retz3fb_par *par){ par->xres = var->xres; par->yres = var->yres; par->xres_vir = var->xres_virtual; par->yres_vir = var->yres_virtual; par->bpp = var->bits_per_pixel; par->pixclock = var->pixclock; par->vmode = var->vmode; par->red = var->red; par->green = var->green; par->blue = var->blue; par->transp = var->transp; par->left_margin = var->left_margin; par->right_margin = var->right_margin; par->upper_margin = var->upper_margin; par->lower_margin = var->lower_margin; par->hsync_len = var->hsync_len; par->vsync_len = var->vsync_len; if (var->accel_flags & FB_ACCELF_TEXT) par->accel = FB_ACCELF_TEXT; else par->accel = 0; return 0;}/* * Fill the `var' structure based on the values in `par' and maybe * other values read out of the hardware. */static int retz3_encode_var(struct fb_var_screeninfo *var, struct retz3fb_par *par){ memset(var, 0, sizeof(struct fb_var_screeninfo)); var->xres = par->xres; var->yres = par->yres; var->xres_virtual = par->xres_vir; var->yres_virtual = par->yres_vir; var->xoffset = 0; var->yoffset = 0; var->bits_per_pixel = par->bpp; var->grayscale = 0; var->red = par->red; var->green = par->green; var->blue = par->blue; var->transp = par->transp; var->nonstd = 0; var->activate = 0; var->height = -1; var->width = -1; var->accel_flags = (par->accel && par->bpp == 8) ? FB_ACCELF_TEXT : 0; var->pixclock = par->pixclock; var->sync = 0; /* ??? */ var->left_margin = par->left_margin; var->right_margin = par->right_margin; var->upper_margin = par->upper_margin; var->lower_margin = par->lower_margin; var->hsync_len = par->hsync_len; var->vsync_len = par->vsync_len; var->vmode = par->vmode; return 0;}/* * Set a single color register. Return != 0 for invalid regno. */static int retz3_setcolreg(unsigned int regno, unsigned int red, unsigned int green, unsigned int blue, unsigned int transp, struct fb_info *info){ struct retz3_fb_info *zinfo = retz3info(info); volatile unsigned char *regs = zinfo->regs; /* We'll get to this */ if (regno > 255) return 1; red >>= 10; green >>= 10; blue >>= 10; zinfo->color_table[regno][0] = red; zinfo->color_table[regno][1] = green; zinfo->color_table[regno][2] = blue; reg_w(regs, VDAC_ADDRESS_W, regno); reg_w(regs, VDAC_DATA, red); reg_w(regs, VDAC_DATA, green); reg_w(regs, VDAC_DATA, blue); return 0;}/* * Read a single color register and split it into * colors/transparent. Return != 0 for invalid regno. */static int retz3_getcolreg(unsigned int regno, unsigned int *red, unsigned int *green, unsigned int *blue, unsigned int *transp, struct fb_info *info){ struct retz3_fb_info *zinfo = retz3info(info); int t; if (regno > 255) return 1; t = zinfo->color_table[regno][0]; *red = (t<<10) | (t<<4) | (t>>2); t = zinfo->color_table[regno][1]; *green = (t<<10) | (t<<4) | (t>>2); t = zinfo->color_table[regno][2]; *blue = (t<<10) | (t<<4) | (t>>2); *transp = 0; return 0;}static inline void retz3_busy(struct display *p){ struct retz3_fb_info *zinfo = retz3info(p->fb_info); volatile unsigned char *acm = zinfo->base + ACM_OFFSET; unsigned char blt_status; if (zinfo->blitbusy) { do{ blt_status = *((acm) + (ACM_START_STATUS + 2)); }while ((blt_status & 1) == 0); zinfo->blitbusy = 0; }}static void retz3_bitblt (struct display *p, unsigned short srcx, unsigned short srcy, unsigned short destx, unsigned short desty, unsigned short width, unsigned short height, unsigned short cmd, unsigned short mask){ struct fb_var_screeninfo *var = &p->var; struct retz3_fb_info *zinfo = retz3info(p->fb_info); volatile unsigned long *acm = (unsigned long *)(zinfo->base + ACM_OFFSET); unsigned long *pattern = (unsigned long *)(zinfo->fbmem + PAT_MEM_OFF); unsigned short mod; unsigned long tmp; unsigned long pat, src, dst; int i, xres_virtual = var->xres_virtual; short bpp = (var->bits_per_pixel & 0xff); if (bpp < 8) bpp = 8; tmp = mask | (mask << 16); retz3_busy(p); i = 0; do{ *pattern++ = tmp; }while(i++ < bpp/4); tmp = cmd << 8; *(acm + ACM_RASTEROP_ROTATION/4) = tmp; mod = 0xc0c2; pat = 8 * PAT_MEM_OFF; dst = bpp * (destx + desty * xres_virtual); /* * Source is not set for clear. */ if ((cmd != Z3BLTclear) && (cmd != Z3BLTset)) { src = bpp * (srcx + srcy * xres_virtual); if (destx > srcx) { mod &= ~0x8000; src += bpp * (width - 1); dst += bpp * (width - 1); pat += bpp * 2; } if (desty > srcy) { mod &= ~0x4000; src += bpp * (height - 1) * xres_virtual; dst += bpp * (height - 1) * xres_virtual; pat += bpp * 4; } *(acm + ACM_SOURCE/4) = cpu_to_le32(src); } *(acm + ACM_PATTERN/4) = cpu_to_le32(pat); *(acm + ACM_DESTINATION/4) = cpu_to_le32(dst); tmp = mod << 16; *(acm + ACM_CONTROL/4) = tmp; tmp = width | (height << 16); *(acm + ACM_BITMAP_DIMENSION/4) = cpu_to_le32(tmp); *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00; *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01; zinfo->blitbusy = 1;}#if 0/* * Move cursor to x, y */static void retz3_MoveCursor (unsigned short x, unsigned short y){ /* Guess we gotta deal with the cursor at some point */}#endif/* * Fill the hardware's `par' structure. */static void retz3fb_get_par(struct fb_info *info, struct retz3fb_par *par){ struct retz3_fb_info *zinfo = retz3info(info); if (zinfo->current_par_valid) *par = zinfo->current_par; else retz3_decode_var(&retz3fb_default, par);}static void retz3fb_set_par(struct fb_info *info, struct retz3fb_par *par){ struct retz3_fb_info *zinfo = retz3info(info); zinfo->current_par = *par; zinfo->current_par_valid = 1;}static int do_fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var, int isactive){ int err, activate; struct retz3fb_par par; struct retz3_fb_info *zinfo = retz3info(info); if ((err = retz3_decode_var(var, &par))) return err; activate = var->activate; /* XXX ... what to do about isactive ? */ if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive) retz3fb_set_par(info, &par); retz3_encode_var(var, &par); var->activate = activate; retz3_set_video(info, var, &zinfo->current_par); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -