linux-fbdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch 0/5] fb driver patches for next kernel
@ 2008-06-22 21:04 Ben Dooks
  2008-06-22 21:04 ` [patch 1/5] SM501: Add inversion controls for VBIASEN and FPEN Ben Dooks
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Ben Dooks @ 2008-06-22 21:04 UTC (permalink / raw)
  To: linux-fbdev-devel, akpm; +Cc: linux-arm-kernel

This is a series of patches for sm501 updates,
support for the ili9320 intelligent lcd interface
controller and a generic lcd power via platform device.

All are against -rc7 with next20080620.

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [patch 1/5] SM501: Add inversion controls for VBIASEN and FPEN
  2008-06-22 21:04 [patch 0/5] fb driver patches for next kernel Ben Dooks
@ 2008-06-22 21:04 ` Ben Dooks
  2008-06-22 21:04 ` [patch 2/5] SM501: Restructure init to allow only 1 fb on an SM501 Ben Dooks
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: Ben Dooks @ 2008-06-22 21:04 UTC (permalink / raw)
  To: linux-fbdev-devel, akpm; +Cc: linux-arm-kernel, Ben Dooks

[-- Attachment #1: simtec/simtec-drivers-fb-sm501-ctrlinvert.patch --]
[-- Type: text/plain, Size: 3049 bytes --]

Add flags to allow the driver to invert the sense of
both VBIASEN and FPEN signals comming from the SM501.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Index: linux-2.6.26-rc4-quilt3/drivers/video/sm501fb.c
===================================================================
--- linux-2.6.26-rc4-quilt3.orig/drivers/video/sm501fb.c	2008-05-26 23:17:37.000000000 +0100
+++ linux-2.6.26-rc4-quilt3/drivers/video/sm501fb.c	2008-05-29 10:53:18.000000000 +0100
@@ -663,15 +663,25 @@ static void sm501fb_panel_power(struct s
 		sm501fb_sync_regs(fbi);
 		mdelay(10);
 
+		/* VBIASEN */
+
 		if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) {
-			control |= SM501_DC_PANEL_CONTROL_BIAS;	/* VBIASEN */
+			if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN)
+				control &= ~SM501_DC_PANEL_CONTROL_BIAS;
+			else
+				control |= SM501_DC_PANEL_CONTROL_BIAS;
+
 			writel(control, ctrl_reg);
 			sm501fb_sync_regs(fbi);
 			mdelay(10);
 		}
 
 		if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) {
-			control |= SM501_DC_PANEL_CONTROL_FPEN;
+			if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN)
+				control &= ~SM501_DC_PANEL_CONTROL_FPEN;
+			else
+				control |= SM501_DC_PANEL_CONTROL_FPEN;
+
 			writel(control, ctrl_reg);
 			sm501fb_sync_regs(fbi);
 			mdelay(10);
@@ -679,14 +689,22 @@ static void sm501fb_panel_power(struct s
 	} else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) {
 		/* disable panel power */
 		if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) {
-			control &= ~SM501_DC_PANEL_CONTROL_FPEN;
+			if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN)
+				control |= SM501_DC_PANEL_CONTROL_FPEN;
+			else
+				control &= ~SM501_DC_PANEL_CONTROL_FPEN;
+
 			writel(control, ctrl_reg);
 			sm501fb_sync_regs(fbi);
 			mdelay(10);
 		}
 
 		if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) {
-			control &= ~SM501_DC_PANEL_CONTROL_BIAS;
+			if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN)
+				control |= SM501_DC_PANEL_CONTROL_BIAS;
+			else
+				control &= ~SM501_DC_PANEL_CONTROL_BIAS;
+
 			writel(control, ctrl_reg);
 			sm501fb_sync_regs(fbi);
 			mdelay(10);
Index: linux-2.6.26-rc4-quilt3/include/linux/sm501.h
===================================================================
--- linux-2.6.26-rc4-quilt3.orig/include/linux/sm501.h	2008-05-27 20:25:43.000000000 +0100
+++ linux-2.6.26-rc4-quilt3/include/linux/sm501.h	2008-05-29 10:54:40.000000000 +0100
@@ -73,6 +73,8 @@ extern unsigned long sm501_gpio_get(stru
 #define SM501FB_FLAG_USE_HWACCEL	(1<<3)
 #define SM501FB_FLAG_PANEL_NO_FPEN	(1<<4)
 #define SM501FB_FLAG_PANEL_NO_VBIASEN	(1<<5)
+#define SM501FB_FLAG_PANEL_INV_FPEN	(1<<6)
+#define SM501FB_FLAG_PANEL_INV_VBIASEN	(1<<7)
 
 struct sm501_platdata_fbsub {
 	struct fb_videomode	*def_mode;

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [patch 2/5] SM501: Restructure init to allow only 1 fb on an SM501
  2008-06-22 21:04 [patch 0/5] fb driver patches for next kernel Ben Dooks
  2008-06-22 21:04 ` [patch 1/5] SM501: Add inversion controls for VBIASEN and FPEN Ben Dooks
@ 2008-06-22 21:04 ` Ben Dooks
  2008-06-24  6:54   ` Andrew Morton
  2008-06-22 21:04 ` [patch 3/5] FB: Add support for the ILI9320 video display controller Ben Dooks
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 11+ messages in thread
From: Ben Dooks @ 2008-06-22 21:04 UTC (permalink / raw)
  To: linux-fbdev-devel, akpm; +Cc: linux-arm-kernel, Ben Dooks

[-- Attachment #1: simtec/simtec-drivers-fb-sm501-onefb.patch --]
[-- Type: text/plain, Size: 11138 bytes --]

Add the ability to register only one of the two possible
main framebuffer devices on the SM501 by passing platform
data for only the framebuffer that you are interested in
having.

As a side note, we update the init sequence to commonise
the code that is executed twice, and fix a pair of missing
frees that we didn't do on framebuffer exit, such as freeing
the fb's cmap.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Index: linux-2.6.26-rc6-quilt1/drivers/video/sm501fb.c
===================================================================
--- linux-2.6.26-rc6-quilt1.orig/drivers/video/sm501fb.c	2008-06-18 19:02:14.000000000 +0100
+++ linux-2.6.26-rc6-quilt1/drivers/video/sm501fb.c	2008-06-18 19:48:01.000000000 +0100
@@ -143,6 +143,8 @@ static int sm501_alloc_mem(struct sm501f
 			   unsigned int why, size_t size)
 {
 	unsigned int ptr = 0;
+	unsigned int end;
+	struct fb_info *fbi;
 
 	switch (why) {
 	case SM501_MEMF_CURSOR:
@@ -152,7 +154,9 @@ static int sm501_alloc_mem(struct sm501f
 
 	case SM501_MEMF_PANEL:
 		ptr = inf->fbmem_len - size;
-		if (ptr < inf->fb[0]->fix.smem_len)
+		fbi = inf->fb[0];
+
+		if (fbi && ptr < fbi->fix.smem_len)
 			return -ENOMEM;
 
 		break;
@@ -162,11 +166,18 @@ static int sm501_alloc_mem(struct sm501f
 		break;
 
 	case SM501_MEMF_ACCEL:
-		ptr = inf->fb[0]->fix.smem_len;
+		fbi = inf->fb[0];
+		ptr = fbi ? fbi->fix.smem_len : 0;
+
+		fbi = inf->fb[1];
+		if (fbi)
+			end = (fbi->fix.smem_start - inf->fbmem_res->start);
+		else
+			end = inf->fbmem_len;
 
-		if ((ptr + size) >
-		    (inf->fb[1]->fix.smem_start - inf->fbmem_res->start))
+		if ((ptr + size) > end)
 			return -ENOMEM;
+
 		break;
 
 	default:
@@ -1228,39 +1239,6 @@ static struct fb_ops sm501fb_ops_pnl = {
 	.fb_imageblit	= cfb_imageblit,
 };
 
-/* sm501fb_info_alloc
- *
- * creates and initialises an sm501fb_info structure
-*/
-
-static struct sm501fb_info *sm501fb_info_alloc(struct fb_info *fbinfo_crt,
-					       struct fb_info *fbinfo_pnl)
-{
-	struct sm501fb_info *info;
-	struct sm501fb_par  *par;
-
-	info = kzalloc(sizeof(struct sm501fb_info), GFP_KERNEL);
-	if (info) {
-		/* set the references back */
-
-		par = fbinfo_crt->par;
-		par->info = info;
-		par->head = HEAD_CRT;
-		fbinfo_crt->pseudo_palette = &par->pseudo_palette;
-
-		par = fbinfo_pnl->par;
-		par->info = info;
-		par->head = HEAD_PANEL;
-		fbinfo_pnl->pseudo_palette = &par->pseudo_palette;
-
-		/* store the two fbs into our info */
-		info->fb[HEAD_CRT] = fbinfo_crt;
-		info->fb[HEAD_PANEL] = fbinfo_pnl;
-	}
-
-	return info;
-}
-
 /* sm501_init_cursor
  *
  * initialise hw cursor parameters
@@ -1268,10 +1246,16 @@ static struct sm501fb_info *sm501fb_info
 
 static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base)
 {
-	struct sm501fb_par *par = fbi->par;
-	struct sm501fb_info *info = par->info;
+	struct sm501fb_par *par;
+	struct sm501fb_info *info;
 	int ret;
 
+	if (fbi == NULL)
+		return 0;
+
+	par = fbi->par;
+	info = par->info;
+
 	par->cursor_regs = info->regs + reg_base;
 
 	ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024);
@@ -1299,13 +1283,10 @@ static int sm501fb_start(struct sm501fb_
 			 struct platform_device *pdev)
 {
 	struct resource	*res;
-	struct device *dev;
+	struct device *dev = &pdev->dev;
 	int k;
 	int ret;
 
-	info->dev = dev = &pdev->dev;
-	platform_set_drvdata(pdev, info);
-
 	info->irq = ret = platform_get_irq(pdev, 0);
 	if (ret < 0) {
 		/* we currently do not use the IRQ */
@@ -1408,11 +1389,6 @@ static void sm501fb_stop(struct sm501fb_
 	kfree(info->regs_res);
 }
 
-static void sm501fb_info_release(struct sm501fb_info *info)
-{
-	kfree(info);
-}
-
 static int sm501fb_init_fb(struct fb_info *fb,
 			   enum sm501_controller head,
 			   const char *fbname)
@@ -1557,36 +1533,93 @@ static struct sm501_platdata_fb sm501fb_
 static char driver_name_crt[] = "sm501fb-crt";
 static char driver_name_pnl[] = "sm501fb-panel";
 
-static int __init sm501fb_probe(struct platform_device *pdev)
+static int __devinit sm501fb_probe_one(struct sm501fb_info *info,
+				       enum sm501_controller head)
 {
-	struct sm501fb_info *info;
-	struct device	    *dev = &pdev->dev;
-	struct fb_info	    *fbinfo_crt;
-	struct fb_info	    *fbinfo_pnl;
-	int		     ret;
+	unsigned char *name = (head == HEAD_CRT) ? "crt" : "panel";
+	struct sm501_platdata_fbsub *pd;
+	struct sm501fb_par *par;
+	struct fb_info *fbi;
 
-	/* allocate our framebuffers */
+	pd = (head == HEAD_CRT) ? info->pdata->fb_crt : info->pdata->fb_pnl;
+
+	/* Do not initialise if we've not been given any platform data */
+	if (pd == NULL) {
+		dev_info(info->dev, "no data for fb %s (disabled)\n", name);
+		return 0;
+	}
 
-	fbinfo_crt = framebuffer_alloc(sizeof(struct sm501fb_par), dev);
-	if (fbinfo_crt == NULL) {
-		dev_err(dev, "cannot allocate crt framebuffer\n");
+	fbi = framebuffer_alloc(sizeof(struct sm501fb_par), info->dev);
+	if (fbi == NULL) {
+		dev_err(info->dev, "cannot allocate %s framebuffer\n", name);
 		return -ENOMEM;
 	}
 
-	fbinfo_pnl = framebuffer_alloc(sizeof(struct sm501fb_par), dev);
-	if (fbinfo_pnl == NULL) {
-		dev_err(dev, "cannot allocate panel framebuffer\n");
-		ret = -ENOMEM;
-		goto fbinfo_crt_alloc_fail;
+	par = fbi->par;
+	par->info = info;
+	par->head = head;
+	fbi->pseudo_palette = &par->pseudo_palette;
+
+	info->fb[head] = fbi;
+
+	return 0;
+}
+
+/* Free up anything allocated by sm501fb_init_fb */
+
+static void sm501_free_init_fb(struct sm501fb_info *info,
+				enum sm501_controller head)
+{
+	struct fb_info *fbi = info->fb[head];
+
+	fb_dealloc_cmap(&fbi->cmap);
+}
+
+static int __devinit sm501fb_start_one(struct sm501fb_info *info,
+				       enum sm501_controller head,
+				       const char *drvname)
+{
+	struct fb_info *fbi = info->fb[head];
+	int ret;
+
+	if (!fbi)
+		return 0;
+
+	ret = sm501fb_init_fb(info->fb[head], head, drvname);
+	if (ret) {
+		dev_err(info->dev, "cannot initialise fb %s\n", drvname);
+		return ret;
+	}
+
+	ret = register_framebuffer(info->fb[head]);
+	if (ret) {
+		dev_err(info->dev, "failed to register fb %s\n", drvname);
+		sm501_free_init_fb(info, head);
+		return ret;
 	}
 
-	info = sm501fb_info_alloc(fbinfo_crt, fbinfo_pnl);
-	if (info == NULL) {
-		dev_err(dev, "cannot allocate par\n");
-		ret = -ENOMEM;
-		goto sm501fb_alloc_fail;
+	dev_info(info->dev, "fb%d: %s frame buffer\n", fbi->node, fbi->fix.id);
+
+	return 0;
+}
+
+static int __devinit sm501fb_probe(struct platform_device *pdev)
+{
+	struct sm501fb_info *info;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	/* allocate our framebuffers */
+
+	info = kzalloc(sizeof(struct sm501fb_info), GFP_KERNEL);
+	if (!info) {
+		dev_err(dev, "failed to allocate state\n");
+		return -ENOMEM;
 	}
 
+	info->dev = dev = &pdev->dev;
+	platform_set_drvdata(pdev, info);
+
 	if (dev->parent->platform_data) {
 		struct sm501_platdata *pd = dev->parent->platform_data;
 		info->pdata = pd->fb;
@@ -1597,90 +1630,88 @@ static int __init sm501fb_probe(struct p
 		info->pdata = &sm501fb_def_pdata;
 	}
 
-	/* start the framebuffers */
+	/* probe for the presence of each panel */
 
-	ret = sm501fb_start(info, pdev);
-	if (ret) {
-		dev_err(dev, "cannot initialise SM501\n");
-		goto sm501fb_start_fail;
+	ret = sm501fb_probe_one(info, HEAD_CRT);
+	if (ret < 0) {
+		dev_err(dev, "failed to probe CRT\n");
+		goto err_alloc;
 	}
 
-	/* CRT framebuffer setup */
+	ret = sm501fb_probe_one(info, HEAD_PANEL);
+	if (ret < 0) {
+		dev_err(dev, "failed to probe PANEL\n");
+		goto err_probed_crt;
+	}
 
-	ret = sm501fb_init_fb(fbinfo_crt, HEAD_CRT, driver_name_crt);
-	if (ret) {
-		dev_err(dev, "cannot initialise CRT fb\n");
-		goto sm501fb_start_fail;
+	if (info->fb[HEAD_PANEL] == NULL &&
+	    info->fb[HEAD_CRT] == NULL) {
+		dev_err(dev, "no framebuffers found\n");
+		goto err_alloc;
 	}
 
-	/* Panel framebuffer setup */
+	/* get the resources for both of the framebuffers */
 
-	ret = sm501fb_init_fb(fbinfo_pnl, HEAD_PANEL, driver_name_pnl);
+	ret = sm501fb_start(info, pdev);
 	if (ret) {
-		dev_err(dev, "cannot initialise Panel fb\n");
-		goto sm501fb_start_fail;
+		dev_err(dev, "cannot initialise SM501\n");
+		goto err_probed_panel;
 	}
 
-	/* register framebuffers */
-
-	ret = register_framebuffer(fbinfo_crt);
-	if (ret < 0) {
-		dev_err(dev, "failed to register CRT fb (%d)\n", ret);
-		goto register_crt_fail;
+	ret = sm501fb_start_one(info, HEAD_CRT, driver_name_crt);
+	if (ret) {
+		dev_err(dev, "failed to start CRT\n");
+		goto err_started;
 	}
 
-	ret = register_framebuffer(fbinfo_pnl);
-	if (ret < 0) {
-		dev_err(dev, "failed to register panel fb (%d)\n", ret);
-		goto register_pnl_fail;
+	ret = sm501fb_start_one(info, HEAD_PANEL, driver_name_pnl);
+	if (ret) {
+		dev_err(dev, "failed to start Panel\n");
+		goto err_started_crt;
 	}
 
-	dev_info(dev, "fb%d: %s frame buffer device\n",
-		 fbinfo_crt->node, fbinfo_crt->fix.id);
-
-	dev_info(dev, "fb%d: %s frame buffer device\n",
-	       fbinfo_pnl->node, fbinfo_pnl->fix.id);
-
 	/* create device files */
 
 	ret = device_create_file(dev, &dev_attr_crt_src);
 	if (ret)
-		goto crtsrc_fail;
+		goto err_started_panel;
 
 	ret = device_create_file(dev, &dev_attr_fbregs_pnl);
 	if (ret)
-		goto fbregs_pnl_fail;
+		goto err_attached_crtsrc_file;
 
 	ret = device_create_file(dev, &dev_attr_fbregs_crt);
 	if (ret)
-		goto fbregs_crt_fail;
+		goto err_attached_pnlregs_file;
 
 	/* we registered, return ok */
 	return 0;
 
- fbregs_crt_fail:
+err_attached_pnlregs_file:
 	device_remove_file(dev, &dev_attr_fbregs_pnl);
 
- fbregs_pnl_fail:
+err_attached_crtsrc_file:
 	device_remove_file(dev, &dev_attr_crt_src);
 
- crtsrc_fail:
-	unregister_framebuffer(fbinfo_pnl);
-
- register_pnl_fail:
-	unregister_framebuffer(fbinfo_crt);
+err_started_panel:
+	unregister_framebuffer(info->fb[HEAD_PANEL]);
+	sm501_free_init_fb(info, HEAD_PANEL);
+
+err_started_crt:
+	unregister_framebuffer(info->fb[HEAD_CRT]);
+	sm501_free_init_fb(info, HEAD_CRT);
 
- register_crt_fail:
+err_started:
 	sm501fb_stop(info);
 
- sm501fb_start_fail:
-	sm501fb_info_release(info);
+err_probed_panel:
+	framebuffer_release(info->fb[HEAD_PANEL]);
 
- sm501fb_alloc_fail:
-	framebuffer_release(fbinfo_pnl);
+err_probed_crt:
+	framebuffer_release(info->fb[HEAD_CRT]);
 
- fbinfo_crt_alloc_fail:
-	framebuffer_release(fbinfo_crt);
+err_alloc:
+	kfree(info);
 
 	return ret;
 }
@@ -1699,11 +1730,14 @@ static int sm501fb_remove(struct platfor
 	device_remove_file(&pdev->dev, &dev_attr_fbregs_pnl);
 	device_remove_file(&pdev->dev, &dev_attr_crt_src);
 
+	sm501_free_init_fb(info, HEAD_CRT);
+	sm501_free_init_fb(info, HEAD_PANEL);
+
 	unregister_framebuffer(fbinfo_crt);
 	unregister_framebuffer(fbinfo_pnl);
 
 	sm501fb_stop(info);
-	sm501fb_info_release(info);
+	kfree(info);
 
 	framebuffer_release(fbinfo_pnl);
 	framebuffer_release(fbinfo_crt);

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [patch 3/5] FB: Add support for the ILI9320 video display controller.
  2008-06-22 21:04 [patch 0/5] fb driver patches for next kernel Ben Dooks
  2008-06-22 21:04 ` [patch 1/5] SM501: Add inversion controls for VBIASEN and FPEN Ben Dooks
  2008-06-22 21:04 ` [patch 2/5] SM501: Restructure init to allow only 1 fb on an SM501 Ben Dooks
@ 2008-06-22 21:04 ` Ben Dooks
  2008-06-24  7:07   ` Andrew Morton
  2008-06-22 21:04 ` [patch 4/5] LCD: Add lcd_device to check_fb() entry in lcd_ops Ben Dooks
  2008-06-22 21:04 ` [patch 5/5] LCD: Add platform_lcd driver Ben Dooks
  4 siblings, 1 reply; 11+ messages in thread
From: Ben Dooks @ 2008-06-22 21:04 UTC (permalink / raw)
  To: linux-fbdev-devel, akpm; +Cc: linux-arm-kernel, Ben Dooks

[-- Attachment #1: simtec/jive/jive-drivers-fb-ili9320.patch --]
[-- Type: text/plain, Size: 25894 bytes --]

Provide support for the ILI9320 display controller chip
which is found in many LCD displays. Included with this
is support for an example LCD using this chip, the
VGG2432A4.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Index: linux-2.6.26-rc5-quilt3/include/video/ili9320.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.26-rc5-quilt3/include/video/ili9320.h	2008-06-15 16:47:07.000000000 +0100
@@ -0,0 +1,201 @@
+/* include/video/ili9320.c
+ *
+ * ILI9320 LCD controller configuration control.
+ *
+ * Copyright 2007 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * 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.
+*/
+
+#define ILI9320_REG(x)	(x)
+
+#define ILI9320_INDEX			ILI9320_REG(0x00)
+
+#define ILI9320_OSCILATION		ILI9320_REG(0x00)
+#define ILI9320_DRIVER			ILI9320_REG(0x01)
+#define ILI9320_DRIVEWAVE		ILI9320_REG(0x02)
+#define ILI9320_ENTRYMODE		ILI9320_REG(0x03)
+#define ILI9320_RESIZING		ILI9320_REG(0x04)
+#define ILI9320_DISPLAY1		ILI9320_REG(0x07)
+#define ILI9320_DISPLAY2		ILI9320_REG(0x08)
+#define ILI9320_DISPLAY3		ILI9320_REG(0x09)
+#define ILI9320_DISPLAY4		ILI9320_REG(0x0A)
+#define ILI9320_RGB_IF1			ILI9320_REG(0x0C)
+#define ILI9320_FRAMEMAKER		ILI9320_REG(0x0D)
+#define ILI9320_RGB_IF2			ILI9320_REG(0x0F)
+
+#define ILI9320_POWER1			ILI9320_REG(0x10)
+#define ILI9320_POWER2			ILI9320_REG(0x11)
+#define ILI9320_POWER3			ILI9320_REG(0x12)
+#define ILI9320_POWER4			ILI9320_REG(0x13)
+#define ILI9320_GRAM_HORIZ_ADDR		ILI9320_REG(0x20)
+#define ILI9320_GRAM_VERT_ADD		ILI9320_REG(0x21)
+#define ILI9320_POWER7			ILI9320_REG(0x29)
+#define ILI9320_FRAME_RATE_COLOUR	ILI9320_REG(0x2B)
+
+#define ILI9320_GAMMA1			ILI9320_REG(0x30)
+#define ILI9320_GAMMA2			ILI9320_REG(0x31)
+#define ILI9320_GAMMA3			ILI9320_REG(0x32)
+#define ILI9320_GAMMA4			ILI9320_REG(0x35)
+#define ILI9320_GAMMA5			ILI9320_REG(0x36)
+#define ILI9320_GAMMA6			ILI9320_REG(0x37)
+#define ILI9320_GAMMA7			ILI9320_REG(0x38)
+#define ILI9320_GAMMA8			ILI9320_REG(0x39)
+#define ILI9320_GAMMA9			ILI9320_REG(0x3C)
+#define ILI9320_GAMMA10			ILI9320_REG(0x3D)
+
+#define ILI9320_HORIZ_START		ILI9320_REG(0x50)
+#define ILI9320_HORIZ_END		ILI9320_REG(0x51)
+#define ILI9320_VERT_START		ILI9320_REG(0x52)
+#define ILI9320_VERT_END		ILI9320_REG(0x53)
+
+#define ILI9320_DRIVER2			ILI9320_REG(0x60)
+#define ILI9320_BASE_IMAGE		ILI9320_REG(0x61)
+#define ILI9320_VERT_SCROLL		ILI9320_REG(0x6a)
+
+#define ILI9320_PARTIAL1_POSITION	ILI9320_REG(0x80)
+#define ILI9320_PARTIAL1_START		ILI9320_REG(0x81)
+#define ILI9320_PARTIAL1_END		ILI9320_REG(0x82)
+#define ILI9320_PARTIAL2_POSITION	ILI9320_REG(0x83)
+#define ILI9320_PARTIAL2_START		ILI9320_REG(0x84)
+#define ILI9320_PARTIAL2_END		ILI9320_REG(0x85)
+
+#define ILI9320_INTERFACE1		ILI9320_REG(0x90)
+#define ILI9320_INTERFACE2		ILI9320_REG(0x92)
+#define ILI9320_INTERFACE3		ILI9320_REG(0x93)
+#define ILI9320_INTERFACE4		ILI9320_REG(0x95)
+#define ILI9320_INTERFACE5		ILI9320_REG(0x97)
+#define ILI9320_INTERFACE6		ILI9320_REG(0x98)
+
+/* Register contents definitions. */
+
+#define ILI9320_OSCILATION_OSC		(1 << 0)
+
+#define ILI9320_DRIVER_SS		(1 << 8)
+#define ILI9320_DRIVER_SM		(1 << 10)
+
+#define ILI9320_DRIVEWAVE_EOR		(1 << 8)
+#define ILI9320_DRIVEWAVE_BC		(1 << 9)
+#define ILI9320_DRIVEWAVE_MUSTSET	(1 << 10)
+
+#define ILI9320_ENTRYMODE_AM		(1 << 3)
+#define ILI9320_ENTRYMODE_ID(x)		((x) << 4)
+#define ILI9320_ENTRYMODE_ORG		(1 << 7)
+#define ILI9320_ENTRYMODE_HWM		(1 << 8)
+#define ILI9320_ENTRYMODE_BGR		(1 << 12)
+#define ILI9320_ENTRYMODE_DFM		(1 << 14)
+#define ILI9320_ENTRYMODE_TRI		(1 << 15)
+
+
+#define ILI9320_RESIZING_RSZ(x)		((x) << 0)
+#define ILI9320_RESIZING_RCH(x)		((x) << 4)
+#define ILI9320_RESIZING_RCV(x)		((x) << 8)
+
+
+#define ILI9320_DISPLAY1_D(x)		((x) << 0)
+#define ILI9320_DISPLAY1_CL		(1 << 3)
+#define ILI9320_DISPLAY1_DTE		(1 << 4)
+#define ILI9320_DISPLAY1_GON		(1 << 5)
+#define ILI9320_DISPLAY1_BASEE		(1 << 8)
+#define ILI9320_DISPLAY1_PTDE(x)	((x) << 12)
+
+
+#define ILI9320_DISPLAY2_BP(x)		((x) << 0)
+#define ILI9320_DISPLAY2_FP(x)		((x) << 8)
+
+
+#define ILI9320_RGBIF1_RIM_RGB18	(0 << 0)
+#define ILI9320_RGBIF1_RIM_RGB16	(1 << 0)
+#define ILI9320_RGBIF1_RIM_RGB6		(2 << 0)
+
+#define ILI9320_RGBIF1_CLK_INT		(0 << 4)
+#define ILI9320_RGBIF1_CLK_RGBIF	(1 << 4)
+#define ILI9320_RGBIF1_CLK_VSYNC	(2 << 4)
+
+#define ILI9320_RGBIF1_RM		(1 << 8)
+
+#define ILI9320_RGBIF1_ENC_FRAMES(x)	(((x) - 1)<< 13)
+
+#define ILI9320_RGBIF2_DPL		(1 << 0)
+#define ILI9320_RGBIF2_EPL		(1 << 1)
+#define ILI9320_RGBIF2_HSPL		(1 << 3)
+#define ILI9320_RGBIF2_VSPL		(1 << 4)
+
+
+#define ILI9320_POWER1_SLP		(1 << 1)
+#define ILI9320_POWER1_DSTB		(1 << 2)
+#define ILI9320_POWER1_AP(x)		((x) << 4)
+#define ILI9320_POWER1_APE		(1 << 7)
+#define ILI9320_POWER1_BT(x)		((x) << 8)
+#define ILI9320_POWER1_SAP		(1 << 12)
+
+
+#define ILI9320_POWER2_VC(x)		((x) << 0)
+#define ILI9320_POWER2_DC0(x)		((x) << 4)
+#define ILI9320_POWER2_DC1(x)		((x) << 8)
+
+
+#define ILI9320_POWER3_VRH(x)		((x) << 0)
+#define ILI9320_POWER3_PON		(1 << 4)
+#define ILI9320_POWER3_VCMR		(1 << 8)
+
+
+#define ILI9320_POWER4_VREOUT(x)	((x) << 8)
+
+
+#define ILI9320_DRIVER2_SCNL(x)		((x) << 0)
+#define ILI9320_DRIVER2_NL(x)		((x) << 8)
+#define ILI9320_DRIVER2_GS		(1 << 15)
+
+
+#define ILI9320_BASEIMAGE_REV		(1 << 0)
+#define ILI9320_BASEIMAGE_VLE		(1 << 1)
+#define ILI9320_BASEIMAGE_NDL		(1 << 2)
+
+
+#define ILI9320_INTERFACE4_RTNE(x)	(x)
+#define ILI9320_INTERFACE4_DIVE(x)	((x) << 8)
+
+/* SPI interface definitions */
+
+#define ILI9320_SPI_IDCODE		(0x70)
+#define ILI9320_SPI_ID(x)		((x) << 2)
+#define ILI9320_SPI_READ		(0x01)
+#define ILI9320_SPI_WRITE		(0x00)
+#define ILI9320_SPI_DATA		(0x02)
+#define ILI9320_SPI_INDEX		(0x00)
+
+/* platform data to pass configuration from lcd */
+
+enum ili9320_suspend {
+	ILI9320_SUSPEND_OFF,
+	ILI9320_SUSPEND_DEEP,
+};
+
+struct ili9320_platdata {
+	unsigned short	hsize;
+	unsigned short	vsize;
+
+	enum ili9320_suspend suspend;
+
+	/* set the reset line, 0 = reset asserted, 1 = normal */
+	void		(*reset)(unsigned int val);
+
+	unsigned short	entry_mode;
+	unsigned short	display2;
+	unsigned short	display3;
+	unsigned short	display4;
+	unsigned short	rgb_if1;
+	unsigned short	rgb_if2;
+	unsigned short	interface2;
+	unsigned short	interface3;
+	unsigned short	interface4;
+	unsigned short	interface5;
+	unsigned short	interface6;
+};
+
Index: linux-2.6.26-rc5-quilt3/drivers/video/backlight/Kconfig
===================================================================
--- linux-2.6.26-rc5-quilt3.orig/drivers/video/backlight/Kconfig	2008-06-15 16:47:05.000000000 +0100
+++ linux-2.6.26-rc5-quilt3/drivers/video/backlight/Kconfig	2008-06-15 16:47:07.000000000 +0100
@@ -36,6 +36,23 @@ config LCD_LTV350QV
 
 	  The LTV350QV panel is present on all ATSTK1000 boards.
 
+config LCD_ILI9320
+	tristate
+	depends on LCD_CLASS_DEVICE && BACKLIGHT_LCD_SUPPORT
+	default n
+	help
+	  If you have a panel based on the ILI9320 controller chip
+	  then say y to include a power driver for it.
+
+config LCD_VGG2432A4
+	tristate "VGG2432A4 LCM device support"
+	depends on BACKLIGHT_LCD_SUPPORT && LCD_CLASS_DEVICE && SPI_MASTER
+	select LCD_ILI9320
+	default n
+	help
+	  If you have a VGG2432A4 panel based on the ILI9320 controller chip
+	  then say y to include a power driver for it.
+
 #
 # Backlight
 #
Index: linux-2.6.26-rc5-quilt3/drivers/video/backlight/Makefile
===================================================================
--- linux-2.6.26-rc5-quilt3.orig/drivers/video/backlight/Makefile	2008-06-15 16:47:05.000000000 +0100
+++ linux-2.6.26-rc5-quilt3/drivers/video/backlight/Makefile	2008-06-15 16:47:07.000000000 +0100
@@ -1,7 +1,9 @@
 # Backlight & LCD drivers
 
 obj-$(CONFIG_LCD_CLASS_DEVICE)     += lcd.o
-obj-$(CONFIG_LCD_LTV350QV)	+= ltv350qv.o
+obj-$(CONFIG_LCD_LTV350QV)	   += ltv350qv.o
+obj-$(CONFIG_LCD_ILI9320)	   += ili9320.o
+obj-$(CONFIG_LCD_VGG2432A4)	   += vgg2432a4.o
 
 obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
 obj-$(CONFIG_BACKLIGHT_CORGI)	+= corgi_bl.o
Index: linux-2.6.26-rc5-quilt3/drivers/video/backlight/ili9320.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.26-rc5-quilt3/drivers/video/backlight/ili9320.c	2008-06-15 16:47:19.000000000 +0100
@@ -0,0 +1,329 @@
+/* drivers/video/backlight/ili9320.c
+ *
+ * ILI9320 LCD controller driver core.
+ *
+ * Copyright 2007 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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.
+*/
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/lcd.h>
+#include <linux/module.h>
+
+#include <linux/spi/spi.h>
+
+#include <video/ili9320.h>
+
+#include "ili9320.h"
+
+
+static inline int ili9320_write_spi(struct ili9320 *ili,
+				    unsigned int reg,
+				    unsigned int value)
+{
+	struct ili9320_spi *spi = &ili->access.spi;
+	unsigned char *addr = spi->buffer_addr;
+	unsigned char *data = spi->buffer_data;
+
+	/* spi message consits of:
+	 * first byte: ID and operation
+	 */
+
+	addr[0] = spi->id | ILI9320_SPI_INDEX | ILI9320_SPI_WRITE;
+	addr[1] = reg >> 8;
+	addr[2] = reg;
+
+	/* second message is the data to transfer */
+
+	data[0] = spi->id | ILI9320_SPI_DATA  | ILI9320_SPI_WRITE;
+ 	data[1] = value >> 8;
+	data[2] = value;
+
+	return spi_sync(spi->dev, &spi->message);
+}
+
+int ili9320_write(struct ili9320 *ili, unsigned int reg, unsigned int value)
+{
+	dev_dbg(ili->dev, "write: reg=%02x, val=%04x\n", reg, value);
+	return ili->write(ili, reg, value);
+}
+
+EXPORT_SYMBOL_GPL(ili9320_write);
+
+int ili9320_write_regs(struct ili9320 *ili,
+		       struct ili9320_reg *values,
+		       int nr_values)
+{
+	int index;
+	int ret;
+
+	for (index = 0; index < nr_values; index++, values++) {
+		ret = ili9320_write(ili, values->address, values->value);
+		if (ret != 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ili9320_write_regs);
+
+static void ili9320_reset(struct ili9320 *lcd)
+{
+	struct ili9320_platdata *cfg = lcd->platdata;
+
+	cfg->reset(1);
+	mdelay(50);
+
+	cfg->reset(0);
+	mdelay(50);
+
+	cfg->reset(1);
+	mdelay(100);
+}
+
+static inline int ili9320_init_chip(struct ili9320 *lcd)
+{
+	int ret;
+
+	ili9320_reset(lcd);
+
+	ret = lcd->client->init(lcd, lcd->platdata);
+	if (ret != 0) {
+		dev_err(lcd->dev, "failed to initialise display\n");
+		return ret;
+	}
+
+	lcd->initialised = 1;
+	return 0;
+}
+
+static inline int ili9320_power_on(struct ili9320 *lcd)
+{
+	if (!lcd->initialised)
+		ili9320_init_chip(lcd);
+
+	lcd->display1 |= (ILI9320_DISPLAY1_D(3) | ILI9320_DISPLAY1_BASEE);
+	ili9320_write(lcd, ILI9320_DISPLAY1, lcd->display1);
+
+	return 0;
+}
+
+static inline int ili9320_power_off(struct ili9320 *lcd)
+{
+	lcd->display1 &= ~(ILI9320_DISPLAY1_D(3) | ILI9320_DISPLAY1_BASEE);
+	ili9320_write(lcd, ILI9320_DISPLAY1, lcd->display1);
+
+	return 0;
+}
+
+#define POWER_IS_ON(pwr)	((pwr) <= FB_BLANK_NORMAL)
+
+static int ili9320_power(struct ili9320 *lcd, int power)
+{
+	int ret = 0;
+
+	dev_dbg(lcd->dev, "power %d => %d\n", lcd->power, power);
+
+	if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power))
+		ret = ili9320_power_on(lcd);
+	else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power))
+		ret = ili9320_power_off(lcd);
+
+	if (ret == 0)
+		lcd->power = power;
+	else
+		dev_warn(lcd->dev, "failed to set power mode %d\n", power);
+
+	return ret;
+}
+
+static inline struct ili9320 *to_our_lcd(struct lcd_device *lcd)
+{
+	return lcd_get_data(lcd);
+}
+
+static int ili9320_set_power(struct lcd_device *ld, int power)
+{
+	struct ili9320 *lcd = to_our_lcd(ld);
+
+	return ili9320_power(lcd, power);
+}
+
+static int ili9320_get_power(struct lcd_device *ld)
+{
+	struct ili9320 *lcd = to_our_lcd(ld);
+
+	return lcd->power;
+}
+
+static struct lcd_ops ili9320_ops = {
+	.get_power	= ili9320_get_power,
+	.set_power	= ili9320_set_power,
+};
+
+static void __devinit ili9320_setup_spi(struct ili9320 *ili,
+					struct spi_device *dev)
+{
+	struct ili9320_spi *spi = &ili->access.spi;
+
+	ili->write = ili9320_write_spi;
+	spi->dev = dev;
+
+	/* fill the two messages we are going to use to send the data
+	 * with, the first the address followed by the data. The datasheet
+	 * says they should be done as two distinct cycles of the SPI CS line.
+	 */
+
+	spi->xfer[0].tx_buf = spi->buffer_addr;
+	spi->xfer[1].tx_buf = spi->buffer_data;
+	spi->xfer[0].len = 3;
+	spi->xfer[1].len = 3;
+	spi->xfer[0].bits_per_word = 8;
+	spi->xfer[1].bits_per_word = 8;
+	spi->xfer[0].cs_change = 1;
+
+	spi_message_init(&spi->message);
+	spi_message_add_tail(&spi->xfer[0], &spi->message);
+	spi_message_add_tail(&spi->xfer[1], &spi->message);
+}
+
+int __devinit ili9320_probe_spi(struct spi_device *spi,
+				struct ili9320_client *client)
+{
+	struct ili9320_platdata *cfg = spi->dev.platform_data;
+	struct device *dev = &spi->dev;
+	struct ili9320 *ili;
+	struct lcd_device *lcd;
+	int ret = 0;
+
+	/* verify we where given some information */
+
+	if (cfg == NULL) {
+		dev_err(dev, "no platform data supplied\n");
+		return -EINVAL;
+	}
+
+	if (cfg->hsize <= 0 || cfg->vsize <= 0 || cfg->reset == NULL) {
+		dev_err(dev, "invalid platform data supplied\n");
+		return -EINVAL;
+	}
+
+	/* allocate and initialse our state */
+
+	ili = kzalloc(sizeof(struct ili9320), GFP_KERNEL);
+	if (ili == NULL) {
+		dev_err(dev, "no memory for device\n");
+		return -ENOMEM;
+	}
+
+	ili->access.spi.id = ILI9320_SPI_IDCODE | ILI9320_SPI_ID(1);
+
+	ili->dev = dev;
+	ili->client = client;
+	ili->power = FB_BLANK_POWERDOWN;
+	ili->platdata = cfg;
+
+	dev_set_drvdata(&spi->dev, ili);
+
+	ili9320_setup_spi(ili, spi);
+
+	lcd = lcd_device_register("ili9320", dev, ili, &ili9320_ops);
+	if (IS_ERR(lcd)) {
+		dev_err(dev, "failed to register lcd device\n");
+		ret = PTR_ERR(lcd);
+		goto err_free;
+	}
+
+	ili->lcd = lcd;
+
+	dev_info(dev, "initialising %s\n", client->name);
+
+	ret = ili9320_power(ili, FB_BLANK_UNBLANK);
+	if (ret != 0) {
+		dev_err(dev, "failed to set lcd power state\n");
+		goto err_unregister;
+	}
+
+	return 0;
+
+ err_unregister:
+	lcd_device_unregister(lcd);
+
+ err_free:
+	kfree(lcd);
+	return ret;
+}
+
+EXPORT_SYMBOL_GPL(ili9320_probe_spi);
+
+int __devexit ili9320_remove(struct ili9320 *lcd)
+{
+	ili9320_power(lcd, FB_BLANK_POWERDOWN);
+
+	lcd_device_unregister(lcd->lcd);
+	kfree(lcd);
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ili9320_remove);
+
+#ifdef CONFIG_PM
+int ili9320_suspend(struct ili9320 *lcd, pm_message_t state)
+{
+	int ret;
+
+	dev_dbg(lcd->dev, "%s: event %d\n", __func__, state.event);
+
+	if (state.event == PM_EVENT_SUSPEND) {
+		ret = ili9320_power(lcd, FB_BLANK_POWERDOWN);
+
+		if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) {
+			ili9320_write(lcd, ILI9320_POWER1, lcd->power1 |
+				      ILI9320_POWER1_SLP |
+				      ILI9320_POWER1_DSTB);
+			lcd->initialised = 0;
+		}
+
+		return ret;
+	}
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ili9320_suspend);
+
+int ili9320_resume(struct ili9320 *lcd)
+{
+	dev_info(lcd->dev, "resuming from power state %d\n", lcd->power);
+
+	if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) {
+		ili9320_write(lcd, ILI9320_POWER1, 0x00);
+	}
+
+	return ili9320_power(lcd, FB_BLANK_UNBLANK);
+}
+
+EXPORT_SYMBOL_GPL(ili9320_resume);
+#endif
+
+/* Power down all displays on reboot, poweroff or halt */
+void ili9320_shutdown(struct ili9320 *lcd)
+{
+	ili9320_power(lcd, FB_BLANK_POWERDOWN);
+}
+
+EXPORT_SYMBOL_GPL(ili9320_shutdown);
+
+MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
+MODULE_DESCRIPTION("ILI9320 LCD Driver");
+MODULE_LICENSE("GPL v2");
Index: linux-2.6.26-rc5-quilt3/drivers/video/backlight/ili9320.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.26-rc5-quilt3/drivers/video/backlight/ili9320.h	2008-06-15 16:47:07.000000000 +0100
@@ -0,0 +1,80 @@
+/* drivers/video/backlight/ili9320.h
+ *
+ * ILI9320 LCD controller driver core.
+ *
+ * Copyright 2007 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * 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.
+*/
+
+/* Holder for register and value pairs. */
+struct ili9320_reg {
+	unsigned short		address;
+	unsigned short		value;
+};
+
+struct ili9320;
+
+struct ili9320_client {
+	const char	*name;
+	int	(*init)(struct ili9320 *ili, struct ili9320_platdata *cfg);
+
+};
+/* Device attached via an SPI bus. */
+struct  ili9320_spi {
+	struct spi_device	*dev;
+	struct spi_message	message;
+	struct spi_transfer	xfer[2];
+
+	unsigned char		id;
+	unsigned char		buffer_addr[4];
+	unsigned char		buffer_data[4];
+};
+
+/* ILI9320 device state. */
+struct ili9320 {
+	union {
+		struct ili9320_spi	spi;	/* SPI attachged device. */
+	} access;				/* Register access method. */
+
+	struct device			*dev;
+	struct lcd_device		*lcd;	/* LCD device we created. */
+	struct ili9320_client		*client;
+	struct ili9320_platdata		*platdata;
+
+	int				 power; /* current power state. */
+	int				 initialised;
+
+	unsigned short			 display1;
+	unsigned short			 power1;
+
+	int (*write)(struct ili9320 *ili, unsigned int reg, unsigned int val);
+};
+
+
+/* ILI9320 register access routines */
+
+extern int ili9320_write(struct ili9320 *ili,
+			 unsigned int reg, unsigned int value);
+
+extern int ili9320_write_regs(struct ili9320 *ili,
+			      struct ili9320_reg *values,
+			      int nr_values);
+
+/* Device probe */
+
+extern int ili9320_probe_spi(struct spi_device *spi,
+			     struct ili9320_client *cli);
+
+extern int ili9320_remove(struct ili9320 *lcd);
+extern void ili9320_shutdown(struct ili9320 *lcd);
+
+/* PM */
+
+extern int ili9320_suspend(struct ili9320 *lcd, pm_message_t state);
+extern int ili9320_resume(struct ili9320 *lcd);
Index: linux-2.6.26-rc5-quilt3/drivers/video/backlight/vgg2432a4.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.26-rc5-quilt3/drivers/video/backlight/vgg2432a4.c	2008-06-15 16:47:19.000000000 +0100
@@ -0,0 +1,284 @@
+/* drivers/video/backlight/vgg2432a4.c
+ *
+ * VGG2432A4 (ILI9320) LCD controller driver.
+ *
+ * Copyright 2007 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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.
+*/
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/lcd.h>
+#include <linux/module.h>
+
+#include <linux/spi/spi.h>
+
+#include <video/ili9320.h>
+
+#include "ili9320.h"
+
+/* Device initialisation sequences */
+
+static struct ili9320_reg vgg_init1[] = {
+	{
+		.address = ILI9320_POWER1,
+		.value	 = ILI9320_POWER1_AP(0) | ILI9320_POWER1_BT(0),
+	}, {
+		.address = ILI9320_POWER2,
+		.value	 = (ILI9320_POWER2_VC(7) |
+			    ILI9320_POWER2_DC0(0) | ILI9320_POWER2_DC1(0)),
+	}, {
+		.address = ILI9320_POWER3,
+		.value	 = ILI9320_POWER3_VRH(0),
+	}, {
+		.address = ILI9320_POWER4,
+		.value	 = ILI9320_POWER4_VREOUT(0),
+	},
+};
+
+static struct ili9320_reg vgg_init2[] = {
+	{
+		.address = ILI9320_POWER1,
+		.value   = (ILI9320_POWER1_AP(3) | ILI9320_POWER1_APE |
+			    ILI9320_POWER1_BT(7) | ILI9320_POWER1_SAP),
+	}, {
+		.address = ILI9320_POWER2,
+		.value   = ILI9320_POWER2_VC(7) | ILI9320_POWER2_DC0(3),
+	}
+};
+
+static struct ili9320_reg vgg_gamma[] = {
+	{
+		.address = ILI9320_GAMMA1,
+		.value	 = 0x0000,
+	}, {
+		.address = ILI9320_GAMMA2,
+		.value   = 0x0505,
+	}, {
+		.address = ILI9320_GAMMA3,
+		.value	 = 0x0004,
+	}, {
+		.address = ILI9320_GAMMA4,
+		.value	 = 0x0006,
+	}, {
+		.address = ILI9320_GAMMA5,
+		.value	 = 0x0707,
+	}, {
+		.address = ILI9320_GAMMA6,
+		.value	 = 0x0105,
+	}, {
+		.address = ILI9320_GAMMA7,
+		.value	 = 0x0002,
+	}, {
+		.address = ILI9320_GAMMA8,
+		.value	 = 0x0707,
+	}, {
+		.address = ILI9320_GAMMA9,
+		.value	 = 0x0704,
+	}, {
+		.address = ILI9320_GAMMA10,
+		.value	 = 0x807,
+	}
+
+};
+
+static struct ili9320_reg vgg_init0[] = {
+	[0]	= {
+		/* set direction and scan mode gate */
+		.address = ILI9320_DRIVER,
+		.value	 = ILI9320_DRIVER_SS,
+	}, {
+		.address = ILI9320_DRIVEWAVE,
+		.value	 = (ILI9320_DRIVEWAVE_MUSTSET |
+			    ILI9320_DRIVEWAVE_EOR | ILI9320_DRIVEWAVE_BC),
+	}, {
+		.address = ILI9320_ENTRYMODE,
+		.value	 = ILI9320_ENTRYMODE_ID(3) | ILI9320_ENTRYMODE_BGR,
+	}, {
+		.address = ILI9320_RESIZING,
+		.value	 = 0x0,
+	},
+};
+
+
+static int vgg2432a4_lcd_init(struct ili9320 *lcd,
+			      struct ili9320_platdata *cfg)
+{
+	unsigned int addr;
+	int ret;
+
+	/* Set VCore before anything else (VGG243237-6UFLWA) */
+	ret = ili9320_write(lcd, 0x00e5, 0x8000);
+	if (ret)
+		goto err_initial;
+
+	/* Start the oscillator up before we can do anything else. */
+	ret = ili9320_write(lcd, ILI9320_OSCILATION, ILI9320_OSCILATION_OSC);
+	if (ret)
+		goto err_initial;
+
+	/* must wait at-lesat 10ms after starting */
+	mdelay(15);
+
+	ret = ili9320_write_regs(lcd, vgg_init0, ARRAY_SIZE(vgg_init0));
+	if (ret != 0)
+		goto err_initial;
+
+	ili9320_write(lcd, ILI9320_DISPLAY2, cfg->display2);
+	ili9320_write(lcd, ILI9320_DISPLAY3, cfg->display3);
+	ili9320_write(lcd, ILI9320_DISPLAY4, cfg->display4);
+
+	ili9320_write(lcd, ILI9320_RGB_IF1, cfg->rgb_if1);
+	ili9320_write(lcd, ILI9320_FRAMEMAKER, 0x0);
+	ili9320_write(lcd, ILI9320_RGB_IF2, ILI9320_RGBIF2_DPL);
+
+	ret = ili9320_write_regs(lcd, vgg_init1, ARRAY_SIZE(vgg_init1));
+	if (ret != 0)
+		goto err_vgg;
+
+	mdelay(300);
+
+	ret = ili9320_write_regs(lcd, vgg_init2, ARRAY_SIZE(vgg_init2));
+	if (ret != 0)
+		goto err_vgg2;
+
+	mdelay(100);
+
+	ili9320_write(lcd, ILI9320_POWER3, 0x13c);
+
+	mdelay(100);
+
+	ili9320_write(lcd, ILI9320_POWER4, 0x1c00);
+	ili9320_write(lcd, ILI9320_POWER7, 0x000e);
+
+	mdelay(100);
+
+	ili9320_write(lcd, ILI9320_GRAM_HORIZ_ADDR, 0x00);
+	ili9320_write(lcd, ILI9320_GRAM_VERT_ADD, 0x00);
+
+	ret = ili9320_write_regs(lcd, vgg_gamma, ARRAY_SIZE(vgg_gamma));
+	if (ret != 0)
+		goto err_vgg3;
+
+	ili9320_write(lcd, ILI9320_HORIZ_START, 0x0);
+	ili9320_write(lcd, ILI9320_HORIZ_END, cfg->hsize - 1);
+	ili9320_write(lcd, ILI9320_VERT_START, 0x0);
+	ili9320_write(lcd, ILI9320_VERT_END, cfg->vsize - 1);
+
+	ili9320_write(lcd, ILI9320_DRIVER2,
+		      ILI9320_DRIVER2_NL(((cfg->vsize - 240) / 8) + 0x1D));
+
+	ili9320_write(lcd, ILI9320_BASE_IMAGE, 0x1);
+	ili9320_write(lcd, ILI9320_VERT_SCROLL, 0x00);
+
+	for (addr = ILI9320_PARTIAL1_POSITION; addr <= ILI9320_PARTIAL2_END;
+	     addr++) {
+		ili9320_write(lcd, addr, 0x0);
+	}
+
+	ili9320_write(lcd, ILI9320_INTERFACE1, 0x10);
+	ili9320_write(lcd, ILI9320_INTERFACE2, cfg->interface2);
+	ili9320_write(lcd, ILI9320_INTERFACE3, cfg->interface3);
+	ili9320_write(lcd, ILI9320_INTERFACE4, cfg->interface4);
+	ili9320_write(lcd, ILI9320_INTERFACE5, cfg->interface5);
+	ili9320_write(lcd, ILI9320_INTERFACE6, cfg->interface6);
+
+	lcd->display1 = (ILI9320_DISPLAY1_D(3) | ILI9320_DISPLAY1_DTE |
+			 ILI9320_DISPLAY1_GON | ILI9320_DISPLAY1_BASEE |
+			 0x40);
+
+	ili9320_write(lcd, ILI9320_DISPLAY1, lcd->display1);
+
+	return 0;
+
+ err_vgg3:
+ err_vgg2:
+ err_vgg:
+ err_initial:
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static int vgg2432a4_suspend(struct spi_device *spi, pm_message_t state)
+{
+	return ili9320_suspend(dev_get_drvdata(&spi->dev), state);
+}
+
+static int vgg2432a4_resume(struct spi_device *spi)
+{
+	return ili9320_resume(dev_get_drvdata(&spi->dev));
+}
+#else
+#define vgg2432a4_suspend	NULL
+#define vgg2432a4_resume 	NULL
+#endif
+
+static struct ili9320_client vgg2432a4_client = {
+	.name	= "VGG2432A4",
+	.init	= vgg2432a4_lcd_init,
+};
+
+/* Device probe */
+
+static int __devinit vgg2432a4_probe(struct spi_device *spi)
+{
+	int ret;
+
+	ret = ili9320_probe_spi(spi, &vgg2432a4_client);
+	if (ret != 0) {
+		dev_err(&spi->dev, "failed to initialise ili9320\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int __devexit vgg2432a4_remove(struct spi_device *spi)
+{
+	return ili9320_remove(dev_get_drvdata(&spi->dev));
+}
+
+static void vgg2432a4_shutdown(struct spi_device *spi)
+{
+	ili9320_shutdown(dev_get_drvdata(&spi->dev));
+}
+
+static struct spi_driver vgg2432a4_driver = {
+	.driver = {
+		.name		= "VGG2432A4",
+		.owner		= THIS_MODULE,
+	},
+	.probe		= vgg2432a4_probe,
+	.remove		= __devexit_p(vgg2432a4_remove),
+	.shutdown	= vgg2432a4_shutdown,
+	.suspend	= vgg2432a4_suspend,
+	.resume		= vgg2432a4_resume,
+};
+
+/* Device driver initialisation */
+
+static int __init vgg2432a4_init(void)
+{
+	return spi_register_driver(&vgg2432a4_driver);
+}
+
+static void __exit vgg2432a4_exit(void)
+{
+	spi_unregister_driver(&vgg2432a4_driver);
+}
+
+module_init(vgg2432a4_init);
+module_exit(vgg2432a4_exit);
+
+MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
+MODULE_DESCRIPTION("VGG2432A4 LCD Driver");
+MODULE_LICENSE("GPL v2");
+
+

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [patch 4/5] LCD: Add lcd_device to check_fb() entry in lcd_ops.
  2008-06-22 21:04 [patch 0/5] fb driver patches for next kernel Ben Dooks
                   ` (2 preceding siblings ...)
  2008-06-22 21:04 ` [patch 3/5] FB: Add support for the ILI9320 video display controller Ben Dooks
@ 2008-06-22 21:04 ` Ben Dooks
  2008-06-22 21:04 ` [patch 5/5] LCD: Add platform_lcd driver Ben Dooks
  4 siblings, 0 replies; 11+ messages in thread
From: Ben Dooks @ 2008-06-22 21:04 UTC (permalink / raw)
  To: linux-fbdev-devel, akpm; +Cc: linux-arm-kernel, Ben Dooks

[-- Attachment #1: simtec/simtec-drivers-fb-backlight-match-entry.patch --]
[-- Type: text/plain, Size: 3129 bytes --]

Add the lcd_device being checked to the check_fb entry
of lcd_ops. This ensures that any driver using this
to check against it's own state can do so, and also
makes all the calls in lcd_ops more orthogonal in their
arguments.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Index: linux-2.6.26-rc5-quilt1/drivers/video/backlight/lcd.c
===================================================================
--- linux-2.6.26-rc5-quilt1.orig/drivers/video/backlight/lcd.c	2008-06-09 11:47:51.000000000 +0100
+++ linux-2.6.26-rc5-quilt1/drivers/video/backlight/lcd.c	2008-06-09 11:49:25.000000000 +0100
@@ -33,7 +33,7 @@ static int fb_notifier_callback(struct n
 	ld = container_of(self, struct lcd_device, fb_notif);
 	mutex_lock(&ld->ops_lock);
 	if (ld->ops)
-		if (!ld->ops->check_fb || ld->ops->check_fb(evdata->info))
+		if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info))
 			ld->ops->set_power(ld, *(int *)evdata->data);
 	mutex_unlock(&ld->ops_lock);
 	return 0;
Index: linux-2.6.26-rc5-quilt1/drivers/video/bf54x-lq043fb.c
===================================================================
--- linux-2.6.26-rc5-quilt1.orig/drivers/video/bf54x-lq043fb.c	2008-06-09 11:56:06.000000000 +0100
+++ linux-2.6.26-rc5-quilt1/drivers/video/bf54x-lq043fb.c	2008-06-09 11:56:24.000000000 +0100
@@ -478,7 +478,7 @@ static int bfin_lcd_set_contrast(struct 
 	return 0;
 }
 
-static int bfin_lcd_check_fb(struct fb_info *fi)
+static int bfin_lcd_check_fb(struct lcd_device *dev, struct fb_info *fi)
 {
 	if (!fi || (fi == &bfin_bf54x_fb))
 		return 1;
Index: linux-2.6.26-rc5-quilt1/drivers/video/bfin-t350mcqb-fb.c
===================================================================
--- linux-2.6.26-rc5-quilt1.orig/drivers/video/bfin-t350mcqb-fb.c	2008-06-09 11:56:40.000000000 +0100
+++ linux-2.6.26-rc5-quilt1/drivers/video/bfin-t350mcqb-fb.c	2008-06-09 11:56:51.000000000 +0100
@@ -396,7 +396,7 @@ static int bfin_lcd_set_contrast(struct 
 	return 0;
 }
 
-static int bfin_lcd_check_fb(struct fb_info *fi)
+static int bfin_lcd_check_fb(struct lcd_device *dev, struct fb_info *fi)
 {
 	if (!fi || (fi == &bfin_t350mcqb_fb))
 		return 1;
Index: linux-2.6.26-rc5-quilt1/include/linux/lcd.h
===================================================================
--- linux-2.6.26-rc5-quilt1.orig/include/linux/lcd.h	2008-06-09 11:23:48.000000000 +0100
+++ linux-2.6.26-rc5-quilt1/include/linux/lcd.h	2008-06-09 11:24:10.000000000 +0100
@@ -47,7 +47,7 @@ struct lcd_ops {
         int (*set_contrast)(struct lcd_device *, int contrast);
 	/* Check if given framebuffer device is the one LCD is bound to;
 	   return 0 if not, !=0 if it is. If NULL, lcd always matches the fb. */
-	int (*check_fb)(struct fb_info *);
+	int (*check_fb)(struct lcd_device *, struct fb_info *);
 };
 
 struct lcd_device {

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [patch 5/5] LCD: Add platform_lcd driver.
  2008-06-22 21:04 [patch 0/5] fb driver patches for next kernel Ben Dooks
                   ` (3 preceding siblings ...)
  2008-06-22 21:04 ` [patch 4/5] LCD: Add lcd_device to check_fb() entry in lcd_ops Ben Dooks
@ 2008-06-22 21:04 ` Ben Dooks
  4 siblings, 0 replies; 11+ messages in thread
