Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6

Conflicts:

	Documentation/kernel-parameters.txt
	arch/sh/include/asm/elf.h
This commit is contained in:
Paul Mundt 2008-10-20 11:17:52 +09:00
commit 4cb40f795a
6752 changed files with 538692 additions and 172011 deletions

View file

@ -76,6 +76,14 @@ config FB_DDC
select I2C
default n
config FB_BOOT_VESA_SUPPORT
bool
depends on FB
default n
---help---
If true, at least one selected framebuffer driver can take advantage
of VESA video modes set at an early boot stage via the vga= parameter.
config FB_CFB_FILLRECT
tristate
depends on FB
@ -172,11 +180,6 @@ config FB_DEFERRED_IO
bool
depends on FB
config FB_METRONOME
tristate
depends on FB
depends on FB_DEFERRED_IO
config FB_HECUBA
tristate
depends on FB
@ -259,16 +262,24 @@ config FB_PM2
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
help
This is the frame buffer device driver for the Permedia2 AGP frame
buffer card from ASK, aka `Graphic Blaster Exxtreme'. There is a
product page at
<http://www.ask.com.hk/product/Permedia%202/permedia2.htm>.
This is the frame buffer device driver for cards based on
the 3D Labs Permedia, Permedia 2 and Permedia 2V chips.
The driver was tested on the following cards:
Diamond FireGL 1000 PRO AGP
ELSA Gloria Synergy PCI
Appian Jeronimo PRO (both heads) PCI
3DLabs Oxygen ACX aka EONtronics Picasso P2 PCI
Techsource Raptor GFX-8P (aka Sun PGX-32) on SPARC
ASK Graphic Blaster Exxtreme AGP
To compile this driver as a module, choose M here: the
module will be called pm2fb.
config FB_PM2_FIFO_DISCONNECT
bool "enable FIFO disconnect feature"
depends on FB_PM2 && PCI
help
Support the Permedia2 FIFO disconnect feature (see CONFIG_FB_PM2).
Support the Permedia2 FIFO disconnect feature.
config FB_ARMCLCD
tristate "ARM PrimeCell PL110 support"
@ -678,7 +689,7 @@ config FB_VESA
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select VIDEO_SELECT
select FB_BOOT_VESA_SUPPORT
help
This is the frame buffer device driver for generic VESA 2.0
compliant graphic cards. The older VESA 1.2 cards are not supported.
@ -687,23 +698,14 @@ config FB_VESA
config FB_EFI
bool "EFI-based Framebuffer Support"
depends on (FB = y) && X86
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
help
This is the EFI frame buffer device driver. If the firmware on
your platform is UEFI2.0, select Y to add support for
Graphics Output Protocol for early console messages to appear.
config FB_IMAC
bool "Intel-based Macintosh Framebuffer Support"
depends on (FB = y) && X86 && EFI
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
help
This is the frame buffer device driver for the Intel-based Macintosh
This is the EFI frame buffer device driver. If the firmware on
your platform is EFI 1.10 or UEFI 2.0, select Y to add support for
using the EFI framebuffer as your console.
config FB_N411
tristate "N411 Apollo/Hecuba devkit support"
@ -1124,6 +1126,7 @@ config FB_INTEL
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_BOOT_VESA_SUPPORT
help
This driver supports the on-board graphics built in to the Intel
830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM chipsets.
@ -1476,6 +1479,7 @@ config FB_SIS
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_BOOT_VESA_SUPPORT
help
This is the frame buffer device driver for the SiS 300, 315, 330
and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets.
@ -1498,6 +1502,24 @@ config FB_SIS_315
(315/H/PRO, 55x, 650, 651, 740, 330, 661, 741, 760, 761) as well
as XGI V3XT, V5, V8 and Z7.
config FB_VIA
tristate "VIA UniChrome (Pro) and Chrome9 display support"
depends on FB && PCI
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
select I2C_ALGOBIT
select I2C
help
This is the frame buffer device driver for Graphics chips of VIA
UniChrome (Pro) Family (CLE266,PM800/CN400,P4M800CE/P4M800Pro/
CN700/VN800,CX700/VX700,P4M890) and Chrome9 Family (K8M890,CN896
/P4M900,VX800)
Say Y if you have a VIA UniChrome graphics board.
To compile this driver as a module, choose M here: the
module will be called viafb.
config FB_NEOMAGIC
tristate "NeoMagic display support"
depends on FB && PCI
@ -1527,25 +1549,25 @@ config FB_KYRO
module will be called kyrofb.
config FB_3DFX
tristate "3Dfx Banshee/Voodoo3 display support"
tristate "3Dfx Banshee/Voodoo3/Voodoo5 display support"
depends on FB && PCI
select FB_CFB_IMAGEBLIT
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
help
This driver supports graphics boards with the 3Dfx Banshee/Voodoo3
chips. Say Y if you have such a graphics board.
This driver supports graphics boards with the 3Dfx Banshee,
Voodoo3 or VSA-100 (aka Voodoo4/5) chips. Say Y if you have
such a graphics board.
To compile this driver as a module, choose M here: the
module will be called tdfxfb.
config FB_3DFX_ACCEL
bool "3Dfx Banshee/Voodoo3 Acceleration functions (EXPERIMENTAL)"
bool "3Dfx Acceleration functions (EXPERIMENTAL)"
depends on FB_3DFX && EXPERIMENTAL
---help---
This will compile the 3Dfx Banshee/Voodoo3 frame buffer device
with acceleration functions.
This will compile the 3Dfx Banshee/Voodoo3/VSA-100 frame buffer
device driver with acceleration functions.
config FB_VOODOO1
tristate "3Dfx Voodoo Graphics (sst1) support"
@ -1583,7 +1605,6 @@ config FB_CYBLA
tristate "Cyberblade/i1 support"
depends on FB && PCI && X86_32 && !64BIT
select FB_CFB_IMAGEBLIT
select VIDEO_SELECT
---help---
This driver is supposed to support the Trident Cyberblade/i1
graphics core integrated in the VIA VT8601A North Bridge,
@ -1611,17 +1632,16 @@ config FB_TRIDENT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
---help---
This driver is supposed to support graphics boards with the
Trident CyberXXXX/Image/CyberBlade chips mostly found in laptops
This is the frame buffer device driver for Trident PCI/AGP chipsets.
Supported chipset families are TGUI 9440/96XX, 3DImage, Blade3D
and Blade XP.
There are also integrated versions of these chips called CyberXXXX,
CyberImage or CyberBlade. These chips are mostly found in laptops
but also on some motherboards. For more information, read
<file:Documentation/fb/tridentfb.txt>
Cyberblade/i1 support will be removed soon, use the cyblafb driver
instead.
Say Y if you have such a graphics board.
To compile this driver as a module, choose M here: the
module will be called tridentfb.
@ -1876,6 +1896,28 @@ config FB_SH_MOBILE_LCDC
---help---
Frame buffer driver for the on-chip SH-Mobile LCD controller.
config FB_TMIO
tristate "Toshiba Mobile IO FrameBuffer support"
depends on FB && MFD_CORE
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
---help---
Frame buffer driver for the Toshiba Mobile IO integrated as found
on the Sharp SL-6000 series
This driver is also available as a module ( = code which can be
inserted and removed from the running kernel whenever you want). The
module will be called tmiofb. If you want to compile it as a module,
say M here and read <file:Documentation/kbuild/modules.txt>.
If unsure, say N.
config FB_TMIO_ACCELL
bool "tmiofb acceleration"
depends on FB_TMIO
default y
config FB_S3C2410
tristate "S3C2410 LCD framebuffer support"
depends on FB && ARCH_S3C2410
@ -1974,19 +2016,6 @@ config FB_XILINX
framebuffer. ML300 carries a 640*480 LCD display on the board,
ML403 uses a standard DB15 VGA connector.
config FB_AM200EPD
tristate "AM-200 E-Ink EPD devkit support"
depends on FB && ARCH_PXA && MMU
select FB_SYS_FILLRECT
select FB_SYS_COPYAREA
select FB_SYS_IMAGEBLIT
select FB_SYS_FOPS
select FB_DEFERRED_IO
select FB_METRONOME
help
This enables support for the Metronome display controller used on
the E-Ink AM-200 EPD devkit.
config FB_COBALT
tristate "Cobalt server LCD frame buffer support"
depends on FB && MIPS_COBALT
@ -2041,6 +2070,19 @@ config XEN_FBDEV_FRONTEND
frame buffer driver. It communicates with a back-end
in another domain.
config FB_METRONOME
tristate "E-Ink Metronome/8track controller support"
depends on FB
select FB_SYS_FILLRECT
select FB_SYS_COPYAREA
select FB_SYS_IMAGEBLIT
select FB_SYS_FOPS
select FB_DEFERRED_IO
help
This driver implements support for the E-Ink Metronome
controller. The pre-release name for this device was 8track
and could also have been called by some vendors as PVI-nnnn.
source "drivers/video/omap/Kconfig"
source "drivers/video/backlight/Kconfig"

View file

@ -29,7 +29,6 @@ obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o
# Hardware specific drivers go first
obj-$(CONFIG_FB_AMIGA) += amifb.o c2p.o
obj-$(CONFIG_FB_AM200EPD) += am200epd.o
obj-$(CONFIG_FB_ARC) += arcfb.o
obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o
obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
@ -43,6 +42,7 @@ 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/
@ -98,6 +98,7 @@ obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o
obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o
obj-$(CONFIG_FB_PXA) += pxafb.o
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_PMAG_AA) += pmag-aa-fb.o
@ -125,7 +126,6 @@ obj-$(CONFIG_FB_CARMINE) += carminefb.o
# Platform or fallback drivers go here
obj-$(CONFIG_FB_UVESA) += uvesafb.o
obj-$(CONFIG_FB_VESA) += vesafb.o
obj-$(CONFIG_FB_IMAC) += imacfb.o
obj-$(CONFIG_FB_EFI) += efifb.o
obj-$(CONFIG_FB_VGA16) += vga16fb.o
obj-$(CONFIG_FB_OF) += offb.o

View file

@ -1,295 +0,0 @@
/*
* linux/drivers/video/am200epd.c -- Platform device for AM200 EPD kit
*
* Copyright (C) 2008, Jaya Kumar
*
* 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 work was made possible by help and equipment support from E-Ink
* Corporation. http://support.eink.com/community
*
* This driver is written to be used with the Metronome display controller.
* on the AM200 EPD prototype kit/development kit with an E-Ink 800x600
* Vizplex EPD on a Gumstix board using the Lyre interface board.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/list.h>
#include <linux/uaccess.h>
#include <linux/irq.h>
#include <video/metronomefb.h>
#include <mach/pxa-regs.h>
/* register offsets for gpio control */
#define LED_GPIO_PIN 51
#define STDBY_GPIO_PIN 48
#define RST_GPIO_PIN 49
#define RDY_GPIO_PIN 32
#define ERR_GPIO_PIN 17
#define PCBPWR_GPIO_PIN 16
#define AF_SEL_GPIO_N 0x3
#define GAFR0_U_OFFSET(pin) ((pin - 16) * 2)
#define GAFR1_L_OFFSET(pin) ((pin - 32) * 2)
#define GAFR1_U_OFFSET(pin) ((pin - 48) * 2)
#define GPDR1_OFFSET(pin) (pin - 32)
#define GPCR1_OFFSET(pin) (pin - 32)
#define GPSR1_OFFSET(pin) (pin - 32)
#define GPCR0_OFFSET(pin) (pin)
#define GPSR0_OFFSET(pin) (pin)
static void am200_set_gpio_output(int pin, int val)
{
u8 index;
index = pin >> 4;
switch (index) {
case 1:
if (val)
GPSR0 |= (1 << GPSR0_OFFSET(pin));
else
GPCR0 |= (1 << GPCR0_OFFSET(pin));
break;
case 2:
break;
case 3:
if (val)
GPSR1 |= (1 << GPSR1_OFFSET(pin));
else
GPCR1 |= (1 << GPCR1_OFFSET(pin));
break;
default:
printk(KERN_ERR "unimplemented\n");
}
}
static void __devinit am200_init_gpio_pin(int pin, int dir)
{
u8 index;
/* dir 0 is output, 1 is input
- do 2 things here:
- set gpio alternate function to standard gpio
- set gpio direction to input or output */
index = pin >> 4;
switch (index) {
case 1:
GAFR0_U &= ~(AF_SEL_GPIO_N << GAFR0_U_OFFSET(pin));
if (dir)
GPDR0 &= ~(1 << pin);
else
GPDR0 |= (1 << pin);
break;
case 2:
GAFR1_L &= ~(AF_SEL_GPIO_N << GAFR1_L_OFFSET(pin));
if (dir)
GPDR1 &= ~(1 << GPDR1_OFFSET(pin));
else
GPDR1 |= (1 << GPDR1_OFFSET(pin));
break;
case 3:
GAFR1_U &= ~(AF_SEL_GPIO_N << GAFR1_U_OFFSET(pin));
if (dir)
GPDR1 &= ~(1 << GPDR1_OFFSET(pin));
else
GPDR1 |= (1 << GPDR1_OFFSET(pin));
break;
default:
printk(KERN_ERR "unimplemented\n");
}
}
static void am200_init_gpio_regs(struct metronomefb_par *par)
{
am200_init_gpio_pin(LED_GPIO_PIN, 0);
am200_set_gpio_output(LED_GPIO_PIN, 0);
am200_init_gpio_pin(STDBY_GPIO_PIN, 0);
am200_set_gpio_output(STDBY_GPIO_PIN, 0);
am200_init_gpio_pin(RST_GPIO_PIN, 0);
am200_set_gpio_output(RST_GPIO_PIN, 0);
am200_init_gpio_pin(RDY_GPIO_PIN, 1);
am200_init_gpio_pin(ERR_GPIO_PIN, 1);
am200_init_gpio_pin(PCBPWR_GPIO_PIN, 0);
am200_set_gpio_output(PCBPWR_GPIO_PIN, 0);
}
static void am200_disable_lcd_controller(struct metronomefb_par *par)
{
LCSR = 0xffffffff; /* Clear LCD Status Register */
LCCR0 |= LCCR0_DIS; /* Disable LCD Controller */
/* we reset and just wait for things to settle */
msleep(200);
}
static void am200_enable_lcd_controller(struct metronomefb_par *par)
{
LCSR = 0xffffffff;
FDADR0 = par->metromem_desc_dma;
LCCR0 |= LCCR0_ENB;
}
static void am200_init_lcdc_regs(struct metronomefb_par *par)
{
/* here we do:
- disable the lcd controller
- setup lcd control registers
- setup dma descriptor
- reenable lcd controller
*/
/* disable the lcd controller */
am200_disable_lcd_controller(par);
/* setup lcd control registers */
LCCR0 = LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM | LCCR0_PAS
| LCCR0_QDM | LCCR0_BM | LCCR0_OUM;
LCCR1 = (par->info->var.xres/2 - 1) /* pixels per line */
| (27 << 10) /* hsync pulse width - 1 */
| (33 << 16) /* eol pixel count */
| (33 << 24); /* bol pixel count */
LCCR2 = (par->info->var.yres - 1) /* lines per panel */
| (24 << 10) /* vsync pulse width - 1 */
| (2 << 16) /* eof pixel count */
| (0 << 24); /* bof pixel count */
LCCR3 = 2 /* pixel clock divisor */
| (24 << 8) /* AC Bias pin freq */
| LCCR3_16BPP /* BPP */
| LCCR3_PCP; /* PCP falling edge */
}
static void am200_post_dma_setup(struct metronomefb_par *par)
{
par->metromem_desc->mFDADR0 = par->metromem_desc_dma;
par->metromem_desc->mFSADR0 = par->metromem_dma;
par->metromem_desc->mFIDR0 = 0;
par->metromem_desc->mLDCMD0 = par->info->var.xres
* par->info->var.yres;
am200_enable_lcd_controller(par);
}
static void am200_free_irq(struct fb_info *info)
{
free_irq(IRQ_GPIO(RDY_GPIO_PIN), info);
}
static irqreturn_t am200_handle_irq(int irq, void *dev_id)
{
struct fb_info *info = dev_id;
struct metronomefb_par *par = info->par;
wake_up_interruptible(&par->waitq);
return IRQ_HANDLED;
}
static int am200_setup_irq(struct fb_info *info)
{
int retval;
retval = request_irq(IRQ_GPIO(RDY_GPIO_PIN), am200_handle_irq,
IRQF_DISABLED, "AM200", info);
if (retval) {
printk(KERN_ERR "am200epd: request_irq failed: %d\n", retval);
return retval;
}
return set_irq_type(IRQ_GPIO(RDY_GPIO_PIN), IRQ_TYPE_EDGE_FALLING);
}
static void am200_set_rst(struct metronomefb_par *par, int state)
{
am200_set_gpio_output(RST_GPIO_PIN, state);
}
static void am200_set_stdby(struct metronomefb_par *par, int state)
{
am200_set_gpio_output(STDBY_GPIO_PIN, state);
}
static int am200_wait_event(struct metronomefb_par *par)
{
return wait_event_timeout(par->waitq, (GPLR1 & 0x01), HZ);
}
static int am200_wait_event_intr(struct metronomefb_par *par)
{
return wait_event_interruptible_timeout(par->waitq, (GPLR1 & 0x01), HZ);
}
static struct metronome_board am200_board = {
.owner = THIS_MODULE,
.free_irq = am200_free_irq,
.setup_irq = am200_setup_irq,
.init_gpio_regs = am200_init_gpio_regs,
.init_lcdc_regs = am200_init_lcdc_regs,
.post_dma_setup = am200_post_dma_setup,
.set_rst = am200_set_rst,
.set_stdby = am200_set_stdby,
.met_wait_event = am200_wait_event,
.met_wait_event_intr = am200_wait_event_intr,
};
static struct platform_device *am200_device;
static int __init am200_init(void)
{
int ret;
/* request our platform independent driver */
request_module("metronomefb");
am200_device = platform_device_alloc("metronomefb", -1);
if (!am200_device)
return -ENOMEM;
platform_device_add_data(am200_device, &am200_board,
sizeof(am200_board));
/* this _add binds metronomefb to am200. metronomefb refcounts am200 */
ret = platform_device_add(am200_device);
if (ret)
platform_device_put(am200_device);
return ret;
}
static void __exit am200_exit(void)
{
platform_device_unregister(am200_device);
}
module_init(am200_init);
module_exit(am200_exit);
MODULE_DESCRIPTION("board driver for am200 metronome epd kit");
MODULE_AUTHOR("Jaya Kumar");
MODULE_LICENSE("GPL");

View file

@ -208,6 +208,36 @@ static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2)
return value;
}
static void atmel_lcdfb_stop_nowait(struct atmel_lcdfb_info *sinfo)
{
/* Turn off the LCD controller and the DMA controller */
lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
/* Wait for the LCDC core to become idle */
while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
msleep(10);
lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
}
static void atmel_lcdfb_stop(struct atmel_lcdfb_info *sinfo)
{
atmel_lcdfb_stop_nowait(sinfo);
/* Wait for DMA engine to become idle... */
while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
msleep(10);
}
static void atmel_lcdfb_start(struct atmel_lcdfb_info *sinfo)
{
lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
(sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET)
| ATMEL_LCDC_PWR);
}
static void atmel_lcdfb_update_dma(struct fb_info *info,
struct fb_var_screeninfo *var)
{
@ -342,6 +372,13 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
var->transp.offset = var->transp.length = 0;
var->xoffset = var->yoffset = 0;
if (info->fix.smem_len) {
unsigned int smem_len = (var->xres_virtual * var->yres_virtual
* ((var->bits_per_pixel + 7) / 8));
if (smem_len > info->fix.smem_len)
return -EINVAL;
}
/* Saturate vertical and horizontal timings at maximum values */
var->vsync_len = min_t(u32, var->vsync_len,
(ATMEL_LCDC_VPW >> ATMEL_LCDC_VPW_OFFSET) + 1);
@ -378,6 +415,10 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
var->red.offset = 11;
var->blue.offset = 0;
var->green.length = 6;
} else if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB555) {
var->red.offset = 10;
var->blue.offset = 0;
var->green.length = 5;
} else {
/* BGR:555 mode */
var->red.offset = 0;
@ -420,26 +461,8 @@ static void atmel_lcdfb_reset(struct atmel_lcdfb_info *sinfo)
{
might_sleep();
/* LCD power off */
lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
/* wait for the LCDC core to become idle */
while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
msleep(10);
/* DMA disable */
lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
/* wait for DMA engine to become idle */
while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
msleep(10);
/* LCD power on */
lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
(sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR);
/* DMA enable */
lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
atmel_lcdfb_stop(sinfo);
atmel_lcdfb_start(sinfo);
}
/**
@ -471,14 +494,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
info->var.xres, info->var.yres,
info->var.xres_virtual, info->var.yres_virtual);
/* Turn off the LCD controller and the DMA controller */
lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
/* Wait for the LCDC core to become idle */
while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
msleep(10);
lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
atmel_lcdfb_stop_nowait(sinfo);
if (info->var.bits_per_pixel == 1)
info->fix.visual = FB_VISUAL_MONO01;
@ -583,13 +599,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
msleep(10);
dev_dbg(info->device, " * re-enable DMA engine\n");
/* ...and enable it with updated configuration */
lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
dev_dbg(info->device, " * re-enable LCDC core\n");
lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
(sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR);
atmel_lcdfb_start(sinfo);
dev_dbg(info->device, " * DONE\n");
@ -1032,11 +1042,20 @@ static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg)
struct fb_info *info = platform_get_drvdata(pdev);
struct atmel_lcdfb_info *sinfo = info->par;
/*
* We don't want to handle interrupts while the clock is
* stopped. It may take forever.
*/
lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0);
if (sinfo->atmel_lcdfb_power_control)
sinfo->atmel_lcdfb_power_control(0);
atmel_lcdfb_stop(sinfo);
atmel_lcdfb_stop_clock(sinfo);
return 0;
}
@ -1046,9 +1065,15 @@ static int atmel_lcdfb_resume(struct platform_device *pdev)
struct atmel_lcdfb_info *sinfo = info->par;
atmel_lcdfb_start_clock(sinfo);
atmel_lcdfb_start(sinfo);
if (sinfo->atmel_lcdfb_power_control)
sinfo->atmel_lcdfb_power_control(1);
lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon);
/* Enable FIFO & DMA errors */
lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI
| ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);
return 0;
}

View file

@ -5,61 +5,61 @@
* --dte
*/
static void radeon_fixup_offset(struct radeonfb_info *rinfo)
#define FLUSH_CACHE_WORKAROUND 1
void radeon_fifo_update_and_wait(struct radeonfb_info *rinfo, int entries)
{
u32 local_base;
int i;
/* *** Ugly workaround *** */
/*
* On some platforms, the video memory is mapped at 0 in radeon chip space
* (like PPCs) by the firmware. X will always move it up so that it's seen
* by the chip to be at the same address as the PCI BAR.
* That means that when switching back from X, there is a mismatch between
* the offsets programmed into the engine. This means that potentially,
* accel operations done before radeonfb has a chance to re-init the engine
* will have incorrect offsets, and potentially trash system memory !
*
* The correct fix is for fbcon to never call any accel op before the engine
* has properly been re-initialized (by a call to set_var), but this is a
* complex fix. This workaround in the meantime, called before every accel
* operation, makes sure the offsets are in sync.
*/
for (i=0; i<2000000; i++) {
rinfo->fifo_free = INREG(RBBM_STATUS) & 0x7f;
if (rinfo->fifo_free >= entries)
return;
udelay(10);
}
printk(KERN_ERR "radeonfb: FIFO Timeout !\n");
/* XXX Todo: attempt to reset the engine */
}
radeon_fifo_wait (1);
local_base = INREG(MC_FB_LOCATION) << 16;
if (local_base == rinfo->fb_local_base)
static inline void radeon_fifo_wait(struct radeonfb_info *rinfo, int entries)
{
if (entries <= rinfo->fifo_free)
rinfo->fifo_free -= entries;
else
radeon_fifo_update_and_wait(rinfo, entries);
}
static inline void radeonfb_set_creg(struct radeonfb_info *rinfo, u32 reg,
u32 *cache, u32 new_val)
{
if (new_val == *cache)
return;
rinfo->fb_local_base = local_base;
radeon_fifo_wait (3);
OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) |
(rinfo->fb_local_base >> 10));
OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
*cache = new_val;
radeon_fifo_wait(rinfo, 1);
OUTREG(reg, new_val);
}
static void radeonfb_prim_fillrect(struct radeonfb_info *rinfo,
const struct fb_fillrect *region)
{
radeon_fifo_wait(4);
OUTREG(DP_GUI_MASTER_CNTL,
rinfo->dp_gui_master_cntl /* contains, like GMC_DST_32BPP */
| GMC_BRUSH_SOLID_COLOR
| ROP3_P);
if (radeon_get_dstbpp(rinfo->depth) != DST_8BPP)
OUTREG(DP_BRUSH_FRGD_CLR, rinfo->pseudo_palette[region->color]);
else
OUTREG(DP_BRUSH_FRGD_CLR, region->color);
OUTREG(DP_WRITE_MSK, 0xffffffff);
OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM));
radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache,
rinfo->dp_gui_mc_base | GMC_BRUSH_SOLID_COLOR | ROP3_P);
radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache,
DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
radeonfb_set_creg(rinfo, DP_BRUSH_FRGD_CLR, &rinfo->dp_brush_fg_cache,
region->color);
radeon_fifo_wait(2);
/* Ensure the dst cache is flushed and the engine idle before
* issuing the operation.
*
* This works around engine lockups on some cards
*/
#if FLUSH_CACHE_WORKAROUND
radeon_fifo_wait(rinfo, 2);
OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
radeon_fifo_wait(2);
#endif
radeon_fifo_wait(rinfo, 2);
OUTREG(DST_Y_X, (region->dy << 16) | region->dx);
OUTREG(DST_WIDTH_HEIGHT, (region->width << 16) | region->height);
}
@ -70,15 +70,14 @@ void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region)
struct fb_fillrect modded;
int vxres, vyres;
if (info->state != FBINFO_STATE_RUNNING)
WARN_ON(rinfo->gfx_mode);
if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode)
return;
if (info->flags & FBINFO_HWACCEL_DISABLED) {
cfb_fillrect(info, region);
return;
}
radeon_fixup_offset(rinfo);
vxres = info->var.xres_virtual;
vyres = info->var.yres_virtual;
@ -91,6 +90,10 @@ void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region)
if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx;
if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
info->fix.visual == FB_VISUAL_DIRECTCOLOR )
modded.color = ((u32 *) (info->pseudo_palette))[region->color];
radeonfb_prim_fillrect(rinfo, &modded);
}
@ -109,22 +112,22 @@ static void radeonfb_prim_copyarea(struct radeonfb_info *rinfo,
if ( xdir < 0 ) { sx += w-1; dx += w-1; }
if ( ydir < 0 ) { sy += h-1; dy += h-1; }
radeon_fifo_wait(3);
OUTREG(DP_GUI_MASTER_CNTL,
rinfo->dp_gui_master_cntl /* i.e. GMC_DST_32BPP */
| GMC_BRUSH_NONE
| GMC_SRC_DSTCOLOR
| ROP3_S
| DP_SRC_SOURCE_MEMORY );
OUTREG(DP_WRITE_MSK, 0xffffffff);
OUTREG(DP_CNTL, (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0)
| (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0));
radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache,
rinfo->dp_gui_mc_base |
GMC_BRUSH_NONE |
GMC_SRC_DATATYPE_COLOR |
ROP3_S |
DP_SRC_SOURCE_MEMORY);
radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache,
(xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0) |
(ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0));
radeon_fifo_wait(2);
#if FLUSH_CACHE_WORKAROUND
radeon_fifo_wait(rinfo, 2);
OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
radeon_fifo_wait(3);
#endif
radeon_fifo_wait(rinfo, 3);
OUTREG(SRC_Y_X, (sy << 16) | sx);
OUTREG(DST_Y_X, (dy << 16) | dx);
OUTREG(DST_HEIGHT_WIDTH, (h << 16) | w);
@ -143,15 +146,14 @@ void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
modded.width = area->width;
modded.height = area->height;
if (info->state != FBINFO_STATE_RUNNING)
WARN_ON(rinfo->gfx_mode);
if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode)
return;
if (info->flags & FBINFO_HWACCEL_DISABLED) {
cfb_copyarea(info, area);
return;
}
radeon_fixup_offset(rinfo);
vxres = info->var.xres_virtual;
vyres = info->var.yres_virtual;
@ -168,13 +170,112 @@ void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
radeonfb_prim_copyarea(rinfo, &modded);
}
static void radeonfb_prim_imageblit(struct radeonfb_info *rinfo,
const struct fb_image *image,
u32 fg, u32 bg)
{
unsigned int src_bytes, dwords;
u32 *bits;
radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache,
rinfo->dp_gui_mc_base |
GMC_BRUSH_NONE |
GMC_SRC_DATATYPE_MONO_FG_BG |
ROP3_S |
GMC_BYTE_ORDER_MSB_TO_LSB |
DP_SRC_SOURCE_HOST_DATA);
radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache,
DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
radeonfb_set_creg(rinfo, DP_SRC_FRGD_CLR, &rinfo->dp_src_fg_cache, fg);
radeonfb_set_creg(rinfo, DP_SRC_BKGD_CLR, &rinfo->dp_src_bg_cache, bg);
radeon_fifo_wait(rinfo, 1);
OUTREG(DST_Y_X, (image->dy << 16) | image->dx);
/* Ensure the dst cache is flushed and the engine idle before
* issuing the operation.
*
* This works around engine lockups on some cards
*/
#if FLUSH_CACHE_WORKAROUND
radeon_fifo_wait(rinfo, 2);
OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
#endif
/* X here pads width to a multiple of 32 and uses the clipper to
* adjust the result. Is that really necessary ? Things seem to
* work ok for me without that and the doco doesn't seem to imply
* there is such a restriction.
*/
OUTREG(DST_WIDTH_HEIGHT, (image->width << 16) | image->height);
src_bytes = (((image->width * image->depth) + 7) / 8) * image->height;
dwords = (src_bytes + 3) / 4;
bits = (u32*)(image->data);
while(dwords >= 8) {
radeon_fifo_wait(rinfo, 8);
#if BITS_PER_LONG == 64
__raw_writeq(*((u64 *)(bits)), rinfo->mmio_base + HOST_DATA0);
__raw_writeq(*((u64 *)(bits+2)), rinfo->mmio_base + HOST_DATA2);
__raw_writeq(*((u64 *)(bits+4)), rinfo->mmio_base + HOST_DATA4);
__raw_writeq(*((u64 *)(bits+6)), rinfo->mmio_base + HOST_DATA6);
bits += 8;
#else
__raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA0);
__raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA1);
__raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA2);
__raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA3);
__raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA4);
__raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA5);
__raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA6);
__raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA7);
#endif
dwords -= 8;
}
while(dwords--) {
radeon_fifo_wait(rinfo, 1);
__raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA0);
}
}
void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct radeonfb_info *rinfo = info->par;
u32 fg, bg;
if (info->state != FBINFO_STATE_RUNNING)
WARN_ON(rinfo->gfx_mode);
if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode)
return;
radeon_engine_idle();
if (!image->width || !image->height)
return;
/* We only do 1 bpp color expansion for now */
if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1)
goto fallback;
/* Fallback if running out of the screen. We may do clipping
* in the future */
if ((image->dx + image->width) > info->var.xres_virtual ||
(image->dy + image->height) > info->var.yres_virtual)
goto fallback;
if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
fg = ((u32*)(info->pseudo_palette))[image->fg_color];
bg = ((u32*)(info->pseudo_palette))[image->bg_color];
} else {
fg = image->fg_color;
bg = image->bg_color;
}
radeonfb_prim_imageblit(rinfo, image, fg, bg);
return;
fallback:
radeon_engine_idle(rinfo);
cfb_imageblit(info, image);
}
@ -185,7 +286,8 @@ int radeonfb_sync(struct fb_info *info)
if (info->state != FBINFO_STATE_RUNNING)
return 0;
radeon_engine_idle();
radeon_engine_idle(rinfo);
return 0;
}
@ -211,9 +313,7 @@ void radeonfb_engine_reset(struct radeonfb_info *rinfo)
host_path_cntl = INREG(HOST_PATH_CNTL);
rbbm_soft_reset = INREG(RBBM_SOFT_RESET);
if (rinfo->family == CHIP_FAMILY_R300 ||
rinfo->family == CHIP_FAMILY_R350 ||
rinfo->family == CHIP_FAMILY_RV350) {
if (IS_R300_VARIANT(rinfo)) {
u32 tmp;
OUTREG(RBBM_SOFT_RESET, (rbbm_soft_reset |
@ -249,9 +349,7 @@ void radeonfb_engine_reset(struct radeonfb_info *rinfo)
INREG(HOST_PATH_CNTL);
OUTREG(HOST_PATH_CNTL, host_path_cntl);
if (rinfo->family != CHIP_FAMILY_R300 &&
rinfo->family != CHIP_FAMILY_R350 &&
rinfo->family != CHIP_FAMILY_RV350)
if (!IS_R300_VARIANT(rinfo))
OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
@ -265,15 +363,24 @@ void radeonfb_engine_init (struct radeonfb_info *rinfo)
/* disable 3D engine */
OUTREG(RB3D_CNTL, 0);
rinfo->fifo_free = 0;
radeonfb_engine_reset(rinfo);
radeon_fifo_wait (1);
if ((rinfo->family != CHIP_FAMILY_R300) &&
(rinfo->family != CHIP_FAMILY_R350) &&
(rinfo->family != CHIP_FAMILY_RV350))
radeon_fifo_wait(rinfo, 1);
if (IS_R300_VARIANT(rinfo)) {
OUTREG(RB2D_DSTCACHE_MODE, INREG(RB2D_DSTCACHE_MODE) |
RB2D_DC_AUTOFLUSH_ENABLE |
RB2D_DC_DC_DISABLE_IGNORE_PE);
} else {
/* This needs to be double checked with ATI. Latest X driver
* completely "forgets" to set this register on < r3xx, and
* we used to just write 0 there... I'll keep the 0 and update
* that when we have sorted things out on X side.
*/
OUTREG(RB2D_DSTCACHE_MODE, 0);
}
radeon_fifo_wait (3);
radeon_fifo_wait(rinfo, 3);
/* We re-read MC_FB_LOCATION from card as it can have been
* modified by XFree drivers (ouch !)
*/
@ -284,41 +391,57 @@ void radeonfb_engine_init (struct radeonfb_info *rinfo)
OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
radeon_fifo_wait (1);
#if defined(__BIG_ENDIAN)
radeon_fifo_wait(rinfo, 1);
#ifdef __BIG_ENDIAN
OUTREGP(DP_DATATYPE, HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN);
#else
OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
#endif
radeon_fifo_wait (2);
radeon_fifo_wait(rinfo, 2);
OUTREG(DEFAULT_SC_TOP_LEFT, 0);
OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX |
DEFAULT_SC_BOTTOM_MAX));
/* set default DP_GUI_MASTER_CNTL */
temp = radeon_get_dstbpp(rinfo->depth);
rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS);
rinfo->dp_gui_mc_base = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS);
radeon_fifo_wait (1);
OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl |
GMC_BRUSH_SOLID_COLOR |
GMC_SRC_DATATYPE_COLOR));
rinfo->dp_gui_mc_cache = rinfo->dp_gui_mc_base |
GMC_BRUSH_SOLID_COLOR |
GMC_SRC_DATATYPE_COLOR;
radeon_fifo_wait(rinfo, 1);
OUTREG(DP_GUI_MASTER_CNTL, rinfo->dp_gui_mc_cache);
radeon_fifo_wait (7);
/* clear line drawing regs */
radeon_fifo_wait(rinfo, 2);
OUTREG(DST_LINE_START, 0);
OUTREG(DST_LINE_END, 0);
/* set brush color regs */
OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff);
OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000);
/* set brush and source color regs */
rinfo->dp_brush_fg_cache = 0xffffffff;
rinfo->dp_brush_bg_cache = 0x00000000;
rinfo->dp_src_fg_cache = 0xffffffff;
rinfo->dp_src_bg_cache = 0x00000000;
radeon_fifo_wait(rinfo, 4);
OUTREG(DP_BRUSH_FRGD_CLR, rinfo->dp_brush_fg_cache);
OUTREG(DP_BRUSH_BKGD_CLR, rinfo->dp_brush_bg_cache);
OUTREG(DP_SRC_FRGD_CLR, rinfo->dp_src_fg_cache);
OUTREG(DP_SRC_BKGD_CLR, rinfo->dp_src_bg_cache);
/* set source color regs */
OUTREG(DP_SRC_FRGD_CLR, 0xffffffff);
OUTREG(DP_SRC_BKGD_CLR, 0x00000000);
/* Default direction */
rinfo->dp_cntl_cache = DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM;
radeon_fifo_wait(rinfo, 1);
OUTREG(DP_CNTL, rinfo->dp_cntl_cache);
/* default write mask */
radeon_fifo_wait(rinfo, 1);
OUTREG(DP_WRITE_MSK, 0xffffffff);
radeon_engine_idle ();
/* Default to no swapping of host data */
radeon_fifo_wait(rinfo, 1);
OUTREG(RBBM_GUICNTL, RBBM_GUICNTL_HOST_DATA_SWAP_NONE);
/* Make sure it's settled */
radeon_engine_idle(rinfo);
}

View file

@ -66,7 +66,7 @@ static int radeon_bl_update_status(struct backlight_device *bd)
level = bd->props.brightness;
del_timer_sync(&rinfo->lvds_timer);
radeon_engine_idle();
radeon_engine_idle(rinfo);
lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
if (level > 0) {

View file

@ -852,7 +852,6 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var,
if (rinfo->asleep)
return 0;
radeon_fifo_wait(2);
OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset)
* var->bits_per_pixel / 8) & ~7);
return 0;
@ -882,7 +881,6 @@ static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd,
if (rc)
return rc;
radeon_fifo_wait(2);
if (value & 0x01) {
tmp = INREG(LVDS_GEN_CNTL);
@ -940,7 +938,7 @@ int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch)
if (rinfo->lock_blank)
return 0;
radeon_engine_idle();
radeon_engine_idle(rinfo);
val = INREG(CRTC_EXT_CNTL);
val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS |
@ -1048,7 +1046,7 @@ static int radeonfb_blank (int blank, struct fb_info *info)
if (rinfo->asleep)
return 0;
return radeon_screen_blank(rinfo, blank, 0);
}
@ -1074,8 +1072,6 @@ static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green,
pindex = regno;
if (!rinfo->asleep) {
radeon_fifo_wait(9);
if (rinfo->bpp == 16) {
pindex = regno * 8;
@ -1244,8 +1240,6 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg
{
int i;
radeon_fifo_wait(20);
/* Workaround from XFree */
if (rinfo->is_mobility) {
/* A temporal workaround for the occational blanking on certain laptop
@ -1286,11 +1280,10 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg
radeon_pll_errata_after_data(rinfo);
/* Set PPLL ref. div */
if (rinfo->family == CHIP_FAMILY_R300 ||
if (IS_R300_VARIANT(rinfo) ||
rinfo->family == CHIP_FAMILY_RS300 ||
rinfo->family == CHIP_FAMILY_R350 ||
rinfo->family == CHIP_FAMILY_RV350 ||
rinfo->family == CHIP_FAMILY_RV380 ) {
rinfo->family == CHIP_FAMILY_RS400 ||
rinfo->family == CHIP_FAMILY_RS480) {
if (mode->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
/* When restoring console mode, use saved PPLL_REF_DIV
* setting.
@ -1342,7 +1335,7 @@ static void radeon_lvds_timer_func(unsigned long data)
{
struct radeonfb_info *rinfo = (struct radeonfb_info *)data;
radeon_engine_idle();
radeon_engine_idle(rinfo);
OUTREG(LVDS_GEN_CNTL, rinfo->pending_lvds_gen_cntl);
}
@ -1360,10 +1353,11 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
if (nomodeset)
return;
radeon_engine_idle(rinfo);
if (!regs_only)
radeon_screen_blank(rinfo, FB_BLANK_NORMAL, 0);
radeon_fifo_wait(31);
for (i=0; i<10; i++)
OUTREG(common_regs[i].reg, common_regs[i].val);
@ -1391,7 +1385,6 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
radeon_write_pll_regs(rinfo, mode);
if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
radeon_fifo_wait(10);
OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp);
OUTREG(FP_CRTC_V_TOTAL_DISP, mode->fp_crtc_v_total_disp);
OUTREG(FP_H_SYNC_STRT_WID, mode->fp_h_sync_strt_wid);
@ -1406,7 +1399,6 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
if (!regs_only)
radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 0);
radeon_fifo_wait(2);
OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl);
return;
@ -1461,10 +1453,7 @@ static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs
/* Not all chip revs have the same format for this register,
* extract the source selection
*/
if (rinfo->family == CHIP_FAMILY_R200 ||
rinfo->family == CHIP_FAMILY_R300 ||
rinfo->family == CHIP_FAMILY_R350 ||
rinfo->family == CHIP_FAMILY_RV350) {
if (rinfo->family == CHIP_FAMILY_R200 || IS_R300_VARIANT(rinfo)) {
source = (fp2_gen_cntl >> 10) & 0x3;
/* sourced from transform unit, check for transform unit
* own source
@ -1560,7 +1549,7 @@ static int radeonfb_set_par(struct fb_info *info)
/* We always want engine to be idle on a mode switch, even
* if we won't actually change the mode
*/
radeon_engine_idle();
radeon_engine_idle(rinfo);
hSyncStart = mode->xres + mode->right_margin;
hSyncEnd = hSyncStart + mode->hsync_len;
@ -1855,7 +1844,6 @@ static int radeonfb_set_par(struct fb_info *info)
return 0;
}
static struct fb_ops radeonfb_ops = {
.owner = THIS_MODULE,
.fb_check_var = radeonfb_check_var,
@ -1879,6 +1867,7 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo)
info->par = rinfo;
info->pseudo_palette = rinfo->pseudo_palette;
info->flags = FBINFO_DEFAULT
| FBINFO_HWACCEL_IMAGEBLIT
| FBINFO_HWACCEL_COPYAREA
| FBINFO_HWACCEL_FILLRECT
| FBINFO_HWACCEL_XPAN
@ -2005,11 +1994,11 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo)
(rinfo->family == CHIP_FAMILY_RS200) ||
(rinfo->family == CHIP_FAMILY_RS300) ||
(rinfo->family == CHIP_FAMILY_RC410) ||
(rinfo->family == CHIP_FAMILY_RS400) ||
(rinfo->family == CHIP_FAMILY_RS480) ) {
u32 tom = INREG(NB_TOM);
tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
radeon_fifo_wait(6);
OUTREG(MC_FB_LOCATION, tom);
OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);

View file

@ -139,12 +139,8 @@ void radeon_delete_i2c_busses(struct radeonfb_info *rinfo)
int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn,
u8 **out_edid)
{
u32 reg = rinfo->i2c[conn-1].ddc_reg;
u8 *edid;
OUTREG(reg, INREG(reg) &
~(VGA_DDC_DATA_OUTPUT | VGA_DDC_CLK_OUTPUT));
edid = fb_ddc_read(&rinfo->i2c[conn-1].adapter);
if (out_edid)

View file

@ -2653,9 +2653,9 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
if (!(info->flags & FBINFO_HWACCEL_DISABLED)) {
/* Make sure engine is reset */
radeon_engine_idle();
radeon_engine_idle(rinfo);
radeonfb_engine_reset(rinfo);
radeon_engine_idle();
radeon_engine_idle(rinfo);
}
/* Blank display and LCD */
@ -2767,7 +2767,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
rinfo->asleep = 0;
} else
radeon_engine_idle();
radeon_engine_idle(rinfo);
/* Restore display & engine */
radeon_write_mode (rinfo, &rinfo->state, 1);

View file

@ -53,6 +53,7 @@ enum radeon_family {
CHIP_FAMILY_RV380, /* RV370/RV380/M22/M24 */
CHIP_FAMILY_R420, /* R420/R423/M18 */
CHIP_FAMILY_RC410,
CHIP_FAMILY_RS400,
CHIP_FAMILY_RS480,
CHIP_FAMILY_LAST,
};
@ -335,7 +336,15 @@ struct radeonfb_info {
int mon2_type;
u8 *mon2_EDID;
u32 dp_gui_master_cntl;
/* accel bits */
u32 dp_gui_mc_base;
u32 dp_gui_mc_cache;
u32 dp_cntl_cache;
u32 dp_brush_fg_cache;
u32 dp_brush_bg_cache;
u32 dp_src_fg_cache;
u32 dp_src_bg_cache;
u32 fifo_free;
struct pll_info pll;
@ -347,6 +356,7 @@ struct radeonfb_info {
int lock_blank;
int dynclk;
int no_schedule;
int gfx_mode;
enum radeon_pm_mode pm_mode;
reinit_function_ptr reinit_func;
@ -391,8 +401,14 @@ static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms)
#define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr)
#define INREG16(addr) readw((rinfo->mmio_base)+addr)
#define OUTREG16(addr,val) writew(val, (rinfo->mmio_base)+addr)
#ifdef CONFIG_PPC
#define INREG(addr) ({ eieio(); ld_le32(rinfo->mmio_base+(addr)); })
#define OUTREG(addr,val) do { eieio(); st_le32(rinfo->mmio_base+(addr),(val)); } while(0)
#else
#define INREG(addr) readl((rinfo->mmio_base)+addr)
#define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr)
#endif
static inline void _OUTREGP(struct radeonfb_info *rinfo, u32 addr,
u32 val, u32 mask)
@ -533,16 +549,25 @@ static inline u32 radeon_get_dstbpp(u16 depth)
/*
* 2D Engine helper routines
*/
extern void radeon_fifo_update_and_wait(struct radeonfb_info *rinfo, int entries);
static inline void radeon_engine_flush (struct radeonfb_info *rinfo)
{
int i;
/* initiate flush */
OUTREGP(RB2D_DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
/* Initiate flush */
OUTREGP(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
~RB2D_DC_FLUSH_ALL);
/* Ensure FIFO is empty, ie, make sure the flush commands
* has reached the cache
*/
radeon_fifo_update_and_wait(rinfo, 64);
/* Wait for the flush to complete */
for (i=0; i < 2000000; i++) {
if (!(INREG(RB2D_DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
if (!(INREG(DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
return;
udelay(1);
}
@ -550,25 +575,12 @@ static inline void radeon_engine_flush (struct radeonfb_info *rinfo)
}
static inline void _radeon_fifo_wait(struct radeonfb_info *rinfo, int entries)
{
int i;
for (i=0; i<2000000; i++) {
if ((INREG(RBBM_STATUS) & 0x7f) >= entries)
return;
udelay(1);
}
printk(KERN_ERR "radeonfb: FIFO Timeout !\n");
}
static inline void _radeon_engine_idle(struct radeonfb_info *rinfo)
static inline void radeon_engine_idle(struct radeonfb_info *rinfo)
{
int i;
/* ensure FIFO is empty before waiting for idle */
_radeon_fifo_wait (rinfo, 64);
radeon_fifo_update_and_wait (rinfo, 64);
for (i=0; i<2000000; i++) {
if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) {
@ -581,8 +593,6 @@ static inline void _radeon_engine_idle(struct radeonfb_info *rinfo)
}
#define radeon_engine_idle() _radeon_engine_idle(rinfo)
#define radeon_fifo_wait(entries) _radeon_fifo_wait(rinfo,entries)
#define radeon_msleep(ms) _radeon_msleep(rinfo,ms)
@ -612,6 +622,7 @@ extern void radeonfb_imageblit(struct fb_info *p, const struct fb_image *image);
extern int radeonfb_sync(struct fb_info *info);
extern void radeonfb_engine_init (struct radeonfb_info *rinfo);
extern void radeonfb_engine_reset(struct radeonfb_info *rinfo);
extern void radeon_fixup_mem_offset(struct radeonfb_info *rinfo);
/* Other functions */
extern int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch);

View file

@ -24,6 +24,13 @@ config LCD_CLASS_DEVICE
To have support for your specific LCD panel you will have to
select the proper drivers which depend on this option.
config LCD_CORGI
tristate "LCD Panel support for SHARP corgi/spitz model"
depends on LCD_CLASS_DEVICE && SPI_MASTER && PXA_SHARPSL
help
Say y here to support the LCD panels usually found on SHARP
corgi (C7x0) and spitz (Cxx00) models.
config LCD_LTV350QV
tristate "Samsung LTV350QV LCD Panel"
depends on LCD_CLASS_DEVICE && SPI_MASTER
@ -44,6 +51,14 @@ config LCD_ILI9320
If you have a panel based on the ILI9320 controller chip
then say y to include a power driver for it.
config LCD_TDO24M
tristate "Toppoly TDO24M LCD Panels support"
depends on LCD_CLASS_DEVICE && SPI_MASTER
default n
help
If you have a Toppoly TDO24M series LCD panel, say y here to
include the support for it.
config LCD_VGG2432A4
tristate "VGG2432A4 LCM device support"
depends on BACKLIGHT_LCD_SUPPORT && LCD_CLASS_DEVICE && SPI_MASTER

View file

@ -1,10 +1,12 @@
# Backlight & LCD drivers
obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o
obj-$(CONFIG_LCD_CORGI) += corgi_lcd.o
obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o
obj-$(CONFIG_LCD_ILI9320) += ili9320.o
obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o
obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o
obj-$(CONFIG_LCD_TDO24M) += tdo24m.o
obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o

View file

@ -0,0 +1,641 @@
/*
* LCD/Backlight Driver for Sharp Zaurus Handhelds (various models)
*
* Copyright (c) 2004-2006 Richard Purdie
*
* Based on Sharp's 2.4 Backlight Driver
*
* Copyright (c) 2008 Marvell International Ltd.
* Converted to SPI device based LCD/Backlight device driver
* by Eric Miao <eric.miao@marvell.com>
*
* 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.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/fb.h>
#include <linux/lcd.h>
#include <linux/spi/spi.h>
#include <linux/spi/corgi_lcd.h>
#include <asm/mach/sharpsl_param.h>
#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
/* Register Addresses */
#define RESCTL_ADRS 0x00
#define PHACTRL_ADRS 0x01
#define DUTYCTRL_ADRS 0x02
#define POWERREG0_ADRS 0x03
#define POWERREG1_ADRS 0x04
#define GPOR3_ADRS 0x05
#define PICTRL_ADRS 0x06
#define POLCTRL_ADRS 0x07
/* Register Bit Definitions */
#define RESCTL_QVGA 0x01
#define RESCTL_VGA 0x00
#define POWER1_VW_ON 0x01 /* VW Supply FET ON */
#define POWER1_GVSS_ON 0x02 /* GVSS(-8V) Power Supply ON */
#define POWER1_VDD_ON 0x04 /* VDD(8V),SVSS(-4V) Power Supply ON */
#define POWER1_VW_OFF 0x00 /* VW Supply FET OFF */
#define POWER1_GVSS_OFF 0x00 /* GVSS(-8V) Power Supply OFF */
#define POWER1_VDD_OFF 0x00 /* VDD(8V),SVSS(-4V) Power Supply OFF */
#define POWER0_COM_DCLK 0x01 /* COM Voltage DC Bias DAC Serial Data Clock */
#define POWER0_COM_DOUT 0x02 /* COM Voltage DC Bias DAC Serial Data Out */
#define POWER0_DAC_ON 0x04 /* DAC Power Supply ON */
#define POWER0_COM_ON 0x08 /* COM Power Supply ON */
#define POWER0_VCC5_ON 0x10 /* VCC5 Power Supply ON */
#define POWER0_DAC_OFF 0x00 /* DAC Power Supply OFF */
#define POWER0_COM_OFF 0x00 /* COM Power Supply OFF */
#define POWER0_VCC5_OFF 0x00 /* VCC5 Power Supply OFF */
#define PICTRL_INIT_STATE 0x01
#define PICTRL_INIOFF 0x02
#define PICTRL_POWER_DOWN 0x04
#define PICTRL_COM_SIGNAL_OFF 0x08
#define PICTRL_DAC_SIGNAL_OFF 0x10
#define POLCTRL_SYNC_POL_FALL 0x01
#define POLCTRL_EN_POL_FALL 0x02
#define POLCTRL_DATA_POL_FALL 0x04
#define POLCTRL_SYNC_ACT_H 0x08
#define POLCTRL_EN_ACT_L 0x10
#define POLCTRL_SYNC_POL_RISE 0x00
#define POLCTRL_EN_POL_RISE 0x00
#define POLCTRL_DATA_POL_RISE 0x00
#define POLCTRL_SYNC_ACT_L 0x00
#define POLCTRL_EN_ACT_H 0x00
#define PHACTRL_PHASE_MANUAL 0x01
#define DEFAULT_PHAD_QVGA (9)
#define DEFAULT_COMADJ (125)
struct corgi_lcd {
struct spi_device *spi_dev;
struct lcd_device *lcd_dev;
struct backlight_device *bl_dev;
int limit_mask;
int intensity;
int power;
int mode;
char buf[2];
int gpio_backlight_on;
int gpio_backlight_cont;
int gpio_backlight_cont_inverted;
void (*kick_battery)(void);
};
static int corgi_ssp_lcdtg_send(struct corgi_lcd *lcd, int reg, uint8_t val);
static struct corgi_lcd *the_corgi_lcd;
static unsigned long corgibl_flags;
#define CORGIBL_SUSPENDED 0x01
#define CORGIBL_BATTLOW 0x02
/*
* This is only a psuedo I2C interface. We can't use the standard kernel
* routines as the interface is write only. We just assume the data is acked...
*/
static void lcdtg_ssp_i2c_send(struct corgi_lcd *lcd, uint8_t data)
{
corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS, data);
udelay(10);
}
static void lcdtg_i2c_send_bit(struct corgi_lcd *lcd, uint8_t data)
{
lcdtg_ssp_i2c_send(lcd, data);
lcdtg_ssp_i2c_send(lcd, data | POWER0_COM_DCLK);
lcdtg_ssp_i2c_send(lcd, data);
}
static void lcdtg_i2c_send_start(struct corgi_lcd *lcd, uint8_t base)
{
lcdtg_ssp_i2c_send(lcd, base | POWER0_COM_DCLK | POWER0_COM_DOUT);
lcdtg_ssp_i2c_send(lcd, base | POWER0_COM_DCLK);
lcdtg_ssp_i2c_send(lcd, base);
}
static void lcdtg_i2c_send_stop(struct corgi_lcd *lcd, uint8_t base)
{
lcdtg_ssp_i2c_send(lcd, base);
lcdtg_ssp_i2c_send(lcd, base | POWER0_COM_DCLK);
lcdtg_ssp_i2c_send(lcd, base | POWER0_COM_DCLK | POWER0_COM_DOUT);
}
static void lcdtg_i2c_send_byte(struct corgi_lcd *lcd,
uint8_t base, uint8_t data)
{
int i;
for (i = 0; i < 8; i++) {
if (data & 0x80)
lcdtg_i2c_send_bit(lcd, base | POWER0_COM_DOUT);
else
lcdtg_i2c_send_bit(lcd, base);
data <<= 1;
}
}
static void lcdtg_i2c_wait_ack(struct corgi_lcd *lcd, uint8_t base)
{
lcdtg_i2c_send_bit(lcd, base);
}
static void lcdtg_set_common_voltage(struct corgi_lcd *lcd,
uint8_t base_data, uint8_t data)
{
/* Set Common Voltage to M62332FP via I2C */
lcdtg_i2c_send_start(lcd, base_data);
lcdtg_i2c_send_byte(lcd, base_data, 0x9c);
lcdtg_i2c_wait_ack(lcd, base_data);
lcdtg_i2c_send_byte(lcd, base_data, 0x00);
lcdtg_i2c_wait_ack(lcd, base_data);
lcdtg_i2c_send_byte(lcd, base_data, data);
lcdtg_i2c_wait_ack(lcd, base_data);
lcdtg_i2c_send_stop(lcd, base_data);
}
static int corgi_ssp_lcdtg_send(struct corgi_lcd *lcd, int adrs, uint8_t data)
{
struct spi_message msg;
struct spi_transfer xfer = {
.len = 1,
.cs_change = 1,
.tx_buf = lcd->buf,
};
lcd->buf[0] = ((adrs & 0x07) << 5) | (data & 0x1f);
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
return spi_sync(lcd->spi_dev, &msg);
}
/* Set Phase Adjust */
static void lcdtg_set_phadadj(struct corgi_lcd *lcd, int mode)
{
int adj;
switch(mode) {
case CORGI_LCD_MODE_VGA:
/* Setting for VGA */
adj = sharpsl_param.phadadj;
adj = (adj < 0) ? PHACTRL_PHASE_MANUAL :
PHACTRL_PHASE_MANUAL | ((adj & 0xf) << 1);
break;
case CORGI_LCD_MODE_QVGA:
default:
/* Setting for QVGA */
adj = (DEFAULT_PHAD_QVGA << 1) | PHACTRL_PHASE_MANUAL;
break;
}
corgi_ssp_lcdtg_send(lcd, PHACTRL_ADRS, adj);
}
static void corgi_lcd_power_on(struct corgi_lcd *lcd)
{
int comadj;
/* Initialize Internal Logic & Port */
corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS,
PICTRL_POWER_DOWN | PICTRL_INIOFF |
PICTRL_INIT_STATE | PICTRL_COM_SIGNAL_OFF |
PICTRL_DAC_SIGNAL_OFF);
corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS,
POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_OFF |
POWER0_COM_OFF | POWER0_VCC5_OFF);
corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS,
POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF);
/* VDD(+8V), SVSS(-4V) ON */
corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS,
POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON);
mdelay(3);
/* DAC ON */
corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS,
POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON |
POWER0_COM_OFF | POWER0_VCC5_OFF);
/* INIB = H, INI = L */
/* PICTL[0] = H , PICTL[1] = PICTL[2] = PICTL[4] = L */
corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS,
PICTRL_INIT_STATE | PICTRL_COM_SIGNAL_OFF);
/* Set Common Voltage */
comadj = sharpsl_param.comadj;
if (comadj < 0)
comadj = DEFAULT_COMADJ;
lcdtg_set_common_voltage(lcd, POWER0_DAC_ON | POWER0_COM_OFF |
POWER0_VCC5_OFF, comadj);
/* VCC5 ON, DAC ON */
corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS,
POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON |
POWER0_COM_OFF | POWER0_VCC5_ON);
/* GVSS(-8V) ON, VDD ON */
corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS,
POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON);
mdelay(2);
/* COM SIGNAL ON (PICTL[3] = L) */
corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS, PICTRL_INIT_STATE);
/* COM ON, DAC ON, VCC5_ON */
corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS,
POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON |
POWER0_COM_ON | POWER0_VCC5_ON);
/* VW ON, GVSS ON, VDD ON */
corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS,
POWER1_VW_ON | POWER1_GVSS_ON | POWER1_VDD_ON);
/* Signals output enable */
corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS, 0);
/* Set Phase Adjust */
lcdtg_set_phadadj(lcd, lcd->mode);
/* Initialize for Input Signals from ATI */
corgi_ssp_lcdtg_send(lcd, POLCTRL_ADRS,
POLCTRL_SYNC_POL_RISE | POLCTRL_EN_POL_RISE |
POLCTRL_DATA_POL_RISE | POLCTRL_SYNC_ACT_L |
POLCTRL_EN_ACT_H);
udelay(1000);
switch (lcd->mode) {
case CORGI_LCD_MODE_VGA:
corgi_ssp_lcdtg_send(lcd, RESCTL_ADRS, RESCTL_VGA);
break;
case CORGI_LCD_MODE_QVGA:
default:
corgi_ssp_lcdtg_send(lcd, RESCTL_ADRS, RESCTL_QVGA);
break;
}
}
static void corgi_lcd_power_off(struct corgi_lcd *lcd)
{
/* 60Hz x 2 frame = 16.7msec x 2 = 33.4 msec */
msleep(34);
/* (1)VW OFF */
corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS,
POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON);
/* (2)COM OFF */
corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS, PICTRL_COM_SIGNAL_OFF);
corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS,
POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON);
/* (3)Set Common Voltage Bias 0V */
lcdtg_set_common_voltage(lcd, POWER0_DAC_ON | POWER0_COM_OFF |
POWER0_VCC5_ON, 0);
/* (4)GVSS OFF */
corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS,
POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON);
/* (5)VCC5 OFF */
corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS,
POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF);
/* (6)Set PDWN, INIOFF, DACOFF */
corgi_ssp_lcdtg_send(lcd, PICTRL_ADRS,
PICTRL_INIOFF | PICTRL_DAC_SIGNAL_OFF |
PICTRL_POWER_DOWN | PICTRL_COM_SIGNAL_OFF);
/* (7)DAC OFF */
corgi_ssp_lcdtg_send(lcd, POWERREG0_ADRS,
POWER0_DAC_OFF | POWER0_COM_OFF | POWER0_VCC5_OFF);
/* (8)VDD OFF */
corgi_ssp_lcdtg_send(lcd, POWERREG1_ADRS,
POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF);
}
static int corgi_lcd_set_mode(struct lcd_device *ld, struct fb_videomode *m)
{
struct corgi_lcd *lcd = dev_get_drvdata(&ld->dev);
int mode = CORGI_LCD_MODE_QVGA;
if (m->xres == 640 || m->xres == 480)
mode = CORGI_LCD_MODE_VGA;
if (lcd->mode == mode)
return 0;
lcdtg_set_phadadj(lcd, mode);
switch (mode) {
case CORGI_LCD_MODE_VGA:
corgi_ssp_lcdtg_send(lcd, RESCTL_ADRS, RESCTL_VGA);
break;
case CORGI_LCD_MODE_QVGA:
default:
corgi_ssp_lcdtg_send(lcd, RESCTL_ADRS, RESCTL_QVGA);
break;
}
lcd->mode = mode;
return 0;
}
static int corgi_lcd_set_power(struct lcd_device *ld, int power)
{
struct corgi_lcd *lcd = dev_get_drvdata(&ld->dev);
if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power))
corgi_lcd_power_on(lcd);
if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power))
corgi_lcd_power_off(lcd);
lcd->power = power;
return 0;
}
static int corgi_lcd_get_power(struct lcd_device *ld)
{
struct corgi_lcd *lcd = dev_get_drvdata(&ld->dev);
return lcd->power;
}
static struct lcd_ops corgi_lcd_ops = {
.get_power = corgi_lcd_get_power,
.set_power = corgi_lcd_set_power,
.set_mode = corgi_lcd_set_mode,
};
static int corgi_bl_get_intensity(struct backlight_device *bd)
{
struct corgi_lcd *lcd = dev_get_drvdata(&bd->dev);
return lcd->intensity;
}
static int corgi_bl_set_intensity(struct corgi_lcd *lcd, int intensity)
{
int cont;
if (intensity > 0x10)
intensity += 0x10;
corgi_ssp_lcdtg_send(lcd, DUTYCTRL_ADRS, intensity);
/* Bit 5 via GPIO_BACKLIGHT_CONT */
cont = !!(intensity & 0x20) ^ lcd->gpio_backlight_cont_inverted;
if (gpio_is_valid(lcd->gpio_backlight_cont))
gpio_set_value(lcd->gpio_backlight_cont, cont);
if (gpio_is_valid(lcd->gpio_backlight_on))
gpio_set_value(lcd->gpio_backlight_on, intensity);
if (lcd->kick_battery)
lcd->kick_battery();
lcd->intensity = intensity;
return 0;
}
static int corgi_bl_update_status(struct backlight_device *bd)
{
struct corgi_lcd *lcd = dev_get_drvdata(&bd->dev);
int intensity = bd->props.brightness;
if (bd->props.power != FB_BLANK_UNBLANK)
intensity = 0;
if (bd->props.fb_blank != FB_BLANK_UNBLANK)
intensity = 0;
if (corgibl_flags & CORGIBL_SUSPENDED)
intensity = 0;
if (corgibl_flags & CORGIBL_BATTLOW)
intensity &= lcd->limit_mask;
return corgi_bl_set_intensity(lcd, intensity);
}
void corgibl_limit_intensity(int limit)
{
if (limit)
corgibl_flags |= CORGIBL_BATTLOW;
else
corgibl_flags &= ~CORGIBL_BATTLOW;
backlight_update_status(the_corgi_lcd->bl_dev);
}
EXPORT_SYMBOL(corgibl_limit_intensity);
static struct backlight_ops corgi_bl_ops = {
.get_brightness = corgi_bl_get_intensity,
.update_status = corgi_bl_update_status,
};
#ifdef CONFIG_PM
static int corgi_lcd_suspend(struct spi_device *spi, pm_message_t state)
{
struct corgi_lcd *lcd = dev_get_drvdata(&spi->dev);
corgibl_flags |= CORGIBL_SUSPENDED;
corgi_bl_set_intensity(lcd, 0);
corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_POWERDOWN);
return 0;
}
static int corgi_lcd_resume(struct spi_device *spi)
{
struct corgi_lcd *lcd = dev_get_drvdata(&spi->dev);
corgibl_flags &= ~CORGIBL_SUSPENDED;
corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_UNBLANK);
backlight_update_status(lcd->bl_dev);
return 0;
}
#else
#define corgi_lcd_suspend NULL
#define corgi_lcd_resume NULL
#endif
static int setup_gpio_backlight(struct corgi_lcd *lcd,
struct corgi_lcd_platform_data *pdata)
{
struct spi_device *spi = lcd->spi_dev;
int err;
lcd->gpio_backlight_on = -1;
lcd->gpio_backlight_cont = -1;
if (gpio_is_valid(pdata->gpio_backlight_on)) {
err = gpio_request(pdata->gpio_backlight_on, "BL_ON");
if (err) {
dev_err(&spi->dev, "failed to request GPIO%d for "
"backlight_on\n", pdata->gpio_backlight_on);
return err;
}
lcd->gpio_backlight_on = pdata->gpio_backlight_on;
gpio_direction_output(lcd->gpio_backlight_on, 0);
}
if (gpio_is_valid(pdata->gpio_backlight_cont)) {
err = gpio_request(pdata->gpio_backlight_cont, "BL_CONT");
if (err) {
dev_err(&spi->dev, "failed to request GPIO%d for "
"backlight_cont\n", pdata->gpio_backlight_cont);
goto err_free_backlight_on;
}
lcd->gpio_backlight_cont = pdata->gpio_backlight_cont;
/* spitz and akita use both GPIOs for backlight, and
* have inverted polarity of GPIO_BACKLIGHT_CONT
*/
if (gpio_is_valid(lcd->gpio_backlight_on)) {
lcd->gpio_backlight_cont_inverted = 1;
gpio_direction_output(lcd->gpio_backlight_cont, 1);
} else {
lcd->gpio_backlight_cont_inverted = 0;
gpio_direction_output(lcd->gpio_backlight_cont, 0);
}
}
return 0;
err_free_backlight_on:
if (gpio_is_valid(lcd->gpio_backlight_on))
gpio_free(lcd->gpio_backlight_on);
return err;
}
static int __devinit corgi_lcd_probe(struct spi_device *spi)
{
struct corgi_lcd_platform_data *pdata = spi->dev.platform_data;
struct corgi_lcd *lcd;
int ret = 0;
if (pdata == NULL) {
dev_err(&spi->dev, "platform data not available\n");
return -EINVAL;
}
lcd = kzalloc(sizeof(struct corgi_lcd), GFP_KERNEL);
if (!lcd) {
dev_err(&spi->dev, "failed to allocate memory\n");
return -ENOMEM;
}
lcd->spi_dev = spi;
lcd->lcd_dev = lcd_device_register("corgi_lcd", &spi->dev,
lcd, &corgi_lcd_ops);
if (IS_ERR(lcd->lcd_dev)) {
ret = PTR_ERR(lcd->lcd_dev);
goto err_free_lcd;
}
lcd->power = FB_BLANK_POWERDOWN;
lcd->mode = (pdata) ? pdata->init_mode : CORGI_LCD_MODE_VGA;
lcd->bl_dev = backlight_device_register("corgi_bl", &spi->dev,
lcd, &corgi_bl_ops);
if (IS_ERR(lcd->bl_dev)) {
ret = PTR_ERR(lcd->bl_dev);
goto err_unregister_lcd;
}
lcd->bl_dev->props.max_brightness = pdata->max_intensity;
lcd->bl_dev->props.brightness = pdata->default_intensity;
lcd->bl_dev->props.power = FB_BLANK_UNBLANK;
ret = setup_gpio_backlight(lcd, pdata);
if (ret)
goto err_unregister_bl;
lcd->kick_battery = pdata->kick_battery;
dev_set_drvdata(&spi->dev, lcd);
corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_UNBLANK);
backlight_update_status(lcd->bl_dev);
lcd->limit_mask = pdata->limit_mask;
the_corgi_lcd = lcd;
return 0;
err_unregister_bl:
backlight_device_unregister(lcd->bl_dev);
err_unregister_lcd:
lcd_device_unregister(lcd->lcd_dev);
err_free_lcd:
kfree(lcd);
return ret;
}
static int __devexit corgi_lcd_remove(struct spi_device *spi)
{
struct corgi_lcd *lcd = dev_get_drvdata(&spi->dev);
lcd->bl_dev->props.power = FB_BLANK_UNBLANK;
lcd->bl_dev->props.brightness = 0;
backlight_update_status(lcd->bl_dev);
backlight_device_unregister(lcd->bl_dev);
if (gpio_is_valid(lcd->gpio_backlight_on))
gpio_free(lcd->gpio_backlight_on);
if (gpio_is_valid(lcd->gpio_backlight_cont))
gpio_free(lcd->gpio_backlight_cont);
corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_POWERDOWN);
lcd_device_unregister(lcd->lcd_dev);
kfree(lcd);
return 0;
}
static struct spi_driver corgi_lcd_driver = {
.driver = {
.name = "corgi-lcd",
.owner = THIS_MODULE,
},
.probe = corgi_lcd_probe,
.remove = __devexit_p(corgi_lcd_remove),
.suspend = corgi_lcd_suspend,
.resume = corgi_lcd_resume,
};
static int __init corgi_lcd_init(void)
{
return spi_register_driver(&corgi_lcd_driver);
}
module_init(corgi_lcd_init);
static void __exit corgi_lcd_exit(void)
{
spi_unregister_driver(&corgi_lcd_driver);
}
module_exit(corgi_lcd_exit);
MODULE_DESCRIPTION("LCD and backlight driver for SHARP C7x0/Cxx00");
MODULE_AUTHOR("Eric Miao <[email protected]>");
MODULE_LICENSE("GPL");

View file

@ -27,14 +27,26 @@ static int fb_notifier_callback(struct notifier_block *self,
struct fb_event *evdata = data;
/* If we aren't interested in this event, skip it immediately ... */
if (event != FB_EVENT_BLANK)
switch (event) {
case FB_EVENT_BLANK:
case FB_EVENT_MODE_CHANGE:
case FB_EVENT_MODE_CHANGE_ALL:
break;
default:
return 0;
}
ld = container_of(self, struct lcd_device, fb_notif);
if (!ld->ops)
return 0;
mutex_lock(&ld->ops_lock);
if (ld->ops)
if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info))
if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info)) {
if (event == FB_EVENT_BLANK)
ld->ops->set_power(ld, *(int *)evdata->data);
else
ld->ops->set_mode(ld, evdata->data);
}
mutex_unlock(&ld->ops_lock);
return 0;
}

View file

@ -111,6 +111,4 @@ module_exit(mbp_exit);
MODULE_AUTHOR("Matthew Garrett <[email protected]>");
MODULE_DESCRIPTION("Nvidia-based Macbook Pro Backlight Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("svnAppleInc.:pnMacBookPro3,1");
MODULE_ALIAS("svnAppleInc.:pnMacBookPro3,2");
MODULE_ALIAS("svnAppleInc.:pnMacBookPro4,1");
MODULE_DEVICE_TABLE(dmi, mbp_device_table);

View file

@ -0,0 +1,396 @@
/*
* tdo24m - SPI-based drivers for Toppoly TDO24M series LCD panels
*
* Copyright (C) 2008 Marvell International Ltd.
* Eric Miao <eric.miao@marvell.com>
*
* 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
* publishhed by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/spi/spi.h>
#include <linux/fb.h>
#include <linux/lcd.h>
#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
#define TDO24M_SPI_BUFF_SIZE (4)
#define MODE_QVGA 0
#define MODE_VGA 1
struct tdo24m {
struct spi_device *spi_dev;
struct lcd_device *lcd_dev;
struct spi_message msg;
struct spi_transfer xfer;
uint8_t *buf;
int power;
int mode;
};
/* use bit 30, 31 as the indicator of command parameter number */
#define CMD0(x) ((0 << 30) | (x))
#define CMD1(x, x1) ((1 << 30) | ((x) << 9) | 0x100 | (x1))
#define CMD2(x, x1, x2) ((2 << 30) | ((x) << 18) | 0x20000 |\
((x1) << 9) | 0x100 | (x2))
#define CMD_NULL (-1)
static uint32_t lcd_panel_reset[] = {
CMD0(0x1), /* reset */
CMD0(0x0), /* nop */
CMD0(0x0), /* nop */
CMD0(0x0), /* nop */
CMD_NULL,
};
static uint32_t lcd_panel_on[] = {
CMD0(0x29), /* Display ON */
CMD2(0xB8, 0xFF, 0xF9), /* Output Control */
CMD0(0x11), /* Sleep out */
CMD1(0xB0, 0x16), /* Wake */
CMD_NULL,
};
static uint32_t lcd_panel_off[] = {
CMD0(0x28), /* Display OFF */
CMD2(0xB8, 0x80, 0x02), /* Output Control */
CMD0(0x10), /* Sleep in */
CMD1(0xB0, 0x00), /* Deep stand by in */
CMD_NULL,
};
static uint32_t lcd_vga_pass_through[] = {
CMD1(0xB0, 0x16),
CMD1(0xBC, 0x80),
CMD1(0xE1, 0x00),
CMD1(0x36, 0x50),
CMD1(0x3B, 0x00),
CMD_NULL,
};
static uint32_t lcd_qvga_pass_through[] = {
CMD1(0xB0, 0x16),
CMD1(0xBC, 0x81),
CMD1(0xE1, 0x00),
CMD1(0x36, 0x50),
CMD1(0x3B, 0x22),
CMD_NULL,
};
static uint32_t lcd_vga_transfer[] = {
CMD1(0xcf, 0x02), /* Blanking period control (1) */
CMD2(0xd0, 0x08, 0x04), /* Blanking period control (2) */
CMD1(0xd1, 0x01), /* CKV timing control on/off */
CMD2(0xd2, 0x14, 0x00), /* CKV 1,2 timing control */
CMD2(0xd3, 0x1a, 0x0f), /* OEV timing control */
CMD2(0xd4, 0x1f, 0xaf), /* ASW timing control (1) */
CMD1(0xd5, 0x14), /* ASW timing control (2) */
CMD0(0x21), /* Invert for normally black display */
CMD0(0x29), /* Display on */
CMD_NULL,
};
static uint32_t lcd_qvga_transfer[] = {
CMD1(0xd6, 0x02), /* Blanking period control (1) */
CMD2(0xd7, 0x08, 0x04), /* Blanking period control (2) */
CMD1(0xd8, 0x01), /* CKV timing control on/off */
CMD2(0xd9, 0x00, 0x08), /* CKV 1,2 timing control */
CMD2(0xde, 0x05, 0x0a), /* OEV timing control */
CMD2(0xdf, 0x0a, 0x19), /* ASW timing control (1) */
CMD1(0xe0, 0x0a), /* ASW timing control (2) */
CMD0(0x21), /* Invert for normally black display */
CMD0(0x29), /* Display on */
CMD_NULL,
};
static uint32_t lcd_panel_config[] = {
CMD2(0xb8, 0xff, 0xf9), /* Output control */
CMD0(0x11), /* sleep out */
CMD1(0xba, 0x01), /* Display mode (1) */
CMD1(0xbb, 0x00), /* Display mode (2) */
CMD1(0x3a, 0x60), /* Display mode 18-bit RGB */
CMD1(0xbf, 0x10), /* Drive system change control */
CMD1(0xb1, 0x56), /* Booster operation setup */
CMD1(0xb2, 0x33), /* Booster mode setup */
CMD1(0xb3, 0x11), /* Booster frequency setup */
CMD1(0xb4, 0x02), /* Op amp/system clock */
CMD1(0xb5, 0x35), /* VCS voltage */
CMD1(0xb6, 0x40), /* VCOM voltage */
CMD1(0xb7, 0x03), /* External display signal */
CMD1(0xbd, 0x00), /* ASW slew rate */
CMD1(0xbe, 0x00), /* Dummy data for QuadData operation */
CMD1(0xc0, 0x11), /* Sleep out FR count (A) */
CMD1(0xc1, 0x11), /* Sleep out FR count (B) */
CMD1(0xc2, 0x11), /* Sleep out FR count (C) */
CMD2(0xc3, 0x20, 0x40), /* Sleep out FR count (D) */
CMD2(0xc4, 0x60, 0xc0), /* Sleep out FR count (E) */
CMD2(0xc5, 0x10, 0x20), /* Sleep out FR count (F) */
CMD1(0xc6, 0xc0), /* Sleep out FR count (G) */
CMD2(0xc7, 0x33, 0x43), /* Gamma 1 fine tuning (1) */
CMD1(0xc8, 0x44), /* Gamma 1 fine tuning (2) */
CMD1(0xc9, 0x33), /* Gamma 1 inclination adjustment */
CMD1(0xca, 0x00), /* Gamma 1 blue offset adjustment */
CMD2(0xec, 0x01, 0xf0), /* Horizontal clock cycles */
CMD_NULL,
};
static int tdo24m_writes(struct tdo24m *lcd, uint32_t *array)
{
struct spi_transfer *x = &lcd->xfer;
uint32_t data, *p = array;
int nparams, err = 0;
for (; *p != CMD_NULL; p++) {
nparams = (*p >> 30) & 0x3;
data = *p << (7 - nparams);
switch (nparams) {
case 0:
lcd->buf[0] = (data >> 8) & 0xff;
lcd->buf[1] = data & 0xff;
break;
case 1:
lcd->buf[0] = (data >> 16) & 0xff;
lcd->buf[1] = (data >> 8) & 0xff;
lcd->buf[2] = data & 0xff;
break;
case 2:
lcd->buf[0] = (data >> 24) & 0xff;
lcd->buf[1] = (data >> 16) & 0xff;
lcd->buf[2] = (data >> 8) & 0xff;
lcd->buf[3] = data & 0xff;
break;
default:
continue;
}
x->len = nparams + 2;
err = spi_sync(lcd->spi_dev, &lcd->msg);
if (err)
break;
}
return err;
}
static int tdo24m_adj_mode(struct tdo24m *lcd, int mode)
{
switch (mode) {
case MODE_VGA:
tdo24m_writes(lcd, lcd_vga_pass_through);
tdo24m_writes(lcd, lcd_panel_config);
tdo24m_writes(lcd, lcd_vga_transfer);
break;
case MODE_QVGA:
tdo24m_writes(lcd, lcd_qvga_pass_through);
tdo24m_writes(lcd, lcd_panel_config);
tdo24m_writes(lcd, lcd_qvga_transfer);
break;
default:
return -EINVAL;
}
lcd->mode = mode;
return 0;
}
static int tdo24m_power_on(struct tdo24m *lcd)
{
int err;
err = tdo24m_writes(lcd, lcd_panel_on);
if (err)
goto out;
err = tdo24m_writes(lcd, lcd_panel_reset);
if (err)
goto out;
err = tdo24m_adj_mode(lcd, lcd->mode);
out:
return err;
}
static int tdo24m_power_off(struct tdo24m *lcd)
{
return tdo24m_writes(lcd, lcd_panel_off);
}
static int tdo24m_power(struct tdo24m *lcd, int power)
{
int ret = 0;
if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power))
ret = tdo24m_power_on(lcd);
else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power))
ret = tdo24m_power_off(lcd);
if (!ret)
lcd->power = power;
return ret;
}
static int tdo24m_set_power(struct lcd_device *ld, int power)
{
struct tdo24m *lcd = lcd_get_data(ld);
return tdo24m_power(lcd, power);
}
static int tdo24m_get_power(struct lcd_device *ld)
{
struct tdo24m *lcd = lcd_get_data(ld);
return lcd->power;
}
static int tdo24m_set_mode(struct lcd_device *ld, struct fb_videomode *m)
{
struct tdo24m *lcd = lcd_get_data(ld);
int mode = MODE_QVGA;
if (m->xres == 640 || m->xres == 480)
mode = MODE_VGA;
if (lcd->mode == mode)
return 0;
return tdo24m_adj_mode(lcd, mode);
}
static struct lcd_ops tdo24m_ops = {
.get_power = tdo24m_get_power,
.set_power = tdo24m_set_power,
.set_mode = tdo24m_set_mode,
};
static int __devinit tdo24m_probe(struct spi_device *spi)
{
struct tdo24m *lcd;
struct spi_message *m;
struct spi_transfer *x;
int err;
spi->bits_per_word = 8;
spi->mode = SPI_MODE_3;
err = spi_setup(spi);
if (err)
return err;
lcd = kzalloc(sizeof(struct tdo24m), GFP_KERNEL);
if (!lcd)
return -ENOMEM;
lcd->spi_dev = spi;
lcd->power = FB_BLANK_POWERDOWN;
lcd->mode = MODE_VGA; /* default to VGA */
lcd->buf = kmalloc(TDO24M_SPI_BUFF_SIZE, sizeof(GFP_KERNEL));
if (lcd->buf == NULL) {
kfree(lcd);
return -ENOMEM;
}
m = &lcd->msg;
x = &lcd->xfer;
spi_message_init(m);
x->tx_buf = &lcd->buf[0];
spi_message_add_tail(x, m);
lcd->lcd_dev = lcd_device_register("tdo24m", &spi->dev,
lcd, &tdo24m_ops);
if (IS_ERR(lcd->lcd_dev)) {
err = PTR_ERR(lcd->lcd_dev);
goto out_free;
}
dev_set_drvdata(&spi->dev, lcd);
err = tdo24m_power(lcd, FB_BLANK_UNBLANK);
if (err)
goto out_unregister;
return 0;
out_unregister:
lcd_device_unregister(lcd->lcd_dev);
out_free:
kfree(lcd->buf);
kfree(lcd);
return err;
}
static int __devexit tdo24m_remove(struct spi_device *spi)
{
struct tdo24m *lcd = dev_get_drvdata(&spi->dev);
tdo24m_power(lcd, FB_BLANK_POWERDOWN);
lcd_device_unregister(lcd->lcd_dev);
kfree(lcd->buf);
kfree(lcd);
return 0;
}
#ifdef CONFIG_PM
static int tdo24m_suspend(struct spi_device *spi, pm_message_t state)
{
struct tdo24m *lcd = dev_get_drvdata(&spi->dev);
return tdo24m_power(lcd, FB_BLANK_POWERDOWN);
}
static int tdo24m_resume(struct spi_device *spi)
{
struct tdo24m *lcd = dev_get_drvdata(&spi->dev);
return tdo24m_power(lcd, FB_BLANK_UNBLANK);
}
#else
#define tdo24m_suspend NULL
#define tdo24m_resume NULL
#endif
/* Power down all displays on reboot, poweroff or halt */
static void tdo24m_shutdown(struct spi_device *spi)
{
struct tdo24m *lcd = dev_get_drvdata(&spi->dev);
tdo24m_power(lcd, FB_BLANK_POWERDOWN);
}
static struct spi_driver tdo24m_driver = {
.driver = {
.name = "tdo24m",
.owner = THIS_MODULE,
},
.probe = tdo24m_probe,
.remove = __devexit_p(tdo24m_remove),
.shutdown = tdo24m_shutdown,
.suspend = tdo24m_suspend,
.resume = tdo24m_resume,
};
static int __init tdo24m_init(void)
{
return spi_register_driver(&tdo24m_driver);
}
module_init(tdo24m_init);
static void __exit tdo24m_exit(void)
{
spi_unregister_driver(&tdo24m_driver);
}
module_exit(tdo24m_exit);
MODULE_AUTHOR("Eric Miao <[email protected]>");
MODULE_DESCRIPTION("Driver for Toppoly TDO24M LCD Panel");
MODULE_LICENSE("GPL");

View file

@ -372,7 +372,7 @@ static int __devexit bw2_remove(struct of_device *op)
return 0;
}
static struct of_device_id bw2_match[] = {
static const struct of_device_id bw2_match[] = {
{
.name = "bwtwo",
},

View file

@ -535,7 +535,7 @@ static struct fb_ops carminefb_ops = {
.fb_setcolreg = carmine_setcolreg,
};
static int alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base,
static int __devinit alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base,
int smem_offset, struct device *device, struct fb_info **rinfo)
{
int ret;

View file

@ -589,7 +589,7 @@ static int __devexit cg14_remove(struct of_device *op)
return 0;
}
static struct of_device_id cg14_match[] = {
static const struct of_device_id cg14_match[] = {
{
.name = "cgfourteen",
},

View file

@ -456,7 +456,7 @@ static int __devexit cg3_remove(struct of_device *op)
return 0;
}
static struct of_device_id cg3_match[] = {
static const struct of_device_id cg3_match[] = {
{
.name = "cgthree",
},

View file

@ -34,10 +34,11 @@ static int cg6_blank(int, struct fb_info *);
static void cg6_imageblit(struct fb_info *, const struct fb_image *);
static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *);
static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area);
static int cg6_sync(struct fb_info *);
static int cg6_mmap(struct fb_info *, struct vm_area_struct *);
static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long);
static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area);
static int cg6_pan_display(struct fb_var_screeninfo *, struct fb_info *);
/*
* Frame buffer operations
@ -47,6 +48,7 @@ static struct fb_ops cg6_ops = {
.owner = THIS_MODULE,
.fb_setcolreg = cg6_setcolreg,
.fb_blank = cg6_blank,
.fb_pan_display = cg6_pan_display,
.fb_fillrect = cg6_fillrect,
.fb_copyarea = cg6_copyarea,
.fb_imageblit = cg6_imageblit,
@ -161,6 +163,7 @@ static struct fb_ops cg6_ops = {
#define CG6_THC_MISC_INT_ENAB (1 << 5)
#define CG6_THC_MISC_INT (1 << 4)
#define CG6_THC_MISC_INIT 0x9f
#define CG6_THC_CURSOFF ((65536-32) | ((65536-32) << 16))
/* The contents are unknown */
struct cg6_tec {
@ -280,6 +283,33 @@ static int cg6_sync(struct fb_info *info)
return 0;
}
static void cg6_switch_from_graph(struct cg6_par *par)
{
struct cg6_thc __iomem *thc = par->thc;
unsigned long flags;
spin_lock_irqsave(&par->lock, flags);
/* Hide the cursor. */
sbus_writel(CG6_THC_CURSOFF, &thc->thc_cursxy);
spin_unlock_irqrestore(&par->lock, flags);
}
static int cg6_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct cg6_par *par = (struct cg6_par *)info->par;
/* We just use this to catch switches out of
* graphics mode.
*/
cg6_switch_from_graph(par);
if (var->xoffset || var->yoffset || var->vmode)
return -EINVAL;
return 0;
}
/**
* cg6_fillrect - Draws a rectangle on the screen.
*
@ -643,9 +673,13 @@ static void __devinit cg6_chip_init(struct fb_info *info)
struct cg6_par *par = (struct cg6_par *)info->par;
struct cg6_tec __iomem *tec = par->tec;
struct cg6_fbc __iomem *fbc = par->fbc;
struct cg6_thc __iomem *thc = par->thc;
u32 rev, conf, mode;
int i;
/* Hide the cursor. */
sbus_writel(CG6_THC_CURSOFF, &thc->thc_cursxy);
/* Turn off stuff in the Transform Engine. */
sbus_writel(0, &tec->tec_matrix);
sbus_writel(0, &tec->tec_clip);
@ -814,7 +848,7 @@ static int __devexit cg6_remove(struct of_device *op)
return 0;
}
static struct of_device_id cg6_match[] = {
static const struct of_device_id cg6_match[] = {
{
.name = "cgsix",
},

View file

@ -327,29 +327,7 @@ static const struct {
#endif /* CONFIG_ZORRO */
struct cirrusfb_regs {
long freq;
long nom;
long den;
long div;
long multiplexing;
long mclk;
long divMCLK;
long HorizRes; /* The x resolution in pixel */
long HorizTotal;
long HorizDispEnd;
long HorizBlankStart;
long HorizBlankEnd;
long HorizSyncStart;
long HorizSyncEnd;
long VertRes; /* the physical y resolution in scanlines */
long VertTotal;
long VertDispEnd;
long VertSyncStart;
long VertSyncEnd;
long VertBlankStart;
long VertBlankEnd;
int multiplexing;
};
#ifdef CIRRUSFB_DEBUG
@ -367,110 +345,13 @@ struct cirrusfb_info {
struct cirrusfb_regs currentmode;
int blank_mode;
u32 pseudo_palette[16];
u32 pseudo_palette[16];
#ifdef CONFIG_ZORRO
struct zorro_dev *zdev;
#endif
#ifdef CONFIG_PCI
struct pci_dev *pdev;
#endif
void (*unmap)(struct fb_info *info);
};
static unsigned cirrusfb_def_mode = 1;
static int noaccel;
/*
* Predefined Video Modes
*/
static const struct {
const char *name;
struct fb_var_screeninfo var;
} cirrusfb_predefined[] = {
{
/* autodetect mode */
.name = "Autodetect",
}, {
/* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
.name = "640x480",
.var = {
.xres = 640,
.yres = 480,
.xres_virtual = 640,
.yres_virtual = 480,
.bits_per_pixel = 8,
.red = { .length = 8 },
.green = { .length = 8 },
.blue = { .length = 8 },
.width = -1,
.height = -1,
.pixclock = 40000,
.left_margin = 48,
.right_margin = 16,
.upper_margin = 32,
.lower_margin = 8,
.hsync_len = 96,
.vsync_len = 4,
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
.vmode = FB_VMODE_NONINTERLACED
}
}, {
/* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */
.name = "800x600",
.var = {
.xres = 800,
.yres = 600,
.xres_virtual = 800,
.yres_virtual = 600,
.bits_per_pixel = 8,
.red = { .length = 8 },
.green = { .length = 8 },
.blue = { .length = 8 },
.width = -1,
.height = -1,
.pixclock = 20000,
.left_margin = 128,
.right_margin = 16,
.upper_margin = 24,
.lower_margin = 2,
.hsync_len = 96,
.vsync_len = 6,
.vmode = FB_VMODE_NONINTERLACED
}
}, {
/*
* Modeline from XF86Config:
* Mode "1024x768" 80 1024 1136 1340 1432 768 770 774 805
*/
/* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
.name = "1024x768",
.var = {
.xres = 1024,
.yres = 768,
.xres_virtual = 1024,
.yres_virtual = 768,
.bits_per_pixel = 8,
.red = { .length = 8 },
.green = { .length = 8 },
.blue = { .length = 8 },
.width = -1,
.height = -1,
.pixclock = 12500,
.left_margin = 144,
.right_margin = 32,
.upper_margin = 30,
.lower_margin = 2,
.hsync_len = 192,
.vsync_len = 6,
.vmode = FB_VMODE_NONINTERLACED
}
}
};
#define NUM_TOTAL_MODES ARRAY_SIZE(cirrusfb_predefined)
static int noaccel __devinitdata;
static char *mode_option __devinitdata = "640x480@60";
/****************************************************************************/
/**** BEGIN PROTOTYPES ******************************************************/
@ -514,10 +395,6 @@ static struct fb_ops cirrusfb_ops = {
.fb_imageblit = cirrusfb_imageblit,
};
/*--- Hardware Specific Routines -------------------------------------------*/
static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
struct cirrusfb_regs *regs,
struct fb_info *info);
/*--- Internal routines ----------------------------------------------------*/
static void init_vgachip(struct fb_info *info);
static void switch_monitor(struct cirrusfb_info *cinfo, int on);
@ -546,9 +423,7 @@ static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
u_short width, u_short height,
u_char color, u_short line_length);
static void bestclock(long freq, long *best,
long *nom, long *den,
long *div, long maxfreq);
static void bestclock(long freq, int *nom, int *den, int *div);
#ifdef CIRRUSFB_DEBUG
static void cirrusfb_dump(void);
@ -584,45 +459,28 @@ static int cirrusfb_release(struct fb_info *info, int user)
/****************************************************************************/
/**** BEGIN Hardware specific Routines **************************************/
/* Get a good MCLK value */
static long cirrusfb_get_mclk(long freq, int bpp, long *div)
/* Check if the MCLK is not a better clock source */
static int cirrusfb_check_mclk(struct cirrusfb_info *cinfo, long freq)
{
long mclk;
long mclk = vga_rseq(cinfo->regbase, CL_SEQR1F) & 0x3f;
assert(div != NULL);
/* Calculate MCLK, in case VCLK is high enough to require > 50MHz.
* Assume a 64-bit data path for now. The formula is:
* ((B * PCLK * 2)/W) * 1.2
* B = bytes per pixel, PCLK = pixclock, W = data width in bytes */
mclk = ((bpp / 8) * freq * 2) / 4;
mclk = (mclk * 12) / 10;
if (mclk < 50000)
mclk = 50000;
DPRINTK("Use MCLK of %ld kHz\n", mclk);
/* Calculate value for SR1F. Multiply by 2 so we can round up. */
mclk = ((mclk * 16) / 14318);
mclk = (mclk + 1) / 2;
DPRINTK("Set SR1F[5:0] to 0x%lx\n", mclk);
/* Read MCLK value */
mclk = (14318 * mclk) >> 3;
DPRINTK("Read MCLK of %ld kHz\n", mclk);
/* Determine if we should use MCLK instead of VCLK, and if so, what we
* should divide it by to get VCLK */
switch (freq) {
case 24751 ... 25249:
*div = 2;
DPRINTK("Using VCLK = MCLK/2\n");
break;
case 49501 ... 50499:
*div = 1;
* should divide it by to get VCLK
*/
if (abs(freq - mclk) < 250) {
DPRINTK("Using VCLK = MCLK\n");
break;
default:
*div = 0;
break;
return 1;
} else if (abs(freq - (mclk / 2)) < 250) {
DPRINTK("Using VCLK = MCLK/2\n");
return 2;
}
return mclk;
return 0;
}
static int cirrusfb_check_var(struct fb_var_screeninfo *var,
@ -638,7 +496,6 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
break; /* 8 pixel per byte, only 1/4th of mem usable */
case 8:
case 16:
case 24:
case 32:
break; /* 1 pixel == 1 byte */
default:
@ -713,7 +570,6 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
var->blue.length = 5;
break;
case 24:
case 32:
if (isPReP) {
var->red.offset = 8;
@ -767,8 +623,6 @@ static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
long maxclock;
int maxclockidx = var->bits_per_pixel >> 3;
struct cirrusfb_info *cinfo = info->par;
int xres, hfront, hsync, hback;
int yres, vfront, vsync, vback;
switch (var->bits_per_pixel) {
case 1:
@ -782,10 +636,9 @@ static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
break;
case 16:
case 24:
case 32:
info->fix.line_length = var->xres_virtual * maxclockidx;
info->fix.visual = FB_VISUAL_DIRECTCOLOR;
info->fix.visual = FB_VISUAL_TRUECOLOR;
break;
default:
@ -827,90 +680,33 @@ static int cirrusfb_decode_var(const struct fb_var_screeninfo *var,
switch (var->bits_per_pixel) {
case 16:
case 32:
if (regs->HorizRes <= 800)
if (var->xres <= 800)
/* Xbh has this type of clock for 32-bit */
freq /= 2;
break;
}
#endif
bestclock(freq, &regs->freq, &regs->nom, &regs->den, &regs->div,
maxclock);
regs->mclk = cirrusfb_get_mclk(freq, var->bits_per_pixel,
&regs->divMCLK);
xres = var->xres;
hfront = var->right_margin;
hsync = var->hsync_len;
hback = var->left_margin;
yres = var->yres;
vfront = var->lower_margin;
vsync = var->vsync_len;
vback = var->upper_margin;
if (var->vmode & FB_VMODE_DOUBLE) {
yres *= 2;
vfront *= 2;
vsync *= 2;
vback *= 2;
} else if (var->vmode & FB_VMODE_INTERLACED) {
yres = (yres + 1) / 2;
vfront = (vfront + 1) / 2;
vsync = (vsync + 1) / 2;
vback = (vback + 1) / 2;
}
regs->HorizRes = xres;
regs->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5;
regs->HorizDispEnd = xres / 8 - 1;
regs->HorizBlankStart = xres / 8;
/* does not count with "-5" */
regs->HorizBlankEnd = regs->HorizTotal + 5;
regs->HorizSyncStart = (xres + hfront) / 8 + 1;
regs->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1;
regs->VertRes = yres;
regs->VertTotal = yres + vfront + vsync + vback - 2;
regs->VertDispEnd = yres - 1;
regs->VertBlankStart = yres;
regs->VertBlankEnd = regs->VertTotal;
regs->VertSyncStart = yres + vfront - 1;
regs->VertSyncEnd = yres + vfront + vsync - 1;
if (regs->VertRes >= 1024) {
regs->VertTotal /= 2;
regs->VertSyncStart /= 2;
regs->VertSyncEnd /= 2;
regs->VertDispEnd /= 2;
}
if (regs->multiplexing) {
regs->HorizTotal /= 2;
regs->HorizSyncStart /= 2;
regs->HorizSyncEnd /= 2;
regs->HorizDispEnd /= 2;
}
return 0;
}
static void cirrusfb_set_mclk(const struct cirrusfb_info *cinfo, int val,
int div)
static void cirrusfb_set_mclk_as_source(const struct cirrusfb_info *cinfo,
int div)
{
unsigned char old1f, old1e;
assert(cinfo != NULL);
old1f = vga_rseq(cinfo->regbase, CL_SEQR1F) & ~0x40;
if (div == 2) {
/* VCLK = MCLK/2 */
unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E);
vga_wseq(cinfo->regbase, CL_SEQR1E, old | 0x1);
vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
} else if (div == 1) {
/* VCLK = MCLK */
unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E);
vga_wseq(cinfo->regbase, CL_SEQR1E, old & ~0x1);
vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f));
} else {
vga_wseq(cinfo->regbase, CL_SEQR1F, val & 0x3f);
if (div) {
DPRINTK("Set %s as pixclock source.\n",
(div == 2) ? "MCLK/2" : "MCLK");
old1f |= 0x40;
old1e = vga_rseq(cinfo->regbase, CL_SEQR1E) & ~0x1;
if (div == 2)
old1e |= 1;
vga_wseq(cinfo->regbase, CL_SEQR1E, old1e);
}
vga_wseq(cinfo->regbase, CL_SEQR1F, old1f);
}
/*************************************************************************
@ -927,6 +723,10 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
unsigned char tmp;
int offset = 0, err;
const struct cirrusfb_board_info_rec *bi;
int hdispend, hsyncstart, hsyncend, htotal;
int yres, vdispend, vsyncstart, vsyncend, vtotal;
long freq;
int nom, den, div;
DPRINTK("ENTER\n");
DPRINTK("Requested mode: %dx%dx%d\n",
@ -944,76 +744,117 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
bi = &cirrusfb_board_info[cinfo->btype];
hsyncstart = var->xres + var->right_margin;
hsyncend = hsyncstart + var->hsync_len;
htotal = (hsyncend + var->left_margin) / 8 - 5;
hdispend = var->xres / 8 - 1;
hsyncstart = hsyncstart / 8 + 1;
hsyncend = hsyncend / 8 + 1;
yres = var->yres;
vsyncstart = yres + var->lower_margin;
vsyncend = vsyncstart + var->vsync_len;
vtotal = vsyncend + var->upper_margin;
vdispend = yres - 1;
if (var->vmode & FB_VMODE_DOUBLE) {
yres *= 2;
vsyncstart *= 2;
vsyncend *= 2;
vtotal *= 2;
} else if (var->vmode & FB_VMODE_INTERLACED) {
yres = (yres + 1) / 2;
vsyncstart = (vsyncstart + 1) / 2;
vsyncend = (vsyncend + 1) / 2;
vtotal = (vtotal + 1) / 2;
}
vtotal -= 2;
vsyncstart -= 1;
vsyncend -= 1;
if (yres >= 1024) {
vtotal /= 2;
vsyncstart /= 2;
vsyncend /= 2;
vdispend /= 2;
}
if (regs.multiplexing) {
htotal /= 2;
hsyncstart /= 2;
hsyncend /= 2;
hdispend /= 2;
}
/* unlock register VGA_CRTC_H_TOTAL..CRT7 */
vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */
/* if debugging is enabled, all parameters get output before writing */
DPRINTK("CRT0: %ld\n", regs.HorizTotal);
vga_wcrt(regbase, VGA_CRTC_H_TOTAL, regs.HorizTotal);
DPRINTK("CRT0: %d\n", htotal);
vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal);
DPRINTK("CRT1: %ld\n", regs.HorizDispEnd);
vga_wcrt(regbase, VGA_CRTC_H_DISP, regs.HorizDispEnd);
DPRINTK("CRT1: %d\n", hdispend);
vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend);
DPRINTK("CRT2: %ld\n", regs.HorizBlankStart);
vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, regs.HorizBlankStart);
DPRINTK("CRT2: %d\n", var->xres / 8);
vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8);
/* + 128: Compatible read */
DPRINTK("CRT3: 128+%ld\n", regs.HorizBlankEnd % 32);
DPRINTK("CRT3: 128+%d\n", (htotal + 5) % 32);
vga_wcrt(regbase, VGA_CRTC_H_BLANK_END,
128 + (regs.HorizBlankEnd % 32));
128 + ((htotal + 5) % 32));
DPRINTK("CRT4: %ld\n", regs.HorizSyncStart);
vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, regs.HorizSyncStart);
DPRINTK("CRT4: %d\n", hsyncstart);
vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart);
tmp = regs.HorizSyncEnd % 32;
if (regs.HorizBlankEnd & 32)
tmp = hsyncend % 32;
if ((htotal + 5) & 32)
tmp += 128;
DPRINTK("CRT5: %d\n", tmp);
vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp);
DPRINTK("CRT6: %ld\n", regs.VertTotal & 0xff);
vga_wcrt(regbase, VGA_CRTC_V_TOTAL, (regs.VertTotal & 0xff));
DPRINTK("CRT6: %d\n", vtotal & 0xff);
vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff);
tmp = 16; /* LineCompare bit #9 */
if (regs.VertTotal & 256)
if (vtotal & 256)
tmp |= 1;
if (regs.VertDispEnd & 256)
if (vdispend & 256)
tmp |= 2;
if (regs.VertSyncStart & 256)
if (vsyncstart & 256)
tmp |= 4;
if (regs.VertBlankStart & 256)
if ((vdispend + 1) & 256)
tmp |= 8;
if (regs.VertTotal & 512)
if (vtotal & 512)
tmp |= 32;
if (regs.VertDispEnd & 512)
if (vdispend & 512)
tmp |= 64;
if (regs.VertSyncStart & 512)
if (vsyncstart & 512)
tmp |= 128;
DPRINTK("CRT7: %d\n", tmp);
vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp);
tmp = 0x40; /* LineCompare bit #8 */
if (regs.VertBlankStart & 512)
if ((vdispend + 1) & 512)
tmp |= 0x20;
if (var->vmode & FB_VMODE_DOUBLE)
tmp |= 0x80;
DPRINTK("CRT9: %d\n", tmp);
vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp);
DPRINTK("CRT10: %ld\n", regs.VertSyncStart & 0xff);
vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, regs.VertSyncStart & 0xff);
DPRINTK("CRT10: %d\n", vsyncstart & 0xff);
vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff);
DPRINTK("CRT11: 64+32+%ld\n", regs.VertSyncEnd % 16);
vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, regs.VertSyncEnd % 16 + 64 + 32);
DPRINTK("CRT11: 64+32+%d\n", vsyncend % 16);
vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32);
DPRINTK("CRT12: %ld\n", regs.VertDispEnd & 0xff);
vga_wcrt(regbase, VGA_CRTC_V_DISP_END, regs.VertDispEnd & 0xff);
DPRINTK("CRT12: %d\n", vdispend & 0xff);
vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff);
DPRINTK("CRT15: %ld\n", regs.VertBlankStart & 0xff);
vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, regs.VertBlankStart & 0xff);
DPRINTK("CRT15: %d\n", (vdispend + 1) & 0xff);
vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff);
DPRINTK("CRT16: %ld\n", regs.VertBlankEnd & 0xff);
vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, regs.VertBlankEnd & 0xff);
DPRINTK("CRT16: %d\n", vtotal & 0xff);
vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff);
DPRINTK("CRT18: 0xff\n");
vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff);
@ -1021,38 +862,53 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
tmp = 0;
if (var->vmode & FB_VMODE_INTERLACED)
tmp |= 1;
if (regs.HorizBlankEnd & 64)
if ((htotal + 5) & 64)
tmp |= 16;
if (regs.HorizBlankEnd & 128)
if ((htotal + 5) & 128)
tmp |= 32;
if (regs.VertBlankEnd & 256)
if (vtotal & 256)
tmp |= 64;
if (regs.VertBlankEnd & 512)
if (vtotal & 512)
tmp |= 128;
DPRINTK("CRT1a: %d\n", tmp);
vga_wcrt(regbase, CL_CRT1A, tmp);
freq = PICOS2KHZ(var->pixclock);
bestclock(freq, &nom, &den, &div);
/* set VCLK0 */
/* hardware RefClock: 14.31818 MHz */
/* formula: VClk = (OSC * N) / (D * (1+P)) */
/* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
vga_wseq(regbase, CL_SEQRB, regs.nom);
tmp = regs.den << 1;
if (regs.div != 0)
tmp |= 1;
if (cinfo->btype == BT_ALPINE) {
/* if freq is close to mclk or mclk/2 select mclk
* as clock source
*/
int divMCLK = cirrusfb_check_mclk(cinfo, freq);
if (divMCLK) {
nom = 0;
cirrusfb_set_mclk_as_source(cinfo, divMCLK);
}
}
if (nom) {
vga_wseq(regbase, CL_SEQRB, nom);
tmp = den << 1;
if (div != 0)
tmp |= 1;
/* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
if ((cinfo->btype == BT_SD64) ||
(cinfo->btype == BT_ALPINE) ||
(cinfo->btype == BT_GD5480))
tmp |= 0x80;
/* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
if ((cinfo->btype == BT_SD64) ||
(cinfo->btype == BT_ALPINE) ||
(cinfo->btype == BT_GD5480))
tmp |= 0x80;
DPRINTK("CL_SEQR1B: %ld\n", (long) tmp);
vga_wseq(regbase, CL_SEQR1B, tmp);
DPRINTK("CL_SEQR1B: %ld\n", (long) tmp);
vga_wseq(regbase, CL_SEQR1B, tmp);
}
if (regs.VertRes >= 1024)
if (yres >= 1024)
/* 1280x1024 */
vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7);
else
@ -1066,7 +922,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
/* don't know if it would hurt to also program this if no interlaced */
/* mode is used, but I feel better this way.. :-) */
if (var->vmode & FB_VMODE_INTERLACED)
vga_wcrt(regbase, VGA_CRTC_REGS, regs.HorizTotal / 2);
vga_wcrt(regbase, VGA_CRTC_REGS, htotal / 2);
else
vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
@ -1240,7 +1096,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
case BT_ALPINE:
DPRINTK(" (for GD543x)\n");
cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
/* We already set SRF and SR1F */
break;
@ -1312,11 +1167,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
case BT_ALPINE:
DPRINTK(" (for GD543x)\n");
if (regs.HorizRes >= 1024)
vga_wseq(regbase, CL_SEQR7, 0xa7);
else
vga_wseq(regbase, CL_SEQR7, 0xa3);
cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
vga_wseq(regbase, CL_SEQR7, 0xa7);
break;
case BT_GD5480:
@ -1360,7 +1211,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
*/
else if (var->bits_per_pixel == 32) {
DPRINTK("cirrusfb: preparing for 24/32 bit deep display\n");
DPRINTK("cirrusfb: preparing for 32 bit deep display\n");
switch (cinfo->btype) {
case BT_SD64:
/* Extended Sequencer Mode: 256c col. mode */
@ -1394,7 +1245,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info)
case BT_ALPINE:
DPRINTK(" (for GD543x)\n");
vga_wseq(regbase, CL_SEQR7, 0xa9);
cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK);
break;
case BT_GD5480:
@ -1949,8 +1799,6 @@ static void init_vgachip(struct fb_info *info)
/* misc... */
WHDR(cinfo, 0); /* Hidden DAC register: - */
printk(KERN_DEBUG "cirrusfb: This board has %ld bytes of DRAM memory\n",
info->screen_size);
DPRINTK("EXIT\n");
return;
}
@ -2122,7 +1970,7 @@ static int release_io_ports;
* based on the DRAM bandwidth bit and DRAM bank switching bit. This
* works with 1MB, 2MB and 4MB configurations (which the Motorola boards
* seem to have. */
static unsigned int cirrusfb_get_memsize(u8 __iomem *regbase)
static unsigned int __devinit cirrusfb_get_memsize(u8 __iomem *regbase)
{
unsigned long mem;
unsigned char SRF;
@ -2188,8 +2036,7 @@ static void get_pci_addrs(const struct pci_dev *pdev,
static void cirrusfb_pci_unmap(struct fb_info *info)
{
struct cirrusfb_info *cinfo = info->par;
struct pci_dev *pdev = cinfo->pdev;
struct pci_dev *pdev = to_pci_dev(info->device);
iounmap(info->screen_base);
#if 0 /* if system didn't claim this region, we would... */
@ -2205,20 +2052,22 @@ static void cirrusfb_pci_unmap(struct fb_info *info)
static void __devexit cirrusfb_zorro_unmap(struct fb_info *info)
{
struct cirrusfb_info *cinfo = info->par;
zorro_release_device(cinfo->zdev);
struct zorro_dev *zdev = to_zorro_dev(info->device);
zorro_release_device(zdev);
if (cinfo->btype == BT_PICASSO4) {
cinfo->regbase -= 0x600000;
iounmap((void *)cinfo->regbase);
iounmap(info->screen_base);
} else {
if (zorro_resource_start(cinfo->zdev) > 0x01000000)
if (zorro_resource_start(zdev) > 0x01000000)
iounmap(info->screen_base);
}
}
#endif /* CONFIG_ZORRO */
static int cirrusfb_set_fbinfo(struct fb_info *info)
static int __devinit cirrusfb_set_fbinfo(struct fb_info *info)
{
struct cirrusfb_info *cinfo = info->par;
struct fb_var_screeninfo *var = &info->var;
@ -2235,7 +2084,7 @@ static int cirrusfb_set_fbinfo(struct fb_info *info)
if (cinfo->btype == BT_GD5480) {
if (var->bits_per_pixel == 16)
info->screen_base += 1 * MB_;
if (var->bits_per_pixel == 24 || var->bits_per_pixel == 32)
if (var->bits_per_pixel == 32)
info->screen_base += 2 * MB_;
}
@ -2262,7 +2111,7 @@ static int cirrusfb_set_fbinfo(struct fb_info *info)
return 0;
}
static int cirrusfb_register(struct fb_info *info)
static int __devinit cirrusfb_register(struct fb_info *info)
{
struct cirrusfb_info *cinfo = info->par;
int err;
@ -2278,23 +2127,27 @@ static int cirrusfb_register(struct fb_info *info)
/* sanity checks */
assert(btype != BT_NONE);
/* set all the vital stuff */
cirrusfb_set_fbinfo(info);
DPRINTK("cirrusfb: (RAM start set to: 0x%p)\n", info->screen_base);
/* Make pretend we've set the var so our structures are in a "good" */
/* state, even though we haven't written the mode to the hw yet... */
info->var = cirrusfb_predefined[cirrusfb_def_mode].var;
err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
if (!err) {
DPRINTK("wrong initial video mode\n");
err = -EINVAL;
goto err_dealloc_cmap;
}
info->var.activate = FB_ACTIVATE_NOW;
err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info);
if (err < 0) {
/* should never happen */
DPRINTK("choking on default var... umm, no good.\n");
goto err_unmap_cirrusfb;
goto err_dealloc_cmap;
}
/* set all the vital stuff */
cirrusfb_set_fbinfo(info);
err = register_framebuffer(info);
if (err < 0) {
printk(KERN_ERR "cirrusfb: could not register "
@ -2307,7 +2160,6 @@ static int cirrusfb_register(struct fb_info *info)
err_dealloc_cmap:
fb_dealloc_cmap(&info->cmap);
err_unmap_cirrusfb:
cinfo->unmap(info);
framebuffer_release(info);
return err;
@ -2330,8 +2182,8 @@ static void __devexit cirrusfb_cleanup(struct fb_info *info)
}
#ifdef CONFIG_PCI
static int cirrusfb_pci_register(struct pci_dev *pdev,
const struct pci_device_id *ent)
static int __devinit cirrusfb_pci_register(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct cirrusfb_info *cinfo;
struct fb_info *info;
@ -2353,7 +2205,6 @@ static int cirrusfb_pci_register(struct pci_dev *pdev,
}
cinfo = info->par;
cinfo->pdev = pdev;
cinfo->btype = btype = (enum cirrus_board) ent->driver_data;
DPRINTK(" Found PCI device, base address 0 is 0x%x, btype set to %d\n",
@ -2459,8 +2310,8 @@ static struct pci_driver cirrusfb_pci_driver = {
#endif /* CONFIG_PCI */
#ifdef CONFIG_ZORRO
static int cirrusfb_zorro_register(struct zorro_dev *z,
const struct zorro_device_id *ent)
static int __devinit cirrusfb_zorro_register(struct zorro_dev *z,
const struct zorro_device_id *ent)
{
struct cirrusfb_info *cinfo;
struct fb_info *info;
@ -2489,7 +2340,6 @@ static int cirrusfb_zorro_register(struct zorro_dev *z,
assert(z);
assert(btype != BT_NONE);
cinfo->zdev = z;
board_addr = zorro_resource_start(z);
board_size = zorro_resource_len(z);
info->screen_size = size;
@ -2621,17 +2471,17 @@ static int __init cirrusfb_setup(char *options) {
return 0;
while ((this_opt = strsep(&options, ",")) != NULL) {
if (!*this_opt) continue;
if (!*this_opt)
continue;
DPRINTK("cirrusfb_setup: option '%s'\n", this_opt);
for (i = 0; i < NUM_TOTAL_MODES; i++) {
sprintf(s, "mode:%s", cirrusfb_predefined[i].name);
if (strcmp(this_opt, s) == 0)
cirrusfb_def_mode = i;
}
if (!strcmp(this_opt, "noaccel"))
noaccel = 1;
else if (!strncmp(this_opt, "mode:", 5))
mode_option = this_opt + 5;
else
mode_option = this_opt;
}
return 0;
}
@ -2657,6 +2507,11 @@ static void __exit cirrusfb_exit(void)
module_init(cirrusfb_init);
module_param(mode_option, charp, 0);
MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
module_param(noaccel, bool, 0);
MODULE_PARM_DESC(noaccel, "Disable acceleration");
#ifdef MODULE
module_exit(cirrusfb_exit);
#endif
@ -3050,16 +2905,14 @@ static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
* bestclock() - determine closest possible clock lower(?) than the
* desired pixel clock
**************************************************************************/
static void bestclock(long freq, long *best, long *nom,
long *den, long *div, long maxfreq)
static void bestclock(long freq, int *nom, int *den, int *div)
{
long n, h, d, f;
int n, d;
long h, diff;
assert(best != NULL);
assert(nom != NULL);
assert(den != NULL);
assert(div != NULL);
assert(maxfreq > 0);
*nom = 0;
*den = 0;
@ -3070,51 +2923,47 @@ static void bestclock(long freq, long *best, long *nom,
if (freq < 8000)
freq = 8000;
if (freq > maxfreq)
freq = maxfreq;
*best = 0;
f = freq * 10;
diff = freq;
for (n = 32; n < 128; n++) {
d = (143181 * n) / f;
int s = 0;
d = (14318 * n) / freq;
if ((d >= 7) && (d <= 63)) {
if (d > 31)
d = (d / 2) * 2;
h = (14318 * n) / d;
if (abs(h - freq) < abs(*best - freq)) {
*best = h;
int temp = d;
if (temp > 31) {
s = 1;
temp >>= 1;
}
h = ((14318 * n) / temp) >> s;
h = h > freq ? h - freq : freq - h;
if (h < diff) {
diff = h;
*nom = n;
if (d < 32) {
*den = d;
*div = 0;
} else {
*den = d / 2;
*div = 1;
}
*den = temp;
*div = s;
}
}
d = DIV_ROUND_UP(143181 * n, f);
d++;
if ((d >= 7) && (d <= 63)) {
if (d > 31)
d = (d / 2) * 2;
h = (14318 * n) / d;
if (abs(h - freq) < abs(*best - freq)) {
*best = h;
if (d > 31) {
s = 1;
d >>= 1;
}
h = ((14318 * n) / d) >> s;
h = h > freq ? h - freq : freq - h;
if (h < diff) {
diff = h;
*nom = n;
if (d < 32) {
*den = d;
*div = 0;
} else {
*den = d / 2;
*div = 1;
}
*den = d;
*div = s;
}
}
}
DPRINTK("Best possible values for given frequency:\n");
DPRINTK(" best: %ld kHz nom: %ld den: %ld div: %ld\n",
DPRINTK(" freq: %ld kHz nom: %d den: %d div: %d\n",
freq, *nom, *den, *div);
DPRINTK("EXIT\n");

View file

@ -43,22 +43,6 @@ config VGACON_SOFT_SCROLLBACK_SIZE
buffer. Each 64KB will give you approximately 16 80x25
screenfuls of scrollback buffer
config VIDEO_SELECT
bool "Video mode selection support"
depends on X86 && VGA_CONSOLE
---help---
This enables support for text mode selection on kernel startup. If
you want to take advantage of some high-resolution text mode your
card's BIOS offers, but the traditional Linux utilities like
SVGATextMode don't, you can say Y here and set the mode using the
"vga=" option from your boot loader (lilo or loadlin) or set
"vga=ask" which brings up a video mode menu on kernel startup. (Try
"man bootparam" or see the documentation of your boot loader about
how to pass options to the kernel.)
Read the file <file:Documentation/svga.txt> for more information
about the Video mode selection support. If unsure, say N.
config MDA_CONSOLE
depends on !M68K && !PARISC && ISA
tristate "MDA text console (dual-headed) (EXPERIMENTAL)"

View file

@ -1855,8 +1855,6 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct display *p = &fb_display[vc->vc_num];
int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK;
unsigned short saved_ec;
int ret;
if (fbcon_is_inactive(vc, info))
return -EINVAL;
@ -1869,11 +1867,6 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
* whole screen (prevents flicker).
*/
saved_ec = vc->vc_video_erase_char;
vc->vc_video_erase_char = vc->vc_scrl_erase_char;
ret = 0;
switch (dir) {
case SM_UP:
if (count > vc->vc_rows) /* Maximum realistic size */
@ -1890,9 +1883,9 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
scr_memsetw((unsigned short *) (vc->vc_origin +
vc->vc_size_row *
(b - count)),
vc->vc_scrl_erase_char,
vc->vc_video_erase_char,
vc->vc_size_row * count);
ret = 1;
return 1;
break;
case SCROLL_WRAP_MOVE:
@ -1962,10 +1955,9 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
scr_memsetw((unsigned short *) (vc->vc_origin +
vc->vc_size_row *
(b - count)),
vc->vc_scrl_erase_char,
vc->vc_video_erase_char,
vc->vc_size_row * count);
ret = 1;
break;
return 1;
}
break;
@ -1982,9 +1974,9 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
scr_memsetw((unsigned short *) (vc->vc_origin +
vc->vc_size_row *
t),
vc->vc_scrl_erase_char,
vc->vc_video_erase_char,
vc->vc_size_row * count);
ret = 1;
return 1;
break;
case SCROLL_WRAP_MOVE:
@ -2052,15 +2044,12 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
scr_memsetw((unsigned short *) (vc->vc_origin +
vc->vc_size_row *
t),
vc->vc_scrl_erase_char,
vc->vc_video_erase_char,
vc->vc_size_row * count);
ret = 1;
break;
return 1;
}
break;
}
vc->vc_video_erase_char = saved_ec;
return ret;
return 0;
}
@ -2400,11 +2389,15 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
if (!fbcon_is_inactive(vc, info)) {
if (ops->blank_state != blank) {
int ret = 1;
ops->blank_state = blank;
fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
ops->cursor_flash = (!blank);
if (fb_blank(info, blank))
if (info->fbops->fb_blank)
ret = info->fbops->fb_blank(blank, info);
if (ret)
fbcon_generic_blank(vc, info, blank);
}
@ -2518,9 +2511,6 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
c = vc->vc_video_erase_char;
vc->vc_video_erase_char =
((c & 0xfe00) >> 1) | (c & 0xff);
c = vc->vc_scrl_erase_char;
vc->vc_scrl_erase_char =
((c & 0xFE00) >> 1) | (c & 0xFF);
vc->vc_attr >>= 1;
}
} else if (!vc->vc_hi_font_mask && cnt == 512) {
@ -2551,14 +2541,9 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
if (vc->vc_can_do_color) {
vc->vc_video_erase_char =
((c & 0xff00) << 1) | (c & 0xff);
c = vc->vc_scrl_erase_char;
vc->vc_scrl_erase_char =
((c & 0xFF00) << 1) | (c & 0xFF);
vc->vc_attr <<= 1;
} else {
} else
vc->vc_video_erase_char = c & ~0x100;
vc->vc_scrl_erase_char = c & ~0x100;
}
}
}
@ -2992,8 +2977,8 @@ static void fbcon_set_all_vcs(struct fb_info *info)
p = &fb_display[vc->vc_num];
set_blitting_type(vc, info);
var_to_display(p, &info->var, info);
cols = FBCON_SWAP(p->rotate, info->var.xres, info->var.yres);
rows = FBCON_SWAP(p->rotate, info->var.yres, info->var.xres);
cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
cols /= vc->vc_font.width;
rows /= vc->vc_font.height;
vc_resize(vc, cols, rows);
@ -3588,8 +3573,8 @@ static int __init fb_console_init(void)
acquire_console_sem();
fb_register_client(&fbcon_event_notifier);
fbcon_device = device_create_drvdata(fb_class, NULL, MKDEV(0, 0),
NULL, "fbcon");
fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), NULL,
"fbcon");
if (IS_ERR(fbcon_device)) {
printk(KERN_WARNING "Unable to create device "

View file

@ -110,7 +110,7 @@ static inline int mono_col(const struct fb_info *info)
__u32 max_len;
max_len = max(info->var.green.length, info->var.red.length);
max_len = max(info->var.blue.length, max_len);
return ~(0xfff << (max_len & 0xff));
return (~(0xfff << max_len)) & 0xff;
}
static inline int attr_col_ec(int shift, struct vc_data *vc,

View file

@ -533,7 +533,7 @@ static void mdacon_cursor(struct vc_data *c, int mode)
static int mdacon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
{
u16 eattr = mda_convert_attr(c->vc_scrl_erase_char);
u16 eattr = mda_convert_attr(c->vc_video_erase_char);
if (!lines)
return 0;

View file

@ -170,12 +170,12 @@ static int sticon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
switch (dir) {
case SM_UP:
sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols);
sti_clear(sti, b - count, 0, count, conp->vc_cols, conp->vc_scrl_erase_char);
sti_clear(sti, b - count, 0, count, conp->vc_cols, conp->vc_video_erase_char);
break;
case SM_DOWN:
sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols);
sti_clear(sti, t, 0, count, conp->vc_cols, conp->vc_scrl_erase_char);
sti_clear(sti, t, 0, count, conp->vc_cols, conp->vc_video_erase_char);
break;
}

View file

@ -239,8 +239,7 @@ static void vgacon_restore_screen(struct vc_data *c)
static int vgacon_scrolldelta(struct vc_data *c, int lines)
{
int start, end, count, soff, diff;
void *d, *s;
int start, end, count, soff;
if (!lines) {
c->vc_visible_origin = c->vc_origin;
@ -287,29 +286,29 @@ static int vgacon_scrolldelta(struct vc_data *c, int lines)
if (count > c->vc_rows)
count = c->vc_rows;
diff = c->vc_rows - count;
if (count) {
int copysize;
d = (void *) c->vc_origin;
s = (void *) c->vc_screenbuf;
int diff = c->vc_rows - count;
void *d = (void *) c->vc_origin;
void *s = (void *) c->vc_screenbuf;
while (count--) {
scr_memcpyw(d, vgacon_scrollback + soff, c->vc_size_row);
d += c->vc_size_row;
soff += c->vc_size_row;
count *= c->vc_size_row;
/* how much memory to end of buffer left? */
copysize = min(count, vgacon_scrollback_size - soff);
scr_memcpyw(d, vgacon_scrollback + soff, copysize);
d += copysize;
count -= copysize;
if (soff >= vgacon_scrollback_size)
soff = 0;
}
if (diff == c->vc_rows) {
vgacon_cursor(c, CM_MOVE);
} else {
while (diff--) {
scr_memcpyw(d, s, c->vc_size_row);
d += c->vc_size_row;
s += c->vc_size_row;
if (count) {
scr_memcpyw(d, vgacon_scrollback, count);
d += count;
}
}
if (diff)
scr_memcpyw(d, s, diff * c->vc_size_row);
} else
vgacon_cursor(c, CM_MOVE);
return 1;
}
@ -1350,7 +1349,7 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
} else
c->vc_origin += delta;
scr_memsetw((u16 *) (c->vc_origin + c->vc_screenbuf_size -
delta), c->vc_scrl_erase_char,
delta), c->vc_video_erase_char,
delta);
} else {
if (oldo - delta < vga_vram_base) {
@ -1363,7 +1362,7 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
} else
c->vc_origin -= delta;
c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
scr_memsetw((u16 *) (c->vc_origin), c->vc_scrl_erase_char,
scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char,
delta);
}
c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;

View file

@ -153,12 +153,9 @@ struct display_device *display_device_register(struct display_driver *driver,
mutex_unlock(&allocated_dsp_lock);
if (!ret) {
new_dev->dev = device_create_drvdata(display_class,
parent,
MKDEV(0,0),
new_dev,
"display%d",
new_dev->idx);
new_dev->dev = device_create(display_class, parent,
MKDEV(0, 0), new_dev,
"display%d", new_dev->idx);
if (!IS_ERR(new_dev->dev)) {
new_dev->parent = parent;
new_dev->driver = driver;

View file

@ -12,6 +12,7 @@
#include <linux/fb.h>
#include <linux/platform_device.h>
#include <linux/screen_info.h>
#include <linux/dmi.h>
#include <video/vga.h>
@ -33,6 +34,105 @@ static struct fb_fix_screeninfo efifb_fix __initdata = {
.visual = FB_VISUAL_TRUECOLOR,
};
enum {
M_I17, /* 17-Inch iMac */
M_I20, /* 20-Inch iMac */
M_I20_SR, /* 20-Inch iMac (Santa Rosa) */
M_I24, /* 24-Inch iMac */
M_MINI, /* Mac Mini */
M_MB, /* MacBook */
M_MB_2, /* MacBook, 2nd rev. */
M_MB_3, /* MacBook, 3rd rev. */
M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */
M_MBA, /* MacBook Air */
M_MBP, /* MacBook Pro */
M_MBP_2, /* MacBook Pro 2nd gen */
M_MBP_SR, /* MacBook Pro (Santa Rosa) */
M_MBP_4, /* MacBook Pro, 4th gen */
M_UNKNOWN /* placeholder */
};
static struct efifb_dmi_info {
char *optname;
unsigned long base;
int stride;
int width;
int height;
} dmi_list[] = {
[M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900 },
[M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */
[M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 },
[M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200 }, /* guess */
[M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768 },
[M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800 },
[M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800 },
[M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900 },
[M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */
[M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 },
[M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 },
[M_UNKNOWN] = { NULL, 0, 0, 0, 0 }
};
static int set_system(const struct dmi_system_id *id);
#define EFIFB_DMI_SYSTEM_ID(vendor, name, enumid) \
{ set_system, name, { \
DMI_MATCH(DMI_BIOS_VENDOR, vendor), \
DMI_MATCH(DMI_PRODUCT_NAME, name) }, \
&dmi_list[enumid] }
static struct dmi_system_id __initdata dmi_system_table[] = {
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac4,1", M_I17),
/* At least one of these two will be right; maybe both? */
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac5,1", M_I20),
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac5,1", M_I20),
/* At least one of these two will be right; maybe both? */
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac6,1", M_I24),
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac6,1", M_I24),
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac7,1", M_I20_SR),
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "Macmini1,1", M_MINI),
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook1,1", M_MB),
/* At least one of these two will be right; maybe both? */
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook2,1", M_MB),
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook2,1", M_MB),
/* At least one of these two will be right; maybe both? */
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook3,1", M_MB),
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook3,1", M_MB),
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook4,1", M_MB),
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA),
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP),
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2),
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro2,1", M_MBP_2),
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR),
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR),
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4),
{},
};
static int set_system(const struct dmi_system_id *id)
{
struct efifb_dmi_info *info = id->driver_data;
if (info->base == 0)
return -ENODEV;
printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p "
"(%dx%d, stride %d)\n", id->ident,
(void *)info->base, info->width, info->height,
info->stride);
/* Trust the bootloader over the DMI tables */
if (screen_info.lfb_base == 0)
screen_info.lfb_base = info->base;
if (screen_info.lfb_linelength == 0)
screen_info.lfb_linelength = info->stride;
if (screen_info.lfb_width == 0)
screen_info.lfb_width = info->width;
if (screen_info.lfb_height == 0)
screen_info.lfb_height = info->height;
return 0;
}
static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info)
@ -67,6 +167,38 @@ static struct fb_ops efifb_ops = {
.fb_imageblit = cfb_imageblit,
};
static int __init efifb_setup(char *options)
{
char *this_opt;
int i;
if (!options || !*options)
return 0;
while ((this_opt = strsep(&options, ",")) != NULL) {
if (!*this_opt) continue;
for (i = 0; i < M_UNKNOWN; i++) {
if (!strcmp(this_opt, dmi_list[i].optname) &&
dmi_list[i].base != 0) {
screen_info.lfb_base = dmi_list[i].base;
screen_info.lfb_linelength = dmi_list[i].stride;
screen_info.lfb_width = dmi_list[i].width;
screen_info.lfb_height = dmi_list[i].height;
}
}
if (!strncmp(this_opt, "base:", 5))
screen_info.lfb_base = simple_strtoul(this_opt+5, NULL, 0);
else if (!strncmp(this_opt, "stride:", 7))
screen_info.lfb_linelength = simple_strtoul(this_opt+7, NULL, 0) * 4;
else if (!strncmp(this_opt, "height:", 7))
screen_info.lfb_height = simple_strtoul(this_opt+7, NULL, 0);
else if (!strncmp(this_opt, "width:", 6))
screen_info.lfb_width = simple_strtoul(this_opt+6, NULL, 0);
}
return 0;
}
static int __init efifb_probe(struct platform_device *dev)
{
struct fb_info *info;
@ -74,6 +206,26 @@ static int __init efifb_probe(struct platform_device *dev)
unsigned int size_vmode;
unsigned int size_remap;
unsigned int size_total;
int request_succeeded = 0;
printk(KERN_INFO "efifb: probing for efifb\n");
if (!screen_info.lfb_depth)
screen_info.lfb_depth = 32;
if (!screen_info.pages)
screen_info.pages = 1;
/* just assume they're all unset if any are */
if (!screen_info.blue_size) {
screen_info.blue_size = 8;
screen_info.blue_pos = 0;
screen_info.green_size = 8;
screen_info.green_pos = 8;
screen_info.red_size = 8;
screen_info.red_pos = 16;
screen_info.rsvd_size = 8;
screen_info.rsvd_pos = 24;
}
efifb_fix.smem_start = screen_info.lfb_base;
efifb_defined.bits_per_pixel = screen_info.lfb_depth;
@ -98,21 +250,25 @@ static int __init efifb_probe(struct platform_device *dev)
* option to simply use size_total as that
* wastes plenty of kernel address space. */
size_remap = size_vmode * 2;
if (size_remap < size_vmode)
size_remap = size_vmode;
if (size_remap > size_total)
size_remap = size_total;
if (size_remap % PAGE_SIZE)
size_remap += PAGE_SIZE - (size_remap % PAGE_SIZE);
efifb_fix.smem_len = size_remap;
if (!request_mem_region(efifb_fix.smem_start, size_total, "efifb"))
if (request_mem_region(efifb_fix.smem_start, size_remap, "efifb")) {
request_succeeded = 1;
} else {
/* We cannot make this fatal. Sometimes this comes from magic
spaces our resource handlers simply don't know about */
printk(KERN_WARNING
"efifb: cannot reserve video memory at 0x%lx\n",
efifb_fix.smem_start);
}
info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
if (!info) {
printk(KERN_ERR "efifb: cannot allocate framebuffer\n");
err = -ENOMEM;
goto err_release_mem;
}
@ -125,7 +281,7 @@ static int __init efifb_probe(struct platform_device *dev)
"0x%x @ 0x%lx\n",
efifb_fix.smem_len, efifb_fix.smem_start);
err = -EIO;
goto err_unmap;
goto err_release_fb;
}
printk(KERN_INFO "efifb: framebuffer at 0x%lx, mapped to 0x%p, "
@ -178,25 +334,27 @@ static int __init efifb_probe(struct platform_device *dev)
info->fix = efifb_fix;
info->flags = FBINFO_FLAG_DEFAULT;
if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
err = -ENOMEM;
if ((err = fb_alloc_cmap(&info->cmap, 256, 0)) < 0) {
printk(KERN_ERR "efifb: cannot allocate colormap\n");
goto err_unmap;
}
if (register_framebuffer(info) < 0) {
err = -EINVAL;
if ((err = register_framebuffer(info)) < 0) {
printk(KERN_ERR "efifb: cannot register framebuffer\n");
goto err_fb_dealoc;
}
printk(KERN_INFO "fb%d: %s frame buffer device\n",
info->node, info->fix.id);
info->node, info->fix.id);
return 0;
err_fb_dealoc:
fb_dealloc_cmap(&info->cmap);
err_unmap:
iounmap(info->screen_base);
err_release_fb:
framebuffer_release(info);
err_release_mem:
release_mem_region(efifb_fix.smem_start, size_total);
if (request_succeeded)
release_mem_region(efifb_fix.smem_start, size_total);
return err;
}
@ -214,9 +372,22 @@ static struct platform_device efifb_device = {
static int __init efifb_init(void)
{
int ret;
char *option = NULL;
if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
return -ENODEV;
dmi_check_system(dmi_system_table);
if (fb_get_options("efifb", &option))
return -ENODEV;
efifb_setup(option);
/* We don't get linelength from UGA Draw Protocol, only from
* EFI Graphics Protocol. So if it's not in DMI, and it's not
* passed in from the user, we really can't use the framebuffer.
*/
if (!screen_info.lfb_linelength)
return -ENODEV;
ret = platform_driver_register(&efifb_driver);

View file

@ -28,9 +28,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/console.h>
#ifdef CONFIG_KMOD
#include <linux/kmod.h>
#endif
#include <linux/err.h>
#include <linux/device.h>
#include <linux/efi.h>
@ -837,13 +835,6 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
return (cnt) ? cnt : err;
}
#ifdef CONFIG_KMOD
static void try_to_load(int fb)
{
request_module("fb%d", fb);
}
#endif /* CONFIG_KMOD */
int
fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
{
@ -979,6 +970,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
info->flags &= ~FBINFO_MISC_USEREVENT;
event.info = info;
event.data = &mode;
fb_notifier_call_chain(evnt, &event);
}
}
@ -1085,10 +1077,8 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return -EINVAL;
if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)
return -EINVAL;
#ifdef CONFIG_KMOD
if (!registered_fb[con2fb.framebuffer])
try_to_load(con2fb.framebuffer);
#endif /* CONFIG_KMOD */
request_module("fb%d", con2fb.framebuffer);
if (!registered_fb[con2fb.framebuffer])
return -EINVAL;
event.info = info;
@ -1326,10 +1316,8 @@ fb_open(struct inode *inode, struct file *file)
if (fbidx >= FB_MAX)
return -ENODEV;
lock_kernel();
#ifdef CONFIG_KMOD
if (!(info = registered_fb[fbidx]))
try_to_load(fbidx);
#endif /* CONFIG_KMOD */
request_module("fb%d", fbidx);
if (!(info = registered_fb[fbidx])) {
res = -ENODEV;
goto out;
@ -1442,9 +1430,8 @@ register_framebuffer(struct fb_info *fb_info)
break;
fb_info->node = i;
fb_info->dev = device_create_drvdata(fb_class, fb_info->device,
MKDEV(FB_MAJOR, i), NULL,
"fb%d", i);
fb_info->dev = device_create(fb_class, fb_info->device,
MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
if (IS_ERR(fb_info->dev)) {
/* Not fatal */
printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));

View file

@ -564,7 +564,13 @@ static void get_detailed_timing(unsigned char *block,
mode->sync |= FB_SYNC_VERT_HIGH_ACT;
mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
(V_ACTIVE + V_BLANKING));
mode->vmode = 0;
if (INTERLACED) {
mode->yres *= 2;
mode->upper_margin *= 2;
mode->lower_margin *= 2;
mode->vsync_len *= 2;
mode->vmode |= FB_VMODE_INTERLACED;
}
mode->flag = FB_MODE_IS_DETAILED;
DPRINTK(" %d MHz ", PIXEL_CLOCK/1000000);

View file

@ -1042,7 +1042,7 @@ static int __devexit ffb_remove(struct of_device *op)
return 0;
}
static struct of_device_id ffb_match[] = {
static const struct of_device_id ffb_match[] = {
{
.name = "SUNW,ffb",
},

View file

@ -1,376 +0,0 @@
/*
* framebuffer driver for Intel Based Mac's
*
* (c) 2006 Edgar Hucek <gimli@dark-green.com>
* Original imac driver written by Gerd Knorr <kraxel@goldbach.in-berlin.de>
*
*/
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/fb.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/screen_info.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/dmi.h>
#include <linux/efi.h>
#include <asm/io.h>
#include <video/vga.h>
typedef enum _MAC_TYPE {
M_I17,
M_I20,
M_MINI,
M_MACBOOK,
M_UNKNOWN
} MAC_TYPE;
/* --------------------------------------------------------------------- */
static struct fb_var_screeninfo imacfb_defined __initdata = {
.activate = FB_ACTIVATE_NOW,
.height = -1,
.width = -1,
.right_margin = 32,
.upper_margin = 16,
.lower_margin = 4,
.vsync_len = 4,
.vmode = FB_VMODE_NONINTERLACED,
};
static struct fb_fix_screeninfo imacfb_fix __initdata = {
.id = "IMAC VGA",
.type = FB_TYPE_PACKED_PIXELS,
.accel = FB_ACCEL_NONE,
.visual = FB_VISUAL_TRUECOLOR,
};
static int inverse;
static int model = M_UNKNOWN;
static int manual_height;
static int manual_width;
static int set_system(const struct dmi_system_id *id)
{
printk(KERN_INFO "imacfb: %s detected - set system to %ld\n",
id->ident, (long)id->driver_data);
model = (long)id->driver_data;
return 0;
}
static struct dmi_system_id __initdata dmi_system_table[] = {
{ set_system, "iMac4,1", {
DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
DMI_MATCH(DMI_PRODUCT_NAME,"iMac4,1") }, (void*)M_I17},
{ set_system, "MacBookPro1,1", {
DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro1,1") }, (void*)M_I17},
{ set_system, "MacBook1,1", {
DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
DMI_MATCH(DMI_PRODUCT_NAME,"MacBook1,1")}, (void *)M_MACBOOK},
{ set_system, "Macmini1,1", {
DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
DMI_MATCH(DMI_PRODUCT_NAME,"Macmini1,1")}, (void *)M_MINI},
{},
};
#define DEFAULT_FB_MEM 1024*1024*16
/* --------------------------------------------------------------------- */
static int imacfb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info)
{
/*
* 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.
*/
if (regno >= info->cmap.len)
return 1;
if (regno < 16) {
red >>= 8;
green >>= 8;
blue >>= 8;
((u32 *)(info->pseudo_palette))[regno] =
(red << info->var.red.offset) |
(green << info->var.green.offset) |
(blue << info->var.blue.offset);
}
return 0;
}
static struct fb_ops imacfb_ops = {
.owner = THIS_MODULE,
.fb_setcolreg = imacfb_setcolreg,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
};
static int __init imacfb_setup(char *options)
{
char *this_opt;
if (!options || !*options)
return 0;
while ((this_opt = strsep(&options, ",")) != NULL) {
if (!*this_opt) continue;
if (!strcmp(this_opt, "inverse"))
inverse = 1;
else if (!strcmp(this_opt, "i17"))
model = M_I17;
else if (!strcmp(this_opt, "i20"))
model = M_I20;
else if (!strcmp(this_opt, "mini"))
model = M_MINI;
else if (!strcmp(this_opt, "macbook"))
model = M_MACBOOK;
else if (!strncmp(this_opt, "height:", 7))
manual_height = simple_strtoul(this_opt+7, NULL, 0);
else if (!strncmp(this_opt, "width:", 6))
manual_width = simple_strtoul(this_opt+6, NULL, 0);
}
return 0;
}
static int __init imacfb_probe(struct platform_device *dev)
{
struct fb_info *info;
int err;
unsigned int size_vmode;
unsigned int size_remap;
unsigned int size_total;
screen_info.lfb_depth = 32;
screen_info.lfb_size = DEFAULT_FB_MEM / 0x10000;
screen_info.pages=1;
screen_info.blue_size = 8;
screen_info.blue_pos = 0;
screen_info.green_size = 8;
screen_info.green_pos = 8;
screen_info.red_size = 8;
screen_info.red_pos = 16;
screen_info.rsvd_size = 8;
screen_info.rsvd_pos = 24;
switch (model) {
case M_I17:
screen_info.lfb_width = 1440;
screen_info.lfb_height = 900;
screen_info.lfb_linelength = 1472 * 4;
screen_info.lfb_base = 0x80010000;
break;
case M_I20:
screen_info.lfb_width = 1680;
screen_info.lfb_height = 1050;
screen_info.lfb_linelength = 1728 * 4;
screen_info.lfb_base = 0x80010000;
break;
case M_MINI:
screen_info.lfb_width = 1024;
screen_info.lfb_height = 768;
screen_info.lfb_linelength = 2048 * 4;
screen_info.lfb_base = 0x80000000;
break;
case M_MACBOOK:
screen_info.lfb_width = 1280;
screen_info.lfb_height = 800;
screen_info.lfb_linelength = 2048 * 4;
screen_info.lfb_base = 0x80000000;
break;
}
/* if the user wants to manually specify height/width,
we will override the defaults */
/* TODO: eventually get auto-detection working */
if (manual_height > 0)
screen_info.lfb_height = manual_height;
if (manual_width > 0)
screen_info.lfb_width = manual_width;
imacfb_fix.smem_start = screen_info.lfb_base;
imacfb_defined.bits_per_pixel = screen_info.lfb_depth;
imacfb_defined.xres = screen_info.lfb_width;
imacfb_defined.yres = screen_info.lfb_height;
imacfb_fix.line_length = screen_info.lfb_linelength;
/* size_vmode -- that is the amount of memory needed for the
* used video mode, i.e. the minimum amount of
* memory we need. */
size_vmode = imacfb_defined.yres * imacfb_fix.line_length;
/* size_total -- all video memory we have. Used for
* entries, ressource allocation and bounds
* checking. */
size_total = screen_info.lfb_size * 65536;
if (size_total < size_vmode)
size_total = size_vmode;
/* size_remap -- the amount of video memory we are going to
* use for imacfb. With modern cards it is no
* option to simply use size_total as that
* wastes plenty of kernel address space. */
size_remap = size_vmode * 2;
if (size_remap < size_vmode)
size_remap = size_vmode;
if (size_remap > size_total)
size_remap = size_total;
imacfb_fix.smem_len = size_remap;
if (!request_mem_region(imacfb_fix.smem_start, size_total, "imacfb")) {
printk(KERN_WARNING
"imacfb: cannot reserve video memory at 0x%lx\n",
imacfb_fix.smem_start);
/* We cannot make this fatal. Sometimes this comes from magic
spaces our resource handlers simply don't know about */
}
info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
if (!info) {
err = -ENOMEM;
goto err_release_mem;
}
info->pseudo_palette = info->par;
info->par = NULL;
info->screen_base = ioremap(imacfb_fix.smem_start, imacfb_fix.smem_len);
if (!info->screen_base) {
printk(KERN_ERR "imacfb: abort, cannot ioremap video memory "
"0x%x @ 0x%lx\n",
imacfb_fix.smem_len, imacfb_fix.smem_start);
err = -EIO;
goto err_unmap;
}
printk(KERN_INFO "imacfb: framebuffer at 0x%lx, mapped to 0x%p, "
"using %dk, total %dk\n",
imacfb_fix.smem_start, info->screen_base,
size_remap/1024, size_total/1024);
printk(KERN_INFO "imacfb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
imacfb_defined.xres, imacfb_defined.yres,
imacfb_defined.bits_per_pixel, imacfb_fix.line_length,
screen_info.pages);
imacfb_defined.xres_virtual = imacfb_defined.xres;
imacfb_defined.yres_virtual = imacfb_fix.smem_len /
imacfb_fix.line_length;
printk(KERN_INFO "imacfb: scrolling: redraw\n");
imacfb_defined.yres_virtual = imacfb_defined.yres;
/* some dummy values for timing to make fbset happy */
imacfb_defined.pixclock = 10000000 / imacfb_defined.xres *
1000 / imacfb_defined.yres;
imacfb_defined.left_margin = (imacfb_defined.xres / 8) & 0xf8;
imacfb_defined.hsync_len = (imacfb_defined.xres / 8) & 0xf8;
imacfb_defined.red.offset = screen_info.red_pos;
imacfb_defined.red.length = screen_info.red_size;
imacfb_defined.green.offset = screen_info.green_pos;
imacfb_defined.green.length = screen_info.green_size;
imacfb_defined.blue.offset = screen_info.blue_pos;
imacfb_defined.blue.length = screen_info.blue_size;
imacfb_defined.transp.offset = screen_info.rsvd_pos;
imacfb_defined.transp.length = screen_info.rsvd_size;
printk(KERN_INFO "imacfb: %s: "
"size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
"Truecolor",
screen_info.rsvd_size,
screen_info.red_size,
screen_info.green_size,
screen_info.blue_size,
screen_info.rsvd_pos,
screen_info.red_pos,
screen_info.green_pos,
screen_info.blue_pos);
imacfb_fix.ypanstep = 0;
imacfb_fix.ywrapstep = 0;
/* request failure does not faze us, as vgacon probably has this
* region already (FIXME) */
request_region(0x3c0, 32, "imacfb");
info->fbops = &imacfb_ops;
info->var = imacfb_defined;
info->fix = imacfb_fix;
info->flags = FBINFO_FLAG_DEFAULT;
if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
err = -ENOMEM;
goto err_unmap;
}
if (register_framebuffer(info)<0) {
err = -EINVAL;
goto err_fb_dealoc;
}
printk(KERN_INFO "fb%d: %s frame buffer device\n",
info->node, info->fix.id);
return 0;
err_fb_dealoc:
fb_dealloc_cmap(&info->cmap);
err_unmap:
iounmap(info->screen_base);
framebuffer_release(info);
err_release_mem:
release_mem_region(imacfb_fix.smem_start, size_total);
return err;
}
static struct platform_driver imacfb_driver = {
.probe = imacfb_probe,
.driver = {
.name = "imacfb",
},
};
static struct platform_device imacfb_device = {
.name = "imacfb",
};
static int __init imacfb_init(void)
{
int ret;
char *option = NULL;
if (!efi_enabled)
return -ENODEV;
if (!dmi_check_system(dmi_system_table))
return -ENODEV;
if (model == M_UNKNOWN)
return -ENODEV;
if (fb_get_options("imacfb", &option))
return -ENODEV;
imacfb_setup(option);
ret = platform_driver_register(&imacfb_driver);
if (!ret) {
ret = platform_device_register(&imacfb_device);
if (ret)
platform_driver_unregister(&imacfb_driver);
}
return ret;
}
module_init(imacfb_init);
MODULE_LICENSE("GPL");

View file

@ -12,9 +12,9 @@
#endif
/*** Version/name ***/
#define INTELFB_VERSION "0.9.5"
#define INTELFB_VERSION "0.9.6"
#define INTELFB_MODULE_NAME "intelfb"
#define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM"
#define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/945GME/965G/965GM"
/*** Debug/feature defines ***/
@ -58,6 +58,7 @@
#define PCI_DEVICE_ID_INTEL_915GM 0x2592
#define PCI_DEVICE_ID_INTEL_945G 0x2772
#define PCI_DEVICE_ID_INTEL_945GM 0x27A2
#define PCI_DEVICE_ID_INTEL_945GME 0x27AE
#define PCI_DEVICE_ID_INTEL_965G 0x29A2
#define PCI_DEVICE_ID_INTEL_965GM 0x2A02
@ -160,6 +161,7 @@ enum intel_chips {
INTEL_915GM,
INTEL_945G,
INTEL_945GM,
INTEL_945GME,
INTEL_965G,
INTEL_965GM,
};
@ -363,6 +365,7 @@ struct intelfb_info {
((dinfo)->chipset == INTEL_915GM) || \
((dinfo)->chipset == INTEL_945G) || \
((dinfo)->chipset == INTEL_945GM) || \
((dinfo)->chipset == INTEL_945GME) || \
((dinfo)->chipset == INTEL_965G) || \
((dinfo)->chipset == INTEL_965GM))

View file

@ -171,6 +171,7 @@ void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
/* has some LVDS + tv-out */
case INTEL_945G:
case INTEL_945GM:
case INTEL_945GME:
case INTEL_965G:
case INTEL_965GM:
/* SDVO ports have a single control bus - 2 devices */

View file

@ -2,7 +2,7 @@
* intelfb
*
* Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM/
* 945G/945GM/965G/965GM integrated graphics chips.
* 945G/945GM/945GME/965G/965GM integrated graphics chips.
*
* Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
* 2004 Sylvain Meyer
@ -102,6 +102,9 @@
*
* 04/2008 - Version 0.9.5
* Add support for 965G/965GM. (Maik Broemme <mbroemme@plusserver.de>)
*
* 08/2008 - Version 0.9.6
* Add support for 945GME. (Phil Endecott <spam_from_intelfb@chezphil.org>)
*/
#include <linux/module.h>
@ -183,6 +186,7 @@ static struct pci_device_id intelfb_pci_table[] __devinitdata = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945G },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GM },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GME, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GME },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965G },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965GM },
{ 0, }
@ -555,6 +559,7 @@ static int __devinit intelfb_pci_register(struct pci_dev *pdev,
(ent->device == PCI_DEVICE_ID_INTEL_915GM) ||
(ent->device == PCI_DEVICE_ID_INTEL_945G) ||
(ent->device == PCI_DEVICE_ID_INTEL_945GM) ||
(ent->device == PCI_DEVICE_ID_INTEL_945GME) ||
(ent->device == PCI_DEVICE_ID_INTEL_965G) ||
(ent->device == PCI_DEVICE_ID_INTEL_965GM)) {

View file

@ -143,6 +143,12 @@ int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo)
dinfo->mobile = 1;
dinfo->pll_index = PLLS_I9xx;
return 0;
case PCI_DEVICE_ID_INTEL_945GME:
dinfo->name = "Intel(R) 945GME";
dinfo->chipset = INTEL_945GME;
dinfo->mobile = 1;
dinfo->pll_index = PLLS_I9xx;
return 0;
case PCI_DEVICE_ID_INTEL_965G:
dinfo->name = "Intel(R) 965G";
dinfo->chipset = INTEL_965G;
@ -186,6 +192,7 @@ int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
case PCI_DEVICE_ID_INTEL_915GM:
case PCI_DEVICE_ID_INTEL_945G:
case PCI_DEVICE_ID_INTEL_945GM:
case PCI_DEVICE_ID_INTEL_945GME:
case PCI_DEVICE_ID_INTEL_965G:
case PCI_DEVICE_ID_INTEL_965GM:
/* 915, 945 and 965 chipsets support a 256MB aperture.

View file

@ -33,6 +33,7 @@ static int leo_blank(int, struct fb_info *);
static int leo_mmap(struct fb_info *, struct vm_area_struct *);
static int leo_ioctl(struct fb_info *, unsigned int, unsigned long);
static int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *);
/*
* Frame buffer operations
@ -42,6 +43,7 @@ static struct fb_ops leo_ops = {
.owner = THIS_MODULE,
.fb_setcolreg = leo_setcolreg,
.fb_blank = leo_blank,
.fb_pan_display = leo_pan_display,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
@ -206,6 +208,60 @@ static void leo_wait(struct leo_lx_krn __iomem *lx_krn)
return;
}
static void leo_switch_from_graph(struct fb_info *info)
{
struct leo_par *par = (struct leo_par *) info->par;
struct leo_ld_ss0 __iomem *ss = par->ld_ss0;
struct leo_cursor __iomem *cursor = par->cursor;
unsigned long flags;
u32 val;
spin_lock_irqsave(&par->lock, flags);
par->extent = ((info->var.xres - 1) |
((info->var.yres - 1) << 16));
sbus_writel(0xffffffff, &ss->wid);
sbus_writel(0xffff, &ss->wmask);
sbus_writel(0, &ss->vclipmin);
sbus_writel(par->extent, &ss->vclipmax);
sbus_writel(0, &ss->fg);
sbus_writel(0xff000000, &ss->planemask);
sbus_writel(0x310850, &ss->rop);
sbus_writel(0, &ss->widclip);
sbus_writel((info->var.xres-1) | ((info->var.yres-1) << 11),
&par->lc_ss0_usr->extent);
sbus_writel(4, &par->lc_ss0_usr->addrspace);
sbus_writel(0x80000000, &par->lc_ss0_usr->fill);
sbus_writel(0, &par->lc_ss0_usr->fontt);
do {
val = sbus_readl(&par->lc_ss0_usr->csr);
} while (val & 0x20000000);
/* setup screen buffer for cfb_* functions */
sbus_writel(1, &ss->wid);
sbus_writel(0x00ffffff, &ss->planemask);
sbus_writel(0x310b90, &ss->rop);
sbus_writel(0, &par->lc_ss0_usr->addrspace);
/* hide cursor */
sbus_writel(sbus_readl(&cursor->cur_misc) & ~LEO_CUR_ENABLE, &cursor->cur_misc);
spin_unlock_irqrestore(&par->lock, flags);
}
static int leo_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
{
/* We just use this to catch switches out of
* graphics mode.
*/
leo_switch_from_graph(info);
if (var->xoffset || var->yoffset || var->vmode)
return -EINVAL;
return 0;
}
/**
* leo_setcolreg - Optional function. Sets a color register.
* @regno: boolean, 0 copy local, 1 get_user() function
@ -454,44 +510,6 @@ static void leo_init_wids(struct fb_info *info)
leo_wid_put(info, &wl);
}
static void leo_switch_from_graph(struct fb_info *info)
{
struct leo_par *par = (struct leo_par *) info->par;
struct leo_ld_ss0 __iomem *ss = par->ld_ss0;
unsigned long flags;
u32 val;
spin_lock_irqsave(&par->lock, flags);
par->extent = ((info->var.xres - 1) |
((info->var.yres - 1) << 16));
sbus_writel(0xffffffff, &ss->wid);
sbus_writel(0xffff, &ss->wmask);
sbus_writel(0, &ss->vclipmin);
sbus_writel(par->extent, &ss->vclipmax);
sbus_writel(0, &ss->fg);
sbus_writel(0xff000000, &ss->planemask);
sbus_writel(0x310850, &ss->rop);
sbus_writel(0, &ss->widclip);
sbus_writel((info->var.xres-1) | ((info->var.yres-1) << 11),
&par->lc_ss0_usr->extent);
sbus_writel(4, &par->lc_ss0_usr->addrspace);
sbus_writel(0x80000000, &par->lc_ss0_usr->fill);
sbus_writel(0, &par->lc_ss0_usr->fontt);
do {
val = sbus_readl(&par->lc_ss0_usr->csr);
} while (val & 0x20000000);
/* setup screen buffer for cfb_* functions */
sbus_writel(1, &ss->wid);
sbus_writel(0x00ffffff, &ss->planemask);
sbus_writel(0x310b90, &ss->rop);
sbus_writel(0, &par->lc_ss0_usr->addrspace);
spin_unlock_irqrestore(&par->lock, flags);
}
static void leo_init_hw(struct fb_info *info)
{
struct leo_par *par = (struct leo_par *) info->par;
@ -641,7 +659,7 @@ static int __devexit leo_remove(struct of_device *op)
return 0;
}
static struct of_device_id leo_match[] = {
static const struct of_device_id leo_match[] = {
{
.name = "SUNW,leo",
},

View file

@ -1453,6 +1453,13 @@ static struct board {
MGA_G100,
&vbG100,
"MGA-G100 (AGP)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200EV_PCI, 0xFF,
0, 0,
DEVF_G200,
230000,
MGA_G200,
&vbG200,
"MGA-G200eV (PCI)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI, 0xFF,
0, 0,
DEVF_G200,
@ -2118,6 +2125,8 @@ static struct pci_device_id matroxfb_devices[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200EV_PCI,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP,

View file

@ -40,29 +40,63 @@
#include <asm/unaligned.h>
#define DEBUG 1
#ifdef DEBUG
#define DPRINTK(f, a...) printk(KERN_DEBUG "%s: " f, __func__ , ## a)
#else
#define DPRINTK(f, a...)
#endif
/* Display specific information */
#define DPY_W 832
#define DPY_H 622
static int user_wfm_size;
/* frame differs from image. frame includes non-visible pixels */
struct epd_frame {
int fw; /* frame width */
int fh; /* frame height */
u16 config[4];
int wfm_size;
};
static struct epd_frame epd_frame_table[] = {
{
.fw = 832,
.fh = 622
.fw = 832,
.fh = 622,
.config = {
15 /* sdlew */
| 2 << 8 /* sdosz */
| 0 << 11 /* sdor */
| 0 << 12 /* sdces */
| 0 << 15, /* sdcer */
42 /* gdspl */
| 1 << 8 /* gdr1 */
| 1 << 9 /* sdshr */
| 0 << 15, /* gdspp */
18 /* gdspw */
| 0 << 15, /* dispc */
599 /* vdlc */
| 0 << 11 /* dsi */
| 0 << 12, /* dsic */
},
.wfm_size = 47001,
},
{
.fw = 1088,
.fh = 791,
.config = {
0x0104,
0x031f,
0x0088,
0x02ff,
},
.wfm_size = 46770,
},
{
.fw = 1200,
.fh = 842,
.config = {
0x0101,
0x030e,
0x0012,
0x0280,
},
.wfm_size = 46770,
},
};
@ -134,9 +168,8 @@ static u16 calc_img_cksum(u16 *start, int length)
}
/* here we decode the incoming waveform file and populate metromem */
#define EXP_WFORM_SIZE 47001
static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
u8 *frame_count)
static int __devinit load_waveform(u8 *mem, size_t size, int m, int t,
struct metronomefb_par *par)
{
int tta;
int wmta;
@ -148,26 +181,31 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
int wfm_idx, owfm_idx;
int mem_idx = 0;
struct waveform_hdr *wfm_hdr;
u8 *metromem = par->metromem_wfm;
struct device *dev = par->info->dev;
if (size != EXP_WFORM_SIZE) {
printk(KERN_ERR "Error: unexpected size %d != %d\n", size,
EXP_WFORM_SIZE);
if (user_wfm_size)
epd_frame_table[par->dt].wfm_size = user_wfm_size;
if (size != epd_frame_table[par->dt].wfm_size) {
dev_err(dev, "Error: unexpected size %Zd != %d\n", size,
epd_frame_table[par->dt].wfm_size);
return -EINVAL;
}
wfm_hdr = (struct waveform_hdr *) mem;
if (wfm_hdr->fvsn != 1) {
printk(KERN_ERR "Error: bad fvsn %x\n", wfm_hdr->fvsn);
dev_err(dev, "Error: bad fvsn %x\n", wfm_hdr->fvsn);
return -EINVAL;
}
if (wfm_hdr->luts != 0) {
printk(KERN_ERR "Error: bad luts %x\n", wfm_hdr->luts);
dev_err(dev, "Error: bad luts %x\n", wfm_hdr->luts);
return -EINVAL;
}
cksum = calc_cksum(32, 47, mem);
if (cksum != wfm_hdr->wfm_cs) {
printk(KERN_ERR "Error: bad cksum %x != %x\n", cksum,
dev_err(dev, "Error: bad cksum %x != %x\n", cksum,
wfm_hdr->wfm_cs);
return -EINVAL;
}
@ -175,7 +213,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
wfm_hdr->trc += 1;
for (i = 0; i < 5; i++) {
if (*(wfm_hdr->stuff2a + i) != 0) {
printk(KERN_ERR "Error: unexpected value in padding\n");
dev_err(dev, "Error: unexpected value in padding\n");
return -EINVAL;
}
}
@ -200,7 +238,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
return -EINVAL;
cksum = calc_cksum(sizeof(*wfm_hdr), cksum_idx, mem);
if (cksum != mem[cksum_idx]) {
printk(KERN_ERR "Error: bad temperature range table cksum"
dev_err(dev, "Error: bad temperature range table cksum"
" %x != %x\n", cksum, mem[cksum_idx]);
return -EINVAL;
}
@ -212,7 +250,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
return -EINVAL;
cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
if (cksum != mem[cksum_idx]) {
printk(KERN_ERR "Error: bad mode table address cksum"
dev_err(dev, "Error: bad mode table address cksum"
" %x != %x\n", cksum, mem[cksum_idx]);
return -EINVAL;
}
@ -224,7 +262,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
return -EINVAL;
cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
if (cksum != mem[cksum_idx]) {
printk(KERN_ERR "Error: bad temperature table address cksum"
dev_err(dev, "Error: bad temperature table address cksum"
" %x != %x\n", cksum, mem[cksum_idx]);
return -EINVAL;
}
@ -259,11 +297,11 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
return -EINVAL;
cksum = calc_cksum(owfm_idx, cksum_idx, mem);
if (cksum != mem[cksum_idx]) {
printk(KERN_ERR "Error: bad waveform data cksum"
dev_err(dev, "Error: bad waveform data cksum"
" %x != %x\n", cksum, mem[cksum_idx]);
return -EINVAL;
}
*frame_count = (mem_idx/64);
par->frame_count = (mem_idx/64);
return 0;
}
@ -274,15 +312,12 @@ static int metronome_display_cmd(struct metronomefb_par *par)
u16 cs;
u16 opcode;
static u8 borderval;
u8 *ptr;
/* setup display command
we can't immediately set the opcode since the controller
will try parse the command before we've set it all up
so we just set cs here and set the opcode at the end */
ptr = par->metromem;
if (par->metromem_cmd->opcode == 0xCC40)
opcode = cs = 0xCC41;
else
@ -335,44 +370,17 @@ static int __devinit metronome_powerup_cmd(struct metronomefb_par *par)
static int __devinit metronome_config_cmd(struct metronomefb_par *par)
{
int i;
u16 cs;
/* setup config command
we can't immediately set the opcode since the controller
will try parse the command before we've set it all up
so we just set cs here and set the opcode at the end */
cs = 0xCC10;
/* set the 12 args ( 8 bytes ) for config. see spec for meanings */
i = 0;
par->metromem_cmd->args[i] = 15 /* sdlew */
| 2 << 8 /* sdosz */
| 0 << 11 /* sdor */
| 0 << 12 /* sdces */
| 0 << 15; /* sdcer */
cs += par->metromem_cmd->args[i++];
par->metromem_cmd->args[i] = 42 /* gdspl */
| 1 << 8 /* gdr1 */
| 1 << 9 /* sdshr */
| 0 << 15; /* gdspp */
cs += par->metromem_cmd->args[i++];
par->metromem_cmd->args[i] = 18 /* gdspw */
| 0 << 15; /* dispc */
cs += par->metromem_cmd->args[i++];
par->metromem_cmd->args[i] = 599 /* vdlc */
| 0 << 11 /* dsi */
| 0 << 12; /* dsic */
cs += par->metromem_cmd->args[i++];
will try parse the command before we've set it all up */
memcpy(par->metromem_cmd->args, epd_frame_table[par->dt].config,
sizeof(epd_frame_table[par->dt].config));
/* the rest are 0 */
memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
memset((u8 *) (par->metromem_cmd->args + 4), 0, (32-4)*2);
par->metromem_cmd->csum = cs;
par->metromem_cmd->csum = 0xCC10;
par->metromem_cmd->csum += calc_img_cksum(par->metromem_cmd->args, 4);
par->metromem_cmd->opcode = 0xCC10; /* config cmd */
return par->board->met_wait_event(par);
@ -408,12 +416,9 @@ static int __devinit metronome_init_regs(struct metronomefb_par *par)
{
int res;
par->board->init_gpio_regs(par);
par->board->init_lcdc_regs(par);
/* now that lcd is setup, setup dma descriptor */
par->board->post_dma_setup(par);
res = par->board->setup_io(par);
if (res)
return res;
res = metronome_powerup_cmd(par);
if (res)
@ -430,16 +435,16 @@ static int __devinit metronome_init_regs(struct metronomefb_par *par)
static void metronomefb_dpy_update(struct metronomefb_par *par)
{
int fbsize;
u16 cksum;
unsigned char *buf = (unsigned char __force *)par->info->screen_base;
fbsize = par->info->fix.smem_len;
/* copy from vm to metromem */
memcpy(par->metromem_img, buf, DPY_W*DPY_H);
memcpy(par->metromem_img, buf, fbsize);
cksum = calc_img_cksum((u16 *) par->metromem_img,
(epd_frame_table[0].fw * DPY_H)/2);
*((u16 *)(par->metromem_img) +
(epd_frame_table[0].fw * DPY_H)/2) = cksum;
cksum = calc_img_cksum((u16 *) par->metromem_img, fbsize/2);
*((u16 *)(par->metromem_img) + fbsize/2) = cksum;
metronome_display_cmd(par);
}
@ -574,8 +579,10 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
unsigned char *videomemory;
struct metronomefb_par *par;
const struct firmware *fw_entry;
int cmd_size, wfm_size, img_size, padding_size, totalsize;
int i;
int panel_type;
int fw, fh;
int epd_dt_index;
/* pick up board specific routines */
board = dev->dev.platform_data;
@ -586,96 +593,108 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
if (!try_module_get(board->owner))
return -ENODEV;
info = framebuffer_alloc(sizeof(struct metronomefb_par), &dev->dev);
if (!info)
goto err;
/* we have two blocks of memory.
info->screen_base which is vm, and is the fb used by apps.
par->metromem which is physically contiguous memory and
contains the display controller commands, waveform,
processed image data and padding. this is the data pulled
by the device's LCD controller and pushed to Metronome */
by the device's LCD controller and pushed to Metronome.
the metromem memory is allocated by the board driver and
is provided to us */
videomemorysize = (DPY_W*DPY_H);
panel_type = board->get_panel_type();
switch (panel_type) {
case 6:
epd_dt_index = 0;
break;
case 8:
epd_dt_index = 1;
break;
case 97:
epd_dt_index = 2;
break;
default:
dev_err(&dev->dev, "Unexpected panel type. Defaulting to 6\n");
epd_dt_index = 0;
break;
}
fw = epd_frame_table[epd_dt_index].fw;
fh = epd_frame_table[epd_dt_index].fh;
/* we need to add a spare page because our csum caching scheme walks
* to the end of the page */
videomemorysize = PAGE_SIZE + (fw * fh);
videomemory = vmalloc(videomemorysize);
if (!videomemory)
return -ENOMEM;
goto err_fb_rel;
memset(videomemory, 0, videomemorysize);
info = framebuffer_alloc(sizeof(struct metronomefb_par), &dev->dev);
if (!info)
goto err_vfree;
info->screen_base = (char __force __iomem *)videomemory;
info->fbops = &metronomefb_ops;
metronomefb_fix.line_length = fw;
metronomefb_var.xres = fw;
metronomefb_var.yres = fh;
metronomefb_var.xres_virtual = fw;
metronomefb_var.yres_virtual = fh;
info->var = metronomefb_var;
info->fix = metronomefb_fix;
info->fix.smem_len = videomemorysize;
par = info->par;
par->info = info;
par->board = board;
par->dt = epd_dt_index;
init_waitqueue_head(&par->waitq);
/* this table caches per page csum values. */
par->csum_table = vmalloc(videomemorysize/PAGE_SIZE);
if (!par->csum_table)
goto err_csum_table;
/* the metromem buffer is divided as follows:
command | CRC | padding
16kb waveform data | CRC | padding
image data | CRC
and an extra 256 bytes for dma descriptors
eg: IW=832 IH=622 WS=128
*/
cmd_size = 1 * epd_frame_table[0].fw;
wfm_size = ((16*1024 + 2 + epd_frame_table[0].fw - 1)
/ epd_frame_table[0].fw) * epd_frame_table[0].fw;
img_size = epd_frame_table[0].fh * epd_frame_table[0].fw;
padding_size = 4 * epd_frame_table[0].fw;
totalsize = cmd_size + wfm_size + img_size + padding_size;
par->metromemsize = PAGE_ALIGN(totalsize + 256);
DPRINTK("desired memory size = %d\n", par->metromemsize);
dev->dev.coherent_dma_mask = 0xffffffffull;
par->metromem = dma_alloc_writecombine(&dev->dev, par->metromemsize,
&par->metromem_dma, GFP_KERNEL);
if (!par->metromem) {
printk(KERN_ERR
"metronomefb: unable to allocate dma buffer\n");
goto err_vfree;
/* the physical framebuffer that we use is setup by
* the platform device driver. It will provide us
* with cmd, wfm and image memory in a contiguous area. */
retval = board->setup_fb(par);
if (retval) {
dev_err(&dev->dev, "Failed to setup fb\n");
goto err_csum_table;
}
/* after this point we should have a framebuffer */
if ((!par->metromem_wfm) || (!par->metromem_img) ||
(!par->metromem_dma)) {
dev_err(&dev->dev, "fb access failure\n");
retval = -EINVAL;
goto err_csum_table;
}
info->fix.smem_start = par->metromem_dma;
par->metromem_cmd = (struct metromem_cmd *) par->metromem;
par->metromem_wfm = par->metromem + cmd_size;
par->metromem_img = par->metromem + cmd_size + wfm_size;
par->metromem_img_csum = (u16 *) (par->metromem_img +
(epd_frame_table[0].fw * DPY_H));
DPRINTK("img offset=0x%x\n", cmd_size + wfm_size);
par->metromem_desc = (struct metromem_desc *) (par->metromem + cmd_size
+ wfm_size + img_size + padding_size);
par->metromem_desc_dma = par->metromem_dma + cmd_size + wfm_size
+ img_size + padding_size;
/* load the waveform in. assume mode 3, temp 31 for now
a) request the waveform file from userspace
b) process waveform and decode into metromem */
retval = request_firmware(&fw_entry, "metronome.wbf", &dev->dev);
if (retval < 0) {
printk(KERN_ERR "metronomefb: couldn't get waveform\n");
goto err_dma_free;
dev_err(&dev->dev, "Failed to get waveform\n");
goto err_csum_table;
}
retval = load_waveform((u8 *) fw_entry->data, fw_entry->size,
par->metromem_wfm, 3, 31, &par->frame_count);
retval = load_waveform((u8 *) fw_entry->data, fw_entry->size, 3, 31,
par);
release_firmware(fw_entry);
if (retval < 0) {
printk(KERN_ERR "metronomefb: couldn't process waveform\n");
goto err_dma_free;
dev_err(&dev->dev, "Failed processing waveform\n");
goto err_csum_table;
}
if (board->setup_irq(info))
goto err_dma_free;
goto err_csum_table;
retval = metronome_init_regs(par);
if (retval < 0)
@ -688,8 +707,8 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
retval = fb_alloc_cmap(&info->cmap, 8, 0);
if (retval < 0) {
printk(KERN_ERR "Failed to allocate colormap\n");
goto err_fb_rel;
dev_err(&dev->dev, "Failed to allocate colormap\n");
goto err_free_irq;
}
/* set cmap */
@ -704,7 +723,7 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
platform_set_drvdata(dev, info);
printk(KERN_INFO
dev_dbg(&dev->dev,
"fb%d: Metronome frame buffer device, using %dK of video"
" memory\n", info->node, videomemorysize >> 10);
@ -712,17 +731,15 @@ static int __devinit metronomefb_probe(struct platform_device *dev)
err_cmap:
fb_dealloc_cmap(&info->cmap);
err_fb_rel:
framebuffer_release(info);
err_free_irq:
board->free_irq(info);
err_dma_free:
dma_free_writecombine(&dev->dev, par->metromemsize, par->metromem,
par->metromem_dma);
board->cleanup(par);
err_csum_table:
vfree(par->csum_table);
err_vfree:
vfree(videomemory);
err_fb_rel:
framebuffer_release(info);
err:
module_put(board->owner);
return retval;
}
@ -733,15 +750,15 @@ static int __devexit metronomefb_remove(struct platform_device *dev)
if (info) {
struct metronomefb_par *par = info->par;
fb_deferred_io_cleanup(info);
dma_free_writecombine(&dev->dev, par->metromemsize,
par->metromem, par->metromem_dma);
fb_dealloc_cmap(&info->cmap);
vfree(par->csum_table);
unregister_framebuffer(info);
fb_deferred_io_cleanup(info);
fb_dealloc_cmap(&info->cmap);
par->board->cleanup(par);
vfree(par->csum_table);
vfree((void __force *)info->screen_base);
par->board->free_irq(info);
module_put(par->board->owner);
dev_dbg(&dev->dev, "calling release\n");
framebuffer_release(info);
}
return 0;
@ -766,6 +783,9 @@ static void __exit metronomefb_exit(void)
platform_driver_unregister(&metronomefb_driver);
}
module_param(user_wfm_size, uint, 0);
MODULE_PARM_DESC(user_wfm_size, "Set custom waveform size");
module_init(metronomefb_init);
module_exit(metronomefb_exit);

View file

@ -426,11 +426,11 @@ static void vgaHWProtect(int on)
{
unsigned char tmp;
tmp = vga_rseq(NULL, 0x01);
if (on) {
/*
* Turn off screen and disable sequencer.
*/
tmp = vga_rseq(NULL, 0x01);
vga_wseq(NULL, 0x00, 0x01); /* Synchronous Reset */
vga_wseq(NULL, 0x01, tmp | 0x20); /* disable the display */
@ -439,7 +439,6 @@ static void vgaHWProtect(int on)
/*
* Reenable sequencer, then turn on screen.
*/
tmp = vga_rseq(NULL, 0x01);
vga_wseq(NULL, 0x01, tmp & ~0x20); /* reenable display */
vga_wseq(NULL, 0x00, 0x03); /* clear synchronousreset */
@ -558,14 +557,12 @@ neofb_open(struct fb_info *info, int user)
{
struct neofb_par *par = info->par;
mutex_lock(&par->open_lock);
if (!par->ref_count) {
memset(&par->state, 0, sizeof(struct vgastate));
par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
save_vga(&par->state);
}
par->ref_count++;
mutex_unlock(&par->open_lock);
return 0;
}
@ -575,16 +572,13 @@ neofb_release(struct fb_info *info, int user)
{
struct neofb_par *par = info->par;
mutex_lock(&par->open_lock);
if (!par->ref_count) {
mutex_unlock(&par->open_lock);
if (!par->ref_count)
return -EINVAL;
}
if (par->ref_count == 1) {
restore_vga(&par->state);
}
par->ref_count--;
mutex_unlock(&par->open_lock);
return 0;
}
@ -648,10 +642,10 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->blue.msb_right = 0;
var->transp.msb_right = 0;
var->transp.offset = 0;
var->transp.length = 0;
switch (var->bits_per_pixel) {
case 8: /* PSEUDOCOLOUR, 256 */
var->transp.offset = 0;
var->transp.length = 0;
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 0;
@ -661,8 +655,6 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
break;
case 16: /* DIRECTCOLOUR, 64k */
var->transp.offset = 0;
var->transp.length = 0;
var->red.offset = 11;
var->red.length = 5;
var->green.offset = 5;
@ -672,8 +664,6 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
break;
case 24: /* TRUECOLOUR, 16m */
var->transp.offset = 0;
var->transp.length = 0;
var->red.offset = 16;
var->red.length = 8;
var->green.offset = 8;
@ -704,8 +694,6 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
if (vramlen > 4 * 1024 * 1024)
vramlen = 4 * 1024 * 1024;
if (var->yres_virtual < var->yres)
var->yres_virtual = var->yres;
if (var->xres_virtual < var->xres)
var->xres_virtual = var->xres;
@ -722,8 +710,6 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
if it was possible. We should return -EINVAL, but I disagree */
if (var->yres_virtual < var->yres)
var->yres = var->yres_virtual;
if (var->xres_virtual < var->xres)
var->xres = var->xres_virtual;
if (var->xoffset + var->xres > var->xres_virtual)
var->xoffset = var->xres_virtual - var->xres;
if (var->yoffset + var->yres > var->yres_virtual)
@ -1186,8 +1172,11 @@ static int neofb_set_par(struct fb_info *info)
return 0;
}
static void neofb_update_start(struct fb_info *info,
struct fb_var_screeninfo *var)
/*
* Pan or Wrap the Display
*/
static int neofb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct neofb_par *par = info->par;
struct vgastate *state = &par->state;
@ -1216,35 +1205,7 @@ static void neofb_update_start(struct fb_info *info,
vga_wgfx(state->vgabase, 0x0E, (((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0)));
neoLock(state);
}
/*
* Pan or Wrap the Display
*/
static int neofb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
u_int y_bottom;
y_bottom = var->yoffset;
if (!(var->vmode & FB_VMODE_YWRAP))
y_bottom += var->yres;
if (var->xoffset > (var->xres_virtual - var->xres))
return -EINVAL;
if (y_bottom > info->var.yres_virtual)
return -EINVAL;
neofb_update_start(info, var);
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;
}
@ -1992,7 +1953,6 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st
info->fix.accel = id->driver_data;
mutex_init(&par->open_lock);
par->pci_burst = !nopciburst;
par->lcd_stretch = !nostretch;
par->libretto = libretto;

View file

@ -156,7 +156,7 @@ struct resmap {
};
static struct {
u32 base;
void __iomem *base;
struct omapfb_mem_desc mem_desc;
struct resmap *res_map[DISPC_MEMTYPE_NUM];
@ -212,9 +212,9 @@ static void enable_rfbi_mode(int enable)
dispc_write_reg(DISPC_CONTROL, l);
/* Set bypass mode in RFBI module */
l = __raw_readl(io_p2v(RFBI_CONTROL));
l = __raw_readl(IO_ADDRESS(RFBI_CONTROL));
l |= enable ? 0 : (1 << 1);
__raw_writel(l, io_p2v(RFBI_CONTROL));
__raw_writel(l, IO_ADDRESS(RFBI_CONTROL));
}
static void set_lcd_data_lines(int data_lines)
@ -1349,14 +1349,19 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
memset(&dispc, 0, sizeof(dispc));
dispc.base = io_p2v(DISPC_BASE);
dispc.base = ioremap(DISPC_BASE, SZ_1K);
if (!dispc.base) {
dev_err(fbdev->dev, "can't ioremap DISPC\n");
return -ENOMEM;
}
dispc.fbdev = fbdev;
dispc.ext_mode = ext_mode;
init_completion(&dispc.frame_done);
if ((r = get_dss_clocks()) < 0)
return r;
goto fail0;
enable_interface_clocks(1);
enable_lcd_clocks(1);
@ -1414,7 +1419,7 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode,
}
/* L3 firewall setting: enable access to OCM RAM */
__raw_writel(0x402000b0, io_p2v(0x680050a0));
__raw_writel(0x402000b0, IO_ADDRESS(0x680050a0));
if ((r = alloc_palette_ram()) < 0)
goto fail2;
@ -1464,7 +1469,8 @@ fail1:
enable_lcd_clocks(0);
enable_interface_clocks(0);
put_dss_clocks();
fail0:
iounmap(dispc.base);
return r;
}
@ -1481,6 +1487,7 @@ static void omap_dispc_cleanup(void)
free_irq(INT_24XX_DSS_IRQ, dispc.fbdev);
enable_interface_clocks(0);
put_dss_clocks();
iounmap(dispc.base);
}
const struct lcd_ctrl omap2_int_ctrl = {

View file

@ -40,4 +40,6 @@ extern void omap_dispc_enable_digit_out(int enable);
extern int omap_dispc_request_irq(void (*callback)(void *data), void *data);
extern void omap_dispc_free_irq(void);
extern const struct lcd_ctrl omap2_int_ctrl;
#endif

View file

@ -47,7 +47,7 @@ static unsigned long h4_panel_get_caps(struct lcd_panel *panel)
return 0;
}
struct lcd_panel h4_panel = {
static struct lcd_panel h4_panel = {
.name = "h4",
.config = OMAP_LCDC_PANEL_TFT,
@ -91,7 +91,7 @@ static int h4_panel_resume(struct platform_device *pdev)
return 0;
}
struct platform_driver h4_panel_driver = {
static struct platform_driver h4_panel_driver = {
.probe = h4_panel_probe,
.remove = h4_panel_remove,
.suspend = h4_panel_suspend,

View file

@ -32,43 +32,43 @@ static int innovator1610_panel_init(struct lcd_panel *panel,
{
int r = 0;
if (omap_request_gpio(14)) {
if (gpio_request(14, "lcd_en0")) {
pr_err(MODULE_NAME ": can't request GPIO 14\n");
r = -1;
goto exit;
}
if (omap_request_gpio(15)) {
if (gpio_request(15, "lcd_en1")) {
pr_err(MODULE_NAME ": can't request GPIO 15\n");
omap_free_gpio(14);
gpio_free(14);
r = -1;
goto exit;
}
/* configure GPIO(14, 15) as outputs */
omap_set_gpio_direction(14, 0);
omap_set_gpio_direction(15, 0);
gpio_direction_output(14, 0);
gpio_direction_output(15, 0);
exit:
return r;
}
static void innovator1610_panel_cleanup(struct lcd_panel *panel)
{
omap_free_gpio(15);
omap_free_gpio(14);
gpio_free(15);
gpio_free(14);
}
static int innovator1610_panel_enable(struct lcd_panel *panel)
{
/* set GPIO14 and GPIO15 high */
omap_set_gpio_dataout(14, 1);
omap_set_gpio_dataout(15, 1);
gpio_set_value(14, 1);
gpio_set_value(15, 1);
return 0;
}
static void innovator1610_panel_disable(struct lcd_panel *panel)
{
/* set GPIO13, GPIO14 and GPIO15 low */
omap_set_gpio_dataout(14, 0);
omap_set_gpio_dataout(15, 0);
gpio_set_value(14, 0);
gpio_set_value(15, 0);
}
static unsigned long innovator1610_panel_get_caps(struct lcd_panel *panel)

View file

@ -29,6 +29,7 @@
static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
{
/* gpio2 was allocated in board init */
return 0;
}
@ -47,11 +48,8 @@ static int osk_panel_enable(struct lcd_panel *panel)
/* Set PWL level */
omap_writeb(0xFF, OMAP_PWL_ENABLE);
/* configure GPIO2 as output */
omap_set_gpio_direction(2, 0);
/* set GPIO2 high */
omap_set_gpio_dataout(2, 1);
/* set GPIO2 high (lcd power enabled) */
gpio_set_value(2, 1);
return 0;
}
@ -65,7 +63,7 @@ static void osk_panel_disable(struct lcd_panel *panel)
omap_writeb(0x00, OMAP_PWL_CLK_ENABLE);
/* set GPIO2 low */
omap_set_gpio_dataout(2, 0);
gpio_set_value(2, 0);
}
static unsigned long osk_panel_get_caps(struct lcd_panel *panel)

View file

@ -81,21 +81,21 @@ static void epson_sendbyte(int flag, unsigned char byte)
int i, shifter = 0x80;
if (!flag)
omap_set_gpio_dataout(_A_LCD_SSC_A0, 0);
gpio_set_value(_A_LCD_SSC_A0, 0);
mdelay(2);
omap_set_gpio_dataout(A_LCD_SSC_RD, 1);
gpio_set_value(A_LCD_SSC_RD, 1);
omap_set_gpio_dataout(A_LCD_SSC_SD, flag);
gpio_set_value(A_LCD_SSC_SD, flag);
OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200);
OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202);
for (i = 0; i < 8; i++) {
OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200);
omap_set_gpio_dataout(A_LCD_SSC_SD, shifter & byte);
gpio_set_value(A_LCD_SSC_SD, shifter & byte);
OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202);
shifter >>= 1;
}
omap_set_gpio_dataout(_A_LCD_SSC_A0, 1);
gpio_set_value(_A_LCD_SSC_A0, 1);
}
static void init_system(void)
@ -107,25 +107,18 @@ static void init_system(void)
static void setup_GPIO(void)
{
/* new wave */
omap_request_gpio(A_LCD_SSC_RD);
omap_request_gpio(A_LCD_SSC_SD);
omap_request_gpio(_A_LCD_RESET);
omap_request_gpio(_A_LCD_SSC_CS);
omap_request_gpio(_A_LCD_SSC_A0);
gpio_request(A_LCD_SSC_RD, "lcd_ssc_rd");
gpio_request(A_LCD_SSC_SD, "lcd_ssc_sd");
gpio_request(_A_LCD_RESET, "lcd_reset");
gpio_request(_A_LCD_SSC_CS, "lcd_ssc_cs");
gpio_request(_A_LCD_SSC_A0, "lcd_ssc_a0");
/* set all GPIOs to output */
omap_set_gpio_direction(A_LCD_SSC_RD, 0);
omap_set_gpio_direction(A_LCD_SSC_SD, 0);
omap_set_gpio_direction(_A_LCD_RESET, 0);
omap_set_gpio_direction(_A_LCD_SSC_CS, 0);
omap_set_gpio_direction(_A_LCD_SSC_A0, 0);
/* set GPIO data */
omap_set_gpio_dataout(A_LCD_SSC_RD, 1);
omap_set_gpio_dataout(A_LCD_SSC_SD, 0);
omap_set_gpio_dataout(_A_LCD_RESET, 0);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
omap_set_gpio_dataout(_A_LCD_SSC_A0, 1);
/* set GPIOs to output, with initial data */
gpio_direction_output(A_LCD_SSC_RD, 1);
gpio_direction_output(A_LCD_SSC_SD, 0);
gpio_direction_output(_A_LCD_RESET, 0);
gpio_direction_output(_A_LCD_SSC_CS, 1);
gpio_direction_output(_A_LCD_SSC_A0, 1);
}
static void display_init(void)
@ -139,61 +132,61 @@ static void display_init(void)
mdelay(2);
/* reset LCD */
omap_set_gpio_dataout(A_LCD_SSC_SD, 1);
gpio_set_value(A_LCD_SSC_SD, 1);
epson_sendbyte(0, 0x25);
omap_set_gpio_dataout(_A_LCD_RESET, 0);
gpio_set_value(_A_LCD_RESET, 0);
mdelay(10);
omap_set_gpio_dataout(_A_LCD_RESET, 1);
gpio_set_value(_A_LCD_RESET, 1);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
gpio_set_value(_A_LCD_SSC_CS, 1);
mdelay(2);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
gpio_set_value(_A_LCD_SSC_CS, 0);
/* init LCD, phase 1 */
epson_sendbyte(0, 0xCA);
for (i = 0; i < 10; i++)
epson_sendbyte(1, INIT_1[i]);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
gpio_set_value(_A_LCD_SSC_CS, 1);
gpio_set_value(_A_LCD_SSC_CS, 0);
/* init LCD phase 2 */
epson_sendbyte(0, 0xCB);
for (i = 0; i < 125; i++)
epson_sendbyte(1, INIT_2[i]);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
gpio_set_value(_A_LCD_SSC_CS, 1);
gpio_set_value(_A_LCD_SSC_CS, 0);
/* init LCD phase 2a */
epson_sendbyte(0, 0xCC);
for (i = 0; i < 14; i++)
epson_sendbyte(1, INIT_3[i]);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
gpio_set_value(_A_LCD_SSC_CS, 1);
gpio_set_value(_A_LCD_SSC_CS, 0);
/* init LCD phase 3 */
epson_sendbyte(0, 0xBC);
epson_sendbyte(1, 0x08);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
gpio_set_value(_A_LCD_SSC_CS, 1);
gpio_set_value(_A_LCD_SSC_CS, 0);
/* init LCD phase 4 */
epson_sendbyte(0, 0x07);
epson_sendbyte(1, 0x05);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
gpio_set_value(_A_LCD_SSC_CS, 1);
gpio_set_value(_A_LCD_SSC_CS, 0);
/* init LCD phase 5 */
epson_sendbyte(0, 0x94);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
gpio_set_value(_A_LCD_SSC_CS, 1);
gpio_set_value(_A_LCD_SSC_CS, 0);
/* init LCD phase 6 */
epson_sendbyte(0, 0xC6);
epson_sendbyte(1, 0x80);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
gpio_set_value(_A_LCD_SSC_CS, 1);
mdelay(100); /* used to be 1000 */
omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
gpio_set_value(_A_LCD_SSC_CS, 0);
/* init LCD phase 7 */
epson_sendbyte(0, 0x16);
@ -201,8 +194,8 @@ static void display_init(void)
epson_sendbyte(1, 0x00);
epson_sendbyte(1, 0xB1);
epson_sendbyte(1, 0x00);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
gpio_set_value(_A_LCD_SSC_CS, 1);
gpio_set_value(_A_LCD_SSC_CS, 0);
/* init LCD phase 8 */
epson_sendbyte(0, 0x76);
@ -210,12 +203,12 @@ static void display_init(void)
epson_sendbyte(1, 0x00);
epson_sendbyte(1, 0xDB);
epson_sendbyte(1, 0x00);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
gpio_set_value(_A_LCD_SSC_CS, 1);
gpio_set_value(_A_LCD_SSC_CS, 0);
/* init LCD phase 9 */
epson_sendbyte(0, 0xAF);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
gpio_set_value(_A_LCD_SSC_CS, 1);
}
static int sx1_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
@ -231,18 +224,18 @@ static void sx1_panel_disable(struct lcd_panel *panel)
{
printk(KERN_INFO "SX1: LCD panel disable\n");
sx1_setmmipower(0);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
gpio_set_value(_A_LCD_SSC_CS, 1);
epson_sendbyte(0, 0x25);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
gpio_set_value(_A_LCD_SSC_CS, 0);
epson_sendbyte(0, 0xAE);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
gpio_set_value(_A_LCD_SSC_CS, 1);
mdelay(100);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 0);
gpio_set_value(_A_LCD_SSC_CS, 0);
epson_sendbyte(0, 0x95);
omap_set_gpio_dataout(_A_LCD_SSC_CS, 1);
gpio_set_value(_A_LCD_SSC_CS, 1);
}
static int sx1_panel_enable(struct lcd_panel *panel)

View file

@ -34,6 +34,8 @@
#include <asm/mach-types.h>
#include "lcdc.h"
#define MODULE_NAME "lcdc"
#define OMAP_LCDC_BASE 0xfffec000

View file

@ -4,4 +4,6 @@
int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data);
void omap_lcdc_free_dma_callback(void);
extern const struct lcd_ctrl omap1_int_ctrl;
#endif

View file

@ -31,11 +31,14 @@
#include <mach/dma.h>
#include <mach/omapfb.h>
#include "lcdc.h"
#include "dispc.h"
#define MODULE_NAME "omapfb"
static unsigned int def_accel;
static unsigned long def_vram[OMAPFB_PLANE_NUM];
static int def_vram_cnt;
static unsigned int def_vram_cnt;
static unsigned long def_vxres;
static unsigned long def_vyres;
static unsigned int def_rotate;
@ -84,12 +87,10 @@ static struct caps_table_struct color_caps[] = {
* LCD panel
* ---------------------------------------------------------------------------
*/
extern struct lcd_ctrl omap1_int_ctrl;
extern struct lcd_ctrl omap2_int_ctrl;
extern struct lcd_ctrl hwa742_ctrl;
extern struct lcd_ctrl blizzard_ctrl;
static struct lcd_ctrl *ctrls[] = {
static const struct lcd_ctrl *ctrls[] = {
#ifdef CONFIG_ARCH_OMAP1
&omap1_int_ctrl,
#else
@ -740,7 +741,7 @@ static int omapfb_update_win(struct fb_info *fbi,
int ret;
omapfb_rqueue_lock(plane->fbdev);
ret = omapfb_update_window_async(fbi, win, NULL, 0);
ret = omapfb_update_window_async(fbi, win, NULL, NULL);
omapfb_rqueue_unlock(plane->fbdev);
return ret;
@ -768,7 +769,7 @@ static int omapfb_update_full_screen(struct fb_info *fbi)
win.format = 0;
omapfb_rqueue_lock(fbdev);
r = fbdev->ctrl->update_window(fbi, &win, NULL, 0);
r = fbdev->ctrl->update_window(fbi, &win, NULL, NULL);
omapfb_rqueue_unlock(fbdev);
return r;
@ -1047,7 +1048,7 @@ void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval)
win.height = 2;
win.out_width = 2;
win.out_height = 2;
fbdev->ctrl->update_window(fbdev->fb_info[0], &win, NULL, 0);
fbdev->ctrl->update_window(fbdev->fb_info[0], &win, NULL, NULL);
}
omapfb_rqueue_unlock(fbdev);
}

View file

@ -59,7 +59,7 @@
#define DISPC_CONTROL 0x0040
static struct {
u32 base;
void __iomem *base;
void (*lcdc_callback)(void *data);
void *lcdc_callback_data;
unsigned long l4_khz;
@ -518,7 +518,11 @@ static int rfbi_init(struct omapfb_device *fbdev)
int r;
rfbi.fbdev = fbdev;
rfbi.base = io_p2v(RFBI_BASE);
rfbi.base = ioremap(RFBI_BASE, SZ_1K);
if (!rfbi.base) {
dev_err(fbdev->dev, "can't ioremap RFBI\n");
return -ENOMEM;
}
if ((r = rfbi_get_clocks()) < 0)
return r;
@ -566,6 +570,7 @@ static void rfbi_cleanup(void)
{
omap_dispc_free_irq();
rfbi_put_clocks();
iounmap(rfbi.base);
}
const struct lcd_ctrl_extif omap2_ext_if = {

View file

@ -574,7 +574,12 @@ static int sossi_init(struct omapfb_device *fbdev)
struct clk *dpll1out_ck;
int r;
sossi.base = (void __iomem *)IO_ADDRESS(OMAP_SOSSI_BASE);
sossi.base = ioremap(OMAP_SOSSI_BASE, SZ_1K);
if (!sossi.base) {
dev_err(fbdev->dev, "can't ioremap SoSSI\n");
return -ENOMEM;
}
sossi.fbdev = fbdev;
spin_lock_init(&sossi.lock);
@ -665,6 +670,7 @@ static void sossi_cleanup(void)
{
omap_lcdc_free_dma_callback();
clk_put(sossi.fck);
iounmap(sossi.base);
}
struct lcd_ctrl_extif omap1_ext_if = {

View file

@ -349,7 +349,7 @@ static int __devexit p9100_remove(struct of_device *op)
return 0;
}
static struct of_device_id p9100_match[] = {
static const struct of_device_id p9100_match[] = {
{
.name = "p9100",
},

View file

@ -50,6 +50,11 @@
#define dbg(fmt, args...) do { } while (0)
#endif
static const int __devinitconst s1d13xxxfb_revisions[] = {
S1D13506_CHIP_REV, /* Rev.4 on HP Jornada 7xx S1D13506 */
S1D13806_CHIP_REV, /* Rev.7 on .. */
};
/*
* Here we define the default struct fb_fix_screeninfo
*/
@ -538,6 +543,7 @@ s1d13xxxfb_probe(struct platform_device *pdev)
struct fb_info *info;
struct s1d13xxxfb_pdata *pdata = NULL;
int ret = 0;
int i;
u8 revision;
dbg("probe called: device is %p\n", pdev);
@ -607,10 +613,19 @@ s1d13xxxfb_probe(struct platform_device *pdev)
goto bail;
}
revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE);
if ((revision >> 2) != S1D_CHIP_REV) {
printk(KERN_INFO PFX "chip not found: %i\n", (revision >> 2));
ret = -ENODEV;
revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) >> 2;
ret = -ENODEV;
for (i = 0; i < ARRAY_SIZE(s1d13xxxfb_revisions); i++) {
if (revision == s1d13xxxfb_revisions[i])
ret = 0;
}
if (!ret)
printk(KERN_INFO PFX "chip revision %i\n", revision);
else {
printk(KERN_INFO PFX "unknown chip revision %i\n", revision);
goto bail;
}

View file

@ -505,7 +505,7 @@ static int __devexit tcx_remove(struct of_device *op)
return 0;
}
static struct of_device_id tcx_match[] = {
static const struct of_device_id tcx_match[] = {
{
.name = "SUNW,tcx",
},

View file

@ -1195,57 +1195,58 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
return -ENOMEM;
default_par = info->par;
info->fix = tdfx_fix;
/* Configure the default fb_fix_screeninfo first */
switch (pdev->device) {
case PCI_DEVICE_ID_3DFX_BANSHEE:
strcpy(tdfx_fix.id, "3Dfx Banshee");
strcpy(info->fix.id, "3Dfx Banshee");
default_par->max_pixclock = BANSHEE_MAX_PIXCLOCK;
break;
case PCI_DEVICE_ID_3DFX_VOODOO3:
strcpy(tdfx_fix.id, "3Dfx Voodoo3");
strcpy(info->fix.id, "3Dfx Voodoo3");
default_par->max_pixclock = VOODOO3_MAX_PIXCLOCK;
break;
case PCI_DEVICE_ID_3DFX_VOODOO5:
strcpy(tdfx_fix.id, "3Dfx Voodoo5");
strcpy(info->fix.id, "3Dfx Voodoo5");
default_par->max_pixclock = VOODOO5_MAX_PIXCLOCK;
break;
}
tdfx_fix.mmio_start = pci_resource_start(pdev, 0);
tdfx_fix.mmio_len = pci_resource_len(pdev, 0);
if (!request_mem_region(tdfx_fix.mmio_start, tdfx_fix.mmio_len,
info->fix.mmio_start = pci_resource_start(pdev, 0);
info->fix.mmio_len = pci_resource_len(pdev, 0);
if (!request_mem_region(info->fix.mmio_start, info->fix.mmio_len,
"tdfx regbase")) {
printk(KERN_ERR "tdfxfb: Can't reserve regbase\n");
goto out_err;
}
default_par->regbase_virt =
ioremap_nocache(tdfx_fix.mmio_start, tdfx_fix.mmio_len);
ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
if (!default_par->regbase_virt) {
printk(KERN_ERR "fb: Can't remap %s register area.\n",
tdfx_fix.id);
info->fix.id);
goto out_err_regbase;
}
tdfx_fix.smem_start = pci_resource_start(pdev, 1);
tdfx_fix.smem_len = do_lfb_size(default_par, pdev->device);
if (!tdfx_fix.smem_len) {
printk(KERN_ERR "fb: Can't count %s memory.\n", tdfx_fix.id);
info->fix.smem_start = pci_resource_start(pdev, 1);
info->fix.smem_len = do_lfb_size(default_par, pdev->device);
if (!info->fix.smem_len) {
printk(KERN_ERR "fb: Can't count %s memory.\n", info->fix.id);
goto out_err_regbase;
}
if (!request_mem_region(tdfx_fix.smem_start,
if (!request_mem_region(info->fix.smem_start,
pci_resource_len(pdev, 1), "tdfx smem")) {
printk(KERN_ERR "tdfxfb: Can't reserve smem\n");
goto out_err_regbase;
}
info->screen_base = ioremap_nocache(tdfx_fix.smem_start,
tdfx_fix.smem_len);
info->screen_base = ioremap_nocache(info->fix.smem_start,
info->fix.smem_len);
if (!info->screen_base) {
printk(KERN_ERR "fb: Can't remap %s framebuffer.\n",
tdfx_fix.id);
info->fix.id);
goto out_err_screenbase;
}
@ -1257,20 +1258,19 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
goto out_err_screenbase;
}
printk(KERN_INFO "fb: %s memory = %dK\n", tdfx_fix.id,
tdfx_fix.smem_len >> 10);
printk(KERN_INFO "fb: %s memory = %dK\n", info->fix.id,
info->fix.smem_len >> 10);
default_par->mtrr_handle = -1;
if (!nomtrr)
default_par->mtrr_handle =
mtrr_add(tdfx_fix.smem_start, tdfx_fix.smem_len,
mtrr_add(info->fix.smem_start, info->fix.smem_len,
MTRR_TYPE_WRCOMB, 1);
tdfx_fix.ypanstep = nopan ? 0 : 1;
tdfx_fix.ywrapstep = nowrap ? 0 : 1;
info->fix.ypanstep = nopan ? 0 : 1;
info->fix.ywrapstep = nowrap ? 0 : 1;
info->fbops = &tdfxfb_ops;
info->fix = tdfx_fix;
info->pseudo_palette = default_par->palette;
info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
#ifdef CONFIG_FB_3DFX_ACCEL
@ -1323,14 +1323,14 @@ out_err_iobase:
out_err_screenbase:
if (info->screen_base)
iounmap(info->screen_base);
release_mem_region(tdfx_fix.smem_start, pci_resource_len(pdev, 1));
release_mem_region(info->fix.smem_start, pci_resource_len(pdev, 1));
out_err_regbase:
/*
* Cleanup after anything that was remapped/allocated.
*/
if (default_par->regbase_virt)
iounmap(default_par->regbase_virt);
release_mem_region(tdfx_fix.mmio_start, tdfx_fix.mmio_len);
release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
out_err:
framebuffer_release(info);
return -ENXIO;

1050
drivers/video/tmiofb.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -516,10 +516,12 @@ static int __devinit uvesafb_vbe_getmodes(struct uvesafb_ktask *task,
err = uvesafb_exec(task);
if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
printk(KERN_ERR "uvesafb: Getting mode info block "
printk(KERN_WARNING "uvesafb: Getting mode info block "
"for mode 0x%x failed (eax=0x%x, err=%d)\n",
*mode, (u32)task->t.regs.eax, err);
return -EINVAL;
mode++;
par->vbe_modes_cnt--;
continue;
}
mib = task->buf;
@ -548,7 +550,10 @@ static int __devinit uvesafb_vbe_getmodes(struct uvesafb_ktask *task,
mib->depth = mib->bits_per_pixel;
}
return 0;
if (par->vbe_modes_cnt > 0)
return 0;
else
return -EINVAL;
}
/*

View file

@ -58,7 +58,6 @@ struct vga16fb_par {
unsigned char ClockingMode; /* Seq-Controller:01h */
} vga_state;
struct vgastate state;
struct mutex open_lock;
unsigned int ref_count;
int palette_blanked, vesa_blanked, mode, isVGA;
u8 misc, pel_msk, vss, clkdiv;
@ -286,7 +285,6 @@ static int vga16fb_open(struct fb_info *info, int user)
{
struct vga16fb_par *par = info->par;
mutex_lock(&par->open_lock);
if (!par->ref_count) {
memset(&par->state, 0, sizeof(struct vgastate));
par->state.flags = VGA_SAVE_FONTS | VGA_SAVE_MODE |
@ -294,7 +292,6 @@ static int vga16fb_open(struct fb_info *info, int user)
save_vga(&par->state);
}
par->ref_count++;
mutex_unlock(&par->open_lock);
return 0;
}
@ -303,15 +300,12 @@ static int vga16fb_release(struct fb_info *info, int user)
{
struct vga16fb_par *par = info->par;
mutex_lock(&par->open_lock);
if (!par->ref_count) {
mutex_unlock(&par->open_lock);
if (!par->ref_count)
return -EINVAL;
}
if (par->ref_count == 1)
restore_vga(&par->state);
par->ref_count--;
mutex_unlock(&par->open_lock);
return 0;
}
@ -1326,7 +1320,6 @@ static int __init vga16fb_probe(struct platform_device *dev)
printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base);
par = info->par;
mutex_init(&par->open_lock);
par->isVGA = screen_info.orig_video_isVGA;
par->palette_blanked = 0;
par->vesa_blanked = 0;

View file

@ -0,0 +1,7 @@
#
# Makefile for the VIA framebuffer driver (for Linux Kernel 2.6)
#
obj-$(CONFIG_FB_VIA) += viafb.o
viafb-y :=viafbdev.o hw.o iface.o via_i2c.o dvi.o lcd.o ioctl.o accel.o via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o

279
drivers/video/via/accel.c Normal file
View file

@ -0,0 +1,279 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "global.h"
void viafb_init_accel(void)
{
viaparinfo->fbmem_free -= CURSOR_SIZE;
viaparinfo->cursor_start = viaparinfo->fbmem_free;
viaparinfo->fbmem_used += CURSOR_SIZE;
/* Reverse 8*1024 memory space for cursor image */
viaparinfo->fbmem_free -= (CURSOR_SIZE + VQ_SIZE);
viaparinfo->VQ_start = viaparinfo->fbmem_free;
viaparinfo->VQ_end = viaparinfo->VQ_start + VQ_SIZE - 1;
viaparinfo->fbmem_used += (CURSOR_SIZE + VQ_SIZE); }
void viafb_init_2d_engine(void)
{
u32 dwVQStartAddr, dwVQEndAddr;
u32 dwVQLen, dwVQStartL, dwVQEndL, dwVQStartEndH;
/* init 2D engine regs to reset 2D engine */
writel(0x0, viaparinfo->io_virt + VIA_REG_GEMODE);
writel(0x0, viaparinfo->io_virt + VIA_REG_SRCPOS);
writel(0x0, viaparinfo->io_virt + VIA_REG_DSTPOS);
writel(0x0, viaparinfo->io_virt + VIA_REG_DIMENSION);
writel(0x0, viaparinfo->io_virt + VIA_REG_PATADDR);
writel(0x0, viaparinfo->io_virt + VIA_REG_FGCOLOR);
writel(0x0, viaparinfo->io_virt + VIA_REG_BGCOLOR);
writel(0x0, viaparinfo->io_virt + VIA_REG_CLIPTL);
writel(0x0, viaparinfo->io_virt + VIA_REG_CLIPBR);
writel(0x0, viaparinfo->io_virt + VIA_REG_OFFSET);
writel(0x0, viaparinfo->io_virt + VIA_REG_KEYCONTROL);
writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
writel(0x0, viaparinfo->io_virt + VIA_REG_DSTBASE);
writel(0x0, viaparinfo->io_virt + VIA_REG_PITCH);
writel(0x0, viaparinfo->io_virt + VIA_REG_MONOPAT1);
/* Init AGP and VQ regs */
switch (viaparinfo->chip_info->gfx_chip_name) {
case UNICHROME_K8M890:
case UNICHROME_P4M900:
writel(0x00100000, viaparinfo->io_virt + VIA_REG_CR_TRANSET);
writel(0x680A0000, viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
writel(0x02000000, viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
break;
default:
writel(0x00100000, viaparinfo->io_virt + VIA_REG_TRANSET);
writel(0x00000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x00333004, viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x60000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x61000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x62000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x63000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x64000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x7D000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0xFE020000, viaparinfo->io_virt + VIA_REG_TRANSET);
writel(0x00000000, viaparinfo->io_virt + VIA_REG_TRANSPACE);
break;
}
if (viaparinfo->VQ_start != 0) {
/* Enable VQ */
dwVQStartAddr = viaparinfo->VQ_start;
dwVQEndAddr = viaparinfo->VQ_end;
dwVQStartL = 0x50000000 | (dwVQStartAddr & 0xFFFFFF);
dwVQEndL = 0x51000000 | (dwVQEndAddr & 0xFFFFFF);
dwVQStartEndH = 0x52000000 |
((dwVQStartAddr & 0xFF000000) >> 24) |
((dwVQEndAddr & 0xFF000000) >> 16);
dwVQLen = 0x53000000 | (VQ_SIZE >> 3);
switch (viaparinfo->chip_info->gfx_chip_name) {
case UNICHROME_K8M890:
case UNICHROME_P4M900:
dwVQStartL |= 0x20000000;
dwVQEndL |= 0x20000000;
dwVQStartEndH |= 0x20000000;
dwVQLen |= 0x20000000;
break;
default:
break;
}
switch (viaparinfo->chip_info->gfx_chip_name) {
case UNICHROME_K8M890:
case UNICHROME_P4M900:
writel(0x00100000,
viaparinfo->io_virt + VIA_REG_CR_TRANSET);
writel(dwVQStartEndH,
viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
writel(dwVQStartL,
viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
writel(dwVQEndL,
viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
writel(dwVQLen,
viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
writel(0x74301001,
viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
writel(0x00000000,
viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
break;
default:
writel(0x00FE0000,
viaparinfo->io_virt + VIA_REG_TRANSET);
writel(0x080003FE,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x0A00027C,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x0B000260,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x0C000274,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x0D000264,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x0E000000,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x0F000020,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x1000027E,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x110002FE,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x200F0060,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x00000006,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x40008C0F,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x44000000,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x45080C04,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x46800408,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(dwVQStartEndH,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(dwVQStartL,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(dwVQEndL,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(dwVQLen,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
break;
}
} else {
/* Disable VQ */
switch (viaparinfo->chip_info->gfx_chip_name) {
case UNICHROME_K8M890:
case UNICHROME_P4M900:
writel(0x00100000,
viaparinfo->io_virt + VIA_REG_CR_TRANSET);
writel(0x74301000,
viaparinfo->io_virt + VIA_REG_CR_TRANSPACE);
break;
default:
writel(0x00FE0000,
viaparinfo->io_virt + VIA_REG_TRANSET);
writel(0x00000004,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x40008C0F,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x44000000,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x45080C04,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
writel(0x46800408,
viaparinfo->io_virt + VIA_REG_TRANSPACE);
break;
}
}
viafb_set_2d_color_depth(viaparinfo->bpp);
writel(0x0, viaparinfo->io_virt + VIA_REG_SRCBASE);
writel(0x0, viaparinfo->io_virt + VIA_REG_DSTBASE);
writel(VIA_PITCH_ENABLE |
(((viaparinfo->hres *
viaparinfo->bpp >> 3) >> 3) | (((viaparinfo->hres *
viaparinfo->
bpp >> 3) >> 3) << 16)),
viaparinfo->io_virt + VIA_REG_PITCH);
}
void viafb_set_2d_color_depth(int bpp)
{
u32 dwGEMode;
dwGEMode = readl(viaparinfo->io_virt + 0x04) & 0xFFFFFCFF;
switch (bpp) {
case 16:
dwGEMode |= VIA_GEM_16bpp;
break;
case 32:
dwGEMode |= VIA_GEM_32bpp;
break;
default:
dwGEMode |= VIA_GEM_8bpp;
break;
}
/* Set BPP and Pitch */
writel(dwGEMode, viaparinfo->io_virt + VIA_REG_GEMODE);
}
void viafb_hw_cursor_init(void)
{
/* Set Cursor Image Base Address */
writel(viaparinfo->cursor_start,
viaparinfo->io_virt + VIA_REG_CURSOR_MODE);
writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_POS);
writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_ORG);
writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_BG);
writel(0x0, viaparinfo->io_virt + VIA_REG_CURSOR_FG);
}
void viafb_show_hw_cursor(struct fb_info *info, int Status)
{
u32 temp;
u32 iga_path = ((struct viafb_par *)(info->par))->iga_path;
temp = readl(viaparinfo->io_virt + VIA_REG_CURSOR_MODE);
switch (Status) {
case HW_Cursor_ON:
temp |= 0x1;
break;
case HW_Cursor_OFF:
temp &= 0xFFFFFFFE;
break;
}
switch (iga_path) {
case IGA2:
temp |= 0x80000000;
break;
case IGA1:
default:
temp &= 0x7FFFFFFF;
}
writel(temp, viaparinfo->io_virt + VIA_REG_CURSOR_MODE);
}
int viafb_wait_engine_idle(void)
{
int loop = 0;
while (!(readl(viaparinfo->io_virt + VIA_REG_STATUS) &
VIA_VR_QUEUE_BUSY) && (loop++ < MAXLOOP))
cpu_relax();
while ((readl(viaparinfo->io_virt + VIA_REG_STATUS) &
(VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) &&
(loop++ < MAXLOOP))
cpu_relax();
return loop >= MAXLOOP;
}

169
drivers/video/via/accel.h Normal file
View file

@ -0,0 +1,169 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __ACCEL_H__
#define __ACCEL_H__
#define FB_ACCEL_VIA_UNICHROME 50
/* MMIO Base Address Definition */
#define MMIO_VGABASE 0x8000
#define MMIO_CR_READ (MMIO_VGABASE + 0x3D4)
#define MMIO_CR_WRITE (MMIO_VGABASE + 0x3D5)
#define MMIO_SR_READ (MMIO_VGABASE + 0x3C4)
#define MMIO_SR_WRITE (MMIO_VGABASE + 0x3C5)
/* HW Cursor Status Define */
#define HW_Cursor_ON 0
#define HW_Cursor_OFF 1
#define CURSOR_SIZE (8 * 1024)
#define VQ_SIZE (256 * 1024)
#define VIA_MMIO_BLTBASE 0x200000
#define VIA_MMIO_BLTSIZE 0x200000
/* Defines for 2D registers */
#define VIA_REG_GECMD 0x000
#define VIA_REG_GEMODE 0x004
#define VIA_REG_SRCPOS 0x008
#define VIA_REG_DSTPOS 0x00C
/* width and height */
#define VIA_REG_DIMENSION 0x010
#define VIA_REG_PATADDR 0x014
#define VIA_REG_FGCOLOR 0x018
#define VIA_REG_BGCOLOR 0x01C
/* top and left of clipping */
#define VIA_REG_CLIPTL 0x020
/* bottom and right of clipping */
#define VIA_REG_CLIPBR 0x024
#define VIA_REG_OFFSET 0x028
/* color key control */
#define VIA_REG_KEYCONTROL 0x02C
#define VIA_REG_SRCBASE 0x030
#define VIA_REG_DSTBASE 0x034
/* pitch of src and dst */
#define VIA_REG_PITCH 0x038
#define VIA_REG_MONOPAT0 0x03C
#define VIA_REG_MONOPAT1 0x040
/* from 0x100 to 0x1ff */
#define VIA_REG_COLORPAT 0x100
/* VIA_REG_PITCH(0x38): Pitch Setting */
#define VIA_PITCH_ENABLE 0x80000000
/* defines for VIA HW cursor registers */
#define VIA_REG_CURSOR_MODE 0x2D0
#define VIA_REG_CURSOR_POS 0x2D4
#define VIA_REG_CURSOR_ORG 0x2D8
#define VIA_REG_CURSOR_BG 0x2DC
#define VIA_REG_CURSOR_FG 0x2E0
/* VIA_REG_GEMODE(0x04): GE mode */
#define VIA_GEM_8bpp 0x00000000
#define VIA_GEM_16bpp 0x00000100
#define VIA_GEM_32bpp 0x00000300
/* VIA_REG_GECMD(0x00): 2D Engine Command */
#define VIA_GEC_NOOP 0x00000000
#define VIA_GEC_BLT 0x00000001
#define VIA_GEC_LINE 0x00000005
/* Rotate Command */
#define VIA_GEC_ROT 0x00000008
#define VIA_GEC_SRC_XY 0x00000000
#define VIA_GEC_SRC_LINEAR 0x00000010
#define VIA_GEC_DST_XY 0x00000000
#define VIA_GEC_DST_LINRAT 0x00000020
#define VIA_GEC_SRC_FB 0x00000000
#define VIA_GEC_SRC_SYS 0x00000040
#define VIA_GEC_DST_FB 0x00000000
#define VIA_GEC_DST_SYS 0x00000080
/* source is mono */
#define VIA_GEC_SRC_MONO 0x00000100
/* pattern is mono */
#define VIA_GEC_PAT_MONO 0x00000200
/* mono src is opaque */
#define VIA_GEC_MSRC_OPAQUE 0x00000000
/* mono src is transparent */
#define VIA_GEC_MSRC_TRANS 0x00000400
/* pattern is in frame buffer */
#define VIA_GEC_PAT_FB 0x00000000
/* pattern is from reg setting */
#define VIA_GEC_PAT_REG 0x00000800
#define VIA_GEC_CLIP_DISABLE 0x00000000
#define VIA_GEC_CLIP_ENABLE 0x00001000
#define VIA_GEC_FIXCOLOR_PAT 0x00002000
#define VIA_GEC_INCX 0x00000000
#define VIA_GEC_DECY 0x00004000
#define VIA_GEC_INCY 0x00000000
#define VIA_GEC_DECX 0x00008000
/* mono pattern is opaque */
#define VIA_GEC_MPAT_OPAQUE 0x00000000
/* mono pattern is transparent */
#define VIA_GEC_MPAT_TRANS 0x00010000
#define VIA_GEC_MONO_UNPACK 0x00000000
#define VIA_GEC_MONO_PACK 0x00020000
#define VIA_GEC_MONO_DWORD 0x00000000
#define VIA_GEC_MONO_WORD 0x00040000
#define VIA_GEC_MONO_BYTE 0x00080000
#define VIA_GEC_LASTPIXEL_ON 0x00000000
#define VIA_GEC_LASTPIXEL_OFF 0x00100000
#define VIA_GEC_X_MAJOR 0x00000000
#define VIA_GEC_Y_MAJOR 0x00200000
#define VIA_GEC_QUICK_START 0x00800000
/* defines for VIA 3D registers */
#define VIA_REG_STATUS 0x400
#define VIA_REG_CR_TRANSET 0x41C
#define VIA_REG_CR_TRANSPACE 0x420
#define VIA_REG_TRANSET 0x43C
#define VIA_REG_TRANSPACE 0x440
/* VIA_REG_STATUS(0x400): Engine Status */
/* Command Regulator is busy */
#define VIA_CMD_RGTR_BUSY 0x00000080
/* 2D Engine is busy */
#define VIA_2D_ENG_BUSY 0x00000002
/* 3D Engine is busy */
#define VIA_3D_ENG_BUSY 0x00000001
/* Virtual Queue is busy */
#define VIA_VR_QUEUE_BUSY 0x00020000
#define MAXLOOP 0xFFFFFF
void viafb_init_accel(void);
void viafb_init_2d_engine(void);
void set_2d_color_depth(int);
void viafb_hw_cursor_init(void);
void viafb_show_hw_cursor(struct fb_info *info, int Status); int
viafb_wait_engine_idle(void); void viafb_set_2d_color_depth(int bpp);
#endif /* __ACCEL_H__ */

190
drivers/video/via/chip.h Normal file
View file

@ -0,0 +1,190 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __CHIP_H__
#define __CHIP_H__
#include "global.h"
/***************************************/
/* Definition Graphic Chip Information */
/***************************************/
#define PCI_VIA_VENDOR_ID 0x1106
/* Define VIA Graphic Chip Name */
#define UNICHROME_CLE266 1
#define UNICHROME_CLE266_DID 0x3122
#define CLE266_REVISION_AX 0x0A
#define CLE266_REVISION_CX 0x0C
#define UNICHROME_K400 2
#define UNICHROME_K400_DID 0x7205
#define UNICHROME_K800 3
#define UNICHROME_K800_DID 0x3108
#define UNICHROME_PM800 4
#define UNICHROME_PM800_DID 0x3118
#define UNICHROME_CN700 5
#define UNICHROME_CN700_DID 0x3344
#define UNICHROME_CX700 6
#define UNICHROME_CX700_DID 0x3157
#define CX700_REVISION_700 0x0
#define CX700_REVISION_700M 0x1
#define CX700_REVISION_700M2 0x2
#define UNICHROME_CN750 7
#define UNICHROME_CN750_DID 0x3225
#define UNICHROME_K8M890 8
#define UNICHROME_K8M890_DID 0x3230
#define UNICHROME_P4M890 9
#define UNICHROME_P4M890_DID 0x3343
#define UNICHROME_P4M900 10
#define UNICHROME_P4M900_DID 0x3371
#define UNICHROME_VX800 11
#define UNICHROME_VX800_DID 0x1122
/**************************************************/
/* Definition TMDS Trasmitter Information */
/**************************************************/
/* Definition TMDS Trasmitter Index */
#define NON_TMDS_TRANSMITTER 0x00
#define VT1632_TMDS 0x01
#define INTEGRATED_TMDS 0x42
/* Definition TMDS Trasmitter I2C Slave Address */
#define VT1632_TMDS_I2C_ADDR 0x10
/**************************************************/
/* Definition LVDS Trasmitter Information */
/**************************************************/
/* Definition LVDS Trasmitter Index */
#define NON_LVDS_TRANSMITTER 0x00
#define VT1631_LVDS 0x01
#define VT1636_LVDS 0x0E
#define INTEGRATED_LVDS 0x41
/* Definition Digital Transmitter Mode */
#define TX_DATA_12_BITS 0x01
#define TX_DATA_24_BITS 0x02
#define TX_DATA_DDR_MODE 0x04
#define TX_DATA_SDR_MODE 0x08
/* Definition LVDS Trasmitter I2C Slave Address */
#define VT1631_LVDS_I2C_ADDR 0x70
#define VT3271_LVDS_I2C_ADDR 0x80
#define VT1636_LVDS_I2C_ADDR 0x80
struct tmds_chip_information {
int tmds_chip_name;
int tmds_chip_slave_addr;
int dvi_panel_id;
int data_mode;
int output_interface;
int i2c_port;
int device_type;
};
struct lvds_chip_information {
int lvds_chip_name;
int lvds_chip_slave_addr;
int data_mode;
int output_interface;
int i2c_port;
};
struct chip_information {
int gfx_chip_name;
int gfx_chip_revision;
int chip_on_slot;
struct tmds_chip_information tmds_chip_info;
struct lvds_chip_information lvds_chip_info;
struct lvds_chip_information lvds_chip_info2;
};
struct crt_setting_information {
int iga_path;
int h_active;
int v_active;
int bpp;
int refresh_rate;
};
struct tmds_setting_information {
int iga_path;
int h_active;
int v_active;
int bpp;
int refresh_rate;
int get_dvi_size_method;
int max_pixel_clock;
int dvi_panel_size;
int dvi_panel_hres;
int dvi_panel_vres;
int native_size;
};
struct lvds_setting_information {
int iga_path;
int h_active;
int v_active;
int bpp;
int refresh_rate;
int get_lcd_size_method;
int lcd_panel_id;
int lcd_panel_size;
int lcd_panel_hres;
int lcd_panel_vres;
int display_method;
int device_lcd_dualedge;
int LCDDithering;
int lcd_mode;
u32 vclk; /*panel mode clock value */
};
struct GFX_DPA_SETTING {
int ClkRangeIndex;
u8 DVP0; /* CR96[3:0] */
u8 DVP0DataDri_S1; /* SR2A[5] */
u8 DVP0DataDri_S; /* SR1B[1] */
u8 DVP0ClockDri_S1; /* SR2A[4] */
u8 DVP0ClockDri_S; /* SR1E[2] */
u8 DVP1; /* CR9B[3:0] */
u8 DVP1Driving; /* SR65[3:0], Data and Clock driving */
u8 DFPHigh; /* CR97[3:0] */
u8 DFPLow; /* CR99[3:0] */
};
struct VT1636_DPA_SETTING {
int PanelSizeID;
u8 CLK_SEL_ST1;
u8 CLK_SEL_ST2;
};
#endif /* __CHIP_H__ */

41
drivers/video/via/debug.h Normal file
View file

@ -0,0 +1,41 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __DEBUG_H__
#define __DEBUG_H__
#ifndef VIAFB_DEBUG
#define VIAFB_DEBUG 0
#endif
#if VIAFB_DEBUG
#define DEBUG_MSG(f, a...) printk(f, ## a)
#else
#define DEBUG_MSG(f, a...)
#endif
#define VIAFB_WARN 0
#if VIAFB_WARN
#define WARN_MSG(f, a...) printk(f, ## a)
#else
#define WARN_MSG(f, a...)
#endif
#endif /* __DEBUG_H__ */

682
drivers/video/via/dvi.c Normal file
View file

@ -0,0 +1,682 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "global.h"
static void tmds_register_write(int index, u8 data);
static int tmds_register_read(int index);
static int tmds_register_read_bytes(int index, u8 *buff, int buff_len);
static int check_reduce_blanking_mode(int mode_index,
int refresh_rate);
static int dvi_get_panel_size_from_DDCv1(void);
static int dvi_get_panel_size_from_DDCv2(void);
static unsigned char dvi_get_panel_info(void);
static int viafb_dvi_query_EDID(void);
static int check_tmds_chip(int device_id_subaddr, int device_id)
{
if (tmds_register_read(device_id_subaddr) == device_id)
return OK;
else
return FAIL;
}
void viafb_init_dvi_size(void)
{
DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n");
DEBUG_MSG(KERN_INFO
"viaparinfo->tmds_setting_info->get_dvi_size_method %d\n",
viaparinfo->tmds_setting_info->get_dvi_size_method);
switch (viaparinfo->tmds_setting_info->get_dvi_size_method) {
case GET_DVI_SIZE_BY_SYSTEM_BIOS:
break;
case GET_DVI_SZIE_BY_HW_STRAPPING:
break;
case GET_DVI_SIZE_BY_VGA_BIOS:
default:
dvi_get_panel_info();
break;
}
return;
}
int viafb_tmds_trasmitter_identify(void)
{
unsigned char sr2a = 0, sr1e = 0, sr3e = 0;
/* Turn on ouputting pad */
switch (viaparinfo->chip_info->gfx_chip_name) {
case UNICHROME_K8M890:
/*=* DFP Low Pad on *=*/
sr2a = viafb_read_reg(VIASR, SR2A);
viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
break;
case UNICHROME_P4M900:
case UNICHROME_P4M890:
/* DFP Low Pad on */
sr2a = viafb_read_reg(VIASR, SR2A);
viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
/* DVP0 Pad on */
sr1e = viafb_read_reg(VIASR, SR1E);
viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT6 + BIT7);
break;
default:
/* DVP0/DVP1 Pad on */
sr1e = viafb_read_reg(VIASR, SR1E);
viafb_write_reg_mask(SR1E, VIASR, 0xF0, BIT4 +
BIT5 + BIT6 + BIT7);
/* SR3E[1]Multi-function selection:
0 = Emulate I2C and DDC bus by GPIO2/3/4. */
sr3e = viafb_read_reg(VIASR, SR3E);
viafb_write_reg_mask(SR3E, VIASR, 0x0, BIT5);
break;
}
/* Check for VT1632: */
viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = VT1632_TMDS;
viaparinfo->chip_info->
tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR;
viaparinfo->chip_info->tmds_chip_info.i2c_port = I2CPORTINDEX;
if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID) != FAIL) {
/*
* Currently only support 12bits,dual edge,add 24bits mode later
*/
tmds_register_write(0x08, 0x3b);
DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n");
DEBUG_MSG(KERN_INFO "\n %2d",
viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
DEBUG_MSG(KERN_INFO "\n %2d",
viaparinfo->chip_info->tmds_chip_info.i2c_port);
return OK;
} else {
viaparinfo->chip_info->tmds_chip_info.i2c_port = GPIOPORTINDEX;
if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)
!= FAIL) {
tmds_register_write(0x08, 0x3b);
DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n");
DEBUG_MSG(KERN_INFO "\n %2d",
viaparinfo->chip_info->
tmds_chip_info.tmds_chip_name);
DEBUG_MSG(KERN_INFO "\n %2d",
viaparinfo->chip_info->
tmds_chip_info.i2c_port);
return OK;
}
}
viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = INTEGRATED_TMDS;
if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) &&
((viafb_display_hardware_layout == HW_LAYOUT_DVI_ONLY) ||
(viafb_display_hardware_layout == HW_LAYOUT_LCD_DVI))) {
DEBUG_MSG(KERN_INFO "\n Integrated TMDS ! \n");
return OK;
}
switch (viaparinfo->chip_info->gfx_chip_name) {
case UNICHROME_K8M890:
viafb_write_reg(SR2A, VIASR, sr2a);
break;
case UNICHROME_P4M900:
case UNICHROME_P4M890:
viafb_write_reg(SR2A, VIASR, sr2a);
viafb_write_reg(SR1E, VIASR, sr1e);
break;
default:
viafb_write_reg(SR1E, VIASR, sr1e);
viafb_write_reg(SR3E, VIASR, sr3e);
break;
}
viaparinfo->chip_info->
tmds_chip_info.tmds_chip_name = NON_TMDS_TRANSMITTER;
viaparinfo->chip_info->tmds_chip_info.
tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR;
return FAIL;
}
static void tmds_register_write(int index, u8 data)
{
viaparinfo->i2c_stuff.i2c_port =
viaparinfo->chip_info->tmds_chip_info.i2c_port;
viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info.
tmds_chip_slave_addr, index,
data);
}
static int tmds_register_read(int index)
{
u8 data;
viaparinfo->i2c_stuff.i2c_port =
viaparinfo->chip_info->tmds_chip_info.i2c_port;
viafb_i2c_readbyte((u8) viaparinfo->chip_info->
tmds_chip_info.tmds_chip_slave_addr,
(u8) index, &data);
return data;
}
static int tmds_register_read_bytes(int index, u8 *buff, int buff_len)
{
viaparinfo->i2c_stuff.i2c_port =
viaparinfo->chip_info->tmds_chip_info.i2c_port;
viafb_i2c_readbytes((u8) viaparinfo->chip_info->tmds_chip_info.
tmds_chip_slave_addr, (u8) index, buff, buff_len);
return 0;
}
static int check_reduce_blanking_mode(int mode_index,
int refresh_rate)
{
if (refresh_rate != 60)
return false;
switch (mode_index) {
/* Following modes have reduce blanking mode. */
case VIA_RES_1360X768:
case VIA_RES_1400X1050:
case VIA_RES_1440X900:
case VIA_RES_1600X900:
case VIA_RES_1680X1050:
case VIA_RES_1920X1080:
case VIA_RES_1920X1200:
break;
default:
DEBUG_MSG(KERN_INFO
"This dvi mode %d have no reduce blanking mode!\n",
mode_index);
return false;
}
return true;
}
/* DVI Set Mode */
void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga)
{
struct VideoModeTable *videoMode = NULL;
struct crt_mode_table *pDviTiming;
unsigned long desirePixelClock, maxPixelClock;
int status = 0;
videoMode = viafb_get_modetbl_pointer(video_index);
pDviTiming = videoMode->crtc;
desirePixelClock = pDviTiming->clk / 1000000;
maxPixelClock = (unsigned long)viaparinfo->
tmds_setting_info->max_pixel_clock;
DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n");
if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) {
/*Check if reduce-blanking mode is exist */
status =
check_reduce_blanking_mode(video_index,
pDviTiming->refresh_rate);
if (status) {
video_index += 100; /*Use reduce-blanking mode */
videoMode = viafb_get_modetbl_pointer(video_index);
pDviTiming = videoMode->crtc;
DEBUG_MSG(KERN_INFO
"DVI use reduce blanking mode %d!!\n",
video_index);
}
}
viafb_fill_crtc_timing(pDviTiming, video_index, mode_bpp / 8, set_iga);
viafb_set_output_path(DEVICE_DVI, set_iga,
viaparinfo->chip_info->tmds_chip_info.output_interface);
}
/* Sense DVI Connector */
int viafb_dvi_sense(void)
{
u8 RegSR1E = 0, RegSR3E = 0, RegCR6B = 0, RegCR91 = 0,
RegCR93 = 0, RegCR9B = 0, data;
int ret = false;
DEBUG_MSG(KERN_INFO "viafb_dvi_sense!!\n");
if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
/* DI1 Pad on */
RegSR1E = viafb_read_reg(VIASR, SR1E);
viafb_write_reg(SR1E, VIASR, RegSR1E | 0x30);
/* CR6B[0]VCK Input Selection: 1 = External clock. */
RegCR6B = viafb_read_reg(VIACR, CR6B);
viafb_write_reg(CR6B, VIACR, RegCR6B | 0x08);
/* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off
[0] Software Control Power Sequence */
RegCR91 = viafb_read_reg(VIACR, CR91);
viafb_write_reg(CR91, VIACR, 0x1D);
/* CR93[7] DI1 Data Source Selection: 1 = DSP2.
CR93[5] DI1 Clock Source: 1 = internal.
CR93[4] DI1 Clock Polarity.
CR93[3:1] DI1 Clock Adjust. CR93[0] DI1 enable */
RegCR93 = viafb_read_reg(VIACR, CR93);
viafb_write_reg(CR93, VIACR, 0x01);
} else {
/* DVP0/DVP1 Pad on */
RegSR1E = viafb_read_reg(VIASR, SR1E);
viafb_write_reg(SR1E, VIASR, RegSR1E | 0xF0);
/* SR3E[1]Multi-function selection:
0 = Emulate I2C and DDC bus by GPIO2/3/4. */
RegSR3E = viafb_read_reg(VIASR, SR3E);
viafb_write_reg(SR3E, VIASR, RegSR3E & (~0x20));
/* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off
[0] Software Control Power Sequence */
RegCR91 = viafb_read_reg(VIACR, CR91);
viafb_write_reg(CR91, VIACR, 0x1D);
/*CR9B[4] DVP1 Data Source Selection: 1 = From secondary
display.CR9B[2:0] DVP1 Clock Adjust */
RegCR9B = viafb_read_reg(VIACR, CR9B);
viafb_write_reg(CR9B, VIACR, 0x01);
}
data = (u8) tmds_register_read(0x09);
if (data & 0x04)
ret = true;
if (ret == false) {
if (viafb_dvi_query_EDID())
ret = true;
}
/* Restore status */
viafb_write_reg(SR1E, VIASR, RegSR1E);
viafb_write_reg(CR91, VIACR, RegCR91);
if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
viafb_write_reg(CR6B, VIACR, RegCR6B);
viafb_write_reg(CR93, VIACR, RegCR93);
} else {
viafb_write_reg(SR3E, VIASR, RegSR3E);
viafb_write_reg(CR9B, VIACR, RegCR9B);
}
return ret;
}
/* Query Flat Panel's EDID Table Version Through DVI Connector */
static int viafb_dvi_query_EDID(void)
{
u8 data0, data1;
int restore;
DEBUG_MSG(KERN_INFO "viafb_dvi_query_EDID!!\n");
restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr;
viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0;
data0 = (u8) tmds_register_read(0x00);
data1 = (u8) tmds_register_read(0x01);
if ((data0 == 0) && (data1 == 0xFF)) {
viaparinfo->chip_info->
tmds_chip_info.tmds_chip_slave_addr = restore;
return EDID_VERSION_1; /* Found EDID1 Table */
}
data0 = (u8) tmds_register_read(0x00);
viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore;
if (data0 == 0x20)
return EDID_VERSION_2; /* Found EDID2 Table */
else
return false;
}
/*
*
* int dvi_get_panel_size_from_DDCv1(void)
*
* - Get Panel Size Using EDID1 Table
*
* Return Type: int
*
*/
static int dvi_get_panel_size_from_DDCv1(void)
{
int i, max_h = 0, max_v = 0, tmp, restore;
unsigned char rData;
unsigned char EDID_DATA[18];
DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n");
restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr;
viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0;
rData = tmds_register_read(0x23);
if (rData & 0x3C)
max_h = 640;
if (rData & 0xC0)
max_h = 720;
if (rData & 0x03)
max_h = 800;
rData = tmds_register_read(0x24);
if (rData & 0xC0)
max_h = 800;
if (rData & 0x1E)
max_h = 1024;
if (rData & 0x01)
max_h = 1280;
for (i = 0x25; i < 0x6D; i++) {
switch (i) {
case 0x26:
case 0x28:
case 0x2A:
case 0x2C:
case 0x2E:
case 0x30:
case 0x32:
case 0x34:
rData = tmds_register_read(i);
if (rData == 1)
break;
/* data = (data + 31) * 8 */
tmp = (rData + 31) << 3;
if (tmp > max_h)
max_h = tmp;
break;
case 0x36:
case 0x48:
case 0x5A:
case 0x6C:
tmds_register_read_bytes(i, EDID_DATA, 10);
if (!(EDID_DATA[0] || EDID_DATA[1])) {
/* The first two byte must be zero. */
if (EDID_DATA[3] == 0xFD) {
/* To get max pixel clock. */
viaparinfo->tmds_setting_info->
max_pixel_clock = EDID_DATA[9] * 10;
}
}
break;
default:
break;
}
}
switch (max_h) {
case 640:
viaparinfo->tmds_setting_info->dvi_panel_size =
VIA_RES_640X480;
break;
case 800:
viaparinfo->tmds_setting_info->dvi_panel_size =
VIA_RES_800X600;
break;
case 1024:
viaparinfo->tmds_setting_info->dvi_panel_size =
VIA_RES_1024X768;
break;
case 1280:
viaparinfo->tmds_setting_info->dvi_panel_size =
VIA_RES_1280X1024;
break;
case 1400:
viaparinfo->tmds_setting_info->dvi_panel_size =
VIA_RES_1400X1050;
break;
case 1440:
viaparinfo->tmds_setting_info->dvi_panel_size =
VIA_RES_1440X1050;
break;
case 1600:
viaparinfo->tmds_setting_info->dvi_panel_size =
VIA_RES_1600X1200;
break;
case 1920:
if (max_v == 1200) {
viaparinfo->tmds_setting_info->dvi_panel_size =
VIA_RES_1920X1200;
} else {
viaparinfo->tmds_setting_info->dvi_panel_size =
VIA_RES_1920X1080;
}
break;
default:
viaparinfo->tmds_setting_info->dvi_panel_size =
VIA_RES_1024X768;
DEBUG_MSG(KERN_INFO "Unknow panel size max resolution = %d !\
set default panel size.\n", max_h);
break;
}
DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n",
viaparinfo->tmds_setting_info->max_pixel_clock);
viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore;
return viaparinfo->tmds_setting_info->dvi_panel_size;
}
/*
*
* int dvi_get_panel_size_from_DDCv2(void)
*
* - Get Panel Size Using EDID2 Table
*
* Return Type: int
*
*/
static int dvi_get_panel_size_from_DDCv2(void)
{
int HSize = 0, restore;
unsigned char R_Buffer[2];
DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv2 \n");
restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr;
viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA2;
/* Horizontal: 0x76, 0x77 */
tmds_register_read_bytes(0x76, R_Buffer, 2);
HSize = R_Buffer[0];
HSize += R_Buffer[1] << 8;
switch (HSize) {
case 640:
viaparinfo->tmds_setting_info->dvi_panel_size =
VIA_RES_640X480;
break;
case 800:
viaparinfo->tmds_setting_info->dvi_panel_size =
VIA_RES_800X600;
break;
case 1024:
viaparinfo->tmds_setting_info->dvi_panel_size =
VIA_RES_1024X768;
break;
case 1280:
viaparinfo->tmds_setting_info->dvi_panel_size =
VIA_RES_1280X1024;
break;
case 1400:
viaparinfo->tmds_setting_info->dvi_panel_size =
VIA_RES_1400X1050;
break;
case 1440:
viaparinfo->tmds_setting_info->dvi_panel_size =
VIA_RES_1440X1050;
break;
case 1600:
viaparinfo->tmds_setting_info->dvi_panel_size =
VIA_RES_1600X1200;
break;
default:
viaparinfo->tmds_setting_info->dvi_panel_size =
VIA_RES_1024X768;
DEBUG_MSG(KERN_INFO "Unknow panel size max resolution = %d!\
set default panel size.\n", HSize);
break;
}
viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore;
return viaparinfo->tmds_setting_info->dvi_panel_size;
}
/*
*
* unsigned char dvi_get_panel_info(void)
*
* - Get Panel Size
*
* Return Type: unsigned char
*/
static unsigned char dvi_get_panel_info(void)
{
unsigned char dvipanelsize;
DEBUG_MSG(KERN_INFO "dvi_get_panel_info! \n");
viafb_dvi_sense();
switch (viafb_dvi_query_EDID()) {
case 1:
dvi_get_panel_size_from_DDCv1();
break;
case 2:
dvi_get_panel_size_from_DDCv2();
break;
default:
break;
}
DEBUG_MSG(KERN_INFO "dvi panel size is %2d \n",
viaparinfo->tmds_setting_info->dvi_panel_size);
dvipanelsize = (unsigned char)(viaparinfo->
tmds_setting_info->dvi_panel_size);
return dvipanelsize;
}
/* If Disable DVI, turn off pad */
void viafb_dvi_disable(void)
{
if (viaparinfo->chip_info->
tmds_chip_info.output_interface == INTERFACE_DVP0)
viafb_write_reg(SR1E, VIASR,
viafb_read_reg(VIASR, SR1E) & (~0xC0));
if (viaparinfo->chip_info->
tmds_chip_info.output_interface == INTERFACE_DVP1)
viafb_write_reg(SR1E, VIASR,
viafb_read_reg(VIASR, SR1E) & (~0x30));
if (viaparinfo->chip_info->
tmds_chip_info.output_interface == INTERFACE_DFP_HIGH)
viafb_write_reg(SR2A, VIASR,
viafb_read_reg(VIASR, SR2A) & (~0x0C));
if (viaparinfo->chip_info->
tmds_chip_info.output_interface == INTERFACE_DFP_LOW)
viafb_write_reg(SR2A, VIASR,
viafb_read_reg(VIASR, SR2A) & (~0x03));
if (viaparinfo->chip_info->
tmds_chip_info.output_interface == INTERFACE_TMDS)
/* Turn off TMDS power. */
viafb_write_reg(CRD2, VIACR,
viafb_read_reg(VIACR, CRD2) | 0x08);
}
/* If Enable DVI, turn off pad */
void viafb_dvi_enable(void)
{
u8 data;
if (viaparinfo->chip_info->
tmds_chip_info.output_interface == INTERFACE_DVP0) {
viafb_write_reg(SR1E, VIASR,
viafb_read_reg(VIASR, SR1E) | 0xC0);
if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
tmds_register_write(0x88, 0x3b);
else
/*clear CR91[5] to direct on display period
in the secondary diplay path */
viafb_write_reg(CR91, VIACR,
viafb_read_reg(VIACR, CR91) & 0xDF);
}
if (viaparinfo->chip_info->
tmds_chip_info.output_interface == INTERFACE_DVP1) {
viafb_write_reg(SR1E, VIASR,
viafb_read_reg(VIASR, SR1E) | 0x30);
/*fix dvi cann't be enabled with MB VT5718C4 - Al Zhang */
if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
tmds_register_write(0x88, 0x3b);
} else {
/*clear CR91[5] to direct on display period
in the secondary diplay path */
viafb_write_reg(CR91, VIACR,
viafb_read_reg(VIACR, CR91) & 0xDF);
}
/*fix DVI cannot enable on EPIA-M board */
if (viafb_platform_epia_dvi == 1) {
viafb_write_reg_mask(CR91, VIACR, 0x1f, 0x1f);
viafb_write_reg_mask(CR88, VIACR, 0x00, BIT6 + BIT0);
if (viafb_bus_width == 24) {
if (viafb_device_lcd_dualedge == 1)
data = 0x3F;
else
data = 0x37;
viafb_i2c_writebyte(viaparinfo->chip_info->
tmds_chip_info.
tmds_chip_slave_addr,
0x08, data);
}
}
}
if (viaparinfo->chip_info->
tmds_chip_info.output_interface == INTERFACE_DFP_HIGH) {
viafb_write_reg(SR2A, VIASR,
viafb_read_reg(VIASR, SR2A) | 0x0C);
viafb_write_reg(CR91, VIACR,
viafb_read_reg(VIACR, CR91) & 0xDF);
}
if (viaparinfo->chip_info->
tmds_chip_info.output_interface == INTERFACE_DFP_LOW) {
viafb_write_reg(SR2A, VIASR,
viafb_read_reg(VIASR, SR2A) | 0x03);
viafb_write_reg(CR91, VIACR,
viafb_read_reg(VIACR, CR91) & 0xDF);
}
if (viaparinfo->chip_info->
tmds_chip_info.output_interface == INTERFACE_TMDS) {
/* Turn on Display period in the panel path. */
viafb_write_reg_mask(CR91, VIACR, 0, BIT7);
/* Turn on TMDS power. */
viafb_write_reg_mask(CRD2, VIACR, 0, BIT3);
}
}

64
drivers/video/via/dvi.h Normal file
View file

@ -0,0 +1,64 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __DVI_H__
#define __DVI_H__
/*Definition TMDS Device ID register*/
#define VT1632_DEVICE_ID_REG 0x02
#define VT1632_DEVICE_ID 0x92
#define GET_DVI_SIZE_BY_SYSTEM_BIOS 0x01
#define GET_DVI_SIZE_BY_VGA_BIOS 0x02
#define GET_DVI_SZIE_BY_HW_STRAPPING 0x03
/* Definition DVI Panel ID*/
/* Resolution: 640x480, Channel: single, Dithering: Enable */
#define DVI_PANEL_ID0_640X480 0x00
/* Resolution: 800x600, Channel: single, Dithering: Enable */
#define DVI_PANEL_ID1_800x600 0x01
/* Resolution: 1024x768, Channel: single, Dithering: Enable */
#define DVI_PANEL_ID1_1024x768 0x02
/* Resolution: 1280x768, Channel: single, Dithering: Enable */
#define DVI_PANEL_ID1_1280x768 0x03
/* Resolution: 1280x1024, Channel: dual, Dithering: Enable */
#define DVI_PANEL_ID1_1280x1024 0x04
/* Resolution: 1400x1050, Channel: dual, Dithering: Enable */
#define DVI_PANEL_ID1_1400x1050 0x05
/* Resolution: 1600x1200, Channel: dual, Dithering: Enable */
#define DVI_PANEL_ID1_1600x1200 0x06
/* Define the version of EDID*/
#define EDID_VERSION_1 1
#define EDID_VERSION_2 2
#define DEV_CONNECT_DVI 0x01
#define DEV_CONNECT_HDMI 0x02
struct VideoModeTable *viafb_get_cea_mode_tbl_pointer(int Index);
int viafb_dvi_sense(void);
void viafb_dvi_disable(void);
void viafb_dvi_enable(void);
int viafb_tmds_trasmitter_identify(void);
void viafb_init_dvi_size(void);
void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga);
#endif /* __DVI_H__ */

View file

@ -0,0 +1,60 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "global.h"
int viafb_platform_epia_dvi = STATE_OFF;
int viafb_device_lcd_dualedge = STATE_OFF;
int viafb_bus_width = 12;
int viafb_display_hardware_layout = HW_LAYOUT_LCD_DVI;
int viafb_memsize;
int viafb_DeviceStatus = CRT_Device;
int viafb_hotplug;
int viafb_refresh = 60;
int viafb_refresh1 = 60;
int viafb_lcd_dsp_method = LCD_EXPANDSION;
int viafb_lcd_mode = LCD_OPENLDI;
int viafb_bpp = 32;
int viafb_bpp1 = 32;
int viafb_accel = 1;
int viafb_CRT_ON = 1;
int viafb_DVI_ON;
int viafb_LCD_ON ;
int viafb_LCD2_ON;
int viafb_SAMM_ON;
int viafb_dual_fb;
int viafb_hotplug_Xres = 640;
int viafb_hotplug_Yres = 480;
int viafb_hotplug_bpp = 32;
int viafb_hotplug_refresh = 60;
unsigned int viafb_second_offset;
int viafb_second_size;
int viafb_primary_dev = None_Device;
void __iomem *viafb_FB_MM;
unsigned int viafb_second_xres = 640;
unsigned int viafb_second_yres = 480;
unsigned int viafb_second_virtual_xres;
unsigned int viafb_second_virtual_yres;
int viafb_lcd_panel_id = LCD_PANEL_ID_MAXIMUM + 1;
struct fb_cursor viacursor;
struct fb_info *viafbinfo;
struct fb_info *viafbinfo1;
struct viafb_par *viaparinfo;
struct viafb_par *viaparinfo1;

View file

@ -0,0 +1,90 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GLOBAL_H__
#define __GLOBAL_H__
#include <linux/fb.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/console.h>
#include <linux/timer.h>
#include "debug.h"
#include "iface.h"
#include "viafbdev.h"
#include "chip.h"
#include "debug.h"
#include "accel.h"
#include "share.h"
#include "dvi.h"
#include "viamode.h"
#include "via_i2c.h"
#include "hw.h"
#include "lcd.h"
#include "ioctl.h"
#include "viamode.h"
#include "via_utility.h"
#include "vt1636.h"
#include "tblDPASetting.h"
#include "tbl1636.h"
#include "viafbdev.h"
/* External struct*/
extern int viafb_platform_epia_dvi;
extern int viafb_device_lcd_dualedge;
extern int viafb_bus_width;
extern int viafb_display_hardware_layout;
extern struct offset offset_reg;
extern struct viafb_par *viaparinfo;
extern struct viafb_par *viaparinfo1;
extern struct fb_info *viafbinfo;
extern struct fb_info *viafbinfo1;
extern int viafb_DeviceStatus;
extern int viafb_refresh;
extern int viafb_refresh1;
extern int viafb_lcd_dsp_method;
extern int viafb_lcd_mode;
extern int viafb_bpp;
extern int viafb_bpp1;
extern int viafb_CRT_ON;
extern int viafb_hotplug_Xres;
extern int viafb_hotplug_Yres;
extern int viafb_hotplug_bpp;
extern int viafb_hotplug_refresh;
extern int viafb_primary_dev;
extern void __iomem *viafb_FB_MM;
extern struct fb_cursor viacursor;
extern unsigned int viafb_second_xres;
extern unsigned int viafb_second_yres;
extern int viafb_lcd_panel_id;
#endif /* __GLOBAL_H__ */

2865
drivers/video/via/hw.c Normal file

File diff suppressed because it is too large Load diff

933
drivers/video/via/hw.h Normal file
View file

@ -0,0 +1,933 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __HW_H__
#define __HW_H__
#include "global.h"
/***************************************************
* Definition IGA1 Design Method of CRTC Registers *
****************************************************/
#define IGA1_HOR_TOTAL_FORMULA(x) (((x)/8)-5)
#define IGA1_HOR_ADDR_FORMULA(x) (((x)/8)-1)
#define IGA1_HOR_BLANK_START_FORMULA(x) (((x)/8)-1)
#define IGA1_HOR_BLANK_END_FORMULA(x, y) (((x+y)/8)-1)
#define IGA1_HOR_SYNC_START_FORMULA(x) ((x)/8)
#define IGA1_HOR_SYNC_END_FORMULA(x, y) ((x+y)/8)
#define IGA1_VER_TOTAL_FORMULA(x) ((x)-2)
#define IGA1_VER_ADDR_FORMULA(x) ((x)-1)
#define IGA1_VER_BLANK_START_FORMULA(x) ((x)-1)
#define IGA1_VER_BLANK_END_FORMULA(x, y) ((x+y)-1)
#define IGA1_VER_SYNC_START_FORMULA(x) ((x)-1)
#define IGA1_VER_SYNC_END_FORMULA(x, y) ((x+y)-1)
/***************************************************
** Definition IGA2 Design Method of CRTC Registers *
****************************************************/
#define IGA2_HOR_TOTAL_FORMULA(x) ((x)-1)
#define IGA2_HOR_ADDR_FORMULA(x) ((x)-1)
#define IGA2_HOR_BLANK_START_FORMULA(x) ((x)-1)
#define IGA2_HOR_BLANK_END_FORMULA(x, y) ((x+y)-1)
#define IGA2_HOR_SYNC_START_FORMULA(x) ((x)-1)
#define IGA2_HOR_SYNC_END_FORMULA(x, y) ((x+y)-1)
#define IGA2_VER_TOTAL_FORMULA(x) ((x)-1)
#define IGA2_VER_ADDR_FORMULA(x) ((x)-1)
#define IGA2_VER_BLANK_START_FORMULA(x) ((x)-1)
#define IGA2_VER_BLANK_END_FORMULA(x, y) ((x+y)-1)
#define IGA2_VER_SYNC_START_FORMULA(x) ((x)-1)
#define IGA2_VER_SYNC_END_FORMULA(x, y) ((x+y)-1)
/**********************************************************/
/* Definition IGA2 Design Method of CRTC Shadow Registers */
/**********************************************************/
#define IGA2_HOR_TOTAL_SHADOW_FORMULA(x) ((x/8)-5)
#define IGA2_HOR_BLANK_END_SHADOW_FORMULA(x, y) (((x+y)/8)-1)
#define IGA2_VER_TOTAL_SHADOW_FORMULA(x) ((x)-2)
#define IGA2_VER_ADDR_SHADOW_FORMULA(x) ((x)-1)
#define IGA2_VER_BLANK_START_SHADOW_FORMULA(x) ((x)-1)
#define IGA2_VER_BLANK_END_SHADOW_FORMULA(x, y) ((x+y)-1)
#define IGA2_VER_SYNC_START_SHADOW_FORMULA(x) (x)
#define IGA2_VER_SYNC_END_SHADOW_FORMULA(x, y) (x+y)
/* Define Register Number for IGA1 CRTC Timing */
/* location: {CR00,0,7},{CR36,3,3} */
#define IGA1_HOR_TOTAL_REG_NUM 2
/* location: {CR01,0,7} */
#define IGA1_HOR_ADDR_REG_NUM 1
/* location: {CR02,0,7} */
#define IGA1_HOR_BLANK_START_REG_NUM 1
/* location: {CR03,0,4},{CR05,7,7},{CR33,5,5} */
#define IGA1_HOR_BLANK_END_REG_NUM 3
/* location: {CR04,0,7},{CR33,4,4} */
#define IGA1_HOR_SYNC_START_REG_NUM 2
/* location: {CR05,0,4} */
#define IGA1_HOR_SYNC_END_REG_NUM 1
/* location: {CR06,0,7},{CR07,0,0},{CR07,5,5},{CR35,0,0} */
#define IGA1_VER_TOTAL_REG_NUM 4
/* location: {CR12,0,7},{CR07,1,1},{CR07,6,6},{CR35,2,2} */
#define IGA1_VER_ADDR_REG_NUM 4
/* location: {CR15,0,7},{CR07,3,3},{CR09,5,5},{CR35,3,3} */
#define IGA1_VER_BLANK_START_REG_NUM 4
/* location: {CR16,0,7} */
#define IGA1_VER_BLANK_END_REG_NUM 1
/* location: {CR10,0,7},{CR07,2,2},{CR07,7,7},{CR35,1,1} */
#define IGA1_VER_SYNC_START_REG_NUM 4
/* location: {CR11,0,3} */
#define IGA1_VER_SYNC_END_REG_NUM 1
/* Define Register Number for IGA2 Shadow CRTC Timing */
/* location: {CR6D,0,7},{CR71,3,3} */
#define IGA2_SHADOW_HOR_TOTAL_REG_NUM 2
/* location: {CR6E,0,7} */
#define IGA2_SHADOW_HOR_BLANK_END_REG_NUM 1
/* location: {CR6F,0,7},{CR71,0,2} */
#define IGA2_SHADOW_VER_TOTAL_REG_NUM 2
/* location: {CR70,0,7},{CR71,4,6} */
#define IGA2_SHADOW_VER_ADDR_REG_NUM 2
/* location: {CR72,0,7},{CR74,4,6} */
#define IGA2_SHADOW_VER_BLANK_START_REG_NUM 2
/* location: {CR73,0,7},{CR74,0,2} */
#define IGA2_SHADOW_VER_BLANK_END_REG_NUM 2
/* location: {CR75,0,7},{CR76,4,6} */
#define IGA2_SHADOW_VER_SYNC_START_REG_NUM 2
/* location: {CR76,0,3} */
#define IGA2_SHADOW_VER_SYNC_END_REG_NUM 1
/* Define Register Number for IGA2 CRTC Timing */
/* location: {CR50,0,7},{CR55,0,3} */
#define IGA2_HOR_TOTAL_REG_NUM 2
/* location: {CR51,0,7},{CR55,4,6} */
#define IGA2_HOR_ADDR_REG_NUM 2
/* location: {CR52,0,7},{CR54,0,2} */
#define IGA2_HOR_BLANK_START_REG_NUM 2
/* location: CLE266: {CR53,0,7},{CR54,3,5} => CLE266's CR5D[6]
is reserved, so it may have problem to set 1600x1200 on IGA2. */
/* Others: {CR53,0,7},{CR54,3,5},{CR5D,6,6} */
#define IGA2_HOR_BLANK_END_REG_NUM 3
/* location: {CR56,0,7},{CR54,6,7},{CR5C,7,7} */
/* VT3314 and Later: {CR56,0,7},{CR54,6,7},{CR5C,7,7}, {CR5D,7,7} */
#define IGA2_HOR_SYNC_START_REG_NUM 4
/* location: {CR57,0,7},{CR5C,6,6} */
#define IGA2_HOR_SYNC_END_REG_NUM 2
/* location: {CR58,0,7},{CR5D,0,2} */
#define IGA2_VER_TOTAL_REG_NUM 2
/* location: {CR59,0,7},{CR5D,3,5} */
#define IGA2_VER_ADDR_REG_NUM 2
/* location: {CR5A,0,7},{CR5C,0,2} */
#define IGA2_VER_BLANK_START_REG_NUM 2
/* location: {CR5E,0,7},{CR5C,3,5} */
#define IGA2_VER_BLANK_END_REG_NUM 2
/* location: {CR5E,0,7},{CR5F,5,7} */
#define IGA2_VER_SYNC_START_REG_NUM 2
/* location: {CR5F,0,4} */
#define IGA2_VER_SYNC_END_REG_NUM 1
/* Define Offset and Fetch Count Register*/
/* location: {CR13,0,7},{CR35,5,7} */
#define IGA1_OFFSET_REG_NUM 2
/* 8 bytes alignment. */
#define IGA1_OFFSER_ALIGN_BYTE 8
/* x: H resolution, y: color depth */
#define IGA1_OFFSET_FORMULA(x, y) ((x*y)/IGA1_OFFSER_ALIGN_BYTE)
/* location: {SR1C,0,7},{SR1D,0,1} */
#define IGA1_FETCH_COUNT_REG_NUM 2
/* 16 bytes alignment. */
#define IGA1_FETCH_COUNT_ALIGN_BYTE 16
/* x: H resolution, y: color depth */
#define IGA1_FETCH_COUNT_PATCH_VALUE 4
#define IGA1_FETCH_COUNT_FORMULA(x, y) \
(((x*y)/IGA1_FETCH_COUNT_ALIGN_BYTE) + IGA1_FETCH_COUNT_PATCH_VALUE)
/* location: {CR66,0,7},{CR67,0,1} */
#define IGA2_OFFSET_REG_NUM 2
#define IGA2_OFFSET_ALIGN_BYTE 8
/* x: H resolution, y: color depth */
#define IGA2_OFFSET_FORMULA(x, y) ((x*y)/IGA2_OFFSET_ALIGN_BYTE)
/* location: {CR65,0,7},{CR67,2,3} */
#define IGA2_FETCH_COUNT_REG_NUM 2
#define IGA2_FETCH_COUNT_ALIGN_BYTE 16
#define IGA2_FETCH_COUNT_PATCH_VALUE 0
#define IGA2_FETCH_COUNT_FORMULA(x, y) \
(((x*y)/IGA2_FETCH_COUNT_ALIGN_BYTE) + IGA2_FETCH_COUNT_PATCH_VALUE)
/* Staring Address*/
/* location: {CR0C,0,7},{CR0D,0,7},{CR34,0,7},{CR48,0,1} */
#define IGA1_STARTING_ADDR_REG_NUM 4
/* location: {CR62,1,7},{CR63,0,7},{CR64,0,7} */
#define IGA2_STARTING_ADDR_REG_NUM 3
/* Define Display OFFSET*/
/* These value are by HW suggested value*/
/* location: {SR17,0,7} */
#define K800_IGA1_FIFO_MAX_DEPTH 384
/* location: {SR16,0,5},{SR16,7,7} */
#define K800_IGA1_FIFO_THRESHOLD 328
/* location: {SR18,0,5},{SR18,7,7} */
#define K800_IGA1_FIFO_HIGH_THRESHOLD 296
/* location: {SR22,0,4}. (128/4) =64, K800 must be set zero, */
/* because HW only 5 bits */
#define K800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 0
/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
#define K800_IGA2_FIFO_MAX_DEPTH 384
/* location: {CR68,0,3},{CR95,4,6} */
#define K800_IGA2_FIFO_THRESHOLD 328
/* location: {CR92,0,3},{CR95,0,2} */
#define K800_IGA2_FIFO_HIGH_THRESHOLD 296
/* location: {CR94,0,6} */
#define K800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128
/* location: {SR17,0,7} */
#define P880_IGA1_FIFO_MAX_DEPTH 192
/* location: {SR16,0,5},{SR16,7,7} */
#define P880_IGA1_FIFO_THRESHOLD 128
/* location: {SR18,0,5},{SR18,7,7} */
#define P880_IGA1_FIFO_HIGH_THRESHOLD 64
/* location: {SR22,0,4}. (128/4) =64, K800 must be set zero, */
/* because HW only 5 bits */
#define P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 0
/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
#define P880_IGA2_FIFO_MAX_DEPTH 96
/* location: {CR68,0,3},{CR95,4,6} */
#define P880_IGA2_FIFO_THRESHOLD 64
/* location: {CR92,0,3},{CR95,0,2} */
#define P880_IGA2_FIFO_HIGH_THRESHOLD 32
/* location: {CR94,0,6} */
#define P880_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128
/* VT3314 chipset*/
/* location: {SR17,0,7} */
#define CN700_IGA1_FIFO_MAX_DEPTH 96
/* location: {SR16,0,5},{SR16,7,7} */
#define CN700_IGA1_FIFO_THRESHOLD 80
/* location: {SR18,0,5},{SR18,7,7} */
#define CN700_IGA1_FIFO_HIGH_THRESHOLD 64
/* location: {SR22,0,4}. (128/4) =64, P800 must be set zero,
because HW only 5 bits */
#define CN700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 0
/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
#define CN700_IGA2_FIFO_MAX_DEPTH 96
/* location: {CR68,0,3},{CR95,4,6} */
#define CN700_IGA2_FIFO_THRESHOLD 80
/* location: {CR92,0,3},{CR95,0,2} */
#define CN700_IGA2_FIFO_HIGH_THRESHOLD 32
/* location: {CR94,0,6} */
#define CN700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128
/* For VT3324, these values are suggested by HW */
/* location: {SR17,0,7} */
#define CX700_IGA1_FIFO_MAX_DEPTH 192
/* location: {SR16,0,5},{SR16,7,7} */
#define CX700_IGA1_FIFO_THRESHOLD 128
/* location: {SR18,0,5},{SR18,7,7} */
#define CX700_IGA1_FIFO_HIGH_THRESHOLD 128
/* location: {SR22,0,4} */
#define CX700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 124
/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
#define CX700_IGA2_FIFO_MAX_DEPTH 96
/* location: {CR68,0,3},{CR95,4,6} */
#define CX700_IGA2_FIFO_THRESHOLD 64
/* location: {CR92,0,3},{CR95,0,2} */
#define CX700_IGA2_FIFO_HIGH_THRESHOLD 32
/* location: {CR94,0,6} */
#define CX700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128
/* VT3336 chipset*/
/* location: {SR17,0,7} */
#define K8M890_IGA1_FIFO_MAX_DEPTH 360
/* location: {SR16,0,5},{SR16,7,7} */
#define K8M890_IGA1_FIFO_THRESHOLD 328
/* location: {SR18,0,5},{SR18,7,7} */
#define K8M890_IGA1_FIFO_HIGH_THRESHOLD 296
/* location: {SR22,0,4}. */
#define K8M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 124
/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
#define K8M890_IGA2_FIFO_MAX_DEPTH 360
/* location: {CR68,0,3},{CR95,4,6} */
#define K8M890_IGA2_FIFO_THRESHOLD 328
/* location: {CR92,0,3},{CR95,0,2} */
#define K8M890_IGA2_FIFO_HIGH_THRESHOLD 296
/* location: {CR94,0,6} */
#define K8M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 124
/* VT3327 chipset*/
/* location: {SR17,0,7} */
#define P4M890_IGA1_FIFO_MAX_DEPTH 96
/* location: {SR16,0,5},{SR16,7,7} */
#define P4M890_IGA1_FIFO_THRESHOLD 76
/* location: {SR18,0,5},{SR18,7,7} */
#define P4M890_IGA1_FIFO_HIGH_THRESHOLD 64
/* location: {SR22,0,4}. (32/4) =8 */
#define P4M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 32
/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
#define P4M890_IGA2_FIFO_MAX_DEPTH 96
/* location: {CR68,0,3},{CR95,4,6} */
#define P4M890_IGA2_FIFO_THRESHOLD 76
/* location: {CR92,0,3},{CR95,0,2} */
#define P4M890_IGA2_FIFO_HIGH_THRESHOLD 64
/* location: {CR94,0,6} */
#define P4M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 32
/* VT3364 chipset*/
/* location: {SR17,0,7} */
#define P4M900_IGA1_FIFO_MAX_DEPTH 96
/* location: {SR16,0,5},{SR16,7,7} */
#define P4M900_IGA1_FIFO_THRESHOLD 76
/* location: {SR18,0,5},{SR18,7,7} */
#define P4M900_IGA1_FIFO_HIGH_THRESHOLD 76
/* location: {SR22,0,4}. */
#define P4M900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 32
/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
#define P4M900_IGA2_FIFO_MAX_DEPTH 96
/* location: {CR68,0,3},{CR95,4,6} */
#define P4M900_IGA2_FIFO_THRESHOLD 76
/* location: {CR92,0,3},{CR95,0,2} */
#define P4M900_IGA2_FIFO_HIGH_THRESHOLD 76
/* location: {CR94,0,6} */
#define P4M900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 32
/* For VT3353, these values are suggested by HW */
/* location: {SR17,0,7} */
#define VX800_IGA1_FIFO_MAX_DEPTH 192
/* location: {SR16,0,5},{SR16,7,7} */
#define VX800_IGA1_FIFO_THRESHOLD 152
/* location: {SR18,0,5},{SR18,7,7} */
#define VX800_IGA1_FIFO_HIGH_THRESHOLD 152
/* location: {SR22,0,4} */
#define VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 64
/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
#define VX800_IGA2_FIFO_MAX_DEPTH 96
/* location: {CR68,0,3},{CR95,4,6} */
#define VX800_IGA2_FIFO_THRESHOLD 64
/* location: {CR92,0,3},{CR95,0,2} */
#define VX800_IGA2_FIFO_HIGH_THRESHOLD 32
/* location: {CR94,0,6} */
#define VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128
#define IGA1_FIFO_DEPTH_SELECT_REG_NUM 1
#define IGA1_FIFO_THRESHOLD_REG_NUM 2
#define IGA1_FIFO_HIGH_THRESHOLD_REG_NUM 2
#define IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM 1
#define IGA2_FIFO_DEPTH_SELECT_REG_NUM 3
#define IGA2_FIFO_THRESHOLD_REG_NUM 2
#define IGA2_FIFO_HIGH_THRESHOLD_REG_NUM 2
#define IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM 1
#define IGA1_FIFO_DEPTH_SELECT_FORMULA(x) ((x/2)-1)
#define IGA1_FIFO_THRESHOLD_FORMULA(x) (x/4)
#define IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA(x) (x/4)
#define IGA1_FIFO_HIGH_THRESHOLD_FORMULA(x) (x/4)
#define IGA2_FIFO_DEPTH_SELECT_FORMULA(x) (((x/2)/4)-1)
#define IGA2_FIFO_THRESHOLD_FORMULA(x) (x/4)
#define IGA2_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA(x) (x/4)
#define IGA2_FIFO_HIGH_THRESHOLD_FORMULA(x) (x/4)
/************************************************************************/
/* LCD Timing */
/************************************************************************/
/* 500 ms = 500000 us */
#define LCD_POWER_SEQ_TD0 500000
/* 50 ms = 50000 us */
#define LCD_POWER_SEQ_TD1 50000
/* 0 us */
#define LCD_POWER_SEQ_TD2 0
/* 210 ms = 210000 us */
#define LCD_POWER_SEQ_TD3 210000
/* 2^10 * (1/14.31818M) = 71.475 us (K400.revA) */
#define CLE266_POWER_SEQ_UNIT 71
/* 2^11 * (1/14.31818M) = 142.95 us (K400.revB) */
#define K800_POWER_SEQ_UNIT 142
/* 2^13 * (1/14.31818M) = 572.1 us */
#define P880_POWER_SEQ_UNIT 572
#define CLE266_POWER_SEQ_FORMULA(x) ((x)/CLE266_POWER_SEQ_UNIT)
#define K800_POWER_SEQ_FORMULA(x) ((x)/K800_POWER_SEQ_UNIT)
#define P880_POWER_SEQ_FORMULA(x) ((x)/P880_POWER_SEQ_UNIT)
/* location: {CR8B,0,7},{CR8F,0,3} */
#define LCD_POWER_SEQ_TD0_REG_NUM 2
/* location: {CR8C,0,7},{CR8F,4,7} */
#define LCD_POWER_SEQ_TD1_REG_NUM 2
/* location: {CR8D,0,7},{CR90,0,3} */
#define LCD_POWER_SEQ_TD2_REG_NUM 2
/* location: {CR8E,0,7},{CR90,4,7} */
#define LCD_POWER_SEQ_TD3_REG_NUM 2
/* LCD Scaling factor*/
/* x: indicate setting horizontal size*/
/* y: indicate panel horizontal size*/
/* Horizontal scaling factor 10 bits (2^10) */
#define CLE266_LCD_HOR_SCF_FORMULA(x, y) (((x-1)*1024)/(y-1))
/* Vertical scaling factor 10 bits (2^10) */
#define CLE266_LCD_VER_SCF_FORMULA(x, y) (((x-1)*1024)/(y-1))
/* Horizontal scaling factor 10 bits (2^12) */
#define K800_LCD_HOR_SCF_FORMULA(x, y) (((x-1)*4096)/(y-1))
/* Vertical scaling factor 10 bits (2^11) */
#define K800_LCD_VER_SCF_FORMULA(x, y) (((x-1)*2048)/(y-1))
/* location: {CR9F,0,1},{CR77,0,7},{CR79,4,5} */
#define LCD_HOR_SCALING_FACTOR_REG_NUM 3
/* location: {CR79,3,3},{CR78,0,7},{CR79,6,7} */
#define LCD_VER_SCALING_FACTOR_REG_NUM 3
/* location: {CR77,0,7},{CR79,4,5} */
#define LCD_HOR_SCALING_FACTOR_REG_NUM_CLE 2
/* location: {CR78,0,7},{CR79,6,7} */
#define LCD_VER_SCALING_FACTOR_REG_NUM_CLE 2
/************************************************
***** Define IGA1 Display Timing *****
************************************************/
struct io_register {
u8 io_addr;
u8 start_bit;
u8 end_bit;
};
/* IGA1 Horizontal Total */
struct iga1_hor_total {
int reg_num;
struct io_register reg[IGA1_HOR_TOTAL_REG_NUM];
};
/* IGA1 Horizontal Addressable Video */
struct iga1_hor_addr {
int reg_num;
struct io_register reg[IGA1_HOR_ADDR_REG_NUM];
};
/* IGA1 Horizontal Blank Start */
struct iga1_hor_blank_start {
int reg_num;
struct io_register reg[IGA1_HOR_BLANK_START_REG_NUM];
};
/* IGA1 Horizontal Blank End */
struct iga1_hor_blank_end {
int reg_num;
struct io_register reg[IGA1_HOR_BLANK_END_REG_NUM];
};
/* IGA1 Horizontal Sync Start */
struct iga1_hor_sync_start {
int reg_num;
struct io_register reg[IGA1_HOR_SYNC_START_REG_NUM];
};
/* IGA1 Horizontal Sync End */
struct iga1_hor_sync_end {
int reg_num;
struct io_register reg[IGA1_HOR_SYNC_END_REG_NUM];
};
/* IGA1 Vertical Total */
struct iga1_ver_total {
int reg_num;
struct io_register reg[IGA1_VER_TOTAL_REG_NUM];
};
/* IGA1 Vertical Addressable Video */
struct iga1_ver_addr {
int reg_num;
struct io_register reg[IGA1_VER_ADDR_REG_NUM];
};
/* IGA1 Vertical Blank Start */
struct iga1_ver_blank_start {
int reg_num;
struct io_register reg[IGA1_VER_BLANK_START_REG_NUM];
};
/* IGA1 Vertical Blank End */
struct iga1_ver_blank_end {
int reg_num;
struct io_register reg[IGA1_VER_BLANK_END_REG_NUM];
};
/* IGA1 Vertical Sync Start */
struct iga1_ver_sync_start {
int reg_num;
struct io_register reg[IGA1_VER_SYNC_START_REG_NUM];
};
/* IGA1 Vertical Sync End */
struct iga1_ver_sync_end {
int reg_num;
struct io_register reg[IGA1_VER_SYNC_END_REG_NUM];
};
/*****************************************************
** Define IGA2 Shadow Display Timing ****
*****************************************************/
/* IGA2 Shadow Horizontal Total */
struct iga2_shadow_hor_total {
int reg_num;
struct io_register reg[IGA2_SHADOW_HOR_TOTAL_REG_NUM];
};
/* IGA2 Shadow Horizontal Blank End */
struct iga2_shadow_hor_blank_end {
int reg_num;
struct io_register reg[IGA2_SHADOW_HOR_BLANK_END_REG_NUM];
};
/* IGA2 Shadow Vertical Total */
struct iga2_shadow_ver_total {
int reg_num;
struct io_register reg[IGA2_SHADOW_VER_TOTAL_REG_NUM];
};
/* IGA2 Shadow Vertical Addressable Video */
struct iga2_shadow_ver_addr {
int reg_num;
struct io_register reg[IGA2_SHADOW_VER_ADDR_REG_NUM];
};
/* IGA2 Shadow Vertical Blank Start */
struct iga2_shadow_ver_blank_start {
int reg_num;
struct io_register reg[IGA2_SHADOW_VER_BLANK_START_REG_NUM];
};
/* IGA2 Shadow Vertical Blank End */
struct iga2_shadow_ver_blank_end {
int reg_num;
struct io_register reg[IGA2_SHADOW_VER_BLANK_END_REG_NUM];
};
/* IGA2 Shadow Vertical Sync Start */
struct iga2_shadow_ver_sync_start {
int reg_num;
struct io_register reg[IGA2_SHADOW_VER_SYNC_START_REG_NUM];
};
/* IGA2 Shadow Vertical Sync End */
struct iga2_shadow_ver_sync_end {
int reg_num;
struct io_register reg[IGA2_SHADOW_VER_SYNC_END_REG_NUM];
};
/*****************************************************
** Define IGA2 Display Timing ****
******************************************************/
/* IGA2 Horizontal Total */
struct iga2_hor_total {
int reg_num;
struct io_register reg[IGA2_HOR_TOTAL_REG_NUM];
};
/* IGA2 Horizontal Addressable Video */
struct iga2_hor_addr {
int reg_num;
struct io_register reg[IGA2_HOR_ADDR_REG_NUM];
};
/* IGA2 Horizontal Blank Start */
struct iga2_hor_blank_start {
int reg_num;
struct io_register reg[IGA2_HOR_BLANK_START_REG_NUM];
};
/* IGA2 Horizontal Blank End */
struct iga2_hor_blank_end {
int reg_num;
struct io_register reg[IGA2_HOR_BLANK_END_REG_NUM];
};
/* IGA2 Horizontal Sync Start */
struct iga2_hor_sync_start {
int reg_num;
struct io_register reg[IGA2_HOR_SYNC_START_REG_NUM];
};
/* IGA2 Horizontal Sync End */
struct iga2_hor_sync_end {
int reg_num;
struct io_register reg[IGA2_HOR_SYNC_END_REG_NUM];
};
/* IGA2 Vertical Total */
struct iga2_ver_total {
int reg_num;
struct io_register reg[IGA2_VER_TOTAL_REG_NUM];
};
/* IGA2 Vertical Addressable Video */
struct iga2_ver_addr {
int reg_num;
struct io_register reg[IGA2_VER_ADDR_REG_NUM];
};
/* IGA2 Vertical Blank Start */
struct iga2_ver_blank_start {
int reg_num;
struct io_register reg[IGA2_VER_BLANK_START_REG_NUM];
};
/* IGA2 Vertical Blank End */
struct iga2_ver_blank_end {
int reg_num;
struct io_register reg[IGA2_VER_BLANK_END_REG_NUM];
};
/* IGA2 Vertical Sync Start */
struct iga2_ver_sync_start {
int reg_num;
struct io_register reg[IGA2_VER_SYNC_START_REG_NUM];
};
/* IGA2 Vertical Sync End */
struct iga2_ver_sync_end {
int reg_num;
struct io_register reg[IGA2_VER_SYNC_END_REG_NUM];
};
/* IGA1 Offset Register */
struct iga1_offset {
int reg_num;
struct io_register reg[IGA1_OFFSET_REG_NUM];
};
/* IGA2 Offset Register */
struct iga2_offset {
int reg_num;
struct io_register reg[IGA2_OFFSET_REG_NUM];
};
struct offset {
struct iga1_offset iga1_offset_reg;
struct iga2_offset iga2_offset_reg;
};
/* IGA1 Fetch Count Register */
struct iga1_fetch_count {
int reg_num;
struct io_register reg[IGA1_FETCH_COUNT_REG_NUM];
};
/* IGA2 Fetch Count Register */
struct iga2_fetch_count {
int reg_num;
struct io_register reg[IGA2_FETCH_COUNT_REG_NUM];
};
struct fetch_count {
struct iga1_fetch_count iga1_fetch_count_reg;
struct iga2_fetch_count iga2_fetch_count_reg;
};
/* Starting Address Register */
struct iga1_starting_addr {
int reg_num;
struct io_register reg[IGA1_STARTING_ADDR_REG_NUM];
};
struct iga2_starting_addr {
int reg_num;
struct io_register reg[IGA2_STARTING_ADDR_REG_NUM];
};
struct starting_addr {
struct iga1_starting_addr iga1_starting_addr_reg;
struct iga2_starting_addr iga2_starting_addr_reg;
};
/* LCD Power Sequence Timer */
struct lcd_pwd_seq_td0 {
int reg_num;
struct io_register reg[LCD_POWER_SEQ_TD0_REG_NUM];
};
struct lcd_pwd_seq_td1 {
int reg_num;
struct io_register reg[LCD_POWER_SEQ_TD1_REG_NUM];
};
struct lcd_pwd_seq_td2 {
int reg_num;
struct io_register reg[LCD_POWER_SEQ_TD2_REG_NUM];
};
struct lcd_pwd_seq_td3 {
int reg_num;
struct io_register reg[LCD_POWER_SEQ_TD3_REG_NUM];
};
struct _lcd_pwd_seq_timer {
struct lcd_pwd_seq_td0 td0;
struct lcd_pwd_seq_td1 td1;
struct lcd_pwd_seq_td2 td2;
struct lcd_pwd_seq_td3 td3;
};
/* LCD Scaling Factor */
struct _lcd_hor_scaling_factor {
int reg_num;
struct io_register reg[LCD_HOR_SCALING_FACTOR_REG_NUM];
};
struct _lcd_ver_scaling_factor {
int reg_num;
struct io_register reg[LCD_VER_SCALING_FACTOR_REG_NUM];
};
struct _lcd_scaling_factor {
struct _lcd_hor_scaling_factor lcd_hor_scaling_factor;
struct _lcd_ver_scaling_factor lcd_ver_scaling_factor;
};
struct pll_map {
u32 clk;
u32 cle266_pll;
u32 k800_pll;
u32 cx700_pll;
};
struct rgbLUT {
u8 red;
u8 green;
u8 blue;
};
struct lcd_pwd_seq_timer {
u16 td0;
u16 td1;
u16 td2;
u16 td3;
};
/* Display FIFO Relation Registers*/
struct iga1_fifo_depth_select {
int reg_num;
struct io_register reg[IGA1_FIFO_DEPTH_SELECT_REG_NUM];
};
struct iga1_fifo_threshold_select {
int reg_num;
struct io_register reg[IGA1_FIFO_THRESHOLD_REG_NUM];
};
struct iga1_fifo_high_threshold_select {
int reg_num;
struct io_register reg[IGA1_FIFO_HIGH_THRESHOLD_REG_NUM];
};
struct iga1_display_queue_expire_num {
int reg_num;
struct io_register reg[IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM];
};
struct iga2_fifo_depth_select {
int reg_num;
struct io_register reg[IGA2_FIFO_DEPTH_SELECT_REG_NUM];
};
struct iga2_fifo_threshold_select {
int reg_num;
struct io_register reg[IGA2_FIFO_THRESHOLD_REG_NUM];
};
struct iga2_fifo_high_threshold_select {
int reg_num;
struct io_register reg[IGA2_FIFO_HIGH_THRESHOLD_REG_NUM];
};
struct iga2_display_queue_expire_num {
int reg_num;
struct io_register reg[IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM];
};
struct fifo_depth_select {
struct iga1_fifo_depth_select iga1_fifo_depth_select_reg;
struct iga2_fifo_depth_select iga2_fifo_depth_select_reg;
};
struct fifo_threshold_select {
struct iga1_fifo_threshold_select iga1_fifo_threshold_select_reg;
struct iga2_fifo_threshold_select iga2_fifo_threshold_select_reg;
};
struct fifo_high_threshold_select {
struct iga1_fifo_high_threshold_select
iga1_fifo_high_threshold_select_reg;
struct iga2_fifo_high_threshold_select
iga2_fifo_high_threshold_select_reg;
};
struct display_queue_expire_num {
struct iga1_display_queue_expire_num
iga1_display_queue_expire_num_reg;
struct iga2_display_queue_expire_num
iga2_display_queue_expire_num_reg;
};
struct iga1_crtc_timing {
struct iga1_hor_total hor_total;
struct iga1_hor_addr hor_addr;
struct iga1_hor_blank_start hor_blank_start;
struct iga1_hor_blank_end hor_blank_end;
struct iga1_hor_sync_start hor_sync_start;
struct iga1_hor_sync_end hor_sync_end;
struct iga1_ver_total ver_total;
struct iga1_ver_addr ver_addr;
struct iga1_ver_blank_start ver_blank_start;
struct iga1_ver_blank_end ver_blank_end;
struct iga1_ver_sync_start ver_sync_start;
struct iga1_ver_sync_end ver_sync_end;
};
struct iga2_shadow_crtc_timing {
struct iga2_shadow_hor_total hor_total_shadow;
struct iga2_shadow_hor_blank_end hor_blank_end_shadow;
struct iga2_shadow_ver_total ver_total_shadow;
struct iga2_shadow_ver_addr ver_addr_shadow;
struct iga2_shadow_ver_blank_start ver_blank_start_shadow;
struct iga2_shadow_ver_blank_end ver_blank_end_shadow;
struct iga2_shadow_ver_sync_start ver_sync_start_shadow;
struct iga2_shadow_ver_sync_end ver_sync_end_shadow;
};
struct iga2_crtc_timing {
struct iga2_hor_total hor_total;
struct iga2_hor_addr hor_addr;
struct iga2_hor_blank_start hor_blank_start;
struct iga2_hor_blank_end hor_blank_end;
struct iga2_hor_sync_start hor_sync_start;
struct iga2_hor_sync_end hor_sync_end;
struct iga2_ver_total ver_total;
struct iga2_ver_addr ver_addr;
struct iga2_ver_blank_start ver_blank_start;
struct iga2_ver_blank_end ver_blank_end;
struct iga2_ver_sync_start ver_sync_start;
struct iga2_ver_sync_end ver_sync_end;
};
/* device ID */
#define CLE266 0x3123
#define KM400 0x3205
#define CN400_FUNCTION2 0x2259
#define CN400_FUNCTION3 0x3259
/* support VT3314 chipset */
#define CN700_FUNCTION2 0x2314
#define CN700_FUNCTION3 0x3208
/* VT3324 chipset */
#define CX700_FUNCTION2 0x2324
#define CX700_FUNCTION3 0x3324
/* VT3204 chipset*/
#define KM800_FUNCTION3 0x3204
/* VT3336 chipset*/
#define KM890_FUNCTION3 0x3336
/* VT3327 chipset*/
#define P4M890_FUNCTION3 0x3327
/* VT3293 chipset*/
#define CN750_FUNCTION3 0x3208
/* VT3364 chipset*/
#define P4M900_FUNCTION3 0x3364
/* VT3353 chipset*/
#define VX800_FUNCTION3 0x3353
#define NUM_TOTAL_PLL_TABLE ARRAY_SIZE(pll_value)
struct IODATA {
u8 Index;
u8 Mask;
u8 Data;
};
struct pci_device_id_info {
u32 vendor;
u32 device;
u32 chip_index;
};
extern unsigned int viafb_second_virtual_xres;
extern unsigned int viafb_second_offset;
extern int viafb_second_size;
extern int viafb_SAMM_ON;
extern int viafb_dual_fb;
extern int viafb_LCD2_ON;
extern int viafb_LCD_ON;
extern int viafb_DVI_ON;
extern int viafb_accel;
extern int viafb_hotplug;
void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask);
void viafb_set_output_path(int device, int set_iga,
int output_interface);
void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
int mode_index, int bpp_byte, int set_iga);
void viafb_set_vclock(u32 CLK, int set_iga);
void viafb_load_reg(int timing_value, int viafb_load_reg_num,
struct io_register *reg,
int io_type);
void viafb_crt_disable(void);
void viafb_crt_enable(void);
void init_ad9389(void);
/* Access I/O Function */
void viafb_write_reg(u8 index, u16 io_port, u8 data);
u8 viafb_read_reg(int io_port, u8 index);
void viafb_lock_crt(void);
void viafb_unlock_crt(void);
void viafb_load_offset_reg(int h_addr, int bpp_byte, int set_iga);
void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga);
void viafb_write_regx(struct io_reg RegTable[], int ItemNum);
struct VideoModeTable *viafb_get_modetbl_pointer(int Index);
u32 viafb_get_clk_value(int clk);
void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active);
void viafb_set_color_depth(int bpp_byte, int set_iga);
void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
*p_gfx_dpa_setting);
int viafb_setmode(int vmode_index, int hor_res, int ver_res,
int video_bpp, int vmode_index1, int hor_res1,
int ver_res1, int video_bpp1);
void viafb_init_chip_info(void);
void viafb_init_dac(int set_iga);
int viafb_get_pixclock(int hres, int vres, int vmode_refresh);
int viafb_get_refresh(int hres, int vres, u32 float_refresh);
void viafb_update_device_setting(int hres, int vres, int bpp,
int vmode_refresh, int flag);
void viafb_get_mmio_info(unsigned long *mmio_base,
unsigned long *mmio_len);
void viafb_set_iga_path(void);
void viafb_set_start_addr(void);
void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len);
#endif /* __HW_H__ */

78
drivers/video/via/iface.c Normal file
View file

@ -0,0 +1,78 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "global.h"
/* Get frame buffer size from VGA BIOS */
unsigned int viafb_get_memsize(void)
{
unsigned int m;
/* If memory size provided by user */
if (viafb_memsize)
m = viafb_memsize * Mb;
else {
m = (unsigned int)viafb_read_reg(VIASR, SR39);
m = m * (4 * Mb);
if ((m < (16 * Mb)) || (m > (64 * Mb)))
m = 16 * Mb;
}
DEBUG_MSG(KERN_INFO "framebuffer size = %d Mb\n", m / Mb);
return m;
}
/* Get Video Buffer Starting Physical Address(back door)*/
unsigned long viafb_get_videobuf_addr(void)
{
struct pci_dev *pdev = NULL;
unsigned char sys_mem;
unsigned char video_mem;
unsigned long sys_mem_size;
unsigned long video_mem_size;
/*system memory = 256 MB, video memory 64 MB */
unsigned long vmem_starting_adr = 0x0C000000;
pdev =
(struct pci_dev *)pci_get_device(VIA_K800_BRIDGE_VID,
VIA_K800_BRIDGE_DID, NULL);
if (pdev != NULL) {
pci_read_config_byte(pdev, VIA_K800_SYSTEM_MEMORY_REG,
&sys_mem);
pci_read_config_byte(pdev, VIA_K800_VIDEO_MEMORY_REG,
&video_mem);
video_mem = (video_mem & 0x70) >> 4;
sys_mem_size = ((unsigned long)sys_mem) << 24;
if (video_mem != 0)
video_mem_size = (1 << (video_mem)) * 1024 * 1024;
else
video_mem_size = 0;
vmem_starting_adr = sys_mem_size - video_mem_size;
pci_dev_put(pdev);
}
DEBUG_MSG(KERN_INFO "Video Memory Starting Address = %lx \n",
vmem_starting_adr);
return vmem_starting_adr;
}

38
drivers/video/via/iface.h Normal file
View file

@ -0,0 +1,38 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __IFACE_H__
#define __IFACE_H__
#define Kb (1024)
#define Mb (Kb*Kb)
#define VIA_K800_BRIDGE_VID 0x1106
#define VIA_K800_BRIDGE_DID 0x3204
#define VIA_K800_SYSTEM_MEMORY_REG 0x47
#define VIA_K800_VIDEO_MEMORY_REG 0xA1
extern int viafb_memsize;
unsigned int viafb_get_memsize(void);
unsigned long viafb_get_videobuf_addr(void);
#endif /* __IFACE_H__ */

112
drivers/video/via/ioctl.c Normal file
View file

@ -0,0 +1,112 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "global.h"
int viafb_ioctl_get_viafb_info(u_long arg)
{
struct viafb_ioctl_info viainfo;
viainfo.viafb_id = VIAID;
viainfo.vendor_id = PCI_VIA_VENDOR_ID;
switch (viaparinfo->chip_info->gfx_chip_name) {
case UNICHROME_CLE266:
viainfo.device_id = UNICHROME_CLE266_DID;
break;
case UNICHROME_K400:
viainfo.device_id = UNICHROME_K400_DID;
break;
case UNICHROME_K800:
viainfo.device_id = UNICHROME_K800_DID;
break;
case UNICHROME_PM800:
viainfo.device_id = UNICHROME_PM800_DID;
break;
case UNICHROME_CN700:
viainfo.device_id = UNICHROME_CN700_DID;
break;
case UNICHROME_CX700:
viainfo.device_id = UNICHROME_CX700_DID;
break;
case UNICHROME_K8M890:
viainfo.device_id = UNICHROME_K8M890_DID;
break;
case UNICHROME_P4M890:
viainfo.device_id = UNICHROME_P4M890_DID;
break;
case UNICHROME_P4M900:
viainfo.device_id = UNICHROME_P4M900_DID;
break;
}
viainfo.version = VERSION_MAJOR;
viainfo.revision = VERSION_MINOR;
if (copy_to_user((void __user *)arg, &viainfo, sizeof(viainfo)))
return -EFAULT;
return 0;
}
/* Hot-Plug Priority: DVI > CRT*/
int viafb_ioctl_hotplug(int hres, int vres, int bpp)
{
int DVIsense, status = 0;
DEBUG_MSG(KERN_INFO "viafb_ioctl_hotplug!!\n");
if (viaparinfo->chip_info->tmds_chip_info.tmds_chip_name !=
NON_TMDS_TRANSMITTER) {
DVIsense = viafb_dvi_sense();
if (DVIsense) {
DEBUG_MSG(KERN_INFO "DVI Attached...\n");
if (viafb_DeviceStatus != DVI_Device) {
viafb_DVI_ON = 1;
viafb_CRT_ON = 0;
viafb_LCD_ON = 0;
viafb_DeviceStatus = DVI_Device;
return viafb_DeviceStatus;
}
status = 1;
} else
DEBUG_MSG(KERN_INFO "DVI De-attached...\n");
}
if ((viafb_DeviceStatus != CRT_Device) && (status == 0)) {
viafb_CRT_ON = 1;
viafb_DVI_ON = 0;
viafb_LCD_ON = 0;
viafb_DeviceStatus = CRT_Device;
return viafb_DeviceStatus;
}
return 0;
}

210
drivers/video/via/ioctl.h Normal file
View file

@ -0,0 +1,210 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __IOCTL_H__
#define __IOCTL_H__
#ifndef __user
#define __user
#endif
/* VIAFB IOCTL definition */
#define VIAFB_GET_INFO_SIZE 0x56494101 /* 'VIA\01' */
#define VIAFB_GET_INFO 0x56494102 /* 'VIA\02' */
#define VIAFB_HOTPLUG 0x56494103 /* 'VIA\03' */
#define VIAFB_SET_HOTPLUG_FLAG 0x56494104 /* 'VIA\04' */
#define VIAFB_GET_RESOLUTION 0x56494105 /* 'VIA\05' */
#define VIAFB_GET_SAMM_INFO 0x56494107 /* 'VIA\07' */
#define VIAFB_TURN_ON_OUTPUT_DEVICE 0x56494108 /* 'VIA\08' */
#define VIAFB_TURN_OFF_OUTPUT_DEVICE 0x56494109 /* 'VIA\09' */
#define VIAFB_SET_DEVICE 0x5649410A
#define VIAFB_GET_DEVICE 0x5649410B
#define VIAFB_GET_DRIVER_VERSION 0x56494112 /* 'VIA\12' */
#define VIAFB_GET_CHIP_INFO 0x56494113 /* 'VIA\13' */
#define VIAFB_SET_DEVICE_INFO 0x56494114
#define VIAFB_GET_DEVICE_INFO 0x56494115
#define VIAFB_GET_DEVICE_SUPPORT 0x56494118
#define VIAFB_GET_DEVICE_CONNECT 0x56494119
#define VIAFB_GET_PANEL_SUPPORT_EXPAND 0x5649411A
#define VIAFB_GET_DRIVER_NAME 0x56494122
#define VIAFB_GET_DEVICE_SUPPORT_STATE 0x56494123
#define VIAFB_GET_GAMMA_LUT 0x56494124
#define VIAFB_SET_GAMMA_LUT 0x56494125
#define VIAFB_GET_GAMMA_SUPPORT_STATE 0x56494126
#define VIAFB_SET_VIDEO_DEVICE 0x56494127
#define VIAFB_GET_VIDEO_DEVICE 0x56494128
#define VIAFB_SET_SECOND_MODE 0x56494129
#define VIAFB_SYNC_SURFACE 0x56494130
#define VIAFB_GET_DRIVER_CAPS 0x56494131
#define VIAFB_GET_IGA_SCALING_INFO 0x56494132
#define VIAFB_GET_PANEL_MAX_SIZE 0x56494133
#define VIAFB_GET_PANEL_MAX_POSITION 0x56494134
#define VIAFB_SET_PANEL_SIZE 0x56494135
#define VIAFB_SET_PANEL_POSITION 0x56494136
#define VIAFB_GET_PANEL_POSITION 0x56494137
#define VIAFB_GET_PANEL_SIZE 0x56494138
#define None_Device 0x00
#define CRT_Device 0x01
#define LCD_Device 0x02
#define DVI_Device 0x08
#define CRT2_Device 0x10
#define LCD2_Device 0x40
#define OP_LCD_CENTERING 0x01
#define OP_LCD_PANEL_ID 0x02
#define OP_LCD_MODE 0x03
/*SAMM operation flag*/
#define OP_SAMM 0x80
#define LCD_PANEL_ID_MAXIMUM 22
#define STATE_ON 0x1
#define STATE_OFF 0x0
#define STATE_DEFAULT 0xFFFF
#define MAX_ACTIVE_DEV_NUM 2
struct device_t {
unsigned short crt:1;
unsigned short dvi:1;
unsigned short lcd:1;
unsigned short samm:1;
unsigned short lcd_dsp_cent:1;
unsigned char lcd_mode:1;
unsigned short epia_dvi:1;
unsigned short lcd_dual_edge:1;
unsigned short lcd2:1;
unsigned short primary_dev;
unsigned char lcd_panel_id;
unsigned short xres, yres;
unsigned short xres1, yres1;
unsigned short refresh;
unsigned short bpp;
unsigned short refresh1;
unsigned short bpp1;
unsigned short sequence;
unsigned short bus_width;
};
struct viafb_ioctl_info {
u32 viafb_id; /* for identifying viafb */
#define VIAID 0x56494146 /* Identify myself with 'VIAF' */
u16 vendor_id;
u16 device_id;
u8 version;
u8 revision;
u8 reserved[246]; /* for future use */
};
struct viafb_ioctl_mode {
u32 xres;
u32 yres;
u32 refresh;
u32 bpp;
u32 xres_sec;
u32 yres_sec;
u32 virtual_xres_sec;
u32 virtual_yres_sec;
u32 refresh_sec;
u32 bpp_sec;
};
struct viafb_ioctl_samm {
u32 samm_status;
u32 size_prim;
u32 size_sec;
u32 mem_base;
u32 offset_sec;
};
struct viafb_driver_version {
int iMajorNum;
int iKernelNum;
int iOSNum;
int iMinorNum;
};
struct viafb_ioctl_lcd_attribute {
unsigned int panel_id;
unsigned int display_center;
unsigned int lcd_mode;
};
struct viafb_ioctl_setting {
/* Enable or disable active devices */
unsigned short device_flag;
/* Indicate which device should be turn on or turn off. */
unsigned short device_status;
unsigned int reserved;
/* Indicate which LCD's attribute can be changed. */
unsigned short lcd_operation_flag;
/* 1: SAMM ON 0: SAMM OFF */
unsigned short samm_status;
/* horizontal resolution of first device */
unsigned short first_dev_hor_res;
/* vertical resolution of first device */
unsigned short first_dev_ver_res;
/* horizontal resolution of second device */
unsigned short second_dev_hor_res;
/* vertical resolution of second device */
unsigned short second_dev_ver_res;
/* refresh rate of first device */
unsigned short first_dev_refresh;
/* bpp of first device */
unsigned short first_dev_bpp;
/* refresh rate of second device */
unsigned short second_dev_refresh;
/* bpp of second device */
unsigned short second_dev_bpp;
/* Indicate which device are primary display device. */
unsigned int primary_device;
/* Indicate which device will show video. only valid in duoview mode */
unsigned int video_device_status;
unsigned int struct_reserved[34];
struct viafb_ioctl_lcd_attribute lcd_attributes;
};
struct _UTFunctionCaps {
unsigned int dw3DScalingState;
unsigned int reserved[31];
};
struct _POSITIONVALUE {
unsigned int dwX;
unsigned int dwY;
};
struct _panel_size_pos_info {
unsigned int device_type;
int x;
int y;
};
extern int viafb_LCD_ON;
extern int viafb_DVI_ON;
int viafb_ioctl_get_viafb_info(u_long arg);
int viafb_ioctl_hotplug(int hres, int vres, int bpp);
#endif /* __IOCTL_H__ */

1821
drivers/video/via/lcd.c Normal file

File diff suppressed because it is too large Load diff

94
drivers/video/via/lcd.h Normal file
View file

@ -0,0 +1,94 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __LCD_H__
#define __LCD_H__
/*Definition TMDS Device ID register*/
#define VT1631_DEVICE_ID_REG 0x02
#define VT1631_DEVICE_ID 0x92
#define VT3271_DEVICE_ID_REG 0x02
#define VT3271_DEVICE_ID 0x71
#define GET_LCD_SIZE_BY_SYSTEM_BIOS 0x01
#define GET_LCD_SIZE_BY_VGA_BIOS 0x02
#define GET_LCD_SZIE_BY_HW_STRAPPING 0x03
#define GET_LCD_SIZE_BY_USER_SETTING 0x04
/* Definition DVI Panel ID*/
/* Resolution: 640x480, Channel: single, Dithering: Enable */
#define LCD_PANEL_ID0_640X480 0x00
/* Resolution: 800x600, Channel: single, Dithering: Enable */
#define LCD_PANEL_ID1_800X600 0x01
/* Resolution: 1024x768, Channel: single, Dithering: Enable */
#define LCD_PANEL_ID2_1024X768 0x02
/* Resolution: 1280x768, Channel: single, Dithering: Enable */
#define LCD_PANEL_ID3_1280X768 0x03
/* Resolution: 1280x1024, Channel: dual, Dithering: Enable */
#define LCD_PANEL_ID4_1280X1024 0x04
/* Resolution: 1400x1050, Channel: dual, Dithering: Enable */
#define LCD_PANEL_ID5_1400X1050 0x05
/* Resolution: 1600x1200, Channel: dual, Dithering: Enable */
#define LCD_PANEL_ID6_1600X1200 0x06
/* Resolution: 1366x768, Channel: single, Dithering: Disable */
#define LCD_PANEL_ID7_1366X768 0x07
/* Resolution: 1024x600, Channel: single, Dithering: Enable*/
#define LCD_PANEL_ID8_1024X600 0x08
/* Resolution: 1280x800, Channel: single, Dithering: Enable*/
#define LCD_PANEL_ID9_1280X800 0x09
/* Resolution: 800x480, Channel: single, Dithering: Enable*/
#define LCD_PANEL_IDA_800X480 0x0A
/* Resolution: 1360x768, Channel: single, Dithering: Disable*/
#define LCD_PANEL_IDB_1360X768 0x0B
/* Resolution: 480x640, Channel: single, Dithering: Enable */
#define LCD_PANEL_IDC_480X640 0x0C
extern int viafb_LCD2_ON;
extern int viafb_LCD_ON;
extern int viafb_DVI_ON;
void viafb_disable_lvds_vt1636(struct lvds_setting_information
*plvds_setting_info,
struct lvds_chip_information *plvds_chip_info);
void viafb_enable_lvds_vt1636(struct lvds_setting_information
*plvds_setting_info,
struct lvds_chip_information *plvds_chip_info);
void viafb_lcd_disable(void);
void viafb_lcd_enable(void);
void viafb_init_lcd_size(void);
void viafb_init_lvds_output_interface(struct lvds_chip_information
*plvds_chip_info,
struct lvds_setting_information
*plvds_setting_info);
void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
struct lvds_setting_information *plvds_setting_info,
struct lvds_chip_information *plvds_chip_info);
int viafb_lvds_trasmitter_identify(void);
void viafb_init_lvds_output_interface(struct lvds_chip_information
*plvds_chip_info,
struct lvds_setting_information
*plvds_setting_info);
bool viafb_lcd_get_mobile_state(bool *mobile);
void viafb_load_crtc_timing(struct display_timing device_timing,
int set_iga);
#endif /* __LCD_H__ */

591
drivers/video/via/lcdtbl.h Normal file
View file

@ -0,0 +1,591 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __LCDTBL_H__
#define __LCDTBL_H__
#include "share.h"
/* CLE266 Software Power Sequence */
/* {Mask}, {Data}, {Delay} */
int PowerSequenceOn[3][3] =
{ {0x10, 0x08, 0x06}, {0x10, 0x08, 0x06}, {0x19, 0x1FE, 0x01} };
int PowerSequenceOff[3][3] =
{ {0x06, 0x08, 0x10}, {0x00, 0x00, 0x00}, {0xD2, 0x19, 0x01} };
/* ++++++ P880 ++++++ */
/* Panel 1600x1200 */
struct io_reg P880_LCD_RES_6X4_16X12[] = {
/*IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x73}, {VIACR, CR55, 0x0F, 0x08},
/*IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x73}, {VIACR, CR54, 0x38, 0x00},
{VIACR, CR5D, 0x40, 0x40},
/*IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0x5A}, {VIACR, CR71, 0x08, 0x00},
/*IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0x5E},
/*IGA2 Offset */
{VIACR, CR66, 0xFF, 0xD6}, {VIACR, CR67, 0x03, 0x00},
/*VCLK*/ {VIASR, SR44, 0xFF, 0x7D}, {VIASR, SR45, 0xFF, 0x8C},
{VIASR, SR46, 0xFF, 0x02}
};
#define NUM_TOTAL_P880_LCD_RES_6X4_16X12 ARRAY_SIZE(P880_LCD_RES_6X4_16X12)
struct io_reg P880_LCD_RES_7X4_16X12[] = {
/*IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x67}, {VIACR, CR55, 0x0F, 0x08},
/*IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x67}, {VIACR, CR54, 0x38, 0x00},
{VIACR, CR5D, 0x40, 0x40},
/*IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0x74}, {VIACR, CR71, 0x08, 0x00},
/*IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0x78},
/*IGA2 Offset */
{VIACR, CR66, 0xFF, 0xF5}, {VIACR, CR67, 0x03, 0x00},
/*VCLK*/ {VIASR, SR44, 0xFF, 0x78}, {VIASR, SR45, 0xFF, 0x8C},
{VIASR, SR46, 0xFF, 0x01}
};
#define NUM_TOTAL_P880_LCD_RES_7X4_16X12 ARRAY_SIZE(P880_LCD_RES_7X4_16X12)
struct io_reg P880_LCD_RES_8X6_16X12[] = {
/*IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x65}, {VIACR, CR55, 0x0F, 0x08},
/*IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x65}, {VIACR, CR54, 0x38, 0x00},
{VIACR, CR5D, 0x40, 0x40},
/*IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x00},
/*IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0x83},
/*IGA2 Offset */
{VIACR, CR66, 0xFF, 0xE1}, {VIACR, CR67, 0x03, 0x00},
/*VCLK*/ {VIASR, SR44, 0xFF, 0x6D}, {VIASR, SR45, 0xFF, 0x88},
{VIASR, SR46, 0xFF, 0x03}
};
#define NUM_TOTAL_P880_LCD_RES_8X6_16X12 ARRAY_SIZE(P880_LCD_RES_8X6_16X12)
struct io_reg P880_LCD_RES_10X7_16X12[] = {
/*IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x65}, {VIACR, CR55, 0x0F, 0x08},
/*IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x65}, {VIACR, CR54, 0x38, 0x00},
{VIACR, CR5D, 0x40, 0x40},
/*IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0xAB}, {VIACR, CR71, 0x08, 0x00},
/*IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0xAF},
/*IGA2 Offset */
{VIACR, CR66, 0xFF, 0xF0}, {VIACR, CR67, 0x03, 0x00},
/*VCLK*/ {VIASR, SR44, 0xFF, 0x92}, {VIASR, SR45, 0xFF, 0x88},
{VIASR, SR46, 0xFF, 0x03}
};
#define NUM_TOTAL_P880_LCD_RES_10X7_16X12 ARRAY_SIZE(P880_LCD_RES_10X7_16X12)
struct io_reg P880_LCD_RES_12X10_16X12[] = {
/*IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x7D}, {VIACR, CR55, 0x0F, 0x08},
/*IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x7D}, {VIACR, CR54, 0x38, 0x00},
{VIACR, CR5D, 0x40, 0x40},
/*IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0xD0}, {VIACR, CR71, 0x08, 0x00},
/*IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0xD4},
/*IGA2 Offset */
{VIACR, CR66, 0xFF, 0xFA}, {VIACR, CR67, 0x03, 0x00},
/*VCLK*/ {VIASR, SR44, 0xFF, 0xF6}, {VIASR, SR45, 0xFF, 0x88},
{VIASR, SR46, 0xFF, 0x05}
};
#define NUM_TOTAL_P880_LCD_RES_12X10_16X12 ARRAY_SIZE(P880_LCD_RES_12X10_16X12)
/* Panel 1400x1050 */
struct io_reg P880_LCD_RES_6X4_14X10[] = {
/* 640x480 */
/* IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
/* IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
{VIACR, CR5D, 0x40, 0x24},
/* IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0x5F}, {VIACR, CR71, 0x08, 0x44},
/* IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0x63},
/* IGA2 Offset */
{VIACR, CR66, 0xFF, 0xB4}, {VIACR, CR67, 0x03, 0x00},
/* VCLK */
{VIASR, SR44, 0xFF, 0xC6}, {VIASR, SR45, 0xFF, 0x8C},
{VIASR, SR46, 0xFF, 0x05}
};
#define NUM_TOTAL_P880_LCD_RES_6X4_14X10 ARRAY_SIZE(P880_LCD_RES_6X4_14X10)
struct io_reg P880_LCD_RES_8X6_14X10[] = {
/* 800x600 */
/* IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
/* IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
{VIACR, CR5D, 0x40, 0x24},
/* IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x44},
/* IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0x83},
/* IGA2 Offset */
{VIACR, CR66, 0xFF, 0xBE}, {VIACR, CR67, 0x03, 0x00},
/* VCLK */
{VIASR, SR44, 0xFF, 0x06}, {VIASR, SR45, 0xFF, 0x8D},
{VIASR, SR46, 0xFF, 0x05}
};
#define NUM_TOTAL_P880_LCD_RES_8X6_14X10 ARRAY_SIZE(P880_LCD_RES_8X6_14X10)
/* ++++++ K400 ++++++ */
/* Panel 1600x1200 */
struct io_reg K400_LCD_RES_6X4_16X12[] = {
/*IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x73}, {VIACR, CR55, 0x0F, 0x08},
/*IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x73}, {VIACR, CR54, 0x38, 0x00},
{VIACR, CR5D, 0x40, 0x40},
/*IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0x5A}, {VIACR, CR71, 0x08, 0x00},
/*IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0x5E},
/*IGA2 Offset */
{VIACR, CR66, 0xFF, 0xDA}, {VIACR, CR67, 0x03, 0x00},
/*VCLK*/ {VIASR, SR46, 0xFF, 0xC4}, {VIASR, SR47, 0xFF, 0x7F}
};
#define NUM_TOTAL_K400_LCD_RES_6X4_16X12 ARRAY_SIZE(K400_LCD_RES_6X4_16X12)
struct io_reg K400_LCD_RES_7X4_16X12[] = {
/*IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x67}, {VIACR, CR55, 0x0F, 0x08},
/*IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x67}, {VIACR, CR54, 0x38, 0x00},
{VIACR, CR5D, 0x40, 0x40},
/*IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0x74}, {VIACR, CR71, 0x08, 0x00},
/*IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0x78},
/*IGA2 Offset */
{VIACR, CR66, 0xFF, 0xF5}, {VIACR, CR67, 0x03, 0x00},
/*VCLK*/ {VIASR, SR46, 0xFF, 0x46}, {VIASR, SR47, 0xFF, 0x3D}
};
#define NUM_TOTAL_K400_LCD_RES_7X4_16X12 ARRAY_SIZE(K400_LCD_RES_7X4_16X12)
struct io_reg K400_LCD_RES_8X6_16X12[] = {
/*IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x65}, {VIACR, CR55, 0x0F, 0x08},
/*IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x65}, {VIACR, CR54, 0x38, 0x00},
{VIACR, CR5D, 0x40, 0x40},
/*IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x00},
/*IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0x83},
/*IGA2 Offset */
{VIACR, CR66, 0xFF, 0xE1}, {VIACR, CR67, 0x03, 0x00},
/*VCLK*/ {VIASR, SR46, 0xFF, 0x85}, {VIASR, SR47, 0xFF, 0x6F}
};
#define NUM_TOTAL_K400_LCD_RES_8X6_16X12 ARRAY_SIZE(K400_LCD_RES_8X6_16X12)
struct io_reg K400_LCD_RES_10X7_16X12[] = {
/*IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x65}, {VIACR, CR55, 0x0F, 0x08},
/*IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x65}, {VIACR, CR54, 0x38, 0x00},
{VIACR, CR5D, 0x40, 0x40},
/*IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0xAB}, {VIACR, CR71, 0x08, 0x00},
/*IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0xAF},
/*IGA2 Offset */
{VIACR, CR66, 0xFF, 0xF0}, {VIACR, CR67, 0x03, 0x00},
/*VCLK*/ {VIASR, SR46, 0xFF, 0x45}, {VIASR, SR47, 0xFF, 0x4A}
};
#define NUM_TOTAL_K400_LCD_RES_10X7_16X12 ARRAY_SIZE(K400_LCD_RES_10X7_16X12)
struct io_reg K400_LCD_RES_12X10_16X12[] = {
/*IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x7D}, {VIACR, CR55, 0x0F, 0x08},
/*IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x7D}, {VIACR, CR54, 0x38, 0x00},
{VIACR, CR5D, 0x40, 0x40},
/*IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0xD0}, {VIACR, CR71, 0x08, 0x00},
/*IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0xD4},
/*IGA2 Offset */
{VIACR, CR66, 0xFF, 0xFA}, {VIACR, CR67, 0x03, 0x00},
/*VCLK*/ {VIASR, SR46, 0xFF, 0x47}, {VIASR, SR47, 0xFF, 0x7C}
};
#define NUM_TOTAL_K400_LCD_RES_12X10_16X12 ARRAY_SIZE(K400_LCD_RES_12X10_16X12)
/* Panel 1400x1050 */
struct io_reg K400_LCD_RES_6X4_14X10[] = {
/* 640x400 */
/* IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
/* IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
{VIACR, CR5D, 0x40, 0x24},
/* IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0x5F}, {VIACR, CR71, 0x08, 0x44},
/* IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0x63},
/* IGA2 Offset */
{VIACR, CR66, 0xFF, 0xB4}, {VIACR, CR67, 0x03, 0x00},
/* VCLK */
{VIASR, SR46, 0xFF, 0x07}, {VIASR, SR47, 0xFF, 0x19}
};
#define NUM_TOTAL_K400_LCD_RES_6X4_14X10 ARRAY_SIZE(K400_LCD_RES_6X4_14X10)
struct io_reg K400_LCD_RES_8X6_14X10[] = {
/* 800x600 */
/* IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
/* IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
{VIACR, CR5D, 0x40, 0x24},
/* IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x44},
/* IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0x83},
/* IGA2 Offset */
{VIACR, CR66, 0xFF, 0xBE}, {VIACR, CR67, 0x03, 0x00},
/* VCLK */
{VIASR, SR46, 0xFF, 0x07}, {VIASR, SR47, 0xFF, 0x21}
};
#define NUM_TOTAL_K400_LCD_RES_8X6_14X10 ARRAY_SIZE(K400_LCD_RES_8X6_14X10)
struct io_reg K400_LCD_RES_10X7_14X10[] = {
/* 1024x768 */
/* IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
/* IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
{VIACR, CR5D, 0x40, 0x24},
/* IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0xA3}, {VIACR, CR71, 0x08, 0x44},
/* IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0xA7},
/* IGA2 Offset */
{VIACR, CR66, 0xFF, 0xC3}, {VIACR, CR67, 0x03, 0x04},
/* VCLK */
{VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x1E}
};
#define NUM_TOTAL_K400_LCD_RES_10X7_14X10 ARRAY_SIZE(K400_LCD_RES_10X7_14X10)
struct io_reg K400_LCD_RES_12X10_14X10[] = {
/* 1280x768, 1280x960, 1280x1024 */
/* IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x97}, {VIACR, CR55, 0x0F, 0x56},
/* IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x97}, {VIACR, CR54, 0x38, 0x75},
{VIACR, CR5D, 0x40, 0x24},
/* IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0xCE}, {VIACR, CR71, 0x08, 0x44},
/* IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0xD2},
/* IGA2 Offset */
{VIACR, CR66, 0xFF, 0xC9}, {VIACR, CR67, 0x03, 0x04},
/* VCLK */
{VIASR, SR46, 0xFF, 0x84}, {VIASR, SR47, 0xFF, 0x79}
};
#define NUM_TOTAL_K400_LCD_RES_12X10_14X10 ARRAY_SIZE(K400_LCD_RES_12X10_14X10)
/* ++++++ K400 ++++++ */
/* Panel 1366x768 */
struct io_reg K400_LCD_RES_6X4_1366X7[] = {
/* 640x400 */
/* IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x47}, {VIACR, CR55, 0x0F, 0x35},
/* IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x47}, {VIACR, CR54, 0x38, 0x2B},
{VIACR, CR5D, 0x40, 0x13},
/* IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0x60}, {VIACR, CR71, 0x08, 0x23},
/* IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0x64},
/* IGA2 Offset */
{VIACR, CR66, 0xFF, 0x8C}, {VIACR, CR67, 0x03, 0x00},
/* VCLK */
{VIASR, SR46, 0xFF, 0x87}, {VIASR, SR47, 0xFF, 0x4C}
};
#define NUM_TOTAL_K400_LCD_RES_6X4_1366X7 ARRAY_SIZE(K400_LCD_RES_6X4_1366X7)
struct io_reg K400_LCD_RES_7X4_1366X7[] = {
/* IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x3B}, {VIACR, CR55, 0x0F, 0x35},
/* IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x3B}, {VIACR, CR54, 0x38, 0x2B},
{VIACR, CR5D, 0x40, 0x13},
/* IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0x71}, {VIACR, CR71, 0x08, 0x23},
/* IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0x75},
/* IGA2 Offset */
{VIACR, CR66, 0xFF, 0x96}, {VIACR, CR67, 0x03, 0x00},
/* VCLK */
{VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x10}
};
#define NUM_TOTAL_K400_LCD_RES_7X4_1366X7 ARRAY_SIZE(K400_LCD_RES_7X4_1366X7)
struct io_reg K400_LCD_RES_8X6_1366X7[] = {
/* 800x600 */
/* IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x37}, {VIACR, CR55, 0x0F, 0x35},
/* IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x37}, {VIACR, CR54, 0x38, 0x2B},
{VIACR, CR5D, 0x40, 0x13},
/* IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0x7E}, {VIACR, CR71, 0x08, 0x23},
/* IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0x82},
/* IGA2 Offset */
{VIACR, CR66, 0xFF, 0x8C}, {VIACR, CR67, 0x03, 0x00},
/* VCLK */
{VIASR, SR46, 0xFF, 0x84}, {VIASR, SR47, 0xFF, 0xB9}
};
#define NUM_TOTAL_K400_LCD_RES_8X6_1366X7 ARRAY_SIZE(K400_LCD_RES_8X6_1366X7)
struct io_reg K400_LCD_RES_10X7_1366X7[] = {
/* 1024x768 */
/* IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x56},
/* IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x75},
{VIACR, CR5D, 0x40, 0x24},
/* IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0xA3}, {VIACR, CR71, 0x08, 0x44},
/* IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0xA7},
/* IGA2 Offset */
{VIACR, CR66, 0xFF, 0xC3}, {VIACR, CR67, 0x03, 0x04},
/* VCLK */
{VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x1E}
};
#define NUM_TOTAL_K400_LCD_RES_10X7_1366X7 ARRAY_SIZE(K400_LCD_RES_10X7_1366X7)
struct io_reg K400_LCD_RES_12X10_1366X7[] = {
/* 1280x768, 1280x960, 1280x1024 */
/* IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x97}, {VIACR, CR55, 0x0F, 0x56},
/* IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x97}, {VIACR, CR54, 0x38, 0x75},
{VIACR, CR5D, 0x40, 0x24},
/* IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0xCE}, {VIACR, CR71, 0x08, 0x44},
/* IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0xD2},
/* IGA2 Offset */
{VIACR, CR66, 0xFF, 0xC9}, {VIACR, CR67, 0x03, 0x04},
/* VCLK */
{VIASR, SR46, 0xFF, 0x84}, {VIASR, SR47, 0xFF, 0x79}
};
#define NUM_TOTAL_K400_LCD_RES_12X10_1366X7\
ARRAY_SIZE(K400_LCD_RES_12X10_1366X7)
/* ++++++ K400 ++++++ */
/* Panel 1280x1024 */
struct io_reg K400_LCD_RES_6X4_12X10[] = {
/*IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x46},
/*IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x74},
{VIACR, CR5D, 0x40, 0x1C},
/*IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0x5F}, {VIACR, CR71, 0x08, 0x34},
/*IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0x63},
/*IGA2 Offset */
{VIACR, CR66, 0xFF, 0xAA}, {VIACR, CR67, 0x03, 0x00},
/*VCLK*/ {VIASR, SR46, 0xFF, 0x07}, {VIASR, SR47, 0xFF, 0x19}
};
#define NUM_TOTAL_K400_LCD_RES_6X4_12X10 ARRAY_SIZE(K400_LCD_RES_6X4_12X10)
struct io_reg K400_LCD_RES_7X4_12X10[] = {
/*IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x46},
/*IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x74},
{VIACR, CR5D, 0x40, 0x1C},
/*IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0x68}, {VIACR, CR71, 0x08, 0x34},
/*IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0x6C},
/*IGA2 Offset */
{VIACR, CR66, 0xFF, 0xA8}, {VIACR, CR67, 0x03, 0x00},
/*VCLK*/ {VIASR, SR46, 0xFF, 0x87}, {VIASR, SR47, 0xFF, 0xED}
};
#define NUM_TOTAL_K400_LCD_RES_7X4_12X10 ARRAY_SIZE(K400_LCD_RES_7X4_12X10)
struct io_reg K400_LCD_RES_8X6_12X10[] = {
/*IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x46},
/*IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x74},
{VIACR, CR5D, 0x40, 0x1C},
/*IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x34},
/*IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0x83},
/*IGA2 Offset */
{VIACR, CR66, 0xFF, 0xBE}, {VIACR, CR67, 0x03, 0x00},
/*VCLK*/ {VIASR, SR46, 0xFF, 0x07}, {VIASR, SR47, 0xFF, 0x21}
};
#define NUM_TOTAL_K400_LCD_RES_8X6_12X10 ARRAY_SIZE(K400_LCD_RES_8X6_12X10)
struct io_reg K400_LCD_RES_10X7_12X10[] = {
/*IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x9D}, {VIACR, CR55, 0x0F, 0x46},
/*IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x9D}, {VIACR, CR54, 0x38, 0x74},
{VIACR, CR5D, 0x40, 0x1C},
/*IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0xA3}, {VIACR, CR71, 0x08, 0x34},
/*IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0xA7},
/*IGA2 Offset */
{VIACR, CR66, 0xFF, 0xBE}, {VIACR, CR67, 0x03, 0x04},
/*VCLK*/ {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x1E}
};
#define NUM_TOTAL_K400_LCD_RES_10X7_12X10 ARRAY_SIZE(K400_LCD_RES_10X7_12X10)
/* ++++++ K400 ++++++ */
/* Panel 1024x768 */
struct io_reg K400_LCD_RES_6X4_10X7[] = {
/*IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x47}, {VIACR, CR55, 0x0F, 0x35},
/*IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x47}, {VIACR, CR54, 0x38, 0x2B},
{VIACR, CR5D, 0x40, 0x13},
/*IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0x60}, {VIACR, CR71, 0x08, 0x23},
/*IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0x64},
/*IGA2 Offset */
{VIACR, CR66, 0xFF, 0x8C}, {VIACR, CR67, 0x03, 0x00},
/*VCLK*/ {VIASR, SR46, 0xFF, 0x87}, {VIASR, SR47, 0xFF, 0x4C}
};
#define NUM_TOTAL_K400_LCD_RES_6X4_10X7 ARRAY_SIZE(K400_LCD_RES_6X4_10X7)
struct io_reg K400_LCD_RES_7X4_10X7[] = {
/*IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x3B}, {VIACR, CR55, 0x0F, 0x35},
/*IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x3B}, {VIACR, CR54, 0x38, 0x2B},
{VIACR, CR5D, 0x40, 0x13},
/*IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0x71}, {VIACR, CR71, 0x08, 0x23},
/*IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0x75},
/*IGA2 Offset */
{VIACR, CR66, 0xFF, 0x96}, {VIACR, CR67, 0x03, 0x00},
/*VCLK*/ {VIASR, SR46, 0xFF, 0x05}, {VIASR, SR47, 0xFF, 0x10}
};
#define NUM_TOTAL_K400_LCD_RES_7X4_10X7 ARRAY_SIZE(K400_LCD_RES_7X4_10X7)
struct io_reg K400_LCD_RES_8X6_10X7[] = {
/*IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x37}, {VIACR, CR55, 0x0F, 0x35},
/*IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x37}, {VIACR, CR54, 0x38, 0x2B},
{VIACR, CR5D, 0x40, 0x13},
/*IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0x7E}, {VIACR, CR71, 0x08, 0x23},
/*IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0x82},
/*IGA2 Offset */
{VIACR, CR66, 0xFF, 0x8C}, {VIACR, CR67, 0x03, 0x00},
/*VCLK*/ {VIASR, SR46, 0xFF, 0x84}, {VIASR, SR47, 0xFF, 0xB9}
};
#define NUM_TOTAL_K400_LCD_RES_8X6_10X7 ARRAY_SIZE(K400_LCD_RES_8X6_10X7)
/* ++++++ K400 ++++++ */
/* Panel 800x600 */
struct io_reg K400_LCD_RES_6X4_8X6[] = {
/*IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x1A}, {VIACR, CR55, 0x0F, 0x34},
/*IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x1A}, {VIACR, CR54, 0x38, 0xE3},
{VIACR, CR5D, 0x40, 0x12},
/*IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0x5F}, {VIACR, CR71, 0x08, 0x22},
/*IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0x63},
/*IGA2 Offset */
{VIACR, CR66, 0xFF, 0x6E}, {VIACR, CR67, 0x03, 0x00},
/*VCLK*/ {VIASR, SR46, 0xFF, 0x86}, {VIASR, SR47, 0xFF, 0xB3}
};
#define NUM_TOTAL_K400_LCD_RES_6X4_8X6 ARRAY_SIZE(K400_LCD_RES_6X4_8X6)
struct io_reg K400_LCD_RES_7X4_8X6[] = {
/*IGA2 Horizontal Total */
{VIACR, CR50, 0xFF, 0x1F}, {VIACR, CR55, 0x0F, 0x34},
/*IGA2 Horizontal Blank End */
{VIACR, CR53, 0xFF, 0x1F}, {VIACR, CR54, 0x38, 0xE3},
{VIACR, CR5D, 0x40, 0x12},
/*IGA2 Horizontal Total Shadow */
{VIACR, CR6D, 0xFF, 0x7F}, {VIACR, CR71, 0x08, 0x22},
/*IGA2 Horizontal Blank End Shadow */
{VIACR, CR6E, 0xFF, 0x83},
/*IGA2 Offset */
{VIACR, CR66, 0xFF, 0x78}, {VIACR, CR67, 0x03, 0x00},
/*VCLK*/ {VIASR, SR46, 0xFF, 0xC4}, {VIASR, SR47, 0xFF, 0x59}
};
#define NUM_TOTAL_K400_LCD_RES_7X4_8X6 ARRAY_SIZE(K400_LCD_RES_7X4_8X6)
#endif /* __LCDTBL_H__ */

1105
drivers/video/via/share.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,71 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "global.h"
struct IODATA COMMON_INIT_TBL_VT1636[] = {
/* Index, Mask, Value */
/* Set panel power sequence timing */
{0x10, 0xC0, 0x00},
/* T1: VDD on - Data on. Each increment is 1 ms. (50ms = 031h) */
{0x0B, 0xFF, 0x40},
/* T2: Data on - Backlight on. Each increment is 2 ms. (210ms = 068h) */
{0x0C, 0xFF, 0x31},
/* T3: Backlight off -Data off. Each increment is 2 ms. (210ms = 068h)*/
{0x0D, 0xFF, 0x31},
/* T4: Data off - VDD off. Each increment is 1 ms. (50ms = 031h) */
{0x0E, 0xFF, 0x68},
/* T5: VDD off - VDD on. Each increment is 100 ms. (500ms = 04h) */
{0x0F, 0xFF, 0x68},
/* LVDS output power up */
{0x09, 0xA0, 0xA0},
/* turn on back light */
{0x10, 0x33, 0x13}
};
struct IODATA DUAL_CHANNEL_ENABLE_TBL_VT1636[] = {
/* Index, Mask, Value */
{0x08, 0xF0, 0xE0} /* Input Data Mode Select */
};
struct IODATA SINGLE_CHANNEL_ENABLE_TBL_VT1636[] = {
/* Index, Mask, Value */
{0x08, 0xF0, 0x00} /* Input Data Mode Select */
};
struct IODATA DITHERING_ENABLE_TBL_VT1636[] = {
/* Index, Mask, Value */
{0x0A, 0x70, 0x50}
};
struct IODATA DITHERING_DISABLE_TBL_VT1636[] = {
/* Index, Mask, Value */
{0x0A, 0x70, 0x00}
};
struct IODATA VDD_ON_TBL_VT1636[] = {
/* Index, Mask, Value */
{0x10, 0x20, 0x20}
};
struct IODATA VDD_OFF_TBL_VT1636[] = {
/* Index, Mask, Value */
{0x10, 0x20, 0x00}
};

View file

@ -0,0 +1,34 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _TBL1636_H_
#define _TBL1636_H_
#include "hw.h"
extern struct IODATA COMMON_INIT_TBL_VT1636[8];
extern struct IODATA DUAL_CHANNEL_ENABLE_TBL_VT1636[1];
extern struct IODATA SINGLE_CHANNEL_ENABLE_TBL_VT1636[1];
extern struct IODATA DITHERING_ENABLE_TBL_VT1636[1];
extern struct IODATA DITHERING_DISABLE_TBL_VT1636[1];
extern struct IODATA VDD_ON_TBL_VT1636[1];
extern struct IODATA VDD_OFF_TBL_VT1636[1];
#endif /* _VIA_TBL1636_H_ */

View file

@ -0,0 +1,109 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "global.h"
/* For VT3324: */
struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3324[] = {
/* Panel ID, CLK_SEL_ST1[09], CLK_SEL_ST2[08] */
{LCD_PANEL_ID0_640X480, 0x00, 0x00}, /* For 640x480 */
{LCD_PANEL_ID1_800X600, 0x00, 0x00}, /* For 800x600 */
{LCD_PANEL_ID2_1024X768, 0x00, 0x00}, /* For 1024x768 */
{LCD_PANEL_ID3_1280X768, 0x00, 0x00}, /* For 1280x768 */
{LCD_PANEL_ID4_1280X1024, 0x00, 0x00}, /* For 1280x1024 */
{LCD_PANEL_ID5_1400X1050, 0x00, 0x00}, /* For 1400x1050 */
{LCD_PANEL_ID6_1600X1200, 0x0B, 0x03} /* For 1600x1200 */
};
struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[] = {
/* ClkRange, DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1,
DVP1Driving, DFPHigh, DFPLow */
/* CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B,
SR65, CR97, CR99 */
/* LCK/VCK < 30000000 will use this value */
{DPA_CLK_RANGE_30M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
0x00},
/* 30000000 < LCK/VCK < 50000000 will use this value */
{DPA_CLK_RANGE_30_50M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
0x00},
/* 50000000 < LCK/VCK < 70000000 will use this value */
{DPA_CLK_RANGE_50_70M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
0x00},
/* 70000000 < LCK/VCK < 100000000 will use this value */
{DPA_CLK_RANGE_70_100M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
0x00},
/* 100000000 < LCK/VCK < 15000000 will use this value */
{DPA_CLK_RANGE_100_150M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
0x00},
/* 15000000 < LCK/VCK will use this value */
{DPA_CLK_RANGE_150M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0E, 0x00,
0x00},
};
/* For VT3327: */
struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3327[] = {
/* Panel ID, CLK_SEL_ST1[09], CLK_SEL_ST2[08] */
{LCD_PANEL_ID0_640X480, 0x00, 0x00}, /* For 640x480 */
{LCD_PANEL_ID1_800X600, 0x00, 0x00}, /* For 800x600 */
{LCD_PANEL_ID2_1024X768, 0x00, 0x00}, /* For 1024x768 */
{LCD_PANEL_ID3_1280X768, 0x00, 0x00}, /* For 1280x768 */
{LCD_PANEL_ID4_1280X1024, 0x00, 0x00}, /* For 1280x1024 */
{LCD_PANEL_ID5_1400X1050, 0x00, 0x00}, /* For 1400x1050 */
{LCD_PANEL_ID6_1600X1200, 0x00, 0x00} /* For 1600x1200 */
};
struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3327[] = {
/* ClkRange,DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1,
DVP1Driving, DFPHigh, DFPLow */
/* CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B,
SR65, CR97, CR99 */
/* LCK/VCK < 30000000 will use this value */
{DPA_CLK_RANGE_30M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01},
/* 30000000 < LCK/VCK < 50000000 will use this value */
{DPA_CLK_RANGE_30_50M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01},
/* 50000000 < LCK/VCK < 70000000 will use this value */
{DPA_CLK_RANGE_50_70M, 0x06, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01},
/* 70000000 < LCK/VCK < 100000000 will use this value */
{DPA_CLK_RANGE_70_100M, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x03},
/* 100000000 < LCK/VCK < 15000000 will use this value */
{DPA_CLK_RANGE_100_150M, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x02},
/* 15000000 < LCK/VCK will use this value */
{DPA_CLK_RANGE_150M, 0x00, 0x20, 0x00, 0x10, 0x00, 0x03, 0x00, 0x0D, 0x03},
};
/* For VT3364: */
struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3364[] = {
/* ClkRange,DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1,
DVP1Driving, DFPHigh, DFPLow */
/* CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B,
SR65, CR97, CR99 */
/* LCK/VCK < 30000000 will use this value */
{DPA_CLK_RANGE_30M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
/* 30000000 < LCK/VCK < 50000000 will use this value */
{DPA_CLK_RANGE_30_50M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
/* 50000000 < LCK/VCK < 70000000 will use this value */
{DPA_CLK_RANGE_50_70M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
/* 70000000 < LCK/VCK < 100000000 will use this value */
{DPA_CLK_RANGE_70_100M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
/* 100000000 < LCK/VCK < 15000000 will use this value */
{DPA_CLK_RANGE_100_150M, 0x03, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
/* 15000000 < LCK/VCK will use this value */
{DPA_CLK_RANGE_150M, 0x01, 0x00, 0x02, 0x10, 0x00, 0x03, 0x00, 0x00, 0x08},
};

View file

@ -0,0 +1,47 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _TBLDPASETTING_H_
#define _TBLDPASETTING_H_
#include "global.h"
#define DPA_CLK_30M 30000000
#define DPA_CLK_50M 50000000
#define DPA_CLK_70M 70000000
#define DPA_CLK_100M 100000000
#define DPA_CLK_150M 150000000
enum DPA_RANGE {
DPA_CLK_RANGE_30M,
DPA_CLK_RANGE_30_50M,
DPA_CLK_RANGE_50_70M,
DPA_CLK_RANGE_70_100M,
DPA_CLK_RANGE_100_150M,
DPA_CLK_RANGE_150M
};
extern struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3324[7];
extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[6];
extern struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3327[7];
extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3327[];
extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3364[6];
#endif

177
drivers/video/via/via_i2c.c Normal file
View file

@ -0,0 +1,177 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "global.h"
static void via_i2c_setscl(void *data, int state)
{
u8 val;
struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data;
val = viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0xF0;
if (state)
val |= 0x20;
else
val &= ~0x20;
switch (via_i2c_chan->i2c_port) {
case I2CPORTINDEX:
val |= 0x01;
break;
case GPIOPORTINDEX:
val |= 0x80;
break;
default:
DEBUG_MSG("via_i2c: specify wrong i2c port.\n");
}
viafb_write_reg(via_i2c_chan->i2c_port, VIASR, val);
}
static int via_i2c_getscl(void *data)
{
struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data;
if (viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0x08)
return 1;
return 0;
}
static int via_i2c_getsda(void *data)
{
struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data;
if (viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0x04)
return 1;
return 0;
}
static void via_i2c_setsda(void *data, int state)
{
u8 val;
struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data;
val = viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0xF0;
if (state)
val |= 0x10;
else
val &= ~0x10;
switch (via_i2c_chan->i2c_port) {
case I2CPORTINDEX:
val |= 0x01;
break;
case GPIOPORTINDEX:
val |= 0x40;
break;
default:
DEBUG_MSG("via_i2c: specify wrong i2c port.\n");
}
viafb_write_reg(via_i2c_chan->i2c_port, VIASR, val);
}
int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata)
{
u8 mm1[] = {0x00};
struct i2c_msg msgs[2];
*pdata = 0;
msgs[0].flags = 0;
msgs[1].flags = I2C_M_RD;
msgs[0].addr = msgs[1].addr = slave_addr / 2;
mm1[0] = index;
msgs[0].len = 1; msgs[1].len = 1;
msgs[0].buf = mm1; msgs[1].buf = pdata;
i2c_transfer(&viaparinfo->i2c_stuff.adapter, msgs, 2);
return 0;
}
int viafb_i2c_writebyte(u8 slave_addr, u8 index, u8 data)
{
u8 msg[2] = { index, data };
struct i2c_msg msgs;
msgs.flags = 0;
msgs.addr = slave_addr / 2;
msgs.len = 2;
msgs.buf = msg;
return i2c_transfer(&viaparinfo->i2c_stuff.adapter, &msgs, 1);
}
int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len)
{
u8 mm1[] = {0x00};
struct i2c_msg msgs[2];
msgs[0].flags = 0;
msgs[1].flags = I2C_M_RD;
msgs[0].addr = msgs[1].addr = slave_addr / 2;
mm1[0] = index;
msgs[0].len = 1; msgs[1].len = buff_len;
msgs[0].buf = mm1; msgs[1].buf = buff;
i2c_transfer(&viaparinfo->i2c_stuff.adapter, msgs, 2);
return 0;
}
int viafb_create_i2c_bus(void *viapar)
{
int ret;
struct viafb_par *par = (struct viafb_par *)viapar;
strcpy(par->i2c_stuff.adapter.name, "via_i2c");
par->i2c_stuff.i2c_port = 0x0;
par->i2c_stuff.adapter.owner = THIS_MODULE;
par->i2c_stuff.adapter.id = 0x01FFFF;
par->i2c_stuff.adapter.class = 0;
par->i2c_stuff.adapter.algo_data = &par->i2c_stuff.algo;
par->i2c_stuff.adapter.dev.parent = NULL;
par->i2c_stuff.algo.setsda = via_i2c_setsda;
par->i2c_stuff.algo.setscl = via_i2c_setscl;
par->i2c_stuff.algo.getsda = via_i2c_getsda;
par->i2c_stuff.algo.getscl = via_i2c_getscl;
par->i2c_stuff.algo.udelay = 40;
par->i2c_stuff.algo.timeout = 20;
par->i2c_stuff.algo.data = &par->i2c_stuff;
i2c_set_adapdata(&par->i2c_stuff.adapter, &par->i2c_stuff);
/* Raise SCL and SDA */
par->i2c_stuff.i2c_port = I2CPORTINDEX;
via_i2c_setsda(&par->i2c_stuff, 1);
via_i2c_setscl(&par->i2c_stuff, 1);
par->i2c_stuff.i2c_port = GPIOPORTINDEX;
via_i2c_setsda(&par->i2c_stuff, 1);
via_i2c_setscl(&par->i2c_stuff, 1);
udelay(20);
ret = i2c_bit_add_bus(&par->i2c_stuff.adapter);
if (ret == 0)
DEBUG_MSG("I2C bus %s registered.\n",
par->i2c_stuff.adapter.name);
else
DEBUG_MSG("Failed to register I2C bus %s.\n",
par->i2c_stuff.adapter.name);
return ret;
}
void viafb_delete_i2c_buss(void *par)
{
i2c_del_adapter(&((struct viafb_par *)par)->i2c_stuff.adapter);
}

View file

@ -0,0 +1,46 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __VIA_I2C_H__
#define __VIA_I2C_H__
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
struct via_i2c_stuff {
u16 i2c_port; /* GPIO or I2C port */
struct i2c_adapter adapter;
struct i2c_algo_bit_data algo;
};
#define I2CPORT 0x3c4
#define I2CPORTINDEX 0x31
#define GPIOPORT 0x3C4
#define GPIOPORTINDEX 0x2C
#define I2C_BUS 1
#define GPIO_BUS 2
#define DELAYPORT 0x3C3
int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata);
int viafb_i2c_writebyte(u8 slave_addr, u8 index, u8 data);
int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len);
int viafb_create_i2c_bus(void *par);
void viafb_delete_i2c_buss(void *par);
#endif /* __VIA_I2C_H__ */

View file

@ -0,0 +1,253 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "global.h"
void viafb_get_device_support_state(u32 *support_state)
{
*support_state = CRT_Device;
if (viaparinfo->chip_info->tmds_chip_info.tmds_chip_name == VT1632_TMDS)
*support_state |= DVI_Device;
if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name == VT1631_LVDS)
*support_state |= LCD_Device;
}
void viafb_get_device_connect_state(u32 *connect_state)
{
bool mobile = false;
*connect_state = CRT_Device;
if (viafb_dvi_sense())
*connect_state |= DVI_Device;
viafb_lcd_get_mobile_state(&mobile);
if (mobile)
*connect_state |= LCD_Device;
}
bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres)
{
unsigned int support_state = 0;
switch (viafb_lcd_panel_id) {
case LCD_PANEL_ID0_640X480:
if ((xres < 640) && (yres < 480))
support_state = true;
break;
case LCD_PANEL_ID1_800X600:
if ((xres < 800) && (yres < 600))
support_state = true;
break;
case LCD_PANEL_ID2_1024X768:
if ((xres < 1024) && (yres < 768))
support_state = true;
break;
case LCD_PANEL_ID3_1280X768:
if ((xres < 1280) && (yres < 768))
support_state = true;
break;
case LCD_PANEL_ID4_1280X1024:
if ((xres < 1280) && (yres < 1024))
support_state = true;
break;
case LCD_PANEL_ID5_1400X1050:
if ((xres < 1400) && (yres < 1050))
support_state = true;
break;
case LCD_PANEL_ID6_1600X1200:
if ((xres < 1600) && (yres < 1200))
support_state = true;
break;
case LCD_PANEL_ID7_1366X768:
if ((xres < 1366) && (yres < 768))
support_state = true;
break;
case LCD_PANEL_ID8_1024X600:
if ((xres < 1024) && (yres < 600))
support_state = true;
break;
case LCD_PANEL_ID9_1280X800:
if ((xres < 1280) && (yres < 800))
support_state = true;
break;
case LCD_PANEL_IDA_800X480:
if ((xres < 800) && (yres < 480))
support_state = true;
break;
case LCD_PANEL_IDB_1360X768:
if ((xres < 1360) && (yres < 768))
support_state = true;
break;
case LCD_PANEL_IDC_480X640:
if ((xres < 480) && (yres < 640))
support_state = true;
break;
default:
support_state = false;
break;
}
return support_state;
}
/*====================================================================*/
/* Gamma Function Implementation*/
/*====================================================================*/
void viafb_set_gamma_table(int bpp, unsigned int *gamma_table)
{
int i, sr1a;
int active_device_amount = 0;
int device_status = viafb_DeviceStatus;
for (i = 0; i < sizeof(viafb_DeviceStatus) * 8; i++) {
if (device_status & 1)
active_device_amount++;
device_status >>= 1;
}
/* 8 bpp mode can't adjust gamma */
if (bpp == 8)
return ;
/* Enable Gamma */
switch (viaparinfo->chip_info->gfx_chip_name) {
case UNICHROME_CLE266:
case UNICHROME_K400:
viafb_write_reg_mask(SR16, VIASR, 0x80, BIT7);
break;
case UNICHROME_K800:
case UNICHROME_PM800:
case UNICHROME_CN700:
case UNICHROME_CX700:
case UNICHROME_K8M890:
case UNICHROME_P4M890:
case UNICHROME_P4M900:
viafb_write_reg_mask(CR33, VIACR, 0x80, BIT7);
break;
}
sr1a = (unsigned int)viafb_read_reg(VIASR, SR1A);
viafb_write_reg_mask(SR1A, VIASR, 0x0, BIT0);
/* Fill IGA1 Gamma Table */
outb(0, LUT_INDEX_WRITE);
for (i = 0; i < 256; i++) {
outb(gamma_table[i] >> 16, LUT_DATA);
outb(gamma_table[i] >> 8 & 0xFF, LUT_DATA);
outb(gamma_table[i] & 0xFF, LUT_DATA);
}
/* If adjust Gamma value in SAMM, fill IGA1,
IGA2 Gamma table simultanous. */
/* Switch to IGA2 Gamma Table */
if ((active_device_amount > 1) &&
!((viaparinfo->chip_info->gfx_chip_name ==
UNICHROME_CLE266) &&
(viaparinfo->chip_info->gfx_chip_revision < 15))) {
viafb_write_reg_mask(SR1A, VIASR, 0x01, BIT0);
viafb_write_reg_mask(CR6A, VIACR, 0x02, BIT1);
/* Fill IGA2 Gamma Table */
outb(0, LUT_INDEX_WRITE);
for (i = 0; i < 256; i++) {
outb(gamma_table[i] >> 16, LUT_DATA);
outb(gamma_table[i] >> 8 & 0xFF, LUT_DATA);
outb(gamma_table[i] & 0xFF, LUT_DATA);
}
}
viafb_write_reg(SR1A, VIASR, sr1a);
}
void viafb_get_gamma_table(unsigned int *gamma_table)
{
unsigned char color_r, color_g, color_b;
unsigned char sr1a = 0;
int i;
/* Enable Gamma */
switch (viaparinfo->chip_info->gfx_chip_name) {
case UNICHROME_CLE266:
case UNICHROME_K400:
viafb_write_reg_mask(SR16, VIASR, 0x80, BIT7);
break;
case UNICHROME_K800:
case UNICHROME_PM800:
case UNICHROME_CN700:
case UNICHROME_CX700:
case UNICHROME_K8M890:
case UNICHROME_P4M890:
case UNICHROME_P4M900:
viafb_write_reg_mask(CR33, VIACR, 0x80, BIT7);
break;
}
sr1a = viafb_read_reg(VIASR, SR1A);
viafb_write_reg_mask(SR1A, VIASR, 0x0, BIT0);
/* Reading gamma table to get color value */
outb(0, LUT_INDEX_READ);
for (i = 0; i < 256; i++) {
color_r = inb(LUT_DATA);
color_g = inb(LUT_DATA);
color_b = inb(LUT_DATA);
gamma_table[i] =
((((u32) color_r) << 16) |
(((u16) color_g) << 8)) | color_b;
}
viafb_write_reg(SR1A, VIASR, sr1a);
}
void viafb_get_gamma_support_state(int bpp, unsigned int *support_state)
{
if (bpp == 8)
*support_state = None_Device;
else
*support_state = CRT_Device | DVI_Device | LCD_Device;
}
int viafb_input_parameter_converter(int parameter_value)
{
int result;
if (parameter_value >= 1 && parameter_value <= 9)
result = 1 << (parameter_value - 1);
else
result = 1;
return result;
}

View file

@ -0,0 +1,35 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __VIAUTILITY_H__
#define __VIAUTILITY_H__
/* These functions are used to get infomation about device's state */
void viafb_get_device_support_state(u32 *support_state);
void viafb_get_device_connect_state(u32 *connect_state);
bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres);
/* These function are used to access gamma table */
void viafb_set_gamma_table(int bpp, unsigned int *gamma_table);
void viafb_get_gamma_table(unsigned int *gamma_table);
void viafb_get_gamma_support_state(int bpp, unsigned int *support_state);
int viafb_input_parameter_converter(int parameter_value);
#endif /* __VIAUTILITY_H__ */

2571
drivers/video/via/viafbdev.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,112 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __VIAFBDEV_H__
#define __VIAFBDEV_H__
#include <linux/proc_fs.h>
#include <linux/fb.h>
#include "ioctl.h"
#include "share.h"
#include "chip.h"
#include "hw.h"
#include "via_i2c.h"
#define VERSION_MAJOR 2
#define VERSION_KERNEL 6 /* For kernel 2.6 */
#define VERSION_OS 0 /* 0: for 32 bits OS, 1: for 64 bits OS */
#define VERSION_MINOR 4
struct viafb_par {
int bpp;
int hres;
int vres;
int linelength;
u32 xoffset;
u32 yoffset;
void __iomem *fbmem_virt; /*framebuffer virtual memory address */
void __iomem *io_virt; /*iospace virtual memory address */
unsigned int fbmem; /*framebuffer physical memory address */
unsigned int memsize; /*size of fbmem */
unsigned int io; /*io space address */
unsigned long mmio_base; /*mmio base address */
unsigned long mmio_len; /*mmio base length */
u32 fbmem_free; /* Free FB memory */
u32 fbmem_used; /* Use FB memory size */
u32 cursor_start; /* Cursor Start Address */
u32 VQ_start; /* Virtual Queue Start Address */
u32 VQ_end; /* Virtual Queue End Address */
u32 iga_path;
struct proc_dir_entry *proc_entry; /*viafb proc entry */
u8 duoview; /*Is working in duoview mode? */
/* I2C stuff */
struct via_i2c_stuff i2c_stuff;
/* All the information will be needed to set engine */
struct tmds_setting_information *tmds_setting_info;
struct crt_setting_information *crt_setting_info;
struct lvds_setting_information *lvds_setting_info;
struct lvds_setting_information *lvds_setting_info2;
struct chip_information *chip_info;
/* some information related to video playing */
int video_on_crt;
int video_on_dvi;
int video_on_lcd;
};
struct viafb_modeinfo {
u32 xres;
u32 yres;
int mode_index;
char *mode_res;
};
extern unsigned int viafb_second_virtual_yres;
extern unsigned int viafb_second_virtual_xres;
extern unsigned int viafb_second_offset;
extern int viafb_second_size;
extern int viafb_SAMM_ON;
extern int viafb_dual_fb;
extern int viafb_LCD2_ON;
extern int viafb_LCD_ON;
extern int viafb_DVI_ON;
extern int viafb_accel;
extern int viafb_hotplug;
extern int viafb_memsize;
extern int strict_strtoul(const char *cp, unsigned int base,
unsigned long *res);
void viafb_memory_pitch_patch(struct fb_info *info);
void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
int mode_index);
int viafb_get_mode_index(int hres, int vres, int flag);
u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
*plvds_setting_info, struct lvds_chip_information
*plvds_chip_info, u8 index);
void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information
*plvds_setting_info, struct lvds_chip_information
*plvds_chip_info, struct IODATA io_data);
#endif /* __VIAFBDEV_H__ */

1086
drivers/video/via/viamode.c Normal file

File diff suppressed because it is too large Load diff

177
drivers/video/via/viamode.h Normal file
View file

@ -0,0 +1,177 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __VIAMODE_H__
#define __VIAMODE_H__
#include "global.h"
struct VPITTable {
unsigned char Misc;
unsigned char SR[StdSR];
unsigned char GR[StdGR];
unsigned char AR[StdAR];
};
struct VideoModeTable {
int ModeIndex;
struct crt_mode_table *crtc;
int mode_array;
};
struct patch_table {
int mode_index;
int table_length;
struct io_reg *io_reg_table;
};
struct res_map_refresh {
int hres;
int vres;
int pixclock;
int vmode_refresh;
};
#define NUM_TOTAL_RES_MAP_REFRESH ARRAY_SIZE(res_map_refresh_tbl)
#define NUM_TOTAL_CEA_MODES ARRAY_SIZE(CEA_HDMI_Modes)
#define NUM_TOTAL_CN400_ModeXregs ARRAY_SIZE(CN400_ModeXregs)
#define NUM_TOTAL_CN700_ModeXregs ARRAY_SIZE(CN700_ModeXregs)
#define NUM_TOTAL_KM400_ModeXregs ARRAY_SIZE(KM400_ModeXregs)
#define NUM_TOTAL_CX700_ModeXregs ARRAY_SIZE(CX700_ModeXregs)
#define NUM_TOTAL_VX800_ModeXregs ARRAY_SIZE(VX800_ModeXregs)
#define NUM_TOTAL_CLE266_ModeXregs ARRAY_SIZE(CLE266_ModeXregs)
#define NUM_TOTAL_PATCH_MODE ARRAY_SIZE(res_patch_table)
#define NUM_TOTAL_MODETABLE ARRAY_SIZE(CLE266Modes)
/********************/
/* Mode Table */
/********************/
/* 480x640 */
extern struct crt_mode_table CRTM480x640[1];
/* 640x480*/
extern struct crt_mode_table CRTM640x480[5];
/*720x480 (GTF)*/
extern struct crt_mode_table CRTM720x480[1];
/*720x576 (GTF)*/
extern struct crt_mode_table CRTM720x576[1];
/* 800x480 (CVT) */
extern struct crt_mode_table CRTM800x480[1];
/* 800x600*/
extern struct crt_mode_table CRTM800x600[5];
/* 848x480 (CVT) */
extern struct crt_mode_table CRTM848x480[1];
/*856x480 (GTF) convert to 852x480*/
extern struct crt_mode_table CRTM852x480[1];
/*1024x512 (GTF)*/
extern struct crt_mode_table CRTM1024x512[1];
/* 1024x600*/
extern struct crt_mode_table CRTM1024x600[1];
/* 1024x768*/
extern struct crt_mode_table CRTM1024x768[4];
/* 1152x864*/
extern struct crt_mode_table CRTM1152x864[1];
/* 1280x720 (HDMI 720P)*/
extern struct crt_mode_table CRTM1280x720[2];
/*1280x768 (GTF)*/
extern struct crt_mode_table CRTM1280x768[2];
/* 1280x800 (CVT) */
extern struct crt_mode_table CRTM1280x800[1];
/*1280x960*/
extern struct crt_mode_table CRTM1280x960[1];
/* 1280x1024*/
extern struct crt_mode_table CRTM1280x1024[3];
/* 1368x768 (GTF) */
extern struct crt_mode_table CRTM1368x768[1];
/*1440x1050 (GTF)*/
extern struct crt_mode_table CRTM1440x1050[1];
/* 1600x1200*/
extern struct crt_mode_table CRTM1600x1200[2];
/* 1680x1050 (CVT) */
extern struct crt_mode_table CRTM1680x1050[2];
/* 1680x1050 (CVT Reduce Blanking) */
extern struct crt_mode_table CRTM1680x1050_RB[1];
/* 1920x1080 (CVT)*/
extern struct crt_mode_table CRTM1920x1080[1];
/* 1920x1080 (CVT with Reduce Blanking) */
extern struct crt_mode_table CRTM1920x1080_RB[1];
/* 1920x1440*/
extern struct crt_mode_table CRTM1920x1440[2];
/* 1400x1050 (CVT) */
extern struct crt_mode_table CRTM1400x1050[2];
/* 1400x1050 (CVT Reduce Blanking) */
extern struct crt_mode_table CRTM1400x1050_RB[1];
/* 960x600 (CVT) */
extern struct crt_mode_table CRTM960x600[1];
/* 1000x600 (GTF) */
extern struct crt_mode_table CRTM1000x600[1];
/* 1024x576 (GTF) */
extern struct crt_mode_table CRTM1024x576[1];
/* 1088x612 (CVT) */
extern struct crt_mode_table CRTM1088x612[1];
/* 1152x720 (CVT) */
extern struct crt_mode_table CRTM1152x720[1];
/* 1200x720 (GTF) */
extern struct crt_mode_table CRTM1200x720[1];
/* 1280x600 (GTF) */
extern struct crt_mode_table CRTM1280x600[1];
/* 1360x768 (CVT) */
extern struct crt_mode_table CRTM1360x768[1];
/* 1360x768 (CVT Reduce Blanking) */
extern struct crt_mode_table CRTM1360x768_RB[1];
/* 1366x768 (GTF) */
extern struct crt_mode_table CRTM1366x768[2];
/* 1440x900 (CVT) */
extern struct crt_mode_table CRTM1440x900[2];
/* 1440x900 (CVT Reduce Blanking) */
extern struct crt_mode_table CRTM1440x900_RB[1];
/* 1600x900 (CVT) */
extern struct crt_mode_table CRTM1600x900[1];
/* 1600x900 (CVT Reduce Blanking) */
extern struct crt_mode_table CRTM1600x900_RB[1];
/* 1600x1024 (GTF) */
extern struct crt_mode_table CRTM1600x1024[1];
/* 1792x1344 (DMT) */
extern struct crt_mode_table CRTM1792x1344[1];
/* 1856x1392 (DMT) */
extern struct crt_mode_table CRTM1856x1392[1];
/* 1920x1200 (CVT) */
extern struct crt_mode_table CRTM1920x1200[1];
/* 1920x1200 (CVT with Reduce Blanking) */
extern struct crt_mode_table CRTM1920x1200_RB[1];
/* 2048x1536 (CVT) */
extern struct crt_mode_table CRTM2048x1536[1];
extern struct VideoModeTable CLE266Modes[47];
extern struct crt_mode_table CEAM1280x720[1];
extern struct crt_mode_table CEAM1920x1080[1];
extern struct VideoModeTable CEA_HDMI_Modes[2];
extern struct res_map_refresh res_map_refresh_tbl[61];
extern struct io_reg CN400_ModeXregs[52];
extern struct io_reg CN700_ModeXregs[66];
extern struct io_reg KM400_ModeXregs[55];
extern struct io_reg CX700_ModeXregs[58];
extern struct io_reg VX800_ModeXregs[58];
extern struct io_reg CLE266_ModeXregs[32];
extern struct io_reg PM1024x768[2];
extern struct patch_table res_patch_table[1];
extern struct VPITTable VPIT;
#endif /* __VIAMODE_H__ */

306
drivers/video/via/vt1636.c Normal file
View file

@ -0,0 +1,306 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "global.h"
u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
*plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
u8 index)
{
u8 data;
viaparinfo->i2c_stuff.i2c_port = plvds_chip_info->i2c_port;
viafb_i2c_readbyte(plvds_chip_info->lvds_chip_slave_addr, index, &data);
return data;
}
void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information
*plvds_setting_info, struct lvds_chip_information
*plvds_chip_info, struct IODATA io_data)
{
int index, data;
viaparinfo->i2c_stuff.i2c_port = plvds_chip_info->i2c_port;
index = io_data.Index;
data = viafb_gpio_i2c_read_lvds(plvds_setting_info, plvds_chip_info,
index);
data = (data & (~io_data.Mask)) | io_data.Data;
viafb_i2c_writebyte(plvds_chip_info->lvds_chip_slave_addr, index, data);
}
void viafb_init_lvds_vt1636(struct lvds_setting_information
*plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
{
int reg_num, i;
/* Common settings: */
reg_num = ARRAY_SIZE(COMMON_INIT_TBL_VT1636);
for (i = 0; i < reg_num; i++) {
viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
plvds_chip_info,
COMMON_INIT_TBL_VT1636[i]);
}
/* Input Data Mode Select */
if (plvds_setting_info->device_lcd_dualedge) {
viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
plvds_chip_info,
DUAL_CHANNEL_ENABLE_TBL_VT1636[0]);
} else {
viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
plvds_chip_info,
SINGLE_CHANNEL_ENABLE_TBL_VT1636[0]);
}
if (plvds_setting_info->LCDDithering) {
viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
plvds_chip_info,
DITHERING_ENABLE_TBL_VT1636[0]);
} else {
viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
plvds_chip_info,
DITHERING_DISABLE_TBL_VT1636[0]);
}
}
void viafb_enable_lvds_vt1636(struct lvds_setting_information
*plvds_setting_info,
struct lvds_chip_information *plvds_chip_info)
{
viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
VDD_ON_TBL_VT1636[0]);
/* Pad on: */
switch (plvds_chip_info->output_interface) {
case INTERFACE_DVP0:
{
viafb_write_reg_mask(SR1E, VIASR, 0xC0, 0xC0);
break;
}
case INTERFACE_DVP1:
{
viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30);
break;
}
case INTERFACE_DFP_LOW:
{
viafb_write_reg_mask(SR2A, VIASR, 0x03, 0x03);
break;
}
case INTERFACE_DFP_HIGH:
{
viafb_write_reg_mask(SR2A, VIASR, 0x03, 0x0C);
break;
}
}
}
void viafb_disable_lvds_vt1636(struct lvds_setting_information
*plvds_setting_info,
struct lvds_chip_information *plvds_chip_info)
{
viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
VDD_OFF_TBL_VT1636[0]);
/* Pad off: */
switch (plvds_chip_info->output_interface) {
case INTERFACE_DVP0:
{
viafb_write_reg_mask(SR1E, VIASR, 0x00, 0xC0);
break;
}
case INTERFACE_DVP1:
{
viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30);
break;
}
case INTERFACE_DFP_LOW:
{
viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x03);
break;
}
case INTERFACE_DFP_HIGH:
{
viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x0C);
break;
}
}
}
bool viafb_lvds_identify_vt1636(void)
{
u8 Buffer[2];
DEBUG_MSG(KERN_INFO "viafb_lvds_identify_vt1636.\n");
/* Sense VT1636 LVDS Transmiter */
viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
VT1636_LVDS_I2C_ADDR;
/* Check vendor ID first: */
viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info.
lvds_chip_slave_addr,
0x00, &Buffer[0]);
viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info.
lvds_chip_slave_addr,
0x01, &Buffer[1]);
if (!((Buffer[0] == 0x06) && (Buffer[1] == 0x11)))
return false;
/* Check Chip ID: */
viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info.
lvds_chip_slave_addr,
0x02, &Buffer[0]);
viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info.
lvds_chip_slave_addr,
0x03, &Buffer[1]);
if ((Buffer[0] == 0x45) && (Buffer[1] == 0x33)) {
viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
VT1636_LVDS;
return true;
}
return false;
}
static int get_clk_range_index(u32 Clk)
{
if (Clk < DPA_CLK_30M)
return DPA_CLK_RANGE_30M;
else if (Clk < DPA_CLK_50M)
return DPA_CLK_RANGE_30_50M;
else if (Clk < DPA_CLK_70M)
return DPA_CLK_RANGE_50_70M;
else if (Clk < DPA_CLK_100M)
return DPA_CLK_RANGE_70_100M;
else if (Clk < DPA_CLK_150M)
return DPA_CLK_RANGE_100_150M;
else
return DPA_CLK_RANGE_150M;
}
static int get_lvds_dpa_setting_index(int panel_size_id,
struct VT1636_DPA_SETTING *p_vt1636_dpasetting_tbl,
int tbl_size)
{
int i;
for (i = 0; i < tbl_size; i++) {
if (panel_size_id == p_vt1636_dpasetting_tbl->PanelSizeID)
return i;
p_vt1636_dpasetting_tbl++;
}
return 0;
}
static void set_dpa_vt1636(struct lvds_setting_information
*plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
struct VT1636_DPA_SETTING *p_vt1636_dpa_setting)
{
struct IODATA io_data;
io_data.Index = 0x09;
io_data.Mask = 0x1F;
io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST1;
viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
plvds_chip_info, io_data);
io_data.Index = 0x08;
io_data.Mask = 0x0F;
io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST2;
viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
io_data);
}
void viafb_vt1636_patch_skew_on_vt3324(
struct lvds_setting_information *plvds_setting_info,
struct lvds_chip_information *plvds_chip_info)
{
int index, size;
DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3324.\n");
/* Graphics DPA settings: */
index = get_clk_range_index(plvds_setting_info->vclk);
viafb_set_dpa_gfx(plvds_chip_info->output_interface,
&GFX_DPA_SETTING_TBL_VT3324[index]);
/* LVDS Transmitter DPA settings: */
size = ARRAY_SIZE(VT1636_DPA_SETTING_TBL_VT3324);
index =
get_lvds_dpa_setting_index(plvds_setting_info->lcd_panel_id,
VT1636_DPA_SETTING_TBL_VT3324, size);
set_dpa_vt1636(plvds_setting_info, plvds_chip_info,
&VT1636_DPA_SETTING_TBL_VT3324[index]);
}
void viafb_vt1636_patch_skew_on_vt3327(
struct lvds_setting_information *plvds_setting_info,
struct lvds_chip_information *plvds_chip_info)
{
int index, size;
DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3327.\n");
/* Graphics DPA settings: */
index = get_clk_range_index(plvds_setting_info->vclk);
viafb_set_dpa_gfx(plvds_chip_info->output_interface,
&GFX_DPA_SETTING_TBL_VT3327[index]);
/* LVDS Transmitter DPA settings: */
size = ARRAY_SIZE(VT1636_DPA_SETTING_TBL_VT3327);
index =
get_lvds_dpa_setting_index(plvds_setting_info->lcd_panel_id,
VT1636_DPA_SETTING_TBL_VT3327, size);
set_dpa_vt1636(plvds_setting_info, plvds_chip_info,
&VT1636_DPA_SETTING_TBL_VT3327[index]);
}
void viafb_vt1636_patch_skew_on_vt3364(
struct lvds_setting_information *plvds_setting_info,
struct lvds_chip_information *plvds_chip_info)
{
int index;
DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3364.\n");
/* Graphics DPA settings: */
index = get_clk_range_index(plvds_setting_info->vclk);
viafb_set_dpa_gfx(plvds_chip_info->output_interface,
&GFX_DPA_SETTING_TBL_VT3364[index]);
}

View file

@ -0,0 +1,44 @@
/*
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
* Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE.See the GNU General Public License
* for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _VT1636_H_
#define _VT1636_H_
#include "chip.h"
bool viafb_lvds_identify_vt1636(void);
void viafb_init_lvds_vt1636(struct lvds_setting_information
*plvds_setting_info, struct lvds_chip_information *plvds_chip_info);
void viafb_enable_lvds_vt1636(struct lvds_setting_information
*plvds_setting_info,
struct lvds_chip_information *plvds_chip_info);
void viafb_disable_lvds_vt1636(struct lvds_setting_information
*plvds_setting_info,
struct lvds_chip_information *plvds_chip_info);
void viafb_vt1636_patch_skew_on_vt3324(
struct lvds_setting_information *plvds_setting_info,
struct lvds_chip_information *plvds_chip_info);
void viafb_vt1636_patch_skew_on_vt3327(
struct lvds_setting_information *plvds_setting_info,
struct lvds_chip_information *plvds_chip_info);
void viafb_vt1636_patch_skew_on_vt3364(
struct lvds_setting_information *plvds_setting_info,
struct lvds_chip_information *plvds_chip_info);
#endif

View file

@ -680,11 +680,11 @@ static struct xenbus_driver xenfb = {
static int __init xenfb_init(void)
{
if (!is_running_on_xen())
if (!xen_domain())
return -ENODEV;
/* Nothing to do if running in dom0. */
if (is_initial_xendomain())
if (xen_initial_domain())
return -ENODEV;
return xenbus_register_frontend(&xenfb);