📄 pm2fb.c
字号:
for (i = 256; i; i--) if (pm2v_RDAC_RD(par, PM2VI_RD_MCLK_CONTROL) & 2) break; pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0); break; case PM2_TYPE_PERMEDIA2: pm2_mnp(clk, &m, &n, &p); WAIT_FIFO(par, 10); pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 6); pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_1, m); pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_2, n); pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 8|p); pm2_RDAC_RD(par, PM2I_RD_MEMORY_CLOCK_STATUS); rmb(); for (i = 256; i; i--) if (pm2_RD(par, PM2R_RD_INDEXED_DATA) & PM2F_PLL_LOCKED) break; break; }}static void set_pixclock(struct pm2fb_par *par, u32 clk){ int i; unsigned char m, n, p; switch (par->type) { case PM2_TYPE_PERMEDIA2: pm2_mnp(clk, &m, &n, &p); WAIT_FIFO(par, 10); pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A3, 0); pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A1, m); pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A2, n); pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A3, 8|p); pm2_RDAC_RD(par, PM2I_RD_PIXEL_CLOCK_STATUS); rmb(); for (i = 256; i; i--) if (pm2_RD(par, PM2R_RD_INDEXED_DATA) & PM2F_PLL_LOCKED) break; break; case PM2_TYPE_PERMEDIA2V: pm2v_mnp(clk/2, &m, &n, &p); WAIT_FIFO(par, 8); pm2_WR(par, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CLK0_PRESCALE >> 8); pm2v_RDAC_WR(par, PM2VI_RD_CLK0_PRESCALE, m); pm2v_RDAC_WR(par, PM2VI_RD_CLK0_FEEDBACK, n); pm2v_RDAC_WR(par, PM2VI_RD_CLK0_POSTSCALE, p); pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0); break; }}static void set_video(struct pm2fb_par *p, u32 video){ u32 tmp; u32 vsync = video; DPRINTK("video = 0x%x\n", video); /* * The hardware cursor needs +vsync to recognise vert retrace. * We may not be using the hardware cursor, but the X Glint * driver may well. So always set +hsync/+vsync and then set * the RAMDAC to invert the sync if necessary. */ vsync &= ~(PM2F_HSYNC_MASK | PM2F_VSYNC_MASK); vsync |= PM2F_HSYNC_ACT_HIGH | PM2F_VSYNC_ACT_HIGH; WAIT_FIFO(p, 3); pm2_WR(p, PM2R_VIDEO_CONTROL, vsync); switch (p->type) { case PM2_TYPE_PERMEDIA2: tmp = PM2F_RD_PALETTE_WIDTH_8; if ((video & PM2F_HSYNC_MASK) == PM2F_HSYNC_ACT_LOW) tmp |= 4; /* invert hsync */ if ((video & PM2F_VSYNC_MASK) == PM2F_VSYNC_ACT_LOW) tmp |= 8; /* invert vsync */ pm2_RDAC_WR(p, PM2I_RD_MISC_CONTROL, tmp); break; case PM2_TYPE_PERMEDIA2V: tmp = 0; if ((video & PM2F_HSYNC_MASK) == PM2F_HSYNC_ACT_LOW) tmp |= 1; /* invert hsync */ if ((video & PM2F_VSYNC_MASK) == PM2F_VSYNC_ACT_LOW) tmp |= 4; /* invert vsync */ pm2v_RDAC_WR(p, PM2VI_RD_SYNC_CONTROL, tmp); break; }}/* * pm2fb_check_var - Optional function. Validates a var passed in. * @var: frame buffer variable screen structure * @info: frame buffer structure that represents a single frame buffer * * Checks to see if the hardware supports the state requested by * var passed in. * * Returns negative errno on error, or zero on success. */static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){ u32 lpitch; if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 && var->bits_per_pixel != 24 && var->bits_per_pixel != 32) { DPRINTK("depth not supported: %u\n", var->bits_per_pixel); return -EINVAL; } if (var->xres != var->xres_virtual) { DPRINTK("virtual x resolution != " "physical x resolution not supported\n"); return -EINVAL; } if (var->yres > var->yres_virtual) { DPRINTK("virtual y resolution < " "physical y resolution not possible\n"); return -EINVAL; } /* permedia cannot blit over 2048 */ if (var->yres_virtual > 2047) { var->yres_virtual = 2047; } if (var->xoffset) { DPRINTK("xoffset not supported\n"); return -EINVAL; } if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { DPRINTK("interlace not supported\n"); return -EINVAL; } var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */ lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3); if (var->xres < 320 || var->xres > 1600) { DPRINTK("width not supported: %u\n", var->xres); return -EINVAL; } if (var->yres < 200 || var->yres > 1200) { DPRINTK("height not supported: %u\n", var->yres); return -EINVAL; } if (lpitch * var->yres_virtual > info->fix.smem_len) { DPRINTK("no memory for screen (%ux%ux%u)\n", var->xres, var->yres_virtual, var->bits_per_pixel); return -EINVAL; } if (PICOS2KHZ(var->pixclock) > PM2_MAX_PIXCLOCK) { DPRINTK("pixclock too high (%ldKHz)\n", PICOS2KHZ(var->pixclock)); return -EINVAL; } var->transp.offset = 0; var->transp.length = 0; switch (var->bits_per_pixel) { case 8: var->red.length = 8; var->green.length = 8; var->blue.length = 8; break; case 16: var->red.offset = 11; var->red.length = 5; var->green.offset = 5; var->green.length = 6; var->blue.offset = 0; var->blue.length = 5; break; case 32: var->transp.offset = 24; var->transp.length = 8; var->red.offset = 16; var->green.offset = 8; var->blue.offset = 0; var->red.length = 8; var->green.length = 8; var->blue.length = 8; break; case 24:#ifdef __BIG_ENDIAN var->red.offset = 0; var->blue.offset = 16;#else var->red.offset = 16; var->blue.offset = 0;#endif var->green.offset = 8; var->red.length = 8; var->green.length = 8; var->blue.length = 8; break; } var->height = -1; var->width = -1; var->accel_flags = 0; /* Can't mmap if this is on */ DPRINTK("Checking graphics mode at %dx%d depth %d\n", var->xres, var->yres, var->bits_per_pixel); return 0;}/** * pm2fb_set_par - Alters the hardware state. * @info: frame buffer structure that represents a single frame buffer * * Using the fb_var_screeninfo in fb_info we set the resolution of the * this particular framebuffer. */static int pm2fb_set_par(struct fb_info *info){ struct pm2fb_par *par = info->par; u32 pixclock; u32 width = (info->var.xres_virtual + 7) & ~7; u32 height = info->var.yres_virtual; u32 depth = (info->var.bits_per_pixel + 7) & ~7; u32 hsstart, hsend, hbend, htotal; u32 vsstart, vsend, vbend, vtotal; u32 stride; u32 base; u32 video = 0; u32 clrmode = PM2F_RD_COLOR_MODE_RGB | PM2F_RD_GUI_ACTIVE; u32 txtmap = 0; u32 pixsize = 0; u32 clrformat = 0; u32 misc = 1; /* 8-bit DAC */ u32 xres = (info->var.xres + 31) & ~31; int data64; reset_card(par); reset_config(par); clear_palette(par); if (par->memclock) set_memclock(par, par->memclock); depth = (depth > 32) ? 32 : depth; data64 = depth > 8 || par->type == PM2_TYPE_PERMEDIA2V; pixclock = PICOS2KHZ(info->var.pixclock); if (pixclock > PM2_MAX_PIXCLOCK) { DPRINTK("pixclock too high (%uKHz)\n", pixclock); return -EINVAL; } hsstart = to3264(info->var.right_margin, depth, data64); hsend = hsstart + to3264(info->var.hsync_len, depth, data64); hbend = hsend + to3264(info->var.left_margin, depth, data64); htotal = to3264(xres, depth, data64) + hbend - 1; vsstart = (info->var.lower_margin) ? info->var.lower_margin - 1 : 0; /* FIXME! */ vsend = info->var.lower_margin + info->var.vsync_len - 1; vbend = info->var.lower_margin + info->var.vsync_len + info->var.upper_margin; vtotal = info->var.yres + vbend - 1; stride = to3264(width, depth, 1); base = to3264(info->var.yoffset * xres + info->var.xoffset, depth, 1); if (data64) video |= PM2F_DATA_64_ENABLE; if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) { if (lowhsync) { DPRINTK("ignoring +hsync, using -hsync.\n"); video |= PM2F_HSYNC_ACT_LOW; } else video |= PM2F_HSYNC_ACT_HIGH; } else video |= PM2F_HSYNC_ACT_LOW; if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) { if (lowvsync) { DPRINTK("ignoring +vsync, using -vsync.\n"); video |= PM2F_VSYNC_ACT_LOW; } else video |= PM2F_VSYNC_ACT_HIGH; } else video |= PM2F_VSYNC_ACT_LOW; if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { DPRINTK("interlaced not supported\n"); return -EINVAL; } if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) video |= PM2F_LINE_DOUBLE; if ((info->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) video |= PM2F_VIDEO_ENABLE; par->video = video; info->fix.visual = (depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; info->fix.line_length = info->var.xres * depth / 8; info->cmap.len = 256; /* * Settings calculated. Now write them out. */ if (par->type == PM2_TYPE_PERMEDIA2V) { WAIT_FIFO(par, 1); pm2_WR(par, PM2VR_RD_INDEX_HIGH, 0); } set_aperture(par, depth); mb(); WAIT_FIFO(par, 19); switch (depth) { case 8: pm2_WR(par, PM2R_FB_READ_PIXEL, 0); clrformat = 0x2e; break; case 16: pm2_WR(par, PM2R_FB_READ_PIXEL, 1); clrmode |= PM2F_RD_TRUECOLOR | PM2F_RD_PIXELFORMAT_RGB565; txtmap = PM2F_TEXTEL_SIZE_16; pixsize = 1; clrformat = 0x70; misc |= 8; break; case 32: pm2_WR(par, PM2R_FB_READ_PIXEL, 2); clrmode |= PM2F_RD_TRUECOLOR | PM2F_RD_PIXELFORMAT_RGBA8888; txtmap = PM2F_TEXTEL_SIZE_32; pixsize = 2; clrformat = 0x20; misc |= 8; break; case 24: pm2_WR(par, PM2R_FB_READ_PIXEL, 4); clrmode |= PM2F_RD_TRUECOLOR | PM2F_RD_PIXELFORMAT_RGB888; txtmap = PM2F_TEXTEL_SIZE_24; pixsize = 4; clrformat = 0x20; misc |= 8; break; } pm2_WR(par, PM2R_FB_WRITE_MODE, PM2F_FB_WRITE_ENABLE); pm2_WR(par, PM2R_FB_READ_MODE, partprod(xres)); pm2_WR(par, PM2R_LB_READ_MODE, partprod(xres)); pm2_WR(par, PM2R_TEXTURE_MAP_FORMAT, txtmap | partprod(xres)); pm2_WR(par, PM2R_H_TOTAL, htotal); pm2_WR(par, PM2R_HS_START, hsstart); pm2_WR(par, PM2R_HS_END, hsend); pm2_WR(par, PM2R_HG_END, hbend); pm2_WR(par, PM2R_HB_END, hbend); pm2_WR(par, PM2R_V_TOTAL, vtotal); pm2_WR(par, PM2R_VS_START, vsstart); pm2_WR(par, PM2R_VS_END, vsend); pm2_WR(par, PM2R_VB_END, vbend); pm2_WR(par, PM2R_SCREEN_STRIDE, stride); wmb(); pm2_WR(par, PM2R_WINDOW_ORIGIN, 0); pm2_WR(par, PM2R_SCREEN_SIZE, (height << 16) | width); pm2_WR(par, PM2R_SCISSOR_MODE, PM2F_SCREEN_SCISSOR_ENABLE); wmb(); pm2_WR(par, PM2R_SCREEN_BASE, base); wmb(); set_video(par, video); WAIT_FIFO(par, 10); switch (par->type) { case PM2_TYPE_PERMEDIA2: pm2_RDAC_WR(par, PM2I_RD_COLOR_MODE, clrmode); pm2_RDAC_WR(par, PM2I_RD_COLOR_KEY_CONTROL, (depth == 8) ? 0 : PM2F_COLOR_KEY_TEST_OFF); break; case PM2_TYPE_PERMEDIA2V: pm2v_RDAC_WR(par, PM2VI_RD_DAC_CONTROL, 0); pm2v_RDAC_WR(par, PM2VI_RD_PIXEL_SIZE, pixsize); pm2v_RDAC_WR(par, PM2VI_RD_COLOR_FORMAT, clrformat); pm2v_RDAC_WR(par, PM2VI_RD_MISC_CONTROL, misc); pm2v_RDAC_WR(par, PM2VI_RD_OVERLAY_KEY, 0); break; } set_pixclock(par, pixclock); DPRINTK("Setting graphics mode at %dx%d depth %d\n", info->var.xres, info->var.yres, info->var.bits_per_pixel); return 0;}/** * pm2fb_setcolreg - Sets a color register. * @regno: boolean, 0 copy local, 1 get_user() function * @red: frame buffer colormap structure * @green: The green value which can be up to 16 bits wide * @blue: The blue value which can be up to 16 bits wide. * @transp: If supported the alpha value which can be up to 16 bits wide. * @info: frame buffer info structure * * Set a single color register. The values supplied have a 16 bit * magnitude which needs to be scaled in this function for the hardware. * Pretty much a direct lift from tdfxfb.c. * * Returns negative errno on error, or zero on success. */static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info){ struct pm2fb_par *par = info->par; if (regno >= info->cmap.len) /* no. of hw registers */ return -EINVAL; /* * Program hardware... do anything you want with transp */ /* grayscale works only partially under directcolor */ /* grayscale = 0.30*R + 0.59*G + 0.11*B */ if (info->var.grayscale) red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; /* Directcolor: * var->{color}.offset contains start of bitfield * var->{color}.length contains length of bitfield * {hardwarespecific} contains width of DAC * cmap[X] is programmed to * (X << red.offset) | (X << green.offset) | (X << blue.offset) * RAMDAC[X] is programmed to (red, green, blue) * * Pseudocolor: * uses offset = 0 && length = DAC register width. * var->{color}.offset is 0 * var->{color}.length contains widht of DAC * cmap is not used * DAC[X] is programmed to (red, green, blue) * Truecolor: * does not use RAMDAC (usually has 3 of them). * var->{color}.offset contains start of bitfield * var->{color}.length contains length of bitfield * cmap is programmed to * (red << red.offset) | (green << green.offset) | * (blue << blue.offset) | (transp << transp.offset) * RAMDAC does not exist */#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF -(val)) >> 16) switch (info->fix.visual) { case FB_VISUAL_TRUECOLOR: case FB_VISUAL_PSEUDOCOLOR: red = CNVT_TOHW(red, info->var.red.length); green = CNVT_TOHW(green, info->var.green.length); blue = CNVT_TOHW(blue, info->var.blue.length); transp = CNVT_TOHW(transp, info->var.transp.length); break; case FB_VISUAL_DIRECTCOLOR: /* example here assumes 8 bit DAC. Might be different * for your hardware */ red = CNVT_TOHW(red, 8); green = CNVT_TOHW(green, 8); blue = CNVT_TOHW(blue, 8); /* hey, there is bug in transp handling... */ transp = CNVT_TOHW(transp, 8); break; }#undef CNVT_TOHW /* Truecolor has hardware independent palette */ if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -