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

📄 aty128fb.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		for (i = 0; (i < 512) && (stage != 4); i++) {			if (R128_sig[0] == *rom)				if (strncmp(R128_sig, rom, 						strlen(R128_sig)) == 0)					stage = 4;			rom++;		}		if (stage != 4) {			iounmap(rom_base);			continue;		}		return rom_base;	}	return NULL;}static void __initaty128_get_pllinfo(struct fb_info_aty128 *info, char *bios_seg){	void *bios_header;	void *header_ptr;	u16 bios_header_offset, pll_info_offset;	PLL_BLOCK pll;	bios_header = bios_seg + 0x48L;	header_ptr  = bios_header;	bios_header_offset = readw(header_ptr);	bios_header = bios_seg + bios_header_offset;	bios_header += 0x30;	header_ptr = bios_header;	pll_info_offset = readw(header_ptr);	header_ptr = bios_seg + pll_info_offset;	memcpy_fromio(&pll, header_ptr, 50);	info->constants.ppll_max = pll.PCLK_max_freq;	info->constants.ppll_min = pll.PCLK_min_freq;	info->constants.xclk = (u32)pll.XCLK;	info->constants.ref_divider = (u32)pll.PCLK_ref_divider;	info->constants.dotclock = (u32)pll.PCLK_ref_freq;	DBG("ppll_max %d ppll_min %d xclk %d ref_divider %d dotclock %d\n",			info->constants.ppll_max, info->constants.ppll_min,			info->constants.xclk, info->constants.ref_divider,			info->constants.dotclock);}           #endif /* !CONFIG_PPC *//* fill in known card constants if pll_block is not available */static void __initaty128_timings(struct fb_info_aty128 *info){#ifdef CONFIG_PPC    /* instead of a table lookup, assume OF has properly     * setup the PLL registers and use their values     * to set the XCLK values and reference divider values */    u32 x_mpll_ref_fb_div;    u32 xclk_cntl;    u32 Nx, M;    unsigned PostDivSet[] =        { 0, 1, 2, 4, 8, 3, 6, 12 };#endif    if (!info->constants.dotclock)        info->constants.dotclock = 2950;#ifdef CONFIG_PPC    x_mpll_ref_fb_div = aty_ld_pll(X_MPLL_REF_FB_DIV);    xclk_cntl = aty_ld_pll(XCLK_CNTL) & 0x7;    Nx = (x_mpll_ref_fb_div & 0x00ff00) >> 8;    M  = x_mpll_ref_fb_div & 0x0000ff;    info->constants.xclk = round_div((2 * Nx *        info->constants.dotclock), (M * PostDivSet[xclk_cntl]));    info->constants.ref_divider =        aty_ld_pll(PPLL_REF_DIV) & PPLL_REF_DIV_MASK;#endif    if (!info->constants.ref_divider) {        info->constants.ref_divider = 0x3b;        aty_st_pll(X_MPLL_REF_FB_DIV, 0x004c4c1e);        aty_pll_writeupdate(info);    }    aty_st_pll(PPLL_REF_DIV, info->constants.ref_divider);    aty_pll_writeupdate(info);    /* from documentation */    if (!info->constants.ppll_min)        info->constants.ppll_min = 12500;    if (!info->constants.ppll_max)        info->constants.ppll_max = 25000;    /* 23000 on some cards? */    if (!info->constants.xclk)        info->constants.xclk = 0x1d4d;	     /* same as mclk */    info->constants.fifo_width = 128;    info->constants.fifo_depth = 32;    switch (aty_ld_le32(MEM_CNTL) & 0x3) {    case 0:	info->mem = &sdr_128;	break;    case 1:	info->mem = &sdr_sgram;	break;    case 2:	info->mem = &ddr_sgram;	break;    default:	info->mem = &sdr_sgram;    }}static intaty128fbcon_switch(int con, struct fb_info *fb){    struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;    struct aty128fb_par par;    /* Do we have to save the colormap? */    if (fb_display[info->currcon].cmap.len)    	fb_get_cmap(&fb_display[info->currcon].cmap, 1,			aty128_getcolreg, fb);    /* set the current console */    info->currcon = con;    aty128_decode_var(&fb_display[con].var, &par, info);    aty128_set_par(&par, info);    aty128_set_dispsw(&fb_display[con], info, par.crtc.bpp,        par.accel_flags & FB_ACCELF_TEXT);    do_install_cmap(con, fb);    return 1;}    /*     *  Blank the display.     */static voidaty128fbcon_blank(int blank, struct fb_info *fb){    struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;    u8 state = 0;#ifdef CONFIG_PMAC_BACKLIGHT    if ((_machine == _MACH_Pmac) && blank)    	set_backlight_enable(0);#endif /* CONFIG_PMAC_BACKLIGHT */    if (blank & VESA_VSYNC_SUSPEND)	state |= 2;    if (blank & VESA_HSYNC_SUSPEND)	state |= 1;    if (blank & VESA_POWERDOWN)	state |= 4;    aty_st_8(CRTC_EXT_CNTL+1, state);#ifdef CONFIG_PMAC_BACKLIGHT    if ((_machine == _MACH_Pmac) && !blank)    	set_backlight_enable(1);#endif /* CONFIG_PMAC_BACKLIGHT */}    /*     *  Read a single color register and split it into     *  colors/transparent. Return != 0 for invalid regno.     */static intaty128_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,                         u_int *transp, struct fb_info *fb){    struct fb_info_aty128 *info = (struct fb_info_aty128 *) fb;    if (regno > 255)	return 1;    *red = (info->palette[regno].red<<8) | info->palette[regno].red;    *green = (info->palette[regno].green<<8) | info->palette[regno].green;    *blue = (info->palette[regno].blue<<8) | info->palette[regno].blue;    *transp = 0;    return 0;}    /*     *  Set a single color register. The values supplied are already     *  rounded down to the hardware's capabilities (according to the     *  entries in the var structure). Return != 0 for invalid regno.     */static intaty128_setcolreg(u_int regno, u_int red, u_int green, u_int blue,                         u_int transp, struct fb_info *fb){    struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;    u32 col;    if (regno > 255)	return 1;    red >>= 8;    green >>= 8;    blue >>= 8;    info->palette[regno].red = red;    info->palette[regno].green = green;    info->palette[regno].blue = blue;    /* Note: For now, on M3, we set palette on both heads, which may     * be useless. Can someone with a M3 check this ? */    /* initialize gamma ramp for hi-color+ */    if ((info->current_par.crtc.bpp > 8) && (regno == 0)) {        int i;        if (info->chip_gen == rage_M3)            aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL);        for (i=16; i<256; i++) {            aty_st_8(PALETTE_INDEX, i);            col = (i << 16) | (i << 8) | i;            aty_st_le32(PALETTE_DATA, col);        }        if (info->chip_gen == rage_M3) {            aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL);            for (i=16; i<256; i++) {                aty_st_8(PALETTE_INDEX, i);                col = (i << 16) | (i << 8) | i;                aty_st_le32(PALETTE_DATA, col);            }        }    }    /* initialize palette */    if (info->chip_gen == rage_M3)        aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL);    if (info->current_par.crtc.bpp == 16)        aty_st_8(PALETTE_INDEX, (regno << 3));    else        aty_st_8(PALETTE_INDEX, regno);    col = (red << 16) | (green << 8) | blue;    aty_st_le32(PALETTE_DATA, col);    if (info->chip_gen == rage_M3) {    	aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL);        if (info->current_par.crtc.bpp == 16)            aty_st_8(PALETTE_INDEX, (regno << 3));        else            aty_st_8(PALETTE_INDEX, regno);        aty_st_le32(PALETTE_DATA, col);    }    if (regno < 16)	switch (info->current_par.crtc.bpp) {#ifdef FBCON_HAS_CFB16	case 9 ... 16:	    info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) |                regno;	    break;#endif#ifdef FBCON_HAS_CFB24	case 17 ... 24:	    info->fbcon_cmap.cfb24[regno] = (regno << 16) | (regno << 8) |		regno;	    break;#endif#ifdef FBCON_HAS_CFB32	case 25 ... 32: {            u32 i;            i = (regno << 8) | regno;            info->fbcon_cmap.cfb32[regno] = (i << 16) | i;	    break;        }#endif	}    return 0;}static voiddo_install_cmap(int con, struct fb_info *info){    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info;    if (con != fb->currcon)	return;    if (fb_display[con].cmap.len)	fb_set_cmap(&fb_display[con].cmap, 1, aty128_setcolreg, info);    else {	int size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 16;	fb_set_cmap(fb_default_cmap(size), 1, aty128_setcolreg, info);    }}#ifdef CONFIG_PMAC_BACKLIGHTstatic int backlight_conv[] = {	0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e,	0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24};static intaty128_set_backlight_enable(int on, int level, void* data){	struct fb_info_aty128 *info = (struct fb_info_aty128 *)data;	unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);		reg |= LVDS_BL_MOD_EN | LVDS_BLON;	if (on && level > BACKLIGHT_OFF) {		reg &= ~LVDS_BL_MOD_LEVEL_MASK;		reg |= (backlight_conv[level] << LVDS_BL_MOD_LEVEL_SHIFT);	} else {		reg &= ~LVDS_BL_MOD_LEVEL_MASK;		reg |= (backlight_conv[0] << LVDS_BL_MOD_LEVEL_SHIFT);	}	aty_st_le32(LVDS_GEN_CNTL, reg);	return 0;}static intaty128_set_backlight_level(int level, void* data){	return aty128_set_backlight_enable(1, level, data);}#endif /* CONFIG_PMAC_BACKLIGHT */    /*     *  Accelerated functions     */static inline voidaty128_rectcopy(int srcx, int srcy, int dstx, int dsty,		u_int width, u_int height,		struct fb_info_aty128 *info){    u32 save_dp_datatype, save_dp_cntl, bppval;    if (!width || !height)        return;    bppval = bpp_to_depth(info->current_par.crtc.bpp);    if (bppval == DST_24BPP) {        srcx *= 3;        dstx *= 3;        width *= 3;    } else if (bppval == -EINVAL) {        printk("aty128fb: invalid depth\n");        return;    }    wait_for_fifo(2, info);    save_dp_datatype = aty_ld_le32(DP_DATATYPE);    save_dp_cntl     = aty_ld_le32(DP_CNTL);    wait_for_fifo(6, info);    aty_st_le32(SRC_Y_X, (srcy << 16) | srcx);    aty_st_le32(DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT);    aty_st_le32(DP_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);    aty_st_le32(DP_DATATYPE, save_dp_datatype | bppval | SRC_DSTCOLOR);    aty_st_le32(DST_Y_X, (dsty << 16) | dstx);    aty_st_le32(DST_HEIGHT_WIDTH, (height << 16) | width);    info->blitter_may_be_busy = 1;    wait_for_fifo(2, info);    aty_st_le32(DP_DATATYPE, save_dp_datatype);    aty_st_le32(DP_CNTL, save_dp_cntl); }    /*     * Text mode accelerated functions     */static voidfbcon_aty128_bmove(struct display *p, int sy, int sx, int dy, int dx,			int height, int width){    sx     *= fontwidth(p);    sy     *= fontheight(p);    dx     *= fontwidth(p);    dy     *= fontheight(p);    width  *= fontwidth(p);    height *= fontheight(p);    aty128_rectcopy(sx, sy, dx, dy, width, height,			(struct fb_info_aty128 *)p->fb_info);}#ifdef FBCON_HAS_CFB8static void fbcon_aty8_putc(struct vc_data *conp, struct display *p,                            int c, int yy, int xx){    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);    if (fb->blitter_may_be_busy)        wait_for_idle(fb);    fbcon_cfb8_putc(conp, p, c, yy, xx);}static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p,                             const unsigned short *s, int count,                             int yy, int xx){    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);    if (fb->blitter_may_be_busy)        wait_for_idle(fb);    fbcon_cfb8_putcs(conp, p, s, count, yy, xx);}static void fbcon_aty8_clear_margins(struct vc_data *conp,                                     struct display *p, int bottom_only){    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);    if (fb->blitter_may_be_busy)        wait_for_idle(fb);    fbcon_cfb8_clear_margins(conp, p, bottom_only);}static struct display_switch fbcon_aty128_8 = {    setup:		fbcon_cfb8_setup,    bmove:		fbcon_aty128_bmove,    clear:		fbcon_cfb8_clear,    putc:		fbcon_aty8_putc,    putcs:		fbcon_aty8_putcs,    revc:		fbcon_cfb8_revc,    clear_margins:	fbcon_aty8_clear_margins,    fontwidthmask:	FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)};#endif#ifdef FBCON_HAS_CFB16static void fbcon_aty16_putc(struct vc_data *conp, struct display *p,                            int c, int yy, int xx){    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);    if (fb->blitter_may_be_busy)        wait_for_idle(fb);    fbcon_cfb16_putc(conp, p, c, yy, xx);}static void fbcon_aty16_putcs(struct vc_data *conp, struct display *p,                             const unsigned short *s, int count,                             int yy, int xx){    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);    if (fb->blitter_may_be_busy)        wait_for_idle(fb);    fbcon_cfb16_putcs(conp, p, s, count, yy, xx);}static void fbcon_aty16_clear_margins(struct vc_data *conp,                                     struct display *p, int bottom_only){    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);    if (fb->blitter_may_be_busy)        wait_for_idle(fb);    fbcon_cfb16_clear_margins(con

⌨️ 快捷键说明

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