Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* Re: [PATCH] radeonfb: Let hwmon driver probe the "monid" I2C bus
From: Benjamin Herrenschmidt @ 2011-02-02  9:51 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <20110111162352.5a634e9e@endymion.delvare>

On Wed, 2011-02-02 at 09:12 +0100, Jean Delvare wrote:
> > If this is a concern to you, I'd be fine excluding CONFIG_PPC from
> the
> > change. Or are you worried about Intel Mac machines too? If there's
> an
> > easy way to spot all powermac machines, we can use that too, just
> let
> > me know how.
> > 
> > > Haven't had a chance to look much yet.
> 
> Ben, any progress on this?

Sorry, too swamped. Go on with CONFIG_PPC excluded for now.

Cheers,
Ben.



^ permalink raw reply

* Re: [PATCH] radeonfb: Let hwmon driver probe the "monid" I2C bus
From: Jean Delvare @ 2011-02-02  8:12 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <20110111162352.5a634e9e@endymion.delvare>

On Thu, 13 Jan 2011 09:56:57 +0100, Jean Delvare wrote:
> Hi Ben,
> 
> On Thu, 13 Jan 2011 15:50:10 +1100, Benjamin Herrenschmidt wrote:
> > On Thu, 2011-01-13 at 14:44 +1000, Dave Airlie wrote:
> > > The radeon BIOS actually contains a table to tell us what chip is on
> > > the bus,
> > > in the KMS driver we read this table and load the appropriate hwmon
> > > device,
> > > 
> > > There could possibly be other things on this bus than hw monitor
> > > devices.
> > > 
> > > Though radeonfb should be considered mostly dead. 
> > 
> > I want to test that on a few powermacs first. "probing" i2c can be
> > destructive and f* knows what Apple put on those busses on some
> > machines.
> 
> If this is a concern to you, I'd be fine excluding CONFIG_PPC from the
> change. Or are you worried about Intel Mac machines too? If there's an
> easy way to spot all powermac machines, we can use that too, just let
> me know how.
> 
> > Haven't had a chance to look much yet.

Ben, any progress on this?

-- 
Jean Delvare

^ permalink raw reply

* Re: [PATCH] radeonfb: Let hwmon driver probe the "monid" I2C bus
From: Jean Delvare @ 2011-02-02  8:11 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <20110111162352.5a634e9e@endymion.delvare>

Alexander,

On Wed, 02 Feb 2011 07:50:16 +0200, Alexander Goomenyuk wrote:
> On Thu, 2011-01-13 at 14:44 +1000, Dave Airlie wrote:
> > On Thu, Jan 13, 2011 at 2:11 PM, Paul Mundt <lethal@linux-sh.org> wrote:
> > > On Tue, Jan 11, 2011 at 04:23:52PM +0100, Jean Delvare wrote:
> > >> Some Radeon cards have an I2C-based thermal sensor chip connected to
> > >> the "monid" I2C bus. Set the I2C probing class of this bus properly so
> > >> that hwmon drivers can detect devices on it and bind to them.
> > >>
> > >> This closes kernel.org bug #26172.
> > >>
> > 
> > The radeon BIOS actually contains a table to tell us what chip is on the bus,
> > in the KMS driver we read this table and load the appropriate hwmon device,
> > 
> > There could possibly be other things on this bus than hw monitor devices.
> > 
> > Though radeonfb should be considered mostly dead.
> > 
> > Dave.
> 
> I have tried radeon KMS driver.
>         modinfo output:
>         filename:       /lib/modules/2.6.36-tuxonice-r3/kernel/drivers/gpu/drm/radeon/radeon.ko
>         depends:
>         drm,drm_kms_helper,ttm,fb,i2c-core,cfbfillrect,cfbimgblt,cfbcopyarea,i2c-algo-bit
>         vermagic:       2.6.36-tuxonice-r3 SMP mod_unload 686 
>         parm:           no_wb:Disable AGP writeback for scratch
>         registers (int)
>         parm:           modeset:Disable/Enable modesetting (int)
>         parm:           dynclks:Disable/Enable dynamic clocks (int)
>         parm:           r4xx_atom:Enable ATOMBIOS modesetting for R4xx
>         (int)
>         parm:           vramlimit:Restrict VRAM for testing (int)
>         parm:           agpmode:AGP Mode (-1 = PCI) (int)
>         parm:           gartsize:Size of PCIE/IGP gart to setup in
>         megabytes (32,64, etc)
>          (int)
>         parm:           benchmark:Run benchmark (int)
>         parm:           test:Run tests (int)
>         parm:           connector_table:Force connector table (int)
>         parm:           tv:TV enable (0 = disable) (int)
>         parm:           new_pll:Select new PLL code (int)
>         parm:           audio:Audio enable (0 = disable) (int)
>         parm:           disp_priority:Display Priority (0 = auto, 1 >         normal, 2 = high) (int)
>         parm:           hw_i2c:hw i2c engine enable (0 = disable) (int)
>         
> But it also need modifications in order to be used by lm63 hwmon driver.
> 1. MONID line is disable by combios_setup_i2c_bus() for RV380 because
> of:
>         case CHIP_RV350:
>         case CHIP_RV380:
>         case CHIP_RS400:
>         case CHIP_RS480:
>                 switch (ddc_line) {
>                 case RADEON_GPIO_VGA_DDC:
>                 case RADEON_GPIO_DVI_DDC:
> +                       i2c.hw_capable = true;
> -                       i2c.hw_capable = false;
>                         break;
>                 case RADEON_GPIO_MONID:
>                      /* hw i2c on RADEON_GPIO_MONID doesn't seem to work
>                       * reliably on some pre-r4xx hardware; not sure why
>                       */
>                         i2c.hw_capable = true;
>                         break;
> 
> extracted from the sources.
> It would be nice if there will be some driver parameter to control this
> behavior. Or/and control it in kernel configuration menu.

I'm sorry but I don't understand what you mean. For one thing, I can't
see how the above change (?) is related to your problem, as it only
affects the DDC channels and not the MONID channel. For another, I
can't see how the bus being software or hardware driven would have any
effect.

> 
> 2. MONID adapter is not registered as HWMON capable.
> So I have added the following line into radeon_combios_i2c_init():
> 
>         } else if (rdev->family >= CHIP_R300) {
>                i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0);
>                rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID");
> +              rdev->i2c_bus[3]->adapter.class = I2C_CLASS_HWMON;
> 
> Now I see GPU temperature using lm_sensors.

But this isn't the way the drm radeon driver is designed. It reads from
the BIOS whether there are sensors available, what is their type and
their address, etc. It does not rely on physical probing as the
radeonfb driver does. So the above is NOT correct.

I can imagine that sensor support has only been implemented for
atom-BIOS based boards and not older com-BIOS based ones. At least
searching for "lm63" in the source code has matches in only
radeon_atombios.c and not radeon_combios.c. I have no idea if it would
be possible to extend this mechanism to older boards or not - I don't
know if the com-BIOS included the information already.

-- 
Jean Delvare

^ permalink raw reply

* Re: [PATCH] radeonfb: Let hwmon driver probe the "monid" I2C bus
From: Alexander Goomenyuk @ 2011-02-02  5:50 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <20110111162352.5a634e9e@endymion.delvare>

On Thu, 2011-01-13 at 14:44 +1000, Dave Airlie wrote:
> On Thu, Jan 13, 2011 at 2:11 PM, Paul Mundt <lethal@linux-sh.org> wrote:
> > On Tue, Jan 11, 2011 at 04:23:52PM +0100, Jean Delvare wrote:
> >> Some Radeon cards have an I2C-based thermal sensor chip connected to
> >> the "monid" I2C bus. Set the I2C probing class of this bus properly so
> >> that hwmon drivers can detect devices on it and bind to them.
> >>
> >> This closes kernel.org bug #26172.
> >>
> 
> The radeon BIOS actually contains a table to tell us what chip is on the bus,
> in the KMS driver we read this table and load the appropriate hwmon device,
> 
> There could possibly be other things on this bus than hw monitor devices.
> 
> Though radeonfb should be considered mostly dead.
> 
> Dave.

I have tried radeon KMS driver.
        modinfo output:
        filename:       /lib/modules/2.6.36-tuxonice-r3/kernel/drivers/gpu/drm/radeon/radeon.ko
        depends:
        drm,drm_kms_helper,ttm,fb,i2c-core,cfbfillrect,cfbimgblt,cfbcopyarea,i2c-algo-bit
        vermagic:       2.6.36-tuxonice-r3 SMP mod_unload 686 
        parm:           no_wb:Disable AGP writeback for scratch
        registers (int)
        parm:           modeset:Disable/Enable modesetting (int)
        parm:           dynclks:Disable/Enable dynamic clocks (int)
        parm:           r4xx_atom:Enable ATOMBIOS modesetting for R4xx
        (int)
        parm:           vramlimit:Restrict VRAM for testing (int)
        parm:           agpmode:AGP Mode (-1 = PCI) (int)
        parm:           gartsize:Size of PCIE/IGP gart to setup in
        megabytes (32,64, etc)
         (int)
        parm:           benchmark:Run benchmark (int)
        parm:           test:Run tests (int)
        parm:           connector_table:Force connector table (int)
        parm:           tv:TV enable (0 = disable) (int)
        parm:           new_pll:Select new PLL code (int)
        parm:           audio:Audio enable (0 = disable) (int)
        parm:           disp_priority:Display Priority (0 = auto, 1         normal, 2 = high) (int)
        parm:           hw_i2c:hw i2c engine enable (0 = disable) (int)
        
But it also need modifications in order to be used by lm63 hwmon driver.
1. MONID line is disable by combios_setup_i2c_bus() for RV380 because
of:
        case CHIP_RV350:
        case CHIP_RV380:
        case CHIP_RS400:
        case CHIP_RS480:
                switch (ddc_line) {
                case RADEON_GPIO_VGA_DDC:
                case RADEON_GPIO_DVI_DDC:
+                       i2c.hw_capable = true;
-                       i2c.hw_capable = false;
                        break;
                case RADEON_GPIO_MONID:
                     /* hw i2c on RADEON_GPIO_MONID doesn't seem to work
                      * reliably on some pre-r4xx hardware; not sure why
                      */
                        i2c.hw_capable = true;
                        break;

extracted from the sources.
It would be nice if there will be some driver parameter to control this
behavior. Or/and control it in kernel configuration menu.

2. MONID adapter is not registered as HWMON capable.
So I have added the following line into radeon_combios_i2c_init():

        } else if (rdev->family >= CHIP_R300) {
               i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0);
               rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID");
+              rdev->i2c_bus[3]->adapter.class = I2C_CLASS_HWMON;

Now I see GPU temperature using lm_sensors.

P.S. There is also strange side effect after reloading radeon driver
from X console: the screen switch off. So I have to switch between
virtual console and X. Is it an bug?


^ permalink raw reply

* Re: [PATCH 3/4 v4] video, sm501: add OF binding to support SM501
From: Samuel Ortiz @ 2011-01-31 10:52 UTC (permalink / raw)
  To: Heiko Schocher
  Cc: linuxppc-dev, linux-fbdev, devicetree-discuss, Ben Dooks,
	Vincent Sanders, linux-kernel, Randy Dunlap, Paul Mundt
In-Reply-To: <1295863058-11168-1-git-send-email-hs@denx.de>

Hi Heiko,

On Mon, Jan 24, 2011 at 10:57:38AM +0100, Heiko Schocher wrote:
> - add binding to OF, compatible name "smi,sm501"
The MFD part looks fine to me:
Acked-by: Samuel Ortiz <sameo@linux.intel.com>

Cheers,
Samuel.

-- 
Intel Open Source Technology Centre
http://oss.intel.com/

^ permalink raw reply

* Re: [PATCH 1/4 v4] video, sm501: add I/O functions for use on
From: Samuel Ortiz @ 2011-01-31 10:50 UTC (permalink / raw)
  To: Heiko Schocher
  Cc: linuxppc-dev, linux-fbdev, devicetree-discuss, Ben Dooks,
	Vincent Sanders, linux-kernel, Randy Dunlap, Paul Mundt
In-Reply-To: <1295863040-11086-1-git-send-email-hs@denx.de>

Hi Heiko,

On Mon, Jan 24, 2011 at 10:57:20AM +0100, Heiko Schocher wrote:
> - add read/write functions for using this driver
>   also on powerpc plattforms
Not sure whose tree this is going through. Probably Paul's one though.
The mfd part looks fine to me, please add my:
Acked-by: Samuel Ortiz <sameo@linux.intel.com>

Cheers,
Samuel.

-- 
Intel Open Source Technology Centre
http://oss.intel.com/

^ permalink raw reply

* [PATCH 2/2] video: sh7760fb: use resource_size()
From: Axel Lin @ 2011-01-29  9:35 UTC (permalink / raw)
  To: linux-kernel; +Cc: Manuel Lauss, Nobuhiro Iwamatsu, Paul Mundt, linux-fbdev
In-Reply-To: <1296293628.13797.2.camel@phoenix>

The size calculation is done incorrectly in request_mem_region because
it should include both the start and end (end - start + 1).

Signed-off-by: Axel Lin <axel.lin@gmail.com>
---
 drivers/video/sh7760fb.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/video/sh7760fb.c b/drivers/video/sh7760fb.c
index bea38fc..8fe1958 100644
--- a/drivers/video/sh7760fb.c
+++ b/drivers/video/sh7760fb.c
@@ -459,14 +459,14 @@ static int __devinit sh7760fb_probe(struct platform_device *pdev)
 	}
 
 	par->ioarea = request_mem_region(res->start,
-					 (res->end - res->start), pdev->name);
+					 resource_size(res), pdev->name);
 	if (!par->ioarea) {
 		dev_err(&pdev->dev, "mmio area busy\n");
 		ret = -EBUSY;
 		goto out_fb;
 	}
 
-	par->base = ioremap_nocache(res->start, res->end - res->start + 1);
+	par->base = ioremap_nocache(res->start, resource_size(res));
 	if (!par->base) {
 		dev_err(&pdev->dev, "cannot remap\n");
 		ret = -ENODEV;
-- 
1.7.0.4




^ permalink raw reply related

* [PATCH 1/2] video: hpfb: use resource_size()
From: Axel Lin @ 2011-01-29  9:33 UTC (permalink / raw)
  To: linux-kernel; +Cc: Phil Blundell, Geert Uytterhoeven, Paul Mundt, linux-fbdev

The size calculation is done incorrectly here because it should include
both the start and end (end - start + 1).

Signed-off-by: Axel Lin <axel.lin@gmail.com>
---
 drivers/video/hpfb.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c
index c8e280f..ebf8495 100644
--- a/drivers/video/hpfb.c
+++ b/drivers/video/hpfb.c
@@ -321,11 +321,11 @@ static int __devinit hpfb_dio_probe(struct dio_dev * d, const struct dio_device_
 	unsigned long paddr, vaddr;
 
 	paddr = d->resource.start;
-	if (!request_mem_region(d->resource.start, d->resource.end - d->resource.start, d->name))
+	if (!request_mem_region(d->resource.start, resource_size(&d->resource), d->name))
                 return -EBUSY;
 
 	if (d->scode >= DIOII_SCBASE) {
-		vaddr = (unsigned long)ioremap(paddr, d->resource.end - d->resource.start);
+		vaddr = (unsigned long)ioremap(paddr, resource_size(&d->resource));
 	} else {
 		vaddr = paddr + DIO_VIRADDRBASE;
 	}
@@ -344,7 +344,7 @@ static void __devexit hpfb_remove_one(struct dio_dev *d)
 	unregister_framebuffer(&fb_info);
 	if (d->scode >= DIOII_SCBASE)
 		iounmap((void *)fb_regs);
-        release_mem_region(d->resource.start, d->resource.end - d->resource.start);
+	release_mem_region(d->resource.start, resource_size(&d->resource));
 }
 
 static struct dio_device_id hpfb_dio_tbl[] = {
-- 
1.7.0.4




^ permalink raw reply related

* RE: [PATCH 0/2][concept RFC] x86: BIOS-save kernel log to disk upon
From: Luck, Tony @ 2011-01-27 18:56 UTC (permalink / raw)
  To: Ingo Molnar, H. Peter Anvin
  Cc: Dave Jones, Ahmed S. Darwish, Linus Torvalds, Thomas Gleixner,
	Ingo Molnar, X86-ML, Andrew Morton, Randy Dunlap, Willy Tarreau,
	Willy Tarreau, Dirk Hohndel, Hohndel, Dirk, IDE-ML, LKML,
	Peter Zijlstra, Frédéric Weisbecker, Borislav Petkov,
	Arjan van de Ven, Tejun Heo, James Bottomley, Mark Lord,
	Jeff Garzik, Eric Biederman
In-Reply-To: <20110127162429.GB26437@elte.hu>

> Yeah, i've done it countless times and it's very painful indeed - but the 
> alternative "losing context" would be even worse to me. Can we do both - i.e. have 
> the barcode on the screen alongside the oops itself? (although at that point they'll 
> be taking screen real estate from each other - degrading the information in *both* 
> venues.)
>
> Keyboard 'oops scrolling' driver with 'flip to barcode output' key? :-)

If we can make the screen scroll, or guarantee that a hot key will switch to
the barcode view, then those look like good solutions. Sharing space on a
non-scrollable view sounds like a poor choice. Perhaps better to have a
command line option to say which to provide (default = text).

-Tony

^ permalink raw reply

* RE: [PATCH 0/2][concept RFC] x86: BIOS-save kernel log to disk upon
From: Luck, Tony @ 2011-01-27 18:35 UTC (permalink / raw)
  To: Ingo Molnar, H. Peter Anvin
  Cc: Dave Jones, Ahmed S. Darwish, Linus Torvalds, Thomas Gleixner,
	Ingo Molnar, X86-ML, Andrew Morton, Randy Dunlap, Willy Tarreau,
	Willy Tarreau, Dirk Hohndel, Hohndel, Dirk, IDE-ML, LKML,
	Peter Zijlstra, Frédéric Weisbecker, Borislav Petkov,
	Arjan van de Ven, Tejun Heo, James Bottomley, Mark Lord,
	Jeff Garzik, Eric Biederman
In-Reply-To: <20110127120039.GD20279@elte.hu>

> - A bar code is encoded and i generally want to know what info i'm sending to
>   potentially untrusted parties ... also, i want to be sure i'm sending the right
>   oops, at a glance, before hitting 'send' on the email.

Maybe someone will write an iPhone/Android/Meego app that takes the picture, does
The decode and lets you look, together with options on whether to just send to
Your e-mail address, or to Cc; kerneloops?

> - A screenshot of a well-compressed oops output tells a lot of context as well:
>   surrounding kernel messages, general state of the system when it crashed.
>   Sometimes it tells me the type of the laptop as well, via the logo visible on the
>   border of the picture ;-) Context strengthens whether i can *trust* the oops - 
>   and often i'm really in doubt about oopses and want more context.

Perhaps some of this context can be encoded in the barcode too?

-Tony

^ permalink raw reply

* [PATCHv2] unicore32: add framebuffer driver for unigfx engine in PKUnity SoC
From: Guan Xuetao @ 2011-01-27  6:53 UTC (permalink / raw)
  To: Paul Mundt; +Cc: linux-fbdev, linux-kernel

From: Guan Xuetao <gxt@mprc.pku.edu.cn>

This patch adds framebuffer driver for unigfx engine in PKUnity SoC.

Changes from previous version: (by advice from Pual Mundt)
  1. adjust platform_device related codes, and add resource handling
  2. remove several static variables
  3. remove acceleration flag assignment
  4. rearrange pm related codes
  5. replace printk with dev_warn
  6. simple options handling
  7. many other minor modifications

Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
---
 arch/unicore32/kernel/puv3-core.c |   15 +
 drivers/video/Kconfig             |   11 +
 drivers/video/Makefile            |    1 +
 drivers/video/fb-puv3.c           |  846 +++++++++++++++++++++++++++++++++++++
 include/linux/fb.h                |    2 +
 5 files changed, 875 insertions(+), 0 deletions(-)

diff --git a/arch/unicore32/kernel/puv3-core.c b/arch/unicore32/kernel/puv3-core.c
index 26cc52b..ff2e5e6 100644
--- a/arch/unicore32/kernel/puv3-core.c
+++ b/arch/unicore32/kernel/puv3-core.c
@@ -93,6 +93,19 @@ static struct resource puv3_mmc_resources[] = {
 	},
 };
 
+static struct resource puv3_unigfx_resources[] = {
+	[0] = {
+		.start	= PKUNITY_UNIGFX_BASE,
+		.end	= PKUNITY_UNIGFX_BASE + 0xfff,
+		.flags	= IORESOURCE_IO,
+	},
+	[1] = {
+		.start	= PKUNITY_UNIGFX_MMAP_BASE,
+		.end	= PKUNITY_UNIGFX_MMAP_BASE + PKUNITY_UNIGFX_MMAP_SIZE,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
 static struct resource puv3_rtc_resources[] = {
 	[0] = {
 		.start = PKUNITY_RTC_BASE,
@@ -256,6 +269,8 @@ void __init puv3_core_init(void)
 			puv3_umal_resources, ARRAY_SIZE(puv3_umal_resources));
 	platform_device_register_simple("PKUnity-v3-MMC", -1,
 			puv3_mmc_resources, ARRAY_SIZE(puv3_mmc_resources));
+	platform_device_register_simple("PKUnity-v3-UNIGFX", -1,
+			puv3_unigfx_resources, ARRAY_SIZE(puv3_unigfx_resources));
 	platform_device_register_simple("PKUnity-v3-PWM", -1,
 			puv3_pwm_resources, ARRAY_SIZE(puv3_pwm_resources));
 	platform_device_register_simple("PKUnity-v3-UART", 0,
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 27c1fb4..13bf36e 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2259,6 +2259,17 @@ config FB_JZ4740
 	help
 	  Framebuffer support for the JZ4740 SoC.
 
+config FB_PUV3_UNIGFX
+	tristate "PKUnity v3 Unigfx framebuffer support"
+	depends on FB && UNICORE32 && ARCH_PUV3
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	help
+	  Choose this option if you want to use the Unigfx device as a
+	  framebuffer device. Without the support of PCI & AGP.
+
 source "drivers/video/omap/Kconfig"
 source "drivers/video/omap2/Kconfig"
 
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 485e8ed..cdfebef 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -134,6 +134,7 @@ obj-$(CONFIG_FB_MB862XX)	  += mb862xx/
 obj-$(CONFIG_FB_MSM)              += msm/
 obj-$(CONFIG_FB_NUC900)           += nuc900fb.o
 obj-$(CONFIG_FB_JZ4740)		  += jz4740_fb.o
+obj-$(CONFIG_FB_PUV3_UNIGFX)      += fb-puv3.o
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_UVESA)            += uvesafb.o
diff --git a/drivers/video/fb-puv3.c b/drivers/video/fb-puv3.c
new file mode 100644
index 0000000..0e0e8ee
--- /dev/null
+++ b/drivers/video/fb-puv3.c
@@ -0,0 +1,846 @@
+/*
+ * Frame Buffer Driver for PKUnity-v3 Unigfx
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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/kernel.h>
+#include <linux/errno.h>
+#include <linux/vmalloc.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/console.h>
+
+#include <asm/sizes.h>
+#include <mach/hardware.h>
+
+/* Platform_data reserved for unifb registers. */
+#define UNIFB_REGS_NUM		10
+/* RAM reserved for the frame buffer. */
+#define UNIFB_MEMSIZE		(SZ_4M)		/* 4 MB for 1024*768*32b */
+
+/*
+ * cause UNIGFX don not have EDID
+ * all the modes are organized as follow
+ */
+static const struct fb_videomode unifb_modes[] = {
+	/* 0 640x480-60 VESA */
+	{ "640x480@60",  60,  640, 480,  25175000,  48, 16, 34, 10,  96, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1 640x480-75 VESA */
+	{ "640x480@75",  75,  640, 480,  31500000, 120, 16, 18,  1,  64, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 2 800x600-60 VESA */
+	{ "800x600@60",  60,  800, 600,  40000000,  88, 40, 26,  1, 128, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 3 800x600-75 VESA */
+	{ "800x600@75",  75,  800, 600,  49500000, 160, 16, 23,  1,  80, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 4 1024x768-60 VESA */
+	{ "1024x768@60", 60, 1024, 768,  65000000, 160, 24, 34,  3, 136, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 5 1024x768-75 VESA */
+	{ "1024x768@75", 75, 1024, 768,  78750000, 176, 16, 30,  1,  96, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 6 1280x960-60 VESA */
+	{ "1280x960@60", 60, 1280, 960, 108000000, 312, 96, 38,  1, 112, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 7 1440x900-60 VESA */
+	{ "1440x900@60", 60, 1440, 900, 106500000, 232, 80, 30,  3, 152, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 8 FIXME 9 1024x600-60 VESA UNTESTED */
+	{ "1024x600@60", 60, 1024, 600,  50650000, 160, 24, 26,  1, 136, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 9 FIXME 10 1024x600-75 VESA UNTESTED */
+	{ "1024x600@75", 75, 1024, 600,  61500000, 176, 16, 23,  1,  96, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 10 FIXME 11 1366x768-60 VESA UNTESTED */
+	{ "1366x768@60", 60, 1366, 768,  85500000, 256, 58, 18,  1,  112, 3,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+};
+
+static struct fb_var_screeninfo unifb_default = {
+	.xres =		640,
+	.yres =		480,
+	.xres_virtual =	640,
+	.yres_virtual =	480,
+	.bits_per_pixel = 16,
+	.red =		{ 11, 5, 0 },
+	.green =	{ 5,  6, 0 },
+	.blue =		{ 0,  5, 0 },
+	.activate =	FB_ACTIVATE_NOW,
+	.height =	-1,
+	.width =	-1,
+	.pixclock =	25175000,
+	.left_margin =	48,
+	.right_margin =	16,
+	.upper_margin =	33,
+	.lower_margin =	10,
+	.hsync_len =	96,
+	.vsync_len =	2,
+	.vmode =	FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo unifb_fix = {
+	.id =		"UNIGFX FB",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_TRUECOLOR,
+	.xpanstep =	1,
+	.ypanstep =	1,
+	.ywrapstep =	1,
+	.accel =	FB_ACCEL_NONE,
+};
+
+static void unifb_sync(struct fb_info *info)
+{
+	/* TODO: may, this can be replaced by interrupt */
+	int cnt;
+
+	for (cnt = 0; cnt < 0x10000000; cnt++) {
+		if (UGE_COMMAND & 0x1000000)
+			return;
+	}
+
+	if (cnt > 0x8000000)
+		dev_warn(info->device, "Warning: UniGFX GE time out ...\n");
+}
+
+static void unifb_prim_fillrect(struct fb_info *info,
+				const struct fb_fillrect *region)
+{
+	int awidth = region->width;
+	int aheight = region->height;
+	int m_iBpp = info->var.bits_per_pixel;
+	int screen_width = info->var.xres;
+	int src_sel = 1;	/* from fg_color */
+	int pat_sel = 1;
+	int src_x0 = 0;
+	int dst_x0 = region->dx;
+	int src_y0 = 0;
+	int dst_y0 = region->dy;
+	int rop_alpha_sel = 0;
+	int rop_alpha_code = 0xCC;
+	int x_dir = 1;
+	int y_dir = 1;
+	int alpha_r = 0;
+	int alpha_sel = 0;
+	int dst_pitch = screen_width * (m_iBpp / 8);
+	int dst_offset = dst_y0 * dst_pitch + dst_x0 * (m_iBpp / 8);
+	int src_pitch = screen_width * (m_iBpp / 8);
+	int src_offset = src_y0 * src_pitch + src_x0 * (m_iBpp / 8);
+	unsigned int command = 0;
+	int clip_region = 0;
+	int clip_en = 0;
+	int tp_en = 0;
+	int fg_color = 0;
+	int bottom = info->var.yres - 1;
+	int right = info->var.xres - 1;
+	int top = 0;
+
+	bottom = (bottom << 16) | right;
+	command = (rop_alpha_sel << 26) | (pat_sel << 18) | (src_sel << 16)
+		| (x_dir << 20) | (y_dir << 21) | (command << 24)
+		| (clip_region << 23) | (clip_en << 22) | (tp_en << 27);
+	src_pitch = (dst_pitch << 16) | src_pitch;
+	awidth = awidth | (aheight << 16);
+	alpha_r = ((rop_alpha_code & 0xff) << 8) | (alpha_r & 0xff)
+		| (alpha_sel << 16);
+	src_x0 = (src_x0 & 0x1fff) | ((src_y0 & 0x1fff) << 16);
+	dst_x0 = (dst_x0 & 0x1fff) | ((dst_y0 & 0x1fff) << 16);
+	fg_color = region->color;
+
+	unifb_sync(info);
+
+	UGE_FCOLOR = ((u32 *)(info->pseudo_palette))[fg_color];
+	UGE_BCOLOR = 0;
+	UGE_PITCH = src_pitch;
+	UGE_SRCSTART = src_offset;
+	UGE_DSTSTART = dst_offset;
+	UGE_WIDHEIGHT = awidth;
+	UGE_CLIP0 = top;
+	UGE_CLIP1 = bottom;
+	UGE_ROPALPHA = alpha_r;
+	UGE_SRCXY = src_x0;
+	UGE_DSTXY = dst_x0;
+	UGE_COMMAND = command;
+}
+
+static void unifb_fillrect(struct fb_info *info,
+		const struct fb_fillrect *region)
+{
+	struct fb_fillrect modded;
+	int vxres, vyres;
+
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		sys_fillrect(info, region);
+		return;
+	}
+
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+
+	memcpy(&modded, region, sizeof(struct fb_fillrect));
+
+	if (!modded.width || !modded.height ||
+	    modded.dx >= vxres || modded.dy >= vyres)
+		return;
+
+	if (modded.dx + modded.width > vxres)
+		modded.width = vxres - modded.dx;
+	if (modded.dy + modded.height > vyres)
+		modded.height = vyres - modded.dy;
+
+	unifb_prim_fillrect(info, &modded);
+}
+
+static void unifb_prim_copyarea(struct fb_info *info,
+				const struct fb_copyarea *area)
+{
+	int awidth = area->width;
+	int aheight = area->height;
+	int m_iBpp = info->var.bits_per_pixel;
+	int screen_width = info->var.xres;
+	int src_sel = 2;	/* from mem */
+	int pat_sel = 0;
+	int src_x0 = area->sx;
+	int dst_x0 = area->dx;
+	int src_y0 = area->sy;
+	int dst_y0 = area->dy;
+
+	int rop_alpha_sel = 0;
+	int rop_alpha_code = 0xCC;
+	int x_dir = 1;
+	int y_dir = 1;
+
+	int alpha_r = 0;
+	int alpha_sel = 0;
+	int dst_pitch = screen_width * (m_iBpp / 8);
+	int dst_offset = dst_y0 * dst_pitch + dst_x0 * (m_iBpp / 8);
+	int src_pitch = screen_width * (m_iBpp / 8);
+	int src_offset = src_y0 * src_pitch + src_x0 * (m_iBpp / 8);
+	unsigned int command = 0;
+	int clip_region = 0;
+	int clip_en = 1;
+	int tp_en = 0;
+	int top = 0;
+	int bottom = info->var.yres;
+	int right = info->var.xres;
+	int fg_color = 0;
+	int bg_color = 0;
+
+	if (src_x0 < 0)
+		src_x0 = 0;
+	if (src_y0 < 0)
+		src_y0 = 0;
+
+	if (src_y0 - dst_y0 > 0) {
+		y_dir = 1;
+	} else {
+		y_dir = 0;
+		src_offset = (src_y0 + aheight) * src_pitch +
+				src_x0 * (m_iBpp / 8);
+		dst_offset = (dst_y0 + aheight) * dst_pitch +
+				dst_x0 * (m_iBpp / 8);
+		src_y0 += aheight;
+		dst_y0 += aheight;
+	}
+
+	command = (rop_alpha_sel << 26) | (pat_sel << 18) | (src_sel << 16) |
+		(x_dir << 20) | (y_dir << 21) | (command << 24) |
+		(clip_region << 23) | (clip_en << 22) | (tp_en << 27);
+	src_pitch = (dst_pitch << 16) | src_pitch;
+	awidth = awidth | (aheight << 16);
+	alpha_r = ((rop_alpha_code & 0xff) << 8) | (alpha_r & 0xff) |
+		(alpha_sel << 16);
+	src_x0 = (src_x0 & 0x1fff) | ((src_y0 & 0x1fff) << 16);
+	dst_x0 = (dst_x0 & 0x1fff) | ((dst_y0 & 0x1fff) << 16);
+	bottom = (bottom << 16) | right;
+
+	unifb_sync(info);
+
+	UGE_PITCH = src_pitch;
+	UGE_SRCSTART = src_offset;
+	UGE_DSTSTART = dst_offset;
+	UGE_WIDHEIGHT = awidth;
+	UGE_CLIP0 = top;
+	UGE_CLIP1 = bottom;
+	UGE_BCOLOR = bg_color;
+	UGE_FCOLOR = fg_color;
+	UGE_ROPALPHA = alpha_r;
+	UGE_SRCXY = src_x0;
+	UGE_DSTXY = dst_x0;
+	UGE_COMMAND = command;
+}
+
+static void unifb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	struct fb_copyarea modded;
+	u32 vxres, vyres;
+	modded.sx = area->sx;
+	modded.sy = area->sy;
+	modded.dx = area->dx;
+	modded.dy = area->dy;
+	modded.width = area->width;
+	modded.height = area->height;
+
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		sys_copyarea(info, area);
+		return;
+	}
+
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+
+	if (!modded.width || !modded.height ||
+	    modded.sx >= vxres || modded.sy >= vyres ||
+	    modded.dx >= vxres || modded.dy >= vyres)
+		return;
+
+	if (modded.sx + modded.width > vxres)
+		modded.width = vxres - modded.sx;
+	if (modded.dx + modded.width > vxres)
+		modded.width = vxres - modded.dx;
+	if (modded.sy + modded.height > vyres)
+		modded.height = vyres - modded.sy;
+	if (modded.dy + modded.height > vyres)
+		modded.height = vyres - modded.dy;
+
+	unifb_prim_copyarea(info, &modded);
+}
+
+static void unifb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	sys_imageblit(info, image);
+}
+
+static u_long get_line_length(int xres_virtual, int bpp)
+{
+	u_long length;
+
+	length = xres_virtual * bpp;
+	length = (length + 31) & ~31;
+	length >>= 3;
+	return length;
+}
+
+/*
+ *  Setting the video mode has been split into two parts.
+ *  First part, xxxfb_check_var, must not write anything
+ *  to hardware, it should only verify and adjust var.
+ *  This means it doesn't alter par but it does use hardware
+ *  data from it to check this var.
+ */
+static int unifb_check_var(struct fb_var_screeninfo *var,
+			 struct fb_info *info)
+{
+	u_long line_length;
+
+	/*
+	 *  FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
+	 *  as FB_VMODE_SMOOTH_XPAN is only used internally
+	 */
+
+	if (var->vmode & FB_VMODE_CONUPDATE) {
+		var->vmode |= FB_VMODE_YWRAP;
+		var->xoffset = info->var.xoffset;
+		var->yoffset = info->var.yoffset;
+	}
+
+	/*
+	 *  Some very basic checks
+	 */
+	if (!var->xres)
+		var->xres = 1;
+	if (!var->yres)
+		var->yres = 1;
+	if (var->xres > var->xres_virtual)
+		var->xres_virtual = var->xres;
+	if (var->yres > var->yres_virtual)
+		var->yres_virtual = var->yres;
+	if (var->bits_per_pixel <= 1)
+		var->bits_per_pixel = 1;
+	else 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;
+
+	if (var->xres_virtual < var->xoffset + var->xres)
+		var->xres_virtual = var->xoffset + var->xres;
+	if (var->yres_virtual < var->yoffset + var->yres)
+		var->yres_virtual = var->yoffset + var->yres;
+
+	/*
+	 *  Memory limit
+	 */
+	line_length +	    get_line_length(var->xres_virtual, var->bits_per_pixel);
+	if (line_length * var->yres_virtual > UNIFB_MEMSIZE)
+		return -ENOMEM;
+
+	/*
+	 * Now that we checked it we alter var. The reason being is that the
+	 * video mode passed in might not work but slight changes to it might
+	 * make it work. This way we let the user know what is acceptable.
+	 */
+	switch (var->bits_per_pixel) {
+	case 1:
+	case 8:
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 16:		/* RGBA 5551 */
+		if (var->transp.length) {
+			var->red.offset = 0;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 5;
+			var->blue.offset = 10;
+			var->blue.length = 5;
+			var->transp.offset = 15;
+			var->transp.length = 1;
+		} else {	/* RGB 565 */
+			var->red.offset = 11;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 6;
+			var->blue.offset = 0;
+			var->blue.length = 5;
+			var->transp.offset = 0;
+			var->transp.length = 0;
+		}
+		break;
+	case 24:		/* RGB 888 */
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 16;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 32:		/* RGBA 8888 */
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		break;
+	}
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+
+	return 0;
+}
+
+/*
+ * This routine actually sets the video mode. It's in here where we
+ * the hardware state info->par and fix which can be affected by the
+ * change in par. For this driver it doesn't do much.
+ */
+static int unifb_set_par(struct fb_info *info)
+{
+	int hTotal, vTotal, hSyncStart, hSyncEnd, vSyncStart, vSyncEnd;
+	int format;
+
+#ifdef CONFIG_PUV3_PM
+	struct clk *clk_vga;
+	u32 pixclk = 0;
+	int i;
+
+	for (i = 0; i <= 10; i++) {
+		if    (info->var.xres         = unifb_modes[i].xres
+		    && info->var.yres         = unifb_modes[i].yres
+		    && info->var.upper_margin = unifb_modes[i].upper_margin
+		    && info->var.lower_margin = unifb_modes[i].lower_margin
+		    && info->var.left_margin  = unifb_modes[i].left_margin
+		    && info->var.right_margin = unifb_modes[i].right_margin
+		    && info->var.hsync_len    = unifb_modes[i].hsync_len
+		    && info->var.vsync_len    = unifb_modes[i].vsync_len) {
+			pixclk = unifb_modes[i].pixclock;
+			break;
+		}
+	}
+
+	/* set clock rate */
+	clk_vga = clk_get(info->device, "VGA_CLK");
+	if (clk_vga = ERR_PTR(-ENOENT))
+		return -ENOENT;
+
+	if (pixclk != 0) {
+		if (clk_set_rate(clk_vga, pixclk)) { /* set clock failed */
+			info->fix = unifb_fix;
+			info->var = unifb_default;
+			if (clk_set_rate(clk_vga, unifb_default.pixclock))
+				return -EINVAL;
+		}
+	}
+#endif
+
+	info->fix.line_length = get_line_length(info->var.xres_virtual,
+						info->var.bits_per_pixel);
+
+	hSyncStart = info->var.xres + info->var.right_margin;
+	hSyncEnd = hSyncStart + info->var.hsync_len;
+	hTotal = hSyncEnd + info->var.left_margin;
+
+	vSyncStart = info->var.yres + info->var.lower_margin;
+	vSyncEnd = vSyncStart + info->var.vsync_len;
+	vTotal = vSyncEnd + info->var.upper_margin;
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		format = UDE_CFG_DST8;
+		break;
+	case 16:
+		format = UDE_CFG_DST16;
+		break;
+	case 24:
+		format = UDE_CFG_DST24;
+		break;
+	case 32:
+		format = UDE_CFG_DST32;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	UDE_FSA = PKUNITY_UNIGFX_MMAP_BASE;
+	UDE_LS  = info->var.yres;
+	UDE_PS  = get_line_length(info->var.xres,
+			info->var.bits_per_pixel) >> 3;
+			/* >> 3 for hardware required. */
+	UDE_HAT = (hTotal << 16) | (info->var.xres);
+	UDE_HBT = ((hTotal - 1) << 16) | (info->var.xres - 1);
+	UDE_HST = ((hSyncEnd - 1) << 16) | (hSyncStart - 1);
+	UDE_VAT = (vTotal << 16) | (info->var.yres);
+	UDE_VBT = ((vTotal - 1) << 16) | (info->var.yres - 1);
+	UDE_VST = ((vSyncEnd - 1) << 16) | (vSyncStart - 1);
+	UDE_CFG = UDE_CFG_GDEN_ENABLE | UDE_CFG_TIMEUP_ENABLE
+			| format | 0xC0000001;
+
+	return 0;
+}
+
+/*
+ *  Set a single color register. The values supplied are already
+ *  rounded down to the hardware's capabilities (according to the
+ *  entries in the var structure). Return != 0 for invalid regno.
+ */
+static int unifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			 u_int transp, struct fb_info *info)
+{
+	if (regno >= 256)	/* no. of hw registers */
+		return 1;
+
+	/* grayscale works only partially under directcolor */
+	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)
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+	case FB_VISUAL_PSEUDOCOLOR:
+		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);
+		break;
+	case FB_VISUAL_DIRECTCOLOR:
+		red = CNVT_TOHW(red, 8);	/* expect 8 bit DAC */
+		green = CNVT_TOHW(green, 8);
+		blue = CNVT_TOHW(blue, 8);
+		/* hey, there is bug in transp handling... */
+		transp = CNVT_TOHW(transp, 8);
+		break;
+	}
+#undef CNVT_TOHW
+	/* Truecolor has hardware independent palette */
+	if (info->fix.visual = FB_VISUAL_TRUECOLOR) {
+		u32 v;
+
+		if (regno >= 16)
+			return 1;
+
+		v = (red << info->var.red.offset) |
+		    (green << info->var.green.offset) |
+		    (blue << info->var.blue.offset) |
+		    (transp << info->var.transp.offset);
+		switch (info->var.bits_per_pixel) {
+		case 8:
+			break;
+		case 16:
+		case 24:
+		case 32:
+			((u32 *) (info->pseudo_palette))[regno] = v;
+			break;
+		default:
+			return 1;
+		}
+		return 0;
+	}
+	return 0;
+}
+
+/*
+ *  Pan or Wrap the Display
+ *
+ *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+ */
+static int unifb_pan_display(struct fb_var_screeninfo *var,
+			   struct fb_info *info)
+{
+	if (var->vmode & FB_VMODE_YWRAP) {
+		if (var->yoffset < 0
+		    || var->yoffset >= info->var.yres_virtual
+		    || var->xoffset)
+			return -EINVAL;
+	} else {
+		if (var->xoffset + var->xres > info->var.xres_virtual ||
+		    var->yoffset + var->yres > info->var.yres_virtual)
+			return -EINVAL;
+	}
+	info->var.xoffset = var->xoffset;
+	info->var.yoffset = var->yoffset;
+	if (var->vmode & FB_VMODE_YWRAP)
+		info->var.vmode |= FB_VMODE_YWRAP;
+	else
+		info->var.vmode &= ~FB_VMODE_YWRAP;
+	return 0;
+}
+
+int unifb_mmap(struct fb_info *info,
+		    struct vm_area_struct *vma)
+{
+	unsigned long size = vma->vm_end - vma->vm_start;
+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+	unsigned long pos = info->fix.smem_start + offset;
+
+	if (offset + size > info->fix.smem_len)
+		return -EINVAL;
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+	if (io_remap_pfn_range(vma, vma->vm_start, pos >> PAGE_SHIFT, size,
+				vma->vm_page_prot))
+		return -EAGAIN;
+
+	vma->vm_flags |= VM_RESERVED;	/* avoid to swap out this VMA */
+	return 0;
+
+}
+
+static struct fb_ops unifb_ops = {
+	.fb_read        = fb_sys_read,
+	.fb_write       = fb_sys_write,
+	.fb_check_var	= unifb_check_var,
+	.fb_set_par	= unifb_set_par,
+	.fb_setcolreg	= unifb_setcolreg,
+	.fb_pan_display	= unifb_pan_display,
+	.fb_fillrect	= unifb_fillrect,
+	.fb_copyarea	= unifb_copyarea,
+	.fb_imageblit   = unifb_imageblit,
+	.fb_mmap	= unifb_mmap,
+};
+
+/*
+ *  Initialisation
+ */
+static int unifb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	u32 unifb_regs[UNIFB_REGS_NUM];
+	int retval = -ENOMEM;
+	struct resource *iomem, *mapmem;
+
+	info = framebuffer_alloc(sizeof(u32)*256, &dev->dev);
+	if (!info)
+		goto err;
+
+	info->screen_base = (char __iomem *)KUSER_UNIGFX_BASE;
+	info->fbops = &unifb_ops;
+
+	retval = fb_find_mode(&info->var, info, NULL,
+			      unifb_modes, 10, &unifb_modes[0], 16);
+
+	if (!retval || (retval = 4))
+		info->var = unifb_default;
+
+	iomem = platform_get_resource(dev, IORESOURCE_IO, 0);
+	unifb_fix.mmio_start = iomem->start;
+
+	mapmem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	unifb_fix.smem_start = mapmem->start;
+	unifb_fix.smem_len = UNIFB_MEMSIZE;
+
+	info->fix = unifb_fix;
+	info->pseudo_palette = info->par;
+	info->par = NULL;
+	info->flags = FBINFO_FLAG_DEFAULT;
+#ifdef FB_ACCEL_PUV3_UNIGFX
+	info->fix.accel = FB_ACCEL_PUV3_UNIGFX;
+#endif
+
+	retval = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (retval < 0)
+		goto err1;
+
+	retval = register_framebuffer(info);
+	if (retval < 0)
+		goto err2;
+	platform_set_drvdata(dev, info);
+	platform_device_add_data(dev, unifb_regs, sizeof(u32) * UNIFB_REGS_NUM);
+
+	printk(KERN_INFO
+	       "fb%d: Virtual frame buffer device, using %dM of video memory\n",
+	       info->node, UNIFB_MEMSIZE >> 20);
+	return 0;
+err2:
+	fb_dealloc_cmap(&info->cmap);
+err1:
+	framebuffer_release(info);
+err:
+	return retval;
+}
+
+static int unifb_remove(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+
+	if (info) {
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int unifb_resume(struct platform_device *dev)
+{
+	int rc = 0;
+	u32 *unifb_regs = dev->dev.platform_data;
+
+	if (dev->dev.power.power_state.event = PM_EVENT_ON)
+		return 0;
+
+	acquire_console_sem();
+
+	if (dev->dev.power.power_state.event = PM_EVENT_SUSPEND) {
+		UDE_FSA = unifb_regs[0];
+		UDE_LS  = unifb_regs[1];
+		UDE_PS  = unifb_regs[2];
+		UDE_HAT = unifb_regs[3];
+		UDE_HBT = unifb_regs[4];
+		UDE_HST = unifb_regs[5];
+		UDE_VAT = unifb_regs[6];
+		UDE_VBT = unifb_regs[7];
+		UDE_VST = unifb_regs[8];
+		UDE_CFG = unifb_regs[9];
+	}
+	dev->dev.power.power_state = PMSG_ON;
+
+	release_console_sem();
+
+	return rc;
+}
+
+static int unifb_suspend(struct platform_device *dev, pm_message_t mesg)
+{
+	u32 *unifb_regs = dev->dev.platform_data;
+
+	unifb_regs[0] = UDE_FSA;
+	unifb_regs[1] = UDE_LS;
+	unifb_regs[2] = UDE_PS;
+	unifb_regs[3] = UDE_HAT;
+	unifb_regs[4] = UDE_HBT;
+	unifb_regs[5] = UDE_HST;
+	unifb_regs[6] = UDE_VAT;
+	unifb_regs[7] = UDE_VBT;
+	unifb_regs[8] = UDE_VST;
+	unifb_regs[9] = UDE_CFG;
+
+	if (mesg.event = dev->dev.power.power_state.event)
+		return 0;
+
+	switch (mesg.event) {
+	case PM_EVENT_FREEZE:		/* about to take snapshot */
+	case PM_EVENT_PRETHAW:		/* before restoring snapshot */
+		goto done;
+	}
+
+	acquire_console_sem();
+
+	/* do nothing... */
+
+	release_console_sem();
+
+done:
+	dev->dev.power.power_state = mesg;
+
+	return 0;
+}
+#else
+#define	unifb_resume	NULL
+#define unifb_suspend	NULL
+#endif
+
+static struct platform_driver unifb_driver = {
+	.probe	 = unifb_probe,
+	.remove  = unifb_remove,
+	.resume  = unifb_resume,
+	.suspend = unifb_suspend,
+	.driver  = {
+		.name	= "PKUnity-v3-UNIGFX",
+	},
+};
+
+static int __init unifb_init(void)
+{
+#ifndef MODULE
+	if (fb_get_options("unifb", NULL))
+		return -ENODEV;
+#endif
+
+	return platform_driver_register(&unifb_driver);
+}
+
+module_init(unifb_init);
+
+static void __exit unifb_exit(void)
+{
+	platform_driver_unregister(&unifb_driver);
+}
+
+module_exit(unifb_exit);
+
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/fb.h b/include/linux/fb.h
index d1631d3..4e9da1b 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -152,6 +152,8 @@
 #define FB_ACCEL_PROSAVAGE_DDR  0x8d	/* S3 ProSavage DDR             */
 #define FB_ACCEL_PROSAVAGE_DDRK 0x8e	/* S3 ProSavage DDR-K           */
 
+#define FB_ACCEL_PUV3_UNIGFX	0xa0	/* PKUnity-v3 Unigfx		*/
+
 struct fb_fix_screeninfo {
 	char id[16];			/* identification string eg "TT Builtin" */
 	unsigned long smem_start;	/* Start of frame buffer mem */


^ permalink raw reply related

* RE: [PATCH] unicore32: add framebuffer driver for unigfx engine in PKUnity SoC
From: Guan Xuetao @ 2011-01-27  6:37 UTC (permalink / raw)
  To: Paul Mundt; +Cc: linux-kernel, linux-fbdev
In-Reply-To: <01cf01cbba1f$49f84130$dde8c390$@mprc.pku.edu.cn>

Paul:
 All your advice accepted, please see my patch v2.
 Thanks.

Guan Xuetao


^ permalink raw reply

* RE: [PATCH 0/2][concept RFC] x86: BIOS-save kernel log to disk upon
From: Luck, Tony @ 2011-01-26 23:07 UTC (permalink / raw)
  To: Ahmed S. Darwish, Linus Torvalds
  Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Ingo Molnar, X86-ML,
	Dave Jones, Andrew Morton, Randy Dunlap, Willy Tarreau,
	Willy Tarreau, Dirk Hohndel, Hohndel, Dirk, IDE-ML, LKML,
	Peter Zijlstra, Frédéric Weisbecker, Borislav Petkov,
	Arjan van de Ven, Tejun Heo, James Bottomley, Mark Lord,
	Jeff Garzik, Eric Biederman, Vivek Goyal
In-Reply-To: <20110126124954.GC24527@laptop>

>- The latest approach (proposed by Linus) is to forget the disk: jump to
>  real-mode, but display the kernel log in a fancy format (with scroll
>  ups and downs) instead.

A while ago (first Plumbers conference?) someone was talking about
using a 2-d barcode to display the tail of the kernel log & oops
register data - with the plan that you could capture the image with
a cell phone camera, and then get all the oops data without worrying
about transcription errors as you wrote down & re-typed all the hex.

Anyone know what happened to that plan?

-Tony



^ permalink raw reply

* [PATCH 3/4 v5] video, sm501: add OF binding to support SM501
From: Heiko Schocher @ 2011-01-26  7:21 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Heiko Schocher, linux-fbdev, devicetree-discuss, Ben Dooks,
	Vincent Sanders, Samuel Ortiz, linux-kernel, Randy Dunlap,
	Paul Mundt
In-Reply-To: <1291451028-22532-1-git-send-email-hs@denx.de>

- add binding to OF, compatible name "smi,sm501"

Signed-off-by: Heiko Schocher <hs@denx.de>
cc: linux-fbdev@vger.kernel.org
cc: devicetree-discuss@ozlabs.org
cc: Ben Dooks <ben@simtec.co.uk>
cc: Vincent Sanders <vince@simtec.co.uk>
cc: Samuel Ortiz <sameo@linux.intel.com>
cc: linux-kernel@vger.kernel.org
cc: Randy Dunlap <rdunlap@xenotime.net>
cc: Paul Mundt <lethal@linux-sh.org>

---
- changes since v1:
  add Ben Dooks, Vincent Sanders and Samuel Ortiz to cc, as suggested from
  Paul Mundt.
- changes since v2:
  add comments from Randy Dunlap:
  - move parameter documentation to Documentation/fb/sm501.txt
- changes since v3:
  - rebased against v2.6.38-rc2
  - split in 3 patches
    - of support patch
      - get rid of "#if defined(CONFIG_PPC_MPC52xx)" usage
        hide this in DTS, as Paul suggested.
    - i/o routine patch
    - edid support patch
- changes since v4
  replace remaining CONFIG_PPC_MPC52xx with CONFIG_OF, as
  it is no longer MPC52xx only.
- changes since v5
  free edid_data after its usage, as it is no longer needed,
  suggested from Paul Mundt. Also fall back to default if
  kmemdup(edid_data) fails.

./scripts/checkpatch.pl 0003-video-sm501-add-OF-binding-to-support-SM501.patch
total: 0 errors, 0 warnings, 132 lines checked

0003-video-sm501-add-OF-binding-to-support-SM501.patch has no obvious style problems and is ready for submission.

 Documentation/powerpc/dts-bindings/sm501.txt |   34 +++++++++++++++++++++
 drivers/mfd/sm501.c                          |    9 +++++-
 drivers/video/sm501fb.c                      |   42 ++++++++++++++++++++++++--
 3 files changed, 81 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/powerpc/dts-bindings/sm501.txt

diff --git a/Documentation/powerpc/dts-bindings/sm501.txt b/Documentation/powerpc/dts-bindings/sm501.txt
new file mode 100644
index 0000000..7d319fb
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/sm501.txt
@@ -0,0 +1,34 @@
+* SM SM501
+
+The SM SM501 is a LCD controller, with proper hardware, it can also
+drive DVI monitors.
+
+Required properties:
+- compatible : should be "smi,sm501".
+- reg : contain two entries:
+    - First entry: System Configuration register
+    - Second entry: IO space (Display Controller register)
+- interrupts : SMI interrupt to the cpu should be described here.
+- interrupt-parent : the phandle for the interrupt controller that
+  services interrupts for this device.
+
+Optional properties:
+- mode : select a video mode:
+    <xres>x<yres>[-<bpp>][@<refresh>]
+- edid : verbatim EDID data block describing attached display.
+  Data from the detailed timing descriptor will be used to
+  program the display controller.
+- little-endian: availiable on big endian systems, to
+  set different foreign endian.
+- big-endian: availiable on little endian systems, to
+  set different foreign endian.
+
+Example for MPC5200:
+	display@1,0 {
+		compatible = "smi,sm501";
+		reg = <1 0x00000000 0x00800000
+		       1 0x03e00000 0x00200000>;
+		interrupts = <1 1 3>;
+		mode = "640x480-32@60";
+		edid = [edid-data];
+	};
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 558d5f3..df3702c 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -1377,7 +1377,7 @@ static int __devinit sm501_init_dev(struct sm501_devdata *sm)
 			sm501_register_gpio(sm);
 	}
 
-	if (pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) {
+	if (pdata && pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) {
 		if (!sm501_gpio_isregistered(sm))
 			dev_err(sm->dev, "no gpio available for i2c gpio.\n");
 		else
@@ -1422,6 +1422,7 @@ static int __devinit sm501_plat_probe(struct platform_device *dev)
 
 	sm->io_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
 	sm->mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+
 	if (sm->io_res = NULL || sm->mem_res = NULL) {
 		dev_err(&dev->dev, "failed to get IO resource\n");
 		ret = -ENOENT;
@@ -1735,10 +1736,16 @@ static struct pci_driver sm501_pci_driver = {
 
 MODULE_ALIAS("platform:sm501");
 
+static struct of_device_id __devinitdata of_sm501_match_tbl[] = {
+	{ .compatible = "smi,sm501", },
+	{ /* end */ }
+};
+
 static struct platform_driver sm501_plat_driver = {
 	.driver		= {
 		.name	= "sm501",
 		.owner	= THIS_MODULE,
+		.of_match_table = of_sm501_match_tbl,
 	},
 	.probe		= sm501_plat_probe,
 	.remove		= sm501_plat_remove,
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index d60b2a2..92b001d 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -1729,6 +1729,15 @@ static int sm501fb_init_fb(struct fb_info *fb,
 		FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
 		FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
 
+#if defined(CONFIG_OF)
+#ifdef __BIG_ENDIAN
+	if (of_get_property(info->dev->parent->of_node, "little-endian", NULL))
+		fb->flags |= FBINFO_FOREIGN_ENDIAN;
+#else
+	if (of_get_property(info->dev->parent->of_node, "big-endian", NULL))
+		fb->flags |= FBINFO_FOREIGN_ENDIAN;
+#endif
+#endif
 	/* fixed data */
 
 	fb->fix.type		= FB_TYPE_PACKED_PIXELS;
@@ -1765,14 +1774,17 @@ static int sm501fb_init_fb(struct fb_info *fb,
 			fb->var.xres_virtual = fb->var.xres;
 			fb->var.yres_virtual = fb->var.yres;
 		} else {
-			if (info->edid_data)
+			if (info->edid_data) {
 				ret = fb_find_mode(&fb->var, fb, fb_mode,
 					fb->monspecs.modedb,
 					fb->monspecs.modedb_len,
 					&sm501_default_mode, default_bpp);
-			else
+				/* edid_data is no longer needed, free it */
+				kfree(info->edid_data);
+			} else {
 				ret = fb_find_mode(&fb->var, fb,
 					   NULL, NULL, 0, NULL, 8);
+			}
 
 			switch (ret) {
 			case 1:
@@ -1933,8 +1945,32 @@ static int __devinit sm501fb_probe(struct platform_device *pdev)
 	}
 
 	if (info->pdata = NULL) {
-		dev_info(dev, "using default configuration data\n");
+		int found = 0;
+#if defined(CONFIG_OF)
+		struct device_node *np = pdev->dev.parent->of_node;
+		const u8 *prop;
+		const char *cp;
+		int len;
+
 		info->pdata = &sm501fb_def_pdata;
+		if (np) {
+			/* Get EDID */
+			cp = of_get_property(np, "mode", &len);
+			if (cp)
+				strcpy(fb_mode, cp);
+			prop = of_get_property(np, "edid", &len);
+			if (prop && len = EDID_LENGTH) {
+				info->edid_data = kmemdup(prop, EDID_LENGTH,
+							  GFP_KERNEL);
+				if (info->edid_data)
+					found = 1;
+			}
+		}
+#endif
+		if (!found) {
+			dev_info(dev, "using default configuration data\n");
+			info->pdata = &sm501fb_def_pdata;
+		}
 	}
 
 	/* probe for the presence of each panel */
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH 2/4 v5] video, sm501: add edid and commandline support
From: Heiko Schocher @ 2011-01-26  7:21 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Heiko Schocher, linux-fbdev, devicetree-discuss, Ben Dooks,
	Vincent Sanders, Samuel Ortiz, linux-kernel, Randy Dunlap,
	Paul Mundt
In-Reply-To: <1291451028-22532-1-git-send-email-hs@denx.de>

- add commandline options:
  sm501fb.mode:
    Specify resolution as "<xres>x<yres>[-<bpp>][@<refresh>]"
  sm501fb.bpp:
    Specify bit-per-pixel if not specified mode

- Add support for encoding display mode information
  in the device tree using verbatim EDID block.

  If the "edid" entry in the "smi,sm501" node is present,
  the driver will build mode database using EDID data
  and allow setting the display modes from this database.

Signed-off-by: Heiko Schocher <hs@denx.de>
cc: linux-fbdev@vger.kernel.org
cc: devicetree-discuss@ozlabs.org
cc: Ben Dooks <ben@simtec.co.uk>
cc: Vincent Sanders <vince@simtec.co.uk>
cc: Samuel Ortiz <sameo@linux.intel.com>
cc: linux-kernel@vger.kernel.org
cc: Randy Dunlap <rdunlap@xenotime.net>
cc: Paul Mundt <lethal@linux-sh.org>

---
- changes since v1:
  add Ben Dooks, Vincent Sanders and Samuel Ortiz to cc, as suggested from
  Paul Mundt.
- changes since v2:
  add comments from Randy Dunlap:
  - move parameter documentation to Documentation/fb/sm501.txt
- changes since v3:
  - rebased against v2.6.38-rc2
  - split in 3 patches
    - of support patch
    - i/o routine patch
    - edid support patch
- changes since v4:
  - add "info->pdata = &sm501fb_def_pdata;" in sm501fb_probe()
    as Paul Mundt suggested (and I wrongly deleted)
  - move kfree(info->edid_data); to patch 3/4
    as edid_data is only allocated in the CONFIG_OF case

./scripts/checkpatch.pl 0002-video-sm501-add-edid-and-commandline-support.patch
total: 0 errors, 0 warnings, 109 lines checked

0002-video-sm501-add-edid-and-commandline-support.patch has no obvious style problems and is ready for submission.

 Documentation/fb/sm501.txt |   10 +++++++
 drivers/video/sm501fb.c    |   65 ++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 70 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/fb/sm501.txt

diff --git a/Documentation/fb/sm501.txt b/Documentation/fb/sm501.txt
new file mode 100644
index 0000000..8d17aeb
--- /dev/null
+++ b/Documentation/fb/sm501.txt
@@ -0,0 +1,10 @@
+Configuration:
+
+You can pass the following kernel command line options to sm501 videoframebuffer:
+
+	sm501fb.bpp=	SM501 Display driver:
+			Specifiy bits-per-pixel if not specified by 'mode'
+
+	sm501fb.mode=	SM501 Display driver:
+			Specify resolution as
+			"<xres>x<yres>[-<bpp>][@<refresh>]"
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index c5b4b95..d60b2a2 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -41,6 +41,26 @@
 #include <linux/sm501.h>
 #include <linux/sm501-regs.h>
 
+#include "edid.h"
+
+static char *fb_mode = "640x480-16@60";
+static unsigned long default_bpp = 16;
+
+static struct fb_videomode __devinitdata sm501_default_mode = {
+	.refresh	= 60,
+	.xres		= 640,
+	.yres		= 480,
+	.pixclock	= 20833,
+	.left_margin	= 142,
+	.right_margin	= 13,
+	.upper_margin	= 21,
+	.lower_margin	= 1,
+	.hsync_len	= 69,
+	.vsync_len	= 3,
+	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	.vmode		= FB_VMODE_NONINTERLACED
+};
+
 #define NR_PALETTE	256
 
 enum sm501_controller {
@@ -77,6 +97,7 @@ struct sm501fb_info {
 	void __iomem		*regs2d;	/* 2d remapped registers */
 	void __iomem		*fbmem;		/* remapped framebuffer */
 	size_t			 fbmem_len;	/* length of remapped region */
+	u8 *edid_data;
 };
 
 /* per-framebuffer private data */
@@ -1725,9 +1746,16 @@ static int sm501fb_init_fb(struct fb_info *fb,
 	fb->var.vmode		= FB_VMODE_NONINTERLACED;
 	fb->var.bits_per_pixel  = 16;
 
+	if (info->edid_data) {
+			/* Now build modedb from EDID */
+			fb_edid_to_monspecs(info->edid_data, &fb->monspecs);
+			fb_videomode_to_modelist(fb->monspecs.modedb,
+						 fb->monspecs.modedb_len,
+						 &fb->modelist);
+	}
+
 	if (enable && (pd->flags & SM501FB_FLAG_USE_INIT_MODE) && 0) {
 		/* TODO read the mode from the current display */
-
 	} else {
 		if (pd->def_mode) {
 			dev_info(info->dev, "using supplied mode\n");
@@ -1737,12 +1765,34 @@ static int sm501fb_init_fb(struct fb_info *fb,
 			fb->var.xres_virtual = fb->var.xres;
 			fb->var.yres_virtual = fb->var.yres;
 		} else {
-			ret = fb_find_mode(&fb->var, fb,
+			if (info->edid_data)
+				ret = fb_find_mode(&fb->var, fb, fb_mode,
+					fb->monspecs.modedb,
+					fb->monspecs.modedb_len,
+					&sm501_default_mode, default_bpp);
+			else
+				ret = fb_find_mode(&fb->var, fb,
 					   NULL, NULL, 0, NULL, 8);
 
-			if (ret = 0 || ret = 4) {
-				dev_err(info->dev,
-					"failed to get initial mode\n");
+			switch (ret) {
+			case 1:
+				dev_info(info->dev, "using mode specified in "
+						"@mode\n");
+				break;
+			case 2:
+				dev_info(info->dev, "using mode specified in "
+					"@mode with ignored refresh rate\n");
+				break;
+			case 3:
+				dev_info(info->dev, "using mode default "
+					"mode\n");
+				break;
+			case 4:
+				dev_info(info->dev, "using mode from list\n");
+				break;
+			default:
+				dev_info(info->dev, "ret = %d\n", ret);
+				dev_info(info->dev, "failed to find mode\n");
 				return -EINVAL;
 			}
 		}
@@ -2157,6 +2207,11 @@ static void __exit sm501fb_cleanup(void)
 module_init(sm501fb_init);
 module_exit(sm501fb_cleanup);
 
+module_param_named(mode, fb_mode, charp, 0);
+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_AUTHOR("Ben Dooks, Vincent Sanders");
 MODULE_DESCRIPTION("SM501 Framebuffer driver");
 MODULE_LICENSE("GPL v2");
-- 
1.7.3.4


^ permalink raw reply related

* Re: [PATCH] video/via: drop deprecated (and unused) i2c_adapter.id
From: Jean Delvare @ 2011-01-25 22:15 UTC (permalink / raw)
  To: Peter Huewe
  Cc: Florian Tobias Schandinat, linux-fbdev, linux-kernel,
	kernel-janitors
In-Reply-To: <1295991264-8640-1-git-send-email-peterhuewe@gmx.de>

On Tue, 25 Jan 2011 22:34:24 +0100, Peter Huewe wrote:
> This patch removes an assignment to the deprecated i2c_adapter.id
> field. Since the field isn't used anywhere else in the driver it is
> save to remove it.
> 
> Signed-off-by: Peter Huewe <peterhuewe@gmx.de>

Acked-by: Jean Delvare <khali@linux-fr.org>

> ---
>  drivers/video/via/via_i2c.c |    1 -
>  1 files changed, 0 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c
> index 3844b55..a172a31 100644
> --- a/drivers/video/via/via_i2c.c
> +++ b/drivers/video/via/via_i2c.c
> @@ -209,7 +209,6 @@ static int create_i2c_bus(struct i2c_adapter *adapter,
>  	sprintf(adapter->name, "viafb i2c io_port idx 0x%02x",
>  		adap_cfg->ioport_index);
>  	adapter->owner = THIS_MODULE;
> -	adapter->id = 0x01FFFF;
>  	adapter->class = I2C_CLASS_DDC;
>  	adapter->algo_data = algo;
>  	if (pdev)


-- 
Jean Delvare

^ permalink raw reply

* [PATCH] video/via: drop deprecated (and unused) i2c_adapter.id
From: Peter Huewe @ 2011-01-25 21:34 UTC (permalink / raw)
  To: Florian Tobias Schandinat
  Cc: linux-fbdev, linux-kernel, kernel-janitors, Jean Delvare,
	Peter Huewe

This patch removes an assignment to the deprecated i2c_adapter.id
field. Since the field isn't used anywhere else in the driver it is
save to remove it.

Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
---
 drivers/video/via/via_i2c.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c
index 3844b55..a172a31 100644
--- a/drivers/video/via/via_i2c.c
+++ b/drivers/video/via/via_i2c.c
@@ -209,7 +209,6 @@ static int create_i2c_bus(struct i2c_adapter *adapter,
 	sprintf(adapter->name, "viafb i2c io_port idx 0x%02x",
 		adap_cfg->ioport_index);
 	adapter->owner = THIS_MODULE;
-	adapter->id = 0x01FFFF;
 	adapter->class = I2C_CLASS_DDC;
 	adapter->algo_data = algo;
 	if (pdev)
-- 
1.7.2.2


^ permalink raw reply related

* [GIT PULL] fbdev updates for 2.6.38-rc3
From: Paul Mundt @ 2011-01-25  9:51 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-fbdev, linux-kernel

Please pull from:

	master.kernel.org:/pub/scm/linux/kernel/git/lethal/fbdev-2.6.git fbdev-fixes-for-linus

Which contains:

Amerigo Wang (1):
      video: fix some comments in drivers/video/console/vgacon.c

Axel Lin (5):
      video: nuc900fb: fix compile error
      video: nuc900fb: properly free resources in nuc900fb_remove
      video: pxa3xx-gcu: Return -EFAULT when copy_from_user() fails
      video: da8xx-fb: fix fb_probe error path
      video: pxa168fb: remove a redundant pxa168fb_check_var call

Julia Lawall (1):
      drivers/video/bf537-lq035.c: Add missing IS_ERR test

Paul Mundt (1):
      mailmap: Add an entry for Axel Lin.

 .mailmap                       |    1 +
 drivers/video/bf537-lq035.c    |   58 ++++++++++++++++++++++-----------------
 drivers/video/console/vgacon.c |    6 +---
 drivers/video/da8xx-fb.c       |    3 +-
 drivers/video/nuc900fb.c       |    6 +++-
 drivers/video/pxa168fb.c       |    6 +---
 drivers/video/pxa3xx-gcu.c     |    4 +-
 7 files changed, 44 insertions(+), 40 deletions(-)

^ permalink raw reply

* Re: [PATCH] unicore32: add framebuffer driver for unigfx engine in PKUnity SoC
From: Paul Mundt @ 2011-01-25  9:02 UTC (permalink / raw)
  To: Guan Xuetao; +Cc: linux-fbdev, linux-kernel
In-Reply-To: <01cf01cbba1f$49f84130$dde8c390$@mprc.pku.edu.cn>

On Sat, Jan 22, 2011 at 06:29:45PM +0800, Guan Xuetao wrote:
> diff --git a/drivers/video/puv3_fb.c b/drivers/video/puv3_fb.c
> new file mode 100644
> index 0000000..d938a73
> --- /dev/null
> +++ b/drivers/video/puv3_fb.c
[snip]

> +static unsigned long unifb_regs[10];
> +
This is probably something that you will want to move in to platform
data.

> +#define VIDEOMEMSIZE	(SZ_4M)		/* 4 MB for 1024*768*32b */
> +
> +static void *videomemory;
> +static u_long videomemorysize = VIDEOMEMSIZE;
> +module_param(videomemorysize, ulong, 0);
> +
Along with these, given that they're not dynamically acquired by the
driver.

> +static int unifb_enable __initdata = 1;	/* enable by default */
> +module_param(unifb_enable, bool, 0);
> +
No need for this, you can use fb_get_options() and -ENODEV out in the
init path then simply use the generic "off" parsing done by the fbmem
code.

> +#ifdef CONFIG_PUV3_UNIGFX_HWACCEL
> +static void unifb_sync(void)
> +{
> +	/* TODO: may, this can be replaced by interrupt */
> +	int cnt;
> +
> +	for (cnt = 0; cnt < 0x10000000; cnt++) {
> +		if (UGE_COMMAND & 0x1000000)
> +			return;
> +	}
> +
> +	if (cnt > 0x8000000)
> +		printk(KERN_WARNING "Warning: UniGFX GE time out ...\n");
> +}
> +
In addition to switching to platform data for the I/O offsets, you can
also use dev_warn() here on the device pointer (fb_info->device).

> +static struct fb_ops unifb_ops = {
> +	.fb_read        = fb_sys_read,
> +	.fb_write       = fb_sys_write,
> +	.fb_check_var	= unifb_check_var,
> +	.fb_set_par	= unifb_set_par,
> +	.fb_setcolreg	= unifb_setcolreg,
> +	.fb_pan_display	= unifb_pan_display,
> +#ifdef CONFIG_PUV3_UNIGFX_HWACCEL
> +	.fb_fillrect	= unifb_fillrect,
> +	.fb_copyarea	= unifb_copyarea,
> +	.fb_imageblit   = unifb_imageblit,
> +#else
> +	.fb_fillrect	= sys_fillrect,
> +	.fb_copyarea	= sys_copyarea,
> +	.fb_imageblit	= sys_imageblit,
> +#endif
> +	.fb_mmap	= unifb_mmap,
> +};
> +
There's no need for the ifdef here, all of your accel routines manually
check if acceleration is disabled or not and fall back on the sys_xxx()
paths, so it's safe to always reference them.

> +static int unifb_set_par(struct fb_info *info)
> +{
> +	int hTotal, vTotal, hSyncStart, hSyncEnd, vSyncStart, vSyncEnd;
> +	int format;
> +
> +#ifdef CONFIG_PUV3_PM
> +	struct clk *clk_vga;
> +	u32 pixclk = 0;
> +	int i;
> +
> +	for (i = 0; i <= 10; i++) {
> +		if    (info->var.xres         = unifb_modes[i].xres
> +		    && info->var.yres         = unifb_modes[i].yres
> +		    && info->var.upper_margin = unifb_modes[i].upper_margin
> +		    && info->var.lower_margin = unifb_modes[i].lower_margin
> +		    && info->var.left_margin  = unifb_modes[i].left_margin
> +		    && info->var.right_margin = unifb_modes[i].right_margin
> +		    && info->var.hsync_len    = unifb_modes[i].hsync_len
> +		    && info->var.vsync_len    = unifb_modes[i].vsync_len) {
> +			pixclk = unifb_modes[i].pixclock;
> +			break;
> +		}
> +	}
> +
> +	/* set clock rate */
> +	clk_vga = clk_get(NULL, "VGA_CLK");
> +	i = 0;

You can pass info->device to clk_get() instead of NULL. This will make it
easier to match specific clocks and lookups per device in the future.

You'll presumably also want to check if clk_get() returned an error and
handle that accordingly.

> +	if (pixclk != 0) {
> +		if (clk_set_rate(clk_vga, pixclk) = 0)
> +			i = 1;
> +	}
> +
> +	if (i = 0) {           /* set clock failed */
> +		info->fix = unifb_fix;
> +		info->var = unifb_default;
> +		clk_set_rate(clk_vga, unifb_default.pixclock);
> +	}

If clk_set_rate() can fail the first time, it can fail the second time
too. You'll want more error handling here.

> +	/* Truecolor has hardware independent palette */
> +	if (info->fix.visual = FB_VISUAL_TRUECOLOR) {
> +		u32 v;
> +
> +		if (regno >= 16)
> +			return 1;
> +
> +		v = (red << info->var.red.offset) |
> +		    (green << info->var.green.offset) |
> +		    (blue << info->var.blue.offset) |
> +		    (transp << info->var.transp.offset);
> +		switch (info->var.bits_per_pixel) {
> +		case 8:
> +			break;
> +		case 16:
> +			((u32 *) (info->pseudo_palette))[regno] = v;
> +			break;
> +		case 24:
> +		case 32:
> +			((u32 *) (info->pseudo_palette))[regno] = v;
> +			break;
> +		}

The 16 case is no different than the 24/32 case.

The default case should also return 1 to indicate an error.

> +#ifndef MODULE
> +/*
> + * The virtual framebuffer driver is only enabled if explicitly
> + * requested by passing 'video=unifb:' (or any actual options).
> + */
> +static int __init unifb_setup(char *options)
> +{
> +	char *this_opt;
> +
> +	unifb_enable = 0;
> +
> +	if (!options)
> +		return 1;
> +
> +	unifb_enable = 1;
> +
> +	if (!*options)
> +		return 1;
> +
> +	while ((this_opt = strsep(&options, ",")) != NULL) {
> +		if (!*this_opt)
> +			continue;
> +		/* Test disable for backwards compatibility */
> +		if (!strcmp(this_opt, "disable"))
> +			unifb_enable = 0;
> +	}
> +	return 1;
> +}
> +#endif  /*  MODULE  */
> +
Just kill all of this and use the generic "off" handling.

> +static int unifb_probe(struct platform_device *dev)
> +{
> +	struct fb_info *info;
> +	int retval = -ENOMEM;
> +
> +	/*
> +	 * For real video cards we use ioremap.
> +	 */
> +	videomemory = (void *)KUSER_UNIGFX_BASE;
> +
> +	/*
> +	 * VFB could clear memory to prevent kernel info
> +	 * leakage into userspace and set black screen
> +	 * VGA-based drivers MUST NOT clear memory if
> +	 * they want to be able to take over vgacon
> +	 */
> +	/* memset(videomemory, 0, videomemorysize); */
> +
This is a remnant from a vmalloc acquired framebuffer base, so can be
killed off.

> +	info = framebuffer_alloc(sizeof(u32)*256, &dev->dev);
> +	if (!info)
> +		goto err;
> +
> +	info->screen_base = (char __iomem *)videomemory;

> +	unifb_fix.smem_start = PKUNITY_UNIGFX_MMAP_BASE;
> +	unifb_fix.smem_len = videomemorysize;
> +	unifb_fix.mmio_start = PKUNITY_UNIGFX_BASE;

All of these should be passed in via your platform device resources, with
necessary remapping.

> +	info->fix = unifb_fix;
> +	info->pseudo_palette = info->par;
> +	info->par = NULL;
> +	info->flags = FBINFO_FLAG_DEFAULT;
> +#ifdef CONFIG_PUV3_UNIGFX_HWACCEL
> +	info->fix.accel = FB_ACCEL_PUV3_UNIGFX;
> +	info->flags |= FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
> +#else
> +	info->flags |= FBINFO_HWACCEL_DISABLED;
> +#endif
> +
The accel flag is deprecated, so just drop it completely.

What happened to FBINFO_HWACCEL_IMAGEBLIT?

> +#ifdef CONFIG_PM
> +static int unifb_resume(struct platform_device *dev)
> +{
> +	int rc = 0;
> +
> +	if (dev->dev.power.power_state.event = PM_EVENT_ON)
> +		return 0;
> +
> +	acquire_console_sem();
> +
> +	if (dev->dev.power.power_state.event = PM_EVENT_SUSPEND) {
> +		UDE_FSA = unifb_regs[0];
> +		UDE_LS  = unifb_regs[1];
> +		UDE_PS  = unifb_regs[2];
> +		UDE_HAT = unifb_regs[3];
> +		UDE_HBT = unifb_regs[4];
> +		UDE_HST = unifb_regs[5];
> +		UDE_VAT = unifb_regs[6];
> +		UDE_VBT = unifb_regs[7];
> +		UDE_VST = unifb_regs[8];
> +		UDE_CFG = unifb_regs[9];
> +	}

This is probably worth abstracting through platform data.

> +
> +static int __init unifb_init(void)
> +{
> +	int ret = 0;
> +
> +#ifndef MODULE
> +	if (fb_get_options("unifb", &unifb_option))
> +		return -ENODEV;
> +	unifb_setup(unifb_option);
> +#endif
> +
> +	if (!unifb_enable)
> +		return -ENXIO;
> +

All of this can just be replaced with:

	if (fb_get_options("unifb", NULL))
		return -ENODEV;

> +	ret = platform_driver_register(&unifb_driver);
> +
> +	if (!ret) {
> +		unifb_device = platform_device_alloc("unifb", 0);
> +
> +		if (unifb_device)
> +			ret = platform_device_add(unifb_device);
> +		else
> +			ret = -ENOMEM;
> +
> +		if (ret) {
> +			platform_device_put(unifb_device);
> +			platform_driver_unregister(&unifb_driver);
> +		}
> +	}
> +
> +	return ret;
> +}
> +
And if your architecture will then register a platform device with the
platform data filled out, all of this can be turned in to just a simple
platform_driver_register().

> +module_init(unifb_init);
> +
> +#ifdef MODULE
> +static void __exit unifb_exit(void)
> +{
> +	platform_device_unregister(unifb_device);
> +	platform_driver_unregister(&unifb_driver);
> +}
> +
> +module_exit(unifb_exit);
> +
> +MODULE_LICENSE("GPL v2");
> +#endif

No need for the ifdef here, either.

^ permalink raw reply

* RE: [PATCH 3/4] drivers/video/bf537-lq035.c: Add missing IS_ERR test
From: Hennerich, Michael @ 2011-01-25  8:36 UTC (permalink / raw)
  To: Julia Lawall, Paul Mundt
  Cc: kernel-janitors@vger.kernel.org, Mike Frysinger, Bryan Wu,
	linux-fbdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <1295898922-18822-4-git-send-email-julia@diku.dk>

Julia Lawall wrote on 2011-01-24:
> lcd_device_register may return ERR_PTR, so a check is added for this
> value before the dereference.  All of the other changes reorganize the
> error handling code in this function to avoid duplicating all of it in
> the added case.
>
> In the original code, in one case, the global variable fb_buffer was
> set to NULL in error code that appears after this variable is
> initialized.  This is done now in all error handling code that has
> this property.
>
> The semantic match that finds this problem is as follows:
> (http://coccinelle.lip6.fr/)
>
> // <smpl>
> @r@
> identifier f;
> @@
> f(...) { ... return ERR_PTR(...); }
>
> @@
> identifier r.f, fld;
> expression x;
> statement S1,S2;
> @@
>  x = f(...) ... when != IS_ERR(x) ( if (IS_ERR(x) ||...) S1 else S2
> |
> *x->fld
> )
> // </smpl>
>
> Signed-off-by: Julia Lawall <julia@diku.dk>

Looks good to me.

Acked-by: "Hennerich, Michael" <Michael.Hennerich@analog.com>

> ---
>  drivers/video/bf537-lq035.c |   58 +++++++++++++++++++++++++----------
>  --------- 1 file changed, 33 insertions(+), 25 deletions(-)
> diff --git a/drivers/video/bf537-lq035.c b/drivers/video/bf537-lq035.c
> index 18c5078..47c21fb 100644
> --- a/drivers/video/bf537-lq035.c
> +++ b/drivers/video/bf537-lq035.c
> @@ -696,6 +696,7 @@ static int __devinit bfin_lq035_probe(struct
> platform_device *pdev)  {
>       struct backlight_properties props;
>       dma_addr_t dma_handle;
> +     int ret;
>
>       if (request_dma(CH_PPI, KBUILD_MODNAME)) {
>               pr_err("couldn't request PPI DMA\n"); @@ -704,17 +705,16 @@ static
> int __devinit bfin_lq035_probe(struct platform_device *pdev)
>
>       if (request_ports()) {
>               pr_err("couldn't request gpio port\n");
> -             free_dma(CH_PPI);
> -             return -EFAULT;
> +             ret = -EFAULT;
> +             goto out_ports;
>       }
>
>       fb_buffer = dma_alloc_coherent(NULL, TOTAL_VIDEO_MEM_SIZE,
>                                      &dma_handle, GFP_KERNEL);
>       if (fb_buffer = NULL) {
>               pr_err("couldn't allocate dma buffer\n");
> -             free_dma(CH_PPI);
> -             free_ports();
> -             return -ENOMEM;
> +             ret = -ENOMEM;
> +             goto out_dma_coherent;
>       }
>
>       if (L1_DATA_A_LENGTH)
> @@ -725,10 +725,8 @@ static int __devinit bfin_lq035_probe(struct
> platform_device *pdev)
>
>       if (dma_desc_table = NULL) {
>               pr_err("couldn't allocate dma descriptor\n");
> -             free_dma(CH_PPI);
> -             free_ports();
> -             dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer,
> 0);
> -             return -ENOMEM;
> +             ret = -ENOMEM;
> +             goto out_table;
>       }
>
>       bfin_lq035_fb.screen_base = (void *)fb_buffer; @@ -771,31 +769,21 @@
>  static int __devinit bfin_lq035_probe(struct platform_device *pdev)
>       bfin_lq035_fb.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL);
>       if (bfin_lq035_fb.pseudo_palette = NULL) {             pr_err("failed to
>  allocate pseudo_palette\n");
> -             free_dma(CH_PPI);
> -             free_ports();
> -             dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer,
> 0);
> -             return -ENOMEM;
> +             ret = -ENOMEM;
> +             goto out_palette;
>       }
>
>       if (fb_alloc_cmap(&bfin_lq035_fb.cmap, NBR_PALETTE, 0) < 0) {
>               pr_err("failed to allocate colormap (%d entries)\n",
>                       NBR_PALETTE);
> -             free_dma(CH_PPI);
> -             free_ports();
> -             dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer,
> 0);
> -             kfree(bfin_lq035_fb.pseudo_palette);
> -             return -EFAULT;
> +             ret = -EFAULT;
> +             goto out_cmap;
>       }
>
>       if (register_framebuffer(&bfin_lq035_fb) < 0) {
>               pr_err("unable to register framebuffer\n");
> -             free_dma(CH_PPI); -             free_ports(); -         dma_free_coherent(NULL,
> TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0); -                fb_buffer = NULL;
> -             kfree(bfin_lq035_fb.pseudo_palette);
> -             fb_dealloc_cmap(&bfin_lq035_fb.cmap); -         return -EINVAL; +               ret > -EINVAL; +            goto out_reg;
>       }
>
>       i2c_add_driver(&ad5280_driver);
> @@ -807,11 +795,31 @@ static int __devinit bfin_lq035_probe(struct
> platform_device *pdev)
>
>       lcd_dev = lcd_device_register(KBUILD_MODNAME, &pdev->dev, NULL,
>                                     &bfin_lcd_ops);
> +     if (IS_ERR(lcd_dev)) {
> +             pr_err("unable to register lcd\n");
> +             ret = PTR_ERR(lcd_dev);
> +             goto out_lcd;
> +     }
>       lcd_dev->props.max_contrast = 255,
>
>       pr_info("initialized");
>
>       return 0;
> +out_lcd:
> +     unregister_framebuffer(&bfin_lq035_fb);
> +out_reg:
> +     fb_dealloc_cmap(&bfin_lq035_fb.cmap);
> +out_cmap:
> +     kfree(bfin_lq035_fb.pseudo_palette);
> +out_palette:
> +out_table:
> +     dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
> +     fb_buffer = NULL;
> +out_dma_coherent:
> +     free_ports();
> +out_ports:
> +     free_dma(CH_PPI);
> +     return ret;
>  }
>
>  static int __devexit bfin_lq035_remove(struct platform_device *pdev)

Greetings,
Michael

--
Analog Devices GmbH      Wilhelm-Wagenfeld-Str. 6      80807 Muenchen
Sitz der Gesellschaft: Muenchen; Registergericht: Muenchen HRB 40368; Geschaeftsfuehrer:Dr.Carsten Suckrow, Thomas Wessel, William A. Martin, Margaret Seif



^ permalink raw reply

* Re: [PATCH 2/4 v4] video, sm501: add edid and commandline support
From: Heiko Schocher @ 2011-01-25  8:04 UTC (permalink / raw)
  To: Paul Mundt
  Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, Samuel Ortiz,
	Vincent Sanders, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Ben Dooks,
	Randy Dunlap, linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ
In-Reply-To: <20110125075104.GJ11673-M7jkjyW5wf5g9hUCZPvPmw@public.gmane.org>

Hello Paul,

Paul Mundt wrote:
> On Mon, Jan 24, 2011 at 10:57:27AM +0100, Heiko Schocher wrote:
>> @@ -1884,7 +1935,6 @@ static int __devinit sm501fb_probe(struct platform_device *pdev)
>>  
>>  	if (info->pdata = NULL) {
>>  		dev_info(dev, "using default configuration data\n");
>> -		info->pdata = &sm501fb_def_pdata;
>>  	}
>>  
>>  	/* probe for the presence of each panel */
> 
> I assume this is accidental? I don't see how you're compensating for this
> in any of the other patches at least, as it's orthogonal from the default
> mode settings.

Seems so, rework this too, thanks!

bye,
heiko
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

^ permalink raw reply

* Re: [PATCH 3/4 v4] video, sm501: add OF binding to support SM501
From: Heiko Schocher @ 2011-01-25  8:02 UTC (permalink / raw)
  To: Paul Mundt
  Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, Samuel Ortiz,
	Vincent Sanders, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Ben Dooks,
	Randy Dunlap, linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ
In-Reply-To: <20110125074820.GI11673-M7jkjyW5wf5g9hUCZPvPmw@public.gmane.org>

Hello Paul,

Paul Mundt wrote:
> On Tue, Jan 25, 2011 at 08:20:31AM +0100, Heiko Schocher wrote:
>> @@ -1934,7 +1943,29 @@ static int __devinit sm501fb_probe(struct platform_device *pdev)
>>  	}
>>  
>>  	if (info->pdata = NULL) {
>> -		dev_info(dev, "using default configuration data\n");
>> +		int found = 0;
>> +#if defined(CONFIG_OF)
>> +		struct device_node *np = pdev->dev.parent->of_node;
>> +		const u8 *prop;
>> +		const char *cp;
>> +		int len;
>> +
>> +		info->pdata = &sm501fb_def_pdata;
>> +		if (np) {
>> +			/* Get EDID */
>> +			cp = of_get_property(np, "mode", &len);
>> +			if (cp)
>> +				strcpy(fb_mode, cp);
>> +			prop = of_get_property(np, "edid", &len);
>> +			if (prop && len = EDID_LENGTH) {
>> +				info->edid_data = kmemdup(prop, EDID_LENGTH,
>> +							  GFP_KERNEL);
>> +				found = 1;
>> +			}
>> +		}
>> +#endif
>> +		if (!found)
>> +			dev_info(dev, "using default configuration data\n");
>>  	}
>>  
>>  	/* probe for the presence of each panel */
> 
> Starting to get a bit pedantic.. but kmemdup() tries to do a kmalloc(),

No problem!

> and so can fail. Your other patches handle the info->edid_data = NULL
> case, in addition to the kfree(), but you're probably going to want to
> chomp that found assignment incase of the allocation failing and falling
> back on the default mode.
> 
> You also don't really have any need to keep the EDID block around after
> probe as far as I can tell, so you should be able to rework this in to
> something more like:
> 
> 	info->edid_data = kmemdup(..);
> 	...
> 	if (info->edid_data) {
> 		fb_edid_to_monspecs(..);
> 		kfree(info->edid_data);
> 		fb_videomode_to_modelist(..);
> 	}
> 
> 	...

Ok, rework this part, thanks!

bye,
Heiko
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

^ permalink raw reply

* Re: [PATCH 2/4 v4] video, sm501: add edid and commandline support
From: Paul Mundt @ 2011-01-25  7:51 UTC (permalink / raw)
  To: Heiko Schocher
  Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, Samuel Ortiz,
	Vincent Sanders, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Ben Dooks,
	Randy Dunlap, linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ
In-Reply-To: <1295863047-11131-1-git-send-email-hs-ynQEQJNshbs@public.gmane.org>

On Mon, Jan 24, 2011 at 10:57:27AM +0100, Heiko Schocher wrote:
> @@ -1884,7 +1935,6 @@ static int __devinit sm501fb_probe(struct platform_device *pdev)
>  
>  	if (info->pdata = NULL) {
>  		dev_info(dev, "using default configuration data\n");
> -		info->pdata = &sm501fb_def_pdata;
>  	}
>  
>  	/* probe for the presence of each panel */

I assume this is accidental? I don't see how you're compensating for this
in any of the other patches at least, as it's orthogonal from the default
mode settings.

^ permalink raw reply

* Re: [PATCH 3/4 v4] video, sm501: add OF binding to support SM501
From: Paul Mundt @ 2011-01-25  7:48 UTC (permalink / raw)
  To: Heiko Schocher
  Cc: linuxppc-dev, linux-fbdev, devicetree-discuss, Ben Dooks,
	Vincent Sanders, Samuel Ortiz, linux-kernel, Randy Dunlap
In-Reply-To: <1295940031-28268-1-git-send-email-hs@denx.de>

On Tue, Jan 25, 2011 at 08:20:31AM +0100, Heiko Schocher wrote:
> @@ -1934,7 +1943,29 @@ static int __devinit sm501fb_probe(struct platform_device *pdev)
>  	}
>  
>  	if (info->pdata = NULL) {
> -		dev_info(dev, "using default configuration data\n");
> +		int found = 0;
> +#if defined(CONFIG_OF)
> +		struct device_node *np = pdev->dev.parent->of_node;
> +		const u8 *prop;
> +		const char *cp;
> +		int len;
> +
> +		info->pdata = &sm501fb_def_pdata;
> +		if (np) {
> +			/* Get EDID */
> +			cp = of_get_property(np, "mode", &len);
> +			if (cp)
> +				strcpy(fb_mode, cp);
> +			prop = of_get_property(np, "edid", &len);
> +			if (prop && len = EDID_LENGTH) {
> +				info->edid_data = kmemdup(prop, EDID_LENGTH,
> +							  GFP_KERNEL);
> +				found = 1;
> +			}
> +		}
> +#endif
> +		if (!found)
> +			dev_info(dev, "using default configuration data\n");
>  	}
>  
>  	/* probe for the presence of each panel */

Starting to get a bit pedantic.. but kmemdup() tries to do a kmalloc(),
and so can fail. Your other patches handle the info->edid_data = NULL
case, in addition to the kfree(), but you're probably going to want to
chomp that found assignment incase of the allocation failing and falling
back on the default mode.

You also don't really have any need to keep the EDID block around after
probe as far as I can tell, so you should be able to rework this in to
something more like:

	info->edid_data = kmemdup(..);
	...
	if (info->edid_data) {
		fb_edid_to_monspecs(..);
		kfree(info->edid_data);
		fb_videomode_to_modelist(..);
	}

	...

^ permalink raw reply

* [PATCH 3/4 v4] video, sm501: add OF binding to support SM501
From: Heiko Schocher @ 2011-01-25  7:20 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Heiko Schocher, linux-fbdev, devicetree-discuss, Ben Dooks,
	Vincent Sanders, Samuel Ortiz, linux-kernel, Randy Dunlap,
	Paul Mundt
In-Reply-To: <1291451028-22532-1-git-send-email-hs@denx.de>

- add binding to OF, compatible name "smi,sm501"

Signed-off-by: Heiko Schocher <hs@denx.de>
cc: linux-fbdev@vger.kernel.org
cc: devicetree-discuss@ozlabs.org
cc: Ben Dooks <ben@simtec.co.uk>
cc: Vincent Sanders <vince@simtec.co.uk>
cc: Samuel Ortiz <sameo@linux.intel.com>
cc: linux-kernel@vger.kernel.org
cc: Randy Dunlap <rdunlap@xenotime.net>
cc: Paul Mundt <lethal@linux-sh.org>

---
- changes since v1:
  add Ben Dooks, Vincent Sanders and Samuel Ortiz to cc, as suggested from
  Paul Mundt.
- changes since v2:
  add comments from Randy Dunlap:
  - move parameter documentation to Documentation/fb/sm501.txt
- changes since v3:
  - rebased against v2.6.38-rc2
  - split in 3 patches
    - of support patch
      - get rid of "#if defined(CONFIG_PPC_MPC52xx)" usage
        hide this in DTS, as Paul suggested.
    - i/o routine patch
    - edid support patch
- changes since v4
  replace remaining CONFIG_PPC_MPC52xx with CONFIG_OF, as
  it is no longer MPC52xx only.

./scripts/checkpatch.pl 0003-video-sm501-add-OF-binding-to-support-SM501.patch
total: 0 errors, 0 warnings, 117 lines checked

0003-video-sm501-add-OF-binding-to-support-SM501.patch has no obvious style problems and is ready for submission.

 Documentation/powerpc/dts-bindings/sm501.txt |   34 ++++++++++++++++++++++++++
 drivers/mfd/sm501.c                          |   16 +++++++++++-
 drivers/video/sm501fb.c                      |   33 ++++++++++++++++++++++++-
 3 files changed, 81 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/powerpc/dts-bindings/sm501.txt

diff --git a/Documentation/powerpc/dts-bindings/sm501.txt b/Documentation/powerpc/dts-bindings/sm501.txt
new file mode 100644
index 0000000..7d319fb
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/sm501.txt
@@ -0,0 +1,34 @@
+* SM SM501
+
+The SM SM501 is a LCD controller, with proper hardware, it can also
+drive DVI monitors.
+
+Required properties:
+- compatible : should be "smi,sm501".
+- reg : contain two entries:
+    - First entry: System Configuration register
+    - Second entry: IO space (Display Controller register)
+- interrupts : SMI interrupt to the cpu should be described here.
+- interrupt-parent : the phandle for the interrupt controller that
+  services interrupts for this device.
+
+Optional properties:
+- mode : select a video mode:
+    <xres>x<yres>[-<bpp>][@<refresh>]
+- edid : verbatim EDID data block describing attached display.
+  Data from the detailed timing descriptor will be used to
+  program the display controller.
+- little-endian: availiable on big endian systems, to
+  set different foreign endian.
+- big-endian: availiable on little endian systems, to
+  set different foreign endian.
+
+Example for MPC5200:
+	display@1,0 {
+		compatible = "smi,sm501";
+		reg = <1 0x00000000 0x00800000
+		       1 0x03e00000 0x00200000>;
+		interrupts = <1 1 3>;
+		mode = "640x480-32@60";
+		edid = [edid-data];
+	};
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 558d5f3..5b7a8f4 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -1377,7 +1377,7 @@ static int __devinit sm501_init_dev(struct sm501_devdata *sm)
 			sm501_register_gpio(sm);
 	}
 
-	if (pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) {
+	if (pdata && pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) {
 		if (!sm501_gpio_isregistered(sm))
 			dev_err(sm->dev, "no gpio available for i2c gpio.\n");
 		else
@@ -1422,6 +1422,14 @@ static int __devinit sm501_plat_probe(struct platform_device *dev)
 
 	sm->io_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
 	sm->mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+
+	if (sm->mem_res)
+		pr_debug("sm501 mem 0x%lx, 0x%lx\n",
+			 sm->mem_res->start, sm->mem_res->end);
+	if (sm->io_res)
+		pr_debug("sm501 io 0x%lx, 0x%lx\n",
+			 sm->io_res->start, sm->io_res->end);
+
 	if (sm->io_res = NULL || sm->mem_res = NULL) {
 		dev_err(&dev->dev, "failed to get IO resource\n");
 		ret = -ENOENT;
@@ -1735,10 +1743,16 @@ static struct pci_driver sm501_pci_driver = {
 
 MODULE_ALIAS("platform:sm501");
 
+static struct of_device_id __devinitdata of_sm501_match_tbl[] = {
+	{ .compatible = "smi,sm501", },
+	{ /* end */ }
+};
+
 static struct platform_driver sm501_plat_driver = {
 	.driver		= {
 		.name	= "sm501",
 		.owner	= THIS_MODULE,
+		.of_match_table = of_sm501_match_tbl,
 	},
 	.probe		= sm501_plat_probe,
 	.remove		= sm501_plat_remove,
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index 30b53ae..bbdb359 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -1729,6 +1729,15 @@ static int sm501fb_init_fb(struct fb_info *fb,
 		FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
 		FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
 
+#if defined(CONFIG_OF)
+#ifdef __BIG_ENDIAN
+	if (of_get_property(info->dev->parent->of_node, "little-endian", NULL))
+		fb->flags |= FBINFO_FOREIGN_ENDIAN;
+#else
+	if (of_get_property(info->dev->parent->of_node, "big-endian", NULL))
+		fb->flags |= FBINFO_FOREIGN_ENDIAN;
+#endif
+#endif
 	/* fixed data */
 
 	fb->fix.type		= FB_TYPE_PACKED_PIXELS;
@@ -1934,7 +1943,29 @@ static int __devinit sm501fb_probe(struct platform_device *pdev)
 	}
 
 	if (info->pdata = NULL) {
-		dev_info(dev, "using default configuration data\n");
+		int found = 0;
+#if defined(CONFIG_OF)
+		struct device_node *np = pdev->dev.parent->of_node;
+		const u8 *prop;
+		const char *cp;
+		int len;
+
+		info->pdata = &sm501fb_def_pdata;
+		if (np) {
+			/* Get EDID */
+			cp = of_get_property(np, "mode", &len);
+			if (cp)
+				strcpy(fb_mode, cp);
+			prop = of_get_property(np, "edid", &len);
+			if (prop && len = EDID_LENGTH) {
+				info->edid_data = kmemdup(prop, EDID_LENGTH,
+							  GFP_KERNEL);
+				found = 1;
+			}
+		}
+#endif
+		if (!found)
+			dev_info(dev, "using default configuration data\n");
 	}
 
 	/* probe for the presence of each panel */
-- 
1.7.3.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