📄 cgsixfb.c
字号:
/* $Id: cgsixfb.c,v 1.26 2001/10/16 05:44:44 davem Exp $ * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) */#include <linux/module.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/tty.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/fb.h>#include <linux/init.h>#include <linux/selection.h>#include <video/sbusfb.h>#include <asm/io.h>/* Offset of interesting structures in the OBIO space *//* * Brooktree is the video dac and is funny to program on the cg6. * (it's even funnier on the cg3) * The FBC could be the frame buffer control * The FHC could is the frame buffer hardware control. */#define CG6_ROM_OFFSET 0x0UL#define CG6_BROOKTREE_OFFSET 0x200000UL#define CG6_DHC_OFFSET 0x240000UL#define CG6_ALT_OFFSET 0x280000UL#define CG6_FHC_OFFSET 0x300000UL#define CG6_THC_OFFSET 0x301000UL#define CG6_FBC_OFFSET 0x700000UL#define CG6_TEC_OFFSET 0x701000UL#define CG6_RAM_OFFSET 0x800000UL/* FHC definitions */#define CG6_FHC_FBID_SHIFT 24#define CG6_FHC_FBID_MASK 255#define CG6_FHC_REV_SHIFT 20#define CG6_FHC_REV_MASK 15#define CG6_FHC_FROP_DISABLE (1 << 19)#define CG6_FHC_ROW_DISABLE (1 << 18)#define CG6_FHC_SRC_DISABLE (1 << 17)#define CG6_FHC_DST_DISABLE (1 << 16)#define CG6_FHC_RESET (1 << 15)#define CG6_FHC_LITTLE_ENDIAN (1 << 13)#define CG6_FHC_RES_MASK (3 << 11)#define CG6_FHC_1024 (0 << 11)#define CG6_FHC_1152 (1 << 11)#define CG6_FHC_1280 (2 << 11)#define CG6_FHC_1600 (3 << 11)#define CG6_FHC_CPU_MASK (3 << 9)#define CG6_FHC_CPU_SPARC (0 << 9)#define CG6_FHC_CPU_68020 (1 << 9)#define CG6_FHC_CPU_386 (2 << 9)#define CG6_FHC_TEST (1 << 8)#define CG6_FHC_TEST_X_SHIFT 4#define CG6_FHC_TEST_X_MASK 15#define CG6_FHC_TEST_Y_SHIFT 0#define CG6_FHC_TEST_Y_MASK 15/* FBC mode definitions */#define CG6_FBC_BLIT_IGNORE 0x00000000#define CG6_FBC_BLIT_NOSRC 0x00100000#define CG6_FBC_BLIT_SRC 0x00200000#define CG6_FBC_BLIT_ILLEGAL 0x00300000#define CG6_FBC_BLIT_MASK 0x00300000#define CG6_FBC_VBLANK 0x00080000#define CG6_FBC_MODE_IGNORE 0x00000000#define CG6_FBC_MODE_COLOR8 0x00020000#define CG6_FBC_MODE_COLOR1 0x00040000#define CG6_FBC_MODE_HRMONO 0x00060000#define CG6_FBC_MODE_MASK 0x00060000#define CG6_FBC_DRAW_IGNORE 0x00000000#define CG6_FBC_DRAW_RENDER 0x00008000#define CG6_FBC_DRAW_PICK 0x00010000#define CG6_FBC_DRAW_ILLEGAL 0x00018000#define CG6_FBC_DRAW_MASK 0x00018000#define CG6_FBC_BWRITE0_IGNORE 0x00000000#define CG6_FBC_BWRITE0_ENABLE 0x00002000#define CG6_FBC_BWRITE0_DISABLE 0x00004000#define CG6_FBC_BWRITE0_ILLEGAL 0x00006000#define CG6_FBC_BWRITE0_MASK 0x00006000#define CG6_FBC_BWRITE1_IGNORE 0x00000000#define CG6_FBC_BWRITE1_ENABLE 0x00000800#define CG6_FBC_BWRITE1_DISABLE 0x00001000#define CG6_FBC_BWRITE1_ILLEGAL 0x00001800#define CG6_FBC_BWRITE1_MASK 0x00001800#define CG6_FBC_BREAD_IGNORE 0x00000000#define CG6_FBC_BREAD_0 0x00000200#define CG6_FBC_BREAD_1 0x00000400#define CG6_FBC_BREAD_ILLEGAL 0x00000600#define CG6_FBC_BREAD_MASK 0x00000600#define CG6_FBC_BDISP_IGNORE 0x00000000#define CG6_FBC_BDISP_0 0x00000080#define CG6_FBC_BDISP_1 0x00000100#define CG6_FBC_BDISP_ILLEGAL 0x00000180#define CG6_FBC_BDISP_MASK 0x00000180#define CG6_FBC_INDEX_MOD 0x00000040#define CG6_FBC_INDEX_MASK 0x00000030/* THC definitions */#define CG6_THC_MISC_REV_SHIFT 16#define CG6_THC_MISC_REV_MASK 15#define CG6_THC_MISC_RESET (1 << 12)#define CG6_THC_MISC_VIDEO (1 << 10)#define CG6_THC_MISC_SYNC (1 << 9)#define CG6_THC_MISC_VSYNC (1 << 8)#define CG6_THC_MISC_SYNC_ENAB (1 << 7)#define CG6_THC_MISC_CURS_RES (1 << 6)#define CG6_THC_MISC_INT_ENAB (1 << 5)#define CG6_THC_MISC_INT (1 << 4)#define CG6_THC_MISC_INIT 0x9fMODULE_LICENSE("GPL");/* The contents are unknown */struct cg6_tec { volatile int tec_matrix; volatile int tec_clip; volatile int tec_vdc;};struct cg6_thc { uint thc_pad0[512]; volatile uint thc_hs; /* hsync timing */ volatile uint thc_hsdvs; volatile uint thc_hd; volatile uint thc_vs; /* vsync timing */ volatile uint thc_vd; volatile uint thc_refresh; volatile uint thc_misc; uint thc_pad1[56]; volatile uint thc_cursxy; /* cursor x,y position (16 bits each) */ volatile uint thc_cursmask[32]; /* cursor mask bits */ volatile uint thc_cursbits[32]; /* what to show where mask enabled */};struct cg6_fbc { u32 xxx0[1]; volatile u32 mode; volatile u32 clip; u32 xxx1[1]; volatile u32 s; volatile u32 draw; volatile u32 blit; volatile u32 font; u32 xxx2[24]; volatile u32 x0, y0, z0, color0; volatile u32 x1, y1, z1, color1; volatile u32 x2, y2, z2, color2; volatile u32 x3, y3, z3, color3; volatile u32 offx, offy; u32 xxx3[2]; volatile u32 incx, incy; u32 xxx4[2]; volatile u32 clipminx, clipminy; u32 xxx5[2]; volatile u32 clipmaxx, clipmaxy; u32 xxx6[2]; volatile u32 fg; volatile u32 bg; volatile u32 alu; volatile u32 pm; volatile u32 pixelm; u32 xxx7[2]; volatile u32 patalign; volatile u32 pattern[8]; u32 xxx8[432]; volatile u32 apointx, apointy, apointz; u32 xxx9[1]; volatile u32 rpointx, rpointy, rpointz; u32 xxx10[5]; volatile u32 pointr, pointg, pointb, pointa; volatile u32 alinex, aliney, alinez; u32 xxx11[1]; volatile u32 rlinex, rliney, rlinez; u32 xxx12[5]; volatile u32 liner, lineg, lineb, linea; volatile u32 atrix, atriy, atriz; u32 xxx13[1]; volatile u32 rtrix, rtriy, rtriz; u32 xxx14[5]; volatile u32 trir, trig, trib, tria; volatile u32 aquadx, aquady, aquadz; u32 xxx15[1]; volatile u32 rquadx, rquady, rquadz; u32 xxx16[5]; volatile u32 quadr, quadg, quadb, quada; volatile u32 arectx, arecty, arectz; u32 xxx17[1]; volatile u32 rrectx, rrecty, rrectz; u32 xxx18[5]; volatile u32 rectr, rectg, rectb, recta;};static struct sbus_mmap_map cg6_mmap_map[] = { { CG6_FBC, CG6_FBC_OFFSET, PAGE_SIZE }, { CG6_TEC, CG6_TEC_OFFSET, PAGE_SIZE }, { CG6_BTREGS, CG6_BROOKTREE_OFFSET, PAGE_SIZE }, { CG6_FHC, CG6_FHC_OFFSET, PAGE_SIZE }, { CG6_THC, CG6_THC_OFFSET, PAGE_SIZE }, { CG6_ROM, CG6_ROM_OFFSET, 0x10000 }, { CG6_RAM, CG6_RAM_OFFSET, SBUS_MMAP_FBSIZE(1) }, { CG6_DHC, CG6_DHC_OFFSET, 0x40000 }, { 0, 0, 0 }};static void cg6_setup(struct display *p){ p->next_line = sbusfbinfo(p->fb_info)->var.xres_virtual; p->next_plane = 0;}static void cg6_clear(struct vc_data *conp, struct display *p, int sy, int sx, int height, int width){ struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct cg6_fbc *fbc = fb->s.cg6.fbc; unsigned long flags; int x, y, w, h; int i; spin_lock_irqsave(&fb->lock, flags); do { i = sbus_readl(&fbc->s); } while (i & 0x10000000); sbus_writel(attr_bgcol_ec(p,conp), &fbc->fg); sbus_writel(attr_bgcol_ec(p,conp), &fbc->bg); sbus_writel(~0, &fbc->pixelm); sbus_writel(0xea80ff00, &fbc->alu); sbus_writel(0, &fbc->s); sbus_writel(0, &fbc->clip); sbus_writel(~0, &fbc->pm); if (fontheightlog(p)) { y = sy << fontheightlog(p); h = height << fontheightlog(p); } else { y = sy * fontheight(p); h = height * fontheight(p); } if (fontwidthlog(p)) { x = sx << fontwidthlog(p); w = width << fontwidthlog(p); } else { x = sx * fontwidth(p); w = width * fontwidth(p); } sbus_writel(y + fb->y_margin, &fbc->arecty); sbus_writel(x + fb->x_margin, &fbc->arectx); sbus_writel(y + fb->y_margin + h, &fbc->arecty); sbus_writel(x + fb->x_margin + w, &fbc->arectx); do { i = sbus_readl(&fbc->draw); } while (i < 0 && (i & 0x20000000)); spin_unlock_irqrestore(&fb->lock, flags);}static void cg6_fill(struct fb_info_sbusfb *fb, struct display *p, int s, int count, unsigned short *boxes){ int i; register struct cg6_fbc *fbc = fb->s.cg6.fbc; unsigned long flags; spin_lock_irqsave(&fb->lock, flags); do { i = sbus_readl(&fbc->s); } while (i & 0x10000000); sbus_writel(attr_bgcol(p,s), &fbc->fg); sbus_writel(attr_bgcol(p,s), &fbc->bg); sbus_writel(~0, &fbc->pixelm); sbus_writel(0xea80ff00, &fbc->alu); sbus_writel(0, &fbc->s); sbus_writel(0, &fbc->clip); sbus_writel(~0, &fbc->pm); while (count-- > 0) { sbus_writel(boxes[1], &fbc->arecty); sbus_writel(boxes[0], &fbc->arectx); sbus_writel(boxes[3], &fbc->arecty); sbus_writel(boxes[2], &fbc->arectx); boxes += 4; do { i = sbus_readl(&fbc->draw); } while (i < 0 && (i & 0x20000000)); } spin_unlock_irqrestore(&fb->lock, flags);}static void cg6_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx){ struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct cg6_fbc *fbc = fb->s.cg6.fbc; unsigned long flags; int i, x, y; u8 *fd; spin_lock_irqsave(&fb->lock, flags); if (fontheightlog(p)) { y = fb->y_margin + (yy << fontheightlog(p)); i = ((c & p->charmask) << fontheightlog(p)); } else { y = fb->y_margin + (yy * fontheight(p)); i = (c & p->charmask) * fontheight(p); } if (fontwidth(p) <= 8) fd = p->fontdata + i; else fd = p->fontdata + (i << 1); if (fontwidthlog(p)) x = fb->x_margin + (xx << fontwidthlog(p)); else x = fb->x_margin + (xx * fontwidth(p)); do { i = sbus_readl(&fbc->s); } while (i & 0x10000000); sbus_writel(attr_fgcol(p,c), &fbc->fg); sbus_writel(attr_bgcol(p,c), &fbc->bg); sbus_writel(0x140000, &fbc->mode); sbus_writel(0xe880fc30, &fbc->alu); sbus_writel(~0, &fbc->pixelm); sbus_writel(0, &fbc->s); sbus_writel(0, &fbc->clip); sbus_writel(0xff, &fbc->pm); sbus_writel(0, &fbc->incx); sbus_writel(1, &fbc->incy); sbus_writel(x, &fbc->x0); sbus_writel(x + fontwidth(p) - 1, &fbc->x1); sbus_writel(y, &fbc->y0); if (fontwidth(p) <= 8) { for (i = 0; i < fontheight(p); i++) { u32 val = *fd++ << 24; sbus_writel(val, &fbc->font); } } else { for (i = 0; i < fontheight(p); i++) { u32 val = *(u16 *)fd << 16; sbus_writel(val, &fbc->font); fd += 2; } } spin_unlock_irqrestore(&fb->lock, flags);}static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned short *s, int count, int yy, int xx){ struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct cg6_fbc *fbc = fb->s.cg6.fbc; unsigned long flags; int i, x, y; u8 *fd1, *fd2, *fd3, *fd4; u16 c; spin_lock_irqsave(&fb->lock, flags); do { i = sbus_readl(&fbc->s); } while (i & 0x10000000); c = scr_readw(s); sbus_writel(attr_fgcol(p, c), &fbc->fg); sbus_writel(attr_bgcol(p, c), &fbc->bg); sbus_writel(0x140000, &fbc->mode); sbus_writel(0xe880fc30, &fbc->alu); sbus_writel(~0, &fbc->pixelm); sbus_writel(0, &fbc->s); sbus_writel(0, &fbc->clip); sbus_writel(0xff, &fbc->pm); x = fb->x_margin; y = fb->y_margin; if (fontwidthlog(p)) x += (xx << fontwidthlog(p)); else x += xx * fontwidth(p); if (fontheightlog(p)) y += (yy << fontheightlog(p)); else y += (yy * fontheight(p)); if (fontwidth(p) <= 8) { while (count >= 4) { count -= 4; sbus_writel(0, &fbc->incx); sbus_writel(1, &fbc->incy); sbus_writel(x, &fbc->x0); sbus_writel((x += 4 * fontwidth(p)) - 1, &fbc->x1); sbus_writel(y, &fbc->y0); if (fontheightlog(p)) { fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); } else { fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); } if (fontwidth(p) == 8) { for (i = 0; i < fontheight(p); i++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -