📄 pm3fb.c
字号:
switch (info->fix.visual) { case FB_VISUAL_PSEUDOCOLOR: fgx = image->fg_color; bgx = image->bg_color; break; case FB_VISUAL_TRUECOLOR: default: fgx = par->palette[image->fg_color]; bgx = par->palette[image->bg_color]; break; } if (image->depth != 1) { cfb_imageblit(info, image); return; } if (info->var.bits_per_pixel == 8) { fgx |= fgx << 8; bgx |= bgx << 8; } if (info->var.bits_per_pixel <= 16) { fgx |= fgx << 16; bgx |= bgx << 16; } PM3_WAIT(par, 7); PM3_WRITE_REG(par, PM3ForegroundColor, fgx); PM3_WRITE_REG(par, PM3BackgroundColor, bgx); /* ROP Ox3 is GXcopy */ PM3_WRITE_REG(par, PM3Config2D, PM3Config2D_UserScissorEnable | PM3Config2D_UseConstantSource | PM3Config2D_ForegroundROPEnable | PM3Config2D_ForegroundROP(0x3) | PM3Config2D_OpaqueSpan | PM3Config2D_FBWriteEnable); PM3_WRITE_REG(par, PM3ScissorMinXY, ((image->dy & 0x0fff) << 16) | (image->dx & 0x0fff)); PM3_WRITE_REG(par, PM3ScissorMaxXY, (((image->dy + image->height) & 0x0fff) << 16) | ((image->dx + image->width) & 0x0fff)); PM3_WRITE_REG(par, PM3RectanglePosition, PM3RectanglePosition_XOffset(image->dx) | PM3RectanglePosition_YOffset(image->dy)); PM3_WRITE_REG(par, PM3Render2D, PM3Render2D_XPositive | PM3Render2D_YPositive | PM3Render2D_Operation_SyncOnBitMask | PM3Render2D_SpanOperation | PM3Render2D_Width(image->width) | PM3Render2D_Height(image->height)); while (height--) { int width = ((image->width + 7) >> 3) + info->pixmap.scan_align - 1; width >>= 2; while (width >= PM3_FIFO_SIZE) { int i = PM3_FIFO_SIZE - 1; PM3_WAIT(par, PM3_FIFO_SIZE); while (i--) { PM3_WRITE_REG(par, PM3BitMaskPattern, *src); src++; } width -= PM3_FIFO_SIZE - 1; } PM3_WAIT(par, width + 1); while (width--) { PM3_WRITE_REG(par, PM3BitMaskPattern, *src); src++; } }}/* end of acceleration functions *//* * Hardware Cursor support. */static const u8 cursor_bits_lookup[16] = { 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54, 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55};static int pm3fb_cursor(struct fb_info *info, struct fb_cursor *cursor){ struct pm3_par *par = info->par; u8 mode; if (!hwcursor) return -EINVAL; /* just to force soft_cursor() call */ /* Too large of a cursor or wrong bpp :-( */ if (cursor->image.width > 64 || cursor->image.height > 64 || cursor->image.depth > 1) return -EINVAL; mode = PM3RD_CursorMode_TYPE_X; if (cursor->enable) mode |= PM3RD_CursorMode_CURSOR_ENABLE; PM3_WRITE_DAC_REG(par, PM3RD_CursorMode, mode); /* * If the cursor is not be changed this means either we want the * current cursor state (if enable is set) or we want to query what * we can do with the cursor (if enable is not set) */ if (!cursor->set) return 0; if (cursor->set & FB_CUR_SETPOS) { int x = cursor->image.dx - info->var.xoffset; int y = cursor->image.dy - info->var.yoffset; PM3_WRITE_DAC_REG(par, PM3RD_CursorXLow, x & 0xff); PM3_WRITE_DAC_REG(par, PM3RD_CursorXHigh, (x >> 8) & 0xf); PM3_WRITE_DAC_REG(par, PM3RD_CursorYLow, y & 0xff); PM3_WRITE_DAC_REG(par, PM3RD_CursorYHigh, (y >> 8) & 0xf); } if (cursor->set & FB_CUR_SETHOT) { PM3_WRITE_DAC_REG(par, PM3RD_CursorHotSpotX, cursor->hot.x & 0x3f); PM3_WRITE_DAC_REG(par, PM3RD_CursorHotSpotY, cursor->hot.y & 0x3f); } if (cursor->set & FB_CUR_SETCMAP) { u32 fg_idx = cursor->image.fg_color; u32 bg_idx = cursor->image.bg_color; struct fb_cmap cmap = info->cmap; /* the X11 driver says one should use these color registers */ PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(39), cmap.red[fg_idx] >> 8 ); PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(40), cmap.green[fg_idx] >> 8 ); PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(41), cmap.blue[fg_idx] >> 8 ); PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(42), cmap.red[bg_idx] >> 8 ); PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(43), cmap.green[bg_idx] >> 8 ); PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(44), cmap.blue[bg_idx] >> 8 ); } if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) { u8 *bitmap = (u8 *)cursor->image.data; u8 *mask = (u8 *)cursor->mask; int i; int pos = PM3RD_CursorPattern(0); for (i = 0; i < cursor->image.height; i++) { int j = (cursor->image.width + 7) >> 3; int k = 8 - j; for (; j > 0; j--) { u8 data = *bitmap ^ *mask; if (cursor->rop == ROP_COPY) data = *mask & *bitmap; /* Upper 4 bits of bitmap data */ PM3_WRITE_DAC_REG(par, pos++, cursor_bits_lookup[data >> 4] | (cursor_bits_lookup[*mask >> 4] << 1)); /* Lower 4 bits of bitmap */ PM3_WRITE_DAC_REG(par, pos++, cursor_bits_lookup[data & 0xf] | (cursor_bits_lookup[*mask & 0xf] << 1)); bitmap++; mask++; } for (; k > 0; k--) { PM3_WRITE_DAC_REG(par, pos++, 0); PM3_WRITE_DAC_REG(par, pos++, 0); } } while (pos < PM3RD_CursorPattern(1024)) PM3_WRITE_DAC_REG(par, pos++, 0); } return 0;}/* write the mode to registers */static void pm3fb_write_mode(struct fb_info *info){ struct pm3_par *par = info->par; char tempsync = 0x00; char tempmisc = 0x00; const u32 hsstart = info->var.right_margin; const u32 hsend = hsstart + info->var.hsync_len; const u32 hbend = hsend + info->var.left_margin; const u32 xres = (info->var.xres + 31) & ~31; const u32 htotal = xres + hbend; const u32 vsstart = info->var.lower_margin; const u32 vsend = vsstart + info->var.vsync_len; const u32 vbend = vsend + info->var.upper_margin; const u32 vtotal = info->var.yres + vbend; const u32 width = (info->var.xres_virtual + 7) & ~7; const unsigned bpp = info->var.bits_per_pixel; PM3_WAIT(par, 20); PM3_WRITE_REG(par, PM3MemBypassWriteMask, 0xffffffff); PM3_WRITE_REG(par, PM3Aperture0, 0x00000000); PM3_WRITE_REG(par, PM3Aperture1, 0x00000000); PM3_WRITE_REG(par, PM3FIFODis, 0x00000007); PM3_WRITE_REG(par, PM3HTotal, pm3fb_shift_bpp(bpp, htotal - 1)); PM3_WRITE_REG(par, PM3HsEnd, pm3fb_shift_bpp(bpp, hsend)); PM3_WRITE_REG(par, PM3HsStart, pm3fb_shift_bpp(bpp, hsstart)); PM3_WRITE_REG(par, PM3HbEnd, pm3fb_shift_bpp(bpp, hbend)); PM3_WRITE_REG(par, PM3HgEnd, pm3fb_shift_bpp(bpp, hbend)); PM3_WRITE_REG(par, PM3ScreenStride, pm3fb_shift_bpp(bpp, width)); PM3_WRITE_REG(par, PM3VTotal, vtotal - 1); PM3_WRITE_REG(par, PM3VsEnd, vsend - 1); PM3_WRITE_REG(par, PM3VsStart, vsstart - 1); PM3_WRITE_REG(par, PM3VbEnd, vbend); switch (bpp) { case 8: PM3_WRITE_REG(par, PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_8BIT); PM3_WRITE_REG(par, PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_8BIT); break; case 16:#ifndef __BIG_ENDIAN PM3_WRITE_REG(par, PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_16BIT); PM3_WRITE_REG(par, PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_16BIT);#else PM3_WRITE_REG(par, PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_16BIT | PM3ByApertureMode_BYTESWAP_BADC); PM3_WRITE_REG(par, PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_16BIT | PM3ByApertureMode_BYTESWAP_BADC);#endif /* ! __BIG_ENDIAN */ break; case 32:#ifndef __BIG_ENDIAN PM3_WRITE_REG(par, PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_32BIT); PM3_WRITE_REG(par, PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_32BIT);#else PM3_WRITE_REG(par, PM3ByAperture1Mode, PM3ByApertureMode_PIXELSIZE_32BIT | PM3ByApertureMode_BYTESWAP_DCBA); PM3_WRITE_REG(par, PM3ByAperture2Mode, PM3ByApertureMode_PIXELSIZE_32BIT | PM3ByApertureMode_BYTESWAP_DCBA);#endif /* ! __BIG_ENDIAN */ break; default: DPRINTK("Unsupported depth %d\n", bpp); break; } /* * Oxygen VX1 - it appears that setting PM3VideoControl and * then PM3RD_SyncControl to the same SYNC settings undoes * any net change - they seem to xor together. Only set the * sync options in PM3RD_SyncControl. --rmk */ { unsigned int video = par->video; video &= ~(PM3VideoControl_HSYNC_MASK | PM3VideoControl_VSYNC_MASK); video |= PM3VideoControl_HSYNC_ACTIVE_HIGH | PM3VideoControl_VSYNC_ACTIVE_HIGH; PM3_WRITE_REG(par, PM3VideoControl, video); } PM3_WRITE_REG(par, PM3VClkCtl, (PM3_READ_REG(par, PM3VClkCtl) & 0xFFFFFFFC)); PM3_WRITE_REG(par, PM3ScreenBase, par->base); PM3_WRITE_REG(par, PM3ChipConfig, (PM3_READ_REG(par, PM3ChipConfig) & 0xFFFFFFFD)); wmb(); { unsigned char uninitialized_var(m); /* ClkPreScale */ unsigned char uninitialized_var(n); /* ClkFeedBackScale */ unsigned char uninitialized_var(p); /* ClkPostScale */ unsigned long pixclock = PICOS2KHZ(info->var.pixclock); (void)pm3fb_calculate_clock(pixclock, &m, &n, &p); DPRINTK("Pixclock: %ld, Pre: %d, Feedback: %d, Post: %d\n", pixclock, (int) m, (int) n, (int) p); PM3_WRITE_DAC_REG(par, PM3RD_DClk0PreScale, m); PM3_WRITE_DAC_REG(par, PM3RD_DClk0FeedbackScale, n); PM3_WRITE_DAC_REG(par, PM3RD_DClk0PostScale, p); } /* PM3_WRITE_DAC_REG(par, PM3RD_IndexControl, 0x00); */ /* PM3_SLOW_WRITE_REG(par, PM3RD_IndexControl, 0x00); */ if ((par->video & PM3VideoControl_HSYNC_MASK) == PM3VideoControl_HSYNC_ACTIVE_HIGH) tempsync |= PM3RD_SyncControl_HSYNC_ACTIVE_HIGH; if ((par->video & PM3VideoControl_VSYNC_MASK) == PM3VideoControl_VSYNC_ACTIVE_HIGH) tempsync |= PM3RD_SyncControl_VSYNC_ACTIVE_HIGH; PM3_WRITE_DAC_REG(par, PM3RD_SyncControl, tempsync); DPRINTK("PM3RD_SyncControl: %d\n", tempsync); PM3_WRITE_DAC_REG(par, PM3RD_DACControl, 0x00); switch (pm3fb_depth(&info->var)) { case 8: PM3_WRITE_DAC_REG(par, PM3RD_PixelSize, PM3RD_PixelSize_8_BIT_PIXELS); PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat, PM3RD_ColorFormat_CI8_COLOR | PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW); tempmisc |= PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE; break; case 12: PM3_WRITE_DAC_REG(par, PM3RD_PixelSize, PM3RD_PixelSize_16_BIT_PIXELS); PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat, PM3RD_ColorFormat_4444_COLOR | PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW | PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE); tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE | PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE; break; case 15: PM3_WRITE_DAC_REG(par, PM3RD_PixelSize, PM3RD_PixelSize_16_BIT_PIXELS); PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat, PM3RD_ColorFormat_5551_FRONT_COLOR | PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW | PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE); tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE | PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE; break; case 16: PM3_WRITE_DAC_REG(par, PM3RD_PixelSize, PM3RD_PixelSize_16_BIT_PIXELS); PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat, PM3RD_ColorFormat_565_FRONT_COLOR | PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW | PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE); tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE | PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE; break; case 32: PM3_WRITE_DAC_REG(par, PM3RD_PixelSize, PM3RD_PixelSize_32_BIT_PIXELS); PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat, PM3RD_ColorFormat_8888_COLOR | PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW); tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE | PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE; break; } PM3_WRITE_DAC_REG(par, PM3RD_MiscControl, tempmisc);}/* * hardware independent functions */static int pm3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){ u32 lpitch; unsigned bpp = var->red.length + var->green.length + var->blue.length + var->transp.length; if (bpp != var->bits_per_pixel) { /* set predefined mode for bits_per_pixel settings */ switch (var->bits_per_pixel) { case 8: var->red.length = 8; var->green.length = 8; var->blue.length = 8; var->red.offset = 0; var->green.offset = 0; var->blue.offset = 0; var->transp.offset = 0; var->transp.length = 0; break; case 16: var->red.length = 5; var->blue.length = 5; var->green.length = 6; var->transp.length = 0; break; case 32: var->red.length = 8; var->green.length = 8; var->blue.length = 8; var->transp.length = 8; break; default: DPRINTK("depth not supported: %u\n", var->bits_per_pixel); return -EINVAL; } } /* it is assumed BGRA order */ if (var->bits_per_pixel > 8 ) { var->blue.offset = 0; var->green.offset = var->blue.length; var->red.offset = var->green.offset + var->green.length; var->transp.offset = var->red.offset + var->red.length; } var->height = -1; var->width = -1; 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; } 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 + 31) & ~31; /* could sometimes be 8 */ lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3); if (var->xres < 200 || var->xres > 2048) { DPRINTK("width not supported: %u\n", var->xres); return -EINVAL; } if (var->yres < 200 || var->yres > 4095) { 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) > PM3_MAX_PIXCLOCK) { DPRINTK("pixclock too high (%ldKHz)\n", PICOS2KHZ(var->pixclock)); return -EINVAL; } 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;}static int pm3fb_set_par(struct fb_info *info){ struct pm3_par *par = info->par; const u32 xres = (info->var.xres + 31) & ~31; const unsigned bpp = info->var.bits_per_pixel; par->base = pm3fb_shift_bpp(bpp, (info->var.yoffset * xres) + info->var.xoffset); par->video = 0; if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) par->video |= PM3VideoControl_HSYNC_ACTIVE_HIGH; else par->video |= PM3VideoControl_HSYNC_ACTIVE_LOW; if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) par->video |= PM3VideoControl_VSYNC_ACTIVE_HIGH; else par->video |= PM3VideoControl_VSYNC_ACTIVE_LOW; if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) par->video |= PM3VideoControl_LINE_DOUBLE_ON; if ((info->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) par->video |= PM3VideoControl_ENABLE; else DPRINTK("PM3Video disabled\n"); switch (bpp) { case 8: par->video |= PM3VideoControl_PIXELSIZE_8BIT; break; case 16: par->video |= PM3VideoControl_PIXELSIZE_16BIT; break; case 32: par->video |= PM3VideoControl_PIXELSIZE_32BIT; break; default: DPRINTK("Unsupported depth\n"); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -