Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* [PATCH 1/3] viafb: use write combining for video ram
From: Florian Tobias Schandinat @ 2011-04-30 14:18 UTC (permalink / raw)
  To: linux-fbdev; +Cc: linux-kernel, Florian Tobias Schandinat
In-Reply-To: <1304173086-3434-1-git-send-email-FlorianSchandinat@gmx.de>

This can give a speed up of factor 6-9, which is quite notable.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
---
 drivers/video/via/via-core.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c
index 6723d69..5b0129b 100644
--- a/drivers/video/via/via-core.c
+++ b/drivers/video/via/via-core.c
@@ -505,7 +505,7 @@ static int __devinit via_pci_setup_mmio(struct viafb_dev *vdev)
 	ret = vdev->fbmem_len = viafb_get_fb_size_from_pci(vdev->chip_type);
 	if (ret < 0)
 		goto out_unmap;
-	vdev->fbmem = ioremap_nocache(vdev->fbmem_start, vdev->fbmem_len);
+	vdev->fbmem = ioremap_wc(vdev->fbmem_start, vdev->fbmem_len);
 	if (vdev->fbmem = NULL) {
 		ret = -ENOMEM;
 		goto out_unmap;
-- 
1.6.3.2


^ permalink raw reply related

* [PATCH 2/3] viafb: try to map less memory in case of failure
From: Florian Tobias Schandinat @ 2011-04-30 14:18 UTC (permalink / raw)
  To: linux-fbdev; +Cc: linux-kernel, Florian Tobias Schandinat
In-Reply-To: <1304173086-3434-1-git-send-email-FlorianSchandinat@gmx.de>

The current code might result in trying to remap 512MB video ram on
a 32 bit system which is quite likely to fail.
This patch tries to map less of it down to 8MB as this should still
be enough to get a reasonably well working framebuffer. This should
make viafb work for many people without requiring them to manually
allocate more space.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
---
 drivers/video/via/via-core.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c
index 5b0129b..eb112b6 100644
--- a/drivers/video/via/via-core.c
+++ b/drivers/video/via/via-core.c
@@ -505,7 +505,14 @@ static int __devinit via_pci_setup_mmio(struct viafb_dev *vdev)
 	ret = vdev->fbmem_len = viafb_get_fb_size_from_pci(vdev->chip_type);
 	if (ret < 0)
 		goto out_unmap;
-	vdev->fbmem = ioremap_wc(vdev->fbmem_start, vdev->fbmem_len);
+
+	/* try to map less memory on failure, 8 MB should be still enough */
+	for (; vdev->fbmem_len >= 8 << 20; vdev->fbmem_len /= 2) {
+		vdev->fbmem = ioremap_wc(vdev->fbmem_start, vdev->fbmem_len);
+		if (vdev->fbmem)
+			break;
+	}
+
 	if (vdev->fbmem = NULL) {
 		ret = -ENOMEM;
 		goto out_unmap;
-- 
1.6.3.2


^ permalink raw reply related

* [PATCH 3/3] viafb: remove unused CEA mode
From: Florian Tobias Schandinat @ 2011-04-30 14:18 UTC (permalink / raw)
  To: linux-fbdev; +Cc: linux-kernel, Florian Tobias Schandinat
In-Reply-To: <1304173086-3434-1-git-send-email-FlorianSchandinat@gmx.de>

This trivial patch removes unused mode tables.

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
---
 drivers/video/via/share.h   |    8 --------
 drivers/video/via/viamode.c |   17 -----------------
 drivers/video/via/viamode.h |    9 ---------
 3 files changed, 0 insertions(+), 34 deletions(-)

diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h
index 8b93e2f..61b0bd5 100644
--- a/drivers/video/via/share.h
+++ b/drivers/video/via/share.h
@@ -568,10 +568,6 @@
 #define M1280X720_R50_HSP       NEGATIVE
 #define M1280X720_R50_VSP       POSITIVE
 
-/* 1280x720@60 Sync Polarity  (CEA Mode) */
-#define M1280X720_CEA_R60_HSP       POSITIVE
-#define M1280X720_CEA_R60_VSP       POSITIVE
-
 /* 1440x900@60 Sync Polarity (CVT Mode) */
 #define M1440X900_R60_HSP       NEGATIVE
 #define M1440X900_R60_VSP       POSITIVE
@@ -612,10 +608,6 @@
 #define M1920X1200_RB_R60_HSP  POSITIVE
 #define M1920X1200_RB_R60_VSP  NEGATIVE
 
-/* 1920x1080@60 Sync Polarity  (CEA Mode) */
-#define M1920X1080_CEA_R60_HSP       POSITIVE
-#define M1920X1080_CEA_R60_VSP       POSITIVE
-
 /* 2048x1536@60 Sync Polarity (CVT Mode) */
 #define M2048x1536_R60_HSP      NEGATIVE
 #define M2048x1536_R60_VSP      POSITIVE
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c
index 50de07f..58df74e 100644
--- a/drivers/video/via/viamode.c
+++ b/drivers/video/via/viamode.c
@@ -854,23 +854,6 @@ static struct VideoModeTable viafb_rb_modes[] = {
 	{CRTM1920x1200_RB, ARRAY_SIZE(CRTM1920x1200_RB)}
 };
 
-struct crt_mode_table CEAM1280x720[] = {
-	{REFRESH_60, M1280X720_CEA_R60_HSP, M1280X720_CEA_R60_VSP,
-	 /* HT,    HA,   HBS,  HBE,  HSS, HSE,  VT,   VA,  VBS, VBE, VSS, VSE */
-	 {1650, 1280, 1280, 370, 1390, 40, 750, 720, 720, 30, 725, 5} }
-};
-struct crt_mode_table CEAM1920x1080[] = {
-	{REFRESH_60, M1920X1080_CEA_R60_HSP, M1920X1080_CEA_R60_VSP,
-	 /* HT,    HA,   HBS,  HBE,  HSS, HSE,  VT,  VA, VBS, VBE,  VSS, VSE */
-	 {2200, 1920, 1920, 300, 2008, 44, 1125, 1080, 1080, 45, 1084, 5} }
-};
-struct VideoModeTable CEA_HDMI_Modes[] = {
-	/* Display : 1280x720 */
-	{CEAM1280x720, ARRAY_SIZE(CEAM1280x720)},
-	{CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)}
-};
-
-int NUM_TOTAL_CEA_MODES = ARRAY_SIZE(CEA_HDMI_Modes);
 int NUM_TOTAL_CN400_ModeXregs = ARRAY_SIZE(CN400_ModeXregs);
 int NUM_TOTAL_CN700_ModeXregs = ARRAY_SIZE(CN700_ModeXregs);
 int NUM_TOTAL_KM400_ModeXregs = ARRAY_SIZE(KM400_ModeXregs);
diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h
index 8a67ea1..3751289 100644
--- a/drivers/video/via/viamode.h
+++ b/drivers/video/via/viamode.h
@@ -41,7 +41,6 @@ struct patch_table {
 	struct io_reg *io_reg_table;
 };
 
-extern int NUM_TOTAL_CEA_MODES;
 extern int NUM_TOTAL_CN400_ModeXregs;
 extern int NUM_TOTAL_CN700_ModeXregs;
 extern int NUM_TOTAL_KM400_ModeXregs;
@@ -50,14 +49,6 @@ extern int NUM_TOTAL_VX855_ModeXregs;
 extern int NUM_TOTAL_CLE266_ModeXregs;
 extern int NUM_TOTAL_PATCH_MODE;
 
-/********************/
-/* Mode Table       */
-/********************/
-
-extern struct crt_mode_table CEAM1280x720[];
-extern struct crt_mode_table CEAM1920x1080[];
-extern struct VideoModeTable CEA_HDMI_Modes[];
-
 extern struct io_reg CN400_ModeXregs[];
 extern struct io_reg CN700_ModeXregs[];
 extern struct io_reg KM400_ModeXregs[];
-- 
1.6.3.2


^ permalink raw reply related

* fbdev test application
From: Laurent Pinchart @ 2011-04-30 14:43 UTC (permalink / raw)
  To: linux-fbdev

Hi everybody,

I've developed a small fbdev application for internal test purpose that might
be useful to other developers, so I'm releasing it under the GPL.

The code can be found in a git repository at
http://git.ideasonboard.org/?pûdev-test.git;a=summary. I'm also adding the
initial patch to this e-mail, in case someone would like to review the
code :-)

