patch-2.1.111 linux/drivers/video/acornfb.c
Next file: linux/drivers/video/amifb.c
Previous file: linux/drivers/video/S3triofb.c
Back to the patch index
Back to the overall index
- Lines: 383
- Date:
Tue Jul 21 10:28:24 1998
- Orig file:
v2.1.110/linux/drivers/video/acornfb.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.1.110/linux/drivers/video/acornfb.c linux/drivers/video/acornfb.c
@@ -0,0 +1,382 @@
+/*
+ * linux/drivers/video/acorn.c
+ *
+ * Copyright (C) 1998 Russell King
+ *
+ * Frame buffer code for Acorn platforms
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "fbcon-mfb.h"
+#include "fbcon-cfb2.h"
+#include "fbcon-cfb4.h"
+#include "fbcon-cfb8.h"
+
+#define MAX_VIDC20_PALETTE 256
+#define MAX_VIDC_PALETTE 16
+
+struct acornfb_par {
+ unsigned long screen_base;
+ unsigned int xres;
+ unsigned int yres;
+ unsigned char bits_per_pixel;
+ unsigned int palette_size;
+
+ union {
+ union {
+ struct {
+ unsigned long red:8;
+ unsigned long green:8;
+ unsigned long blue:8;
+ unsigned long ext:4;
+ unsigned long unused:4;
+ } d;
+ unsigned long p;
+ } vidc20[MAX_VIDC20_PALETTE];
+ union {
+ struct {
+ unsigned long red:4;
+ unsigned long green:4;
+ unsigned long blue:4;
+ unsigned long trans:1;
+ unsigned long unused:19;
+ } d;
+ unsigned long p;
+ } vidc[MAX_VIDC_PALETTE];
+ } palette;
+};
+
+static int currcon = 0;
+static struct display disp;
+static struct fb_info fb_info;
+static struct acornfb_par current_par;
+
+static int
+acornfb_open(struct fb_info *info, int user)
+{
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int
+acornfb_release(struct fb_info *info, int user)
+{
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+static void
+acornfb_encode_var(struct fb_var_screeninfo *var, struct acornfb_par *par)
+{
+ var->xres = par->xres;
+ var->yres = par->yres;
+ var->xres_virtual = par->xres;
+ var->yres_virtual = par->yres;
+ var->xoffset = 0;
+ var->yoffset = 0;
+ var->bits_per_pixel = par->bits_per_pixel;
+ var->grayscale = 0;
+ var->red.offset = 0;
+ var->red.length = 8;
+ var->red.msb_right = 0;
+ var->green.offset = 0;
+ var->green.length = 8;
+ var->green.msb_right = 0;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ var->blue.msb_right = 0;
+ var->transp.offset = 0;
+ var->transp.length = 4;
+ var->transp.msb_right = 0;
+ var->nonstd = 0;
+ var->activate = FB_ACTIVATE_NOW;
+ var->height = -1;
+ var->width = -1;
+ var->vmode = FB_VMODE_NONINTERLACED;
+ var->pixclock = 1;
+ 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;
+}
+
+static int
+acornfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+{
+ struct acornfb_par *par = ¤t_par;
+ unsigned int line_length;
+
+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+ strcpy(fix->id, "Acorn");
+
+ line_length = par->xres * par->bits_per_pixel / 8;
+
+ fix->smem_start = (char *)SCREEN2_BASE;
+ fix->smem_len = (((line_length * par->yres) - 1) | (PAGE_SIZE - 1)) + 1;
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->type_aux = 0;
+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
+ fix->xpanstep = 0;
+ fix->ypanstep = 0;
+ fix->ywrapstep = 1;
+ fix->line_length = line_length;
+ fix->accel = FB_ACCEL_NONE;
+
+ return 0;
+}
+
+static int
+acornfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+ if (con == -1) {
+ acornfb_encode_var(var, ¤t_par);
+ } else
+ *var = fb_display[con].var;
+ return 0;
+}
+
+static int
+acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+ return 0;
+}
+
+static void
+acornfb_set_disp(int con)
+{
+ struct fb_fix_screeninfo fix;
+ struct display *display;
+
+ if (con >= 0)
+ display = &fb_display[con];
+ else
+ display = &disp;
+
+ current_par.xres = 8 * ORIG_VIDEO_COLS;
+ current_par.yres = 8 * ORIG_VIDEO_LINES;
+ current_par.bits_per_pixel = 8;
+ current_par.palette_size = MAX_VIDC20_PALETTE;
+
+ acornfb_get_fix(&fix, con, 0);
+
+ acornfb_get_var(&display->var, con, 0);
+
+ display->cmap.start = 0;
+ display->cmap.len = 0;
+ display->cmap.red = NULL;
+ display->cmap.green = NULL;
+ display->cmap.blue = NULL;
+ display->cmap.transp = NULL;
+ 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->line_length = fix.line_length;
+ display->can_soft_blank = 0;
+ display->inverse = 0;
+
+ outl(SCREEN_START, VDMA_START);
+ outl(SCREEN_START + fix.smem_len - VDMA_XFERSIZE, VDMA_END);
+ outl(SCREEN_START, VDMA_INIT);
+
+ switch (display->var.bits_per_pixel) {
+#ifdef FBCON_HAS_MFB
+ case 1:
+ display->dispsw = &fbcon_mfb;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB2
+ case 2:
+ display->dispsw = &fbcon_cfb2;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB4
+ case 4:
+ display->dispsw = &fbcon_cfb4;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ display->dispsw = &fbcon_cfb8;
+ break;
+#endif
+ default:
+ display->dispsw = NULL;
+ break;
+ }
+}
+
+static int
+acornfb_vidc20_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *trans, struct fb_info *info)
+{
+ if (regno >= current_par.palette_size)
+ return 1;
+ *red = current_par.palette.vidc20[regno].d.red;
+ *green = current_par.palette.vidc20[regno].d.green;
+ *blue = current_par.palette.vidc20[regno].d.blue;
+ *trans = current_par.palette.vidc20[regno].d.ext;
+ return 0;
+}
+
+static int
+acornfb_vidc20_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int trans, struct fb_info *info)
+{
+ if (regno >= current_par.palette_size)
+ return 1;
+
+ current_par.palette.vidc20[regno].p = 0;
+ current_par.palette.vidc20[regno].d.red = red;
+ current_par.palette.vidc20[regno].d.green = green;
+ current_par.palette.vidc20[regno].d.blue = blue;
+
+ outl(0x10000000 | regno, VIDC_BASE);
+ outl(current_par.palette.vidc20[regno].p, VIDC_BASE);
+
+ return 0;
+}
+
+static int
+acornfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
+{
+ int err = 0;
+
+ if (con == currcon)
+ err = fb_get_cmap(cmap, &fb_display[con].var,
+ kspc, acornfb_vidc20_getcolreg, info);
+ else if (fb_display[con].cmap.len)
+ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+ else
+ fb_copy_cmap(fb_default_cmap(current_par.palette_size),
+ cmap, kspc ? 0 : 2);
+ return err;
+}
+
+static int
+acornfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
+{
+ int err = 0;
+
+ if (!fb_display[con].cmap.len)
+ err = fb_alloc_cmap(&fb_display[con].cmap,
+ current_par.palette_size, 0);
+ if (!err) {
+ if (con == currcon)
+ err = fb_set_cmap(cmap, &fb_display[con].var,
+ kspc, acornfb_vidc20_setcolreg, info);
+ else
+ fb_copy_cmap(cmap, &fb_display[con].cmap,
+ kspc ? 0 : 1);
+ }
+ return err;
+}
+
+static int
+acornfb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
+{
+ if (var->xoffset || var->yoffset)
+ return -EINVAL;
+ else
+ return 0;
+}
+
+static int
+acornfb_ioctl(struct inode *ino, struct file *file, unsigned int cmd,
+ unsigned long arg, int con, struct fb_info *info)
+{
+ return -ENOIOCTLCMD;
+}
+
+static struct fb_ops acornfb_ops = {
+ acornfb_open,
+ acornfb_release,
+ acornfb_get_fix,
+ acornfb_get_var,
+ acornfb_set_var,
+ acornfb_get_cmap,
+ acornfb_set_cmap,
+ acornfb_pan_display,
+ acornfb_ioctl
+};
+
+void
+acornfb_setup(char *options, int *ints)
+{
+}
+
+static int
+acornfb_update_var(int con, struct fb_info *info)
+{
+ if (con == currcon) {
+ int off = fb_display[con].var.yoffset *
+ fb_display[con].var.xres_virtual *
+ fb_display[con].var.bits_per_pixel >> 3;
+ unsigned long base;
+
+ base = current_par.screen_base = SCREEN_START + off;
+
+ outl (SCREEN_START + base, VDMA_INIT);
+ }
+
+ return 0;
+}
+
+static int
+acornfb_switch(int con, struct fb_info *info)
+{
+ currcon = con;
+ acornfb_update_var(con, info);
+ return 0;
+}
+
+static void
+acornfb_blank(int blank, struct fb_info *info)
+{
+}
+
+__initfunc(unsigned long
+acornfb_init(unsigned long mem_start))
+{
+ strcpy(fb_info.modename, "Acorn");
+ fb_info.node = -1;
+ fb_info.fbops = &acornfb_ops;
+ fb_info.disp = &disp;
+ fb_info.monspecs.hfmin = 0;
+ fb_info.monspecs.hfmax = 0;
+ fb_info.monspecs.vfmin = 0;
+ fb_info.monspecs.vfmax = 0;
+ fb_info.monspecs.dpms = 0;
+ strcpy(fb_info.fontname, "Acorn8x8");
+ fb_info.changevar = NULL;
+ fb_info.switch_con = acornfb_switch;
+ fb_info.updatevar = acornfb_update_var;
+ fb_info.blank = acornfb_blank;
+
+ acornfb_set_disp(-1);
+ fb_set_cmap(fb_default_cmap(current_par.palette_size), &fb_display[0].var,
+ 1, acornfb_vidc20_setcolreg, &fb_info);
+ register_framebuffer(&fb_info);
+
+ return mem_start;
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov