---
 drivers/video/Kconfig           |   22 +
 drivers/video/Makefile          |    1 
 drivers/video/fbmem.c           |    6 
 drivers/video/sidsafb.c         |  805 ++++++++++++++++++++++++++++++++++++++++
 include/asm-avr32/periph/lcdc.h |  271 +++++++++++++
 include/linux/fb.h              |    3 
 6 files changed, 1107 insertions(+), 1 deletion(-)

Index: linux-2.6.18-avr32/drivers/video/Kconfig
===================================================================
--- linux-2.6.18-avr32.orig/drivers/video/Kconfig	2006-11-02 15:54:18.000000000 +0100
+++ linux-2.6.18-avr32/drivers/video/Kconfig	2006-11-02 15:56:20.000000000 +0100
@@ -271,6 +271,28 @@ config FB_SA1100
 	  If you plan to use the LCD display with your SA-1100 system, say
 	  Y here.
 
+config FB_SIDSA
+	tristate "SIDSA LCDC support"
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	depends on FB && AVR32
+	help
+	  This enables support for the SIDSA LCD Controller.
+
+config FB_SIDSA_DEFAULT_BPP
+	int "SIDSA LCDC default color depth"
+	default 24
+	depends on FB_SIDSA
+	help
+	  Specify the maximum color depth you want to be able to
+	  support. This, together with the resolution of the LCD
+	  panel, determines the amount of framebuffer memory allocated
+	  when the driver is initialized.
+
+	  Allowable values are 1, 2, 4, 8, 16, 24 and 32. If unsure,
+	  say 24.
+
 config FB_IMX
 	tristate "Motorola i.MX LCD support"
 	depends on FB && ARM && ARCH_IMX
Index: linux-2.6.18-avr32/drivers/video/Makefile
===================================================================
--- linux-2.6.18-avr32.orig/drivers/video/Makefile	2006-11-02 15:54:18.000000000 +0100
+++ linux-2.6.18-avr32/drivers/video/Makefile	2006-11-02 15:56:20.000000000 +0100
@@ -75,6 +75,7 @@ obj-$(CONFIG_FB_HP300)            += hpf
 obj-$(CONFIG_FB_G364)             += g364fb.o
 obj-$(CONFIG_FB_SA1100)           += sa1100fb.o
 obj-$(CONFIG_FB_SUN3)             += sun3fb.o
+obj-$(CONFIG_FB_SIDSA)		  += sidsafb.o
 obj-$(CONFIG_FB_HIT)              += hitfb.o
 obj-$(CONFIG_FB_EPSON1355)	  += epson1355fb.o
 obj-$(CONFIG_FB_PVR2)             += pvr2fb.o
Index: linux-2.6.18-avr32/drivers/video/fbmem.c
===================================================================
--- linux-2.6.18-avr32.orig/drivers/video/fbmem.c	2006-11-02 15:54:18.000000000 +0100
+++ linux-2.6.18-avr32/drivers/video/fbmem.c	2006-11-02 15:56:20.000000000 +0100
@@ -1153,6 +1153,7 @@ fb_mmap(struct file *file, struct vm_are
 	/* frame buffer memory */
 	start = info->fix.smem_start;
 	len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
+	pr_debug("fb_mmap: start = 0x%08lx, len = 0x%08lx\n", start, len);
 	if (off >= len) {
 		/* memory mapped io */
 		off -= len;
@@ -1168,6 +1169,7 @@ fb_mmap(struct file *file, struct vm_are
 	if ((vma->vm_end - vma->vm_start + off) > len)
 		return -EINVAL;
 	off += start;
+	pr_debug("fb_mmap: off = 0x%08lx\n", off);
 	vma->vm_pgoff = off >> PAGE_SHIFT;
 	/* This is an IO map - tell maydump to skip this VMA */
 	vma->vm_flags |= VM_IO | VM_RESERVED;
@@ -1198,6 +1200,10 @@ fb_mmap(struct file *file, struct vm_are
 	pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
 #elif defined(__arm__) || defined(__sh__) || defined(__m32r__)
 	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+#elif defined(__avr32__)
+	vma->vm_page_prot = __pgprot((pgprot_val(vma->vm_page_prot)
+				      & ~_PAGE_CACHABLE)
+				     | (_PAGE_BUFFER | _PAGE_DIRTY));
 #elif defined(__ia64__)
 	if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
 		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
Index: linux-2.6.18-avr32/drivers/video/sidsafb.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.18-avr32/drivers/video/sidsafb.c	2006-11-02 16:07:55.000000000 +0100
@@ -0,0 +1,805 @@
+/*
+ * Framebuffer Driver for Atmel/SIDSA LCD Controller
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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.
+ */
+#undef DEBUG
+
+#include <linux/config.h>
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+
+#include <asm/arch/board.h>
+
+#include <asm/periph/lcdc.h>
+
+/* More or less configurable parameters */
+#define SIDSAFB_FIFO_SIZE		512
+#define SIDSAFB_DMA_BURST_LEN		8
+
+/* TODO: These should be autogenerated from part description file */
+#define LCDC_DISTYPE_STN_MONO		0
+#define LCDC_DISTYPE_STN_COLOR		1
+#define LCDC_DISTYPE_TFT		2
+#define LCDC_LUT			0xc00
+
+struct sidsafb_info {
+	spinlock_t		lock;
+	struct fb_info *	info;
+	void __iomem *		regs;
+	unsigned long		irq_base;
+	wait_queue_head_t	vsync_wait;
+	unsigned int		guard_time;
+	struct clk		*hclk;
+	struct clk		*pixclk;
+	struct platform_device	*pdev;
+	u32			pseudo_palette[16];
+};
+
+/*
+ * How large framebuffer to allocate if none was provided by the
+ * platform. This default is the smallest we can possibly get away
+ * with.
+ */
+static unsigned long fb_size = (320 * 240);
+
+#if 0
+static struct fb_videomode sony_modes[] = {
+	{
+		.refresh	= 48,
+		.xres		= 240,		.yres		= 160,
+		.pixclock	= 520833,
+
+		.left_margin	= 7,		.right_margin	= 9,
+		.upper_margin	= 19,		.lower_margin	= 20,
+		.hsync_len	= 9,		.vsync_len	= 2,
+
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+};
+#endif
+
+#if 0
+static struct fb_videomode vga_modes[] = {
+	{
+		.refresh	= 122,
+		.xres		= 320,		.yres		= 240,
+		.pixclock	= 80000,
+
+		.left_margin	= 10,		.right_margin	= 20,
+		.upper_margin	= 30,		.lower_margin	= 5,
+		.hsync_len	= 20,		.vsync_len	= 3,
+
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	{
+		.refresh	= 70,
+		.xres		= 640,		.yres		= 480,
+		.pixclock	= 40000,
+
+		.left_margin	= 10,		.right_margin	= 20,
+		.upper_margin	= 30,		.lower_margin	= 5,
+		.hsync_len	= 20,		.vsync_len	= 3,
+
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+};
+#else
+static struct fb_videomode samsung_modes[] = {
+	{
+		.refresh	= 75,
+		.xres		= 320,		.yres		= 240,
+		.pixclock	= 145111,
+
+		.left_margin	= 17,		.right_margin	= 33,
+		.upper_margin	= 8,		.lower_margin	= 10,
+		.hsync_len	= 16,		.vsync_len	= 1,
+
+		.sync		= FB_SYNC_PCLK_RISING,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+};
+#endif
+
+#if 1
+static struct fb_monspecs default_monspecs = {
+	.modedb		= samsung_modes,
+	.manufacturer	= "SNG",
+	.monitor	= "LCD panel",
+	.serial_no	= "xxxx",
+	.ascii		= "yyyy",
+	.modedb_len	= ARRAY_SIZE(samsung_modes),
+	.hfmin		= 14820,
+	.hfmax		= 22230,
+	.vfmin		= 60,
+	.vfmax		= 90,
+	.dclkmax	= 30000000,
+};
+#endif
+
+#if 0
+static struct fb_monspecs default_monspecs = {
+	.modedb		= sony_modes,
+	.manufacturer	= "SNY",	/* 4 chars?!? */
+	.monitor	= "LCD panel",
+	.serial_no	= "xxxx",
+	.ascii		= "yyyy",
+	.modedb_len	= ARRAY_SIZE(sony_modes),
+	.hfmin		= 7000,
+	.hfmax		= 8000,
+	.vfmin		= 45,
+	.vfmax		= 50,
+};
+// #else
+static struct fb_monspecs default_monspecs = {
+	.modedb		= vga_modes,
+	.manufacturer	= "VGA",
+	.monitor	= "Generic VGA",
+	.serial_no	= "xxxx",
+	.ascii		= "yyyy",
+	.modedb_len	= ARRAY_SIZE(vga_modes),
+	.hfmin		= 30000,
+	.hfmax		= 64000,
+	.vfmin		= 50,
+	.vfmax		= 150,
+};
+#endif
+
+/* Driver defaults */
+static struct fb_fix_screeninfo sidsafb_fix __devinitdata = {
+	.id		= "sidsafb",
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_TRUECOLOR,
+	.xpanstep	= 1,
+	.ypanstep	= 1,
+	.ywrapstep	= 0,
+	.accel		= FB_ACCEL_NONE,
+};
+
+static void sidsafb_update_dma(struct fb_info *info,
+			       struct fb_var_screeninfo *var)
+{
+	struct sidsafb_info *sinfo = info->par;
+	struct fb_fix_screeninfo *fix = &info->fix;
+	unsigned long dma_addr;
+	unsigned long pixeloff;
+	unsigned long dma2dcfg;
+
+	dma_addr = (fix->smem_start + var->yoffset * fix->line_length
+		    + var->xoffset * var->bits_per_pixel / 8);
+
+	dma_addr &= ~3UL;
+	pixeloff = LCDC_MKBF(DMA2DCFG_PIXELOFF, var->xoffset * var->bits_per_pixel);
+
+	/* Set framebuffer DMA base address and pixel offset */
+	lcdc_writel(sinfo, DMABADDR1, dma_addr);
+	dma2dcfg = lcdc_readl(sinfo, DMA2DCFG);
+	dma2dcfg = LCDC_INSBF(DMA2DCFG_PIXELOFF, pixeloff, dma2dcfg);
+	lcdc_writel(sinfo, DMA2DCFG, dma2dcfg);
+
+	/* Update configuration */
+	lcdc_writel(sinfo, DMACON, (lcdc_readl(sinfo, DMACON)
+				    | LCDC_BIT(DMACON_DMAUPDT)));
+}
+
+/**
+ *      sidsafb_check_var - Validates a var passed in.
+ *      @var: frame buffer variable screen structure
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *	Checks to see if the hardware supports the state requested by
+ *	var passed in. This function does not alter the hardware
+ *	state!!!  This means the data stored in struct fb_info and
+ *	struct sidsafb_info do not change. This includes the var
+ *	inside of struct fb_info.  Do NOT change these. This function
+ *	can be called on its own if we intent to only test a mode and
+ *	not actually set it. The stuff in modedb.c is a example of
+ *	this. If the var passed in is slightly off by what the
+ *	hardware can support then we alter the var PASSED in to what
+ *	we can do. If the hardware doesn't support mode change a
+ *	-EINVAL will be returned by the upper layers. You don't need
+ *	to implement this function then. If you hardware doesn't
+ *	support changing the resolution then this function is not
+ *	needed. In this case the driver would just provide a var that
+ *	represents the static state the screen is in.
+ *
+ *	Returns negative errno on error, or zero on success.
+ */
+static int sidsafb_check_var(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	unsigned long new_fb_size;
+
+	pr_debug("sidsafb_check_var:\n");
+	pr_debug("  resolution: %ux%u\n", var->xres, var->yres);
+	pr_debug("  pixclk:     %llu Hz\n", 1000000000000ULL / var->pixclock);
+	pr_debug("  bpp:        %u\n", var->bits_per_pixel);
+
+	new_fb_size = (var->xres_virtual * var->yres_virtual
+		       * ((var->bits_per_pixel + 7) / 8));
+	if (new_fb_size > info->fix.smem_len) {
+		printk(KERN_NOTICE
+		       "sidsafb: %uB framebuffer too small for %ux%ux%u\n",
+		       info->fix.smem_len, var->xres_virtual,
+		       var->yres_virtual, var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	/* Force same alignment for each line */
+	var->xres = (var->xres + 3) & ~3UL;
+	var->xres_virtual = (var->xres_virtual + 3) & ~3UL;
+
+	var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0;
+	var->transp.offset = var->transp.length = 0;
+
+	switch (var->bits_per_pixel) {
+	case 2:
+	case 4:
+	case 8:
+		var->red.offset = var->green.offset = var->blue.offset = 0;
+		var->red.length = var->green.length = var->blue.length
+			= var->bits_per_pixel;
+		break;
+	case 15:
+	case 16:
+		/*
+		 * Bit 16 is the "intensity" bit, I think. Not sure
+		 * what we're going to use that for...
+		 */
+		var->red.offset = 0;
+		var->green.offset = 5;
+		var->blue.offset = 10;
+		var->red.length = 5;
+		var->green.length = 5;
+		var->blue.length = 5;
+		break;
+	case 24:
+	case 32:
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+		var->red.length = var->green.length = var->blue.length = 8;
+		break;
+	default:
+		printk(KERN_NOTICE "sidsafb: color depth %d not supported\n",
+		       var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	var->xoffset = var->yoffset = 0;
+	var->red.msb_right = var->green.msb_right = var->blue.msb_right =
+		var->transp.msb_right = 0;
+
+	return 0;
+}
+
+/**
+ *      sidsafb_set_par - Alters the hardware state.
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *	Using the fb_var_screeninfo in fb_info we set the resolution
+ *	of the this particular framebuffer. This function alters the
+ *	par AND the fb_fix_screeninfo stored in fb_info. It doesn't
+ *	not alter var in fb_info since we are using that data. This
+ *	means we depend on the data in var inside fb_info to be
+ *	supported by the hardware.  sidsafb_check_var is always called
+ *	before sidsafb_set_par to ensure this.  Again if you can't
+ *	change the resolution you don't need this function.
+ *
+ */
+static int sidsafb_set_par(struct fb_info *info)
+{
+	struct sidsafb_info *sinfo = info->par;
+	unsigned long value;
+
+	pr_debug("sidsafb_set_par:\n");
+	pr_debug("  * resolution: %ux%u (%ux%u virtual)\n",
+		 info->var.xres, info->var.yres,
+		 info->var.xres_virtual, info->var.yres_virtual);
+
+	/* Turn off the LCD controller and the DMA controller */
+	pr_debug("writing 0x%08x to %p\n",
+		 LCDC_MKBF(PWRCON_GUARD_TIME, sinfo->guard_time),
+		 sinfo->regs + LCDC_PWRCON);
+	lcdc_writel(sinfo, PWRCON,
+		    LCDC_MKBF(PWRCON_GUARD_TIME, sinfo->guard_time));
+	pr_debug("writing 0 to %p\n", sinfo->regs + LCDC_DMACON);
+	lcdc_writel(sinfo, DMACON, 0);
+
+	info->fix.line_length = (info->var.xres_virtual
+				 * (info->var.bits_per_pixel / 8));
+
+	if (info->var.bits_per_pixel <= 8)
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	else
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+	/* Re-initialize the DMA engine... */
+	pr_debug("  * update DMA engine\n");
+	sidsafb_update_dma(info, &info->var);
+
+	/* ...set frame size and burst length = 8 words (?) */
+	value = LCDC_MKBF(DMAFRMCFG_FRMSIZE,
+			  (info->var.yres * info->fix.line_length + 3) / 4);
+	value |= LCDC_MKBF(DMAFRMCFG_BRSTLEN, (SIDSAFB_DMA_BURST_LEN - 1));
+	lcdc_writel(sinfo, DMAFRMCFG, value);
+
+	/* ...set 2D configuration (necessary for xres_virtual != xres) */
+	value = LCDC_MKBF(DMA2DCFG_ADDRINC,
+			  info->var.xres_virtual - info->var.xres);
+	lcdc_writel(sinfo, DMA2DCFG, value);
+
+	/* ...wait for DMA engine to become idle... */
+	while (lcdc_readl(sinfo, DMACON) & LCDC_BIT(DMACON_DMABUSY))
+		msleep(10);
+
+	pr_debug("  * re-enable DMA engine\n");
+	/* ...and enable it with updated configuration */
+	lcdc_writel(sinfo, DMACON, (LCDC_BIT(DMACON_DMAEN)
+				    | LCDC_BIT(DMACON_DMAUPDT)
+				    | LCDC_BIT(DMACON_DMA2DEN)));
+
+	/* Now, the LCD core... */
+
+	/* Set pixel clock. */
+	value = (clk_get_rate(sinfo->pixclk) / 100000) * info->var.pixclock;
+	value /= 10000000;
+	value = (value + 1) / 2;
+	if (value == 0) {
+		printk("sidsafb: Bypassing lcdc_pclk divider\n");
+		lcdc_writel(sinfo, LCDCON1, LCDC_BIT(LCDCON1_BYPASS));
+	} else {
+		lcdc_writel(sinfo, LCDCON1, LCDC_MKBF(LCDCON1_CLKVAL, value - 1));
+	}
+
+	/* Initialize control register 2 */
+	value = (LCDC_BIT(LCDCON2_CLKMOD)
+		 | LCDC_MKBF(LCDCON2_DISTYPE, LCDC_DISTYPE_TFT));
+	if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
+		value |= LCDC_BIT(LCDCON2_INVLINE);
+	if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
+		value |= LCDC_BIT(LCDCON2_INVFRAME);
+	if (info->var.sync & FB_SYNC_PCLK_RISING)
+		value |= LCDC_BIT(LCDCON2_INVCLK);
+
+	switch (info->var.bits_per_pixel) {
+	case 1:	value |= LCDC_MKBF(LCDCON2_PIXELSIZE, 0); break;
+	case 2: value |= LCDC_MKBF(LCDCON2_PIXELSIZE, 1); break;
+	case 4: value |= LCDC_MKBF(LCDCON2_PIXELSIZE, 2); break;
+	case 8: value |= LCDC_MKBF(LCDCON2_PIXELSIZE, 3); break;
+	case 15: /* fall through */
+	case 16: value |= LCDC_MKBF(LCDCON2_PIXELSIZE, 4); break;
+	case 24: value |= LCDC_MKBF(LCDCON2_PIXELSIZE, 5); break;
+	case 32: value |= LCDC_MKBF(LCDCON2_PIXELSIZE, 6); break;
+	default: BUG(); break;
+	}
+	pr_debug("  * LCDCON2 = %08lx\n", value);
+	lcdc_writel(sinfo, LCDCON2, value);
+
+	/* Vertical timing */
+	value = LCDC_MKBF(LCDTIM1_VPW, info->var.vsync_len - 1);
+	value |= LCDC_MKBF(LCDTIM1_VBP, info->var.upper_margin);
+	value |= LCDC_MKBF(LCDTIM1_VFP, info->var.lower_margin);
+	pr_debug("  * LCDTIM1 = %08lx\n", value);
+	lcdc_writel(sinfo, LCDTIM1, value);
+
+	/* Horizontal timing */
+	value = LCDC_MKBF(LCDTIM2_HFP, info->var.right_margin - 1);
+	value |= LCDC_MKBF(LCDTIM2_HPW, info->var.hsync_len - 1);
+	value |= LCDC_MKBF(LCDTIM2_HBP, info->var.left_margin - 1);
+	pr_debug("  * LCDTIM2 = %08lx\n", value);
+	lcdc_writel(sinfo, LCDTIM2, value);
+
+	/* Display size */
+	value = LCDC_MKBF(LCDFRMCFG_LINESIZE, info->var.xres - 1);
+	value |= LCDC_MKBF(LCDFRMCFG_LINEVAL, info->var.yres - 1);
+	lcdc_writel(sinfo, LCDFRMCFG, value);
+
+	/* FIFO Threshold: Use formula from data sheet */
+	value = SIDSAFB_FIFO_SIZE - (2 * SIDSAFB_DMA_BURST_LEN + 3);
+	lcdc_writel(sinfo, LCDFIFO, value);
+
+	/* Toggle LCD_MODE every frame */
+	lcdc_writel(sinfo, LCDMVAL, 0);
+
+	/* Disable all interrupts */
+	lcdc_writel(sinfo, LCD_IDR, ~0UL);
+
+	/* Wait for the LCDC core to become idle and enable it */
+	while(lcdc_readl(sinfo, PWRCON) & LCDC_BIT(PWRCON_LCD_BUSY))
+		msleep(10);
+
+	pr_debug("  * re-enable LCD core\n");
+	lcdc_writel(sinfo, PWRCON,
+		    LCDC_MKBF(PWRCON_GUARD_TIME, sinfo->guard_time)
+		    | LCDC_BIT(PWRCON_LCD_PWR));
+
+	pr_debug("  * DONE\n");
+	return 0;
+}
+
+static inline u_int chan_to_field(u_int chan, const struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+/**
+ *  	sidsafb_setcolreg - Optional function. Sets a color register.
+ *      @regno: Which register in the CLUT we are programming
+ *      @red: The red value which can be up to 16 bits wide
+ *	@green: The green value which can be up to 16 bits wide
+ *	@blue:  The blue value which can be up to 16 bits wide.
+ *	@transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ *
+ *  	Set a single color register. The values supplied have a 16 bit
+ *  	magnitude which needs to be scaled in this function for the hardware.
+ *	Things to take into consideration are how many color registers, if
+ *	any, are supported with the current color visual. With truecolor mode
+ *	no color palettes are supported. Here a psuedo palette is created
+ *	which we store the value in pseudo_palette in struct fb_info. For
+ *	pseudocolor mode we have a limited color palette. To deal with this
+ *	we can program what color is displayed for a particular pixel value.
+ *	DirectColor is similar in that we can program each color field. If
+ *	we have a static colormap we don't need to implement this function.
+ *
+ *	Returns negative errno on error, or zero on success. In an
+ *	ideal world, this would have been the case, but as it turns
+ *	out, the other drivers return 1 on failure, so that's what
+ *	we're going to do.
+ */
+static int sidsafb_setcolreg(unsigned int regno, unsigned int red,
+			     unsigned int green, unsigned int blue,
+			     unsigned int transp, struct fb_info *info)
+{
+	struct sidsafb_info *sinfo = info->par;
+	unsigned int val;
+	u32 *pal;
+	int ret = 1;
+
+	if (info->var.grayscale)
+		red = green = blue = (19595 * red + 38470 * green
+				      + 7471 * blue) >> 16;
+
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		if (regno < 16) {
+			pal = info->pseudo_palette;
+
+			val  = chan_to_field(red, &info->var.red);
+			val |= chan_to_field(green, &info->var.green);
+			val |= chan_to_field(blue, &info->var.blue);
+
+			pal[regno] = val;
+			ret = 0;
+		}
+		break;
+
+	case FB_VISUAL_PSEUDOCOLOR:
+		if (regno < 256) {
+			val  = ((red   >> 11) & 0x001f);
+			val |= ((green >>  6) & 0x03e0);
+			val |= ((blue  >>  1) & 0x7c00);
+
+			/*
+			 * TODO: intensity bit. Maybe something like
+			 *   ~(red[10] ^ green[10] ^ blue[10]) & 1
+			 */
+
+			lcdc_writel(sinfo, LUT + regno * 4, val);
+			ret = 0;
+		}
+		break;
+	}
+
+	return ret;
+}
+
+static int sidsafb_pan_display(struct fb_var_screeninfo *var,
+			       struct fb_info *info)
+{
+	pr_debug("sidsafb_pan_display\n");
+
+	sidsafb_update_dma(info, var);
+
+	return 0;
+}
+
+static struct fb_ops sidsafb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= sidsafb_check_var,
+	.fb_set_par	= sidsafb_set_par,
+	.fb_setcolreg	= sidsafb_setcolreg,
+	.fb_pan_display	= sidsafb_pan_display,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static irqreturn_t sidsafb_interrupt(int irq, void *dev_id,
+				     struct pt_regs *regs)
+{
+	struct fb_info *info = dev_id;
+	struct sidsafb_info *sinfo = info->par;
+	u32 status;
+
+	status = lcdc_readl(sinfo, LCD_ISR);
+	while (status) {
+		if (status & LCDC_BIT(LCD_ISR_EOFIS)) {
+			pr_debug("sidsafb: DMA End Of Frame interrupt\n");
+
+			lcdc_writel(sinfo, LCD_ICR, LCDC_BIT(LCD_ICR_EOFIC));
+			status &= ~LCDC_BIT(LCD_ISR_EOFIS);
+			wake_up(&sinfo->vsync_wait);
+		}
+
+		if (status) {
+			printk(KERN_ERR
+			       "LCDC: Interrupts still pending: 0x%x\n",
+			       status);
+			lcdc_writel(sinfo, LCD_IDR, status);
+		}
+
+		status = lcdc_readl(sinfo, LCD_ISR);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void __devinit init_pseudo_palette(u32 *palette)
+{
+	static const u32 init_palette[16] = {
+		0x000000,
+		0xaa0000,
+		0x00aa00,
+		0xaa5500,
+		0x0000aa,
+		0xaa00aa,
+		0x00aaaa,
+		0xaaaaaa,
+		0x555555,
+		0xff5555,
+		0x55ff55,
+		0xffff55,
+		0x5555ff,
+		0xff55ff,
+		0x55ffff,
+		0xffffff
+	};
+
+	memcpy(palette, init_palette, sizeof(init_palette));
+}
+
+static int __devinit sidsafb_set_fbinfo(struct sidsafb_info *sinfo)
+{
+	struct fb_info *info = sinfo->info;
+
+	init_pseudo_palette(sinfo->pseudo_palette);
+
+	info->flags		= (FBINFO_DEFAULT
+				   | FBINFO_PARTIAL_PAN_OK
+				   | FBINFO_HWACCEL_XPAN
+				   | FBINFO_HWACCEL_YPAN);
+	memcpy(&info->fix, &sidsafb_fix, sizeof(info->fix));
+	memcpy(&info->monspecs, &default_monspecs, sizeof(info->monspecs));
+	info->fbops		= &sidsafb_ops;
+	info->pseudo_palette	= sinfo->pseudo_palette;
+
+	init_waitqueue_head(&sinfo->vsync_wait);
+
+	return 0;
+}
+
+static int __devinit sidsafb_probe(struct platform_device *pdev)
+{
+	struct lcdc_platform_data *fb_data = pdev->dev.platform_data;
+	struct fb_info *info;
+	struct sidsafb_info *sinfo;
+	const struct resource *mmio_resource;
+	int ret;
+
+	pr_debug("sidsafb_probe BEGIN\n");
+
+	mmio_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mmio_resource) {
+		dev_err(&pdev->dev, "no MMIO resource found\n");
+		return -ENXIO;
+	}
+
+	ret = -ENOMEM;
+	info = framebuffer_alloc(sizeof(struct sidsafb_info), &pdev->dev);
+	if (!info) {
+		dev_err(&pdev->dev, "failed to allocate memory\n");
+		goto out;
+	}
+
+	sinfo = info->par;
+	sinfo->info = info;
+	sinfo->pdev = pdev;
+	sinfo->guard_time = 1;
+
+	spin_lock_init(&sinfo->lock);
+	sidsafb_set_fbinfo(sinfo);
+	info->fix.mmio_start = mmio_resource->start;
+	info->fix.mmio_len = mmio_resource->end - mmio_resource->start + 1;
+	sinfo->irq_base = platform_get_irq(pdev, 0);
+
+	sinfo->hclk = clk_get(&pdev->dev, "hclk");
+	if (IS_ERR(sinfo->hclk)) {
+		dev_err(&pdev->dev, "failed to get hclk\n");
+		ret = PTR_ERR(sinfo->hclk);
+		goto free_info;
+	}
+	sinfo->pixclk = clk_get(&pdev->dev, "pixclk");
+	if (IS_ERR(sinfo->pixclk)) {
+		dev_err(&pdev->dev, "failed to get pixel clock\n");
+		ret = PTR_ERR(sinfo->hclk);
+		goto put_hclk;
+	}
+
+	clk_enable(sinfo->hclk);
+	clk_enable(sinfo->pixclk);
+
+	/* Use platform-supplied framebuffer memory if available */
+	if (fb_data && fb_data->fbmem_size != 0) {
+		info->fix.smem_start = fb_data->fbmem_start;
+		info->fix.smem_len = fb_data->fbmem_size;
+		info->screen_base = ioremap(info->fix.smem_start,
+					    info->fix.smem_len);
+	} else {
+		dma_addr_t paddr;
+
+		info->fix.smem_len = fb_size;
+		info->screen_base = dma_alloc_coherent(&pdev->dev, fb_size,
+						       &paddr, GFP_KERNEL);
+		info->fix.smem_start = paddr;
+	}
+
+	if (!info->screen_base) {
+		printk(KERN_ERR "sidsafb: Could not allocate framebuffer\n");
+		goto disable_clocks;
+	}
+
+	sinfo->regs = ioremap(info->fix.mmio_start, info->fix.mmio_len);
+	if (!sinfo->regs) {
+		printk(KERN_ERR "sidsafb: Could not map LCDC registers\n");
+		goto free_fb;
+	}
+
+	ret = fb_find_mode(&info->var, info, NULL, info->monspecs.modedb,
+			   info->monspecs.modedb_len, info->monspecs.modedb,
+			   CONFIG_FB_SIDSA_DEFAULT_BPP);
+	if (!ret) {
+		printk(KERN_ERR "sidsafb: No suitable video mode found\n");
+		goto unmap_regs;
+	}
+
+	ret = request_irq(sinfo->irq_base, sidsafb_interrupt, 0,
+			  "sidsafb", info);
+	if (ret)
+		goto unmap_regs;
+
+	/* Allocate colormap */
+	if (fb_alloc_cmap(&info->cmap, 256, 0)) {
+		ret = -ENOMEM;
+		goto unregister_irqs;
+	}
+
+	/*
+	 * Tell the world that we're ready to go
+	 */
+	ret = register_framebuffer(info);
+	if (ret)
+		goto free_cmap;
+
+	printk("fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %lu\n",
+	       info->node, info->fix.mmio_start, sinfo->regs, sinfo->irq_base);
+
+	platform_set_drvdata(pdev, info);
+
+	memset_io(info->screen_base, 0, info->fix.smem_len);
+	info->var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW;
+	ret = fb_set_var(info, &info->var);
+	if (ret)
+		printk(KERN_WARNING
+		       "sidsafb: Unable to set display parameters\n");
+	info->var.activate &= ~(FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW);
+
+	pr_debug("sidsafb_probe SUCCESS\n");
+	return 0;
+
+
+free_cmap:
+	fb_dealloc_cmap(&info->cmap);
+unregister_irqs:
+	free_irq(sinfo->irq_base, info);
+unmap_regs:
+	iounmap(sinfo->regs);
+free_fb:
+	if (!fb_data || fb_data->fbmem_size == 0)
+		dma_free_coherent(&pdev->dev, info->fix.smem_len,
+				  (void __force *)info->screen_base,
+				  info->fix.smem_start);
+disable_clocks:
+	clk_disable(sinfo->pixclk);
+	clk_disable(sinfo->hclk);
+	clk_put(sinfo->pixclk);
+put_hclk:
+	clk_put(sinfo->hclk);
+free_info:
+	framebuffer_release(info);
+out:
+	pr_debug("sidsafb_probe FAILED\n");
+	return ret;
+}
+
+static int __devexit sidsafb_remove(struct platform_device *pdev)
+{
+	struct lcdc_platform_data *fb_data = pdev->dev.platform_data;
+	struct fb_info *info = platform_get_drvdata(pdev);
+	struct sidsafb_info *sinfo;
+
+	if (!info)
+		return 0;
+	sinfo = info->par;
+
+	/* TODO: Restore original state */
+	unregister_framebuffer(info);
+
+	fb_dealloc_cmap(&info->cmap);
+	free_irq(sinfo->irq_base, info);
+	iounmap(sinfo->regs);
+	if (!fb_data || fb_data->fbmem_size == 0)
+		dma_free_coherent(&pdev->dev, info->fix.smem_len,
+				  (void __force *)info->screen_base,
+				  info->fix.smem_start);
+	clk_disable(sinfo->hclk);
+	clk_put(sinfo->hclk);
+	platform_set_drvdata(pdev, NULL);
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static struct platform_driver sidsafb_driver = {
+	.probe		= sidsafb_probe,
+	.remove		= __devexit_p(sidsafb_remove),
+	.driver		= {
+		.name		= "lcdc",
+	},
+};
+
+int __init sidsafb_init(void)
+{
+	return platform_driver_register(&sidsafb_driver);
+}
+
+static void __exit sidsafb_exit(void)
+{
+	platform_driver_unregister(&sidsafb_driver);
+}
+
+module_init(sidsafb_init);
+module_exit(sidsafb_exit);
+
+module_param(fb_size, ulong, 0644);
+MODULE_PARM_DESC(fb_size, "Minimum framebuffer size to allocate");
+
+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
+MODULE_DESCRIPTION("Atmel/SIDSA LCD Controller framebuffer driver");
+MODULE_LICENSE("GPL");
Index: linux-2.6.18-avr32/include/asm-avr32/periph/lcdc.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.18-avr32/include/asm-avr32/periph/lcdc.h	2006-11-02 16:08:35.000000000 +0100
@@ -0,0 +1,271 @@
+/*
+ * Register definitions for Atmel/SIDSA LCD Controller
+ *
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * 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.
+ */
+#ifndef __ASM_AVR32_PERIPH_LCDC_H__
+#define __ASM_AVR32_PERIPH_LCDC_H__
+
+#define LCDC_CONTRAST_CTR                       0x00000840
+# define LCDC_CONTRAST_CTR_ENA_OFFSET           3
+# define LCDC_CONTRAST_CTR_ENA_SIZE             1
+# define LCDC_CONTRAST_CTR_POL_OFFSET           2
+# define LCDC_CONTRAST_CTR_POL_SIZE             1
+# define LCDC_CONTRAST_CTR_PS_OFFSET            0
+# define LCDC_CONTRAST_CTR_PS_SIZE              2
+#define LCDC_CONTRAST_VAL                       0x00000844
+# define LCDC_CONTRAST_VAL_CVAL_OFFSET          0
+# define LCDC_CONTRAST_VAL_CVAL_SIZE            8
+#define LCDC_DMABADDR1                          0x00000000
+# define LCDC_DMABADDR1_BADDR_U_OFFSET          0
+# define LCDC_DMABADDR1_BADDR_U_SIZE            32
+#define LCDC_DMABADDR2                          0x00000004
+# define LCDC_DMABADDR2_BADDR_L_OFFSET          0
+# define LCDC_DMABADDR2_BADDR_L_SIZE            32
+#define LCDC_DMACON                             0x0000001C
+# define LCDC_DMACON_DMABUSY_OFFSET             2
+# define LCDC_DMACON_DMABUSY_SIZE               1
+# define LCDC_DMACON_DMAEN_OFFSET               0
+# define LCDC_DMACON_DMAEN_SIZE                 1
+# define LCDC_DMACON_DMARST_OFFSET              1
+# define LCDC_DMACON_DMARST_SIZE                1
+# define LCDC_DMACON_DMAUPDT_OFFSET             3
+# define LCDC_DMACON_DMAUPDT_SIZE               1
+# define LCDC_DMACON_DMA2DEN_OFFSET             4
+# define LCDC_DMACON_DMA2DEN_SIZE               1
+#define LCDC_DMAFRMADD1                         0x00000010
+# define LCDC_DMAFRMADD1_FRMADD_U_OFFSET        0
+# define LCDC_DMAFRMADD1_FRMADD_U_SIZE          32
+#define LCDC_DMAFRMADD2                         0x00000014
+# define LCDC_DMAFRMADD2_FRMADD_L_OFFSET        0
+# define LCDC_DMAFRMADD2_FRMADD_L_SIZE          32
+#define LCDC_DMAFRMCFG                          0x00000018
+# define LCDC_DMAFRMCFG_BRSTLEN_OFFSET          24
+# define LCDC_DMAFRMCFG_BRSTLEN_SIZE            7
+# define LCDC_DMAFRMCFG_FRMSIZE_OFFSET          0
+# define LCDC_DMAFRMCFG_FRMSIZE_SIZE            23
+#define LCDC_DMAFRMPT1                          0x00000008
+# define LCDC_DMAFRMPT1_FRMPT_U_OFFSET          0
+# define LCDC_DMAFRMPT1_FRMPT_U_SIZE            23
+#define LCDC_DMAFRMPT2                          0x0000000C
+# define LCDC_DMAFRMPT2_FRMPT_L_OFFSET          0
+# define LCDC_DMAFRMPT2_FRMPT_L_SIZE            23
+#define LCDC_DMA2DCFG                           0x00000020
+# define LCDC_DMA2DCFG_ADDRINC_OFFSET           0
+# define LCDC_DMA2DCFG_ADDRINC_SIZE             16
+# define LCDC_DMA2DCFG_PIXELOFF_OFFSET          24
+# define LCDC_DMA2DCFG_PIXELOFF_SIZE            5
+#define LCDC_DP1_2                              0x0000081C
+# define LCDC_DP1_2_DP1_2_OFFSET                0
+# define LCDC_DP1_2_DP1_2_SIZE                  8
+#define LCDC_DP2_3                              0x00000828
+# define LCDC_DP2_3_DP2_3_OFFSET                0
+# define LCDC_DP2_3_DP2_3_SIZE                  12
+#define LCDC_DP3_4                              0x00000830
+# define LCDC_DP3_4_DP3_4_OFFSET                0
+# define LCDC_DP3_4_DP3_4_SIZE                  16
+#define LCDC_DP3_5                              0x00000824
+# define LCDC_DP3_5_DP3_5_OFFSET                0
+# define LCDC_DP3_5_DP3_5_SIZE                  20
+#define LCDC_DP4_5                              0x00000834
+# define LCDC_DP4_5_DP4_5_OFFSET                0
+# define LCDC_DP4_5_DP4_5_SIZE                  20
+#define LCDC_DP4_7                              0x00000820
+# define LCDC_DP4_7_DP4_7_OFFSET                0
+# define LCDC_DP4_7_DP4_7_SIZE                  28
+#define LCDC_DP5_7                              0x0000082C
+# define LCDC_DP5_7_DP5_7_OFFSET                0
+# define LCDC_DP5_7_DP5_7_SIZE                  28
+#define LCDC_DP6_7                              0x00000838
+# define LCDC_DP6_7_DP6_7_OFFSET                0
+# define LCDC_DP6_7_DP6_7_SIZE                  28
+#define LCDC_LCDCON1                            0x00000800
+# define LCDC_LCDCON1_BYPASS_OFFSET             0
+# define LCDC_LCDCON1_BYPASS_SIZE               1
+# define LCDC_LCDCON1_CLKVAL_OFFSET             12
+# define LCDC_LCDCON1_CLKVAL_SIZE               9
+# define LCDC_LCDCON1_LINECNT_OFFSET            21
+# define LCDC_LCDCON1_LINECNT_SIZE              11
+#define LCDC_LCDCON2                            0x00000804
+# define LCDC_LCDCON2_CLKMOD_OFFSET             15
+# define LCDC_LCDCON2_CLKMOD_SIZE               1
+# define LCDC_LCDCON2_DISTYPE_OFFSET            0
+# define LCDC_LCDCON2_DISTYPE_SIZE              2
+# define LCDC_LCDCON2_IFWIDTH_OFFSET            3
+# define LCDC_LCDCON2_IFWIDTH_SIZE              2
+# define LCDC_LCDCON2_INVCLK_OFFSET             11
+# define LCDC_LCDCON2_INVCLK_SIZE               1
+# define LCDC_LCDCON2_INVDVAL_OFFSET            12
+# define LCDC_LCDCON2_INVDVAL_SIZE              1
+# define LCDC_LCDCON2_INVFRAME_OFFSET           9
+# define LCDC_LCDCON2_INVFRAME_SIZE             1
+# define LCDC_LCDCON2_INVLINE_OFFSET            10
+# define LCDC_LCDCON2_INVLINE_SIZE              1
+# define LCDC_LCDCON2_INVVD_OFFSET              8
+# define LCDC_LCDCON2_INVVD_SIZE                1
+# define LCDC_LCDCON2_MEMOR_OFFSET              30
+# define LCDC_LCDCON2_MEMOR_SIZE                2
+# define LCDC_LCDCON2_PIXELSIZE_OFFSET          5
+# define LCDC_LCDCON2_PIXELSIZE_SIZE            3
+# define LCDC_LCDCON2_SCANMOD_OFFSET            2
+# define LCDC_LCDCON2_SCANMOD_SIZE              1
+#define LCDC_LCDFIFO                            0x00000814
+# define LCDC_LCDFIFO_FIFOTH_OFFSET             0
+# define LCDC_LCDFIFO_FIFOTH_SIZE               16
+#define LCDC_LCDFRMCFG                          0x00000810
+# define LCDC_LCDFRMCFG_LINESIZE_OFFSET         21
+# define LCDC_LCDFRMCFG_LINESIZE_SIZE           11
+# define LCDC_LCDFRMCFG_LINEVAL_OFFSET          0
+# define LCDC_LCDFRMCFG_LINEVAL_SIZE            11
+#define LCDC_LCDMVAL                            0x00000818
+# define LCDC_LCDMVAL_MMODE_OFFSET              31
+# define LCDC_LCDMVAL_MMODE_SIZE                1
+# define LCDC_LCDMVAL_MVAL_OFFSET               0
+# define LCDC_LCDMVAL_MVAL_SIZE                 8
+#define LCDC_LCDTIM1                            0x00000808
+# define LCDC_LCDTIM1_VBP_OFFSET                8
+# define LCDC_LCDTIM1_VBP_SIZE                  8
+# define LCDC_LCDTIM1_VFP_OFFSET                0
+# define LCDC_LCDTIM1_VFP_SIZE                  8
+# define LCDC_LCDTIM1_VHDLY_OFFSET              24
+# define LCDC_LCDTIM1_VHDLY_SIZE                4
+# define LCDC_LCDTIM1_VPW_OFFSET                16
+# define LCDC_LCDTIM1_VPW_SIZE                  6
+#define LCDC_LCDTIM2                            0x0000080C
+# define LCDC_LCDTIM2_HBP_OFFSET                0
+# define LCDC_LCDTIM2_HBP_SIZE                  8
+# define LCDC_LCDTIM2_HFP_OFFSET                21
+# define LCDC_LCDTIM2_HFP_SIZE                  11
+# define LCDC_LCDTIM2_HPW_OFFSET                8
+# define LCDC_LCDTIM2_HPW_SIZE                  6
+#define LCDC_LCD_GPR                            0x0000085C
+# define LCDC_LCD_GPR_GPRB0_OFFSET              0
+# define LCDC_LCD_GPR_GPRB0_SIZE                1
+# define LCDC_LCD_GPR_GPRB1_OFFSET              1
+# define LCDC_LCD_GPR_GPRB1_SIZE                1
+# define LCDC_LCD_GPR_GPRB2_OFFSET              2
+# define LCDC_LCD_GPR_GPRB2_SIZE                1
+# define LCDC_LCD_GPR_GPRB3_OFFSET              3
+# define LCDC_LCD_GPR_GPRB3_SIZE                1
+# define LCDC_LCD_GPR_GPRB4_OFFSET              4
+# define LCDC_LCD_GPR_GPRB4_SIZE                1
+# define LCDC_LCD_GPR_GPRB5_OFFSET              5
+# define LCDC_LCD_GPR_GPRB5_SIZE                1
+# define LCDC_LCD_GPR_GPRB6_OFFSET              6
+# define LCDC_LCD_GPR_GPRB6_SIZE                1
+# define LCDC_LCD_GPR_GPRB7_OFFSET              7
+# define LCDC_LCD_GPR_GPRB7_SIZE                1
+#define LCDC_LCD_ICR                            0x00000858
+# define LCDC_LCD_ICR_EOFIC_OFFSET              2
+# define LCDC_LCD_ICR_EOFIC_SIZE                1
+# define LCDC_LCD_ICR_LNIC_OFFSET               0
+# define LCDC_LCD_ICR_LNIC_SIZE                 1
+# define LCDC_LCD_ICR_LSTLNIC_OFFSET            1
+# define LCDC_LCD_ICR_LSTLNIC_SIZE              1
+# define LCDC_LCD_ICR_MERIC_OFFSET              6
+# define LCDC_LCD_ICR_MERIC_SIZE                1
+# define LCDC_LCD_ICR_OWRIC_OFFSET              5
+# define LCDC_LCD_ICR_OWRIC_SIZE                1
+# define LCDC_LCD_ICR_UFLWIC_OFFSET             4
+# define LCDC_LCD_ICR_UFLWIC_SIZE               1
+#define LCDC_LCD_IDR                            0x0000084C
+# define LCDC_LCD_IDR_EOFID_OFFSET              2
+# define LCDC_LCD_IDR_EOFID_SIZE                1
+# define LCDC_LCD_IDR_LNID_OFFSET               0
+# define LCDC_LCD_IDR_LNID_SIZE                 1
+# define LCDC_LCD_IDR_LSTLNID_OFFSET            1
+# define LCDC_LCD_IDR_LSTLNID_SIZE              1
+# define LCDC_LCD_IDR_MERID_OFFSET              6
+# define LCDC_LCD_IDR_MERID_SIZE                1
+# define LCDC_LCD_IDR_OWRID_OFFSET              5
+# define LCDC_LCD_IDR_OWRID_SIZE                1
+# define LCDC_LCD_IDR_UFLWID_OFFSET             4
+# define LCDC_LCD_IDR_UFLWID_SIZE               1
+#define LCDC_LCD_IER                            0x00000848
+# define LCDC_LCD_IER_EOFIE_OFFSET              2
+# define LCDC_LCD_IER_EOFIE_SIZE                1
+# define LCDC_LCD_IER_LNIE_OFFSET               0
+# define LCDC_LCD_IER_LNIE_SIZE                 1
+# define LCDC_LCD_IER_LSTLNIE_OFFSET            1
+# define LCDC_LCD_IER_LSTLNIE_SIZE              1
+# define LCDC_LCD_IER_MERIE_OFFSET              6
+# define LCDC_LCD_IER_MERIE_SIZE                1
+# define LCDC_LCD_IER_OWRIE_OFFSET              5
+# define LCDC_LCD_IER_OWRIE_SIZE                1
+# define LCDC_LCD_IER_UFLWIE_OFFSET             4
+# define LCDC_LCD_IER_UFLWIE_SIZE               1
+#define LCDC_LCD_IMR                            0x00000850
+# define LCDC_LCD_IMR_EOFIM_OFFSET              2
+# define LCDC_LCD_IMR_EOFIM_SIZE                1
+# define LCDC_LCD_IMR_LNIM_OFFSET               0
+# define LCDC_LCD_IMR_LNIM_SIZE                 1
+# define LCDC_LCD_IMR_LSTLNIM_OFFSET            1
+# define LCDC_LCD_IMR_LSTLNIM_SIZE              1
+# define LCDC_LCD_IMR_MERIM_OFFSET              6
+# define LCDC_LCD_IMR_MERIM_SIZE                1
+# define LCDC_LCD_IMR_OWRIM_OFFSET              5
+# define LCDC_LCD_IMR_OWRIM_SIZE                1
+# define LCDC_LCD_IMR_UFLWIM_OFFSET             4
+# define LCDC_LCD_IMR_UFLWIM_SIZE               1
+#define LCDC_LCD_IRR                            0x00000864
+# define LCDC_LCD_IRR_EOFIR_OFFSET              2
+# define LCDC_LCD_IRR_EOFIR_SIZE                1
+# define LCDC_LCD_IRR_LNIR_OFFSET               0
+# define LCDC_LCD_IRR_LNIR_SIZE                 1
+# define LCDC_LCD_IRR_LSTLNIR_OFFSET            1
+# define LCDC_LCD_IRR_LSTLNIR_SIZE              1
+# define LCDC_LCD_IRR_MERIR_OFFSET              6
+# define LCDC_LCD_IRR_MERIR_SIZE                1
+# define LCDC_LCD_IRR_OWRIR_OFFSET              5
+# define LCDC_LCD_IRR_OWRIR_SIZE                1
+# define LCDC_LCD_IRR_UFLWIR_OFFSET             4
+# define LCDC_LCD_IRR_UFLWIR_SIZE               1
+#define LCDC_LCD_ISR                            0x00000854
+# define LCDC_LCD_ISR_EOFIS_OFFSET              2
+# define LCDC_LCD_ISR_EOFIS_SIZE                1
+# define LCDC_LCD_ISR_LNIS_OFFSET               0
+# define LCDC_LCD_ISR_LNIS_SIZE                 1
+# define LCDC_LCD_ISR_LSTLNIS_OFFSET            1
+# define LCDC_LCD_ISR_LSTLNIS_SIZE              1
+# define LCDC_LCD_ISR_MERIS_OFFSET              6
+# define LCDC_LCD_ISR_MERIS_SIZE                1
+# define LCDC_LCD_ISR_OWRIS_OFFSET              5
+# define LCDC_LCD_ISR_OWRIS_SIZE                1
+# define LCDC_LCD_ISR_UFLWIS_OFFSET             4
+# define LCDC_LCD_ISR_UFLWIS_SIZE               1
+#define LCDC_LCD_ITR                            0x00000860
+# define LCDC_LCD_ITR_EOFIT_OFFSET              2
+# define LCDC_LCD_ITR_EOFIT_SIZE                1
+# define LCDC_LCD_ITR_LNIT_OFFSET               0
+# define LCDC_LCD_ITR_LNIT_SIZE                 1
+# define LCDC_LCD_ITR_LSTLNIT_OFFSET            1
+# define LCDC_LCD_ITR_LSTLNIT_SIZE              1
+# define LCDC_LCD_ITR_MERIT_OFFSET              6
+# define LCDC_LCD_ITR_MERIT_SIZE                1
+# define LCDC_LCD_ITR_OWRIT_OFFSET              5
+# define LCDC_LCD_ITR_OWRIT_SIZE                1
+# define LCDC_LCD_ITR_UFLWIT_OFFSET             4
+# define LCDC_LCD_ITR_UFLWIT_SIZE               1
+#define LCDC_PWRCON                             0x0000083C
+# define LCDC_PWRCON_GUARD_TIME_OFFSET          1
+# define LCDC_PWRCON_GUARD_TIME_SIZE            7
+# define LCDC_PWRCON_LCD_BUSY_OFFSET            31
+# define LCDC_PWRCON_LCD_BUSY_SIZE              1
+# define LCDC_PWRCON_LCD_PWR_OFFSET             0
+# define LCDC_PWRCON_LCD_PWR_SIZE               1
+
+#define LCDC_BIT(name)                          (1 << LCDC_##name##_OFFSET)
+#define LCDC_MKBF(name,value)                   (((value) & ((1 << LCDC_##name##_SIZE) - 1)) << LCDC_##name##_OFFSET)
+#define LCDC_GETBF(name,value)                  (((value) >> LCDC_##name##_OFFSET) & ((1 << LCDC_##name##_SIZE) - 1))
+#define LCDC_INSBF(name,value,old)              (((old) & ~(((1 << LCDC_##name##_SIZE) - 1) << LCDC_##name##_OFFSET)) | LCDC_MKBF(name, value))
+
+#define lcdc_readl(port,reg)				\
+	__raw_readl((port)->regs + LCDC_##reg)
+#define lcdc_writel(port,reg,value)			\
+	__raw_writel((value), (port)->regs + LCDC_##reg)
+
+#endif /* __ASM_AVR32_PERIPH_LCDC_H__ */
Index: linux-2.6.18-avr32/include/linux/fb.h
===================================================================
--- linux-2.6.18-avr32.orig/include/linux/fb.h	2006-11-02 15:54:18.000000000 +0100
+++ linux-2.6.18-avr32/include/linux/fb.h	2006-11-02 15:56:20.000000000 +0100
@@ -191,6 +191,7 @@ struct fb_bitfield {
 					/* vtotal = 144d/288n/576i => PAL  */
 					/* vtotal = 121d/242n/484i => NTSC */
 #define FB_SYNC_ON_GREEN	32	/* sync on green */
+#define FB_SYNC_PCLK_RISING	64	/* pixel data sampled on rising pclk */
 
 #define FB_VMODE_NONINTERLACED  0	/* non interlaced */
 #define FB_VMODE_INTERLACED	1	/* interlaced	*/
@@ -825,7 +826,7 @@ struct fb_info {
 #define fb_writeq sbus_writeq
 #define fb_memset sbus_memset_io
 
-#elif defined(__i386__) || defined(__alpha__) || defined(__x86_64__) || defined(__hppa__) || (defined(__sh__) && !defined(__SH5__)) || defined(__powerpc__)
+#elif defined(__i386__) || defined(__alpha__) || defined(__x86_64__) || defined(__hppa__) || (defined(__sh__) && !defined(__SH5__)) || defined(__powerpc__) || defined(__avr32__)
 
 #define fb_readb __raw_readb
 #define fb_readw __raw_readw