📄 atyfb_base.c
字号:
{ u32 xoffset = par->crtc.xoffset; u32 yoffset = par->crtc.yoffset; u32 vxres = par->crtc.vxres; u32 bpp = par->crtc.bpp; par->crtc.off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19); aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, info);} /* * Open/Release the frame buffer device */static int atyfb_open(struct fb_info *info, int user){#ifdef __sparc__ struct fb_info_aty *fb = (struct fb_info_aty *)info; if (user) { fb->open++; fb->mmaped = 0; fb->vtconsole = -1; } else { fb->consolecnt++; }#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 fb_info_aty *fb = (struct fb_info_aty *)info; if (user) { fb->open--; mdelay(1); wait_for_idle(fb); if (!fb->open) { int was_mmaped = fb->mmaped; fb->mmaped = 0; if (fb->vtconsole != -1) vt_cons[fb->vtconsole]->vc_mode = KD_TEXT; fb->vtconsole = -1; 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 = (fb->total_vram - (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; } atyfb_set_var(&var, -1, &fb->fb_info); } } } else { fb->consolecnt--; }#endif return(0);}static int encode_fix(struct fb_fix_screeninfo *fix, const struct atyfb_par *par, const struct fb_info_aty *info){ memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, atyfb_name); fix->smem_start = info->frame_buffer_phys; fix->smem_len = (u32)info->total_vram; /* * Reg Block 0 (CT-compatible block) is at ati_regbase_phys * Reg Block 1 (multimedia extensions) is at ati_regbase_phys-0x400 */ if (M64_HAS(GX)) { fix->mmio_start = info->ati_regbase_phys; fix->mmio_len = 0x400; fix->accel = FB_ACCEL_ATI_MACH64GX; } else if (M64_HAS(CT)) { fix->mmio_start = info->ati_regbase_phys; fix->mmio_len = 0x400; fix->accel = FB_ACCEL_ATI_MACH64CT; } else if (M64_HAS(VT)) { fix->mmio_start = info->ati_regbase_phys-0x400; fix->mmio_len = 0x800; fix->accel = FB_ACCEL_ATI_MACH64VT; } else /* if (M64_HAS(GT)) */ { fix->mmio_start = info->ati_regbase_phys-0x400; fix->mmio_len = 0x800; fix->accel = FB_ACCEL_ATI_MACH64GT; } fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; fix->line_length = par->crtc.vxres*par->crtc.bpp/8; fix->visual = par->crtc.bpp <= 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; fix->ywrapstep = 0; fix->xpanstep = 8; fix->ypanstep = 1; return 0;} /* * Get the Fixed Part of the Display */static int atyfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *fb){ const struct fb_info_aty *info = (struct fb_info_aty *)fb; struct atyfb_par par; if (con == -1) par = info->default_par; else atyfb_decode_var(&fb_display[con].var, &par, info); encode_fix(fix, &par, info); return 0;} /* * Get the User Defined Part of the Display */static int atyfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb){ const struct fb_info_aty *info = (struct fb_info_aty *)fb; if (con == -1) atyfb_encode_var(var, &info->default_par, info); else *var = fb_display[con].var; return 0;}static void atyfb_set_dispsw(struct display *disp, struct fb_info_aty *info, int bpp, int accel){ switch (bpp) {#ifdef FBCON_HAS_CFB8 case 8: info->dispsw = accel ? fbcon_aty8 : fbcon_cfb8; disp->dispsw = &info->dispsw; break;#endif#ifdef FBCON_HAS_CFB16 case 16: info->dispsw = accel ? fbcon_aty16 : fbcon_cfb16; disp->dispsw = &info->dispsw; disp->dispsw_data = info->fbcon_cmap.cfb16; break;#endif#ifdef FBCON_HAS_CFB24 case 24: info->dispsw = accel ? fbcon_aty24 : fbcon_cfb24; disp->dispsw = &info->dispsw; disp->dispsw_data = info->fbcon_cmap.cfb24; break;#endif#ifdef FBCON_HAS_CFB32 case 32: info->dispsw = accel ? fbcon_aty32 : fbcon_cfb32; disp->dispsw = &info->dispsw; disp->dispsw_data = info->fbcon_cmap.cfb32; break;#endif default: disp->dispsw = &fbcon_dummy; }#ifdef CONFIG_FB_ATY_CT if (info->cursor) { info->dispsw.cursor = atyfb_cursor; info->dispsw.set_font = atyfb_set_font; }#endif /* CONFIG_FB_ATY_CT */} /* * Set the User Defined Part of the Display */static int atyfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb){ struct fb_info_aty *info = (struct fb_info_aty *)fb; struct atyfb_par par; struct display *display; int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel, accel, err; int activate = var->activate; if (con >= 0) display = &fb_display[con]; else display = fb->disp; /* used during initialization */ if ((err = atyfb_decode_var(var, &par, info))) return err; atyfb_encode_var(var, &par, (struct fb_info_aty *)info); if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { oldxres = display->var.xres; oldyres = display->var.yres; oldvxres = display->var.xres_virtual; oldvyres = display->var.yres_virtual; oldbpp = display->var.bits_per_pixel; oldaccel = display->var.accel_flags; display->var = *var; accel = var->accel_flags & FB_ACCELF_TEXT; if (oldxres != var->xres || oldyres != var->yres || oldvxres != var->xres_virtual || oldvyres != var->yres_virtual || oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) { struct fb_fix_screeninfo fix; encode_fix(&fix, &par, info); display->screen_base = (char *)info->frame_buffer; display->visual = fix.visual; display->type = fix.type; display->type_aux = fix.type_aux; display->ypanstep = fix.ypanstep; display->ywrapstep = fix.ywrapstep; display->line_length = fix.line_length; display->can_soft_blank = 1; display->inverse = 0; if (accel) display->scrollmode = (info->bus_type == PCI) ? SCROLL_YNOMOVE : 0; else display->scrollmode = SCROLL_YREDRAW; if (info->fb_info.changevar) (*info->fb_info.changevar)(con); } if (!info->fb_info.display_fg || info->fb_info.display_fg->vc_num == con) { atyfb_set_par(&par, info); atyfb_set_dispsw(display, info, par.crtc.bpp, accel); } if (oldbpp != var->bits_per_pixel) { if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) return err; do_install_cmap(con, &info->fb_info); } } return 0;} /* * Pan or Wrap the Display * * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag */static int atyfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *fb){ struct fb_info_aty *info = (struct fb_info_aty *)fb; u32 xres, yres, xoffset, yoffset; struct atyfb_par *par = &info->current_par; xres = (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8; yres = ((par->crtc.v_tot_disp>>16) & 0x7ff)+1; xoffset = (var->xoffset+7) & ~7; yoffset = var->yoffset; if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres) return -EINVAL; par->crtc.xoffset = xoffset; par->crtc.yoffset = yoffset; set_off_pitch(par, info); return 0;} /* * Get the Colormap */static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */ return fb_get_cmap(cmap, kspc, atyfb_getcolreg, info); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else { int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256; fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2); } return 0;} /* * Set the Colormap */static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ int err; struct display *disp; if (con >= 0) disp = &fb_display[con]; else disp = info->disp; if (!disp->cmap.len) { /* no colormap allocated? */ int size = disp->var.bits_per_pixel == 16 ? 32 : 256; if ((err = fb_alloc_cmap(&disp->cmap, size, 0))) return err; } if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */ return fb_set_cmap(cmap, kspc, atyfb_setcolreg, info); else fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1); return 0;}#ifdef DEBUG#define ATYIO_CLKR 0x41545900 /* ATY\00 */#define ATYIO_CLKW 0x41545901 /* ATY\01 */struct atyclk { u32 ref_clk_per; u8 pll_ref_div; u8 mclk_fb_div; u8 mclk_post_div; /* 1,2,3,4,8 */ u8 vclk_fb_div; u8 vclk_post_div; /* 1,2,3,4,6,8,12 */ u32 dsp_xclks_per_row; /* 0-16383 */ u32 dsp_loop_latency; /* 0-15 */ u32 dsp_precision; /* 0-7 */ u32 dsp_on; /* 0-2047 */ u32 dsp_off; /* 0-2047 */};#define ATYIO_FEATR 0x41545902 /* ATY\02 */#define ATYIO_FEATW 0x41545903 /* ATY\03 */#endifstatic int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg, int con, struct fb_info *info2){#if defined(__sparc__) || (defined(DEBUG) && defined(CONFIG_FB_ATY_CT)) struct fb_info_aty *info = (struct fb_info_aty *)info2;#endif /* __sparc__ || DEBUG */#ifdef __sparc__ struct fbtype fbtyp; struct display *disp; if (con >= 0) disp = &fb_display[con]; else disp = info2->disp;#endif switch (cmd) {#ifdef __sparc__ case FBIOGTYPE: fbtyp.fb_type = FBTYPE_PCI_GENERIC; fbtyp.fb_width = info->current_par.crtc.vxres; fbtyp.fb_height = info->current_par.crtc.vyres; fbtyp.fb_depth = info->current_par.crtc.bpp; fbtyp.fb_cmsize = disp->cmap.len; fbtyp.fb_size = info->total_vram; if (copy_to_user((struct fbtype *)arg, &fbtyp, sizeof(fbtyp))) return -EFAULT; break;#endif /* __sparc__ */#if defined(DEBUG) && defined(CONFIG_FB_ATY_CT) case ATYIO_CLKR: if (M64_HAS(INTEGRATED)) { struct atyclk clk; union aty_pll *pll = &info->current_par.pll; u32 dsp_config = pll->ct.dsp_config; u32 dsp_on_off = pll->ct.dsp_on_off; clk.ref_clk_per = info->ref_clk_per; clk.pll_ref_div = pll->ct.pll_ref_div; clk.mclk_fb_div = pll->ct.mclk_fb_div; clk.mclk_post_div = pll->ct.mclk_post_div_real; clk.vclk_fb_div = pll->ct.vclk_fb_div; clk.vclk_post_div = pll->ct.vclk_post_div_real; clk.dsp_xclks_per_row = dsp_config & 0x3fff; clk.dsp_loop_latency = (dsp_config>>16) & 0xf; clk.dsp_precision = (dsp_config>>20) & 7; clk.dsp_on = dsp_on_off & 0x7ff; clk.dsp_off = (dsp_on_off>>16) & 0x7ff; if (copy_to_user((struct atyclk *)arg, &clk, sizeof(clk))) return -EFAULT; } else return -EINVAL; break; case ATYIO_CLKW: if (M64_HAS(INTEGRATED)) { struct atyclk clk; union aty_pll *pll = &info->current_par.pll; if (copy_from_user(&clk, (struct atyclk *)arg, sizeof(clk))) return -EFAULT; info->ref_clk_per = clk.ref_clk_per; pll->ct.pll_ref_div = clk.pll_ref_div; pll->ct.mclk_fb_div = clk.mclk_fb_div; pll->ct.mclk_post_div_real = clk.mclk_post_div; pll->ct.vclk_fb_div = clk.vclk_fb_div; pll->ct.vclk_post_div_real = clk.vclk_post_div; pll->ct.dsp_config = (clk.dsp_xclks_per_row & 0x3fff) | ((clk.dsp_loop_latency & 0xf)<<16) | ((clk.dsp_precision & 7)<<20); pll->ct.dsp_on_off = (clk.dsp_on & 0x7ff) | ((clk.dsp_off & 0x7ff)<<16); aty_calc_pll_ct(info, &pll->ct); aty_set_pll_ct(info, pll); } else return -EINVAL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -