atyfb.c
来自「讲述linux的初始化过程」· C语言 代码 · 共 2,436 行 · 第 1/5 页
C
2,436 行
fb_writeb (0xaa, ram++); } } fb_memset (ram, 0xaa, (64 - c->size.y) * 16);}static voidaty_set_cursor(struct fb_info_aty *fb, int on){ struct atyfb_par *par = &fb->current_par; struct aty_cursor *c = fb->cursor; u16 xoff, yoff; int x, y; if (!c) return;#ifdef __sparc__ if (fb->mmaped && (!fb->fb_info.display_fg || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return;#endif if (on) { x = c->pos.x - c->hot.x - par->crtc.xoffset; if (x < 0) { xoff = -x; x = 0; } else { xoff = 0; } y = c->pos.y - c->hot.y - par->crtc.yoffset; if (y < 0) { yoff = -y; y = 0; } else { yoff = 0; } wait_for_fifo(4, fb); aty_st_le32(CUR_OFFSET, (c->offset >> 3) + (yoff << 1), fb); aty_st_le32(CUR_HORZ_VERT_OFF, ((u32)(64 - c->size.y + yoff) << 16) | xoff, fb); aty_st_le32(CUR_HORZ_VERT_POSN, ((u32)y << 16) | x, fb); aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, fb) | HWCURSOR_ENABLE, fb); } else { wait_for_fifo(1, fb); aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, fb) & ~HWCURSOR_ENABLE, fb); } if (fb->blitter_may_be_busy) wait_for_idle(fb);}static voidaty_cursor_timer_handler(unsigned long dev_addr){ struct fb_info_aty *fb = (struct fb_info_aty *)dev_addr; if (!fb->cursor) return; if (!fb->cursor->enable) goto out; if (fb->cursor->vbl_cnt && --fb->cursor->vbl_cnt == 0) { fb->cursor->on ^= 1; aty_set_cursor(fb, fb->cursor->on); fb->cursor->vbl_cnt = fb->cursor->blink_rate; }out: fb->cursor->timer->expires = jiffies + (HZ / 50); add_timer(fb->cursor->timer);}static voidatyfb_cursor(struct display *p, int mode, int x, int y){ struct fb_info_aty *fb = (struct fb_info_aty *)p->fb_info; struct aty_cursor *c = fb->cursor; if (!c) return;#ifdef __sparc__ if (fb->mmaped && (!fb->fb_info.display_fg || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return;#endif x *= fontwidth(p); y *= fontheight(p); if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->enable) return; c->enable = 0; if (c->on) aty_set_cursor(fb, 0); c->pos.x = x; c->pos.y = y; switch (mode) { case CM_ERASE: c->on = 0; break; case CM_DRAW: case CM_MOVE: if (c->on) aty_set_cursor(fb, 1); else c->vbl_cnt = CURSOR_DRAW_DELAY; c->enable = 1; break; }}static struct fb_info_aty *fb_list = NULL;static struct aty_cursor * __initaty_init_cursor(struct fb_info_aty *fb){ struct aty_cursor *cursor; unsigned long addr; cursor = kmalloc(sizeof(struct aty_cursor), GFP_ATOMIC); if (!cursor) return 0; memset(cursor, 0, sizeof(*cursor)); cursor->timer = kmalloc(sizeof(*cursor->timer), GFP_KERNEL); if (!cursor->timer) { kfree(cursor); return 0; } memset(cursor->timer, 0, sizeof(*cursor->timer)); cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE; fb->total_vram -= PAGE_SIZE; cursor->offset = fb->total_vram;#ifdef __sparc__ addr = fb->frame_buffer - 0x800000 + cursor->offset; cursor->ram = (u8 *)addr;#else#ifdef __BIG_ENDIAN addr = fb->frame_buffer_phys - 0x800000 + cursor->offset; cursor->ram = (u8 *)ioremap(addr, 1024);#else addr = fb->frame_buffer + cursor->offset; cursor->ram = (u8 *)addr;#endif#endif if (! cursor->ram) { kfree(cursor); return NULL; } if (curblink) { init_timer(cursor->timer); cursor->timer->expires = jiffies + (HZ / 50); cursor->timer->data = (unsigned long)fb; cursor->timer->function = aty_cursor_timer_handler; add_timer(cursor->timer); } return cursor;}static intatyfb_set_font(struct display *d, int width, int height){ struct fb_info_aty *fb = (struct fb_info_aty *)d->fb_info; struct aty_cursor *c = fb->cursor; int i, j; if (c) { if (!width || !height) { width = 8; height = 16; } c->hot.x = 0; c->hot.y = 0; c->size.x = width; c->size.y = height; memset(c->bits, 0xff, sizeof(c->bits)); memset(c->mask, 0, sizeof(c->mask)); for (i = 0, j = width; j >= 0; j -= 8, i++) { c->mask[i][height-2] = (j >= 8) ? 0xff : (0xff << (8 - j)); c->mask[i][height-1] = (j >= 8) ? 0xff : (0xff << (8 - j)); } aty_set_cursor_color(fb, cursor_pixel_map, cursor_color_map, cursor_color_map, cursor_color_map); aty_set_cursor_shape(fb); } return 1;}/* ------------------------------------------------------------------------- */ /* * CRTC programming */static void aty_set_crtc(const struct fb_info_aty *info, const struct crtc *crtc){ aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, info); aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, info); aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_tot_disp, info); aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid, info); aty_st_le32(CRTC_VLINE_CRNT_VLINE, 0, info); aty_st_le32(CRTC_OFF_PITCH, crtc->off_pitch, info); aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl, info);}static int aty_var_to_crtc(const struct fb_info_aty *info, const struct fb_var_screeninfo *var, struct crtc *crtc){ u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp; u32 left, right, upper, lower, hslen, vslen, sync, vmode; u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol; u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync; u32 pix_width, dp_pix_width, dp_chain_mask; /* input */ xres = var->xres; yres = var->yres; vxres = var->xres_virtual; vyres = var->yres_virtual; xoffset = var->xoffset; yoffset = var->yoffset; bpp = var->bits_per_pixel; left = var->left_margin; right = var->right_margin; upper = var->upper_margin; lower = var->lower_margin; hslen = var->hsync_len; vslen = var->vsync_len; sync = var->sync; vmode = var->vmode; /* convert (and round up) and validate */ xres = (xres+7) & ~7; xoffset = (xoffset+7) & ~7; vxres = (vxres+7) & ~7; if (vxres < xres+xoffset) vxres = xres+xoffset; h_disp = xres/8-1; if (h_disp > 0xff) FAIL("h_disp too large"); h_sync_strt = h_disp+(right/8); if (h_sync_strt > 0x1ff) FAIL("h_sync_start too large"); h_sync_dly = right & 7; h_sync_wid = (hslen+7)/8; if (h_sync_wid > 0x1f) FAIL("h_sync_wid too large"); h_total = h_sync_strt+h_sync_wid+(h_sync_dly+left+7)/8; if (h_total > 0x1ff) FAIL("h_total too large"); h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1; if (vyres < yres+yoffset) vyres = yres+yoffset; v_disp = yres-1; if (v_disp > 0x7ff) FAIL("v_disp too large"); v_sync_strt = v_disp+lower; if (v_sync_strt > 0x7ff) FAIL("v_sync_strt too large"); v_sync_wid = vslen; if (v_sync_wid > 0x1f) FAIL("v_sync_wid too large"); v_total = v_sync_strt+v_sync_wid+upper; if (v_total > 0x7ff) FAIL("v_total too large"); v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1; c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0; if (bpp <= 8) { bpp = 8; pix_width = CRTC_PIX_WIDTH_8BPP; dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB; dp_chain_mask = 0x8080; } else if (bpp <= 16) { bpp = 16; pix_width = CRTC_PIX_WIDTH_15BPP; dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP | BYTE_ORDER_LSB_TO_MSB; dp_chain_mask = 0x4210; } else if ((bpp <= 24) && (Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) { bpp = 24; pix_width = CRTC_PIX_WIDTH_24BPP; dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB; dp_chain_mask = 0x8080; } else if (bpp <= 32) { bpp = 32; pix_width = CRTC_PIX_WIDTH_32BPP; dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP | BYTE_ORDER_LSB_TO_MSB; dp_chain_mask = 0x8080; } else FAIL("invalid bpp"); if (vxres*vyres*bpp/8 > info->total_vram) FAIL("not enough video RAM"); if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) FAIL("invalid vmode"); /* output */ crtc->vxres = vxres; crtc->vyres = vyres; crtc->xoffset = xoffset; crtc->yoffset = yoffset; crtc->bpp = bpp; crtc->h_tot_disp = h_total | (h_disp<<16); crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly<<8) | ((h_sync_strt & 0x100)<<4) | (h_sync_wid<<16) | (h_sync_pol<<21); crtc->v_tot_disp = v_total | (v_disp<<16); crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid<<16) | (v_sync_pol<<21); crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19); crtc->gen_cntl = pix_width | c_sync | CRTC_EXT_DISP_EN | CRTC_ENABLE; if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID) || ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07))) { /* Not VTB/GTB */ /* FIXME: magic FIFO values */ crtc->gen_cntl |= aty_ld_le32(CRTC_GEN_CNTL, info) & 0x000e0000; } crtc->dp_pix_width = dp_pix_width; crtc->dp_chain_mask = dp_chain_mask; return 0;}static int aty_set_dac_ATI68860_B(const struct fb_info_aty *info, u32 bpp, u32 AccelMode){ u32 gModeReg, devSetupRegA, temp, mask; gModeReg = 0; devSetupRegA = 0; switch (bpp) { case 8: gModeReg = 0x83; devSetupRegA = 0x60 | 0x00 /*(info->mach64DAC8Bit ? 0x00 : 0x01) */; break; case 15: gModeReg = 0xA0; devSetupRegA = 0x60; break; case 16: gModeReg = 0xA1; devSetupRegA = 0x60; break; case 24: gModeReg = 0xC0; devSetupRegA = 0x60; break; case 32: gModeReg = 0xE3; devSetupRegA = 0x60; break; } if (!AccelMode) { gModeReg = 0x80; devSetupRegA = 0x61; } temp = aty_ld_8(DAC_CNTL, info); aty_st_8(DAC_CNTL, (temp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3, info); aty_st_8(DAC_REGS + 2, 0x1D, info); aty_st_8(DAC_REGS + 3, gModeReg, info); aty_st_8(DAC_REGS, 0x02, info); temp = aty_ld_8(DAC_CNTL, info); aty_st_8(DAC_CNTL, temp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, info); if (info->total_vram < MEM_SIZE_1M) mask = 0x04; else if (info->total_vram == MEM_SIZE_1M) mask = 0x08; else mask = 0x0C; /* The following assumes that the BIOS has correctly set R7 of the * Device Setup Register A at boot time. */#define A860_DELAY_L 0x80 temp = aty_ld_8(DAC_REGS, info); aty_st_8(DAC_REGS, (devSetupRegA | mask) | (temp & A860_DELAY_L), info); temp = aty_ld_8(DAC_CNTL, info); aty_st_8(DAC_CNTL, (temp & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3)), info); return 0;}static int aty_set_dac_ATT21C498(const struct fb_info_aty *info, const struct pll_18818 *pll, u32 bpp){ u32 dotClock; int muxmode = 0; int DACMask = 0; dotClock = 100000000 / pll->period_in_ps; switch (bpp) { case 8: if (dotClock > 8000) { DACMask = 0x24; muxmode = 1; } else DACMask = 0x04; break; case 15: DACMask = 0x16; break; case 16: DACMask = 0x36; break; case 24: DACMask = 0xE6; break; case 32: DACMask = 0xE6; break; } if (1 /* info->mach64DAC8Bit */) DACMask |= 0x02; aty_dac_waste4(info); aty_st_8(DAC_REGS + 2, DACMask, info); return muxmode;}void aty_dac_waste4(const struct fb_info_aty *info){ (void)aty_ld_8(DAC_REGS, info); (void)aty_ld_8(DAC_REGS + 2, info); (void)aty_ld_8(DAC_REGS + 2, info); (void)aty_ld_8(DAC_REGS + 2, info); (void)aty_ld_8(DAC_REGS + 2, info);}static void aty_set_dac_514(const struct fb_info_aty *info, u32 bpp){ static struct { u8 pixel_dly; u8 misc2_cntl; u8 pixel_rep; u8 pixel_cntl_index; u8 pixel_cntl_v1; } tab[3] = { { 0, 0x41, 0x03, 0x71, 0x45 }, /* 8 bpp */ { 0, 0x45, 0x04, 0x0c, 0x01 }, /* 555 */ { 0, 0x45, 0x06, 0x0e, 0x00 }, /* XRGB */ }; int i; switch (bpp) { case 8: default: i = 0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?