📄 ep93xxfb.c
字号:
outl( pal, (COLOR_LUT+(regno<<2)) ); cont = inl(LUTCONT); if ((cont&LUTCONT_STAT && cont&LUTCONT_RAM1) || (!(cont&LUTCONT_STAT) && !(cont&LUTCONT_RAM1))) { // LUT switch is no longer pending // We do not know if write to LUT above really went // to currently active LUT. So need to make sure that // data gets into inactive LUT and switch LUTs. // // But currently inactive LUT may be out of date // in more entries than just last write. // Need to update currently inactive LUT for all writes // which went to currently active LUT. // Fully update the LUT now, which is a simpler policy // than trying to track writes and do partial update of LUT. // (Worstcase impact: we update palette every frame) for (i=0; i< 256; i++) // Update inactive LUT outl( master_palette[i], (COLOR_LUT+(i<<2)) ); // Switch active LUTs next frame outl( cont ^ LUTCONT_RAM1, LUTCONT ); }}static inline voidep93xxfb_palette_read(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *trans){ // Only supports color LUT, not gray LUT unsigned int pal; // Read only needs to access master palette, not hw palettes. pal = master_palette[regno]; //TBD LCD mode may change LUT from R/G/B order to B/G/R order *red = (pal >> 8) & 0xFF00; *green = pal & 0xFF00; *blue = (pal << 8) & 0xFF00; *trans = 0;}//-----------------------------------------------------------------------------// Helper functions for fb driver//-----------------------------------------------------------------------------static intep93xxfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *trans, struct fb_info *info){ if (regno >= mypar.palette_size) return 1; ep93xxfb_palette_read(regno, red, green, blue, trans); return 0;}static inline u_intchan_to_field(u_int chan, struct fb_bitfield *bf){ chan &= 0xffff; chan >>= 16 - bf->length; return chan << bf->offset;}static intep93xxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int trans, struct fb_info *info){ u_int val; if (regno >= mypar.palette_size) return 1; switch (info->disp->visual) { case FB_VISUAL_TRUECOLOR: if (regno < 16) { u16 *pal = info->pseudo_palette; val = chan_to_field(red, &info->var.red); val |= chan_to_field(green, &info->var.green); val |= chan_to_field(blue, &info->var.blue); pal[regno] = val; } break; case FB_VISUAL_PSEUDOCOLOR: ep93xxfb_palette_write(regno, red, green, blue, trans); break; } return 0;}//TBD Warning: fbmem.c ioctl could result in any of the helper functions being//TBD called with con=-1, which happens when info->display_fg == NULL,//TBD which presumably is only during initialization of fbcon.//TBD Is there any other condition under which con=-1?//TBD Maybe we do not even need to support it!static intep93xxfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ int err = 0; //TBD does not expect call with con=-1 if currcon!=-1 if (con == -1) DPRINTK("get_cmap called with con=-1\n"); DPRINTK("mypar.visual=%d\n", mypar.visual); if (con == mypar.currcon) err = fb_get_cmap(cmap, kspc, ep93xxfb_getcolreg, info); else if (fb_display[con].cmap.len) fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else fb_copy_cmap(fb_default_cmap(mypar.palette_size), cmap, kspc ? 0 : 2); return err;}static intep93xxfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ int err = 0; // // What kind of request is this??? // if (con == -1) { DPRINTK("ERROR set_cmap called with con=-1\n"); return(-1); } DPRINTK("mypar.visual=%d\n", mypar.visual); if (!fb_display[con].cmap.len) err = fb_alloc_cmap(&fb_display[con].cmap, mypar.palette_size, 0); if (!err) { if (con == mypar.currcon) err = fb_set_cmap(cmap, kspc, ep93xxfb_setcolreg, info); fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); } return err;}static unsigned long cursor_data[64][4];static voidep93xxfb_cursor(struct ep93xx_cursor *cursor){ unsigned long data[64 * 4]; long i, x, y, save; if (cursor->flags & CURSOR_OFF) outl(inl(CURSORXYLOC) & ~0x00008000, CURSORXYLOC); if (cursor->flags & CURSOR_SETSHAPE) { copy_from_user(data, cursor->data, cursor->width * cursor->height / 4); save = inl(CURSORXYLOC); outl(save & ~0x00008000, CURSORXYLOC); for (y = 0, i = 0; y < cursor->height; y++) { for (x = 0; x < cursor->width; x += 16) cursor_data[y][x] = data[i++]; } outl(virt_to_phys(cursor_data), CURSOR_ADR_START); outl(virt_to_phys(cursor_data), CURSOR_ADR_RESET); outl(0x00000300 | ((cursor->height - 1) << 2) | ((cursor->width - 1) >> 4), CURSORSIZE); outl(save, CURSORXYLOC); } if (cursor->flags & CURSOR_SETCOLOR) { outl(cursor->color1, CURSORCOLOR1); outl(cursor->color2, CURSORCOLOR2); outl(cursor->blinkcolor1, CURSORBLINK1); outl(cursor->blinkcolor2, CURSORBLINK2); } if (cursor->flags & CURSOR_BLINK) { if (cursor->blinkrate) outl(0x00000100 | cursor->blinkrate, CURSORBLINK); else outl(0x000000ff, CURSORBLINK); } if (cursor->flags & CURSOR_MOVE) { x = (inl(HACTIVESTRTSTOP) & 0x000003ff) - cursor->dx - 2; y = (inl(VACTIVESTRTSTOP) & 0x000003ff) - cursor->dy; outl((inl(CURSORXYLOC) & 0x8000) | (y << 16) | x, CURSORXYLOC); } if (cursor->flags & CURSOR_ON) outl(inl(CURSORXYLOC) | 0x00008000, CURSORXYLOC);}#ifdef CONFIG_EP93XX_GRAPHICS#ifdef CONFIG_FB_EP93XX_8BPP#define BITS_PER_PIXEL 8#define BYTES_PER_PIXEL 1#define PIXEL_MASK 3#define PIXEL_SHIFT 2#define PIXEL_FORMAT 0x00040000#endif#ifdef CONFIG_FB_EP93XX_16BPP_565#define BITS_PER_PIXEL 16#define BYTES_PER_PIXEL 2#define PIXEL_MASK 1#define PIXEL_SHIFT 1#define PIXEL_FORMAT 0x00080000#endif#define BYTES_PER_LINE (fb_info.var.xres * BYTES_PER_PIXEL)static DECLARE_WAIT_QUEUE_HEAD(ep93xxfb_wait_in);static voidep93xxfb_irq_handler(int i, void *blah, struct pt_regs *regs){ outl(0x00000000, BLOCKCTRL); wake_up_interruptible(&ep93xxfb_wait_in);}static voidep93xxfb_wait(void){ DECLARE_WAITQUEUE(wait, current); add_wait_queue(&ep93xxfb_wait_in, &wait); current->state = TASK_INTERRUPTIBLE; while (inl(BLOCKCTRL) & 0x00000001) { schedule(); current->state = TASK_INTERRUPTIBLE; } remove_wait_queue(&ep93xxfb_wait_in, &wait); current->state = TASK_RUNNING;}static unsigned char pucBlitBuf[4096];static intep93xxfb_blit(struct ep93xx_blit *blit){ unsigned long value = 0, size, dx1, dx2, dy1, sx1, sx2, sy1; if ((blit->dx >= fb_info.var.xres) || (blit->dy >= fb_info.var.yres) || ((blit->dx + blit->width - 1) >= fb_info.var.xres) || ((blit->dy + blit->height - 1) >= fb_info.var.yres)) return -EFAULT; value = blit->flags & (BLIT_TRANSPARENT | BLIT_MASK_MASK | BLIT_DEST_MASK | BLIT_1BPP_SOURCE); if ((blit->flags & BLIT_SOURCE_MASK) == BLIT_SOURCE_MEMORY) { if (blit->flags & BLIT_1BPP_SOURCE) { size = blit->swidth * blit->height / 8; if (size <= 4096) copy_from_user(pucBlitBuf, blit->data, size); else { for (size = blit->height; size; ) { blit->height = 32768 / blit->swidth; if (blit->height > size) blit->height = size; ep93xxfb_blit(blit); blit->dy += blit->height; blit->data += blit->swidth * blit->height / 8; size -= blit->height; } return 0; } if (blit->flags & BLIT_TRANSPARENT) value ^= 0x00004000; outl(0x00000007, SRCPIXELSTRT); outl(blit->swidth >> 5, SRCLINELENGTH); outl((blit->width - 1) >> 5, BLKSRCWIDTH); outl(blit->bgcolor, BACKGROUND); } else { size = blit->swidth * blit->height * BYTES_PER_PIXEL; if (size <= 4096) copy_from_user(pucBlitBuf, blit->data, size); else { for (size = blit->height; size; ) { blit->height = 4096 / BYTES_PER_PIXEL / blit->swidth; if (blit->height > size) blit->height = size; ep93xxfb_blit(blit); blit->dy += blit->height; blit->data += blit->swidth * blit->height * BYTES_PER_PIXEL; size -= blit->height; } return 0; } outl(0x00000000, SRCPIXELSTRT); outl(blit->swidth >> PIXEL_SHIFT, SRCLINELENGTH); outl((blit->width - 1) >> PIXEL_SHIFT, BLKSRCWIDTH); } outl(virt_to_phys(pucBlitBuf), BLKSRCSTRT); dx1 = blit->dx; dy1 = blit->dy; dx2 = blit->dx + blit->width - 1; } else { if ((blit->sx >= fb_info.var.xres) || (blit->sy >= fb_info.var.yres) || ((blit->sx + blit->width - 1) >= fb_info.var.xres) || ((blit->sy + blit->height - 1) >= fb_info.var.yres)) return -EFAULT; if ((blit->dy == blit->sy) && (blit->dx == blit->sx)) return 0; if ((blit->dy == blit->sy) && (blit->dx > blit->sx) && (blit->dx < (blit->sx + blit->width - 1))) { dx1 = blit->dx + blit->width - 1; dx2 = blit->dx; sx1 = blit->sx + blit->width - 1; sx2 = blit->sx; value |= 0x000000a0; } else { dx1 = blit->dx; dx2 = blit->dx + blit->width - 1; sx1 = blit->sx; sx2 = blit->sx + blit->width - 1; } if (blit->dy <= blit->sy) { dy1 = blit->dy; sy1 = blit->sy; } else { dy1 = blit->dy + blit->height - 1; sy1 = blit->sy + blit->height - 1; value |= 0x00000140; } outl(((sx1 & PIXEL_MASK) * BITS_PER_PIXEL) | (((sx2 & PIXEL_MASK) * BITS_PER_PIXEL) << 16), SRCPIXELSTRT); outl(inl(VIDSCRNPAGE) + (sy1 * BYTES_PER_LINE) + ((sx1 * BYTES_PER_PIXEL) & ~PIXEL_MASK), BLKSRCSTRT); outl(BYTES_PER_LINE / 4, SRCLINELENGTH); if (sx1 < sx2) outl((sx2 >> PIXEL_SHIFT) - (sx1 >> PIXEL_SHIFT), BLKSRCWIDTH); else outl((sx1 >> PIXEL_SHIFT) - (sx2 >> PIXEL_SHIFT), BLKSRCWIDTH); } outl(((dx1 & PIXEL_MASK) * BITS_PER_PIXEL) | (((dx2 & PIXEL_MASK) * BITS_PER_PIXEL) << 16), DESTPIXELSTRT); outl(inl(VIDSCRNPAGE) + (dy1 * BYTES_PER_LINE) + ((dx1 * BYTES_PER_PIXEL) & ~PIXEL_MASK), BLKDSTSTRT); outl(BYTES_PER_LINE / 4, DESTLINELENGTH); if (dx1 < dx2) outl((dx2 >> PIXEL_SHIFT) - (dx1 >> PIXEL_SHIFT), BLKDESTWIDTH); else outl((dx1 >> PIXEL_SHIFT) - (dx2 >> PIXEL_SHIFT), BLKDESTWIDTH); outl(blit->height - 1, BLKDESTHEIGHT); outl(blit->fgcolor, BLOCKMASK); outl(blit->transcolor, TRANSPATTRN); outl(value | PIXEL_FORMAT | 0x00000003, BLOCKCTRL); ep93xxfb_wait(); return 0;}static intep93xxfb_fill(struct ep93xx_fill *fill){ if ((fill->dx >= fb_info.var.xres) || (fill->dy >= fb_info.var.yres)) return -EFAULT; if ((fill->dx + fill->width - 1) >= fb_info.var.xres) fill->width = fb_info.var.xres - fill->dx; if ((fill->dy + fill->height - 1) >= fb_info.var.yres) fill->height = fb_info.var.yres - fill->dy; outl(mypar.p_screen_base + (fill->dy * BYTES_PER_LINE) + ((fill->dx * BYTES_PER_PIXEL) & ~PIXEL_MASK), BLKDSTSTRT); outl(((fill->dx & PIXEL_MASK) * BITS_PER_PIXEL) | ((((fill->dx + fill->width - 1) & PIXEL_MASK) * BITS_PER_PIXEL) << 16), DESTPIXELSTRT); outl(BYTES_PER_LINE / 4, DESTLINELENGTH); outl(((fill->dx + fill->width - 1) >> PIXEL_SHIFT) - (fill->dx >> PIXEL_SHIFT), BLKDESTWIDTH); outl(fill->height - 1, BLKDESTHEIGHT); outl(fill->color, BLOCKMASK); outl(PIXEL_FORMAT | 0x0000000b, BLOCKCTRL); ep93xxfb_wait(); return 0;}static unsigned longisqrt(unsigned long a){ unsigned long rem = 0; unsigned long root = 0; int i; for (i = 0; i < 16; i++) { root <<= 1; rem = ((rem << 2) + (a >> 30)); a <<= 2; root++; if (root <= rem) { rem -= root; root++; } else root--; } return root >> 1;}static intep93xxfb_line(struct ep93xx_line *line){ unsigned long value = 0; long dx, dy, count, xinc, yinc, xval, yval, incr; if ((line->x1 >= fb_info.var.xres) || (line->x2 >= fb_info.var.xres) || (line->y1 >= fb_info.var.yres) || (line->y2 >= fb_info.var.yres)) return -EFAULT; dx = line->x2 - line->x1; if (dx < 0) { value |= 0x00000020; dx *= -1; } dy = line->y2 - line->y1; if (dy < 0) { value |= 0x00000040; dy *= -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -