Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* [PATCH 3/6] au1200fb: make number of windows configurable at load time.
From: Manuel Lauss @ 2011-09-02 14:40 UTC (permalink / raw)
  To: linux-fbdev

Make the number of framebuffer windows and the window configuration
selectable at the kernel commandline instead of hardcoding it
in the kernel config.

Signed-off-by: Manuel Lauss <manuel.lauss@googlemail.com>
---
 drivers/video/au1200fb.c |   53 +++++++++++++++++++++++++++++++++------------
 1 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
index 480ecb1..4b58f7b 100644
--- a/drivers/video/au1200fb.c
+++ b/drivers/video/au1200fb.c
@@ -46,10 +46,6 @@
 #include <asm/mach-au1x00/au1000.h>
 #include "au1200fb.h"
 
-#ifndef CONFIG_FB_AU1200_DEVS
-#define CONFIG_FB_AU1200_DEVS 4
-#endif
-
 #define DRIVER_NAME "au1200fb"
 #define DRIVER_DESC "LCD controller driver for AU1200 processors"
 
@@ -154,7 +150,6 @@ struct au1200fb_device {
 	dma_addr_t    		fb_phys;
 };
 
-static struct fb_info *_au1200fb_infos[CONFIG_FB_AU1200_DEVS];
 /********************************************************************/
 
 /* LCD controller restrictions */
@@ -167,10 +162,18 @@ static struct fb_info *_au1200fb_infos[CONFIG_FB_AU1200_DEVS];
 /* Default number of visible screen buffer to allocate */
 #define AU1200FB_NBR_VIDEO_BUFFERS 1
 
+/* Default maximum number of fb devices to create */
+#define MAX_DEVICE_COUNT	4
+
+/* Default window configuration entry to use (see windows[]) */
+#define DEFAULT_WINDOW_INDEX	2
+
 /********************************************************************/
 
+static struct fb_info *_au1200fb_infos[MAX_DEVICE_COUNT];
 static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR;
-static int window_index = 2; /* default is zero */
+static int device_count = MAX_DEVICE_COUNT;
+static int window_index = DEFAULT_WINDOW_INDEX;	/* default is zero */
 static int panel_index = 2; /* default is zero */
 static struct window_settings *win;
 static struct panel_settings *panel;
@@ -683,7 +686,7 @@ static int fbinfo2index (struct fb_info *fb_info)
 {
 	int i;
 
-	for (i = 0; i < CONFIG_FB_AU1200_DEVS; ++i) {
+	for (i = 0; i < device_count; ++i) {
 		if (fb_info = _au1200fb_infos[i])
 			return i;
 	}
@@ -1599,7 +1602,7 @@ static int __devinit au1200fb_drv_probe(struct platform_device *dev)
 	/* Kickstart the panel */
 	au1200_setpanel(panel);
 
-	for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) {
+	for (plane = 0; plane < device_count; ++plane) {
 		bpp = winbpp(win->w[plane].mode_winctrl1);
 		if (win->w[plane].xres = 0)
 			win->w[plane].xres = panel->Xres;
@@ -1699,7 +1702,7 @@ static int __devexit au1200fb_drv_remove(struct platform_device *dev)
 	/* Turn off the panel */
 	au1200_setpanel(NULL);
 
-	for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane)	{
+	for (plane = 0; plane < device_count; ++plane)	{
 		fbi = _au1200fb_infos[plane];
 		fbdev = fbi->par;
 
@@ -1741,7 +1744,7 @@ static int au1200fb_drv_resume(struct device *dev)
 	/* Kickstart the panel */
 	au1200_setpanel(panel);
 
-	for (i = 0; i < CONFIG_FB_AU1200_DEVS; i++) {
+	for (i = 0; i < device_count; i++) {
 		fbi = _au1200fb_infos[i];
 		au1200fb_fb_set_par(fbi);
 	}
@@ -1776,10 +1779,10 @@ static struct platform_driver au1200fb_driver = {
 
 /* Kernel driver */
 
-static void au1200fb_setup(void)
+static int au1200fb_setup(void)
 {
-	char* options = NULL;
-	char* this_opt;
+	char *options = NULL;
+	char *this_opt, *endptr;
 	int num_panels = ARRAY_SIZE(known_lcd_panels);
 	int panel_idx = -1;
 
@@ -1824,12 +1827,33 @@ static void au1200fb_setup(void)
 				nohwcursor = 1;
 			}
 
+			else if (strncmp(this_opt, "devices:", 8) = 0) {
+				this_opt += 8;
+				device_count = simple_strtol(this_opt,
+							     &endptr, 0);
+				if ((device_count < 0) ||
+				    (device_count > MAX_DEVICE_COUNT))
+					device_count = MAX_DEVICE_COUNT;
+			}
+
+			else if (strncmp(this_opt, "wincfg:", 7) = 0) {
+				this_opt += 7;
+				window_index = simple_strtol(this_opt,
+							     &endptr, 0);
+				if ((window_index < 0) ||
+				    (window_index >= ARRAY_SIZE(windows)))
+					window_index = DEFAULT_WINDOW_INDEX;
+			}
+
+			else if (strncmp(this_opt, "off", 3) = 0)
+				return 1;
 			/* Unsupported option */
 			else {
 				print_warn("Unsupported option \"%s\"", this_opt);
 			}
 		}
 	}
+	return 0;
 }
 
 static int __init au1200fb_init(void)
@@ -1837,7 +1861,8 @@ static int __init au1200fb_init(void)
 	print_info("" DRIVER_DESC "");
 
 	/* Setup driver with options */
-	au1200fb_setup();
+	if (au1200fb_setup())
+		return -ENODEV;
 
 	/* Point to the panel selected */
 	panel = &known_lcd_panels[panel_index];
-- 
1.7.6


^ permalink raw reply related

* [PATCH 2/6] au1200fb: fixup PM
From: Manuel Lauss @ 2011-09-02 14:40 UTC (permalink / raw)
  To: linux-fbdev

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="windows-1252", Size: 7074 bytes --]

Remove last traces of the unused custom Alchemy PM code, implement
suspend/resume callbacks.

Signed-off-by: Manuel Lauss <manuel.lauss@googlemail.com>
---
 drivers/video/au1200fb.c |  154 ++++++++++++----------------------------------
 1 files changed, 39 insertions(+), 115 deletions(-)

diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
index 442d005..480ecb1 100644
--- a/drivers/video/au1200fb.c
+++ b/drivers/video/au1200fb.c
@@ -46,10 +46,6 @@
 #include <asm/mach-au1x00/au1000.h>
 #include "au1200fb.h"
 
-#ifdef CONFIG_PM
-#include <asm/mach-au1x00/au1xxx_pm.h>
-#endif
-
 #ifndef CONFIG_FB_AU1200_DEVS
 #define CONFIG_FB_AU1200_DEVS 4
 #endif
@@ -205,12 +201,6 @@ struct window_settings {
 extern int board_au1200fb_panel_init (void);
 extern int board_au1200fb_panel_shutdown (void);
 
-#ifdef CONFIG_PM
-int au1200fb_pm_callback(au1xxx_power_dev_t *dev,
-		au1xxx_request_t request, void *data);
-au1xxx_power_dev_t *LCD_pm_dev;
-#endif
-
 /*
  * Default window configurations
  */
@@ -652,25 +642,6 @@ static struct panel_settings known_lcd_panels[]  
 /********************************************************************/
 
-#ifdef CONFIG_PM
-static int set_brightness(unsigned int brightness)
-{
-	unsigned int hi1, divider;
-
-	/* limit brightness pwm duty to >= 30/1600 */
-	if (brightness < 30) {
-		brightness = 30;
-	}
-	divider = (lcd->pwmdiv & 0x3FFFF) + 1;
-	hi1 = (lcd->pwmhi >> 16) + 1;
-	hi1 = (((brightness & 0xFF) + 1) * divider >> 8);
-	lcd->pwmhi &= 0xFFFF;
-	lcd->pwmhi |= (hi1 << 16);
-
-	return brightness;
-}
-#endif /* CONFIG_PM */
-
 static int winbpp (unsigned int winctrl1)
 {
 	int bits = 0;
@@ -1248,10 +1219,6 @@ static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 	unsigned long start=0, off;
 	struct au1200fb_device *fbdev = info->par;
 
-#ifdef CONFIG_PM
-	au1xxx_pm_access(LCD_pm_dev);
-#endif
-
 	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
 		return -EINVAL;
 	}
@@ -1461,10 +1428,6 @@ static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd,
 	int plane;
 	int val;
 
-#ifdef CONFIG_PM
-	au1xxx_pm_access(LCD_pm_dev);
-#endif
-
 	plane = fbinfo2index(info);
 	print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane);
 
@@ -1622,7 +1585,7 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
 
 /* AU1200 LCD controller device driver */
 
-static int au1200fb_drv_probe(struct platform_device *dev)
+static int __devinit au1200fb_drv_probe(struct platform_device *dev)
 {
 	struct au1200fb_device *fbdev;
 	struct fb_info *fbi = NULL;
@@ -1633,6 +1596,9 @@ static int au1200fb_drv_probe(struct platform_device *dev)
 	ret = 0;
 	fbdev = NULL;
 
+	/* Kickstart the panel */
+	au1200_setpanel(panel);
+
 	for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) {
 		bpp = winbpp(win->w[plane].mode_winctrl1);
 		if (win->w[plane].xres = 0)
@@ -1724,15 +1690,12 @@ failed:
 	return ret;
 }
 
-static int au1200fb_drv_remove(struct platform_device *dev)
+static int __devexit au1200fb_drv_remove(struct platform_device *dev)
 {
 	struct au1200fb_device *fbdev;
 	struct fb_info *fbi;
 	int plane;
 
-	if (!dev)
-		return -ENODEV;
-
 	/* Turn off the panel */
 	au1200_setpanel(NULL);
 
@@ -1760,31 +1723,53 @@ static int au1200fb_drv_remove(struct platform_device *dev)
 }
 
 #ifdef CONFIG_PM
-static int au1200fb_drv_suspend(struct platform_device *dev,
-				pm_message_t state)
+static int au1200fb_drv_suspend(struct device *dev)
 {
-	/* TODO */
+	au1200_setpanel(NULL);
+
+	lcd->outmask = 0;
+	au_sync();
+
 	return 0;
 }
 
-static int au1200fb_drv_resume(struct platform_device *dev)
+static int au1200fb_drv_resume(struct device *dev)
 {
-	/* TODO */
+	struct fb_info *fbi;
+	int i;
+
+	/* Kickstart the panel */
+	au1200_setpanel(panel);
+
+	for (i = 0; i < CONFIG_FB_AU1200_DEVS; i++) {
+		fbi = _au1200fb_infos[i];
+		au1200fb_fb_set_par(fbi);
+	}
+
 	return 0;
 }
+
+static const struct dev_pm_ops au1200fb_pmops = {
+	.suspend	= au1200fb_drv_suspend,
+	.resume		= au1200fb_drv_resume,
+	.freeze		= au1200fb_drv_suspend,
+	.thaw		= au1200fb_drv_resume,
+};
+
+#define AU1200FB_PMOPS	(&au1200fb_pmops)
+
+#else
+#define AU1200FB_PMOPS	NULL
 #endif /* CONFIG_PM */
 
 static struct platform_driver au1200fb_driver = {
 	.driver = {
-		.name		= "au1200-lcd",
-		.owner          = THIS_MODULE,
+		.name	= "au1200-lcd",
+		.owner	= THIS_MODULE,
+		.pm	= AU1200FB_PMOPS,
 	},
 	.probe		= au1200fb_drv_probe,
-	.remove		= au1200fb_drv_remove,
-#ifdef CONFIG_PM
-	.suspend	= au1200fb_drv_suspend,
-	.resume		= au1200fb_drv_resume,
-#endif
+	.remove		= __devexit_p(au1200fb_drv_remove),
 };
 
 /*-------------------------------------------------------------------------*/
@@ -1847,56 +1832,6 @@ static void au1200fb_setup(void)
 	}
 }
 
