Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* [PATCH 2/2] video: s3c-fb: Convert to devm style allocation
From: Mark Brown @ 2011-11-27 22:51 UTC (permalink / raw)
  To: linux-fbdev

Saves some code, especially useful as the code saved is mostly in the
infrequently tested error paths.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
 drivers/video/s3c-fb.c |   32 +++++---------------------------
 1 files changed, 5 insertions(+), 27 deletions(-)

diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 27971bc..c8e822b 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -186,7 +186,6 @@ struct s3c_fb_vsync {
  * struct s3c_fb - overall hardware state of the hardware
  * @slock: The spinlock protection for this data sturcture.
  * @dev: The device that we bound to, for printing, etc.
- * @regs_res: The resource we claimed for the IO registers.
  * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
  * @lcd_clk: The clk (sclk) feeding pixclk.
  * @regs: The mapped hardware registers.
@@ -201,7 +200,6 @@ struct s3c_fb_vsync {
 struct s3c_fb {
 	spinlock_t		slock;
 	struct device		*dev;
-	struct resource		*regs_res;
 	struct clk		*bus_clk;
 	struct clk		*lcd_clk;
 	void __iomem		*regs;
@@ -1341,7 +1339,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	sfb = kzalloc(sizeof(struct s3c_fb), GFP_KERNEL);
+	sfb = devm_kzalloc(dev, sizeof(struct s3c_fb), GFP_KERNEL);
 	if (!sfb) {
 		dev_err(dev, "no memory for framebuffers\n");
 		return -ENOMEM;
@@ -1384,33 +1382,25 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
 		goto err_lcd_clk;
 	}
 
-	sfb->regs_res = request_mem_region(res->start, resource_size(res),
-					   dev_name(dev));
-	if (!sfb->regs_res) {
-		dev_err(dev, "failed to claim register region\n");
-		ret = -ENOENT;
-		goto err_lcd_clk;
-	}
-
-	sfb->regs = ioremap(res->start, resource_size(res));
+	sfb->regs = devm_request_and_ioremap(dev, res);
 	if (!sfb->regs) {
 		dev_err(dev, "failed to map registers\n");
 		ret = -ENXIO;
-		goto err_req_region;
+		goto err_lcd_clk;
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (!res) {
 		dev_err(dev, "failed to acquire irq resource\n");
 		ret = -ENOENT;
-		goto err_ioremap;
+		goto err_lcd_clk;
 	}
 	sfb->irq_no = res->start;
 	ret = request_irq(sfb->irq_no, s3c_fb_irq,
 			  0, "s3c_fb", sfb);
 	if (ret) {
 		dev_err(dev, "irq request failed\n");
-		goto err_ioremap;
+		goto err_lcd_clk;
 	}
 
 	dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);
@@ -1465,12 +1455,6 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
 err_irq:
 	free_irq(sfb->irq_no, sfb);
 
-err_ioremap:
-	iounmap(sfb->regs);
-
-err_req_region:
-	release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
-
 err_lcd_clk:
 	if (!sfb->variant.has_clksel) {
 		clk_disable(sfb->lcd_clk);
@@ -1482,7 +1466,6 @@ err_bus_clk:
 	clk_put(sfb->bus_clk);
 
 err_sfb:
-	kfree(sfb);
 	return ret;
 }
 
@@ -1506,8 +1489,6 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
 
 	free_irq(sfb->irq_no, sfb);
 
-	iounmap(sfb->regs);
-
 	if (!sfb->variant.has_clksel) {
 		clk_disable(sfb->lcd_clk);
 		clk_put(sfb->lcd_clk);
@@ -1516,12 +1497,9 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
 	clk_disable(sfb->bus_clk);
 	clk_put(sfb->bus_clk);
 
-	release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
-
 	pm_runtime_put_sync(sfb->dev);
 	pm_runtime_disable(sfb->dev);
 
-	kfree(sfb);
 	return 0;
 }
 
-- 
1.7.7.3


^ permalink raw reply related

* [PATCH 1/2] video: s3c-fb: Unify runtime and system PM functions
From: Mark Brown @ 2011-11-27 22:51 UTC (permalink / raw)
  To: linux-fbdev

The s3c-fb driver has separate runtime and system PM functions but the
implementations are identical so far as I can tell so unify them for
simplicity.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---

This is a slightly updated version of the patch, previously I forgot to
staticise the pm_ops.

 drivers/video/s3c-fb.c |   75 +-----------------------------------------------
 1 files changed, 1 insertions(+), 74 deletions(-)

diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 12eaee0..27971bc 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -1590,77 +1590,9 @@ static int s3c_fb_resume(struct device *dev)
 
 	return 0;
 }
-
-static int s3c_fb_runtime_suspend(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct s3c_fb *sfb = platform_get_drvdata(pdev);
-	struct s3c_fb_win *win;
-	int win_no;
-
-	for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) {
-		win = sfb->windows[win_no];
-		if (!win)
-			continue;
-
-		/* use the blank function to push into power-down */
-		s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
-	}
-
-	if (!sfb->variant.has_clksel)
-		clk_disable(sfb->lcd_clk);
-
-	clk_disable(sfb->bus_clk);
-	return 0;
-}
-
-static int s3c_fb_runtime_resume(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct s3c_fb *sfb = platform_get_drvdata(pdev);
-	struct s3c_fb_platdata *pd = sfb->pdata;
-	struct s3c_fb_win *win;
-	int win_no;
-
-	clk_enable(sfb->bus_clk);
-
-	if (!sfb->variant.has_clksel)
-		clk_enable(sfb->lcd_clk);
-
-	/* setup gpio and output polarity controls */
-	pd->setup_gpio();
-	writel(pd->vidcon1, sfb->regs + VIDCON1);
-
-	/* zero all windows before we do anything */
-	for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++)
-		s3c_fb_clear_win(sfb, win_no);
-
-	for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) {
-		void __iomem *regs = sfb->regs + sfb->variant.keycon;
-
-		regs += (win_no * 8);
-		writel(0xffffff, regs + WKEYCON0);
-		writel(0xffffff, regs + WKEYCON1);
-	}
-
-	/* restore framebuffers */
-	for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) {
-		win = sfb->windows[win_no];
-		if (!win)
-			continue;
-
-		dev_dbg(&pdev->dev, "resuming window %d\n", win_no);
-		s3c_fb_set_par(win->fbinfo);
-	}
-
-	return 0;
-}
-
 #else
 #define s3c_fb_suspend NULL
 #define s3c_fb_resume  NULL
-#define s3c_fb_runtime_suspend NULL
-#define s3c_fb_runtime_resume NULL
 #endif
 
 
@@ -1985,12 +1917,7 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
 };
 MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids);
 
-static const struct dev_pm_ops s3cfb_pm_ops = {
-	.suspend	= s3c_fb_suspend,
-	.resume		= s3c_fb_resume,
-	.runtime_suspend	= s3c_fb_runtime_suspend,
-	.runtime_resume		= s3c_fb_runtime_resume,
-};
+static UNIVERSAL_DEV_PM_OPS(s3cfb_pm_ops, s3c_fb_suspend, s3c_fb_resume, NULL);
 
 static struct platform_driver s3c_fb_driver = {
 	.probe		= s3c_fb_probe,
-- 
1.7.7.3


^ permalink raw reply related

* Problems with radeon driver under KDE-4.7.2
From: Hendrik Sattler @ 2011-11-27 14:15 UTC (permalink / raw)
  To: linux-fbdev

Hi,

I just upgraded to KDE-4.7.2 and Linux-3.1 and mostly when using Firefox, I 
get issues like a stall screen, then a short blank screen and then it works 
some time until that happens again.

The kernel log then shows something like:
WARNING: at drivers/gpu/drm/radeon/radeon_fence.c:267 
radeon_fence_wait+0x215/0x292()
Hardware name: TravelMate 6592
GPU lockup (waiting for 0x00158B0E last fence id 0x00158B0C)
Modules linked in: [...]
Pid: 12672, comm: Xorg Not tainted 3.1.0 #2
Call Trace:
[<ffffffff8105c51d>] warn_slowpath_common+0x7e/0x96
[<ffffffff8105c5c9>] warn_slowpath_fmt+0x41/0x43
[<ffffffff8128bdad>] radeon_fence_wait+0x215/0x292
[<ffffffff810730fc>] ? abort_exclusive_wait+0x89/0x89
[<ffffffff8128c30c>] radeon_sync_obj_wait+0xc/0xe
[<ffffffff8125f56e>] ttm_bo_wait+0xb8/0x174
[<ffffffff8125ffdb>] ? ttm_bo_list_ref_sub+0x24/0x26
[<ffffffff812a03c0>] radeon_gem_wait_idle_ioctl+0x7c/0xec
[<ffffffff8124d2dd>] drm_ioctl+0x290/0x368
[<ffffffff812a0344>] ? radeon_gem_busy_ioctl+0x112/0x112
[<ffffffff8106993e>] ? set_current_blocked+0x44/0x49
[<ffffffff81028fe8>] ? do_signal+0x554/0x62a
[<ffffffff810e7bf4>] do_vfs_ioctl+0x40d/0x44e
[<ffffffff810293a5>] ? sys_rt_sigreturn+0x1b4/0x1e3
[<ffffffff810e7c77>] sys_ioctl+0x42/0x67
[<ffffffff81513dbb>] system_call_fastpath+0x16/0x1b
---[ end trace ac77b0f03ca6a6bd ]---
radeon 0000:01:00.0: GPU softreset 
radeon 0000:01:00.0:   R_008010_GRBM_STATUS=0xA40034E0
radeon 0000:01:00.0:   R_008014_GRBM_STATUS2=0x00010003
radeon 0000:01:00.0:   R_000E50_SRBM_STATUS=0x200000C0
radeon 0000:01:00.0:   R_008020_GRBM_SOFT_RESET=0x00007FEE
radeon 0000:01:00.0: R_008020_GRBM_SOFT_RESET=0x00000001
radeon 0000:01:00.0:   R_008010_GRBM_STATUS=0xA0003030
radeon 0000:01:00.0:   R_008014_GRBM_STATUS2=0x00000003
radeon 0000:01:00.0:   R_000E50_SRBM_STATUS=0x200080C0
radeon 0000:01:00.0: GPU reset succeed
radeon 0000:01:00.0: WB enabled
[drm] ring test succeeded in 1 usecs
[drm] ib test succeeded in 2 usecs
radeon 0000:01:00.0: GPU lockup CP stall for more than 10000msec


So far, I think it's great that it can recover pretty fine most of the time 
:-)
I now upgraded to Linux-3.1.3 and looked at the KDE setting about the possible
cause for this. New to me was the desktop effect setting about using 
"OpenGL-2-Shader". I deactivated it and its stable so far. Is this a know 
issue?

Note: I also have the some effects disabled that are very slow when scrolling 
windows. My hardware: "ATI Mobility Radeon HD 2400 XT" (ChipID = 0x94c8)



One other question: I saw that vdpau seems to be supported:
[    24.226] (II) RADEON(0): [DRI2]   VDPAU driver: r600
What exactly is needed to use this? I tried "mplayer -vo vdpau" but that only 
gives me:
Failed to open VDPAU backend libvdpau_r600.so: cannot open shared object file: 
No such file or directory
[vdpau] Error when calling vdp_device_create_x11: 1
Error opening/initializing the selected video_out (-vo) device.

Where can I get this file. Latest Debian does not seem to have it...

Regards...

HS


^ permalink raw reply

* [GIT PULL] fbdev fixes for 3.2
From: Florian Tobias Schandinat @ 2011-11-26 19:14 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: LKML, linux-fbdev@vger.kernel.org

Hi Linus,

please pull the following changes to the fbdev subsystem.
Nothing exciting here, just one regression fix for viafb, 3 trivial patches for
OMAP and one patch to fix the reset sequence for da8xx-fb.


Thanks,

Florian Tobias Schandinat


The following changes since commit cfcfc9eca2bcbd26a8e206baeb005b055dbf8e37:

  Linux 3.2-rc2 (2011-11-15 15:02:59 -0200)

are available in the git repository at:
  git://github.com/schandinat/linux-2.6.git fbdev-for-linus

Daniel Drake (1):
      viafb: correct sync polarity for OLPC DCON

Florian Tobias Schandinat (1):
      Merge branch 'for-3.2-rc' of git://gitorious.org/linux-omap-dss2/linux
into fbdev-for-linus

Manjunathappa, Prakash (1):
      video:da8xx-fb: Disable and reset sequence on version2 of LCDC

Tomi Valkeinen (3):
      OMAPDSS: HDMI: fix returned HDMI pixel clock
      OMAPFB: fix compilation warnings due to missing include
      OMAPDSS: DISPC: skip scaling calculations when not scaling

 drivers/video/da8xx-fb.c        |   15 ++++++++++++++-
 drivers/video/omap/dispc.c      |    1 +
 drivers/video/omap2/dss/dispc.c |   11 +++++------
 drivers/video/omap2/dss/hdmi.c  |    2 +-
 drivers/video/via/share.h       |    4 ++--
 5 files changed, 23 insertions(+), 10 deletions(-)

^ permalink raw reply

* [PATCH] video: convert drivers/video/* to use
From: Axel Lin @ 2011-11-26  2:25 UTC (permalink / raw)
  To: linux-kernel
  Cc: Wan ZongShun, Sascha Hauer, Lennert Buytenhek, Ben Dooks,
	Alexey Charkov, Damian Hobson-Garcia, Manuel Lauss,
	Florian Tobias Schandinat, linux-fbdev

This patch converts the drivers in drivers/video/* to use the
module_platform_driver() macro which makes the code smaller and a bit
simpler.

Cc: Wan ZongShun <mcuos.com@gmail.com>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Lennert Buytenhek <buytenh@marvell.com>
Cc: Ben Dooks <ben@simtec.co.uk>
Cc: Alexey Charkov <alchark@gmail.com>
Cc: Damian Hobson-Garcia <dhobsong@igel.co.jp>
Cc: Manuel Lauss <mano@roarinelk.homelinux.net>
Signed-off-by: Axel Lin <axel.lin@gmail.com>
---
 drivers/video/mxsfb.c            |   13 +------------
 drivers/video/nuc900fb.c         |   13 +------------
 drivers/video/pxa168fb.c         |   12 +-----------
 drivers/video/pxa3xx-gcu.c       |   15 +--------------
 drivers/video/s3c-fb.c           |   13 +------------
 drivers/video/sh7760fb.c         |   13 +------------
 drivers/video/sh_mobile_lcdcfb.c |   13 +------------
 drivers/video/sh_mobile_meram.c  |   13 +------------
 drivers/video/sm501fb.c          |   13 +------------
 drivers/video/vt8500lcdfb.c      |   13 +------------
 drivers/video/w100fb.c           |   13 +------------
 drivers/video/wm8505fb.c         |   13 +------------
 drivers/video/wmt_ge_rops.c      |   13 +------------
 drivers/video/xilinxfb.c         |   20 +-------------------
 14 files changed, 14 insertions(+), 176 deletions(-)

diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index d837d63..18742c2 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -902,18 +902,7 @@ static struct platform_driver mxsfb_driver = {
 	},
 };
 
-static int __init mxsfb_init(void)
-{
-	return platform_driver_register(&mxsfb_driver);
-}
-
-static void __exit mxsfb_exit(void)
-{
-	platform_driver_unregister(&mxsfb_driver);
-}
-
-module_init(mxsfb_init);
-module_exit(mxsfb_exit);
+module_platform_driver(mxsfb_devtype);
 
 MODULE_DESCRIPTION("Freescale mxs framebuffer driver");
 MODULE_AUTHOR("Sascha Hauer, Pengutronix");
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
index d1fbbd8..e10f551 100644
--- a/drivers/video/nuc900fb.c
+++ b/drivers/video/nuc900fb.c
@@ -762,18 +762,7 @@ static struct platform_driver nuc900fb_driver = {
 	},
 };
 
-int __devinit nuc900fb_init(void)
-{
-	return platform_driver_register(&nuc900fb_driver);
-}
-
-static void __exit nuc900fb_cleanup(void)
-{
-	platform_driver_unregister(&nuc900fb_driver);
-}
-
-module_init(nuc900fb_init);
-module_exit(nuc900fb_cleanup);
+module_platform_driver(nuc900fb_driver);
 
 MODULE_DESCRIPTION("Framebuffer driver for the NUC900");
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
index 18ead6f..8384b94 100644
--- a/drivers/video/pxa168fb.c
+++ b/drivers/video/pxa168fb.c
@@ -832,17 +832,7 @@ static struct platform_driver pxa168fb_driver = {
 	.remove		= __devexit_p(pxa168fb_remove),
 };
 
-static int __init pxa168fb_init(void)
-{
-	return platform_driver_register(&pxa168fb_driver);
-}
-module_init(pxa168fb_init);
-
-static void __exit pxa168fb_exit(void)
-{
-	platform_driver_unregister(&pxa168fb_driver);
-}
-module_exit(pxa168fb_exit);
+module_platform_driver(pxa168fb_driver);
 
 MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> "
 	      "Green Wan <gwan@marvell.com>");
diff --git a/drivers/video/pxa3xx-gcu.c b/drivers/video/pxa3xx-gcu.c
index 1ed8b36..1d71c08 100644
--- a/drivers/video/pxa3xx-gcu.c
+++ b/drivers/video/pxa3xx-gcu.c
@@ -747,20 +747,7 @@ static struct platform_driver pxa3xx_gcu_driver = {
 	},
 };
 
-static int __init
-pxa3xx_gcu_init(void)
-{
-	return platform_driver_register(&pxa3xx_gcu_driver);
-}
-
-static void __exit
-pxa3xx_gcu_exit(void)
-{
-	platform_driver_unregister(&pxa3xx_gcu_driver);
-}
-
-module_init(pxa3xx_gcu_init);
-module_exit(pxa3xx_gcu_exit);
+module_platform_driver(pxa3xx_gcu_driver);
 
 MODULE_DESCRIPTION("PXA3xx graphics controller unit driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 12eaee0..cf1d11f 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -2003,18 +2003,7 @@ static struct platform_driver s3c_fb_driver = {
 	},
 };
 
-static int __init s3c_fb_init(void)
-{
-	return platform_driver_register(&s3c_fb_driver);
-}
-
-static void __exit s3c_fb_cleanup(void)
-{
-	platform_driver_unregister(&s3c_fb_driver);
-}
-
-module_init(s3c_fb_init);
-module_exit(s3c_fb_cleanup);
+module_platform_driver(s3c_fb_driver);
 
 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("Samsung S3C SoC Framebuffer driver");
diff --git a/drivers/video/sh7760fb.c b/drivers/video/sh7760fb.c
index 45e47d8..83b16e2 100644
--- a/drivers/video/sh7760fb.c
+++ b/drivers/video/sh7760fb.c
@@ -585,18 +585,7 @@ static struct platform_driver sh7760_lcdc_driver = {
 	.remove = __devexit_p(sh7760fb_remove),
 };
 
-static int __init sh7760fb_init(void)
-{
-	return platform_driver_register(&sh7760_lcdc_driver);
-}
-
-static void __exit sh7760fb_exit(void)
-{
-	platform_driver_unregister(&sh7760_lcdc_driver);
-}
-
-module_init(sh7760fb_init);
-module_exit(sh7760fb_exit);
+module_platform_driver(sh7760_lcdc_driver);
 
 MODULE_AUTHOR("Nobuhiro Iwamatsu, Manuel Lauss");
 MODULE_DESCRIPTION("FBdev for SH7760/63 integrated LCD Controller");
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 1f49ab4..a264ebf 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -1709,18 +1709,7 @@ static struct platform_driver sh_mobile_lcdc_driver = {
 	.remove		= sh_mobile_lcdc_remove,
 };
 
-static int __init sh_mobile_lcdc_init(void)
-{
-	return platform_driver_register(&sh_mobile_lcdc_driver);
-}
-
-static void __exit sh_mobile_lcdc_exit(void)
-{
-	platform_driver_unregister(&sh_mobile_lcdc_driver);
-}
-
-module_init(sh_mobile_lcdc_init);
-module_exit(sh_mobile_lcdc_exit);
+module_platform_driver(sh_mobile_lcdc_driver);
 
 MODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver");
 MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
index 4d63490..f45d83e 100644
--- a/drivers/video/sh_mobile_meram.c
+++ b/drivers/video/sh_mobile_meram.c
@@ -679,18 +679,7 @@ static struct platform_driver sh_mobile_meram_driver = {
 	.remove		= sh_mobile_meram_remove,
 };
 
-static int __init sh_mobile_meram_init(void)
-{
-	return platform_driver_register(&sh_mobile_meram_driver);
-}
-
-static void __exit sh_mobile_meram_exit(void)
-{
-	platform_driver_unregister(&sh_mobile_meram_driver);
-}
-
-module_init(sh_mobile_meram_init);
-module_exit(sh_mobile_meram_exit);
+module_platform_driver(sh_mobile_meram_driver);
 
 MODULE_DESCRIPTION("SuperH Mobile MERAM driver");
 MODULE_AUTHOR("Damian Hobson-Garcia / Takanari Hayama");
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index a78254c..3690eff 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -2230,18 +2230,7 @@ static struct platform_driver sm501fb_driver = {
 	},
 };
 
-static int __devinit sm501fb_init(void)
-{
-	return platform_driver_register(&sm501fb_driver);
-}
-
-static void __exit sm501fb_cleanup(void)
-{
-	platform_driver_unregister(&sm501fb_driver);
-}
-
-module_init(sm501fb_init);
-module_exit(sm501fb_cleanup);
+module_platform_driver(sm501fb_driver);
 
 module_param_named(mode, fb_mode, charp, 0);
 MODULE_PARM_DESC(mode,
diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c
index 777c21d..2a5fe6e 100644
--- a/drivers/video/vt8500lcdfb.c
+++ b/drivers/video/vt8500lcdfb.c
@@ -457,18 +457,7 @@ static struct platform_driver vt8500lcd_driver = {
 	},
 };
 
-static int __init vt8500lcd_init(void)
-{
-	return platform_driver_register(&vt8500lcd_driver);
-}
-
-static void __exit vt8500lcd_exit(void)
-{
-	platform_driver_unregister(&vt8500lcd_driver);
-}
-
-module_init(vt8500lcd_init);
-module_exit(vt8500lcd_exit);
+module_platform_driver(vt8500lcd_driver);
 
 MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
 MODULE_DESCRIPTION("LCD controller driver for VIA VT8500");
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index 2375e5b..90a2e30 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -1620,18 +1620,7 @@ static struct platform_driver w100fb_driver = {
 	},
 };
 
-int __init w100fb_init(void)
-{
-	return platform_driver_register(&w100fb_driver);
-}
-
-void __exit w100fb_cleanup(void)
-{
-	platform_driver_unregister(&w100fb_driver);
-}
-
-module_init(w100fb_init);
-module_exit(w100fb_cleanup);
+module_platform_driver(w100fb_driver);
 
 MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c
index 96e34a5..c8703bd 100644
--- a/drivers/video/wm8505fb.c
+++ b/drivers/video/wm8505fb.c
@@ -404,18 +404,7 @@ static struct platform_driver wm8505fb_driver = {
 	},
 };
 
-static int __init wm8505fb_init(void)
-{
-	return platform_driver_register(&wm8505fb_driver);
-}
-
-static void __exit wm8505fb_exit(void)
-{
-	platform_driver_unregister(&wm8505fb_driver);
-}
-
-module_init(wm8505fb_init);
-module_exit(wm8505fb_exit);
+module_platform_driver(wm8505fb_driver);
 
 MODULE_AUTHOR("Ed Spiridonov <edo.rus@gmail.com>");
 MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505");
diff --git a/drivers/video/wmt_ge_rops.c b/drivers/video/wmt_ge_rops.c
index 45832b7..55be386 100644
--- a/drivers/video/wmt_ge_rops.c
+++ b/drivers/video/wmt_ge_rops.c
@@ -167,18 +167,7 @@ static struct platform_driver wmt_ge_rops_driver = {
 	},
 };
 
-static int __init wmt_ge_rops_init(void)
-{
-	return platform_driver_register(&wmt_ge_rops_driver);
-}
-
-static void __exit wmt_ge_rops_exit(void)
-{
-	platform_driver_unregister(&wmt_ge_rops_driver);
-}
-
-module_init(wmt_ge_rops_init);
-module_exit(wmt_ge_rops_exit);
+module_platform_driver(wmt_ge_rops_driver);
 
 MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com");
 MODULE_DESCRIPTION("Accelerators for raster operations using "
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c
index fcb6cd9..1808452 100644
--- a/drivers/video/xilinxfb.c
+++ b/drivers/video/xilinxfb.c
@@ -511,25 +511,7 @@ static struct platform_driver xilinxfb_of_driver = {
 	},
 };
 
-
-/* ---------------------------------------------------------------------
- * Module setup and teardown
- */
-
-static int __init
-xilinxfb_init(void)
-{
-	return platform_driver_register(&xilinxfb_of_driver);
-}
-
-static void __exit
-xilinxfb_cleanup(void)
-{
-	platform_driver_unregister(&xilinxfb_of_driver);
-}
-
-module_init(xilinxfb_init);
-module_exit(xilinxfb_cleanup);
+module_platform_driver(xilinxfb_of_driver);
 
 MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
 MODULE_DESCRIPTION("Xilinx TFT frame buffer driver");
-- 
1.7.5.4




^ permalink raw reply related

* Re: [PATCH v3 1/3] fbdev: Add FOURCC-based format configuration API
From: Florian Tobias Schandinat @ 2011-11-25 22:09 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-fbdev, linux-media, magnus.damm
In-Reply-To: <201111241150.38653.laurent.pinchart@ideasonboard.com>

Hi Laurent,

On 11/24/2011 10:50 AM, Laurent Pinchart wrote:
> Hi Florian,
> 
> Gentle ping ?

Sorry, but I'm very busy at the moment and therefore time-consuming things, like
solving challenging problems, are delayed for some time.

> 
> On Sunday 20 November 2011 11:55:22 Laurent Pinchart wrote:
>> On Sunday 20 November 2011 03:00:33 Florian Tobias Schandinat wrote:
>>> Hi Laurent,
>>>
>>> On 08/31/2011 11:18 AM, Laurent Pinchart wrote:
>>>> This API will be used to support YUV frame buffer formats in a standard
>>>> way.
>>>
>>> looks like the union is causing problems. With this patch applied I get
>>>
>>> errors like this:
>>>   CC [M]  drivers/auxdisplay/cfag12864bfb.o
>>>
>>> drivers/auxdisplay/cfag12864bfb.c:57: error: unknown field ‘red’
>>> specified in initializer
>>
>> *ouch*
>>
>> gcc < 4.6 chokes on anonymous unions initializers :-/
>>
>> [snip]
>>
>>>> @@ -246,12 +251,23 @@ struct fb_var_screeninfo {
>>>>
>>>>  	__u32 yoffset;			/* resolution			*/
>>>>  	
>>>>  	__u32 bits_per_pixel;		/* guess what			*/
>>>>
>>>> -	__u32 grayscale;		/* != 0 Graylevels instead of colors */
>>>>
>>>> -	struct fb_bitfield red;		/* bitfield in fb mem if true color, */
>>>> -	struct fb_bitfield green;	/* else only length is significant */
>>>> -	struct fb_bitfield blue;
>>>> -	struct fb_bitfield transp;	/* transparency			*/
>>>> +	union {
>>>> +		struct {		/* Legacy format API		*/
>>>> +			__u32 grayscale; /* 0 = color, 1 = grayscale	*/
>>>> +			/* bitfields in fb mem if true color, else only */
>>>> +			/* length is significant			*/
>>>> +			struct fb_bitfield red;
>>>> +			struct fb_bitfield green;
>>>> +			struct fb_bitfield blue;
>>>> +			struct fb_bitfield transp;	/* transparency	*/
>>>> +		};
>>>> +		struct {		/* FOURCC-based format API	*/
>>>> +			__u32 fourcc;		/* FOURCC format	*/
>>>> +			__u32 colorspace;
>>>> +			__u32 reserved[11];
>>>> +		} fourcc;
>>>> +	};
>>
>> We can't name the union, otherwise this will change the userspace API.
>>
>> We could "fix" the problem on the kernel side with
>>
>> #ifdef __KERNEL__
>> 	} color;
>> #else
>> 	};
>> #endif
> 
> (and the structure that contains the grayscale, red, green, blue and transp 
> fields would need to be similarly named, the "rgb" name comes to mind)

Which, I guess, would require modifying all drivers?
I don't consider that a good idea. Maybe the simplest solution would be to drop
the union idea and just accept an utterly misleading name "grayscale" for
setting the FOURCC value. The colorspace could use one of the reserved fields at
the end or do you worry that we need to add a lot of other things?


Best regards,

Florian Tobias Schandinat

> 
>> That's quite hackish though... What's your opinion ?
>>
>> It would also not handle userspace code that initializes an
>> fb_var_screeninfo structure with named initializers, but that shouldn't
>> happen, as application should read fb_var_screeninfo , modify it and write
>> it back.
>>
>>>>  	__u32 nonstd;			/* != 0 Non standard pixel format */
> 


^ permalink raw reply

* Re: [PATCH] video:da8xx-fb: Add 24bpp LCD configuration support
From: Florian Tobias Schandinat @ 2011-11-25 21:28 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1321358479-20390-1-git-send-email-prakash.pm@ti.com>

On 11/25/2011 07:45 AM, Manjunathappa, Prakash wrote:
> Hi Florian Tobias Schandinat
> 
> On Sun, Nov 20, 2011 at 06:11:44, Florian Tobias Schandinat wrote:
>> On 11/15/2011 12:01 PM, Manjunathappa, Prakash wrote:
>>> LCD controller on am335x supports 24bpp raster configuration
>>> in addition to ones on da850. LCDC also supports 24bpp in unpacked
>>> format having ARGB:8888 32bpp format data in DDR, but it doesn't
>>> interpret Alpha component of the data.
>>>
>>> Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
>>> ---
>>>  drivers/video/da8xx-fb.c |   57 +++++++++++++++++++++++++++++++++++++++++++++-
>>>  1 files changed, 56 insertions(+), 1 deletions(-)
>>>
>>> diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
>>> index 55f91d9..e111971 100644
>>> --- a/drivers/video/da8xx-fb.c
>>> +++ b/drivers/video/da8xx-fb.c
>>> @@ -82,6 +82,8 @@
>>>  #define LCD_V2_LIDD_CLK_EN		BIT(1)
>>>  #define LCD_V2_CORE_CLK_EN		BIT(0)
>>>  #define LCD_V2_LPP_B10			26
>>> +#define LCD_V2_TFT_24BPP_MODE		BIT(25)
>>> +#define LCD_V2_TFT_24BPP_UNPACK		BIT(26)
>>>  
>>>  /* LCD Raster Timing 2 Register */
>>>  #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x)	((x) << 16)
>>> @@ -151,7 +153,7 @@ struct da8xx_fb_par {
>>>  	unsigned int		dma_end;
>>>  	struct clk *lcdc_clk;
>>>  	int irq;
>>> -	unsigned short pseudo_palette[16];
>>> +	unsigned short pseudo_palette[32];
>>
>> This looks wrong, include/linux/fb.h says:
>> "void *pseudo_palette;           /* Fake palette of 16 colors */"
>> This will probably also simplify the code below to write to the pseudo palette.
>> But I think you have to increase the data type of the palette, maybe to u32?
>>
>>
> 
> Yes, I accept that data type has to be changed to u32. But how does it simplify updating of pseudo palette.

Your code is even buggier than I saw. Where did you get the information how to
write fb_setcolreg?
First, as I wrote in my last mail, the pseudo_palette has always exactly 16
colors, regardless of the color depth.
Second, the existing code is some sort of wrong to check for bpp the only thing
that really matters is whether it is Truecolor or not, the code for handling the
Truecolor case will very likely be always the same regardless of the bpp, just
the values in {red,green,blue}{length,offset} differ.
Third your patch is wrong in using 24 in things like
red >>= (24 - info->var.red.length);
skeletonfb.c: "The values supplied have a 16 bit magnitude which needs to be
scaled in this function for the hardware."
So it has to be 16, always.

Just have a look at drivers/video/skeletonfb.c, it contains much useful information.


Best regards,

Florian Tobias Schandinat

> 
> Thanks,
> Prakash
> 
>> Best regards,
>>
>> Florian Tobias Schandinat
>>
>>>  	unsigned int palette_sz;
>>>  	unsigned int pxl_clk;
>>>  	int blank;
>>> @@ -458,6 +460,9 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
>>>  {
>>>  	u32 reg;
>>>  
>>> +	if ((bpp > 16) && (lcd_revision = LCD_VERSION_1))
>>> +		return -EINVAL;
>>> +
>>>  	/* Set the Panel Width */
>>>  	/* Pixels per line = (PPL + 1)*16 */
>>>  	if (lcd_revision = LCD_VERSION_1) {
>>> @@ -501,6 +506,13 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
>>>  	reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8);
>>>  	if (raster_order)
>>>  		reg |= LCD_RASTER_ORDER;
>>> +
>>> +	if (bpp = 24)
>>> +		reg |= (LCD_TFT_MODE | LCD_V2_TFT_24BPP_MODE);
>>> +	else if (bpp = 32)
>>> +		reg |= (LCD_TFT_MODE | LCD_V2_TFT_24BPP_MODE
>>> +				| LCD_V2_TFT_24BPP_UNPACK);
>>> +
>>>  	lcdc_write(reg, LCD_RASTER_CTRL_REG);
>>>  
>>>  	switch (bpp) {
>>> @@ -508,6 +520,8 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
>>>  	case 2:
>>>  	case 4:
>>>  	case 16:
>>> +	case 24:
>>> +	case 32:
>>>  		par->palette_sz = 16 * 2;
>>>  		break;
>>>  
>>> @@ -537,6 +551,9 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
>>>  	if (info->fix.visual = FB_VISUAL_DIRECTCOLOR)
>>>  		return 1;
>>>  
>>> +	if ((info->var.bits_per_pixel > 16) && (lcd_revision = LCD_VERSION_1))
>>> +		return 1;
>>> +
>>>  	if (info->var.bits_per_pixel = 8) {
>>>  		red >>= 4;
>>>  		green >>= 8;
>>> @@ -566,6 +583,23 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
>>>  			update_hw = 1;
>>>  			palette[0] = 0x4000;
>>>  		}
>>> +	} else if (((info->var.bits_per_pixel = 32) && regno < 32) ||
>>> +		    ((info->var.bits_per_pixel = 24) && regno < 24)) {
>>> +		red >>= (24 - info->var.red.length);
>>> +		red <<= info->var.red.offset;
>>> +
>>> +		green >>= (24 - info->var.green.length);
>>> +		green <<= info->var.green.offset;
>>> +
>>> +		blue >>= (24 - info->var.blue.length);
>>> +		blue <<= info->var.blue.offset;
>>> +
>>> +		par->pseudo_palette[regno] = red | green | blue;
>>> +
>>> +		if (palette[0] != 0x4000) {
>>> +			update_hw = 1;
>>> +			palette[0] = 0x4000;
>>> +		}
>>>  	}
>>>  
>>>  	/* Update the palette in the h/w as needed. */
>>> @@ -777,6 +811,9 @@ static int fb_check_var(struct fb_var_screeninfo *var,
>>>  {
>>>  	int err = 0;
>>>  
>>> +	if ((var->bits_per_pixel > 16) && (lcd_revision = LCD_VERSION_1))
>>> +		return -EINVAL;
>>> +
>>>  	switch (var->bits_per_pixel) {
>>>  	case 1:
>>>  	case 8:
>>> @@ -809,6 +846,24 @@ static int fb_check_var(struct fb_var_screeninfo *var,
>>>  		var->transp.offset = 0;
>>>  		var->transp.length = 0;
>>>  		break;
>>> +	case 24:
>>> +		var->red.offset = 16;
>>> +		var->red.length = 8;
>>> +		var->green.offset = 8;
>>> +		var->green.length = 8;
>>> +		var->blue.offset = 0;
>>> +		var->blue.length = 8;
>>> +		break;
>>> +	case 32:
>>> +		var->transp.offset = 24;
>>> +		var->transp.length = 8;
>>> +		var->red.offset = 16;
>>> +		var->red.length = 8;
>>> +		var->green.offset = 8;
>>> +		var->green.length = 8;
>>> +		var->blue.offset = 0;
>>> +		var->blue.length = 8;
>>> +		break;
>>>  	default:
>>>  		err = -EINVAL;
>>>  	}
>>
>>
> 
> 


^ permalink raw reply

* [PATCH] video: s3c-fb: Unify runtime and system PM functions
From: Mark Brown @ 2011-11-25 18:55 UTC (permalink / raw)
  To: linux-fbdev

The s3c-fb driver has separate runtime and system PM functions but the
implementations are identical so far as I can tell so unify them for
simplicity.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
 drivers/video/s3c-fb.c |   75 +-----------------------------------------------
 1 files changed, 1 insertions(+), 74 deletions(-)

diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 12eaee0..0860590 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -1590,77 +1590,9 @@ static int s3c_fb_resume(struct device *dev)
 
 	return 0;
 }
-
-static int s3c_fb_runtime_suspend(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct s3c_fb *sfb = platform_get_drvdata(pdev);
-	struct s3c_fb_win *win;
-	int win_no;
-
-	for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) {
-		win = sfb->windows[win_no];
-		if (!win)
-			continue;
-
-		/* use the blank function to push into power-down */
-		s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
-	}
-
-	if (!sfb->variant.has_clksel)
-		clk_disable(sfb->lcd_clk);
-
-	clk_disable(sfb->bus_clk);
-	return 0;
-}
-
-static int s3c_fb_runtime_resume(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct s3c_fb *sfb = platform_get_drvdata(pdev);
-	struct s3c_fb_platdata *pd = sfb->pdata;
-	struct s3c_fb_win *win;
-	int win_no;
-
-	clk_enable(sfb->bus_clk);
-
-	if (!sfb->variant.has_clksel)
-		clk_enable(sfb->lcd_clk);
-
-	/* setup gpio and output polarity controls */
-	pd->setup_gpio();
-	writel(pd->vidcon1, sfb->regs + VIDCON1);
-
-	/* zero all windows before we do anything */
-	for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++)
-		s3c_fb_clear_win(sfb, win_no);
-
-	for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) {
-		void __iomem *regs = sfb->regs + sfb->variant.keycon;
-
-		regs += (win_no * 8);
-		writel(0xffffff, regs + WKEYCON0);
-		writel(0xffffff, regs + WKEYCON1);
-	}
-
-	/* restore framebuffers */
-	for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) {
-		win = sfb->windows[win_no];
-		if (!win)
-			continue;
-
-		dev_dbg(&pdev->dev, "resuming window %d\n", win_no);
-		s3c_fb_set_par(win->fbinfo);
-	}
-
-	return 0;
-}
-
 #else
 #define s3c_fb_suspend NULL
 #define s3c_fb_resume  NULL
-#define s3c_fb_runtime_suspend NULL
-#define s3c_fb_runtime_resume NULL
 #endif
 
 
@@ -1985,12 +1917,7 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
 };
 MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids);
 
-static const struct dev_pm_ops s3cfb_pm_ops = {
-	.suspend	= s3c_fb_suspend,
-	.resume		= s3c_fb_resume,
-	.runtime_suspend	= s3c_fb_runtime_suspend,
-	.runtime_resume		= s3c_fb_runtime_resume,
-};
+UNIVERSAL_DEV_PM_OPS(s3cfb_pm_ops, s3c_fb_suspend, s3c_fb_resume, NULL);
 
 static struct platform_driver s3c_fb_driver = {
 	.probe		= s3c_fb_probe,
-- 
1.7.7.3


^ permalink raw reply related

* RE: [PATCH] video:da8xx-fb: Add 24bpp LCD configuration support
From: Manjunathappa, Prakash @ 2011-11-25  7:45 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1321358479-20390-1-git-send-email-prakash.pm@ti.com>

Hi Florian Tobias Schandinat

On Sun, Nov 20, 2011 at 06:11:44, Florian Tobias Schandinat wrote:
> On 11/15/2011 12:01 PM, Manjunathappa, Prakash wrote:
> > LCD controller on am335x supports 24bpp raster configuration
> > in addition to ones on da850. LCDC also supports 24bpp in unpacked
> > format having ARGB:8888 32bpp format data in DDR, but it doesn't
> > interpret Alpha component of the data.
> > 
> > Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
> > ---
> >  drivers/video/da8xx-fb.c |   57 +++++++++++++++++++++++++++++++++++++++++++++-
> >  1 files changed, 56 insertions(+), 1 deletions(-)
> > 
> > diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
> > index 55f91d9..e111971 100644
> > --- a/drivers/video/da8xx-fb.c
> > +++ b/drivers/video/da8xx-fb.c
> > @@ -82,6 +82,8 @@
> >  #define LCD_V2_LIDD_CLK_EN		BIT(1)
> >  #define LCD_V2_CORE_CLK_EN		BIT(0)
> >  #define LCD_V2_LPP_B10			26
> > +#define LCD_V2_TFT_24BPP_MODE		BIT(25)
> > +#define LCD_V2_TFT_24BPP_UNPACK		BIT(26)
> >  
> >  /* LCD Raster Timing 2 Register */
> >  #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x)	((x) << 16)
> > @@ -151,7 +153,7 @@ struct da8xx_fb_par {
> >  	unsigned int		dma_end;
> >  	struct clk *lcdc_clk;
> >  	int irq;
> > -	unsigned short pseudo_palette[16];
> > +	unsigned short pseudo_palette[32];
> 
> This looks wrong, include/linux/fb.h says:
> "void *pseudo_palette;           /* Fake palette of 16 colors */"
> This will probably also simplify the code below to write to the pseudo palette.
> But I think you have to increase the data type of the palette, maybe to u32?
> 
> 

Yes, I accept that data type has to be changed to u32. But how does it simplify updating of pseudo palette.

Thanks,
Prakash

> Best regards,
> 
> Florian Tobias Schandinat
> 
> >  	unsigned int palette_sz;
> >  	unsigned int pxl_clk;
> >  	int blank;
> > @@ -458,6 +460,9 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
> >  {
> >  	u32 reg;
> >  
> > +	if ((bpp > 16) && (lcd_revision = LCD_VERSION_1))
> > +		return -EINVAL;
> > +
> >  	/* Set the Panel Width */
> >  	/* Pixels per line = (PPL + 1)*16 */
> >  	if (lcd_revision = LCD_VERSION_1) {
> > @@ -501,6 +506,13 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
> >  	reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8);
> >  	if (raster_order)
> >  		reg |= LCD_RASTER_ORDER;
> > +
> > +	if (bpp = 24)
> > +		reg |= (LCD_TFT_MODE | LCD_V2_TFT_24BPP_MODE);
> > +	else if (bpp = 32)
> > +		reg |= (LCD_TFT_MODE | LCD_V2_TFT_24BPP_MODE
> > +				| LCD_V2_TFT_24BPP_UNPACK);
> > +
> >  	lcdc_write(reg, LCD_RASTER_CTRL_REG);
> >  
> >  	switch (bpp) {
> > @@ -508,6 +520,8 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
> >  	case 2:
> >  	case 4:
> >  	case 16:
> > +	case 24:
> > +	case 32:
> >  		par->palette_sz = 16 * 2;
> >  		break;
> >  
> > @@ -537,6 +551,9 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
> >  	if (info->fix.visual = FB_VISUAL_DIRECTCOLOR)
> >  		return 1;
> >  
> > +	if ((info->var.bits_per_pixel > 16) && (lcd_revision = LCD_VERSION_1))
> > +		return 1;
> > +
> >  	if (info->var.bits_per_pixel = 8) {
> >  		red >>= 4;
> >  		green >>= 8;
> > @@ -566,6 +583,23 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
> >  			update_hw = 1;
> >  			palette[0] = 0x4000;
> >  		}
> > +	} else if (((info->var.bits_per_pixel = 32) && regno < 32) ||
> > +		    ((info->var.bits_per_pixel = 24) && regno < 24)) {
> > +		red >>= (24 - info->var.red.length);
> > +		red <<= info->var.red.offset;
> > +
> > +		green >>= (24 - info->var.green.length);
> > +		green <<= info->var.green.offset;
> > +
> > +		blue >>= (24 - info->var.blue.length);
> > +		blue <<= info->var.blue.offset;
> > +
> > +		par->pseudo_palette[regno] = red | green | blue;
> > +
> > +		if (palette[0] != 0x4000) {
> > +			update_hw = 1;
> > +			palette[0] = 0x4000;
> > +		}
> >  	}
> >  
> >  	/* Update the palette in the h/w as needed. */
> > @@ -777,6 +811,9 @@ static int fb_check_var(struct fb_var_screeninfo *var,
> >  {
> >  	int err = 0;
> >  
> > +	if ((var->bits_per_pixel > 16) && (lcd_revision = LCD_VERSION_1))
> > +		return -EINVAL;
> > +
> >  	switch (var->bits_per_pixel) {
> >  	case 1:
> >  	case 8:
> > @@ -809,6 +846,24 @@ static int fb_check_var(struct fb_var_screeninfo *var,
> >  		var->transp.offset = 0;
> >  		var->transp.length = 0;
> >  		break;
> > +	case 24:
> > +		var->red.offset = 16;
> > +		var->red.length = 8;
> > +		var->green.offset = 8;
> > +		var->green.length = 8;
> > +		var->blue.offset = 0;
> > +		var->blue.length = 8;
> > +		break;
> > +	case 32:
> > +		var->transp.offset = 24;
> > +		var->transp.length = 8;
> > +		var->red.offset = 16;
> > +		var->red.length = 8;
> > +		var->green.offset = 8;
> > +		var->green.length = 8;
> > +		var->blue.offset = 0;
> > +		var->blue.length = 8;
> > +		break;
> >  	default:
> >  		err = -EINVAL;
> >  	}
> 
> 


^ permalink raw reply

* Re: [RFC] Virtual CRTCs (proposal + experimental code)
From: Ilija Hadzic @ 2011-11-25  5:11 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: linux-fbdev, dri-devel
In-Reply-To: <20111124105249.GA3867@phenom.ffwll.local>


>
> So I think we do have enough people interested in this and should be able
> to cobble together something that does The Right Thing.
>

We indeed have a non-trivial set of people interested in the same set of 
problems and each of us has partial and maybe competing solution. I want 
to make it clear that my, maybe disruptive and different from the 
plan-of-record, proposal should not be viewed as destructive or 
distracting. I am just offering to the community what I think is useful.

If this discussion sparks some joint effort that will bring us to the 
solution that everyone is happy with, even if no line of my code is found 
useful, I am perfectly fine with that (and I'll join the effort).

So at this point I think I should put out my back-of-the-napkin 
desiderata. That will hopefully shed some light on where I am coming from 
with VCRTCM proposal.

I want to be able to pull pixels out of the GPU and redirect them to an 
arbitrary device that can do something useful with them. This should not 
be limited to shooting photons into human eyeballs. I want to be able to 
run my applications without having to run X. I'd like the solution to be 
transparent to the application; that is, if I can write an application 
that can render something to a full screen, I want to redirect that 
"screen" to wherever I want without having to rewrite, recompile or relink 
the application. Actually, I want to do that redirection at runtime. I'd 
like to support all of the above in a way that it can also help solve more 
imminent shotcomings of Linux graphics system (Optimus, DisplayLink, etc. 
... cf. previous E-mails in this thread). I'd like it to work with 
multiple render nodes on the same GPU (something like Dave's multiseat 
work, in which both GPU and its display resources are virtual).

The logical consequence of this is that the render node and the display 
node should at some point become logically separate (different driver 
modules) even if they are physically on the same GPU. They are really two 
different subsystems that just happen to reside on the same circuit 
board, so it makes sense to separate them.

I don't think what I am saying is anything unique and what I said probably 
overlaps in good part with what others also want from the graphics 
subsystem. I can see the role of VCRTCM in all of the above, but I am 
open-minded. If we end up with a solution that has nothing to do with 
VCRTCM, I have no emotional ties with my code (and code of my colleagues 
that worked with me so far).

-- Ilija



^ permalink raw reply

* Re: [RFC] Virtual CRTCs (proposal + experimental code)
From: Ilija Hadzic @ 2011-11-25  4:08 UTC (permalink / raw)
  To: Dave Airlie; +Cc: linux-fbdev, dri-devel
In-Reply-To: <CAPM=9tx3ue8+PQ6QBxL_0Do2kLB01Q0yN-FOZrJkY2RKiyNm4Q@mail.gmail.com>



On Thu, 24 Nov 2011, Dave Airlie wrote:

> Okay so thats pretty much how I expected it to work, I don't think
> Virtual makes sense for a displaylink attached device though,
> again if you were using a real driver you would just re-use whatever
> output type it uses, though I'm not sure how well that works,

That is the consequence of the fact that virtual CRTCs are created at 
startup time when attached CTD is not known, while CTDs are attached at 
runtime. So when I register the virtual CRTC and the associated connector 
I have to use something for the connector type.

Admitting that my logic is biased by my design, to me "Virtual" connector 
type is an indicative that from GPU's perspective it's a connector that 
does not physically exist and is yet to be attached to some real display 
device. At that point the properties of the attached display become known 
to the system.

>
> Do you propogate full EDID information and all the modes or just the
> supported modes? we use this in userspace to put monitor names in
> GNOME display settings etc.
>

Right now we propagate the entire list of modes that the attached CTD 
device has queried from the connected display (monitor). Propagating full 
EDID is really easy to add. That's if the CTD is driver for some real 
display. If CTD is just a "make-believe" display whose purpose is to be 
the conduit to some other pixel-processing component (e.g. V4L2CTD), then 
at some point in the chain we have to make up the set of modes that the 
logical display accepts and in that case the EDID does not exist by 
definition.

> what does xrandr output looks like for a radeon GPU with 4 vcrtcs? do
> you see 4 disconnected connectors? that again isn't a pretty user
> experience.
>

Yes it shows 4 disconnected monitors. To me that is a logical consequence 
of the design in which virtual CRTCs and associated virtual connectors are 
always there. By know, it's clear to me that you are not too thrilled 
about it, but please allow me to turn the question back to you: in your 
solution with udl-v2 driver and a dedicated DDX for it, can you do the big 
desktop that spans across GPU's local and "foreign" displays and have 
acceleration on both? If not, what would it take you to get there and how 
complex the end result will be?

I'll get to Optimus/PRIME use case later, but if we for the moment focus 
on the use case in which a dumb framebuffer device extens the number of 
displays of a rendering-capable GPU, I think that VCRTCM offers quite a 
complete and universal solution and it is completely transparent with 
regard to the application, window manager, and display server.

Radeon + DisplayLink is the specific example. But in general it's Any GPU 
+ Any fbdev. It's not just one use case, it's a whole class of use cases
that would follow the same principle and for then the VCRTC alone 
suffices.


> My main problem with this is as I'll explain below it only covers some
> of the use cases, and I don't want a 50% solution at this point, by
> doing something like this you are making it harder to get proper
> support into something like wayland as they can ignore some of the
> problems, however since this doesn't solve all the other problems it
> means getting to a finished solution is actually less likely to
> happen.
>

I presume that by 50% solution you are referring to Optimus/PRIME use 
case. That case actually consists of two related, but different problems. 
First is "render on node X and display on node Y" and the second is 
"dynamically and hitlessly switch rendering between node X and Y".

I have never claimed that VCRTCs solve the second problem (I could switch 
by restarting Xorg, but I know that this is not the solution you are 
looking for). I fully understand why you want both problems solved at the 
same time. However, I don't understand why solving one first would inhibit 
solving the other.

On the other hand, the Radeon + DisplayLink tandem use case (or in general 
GPU + fbdev tandem) consists only of "render on X, display on Y" problem. 
Here, you will probably say that there one can switch between hardware and 
software rendering and that it also has both problems. That is true, but 
unlike the Optimus/PRIME use case, using fbdev as a display extension to 
GPU is still useful alone. My point is that there is a value in solving 
first one problem and then follow with the other.

I think the crux of the problem is that you are not convinced that the
VCRTCM solution for problem #1 will make solving problem #2 easier and 
maybe you are afraid that it will make it harder. If that's a fair 
statement and if having me create an existence proof for problem #2 that 
still uses VCRTCM will help bring our positions closer, I am perfectly 
willing to do so .... I guess I've just signed up for some hacking ;-)

Note that for hitless GPU switching, I fully agree that support must be in 
userspace (you have to swap out paths in Mesa and DDX before even getting 
to kernel), but like I said, that is a separate problem from redirecting 
the display to another node.


> r600 has 16 tiling
> modes (we might only see 2 of these on scanout)

But VCRTC emulates a CRTC, so the only ones relevant are those that we see 
on the scnout. Do we really anticipate using all 16 for CRTC buffers ?

>
> The thing is this is how optimus works, the nvidia gpus have an engine
> that you can program to move data from the nvidia tiled VRAM format to
> the intel main memory tiled format, and make if efficent. radeon's
> also have some engines that AMD so far haven't told us about, but
> someone with no NDA with AMD could easily start REing that sort of
> thing.
>

If we could have every GPU efficiently push out pixels in some "common 
denominator" format that would be ideal, but at this time, the reality is 
far from it. Whether the obstacles are technical or legal, doesn't matter.

I fully understand your concern about the number of tiling/detiling 
combinations getting out of control, but I am not sure that the problem is 
as bad as you picture it if CRTC buffer uses only a subset of available 
tiling modes.



>
> Switchable/Optimus mode has two modes of operation,
>
> a) nvidia GPU is rendering engine and the intel GPU is just used as a
> scanout buffer for the LVDS panel. This mode is used when an external
> digital display is plugged in, or in some plugged in configurations.
>
> b) intel GPU is primary rendering engine, and the nvidia gpu is used
> as an offload engine. This mode is used when on battery or power
> saving, with no external displays plugged in. You can completely turn
> on/off the nvidia GPU.
>
> Moving between a and b has to be completely dynamic, userspace apps
> need to deal with the whole world changing beneath them.
>

So case a) is "render on X display on Y" problem and case b) (when NVidia 
is turned off, offload aside) is just a traditional rendering on one 
(Intel) GPU.  Real sticky point is dynamic switching and offload.

> There is also switchable graphics mode, where there is a MUX used to
> switch the outputs between the two GPUs.
>

One question for my education: I understand that MUX is essentially a 
switch outside the two GPUs that selects whether the output takes NVidia's 
"connector" or Intel's "connector", right ? When MUX is involved, then you 
don't have "render on X display on Y" problem at all, but it's only the 
"dynamic switching" problem. Is my understanding correct ?

There are also MUX-less laptops, where you only have case a)/b) that you 
described above, right ?


> So the main problem with taking all this code on-board is it sort of
> solves (a), and (b) needs another bunch of work. Now I'd rather not
> solve 50% of the issue and have future userspace apps just think they
> can ignore the problem. As much as I dislike the whole dual-gpu setups
> the fact is they exist and we can't change that, so writing userspace
> to ignore the problem because its too hard isn't going to work. So if
> I merge this VCRTC stuff I give a lot of people an excuse for not
> bothering to fix the harder problems that hotplug and dynamic GPUs put
> in front of you.
>

Point taken. I still think that we are actually dealing with two separate 
problems, but you have your reasons why you want them solved together.
I also have a few more use cases which are solved with VCRTCM only and 
don't need dynamic switching, so these and also "3D Accel + DisplayLink" 
one will suffer by having to wait for full solution that covers all use 
cases, but that's your call and I don't question it.

I hope that you are not categorically dismissing an option that the 
solution can be implemented on the top of VCRTCM and that if I come back 
with some more code that shows that it addresses your concern that you 
will be perceptive to another round of review. I do appreciate you taking 
the time to look at this. I know that you are overbusy with day-to-day 
patches and merging.

I understand that the burden of building an existence proof falls on me 
and I am perfectly fine with that. BTW, If some poor soul reading this 
buys into my arguments and wants to join me in some hacking, I'd 
definitely welcome the collaboration ;-).

-- Ilija



^ permalink raw reply

* [PATCH 09/11] video: Remove redundant spi driver bus initialization
From: Lars-Peter Clausen @ 2011-11-24 15:29 UTC (permalink / raw)
  To: linux-kernel
  Cc: Lars-Peter Clausen, Tomi Valkeinen, Florian Tobias Schandinat,
	linux-fbdev, linux-omap
In-Reply-To: <1322148561-25138-1-git-send-email-lars@metafoo.de>

In ancient times it was necessary to manually initialize the bus field of an
spi_driver to spi_bus_type. These days this is done in spi_driver_register(),
so we can drop the manual assignment.

The patch was generated using the following coccinelle semantic patch:
// <smpl>
@@
identifier _driver;
@@
struct spi_driver _driver = {
	.driver = {
-		.bus = &spi_bus_type,
	},
};
// </smpl>

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: linux-fbdev@vger.kernel.org
Cc: linux-omap@vger.kernel.org
---
 drivers/video/omap/lcd_mipid.c                     |    1 -
 drivers/video/omap2/displays/panel-acx565akm.c     |    1 -
 drivers/video/omap2/displays/panel-n8x0.c          |    1 -
 .../omap2/displays/panel-nec-nl8048hl11-01b.c      |    1 -
 .../video/omap2/displays/panel-tpo-td043mtea1.c    |    1 -
 5 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/omap/lcd_mipid.c
index eb381db..8d546dd 100644
--- a/drivers/video/omap/lcd_mipid.c
+++ b/drivers/video/omap/lcd_mipid.c
@@ -603,7 +603,6 @@ static int mipid_spi_remove(struct spi_device *spi)
 static struct spi_driver mipid_spi_driver = {
 	.driver = {
 		.name	= MIPID_MODULE_NAME,
-		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
 	},
 	.probe	= mipid_spi_probe,
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index dbd59b8..51a87e1 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -803,7 +803,6 @@ static int acx565akm_spi_remove(struct spi_device *spi)
 static struct spi_driver acx565akm_spi_driver = {
 	.driver = {
 		.name	= "acx565akm",
-		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
 	},
 	.probe	= acx565akm_spi_probe,
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c
index 150e8ba..dc9408d 100644
--- a/drivers/video/omap2/displays/panel-n8x0.c
+++ b/drivers/video/omap2/displays/panel-n8x0.c
@@ -708,7 +708,6 @@ static int mipid_spi_remove(struct spi_device *spi)
 static struct spi_driver mipid_spi_driver = {
 	.driver = {
 		.name	= "lcd_mipid",
-		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
 	},
 	.probe	= mipid_spi_probe,
diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
index 2ba9d0c..8365e77 100644
--- a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
+++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
@@ -303,7 +303,6 @@ static struct spi_driver nec_8048_spi_driver = {
 	.resume		= nec_8048_spi_resume,
 	.driver		= {
 		.name	= "nec_8048_spi",
-		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
 	},
 };
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index 2462b9e..e6649aa 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -512,7 +512,6 @@ static int __devexit tpo_td043_spi_remove(struct spi_device *spi)
 static struct spi_driver tpo_td043_spi_driver = {
 	.driver = {
 		.name	= "tpo_td043mtea1_panel_spi",
-		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
 	},
 	.probe	= tpo_td043_spi_probe,
-- 
1.7.7.1



^ permalink raw reply related

* Re: [RFC] Virtual CRTCs (proposal + experimental code)
From: Dave Airlie @ 2011-11-24 13:48 UTC (permalink / raw)
  To: Alan Cox; +Cc: linux-fbdev, dri-devel
In-Reply-To: <20111124125853.6ddc1a56@lxorguk.ukuu.org.uk>

On Thu, Nov 24, 2011 at 12:58 PM, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
>> The thing is this is how optimus works, the nvidia gpus have an engine
>> that you can program to move data from the nvidia tiled VRAM format to
>
> This is even more of a special case than DisplayLink ;-)
>
>> Probably a good idea to do some more research on intel/nvidia GPUs.
>> With intel you can't read back from UMA since it'll be uncached memory
>> so unuseable, so you'll need to use the GPU to detile and move to some
>> sort of cached linear area you can readback from.
>
> It's main memory so there are various ways to read it or pull it into
> cached space.

We have no way to detile on the CPU for lots of intel corner cases, I don't hold
out for it being a proper solution, though in theory for hibernate its
a requirement to figure out.
But you can expose stuff via the GTT using fences to detile, but you
can't then get cached access to it.
So no really various ways, none of them useful or faster than getting
the GPU to blit somewhere linear
and flipping the dest mapping.

>
>> I merge this VCRTC stuff I give a lot of people an excuse for not
>> bothering to fix the harder problems that hotplug and dynamic GPUs put
>> in front of you.
>
> I think both cases are slightly missing the mark, both are specialist
> corner cases and once you add things like cameras to the mix that will
> become even more painfully obvious.
>
> The underlying need I think is a way to negotiate a shared buffer format
> or pipeline between two devices. You also need in some cases to think
> about shared fencing, and that is the bit that is really scary.
>
> Figuring out the transform from A to B ('lets both use this buffer
> format') or 'I can render then convert' is one thing. Dealing with two
> GPUs firing into the same buffer while scanning it out I just pray
> doesn't ever need shared fences.

But we have a project looking into all that, called dmabuf, we also
have the PRIME work which we hope to build on top of dmabuf.

The thing is there are lots of building blocks we need to put in
place, and we've mostly identified what they are, its just typing now.

Dave.

^ permalink raw reply

* [PATCH 13/13] OMAPDSS: DSI: disable DDR_CLK_ALWAYS_ON when entering ULPS
From: Tomi Valkeinen @ 2011-11-24 13:29 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1322141381-5395-1-git-send-email-tomi.valkeinen@ti.com>

ULPS cannot be entered if the DDR clk is enabled. Thus disable the DDR
clk before entering ULPS.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index a01a011..9bcb5c2 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -3544,9 +3544,11 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
 	if (dsi->ulps_enabled)
 		return 0;
 
+	/* DDR_CLK_ALWAYS_ON */
 	if (REG_GET(dsidev, DSI_CLK_CTRL, 13, 13)) {
-		DSSERR("DDR_CLK_ALWAYS_ON enabled when entering ULPS\n");
-		return -EIO;
+		dsi_if_enable(dsidev, 0);
+		REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13);
+		dsi_if_enable(dsidev, 1);
 	}
 
 	dsi_sync_vc(dsidev, 0);
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 12/13] OMAPDSS: DSI: improve wait_for_bit_change
From: Tomi Valkeinen @ 2011-11-24 13:29 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1322141381-5395-1-git-send-email-tomi.valkeinen@ti.com>

We sometimes get timeout when disabling the DSI interface with video
mode. It looks like the disable will stall until the current frame has
been finished, and this can take multiple milliseconds.

wait_for_bit_change() currently uses a busyloop to wait for a bit to
change. This is used in multiple places. The problem is, we don't have
clear understanding how long particular operations can take, so the
function needs to support longer waits.

Improve wait_for_bit_change() to first busy loop for 100 times to see if
the bit changes almost right away. If the bit hasn't changed, move to a
loop with a sleep of 1ms, and poll for 500ms.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |   25 ++++++++++++++++++++-----
 1 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 22055db..a01a011 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -418,14 +418,29 @@ static void dsi_completion_handler(void *data, u32 mask)
 static inline int wait_for_bit_change(struct platform_device *dsidev,
 		const struct dsi_reg idx, int bitnum, int value)
 {
-	int t = 100000;
+	unsigned long timeout;
+	ktime_t wait;
+	int t;
+
+	/* first busyloop to see if the bit changes right away */
+	t = 100;
+	while (t-- > 0) {
+		if (REG_GET(dsidev, idx, bitnum, bitnum) = value)
+			return value;
+	}
+
+	/* then loop for 500ms, sleeping for 1ms in between */
+	timeout = jiffies + msecs_to_jiffies(500);
+	while (time_before(jiffies, timeout)) {
+		if (REG_GET(dsidev, idx, bitnum, bitnum) = value)
+			return value;
 
-	while (REG_GET(dsidev, idx, bitnum, bitnum) != value) {
-		if (--t = 0)
-			return !value;
+		wait = ns_to_ktime(1000 * 1000);
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_hrtimeout(&wait, HRTIMER_MODE_REL);
 	}
 
-	return value;
+	return !value;
 }
 
 u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 11/13] OMAPDSS: DSI: fix lane handling when entering ULPS
From: Tomi Valkeinen @ 2011-11-24 13:29 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1322141381-5395-1-git-send-email-tomi.valkeinen@ti.com>

The current code always enters ULPS for 3 lanes. This is not right, as
there could be only 2 lanes used, and on OMAP4 we have 5 lanes.

Fix the code to put all used lanes into ULPS.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |   16 +++++++++++-----
 1 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 2b375c6..22055db 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -3517,7 +3517,8 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
 {
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	DECLARE_COMPLETION_ONSTACK(completion);
-	int r;
+	int r, i;
+	unsigned mask;
 
 	DSSDBGF();
 
@@ -3560,10 +3561,16 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
 	if (r)
 		return r;
 
+	mask = 0;
+
+	for (i = 0; i < dsi->num_lanes_supported; ++i) {
+		if (dsi->lanes[i].function = DSI_LANE_UNUSED)
+			continue;
+		mask |= 1 << i;
+	}
 	/* Assert TxRequestEsc for data lanes and TxUlpsClk for clk lane */
 	/* LANEx_ULPS_SIG2 */
-	REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (1 << 0) | (1 << 1) | (1 << 2),
-		7, 5);
+	REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, mask, 9, 5);
 
 	/* flush posted write and wait for SCP interface to finish the write */
 	dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2);
@@ -3579,8 +3586,7 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
 			DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
 
 	/* Reset LANEx_ULPS_SIG2 */
-	REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0 << 0) | (0 << 1) | (0 << 2),
-		7, 5);
+	REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, 0, 9, 5);
 
 	/* flush posted write and wait for SCP interface to finish the write */
 	dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2);
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 10/13] OMAPDSS: DSI: remove dsi_get_num_lanes_used
From: Tomi Valkeinen @ 2011-11-24 13:29 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1322141381-5395-1-git-send-email-tomi.valkeinen@ti.com>

There's no longer need for the dsi_get_num_lanes_used function, so it
can be removed. The lane check in dsi_init_display() can be removed as
the validity of the config will be verified when parsing it.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |   27 ++-------------------------
 1 files changed, 2 insertions(+), 25 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index dee9525..2b375c6 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -2034,23 +2034,6 @@ static int dsi_cio_power(struct platform_device *dsidev,
 	return 0;
 }
 
-/* Number of lanes used by the dss device */
-static inline int dsi_get_num_lanes_used(struct omap_dss_device *dssdev)
-{
-	int num_data_lanes = 0;
-
-	if (dssdev->phy.dsi.data1_lane != 0)
-		num_data_lanes++;
-	if (dssdev->phy.dsi.data2_lane != 0)
-		num_data_lanes++;
-	if (dssdev->phy.dsi.data3_lane != 0)
-		num_data_lanes++;
-	if (dssdev->phy.dsi.data4_lane != 0)
-		num_data_lanes++;
-
-	return num_data_lanes + 1;
-}
-
 static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
 {
 	int val;
@@ -3863,6 +3846,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
 static void dsi_proto_timings(struct omap_dss_device *dssdev)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
 	unsigned tclk_pre, tclk_post;
 	unsigned ths_prepare, ths_prepare_ths_zero, ths_zero;
@@ -3870,7 +3854,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
 	unsigned ddr_clk_pre, ddr_clk_post;
 	unsigned enter_hs_mode_lat, exit_hs_mode_lat;
 	unsigned ths_eot;
-	int ndl = dsi_get_num_lanes_used(dssdev) - 1;
+	int ndl = dsi->num_lanes_used - 1;
 	u32 r;
 
 	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
@@ -4554,7 +4538,6 @@ int dsi_init_display(struct omap_dss_device *dssdev)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int dsi_module = dsi_get_dsidev_id(dsidev);
 
 	DSSDBG("DSI init\n");
 
@@ -4576,12 +4559,6 @@ int dsi_init_display(struct omap_dss_device *dssdev)
 		dsi->vdds_dsi_reg = vdds_dsi;
 	}
 
-	if (dsi_get_num_lanes_used(dssdev) > dsi->num_lanes_supported) {
-		DSSERR("DSI%d can't support more than %d lanes\n",
-			dsi_module + 1, dsi->num_lanes_supported);
-		return -EINVAL;
-	}
-
 	return 0;
 }
 
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 09/13] OMAPDSS: DSI: use lane config in dsi_cio_enable_lane_override
From: Tomi Valkeinen @ 2011-11-24 13:29 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1322141381-5395-1-git-send-email-tomi.valkeinen@ti.com>

Use the new lane config in dsi_cio_enable_lane_override(). The function
parameters are also slightly changed.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |   85 +++++++++++++----------------------------
 1 files changed, 27 insertions(+), 58 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 52cf97f..dee9525 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -238,19 +238,6 @@ enum dsi_vc_source {
 	DSI_VC_SOURCE_VP,
 };
 
-enum dsi_lane {
-	DSI_CLK_P	= 1 << 0,
-	DSI_CLK_N	= 1 << 1,
-	DSI_DATA1_P	= 1 << 2,
-	DSI_DATA1_N	= 1 << 3,
-	DSI_DATA2_P	= 1 << 4,
-	DSI_DATA2_N	= 1 << 5,
-	DSI_DATA3_P	= 1 << 6,
-	DSI_DATA3_N	= 1 << 7,
-	DSI_DATA4_P	= 1 << 8,
-	DSI_DATA4_N	= 1 << 9,
-};
-
 struct dsi_update_region {
 	u16 x, y, w, h;
 	struct omap_dss_device *device;
@@ -2290,49 +2277,28 @@ static void dsi_cio_timings(struct platform_device *dsidev)
 	dsi_write_reg(dsidev, DSI_DSIPHY_CFG2, r);
 }
 
+/* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */
 static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev,
-		enum dsi_lane lanes)
+		unsigned mask_p, unsigned mask_n)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-	int clk_lane   = dssdev->phy.dsi.clk_lane;
-	int data1_lane = dssdev->phy.dsi.data1_lane;
-	int data2_lane = dssdev->phy.dsi.data2_lane;
-	int data3_lane = dssdev->phy.dsi.data3_lane;
-	int data4_lane = dssdev->phy.dsi.data4_lane;
-	int clk_pol    = dssdev->phy.dsi.clk_pol;
-	int data1_pol  = dssdev->phy.dsi.data1_pol;
-	int data2_pol  = dssdev->phy.dsi.data2_pol;
-	int data3_pol  = dssdev->phy.dsi.data3_pol;
-	int data4_pol  = dssdev->phy.dsi.data4_pol;
-
-	u32 l = 0;
+	int i;
+	u32 l;
 	u8 lptxscp_start = dsi->num_lanes_supported = 3 ? 22 : 26;
 
-	if (lanes & DSI_CLK_P)
-		l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 0 : 1));
-	if (lanes & DSI_CLK_N)
-		l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 1 : 0));
-
-	if (lanes & DSI_DATA1_P)
-		l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 0 : 1));
-	if (lanes & DSI_DATA1_N)
-		l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 1 : 0));
-
-	if (lanes & DSI_DATA2_P)
-		l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 0 : 1));
-	if (lanes & DSI_DATA2_N)
-		l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 1 : 0));
-
-	if (lanes & DSI_DATA3_P)
-		l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 0 : 1));
-	if (lanes & DSI_DATA3_N)
-		l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 1 : 0));
-
-	if (lanes & DSI_DATA4_P)
-		l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 0 : 1));
-	if (lanes & DSI_DATA4_N)
-		l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 1 : 0));
+	l = 0;
+
+	for (i = 0; i < dsi->num_lanes_supported; ++i) {
+		unsigned p = dsi->lanes[i].polarity;
+
+		if (mask_p & (1 << i))
+			l |= 1 << (i * 2 + (p ? 0 : 1));
+
+		if (mask_n & (1 << i))
+			l |= 1 << (i * 2 + (p ? 1 : 0));
+	}
+
 	/*
 	 * Bits in REGLPTXSCPDAT4TO0DXDY:
 	 * 17: DY0 18: DX0
@@ -2432,7 +2398,6 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	int r;
-	int num_lanes_used = dsi_get_num_lanes_used(dssdev);
 	u32 l;
 
 	DSSDBGF();
@@ -2467,7 +2432,8 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
 	dsi_write_reg(dsidev, DSI_TIMING1, l);
 
 	if (dsi->ulps_enabled) {
-		u32 lane_mask = DSI_CLK_P | DSI_DATA1_P | DSI_DATA2_P;
+		unsigned mask_p;
+		int i;
 
 		DSSDBG("manual ulps exit\n");
 
@@ -2476,16 +2442,19 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
 		 * ULPS exit sequence, as after reset the DSS HW thinks
 		 * that we are not in ULPS mode, and refuses to send the
 		 * sequence. So we need to send the ULPS exit sequence
-		 * manually.
+		 * manually by setting positive lines high and negative lines
+		 * low for 1ms.
 		 */
 
-		if (num_lanes_used > 3)
-			lane_mask |= DSI_DATA3_P;
+		mask_p = 0;
 
-		if (num_lanes_used > 4)
-			lane_mask |= DSI_DATA4_P;
+		for (i = 0; i < dsi->num_lanes_supported; ++i) {
+			if (dsi->lanes[i].function = DSI_LANE_UNUSED)
+				continue;
+			mask_p |= 1 << i;
+		}
 
-		dsi_cio_enable_lane_override(dssdev, lane_mask);
+		dsi_cio_enable_lane_override(dssdev, mask_p, 0);
 	}
 
 	r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON);
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 08/13] OMAPDSS: DSI: use lane config in dsi_cio_wait_tx_clk_esc_reset
From: Tomi Valkeinen @ 2011-11-24 13:29 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1322141381-5395-1-git-send-email-tomi.valkeinen@ti.com>

Use the new lane config in dsi_cio_wait_tx_clk_esc_reset(). This also
extends the function to support 5 lanes on OMAP4, instead of 3 lanes.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |   47 +++++++++++++++-------------------------
 1 files changed, 18 insertions(+), 29 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 1a209a2..52cf97f 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -2365,51 +2365,40 @@ static void dsi_cio_disable_lane_override(struct platform_device *dsidev)
 static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
-	int t;
-	int bits[3];
-	bool in_use[3];
-
-	if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) {
-		bits[0] = 28;
-		bits[1] = 27;
-		bits[2] = 26;
-	} else {
-		bits[0] = 24;
-		bits[1] = 25;
-		bits[2] = 26;
-	}
-
-	in_use[0] = false;
-	in_use[1] = false;
-	in_use[2] = false;
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	int t, i;
+	bool in_use[DSI_MAX_NR_LANES];
+	static const u8 offsets_old[] = { 28, 27, 26 };
+	static const u8 offsets_new[] = { 24, 25, 26, 27, 28 };
+	const u8 *offsets;
+
+	if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC))
+		offsets = offsets_old;
+	else
+		offsets = offsets_new;
 
-	if (dssdev->phy.dsi.clk_lane != 0)
-		in_use[dssdev->phy.dsi.clk_lane - 1] = true;
-	if (dssdev->phy.dsi.data1_lane != 0)
-		in_use[dssdev->phy.dsi.data1_lane - 1] = true;
-	if (dssdev->phy.dsi.data2_lane != 0)
-		in_use[dssdev->phy.dsi.data2_lane - 1] = true;
+	for (i = 0; i < dsi->num_lanes_supported; ++i)
+		in_use[i] = dsi->lanes[i].function != DSI_LANE_UNUSED;
 
 	t = 100000;
 	while (true) {
 		u32 l;
-		int i;
 		int ok;
 
 		l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
 
 		ok = 0;
-		for (i = 0; i < 3; ++i) {
-			if (!in_use[i] || (l & (1 << bits[i])))
+		for (i = 0; i < dsi->num_lanes_supported; ++i) {
+			if (!in_use[i] || (l & (1 << offsets[i])))
 				ok++;
 		}
 
-		if (ok = 3)
+		if (ok = dsi->num_lanes_supported)
 			break;
 
 		if (--t = 0) {
-			for (i = 0; i < 3; ++i) {
-				if (!in_use[i] || (l & (1 << bits[i])))
+			for (i = 0; i < dsi->num_lanes_supported; ++i) {
+				if (!in_use[i] || (l & (1 << offsets[i])))
 					continue;
 
 				DSSERR("CIO TXCLKESC%d domain not coming " \
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 07/13] OMAPDSS: DSI: use lane config in dsi_get_lane_mask
From: Tomi Valkeinen @ 2011-11-24 13:29 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1322141381-5395-1-git-send-email-tomi.valkeinen@ti.com>

Use the new lane config in dsi_get_lane_mask().

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |   22 ++++++++++------------
 1 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index ba8d6b3..1a209a2 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -2422,22 +2422,20 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)
 	return 0;
 }
 
+/* return bitmask of enabled lanes, lane0 being the lsb */
 static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev)
 {
-	unsigned lanes = 0;
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	unsigned mask = 0;
+	int i;
 
-	if (dssdev->phy.dsi.clk_lane != 0)
-		lanes |= 1 << (dssdev->phy.dsi.clk_lane - 1);
-	if (dssdev->phy.dsi.data1_lane != 0)
-		lanes |= 1 << (dssdev->phy.dsi.data1_lane - 1);
-	if (dssdev->phy.dsi.data2_lane != 0)
-		lanes |= 1 << (dssdev->phy.dsi.data2_lane - 1);
-	if (dssdev->phy.dsi.data3_lane != 0)
-		lanes |= 1 << (dssdev->phy.dsi.data3_lane - 1);
-	if (dssdev->phy.dsi.data4_lane != 0)
-		lanes |= 1 << (dssdev->phy.dsi.data4_lane - 1);
+	for (i = 0; i < dsi->num_lanes_supported; ++i) {
+		if (dsi->lanes[i].function != DSI_LANE_UNUSED)
+			mask |= 1 << i;
+	}
 
-	return lanes;
+	return mask;
 }
 
 static int dsi_cio_init(struct omap_dss_device *dssdev)
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 06/13] OMAPDSS: DSI: Use new lane config in dsi_set_lane_config
From: Tomi Valkeinen @ 2011-11-24 13:29 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1322141381-5395-1-git-send-email-tomi.valkeinen@ti.com>

Use the new lane config in dsi_set_lane_config().

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |   84 +++++++++++++++++++---------------------
 1 files changed, 40 insertions(+), 44 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index aea110c..ba8d6b3 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -2154,59 +2154,53 @@ static int dsi_parse_lane_config(struct omap_dss_device *dssdev)
 	return 0;
 }
 
-static void dsi_set_lane_config(struct omap_dss_device *dssdev)
+static int dsi_set_lane_config(struct omap_dss_device *dssdev)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	static const u8 offsets[] = { 0, 4, 8, 12, 16 };
+	static const enum dsi_lane_function functions[] = {
+		DSI_LANE_CLK,
+		DSI_LANE_DATA1,
+		DSI_LANE_DATA2,
+		DSI_LANE_DATA3,
+		DSI_LANE_DATA4,
+	};
 	u32 r;
-	int num_lanes_used = dsi_get_num_lanes_used(dssdev);
-
-	int clk_lane   = dssdev->phy.dsi.clk_lane;
-	int data1_lane = dssdev->phy.dsi.data1_lane;
-	int data2_lane = dssdev->phy.dsi.data2_lane;
-	int clk_pol    = dssdev->phy.dsi.clk_pol;
-	int data1_pol  = dssdev->phy.dsi.data1_pol;
-	int data2_pol  = dssdev->phy.dsi.data2_pol;
+	int i;
 
 	r = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1);
-	r = FLD_MOD(r, clk_lane, 2, 0);
-	r = FLD_MOD(r, clk_pol, 3, 3);
-	r = FLD_MOD(r, data1_lane, 6, 4);
-	r = FLD_MOD(r, data1_pol, 7, 7);
-	r = FLD_MOD(r, data2_lane, 10, 8);
-	r = FLD_MOD(r, data2_pol, 11, 11);
-	if (num_lanes_used > 3) {
-		int data3_lane  = dssdev->phy.dsi.data3_lane;
-		int data3_pol  = dssdev->phy.dsi.data3_pol;
-
-		r = FLD_MOD(r, data3_lane, 14, 12);
-		r = FLD_MOD(r, data3_pol, 15, 15);
+
+	for (i = 0; i < dsi->num_lanes_used; ++i) {
+		unsigned offset = offsets[i];
+		unsigned polarity, lane_number;
+		unsigned t;
+
+		for (t = 0; t < dsi->num_lanes_supported; ++t)
+			if (dsi->lanes[t].function = functions[i])
+				break;
+
+		if (t = dsi->num_lanes_supported)
+			return -EINVAL;
+
+		lane_number = t;
+		polarity = dsi->lanes[t].polarity;
+
+		r = FLD_MOD(r, lane_number + 1, offset + 2, offset);
+		r = FLD_MOD(r, polarity, offset + 3, offset + 3);
 	}
-	if (num_lanes_used > 4) {
-		int data4_lane  = dssdev->phy.dsi.data4_lane;
-		int data4_pol  = dssdev->phy.dsi.data4_pol;
 
-		r = FLD_MOD(r, data4_lane, 18, 16);
-		r = FLD_MOD(r, data4_pol, 19, 19);
+	/* clear the unused lanes */
+	for (; i < dsi->num_lanes_supported; ++i) {
+		unsigned offset = offsets[i];
+
+		r = FLD_MOD(r, 0, offset + 2, offset);
+		r = FLD_MOD(r, 0, offset + 3, offset + 3);
 	}
-	dsi_write_reg(dsidev, DSI_COMPLEXIO_CFG1, r);
 
-	/* The configuration of the DSI complex I/O (number of data lanes,
-	   position, differential order) should not be changed while
-	   DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for
-	   the hardware to take into account a new configuration of the complex
-	   I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to
-	   follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1,
-	   then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set
-	   DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the
-	   DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the
-	   DSI complex I/O configuration is unknown. */
+	dsi_write_reg(dsidev, DSI_COMPLEXIO_CFG1, r);
 
-	/*
-	REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0);
-	REG_FLD_MOD(dsidev, DSI_CTRL, 0, 0, 0);
-	REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20);
-	REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0);
-	*/
+	return 0;
 }
 
 static inline unsigned ns2ddr(struct platform_device *dsidev, unsigned ns)
@@ -2473,7 +2467,9 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
 		goto err_scp_clk_dom;
 	}
 
-	dsi_set_lane_config(dssdev);
+	r = dsi_set_lane_config(dssdev);
+	if (r)
+		goto err_scp_clk_dom;
 
 	/* set TX STOP MODE timer to maximum for this operation */
 	l = dsi_read_reg(dsidev, DSI_TIMING1);
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 05/13] OMAPDSS: DSI: Parse lane config
From: Tomi Valkeinen @ 2011-11-24 13:29 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1322141381-5395-1-git-send-email-tomi.valkeinen@ti.com>

Parse the lane configuration from the device data into internal lane
config format. This will be used in the following patches to clean up
the lane handling.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |   83 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 83 insertions(+), 0 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 6a110b2..aea110c 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -203,6 +203,21 @@ struct dsi_reg { u16 idx; };
 typedef void (*omap_dsi_isr_t) (void *arg, u32 mask);
 
 #define DSI_MAX_NR_ISRS                2
+#define DSI_MAX_NR_LANES	5
+
+enum dsi_lane_function {
+	DSI_LANE_UNUSED	= 0,
+	DSI_LANE_CLK,
+	DSI_LANE_DATA1,
+	DSI_LANE_DATA2,
+	DSI_LANE_DATA3,
+	DSI_LANE_DATA4,
+};
+
+struct dsi_lane_config {
+	enum dsi_lane_function function;
+	u8 polarity;
+};
 
 struct dsi_isr_data {
 	omap_dsi_isr_t	isr;
@@ -329,6 +344,9 @@ struct dsi_data {
 
 	unsigned num_lanes_supported;
 
+	struct dsi_lane_config lanes[DSI_MAX_NR_LANES];
+	unsigned num_lanes_used;
+
 	unsigned scp_clk_refcount;
 };
 
@@ -2077,6 +2095,65 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
 	}
 }
 
+static int dsi_parse_lane_config(struct omap_dss_device *dssdev)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	u8 lanes[DSI_MAX_NR_LANES];
+	u8 polarities[DSI_MAX_NR_LANES];
+	int num_lanes, i;
+
+	static const enum dsi_lane_function functions[] = {
+		DSI_LANE_CLK,
+		DSI_LANE_DATA1,
+		DSI_LANE_DATA2,
+		DSI_LANE_DATA3,
+		DSI_LANE_DATA4,
+	};
+
+	lanes[0] = dssdev->phy.dsi.clk_lane;
+	lanes[1] = dssdev->phy.dsi.data1_lane;
+	lanes[2] = dssdev->phy.dsi.data2_lane;
+	lanes[3] = dssdev->phy.dsi.data3_lane;
+	lanes[4] = dssdev->phy.dsi.data4_lane;
+	polarities[0] = dssdev->phy.dsi.clk_pol;
+	polarities[1] = dssdev->phy.dsi.data1_pol;
+	polarities[2] = dssdev->phy.dsi.data2_pol;
+	polarities[3] = dssdev->phy.dsi.data3_pol;
+	polarities[4] = dssdev->phy.dsi.data4_pol;
+
+	num_lanes = 0;
+
+	for (i = 0; i < dsi->num_lanes_supported; ++i)
+		dsi->lanes[i].function = DSI_LANE_UNUSED;
+
+	for (i = 0; i < dsi->num_lanes_supported; ++i) {
+		int num;
+
+		if (lanes[i] = DSI_LANE_UNUSED)
+			break;
+
+		num = lanes[i] - 1;
+
+		if (num >= dsi->num_lanes_supported)
+			return -EINVAL;
+
+		if (dsi->lanes[num].function != DSI_LANE_UNUSED)
+			return -EINVAL;
+
+		dsi->lanes[num].function = functions[i];
+		dsi->lanes[num].polarity = polarities[i];
+		num_lanes++;
+	}
+
+	if (num_lanes < 2 || num_lanes > dsi->num_lanes_supported)
+		return -EINVAL;
+
+	dsi->num_lanes_used = num_lanes;
+
+	return 0;
+}
+
 static void dsi_set_lane_config(struct omap_dss_device *dssdev)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -4328,6 +4405,12 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
 	int dsi_module = dsi_get_dsidev_id(dsidev);
 	int r;
 
+	r = dsi_parse_lane_config(dssdev);
+	if (r) {
+		DSSERR("illegal lane config");
+		goto err0;
+	}
+
 	r = dsi_pll_init(dsidev, true, true);
 	if (r)
 		goto err0;
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 04/13] OMAPDSS: DSI: count with number of lanes
From: Tomi Valkeinen @ 2011-11-24 13:29 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1322141381-5395-1-git-send-email-tomi.valkeinen@ti.com>

DSI driver currently counts used lanes and number of supported lanes by
using the number of data lanes (i.e. excluding clock lane). This patch
changes this to use the number of all lanes so that the following lane
config patches are cleaner.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |   49 ++++++++++++++++++----------------------
 1 files changed, 22 insertions(+), 27 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 4b1c074..6a110b2 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -327,7 +327,7 @@ struct dsi_data {
 	unsigned long  fint_min, fint_max;
 	unsigned long lpdiv_max;
 
-	int num_data_lanes;
+	unsigned num_lanes_supported;
 
 	unsigned scp_clk_refcount;
 };
@@ -2029,19 +2029,8 @@ static int dsi_cio_power(struct platform_device *dsidev,
 	return 0;
 }
 
-/* Number of data lanes present on DSI interface */
-static inline int dsi_get_num_data_lanes(struct platform_device *dsidev)
-{
-	/* DSI on OMAP3 doesn't have register DSI_GNQ, set number
-	 * of data lanes as 2 by default */
-	if (dss_has_feature(FEAT_DSI_GNQ))
-		return REG_GET(dsidev, DSI_GNQ, 11, 9);	/* NB_DATA_LANES */
-	else
-		return 2;
-}
-
-/* Number of data lanes used by the dss device */
-static inline int dsi_get_num_data_lanes_dssdev(struct omap_dss_device *dssdev)
+/* Number of lanes used by the dss device */
+static inline int dsi_get_num_lanes_used(struct omap_dss_device *dssdev)
 {
 	int num_data_lanes = 0;
 
@@ -2054,7 +2043,7 @@ static inline int dsi_get_num_data_lanes_dssdev(struct omap_dss_device *dssdev)
 	if (dssdev->phy.dsi.data4_lane != 0)
 		num_data_lanes++;
 
-	return num_data_lanes;
+	return num_data_lanes + 1;
 }
 
 static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
@@ -2092,7 +2081,7 @@ static void dsi_set_lane_config(struct omap_dss_device *dssdev)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	u32 r;
-	int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev);
+	int num_lanes_used = dsi_get_num_lanes_used(dssdev);
 
 	int clk_lane   = dssdev->phy.dsi.clk_lane;
 	int data1_lane = dssdev->phy.dsi.data1_lane;
@@ -2108,14 +2097,14 @@ static void dsi_set_lane_config(struct omap_dss_device *dssdev)
 	r = FLD_MOD(r, data1_pol, 7, 7);
 	r = FLD_MOD(r, data2_lane, 10, 8);
 	r = FLD_MOD(r, data2_pol, 11, 11);
-	if (num_data_lanes_dssdev > 2) {
+	if (num_lanes_used > 3) {
 		int data3_lane  = dssdev->phy.dsi.data3_lane;
 		int data3_pol  = dssdev->phy.dsi.data3_pol;
 
 		r = FLD_MOD(r, data3_lane, 14, 12);
 		r = FLD_MOD(r, data3_pol, 15, 15);
 	}
-	if (num_data_lanes_dssdev > 3) {
+	if (num_lanes_used > 4) {
 		int data4_lane  = dssdev->phy.dsi.data4_lane;
 		int data4_pol  = dssdev->phy.dsi.data4_pol;
 
@@ -2247,7 +2236,7 @@ static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev,
 	int data4_pol  = dssdev->phy.dsi.data4_pol;
 
 	u32 l = 0;
-	u8 lptxscp_start = dsi->num_data_lanes = 2 ? 22 : 26;
+	u8 lptxscp_start = dsi->num_lanes_supported = 3 ? 22 : 26;
 
 	if (lanes & DSI_CLK_P)
 		l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 0 : 1));
@@ -2385,7 +2374,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	int r;
-	int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev);
+	int num_lanes_used = dsi_get_num_lanes_used(dssdev);
 	u32 l;
 
 	DSSDBGF();
@@ -2430,10 +2419,10 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
 		 * manually.
 		 */
 
-		if (num_data_lanes_dssdev > 2)
+		if (num_lanes_used > 3)
 			lane_mask |= DSI_DATA3_P;
 
-		if (num_data_lanes_dssdev > 3)
+		if (num_lanes_used > 4)
 			lane_mask |= DSI_DATA4_P;
 
 		dsi_cio_enable_lane_override(dssdev, lane_mask);
@@ -3852,7 +3841,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
 	unsigned ddr_clk_pre, ddr_clk_post;
 	unsigned enter_hs_mode_lat, exit_hs_mode_lat;
 	unsigned ths_eot;
-	int ndl = dsi_get_num_data_lanes_dssdev(dssdev);
+	int ndl = dsi_get_num_lanes_used(dssdev) - 1;
 	u32 r;
 
 	r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
@@ -4552,9 +4541,9 @@ int dsi_init_display(struct omap_dss_device *dssdev)
 		dsi->vdds_dsi_reg = vdds_dsi;
 	}
 
-	if (dsi_get_num_data_lanes_dssdev(dssdev) > dsi->num_data_lanes) {
-		DSSERR("DSI%d can't support more than %d data lanes\n",
-			dsi_module + 1, dsi->num_data_lanes);
+	if (dsi_get_num_lanes_used(dssdev) > dsi->num_lanes_supported) {
+		DSSERR("DSI%d can't support more than %d lanes\n",
+			dsi_module + 1, dsi->num_lanes_supported);
 		return -EINVAL;
 	}
 
@@ -4780,7 +4769,13 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
 	dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n",
 	       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
 
-	dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev);
+	/* DSI on OMAP3 doesn't have register DSI_GNQ, set number
+	 * of data to 3 by default */
+	if (dss_has_feature(FEAT_DSI_GNQ))
+		/* NB_DATA_LANES */
+		dsi->num_lanes_supported = 1 + REG_GET(dsidev, DSI_GNQ, 11, 9);
+	else
+		dsi->num_lanes_supported = 3;
 
 	dsi_runtime_put(dsidev);
 
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 03/13] OMAPDSS: DISPC: Flush posted writes when enabling outputs
From: Tomi Valkeinen @ 2011-11-24 13:29 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1322141381-5395-1-git-send-email-tomi.valkeinen@ti.com>

Flush posted write in _enable_lcd_out() and _enable_digit_out(). This
ensures the the lcd/digit bit is written before the code starts waiting
for interrupts about enabling/disabling the output.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dispc.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 5c81533..5bbd838 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -1916,10 +1916,14 @@ static void dispc_disable_isr(void *data, u32 mask)
 
 static void _enable_lcd_out(enum omap_channel channel, bool enable)
 {
-	if (channel = OMAP_DSS_CHANNEL_LCD2)
+	if (channel = OMAP_DSS_CHANNEL_LCD2) {
 		REG_FLD_MOD(DISPC_CONTROL2, enable ? 1 : 0, 0, 0);
-	else
+		/* flush posted write */
+		dispc_read_reg(DISPC_CONTROL2);
+	} else {
 		REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
+		dispc_read_reg(DISPC_CONTROL);
+	}
 }
 
 static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable)
@@ -1967,6 +1971,8 @@ static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable)
 static void _enable_digit_out(bool enable)
 {
 	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
+	/* flush posted write */
+	dispc_read_reg(DISPC_CONTROL);
 }
 
 static void dispc_mgr_enable_digit_out(bool enable)
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 02/13] OMAPDSS: DSI: flush posted write in send_bta
From: Tomi Valkeinen @ 2011-11-24 13:29 UTC (permalink / raw)
  To: linux-fbdev, linux-omap; +Cc: archit, Tomi Valkeinen
In-Reply-To: <1322141381-5395-1-git-send-email-tomi.valkeinen@ti.com>

Flush posted write after setting the bit to send the BTA to ensure the
BTA is sent right away, as the code in dsi_vc_send_bta_sync() waits for
an interrupt caused indirectly by sending the BTA.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dsi.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 1331f92..4b1c074 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -2913,6 +2913,9 @@ static int dsi_vc_send_bta(struct platform_device *dsidev, int channel)
 
 	REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */
 
+	/* flush posted write */
+	dsi_read_reg(dsidev, DSI_VC_CTRL(channel));
+
 	return 0;
 }
 
-- 
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