Commit 65320e70 authored by James Simmons's avatar James Simmons

Ported the Maxine framebuffer driver to the new api.

parent 96520e1d
......@@ -274,8 +274,7 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \
"$CONFIG_FB_SGIVW" = "y" -o "$CONFIG_FB_CYBER2000" = "y" -o \
"$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_SIS" = "y" -o \
"$CONFIG_FB_PMAG_BA" = "y" -o "$CONFIG_FB_PMAGB_B" = "y" -o \
"$CONFIG_FB_MAXINE" = "y" ]; then
"$CONFIG_FB_PMAG_BA" = "y" -o "$CONFIG_FB_PMAGB_B" = "y" ]; then
define_tristate CONFIG_FBCON_CFB8 y
else
if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
......@@ -293,8 +292,7 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_TX3912" = "m" -o \
"$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_CYBER2000" = "m" -o \
"$CONFIG_FB_PMAG_BA" = "m" -o "$CONFIG_FB_PMAGB_B" = "m" -o \
"$CONFIG_FB_MAXINE" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \
"$CONFIG_FB_SA1100" = "m" ]; then
"$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_RADEON" = "m" ]; then
define_tristate CONFIG_FBCON_CFB8 m
fi
fi
......@@ -372,7 +370,8 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_HP300" = "y" -o "$CONFIG_FB_Q40" = "y" -o \
"$CONFIG_FB_ANAKIN" = "y" -o "$CONFIG_FB_G364" = "y" -o \
"$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_CLPS711X" = "y" -o \
"$CONFIG_FB_3DFX" = "y" -o "$CONFIG_FB_APOLLO" = "y" ]; then
"$CONFIG_FB_3DFX" = "y" -o "$CONFIG_FB_APOLLO" = "y" -o
"$CONFIG_FB_MAXINE" = "y" ]; then
define_tristate CONFIG_FBCON_ACCEL y
else
if [ "$CONFIG_FB_NEOMAGIC" = "m" -o "$CONFIG_FB_HIT" = "m" -o \
......
......@@ -85,7 +85,7 @@ obj-$(CONFIG_FB_LEO) += leofb.o sbusfb.o
obj-$(CONFIG_FB_STI) += stifb.o sticore.o
obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o
obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o
obj-$(CONFIG_FB_MAXINE) += maxinefb.o
obj-$(CONFIG_FB_MAXINE) += maxinefb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_TX3912) += tx3912fb.o
obj-$(CONFIG_FB_MATROX) += matrox/
......
#ifndef _DN_ACCEL_H_
#define _DN_ACCEL_H_
#include <linux/fb.h>
void dn_bitblt(struct display *p,int x_src,int y_src, int x_dest, int y_dest,
int x_count, int y_count);
#endif
#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/delay.h>
#include <linux/interrupt.h>
#include <asm/setup.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#include <asm/apollohw.h>
#include <linux/fb.h>
#include <linux/module.h>
#include <video/fbcon.h>
#include <video/fbcon-mfb.h>
#include "dn_accel.h"
/* apollo video HW definitions */
/*
* Control Registers. IOBASE + $x
*
* Note: these are the Memory/IO BASE definitions for a mono card set to the
* alternate address
*
* Control 3A and 3B serve identical functions except that 3A
* deals with control 1 and 3b deals with Color LUT reg.
*/
#define AP_IOBASE 0x3d0 /* Base address of 1 plane board. */
#define AP_STATUS isaIO2mem(AP_IOBASE+0) /* Status register. Read */
#define AP_WRITE_ENABLE isaIO2mem(AP_IOBASE+0) /* Write Enable Register Write */
#define AP_DEVICE_ID isaIO2mem(AP_IOBASE+1) /* Device ID Register. Read */
#define AP_ROP_1 isaIO2mem(AP_IOBASE+2) /* Raster Operation reg. Write Word */
#define AP_DIAG_MEM_REQ isaIO2mem(AP_IOBASE+4) /* Diagnostic Memory Request. Write Word */
#define AP_CONTROL_0 isaIO2mem(AP_IOBASE+8) /* Control Register 0. Read/Write */
#define AP_CONTROL_1 isaIO2mem(AP_IOBASE+0xa) /* Control Register 1. Read/Write */
#define AP_CONTROL_2 isaIO2mem(AP_IOBASE+0xc) /* Control Register 2. Read/Write */
#define AP_CONTROL_3A isaIO2mem(AP_IOBASE+0xe) /* Control Register 3a. Read/Write */
#define AP_LUT_RED isaIO2mem(AP_IOBASE+9) /* Red Lookup Table register. Write */
#define AP_LUT_GREEN isaIO2mem(AP_IOBASE+0xb) /* Green Lookup Table register. Write */
#define AP_LUT_BLUE isaIO2mem(AP_IOBASE+0xd) /* Blue Lookup Table register. Write */
#define AP_AD_CHANNEL isaIO2mem(AP_IOBASE+0xf) /* A/D Result/Channel register. Read/Write */
#define FRAME_BUFFER_START 0x0A0000
#define FRAME_BUFFER_LEN 0x20000
/* CREG 0 */
#define VECTOR_MODE 0x40 /* 010x.xxxx */
#define DBLT_MODE 0x80 /* 100x.xxxx */
#define NORMAL_MODE 0xE0 /* 111x.xxxx */
#define SHIFT_BITS 0x1F /* xxx1.1111 */
/* other bits are Shift value */
/* CREG 1 */
#define AD_BLT 0x80 /* 1xxx.xxxx */
#define ROP_EN 0x10 /* xxx1.xxxx */
#define DST_EQ_SRC 0x00 /* xxx0.xxxx */
#define nRESET_SYNC 0x08 /* xxxx.1xxx */
#define SYNC_ENAB 0x02 /* xxxx.xx1x */
#define BLANK_DISP 0x00 /* xxxx.xxx0 */
#define ENAB_DISP 0x01 /* xxxx.xxx1 */
#define NORM_CREG1 (nRESET_SYNC | SYNC_ENAB | ENAB_DISP) /* no reset sync */
/* CREG 2B */
/*
* Following 3 defines are common to 1, 4 and 8 plane.
*/
#define S_DATA_1s 0x00 /* 00xx.xxxx */ /* set source to all 1's -- vector drawing */
#define S_DATA_PIX 0x40 /* 01xx.xxxx */ /* takes source from ls-bits and replicates over 16 bits */
#define S_DATA_PLN 0xC0 /* 11xx.xxxx */ /* normal, each data access =16-bits in
one plane of image mem */
/* CREG 3A/CREG 3B */
# define RESET_CREG 0x80 /* 1000.0000 */
/* ROP REG - all one nibble */
/* ********* NOTE : this is used r0,r1,r2,r3 *********** */
#define ROP(r2,r3,r0,r1) ( (U_SHORT)((r0)|((r1)<<4)|((r2)<<8)|((r3)<<12)) )
#define DEST_ZERO 0x0
#define SRC_AND_DEST 0x1
#define SRC_AND_nDEST 0x2
#define SRC 0x3
#define nSRC_AND_DEST 0x4
#define DEST 0x5
#define SRC_XOR_DEST 0x6
#define SRC_OR_DEST 0x7
#define SRC_NOR_DEST 0x8
#define SRC_XNOR_DEST 0x9
#define nDEST 0xA
#define SRC_OR_nDEST 0xB
#define nSRC 0xC
#define nSRC_OR_DEST 0xD
#define SRC_NAND_DEST 0xE
#define DEST_ONE 0xF
#define SWAP(A) ((A>>8) | ((A&0xff) <<8))
/* frame buffer operations */
static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info);
static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int dn_fb_set_var(struct fb_var_screeninfo *var, int isactive,
struct fb_info *info);
static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
struct fb_info *info);
static int dn_fb_blank(int blank,struct fb_info *info);
static int dnfbcon_switch(int con,struct fb_info *info);
static int dnfbcon_updatevar(int con,struct fb_info *info);
static void dn_fb_set_disp(int con,struct fb_info *info);
static struct display disp[MAX_NR_CONSOLES];
static struct fb_info fb_info;
static struct fb_ops dn_fb_ops = {
owner: THIS_MODULE,
fb_get_fix: dn_fb_get_fix,
fb_get_var: dn_fb_get_var,
fb_set_var: dn_fb_set_var,
fb_get_cmap: dn_fb_get_cmap,
fb_set_cmap: gen_set_cmap,
fb_blank: dn_fb_blank,
};
#define NUM_TOTAL_MODES 1
struct fb_var_screeninfo dn_fb_predefined[] = {
{ 0, },
};
static char dn_fb_name[]="Apollo ";
/* accel stuff */
#define USE_DN_ACCEL
static struct display_switch dispsw_apollofb;
static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info) {
strcpy(fix->id,"Apollo Color4");
fix->smem_start=(FRAME_BUFFER_START+IO_BASE);
fix->smem_len=FRAME_BUFFER_LEN;
fix->type=FB_TYPE_PACKED_PIXELS;
fix->type_aux=0;
fix->visual=FB_VISUAL_MONO10;
fix->xpanstep=0;
fix->ypanstep=0;
fix->ywrapstep=0;
fix->line_length=128;
return 0;
}
static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info) {
var->xres=1024;
var->yres=800;
var->xres_virtual=1024;
var->yres_virtual=1024;
var->xoffset=0;
var->yoffset=0;
var->bits_per_pixel=1;
var->grayscale=0;
var->nonstd=0;
var->activate=0;
var->height=-1;
var->width=-1;
var->pixclock=0;
var->left_margin=0;
var->right_margin=0;
var->hsync_len=0;
var->vsync_len=0;
var->sync=0;
var->vmode=FB_VMODE_NONINTERLACED;
return 0;
}
static int dn_fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info) {
printk("fb_set_var\n");
if(var->xres!=1024)
return -EINVAL;
if(var->yres!=800)
return -EINVAL;
if(var->xres_virtual!=1024)
return -EINVAL;
if(var->yres_virtual!=1024)
return -EINVAL;
if(var->xoffset!=0)
return -EINVAL;
if(var->yoffset!=0)
return -EINVAL;
if(var->bits_per_pixel!=1)
return -EINVAL;
if(var->grayscale!=0)
return -EINVAL;
if(var->nonstd!=0)
return -EINVAL;
if(var->activate!=0)
return -EINVAL;
if(var->pixclock!=0)
return -EINVAL;
if(var->left_margin!=0)
return -EINVAL;
if(var->right_margin!=0)
return -EINVAL;
if(var->hsync_len!=0)
return -EINVAL;
if(var->vsync_len!=0)
return -EINVAL;
if(var->sync!=0)
return -EINVAL;
if(var->vmode!=FB_VMODE_NONINTERLACED)
return -EINVAL;
return 0;
}
static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
struct fb_info *info) {
printk("get cmap not supported\n");
return -EINVAL;
}
static void dn_fb_set_disp(int con, struct fb_info *info) {
struct fb_fix_screeninfo fix;
struct display *display;
dn_fb_get_fix(&fix,con, info);
if (con>=0)
display=&fb_display[con];
else
display=&disp[0];
if(con==-1)
con=0;
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
display->ypanstep = fix.ypanstep;
display->ywrapstep = fix.ywrapstep;
display->can_soft_blank = 1;
display->inverse = 0;
display->line_length = fix.line_length;
display->scrollmode = SCROLL_YREDRAW;
#ifdef FBCON_HAS_MFB
display->dispsw = &fbcon_mfb;
#else
display->dispsw=&fbcon_dummy;
#endif
}
unsigned long dnfb_init(unsigned long mem_start) {
int err;
printk("dn_fb_init\n");
fb_info.changevar=NULL;
strcpy(&fb_info.modename[0],dn_fb_name);
fb_info.fontname[0]=0;
fb_info.disp=disp;
fb_info.switch_con=&dnfbcon_switch;
fb_info.updatevar=&dnfbcon_updatevar;
fb_info.node = NODEV;
fb_info.fbops = &dn_fb_ops;
fb_info.screen_base = (u_char *)fix.smem_start;
printk("screenbase: %lx\n",fix.smem_start);
fb_info.currcon = -1;
fb_info.flags = FBINFO_FLAG_DEFAULT;
dn_fb_get_var(&disp[0].var,0, &fb_info);
dn_fb_set_disp(-1, &fb_info);
printk("dn_fb_init: register\n");
err=register_framebuffer(&fb_info);
if(err < 0) {
panic("unable to register apollo frame buffer\n");
}
/* now we have registered we can safely setup the hardware */
outb(RESET_CREG, AP_CONTROL_3A);
outb(NORMAL_MODE, AP_CONTROL_0);
outb((AD_BLT | DST_EQ_SRC | NORM_CREG1), AP_CONTROL_1);
outb(S_DATA_PLN, AP_CONTROL_2);
outw(SWAP(0x3), AP_ROP_1);
printk("apollo frame buffer alive and kicking !\n");
return mem_start;
}
static int dnfbcon_switch(int con, struct fb_info *info) {
info->currcon = con;
return 0;
}
static int dnfbcon_updatevar(int con, struct fb_info *info) {
return 0;
}
static int dn_fb_blank(int blank, struct fb_info *info)
{
if (blank)
outb(0x0, AP_CONTROL_3A);
else
outb(0x1, AP_CONTROL_3A);
return 0;
}
void dn_bitblt(struct display *p,int x_src,int y_src, int x_dest, int y_dest,
int x_count, int y_count) {
int incr,y_delta,pre_read=0,x_end,x_word_count;
ushort *src,dummy;
uint start_mask,end_mask,dest;
short i,j;
incr=(y_dest<=y_src) ? 1 : -1 ;
src=(ushort *)(p->fb_info.screen_base+ y_src*p->next_line+(x_src >> 4));
dest=y_dest*(p->next_line >> 1)+(x_dest >> 4);
if(incr>0) {
y_delta=(p->next_line*8)-x_src-x_count;
x_end=x_dest+x_count-1;
x_word_count=(x_end>>4) - (x_dest >> 4) + 1;
start_mask=0xffff0000 >> (x_dest & 0xf);
end_mask=0x7ffff >> (x_end & 0xf);
outb((((x_dest & 0xf) - (x_src &0xf)) % 16)|(0x4 << 5),AP_CONTROL_0);
if((x_dest & 0xf) < (x_src & 0xf))
pre_read=1;
}
else {
y_delta=-((p->next_line*8)-x_src-x_count);
x_end=x_dest-x_count+1;
x_word_count=(x_dest>>4) - (x_end >> 4) + 1;
start_mask=0x7ffff >> (x_dest & 0xf);
end_mask=0xffff0000 >> (x_end & 0xf);
outb(((-((x_src & 0xf) - (x_dest &0xf))) % 16)|(0x4 << 5),AP_CONTROL_0);
if((x_dest & 0xf) > (x_src & 0xf))
pre_read=1;
}
for(i=0;i<y_count;i++) {
if(pre_read) {
dummy=*src;
src+=incr;
}
if(x_word_count) {
outb(start_mask,AP_WRITE_ENABLE);
*src=dest;
src+=incr;
dest+=incr;
outb(0,AP_WRITE_ENABLE);
for(j=1;j<(x_word_count-1);j++) {
*src=dest;
src+=incr;
dest+=incr;
}
outb(start_mask,AP_WRITE_ENABLE);
*src=dest;
dest+=incr;
src+=incr;
}
else {
outb(start_mask | end_mask, AP_WRITE_ENABLE);
*src=dest;
dest+=incr;
src+=incr;
}
src+=(y_delta/16);
dest+=(y_delta/16);
}
outb(NORMAL_MODE,AP_CONTROL_0);
}
static void bmove_apollofb(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
int fontheight,fontwidth;
fontheight=fontheight(p);
fontwidth=fontwidth(p);
#ifdef USE_DN_ACCEL
dn_bitblt(p,sx,sy*fontheight,dx,dy*fontheight,width*fontwidth,
height*fontheight);
#else
u_char *src, *dest;
u_int rows;
if (sx == 0 && dx == 0 && width == p->next_line) {
src = p->fb_info.screen_base+sy*fontheight*width;
dest = p->fb_info.screen_base+dy*fontheight*width;
mymemmove(dest, src, height*fontheight*width);
} else if (dy <= sy) {
src = p->fb_info.screen_base+sy*fontheight*p->next_line+sx;
dest = p->fb_info.screen_base+dy*fontheight*p->next_line+dx;
for (rows = height*fontheight; rows--;) {
mymemmove(dest, src, width);
src += p->next_line;
dest += p->next_line;
}
} else {
src = p->fb_info.screen_base+((sy+height)*fontheight-1)*p->next_line+sx;
dest = p->fb_info.screen_base+((dy+height)*fontheight-1)*p->next_line+dx;
for (rows = height*fontheight; rows--;) {
mymemmove(dest, src, width);
src -= p->next_line;
dest -= p->next_line;
}
}
#endif
}
static void clear_apollofb(struct vc_data *conp, struct display *p, int sy, int sx,
int height, int width)
{
fbcon_mfb_clear(conp,p,sy,sx,height,width);
}
static void putc_apollofb(struct vc_data *conp, struct display *p, int c, int yy,
int xx)
{
fbcon_mfb_putc(conp,p,c,yy,xx);
}
static void putcs_apollofb(struct vc_data *conp, struct display *p, const unsigned short *s,
int count, int yy, int xx)
{
fbcon_mfb_putcs(conp,p,s,count,yy,xx);
}
static void rev_char_apollofb(struct display *p, int xx, int yy)
{
fbcon_mfb_revc(p,xx,yy);
}
static struct display_switch dispsw_apollofb = {
setup: fbcon_mfb_setup,
bmove: bmove_apollofb,
clear: clear_apollofb,
putc: putc_apollofb,
putcs: putcs_apollofb,
revc: rev_char_apollofb,
fontwidthmask: FONTWIDTH(8)
};
MODULE_LICENSE("GPL");
#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/delay.h>
#include <linux/interrupt.h>
#include <asm/setup.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#include <asm/apollohw.h>
#include <linux/fb.h>
#include <linux/module.h>
#include "dn_accel.h"
#include "fbcon.h"
#include "fbcon-mfb.h"
/* apollo video HW definitions */
/*
* Control Registers. IOBASE + $x
*
* Note: these are the Memory/IO BASE definitions for a mono card set to the
* alternate address
*
* Control 3A and 3B serve identical functions except that 3A
* deals with control 1 and 3b deals with Color LUT reg.
*/
#define AP_IOBASE 0x3d0 /* Base address of 1 plane board. */
#define AP_STATUS isaIO2mem(AP_IOBASE+0) /* Status register. Read */
#define AP_WRITE_ENABLE isaIO2mem(AP_IOBASE+0) /* Write Enable Register Write */
#define AP_DEVICE_ID isaIO2mem(AP_IOBASE+1) /* Device ID Register. Read */
#define AP_ROP_0 isaIO2mem(AP_IOBASE+2) /* Raster Operation reg. Write Word */
#define AP_ROP_1 isaIO2mem(AP_IOBASE+4) /* Raster Operation reg. Write Word */
#define AP_DIAG_MEM_REQ isaIO2mem(AP_IOBASE+6) /* Diagnostic Memory Request. Write Word */
#define AP_CONTROL_0 isaIO2mem(AP_IOBASE+8) /* Control Register 0. Read/Write */
#define AP_LUT_DATA isaIO2mem(AP_IOBASE+9) /* Control Register 0. Read/Write */
#define AP_CONTROL_1 isaIO2mem(AP_IOBASE+0xa) /* Control Register 1. Read/Write */
#define AP_LUT_CONTROL isaIO2mem(AP_IOBASE+0xb) /* Control Register 1. Read/Write */
#define AP_CONTROL_2A isaIO2mem(AP_IOBASE+0xc) /* Control Register 2. Read/Write */
#define AP_CONTROL_2B isaIO2mem(AP_IOBASE+0xd) /* Control Register 2. Read/Write */
#define AP_CONTROL_3A isaIO2mem(AP_IOBASE+0xe) /* Control Register 3a. Read/Write */
#define AP_CONTROL_3B isaIO2mem(AP_IOBASE+0xf) /* Control Register 3a. Read/Write */
#define FRAME_BUFFER_START 0x0A0000
#define FRAME_BUFFER_LEN 0x20000
/* CREG 0 */
#define VECTOR_MODE 0x40 /* 010x.xxxx */
#define DBLT_MODE 0x80 /* 100x.xxxx */
#define NORMAL_MODE 0xE0 /* 111x.xxxx */
#define SHIFT_BITS 0x1F /* xxx1.1111 */
/* other bits are Shift value */
/* CREG 1 */
#define AD_BLT 0x80 /* 1xxx.xxxx */
#define ROP_EN 0x10 /* xxx1.xxxx */
#define DST_EQ_SRC 0x00 /* xxx0.xxxx */
#define nRESET_SYNC 0x08 /* xxxx.1xxx */
#define SYNC_ENAB 0x02 /* xxxx.xx1x */
#define BLANK_DISP 0x00 /* xxxx.xxx0 */
#define ENAB_DISP 0x01 /* xxxx.xxx1 */
#define NORM_CREG1 (nRESET_SYNC | SYNC_ENAB | ENAB_DISP) /* no reset sync */
/* CREG 2B */
/*
* Following 3 defines are common to 1, 4 and 8 plane.
*/
#define S_DATA_1s 0x00 /* 00xx.xxxx */ /* set source to all 1's -- vector drawing */
#define S_DATA_PIX 0x40 /* 01xx.xxxx */ /* takes source from ls-bits and replicates over 16 bits */
#define S_DATA_PLN 0xC0 /* 11xx.xxxx */ /* normal, each data access =16-bits in
one plane of image mem */
/* CREG 3A/CREG 3B */
# define RESET_CREG 0x80 /* 1000.0000 */
/* ROP REG - all one nibble */
/* ********* NOTE : this is used r0,r1,r2,r3 *********** */
#define ROP(r2,r3,r0,r1) ( (U_SHORT)((r0)|((r1)<<4)|((r2)<<8)|((r3)<<12)) )
#define DEST_ZERO 0x0
#define SRC_AND_DEST 0x1
#define SRC_AND_nDEST 0x2
#define SRC 0x3
#define nSRC_AND_DEST 0x4
#define DEST 0x5
#define SRC_XOR_DEST 0x6
#define SRC_OR_DEST 0x7
#define SRC_NOR_DEST 0x8
#define SRC_XNOR_DEST 0x9
#define nDEST 0xA
#define SRC_OR_nDEST 0xB
#define nSRC 0xC
#define nSRC_OR_DEST 0xD
#define SRC_NAND_DEST 0xE
#define DEST_ONE 0xF
#define SWAP(A) ((A>>8) | ((A&0xff) <<8))
/* frame buffer operations */
static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info);
static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int dn_fb_set_var(struct fb_var_screeninfo *var, int isactive,
struct fb_info *info);
static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
struct fb_info *info);
static int dn_fb_blank(int blank,struct fb_info *info);
static int dnfbcon_switch(int con,struct fb_info *info);
static int dnfbcon_updatevar(int con,struct fb_info *info);
static void dn_fb_set_disp(int con,struct fb_info *info);
static struct display disp[MAX_NR_CONSOLES];
static struct fb_info fb_info;
static struct fb_ops dn_fb_ops = {
owner: THIS_MODULE,
fb_get_fix: dn_fb_get_fix,
fb_get_var: dn_fb_get_var,
fb_set_var: dn_fb_set_var,
fb_get_cmap: dn_fb_get_cmap,
fb_set_cmap: gen_set_cmap,
fb_blank: dn_fb_blank,
};
#define NUM_TOTAL_MODES 1
struct fb_var_screeninfo dn_fb_predefined[] = {
{ 0, },
};
static char dn_fb_name[]="Apollo ";
/* accel stuff */
#define USE_DN_ACCEL
static struct display_switch dispsw_apollofb;
static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info) {
strcpy(fix->id,"Apollo Color8");
fix->smem_start=(char*)(FRAME_BUFFER_START+IO_BASE);
fix->smem_len=FRAME_BUFFER_LEN;
fix->type=FB_TYPE_PACKED_PIXELS;
fix->type_aux=0;
fix->visual=FB_VISUAL_MONO10;
fix->xpanstep=0;
fix->ypanstep=0;
fix->ywrapstep=0;
fix->line_length=128;
return 0;
}
static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info) {
var->xres=1024;
var->yres=800;
var->xres_virtual=1024;
var->yres_virtual=1024;
var->xoffset=0;
var->yoffset=0;
var->bits_per_pixel=1;
var->grayscale=0;
var->nonstd=0;
var->activate=0;
var->height=-1;
var->width=-1;
var->pixclock=0;
var->left_margin=0;
var->right_margin=0;
var->hsync_len=0;
var->vsync_len=0;
var->sync=0;
var->vmode=FB_VMODE_NONINTERLACED;
return 0;
}
static int dn_fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info) {
printk("fb_set_var\n");
if(var->xres!=1024)
return -EINVAL;
if(var->yres!=800)
return -EINVAL;
if(var->xres_virtual!=1024)
return -EINVAL;
if(var->yres_virtual!=1024)
return -EINVAL;
if(var->xoffset!=0)
return -EINVAL;
if(var->yoffset!=0)
return -EINVAL;
if(var->bits_per_pixel!=1)
return -EINVAL;
if(var->grayscale!=0)
return -EINVAL;
if(var->nonstd!=0)
return -EINVAL;
if(var->activate!=0)
return -EINVAL;
if(var->pixclock!=0)
return -EINVAL;
if(var->left_margin!=0)
return -EINVAL;
if(var->right_margin!=0)
return -EINVAL;
if(var->hsync_len!=0)
return -EINVAL;
if(var->vsync_len!=0)
return -EINVAL;
if(var->sync!=0)
return -EINVAL;
if(var->vmode!=FB_VMODE_NONINTERLACED)
return -EINVAL;
return 0;
}
static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
struct fb_info *info) {
printk("get cmap not supported\n");
return -EINVAL;
}
static void dn_fb_set_disp(int con, struct fb_info *info) {
struct fb_fix_screeninfo fix;
dn_fb_get_fix(&fix,con, info);
if(con==-1)
con=0;
disp[con].visual = fix.visual;
disp[con].type = fix.type;
disp[con].type_aux = fix.type_aux;
disp[con].ypanstep = fix.ypanstep;
disp[con].ywrapstep = fix.ywrapstep;
disp[con].can_soft_blank = 1;
disp[con].inverse = 0;
disp[con].line_length = fix.line_length;
disp[con].dispsw = &dispsw_apollofb;
}
unsigned long dn_fb_init(unsigned long mem_start) {
int err;
printk("dn_fb_init\n");
fb_info.changevar=NULL;
strcpy(&fb_info.modename[0],dn_fb_name);
fb_info.fontname[0]=0;
fb_info.disp=disp;
fb_info.switch_con=&dnfbcon_switch;
fb_info.updatevar=&dnfbcon_updatevar;
fb_info.node = NODEV;
fb_info.currcon = -1;
fb_info.fbops = &dn_fb_ops;
printk("screenbase: %p\n",fix.smem_start);
printk("dn_fb_init: register\n");
err=register_framebuffer(&fb_info);
if(err < 0) {
panic("unable to register apollo frame buffer\n");
}
/* now we have registered we can safely setup the hardware */
outb(RESET_CREG, AP_CONTROL_3A);
outb(RESET_CREG, AP_CONTROL_3B);
outw(0x0, AP_WRITE_ENABLE);
outb(NORMAL_MODE, AP_CONTROL_0);
outb((AD_BLT | DST_EQ_SRC | NORM_CREG1), AP_CONTROL_1);
outb(0, AP_CONTROL_2A);
outb(S_DATA_PLN, AP_CONTROL_2B);
outw(SWAP(0x3), AP_ROP_1);
printk("apollo frame buffer alive and kicking !\n");
dn_fb_get_var(&disp[0].var,0, &fb_info);
dn_fb_set_disp(-1, &fb_info);
fb_info.screen_base = (u_char *)fix.smem_start;
return mem_start;
}
static int dnfbcon_switch(int con, struct fb_info *info) {
info->currcon = con;
return 0;
}
static int dnfbcon_updatevar(int con, struct fb_info *info) {
return 0;
}
static int dn_fb_blank(int blank, struct fb_info *info)
{
if (blank)
outb(0x0, AP_CONTROL_3A);
else
outb(0x1, AP_CONTROL_3A);
return 0;
}
void dn_bitblt(struct display *p,int x_src,int y_src, int x_dest, int y_dest,
int x_count, int y_count) {
int incr,y_delta,pre_read=0,x_end,x_word_count;
ushort *src,dummy;
uint start_mask,end_mask,dest;
short i,j;
incr=(y_dest<=y_src) ? 1 : -1 ;
src=(ushort *)(p->fb_info.screen_base+ y_src*p->next_line+(x_src >> 4));
dest=y_dest*(p->next_line >> 1)+(x_dest >> 4);
if(incr>0) {
y_delta=(p->next_line*8)-x_src-x_count;
x_end=x_dest+x_count-1;
x_word_count=(x_end>>4) - (x_dest >> 4) + 1;
start_mask=0xffff0000 >> (x_dest & 0xf);
end_mask=0x7ffff >> (x_end & 0xf);
outb((((x_dest & 0xf) - (x_src &0xf)) % 16)|(0x4 << 5),AP_CONTROL_0);
if((x_dest & 0xf) < (x_src & 0xf))
pre_read=1;
}
else {
y_delta=-((p->next_line*8)-x_src-x_count);
x_end=x_dest-x_count+1;
x_word_count=(x_dest>>4) - (x_end >> 4) + 1;
start_mask=0x7ffff >> (x_dest & 0xf);
end_mask=0xffff0000 >> (x_end & 0xf);
outb(((-((x_src & 0xf) - (x_dest &0xf))) % 16)|(0x4 << 5),AP_CONTROL_0);
if((x_dest & 0xf) > (x_src & 0xf))
pre_read=1;
}
for(i=0;i<y_count;i++) {
if(pre_read) {
dummy=*src;
src+=incr;
}
if(x_word_count) {
outb(start_mask,AP_WRITE_ENABLE);
*src=dest;
src+=incr;
dest+=incr;
outb(0,AP_WRITE_ENABLE);
for(j=1;j<(x_word_count-1);j++) {
*src=dest;
src+=incr;
dest+=incr;
}
outb(start_mask,AP_WRITE_ENABLE);
*src=dest;
dest+=incr;
src+=incr;
}
else {
outb(start_mask | end_mask, AP_WRITE_ENABLE);
*src=dest;
dest+=incr;
src+=incr;
}
src+=(y_delta/16);
dest+=(y_delta/16);
}
outb(NORMAL_MODE,AP_CONTROL_0);
}
static void bmove_apollofb(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
#ifdef USE_DN_ACCEL
dn_bitblt(p,sx,sy*p->fontheight,dx,dy*p->fontheight,width*p->fontwidth,
height*p->fontheight);
#else
u_char *src, *dest;
u_int rows;
if (sx == 0 && dx == 0 && width == p->next_line) {
src = p->fb_info.screen_base+sy*p->fontheight*width;
dest = p->fb_info.screen_base+dy*p->fontheight*width;
mymemmove(dest, src, height*p->fontheight*width);
} else if (dy <= sy) {
src = p->fb_info.screen_base+sy*p->fontheight*p->next_line+sx;
dest = p->fb_info.screen_base+dy*p->fontheight*p->next_line+dx;
for (rows = height*p->fontheight; rows--;) {
mymemmove(dest, src, width);
src += p->next_line;
dest += p->next_line;
}
} else {
src = p->fb_info.screen_base+((sy+height)*p->fontheight-1)*p->next_line+sx;
dest = p->fb_info.screen_base+((dy+height)*p->fontheight-1)*p->next_line+dx;
for (rows = height*p->fontheight; rows--;) {
mymemmove(dest, src, width);
src -= p->next_line;
dest -= p->next_line;
}
}
#endif
}
static void clear_apollofb(struct vc_data *conp, struct display *p, int sy, int sx,
int height, int width)
{
u_char *dest;
u_int rows;
dest = p->fb_info.screen_base+sy*p->fontheight*p->next_line+sx;
if (sx == 0 && width == p->next_line)
if (attr_reverse(p,conp))
mymemset(dest, height*p->fontheight*width);
else
mymemclear(dest, height*p->fontheight*width);
else
for (rows = height*p->fontheight; rows--; dest += p->next_line)
if (attr_reverse(p,conp))
mymemset(dest, width);
else
mymemclear_small(dest, width);
}
static void putc_apollofb(struct vc_data *conp, struct display *p, int c, int yy,
int xx)
{
u_char *dest, *cdat;
u_int rows, bold, revs, underl;
u_char d;
c &= 0xff;
dest = p->fb_info.screen_base+yy*p->fontheight*p->next_line+xx;
cdat = p->fontdata+c*p->fontheight;
bold = attr_bold(p,conp);
revs = attr_reverse(p,conp);
underl = attr_underline(p,conp);
for (rows = p->fontheight; rows--; dest += p->next_line) {
d = *cdat++;
if (underl && !rows)
d = 0xff;
else if (bold)
d |= d>>1;
if (revs)
d = ~d;
*dest = d;
}
}
static void putcs_apollofb(struct vc_data *conp, struct display *p, const char *s,
int count, int yy, int xx)
{
u_char *dest, *dest0, *cdat;
u_int rows, bold, revs, underl;
u_char c, d;
dest0 = p->fb_info.screen_base+yy*p->fontheight*p->next_line+xx;
bold = attr_bold(p,conp);
revs = attr_reverse(p,conp);
underl = attr_underline(p,conp);
while (count--) {
c = scr_readw(s++);
dest = dest0++;
cdat = p->fontdata+c*p->fontheight;
for (rows = p->fontheight; rows--; dest += p->next_line) {
d = *cdat++;
if (underl && !rows)
d = 0xff;
else if (bold)
d |= d>>1;
if (revs)
d = ~d;
*dest = d;
}
}
}
static void rev_char_apollofb(struct display *p, int xx, int yy)
{
u_char *dest;
u_int rows;
dest = p->fb_info.screen_base+yy*p->fontheight*p->next_line+xx;
for (rows = p->fontheight; rows--; dest += p->next_line)
*dest = ~*dest;
}
static struct display_switch dispsw_apollofb = {
setup: fbcon_mfb_setup,
bmove: bmove_apollofb,
clear: clear_apollofb,
putc: putc_apollofb,
putcs: putcs_apollofb,
revc: rev_char_apollofb,
fontwidthmask: FONTWIDTH(8)
};
MODULE_LICENSE("GPL");
......@@ -23,7 +23,6 @@
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
......@@ -42,48 +41,37 @@
/* whether are really running on a maxine, KM */
#include <asm/bootinfo.h>
#include <video/fbcon-mfb.h>
#include <video/fbcon-cfb2.h>
#include <video/fbcon-cfb4.h>
#include <video/fbcon-cfb8.h>
#define arraysize(x) (sizeof(x)/sizeof(*(x)))
static struct display disp;
static struct fb_info fb_info;
unsigned long fb_start, fb_size = 1024 * 768, fb_line_length = 1024;
unsigned long fb_regs;
unsigned char fb_bitmask;
static struct fb_var_screeninfo maxinefb_defined = {
0, 0, 0, 0, /* W,H, W, H (virtual) load xres,xres_virtual */
0, 0, /* virtual -> visible no offset */
0, /* depth -> load bits_per_pixel */
0, /* greyscale ? */
{0, 0, 0}, /* R */
{0, 0, 0}, /* G */
{0, 0, 0}, /* B */
{0, 0, 0}, /* transparency */
0, /* standard pixel format */
FB_ACTIVATE_NOW,
274, 195, /* 14" monitor */
FB_ACCEL_NONE,
0L, 0L, 0L, 0L, 0L,
0L, 0L, 0, /* No sync info */
FB_VMODE_NONINTERLACED,
{0, 0, 0, 0, 0, 0}
};
struct maxinefb_par {
xres: 1024,
yres: 768,
xres_virtual: 1024,
yres_virtual: 768,
bits_per_pixel: 8,
activate: FB_ACTIVATE_NOW,
height: -1,
width: -1,
vmode: FB_VMODE_NONINTERLACED,
};
struct maxinefb_par current_par;
static struct fb_fix_screeninfo maxinefb_fix = {
id: "Maxine onboard graphics 1024x768x8",
smem_len: (1024*768),
type: FB_TYPE_PACKED_PIXELS,
visual: FB_VISUAL_PSEUDOCOLOR,
line_length: 1024,
}
/* Reference to machine type set in arch/mips/dec/prom/identify.c, KM */
extern unsigned long mips_machtype;
/* Handle the funny Inmos RamDAC/video controller ... */
void maxinefb_ims332_write_register(int regno, register unsigned int val)
......@@ -109,212 +97,42 @@ unsigned int maxinefb_ims332_read_register(int regno)
return (j & 0xffff) | ((k & 0xff00) << 8);
}
static void maxinefb_encode_var(struct fb_var_screeninfo *var,
struct maxinefb_par *par)
{
int i = 0;
var->xres = 1024;
var->yres = 768;
var->xres_virtual = 1024;
var->yres_virtual = 768;
var->xoffset = 0;
var->yoffset = 0;
var->bits_per_pixel = 8;
var->grayscale = 0;
var->transp.offset = 0;
var->transp.length = 0;
var->transp.msb_right = 0;
var->nonstd = 0;
var->activate = 1;
var->height = -1;
var->width = -1;
var->vmode = FB_VMODE_NONINTERLACED;
var->pixclock = 0;
var->sync = 0;
var->left_margin = 0;
var->right_margin = 0;
var->upper_margin = 0;
var->lower_margin = 0;
var->hsync_len = 0;
var->vsync_len = 0;
for (i = 0; i < arraysize(var->reserved); i++)
var->reserved[i] = 0;
}
static void maxinefb_get_par(struct maxinefb_par *par)
{
*par = current_par;
}
static int maxinefb_fb_update_var(int con, struct fb_info *info)
{
return 0;
}
static int maxinefb_do_fb_set_var(struct fb_var_screeninfo *var,
int isactive)
{
struct maxinefb_par par;
maxinefb_get_par(&par);
maxinefb_encode_var(var, &par);
return 0;
}
/* Get the palette */
static int maxinefb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
unsigned int i;
unsigned long hw_colorvalue = 0; /* raw color value from the register */
unsigned int length;
if (((cmap->start) + (cmap->len)) >= 256) {
length = 256 - (cmap->start);
} else {
length = cmap->len;
}
for (i = 0; i < length; i++) {
hw_colorvalue =
maxinefb_ims332_read_register(IMS332_REG_COLOR_PALETTE
+ cmap->start + i);
(cmap->red[i]) = ((hw_colorvalue & 0x0000ff));
(cmap->green[i]) = ((hw_colorvalue & 0x00ff00) >> 8);
(cmap->blue[i]) = ((hw_colorvalue & 0xff0000) >> 16);
}
return 0;
}
/* Set the palette */
static int maxinefb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
unsigned int i;
unsigned long hw_colorvalue; /* value to be written into the palette reg. */
unsigned short cmap_red;
unsigned short cmap_green;
unsigned short cmap_blue;
unsigned int length;
hw_colorvalue = 0;
if (((cmap->start) + (cmap->len)) >= 256) {
length = 256 - (cmap->start);
} else {
length = cmap->len;
}
for (i = 0; i < length; i++) {
cmap_red = ((cmap->red[i]) >> 8); /* The cmap fields are 16 bits */
cmap_green = ((cmap->green[i]) >> 8); /* wide, but the harware colormap */
cmap_blue = ((cmap->blue[i]) >> 8); /* registers are only 8 bits wide */
hw_colorvalue =
(cmap_blue << 16) + (cmap_green << 8) + (cmap_red);
maxinefb_ims332_write_register(IMS332_REG_COLOR_PALETTE +
cmap->start + i,
hw_colorvalue);
}
return 0;
}
static int maxinefb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
struct maxinefb_par par;
if (con == -1) {
maxinefb_get_par(&par);
maxinefb_encode_var(var, &par);
} else
*var = fb_display[con].var;
return 0;
}
static int maxinefb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
static int maxinefb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp, struct fb_info *info)
{
int err;
/* value to be written into the palette reg. */
unsigned long hw_colorvalue = 0;
if ((err = maxinefb_do_fb_set_var(var, 1)))
return err;
return 0;
}
static void maxinefb_encode_fix(struct fb_fix_screeninfo *fix,
struct maxinefb_par *par)
{
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id, "maxinefb");
/* fix->id is a char[16], so a maximum of 15 characters, KM */
fix->smem_start = (char *) fb_start; /* display memory base address, KM */
fix->smem_len = fb_size;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->visual = FB_VISUAL_PSEUDOCOLOR;
fix->xpanstep = 0;
fix->ypanstep = 0;
fix->ywrapstep = 0;
fix->line_length = fb_line_length;
}
red >>= 8; /* The cmap fields are 16 bits */
green >>= 8; /* wide, but the harware colormap */
blue >>= 8; /* registers are only 8 bits wide */
static int maxinefb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info)
{
struct maxinefb_par par;
maxinefb_get_par(&par);
maxinefb_encode_fix(fix, &par);
hw_colorvalue =
(blue << 16) + (green << 8) + (red);
maxinefb_ims332_write_register(IMS332_REG_COLOR_PALETTE +
regno,
hw_colorvalue);
return 0;
}
static int maxinefb_switch(int con, struct fb_info *info)
{
maxinefb_do_fb_set_var(&fb_display[con].var, 1);
info->currcon = con;
return 0;
}
static void maxinefb_set_disp(int con)
{
struct fb_fix_screeninfo fix;
struct display *display;
if (con >= 0)
display = &fb_display[con];
else
display = &disp; /* used during initialization */
maxinefb_get_fix(&fix, con, 0);
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->next_line = fix.line_length;
display->can_soft_blank = 0;
display->inverse = 0;
display->dispsw = &fbcon_cfb8;
}
static struct fb_ops maxinefb_ops = {
owner: THIS_MODULE,
fb_get_fix: maxinefb_get_fix,
fb_get_var: maxinefb_get_var,
fb_set_var: maxinefb_set_var,
fb_get_cmap: maxinefb_get_cmap,
fb_set_cmap: maxinefb_set_cmap,
fb_get_fix: gen_get_fix,
fb_get_var: gen_get_var,
fb_set_var: gen_set_var,
fb_get_cmap: gen_get_cmap,
fb_set_cmap: gen_set_cmap,
fb_setcolreg: maxinefb_setcolreg,
fb_fillrect: cfb_fillrect,
fb_copyarea: cfb_copyarea,
fb_imageblit: cfb_imageblit,
};
int __init maxinefb_init(void)
{
volatile unsigned char *fboff;
unsigned long fb_start;
int i;
/* Validate we're on the proper machine type */
......@@ -332,6 +150,8 @@ int __init maxinefb_init(void)
for (fboff = fb_start; fboff < fb_start + 0x1ffff; fboff++)
*fboff = 0x0;
maxinefb_fix.smem_start = fb_start;
/* erase hardware cursor */
for (i = 0; i < 512; i++) {
maxinefb_ims332_write_register(IMS332_REG_CURSOR_RAM + i,
......@@ -344,34 +164,25 @@ int __init maxinefb_init(void)
*/
}
/* Fill in the available video resolution */
maxinefb_defined.xres = 1024;
maxinefb_defined.yres = 768;
maxinefb_defined.xres_virtual = 1024;
maxinefb_defined.yres_virtual = 768;
maxinefb_defined.bits_per_pixel = 8;
/* Let there be consoles... */
strcpy(fb_info.modename, "Maxine onboard graphics 1024x768x8");
/* fb_info.modename: maximum of 39 characters + trailing nullbyte, KM */
fb_info.changevar = NULL;
fb_info.node = NODEV;
fb_info.fbops = &maxinefb_ops;
fb_info.screen_base = (char *) fb_start;
fb_info.screen_base = (char *) maxinefb_fix.smem_start;
fb_info.var = maxinefb_defined;
fb_info.fix = maxinefb_fix;
fb_info.disp = &disp;
fb_info.currcon = -1;
fb_info.switch_con = &maxinefb_switch;
fb_info.updatevar = &maxinefb_fb_update_var;
fb_info.switch_con = gen_switch;
fb_info.updatevar = gen_update_var;
fb_info.flags = FBINFO_FLAG_DEFAULT;
maxinefb_do_fb_set_var(&maxinefb_defined, 1);
maxinefb_get_var(&disp.var, -1, &fb_info);
maxinefb_set_disp(-1);
gen_set_disp(-1, &fb_info);
if (register_framebuffer(&fb_info) < 0)
return 1;
return 0;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment