From: Mans Rullgard <mans@mansr.com>
Date: Fri, 29 Aug 2008 01:42:12 +0000 (+0100)
Subject: OMAP: Make video mode selectable from pre-defined list
X-Git-Url: http://git.mansr.com/?p=linux-omap;a=commitdiff_plain;h=7a9e55d7156dae6bc930c77620a88a669d2ed1c9

OMAP: Make video mode selectable from pre-defined list

This adds a list of common video modes and allows one to be
selected with video=omapfb:mode:name on the command line,
overriding the defaults from lcd_*.c. A default named mode
can also be specified in the kernel configuration.

Signed-off-by: Mans Rullgard <mans@mansr.com>
---

diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
index 5ebd591..9977e80 100644
--- a/drivers/video/omap/Kconfig
+++ b/drivers/video/omap/Kconfig
@@ -7,26 +7,13 @@ config FB_OMAP
 	help
           Frame buffer driver for OMAP based boards.
 
-choice
-	depends on FB_OMAP && MACH_OVERO
-	prompt "Screen resolution"
-	default FB_OMAP_079M3R
+config FB_OMAP_VIDEO_MODE
+	string "Default video mode"
+	depends on FB_OMAP
 	help
-	  Selected desired screen resolution
-
-config FB_OMAP_031M3R
-	boolean "640 x 480 @ 60 Hz Reduced blanking"
-
-config FB_OMAP_048M3R
-	boolean "800 x 600 @ 60 Hz Reduced blanking"
-
-config FB_OMAP_079M3R
-	boolean "1024 x 768 @ 60 Hz Reduced blanking"
-
-config FB_OMAP_092M9R
-	boolean "1280 x 720 @ 60 Hz Reduced blanking"
-
-endchoice
+	  Enter video mode name to use if none is specified on the kernel
+	  command line. If left blank, board-specific default timings
+	  will be used. See omapfb_main.c for a list of valid mode names.
 
 config FB_OMAP_LCDC_EXTERNAL
 	bool "External LCD controller support"
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index e9ffb92..c4c4049 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -36,6 +36,20 @@
 
 #define MODULE_NAME	"omapfb"
 
+struct video_mode {
+	const char	*name;
+	int		x_res, y_res;
+	int		pixel_clock;	/* In kHz */
+	int		hsw;		/* Horizontal synchronization
+					   pulse width */
+	int		hfp;		/* Horizontal front porch */
+	int		hbp;		/* Horizontal back porch */
+	int		vsw;		/* Vertical synchronization
+					   pulse width */
+	int		vfp;		/* Vertical front porch */
+	int		vbp;		/* Vertical back porch */
+};
+
 static unsigned int	def_accel;
 static unsigned long	def_vram[OMAPFB_PLANE_NUM];
 static unsigned int	def_vram_cnt;
@@ -43,6 +57,7 @@ static unsigned long	def_vxres;
 static unsigned long	def_vyres;
 static unsigned int	def_rotate;
 static unsigned int	def_mirror;
+static char		def_mode[16] = CONFIG_FB_OMAP_VIDEO_MODE;
 
 #ifdef CONFIG_FB_OMAP_MANUAL_UPDATE
 static int		manual_update = 1;
@@ -53,6 +68,7 @@ static int		manual_update;
 static struct platform_device	*fbdev_pdev;
 static struct lcd_panel		*fbdev_panel;
 static struct omapfb_device	*omapfb_dev;
+static struct video_mode	video_mode;
 
 struct caps_table_struct {
 	unsigned long flag;
@@ -83,6 +99,152 @@ static struct caps_table_struct color_caps[] = {
 	{ 1 << OMAPFB_COLOR_YUY422,	"YUY422", },
 };
 
+static struct video_mode video_modes[] __initdata = {
+	{
+		/* 640 x 480 @ 60 Hz  Reduced blanking VESA CVT 0.31M3-R */
+		.name		= "640x480@60",
+		.x_res		= 640,
+		.y_res		= 480,
+		.hfp		= 48,
+		.hsw		= 32,
+		.hbp		= 80,
+		.vfp		= 3,
+		.vsw		= 4,
+		.vbp		= 7,
+		.pixel_clock	= 23500,
+	},
+	{
+		/* 800 x 600 @ 60 Hz  Reduced blanking VESA CVT 0.48M3-R */
+		.name		= "800x600@60",
+		.x_res		= 800,
+		.y_res		= 600,
+		.hfp		= 48,
+		.hsw		= 32,
+		.hbp		= 80,
+		.vfp		= 3,
+		.vsw		= 4,
+		.vbp		= 11,
+		.pixel_clock	= 35500,
+	},
+	{
+		/* 1024 x 768 @ 60 Hz  Reduced blanking VESA CVT 0.79M3-R */
+		.name		= "1024x768@60",
+		.x_res		= 1024,
+		.y_res		= 768,
+		.hfp		= 48,
+		.hsw		= 32,
+		.hbp		= 80,
+		.vfp		= 3,
+		.vsw		= 4,
+		.vbp		= 15,
+		.pixel_clock	= 56000,
+	},
+	{
+		/* 1280 x 720 @ 60 Hz  Reduced blanking VESA CVT 0.92M9-R */
+		.name		= "1280x720@60",
+		.x_res		= 1280,
+		.y_res		= 720,
+		.hfp		= 48,
+		.hsw		= 32,
+		.hbp		= 80,
+		.vfp		= 3,
+		.vsw		= 5,
+		.vbp		= 13,
+		.pixel_clock	= 64000,
+	},
+	{
+		/* 720 x 480 @ 60 Hz  CEA-861 Format 3 */
+		.name		= "480p60",
+		.x_res		= 720,
+		.y_res		= 480,
+		.hfp		= 16,
+		.hsw		= 62,
+		.hbp		= 60,
+		.vfp		= 9,
+		.vsw		= 6,
+		.vbp		= 30,
+		.pixel_clock	= 27027,
+	},
+	{
+		/* 720 x 576 @ 60 Hz  CEA-861 Format 18 */
+		.name		= "576p50",
+		.x_res		= 720,
+		.y_res		= 576,
+		.hfp		= 12,
+		.hsw		= 64,
+		.hbp		= 68,
+		.vfp		= 5,
+		.vsw		= 5,
+		.vbp		= 39,
+		.pixel_clock	= 27000,
+	},
+	{
+		/* 1280 x 720 @ 50 Hz  CEA-861B Format 19 */
+		.name 		= "720p50",
+		.x_res		= 1280,
+		.y_res		= 720,
+		.hfp		= 440,
+		.hsw		= 40,
+		.hbp		= 220,
+		.vfp		= 20,
+		.vsw		= 5,
+		.vbp		= 5,
+		.pixel_clock	= 74250,
+	},
+	{
+		/* 1280 x 720 @ 60 Hz  CEA-861B Format 4 */
+		.name		= "720p60",
+		.x_res		= 1280,
+		.y_res		= 720,
+		.hfp		= 110,
+		.hsw		= 40,
+		.hbp		= 220,
+		.vfp		= 20,
+		.vsw		= 5,
+		.vbp		= 5,
+		.pixel_clock	= 74250,
+	},
+	{
+		/* 1920 x 1080 @ 24 Hz  CEA-861B Format 32 */
+		.name		= "1080p24",
+		.x_res		= 1920,
+		.y_res		= 1080,
+		.hfp		= 148,
+		.hsw		= 44,
+		.hbp		= 638,
+		.vfp		= 36,
+		.vsw		= 5,
+		.vbp		= 4,
+		.pixel_clock	= 74250,
+	},
+	{
+		/* 1920 x 1080 @ 25 Hz  CEA-861B Format 33 */
+		.name		= "1080p25",
+		.x_res		= 1920,
+		.y_res		= 1080,
+		.hfp		= 148,
+		.hsw		= 44,
+		.hbp		= 528,
+		.vfp		= 36,
+		.vsw		= 5,
+		.vbp		= 4,
+		.pixel_clock	= 74250,
+	},
+	{
+		/* 1920 x 1080 @ 30 Hz  CEA-861B Format 34 */
+		.name		= "1080p30",
+		.x_res		= 1920,
+		.y_res		= 1080,
+		.hfp		= 148,
+		.hsw		= 44,
+		.hbp		= 88,
+		.vfp		= 36,
+		.vsw		= 5,
+		.vbp		= 4,
+		.pixel_clock	= 74250,
+	},
+};
+
 /*
  * ---------------------------------------------------------------------------
  * LCD panel
@@ -1714,6 +1876,20 @@ static int omapfb_do_probe(struct platform_device *pdev,
 		goto cleanup;
 	}
 
+	if (video_mode.name) {
+		pr_info("omapfb: using mode %s\n", video_mode.name);
+
+		fbdev->panel->x_res	= video_mode.x_res;
+		fbdev->panel->y_res	= video_mode.y_res;
+		fbdev->panel->pixel_clock = video_mode.pixel_clock;
+		fbdev->panel->hsw	= video_mode.hsw;
+		fbdev->panel->hfp	= video_mode.hfp;
+		fbdev->panel->hbp	= video_mode.hbp;
+		fbdev->panel->vsw	= video_mode.vsw;
+		fbdev->panel->vfp	= video_mode.vfp;
+		fbdev->panel->vbp	= video_mode.vbp;
+	}
+
 	r = fbdev->panel->init(fbdev->panel, fbdev);
 	if (r)
 		goto cleanup;
@@ -1870,6 +2046,17 @@ static struct platform_driver omapfb_driver = {
 	},
 };
 
+static void __init omapfb_find_mode(char *name, struct video_mode *vmode)
+{
+	int i;
+
+	for (i = 0; i < sizeof(video_modes)/sizeof(video_modes[0]); i++)
+		if (!strcmp(name, video_modes[i].name)) {
+			*vmode = video_modes[i];
+			break;
+		}
+}
+
 #ifndef MODULE
 
 /* Process kernel command line parameters */
@@ -1918,6 +2105,8 @@ static int __init omapfb_setup(char *options)
 			def_mirror = (simple_strtoul(this_opt + 7, NULL, 0));
 		else if (!strncmp(this_opt, "manual_update", 13))
 			manual_update = 1;
+		else if (!strncmp(this_opt, "mode:", 5))
+			strncpy(def_mode, this_opt + 5, sizeof(def_mode));
 		else {
 			pr_debug("omapfb: invalid option\n");
 			r = -1;
@@ -1939,6 +2128,9 @@ static int __init omapfb_init(void)
 		return -ENODEV;
 	omapfb_setup(option);
 #endif
+
+	omapfb_find_mode(def_mode, &video_mode);
+
 	/* Register the driver with LDM */
 	if (platform_driver_register(&omapfb_driver)) {
 		pr_debug("failed to register omapfb driver\n");
@@ -1960,6 +2152,7 @@ module_param_named(vyres, def_vyres, long, 0664);
 module_param_named(rotate, def_rotate, uint, 0664);
 module_param_named(mirror, def_mirror, uint, 0664);
 module_param_named(manual_update, manual_update, bool, 0664);
+module_param_string(video_mode, def_mode, sizeof(def_mode), 0664);
 
 module_init(omapfb_init);
 module_exit(omapfb_cleanup);