⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aty128fb.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    var->yres_virtual = crtc->vyres;    var->xoffset = crtc->xoffset;    var->yoffset = crtc->yoffset;    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 voidaty128_set_pll(struct aty128_pll *pll, const struct fb_info_aty128 *info){    u32 div3;    unsigned char post_conv[] =	/* register values for post dividers */        { 2, 0, 1, 4, 2, 2, 6, 2, 3, 2, 2, 2, 7 };    /* select PPLL_DIV_3 */    aty_st_le32(CLOCK_CNTL_INDEX, aty_ld_le32(CLOCK_CNTL_INDEX) | (3 << 8));    /* reset PLL */    aty_st_pll(PPLL_CNTL,		aty_ld_pll(PPLL_CNTL) | PPLL_RESET | PPLL_ATOMIC_UPDATE_EN);    /* write the reference divider */    aty_pll_wait_readupdate(info);    aty_st_pll(PPLL_REF_DIV, info->constants.ref_divider & 0x3ff);    aty_pll_writeupdate(info);    div3 = aty_ld_pll(PPLL_DIV_3);    div3 &= ~PPLL_FB3_DIV_MASK;    div3 |= pll->feedback_divider;    div3 &= ~PPLL_POST3_DIV_MASK;    div3 |= post_conv[pll->post_divider] << 16;    /* write feedback and post dividers */    aty_pll_wait_readupdate(info);    aty_st_pll(PPLL_DIV_3, div3);    aty_pll_writeupdate(info);    aty_pll_wait_readupdate(info);    aty_st_pll(HTOTAL_CNTL, 0);	/* no horiz crtc adjustment */    aty_pll_writeupdate(info);    /* clear the reset, just in case */    aty_st_pll(PPLL_CNTL, aty_ld_pll(PPLL_CNTL) & ~PPLL_RESET);}static intaty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,			const struct fb_info_aty128 *info){    const struct aty128_constants c = info->constants;    unsigned char post_dividers[] = {1,2,4,8,3,6,12};    u32 output_freq;    u32 vclk;        /* in .01 MHz */    int i;    u32 n, d;    vclk = 100000000 / period_in_ps;	/* convert units to 10 kHz */    /* adjust pixel clock if necessary */    if (vclk > c.ppll_max)	vclk = c.ppll_max;    if (vclk * 12 < c.ppll_min)	vclk = c.ppll_min/12;    /* now, find an acceptable divider */    for (i = 0; i < sizeof(post_dividers); i++) {	output_freq = post_dividers[i] * vclk;	if (output_freq >= c.ppll_min && output_freq <= c.ppll_max)	    break;    }    /* calculate feedback divider */    n = c.ref_divider * output_freq;    d = c.dotclock;    pll->post_divider = post_dividers[i];    pll->feedback_divider = round_div(n, d);    pll->vclk = vclk;    DBG("post %d feedback %d vlck %d output %d ref_divider %d "			"vclk_per: %d\n", pll->post_divider,			pll->feedback_divider, vclk, output_freq,			c.ref_divider, period_in_ps);    return 0;}static intaty128_pll_to_var(const struct aty128_pll *pll, struct fb_var_screeninfo *var,		const struct fb_info_aty128 *info){    var->pixclock = 100000000 / pll->vclk;    return 0;}static voidaty128_set_fifo(const struct aty128_ddafifo *dsp,			const struct fb_info_aty128 *info){    aty_st_le32(DDA_CONFIG, dsp->dda_config);    aty_st_le32(DDA_ON_OFF, dsp->dda_on_off);}static intaty128_ddafifo(struct aty128_ddafifo *dsp,		const struct aty128_pll *pll,		u32 bpp,		const struct fb_info_aty128 *info){    const struct aty128_meminfo *m = info->mem;    u32 xclk = info->constants.xclk;    u32 fifo_width = info->constants.fifo_width;    u32 fifo_depth = info->constants.fifo_depth;    s32 x, b, p, ron, roff;    u32 n, d;    /* 15bpp is really 16bpp */    if (bpp == 15)	bpp = 16;    n = xclk * fifo_width;    d = pll->vclk * bpp;    x = round_div(n, d);    ron = 4 * m->MB +	3 * ((m->Trcd - 2 > 0) ? m->Trcd - 2 : 0) +	2 * m->Trp +	m->Twr +	m->CL +	m->Tr2w +	x;    DBG("x %x\n", x);    b = 0;    while (x) {	x >>= 1;	b++;    }    p = b + 1;    ron <<= (11 - p);    n <<= (11 - p);    x = round_div(n, d);    roff = x * (fifo_depth - 4);    if ((ron + m->Rloop) >= roff) {	printk(KERN_ERR "aty128fb: Mode out of range!\n");	return -EINVAL;    }    DBG("p: %x rloop: %x x: %x ron: %x roff: %x\n",			p, m->Rloop, x, ron, roff);    dsp->dda_config = p << 16 | m->Rloop << 20 | x;    dsp->dda_on_off = ron << 16 | roff;    return 0;}/* * This actually sets the video mode. */static voidaty128_set_par(struct aty128fb_par *par,			struct fb_info_aty128 *info){     u32 config;    info->current_par = *par;        if (info->blitter_may_be_busy)        wait_for_idle(info);    /* clear all registers that may interfere with mode setting */    aty_st_le32(OVR_CLR, 0);    aty_st_le32(OVR_WID_LEFT_RIGHT, 0);    aty_st_le32(OVR_WID_TOP_BOTTOM, 0);    aty_st_le32(OV0_SCALE_CNTL, 0);    aty_st_le32(MPP_TB_CONFIG, 0);    aty_st_le32(MPP_GP_CONFIG, 0);    aty_st_le32(SUBPIC_CNTL, 0);    aty_st_le32(VIPH_CONTROL, 0);    aty_st_le32(I2C_CNTL_1, 0);         /* turn off i2c */    aty_st_le32(GEN_INT_CNTL, 0);	/* turn off interrupts */    aty_st_le32(CAP0_TRIG_CNTL, 0);    aty_st_le32(CAP1_TRIG_CNTL, 0);    aty_st_8(CRTC_EXT_CNTL + 1, 4);	/* turn video off */    aty128_set_crtc(&par->crtc, info);    aty128_set_pll(&par->pll, info);    aty128_set_fifo(&par->fifo_reg, info);    config = aty_ld_le32(CONFIG_CNTL) & ~3;#if defined(__BIG_ENDIAN)    if (par->crtc.bpp >= 24)	config |= 2;	/* make aperture do 32 byte swapping */    else if (par->crtc.bpp > 8)	config |= 1;	/* make aperture do 16 byte swapping */#endif    aty_st_le32(CONFIG_CNTL, config);    aty_st_8(CRTC_EXT_CNTL + 1, 0);	/* turn the video back on */    if (par->accel_flags & FB_ACCELF_TEXT)        aty128_init_engine(par, info);#ifdef CONFIG_FB_COMPAT_XPMAC    if (!console_fb_info || console_fb_info == &info->fb_info) {        struct fb_var_screeninfo var;        int cmode, vmode;	display_info.height = ((par->crtc.v_total >> 16) & 0x7ff) + 1;	display_info.width = (((par->crtc.h_total >> 16) & 0xff) + 1) << 3;	display_info.depth = par->crtc.bpp;	display_info.pitch = (par->crtc.vxres * par->crtc.bpp) >> 3;        aty128_encode_var(&var, par, info);	if (mac_var_to_vmode(&var, &vmode, &cmode))	    display_info.mode = 0;	else	    display_info.mode = vmode;	strcpy(display_info.name, aty128fb_name);	display_info.fb_address = info->frame_buffer_phys;	display_info.cmap_adr_address = 0;	display_info.cmap_data_address = 0;	display_info.disp_reg_address = info->regbase_phys;    }#endif /* CONFIG_FB_COMPAT_XPMAC */}    /*     *  encode/decode the User Defined Part of the Display     */static intaty128_decode_var(struct fb_var_screeninfo *var, struct aty128fb_par *par,			const struct fb_info_aty128 *info){    int err;    if ((err = aty128_var_to_crtc(var, &par->crtc, info)))	return err;    if ((err = aty128_var_to_pll(var->pixclock, &par->pll, info)))	return err;    if ((err = aty128_ddafifo(&par->fifo_reg, &par->pll, par->crtc.bpp, info)))	return err;    if (var->accel_flags & FB_ACCELF_TEXT)	par->accel_flags = FB_ACCELF_TEXT;    else	par->accel_flags = 0;    return 0;}static intaty128_encode_var(struct fb_var_screeninfo *var,			const struct aty128fb_par *par,			const struct fb_info_aty128 *info){    int err;    if ((err = aty128_crtc_to_var(&par->crtc, var)))	return err;    if ((err = aty128_pll_to_var(&par->pll, var, info)))	return err;    var->red.msb_right = 0;    var->green.msb_right = 0;    var->blue.msb_right = 0;    var->transp.msb_right = 0;    var->nonstd = 0;    var->activate = 0;    var->height = -1;    var->width = -1;    var->accel_flags = par->accel_flags;    return 0;}               /*     *  Get the User Defined Part of the Display     */static intaty128fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb){    const struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;    if (con == -1)	aty128_encode_var(var, &info->default_par, info);     else	*var = fb_display[con].var;    return 0;}    /*     *  Set the User Defined Part of the Display     */static intaty128fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb){    struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;    struct aty128fb_par par;    struct display *display;    int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;    int accel, err;    display = (con >= 0) ? &fb_display[con] : fb->disp;    /* basic (in)sanity checks */    if (!var->xres)        var->xres = 1;    if (!var->yres)        var->yres = 1;    if (var->xres > var->xres_virtual)        var->xres_virtual = var->xres;    if (var->yres > var->yres_virtual)        var->yres_virtual = var->yres;    switch (var->bits_per_pixel) {        case 0 ... 8:            var->bits_per_pixel = 8;            break;        case 9 ... 16:            var->bits_per_pixel = 16;            break;        case 17 ... 24:            var->bits_per_pixel = 24;            break;        case 25 ... 32:            var->bits_per_pixel = 32;            break;        default:            return -EINVAL;    }    if ((err = aty128_decode_var(var, &par, info)))	return err;    aty128_encode_var(var, &par, info);    if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)	return 0;    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;    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;	aty128_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;	accel = var->accel_flags & FB_ACCELF_TEXT;        aty128_set_dispsw(display, info, par.crtc.bpp, accel);	if (accel)	    display->scrollmode = SCROLL_YNOMOVE;	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)	aty128_set_par(&par, info);    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;}static voidaty128_set_dispsw(struct display *disp,			struct fb_info_aty128 *info, int bpp, int accel){    switch (bpp) {#ifdef FBCON_HAS_CFB8    case 8:	disp->dispsw = accel ? &fbcon_aty128_8 : &fbcon_cfb8;	break;#endif#ifdef FBCON_HAS_CFB16    case 15:    case 16:	disp->dispsw = accel ? &fbcon_aty128_16 : &fbcon_cfb16;	disp->dispsw_data = info->fbcon_cmap.cfb16;	break;#endif#ifdef FBCON_HAS_CFB24    case 24:	disp->dispsw = accel ? &fbcon_aty128_24 : &fbcon_cfb24;	disp->dispsw_data = info->fbcon_cmap.cfb24;	break;#endif#ifdef FBCON_HAS_CFB32    case 32:	disp->dispsw = accel ? &fbcon_aty128_32 : &fbcon_cfb32;	disp->dispsw_data = info->fbcon_cmap.cfb32;	break;#endif    default:	disp->dispsw = &fbcon_dummy;    }}static voidaty128_encode_fix(struct fb_fix_screeninfo *fix,			struct aty128fb_par *par,			const struct fb_info_aty128 *info){    memset(fix, 0, sizeof(struct fb_fix_screeninfo));        strcpy(fix->id, aty128fb_name);    fix->smem_start = (unsigned long)info->frame_buffer_phys;    fix->mmio_start = (unsigned long)info->regbase_phys;    fix->smem_len = info->vram_size;    fix->mmio_len = 0x1fff;    fix->type        = FB_TYPE_PACKED_PIXELS;    fix->type_aux    = 0;    fix->line_length = (par->crtc.vxres * par->crtc.bpp) >> 3;    fix->visual      = par->crtc.bpp <= 8 ? FB_VISUAL_PSEUDOCOLOR                                          : FB_VISUAL_DIRECTCOLOR;    fix->ywrapstep = 0;    fix->xpanstep  = 8;    fix->ypanstep  = 1;    fix->accel = FB_ACCEL_ATI_RAGE128;    return;}    /*     *  Get the Fixed Part of the Display     */static intaty128fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *fb){    const struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;    struct aty128fb_par par;    if (con == -1)	par = info->default_par;    else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -