📄 cirrusfb.c
字号:
DPRINTK("ENTER, blank mode = %d\n", blank_mode); if (info->state != FBINFO_STATE_RUNNING || current_mode == blank_mode) { DPRINTK("EXIT, returning 0\n"); return 0; } /* Undo current */ if (current_mode == FB_BLANK_NORMAL || current_mode == FB_BLANK_UNBLANK) { /* unblank the screen */ val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE); /* clear "FullBandwidth" bit */ vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val & 0xdf); /* and undo VESA suspend trickery */ vga_wgfx(cinfo->regbase, CL_GRE, 0x00); } /* set new */ if (blank_mode > FB_BLANK_NORMAL) { /* blank the screen */ val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE); /* set "FullBandwidth" bit */ vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val | 0x20); } switch (blank_mode) { case FB_BLANK_UNBLANK: case FB_BLANK_NORMAL: break; case FB_BLANK_VSYNC_SUSPEND: vga_wgfx(cinfo->regbase, CL_GRE, 0x04); break; case FB_BLANK_HSYNC_SUSPEND: vga_wgfx(cinfo->regbase, CL_GRE, 0x02); break; case FB_BLANK_POWERDOWN: vga_wgfx(cinfo->regbase, CL_GRE, 0x06); break; default: DPRINTK("EXIT, returning 1\n"); return 1; } cinfo->blank_mode = blank_mode; DPRINTK("EXIT, returning 0\n"); /* Let fbcon do a soft blank for us */ return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;}/**** END Hardware specific Routines **************************************//****************************************************************************//**** BEGIN Internal Routines ***********************************************/static void init_vgachip(struct fb_info *info){ struct cirrusfb_info *cinfo = info->par; const struct cirrusfb_board_info_rec *bi; DPRINTK("ENTER\n"); assert(cinfo != NULL); bi = &cirrusfb_board_info[cinfo->btype]; /* reset board globally */ switch (cinfo->btype) { case BT_PICCOLO: WSFR(cinfo, 0x01); udelay(500); WSFR(cinfo, 0x51); udelay(500); break; case BT_PICASSO: WSFR2(cinfo, 0xff); udelay(500); break; case BT_SD64: case BT_SPECTRUM: WSFR(cinfo, 0x1f); udelay(500); WSFR(cinfo, 0x4f); udelay(500); break; case BT_PICASSO4: /* disable flickerfixer */ vga_wcrt(cinfo->regbase, CL_CRT51, 0x00); mdelay(100); /* from Klaus' NetBSD driver: */ vga_wgfx(cinfo->regbase, CL_GR2F, 0x00); /* put blitter into 542x compat */ vga_wgfx(cinfo->regbase, CL_GR33, 0x00); /* mode */ vga_wgfx(cinfo->regbase, CL_GR31, 0x00); break; case BT_GD5480: /* from Klaus' NetBSD driver: */ vga_wgfx(cinfo->regbase, CL_GR2F, 0x00); break; case BT_ALPINE: /* Nothing to do to reset the board. */ break; default: printk(KERN_ERR "cirrusfb: Warning: Unknown board type\n"); break; } /* make sure RAM size set by this point */ assert(info->screen_size > 0); /* the P4 is not fully initialized here; I rely on it having been */ /* inited under AmigaOS already, which seems to work just fine */ /* (Klaus advised to do it this way) */ if (cinfo->btype != BT_PICASSO4) { WGen(cinfo, CL_VSSM, 0x10); /* EGS: 0x16 */ WGen(cinfo, CL_POS102, 0x01); WGen(cinfo, CL_VSSM, 0x08); /* EGS: 0x0e */ if (cinfo->btype != BT_SD64) WGen(cinfo, CL_VSSM2, 0x01); /* reset sequencer logic */ vga_wseq(cinfo->regbase, CL_SEQR0, 0x03); /* FullBandwidth (video off) and 8/9 dot clock */ vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21); /* polarity (-/-), disable access to display memory, * VGA_CRTC_START_HI base address: color */ WGen(cinfo, VGA_MIS_W, 0xc1); /* "magic cookie" - doesn't make any sense to me.. *//* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */ /* unlock all extension registers */ vga_wseq(cinfo->regbase, CL_SEQR6, 0x12); /* reset blitter */ vga_wgfx(cinfo->regbase, CL_GR31, 0x04); switch (cinfo->btype) { case BT_GD5480: vga_wseq(cinfo->regbase, CL_SEQRF, 0x98); break; case BT_ALPINE: break; case BT_SD64: vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8); break; default: vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f); vga_wseq(cinfo->regbase, CL_SEQRF, 0xb0); break; } } /* plane mask: nothing */ vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* character map select: doesn't even matter in gx mode */ vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00); /* memory mode: chain-4, no odd/even, ext. memory */ vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0e); /* controller-internal base address of video memory */ if (bi->init_sr07) vga_wseq(cinfo->regbase, CL_SEQR7, bi->sr07); /* vga_wseq(cinfo->regbase, CL_SEQR8, 0x00); */ /* EEPROM control: shouldn't be necessary to write to this at all.. */ /* graphics cursor X position (incomplete; position gives rem. 3 bits */ vga_wseq(cinfo->regbase, CL_SEQR10, 0x00); /* graphics cursor Y position (..."... ) */ vga_wseq(cinfo->regbase, CL_SEQR11, 0x00); /* graphics cursor attributes */ vga_wseq(cinfo->regbase, CL_SEQR12, 0x00); /* graphics cursor pattern address */ vga_wseq(cinfo->regbase, CL_SEQR13, 0x00); /* writing these on a P4 might give problems.. */ if (cinfo->btype != BT_PICASSO4) { /* configuration readback and ext. color */ vga_wseq(cinfo->regbase, CL_SEQR17, 0x00); /* signature generator */ vga_wseq(cinfo->regbase, CL_SEQR18, 0x02); } /* MCLK select etc. */ if (bi->init_sr1f) vga_wseq(cinfo->regbase, CL_SEQR1F, bi->sr1f); /* Screen A preset row scan: none */ vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00); /* Text cursor start: disable text cursor */ vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20); /* Text cursor end: - */ vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00); /* Screen start address high: 0 */ vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, 0x00); /* Screen start address low: 0 */ vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, 0x00); /* text cursor location high: 0 */ vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00); /* text cursor location low: 0 */ vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00); /* Underline Row scanline: - */ vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00); /* mode control: timing enable, byte mode, no compat modes */ vga_wcrt(cinfo->regbase, VGA_CRTC_MODE, 0xc3); /* Line Compare: not needed */ vga_wcrt(cinfo->regbase, VGA_CRTC_LINE_COMPARE, 0x00); /* ### add 0x40 for text modes with > 30 MHz pixclock */ /* ext. display controls: ext.adr. wrap */ vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02); /* Set/Reset registes: - */ vga_wgfx(cinfo->regbase, VGA_GFX_SR_VALUE, 0x00); /* Set/Reset enable: - */ vga_wgfx(cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00); /* Color Compare: - */ vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00); /* Data Rotate: - */ vga_wgfx(cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00); /* Read Map Select: - */ vga_wgfx(cinfo->regbase, VGA_GFX_PLANE_READ, 0x00); /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */ vga_wgfx(cinfo->regbase, VGA_GFX_MODE, 0x00); /* Miscellaneous: memory map base address, graphics mode */ vga_wgfx(cinfo->regbase, VGA_GFX_MISC, 0x01); /* Color Don't care: involve all planes */ vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f); /* Bit Mask: no mask at all */ vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff); if (cinfo->btype == BT_ALPINE) /* (5434 can't have bit 3 set for bitblt) */ vga_wgfx(cinfo->regbase, CL_GRB, 0x20); else /* Graphics controller mode extensions: finer granularity, * 8byte data latches */ vga_wgfx(cinfo->regbase, CL_GRB, 0x28); vga_wgfx(cinfo->regbase, CL_GRC, 0xff); /* Color Key compare: - */ vga_wgfx(cinfo->regbase, CL_GRD, 0x00); /* Color Key compare mask: - */ vga_wgfx(cinfo->regbase, CL_GRE, 0x00); /* Miscellaneous control: - */ /* Background color byte 1: - */ /* vga_wgfx (cinfo->regbase, CL_GR10, 0x00); */ /* vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */ /* Attribute Controller palette registers: "identity mapping" */ vga_wattr(cinfo->regbase, VGA_ATC_PALETTE0, 0x00); vga_wattr(cinfo->regbase, VGA_ATC_PALETTE1, 0x01); vga_wattr(cinfo->regbase, VGA_ATC_PALETTE2, 0x02); vga_wattr(cinfo->regbase, VGA_ATC_PALETTE3, 0x03); vga_wattr(cinfo->regbase, VGA_ATC_PALETTE4, 0x04); vga_wattr(cinfo->regbase, VGA_ATC_PALETTE5, 0x05); vga_wattr(cinfo->regbase, VGA_ATC_PALETTE6, 0x06); vga_wattr(cinfo->regbase, VGA_ATC_PALETTE7, 0x07); vga_wattr(cinfo->regbase, VGA_ATC_PALETTE8, 0x08); vga_wattr(cinfo->regbase, VGA_ATC_PALETTE9, 0x09); vga_wattr(cinfo->regbase, VGA_ATC_PALETTEA, 0x0a); vga_wattr(cinfo->regbase, VGA_ATC_PALETTEB, 0x0b); vga_wattr(cinfo->regbase, VGA_ATC_PALETTEC, 0x0c); vga_wattr(cinfo->regbase, VGA_ATC_PALETTED, 0x0d); vga_wattr(cinfo->regbase, VGA_ATC_PALETTEE, 0x0e); vga_wattr(cinfo->regbase, VGA_ATC_PALETTEF, 0x0f); /* Attribute Controller mode: graphics mode */ vga_wattr(cinfo->regbase, VGA_ATC_MODE, 0x01); /* Overscan color reg.: reg. 0 */ vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00); /* Color Plane enable: Enable all 4 planes */ vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f);/* ### vga_wattr(cinfo->regbase, CL_AR33, 0x00); * Pixel Panning: - */ /* Color Select: - */ vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00); WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */ if (cinfo->btype != BT_ALPINE && cinfo->btype != BT_GD5480) /* polarity (-/-), enable display mem, * VGA_CRTC_START_HI i/o base = color */ WGen(cinfo, VGA_MIS_W, 0xc3); /* BLT Start/status: Blitter reset */ vga_wgfx(cinfo->regbase, CL_GR31, 0x04); /* - " - : "end-of-reset" */ vga_wgfx(cinfo->regbase, CL_GR31, 0x00); /* misc... */ WHDR(cinfo, 0); /* Hidden DAC register: - */ DPRINTK("EXIT\n"); return;}static void switch_monitor(struct cirrusfb_info *cinfo, int on){#ifdef CONFIG_ZORRO /* only works on Zorro boards */ static int IsOn = 0; /* XXX not ok for multiple boards */ DPRINTK("ENTER\n"); if (cinfo->btype == BT_PICASSO4) return; /* nothing to switch */ if (cinfo->btype == BT_ALPINE) return; /* nothing to switch */ if (cinfo->btype == BT_GD5480) return; /* nothing to switch */ if (cinfo->btype == BT_PICASSO) { if ((on && !IsOn) || (!on && IsOn)) WSFR(cinfo, 0xff); DPRINTK("EXIT\n"); return; } if (on) { switch (cinfo->btype) { case BT_SD64: WSFR(cinfo, cinfo->SFR | 0x21); break; case BT_PICCOLO: WSFR(cinfo, cinfo->SFR | 0x28); break; case BT_SPECTRUM: WSFR(cinfo, 0x6f); break; default: /* do nothing */ break; } } else { switch (cinfo->btype) { case BT_SD64: WSFR(cinfo, cinfo->SFR & 0xde); break; case BT_PICCOLO: WSFR(cinfo, cinfo->SFR & 0xd7); break; case BT_SPECTRUM: WSFR(cinfo, 0x4f); break; default: /* do nothing */ break; } } DPRINTK("EXIT\n");#endif /* CONFIG_ZORRO */}/******************************************//* Linux 2.6-style accelerated functions *//******************************************/static void cirrusfb_fillrect(struct fb_info *info, const struct fb_fillrect *region){ struct fb_fillrect modded; int vxres, vyres; struct cirrusfb_info *cinfo = info->par; int m = info->var.bits_per_pixel; u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ? cinfo->pseudo_palette[region->color] : region->color; if (info->state != FBINFO_STATE_RUNNING) return; if (info->flags & FBINFO_HWACCEL_DISABLED) { cfb_fillrect(info, region); return; } vxres = info->var.xres_virtual; vyres = info->var.yres_virtual; memcpy(&modded, region, sizeof(struct fb_fillrect)); if (!modded.width || !modded.height || modded.dx >= vxres || modded.dy >= vyres) return; if (modded.dx + modded.width > vxres) modded.width = vxres - modded.dx; if (modded.dy + modded.height > vyres) modded.height = vyres - modded.dy; cirrusfb_RectFill(cinfo->regbase, info->var.bits_per_pixel, (region->dx * m) / 8, region->dy, (region->width * m) / 8, region->height, color, info->fix.line_length);}static void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area){ struct fb_copyarea modded; u32 vxres, vyres; struct cirrusfb_info *cinfo = info->par; int m = info->var.bits_per_pixel; if (info->state != FBINFO_STATE_RUNNING) return; if (info->flags & FBINFO_HWACCEL_DISABLED) { cfb_copyarea(info, area); return; } vxres = info->var.xres_virtual; vyres = info->var.yres_virtual; memcpy(&modded, area, sizeof(struct fb_copyarea)); if (!modded.width || !modded.height || modded.sx >= vxres || modded.sy >= vyres || modded.dx >= vxres || modded.dy >= vyres) return; if (modded.sx + modded.width > vxres) modded.width = vxres - modded.sx; if (modded.dx + modded.width > vxres) modded.width = vxres - modded.dx; if (modded.sy + modded.height > vyres) modded.height = vyres - modded.sy; if (modded.dy + modded.height > vyres) modded.height = vyres - modded.dy; cirrusfb_BitBLT(cinfo->regbase, info->var.bits_per_pixel, (area->sx * m) / 8, area->sy, (area->dx * m) / 8, area->dy, (area->width * m) / 8, area->height, info->fix.line_length);}static void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image){ struct cirrusfb_info *cinfo = info->par; cirrusfb_WaitBLT(cinfo->regbase); cfb_imageblit(info, image);}#ifdef CONFIG_PPC_PREP#define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)#define PREP_IO_BASE ((volatile unsigned char *) 0x80000000)static void get_prep_addrs(unsigned long *display, unsigned long *registers){ DPRINTK("ENTER\n"); *display = PREP_VIDEO_BASE; *registers = (unsigned long) PREP_IO_BASE; DPRINTK("EXIT\n");}#endif /* CONFIG_PPC_PREP */#ifdef CONFIG_PCIstatic int release_io_ports;/* Pulled the logic from XFree86 Cirrus driver to get the memory size, * based on the DRAM bandwidth bit and DRAM bank switching bit. This * works with 1MB, 2MB and 4MB configurations (which the Motorola boards * seem to have. */static unsigned int __devinit cirrusfb_get_memsize(u8 __iomem *regbase){ unsigned long mem; unsigned char SRF; DPRINTK("ENTER\n"); SRF = vga_rseq(regbase, CL_SEQRF); switch ((SRF & 0x18)) { case 0x08: mem = 512 * 1024; break; case 0x10: mem = 1024 * 1024; break; /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory * on the 5430. */ case 0x18: mem = 2048 * 1024; break; default: printk(KERN_WARNING "CLgenfb: Unknown memory size!\n"); mem = 1024 * 1024; } if (SRF & 0x80) /* If DRAM bank switching is enabled, there must be twice as much * memory installed. (4MB on the 5434) */ mem *= 2; /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -