Commit 2031ab46 authored by Russell King's avatar Russell King

Merge flint.arm.linux.org.uk:/usr/src/linux-bk-2.5/linux-2.5

into flint.arm.linux.org.uk:/usr/src/linux-bk-2.5/linux-2.5-rmk
parents 9038672a eb46c837
......@@ -18,14 +18,14 @@
* Please select one of the following when turning on debugging.
*/
#ifdef DEBUG
#if 0 /* DC21285-type */
#if defined(CONFIG_DEBUG_DC21285_PORT)
.macro loadsp, rb
mov \rb, #0x7c000000
.endm
.macro writeb, rb
strb \rb, [r3, #0x3f8]
.endm
#elif 0 /* RiscPC-type */
#elif defined(CONFIG_ARCH_RPC)
.macro loadsp, rb
mov \rb, #0x03000000
orr \rb, \rb, #0x00010000
......@@ -33,7 +33,7 @@
.macro writeb, rb
strb \rb, [r3, #0x3f8 << 2]
.endm
#elif 0 /* integrator-type */
#elif defined(CONFIG_ARCH_INTEGRATOR)
.macro loadsp, rb
mov \rb, #0x16000000
.endm
......
......@@ -694,7 +694,6 @@ dep_bool ' Verbose kernel error messages' CONFIG_DEBUG_ERRORS $CONFIG_DEBUG_KER
dep_bool ' Kernel low-level debugging functions' CONFIG_DEBUG_LL $CONFIG_DEBUG_KERNEL
dep_bool ' Kernel low-level debugging messages via footbridge serial port' CONFIG_DEBUG_DC21285_PORT $CONFIG_DEBUG_LL $CONFIG_FOOTBRIDGE
dep_bool ' Kernel low-level debugging messages via UART2' CONFIG_DEBUG_CLPS711X_UART2 $CONFIG_DEBUG_LL $CONFIG_ARCH_CLPS711X
dep_bool ' Kernel low-level debugging messages via SA1100 Ser3 (otherwise Ser1)' CONFIG_DEBUG_LL_SER3 $CONFIG_DEBUG_LL $CONFIG_ARCH_SA1100
endmenu
source lib/Config.in
......@@ -385,6 +385,55 @@
bne 1001b
.endm
#elif defined(CONFIG_ARCH_IQ80310)
.macro addruart,rx
mov \rx, #0xfe000000 @ physical
orr \rx, \rx, #0x00810000
.endm
.macro senduart,rd,rx
strb \rd, [\rx]
.endm
.macro busyuart,rd,rx
1002: ldrb \rd, [\rx, #0x5]
and \rd, \rd, #0x60
teq \rd, #0x60
bne 1002b
.endm
.macro waituart,rd,rx
1001: ldrb \rd, [\rx, #0x6]
tst \rd, #0x10
beq 1001b
.endm
#elif defined(CONFIG_ARCH_ADI_EVB)
.macro addruart,rx
mrc p15, 0, \rx, c1, c0
tst \rx, #1 @ MMU enabled?
mov \rx, #0x00400000 @ physical base address
orrne \rx, \rx, #0xff000000 @ virtual base
.endm
.macro senduart,rd,rx
strb \rd, [\rx]
.endm
.macro busyuart,rd,rx
1002: ldrb \rd, [\rx, #0x5]
and \rd, \rd, #0x60
teq \rd, #0x60
bne 1002b
.endm
.macro waituart,rd,rx
1001: ldrb \rd, [\rx, #0x6]
tst \rd, #0x10
beq 1001b
.endm
#else
#error Unknown architecture
#endif
......
......@@ -6,7 +6,6 @@
#include <asm/errno.h>
#include <asm/hardware.h>
#include <asm/arch/irqs.h>
#include <asm/proc-fns.h>
#ifndef MODE_SVC
#define MODE_SVC 0x13
......
......@@ -27,6 +27,7 @@
#include <asm/atomic.h>
#include <asm/io.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/uaccess.h>
......@@ -335,6 +336,25 @@ static int bad_syscall(int n, struct pt_regs *regs)
return regs->ARM_r0;
}
static inline void
do_cache_op(unsigned long start, unsigned long end, int flags)
{
struct vm_area_struct *vma;
if (end < start)
return;
vma = find_vma(current->active_mm, start);
if (vma && vma->vm_start < end) {
if (start < vma->vm_start)
start = vma->vm_start;
if (end > vma->vm_end)
end = vma->vm_end;
flush_cache_range(vma, start, end);
}
}
/*
* Handle all unrecognised system calls.
* 0x9f0000 - 0x9fffff are some more esoteric system calls
......@@ -392,7 +412,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
* the specified region).
*/
case NR(cacheflush):
cpu_cache_clean_invalidate_range(regs->ARM_r0, regs->ARM_r1, 1);
do_cache_op(regs->ARM_r0, regs->ARM_r1, regs->ARM_r2);
return 0;
case NR(usr26):
......
......@@ -62,7 +62,7 @@ static u_long iq80310_read_timer (void)
*/
static unsigned long iq80310_gettimeoffset (void)
{
unsigned long elapsed, usec, tmp1;
unsigned long elapsed, usec;
unsigned int stat1, stat2;
stat1 = *(volatile u8 *)IQ80310_INT_STAT;
......
......@@ -187,9 +187,9 @@ fixup_badge4(struct machine_desc *desc, struct param_struct *params,
static struct map_desc badge4_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
{0xf1000000, 0x08000000, 0x00100000, DOMAIN_IO, 1,1,0,0},/* SRAM bank 1 */
{0xf2000000, 0x10000000, 0x00100000, DOMAIN_IO, 1,1,0,0},/* SRAM bank 2 */
{0xf4000000, 0x48000000, 0x00100000, DOMAIN_IO, 1,1,0,0},/* SA-1111 */
{0xf1000000, 0x08000000, 0x00100000, DOMAIN_IO, 0,1,0,0},/* SRAM bank 1 */
{0xf2000000, 0x10000000, 0x00100000, DOMAIN_IO, 0,1,0,0},/* SRAM bank 2 */
{0xf4000000, 0x48000000, 0x00100000, DOMAIN_IO, 0,1,0,0},/* SA-1111 */
LAST_DESC
};
......
......@@ -399,24 +399,6 @@ static u_int h3600_uart_get_mctrl(struct uart_port *port)
return ret;
}
static void h3600_dcd_intr(int irq, void *dev_id, struct pt_regs *regs)
{
struct uart_info *info = dev_id;
/* Note: should only call this if something has changed */
spin_lock_irq(&info->lock);
uart_handle_dcd_change(info, !(GPLR & GPIO_H3600_COM_DCD));
spin_unlock_irq(&info->lock);
}
static void h3600_cts_intr(int irq, void *dev_id, struct pt_regs *regs)
{
struct uart_info *info = dev_id;
/* Note: should only call this if something has changed */
spin_lock_irq(&info->lock);
uart_handle_cts_change(info, !(GPLR & GPIO_H3600_COM_CTS));
spin_unlock_irq(&info->lock);
}
static void h3600_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
{
if (port->mapbase == _Ser2UTCR0) {
......@@ -444,47 +426,11 @@ static int h3600_uart_set_wake(struct uart_port *port, u_int enable)
return err;
}
static int h3600_uart_open(struct uart_port *port, struct uart_info *info)
{
int ret = 0;
if (port->mapbase == _Ser2UTCR0) {
Ser2UTCR4 = UTCR4_HSE;
Ser2HSCR0 = 0;
Ser2HSSR0 = HSSR0_EIF | HSSR0_TUR |
HSSR0_RAB | HSSR0_FRE;
} else if (port->mapbase == _Ser3UTCR0) {
set_GPIO_IRQ_edge(GPIO_H3600_COM_DCD|GPIO_H3600_COM_CTS,
GPIO_BOTH_EDGES);
ret = request_irq(IRQ_GPIO_H3600_COM_DCD, h3600_dcd_intr,
0, "RS232 DCD", info);
if (ret)
return ret;
ret = request_irq(IRQ_GPIO_H3600_COM_CTS, h3600_cts_intr,
0, "RS232 CTS", info);
if (ret)
free_irq(IRQ_GPIO_H3600_COM_DCD, info);
}
return ret;
}
static void h3600_uart_close(struct uart_port *port, struct uart_info *info)
{
if (port->mapbase == _Ser3UTCR0) {
free_irq(IRQ_GPIO_H3600_COM_DCD, info);
free_irq(IRQ_GPIO_H3600_COM_CTS, info);
}
}
static struct sa1100_port_fns h3600_port_fns __initdata = {
set_mctrl: h3600_uart_set_mctrl,
get_mctrl: h3600_uart_get_mctrl,
pm: h3600_uart_pm,
set_wake: h3600_uart_set_wake,
open: h3600_uart_open,
close: h3600_uart_close,
};
static struct map_desc h3600_io_desc[] __initdata = {
......
......@@ -17,6 +17,8 @@ sa1100_leds_init(void)
{
if (machine_is_assabet())
leds_event = assabet_leds_event;
if (machine_is_consus())
leds_event = consus_leds_event;
if (machine_is_brutus())
leds_event = brutus_leds_event;
if (machine_is_cerf())
......
extern void assabet_leds_event(led_event_t evt);
extern void consus_leds_event(led_event_t evt);
extern void brutus_leds_event(led_event_t evt);
extern void cerf_leds_event(led_event_t evt);
extern void flexanet_leds_event(led_event_t evt);
......
......@@ -243,10 +243,8 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
struct page *page = pte_page(pte);
if (VALID_PAGE(page) && page->mapping) {
if (test_and_clear_bit(PG_dcache_dirty, &page->flags)) {
unsigned long kvirt = (unsigned long)page_address(page);
cpu_cache_clean_invalidate_range(kvirt, kvirt + PAGE_SIZE, 0);
}
if (test_and_clear_bit(PG_dcache_dirty, &page->flags))
__flush_dcache_page(page);
make_coherent(vma, addr, page);
}
......
......@@ -60,10 +60,6 @@ __setup("nowb", nowrite_setup);
#define FIRST_KERNEL_PGD_NR (FIRST_USER_PGD_NR + USER_PTRS_PER_PGD)
#define clean_cache_area(start,size) \
cpu_cache_clean_invalidate_range((unsigned long)start, ((unsigned long)start) + size, 0);
/*
* need to get a 16k page for level 1
*/
......@@ -114,10 +110,7 @@ pgd_t *get_pgd_slow(struct mm_struct *mm)
memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
(PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
/*
* FIXME: this should not be necessary
*/
clean_cache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
return new_pgd;
......
/*
* We need constants.h for:
* VMA_VM_MM
* VMA_VM_FLAGS
* VM_EXEC
*/
#include <asm/constants.h>
#include <asm/thread_info.h>
/*
......
......@@ -79,10 +79,12 @@ ENTRY(v3_flush_kern_tlb_page)
mcr p15, 0, r0, c6, c0, 0 @ invalidate TLB entry
mov pc, lr
.section ".text.init", #alloc, #execinstr
ENTRY(v3_tlb_fns)
.word v3_flush_kern_tlb_all
.word v3_flush_user_tlb_mm
.word v3_flush_user_tlb_range
.word v3_flush_user_tlb_page
.word v3_flush_kern_tlb_page
.long v3_flush_kern_tlb_all
.long v3_flush_user_tlb_mm
.long v3_flush_user_tlb_range
.long v3_flush_user_tlb_page
.long v3_flush_kern_tlb_page
......@@ -98,9 +98,11 @@ ENTRY(v4_flush_kern_tlb_page)
mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
mov pc, lr
.section ".text.init", #alloc, #execinstr
ENTRY(v4_tlb_fns)
.word v4_flush_kern_tlb_all
.word v4_flush_user_tlb_mm
.word v4_flush_user_tlb_range
.word v4_flush_user_tlb_page
.word v4_flush_kern_tlb_page
.long v4_flush_kern_tlb_all
.long v4_flush_user_tlb_mm
.long v4_flush_user_tlb_range
.long v4_flush_user_tlb_page
.long v4_flush_kern_tlb_page
......@@ -144,17 +144,19 @@ ENTRY(v4wbi_flush_kern_tlb_page)
mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
mov pc, lr
.section ".text.init", #alloc, #execinstr
ENTRY(v4wb_tlb_fns)
.word v4wb_flush_kern_tlb_all
.word v4wb_flush_user_tlb_mm
.word v4wb_flush_user_tlb_range
.word v4wb_flush_user_tlb_page
.word v4wb_flush_kern_tlb_page
.long v4wb_flush_kern_tlb_all
.long v4wb_flush_user_tlb_mm
.long v4wb_flush_user_tlb_range
.long v4wb_flush_user_tlb_page
.long v4wb_flush_kern_tlb_page
ENTRY(v4wbi_tlb_fns)
.word v4wbi_flush_kern_tlb_all
.word v4wbi_flush_user_tlb_mm
.word v4wbi_flush_user_tlb_range
.word v4wbi_flush_user_tlb_page
.word v4wbi_flush_kern_tlb_page
.long v4wbi_flush_kern_tlb_all
.long v4wbi_flush_user_tlb_mm
.long v4wbi_flush_user_tlb_range
.long v4wbi_flush_user_tlb_page
.long v4wbi_flush_kern_tlb_page
......@@ -6,7 +6,7 @@
# To add an entry into this database, please see Documentation/arm/README,
# or contact rmk@arm.linux.org.uk
#
# Last update: Sun Feb 24 17:43:42 2002
# Last update: Fri Mar 8 20:08:02 2002
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
......@@ -147,7 +147,7 @@ whitechapel SA1100_WHITECHAPEL WHITECHAPEL 135
h3100 SA1100_H3100 H3100 136
h3800 SA1100_H3800 H3800 137
blue_v1 ARCH_BLUE_V1 BLUE_V1 138
xscale_cerf ARCH_XSCALE_CERF XSCALE_CERF 139
pxa_cerf ARCH_PXA_CERF PXA_CERF 139
arm7tevb ARCH_ARM7TEVB ARM7TEVB 140
d7400 ARCH_D7400 D7400 141
piranha ARCH_PIRANHA PIRANHA 142
......@@ -174,3 +174,5 @@ h7202 ARCH_H7202 H7202 162
amico ARCH_AMICO AMICO 163
iam SA1100_IAM IAM 164
tt530 SA1100_TT530 TT530 165
sam2400 ARCH_SAM2400 SAM2400 166
jornada56x ARCH_JORNADA56X JORNADA56X 167
......@@ -348,7 +348,7 @@ static struct miscdevice ds1620_miscdev = {
&ds1620_fops
};
int __init ds1620_init(void)
static int __init ds1620_init(void)
{
int ret;
struct therm th, th_start;
......@@ -400,7 +400,7 @@ int __init ds1620_init(void)
return 0;
}
void __exit ds1620_exit(void)
static void __exit ds1620_exit(void)
{
#ifdef THERM_USE_PROC
remove_proc_entry("therm", NULL);
......
......@@ -672,7 +672,7 @@ static int __init nwflash_init(void)
if (machine_is_netwinder()) {
int id;
FLASH_BASE = __ioremap(DC21285_FLASH, KFLASH_SIZE4, 0);
FLASH_BASE = ioremap(DC21285_FLASH, KFLASH_SIZE4);
if (!FLASH_BASE)
goto out;
......
......@@ -27,13 +27,23 @@ if [ "$CONFIG_FB" = "y" ]; then
fi
fi
fi
if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
bool ' Acorn VIDC support' CONFIG_FB_ACORN
fi
dep_tristate ' Cyber2000 support' CONFIG_FB_CYBER2000 $CONFIG_PCI
if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
bool ' SA-1100 LCD support' CONFIG_FB_SA1100
if [ "$CONFIG_ARM" = "y" ]; then
dep_bool ' Acorn VIDC support' CONFIG_FB_ACORN $CONFIG_ARCH_ACORN
dep_bool ' Anakin LCD support' CONFIG_FB_ANAKIN $CONFIG_ARCH_ANAKIN
dep_bool ' CLPS711X LCD support' CONFIG_FB_CLPS711X $CONFIG_ARCH_CLPS711X
dep_bool ' SA-1100 LCD support' CONFIG_FB_SA1100 $CONFIG_ARCH_SA1100
if [ "$CONFIG_FB_SA1100" = "y" -a "$CONFIG_SA1100_CERF" = "y" ]; then
choice 'CerfBoard LCD Display Size' \
"3.8_Color CONFIG_CERF_LCD_38_A \
3.8_Mono CONFIG_CERF_LCD_38_B \
5.7 CONFIG_CERF_LCD_57_A \
7.2 CONFIG_CERF_LCD_72_A" 5.7
fi
if [ "$CONFIG_FB_SA1100" = "y" -a "$CONFIG_SA1100_CERF_CPLD" = "y" ]; then
bool 'Cerfboard Backlight (CerfPDA)' CONFIG_SA1100_CERF_LCD_BACKLIGHT
fi
fi
dep_tristate ' CyberPro 2000/2010/5000 support' CONFIG_FB_CYBER2000 $CONFIG_PCI
if [ "$CONFIG_APOLLO" = "y" ]; then
define_bool CONFIG_FB_APOLLO y
fi
......
......@@ -55,6 +55,8 @@ obj-$(CONFIG_FB_CONTROL) += controlfb.o
obj-$(CONFIG_FB_PLATINUM) += platinumfb.o
obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o
obj-$(CONFIG_FB_CT65550) += chipsfb.o
obj-$(CONFIG_FB_ANAKIN) += anakinfb.o
obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o
obj-$(CONFIG_FB_CYBER) += cyberfb.o
obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
obj-$(CONFIG_FB_SGIVW) += sgivwfb.o
......
/*
* linux/drivers/video/anakinfb.c
*
* Copyright (C) 2001 Aleph One Ltd. for Acunia N.V.
*
* 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.
*
* Changelog:
* 23-Apr-2001 TTC Created
*/
#include <linux/types.h>
#include <linux/fb.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/module.h>
#include <asm/io.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb16.h>
static u16 colreg[16];
static int currcon = 0;
static struct fb_info fb_info;
static struct display display;
static int
anakinfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info)
{
if (regno > 15)
return 1;
*red = colreg[regno] & 0xf800;
*green = colreg[regno] & 0x7e0 << 5;
*blue = colreg[regno] & 0x1f << 11;
*transp = 0;
return 0;
}
static int
anakinfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
if (regno > 15)
return 1;
colreg[regno] = (red & 0xf800) | (green & 0xfc00 >> 5) |
(blue & 0xf800 >> 11);
return 0;
}
static int
anakinfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
{
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id, "AnakinFB");
fix->smem_start = VGA_START;
fix->smem_len = VGA_SIZE;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0;
fix->visual = FB_VISUAL_TRUECOLOR;
fix->xpanstep = 0;
fix->ypanstep = 0;
fix->ywrapstep = 0;
fix->line_length = 400 * 2;
fix->accel = FB_ACCEL_NONE;
return 0;
}
static int
anakinfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
memset(var, 0, sizeof(struct fb_var_screeninfo));
var->xres = 400;
var->yres = 234;
var->xres_virtual = 400;
var->yres_virtual = 234;
var->xoffset = 0;
var->yoffset = 0;
var->bits_per_pixel = 16;
var->grayscale = 0;
var->red.offset = 11;
var->red.length = 5;
var->green.offset = 5;
var->green.length = 6;
var->blue.offset = 0;
var->blue.length = 5;
var->transp.offset = 0;
var->transp.length = 0;
var->nonstd = 0;
var->activate = FB_ACTIVATE_NOW;
var->height = -1;
var->width = -1;
var->pixclock = 0;
var->left_margin = 0;
var->right_margin = 0;
var->upper_margin = 0;
var->lower_margin = 0;
var->hsync_len = 0;
var->vsync_len = 0;
var->sync = 0;
var->vmode = FB_VMODE_NONINTERLACED;
return 0;
}
static int
anakinfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
return -EINVAL;
}
static int
anakinfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
if (con == currcon)
return fb_get_cmap(cmap, kspc, anakinfb_getcolreg, info);
else if (fb_display[con].cmap.len)
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
fb_copy_cmap(fb_default_cmap(16), cmap, kspc ? 0 : 2);
return 0;
}
static int
anakinfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
int err;
if (!fb_display[con].cmap.len) {
if ((err = fb_alloc_cmap(&fb_display[con].cmap, 16, 0)))
return err;
}
if (con == currcon)
return fb_set_cmap(cmap, kspc, anakinfb_setcolreg, info);
else
fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
return 0;
}
static int
anakinfb_switch_con(int con, struct fb_info *info)
{
currcon = con;
return 0;
}
static int
anakinfb_updatevar(int con, struct fb_info *info)
{
return 0;
}
static void
anakinfb_blank(int blank, struct fb_info *info)
{
/*
* TODO: use I2C to blank/unblank the screen
*/
}
static struct fb_ops anakinfb_ops = {
owner: THIS_MODULE,
fb_get_fix: anakinfb_get_fix,
fb_get_var: anakinfb_get_var,
fb_set_var: anakinfb_set_var,
fb_get_cmap: anakinfb_get_cmap,
fb_set_cmap: anakinfb_set_cmap,
};
int __init
anakinfb_init(void)
{
memset(&fb_info, 0, sizeof(struct fb_info));
strcpy(fb_info.modename, "AnakinFB");
fb_info.node = -1;
fb_info.flags = FBINFO_FLAG_DEFAULT;
fb_info.fbops = &anakinfb_ops;
fb_info.disp = &display;
strcpy(fb_info.fontname, "VGA8x16");
fb_info.changevar = NULL;
fb_info.switch_con = &anakinfb_switch_con;
fb_info.updatevar = &anakinfb_updatevar;
fb_info.blank = &anakinfb_blank;
memset(&display, 0, sizeof(struct display));
anakinfb_get_var(&display.var, 0, &fb_info);
display.screen_base = ioremap(VGA_START, VGA_SIZE);
display.visual = FB_VISUAL_TRUECOLOR;
display.type = FB_TYPE_PACKED_PIXELS;
display.type_aux = 0;
display.ypanstep = 0;
display.ywrapstep = 0;
display.line_length = 400 * 2;
display.can_soft_blank = 1;
display.inverse = 0;
#ifdef FBCON_HAS_CFB16
display.dispsw = &fbcon_cfb16;
display.dispsw_data = colreg;
#else
display.dispsw = &fbcon_dummy;
#endif
if (register_framebuffer(&fb_info) < 0)
return -EINVAL;
MOD_INC_USE_COUNT;
return 0;
}
MODULE_AUTHOR("Tak-Shing Chan <chan@aleph1.co.uk>");
MODULE_DESCRIPTION("Anakin framebuffer driver");
MODULE_SUPPORTED_DEVICE("fb");
/*
* linux/drivers/video/clps711xfb.c
*
* Copyright (C) 2000-2001 Deep Blue Solutions Ltd.
*
* 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 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; 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
*
* Framebuffer driver for the CLPS7111 and EP7212 processors.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb4.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/uaccess.h>
#include <asm/hardware/clps7111.h>
#include <asm/arch/syspld.h>
static struct clps7111fb_info {
struct fb_info fb;
int currcon;
} *cfb;
#define CMAP_SIZE 16
/* The /proc entry for the backlight. */
static struct proc_dir_entry *clps7111fb_backlight_proc_entry = NULL;
static int clps7111fb_proc_backlight_read(char *page, char **start, off_t off,
int count, int *eof, void *data);
static int clps7111fb_proc_backlight_write(struct file *file,
const char *buffer, unsigned long count, void *data);
/*
* Set a single color register. Return != 0 for invalid regno.
*/
static int
clps7111fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
unsigned int level, mask, shift, pal;
if (regno >= CMAP_SIZE)
return 1;
/* gray = 0.30*R + 0.58*G + 0.11*B */
level = (red * 77 + green * 151 + blue * 28) >> 20;
/*
* On an LCD, a high value is dark, while a low value is light.
* So we invert the level.
*
* This isn't true on all machines, so we only do it on EDB7211.
* --rmk
*/
if (machine_is_edb7211()) {
level = 15 - level;
}
shift = 4 * (regno & 7);
level <<= shift;
mask = 15 << shift;
level &= mask;
regno = regno < 8 ? PALLSW : PALMSW;
pal = clps_readl(regno);
pal = (pal & ~mask) | level;
clps_writel(pal, regno);
return 0;
}
/*
* Set the colormap
*/
static int
clps7111fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
struct clps7111fb_info *cfb = (struct clps7111fb_info *)info;
struct fb_cmap *dcmap = &fb_display[con].cmap;
int err = 0;
/* no colormap allocated? */
if (!dcmap->len)
err = fb_alloc_cmap(dcmap, CMAP_SIZE, 0);
if (!err && con == cfb->currcon) {
err = fb_set_cmap(cmap, kspc, clps7111fb_setcolreg, &cfb->fb);
dcmap = &cfb->fb.cmap;
}
if (!err)
fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1);
return err;
}
/*
* Set the User Defined Part of the Display
*/
static int
clps7111fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
struct display *display;
unsigned int lcdcon, syscon;
int chgvar = 0;
if (var->activate & FB_ACTIVATE_TEST)
return 0;
if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
return -EINVAL;
if (cfb->fb.var.xres != var->xres)
chgvar = 1;
if (cfb->fb.var.yres != var->yres)
chgvar = 1;
if (cfb->fb.var.xres_virtual != var->xres_virtual)
chgvar = 1;
if (cfb->fb.var.yres_virtual != var->yres_virtual)
chgvar = 1;
if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel)
chgvar = 1;
if (con < 0) {
display = cfb->fb.disp;
chgvar = 0;
} else {
display = fb_display + con;
}
var->transp.msb_right = 0;
var->transp.offset = 0;
var->transp.length = 0;
var->red.msb_right = 0;
var->red.offset = 0;
var->red.length = var->bits_per_pixel;
var->green = var->red;
var->blue = var->red;
switch (var->bits_per_pixel) {
#ifdef FBCON_HAS_MFB
case 1:
cfb->fb.fix.visual = FB_VISUAL_MONO01;
display->dispsw = &fbcon_mfb;
display->dispsw_data = NULL;
break;
#endif
#ifdef FBCON_HAS_CFB2
case 2:
cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
display->dispsw = &fbcon_cfb2;
display->dispsw_data = NULL;
break;
#endif
#ifdef FBCON_HAS_CFB4
case 4:
cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
display->dispsw = &fbcon_cfb4;
display->dispsw_data = NULL;
break;
#endif
default:
return -EINVAL;
}
display->next_line = var->xres_virtual * var->bits_per_pixel / 8;
cfb->fb.fix.line_length = display->next_line;
display->screen_base = cfb->fb.screen_base;
display->line_length = cfb->fb.fix.line_length;
display->visual = cfb->fb.fix.visual;
display->type = cfb->fb.fix.type;
display->type_aux = cfb->fb.fix.type_aux;
display->ypanstep = cfb->fb.fix.ypanstep;
display->ywrapstep = cfb->fb.fix.ywrapstep;
display->can_soft_blank = 1;
display->inverse = 0;
cfb->fb.var = *var;
cfb->fb.var.activate &= ~FB_ACTIVATE_ALL;
/*
* Update the old var. The fbcon drivers still use this.
* Once they are using cfb->fb.var, this can be dropped.
* --rmk
*/
display->var = cfb->fb.var;
/*
* If we are setting all the virtual consoles, also set the
* defaults used to create new consoles.
*/
if (var->activate & FB_ACTIVATE_ALL)
cfb->fb.disp->var = cfb->fb.var;
if (chgvar && info && cfb->fb.changevar)
cfb->fb.changevar(con);
/*
* LCDCON must only be changed while the LCD is disabled
*/
lcdcon = (var->xres_virtual * var->yres_virtual * var->bits_per_pixel) / 128 - 1;
lcdcon |= ((var->xres_virtual / 16) - 1) << 13;
lcdcon |= 2 << 19;
lcdcon |= 13 << 25;
lcdcon |= LCDCON_GSEN;
lcdcon |= LCDCON_GSMD;
syscon = clps_readl(SYSCON1);
clps_writel(syscon & ~SYSCON1_LCDEN, SYSCON1);
clps_writel(lcdcon, LCDCON);
clps_writel(syscon | SYSCON1_LCDEN, SYSCON1);
fb_set_cmap(&cfb->fb.cmap, 1, clps7111fb_setcolreg, &cfb->fb);
return 0;
}
/*
* Get the currently displayed virtual consoles colormap.
*/
static int
gen_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
{
fb_copy_cmap(&info->cmap, cmap, kspc ? 0 : 2);
return 0;
}
/*
* Get the currently displayed virtual consoles fixed part of the display.
*/
static int
gen_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
{
*fix = info->fix;
return 0;
}
/*
* Get the current user defined part of the display.
*/
static int
gen_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
*var = info->var;
return 0;
}
static struct fb_ops clps7111fb_ops = {
owner: THIS_MODULE,
fb_set_var: clps7111fb_set_var,
fb_set_cmap: clps7111fb_set_cmap,
fb_get_fix: gen_get_fix,
fb_get_var: gen_get_var,
fb_get_cmap: gen_get_cmap,
};
static int clps7111fb_switch(int con, struct fb_info *info)
{
struct clps7111fb_info *cfb = (struct clps7111fb_info *)info;
struct display *disp;
struct fb_cmap *cmap;
if (cfb->currcon >= 0) {
disp = fb_display + cfb->currcon;
/*
* Save the old colormap and video mode.
*/
disp->var = cfb->fb.var;
if (disp->cmap.len)
fb_copy_cmap(&cfb->fb.cmap, &disp->cmap, 0);
}
cfb->currcon = con;
disp = fb_display + con;
/*
* Install the new colormap and change the video mode. By default,
* fbcon sets all the colormaps and video modes to the default
* values at bootup.
*/
if (disp->cmap.len)
cmap = &disp->cmap;
else
cmap = fb_default_cmap(CMAP_SIZE);
fb_copy_cmap(cmap, &cfb->fb.cmap, 0);
cfb->fb.var = disp->var;
cfb->fb.var.activate = FB_ACTIVATE_NOW;
clps7111fb_set_var(&cfb->fb.var, con, &cfb->fb);
return 0;
}
static int clps7111fb_updatevar(int con, struct fb_info *info)
{
return -EINVAL;
}
static void clps7111fb_blank(int blank, struct fb_info *info)
{
if (blank) {
if (machine_is_edb7211()) {
int i;
/* Turn off the LCD backlight. */
clps_writeb(clps_readb(PDDR) & ~EDB_PD3_LCDBL, PDDR);
/* Power off the LCD DC-DC converter. */
clps_writeb(clps_readb(PDDR) & ~EDB_PD1_LCD_DC_DC_EN, PDDR);
/* Delay for a little while (half a second). */
for (i=0; i<65536*4; i++);
/* Power off the LCD panel. */
clps_writeb(clps_readb(PDDR) & ~EDB_PD2_LCDEN, PDDR);
/* Power off the LCD controller. */
clps_writel(clps_readl(SYSCON1) & ~SYSCON1_LCDEN,
SYSCON1);
}
} else {
if (machine_is_edb7211()) {
int i;
/* Power up the LCD controller. */
clps_writel(clps_readl(SYSCON1) | SYSCON1_LCDEN,
SYSCON1);
/* Power up the LCD panel. */
clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR);
/* Delay for a little while. */
for (i=0; i<65536*4; i++);
/* Power up the LCD DC-DC converter. */
clps_writeb(clps_readb(PDDR) | EDB_PD1_LCD_DC_DC_EN,
PDDR);
/* Turn on the LCD backlight. */
clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR);
}
}
}
static int
clps7111fb_proc_backlight_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
/* We need at least two characters, one for the digit, and one for
* the terminating NULL. */
if (count < 2)
return -EINVAL;
if (machine_is_edb7211()) {
return sprintf(page, "%d\n",
(clps_readb(PDDR) & EDB_PD3_LCDBL) ? 1 : 0);
}
return 0;
}
static int
clps7111fb_proc_backlight_write(struct file *file, const char *buffer,
unsigned long count, void *data)
{
unsigned char char_value;
int value;
if (count < 1) {
return -EINVAL;
}
if (copy_from_user(&char_value, buffer, 1))
return -EFAULT;
value = char_value - '0';
if (machine_is_edb7211()) {
unsigned char port_d;
port_d = clps_readb(PDDR);
if (value) {
port_d |= EDB_PD3_LCDBL;
} else {
port_d &= ~EDB_PD3_LCDBL;
}
clps_writeb(port_d, PDDR);
}
return count;
}
int __init clps711xfb_init(void)
{
int err = -ENOMEM;
cfb = kmalloc(sizeof(*cfb) + sizeof(struct display), GFP_KERNEL);
if (!cfb)
goto out;
memset(cfb, 0, sizeof(*cfb) + sizeof(struct display));
memset((void *)PAGE_OFFSET, 0, 0x14000);
cfb->currcon = -1;
strcpy(cfb->fb.fix.id, "clps7111");
cfb->fb.screen_base = (void *)PAGE_OFFSET;
cfb->fb.fix.smem_start = PAGE_OFFSET;
cfb->fb.fix.smem_len = 0x14000;
cfb->fb.fix.type = FB_TYPE_PACKED_PIXELS;
cfb->fb.var.xres = 640;
cfb->fb.var.xres_virtual = 640;
cfb->fb.var.yres = 240;
cfb->fb.var.yres_virtual = 240;
cfb->fb.var.bits_per_pixel = 4;
cfb->fb.var.grayscale = 1;
cfb->fb.var.activate = FB_ACTIVATE_NOW;
cfb->fb.var.height = -1;
cfb->fb.var.width = -1;
cfb->fb.fbops = &clps7111fb_ops;
cfb->fb.changevar = NULL;
cfb->fb.switch_con = clps7111fb_switch;
cfb->fb.updatevar = clps7111fb_updatevar;
cfb->fb.blank = clps7111fb_blank;
cfb->fb.flags = FBINFO_FLAG_DEFAULT;
cfb->fb.disp = (struct display *)(cfb + 1);
fb_alloc_cmap(&cfb->fb.cmap, CMAP_SIZE, 0);
/* Register the /proc entries. */
clps7111fb_backlight_proc_entry = create_proc_entry("backlight", 0444,
&proc_root);
if (clps7111fb_backlight_proc_entry == NULL) {
printk("Couldn't create the /proc entry for the backlight.\n");
return -EINVAL;
}
clps7111fb_backlight_proc_entry->read_proc =
&clps7111fb_proc_backlight_read;
clps7111fb_backlight_proc_entry->write_proc =
&clps7111fb_proc_backlight_write;
/*
* Power up the LCD
*/
if (machine_is_p720t()) {
PLD_LCDEN = PLD_LCDEN_EN;
PLD_PWR |= (PLD_S4_ON|PLD_S3_ON|PLD_S2_ON|PLD_S1_ON);
}
if (machine_is_edb7211()) {
int i;
/* Power up the LCD panel. */
clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR);
/* Delay for a little while. */
for (i=0; i<65536*4; i++);
/* Power up the LCD DC-DC converter. */
clps_writeb(clps_readb(PDDR) | EDB_PD1_LCD_DC_DC_EN, PDDR);
/* Turn on the LCD backlight. */
clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR);
}
clps7111fb_set_var(&cfb->fb.var, -1, &cfb->fb);
err = register_framebuffer(&cfb->fb);
out: return err;
}
static void __exit clps711xfb_exit(void)
{
unregister_framebuffer(&cfb->fb);
kfree(cfb);
/*
* Power down the LCD
*/
if (machine_is_p720t()) {
PLD_LCDEN = 0;
PLD_PWR &= ~(PLD_S4_ON|PLD_S3_ON|PLD_S2_ON|PLD_S1_ON);
}
}
#ifdef MODULE
module_init(clps711xfb_init);
#endif
module_exit(clps711xfb_exit);
......@@ -16,8 +16,7 @@
*
* Note that we now use the new fbcon fix, var and cmap scheme. We do still
* have to check which console is the currently displayed one however, since
* especially for the colourmap stuff. Once fbcon has been fully migrated,
* we can kill the last 5 references to cfb->currcon.
* especially for the colourmap stuff.
*
* We also use the new hotplug PCI subsystem. I'm not sure if there are any
* such cards, but I'm erring on the side of caution. We don't want to go
......@@ -61,10 +60,10 @@
struct cfb_info {
struct fb_info fb;
struct display_switch *dispsw;
struct display *display;
struct pci_dev *dev;
unsigned char *region;
unsigned char *regs;
signed int currcon;
int func_use_count;
u_long ref_ps;
......@@ -150,24 +149,24 @@ static void cyber2000_accel_wait(struct cfb_info *cfb)
}
}
static void cyber2000_accel_setup(struct display *p)
static void cyber2000_accel_setup(struct display *display)
{
struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
cfb->dispsw->setup(p);
cfb->dispsw->setup(display);
}
static void
cyber2000_accel_bmove(struct display *p, int sy, int sx, int dy, int dx,
cyber2000_accel_bmove(struct display *display, int sy, int sx, int dy, int dx,
int height, int width)
{
struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
struct fb_var_screeninfo *var = &p->fb_info->var;
struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
struct fb_var_screeninfo *var = &display->var;
u_long src, dst;
u_int fh, fw;
int cmd = CO_CMD_L_PATTERN_FGCOL;
fw = fontwidth(p);
fw = fontwidth(display);
sx *= fw;
dx *= fw;
width *= fw;
......@@ -179,7 +178,7 @@ cyber2000_accel_bmove(struct display *p, int sy, int sx, int dy, int dx,
cmd |= CO_CMD_L_INC_LEFT;
}
fh = fontheight(p);
fh = fontheight(display);
sy *= fh;
dy *= fh;
height *= fh;
......@@ -214,17 +213,17 @@ cyber2000_accel_bmove(struct display *p, int sy, int sx, int dy, int dx,
}
static void
cyber2000_accel_clear(struct vc_data *conp, struct display *p, int sy, int sx,
int height, int width)
cyber2000_accel_clear(struct vc_data *conp, struct display *display, int sy,
int sx, int height, int width)
{
struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
struct fb_var_screeninfo *var = &p->fb_info->var;
struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
struct fb_var_screeninfo *var = &display->var;
u_long dst;
u_int fw, fh;
u32 bgx = attr_bgcol_ec(p, conp);
u32 bgx = attr_bgcol_ec(display, conp);
fw = fontwidth(p);
fh = fontheight(p);
fw = fontwidth(display);
fh = fontheight(display);
dst = sx * fw + sy * var->xres_virtual * fh;
width = width * fw - 1;
......@@ -237,9 +236,8 @@ cyber2000_accel_clear(struct vc_data *conp, struct display *p, int sy, int sx,
cyber2000fb_writew(height, CO_REG_HEIGHT, cfb);
switch (var->bits_per_pixel) {
case 15:
case 16:
bgx = ((u16 *)p->dispsw_data)[bgx];
bgx = ((u16 *)display->dispsw_data)[bgx];
case 8:
cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
break;
......@@ -247,7 +245,7 @@ cyber2000_accel_clear(struct vc_data *conp, struct display *p, int sy, int sx,
case 24:
cyber2000fb_writel(dst * 3, CO_REG_DEST_PTR, cfb);
cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
bgx = ((u32 *)p->dispsw_data)[bgx];
bgx = ((u32 *)display->dispsw_data)[bgx];
break;
}
......@@ -257,40 +255,40 @@ cyber2000_accel_clear(struct vc_data *conp, struct display *p, int sy, int sx,
}
static void
cyber2000_accel_putc(struct vc_data *conp, struct display *p, int c,
cyber2000_accel_putc(struct vc_data *conp, struct display *display, int c,
int yy, int xx)
{
struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
cyber2000_accel_wait(cfb);
cfb->dispsw->putc(conp, p, c, yy, xx);
cfb->dispsw->putc(conp, display, c, yy, xx);
}
static void
cyber2000_accel_putcs(struct vc_data *conp, struct display *p,
cyber2000_accel_putcs(struct vc_data *conp, struct display *display,
const unsigned short *s, int count, int yy, int xx)
{
struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
cyber2000_accel_wait(cfb);
cfb->dispsw->putcs(conp, p, s, count, yy, xx);
cfb->dispsw->putcs(conp, display, s, count, yy, xx);
}
static void cyber2000_accel_revc(struct display *p, int xx, int yy)
static void cyber2000_accel_revc(struct display *display, int xx, int yy)
{
struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
cyber2000_accel_wait(cfb);
cfb->dispsw->revc(p, xx, yy);
cfb->dispsw->revc(display, xx, yy);
}
static void
cyber2000_accel_clear_margins(struct vc_data *conp, struct display *p,
cyber2000_accel_clear_margins(struct vc_data *conp, struct display *display,
int bottom_only)
{
struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
cfb->dispsw->clear_margins(conp, p, bottom_only);
cfb->dispsw->clear_margins(conp, display, bottom_only);
}
static struct display_switch fbcon_cyber_accel = {
......@@ -312,6 +310,7 @@ cyber2000_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
struct cfb_info *cfb = (struct cfb_info *)info;
struct fb_var_screeninfo *var = &cfb->display->var;
if (regno >= NR_PALETTE)
return 1;
......@@ -324,7 +323,7 @@ cyber2000_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
cfb->palette[regno].green = green;
cfb->palette[regno].blue = blue;
switch (cfb->fb.var.bits_per_pixel) {
switch (var->bits_per_pixel) {
#ifdef FBCON_HAS_CFB8
case 8:
cyber2000fb_writeb(regno, 0x3c8, cfb);
......@@ -337,29 +336,29 @@ cyber2000_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
#ifdef FBCON_HAS_CFB16
case 16:
#ifndef CFB16_IS_CFB15
if (regno < 64) {
/* write green */
cyber2000fb_writeb(regno << 2, 0x3c8, cfb);
cyber2000fb_writeb(cfb->palette[regno >> 1].red, 0x3c9, cfb);
cyber2000fb_writeb(green, 0x3c9, cfb);
cyber2000fb_writeb(cfb->palette[regno >> 1].blue, 0x3c9, cfb);
}
if (regno < 32) {
/* write red,blue */
cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
cyber2000fb_writeb(red, 0x3c9, cfb);
cyber2000fb_writeb(cfb->palette[regno << 1].green, 0x3c9, cfb);
cyber2000fb_writeb(blue, 0x3c9, cfb);
if (var->green.length == 6) {
if (regno < 64) {
/* write green */
cyber2000fb_writeb(regno << 2, 0x3c8, cfb);
cyber2000fb_writeb(cfb->palette[regno >> 1].red, 0x3c9, cfb);
cyber2000fb_writeb(green, 0x3c9, cfb);
cyber2000fb_writeb(cfb->palette[regno >> 1].blue, 0x3c9, cfb);
}
if (regno < 32) {
/* write red,blue */
cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
cyber2000fb_writeb(red, 0x3c9, cfb);
cyber2000fb_writeb(cfb->palette[regno << 1].green, 0x3c9, cfb);
cyber2000fb_writeb(blue, 0x3c9, cfb);
}
if (regno < 16)
((u16 *)cfb->fb.pseudo_palette)[regno] =
regno | regno << 5 | regno << 11;
break;
}
if (regno < 16)
((u16 *)cfb->fb.pseudo_palette)[regno] =
regno | regno << 5 | regno << 11;
break;
#endif
case 15:
if (regno < 32) {
cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
cyber2000fb_writeb(red, 0x3c9, cfb);
......@@ -399,7 +398,7 @@ struct par_info {
*/
u_char clock_mult;
u_char clock_div;
u_char visualid;
u_char extseqmisc;
u_char pixformat;
u_char crtc_ofl;
u_char crtc[19];
......@@ -483,10 +482,10 @@ static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
cyber2000fb_writeb(i, 0x3cf, cfb);
/* PLL registers */
cyber2000_grphw(DCLK_MULT, hw->clock_mult, cfb);
cyber2000_grphw(DCLK_DIV, hw->clock_div, cfb);
cyber2000_grphw(MCLK_MULT, cfb->mclk_mult, cfb);
cyber2000_grphw(MCLK_DIV, cfb->mclk_div, cfb);
cyber2000_grphw(EXT_DCLK_MULT, hw->clock_mult, cfb);
cyber2000_grphw(EXT_DCLK_DIV, hw->clock_div, cfb);
cyber2000_grphw(EXT_MCLK_MULT, cfb->mclk_mult, cfb);
cyber2000_grphw(EXT_MCLK_DIV, cfb->mclk_div, cfb);
cyber2000_grphw(0x90, 0x01, cfb);
cyber2000_grphw(0xb9, 0x80, cfb);
cyber2000_grphw(0xb9, 0x00, cfb);
......@@ -503,10 +502,11 @@ static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
cyber2000_grphw(0x14, hw->fetch, cfb);
cyber2000_grphw(0x15, ((hw->fetch >> 8) & 0x03) |
((hw->pitch >> 4) & 0x30), cfb);
cyber2000_grphw(0x77, hw->visualid, cfb);
cyber2000_grphw(EXT_SEQ_MISC, hw->extseqmisc, cfb);
/* make sure we stay in linear mode */
cyber2000_grphw(0x33, 0x0d, cfb);
cyber2000_grphw(EXT_BIU_MISC, EXT_BIU_MISC_LIN_ENABLE |
EXT_BIU_MISC_COP_ENABLE |
EXT_BIU_MISC_COP_BFC, cfb);
/*
* Set up accelerator registers
......@@ -521,9 +521,14 @@ cyber2000fb_update_start(struct cfb_info *cfb, struct fb_var_screeninfo *var)
{
u_int base;
base = var->yoffset * var->xres_virtual + var->xoffset;
base = var->yoffset * var->xres_virtual * var->bits_per_pixel +
var->xoffset * var->bits_per_pixel;
base >>= 2;
/*
* Convert to bytes and shift two extra bits because DAC
* can only start on 4 byte aligned data.
*/
base >>= 5;
if (base >= 1 << 20)
return -EINVAL;
......@@ -543,26 +548,19 @@ cyber2000fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
struct cfb_info *cfb = (struct cfb_info *)info;
struct fb_cmap *dcmap = &fb_display[con].cmap;
struct display *display = fb_display + con;
struct fb_cmap *dcmap = &display->cmap;
int err = 0;
/* no colormap allocated? */
if (!dcmap->len) {
int size;
if (cfb->fb.var.bits_per_pixel == 16)
size = 32;
else
size = 256;
err = fb_alloc_cmap(dcmap, size, 0);
}
if (!dcmap->len)
err = fb_alloc_cmap(dcmap, 256, 0);
/*
* we should be able to remove this test once fbcon has been
* "improved" --rmk
*/
if (!err && con == cfb->currcon) {
if (!err && display == cfb->display) {
err = fb_set_cmap(cmap, kspc, cyber2000_setcolreg, &cfb->fb);
dcmap = &cfb->fb.cmap;
}
......@@ -754,7 +752,7 @@ cyber2000fb_decode_clock(struct par_info *hw, struct cfb_info *cfb,
vco = ref_ps * best_div1 / best_mult;
if ((ref_ps == 40690) && (vco < 5556))
/* Set VFSEL when VCO > 180MHz (5.556 ps). */
hw->clock_div |= DCLK_DIV_VFSEL;
hw->clock_div |= EXT_DCLK_DIV_VFSEL;
return 0;
}
......@@ -778,31 +776,32 @@ cyber2000fb_decode_var(struct fb_var_screeninfo *var, struct cfb_info *cfb,
#ifdef FBCON_HAS_CFB8
case 8: /* PSEUDOCOLOUR, 256 */
hw->pixformat = PIXFORMAT_8BPP;
hw->visualid = VISUALID_256;
hw->extseqmisc = EXT_SEQ_MISC_8;
hw->pitch = hw->width >> 3;
break;
#endif
#ifdef FBCON_HAS_CFB16
case 16:/* DIRECTCOLOUR, 64k */
#ifndef CFB16_IS_CFB15
case 16:
hw->pixformat = PIXFORMAT_16BPP;
hw->visualid = VISUALID_64K;
hw->pitch = hw->width >> 2;
hw->palette_ctrl |= 0x10;
break;
#ifndef CFB16_IS_CFB15
/* DIRECTCOLOUR, 64k */
if (var->green.length == 6) {
hw->extseqmisc = EXT_SEQ_MISC_16_RGB565;
break;
}
#endif
case 15:/* DIRECTCOLOUR, 32k */
hw->pixformat = PIXFORMAT_16BPP;
hw->visualid = VISUALID_32K;
hw->pitch = hw->width >> 2;
hw->palette_ctrl |= 0x10;
/* DIRECTCOLOUR, 32k */
hw->extseqmisc = EXT_SEQ_MISC_16_RGB555;
break;
#endif
#ifdef FBCON_HAS_CFB24
case 24:/* TRUECOLOUR, 16m */
hw->pixformat = PIXFORMAT_24BPP;
hw->visualid = VISUALID_16M;
hw->extseqmisc = EXT_SEQ_MISC_24_RGB888;
hw->width *= 3;
hw->pitch = hw->width >> 3;
hw->palette_ctrl |= 0x10;
......@@ -847,8 +846,8 @@ cyber2000fb_set_var(struct fb_var_screeninfo *var, int con,
*/
if (var->vmode & FB_VMODE_CONUPDATE) {
var->vmode |= FB_VMODE_YWRAP;
var->xoffset = cfb->fb.var.xoffset;
var->yoffset = cfb->fb.var.yoffset;
var->xoffset = cfb->display->var.xoffset;
var->yoffset = cfb->display->var.yoffset;
}
err = cyber2000fb_decode_var(var, (struct cfb_info *)info, &hw);
......@@ -861,23 +860,26 @@ cyber2000fb_set_var(struct fb_var_screeninfo *var, int con,
if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
return -EINVAL;
if (cfb->fb.var.xres != var->xres)
if (con < 0) {
display = cfb->fb.disp;
chgvar = 0;
} else {
display = fb_display + con;
}
if (display->var.xres != var->xres)
chgvar = 1;
if (cfb->fb.var.yres != var->yres)
if (display->var.yres != var->yres)
chgvar = 1;
if (cfb->fb.var.xres_virtual != var->xres_virtual)
if (display->var.xres_virtual != var->xres_virtual)
chgvar = 1;
if (cfb->fb.var.yres_virtual != var->yres_virtual)
if (display->var.yres_virtual != var->yres_virtual)
chgvar = 1;
if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel)
if (display->var.bits_per_pixel != var->bits_per_pixel)
chgvar = 1;
if (con < 0) {
display = cfb->fb.disp;
if (con < 0)
chgvar = 0;
} else {
display = fb_display + con;
}
var->red.msb_right = 0;
var->green.msb_right = 0;
......@@ -900,13 +902,10 @@ cyber2000fb_set_var(struct fb_var_screeninfo *var, int con,
break;
#endif
#ifdef FBCON_HAS_CFB16
case 16:/* DIRECTCOLOUR, 64k */
#ifndef CFB16_IS_CFB15
var->bits_per_pixel = 15;
var->red.offset = 11;
case 16:
var->bits_per_pixel = 16;
var->red.length = 5;
var->green.offset = 5;
var->green.length = 6;
var->blue.offset = 0;
var->blue.length = 5;
......@@ -914,21 +913,18 @@ cyber2000fb_set_var(struct fb_var_screeninfo *var, int con,
cfb->dispsw = &fbcon_cfb16;
display->dispsw_data = cfb->fb.pseudo_palette;
display->next_line = var->xres_virtual * 2;
break;
#ifndef CFB16_IS_CFB15
/* DIRECTCOLOUR, 64k */
if (var->green.length == 6) {
var->red.offset = 11;
var->green.length = 6;
break;
}
#endif
case 15:/* DIRECTCOLOUR, 32k */
var->bits_per_pixel = 15;
/* DIRECTCOLOUR, 32k */
var->red.offset = 10;
var->red.length = 5;
var->green.offset = 5;
var->green.length = 5;
var->blue.offset = 0;
var->blue.length = 5;
cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR;
cfb->dispsw = &fbcon_cfb16;
display->dispsw_data = cfb->fb.pseudo_palette;
display->next_line = var->xres_virtual * 2;
break;
#endif
#ifdef FBCON_HAS_CFB24
......@@ -969,23 +965,17 @@ cyber2000fb_set_var(struct fb_var_screeninfo *var, int con,
display->ywrapstep = cfb->fb.fix.ywrapstep;
display->can_soft_blank = 1;
display->inverse = 0;
display->var = *var;
display->var.activate &= ~FB_ACTIVATE_ALL;
cfb->fb.var = *var;
cfb->fb.var.activate &= ~FB_ACTIVATE_ALL;
/*
* Update the old var. The fbcon drivers still use this.
* Once they are using cfb->fb.var, this can be dropped.
* --rmk
*/
display->var = cfb->fb.var;
cfb->fb.var = display->var;
/*
* If we are setting all the virtual consoles, also set the
* defaults used to create new consoles.
*/
if (var->activate & FB_ACTIVATE_ALL)
cfb->fb.disp->var = cfb->fb.var;
cfb->fb.disp->var = display->var;
if (chgvar && info && cfb->fb.changevar)
cfb->fb.changevar(con);
......@@ -1015,18 +1005,18 @@ cyber2000fb_pan_display(struct fb_var_screeninfo *var, int con,
if (var->xoffset > (var->xres_virtual - var->xres))
return -EINVAL;
if (y_bottom > cfb->fb.var.yres_virtual)
if (y_bottom > cfb->display->var.yres_virtual)
return -EINVAL;
if (cyber2000fb_update_start(cfb, var))
return -EINVAL;
cfb->fb.var.xoffset = var->xoffset;
cfb->fb.var.yoffset = var->yoffset;
cfb->display->var.xoffset = var->xoffset;
cfb->display->var.yoffset = var->yoffset;
if (var->vmode & FB_VMODE_YWRAP) {
cfb->fb.var.vmode |= FB_VMODE_YWRAP;
cfb->display->var.vmode |= FB_VMODE_YWRAP;
} else {
cfb->fb.var.vmode &= ~FB_VMODE_YWRAP;
cfb->display->var.vmode &= ~FB_VMODE_YWRAP;
}
return 0;
......@@ -1049,22 +1039,18 @@ static int cyber2000fb_updatevar(int con, struct fb_info *info)
static int cyber2000fb_switch(int con, struct fb_info *info)
{
struct cfb_info *cfb = (struct cfb_info *)info;
struct display *disp;
struct display *display = cfb->display;
struct fb_cmap *cmap;
if (cfb->currcon >= 0) {
disp = fb_display + cfb->currcon;
if (display) {
/*
* Save the old colormap and video mode.
*/
disp->var = cfb->fb.var;
if (disp->cmap.len)
fb_copy_cmap(&cfb->fb.cmap, &disp->cmap, 0);
if (display->cmap.len)
fb_copy_cmap(&cfb->fb.cmap, &display->cmap, 0);
}
cfb->currcon = con;
disp = fb_display + con;
cfb->display = display = fb_display + con;
/*
* Install the new colormap and change the video mode. By default,
......@@ -1075,17 +1061,15 @@ static int cyber2000fb_switch(int con, struct fb_info *info)
* depth of the new video mode. For now, we leave it at its
* default 256 entry.
*/
if (disp->cmap.len)
cmap = &disp->cmap;
if (display->cmap.len)
cmap = &display->cmap;
else
cmap = fb_default_cmap(1 << disp->var.bits_per_pixel);
cmap = fb_default_cmap(1 << display->var.bits_per_pixel);
fb_copy_cmap(cmap, &cfb->fb.cmap, 0);
cfb->fb.var = disp->var;
cfb->fb.var.activate = FB_ACTIVATE_NOW;
cyber2000fb_set_var(&cfb->fb.var, con, &cfb->fb);
display->var.activate = FB_ACTIVATE_NOW;
cyber2000fb_set_var(&display->var, con, &cfb->fb);
return 0;
}
......@@ -1096,6 +1080,7 @@ static int cyber2000fb_switch(int con, struct fb_info *info)
static void cyber2000fb_blank(int blank, struct fb_info *info)
{
struct cfb_info *cfb = (struct cfb_info *)info;
unsigned int sync = 0;
int i;
/*
......@@ -1116,16 +1101,26 @@ static void cyber2000fb_blank(int blank, struct fb_info *info)
switch (blank) {
case 4: /* powerdown - both sync lines down */
cyber2000_grphw(0x16, 0x05, cfb);
sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_0;
break;
case 3: /* hsync off */
cyber2000_grphw(0x16, 0x01, cfb);
sync = EXT_SYNC_CTL_VS_NORMAL | EXT_SYNC_CTL_HS_0;
break;
case 2: /* vsync off */
cyber2000_grphw(0x16, 0x04, cfb);
break;
sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_NORMAL;
break;
case 1: /* soft blank */
break;
default: /* unblank */
break;
}
cyber2000_grphw(EXT_SYNC_CTL, sync, cfb);
switch (blank) {
case 4:
case 3:
case 2:
case 1: /* soft blank */
cyber2000_grphw(0x16, 0x00, cfb);
for (i = 0; i < NR_PALETTE; i++) {
cyber2000fb_writeb(i, 0x3c8, cfb);
cyber2000fb_writeb(0, 0x3c9, cfb);
......@@ -1134,7 +1129,6 @@ static void cyber2000fb_blank(int blank, struct fb_info *info)
}
break;
default: /* unblank */
cyber2000_grphw(0x16, 0x00, cfb);
for (i = 0; i < NR_PALETTE; i++) {
cyber2000fb_writeb(i, 0x3c8, cfb);
cyber2000fb_writeb(cfb->palette[i].red, 0x3c9, cfb);
......@@ -1185,42 +1179,52 @@ static struct fb_ops cyber2000fb_ops = {
fb_get_cmap: gen_get_cmap,
};
/*
* This is the only "static" reference to the internal data structures
* of this driver. It is here solely at the moment to support the other
* CyberPro modules external to this driver.
*/
static struct cfb_info *int_cfb_info;
/*
* Enable access to the extended registers
*/
static void cyber2000fb_enable_extregs(struct cfb_info *cfb)
void cyber2000fb_enable_extregs(struct cfb_info *cfb)
{
cfb->func_use_count += 1;
if (cfb->func_use_count == 1) {
int old;
old = cyber2000_grphr(FUNC_CTL, cfb);
cyber2000_grphw(FUNC_CTL, old | FUNC_CTL_EXTREGENBL, cfb);
old = cyber2000_grphr(EXT_FUNC_CTL, cfb);
old |= EXT_FUNC_CTL_EXTREGENBL;
cyber2000_grphw(EXT_FUNC_CTL, old, cfb);
}
}
/*
* Disable access to the extended registers
*/
static void cyber2000fb_disable_extregs(struct cfb_info *cfb)
void cyber2000fb_disable_extregs(struct cfb_info *cfb)
{
if (cfb->func_use_count == 1) {
int old;
old = cyber2000_grphr(FUNC_CTL, cfb);
cyber2000_grphw(FUNC_CTL, old & ~FUNC_CTL_EXTREGENBL, cfb);
old = cyber2000_grphr(EXT_FUNC_CTL, cfb);
old &= ~EXT_FUNC_CTL_EXTREGENBL;
cyber2000_grphw(EXT_FUNC_CTL, old, cfb);
}
cfb->func_use_count -= 1;
if (cfb->func_use_count == 0)
printk(KERN_ERR "disable_extregs: count = 0\n");
else
cfb->func_use_count -= 1;
}
/*
* This is the only "static" reference to the internal data structures
* of this driver. It is here solely at the moment to support the other
* CyberPro modules external to this driver.
*/
static struct cfb_info *int_cfb_info;
void cyber2000fb_get_fb_var(struct cfb_info *cfb, struct fb_var_screeninfo *var)
{
memcpy(var, &cfb->display->var, sizeof(struct fb_var_screeninfo));
}
/*
* Attach a capture/tv driver to the core CyberX0X0 driver.
......@@ -1254,6 +1258,9 @@ void cyber2000fb_detach(int idx)
EXPORT_SYMBOL(cyber2000fb_attach);
EXPORT_SYMBOL(cyber2000fb_detach);
EXPORT_SYMBOL(cyber2000fb_enable_extregs);
EXPORT_SYMBOL(cyber2000fb_disable_extregs);
EXPORT_SYMBOL(cyber2000fb_get_fb_var);
/*
* These parameters give
......@@ -1275,143 +1282,60 @@ static struct fb_videomode __devinitdata cyber2000fb_default_mode = {
};
static char igs_regs[] __devinitdata = {
0x12, 0x00, 0x13, 0x00,
0x16, 0x00,
0x31, 0x00, 0x32, 0x00,
0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00,
0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x01,
0x58, 0x00, 0x59, 0x00, 0x5a, 0x00,
0x70, 0x0b, 0x73, 0x30,
0x74, 0x0b, 0x75, 0x17, 0x76, 0x00, 0x7a, 0xc8
EXT_CRT_IRQ, 0,
EXT_CRT_TEST, 0,
EXT_SYNC_CTL, 0,
EXT_SEG_WRITE_PTR, 0,
EXT_SEG_READ_PTR, 0,
EXT_BIU_MISC, EXT_BIU_MISC_LIN_ENABLE |
EXT_BIU_MISC_COP_ENABLE |
EXT_BIU_MISC_COP_BFC,
EXT_FUNC_CTL, 0,
CURS_H_START, 0,
CURS_H_START + 1, 0,
CURS_H_PRESET, 0,
CURS_V_START, 0,
CURS_V_START + 1, 0,
CURS_V_PRESET, 0,
CURS_CTL, 0,
EXT_ATTRIB_CTL, EXT_ATTRIB_CTL_EXT,
EXT_OVERSCAN_RED, 0,
EXT_OVERSCAN_GREEN, 0,
EXT_OVERSCAN_BLUE, 0,
/* some of these are questionable when we have a BIOS */
EXT_MEM_CTL0, EXT_MEM_CTL0_7CLK |
EXT_MEM_CTL0_RAS_1 |
EXT_MEM_CTL0_MULTCAS,
EXT_HIDDEN_CTL1, 0x30,
EXT_FIFO_CTL, 0x0b,
EXT_FIFO_CTL + 1, 0x17,
0x76, 0x00,
EXT_HIDDEN_CTL4, 0xc8
};
/*
* We need to wake up the CyberPro, and make sure its in linear memory
* mode. Unfortunately, this is specific to the platform and card that
* we are running on.
*
* On x86 and ARM, should we be initialising the CyberPro first via the
* IO registers, and then the MMIO registers to catch all cases? Can we
* end up in the situation where the chip is in MMIO mode, but not awake
* on an x86 system?
*
* Note that on the NetWinder, the firmware automatically detects the
* type, width and size, and leaves this in extended registers 0x71 and
* 0x72 for us.
* Initialise the CyberPro hardware. On the CyberPro5XXXX,
* ensure that we're using the correct PLL (5XXX's may be
* programmed to use an additional set of PLLs.)
*/
static inline void cyberpro_init_hw(struct cfb_info *cfb, int at_boot)
static void cyberpro_init_hw(struct cfb_info *cfb)
{
int i;
/*
* Wake up the CyberPro.
*/
#ifdef __sparc__
#ifdef __sparc_v9__
#error "You loose, consult DaveM."
#else
/*
* SPARC does not have an "outb" instruction, so we generate
* I/O cycles storing into a reserved memory space at
* physical address 0x3000000
*/
{
unsigned char *iop;
iop = ioremap(0x3000000, 0x5000);
if (iop == NULL) {
prom_printf("iga5000: cannot map I/O\n");
return -ENOMEM;
}
writeb(0x18, iop + 0x46e8);
writeb(0x01, iop + 0x102);
writeb(0x08, iop + 0x46e8);
writeb(0x33, iop + 0x3ce);
writeb(0x01, iop + 0x3cf);
iounmap((void *)iop);
}
#endif
if (at_boot) {
/*
* Use mclk from BIOS. Only read this if we're
* initialising this card for the first time.
* FIXME: what about hotplug?
*/
cfb->mclk_mult = cyber2000_grphr(MCLK_MULT, cfb);
cfb->mclk_div = cyber2000_grphr(MCLK_DIV, cfb);
}
#endif
#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
/*
* x86 and MIPS are simple, we just do regular
* outb's instead of cyber2000fb_writeb.
*/
outb(0x18, 0x46e8);
outb(0x01, 0x102);
outb(0x08, 0x46e8);
outb(0x33, 0x3ce);
outb(0x01, 0x3cf);
if (at_boot) {
/*
* Use mclk from BIOS. Only read this if we're
* initialising this card for the first time.
* FIXME: what about hotplug?
*/
cfb->mclk_mult = cyber2000_grphr(MCLK_MULT, cfb);
cfb->mclk_div = cyber2000_grphr(MCLK_DIV, cfb);
}
#endif
#ifdef __arm__
cyber2000fb_writeb(0x18, 0x46e8, cfb);
cyber2000fb_writeb(0x01, 0x102, cfb);
cyber2000fb_writeb(0x08, 0x46e8, cfb);
cyber2000fb_writeb(0x33, 0x3ce, cfb);
cyber2000fb_writeb(0x01, 0x3cf, cfb);
/*
* MCLK on the NetWinder and the Shark is fixed at 75MHz
*/
cfb->mclk_mult = 0xdb;
cfb->mclk_div = 0x54;
#endif
/*
* Initialise the CyberPro
*/
for (i = 0; i < sizeof(igs_regs); i += 2)
cyber2000_grphw(igs_regs[i], igs_regs[i+1], cfb);
if (at_boot) {
/*
* get the video RAM size and width from the VGA register.
* This should have been already initialised by the BIOS,
* but if it's garbage, claim default 1MB VRAM (woody)
*/
cfb->mem_ctl1 = cyber2000_grphr(MEM_CTL1, cfb);
cfb->mem_ctl2 = cyber2000_grphr(MEM_CTL2, cfb);
} else {
/*
* Reprogram the MEM_CTL1 and MEM_CTL2 registers
*/
cyber2000_grphw(MEM_CTL1, cfb->mem_ctl1, cfb);
cyber2000_grphw(MEM_CTL2, cfb->mem_ctl2, cfb);
if (cfb->fb.fix.accel == FB_ACCEL_IGS_CYBER5000) {
unsigned char val;
cyber2000fb_writeb(0xba, 0x3ce, cfb);
val = cyber2000fb_readb(0x3cf, cfb) & 0x80;
cyber2000fb_writeb(val, 0x3cf, cfb);
}
/*
* Ensure thatwe are using the correct PLL.
* (CyberPro 5000's may be programmed to use
* an additional set of PLLs.
*/
cyber2000fb_writeb(0xba, 0x3ce, cfb);
cyber2000fb_writeb(cyber2000fb_readb(0x3cf, cfb) & 0x80, 0x3cf, cfb);
}
static struct cfb_info * __devinit
cyberpro_alloc_fb_info(struct pci_dev *dev, const struct pci_device_id *id, char *name)
cyberpro_alloc_fb_info(unsigned int id, char *name)
{
struct cfb_info *cfb;
......@@ -1423,10 +1347,7 @@ cyberpro_alloc_fb_info(struct pci_dev *dev, const struct pci_device_id *id, char
memset(cfb, 0, sizeof(struct cfb_info) + sizeof(struct display));
cfb->currcon = -1;
cfb->dev = dev;
if (id->driver_data == FB_ACCEL_IGS_CYBER5000)
if (id == ID_CYBERPRO_5000)
cfb->ref_ps = 40690; // 24.576 MHz
else
cfb->ref_ps = 69842; // 14.31818 MHz (69841?)
......@@ -1435,7 +1356,7 @@ cyberpro_alloc_fb_info(struct pci_dev *dev, const struct pci_device_id *id, char
cfb->divisors[1] = 2;
cfb->divisors[2] = 4;
if (id->driver_data == FB_ACCEL_IGS_CYBER2000)
if (id == ID_CYBERPRO_2000)
cfb->divisors[3] = 8;
else
cfb->divisors[3] = 6;
......@@ -1447,7 +1368,24 @@ cyberpro_alloc_fb_info(struct pci_dev *dev, const struct pci_device_id *id, char
cfb->fb.fix.xpanstep = 0;
cfb->fb.fix.ypanstep = 1;
cfb->fb.fix.ywrapstep = 0;
cfb->fb.fix.accel = id->driver_data;
switch (id) {
case ID_IGA_1682:
cfb->fb.fix.accel = 0;
break;
case ID_CYBERPRO_2000:
cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER2000;
break;
case ID_CYBERPRO_2010:
cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER2010;
break;
case ID_CYBERPRO_5000:
cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER5000;
break;
}
cfb->fb.var.nonstd = 0;
cfb->fb.var.activate = FB_ACTIVATE_NOW;
......@@ -1512,55 +1450,43 @@ cyber2000fb_setup(char *options)
return 0;
}
static int __devinit
cyberpro_probe(struct pci_dev *dev, const struct pci_device_id *id)
/*
* The CyberPro chips can be placed on many different bus types.
* This probe function is common to all bus types. The bus-specific
* probe function is expected to have:
* - enabled access to the linear memory region
* - memory mapped access to the registers
* - initialised mem_ctl1 and mem_ctl2 appropriately.
*/
static int __devinit cyberpro_common_probe(struct cfb_info *cfb)
{
struct cfb_info *cfb;
u_int h_sync, v_sync;
u_long smem_size;
char name[16];
u_int h_sync, v_sync;
int err;
sprintf(name, "CyberPro%4X", id->device);
err = pci_enable_device(dev);
if (err)
return err;
err = pci_request_regions(dev, name);
if (err)
return err;
err = -ENOMEM;
cfb = cyberpro_alloc_fb_info(dev, id, name);
if (!cfb)
goto failed_release;
cfb->region = ioremap(pci_resource_start(dev, 0),
pci_resource_len(dev, 0));
if (!cfb->region)
goto failed_ioremap;
cfb->regs = cfb->region + MMIO_OFFSET;
cyberpro_init_hw(cfb, 1);
/*
* Get the video RAM size and width from the VGA register.
* This should have been already initialised by the BIOS,
* but if it's garbage, claim default 1MB VRAM (woody)
*/
cfb->mem_ctl1 = cyber2000_grphr(EXT_MEM_CTL1, cfb);
cfb->mem_ctl2 = cyber2000_grphr(EXT_MEM_CTL2, cfb);
/*
* Determine the size of the memory.
*/
switch (cfb->mem_ctl2 & MEM_CTL2_SIZE_MASK) {
case MEM_CTL2_SIZE_4MB: smem_size = 0x00400000; break;
case MEM_CTL2_SIZE_2MB: smem_size = 0x00200000; break;
case MEM_CTL2_SIZE_1MB: smem_size = 0x00100000; break;
default: smem_size = 0x00100000; break;
}
/*
* Hmm, we _need_ a portable way of finding the address for
* the remap stuff, both for mmio and for smem.
*/
cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET;
cfb->fb.fix.smem_start = pci_resource_start(dev, 0);
cfb->fb.fix.mmio_len = MMIO_SIZE;
cfb->fb.fix.smem_len = smem_size;
cfb->fb.fix.mmio_len = MMIO_SIZE;
cfb->fb.screen_base = cfb->region;
err = -EINVAL;
if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0,
&cyber2000fb_default_mode, 8)) {
printk("%s: no valid mode found\n", cfb->fb.fix.id);
......@@ -1587,13 +1513,210 @@ cyberpro_probe(struct pci_dev *dev, const struct pci_device_id *id)
v_sync = h_sync / (cfb->fb.var.yres + cfb->fb.var.upper_margin +
cfb->fb.var.lower_margin + cfb->fb.var.vsync_len);
printk(KERN_INFO "%s: %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
printk(KERN_INFO "%s: %dKiB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
cfb->fb.fix.id, cfb->fb.fix.smem_len >> 10,
cfb->fb.var.xres, cfb->fb.var.yres,
h_sync / 1000, h_sync % 1000, v_sync);
err = register_framebuffer(&cfb->fb);
if (err < 0)
failed:
return err;
}
static void cyberpro_common_resume(struct cfb_info *cfb)
{
cyberpro_init_hw(cfb);
/*
* Reprogram the MEM_CTL1 and MEM_CTL2 registers
*/
cyber2000_grphw(EXT_MEM_CTL1, cfb->mem_ctl1, cfb);
cyber2000_grphw(EXT_MEM_CTL2, cfb->mem_ctl2, cfb);
/*
* Restore the old video mode and the palette.
* We also need to tell fbcon to redraw the console.
*/
cfb->fb.var.activate = FB_ACTIVATE_NOW;
cyber2000fb_set_var(&cfb->fb.var, -1, &cfb->fb);
}
#ifdef CONFIG_ARCH_SHARK
#include <asm/arch/hardware.h>
static int __devinit
cyberpro_vl_probe(void)
{
struct cfb_info *cfb;
int err = -ENOMEM;
if (!request_mem_region(FB_START,FB_SIZE,"CyberPro2010")) return err;
cfb = cyberpro_alloc_fb_info(ID_CYBERPRO_2010, "CyberPro2010");
if (!cfb)
goto failed_release;
cfb->dev = NULL;
cfb->region = ioremap(FB_START,FB_SIZE);
if (!cfb->region)
goto failed_ioremap;
cfb->regs = cfb->region + MMIO_OFFSET;
cfb->fb.fix.mmio_start = FB_START + MMIO_OFFSET;
cfb->fb.fix.smem_start = FB_START;
/*
* Bring up the hardware. This is expected to enable access
* to the linear memory region, and allow access to the memory
* mapped registers. Also, mem_ctl1 and mem_ctl2 must be
* initialised.
*/
cyber2000fb_writeb(0x18, 0x46e8, cfb);
cyber2000fb_writeb(0x01, 0x102, cfb);
cyber2000fb_writeb(0x08, 0x46e8, cfb);
cyber2000fb_writeb(EXT_BIU_MISC, 0x3ce, cfb);
cyber2000fb_writeb(EXT_BIU_MISC_LIN_ENABLE, 0x3cf, cfb);
cfb->mclk_mult = 0xdb;
cfb->mclk_div = 0x54;
cyberpro_init_hw(cfb);
err = cyberpro_common_probe(cfb);
if (err)
goto failed;
if (int_cfb_info == NULL)
int_cfb_info = cfb;
return 0;
failed:
iounmap(cfb->region);
failed_ioremap:
cyberpro_free_fb_info(cfb);
failed_release:
release_mem_region(FB_START,FB_SIZE);
return err;
}
#endif /* CONFIG_ARCH_SHARK */
/*
* PCI specific support.
*/
#ifdef CONFIG_PCI
/*
* We need to wake up the CyberPro, and make sure its in linear memory
* mode. Unfortunately, this is specific to the platform and card that
* we are running on.
*
* On x86 and ARM, should we be initialising the CyberPro first via the
* IO registers, and then the MMIO registers to catch all cases? Can we
* end up in the situation where the chip is in MMIO mode, but not awake
* on an x86 system?
*/
static int cyberpro_pci_enable_mmio(struct cfb_info *cfb)
{
#if defined(__sparc_v9__)
#error "You loose, consult DaveM."
#elif defined(__sparc__)
/*
* SPARC does not have an "outb" instruction, so we generate
* I/O cycles storing into a reserved memory space at
* physical address 0x3000000
*/
unsigned char *iop;
iop = ioremap(0x3000000, 0x5000);
if (iop == NULL) {
prom_printf("iga5000: cannot map I/O\n");
return -ENOMEM;
}
writeb(0x18, iop + 0x46e8);
writeb(0x01, iop + 0x102);
writeb(0x08, iop + 0x46e8);
writeb(EXT_BIU_MISC, iop + 0x3ce);
writeb(EXT_BIU_MISC_LIN_ENABLE, iop + 0x3cf);
iounmap((void *)iop);
#else
/*
* Most other machine types are "normal", so
* we use the standard IO-based wakeup.
*/
outb(0x18, 0x46e8);
outb(0x01, 0x102);
outb(0x08, 0x46e8);
outb(EXT_BIU_MISC, 0x3ce);
outb(EXT_BIU_MISC_LIN_ENABLE, 0x3cf);
#endif
return 0;
}
static int __devinit
cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct cfb_info *cfb;
char name[16];
int err;
sprintf(name, "CyberPro%4X", id->device);
err = pci_enable_device(dev);
if (err)
return err;
err = pci_request_regions(dev, name);
if (err)
return err;
err = -ENOMEM;
cfb = cyberpro_alloc_fb_info(id->driver_data, name);
if (!cfb)
goto failed_release;
cfb->dev = dev;
cfb->region = ioremap(pci_resource_start(dev, 0),
pci_resource_len(dev, 0));
if (!cfb->region)
goto failed_ioremap;
cfb->regs = cfb->region + MMIO_OFFSET;
cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET;
cfb->fb.fix.smem_start = pci_resource_start(dev, 0);
/*
* Bring up the hardware. This is expected to enable access
* to the linear memory region, and allow access to the memory
* mapped registers. Also, mem_ctl1 and mem_ctl2 must be
* initialised.
*/
err = cyberpro_pci_enable_mmio(cfb);
if (err)
goto failed;
/*
* Use MCLK from BIOS. FIXME: what about hotplug?
*/
#ifndef __arm__
cfb->mclk_mult = cyber2000_grphr(MCLK_MULT, cfb);
cfb->mclk_div = cyber2000_grphr(MCLK_DIV, cfb);
#else
/*
* MCLK on the NetWinder and the Shark is fixed at 75MHz
*/
cfb->mclk_mult = 0xdb;
cfb->mclk_div = 0x54;
#endif
cyberpro_init_hw(cfb);
err = cyberpro_common_probe(cfb);
if (err)
goto failed;
/*
......@@ -1615,7 +1738,7 @@ cyberpro_probe(struct pci_dev *dev, const struct pci_device_id *id)
return err;
}
static void __devexit cyberpro_remove(struct pci_dev *dev)
static void __devexit cyberpro_pci_remove(struct pci_dev *dev)
{
struct cfb_info *cfb = pci_get_drvdata(dev);
......@@ -1644,7 +1767,7 @@ static void __devexit cyberpro_remove(struct pci_dev *dev)
}
}
static int cyberpro_suspend(struct pci_dev *dev, u32 state)
static int cyberpro_pci_suspend(struct pci_dev *dev, u32 state)
{
return 0;
}
......@@ -1652,42 +1775,42 @@ static int cyberpro_suspend(struct pci_dev *dev, u32 state)
/*
* Re-initialise the CyberPro hardware
*/
static int cyberpro_resume(struct pci_dev *dev)
static int cyberpro_pci_resume(struct pci_dev *dev)
{
struct cfb_info *cfb = pci_get_drvdata(dev);
if (cfb) {
cyberpro_init_hw(cfb, 0);
/*
* Restore the old video mode and the palette.
* We also need to tell fbcon to redraw the console.
*/
cfb->fb.var.activate = FB_ACTIVATE_NOW;
cyber2000fb_set_var(&cfb->fb.var, -1, &cfb->fb);
cyberpro_pci_enable_mmio(cfb);
cyberpro_common_resume(cfb);
}
return 0;
}
static struct pci_device_id cyberpro_pci_table[] __devinitdata = {
// Not yet
// { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682,
// PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_IGA_1682 },
{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER2000 },
PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2000 },
{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2010,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER2010 },
PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2010 },
{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5000,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER5000 },
PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_5000 },
{ 0, }
};
MODULE_DEVICE_TABLE(pci,cyberpro_pci_table);
static struct pci_driver cyberpro_driver = {
name: "CyberPro",
probe: cyberpro_probe,
remove: __devexit_p(cyberpro_remove),
suspend: cyberpro_suspend,
resume: cyberpro_resume,
probe: cyberpro_pci_probe,
remove: __devexit_p(cyberpro_pci_remove),
suspend: cyberpro_pci_suspend,
resume: cyberpro_pci_resume,
id_table: cyberpro_pci_table
};
#endif
/*
* I don't think we can use the "module_init" stuff here because
......@@ -1696,12 +1819,27 @@ static struct pci_driver cyberpro_driver = {
*/
int __init cyber2000fb_init(void)
{
return pci_module_init(&cyberpro_driver);
int ret = -1, err = 0;
#ifdef CONFIG_ARCH_SHARK
err = cyberpro_vl_probe();
if (!err) {
ret = err;
MOD_INC_USE_COUNT;
}
#endif
#ifdef CONFIG_PCI
err = pci_module_init(&cyberpro_driver);
if (!err)
ret = err;
#endif
return ret ? err : 0;
}
static void __exit cyberpro_exit(void)
{
#ifdef CONFIG_PCI
pci_unregister_driver(&cyberpro_driver);
#endif
}
#ifdef MODULE
......@@ -1711,5 +1849,4 @@ module_exit(cyberpro_exit);
MODULE_AUTHOR("Russell King");
MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver");
MODULE_DEVICE_TABLE(pci,cyberpro_pci_table);
MODULE_LICENSE("GPL");
......@@ -40,18 +40,44 @@ static void debug_printf(char *fmt, ...)
#define PIXFORMAT_16BPP 1
#define PIXFORMAT_24BPP 2
#define VISUALID_256 1
#define VISUALID_64K 2
#define VISUALID_16M 4
#define VISUALID_32K 6
#define FUNC_CTL 0x3c
#define FUNC_CTL_EXTREGENBL 0x80 /* enable access to 0xbcxxx */
#define BIU_BM_CONTROL 0x3e
#define BIU_BM_CONTROL_ENABLE 0x01 /* enable bus-master */
#define BIU_BM_CONTROL_BURST 0x02 /* enable burst */
#define BIU_BM_CONTROL_BACK2BACK 0x04 /* enable back to back */
#define EXT_CRT_IRQ 0x12
#define EXT_CRT_IRQ_ENABLE 0x01
#define EXT_CRT_IRQ_ACT_HIGH 0x04
#define EXT_CRT_TEST 0x13
#define EXT_SYNC_CTL 0x16
#define EXT_SYNC_CTL_HS_NORMAL 0x00
#define EXT_SYNC_CTL_HS_0 0x01
#define EXT_SYNC_CTL_HS_1 0x02
#define EXT_SYNC_CTL_HS_HSVS 0x03
#define EXT_SYNC_CTL_VS_NORMAL 0x00
#define EXT_SYNC_CTL_VS_0 0x04
#define EXT_SYNC_CTL_VS_1 0x08
#define EXT_SYNC_CTL_VS_COMP 0x0c
#define EXT_BUS_CTL 0x30
#define EXT_BUS_CTL_LIN_1MB 0x00
#define EXT_BUS_CTL_LIN_2MB 0x01
#define EXT_BUS_CTL_LIN_4MB 0x02
#define EXT_BUS_CTL_ZEROWAIT 0x04
#define EXT_BUS_CTL_PCIBURST 0x20
#define EXT_SEG_WRITE_PTR 0x31
#define EXT_SEG_READ_PTR 0x32
#define EXT_BIU_MISC 0x33
#define EXT_BIU_MISC_LIN_ENABLE 0x01
#define EXT_BIU_MISC_COP_ENABLE 0x04
#define EXT_BIU_MISC_COP_BFC 0x08
#define EXT_FUNC_CTL 0x3c
#define EXT_FUNC_CTL_EXTREGENBL 0x80 /* enable access to 0xbcxxx */
#define PCI_BM_CTL 0x3e
#define PCI_BM_CTL_ENABLE 0x01 /* enable bus-master */
#define PCI_BM_CTL_BURST 0x02 /* enable burst */
#define PCI_BM_CTL_BACK2BACK 0x04 /* enable back to back */
#define PCI_BM_CTL_DUMMY 0x08 /* insert dummy cycle */
#define X_V2_VID_MEM_START 0x40
#define X_V2_VID_SRC_WIDTH 0x43
......@@ -85,6 +111,19 @@ static void debug_printf(char *fmt, ...)
#define K_CAP_X2_CTL1 0x49
#define CURS_H_START 0x50
#define CURS_H_PRESET 0x52
#define CURS_V_START 0x53
#define CURS_V_PRESET 0x55
#define CURS_CTL 0x56
#define EXT_ATTRIB_CTL 0x57
#define EXT_ATTRIB_CTL_EXT 0x01
#define EXT_OVERSCAN_RED 0x58
#define EXT_OVERSCAN_GREEN 0x59
#define EXT_OVERSCAN_BLUE 0x5a
#define CAP_X_START 0x60
#define CAP_X_END 0x62
#define CAP_Y_START 0x64
......@@ -94,46 +133,112 @@ static void debug_printf(char *fmt, ...)
#define CAP_DDA_Y_INIT 0x6c
#define CAP_DDA_Y_INC 0x6e
#define MEM_CTL1 0x71
#define MEM_CTL2 0x72
#define EXT_MEM_CTL0 0x70
#define EXT_MEM_CTL0_7CLK 0x01
#define EXT_MEM_CTL0_RAS_1 0x02
#define EXT_MEM_CTL0_RAS2CAS_1 0x04
#define EXT_MEM_CTL0_MULTCAS 0x08
#define EXT_MEM_CTL0_ASYM 0x10
#define EXT_MEM_CTL0_CAS1ON 0x20
#define EXT_MEM_CTL0_FIFOFLUSH 0x40
#define EXT_MEM_CTL0_SEQRESET 0x80
#define EXT_MEM_CTL1 0x71
#define EXT_MEM_CTL1_PAR 0x00
#define EXT_MEM_CTL1_SERPAR 0x01
#define EXT_MEM_CTL1_SER 0x03
#define EXT_MEM_CTL1_SYNC 0x04
#define EXT_MEM_CTL1_VRAM 0x08
#define EXT_MEM_CTL1_4K_REFRESH 0x10
#define EXT_MEM_CTL1_256Kx4 0x00
#define EXT_MEM_CTL1_512Kx8 0x40
#define EXT_MEM_CTL1_1Mx16 0x60
#define EXT_MEM_CTL2 0x72
#define MEM_CTL2_SIZE_1MB 0x00
#define MEM_CTL2_SIZE_2MB 0x01
#define MEM_CTL2_SIZE_4MB 0x02
#define MEM_CTL2_SIZE_MASK 0x03
#define MEM_CTL2_64BIT 0x04
#define EXT_HIDDEN_CTL1 0x73
#define EXT_FIFO_CTL 0x74
#define EXT_SEQ_MISC 0x77
#define EXT_SEQ_MISC_8 0x01
#define EXT_SEQ_MISC_16_RGB565 0x02
#define EXT_SEQ_MISC_32 0x03
#define EXT_SEQ_MISC_24_RGB888 0x04
#define EXT_SEQ_MISC_16_RGB555 0x06
#define EXT_SEQ_MISC_8_RGB332 0x09
#define EXT_SEQ_MISC_16_RGB444 0x0a
#define EXT_HIDDEN_CTL4 0x7a
#define CURS_MEM_START 0x7e /* bits 23..12 */
#define CAP_PIP_X_START 0x80
#define CAP_PIP_X_END 0x82
#define CAP_PIP_Y_START 0x84
#define CAP_PIP_Y_END 0x86
#define CAP_NEW_CTL1 0x88
#define EXT_CAP_CTL1 0x88
#define CAP_NEW_CTL2 0x89
#define EXT_CAP_CTL2 0x89
#define EXT_CAP_CTL2_ODDFRAMEIRQ 0x01
#define EXT_CAP_CTL2_ANYFRAMEIRQ 0x02
#define BM_CTRL0 0x9c
#define BM_CTRL1 0x9d
#define CAP_MODE1 0xa4
#define CAP_MODE1_8BIT 0x01 /* enable 8bit capture mode */
#define CAP_MODE1_CCIR656 0x02 /* CCIR656 mode */
#define CAP_MODE1_IGNOREVGT 0x04 /* ignore VGT */
#define CAP_MODE1_ALTFIFO 0x10 /* use alternate FIFO for capture */
#define CAP_MODE1_SWAPUV 0x20 /* swap UV bytes */
#define CAP_MODE1_MIRRORY 0x40 /* mirror vertically */
#define CAP_MODE1_MIRRORX 0x80 /* mirror horizontally */
#define DCLK_MULT 0xb0
#define DCLK_DIV 0xb1
#define DCLK_DIV_VFSEL 0x20
#define MCLK_MULT 0xb2
#define MCLK_DIV 0xb3
#define CAP_MODE2 0xa5
#define Y_TV_CTL 0xae
#define EXT_CAP_MODE1 0xa4
#define EXT_CAP_MODE1_8BIT 0x01 /* enable 8bit capture mode */
#define EXT_CAP_MODE1_CCIR656 0x02 /* CCIR656 mode */
#define EXT_CAP_MODE1_IGNOREVGT 0x04 /* ignore VGT */
#define EXT_CAP_MODE1_ALTFIFO 0x10 /* use alternate FIFO for capture */
#define EXT_CAP_MODE1_SWAPUV 0x20 /* swap UV bytes */
#define EXT_CAP_MODE1_MIRRORY 0x40 /* mirror vertically */
#define EXT_CAP_MODE1_MIRRORX 0x80 /* mirror horizontally */
#define EXT_CAP_MODE2 0xa5
#define EXT_CAP_MODE2_CCIRINVOE 0x01
#define EXT_CAP_MODE2_CCIRINVVGT 0x02
#define EXT_CAP_MODE2_CCIRINVHGT 0x04
#define EXT_CAP_MODE2_CCIRINVDG 0x08
#define EXT_CAP_MODE2_DATEND 0x10
#define EXT_CAP_MODE2_CCIRDGH 0x20
#define EXT_CAP_MODE2_FIXSONY 0x40
#define EXT_CAP_MODE2_SYNCFREEZE 0x80
#define EXT_TV_CTL 0xae
#define EXT_DCLK_MULT 0xb0
#define EXT_DCLK_DIV 0xb1
#define EXT_DCLK_DIV_VFSEL 0x20
#define EXT_MCLK_MULT 0xb2
#define EXT_MCLK_DIV 0xb3
#define EXT_LATCH1 0xb5
#define EXT_LATCH1_VAFC_EN 0x01 /* enable VAFC */
#define EXT_FEATURE 0xb7
#define EXT_FEATURE_BUS_MASK 0x07 /* host bus mask */
#define EXT_FEATURE_BUS_PCI 0x00
#define EXT_FEATURE_BUS_VL_STD 0x04
#define EXT_FEATURE_BUS_VL_LINEAR 0x05
#define EXT_FEATURE_1682 0x20 /* IGS 1682 compatibility */
#define EXT_LATCH2 0xb6
#define EXT_LATCH2_I2C_CLKEN 0x10
#define EXT_LATCH2_I2C_CLK 0x20
#define EXT_LATCH2_I2C_DATEN 0x40
#define EXT_LATCH2_I2C_DAT 0x80
#define EXT_XT_CTL 0xbe
#define EXT_XT_CAP16 0x04
#define EXT_XT_LINEARFB 0x08
#define EXT_XT_PAL 0x10
#define EXT_MEM_START 0xc0 /* ext start address 21 bits */
#define HOR_PHASE_SHIFT 0xc2 /* high 3 bits */
......@@ -158,25 +263,37 @@ static void debug_printf(char *fmt, ...)
#define EXT_VID_FMT_RGB565 0x02
#define EXT_VID_FMT_RGB888_24 0x03
#define EXT_VID_FMT_RGB888_32 0x04
#define EXT_VID_FMT_RGB8 0x05
#define EXT_VID_FMT_RGB4444 0x06
#define EXT_VID_FMT_RGB8T 0x07
#define EXT_VID_FMT_DUP_PIX_ZOON 0x08 /* duplicate pixel zoom */
#define EXT_VID_FMT_MOD_3RD_PIX 0x20 /* modify 3rd duplicated pixel */
#define EXT_VID_FMT_DBL_H_PIX 0x40 /* double horiz pixels */
#define EXT_VID_FMT_UV128 0x80 /* UV data offset by 128 */
#define EXT_VID_FMT_YUV128 0x80 /* YUV data offset by 128 */
#define EXT_VID_DISP_CTL1 0xdc
#define EXT_VID_DISP_CTL1_INTRAM 0x01 /* video pixels go to internal RAM */
#define EXT_VID_DISP_CTL1_IGNORE_CCOMP 0x02 /* ignore colour compare registers */
#define EXT_VID_DISP_CTL1_NOCLIP 0x04 /* do not clip to 16235,16240 */
#define EXT_VID_DISP_CTL1_UV_AVG 0x08 /* U/V data is averaged */
#define EXT_VID_DISP_CTL1_Y128 0x10 /* Y data offset by 128 */
#define EXT_VID_DISP_CTL1_VINTERPOL_OFF 0x20 /* vertical interpolation off */
#define EXT_VID_DISP_CTL1_Y128 0x10 /* Y data offset by 128 (if YUV128 set) */
#define EXT_VID_DISP_CTL1_VINTERPOL_OFF 0x20 /* disable vertical interpolation */
#define EXT_VID_DISP_CTL1_FULL_WIN 0x40 /* video out window full */
#define EXT_VID_DISP_CTL1_ENABLE_WINDOW 0x80 /* enable video window */
#define EXT_VID_FIFO_CTL1 0xdd
#define EXT_VID_FIFO_CTL1_OE_HIGH 0x02
#define EXT_VID_FIFO_CTL1_INTERLEAVE 0x04 /* enable interleaved memory read */
#define EXT_ROM_UCB4GH 0xe5
#define EXT_ROM_UCB4GH_FREEZE 0x02 /* capture frozen */
#define EXT_ROM_UCB4GH_ODDFRAME 0x04 /* 1 = odd frame captured */
#define EXT_ROM_UCB4GH_1HL 0x08 /* first horizonal line after VGT falling edge */
#define EXT_ROM_UCB4GH_ODD 0x10 /* odd frame indicator */
#define EXT_ROM_UCB4GH_INTSTAT 0x20 /* video interrupt */
#define VFAC_CTL1 0xe8
#define VFAC_CTL1_CAPTURE 0x01 /* capture enable */
#define VFAC_CTL1_CAPTURE 0x01 /* capture enable (only when VSYNC high)*/
#define VFAC_CTL1_VFAC_ENABLE 0x02 /* vfac enable */
#define VFAC_CTL1_FREEZE_CAPTURE 0x04 /* freeze capture */
#define VFAC_CTL1_FREEZE_CAPTURE_SYNC 0x08 /* sync freeze capture */
......@@ -195,6 +312,13 @@ static void debug_printf(char *fmt, ...)
#define VFAC_CTL2_INVERT_OVSYNC 0x80 /* invert other vsync input */
#define VFAC_CTL3 0xea
#define VFAC_CTL3_CAP_LARGE_FIFO 0x01 /* large capture fifo */
#define VFAC_CTL3_CAP_INTERLACE 0x02 /* capture odd and even fields */
#define VFAC_CTL3_CAP_HOLD_4NS 0x00 /* hold capture data for 4ns */
#define VFAC_CTL3_CAP_HOLD_2NS 0x04 /* hold capture data for 2ns */
#define VFAC_CTL3_CAP_HOLD_6NS 0x08 /* hold capture data for 6ns */
#define VFAC_CTL3_CAP_HOLD_0NS 0x0c /* hold capture data for 0ns */
#define VFAC_CTL3_CHROMAKEY 0x20 /* capture data will be chromakeyed */
#define VFAC_CTL3_CAP_IRQ 0x40 /* enable capture interrupt */
#define CAP_MEM_START 0xeb /* 18 bits */
......@@ -232,6 +356,48 @@ static void debug_printf(char *fmt, ...)
#define BM_CONTROL_INIT 0x04 /* initialise status & count */
#define BM_COUNT 0xbc090 /* read-only */
/*
* TV registers
*/
#define TV_VBLANK_EVEN_START 0xbe43c
#define TV_VBLANK_EVEN_END 0xbe440
#define TV_VBLANK_ODD_START 0xbe444
#define TV_VBLANK_ODD_END 0xbe448
#define TV_SYNC_YGAIN 0xbe44c
#define TV_UV_GAIN 0xbe450
#define TV_PED_UVDET 0xbe454
#define TV_UV_BURST_AMP 0xbe458
#define TV_HSYNC_START 0xbe45c
#define TV_HSYNC_END 0xbe460
#define TV_Y_DELAY1 0xbe464
#define TV_Y_DELAY2 0xbe468
#define TV_UV_DELAY1 0xbe46c
#define TV_BURST_START 0xbe470
#define TV_BURST_END 0xbe474
#define TV_HBLANK_START 0xbe478
#define TV_HBLANK_END 0xbe47c
#define TV_PED_EVEN_START 0xbe480
#define TV_PED_EVEN_END 0xbe484
#define TV_PED_ODD_START 0xbe488
#define TV_PED_ODD_END 0xbe48c
#define TV_VSYNC_EVEN_START 0xbe490
#define TV_VSYNC_EVEN_END 0xbe494
#define TV_VSYNC_ODD_START 0xbe498
#define TV_VSYNC_ODD_END 0xbe49c
#define TV_SCFL 0xbe4a0
#define TV_SCFH 0xbe4a4
#define TV_SCP 0xbe4a8
#define TV_DELAYBYPASS 0xbe4b4
#define TV_EQL_END 0xbe4bc
#define TV_SERR_START 0xbe4c0
#define TV_SERR_END 0xbe4c4
#define TV_CTL 0xbe4dc /* reflects a previous register- MVFCLR, MVPCLR etc P241*/
#define TV_VSYNC_VGA_HS 0xbe4e8
#define TV_FLICK_XMIN 0xbe514
#define TV_FLICK_XMAX 0xbe518
#define TV_FLICK_YMIN 0xbe51c
#define TV_FLICK_YMAX 0xbe520
/*
* Graphics Co-processor
*/
......@@ -267,6 +433,7 @@ struct cyberpro_info {
char *fb;
char dev_name[32];
unsigned int fb_size;
unsigned int chip_id;
/*
* The following is a pointer to be passed into the
......@@ -286,10 +453,19 @@ struct cyberpro_info {
void (*disable_extregs)(struct cfb_info *);
};
#define ID_IGA_1682 0
#define ID_CYBERPRO_2000 1
#define ID_CYBERPRO_2010 2
#define ID_CYBERPRO_5000 3
struct fb_var_screeninfo;
/*
* Note! Writing to the Cyber20x0 registers from an interrupt
* routine is definitely a bad idea atm.
*/
int cyber2000fb_attach(struct cyberpro_info *info, int idx);
void cyber2000fb_detach(int idx);
void cyber2000fb_enable_extregs(struct cfb_info *cfb);
void cyber2000fb_disable_extregs(struct cfb_info *cfb);
void cyber2000fb_get_fb_var(struct cfb_info *cfb, struct fb_var_screeninfo *var);
......@@ -52,6 +52,7 @@ extern int acornfb_init(void);
extern int acornfb_setup(char*);
extern int amifb_init(void);
extern int amifb_setup(char*);
extern int anakinfb_init(void);
extern int atafb_init(void);
extern int atafb_setup(char*);
extern int macfb_init(void);
......@@ -60,7 +61,9 @@ extern int cyberfb_init(void);
extern int cyberfb_setup(char*);
extern int pm2fb_init(void);
extern int pm2fb_setup(char*);
extern int clps711xfb_init(void);
extern int cyber2000fb_init(void);
extern int cyber2000fb_setup(char*);
extern int retz3fb_init(void);
extern int retz3fb_setup(char*);
extern int clgenfb_init(void);
......@@ -154,11 +157,17 @@ static struct {
#ifdef CONFIG_FB_AMIGA
{ "amifb", amifb_init, amifb_setup },
#endif
#ifdef CONFIG_FB_ANAKIN
{ "anakinfb", anakinfb_init, NULL },
#endif
#ifdef CONFIG_FB_CLPS711X
{ "clps711xfb", clps711xfb_init, NULL },
#endif
#ifdef CONFIG_FB_CYBER
{ "cyber", cyberfb_init, cyberfb_setup },
#endif
#ifdef CONFIG_FB_CYBER2000
{ "cyber2000", cyber2000fb_init, NULL },
{ "cyber2000", cyber2000fb_init, cyber2000fb_setup },
#endif
#ifdef CONFIG_FB_PM2
{ "pm2fb", pm2fb_init, pm2fb_setup },
......
......@@ -23,11 +23,11 @@
* Thank you.
*
* Known problems:
* - With the Neponset plugged into an Assabet, LCD powerdown
* doesn't work (LCD stays powered up). Therefore we shouldn't
* blank the screen.
* - We don't limit the CPU clock rate nor the mode selection
* according to the available SDRAM bandwidth.
* - With the Neponset plugged into an Assabet, LCD powerdown
* doesn't work (LCD stays powered up). Therefore we shouldn't
* blank the screen.
* - We don't limit the CPU clock rate nor the mode selection
* according to the available SDRAM bandwidth.
*
* Other notes:
* - Linear grayscale palettes and the kernel.
......@@ -41,6 +41,17 @@
* David Neuer. It's around 8 lines of C code, plus another 4 to
* detect if we are using grayscale.
*
* - The following must never be specified in a panel definition:
* LCCR0_LtlEnd, LCCR3_PixClkDiv, LCCR3_VrtSnchL, LCCR3_HorSnchL
*
* - The following should be specified:
* either LCCR0_Color or LCCR0_Mono
* either LCCR0_Sngl or LCCR0_Dual
* either LCCR0_Act or LCCR0_Pas
* either LCCR3_OutEnH or LCCD3_OutEnL
* either LCCR3_PixRsEdg or LCCR3_PixFlEdg
* either LCCR3_ACBsDiv or LCCR3_ACBsCntOff
*
* Code Status:
* 1999/04/01:
* - Driver appears to be working for Brutus 320x200x8bpp mode. Other
......@@ -161,6 +172,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/cpufreq.h>
#include <asm/hardware.h>
......@@ -169,6 +181,7 @@
#include <asm/mach-types.h>
#include <asm/uaccess.h>
#include <asm/arch/assabet.h>
#include <asm/arch/shannon.h>
#include <video/fbcon.h>
#include <video/fbcon-mfb.h>
......@@ -176,11 +189,6 @@
#include <video/fbcon-cfb8.h>
#include <video/fbcon-cfb16.h>
/*
* enable this if your panel appears to have broken
*/
#undef CHECK_COMPAT
/*
* debugging?
*/
......@@ -194,246 +202,12 @@
#include "sa1100fb.h"
extern void (*sa1100fb_backlight_power)(int on);
extern void (*sa1100fb_lcd_power)(int on);
void (*sa1100fb_blank_helper)(int blank);
EXPORT_SYMBOL(sa1100fb_blank_helper);
#ifdef CHECK_COMPAT
static void
sa1100fb_check_shadow(struct sa1100fb_lcd_reg *new_regs,
struct fb_var_screeninfo *var, u_int pcd)
{
struct sa1100fb_lcd_reg shadow;
int different = 0;
/*
* These machines are good machines!
*/
if (machine_is_assabet() || machine_is_h3600())
return;
/*
* The following ones are bad, bad, bad.
* Please make yours good!
*/
if (machine_is_pangolin()) {
DPRINTK("Configuring Pangolin LCD\n");
shadow.lccr0 =
LCCR0_LEN + LCCR0_Color + LCCR0_LDM +
LCCR0_BAM + LCCR0_ERM + LCCR0_Act +
LCCR0_LtlEnd + LCCR0_DMADel(0);
shadow.lccr1 =
LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(64) +
LCCR1_BegLnDel(160) + LCCR1_EndLnDel(24);
shadow.lccr2 =
LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(7) +
LCCR2_BegFrmDel(7) + LCCR2_EndFrmDel(1);
shadow.lccr3 =
LCCR3_PixClkDiv(pcd) + LCCR3_HorSnchH +
LCCR3_VrtSnchH + LCCR3_PixFlEdg + LCCR3_OutEnH;
DPRINTK("pcd = %x, PixCldDiv(pcd)=%x\n",
pcd, LCCR3_PixClkDiv(pcd));
}
if (machine_is_freebird()) {
DPRINTK("Configuring Freebird LCD\n");
#if 1
shadow.lccr0 = 0x00000038;
shadow.lccr1 = 0x010108e0;
shadow.lccr2 = 0x0000053f;
shadow.lccr3 = 0x00000c20;
#else
shadow.lccr0 =
LCCR0_LEN + LCCR0_Color + LCCR0_Sngl +
LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + LCCR0_Pas +
LCCR0_LtlEnd + LCCR0_DMADel(0);
/* Check ,Chester */
shadow.lccr1 =
LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(5) +
LCCR1_BegLnDel(61) + LCCR1_EndLnDel(9);
/* Check ,Chester */
shadow.lccr2 =
LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
LCCR2_BegFrmDel(3) + LCCR2_EndFrmDel(0);
/* Check ,Chester */
shadow.lccr3 =
LCCR3_OutEnH + LCCR3_PixFlEdg + LCCR3_VrtSnchH +
LCCR3_HorSnchH + LCCR3_ACBsCntOff +
LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(pcd);
#endif
}
if (machine_is_brutus()) {
DPRINTK("Configuring Brutus LCD\n");
shadow.lccr0 =
LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Pas +
LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
LCCR0_DMADel(0);
shadow.lccr1 =
LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(3) +
LCCR1_BegLnDel(41) + LCCR1_EndLnDel(101);
shadow.lccr2 =
LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0);
shadow.lccr3 =
LCCR3_OutEnH + LCCR3_PixRsEdg + LCCR3_VrtSnchH +
LCCR3_HorSnchH + LCCR3_ACBsCntOff +
LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(44);
}
if (machine_is_huw_webpanel()) {
DPRINTK("Configuring HuW LCD\n");
shadow.lccr0 = LCCR0_LEN + LCCR0_Dual + LCCR0_LDM;
shadow.lccr1 = LCCR1_DisWdth(var->xres) +
LCCR1_HorSnchWdth(3) +
LCCR1_BegLnDel(41) + LCCR1_EndLnDel(101);
shadow.lccr2 = 239 + LCCR2_VrtSnchWdth(1);
shadow.lccr3 = 8 + LCCR3_OutEnH +
LCCR3_PixRsEdg + LCCR3_VrtSnchH +
LCCR3_HorSnchH + LCCR3_ACBsCntOff + LCCR3_ACBsDiv(2);
}
if (machine_is_lart()) {
DPRINTK("Configuring LART LCD\n");
#if defined LART_GREY_LCD
shadow.lccr0 =
LCCR0_LEN + LCCR0_Mono + LCCR0_Sngl + LCCR0_Pas +
LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
LCCR0_DMADel(0);
shadow.lccr1 =
LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(1) +
LCCR1_BegLnDel(4) + LCCR1_EndLnDel(2);
shadow.lccr2 =
LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0);
shadow.lccr3 =
LCCR3_PixClkDiv(34) + LCCR3_ACBsDiv(512) +
LCCR3_ACBsCntOff + LCCR3_HorSnchH + LCCR3_VrtSnchH;
#endif
#if defined LART_COLOR_LCD
shadow.lccr0 =
LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
LCCR0_DMADel(0);
shadow.lccr1 =
LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(2) +
LCCR1_BegLnDel(69) + LCCR1_EndLnDel(8);
shadow.lccr2 =
LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(3) +
LCCR2_BegFrmDel(14) + LCCR2_EndFrmDel(4);
shadow.lccr3 =
LCCR3_PixClkDiv(34) + LCCR3_ACBsDiv(512) +
LCCR3_ACBsCntOff + LCCR3_HorSnchL + LCCR3_VrtSnchL +
LCCR3_PixFlEdg;
#endif
#if defined LART_VIDEO_OUT
shadow.lccr0 =
LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
LCCR0_DMADel(0);
shadow.lccr1 =
LCCR1_DisWdth(640) + LCCR1_HorSnchWdth(95) +
LCCR1_BegLnDel(40) + LCCR1_EndLnDel(24);
shadow.lccr2 =
LCCR2_DisHght(480) + LCCR2_VrtSnchWdth(2) +
LCCR2_BegFrmDel(32) + LCCR2_EndFrmDel(11);
shadow.lccr3 =
LCCR3_PixClkDiv(8) + LCCR3_ACBsDiv(512) +
LCCR3_ACBsCntOff + LCCR3_HorSnchH + LCCR3_VrtSnchH +
LCCR3_PixFlEdg + LCCR3_OutEnL;
#endif
}
if (machine_is_graphicsclient()) {
DPRINTK("Configuring GraphicsClient LCD\n");
shadow.lccr0 =
LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act;
shadow.lccr1 =
LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(9) +
LCCR1_EndLnDel(54) + LCCR1_BegLnDel(54);
shadow.lccr2 =
LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(9) +
LCCR2_EndFrmDel(32) + LCCR2_BegFrmDel(24);
shadow.lccr3 =
LCCR3_PixClkDiv(10) + LCCR3_ACBsDiv(2) +
LCCR3_ACBsCntOff + LCCR3_HorSnchL + LCCR3_VrtSnchL;
}
if (machine_is_omnimeter()) {
DPRINTK("Configuring OMNI LCD\n");
shadow.lccr0 = LCCR0_LEN | LCCR0_CMS | LCCR0_DPD;
shadow.lccr1 =
LCCR1_BegLnDel(10) + LCCR1_EndLnDel(10) +
LCCR1_HorSnchWdth(1) + LCCR1_DisWdth(var->xres);
shadow.lccr2 = LCCR2_DisHght(var->yres);
shadow.lccr3 =
LCCR3_ACBsDiv(0xFF) + LCCR3_PixClkDiv(44);
//jca (GetPCD(25) << LCD3_V_PCD);
}
if (machine_is_xp860()) {
DPRINTK("Configuring XP860 LCD\n");
shadow.lccr0 =
LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
LCCR0_LtlEnd + LCCR0_LDM + LCCR0_ERM + LCCR0_DMADel(0);
shadow.lccr1 =
LCCR1_DisWdth(var->xres) +
LCCR1_HorSnchWdth(var->hsync_len) +
LCCR1_BegLnDel(var->left_margin) +
LCCR1_EndLnDel(var->right_margin);
shadow.lccr2 =
LCCR2_DisHght(var->yres) +
LCCR2_VrtSnchWdth(var->vsync_len) +
LCCR2_BegFrmDel(var->upper_margin) +
LCCR2_EndFrmDel(var->lower_margin);
shadow.lccr3 =
LCCR3_PixClkDiv(6) + LCCR3_HorSnchL + LCCR3_VrtSnchL;
}
/*
* Ok, since we're calculating these values, we want to know
* if the calculation is correct. If you see any of these
* messages _PLEASE_ report the incident to me for diagnosis,
* including details about what was happening when the
* messages appeared. --rmk, 30 March 2001
*/
if (shadow.lccr0 != new_regs->lccr0) {
printk(KERN_ERR "LCCR1 mismatch: 0x%08x != 0x%08x\n",
shadow.lccr1, new_regs->lccr1);
different = 1;
}
if (shadow.lccr1 != new_regs->lccr1) {
printk(KERN_ERR "LCCR1 mismatch: 0x%08x != 0x%08x\n",
shadow.lccr1, new_regs->lccr1);
different = 1;
}
if (shadow.lccr2 != new_regs->lccr2) {
printk(KERN_ERR "LCCR2 mismatch: 0x%08x != 0x%08x\n",
shadow.lccr2, new_regs->lccr2);
different = 1;
}
if (shadow.lccr3 != new_regs->lccr3) {
printk(KERN_ERR "LCCR3 mismatch: 0x%08x != 0x%08x\n",
shadow.lccr3, new_regs->lccr3);
different = 1;
}
if (different) {
printk(KERN_ERR "var: xres=%d hslen=%d lm=%d rm=%d\n",
var->xres, var->hsync_len,
var->left_margin, var->right_margin);
printk(KERN_ERR "var: yres=%d vslen=%d um=%d bm=%d\n",
var->yres, var->vsync_len,
var->upper_margin, var->lower_margin);
printk(KERN_ERR "Please report this to Russell King "
"<rmk@arm.linux.org.uk>\n");
}
DPRINTK("olccr0 = 0x%08x\n", shadow.lccr0);
DPRINTK("olccr1 = 0x%08x\n", shadow.lccr1);
DPRINTK("olccr2 = 0x%08x\n", shadow.lccr2);
DPRINTK("olccr3 = 0x%08x\n", shadow.lccr3);
}
#else
#define sa1100fb_check_shadow(regs,var,pcd)
#endif
/*
* IMHO this looks wrong. In 8BPP, length should be 8.
*/
......@@ -488,42 +262,56 @@ static struct sa1100fb_mach_info pal_info __initdata = {
#endif
#endif
#ifdef CONFIG_SA1100_H3600
static struct sa1100fb_mach_info h3600_info __initdata = {
#ifdef CONFIG_IPAQ_H3100
pixclock: 407766, bpp: 4,
#ifdef CONFIG_SA1100_H3XXX
static struct sa1100fb_mach_info h3800_info __initdata = {
pixclock: 174757, bpp: 16,
xres: 320, yres: 240,
hsync_len: 26, vsync_len: 41,
left_margin: 4, upper_margin: 0,
right_margin: 4, lower_margin: 0,
hsync_len: 3, vsync_len: 3,
left_margin: 12, upper_margin: 10,
right_margin: 17, lower_margin: 1,
sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
cmap_greyscale: 1, cmap_static: 1,
cmap_inverse: 1,
sync: 0, cmap_static: 1,
lccr0: LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
#else
pixclock: 174757, bpp: 16,
lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
lccr3: LCCR3_ACBsCntOff | LCCR3_PixFlEdg | LCCR3_OutEnH,
};
static struct sa1100fb_mach_info h3600_info __initdata = {
pixclock: 174757, bpp: 16,
xres: 320, yres: 240,
hsync_len: 3, vsync_len: 3,
left_margin: 12, upper_margin: 10,
right_margin: 17, lower_margin: 1,
sync: 0,
sync: 0, cmap_static: 1,
lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
#endif
lccr3: LCCR3_ACBsCntOff | LCCR3_OutEnH | LCCR3_PixFlEdg,
};
static struct sa1100fb_rgb h3600_rgb_16 = {
red: { offset: 12, length: 4, },
green: { offset: 7, length: 4, },
blue: { offset: 1, length: 4, },
transp: { offset: 0, length: 0, },
transp: { offset: 0, length: 0, },
};
static struct sa1100fb_mach_info h3100_info __initdata = {
pixclock: 406977, bpp: 4,
xres: 320, yres: 240,
hsync_len: 26, vsync_len: 41,
left_margin: 4, upper_margin: 0,
right_margin: 4, lower_margin: 0,
sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
cmap_greyscale: 1,
cmap_inverse: 1,
lccr0: LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
};
#endif
......@@ -717,6 +505,22 @@ static struct sa1100fb_mach_info lart_kit01_info __initdata =
};
#endif
#ifdef CONFIG_SA1100_SHANNON
static struct sa1100fb_mach_info shannon_info __initdata = {
pixclock: 152500, bpp: 8,
xres: 640, yres: 480,
hsync_len: 4, vsync_len: 3,
left_margin: 2, upper_margin: 0,
right_margin: 1, lower_margin: 0,
sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
lccr0: LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
lccr3: LCCR3_ACBsDiv(512),
};
#endif
#ifdef CONFIG_SA1100_OMNIMETER
static struct sa1100fb_mach_info omnimeter_info __initdata = {
pixclock: 0, bpp: 4,
......@@ -752,7 +556,7 @@ static struct sa1100fb_mach_info pangolin_info __initdata = {
sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg,
lccr3: LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsCntOff,
};
#endif
......@@ -811,6 +615,33 @@ static struct sa1100fb_rgb stork_dstn_rgb_16 = {
#endif
#endif
#ifdef CONFIG_SA1100_PT_SYSTEM3
/*
* 648 x 480 x 8bpp x 75Hz Dual Panel Color STN Display
*
* pixclock = 1/( 640*3/8*240 ), [pixclock]=1e-12s=ps
* 3 due to r,g,b lines
* 8 due to 8 bit data bus
* 640 due to 640 pixels per line
* 240 = 480/2 due to dual panel display
* =>4.32Mhz => 231481E-12s
*/
static struct sa1100fb_mach_info system3_info __initdata = {
pixclock: 231481, bpp: 8,
xres: 640, yres: 480,
hsync_len: 2, vsync_len: 2,
left_margin: 2, upper_margin: 0,
right_margin: 2, lower_margin: 0,
sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
lccr0: LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512) |
LCCR3_ACBsCntOff,
};
#endif
#ifdef CONFIG_SA1100_XP860
static struct sa1100fb_mach_info xp860_info __initdata = {
pixclock: 0, bpp: 8,
......@@ -849,11 +680,17 @@ sa1100fb_get_machine_info(struct sa1100fb_info *fbi)
#endif
}
#endif
#ifdef CONFIG_SA1100_H3600
#ifdef CONFIG_SA1100_H3XXX
if (machine_is_h3600()) {
inf = &h3600_info;
fbi->rgb[RGB_16] = &h3600_rgb_16;
}
if (machine_is_h3100()) {
inf = &h3100_info;
}
if (machine_is_h3800()) {
inf = &h3800_info;
}
#endif
#ifdef CONFIG_SA1100_BRUTUS
if (machine_is_brutus()) {
......@@ -907,9 +744,14 @@ sa1100fb_get_machine_info(struct sa1100fb_info *fbi)
inf = &pangolin_info;
}
#endif
#ifdef CONFIG_SA1100_XP860
if (machine_is_xp860()) {
inf = &xp860_info;
#ifdef CONFIG_SA1100_PT_SYSTEM3
if (machine_is_pt_system3()) {
inf = &system3_info;
}
#endif
#ifdef CONFIG_SA1100_SHANNON
if (machine_is_shannon()) {
inf = &shannon_info;
}
#endif
#ifdef CONFIG_SA1100_STORK
......@@ -922,6 +764,11 @@ sa1100fb_get_machine_info(struct sa1100fb_info *fbi)
fbi->rgb[RGB_16] = &stork_dstn_rgb_16;
#endif
}
#endif
#ifdef CONFIG_SA1100_XP860
if (machine_is_xp860()) {
inf = &xp860_info;
}
#endif
return inf;
}
......@@ -1556,7 +1403,8 @@ static inline int get_pcd(unsigned int pixclock)
unsigned int pcd;
if (pixclock) {
pcd = get_cclk_frequency() * pixclock;
pcd = cpufreq_get(0) / 100;
pcd *= pixclock;
pcd /= 10000000;
pcd += 1; /* make up for integer math truncations */
} else {
......@@ -1659,8 +1507,6 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_
if (pcd)
new_regs.lccr3 |= LCCR3_PixClkDiv(pcd);
sa1100fb_check_shadow(&new_regs, var, pcd);
DPRINTK("nlccr0 = 0x%08x\n", new_regs.lccr0);
DPRINTK("nlccr1 = 0x%08x\n", new_regs.lccr1);
DPRINTK("nlccr2 = 0x%08x\n", new_regs.lccr2);
......@@ -1704,35 +1550,12 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_
* Also, I'm expecting that the backlight stuff should
* be handled differently.
*/
static void sa1100fb_backlight_on(struct sa1100fb_info *fbi)
static inline void sa1100fb_backlight_on(struct sa1100fb_info *fbi)
{
DPRINTK("backlight on\n");
#ifdef CONFIG_SA1100_FREEBIRD
#error FIXME
if (machine_is_freebird()) {
BCR_set(BCR_FREEBIRD_LCD_PWR | BCR_FREEBIRD_LCD_DISP);
}
#endif
#ifdef CONFIG_SA1100_FREEBIRD
if (machine_is_freebird()) {
/* Turn on backlight ,Chester */
BCR_set(BCR_FREEBIRD_LCD_BACKLIGHT);
}
#endif
#ifdef CONFIG_SA1100_HUW_WEBPANEL
#error FIXME
if (machine_is_huw_webpanel()) {
BCR_set(BCR_CCFL_POW + BCR_PWM_BACKLIGHT);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_task(200 * HZ / 1000);
BCR_set(BCR_TFT_ENA);
}
#endif
#ifdef CONFIG_SA1100_OMNIMETER
if (machine_is_omnimeter())
LEDBacklightOn();
#endif
if (sa1100fb_backlight_power)
sa1100fb_backlight_power(1);
}
/*
......@@ -1740,47 +1563,21 @@ static void sa1100fb_backlight_on(struct sa1100fb_info *fbi)
* Also, I'm expecting that the backlight stuff should
* be handled differently.
*/
static void sa1100fb_backlight_off(struct sa1100fb_info *fbi)
static inline void sa1100fb_backlight_off(struct sa1100fb_info *fbi)
{
DPRINTK("backlight off\n");
#ifdef CONFIG_SA1100_FREEBIRD
#error FIXME
if (machine_is_freebird()) {
BCR_clear(BCR_FREEBIRD_LCD_PWR | BCR_FREEBIRD_LCD_DISP
/*| BCR_FREEBIRD_LCD_BACKLIGHT */ );
}
#endif
#ifdef CONFIG_SA1100_OMNIMETER
if (machine_is_omnimeter())
LEDBacklightOff();
#endif
if (sa1100fb_backlight_power)
sa1100fb_backlight_power(0);
}
static void sa1100fb_power_up_lcd(struct sa1100fb_info *fbi)
static inline void sa1100fb_power_up_lcd(struct sa1100fb_info *fbi)
{
DPRINTK("LCD power on\n");
#ifndef ASSABET_PAL_VIDEO
if (machine_is_assabet())
ASSABET_BCR_set(ASSABET_BCR_LCD_ON);
#endif
#ifdef CONFIG_SA1100_HUW_WEBPANEL
if (machine_is_huw_webpanel())
BCR_clear(BCR_TFT_NPWR);
#endif
#ifdef CONFIG_SA1100_OMNIMETER
if (machine_is_omnimeter())
LCDPowerOn();
#endif
#ifdef CONFIG_SA1100_H3600
if (machine_is_h3600()) {
set_h3600_egpio(EGPIO_H3600_LCD_ON |
EGPIO_H3600_LCD_PCI |
EGPIO_H3600_LCD_5V_ON |
EGPIO_H3600_LVDD_ON);
}
#endif
if (sa1100fb_lcd_power)
sa1100fb_lcd_power(1);
#ifdef CONFIG_SA1100_STORK
if (machine_is_stork()) {
storkSetLCDCPLD(0, 1);
......@@ -1789,27 +1586,13 @@ static void sa1100fb_power_up_lcd(struct sa1100fb_info *fbi)
#endif
}
static void sa1100fb_power_down_lcd(struct sa1100fb_info *fbi)
static inline void sa1100fb_power_down_lcd(struct sa1100fb_info *fbi)
{
DPRINTK("LCD power off\n");
#ifndef ASSABET_PAL_VIDEO
if (machine_is_assabet())
ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
#endif
#ifdef CONFIG_SA1100_HUW_WEBPANEL
// dont forget to set the control lines to zero (?)
if (machine_is_huw_webpanel())
BCR_set(BCR_TFT_NPWR);
#endif
#ifdef CONFIG_SA1100_H3600
if (machine_is_h3600()) {
clr_h3600_egpio(EGPIO_H3600_LCD_ON |
EGPIO_H3600_LCD_PCI |
EGPIO_H3600_LCD_5V_ON |
EGPIO_H3600_LVDD_ON);
}
#endif
if (sa1100fb_lcd_power)
sa1100fb_lcd_power(0);
#ifdef CONFIG_SA1100_STORK
if (machine_is_stork()) {
storkSetLCDCPLD(0, 0);
......@@ -1844,14 +1627,6 @@ static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi)
}
#ifdef CONFIG_SA1100_FREEBIRD
#error Please contact <rmk@arm.linux.org.uk> about this
if (machine_is_freebird()) {
/* Color single passive */
mask |= GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 |
GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8;
}
#endif
if (machine_is_cerf()) {
/* GPIO15 is used as a bypass for 3.8" displays */
mask |= GPIO_GPIO15;
......@@ -1920,6 +1695,11 @@ static void sa1100fb_enable_controller(struct sa1100fb_info *fbi)
}
#endif
if (machine_is_shannon()) {
GPDR |= SHANNON_GPIO_DISP_EN;
GPSR |= SHANNON_GPIO_DISP_EN;
}
DPRINTK("DBAR1 = %p\n", DBAR1);
DPRINTK("DBAR2 = %p\n", DBAR2);
DPRINTK("LCCR0 = 0x%08x\n", LCCR0);
......@@ -1958,6 +1738,10 @@ static void sa1100fb_disable_controller(struct sa1100fb_info *fbi)
}
#endif
if (machine_is_shannon()) {
GPCR |= SHANNON_GPIO_DISP_EN;
}
add_wait_queue(&fbi->ctrlr_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE);
......@@ -2006,12 +1790,13 @@ static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state)
* Disable controller for clock change. If the
* controller is already disabled, then do nothing.
*/
if (old_state != C_DISABLE) {
if (old_state != C_DISABLE && old_state != C_DISABLE_PM) {
fbi->state = state;
sa1100fb_disable_controller(fbi);
}
break;
case C_DISABLE_PM:
case C_DISABLE:
/*
* Disable controller
......@@ -2050,6 +1835,16 @@ static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state)
}
break;
case C_ENABLE_PM:
/*
* Re-enable the controller after PM. This is not
* perfect - think about the case where we were doing
* a clock change, and we suspended half-way through.
*/
if (old_state != C_DISABLE_PM)
break;
/* fall through */
case C_ENABLE:
/*
* Power up the LCD screen, enable controller, and
......@@ -2162,10 +1957,10 @@ sa1100fb_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
if (state == 0) {
/* Enter D0. */
set_ctrlr_state(fbi, C_ENABLE);
set_ctrlr_state(fbi, C_ENABLE_PM);
} else {
/* Enter D1-D3. Disable the LCD controller. */
set_ctrlr_state(fbi, C_DISABLE);
set_ctrlr_state(fbi, C_DISABLE_PM);
}
}
DPRINTK("done\n");
......@@ -2245,7 +2040,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void)
fbi->fb.updatevar = sa1100fb_updatevar;
fbi->fb.blank = sa1100fb_blank;
fbi->fb.flags = FBINFO_FLAG_DEFAULT;
fbi->fb.node = -1;
fbi->fb.node = NODEV;
fbi->fb.monspecs = monspecs;
fbi->fb.disp = (struct display *)(fbi + 1);
fbi->fb.pseudo_palette = (void *)(fbi->fb.disp + 1);
......@@ -2293,6 +2088,9 @@ int __init sa1100fb_init(void)
struct sa1100fb_info *fbi;
int ret;
if (!request_mem_region(0xb0100000, 0x10000, "LCD"))
return -EBUSY;
fbi = sa1100fb_init_fbinfo();
ret = -ENOMEM;
if (!fbi)
......@@ -2304,7 +2102,7 @@ int __init sa1100fb_init(void)
goto failed;
ret = request_irq(IRQ_LCD, sa1100fb_handle_irq, SA_INTERRUPT,
fbi->fb.fix.id, fbi);
"LCD", fbi);
if (ret) {
printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret);
goto failed;
......@@ -2358,6 +2156,7 @@ int __init sa1100fb_init(void)
failed:
if (fbi)
kfree(fbi);
release_mem_region(0xb0100000, 0x10000);
return ret;
}
......
......@@ -127,6 +127,8 @@ struct sa1100fb_info {
#define C_DISABLE_CLKCHANGE (2)
#define C_ENABLE_CLKCHANGE (3)
#define C_REENABLE (4)
#define C_DISABLE_PM (5)
#define C_ENABLE_PM (6)
#define SA1100_NAME "SA1100"
......
......@@ -19,6 +19,8 @@
#define NO_IRQ ((unsigned int)(-1))
#endif
struct irqaction;
#define disable_irq_nosync(i) disable_irq(i)
extern void disable_irq(unsigned int);
......@@ -38,5 +40,7 @@ extern void enable_irq(unsigned int);
int set_irq_type(unsigned int irq, unsigned int type);
int setup_irq(unsigned int, struct irqaction *);
#endif
......@@ -23,12 +23,16 @@ typedef enum {
led_stop,
led_claim, /* override idle & timer leds */
led_release, /* restore idle & timer leds */
led_start_timer_mode,
led_stop_timer_mode,
led_green_on,
led_green_off,
led_amber_on,
led_amber_off,
led_red_on,
led_red_off,
led_blue_on,
led_blue_off,
/*
* I want this between led_timer and led_start, but
* someone has decided to export this to user space
......
......@@ -75,7 +75,6 @@ extern void (*init_arch_irq)(void);
extern void init_FIQ(void);
extern int show_fiq_list(struct seq_file *, void *);
void __set_irq_handler(unsigned int irq, irq_handler_t, int);
int setup_irq(unsigned int, struct irqaction *);
/*
* External stuff.
......
......@@ -61,6 +61,7 @@ u8 pci_std_swizzle(struct pci_dev *dev, u8 *pinp);
*/
extern int iop310_setup(int nr, struct pci_sys_data *);
extern struct pci_bus *iop310_scan_bus(int nr, struct pci_sys_data *);
extern void iop310_init(void);
extern int dc21285_setup(int nr, struct pci_sys_data *);
extern struct pci_bus *dc21285_scan_bus(int nr, struct pci_sys_data *);
......@@ -75,4 +76,3 @@ extern int pci_v3_setup(int nr, struct pci_sys_data *);
extern struct pci_bus *pci_v3_scan_bus(int nr, struct pci_sys_data *);
extern void pci_v3_preinit(void);
extern void pci_v3_postinit(void);
......@@ -26,13 +26,10 @@ struct sa1100_port_fns {
void (*close)(struct uart_port *, struct uart_info *);
};
#if defined(CONFIG_SERIAL_SA1100) && !defined(CONFIG_SERIAL_SA1100_OLD)
#ifdef CONFIG_SERIAL_SA1100
void sa1100_register_uart_fns(struct sa1100_port_fns *fns);
void sa1100_register_uart(int idx, int port);
#else
#define sa1100_register_uart_fns(fns) do { } while (0)
#define sa1100_register_uart(idx,port) do { } while (0)
#endif
void sa1100_uart1_altgpio(void);
......@@ -58,74 +58,6 @@
} \
} while (0)
/*
* This flushes back any buffered write data. We have to clean the entries
* in the cache for this page. This does not invalidate either I or D caches.
*
* Called from:
* 1. fs/exec.c:put_dirty_page - ok
* - page came from alloc_page(), so page->mapping = NULL.
* - flush_dcache_page called immediately prior.
*
* 2. kernel/ptrace.c:access_one_page - flush_icache_page
* - flush_cache_page takes care of the user space side of the mapping.
* - page is either a page cache page (with page->mapping set, and
* hence page->mapping->i_mmap{,shared} also set) or an anonymous
* page. I think this is ok.
*
* 3. kernel/ptrace.c:access_one_page - bad
* - flush_cache_page takes care of the user space side of the mapping.
* - no apparant cache protection, reading the kernel virtual alias
*
* 4. mm/filemap.c:filemap_no_page - ok
* - add_to_page_cache_* clears PG_arch_1.
* - page->mapping != NULL.
* - i_mmap or i_mmap_shared will be non-null if mmap'd
* - called from (8).
*
* 5. mm/memory.c:break_cow,do_wp_page - {copy,clear}_user_page
* - need to ensure that copy_cow_page has pushed all data from the dcache
* to the page.
* - calls
* - clear_user_highpage -> clear_user_page
* - copy_user_highpage -> copy_user_page
*
* 6. mm/memory.c:do_swap_page - flush_icache_page
* - flush_icache_page called afterwards - if flush_icache_page does the
* same as flush_dcache_page, update_mmu_cache will do the work for us.
* - update_mmu_cache called.
*
* 7. mm/memory.c:do_anonymous_page - {copy,clear}_user_page
* - calls clear_user_highpage. See (5)
*
* 8. mm/memory.c:do_no_page - flush_icache_page
* - flush_icache_page called afterwards - if flush_icache_page does the
* same as flush_dcache_page, update_mmu_cache will do the work for us.
* - update_mmu_cache called.
* - When we place a user mapping, we will call update_mmu_cache,
* which will catch PG_arch_1 set.
*
* 9. mm/shmem.c:shmem_no_page - ok
* - shmem_get_page clears PG_arch_1, as does add_to_page_cache (duplicate)
* - page->mapping != NULL.
* - i_mmap or i_mmap_shared will be non-null if mmap'd
* - called from (8).
*
* 10. mm/swapfile.c:try_to_unuse - bad
* - this looks really dodgy - we're putting pages from the swap cache
* straight into processes, and the only cache handling appears to
* be flush_page_to_ram.
*/
#define flush_page_to_ram_ok
#ifdef flush_page_to_ram_ok
#define flush_page_to_ram(page) do { } while (0)
#else
static __inline__ void flush_page_to_ram(struct page *page)
{
cpu_flush_ram_page(page_address(page));
}
#endif
/*
* D cache only
*/
......@@ -134,8 +66,16 @@ static __inline__ void flush_page_to_ram(struct page *page)
#define clean_dcache_range(_s,_e) cpu_dcache_clean_range((_s),(_e))
#define flush_dcache_range(_s,_e) cpu_cache_clean_invalidate_range((_s),(_e),0)
#define mapping_mapped(map) (!list_empty(&(map)->i_mmap) || \
!list_empty(&(map)->i_mmap_shared))
#define clean_dcache_area(start,size) \
cpu_cache_clean_invalidate_range((unsigned long)start, \
((unsigned long)start) + size, 0);
/*
* This is an obsolete interface; the functionality that was provided by this
* function is now merged into our flush_dcache_page, flush_icache_page,
* copy_user_page and clear_user_page functions.
*/
#define flush_page_to_ram(page) do { } while (0)
/*
* flush_dcache_page is used when the kernel has written to the page
......@@ -150,39 +90,31 @@ static __inline__ void flush_page_to_ram(struct page *page)
* about to change to user space. This is the same method as used on SPARC64.
* See update_mmu_cache for the user space part.
*/
#define mapping_mapped(map) (!list_empty(&(map)->i_mmap) || \
!list_empty(&(map)->i_mmap_shared))
static inline void __flush_dcache_page(struct page *page)
{
unsigned long virt = (unsigned long)page_address(page);
cpu_cache_clean_invalidate_range(virt, virt + PAGE_SIZE, 0);
}
static inline void flush_dcache_page(struct page *page)
{
if (page->mapping && !mapping_mapped(page->mapping))
set_bit(PG_dcache_dirty, &page->flags);
else {
unsigned long virt = (unsigned long)page_address(page);
cpu_cache_clean_invalidate_range(virt, virt + PAGE_SIZE, 0);
}
else
__flush_dcache_page(page);
}
#define flush_icache_user_range(vma,page,addr,len) \
flush_dcache_page(page)
/*
* flush_icache_page makes the kernel page address consistent with the
* user space mappings. The functionality is the same as flush_dcache_page,
* except we can do an optimisation and only clean the caches here if
* vma->vm_mm == current->active_mm.
*
* This function is misnamed IMHO. There are three places where it
* is called, each of which is preceded immediately by a call to
* flush_page_to_ram:
* We don't appear to need to do anything here. In fact, if we did, we'd
* duplicate cache flushing elsewhere performed by flush_dcache_page().
*/
#ifdef flush_page_to_ram_ok
static inline void flush_icache_page(struct vm_area_struct *vma, struct page *page)
{
if (page->mapping && !mapping_mapped(page->mapping))
set_bit(PG_dcache_dirty, &page->flags);
else if (vma->vm_mm == current->active_mm) {
unsigned long virt = (unsigned long)page_address(page);
cpu_cache_clean_invalidate_range(virt, virt + PAGE_SIZE, 0);
}
}
#else
#define flush_icache_page(vma,pg) do { } while (0)
#endif
#define flush_icache_page(vma,page) do { } while (0)
#define clean_dcache_entry(_s) cpu_dcache_clean_entry((unsigned long)(_s))
......
......@@ -38,13 +38,13 @@
: : "r" (x)); \
} while (0)
#define modify_domain(dom,type) \
do { \
unsigned int domain = current->thread.domain; \
domain &= ~domain_val(dom, DOMAIN_MANAGER); \
domain |= domain_val(dom, type); \
current->thread.domain = domain; \
set_domain(current->thread.domain); \
#define modify_domain(dom,type) \
do { \
struct thread_info *thread = current_thread_info(); \
unsigned int domain = thread->cpu_domain; \
domain &= ~domain_val(dom, DOMAIN_MANAGER); \
thread->cpu_domain = domain | domain_val(dom, type); \
set_domain(thread->cpu_domain); \
} while (0)
#endif
......@@ -107,7 +107,8 @@ typedef struct siginfo {
#define SI_MESGQ -3 /* sent by real time mesq state change */
#define SI_ASYNCIO -4 /* sent by AIO completion */
#define SI_SIGIO -5 /* sent by queued SIGIO */
#define SI_TKILL -6 /* sent by tkill system call */
#define SI_TKILL -6 /* sent by tkill system call */
#define SI_DETHREAD -7 /* sent by execve() killing subsidiary threads */
#define SI_FROMUSER(siptr) ((siptr)->si_code <= 0)
#define SI_FROMKERNEL(siptr) ((siptr)->si_code > 0)
......
......@@ -84,7 +84,6 @@ extern struct task_struct *__switch_to(struct thread_info *, struct thread_info
#define stf() __stf()
#define save_flags(x) __save_flags(x)
#define restore_flags(x) __restore_flags(x)
#define save_flags_cli(x) __save_flags_cli(x)
#endif /* CONFIG_SMP */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment