From: Christian <c.pellegrin@exadron.com>
To: linux-mips@linux-mips.org
Subject: [PATCH] au1100fb.c ported from 2.4 to 2.6
Date: Wed, 12 Jan 2005 10:50:07 +0100 [thread overview]
Message-ID: <1105523407.5654.18.camel@absolute.ascensit.com> (raw)
[-- Attachment #1.1: Type: text/plain, Size: 149 bytes --]
Hi,
works in 16bpp, anyone with a system that works in 8bbp can give me a
hand to test this mode?
--
Christian <c.pellegrin@exadron.com>
[-- Attachment #1.2: fb1 --]
[-- Type: text/x-patch, Size: 28517 bytes --]
Index: drivers/video/Kconfig
===================================================================
RCS file: /home/cvs/linux/drivers/video/Kconfig,v
retrieving revision 1.31
diff -u -r1.31 Kconfig
--- drivers/video/Kconfig 24 Nov 2004 09:03:40 -0000 1.31
+++ drivers/video/Kconfig 12 Jan 2005 09:05:16 -0000
@@ -973,7 +973,7 @@
config FB_AU1100
bool "Au1100 LCD Driver"
- depends on FB && EXPERIMENTAL && PCI && MIPS && MIPS_PB1100=y
+ depends on FB && EXPERIMENTAL && MIPS && SOC_AU1X00
config FB_SBUS
bool "SBUS and UPA framebuffers"
Index: drivers/video/Makefile
===================================================================
RCS file: /home/cvs/linux/drivers/video/Makefile,v
retrieving revision 1.85
diff -u -r1.85 Makefile
--- drivers/video/Makefile 15 Nov 2004 11:49:34 -0000 1.85
+++ drivers/video/Makefile 12 Jan 2005 09:05:21 -0000
@@ -94,7 +94,7 @@
obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_MAXINE) += maxinefb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_TX3912) += tx3912fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_AU1100) += au1100fb.o fbgen.o
+obj-$(CONFIG_FB_AU1100) += au1100fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
# Platform or fallback drivers go here
Index: drivers/video/au1100fb.c
===================================================================
RCS file: /home/cvs/linux/drivers/video/au1100fb.c,v
retrieving revision 1.3
diff -u -r1.3 au1100fb.c
--- drivers/video/au1100fb.c 26 Oct 2004 02:23:08 -0000 1.3
+++ drivers/video/au1100fb.c 12 Jan 2005 09:05:26 -0000
@@ -2,16 +2,28 @@
* BRIEF MODULE DESCRIPTION
* Au1100 LCD Driver.
*
+ * Adapted by <c.pellegrin@exadron.com> for kernel 2.6
+ *
+ * TODO:
+ * 8bpp support ASA I get hardware for testing
+ *
+ * based on code:
+ ****** 2.4 au1100fb.c
* Copyright 2002 MontaVista Software
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
*
* Copyright 2002 Alchemy Semiconductor
* Author: Alchemy Semiconductor
+ ****** 2.6 vesafb.c
+ * framebuffer driver for VBE 2.0 compliant graphic boards
+ *
+ * switching to graphics mode happens at boot time (while
+ * running in real mode, see arch/i386/boot/video.S).
+ *
+ * (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
*
- * Based on:
- * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device
- * Created 28 Dec 1997 by Geert Uytterhoeven
+ ******
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -43,37 +55,18 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
+#include <linux/ioport.h>
#include <linux/init.h>
-#include <linux/pci.h>
-#include <asm/au1000.h>
-#include <asm/pb1100.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-pb1x00/pb1100.h>
#include "au1100fb.h"
-#include <video/fbcon.h>
-#include <video/fbcon-mfb.h>
-#include <video/fbcon-cfb2.h>
-#include <video/fbcon-cfb4.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
-
-/*
- * Sanity check. If this is a new Au1100 based board, search for
- * the PB1100 ifdefs to make sure you modify the code accordingly.
- */
-#if defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_HYDROGEN3)
-#else
-error Unknown Au1100 board
-#endif
-
-#define CMAPSIZE 16
-static int my_lcd_index; /* default is zero */
-struct known_lcd_panels *p_lcd;
-AU1100_LCD *p_lcd_reg = (AU1100_LCD *)AU1100_LCD_ADDR;
+/* --------------------------------------------------------------------- */
struct au1100fb_info {
- struct fb_info_gen gen;
+ struct fb_info gen;
unsigned long fb_virt_start;
unsigned long fb_size;
unsigned long fb_phys;
@@ -88,192 +81,53 @@
};
-struct au1100fb_par {
- struct fb_var_screeninfo var;
-
- int line_length; // in bytes
- int cmap_len; // color-map length
-};
-
+/* --------------------------------------------------------------------- */
-static struct au1100fb_info fb_info;
-static struct au1100fb_par current_par;
-static struct display disp;
-
-int au1100fb_init(void);
-void au1100fb_setup(char *options, int *ints);
-static int au1100fb_mmap(struct fb_info *fb, struct file *file,
- struct vm_area_struct *vma);
-static int au1100_blank(int blank_mode, struct fb_info_gen *info);
-static int au1100fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg, int con, struct fb_info *info);
+static int my_lcd_index; /* default is zero */
+struct known_lcd_panels *p_lcd;
+AU1100_LCD *p_lcd_reg = (AU1100_LCD *)AU1100_LCD_ADDR;
+static int depth;
+static int nohwcursor;
-void au1100_nocursor(struct display *p, int mode, int xx, int yy){};
+static struct au1100fb_info *my_fb_info; /* the info for the current driver */
-static struct fb_ops au1100fb_ops = {
- owner: THIS_MODULE,
- fb_get_fix: fbgen_get_fix,
- fb_get_var: fbgen_get_var,
- fb_set_var: fbgen_set_var,
- fb_get_cmap: fbgen_get_cmap,
- fb_set_cmap: fbgen_set_cmap,
- fb_pan_display: fbgen_pan_display,
- fb_ioctl: au1100fb_ioctl,
- fb_mmap: au1100fb_mmap,
+static struct fb_var_screeninfo au1100fb_defined __initdata = {
+ .activate = FB_ACTIVATE_NOW,
+ .height = -1,
+ .width = -1,
+ .right_margin = 32,
+ .upper_margin = 16,
+ .lower_margin = 4,
+ .vsync_len = 4,
+ .vmode = FB_VMODE_NONINTERLACED,
};
-static void au1100_detect(void)
-{
- /*
- * This function should detect the current video mode settings
- * and store it as the default video mode
- */
-
- /*
- * Yeh, well, we're not going to change any settings so we're
- * always stuck with the default ...
- */
+static struct fb_fix_screeninfo au1100fb_fix __initdata = {
+ .id = "AU1100 FB",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .accel = FB_ACCEL_NONE,
+};
-}
+/* --------------------------------------------------------------------- */
-static int au1100_encode_fix(struct fb_fix_screeninfo *fix,
- const void *_par, struct fb_info_gen *_info)
+static int au1100fb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
{
- struct au1100fb_info *info = (struct au1100fb_info *) _info;
- struct au1100fb_par *par = (struct au1100fb_par *) _par;
- struct fb_var_screeninfo *var = &par->var;
-
- memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-
- fix->smem_start = info->fb_phys;
- fix->smem_len = info->fb_size;
- fix->type = FB_TYPE_PACKED_PIXELS;
- fix->type_aux = 0;
- fix->visual = (var->bits_per_pixel == 8) ?
- FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
- fix->ywrapstep = 0;
- fix->xpanstep = 1;
- fix->ypanstep = 1;
- fix->line_length = current_par.line_length;
return 0;
}
-static void set_color_bitfields(struct fb_var_screeninfo *var)
+static int au1100fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
{
- switch (var->bits_per_pixel) {
- case 8:
- var->red.offset = 0;
- var->red.length = 8;
- var->green.offset = 0;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
- var->transp.offset = 0;
- var->transp.length = 0;
- break;
- case 16: /* RGB 565 */
- var->red.offset = 11;
- var->red.length = 5;
- var->green.offset = 5;
- var->green.length = 6;
- var->blue.offset = 0;
- var->blue.length = 5;
- var->transp.offset = 0;
- var->transp.length = 0;
- break;
- }
-
- var->red.msb_right = 0;
- var->green.msb_right = 0;
- var->blue.msb_right = 0;
- var->transp.msb_right = 0;
-}
-
-static int au1100_decode_var(const struct fb_var_screeninfo *var,
- void *_par, struct fb_info_gen *_info)
-{
-
- struct au1100fb_par *par = (struct au1100fb_par *)_par;
-
/*
- * Don't allow setting any of these yet: xres and yres don't
- * make sense for LCD panels.
+ * Set a single color register. The values supplied are
+ * already rounded down to the hardware's capabilities
+ * (according to the entries in the `var' structure). Return
+ * != 0 for invalid regno.
*/
- if (var->xres != p_lcd->xres ||
- var->yres != p_lcd->yres ||
- var->xres != p_lcd->xres ||
- var->yres != p_lcd->yres) {
- return -EINVAL;
- }
- if(var->bits_per_pixel != p_lcd->bpp) {
- return -EINVAL;
- }
-
- memset(par, 0, sizeof(struct au1100fb_par));
- par->var = *var;
- /* FIXME */
- switch (var->bits_per_pixel) {
- case 8:
- par->var.bits_per_pixel = 8;
- break;
- case 16:
- par->var.bits_per_pixel = 16;
- break;
- default:
- printk("color depth %d bpp not supported\n",
- var->bits_per_pixel);
- return -EINVAL;
-
- }
- set_color_bitfields(&par->var);
- par->cmap_len = (par->var.bits_per_pixel == 8) ? 256 : 16;
- return 0;
-}
-
-static int au1100_encode_var(struct fb_var_screeninfo *var,
- const void *par, struct fb_info_gen *_info)
-{
-
- *var = ((struct au1100fb_par *)par)->var;
- return 0;
-}
-
-static void
-au1100_get_par(void *_par, struct fb_info_gen *_info)
-{
- *(struct au1100fb_par *)_par = current_par;
-}
-
-static void au1100_set_par(const void *par, struct fb_info_gen *info)
-{
- /* nothing to do: we don't change any settings */
-}
-
-static int au1100_getcolreg(unsigned regno, unsigned *red, unsigned *green,
- unsigned *blue, unsigned *transp,
- struct fb_info *info)
-{
-
- struct au1100fb_info* i = (struct au1100fb_info*)info;
-
- if (regno > 255)
- return 1;
-
- *red = i->palette[regno].red;
- *green = i->palette[regno].green;
- *blue = i->palette[regno].blue;
- *transp = 0;
-
- return 0;
-}
-
-static int au1100_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *info)
-{
struct au1100fb_info* i = (struct au1100fb_info *)info;
- u32 rgbcol;
if (regno > 255)
return 1;
@@ -307,75 +161,6 @@
return 0;
}
-
-static int au1100_blank(int blank_mode, struct fb_info_gen *_info)
-{
-
- switch (blank_mode) {
- case VESA_NO_BLANKING:
- /* turn on panel */
- //printk("turn on panel\n");
-#ifdef CONFIG_MIPS_PB1100
- p_lcd_reg->lcd_control |= LCD_CONTROL_GO;
- au_writew(au_readw(PB1100_G_CONTROL) | p_lcd->mode_backlight,
- PB1100_G_CONTROL);
-#endif
-#ifdef CONFIG_MIPS_HYDROGEN3
- /* Turn controller & power supply on, GPIO213 */
- au_writel(0x20002000, 0xB1700008);
- au_writel(0x00040000, 0xB1900108);
- au_writel(0x01000100, 0xB1700008);
-#endif
- au_sync();
- break;
-
- case VESA_VSYNC_SUSPEND:
- case VESA_HSYNC_SUSPEND:
- case VESA_POWERDOWN:
- /* turn off panel */
- //printk("turn off panel\n");
-#ifdef CONFIG_MIPS_PB1100
- au_writew(au_readw(PB1100_G_CONTROL) & ~p_lcd->mode_backlight,
- PB1100_G_CONTROL);
- p_lcd_reg->lcd_control &= ~LCD_CONTROL_GO;
-#endif
- au_sync();
- break;
- default:
- break;
-
- }
- return 0;
-}
-
-static void au1100_set_disp(const void *unused, struct display *disp,
- struct fb_info_gen *info)
-{
- disp->screen_base = (char *)fb_info.fb_virt_start;
-
- switch (disp->var.bits_per_pixel) {
-#ifdef FBCON_HAS_CFB8
- case 8:
- disp->dispsw = &fbcon_cfb8;
- if (fb_info.nohwcursor)
- fbcon_cfb8.cursor = au1100_nocursor;
- break;
-#endif
-#ifdef FBCON_HAS_CFB16
- case 16:
- disp->dispsw = &fbcon_cfb16;
- disp->dispsw_data = fb_info.fbcon_cmap16;
- if (fb_info.nohwcursor)
- fbcon_cfb16.cursor = au1100_nocursor;
- break;
-#endif
- default:
- disp->dispsw = &fbcon_dummy;
- disp->dispsw_data = NULL;
- break;
- }
-}
-
static int
au1100fb_mmap(struct fb_info *_fb,
struct file *file,
@@ -389,8 +174,8 @@
return -EINVAL;
}
- start = fb_info.fb_phys & PAGE_MASK;
- len = PAGE_ALIGN((start & ~PAGE_MASK) + fb_info.fb_size);
+ start = my_fb_info->fb_phys & PAGE_MASK;
+ len = PAGE_ALIGN((start & ~PAGE_MASK) + my_fb_info->fb_size);
off = vma->vm_pgoff << PAGE_SHIFT;
@@ -408,7 +193,7 @@
/* This is an IO map - tell maydump to skip this VMA */
vma->vm_flags |= VM_IO;
- if (io_remap_page_range(vma->vm_start, off,
+ if (io_remap_page_range(vma, vma->vm_start, off,
vma->vm_end - vma->vm_start,
vma->vm_page_prot)) {
return -EAGAIN;
@@ -418,33 +203,68 @@
return 0;
}
-int au1100_pan_display(const struct fb_var_screeninfo *var,
- struct fb_info_gen *info)
-{
- return 0;
-}
+static struct fb_ops au1100fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_setcolreg = au1100fb_setcolreg,
+ .fb_pan_display = au1100fb_pan_display,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_cursor = soft_cursor,
+ .fb_mmap = au1100fb_mmap,
+};
-static int au1100fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg, int con, struct fb_info *info)
+void au1100fb_setup(char *options)
{
- /* nothing to do yet */
- return -EINVAL;
-}
+ char* this_opt;
+#ifndef CONFIG_WWPC
+ int i;
+ int num_panels = sizeof(panels)/sizeof(struct known_lcd_panels);
+#endif
-static struct fbgen_hwswitch au1100_switch = {
- au1100_detect,
- au1100_encode_fix,
- au1100_decode_var,
- au1100_encode_var,
- au1100_get_par,
- au1100_set_par,
- au1100_getcolreg,
- au1100_setcolreg,
- au1100_pan_display,
- au1100_blank,
- au1100_set_disp
-};
+
+ if (!options || !*options)
+ return;
+
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+ if (!strncmp(this_opt, "panel:", 6)) {
+#ifdef CONFIG_WWPC
+ /* we have just one fixed LCD */
+ my_lcd_index = 0;
+#else
+#if defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100)
+ /* Read Pb1100 Switch S10 ? */
+ if (!strncmp(this_opt+6, "s10", 3))
+ {
+ int panel;
+ panel = *(volatile int *)0xAE000008; /* BCSR SWITCHES */
+ panel >>= 8;
+ panel &= 0x0F;
+ if (panel >= num_panels) panel = 0;
+ my_lcd_index = panel;
+ }
+ else
+#endif
+ /* Get the panel name, everything else if fixed */
+ for (i=0; i<num_panels; i++) {
+ if (!strncmp(this_opt+6, panels[i].panel_name,
+ strlen(this_opt))) {
+ my_lcd_index = i;
+ break;
+ }
+ }
+#endif /* CONFIG_WWPC */
+ }
+ else if (!strncmp(this_opt, "nohwcursor", 10)) {
+ printk("nohwcursor\n");
+ nohwcursor = 1;
+ }
+ }
+ printk("au1100fb: Panel %d %s\n", my_lcd_index,
+ panels[my_lcd_index].panel_name);
+ p_lcd = &panels[my_lcd_index];
+}
int au1100_setmode(void)
{
@@ -478,7 +298,7 @@
p_lcd_reg->lcd_verttiming = p_lcd->mode_verttiming;
p_lcd_reg->lcd_clkcontrol = p_lcd->mode_clkcontrol;
p_lcd_reg->lcd_words = words - 1;
- p_lcd_reg->lcd_dmaaddr0 = fb_info.fb_phys;
+ p_lcd_reg->lcd_dmaaddr0 = my_fb_info->fb_phys;
/* turn on panel */
#ifdef CONFIG_MIPS_PB1100
@@ -491,23 +311,49 @@
au_writel(0x00040000, 0xB1900108);
au_writel(0x01000100, 0xB1700008);
#endif
+#ifdef CONFIG_WWPC
+ au_writel(0x000221A1, 0xB190002C);
+
+ au_writel(0x40228000, 0xB1900108);
+ au_writel(0x001D0000, 0xB190010C);
+ au_writel(0x403F8000, 0xB1900100);
+
+ /* TODO: move in the right place */
+
+ au_writel(0x00000001, 0xB1700014);
+ au_writel(0x0000060F, 0xB1700000);
+ au_writel(0x060F0400, 0xB1700008);
+
+ /* turn on LCD */
+ {
+ unsigned long t;
+
+ t = au_readl(0xB1900108);
+ t |= (1 << 20);
+ au_writel(t, 0xB1900108);
+ udelay(1000);
+ t |= (1 << 19);
+ au_writel(t, 0xB1900108);
+ printk("LCD ON: 0xB1900108 is %08lx\n", t);
+ }
+
+#endif
p_lcd_reg->lcd_control |= LCD_CONTROL_GO;
return 0;
}
-
-int __init au1100fb_init(void)
+static int __init au1100fb_probe(struct device *device)
{
- uint32 sys_clksrc;
+ struct platform_device *dev = to_platform_device(device);
+ struct fb_info *info;
+ int err;
unsigned long page;
+ unsigned int size_vmode;
+ uint32 sys_clksrc;
- /*
- * Get the panel information/display mode and update the registry
- */
- p_lcd = &panels[my_lcd_index];
-
+ /* verify LCD rotation */
switch (p_lcd->mode_control & LCD_CONTROL_SM)
{
case LCD_CONTROL_SM_0:
@@ -526,6 +372,17 @@
break;
}
+ /* alloc info struct */
+ info = framebuffer_alloc(sizeof(struct au1100fb_info), &dev->dev);
+ if (!info) {
+ printk("Cannot allocate FB\n");
+ return -ENOMEM;
+ }
+ my_fb_info = (struct au1100fb_info *) info;
+ info->pseudo_palette = info->par;
+ info->par = NULL;
+ my_fb_info->nohwcursor = nohwcursor;
+
/*
* Panel dimensions x bpp must be divisible by 32
*/
@@ -534,143 +391,225 @@
if (((p_lcd->xres * p_lcd->bpp) % 32) != 0)
printk("HORZ %% 32\n");
- /*
- * Allocate LCD framebuffer from system memory
- */
- fb_info.fb_size = (p_lcd->xres * p_lcd->yres * p_lcd->bpp) / 8;
-
- current_par.var.xres = p_lcd->xres;
- current_par.var.xres_virtual = p_lcd->xres;
- current_par.var.yres = p_lcd->yres;
- current_par.var.yres_virtual = p_lcd->yres;
- current_par.var.bits_per_pixel = p_lcd->bpp;
-
- /* FIX!!! only works for 8/16 bpp */
- current_par.line_length = p_lcd->xres * p_lcd->bpp / 8; /* in bytes */
- fb_info.fb_virt_start = (unsigned long )
+ /* determine start address of the FB */
+ my_fb_info->fb_size = (p_lcd->xres * p_lcd->yres * p_lcd->bpp) / 8;
+ my_fb_info->fb_virt_start = (unsigned long )
__get_free_pages(GFP_ATOMIC | GFP_DMA,
- get_order(fb_info.fb_size + 0x1000));
- if (!fb_info.fb_virt_start) {
+ get_order(my_fb_info->fb_size + 0x1000));
+ if (!my_fb_info->fb_virt_start) {
printk("Unable to allocate fb memory\n");
return -ENOMEM;
}
- fb_info.fb_phys = virt_to_bus((void *)fb_info.fb_virt_start);
-
+ info->screen_base = my_fb_info->fb_virt_start;
+ my_fb_info->fb_phys = virt_to_bus((void *)my_fb_info->fb_virt_start);
+ au1100fb_fix.smem_start = my_fb_info->fb_virt_start;
/*
* Set page reserved so that mmap will work. This is necessary
* since we'll be remapping normal memory.
*/
- for (page = fb_info.fb_virt_start;
- page < PAGE_ALIGN(fb_info.fb_virt_start + fb_info.fb_size);
+ for (page = my_fb_info->fb_virt_start;
+ page < PAGE_ALIGN(my_fb_info->fb_virt_start + my_fb_info->fb_size);
page += PAGE_SIZE) {
SetPageReserved(virt_to_page(page));
}
- memset((void *)fb_info.fb_virt_start, 0, fb_info.fb_size);
+ /* setup bpp */
+ au1100fb_defined.bits_per_pixel = p_lcd->bpp;
+ if (15 == au1100fb_defined.bits_per_pixel)
+ au1100fb_defined.bits_per_pixel = 16;
+ au1100fb_fix.visual = (au1100fb_defined.bits_per_pixel == 8) ?
+ FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+
+ /* setup geometry */
+ au1100fb_defined.xres = p_lcd->xres;
+ au1100fb_defined.yres = p_lcd->yres;
+ au1100fb_fix.line_length = p_lcd->xres * p_lcd->bpp / 8;
+
+ /* size_vmode -- that is the amount of memory needed for the
+ * used video mode, i.e. the minimum amount of
+ * memory we need. */
+ size_vmode = au1100fb_defined.yres * au1100fb_fix.line_length;
+
+ au1100fb_fix.smem_len = my_fb_info->fb_size;
+
+ printk(KERN_INFO "au1100fb: framebuffer at 0x%lx, mapped to 0x%p\n",
+ au1100fb_fix.smem_start, info->screen_base);
+ printk(KERN_INFO "au1100fb: mode is %dx%dx%d, linelength=%d\n",
+ au1100fb_defined.xres, au1100fb_defined.yres, au1100fb_defined.bits_per_pixel, au1100fb_fix.line_length);
+
+ au1100fb_defined.xres_virtual = au1100fb_defined.xres;
+ au1100fb_defined.yres_virtual = au1100fb_fix.smem_len / au1100fb_fix.line_length;
+
+ /* some dummy values for timing to make fbset happy */
+ au1100fb_defined.pixclock = 10000000 / au1100fb_defined.xres * 1000 / au1100fb_defined.yres;
+ au1100fb_defined.left_margin = (au1100fb_defined.xres / 8) & 0xf8;
+ au1100fb_defined.hsync_len = (au1100fb_defined.xres / 8) & 0xf8;
+
+ /* TODO, 8bpp */
+ au1100fb_defined.red.offset = 11;
+ au1100fb_defined.red.length = 5;
+ au1100fb_defined.green.offset = 5;
+ au1100fb_defined.green.length = 6;
+ au1100fb_defined.blue.offset = 0;
+ au1100fb_defined.blue.length = 5;
+ au1100fb_defined.transp.offset = 0;
+ au1100fb_defined.transp.length = 0;
+
+#if 0
+ /* test pattern */
+#define BLOCK 16
+ {
+ int x,y,xx,yy,i;
+ unsigned short c;
+ unsigned short *p = (unsigned short *) my_fb_info->fb_virt_start;
+ int mx = p_lcd->xres / BLOCK;
+ int my = p_lcd->yres / BLOCK;;
+ i = 0;
+ for(x=0; x<mx; x++)
+ for(y=0; y<my; y++) {
+ switch (i%3) {
+ case 0:
+ c = (0x1f << au1100fb_defined.red.offset);
+ break;
+ case 1:
+ c = (0x3f << au1100fb_defined.green.offset);
+ break;
+ case 2:
+ c = (0x1f << au1100fb_defined.blue.offset);
+ break;
+ default:
+ c = 0;
+ break;
+ }
+ for(xx = x*BLOCK ; xx < (x+1)*BLOCK; xx++)
+ for(yy = y*BLOCK ; yy < (y+1)*BLOCK; yy++)
+ p[xx+yy*p_lcd->xres] = c;
+ i++;
+ }
+ }
+#undef BLOCK
+#else
+ memset((void *)my_fb_info->fb_virt_start, 0, my_fb_info->fb_size);
+#endif
+
+ screen_info.rsvd_size = 0;
+ screen_info.red_size = au1100fb_defined.red.length;
+ screen_info.green_size = au1100fb_defined.green.length;
+ screen_info.blue_size = au1100fb_defined.blue.length;
+ screen_info.rsvd_pos = 0;
+ screen_info.red_pos = au1100fb_defined.red.offset;
+ screen_info.green_pos = au1100fb_defined.green.offset;
+ screen_info.blue_pos = au1100fb_defined.blue.offset;
+ screen_info.lfb_base = my_fb_info->fb_virt_start;
+ screen_info.lfb_width = au1100fb_defined.xres;
+ screen_info.lfb_height = au1100fb_defined.yres;
+ screen_info.lfb_depth = au1100fb_defined.bits_per_pixel;
+ screen_info.lfb_linelength = au1100fb_fix.line_length;
+ screen_info.lfb_size = my_fb_info->fb_size;
+
+ if (au1100fb_defined.bits_per_pixel <= 8) {
+ depth = au1100fb_defined.green.length;
+ au1100fb_defined.red.length =
+ au1100fb_defined.green.length =
+ au1100fb_defined.blue.length =
+ au1100fb_defined.bits_per_pixel;
+ }
+
+ printk(KERN_INFO "au1100fb: %s: "
+ "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
+ (au1100fb_defined.bits_per_pixel > 8) ?
+ "Truecolor" : "Pseudocolor",
+ screen_info.rsvd_size,
+ screen_info.red_size,
+ screen_info.green_size,
+ screen_info.blue_size,
+ screen_info.rsvd_pos,
+ screen_info.red_pos,
+ screen_info.green_pos,
+ screen_info.blue_pos);
+
+ info->fbops = &au1100fb_ops;
+ info->var = au1100fb_defined;
+ info->fix = au1100fb_fix;
+ info->flags = FBINFO_FLAG_DEFAULT;
+
+ if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+ err = -ENXIO;
+ goto err;
+ }
+ if (register_framebuffer(info)<0) {
+ err = -EINVAL;
+ fb_dealloc_cmap(&info->cmap);
+ goto err;
+ }
+ printk(KERN_INFO "fb%d: %s frame buffer device\n",
+ info->node, info->fix.id);
/* set freqctrl now to allow more time to stabilize */
/* zero-out out LCD bits */
+#ifdef CONFIG_WWPC
+ {
+ unsigned long t;
+
+ t = au_readl(SYS_FREQCTRL1) & ~(0x3ff);
+ printk("before SYS_FREQCTRL1 is %08lx\n", t);
+ t |= (1 << 1) | (9 << 2);
+ au_writel(t, SYS_FREQCTRL1);
+ printk("after SYS_FREQCTRL1 is %08lx\n", t);
+ }
+ sys_clksrc = au_readl(SYS_CLKSRC) & ~( (1<<9) | (1<<8) | (1<<7) | (1<<6) | (1<<5) );
+ sys_clksrc |= (1<<9) | (1<<7);
+ au_writel(sys_clksrc, SYS_CLKSRC);
+#else
sys_clksrc = au_readl(SYS_CLKSRC) & ~0x000003e0;
sys_clksrc |= p_lcd->mode_toyclksrc;
au_writel(sys_clksrc, SYS_CLKSRC);
+#endif
- /* FIXME add check to make sure auxpll is what is expected! */
+ /* setup LCD */
au1100_setmode();
- fb_info.gen.parsize = sizeof(struct au1100fb_par);
- fb_info.gen.fbhw = &au1100_switch;
-
- strcpy(fb_info.gen.info.modename, "Au1100 LCD");
- fb_info.gen.info.changevar = NULL;
- fb_info.gen.info.node = -1;
-
- fb_info.gen.info.fbops = &au1100fb_ops;
- fb_info.gen.info.disp = &disp;
- fb_info.gen.info.switch_con = &fbgen_switch;
- fb_info.gen.info.updatevar = &fbgen_update_var;
- fb_info.gen.info.blank = &fbgen_blank;
- fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
-
- /* This should give a reasonable default video mode */
- fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
- fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
- fbgen_set_disp(-1, &fb_info.gen);
- fbgen_install_cmap(0, &fb_info.gen);
- if (register_framebuffer(&fb_info.gen.info) < 0)
- return -EINVAL;
- printk(KERN_INFO "fb%d: %s frame buffer device\n",
- GET_FB_IDX(fb_info.gen.info.node),
- fb_info.gen.info.modename);
-
return 0;
+err:
+ framebuffer_release(info);
+ return err;
}
+static struct device_driver au1100fb_driver = {
+ .name = "au1100fb",
+ .bus = &platform_bus_type,
+ .probe = au1100fb_probe,
+};
-void au1100fb_cleanup(struct fb_info *info)
-{
- unregister_framebuffer(info);
-}
-
+static struct platform_device au1100fb_device = {
+ .name = "au1100fb",
+};
-void au1100fb_setup(char *options, int *ints)
+int __init au1100fb_init(void)
{
- char* this_opt;
- int i;
- int num_panels = sizeof(panels)/sizeof(struct known_lcd_panels);
-
-
- if (!options || !*options)
- return;
-
- for(this_opt=strtok(options, ","); this_opt;
- this_opt=strtok(NULL, ",")) {
- if (!strncmp(this_opt, "panel:", 6)) {
-#if defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100)
- /* Read Pb1100 Switch S10 ? */
- if (!strncmp(this_opt+6, "s10", 3))
- {
- int panel;
- panel = *(volatile int *)0xAE000008; /* BCSR SWITCHES */
- panel >>= 8;
- panel &= 0x0F;
- if (panel >= num_panels) panel = 0;
- my_lcd_index = panel;
- }
- else
-#endif
- /* Get the panel name, everything else if fixed */
- for (i=0; i<num_panels; i++) {
- if (!strncmp(this_opt+6, panels[i].panel_name,
- strlen(this_opt))) {
- my_lcd_index = i;
- break;
- }
- }
- }
- else if (!strncmp(this_opt, "nohwcursor", 10)) {
- printk("nohwcursor\n");
- fb_info.nohwcursor = 1;
- }
- }
-
- printk("au1100fb: Panel %d %s\n", my_lcd_index,
- panels[my_lcd_index].panel_name);
-}
-
+ int ret;
+ char *option = NULL;
+ /* ignore error return of fb_get_options */
+ fb_get_options("au1100fb", &option);
+ au1100fb_setup(option);
+ ret = driver_register(&au1100fb_driver);
+
+ if (!ret) {
+ ret = platform_device_register(&au1100fb_device);
+ if (ret)
+ driver_unregister(&au1100fb_driver);
+ }
+ return ret;
+}
+module_init(au1100fb_init);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
-#ifdef MODULE
MODULE_LICENSE("GPL");
-int init_module(void)
-{
- return au1100fb_init();
-}
-
-void cleanup_module(void)
-{
- au1100fb_cleanup(void);
-}
-
-MODULE_AUTHOR("Pete Popov <ppopov@mvista.com>");
-MODULE_DESCRIPTION("Au1100 LCD framebuffer device driver");
-#endif /* MODULE */
Index: drivers/video/au1100fb.h
===================================================================
RCS file: /home/cvs/linux/drivers/video/au1100fb.h,v
retrieving revision 1.1
diff -u -r1.1 au1100fb.h
--- drivers/video/au1100fb.h 14 Jul 2002 21:33:34 -0000 1.1
+++ drivers/video/au1100fb.h 12 Jan 2005 09:05:31 -0000
@@ -191,6 +191,39 @@
*/
struct known_lcd_panels panels[] =
{
+#ifdef CONFIG_WWPC
+ { /* just the standard LCD */
+ 240, /* xres */
+ 320, /* yres */
+ 16, /* bpp */
+
+ "WWPC LCD",
+
+ /* mode_control */
+ 0x0006806A,
+
+ /* mode_horztiming */
+ 0x0A1010EF,
+
+ /* mode_verttiming */
+ 0x0301013F,
+
+ /* mode_clkcontrol */
+ 0x00018001,
+
+ /* mode_pwmdiv */
+ 0,
+
+ /* mode_pwmhi */
+ 0,
+
+ /* mode_toyclksrc */
+ 0, /* not used */
+
+ /* mode_backlight */
+ 0 /* not used */
+ }
+#else
{ /* 0: Pb1100 LCDA: Sharp 320x240 TFT panel */
320, /* xres */
240, /* yres */
@@ -377,5 +410,6 @@
/* mode_backlight */
7
},
+#endif
};
#endif /* _AU1100LCD_H */
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
next reply other threads:[~2005-01-12 9:54 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-01-12 9:50 Christian [this message]
2005-02-02 9:05 ` [PATCH] au1100fb.c ported from 2.4 to 2.6 Ulrich Eckhardt
2005-02-04 9:56 ` Christian
2005-02-04 13:18 ` Ulrich Eckhardt
2005-02-08 14:14 ` Ulrich Eckhardt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1105523407.5654.18.camel@absolute.ascensit.com \
--to=c.pellegrin@exadron.com \
--cc=linux-mips@linux-mips.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.