* [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
* Re: [PATCH 4/4 v5] powerpc, video: add SM501 support for charon board.
From: Heiko Schocher @ 2011-01-25 7:07 UTC (permalink / raw)
To: Paul Mundt
Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, Samuel Ortiz,
Vincent Sanders, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Ben Dooks,
linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ
In-Reply-To: <20110125064949.GF11673-M7jkjyW5wf5g9hUCZPvPmw@public.gmane.org>
Hello Paul,
Paul Mundt wrote:
> On Tue, Jan 25, 2011 at 07:45:46AM +0100, Heiko Schocher wrote:
>> @@ -197,6 +198,15 @@
>> #address-cells = <1>;
>> };
>>
>> + display@1,0 {
>> + compatible = "smi,sm501";
>> + reg = <1 0x00000000 0x00800000
>> + 1 0x03e00000 0x00200000>;
>> + mode = "640x480-32@60";
>> + interrupts = <1 1 3>;
>> + little-endian;
>> + };
>> +
>
> The endian designation looks good, but it still doesn't explain why you
> have a remaining CONFIG_PPC_MPC52xx ifdef encapsulating the property
> check in the sm501fb patch. It shouldn't be needed at all. If the
> platform supports OF then the property will need to be set one way or the
> other, so there is no need for any board or CPU ifdeffery within the
> driver itself.
Argh, of course you are right, thanks! I post an update for the
"sm501fb of support" patch.
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 V2] video: fix some comments in drivers/video/console/vgacon.c
From: Paul Mundt @ 2011-01-25 7:03 UTC (permalink / raw)
To: Amerigo Wang
Cc: linux-kernel, Arnd Bergmann, Andrew Morton, Greg Kroah-Hartman,
Yannick Heneault, Matthew Garrett, linux-fbdev
In-Reply-To: <1295418242-19859-1-git-send-email-amwang@redhat.com>
On Wed, Jan 19, 2011 at 02:24:02PM +0800, Amerigo Wang wrote:
> Now vgacon_scrollback_startup() uses slab, not bootmem,
> the comment above it is obsolete, so does __init_refok.
>
> Signed-off-by: WANG Cong <amwang@redhat.com>
>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH 4/4 v5] powerpc, video: add SM501 support for charon board.
From: Paul Mundt @ 2011-01-25 6:49 UTC (permalink / raw)
To: Heiko Schocher
Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, Samuel Ortiz,
Vincent Sanders, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Ben Dooks,
linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ
In-Reply-To: <1295937946-26934-1-git-send-email-hs-ynQEQJNshbs@public.gmane.org>
On Tue, Jan 25, 2011 at 07:45:46AM +0100, Heiko Schocher wrote:
> @@ -197,6 +198,15 @@
> #address-cells = <1>;
> };
>
> + display@1,0 {
> + compatible = "smi,sm501";
> + reg = <1 0x00000000 0x00800000
> + 1 0x03e00000 0x00200000>;
> + mode = "640x480-32@60";
> + interrupts = <1 1 3>;
> + little-endian;
> + };
> +
The endian designation looks good, but it still doesn't explain why you
have a remaining CONFIG_PPC_MPC52xx ifdef encapsulating the property
check in the sm501fb patch. It shouldn't be needed at all. If the
platform supports OF then the property will need to be set one way or the
other, so there is no need for any board or CPU ifdeffery within the
driver itself.
^ permalink raw reply
* [PATCH 4/4 v5] powerpc, video: add SM501 support for charon board.
From: Heiko Schocher @ 2011-01-25 6:45 UTC (permalink / raw)
To: linuxppc-dev
Cc: linux-fbdev, devicetree-discuss, Samuel Ortiz, Vincent Sanders,
linux-kernel, Ben Dooks, Paul Mundt, Heiko Schocher
In-Reply-To: <1291451028-22532-2-git-send-email-hs@denx.de>
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: Paul Mundt <lethal@linux-sh.org>
---
- changes since v1:
- no board specific defconfig file for mpc52xx based boards as suggested
from Wolfram Sang
- changes since v2:
add Ben Dooks, Vincent Sanders and Samuel Ortiz and lkml to cc, as
suggested from Paul Mundt.
- changes since v3:
- rebased against v2.6.38-rc2
- changes since v4:
- added Paul Mundt to cc (Sorry forgot this in series v4)
./scripts/checkpatch.pl 0004-powerpc-video-add-SM501-support-for-charon-board.patch
total: 0 errors, 0 warnings, 22 lines checked
0004-powerpc-video-add-SM501-support-for-charon-board.patch has no obvious style problems and is ready for submission.
arch/powerpc/boot/dts/charon.dts | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/boot/dts/charon.dts b/arch/powerpc/boot/dts/charon.dts
index 9776889..0e00e50 100644
--- a/arch/powerpc/boot/dts/charon.dts
+++ b/arch/powerpc/boot/dts/charon.dts
@@ -186,6 +186,7 @@
#address-cells = <2>;
#size-cells = <1>;
ranges = < 0 0 0xfc000000 0x02000000
+ 1 0 0xe0000000 0x04000000 // CS1 range, SM501
3 0 0xe8000000 0x00080000>;
flash@0,0 {
@@ -197,6 +198,15 @@
#address-cells = <1>;
};
+ display@1,0 {
+ compatible = "smi,sm501";
+ reg = <1 0x00000000 0x00800000
+ 1 0x03e00000 0x00200000>;
+ mode = "640x480-32@60";
+ interrupts = <1 1 3>;
+ little-endian;
+ };
+
mram0@3,0 {
compatible = "mtd-ram";
reg = <3 0x00000 0x80000>;
--
1.7.3.4
^ permalink raw reply related
* Re: [PATCH 3/4 v4] video, sm501: add OF binding to support SM501
From: Paul Mundt @ 2011-01-25 6:38 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: <1295863058-11168-1-git-send-email-hs@denx.de>
On Mon, Jan 24, 2011 at 10:57:38AM +0100, Heiko Schocher wrote:
> - 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
>
[snip]
> diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
> index 30b53ae..2ae57aa 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_PPC_MPC52xx)
> +#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;
Missed one?
^ permalink raw reply
* Re: [PATCH 3/4] drivers/video/bf537-lq035.c: Add missing IS_ERR test
From: Paul Mundt @ 2011-01-25 6:12 UTC (permalink / raw)
To: Mike Frysinger
Cc: Julia Lawall, kernel-janitors, Michael Hennerich, Bryan Wu,
linux-fbdev, linux-kernel
In-Reply-To: <201101241543.19543.vapier@gentoo.org>
On Mon, Jan 24, 2011 at 03:43:17PM -0500, Mike Frysinger wrote:
> On Monday, January 24, 2011 14:55:21 Julia Lawall wrote:
> > 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.
>
> Acked-by: Mike Frysinger <vapier@gentoo.org>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH] video: da8xx-fb: fix fb_probe error path
From: Paul Mundt @ 2011-01-25 6:11 UTC (permalink / raw)
To: Axel Lin
Cc: linux-kernel, linux-fbdev, Sudhakar Rajashekhara,
Lennert Buytenhek, Green Wan, Eric Miao, Marek Vasut,
Haojian Zhuang
In-Reply-To: <1295495451.20884.3.camel@mola>
On Thu, Jan 20, 2011 at 11:50:51AM +0800, Axel Lin wrote:
> Current implementation puts CONFIG_CPU_FREQ at wrong place, CONFIG_CPU_FREQ
> is for lcd_da8xx_cpufreq_deregister not for unregister_framebuffer.
On Fri, Jan 21, 2011 at 07:18:06PM +0800, Axel Lin wrote:
> Current implementation calls pxa168fb_check_var twice in pxa168fb_probe.
Both applied, thanks.
^ permalink raw reply
* Re: [PATCH 3/4] drivers/video/bf537-lq035.c: Add missing IS_ERR test
From: Mike Frysinger @ 2011-01-24 20:43 UTC (permalink / raw)
To: Julia Lawall
Cc: Paul Mundt, kernel-janitors, Michael Hennerich, Bryan Wu,
linux-fbdev, linux-kernel
In-Reply-To: <1295898922-18822-4-git-send-email-julia@diku.dk>
[-- Attachment #1: Type: Text/Plain, Size: 578 bytes --]
On Monday, January 24, 2011 14:55:21 Julia Lawall wrote:
> 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.
Acked-by: Mike Frysinger <vapier@gentoo.org>
-mike
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* [PATCH 3/4] drivers/video/bf537-lq035.c: Add missing IS_ERR test
From: Julia Lawall @ 2011-01-24 19:55 UTC (permalink / raw)
To: Paul Mundt
Cc: kernel-janitors, Mike Frysinger, Michael Hennerich, Bryan Wu,
linux-fbdev, linux-kernel
In-Reply-To: <1295898922-18822-1-git-send-email-julia@diku.dk>
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>
---
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)
^ permalink raw reply related
* [PATCH 4/4 v4] powerpc, video: add SM501 support for charon board.
From: Heiko Schocher @ 2011-01-24 9:57 UTC (permalink / raw)
To: linuxppc-dev
Cc: Heiko Schocher, linux-fbdev, devicetree-discuss, Ben Dooks,
Vincent Sanders, Samuel Ortiz, linux-kernel
In-Reply-To: <1291451028-22532-2-git-send-email-hs@denx.de>
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
---
- changes since v1:
- no board specific defconfig file for mpc52xx based boards as suggested
from Wolfram Sang
- changes since v2:
add Ben Dooks, Vincent Sanders and Samuel Ortiz and lkml to cc, as
suggested from Paul Mundt.
- changes since v3:
- rebased against v2.6.38-rc2
./scripts/checkpatch.pl 0004-powerpc-video-add-SM501-support-for-charon-board.patch
total: 0 errors, 0 warnings, 22 lines checked
0004-powerpc-video-add-SM501-support-for-charon-board.patch has no obvious style problems and is ready for submission.
arch/powerpc/boot/dts/charon.dts | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/boot/dts/charon.dts b/arch/powerpc/boot/dts/charon.dts
index 9776889..0e00e50 100644
--- a/arch/powerpc/boot/dts/charon.dts
+++ b/arch/powerpc/boot/dts/charon.dts
@@ -186,6 +186,7 @@
#address-cells = <2>;
#size-cells = <1>;
ranges = < 0 0 0xfc000000 0x02000000
+ 1 0 0xe0000000 0x04000000 // CS1 range, SM501
3 0 0xe8000000 0x00080000>;
flash@0,0 {
@@ -197,6 +198,15 @@
#address-cells = <1>;
};
+ display@1,0 {
+ compatible = "smi,sm501";
+ reg = <1 0x00000000 0x00800000
+ 1 0x03e00000 0x00200000>;
+ mode = "640x480-32@60";
+ interrupts = <1 1 3>;
+ little-endian;
+ };
+
mram0@3,0 {
compatible = "mtd-ram";
reg = <3 0x00000 0x80000>;
--
1.7.3.4
^ permalink raw reply related
* [PATCH 3/4 v4] video, sm501: add OF binding to support SM501
From: Heiko Schocher @ 2011-01-24 9:57 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
./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..2ae57aa 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_PPC_MPC52xx)
+#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
* [PATCH 2/4 v4] video, sm501: add edid and commandline support
From: Heiko Schocher @ 2011-01-24 9:57 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
./scripts/checkpatch.pl 0002-video-sm501-add-edid-and-commandline-support.patch
total: 0 errors, 0 warnings, 123 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 | 67 ++++++++++++++++++++++++++++++++++++++++----
2 files changed, 71 insertions(+), 6 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..30b53ae 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;
}
}
@@ -1827,6 +1877,7 @@ static void sm501_free_init_fb(struct sm501fb_info *info,
{
struct fb_info *fbi = info->fb[head];
+ kfree(info->edid_data);
fb_dealloc_cmap(&fbi->cmap);
}
@@ -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 */
@@ -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
* [PATCH 1/4 v4] video, sm501: add I/O functions for use on powerpc
From: Heiko Schocher @ 2011-01-24 9:57 UTC (permalink / raw)
To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ
Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, Samuel Ortiz,
Vincent Sanders, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Ben Dooks,
Randy Dunlap, Paul Mundt, Heiko Schocher
In-Reply-To: <1291451028-22532-1-git-send-email-hs-ynQEQJNshbs@public.gmane.org>
- add read/write functions for using this driver
also on powerpc plattforms
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
- use ioread/write32{be} accessors instead of
__do_readl/__do_writel{_be}
- edid support patch
./scripts/checkpatch.pl 0001-video-sm501-add-I-O-functions-for-use-on-powerpc.patch
total: 0 errors, 0 warnings, 841 lines checked
0001-video-sm501-add-I-O-functions-for-use-on-powerpc.patch has no obvious style problems and is ready for submission.
drivers/mfd/sm501.c | 125 +++++++++++++++++-----------------
drivers/video/sm501fb.c | 172 ++++++++++++++++++++++++----------------------
include/linux/sm501.h | 8 ++
3 files changed, 161 insertions(+), 144 deletions(-)
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 5de3a76..558d5f3 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -133,10 +133,10 @@ static unsigned long decode_div(unsigned long pll2, unsigned long val,
static void sm501_dump_clk(struct sm501_devdata *sm)
{
- unsigned long misct = readl(sm->regs + SM501_MISC_TIMING);
- unsigned long pm0 = readl(sm->regs + SM501_POWER_MODE_0_CLOCK);
- unsigned long pm1 = readl(sm->regs + SM501_POWER_MODE_1_CLOCK);
- unsigned long pmc = readl(sm->regs + SM501_POWER_MODE_CONTROL);
+ unsigned long misct = smc501_readl(sm->regs + SM501_MISC_TIMING);
+ unsigned long pm0 = smc501_readl(sm->regs + SM501_POWER_MODE_0_CLOCK);
+ unsigned long pm1 = smc501_readl(sm->regs + SM501_POWER_MODE_1_CLOCK);
+ unsigned long pmc = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL);
unsigned long sdclk0, sdclk1;
unsigned long pll2 = 0;
@@ -193,29 +193,29 @@ static void sm501_dump_regs(struct sm501_devdata *sm)
void __iomem *regs = sm->regs;
dev_info(sm->dev, "System Control %08x\n",
- readl(regs + SM501_SYSTEM_CONTROL));
+ smc501_readl(regs + SM501_SYSTEM_CONTROL));
dev_info(sm->dev, "Misc Control %08x\n",
- readl(regs + SM501_MISC_CONTROL));
+ smc501_readl(regs + SM501_MISC_CONTROL));
dev_info(sm->dev, "GPIO Control Low %08x\n",
- readl(regs + SM501_GPIO31_0_CONTROL));
+ smc501_readl(regs + SM501_GPIO31_0_CONTROL));
dev_info(sm->dev, "GPIO Control Hi %08x\n",
- readl(regs + SM501_GPIO63_32_CONTROL));
+ smc501_readl(regs + SM501_GPIO63_32_CONTROL));
dev_info(sm->dev, "DRAM Control %08x\n",
- readl(regs + SM501_DRAM_CONTROL));
+ smc501_readl(regs + SM501_DRAM_CONTROL));
dev_info(sm->dev, "Arbitration Ctrl %08x\n",
- readl(regs + SM501_ARBTRTN_CONTROL));
+ smc501_readl(regs + SM501_ARBTRTN_CONTROL));
dev_info(sm->dev, "Misc Timing %08x\n",
- readl(regs + SM501_MISC_TIMING));
+ smc501_readl(regs + SM501_MISC_TIMING));
}
static void sm501_dump_gate(struct sm501_devdata *sm)
{
dev_info(sm->dev, "CurrentGate %08x\n",
- readl(sm->regs + SM501_CURRENT_GATE));
+ smc501_readl(sm->regs + SM501_CURRENT_GATE));
dev_info(sm->dev, "CurrentClock %08x\n",
- readl(sm->regs + SM501_CURRENT_CLOCK));
+ smc501_readl(sm->regs + SM501_CURRENT_CLOCK));
dev_info(sm->dev, "PowerModeControl %08x\n",
- readl(sm->regs + SM501_POWER_MODE_CONTROL));
+ smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL));
}
#else
@@ -231,7 +231,7 @@ static inline void sm501_dump_clk(struct sm501_devdata *sm) { }
static void sm501_sync_regs(struct sm501_devdata *sm)
{
- readl(sm->regs);
+ smc501_readl(sm->regs);
}
static inline void sm501_mdelay(struct sm501_devdata *sm, unsigned int delay)
@@ -261,11 +261,11 @@ int sm501_misc_control(struct device *dev,
spin_lock_irqsave(&sm->reg_lock, save);
- misc = readl(sm->regs + SM501_MISC_CONTROL);
+ misc = smc501_readl(sm->regs + SM501_MISC_CONTROL);
to = (misc & ~clear) | set;
if (to != misc) {
- writel(to, sm->regs + SM501_MISC_CONTROL);
+ smc501_writel(to, sm->regs + SM501_MISC_CONTROL);
sm501_sync_regs(sm);
dev_dbg(sm->dev, "MISC_CONTROL %08lx\n", misc);
@@ -294,11 +294,11 @@ unsigned long sm501_modify_reg(struct device *dev,
spin_lock_irqsave(&sm->reg_lock, save);
- data = readl(sm->regs + reg);
+ data = smc501_readl(sm->regs + reg);
data |= set;
data &= ~clear;
- writel(data, sm->regs + reg);
+ smc501_writel(data, sm->regs + reg);
sm501_sync_regs(sm);
spin_unlock_irqrestore(&sm->reg_lock, save);
@@ -322,9 +322,9 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
mutex_lock(&sm->clock_lock);
- mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
- gate = readl(sm->regs + SM501_CURRENT_GATE);
- clock = readl(sm->regs + SM501_CURRENT_CLOCK);
+ mode = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL);
+ gate = smc501_readl(sm->regs + SM501_CURRENT_GATE);
+ clock = smc501_readl(sm->regs + SM501_CURRENT_CLOCK);
mode &= 3; /* get current power mode */
@@ -356,14 +356,14 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
switch (mode) {
case 1:
- writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
- writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
+ smc501_writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
+ smc501_writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
mode = 0;
break;
case 2:
case 0:
- writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
- writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
+ smc501_writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
+ smc501_writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
mode = 1;
break;
@@ -372,7 +372,7 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
goto already;
}
- writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
+ smc501_writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
sm501_sync_regs(sm);
dev_dbg(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
@@ -519,9 +519,9 @@ unsigned long sm501_set_clock(struct device *dev,
unsigned long req_freq)
{
struct sm501_devdata *sm = dev_get_drvdata(dev);
- unsigned long mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
- unsigned long gate = readl(sm->regs + SM501_CURRENT_GATE);
- unsigned long clock = readl(sm->regs + SM501_CURRENT_CLOCK);
+ unsigned long mode = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL);
+ unsigned long gate = smc501_readl(sm->regs + SM501_CURRENT_GATE);
+ unsigned long clock = smc501_readl(sm->regs + SM501_CURRENT_CLOCK);
unsigned char reg;
unsigned int pll_reg = 0;
unsigned long sm501_freq; /* the actual frequency achieved */
@@ -592,9 +592,9 @@ unsigned long sm501_set_clock(struct device *dev,
mutex_lock(&sm->clock_lock);
- mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
- gate = readl(sm->regs + SM501_CURRENT_GATE);
- clock = readl(sm->regs + SM501_CURRENT_CLOCK);
+ mode = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL);
+ gate = smc501_readl(sm->regs + SM501_CURRENT_GATE);
+ clock = smc501_readl(sm->regs + SM501_CURRENT_CLOCK);
clock = clock & ~(0xFF << clksrc);
clock |= reg<<clksrc;
@@ -603,14 +603,14 @@ unsigned long sm501_set_clock(struct device *dev,
switch (mode) {
case 1:
- writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
- writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
+ smc501_writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
+ smc501_writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
mode = 0;
break;
case 2:
case 0:
- writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
- writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
+ smc501_writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
+ smc501_writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
mode = 1;
break;
@@ -619,10 +619,11 @@ unsigned long sm501_set_clock(struct device *dev,
return -1;
}
- writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
+ smc501_writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
if (pll_reg)
- writel(pll_reg, sm->regs + SM501_PROGRAMMABLE_PLL_CONTROL);
+ smc501_writel(pll_reg,
+ sm->regs + SM501_PROGRAMMABLE_PLL_CONTROL);
sm501_sync_regs(sm);
@@ -902,7 +903,7 @@ static int sm501_gpio_get(struct gpio_chip *chip, unsigned offset)
struct sm501_gpio_chip *smgpio = to_sm501_gpio(chip);
unsigned long result;
- result = readl(smgpio->regbase + SM501_GPIO_DATA_LOW);
+ result = smc501_readl(smgpio->regbase + SM501_GPIO_DATA_LOW);
result >>= offset;
return result & 1UL;
@@ -915,13 +916,13 @@ static void sm501_gpio_ensure_gpio(struct sm501_gpio_chip *smchip,
/* check and modify if this pin is not set as gpio. */
- if (readl(smchip->control) & bit) {
+ if (smc501_readl(smchip->control) & bit) {
dev_info(sm501_gpio_to_dev(smchip->ourgpio)->dev,
"changing mode of gpio, bit %08lx\n", bit);
- ctrl = readl(smchip->control);
+ ctrl = smc501_readl(smchip->control);
ctrl &= ~bit;
- writel(ctrl, smchip->control);
+ smc501_writel(ctrl, smchip->control);
sm501_sync_regs(sm501_gpio_to_dev(smchip->ourgpio));
}
@@ -942,10 +943,10 @@ static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
spin_lock_irqsave(&smgpio->lock, save);
- val = readl(regs + SM501_GPIO_DATA_LOW) & ~bit;
+ val = smc501_readl(regs + SM501_GPIO_DATA_LOW) & ~bit;
if (value)
val |= bit;
- writel(val, regs);
+ smc501_writel(val, regs);
sm501_sync_regs(sm501_gpio_to_dev(smgpio));
sm501_gpio_ensure_gpio(smchip, bit);
@@ -967,8 +968,8 @@ static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset)
spin_lock_irqsave(&smgpio->lock, save);
- ddr = readl(regs + SM501_GPIO_DDR_LOW);
- writel(ddr & ~bit, regs + SM501_GPIO_DDR_LOW);
+ ddr = smc501_readl(regs + SM501_GPIO_DDR_LOW);
+ smc501_writel(ddr & ~bit, regs + SM501_GPIO_DDR_LOW);
sm501_sync_regs(sm501_gpio_to_dev(smgpio));
sm501_gpio_ensure_gpio(smchip, bit);
@@ -994,18 +995,18 @@ static int sm501_gpio_output(struct gpio_chip *chip,
spin_lock_irqsave(&smgpio->lock, save);
- val = readl(regs + SM501_GPIO_DATA_LOW);
+ val = smc501_readl(regs + SM501_GPIO_DATA_LOW);
if (value)
val |= bit;
else
val &= ~bit;
- writel(val, regs);
+ smc501_writel(val, regs);
- ddr = readl(regs + SM501_GPIO_DDR_LOW);
- writel(ddr | bit, regs + SM501_GPIO_DDR_LOW);
+ ddr = smc501_readl(regs + SM501_GPIO_DDR_LOW);
+ smc501_writel(ddr | bit, regs + SM501_GPIO_DDR_LOW);
sm501_sync_regs(sm501_gpio_to_dev(smgpio));
- writel(val, regs + SM501_GPIO_DATA_LOW);
+ smc501_writel(val, regs + SM501_GPIO_DATA_LOW);
sm501_sync_regs(sm501_gpio_to_dev(smgpio));
spin_unlock_irqrestore(&smgpio->lock, save);
@@ -1231,7 +1232,7 @@ static ssize_t sm501_dbg_regs(struct device *dev,
for (reg = 0x00; reg < 0x70; reg += 4) {
ret = sprintf(ptr, "%08x = %08x\n",
- reg, readl(sm->regs + reg));
+ reg, smc501_readl(sm->regs + reg));
ptr += ret;
}
@@ -1255,10 +1256,10 @@ static inline void sm501_init_reg(struct sm501_devdata *sm,
{
unsigned long tmp;
- tmp = readl(sm->regs + reg);
+ tmp = smc501_readl(sm->regs + reg);
tmp &= ~r->mask;
tmp |= r->set;
- writel(tmp, sm->regs + reg);
+ smc501_writel(tmp, sm->regs + reg);
}
/* sm501_init_regs
@@ -1299,7 +1300,7 @@ static void sm501_init_regs(struct sm501_devdata *sm,
static int sm501_check_clocks(struct sm501_devdata *sm)
{
- unsigned long pwrmode = readl(sm->regs + SM501_CURRENT_CLOCK);
+ unsigned long pwrmode = smc501_readl(sm->regs + SM501_CURRENT_CLOCK);
unsigned long msrc = (pwrmode & SM501_POWERMODE_M_SRC);
unsigned long m1src = (pwrmode & SM501_POWERMODE_M1_SRC);
@@ -1334,7 +1335,7 @@ static int __devinit sm501_init_dev(struct sm501_devdata *sm)
INIT_LIST_HEAD(&sm->devices);
- devid = readl(sm->regs + SM501_DEVICEID);
+ devid = smc501_readl(sm->regs + SM501_DEVICEID);
if ((devid & SM501_DEVICEID_IDMASK) != SM501_DEVICEID_SM501) {
dev_err(sm->dev, "incorrect device id %08lx\n", devid);
@@ -1342,9 +1343,9 @@ static int __devinit sm501_init_dev(struct sm501_devdata *sm)
}
/* disable irqs */
- writel(0, sm->regs + SM501_IRQ_MASK);
+ smc501_writel(0, sm->regs + SM501_IRQ_MASK);
- dramctrl = readl(sm->regs + SM501_DRAM_CONTROL);
+ dramctrl = smc501_readl(sm->regs + SM501_DRAM_CONTROL);
mem_avail = sm501_mem_local[(dramctrl >> 13) & 0x7];
dev_info(sm->dev, "SM501 At %p: Version %08lx, %ld Mb, IRQ %d\n",
@@ -1489,7 +1490,7 @@ static int sm501_plat_suspend(struct platform_device *pdev, pm_message_t state)
struct sm501_devdata *sm = platform_get_drvdata(pdev);
sm->in_suspend = 1;
- sm->pm_misc = readl(sm->regs + SM501_MISC_CONTROL);
+ sm->pm_misc = smc501_readl(sm->regs + SM501_MISC_CONTROL);
sm501_dump_regs(sm);
@@ -1513,9 +1514,9 @@ static int sm501_plat_resume(struct platform_device *pdev)
/* check to see if we are in the same state as when suspended */
- if (readl(sm->regs + SM501_MISC_CONTROL) != sm->pm_misc) {
+ if (smc501_readl(sm->regs + SM501_MISC_CONTROL) != sm->pm_misc) {
dev_info(sm->dev, "SM501_MISC_CONTROL changed over sleep\n");
- writel(sm->pm_misc, sm->regs + SM501_MISC_CONTROL);
+ smc501_writel(sm->pm_misc, sm->regs + SM501_MISC_CONTROL);
/* our suspend causes the controller state to change,
* either by something attempting setup, power loss,
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index b7dc180..c5b4b95 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -117,7 +117,7 @@ static inline int v_total(struct fb_var_screeninfo *var)
static inline void sm501fb_sync_regs(struct sm501fb_info *info)
{
- readl(info->regs);
+ smc501_readl(info->regs);
}
/* sm501_alloc_mem
@@ -262,7 +262,7 @@ static void sm501fb_setup_gamma(struct sm501fb_info *fbi,
/* set gamma values */
for (offset = 0; offset < 256 * 4; offset += 4) {
- writel(value, fbi->regs + palette + offset);
+ smc501_writel(value, fbi->regs + palette + offset);
value += 0x010101; /* Advance RGB by 1,1,1.*/
}
}
@@ -476,7 +476,8 @@ static int sm501fb_set_par_common(struct fb_info *info,
/* set start of framebuffer to the screen */
- writel(par->screen.sm_addr | SM501_ADDR_FLIP, fbi->regs + head_addr);
+ smc501_writel(par->screen.sm_addr | SM501_ADDR_FLIP,
+ fbi->regs + head_addr);
/* program CRT clock */
@@ -519,7 +520,7 @@ static void sm501fb_set_par_geometry(struct fb_info *info,
reg = info->fix.line_length;
reg |= ((var->xres * var->bits_per_pixel)/8) << 16;
- writel(reg, fbi->regs + (par->head = HEAD_CRT ?
+ smc501_writel(reg, fbi->regs + (par->head = HEAD_CRT ?
SM501_DC_CRT_FB_OFFSET : SM501_DC_PANEL_FB_OFFSET));
/* program horizontal total */
@@ -527,27 +528,27 @@ static void sm501fb_set_par_geometry(struct fb_info *info,
reg = (h_total(var) - 1) << 16;
reg |= (var->xres - 1);
- writel(reg, base + SM501_OFF_DC_H_TOT);
+ smc501_writel(reg, base + SM501_OFF_DC_H_TOT);
/* program horizontal sync */
reg = var->hsync_len << 16;
reg |= var->xres + var->right_margin - 1;
- writel(reg, base + SM501_OFF_DC_H_SYNC);
+ smc501_writel(reg, base + SM501_OFF_DC_H_SYNC);
/* program vertical total */
reg = (v_total(var) - 1) << 16;
reg |= (var->yres - 1);
- writel(reg, base + SM501_OFF_DC_V_TOT);
+ smc501_writel(reg, base + SM501_OFF_DC_V_TOT);
/* program vertical sync */
reg = var->vsync_len << 16;
reg |= var->yres + var->lower_margin - 1;
- writel(reg, base + SM501_OFF_DC_V_SYNC);
+ smc501_writel(reg, base + SM501_OFF_DC_V_SYNC);
}
/* sm501fb_pan_crt
@@ -566,15 +567,15 @@ static int sm501fb_pan_crt(struct fb_var_screeninfo *var,
xoffs = var->xoffset * bytes_pixel;
- reg = readl(fbi->regs + SM501_DC_CRT_CONTROL);
+ reg = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL);
reg &= ~SM501_DC_CRT_CONTROL_PIXEL_MASK;
reg |= ((xoffs & 15) / bytes_pixel) << 4;
- writel(reg, fbi->regs + SM501_DC_CRT_CONTROL);
+ smc501_writel(reg, fbi->regs + SM501_DC_CRT_CONTROL);
reg = (par->screen.sm_addr + xoffs +
var->yoffset * info->fix.line_length);
- writel(reg | SM501_ADDR_FLIP, fbi->regs + SM501_DC_CRT_FB_ADDR);
+ smc501_writel(reg | SM501_ADDR_FLIP, fbi->regs + SM501_DC_CRT_FB_ADDR);
sm501fb_sync_regs(fbi);
return 0;
@@ -593,10 +594,10 @@ static int sm501fb_pan_pnl(struct fb_var_screeninfo *var,
unsigned long reg;
reg = var->xoffset | (var->xres_virtual << 16);
- writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH);
+ smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH);
reg = var->yoffset | (var->yres_virtual << 16);
- writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT);
+ smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT);
sm501fb_sync_regs(fbi);
return 0;
@@ -622,7 +623,7 @@ static int sm501fb_set_par_crt(struct fb_info *info)
/* enable CRT DAC - note 0 is on!*/
sm501_misc_control(fbi->dev->parent, 0, SM501_MISC_DAC_POWER);
- control = readl(fbi->regs + SM501_DC_CRT_CONTROL);
+ control = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL);
control &= (SM501_DC_CRT_CONTROL_PIXEL_MASK |
SM501_DC_CRT_CONTROL_GAMMA |
@@ -684,7 +685,7 @@ static int sm501fb_set_par_crt(struct fb_info *info)
out_update:
dev_dbg(fbi->dev, "new control is %08lx\n", control);
- writel(control, fbi->regs + SM501_DC_CRT_CONTROL);
+ smc501_writel(control, fbi->regs + SM501_DC_CRT_CONTROL);
sm501fb_sync_regs(fbi);
return 0;
@@ -696,18 +697,18 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL;
struct sm501_platdata_fbsub *pd = fbi->pdata->fb_pnl;
- control = readl(ctrl_reg);
+ control = smc501_readl(ctrl_reg);
if (to && (control & SM501_DC_PANEL_CONTROL_VDD) = 0) {
/* enable panel power */
control |= SM501_DC_PANEL_CONTROL_VDD; /* FPVDDEN */
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
control |= SM501_DC_PANEL_CONTROL_DATA; /* DATA */
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
@@ -719,7 +720,7 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
else
control |= SM501_DC_PANEL_CONTROL_BIAS;
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
}
@@ -730,7 +731,7 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
else
control |= SM501_DC_PANEL_CONTROL_FPEN;
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
}
@@ -742,7 +743,7 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
else
control &= ~SM501_DC_PANEL_CONTROL_FPEN;
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
}
@@ -753,18 +754,18 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
else
control &= ~SM501_DC_PANEL_CONTROL_BIAS;
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
}
control &= ~SM501_DC_PANEL_CONTROL_DATA;
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
control &= ~SM501_DC_PANEL_CONTROL_VDD;
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
}
@@ -799,7 +800,7 @@ static int sm501fb_set_par_pnl(struct fb_info *info)
/* update control register */
- control = readl(fbi->regs + SM501_DC_PANEL_CONTROL);
+ control = smc501_readl(fbi->regs + SM501_DC_PANEL_CONTROL);
control &= (SM501_DC_PANEL_CONTROL_GAMMA |
SM501_DC_PANEL_CONTROL_VDD |
SM501_DC_PANEL_CONTROL_DATA |
@@ -833,16 +834,16 @@ static int sm501fb_set_par_pnl(struct fb_info *info)
BUG();
}
- writel(0x0, fbi->regs + SM501_DC_PANEL_PANNING_CONTROL);
+ smc501_writel(0x0, fbi->regs + SM501_DC_PANEL_PANNING_CONTROL);
/* panel plane top left and bottom right location */
- writel(0x00, fbi->regs + SM501_DC_PANEL_TL_LOC);
+ smc501_writel(0x00, fbi->regs + SM501_DC_PANEL_TL_LOC);
reg = var->xres - 1;
reg |= (var->yres - 1) << 16;
- writel(reg, fbi->regs + SM501_DC_PANEL_BR_LOC);
+ smc501_writel(reg, fbi->regs + SM501_DC_PANEL_BR_LOC);
/* program panel control register */
@@ -855,7 +856,7 @@ static int sm501fb_set_par_pnl(struct fb_info *info)
if ((var->sync & FB_SYNC_VERT_HIGH_ACT) = 0)
control |= SM501_DC_PANEL_CONTROL_VSP;
- writel(control, fbi->regs + SM501_DC_PANEL_CONTROL);
+ smc501_writel(control, fbi->regs + SM501_DC_PANEL_CONTROL);
sm501fb_sync_regs(fbi);
/* ensure the panel interface is not tristated at this point */
@@ -924,7 +925,7 @@ static int sm501fb_setcolreg(unsigned regno,
val |= (green >> 8) << 8;
val |= blue >> 8;
- writel(val, base + (regno * 4));
+ smc501_writel(val, base + (regno * 4));
}
break;
@@ -980,7 +981,7 @@ static int sm501fb_blank_crt(int blank_mode, struct fb_info *info)
dev_dbg(fbi->dev, "%s(mode=%d, %p)\n", __func__, blank_mode, info);
- ctrl = readl(fbi->regs + SM501_DC_CRT_CONTROL);
+ ctrl = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL);
switch (blank_mode) {
case FB_BLANK_POWERDOWN:
@@ -1004,7 +1005,7 @@ static int sm501fb_blank_crt(int blank_mode, struct fb_info *info)
}
- writel(ctrl, fbi->regs + SM501_DC_CRT_CONTROL);
+ smc501_writel(ctrl, fbi->regs + SM501_DC_CRT_CONTROL);
sm501fb_sync_regs(fbi);
return 0;
@@ -1041,12 +1042,14 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
if (cursor->image.depth > 1)
return -EINVAL;
- hwc_addr = readl(base + SM501_OFF_HWC_ADDR);
+ hwc_addr = smc501_readl(base + SM501_OFF_HWC_ADDR);
if (cursor->enable)
- writel(hwc_addr | SM501_HWC_EN, base + SM501_OFF_HWC_ADDR);
+ smc501_writel(hwc_addr | SM501_HWC_EN,
+ base + SM501_OFF_HWC_ADDR);
else
- writel(hwc_addr & ~SM501_HWC_EN, base + SM501_OFF_HWC_ADDR);
+ smc501_writel(hwc_addr & ~SM501_HWC_EN,
+ base + SM501_OFF_HWC_ADDR);
/* set data */
if (cursor->set & FB_CUR_SETPOS) {
@@ -1060,7 +1063,7 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
//y += cursor->image.height;
- writel(x | (y << 16), base + SM501_OFF_HWC_LOC);
+ smc501_writel(x | (y << 16), base + SM501_OFF_HWC_LOC);
}
if (cursor->set & FB_CUR_SETCMAP) {
@@ -1080,8 +1083,8 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
dev_dbg(fbi->dev, "fgcol %08lx, bgcol %08lx\n", fg, bg);
- writel(bg, base + SM501_OFF_HWC_COLOR_1_2);
- writel(fg, base + SM501_OFF_HWC_COLOR_3);
+ smc501_writel(bg, base + SM501_OFF_HWC_COLOR_1_2);
+ smc501_writel(fg, base + SM501_OFF_HWC_COLOR_3);
}
if (cursor->set & FB_CUR_SETSIZE ||
@@ -1102,7 +1105,7 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
__func__, cursor->image.width, cursor->image.height);
for (op = 0; op < (64*64*2)/8; op+=4)
- writel(0x0, dst + op);
+ smc501_writel(0x0, dst + op);
for (y = 0; y < cursor->image.height; y++) {
for (x = 0; x < cursor->image.width; x++) {
@@ -1141,7 +1144,7 @@ static ssize_t sm501fb_crtsrc_show(struct device *dev,
struct sm501fb_info *info = dev_get_drvdata(dev);
unsigned long ctrl;
- ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+ ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
ctrl &= SM501_DC_CRT_CONTROL_SEL;
return snprintf(buf, PAGE_SIZE, "%s\n", ctrl ? "crt" : "panel");
@@ -1172,7 +1175,7 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev,
dev_info(dev, "setting crt source to head %d\n", head);
- ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+ ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
if (head = HEAD_CRT) {
ctrl |= SM501_DC_CRT_CONTROL_SEL;
@@ -1184,7 +1187,7 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev,
ctrl &= ~SM501_DC_CRT_CONTROL_TE;
}
- writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
+ smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
sm501fb_sync_regs(info);
return len;
@@ -1205,7 +1208,8 @@ static int sm501fb_show_regs(struct sm501fb_info *info, char *ptr,
unsigned int reg;
for (reg = start; reg < (len + start); reg += 4)
- ptr += sprintf(ptr, "%08x = %08x\n", reg, readl(mem + reg));
+ ptr += sprintf(ptr, "%08x = %08x\n", reg,
+ smc501_readl(mem + reg));
return ptr - buf;
}
@@ -1257,7 +1261,7 @@ static int sm501fb_sync(struct fb_info *info)
/* wait for the 2d engine to be ready */
while ((count > 0) &&
- (readl(fbi->regs + SM501_SYSTEM_CONTROL) &
+ (smc501_readl(fbi->regs + SM501_SYSTEM_CONTROL) &
SM501_SYSCTRL_2D_ENGINE_STATUS) != 0)
count--;
@@ -1312,45 +1316,46 @@ static void sm501fb_copyarea(struct fb_info *info, const struct fb_copyarea *are
return;
/* set the base addresses */
- writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
- writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_DESTINATION_BASE);
+ smc501_writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
+ smc501_writel(par->screen.sm_addr,
+ fbi->regs2d + SM501_2D_DESTINATION_BASE);
/* set the window width */
- writel((info->var.xres << 16) | info->var.xres,
+ smc501_writel((info->var.xres << 16) | info->var.xres,
fbi->regs2d + SM501_2D_WINDOW_WIDTH);
/* set window stride */
- writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
+ smc501_writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
fbi->regs2d + SM501_2D_PITCH);
/* set data format */
switch (info->var.bits_per_pixel) {
case 8:
- writel(0, fbi->regs2d + SM501_2D_STRETCH);
+ smc501_writel(0, fbi->regs2d + SM501_2D_STRETCH);
break;
case 16:
- writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
+ smc501_writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
break;
case 32:
- writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
+ smc501_writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
break;
}
/* 2d compare mask */
- writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
+ smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
/* 2d mask */
- writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
+ smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
/* source and destination x y */
- writel((sx << 16) | sy, fbi->regs2d + SM501_2D_SOURCE);
- writel((dx << 16) | dy, fbi->regs2d + SM501_2D_DESTINATION);
+ smc501_writel((sx << 16) | sy, fbi->regs2d + SM501_2D_SOURCE);
+ smc501_writel((dx << 16) | dy, fbi->regs2d + SM501_2D_DESTINATION);
/* w/h */
- writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
+ smc501_writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
/* do area move */
- writel(0x800000cc | rtl, fbi->regs2d + SM501_2D_CONTROL);
+ smc501_writel(0x800000cc | rtl, fbi->regs2d + SM501_2D_CONTROL);
}
static void sm501fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
@@ -1372,47 +1377,49 @@ static void sm501fb_fillrect(struct fb_info *info, const struct fb_fillrect *rec
return;
/* set the base addresses */
- writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
- writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_DESTINATION_BASE);
+ smc501_writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
+ smc501_writel(par->screen.sm_addr,
+ fbi->regs2d + SM501_2D_DESTINATION_BASE);
/* set the window width */
- writel((info->var.xres << 16) | info->var.xres,
+ smc501_writel((info->var.xres << 16) | info->var.xres,
fbi->regs2d + SM501_2D_WINDOW_WIDTH);
/* set window stride */
- writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
+ smc501_writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
fbi->regs2d + SM501_2D_PITCH);
/* set data format */
switch (info->var.bits_per_pixel) {
case 8:
- writel(0, fbi->regs2d + SM501_2D_STRETCH);
+ smc501_writel(0, fbi->regs2d + SM501_2D_STRETCH);
break;
case 16:
- writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
+ smc501_writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
break;
case 32:
- writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
+ smc501_writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
break;
}
/* 2d compare mask */
- writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
+ smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
/* 2d mask */
- writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
+ smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
/* colour */
- writel(rect->color, fbi->regs2d + SM501_2D_FOREGROUND);
+ smc501_writel(rect->color, fbi->regs2d + SM501_2D_FOREGROUND);
/* x y */
- writel((rect->dx << 16) | rect->dy, fbi->regs2d + SM501_2D_DESTINATION);
+ smc501_writel((rect->dx << 16) | rect->dy,
+ fbi->regs2d + SM501_2D_DESTINATION);
/* w/h */
- writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
+ smc501_writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
/* do rectangle fill */
- writel(0x800100cc, fbi->regs2d + SM501_2D_CONTROL);
+ smc501_writel(0x800100cc, fbi->regs2d + SM501_2D_CONTROL);
}
@@ -1470,11 +1477,12 @@ static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base)
/* initialise the colour registers */
- writel(par->cursor.sm_addr, par->cursor_regs + SM501_OFF_HWC_ADDR);
+ smc501_writel(par->cursor.sm_addr,
+ par->cursor_regs + SM501_OFF_HWC_ADDR);
- writel(0x00, par->cursor_regs + SM501_OFF_HWC_LOC);
- writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_1_2);
- writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_3);
+ smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_LOC);
+ smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_1_2);
+ smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_3);
sm501fb_sync_regs(info);
return 0;
@@ -1581,7 +1589,7 @@ static int sm501fb_start(struct sm501fb_info *info,
/* clear palette ram - undefined at power on */
for (k = 0; k < (256 * 3); k++)
- writel(0, info->regs + SM501_DC_PANEL_PALETTE + (k * 4));
+ smc501_writel(0, info->regs + SM501_DC_PANEL_PALETTE + (k * 4));
/* enable display controller */
sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1);
@@ -1649,20 +1657,20 @@ static int sm501fb_init_fb(struct fb_info *fb,
switch (head) {
case HEAD_CRT:
pd = info->pdata->fb_crt;
- ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+ ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
enable = (ctrl & SM501_DC_CRT_CONTROL_ENABLE) ? 1 : 0;
/* ensure we set the correct source register */
if (info->pdata->fb_route != SM501_FB_CRT_PANEL) {
ctrl |= SM501_DC_CRT_CONTROL_SEL;
- writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
+ smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
}
break;
case HEAD_PANEL:
pd = info->pdata->fb_pnl;
- ctrl = readl(info->regs + SM501_DC_PANEL_CONTROL);
+ ctrl = smc501_readl(info->regs + SM501_DC_PANEL_CONTROL);
enable = (ctrl & SM501_DC_PANEL_CONTROL_EN) ? 1 : 0;
break;
@@ -1680,7 +1688,7 @@ static int sm501fb_init_fb(struct fb_info *fb,
if (head = HEAD_CRT && info->pdata->fb_route = SM501_FB_CRT_PANEL) {
ctrl &= ~SM501_DC_CRT_CONTROL_SEL;
- writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
+ smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
enable = 0;
}
@@ -2085,7 +2093,7 @@ static int sm501fb_suspend(struct platform_device *pdev, pm_message_t state)
struct sm501fb_info *info = platform_get_drvdata(pdev);
/* store crt control to resume with */
- info->pm_crt_ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+ info->pm_crt_ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
sm501fb_suspend_fb(info, HEAD_CRT);
sm501fb_suspend_fb(info, HEAD_PANEL);
@@ -2109,10 +2117,10 @@ static int sm501fb_resume(struct platform_device *pdev)
/* restore the items we want to be saved for crt control */
- crt_ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+ crt_ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
crt_ctrl &= ~SM501_CRT_CTRL_SAVE;
crt_ctrl |= info->pm_crt_ctrl & SM501_CRT_CTRL_SAVE;
- writel(crt_ctrl, info->regs + SM501_DC_CRT_CONTROL);
+ smc501_writel(crt_ctrl, info->regs + SM501_DC_CRT_CONTROL);
sm501fb_resume_fb(info, HEAD_CRT);
sm501fb_resume_fb(info, HEAD_PANEL);
diff --git a/include/linux/sm501.h b/include/linux/sm501.h
index 214f932..02fde50 100644
--- a/include/linux/sm501.h
+++ b/include/linux/sm501.h
@@ -172,3 +172,11 @@ struct sm501_platdata {
struct sm501_platdata_gpio_i2c *gpio_i2c;
unsigned int gpio_i2c_nr;
};
+
+#if defined(CONFIG_PPC32)
+#define smc501_readl(addr) ioread32be((addr))
+#define smc501_writel(val, addr) iowrite32be((val), (addr))
+#else
+#define smc501_readl(addr) readl(addr)
+#define smc501_writel(val, addr) writel(val, addr)
+#endif
--
1.7.3.4
^ permalink raw reply related
* Re: [PATCH 0/22] Make SVGA oriented FBs work on multi-domain PCI
From: Alex Buell @ 2011-01-22 10:55 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <20110111.154846.233419170.davem@davemloft.net>
On Fri, 2011-01-21 at 20:11 -0800, David Miller wrote:
> > [00000000000a0000]
>
> Yeah, it's dying the same way as before.
>
> I'm stumped at the moment.
I just spotted something. Looking at the above address, it seems to be
0xA0000, same as the high address for accessing VGA memory in a PC.
Perhaps it's still trying to access that whereas on a SUN it may need
remapping to the correct location?
--
Tactical Nuclear Kittens
^ permalink raw reply
* [PATCH] unicore32: add framebuffer driver for unigfx engine in PKUnity SoC
From: Guan Xuetao @ 2011-01-22 10:29 UTC (permalink / raw)
To: linux-fbdev; +Cc: linux-kernel
From: Guan Xuetao <gxt@mprc.pku.edu.cn>
This patch adds framebuffer driver for unigfx engine in PKUnity SoC.
1. add CONFIG_FB_PUV3_UNIGFX for configuration and build
2. add FB_ACCEL_PUV3_UNIGFX definition in include/linux/fb.h
3. driver based on drivers/video/vfb.c
Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
---
drivers/video/Kconfig | 11 +
drivers/video/Makefile | 1 +
drivers/video/puv3_fb.c | 932 +++++++++++++++++++++++++++++++++++++++++++++++
include/linux/fb.h | 2 +
4 files changed, 946 insertions(+), 0 deletions(-)
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..45ecd11 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) += puv3_fb.o
# Platform or fallback drivers go here
obj-$(CONFIG_FB_UVESA) += uvesafb.o
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
@@ -0,0 +1,932 @@
+/*
+ * 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/string.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.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>
+
+static char *unifb_option = NULL;
+static unsigned long unifb_regs[10];
+
+/*
+ * 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 },
+};
+
+/*
+ * RAM we reserve for the frame buffer. This defines the maximum screen size
+ *
+ * The default can be overridden if the driver is compiled as a module
+ */
+#define VIDEOMEMSIZE (SZ_4M) /* 4 MB for 1024*768*32b */
+
+static void *videomemory;
+static u_long videomemorysize = VIDEOMEMSIZE;
+module_param(videomemorysize, ulong, 0);
+
+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 int unifb_enable __initdata = 1; /* enable by default */
+module_param(unifb_enable, bool, 0);
+
+static int unifb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info);
+static int unifb_set_par(struct fb_info *info);
+static int unifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info);
+static int unifb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info);
+static int unifb_mmap(struct fb_info *info,
+ struct vm_area_struct *vma);
+
+#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");
+}
+
+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();
+
+ 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();
+
+ 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);
+}
+#endif
+
+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,
+};
+
+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 > videomemorysize)
+ 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(NULL, "VGA_CLK");
+ i = 0;
+ 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);
+ }
+#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 = unifb_regs[0] = PKUNITY_UNIGFX_MMAP_BASE;
+ UDE_LS = unifb_regs[1] = info->var.yres;
+ UDE_PS = unifb_regs[2] = get_line_length(info->var.xres,
+ info->var.bits_per_pixel) >> 3;
+ /* >> 3 for hardware required. */
+ UDE_HAT = unifb_regs[3] = (hTotal << 16) | (info->var.xres);
+ UDE_HBT = unifb_regs[4] = ((hTotal - 1) << 16) | (info->var.xres - 1);
+ UDE_HST = unifb_regs[5] = ((hSyncEnd - 1) << 16) | (hSyncStart - 1);
+ UDE_VAT = unifb_regs[6] = (vTotal << 16) | (info->var.yres);
+ UDE_VBT = unifb_regs[7] = ((vTotal - 1) << 16) | (info->var.yres - 1);
+ UDE_VST = unifb_regs[8] = ((vSyncEnd - 1) << 16) | (vSyncStart - 1);
+ UDE_CFG = unifb_regs[9] = 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:
+ ((u32 *) (info->pseudo_palette))[regno] = v;
+ break;
+ case 24:
+ case 32:
+ ((u32 *) (info->pseudo_palette))[regno] = v;
+ break;
+ }
+ 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;
+
+}
+
+#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 */
+
+ /*
+ * Initialisation
+ */
+
+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); */
+
+ info = framebuffer_alloc(sizeof(u32)*256, &dev->dev);
+ if (!info)
+ goto err;
+
+ info->screen_base = (char __iomem *)videomemory;
+ info->fbops = &unifb_ops;
+
+ retval = fb_find_mode(&info->var, info, unifb_option,
+ unifb_modes, 10, &unifb_modes[0], 16);
+
+ if (!retval || (retval = 4))
+ info->var = unifb_default;
+ unifb_fix.smem_start = PKUNITY_UNIGFX_MMAP_BASE;
+ unifb_fix.smem_len = videomemorysize;
+ unifb_fix.mmio_start = PKUNITY_UNIGFX_BASE;
+ 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
+
+ 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);
+
+ printk(KERN_INFO
+ "fb%d: Virtual frame buffer device, using %ldK of video memory\n",
+ info->node, videomemorysize >> 10);
+ 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;
+
+ 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)
+{
+ 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 = "unifb",
+ },
+};
+
+static struct platform_device *unifb_device;
+
+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;
+
+ 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;
+}
+
+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
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 0/22] Make SVGA oriented FBs work on multi-domain PCI
From: David Miller @ 2011-01-22 4:11 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <20110111.154846.233419170.davem@davemloft.net>
From: Alex Buell <alex.buell@munted.org.uk>
Date: Mon, 17 Jan 2011 13:06:48 +0000
> The module loads OK but generates the following when I run fbset -i
> -fb /dev/fb1
>
> Jan 17 13:00:54 sodium kernel: [ 369.984028] /pci@8,700000: PCI Error,
> primary error type[Master Abort]
> Jan 17 13:00:54 sodium kernel: [ 369.984042] /pci@8,700000:
> bytemask[0001] was_block(0) space(Memory)
> Jan 17 13:00:54 sodium kernel: [ 369.984049] /pci@8,700000: PCI AFAR
> [00000000000a0000]
Yeah, it's dying the same way as before.
I'm stumped at the moment.
^ permalink raw reply
* RE: Request for unicore32 architecture codes to merge into linux-next
From: Guan Xuetao @ 2011-01-22 2:17 UTC (permalink / raw)
To: 'Jesse Barnes'
Cc: sfr, 'Arnd Bergmann', gregkh, dmitry.torokhov, dtor,
rubini, linux-arch, linux-kernel, linux-fbdev, linux-next
In-Reply-To: <20110120114216.4b23182a@jbarnes-desktop>
> -----Original Message-----
> From: Jesse Barnes [mailto:jbarnes@virtuousgeek.org]
> Sent: Friday, January 21, 2011 3:42 AM
> To: Guan Xuetao
> Cc: sfr@canb.auug.org.au; Arnd Bergmann; gregkh@suse.de; dmitry.torokhov@gmail.com; dtor@mail.ru; rubini@cvml.unipv.it; linux-
> arch@vger.kernel.org; linux-kernel@vger.kernel.org; linux-fbdev@vger.kernel.org; linux-next@vger.kernel.org
> Subject: Re: Request for unicore32 architecture codes to merge into linux-next
>
> On Sun, 16 Jan 2011 01:00:31 +0800
> "Guan Xuetao" <guanxuetao@mprc.pku.edu.cn> wrote:
>
> > Hi,
> >
> > I want to merge unicore32 repo into linux-next tree, the position is (unicore32 branch):
> > git://git.kernel.org/pub/scm/linux/kernel/git/epip/linux-2.6-unicore32.git
> >
> > Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
> > ---
>
> Took a quick look at the PCI parts, looks like you have a pretty big
> DMA restriction.
Yes, only 128MB low memory could be used as dma space for pci devices.
>
> You could provide your own dma map ops and make the allocator a bit
> smarter about where it gets memory (preferentially allocating from the
> DMA'able region, which you could hide). Or do you find that swiotlb
> does ok in general?
Swiotlb works well. For almost all functions are provided by IPs inside the SoC,
the dma function is used mainly through amba/axi bus, not pci bus.
>
> Other than that you had pretty tiny bits of enabling code, I assume
> they work on your platform (config space access & setup, etc.).
Yes.
>
> --
> Jesse Barnes, Intel Open Source Technology Center
Thanks Jesse
Guan Xuetao
^ permalink raw reply
* [PATCH] video: pxa168fb: remove a redundant pxa168fb_check_var call
From: Axel Lin @ 2011-01-21 11:18 UTC (permalink / raw)
To: linux-kernel
Cc: Lennert Buytenhek, Green Wan, Eric Miao, Marek Vasut,
Haojian Zhuang, linux-fbdev, Paul Mundt
Current implementation calls pxa168fb_check_var twice in pxa168fb_probe.
Signed-off-by: Axel Lin <axel.lin@gmail.com>
---
drivers/video/pxa168fb.c | 6 +-----
1 files changed, 1 insertions(+), 5 deletions(-)
diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
index cea6403..35f61dd 100644
--- a/drivers/video/pxa168fb.c
+++ b/drivers/video/pxa168fb.c
@@ -701,16 +701,12 @@ static int __devinit pxa168fb_probe(struct platform_device *pdev)
*/
pxa168fb_init_mode(info, mi);
- ret = pxa168fb_check_var(&info->var, info);
- if (ret)
- goto failed_free_fbmem;
-
/*
* Fill in sane defaults.
*/
ret = pxa168fb_check_var(&info->var, info);
if (ret)
- goto failed;
+ goto failed_free_fbmem;
/*
* enable controller clock
--
1.7.0.4
^ permalink raw reply related
* Re: Request for unicore32 architecture codes to merge into
From: Jesse Barnes @ 2011-01-20 19:42 UTC (permalink / raw)
To: Guan Xuetao
Cc: sfr, Arnd Bergmann, gregkh, dmitry.torokhov, dtor, rubini,
linux-arch, linux-kernel, linux-fbdev, linux-next
In-Reply-To: <004901cbb4d5$b9bb1370$2d313a50$@mprc.pku.edu.cn>
On Sun, 16 Jan 2011 01:00:31 +0800
"Guan Xuetao" <guanxuetao@mprc.pku.edu.cn> wrote:
> Hi,
>
> I want to merge unicore32 repo into linux-next tree, the position is (unicore32 branch):
> git://git.kernel.org/pub/scm/linux/kernel/git/epip/linux-2.6-unicore32.git
>
> Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
> ---
Took a quick look at the PCI parts, looks like you have a pretty big
DMA restriction.
You could provide your own dma map ops and make the allocator a bit
smarter about where it gets memory (preferentially allocating from the
DMA'able region, which you could hide). Or do you find that swiotlb
does ok in general?
Other than that you had pretty tiny bits of enabling code, I assume
they work on your platform (config space access & setup, etc.).
--
Jesse Barnes, Intel Open Source Technology Center
^ permalink raw reply
* frame buffer on PXA320
From: James Simmons @ 2011-01-20 16:03 UTC (permalink / raw)
To: linux-fbdev
Hi!
I forward this email to the proper list.
Hello,
I have a board Toradex Colibri PXA320 with linux (2.6.31).
Could anybody tell me how can I set up framebuffer for 800x600 24 bits per
pixel mode?
The picture is blinking on the screen.
With another modes framebuffer works fine, e.g. 16bpp.
There are correct values in LCD controller registers and GPIO pins are set
well too.
In file "drivers/video/pxafb.c" I found this code:
if (fbi->fb.var.bits_per_pixel >= 16)
fb_dealloc_cmap(&fbi->fb.cmap);
Why do we deallocate color map in struct fb_info if bits per pixel is more
than 16?
Thus fb_info.cmap = NULL and I can't use ioctl request FBIOGETCMAP and
can't play with different color maps.
Or may be it's not a color map issue?
Thanks,
Best regards,
Dennis Semakin.
^ permalink raw reply
* [PATCH] video: da8xx-fb: fix fb_probe error path
From: Axel Lin @ 2011-01-20 3:50 UTC (permalink / raw)
To: linux-kernel; +Cc: Paul Mundt, linux-fbdev, Sudhakar Rajashekhara
Current implementation puts CONFIG_CPU_FREQ at wrong place, CONFIG_CPU_FREQ
is for lcd_da8xx_cpufreq_deregister not for unregister_framebuffer.
Signed-off-by: Axel Lin <axel.lin@gmail.com>
---
drivers/video/da8xx-fb.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index c265aed..520047a 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -1092,9 +1092,10 @@ static int __init fb_probe(struct platform_device *device)
irq_freq:
#ifdef CONFIG_CPU_FREQ
+ lcd_da8xx_cpufreq_deregister(par);
+#endif
err_cpu_freq:
unregister_framebuffer(da8xx_fb_info);
-#endif
err_dealloc_cmap:
fb_dealloc_cmap(&da8xx_fb_info->cmap);
--
1.7.2
^ permalink raw reply related
* [Patch V2] video: fix some comments in drivers/video/console/vgacon.c
From: Amerigo Wang @ 2011-01-19 6:24 UTC (permalink / raw)
To: linux-kernel
Cc: lethal, WANG Cong, Arnd Bergmann, Andrew Morton,
Greg Kroah-Hartman, Yannick Heneault, Matthew Garrett,
open list:FRAMEBUFFER LAYER
Now vgacon_scrollback_startup() uses slab, not bootmem,
the comment above it is obsolete, so does __init_refok.
Signed-off-by: WANG Cong <amwang@redhat.com>
---
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c97491b..915fd74 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -202,11 +202,7 @@ static void vgacon_scrollback_init(int pitch)
}
}
-/*
- * Called only duing init so call of alloc_bootmen is ok.
- * Marked __init_refok to silence modpost.
- */
-static void __init_refok vgacon_scrollback_startup(void)
+static void vgacon_scrollback_startup(void)
{
vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, GFP_NOWAIT);
vgacon_scrollback_init(vga_video_num_columns * 2);
^ permalink raw reply related
* Re: [Patch] video: remove pointless comments in drivers/video/console/vgacon.c
From: Cong Wang @ 2011-01-19 6:19 UTC (permalink / raw)
To: Paul Mundt
Cc: linux-kernel, Arnd Bergmann, Andrew Morton, Greg Kroah-Hartman,
Yannick Heneault, Matthew Garrett, open,
"list@linux-sh.org"@zmta03.collab.prod.int.phx2.redhat.com:FRAMEBUFFER LAYER
In-Reply-To: <20110119061551.GB12205@linux-sh.org>
于 2011年01月19日 14:15, Paul Mundt 写道:
> On Wed, Jan 19, 2011 at 02:08:22PM +0800, Cong Wang wrote:
>> ??? 2011???01???19??? 14:02, Paul Mundt ??????:
>>> On Wed, Jan 19, 2011 at 02:00:02PM +0800, Amerigo Wang wrote:
>>>> Now vgacon_scrollback_startup() uses slab, not bootmem,
>>>> so that comment is obsolete, the rest are useless.
>>>>
>>>> Signed-off-by: WANG Cong<amwang@redhat.com>
>>>>
>>> If you're going to do this then at least follow through and do the rest
>>> of it. The comment is no longer applicable, but then neither is the
>>> __init_refok annotation. Killing off the comment explaining why something
>>> is (or was there) without killing off the thing that is referenced by the
>>> comment is not terribly productive.
>>
>> Isn't __init_refok already a clear sign of "silence modpost"?
>> Why need to comment it again?
>
> __init_refok was to silence what was presumably an alloc_bootmem()
> reference at the time that the slab allocations were not early enough to
> satisfy the allocation, necessitating the use of bootmem. Since kmalloc
> and friends became usable early enough and the bootmem allocation has
> subsequently been dropped, there's no longer any need for the annotation.
>
> ie, alloc_bootmem() itself is __init while vgacon_scrollback_startup() is
> not, hence the modpost complaint.
Ah, I see, will remove '__init_refok' as well.
Thanks!
^ permalink raw reply
* Re: [Patch] video: remove pointless comments in drivers/video/console/vgacon.c
From: Paul Mundt @ 2011-01-19 6:02 UTC (permalink / raw)
To: Amerigo Wang
Cc: linux-kernel, Arnd Bergmann, Andrew Morton, Greg Kroah-Hartman,
Yannick Heneault, Matthew Garrett, open list:FRAMEBUFFER LAYER
In-Reply-To: <1295416803-17651-1-git-send-email-amwang@redhat.com>
On Wed, Jan 19, 2011 at 02:00:02PM +0800, Amerigo Wang wrote:
> Now vgacon_scrollback_startup() uses slab, not bootmem,
> so that comment is obsolete, the rest are useless.
>
> Signed-off-by: WANG Cong <amwang@redhat.com>
>
If you're going to do this then at least follow through and do the rest
of it. The comment is no longer applicable, but then neither is the
__init_refok annotation. Killing off the comment explaining why something
is (or was there) without killing off the thing that is referenced by the
comment is not terribly productive.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox