* - Add patch 681/1 and clean up stork definitions.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/cpufreq.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <asm/hardware.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/mach-types.h>
#include <asm/uaccess.h>
#include <asm/arch/assabet.h>
};
#endif
-#ifdef CONFIG_SA1100_BRUTUS
-static struct sa1100fb_mach_info brutus_info __initdata = {
- .pixclock = 0, .bpp = 8,
- .xres = 320, .yres = 240,
-
- .hsync_len = 3, .vsync_len = 1,
- .left_margin = 41, .upper_margin = 0,
- .right_margin = 101, .lower_margin = 0,
-
- .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-
- .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Pas,
- .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) |
- LCCR3_PixClkDiv(44),
-};
-#endif
-
#ifdef CONFIG_SA1100_COLLIE
static struct sa1100fb_mach_info collie_info __initdata = {
.pixclock = 171521, .bpp = 16,
};
#endif
-#ifdef CONFIG_SA1100_FREEBIRD
-#warning Please check this carefully
-static struct sa1100fb_mach_info freebird_info __initdata = {
- .pixclock = 171521, .bpp = 16,
- .xres = 240, .yres = 320,
-
- .hsync_len = 3, .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_Sngl | LCCR0_Pas,
- .lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsDiv(2),
-};
-
-static struct sa1100fb_rgb freebird_rgb_16 = {
- .red = { .offset = 8, .length = 4, },
- .green = { .offset = 4, .length = 4, },
- .blue = { .offset = 0, .length = 4, },
- .transp = { .offset = 12, .length = 4, },
-};
-#endif
-
-#ifdef CONFIG_SA1100_GRAPHICSCLIENT
-static struct sa1100fb_mach_info graphicsclient_info __initdata = {
- .pixclock = 53500, .bpp = 8,
- .xres = 640, .yres = 480,
-
- .hsync_len = 9, .vsync_len = 9,
- .left_margin = 54, .upper_margin = 24,
- .right_margin = 54, .lower_margin = 32,
-
- .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
- .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
-};
-#endif
-
-#ifdef CONFIG_SA1100_HUW_WEBPANEL
-static struct sa1100fb_mach_info huw_webpanel_info __initdata = {
- .pixclock = 0, .bpp = 8,
- .xres = 640, .yres = 480,
-
- .hsync_len = 3, .vsync_len = 1,
- .left_margin = 41, .upper_margin = 0,
- .right_margin = 101, .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(2) | 8,
-#error FIXME
- /*
- * FIXME: please get rid of the '| 8' in preference to an
- * LCCR3_PixClkDiv() version. --rmk
- */
-};
-#endif
-
#ifdef LART_GREY_LCD
static struct sa1100fb_mach_info lart_grey_info __initdata = {
.pixclock = 150000, .bpp = 4,
.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,
- .xres = 480, .yres = 320,
-
- .hsync_len = 1, .vsync_len = 1,
- .left_margin = 10, .upper_margin = 0,
- .right_margin = 10, .lower_margin = 0,
-
- .cmap_greyscale = 1,
- .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-
- .lccr0 = LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_8PixMono,
- .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(255) |
- LCCR3_PixClkDiv(44),
-#error FIXME: fix pixclock, ACBsDiv
- /*
- * FIXME: I think ACBsDiv is wrong above - should it be 512 (disabled)?
- * - rmk
- */
-};
-#endif
-
-#ifdef CONFIG_SA1100_PANGOLIN
-static struct sa1100fb_mach_info pangolin_info __initdata = {
- .pixclock = 341521, .bpp = 16,
- .xres = 800, .yres = 600,
-
- .hsync_len = 64, .vsync_len = 7,
- .left_margin = 160, .upper_margin = 7,
- .right_margin = 24, .lower_margin = 1,
-
- .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-
- .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
- .lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsCntOff,
-};
-#endif
-
-#ifdef CONFIG_SA1100_STORK
-#if STORK_TFT /* ie the NEC TFT */
-/*
- * pixclock is ps per clock. say 72Hz, 800x600 clocks => (1/72)/(800*600)
- * = 28935 and a bit
- * NB likely to be increased to ease bus timings wrt pcmcia interface
- */
-static struct sa1100fb_mach_info stork_tft_info __initdata = {
- .pixclock = 28935, .bpp = 16,
- .xres = 640, .yres = 480,
-
- .hsync_len = 64, .vsync_len = 2,
- .left_margin = 48, .upper_margin = 12,
- .right_margin = 48, .lower_margin = 31,
-
- .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
- .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsCntOff,
-};
-
-static struct sa1100fb_rgb stork_tft_rgb_16 = {
- .red = { .offset = 11, .length = 5, },
- .green = { .offset = 5, .length = 6, },
- .blue = { .offset = 0, .length = 5, },
- .transp = { .offset = 0, .length = 0, },
-};
-
-#else /* Kyocera DSTN */
-
-static struct sa1100fb_mach_info stork_dstn_info __initdata = {
- .pixclock = 0, .bpp = 16,
- .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,
-#error Fixme
- .lccr3 = 0xff00 |
- 0x18 /* ought to be 0x14 but DMA isn't up to that as yet */
-};
-
-static struct sa1100fb_rgb stork_dstn_rgb_16 = {
- .red = { .offset = 8, .length = 4, },
- .green = { .offset = 4, .length = 4, },
- .blue = { .offset = 0, .length = 4, },
- .transp = { .offset = 0, .length = 0, },
-};
-#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),
-};
-#endif
-
-#ifdef CONFIG_SA1100_XP860
-static struct sa1100fb_mach_info xp860_info __initdata = {
- .pixclock = 0, .bpp = 8,
- .xres = 1024, .yres = 768,
-
- .hsync_len = 3, .vsync_len = 3,
- .left_margin = 3, .upper_margin = 2,
- .right_margin = 2, .lower_margin = 1,
-
- .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
- .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_PixClkDiv(6),
+ .lccr3 = LCCR3_ACBsDiv(512),
};
#endif
inf = &h3800_info;
}
#endif
-#ifdef CONFIG_SA1100_BRUTUS
- if (machine_is_brutus()) {
- inf = &brutus_info;
- }
-#endif
#ifdef CONFIG_SA1100_COLLIE
if (machine_is_collie()) {
inf = &collie_info;
}
#endif
-#ifdef CONFIG_SA1100_FREEBIRD
- if (machine_is_freebird()) {
- inf = &freebird_info;
- fbi->rgb[RGB_16] = &freebird_rgb16;
- }
-#endif
-#ifdef CONFIG_SA1100_GRAPHICSCLIENT
- if (machine_is_graphicsclient()) {
- inf = &graphicsclient_info;
- }
-#endif
-#ifdef CONFIG_SA1100_HUW_WEBPANEL
- if (machine_is_huw_webpanel()) {
- inf = &huw_webpanel_info;
- }
-#endif
#ifdef CONFIG_SA1100_LART
if (machine_is_lart()) {
#ifdef LART_GREY_LCD
#endif
}
#endif
-#ifdef CONFIG_SA1100_OMNIMETER
- if (machine_is_omnimeter()) {
- inf = &omnimeter_info;
- }
-#endif
-#ifdef CONFIG_SA1100_PANGOLIN
- if (machine_is_pangolin()) {
- inf = &pangolin_info;
- }
-#endif
-#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
- if (machine_is_stork()) {
-#if STORK_TFT
- inf = &stork_tft_info;
- fbi->rgb[RGB_16] = &stork_tft_rgb_16;
-#else
- inf = &stork_dstn_info;
- fbi->rgb[RGB_16] = &stork_dstn_rgb_16;
-#endif
- }
-#endif
-#ifdef CONFIG_SA1100_XP860
- if (machine_is_xp860()) {
- inf = &xp860_info;
- }
#endif
return inf;
}
return ret;
}
+#ifdef CONFIG_CPU_FREQ
/*
* sa1100fb_display_dma_period()
* Calculate the minimum period (in picoseconds) between two DMA
* requests for the LCD controller. If we hit this, it means we're
* doing nothing but LCD DMA.
*/
-static unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var)
+static inline unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var)
{
/*
* Period = pixclock * bits_per_byte * bytes_per_transfer
*/
return var->pixclock * 8 * 16 / var->bits_per_pixel;
}
+#endif
/*
* sa1100fb_check_var():
* Set (any) board control register to handle new color depth
*/
sa1100fb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR);
-
-#ifdef CONFIG_SA1100_OMNIMETER
-#error Do we have to do this here? We already do it at init time.
- if (machine_is_omnimeter())
- SetLCDContrast(DefaultLCDContrast);
-#endif
-
sa1100fb_activate_var(var, fbi);
return 0;
DPRINTK("sa1100fb_blank: blank=%d\n", blank);
switch (blank) {
- case VESA_POWERDOWN:
- case VESA_VSYNC_SUSPEND:
- case VESA_HSYNC_SUSPEND:
+ case FB_BLANK_POWERDOWN:
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_NORMAL:
if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
for (i = 0; i < fbi->palette_size; i++)
sa1100fb_schedule_work(fbi, C_DISABLE);
break;
- case VESA_NO_BLANKING:
+ case FB_BLANK_UNBLANK:
if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
- fb_set_cmap(&fbi->fb.cmap, 1, info);
+ fb_set_cmap(&fbi->fb.cmap, info);
sa1100fb_schedule_work(fbi, C_ENABLE);
}
return 0;
}
+static int sa1100fb_mmap(struct fb_info *info,
+ struct vm_area_struct *vma)
+{
+ struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+ unsigned long start, len, off = vma->vm_pgoff << PAGE_SHIFT;
+
+ if (off < info->fix.smem_len) {
+ vma->vm_pgoff += 1; /* skip over the palette */
+ return dma_mmap_writecombine(fbi->dev, vma, fbi->map_cpu,
+ fbi->map_dma, fbi->map_size);
+ }
+
+ start = info->fix.mmio_start;
+ len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
+
+ if ((vma->vm_end - vma->vm_start + off) > len)
+ return -EINVAL;
+
+ off += start & PAGE_MASK;
+ vma->vm_pgoff = off >> PAGE_SHIFT;
+ vma->vm_flags |= VM_IO;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+}
+
static struct fb_ops sa1100fb_ops = {
.owner = THIS_MODULE,
.fb_check_var = sa1100fb_check_var,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_blank = sa1100fb_blank,
- .fb_cursor = soft_cursor,
+ .fb_mmap = sa1100fb_mmap,
};
/*
DBAR2 = fbi->dbar2;
LCCR0 |= LCCR0_LEN;
-#ifdef CONFIG_SA1100_GRAPHICSCLIENT
-#error Where is GPIO24 set as an output? Can we fit this in somewhere else?
- if (machine_is_graphicsclient()) {
- // From ADS doc again...same as disable
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(20 * HZ / 1000);
- GPSR |= GPIO_GPIO24;
- }
-#endif
-
if (machine_is_shannon()) {
GPDR |= SHANNON_GPIO_DISP_EN;
GPSR |= SHANNON_GPIO_DISP_EN;
- }
+ }
DPRINTK("DBAR1 = 0x%08x\n", DBAR1);
DPRINTK("DBAR2 = 0x%08x\n", DBAR2);
DPRINTK("Disabling LCD controller\n");
-#ifdef CONFIG_SA1100_GRAPHICSCLIENT
-#error Where is GPIO24 set as an output? Can we fit this in somewhere else?
- if (machine_is_graphicsclient()) {
- /*
- * From ADS internal document:
- * GPIO24 should be LOW at least 10msec prior to disabling
- * the LCD interface.
- *
- * We'll wait 20msec.
- */
- GPCR |= GPIO_GPIO24;
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(20 * HZ / 1000);
- }
-#endif
-#ifdef CONFIG_SA1100_HUW_WEBPANEL
-#error Move me into __sa1100fb_lcd_power and/or __sa1100fb_backlight_power
- if (machine_is_huw_webpanel()) {
- // don't forget to set the control lines to zero (?)
- DPRINTK("ShutDown HuW LCD controller\n");
- BCR_clear(BCR_TFT_ENA + BCR_CCFL_POW + BCR_PWM_BACKLIGHT);
- }
-#endif
-
if (machine_is_shannon()) {
GPCR |= SHANNON_GPIO_DISP_EN;
}
- add_wait_queue(&fbi->ctrlr_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE);
+ add_wait_queue(&fbi->ctrlr_wait, &wait);
LCSR = 0xffffffff; /* Clear LCD Status Register */
LCCR0 &= ~LCCR0_LDM; /* Enable LCD Disable Done Interrupt */
/*
* sa1100fb_handle_irq: Handle 'LCD DONE' interrupts.
*/
-static irqreturn_t sa1100fb_handle_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sa1100fb_handle_irq(int irq, void *dev_id)
{
struct sa1100fb_info *fbi = dev_id;
unsigned int lcsr = LCSR;
* Our LCD controller task (which is called when we blank or unblank)
* via keventd.
*/
-static void sa1100fb_task(void *dummy)
+static void sa1100fb_task(struct work_struct *w)
{
- struct sa1100fb_info *fbi = dummy;
+ struct sa1100fb_info *fbi = container_of(w, struct sa1100fb_info, task);
u_int state = xchg(&fbi->task_state, -1);
set_ctrlr_state(fbi, state);
* Power management hooks. Note that we won't be called from IRQ context,
* unlike the blank functions above, so we may sleep.
*/
-static int sa1100fb_suspend(struct device *dev, u32 state, u32 level)
+static int sa1100fb_suspend(struct platform_device *dev, pm_message_t state)
{
- struct sa1100fb_info *fbi = dev_get_drvdata(dev);
+ struct sa1100fb_info *fbi = platform_get_drvdata(dev);
- if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN)
- set_ctrlr_state(fbi, C_DISABLE_PM);
+ set_ctrlr_state(fbi, C_DISABLE_PM);
return 0;
}
-static int sa1100fb_resume(struct device *dev, u32 level)
+static int sa1100fb_resume(struct platform_device *dev)
{
- struct sa1100fb_info *fbi = dev_get_drvdata(dev);
+ struct sa1100fb_info *fbi = platform_get_drvdata(dev);
- if (level == RESUME_ENABLE)
- set_ctrlr_state(fbi, C_ENABLE_PM);
+ set_ctrlr_state(fbi, C_ENABLE_PM);
return 0;
}
#else
fbi->fb.var.vmode = FB_VMODE_NONINTERLACED;
fbi->fb.fbops = &sa1100fb_ops;
- fbi->fb.flags = FBINFO_FLAG_DEFAULT;
+ fbi->fb.flags = FBINFO_DEFAULT;
fbi->fb.monspecs = monspecs;
- fbi->fb.currcon = -1;
fbi->fb.pseudo_palette = (fbi + 1);
fbi->rgb[RGB_8] = &rgb_8;
fbi->max_bpp / 8;
init_waitqueue_head(&fbi->ctrlr_wait);
- INIT_WORK(&fbi->task, sa1100fb_task, fbi);
+ INIT_WORK(&fbi->task, sa1100fb_task);
init_MUTEX(&fbi->ctrlr_sem);
return fbi;
}
-static int __init sa1100fb_probe(struct device *dev)
+static int __init sa1100fb_probe(struct platform_device *pdev)
{
struct sa1100fb_info *fbi;
- int ret;
+ int ret, irq;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return -EINVAL;
if (!request_mem_region(0xb0100000, 0x10000, "LCD"))
return -EBUSY;
- fbi = sa1100fb_init_fbinfo(dev);
+ fbi = sa1100fb_init_fbinfo(&pdev->dev);
ret = -ENOMEM;
if (!fbi)
goto failed;
if (ret)
goto failed;
- ret = request_irq(IRQ_LCD, sa1100fb_handle_irq, SA_INTERRUPT,
+ ret = request_irq(irq, sa1100fb_handle_irq, IRQF_DISABLED,
"LCD", fbi);
if (ret) {
printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret);
ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
#endif
-#ifdef CONFIG_SA1100_FREEBIRD
-#error Please move this into __sa1100fb_lcd_power
- if (machine_is_freebird()) {
- BCR_set(BCR_FREEBIRD_LCD_DISP);
- mdelay(20);
- BCR_set(BCR_FREEBIRD_LCD_PWR);
- mdelay(20);
- }
-#endif
-
/*
* This makes sure that our colour bitfield
* descriptors are correctly initialised.
*/
sa1100fb_check_var(&fbi->fb.var, &fbi->fb);
- dev_set_drvdata(dev, fbi);
+ platform_set_drvdata(pdev, fbi);
ret = register_framebuffer(&fbi->fb);
if (ret < 0)
- goto failed;
+ goto err_free_irq;
#ifdef CONFIG_CPU_FREQ
fbi->freq_transition.notifier_call = sa1100fb_freq_transition;
/* This driver cannot be unloaded at the moment */
return 0;
-failed:
- dev_set_drvdata(dev, NULL);
- if (fbi)
- kfree(fbi);
+ err_free_irq:
+ free_irq(irq, fbi);
+ failed:
+ platform_set_drvdata(pdev, NULL);
+ kfree(fbi);
release_mem_region(0xb0100000, 0x10000);
return ret;
}
-static struct device_driver sa1100fb_driver = {
- .name = "sa11x0-fb",
- .bus = &platform_bus_type,
+static struct platform_driver sa1100fb_driver = {
.probe = sa1100fb_probe,
.suspend = sa1100fb_suspend,
.resume = sa1100fb_resume,
+ .driver = {
+ .name = "sa11x0-fb",
+ },
};
int __init sa1100fb_init(void)
{
- return driver_register(&sa1100fb_driver);
+ if (fb_get_options("sa1100fb", NULL))
+ return -ENODEV;
+
+ return platform_driver_register(&sa1100fb_driver);
}
int __init sa1100fb_setup(char *options)
return 0;
}
+module_init(sa1100fb_init);
MODULE_DESCRIPTION("StrongARM-1100/1110 framebuffer driver");
MODULE_LICENSE("GPL");