video: move fbdev to drivers/video/fbdev
The drivers/video directory is a mess. It contains generic video related files, directories for backlight, console, linux logo, lots of fbdev device drivers, fbdev framework files. Make some order into the chaos by creating drivers/video/fbdev directory, and move all fbdev related files there. No functionality is changed, although I guess it is possible that some subtle Makefile build order related issue could be created by this patch. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Geert Uytterhoeven <geert@linux-m68k.org> Acked-by: Rob Clark <robdclark@gmail.com> Acked-by: Jingoo Han <jg1.han@samsung.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
c26ef3eb3c
commit
f7018c2135
481 changed files with 2672 additions and 2662 deletions
|
|
@ -276,7 +276,7 @@ X!Isound/sound_firmware.c
|
|||
</para>
|
||||
|
||||
<sect1><title>Frame Buffer Memory</title>
|
||||
!Edrivers/video/fbmem.c
|
||||
!Edrivers/video/fbdev/fbmem.c
|
||||
</sect1>
|
||||
<!--
|
||||
<sect1><title>Frame Buffer Console</title>
|
||||
|
|
@ -284,7 +284,7 @@ X!Edrivers/video/console/fbcon.c
|
|||
</sect1>
|
||||
-->
|
||||
<sect1><title>Frame Buffer Colormap</title>
|
||||
!Edrivers/video/fbcmap.c
|
||||
!Edrivers/video/fbdev/fbcmap.c
|
||||
</sect1>
|
||||
<!-- FIXME:
|
||||
drivers/video/fbgen.c has no docs, which stuffs up the sgml. Comment
|
||||
|
|
@ -294,11 +294,11 @@ X!Idrivers/video/fbgen.c
|
|||
</sect1>
|
||||
KAO -->
|
||||
<sect1><title>Frame Buffer Video Mode Database</title>
|
||||
!Idrivers/video/modedb.c
|
||||
!Edrivers/video/modedb.c
|
||||
!Idrivers/video/fbdev/modedb.c
|
||||
!Edrivers/video/fbdev/modedb.c
|
||||
</sect1>
|
||||
<sect1><title>Frame Buffer Macintosh Video Mode Database</title>
|
||||
!Edrivers/video/macmodes.c
|
||||
!Edrivers/video/fbdev/macmodes.c
|
||||
</sect1>
|
||||
<sect1><title>Frame Buffer Fonts</title>
|
||||
<para>
|
||||
|
|
|
|||
|
|
@ -53,8 +53,8 @@ obj-y += gpu/
|
|||
obj-$(CONFIG_CONNECTOR) += connector/
|
||||
|
||||
# i810fb and intelfb depend on char/agp/
|
||||
obj-$(CONFIG_FB_I810) += video/i810/
|
||||
obj-$(CONFIG_FB_INTEL) += video/intelfb/
|
||||
obj-$(CONFIG_FB_I810) += video/fbdev/i810/
|
||||
obj-$(CONFIG_FB_INTEL) += video/fbdev/intelfb/
|
||||
|
||||
obj-$(CONFIG_PARPORT) += parport/
|
||||
obj-y += base/ block/ misc/ mfd/ nfc/
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#ifndef _VB_DEF_
|
||||
#define _VB_DEF_
|
||||
#include "../../video/sis/initdef.h"
|
||||
#include "../../video/fbdev/sis/initdef.h"
|
||||
|
||||
#define VB_XGI301C 0x0020 /* for 301C */
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#ifndef _VB_STRUCT_
|
||||
#define _VB_STRUCT_
|
||||
#include "../../video/sis/vstruct.h"
|
||||
#include "../../video/fbdev/sis/vstruct.h"
|
||||
|
||||
struct XGI_LVDSCRT1HDataStruct {
|
||||
unsigned char Reg[8];
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
#define _VGATYPES_
|
||||
|
||||
#include <linux/fb.h> /* for struct fb_var_screeninfo for sis.h */
|
||||
#include "../../video/sis/vgatypes.h"
|
||||
#include "../../video/sis/sis.h" /* for LCD_TYPE */
|
||||
#include "../../video/fbdev/sis/vgatypes.h"
|
||||
#include "../../video/fbdev/sis/sis.h" /* for LCD_TYPE */
|
||||
|
||||
#ifndef XGI_VB_CHIP_TYPE
|
||||
enum XGI_VB_CHIP_TYPE {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,175 +1,11 @@
|
|||
# Makefile for the Linux video drivers.
|
||||
# 5 Aug 1999, James Simmons, <mailto:jsimmons@users.sf.net>
|
||||
# Rewritten to use lists instead of if-statements.
|
||||
|
||||
# Each configuration option enables a list of files.
|
||||
|
||||
obj-$(CONFIG_VGASTATE) += vgastate.o
|
||||
obj-$(CONFIG_HDMI) += hdmi.o
|
||||
obj-y += fb_notify.o
|
||||
obj-$(CONFIG_FB) += fb.o
|
||||
fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
|
||||
modedb.o fbcvt.o
|
||||
fb-objs := $(fb-y)
|
||||
|
||||
obj-$(CONFIG_VT) += console/
|
||||
obj-$(CONFIG_LOGO) += logo/
|
||||
obj-y += backlight/
|
||||
|
||||
obj-$(CONFIG_EXYNOS_VIDEO) += exynos/
|
||||
|
||||
obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o
|
||||
obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o
|
||||
obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o
|
||||
obj-$(CONFIG_FB_SYS_FILLRECT) += sysfillrect.o
|
||||
obj-$(CONFIG_FB_SYS_COPYAREA) += syscopyarea.o
|
||||
obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimgblt.o
|
||||
obj-$(CONFIG_FB_SYS_FOPS) += fb_sys_fops.o
|
||||
obj-$(CONFIG_FB_SVGALIB) += svgalib.o
|
||||
obj-$(CONFIG_FB_MACMODES) += macmodes.o
|
||||
obj-$(CONFIG_FB_DDC) += fb_ddc.o
|
||||
obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o
|
||||
obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o
|
||||
|
||||
# Hardware specific drivers go first
|
||||
obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o
|
||||
obj-$(CONFIG_FB_ARC) += arcfb.o
|
||||
obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o
|
||||
obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
|
||||
obj-$(CONFIG_FB_GRVGA) += grvga.o
|
||||
obj-$(CONFIG_FB_PM2) += pm2fb.o
|
||||
obj-$(CONFIG_FB_PM3) += pm3fb.o
|
||||
|
||||
obj-$(CONFIG_FB_I740) += i740fb.o
|
||||
obj-$(CONFIG_FB_MATROX) += matrox/
|
||||
obj-$(CONFIG_FB_RIVA) += riva/
|
||||
obj-$(CONFIG_FB_NVIDIA) += nvidia/
|
||||
obj-$(CONFIG_FB_ATY) += aty/ macmodes.o
|
||||
obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o
|
||||
obj-$(CONFIG_FB_RADEON) += aty/
|
||||
obj-$(CONFIG_FB_SIS) += sis/
|
||||
obj-$(CONFIG_FB_VIA) += via/
|
||||
obj-$(CONFIG_FB_KYRO) += kyro/
|
||||
obj-$(CONFIG_FB_SAVAGE) += savage/
|
||||
obj-$(CONFIG_FB_GEODE) += geode/
|
||||
obj-$(CONFIG_FB_MBX) += mbx/
|
||||
obj-$(CONFIG_FB_NEOMAGIC) += neofb.o
|
||||
obj-$(CONFIG_FB_3DFX) += tdfxfb.o
|
||||
obj-$(CONFIG_FB_CONTROL) += controlfb.o
|
||||
obj-$(CONFIG_FB_PLATINUM) += platinumfb.o
|
||||
obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o
|
||||
obj-$(CONFIG_FB_CT65550) += chipsfb.o
|
||||
obj-$(CONFIG_FB_IMSTT) += imsttfb.o
|
||||
obj-$(CONFIG_FB_FM2) += fm2fb.o
|
||||
obj-$(CONFIG_FB_VT8623) += vt8623fb.o
|
||||
obj-$(CONFIG_FB_TRIDENT) += tridentfb.o
|
||||
obj-$(CONFIG_FB_LE80578) += vermilion/
|
||||
obj-$(CONFIG_FB_S3) += s3fb.o
|
||||
obj-$(CONFIG_FB_ARK) += arkfb.o
|
||||
obj-$(CONFIG_FB_STI) += stifb.o
|
||||
obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o
|
||||
obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o
|
||||
obj-$(CONFIG_FB_CG3) += cg3.o sbuslib.o
|
||||
obj-$(CONFIG_FB_BW2) += bw2.o sbuslib.o
|
||||
obj-$(CONFIG_FB_CG14) += cg14.o sbuslib.o
|
||||
obj-$(CONFIG_FB_P9100) += p9100.o sbuslib.o
|
||||
obj-$(CONFIG_FB_TCX) += tcx.o sbuslib.o
|
||||
obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o
|
||||
obj-$(CONFIG_FB_ACORN) += acornfb.o
|
||||
obj-$(CONFIG_FB_ATARI) += atafb.o c2p_iplan2.o atafb_mfb.o \
|
||||
atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o
|
||||
obj-$(CONFIG_FB_MAC) += macfb.o
|
||||
obj-$(CONFIG_FB_HECUBA) += hecubafb.o
|
||||
obj-$(CONFIG_FB_N411) += n411.o
|
||||
obj-$(CONFIG_FB_HGA) += hgafb.o
|
||||
obj-$(CONFIG_FB_XVR500) += sunxvr500.o
|
||||
obj-$(CONFIG_FB_XVR2500) += sunxvr2500.o
|
||||
obj-$(CONFIG_FB_XVR1000) += sunxvr1000.o
|
||||
obj-$(CONFIG_FB_IGA) += igafb.o
|
||||
obj-$(CONFIG_FB_APOLLO) += dnfb.o
|
||||
obj-$(CONFIG_FB_Q40) += q40fb.o
|
||||
obj-$(CONFIG_FB_TGA) += tgafb.o
|
||||
obj-$(CONFIG_FB_HP300) += hpfb.o
|
||||
obj-$(CONFIG_FB_G364) += g364fb.o
|
||||
obj-$(CONFIG_FB_EP93XX) += ep93xx-fb.o
|
||||
obj-$(CONFIG_FB_SA1100) += sa1100fb.o
|
||||
obj-$(CONFIG_FB_HIT) += hitfb.o
|
||||
obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o
|
||||
obj-$(CONFIG_FB_PVR2) += pvr2fb.o
|
||||
obj-$(CONFIG_FB_VOODOO1) += sstfb.o
|
||||
obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o
|
||||
obj-$(CONFIG_FB_GOLDFISH) += goldfishfb.o
|
||||
obj-$(CONFIG_FB_68328) += 68328fb.o
|
||||
obj-$(CONFIG_FB_GBE) += gbefb.o
|
||||
obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o
|
||||
obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o
|
||||
obj-$(CONFIG_FB_PXA) += pxafb.o
|
||||
obj-$(CONFIG_FB_PXA168) += pxa168fb.o
|
||||
obj-$(CONFIG_PXA3XX_GCU) += pxa3xx-gcu.o
|
||||
obj-$(CONFIG_MMP_DISP) += mmp/
|
||||
obj-$(CONFIG_FB_W100) += w100fb.o
|
||||
obj-$(CONFIG_FB_TMIO) += tmiofb.o
|
||||
obj-$(CONFIG_FB_AU1100) += au1100fb.o
|
||||
obj-$(CONFIG_FB_AU1200) += au1200fb.o
|
||||
obj-$(CONFIG_FB_VT8500) += vt8500lcdfb.o
|
||||
obj-$(CONFIG_FB_WM8505) += wm8505fb.o
|
||||
obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.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_METRONOME) += metronomefb.o
|
||||
obj-$(CONFIG_FB_BROADSHEET) += broadsheetfb.o
|
||||
obj-$(CONFIG_FB_AUO_K190X) += auo_k190x.o
|
||||
obj-$(CONFIG_FB_AUO_K1900) += auo_k1900fb.o
|
||||
obj-$(CONFIG_FB_AUO_K1901) += auo_k1901fb.o
|
||||
obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o
|
||||
obj-$(CONFIG_FB_SH7760) += sh7760fb.o
|
||||
obj-$(CONFIG_FB_IMX) += imxfb.o
|
||||
obj-$(CONFIG_FB_S3C) += s3c-fb.o
|
||||
obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o
|
||||
obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o
|
||||
obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o
|
||||
obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
|
||||
obj-$(CONFIG_FB_PS3) += ps3fb.o
|
||||
obj-$(CONFIG_FB_SM501) += sm501fb.o
|
||||
obj-$(CONFIG_FB_UDL) += udlfb.o
|
||||
obj-$(CONFIG_FB_SMSCUFX) += smscufx.o
|
||||
obj-$(CONFIG_FB_XILINX) += xilinxfb.o
|
||||
obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o
|
||||
obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o
|
||||
obj-$(CONFIG_FB_SH_MOBILE_MERAM) += sh_mobile_meram.o
|
||||
obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
|
||||
obj-$(CONFIG_FB_OMAP) += omap/
|
||||
obj-y += omap2/
|
||||
obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
|
||||
obj-$(CONFIG_FB_CARMINE) += carminefb.o
|
||||
obj-$(CONFIG_FB_MB862XX) += mb862xx/
|
||||
obj-$(CONFIG_FB_MSM) += msm/
|
||||
obj-$(CONFIG_FB_NUC900) += nuc900fb.o
|
||||
obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o
|
||||
obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o
|
||||
obj-$(CONFIG_FB_HYPERV) += hyperv_fb.o
|
||||
obj-$(CONFIG_FB_OPENCORES) += ocfb.o
|
||||
|
||||
# Platform or fallback drivers go here
|
||||
obj-$(CONFIG_FB_UVESA) += uvesafb.o
|
||||
obj-$(CONFIG_FB_VESA) += vesafb.o
|
||||
obj-$(CONFIG_FB_EFI) += efifb.o
|
||||
obj-$(CONFIG_FB_VGA16) += vga16fb.o
|
||||
obj-$(CONFIG_FB_OF) += offb.o
|
||||
obj-$(CONFIG_FB_BF537_LQ035) += bf537-lq035.o
|
||||
obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o
|
||||
obj-$(CONFIG_FB_BFIN_LQ035Q1) += bfin-lq035q1-fb.o
|
||||
obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o
|
||||
obj-$(CONFIG_FB_BFIN_7393) += bfin_adv7393fb.o
|
||||
obj-$(CONFIG_FB_MX3) += mx3fb.o
|
||||
obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o
|
||||
obj-$(CONFIG_FB_MXS) += mxsfb.o
|
||||
obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o
|
||||
obj-$(CONFIG_FB_SIMPLE) += simplefb.o
|
||||
|
||||
# the test framebuffer is last
|
||||
obj-$(CONFIG_FB_VIRTUAL) += vfb.o
|
||||
obj-y += fbdev/
|
||||
|
||||
obj-$(CONFIG_VIDEOMODE_HELPERS) += display_timing.o videomode.o
|
||||
ifeq ($(CONFIG_OF),y)
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
|
||||
#include <asm/io.h>
|
||||
|
||||
#include "../sticore.h"
|
||||
#include "../fbdev/sticore.h"
|
||||
|
||||
/* switching to graphics mode */
|
||||
#define BLANK 0
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
#include <asm/cacheflush.h>
|
||||
#include <asm/grfioctl.h>
|
||||
|
||||
#include "../sticore.h"
|
||||
#include "../fbdev/sticore.h"
|
||||
|
||||
#define STI_DRIVERVERSION "Version 0.9b"
|
||||
|
||||
|
|
|
|||
503
drivers/video/fbdev/68328fb.c
Normal file
503
drivers/video/fbdev/68328fb.c
Normal file
|
|
@ -0,0 +1,503 @@
|
|||
/*
|
||||
* linux/drivers/video/68328fb.c -- Low level implementation of the
|
||||
* mc68x328 LCD frame buffer device
|
||||
*
|
||||
* Copyright (C) 2003 Georges Menie
|
||||
*
|
||||
* This driver assumes an already configured controller (e.g. from config.c)
|
||||
* Keep the code clean of board specific initialization.
|
||||
*
|
||||
* This code has not been tested with colors, colormap management functions
|
||||
* are minimal (no colormap data written to the 68328 registers...)
|
||||
*
|
||||
* initial version of this driver:
|
||||
* Copyright (C) 1998,1999 Kenneth Albanowski <kjahds@kjahds.com>,
|
||||
* The Silver Hammer Group, Ltd.
|
||||
*
|
||||
* this version is based on :
|
||||
*
|
||||
* linux/drivers/video/vfb.c -- Virtual frame buffer device
|
||||
*
|
||||
* Copyright (C) 2002 James Simmons
|
||||
*
|
||||
* Copyright (C) 1997 Geert Uytterhoeven
|
||||
*
|
||||
* 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/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#if defined(CONFIG_M68VZ328)
|
||||
#include <asm/MC68VZ328.h>
|
||||
#elif defined(CONFIG_M68EZ328)
|
||||
#include <asm/MC68EZ328.h>
|
||||
#elif defined(CONFIG_M68328)
|
||||
#include <asm/MC68328.h>
|
||||
#else
|
||||
#error wrong architecture for the MC68x328 frame buffer device
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_FB_68328_INVERT)
|
||||
#define MC68X328FB_MONO_VISUAL FB_VISUAL_MONO01
|
||||
#else
|
||||
#define MC68X328FB_MONO_VISUAL FB_VISUAL_MONO10
|
||||
#endif
|
||||
|
||||
static u_long videomemory;
|
||||
static u_long videomemorysize;
|
||||
|
||||
static struct fb_info fb_info;
|
||||
static u32 mc68x328fb_pseudo_palette[16];
|
||||
|
||||
static struct fb_var_screeninfo mc68x328fb_default __initdata = {
|
||||
.red = { 0, 8, 0 },
|
||||
.green = { 0, 8, 0 },
|
||||
.blue = { 0, 8, 0 },
|
||||
.activate = FB_ACTIVATE_TEST,
|
||||
.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_fix_screeninfo mc68x328fb_fix __initdata = {
|
||||
.id = "68328fb",
|
||||
.type = FB_TYPE_PACKED_PIXELS,
|
||||
.xpanstep = 1,
|
||||
.ypanstep = 1,
|
||||
.ywrapstep = 1,
|
||||
.accel = FB_ACCEL_NONE,
|
||||
};
|
||||
|
||||
/*
|
||||
* Interface used by the world
|
||||
*/
|
||||
int mc68x328fb_init(void);
|
||||
int mc68x328fb_setup(char *);
|
||||
|
||||
static int mc68x328fb_check_var(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info);
|
||||
static int mc68x328fb_set_par(struct fb_info *info);
|
||||
static int mc68x328fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
|
||||
u_int transp, struct fb_info *info);
|
||||
static int mc68x328fb_pan_display(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info);
|
||||
static int mc68x328fb_mmap(struct fb_info *info, struct vm_area_struct *vma);
|
||||
|
||||
static struct fb_ops mc68x328fb_ops = {
|
||||
.fb_check_var = mc68x328fb_check_var,
|
||||
.fb_set_par = mc68x328fb_set_par,
|
||||
.fb_setcolreg = mc68x328fb_setcolreg,
|
||||
.fb_pan_display = mc68x328fb_pan_display,
|
||||
.fb_fillrect = cfb_fillrect,
|
||||
.fb_copyarea = cfb_copyarea,
|
||||
.fb_imageblit = cfb_imageblit,
|
||||
.fb_mmap = mc68x328fb_mmap,
|
||||
};
|
||||
|
||||
/*
|
||||
* Internal routines
|
||||
*/
|
||||
|
||||
static u_long get_line_length(int xres_virtual, int bpp)
|
||||
{
|
||||
u_long length;
|
||||
|
||||
length = xres_virtual * bpp;
|
||||
length = (length + 31) & ~31;
|
||||
length >>= 3;
|
||||
return (length);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setting the video mode has been split into two parts.
|
||||
* First part, xxxfb_check_var, must not write anything
|
||||
* to hardware, it should only verify and adjust var.
|
||||
* This means it doesn't alter par but it does use hardware
|
||||
* data from it to check this var.
|
||||
*/
|
||||
|
||||
static int mc68x328fb_check_var(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info)
|
||||
{
|
||||
u_long line_length;
|
||||
|
||||
/*
|
||||
* FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
|
||||
* as FB_VMODE_SMOOTH_XPAN is only used internally
|
||||
*/
|
||||
|
||||
if (var->vmode & FB_VMODE_CONUPDATE) {
|
||||
var->vmode |= FB_VMODE_YWRAP;
|
||||
var->xoffset = info->var.xoffset;
|
||||
var->yoffset = info->var.yoffset;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some very basic checks
|
||||
*/
|
||||
if (!var->xres)
|
||||
var->xres = 1;
|
||||
if (!var->yres)
|
||||
var->yres = 1;
|
||||
if (var->xres > var->xres_virtual)
|
||||
var->xres_virtual = var->xres;
|
||||
if (var->yres > var->yres_virtual)
|
||||
var->yres_virtual = var->yres;
|
||||
if (var->bits_per_pixel <= 1)
|
||||
var->bits_per_pixel = 1;
|
||||
else if (var->bits_per_pixel <= 8)
|
||||
var->bits_per_pixel = 8;
|
||||
else if (var->bits_per_pixel <= 16)
|
||||
var->bits_per_pixel = 16;
|
||||
else if (var->bits_per_pixel <= 24)
|
||||
var->bits_per_pixel = 24;
|
||||
else if (var->bits_per_pixel <= 32)
|
||||
var->bits_per_pixel = 32;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
if (var->xres_virtual < var->xoffset + var->xres)
|
||||
var->xres_virtual = var->xoffset + var->xres;
|
||||
if (var->yres_virtual < var->yoffset + var->yres)
|
||||
var->yres_virtual = var->yoffset + var->yres;
|
||||
|
||||
/*
|
||||
* Memory limit
|
||||
*/
|
||||
line_length =
|
||||
get_line_length(var->xres_virtual, var->bits_per_pixel);
|
||||
if (line_length * var->yres_virtual > videomemorysize)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Now that we checked it we alter var. The reason being is that the video
|
||||
* mode passed in might not work but slight changes to it might make it
|
||||
* work. This way we let the user know what is acceptable.
|
||||
*/
|
||||
switch (var->bits_per_pixel) {
|
||||
case 1:
|
||||
var->red.offset = 0;
|
||||
var->red.length = 1;
|
||||
var->green.offset = 0;
|
||||
var->green.length = 1;
|
||||
var->blue.offset = 0;
|
||||
var->blue.length = 1;
|
||||
var->transp.offset = 0;
|
||||
var->transp.length = 0;
|
||||
break;
|
||||
case 8:
|
||||
var->red.offset = 0;
|
||||
var->red.length = 8;
|
||||
var->green.offset = 0;
|
||||
var->green.length = 8;
|
||||
var->blue.offset = 0;
|
||||
var->blue.length = 8;
|
||||
var->transp.offset = 0;
|
||||
var->transp.length = 0;
|
||||
break;
|
||||
case 16: /* RGBA 5551 */
|
||||
if (var->transp.length) {
|
||||
var->red.offset = 0;
|
||||
var->red.length = 5;
|
||||
var->green.offset = 5;
|
||||
var->green.length = 5;
|
||||
var->blue.offset = 10;
|
||||
var->blue.length = 5;
|
||||
var->transp.offset = 15;
|
||||
var->transp.length = 1;
|
||||
} else { /* RGB 565 */
|
||||
var->red.offset = 0;
|
||||
var->red.length = 5;
|
||||
var->green.offset = 5;
|
||||
var->green.length = 6;
|
||||
var->blue.offset = 11;
|
||||
var->blue.length = 5;
|
||||
var->transp.offset = 0;
|
||||
var->transp.length = 0;
|
||||
}
|
||||
break;
|
||||
case 24: /* RGB 888 */
|
||||
var->red.offset = 0;
|
||||
var->red.length = 8;
|
||||
var->green.offset = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.offset = 16;
|
||||
var->blue.length = 8;
|
||||
var->transp.offset = 0;
|
||||
var->transp.length = 0;
|
||||
break;
|
||||
case 32: /* RGBA 8888 */
|
||||
var->red.offset = 0;
|
||||
var->red.length = 8;
|
||||
var->green.offset = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.offset = 16;
|
||||
var->blue.length = 8;
|
||||
var->transp.offset = 24;
|
||||
var->transp.length = 8;
|
||||
break;
|
||||
}
|
||||
var->red.msb_right = 0;
|
||||
var->green.msb_right = 0;
|
||||
var->blue.msb_right = 0;
|
||||
var->transp.msb_right = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This routine actually sets the video mode. It's in here where we
|
||||
* the hardware state info->par and fix which can be affected by the
|
||||
* change in par. For this driver it doesn't do much.
|
||||
*/
|
||||
static int mc68x328fb_set_par(struct fb_info *info)
|
||||
{
|
||||
info->fix.line_length = get_line_length(info->var.xres_virtual,
|
||||
info->var.bits_per_pixel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a single color register. The values supplied are already
|
||||
* rounded down to the hardware's capabilities (according to the
|
||||
* entries in the var structure). Return != 0 for invalid regno.
|
||||
*/
|
||||
|
||||
static int mc68x328fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
|
||||
u_int transp, struct fb_info *info)
|
||||
{
|
||||
if (regno >= 256) /* no. of hw registers */
|
||||
return 1;
|
||||
/*
|
||||
* Program hardware... do anything you want with transp
|
||||
*/
|
||||
|
||||
/* grayscale works only partially under directcolor */
|
||||
if (info->var.grayscale) {
|
||||
/* grayscale = 0.30*R + 0.59*G + 0.11*B */
|
||||
red = green = blue =
|
||||
(red * 77 + green * 151 + blue * 28) >> 8;
|
||||
}
|
||||
|
||||
/* Directcolor:
|
||||
* var->{color}.offset contains start of bitfield
|
||||
* var->{color}.length contains length of bitfield
|
||||
* {hardwarespecific} contains width of RAMDAC
|
||||
* cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
|
||||
* RAMDAC[X] is programmed to (red, green, blue)
|
||||
*
|
||||
* Pseudocolor:
|
||||
* uses offset = 0 && length = RAMDAC register width.
|
||||
* var->{color}.offset is 0
|
||||
* var->{color}.length contains width of DAC
|
||||
* cmap is not used
|
||||
* RAMDAC[X] is programmed to (red, green, blue)
|
||||
* Truecolor:
|
||||
* does not use DAC. Usually 3 are present.
|
||||
* var->{color}.offset contains start of bitfield
|
||||
* var->{color}.length contains length of bitfield
|
||||
* cmap is programmed to (red << red.offset) | (green << green.offset) |
|
||||
* (blue << blue.offset) | (transp << transp.offset)
|
||||
* RAMDAC does not exist
|
||||
*/
|
||||
#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
|
||||
switch (info->fix.visual) {
|
||||
case FB_VISUAL_TRUECOLOR:
|
||||
case FB_VISUAL_PSEUDOCOLOR:
|
||||
red = CNVT_TOHW(red, info->var.red.length);
|
||||
green = CNVT_TOHW(green, info->var.green.length);
|
||||
blue = CNVT_TOHW(blue, info->var.blue.length);
|
||||
transp = CNVT_TOHW(transp, info->var.transp.length);
|
||||
break;
|
||||
case FB_VISUAL_DIRECTCOLOR:
|
||||
red = CNVT_TOHW(red, 8); /* expect 8 bit DAC */
|
||||
green = CNVT_TOHW(green, 8);
|
||||
blue = CNVT_TOHW(blue, 8);
|
||||
/* hey, there is bug in transp handling... */
|
||||
transp = CNVT_TOHW(transp, 8);
|
||||
break;
|
||||
}
|
||||
#undef CNVT_TOHW
|
||||
/* Truecolor has hardware independent palette */
|
||||
if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
|
||||
u32 v;
|
||||
|
||||
if (regno >= 16)
|
||||
return 1;
|
||||
|
||||
v = (red << info->var.red.offset) |
|
||||
(green << info->var.green.offset) |
|
||||
(blue << info->var.blue.offset) |
|
||||
(transp << info->var.transp.offset);
|
||||
switch (info->var.bits_per_pixel) {
|
||||
case 8:
|
||||
break;
|
||||
case 16:
|
||||
((u32 *) (info->pseudo_palette))[regno] = v;
|
||||
break;
|
||||
case 24:
|
||||
case 32:
|
||||
((u32 *) (info->pseudo_palette))[regno] = v;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pan or Wrap the Display
|
||||
*
|
||||
* This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
|
||||
*/
|
||||
|
||||
static int mc68x328fb_pan_display(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info)
|
||||
{
|
||||
if (var->vmode & FB_VMODE_YWRAP) {
|
||||
if (var->yoffset < 0
|
||||
|| var->yoffset >= info->var.yres_virtual
|
||||
|| var->xoffset)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (var->xoffset + info->var.xres > info->var.xres_virtual ||
|
||||
var->yoffset + info->var.yres > info->var.yres_virtual)
|
||||
return -EINVAL;
|
||||
}
|
||||
info->var.xoffset = var->xoffset;
|
||||
info->var.yoffset = var->yoffset;
|
||||
if (var->vmode & FB_VMODE_YWRAP)
|
||||
info->var.vmode |= FB_VMODE_YWRAP;
|
||||
else
|
||||
info->var.vmode &= ~FB_VMODE_YWRAP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Most drivers don't need their own mmap function
|
||||
*/
|
||||
|
||||
static int mc68x328fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
|
||||
{
|
||||
#ifndef MMU
|
||||
/* this is uClinux (no MMU) specific code */
|
||||
|
||||
vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
|
||||
vma->vm_start = videomemory;
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return -EINVAL;
|
||||
#endif
|
||||
}
|
||||
|
||||
int __init mc68x328fb_setup(char *options)
|
||||
{
|
||||
#if 0
|
||||
char *this_opt;
|
||||
#endif
|
||||
|
||||
if (!options || !*options)
|
||||
return 1;
|
||||
#if 0
|
||||
while ((this_opt = strsep(&options, ",")) != NULL) {
|
||||
if (!*this_opt)
|
||||
continue;
|
||||
if (!strncmp(this_opt, "disable", 7))
|
||||
mc68x328fb_enable = 0;
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialisation
|
||||
*/
|
||||
|
||||
int __init mc68x328fb_init(void)
|
||||
{
|
||||
#ifndef MODULE
|
||||
char *option = NULL;
|
||||
|
||||
if (fb_get_options("68328fb", &option))
|
||||
return -ENODEV;
|
||||
mc68x328fb_setup(option);
|
||||
#endif
|
||||
/*
|
||||
* initialize the default mode from the LCD controller registers
|
||||
*/
|
||||
mc68x328fb_default.xres = LXMAX;
|
||||
mc68x328fb_default.yres = LYMAX+1;
|
||||
mc68x328fb_default.xres_virtual = mc68x328fb_default.xres;
|
||||
mc68x328fb_default.yres_virtual = mc68x328fb_default.yres;
|
||||
mc68x328fb_default.bits_per_pixel = 1 + (LPICF & 0x01);
|
||||
videomemory = LSSA;
|
||||
videomemorysize = (mc68x328fb_default.xres_virtual+7) / 8 *
|
||||
mc68x328fb_default.yres_virtual * mc68x328fb_default.bits_per_pixel;
|
||||
|
||||
fb_info.screen_base = (void *)videomemory;
|
||||
fb_info.fbops = &mc68x328fb_ops;
|
||||
fb_info.var = mc68x328fb_default;
|
||||
fb_info.fix = mc68x328fb_fix;
|
||||
fb_info.fix.smem_start = videomemory;
|
||||
fb_info.fix.smem_len = videomemorysize;
|
||||
fb_info.fix.line_length =
|
||||
get_line_length(mc68x328fb_default.xres_virtual, mc68x328fb_default.bits_per_pixel);
|
||||
fb_info.fix.visual = (mc68x328fb_default.bits_per_pixel) == 1 ?
|
||||
MC68X328FB_MONO_VISUAL : FB_VISUAL_PSEUDOCOLOR;
|
||||
if (fb_info.var.bits_per_pixel == 1) {
|
||||
fb_info.var.red.length = fb_info.var.green.length = fb_info.var.blue.length = 1;
|
||||
fb_info.var.red.offset = fb_info.var.green.offset = fb_info.var.blue.offset = 0;
|
||||
}
|
||||
fb_info.pseudo_palette = &mc68x328fb_pseudo_palette;
|
||||
fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
|
||||
|
||||
if (fb_alloc_cmap(&fb_info.cmap, 256, 0))
|
||||
return -ENOMEM;
|
||||
|
||||
if (register_framebuffer(&fb_info) < 0) {
|
||||
fb_dealloc_cmap(&fb_info.cmap);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fb_info(&fb_info, "%s frame buffer device\n", fb_info.fix.id);
|
||||
fb_info(&fb_info, "%dx%dx%d at 0x%08lx\n",
|
||||
mc68x328fb_default.xres_virtual,
|
||||
mc68x328fb_default.yres_virtual,
|
||||
1 << mc68x328fb_default.bits_per_pixel, videomemory);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(mc68x328fb_init);
|
||||
|
||||
#ifdef MODULE
|
||||
|
||||
static void __exit mc68x328fb_cleanup(void)
|
||||
{
|
||||
unregister_framebuffer(&fb_info);
|
||||
fb_dealloc_cmap(&fb_info.cmap);
|
||||
}
|
||||
|
||||
module_exit(mc68x328fb_cleanup);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
#endif /* MODULE */
|
||||
2474
drivers/video/fbdev/Kconfig
Normal file
2474
drivers/video/fbdev/Kconfig
Normal file
File diff suppressed because it is too large
Load diff
166
drivers/video/fbdev/Makefile
Normal file
166
drivers/video/fbdev/Makefile
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
# Makefile for the Linux video drivers.
|
||||
# 5 Aug 1999, James Simmons, <mailto:jsimmons@users.sf.net>
|
||||
# Rewritten to use lists instead of if-statements.
|
||||
|
||||
# Each configuration option enables a list of files.
|
||||
|
||||
obj-y += fb_notify.o
|
||||
obj-$(CONFIG_FB) += fb.o
|
||||
fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
|
||||
modedb.o fbcvt.o
|
||||
fb-objs := $(fb-y)
|
||||
|
||||
obj-$(CONFIG_EXYNOS_VIDEO) += exynos/
|
||||
|
||||
obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o
|
||||
obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o
|
||||
obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o
|
||||
obj-$(CONFIG_FB_SYS_FILLRECT) += sysfillrect.o
|
||||
obj-$(CONFIG_FB_SYS_COPYAREA) += syscopyarea.o
|
||||
obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimgblt.o
|
||||
obj-$(CONFIG_FB_SYS_FOPS) += fb_sys_fops.o
|
||||
obj-$(CONFIG_FB_SVGALIB) += svgalib.o
|
||||
obj-$(CONFIG_FB_MACMODES) += macmodes.o
|
||||
obj-$(CONFIG_FB_DDC) += fb_ddc.o
|
||||
obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o
|
||||
obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o
|
||||
|
||||
# Hardware specific drivers go first
|
||||
obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o
|
||||
obj-$(CONFIG_FB_ARC) += arcfb.o
|
||||
obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o
|
||||
obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
|
||||
obj-$(CONFIG_FB_GRVGA) += grvga.o
|
||||
obj-$(CONFIG_FB_PM2) += pm2fb.o
|
||||
obj-$(CONFIG_FB_PM3) += pm3fb.o
|
||||
|
||||
obj-$(CONFIG_FB_I740) += i740fb.o
|
||||
obj-$(CONFIG_FB_MATROX) += matrox/
|
||||
obj-$(CONFIG_FB_RIVA) += riva/
|
||||
obj-$(CONFIG_FB_NVIDIA) += nvidia/
|
||||
obj-$(CONFIG_FB_ATY) += aty/ macmodes.o
|
||||
obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o
|
||||
obj-$(CONFIG_FB_RADEON) += aty/
|
||||
obj-$(CONFIG_FB_SIS) += sis/
|
||||
obj-$(CONFIG_FB_VIA) += via/
|
||||
obj-$(CONFIG_FB_KYRO) += kyro/
|
||||
obj-$(CONFIG_FB_SAVAGE) += savage/
|
||||
obj-$(CONFIG_FB_GEODE) += geode/
|
||||
obj-$(CONFIG_FB_MBX) += mbx/
|
||||
obj-$(CONFIG_FB_NEOMAGIC) += neofb.o
|
||||
obj-$(CONFIG_FB_3DFX) += tdfxfb.o
|
||||
obj-$(CONFIG_FB_CONTROL) += controlfb.o
|
||||
obj-$(CONFIG_FB_PLATINUM) += platinumfb.o
|
||||
obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o
|
||||
obj-$(CONFIG_FB_CT65550) += chipsfb.o
|
||||
obj-$(CONFIG_FB_IMSTT) += imsttfb.o
|
||||
obj-$(CONFIG_FB_FM2) += fm2fb.o
|
||||
obj-$(CONFIG_FB_VT8623) += vt8623fb.o
|
||||
obj-$(CONFIG_FB_TRIDENT) += tridentfb.o
|
||||
obj-$(CONFIG_FB_LE80578) += vermilion/
|
||||
obj-$(CONFIG_FB_S3) += s3fb.o
|
||||
obj-$(CONFIG_FB_ARK) += arkfb.o
|
||||
obj-$(CONFIG_FB_STI) += stifb.o
|
||||
obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o
|
||||
obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o
|
||||
obj-$(CONFIG_FB_CG3) += cg3.o sbuslib.o
|
||||
obj-$(CONFIG_FB_BW2) += bw2.o sbuslib.o
|
||||
obj-$(CONFIG_FB_CG14) += cg14.o sbuslib.o
|
||||
obj-$(CONFIG_FB_P9100) += p9100.o sbuslib.o
|
||||
obj-$(CONFIG_FB_TCX) += tcx.o sbuslib.o
|
||||
obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o
|
||||
obj-$(CONFIG_FB_ACORN) += acornfb.o
|
||||
obj-$(CONFIG_FB_ATARI) += atafb.o c2p_iplan2.o atafb_mfb.o \
|
||||
atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o
|
||||
obj-$(CONFIG_FB_MAC) += macfb.o
|
||||
obj-$(CONFIG_FB_HECUBA) += hecubafb.o
|
||||
obj-$(CONFIG_FB_N411) += n411.o
|
||||
obj-$(CONFIG_FB_HGA) += hgafb.o
|
||||
obj-$(CONFIG_FB_XVR500) += sunxvr500.o
|
||||
obj-$(CONFIG_FB_XVR2500) += sunxvr2500.o
|
||||
obj-$(CONFIG_FB_XVR1000) += sunxvr1000.o
|
||||
obj-$(CONFIG_FB_IGA) += igafb.o
|
||||
obj-$(CONFIG_FB_APOLLO) += dnfb.o
|
||||
obj-$(CONFIG_FB_Q40) += q40fb.o
|
||||
obj-$(CONFIG_FB_TGA) += tgafb.o
|
||||
obj-$(CONFIG_FB_HP300) += hpfb.o
|
||||
obj-$(CONFIG_FB_G364) += g364fb.o
|
||||
obj-$(CONFIG_FB_EP93XX) += ep93xx-fb.o
|
||||
obj-$(CONFIG_FB_SA1100) += sa1100fb.o
|
||||
obj-$(CONFIG_FB_HIT) += hitfb.o
|
||||
obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o
|
||||
obj-$(CONFIG_FB_PVR2) += pvr2fb.o
|
||||
obj-$(CONFIG_FB_VOODOO1) += sstfb.o
|
||||
obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o
|
||||
obj-$(CONFIG_FB_GOLDFISH) += goldfishfb.o
|
||||
obj-$(CONFIG_FB_68328) += 68328fb.o
|
||||
obj-$(CONFIG_FB_GBE) += gbefb.o
|
||||
obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o
|
||||
obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o
|
||||
obj-$(CONFIG_FB_PXA) += pxafb.o
|
||||
obj-$(CONFIG_FB_PXA168) += pxa168fb.o
|
||||
obj-$(CONFIG_PXA3XX_GCU) += pxa3xx-gcu.o
|
||||
obj-$(CONFIG_MMP_DISP) += mmp/
|
||||
obj-$(CONFIG_FB_W100) += w100fb.o
|
||||
obj-$(CONFIG_FB_TMIO) += tmiofb.o
|
||||
obj-$(CONFIG_FB_AU1100) += au1100fb.o
|
||||
obj-$(CONFIG_FB_AU1200) += au1200fb.o
|
||||
obj-$(CONFIG_FB_VT8500) += vt8500lcdfb.o
|
||||
obj-$(CONFIG_FB_WM8505) += wm8505fb.o
|
||||
obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.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_METRONOME) += metronomefb.o
|
||||
obj-$(CONFIG_FB_BROADSHEET) += broadsheetfb.o
|
||||
obj-$(CONFIG_FB_AUO_K190X) += auo_k190x.o
|
||||
obj-$(CONFIG_FB_AUO_K1900) += auo_k1900fb.o
|
||||
obj-$(CONFIG_FB_AUO_K1901) += auo_k1901fb.o
|
||||
obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o
|
||||
obj-$(CONFIG_FB_SH7760) += sh7760fb.o
|
||||
obj-$(CONFIG_FB_IMX) += imxfb.o
|
||||
obj-$(CONFIG_FB_S3C) += s3c-fb.o
|
||||
obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o
|
||||
obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o
|
||||
obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o
|
||||
obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
|
||||
obj-$(CONFIG_FB_PS3) += ps3fb.o
|
||||
obj-$(CONFIG_FB_SM501) += sm501fb.o
|
||||
obj-$(CONFIG_FB_UDL) += udlfb.o
|
||||
obj-$(CONFIG_FB_SMSCUFX) += smscufx.o
|
||||
obj-$(CONFIG_FB_XILINX) += xilinxfb.o
|
||||
obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o
|
||||
obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o
|
||||
obj-$(CONFIG_FB_SH_MOBILE_MERAM) += sh_mobile_meram.o
|
||||
obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
|
||||
obj-$(CONFIG_FB_OMAP) += omap/
|
||||
obj-y += omap2/
|
||||
obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
|
||||
obj-$(CONFIG_FB_CARMINE) += carminefb.o
|
||||
obj-$(CONFIG_FB_MB862XX) += mb862xx/
|
||||
obj-$(CONFIG_FB_MSM) += msm/
|
||||
obj-$(CONFIG_FB_NUC900) += nuc900fb.o
|
||||
obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o
|
||||
obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o
|
||||
obj-$(CONFIG_FB_HYPERV) += hyperv_fb.o
|
||||
obj-$(CONFIG_FB_OPENCORES) += ocfb.o
|
||||
|
||||
# Platform or fallback drivers go here
|
||||
obj-$(CONFIG_FB_UVESA) += uvesafb.o
|
||||
obj-$(CONFIG_FB_VESA) += vesafb.o
|
||||
obj-$(CONFIG_FB_EFI) += efifb.o
|
||||
obj-$(CONFIG_FB_VGA16) += vga16fb.o
|
||||
obj-$(CONFIG_FB_OF) += offb.o
|
||||
obj-$(CONFIG_FB_BF537_LQ035) += bf537-lq035.o
|
||||
obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o
|
||||
obj-$(CONFIG_FB_BFIN_LQ035Q1) += bfin-lq035q1-fb.o
|
||||
obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o
|
||||
obj-$(CONFIG_FB_BFIN_7393) += bfin_adv7393fb.o
|
||||
obj-$(CONFIG_FB_MX3) += mx3fb.o
|
||||
obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o
|
||||
obj-$(CONFIG_FB_MXS) += mxsfb.o
|
||||
obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o
|
||||
obj-$(CONFIG_FB_SIMPLE) += simplefb.o
|
||||
|
||||
# the test framebuffer is last
|
||||
obj-$(CONFIG_FB_VIRTUAL) += vfb.o
|
||||
1143
drivers/video/fbdev/acornfb.c
Normal file
1143
drivers/video/fbdev/acornfb.c
Normal file
File diff suppressed because it is too large
Load diff
169
drivers/video/fbdev/acornfb.h
Normal file
169
drivers/video/fbdev/acornfb.h
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* linux/drivers/video/acornfb.h
|
||||
*
|
||||
* Copyright (C) 1998,1999 Russell King
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Frame buffer code for Acorn platforms
|
||||
*/
|
||||
#if defined(HAS_VIDC20)
|
||||
#include <asm/hardware/iomd.h>
|
||||
#define VIDC_PALETTE_SIZE 256
|
||||
#define VIDC_NAME "VIDC20"
|
||||
#endif
|
||||
|
||||
#define EXTEND8(x) ((x)|(x)<<8)
|
||||
#define EXTEND4(x) ((x)|(x)<<4|(x)<<8|(x)<<12)
|
||||
|
||||
struct vidc20_palette {
|
||||
u_int red:8;
|
||||
u_int green:8;
|
||||
u_int blue:8;
|
||||
u_int ext:4;
|
||||
u_int unused:4;
|
||||
};
|
||||
|
||||
struct vidc_palette {
|
||||
u_int red:4;
|
||||
u_int green:4;
|
||||
u_int blue:4;
|
||||
u_int trans:1;
|
||||
u_int sbz1:13;
|
||||
u_int reg:4;
|
||||
u_int sbz2:2;
|
||||
};
|
||||
|
||||
union palette {
|
||||
struct vidc20_palette vidc20;
|
||||
struct vidc_palette vidc;
|
||||
u_int p;
|
||||
};
|
||||
|
||||
struct acornfb_par {
|
||||
struct device *dev;
|
||||
unsigned long screen_end;
|
||||
unsigned int dram_size;
|
||||
unsigned int vram_half_sam;
|
||||
unsigned int palette_size;
|
||||
signed int montype;
|
||||
unsigned int using_vram : 1;
|
||||
unsigned int dpms : 1;
|
||||
|
||||
union palette palette[VIDC_PALETTE_SIZE];
|
||||
|
||||
u32 pseudo_palette[16];
|
||||
};
|
||||
|
||||
struct vidc_timing {
|
||||
u_int h_cycle;
|
||||
u_int h_sync_width;
|
||||
u_int h_border_start;
|
||||
u_int h_display_start;
|
||||
u_int h_display_end;
|
||||
u_int h_border_end;
|
||||
u_int h_interlace;
|
||||
|
||||
u_int v_cycle;
|
||||
u_int v_sync_width;
|
||||
u_int v_border_start;
|
||||
u_int v_display_start;
|
||||
u_int v_display_end;
|
||||
u_int v_border_end;
|
||||
|
||||
u_int control;
|
||||
|
||||
/* VIDC20 only */
|
||||
u_int pll_ctl;
|
||||
};
|
||||
|
||||
struct modey_params {
|
||||
u_int y_res;
|
||||
u_int u_margin;
|
||||
u_int b_margin;
|
||||
u_int vsync_len;
|
||||
u_int vf;
|
||||
};
|
||||
|
||||
struct modex_params {
|
||||
u_int x_res;
|
||||
u_int l_margin;
|
||||
u_int r_margin;
|
||||
u_int hsync_len;
|
||||
u_int clock;
|
||||
u_int hf;
|
||||
const struct modey_params *modey;
|
||||
};
|
||||
|
||||
#ifdef HAS_VIDC20
|
||||
/*
|
||||
* VIDC20 registers
|
||||
*/
|
||||
#define VIDC20_CTRL 0xe0000000
|
||||
#define VIDC20_CTRL_PIX_VCLK (0 << 0)
|
||||
#define VIDC20_CTRL_PIX_HCLK (1 << 0)
|
||||
#define VIDC20_CTRL_PIX_RCLK (2 << 0)
|
||||
#define VIDC20_CTRL_PIX_CK (0 << 2)
|
||||
#define VIDC20_CTRL_PIX_CK2 (1 << 2)
|
||||
#define VIDC20_CTRL_PIX_CK3 (2 << 2)
|
||||
#define VIDC20_CTRL_PIX_CK4 (3 << 2)
|
||||
#define VIDC20_CTRL_PIX_CK5 (4 << 2)
|
||||
#define VIDC20_CTRL_PIX_CK6 (5 << 2)
|
||||
#define VIDC20_CTRL_PIX_CK7 (6 << 2)
|
||||
#define VIDC20_CTRL_PIX_CK8 (7 << 2)
|
||||
#define VIDC20_CTRL_1BPP (0 << 5)
|
||||
#define VIDC20_CTRL_2BPP (1 << 5)
|
||||
#define VIDC20_CTRL_4BPP (2 << 5)
|
||||
#define VIDC20_CTRL_8BPP (3 << 5)
|
||||
#define VIDC20_CTRL_16BPP (4 << 5)
|
||||
#define VIDC20_CTRL_32BPP (6 << 5)
|
||||
#define VIDC20_CTRL_FIFO_NS (0 << 8)
|
||||
#define VIDC20_CTRL_FIFO_4 (1 << 8)
|
||||
#define VIDC20_CTRL_FIFO_8 (2 << 8)
|
||||
#define VIDC20_CTRL_FIFO_12 (3 << 8)
|
||||
#define VIDC20_CTRL_FIFO_16 (4 << 8)
|
||||
#define VIDC20_CTRL_FIFO_20 (5 << 8)
|
||||
#define VIDC20_CTRL_FIFO_24 (6 << 8)
|
||||
#define VIDC20_CTRL_FIFO_28 (7 << 8)
|
||||
#define VIDC20_CTRL_INT (1 << 12)
|
||||
#define VIDC20_CTRL_DUP (1 << 13)
|
||||
#define VIDC20_CTRL_PDOWN (1 << 14)
|
||||
|
||||
#define VIDC20_ECTL 0xc0000000
|
||||
#define VIDC20_ECTL_REG(x) ((x) & 0xf3)
|
||||
#define VIDC20_ECTL_ECK (1 << 2)
|
||||
#define VIDC20_ECTL_REDPED (1 << 8)
|
||||
#define VIDC20_ECTL_GREENPED (1 << 9)
|
||||
#define VIDC20_ECTL_BLUEPED (1 << 10)
|
||||
#define VIDC20_ECTL_DAC (1 << 12)
|
||||
#define VIDC20_ECTL_LCDGS (1 << 13)
|
||||
#define VIDC20_ECTL_HRM (1 << 14)
|
||||
|
||||
#define VIDC20_ECTL_HS_MASK (3 << 16)
|
||||
#define VIDC20_ECTL_HS_HSYNC (0 << 16)
|
||||
#define VIDC20_ECTL_HS_NHSYNC (1 << 16)
|
||||
#define VIDC20_ECTL_HS_CSYNC (2 << 16)
|
||||
#define VIDC20_ECTL_HS_NCSYNC (3 << 16)
|
||||
|
||||
#define VIDC20_ECTL_VS_MASK (3 << 18)
|
||||
#define VIDC20_ECTL_VS_VSYNC (0 << 18)
|
||||
#define VIDC20_ECTL_VS_NVSYNC (1 << 18)
|
||||
#define VIDC20_ECTL_VS_CSYNC (2 << 18)
|
||||
#define VIDC20_ECTL_VS_NCSYNC (3 << 18)
|
||||
|
||||
#define VIDC20_DCTL 0xf0000000
|
||||
/* 0-9 = number of words in scanline */
|
||||
#define VIDC20_DCTL_SNA (1 << 12)
|
||||
#define VIDC20_DCTL_HDIS (1 << 13)
|
||||
#define VIDC20_DCTL_BUS_NS (0 << 16)
|
||||
#define VIDC20_DCTL_BUS_D31_0 (1 << 16)
|
||||
#define VIDC20_DCTL_BUS_D63_32 (2 << 16)
|
||||
#define VIDC20_DCTL_BUS_D63_0 (3 << 16)
|
||||
#define VIDC20_DCTL_VRAM_DIS (0 << 18)
|
||||
#define VIDC20_DCTL_VRAM_PXCLK (1 << 18)
|
||||
#define VIDC20_DCTL_VRAM_PXCLK2 (2 << 18)
|
||||
#define VIDC20_DCTL_VRAM_PXCLK4 (3 << 18)
|
||||
|
||||
#endif
|
||||
656
drivers/video/fbdev/amba-clcd.c
Normal file
656
drivers/video/fbdev/amba-clcd.c
Normal file
|
|
@ -0,0 +1,656 @@
|
|||
/*
|
||||
* linux/drivers/video/amba-clcd.c
|
||||
*
|
||||
* Copyright (C) 2001 ARM Limited, by David A Rusling
|
||||
* Updated to 2.5, Deep Blue Solutions Ltd.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* ARM PrimeCell PL110 Color LCD Controller
|
||||
*/
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/amba/clcd.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/hardirq.h>
|
||||
|
||||
#include <asm/sizes.h>
|
||||
|
||||
#define to_clcd(info) container_of(info, struct clcd_fb, fb)
|
||||
|
||||
/* This is limited to 16 characters when displayed by X startup */
|
||||
static const char *clcd_name = "CLCD FB";
|
||||
|
||||
/*
|
||||
* Unfortunately, the enable/disable functions may be called either from
|
||||
* process or IRQ context, and we _need_ to delay. This is _not_ good.
|
||||
*/
|
||||
static inline void clcdfb_sleep(unsigned int ms)
|
||||
{
|
||||
if (in_atomic()) {
|
||||
mdelay(ms);
|
||||
} else {
|
||||
msleep(ms);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void clcdfb_set_start(struct clcd_fb *fb)
|
||||
{
|
||||
unsigned long ustart = fb->fb.fix.smem_start;
|
||||
unsigned long lstart;
|
||||
|
||||
ustart += fb->fb.var.yoffset * fb->fb.fix.line_length;
|
||||
lstart = ustart + fb->fb.var.yres * fb->fb.fix.line_length / 2;
|
||||
|
||||
writel(ustart, fb->regs + CLCD_UBAS);
|
||||
writel(lstart, fb->regs + CLCD_LBAS);
|
||||
}
|
||||
|
||||
static void clcdfb_disable(struct clcd_fb *fb)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (fb->board->disable)
|
||||
fb->board->disable(fb);
|
||||
|
||||
val = readl(fb->regs + fb->off_cntl);
|
||||
if (val & CNTL_LCDPWR) {
|
||||
val &= ~CNTL_LCDPWR;
|
||||
writel(val, fb->regs + fb->off_cntl);
|
||||
|
||||
clcdfb_sleep(20);
|
||||
}
|
||||
if (val & CNTL_LCDEN) {
|
||||
val &= ~CNTL_LCDEN;
|
||||
writel(val, fb->regs + fb->off_cntl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable CLCD clock source.
|
||||
*/
|
||||
if (fb->clk_enabled) {
|
||||
fb->clk_enabled = false;
|
||||
clk_disable(fb->clk);
|
||||
}
|
||||
}
|
||||
|
||||
static void clcdfb_enable(struct clcd_fb *fb, u32 cntl)
|
||||
{
|
||||
/*
|
||||
* Enable the CLCD clock source.
|
||||
*/
|
||||
if (!fb->clk_enabled) {
|
||||
fb->clk_enabled = true;
|
||||
clk_enable(fb->clk);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bring up by first enabling..
|
||||
*/
|
||||
cntl |= CNTL_LCDEN;
|
||||
writel(cntl, fb->regs + fb->off_cntl);
|
||||
|
||||
clcdfb_sleep(20);
|
||||
|
||||
/*
|
||||
* and now apply power.
|
||||
*/
|
||||
cntl |= CNTL_LCDPWR;
|
||||
writel(cntl, fb->regs + fb->off_cntl);
|
||||
|
||||
/*
|
||||
* finally, enable the interface.
|
||||
*/
|
||||
if (fb->board->enable)
|
||||
fb->board->enable(fb);
|
||||
}
|
||||
|
||||
static int
|
||||
clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
|
||||
{
|
||||
u32 caps;
|
||||
int ret = 0;
|
||||
|
||||
if (fb->panel->caps && fb->board->caps)
|
||||
caps = fb->panel->caps & fb->board->caps;
|
||||
else {
|
||||
/* Old way of specifying what can be used */
|
||||
caps = fb->panel->cntl & CNTL_BGR ?
|
||||
CLCD_CAP_BGR : CLCD_CAP_RGB;
|
||||
/* But mask out 444 modes as they weren't supported */
|
||||
caps &= ~CLCD_CAP_444;
|
||||
}
|
||||
|
||||
/* Only TFT panels can do RGB888/BGR888 */
|
||||
if (!(fb->panel->cntl & CNTL_LCDTFT))
|
||||
caps &= ~CLCD_CAP_888;
|
||||
|
||||
memset(&var->transp, 0, sizeof(var->transp));
|
||||
|
||||
var->red.msb_right = 0;
|
||||
var->green.msb_right = 0;
|
||||
var->blue.msb_right = 0;
|
||||
|
||||
switch (var->bits_per_pixel) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
/* If we can't do 5551, reject */
|
||||
caps &= CLCD_CAP_5551;
|
||||
if (!caps) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
var->red.length = var->bits_per_pixel;
|
||||
var->red.offset = 0;
|
||||
var->green.length = var->bits_per_pixel;
|
||||
var->green.offset = 0;
|
||||
var->blue.length = var->bits_per_pixel;
|
||||
var->blue.offset = 0;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
/* If we can't do 444, 5551 or 565, reject */
|
||||
if (!(caps & (CLCD_CAP_444 | CLCD_CAP_5551 | CLCD_CAP_565))) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Green length can be 4, 5 or 6 depending whether
|
||||
* we're operating in 444, 5551 or 565 mode.
|
||||
*/
|
||||
if (var->green.length == 4 && caps & CLCD_CAP_444)
|
||||
caps &= CLCD_CAP_444;
|
||||
if (var->green.length == 5 && caps & CLCD_CAP_5551)
|
||||
caps &= CLCD_CAP_5551;
|
||||
else if (var->green.length == 6 && caps & CLCD_CAP_565)
|
||||
caps &= CLCD_CAP_565;
|
||||
else {
|
||||
/*
|
||||
* PL110 officially only supports RGB555,
|
||||
* but may be wired up to allow RGB565.
|
||||
*/
|
||||
if (caps & CLCD_CAP_565) {
|
||||
var->green.length = 6;
|
||||
caps &= CLCD_CAP_565;
|
||||
} else if (caps & CLCD_CAP_5551) {
|
||||
var->green.length = 5;
|
||||
caps &= CLCD_CAP_5551;
|
||||
} else {
|
||||
var->green.length = 4;
|
||||
caps &= CLCD_CAP_444;
|
||||
}
|
||||
}
|
||||
|
||||
if (var->green.length >= 5) {
|
||||
var->red.length = 5;
|
||||
var->blue.length = 5;
|
||||
} else {
|
||||
var->red.length = 4;
|
||||
var->blue.length = 4;
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
/* If we can't do 888, reject */
|
||||
caps &= CLCD_CAP_888;
|
||||
if (!caps) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
var->red.length = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.length = 8;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* >= 16bpp displays have separate colour component bitfields
|
||||
* encoded in the pixel data. Calculate their position from
|
||||
* the bitfield length defined above.
|
||||
*/
|
||||
if (ret == 0 && var->bits_per_pixel >= 16) {
|
||||
bool bgr, rgb;
|
||||
|
||||
bgr = caps & CLCD_CAP_BGR && var->blue.offset == 0;
|
||||
rgb = caps & CLCD_CAP_RGB && var->red.offset == 0;
|
||||
|
||||
if (!bgr && !rgb)
|
||||
/*
|
||||
* The requested format was not possible, try just
|
||||
* our capabilities. One of BGR or RGB must be
|
||||
* supported.
|
||||
*/
|
||||
bgr = caps & CLCD_CAP_BGR;
|
||||
|
||||
if (bgr) {
|
||||
var->blue.offset = 0;
|
||||
var->green.offset = var->blue.offset + var->blue.length;
|
||||
var->red.offset = var->green.offset + var->green.length;
|
||||
} else {
|
||||
var->red.offset = 0;
|
||||
var->green.offset = var->red.offset + var->red.length;
|
||||
var->blue.offset = var->green.offset + var->green.length;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int clcdfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
|
||||
{
|
||||
struct clcd_fb *fb = to_clcd(info);
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (fb->board->check)
|
||||
ret = fb->board->check(fb, var);
|
||||
|
||||
if (ret == 0 &&
|
||||
var->xres_virtual * var->bits_per_pixel / 8 *
|
||||
var->yres_virtual > fb->fb.fix.smem_len)
|
||||
ret = -EINVAL;
|
||||
|
||||
if (ret == 0)
|
||||
ret = clcdfb_set_bitfields(fb, var);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int clcdfb_set_par(struct fb_info *info)
|
||||
{
|
||||
struct clcd_fb *fb = to_clcd(info);
|
||||
struct clcd_regs regs;
|
||||
|
||||
fb->fb.fix.line_length = fb->fb.var.xres_virtual *
|
||||
fb->fb.var.bits_per_pixel / 8;
|
||||
|
||||
if (fb->fb.var.bits_per_pixel <= 8)
|
||||
fb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
|
||||
else
|
||||
fb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
|
||||
|
||||
fb->board->decode(fb, ®s);
|
||||
|
||||
clcdfb_disable(fb);
|
||||
|
||||
writel(regs.tim0, fb->regs + CLCD_TIM0);
|
||||
writel(regs.tim1, fb->regs + CLCD_TIM1);
|
||||
writel(regs.tim2, fb->regs + CLCD_TIM2);
|
||||
writel(regs.tim3, fb->regs + CLCD_TIM3);
|
||||
|
||||
clcdfb_set_start(fb);
|
||||
|
||||
clk_set_rate(fb->clk, (1000000000 / regs.pixclock) * 1000);
|
||||
|
||||
fb->clcd_cntl = regs.cntl;
|
||||
|
||||
clcdfb_enable(fb, regs.cntl);
|
||||
|
||||
#ifdef DEBUG
|
||||
printk(KERN_INFO
|
||||
"CLCD: Registers set to\n"
|
||||
" %08x %08x %08x %08x\n"
|
||||
" %08x %08x %08x %08x\n",
|
||||
readl(fb->regs + CLCD_TIM0), readl(fb->regs + CLCD_TIM1),
|
||||
readl(fb->regs + CLCD_TIM2), readl(fb->regs + CLCD_TIM3),
|
||||
readl(fb->regs + CLCD_UBAS), readl(fb->regs + CLCD_LBAS),
|
||||
readl(fb->regs + fb->off_ienb), readl(fb->regs + fb->off_cntl));
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u32 convert_bitfield(int val, struct fb_bitfield *bf)
|
||||
{
|
||||
unsigned int mask = (1 << bf->length) - 1;
|
||||
|
||||
return (val >> (16 - bf->length) & mask) << bf->offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a single color register. The values supplied have a 16 bit
|
||||
* magnitude. Return != 0 for invalid regno.
|
||||
*/
|
||||
static int
|
||||
clcdfb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
|
||||
unsigned int blue, unsigned int transp, struct fb_info *info)
|
||||
{
|
||||
struct clcd_fb *fb = to_clcd(info);
|
||||
|
||||
if (regno < 16)
|
||||
fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) |
|
||||
convert_bitfield(blue, &fb->fb.var.blue) |
|
||||
convert_bitfield(green, &fb->fb.var.green) |
|
||||
convert_bitfield(red, &fb->fb.var.red);
|
||||
|
||||
if (fb->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR && regno < 256) {
|
||||
int hw_reg = CLCD_PALETTE + ((regno * 2) & ~3);
|
||||
u32 val, mask, newval;
|
||||
|
||||
newval = (red >> 11) & 0x001f;
|
||||
newval |= (green >> 6) & 0x03e0;
|
||||
newval |= (blue >> 1) & 0x7c00;
|
||||
|
||||
/*
|
||||
* 3.2.11: if we're configured for big endian
|
||||
* byte order, the palette entries are swapped.
|
||||
*/
|
||||
if (fb->clcd_cntl & CNTL_BEBO)
|
||||
regno ^= 1;
|
||||
|
||||
if (regno & 1) {
|
||||
newval <<= 16;
|
||||
mask = 0x0000ffff;
|
||||
} else {
|
||||
mask = 0xffff0000;
|
||||
}
|
||||
|
||||
val = readl(fb->regs + hw_reg) & mask;
|
||||
writel(val | newval, fb->regs + hw_reg);
|
||||
}
|
||||
|
||||
return regno > 255;
|
||||
}
|
||||
|
||||
/*
|
||||
* Blank the screen if blank_mode != 0, else unblank. If blank == NULL
|
||||
* then the caller blanks by setting the CLUT (Color Look Up Table) to all
|
||||
* black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
|
||||
* to e.g. a video mode which doesn't support it. Implements VESA suspend
|
||||
* and powerdown modes on hardware that supports disabling hsync/vsync:
|
||||
* blank_mode == 2: suspend vsync
|
||||
* blank_mode == 3: suspend hsync
|
||||
* blank_mode == 4: powerdown
|
||||
*/
|
||||
static int clcdfb_blank(int blank_mode, struct fb_info *info)
|
||||
{
|
||||
struct clcd_fb *fb = to_clcd(info);
|
||||
|
||||
if (blank_mode != 0) {
|
||||
clcdfb_disable(fb);
|
||||
} else {
|
||||
clcdfb_enable(fb, fb->clcd_cntl);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clcdfb_mmap(struct fb_info *info,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
struct clcd_fb *fb = to_clcd(info);
|
||||
unsigned long len, off = vma->vm_pgoff << PAGE_SHIFT;
|
||||
int ret = -EINVAL;
|
||||
|
||||
len = info->fix.smem_len;
|
||||
|
||||
if (off <= len && vma->vm_end - vma->vm_start <= len - off &&
|
||||
fb->board->mmap)
|
||||
ret = fb->board->mmap(fb, vma);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct fb_ops clcdfb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_check_var = clcdfb_check_var,
|
||||
.fb_set_par = clcdfb_set_par,
|
||||
.fb_setcolreg = clcdfb_setcolreg,
|
||||
.fb_blank = clcdfb_blank,
|
||||
.fb_fillrect = cfb_fillrect,
|
||||
.fb_copyarea = cfb_copyarea,
|
||||
.fb_imageblit = cfb_imageblit,
|
||||
.fb_mmap = clcdfb_mmap,
|
||||
};
|
||||
|
||||
static int clcdfb_register(struct clcd_fb *fb)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* ARM PL111 always has IENB at 0x1c; it's only PL110
|
||||
* which is reversed on some platforms.
|
||||
*/
|
||||
if (amba_manf(fb->dev) == 0x41 && amba_part(fb->dev) == 0x111) {
|
||||
fb->off_ienb = CLCD_PL111_IENB;
|
||||
fb->off_cntl = CLCD_PL111_CNTL;
|
||||
} else {
|
||||
#ifdef CONFIG_ARCH_VERSATILE
|
||||
fb->off_ienb = CLCD_PL111_IENB;
|
||||
fb->off_cntl = CLCD_PL111_CNTL;
|
||||
#else
|
||||
fb->off_ienb = CLCD_PL110_IENB;
|
||||
fb->off_cntl = CLCD_PL110_CNTL;
|
||||
#endif
|
||||
}
|
||||
|
||||
fb->clk = clk_get(&fb->dev->dev, NULL);
|
||||
if (IS_ERR(fb->clk)) {
|
||||
ret = PTR_ERR(fb->clk);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = clk_prepare(fb->clk);
|
||||
if (ret)
|
||||
goto free_clk;
|
||||
|
||||
fb->fb.device = &fb->dev->dev;
|
||||
|
||||
fb->fb.fix.mmio_start = fb->dev->res.start;
|
||||
fb->fb.fix.mmio_len = resource_size(&fb->dev->res);
|
||||
|
||||
fb->regs = ioremap(fb->fb.fix.mmio_start, fb->fb.fix.mmio_len);
|
||||
if (!fb->regs) {
|
||||
printk(KERN_ERR "CLCD: unable to remap registers\n");
|
||||
ret = -ENOMEM;
|
||||
goto clk_unprep;
|
||||
}
|
||||
|
||||
fb->fb.fbops = &clcdfb_ops;
|
||||
fb->fb.flags = FBINFO_FLAG_DEFAULT;
|
||||
fb->fb.pseudo_palette = fb->cmap;
|
||||
|
||||
strncpy(fb->fb.fix.id, clcd_name, sizeof(fb->fb.fix.id));
|
||||
fb->fb.fix.type = FB_TYPE_PACKED_PIXELS;
|
||||
fb->fb.fix.type_aux = 0;
|
||||
fb->fb.fix.xpanstep = 0;
|
||||
fb->fb.fix.ypanstep = 0;
|
||||
fb->fb.fix.ywrapstep = 0;
|
||||
fb->fb.fix.accel = FB_ACCEL_NONE;
|
||||
|
||||
fb->fb.var.xres = fb->panel->mode.xres;
|
||||
fb->fb.var.yres = fb->panel->mode.yres;
|
||||
fb->fb.var.xres_virtual = fb->panel->mode.xres;
|
||||
fb->fb.var.yres_virtual = fb->panel->mode.yres;
|
||||
fb->fb.var.bits_per_pixel = fb->panel->bpp;
|
||||
fb->fb.var.grayscale = fb->panel->grayscale;
|
||||
fb->fb.var.pixclock = fb->panel->mode.pixclock;
|
||||
fb->fb.var.left_margin = fb->panel->mode.left_margin;
|
||||
fb->fb.var.right_margin = fb->panel->mode.right_margin;
|
||||
fb->fb.var.upper_margin = fb->panel->mode.upper_margin;
|
||||
fb->fb.var.lower_margin = fb->panel->mode.lower_margin;
|
||||
fb->fb.var.hsync_len = fb->panel->mode.hsync_len;
|
||||
fb->fb.var.vsync_len = fb->panel->mode.vsync_len;
|
||||
fb->fb.var.sync = fb->panel->mode.sync;
|
||||
fb->fb.var.vmode = fb->panel->mode.vmode;
|
||||
fb->fb.var.activate = FB_ACTIVATE_NOW;
|
||||
fb->fb.var.nonstd = 0;
|
||||
fb->fb.var.height = fb->panel->height;
|
||||
fb->fb.var.width = fb->panel->width;
|
||||
fb->fb.var.accel_flags = 0;
|
||||
|
||||
fb->fb.monspecs.hfmin = 0;
|
||||
fb->fb.monspecs.hfmax = 100000;
|
||||
fb->fb.monspecs.vfmin = 0;
|
||||
fb->fb.monspecs.vfmax = 400;
|
||||
fb->fb.monspecs.dclkmin = 1000000;
|
||||
fb->fb.monspecs.dclkmax = 100000000;
|
||||
|
||||
/*
|
||||
* Make sure that the bitfields are set appropriately.
|
||||
*/
|
||||
clcdfb_set_bitfields(fb, &fb->fb.var);
|
||||
|
||||
/*
|
||||
* Allocate colourmap.
|
||||
*/
|
||||
ret = fb_alloc_cmap(&fb->fb.cmap, 256, 0);
|
||||
if (ret)
|
||||
goto unmap;
|
||||
|
||||
/*
|
||||
* Ensure interrupts are disabled.
|
||||
*/
|
||||
writel(0, fb->regs + fb->off_ienb);
|
||||
|
||||
fb_set_var(&fb->fb, &fb->fb.var);
|
||||
|
||||
dev_info(&fb->dev->dev, "%s hardware, %s display\n",
|
||||
fb->board->name, fb->panel->mode.name);
|
||||
|
||||
ret = register_framebuffer(&fb->fb);
|
||||
if (ret == 0)
|
||||
goto out;
|
||||
|
||||
printk(KERN_ERR "CLCD: cannot register framebuffer (%d)\n", ret);
|
||||
|
||||
fb_dealloc_cmap(&fb->fb.cmap);
|
||||
unmap:
|
||||
iounmap(fb->regs);
|
||||
clk_unprep:
|
||||
clk_unprepare(fb->clk);
|
||||
free_clk:
|
||||
clk_put(fb->clk);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
|
||||
{
|
||||
struct clcd_board *board = dev_get_platdata(&dev->dev);
|
||||
struct clcd_fb *fb;
|
||||
int ret;
|
||||
|
||||
if (!board)
|
||||
return -EINVAL;
|
||||
|
||||
ret = dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = amba_request_regions(dev, NULL);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "CLCD: unable to reserve regs region\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
fb = kzalloc(sizeof(struct clcd_fb), GFP_KERNEL);
|
||||
if (!fb) {
|
||||
printk(KERN_INFO "CLCD: could not allocate new clcd_fb struct\n");
|
||||
ret = -ENOMEM;
|
||||
goto free_region;
|
||||
}
|
||||
|
||||
fb->dev = dev;
|
||||
fb->board = board;
|
||||
|
||||
dev_info(&fb->dev->dev, "PL%03x rev%u at 0x%08llx\n",
|
||||
amba_part(dev), amba_rev(dev),
|
||||
(unsigned long long)dev->res.start);
|
||||
|
||||
ret = fb->board->setup(fb);
|
||||
if (ret)
|
||||
goto free_fb;
|
||||
|
||||
ret = clcdfb_register(fb);
|
||||
if (ret == 0) {
|
||||
amba_set_drvdata(dev, fb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fb->board->remove(fb);
|
||||
free_fb:
|
||||
kfree(fb);
|
||||
free_region:
|
||||
amba_release_regions(dev);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int clcdfb_remove(struct amba_device *dev)
|
||||
{
|
||||
struct clcd_fb *fb = amba_get_drvdata(dev);
|
||||
|
||||
clcdfb_disable(fb);
|
||||
unregister_framebuffer(&fb->fb);
|
||||
if (fb->fb.cmap.len)
|
||||
fb_dealloc_cmap(&fb->fb.cmap);
|
||||
iounmap(fb->regs);
|
||||
clk_unprepare(fb->clk);
|
||||
clk_put(fb->clk);
|
||||
|
||||
fb->board->remove(fb);
|
||||
|
||||
kfree(fb);
|
||||
|
||||
amba_release_regions(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct amba_id clcdfb_id_table[] = {
|
||||
{
|
||||
.id = 0x00041110,
|
||||
.mask = 0x000ffffe,
|
||||
},
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(amba, clcdfb_id_table);
|
||||
|
||||
static struct amba_driver clcd_driver = {
|
||||
.drv = {
|
||||
.name = "clcd-pl11x",
|
||||
},
|
||||
.probe = clcdfb_probe,
|
||||
.remove = clcdfb_remove,
|
||||
.id_table = clcdfb_id_table,
|
||||
};
|
||||
|
||||
static int __init amba_clcdfb_init(void)
|
||||
{
|
||||
if (fb_get_options("ambafb", NULL))
|
||||
return -ENODEV;
|
||||
|
||||
return amba_driver_register(&clcd_driver);
|
||||
}
|
||||
|
||||
module_init(amba_clcdfb_init);
|
||||
|
||||
static void __exit amba_clcdfb_exit(void)
|
||||
{
|
||||
amba_driver_unregister(&clcd_driver);
|
||||
}
|
||||
|
||||
module_exit(amba_clcdfb_exit);
|
||||
|
||||
MODULE_DESCRIPTION("ARM PrimeCell PL110 CLCD core driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
3792
drivers/video/fbdev/amifb.c
Normal file
3792
drivers/video/fbdev/amifb.c
Normal file
File diff suppressed because it is too large
Load diff
667
drivers/video/fbdev/arcfb.c
Normal file
667
drivers/video/fbdev/arcfb.c
Normal file
|
|
@ -0,0 +1,667 @@
|
|||
/*
|
||||
* linux/drivers/video/arcfb.c -- FB driver for Arc monochrome LCD board
|
||||
*
|
||||
* Copyright (C) 2005, Jaya Kumar <jayalk@intworks.biz>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
|
||||
*
|
||||
* This driver was written to be used with the Arc LCD board. Arc uses a
|
||||
* set of KS108 chips that control individual 64x64 LCD matrices. The board
|
||||
* can be paneled in a variety of setups such as 2x1=128x64, 4x4=256x256 and
|
||||
* so on. The interface between the board and the host is TTL based GPIO. The
|
||||
* GPIO requirements are 8 writable data lines and 4+n lines for control. On a
|
||||
* GPIO-less system, the board can be tested by connecting the respective sigs
|
||||
* up to a parallel port connector. The driver requires the IO addresses for
|
||||
* data and control GPIO at load time. It is unable to probe for the
|
||||
* existence of the LCD so it must be told at load time whether it should
|
||||
* be enabled or not.
|
||||
*
|
||||
* Todo:
|
||||
* - testing with 4x4
|
||||
* - testing with interrupt hw
|
||||
*
|
||||
* General notes:
|
||||
* - User must set tuhold. It's in microseconds. According to the 108 spec,
|
||||
* the hold time is supposed to be at least 1 microsecond.
|
||||
* - User must set num_cols=x num_rows=y, eg: x=2 means 128
|
||||
* - User must set arcfb_enable=1 to enable it
|
||||
* - User must set dio_addr=0xIOADDR cio_addr=0xIOADDR
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/arcfb.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#define floor8(a) (a&(~0x07))
|
||||
#define floorXres(a,xres) (a&(~(xres - 1)))
|
||||
#define iceil8(a) (((int)((a+7)/8))*8)
|
||||
#define ceil64(a) (a|0x3F)
|
||||
#define ceilXres(a,xres) (a|(xres - 1))
|
||||
|
||||
/* ks108 chipset specific defines and code */
|
||||
|
||||
#define KS_SET_DPY_START_LINE 0xC0
|
||||
#define KS_SET_PAGE_NUM 0xB8
|
||||
#define KS_SET_X 0x40
|
||||
#define KS_CEHI 0x01
|
||||
#define KS_CELO 0x00
|
||||
#define KS_SEL_CMD 0x08
|
||||
#define KS_SEL_DATA 0x00
|
||||
#define KS_DPY_ON 0x3F
|
||||
#define KS_DPY_OFF 0x3E
|
||||
#define KS_INTACK 0x40
|
||||
#define KS_CLRINT 0x02
|
||||
|
||||
struct arcfb_par {
|
||||
unsigned long dio_addr;
|
||||
unsigned long cio_addr;
|
||||
unsigned long c2io_addr;
|
||||
atomic_t ref_count;
|
||||
unsigned char cslut[9];
|
||||
struct fb_info *info;
|
||||
unsigned int irq;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
static struct fb_fix_screeninfo arcfb_fix = {
|
||||
.id = "arcfb",
|
||||
.type = FB_TYPE_PACKED_PIXELS,
|
||||
.visual = FB_VISUAL_MONO01,
|
||||
.xpanstep = 0,
|
||||
.ypanstep = 1,
|
||||
.ywrapstep = 0,
|
||||
.accel = FB_ACCEL_NONE,
|
||||
};
|
||||
|
||||
static struct fb_var_screeninfo arcfb_var = {
|
||||
.xres = 128,
|
||||
.yres = 64,
|
||||
.xres_virtual = 128,
|
||||
.yres_virtual = 64,
|
||||
.bits_per_pixel = 1,
|
||||
.nonstd = 1,
|
||||
};
|
||||
|
||||
static unsigned long num_cols;
|
||||
static unsigned long num_rows;
|
||||
static unsigned long dio_addr;
|
||||
static unsigned long cio_addr;
|
||||
static unsigned long c2io_addr;
|
||||
static unsigned long splashval;
|
||||
static unsigned long tuhold;
|
||||
static unsigned int nosplash;
|
||||
static unsigned int arcfb_enable;
|
||||
static unsigned int irq;
|
||||
|
||||
static DECLARE_WAIT_QUEUE_HEAD(arcfb_waitq);
|
||||
|
||||
static void ks108_writeb_ctl(struct arcfb_par *par,
|
||||
unsigned int chipindex, unsigned char value)
|
||||
{
|
||||
unsigned char chipselval = par->cslut[chipindex];
|
||||
|
||||
outb(chipselval|KS_CEHI|KS_SEL_CMD, par->cio_addr);
|
||||
outb(value, par->dio_addr);
|
||||
udelay(tuhold);
|
||||
outb(chipselval|KS_CELO|KS_SEL_CMD, par->cio_addr);
|
||||
}
|
||||
|
||||
static void ks108_writeb_mainctl(struct arcfb_par *par, unsigned char value)
|
||||
{
|
||||
|
||||
outb(value, par->cio_addr);
|
||||
udelay(tuhold);
|
||||
}
|
||||
|
||||
static unsigned char ks108_readb_ctl2(struct arcfb_par *par)
|
||||
{
|
||||
return inb(par->c2io_addr);
|
||||
}
|
||||
|
||||
static void ks108_writeb_data(struct arcfb_par *par,
|
||||
unsigned int chipindex, unsigned char value)
|
||||
{
|
||||
unsigned char chipselval = par->cslut[chipindex];
|
||||
|
||||
outb(chipselval|KS_CEHI|KS_SEL_DATA, par->cio_addr);
|
||||
outb(value, par->dio_addr);
|
||||
udelay(tuhold);
|
||||
outb(chipselval|KS_CELO|KS_SEL_DATA, par->cio_addr);
|
||||
}
|
||||
|
||||
static void ks108_set_start_line(struct arcfb_par *par,
|
||||
unsigned int chipindex, unsigned char y)
|
||||
{
|
||||
ks108_writeb_ctl(par, chipindex, KS_SET_DPY_START_LINE|y);
|
||||
}
|
||||
|
||||
static void ks108_set_yaddr(struct arcfb_par *par,
|
||||
unsigned int chipindex, unsigned char y)
|
||||
{
|
||||
ks108_writeb_ctl(par, chipindex, KS_SET_PAGE_NUM|y);
|
||||
}
|
||||
|
||||
static void ks108_set_xaddr(struct arcfb_par *par,
|
||||
unsigned int chipindex, unsigned char x)
|
||||
{
|
||||
ks108_writeb_ctl(par, chipindex, KS_SET_X|x);
|
||||
}
|
||||
|
||||
static void ks108_clear_lcd(struct arcfb_par *par, unsigned int chipindex)
|
||||
{
|
||||
int i,j;
|
||||
|
||||
for (i = 0; i <= 8; i++) {
|
||||
ks108_set_yaddr(par, chipindex, i);
|
||||
ks108_set_xaddr(par, chipindex, 0);
|
||||
for (j = 0; j < 64; j++) {
|
||||
ks108_writeb_data(par, chipindex,
|
||||
(unsigned char) splashval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* main arcfb functions */
|
||||
|
||||
static int arcfb_open(struct fb_info *info, int user)
|
||||
{
|
||||
struct arcfb_par *par = info->par;
|
||||
|
||||
atomic_inc(&par->ref_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int arcfb_release(struct fb_info *info, int user)
|
||||
{
|
||||
struct arcfb_par *par = info->par;
|
||||
int count = atomic_read(&par->ref_count);
|
||||
|
||||
if (!count)
|
||||
return -EINVAL;
|
||||
atomic_dec(&par->ref_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int arcfb_pan_display(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info)
|
||||
{
|
||||
int i;
|
||||
struct arcfb_par *par = info->par;
|
||||
|
||||
if ((var->vmode & FB_VMODE_YWRAP) && (var->yoffset < 64)
|
||||
&& (info->var.yres <= 64)) {
|
||||
for (i = 0; i < num_cols; i++) {
|
||||
ks108_set_start_line(par, i, var->yoffset);
|
||||
}
|
||||
info->var.yoffset = var->yoffset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static irqreturn_t arcfb_interrupt(int vec, void *dev_instance)
|
||||
{
|
||||
struct fb_info *info = dev_instance;
|
||||
unsigned char ctl2status;
|
||||
struct arcfb_par *par = info->par;
|
||||
|
||||
ctl2status = ks108_readb_ctl2(par);
|
||||
|
||||
if (!(ctl2status & KS_INTACK)) /* not arc generated interrupt */
|
||||
return IRQ_NONE;
|
||||
|
||||
ks108_writeb_mainctl(par, KS_CLRINT);
|
||||
|
||||
spin_lock(&par->lock);
|
||||
if (waitqueue_active(&arcfb_waitq)) {
|
||||
wake_up(&arcfb_waitq);
|
||||
}
|
||||
spin_unlock(&par->lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* here we handle a specific page on the lcd. the complexity comes from
|
||||
* the fact that the fb is laidout in 8xX vertical columns. we extract
|
||||
* each write of 8 vertical pixels. then we shift out as we move along
|
||||
* X. That's what rightshift does. bitmask selects the desired input bit.
|
||||
*/
|
||||
static void arcfb_lcd_update_page(struct arcfb_par *par, unsigned int upper,
|
||||
unsigned int left, unsigned int right, unsigned int distance)
|
||||
{
|
||||
unsigned char *src;
|
||||
unsigned int xindex, yindex, chipindex, linesize;
|
||||
int i;
|
||||
unsigned char val;
|
||||
unsigned char bitmask, rightshift;
|
||||
|
||||
xindex = left >> 6;
|
||||
yindex = upper >> 6;
|
||||
chipindex = (xindex + (yindex*num_cols));
|
||||
|
||||
ks108_set_yaddr(par, chipindex, upper/8);
|
||||
|
||||
linesize = par->info->var.xres/8;
|
||||
src = (unsigned char __force *) par->info->screen_base + (left/8) +
|
||||
(upper * linesize);
|
||||
ks108_set_xaddr(par, chipindex, left);
|
||||
|
||||
bitmask=1;
|
||||
rightshift=0;
|
||||
while (left <= right) {
|
||||
val = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if ( i > rightshift) {
|
||||
val |= (*(src + (i*linesize)) & bitmask)
|
||||
<< (i - rightshift);
|
||||
} else {
|
||||
val |= (*(src + (i*linesize)) & bitmask)
|
||||
>> (rightshift - i);
|
||||
}
|
||||
}
|
||||
ks108_writeb_data(par, chipindex, val);
|
||||
left++;
|
||||
if (bitmask == 0x80) {
|
||||
bitmask = 1;
|
||||
src++;
|
||||
rightshift=0;
|
||||
} else {
|
||||
bitmask <<= 1;
|
||||
rightshift++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* here we handle the entire vertical page of the update. we write across
|
||||
* lcd chips. update_page uses the upper/left values to decide which
|
||||
* chip to select for the right. upper is needed for setting the page
|
||||
* desired for the write.
|
||||
*/
|
||||
static void arcfb_lcd_update_vert(struct arcfb_par *par, unsigned int top,
|
||||
unsigned int bottom, unsigned int left, unsigned int right)
|
||||
{
|
||||
unsigned int distance, upper, lower;
|
||||
|
||||
distance = (bottom - top) + 1;
|
||||
upper = top;
|
||||
lower = top + 7;
|
||||
|
||||
while (distance > 0) {
|
||||
distance -= 8;
|
||||
arcfb_lcd_update_page(par, upper, left, right, 8);
|
||||
upper = lower + 1;
|
||||
lower = upper + 7;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* here we handle horizontal blocks for the update. update_vert will
|
||||
* handle spaning multiple pages. we break out each horizontal
|
||||
* block in to individual blocks no taller than 64 pixels.
|
||||
*/
|
||||
static void arcfb_lcd_update_horiz(struct arcfb_par *par, unsigned int left,
|
||||
unsigned int right, unsigned int top, unsigned int h)
|
||||
{
|
||||
unsigned int distance, upper, lower;
|
||||
|
||||
distance = h;
|
||||
upper = floor8(top);
|
||||
lower = min(upper + distance - 1, ceil64(upper));
|
||||
|
||||
while (distance > 0) {
|
||||
distance -= ((lower - upper) + 1 );
|
||||
arcfb_lcd_update_vert(par, upper, lower, left, right);
|
||||
upper = lower + 1;
|
||||
lower = min(upper + distance - 1, ceil64(upper));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* here we start the process of splitting out the fb update into
|
||||
* individual blocks of pixels. we end up splitting into 64x64 blocks
|
||||
* and finally down to 64x8 pages.
|
||||
*/
|
||||
static void arcfb_lcd_update(struct arcfb_par *par, unsigned int dx,
|
||||
unsigned int dy, unsigned int w, unsigned int h)
|
||||
{
|
||||
unsigned int left, right, distance, y;
|
||||
|
||||
/* align the request first */
|
||||
y = floor8(dy);
|
||||
h += dy - y;
|
||||
h = iceil8(h);
|
||||
|
||||
distance = w;
|
||||
left = dx;
|
||||
right = min(left + w - 1, ceil64(left));
|
||||
|
||||
while (distance > 0) {
|
||||
arcfb_lcd_update_horiz(par, left, right, y, h);
|
||||
distance -= ((right - left) + 1);
|
||||
left = right + 1;
|
||||
right = min(left + distance - 1, ceil64(left));
|
||||
}
|
||||
}
|
||||
|
||||
static void arcfb_fillrect(struct fb_info *info,
|
||||
const struct fb_fillrect *rect)
|
||||
{
|
||||
struct arcfb_par *par = info->par;
|
||||
|
||||
sys_fillrect(info, rect);
|
||||
|
||||
/* update the physical lcd */
|
||||
arcfb_lcd_update(par, rect->dx, rect->dy, rect->width, rect->height);
|
||||
}
|
||||
|
||||
static void arcfb_copyarea(struct fb_info *info,
|
||||
const struct fb_copyarea *area)
|
||||
{
|
||||
struct arcfb_par *par = info->par;
|
||||
|
||||
sys_copyarea(info, area);
|
||||
|
||||
/* update the physical lcd */
|
||||
arcfb_lcd_update(par, area->dx, area->dy, area->width, area->height);
|
||||
}
|
||||
|
||||
static void arcfb_imageblit(struct fb_info *info, const struct fb_image *image)
|
||||
{
|
||||
struct arcfb_par *par = info->par;
|
||||
|
||||
sys_imageblit(info, image);
|
||||
|
||||
/* update the physical lcd */
|
||||
arcfb_lcd_update(par, image->dx, image->dy, image->width,
|
||||
image->height);
|
||||
}
|
||||
|
||||
static int arcfb_ioctl(struct fb_info *info,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
void __user *argp = (void __user *)arg;
|
||||
struct arcfb_par *par = info->par;
|
||||
unsigned long flags;
|
||||
|
||||
switch (cmd) {
|
||||
case FBIO_WAITEVENT:
|
||||
{
|
||||
DEFINE_WAIT(wait);
|
||||
/* illegal to wait on arc if no irq will occur */
|
||||
if (!par->irq)
|
||||
return -EINVAL;
|
||||
|
||||
/* wait until the Arc has generated an interrupt
|
||||
* which will wake us up */
|
||||
spin_lock_irqsave(&par->lock, flags);
|
||||
prepare_to_wait(&arcfb_waitq, &wait,
|
||||
TASK_INTERRUPTIBLE);
|
||||
spin_unlock_irqrestore(&par->lock, flags);
|
||||
schedule();
|
||||
finish_wait(&arcfb_waitq, &wait);
|
||||
}
|
||||
case FBIO_GETCONTROL2:
|
||||
{
|
||||
unsigned char ctl2;
|
||||
|
||||
ctl2 = ks108_readb_ctl2(info->par);
|
||||
if (copy_to_user(argp, &ctl2, sizeof(ctl2)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* this is the access path from userspace. they can seek and write to
|
||||
* the fb. it's inefficient for them to do anything less than 64*8
|
||||
* writes since we update the lcd in each write() anyway.
|
||||
*/
|
||||
static ssize_t arcfb_write(struct fb_info *info, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
/* modded from epson 1355 */
|
||||
|
||||
unsigned long p;
|
||||
int err=-EINVAL;
|
||||
unsigned int fbmemlength,x,y,w,h, bitppos, startpos, endpos, bitcount;
|
||||
struct arcfb_par *par;
|
||||
unsigned int xres;
|
||||
|
||||
p = *ppos;
|
||||
par = info->par;
|
||||
xres = info->var.xres;
|
||||
fbmemlength = (xres * info->var.yres)/8;
|
||||
|
||||
if (p > fbmemlength)
|
||||
return -ENOSPC;
|
||||
|
||||
err = 0;
|
||||
if ((count + p) > fbmemlength) {
|
||||
count = fbmemlength - p;
|
||||
err = -ENOSPC;
|
||||
}
|
||||
|
||||
if (count) {
|
||||
char *base_addr;
|
||||
|
||||
base_addr = (char __force *)info->screen_base;
|
||||
count -= copy_from_user(base_addr + p, buf, count);
|
||||
*ppos += count;
|
||||
err = -EFAULT;
|
||||
}
|
||||
|
||||
|
||||
bitppos = p*8;
|
||||
startpos = floorXres(bitppos, xres);
|
||||
endpos = ceilXres((bitppos + (count*8)), xres);
|
||||
bitcount = endpos - startpos;
|
||||
|
||||
x = startpos % xres;
|
||||
y = startpos / xres;
|
||||
w = xres;
|
||||
h = bitcount / xres;
|
||||
arcfb_lcd_update(par, x, y, w, h);
|
||||
|
||||
if (count)
|
||||
return count;
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct fb_ops arcfb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_open = arcfb_open,
|
||||
.fb_read = fb_sys_read,
|
||||
.fb_write = arcfb_write,
|
||||
.fb_release = arcfb_release,
|
||||
.fb_pan_display = arcfb_pan_display,
|
||||
.fb_fillrect = arcfb_fillrect,
|
||||
.fb_copyarea = arcfb_copyarea,
|
||||
.fb_imageblit = arcfb_imageblit,
|
||||
.fb_ioctl = arcfb_ioctl,
|
||||
};
|
||||
|
||||
static int arcfb_probe(struct platform_device *dev)
|
||||
{
|
||||
struct fb_info *info;
|
||||
int retval = -ENOMEM;
|
||||
int videomemorysize;
|
||||
unsigned char *videomemory;
|
||||
struct arcfb_par *par;
|
||||
int i;
|
||||
|
||||
videomemorysize = (((64*64)*num_cols)*num_rows)/8;
|
||||
|
||||
/* We need a flat backing store for the Arc's
|
||||
less-flat actual paged framebuffer */
|
||||
videomemory = vzalloc(videomemorysize);
|
||||
if (!videomemory)
|
||||
return retval;
|
||||
|
||||
info = framebuffer_alloc(sizeof(struct arcfb_par), &dev->dev);
|
||||
if (!info)
|
||||
goto err;
|
||||
|
||||
info->screen_base = (char __iomem *)videomemory;
|
||||
info->fbops = &arcfb_ops;
|
||||
|
||||
info->var = arcfb_var;
|
||||
info->fix = arcfb_fix;
|
||||
par = info->par;
|
||||
par->info = info;
|
||||
|
||||
if (!dio_addr || !cio_addr || !c2io_addr) {
|
||||
printk(KERN_WARNING "no IO addresses supplied\n");
|
||||
goto err1;
|
||||
}
|
||||
par->dio_addr = dio_addr;
|
||||
par->cio_addr = cio_addr;
|
||||
par->c2io_addr = c2io_addr;
|
||||
par->cslut[0] = 0x00;
|
||||
par->cslut[1] = 0x06;
|
||||
info->flags = FBINFO_FLAG_DEFAULT;
|
||||
spin_lock_init(&par->lock);
|
||||
retval = register_framebuffer(info);
|
||||
if (retval < 0)
|
||||
goto err1;
|
||||
platform_set_drvdata(dev, info);
|
||||
if (irq) {
|
||||
par->irq = irq;
|
||||
if (request_irq(par->irq, &arcfb_interrupt, IRQF_SHARED,
|
||||
"arcfb", info)) {
|
||||
printk(KERN_INFO
|
||||
"arcfb: Failed req IRQ %d\n", par->irq);
|
||||
retval = -EBUSY;
|
||||
goto err1;
|
||||
}
|
||||
}
|
||||
fb_info(info, "Arc frame buffer device, using %dK of video memory\n",
|
||||
videomemorysize >> 10);
|
||||
|
||||
/* this inits the lcd but doesn't clear dirty pixels */
|
||||
for (i = 0; i < num_cols * num_rows; i++) {
|
||||
ks108_writeb_ctl(par, i, KS_DPY_OFF);
|
||||
ks108_set_start_line(par, i, 0);
|
||||
ks108_set_yaddr(par, i, 0);
|
||||
ks108_set_xaddr(par, i, 0);
|
||||
ks108_writeb_ctl(par, i, KS_DPY_ON);
|
||||
}
|
||||
|
||||
/* if we were told to splash the screen, we just clear it */
|
||||
if (!nosplash) {
|
||||
for (i = 0; i < num_cols * num_rows; i++) {
|
||||
fb_info(info, "splashing lcd %d\n", i);
|
||||
ks108_set_start_line(par, i, 0);
|
||||
ks108_clear_lcd(par, i);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
err1:
|
||||
framebuffer_release(info);
|
||||
err:
|
||||
vfree(videomemory);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int arcfb_remove(struct platform_device *dev)
|
||||
{
|
||||
struct fb_info *info = platform_get_drvdata(dev);
|
||||
|
||||
if (info) {
|
||||
unregister_framebuffer(info);
|
||||
vfree((void __force *)info->screen_base);
|
||||
framebuffer_release(info);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver arcfb_driver = {
|
||||
.probe = arcfb_probe,
|
||||
.remove = arcfb_remove,
|
||||
.driver = {
|
||||
.name = "arcfb",
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device *arcfb_device;
|
||||
|
||||
static int __init arcfb_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!arcfb_enable)
|
||||
return -ENXIO;
|
||||
|
||||
ret = platform_driver_register(&arcfb_driver);
|
||||
if (!ret) {
|
||||
arcfb_device = platform_device_alloc("arcfb", 0);
|
||||
if (arcfb_device) {
|
||||
ret = platform_device_add(arcfb_device);
|
||||
} else {
|
||||
ret = -ENOMEM;
|
||||
}
|
||||
if (ret) {
|
||||
platform_device_put(arcfb_device);
|
||||
platform_driver_unregister(&arcfb_driver);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static void __exit arcfb_exit(void)
|
||||
{
|
||||
platform_device_unregister(arcfb_device);
|
||||
platform_driver_unregister(&arcfb_driver);
|
||||
}
|
||||
|
||||
module_param(num_cols, ulong, 0);
|
||||
MODULE_PARM_DESC(num_cols, "Num horiz panels, eg: 2 = 128 bit wide");
|
||||
module_param(num_rows, ulong, 0);
|
||||
MODULE_PARM_DESC(num_rows, "Num vert panels, eg: 1 = 64 bit high");
|
||||
module_param(nosplash, uint, 0);
|
||||
MODULE_PARM_DESC(nosplash, "Disable doing the splash screen");
|
||||
module_param(arcfb_enable, uint, 0);
|
||||
MODULE_PARM_DESC(arcfb_enable, "Enable communication with Arc board");
|
||||
module_param(dio_addr, ulong, 0);
|
||||
MODULE_PARM_DESC(dio_addr, "IO address for data, eg: 0x480");
|
||||
module_param(cio_addr, ulong, 0);
|
||||
MODULE_PARM_DESC(cio_addr, "IO address for control, eg: 0x400");
|
||||
module_param(c2io_addr, ulong, 0);
|
||||
MODULE_PARM_DESC(c2io_addr, "IO address for secondary control, eg: 0x408");
|
||||
module_param(splashval, ulong, 0);
|
||||
MODULE_PARM_DESC(splashval, "Splash pattern: 0xFF is black, 0x00 is green");
|
||||
module_param(tuhold, ulong, 0);
|
||||
MODULE_PARM_DESC(tuhold, "Time to hold between strobing data to Arc board");
|
||||
module_param(irq, uint, 0);
|
||||
MODULE_PARM_DESC(irq, "IRQ for the Arc board");
|
||||
|
||||
module_init(arcfb_init);
|
||||
module_exit(arcfb_exit);
|
||||
|
||||
MODULE_DESCRIPTION("fbdev driver for Arc monochrome LCD board");
|
||||
MODULE_AUTHOR("Jaya Kumar");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
1231
drivers/video/fbdev/arkfb.c
Normal file
1231
drivers/video/fbdev/arkfb.c
Normal file
File diff suppressed because it is too large
Load diff
624
drivers/video/fbdev/asiliantfb.c
Normal file
624
drivers/video/fbdev/asiliantfb.c
Normal file
|
|
@ -0,0 +1,624 @@
|
|||
/*
|
||||
* drivers/video/asiliantfb.c
|
||||
* frame buffer driver for Asiliant 69000 chip
|
||||
* Copyright (C) 2001-2003 Saito.K & Jeanne
|
||||
*
|
||||
* from driver/video/chipsfb.c and,
|
||||
*
|
||||
* drivers/video/asiliantfb.c -- frame buffer device for
|
||||
* Asiliant 69030 chip (formerly Intel, formerly Chips & Technologies)
|
||||
* Author: apc@agelectronics.co.uk
|
||||
* Copyright (C) 2000 AG Electronics
|
||||
* Note: the data sheets don't seem to be available from Asiliant.
|
||||
* They are available by searching developer.intel.com, but are not otherwise
|
||||
* linked to.
|
||||
*
|
||||
* This driver should be portable with minimal effort to the 69000 display
|
||||
* chip, and to the twin-display mode of the 69030.
|
||||
* Contains code from Thomas Hhenleitner <th@visuelle-maschinen.de> (thanks)
|
||||
*
|
||||
* Derived from the CT65550 driver chipsfb.c:
|
||||
* Copyright (C) 1998 Paul Mackerras
|
||||
* ...which was derived from the Powermac "chips" driver:
|
||||
* Copyright (C) 1997 Fabio Riccardi.
|
||||
* And from the frame buffer device for Open Firmware-initialized devices:
|
||||
* Copyright (C) 1997 Geert Uytterhoeven.
|
||||
*
|
||||
* 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/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
/* Built in clock of the 69030 */
|
||||
static const unsigned Fref = 14318180;
|
||||
|
||||
#define mmio_base (p->screen_base + 0x400000)
|
||||
|
||||
#define mm_write_ind(num, val, ap, dp) do { \
|
||||
writeb((num), mmio_base + (ap)); writeb((val), mmio_base + (dp)); \
|
||||
} while (0)
|
||||
|
||||
static void mm_write_xr(struct fb_info *p, u8 reg, u8 data)
|
||||
{
|
||||
mm_write_ind(reg, data, 0x7ac, 0x7ad);
|
||||
}
|
||||
#define write_xr(num, val) mm_write_xr(p, num, val)
|
||||
|
||||
static void mm_write_fr(struct fb_info *p, u8 reg, u8 data)
|
||||
{
|
||||
mm_write_ind(reg, data, 0x7a0, 0x7a1);
|
||||
}
|
||||
#define write_fr(num, val) mm_write_fr(p, num, val)
|
||||
|
||||
static void mm_write_cr(struct fb_info *p, u8 reg, u8 data)
|
||||
{
|
||||
mm_write_ind(reg, data, 0x7a8, 0x7a9);
|
||||
}
|
||||
#define write_cr(num, val) mm_write_cr(p, num, val)
|
||||
|
||||
static void mm_write_gr(struct fb_info *p, u8 reg, u8 data)
|
||||
{
|
||||
mm_write_ind(reg, data, 0x79c, 0x79d);
|
||||
}
|
||||
#define write_gr(num, val) mm_write_gr(p, num, val)
|
||||
|
||||
static void mm_write_sr(struct fb_info *p, u8 reg, u8 data)
|
||||
{
|
||||
mm_write_ind(reg, data, 0x788, 0x789);
|
||||
}
|
||||
#define write_sr(num, val) mm_write_sr(p, num, val)
|
||||
|
||||
static void mm_write_ar(struct fb_info *p, u8 reg, u8 data)
|
||||
{
|
||||
readb(mmio_base + 0x7b4);
|
||||
mm_write_ind(reg, data, 0x780, 0x780);
|
||||
}
|
||||
#define write_ar(num, val) mm_write_ar(p, num, val)
|
||||
|
||||
static int asiliantfb_pci_init(struct pci_dev *dp, const struct pci_device_id *);
|
||||
static int asiliantfb_check_var(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info);
|
||||
static int asiliantfb_set_par(struct fb_info *info);
|
||||
static int asiliantfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
|
||||
u_int transp, struct fb_info *info);
|
||||
|
||||
static struct fb_ops asiliantfb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_check_var = asiliantfb_check_var,
|
||||
.fb_set_par = asiliantfb_set_par,
|
||||
.fb_setcolreg = asiliantfb_setcolreg,
|
||||
.fb_fillrect = cfb_fillrect,
|
||||
.fb_copyarea = cfb_copyarea,
|
||||
.fb_imageblit = cfb_imageblit,
|
||||
};
|
||||
|
||||
/* Calculate the ratios for the dot clocks without using a single long long
|
||||
* value */
|
||||
static void asiliant_calc_dclk2(u32 *ppixclock, u8 *dclk2_m, u8 *dclk2_n, u8 *dclk2_div)
|
||||
{
|
||||
unsigned pixclock = *ppixclock;
|
||||
unsigned Ftarget = 1000000 * (1000000 / pixclock);
|
||||
unsigned n;
|
||||
unsigned best_error = 0xffffffff;
|
||||
unsigned best_m = 0xffffffff,
|
||||
best_n = 0xffffffff;
|
||||
unsigned ratio;
|
||||
unsigned remainder;
|
||||
unsigned char divisor = 0;
|
||||
|
||||
/* Calculate the frequency required. This is hard enough. */
|
||||
ratio = 1000000 / pixclock;
|
||||
remainder = 1000000 % pixclock;
|
||||
Ftarget = 1000000 * ratio + (1000000 * remainder) / pixclock;
|
||||
|
||||
while (Ftarget < 100000000) {
|
||||
divisor += 0x10;
|
||||
Ftarget <<= 1;
|
||||
}
|
||||
|
||||
ratio = Ftarget / Fref;
|
||||
remainder = Ftarget % Fref;
|
||||
|
||||
/* This expresses the constraint that 150kHz <= Fref/n <= 5Mhz,
|
||||
* together with 3 <= n <= 257. */
|
||||
for (n = 3; n <= 257; n++) {
|
||||
unsigned m = n * ratio + (n * remainder) / Fref;
|
||||
|
||||
/* 3 <= m <= 257 */
|
||||
if (m >= 3 && m <= 257) {
|
||||
unsigned new_error = Ftarget * n >= Fref * m ?
|
||||
((Ftarget * n) - (Fref * m)) : ((Fref * m) - (Ftarget * n));
|
||||
if (new_error < best_error) {
|
||||
best_n = n;
|
||||
best_m = m;
|
||||
best_error = new_error;
|
||||
}
|
||||
}
|
||||
/* But if VLD = 4, then 4m <= 1028 */
|
||||
else if (m <= 1028) {
|
||||
/* remember there are still only 8-bits of precision in m, so
|
||||
* avoid over-optimistic error calculations */
|
||||
unsigned new_error = Ftarget * n >= Fref * (m & ~3) ?
|
||||
((Ftarget * n) - (Fref * (m & ~3))) : ((Fref * (m & ~3)) - (Ftarget * n));
|
||||
if (new_error < best_error) {
|
||||
best_n = n;
|
||||
best_m = m;
|
||||
best_error = new_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (best_m > 257)
|
||||
best_m >>= 2; /* divide m by 4, and leave VCO loop divide at 4 */
|
||||
else
|
||||
divisor |= 4; /* or set VCO loop divide to 1 */
|
||||
*dclk2_m = best_m - 2;
|
||||
*dclk2_n = best_n - 2;
|
||||
*dclk2_div = divisor;
|
||||
*ppixclock = pixclock;
|
||||
return;
|
||||
}
|
||||
|
||||
static void asiliant_set_timing(struct fb_info *p)
|
||||
{
|
||||
unsigned hd = p->var.xres / 8;
|
||||
unsigned hs = (p->var.xres + p->var.right_margin) / 8;
|
||||
unsigned he = (p->var.xres + p->var.right_margin + p->var.hsync_len) / 8;
|
||||
unsigned ht = (p->var.left_margin + p->var.xres + p->var.right_margin + p->var.hsync_len) / 8;
|
||||
unsigned vd = p->var.yres;
|
||||
unsigned vs = p->var.yres + p->var.lower_margin;
|
||||
unsigned ve = p->var.yres + p->var.lower_margin + p->var.vsync_len;
|
||||
unsigned vt = p->var.upper_margin + p->var.yres + p->var.lower_margin + p->var.vsync_len;
|
||||
unsigned wd = (p->var.xres_virtual * ((p->var.bits_per_pixel+7)/8)) / 8;
|
||||
|
||||
if ((p->var.xres == 640) && (p->var.yres == 480) && (p->var.pixclock == 39722)) {
|
||||
write_fr(0x01, 0x02); /* LCD */
|
||||
} else {
|
||||
write_fr(0x01, 0x01); /* CRT */
|
||||
}
|
||||
|
||||
write_cr(0x11, (ve - 1) & 0x0f);
|
||||
write_cr(0x00, (ht - 5) & 0xff);
|
||||
write_cr(0x01, hd - 1);
|
||||
write_cr(0x02, hd);
|
||||
write_cr(0x03, ((ht - 1) & 0x1f) | 0x80);
|
||||
write_cr(0x04, hs);
|
||||
write_cr(0x05, (((ht - 1) & 0x20) <<2) | (he & 0x1f));
|
||||
write_cr(0x3c, (ht - 1) & 0xc0);
|
||||
write_cr(0x06, (vt - 2) & 0xff);
|
||||
write_cr(0x30, (vt - 2) >> 8);
|
||||
write_cr(0x07, 0x00);
|
||||
write_cr(0x08, 0x00);
|
||||
write_cr(0x09, 0x00);
|
||||
write_cr(0x10, (vs - 1) & 0xff);
|
||||
write_cr(0x32, ((vs - 1) >> 8) & 0xf);
|
||||
write_cr(0x11, ((ve - 1) & 0x0f) | 0x80);
|
||||
write_cr(0x12, (vd - 1) & 0xff);
|
||||
write_cr(0x31, ((vd - 1) & 0xf00) >> 8);
|
||||
write_cr(0x13, wd & 0xff);
|
||||
write_cr(0x41, (wd & 0xf00) >> 8);
|
||||
write_cr(0x15, (vs - 1) & 0xff);
|
||||
write_cr(0x33, ((vs - 1) >> 8) & 0xf);
|
||||
write_cr(0x38, ((ht - 5) & 0x100) >> 8);
|
||||
write_cr(0x16, (vt - 1) & 0xff);
|
||||
write_cr(0x18, 0x00);
|
||||
|
||||
if (p->var.xres == 640) {
|
||||
writeb(0xc7, mmio_base + 0x784); /* set misc output reg */
|
||||
} else {
|
||||
writeb(0x07, mmio_base + 0x784); /* set misc output reg */
|
||||
}
|
||||
}
|
||||
|
||||
static int asiliantfb_check_var(struct fb_var_screeninfo *var,
|
||||
struct fb_info *p)
|
||||
{
|
||||
unsigned long Ftarget, ratio, remainder;
|
||||
|
||||
ratio = 1000000 / var->pixclock;
|
||||
remainder = 1000000 % var->pixclock;
|
||||
Ftarget = 1000000 * ratio + (1000000 * remainder) / var->pixclock;
|
||||
|
||||
/* First check the constraint that the maximum post-VCO divisor is 32,
|
||||
* and the maximum Fvco is 220MHz */
|
||||
if (Ftarget > 220000000 || Ftarget < 3125000) {
|
||||
printk(KERN_ERR "asiliantfb dotclock must be between 3.125 and 220MHz\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
var->xres_virtual = var->xres;
|
||||
var->yres_virtual = var->yres;
|
||||
|
||||
if (var->bits_per_pixel == 24) {
|
||||
var->red.offset = 16;
|
||||
var->green.offset = 8;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = var->blue.length = var->green.length = 8;
|
||||
} else if (var->bits_per_pixel == 16) {
|
||||
switch (var->red.offset) {
|
||||
case 11:
|
||||
var->green.length = 6;
|
||||
break;
|
||||
case 10:
|
||||
var->green.length = 5;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
var->green.offset = 5;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = var->blue.length = 5;
|
||||
} else if (var->bits_per_pixel == 8) {
|
||||
var->red.offset = var->green.offset = var->blue.offset = 0;
|
||||
var->red.length = var->green.length = var->blue.length = 8;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int asiliantfb_set_par(struct fb_info *p)
|
||||
{
|
||||
u8 dclk2_m; /* Holds m-2 value for register */
|
||||
u8 dclk2_n; /* Holds n-2 value for register */
|
||||
u8 dclk2_div; /* Holds divisor bitmask */
|
||||
|
||||
/* Set pixclock */
|
||||
asiliant_calc_dclk2(&p->var.pixclock, &dclk2_m, &dclk2_n, &dclk2_div);
|
||||
|
||||
/* Set color depth */
|
||||
if (p->var.bits_per_pixel == 24) {
|
||||
write_xr(0x81, 0x16); /* 24 bit packed color mode */
|
||||
write_xr(0x82, 0x00); /* Disable palettes */
|
||||
write_xr(0x20, 0x20); /* 24 bit blitter mode */
|
||||
} else if (p->var.bits_per_pixel == 16) {
|
||||
if (p->var.red.offset == 11)
|
||||
write_xr(0x81, 0x15); /* 16 bit color mode */
|
||||
else
|
||||
write_xr(0x81, 0x14); /* 15 bit color mode */
|
||||
write_xr(0x82, 0x00); /* Disable palettes */
|
||||
write_xr(0x20, 0x10); /* 16 bit blitter mode */
|
||||
} else if (p->var.bits_per_pixel == 8) {
|
||||
write_xr(0x0a, 0x02); /* Linear */
|
||||
write_xr(0x81, 0x12); /* 8 bit color mode */
|
||||
write_xr(0x82, 0x00); /* Graphics gamma enable */
|
||||
write_xr(0x20, 0x00); /* 8 bit blitter mode */
|
||||
}
|
||||
p->fix.line_length = p->var.xres * (p->var.bits_per_pixel >> 3);
|
||||
p->fix.visual = (p->var.bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
|
||||
write_xr(0xc4, dclk2_m);
|
||||
write_xr(0xc5, dclk2_n);
|
||||
write_xr(0xc7, dclk2_div);
|
||||
/* Set up the CR registers */
|
||||
asiliant_set_timing(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int asiliantfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
|
||||
u_int transp, struct fb_info *p)
|
||||
{
|
||||
if (regno > 255)
|
||||
return 1;
|
||||
red >>= 8;
|
||||
green >>= 8;
|
||||
blue >>= 8;
|
||||
|
||||
/* Set hardware palete */
|
||||
writeb(regno, mmio_base + 0x790);
|
||||
udelay(1);
|
||||
writeb(red, mmio_base + 0x791);
|
||||
writeb(green, mmio_base + 0x791);
|
||||
writeb(blue, mmio_base + 0x791);
|
||||
|
||||
if (regno < 16) {
|
||||
switch(p->var.red.offset) {
|
||||
case 10: /* RGB 555 */
|
||||
((u32 *)(p->pseudo_palette))[regno] =
|
||||
((red & 0xf8) << 7) |
|
||||
((green & 0xf8) << 2) |
|
||||
((blue & 0xf8) >> 3);
|
||||
break;
|
||||
case 11: /* RGB 565 */
|
||||
((u32 *)(p->pseudo_palette))[regno] =
|
||||
((red & 0xf8) << 8) |
|
||||
((green & 0xfc) << 3) |
|
||||
((blue & 0xf8) >> 3);
|
||||
break;
|
||||
case 16: /* RGB 888 */
|
||||
((u32 *)(p->pseudo_palette))[regno] =
|
||||
(red << 16) |
|
||||
(green << 8) |
|
||||
(blue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct chips_init_reg {
|
||||
unsigned char addr;
|
||||
unsigned char data;
|
||||
};
|
||||
|
||||
static struct chips_init_reg chips_init_sr[] =
|
||||
{
|
||||
{0x00, 0x03}, /* Reset register */
|
||||
{0x01, 0x01}, /* Clocking mode */
|
||||
{0x02, 0x0f}, /* Plane mask */
|
||||
{0x04, 0x0e} /* Memory mode */
|
||||
};
|
||||
|
||||
static struct chips_init_reg chips_init_gr[] =
|
||||
{
|
||||
{0x03, 0x00}, /* Data rotate */
|
||||
{0x05, 0x00}, /* Graphics mode */
|
||||
{0x06, 0x01}, /* Miscellaneous */
|
||||
{0x08, 0x00} /* Bit mask */
|
||||
};
|
||||
|
||||
static struct chips_init_reg chips_init_ar[] =
|
||||
{
|
||||
{0x10, 0x01}, /* Mode control */
|
||||
{0x11, 0x00}, /* Overscan */
|
||||
{0x12, 0x0f}, /* Memory plane enable */
|
||||
{0x13, 0x00} /* Horizontal pixel panning */
|
||||
};
|
||||
|
||||
static struct chips_init_reg chips_init_cr[] =
|
||||
{
|
||||
{0x0c, 0x00}, /* Start address high */
|
||||
{0x0d, 0x00}, /* Start address low */
|
||||
{0x40, 0x00}, /* Extended Start Address */
|
||||
{0x41, 0x00}, /* Extended Start Address */
|
||||
{0x14, 0x00}, /* Underline location */
|
||||
{0x17, 0xe3}, /* CRT mode control */
|
||||
{0x70, 0x00} /* Interlace control */
|
||||
};
|
||||
|
||||
|
||||
static struct chips_init_reg chips_init_fr[] =
|
||||
{
|
||||
{0x01, 0x02},
|
||||
{0x03, 0x08},
|
||||
{0x08, 0xcc},
|
||||
{0x0a, 0x08},
|
||||
{0x18, 0x00},
|
||||
{0x1e, 0x80},
|
||||
{0x40, 0x83},
|
||||
{0x41, 0x00},
|
||||
{0x48, 0x13},
|
||||
{0x4d, 0x60},
|
||||
{0x4e, 0x0f},
|
||||
|
||||
{0x0b, 0x01},
|
||||
|
||||
{0x21, 0x51},
|
||||
{0x22, 0x1d},
|
||||
{0x23, 0x5f},
|
||||
{0x20, 0x4f},
|
||||
{0x34, 0x00},
|
||||
{0x24, 0x51},
|
||||
{0x25, 0x00},
|
||||
{0x27, 0x0b},
|
||||
{0x26, 0x00},
|
||||
{0x37, 0x80},
|
||||
{0x33, 0x0b},
|
||||
{0x35, 0x11},
|
||||
{0x36, 0x02},
|
||||
{0x31, 0xea},
|
||||
{0x32, 0x0c},
|
||||
{0x30, 0xdf},
|
||||
{0x10, 0x0c},
|
||||
{0x11, 0xe0},
|
||||
{0x12, 0x50},
|
||||
{0x13, 0x00},
|
||||
{0x16, 0x03},
|
||||
{0x17, 0xbd},
|
||||
{0x1a, 0x00},
|
||||
};
|
||||
|
||||
|
||||
static struct chips_init_reg chips_init_xr[] =
|
||||
{
|
||||
{0xce, 0x00}, /* set default memory clock */
|
||||
{0xcc, 200 }, /* MCLK ratio M */
|
||||
{0xcd, 18 }, /* MCLK ratio N */
|
||||
{0xce, 0x90}, /* MCLK divisor = 2 */
|
||||
|
||||
{0xc4, 209 },
|
||||
{0xc5, 118 },
|
||||
{0xc7, 32 },
|
||||
{0xcf, 0x06},
|
||||
{0x09, 0x01}, /* IO Control - CRT controller extensions */
|
||||
{0x0a, 0x02}, /* Frame buffer mapping */
|
||||
{0x0b, 0x01}, /* PCI burst write */
|
||||
{0x40, 0x03}, /* Memory access control */
|
||||
{0x80, 0x82}, /* Pixel pipeline configuration 0 */
|
||||
{0x81, 0x12}, /* Pixel pipeline configuration 1 */
|
||||
{0x82, 0x08}, /* Pixel pipeline configuration 2 */
|
||||
|
||||
{0xd0, 0x0f},
|
||||
{0xd1, 0x01},
|
||||
};
|
||||
|
||||
static void chips_hw_init(struct fb_info *p)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(chips_init_xr); ++i)
|
||||
write_xr(chips_init_xr[i].addr, chips_init_xr[i].data);
|
||||
write_xr(0x81, 0x12);
|
||||
write_xr(0x82, 0x08);
|
||||
write_xr(0x20, 0x00);
|
||||
for (i = 0; i < ARRAY_SIZE(chips_init_sr); ++i)
|
||||
write_sr(chips_init_sr[i].addr, chips_init_sr[i].data);
|
||||
for (i = 0; i < ARRAY_SIZE(chips_init_gr); ++i)
|
||||
write_gr(chips_init_gr[i].addr, chips_init_gr[i].data);
|
||||
for (i = 0; i < ARRAY_SIZE(chips_init_ar); ++i)
|
||||
write_ar(chips_init_ar[i].addr, chips_init_ar[i].data);
|
||||
/* Enable video output in attribute index register */
|
||||
writeb(0x20, mmio_base + 0x780);
|
||||
for (i = 0; i < ARRAY_SIZE(chips_init_cr); ++i)
|
||||
write_cr(chips_init_cr[i].addr, chips_init_cr[i].data);
|
||||
for (i = 0; i < ARRAY_SIZE(chips_init_fr); ++i)
|
||||
write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
|
||||
}
|
||||
|
||||
static struct fb_fix_screeninfo asiliantfb_fix = {
|
||||
.id = "Asiliant 69000",
|
||||
.type = FB_TYPE_PACKED_PIXELS,
|
||||
.visual = FB_VISUAL_PSEUDOCOLOR,
|
||||
.accel = FB_ACCEL_NONE,
|
||||
.line_length = 640,
|
||||
.smem_len = 0x200000, /* 2MB */
|
||||
};
|
||||
|
||||
static struct fb_var_screeninfo asiliantfb_var = {
|
||||
.xres = 640,
|
||||
.yres = 480,
|
||||
.xres_virtual = 640,
|
||||
.yres_virtual = 480,
|
||||
.bits_per_pixel = 8,
|
||||
.red = { .length = 8 },
|
||||
.green = { .length = 8 },
|
||||
.blue = { .length = 8 },
|
||||
.height = -1,
|
||||
.width = -1,
|
||||
.vmode = FB_VMODE_NONINTERLACED,
|
||||
.pixclock = 39722,
|
||||
.left_margin = 48,
|
||||
.right_margin = 16,
|
||||
.upper_margin = 33,
|
||||
.lower_margin = 10,
|
||||
.hsync_len = 96,
|
||||
.vsync_len = 2,
|
||||
};
|
||||
|
||||
static int init_asiliant(struct fb_info *p, unsigned long addr)
|
||||
{
|
||||
int err;
|
||||
|
||||
p->fix = asiliantfb_fix;
|
||||
p->fix.smem_start = addr;
|
||||
p->var = asiliantfb_var;
|
||||
p->fbops = &asiliantfb_ops;
|
||||
p->flags = FBINFO_DEFAULT;
|
||||
|
||||
err = fb_alloc_cmap(&p->cmap, 256, 0);
|
||||
if (err) {
|
||||
printk(KERN_ERR "C&T 69000 fb failed to alloc cmap memory\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = register_framebuffer(p);
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR "C&T 69000 framebuffer failed to register\n");
|
||||
fb_dealloc_cmap(&p->cmap);
|
||||
return err;
|
||||
}
|
||||
|
||||
fb_info(p, "Asiliant 69000 frame buffer (%dK RAM detected)\n",
|
||||
p->fix.smem_len / 1024);
|
||||
|
||||
writeb(0xff, mmio_base + 0x78c);
|
||||
chips_hw_init(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int asiliantfb_pci_init(struct pci_dev *dp,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
unsigned long addr, size;
|
||||
struct fb_info *p;
|
||||
int err;
|
||||
|
||||
if ((dp->resource[0].flags & IORESOURCE_MEM) == 0)
|
||||
return -ENODEV;
|
||||
addr = pci_resource_start(dp, 0);
|
||||
size = pci_resource_len(dp, 0);
|
||||
if (addr == 0)
|
||||
return -ENODEV;
|
||||
if (!request_mem_region(addr, size, "asiliantfb"))
|
||||
return -EBUSY;
|
||||
|
||||
p = framebuffer_alloc(sizeof(u32) * 16, &dp->dev);
|
||||
if (!p) {
|
||||
release_mem_region(addr, size);
|
||||
return -ENOMEM;
|
||||
}
|
||||
p->pseudo_palette = p->par;
|
||||
p->par = NULL;
|
||||
|
||||
p->screen_base = ioremap(addr, 0x800000);
|
||||
if (p->screen_base == NULL) {
|
||||
release_mem_region(addr, size);
|
||||
framebuffer_release(p);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pci_write_config_dword(dp, 4, 0x02800083);
|
||||
writeb(3, p->screen_base + 0x400784);
|
||||
|
||||
err = init_asiliant(p, addr);
|
||||
if (err) {
|
||||
iounmap(p->screen_base);
|
||||
release_mem_region(addr, size);
|
||||
framebuffer_release(p);
|
||||
return err;
|
||||
}
|
||||
|
||||
pci_set_drvdata(dp, p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void asiliantfb_remove(struct pci_dev *dp)
|
||||
{
|
||||
struct fb_info *p = pci_get_drvdata(dp);
|
||||
|
||||
unregister_framebuffer(p);
|
||||
fb_dealloc_cmap(&p->cmap);
|
||||
iounmap(p->screen_base);
|
||||
release_mem_region(pci_resource_start(dp, 0), pci_resource_len(dp, 0));
|
||||
framebuffer_release(p);
|
||||
}
|
||||
|
||||
static struct pci_device_id asiliantfb_pci_tbl[] = {
|
||||
{ PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_69000, PCI_ANY_ID, PCI_ANY_ID },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, asiliantfb_pci_tbl);
|
||||
|
||||
static struct pci_driver asiliantfb_driver = {
|
||||
.name = "asiliantfb",
|
||||
.id_table = asiliantfb_pci_tbl,
|
||||
.probe = asiliantfb_pci_init,
|
||||
.remove = asiliantfb_remove,
|
||||
};
|
||||
|
||||
static int __init asiliantfb_init(void)
|
||||
{
|
||||
if (fb_get_options("asiliantfb", NULL))
|
||||
return -ENODEV;
|
||||
|
||||
return pci_register_driver(&asiliantfb_driver);
|
||||
}
|
||||
|
||||
module_init(asiliantfb_init);
|
||||
|
||||
static void __exit asiliantfb_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&asiliantfb_driver);
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
3266
drivers/video/fbdev/atafb.c
Normal file
3266
drivers/video/fbdev/atafb.c
Normal file
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue