📄 imsttfb.c
字号:
case 1280: init = yres == 960 ? &tvp_reg_init_19 : &tvp_reg_init_20; break; default: return NULL; } par->init = *init; return init;}static struct imstt_regvals *compute_imstt_regvals (struct imstt_par *par, u_int xres, u_int yres){ if (par->ramdac == IBM) return compute_imstt_regvals_ibm(par, xres, yres); else return compute_imstt_regvals_tvp(par, xres, yres);}static voidset_imstt_regvals_ibm (struct imstt_par *par, u_int bpp){ struct imstt_regvals *init = &par->init; __u8 pformat = (bpp >> 3) + 2; par->cmap_regs[PIDXHI] = 0; eieio(); par->cmap_regs[PIDXLO] = PIXM0; eieio(); par->cmap_regs[PIDXDATA] = init->pclk_m;eieio(); par->cmap_regs[PIDXLO] = PIXN0; eieio(); par->cmap_regs[PIDXDATA] = init->pclk_n;eieio(); par->cmap_regs[PIDXLO] = PIXP0; eieio(); par->cmap_regs[PIDXDATA] = init->pclk_p;eieio(); par->cmap_regs[PIDXLO] = PIXC0; eieio(); par->cmap_regs[PIDXDATA] = 0x02; eieio(); par->cmap_regs[PIDXLO] = PIXFMT; eieio(); par->cmap_regs[PIDXDATA] = pformat; eieio();}static voidset_imstt_regvals_tvp (struct imstt_par *par, u_int bpp){ struct imstt_regvals *init = &par->init; __u8 tcc, mxc, lckl_n, mic; __u8 mlc, lckl_p; switch (bpp) { default: case 8: tcc = 0x80; mxc = 0x4d; lckl_n = 0xc1; mlc = init->mlc[0]; lckl_p = init->lckl_p[0]; break; case 16: tcc = 0x44; mxc = 0x55; lckl_n = 0xe1; mlc = init->mlc[1]; lckl_p = init->lckl_p[1]; break; case 24: tcc = 0x5e; mxc = 0x5d; lckl_n = 0xf1; mlc = init->mlc[2]; lckl_p = init->lckl_p[2]; break; case 32: tcc = 0x46; mxc = 0x5d; lckl_n = 0xf1; mlc = init->mlc[2]; lckl_p = init->lckl_p[2]; break; } mic = 0x08; par->cmap_regs[TVPADDRW] = TVPIRPLA; eieio(); par->cmap_regs[TVPIDATA] = 0x00; eieio(); par->cmap_regs[TVPADDRW] = TVPIRPPD; eieio(); par->cmap_regs[TVPIDATA] = init->pclk_m; eieio(); par->cmap_regs[TVPADDRW] = TVPIRPPD; eieio(); par->cmap_regs[TVPIDATA] = init->pclk_n; eieio(); par->cmap_regs[TVPADDRW] = TVPIRPPD; eieio(); par->cmap_regs[TVPIDATA] = init->pclk_p; eieio(); par->cmap_regs[TVPADDRW] = TVPIRTCC; eieio(); par->cmap_regs[TVPIDATA] = tcc; eieio(); par->cmap_regs[TVPADDRW] = TVPIRMXC; eieio(); par->cmap_regs[TVPIDATA] = mxc; eieio(); par->cmap_regs[TVPADDRW] = TVPIRMIC; eieio(); par->cmap_regs[TVPIDATA] = mic; eieio(); par->cmap_regs[TVPADDRW] = TVPIRPLA; eieio(); par->cmap_regs[TVPIDATA] = 0x00; eieio(); par->cmap_regs[TVPADDRW] = TVPIRLPD; eieio(); par->cmap_regs[TVPIDATA] = lckl_n; eieio(); par->cmap_regs[TVPADDRW] = TVPIRPLA; eieio(); par->cmap_regs[TVPIDATA] = 0x15; eieio(); par->cmap_regs[TVPADDRW] = TVPIRMLC; eieio(); par->cmap_regs[TVPIDATA] = mlc; eieio(); par->cmap_regs[TVPADDRW] = TVPIRPLA; eieio(); par->cmap_regs[TVPIDATA] = 0x2a; eieio(); par->cmap_regs[TVPADDRW] = TVPIRLPD; eieio(); par->cmap_regs[TVPIDATA] = lckl_p; eieio();}static voidset_imstt_regvals (struct fb_info *info, u_int bpp){ struct imstt_par *par = info->par; struct imstt_regvals *init = &par->init; __u32 ctl, pitch, byteswap, scr; if (par->ramdac == IBM) set_imstt_regvals_ibm(par, bpp); else set_imstt_regvals_tvp(par, bpp); /* * From what I (jsk) can gather poking around with MacsBug, * bits 8 and 9 in the SCR register control endianness * correction (byte swapping). These bits must be set according * to the color depth as follows: * Color depth Bit 9 Bit 8 * ========== ===== ===== * 8bpp 0 0 * 16bpp 0 1 * 32bpp 1 1 */ switch (bpp) { default: case 8: ctl = 0x17b1; pitch = init->pitch >> 2; byteswap = 0x000; break; case 16: ctl = 0x17b3; pitch = init->pitch >> 1; byteswap = 0x100; break; case 24: ctl = 0x17b9; pitch = init->pitch - (init->pitch >> 2); byteswap = 0x200; break; case 32: ctl = 0x17b5; pitch = init->pitch; byteswap = 0x300; break; } if (par->ramdac == TVP) ctl -= 0x30; write_reg_le32(par->dc_regs, HES, init->hes); write_reg_le32(par->dc_regs, HEB, init->heb); write_reg_le32(par->dc_regs, HSB, init->hsb); write_reg_le32(par->dc_regs, HT, init->ht); write_reg_le32(par->dc_regs, VES, init->ves); write_reg_le32(par->dc_regs, VEB, init->veb); write_reg_le32(par->dc_regs, VSB, init->vsb); write_reg_le32(par->dc_regs, VT, init->vt); write_reg_le32(par->dc_regs, VIL, init->vil); write_reg_le32(par->dc_regs, HCIV, 1); write_reg_le32(par->dc_regs, VCIV, 1); write_reg_le32(par->dc_regs, TCDR, 4); write_reg_le32(par->dc_regs, RRCIV, 1); write_reg_le32(par->dc_regs, RRSC, 0x980); write_reg_le32(par->dc_regs, RRCR, 0x11); if (par->ramdac == IBM) { write_reg_le32(par->dc_regs, HRIR, 0x0100); write_reg_le32(par->dc_regs, CMR, 0x00ff); write_reg_le32(par->dc_regs, SRGCTL, 0x0073); } else { write_reg_le32(par->dc_regs, HRIR, 0x0200); write_reg_le32(par->dc_regs, CMR, 0x01ff); write_reg_le32(par->dc_regs, SRGCTL, 0x0003); } switch (info->fix.smem_len) { case 0x200000: scr = 0x059d | byteswap; break; /* case 0x400000: case 0x800000: */ default: pitch >>= 1; scr = 0x150dd | byteswap; break; } write_reg_le32(par->dc_regs, SCR, scr); write_reg_le32(par->dc_regs, SPR, pitch); write_reg_le32(par->dc_regs, STGCTL, ctl);}static inline voidset_offset (struct fb_var_screeninfo *var, struct fb_info *info){ struct imstt_par *par = info->par; __u32 off = var->yoffset * (info->fix.line_length >> 3) + ((var->xoffset * (var->bits_per_pixel >> 3)) >> 3); write_reg_le32(par->dc_regs, SSR, off);}static inline voidset_555 (struct imstt_par *par){ if (par->ramdac == IBM) { par->cmap_regs[PIDXHI] = 0; eieio(); par->cmap_regs[PIDXLO] = BPP16; eieio(); par->cmap_regs[PIDXDATA] = 0x01; eieio(); } else { par->cmap_regs[TVPADDRW] = TVPIRTCC; eieio(); par->cmap_regs[TVPIDATA] = 0x44; eieio(); }}static inline voidset_565 (struct imstt_par *par){ if (par->ramdac == IBM) { par->cmap_regs[PIDXHI] = 0; eieio(); par->cmap_regs[PIDXLO] = BPP16; eieio(); par->cmap_regs[PIDXDATA] = 0x03; eieio(); } else { par->cmap_regs[TVPADDRW] = TVPIRTCC; eieio(); par->cmap_regs[TVPIDATA] = 0x45; eieio(); }}static intimsttfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){ if ((var->bits_per_pixel != 8 && var->bits_per_pixel != 16 && var->bits_per_pixel != 24 && var->bits_per_pixel != 32) || var->xres_virtual < var->xres || var->yres_virtual < var->yres || var->nonstd || (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) return -EINVAL; if ((var->xres * var->yres) * (var->bits_per_pixel >> 3) > info->fix.smem_len || (var->xres_virtual * var->yres_virtual) * (var->bits_per_pixel >> 3) > info->fix.smem_len) return -EINVAL; switch (var->bits_per_pixel) { case 8: var->red.offset = 0; var->red.length = 8; var->green.offset = 0; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; var->transp.offset = 0; var->transp.length = 0; break; case 16: /* RGB 555 or 565 */ if (var->green.length != 6) var->red.offset = 10; var->red.length = 5; var->green.offset = 5; if (var->green.length != 6) var->green.length = 5; var->blue.offset = 0; var->blue.length = 5; var->transp.offset = 0; var->transp.length = 0; break; case 24: /* RGB 888 */ var->red.offset = 16; var->red.length = 8; var->green.offset = 8; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; var->transp.offset = 0; var->transp.length = 0; break; case 32: /* RGBA 8888 */ var->red.offset = 16; var->red.length = 8; var->green.offset = 8; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; var->transp.offset = 24; var->transp.length = 8; break; } if (var->yres == var->yres_virtual) { __u32 vram = (info->fix.smem_len - (PAGE_SIZE << 2)); var->yres_virtual = ((vram << 3) / var->bits_per_pixel) / var->xres_virtual; if (var->yres_virtual < var->yres) var->yres_virtual = var->yres; } var->red.msb_right = 0; var->green.msb_right = 0; var->blue.msb_right = 0; var->transp.msb_right = 0; var->height = -1; var->width = -1; var->vmode = FB_VMODE_NONINTERLACED; var->left_margin = var->right_margin = 16; var->upper_margin = var->lower_margin = 16; var->hsync_len = var->vsync_len = 8; return 0;}static intimsttfb_set_par(struct fb_info *info) { struct imstt_par *par = info->par; if (!compute_imstt_regvals(par, info->var.xres, info->var.yres)) return -EINVAL; if (info->var.green.length == 6) set_565(par); else set_555(par); set_imstt_regvals(info, info->var.bits_per_pixel); info->var.pixclock = 1000000 / getclkMHz(par); return 0;}static intimsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info){ struct imstt_par *par = info->par; u_int bpp = info->var.bits_per_pixel; if (regno > 255) return 1; red >>= 8; green >>= 8; blue >>= 8; /* PADDRW/PDATA are the same as TVPPADDRW/TVPPDATA */ if (0 && bpp == 16) /* screws up X */ par->cmap_regs[PADDRW] = regno << 3; else par->cmap_regs[PADDRW] = regno; eieio(); par->cmap_regs[PDATA] = red; eieio(); par->cmap_regs[PDATA] = green; eieio(); par->cmap_regs[PDATA] = blue; eieio(); if (regno < 16) switch (bpp) { case 16: par->palette[regno] = (regno << (info->var.green.length == 5 ? 10 : 11)) | (regno << 5) | regno; break; case 24: par->palette[regno] = (regno << 16) | (regno << 8) | regno; break; case 32: { int i = (regno << 8) | regno; par->palette[regno] = (i << 16) |i; break; } } return 0;}static intimsttfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info){ if (var->xoffset + info->var.xres > info->var.xres_virtual || var->yoffset + info->var.yres > info->var.yres_virtual) return -EINVAL; info->var.xoffset = var->xoffset; info->var.yoffset = var->yoffset; set_offset(var, info); return 0;}static int imsttfb_blank(int blank, struct fb_info *info){ struct imstt_par *par = info->par; __u32 ctrl; ctrl = read_reg_le32(par->dc_regs, STGCTL); if (blank > 0) { switch (blank) { case FB_BLANK_NORMAL: case FB_BLANK_POWERDOWN: ctrl &= ~0x00000380; if (par->ramdac == IBM) { par->cmap_regs[PIDXHI] = 0; eieio(); par->cmap_regs[PIDXLO] = MISCTL2; eieio(); par->cmap_regs[PIDXDATA] = 0x55; eieio(); par->cmap_regs[PIDXLO] = MISCTL1; eieio(); par->cmap_regs[PIDXDATA] = 0x11; eieio(); par->cmap_regs[PIDXLO] = SYNCCTL; eieio(); par->cmap_regs[PIDXDATA] = 0x0f; eieio(); par->cmap_regs[PIDXLO] = PWRMNGMT; eieio(); par->cmap_regs[PIDXDATA] = 0x1f; eieio(); par->cmap_regs[PIDXLO] = CLKCTL; eieio(); par->cmap_regs[PIDXDATA] = 0xc0; } break; case FB_BLANK_VSYNC_SUSPEND: ctrl &= ~0x00000020; break; case FB_BLANK_HSYNC_SUSPEND: ctrl &= ~0x00000010; break; } } else { if (par->ramdac == IBM) { ctrl |= 0x000017b0; par->cmap_regs[PIDXHI] = 0; eieio(); par->cmap_regs[PIDXLO] = CLKCTL; eieio(); par->cmap_regs[PIDXDATA] = 0x01; eieio(); par->cmap_regs[PIDXLO] = PWRMNGMT; eieio(); par->cmap_regs[PIDXDATA] = 0x00; eieio(); par->cmap_regs[PIDXLO] = SYNCCTL; eieio(); par->cmap_regs[PIDXDATA] = 0x00; eieio(); par->cmap_regs[PIDXLO] = MISCTL1; eieio(); par->cmap_regs[PIDXDATA] = 0x01; eieio(); par->cmap_regs[PIDXLO] = MISCTL2; eieio(); par->cmap_regs[PIDXDATA] = 0x45; eieio(); } else ctrl |= 0x00001780; } write_reg_le32(par->dc_regs, STGCTL, ctrl); return 0;}static voidimsttfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect){ struct imstt_par *par = info->par; __u32 Bpp, line_pitch, bgc, dx, dy, width, height; bgc = rect->color; bgc |= (bgc << 8); bgc |= (bgc << 16); Bpp = info->var.bits_per_pixel >> 3, line_pitch = info->fix.line_length; dy = rect->dy * line_pitch; dx = rect->dx * Bpp; height = rect->height; height--; width = rect->width * Bpp; width--; if (rect->rop == ROP_COPY) { while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80); write_reg_le32(par->dc_regs, DSA, dy + dx); write_reg_le32(par->dc_regs, CNT, (height << 16) | width); write_reg_le32(par->dc_regs, DP_OCTL, line_pitch); write_reg_le32(par->dc_regs, BI, 0xffffffff); write_reg_le32(par->dc_regs, MBC, 0xffffffff); write_reg_le32(par->dc_regs, CLR, bgc); write_reg_le32(par->dc_regs, BLTCTL, 0x840); /* 0x200000 */ while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80); while(read_reg_le32(par->dc_regs, SSTATUS) & 0x40); } else { while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80); write_reg_le32(par->dc_regs, DSA, dy + dx); write_reg_le32(par->dc_regs, S1SA, dy + dx); write_reg_le32(par->dc_regs, CNT, (height << 16) | width); write_reg_le32(par->dc_regs, DP_OCTL, line_pitch); write_reg_le32(par->dc_regs, SP, line_pitch); write_reg_le32(par->dc_regs, BLTCTL, 0x40005); while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80); while(read_reg_le32(par->dc_regs, SSTATUS) & 0x40); }}static voidimsttfb_copyarea(struct fb_info *info, const struct fb_copyarea *area){ struct imstt_par *par = info->par; __u32 Bpp, line_pitch, fb_offset_old, fb_offset_new, sp, dp_octl; __u32 cnt, bltctl, sx, sy, dx, dy, height, width; Bpp = info->var.bits_per_pixel >> 3, sx = area->sx * Bpp; sy = area->sy; dx = area->dx * Bpp; dy = area->dy; height = area->height; height--; width = area->width * Bpp; width--; line_pitch = info->fix.line_length; bltctl = 0x05; sp = line_pitch << 16; cnt = height << 16; if (sy < dy) { sy += height; dy += height; sp |= -(line_pitch) & 0xffff; dp_octl = -(line_pitch) & 0xffff; } else { sp |= line_pitch; dp_octl = line_pitch; } if (sx < dx) { sx += width; dx += width; bltctl |= 0x80; cnt |= -(width) & 0xffff; } else { cnt |= width; } fb_offset_old = sy * line_pitch + sx; fb_offset_new = dy * line_pitch + dx; while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80); write_reg_le32(par->dc_regs, S1SA, fb_offset_old); write_reg_le32(par->dc_regs, SP, sp); write_reg_le32(par->dc_regs, DSA, fb_offset_new); write_reg_le32(par->dc_regs, CNT, cnt); write_reg_le32(par->dc_regs, DP_OCTL, dp_octl); write_reg_le32(par->dc_regs, BLTCTL, bltctl); while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80); while(read_reg_le32(par->dc_regs, SSTATUS) & 0x40);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -