atyfb_base.c
来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,413 行 · 第 1/5 页
C
2,413 行
return aty_ld_le32(LCD_DATA, par);}#endif /* CONFIG_PMAC_PBOOK || CONFIG_PMAC_BACKLIGHT *//* ------------------------------------------------------------------------- */ /* * CRTC programming */static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc){ aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, par); aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, par); aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_tot_disp, par); aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid, par); aty_st_le32(CRTC_VLINE_CRNT_VLINE, 0, par); aty_st_le32(CRTC_OFF_PITCH, crtc->off_pitch, par); aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl, par);}static int aty_var_to_crtc(const struct fb_info *info, const struct fb_var_screeninfo *var, struct crtc *crtc){ struct atyfb_par *par = (struct atyfb_par *) info->par; 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 && M64_HAS(INTEGRATED)) { 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->fix.smem_len) FAIL("not enough video RAM"); if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) FAIL("invalid vmode"); /* output */ crtc->vxres = vxres; crtc->vyres = vyres; 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 (M64_HAS(MAGIC_FIFO)) { /* Not VTB/GTB */ /* FIXME: magic FIFO values */ crtc->gen_cntl |= aty_ld_le32(CRTC_GEN_CNTL, par) & 0x000e0000; } crtc->dp_pix_width = dp_pix_width; crtc->dp_chain_mask = dp_chain_mask; return 0;}static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *var){ u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync; 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; /* input */ h_total = crtc->h_tot_disp & 0x1ff; h_disp = (crtc->h_tot_disp >> 16) & 0xff; h_sync_strt = (crtc->h_sync_strt_wid & 0xff) | ((crtc->h_sync_strt_wid >> 4) & 0x100); h_sync_dly = (crtc->h_sync_strt_wid >> 8) & 0x7; h_sync_wid = (crtc->h_sync_strt_wid >> 16) & 0x1f; h_sync_pol = (crtc->h_sync_strt_wid >> 21) & 0x1; v_total = crtc->v_tot_disp & 0x7ff; v_disp = (crtc->v_tot_disp >> 16) & 0x7ff; v_sync_strt = crtc->v_sync_strt_wid & 0x7ff; v_sync_wid = (crtc->v_sync_strt_wid >> 16) & 0x1f; v_sync_pol = (crtc->v_sync_strt_wid >> 21) & 0x1; c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0; pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK; /* convert */ xres = (h_disp + 1) * 8; yres = v_disp + 1; left = (h_total - h_sync_strt - h_sync_wid) * 8 - h_sync_dly; right = (h_sync_strt - h_disp) * 8 + h_sync_dly; hslen = h_sync_wid * 8; upper = v_total - v_sync_strt - v_sync_wid; lower = v_sync_strt - v_disp; vslen = v_sync_wid; sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) | (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) | (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0); switch (pix_width) {#if 0 case CRTC_PIX_WIDTH_4BPP: bpp = 4; var->red.offset = 0; var->red.length = 8; var->green.offset = 0; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; var->transp.offset = 0; var->transp.length = 0; break;#endif case CRTC_PIX_WIDTH_8BPP: bpp = 8; var->red.offset = 0; var->red.length = 8; var->green.offset = 0; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; var->transp.offset = 0; var->transp.length = 0; break; case CRTC_PIX_WIDTH_15BPP: /* RGB 555 */ bpp = 16; var->red.offset = 10; var->red.length = 5; var->green.offset = 5; var->green.length = 5; var->blue.offset = 0; var->blue.length = 5; var->transp.offset = 0; var->transp.length = 0; break;#if 0 case CRTC_PIX_WIDTH_16BPP: /* RGB 565 */ bpp = 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; var->transp.offset = 0; var->transp.length = 0; break;#endif case CRTC_PIX_WIDTH_24BPP: /* RGB 888 */ bpp = 24; var->red.offset = 16; var->red.length = 8; var->green.offset = 8; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; var->transp.offset = 0; var->transp.length = 0; break; case CRTC_PIX_WIDTH_32BPP: /* ARGB 8888 */ bpp = 32; var->red.offset = 16; var->red.length = 8; var->green.offset = 8; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; var->transp.offset = 24; var->transp.length = 8; break; default: FAIL("Invalid pixel width"); } /* output */ var->xres = xres; var->yres = yres; var->xres_virtual = crtc->vxres; var->yres_virtual = crtc->vyres; var->bits_per_pixel = bpp; var->left_margin = left; var->right_margin = right; var->upper_margin = upper; var->lower_margin = lower; var->hsync_len = hslen; var->vsync_len = vslen; var->sync = sync; var->vmode = FB_VMODE_NONINTERLACED; return 0;}/* ------------------------------------------------------------------------- */static int atyfb_set_par(struct fb_info *info){ struct atyfb_par *par = (struct atyfb_par *) info->par; struct fb_var_screeninfo *var = &info->var; u8 tmp; u32 i; int err; if ((err = aty_var_to_crtc(info, var, &par->crtc)) || (err = par->pll_ops->var_to_pll(info, var->pixclock, var->bits_per_pixel, &par->pll))) return err; par->accel_flags = var->accel_flags; /* hack */ if (par->blitter_may_be_busy) wait_for_idle(par); tmp = aty_ld_8(CRTC_GEN_CNTL + 3, par); aty_set_crtc(par, &par->crtc); aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 0, par); /* better call aty_StrobeClock ?? */ aty_st_8(CLOCK_CNTL + par->clk_wr_offset, CLOCK_STROBE, par); par->dac_ops->set_dac(info, &par->pll, var->bits_per_pixel, par->accel_flags); par->pll_ops->set_pll(info, &par->pll); if (!M64_HAS(INTEGRATED)) { /* Don't forget MEM_CNTL */ i = aty_ld_le32(MEM_CNTL, par) & 0xf0ffffff; switch (var->bits_per_pixel) { case 8: i |= 0x02000000; break; case 16: i |= 0x03000000; break; case 32: i |= 0x06000000; break; } aty_st_le32(MEM_CNTL, i, par); } else { i = aty_ld_le32(MEM_CNTL, par) & 0xf00fffff; if (!M64_HAS(MAGIC_POSTDIV)) i |= par->mem_refresh_rate << 20; switch (var->bits_per_pixel) { case 8: case 24: i |= 0x00000000; break; case 16: i |= 0x04000000; break; case 32: i |= 0x08000000; break; } if (M64_HAS(CT_BUS)) { aty_st_le32(DAC_CNTL, 0x87010184, par); aty_st_le32(BUS_CNTL, 0x680000f9, par); } else if (M64_HAS(VT_BUS)) { aty_st_le32(DAC_CNTL, 0x87010184, par); aty_st_le32(BUS_CNTL, 0x680000f9, par); } else if (M64_HAS(MOBIL_BUS)) { aty_st_le32(DAC_CNTL, 0x80010102, par); aty_st_le32(BUS_CNTL, 0x7b33a040, par); } else { /* GT */ aty_st_le32(DAC_CNTL, 0x86010102, par); aty_st_le32(BUS_CNTL, 0x7b23a040, par); aty_st_le32(EXT_MEM_CNTL, aty_ld_le32(EXT_MEM_CNTL, par) | 0x5000001, par); } aty_st_le32(MEM_CNTL, i, par); } aty_st_8(DAC_MASK, 0xff, par); info->fix.line_length = var->xres_virtual * var->bits_per_pixel/8; info->fix.visual = var->bits_per_pixel <= 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; /* Initialize the graphics engine */ if (par->accel_flags & FB_ACCELF_TEXT) aty_init_engine(par, info);#ifdef CONFIG_BOOTX_TEXT btext_update_display(info->fix.smem_start, (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8, ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1, var->bits_per_pixel, par->crtc.vxres * var->bits_per_pixel / 8);#endif /* CONFIG_BOOTX_TEXT */ return 0;}static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){ struct atyfb_par *par = (struct atyfb_par *) info->par; struct crtc crtc; union aty_pll pll; int err; if ((err = aty_var_to_crtc(info, var, &crtc)) || (err = par->pll_ops->var_to_pll(info, var->pixclock, var->bits_per_pixel, &pll))) return err;#if 0 /* fbmon is not done. uncomment for 2.5.x -brad */ if (!fbmon_valid_timings(var->pixclock, htotal, vtotal, info)) return -EINVAL;#endif aty_crtc_to_var(&crtc, var); var->pixclock = par->pll_ops->pll_to_var(info, &pll); return 0;}static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info){ u32 xoffset = info->var.xoffset; u32 yoffset = info->var.yoffset; u32 vxres = par->crtc.vxres; u32 bpp = info->var.bits_per_pixel; par->crtc.off_pitch = ((yoffset * vxres + xoffset) * bpp / 64) | (vxres << 19); aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);} /* * Open/Release the frame buffer device */static int atyfb_open(struct fb_info *info, int user){#ifdef __sparc__ struct atyfb_par *par = (struct atyfb_par *) info->par; if (user) { par->open++; par->mmaped = 0; }#endif return (0);}struct fb_var_screeninfo default_var = { /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ 640, 480, 640, 480, 0, 0, 8, 0, {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2, 0, FB_VMODE_NONINTERLACED};static int atyfb_release(struct fb_info *info, int user){#ifdef __sparc__ struct atyfb_par *par = (struct atyfb_par *) info->par; if (user) { par->open--; mdelay(1); wait_for_idle(par); if (!par->open) { int was_mmaped = par->mmaped; par->mmaped = 0; if (was_mmaped) { struct fb_var_screeninfo var; /* Now reset the default display config, we have no * idea what the program(s) which mmap'd the chip did * to the configuration, nor whether it restored it * correctly. */ var = default_var; if (noaccel) var.accel_flags &= ~FB_ACCELF_TEXT; else var.accel_flags |= FB_ACCELF_TEXT; if (var.yres == var.yres_virtual) { u32 vram = (info->fix.smem_len - (PAGE_SIZE << 2)); var.yres_virtual = ((vram * 8) / var.bits_per_pixel) / var.xres_virtual; if (var.yres_virtual < var.yres) var.yres_virtual = var.yres; } }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?