aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Kconfig18
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/backlight/Kconfig8
-rw-r--r--drivers/video/backlight/Makefile1
-rw-r--r--drivers/video/backlight/hp680_bl.c44
-rw-r--r--drivers/video/backlight/jornada720_bllcd.c309
-rw-r--r--drivers/video/s1d13mp900fb.c282
-rw-r--r--drivers/video/s1d13xxxfb.c25
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;