patch-2.2.3 linux/drivers/video/q40fb.c
Next file: linux/drivers/video/retz3fb.c
Previous file: linux/drivers/video/promcon.c
Back to the patch index
Back to the overall index
- Lines: 363
- Date:
Thu Feb 25 10:02:12 1999
- Orig file:
v2.2.2/linux/drivers/video/q40fb.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.2.2/linux/drivers/video/q40fb.c linux/drivers/video/q40fb.c
@@ -0,0 +1,362 @@
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+/*#include <asm/irq.h>*/
+#include <asm/q40_master.h>
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <asm/pgtable.h>
+
+#include <video/fbcon-cfb16.h>
+
+
+#define Q40_PHYS_SCREEN_ADDR 0xFE800000
+static unsigned long q40_screen_addr;
+
+static u16 fbcon_cmap_cfb16[16];
+
+/* frame buffer operations */
+
+static int q40fb_open(struct fb_info *info, int user);
+static int q40fb_release(struct fb_info *info, int user);
+static int q40fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info);
+static int q40fb_get_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int q40fb_set_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int q40fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
+ struct fb_info *info);
+static int q40fb_set_cmap(struct fb_cmap *cmap,int kspc,int con,
+ struct fb_info *info);
+static int q40fb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int q40fb_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg, int con,
+ struct fb_info *info);
+
+static int q40con_switch(int con, struct fb_info *info);
+static int q40con_updatevar(int con, struct fb_info *info);
+static void q40con_blank(int blank, struct fb_info *info);
+
+static void q40fb_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 q40fb_ops = {
+ q40fb_open,q40fb_release, q40fb_get_fix, q40fb_get_var, q40fb_set_var,
+ q40fb_get_cmap, q40fb_set_cmap, q40fb_pan_display, q40fb_ioctl
+};
+
+static int currcon=0;
+
+static char q40fb_name[]="Q40";
+
+static int q40fb_open(struct fb_info *info, int user)
+{
+ /*
+ * Nothing, only a usage count for the moment
+ */
+
+ MOD_INC_USE_COUNT;
+ return(0);
+}
+
+static int q40fb_release(struct fb_info *info, int user)
+{
+ MOD_DEC_USE_COUNT;
+ return(0);
+}
+
+static int q40fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info)
+{
+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+
+ strcpy(fix->id,"Q40");
+ fix->smem_start=(char*)q40_screen_addr;
+ fix->smem_len=1024*1024;
+ fix->type=FB_TYPE_PACKED_PIXELS;
+ fix->type_aux=0;
+ fix->visual=FB_VISUAL_TRUECOLOR; /* good approximation so far ..*/;
+ fix->xpanstep=0;
+ fix->ypanstep=0;
+ fix->ywrapstep=0;
+ fix->line_length=1024*2;
+
+ /* no mmio,accel ...*/
+
+ return 0;
+
+}
+
+static int q40fb_get_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
+{
+ memset(var, 0, sizeof(struct fb_var_screeninfo));
+
+ var->xres=1024;
+ var->yres=512;
+ var->xres_virtual=1024;
+ var->yres_virtual=512;
+ var->xoffset=0;
+ var->yoffset=0;
+ var->bits_per_pixel=16;
+ var->grayscale=0;
+ var->nonstd=0;
+ var->activate=FB_ACTIVATE_NOW;
+ var->height=230; /* approx for my 17" monitor, more important */
+ var->width=300; /* than the absolute values is the unusual aspect ratio*/
+
+ var->red.offset=6; /*6*/
+ var->red.length=5;
+ var->green.offset=11; /*11*/
+ var->green.length=5;
+ var->blue.offset=0;
+ var->blue.length=6;
+ var->transp.length=0;
+
+ 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 q40fb_set_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
+{
+ if(var->xres!=1024)
+ return -EINVAL;
+ if(var->yres!=512)
+ return -EINVAL;
+ if(var->xres_virtual!=1024)
+ return -EINVAL;
+ if(var->yres_virtual!=512)
+ return -EINVAL;
+ if(var->xoffset!=0)
+ return -EINVAL;
+ if(var->yoffset!=0)
+ return -EINVAL;
+ if(var->bits_per_pixel!=16)
+ return -EINVAL;
+ if(var->grayscale!=0)
+ return -EINVAL;
+ if(var->nonstd!=0)
+ return -EINVAL;
+ if(var->activate!=FB_ACTIVATE_NOW)
+ 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 q40_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+ unsigned *blue, unsigned *transp,
+ struct fb_info *info)
+{
+ /*
+ * Read a single color register and split it into colors/transparent.
+ * The return values must have a 16 bit magnitude.
+ * Return != 0 for invalid regno.
+ */
+ if (regno>=16) return 1;
+
+ *transp=0;
+ *green = ((fbcon_cmap_cfb16[regno]>>11) & 31)<<11;
+ *red = ((fbcon_cmap_cfb16[regno]>>6) & 31)<<11;
+ *blue = ((fbcon_cmap_cfb16[regno]) & 63)<<10;
+
+ return 0;
+}
+
+static int q40_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ const struct fb_info *info)
+{
+ /*
+ * Set a single color register. The values supplied have a 16 bit
+ * magnitude.
+ * Return != 0 for invalid regno.
+ */
+
+ red>>=11;
+ green>>=11;
+ blue>>=10;
+
+ if (regno < 16) {
+ fbcon_cmap_cfb16[regno] = ((red & 31) <<5) |
+ ((green & 31) << 11) |
+ (blue & 63);
+ }
+ return 0;
+}
+
+static int q40fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
+{
+#if 1
+ if (con == currcon) /* current console? */
+ return fb_get_cmap(cmap, kspc, q40_getcolreg, info);
+ else if (fb_display[con].cmap.len) /* non default colormap? */
+ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+ else
+ fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
+ cmap, kspc ? 0 : 2);
+ return 0;
+#else
+ printk("get cmap not supported\n");
+
+ return -EINVAL;
+#endif
+}
+
+static int q40fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
+{
+#if 1
+ int err;
+
+ if (!fb_display[con].cmap.len) { /* no colormap allocated? */
+ if ((err = fb_alloc_cmap(&fb_display[con].cmap,
+ 1<<fb_display[con].var.bits_per_pixel,
+ 0)))
+ return err;
+ }
+ if (con == currcon) /* current console? */
+ return fb_set_cmap(cmap, kspc, q40_setcolreg, info);
+ else
+ fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+ return 0;
+#else
+ printk("set cmap not supported\n");
+
+ return -EINVAL;
+#endif
+}
+
+static int q40fb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
+{
+ printk("panning not supported\n");
+
+ return -EINVAL;
+
+}
+
+static int q40fb_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg, int con,
+ struct fb_info *info)
+{
+ return -EINVAL;
+}
+
+static void q40fb_set_disp(int con, struct fb_info *info)
+{
+ struct fb_fix_screeninfo fix;
+ struct display *display;
+
+ q40fb_get_fix(&fix, con, info);
+
+ if (con>=0)
+ display = &fb_display[con];
+ else
+ display = &disp[0];
+
+ if (con<0) con=0;
+
+ display->screen_base = fix.smem_start;
+ 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 = 0;
+ display->inverse = 0;
+ display->line_length = fix.line_length;
+
+#ifdef FBCON_HAS_CFB16
+ display->dispsw = &fbcon_cfb16;
+ disp->dispsw_data = fbcon_cmap_cfb16;
+#else
+ display->dispsw = &fbcon_dummy;
+#endif
+}
+
+void q40fb_init(void)
+{
+#if 0
+ q40_screen_addr = kernel_map(Q40_PHYS_SCREEN_ADDR, 1024*1024,
+ KERNELMAP_NO_COPYBACK, NULL);
+#else
+ q40_screen_addr = Q40_PHYS_SCREEN_ADDR; /* mapped in q40/config.c */
+#endif
+
+ fb_info.changevar=NULL;
+ strcpy(&fb_info.modename[0],q40fb_name);
+ fb_info.fontname[0]=0;
+ fb_info.disp=disp;
+ fb_info.switch_con=&q40con_switch;
+ fb_info.updatevar=&q40con_updatevar;
+ fb_info.blank=&q40con_blank;
+ fb_info.node = -1;
+ fb_info.fbops = &q40fb_ops;
+ fb_info.flags = FBINFO_FLAG_DEFAULT; /* not as module for now */
+
+ master_outb(3,DISPLAY_CONTROL_REG);
+
+ q40fb_get_var(&disp[0].var, 0, &fb_info);
+ q40fb_set_disp(-1, &fb_info);
+
+ if (register_framebuffer(&fb_info) < 0)
+ panic("unable to register Q40 frame buffer\n");
+
+
+ printk("fb%d: Q40 frame buffer alive and kicking !\n",
+ GET_FB_IDX(fb_info.node));
+}
+
+
+static int q40con_switch(int con, struct fb_info *info)
+{
+ currcon=con;
+
+ return 0;
+
+}
+
+static int q40con_updatevar(int con, struct fb_info *info)
+{
+ return 0;
+}
+
+static void q40con_blank(int blank, struct fb_info *info)
+{
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)