--- 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +/* 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 "); +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