Commit 28faab99 authored by Russell King's avatar Russell King

[ARM] Update sa1100fb to new fbcon API and device model

This brings sa1100fb up to date with 2.5.54.
parent 5a92c3df
...@@ -170,10 +170,11 @@ ...@@ -170,10 +170,11 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/pm.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -183,12 +184,6 @@ ...@@ -183,12 +184,6 @@
#include <asm/arch/assabet.h> #include <asm/arch/assabet.h>
#include <asm/arch/shannon.h> #include <asm/arch/shannon.h>
#include <video/fbcon.h>
#include <video/fbcon-mfb.h>
#include <video/fbcon-cfb4.h>
#include <video/fbcon-cfb8.h>
#include <video/fbcon-cfb16.h>
/* /*
* debugging? * debugging?
*/ */
...@@ -806,15 +801,9 @@ static inline u_int palette_pbs(struct fb_var_screeninfo *var) ...@@ -806,15 +801,9 @@ static inline u_int palette_pbs(struct fb_var_screeninfo *var)
{ {
int ret = 0; int ret = 0;
switch (var->bits_per_pixel) { switch (var->bits_per_pixel) {
#ifdef FBCON_HAS_CFB4
case 4: ret = 0 << 12; break; case 4: ret = 0 << 12; break;
#endif
#ifdef FBCON_HAS_CFB8
case 8: ret = 1 << 12; break; case 8: ret = 1 << 12; break;
#endif
#ifdef FBCON_HAS_CFB16
case 16: ret = 2 << 12; break; case 16: ret = 2 << 12; break;
#endif
} }
return ret; return ret;
} }
...@@ -875,7 +864,7 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, ...@@ -875,7 +864,7 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
* according to the RGB bitfield information. * according to the RGB bitfield information.
*/ */
if (regno < 16) { if (regno < 16) {
u16 *pal = fbi->fb.pseudo_palette; u32 *pal = fbi->fb.pseudo_palette;
val = chan_to_field(red, &fbi->fb.var.red); val = chan_to_field(red, &fbi->fb.var.red);
val |= chan_to_field(green, &fbi->fb.var.green); val |= chan_to_field(green, &fbi->fb.var.green);
...@@ -935,21 +924,15 @@ sa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) ...@@ -935,21 +924,15 @@ sa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel); DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel);
switch (var->bits_per_pixel) { switch (var->bits_per_pixel) {
#ifdef FBCON_HAS_CFB4
case 4: case 4:
rgbidx = RGB_8; rgbidx = RGB_8;
break; break;
#endif
#ifdef FBCON_HAS_CFB8
case 8: case 8:
rgbidx = RGB_8; rgbidx = RGB_8;
break; break;
#endif
#ifdef FBCON_HAS_CFB16
case 16: case 16:
rgbidx = RGB_16; rgbidx = RGB_16;
break; break;
#endif
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -1023,6 +1006,8 @@ static int sa1100fb_set_par(struct fb_info *info) ...@@ -1023,6 +1006,8 @@ static int sa1100fb_set_par(struct fb_info *info)
fbi->fb.fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR; fbi->fb.fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
} }
fbi->fb.fix.line_length = var->xres_virtual *
var->bits_per_pixel / 8;
fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16; fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16;
palette_mem_size = fbi->palette_size * sizeof(u16); palette_mem_size = fbi->palette_size * sizeof(u16);
...@@ -1048,46 +1033,22 @@ static int sa1100fb_set_par(struct fb_info *info) ...@@ -1048,46 +1033,22 @@ static int sa1100fb_set_par(struct fb_info *info)
return 0; return 0;
} }
/* #if 0
* sa1100fb_set_var():
* Set the user defined part of the display for the specified console
*/
static int
sa1100fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
int ret, act;
act = var->activate & FB_ACTIVATE_MASK;
ret = gen_set_var(var, con, info);
if (ret == 0 && act & FB_ACTIVATE_NOW) {
struct display *display = (con < 0) ? info->disp : fb_display + con;
/*
* fbcon assumes too much.
*/
display->can_soft_blank = 1;
}
return ret;
}
static int static int
sa1100fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, sa1100fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info) struct fb_info *info)
{ {
struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
struct display *disp = (con < 0) ? info->disp : (fb_display + con);
/* /*
* Make sure the user isn't doing something stupid. * Make sure the user isn't doing something stupid.
*/ */
if (!kspc && (disp->var.bits_per_pixel == 16 || fbi->cmap_static)) if (!kspc && (fbi->fb.var.bits_per_pixel == 16 || fbi->cmap_static))
return -EINVAL; return -EINVAL;
return gen_set_cmap(cmap, kspc, con, info); return gen_set_cmap(cmap, kspc, con, info);
} }
#endif
/* /*
* Formal definition of the VESA spec: * Formal definition of the VESA spec:
...@@ -1129,8 +1090,7 @@ static int sa1100fb_blank(int blank, struct fb_info *info) ...@@ -1129,8 +1090,7 @@ static int sa1100fb_blank(int blank, struct fb_info *info)
struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
int i; int i;
DPRINTK("sa1100fb_blank: blank=%d info->modename=%s\n", blank, DPRINTK("sa1100fb_blank: blank=%d\n", blank);
fbi->fb.modename);
switch (blank) { switch (blank) {
case VESA_POWERDOWN: case VESA_POWERDOWN:
...@@ -1156,19 +1116,14 @@ static struct fb_ops sa1100fb_ops = { ...@@ -1156,19 +1116,14 @@ static struct fb_ops sa1100fb_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.fb_check_var = sa1100fb_check_var, .fb_check_var = sa1100fb_check_var,
.fb_set_par = sa1100fb_set_par, .fb_set_par = sa1100fb_set_par,
.fb_set_var = sa1100fb_set_var, // .fb_set_cmap = sa1100fb_set_cmap,
.fb_get_cmap = gen_get_cmap,
.fb_set_cmap = sa1100fb_set_cmap,
.fb_setcolreg = sa1100fb_setcolreg, .fb_setcolreg = sa1100fb_setcolreg,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_blank = sa1100fb_blank, .fb_blank = sa1100fb_blank,
}; };
static int sa1100fb_updatevar(int con, struct fb_info *info)
{
/* we don't support panning nor scrolling */
return 0;
}
/* /*
* Calculate the PCD value from the clock rate (in picoseconds). * Calculate the PCD value from the clock rate (in picoseconds).
* We take account of the PPCR clock setting. * We take account of the PPCR clock setting.
...@@ -1259,10 +1214,10 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_ ...@@ -1259,10 +1214,10 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_
(var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) | (var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
(var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL); (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL);
DPRINTK("nlccr0 = 0x%08x\n", new_regs.lccr0); DPRINTK("nlccr0 = 0x%08lx\n", new_regs.lccr0);
DPRINTK("nlccr1 = 0x%08x\n", new_regs.lccr1); DPRINTK("nlccr1 = 0x%08lx\n", new_regs.lccr1);
DPRINTK("nlccr2 = 0x%08x\n", new_regs.lccr2); DPRINTK("nlccr2 = 0x%08lx\n", new_regs.lccr2);
DPRINTK("nlccr3 = 0x%08x\n", new_regs.lccr3); DPRINTK("nlccr3 = 0x%08lx\n", new_regs.lccr3);
half_screen_size = var->bits_per_pixel; half_screen_size = var->bits_per_pixel;
half_screen_size = half_screen_size * var->xres * var->yres / 16; half_screen_size = half_screen_size * var->xres * var->yres / 16;
...@@ -1382,8 +1337,8 @@ static void sa1100fb_enable_controller(struct sa1100fb_info *fbi) ...@@ -1382,8 +1337,8 @@ static void sa1100fb_enable_controller(struct sa1100fb_info *fbi)
GPSR |= SHANNON_GPIO_DISP_EN; GPSR |= SHANNON_GPIO_DISP_EN;
} }
DPRINTK("DBAR1 = %p\n", DBAR1); DPRINTK("DBAR1 = 0x%08x\n", DBAR1);
DPRINTK("DBAR2 = %p\n", DBAR2); DPRINTK("DBAR2 = 0x%08x\n", DBAR2);
DPRINTK("LCCR0 = 0x%08x\n", LCCR0); DPRINTK("LCCR0 = 0x%08x\n", LCCR0);
DPRINTK("LCCR1 = 0x%08x\n", LCCR1); DPRINTK("LCCR1 = 0x%08x\n", LCCR1);
DPRINTK("LCCR2 = 0x%08x\n", LCCR2); DPRINTK("LCCR2 = 0x%08x\n", LCCR2);
...@@ -1465,6 +1420,12 @@ static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state) ...@@ -1465,6 +1420,12 @@ static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state)
old_state = fbi->state; old_state = fbi->state;
/*
* Hack around fbcon initialisation.
*/
if (old_state == C_STARTUP && state == C_REENABLE)
state = C_ENABLE;
switch (state) { switch (state) {
case C_DISABLE_CLKCHANGE: case C_DISABLE_CLKCHANGE:
/* /*
...@@ -1563,6 +1524,7 @@ static void sa1100fb_task(void *dummy) ...@@ -1563,6 +1524,7 @@ static void sa1100fb_task(void *dummy)
*/ */
static unsigned int sa1100fb_min_dma_period(struct sa1100fb_info *fbi) static unsigned int sa1100fb_min_dma_period(struct sa1100fb_info *fbi)
{ {
#if 0
unsigned int min_period = (unsigned int)-1; unsigned int min_period = (unsigned int)-1;
int i; int i;
...@@ -1585,6 +1547,12 @@ static unsigned int sa1100fb_min_dma_period(struct sa1100fb_info *fbi) ...@@ -1585,6 +1547,12 @@ static unsigned int sa1100fb_min_dma_period(struct sa1100fb_info *fbi)
} }
return min_period; return min_period;
#else
/*
* FIXME: we need to verify _all_ consoles.
*/
return sa1100fb_display_dma_period(&fbi->fb.var);
#endif
} }
/* /*
...@@ -1633,30 +1601,29 @@ sa1100fb_freq_policy(struct notifier_block *nb, unsigned long val, ...@@ -1633,30 +1601,29 @@ sa1100fb_freq_policy(struct notifier_block *nb, unsigned long val,
#ifdef CONFIG_PM #ifdef CONFIG_PM
/* /*
* Power management hook. Note that we won't be called from IRQ context, * Power management hooks. Note that we won't be called from IRQ context,
* unlike the blank functions above, so we may sleep. * unlike the blank functions above, so we may sleep.
*/ */
static int static int sa1100fb_suspend(struct device *dev, u32 state, u32 level)
sa1100fb_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
{ {
struct sa1100fb_info *fbi = pm_dev->data; struct sa1100fb_info *fbi = dev_get_drvdata(dev);
DPRINTK("pm_callback: %d\n", req); if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN)
set_ctrlr_state(fbi, C_DISABLE_PM);
return 0;
}
if (req == PM_SUSPEND || req == PM_RESUME) { static int sa1100fb_resume(struct device *dev, u32 level)
int state = (int)data; {
struct sa1100fb_info *fbi = dev_get_drvdata(dev);
if (state == 0) { if (level == RESUME_ENABLE)
/* Enter D0. */
set_ctrlr_state(fbi, C_ENABLE_PM); set_ctrlr_state(fbi, C_ENABLE_PM);
} else {
/* Enter D1-D3. Disable the LCD controller. */
set_ctrlr_state(fbi, C_DISABLE_PM);
}
}
DPRINTK("done\n");
return 0; return 0;
} }
#else
#define sa1100fb_suspend NULL
#define sa1100fb_resume NULL
#endif #endif
/* /*
...@@ -1697,12 +1664,12 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void) ...@@ -1697,12 +1664,12 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void)
struct sa1100fb_mach_info *inf; struct sa1100fb_mach_info *inf;
struct sa1100fb_info *fbi; struct sa1100fb_info *fbi;
fbi = kmalloc(sizeof(struct sa1100fb_info) + sizeof(struct display) + fbi = kmalloc(sizeof(struct sa1100fb_info) + sizeof(u32) * 16,
sizeof(u16) * 16, GFP_KERNEL); GFP_KERNEL);
if (!fbi) if (!fbi)
return NULL; return NULL;
memset(fbi, 0, sizeof(struct sa1100fb_info) + sizeof(struct display)); memset(fbi, 0, sizeof(struct sa1100fb_info));
strcpy(fbi->fb.fix.id, SA1100_NAME); strcpy(fbi->fb.fix.id, SA1100_NAME);
...@@ -1711,7 +1678,6 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void) ...@@ -1711,7 +1678,6 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void)
fbi->fb.fix.xpanstep = 0; fbi->fb.fix.xpanstep = 0;
fbi->fb.fix.ypanstep = 0; fbi->fb.fix.ypanstep = 0;
fbi->fb.fix.ywrapstep = 0; fbi->fb.fix.ywrapstep = 0;
fbi->fb.fix.line_length = 0;
fbi->fb.fix.accel = FB_ACCEL_NONE; fbi->fb.fix.accel = FB_ACCEL_NONE;
fbi->fb.var.nonstd = 0; fbi->fb.var.nonstd = 0;
...@@ -1721,19 +1687,12 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void) ...@@ -1721,19 +1687,12 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void)
fbi->fb.var.accel_flags = 0; fbi->fb.var.accel_flags = 0;
fbi->fb.var.vmode = FB_VMODE_NONINTERLACED; fbi->fb.var.vmode = FB_VMODE_NONINTERLACED;
strcpy(fbi->fb.modename, SA1100_NAME);
strcpy(fbi->fb.fontname, "Acorn8x8");
fbi->fb.fbops = &sa1100fb_ops; fbi->fb.fbops = &sa1100fb_ops;
fbi->fb.changevar = NULL;
fbi->fb.switch_con = gen_switch;
fbi->fb.updatevar = sa1100fb_updatevar;
fbi->fb.flags = FBINFO_FLAG_DEFAULT; fbi->fb.flags = FBINFO_FLAG_DEFAULT;
fbi->fb.node = NODEV; fbi->fb.node = NODEV;
fbi->fb.monspecs = monspecs; fbi->fb.monspecs = monspecs;
fbi->fb.currcon = -1; fbi->fb.currcon = -1;
fbi->fb.disp = (struct display *)(fbi + 1); fbi->fb.pseudo_palette = (fbi + 1);
fbi->fb.pseudo_palette = (void *)(fbi->fb.disp + 1);
fbi->rgb[RGB_8] = &rgb_8; fbi->rgb[RGB_8] = &rgb_8;
fbi->rgb[RGB_16] = &def_rgb_16; fbi->rgb[RGB_16] = &def_rgb_16;
...@@ -1771,11 +1730,10 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void) ...@@ -1771,11 +1730,10 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void)
fbi->cmap_static = inf->cmap_static; fbi->cmap_static = inf->cmap_static;
fbi->lccr0 = inf->lccr0; fbi->lccr0 = inf->lccr0;
fbi->lccr3 = inf->lccr3; fbi->lccr3 = inf->lccr3;
fbi->state = C_DISABLE; fbi->state = C_STARTUP;
fbi->task_state = (u_char)-1; fbi->task_state = (u_char)-1;
fbi->fb.fix.smem_len = fbi->max_xres * fbi->max_yres * fbi->fb.fix.smem_len = fbi->max_xres * fbi->max_yres *
fbi->max_bpp / 8; fbi->max_bpp / 8;
fbi->fb.disp->inverse = inf->cmap_inverse;
init_waitqueue_head(&fbi->ctrlr_wait); init_waitqueue_head(&fbi->ctrlr_wait);
INIT_WORK(&fbi->task, sa1100fb_task, fbi); INIT_WORK(&fbi->task, sa1100fb_task, fbi);
...@@ -1784,6 +1742,24 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void) ...@@ -1784,6 +1742,24 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void)
return fbi; return fbi;
} }
static struct device_driver sa1100fb_driver = {
.name = "sa1100fb",
.bus = &system_bus_type,
.suspend = sa1100fb_suspend,
.resume = sa1100fb_resume,
};
static struct sys_device sa1100fb_dev = {
.name = "LCD",
.id = 0,
.root = NULL,
.dev = {
.name = "Intel Corporation SA11x0 [LCD]",
.bus_id = "b0100000",
.driver = &sa1100fb_driver,
},
};
int __init sa1100fb_init(void) int __init sa1100fb_init(void)
{ {
struct sa1100fb_info *fbi; struct sa1100fb_info *fbi;
...@@ -1792,11 +1768,16 @@ int __init sa1100fb_init(void) ...@@ -1792,11 +1768,16 @@ int __init sa1100fb_init(void)
if (!request_mem_region(0xb0100000, 0x10000, "LCD")) if (!request_mem_region(0xb0100000, 0x10000, "LCD"))
return -EBUSY; return -EBUSY;
driver_register(&sa1100fb_driver);
sys_device_register(&sa1100fb_dev);
fbi = sa1100fb_init_fbinfo(); fbi = sa1100fb_init_fbinfo();
ret = -ENOMEM; ret = -ENOMEM;
if (!fbi) if (!fbi)
goto failed; goto failed;
dev_set_drvdata(&sa1100fb_dev.dev, fbi);
/* Initialize video memory */ /* Initialize video memory */
ret = sa1100fb_map_video_memory(fbi); ret = sa1100fb_map_video_memory(fbi);
if (ret) if (ret)
...@@ -1824,21 +1805,16 @@ int __init sa1100fb_init(void) ...@@ -1824,21 +1805,16 @@ int __init sa1100fb_init(void)
} }
#endif #endif
sa1100fb_set_var(&fbi->fb.var, -1, &fbi->fb); /*
* This makes sure that our colour bitfield
* descriptors are correctly initialised.
*/
sa1100fb_check_var(&fbi->fb.var, &fbi->fb);
ret = register_framebuffer(&fbi->fb); ret = register_framebuffer(&fbi->fb);
if (ret < 0) if (ret < 0)
goto failed; goto failed;
#ifdef CONFIG_PM
/*
* Note that the console registers this as well, but we want to
* power down the display prior to sleeping.
*/
fbi->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, sa1100fb_pm_callback);
if (fbi->pm)
fbi->pm->data = fbi;
#endif
#ifdef CONFIG_CPU_FREQ #ifdef CONFIG_CPU_FREQ
fbi->freq_transition.notifier_call = sa1100fb_freq_transition; fbi->freq_transition.notifier_call = sa1100fb_freq_transition;
fbi->freq_policy.notifier_call = sa1100fb_freq_policy; fbi->freq_policy.notifier_call = sa1100fb_freq_policy;
...@@ -1846,17 +1822,14 @@ int __init sa1100fb_init(void) ...@@ -1846,17 +1822,14 @@ int __init sa1100fb_init(void)
cpufreq_register_notifier(&fbi->freq_policy, CPUFREQ_POLICY_NOTIFIER); cpufreq_register_notifier(&fbi->freq_policy, CPUFREQ_POLICY_NOTIFIER);
#endif #endif
/*
* Ok, now enable the LCD controller
*/
set_ctrlr_state(fbi, C_ENABLE);
/* This driver cannot be unloaded at the moment */ /* This driver cannot be unloaded at the moment */
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
return 0; return 0;
failed: failed:
sys_device_unregister(&sa1100fb_dev);
driver_unregister(&sa1100fb_driver);
if (fbi) if (fbi)
kfree(fbi); kfree(fbi);
release_mem_region(0xb0100000, 0x10000); release_mem_region(0xb0100000, 0x10000);
......
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