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 + -
显示快捷键?