From: Ben Dooks @ 2008-06-22 21:04 UTC (permalink / raw)
  To: linux-fbdev-devel, akpm; +Cc: linux-arm-kernel, Ben Dooks

[-- Attachment #1: simtec/simtec-drivers-fb-backlight-generic.patch --]
[-- Type: text/plain, Size: 6950 bytes --]

Add a platform_lcd driver to allow boards with simple
lcd power controls to register themselves easily.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>

Index: linux-2.6.26-rc5-quilt2/include/video/platform_lcd.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.26-rc5-quilt2/include/video/platform_lcd.h	2008-06-12 11:32:17.000000000 +0100
@@ -0,0 +1,21 @@
+/* include/video/platform_lcd.h
+ *
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Generic platform-device LCD power control interface.
+ *
+ * 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.
+ *
+*/
+
+struct plat_lcd_data;
+struct fb_info;
+
+struct plat_lcd_data {
+	void	(*set_power)(struct plat_lcd_data *, unsigned int power);
+	int	(*match_fb)(struct plat_lcd_data *, struct fb_info *);
+};
+
Index: linux-2.6.26-rc5-quilt2/drivers/video/backlight/Kconfig
===================================================================
--- linux-2.6.26-rc5-quilt2.orig/drivers/video/backlight/Kconfig	2008-06-12 10:49:49.000000000 +0100
+++ linux-2.6.26-rc5-quilt2/drivers/video/backlight/Kconfig	2008-06-12 11:25:22.000000000 +0100
@@ -53,6 +53,13 @@ config LCD_VGG2432A4
 	  If you have a VGG2432A4 panel based on the ILI9320 controller chip
 	  then say y to include a power driver for it.
 
+config LCD_PLATFORM
+	tristate "Platform LCD controls"
+	depends on LCD_CLASS_DEVICE
+	help
+	  This driver provides a platform-device registered LCD power
+	  control interface.
+
 #
 # Backlight
 #
Index: linux-2.6.26-rc5-quilt2/drivers/video/backlight/Makefile
===================================================================
--- linux-2.6.26-rc5-quilt2.orig/drivers/video/backlight/Makefile	2008-06-12 10:49:49.000000000 +0100
+++ linux-2.6.26-rc5-quilt2/drivers/video/backlight/Makefile	2008-06-12 11:25:22.000000000 +0100
@@ -3,6 +3,7 @@
 obj-$(CONFIG_LCD_CLASS_DEVICE)     += lcd.o
 obj-$(CONFIG_LCD_LTV350QV)	   += ltv350qv.o
 obj-$(CONFIG_LCD_ILI9320)	   += ili9320.o
+obj-$(CONFIG_LCD_PLATFORM)	   += platform_lcd.o
 obj-$(CONFIG_LCD_VGG2432A4)	   += vgg2432a4.o
 
 obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
Index: linux-2.6.26-rc5-quilt2/drivers/video/backlight/platform_lcd.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.26-rc5-quilt2/drivers/video/backlight/platform_lcd.c	2008-06-12 14:19:55.000000000 +0100
@@ -0,0 +1,172 @@
+/* drivers/video/backlight/platform_lcd.c
+ *
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Generic platform-device LCD power control interface.
+ *
+ * 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.
+ *
+*/
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/lcd.h>
+
+#include <video/platform_lcd.h>
+
+struct platform_lcd {
+	struct device		*us;
+	struct lcd_device	*lcd;
+	struct plat_lcd_data	*pdata;
+
+	unsigned int		 power;
+	unsigned int		 suspended : 1;
+};
+
+static inline struct platform_lcd *to_our_lcd(struct lcd_device *lcd)
+{
+	return lcd_get_data(lcd);
+}
+
+static int platform_lcd_get_power(struct lcd_device *lcd)
+{
+	struct platform_lcd *plcd = to_our_lcd(lcd);
+
+	return plcd->power;
+}
+
+static int platform_lcd_set_power(struct lcd_device *lcd, int power)
+{
+	struct platform_lcd *plcd = to_our_lcd(lcd);
+	int lcd_power = 1;
+
+	if (power == FB_BLANK_POWERDOWN || plcd->suspended)
+		lcd_power = 0;
+
+	plcd->pdata->set_power(plcd->pdata, lcd_power);
+	plcd->power = power;
+
+	return 0;
+}
+
+static int platform_lcd_match(struct lcd_device *lcd, struct fb_info *info)
+{
+	struct platform_lcd *plcd = to_our_lcd(lcd);
+	struct plat_lcd_data *pdata = plcd->pdata;
+
+	if (pdata->match_fb)
+		return pdata->match_fb(pdata, info);
+
+	return plcd->us->parent == info->dev;
+}
+
+static struct lcd_ops platform_lcd_ops = {
+	.get_power	= platform_lcd_get_power,
+	.set_power	= platform_lcd_set_power,
+	.check_fb	= platform_lcd_match,
+};
+
+static int __devinit platform_lcd_probe(struct platform_device *pdev)
+{
+	struct plat_lcd_data *pdata;
+	struct platform_lcd *plcd;
+	struct device *dev = &pdev->dev;
+	int err;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_err(dev, "no platform data supplied\n");
+		return -EINVAL;
+	}
+
+	plcd = kzalloc(sizeof(struct platform_lcd), GFP_KERNEL);
+	if (!plcd) {
+		dev_err(dev, "no memory for state\n");
+		return -ENOMEM;
+	}
+
+	plcd->us = dev;
+	plcd->pdata = pdata;
+	plcd->lcd = lcd_device_register("platform-lcd", dev,
+					plcd, &platform_lcd_ops);
+	if (IS_ERR(plcd->lcd)) {
+		dev_err(dev, "cannot register lcd device\n");
+		err = PTR_ERR(plcd->lcd);
+		goto err_mem;
+	}
+
+	platform_set_drvdata(pdev, plcd);
+	return 0;
+
+ err_mem:
+	kfree(plcd);
+	return err;
+}
+
+static int __devexit platform_lcd_remove(struct platform_device *pdev)
+{
+	struct platform_lcd *plcd = platform_get_drvdata(pdev);
+
+	lcd_device_unregister(plcd->lcd);
+	kfree(plcd);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int platform_lcd_suspend(struct platform_device *pdev, pm_message_t st)
+{
+	struct platform_lcd *plcd = platform_get_drvdata(pdev);
+
+	plcd->suspended = 1;
+	platform_lcd_set_power(plcd->lcd, plcd->power);
+
+	return 0;
+}
+
+static int platform_lcd_resume(struct platform_device *pdev)
+{
+	struct platform_lcd *plcd = platform_get_drvdata(pdev);
+
+	plcd->suspended = 0;
+	platform_lcd_set_power(plcd->lcd, plcd->power);
+
+	return 0;
+}
+#else
+#define s3c2410bl_suspend NULL
+#define s3c2410bl_resume  NULL
+#endif
+
+static struct platform_driver platform_lcd_driver = {
+	.driver		= {
+		.name	= "platform-lcd",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= platform_lcd_probe,
+	.remove		= __devexit_p(platform_lcd_remove),
+	.suspend        = platform_lcd_suspend,
+	.resume         = platform_lcd_resume,
+};
+
+static int __init platform_lcd_init(void)
+{
+	return platform_driver_register(&platform_lcd_driver);
+}
+
+static void __exit platform_lcd_cleanup(void)
+{
+	platform_driver_unregister(&platform_lcd_driver);
+}
+
+module_init(platform_lcd_init);
+module_exit(platform_lcd_cleanup);
+
+MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:platform-lcd");

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [patch 2/5] SM501: Restructure init to allow only 1 fb on an SM501
  2008-06-22 21:04 ` [patch 2/5] SM501: Restructure init to allow only 1 fb on an SM501 Ben Dooks
@ 2008-06-24  6:54   ` Andrew Morton
  2008-06-24 11:54     ` Ben Dooks
  0 siblings, 1 reply; 11+ messages in thread
From: Andrew Morton @ 2008-06-24  6:54 UTC (permalink / raw)
  To: Ben Dooks; +Cc: linux-fbdev-devel, linux-arm-kernel

On Sun, 22 Jun 2008 22:04:41 +0100 Ben Dooks <ben-linux@fluff.org> wrote:

> Add the ability to register only one of the two possible
> main framebuffer devices on the SM501 by passing platform
> data for only the framebuffer that you are interested in
> having.
> 
> As a side note, we update the init sequence to commonise
> the code that is executed twice, and fix a pair of missing
> frees that we didn't do on framebuffer exit, such as freeing
> the fb's cmap.
> 
> Signed-off-by: Ben Dooks <ben-linux@fluff.org>
> 
> Index: linux-2.6.26-rc6-quilt1/drivers/video/sm501fb.c
> ===================================================================
> --- linux-2.6.26-rc6-quilt1.orig/drivers/video/sm501fb.c	2008-06-18 19:02:14.000000000 +0100
> +++ linux-2.6.26-rc6-quilt1/drivers/video/sm501fb.c	2008-06-18 19:48:01.000000000 +0100
> @@ -143,6 +143,8 @@ static int sm501_alloc_mem(struct sm501f
>  			   unsigned int why, size_t size)
>  {
>  	unsigned int ptr = 0;
> +	unsigned int end;
> +	struct fb_info *fbi;
>  
>  	switch (why) {
>  	case SM501_MEMF_CURSOR:
> @@ -152,7 +154,9 @@ static int sm501_alloc_mem(struct sm501f
>  
>  	case SM501_MEMF_PANEL:
>  		ptr = inf->fbmem_len - size;
> -		if (ptr < inf->fb[0]->fix.smem_len)
> +		fbi = inf->fb[0];
> +
> +		if (fbi && ptr < fbi->fix.smem_len)
>  			return -ENOMEM;
>  
>  		break;
> @@ -162,11 +166,18 @@ static int sm501_alloc_mem(struct sm501f
>  		break;
>  
>  	case SM501_MEMF_ACCEL:
> -		ptr = inf->fb[0]->fix.smem_len;
> +		fbi = inf->fb[0];
> +		ptr = fbi ? fbi->fix.smem_len : 0;
> +
> +		fbi = inf->fb[1];
> +		if (fbi)
> +			end = (fbi->fix.smem_start - inf->fbmem_res->start);

Local variable `end' doesn't have an appropriate type.

It could be that overflows here are not possible due to hardware and
architecture limitations, but still, it's best to get these things
right.


-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [patch 3/5] FB: Add support for the ILI9320 video display controller.
  2008-06-22 21:04 ` [patch 3/5] FB: Add support for the ILI9320 video display controller Ben Dooks
@ 2008-06-24  7:07   ` Andrew Morton
  2008-06-24 13:37     ` Ben Dooks
  0 siblings, 1 reply; 11+ messages in thread
From: Andrew Morton @ 2008-06-24  7:07 UTC (permalink / raw)
  To: Ben Dooks; +Cc: linux-fbdev-devel, linux-arm-kernel

On Sun, 22 Jun 2008 22:04:42 +0100 Ben Dooks <ben-linux@fluff.org> wrote:

> Provide support for the ILI9320 display controller chip
> which is found in many LCD displays. Included with this
> is support for an example LCD using this chip, the
> VGG2432A4.
> 

Please pass this patch (and indeed all patches) through
scripts/checkpatch.pl.  It finds things which you wouldn't have sent
had you known they were there.

>
> ...
>
> +int __devinit ili9320_probe_spi(struct spi_device *spi,
> +				struct ili9320_client *client)
> +{
> +	struct ili9320_platdata *cfg = spi->dev.platform_data;
> +	struct device *dev = &spi->dev;
> +	struct ili9320 *ili;
> +	struct lcd_device *lcd;
> +	int ret = 0;
> +
> +	/* verify we where given some information */
> +
> +	if (cfg == NULL) {
> +		dev_err(dev, "no platform data supplied\n");
> +		return -EINVAL;
> +	}
> +
> +	if (cfg->hsize <= 0 || cfg->vsize <= 0 || cfg->reset == NULL) {
> +		dev_err(dev, "invalid platform data supplied\n");
> +		return -EINVAL;
> +	}
> +
> +	/* allocate and initialse our state */
> +
> +	ili = kzalloc(sizeof(struct ili9320), GFP_KERNEL);
> +	if (ili == NULL) {
> +		dev_err(dev, "no memory for device\n");
> +		return -ENOMEM;
> +	}
> +
> +	ili->access.spi.id = ILI9320_SPI_IDCODE | ILI9320_SPI_ID(1);
> +
> +	ili->dev = dev;
> +	ili->client = client;
> +	ili->power = FB_BLANK_POWERDOWN;
> +	ili->platdata = cfg;
> +
> +	dev_set_drvdata(&spi->dev, ili);
> +
> +	ili9320_setup_spi(ili, spi);
> +
> +	lcd = lcd_device_register("ili9320", dev, ili, &ili9320_ops);
> +	if (IS_ERR(lcd)) {
> +		dev_err(dev, "failed to register lcd device\n");
> +		ret = PTR_ERR(lcd);
> +		goto err_free;
> +	}
> +
> +	ili->lcd = lcd;
> +
> +	dev_info(dev, "initialising %s\n", client->name);
> +
> +	ret = ili9320_power(ili, FB_BLANK_UNBLANK);
> +	if (ret != 0) {
> +		dev_err(dev, "failed to set lcd power state\n");
> +		goto err_unregister;
> +	}
> +
> +	return 0;
> +
> + err_unregister:
> +	lcd_device_unregister(lcd);
> +
> + err_free:
> +	kfree(lcd);
> +	return ret;
> +}

urgh.  lcd_device_register() returns kmalloced memory which the caller
must kfree() after having run lcd_device_unregister()?  Who thought
that scheme up?  :(

Does this function leaks *ili on errors?

> +EXPORT_SYMBOL_GPL(ili9320_probe_spi);
> +
> +int __devexit ili9320_remove(struct ili9320 *lcd)
> +{
> +	ili9320_power(lcd, FB_BLANK_POWERDOWN);
> +
> +	lcd_device_unregister(lcd->lcd);
> +	kfree(lcd);
> +
> +	return 0;
> +}
> +
> +EXPORT_SYMBOL_GPL(ili9320_remove);

Did ili get freed in here?

>
> ...
>
> +/* Holder for register and value pairs. */
> +struct ili9320_reg {
> +	unsigned short		address;
> +	unsigned short		value;
> +};
> +
> +struct ili9320;
> +
> +struct ili9320_client {
> +	const char	*name;
> +	int	(*init)(struct ili9320 *ili, struct ili9320_platdata *cfg);
> +
> +};
> +/* Device attached via an SPI bus. */
> +struct  ili9320_spi {

s/  / /

> +	struct spi_device	*dev;
> +	struct spi_message	message;
> +	struct spi_transfer	xfer[2];
> +
> +	unsigned char		id;
> +	unsigned char		buffer_addr[4];
> +	unsigned char		buffer_data[4];
> +};
> +
>
> ...
>
> +static int vgg2432a4_lcd_init(struct ili9320 *lcd,
> +			      struct ili9320_platdata *cfg)
> +{
> +	unsigned int addr;
> +	int ret;
> +
> +	/* Set VCore before anything else (VGG243237-6UFLWA) */
> +	ret = ili9320_write(lcd, 0x00e5, 0x8000);
> +	if (ret)
> +		goto err_initial;
> +
> +	/* Start the oscillator up before we can do anything else. */
> +	ret = ili9320_write(lcd, ILI9320_OSCILATION, ILI9320_OSCILATION_OSC);
> +	if (ret)
> +		goto err_initial;
> +
> +	/* must wait at-lesat 10ms after starting */
> +	mdelay(15);

msleep()?  And everywhere else.  This function alone consumes maybe
half a second CPU time.

>
> ...
>

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [patch 2/5] SM501: Restructure init to allow only 1 fb on an SM501
  2008-06-24  6:54   ` Andrew Morton
@ 2008-06-24 11:54     ` Ben Dooks
  0 siblings, 0 replies; 11+ messages in thread
From: Ben Dooks @ 2008-06-24 11:54 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-fbdev-devel, linux-arm-kernel, Ben Dooks

On Mon, Jun 23, 2008 at 11:54:02PM -0700, Andrew Morton wrote:
> On Sun, 22 Jun 2008 22:04:41 +0100 Ben Dooks <ben-linux@fluff.org> wrote:

[snip]
 
> Local variable `end' doesn't have an appropriate type.
> 
> It could be that overflows here are not possible due to hardware and
> architecture limitations, but still, it's best to get these things
> right.

I've rewritten this to remove the need to go back and look at the
resource and also add some small cleanups/fixups. Will post once
I've had a chance to actually runtime test.

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [patch 3/5] FB: Add support for the ILI9320 video display controller.
  2008-06-24  7:07   ` Andrew Morton
@ 2008-06-24 13:37     ` Ben Dooks
  2008-06-24 17:51       ` Andrew Morton
  0 siblings, 1 reply; 11+ messages in thread
From: Ben Dooks @ 2008-06-24 13:37 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-fbdev-devel, linux-arm-kernel, Ben Dooks

On Tue, Jun 24, 2008 at 12:07:25AM -0700, Andrew Morton wrote:
> On Sun, 22 Jun 2008 22:04:42 +0100 Ben Dooks <ben-linux@fluff.org> wrote:
> 
> > Provide support for the ILI9320 display controller chip
> > which is found in many LCD displays. Included with this
> > is support for an example LCD using this chip, the
> > VGG2432A4.
> > 
> 
> Please pass this patch (and indeed all patches) through
> scripts/checkpatch.pl.  It finds things which you wouldn't have sent
> had you known they were there.
> 
> >
> > ...
> >
> > +int __devinit ili9320_probe_spi(struct spi_device *spi,
> > +				struct ili9320_client *client)
> > +{
> > +	struct ili9320_platdata *cfg = spi->dev.platform_data;
> > +	struct device *dev = &spi->dev;
> > +	struct ili9320 *ili;
> > +	struct lcd_device *lcd;
> > +	int ret = 0;
> > +
> > +	/* verify we where given some information */
> > +
> > +	if (cfg == NULL) {
> > +		dev_err(dev, "no platform data supplied\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (cfg->hsize <= 0 || cfg->vsize <= 0 || cfg->reset == NULL) {
> > +		dev_err(dev, "invalid platform data supplied\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	/* allocate and initialse our state */
> > +
> > +	ili = kzalloc(sizeof(struct ili9320), GFP_KERNEL);
> > +	if (ili == NULL) {
> > +		dev_err(dev, "no memory for device\n");
> > +		return -ENOMEM;
> > +	}
> > +
> > +	ili->access.spi.id = ILI9320_SPI_IDCODE | ILI9320_SPI_ID(1);
> > +
> > +	ili->dev = dev;
> > +	ili->client = client;
> > +	ili->power = FB_BLANK_POWERDOWN;
> > +	ili->platdata = cfg;
> > +
> > +	dev_set_drvdata(&spi->dev, ili);
> > +
> > +	ili9320_setup_spi(ili, spi);
> > +
> > +	lcd = lcd_device_register("ili9320", dev, ili, &ili9320_ops);
> > +	if (IS_ERR(lcd)) {
> > +		dev_err(dev, "failed to register lcd device\n");
> > +		ret = PTR_ERR(lcd);
> > +		goto err_free;
> > +	}
> > +
> > +	ili->lcd = lcd;
> > +
> > +	dev_info(dev, "initialising %s\n", client->name);
> > +
> > +	ret = ili9320_power(ili, FB_BLANK_UNBLANK);
> > +	if (ret != 0) {
> > +		dev_err(dev, "failed to set lcd power state\n");
> > +		goto err_unregister;
> > +	}
> > +
> > +	return 0;
> > +
> > + err_unregister:
> > +	lcd_device_unregister(lcd);
> > +
> > + err_free:
> > +	kfree(lcd);
> > +	return ret;
> > +}
> 
> urgh.  lcd_device_register() returns kmalloced memory which the caller
> must kfree() after having run lcd_device_unregister()?  Who thought
> that scheme up?  :(

This seems to be some confusion on my part about what was being freed
and where. There is a cleanup method on the device release and what
was meant to be freed was the ili.

> Does this function leaks *ili on errors?

I've fixed that.


 
> > +EXPORT_SYMBOL_GPL(ili9320_probe_spi);
> > +
> > +int __devexit ili9320_remove(struct ili9320 *lcd)
> > +{
> > +	ili9320_power(lcd, FB_BLANK_POWERDOWN);
> > +
> > +	lcd_device_unregister(lcd->lcd);
> > +	kfree(lcd);
> > +
> > +	return 0;
> > +}
> > +
> > +EXPORT_SYMBOL_GPL(ili9320_remove);
> 
> Did ili get freed in here?

Yes, but the naming confusion means that it looks like it
was freeing the lcd. I've renamed the argument to ili and
ensured we kfree() what we intended to kfree().

> > +static int vgg2432a4_lcd_init(struct ili9320 *lcd,
> > +			      struct ili9320_platdata *cfg)
> > +{
> > +	unsigned int addr;
> > +	int ret;
> > +
> > +	/* Set VCore before anything else (VGG243237-6UFLWA) */
> > +	ret = ili9320_write(lcd, 0x00e5, 0x8000);
> > +	if (ret)
> > +		goto err_initial;
> > +
> > +	/* Start the oscillator up before we can do anything else. */
> > +	ret = ili9320_write(lcd, ILI9320_OSCILATION, ILI9320_OSCILATION_OSC);
> > +	if (ret)
> > +		goto err_initial;
> > +
> > +	/* must wait at-lesat 10ms after starting */
> > +	mdelay(15);
> 
> msleep()?  And everywhere else.  This function alone consumes maybe
> half a second CPU time.

I've had no end of problems with getting suspend/resume working
with msleep in. I'll try and see if this can be changed, but I've
got lots of other patches in flight atm. 

Would you like a new patch for the other issues, or a fixup patch for
the driver?

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [patch 3/5] FB: Add support for the ILI9320 video display controller.
  2008-06-24 13:37     ` Ben Dooks
@ 2008-06-24 17:51       ` Andrew Morton
  0 siblings, 0 replies; 11+ messages in thread
From: Andrew Morton @ 2008-06-24 17:51 UTC (permalink / raw)
  To: Ben Dooks; +Cc: linux-fbdev-devel, linux-arm-kernel

On Tue, 24 Jun 2008 14:37:28 +0100 Ben Dooks <ben-linux@fluff.org> wrote:

> Would you like a new patch for the other issues, or a fixup patch for
> the driver?

Either is OK at this stage.  But I'll routinely convert the replacement
patch into an incremental so I can see what changed, thanks.

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2008-06-24 17:52 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-22 21:04 [patch 0/5] fb driver patches for next kernel Ben Dooks
2008-06-22 21:04 ` [patch 1/5] SM501: Add inversion controls for VBIASEN and FPEN Ben Dooks
2008-06-22 21:04 ` [patch 2/5] SM501: Restructure init to allow only 1 fb on an SM501 Ben Dooks
2008-06-24  6:54   ` Andrew Morton
2008-06-24 11:54     ` Ben Dooks
2008-06-22 21:04 ` [patch 3/5] FB: Add support for the ILI9320 video display controller Ben Dooks
2008-06-24  7:07   ` Andrew Morton
2008-06-24 13:37     ` Ben Dooks
2008-06-24 17:51       ` Andrew Morton
2008-06-22 21:04 ` [patch 4/5] LCD: Add lcd_device to check_fb() entry in lcd_ops Ben Dooks
2008-06-22 21:04 ` [patch 5/5] LCD: Add platform_lcd driver Ben Dooks

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).