/*
* linux/drivers/video/sgivwfb.c -- SGI DBE frame buffer device
*
* Copyright (C) 1999 Silicon Graphics, Inc.
* Jeffrey Newquist, newquist@engr.sgi.som
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/mtrr.h>
#define INCLUDE_TIMING_TABLE_DATA
#define DBE_REG_BASE par->regs
#include <video/sgivw.h>
struct sgivw_par {
struct asregs *regs;
u32 cmap_fifo;
u_long timing_num;
};
#define FLATPANEL_SGI_1600SW 5
/*
* RAM we reserve for the frame buffer. This defines the maximum screen
* size
*
* The default can be overridden if the driver is compiled as a module
*/
/* set by arch/i386/kernel/setup.c */
extern unsigned long sgivwfb_mem_phys;
extern unsigned long sgivwfb_mem_size;
static int ypan = 0;
static int ywrap = 0;
static int flatpanel_id = -1;
static struct fb_fix_screeninfo sgivwfb_fix __initdata = {
.id = "SGI Vis WS FB",
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_PSEUDOCOLOR,
.mmio_start = DBE_REG_PHYS,
.mmio_len = DBE_REG_SIZE,
.accel = FB_ACCEL_NONE,
.line_length = 640,
};
static struct fb_var_screeninfo sgivwfb_var __initdata = {
/* 640x480, 8 bpp */
.xres = 640,
.yres = 480,
.xres_virtual = 640,
.yres_virtual = 480,
.bits_per_pixel = 8,
.red = { 0, 8, 0 },
.green = { 0, 8, 0 },
.blue = { 0, 8, 0 },
.height = -1,
.width = -1,
.pixclock = 20000,
.left_margin = 64,
.right_margin = 64,
.upper_margin = 32,
.lower_margin = 32,
.hsync_len = 64,
.vsync_len = 2,
.vmode = FB_VMODE_NONINTERLACED
};
static struct fb_var_screeninfo sgivwfb_var1600sw __initdata = {
/* 1600x1024, 8 bpp */
.xres = 1600,
.yres = 1024,
.xres_virtual = 1600,
.yres_virtual = 1024,
.bits_per_pixel = 8,
.red = { 0, 8, 0 },
.green = { 0, 8, 0 },
.blue = { 0, 8, 0 },
.height = -1,
.width = -1,
.pixclock = 9353,
.left_margin = 20,
.right_margin = 30,
.upper_margin = 37,
.lower_margin = 3,
.hsync_len = 20,
.vsync_len = 3,
.vmode = FB_VMODE_NONINTERLACED
};
/*
* Interface used by the world
*/
int sgivwfb_init(void);
static int sgivwfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
static int sgivwfb_set_par(struct fb_info *info);
static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green,
u_int blue, u_int transp,
struct fb_info *info);
static int sgivwfb_mmap(struct fb_info *info, struct file *file,
struct vm_area_struct *vma);
static struct fb_ops sgivwfb_ops = {
.owner = THIS_MODULE,
.fb_check_var = sgivwfb_check_var,
.fb_set_par = sgivwfb_set_par,
.fb_setcolreg = sgivwfb_setcolreg,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_mmap = sgivwfb_mmap,
};
/*
* Internal routines
*/
static unsigned long bytes_per_pixel(int bpp)
{
switch (bpp) {
case 8:
return 1;
case 16:
return 2;
case 32:
return 4;
default:
printk(KERN_INFO "sgivwfb: unsupported bpp %d\n", bpp);
return 0;
}
}
static unsigned long get_line_length(int xres_virtual, int bpp)
{
return (xres_virtual * bytes_per_pixel(bpp));
}
/*
* Function: dbe_TurnOffDma
* Parameters: (None)
* Description: This should turn off the monitor and dbe. This is used
* when switching between the serial console and the graphics
* console.
*/
static void dbe_TurnOffDma(struct sgivw_par *par)
{
unsigned int readVal;
int i;
// Check to see if things are already turned off:
// 1) Check to see if dbe is not using the internal dotclock.
// 2) Check to see if the xy counter in dbe is already off.
DBE_GETREG(ctrlstat, readVal);
if (GET_DBE_FIELD(CTRLSTAT, PCLKSEL, readVal) < 2)
return;
DBE_GETREG(vt_xy, readVal);
if (GET_DBE_FIELD(VT_XY, VT_FREEZE, readVal) == 1)
return;
// Otherwise, turn off dbe