diff -Nur a/fbdev.c b/fbdev.c
--- a/fbdev.c	1970-01-01 01:00:00.000000000 +0100
+++ b/fbdev.c	2011-04-29 17:04:03.000000000 +0200
@@ -0,0 +1,1062 @@
+/*
+ * fbdev -- Frame buffer device test application
+ *
+ * Copyright (C) 2011 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+
+#include <linux/fb.h>
+
+#define ARRAY_SIZE(a)	(sizeof(a)/sizeof((a)[0]))
+
+struct device {
+	int fd;
+	void *mem;
+
+	struct fb_fix_screeninfo fix_info;
+	struct fb_var_screeninfo var_info;
+};
+
+enum fb_fill_mode {
+	FB_FILL_NONE = 0,
+	FB_FILL_DISPLAY = 1,
+	FB_FILL_VIRTUAL = 2,
+};
+
+/* -----------------------------------------------------------------------------
+ * FB information display
+ */
+
+struct fb_value_name {
+	unsigned int value;
+	const char *name;
+};
+
+static const struct fb_value_name fb_type_names[] = {
+	{ FB_TYPE_PACKED_PIXELS, "Packed Pixels" },
+	{ FB_TYPE_PLANES, "Non Interleaved Planes" },
+	{ FB_TYPE_INTERLEAVED_PLANES, "Interleaved Planes" },
+	{ FB_TYPE_TEXT, "Text/Attributes" },
+	{ FB_TYPE_VGA_PLANES, "EGA/VGA Planes" },
+};
+
+static const struct fb_value_name fb_visual_names[] = {
+	{ FB_VISUAL_MONO01, "Monochrome (white 0, black 1)" },
+	{ FB_VISUAL_MONO10, "Monochrome (white 1, black 0)" },
+	{ FB_VISUAL_TRUECOLOR, "True Color" },
+	{ FB_VISUAL_PSEUDOCOLOR, "Pseudo Color" },
+	{ FB_VISUAL_DIRECTCOLOR, "Direct Color" },
+	{ FB_VISUAL_STATIC_PSEUDOCOLOR, "Pseudo Color (read-only)" },
+};
+
+static const struct fb_value_name fb_accel_names[] = {
+	{ FB_ACCEL_NONE, "no hardware accelerator" },
+	{ FB_ACCEL_ATARIBLITT, "Atari Blitter" },
+	{ FB_ACCEL_AMIGABLITT, "Amiga Blitter" },
+	{ FB_ACCEL_S3_TRIO64, "Cybervision64 (S3 Trio64)" },
+	{ FB_ACCEL_NCR_77C32BLT, "RetinaZ3 (NCR 77C32BLT)" },
+	{ FB_ACCEL_S3_VIRGE, "Cybervision64/3D (S3 ViRGE)" },
+	{ FB_ACCEL_ATI_MACH64GX, "ATI Mach 64GX family" },
+	{ FB_ACCEL_DEC_TGA, "DEC 21030 TGA" },
+	{ FB_ACCEL_ATI_MACH64CT, "ATI Mach 64CT family" },
+	{ FB_ACCEL_ATI_MACH64VT, "ATI Mach 64CT family VT class" },
+	{ FB_ACCEL_ATI_MACH64GT, "ATI Mach 64CT family GT class" },
+	{ FB_ACCEL_SUN_CREATOR, "Sun Creator/Creator3D" },
+	{ FB_ACCEL_SUN_CGSIX, "Sun cg6" },
+	{ FB_ACCEL_SUN_LEO, "Sun leo/zx" },
+	{ FB_ACCEL_IMS_TWINTURBO, "IMS Twin Turbo" },
+	{ FB_ACCEL_3DLABS_PERMEDIA2, "3Dlabs Permedia 2" },
+	{ FB_ACCEL_MATROX_MGA2064W, "Matrox MGA2064W (Millenium)" },
+	{ FB_ACCEL_MATROX_MGA1064SG, "Matrox MGA1064SG (Mystique)" },
+	{ FB_ACCEL_MATROX_MGA2164W, "Matrox MGA2164W (Millenium II)" },
+	{ FB_ACCEL_MATROX_MGA2164W_AGP, "Matrox MGA2164W (Millenium II)" },
+	{ FB_ACCEL_MATROX_MGAG100, "Matrox G100 (Productiva G100)" },
+	{ FB_ACCEL_MATROX_MGAG200, "Matrox G200 (Myst, Mill, ...)" },
+	{ FB_ACCEL_SUN_CG14, "Sun cgfourteen" },
+	{ FB_ACCEL_SUN_BWTWO, "Sun bwtwo" },
+	{ FB_ACCEL_SUN_CGTHREE, "Sun cgthree" },
+	{ FB_ACCEL_SUN_TCX, "Sun tcx" },
+	{ FB_ACCEL_MATROX_MGAG400, "Matrox G400" },
+	{ FB_ACCEL_NV3, "nVidia RIVA 128" },
+	{ FB_ACCEL_NV4, "nVidia RIVA TNT" },
+	{ FB_ACCEL_NV5, "nVidia RIVA TNT2" },
+	{ FB_ACCEL_CT_6555x, "C&T 6555x" },
+	{ FB_ACCEL_3DFX_BANSHEE, "3Dfx Banshee" },
+	{ FB_ACCEL_ATI_RAGE128, "ATI Rage128 family" },
+	{ FB_ACCEL_IGS_CYBER2000, "CyberPro 2000" },
+	{ FB_ACCEL_IGS_CYBER2010, "CyberPro 2010" },
+	{ FB_ACCEL_IGS_CYBER5000, "CyberPro 5000" },
+	{ FB_ACCEL_SIS_GLAMOUR, "SiS 300/630/540" },
+	{ FB_ACCEL_3DLABS_PERMEDIA3, "3Dlabs Permedia 3" },
+	{ FB_ACCEL_ATI_RADEON, "ATI Radeon family" },
+	{ FB_ACCEL_I810, "Intel 810/815" },
+	{ FB_ACCEL_SIS_GLAMOUR_2, "SiS 315, 650, 740" },
+	{ FB_ACCEL_SIS_XABRE, "SiS 330 (\"Xabre\")" },
+	{ FB_ACCEL_I830, "Intel 830M/845G/85x/865G" },
+	{ FB_ACCEL_NV_10, "nVidia Arch 10" },
+	{ FB_ACCEL_NV_20, "nVidia Arch 20" },
+	{ FB_ACCEL_NV_30, "nVidia Arch 30" },
+	{ FB_ACCEL_NV_40, "nVidia Arch 40" },
+	{ FB_ACCEL_XGI_VOLARI_V, "XGI Volari V3XT, V5, V8" },
+	{ FB_ACCEL_XGI_VOLARI_Z, "XGI Volari Z7" },
+	{ FB_ACCEL_OMAP1610, "TI OMAP16xx" },
+	{ FB_ACCEL_TRIDENT_TGUI, "Trident TGUI" },
+	{ FB_ACCEL_TRIDENT_3DIMAGE, "Trident 3DImage" },
+	{ FB_ACCEL_TRIDENT_BLADE3D, "Trident Blade3D" },
+	{ FB_ACCEL_TRIDENT_BLADEXP, "Trident BladeXP" },
+	{ FB_ACCEL_CIRRUS_ALPINE, "Cirrus Logic 543x/544x/5480" },
+	{ FB_ACCEL_NEOMAGIC_NM2070, "NeoMagic NM2070" },
+	{ FB_ACCEL_NEOMAGIC_NM2090, "NeoMagic NM2090" },
+	{ FB_ACCEL_NEOMAGIC_NM2093, "NeoMagic NM2093" },
+	{ FB_ACCEL_NEOMAGIC_NM2097, "NeoMagic NM2097" },
+	{ FB_ACCEL_NEOMAGIC_NM2160, "NeoMagic NM2160" },
+	{ FB_ACCEL_NEOMAGIC_NM2200, "NeoMagic NM2200" },
+	{ FB_ACCEL_NEOMAGIC_NM2230, "NeoMagic NM2230" },
+	{ FB_ACCEL_NEOMAGIC_NM2360, "NeoMagic NM2360" },
+	{ FB_ACCEL_NEOMAGIC_NM2380, "NeoMagic NM2380" },
+	{ FB_ACCEL_SAVAGE4, "S3 Savage4" },
+	{ FB_ACCEL_SAVAGE3D, "S3 Savage3D" },
+	{ FB_ACCEL_SAVAGE3D_MV, "S3 Savage3D-MV" },
+	{ FB_ACCEL_SAVAGE2000, "S3 Savage2000" },
+	{ FB_ACCEL_SAVAGE_MX_MV, "S3 Savage/MX-MV" },
+	{ FB_ACCEL_SAVAGE_MX, "S3 Savage/MX" },
+	{ FB_ACCEL_SAVAGE_IX_MV, "S3 Savage/IX-MV" },
+	{ FB_ACCEL_SAVAGE_IX, "S3 Savage/IX" },
+	{ FB_ACCEL_PROSAVAGE_PM, "S3 ProSavage PM133" },
+	{ FB_ACCEL_PROSAVAGE_KM, "S3 ProSavage KM133" },
+	{ FB_ACCEL_S3TWISTER_P, "S3 Twister" },
+	{ FB_ACCEL_S3TWISTER_K, "S3 TwisterK" },
+	{ FB_ACCEL_SUPERSAVAGE, "S3 Supersavage" },
+	{ FB_ACCEL_PROSAVAGE_DDR, "S3 ProSavage DDR" },
+	{ FB_ACCEL_PROSAVAGE_DDRK, "S3 ProSavage DDR-K" },
+};
+
+static const char *fb_value_name(const struct fb_value_name *names,
+				 unsigned int size, unsigned int value)
+{
+	unsigned int i;
+
+	for (i = 0; i < size; ++i) {
+		if (names[i].value = value)
+			return names[i].name;
+	}
+
+	return "Unknown";
+}
+
+static const char *fb_type_name(unsigned int type)
+{
+	return fb_value_name(fb_type_names, ARRAY_SIZE(fb_type_names), type);
+}
+
+static const char *fb_visual_name(unsigned int visual)
+{
+	return fb_value_name(fb_visual_names, ARRAY_SIZE(fb_visual_names), visual);
+}
+
+static const char *fb_accel_name(unsigned int accel)
+{
+	return fb_value_name(fb_accel_names, ARRAY_SIZE(fb_accel_names), accel);
+}
+
+/*
+ * fb_print_fix - Print fixed screen information
+ * @dev: FB device
+ * @var: fixed screen information
+ */
+static void fb_print_fix(struct device *dev __attribute__((__unused__)),
+			 struct fb_fix_screeninfo *fix)
+{
+	printf("--- Fixed screen info ---\n");
+	printf(" Type:\t\t%s\n", fb_type_name(fix->type));
+	printf(" Visual:\t%s\n", fb_visual_name(fix->visual));
+	printf(" Chip/card:\t%s\n", fb_accel_name(fix->accel));
+
+	printf(" Memory:\t%u bytes @0x%08lx\n", fix->smem_len,
+		fix->smem_start);
+
+	if (fix->xpanstep = 0)
+		printf(" X Pan:\t\tUnsupported\n");
+	else
+		printf(" X Pan Step:\t%u\n", fix->xpanstep);
+
+	if (fix->ypanstep = 0)
+		printf(" Y Pan:\t\tUnsupported\n");
+	else
+		printf(" Y Pan Step:\t%u\n", fix->ypanstep);
+
+	printf(" Line Length:\t%u bytes\n", fix->line_length);
+}
+
+/*
+ * fb_print_var - Print fixed screen information
+ * @dev: FB device
+ * @var: variable screen information
+ */
+static void fb_print_var(struct device *dev, struct fb_var_screeninfo *var)
+{
+	unsigned int i;
+
+	printf("--- Variable screen info ---\n");
+	printf(" Resolution:\t\t%ux%u\n", var->xres, var->yres);
+	printf(" Virtual Resolution:\t%ux%u\n", var->xres_virtual,
+		var->yres_virtual);
+	printf(" X/Y Offset:\t\t(%u,%u)\n", var->xoffset, var->yoffset);
+	printf(" Size:\t\t\t%umm x %umm\n", var->width, var->height);
+
+	if (dev->fix_info.visual = FB_VISUAL_TRUECOLOR) {
+		printf(" Pixel organization:\t");
+		for (i = var->bits_per_pixel - 1; i < var->bits_per_pixel; --i) {
+			if (var->red.offset <= i && var->red.offset + var->red.length > i)
+				printf("R");
+			else if (var->green.offset <= i && var->green.offset + var->green.length > i)
+				printf("G");
+			else if (var->blue.offset <= i && var->blue.offset + var->green.length > i)
+				printf("B");
+			else if (var->transp.offset <= i && var->transp.offset + var->transp.length > i)
+				printf("A");
+		}
+		printf("\n  (%u bits per pixel)\t", var->bits_per_pixel);
+		for (i = var->bits_per_pixel - 1; i < var->bits_per_pixel; --i) {
+			if (var->red.offset <= i &&
+			    var->red.offset + var->red.length > i)
+				printf("%u", var->red.msb_right ?
+					var->red.offset + var->red.length - 1 - i :
+					i - var->red.offset);
+			else if (var->green.offset <= i &&
+				 var->green.offset + var->green.length > i)
+				printf("%u", var->green.msb_right ?
+					var->green.offset + var->green.length - 1 - i :
+					i - var->green.offset);
+			else if (var->blue.offset <= i &&
+				 var->blue.offset + var->green.length > i)
+				printf("%u", var->blue.msb_right ?
+					var->blue.offset + var->blue.length - 1 - i :
+					i - var->blue.offset);
+			else if (var->transp.offset <= i &&
+				 var->transp.offset + var->transp.length > i)
+				printf("%u", var->transp.msb_right ?
+					var->transp.offset + var->transp.length - 1 - i :
+					i - var->transp.offset);
+		}
+		printf("\n");
+	}
+}
+
+/* -----------------------------------------------------------------------------
+ * Memory mapping
+ */
+
+/*
+ * fb_map_memory - Map the frame buffer memory to userspace
+ * @dev: FB device
+ */
+static int fb_map_memory(struct device *dev)
+{
+	void *mem;
+
+	mem = mmap(NULL, dev->fix_info.smem_len, PROT_READ | PROT_WRITE,
+		   MAP_SHARED, dev->fd, 0);
+	if (mem = MAP_FAILED) {
+		printf("Error: FB memory map failed: %s (%d)\n",
+			strerror(errno), errno);
+		return -1;
+	}
+
+	dev->mem = mem;
+	return 0;
+}
+
+/*
+ * fb_unmap_memory - Unmap the frame buffer memory from userspace
+ * @dev: FB device
+ */
+static void fb_unmap_memory(struct device *dev)
+{
+	if (dev->mem = MAP_FAILED)
+		return;
+
+	munmap(dev->mem, dev->fix_info.smem_len);
+}
+
+/* -----------------------------------------------------------------------------
+ * Open/close
+ */
+
+/*
+ * fb_open - Open a frame buffer device
+ * @dev: FB device
+ * @devname: FB device node name and path
+ *
+ * Open the FB devide referenced by devname. Retrieve fixed and variable screen
+ * information, map the frame buffer memory and fill the dev structure.
+ */
+static int fb_open(struct device *dev, const char *devname)
+{
+	int ret;
+
+	memset(dev, 0, sizeof *dev);
+	dev->fd = -1;
+	dev->mem = MAP_FAILED;
+
+	dev->fd = open(devname, O_RDWR);
+	if (dev->fd < 0) {
+		printf("Error opening device %s: %d.\n", devname, errno);
+		return dev->fd;
+	}
+
+	ret = ioctl(dev->fd, FBIOGET_FSCREENINFO, &dev->fix_info);
+	if (ret < 0) {
+		printf("Error opening device %s: unable to get fixed screen "
+			"info.\n", devname);
+		close(dev->fd);
+		return ret;
+	}
+
+	ret = ioctl(dev->fd, FBIOGET_VSCREENINFO, &dev->var_info);
+	if (ret < 0) {
+		printf("Error opening device %s: unable to get variable screen "
+			"info.\n", devname);
+		close(dev->fd);
+		return ret;
+	}
+
+	printf("Device %s opened: %s\n\n", devname, dev->fix_info.id);
+	fb_print_fix(dev, &dev->fix_info);
+	printf("\n");
+	fb_print_var(dev, &dev->var_info);
+	printf("\n");
+
+	ret = fb_map_memory(dev);
+	if (ret < 0) {
+		close(dev->fd);
+		return ret;
+	}
+
+	printf("FB memory mapped at %p\n", dev->mem);
+	return 0;
+}
+
+/*
+ * fb_close - Close a frame buffer device
+ * @dev: FB device
+ *
+ * Close a frame buffer device previously opened by fb_open().
+ */
+static void fb_close(struct device *dev)
+{
+	fb_unmap_memory(dev);
+	close(dev->fd);
+}
+
+/* -----------------------------------------------------------------------------
+ * Blanking and sync
+ */
+
+/*
+ * fb_blank - Control screen blanking
+ * @dev: FB device
+ * @blank: Blanking state
+ *
+ * Set the frame buffer screen blanking state. Acceptable values for the blank
+ * parameter are
+ *
+ * FB_BLANK_UNBLANK		Blanking off, screen active
+ * FB_BLANK_NORMAL		Blanked, HSync on,  VSync on
+ * FB_BLANK_VSYNC_SUSPEND	Blanked, HSync on,  VSync off
+ * FB_BLANK_HSYNC_SUSPEND	Blanked, HSync off, VSync on
+ * FB_BLANK_POWERDOWN		Blanked, HSync off, VSync off
+ */
+static int fb_blank(struct device *dev, int blank)
+{
+	int ret;
+
+	ret = ioctl(dev->fd, FBIOBLANK, blank);
+	if (ret < 0) {
+		printf("Error: blank failed: %s (%d)\n", strerror(errno), errno);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+ * fb_wait_for_vsync - Wait for vsync
+ * @dev: FB device
+ * @screen: Screen number
+ *
+ * Unblank the screen to make sure vsync events are generated and wait for 1000
+ * 1000 vsync events on the given screen. Print the average refresh rate when
+ * done.
+ */
+static int fb_wait_for_vsync(struct device *dev, unsigned int screen)
+{
+	struct timespec start, end;
+	unsigned int i;
+	double fps;
+	int ret;
+
+	/* Can't wait for vsync if the displayed is blanked. */
+	fb_blank(dev, FB_BLANK_UNBLANK);
+
+	printf("waiting for 1000 vsync events... ");
+	fflush(stdout);
+
+	clock_gettime(CLOCK_MONOTONIC, &start);
+
+	for (i = 0; i < 1000; ++i) {
+		ret = ioctl(dev->fd, FBIO_WAITFORVSYNC, &screen);
+		if (ret < 0) {
+			printf("\nError: wait for vsync failed: %s (%d)\n",
+				strerror(errno), errno);
+			return ret;
+		}
+	}
+
+	clock_gettime(CLOCK_MONOTONIC, &end);
+
+	end.tv_sec -= start.tv_sec;
+	end.tv_nsec -= start.tv_nsec;
+	if (end.tv_nsec < 0) {
+		end.tv_sec--;
+		end.tv_nsec += 1000000000;
+	}
+
+	fps = i / (end.tv_sec + end.tv_nsec / 1000000000.);
+
+	printf("done\n");
+	printf("%u vsync interrupts in %lu.%06lu s, %f Hz\n",
+		i, end.tv_sec, end.tv_nsec / 1000, fps);
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Resolution and pan
+ */
+
+/*
+ * fb_set_format - Set the frame buffer pixel format
+ * @dev: FB device
+ * @bpp: Bits per pixel
+ */
+static int fb_set_format(struct device *dev, unsigned int bpp)
+{
+	struct fb_var_screeninfo var_info;
+	int ret;
+
+	var_info = dev->var_info;
+
+	var_info.bits_per_pixel = bpp;
+	var_info.activate = FB_ACTIVATE_NOW;
+
+	ret = ioctl(dev->fd, FBIOPUT_VSCREENINFO, &var_info);
+	if (ret < 0) {
+		printf("Error: set format failed: %s (%d)\n",
+			strerror(errno), errno);
+		return ret;
+	}
+
+	dev->var_info = var_info;
+
+	printf("Format set to %u bits per pixel\n\n",
+		var_info.bits_per_pixel);
+
+	fb_print_var(dev, &var_info);
+
+	return 0;
+}
+
+/*
+ * fb_set_resolution - Set the frame buffer real and virtual resolutions
+ * @dev: FB device
+ * @xres: Horizontal resolution
+ * @yres: Vertical resolution
+ * @xres_virtual: Horizontal virtual resolution
+ * @yres_virtual: Vertical virtual resolution
+ *
+ * Modify the real and virtual resolutions of the frame buffer to (xres, yres)
+ * and (xres_virtual, yres_virtual). The real or virtual resolution can be kept
+ * unchanged by setting its value to (-1, -1).
+ */
+static int fb_set_resolution(struct device *dev, int xres, int yres,
+			     int xres_virtual, int yres_virtual)
+{
+	struct fb_var_screeninfo var_info;
+	int ret;
+
+	var_info = dev->var_info;
+
+	if (xres != -1 && yres != -1 ) {
+		var_info.xres = xres;
+		var_info.yres = yres;
+	}
+
+	if (xres_virtual != -1 && yres_virtual != -1 ) {
+		var_info.xres_virtual = xres_virtual;
+		var_info.yres_virtual = yres_virtual;
+	}
+
+	printf("Setting resolution to %ux%u (virtual %ux%u)\n",
+		var_info.xres, var_info.yres,
+		var_info.xres_virtual, var_info.yres_virtual);
+
+	var_info.bits_per_pixel = 16;
+	var_info.activate = FB_ACTIVATE_NOW;
+
+	ret = ioctl(dev->fd, FBIOPUT_VSCREENINFO, &var_info);
+	if (ret < 0) {
+		printf("Error: set resolution failed: %s (%d)\n",
+			strerror(errno), errno);
+		return ret;
+	}
+
+	dev->var_info = var_info;
+
+	printf("Resolution set to %ux%u (virtual %ux%u)\n\n",
+		var_info.xres, var_info.yres,
+		var_info.xres_virtual, var_info.yres_virtual);
+
+	fb_print_var(dev, &var_info);
+
+	return 0;
+}
+
+/*
+ * fb_pan - Pan the display
+ * @dev: FB device
+ * @x: Horizontal offset
+ * @y: Vertical offset
+ *
+ * Pan the display to set the virtual point (x, y) on the top left corner of the
+ * screen.
+ */
+static int fb_pan(struct device *dev, unsigned int x, unsigned int y)
+{
+	struct fb_var_screeninfo var_info;
+	int ret;
+
+	memset(&var_info, 0, sizeof var_info);
+	var_info.xoffset = x;
+	var_info.yoffset = y;
+
+	ret = ioctl(dev->fd, FBIOPAN_DISPLAY, &var_info);
+	if (ret < 0) {
+		printf("Error: pan failed: %s (%d)\n", strerror(errno), errno);
+		return ret;
+	}
+
+	dev->var_info.xoffset = var_info.xoffset;
+	dev->var_info.yoffset = var_info.yoffset;
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Test pattern
+ */
+
+#define FB_MAKE_COLOR(var, r, g, b) \
+	((((r) >> (8 - (var)->red.length)) << (var)->red.offset) | \
+	 (((g) >> (8 - (var)->green.length)) << (var)->green.offset) | \
+	 (((b) >> (8 - (var)->blue.length)) << (var)->blue.offset))
+
+static void
+fb_fill_rgb16(struct device *dev, unsigned int xoffset, unsigned int yoffset,
+	      unsigned int xres, unsigned int yres)
+{
+	const uint16_t colors_top[] = {
+		FB_MAKE_COLOR(&dev->var_info, 192, 192, 192),	/* grey */
+		FB_MAKE_COLOR(&dev->var_info, 192, 192, 0),	/* yellow */
+		FB_MAKE_COLOR(&dev->var_info, 0, 192, 192),	/* cyan */
+		FB_MAKE_COLOR(&dev->var_info, 0, 192, 0),	/* green */
+		FB_MAKE_COLOR(&dev->var_info, 192, 0, 192),	/* magenta */
+		FB_MAKE_COLOR(&dev->var_info, 192, 0, 0),	/* red */
+		FB_MAKE_COLOR(&dev->var_info, 0, 0, 192),	/* blue */
+	};
+	const uint16_t colors_middle[] = {
+		FB_MAKE_COLOR(&dev->var_info, 0, 0, 192),	/* blue */
+		FB_MAKE_COLOR(&dev->var_info, 19, 19, 19),	/* black */
+		FB_MAKE_COLOR(&dev->var_info, 192, 0, 192),	/* magenta */
+		FB_MAKE_COLOR(&dev->var_info, 19, 19, 19),	/* black */
+		FB_MAKE_COLOR(&dev->var_info, 0, 192, 192),	/* cyan */
+		FB_MAKE_COLOR(&dev->var_info, 19, 19, 19),	/* black */
+		FB_MAKE_COLOR(&dev->var_info, 192, 192, 192),	/* grey */
+	};
+	const uint16_t colors_bottom[] = {
+		FB_MAKE_COLOR(&dev->var_info, 0, 33, 76),	/* in-phase */
+		FB_MAKE_COLOR(&dev->var_info, 255, 255, 255),	/* super white */
+		FB_MAKE_COLOR(&dev->var_info, 50, 0, 106),	/* quadrature */
+		FB_MAKE_COLOR(&dev->var_info, 19, 19, 19),	/* black */
+		FB_MAKE_COLOR(&dev->var_info, 9, 9, 9),		/* 3.5% */
+		FB_MAKE_COLOR(&dev->var_info, 19, 19, 19),	/* 7.5% */
+		FB_MAKE_COLOR(&dev->var_info, 29, 29, 29),	/* 11.5% */
+		FB_MAKE_COLOR(&dev->var_info, 19, 19, 19),	/* black */
+	};
+	void *mem = dev->mem + dev->fix_info.line_length * yoffset
+		  + xoffset * dev->var_info.bits_per_pixel / 8;
+	unsigned int x;
+	unsigned int y;
+
+	for (y = 0; y < yres * 6 / 9; ++y) {
+		for (x = 0; x < xres; ++x)
+			((uint16_t *)mem)[x] = colors_top[x * 7 / xres];
+		mem += dev->fix_info.line_length;
+	}
+
+	for (; y < yres * 7 / 9; ++y) {
+		for (x = 0; x < xres; ++x)
+			((uint16_t *)mem)[x] = colors_middle[x * 7 / xres];
+		mem += dev->fix_info.line_length;
+	}
+
+	for (; y < yres; ++y) {
+		for (x = 0; x < xres * 5 / 7; ++x)
+			((uint16_t *)mem)[x] +				colors_bottom[x * 4 / (xres * 5 / 7)];
+		for (; x < xres * 6 / 7; ++x)
+			((uint16_t *)mem)[x] +				colors_bottom[(x - xres * 5 / 7) * 3
+					      / (xres / 7) + 4];
+		for (; x < xres; ++x)
+			((uint16_t *)mem)[x] = colors_bottom[7];
+		mem += dev->fix_info.line_length;
+	}
+}
+
+struct fb_color24 {
+	unsigned int value:24;
+} __attribute__((__packed__));
+
+#define FB_MAKE_COLOR24(var, r, g, b) \
+	{ .value = FB_MAKE_COLOR(var, r, g, b) }
+
+static void
+fb_fill_rgb24(struct device *dev, unsigned int xoffset, unsigned int yoffset,
+	      unsigned int xres, unsigned int yres)
+{
+	const struct fb_color24 colors_top[] = {
+		FB_MAKE_COLOR24(&dev->var_info, 192, 192, 192),	/* grey */
+		FB_MAKE_COLOR24(&dev->var_info, 192, 192, 0),	/* yellow */
+		FB_MAKE_COLOR24(&dev->var_info, 0, 192, 192),	/* cyan */
+		FB_MAKE_COLOR24(&dev->var_info, 0, 192, 0),	/* green */
+		FB_MAKE_COLOR24(&dev->var_info, 192, 0, 192),	/* magenta */
+		FB_MAKE_COLOR24(&dev->var_info, 192, 0, 0),	/* red */
+		FB_MAKE_COLOR24(&dev->var_info, 0, 0, 192),	/* blue */
+	};
+	const struct fb_color24 colors_middle[] = {
+		FB_MAKE_COLOR24(&dev->var_info, 0, 0, 192),	/* blue */
+		FB_MAKE_COLOR24(&dev->var_info, 19, 19, 19),	/* black */
+		FB_MAKE_COLOR24(&dev->var_info, 192, 0, 192),	/* magenta */
+		FB_MAKE_COLOR24(&dev->var_info, 19, 19, 19),	/* black */
+		FB_MAKE_COLOR24(&dev->var_info, 0, 192, 192),	/* cyan */
+		FB_MAKE_COLOR24(&dev->var_info, 19, 19, 19),	/* black */
+		FB_MAKE_COLOR24(&dev->var_info, 192, 192, 192),	/* grey */
+	};
+	const struct fb_color24 colors_bottom[] = {
+		FB_MAKE_COLOR24(&dev->var_info, 0, 33, 76),	/* in-phase */
+		FB_MAKE_COLOR24(&dev->var_info, 255, 255, 255),	/* super white */
+		FB_MAKE_COLOR24(&dev->var_info, 50, 0, 106),	/* quadrature */
+		FB_MAKE_COLOR24(&dev->var_info, 19, 19, 19),	/* black */
+		FB_MAKE_COLOR24(&dev->var_info, 9, 9, 9),	/* 3.5% */
+		FB_MAKE_COLOR24(&dev->var_info, 19, 19, 19),	/* 7.5% */
+		FB_MAKE_COLOR24(&dev->var_info, 29, 29, 29),	/* 11.5% */
+		FB_MAKE_COLOR24(&dev->var_info, 19, 19, 19),	/* black */
+	};
+	void *mem = dev->mem + dev->fix_info.line_length * yoffset
+		  + xoffset * dev->var_info.bits_per_pixel / 8;
+	unsigned int x;
+	unsigned int y;
+
+	for (y = 0; y < yres * 6 / 9; ++y) {
+		for (x = 0; x < xres; ++x)
+			((struct fb_color24 *)mem)[x] +				colors_top[x * 7 / xres];
+		mem += dev->fix_info.line_length;
+	}
+
+	for (; y < yres * 7 / 9; ++y) {
+		for (x = 0; x < xres; ++x)
+			((struct fb_color24 *)mem)[x] +				colors_middle[x * 7 / xres];
+		mem += dev->fix_info.line_length;
+	}
+
+	for (; y < yres; ++y) {
+		for (x = 0; x < xres * 5 / 7; ++x)
+			((struct fb_color24 *)mem)[x] +				colors_bottom[x * 4 / (xres * 5 / 7)];
+		for (; x < xres * 6 / 7; ++x)
+			((struct fb_color24 *)mem)[x] +				colors_bottom[(x - xres * 5 / 7) * 3
+					      / (xres / 7) + 4];
+		for (; x < xres; ++x)
+			((struct fb_color24 *)mem)[x] = colors_bottom[7];
+		mem += dev->fix_info.line_length;
+	}
+}
+
+static void
+fb_fill_rgb32(struct device *dev, unsigned int xoffset, unsigned int yoffset,
+	      unsigned int xres, unsigned int yres)
+{
+	const uint32_t colors_top[] = {
+		FB_MAKE_COLOR(&dev->var_info, 192, 192, 192),	/* grey */
+		FB_MAKE_COLOR(&dev->var_info, 192, 192, 0),	/* yellow */
+		FB_MAKE_COLOR(&dev->var_info, 0, 192, 192),	/* cyan */
+		FB_MAKE_COLOR(&dev->var_info, 0, 192, 0),	/* green */
+		FB_MAKE_COLOR(&dev->var_info, 192, 0, 192),	/* magenta */
+		FB_MAKE_COLOR(&dev->var_info, 192, 0, 0),	/* red */
+		FB_MAKE_COLOR(&dev->var_info, 0, 0, 192),	/* blue */
+	};
+	const uint32_t colors_middle[] = {
+		FB_MAKE_COLOR(&dev->var_info, 0, 0, 192),	/* blue */
+		FB_MAKE_COLOR(&dev->var_info, 19, 19, 19),	/* black */
+		FB_MAKE_COLOR(&dev->var_info, 192, 0, 192),	/* magenta */
+		FB_MAKE_COLOR(&dev->var_info, 19, 19, 19),	/* black */
+		FB_MAKE_COLOR(&dev->var_info, 0, 192, 192),	/* cyan */
+		FB_MAKE_COLOR(&dev->var_info, 19, 19, 19),	/* black */
+		FB_MAKE_COLOR(&dev->var_info, 192, 192, 192),	/* grey */
+	};
+	const uint32_t colors_bottom[] = {
+		FB_MAKE_COLOR(&dev->var_info, 0, 33, 76),	/* in-phase */
+		FB_MAKE_COLOR(&dev->var_info, 255, 255, 255),	/* super white */
+		FB_MAKE_COLOR(&dev->var_info, 50, 0, 106),	/* quadrature */
+		FB_MAKE_COLOR(&dev->var_info, 19, 19, 19),	/* black */
+		FB_MAKE_COLOR(&dev->var_info, 9, 9, 9),		/* 3.5% */
+		FB_MAKE_COLOR(&dev->var_info, 19, 19, 19),	/* 7.5% */
+		FB_MAKE_COLOR(&dev->var_info, 29, 29, 29),	/* 11.5% */
+		FB_MAKE_COLOR(&dev->var_info, 19, 19, 19),	/* black */
+	};
+	void *mem = dev->mem + dev->fix_info.line_length * yoffset
+		  + xoffset * dev->var_info.bits_per_pixel / 8;
+	unsigned int x;
+	unsigned int y;
+
+	for (y = 0; y < yres * 6 / 9; ++y) {
+		for (x = 0; x < xres; ++x)
+			((uint32_t *)mem)[x] = colors_top[x * 7 / xres];
+		mem += dev->fix_info.line_length;
+	}
+
+	for (; y < yres * 7 / 9; ++y) {
+		for (x = 0; x < xres; ++x)
+			((uint32_t *)mem)[x] = colors_middle[x * 7 / xres];
+		mem += dev->fix_info.line_length;
+	}
+
+	for (; y < yres; ++y) {
+		for (x = 0; x < xres * 5 / 7; ++x)
+			((uint32_t *)mem)[x] +				colors_bottom[x * 4 / (xres * 5 / 7)];
+		for (; x < xres * 6 / 7; ++x)
+			((uint32_t *)mem)[x] +				colors_bottom[(x - xres * 5 / 7) * 3
+					      / (xres / 7) + 4];
+		for (; x < xres; ++x)
+			((uint32_t *)mem)[x] = colors_bottom[7];
+		mem += dev->fix_info.line_length;
+	}
+}
+
+/*
+ * fb_fill - Fill the frame buffer with an SMPTE test pattern
+ * @dev: FB device
+ * @mode: Fill mode
+ *
+ * Fill the display (when mode is FB_FILL_DISPLAY) or virtual frame buffer area
+ * (when mode is FB_FILL_VIRTUAL) with an SMPTE color bars pattern. Only RGB16,
+ * RGB24 and RGB32 on true color visuals are supported.
+ */
+static void fb_fill(struct device *dev, enum fb_fill_mode mode)
+{
+	unsigned int xoffset, yoffset;
+	unsigned int xres, yres;
+
+	if (dev->fix_info.visual != FB_VISUAL_TRUECOLOR) {
+		printf("Error: test pattern is only supported for true color "
+			"visuals.\n");
+		return;
+	}
+
+	printf("Filling frame buffer with SMPTE test pattern\n");
+
+	if (mode = FB_FILL_DISPLAY) {
+		xoffset = dev->var_info.xoffset;
+		yoffset = dev->var_info.yoffset;
+		xres = dev->var_info.xres;
+		yres = dev->var_info.yres;
+	} else {
+		xoffset = 0;
+		yoffset = 0;
+		xres = dev->var_info.xres_virtual;
+		yres = dev->var_info.yres_virtual;
+	}
+
+	switch (dev->var_info.bits_per_pixel) {
+	case 16:
+		return fb_fill_rgb16(dev, xoffset, yoffset, xres, yres);
+	case 24:
+		return fb_fill_rgb24(dev, xoffset, yoffset, xres, yres);
+	case 32:
+		return fb_fill_rgb32(dev, xoffset, yoffset, xres, yres);
+	default:
+		printf("Error: display depth %u bpp not supported.\n",
+			dev->var_info.bits_per_pixel);
+		break;
+	}
+}
+
+/* -----------------------------------------------------------------------------
+ * Main
+ */
+
+static void usage(const char *argv0)
+{
+	printf("Usage: %s [options] device\n", argv0);
+	printf("Supported options:\n");
+	printf("-b, --blank mode		Set blanking mode\n");
+	printf("-f, --fill[=mode]		Fill the frame buffer with a test pattern\n");
+	printf("-F, --format bpp		Set the number of bits per pixel\n");
+	printf("-h, --help			Show this help screen\n");
+	printf("-p, --pan x,y			Pan the display to position (x,y)\n");
+	printf("-r, --resolution wxh		Set the display resolution to width x height\n");
+	printf("-v, --virtual wxh		Set the display virtual resolution to width x height\n");
+	printf("-w, --wait-vsync[=screen]	Wait for VSync on the given screen\n");
+	printf("\n");
+	printf("Support fill modes are:\n");
+	printf("display		Fill the displayed frame buffer only\n");
+	printf("virtual		Fill the whole virtual frame buffer\n");
+	printf("Supported blanking modes are:\n");
+	printf(" off		Blanking off, screen active\n");
+	printf(" on		Blanked, HSync on,  VSync on\n");
+	printf(" vsync		Blanked, HSync on,  VSync off\n");
+	printf(" hsync		Blanked, HSync off, VSync on\n");
+	printf(" powerdown	Blanked, HSync off, VSync off\n");
+}
+
+static struct option opts[] = {
+	{"blank", 1, 0, 'b'},
+	{"fill", 2, 0, 'f'},
+	{"format", 1, 0, 'F'},
+	{"help", 0, 0, 'h'},
+	{"pan", 1, 0, 'p'},
+	{"resolution", 1, 0, 'r'},
+	{"virtual", 1, 0, 'v'},
+	{"wait-vsync", 2, 0, 'w'},
+	{0, 0, 0, 0}
+};
+
+static int fb_blank_parse(const char *arg, int *value)
+{
+	static const struct fb_value_name names[] = {
+		{ FB_BLANK_UNBLANK, "off" },
+		{ FB_BLANK_NORMAL, "on" },
+		{ FB_BLANK_VSYNC_SUSPEND, "vsync" },
+		{ FB_BLANK_HSYNC_SUSPEND, "hsync" },
+		{ FB_BLANK_POWERDOWN, "powerdown" },
+	};
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(names); ++i) {
+		if (strcmp(names[i].name, arg) = 0) {
+			*value = names[i].value;
+			return 0;
+		}
+	}
+
+	return -1;
+}
+
+static int fb_point_parse(const char *arg, unsigned int *x, unsigned int *y)
+{
+	unsigned long value;
+	char *endptr;
+
+	value = strtoul(arg, &endptr, 10);
+	if (endptr = arg || *endptr != ',')
+		return -1;
+	*x = value;
+	arg = endptr + 1;
+
+	value = strtoul(arg, &endptr, 10);
+	if (endptr = arg || *endptr != '\0')
+		return -1;
+	*y = value;
+
+	return 0;
+}
+
+static int fb_size_parse(const char *arg, int *x, int *y)
+{
+	unsigned long value;
+	char *endptr;
+
+	value = strtoul(arg, &endptr, 10);
+	if (endptr = arg || *endptr != 'x')
+		return -1;
+	*x = value;
+	arg = endptr + 1;
+
+	value = strtoul(arg, &endptr, 10);
+	if (endptr = arg || *endptr != '\0')
+		return -1;
+	*y = value;
+
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	struct device dev;
+	int ret;
+
+	/* Options parsing. */
+	bool do_blank = false;
+	int blank = 0;
+
+	enum fb_fill_mode fill_mode = FB_FILL_NONE;
+
+	bool do_format = false;
+	unsigned int bpp = 0;
+
+	bool do_pan = false;
+	unsigned int pan_x = 0;
+	unsigned int pan_y = 0;
+
+	bool do_resolution = false;
+	int xres = -1;
+	int yres = -1;
+	int xres_virtual = -1;
+	int yres_virtual = -1;
+
+	bool do_wait_for_vsync = false;
+	unsigned int screen = 0;
+
+	int c;
+
+	opterr = 0;
+	while ((c = getopt_long(argc, argv, "b:f::F:hp:r:v:w::", opts, NULL)) != -1) {
+
+		switch (c) {
+		case 'b':
+			do_blank = true;
+			if (fb_blank_parse(optarg, &blank) < 0) {
+				printf("Invalid blanking mode `%s'\n", optarg);
+				printf("Run %s -h for help.\n", argv[0]);
+				return 1;
+			}
+			break;
+		case 'f':
+			if (optarg = NULL)
+				fill_mode = FB_FILL_DISPLAY;
+			else if (strcmp(optarg, "display") = 0)
+				fill_mode = FB_FILL_DISPLAY;
+			else if (strcmp(optarg, "virtual") = 0)
+				fill_mode = FB_FILL_VIRTUAL;
+			else {
+				printf("Invalid fill mode `%s'\n", optarg);
+				printf("Run %s -h for help.\n", argv[0]);
+				return 1;
+			}
+			break;
+		case 'F':
+			do_format = true;
+			bpp = atoi(optarg);
+			break;
+		case 'h':
+			usage(argv[0]);
+			return 0;
+		case 'p':
+			do_pan = true;
+			if (fb_point_parse(optarg, &pan_x, &pan_y) < 0) {
+				printf("Invalid pan point `%s'\n", optarg);
+				printf("Run %s -h for help.\n", argv[0]);
+				return 1;
+			}
+			break;
+		case 'r':
+			do_resolution = true;
+			if (fb_size_parse(optarg, &xres, &yres) < 0) {
+				printf("Invalid resolution `%s'\n", optarg);
+				printf("Run %s -h for help.\n", argv[0]);
+				return 1;
+			}
+			break;
+		case 'v':
+			do_resolution = true;
+			if (fb_size_parse(optarg, &xres_virtual, &yres_virtual) < 0) {
+				printf("Invalid virtual resolution `%s'\n", optarg);
+				printf("Run %s -h for help.\n", argv[0]);
+				return 1;
+			}
+			break;
+		case 'w':
+			do_wait_for_vsync = true;
+			if (optarg)
+				screen = atoi(optarg);
+			break;
+		default:
+			printf("Invalid option -%c\n", c);
+			printf("Run %s -h for help.\n", argv[0]);
+			return 1;
+		}
+	}
+
+	if (optind >= argc) {
+		usage(argv[0]);
+		return 1;
+	}
+
+	ret = fb_open(&dev, argv[optind]);
+	if (ret < 0)
+		return 1;
+
+	if (do_blank)
+		fb_blank(&dev, blank);
+
+	if (do_format)
+		fb_set_format(&dev, bpp);
+
+	if (do_resolution)
+		fb_set_resolution(&dev, xres, yres, xres_virtual, yres_virtual);
+
+	if (fill_mode != FB_FILL_NONE)
+		fb_fill(&dev, fill_mode);
+
+	if (do_pan)
+		fb_pan(&dev, pan_x, pan_y);
+
+	if (do_wait_for_vsync)
+		fb_wait_for_vsync(&dev, screen);
+
+	fb_close(&dev);
+	return 0;
+}

-- 
Regards,

Laurent Pinchart

^ permalink raw reply

* Re: fbdev test application
From: Geert Uytterhoeven @ 2011-04-30 17:13 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <201104301643.23482.laurent.pinchart@ideasonboard.com>

On Sat, Apr 30, 2011 at 16:43, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> Hi everybody,
>
> I've developed a small fbdev application for internal test purpose that might
> be useful to other developers, so I'm releasing it under the GPL.

Have you ever looked at
http://git.kernel.org/?p=linux/kernel/git/geert/fbtest.git,
which is a git clone of CVS module FBdev/utlilities/fbtest of project
linux-fbdev on
sf.net?

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* Re: fbdev test application
From: Laurent Pinchart @ 2011-04-30 17:31 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <201104301643.23482.laurent.pinchart@ideasonboard.com>

Hi Geert,

On Saturday 30 April 2011 19:13:47 Geert Uytterhoeven wrote:
> On Sat, Apr 30, 2011 at 16:43, Laurent Pinchart
> 
> <laurent.pinchart@ideasonboard.com> wrote:
> > Hi everybody,
> > 
> > I've developed a small fbdev application for internal test purpose that
> > might be useful to other developers, so I'm releasing it under the GPL.
> 
> Have you ever looked at
> http://git.kernel.org/?p=linux/kernel/git/geert/fbtest.git,
> which is a git clone of CVS module FBdev/utlilities/fbtest of project
> linux-fbdev on sf.net?

I've seen the project, but my fbdev test application serves slightly different 
purposes, as I wanted to control FB devices from the command line, not run a 
test suite. It was also a way for me to learn the FB API, no existing 
application could have properly helped me there :-)

I see that fbtest.git hasn't been updated for quite some time. Do you think we 
should try to merge the projects ?

-- 
Regards,

Laurent Pinchart

^ permalink raw reply

* Re: fbdev test application
From: Geert Uytterhoeven @ 2011-04-30 18:30 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <201104301643.23482.laurent.pinchart@ideasonboard.com>

Hi Laurent,

On Sat, Apr 30, 2011 at 19:31, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> On Saturday 30 April 2011 19:13:47 Geert Uytterhoeven wrote:
>> On Sat, Apr 30, 2011 at 16:43, Laurent Pinchart
>> > I've developed a small fbdev application for internal test purpose that
>> > might be useful to other developers, so I'm releasing it under the GPL.
>>
>> Have you ever looked at
>> http://git.kernel.org/?p=linux/kernel/git/geert/fbtest.git,
>> which is a git clone of CVS module FBdev/utlilities/fbtest of project
>> linux-fbdev on sf.net?
>
> I've seen the project, but my fbdev test application serves slightly different
> purposes, as I wanted to control FB devices from the command line, not run a

Ah, so it's more like fbset.

> test suite. It was also a way for me to learn the FB API, no existing
> application could have properly helped me there :-)

IC...

> I see that fbtest.git hasn't been updated for quite some time. Do you think we
> should try to merge the projects ?

Perhaps, if you're willing to spend time on it. I don't think I can
work much on it
currently.

One big advantage of fbtest is that it knows how to draw on whatever
frame buffer
format and visual, while most fbdev apps support cfb8 in pseudocolor
and cfb32 in
truecolor only.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* [PATCH 0/2] OMAP: DSS: Support new dpi panels
From: Enric Balletbo i Serra @ 2011-05-02 10:29 UTC (permalink / raw)
  To: tomi.valkeinen, linux-omap, linux-fbdev; +Cc: Enric Balletbo i Serra

Hi all,

These patches add support for two new panels to the generic-dpi-panel.

The first patch adds support for the Seiko 70WVW1TZ3 LCD panel, and the second
adds support for the Powertip PH480272T LCD panel.

Tested with an IGEP v2 board.

Please consider to add in next merge window, thanks,

Enric Balletbo i Serra (2):
  OMAP: DSS2: Support for Seiko 70WVW1TZ3
  OMAP: DSS2: Support for Powertip PH480272T

 drivers/video/omap2/displays/panel-generic-dpi.c |   50 ++++++++++++++++++++++
 1 files changed, 50 insertions(+), 0 deletions(-)


^ permalink raw reply

* [PATCH 1/2] OMAP: DSS2: Support for Seiko 70WVW1TZ3
From: Enric Balletbo i Serra @ 2011-05-02 10:29 UTC (permalink / raw)
  To: tomi.valkeinen, linux-omap, linux-fbdev; +Cc: Enric Balletbo i Serra
In-Reply-To: <1304332184-14687-1-git-send-email-eballetbo@iseebcn.com>

Add support for Seiko 70WVW1TZ3, a LCD 7.0inch WVGA (800x480) display
type with 24-bit RGB interface and Touch-Panel, to panel-generic-dpi.

Signed-off-by: Enric Balletbo i Serra <eballetbo@iseebcn.com>
---
 drivers/video/omap2/displays/panel-generic-dpi.c |   25 ++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 4a9b9ff..e8819ee 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -181,6 +181,31 @@ static struct panel_config generic_dpi_panels[] = {
 		.power_off_delay	= 0,
 		.name			= "samsung_lte430wq_f0c",
 	},
+
+	/* Seiko 70WVW1TZ3Z3 */
+	{
+		{
+			.x_res		= 800,
+			.y_res		= 480,
+
+			.pixel_clock	= 33000,
+
+			.hsw		= 128,
+			.hfp		= 10,
+			.hbp		= 10,
+
+			.vsw		= 2,
+			.vfp		= 4,
+			.vbp		= 11,
+		},
+		.acbi			= 0x0,
+		.acb			= 0x0,
+		.config			= OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+						OMAP_DSS_LCD_IHS,
+		.power_on_delay		= 0,
+		.power_off_delay	= 0,
+		.name			= "70wvw1tz3",
+	},
 };
 
 struct panel_drv_data {
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 2/2] OMAP: DSS2: Support for Powertip PH480272T
From: Enric Balletbo i Serra @ 2011-05-02 10:29 UTC (permalink / raw)
  To: tomi.valkeinen, linux-omap, linux-fbdev; +Cc: Enric Balletbo i Serra
In-Reply-To: <1304332184-14687-1-git-send-email-eballetbo@iseebcn.com>

Add support for Powertip PH480242T, a LCD 4.3inch (480x242) display
type with 24-bit RGB interface, to panel-generic-dpi.

Signed-off-by: Enric Balletbo i Serra <eballetbo@iseebcn.com>
---
 drivers/video/omap2/displays/panel-generic-dpi.c |   25 ++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index e8819ee..3250a85 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -206,6 +206,31 @@ static struct panel_config generic_dpi_panels[] = {
 		.power_off_delay	= 0,
 		.name			= "70wvw1tz3",
 	},
+
+	/* Powertip PH480272T */
+	{
+		{
+			.x_res		= 480,
+			.y_res		= 272,
+
+			.pixel_clock	= 9000,
+
+			.hsw		= 40,
+			.hfp		= 2,
+			.hbp		= 2,
+
+			.vsw		= 10,
+			.vfp		= 2,
+			.vbp		= 2,
+		},
+		.acbi			= 0x0,
+		.acb			= 0x0,
+		.config			= OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+					  OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IEO,
+		.power_on_delay		= 0,
+		.power_off_delay	= 0,
+		.name			= "ph480272t",
+	},
 };
 
 struct panel_drv_data {
-- 
1.7.0.4


^ permalink raw reply related

* Query: Implementation of overlay on linux
From: vipul kumar samar @ 2011-05-02 11:16 UTC (permalink / raw)
  To: linux-media, linux-fbdev
In-Reply-To: <4DB6CE44.2020000@st.com>

Hello,

I am working on LCD module and I want to implement two overlay windows
on frame buffer. I have some queries related to this:

1. Can any body suggest me how to proceed towards it??
2. Is their any standard way to use frame buffer ioctl calls??
3. If i have to define my own ioctls then how application manage it??


Thanks and Regards
Vipul Samar

^ permalink raw reply

* Re: Query: Implementation of overlay on linux
From: Hans Verkuil @ 2011-05-02 13:20 UTC (permalink / raw)
  To: vipul kumar samar; +Cc: linux-media, linux-fbdev
In-Reply-To: <4DBE8FDB.5010506@st.com>

On Monday, May 02, 2011 13:04:59 vipul kumar samar wrote:
> Hello,
> 
> I am working on LCD module and I want to implement two overlay windows
> on frame buffer. I have some queries related to this:

You mean capture overlay windows? E.g. you want to capture from a video input 
and have the video directly rendered in the framebuffer?

The "Video Overlay Interface" section in the V4L2 specification describes how 
to do that, but it also depends on whether the V4L2 driver in question 
supports that feature.

It might be that you mean something else, though.

Regards,

	Hans

> 1. Can any body suggest me how to proceed towards it??
> 2. Is their any standard way to use frame buffer ioctl calls??
> 3. If i have to define my own ioctls then how application manage it??
> 
> 
> Thanks and Regards
> Vipul Samar
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 

^ permalink raw reply

* Login prompt on a video console instead of serial port?
From: Timur Tabi @ 2011-05-02 19:30 UTC (permalink / raw)
  To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, devicetree-discuss,
	linux-fbdev-u79uwXL29TY76Z2rM5mHXA

I'm using a Freescale P1022DS (PowerPC e500 core) system, which has a built-in
video controller.  I have a framebuffer driver that works fine, and if I add
"video=fslfb:1280x1024-32@60,monitor=0 console=tty0" to the command-line, then
*most* of the kernel boot log appears on the serial port and the video display.

However, the login prompt is always on the serial port.  This happens even if I
delete the "console=ttyS0,115200" from the command-line.  I presume this is
because the "linux,stdout-path" property in the device tree always points to a
serial port node.

So my question is: what do I need to do get the login prompt on the video
console?  That is, stdout goes to /dev/fb0 but stdin is still from /dev/ttyS0.
I presume I need to direct "linux,stdout-path" to the fslfb node in the device
tree, but there doesn't appear to be support for "linux,stdin-path".

-- 
Timur Tabi
Linux kernel developer at Freescale


^ permalink raw reply

* Re: Login prompt on a video console instead of serial port?
From: McClintock Matthew-B29882 @ 2011-05-02 19:55 UTC (permalink / raw)
  To: Tabi Timur-B04825
  Cc: linux-fbdev@vger.kernel.org, devicetree-discuss,
	linuxppc-dev@lists.ozlabs.org
In-Reply-To: <4DBF065C.3030407@freescale.com>

Don't you have to spawn a terminal on the framebuffer for the login?
Right now getty spawns the login on the serial port via /etc/inittab.
Something similiar is probably needed for the framebuffer.

-M



On Mon, May 2, 2011 at 2:30 PM, Timur Tabi <timur@freescale.com> wrote:
> I'm using a Freescale P1022DS (PowerPC e500 core) system, which has a built-in
> video controller.  I have a framebuffer driver that works fine, and if I add
> "video=fslfb:1280x1024-32@60,monitor=0 console=tty0" to the command-line, then
> *most* of the kernel boot log appears on the serial port and the video display.
>
> However, the login prompt is always on the serial port.  This happens even if I
> delete the "console=ttyS0,115200" from the command-line.  I presume this is
> because the "linux,stdout-path" property in the device tree always points to a
> serial port node.
>
> So my question is: what do I need to do get the login prompt on the video
> console?  That is, stdout goes to /dev/fb0 but stdin is still from /dev/ttyS0.
> I presume I need to direct "linux,stdout-path" to the fslfb node in the device
> tree, but there doesn't appear to be support for "linux,stdin-path".

^ permalink raw reply

* Re: Login prompt on a video console instead of serial port?
From: Timur Tabi @ 2011-05-02 20:02 UTC (permalink / raw)
  To: McClintock Matthew-B29882
  Cc: devicetree-discuss, linuxppc-dev@lists.ozlabs.org,
	linux-fbdev@vger.kernel.org
In-Reply-To: <BANLkTikWMksVsvs8KzjdiZfRR-2WGD0Ftw@mail.gmail.com>

McClintock Matthew-B29882 wrote:
> Don't you have to spawn a terminal on the framebuffer for the login?

I suppose, but I don't know how to do that.  And although that would technically
answer the question in the subject of this thread, I still would have *some*
boot output on the serial port.  It would be nice if I could get all of stdout
on the video display, and all of stdin from the serial port.

> Right now getty spawns the login on the serial port via /etc/inittab.
> Something similiar is probably needed for the framebuffer.

getty appears to work only with serial devices, since it insists on a baud rate
as one of the parameters.

-- 
Timur Tabi
Linux kernel developer at Freescale


^ permalink raw reply

* Re: Login prompt on a video console instead of serial port?
From: Grant Likely @ 2011-05-02 20:12 UTC (permalink / raw)
  To: Timur Tabi; +Cc: linux-fbdev, devicetree-discuss, linuxppc-dev
In-Reply-To: <4DBF065C.3030407@freescale.com>

On Mon, May 2, 2011 at 1:30 PM, Timur Tabi <timur@freescale.com> wrote:
> I'm using a Freescale P1022DS (PowerPC e500 core) system, which has a built-in
> video controller.  I have a framebuffer driver that works fine, and if I add
> "video=fslfb:1280x1024-32@60,monitor=0 console=tty0" to the command-line, then
> *most* of the kernel boot log appears on the serial port and the video display.
>
> However, the login prompt is always on the serial port.  This happens even if I
> delete the "console=ttyS0,115200" from the command-line.  I presume this is
> because the "linux,stdout-path" property in the device tree always points to a
> serial port node.
>
> So my question is: what do I need to do get the login prompt on the video
> console?  That is, stdout goes to /dev/fb0 but stdin is still from /dev/ttyS0.
> I presume I need to direct "linux,stdout-path" to the fslfb node in the device
> tree, but there doesn't appear to be support for "linux,stdin-path".

Look in /etc/inittab.  That's usually where the login gettys are specified.

g.

>
> --
> Timur Tabi
> Linux kernel developer at Freescale
>
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
>



-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* Re: [PATCH v6 0/6] powerpc, 52xx: add charon board support
From: Grant Likely @ 2011-05-02 22:14 UTC (permalink / raw)
  To: Heiko Schocher
  Cc: linuxppc-dev, Wolfram Sang, Benjamin Herrenschmidt, linux-fbdev,
	devicetree-discuss, Ben Dooks, Vincent Sanders, Samuel Ortiz,
	linux-kernel, Randy Dunlap, Wolfgang Denk, Paul Mundt
In-Reply-To: <1300782452-528-1-git-send-email-hs@denx.de>

On Tue, Mar 22, 2011 at 09:27:26AM +0100, Heiko Schocher wrote:
> cc: Wolfram Sang <w.sang@pengutronix.de>
> cc: Grant Likely <grant.likely@secretlab.ca>
> cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> 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: Wolfgang Denk <wd@denx.de>
> cc: Paul Mundt <lethal@linux-sh.org>
> 
> changes since v5:
> - repost complete patchseries, as Paul Mundt suggested
> - rebased against current head
> - add Acked-by from Samuel Ortiz (MFD parts)
>   http://www.spinics.net/lists/linux-fbdev/msg02550.html
>   http://linux.derkeiler.com/Mailing-Lists/Kernel/2011-01/msg11798.html
> 
>   and Benjamin Herrenschmidt (DTS parts)
>   http://lists.ozlabs.org/pipermail/linuxppc-dev/2011-February/088279.html
> - removed patch 
>   "powerpc, mpc5200: update mpc5200_defconfig to fit for charon board."
>   therefore added
>   "powerpc, tqm5200: update tqm5200_defconfig to fit for charon board."

Refresh my memory, why was the mpc5200_defconfig updated dropped?

g.


^ permalink raw reply

* Re: [PATCH v6 2/6] video, sm501: add I/O functions for use on powerpc
From: Grant Likely @ 2011-05-02 22:24 UTC (permalink / raw)
  To: Heiko Schocher
  Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, Samuel Ortiz,
	Vincent Sanders, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Ben Dooks,
	Randy Dunlap, Paul Mundt, linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
	Wolfgang Denk
In-Reply-To: <1300782452-528-3-git-send-email-hs-ynQEQJNshbs@public.gmane.org>

On Tue, Mar 22, 2011 at 09:27:28AM +0100, Heiko Schocher wrote:
> - add read/write functions for using this driver
>   also on powerpc plattforms
> 
> Signed-off-by: Heiko Schocher <hs@denx.de>
> Acked-by: Samuel Ortiz <sameo@linux.intel.com>

Merged, thanks.

g.

> cc: Wolfram Sang <w.sang@pengutronix.de>
> cc: Grant Likely <grant.likely@secretlab.ca>
> cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> 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: Wolfgang Denk <wd@denx.de>
> 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
> - changes for v6:
>   - repost complete patchserie
>   - rebased against current head
> 
>  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 bcb44a5..5df406c 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.4
> 

^ permalink raw reply

* Re: [PATCH v6 3/6] video, sm501: add edid and commandline support
From: Grant Likely @ 2011-05-02 22:27 UTC (permalink / raw)
  To: Heiko Schocher
  Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, Samuel Ortiz,
	Vincent Sanders, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Ben Dooks,
	Randy Dunlap, Paul Mundt, linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ,
	Wolfgang Denk
In-Reply-To: <1300782452-528-4-git-send-email-hs-ynQEQJNshbs@public.gmane.org>

On Tue, Mar 22, 2011 at 09:27:29AM +0100, Heiko Schocher wrote:
> - 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>

Merged, thanks.

g.

> cc: Wolfram Sang <w.sang@pengutronix.de>
> cc: Grant Likely <grant.likely@secretlab.ca>
> cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> 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: Wolfgang Denk <wd@denx.de>
> cc: Paul Mundt <lethal@linux-sh.org>
> ---
> - changes since v1:
>   add Ben Dooks, Vincent Sanders and Samuel Ortiz to cc, as suggested from
>   Paul Mundt.
> - changes since v2:
>   add comments from Randy Dunlap:
>   - move parameter documentation to Documentation/fb/sm501.txt
> - changes since v3:
>   - rebased against v2.6.38-rc2
>   - split in 3 patches
>     - of support patch
>     - i/o routine patch
>     - edid support patch
> - changes since v4:
>   - add "info->pdata = &sm501fb_def_pdata;" in sm501fb_probe()
>     as Paul Mundt suggested (and I wrongly deleted)
>   - move kfree(info->edid_data); to patch 3/4
>     as edid_data is only allocated in the CONFIG_OF case
> - changes for v6:
>   - repost complete patchserie
>   - rebased against current head
> 
>  Documentation/fb/sm501.txt |   10 +++++++
>  drivers/video/sm501fb.c    |   65 ++++++++++++++++++++++++++++++++++++++++---
>  2 files changed, 70 insertions(+), 5 deletions(-)
>  create mode 100644 Documentation/fb/sm501.txt
> 
> diff --git a/Documentation/fb/sm501.txt b/Documentation/fb/sm501.txt
> new file mode 100644
> index 0000000..8d17aeb
> --- /dev/null
> +++ b/Documentation/fb/sm501.txt
> @@ -0,0 +1,10 @@
> +Configuration:
> +
> +You can pass the following kernel command line options to sm501 videoframebuffer:
> +
> +	sm501fb.bpp=	SM501 Display driver:
> +			Specifiy bits-per-pixel if not specified by 'mode'
> +
> +	sm501fb.mode=	SM501 Display driver:
> +			Specify resolution as
> +			"<xres>x<yres>[-<bpp>][@<refresh>]"
> diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
> index 5df406c..f31252c 100644
> --- a/drivers/video/sm501fb.c
> +++ b/drivers/video/sm501fb.c
> @@ -41,6 +41,26 @@
>  #include <linux/sm501.h>
>  #include <linux/sm501-regs.h>
>  
> +#include "edid.h"
> +
> +static char *fb_mode = "640x480-16@60";
> +static unsigned long default_bpp = 16;
> +
> +static struct fb_videomode __devinitdata sm501_default_mode = {
> +	.refresh	= 60,
> +	.xres		= 640,
> +	.yres		= 480,
> +	.pixclock	= 20833,
> +	.left_margin	= 142,
> +	.right_margin	= 13,
> +	.upper_margin	= 21,
> +	.lower_margin	= 1,
> +	.hsync_len	= 69,
> +	.vsync_len	= 3,
> +	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
> +	.vmode		= FB_VMODE_NONINTERLACED
> +};
> +
>  #define NR_PALETTE	256
>  
>  enum sm501_controller {
> @@ -77,6 +97,7 @@ struct sm501fb_info {
>  	void __iomem		*regs2d;	/* 2d remapped registers */
>  	void __iomem		*fbmem;		/* remapped framebuffer */
>  	size_t			 fbmem_len;	/* length of remapped region */
> +	u8 *edid_data;
>  };
>  
>  /* per-framebuffer private data */
> @@ -1725,9 +1746,16 @@ static int sm501fb_init_fb(struct fb_info *fb,
>  	fb->var.vmode		= FB_VMODE_NONINTERLACED;
>  	fb->var.bits_per_pixel  = 16;
>  
> +	if (info->edid_data) {
> +			/* Now build modedb from EDID */
> +			fb_edid_to_monspecs(info->edid_data, &fb->monspecs);
> +			fb_videomode_to_modelist(fb->monspecs.modedb,
> +						 fb->monspecs.modedb_len,
> +						 &fb->modelist);
> +	}
> +
>  	if (enable && (pd->flags & SM501FB_FLAG_USE_INIT_MODE) && 0) {
>  		/* TODO read the mode from the current display */
> -
>  	} else {
>  		if (pd->def_mode) {
>  			dev_info(info->dev, "using supplied mode\n");
> @@ -1737,12 +1765,34 @@ static int sm501fb_init_fb(struct fb_info *fb,
>  			fb->var.xres_virtual = fb->var.xres;
>  			fb->var.yres_virtual = fb->var.yres;
>  		} else {
> -			ret = fb_find_mode(&fb->var, fb,
> +			if (info->edid_data)
> +				ret = fb_find_mode(&fb->var, fb, fb_mode,
> +					fb->monspecs.modedb,
> +					fb->monspecs.modedb_len,
> +					&sm501_default_mode, default_bpp);
> +			else
> +				ret = fb_find_mode(&fb->var, fb,
>  					   NULL, NULL, 0, NULL, 8);
>  
> -			if (ret = 0 || ret = 4) {
> -				dev_err(info->dev,
> -					"failed to get initial mode\n");
> +			switch (ret) {
> +			case 1:
> +				dev_info(info->dev, "using mode specified in "
> +						"@mode\n");
> +				break;
> +			case 2:
> +				dev_info(info->dev, "using mode specified in "
> +					"@mode with ignored refresh rate\n");
> +				break;
> +			case 3:
> +				dev_info(info->dev, "using mode default "
> +					"mode\n");
> +				break;
> +			case 4:
> +				dev_info(info->dev, "using mode from list\n");
> +				break;
> +			default:
> +				dev_info(info->dev, "ret = %d\n", ret);
> +				dev_info(info->dev, "failed to find mode\n");
>  				return -EINVAL;
>  			}
>  		}
> @@ -2157,6 +2207,11 @@ static void __exit sm501fb_cleanup(void)
>  module_init(sm501fb_init);
>  module_exit(sm501fb_cleanup);
>  
> +module_param_named(mode, fb_mode, charp, 0);
> +MODULE_PARM_DESC(mode,
> +	"Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
> +module_param_named(bpp, default_bpp, ulong, 0);
> +MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode");
>  MODULE_AUTHOR("Ben Dooks, Vincent Sanders");
>  MODULE_DESCRIPTION("SM501 Framebuffer driver");
>  MODULE_LICENSE("GPL v2");
> -- 
> 1.7.4
> 

^ permalink raw reply

* Re: [PATCH v6 4/6] video, sm501: add OF binding to support SM501
From: Grant Likely @ 2011-05-02 22:28 UTC (permalink / raw)
  To: Heiko Schocher
  Cc: linuxppc-dev, Wolfram Sang, Benjamin Herrenschmidt, linux-fbdev,
	devicetree-discuss, Ben Dooks, Vincent Sanders, Samuel Ortiz,
	linux-kernel, Randy Dunlap, Wolfgang Denk, Paul Mundt
In-Reply-To: <1300782452-528-5-git-send-email-hs@denx.de>

On Tue, Mar 22, 2011 at 09:27:30AM +0100, Heiko Schocher wrote:
> - add binding to OF, compatible name "smi,sm501"
> 
> Signed-off-by: Heiko Schocher <hs@denx.de>
> Acked-by: Samuel Ortiz <sameo@linux.intel.com>

Merged, thanks.

g.

> cc: Wolfram Sang <w.sang@pengutronix.de>
> cc: Grant Likely <grant.likely@secretlab.ca>
> cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> 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: Wolfgang Denk <wd@denx.de>
> cc: Paul Mundt <lethal@linux-sh.org>
> ---
> - changes since v1:
>   add Ben Dooks, Vincent Sanders and Samuel Ortiz to cc, as suggested from
>   Paul Mundt.
> - changes since v2:
>   add comments from Randy Dunlap:
>   - move parameter documentation to Documentation/fb/sm501.txt
> - changes since v3:
>   - rebased against v2.6.38-rc2
>   - split in 3 patches
>     - of support patch
>       - get rid of "#if defined(CONFIG_PPC_MPC52xx)" usage
>         hide this in DTS, as Paul suggested.
>     - i/o routine patch
>     - edid support patch
> - changes since v4
>   replace remaining CONFIG_PPC_MPC52xx with CONFIG_OF, as
>   it is no longer MPC52xx only.
> - changes since v5
>   free edid_data after its usage, as it is no longer needed,
>   suggested from Paul Mundt. Also fall back to default if
>   kmemdup(edid_data) fails.
> - changes for v6:
>   - repost complete patchserie
>   - rebased against current head
> 
>  Documentation/powerpc/dts-bindings/sm501.txt |   34 +++++++++++++++++++++++++
>  drivers/mfd/sm501.c                          |    8 +++++-
>  drivers/video/sm501fb.c                      |   35 +++++++++++++++++++++++++-
>  3 files changed, 75 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..574f696 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
> @@ -1735,10 +1735,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 f31252c..f275385 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;
> @@ -1933,8 +1942,32 @@ static int __devinit sm501fb_probe(struct platform_device *pdev)
>  	}
>  
>  	if (info->pdata = NULL) {
> -		dev_info(dev, "using default configuration data\n");
> +		int found = 0;
> +#if defined(CONFIG_OF)
> +		struct device_node *np = pdev->dev.parent->of_node;
> +		const u8 *prop;
> +		const char *cp;
> +		int len;
> +
>  		info->pdata = &sm501fb_def_pdata;
> +		if (np) {
> +			/* Get EDID */
> +			cp = of_get_property(np, "mode", &len);
> +			if (cp)
> +				strcpy(fb_mode, cp);
> +			prop = of_get_property(np, "edid", &len);
> +			if (prop && len = EDID_LENGTH) {
> +				info->edid_data = kmemdup(prop, EDID_LENGTH,
> +							  GFP_KERNEL);
> +				if (info->edid_data)
> +					found = 1;
> +			}
> +		}
> +#endif
> +		if (!found) {
> +			dev_info(dev, "using default configuration data\n");
> +			info->pdata = &sm501fb_def_pdata;
> +		}
>  	}
>  
>  	/* probe for the presence of each panel */
> -- 
> 1.7.4
> 

^ permalink raw reply

* Re: [PATCH v6 6/6] powerpc, tqm5200: update tqm5200_defconfig to fit
From: Grant Likely @ 2011-05-02 22:31 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: Heiko Schocher, linuxppc-dev, Benjamin Herrenschmidt, linux-fbdev,
	devicetree-discuss, Ben Dooks, Vincent Sanders, Samuel Ortiz,
	linux-kernel, Randy Dunlap, Wolfgang Denk, Paul Mundt
In-Reply-To: <20110322091027.GC2134@pengutronix.de>

On Tue, Mar 22, 2011 at 10:10:27AM +0100, Wolfram Sang wrote:
> >     As this board is tqm5200 based, added necessary changes
> >     to the tqm5200_defconfig. In previous patchserie I added
> >     the changes to mpc5200_defconfig, as Wolfram Sang mentioned,
> >     but as tqm5200_defconfig is in mainline, and the board is
> >     tqm5200 based, I think, thats the appropriate place, as
> 
> I'd think the perfect solution would have been to merge the
> tqm-defconfig into the mpc5200-defconfig entirely and get rid of it.
> That being said, I don't think this issue is big enough to block this
> series, so fine enough with me.

Merged, thanks.

g.




^ permalink raw reply

* Re: [PATCH v6 3/6] video, sm501: add edid and commandline support
From: Grant Likely @ 2011-05-02 22:37 UTC (permalink / raw)
  To: Heiko Schocher
  Cc: linuxppc-dev, Wolfram Sang, Benjamin Herrenschmidt, linux-fbdev,
	devicetree-discuss, Ben Dooks, Vincent Sanders, Samuel Ortiz,
	linux-kernel, Randy Dunlap, Wolfgang Denk, Paul Mundt
In-Reply-To: <20110502222716.GB15187@ponder.secretlab.ca>

On Mon, May 2, 2011 at 4:27 PM, Grant Likely <grant.likely@secretlab.ca> wrote:
> On Tue, Mar 22, 2011 at 09:27:29AM +0100, Heiko Schocher wrote:
>> - 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>
>
> Merged, thanks.

This patch causes the following build warning:

  MODPOST vmlinux.o
WARNING: vmlinux.o(.text+0x1d5572): Section mismatch in reference from
the function sm501fb_init_fb() to the variable
.devinit.data:sm501_default_mode
The function sm501fb_init_fb() references
the variable __devinitdata sm501_default_mode.
This is often because sm501fb_init_fb lacks a __devinitdata
annotation or the annotation of sm501_default_mode is wrong.

WARNING: vmlinux.o(.text+0x1d557a): Section mismatch in reference from
the function sm501fb_init_fb() to the variable
.devinit.data:sm501_default_mode
The function sm501fb_init_fb() references
the variable __devinitdata sm501_default_mode.
This is often because sm501fb_init_fb lacks a __devinitdata
annotation or the annotation of sm501_default_mode is wrong.

I've dropped the __devinitdata declaration in what I committed; can
you investigate and post a fixup patch?

>
> g.
>
>> cc: Wolfram Sang <w.sang@pengutronix.de>
>> cc: Grant Likely <grant.likely@secretlab.ca>
>> cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> 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: Wolfgang Denk <wd@denx.de>
>> cc: Paul Mundt <lethal@linux-sh.org>
>> ---
>> - changes since v1:
>>   add Ben Dooks, Vincent Sanders and Samuel Ortiz to cc, as suggested from
>>   Paul Mundt.
>> - changes since v2:
>>   add comments from Randy Dunlap:
>>   - move parameter documentation to Documentation/fb/sm501.txt
>> - changes since v3:
>>   - rebased against v2.6.38-rc2
>>   - split in 3 patches
>>     - of support patch
>>     - i/o routine patch
>>     - edid support patch
>> - changes since v4:
>>   - add "info->pdata = &sm501fb_def_pdata;" in sm501fb_probe()
>>     as Paul Mundt suggested (and I wrongly deleted)
>>   - move kfree(info->edid_data); to patch 3/4
>>     as edid_data is only allocated in the CONFIG_OF case
>> - changes for v6:
>>   - repost complete patchserie
>>   - rebased against current head
>>
>>  Documentation/fb/sm501.txt |   10 +++++++
>>  drivers/video/sm501fb.c    |   65 ++++++++++++++++++++++++++++++++++++++++---
>>  2 files changed, 70 insertions(+), 5 deletions(-)
>>  create mode 100644 Documentation/fb/sm501.txt
>>
>> diff --git a/Documentation/fb/sm501.txt b/Documentation/fb/sm501.txt
>> new file mode 100644
>> index 0000000..8d17aeb
>> --- /dev/null
>> +++ b/Documentation/fb/sm501.txt
>> @@ -0,0 +1,10 @@
>> +Configuration:
>> +
>> +You can pass the following kernel command line options to sm501 videoframebuffer:
>> +
>> +     sm501fb.bpp=    SM501 Display driver:
>> +                     Specifiy bits-per-pixel if not specified by 'mode'
>> +
>> +     sm501fb.mode=   SM501 Display driver:
>> +                     Specify resolution as
>> +                     "<xres>x<yres>[-<bpp>][@<refresh>]"
>> diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
>> index 5df406c..f31252c 100644
>> --- a/drivers/video/sm501fb.c
>> +++ b/drivers/video/sm501fb.c
>> @@ -41,6 +41,26 @@
>>  #include <linux/sm501.h>
>>  #include <linux/sm501-regs.h>
>>
>> +#include "edid.h"
>> +
>> +static char *fb_mode = "640x480-16@60";
>> +static unsigned long default_bpp = 16;
>> +
>> +static struct fb_videomode __devinitdata sm501_default_mode = {
>> +     .refresh        = 60,
>> +     .xres           = 640,
>> +     .yres           = 480,
>> +     .pixclock       = 20833,
>> +     .left_margin    = 142,
>> +     .right_margin   = 13,
>> +     .upper_margin   = 21,
>> +     .lower_margin   = 1,
>> +     .hsync_len      = 69,
>> +     .vsync_len      = 3,
>> +     .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
>> +     .vmode          = FB_VMODE_NONINTERLACED
>> +};
>> +
>>  #define NR_PALETTE   256
>>
>>  enum sm501_controller {
>> @@ -77,6 +97,7 @@ struct sm501fb_info {
>>       void __iomem            *regs2d;        /* 2d remapped registers */
>>       void __iomem            *fbmem;         /* remapped framebuffer */
>>       size_t                   fbmem_len;     /* length of remapped region */
>> +     u8 *edid_data;
>>  };
>>
>>  /* per-framebuffer private data */
>> @@ -1725,9 +1746,16 @@ static int sm501fb_init_fb(struct fb_info *fb,
>>       fb->var.vmode           = FB_VMODE_NONINTERLACED;
>>       fb->var.bits_per_pixel  = 16;
>>
>> +     if (info->edid_data) {
>> +                     /* Now build modedb from EDID */
>> +                     fb_edid_to_monspecs(info->edid_data, &fb->monspecs);
>> +                     fb_videomode_to_modelist(fb->monspecs.modedb,
>> +                                              fb->monspecs.modedb_len,
>> +                                              &fb->modelist);
>> +     }
>> +
>>       if (enable && (pd->flags & SM501FB_FLAG_USE_INIT_MODE) && 0) {
>>               /* TODO read the mode from the current display */
>> -
>>       } else {
>>               if (pd->def_mode) {
>>                       dev_info(info->dev, "using supplied mode\n");
>> @@ -1737,12 +1765,34 @@ static int sm501fb_init_fb(struct fb_info *fb,
>>                       fb->var.xres_virtual = fb->var.xres;
>>                       fb->var.yres_virtual = fb->var.yres;
>>               } else {
>> -                     ret = fb_find_mode(&fb->var, fb,
>> +                     if (info->edid_data)
>> +                             ret = fb_find_mode(&fb->var, fb, fb_mode,
>> +                                     fb->monspecs.modedb,
>> +                                     fb->monspecs.modedb_len,
>> +                                     &sm501_default_mode, default_bpp);
>> +                     else
>> +                             ret = fb_find_mode(&fb->var, fb,
>>                                          NULL, NULL, 0, NULL, 8);
>>
>> -                     if (ret = 0 || ret = 4) {
>> -                             dev_err(info->dev,
>> -                                     "failed to get initial mode\n");
>> +                     switch (ret) {
>> +                     case 1:
>> +                             dev_info(info->dev, "using mode specified in "
>> +                                             "@mode\n");
>> +                             break;
>> +                     case 2:
>> +                             dev_info(info->dev, "using mode specified in "
>> +                                     "@mode with ignored refresh rate\n");
>> +                             break;
>> +                     case 3:
>> +                             dev_info(info->dev, "using mode default "
>> +                                     "mode\n");
>> +                             break;
>> +                     case 4:
>> +                             dev_info(info->dev, "using mode from list\n");
>> +                             break;
>> +                     default:
>> +                             dev_info(info->dev, "ret = %d\n", ret);
>> +                             dev_info(info->dev, "failed to find mode\n");
>>                               return -EINVAL;
>>                       }
>>               }
>> @@ -2157,6 +2207,11 @@ static void __exit sm501fb_cleanup(void)
>>  module_init(sm501fb_init);
>>  module_exit(sm501fb_cleanup);
>>
>> +module_param_named(mode, fb_mode, charp, 0);
>> +MODULE_PARM_DESC(mode,
>> +     "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
>> +module_param_named(bpp, default_bpp, ulong, 0);
>> +MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode");
>>  MODULE_AUTHOR("Ben Dooks, Vincent Sanders");
>>  MODULE_DESCRIPTION("SM501 Framebuffer driver");
>>  MODULE_LICENSE("GPL v2");
>> --
>> 1.7.4
>>
>



-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* Re: [PATCH v6 0/6] powerpc, 52xx: add charon board support
From: Heiko Schocher @ 2011-05-03  5:17 UTC (permalink / raw)
  To: Grant Likely
  Cc: linuxppc-dev, Wolfram Sang, Benjamin Herrenschmidt, linux-fbdev,
	devicetree-discuss, Ben Dooks, Vincent Sanders, Samuel Ortiz,
	linux-kernel, Randy Dunlap, Wolfgang Denk, Paul Mundt
In-Reply-To: <20110502221406.GA15043@ponder.secretlab.ca>

Hello Grant,

Grant Likely wrote:
> On Tue, Mar 22, 2011 at 09:27:26AM +0100, Heiko Schocher wrote:
>> cc: Wolfram Sang <w.sang@pengutronix.de>
>> cc: Grant Likely <grant.likely@secretlab.ca>
>> cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> 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: Wolfgang Denk <wd@denx.de>
>> cc: Paul Mundt <lethal@linux-sh.org>
>>
>> changes since v5:
>> - repost complete patchseries, as Paul Mundt suggested
>> - rebased against current head
>> - add Acked-by from Samuel Ortiz (MFD parts)
>>   http://www.spinics.net/lists/linux-fbdev/msg02550.html
>>   http://linux.derkeiler.com/Mailing-Lists/Kernel/2011-01/msg11798.html
>>
>>   and Benjamin Herrenschmidt (DTS parts)
>>   http://lists.ozlabs.org/pipermail/linuxppc-dev/2011-February/088279.html
>> - removed patch 
>>   "powerpc, mpc5200: update mpc5200_defconfig to fit for charon board."
>>   therefore added
>>   "powerpc, tqm5200: update tqm5200_defconfig to fit for charon board."
> 
> Refresh my memory, why was the mpc5200_defconfig updated dropped?

Because it is a board based on the tqm5200 board port ... no other
reason.

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 v6 3/6] video, sm501: add edid and commandline support
From: Heiko Schocher @ 2011-05-03  5:27 UTC (permalink / raw)
  To: Grant Likely
  Cc: linuxppc-dev, Wolfram Sang, Benjamin Herrenschmidt, linux-fbdev,
	devicetree-discuss, Ben Dooks, Vincent Sanders, Samuel Ortiz,
	linux-kernel, Randy Dunlap, Wolfgang Denk, Paul Mundt
In-Reply-To: <BANLkTik3L28mmL=LGZ_0nV7vSOX9Miw3ow@mail.gmail.com>

Hello Grant,

Grant Likely wrote:
> On Mon, May 2, 2011 at 4:27 PM, Grant Likely <grant.likely@secretlab.ca> wrote:
>> On Tue, Mar 22, 2011 at 09:27:29AM +0100, Heiko Schocher wrote:
>>> - 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>
>> Merged, thanks.
> 
> This patch causes the following build warning:

Hups ... when I posted the patch, it compiled clean ...

>   MODPOST vmlinux.o
> WARNING: vmlinux.o(.text+0x1d5572): Section mismatch in reference from
> the function sm501fb_init_fb() to the variable
> .devinit.data:sm501_default_mode
> The function sm501fb_init_fb() references
> the variable __devinitdata sm501_default_mode.
> This is often because sm501fb_init_fb lacks a __devinitdata
> annotation or the annotation of sm501_default_mode is wrong.
> 
> WARNING: vmlinux.o(.text+0x1d557a): Section mismatch in reference from
> the function sm501fb_init_fb() to the variable
> .devinit.data:sm501_default_mode
> The function sm501fb_init_fb() references
> the variable __devinitdata sm501_default_mode.
> This is often because sm501fb_init_fb lacks a __devinitdata
> annotation or the annotation of sm501_default_mode is wrong.
> 
> I've dropped the __devinitdata declaration in what I committed; can
> you investigate and post a fixup patch?

Of course, I look ASAP at it, thanks!
(Dummy question: where can I find your tree?)

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: Login prompt on a video console instead of serial port?
From: Benjamin Herrenschmidt @ 2011-05-03  5:41 UTC (permalink / raw)
  To: Timur Tabi
  Cc: McClintock Matthew-B29882, devicetree-discuss,
	linuxppc-dev@lists.ozlabs.org, linux-fbdev@vger.kernel.org
In-Reply-To: <4DBF0DF1.6050207@freescale.com>

On Mon, 2011-05-02 at 15:02 -0500, Timur Tabi wrote:
> McClintock Matthew-B29882 wrote:
> > Don't you have to spawn a terminal on the framebuffer for the login?
> 
> I suppose, but I don't know how to do that.  And although that would technically
> answer the question in the subject of this thread, I still would have *some*
> boot output on the serial port.  It would be nice if I could get all of stdout
> on the video display, and all of stdin from the serial port.

I don't think we have a way to do that unless you can make a serial
"keyboard" device in the input layer. The VT layer will only get its
input from such a thing, maybe that does exist in the depth of legacy
code in there but it has nothing to do with your device-tree.

> > Right now getty spawns the login on the serial port via /etc/inittab.
> > Something similiar is probably needed for the framebuffer.
> 
> getty appears to work only with serial devices, since it insists on a baud rate
> as one of the parameters.

No, or no existing distro would work :-)

Just fake a baudrate for the tty's

Cheers,
Ben.


^ permalink raw reply


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