From f62e770b25bdc24e18c9191fe2ca3e159036bd79 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 6 Feb 2008 01:39:41 -0800 Subject: [PATCH] FB/S3C2412: add S3C2412 support to S3C2410 fb driver Add support for the S3C2412 to the S3C2410 frame buffer driver by ensuring that any moved registers can be dealt with. Signed-off-by: Ben Dooks Cc: "Antonino A. Daplas" Cc: Vincent Sanders Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/s3c2410fb.c | 78 ++++++++++++++++++++----- drivers/video/s3c2410fb.h | 7 +++ include/asm-arm/arch-s3c2410/regs-lcd.h | 15 ++++- 3 files changed, 82 insertions(+), 18 deletions(-) diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index b3c31d9dc591..628b9e67f0ca 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -110,6 +110,11 @@ static int debug = 0; /* useful functions */ +static int is_s3c2412(struct s3c2410fb_info *fbi) +{ + return (fbi->drv_type == DRV_S3C2412); +} + /* s3c2410fb_set_lcdaddr * * initialise lcd controller address pointers @@ -501,7 +506,7 @@ static void schedule_palette_update(struct s3c2410fb_info *fbi, { unsigned long flags; unsigned long irqen; - void __iomem *regs = fbi->io; + void __iomem *irq_base = fbi->irq_base; local_irq_save(flags); @@ -511,9 +516,9 @@ static void schedule_palette_update(struct s3c2410fb_info *fbi, fbi->palette_ready = 1; /* enable IRQ */ - irqen = readl(regs + S3C2410_LCDINTMSK); + irqen = readl(irq_base + S3C24XX_LCDINTMSK); irqen &= ~S3C2410_LCDINT_FRSYNC; - writel(irqen, regs + S3C2410_LCDINTMSK); + writel(irqen, irq_base + S3C24XX_LCDINTMSK); } local_irq_restore(flags); @@ -594,15 +599,17 @@ static int s3c2410fb_setcolreg(unsigned regno, static int s3c2410fb_blank(int blank_mode, struct fb_info *info) { struct s3c2410fb_info *fbi = info->par; - void __iomem *regs = fbi->io; + void __iomem *tpal_reg = fbi->io; dprintk("blank(mode=%d, info=%p)\n", blank_mode, info); + tpal_reg += is_s3c2412(fbi) ? S3C2412_TPAL : S3C2410_TPAL; + if (blank_mode == FB_BLANK_UNBLANK) - writel(0x0, regs + S3C2410_TPAL); + writel(0x0, tpal_reg); else { dprintk("setting TPAL to output 0x000000\n"); - writel(S3C2410_TPAL_EN, regs + S3C2410_TPAL); + writel(S3C2410_TPAL_EN, tpal_reg); } return 0; @@ -709,6 +716,16 @@ static int s3c2410fb_init_registers(struct fb_info *info) struct s3c2410fb_mach_info *mach_info = fbi->dev->platform_data; unsigned long flags; void __iomem *regs = fbi->io; + void __iomem *tpal; + void __iomem *lpcsel; + + if (is_s3c2412(fbi)) { + tpal = regs + S3C2412_TPAL; + lpcsel = regs + S3C2412_TCONSEL; + } else { + tpal = regs + S3C2410_TPAL; + lpcsel = regs + S3C2410_LPCSEL; + } /* Initialise LCD with values from haret */ @@ -724,12 +741,12 @@ static int s3c2410fb_init_registers(struct fb_info *info) local_irq_restore(flags); dprintk("LPCSEL = 0x%08lx\n", mach_info->lpcsel); - writel(mach_info->lpcsel, regs + S3C2410_LPCSEL); + writel(mach_info->lpcsel, lpcsel); - dprintk("replacing TPAL %08x\n", readl(regs + S3C2410_TPAL)); + dprintk("replacing TPAL %08x\n", readl(tpal)); /* ensure temporary palette disabled */ - writel(0x00, regs + S3C2410_TPAL); + writel(0x00, tpal); return 0; } @@ -763,15 +780,15 @@ static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi) static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) { struct s3c2410fb_info *fbi = dev_id; - void __iomem *regs = fbi->io; - unsigned long lcdirq = readl(regs + S3C2410_LCDINTPND); + void __iomem *irq_base = fbi->irq_base; + unsigned long lcdirq = readl(irq_base + S3C24XX_LCDINTPND); if (lcdirq & S3C2410_LCDINT_FRSYNC) { if (fbi->palette_ready) s3c2410fb_write_palette(fbi); - writel(S3C2410_LCDINT_FRSYNC, regs + S3C2410_LCDINTPND); - writel(S3C2410_LCDINT_FRSYNC, regs + S3C2410_LCDSRCPND); + writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDINTPND); + writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDSRCPND); } return IRQ_HANDLED; @@ -779,7 +796,8 @@ static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) static char driver_name[] = "s3c2410fb"; -static int __init s3c2410fb_probe(struct platform_device *pdev) +static int __init s3c24xxfb_probe(struct platform_device *pdev, + enum s3c_drv_type drv_type) { struct s3c2410fb_info *info; struct s3c2410fb_display *display; @@ -815,6 +833,7 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) info = fbinfo->par; info->dev = &pdev->dev; + info->drv_type = drv_type; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { @@ -838,6 +857,8 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) goto release_mem; } + info->irq_base = info->io + ((drv_type == DRV_S3C2412) ? S3C2412_LCDINTBASE : S3C2410_LCDINTBASE); + dprintk("devinit\n"); strcpy(fbinfo->fix.id, driver_name); @@ -946,6 +967,16 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) return ret; } +static int __init s3c2410fb_probe(struct platform_device *pdev) +{ + return s3c24xxfb_probe(pdev, DRV_S3C2410); +} + +static int __init s3c2412fb_probe(struct platform_device *pdev) +{ + return s3c24xxfb_probe(pdev, DRV_S3C2412); +} + /* s3c2410fb_stop_lcd * * shutdown the lcd controller @@ -1047,14 +1078,31 @@ static struct platform_driver s3c2410fb_driver = { }, }; +static struct platform_driver s3c2412fb_driver = { + .probe = s3c2412fb_probe, + .remove = s3c2410fb_remove, + .suspend = s3c2410fb_suspend, + .resume = s3c2410fb_resume, + .driver = { + .name = "s3c2412-lcd", + .owner = THIS_MODULE, + }, +}; + int __init s3c2410fb_init(void) { - return platform_driver_register(&s3c2410fb_driver); + int ret = platform_driver_register(&s3c2410fb_driver); + + if (ret == 0) + ret = platform_driver_register(&s3c2412fb_driver);; + + return ret; } static void __exit s3c2410fb_cleanup(void) { platform_driver_unregister(&s3c2410fb_driver); + platform_driver_unregister(&s3c2412fb_driver); } module_init(s3c2410fb_init); diff --git a/drivers/video/s3c2410fb.h b/drivers/video/s3c2410fb.h index 6ce5dc26c5f7..dbb73b95e2ef 100644 --- a/drivers/video/s3c2410fb.h +++ b/drivers/video/s3c2410fb.h @@ -25,13 +25,20 @@ #ifndef __S3C2410FB_H #define __S3C2410FB_H +enum s3c_drv_type { + DRV_S3C2410, + DRV_S3C2412, +}; + struct s3c2410fb_info { struct device *dev; struct clk *clk; struct resource *mem; void __iomem *io; + void __iomem *irq_base; + enum s3c_drv_type drv_type; struct s3c2410fb_hw regs; unsigned int palette_ready; diff --git a/include/asm-arm/arch-s3c2410/regs-lcd.h b/include/asm-arm/arch-s3c2410/regs-lcd.h index 76fe5f693426..bd854845697f 100644 --- a/include/asm-arm/arch-s3c2410/regs-lcd.h +++ b/include/asm-arm/arch-s3c2410/regs-lcd.h @@ -147,7 +147,16 @@ #define S3C2412_FRCPAT(x) S3C2410_LCDREG(0xB4 + ((x)*4)) +/* general registers */ + +/* base of the LCD registers, where INTPND, INTSRC and then INTMSK + * are available. */ + +#define S3C2410_LCDINTBASE S3C2410_LCDREG(0x54) +#define S3C2412_LCDINTBASE S3C2410_LCDREG(0x24) + +#define S3C24XX_LCDINTPND (0x00) +#define S3C24XX_LCDSRCPND (0x04) +#define S3C24XX_LCDINTMSK (0x08) + #endif /* ___ASM_ARCH_REGS_LCD_H */ - - -