-#ifdef CONFIG_PM
-static int au1200fb_pm_callback(au1xxx_power_dev_t *dev,
-		au1xxx_request_t request, void *data) {
-	int retval = -1;
-	unsigned int d = 0;
-	unsigned int brightness = 0;
-
-	if (request = AU1XXX_PM_SLEEP) {
-		board_au1200fb_panel_shutdown();
-	}
-	else if (request = AU1XXX_PM_WAKEUP) {
-		if(dev->prev_state = SLEEP_STATE)
-		{
-			int plane;
-			au1200_setpanel(panel);
-			for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) 	{
-				struct au1200fb_device *fbdev;
-				fbdev = &_au1200fb_devices[plane];
-				au1200fb_fb_set_par(&fbdev->fb_info);
-			}
-		}
-
-		d = *((unsigned int*)data);
-		if(d <\x10) brightness = 26;
-		else if(d< ) brightness = 51;
-		else if(d<0) brightness = 77;
-		else if(d<@) brightness = 102;
-		else if(d<P) brightness = 128;
-		else if(d<`) brightness = 153;
-		else if(d<p) brightness = 179;
-		else if(d<€) brightness = 204;
-		else if(d<) brightness = 230;
-		else brightness = 255;
-		set_brightness(brightness);
-	} else if (request = AU1XXX_PM_GETSTATUS) {
-		return dev->cur_state;
-	} else if (request = AU1XXX_PM_ACCESS) {
-		if (dev->cur_state != SLEEP_STATE)
-			return retval;
-		else {
-			au1200_setpanel(panel);
-		}
-	} else if (request = AU1XXX_PM_IDLE) {
-	} else if (request = AU1XXX_PM_CLEANUP) {
-	}
-
-	return retval;
-}
-#endif
-
 static int __init au1200fb_init(void)
 {
 	print_info("" DRIVER_DESC "");
@@ -1911,17 +1846,6 @@ static int __init au1200fb_init(void)
 	printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name);
 	printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name);
 
-	/* Kickstart the panel, the framebuffers/windows come soon enough */
-	au1200_setpanel(panel);
-
-	#ifdef CONFIG_PM
-	LCD_pm_dev = new_au1xxx_power_device("LCD", &au1200fb_pm_callback, NULL);
-	if ( LCD_pm_dev = NULL)
-		printk(KERN_INFO "Unable to create a power management device entry for the au1200fb.\n");
-	else
-		printk(KERN_INFO "Power management device entry for the au1200fb loaded.\n");
-	#endif
-
 	return platform_driver_register(&au1200fb_driver);
 }
 
-- 
1.7.6


^ permalink raw reply related

* [PATCH 1/6] au1200fb: use framebuffer_alloc()
From: Manuel Lauss @ 2011-09-02 14:40 UTC (permalink / raw)
  To: linux-fbdev

Convert to use framebuffer_alloc() instead of using fb_info embedded
into device context (which broke the driver in the past due to un-
initialized elements).

Signed-off-by: Manuel Lauss <manuel.lauss@googlemail.com>
---
 drivers/video/au1200fb.c |   80 ++++++++++++++++++++++++++-------------------
 1 files changed, 46 insertions(+), 34 deletions(-)

diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
index 5dff32a..442d005 100644
--- a/drivers/video/au1200fb.c
+++ b/drivers/video/au1200fb.c
@@ -150,7 +150,7 @@ struct au1200_lcd_iodata_t {
 
 /* Private, per-framebuffer management information (independent of the panel itself) */
 struct au1200fb_device {
-	struct fb_info fb_info;			/* FB driver info record */
+	struct fb_info *fb_info;		/* FB driver info record */
 
 	int					plane;
 	unsigned char* 		fb_mem;		/* FrameBuffer memory map */
@@ -158,7 +158,7 @@ struct au1200fb_device {
 	dma_addr_t    		fb_phys;
 };
 
-static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS];
+static struct fb_info *_au1200fb_infos[CONFIG_FB_AU1200_DEVS];
 /********************************************************************/
 
 /* LCD controller restrictions */
@@ -713,7 +713,7 @@ static int fbinfo2index (struct fb_info *fb_info)
 	int i;
 
 	for (i = 0; i < CONFIG_FB_AU1200_DEVS; ++i) {
-		if (fb_info = (struct fb_info *)(&_au1200fb_devices[i].fb_info))
+		if (fb_info = _au1200fb_infos[i])
 			return i;
 	}
 	printk("au1200fb: ERROR: fbinfo2index failed!\n");
@@ -962,7 +962,7 @@ static void au1200_setmode(struct au1200fb_device *fbdev)
 	lcd->window[plane].winctrl2 = ( 0
 		| LCD_WINCTRL2_CKMODE_00
 		| LCD_WINCTRL2_DBM
-		| LCD_WINCTRL2_BX_N( fbdev->fb_info.fix.line_length)
+		| LCD_WINCTRL2_BX_N(fbdev->fb_info->fix.line_length)
 		| LCD_WINCTRL2_SCX_1
 		| LCD_WINCTRL2_SCY_1
 		) ;
@@ -1050,7 +1050,7 @@ static void au1200fb_update_fbinfo(struct fb_info *fbi)
 static int au1200fb_fb_check_var(struct fb_var_screeninfo *var,
 	struct fb_info *fbi)
 {
-	struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi;
+	struct au1200fb_device *fbdev = fbi->par;
 	u32 pixclock;
 	int screen_size, plane;
 
@@ -1142,7 +1142,7 @@ static int au1200fb_fb_check_var(struct fb_var_screeninfo *var,
  */
 static int au1200fb_fb_set_par(struct fb_info *fbi)
 {
-	struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi;
+	struct au1200fb_device *fbdev = fbi->par;
 
 	au1200fb_update_fbinfo(fbi);
 	au1200_setmode(fbdev);
@@ -1246,7 +1246,7 @@ static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 {
 	unsigned int len;
 	unsigned long start=0, off;
-	struct au1200fb_device *fbdev = (struct au1200fb_device *) info;
+	struct au1200fb_device *fbdev = info->par;
 
 #ifdef CONFIG_PM
 	au1xxx_pm_access(LCD_pm_dev);
@@ -1561,10 +1561,9 @@ static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id)
 
 static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
 {
-	struct fb_info *fbi = &fbdev->fb_info;
+	struct fb_info *fbi = fbdev->fb_info;
 	int bpp;
 
-	memset(fbi, 0, sizeof(struct fb_info));
 	fbi->fbops = &au1200fb_fb_ops;
 
 	bpp = winbpp(win->w[fbdev->plane].mode_winctrl1);
@@ -1626,11 +1625,13 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
 static int au1200fb_drv_probe(struct platform_device *dev)
 {
 	struct au1200fb_device *fbdev;
+	struct fb_info *fbi = NULL;
 	unsigned long page;
 	int bpp, plane, ret;
 
-	if (!dev)
-		return -EINVAL;
+	/* shut gcc up */
+	ret = 0;
+	fbdev = NULL;
 
 	for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) {
 		bpp = winbpp(win->w[plane].mode_winctrl1);
@@ -1639,8 +1640,15 @@ static int au1200fb_drv_probe(struct platform_device *dev)
 		if (win->w[plane].yres = 0)
 			win->w[plane].yres = panel->Yres;
 
-		fbdev = &_au1200fb_devices[plane];
-		memset(fbdev, 0, sizeof(struct au1200fb_device));
+		fbi = framebuffer_alloc(sizeof(struct au1200fb_device),
+					&dev->dev);
+		if (!fbi)
+			goto failed;
+
+		_au1200fb_infos[plane] = fbi;
+		fbdev = fbi->par;
+		fbdev->fb_info = fbi;
+
 		fbdev->plane = plane;
 
 		/* Allocate the framebuffer to the maximum screen size */
@@ -1673,21 +1681,20 @@ static int au1200fb_drv_probe(struct platform_device *dev)
 			goto failed;
 
 		/* Register new framebuffer */
-		if ((ret = register_framebuffer(&fbdev->fb_info)) < 0) {
+		ret = register_framebuffer(fbi);
+		if (ret < 0) {
 			print_err("cannot register new framebuffer");
 			goto failed;
 		}
 
-		au1200fb_fb_set_par(&fbdev->fb_info);
+		au1200fb_fb_set_par(fbi);
 
 #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
 		if (plane = 0)
-			if (fb_prepare_logo(&fbdev->fb_info, FB_ROTATE_UR)) {
+			if (fb_prepare_logo(fbi, FB_ROTATE_UR)) {
 				/* Start display and show logo on boot */
-				fb_set_cmap(&fbdev->fb_info.cmap,
-						&fbdev->fb_info);
-
-				fb_show_logo(&fbdev->fb_info, FB_ROTATE_UR);
+				fb_set_cmap(&fbi->cmap, fbi);
+				fb_show_logo(fbi, FB_ROTATE_UR);
 			}
 #endif
 	}
@@ -1705,12 +1712,13 @@ static int au1200fb_drv_probe(struct platform_device *dev)
 failed:
 	/* NOTE: This only does the current plane/window that failed; others are still active */
 	if (fbdev->fb_mem)
-		dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len),
+		dma_free_noncoherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len),
 				fbdev->fb_mem, fbdev->fb_phys);
-	if (fbdev->fb_info.cmap.len != 0)
-		fb_dealloc_cmap(&fbdev->fb_info.cmap);
-	if (fbdev->fb_info.pseudo_palette)
-		kfree(fbdev->fb_info.pseudo_palette);
+	if (fbi) {
+		if (fbi->cmap.len != 0)
+			fb_dealloc_cmap(&fbi->cmap);
+		kfree(fbi->pseudo_palette);
+	}
 	if (plane = 0)
 		free_irq(AU1200_LCD_INT, (void*)dev);
 	return ret;
@@ -1719,6 +1727,7 @@ failed:
 static int au1200fb_drv_remove(struct platform_device *dev)
 {
 	struct au1200fb_device *fbdev;
+	struct fb_info *fbi;
 	int plane;
 
 	if (!dev)
@@ -1727,20 +1736,22 @@ static int au1200fb_drv_remove(struct platform_device *dev)
 	/* Turn off the panel */
 	au1200_setpanel(NULL);
 
-	for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane)
-	{
-		fbdev = &_au1200fb_devices[plane];
+	for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane)	{
+		fbi = _au1200fb_infos[plane];
+		fbdev = fbi->par;
 
 		/* Clean up all probe data */
-		unregister_framebuffer(&fbdev->fb_info);
+		unregister_framebuffer(fbi);
 		if (fbdev->fb_mem)
 			dma_free_noncoherent(&dev->dev,
 					PAGE_ALIGN(fbdev->fb_len),
 					fbdev->fb_mem, fbdev->fb_phys);
-		if (fbdev->fb_info.cmap.len != 0)
-			fb_dealloc_cmap(&fbdev->fb_info.cmap);
-		if (fbdev->fb_info.pseudo_palette)
-			kfree(fbdev->fb_info.pseudo_palette);
+		if (fbi->cmap.len != 0)
+			fb_dealloc_cmap(&fbi->cmap);
+		kfree(fbi->pseudo_palette);
+
+		framebuffer_release(fbi);
+		_au1200fb_infos[plane] = NULL;
 	}
 
 	free_irq(AU1200_LCD_INT, (void *)dev);
@@ -1749,7 +1760,8 @@ static int au1200fb_drv_remove(struct platform_device *dev)
 }
 
 #ifdef CONFIG_PM
-static int au1200fb_drv_suspend(struct platform_device *dev, u32 state)
+static int au1200fb_drv_suspend(struct platform_device *dev,
+				pm_message_t state)
 {
 	/* TODO */
 	return 0;
-- 
1.7.6


^ permalink raw reply related

* [PATCH 0/6] fbdev: au1200fb updates
From: Manuel Lauss @ 2011-09-02 14:40 UTC (permalink / raw)
  To: linux-fbdev

This is a resend of 5 patches Paul Mundt previously added to the fbdev tree,
plus a new one to silence excessive dmesg output.  Please consider for 3.2.

Among other things, patch #2 fixes an annoying build failure with CONFIG_PM=y
which has been bugging Ralf Baechle (MIPS maintainer) for quite some time.

Run-tested on DB1200 and DB1300 evaluation boards.

Manuel Lauss (6):
  au1200fb: use framebuffer_alloc()
  au1200fb: fixup PM
  au1200fb: make number of windows configurable at load time.
  au1200fb: switch to FB_SYS helpers
  au1200fb: fix hardcoded IRQ
  fbdev: au1200fb: silence debug output

 drivers/video/Kconfig    |    7 +-
 drivers/video/au1200fb.c |  299 ++++++++++++++++++++--------------------------
 2 files changed, 136 insertions(+), 170 deletions(-)

-- 
1.7.6


^ permalink raw reply

* Re: [PATCH 0/2] video: s3c-fb: Add window positioning support
From: Tomi Valkeinen @ 2011-09-02  9:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4E5FB69E.2060907@gmx.de>

Hi,

On Thu, 2011-09-01 at 16:45 +0000, Florian Tobias Schandinat wrote:
> Hi all,
> 
> On 08/25/2011 07:51 PM, Ajay Kumar wrote:
> > Just as a note, there are many drivers like mx3fb.c, au1200fb.c and OMAP
> > seem to be doing window/plane positioning in their driver code.
> > Is it possible to have this window positioning support at a common place?
> 
> Good point. Congratulations for figuring out that I like to standardize things.
> But I think your suggestion is far from being enough to be useful for userspace
> (which is our goal so that applications can be reused along drivers and don't
> need to know about individual drivers).
> 
> So let me at first summarize how I understand you implemented those things after
> having a brief look at some of the drivers:
> Windows are rectangular screen areas whose pixel data come from other locations.
> The other locations are accessible via other framebuffer devices (e.g. fb1). So
> in this area the data of fb1 is shown and not the data of fb0 that would be
> normally shown.

Here's what we have on OMAP:

We have a bunch of hardware overlays, each of which can go to one
output. When using fbdev, the pixel data for overlays comes from the
framebuffers. One fb can be used as a  pixel source for multiple
overlays.

So, for example, the "connections" can be like these:

           Initial configuration

 .-----.         .------.           .------.
 | fb0 |-------->| ovl0 |-----.---->| LCD  |
 '-----'         '------'     |     '------'
 .-----.         .------.     |
 | fb1 |-------->| ovl1 |-----|
 '-----'         '------'     |
 .-----.         .------.     |     .------.
 | fb2 |-------->| ovl2 |-----'     |  TV  |
 '-----'         '------'           '------'


      Video on fb1, shown on LCD and TV

 .-----.         .------.           .------.
 | fb0 |-------->| ovl0 |-----.---->| LCD  |
 '-----'         '------'     |     '------'
 .-----.         .------.     |
 | fb1 |----.--->| ovl1 |-----'
 '-----'    |    '------'
 .-----.    |    .------.           .------.
 | fb2 |    '--->| ovl2 |---------->|  TV  |
 '-----'         '------'           '------'


And how the actual image is composited on the display, we have first the
fb side (no news there):

 .---------------------fb-vxres---------------------.
 |                                                  |
 |                                                  |
 |   (xoffset,yoffset)                              |
 |           .-------fb-xres------------.           |
 f           |                          |           |
 b           f                          |           |
 |           b                          |           |
 v           |                          |           |
 y           y                          |           |
 r           r                          |           |
 e           e                          |           |
 s           s                          |           |
 |           |                          |           |
 |           '--------------------------'           |
 |                                                  |
 |                                                  |
 '--------------------------------------------------'

The area marked by x/yoffset and x/yres is used as the pixel source for
the overlay.

On the display we have something like this:

 .----------------disp-xres----------------.
 |                                         |
 | (xpos,ypos)                             |
 |      .-----ovl-xres-----.               |
 d      |                  |               |
 i      o                  |               |
 s      v                  |               |
 p      l                  |               |
 |      |                  |               |
 y      y                  |               |
 r      r                  |               |
 e      e                  |               |
 s      s                  |               |
 |      |                  |               |
 |      '------------------'               |
 |                                         |
 '-----------------------------------------'

The x/ypos of the overlay does not have any relation to the x/yoffset of
the framebuffer. The overlay's x/yres is the same as the fb's x/yres in
case the overlay doesn't support scaling (OMAP's case this is true for
overlay0). Otherwise the overlay's x/yres is only limited by the HW's
scaling capabilities.

The overlays have a priority order, and where there's no overlay, a
background color is used. So like this:

 .-----------------------------------------.
 |            background color             |
 | .-----------------------.               |
 | |         ovl0          |               |
 | |                       |               |
 | | .--------------.      |               |
 | | |     ovl1     |      |               |
 | | |              |      |               |
 | | |        .-------------------.        |
 | | |        |       ovl2        |        |
 | | '--------|                   |        |
 | '----------|                   |        |
 |            |                   |        |
 |            |                   |        |
 |            |                   |        |
 |            '-------------------'        |
 '-----------------------------------------'

As you may have noticed, this raises in annoying problem: the
framebuffer does not represent the display, and thus the display related
information in the fb, like video timings, are difficult or impossible
to use. I haven't found any solution to this.

> So in addition to your proposed positioning I think we should also have the
> following to give userspace a useful set of functionality:
> 
> - a way to discover how the screen is composited (how many windows are there,
> how they are stacked and how to access those)
> 
> - a way to enable/disable windows (make them (in)visible)
> 
> - reporting and selecting how the window content can be mixed with the root
> screen (overwrite, source or destination color keying)

Right, and there may not be a root screen at all, like on OMAP. (if the
background color doesn't count as a root screen).

> - things like window size and color format could be handled by the usual fb API
> used on the window. However there might be restrictions which cause them to be
> not 100% API compatible (for example when changing the color format if the
> windows are required to have the same format as the root screen)
> 
> - do we need to worry about hardware (up/down) scaling of the window content?
> 
> 
> So is that what you need for a standardized window implementation?
> Any additional things that were useful/needed in this context?
> Would you consider adding support for this API in your drivers? (as
> standardizing wouldn't be useful if nobody would implement it)

We already have the current implementation in omapfb, so while a
standard API would be nice, we still need to keep the old custom API for
compatibility.

Another thing is that I'm not sure how much features we should try to
add to fbdev. The fbdev model is a bit limited (for example, the timings
problem above, or double/triple buffering), and at least we are
currently looking at using DRM. There will still be a framebuffer, but
that's mostly for fbconsole and such, and doesn't need to support
overlays, scaling, and other more complex features.

 Tomi



^ permalink raw reply

* Re: [PATCH 3/4] OMAP: DSS2: Handle manager change in apply
From: Archit Taneja @ 2011-09-02  7:44 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: linux-omap@vger.kernel.org, linux-fbdev@vger.kernel.org
In-Reply-To: <1314948322.3374.21.camel@deskari>

On Friday 02 September 2011 12:55 PM, Valkeinen, Tomi wrote:
> On Fri, 2011-09-02 at 12:20 +0530, Archit Taneja wrote:
>> On Monday 22 August 2011 01:57 PM, Valkeinen, Tomi wrote:
>>> Currently when changing the manager of an overlay, set_manager()
>> directly
>>> calls dispc to set the overlay's destination.
>>>
>>> Change this to be more in line with other overlay configurations,
>> and
>>> this will also remove the need to have dispc clocks enabled when
>> calling
>>> set_manager().
>>>
>>> A new field is added to overlay struct, "manager_changed". This is
>>> similar to "display_changed" field in manager struct, and is used to
>>> inform apply that the manager has changed and thus write to the
>>> registers is needed.
>>
>> I was wondering if it would be better to create an overlay_info
>> member
>> called 'channel_out' rather than having 'manager_enabled' at a higher
>> level? This way, we won't need to do some of the things below(I have
>> pointed them out):
>
> The overlay_info is written by the users of the DSS. So if we had
> channel_out there, we'd need to remove the set/get_manager() functions.
> I made those functions in the first place as I felt changing the manager
> is a bit bigger operation than the normal overlay attributes. Changing
> the manager does effect both the old and the new managers. While I don't
> think we currently do anything related to that, I believe it would be
> needed for optimizations like FIFO merge.

Right, I forgot users of DSS2 will also get the opportunity to change 
channel_out, and we would need to do extra stuff in that case.

>
> It could perhaps be possible to change this so that the overlay_info has
> the channel_out parameter, but that would be a bit bigger change, and
> would needs lots of testing. So I feel this is a safer change, and it
> fixes a problem we had with DRM.

Okay, we could think about this later then.

Archit

>
>   Tomi
>
>


^ permalink raw reply

* Re: [PATCH 2/4] OMAP4: TWL: Add common omapdss supplies
From: Tomi Valkeinen @ 2011-09-02  7:30 UTC (permalink / raw)
  To: Archit Taneja; +Cc: linux-omap@vger.kernel.org, linux-fbdev@vger.kernel.org
In-Reply-To: <4E607A40.8000707@ti.com>

On Fri, 2011-09-02 at 12:10 +0530, Archit Taneja wrote:
> Hi,
> 
> On Monday 22 August 2011 01:56 PM, Valkeinen, Tomi wrote:
> > OMAP DSS normally gets power from VCXIO on OMAP4. Add configuration
> for
> > this into twl-common.c
> >
> > Mark VCXIO as always_on, as VCXIO is used by multiple components,
> > including the MPU, and turning it off when DSS doesn't need it would
> > lead the device to halt.
> 
> I had a query. Is this the right place to set always_on to true?
> Won't 
> this lead to VCXIO being always on all omap4 boards? Is it necessary 
> that VCXIO will be used to power on MPU for all omap4 boards? 

I don't really know, but TRM's 27.2.1 Power Requirements chapter shows
vcxio connected to multiple places. It's an example, but I would guess
it is the common setup, thus setting it to always on in twl-common.c
sounds ok.

If there will be an omap4 board with different setup, then we need to
revisit this.

 Tomi



^ permalink raw reply

* Re: [PATCH 3/4] OMAP: DSS2: Handle manager change in apply
From: Tomi Valkeinen @ 2011-09-02  7:25 UTC (permalink / raw)
  To: Archit Taneja; +Cc: linux-omap@vger.kernel.org, linux-fbdev@vger.kernel.org
In-Reply-To: <4E607CC3.2000407@ti.com>

On Fri, 2011-09-02 at 12:20 +0530, Archit Taneja wrote:
> On Monday 22 August 2011 01:57 PM, Valkeinen, Tomi wrote:
> > Currently when changing the manager of an overlay, set_manager()
> directly
> > calls dispc to set the overlay's destination.
> >
> > Change this to be more in line with other overlay configurations,
> and
> > this will also remove the need to have dispc clocks enabled when
> calling
> > set_manager().
> >
> > A new field is added to overlay struct, "manager_changed". This is
> > similar to "display_changed" field in manager struct, and is used to
> > inform apply that the manager has changed and thus write to the
> > registers is needed.
> 
> I was wondering if it would be better to create an overlay_info
> member 
> called 'channel_out' rather than having 'manager_enabled' at a higher 
> level? This way, we won't need to do some of the things below(I have 
> pointed them out): 

The overlay_info is written by the users of the DSS. So if we had
channel_out there, we'd need to remove the set/get_manager() functions.
I made those functions in the first place as I felt changing the manager
is a bit bigger operation than the normal overlay attributes. Changing
the manager does effect both the old and the new managers. While I don't
think we currently do anything related to that, I believe it would be
needed for optimizations like FIFO merge.

It could perhaps be possible to change this so that the overlay_info has
the channel_out parameter, but that would be a bit bigger change, and
would needs lots of testing. So I feel this is a safer change, and it
fixes a problem we had with DRM.

 Tomi



^ permalink raw reply

* Re: [PATCH 1/8] OMAP: DSS2: DISPC: Fix minimum PCD value
From: Archit Taneja @ 2011-09-02  6:54 UTC (permalink / raw)
  To: Valkeinen, Tomi
  Cc: linux-omap@vger.kernel.org, linux-fbdev@vger.kernel.org,
	K, Mythri P
In-Reply-To: <1314796908-17354-2-git-send-email-tomi.valkeinen@ti.com>

On Wednesday 31 August 2011 06:51 PM, Valkeinen, Tomi wrote:
> The current driver had a hardcoded minimum value of 2 for pixel clock
> divisor (PCD). This doesn't seem to be right.
>
> OMAP4 TRM says that PCD can be 1 when not downscaling, and inverted
> pixel clock (IPC) is off.
>
> OMAP3 TRM says the same, but also in the register descriptions that PCD
> value 1 is invalid.
>
> OMAP2 TRM says PCD 2 is the minimum.
>
> OMAP2 is still untested, but for both OMAP3 and OMAP4 PCD of 1 seems to
> work fine.
>
> This patch adds a new DSS feature, FEAT_PARAM_DSS_PCD, which is used to
> find the minimum and maximum PCD. The minimum is set to 2 for OMAP2, and
> 1 for OMAP3/4.

This looks good to me.

Archit

>
> Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
> ---
>   drivers/video/omap2/dss/dispc.c        |   14 ++++++++++----
>   drivers/video/omap2/dss/dss_features.c |    3 +++
>   drivers/video/omap2/dss/dss_features.h |    1 +
>   3 files changed, 14 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
> index de20936..7f3d847 100644
> --- a/drivers/video/omap2/dss/dispc.c
> +++ b/drivers/video/omap2/dss/dispc.c
> @@ -2339,7 +2339,7 @@ static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
>   		u16 pck_div)
>   {
>   	BUG_ON(lck_div<  1);
> -	BUG_ON(pck_div<  2);
> +	BUG_ON(pck_div<  1);
>
>   	dispc_write_reg(DISPC_DIVISORo(channel),
>   			FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
> @@ -2726,11 +2726,17 @@ void dispc_mgr_set_pol_freq(enum omap_channel channel,
>   void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
>   		struct dispc_clock_info *cinfo)
>   {
> -	u16 pcd_min = is_tft ? 2 : 3;
> +	u16 pcd_min, pcd_max;
>   	unsigned long best_pck;
>   	u16 best_ld, cur_ld;
>   	u16 best_pd, cur_pd;
>
> +	pcd_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD);
> +	pcd_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD);
> +
> +	if (!is_tft)
> +		pcd_min = 3;
> +
>   	best_pck = 0;
>   	best_ld = 0;
>   	best_pd = 0;
> @@ -2738,7 +2744,7 @@ void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
>   	for (cur_ld = 1; cur_ld<= 255; ++cur_ld) {
>   		unsigned long lck = fck / cur_ld;
>
> -		for (cur_pd = pcd_min; cur_pd<= 255; ++cur_pd) {
> +		for (cur_pd = pcd_min; cur_pd<= pcd_max; ++cur_pd) {
>   			unsigned long pck = lck / cur_pd;
>   			long old_delta = abs(best_pck - req_pck);
>   			long new_delta = abs(pck - req_pck);
> @@ -2773,7 +2779,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
>   {
>   	if (cinfo->lck_div>  255 || cinfo->lck_div = 0)
>   		return -EINVAL;
> -	if (cinfo->pck_div<  2 || cinfo->pck_div>  255)
> +	if (cinfo->pck_div<  1 || cinfo->pck_div>  255)
>   		return -EINVAL;
>
>   	cinfo->lck = dispc_fclk_rate / cinfo->lck_div;
> diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
> index b63c5f8..85b07ca 100644
> --- a/drivers/video/omap2/dss/dss_features.c
> +++ b/drivers/video/omap2/dss/dss_features.c
> @@ -281,6 +281,7 @@ static const char * const omap4_dss_clk_source_names[] = {
>
>   static const struct dss_param_range omap2_dss_param_range[] = {
>   	[FEAT_PARAM_DSS_FCK]			= { 0, 173000000 },
> +	[FEAT_PARAM_DSS_PCD]			= { 2, 255 },
>   	[FEAT_PARAM_DSIPLL_REGN]		= { 0, 0 },
>   	[FEAT_PARAM_DSIPLL_REGM]		= { 0, 0 },
>   	[FEAT_PARAM_DSIPLL_REGM_DISPC]		= { 0, 0 },
> @@ -291,6 +292,7 @@ static const struct dss_param_range omap2_dss_param_range[] = {
>
>   static const struct dss_param_range omap3_dss_param_range[] = {
>   	[FEAT_PARAM_DSS_FCK]			= { 0, 173000000 },
> +	[FEAT_PARAM_DSS_PCD]			= { 1, 255 },
>   	[FEAT_PARAM_DSIPLL_REGN]		= { 0, (1<<  7) - 1 },
>   	[FEAT_PARAM_DSIPLL_REGM]		= { 0, (1<<  11) - 1 },
>   	[FEAT_PARAM_DSIPLL_REGM_DISPC]		= { 0, (1<<  4) - 1 },
> @@ -301,6 +303,7 @@ static const struct dss_param_range omap3_dss_param_range[] = {
>
>   static const struct dss_param_range omap4_dss_param_range[] = {
>   	[FEAT_PARAM_DSS_FCK]			= { 0, 186000000 },
> +	[FEAT_PARAM_DSS_PCD]			= { 1, 255 },
>   	[FEAT_PARAM_DSIPLL_REGN]		= { 0, (1<<  8) - 1 },
>   	[FEAT_PARAM_DSIPLL_REGM]		= { 0, (1<<  12) - 1 },
>   	[FEAT_PARAM_DSIPLL_REGM_DISPC]		= { 0, (1<<  5) - 1 },
> diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
> index 4271e96..158d922 100644
> --- a/drivers/video/omap2/dss/dss_features.h
> +++ b/drivers/video/omap2/dss/dss_features.h
> @@ -73,6 +73,7 @@ enum dss_feat_reg_field {
>
>   enum dss_range_param {
>   	FEAT_PARAM_DSS_FCK,
> +	FEAT_PARAM_DSS_PCD,
>   	FEAT_PARAM_DSIPLL_REGN,
>   	FEAT_PARAM_DSIPLL_REGM,
>   	FEAT_PARAM_DSIPLL_REGM_DISPC,


^ permalink raw reply

* Re: [PATCH 2/4] OMAP4: TWL: Add common omapdss supplies
From: Archit Taneja @ 2011-09-02  6:52 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: linux-omap@vger.kernel.org, linux-fbdev@vger.kernel.org
In-Reply-To: <1314001599-17951-3-git-send-email-tomi.valkeinen@ti.com>

Hi,

On Monday 22 August 2011 01:56 PM, Valkeinen, Tomi wrote:
> OMAP DSS normally gets power from VCXIO on OMAP4. Add configuration for
> this into twl-common.c
>
> Mark VCXIO as always_on, as VCXIO is used by multiple components,
> including the MPU, and turning it off when DSS doesn't need it would
> lead the device to halt.

I had a query. Is this the right place to set always_on to true? Won't 
this lead to VCXIO being always on all omap4 boards? Is it necessary 
that VCXIO will be used to power on MPU for all omap4 boards?

Archit

>
> Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
> ---
>   arch/arm/mach-omap2/twl-common.c |    9 +++++++++
>   1 files changed, 9 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
> index 4f6d216..52243577 100644
> --- a/arch/arm/mach-omap2/twl-common.c
> +++ b/arch/arm/mach-omap2/twl-common.c
> @@ -235,6 +235,12 @@ static struct regulator_init_data omap4_vana_idata = {
>   	},
>   };
>
> +static struct regulator_consumer_supply omap4_vcxio_supply[] = {
> +	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dss"),
> +	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),
> +	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.1"),
> +};
> +
>   static struct regulator_init_data omap4_vcxio_idata = {
>   	.constraints = {
>   		.min_uV			= 1800000,
> @@ -243,7 +249,10 @@ static struct regulator_init_data omap4_vcxio_idata = {
>   					| REGULATOR_MODE_STANDBY,
>   		.valid_ops_mask		= REGULATOR_CHANGE_MODE
>   					| REGULATOR_CHANGE_STATUS,
> +		.always_on		= true,
>   	},
> +	.num_consumer_supplies	= ARRAY_SIZE(omap4_vcxio_supply),
> +	.consumer_supplies	= omap4_vcxio_supply,
>   };
>
>   static struct regulator_init_data omap4_vusb_idata = {


^ permalink raw reply

* Re: [PATCH 3/4] OMAP: DSS2: Handle manager change in apply
From: Archit Taneja @ 2011-09-02  6:51 UTC (permalink / raw)
  To: Valkeinen, Tomi; +Cc: linux-omap@vger.kernel.org, linux-fbdev@vger.kernel.org
In-Reply-To: <1314001636-18036-4-git-send-email-tomi.valkeinen@ti.com>

On Monday 22 August 2011 01:57 PM, Valkeinen, Tomi wrote:
> Currently when changing the manager of an overlay, set_manager() directly
> calls dispc to set the overlay's destination.
>
> Change this to be more in line with other overlay configurations, and
> this will also remove the need to have dispc clocks enabled when calling
> set_manager().
>
> A new field is added to overlay struct, "manager_changed". This is
> similar to "display_changed" field in manager struct, and is used to
> inform apply that the manager has changed and thus write to the
> registers is needed.

I was wondering if it would be better to create an overlay_info member 
called 'channel_out' rather than having 'manager_enabled' at a higher 
level? This way, we won't need to do some of the things below(I have 
pointed them out):

>
> Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
> ---
>   drivers/video/omap2/dss/dispc.c   |    4 +++-
>   drivers/video/omap2/dss/dss.h     |    2 --
>   drivers/video/omap2/dss/manager.c |    5 +++++
>   drivers/video/omap2/dss/overlay.c |    9 ++-------
>   include/video/omapdss.h           |    1 +
>   5 files changed, 11 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
> index 9d9fbeb..003227c 100644
> --- a/drivers/video/omap2/dss/dispc.c
> +++ b/drivers/video/omap2/dss/dispc.c
> @@ -841,7 +841,7 @@ static void _dispc_set_color_mode(enum omap_plane plane,
>   	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
>   }
>
> -void dispc_set_channel_out(enum omap_plane plane,
> +static void dispc_set_channel_out(enum omap_plane plane,
>   		enum omap_channel channel)
>   {
>   	int shift;
> @@ -1860,6 +1860,8 @@ int dispc_setup_plane(enum omap_plane plane,
>   	_dispc_set_pre_mult_alpha(plane, pre_mult_alpha);
>   	_dispc_setup_global_alpha(plane, global_alpha);
>
> +	dispc_set_channel_out(plane, channel);
> +
>   	return 0;
>   }
>
> diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
> index adeff04..ff7ac35 100644
> --- a/drivers/video/omap2/dss/dss.h
> +++ b/drivers/video/omap2/dss/dss.h
> @@ -399,8 +399,6 @@ void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
>   void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
>   void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y);
>   void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height);
> -void dispc_set_channel_out(enum omap_plane plane,
> -		enum omap_channel channel_out);
>
>   void dispc_enable_gamma_table(bool enable);
>   int dispc_setup_plane(enum omap_plane plane,
> diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
> index 63674b0..a6a909a 100644
> --- a/drivers/video/omap2/dss/manager.c
> +++ b/drivers/video/omap2/dss/manager.c
> @@ -1338,6 +1338,11 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
>
>   		oc =&dss_cache.overlay_cache[ovl->id];
>
> +		if (ovl->manager_changed) {
> +			ovl->manager_changed = false;
> +			ovl->info_dirty  = true;
> +		}
> +

We won't need to do this if we created channel_out as an overlay_info 
member. The info will get dirty automatically.

>   		if (!overlay_enabled(ovl)) {
>   			if (oc->enabled) {
>   				oc->enabled = false;
> diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
> index c84380c..ab44403 100644
> --- a/drivers/video/omap2/dss/overlay.c
> +++ b/drivers/video/omap2/dss/overlay.c
> @@ -516,6 +516,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
>   	}
>
>   	ovl->manager = mgr;
> +	ovl->manager_changed = true;
>
>   	/* XXX: When there is an overlay on a DSI manual update display, and
>   	 * the overlay is first disabled, then moved to tv, and enabled, we
> @@ -529,15 +530,12 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
>   	 * Userspace workaround for this is to update the LCD after disabling
>   	 * the overlay, but before moving the overlay to TV.
>   	 */
> -	dispc_set_channel_out(ovl->id, mgr->id);

We would need to do a get_overlay_info/set_overlay_info here, like it is 
done for other overlay sysfs attributes.

>
>   	return 0;
>   }
>
>   static int omap_dss_unset_manager(struct omap_overlay *ovl)
>   {
> -	int r;
> -
>   	if (!ovl->manager) {
>   		DSSERR("failed to detach overlay: manager not set\n");
>   		return -EINVAL;
> @@ -548,11 +546,8 @@ static int omap_dss_unset_manager(struct omap_overlay *ovl)
>   		return -EINVAL;
>   	}
>
> -	r = ovl->wait_for_go(ovl);
> -	if (r)
> -		return r;
> -
>   	ovl->manager = NULL;
> +	ovl->manager_changed = true;
>
>   	return 0;
>   }
> diff --git a/include/video/omapdss.h b/include/video/omapdss.h
> index 9301805..b965f5a 100644
> --- a/include/video/omapdss.h
> +++ b/include/video/omapdss.h
> @@ -326,6 +326,7 @@ struct omap_overlay {
>   	struct omap_overlay_manager *manager;
>   	struct omap_overlay_info info;
>
> +	bool manager_changed;
>   	/* if true, info has been changed, but not applied() yet */
>   	bool info_dirty;
>


^ permalink raw reply

* Re: [PATCH 0/2] video: s3c-fb: Add window positioning support
From: Florian Tobias Schandinat @ 2011-09-01 16:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1314301917-9938-1-git-send-email-ajaykumar.rs@samsung.com>

Hi all,

On 08/25/2011 07:51 PM, Ajay Kumar wrote:
> Just as a note, there are many drivers like mx3fb.c, au1200fb.c and OMAP
> seem to be doing window/plane positioning in their driver code.
> Is it possible to have this window positioning support at a common place?

Good point. Congratulations for figuring out that I like to standardize things.
But I think your suggestion is far from being enough to be useful for userspace
(which is our goal so that applications can be reused along drivers and don't
need to know about individual drivers).

So let me at first summarize how I understand you implemented those things after
having a brief look at some of the drivers:
Windows are rectangular screen areas whose pixel data come from other locations.
The other locations are accessible via other framebuffer devices (e.g. fb1). So
in this area the data of fb1 is shown and not the data of fb0 that would be
normally shown.

So in addition to your proposed positioning I think we should also have the
following to give userspace a useful set of functionality:

- a way to discover how the screen is composited (how many windows are there,
how they are stacked and how to access those)

- a way to enable/disable windows (make them (in)visible)

- reporting and selecting how the window content can be mixed with the root
screen (overwrite, source or destination color keying)

- things like window size and color format could be handled by the usual fb API
used on the window. However there might be restrictions which cause them to be
not 100% API compatible (for example when changing the color format if the
windows are required to have the same format as the root screen)

- do we need to worry about hardware (up/down) scaling of the window content?


So is that what you need for a standardized window implementation?
Any additional things that were useful/needed in this context?
Would you consider adding support for this API in your drivers? (as
standardizing wouldn't be useful if nobody would implement it)


Best regards,

Florian Tobias Schandinat


> 
> For instance, we can have a common struture and ioctl number in 
> include/linux/fb.h as below:
> 
> 	#define FBIOPOS_OVERLAY_WIN    _IOW('F', 0x21, struct fb_overlay_win_pos)
> 
> 	struct fb_overlay_win_pos {
> 		__u32 win_pos_x;  /* x-offset of window from LCD(0,0) */
> 		__u32 win_pos_y;  /* y-offset of window from LCD(0,0) */
> 	};
> 
> where LCD(0,0) means the first pixel of the LCD screen.
> Individual drivers can have implementation for this ioctl.
> 
> To Kukjin Kim,
>   [PATCH 1/2] ARM: SAMSUNG: Add Window Positioning Support for s3c-fb driver
> 
> To Paul Mundt, Florian Tobias Schandinat
>   [PATCH 2/2] video: s3c-fb: Modify s3c-fb driver to support window positioning
> 
>  arch/arm/plat-samsung/include/plat/fb.h |   14 +++++++++++
>  drivers/video/s3c-fb.c                  |   37 ++++++++++++++++++++++++++----
>  2 files changed, 46 insertions(+), 5 deletions(-)
> 
> 


^ permalink raw reply

* Re: [PATCH] fb: avoid possible deadlock caused by fb_set_suspend
From: Guennadi Liakhovetski @ 2011-09-01 16:28 UTC (permalink / raw)
  To: Florian Tobias Schandinat
  Cc: Bruno Prémont, lethal, linux-fbdev, francis.moro, torvalds,
	linux-kernel, Herton Ronaldo Krzesinski, stable
In-Reply-To: <4E5FA7F9.9030802@gmx.de>

Hi Florian

On Thu, 1 Sep 2011, Florian Tobias Schandinat wrote:

> ping
> 
> Guennadi, I really want this issue fixed. Please have a look at Bruno's patch
> otherwise your driver might remain or get even more broken...

Sorry, somehow this patch excaped my attention. Will test tomorrow.

Thanks
Guennadi

> 
> I am scheduling Herton's patch for the next merge window.
> 
> 
> Regards,
> 
> Florian Tobias Schandinat
> 
> 
> On 06/18/2011 09:19 AM, Bruno Prémont wrote:
> > Guennadi, could you have a look at (completely untested) patch which avoids
> > possible deadlock due to inverted lock taking order on hotplug as well
> > as "readding" lock_fb_info() for fb_set_suspend() call after Herton's
> > patch to fb_set_suspend().
> > 
> > Thanks,
> > Bruno
> > 
> > 
> > On Sat, 18 June 2011 Bruno Prémont <bonbons@linux-vserver.org> wrote:
> >> On Fri, 17 June 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de> wrote:
> >>> From: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
> >>>
> >>> A lock ordering issue can cause deadlocks: in framebuffer/console code,
> >>> all needed struct fb_info locks are taken before acquire_console_sem(),
> >>> in places which need to take console semaphore.
> >>>
> >>> But fb_set_suspend is always called with console semaphore held, and
> >>> inside it we call lock_fb_info which gets the fb_info lock, inverse
> >>> locking order of what the rest of the code does. This causes a real
> >>> deadlock issue, when we write to state fb sysfs attribute (which calls
> >>> fb_set_suspend) while a framebuffer is being unregistered by
> >>> remove_conflicting_framebuffers, as can be shown by following show
> >>> blocked state trace on a test program which loads i915 and runs another
> >>> forked processes writing to state attribute:
> >>>
> >>> Test process with semaphore held and trying to get fb_info lock:
> >>
> >> ...
> >>
> >>> fb-test2 which reproduces above is available on kernel.org bug #26232.
> >>> To solve this issue, avoid calling lock_fb_info inside fb_set_suspend,
> >>> and move it out to where needed (callers of fb_set_suspend must call
> >>> lock_fb_info before if needed). So far, the only place which needs to
> >>> call lock_fb_info is store_fbstate, all other places which calls
> >>> fb_set_suspend are suspend/resume hooks that should not need the lock as
> >>> they should be run only when processes are already frozen in
> >>> suspend/resume.
> >>
> >> From a quick look through FB drivers in 2.6.39 I've found one that would need
> >> more work:
> >> - drivers/video/sh_mobile_hdmi.c: sh_hdmi_edid_work_fn()
> >>   Should get changed to
> >>   a) right locking order in case (hdmi->hp_state = HDMI_HOTPLUG_CONNECTED)
> >>   b) lock fb_info in the other case
> >>   For this one fb_set_suspend() does get call in a hotplug worker,
> >>   thus independently on suspend/resume process.
> >>
> >> The rest does match the suspend/resume hook pattern mentioned.
> >>
> >> Bruno
> >>
> >>
> >>> References: https://bugzilla.kernel.org/show_bug.cgi?id&232
> >>> Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
> >>> Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
> >>> Cc: stable@kernel.org
> >>> ---
> >>>  drivers/video/fbmem.c   |    3 ---
> >>>  drivers/video/fbsysfs.c |    3 +++
> >>>  2 files changed, 3 insertions(+), 3 deletions(-)
> >>>
> >>> diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
> >>> index 5aac00e..ad93629 100644
> >>> --- a/drivers/video/fbmem.c
> >>> +++ b/drivers/video/fbmem.c
> >>> @@ -1738,8 +1738,6 @@ void fb_set_suspend(struct fb_info *info, int state)
> >>>  {
> >>>  	struct fb_event event;
> >>>  
> >>> -	if (!lock_fb_info(info))
> >>> -		return;
> >>>  	event.info = info;
> >>>  	if (state) {
> >>>  		fb_notifier_call_chain(FB_EVENT_SUSPEND, &event);
> >>> @@ -1748,7 +1746,6 @@ void fb_set_suspend(struct fb_info *info, int state)
> >>>  		info->state = FBINFO_STATE_RUNNING;
> >>>  		fb_notifier_call_chain(FB_EVENT_RESUME, &event);
> >>>  	}
> >>> -	unlock_fb_info(info);
> >>>  }
> >>>  
> >>>  /**
> >>> diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
> >>> index 04251ce..67afa9c 100644
> >>> --- a/drivers/video/fbsysfs.c
> >>> +++ b/drivers/video/fbsysfs.c
> >>> @@ -399,9 +399,12 @@ static ssize_t store_fbstate(struct device *device,
> >>>  
> >>>  	state = simple_strtoul(buf, &last, 0);
> >>>  
> >>> +	if (!lock_fb_info(fb_info))
> >>> +		return -ENODEV;
> >>>  	console_lock();
> >>>  	fb_set_suspend(fb_info, (int)state);
> >>>  	console_unlock();
> >>> +	unlock_fb_info(fb_info);
> >>>  
> >>>  	return count;
> >>>  }
> > 
> > 
> > diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
> > index 2b9e56a..b1a13ab 100644
> > --- a/drivers/video/sh_mobile_hdmi.c
> > +++ b/drivers/video/sh_mobile_hdmi.c
> > @@ -1151,27 +1151,27 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
> >  
> >  		ch = info->par;
> >  
> > -		console_lock();
> > +		if (lock_fb_info(info)) {
> > +			console_lock();
> >  
> > -		/* HDMI plug in */
> > -		if (!sh_hdmi_must_reconfigure(hdmi) &&
> > -		    info->state = FBINFO_STATE_RUNNING) {
> > -			/*
> > -			 * First activation with the default monitor - just turn
> > -			 * on, if we run a resume here, the logo disappears
> > -			 */
> > -			if (lock_fb_info(info)) {
> > +			/* HDMI plug in */
> > +			if (!sh_hdmi_must_reconfigure(hdmi) &&
> > +			    info->state = FBINFO_STATE_RUNNING) {
> > +				/*
> > +				 * First activation with the default monitor - just turn
> > +				 * on, if we run a resume here, the logo disappears
> > +				 */
> >  				info->var.width = hdmi->var.width;
> >  				info->var.height = hdmi->var.height;
> >  				sh_hdmi_display_on(hdmi, info);
> > -				unlock_fb_info(info);
> > +			} else {
> > +				/* New monitor or have to wake up */
> > +				fb_set_suspend(info, 0);
> >  			}
> > -		} else {
> > -			/* New monitor or have to wake up */
> > -			fb_set_suspend(info, 0);
> > -		}
> >  
> > -		console_unlock();
> > +			console_unlock();
> > +			unlock_fb_info(info);
> > +		}
> >  	} else {
> >  		ret = 0;
> >  		if (!hdmi->info)
> > @@ -1181,12 +1181,15 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
> >  		fb_destroy_modedb(hdmi->monspec.modedb);
> >  		hdmi->monspec.modedb = NULL;
> >  
> > -		console_lock();
> > +		if (lock_fb_info(info)) {
> > +			console_lock();
> >  
> > -		/* HDMI disconnect */
> > -		fb_set_suspend(hdmi->info, 1);
> > +			/* HDMI disconnect */
> > +			fb_set_suspend(hdmi->info, 1);
> >  
> > -		console_unlock();
> > +			console_unlock();
> > +			unlock_fb_info(info);
> > +		}
> >  		pm_runtime_put(hdmi->dev);
> >  	}
> >  
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > 
> 

---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply

* [PATCH] video: mb862xx-i2c: fix for reliable decoder register access
From: Anatolij Gustschin @ 2011-09-01 15:53 UTC (permalink / raw)
  To: linux-fbdev

Increase delay when polling for tx status. This fixes
the unreliable video decoder i2c register access.

Signed-off-by: Anatolij Gustschin <agust@denx.de>
---
 drivers/video/mb862xx/mb862xx-i2c.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/video/mb862xx/mb862xx-i2c.c b/drivers/video/mb862xx/mb862xx-i2c.c
index b953099..934081d 100644
--- a/drivers/video/mb862xx/mb862xx-i2c.c
+++ b/drivers/video/mb862xx/mb862xx-i2c.c
@@ -23,7 +23,7 @@ static int mb862xx_i2c_wait_event(struct i2c_adapter *adap)
 	u32 reg;
 
 	do {
-		udelay(1);
+		udelay(10);
 		reg = inreg(i2c, GC_I2C_BCR);
 		if (reg & (I2C_INT | I2C_BER))
 			break;
-- 
1.7.1


^ permalink raw reply related

* Re: [PATCH] fb: avoid possible deadlock caused by fb_set_suspend
From: Florian Tobias Schandinat @ 2011-09-01 15:42 UTC (permalink / raw)
  To: Guennadi Liakhovetski
  Cc: Bruno Prémont, lethal, linux-fbdev, francis.moro, torvalds,
	linux-kernel, Herton Ronaldo Krzesinski, stable
In-Reply-To: <20110618111934.26203dbf@neptune.home>

ping

Guennadi, I really want this issue fixed. Please have a look at Bruno's patch
otherwise your driver might remain or get even more broken...

I am scheduling Herton's patch for the next merge window.


Regards,

Florian Tobias Schandinat


On 06/18/2011 09:19 AM, Bruno Prémont wrote:
> Guennadi, could you have a look at (completely untested) patch which avoids
> possible deadlock due to inverted lock taking order on hotplug as well
> as "readding" lock_fb_info() for fb_set_suspend() call after Herton's
> patch to fb_set_suspend().
> 
> Thanks,
> Bruno
> 
> 
> On Sat, 18 June 2011 Bruno Prémont <bonbons@linux-vserver.org> wrote:
>> On Fri, 17 June 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de> wrote:
>>> From: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
>>>
>>> A lock ordering issue can cause deadlocks: in framebuffer/console code,
>>> all needed struct fb_info locks are taken before acquire_console_sem(),
>>> in places which need to take console semaphore.
>>>
>>> But fb_set_suspend is always called with console semaphore held, and
>>> inside it we call lock_fb_info which gets the fb_info lock, inverse
>>> locking order of what the rest of the code does. This causes a real
>>> deadlock issue, when we write to state fb sysfs attribute (which calls
>>> fb_set_suspend) while a framebuffer is being unregistered by
>>> remove_conflicting_framebuffers, as can be shown by following show
>>> blocked state trace on a test program which loads i915 and runs another
>>> forked processes writing to state attribute:
>>>
>>> Test process with semaphore held and trying to get fb_info lock:
>>
>> ...
>>
>>> fb-test2 which reproduces above is available on kernel.org bug #26232.
>>> To solve this issue, avoid calling lock_fb_info inside fb_set_suspend,
>>> and move it out to where needed (callers of fb_set_suspend must call
>>> lock_fb_info before if needed). So far, the only place which needs to
>>> call lock_fb_info is store_fbstate, all other places which calls
>>> fb_set_suspend are suspend/resume hooks that should not need the lock as
>>> they should be run only when processes are already frozen in
>>> suspend/resume.
>>
>> From a quick look through FB drivers in 2.6.39 I've found one that would need
>> more work:
>> - drivers/video/sh_mobile_hdmi.c: sh_hdmi_edid_work_fn()
>>   Should get changed to
>>   a) right locking order in case (hdmi->hp_state = HDMI_HOTPLUG_CONNECTED)
>>   b) lock fb_info in the other case
>>   For this one fb_set_suspend() does get call in a hotplug worker,
>>   thus independently on suspend/resume process.
>>
>> The rest does match the suspend/resume hook pattern mentioned.
>>
>> Bruno
>>
>>
>>> References: https://bugzilla.kernel.org/show_bug.cgi?id&232
>>> Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
>>> Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
>>> Cc: stable@kernel.org
>>> ---
>>>  drivers/video/fbmem.c   |    3 ---
>>>  drivers/video/fbsysfs.c |    3 +++
>>>  2 files changed, 3 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
>>> index 5aac00e..ad93629 100644
>>> --- a/drivers/video/fbmem.c
>>> +++ b/drivers/video/fbmem.c
>>> @@ -1738,8 +1738,6 @@ void fb_set_suspend(struct fb_info *info, int state)
>>>  {
>>>  	struct fb_event event;
>>>  
>>> -	if (!lock_fb_info(info))
>>> -		return;
>>>  	event.info = info;
>>>  	if (state) {
>>>  		fb_notifier_call_chain(FB_EVENT_SUSPEND, &event);
>>> @@ -1748,7 +1746,6 @@ void fb_set_suspend(struct fb_info *info, int state)
>>>  		info->state = FBINFO_STATE_RUNNING;
>>>  		fb_notifier_call_chain(FB_EVENT_RESUME, &event);
>>>  	}
>>> -	unlock_fb_info(info);
>>>  }
>>>  
>>>  /**
>>> diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
>>> index 04251ce..67afa9c 100644
>>> --- a/drivers/video/fbsysfs.c
>>> +++ b/drivers/video/fbsysfs.c
>>> @@ -399,9 +399,12 @@ static ssize_t store_fbstate(struct device *device,
>>>  
>>>  	state = simple_strtoul(buf, &last, 0);
>>>  
>>> +	if (!lock_fb_info(fb_info))
>>> +		return -ENODEV;
>>>  	console_lock();
>>>  	fb_set_suspend(fb_info, (int)state);
>>>  	console_unlock();
>>> +	unlock_fb_info(fb_info);
>>>  
>>>  	return count;
>>>  }
> 
> 
> diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
> index 2b9e56a..b1a13ab 100644
> --- a/drivers/video/sh_mobile_hdmi.c
> +++ b/drivers/video/sh_mobile_hdmi.c
> @@ -1151,27 +1151,27 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
>  
>  		ch = info->par;
>  
> -		console_lock();
> +		if (lock_fb_info(info)) {
> +			console_lock();
>  
> -		/* HDMI plug in */
> -		if (!sh_hdmi_must_reconfigure(hdmi) &&
> -		    info->state = FBINFO_STATE_RUNNING) {
> -			/*
> -			 * First activation with the default monitor - just turn
> -			 * on, if we run a resume here, the logo disappears
> -			 */
> -			if (lock_fb_info(info)) {
> +			/* HDMI plug in */
> +			if (!sh_hdmi_must_reconfigure(hdmi) &&
> +			    info->state = FBINFO_STATE_RUNNING) {
> +				/*
> +				 * First activation with the default monitor - just turn
> +				 * on, if we run a resume here, the logo disappears
> +				 */
>  				info->var.width = hdmi->var.width;
>  				info->var.height = hdmi->var.height;
>  				sh_hdmi_display_on(hdmi, info);
> -				unlock_fb_info(info);
> +			} else {
> +				/* New monitor or have to wake up */
> +				fb_set_suspend(info, 0);
>  			}
> -		} else {
> -			/* New monitor or have to wake up */
> -			fb_set_suspend(info, 0);
> -		}
>  
> -		console_unlock();
> +			console_unlock();
> +			unlock_fb_info(info);
> +		}
>  	} else {
>  		ret = 0;
>  		if (!hdmi->info)
> @@ -1181,12 +1181,15 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
>  		fb_destroy_modedb(hdmi->monspec.modedb);
>  		hdmi->monspec.modedb = NULL;
>  
> -		console_lock();
> +		if (lock_fb_info(info)) {
> +			console_lock();
>  
> -		/* HDMI disconnect */
> -		fb_set_suspend(hdmi->info, 1);
> +			/* HDMI disconnect */
> +			fb_set_suspend(hdmi->info, 1);
>  
> -		console_unlock();
> +			console_unlock();
> +			unlock_fb_info(info);
> +		}
>  		pm_runtime_put(hdmi->dev);
>  	}
>  
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fbdev" 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

* Re: [PATCH] fbdev: fix parsing of standard timings
From: Tomi Valkeinen @ 2011-09-01 13:27 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1314362328-30456-1-git-send-email-tomi.valkeinen@ti.com>

On Thu, 2011-09-01 at 13:10 +0000, Florian Tobias Schandinat wrote:
> On 08/30/2011 05:31 AM, Tomi Valkeinen wrote:
> > Hi Florian,
> > 
> > On Fri, 2011-08-26 at 18:02 +0000, Florian Tobias Schandinat wrote:
> >> Hi Tomi,
> >>
> >> On 08/26/2011 12:38 PM, Tomi Valkeinen wrote:
> >>> The standard timings parses uses 1:1 dimensions when the ratio in the
> >>> EDID data is 0. However, for EDID 1.3 and later the dimensions are 16:10
> >>> when the ratio is 0.
> >>>
> >>> Pass the version and revision numbers to get_std_timing() which can then
> >>> make the right decision about dimensions.
> >>>
> >>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> >>
> >> Thanks, looks good to me.
> >> I'd be happy if someone with access to the original EDID specs could confirm
> >> this and add his reviewed by.
> >> I also think adding a comment explaining this change would be helpful.
> > 
> > You can see the same thing done in
> > drivers/gpu/drm/drm_edid.c:drm_mode_std(). Although they seem to check
> > only revision, which looks a bit risky to me.
> > 
> > The specs seem to be available by just googling them, although I don't
> > know if it's legal to distribute them or not...
> > 
> > I've added your comment, I agree it's good. Patch below.
> 
> Looks like your googling is better than mine, I only found references to it.

=). Try "e-edid standard pdf" or "edid standard pdf".

> Anyway, I've applied this patch.

Thanks!

 Tomi



^ permalink raw reply

* Re: [PATCH] fbdev: fix parsing of standard timings
From: Florian Tobias Schandinat @ 2011-09-01 13:10 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1314362328-30456-1-git-send-email-tomi.valkeinen@ti.com>

On 08/30/2011 05:31 AM, Tomi Valkeinen wrote:
> Hi Florian,
> 
> On Fri, 2011-08-26 at 18:02 +0000, Florian Tobias Schandinat wrote:
>> Hi Tomi,
>>
>> On 08/26/2011 12:38 PM, Tomi Valkeinen wrote:
>>> The standard timings parses uses 1:1 dimensions when the ratio in the
>>> EDID data is 0. However, for EDID 1.3 and later the dimensions are 16:10
>>> when the ratio is 0.
>>>
>>> Pass the version and revision numbers to get_std_timing() which can then
>>> make the right decision about dimensions.
>>>
>>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
>>
>> Thanks, looks good to me.
>> I'd be happy if someone with access to the original EDID specs could confirm
>> this and add his reviewed by.
>> I also think adding a comment explaining this change would be helpful.
> 
> You can see the same thing done in
> drivers/gpu/drm/drm_edid.c:drm_mode_std(). Although they seem to check
> only revision, which looks a bit risky to me.
> 
> The specs seem to be available by just googling them, although I don't
> know if it's legal to distribute them or not...
> 
> I've added your comment, I agree it's good. Patch below.

Looks like your googling is better than mine, I only found references to it.
Anyway, I've applied this patch.


Thanks,

Florian Tobias Schandinat

> 
>  Tomi
> 
> 
>>From 82c630291ad39d45009352fce1b23b4d0f44f92d Mon Sep 17 00:00:00 2001
> From: Tomi Valkeinen <tomi.valkeinen@ti.com>
> Date: Thu, 25 Aug 2011 15:36:40 +0300
> Subject: [PATCH] fbdev: fix parsing of standard timings
> 
> The standard timings parses uses 1:1 dimensions when the ratio in the
> EDID data is 0. However, for EDID 1.3 and later the dimensions are 16:10
> when the ratio is 0.
> 
> Pass the version and revision numbers to get_std_timing() which can then
> make the right decision about dimensions.
> 
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> ---
>  drivers/video/fbmon.c |   21 +++++++++++++++------
>  1 files changed, 15 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
> index 4f57485..cef6557 100644
> --- a/drivers/video/fbmon.c
> +++ b/drivers/video/fbmon.c
> @@ -493,7 +493,8 @@ static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
>  	return num;
>  }
>  
> -static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
> +static int get_std_timing(unsigned char *block, struct fb_videomode *mode,
> +		int ver, int rev)
>  {
>  	int xres, yres = 0, refresh, ratio, i;
>  
> @@ -504,7 +505,11 @@ static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
>  	ratio = (block[1] & 0xc0) >> 6;
>  	switch (ratio) {
>  	case 0:
> -		yres = xres;
> +		/* in EDID 1.3 the meaning of 0 changed to 16:10 (prior 1:1) */
> +		if (ver < 1 || (ver = 1 && rev < 3))
> +			yres = xres;
> +		else
> +			yres = (xres * 10)/16;
>  		break;
>  	case 1:
>  		yres = (xres * 3)/4;
> @@ -533,12 +538,12 @@ static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
>  }
>  
>  static int get_dst_timing(unsigned char *block,
> -			  struct fb_videomode *mode)
> +			  struct fb_videomode *mode, int ver, int rev)
>  {
>  	int j, num = 0;
>  
>  	for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE)
> -		num += get_std_timing(block, &mode[num]);
> +		num += get_std_timing(block, &mode[num], ver, rev);
>  
>  	return num;
>  }
> @@ -599,6 +604,10 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
>  	struct fb_videomode *mode, *m;
>  	unsigned char *block;
>  	int num = 0, i, first = 1;
> +	int ver, rev;
> +
> +	ver = edid[EDID_STRUCT_VERSION];
> +	rev = edid[EDID_STRUCT_REVISION];
>  
>  	mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
>  	if (mode = NULL)
> @@ -632,12 +641,12 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
>  	DPRINTK("   Standard Timings\n");
>  	block = edid + STD_TIMING_DESCRIPTIONS_START;
>  	for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE)
> -		num += get_std_timing(block, &mode[num]);
> +		num += get_std_timing(block, &mode[num], ver, rev);
>  
>  	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
>  	for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
>  		if (block[0] = 0x00 && block[1] = 0x00 && block[3] = 0xfa)
> -			num += get_dst_timing(block + 5, &mode[num]);
> +			num += get_dst_timing(block + 5, &mode[num], ver, rev);
>  	}
>  
>  	/* Yikes, EDID data is totally useless */


^ permalink raw reply

* Re: [PATCH RESEND] video: nuc900fb: remove include of mach/clkdev.h
From: Florian Tobias Schandinat @ 2011-09-01 13:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1314836018.2208.3.camel@phoenix>

On 09/01/2011 12:13 AM, Axel Lin wrote:
> Since commit aa3831cf9d29cfeaebd8c2169378b74111364487
> "ARM: Consolidate the clkdev header files",
> the header file arch/arm/mach-nuc93x/include/mach/clkdev.h is removed.
> 
> This patch fixes below build error:
> 
> drivers/video/nuc900fb.c:42:25: error: mach/clkdev.h: No such file or directory
> make[2]: *** [drivers/video/nuc900fb.o] Error 1
> make[1]: *** [drivers/video] Error 2
> make: *** [drivers] Error 2
> 
> Signed-off-by: Axel Lin <axel.lin@gmail.com>

Applied.
I'm wondering whether this build regression was unavoidable...


Thanks,

Florian Tobias Schandinat


> ---
>  drivers/video/nuc900fb.c |    1 -
>  1 files changed, 0 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
> index 0fff5978..37dd850 100644
> --- a/drivers/video/nuc900fb.c
> +++ b/drivers/video/nuc900fb.c
> @@ -39,7 +39,6 @@
>  #include <mach/regs-clock.h>
>  #include <mach/regs-ldm.h>
>  #include <mach/fb.h>
> -#include <mach/clkdev.h>
>  
>  #include "nuc900fb.h"
>  


^ permalink raw reply

* Re: [PATCH RESEND] video: mxsfb: add missing include of linux/module.h
From: Florian Tobias Schandinat @ 2011-09-01 13:01 UTC (permalink / raw)
  To: Axel Lin; +Cc: linux-kernel, Sascha Hauer, Paul Mundt, linux-fbdev
In-Reply-To: <1314835919.2208.1.camel@phoenix>

On 09/01/2011 12:11 AM, Axel Lin wrote:
> Include linux/module.h to fix below build error:
> 
>                  from drivers/video/mxsfb.c:42:
> arch/arm/mach-mxs/include/mach/memory.h:22:1: warning: this is the location of the previous definition
> drivers/video/mxsfb.c:574: error: 'THIS_MODULE' undeclared here (not in a function)
> drivers/video/mxsfb.c:893: warning: data definition has no type or storage class
> drivers/video/mxsfb.c:893: warning: type defaults to 'int' in declaration of 'MODULE_DEVICE_TABLE'
> drivers/video/mxsfb.c:893: warning: parameter names (without types) in function declaration
> drivers/video/mxsfb.c:917: error: expected declaration specifiers or '...' before string constant
> drivers/video/mxsfb.c:917: warning: data definition has no type or storage class
> drivers/video/mxsfb.c:917: warning: type defaults to 'int' in declaration of 'MODULE_DESCRIPTION'
> drivers/video/mxsfb.c:917: warning: function declaration isn't a prototype
> drivers/video/mxsfb.c:918: error: expected declaration specifiers or '...' before string constant
> drivers/video/mxsfb.c:918: warning: data definition has no type or storage class
> drivers/video/mxsfb.c:918: warning: type defaults to 'int' in declaration of 'MODULE_AUTHOR'
> drivers/video/mxsfb.c:918: warning: function declaration isn't a prototype
> drivers/video/mxsfb.c:919: error: expected declaration specifiers or '...' before string constant
> drivers/video/mxsfb.c:919: warning: data definition has no type or storage class
> drivers/video/mxsfb.c:919: warning: type defaults to 'int' in declaration of 'MODULE_LICENSE'
> drivers/video/mxsfb.c:919: warning: function declaration isn't a prototype
> make[2]: *** [drivers/video/mxsfb.o] Error 1
> make[1]: *** [drivers/video] Error 2
> make: *** [drivers] Error 2
> 
> Signed-off-by: Axel Lin <axel.lin@gmail.com>

Applied.


Thanks,

Florian Tobias Schandinat

> ---
>  drivers/video/mxsfb.c |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
> index 0b2f2dd..d837d63 100644
> --- a/drivers/video/mxsfb.c
> +++ b/drivers/video/mxsfb.c
> @@ -39,6 +39,7 @@
>   * the required value in the imx_fb_videomode structure.
>   */
>  
> +#include <linux/module.h>
>  #include <linux/kernel.h>
>  #include <linux/platform_device.h>
>  #include <linux/clk.h>


^ permalink raw reply

* [PATCH RESEND] video: nuc900fb: remove include of mach/clkdev.h
From: Axel Lin @ 2011-09-01  0:13 UTC (permalink / raw)
  To: linux-arm-kernel

Since commit aa3831cf9d29cfeaebd8c2169378b74111364487
"ARM: Consolidate the clkdev header files",
the header file arch/arm/mach-nuc93x/include/mach/clkdev.h is removed.

This patch fixes below build error:

drivers/video/nuc900fb.c:42:25: error: mach/clkdev.h: No such file or directory
make[2]: *** [drivers/video/nuc900fb.o] Error 1
make[1]: *** [drivers/video] Error 2
make: *** [drivers] Error 2

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

diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
index 0fff5978..37dd850 100644
--- a/drivers/video/nuc900fb.c
+++ b/drivers/video/nuc900fb.c
@@ -39,7 +39,6 @@
 #include <mach/regs-clock.h>
 #include <mach/regs-ldm.h>
 #include <mach/fb.h>
-#include <mach/clkdev.h>
 
 #include "nuc900fb.h"
 
-- 
1.7.4.1




^ permalink raw reply related

* [PATCH RESEND] video: mxsfb: add missing include of linux/module.h
From: Axel Lin @ 2011-09-01  0:11 UTC (permalink / raw)
  To: linux-kernel
  Cc: Sascha Hauer, Paul Mundt, linux-fbdev, Florian Tobias Schandinat

Include linux/module.h to fix below build error:

                 from drivers/video/mxsfb.c:42:
arch/arm/mach-mxs/include/mach/memory.h:22:1: warning: this is the location of the previous definition
drivers/video/mxsfb.c:574: error: 'THIS_MODULE' undeclared here (not in a function)
drivers/video/mxsfb.c:893: warning: data definition has no type or storage class
drivers/video/mxsfb.c:893: warning: type defaults to 'int' in declaration of 'MODULE_DEVICE_TABLE'
drivers/video/mxsfb.c:893: warning: parameter names (without types) in function declaration
drivers/video/mxsfb.c:917: error: expected declaration specifiers or '...' before string constant
drivers/video/mxsfb.c:917: warning: data definition has no type or storage class
drivers/video/mxsfb.c:917: warning: type defaults to 'int' in declaration of 'MODULE_DESCRIPTION'
drivers/video/mxsfb.c:917: warning: function declaration isn't a prototype
drivers/video/mxsfb.c:918: error: expected declaration specifiers or '...' before string constant
drivers/video/mxsfb.c:918: warning: data definition has no type or storage class
drivers/video/mxsfb.c:918: warning: type defaults to 'int' in declaration of 'MODULE_AUTHOR'
drivers/video/mxsfb.c:918: warning: function declaration isn't a prototype
drivers/video/mxsfb.c:919: error: expected declaration specifiers or '...' before string constant
drivers/video/mxsfb.c:919: warning: data definition has no type or storage class
drivers/video/mxsfb.c:919: warning: type defaults to 'int' in declaration of 'MODULE_LICENSE'
drivers/video/mxsfb.c:919: warning: function declaration isn't a prototype
make[2]: *** [drivers/video/mxsfb.o] Error 1
make[1]: *** [drivers/video] Error 2
make: *** [drivers] Error 2

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

diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 0b2f2dd..d837d63 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -39,6 +39,7 @@
  * the required value in the imx_fb_videomode structure.
  */
 
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
-- 
1.7.4.1




^ permalink raw reply related

* Re: [PATCH 11/12] OMAP: Panda & Beagle: DVI: Add i2c_bus_num
From: Tomi Valkeinen @ 2011-08-31 18:09 UTC (permalink / raw)
  To: Andy Doan; +Cc: linux-omap, linux-fbdev, archit, mythripk
In-Reply-To: <4E5E4C9B.2010504@linaro.org>

On Wed, 2011-08-31 at 10:00 -0500, Andy Doan wrote:
> On 08/31/2011 08:23 AM, Tomi Valkeinen wrote:
> > Add i2c bus number for DVI output. The driver uses this to detect if a
> > panel is connected and to read EDID.
> >
> > Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
> > ---
> >   arch/arm/mach-omap2/board-omap3beagle.c |    1 +
> >   arch/arm/mach-omap2/board-omap4panda.c  |    1 +
> >   2 files changed, 2 insertions(+), 0 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
> > index 3ae16b4..13244e9 100644
> > --- a/arch/arm/mach-omap2/board-omap3beagle.c
> > +++ b/arch/arm/mach-omap2/board-omap3beagle.c
> > @@ -207,6 +207,7 @@ static struct panel_generic_dpi_data dvi_panel = {
> >   	.name = "generic",
> >   	.platform_enable = beagle_enable_dvi,
> >   	.platform_disable = beagle_disable_dvi,
> > +	.i2c_bus_num = 3,
> >   };
> >
> >   static struct omap_dss_device beagle_dvi_device = {
> > diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
> > index 9aaa960..d5760e3 100644
> > --- a/arch/arm/mach-omap2/board-omap4panda.c
> > +++ b/arch/arm/mach-omap2/board-omap4panda.c
> > @@ -459,6 +459,7 @@ static struct panel_generic_dpi_data omap4_dvi_panel = {
> >   	.name			= "generic",
> >   	.platform_enable	= omap4_panda_enable_dvi,
> >   	.platform_disable	= omap4_panda_disable_dvi,
> > +	.i2c_bus_num = 3,
> >   };
> >
> >   struct omap_dss_device omap4_panda_dvi_device = {
> 
> Can you add a similar patch for board-overo.c? I've tested earlier 
> versions of this patch series on a Tide+Tobi successfully. Here's a copy 
> of my patch:
> 
>    http://tinyurl.com/3cek5m7

Sure. I only added the boards I know have the ddc i2c on bus 3 (i.e.
those I was able to test).

 Tomi



^ permalink raw reply

* Re: [PATCH 11/12] OMAP: Panda & Beagle: DVI: Add i2c_bus_num
From: Andy Doan @ 2011-08-31 15:00 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev, archit, mythripk
In-Reply-To: <1314797003-17638-12-git-send-email-tomi.valkeinen@ti.com>

On 08/31/2011 08:23 AM, Tomi Valkeinen wrote:
> Add i2c bus number for DVI output. The driver uses this to detect if a
> panel is connected and to read EDID.
>
> Signed-off-by: Tomi Valkeinen<tomi.valkeinen@ti.com>
> ---
>   arch/arm/mach-omap2/board-omap3beagle.c |    1 +
>   arch/arm/mach-omap2/board-omap4panda.c  |    1 +
>   2 files changed, 2 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
> index 3ae16b4..13244e9 100644
> --- a/arch/arm/mach-omap2/board-omap3beagle.c
> +++ b/arch/arm/mach-omap2/board-omap3beagle.c
> @@ -207,6 +207,7 @@ static struct panel_generic_dpi_data dvi_panel = {
>   	.name = "generic",
>   	.platform_enable = beagle_enable_dvi,
>   	.platform_disable = beagle_disable_dvi,
> +	.i2c_bus_num = 3,
>   };
>
>   static struct omap_dss_device beagle_dvi_device = {
> diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
> index 9aaa960..d5760e3 100644
> --- a/arch/arm/mach-omap2/board-omap4panda.c
> +++ b/arch/arm/mach-omap2/board-omap4panda.c
> @@ -459,6 +459,7 @@ static struct panel_generic_dpi_data omap4_dvi_panel = {
>   	.name			= "generic",
>   	.platform_enable	= omap4_panda_enable_dvi,
>   	.platform_disable	= omap4_panda_disable_dvi,
> +	.i2c_bus_num = 3,
>   };
>
>   struct omap_dss_device omap4_panda_dvi_device = {

Can you add a similar patch for board-overo.c? I've tested earlier 
versions of this patch series on a Tide+Tobi successfully. Here's a copy 
of my patch:

   http://tinyurl.com/3cek5m7


^ permalink raw reply

* [PATCH 12/12] OMAPFB: find best mode from edid
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen
In-Reply-To: <1314797003-17638-1-git-send-email-tomi.valkeinen@ti.com>

Use the new read_edid() function to get EDID information from the
display (when available), and use the information to use a suitable mode
at initialization time.

Hot-plug is not yet supported, so the timings selected at init time will
stay even if the monitor would be changed.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/omapfb/omapfb-main.c |  109 +++++++++++++++++++++++++++---
 1 files changed, 99 insertions(+), 10 deletions(-)

diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index cd2cae8e..c84cc29 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -2276,6 +2276,87 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
 	return r;
 }
 
+static void fb_videomode_to_omap_timings(struct fb_videomode *m,
+		struct omap_video_timings *t)
+{
+	t->x_res = m->xres;
+	t->y_res = m->yres;
+	t->pixel_clock = PICOS2KHZ(m->pixclock);
+	t->hsw = m->hsync_len;
+	t->hfp = m->right_margin;
+	t->hbp = m->left_margin;
+	t->vsw = m->vsync_len;
+	t->vfp = m->lower_margin;
+	t->vbp = m->upper_margin;
+}
+
+static int omapfb_find_best_mode(struct omap_dss_device *display,
+		struct omap_video_timings *timings)
+{
+	struct fb_monspecs *specs;
+	u8 *edid;
+	int r, i, best_xres, best_idx, len;
+
+	if (!display->driver->read_edid)
+		return -ENODEV;
+
+	len = 0x80 * 2;
+	edid = kmalloc(len, GFP_KERNEL);
+
+	r = display->driver->read_edid(display, edid, len);
+	if (r < 0)
+		goto err1;
+
+	specs = kzalloc(sizeof(*specs), GFP_KERNEL);
+
+	fb_edid_to_monspecs(edid, specs);
+
+	if (edid[126] > 0)
+		fb_edid_add_monspecs(edid + 0x80, specs);
+
+	best_xres = 0;
+	best_idx = -1;
+
+	for (i = 0; i < specs->modedb_len; ++i) {
+		struct fb_videomode *m;
+		struct omap_video_timings t;
+
+		m = &specs->modedb[i];
+
+		if (m->pixclock = 0)
+			continue;
+
+		/* skip repeated pixel modes */
+		if (m->xres = 2880 || m->xres = 1440)
+			continue;
+
+		fb_videomode_to_omap_timings(m, &t);
+
+		r = display->driver->check_timings(display, &t);
+		if (r = 0 && best_xres < m->xres) {
+			best_xres = m->xres;
+			best_idx = i;
+		}
+	}
+
+	if (best_xres = 0) {
+		r = -ENOENT;
+		goto err2;
+	}
+
+	fb_videomode_to_omap_timings(&specs->modedb[best_idx], timings);
+
+	r = 0;
+
+err2:
+	fb_destroy_modedb(specs->modedb);
+	kfree(specs);
+err1:
+	kfree(edid);
+
+	return r;
+}
+
 static int omapfb_init_display(struct omapfb2_device *fbdev,
 		struct omap_dss_device *dssdev)
 {
@@ -2404,9 +2485,27 @@ static int omapfb_probe(struct platform_device *pdev)
 	for (i = 0; i < fbdev->num_managers; i++)
 		fbdev->managers[i] = omap_dss_get_overlay_manager(i);
 
+	/* gfx overlay should be the default one. find a display
+	 * connected to that, and use it as default display */
+	ovl = omap_dss_get_overlay(0);
+	if (ovl->manager && ovl->manager->device) {
+		def_display = ovl->manager->device;
+	} else {
+		dev_warn(&pdev->dev, "cannot find default display\n");
+		def_display = NULL;
+	}
+
 	if (def_mode && strlen(def_mode) > 0) {
 		if (omapfb_parse_def_modes(fbdev))
 			dev_warn(&pdev->dev, "cannot parse default modes\n");
+	} else if (def_display && def_display->driver->set_timings &&
+			def_display->driver->check_timings) {
+		struct omap_video_timings t;
+
+		r = omapfb_find_best_mode(def_display, &t);
+
+		if (r = 0)
+			def_display->driver->set_timings(def_display, &t);
 	}
 
 	r = omapfb_create_framebuffers(fbdev);
@@ -2423,16 +2522,6 @@ static int omapfb_probe(struct platform_device *pdev)
 
 	DBG("mgr->apply'ed\n");
 
-	/* gfx overlay should be the default one. find a display
-	 * connected to that, and use it as default display */
-	ovl = omap_dss_get_overlay(0);
-	if (ovl->manager && ovl->manager->device) {
-		def_display = ovl->manager->device;
-	} else {
-		dev_warn(&pdev->dev, "cannot find default display\n");
-		def_display = NULL;
-	}
-
 	if (def_display) {
 		r = omapfb_init_display(fbdev, def_display);
 		if (r) {
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 11/12] OMAP: Panda & Beagle: DVI: Add i2c_bus_num
From: Tomi Valkeinen @ 2011-08-31 13:23 UTC (permalink / raw)
  To: linux-omap, linux-fbdev; +Cc: archit, mythripk, Tomi Valkeinen
In-Reply-To: <1314797003-17638-1-git-send-email-tomi.valkeinen@ti.com>

Add i2c bus number for DVI output. The driver uses this to detect if a
panel is connected and to read EDID.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 arch/arm/mach-omap2/board-omap3beagle.c |    1 +
 arch/arm/mach-omap2/board-omap4panda.c  |    1 +
 2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 3ae16b4..13244e9 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -207,6 +207,7 @@ static struct panel_generic_dpi_data dvi_panel = {
 	.name = "generic",
 	.platform_enable = beagle_enable_dvi,
 	.platform_disable = beagle_disable_dvi,
+	.i2c_bus_num = 3,
 };
 
 static struct omap_dss_device beagle_dvi_device = {
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 9aaa960..d5760e3 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -459,6 +459,7 @@ static struct panel_generic_dpi_data omap4_dvi_panel = {
 	.name			= "generic",
 	.platform_enable	= omap4_panda_enable_dvi,
 	.platform_disable	= omap4_panda_disable_dvi,
+	.i2c_bus_num = 3,
 };
 
 struct omap_dss_device omap4_panda_dvi_device = {
-- 
1.7.4.1


^ permalink raw reply related


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