diff options
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/Kconfig | 18 | ||||
-rw-r--r-- | drivers/video/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/backlight/Kconfig | 8 | ||||
-rw-r--r-- | drivers/video/backlight/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/backlight/hp680_bl.c | 44 | ||||
-rw-r--r-- | drivers/video/backlight/jornada720_bllcd.c | 309 | ||||
-rw-r--r-- | drivers/video/s1d13mp900fb.c | 282 | ||||
-rw-r--r-- | drivers/video/s1d13xxxfb.c | 25 |
8 files changed, 661 insertions, 27 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index e0c5f96b273d15..61e5fd504157a3 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -955,6 +955,24 @@ config FB_ATMEL_STN If unsure, say N. +config FB_S1D13MP900 + tristate "Experimental S1D13806 framebuffer support for MP900/C" + depends on FB + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Support for S1D13XXX framebuffer device family + on the NEC MobilePro900/c. + + This really should not be needed as the existing S1D13XXX + driver should be able to accomodate the Mobilepro900 with a + few tweaks... + + Preliminary backlight/blanking support included in this + driver would be better placed somewhere like + drivers/video/backlight/mp900_bl.c + config FB_NVIDIA tristate "nVidia Framebuffer Support" depends on FB && PCI diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 04bca35403ff6d..78265ffeac857e 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -106,6 +106,7 @@ obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o obj-$(CONFIG_FB_MAXINE) += maxinefb.o obj-$(CONFIG_FB_METRONOME) += metronomefb.o obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o +obj-$(CONFIG_FB_S1D13MP900) += s1d13mp900fb.o obj-$(CONFIG_FB_IMX) += imxfb.o obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index dcd8073c236930..5b93e91358361c 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -97,6 +97,14 @@ config BACKLIGHT_HP680 If you have a HP Jornada 680, say y to enable the backlight driver. +config BACKLIGHT_HP7XX + tristate "HP Jornada 7xx LCD/Backlight Driver" + depends on BACKLIGHT_CLASS_DEVICE && SA1100_JORNADA720 + default y + help + If you have a HP Jornada 710/720/728, say y to enable + the LCD/BL driver. + config BACKLIGHT_PROGEAR tristate "Frontpath ProGear Backlight Driver" depends on BACKLIGHT_CLASS_DEVICE && PCI && X86 diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 33f6c7cecc73ef..925d50bb95540e 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o obj-$(CONFIG_BACKLIGHT_CORGI) += corgi_bl.o obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o +obj-$(CONFIG_BACKLIGHT_HP7XX) += jornada720_bllcd.o obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c index fbea2bd129c73d..9badb23c1ef813 100644 --- a/drivers/video/backlight/hp680_bl.c +++ b/drivers/video/backlight/hp680_bl.c @@ -1,6 +1,7 @@ /* * Backlight Driver for HP Jornada 680 * + * Copyright (c) 2007 Kristoffer Ericson * Copyright (c) 2005 Andriy Skulysh * * Based on Sharp's Corgi Backlight Driver @@ -27,11 +28,13 @@ static int hp680bl_suspended; static int current_intensity = 0; -static DEFINE_SPINLOCK(bl_lock); +static DEFINE_SPINLOCK(jornada_bl_lock); +unsigned long jornada_flags; +static struct platform_device *hp680_platform_device; +static struct backlight_device *hp680_backlight_device; static void hp680bl_send_intensity(struct backlight_device *bd) { - unsigned long flags; u16 v; int intensity = bd->props.brightness; @@ -42,7 +45,7 @@ static void hp680bl_send_intensity(struct backlight_device *bd) if (hp680bl_suspended) intensity = 0; - spin_lock_irqsave(&bl_lock, flags); + spin_lock_irqsave(&jornada_bl_lock, jornada_flags); if (intensity && current_intensity == 0) { sh_dac_enable(DAC_LCD_BRIGHTNESS); v = inw(HD64461_GPBDR); @@ -58,17 +61,19 @@ static void hp680bl_send_intensity(struct backlight_device *bd) } else if (intensity) { sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS); } - spin_unlock_irqrestore(&bl_lock, flags); + spin_unlock_irqrestore(&jornada_bl_lock, jornada_flags); current_intensity = intensity; + } - #ifdef CONFIG_PM static int hp680bl_suspend(struct platform_device *pdev, pm_message_t state) { struct backlight_device *bd = platform_get_drvdata(pdev); + bd->props.power = FB_BLANK_POWERDOWN; + hp680bl_suspended = 1; hp680bl_send_intensity(bd); return 0; @@ -78,6 +83,8 @@ static int hp680bl_resume(struct platform_device *pdev) { struct backlight_device *bd = platform_get_drvdata(pdev); + bd->props.power = FB_BLANK_UNBLANK; + hp680bl_suspended = 0; hp680bl_send_intensity(bd); return 0; @@ -105,18 +112,13 @@ static struct backlight_ops hp680bl_ops = { static int __init hp680bl_probe(struct platform_device *pdev) { - struct backlight_device *bd; + hp680_backlight_device = backlight_device_register ("hp680-bl", &pdev->dev, NULL, &hp680bl_ops); - bd = backlight_device_register ("hp680-bl", &pdev->dev, NULL, - &hp680bl_ops); - if (IS_ERR(bd)) - return PTR_ERR(bd); + platform_set_drvdata(pdev, hp680_backlight_device); - platform_set_drvdata(pdev, bd); - - bd->props.max_brightness = HP680_MAX_INTENSITY; - bd->props.brightness = HP680_DEFAULT_INTENSITY; - hp680bl_send_intensity(bd); + hp680_backlight_device->props.max_brightness = HP680_MAX_INTENSITY; + hp680_backlight_device->props.brightness = HP680_DEFAULT_INTENSITY; + hp680bl_send_intensity(hp680_backlight_device); return 0; } @@ -144,22 +146,20 @@ static struct platform_driver hp680bl_driver = { }, }; -static struct platform_device *hp680bl_device; - static int __init hp680bl_init(void) { int ret; ret = platform_driver_register(&hp680bl_driver); if (!ret) { - hp680bl_device = platform_device_alloc("hp680-bl", -1); - if (!hp680bl_device) + hp680_platform_device = platform_device_alloc("hp680-bl", -1); + if (!hp680_platform_device) return -ENOMEM; - ret = platform_device_add(hp680bl_device); + ret = platform_device_add(hp680_platform_device); if (ret) { - platform_device_put(hp680bl_device); + platform_device_put(hp680_platform_device); platform_driver_unregister(&hp680bl_driver); } } @@ -168,7 +168,7 @@ static int __init hp680bl_init(void) static void __exit hp680bl_exit(void) { - platform_device_unregister(hp680bl_device); + platform_device_unregister(hp680_platform_device); platform_driver_unregister(&hp680bl_driver); } diff --git a/drivers/video/backlight/jornada720_bllcd.c b/drivers/video/backlight/jornada720_bllcd.c new file mode 100644 index 00000000000000..645f9bae2e776c --- /dev/null +++ b/drivers/video/backlight/jornada720_bllcd.c @@ -0,0 +1,309 @@ +/* + * + * Backlight and LCD Driver for HP Jornada 720 + * Copyright (C) 2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * or any later version as published by the Free Software Foundation. + * + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/backlight.h> +#include <linux/lcd.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/fb.h> +#include <linux/device.h> +#include <asm/hardware.h> +#include <asm/arch/jornada720.h> +#include <video/s1d13xxxfb.h> + +MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>"); +MODULE_DESCRIPTION("HP Jornada 710/720/728 Backlight/LCD Driver"); +MODULE_LICENSE("GPL"); + +/* Contrast */ +#define LCD_MAX_CONTR 0xff +#define LCD_DEF_CONTR 0x80 +/* Brightness */ +#define BL_MAX_BRIGHT 0xff +#define BL_DEF_BRIGHT 0x19 + +struct bllcd_device { + struct backlight_device *bl_device; + struct lcd_device *lcd_device; +}; + +/* + * BACKLIGHT HANDLING ROUTINES + */ +static int jornada_bl_get_brightness(struct backlight_device *dev) +{ + int ret; + + /* check if backlight is on */ + if (!(PPSR & PPC_LDD1)) + return BL_MAX_BRIGHT; + + jornada_ssp_start(); + if (jornada_ssp_inout(GETBRIGHTNESS) == -ETIMEDOUT) { + printk(KERN_ERR "bl :get brightness timeout\n"); + ret = -1; + } else + ret = jornada_ssp_inout(TXDUMMY); + + jornada_ssp_end(); + + /* 0 is max brightness */ + return BL_MAX_BRIGHT - ret; +} + +static int jornada_bl_update_status(struct backlight_device *dev) +{ + int ret = 0; + int value; + + jornada_ssp_start(); + + if (dev->props.power != FB_BLANK_UNBLANK || + dev->props.fb_blank != FB_BLANK_UNBLANK) { + ret = jornada_ssp_inout(BRIGHTNESSOFF); + if (ret == -ETIMEDOUT) { + printk(KERN_ERR "bl : brightness off timeout\n"); + /* backlight off */ + PPSR &= ~PPC_LDD1; + PPDR |= PPC_LDD1; + } + } else { /* backlight on */ + PPSR |= PPC_LDD1; + /* send setbrightness cmd */ + ret = jornada_ssp_inout(SETBRIGHTNESS); + if (ret != TXDUMMY) { + printk(KERN_ERR "bl :set brightness timeout\n"); + } else { + /* cmd accepted */ + value = BL_MAX_BRIGHT - dev->props.brightness; + if (jornada_ssp_byte(value) == TXDUMMY) + ret = value; + else + printk(KERN_ERR "bl :set brightness failed\n"); + } + } + + jornada_ssp_end(); + + return ret; +} + +/* + * LCD HANDLING FUNCTIONS + */ +static int jornada_lcd_set_contrast(struct lcd_device *pdev, int contrast) +{ + int ret = 0; + + jornada_ssp_start(); + + ret = jornada_ssp_inout(SETCONTRAST); + + if (ret == -ETIMEDOUT) + printk(KERN_ERR "lcd :set contrast timeout\n"); + else + ret = jornada_ssp_byte(contrast); + + jornada_ssp_end(); + + return ret; +} + +static int jornada_lcd_set_power(struct lcd_device *pdev, int power) +{ + if (power != FB_BLANK_UNBLANK) { + /* turn off LCD */ + PPSR &= ~PPC_LDD2; + PPDR |= PPC_LDD2; + } else { + /* turn on LCD */ + PPSR |= PPC_LDD2; + } + + return 0; +} + +static int jornada_lcd_get_power(struct lcd_device *pdev) +{ + if (PPSR & PPC_LDD2) + return FB_BLANK_UNBLANK; + else + return FB_BLANK_POWERDOWN; +} + +static int jornada_lcd_get_contrast(struct lcd_device *pdev) +{ + int ret; + + /* Don't set contrast on off powerd LCD */ + if (jornada_lcd_get_power(pdev) != FB_BLANK_UNBLANK) + return 0; + + jornada_ssp_start(); + + ret = jornada_ssp_inout(GETCONTRAST); + if (ret != -ETIMEDOUT) + ret = jornada_ssp_inout(TXDUMMY); + else { + printk(KERN_ERR "lcd :get contrast timeout\n"); + ret = -1; + } + + jornada_ssp_end(); + + return ret; +} + +static struct backlight_ops jornada_bl_ops = { + .get_brightness = jornada_bl_get_brightness, + .update_status = jornada_bl_update_status, +}; + +static struct lcd_ops jornada_lcd_ops = { + .get_contrast = jornada_lcd_get_contrast, + .set_contrast = jornada_lcd_set_contrast, + .get_power = jornada_lcd_get_power, + .set_power = jornada_lcd_set_power, +}; + +static int jornada_bl_probe(struct platform_device *pdev) +{ + struct bllcd_device *bllcd; + int ret; + +#ifdef CONFIG_SA1100_JORNADA720_FLASHROM + /* Just turn it off and on again */ + PPSR &= ~(PPC_LDD0 | PPC_LDD1 | PPC_LDD2); + PPDR |= PPC_LDD0 | PPC_LDD1 | PPC_LDD2; + LCCR3 = 0; + LCCR2 = 0; + LCCR1 = 0; + LCCR0 = 0; + DBAR1 = 0; + DBAR2 = 0; + + /* Start it in order */ + PPSR |= PPC_LDD0; + mdelay(100); + PPSR |= PPC_LDD2; + mdelay(100); + PPSR |= PPC_LDD1; +#endif + + bllcd = kzalloc(sizeof(*bllcd), GFP_KERNEL); + if (bllcd == NULL) + return -ENOMEM; + + /* bl driver - name must match fb driver name */ + bllcd->bl_device = backlight_device_register(S1D_DEVICENAME, + &pdev->dev, NULL, &jornada_bl_ops); + + if (IS_ERR(bllcd->bl_device)) { + ret = PTR_ERR(bllcd->bl_device); + printk(KERN_ERR "bl :failed to register device\n"); + kfree(bllcd); + return ret; + } + + /* lcd driver */ + bllcd->lcd_device = lcd_device_register(S1D_DEVICENAME, + &pdev->dev, NULL, &jornada_lcd_ops); + if (IS_ERR(bllcd->lcd_device)) { + ret = PTR_ERR(bllcd->lcd_device); + backlight_device_unregister(bllcd->bl_device); + printk(KERN_ERR "lcd :failed to register device\n"); + kfree(bllcd); + return ret; + } + + jornada_lcd_set_contrast(bllcd->lcd_device, LCD_DEF_CONTR); + jornada_lcd_set_power(bllcd->lcd_device, FB_BLANK_UNBLANK); + + msleep(100); + + bllcd->bl_device->props.power = FB_BLANK_UNBLANK; + bllcd->bl_device->props.brightness = BL_DEF_BRIGHT; + jornada_bl_update_status(bllcd->bl_device); + + platform_set_drvdata(pdev, bllcd); + printk(KERN_INFO "HP Jornada 7xx Backlight/LCD driver activated\n"); + + return 0; +} + +static int jornada_bl_remove(struct platform_device *pdev) +{ + struct bllcd_device *bllcd = platform_get_drvdata(pdev); + + bllcd->bl_device->props.power = FB_BLANK_POWERDOWN; + bllcd->bl_device->props.brightness = 0; + bllcd->bl_device->props.max_brightness = 0; + + backlight_device_unregister(bllcd->bl_device); + lcd_device_unregister(bllcd->lcd_device); + + return 0; +} + +static int jornada_bl_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct bllcd_device *bllcd = platform_get_drvdata(pdev); + + bllcd->bl_device->props.power = FB_BLANK_POWERDOWN; + bllcd->bl_device->props.brightness = 0; + bllcd->bl_device->props.max_brightness = 0; + jornada_bl_update_status(bllcd->bl_device); + + jornada_lcd_set_power(bllcd->lcd_device, FB_BLANK_POWERDOWN); + + return 0; +} + +static int jornada_bl_resume(struct platform_device *pdev) +{ + struct bllcd_device *bllcd = platform_get_drvdata(pdev); + + bllcd->bl_device->props.power = FB_BLANK_UNBLANK; + bllcd->bl_device->props.brightness = BL_DEF_BRIGHT; + bllcd->bl_device->props.max_brightness = BL_MAX_BRIGHT; + jornada_bl_update_status(bllcd->bl_device); + + jornada_lcd_set_power(bllcd->lcd_device, FB_BLANK_UNBLANK); + + return 0; +} + +static struct platform_driver jornada_bl_driver = { + .probe = jornada_bl_probe, + .remove = jornada_bl_remove, +#ifdef CONFIG_PM + .suspend = jornada_bl_suspend, + .resume = jornada_bl_resume, +#endif + .driver = { + .name = "jornada_bllcd", + }, +}; + +int __init jornada_bl_init(void) +{ + return platform_driver_register(&jornada_bl_driver); +} + +void __exit jornada_bl_exit(void) +{ + platform_driver_unregister(&jornada_bl_driver); +} + +module_init(jornada_bl_init); +module_exit(jornada_bl_exit); diff --git a/drivers/video/s1d13mp900fb.c b/drivers/video/s1d13mp900fb.c new file mode 100644 index 00000000000000..3248004d41fa3f --- /dev/null +++ b/drivers/video/s1d13mp900fb.c @@ -0,0 +1,282 @@ +/* drivers/video/s1d13mp900fb.c + * + * IT IS NOT INTENDED THAT THIS FILE BE SUBMITTED TO VANILLA + * + * for now this is a standalone driver for testing the + * specifics of the MobilePro->S1D13806 interface + * + * the existing s1d13xxxfb.c driver should work with the Mobilepro900c + * if it is told where in memory to find the chip + * physical addresses: + * base/registers 0x0c00_0000 + * framebuffer 0x0c20_0000 + * and initial register settings + * TODO establish default register values + * perhaps all that belongs in + * arch/arm/mach-pxa/mp900.c + * + * blanking/backlight specific code should go in + * drivers/video/backlight/mp900_bl.c or so + * + * Michael Petchkovsky mkpetch@internode.on.net May 2007 + */ + +/* TODO + * clear hardware cursor + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/interrupt.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/fb.h> +#include <linux/init.h> + +#include <linux/ioport.h> +#include <linux/device.h> +#include <linux/dma-mapping.h> + +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/hardware.h> + +#include "console/fbcon.h" + +#define PFX "s1d13mp900fb: " +#define S1D13MP900_FB_PHYS 0x0C200000 +#define S1D13MP900_REG_PHYS 0x0C000000 +#define S1D13MP900_FB_SIZE 0x00140000 + +u32 pseudo_pal[16]; +static void *remapped_regs; +static void *remapped_fb; +struct fb_info fb_info; + +static int s1d13mp900fb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *fb_info) +{ + int bpp, m = 0; + + bpp = fb_info->var.bits_per_pixel; + m = (bpp <= 8) ? (1 << bpp) : 256; + if (regno >= m) { + printk("regno %d out of range (max %d)\n", regno, m); + return -EINVAL; + } + switch (bpp) { + case 8: + break; + case 16: + pseudo_pal[regno] = ((red & 0xF800) | + ((green & 0xFC00) >> 5) | + ((blue & 0xF800) >> 11)); + break; + } + + return 0; +} + +static int s1d13mp900fb_blank(int blank, struct fb_info *info) +{ + u32 rval; + switch (blank) { + case FB_BLANK_POWERDOWN: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_NORMAL: + /* we want to switch off the backlight via + * the s1d13xxx gpio pins and put the chip + * to sleep + * + * gpio pins are controlled through register + * 0x08/0x09, we clear pins 4,1,2 and set pin 0 + * + * this could be done by + * writel(0x0001, remapped_regs + 0x8) + * but safer to read initial values and set pins + * one-by-one, delays could be introduced between + * steps if required... + */ + rval = readl(remapped_regs + 0x8); + rval &= 0xffef; + writel(rval, remapped_regs + 0x8); + rval &= 0xfffd; + writel(rval, remapped_regs + 0x8); + rval &= 0xfffd; + writel(rval, remapped_regs + 0x8); + rval |= 1; + writel(rval, remapped_regs + 0x8); + /* power save config register is at 0x1f0 + * set it to 0x11 for zzz and 0x10 to wake + */ + writel(0x11, remapped_regs + 0x1f0); + /* after this it would be safe to shutdown + * pixel and memory clocks, read 0x1f1 to + * confirm sleep-mode entered + * + * perhaps PWM0 clock can be disabled with + * backlight off to save a little power + */ + break; + + case FB_BLANK_UNBLANK: + /* we reverse the blanking sequence */ + writel(0x10, remapped_regs + 0x1f0); + rval = readl(remapped_regs + 0x8); + rval &= 0xfffe; + writel(rval, remapped_regs + 0x8); + rval |= 4; + writel(rval, remapped_regs + 0x8); + rval |= 2; + writel(rval, remapped_regs + 0x8); + /* want a delay here? */ + rval |= 0x10; + writel(rval, remapped_regs + 0x8); + } + + return 0; +} + +struct s1d13mp900fb_par { + void __iomem *regs; + unsigned char display; +}; + +static struct fb_fix_screeninfo s1d13mp900fb_fix __initdata = { + .id = "S1DMP_FBID", +// .smem_len = (640 * 240 * 16) / 8, //TODO check this + .smem_len = S1D13MP900_FB_SIZE, + .smem_start = S1D13MP900_FB_PHYS, + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, + .line_length = (640 * 16) / 8, + .type_aux = 0, + .xpanstep = 0, + .ypanstep = 1, + .ywrapstep = 0, + .accel = FB_ACCEL_NONE, +}; + +static struct fb_var_screeninfo s1d13mp900fb_screeninfo = { + .xres = 640, + .yres = 240, + .xres_virtual = 640, + .yres_virtual = 240, + .bits_per_pixel = 16, + .red.length = 5, + .green.length = 6, + .blue.length = 5, + .transp.length = 0, + .red.offset = 11, + .green.offset = 5, + .blue.offset = 0, + .transp.offset = 0, + .activate = FB_ACTIVATE_NOW, + .height = -1, + .width = -1, + .vmode = FB_VMODE_NONINTERLACED, + .accel_flags = 0, + .nonstd = 0, +}; + +static struct fb_ops s1d13mp900fb_ops = { + .owner = THIS_MODULE, + .fb_setcolreg = s1d13mp900fb_setcolreg, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +// .fb_cursor = soft_cursor, + .fb_blank = s1d13mp900fb_blank, +}; + +/* colour lookup tables? l8r if we need them + */ + +unsigned char LUT8[256*3]; + +//static char lut_base[90]; + +void s1d13mp900fb_init_hardware (void) +{ +// unsigned char *pLUT = LUT8; +// unsigned char *pseed = lut_base; +// unsigned char plast[3]; +// int i, j, rgb; + int rval; + + /* OK let's assume chip has been set up by bootloader for now + * this would be a good chance to take a peek at the regs ;) + * TODO let's not assume... + */ + + rval = readb(remapped_regs); + printk (KERN_INFO PFX "reg[0x000] revision code is 0x%X\n", rval); +} + +int __init s1d13mp900fb_init(void) +{ + if (fb_get_options("s1d13mp900fb", NULL)) + return -ENODEV; + + printk (KERN_INFO PFX "initing now...\n"); + + /* remap framebuffer and registers */ + + /* do we need to request_mem_region ? */ + if (!request_mem_region(S1D13MP900_FB_PHYS, + S1D13MP900_FB_SIZE, "s1d13806_fb")) { + printk (KERN_ERR PFX "unable to reserve framebuffer\n"); + } else { + remapped_fb = ioremap_nocache(S1D13MP900_FB_PHYS, + S1D13MP900_FB_SIZE); + if (!remapped_fb) + printk (KERN_INFO PFX "unable to map framebuffer\n"); + } + + if (!request_mem_region(S1D13MP900_REG_PHYS, 512, "s1d13806_regs")) { + printk (KERN_ERR PFX "unable to reserve registers\n"); + } else { + remapped_regs = ioremap_nocache(S1D13MP900_REG_PHYS, 512); + if (!remapped_regs) + printk(KERN_ERR PFX "unable to map registers\n"); + } + + fb_info.screen_base = remapped_fb; + fb_info.screen_size = S1D13MP900_FB_SIZE; //TODO correct?? + memset(&fb_info.var, 0, sizeof(fb_info.var)); + + s1d13mp900fb_init_hardware(); + /* you could zero out the display here with memset */ + + fb_info.fbops = &s1d13mp900fb_ops; + fb_info.var = s1d13mp900fb_screeninfo; + fb_info.fix = s1d13mp900fb_fix; + fb_info.flags = FBINFO_DEFAULT; + fb_info.pseudo_palette= &pseudo_pal; + + if (register_framebuffer(&fb_info) < 0) + return 1; + + return 0; +} + +static void __exit s1d13mp900fb_exit(void) +{ + printk (KERN_INFO PFX "unregistering framebuffer device\n"); + iounmap(remapped_regs); + iounmap(remapped_fb); + release_mem_region(S1D13MP900_REG_PHYS, 512); + release_mem_region(S1D13MP900_FB_PHYS, S1D13MP900_FB_SIZE); + unregister_framebuffer(&fb_info); +} + +module_init(s1d13mp900fb_init); +module_exit(s1d13mp900fb_exit); +MODULE_AUTHOR("Michael Petchkovsky"); +MODULE_DESCRIPTION("Epson S1D13806 fb interface for NEC MobilePro900/c"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c index b829dc7c5edfeb..46fa88f1491e1f 100644 --- a/drivers/video/s1d13xxxfb.c +++ b/drivers/video/s1d13xxxfb.c @@ -50,6 +50,11 @@ #define dbg(fmt, args...) do { } while (0) #endif +static const int __devinitconst s1d13xxxfb_revisions[] = { + S1D13506_CHIP_REV, /* Rev.4 on HP Jornada 7xx S1D13506 */ + S1D13806_CHIP_REV /* Rev.7 on .. */ +}; + /* * Here we define the default struct fb_fix_screeninfo */ @@ -538,6 +543,7 @@ s1d13xxxfb_probe(struct platform_device *pdev) struct fb_info *info; struct s1d13xxxfb_pdata *pdata = NULL; int ret = 0; + int i; u8 revision; dbg("probe called: device is %p\n", pdev); @@ -607,13 +613,22 @@ s1d13xxxfb_probe(struct platform_device *pdev) goto bail; } - revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE); - if ((revision >> 2) != S1D_CHIP_REV) { - printk(KERN_INFO PFX "chip not found: %i\n", (revision >> 2)); - ret = -ENODEV; + revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) >> 2; + + ret = -ENODEV; + + for (i = 0; i < ARRAY_SIZE(s1d13xxxfb_revisions); i++) { + if (revision == s1d13xxxfb_revisions[i]) + ret = 0; + } + + if (!ret) + printk(KERN_INFO PFX "chip revision %i\n", (revision)); + else { + printk(KERN_INFO PFX "unknown chip revision %i\n", (revision)); goto bail; } - + info->fix = s1d13xxxfb_fix; info->fix.mmio_start = pdev->resource[1].start; info->fix.mmio_len = pdev->resource[1].end - pdev->resource[1].start +1; |