📄 tgafb.c
字号:
if (f >= TGA_PLL_MAX_FREQ / 2) shift = 0; else if (f >= TGA_PLL_MAX_FREQ / 4) shift = 1; else shift = 2; TGA_WRITE_REG(par, shift & 1, TGA_CLOCK_REG); TGA_WRITE_REG(par, shift >> 1, TGA_CLOCK_REG); for (r = 0 ; r < 10 ; r++) TGA_WRITE_REG(par, 0, TGA_CLOCK_REG); if (f <= 120000) { TGA_WRITE_REG(par, 0, TGA_CLOCK_REG); TGA_WRITE_REG(par, 0, TGA_CLOCK_REG); } else if (f <= 200000) { TGA_WRITE_REG(par, 1, TGA_CLOCK_REG); TGA_WRITE_REG(par, 0, TGA_CLOCK_REG); } else { TGA_WRITE_REG(par, 0, TGA_CLOCK_REG); TGA_WRITE_REG(par, 1, TGA_CLOCK_REG); } TGA_WRITE_REG(par, 1, TGA_CLOCK_REG); TGA_WRITE_REG(par, 0, TGA_CLOCK_REG); TGA_WRITE_REG(par, 0, TGA_CLOCK_REG); TGA_WRITE_REG(par, 1, TGA_CLOCK_REG); TGA_WRITE_REG(par, 0, TGA_CLOCK_REG); TGA_WRITE_REG(par, 1, TGA_CLOCK_REG); target = (f << shift) / TGA_PLL_BASE_FREQ; min_diff = TGA_PLL_MAX_FREQ; r = 7 / target; if (!r) r = 1; base = target * r; while (base < 449) { for (n = base < 7 ? 7 : base; n < base + target && n < 449; n++) { m = ((n + 3) / 7) - 1; a = 0; DIFFCHECK((m + 1) * 7); m++; DIFFCHECK((m + 1) * 7); m = (n / 6) - 1; if ((a = n % 6)) DIFFCHECK(n); } r++; base += target; } vr--; for (r = 0; r < 8; r++) TGA_WRITE_REG(par, (vm >> r) & 1, TGA_CLOCK_REG); for (r = 0; r < 8 ; r++) TGA_WRITE_REG(par, (va >> r) & 1, TGA_CLOCK_REG); for (r = 0; r < 7 ; r++) TGA_WRITE_REG(par, (vr >> r) & 1, TGA_CLOCK_REG); TGA_WRITE_REG(par, ((vr >> 7) & 1)|2, TGA_CLOCK_REG);}/** * tgafb_setcolreg - Optional function. 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 */static inttgafb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info){ struct tga_par *par = (struct tga_par *) info->par; int tga_bus_pci = TGA_BUS_PCI(par->dev); int tga_bus_tc = TGA_BUS_TC(par->dev); if (regno > 255) return 1; red >>= 8; green >>= 8; blue >>= 8; if (par->tga_type == TGA_TYPE_8PLANE && tga_bus_pci) { BT485_WRITE(par, regno, BT485_ADDR_PAL_WRITE); TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG); TGA_WRITE_REG(par, red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG); TGA_WRITE_REG(par, green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG); TGA_WRITE_REG(par, blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG); } else if (par->tga_type == TGA_TYPE_8PLANE && tga_bus_tc) { BT459_LOAD_ADDR(par, regno); TGA_WRITE_REG(par, BT459_PALETTE << 2, TGA_RAMDAC_SETUP_REG); TGA_WRITE_REG(par, red, TGA_RAMDAC_REG); TGA_WRITE_REG(par, green, TGA_RAMDAC_REG); TGA_WRITE_REG(par, blue, TGA_RAMDAC_REG); } else { if (regno < 16) { u32 value = (regno << 16) | (regno << 8) | regno; ((u32 *)info->pseudo_palette)[regno] = value; } BT463_LOAD_ADDR(par, regno); TGA_WRITE_REG(par, BT463_PALETTE << 2, TGA_RAMDAC_SETUP_REG); TGA_WRITE_REG(par, red, TGA_RAMDAC_REG); TGA_WRITE_REG(par, green, TGA_RAMDAC_REG); TGA_WRITE_REG(par, blue, TGA_RAMDAC_REG); } return 0;}/** * tgafb_blank - Optional function. Blanks the display. * @blank_mode: the blank mode we want. * @info: frame buffer structure that represents a single frame buffer */static inttgafb_blank(int blank, struct fb_info *info){ struct tga_par *par = (struct tga_par *) info->par; u32 vhcr, vvcr, vvvr; unsigned long flags; local_irq_save(flags); vhcr = TGA_READ_REG(par, TGA_HORIZ_REG); vvcr = TGA_READ_REG(par, TGA_VERT_REG); vvvr = TGA_READ_REG(par, TGA_VALID_REG); vvvr &= ~(TGA_VALID_VIDEO | TGA_VALID_BLANK); switch (blank) { case FB_BLANK_UNBLANK: /* Unblanking */ if (par->vesa_blanked) { TGA_WRITE_REG(par, vhcr & 0xbfffffff, TGA_HORIZ_REG); TGA_WRITE_REG(par, vvcr & 0xbfffffff, TGA_VERT_REG); par->vesa_blanked = 0; } TGA_WRITE_REG(par, vvvr | TGA_VALID_VIDEO, TGA_VALID_REG); break; case FB_BLANK_NORMAL: /* Normal blanking */ TGA_WRITE_REG(par, vvvr | TGA_VALID_VIDEO | TGA_VALID_BLANK, TGA_VALID_REG); break; case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */ TGA_WRITE_REG(par, vvcr | 0x40000000, TGA_VERT_REG); TGA_WRITE_REG(par, vvvr | TGA_VALID_BLANK, TGA_VALID_REG); par->vesa_blanked = 1; break; case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */ TGA_WRITE_REG(par, vhcr | 0x40000000, TGA_HORIZ_REG); TGA_WRITE_REG(par, vvvr | TGA_VALID_BLANK, TGA_VALID_REG); par->vesa_blanked = 1; break; case FB_BLANK_POWERDOWN: /* Poweroff */ TGA_WRITE_REG(par, vhcr | 0x40000000, TGA_HORIZ_REG); TGA_WRITE_REG(par, vvcr | 0x40000000, TGA_VERT_REG); TGA_WRITE_REG(par, vvvr | TGA_VALID_BLANK, TGA_VALID_REG); par->vesa_blanked = 1; break; } local_irq_restore(flags); return 0;}/* * Acceleration. */static voidtgafb_mono_imageblit(struct fb_info *info, const struct fb_image *image){ struct tga_par *par = (struct tga_par *) info->par; u32 fgcolor, bgcolor, dx, dy, width, height, vxres, vyres, pixelmask; unsigned long rincr, line_length, shift, pos, is8bpp; unsigned long i, j; const unsigned char *data; void __iomem *regs_base; void __iomem *fb_base; is8bpp = info->var.bits_per_pixel == 8; dx = image->dx; dy = image->dy; width = image->width; height = image->height; vxres = info->var.xres_virtual; vyres = info->var.yres_virtual; line_length = info->fix.line_length; rincr = (width + 7) / 8; /* A shift below cannot cope with. */ if (unlikely(width == 0)) return; /* Crop the image to the screen. */ if (dx > vxres || dy > vyres) return; if (dx + width > vxres) width = vxres - dx; if (dy + height > vyres) height = vyres - dy; regs_base = par->tga_regs_base; fb_base = par->tga_fb_base; /* Expand the color values to fill 32-bits. */ /* ??? Would be nice to notice colour changes elsewhere, so that we can do this only when necessary. */ fgcolor = image->fg_color; bgcolor = image->bg_color; if (is8bpp) { fgcolor |= fgcolor << 8; fgcolor |= fgcolor << 16; bgcolor |= bgcolor << 8; bgcolor |= bgcolor << 16; } else { if (fgcolor < 16) fgcolor = ((u32 *)info->pseudo_palette)[fgcolor]; if (bgcolor < 16) bgcolor = ((u32 *)info->pseudo_palette)[bgcolor]; } __raw_writel(fgcolor, regs_base + TGA_FOREGROUND_REG); __raw_writel(bgcolor, regs_base + TGA_BACKGROUND_REG); /* Acquire proper alignment; set up the PIXELMASK register so that we only write the proper character cell. */ pos = dy * line_length; if (is8bpp) { pos += dx; shift = pos & 3; pos &= -4; } else { pos += dx * 4; shift = (pos & 7) >> 2; pos &= -8; } data = (const unsigned char *) image->data; /* Enable opaque stipple mode. */ __raw_writel((is8bpp ? TGA_MODE_SBM_8BPP | TGA_MODE_OPAQUE_STIPPLE : TGA_MODE_SBM_24BPP | TGA_MODE_OPAQUE_STIPPLE), regs_base + TGA_MODE_REG); if (width + shift <= 32) { unsigned long bwidth; /* Handle common case of imaging a single character, in a font less than or 32 pixels wide. */ /* Avoid a shift by 32; width > 0 implied. */ pixelmask = (2ul << (width - 1)) - 1; pixelmask <<= shift; __raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG); wmb(); bwidth = (width + 7) / 8; for (i = 0; i < height; ++i) { u32 mask = 0; /* The image data is bit big endian; we need little endian. */ for (j = 0; j < bwidth; ++j) mask |= bitrev8(data[j]) << (j * 8); __raw_writel(mask << shift, fb_base + pos); pos += line_length; data += rincr; } wmb(); __raw_writel(0xffffffff, regs_base + TGA_PIXELMASK_REG); } else if (shift == 0) { unsigned long pos0 = pos; const unsigned char *data0 = data; unsigned long bincr = (is8bpp ? 8 : 8*4); unsigned long bwidth; /* Handle another common case in which accel_putcs generates a large bitmap, which happens to be aligned. Allow the tail to be misaligned. This case is interesting because we've not got to hold partial bytes across the words being written. */ wmb(); bwidth = (width / 8) & -4; for (i = 0; i < height; ++i) { for (j = 0; j < bwidth; j += 4) { u32 mask = 0; mask |= bitrev8(data[j+0]) << (0 * 8); mask |= bitrev8(data[j+1]) << (1 * 8); mask |= bitrev8(data[j+2]) << (2 * 8); mask |= bitrev8(data[j+3]) << (3 * 8); __raw_writel(mask, fb_base + pos + j*bincr); } pos += line_length; data += rincr; } wmb(); pixelmask = (1ul << (width & 31)) - 1; if (pixelmask) { __raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG); wmb(); pos = pos0 + bwidth*bincr; data = data0 + bwidth; bwidth = ((width & 31) + 7) / 8; for (i = 0; i < height; ++i) { u32 mask = 0; for (j = 0; j < bwidth; ++j) mask |= bitrev8(data[j]) << (j * 8); __raw_writel(mask, fb_base + pos); pos += line_length; data += rincr; } wmb(); __raw_writel(0xffffffff, regs_base + TGA_PIXELMASK_REG); } } else { unsigned long pos0 = pos; const unsigned char *data0 = data; unsigned long bincr = (is8bpp ? 8 : 8*4); unsigned long bwidth; /* Finally, handle the generic case of misaligned start. Here we split the write into 16-bit spans. This allows us to use only one pixel mask, instead of four as would be required by writing 24-bit spans. */ pixelmask = 0xffff << shift; __raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG); wmb(); bwidth = (width / 8) & -2; for (i = 0; i < height; ++i) { for (j = 0; j < bwidth; j += 2) { u32 mask = 0; mask |= bitrev8(data[j+0]) << (0 * 8); mask |= bitrev8(data[j+1]) << (1 * 8); mask <<= shift; __raw_writel(mask, fb_base + pos + j*bincr); } pos += line_length; data += rincr; } wmb(); pixelmask = ((1ul << (width & 15)) - 1) << shift; if (pixelmask) { __raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG); wmb(); pos = pos0 + bwidth*bincr; data = data0 + bwidth; bwidth = (width & 15) > 8; for (i = 0; i < height; ++i) { u32 mask = bitrev8(data[0]); if (bwidth) mask |= bitrev8(data[1]) << 8; mask <<= shift; __raw_writel(mask, fb_base + pos); pos += line_length; data += rincr; } wmb(); } __raw_writel(0xffffffff, regs_base + TGA_PIXELMASK_REG); } /* Disable opaque stipple mode. */ __raw_writel((is8bpp ? TGA_MODE_SBM_8BPP | TGA_MODE_SIMPLE : TGA_MODE_SBM_24BPP | TGA_MODE_SIMPLE), regs_base + TGA_MODE_REG);}static voidtgafb_clut_imageblit(struct fb_info *info, const struct fb_image *image){ struct tga_par *par = (struct tga_par *) info->par; u32 color, dx, dy, width, height, vxres, vyres; u32 *palette = ((u32 *)info->pseudo_palette); unsigned long pos, line_length, i, j; const unsigned char *data; void __iomem *regs_base, *fb_base; dx = image->dx; dy = image->dy; width = image->width; height = image->height; vxres = info->var.xres_virtual; vyres = info->var.yres_virtual; line_length = info->fix.line_length; /* Crop the image to the screen. */ if (dx > vxres || dy > vyres) return; if (dx + width > vxres) width = vxres - dx; if (dy + height > vyres) height = vyres - dy; regs_base = par->tga_regs_base; fb_base = par->tga_fb_base; pos = dy * line_length + (dx * 4); data = image->data; /* Now copy the image, color_expanding via the palette. */ for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { color = palette[*data++]; __raw_writel(color, fb_base + pos + j*4); } pos += line_length; }}/** * tgafb_imageblit - REQUIRED function. Can use generic routines if * non acclerated hardware and packed pixel based. * Copies a image from system memory to the screen. * * @info: frame buffer structure that represents a single frame buffer * @image: structure defining the image. */static void
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -