Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* [PATCH v3 14/29] mb862xxfb: use display information in info not in var for panning
From: Laurent Pinchart @ 2011-07-08 11:14 UTC (permalink / raw)
  To: linux-fbdev

We must not use any information in the passed var besides xoffset,
yoffset and vmode as otherwise applications might abuse it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Anatolij Gustschin <agust@denx.de>
---
 drivers/video/mb862xx/mb862xxfbdrv.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/mb862xx/mb862xxfbdrv.c
index f70bd63..2191de0 100644
--- a/drivers/video/mb862xx/mb862xxfbdrv.c
+++ b/drivers/video/mb862xx/mb862xxfbdrv.c
@@ -278,7 +278,7 @@ static int mb862xxfb_pan(struct fb_var_screeninfo *var,
 	reg = pack(var->yoffset, var->xoffset);
 	outreg(disp, GC_L0WY_L0WX, reg);
 
-	reg = pack(var->yres_virtual, var->xres_virtual);
+	reg = pack(info->var.yres_virtual, info->var.xres_virtual);
 	outreg(disp, GC_L0WH_L0WW, reg);
 	return 0;
 }
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v3 13/29] intelfb: use display information in info not in var for panning
From: Laurent Pinchart @ 2011-07-08 11:14 UTC (permalink / raw)
  To: linux-fbdev

We must not use any information in the passed var besides xoffset,
yoffset and vmode as otherwise applications might abuse it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Maik Broemme <mbroemme@plusserver.de>
---
 drivers/video/intelfb/intelfbhw.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index 38065cf..fbad61d 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -390,12 +390,12 @@ int intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 	xoffset = ROUND_DOWN_TO(var->xoffset, 8);
 	yoffset = var->yoffset;
 
-	if ((xoffset + var->xres > var->xres_virtual) ||
-	    (yoffset + var->yres > var->yres_virtual))
+	if ((xoffset + info->var.xres > info->var.xres_virtual) ||
+	    (yoffset + info->var.yres > info->var.yres_virtual))
 		return -EINVAL;
 
 	offset = (yoffset * dinfo->pitch) +
-		 (xoffset * var->bits_per_pixel) / 8;
+		 (xoffset * info->var.bits_per_pixel) / 8;
 
 	offset += dinfo->fb.offset << 12;
 
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v3 12/29] imsttfb: use display information in info not in var for panning
From: Laurent Pinchart @ 2011-07-08 11:14 UTC (permalink / raw)
  To: linux-fbdev

We must not use any information in the passed var besides xoffset,
yoffset and vmode as otherwise applications might abuse it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/imsttfb.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
index efb2c10..8149356 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/imsttfb.c
@@ -749,7 +749,7 @@ set_offset (struct fb_var_screeninfo *var, struct fb_info *info)
 {
 	struct imstt_par *par = info->par;
 	__u32 off = var->yoffset * (info->fix.line_length >> 3)
-		    + ((var->xoffset * (var->bits_per_pixel >> 3)) >> 3);
+		    + ((var->xoffset * (info->var.bits_per_pixel >> 3)) >> 3);
 	write_reg_le32(par->dc_regs, SSR, off);
 }
 
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v3 11/29] hgafb: use display information in info not in var for panning
From: Laurent Pinchart @ 2011-07-08 11:14 UTC (permalink / raw)
  To: linux-fbdev

We must not use any information in the passed var besides xoffset,
yoffset and vmode as otherwise applications might abuse it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Ferenc Bakonyi <fero@drama.obuda.kando.hu>
Cc: Brent Cook <busterb@gmail.com>
---
 drivers/video/hgafb.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c
index 4052718..4394389 100644
--- a/drivers/video/hgafb.c
+++ b/drivers/video/hgafb.c
@@ -422,8 +422,8 @@ static int hgafb_pan_display(struct fb_var_screeninfo *var,
 		    var->xoffset)
 			return -EINVAL;
 	} else {
-		if (var->xoffset + var->xres > info->var.xres_virtual
-		 || var->yoffset + var->yres > info->var.yres_virtual
+		if (var->xoffset + info->var.xres > info->var.xres_virtual
+		 || var->yoffset + info->var.yres > info->var.yres_virtual
 		 || var->yoffset % 8)
 			return -EINVAL;
 	}
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v3 10/29] gxt4500: use display information in info not in var for panning
From: Laurent Pinchart @ 2011-07-08 11:14 UTC (permalink / raw)
  To: linux-fbdev

We must not use any information in the passed var besides xoffset,
yoffset and vmode as otherwise applications might abuse it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Paul Mackerras <paulus@samba.org>
---
 drivers/video/gxt4500.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/video/gxt4500.c b/drivers/video/gxt4500.c
index 896e53d..0fad23f 100644
--- a/drivers/video/gxt4500.c
+++ b/drivers/video/gxt4500.c
@@ -543,8 +543,8 @@ static int gxt4500_pan_display(struct fb_var_screeninfo *var,
 
 	if (var->xoffset & 7)
 		return -EINVAL;
-	if (var->xoffset + var->xres > var->xres_virtual ||
-	    var->yoffset + var->yres > var->yres_virtual)
+	if (var->xoffset + info->var.xres > info->var.xres_virtual ||
+	    var->yoffset + info->var.yres > info->var.yres_virtual)
 		return -EINVAL;
 
 	writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset);
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v3 09/29] g364fb: use display information in info not in var for panning
From: Laurent Pinchart @ 2011-07-08 11:14 UTC (permalink / raw)
  To: linux-fbdev

We must not use any information in the passed var besides xoffset,
yoffset and vmode as otherwise applications might abuse it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/g364fb.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/video/g364fb.c b/drivers/video/g364fb.c
index d662317..223896c 100644
--- a/drivers/video/g364fb.c
+++ b/drivers/video/g364fb.c
@@ -149,10 +149,11 @@ int g364fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 static int g364fb_pan_display(struct fb_var_screeninfo *var, 
 			      struct fb_info *info)
 {
-	if (var->xoffset || var->yoffset + var->yres > var->yres_virtual)
+	if (var->xoffset ||
+	    var->yoffset + info->var.yres > info->var.yres_virtual)
 		return -EINVAL;
 
-	*(unsigned int *) TOP_REG = var->yoffset * var->xres;
+	*(unsigned int *) TOP_REG = var->yoffset * info->var.xres;
 	return 0;
 }
 
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v3 08/29] fbdev: unicore32: use display information in info not in var for panning
From: Laurent Pinchart @ 2011-07-08 11:14 UTC (permalink / raw)
  To: linux-fbdev

We must not use any information in the passed var besides xoffset,
yoffset and vmode as otherwise applications might abuse it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Tested-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
Acked-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
---
 drivers/video/fb-puv3.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/video/fb-puv3.c b/drivers/video/fb-puv3.c
index 27f2c57..60a787f 100644
--- a/drivers/video/fb-puv3.c
+++ b/drivers/video/fb-puv3.c
@@ -624,8 +624,8 @@ static int unifb_pan_display(struct fb_var_screeninfo *var,
 		    || var->xoffset)
 			return -EINVAL;
 	} else {
-		if (var->xoffset + var->xres > info->var.xres_virtual ||
-		    var->yoffset + var->yres > info->var.yres_virtual)
+		if (var->xoffset + info->var.xres > info->var.xres_virtual ||
+		    var->yoffset + info->var.yres > info->var.yres_virtual)
 			return -EINVAL;
 	}
 	info->var.xoffset = var->xoffset;
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v3 07/29] fbdev: da8xx: use display information in info not in var for panning
From: Laurent Pinchart @ 2011-07-08 11:14 UTC (permalink / raw)
  To: linux-fbdev

We must not use any information in the passed var besides xoffset,
yoffset and vmode as otherwise applications might abuse it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Sudhakar Rajashekhara <sudhakar.raj@ti.com>
Cc: Martin Ambrose <martin@ti.com>
---
 drivers/video/da8xx-fb.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index fcdac87..8d4e4eb 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -877,8 +877,8 @@ static int da8xx_pan_display(struct fb_var_screeninfo *var,
 
 			start	= fix->smem_start +
 				new_var.yoffset * fix->line_length +
-				new_var.xoffset * var->bits_per_pixel / 8;
-			end	= start + var->yres * fix->line_length - 1;
+				new_var.xoffset * fbi->var.bits_per_pixel / 8;
+			end	= start + fbi->var.yres * fix->line_length - 1;
 			par->dma_start	= start;
 			par->dma_end	= end;
 		}
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v3 06/29] radeonfb: use display information in info not in var for panning
From: Laurent Pinchart @ 2011-07-08 11:14 UTC (permalink / raw)
  To: linux-fbdev

We must not use any information in the passed var besides xoffset,
yoffset and vmode as otherwise applications might abuse it. Also use the
aligned fix.line_length and not the (possible) unaligned xres_virtual.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 drivers/video/aty/radeon_base.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 32f8cf6..1506848 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -845,16 +845,16 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var,
 {
         struct radeonfb_info *rinfo = info->par;
 
-        if ((var->xoffset + var->xres > var->xres_virtual)
-	    || (var->yoffset + var->yres > var->yres_virtual))
-               return -EINVAL;
+	if ((var->xoffset + info->var.xres > info->var.xres_virtual)
+	    || (var->yoffset + info->var.yres > info->var.yres_virtual))
+		return -EINVAL;
                 
         if (rinfo->asleep)
         	return 0;
 
 	radeon_fifo_wait(2);
-        OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset)
-			     * var->bits_per_pixel / 8) & ~7);
+	OUTREG(CRTC_OFFSET, (var->yoffset * info->fix.line_length +
+			     var->xoffset * info->var.bits_per_pixel / 8) & ~7);
         return 0;
 }
 
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v3 05/29] atmel_lcdfb: use display information in info not in var for panning
From: Laurent Pinchart @ 2011-07-08 11:14 UTC (permalink / raw)
  To: linux-fbdev

We must not use any information in the passed var besides xoffset,
yoffset and vmode as otherwise applications might abuse it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Reviewed-by: Wolfram Sang <w.sang@pengutronix.de>
---
 drivers/video/atmel_lcdfb.c |   15 +++++++++------
 1 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 4484c72..5f1de1f 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -39,7 +39,8 @@
 					 | FBINFO_HWACCEL_YPAN)
 
 static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
-					struct fb_var_screeninfo *var)
+					struct fb_var_screeninfo *var,
+					struct fb_info *info)
 {
 
 }
@@ -50,14 +51,16 @@ static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
 					| FBINFO_HWACCEL_YPAN)
 
 static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
-				     struct fb_var_screeninfo *var)
+				     struct fb_var_screeninfo *var,
+				     struct fb_info *info)
 {
 	u32 dma2dcfg;
 	u32 pixeloff;
 
-	pixeloff = (var->xoffset * var->bits_per_pixel) & 0x1f;
+	pixeloff = (var->xoffset * info->var.bits_per_pixel) & 0x1f;
 
-	dma2dcfg = ((var->xres_virtual - var->xres) * var->bits_per_pixel) / 8;
+	dma2dcfg = (info->var.xres_virtual - info->var.xres)
+		 * info->var.bits_per_pixel / 8;
 	dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET;
 	lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg);
 
@@ -249,14 +252,14 @@ static void atmel_lcdfb_update_dma(struct fb_info *info,
 	unsigned long dma_addr;
 
 	dma_addr = (fix->smem_start + var->yoffset * fix->line_length
-		    + var->xoffset * var->bits_per_pixel / 8);
+		    + var->xoffset * info->var.bits_per_pixel / 8);
 
 	dma_addr &= ~3UL;
 
 	/* Set framebuffer DMA base address and pixel offset */
 	lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr);
 
-	atmel_lcdfb_update_dma2d(sinfo, var);
+	atmel_lcdfb_update_dma2d(sinfo, var, info);
 }
 
 static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo)
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v3 04/29] arkfb: use display information in info not in var for panning
From: Laurent Pinchart @ 2011-07-08 11:14 UTC (permalink / raw)
  To: linux-fbdev

We must not use any information in the passed var besides xoffset,
yoffset and vmode as otherwise applications might abuse it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Ondrej Zajicek <santiago@crfreenet.org>
---
 drivers/video/arkfb.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c
index 8686429..555dd4c 100644
--- a/drivers/video/arkfb.c
+++ b/drivers/video/arkfb.c
@@ -908,13 +908,14 @@ static int arkfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info
 	unsigned int offset;
 
 	/* Calculate the offset */
-	if (var->bits_per_pixel = 0) {
-		offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2);
+	if (info->var.bits_per_pixel = 0) {
+		offset = (var->yoffset / 16) * (info->var.xres_virtual / 2)
+		       + (var->xoffset / 2);
 		offset = offset >> 2;
 	} else {
 		offset = (var->yoffset * info->fix.line_length) +
-			 (var->xoffset * var->bits_per_pixel / 8);
-		offset = offset >> ((var->bits_per_pixel = 4) ? 2 : 3);
+			 (var->xoffset * info->var.bits_per_pixel / 8);
+		offset = offset >> ((info->var.bits_per_pixel = 4) ? 2 : 3);
 	}
 
 	/* Set the offset */
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v3 03/29] acornfb: use display information in info not in var for panning
From: Laurent Pinchart @ 2011-07-08 11:14 UTC (permalink / raw)
  To: linux-fbdev

We must not use any information in the passed var besides xoffset,
yoffset and vmode as otherwise applications might abuse it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/acornfb.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index 3bacc12..b303f17 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -850,9 +850,9 @@ acornfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 	u_int y_bottom = var->yoffset;
 
 	if (!(var->vmode & FB_VMODE_YWRAP))
-		y_bottom += var->yres;
+		y_bottom += info->var.yres;
 
-	if (y_bottom > var->yres_virtual)
+	if (y_bottom > info->var.yres_virtual)
 		return -EINVAL;
 
 	acornfb_update_dma(info, var);
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v3 02/29] acornfb: Dont BUG() on invalid pan parameters
From: Laurent Pinchart @ 2011-07-08 11:14 UTC (permalink / raw)
  To: linux-fbdev

The driver currently BUG()s if the pan parameters passed directly from
userspace are invalid. Return -EINVAL instead.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/acornfb.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index 6183a57..3bacc12 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -852,7 +852,8 @@ acornfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 	if (!(var->vmode & FB_VMODE_YWRAP))
 		y_bottom += var->yres;
 
-	BUG_ON(y_bottom > var->yres_virtual);
+	if (y_bottom > var->yres_virtual)
+		return -EINVAL;
 
 	acornfb_update_dma(info, var);
 
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v3 01/29] 68328fb: use display information in info not in var for panning
From: Laurent Pinchart @ 2011-07-08 11:14 UTC (permalink / raw)
  To: linux-fbdev

We must not use any information in the passed var besides xoffset,
yoffset and vmode as otherwise applications might abuse it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/68328fb.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c
index 75a39ea..a425d65 100644
--- a/drivers/video/68328fb.c
+++ b/drivers/video/68328fb.c
@@ -378,8 +378,8 @@ static int mc68x328fb_pan_display(struct fb_var_screeninfo *var,
 		    || var->xoffset)
 			return -EINVAL;
 	} else {
-		if (var->xoffset + var->xres > info->var.xres_virtual ||
-		    var->yoffset + var->yres > info->var.yres_virtual)
+		if (var->xoffset + info->var.xres > info->var.xres_virtual ||
+		    var->yoffset + info->var.yres > info->var.yres_virtual)
 			return -EINVAL;
 	}
 	info->var.xoffset = var->xoffset;
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v3 00/29] Use display information in info not in var for panning
From: Laurent Pinchart @ 2011-07-08 11:14 UTC (permalink / raw)
  To: linux-fbdev

Hi everybody,

Here's the third version of the FBIOPAN_DISPLAY fixes patch series.

As a reminder, while playing with the FBIOPAN_DISPLAY ioctl I noticed that many
drivers use information from the ioctl argument such as the display resolution
when they should use the current settings from the fb_info structure.

These 29 patches fix most of those drivers. Missing drivers are ivtv (for
which a patch has Andy Walls has already pushed a patch), sh_mobile_lcdcfb (for
which the fix is a bit more complex, I will work on it later) and viafb (for
which Florian Tobias Schandinat has already sent a patch).

The patches have been compile-tested on architectures for which I have a
working compiler (x86 and ARM) with allyesconfig. I don't own any hardware
supported by these drivers so I haven't been able to perform additional tests.

I've split the fixes in one patch per driver for easier review and handling of
potential problems. The patches can be squashed together if needed. I've tried
to CC individual driver maintainers when possible, and Acked-by lines received
in reply to the first version have been included.

Compared to v2, I've fixed a compile issue in the atmel_lcdfb driver and added
a couple of SoB lines.

Paul, is it time to push this for 3.1 ?

Laurent Pinchart (29):
  68328fb: use display information in info not in var for panning
  acornfb: Dont BUG() on invalid pan parameters
  acornfb: use display information in info not in var for panning
  arkfb: use display information in info not in var for panning
  atmel_lcdfb: use display information in info not in var for panning
  radeonfb: use display information in info not in var for panning
  fbdev: da8xx: use display information in info not in var for panning
  fbdev: unicore32: use display information in info not in var for
    panning
  g364fb: use display information in info not in var for panning
  gxt4500: use display information in info not in var for panning
  hgafb: use display information in info not in var for panning
  imsttfb: use display information in info not in var for panning
  intelfb: use display information in info not in var for panning
  mb862xxfb: use display information in info not in var for panning
  mx3fb: use display information in info not in var for panning
  neofb: use display information in info not in var for panning
  pm2fb: use display information in info not in var for panning
  pm3fb: use display information in info not in var for panning
  s3c-fb: use display information in info not in var for panning
  s3fb: use display information in info not in var for panning
  savagefb: use display information in info not in var for panning
  sisfb: use display information in info not in var for panning
  sm501fb: use display information in info not in var for panning
  tridentfb: use display information in info not in var for panning
  vfb: use display information in info not in var for panning
  vga16fb: use display information in info not in var for panning
  vt8500lcdfb: use display information in info not in var for panning
  vt8623fb: use display information in info not in var for panning
  staging: xgifb: use display information in info not in var for
    panning

 drivers/staging/xgifb/XGI_main_26.c    |   22 ++++++----------------
 drivers/video/68328fb.c                |    4 ++--
 drivers/video/acornfb.c                |    5 +++--
 drivers/video/arkfb.c                  |    9 +++++----
 drivers/video/atmel_lcdfb.c            |   15 +++++++++------
 drivers/video/aty/radeon_base.c        |   10 +++++-----
 drivers/video/da8xx-fb.c               |    4 ++--
 drivers/video/fb-puv3.c                |    4 ++--
 drivers/video/g364fb.c                 |    5 +++--
 drivers/video/gxt4500.c                |    4 ++--
 drivers/video/hgafb.c                  |    4 ++--
 drivers/video/imsttfb.c                |    2 +-
 drivers/video/intelfb/intelfbhw.c      |    6 +++---
 drivers/video/mb862xx/mb862xxfbdrv.c   |    2 +-
 drivers/video/mx3fb.c                  |    6 +++---
 drivers/video/neofb.c                  |    4 ++--
 drivers/video/pm2fb.c                  |    4 ++--
 drivers/video/pm3fb.c                  |    4 ++--
 drivers/video/s3c-fb.c                 |    2 +-
 drivers/video/s3fb.c                   |    7 ++++---
 drivers/video/savage/savagefb_driver.c |   16 +++++++---------
 drivers/video/sis/sis_main.c           |   30 ++++++++++--------------------
 drivers/video/sm501fb.c                |    6 +++---
 drivers/video/tridentfb.c              |    4 ++--
 drivers/video/vfb.c                    |    4 ++--
 drivers/video/vga16fb.c                |    2 +-
 drivers/video/vt8500lcdfb.c            |    4 ++--
 drivers/video/vt8623fb.c               |    9 +++++----
 28 files changed, 92 insertions(+), 106 deletions(-)

-- 
Regards,

Laurent Pinchart


^ permalink raw reply

* [PATCH] ARM: OMAP2+ Add Primview dispalys to panel-generic
From: Jan Weitzel @ 2011-07-08 10:47 UTC (permalink / raw)
  To: linux-arm-kernel

Add displays to panel-generic-dpi.c
Prime View PD035VL1 (640 x 480)
Prime View PD050VL1 (640 x 480)
Prime View PD104SLF (800 x 600)
Prime View PM070WL4 (800 x 480)

Signed-off-by: Jan Weitzel <j.weitzel@phytec.de>
---
 drivers/video/omap2/displays/panel-generic-dpi.c |  100 ++++++++++++++++++++++
 1 files changed, 100 insertions(+), 0 deletions(-)

diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 9c90f75..87d9ba1 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -232,6 +232,106 @@ static struct panel_config generic_dpi_panels[] = {
 		.power_off_delay	= 0,
 		.name			= "powertip_ph480272t",
 	},
+
+	/* Prime-View PD035VL1 */
+	{
+		{
+			.x_res		= 640,
+			.y_res		= 480,
+
+			.pixel_clock	= 25000,
+
+			.hsw		= 96,
+			.hfp		= 18,
+			.hbp		= 46,
+
+			.vsw		= 2,
+			.vfp		= 10,
+			.vbp		= 33,
+		},
+		.acbi			= 0x0,
+		.acb			= 0x28,
+		.config			= OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+					  OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC,
+		.power_on_delay		= 50,
+		.power_off_delay	= 100,
+		.name			= "pd035vl1",
+	},
+
+	/* Prime-View PD050VL1 */
+	{
+		{
+			.x_res		= 640,
+			.y_res		= 480,
+
+			.pixel_clock	= 25000,
+
+			.hsw		= 96,
+			.hfp		= 18,
+			.hbp		= 46,
+
+			.vsw		= 2,
+			.vfp		= 10,
+			.vbp		= 33,
+		},
+		.acbi			= 0x0,
+		.acb			= 0x28,
+		.config			= OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+					  OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC,
+		.power_on_delay		= 50,
+		.power_off_delay	= 100,
+		.name			= "pd050vl1",
+	},
+
+	/* Prime-View PM070WL4 */
+	{
+		{
+			.x_res		= 800,
+			.y_res		= 480,
+
+			.pixel_clock	= 32000,
+
+			.hsw		= 128,
+			.hfp		= 42,
+			.hbp		= 86,
+
+			.vsw		= 2,
+			.vfp		= 10,
+			.vbp		= 33,
+		},
+		.acbi			= 0x0,
+		.acb			= 0x28,
+		.config			= OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+					  OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC,
+		.power_on_delay		= 50,
+		.power_off_delay	= 100,
+		.name			= "pm070wl4",
+	},
+
+	/* Prime-View PD104SLF */
+	{
+		{
+			.x_res		= 800,
+			.y_res		= 600,
+
+			.pixel_clock	= 40000,
+
+			.hsw		= 128,
+			.hfp		= 42,
+			.hbp		= 86,
+
+			.vsw		= 4,
+			.vfp		= 1,
+			.vbp		= 23,
+		},
+		.acbi			= 0x0,
+		.acb			= 0x28,
+		.config			= OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+					  OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC,
+		.power_on_delay		= 50,
+		.power_off_delay	= 100,
+		.name			= "pd104slf",
+	},
 };
 
 struct panel_drv_data {
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH] carminefb: Fix module parameters permissions
From: Jean Delvare @ 2011-07-08  9:04 UTC (permalink / raw)
  To: linux-fbdev

The third parameter of module_param is supposed to be an octal value.
The missing leading "0" causes the following:

$ ls -l /sys/module/carminefb/parameters/
total 0
-rw-rwxr-- 1 root root 4096 Jul  8 08:55 fb_displays
-rw-rwxr-- 1 root root 4096 Jul  8 08:55 fb_mode
-rw-rwxr-- 1 root root 4096 Jul  8 08:55 fb_mode_str

After fixing the perm parameter, we get the expected:

$ ls -l /sys/module/carminefb/parameters/
total 0
-r--r--r-- 1 root root 4096 Jul  8 08:56 fb_displays
-r--r--r-- 1 root root 4096 Jul  8 08:56 fb_mode
-r--r--r-- 1 root root 4096 Jul  8 08:56 fb_mode_str

Signed-off-by: Jean Delvare <jdelvare@suse.de>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: Sebastian Siewior <bigeasy@linutronix.de>
Cc: stable@kernel.org
---
 drivers/video/carminefb.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

--- linux-3.0-rc6.orig/drivers/video/carminefb.c	2011-07-08 08:47:52.000000000 +0200
+++ linux-3.0-rc6/drivers/video/carminefb.c	2011-07-08 08:55:21.000000000 +0200
@@ -32,11 +32,11 @@
 #define CARMINEFB_DEFAULT_VIDEO_MODE	1
 
 static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
-module_param(fb_mode, uint, 444);
+module_param(fb_mode, uint, 0444);
 MODULE_PARM_DESC(fb_mode, "Initial video mode as integer.");
 
 static char *fb_mode_str;
-module_param(fb_mode_str, charp, 444);
+module_param(fb_mode_str, charp, 0444);
 MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters.");
 
 /*
@@ -46,7 +46,7 @@ MODULE_PARM_DESC(fb_mode_str, "Initial v
  * 0b010 Display 1
  */
 static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1;
-module_param(fb_displays, int, 444);
+module_param(fb_displays, int, 0444);
 MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used");
 
 struct carmine_hw {

-- 
Jean Delvare
Suse L3

^ permalink raw reply

* [PATCH] backlight/ep93xx_bl: fix section mismatch
From: H Hartley Sweeten @ 2011-07-07 18:56 UTC (permalink / raw)
  To: Linux Kernel; +Cc: linux-fbdev, rpurdie, lethal

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Cc: Richard Purdie <rpurdie@rpsys.net>
Cc: Paul Mundt <lethal@linux-sh.org>

---

diff --git a/drivers/video/backlight/ep93xx_bl.c b/drivers/video/backlight/ep93xx_bl.c
index 9f1e389..91dce60 100644
--- a/drivers/video/backlight/ep93xx_bl.c
+++ b/drivers/video/backlight/ep93xx_bl.c
@@ -65,7 +65,7 @@ static const struct backlight_ops ep93xxbl_ops = {
 	.get_brightness	= ep93xxbl_get_brightness,
 };
 
-static int __init ep93xxbl_probe(struct platform_device *dev)
+static int __devinit ep93xxbl_probe(struct platform_device *dev)
 {
 	struct ep93xxbl *ep93xxbl;
 	struct backlight_device *bl;
@@ -103,7 +103,7 @@ static int __init ep93xxbl_probe(struct platform_device *dev)
 	return 0;
 }
 
-static int ep93xxbl_remove(struct platform_device *dev)
+static int __devexit ep93xxbl_remove(struct platform_device *dev)
 {
 	struct backlight_device *bl = platform_get_drvdata(dev);
 

^ permalink raw reply related

* [PATCH] drivers/video: use strings to specify the Freescale DIU monitor port
From: Timur Tabi @ 2011-07-07 16:51 UTC (permalink / raw)
  To: kumar.gala, lethal, linuxppc-dev, linux-fbdev

Instead of using ill-defined numbers (0, 1, and 2) for the monitor port, allow
the user to specify the port by name ("dvi", "lvds", or "dlvds").  This works
on the kernel command line, the module command-line, and the sysfs "monitor"
device.

Note that changing the monitor port does not currently work on the P1022DS,
because the code that talks to the PIXIS FPGA is broken.

Signed-off-by: Timur Tabi <timur@freescale.com>
---
 arch/powerpc/platforms/512x/mpc512x_shared.c |   22 +++-----
 arch/powerpc/platforms/85xx/p1022_ds.c       |   47 ++++++++---------
 arch/powerpc/platforms/86xx/mpc8610_hpcd.c   |   55 +++++++++-----------
 arch/powerpc/sysdev/fsl_soc.h                |   25 ++++++---
 drivers/video/fsl-diu-fb.c                   |   73 +++++++++++++++++++------
 5 files changed, 128 insertions(+), 94 deletions(-)

diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index e41ebbd..3dc62f9 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -66,8 +66,8 @@ struct fsl_diu_shared_fb {
 	bool		in_use;
 };
 
-unsigned int mpc512x_get_pixel_format(unsigned int bits_per_pixel,
-				      int monitor_port)
+u32 mpc512x_get_pixel_format(enum fsl_diu_monitor_port port,
+			     unsigned int bits_per_pixel)
 {
 	switch (bits_per_pixel) {
 	case 32:
@@ -80,11 +80,12 @@ unsigned int mpc512x_get_pixel_format(unsigned int bits_per_pixel,
 	return 0x00000400;
 }
 
-void mpc512x_set_gamma_table(int monitor_port, char *gamma_table_base)
+void mpc512x_set_gamma_table(enum fsl_diu_monitor_port port,
+			     char *gamma_table_base)
 {
 }
 
-void mpc512x_set_monitor_port(int monitor_port)
+void mpc512x_set_monitor_port(enum fsl_diu_monitor_port port)
 {
 }
 
@@ -182,14 +183,10 @@ void mpc512x_set_pixel_clock(unsigned int pixclock)
 	iounmap(ccm);
 }
 
-ssize_t mpc512x_show_monitor_port(int monitor_port, char *buf)
+enum fsl_diu_monitor_port
+mpc512x_valid_monitor_port(enum fsl_diu_monitor_port port)
 {
-	return sprintf(buf, "0 - 5121 LCD\n");
-}
-
-int mpc512x_set_sysfs_monitor_port(int val)
-{
-	return 0;
+	return FSL_DIU_PORT_DVI;
 }
 
 static struct fsl_diu_shared_fb __attribute__ ((__aligned__(8))) diu_shared_fb;
@@ -332,8 +329,7 @@ void __init mpc512x_setup_diu(void)
 	diu_ops.set_gamma_table		= mpc512x_set_gamma_table;
 	diu_ops.set_monitor_port	= mpc512x_set_monitor_port;
 	diu_ops.set_pixel_clock		= mpc512x_set_pixel_clock;
-	diu_ops.show_monitor_port	= mpc512x_show_monitor_port;
-	diu_ops.set_sysfs_monitor_port	= mpc512x_set_sysfs_monitor_port;
+	diu_ops.valid_monitor_port	= mpc512x_valid_monitor_port;
 	diu_ops.release_bootmem		= mpc512x_release_bootmem;
 #endif
 }
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 266b3aa..c01c727 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -93,8 +93,8 @@
  * The Area Descriptor is a 32-bit value that determine which bits in each
  * pixel are to be used for each color.
  */
-static unsigned int p1022ds_get_pixel_format(unsigned int bits_per_pixel,
-	int monitor_port)
+static u32 p1022ds_get_pixel_format(enum fsl_diu_monitor_port port,
+				    unsigned int bits_per_pixel)
 {
 	switch (bits_per_pixel) {
 	case 32:
@@ -118,7 +118,8 @@ static unsigned int p1022ds_get_pixel_format(unsigned int bits_per_pixel,
  * On some boards, the gamma table for some ports may need to be modified.
  * This is not the case on the P1022DS, so we do nothing.
 */
-static void p1022ds_set_gamma_table(int monitor_port, char *gamma_table_base)
+static void p1022ds_set_gamma_table(enum fsl_diu_monitor_port port,
+				    char *gamma_table_base)
 {
 }
 
@@ -126,7 +127,7 @@ static void p1022ds_set_gamma_table(int monitor_port, char *gamma_table_base)
  * p1022ds_set_monitor_port: switch the output to a different monitor port
  *
  */
-static void p1022ds_set_monitor_port(int monitor_port)
+static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
 {
 	struct device_node *pixis_node;
 	void __iomem *pixis;
@@ -145,19 +146,21 @@ static void p1022ds_set_monitor_port(int monitor_port)
 	}
 	brdcfg1 = pixis + 9;	/* BRDCFG1 is at offset 9 in the ngPIXIS */
 
-	switch (monitor_port) {
-	case 0: /* DVI */
+	switch (port) {
+	case FSL_DIU_PORT_DVI:
+		printk(KERN_INFO "%s:%u\n", __func__, __LINE__);
 		/* Enable the DVI port, disable the DFP and the backlight */
 		clrsetbits_8(brdcfg1, PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT,
 			     PX_BRDCFG1_DVIEN);
 		break;
-	case 1: /* Single link LVDS */
+	case FSL_DIU_PORT_LVDS:
+		printk(KERN_INFO "%s:%u\n", __func__, __LINE__);
 		/* Enable the DFP port, disable the DVI and the backlight */
 		clrsetbits_8(brdcfg1, PX_BRDCFG1_DVIEN | PX_BRDCFG1_BACKLIGHT,
 			     PX_BRDCFG1_DFPEN);
 		break;
 	default:
-		pr_err("p1022ds: unsupported monitor port %i\n", monitor_port);
+		pr_err("p1022ds: unsupported monitor port %i\n", port);
 	}
 
 	iounmap(pixis);
@@ -214,23 +217,18 @@ void p1022ds_set_pixel_clock(unsigned int pixclock)
 }
 
 /**
- * p1022ds_show_monitor_port: show the current monitor
- *
- * This function returns a string indicating whether the current monitor is
- * set to DVI or LVDS.
- */
-ssize_t p1022ds_show_monitor_port(int monitor_port, char *buf)
-{
-	return sprintf(buf, "%c0 - DVI\n%c1 - Single link LVDS\n",
-		monitor_port = 0 ? '*' : ' ', monitor_port = 1 ? '*' : ' ');
-}
-
-/**
- * p1022ds_set_sysfs_monitor_port: set the monitor port for sysfs
+ * p1022ds_valid_monitor_port: set the monitor port for sysfs
  */
-int p1022ds_set_sysfs_monitor_port(int val)
+enum fsl_diu_monitor_port
+p1022ds_valid_monitor_port(enum fsl_diu_monitor_port port)
 {
-	return val < 2 ? val : 0;
+	switch (port) {
+	case FSL_DIU_PORT_DVI:
+	case FSL_DIU_PORT_LVDS:
+		return port;
+	default:
+		return FSL_DIU_PORT_DVI; /* Dual-link LVDS is not supported */
+	}
 }
 
 #endif
@@ -305,8 +303,7 @@ static void __init p1022_ds_setup_arch(void)
 	diu_ops.set_gamma_table		= p1022ds_set_gamma_table;
 	diu_ops.set_monitor_port	= p1022ds_set_monitor_port;
 	diu_ops.set_pixel_clock		= p1022ds_set_pixel_clock;
-	diu_ops.show_monitor_port	= p1022ds_show_monitor_port;
-	diu_ops.set_sysfs_monitor_port	= p1022ds_set_sysfs_monitor_port;
+	diu_ops.valid_monitor_port	= p1022ds_valid_monitor_port;
 #endif
 
 #ifdef CONFIG_SMP
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index 74e018e..13fa9a6 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -152,10 +152,10 @@ machine_device_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices);
 	(c2 << AD_COMP_2_SHIFT) | (c1 << AD_COMP_1_SHIFT) | \
 	(c0 << AD_COMP_0_SHIFT) | (size << AD_PIXEL_S_SHIFT))
 
-unsigned int mpc8610hpcd_get_pixel_format(unsigned int bits_per_pixel,
-						int monitor_port)
+u32 mpc8610hpcd_get_pixel_format(enum fsl_diu_monitor_port port,
+				 unsigned int bits_per_pixel)
 {
-	static const unsigned long pixelformat[][3] = {
+	static const u32 pixelformat[][3] = {
 		{
 			MAKE_AD(3, 0, 2, 1, 3, 8, 8, 8, 8),
 			MAKE_AD(4, 2, 0, 1, 2, 8, 8, 8, 0),
@@ -170,7 +170,8 @@ unsigned int mpc8610hpcd_get_pixel_format(unsigned int bits_per_pixel,
 	unsigned int arch_monitor;
 
 	/* The DVI port is mis-wired on revision 1 of this board. */
-	arch_monitor = ((*pixis_arch = 0x01) && (monitor_port = 0))? 0 : 1;
+	arch_monitor +		((*pixis_arch = 0x01) && (port = FSL_DIU_PORT_DVI)) ? 0 : 1;
 
 	switch (bits_per_pixel) {
 	case 32:
@@ -185,10 +186,11 @@ unsigned int mpc8610hpcd_get_pixel_format(unsigned int bits_per_pixel,
 	}
 }
 
-void mpc8610hpcd_set_gamma_table(int monitor_port, char *gamma_table_base)
+void mpc8610hpcd_set_gamma_table(enum fsl_diu_monitor_port port,
+				 char *gamma_table_base)
 {
 	int i;
-	if (monitor_port = 2) {		/* dual link LVDS */
+	if (port = FSL_DIU_PORT_DLVDS) {
 		for (i = 0; i < 256*3; i++)
 			gamma_table_base[i] = (gamma_table_base[i] << 2) |
 					 ((gamma_table_base[i] >> 6) & 0x03);
@@ -199,17 +201,21 @@ void mpc8610hpcd_set_gamma_table(int monitor_port, char *gamma_table_base)
 #define PX_BRDCFG0_DLINK	(1 << 4)
 #define PX_BRDCFG0_DIU_MASK	(PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK)
 
-void mpc8610hpcd_set_monitor_port(int monitor_port)
+void mpc8610hpcd_set_monitor_port(enum fsl_diu_monitor_port port)
 {
-	static const u8 bdcfg[] = {
-		PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK,
-		PX_BRDCFG0_DLINK,
-		0,
-	};
-
-	if (monitor_port < 3)
+	switch (port) {
+	case FSL_DIU_PORT_DVI:
 		clrsetbits_8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK,
-			     bdcfg[monitor_port]);
+			     PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK);
+		break;
+	case FSL_DIU_PORT_LVDS:
+		clrsetbits_8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK,
+			     PX_BRDCFG0_DLINK);
+		break;
+	case FSL_DIU_PORT_DLVDS:
+		clrbits8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK);
+		break;
+	}
 }
 
 /**
@@ -262,20 +268,10 @@ void mpc8610hpcd_set_pixel_clock(unsigned int pixclock)
 	iounmap(guts);
 }
 
-ssize_t mpc8610hpcd_show_monitor_port(int monitor_port, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE,
-			"%c0 - DVI\n"
-			"%c1 - Single link LVDS\n"
-			"%c2 - Dual link LVDS\n",
-			monitor_port = 0 ? '*' : ' ',
-			monitor_port = 1 ? '*' : ' ',
-			monitor_port = 2 ? '*' : ' ');
-}
-
-int mpc8610hpcd_set_sysfs_monitor_port(int val)
+enum fsl_diu_monitor_port
+mpc8610hpcd_valid_monitor_port(enum fsl_diu_monitor_port port)
 {
-	return val < 3 ? val : 0;
+	return port;
 }
 
 #endif
@@ -307,8 +303,7 @@ static void __init mpc86xx_hpcd_setup_arch(void)
 	diu_ops.set_gamma_table		= mpc8610hpcd_set_gamma_table;
 	diu_ops.set_monitor_port	= mpc8610hpcd_set_monitor_port;
 	diu_ops.set_pixel_clock		= mpc8610hpcd_set_pixel_clock;
-	diu_ops.show_monitor_port	= mpc8610hpcd_show_monitor_port;
-	diu_ops.set_sysfs_monitor_port	= mpc8610hpcd_set_sysfs_monitor_port;
+	diu_ops.valid_monitor_port	= mpc8610hpcd_valid_monitor_port;
 #endif
 
 	pixis_node = of_find_compatible_node(NULL, NULL, "fsl,fpga-pixis");
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index 5360948..064bc70 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -22,15 +22,24 @@ struct device_node;
 extern void fsl_rstcr_restart(char *cmd);
 
 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
+
+/* The different ports that the DIU can be connected to */
+enum fsl_diu_monitor_port {
+	FSL_DIU_PORT_DVI,	/* DVI */
+	FSL_DIU_PORT_LVDS,	/* Single-link LVDS */
+	FSL_DIU_PORT_DLVDS	/* Dual-link LVDS */
+};
+
 struct platform_diu_data_ops {
-	unsigned int (*get_pixel_format) (unsigned int bits_per_pixel,
-		int monitor_port);
-	void (*set_gamma_table) (int monitor_port, char *gamma_table_base);
-	void (*set_monitor_port) (int monitor_port);
-	void (*set_pixel_clock) (unsigned int pixclock);
-	ssize_t (*show_monitor_port) (int monitor_port, char *buf);
-	int (*set_sysfs_monitor_port) (int val);
-	void (*release_bootmem) (void);
+	u32 (*get_pixel_format)(enum fsl_diu_monitor_port port,
+		unsigned int bpp);
+	void (*set_gamma_table)(enum fsl_diu_monitor_port port,
+		char *gamma_table_base);
+	void (*set_monitor_port)(enum fsl_diu_monitor_port port);
+	void (*set_pixel_clock)(unsigned int pixclock);
+	enum fsl_diu_monitor_port (*valid_monitor_port)
+		(enum fsl_diu_monitor_port port);
+	void (*release_bootmem)(void);
 };
 
 extern struct platform_diu_data_ops diu_ops;
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 0acc7d6..9c6837e 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -31,8 +31,6 @@
 #include <linux/uaccess.h>
 #include <linux/vmalloc.h>
 
-#include <linux/of_platform.h>
-
 #include <sysdev/fsl_soc.h>
 #include <linux/fsl-diu-fb.h>
 #include "edid.h"
@@ -183,7 +181,8 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
 
 static char *fb_mode = "1024x768-32@60";
 static unsigned long default_bpp = 32;
-static int monitor_port;
+static enum fsl_diu_monitor_port monitor_port;
+static char *monitor_string;
 
 #if defined(CONFIG_NOT_COHERENT_CACHE)
 static u8 *coherence_data;
@@ -201,7 +200,7 @@ struct fsl_diu_data {
 	void *dummy_aoi_virt;
 	unsigned int irq;
 	int fb_enabled;
-	int monitor_port;
+	enum fsl_diu_monitor_port monitor_port;
 };
 
 struct mfb_info {
@@ -282,6 +281,37 @@ static struct diu_hw dr = {
 static struct diu_pool pool;
 
 /**
+ * fsl_diu_name_to_port - convert a port name to a monitor port enum
+ *
+ * Takes the name of a monitor port ("dvi", "lvds", or "dlvds") and returns
+ * the enum fsl_diu_monitor_port that corresponds to that string.
+ *
+ * For compatibility with older versions, a number ("0", "1", or "2") is also
+ * supported.
+ *
+ * If the string is unknown, DVI is assumed.
+ *
+ * If the particular port is not supported by the platform, another port
+ * (platform-specific) is chosen instead.
+ */
+static enum fsl_diu_monitor_port fsl_diu_name_to_port(const char *s)
+{
+	enum fsl_diu_monitor_port port = FSL_DIU_PORT_DVI;
+	unsigned long val;
+
+	if (s) {
+		if (!strict_strtoul(s, 10, &val) && (val <= 2))
+			port = (enum fsl_diu_monitor_port) val;
+		else if (strncmp(s, "lvds", 4) = 0)
+			port = FSL_DIU_PORT_LVDS;
+		else if (strncmp(s, "dlvds", 5) = 0)
+			port = FSL_DIU_PORT_DLVDS;
+	}
+
+	return diu_ops.valid_monitor_port(port);
+}
+
+/**
  * fsl_diu_alloc - allocate memory for the DIU
  * @size: number of bytes to allocate
  * @param: returned physical address of memory
@@ -832,8 +862,8 @@ static int fsl_diu_set_par(struct fb_info *info)
 	}
 
 	ad->pix_fmt -		diu_ops.get_pixel_format(var->bits_per_pixel,
-					 machine_data->monitor_port);
+		cpu_to_be32(diu_ops.get_pixel_format(machine_data->monitor_port,
+						     var->bits_per_pixel));
 	ad->addr    = cpu_to_le32(info->fix.smem_start);
 	ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) |
 				var->xres_virtual) | mfbi->g_alpha;
@@ -1439,16 +1469,12 @@ static void free_buf(struct device *dev, struct diu_addr *buf, u32 size,
 static ssize_t store_monitor(struct device *device,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
-	int old_monitor_port;
-	unsigned long val;
+	enum fsl_diu_monitor_port old_monitor_port;
 	struct fsl_diu_data *machine_data  		container_of(attr, struct fsl_diu_data, dev_attr);
 
-	if (strict_strtoul(buf, 10, &val))
-		return 0;
-
 	old_monitor_port = machine_data->monitor_port;
-	machine_data->monitor_port = diu_ops.set_sysfs_monitor_port(val);
+	machine_data->monitor_port = fsl_diu_name_to_port(buf);
 
 	if (old_monitor_port != machine_data->monitor_port) {
 		/* All AOIs need adjust pixel format
@@ -1468,7 +1494,17 @@ static ssize_t show_monitor(struct device *device,
 {
 	struct fsl_diu_data *machine_data  		container_of(attr, struct fsl_diu_data, dev_attr);
-	return diu_ops.show_monitor_port(machine_data->monitor_port, buf);
+
+	switch (machine_data->monitor_port) {
+	case FSL_DIU_PORT_DVI:
+		return sprintf(buf, "DVI\n");
+	case FSL_DIU_PORT_LVDS:
+		return sprintf(buf, "Single-link LVDS\n");
+	case FSL_DIU_PORT_DLVDS:
+		return sprintf(buf, "Dual-link LVDS\n");
+	}
+
+	return 0;
 }
 
 static int __devinit fsl_diu_probe(struct platform_device *ofdev)
@@ -1692,8 +1728,7 @@ static int __init fsl_diu_setup(char *options)
 		if (!*opt)
 			continue;
 		if (!strncmp(opt, "monitor=", 8)) {
-			if (!strict_strtoul(opt + 8, 10, &val) && (val <= 2))
-				monitor_port = val;
+			monitor_port = fsl_diu_name_to_port(opt + 8);
 		} else if (!strncmp(opt, "bpp=", 4)) {
 			if (!strict_strtoul(opt + 4, 10, &val))
 				default_bpp = val;
@@ -1746,6 +1781,8 @@ static int __init fsl_diu_init(void)
 	if (fb_get_options("fslfb", &option))
 		return -ENODEV;
 	fsl_diu_setup(option);
+#else
+	monitor_port = fsl_diu_name_to_port(monitor_string);
 #endif
 	printk(KERN_INFO "Freescale DIU driver\n");
 
@@ -1812,7 +1849,7 @@ MODULE_PARM_DESC(mode,
 	"Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
 module_param_named(bpp, default_bpp, ulong, 0);
 MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode");
-module_param_named(monitor, monitor_port, int, 0);
-MODULE_PARM_DESC(monitor,
-	"Specify the monitor port (0, 1 or 2) if supported by the platform");
+module_param_named(monitor, monitor_string, charp, 0);
+MODULE_PARM_DESC(monitor, "Specify the monitor port "
+	"(\"dvi\", \"lvds\", or \"dlvds\") if supported by the platform");
 
-- 
1.7.3.4



^ permalink raw reply related

* [PATCH] video: s3c2410: remove unused variable
From: Wolfram Sang @ 2011-07-07 10:20 UTC (permalink / raw)
  To: linux-fbdev

Fixes:

drivers/video/s3c2410fb.c: In function 's3c2410fb_cpufreq_transition':
drivers/video/s3c2410fb.c:770:24: warning: unused variable 'freqs'

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Cc: Paul Mundt <lethal@linux-sh.org>
---
 drivers/video/s3c2410fb.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index 0aa1376..798144a 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -767,7 +767,6 @@ static irqreturn_t s3c2410fb_irq(int irq, void *dev_id)
 static int s3c2410fb_cpufreq_transition(struct notifier_block *nb,
 					unsigned long val, void *data)
 {
-	struct cpufreq_freqs *freqs = data;
 	struct s3c2410fb_info *info;
 	struct fb_info *fbinfo;
 	long delta_f;
-- 
1.7.5.4


^ permalink raw reply related

* [PATCH] OMAPFB: make debug message more useful
From: Andy Doan @ 2011-07-06 17:08 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: Tomi Valkeinen, Andy Doan

Make the debug message useful by printing the name of the device
that no associated driver could be found for.

Signed-off-by: Andy Doan <andy.doan@linaro.org>
---
 drivers/video/omap2/omapfb/omapfb-main.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 602b71a..e5a64b3 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -2373,7 +2373,8 @@ static int omapfb_probe(struct platform_device *pdev)
 		omap_dss_get_device(dssdev);
 
 		if (!dssdev->driver) {
-			dev_err(&pdev->dev, "no driver for display\n");
+			dev_err(&pdev->dev, "no driver for display: %s\n",
+				dssdev->name);
 			r = -ENODEV;
 		}
 
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH] video: output: remove video_output_{register,unregister}
From: Pavel Roskin @ 2011-07-06 15:02 UTC (permalink / raw)
  To: linux-fbdev

Signed-off-by: Pavel Roskin <proski@gnu.org>

video_output_register() and video_output_unregister() are not called
anywhere in the kernel code.  Also remove the fallback implementation
from the header.
---
 drivers/video/output.c       |   38 --------------------------------------
 include/linux/video_output.h |   19 -------------------
 2 files changed, 0 insertions(+), 57 deletions(-)

diff --git a/drivers/video/output.c b/drivers/video/output.c
index 0d6f2cd..858b6d1 100644
--- a/drivers/video/output.c
+++ b/drivers/video/output.c
@@ -81,44 +81,6 @@ static struct class video_output_class = {
 	.dev_attrs = video_output_attributes,
 };
 
-struct output_device *video_output_register(const char *name,
-	struct device *dev,
-	void *devdata,
-	struct output_properties *op)
-{
-	struct output_device *new_dev;
-	int ret_code = 0;
-
-	new_dev = kzalloc(sizeof(struct output_device),GFP_KERNEL);
-	if (!new_dev) {
-		ret_code = -ENOMEM;
-		goto error_return;
-	}
-	new_dev->props = op;
-	new_dev->dev.class = &video_output_class;
-	new_dev->dev.parent = dev;
-	dev_set_name(&new_dev->dev, name);
-	dev_set_drvdata(&new_dev->dev, devdata);
-	ret_code = device_register(&new_dev->dev);
-	if (ret_code) {
-		kfree(new_dev);
-		goto error_return;
-	}
-	return new_dev;
-
-error_return:
-	return ERR_PTR(ret_code);
-}
-EXPORT_SYMBOL(video_output_register);
-
-void video_output_unregister(struct output_device *dev)
-{
-	if (!dev)
-		return;
-	device_unregister(&dev->dev);
-}
-EXPORT_SYMBOL(video_output_unregister);
-
 static void __exit video_output_class_exit(void)
 {
 	class_unregister(&video_output_class);
diff --git a/include/linux/video_output.h b/include/linux/video_output.h
index ed5cdeb..be03118 100644
--- a/include/linux/video_output.h
+++ b/include/linux/video_output.h
@@ -35,23 +35,4 @@ struct output_device {
 	struct device dev;
 };
 #define to_output_device(obj) container_of(obj, struct output_device, dev)
-#if	defined(CONFIG_VIDEO_OUTPUT_CONTROL) || defined(CONFIG_VIDEO_OUTPUT_CONTROL_MODULE)
-struct output_device *video_output_register(const char *name,
-	struct device *dev,
-	void *devdata,
-	struct output_properties *op);
-void video_output_unregister(struct output_device *dev);
-#else
-static struct output_device *video_output_register(const char *name,
-        struct device *dev,
-        void *devdata,
-        struct output_properties *op)
-{
-	return ERR_PTR(-ENODEV);
-}
-static void video_output_unregister(struct output_device *dev)
-{
-	return;
-}
-#endif
 #endif

^ permalink raw reply related

* [PATCH] drivers/video/udlfb bind framebuffer to interface.
From: bernie @ 2011-07-06  0:04 UTC (permalink / raw)
  To: linux-fbdev

From: Kay Sievers <kay.sievers@vrfy.org>

Udlfb has been binding the framebuffer device to its parent, which
isn't correct and causes confusion with operations like udev remove.

Coming plug and play multiseat support is dependent on this fix.

Signed-off-by: Bernie Thompson <bernie@plugable.com>
---
 drivers/video/udlfb.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c
index 816a4fd..c6584c9 100644
--- a/drivers/video/udlfb.c
+++ b/drivers/video/udlfb.c
@@ -1549,7 +1549,7 @@ static int dlfb_usb_probe(struct usb_interface *interface,
 	/* We don't register a new USB class. Our client interface is fbdev */
 
 	/* allocates framebuffer driver structure, not framebuffer memory */
-	info = framebuffer_alloc(0, &usbdev->dev);
+	info = framebuffer_alloc(0, &interface->dev);
 	if (!info) {
 		retval = -ENOMEM;
 		pr_err("framebuffer_alloc failed\n");
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH v2] video: da8xx-fb: Interrupt configuration of revised LCDC IP
From: Manjunathappa, Prakash @ 2011-07-05 10:33 UTC (permalink / raw)
  To: linux-fbdev

An upcoming SoC of TI comes with an LCD controller which is an updated
version of that found on TI's DA850 SoC. The da8xx-fb driver can support
this LCD with some enhancements.
This patch adds support for updated interrupt configuration on the new
SoC.
1) Registers for setting and clearing interrupts are different.
2) Raw and masked status registers are different.
The updates have been tested on an emulation platform for new features
and the patch has been tested on DA850 platform to make sure nothing
existing breaks.

Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
---
Since v1:
1)Added verification details in commit message.
2)Removed random white spaces in code.
 drivers/video/da8xx-fb.c |  151 +++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 142 insertions(+), 9 deletions(-)

diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index fcdac87..620f1c3 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -35,6 +35,9 @@
 
 #define DRIVER_NAME "da8xx_lcdc"
 
+#define LCD_VERSION_1	1
+#define LCD_VERSION_2	2
+
 /* LCD Status Register */
 #define LCD_END_OF_FRAME1		BIT(9)
 #define LCD_END_OF_FRAME0		BIT(8)
@@ -49,7 +52,9 @@
 #define LCD_DMA_BURST_4			0x2
 #define LCD_DMA_BURST_8			0x3
 #define LCD_DMA_BURST_16		0x4
-#define LCD_END_OF_FRAME_INT_ENA	BIT(2)
+#define LCD_V1_END_OF_FRAME_INT_ENA	BIT(2)
+#define LCD_V2_END_OF_FRAME0_INT_ENA	BIT(8)
+#define LCD_V2_END_OF_FRAME1_INT_ENA	BIT(9)
 #define LCD_DUAL_FRAME_BUFFER_ENABLE	BIT(0)
 
 /* LCD Control Register */
@@ -65,12 +70,18 @@
 #define LCD_MONO_8BIT_MODE		BIT(9)
 #define LCD_RASTER_ORDER		BIT(8)
 #define LCD_TFT_MODE			BIT(7)
-#define LCD_UNDERFLOW_INT_ENA		BIT(6)
-#define LCD_PL_ENABLE			BIT(4)
+#define LCD_V1_UNDERFLOW_INT_ENA	BIT(6)
+#define LCD_V2_UNDERFLOW_INT_ENA	BIT(5)
+#define LCD_V1_PL_INT_ENA		BIT(4)
+#define LCD_V2_PL_INT_ENA		BIT(6)
 #define LCD_MONOCHROME_MODE		BIT(1)
 #define LCD_RASTER_ENABLE		BIT(0)
 #define LCD_TFT_ALT_ENABLE		BIT(23)
 #define LCD_STN_565_ENABLE		BIT(24)
+#define LCD_V2_DMA_CLK_EN		BIT(2)
+#define LCD_V2_LIDD_CLK_EN		BIT(1)
+#define LCD_V2_CORE_CLK_EN		BIT(0)
+#define LCD_V2_LPP_B10			26
 
 /* LCD Raster Timing 2 Register */
 #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x)	((x) << 16)
@@ -82,6 +93,7 @@
 #define LCD_INVERT_FRAME_CLOCK			BIT(20)
 
 /* LCD Block */
+#define  LCD_PID_REG				0x0
 #define  LCD_CTRL_REG				0x4
 #define  LCD_STAT_REG				0x8
 #define  LCD_RASTER_CTRL_REG			0x28
@@ -94,6 +106,17 @@
 #define  LCD_DMA_FRM_BUF_BASE_ADDR_1_REG	0x4C
 #define  LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG	0x50
 
+/* Interrupt Registers available only in Version 2 */
+#define  LCD_RAW_STAT_REG			0x58
+#define  LCD_MASKED_STAT_REG			0x5c
+#define  LCD_INT_ENABLE_SET_REG			0x60
+#define  LCD_INT_ENABLE_CLR_REG			0x64
+#define  LCD_END_OF_INT_IND_REG			0x68
+
+/* Clock registers available only on Version 2 */
+#define  LCD_CLK_ENABLE_REG			0x6c
+#define  LCD_CLK_RESET_REG			0x70
+
 #define LCD_NUM_BUFFERS	2
 
 #define WSI_TIMEOUT	50
@@ -105,6 +128,8 @@
 
 static resource_size_t da8xx_fb_reg_base;
 static struct resource *lcdc_regs;
+static unsigned int lcd_revision;
+static irq_handler_t lcdc_irq_handler;
 
 static inline unsigned int lcdc_read(unsigned int addr)
 {
@@ -240,6 +265,7 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
 	u32 end;
 	u32 reg_ras;
 	u32 reg_dma;
+	u32 reg_int;
 
 	/* init reg to clear PLM (loading mode) fields */
 	reg_ras = lcdc_read(LCD_RASTER_CTRL_REG);
@@ -252,7 +278,14 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
 		end      = par->dma_end;
 
 		reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY);
-		reg_dma |= LCD_END_OF_FRAME_INT_ENA;
+		if (lcd_revision = LCD_VERSION_1) {
+			reg_dma |= LCD_V1_END_OF_FRAME_INT_ENA;
+		} else {
+			reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
+				LCD_V2_END_OF_FRAME0_INT_ENA |
+				LCD_V2_END_OF_FRAME1_INT_ENA;
+			lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
+		}
 		reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE;
 
 		lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
@@ -264,7 +297,14 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
 		end      = start + par->palette_sz - 1;
 
 		reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY);
-		reg_ras |= LCD_PL_ENABLE;
+
+		if (lcd_revision = LCD_VERSION_1) {
+			reg_ras |= LCD_V1_PL_INT_ENA;
+		} else {
+			reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
+				LCD_V2_PL_INT_ENA;
+			lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
+		}
 
 		lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
 		lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
@@ -348,6 +388,7 @@ static void lcd_cfg_vertical_sync(int back_porch, int pulse_width,
 static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
 {
 	u32 reg;
+	u32 reg_int;
 
 	reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE |
 						LCD_MONO_8BIT_MODE |
@@ -375,7 +416,13 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
 	}
 
 	/* enable additional interrupts here */
-	reg |= LCD_UNDERFLOW_INT_ENA;
+	if (lcd_revision = LCD_VERSION_1) {
+		reg |= LCD_V1_UNDERFLOW_INT_ENA;
+	} else {
+		reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
+			LCD_V2_UNDERFLOW_INT_ENA;
+		lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
+	}
 
 	lcdc_write(reg, LCD_RASTER_CTRL_REG);
 
@@ -511,6 +558,9 @@ static void lcd_reset(struct da8xx_fb_par *par)
 	/* DMA has to be disabled */
 	lcdc_write(0, LCD_DMA_CTRL_REG);
 	lcdc_write(0, LCD_RASTER_CTRL_REG);
+
+	if (lcd_revision = LCD_VERSION_2)
+		lcdc_write(0, LCD_INT_ENABLE_SET_REG);
 }
 
 static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
@@ -523,6 +573,11 @@ static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
 	/* Configure the LCD clock divisor. */
 	lcdc_write(LCD_CLK_DIVISOR(div) |
 			(LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
+
+	if (lcd_revision = LCD_VERSION_2)
+		lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN |
+				LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG);
+
 }
 
 static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
@@ -583,7 +638,63 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
 	return 0;
 }
 
-static irqreturn_t lcdc_irq_handler(int irq, void *arg)
+/* IRQ handler for version 2 of LCDC */
+static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
+{
+	struct da8xx_fb_par *par = arg;
+	u32 stat = lcdc_read(LCD_MASKED_STAT_REG);
+	u32 reg_int;
+
+	if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
+		lcd_disable_raster();
+		lcdc_write(stat, LCD_MASKED_STAT_REG);
+		lcd_enable_raster();
+	} else if (stat & LCD_PL_LOAD_DONE) {
+		/*
+		 * Must disable raster before changing state of any control bit.
+		 * And also must be disabled before clearing the PL loading
+		 * interrupt via the following write to the status register. If
+		 * this is done after then one gets multiple PL done interrupts.
+		 */
+		lcd_disable_raster();
+
+		lcdc_write(stat, LCD_MASKED_STAT_REG);
+
+		/* Disable PL completion inerrupt */
+		reg_int = lcdc_read(LCD_INT_ENABLE_CLR_REG) |
+		       (LCD_V2_PL_INT_ENA);
+		lcdc_write(reg_int, LCD_INT_ENABLE_CLR_REG);
+
+		/* Setup and start data loading mode */
+		lcd_blit(LOAD_DATA, par);
+	} else {
+		lcdc_write(stat, LCD_MASKED_STAT_REG);
+
+		if (stat & LCD_END_OF_FRAME0) {
+			lcdc_write(par->dma_start,
+				   LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
+			lcdc_write(par->dma_end,
+				   LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
+			par->vsync_flag = 1;
+			wake_up_interruptible(&par->vsync_wait);
+		}
+
+		if (stat & LCD_END_OF_FRAME1) {
+			lcdc_write(par->dma_start,
+				   LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
+			lcdc_write(par->dma_end,
+				   LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
+			par->vsync_flag = 1;
+			wake_up_interruptible(&par->vsync_wait);
+		}
+	}
+
+	lcdc_write(0, LCD_END_OF_INT_IND_REG);
+	return IRQ_HANDLED;
+}
+
+/* IRQ handler for version 1 LCDC */
+static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
 {
 	struct da8xx_fb_par *par = arg;
 	u32 stat = lcdc_read(LCD_STAT_REG);
@@ -606,7 +717,7 @@ static irqreturn_t lcdc_irq_handler(int irq, void *arg)
 
 		/* Disable PL completion inerrupt */
 		reg_ras  = lcdc_read(LCD_RASTER_CTRL_REG);
-		reg_ras &= ~LCD_PL_ENABLE;
+		reg_ras &= ~LCD_V1_PL_INT_ENA;
 		lcdc_write(reg_ras, LCD_RASTER_CTRL_REG);
 
 		/* Setup and start data loading mode */
@@ -945,6 +1056,22 @@ static int __devinit fb_probe(struct platform_device *device)
 	if (ret)
 		goto err_clk_put;
 
+	/* Determine LCD IP Version */
+	switch (lcdc_read(LCD_PID_REG)) {
+	case 0x4C100102:
+		lcd_revision = LCD_VERSION_1;
+		break;
+	case 0x4F200800:
+		lcd_revision = LCD_VERSION_2;
+		break;
+	default:
+		dev_warn(&device->dev, "Unknown PID Reg value 0x%x, "
+				"defaulting to LCD revision 1\n",
+				lcdc_read(LCD_PID_REG));
+		lcd_revision = LCD_VERSION_1;
+		break;
+	}
+
 	for (i = 0, lcdc_info = known_lcd_panels;
 		i < ARRAY_SIZE(known_lcd_panels);
 		i++, lcdc_info++) {
@@ -1085,7 +1212,13 @@ static int __devinit fb_probe(struct platform_device *device)
 	}
 #endif
 
-	ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par);
+	if (lcd_revision = LCD_VERSION_1)
+		lcdc_irq_handler = lcdc_irq_handler_rev01;
+	else
+		lcdc_irq_handler = lcdc_irq_handler_rev02;
+
+	ret = request_irq(par->irq, lcdc_irq_handler, 0,
+			DRIVER_NAME, par);
 	if (ret)
 		goto irq_freq;
 	return 0;
-- 
1.7.1


^ permalink raw reply related

* [PATCH v3] video: Add Aeroflex Gaisler GRVGA framebuffer device driver
From: Kristoffer Glembo @ 2011-07-05  7:29 UTC (permalink / raw)
  To: linux-fbdev

This patch adds support for the GRVGA framebuffer IP core from Aeroflex Gaisler.
The device is used in LEON SPARCV8 based System on Chips. Documentation can
be found here: www.gaisler.com/products/grlib/grip.pdf.

Signed-off-by: Kristoffer Glembo <kristoffer@gaisler.com>
---
 drivers/video/Kconfig  |   10 +
 drivers/video/Makefile |    1 +
 drivers/video/grvga.c  |  579 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 590 insertions(+), 0 deletions(-)
 create mode 100644 drivers/video/grvga.c

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 549b960..18ee201 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -259,6 +259,16 @@ config FB_TILEBLITTING
 comment "Frame buffer hardware drivers"
 	depends on FB
 
+config FB_GRVGA
+	tristate "Aeroflex Gaisler framebuffer support"
+	depends on FB && SPARC
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	This enables support for the SVGACTRL framebuffer in the GRLIB IP library from Aeroflex Gaisler.
+
+
 config FB_CIRRUS
 	tristate "Cirrus Logic support"
 	depends on FB && (ZORRO || PCI)
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 8b83129..4cff5ec 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_FB_DEFERRED_IO)   += fb_defio.o
 obj-$(CONFIG_FB_WMT_GE_ROPS)   += wmt_ge_rops.o
 
 # Hardware specific drivers go first
+obj-$(CONFIG_FB_GRVGA)            += grvga.o
 obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p_planar.o
 obj-$(CONFIG_FB_ARC)              += arcfb.o
 obj-$(CONFIG_FB_CLPS711X)         += clps711xfb.o
diff --git a/drivers/video/grvga.c b/drivers/video/grvga.c
new file mode 100644
index 0000000..f37e025
--- /dev/null
+++ b/drivers/video/grvga.c
@@ -0,0 +1,579 @@
+/*
+ * Driver for Aeroflex Gaisler SVGACTRL framebuffer device.
+ *
+ * 2011 (c) Aeroflex Gaisler AB
+ *
+ * Full documentation of the core can be found here:
+ * http://www.gaisler.com/products/grlib/grip.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Contributors: Kristoffer Glembo <kristoffer@gaisler.com>
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/mm.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+
+struct grvga_regs {
+	u32 status; 		/* 0x00 */
+	u32 video_length; 	/* 0x04 */
+	u32 front_porch;	/* 0x08 */
+	u32 sync_length;	/* 0x0C */
+	u32 line_length;	/* 0x10 */
+	u32 fb_pos;		/* 0x14 */
+	u32 clk_vector[4];	/* 0x18 */
+	u32 clut;	        /* 0x20 */
+};
+
+struct grvga_par {
+	struct grvga_regs *regs;
+	u32 color_palette[16];  /* 16 entry pseudo palette used by fbcon in true color mode */
+	int clk_sel;
+	int fb_alloced;         /* = 1 if framebuffer is allocated in main memory */
+};
+
+
+static const struct fb_videomode grvga_modedb[] = {
+    {
+	/* 640x480 @ 60 Hz */
+	NULL, 60, 640, 480, 40000, 48, 16, 39, 11, 96, 2,
+	0, FB_VMODE_NONINTERLACED
+    }, {
+	/* 800x600 @ 60 Hz */
+	NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4,
+	0, FB_VMODE_NONINTERLACED
+    }, {
+	/* 800x600 @ 72 Hz */
+	NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
+	0, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1024x768 @ 60 Hz */
+	NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
+	0, FB_VMODE_NONINTERLACED
+    }
+ };
+
+static struct fb_fix_screeninfo grvga_fix __initdata = {
+	.id =		"AG SVGACTRL",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =       FB_VISUAL_PSEUDOCOLOR,
+	.xpanstep =	0,
+	.ypanstep =	1,
+	.ywrapstep =	0,
+	.accel =	FB_ACCEL_NONE,
+};
+
+static int grvga_check_var(struct fb_var_screeninfo *var,
+			   struct fb_info *info)
+{
+	struct grvga_par *par = info->par;
+	int i;
+
+	if (!var->xres)
+		var->xres = 1;
+	if (!var->yres)
+		var->yres = 1;
+	if (var->bits_per_pixel <= 8)
+		var->bits_per_pixel = 8;
+	else if (var->bits_per_pixel <= 16)
+		var->bits_per_pixel = 16;
+	else if (var->bits_per_pixel <= 24)
+		var->bits_per_pixel = 24;
+	else if (var->bits_per_pixel <= 32)
+		var->bits_per_pixel = 32;
+	else
+		return -EINVAL;
+
+	var->xres_virtual = var->xres;
+	var->yres_virtual = 2*var->yres;
+
+	if (info->fix.smem_len) {
+		if ((var->yres_virtual*var->xres_virtual*var->bits_per_pixel/8) > info->fix.smem_len)
+			return -ENOMEM;
+	}
+
+	/* Which clocks that are available can be read out in these registers */
+	for (i = 0; i <= 3 ; i++) {
+		if (var->pixclock = par->regs->clk_vector[i])
+			break;
+	}
+	if (i <= 3)
+		par->clk_sel = i;
+	else
+		return -EINVAL;
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		var->red   = (struct fb_bitfield) {0, 8, 0};      /* offset, length, msb-right */
+		var->green = (struct fb_bitfield) {0, 8, 0};
+		var->blue  = (struct fb_bitfield) {0, 8, 0};
+		var->transp = (struct fb_bitfield) {0, 0, 0};
+		break;
+	case 16:
+		var->red   = (struct fb_bitfield) {11, 5, 0};
+		var->green = (struct fb_bitfield) {5, 6, 0};
+		var->blue  = (struct fb_bitfield) {0, 5, 0};
+		var->transp = (struct fb_bitfield) {0, 0, 0};
+		break;
+	case 24:
+	case 32:
+		var->red   = (struct fb_bitfield) {16, 8, 0};
+		var->green = (struct fb_bitfield) {8, 8, 0};
+		var->blue  = (struct fb_bitfield) {0, 8, 0};
+		var->transp = (struct fb_bitfield) {24, 8, 0};
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int grvga_set_par(struct fb_info *info)
+{
+
+	u32 func = 0;
+	struct grvga_par *par = info->par;
+
+	__raw_writel(((info->var.yres - 1) << 16) | (info->var.xres - 1),
+		     &par->regs->video_length);
+
+	__raw_writel((info->var.lower_margin << 16) | (info->var.right_margin),
+		     &par->regs->front_porch);
+
+	__raw_writel((info->var.vsync_len << 16) | (info->var.hsync_len),
+		     &par->regs->sync_length);
+
+	__raw_writel(((info->var.yres + info->var.lower_margin + info->var.upper_margin + info->var.vsync_len - 1) << 16) |
+		     (info->var.xres + info->var.right_margin + info->var.left_margin + info->var.hsync_len - 1),
+		     &par->regs->line_length);
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		func = 1;
+		break;
+	case 16:
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		func = 2;
+		break;
+	case 24:
+	case 32:
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		func = 3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	__raw_writel((par->clk_sel << 6) | (func << 4) | 1,
+		     &par->regs->status);
+
+	info->fix.line_length = (info->var.xres_virtual*info->var.bits_per_pixel)/8;
+	return 0;
+}
+
+static int grvga_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info)
+{
+	struct grvga_par *par;
+	par = info->par;
+
+	if (regno >= 256)	/* Size of CLUT */
+		return -EINVAL;
+
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+
+
+#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
+
+	red    = CNVT_TOHW(red,   info->var.red.length);
+	green  = CNVT_TOHW(green, info->var.green.length);
+	blue   = CNVT_TOHW(blue,  info->var.blue.length);
+	transp = CNVT_TOHW(transp, info->var.transp.length);
+
+#undef CNVT_TOHW
+
+	/* In PSEUDOCOLOR we use the hardware CLUT */
+	if (info->fix.visual = FB_VISUAL_PSEUDOCOLOR)
+		__raw_writel((regno << 24) | (red << 16) | (green << 8) | blue,
+			     &par->regs->clut);
+
+	/* Truecolor uses the pseudo palette */
+	else if (info->fix.visual = FB_VISUAL_TRUECOLOR) {
+		u32 v;
+		if (regno >= 16)
+			return -EINVAL;
+
+
+		v =     (red    << info->var.red.offset)   |
+			(green  << info->var.green.offset) |
+			(blue   << info->var.blue.offset)  |
+			(transp << info->var.transp.offset);
+
+		((u32 *) (info->pseudo_palette))[regno] = v;
+	}
+	return 0;
+}
+
+static int grvga_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	struct grvga_par *par = info->par;
+	struct fb_fix_screeninfo *fix = &info->fix;
+	u32 base_addr;
+
+	if (var->xoffset != 0)
+		return -EINVAL;
+
+	base_addr = fix->smem_start + (var->yoffset * fix->line_length);
+	base_addr &= ~3UL;
+
+	/* Set framebuffer base address  */
+	__raw_writel(base_addr,
+		     &par->regs->fb_pos);
+
+	return 0;
+}
+
+static struct fb_ops grvga_ops = {
+	.owner          = THIS_MODULE,
+	.fb_check_var   = grvga_check_var,
+	.fb_set_par	= grvga_set_par,
+	.fb_setcolreg   = grvga_setcolreg,
+	.fb_pan_display = grvga_pan_display,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit
+};
+
+static int __init grvga_parse_custom(char *options,
+				     struct fb_var_screeninfo *screendata)
+{
+	char *this_opt;
+	int count = 0;
+	if (!options || !*options)
+		return -1;
+
+	while ((this_opt = strsep(&options, " ")) != NULL) {
+		if (!*this_opt)
+			continue;
+
+		switch (count) {
+		case 0:
+			screendata->pixclock = simple_strtoul(this_opt, NULL, 0);
+			count++;
+			break;
+		case 1:
+			screendata->xres = screendata->xres_virtual = simple_strtoul(this_opt, NULL, 0);
+			count++;
+			break;
+		case 2:
+			screendata->right_margin = simple_strtoul(this_opt, NULL, 0);
+			count++;
+			break;
+		case 3:
+			screendata->hsync_len = simple_strtoul(this_opt, NULL, 0);
+			count++;
+			break;
+		case 4:
+			screendata->left_margin = simple_strtoul(this_opt, NULL, 0);
+			count++;
+			break;
+		case 5:
+			screendata->yres = screendata->yres_virtual = simple_strtoul(this_opt, NULL, 0);
+			count++;
+			break;
+		case 6:
+			screendata->lower_margin = simple_strtoul(this_opt, NULL, 0);
+			count++;
+			break;
+		case 7:
+			screendata->vsync_len = simple_strtoul(this_opt, NULL, 0);
+			count++;
+			break;
+		case 8:
+			screendata->upper_margin = simple_strtoul(this_opt, NULL, 0);
+			count++;
+			break;
+		case 9:
+			screendata->bits_per_pixel = simple_strtoul(this_opt, NULL, 0);
+			count++;
+			break;
+		default:
+			return -1;
+		}
+	}
+	screendata->activate  = FB_ACTIVATE_NOW;
+	screendata->vmode     = FB_VMODE_NONINTERLACED;
+	return 0;
+}
+
+static int __devinit grvga_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	int retval = -ENOMEM;
+	unsigned long virtual_start;
+	unsigned long grvga_fix_addr = 0;
+	unsigned long physical_start = 0;
+	unsigned long grvga_mem_size = 0;
+	struct grvga_par *par = NULL;
+	char *options = NULL, *mode_opt = NULL;
+
+	info = framebuffer_alloc(sizeof(struct grvga_par), &dev->dev);
+	if (!info) {
+		dev_err(&dev->dev, "framebuffer_alloc failed\n");
+		return -ENOMEM;
+	}
+
+	/* Expecting: "grvga: modestring, [addr:<framebuffer physical address>], [size:<framebuffer size>]
+	 *
+	 * If modestring is custom:<custom mode string> we parse the string which then contains all videoparameters
+	 * If address is left out, we allocate memory,
+	 * if size is left out we only allocate enough to support the given mode.
+	 */
+	if (fb_get_options("grvga", &options)) {
+		retval = -ENODEV;
+		goto err;
+	}
+
+	if (!options || !*options)
+		options =  "640x480-8@60";
+
+	while (1) {
+		char *this_opt = strsep(&options, ",");
+
+		if (!this_opt)
+			break;
+
+		if (!strncmp(this_opt, "custom", 6)) {
+			if (grvga_parse_custom(this_opt, &info->var) < 0) {
+				dev_err(&dev->dev, "Failed to parse custom mode (%s).\n", this_opt);
+				retval = -EINVAL;
+				goto err1;
+			}
+		} else if (!strncmp(this_opt, "addr", 4))
+			grvga_fix_addr = simple_strtoul(this_opt + 5, NULL, 16);
+		else if (!strncmp(this_opt, "size", 4))
+			grvga_mem_size = simple_strtoul(this_opt + 5, NULL, 0);
+		else
+			mode_opt = this_opt;
+	}
+
+	par = info->par;
+	info->fbops = &grvga_ops;
+	info->fix = grvga_fix;
+	info->pseudo_palette = par->color_palette;
+	info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;
+	info->fix.smem_len = grvga_mem_size;
+
+	if (!request_mem_region(dev->resource[0].start, resource_size(&dev->resource[0]), "grlib-svgactrl regs")) {
+		dev_err(&dev->dev, "registers already mapped\n");
+		retval = -EBUSY;
+		goto err;
+	}
+
+	par->regs = of_ioremap(&dev->resource[0], 0,
+			       resource_size(&dev->resource[0]),
+			       "grlib-svgactrl regs");
+
+	if (!par->regs) {
+		dev_err(&dev->dev, "failed to map registers\n");
+		retval = -ENOMEM;
+		goto err1;
+	}
+
+	retval = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (retval < 0) {
+		dev_err(&dev->dev, "failed to allocate mem with fb_alloc_cmap\n");
+		retval = -ENOMEM;
+		goto err2;
+	}
+
+	if (mode_opt) {
+		retval = fb_find_mode(&info->var, info, mode_opt,
+				      grvga_modedb, sizeof(grvga_modedb), &grvga_modedb[0], 8);
+		if (!retval || retval = 4) {
+			retval = -EINVAL;
+			goto err3;
+		}
+	}
+
+	if (!grvga_mem_size)
+		grvga_mem_size = info->var.xres_virtual * info->var.yres_virtual * info->var.bits_per_pixel/8;
+
+	if (grvga_fix_addr) {
+		/* Got framebuffer base address from argument list */
+
+		physical_start = grvga_fix_addr;
+
+		if (!request_mem_region(physical_start, grvga_mem_size, dev->name)) {
+			dev_err(&dev->dev, "failed to request memory region\n");
+			retval = -ENOMEM;
+			goto err3;
+		}
+
+		virtual_start = (unsigned long) ioremap(physical_start, grvga_mem_size);
+
+		if (!virtual_start) {
+			dev_err(&dev->dev, "error mapping framebuffer memory\n");
+			retval = -ENOMEM;
+			goto err4;
+		}
+	} else {	/* Allocate frambuffer memory */
+
+		unsigned long page;
+
+		virtual_start = (unsigned long) __get_free_pages(GFP_DMA,
+								 get_order(grvga_mem_size));
+		if (!virtual_start) {
+			dev_err(&dev->dev,
+				"unable to allocate framebuffer memory (%lu bytes)\n",
+				grvga_mem_size);
+			retval = -ENOMEM;
+			goto err3;
+		}
+
+		physical_start = dma_map_single(&dev->dev, (void *)virtual_start, grvga_mem_size, DMA_TO_DEVICE);
+
+		/* Set page reserved so that mmap will work. This is necessary
+		 * since we'll be remapping normal memory.
+		 */
+		for (page = virtual_start;
+		     page < PAGE_ALIGN(virtual_start + grvga_mem_size);
+		     page += PAGE_SIZE) {
+			SetPageReserved(virt_to_page(page));
+		}
+
+		par->fb_alloced = 1;
+	}
+
+	memset((unsigned long *) virtual_start, 0, grvga_mem_size);
+
+	info->screen_base = (char __iomem *) virtual_start;
+	info->fix.smem_start = physical_start;
+	info->fix.smem_len   = grvga_mem_size;
+
+	dev_set_drvdata(&dev->dev, info);
+
+	dev_info(&dev->dev,
+		 "Aeroflex Gaisler framebuffer device (fb%d), %dx%d-%d, using %luK of video memory @ %p\n",
+		 info->node, info->var.xres, info->var.yres, info->var.bits_per_pixel,
+		 grvga_mem_size >> 10, info->screen_base);
+
+	retval = register_framebuffer(info);
+	if (retval < 0) {
+		dev_err(&dev->dev, "failed to register framebuffer\n");
+		goto err4;
+	}
+
+	__raw_writel(physical_start, &par->regs->fb_pos);
+	__raw_writel(__raw_readl(&par->regs->status) | 1,  /* Enable framebuffer */
+		     &par->regs->status);
+
+	return 0;
+
+err4:
+	dev_set_drvdata(&dev->dev, NULL);
+	if (grvga_fix_addr) {
+		release_mem_region(physical_start, grvga_mem_size);
+		iounmap((void *)virtual_start);
+	} else
+		kfree((void *)virtual_start);
+err3:
+	fb_dealloc_cmap(&info->cmap);
+err2:
+	of_iounmap(&dev->resource[0], par->regs,
+		   resource_size(&dev->resource[0]));
+err1:
+	release_mem_region(dev->resource[0].start, resource_size(&dev->resource[0]));
+err:
+	framebuffer_release(info);
+
+	return retval;
+}
+
+static int __devexit grvga_remove(struct platform_device *device)
+{
+	struct fb_info *info = dev_get_drvdata(&device->dev);
+	struct grvga_par *par = info->par;
+
+	if (info) {
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+
+		of_iounmap(&device->resource[0], par->regs,
+			   resource_size(&device->resource[0]));
+		release_mem_region(device->resource[0].start, resource_size(&device->resource[0]));
+
+		if (!par->fb_alloced) {
+			release_mem_region(info->fix.smem_start, info->fix.smem_len);
+			iounmap(info->screen_base);
+		} else
+			kfree((void *)info->screen_base);
+
+		framebuffer_release(info);
+		dev_set_drvdata(&device->dev, NULL);
+	}
+
+	return 0;
+}
+
+static struct of_device_id svgactrl_of_match[] = {
+	{
+		.name = "GAISLER_SVGACTRL",
+	},
+	{
+		.name = "01_063",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, svgactrl_of_match);
+
+static struct platform_driver grvga_driver = {
+	.driver = {
+		.name = "grlib-svgactrl",
+		.owner = THIS_MODULE,
+		.of_match_table = svgactrl_of_match,
+	},
+	.probe		= grvga_probe,
+	.remove		= __devexit_p(grvga_remove),
+};
+
+
+static int __init grvga_init(void)
+{
+	return platform_driver_register(&grvga_driver);
+}
+
+static void __exit grvga_exit(void)
+{
+	platform_driver_unregister(&grvga_driver);
+}
+
+module_init(grvga_init);
+module_exit(grvga_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Aeroflex Gaisler");
+MODULE_DESCRIPTION("Aeroflex Gaisler framebuffer device driver");
-- 
1.7.0.4


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox