Эх сурвалжийг харах

Merge tag 'fbdev-for-3.8' of git://gitorious.org/linux-omap-dss2/linux

Pull fbdev changes from Tomi Valkeinen:
 "OMAPDSS changes, including:
   - use dynanic debug prints
   - OMAP platform dependency removals
   - Creation of compat-layer, helping us to improve omapdrm
   - Misc cleanups, aiming to make omadss more in line with the upcoming
     common display framework

  Exynos DP changes for the 3.8 merge window:
   - Device Tree support for Samsung Exynos DP
   - SW Link training is cleaned up.
   - HPD interrupt is supported.

  Samsung Framebuffer changes for the 3.8 merge window:
   - The bit definitions of header file are updated.
   - Some minor typos are fixed.
   - Some minor bugs of s3c_fb_check_var() are fixed.

  FB related changes for SH Mobile, Freescale DIU

  Add support for the Solomon SSD1307 OLED Controller"

* tag 'fbdev-for-3.8' of git://gitorious.org/linux-omap-dss2/linux: (191 commits)
  OMAPDSS: fix TV-out issue with DSI PLL
  Revert "OMAPFB: simplify locking"
  OMAPFB: remove silly loop in fb2display()
  OMAPFB: fix error handling in omapfb_find_best_mode()
  OMAPFB: use devm_kzalloc to allocate omapfb2_device
  OMAPDSS: DISPC: remove dispc fck uses
  OMAPDSS: DISPC: get dss clock rate from dss driver
  drivers/video/console/softcursor.c: remove redundant NULL check before kfree()
  drivers/video: add support for the Solomon SSD1307 OLED Controller
  OMAPDSS: use omapdss_compat_init() in other drivers
  OMAPDSS: export dispc functions
  OMAPDSS: export dss_feat functions
  OMAPDSS: export dss_mgr_ops functions
  OMAPDSS: separate compat files in the Makefile
  OMAPDSS: move display sysfs init to compat layer
  OMAPDSS: DPI: use dispc's check_timings
  OMAPDSS: DISPC: add dispc_ovl_check()
  OMAPDSS: move irq handling to dispc-compat
  OMAPDSS: move omap_dispc_wait_for_irq_interruptible_timeout to dispc-compat.c
  OMAPDSS: move blocking mgr enable/disable to compat layer
  ...

Conflicts:
	arch/arm/mach-davinci/devices-da8xx.c
	arch/arm/plat-omap/common.c
	drivers/media/platform/omap/omap_vout.c
Linus Torvalds 12 жил өмнө
parent
commit
2b8318881d
89 өөрчлөгдсөн 4013 нэмэгдсэн , 3771 устгасан
  1. 4 6
      Documentation/arm/OMAP/DSS
  2. 80 0
      Documentation/devicetree/bindings/video/exynos_dp.txt
  3. 24 0
      Documentation/devicetree/bindings/video/ssd1307fb.txt
  4. 6 0
      MAINTAINERS
  5. 1 1
      arch/arm/mach-davinci/da830.c
  6. 1 1
      arch/arm/mach-davinci/da850.c
  7. 1 21
      arch/arm/mach-davinci/devices-da8xx.c
  8. 1 0
      arch/arm/mach-davinci/pm_domain.c
  9. 0 14
      arch/arm/mach-omap2/board-rx51-video.c
  10. 0 3
      arch/arm/mach-omap2/board-rx51.c
  11. 10 5
      arch/arm/mach-omap2/display.c
  12. 106 92
      arch/arm/mach-shmobile/board-ag5evm.c
  13. 1 3
      arch/arm/mach-shmobile/board-ap4evb.c
  14. 0 6
      arch/arm/mach-shmobile/board-mackerel.c
  15. 3 2
      arch/arm/plat-omap/fb.c
  16. 0 43
      arch/arm/plat-omap/include/plat/vram.h
  17. 0 6
      arch/sh/boards/mach-ap325rxa/setup.c
  18. 0 6
      arch/sh/boards/mach-ecovec24/setup.c
  19. 3 13
      arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
  20. 5 2
      arch/sh/boards/mach-kfr2r09/setup.c
  21. 2 4
      arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
  22. 15 6
      drivers/media/platform/omap/omap_vout.c
  23. 28 10
      drivers/media/platform/omap/omap_voutlib.c
  24. 3 0
      drivers/media/platform/omap/omap_voutlib.h
  25. 11 0
      drivers/staging/omapdrm/omap_drv.c
  26. 16 1
      drivers/video/Kconfig
  27. 1 0
      drivers/video/Makefile
  28. 1 2
      drivers/video/console/softcursor.c
  29. 76 94
      drivers/video/da8xx-fb.c
  30. 439 258
      drivers/video/exynos/exynos_dp_core.c
  31. 14 7
      drivers/video/exynos/exynos_dp_core.h
  32. 48 29
      drivers/video/exynos/exynos_dp_reg.c
  33. 2 1
      drivers/video/exynos/exynos_dp_reg.h
  34. 120 81
      drivers/video/fsl-diu-fb.c
  35. 0 3
      drivers/video/omap2/Kconfig
  36. 0 1
      drivers/video/omap2/Makefile
  37. 0 23
      drivers/video/omap2/displays/panel-acx565akm.c
  38. 0 36
      drivers/video/omap2/displays/panel-generic-dpi.c
  39. 0 34
      drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
  40. 9 80
      drivers/video/omap2/displays/panel-n8x0.c
  41. 0 24
      drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
  42. 1 44
      drivers/video/omap2/displays/panel-picodlp.c
  43. 0 17
      drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
  44. 0 72
      drivers/video/omap2/displays/panel-taal.c
  45. 0 33
      drivers/video/omap2/displays/panel-tfp410.c
  46. 0 20
      drivers/video/omap2/displays/panel-tpo-td043mtea1.c
  47. 14 21
      drivers/video/omap2/dss/Kconfig
  48. 6 1
      drivers/video/omap2/dss/Makefile
  49. 264 67
      drivers/video/omap2/dss/apply.c
  50. 25 47
      drivers/video/omap2/dss/core.c
  51. 667 0
      drivers/video/omap2/dss/dispc-compat.c
  52. 30 0
      drivers/video/omap2/dss/dispc-compat.h
  53. 277 786
      drivers/video/omap2/dss/dispc.c
  54. 321 0
      drivers/video/omap2/dss/display-sysfs.c
  55. 3 383
      drivers/video/omap2/dss/display.c
  56. 95 31
      drivers/video/omap2/dss/dpi.c
  57. 122 125
      drivers/video/omap2/dss/dsi.c
  58. 96 5
      drivers/video/omap2/dss/dss.c
  59. 19 105
      drivers/video/omap2/dss/dss.h
  60. 7 8
      drivers/video/omap2/dss/dss_features.c
  61. 0 7
      drivers/video/omap2/dss/dss_features.h
  62. 114 45
      drivers/video/omap2/dss/hdmi.c
  63. 15 67
      drivers/video/omap2/dss/hdmi_panel.c
  64. 0 39
      drivers/video/omap2/dss/manager.c
  65. 61 29
      drivers/video/omap2/dss/output.c
  66. 0 17
      drivers/video/omap2/dss/overlay.c
  67. 17 6
      drivers/video/omap2/dss/rfbi.c
  68. 10 1
      drivers/video/omap2/dss/sdi.c
  69. 3 0
      drivers/video/omap2/dss/ti_hdmi.h
  70. 10 1
      drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
  71. 10 1
      drivers/video/omap2/dss/venc.c
  72. 0 19
      drivers/video/omap2/dss/venc_panel.c
  73. 0 1
      drivers/video/omap2/omapfb/Kconfig
  74. 15 31
      drivers/video/omap2/omapfb/omapfb-ioctl.c
  75. 137 67
      drivers/video/omap2/omapfb/omapfb-main.c
  76. 4 0
      drivers/video/omap2/omapfb/omapfb-sysfs.c
  77. 11 9
      drivers/video/omap2/omapfb/omapfb.h
  78. 0 514
      drivers/video/omap2/vram.c
  79. 11 13
      drivers/video/s3c-fb.c
  80. 26 43
      drivers/video/sh_mipi_dsi.c
  81. 47 27
      drivers/video/sh_mobile_lcdcfb.c
  82. 1 0
      drivers/video/sh_mobile_lcdcfb.h
  83. 396 0
      drivers/video/ssd1307fb.c
  84. 9 0
      include/linux/fsl-diu-fb.h
  85. 4 21
      include/video/da8xx-fb.h
  86. 81 10
      include/video/omapdss.h
  87. 52 116
      include/video/samsung_fimd.h
  88. 1 3
      include/video/sh_mipi_dsi.h
  89. 0 1
      include/video/sh_mobile_lcdc.h

+ 4 - 6
Documentation/arm/OMAP/DSS

@@ -285,7 +285,10 @@ FB0 +-- GFX  ---- LCD ---- LCD
 Misc notes
 Misc notes
 ----------
 ----------
 
 
-OMAP FB allocates the framebuffer memory using the OMAP VRAM allocator.
+OMAP FB allocates the framebuffer memory using the standard dma allocator. You
+can enable Contiguous Memory Allocator (CONFIG_CMA) to improve the dma
+allocator, and if CMA is enabled, you use "cma=" kernel parameter to increase
+the global memory area for CMA.
 
 
 Using DSI DPLL to generate pixel clock it is possible produce the pixel clock
 Using DSI DPLL to generate pixel clock it is possible produce the pixel clock
 of 86.5MHz (max possible), and with that you get 1280x1024@57 output from DVI.
 of 86.5MHz (max possible), and with that you get 1280x1024@57 output from DVI.
@@ -301,11 +304,6 @@ framebuffer parameters.
 Kernel boot arguments
 Kernel boot arguments
 ---------------------
 ---------------------
 
 
-vram=<size>[,<physaddr>]
-	- Amount of total VRAM to preallocate and optionally a physical start
-	  memory address. For example, "10M". omapfb allocates memory for
-	  framebuffers from VRAM.
-
 omapfb.mode=<display>:<mode>[,...]
 omapfb.mode=<display>:<mode>[,...]
 	- Default video mode for specified displays. For example,
 	- Default video mode for specified displays. For example,
 	  "dvi:800x400MR-24@60".  See drivers/video/modedb.c.
 	  "dvi:800x400MR-24@60".  See drivers/video/modedb.c.

+ 80 - 0
Documentation/devicetree/bindings/video/exynos_dp.txt

@@ -0,0 +1,80 @@
+The Exynos display port interface should be configured based on
+the type of panel connected to it.
+
+We use two nodes:
+	-dp-controller node
+	-dptx-phy node(defined inside dp-controller node)
+
+For the DP-PHY initialization, we use the dptx-phy node.
+Required properties for dptx-phy:
+	-reg:
+		Base address of DP PHY register.
+	-samsung,enable-mask:
+		The bit-mask used to enable/disable DP PHY.
+
+For the Panel initialization, we read data from dp-controller node.
+Required properties for dp-controller:
+	-compatible:
+		should be "samsung,exynos5-dp".
+	-reg:
+		physical base address of the controller and length
+		of memory mapped region.
+	-interrupts:
+		interrupt combiner values.
+	-interrupt-parent:
+		phandle to Interrupt combiner node.
+	-samsung,color-space:
+		input video data format.
+			COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
+	-samsung,dynamic-range:
+		dynamic range for input video data.
+			VESA = 0, CEA = 1
+	-samsung,ycbcr-coeff:
+		YCbCr co-efficients for input video.
+			COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1
+	-samsung,color-depth:
+		number of bits per colour component.
+			COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
+	-samsung,link-rate:
+		link rate supported by the panel.
+			LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A
+	-samsung,lane-count:
+		number of lanes supported by the panel.
+			LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
+
+Optional properties for dp-controller:
+	-interlaced:
+		interlace scan mode.
+			Progressive if defined, Interlaced if not defined
+	-vsync-active-high:
+		VSYNC polarity configuration.
+			High if defined, Low if not defined
+	-hsync-active-high:
+		HSYNC polarity configuration.
+			High if defined, Low if not defined
+
+Example:
+
+SOC specific portion:
+	dp-controller {
+		compatible = "samsung,exynos5-dp";
+		reg = <0x145b0000 0x10000>;
+		interrupts = <10 3>;
+		interrupt-parent = <&combiner>;
+
+		dptx-phy {
+			reg = <0x10040720>;
+			samsung,enable-mask = <1>;
+		};
+
+	};
+
+Board Specific portion:
+	dp-controller {
+		samsung,color-space = <0>;
+		samsung,dynamic-range = <0>;
+		samsung,ycbcr-coeff = <0>;
+		samsung,color-depth = <1>;
+		samsung,link-rate = <0x0a>;
+		samsung,lane-count = <4>;
+	};

+ 24 - 0
Documentation/devicetree/bindings/video/ssd1307fb.txt

@@ -0,0 +1,24 @@
+* Solomon SSD1307 Framebuffer Driver
+
+Required properties:
+  - compatible: Should be "solomon,ssd1307fb-<bus>". The only supported bus for
+    now is i2c.
+  - reg: Should contain address of the controller on the I2C bus. Most likely
+         0x3c or 0x3d
+  - pwm: Should contain the pwm to use according to the OF device tree PWM
+         specification [0]
+  - reset-gpios: Should contain the GPIO used to reset the OLED display
+
+Optional properties:
+  - reset-active-low: Is the reset gpio is active on physical low?
+
+[0]: Documentation/devicetree/bindings/pwm/pwm.txt
+
+Examples:
+ssd1307: oled@3c {
+        compatible = "solomon,ssd1307fb-i2c";
+        reg = <0x3c>;
+        pwms = <&pwm 4 3000>;
+        reset-gpios = <&gpio2 7>;
+        reset-active-low;
+};

+ 6 - 0
MAINTAINERS

@@ -3162,6 +3162,12 @@ F:	drivers/video/
 F:	include/video/
 F:	include/video/
 F:	include/linux/fb.h
 F:	include/linux/fb.h
 
 
+FREESCALE DIU FRAMEBUFFER DRIVER
+M:	Timur Tabi <timur@freescale.com>
+L:	linux-fbdev@vger.kernel.org
+S:	Supported
+F:	drivers/video/fsl-diu-fb.*
+
 FREESCALE DMA DRIVER
 FREESCALE DMA DRIVER
 M:	Li Yang <leoli@freescale.com>
 M:	Li Yang <leoli@freescale.com>
 M:	Zhang Wei <zw@zh-kernel.org>
 M:	Zhang Wei <zw@zh-kernel.org>

+ 1 - 1
arch/arm/mach-davinci/da830.c

@@ -408,7 +408,7 @@ static struct clk_lookup da830_clks[] = {
 	CLK(NULL,		"pwm2",		&pwm2_clk),
 	CLK(NULL,		"pwm2",		&pwm2_clk),
 	CLK("eqep.0",		NULL,		&eqep0_clk),
 	CLK("eqep.0",		NULL,		&eqep0_clk),
 	CLK("eqep.1",		NULL,		&eqep1_clk),
 	CLK("eqep.1",		NULL,		&eqep1_clk),
-	CLK("da8xx_lcdc.0",	NULL,		&lcdc_clk),
+	CLK("da8xx_lcdc.0",	"fck",		&lcdc_clk),
 	CLK("davinci-mcasp.0",	NULL,		&mcasp0_clk),
 	CLK("davinci-mcasp.0",	NULL,		&mcasp0_clk),
 	CLK("davinci-mcasp.1",	NULL,		&mcasp1_clk),
 	CLK("davinci-mcasp.1",	NULL,		&mcasp1_clk),
 	CLK("davinci-mcasp.2",	NULL,		&mcasp2_clk),
 	CLK("davinci-mcasp.2",	NULL,		&mcasp2_clk),

+ 1 - 1
arch/arm/mach-davinci/da850.c

@@ -403,7 +403,7 @@ static struct clk_lookup da850_clks[] = {
 	CLK(NULL,		"rmii",		&rmii_clk),
 	CLK(NULL,		"rmii",		&rmii_clk),
 	CLK("davinci_emac.1",	NULL,		&emac_clk),
 	CLK("davinci_emac.1",	NULL,		&emac_clk),
 	CLK("davinci-mcasp.0",	NULL,		&mcasp_clk),
 	CLK("davinci-mcasp.0",	NULL,		&mcasp_clk),
-	CLK("da8xx_lcdc.0",	NULL,		&lcdc_clk),
+	CLK("da8xx_lcdc.0",	"fck",		&lcdc_clk),
 	CLK("davinci_mmc.0",	NULL,		&mmcsd0_clk),
 	CLK("davinci_mmc.0",	NULL,		&mmcsd0_clk),
 	CLK("davinci_mmc.1",	NULL,		&mmcsd1_clk),
 	CLK("davinci_mmc.1",	NULL,		&mmcsd1_clk),
 	CLK(NULL,		"aemif",	&aemif_clk),
 	CLK(NULL,		"aemif",	&aemif_clk),

+ 1 - 21
arch/arm/mach-davinci/devices-da8xx.c

@@ -589,29 +589,9 @@ int __init da8xx_register_uio_pruss(void)
 	return platform_device_register(&da8xx_uio_pruss_dev);
 	return platform_device_register(&da8xx_uio_pruss_dev);
 }
 }
 
 
-static const struct display_panel disp_panel = {
-	QVGA,
-	16,
-	16,
-	COLOR_ACTIVE,
-};
-
 static struct lcd_ctrl_config lcd_cfg = {
 static struct lcd_ctrl_config lcd_cfg = {
-	&disp_panel,
-	.ac_bias		= 255,
-	.ac_bias_intrpt		= 0,
-	.dma_burst_sz		= 16,
+	.panel_shade		= COLOR_ACTIVE,
 	.bpp			= 16,
 	.bpp			= 16,
-	.fdd			= 255,
-	.tft_alt_mode		= 0,
-	.stn_565_mode		= 0,
-	.mono_8bit_mode		= 0,
-	.invert_line_clock	= 1,
-	.invert_frm_clock	= 1,
-	.sync_edge		= 0,
-	.sync_ctrl		= 1,
-	.raster_order		= 0,
-	.fifo_th		= 6,
 };
 };
 
 
 struct da8xx_lcdc_platform_data sharp_lcd035q3dg01_pdata = {
 struct da8xx_lcdc_platform_data sharp_lcd035q3dg01_pdata = {

+ 1 - 0
arch/arm/mach-davinci/pm_domain.c

@@ -53,6 +53,7 @@ static struct dev_pm_domain davinci_pm_domain = {
 
 
 static struct pm_clk_notifier_block platform_bus_notifier = {
 static struct pm_clk_notifier_block platform_bus_notifier = {
 	.pm_domain = &davinci_pm_domain,
 	.pm_domain = &davinci_pm_domain,
+	.con_ids = { "fck", NULL, },
 };
 };
 
 
 static int __init davinci_pm_runtime_init(void)
 static int __init davinci_pm_runtime_init(void)

+ 0 - 14
arch/arm/mach-omap2/board-rx51-video.c

@@ -16,7 +16,6 @@
 #include <linux/mm.h>
 #include <linux/mm.h>
 #include <asm/mach-types.h>
 #include <asm/mach-types.h>
 #include <video/omapdss.h>
 #include <video/omapdss.h>
-#include <plat/vram.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 
 
 #include "board-rx51.h"
 #include "board-rx51.h"
@@ -87,17 +86,4 @@ static int __init rx51_video_init(void)
 }
 }
 
 
 subsys_initcall(rx51_video_init);
 subsys_initcall(rx51_video_init);
-
-void __init rx51_video_mem_init(void)
-{
-	/*
-	 * GFX 864x480x32bpp
-	 * VID1/2 1280x720x32bpp double buffered
-	 */
-	omap_vram_set_sdram_vram(PAGE_ALIGN(864 * 480 * 4) +
-			2 * PAGE_ALIGN(1280 * 720 * 4 * 2), 0);
-}
-
-#else
-void __init rx51_video_mem_init(void) { }
 #endif /* defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) */
 #endif /* defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) */

+ 0 - 3
arch/arm/mach-omap2/board-rx51.c

@@ -34,8 +34,6 @@
 
 
 #define RX51_GPIO_SLEEP_IND 162
 #define RX51_GPIO_SLEEP_IND 162
 
 
-extern void rx51_video_mem_init(void);
-
 static struct gpio_led gpio_leds[] = {
 static struct gpio_led gpio_leds[] = {
 	{
 	{
 		.name	= "sleep_ind",
 		.name	= "sleep_ind",
@@ -112,7 +110,6 @@ static void __init rx51_init(void)
 
 
 static void __init rx51_reserve(void)
 static void __init rx51_reserve(void)
 {
 {
-	rx51_video_mem_init();
 	omap_reserve();
 	omap_reserve();
 }
 }
 
 

+ 10 - 5
arch/arm/mach-omap2/display.c

@@ -102,17 +102,20 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initconst = {
 	{ "dss_hdmi", "omapdss_hdmi", -1 },
 	{ "dss_hdmi", "omapdss_hdmi", -1 },
 };
 };
 
 
-static void __init omap4_hdmi_mux_pads(enum omap_hdmi_flags flags)
+static void __init omap4_tpd12s015_mux_pads(void)
 {
 {
-	u32 reg;
-	u16 control_i2c_1;
-
 	omap_mux_init_signal("hdmi_cec",
 	omap_mux_init_signal("hdmi_cec",
 			OMAP_PIN_INPUT_PULLUP);
 			OMAP_PIN_INPUT_PULLUP);
 	omap_mux_init_signal("hdmi_ddc_scl",
 	omap_mux_init_signal("hdmi_ddc_scl",
 			OMAP_PIN_INPUT_PULLUP);
 			OMAP_PIN_INPUT_PULLUP);
 	omap_mux_init_signal("hdmi_ddc_sda",
 	omap_mux_init_signal("hdmi_ddc_sda",
 			OMAP_PIN_INPUT_PULLUP);
 			OMAP_PIN_INPUT_PULLUP);
+}
+
+static void __init omap4_hdmi_mux_pads(enum omap_hdmi_flags flags)
+{
+	u32 reg;
+	u16 control_i2c_1;
 
 
 	/*
 	/*
 	 * CONTROL_I2C_1: HDMI_DDC_SDA_PULLUPRESX (bit 28) and
 	 * CONTROL_I2C_1: HDMI_DDC_SDA_PULLUPRESX (bit 28) and
@@ -163,8 +166,10 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
 
 
 int __init omap_hdmi_init(enum omap_hdmi_flags flags)
 int __init omap_hdmi_init(enum omap_hdmi_flags flags)
 {
 {
-	if (cpu_is_omap44xx())
+	if (cpu_is_omap44xx()) {
 		omap4_hdmi_mux_pads(flags);
 		omap4_hdmi_mux_pads(flags);
+		omap4_tpd12s015_mux_pads();
+	}
 
 
 	return 0;
 	return 0;
 }
 }

+ 106 - 92
arch/arm/mach-shmobile/board-ag5evm.c

@@ -213,95 +213,6 @@ static struct platform_device irda_device = {
 	.num_resources  = ARRAY_SIZE(irda_resources),
 	.num_resources  = ARRAY_SIZE(irda_resources),
 };
 };
 
 
-static unsigned char lcd_backlight_seq[3][2] = {
-	{ 0x04, 0x07 },
-	{ 0x23, 0x80 },
-	{ 0x03, 0x01 },
-};
-
-static void lcd_backlight_on(void)
-{
-	struct i2c_adapter *a;
-	struct i2c_msg msg;
-	int k;
-
-	a = i2c_get_adapter(1);
-	for (k = 0; a && k < 3; k++) {
-		msg.addr = 0x6d;
-		msg.buf = &lcd_backlight_seq[k][0];
-		msg.len = 2;
-		msg.flags = 0;
-		if (i2c_transfer(a, &msg, 1) != 1)
-			break;
-	}
-}
-
-static void lcd_backlight_reset(void)
-{
-	gpio_set_value(GPIO_PORT235, 0);
-	mdelay(24);
-	gpio_set_value(GPIO_PORT235, 1);
-}
-
-/* LCDC0 */
-static const struct fb_videomode lcdc0_modes[] = {
-	{
-		.name		= "R63302(QHD)",
-		.xres		= 544,
-		.yres		= 961,
-		.left_margin	= 72,
-		.right_margin	= 600,
-		.hsync_len	= 16,
-		.upper_margin	= 8,
-		.lower_margin	= 8,
-		.vsync_len	= 2,
-		.sync		= FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
-	},
-};
-
-static struct sh_mobile_lcdc_info lcdc0_info = {
-	.clock_source = LCDC_CLK_PERIPHERAL,
-	.ch[0] = {
-		.chan = LCDC_CHAN_MAINLCD,
-		.interface_type = RGB24,
-		.clock_divider = 1,
-		.flags = LCDC_FLAGS_DWPOL,
-		.fourcc = V4L2_PIX_FMT_RGB565,
-		.lcd_modes = lcdc0_modes,
-		.num_modes = ARRAY_SIZE(lcdc0_modes),
-		.panel_cfg = {
-			.width = 44,
-			.height = 79,
-			.display_on = lcd_backlight_on,
-			.display_off = lcd_backlight_reset,
-		},
-	}
-};
-
-static struct resource lcdc0_resources[] = {
-	[0] = {
-		.name	= "LCDC0",
-		.start	= 0xfe940000, /* P4-only space */
-		.end	= 0xfe943fff,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= intcs_evt2irq(0x580),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device lcdc0_device = {
-	.name		= "sh_mobile_lcdc_fb",
-	.num_resources	= ARRAY_SIZE(lcdc0_resources),
-	.resource	= lcdc0_resources,
-	.id             = 0,
-	.dev	= {
-		.platform_data	= &lcdc0_info,
-		.coherent_dma_mask = ~0,
-	},
-};
-
 /* MIPI-DSI */
 /* MIPI-DSI */
 static struct resource mipidsi0_resources[] = {
 static struct resource mipidsi0_resources[] = {
 	[0] = {
 	[0] = {
@@ -358,7 +269,7 @@ sh_mipi_set_dot_clock_pck_err:
 
 
 static struct sh_mipi_dsi_info mipidsi0_info = {
 static struct sh_mipi_dsi_info mipidsi0_info = {
 	.data_format	= MIPI_RGB888,
 	.data_format	= MIPI_RGB888,
-	.lcd_chan	= &lcdc0_info.ch[0],
+	.channel	= LCDC_CHAN_MAINLCD,
 	.lane		= 2,
 	.lane		= 2,
 	.vsynw_offset	= 20,
 	.vsynw_offset	= 20,
 	.clksrc		= 1,
 	.clksrc		= 1,
@@ -378,6 +289,109 @@ static struct platform_device mipidsi0_device = {
 	},
 	},
 };
 };
 
 
+static unsigned char lcd_backlight_seq[3][2] = {
+	{ 0x04, 0x07 },
+	{ 0x23, 0x80 },
+	{ 0x03, 0x01 },
+};
+
+static int lcd_backlight_set_brightness(int brightness)
+{
+	struct i2c_adapter *adap;
+	struct i2c_msg msg;
+	unsigned int i;
+	int ret;
+
+	if (brightness == 0) {
+		/* Reset the chip */
+		gpio_set_value(GPIO_PORT235, 0);
+		mdelay(24);
+		gpio_set_value(GPIO_PORT235, 1);
+		return 0;
+	}
+
+	adap = i2c_get_adapter(1);
+	if (adap == NULL)
+		return -ENODEV;
+
+	for (i = 0; i < ARRAY_SIZE(lcd_backlight_seq); i++) {
+		msg.addr = 0x6d;
+		msg.buf = &lcd_backlight_seq[i][0];
+		msg.len = 2;
+		msg.flags = 0;
+
+		ret = i2c_transfer(adap, &msg, 1);
+		if (ret < 0)
+			break;
+	}
+
+	i2c_put_adapter(adap);
+	return ret < 0 ? ret : 0;
+}
+
+/* LCDC0 */
+static const struct fb_videomode lcdc0_modes[] = {
+	{
+		.name		= "R63302(QHD)",
+		.xres		= 544,
+		.yres		= 961,
+		.left_margin	= 72,
+		.right_margin	= 600,
+		.hsync_len	= 16,
+		.upper_margin	= 8,
+		.lower_margin	= 8,
+		.vsync_len	= 2,
+		.sync		= FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
+	},
+};
+
+static struct sh_mobile_lcdc_info lcdc0_info = {
+	.clock_source = LCDC_CLK_PERIPHERAL,
+	.ch[0] = {
+		.chan = LCDC_CHAN_MAINLCD,
+		.interface_type = RGB24,
+		.clock_divider = 1,
+		.flags = LCDC_FLAGS_DWPOL,
+		.fourcc = V4L2_PIX_FMT_RGB565,
+		.lcd_modes = lcdc0_modes,
+		.num_modes = ARRAY_SIZE(lcdc0_modes),
+		.panel_cfg = {
+			.width = 44,
+			.height = 79,
+		},
+		.bl_info = {
+			.name = "sh_mobile_lcdc_bl",
+			.max_brightness = 1,
+			.set_brightness = lcd_backlight_set_brightness,
+		},
+		.tx_dev = &mipidsi0_device,
+	}
+};
+
+static struct resource lcdc0_resources[] = {
+	[0] = {
+		.name	= "LCDC0",
+		.start	= 0xfe940000, /* P4-only space */
+		.end	= 0xfe943fff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= intcs_evt2irq(0x580),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device lcdc0_device = {
+	.name		= "sh_mobile_lcdc_fb",
+	.num_resources	= ARRAY_SIZE(lcdc0_resources),
+	.resource	= lcdc0_resources,
+	.id             = 0,
+	.dev	= {
+		.platform_data	= &lcdc0_info,
+		.coherent_dma_mask = ~0,
+	},
+};
+
 /* Fixed 2.8V regulators to be used by SDHI0 */
 /* Fixed 2.8V regulators to be used by SDHI0 */
 static struct regulator_consumer_supply fixed2v8_power_consumers[] =
 static struct regulator_consumer_supply fixed2v8_power_consumers[] =
 {
 {
@@ -531,8 +545,8 @@ static struct platform_device *ag5evm_devices[] __initdata = {
 	&fsi_device,
 	&fsi_device,
 	&mmc_device,
 	&mmc_device,
 	&irda_device,
 	&irda_device,
-	&lcdc0_device,
 	&mipidsi0_device,
 	&mipidsi0_device,
+	&lcdc0_device,
 	&sdhi0_device,
 	&sdhi0_device,
 	&sdhi1_device,
 	&sdhi1_device,
 };
 };
@@ -621,7 +635,7 @@ static void __init ag5evm_init(void)
 	/* LCD backlight controller */
 	/* LCD backlight controller */
 	gpio_request(GPIO_PORT235, NULL); /* RESET */
 	gpio_request(GPIO_PORT235, NULL); /* RESET */
 	gpio_direction_output(GPIO_PORT235, 0);
 	gpio_direction_output(GPIO_PORT235, 0);
-	lcd_backlight_reset();
+	lcd_backlight_set_brightness(0);
 
 
 	/* enable SDHI0 on CN15 [SD I/F] */
 	/* enable SDHI0 on CN15 [SD I/F] */
 	gpio_request(GPIO_FN_SDHIWP0, NULL);
 	gpio_request(GPIO_FN_SDHIWP0, NULL);

+ 1 - 3
arch/arm/mach-shmobile/board-ap4evb.c

@@ -552,11 +552,9 @@ static struct resource mipidsi0_resources[] = {
 	},
 	},
 };
 };
 
 
-static struct sh_mobile_lcdc_info lcdc_info;
-
 static struct sh_mipi_dsi_info mipidsi0_info = {
 static struct sh_mipi_dsi_info mipidsi0_info = {
 	.data_format	= MIPI_RGB888,
 	.data_format	= MIPI_RGB888,
-	.lcd_chan	= &lcdc_info.ch[0],
+	.channel	= LCDC_CHAN_MAINLCD,
 	.lane		= 2,
 	.lane		= 2,
 	.vsynw_offset	= 17,
 	.vsynw_offset	= 17,
 	.phyctrl	= 0x6 << 8,
 	.phyctrl	= 0x6 << 8,

+ 0 - 6
arch/arm/mach-shmobile/board-mackerel.c

@@ -370,11 +370,6 @@ static int mackerel_set_brightness(int brightness)
 	return 0;
 	return 0;
 }
 }
 
 
-static int mackerel_get_brightness(void)
-{
-	return gpio_get_value(GPIO_PORT31);
-}
-
 static const struct sh_mobile_meram_cfg lcd_meram_cfg = {
 static const struct sh_mobile_meram_cfg lcd_meram_cfg = {
 	.icb[0] = {
 	.icb[0] = {
 		.meram_size     = 0x40,
 		.meram_size     = 0x40,
@@ -403,7 +398,6 @@ static struct sh_mobile_lcdc_info lcdc_info = {
 			.name = "sh_mobile_lcdc_bl",
 			.name = "sh_mobile_lcdc_bl",
 			.max_brightness = 1,
 			.max_brightness = 1,
 			.set_brightness = mackerel_set_brightness,
 			.set_brightness = mackerel_set_brightness,
-			.get_brightness = mackerel_get_brightness,
 		},
 		},
 		.meram_cfg = &lcd_meram_cfg,
 		.meram_cfg = &lcd_meram_cfg,
 	}
 	}

+ 3 - 2
arch/arm/plat-omap/fb.c

@@ -29,6 +29,7 @@
 #include <linux/memblock.h>
 #include <linux/memblock.h>
 #include <linux/io.h>
 #include <linux/io.h>
 #include <linux/omapfb.h>
 #include <linux/omapfb.h>
+#include <linux/dma-mapping.h>
 
 
 #include <asm/mach/map.h>
 #include <asm/mach/map.h>
 
 
@@ -105,7 +106,7 @@ static struct platform_device omap_fb_device = {
 	.id		= -1,
 	.id		= -1,
 	.dev = {
 	.dev = {
 		.dma_mask		= &omap_fb_dma_mask,
 		.dma_mask		= &omap_fb_dma_mask,
-		.coherent_dma_mask	= ~(u32)0,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
 		.platform_data		= &omapfb_config,
 		.platform_data		= &omapfb_config,
 	},
 	},
 	.num_resources = 0,
 	.num_resources = 0,
@@ -141,7 +142,7 @@ static struct platform_device omap_fb_device = {
 	.id		= -1,
 	.id		= -1,
 	.dev = {
 	.dev = {
 		.dma_mask		= &omap_fb_dma_mask,
 		.dma_mask		= &omap_fb_dma_mask,
-		.coherent_dma_mask	= ~(u32)0,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
 		.platform_data		= &omapfb_config,
 		.platform_data		= &omapfb_config,
 	},
 	},
 	.num_resources = 0,
 	.num_resources = 0,

+ 0 - 43
arch/arm/plat-omap/include/plat/vram.h

@@ -1,43 +0,0 @@
-/*
- * VRAM manager for OMAP
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#ifndef __OMAP_VRAM_H__
-#define __OMAP_VRAM_H__
-
-#include <linux/types.h>
-
-extern int omap_vram_add_region(unsigned long paddr, size_t size);
-extern int omap_vram_free(unsigned long paddr, size_t size);
-extern int omap_vram_alloc(size_t size, unsigned long *paddr);
-extern int omap_vram_reserve(unsigned long paddr, size_t size);
-extern void omap_vram_get_info(unsigned long *vram, unsigned long *free_vram,
-		unsigned long *largest_free_block);
-
-#ifdef CONFIG_OMAP2_VRAM
-extern void omap_vram_set_sdram_vram(u32 size, u32 start);
-
-extern void omap_vram_reserve_sdram_memblock(void);
-#else
-static inline void omap_vram_set_sdram_vram(u32 size, u32 start) { }
-
-static inline void omap_vram_reserve_sdram_memblock(void) { }
-#endif
-
-#endif

+ 0 - 6
arch/sh/boards/mach-ap325rxa/setup.c

@@ -179,11 +179,6 @@ static int ap320_wvga_set_brightness(int brightness)
 	return 0;
 	return 0;
 }
 }
 
 
-static int ap320_wvga_get_brightness(void)
-{
-	return gpio_get_value(GPIO_PTS3);
-}
-
 static void ap320_wvga_power_on(void)
 static void ap320_wvga_power_on(void)
 {
 {
 	msleep(100);
 	msleep(100);
@@ -232,7 +227,6 @@ static struct sh_mobile_lcdc_info lcdc_info = {
 			.name = "sh_mobile_lcdc_bl",
 			.name = "sh_mobile_lcdc_bl",
 			.max_brightness = 1,
 			.max_brightness = 1,
 			.set_brightness = ap320_wvga_set_brightness,
 			.set_brightness = ap320_wvga_set_brightness,
-			.get_brightness = ap320_wvga_get_brightness,
 		},
 		},
 	}
 	}
 };
 };

+ 0 - 6
arch/sh/boards/mach-ecovec24/setup.c

@@ -329,11 +329,6 @@ static int ecovec24_set_brightness(int brightness)
 	return 0;
 	return 0;
 }
 }
 
 
-static int ecovec24_get_brightness(void)
-{
-	return gpio_get_value(GPIO_PTR1);
-}
-
 static struct sh_mobile_lcdc_info lcdc_info = {
 static struct sh_mobile_lcdc_info lcdc_info = {
 	.ch[0] = {
 	.ch[0] = {
 		.interface_type = RGB18,
 		.interface_type = RGB18,
@@ -347,7 +342,6 @@ static struct sh_mobile_lcdc_info lcdc_info = {
 			.name = "sh_mobile_lcdc_bl",
 			.name = "sh_mobile_lcdc_bl",
 			.max_brightness = 1,
 			.max_brightness = 1,
 			.set_brightness = ecovec24_set_brightness,
 			.set_brightness = ecovec24_set_brightness,
-			.get_brightness = ecovec24_get_brightness,
 		},
 		},
 	}
 	}
 };
 };

+ 3 - 13
arch/sh/boards/mach-kfr2r09/lcd_wqvga.c

@@ -283,7 +283,7 @@ void kfr2r09_lcd_start(void *sohandle, struct sh_mobile_lcdc_sys_bus_ops *so)
 #define MAIN_MLED4      0x40
 #define MAIN_MLED4      0x40
 #define MAIN_MSW        0x80
 #define MAIN_MSW        0x80
 
 
-static int kfr2r09_lcd_backlight(int on)
+int kfr2r09_lcd_set_brightness(int brightness)
 {
 {
 	struct i2c_adapter *a;
 	struct i2c_adapter *a;
 	struct i2c_msg msg;
 	struct i2c_msg msg;
@@ -295,7 +295,7 @@ static int kfr2r09_lcd_backlight(int on)
 		return -ENODEV;
 		return -ENODEV;
 
 
 	buf[0] = 0x00;
 	buf[0] = 0x00;
-	if (on)
+	if (brightness)
 		buf[1] = CTRL_CPSW | CTRL_C10 | CTRL_CKSW;
 		buf[1] = CTRL_CPSW | CTRL_C10 | CTRL_CKSW;
 	else
 	else
 		buf[1] = 0;
 		buf[1] = 0;
@@ -309,7 +309,7 @@ static int kfr2r09_lcd_backlight(int on)
 		return -ENODEV;
 		return -ENODEV;
 
 
 	buf[0] = 0x01;
 	buf[0] = 0x01;
-	if (on)
+	if (brightness)
 		buf[1] = MAIN_MSW | MAIN_MLED4 | 0x0c;
 		buf[1] = MAIN_MSW | MAIN_MLED4 | 0x0c;
 	else
 	else
 		buf[1] = 0;
 		buf[1] = 0;
@@ -324,13 +324,3 @@ static int kfr2r09_lcd_backlight(int on)
 
 
 	return 0;
 	return 0;
 }
 }
-
-void kfr2r09_lcd_on(void)
-{
-	kfr2r09_lcd_backlight(1);
-}
-
-void kfr2r09_lcd_off(void)
-{
-	kfr2r09_lcd_backlight(0);
-}

+ 5 - 2
arch/sh/boards/mach-kfr2r09/setup.c

@@ -158,8 +158,11 @@ static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = {
 			.height = 58,
 			.height = 58,
 			.setup_sys = kfr2r09_lcd_setup,
 			.setup_sys = kfr2r09_lcd_setup,
 			.start_transfer = kfr2r09_lcd_start,
 			.start_transfer = kfr2r09_lcd_start,
-			.display_on = kfr2r09_lcd_on,
-			.display_off = kfr2r09_lcd_off,
+		},
+		.bl_info = {
+			.name = "sh_mobile_lcdc_bl",
+			.max_brightness = 1,
+			.set_brightness = kfr2r09_lcd_set_brightness,
 		},
 		},
 		.sys_bus_cfg = {
 		.sys_bus_cfg = {
 			.ldmt2r = 0x07010904,
 			.ldmt2r = 0x07010904,

+ 2 - 4
arch/sh/include/mach-kfr2r09/mach/kfr2r09.h

@@ -4,15 +4,13 @@
 #include <video/sh_mobile_lcdc.h>
 #include <video/sh_mobile_lcdc.h>
 
 
 #if defined(CONFIG_FB_SH_MOBILE_LCDC) || defined(CONFIG_FB_SH_MOBILE_LCDC_MODULE)
 #if defined(CONFIG_FB_SH_MOBILE_LCDC) || defined(CONFIG_FB_SH_MOBILE_LCDC_MODULE)
-void kfr2r09_lcd_on(void);
-void kfr2r09_lcd_off(void);
+int kfr2r09_lcd_set_brightness(int brightness);
 int kfr2r09_lcd_setup(void *sys_ops_handle,
 int kfr2r09_lcd_setup(void *sys_ops_handle,
 		      struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
 		      struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
 void kfr2r09_lcd_start(void *sys_ops_handle,
 void kfr2r09_lcd_start(void *sys_ops_handle,
 		       struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
 		       struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
 #else
 #else
-static void kfr2r09_lcd_on(void) {}
-static void kfr2r09_lcd_off(void) {}
+static int kfr2r09_lcd_set_brightness(int brightness) {}
 static int kfr2r09_lcd_setup(void *sys_ops_handle,
 static int kfr2r09_lcd_setup(void *sys_ops_handle,
 				struct sh_mobile_lcdc_sys_bus_ops *sys_ops)
 				struct sh_mobile_lcdc_sys_bus_ops *sys_ops)
 {
 {

+ 15 - 6
drivers/media/platform/omap/omap_vout.c

@@ -44,8 +44,6 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-ioctl.h>
 
 
-#include <plat/cpu.h>
-#include <linux/omap-dma.h>
 #include <video/omapvrfb.h>
 #include <video/omapvrfb.h>
 #include <video/omapdss.h>
 #include <video/omapdss.h>
 
 
@@ -2043,7 +2041,7 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev)
 		vout->vid_info.id = k + 1;
 		vout->vid_info.id = k + 1;
 
 
 		/* Set VRFB as rotation_type for omap2 and omap3 */
 		/* Set VRFB as rotation_type for omap2 and omap3 */
-		if (cpu_is_omap24xx() || cpu_is_omap34xx())
+		if (omap_vout_dss_omap24xx() || omap_vout_dss_omap34xx())
 			vout->vid_info.rotation_type = VOUT_ROT_VRFB;
 			vout->vid_info.rotation_type = VOUT_ROT_VRFB;
 
 
 		/* Setup the default configuration for the video devices
 		/* Setup the default configuration for the video devices
@@ -2160,14 +2158,23 @@ static int __init omap_vout_probe(struct platform_device *pdev)
 	struct omap_dss_device *def_display;
 	struct omap_dss_device *def_display;
 	struct omap2video_device *vid_dev = NULL;
 	struct omap2video_device *vid_dev = NULL;
 
 
+	ret = omapdss_compat_init();
+	if (ret) {
+		dev_err(&pdev->dev, "failed to init dss\n");
+		return ret;
+	}
+
 	if (pdev->num_resources == 0) {
 	if (pdev->num_resources == 0) {
 		dev_err(&pdev->dev, "probed for an unknown device\n");
 		dev_err(&pdev->dev, "probed for an unknown device\n");
-		return -ENODEV;
+		ret = -ENODEV;
+		goto err_dss_init;
 	}
 	}
 
 
 	vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL);
 	vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL);
-	if (vid_dev == NULL)
-		return -ENOMEM;
+	if (vid_dev == NULL) {
+		ret = -ENOMEM;
+		goto err_dss_init;
+	}
 
 
 	vid_dev->num_displays = 0;
 	vid_dev->num_displays = 0;
 	for_each_dss_dev(dssdev) {
 	for_each_dss_dev(dssdev) {
@@ -2262,6 +2269,8 @@ probe_err1:
 	}
 	}
 probe_err0:
 probe_err0:
 	kfree(vid_dev);
 	kfree(vid_dev);
+err_dss_init:
+	omapdss_compat_uninit();
 	return ret;
 	return ret;
 }
 }
 
 

+ 28 - 10
drivers/media/platform/omap/omap_voutlib.c

@@ -26,7 +26,7 @@
 
 
 #include <linux/dma-mapping.h>
 #include <linux/dma-mapping.h>
 
 
-#include <plat/cpu.h>
+#include <video/omapdss.h>
 
 
 #include "omap_voutlib.h"
 #include "omap_voutlib.h"
 
 
@@ -124,7 +124,7 @@ int omap_vout_new_window(struct v4l2_rect *crop,
 	win->chromakey = new_win->chromakey;
 	win->chromakey = new_win->chromakey;
 
 
 	/* Adjust the cropping window to allow for resizing limitation */
 	/* Adjust the cropping window to allow for resizing limitation */
-	if (cpu_is_omap24xx()) {
+	if (omap_vout_dss_omap24xx()) {
 		/* For 24xx limit is 8x to 1/2x scaling. */
 		/* For 24xx limit is 8x to 1/2x scaling. */
 		if ((crop->height/win->w.height) >= 2)
 		if ((crop->height/win->w.height) >= 2)
 			crop->height = win->w.height * 2;
 			crop->height = win->w.height * 2;
@@ -140,7 +140,7 @@ int omap_vout_new_window(struct v4l2_rect *crop,
 			if (crop->height != win->w.height)
 			if (crop->height != win->w.height)
 				crop->width = 768;
 				crop->width = 768;
 		}
 		}
-	} else if (cpu_is_omap34xx()) {
+	} else if (omap_vout_dss_omap34xx()) {
 		/* For 34xx limit is 8x to 1/4x scaling. */
 		/* For 34xx limit is 8x to 1/4x scaling. */
 		if ((crop->height/win->w.height) >= 4)
 		if ((crop->height/win->w.height) >= 4)
 			crop->height = win->w.height * 4;
 			crop->height = win->w.height * 4;
@@ -196,7 +196,7 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
 	if (try_crop.width <= 0 || try_crop.height <= 0)
 	if (try_crop.width <= 0 || try_crop.height <= 0)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	if (cpu_is_omap24xx()) {
+	if (omap_vout_dss_omap24xx()) {
 		if (try_crop.height != win->w.height) {
 		if (try_crop.height != win->w.height) {
 			/* If we're resizing vertically, we can't support a
 			/* If we're resizing vertically, we can't support a
 			 * crop width wider than 768 pixels.
 			 * crop width wider than 768 pixels.
@@ -207,9 +207,9 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
 	}
 	}
 	/* vertical resizing */
 	/* vertical resizing */
 	vresize = (1024 * try_crop.height) / win->w.height;
 	vresize = (1024 * try_crop.height) / win->w.height;
-	if (cpu_is_omap24xx() && (vresize > 2048))
+	if (omap_vout_dss_omap24xx() && (vresize > 2048))
 		vresize = 2048;
 		vresize = 2048;
-	else if (cpu_is_omap34xx() && (vresize > 4096))
+	else if (omap_vout_dss_omap34xx() && (vresize > 4096))
 		vresize = 4096;
 		vresize = 4096;
 
 
 	win->w.height = ((1024 * try_crop.height) / vresize) & ~1;
 	win->w.height = ((1024 * try_crop.height) / vresize) & ~1;
@@ -226,9 +226,9 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
 	}
 	}
 	/* horizontal resizing */
 	/* horizontal resizing */
 	hresize = (1024 * try_crop.width) / win->w.width;
 	hresize = (1024 * try_crop.width) / win->w.width;
-	if (cpu_is_omap24xx() && (hresize > 2048))
+	if (omap_vout_dss_omap24xx() && (hresize > 2048))
 		hresize = 2048;
 		hresize = 2048;
-	else if (cpu_is_omap34xx() && (hresize > 4096))
+	else if (omap_vout_dss_omap34xx() && (hresize > 4096))
 		hresize = 4096;
 		hresize = 4096;
 
 
 	win->w.width = ((1024 * try_crop.width) / hresize) & ~1;
 	win->w.width = ((1024 * try_crop.width) / hresize) & ~1;
@@ -243,7 +243,7 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
 		if (try_crop.width == 0)
 		if (try_crop.width == 0)
 			try_crop.width = 2;
 			try_crop.width = 2;
 	}
 	}
-	if (cpu_is_omap24xx()) {
+	if (omap_vout_dss_omap24xx()) {
 		if ((try_crop.height/win->w.height) >= 2)
 		if ((try_crop.height/win->w.height) >= 2)
 			try_crop.height = win->w.height * 2;
 			try_crop.height = win->w.height * 2;
 
 
@@ -258,7 +258,7 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
 			if (try_crop.height != win->w.height)
 			if (try_crop.height != win->w.height)
 				try_crop.width = 768;
 				try_crop.width = 768;
 		}
 		}
-	} else if (cpu_is_omap34xx()) {
+	} else if (omap_vout_dss_omap34xx()) {
 		if ((try_crop.height/win->w.height) >= 4)
 		if ((try_crop.height/win->w.height) >= 4)
 			try_crop.height = win->w.height * 4;
 			try_crop.height = win->w.height * 4;
 
 
@@ -337,3 +337,21 @@ void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size)
 	}
 	}
 	free_pages((unsigned long) virtaddr, order);
 	free_pages((unsigned long) virtaddr, order);
 }
 }
+
+bool omap_vout_dss_omap24xx(void)
+{
+	return omapdss_get_version() == OMAPDSS_VER_OMAP24xx;
+}
+
+bool omap_vout_dss_omap34xx(void)
+{
+	switch (omapdss_get_version()) {
+	case OMAPDSS_VER_OMAP34xx_ES1:
+	case OMAPDSS_VER_OMAP34xx_ES3:
+	case OMAPDSS_VER_OMAP3630:
+	case OMAPDSS_VER_AM35xx:
+		return true;
+	default:
+		return false;
+	}
+}

+ 3 - 0
drivers/media/platform/omap/omap_voutlib.h

@@ -32,5 +32,8 @@ void omap_vout_new_format(struct v4l2_pix_format *pix,
 		struct v4l2_window *win);
 		struct v4l2_window *win);
 unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr);
 unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr);
 void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size);
 void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size);
+
+bool omap_vout_dss_omap24xx(void);
+bool omap_vout_dss_omap34xx(void);
 #endif	/* #ifndef OMAP_VOUTLIB_H */
 #endif	/* #ifndef OMAP_VOUTLIB_H */
 
 

+ 11 - 0
drivers/staging/omapdrm/omap_drv.c

@@ -565,6 +565,14 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
 
 
 	dev->dev_private = priv;
 	dev->dev_private = priv;
 
 
+	ret = omapdss_compat_init();
+	if (ret) {
+		dev_err(dev->dev, "coult not init omapdss\n");
+		dev->dev_private = NULL;
+		kfree(priv);
+		return ret;
+	}
+
 	priv->wq = alloc_ordered_workqueue("omapdrm", 0);
 	priv->wq = alloc_ordered_workqueue("omapdrm", 0);
 
 
 	INIT_LIST_HEAD(&priv->obj_list);
 	INIT_LIST_HEAD(&priv->obj_list);
@@ -576,6 +584,7 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
 		dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret);
 		dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret);
 		dev->dev_private = NULL;
 		dev->dev_private = NULL;
 		kfree(priv);
 		kfree(priv);
+		omapdss_compat_uninit();
 		return ret;
 		return ret;
 	}
 	}
 
 
@@ -610,6 +619,8 @@ static int dev_unload(struct drm_device *dev)
 	flush_workqueue(priv->wq);
 	flush_workqueue(priv->wq);
 	destroy_workqueue(priv->wq);
 	destroy_workqueue(priv->wq);
 
 
+	omapdss_compat_uninit();
+
 	kfree(dev->dev_private);
 	kfree(dev->dev_private);
 	dev->dev_private = NULL;
 	dev->dev_private = NULL;
 
 

+ 16 - 1
drivers/video/Kconfig

@@ -2045,7 +2045,7 @@ config FB_S3C_DEBUG_REGWRITE
        bool "Debug register writes"
        bool "Debug register writes"
        depends on FB_S3C
        depends on FB_S3C
        ---help---
        ---help---
-         Show all register writes via printk(KERN_DEBUG)
+         Show all register writes via pr_debug()
 
 
 config FB_S3C2410
 config FB_S3C2410
 	tristate "S3C2410 LCD framebuffer support"
 	tristate "S3C2410 LCD framebuffer support"
@@ -2442,4 +2442,19 @@ config FB_SH_MOBILE_MERAM
 	  Up to 4 memory channels can be configured, allowing 4 RGB or
 	  Up to 4 memory channels can be configured, allowing 4 RGB or
 	  2 YCbCr framebuffers to be configured.
 	  2 YCbCr framebuffers to be configured.
 
 
+config FB_SSD1307
+	tristate "Solomon SSD1307 framebuffer support"
+	depends on FB && I2C
+	depends on OF
+	depends on GENERIC_GPIO
+	select FB_SYS_FOPS
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_DEFERRED_IO
+	select PWM
+	help
+	  This driver implements support for the Solomon SSD1307
+	  OLED controller over I2C.
+
 endmenu
 endmenu

+ 1 - 0
drivers/video/Makefile

@@ -161,6 +161,7 @@ obj-$(CONFIG_FB_BFIN_7393)        += bfin_adv7393fb.o
 obj-$(CONFIG_FB_MX3)		  += mx3fb.o
 obj-$(CONFIG_FB_MX3)		  += mx3fb.o
 obj-$(CONFIG_FB_DA8XX)		  += da8xx-fb.o
 obj-$(CONFIG_FB_DA8XX)		  += da8xx-fb.o
 obj-$(CONFIG_FB_MXS)		  += mxsfb.o
 obj-$(CONFIG_FB_MXS)		  += mxsfb.o
+obj-$(CONFIG_FB_SSD1307)	  += ssd1307fb.o
 
 
 # the test framebuffer is last
 # the test framebuffer is last
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o

+ 1 - 2
drivers/video/console/softcursor.c

@@ -35,8 +35,7 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
 	dsize = s_pitch * cursor->image.height;
 	dsize = s_pitch * cursor->image.height;
 
 
 	if (dsize + sizeof(struct fb_image) != ops->cursor_size) {
 	if (dsize + sizeof(struct fb_image) != ops->cursor_size) {
-		if (ops->cursor_src != NULL)
-			kfree(ops->cursor_src);
+		kfree(ops->cursor_src);
 		ops->cursor_size = dsize + sizeof(struct fb_image);
 		ops->cursor_size = dsize + sizeof(struct fb_image);
 
 
 		ops->cursor_src = kmalloc(ops->cursor_size, GFP_ATOMIC);
 		ops->cursor_src = kmalloc(ops->cursor_size, GFP_ATOMIC);

+ 76 - 94
drivers/video/da8xx-fb.c

@@ -213,62 +213,51 @@ static struct fb_fix_screeninfo da8xx_fb_fix __devinitdata = {
 	.accel = FB_ACCEL_NONE
 	.accel = FB_ACCEL_NONE
 };
 };
 
 
-struct da8xx_panel {
-	const char	name[25];	/* Full name <vendor>_<model> */
-	unsigned short	width;
-	unsigned short	height;
-	int		hfp;		/* Horizontal front porch */
-	int		hbp;		/* Horizontal back porch */
-	int		hsw;		/* Horizontal Sync Pulse Width */
-	int		vfp;		/* Vertical front porch */
-	int		vbp;		/* Vertical back porch */
-	int		vsw;		/* Vertical Sync Pulse Width */
-	unsigned int	pxl_clk;	/* Pixel clock */
-	unsigned char	invert_pxl_clk;	/* Invert Pixel clock */
-};
-
-static struct da8xx_panel known_lcd_panels[] = {
+static struct fb_videomode known_lcd_panels[] = {
 	/* Sharp LCD035Q3DG01 */
 	/* Sharp LCD035Q3DG01 */
 	[0] = {
 	[0] = {
-		.name = "Sharp_LCD035Q3DG01",
-		.width = 320,
-		.height = 240,
-		.hfp = 8,
-		.hbp = 6,
-		.hsw = 0,
-		.vfp = 2,
-		.vbp = 2,
-		.vsw = 0,
-		.pxl_clk = 4608000,
-		.invert_pxl_clk = 1,
+		.name           = "Sharp_LCD035Q3DG01",
+		.xres           = 320,
+		.yres           = 240,
+		.pixclock       = 4608000,
+		.left_margin    = 6,
+		.right_margin   = 8,
+		.upper_margin   = 2,
+		.lower_margin   = 2,
+		.hsync_len      = 0,
+		.vsync_len      = 0,
+		.sync           = FB_SYNC_CLK_INVERT |
+			FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
 	},
 	},
 	/* Sharp LK043T1DG01 */
 	/* Sharp LK043T1DG01 */
 	[1] = {
 	[1] = {
-		.name = "Sharp_LK043T1DG01",
-		.width = 480,
-		.height = 272,
-		.hfp = 2,
-		.hbp = 2,
-		.hsw = 41,
-		.vfp = 2,
-		.vbp = 2,
-		.vsw = 10,
-		.pxl_clk = 7833600,
-		.invert_pxl_clk = 0,
+		.name           = "Sharp_LK043T1DG01",
+		.xres           = 480,
+		.yres           = 272,
+		.pixclock       = 7833600,
+		.left_margin    = 2,
+		.right_margin   = 2,
+		.upper_margin   = 2,
+		.lower_margin   = 2,
+		.hsync_len      = 41,
+		.vsync_len      = 10,
+		.sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.flag           = 0,
 	},
 	},
 	[2] = {
 	[2] = {
 		/* Hitachi SP10Q010 */
 		/* Hitachi SP10Q010 */
-		.name = "SP10Q010",
-		.width = 320,
-		.height = 240,
-		.hfp = 10,
-		.hbp = 10,
-		.hsw = 10,
-		.vfp = 10,
-		.vbp = 10,
-		.vsw = 10,
-		.pxl_clk = 7833600,
-		.invert_pxl_clk = 0,
+		.name           = "SP10Q010",
+		.xres           = 320,
+		.yres           = 240,
+		.pixclock       = 7833600,
+		.left_margin    = 10,
+		.right_margin   = 10,
+		.upper_margin   = 10,
+		.lower_margin   = 10,
+		.hsync_len      = 10,
+		.vsync_len      = 10,
+		.sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.flag           = 0,
 	},
 	},
 };
 };
 
 
@@ -399,10 +388,9 @@ static int lcd_cfg_dma(int burst_size, int fifo_th)
 		reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8);
 		reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8);
 		break;
 		break;
 	case 16:
 	case 16:
+	default:
 		reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16);
 		reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16);
 		break;
 		break;
-	default:
-		return -EINVAL;
 	}
 	}
 
 
 	reg |= (fifo_th << 8);
 	reg |= (fifo_th << 8);
@@ -447,7 +435,8 @@ static void lcd_cfg_vertical_sync(int back_porch, int pulse_width,
 	lcdc_write(reg, LCD_RASTER_TIMING_1_REG);
 	lcdc_write(reg, LCD_RASTER_TIMING_1_REG);
 }
 }
 
 
-static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
+static int lcd_cfg_display(const struct lcd_ctrl_config *cfg,
+		struct fb_videomode *panel)
 {
 {
 	u32 reg;
 	u32 reg;
 	u32 reg_int;
 	u32 reg_int;
@@ -456,7 +445,7 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
 						LCD_MONO_8BIT_MODE |
 						LCD_MONO_8BIT_MODE |
 						LCD_MONOCHROME_MODE);
 						LCD_MONOCHROME_MODE);
 
 
-	switch (cfg->p_disp_panel->panel_shade) {
+	switch (cfg->panel_shade) {
 	case MONOCHROME:
 	case MONOCHROME:
 		reg |= LCD_MONOCHROME_MODE;
 		reg |= LCD_MONOCHROME_MODE;
 		if (cfg->mono_8bit_mode)
 		if (cfg->mono_8bit_mode)
@@ -469,7 +458,9 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
 		break;
 		break;
 
 
 	case COLOR_PASSIVE:
 	case COLOR_PASSIVE:
-		if (cfg->stn_565_mode)
+		/* AC bias applicable only for Pasive panels */
+		lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt);
+		if (cfg->bpp == 12 && cfg->stn_565_mode)
 			reg |= LCD_STN_565_ENABLE;
 			reg |= LCD_STN_565_ENABLE;
 		break;
 		break;
 
 
@@ -490,22 +481,19 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
 
 
 	reg = lcdc_read(LCD_RASTER_TIMING_2_REG);
 	reg = lcdc_read(LCD_RASTER_TIMING_2_REG);
 
 
-	if (cfg->sync_ctrl)
-		reg |= LCD_SYNC_CTRL;
-	else
-		reg &= ~LCD_SYNC_CTRL;
+	reg |= LCD_SYNC_CTRL;
 
 
 	if (cfg->sync_edge)
 	if (cfg->sync_edge)
 		reg |= LCD_SYNC_EDGE;
 		reg |= LCD_SYNC_EDGE;
 	else
 	else
 		reg &= ~LCD_SYNC_EDGE;
 		reg &= ~LCD_SYNC_EDGE;
 
 
-	if (cfg->invert_line_clock)
+	if (panel->sync & FB_SYNC_HOR_HIGH_ACT)
 		reg |= LCD_INVERT_LINE_CLOCK;
 		reg |= LCD_INVERT_LINE_CLOCK;
 	else
 	else
 		reg &= ~LCD_INVERT_LINE_CLOCK;
 		reg &= ~LCD_INVERT_LINE_CLOCK;
 
 
-	if (cfg->invert_frm_clock)
+	if (panel->sync & FB_SYNC_VERT_HIGH_ACT)
 		reg |= LCD_INVERT_FRAME_CLOCK;
 		reg |= LCD_INVERT_FRAME_CLOCK;
 	else
 	else
 		reg &= ~LCD_INVERT_FRAME_CLOCK;
 		reg &= ~LCD_INVERT_FRAME_CLOCK;
@@ -728,7 +716,7 @@ static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
 }
 }
 
 
 static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
 static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
-		struct da8xx_panel *panel)
+		struct fb_videomode *panel)
 {
 {
 	u32 bpp;
 	u32 bpp;
 	int ret = 0;
 	int ret = 0;
@@ -738,7 +726,7 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
 	/* Calculate the divider */
 	/* Calculate the divider */
 	lcd_calc_clk_divider(par);
 	lcd_calc_clk_divider(par);
 
 
-	if (panel->invert_pxl_clk)
+	if (panel->sync & FB_SYNC_CLK_INVERT)
 		lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) |
 		lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) |
 			LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG);
 			LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG);
 	else
 	else
@@ -750,30 +738,23 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 
-	/* Configure the AC bias properties. */
-	lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt);
-
 	/* Configure the vertical and horizontal sync properties. */
 	/* Configure the vertical and horizontal sync properties. */
-	lcd_cfg_vertical_sync(panel->vbp, panel->vsw, panel->vfp);
-	lcd_cfg_horizontal_sync(panel->hbp, panel->hsw, panel->hfp);
+	lcd_cfg_vertical_sync(panel->lower_margin, panel->vsync_len,
+			panel->upper_margin);
+	lcd_cfg_horizontal_sync(panel->right_margin, panel->hsync_len,
+			panel->left_margin);
 
 
 	/* Configure for disply */
 	/* Configure for disply */
-	ret = lcd_cfg_display(cfg);
+	ret = lcd_cfg_display(cfg, panel);
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 
-	if (QVGA != cfg->p_disp_panel->panel_type)
-		return -EINVAL;
+	bpp = cfg->bpp;
 
 
-	if (cfg->bpp <= cfg->p_disp_panel->max_bpp &&
-	    cfg->bpp >= cfg->p_disp_panel->min_bpp)
-		bpp = cfg->bpp;
-	else
-		bpp = cfg->p_disp_panel->max_bpp;
 	if (bpp == 12)
 	if (bpp == 12)
 		bpp = 16;
 		bpp = 16;
-	ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->width,
-				(unsigned int)panel->height, bpp,
+	ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->xres,
+				(unsigned int)panel->yres, bpp,
 				cfg->raster_order);
 				cfg->raster_order);
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
@@ -1235,7 +1216,7 @@ static int __devinit fb_probe(struct platform_device *device)
 	struct da8xx_lcdc_platform_data *fb_pdata =
 	struct da8xx_lcdc_platform_data *fb_pdata =
 						device->dev.platform_data;
 						device->dev.platform_data;
 	struct lcd_ctrl_config *lcd_cfg;
 	struct lcd_ctrl_config *lcd_cfg;
-	struct da8xx_panel *lcdc_info;
+	struct fb_videomode *lcdc_info;
 	struct fb_info *da8xx_fb_info;
 	struct fb_info *da8xx_fb_info;
 	struct clk *fb_clk = NULL;
 	struct clk *fb_clk = NULL;
 	struct da8xx_fb_par *par;
 	struct da8xx_fb_par *par;
@@ -1267,7 +1248,7 @@ static int __devinit fb_probe(struct platform_device *device)
 		goto err_request_mem;
 		goto err_request_mem;
 	}
 	}
 
 
-	fb_clk = clk_get(&device->dev, NULL);
+	fb_clk = clk_get(&device->dev, "fck");
 	if (IS_ERR(fb_clk)) {
 	if (IS_ERR(fb_clk)) {
 		dev_err(&device->dev, "Can not get device clock\n");
 		dev_err(&device->dev, "Can not get device clock\n");
 		ret = -ENODEV;
 		ret = -ENODEV;
@@ -1283,6 +1264,7 @@ static int __devinit fb_probe(struct platform_device *device)
 		lcd_revision = LCD_VERSION_1;
 		lcd_revision = LCD_VERSION_1;
 		break;
 		break;
 	case 0x4F200800:
 	case 0x4F200800:
+	case 0x4F201000:
 		lcd_revision = LCD_VERSION_2;
 		lcd_revision = LCD_VERSION_2;
 		break;
 		break;
 	default:
 	default:
@@ -1323,7 +1305,7 @@ static int __devinit fb_probe(struct platform_device *device)
 #ifdef CONFIG_CPU_FREQ
 #ifdef CONFIG_CPU_FREQ
 	par->lcd_fck_rate = clk_get_rate(fb_clk);
 	par->lcd_fck_rate = clk_get_rate(fb_clk);
 #endif
 #endif
-	par->pxl_clk = lcdc_info->pxl_clk;
+	par->pxl_clk = lcdc_info->pixclock;
 	if (fb_pdata->panel_power_ctrl) {
 	if (fb_pdata->panel_power_ctrl) {
 		par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
 		par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
 		par->panel_power_ctrl(1);
 		par->panel_power_ctrl(1);
@@ -1336,8 +1318,8 @@ static int __devinit fb_probe(struct platform_device *device)
 	}
 	}
 
 
 	/* allocate frame buffer */
 	/* allocate frame buffer */
-	par->vram_size = lcdc_info->width * lcdc_info->height * lcd_cfg->bpp;
-	ulcm = lcm((lcdc_info->width * lcd_cfg->bpp)/8, PAGE_SIZE);
+	par->vram_size = lcdc_info->xres * lcdc_info->yres * lcd_cfg->bpp;
+	ulcm = lcm((lcdc_info->xres * lcd_cfg->bpp)/8, PAGE_SIZE);
 	par->vram_size = roundup(par->vram_size/8, ulcm);
 	par->vram_size = roundup(par->vram_size/8, ulcm);
 	par->vram_size = par->vram_size * LCD_NUM_BUFFERS;
 	par->vram_size = par->vram_size * LCD_NUM_BUFFERS;
 
 
@@ -1355,10 +1337,10 @@ static int __devinit fb_probe(struct platform_device *device)
 	da8xx_fb_info->screen_base = (char __iomem *) par->vram_virt;
 	da8xx_fb_info->screen_base = (char __iomem *) par->vram_virt;
 	da8xx_fb_fix.smem_start    = par->vram_phys;
 	da8xx_fb_fix.smem_start    = par->vram_phys;
 	da8xx_fb_fix.smem_len      = par->vram_size;
 	da8xx_fb_fix.smem_len      = par->vram_size;
-	da8xx_fb_fix.line_length   = (lcdc_info->width * lcd_cfg->bpp) / 8;
+	da8xx_fb_fix.line_length   = (lcdc_info->xres * lcd_cfg->bpp) / 8;
 
 
 	par->dma_start = par->vram_phys;
 	par->dma_start = par->vram_phys;
-	par->dma_end   = par->dma_start + lcdc_info->height *
+	par->dma_end   = par->dma_start + lcdc_info->yres *
 		da8xx_fb_fix.line_length - 1;
 		da8xx_fb_fix.line_length - 1;
 
 
 	/* allocate palette buffer */
 	/* allocate palette buffer */
@@ -1384,22 +1366,22 @@ static int __devinit fb_probe(struct platform_device *device)
 	/* Initialize par */
 	/* Initialize par */
 	da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp;
 	da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp;
 
 
-	da8xx_fb_var.xres = lcdc_info->width;
-	da8xx_fb_var.xres_virtual = lcdc_info->width;
+	da8xx_fb_var.xres = lcdc_info->xres;
+	da8xx_fb_var.xres_virtual = lcdc_info->xres;
 
 
-	da8xx_fb_var.yres         = lcdc_info->height;
-	da8xx_fb_var.yres_virtual = lcdc_info->height * LCD_NUM_BUFFERS;
+	da8xx_fb_var.yres         = lcdc_info->yres;
+	da8xx_fb_var.yres_virtual = lcdc_info->yres * LCD_NUM_BUFFERS;
 
 
 	da8xx_fb_var.grayscale =
 	da8xx_fb_var.grayscale =
-	    lcd_cfg->p_disp_panel->panel_shade == MONOCHROME ? 1 : 0;
+	    lcd_cfg->panel_shade == MONOCHROME ? 1 : 0;
 	da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp;
 	da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp;
 
 
-	da8xx_fb_var.hsync_len = lcdc_info->hsw;
-	da8xx_fb_var.vsync_len = lcdc_info->vsw;
-	da8xx_fb_var.right_margin = lcdc_info->hfp;
-	da8xx_fb_var.left_margin  = lcdc_info->hbp;
-	da8xx_fb_var.lower_margin = lcdc_info->vfp;
-	da8xx_fb_var.upper_margin = lcdc_info->vbp;
+	da8xx_fb_var.hsync_len = lcdc_info->hsync_len;
+	da8xx_fb_var.vsync_len = lcdc_info->vsync_len;
+	da8xx_fb_var.right_margin = lcdc_info->right_margin;
+	da8xx_fb_var.left_margin  = lcdc_info->left_margin;
+	da8xx_fb_var.lower_margin = lcdc_info->lower_margin;
+	da8xx_fb_var.upper_margin = lcdc_info->upper_margin;
 	da8xx_fb_var.pixclock = da8xxfb_pixel_clk_period(par);
 	da8xx_fb_var.pixclock = da8xxfb_pixel_clk_period(par);
 
 
 	/* Initialize fbinfo */
 	/* Initialize fbinfo */

+ 439 - 258
drivers/video/exynos/exynos_dp_core.c

@@ -18,6 +18,7 @@
 #include <linux/io.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
+#include <linux/of.h>
 
 
 #include <video/exynos_dp.h>
 #include <video/exynos_dp.h>
 
 
@@ -48,10 +49,6 @@ static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
 {
 {
 	int timeout_loop = 0;
 	int timeout_loop = 0;
 
 
-	exynos_dp_init_hpd(dp);
-
-	usleep_range(200, 210);
-
 	while (exynos_dp_get_plug_in_status(dp) != 0) {
 	while (exynos_dp_get_plug_in_status(dp) != 0) {
 		timeout_loop++;
 		timeout_loop++;
 		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
 		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
@@ -90,9 +87,11 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp)
 	 */
 	 */
 
 
 	/* Read Extension Flag, Number of 128-byte EDID extension blocks */
 	/* Read Extension Flag, Number of 128-byte EDID extension blocks */
-	exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
+	retval = exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
 				EDID_EXTENSION_FLAG,
 				EDID_EXTENSION_FLAG,
 				&extend_block);
 				&extend_block);
+	if (retval)
+		return retval;
 
 
 	if (extend_block > 0) {
 	if (extend_block > 0) {
 		dev_dbg(dp->dev, "EDID data includes a single extension!\n");
 		dev_dbg(dp->dev, "EDID data includes a single extension!\n");
@@ -181,14 +180,15 @@ static int exynos_dp_handle_edid(struct exynos_dp_device *dp)
 	int retval;
 	int retval;
 
 
 	/* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */
 	/* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */
-	exynos_dp_read_bytes_from_dpcd(dp,
-		DPCD_ADDR_DPCD_REV,
-		12, buf);
+	retval = exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_DPCD_REV,
+				12, buf);
+	if (retval)
+		return retval;
 
 
 	/* Read EDID */
 	/* Read EDID */
 	for (i = 0; i < 3; i++) {
 	for (i = 0; i < 3; i++) {
 		retval = exynos_dp_read_edid(dp);
 		retval = exynos_dp_read_edid(dp);
-		if (retval == 0)
+		if (!retval)
 			break;
 			break;
 	}
 	}
 
 
@@ -261,11 +261,10 @@ static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp,
 	}
 	}
 }
 }
 
 
-static void exynos_dp_link_start(struct exynos_dp_device *dp)
+static int exynos_dp_link_start(struct exynos_dp_device *dp)
 {
 {
 	u8 buf[4];
 	u8 buf[4];
-	int lane;
-	int lane_count;
+	int lane, lane_count, pll_tries, retval;
 
 
 	lane_count = dp->link_train.lane_count;
 	lane_count = dp->link_train.lane_count;
 
 
@@ -275,10 +274,6 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)
 	for (lane = 0; lane < lane_count; lane++)
 	for (lane = 0; lane < lane_count; lane++)
 		dp->link_train.cr_loop[lane] = 0;
 		dp->link_train.cr_loop[lane] = 0;
 
 
-	/* Set sink to D0 (Sink Not Ready) mode. */
-	exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_SINK_POWER_STATE,
-				DPCD_SET_POWER_STATE_D0);
-
 	/* Set link rate and count as you want to establish*/
 	/* Set link rate and count as you want to establish*/
 	exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
 	exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
 	exynos_dp_set_lane_count(dp, dp->link_train.lane_count);
 	exynos_dp_set_lane_count(dp, dp->link_train.lane_count);
@@ -286,29 +281,46 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)
 	/* Setup RX configuration */
 	/* Setup RX configuration */
 	buf[0] = dp->link_train.link_rate;
 	buf[0] = dp->link_train.link_rate;
 	buf[1] = dp->link_train.lane_count;
 	buf[1] = dp->link_train.lane_count;
-	exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
+	retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
 				2, buf);
 				2, buf);
+	if (retval)
+		return retval;
 
 
 	/* Set TX pre-emphasis to minimum */
 	/* Set TX pre-emphasis to minimum */
 	for (lane = 0; lane < lane_count; lane++)
 	for (lane = 0; lane < lane_count; lane++)
 		exynos_dp_set_lane_lane_pre_emphasis(dp,
 		exynos_dp_set_lane_lane_pre_emphasis(dp,
 			PRE_EMPHASIS_LEVEL_0, lane);
 			PRE_EMPHASIS_LEVEL_0, lane);
 
 
+	/* Wait for PLL lock */
+	pll_tries = 0;
+	while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
+		if (pll_tries == DP_TIMEOUT_LOOP_COUNT) {
+			dev_err(dp->dev, "Wait for PLL lock timed out\n");
+			return -ETIMEDOUT;
+		}
+
+		pll_tries++;
+		usleep_range(90, 120);
+	}
+
 	/* Set training pattern 1 */
 	/* Set training pattern 1 */
 	exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
 	exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
 
 
 	/* Set RX training pattern */
 	/* Set RX training pattern */
-	exynos_dp_write_byte_to_dpcd(dp,
-		DPCD_ADDR_TRAINING_PATTERN_SET,
-		DPCD_SCRAMBLING_DISABLED |
-		DPCD_TRAINING_PATTERN_1);
+	retval = exynos_dp_write_byte_to_dpcd(dp,
+			DPCD_ADDR_TRAINING_PATTERN_SET,
+			DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1);
+	if (retval)
+		return retval;
 
 
 	for (lane = 0; lane < lane_count; lane++)
 	for (lane = 0; lane < lane_count; lane++)
 		buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
 		buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
 			    DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0;
 			    DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0;
-	exynos_dp_write_bytes_to_dpcd(dp,
-		DPCD_ADDR_TRAINING_LANE0_SET,
-		lane_count, buf);
+
+	retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET,
+			lane_count, buf);
+
+	return retval;
 }
 }
 
 
 static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane)
 static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane)
@@ -332,18 +344,17 @@ static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
 	return 0;
 	return 0;
 }
 }
 
 
-static int exynos_dp_channel_eq_ok(u8 link_align[3], int lane_count)
+static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align,
+				int lane_count)
 {
 {
 	int lane;
 	int lane;
-	u8 lane_align;
 	u8 lane_status;
 	u8 lane_status;
 
 
-	lane_align = link_align[2];
-	if ((lane_align & DPCD_INTERLANE_ALIGN_DONE) == 0)
+	if ((link_align & DPCD_INTERLANE_ALIGN_DONE) == 0)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	for (lane = 0; lane < lane_count; lane++) {
 	for (lane = 0; lane < lane_count; lane++) {
-		lane_status = exynos_dp_get_lane_status(link_align, lane);
+		lane_status = exynos_dp_get_lane_status(link_status, lane);
 		lane_status &= DPCD_CHANNEL_EQ_BITS;
 		lane_status &= DPCD_CHANNEL_EQ_BITS;
 		if (lane_status != DPCD_CHANNEL_EQ_BITS)
 		if (lane_status != DPCD_CHANNEL_EQ_BITS)
 			return -EINVAL;
 			return -EINVAL;
@@ -427,60 +438,60 @@ static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
 	dp->link_train.lt_state = FAILED;
 	dp->link_train.lt_state = FAILED;
 }
 }
 
 
-static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
+static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device *dp,
+					u8 adjust_request[2])
 {
 {
-	u8 link_status[2];
-	int lane;
-	int lane_count;
+	int lane, lane_count;
+	u8 voltage_swing, pre_emphasis, training_lane;
 
 
-	u8 adjust_request[2];
-	u8 voltage_swing;
-	u8 pre_emphasis;
-	u8 training_lane;
+	lane_count = dp->link_train.lane_count;
+	for (lane = 0; lane < lane_count; lane++) {
+		voltage_swing = exynos_dp_get_adjust_request_voltage(
+						adjust_request, lane);
+		pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
+						adjust_request, lane);
+		training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
+				DPCD_PRE_EMPHASIS_SET(pre_emphasis);
+
+		if (voltage_swing == VOLTAGE_LEVEL_3)
+			training_lane |= DPCD_MAX_SWING_REACHED;
+		if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
+			training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
+
+		dp->link_train.training_lane[lane] = training_lane;
+	}
+}
+
+static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
+{
+	int lane, lane_count, retval;
+	u8 voltage_swing, pre_emphasis, training_lane;
+	u8 link_status[2], adjust_request[2];
 
 
 	usleep_range(100, 101);
 	usleep_range(100, 101);
 
 
 	lane_count = dp->link_train.lane_count;
 	lane_count = dp->link_train.lane_count;
 
 
-	exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
-				2, link_status);
+	retval =  exynos_dp_read_bytes_from_dpcd(dp,
+			DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
+	if (retval)
+		return retval;
+
+	retval =  exynos_dp_read_bytes_from_dpcd(dp,
+			DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
+	if (retval)
+		return retval;
 
 
 	if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
 	if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
 		/* set training pattern 2 for EQ */
 		/* set training pattern 2 for EQ */
 		exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
 		exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
 
 
-		for (lane = 0; lane < lane_count; lane++) {
-			exynos_dp_read_bytes_from_dpcd(dp,
-					DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
-					2, adjust_request);
-			voltage_swing = exynos_dp_get_adjust_request_voltage(
-							adjust_request, lane);
-			pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
-							adjust_request, lane);
-			training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
-					DPCD_PRE_EMPHASIS_SET(pre_emphasis);
-
-			if (voltage_swing == VOLTAGE_LEVEL_3)
-				training_lane |= DPCD_MAX_SWING_REACHED;
-			if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
-				training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
-
-			dp->link_train.training_lane[lane] = training_lane;
-
-			exynos_dp_set_lane_link_training(dp,
-				dp->link_train.training_lane[lane],
-				lane);
-		}
-
-		exynos_dp_write_byte_to_dpcd(dp,
-			DPCD_ADDR_TRAINING_PATTERN_SET,
-			DPCD_SCRAMBLING_DISABLED |
-			DPCD_TRAINING_PATTERN_2);
-
-		exynos_dp_write_bytes_to_dpcd(dp,
-			DPCD_ADDR_TRAINING_LANE0_SET,
-			lane_count,
-			dp->link_train.training_lane);
+		retval = exynos_dp_write_byte_to_dpcd(dp,
+				DPCD_ADDR_TRAINING_PATTERN_SET,
+				DPCD_SCRAMBLING_DISABLED |
+				DPCD_TRAINING_PATTERN_2);
+		if (retval)
+			return retval;
 
 
 		dev_info(dp->dev, "Link Training Clock Recovery success\n");
 		dev_info(dp->dev, "Link Training Clock Recovery success\n");
 		dp->link_train.lt_state = EQUALIZER_TRAINING;
 		dp->link_train.lt_state = EQUALIZER_TRAINING;
@@ -488,152 +499,116 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
 		for (lane = 0; lane < lane_count; lane++) {
 		for (lane = 0; lane < lane_count; lane++) {
 			training_lane = exynos_dp_get_lane_link_training(
 			training_lane = exynos_dp_get_lane_link_training(
 							dp, lane);
 							dp, lane);
-			exynos_dp_read_bytes_from_dpcd(dp,
-					DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
-					2, adjust_request);
 			voltage_swing = exynos_dp_get_adjust_request_voltage(
 			voltage_swing = exynos_dp_get_adjust_request_voltage(
 							adjust_request, lane);
 							adjust_request, lane);
 			pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
 			pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
 							adjust_request, lane);
 							adjust_request, lane);
 
 
-			if (voltage_swing == VOLTAGE_LEVEL_3 ||
-			    pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
-				dev_err(dp->dev, "voltage or pre emphasis reached max level\n");
-				goto reduce_link_rate;
-			}
-
-			if ((DPCD_VOLTAGE_SWING_GET(training_lane) ==
-					voltage_swing) &&
-			   (DPCD_PRE_EMPHASIS_GET(training_lane) ==
-					pre_emphasis)) {
+			if (DPCD_VOLTAGE_SWING_GET(training_lane) ==
+					voltage_swing &&
+			    DPCD_PRE_EMPHASIS_GET(training_lane) ==
+					pre_emphasis)
 				dp->link_train.cr_loop[lane]++;
 				dp->link_train.cr_loop[lane]++;
-				if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP) {
-					dev_err(dp->dev, "CR Max loop\n");
-					goto reduce_link_rate;
-				}
-			}
-
-			training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
-					DPCD_PRE_EMPHASIS_SET(pre_emphasis);
 
 
-			if (voltage_swing == VOLTAGE_LEVEL_3)
-				training_lane |= DPCD_MAX_SWING_REACHED;
-			if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
-				training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
+			if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP ||
+			    voltage_swing == VOLTAGE_LEVEL_3 ||
+			    pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
+				dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n",
+					dp->link_train.cr_loop[lane],
+					voltage_swing, pre_emphasis);
+				exynos_dp_reduce_link_rate(dp);
+				return -EIO;
+			}
+		}
+	}
 
 
-			dp->link_train.training_lane[lane] = training_lane;
+	exynos_dp_get_adjust_training_lane(dp, adjust_request);
 
 
-			exynos_dp_set_lane_link_training(dp,
-				dp->link_train.training_lane[lane], lane);
-		}
+	for (lane = 0; lane < lane_count; lane++)
+		exynos_dp_set_lane_link_training(dp,
+			dp->link_train.training_lane[lane], lane);
 
 
-		exynos_dp_write_bytes_to_dpcd(dp,
-			DPCD_ADDR_TRAINING_LANE0_SET,
-			lane_count,
+	retval = exynos_dp_write_bytes_to_dpcd(dp,
+			DPCD_ADDR_TRAINING_LANE0_SET, lane_count,
 			dp->link_train.training_lane);
 			dp->link_train.training_lane);
-	}
-
-	return 0;
+	if (retval)
+		return retval;
 
 
-reduce_link_rate:
-	exynos_dp_reduce_link_rate(dp);
-	return -EIO;
+	return retval;
 }
 }
 
 
 static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
 static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
 {
 {
-	u8 link_status[2];
-	u8 link_align[3];
-	int lane;
-	int lane_count;
+	int lane, lane_count, retval;
 	u32 reg;
 	u32 reg;
-
-	u8 adjust_request[2];
-	u8 voltage_swing;
-	u8 pre_emphasis;
-	u8 training_lane;
+	u8 link_align, link_status[2], adjust_request[2];
 
 
 	usleep_range(400, 401);
 	usleep_range(400, 401);
 
 
 	lane_count = dp->link_train.lane_count;
 	lane_count = dp->link_train.lane_count;
 
 
-	exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
-				2, link_status);
+	retval = exynos_dp_read_bytes_from_dpcd(dp,
+			DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
+	if (retval)
+		return retval;
 
 
-	if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
-		link_align[0] = link_status[0];
-		link_align[1] = link_status[1];
+	if (exynos_dp_clock_recovery_ok(link_status, lane_count)) {
+		exynos_dp_reduce_link_rate(dp);
+		return -EIO;
+	}
 
 
-		exynos_dp_read_byte_from_dpcd(dp,
-			DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED,
-			&link_align[2]);
+	retval = exynos_dp_read_bytes_from_dpcd(dp,
+			DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
+	if (retval)
+		return retval;
 
 
-		for (lane = 0; lane < lane_count; lane++) {
-			exynos_dp_read_bytes_from_dpcd(dp,
-					DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
-					2, adjust_request);
-			voltage_swing = exynos_dp_get_adjust_request_voltage(
-							adjust_request, lane);
-			pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
-							adjust_request, lane);
-			training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
-					DPCD_PRE_EMPHASIS_SET(pre_emphasis);
+	retval = exynos_dp_read_byte_from_dpcd(dp,
+			DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED, &link_align);
+	if (retval)
+		return retval;
 
 
-			if (voltage_swing == VOLTAGE_LEVEL_3)
-				training_lane |= DPCD_MAX_SWING_REACHED;
-			if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
-				training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
+	exynos_dp_get_adjust_training_lane(dp, adjust_request);
 
 
-			dp->link_train.training_lane[lane] = training_lane;
-		}
+	if (!exynos_dp_channel_eq_ok(link_status, link_align, lane_count)) {
+		/* traing pattern Set to Normal */
+		exynos_dp_training_pattern_dis(dp);
 
 
-		if (exynos_dp_channel_eq_ok(link_align, lane_count) == 0) {
-			/* traing pattern Set to Normal */
-			exynos_dp_training_pattern_dis(dp);
+		dev_info(dp->dev, "Link Training success!\n");
 
 
-			dev_info(dp->dev, "Link Training success!\n");
-
-			exynos_dp_get_link_bandwidth(dp, &reg);
-			dp->link_train.link_rate = reg;
-			dev_dbg(dp->dev, "final bandwidth = %.2x\n",
-				dp->link_train.link_rate);
+		exynos_dp_get_link_bandwidth(dp, &reg);
+		dp->link_train.link_rate = reg;
+		dev_dbg(dp->dev, "final bandwidth = %.2x\n",
+			dp->link_train.link_rate);
 
 
-			exynos_dp_get_lane_count(dp, &reg);
-			dp->link_train.lane_count = reg;
-			dev_dbg(dp->dev, "final lane count = %.2x\n",
-				dp->link_train.lane_count);
+		exynos_dp_get_lane_count(dp, &reg);
+		dp->link_train.lane_count = reg;
+		dev_dbg(dp->dev, "final lane count = %.2x\n",
+			dp->link_train.lane_count);
 
 
-			/* set enhanced mode if available */
-			exynos_dp_set_enhanced_mode(dp);
-			dp->link_train.lt_state = FINISHED;
-		} else {
-			/* not all locked */
-			dp->link_train.eq_loop++;
+		/* set enhanced mode if available */
+		exynos_dp_set_enhanced_mode(dp);
+		dp->link_train.lt_state = FINISHED;
 
 
-			if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
-				dev_err(dp->dev, "EQ Max loop\n");
-				goto reduce_link_rate;
-			}
+		return 0;
+	}
 
 
-			for (lane = 0; lane < lane_count; lane++)
-				exynos_dp_set_lane_link_training(dp,
-					dp->link_train.training_lane[lane],
-					lane);
+	/* not all locked */
+	dp->link_train.eq_loop++;
 
 
-			exynos_dp_write_bytes_to_dpcd(dp,
-				DPCD_ADDR_TRAINING_LANE0_SET,
-				lane_count,
-				dp->link_train.training_lane);
-		}
-	} else {
-		goto reduce_link_rate;
+	if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
+		dev_err(dp->dev, "EQ Max loop\n");
+		exynos_dp_reduce_link_rate(dp);
+		return -EIO;
 	}
 	}
 
 
-	return 0;
+	for (lane = 0; lane < lane_count; lane++)
+		exynos_dp_set_lane_link_training(dp,
+			dp->link_train.training_lane[lane], lane);
+
+	retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET,
+			lane_count, dp->link_train.training_lane);
 
 
-reduce_link_rate:
-	exynos_dp_reduce_link_rate(dp);
-	return -EIO;
+	return retval;
 }
 }
 
 
 static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
 static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
@@ -701,16 +676,17 @@ static void exynos_dp_init_training(struct exynos_dp_device *dp,
 
 
 static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
 static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
 {
 {
-	int retval = 0;
-	int training_finished = 0;
+	int retval = 0, training_finished = 0;
 
 
 	dp->link_train.lt_state = START;
 	dp->link_train.lt_state = START;
 
 
 	/* Process here */
 	/* Process here */
-	while (!training_finished) {
+	while (!retval && !training_finished) {
 		switch (dp->link_train.lt_state) {
 		switch (dp->link_train.lt_state) {
 		case START:
 		case START:
-			exynos_dp_link_start(dp);
+			retval = exynos_dp_link_start(dp);
+			if (retval)
+				dev_err(dp->dev, "LT link start failed!\n");
 			break;
 			break;
 		case CLOCK_RECOVERY:
 		case CLOCK_RECOVERY:
 			retval = exynos_dp_process_clock_recovery(dp);
 			retval = exynos_dp_process_clock_recovery(dp);
@@ -729,6 +705,8 @@ static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
 			return -EREMOTEIO;
 			return -EREMOTEIO;
 		}
 		}
 	}
 	}
+	if (retval)
+		dev_err(dp->dev, "eDP link training failed (%d)\n", retval);
 
 
 	return retval;
 	return retval;
 }
 }
@@ -752,19 +730,15 @@ static int exynos_dp_set_link_train(struct exynos_dp_device *dp,
 	return retval;
 	return retval;
 }
 }
 
 
-static int exynos_dp_config_video(struct exynos_dp_device *dp,
-			struct video_info *video_info)
+static int exynos_dp_config_video(struct exynos_dp_device *dp)
 {
 {
 	int retval = 0;
 	int retval = 0;
 	int timeout_loop = 0;
 	int timeout_loop = 0;
 	int done_count = 0;
 	int done_count = 0;
 
 
-	exynos_dp_config_video_slave_mode(dp, video_info);
+	exynos_dp_config_video_slave_mode(dp);
 
 
-	exynos_dp_set_video_color_format(dp, video_info->color_depth,
-			video_info->color_space,
-			video_info->dynamic_range,
-			video_info->ycbcr_coeff);
+	exynos_dp_set_video_color_format(dp);
 
 
 	if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
 	if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
 		dev_err(dp->dev, "PLL is not locked yet.\n");
 		dev_err(dp->dev, "PLL is not locked yet.\n");
@@ -852,10 +826,213 @@ static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
 {
 {
 	struct exynos_dp_device *dp = arg;
 	struct exynos_dp_device *dp = arg;
 
 
-	dev_err(dp->dev, "exynos_dp_irq_handler\n");
+	enum dp_irq_type irq_type;
+
+	irq_type = exynos_dp_get_irq_type(dp);
+	switch (irq_type) {
+	case DP_IRQ_TYPE_HP_CABLE_IN:
+		dev_dbg(dp->dev, "Received irq - cable in\n");
+		schedule_work(&dp->hotplug_work);
+		exynos_dp_clear_hotplug_interrupts(dp);
+		break;
+	case DP_IRQ_TYPE_HP_CABLE_OUT:
+		dev_dbg(dp->dev, "Received irq - cable out\n");
+		exynos_dp_clear_hotplug_interrupts(dp);
+		break;
+	case DP_IRQ_TYPE_HP_CHANGE:
+		/*
+		 * We get these change notifications once in a while, but there
+		 * is nothing we can do with them. Just ignore it for now and
+		 * only handle cable changes.
+		 */
+		dev_dbg(dp->dev, "Received irq - hotplug change; ignoring.\n");
+		exynos_dp_clear_hotplug_interrupts(dp);
+		break;
+	default:
+		dev_err(dp->dev, "Received irq - unknown type!\n");
+		break;
+	}
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
 
 
+static void exynos_dp_hotplug(struct work_struct *work)
+{
+	struct exynos_dp_device *dp;
+	int ret;
+
+	dp = container_of(work, struct exynos_dp_device, hotplug_work);
+
+	ret = exynos_dp_detect_hpd(dp);
+	if (ret) {
+		/* Cable has been disconnected, we're done */
+		return;
+	}
+
+	ret = exynos_dp_handle_edid(dp);
+	if (ret) {
+		dev_err(dp->dev, "unable to handle edid\n");
+		return;
+	}
+
+	ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
+					dp->video_info->link_rate);
+	if (ret) {
+		dev_err(dp->dev, "unable to do link train\n");
+		return;
+	}
+
+	exynos_dp_enable_scramble(dp, 1);
+	exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
+	exynos_dp_enable_enhanced_mode(dp, 1);
+
+	exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
+	exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
+
+	exynos_dp_init_video(dp);
+	ret = exynos_dp_config_video(dp);
+	if (ret)
+		dev_err(dp->dev, "unable to config video\n");
+}
+
+#ifdef CONFIG_OF
+static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
+{
+	struct device_node *dp_node = dev->of_node;
+	struct exynos_dp_platdata *pd;
+	struct video_info *dp_video_config;
+
+	pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+	if (!pd) {
+		dev_err(dev, "memory allocation for pdata failed\n");
+		return ERR_PTR(-ENOMEM);
+	}
+	dp_video_config = devm_kzalloc(dev,
+				sizeof(*dp_video_config), GFP_KERNEL);
+
+	if (!dp_video_config) {
+		dev_err(dev, "memory allocation for video config failed\n");
+		return ERR_PTR(-ENOMEM);
+	}
+	pd->video_info = dp_video_config;
+
+	dp_video_config->h_sync_polarity =
+		of_property_read_bool(dp_node, "hsync-active-high");
+
+	dp_video_config->v_sync_polarity =
+		of_property_read_bool(dp_node, "vsync-active-high");
+
+	dp_video_config->interlaced =
+		of_property_read_bool(dp_node, "interlaced");
+
+	if (of_property_read_u32(dp_node, "samsung,color-space",
+				&dp_video_config->color_space)) {
+		dev_err(dev, "failed to get color-space\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (of_property_read_u32(dp_node, "samsung,dynamic-range",
+				&dp_video_config->dynamic_range)) {
+		dev_err(dev, "failed to get dynamic-range\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
+				&dp_video_config->ycbcr_coeff)) {
+		dev_err(dev, "failed to get ycbcr-coeff\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (of_property_read_u32(dp_node, "samsung,color-depth",
+				&dp_video_config->color_depth)) {
+		dev_err(dev, "failed to get color-depth\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (of_property_read_u32(dp_node, "samsung,link-rate",
+				&dp_video_config->link_rate)) {
+		dev_err(dev, "failed to get link-rate\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (of_property_read_u32(dp_node, "samsung,lane-count",
+				&dp_video_config->lane_count)) {
+		dev_err(dev, "failed to get lane-count\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	return pd;
+}
+
+static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
+{
+	struct device_node *dp_phy_node;
+	u32 phy_base;
+
+	dp_phy_node = of_find_node_by_name(dp->dev->of_node, "dptx-phy");
+	if (!dp_phy_node) {
+		dev_err(dp->dev, "could not find dptx-phy node\n");
+		return -ENODEV;
+	}
+
+	if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
+		dev_err(dp->dev, "faild to get reg for dptx-phy\n");
+		return -EINVAL;
+	}
+
+	if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
+				&dp->enable_mask)) {
+		dev_err(dp->dev, "faild to get enable-mask for dptx-phy\n");
+		return -EINVAL;
+	}
+
+	dp->phy_addr = ioremap(phy_base, SZ_4);
+	if (!dp->phy_addr) {
+		dev_err(dp->dev, "failed to ioremap dp-phy\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void exynos_dp_phy_init(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = __raw_readl(dp->phy_addr);
+	reg |= dp->enable_mask;
+	__raw_writel(reg, dp->phy_addr);
+}
+
+static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	reg = __raw_readl(dp->phy_addr);
+	reg &= ~(dp->enable_mask);
+	__raw_writel(reg, dp->phy_addr);
+}
+#else
+static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
+{
+	return NULL;
+}
+
+static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
+{
+	return -EINVAL;
+}
+
+static void exynos_dp_phy_init(struct exynos_dp_device *dp)
+{
+	return;
+}
+
+static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
+{
+	return;
+}
+#endif /* CONFIG_OF */
+
 static int __devinit exynos_dp_probe(struct platform_device *pdev)
 static int __devinit exynos_dp_probe(struct platform_device *pdev)
 {
 {
 	struct resource *res;
 	struct resource *res;
@@ -864,12 +1041,6 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
 
 
 	int ret = 0;
 	int ret = 0;
 
 
-	pdata = pdev->dev.platform_data;
-	if (!pdata) {
-		dev_err(&pdev->dev, "no platform data\n");
-		return -EINVAL;
-	}
-
 	dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
 	dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
 				GFP_KERNEL);
 				GFP_KERNEL);
 	if (!dp) {
 	if (!dp) {
@@ -879,6 +1050,22 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
 
 
 	dp->dev = &pdev->dev;
 	dp->dev = &pdev->dev;
 
 
+	if (pdev->dev.of_node) {
+		pdata = exynos_dp_dt_parse_pdata(&pdev->dev);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+
+		ret = exynos_dp_dt_parse_phydata(dp);
+		if (ret)
+			return ret;
+	} else {
+		pdata = pdev->dev.platform_data;
+		if (!pdata) {
+			dev_err(&pdev->dev, "no platform data\n");
+			return -EINVAL;
+		}
+	}
+
 	dp->clock = devm_clk_get(&pdev->dev, "dp");
 	dp->clock = devm_clk_get(&pdev->dev, "dp");
 	if (IS_ERR(dp->clock)) {
 	if (IS_ERR(dp->clock)) {
 		dev_err(&pdev->dev, "failed to get clock\n");
 		dev_err(&pdev->dev, "failed to get clock\n");
@@ -896,50 +1083,29 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
 	}
 	}
 
 
 	dp->irq = platform_get_irq(pdev, 0);
 	dp->irq = platform_get_irq(pdev, 0);
-	if (!dp->irq) {
+	if (dp->irq == -ENXIO) {
 		dev_err(&pdev->dev, "failed to get irq\n");
 		dev_err(&pdev->dev, "failed to get irq\n");
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
-	ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0,
-				"exynos-dp", dp);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to request irq\n");
-		return ret;
-	}
+	INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
 
 
 	dp->video_info = pdata->video_info;
 	dp->video_info = pdata->video_info;
-	if (pdata->phy_init)
-		pdata->phy_init();
-
-	exynos_dp_init_dp(dp);
-
-	ret = exynos_dp_detect_hpd(dp);
-	if (ret) {
-		dev_err(&pdev->dev, "unable to detect hpd\n");
-		return ret;
-	}
 
 
-	exynos_dp_handle_edid(dp);
-
-	ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
-				dp->video_info->link_rate);
-	if (ret) {
-		dev_err(&pdev->dev, "unable to do link train\n");
-		return ret;
+	if (pdev->dev.of_node) {
+		if (dp->phy_addr)
+			exynos_dp_phy_init(dp);
+	} else {
+		if (pdata->phy_init)
+			pdata->phy_init();
 	}
 	}
 
 
-	exynos_dp_enable_scramble(dp, 1);
-	exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
-	exynos_dp_enable_enhanced_mode(dp, 1);
-
-	exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
-	exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
+	exynos_dp_init_dp(dp);
 
 
-	exynos_dp_init_video(dp);
-	ret = exynos_dp_config_video(dp, dp->video_info);
+	ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0,
+				"exynos-dp", dp);
 	if (ret) {
 	if (ret) {
-		dev_err(&pdev->dev, "unable to config video\n");
+		dev_err(&pdev->dev, "failed to request irq\n");
 		return ret;
 		return ret;
 	}
 	}
 
 
@@ -953,23 +1119,41 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
 	struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
 	struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
 	struct exynos_dp_device *dp = platform_get_drvdata(pdev);
 	struct exynos_dp_device *dp = platform_get_drvdata(pdev);
 
 
-	if (pdata && pdata->phy_exit)
-		pdata->phy_exit();
+	disable_irq(dp->irq);
+
+	if (work_pending(&dp->hotplug_work))
+		flush_work(&dp->hotplug_work);
+
+	if (pdev->dev.of_node) {
+		if (dp->phy_addr)
+			exynos_dp_phy_exit(dp);
+	} else {
+		if (pdata->phy_exit)
+			pdata->phy_exit();
+	}
 
 
 	clk_disable_unprepare(dp->clock);
 	clk_disable_unprepare(dp->clock);
 
 
+
 	return 0;
 	return 0;
 }
 }
 
 
 #ifdef CONFIG_PM_SLEEP
 #ifdef CONFIG_PM_SLEEP
 static int exynos_dp_suspend(struct device *dev)
 static int exynos_dp_suspend(struct device *dev)
 {
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
-	struct exynos_dp_device *dp = platform_get_drvdata(pdev);
+	struct exynos_dp_platdata *pdata = dev->platform_data;
+	struct exynos_dp_device *dp = dev_get_drvdata(dev);
 
 
-	if (pdata && pdata->phy_exit)
-		pdata->phy_exit();
+	if (work_pending(&dp->hotplug_work))
+		flush_work(&dp->hotplug_work);
+
+	if (dev->of_node) {
+		if (dp->phy_addr)
+			exynos_dp_phy_exit(dp);
+	} else {
+		if (pdata->phy_exit)
+			pdata->phy_exit();
+	}
 
 
 	clk_disable_unprepare(dp->clock);
 	clk_disable_unprepare(dp->clock);
 
 
@@ -978,32 +1162,22 @@ static int exynos_dp_suspend(struct device *dev)
 
 
 static int exynos_dp_resume(struct device *dev)
 static int exynos_dp_resume(struct device *dev)
 {
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
-	struct exynos_dp_device *dp = platform_get_drvdata(pdev);
+	struct exynos_dp_platdata *pdata = dev->platform_data;
+	struct exynos_dp_device *dp = dev_get_drvdata(dev);
 
 
-	if (pdata && pdata->phy_init)
-		pdata->phy_init();
+	if (dev->of_node) {
+		if (dp->phy_addr)
+			exynos_dp_phy_init(dp);
+	} else {
+		if (pdata->phy_init)
+			pdata->phy_init();
+	}
 
 
 	clk_prepare_enable(dp->clock);
 	clk_prepare_enable(dp->clock);
 
 
 	exynos_dp_init_dp(dp);
 	exynos_dp_init_dp(dp);
 
 
-	exynos_dp_detect_hpd(dp);
-	exynos_dp_handle_edid(dp);
-
-	exynos_dp_set_link_train(dp, dp->video_info->lane_count,
-				dp->video_info->link_rate);
-
-	exynos_dp_enable_scramble(dp, 1);
-	exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
-	exynos_dp_enable_enhanced_mode(dp, 1);
-
-	exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
-	exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
-
-	exynos_dp_init_video(dp);
-	exynos_dp_config_video(dp, dp->video_info);
+	enable_irq(dp->irq);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -1013,6 +1187,12 @@ static const struct dev_pm_ops exynos_dp_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
 	SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
 };
 };
 
 
+static const struct of_device_id exynos_dp_match[] = {
+	{ .compatible = "samsung,exynos5-dp" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, exynos_dp_match);
+
 static struct platform_driver exynos_dp_driver = {
 static struct platform_driver exynos_dp_driver = {
 	.probe		= exynos_dp_probe,
 	.probe		= exynos_dp_probe,
 	.remove		= __devexit_p(exynos_dp_remove),
 	.remove		= __devexit_p(exynos_dp_remove),
@@ -1020,6 +1200,7 @@ static struct platform_driver exynos_dp_driver = {
 		.name	= "exynos-dp",
 		.name	= "exynos-dp",
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 		.pm	= &exynos_dp_pm_ops,
 		.pm	= &exynos_dp_pm_ops,
+		.of_match_table = of_match_ptr(exynos_dp_match),
 	},
 	},
 };
 };
 
 

+ 14 - 7
drivers/video/exynos/exynos_dp_core.h

@@ -13,6 +13,13 @@
 #ifndef _EXYNOS_DP_CORE_H
 #ifndef _EXYNOS_DP_CORE_H
 #define _EXYNOS_DP_CORE_H
 #define _EXYNOS_DP_CORE_H
 
 
+enum dp_irq_type {
+	DP_IRQ_TYPE_HP_CABLE_IN,
+	DP_IRQ_TYPE_HP_CABLE_OUT,
+	DP_IRQ_TYPE_HP_CHANGE,
+	DP_IRQ_TYPE_UNKNOWN,
+};
+
 struct link_train {
 struct link_train {
 	int eq_loop;
 	int eq_loop;
 	int cr_loop[4];
 	int cr_loop[4];
@@ -29,9 +36,12 @@ struct exynos_dp_device {
 	struct clk		*clock;
 	struct clk		*clock;
 	unsigned int		irq;
 	unsigned int		irq;
 	void __iomem		*reg_base;
 	void __iomem		*reg_base;
+	void __iomem		*phy_addr;
+	unsigned int		enable_mask;
 
 
 	struct video_info	*video_info;
 	struct video_info	*video_info;
 	struct link_train	link_train;
 	struct link_train	link_train;
+	struct work_struct	hotplug_work;
 };
 };
 
 
 /* exynos_dp_reg.c */
 /* exynos_dp_reg.c */
@@ -50,6 +60,8 @@ void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
 				bool enable);
 				bool enable);
 void exynos_dp_init_analog_func(struct exynos_dp_device *dp);
 void exynos_dp_init_analog_func(struct exynos_dp_device *dp);
 void exynos_dp_init_hpd(struct exynos_dp_device *dp);
 void exynos_dp_init_hpd(struct exynos_dp_device *dp);
+enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp);
+void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp);
 void exynos_dp_reset_aux(struct exynos_dp_device *dp);
 void exynos_dp_reset_aux(struct exynos_dp_device *dp);
 void exynos_dp_init_aux(struct exynos_dp_device *dp);
 void exynos_dp_init_aux(struct exynos_dp_device *dp);
 int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp);
 int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp);
@@ -107,11 +119,7 @@ u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
 void exynos_dp_reset_macro(struct exynos_dp_device *dp);
 void exynos_dp_reset_macro(struct exynos_dp_device *dp);
 void exynos_dp_init_video(struct exynos_dp_device *dp);
 void exynos_dp_init_video(struct exynos_dp_device *dp);
 
 
-void exynos_dp_set_video_color_format(struct exynos_dp_device *dp,
-				u32 color_depth,
-				u32 color_space,
-				u32 dynamic_range,
-				u32 ycbcr_coeff);
+void exynos_dp_set_video_color_format(struct exynos_dp_device *dp);
 int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp);
 int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp);
 void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
 void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
 			enum clock_recovery_m_value_type type,
 			enum clock_recovery_m_value_type type,
@@ -121,8 +129,7 @@ void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type);
 void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable);
 void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable);
 void exynos_dp_start_video(struct exynos_dp_device *dp);
 void exynos_dp_start_video(struct exynos_dp_device *dp);
 int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp);
 int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp);
-void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp,
-			struct video_info *video_info);
+void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp);
 void exynos_dp_enable_scrambling(struct exynos_dp_device *dp);
 void exynos_dp_enable_scrambling(struct exynos_dp_device *dp);
 void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
 void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
 
 

+ 48 - 29
drivers/video/exynos/exynos_dp_reg.c

@@ -19,11 +19,11 @@
 #include "exynos_dp_core.h"
 #include "exynos_dp_core.h"
 #include "exynos_dp_reg.h"
 #include "exynos_dp_reg.h"
 
 
-#define COMMON_INT_MASK_1 (0)
-#define COMMON_INT_MASK_2 (0)
-#define COMMON_INT_MASK_3 (0)
-#define COMMON_INT_MASK_4 (0)
-#define INT_STA_MASK (0)
+#define COMMON_INT_MASK_1	0
+#define COMMON_INT_MASK_2	0
+#define COMMON_INT_MASK_3	0
+#define COMMON_INT_MASK_4	(HOTPLUG_CHG | HPD_LOST | PLUG)
+#define INT_STA_MASK		INT_HPD
 
 
 void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable)
 void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable)
 {
 {
@@ -88,7 +88,7 @@ void exynos_dp_init_analog_param(struct exynos_dp_device *dp)
 void exynos_dp_init_interrupt(struct exynos_dp_device *dp)
 void exynos_dp_init_interrupt(struct exynos_dp_device *dp)
 {
 {
 	/* Set interrupt pin assertion polarity as high */
 	/* Set interrupt pin assertion polarity as high */
-	writel(INT_POL, dp->reg_base + EXYNOS_DP_INT_CTL);
+	writel(INT_POL1 | INT_POL0, dp->reg_base + EXYNOS_DP_INT_CTL);
 
 
 	/* Clear pending regisers */
 	/* Clear pending regisers */
 	writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
 	writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
@@ -324,7 +324,7 @@ void exynos_dp_init_analog_func(struct exynos_dp_device *dp)
 	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
 	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
 }
 }
 
 
-void exynos_dp_init_hpd(struct exynos_dp_device *dp)
+void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp)
 {
 {
 	u32 reg;
 	u32 reg;
 
 
@@ -333,12 +333,38 @@ void exynos_dp_init_hpd(struct exynos_dp_device *dp)
 
 
 	reg = INT_HPD;
 	reg = INT_HPD;
 	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
 	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
+}
+
+void exynos_dp_init_hpd(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	exynos_dp_clear_hotplug_interrupts(dp);
 
 
 	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
 	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
 	reg &= ~(F_HPD | HPD_CTRL);
 	reg &= ~(F_HPD | HPD_CTRL);
 	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
 	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
 }
 }
 
 
+enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp)
+{
+	u32 reg;
+
+	/* Parse hotplug interrupt status register */
+	reg = readl(dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
+
+	if (reg & PLUG)
+		return DP_IRQ_TYPE_HP_CABLE_IN;
+
+	if (reg & HPD_LOST)
+		return DP_IRQ_TYPE_HP_CABLE_OUT;
+
+	if (reg & HOTPLUG_CHG)
+		return DP_IRQ_TYPE_HP_CHANGE;
+
+	return DP_IRQ_TYPE_UNKNOWN;
+}
+
 void exynos_dp_reset_aux(struct exynos_dp_device *dp)
 void exynos_dp_reset_aux(struct exynos_dp_device *dp)
 {
 {
 	u32 reg;
 	u32 reg;
@@ -491,7 +517,7 @@ int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
 	int i;
 	int i;
 	int retval;
 	int retval;
 
 
-	for (i = 0; i < 10; i++) {
+	for (i = 0; i < 3; i++) {
 		/* Clear AUX CH data buffer */
 		/* Clear AUX CH data buffer */
 		reg = BUF_CLR;
 		reg = BUF_CLR;
 		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
 		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
@@ -552,7 +578,7 @@ int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
 		else
 		else
 			cur_data_count = count - start_offset;
 			cur_data_count = count - start_offset;
 
 
-		for (i = 0; i < 10; i++) {
+		for (i = 0; i < 3; i++) {
 			/* Select DPCD device address */
 			/* Select DPCD device address */
 			reg = AUX_ADDR_7_0(reg_addr + start_offset);
 			reg = AUX_ADDR_7_0(reg_addr + start_offset);
 			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
 			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
@@ -617,7 +643,7 @@ int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
 			cur_data_count = count - start_offset;
 			cur_data_count = count - start_offset;
 
 
 		/* AUX CH Request Transaction process */
 		/* AUX CH Request Transaction process */
-		for (i = 0; i < 10; i++) {
+		for (i = 0; i < 3; i++) {
 			/* Select DPCD device address */
 			/* Select DPCD device address */
 			reg = AUX_ADDR_7_0(reg_addr + start_offset);
 			reg = AUX_ADDR_7_0(reg_addr + start_offset);
 			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
 			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
@@ -700,17 +726,15 @@ int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
 	int i;
 	int i;
 	int retval;
 	int retval;
 
 
-	for (i = 0; i < 10; i++) {
+	for (i = 0; i < 3; i++) {
 		/* Clear AUX CH data buffer */
 		/* Clear AUX CH data buffer */
 		reg = BUF_CLR;
 		reg = BUF_CLR;
 		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
 		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
 
 
 		/* Select EDID device */
 		/* Select EDID device */
 		retval = exynos_dp_select_i2c_device(dp, device_addr, reg_addr);
 		retval = exynos_dp_select_i2c_device(dp, device_addr, reg_addr);
-		if (retval != 0) {
-			dev_err(dp->dev, "Select EDID device fail!\n");
+		if (retval != 0)
 			continue;
 			continue;
-		}
 
 
 		/*
 		/*
 		 * Set I2C transaction and read data
 		 * Set I2C transaction and read data
@@ -750,7 +774,7 @@ int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
 	int retval = 0;
 	int retval = 0;
 
 
 	for (i = 0; i < count; i += 16) {
 	for (i = 0; i < count; i += 16) {
-		for (j = 0; j < 100; j++) {
+		for (j = 0; j < 3; j++) {
 			/* Clear AUX CH data buffer */
 			/* Clear AUX CH data buffer */
 			reg = BUF_CLR;
 			reg = BUF_CLR;
 			writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
 			writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
@@ -1034,24 +1058,20 @@ void exynos_dp_init_video(struct exynos_dp_device *dp)
 	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
 	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
 }
 }
 
 
-void exynos_dp_set_video_color_format(struct exynos_dp_device *dp,
-			u32 color_depth,
-			u32 color_space,
-			u32 dynamic_range,
-			u32 ycbcr_coeff)
+void exynos_dp_set_video_color_format(struct exynos_dp_device *dp)
 {
 {
 	u32 reg;
 	u32 reg;
 
 
 	/* Configure the input color depth, color space, dynamic range */
 	/* Configure the input color depth, color space, dynamic range */
-	reg = (dynamic_range << IN_D_RANGE_SHIFT) |
-		(color_depth << IN_BPC_SHIFT) |
-		(color_space << IN_COLOR_F_SHIFT);
+	reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) |
+		(dp->video_info->color_depth << IN_BPC_SHIFT) |
+		(dp->video_info->color_space << IN_COLOR_F_SHIFT);
 	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2);
 	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2);
 
 
 	/* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
 	/* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
 	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
 	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
 	reg &= ~IN_YC_COEFFI_MASK;
 	reg &= ~IN_YC_COEFFI_MASK;
-	if (ycbcr_coeff)
+	if (dp->video_info->ycbcr_coeff)
 		reg |= IN_YC_COEFFI_ITU709;
 		reg |= IN_YC_COEFFI_ITU709;
 	else
 	else
 		reg |= IN_YC_COEFFI_ITU601;
 		reg |= IN_YC_COEFFI_ITU601;
@@ -1178,8 +1198,7 @@ int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp)
 	return 0;
 	return 0;
 }
 }
 
 
-void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp,
-			struct video_info *video_info)
+void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp)
 {
 {
 	u32 reg;
 	u32 reg;
 
 
@@ -1190,17 +1209,17 @@ void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp,
 
 
 	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
 	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
 	reg &= ~INTERACE_SCAN_CFG;
 	reg &= ~INTERACE_SCAN_CFG;
-	reg |= (video_info->interlaced << 2);
+	reg |= (dp->video_info->interlaced << 2);
 	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
 	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
 
 
 	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
 	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
 	reg &= ~VSYNC_POLARITY_CFG;
 	reg &= ~VSYNC_POLARITY_CFG;
-	reg |= (video_info->v_sync_polarity << 1);
+	reg |= (dp->video_info->v_sync_polarity << 1);
 	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
 	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
 
 
 	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
 	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
 	reg &= ~HSYNC_POLARITY_CFG;
 	reg &= ~HSYNC_POLARITY_CFG;
-	reg |= (video_info->h_sync_polarity << 0);
+	reg |= (dp->video_info->h_sync_polarity << 0);
 	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
 	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
 
 
 	reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
 	reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;

+ 2 - 1
drivers/video/exynos/exynos_dp_reg.h

@@ -242,7 +242,8 @@
 
 
 /* EXYNOS_DP_INT_CTL */
 /* EXYNOS_DP_INT_CTL */
 #define SOFT_INT_CTRL				(0x1 << 2)
 #define SOFT_INT_CTRL				(0x1 << 2)
-#define INT_POL					(0x1 << 0)
+#define INT_POL1				(0x1 << 1)
+#define INT_POL0				(0x1 << 0)
 
 
 /* EXYNOS_DP_SYS_CTL_1 */
 /* EXYNOS_DP_SYS_CTL_1 */
 #define DET_STA					(0x1 << 2)
 #define DET_STA					(0x1 << 2)

+ 120 - 81
drivers/video/fsl-diu-fb.c

@@ -337,13 +337,11 @@ struct mfb_info {
 	int registered;
 	int registered;
 	unsigned long pseudo_palette[16];
 	unsigned long pseudo_palette[16];
 	struct diu_ad *ad;
 	struct diu_ad *ad;
-	int cursor_reset;
 	unsigned char g_alpha;
 	unsigned char g_alpha;
 	unsigned int count;
 	unsigned int count;
 	int x_aoi_d;		/* aoi display x offset to physical screen */
 	int x_aoi_d;		/* aoi display x offset to physical screen */
 	int y_aoi_d;		/* aoi display y offset to physical screen */
 	int y_aoi_d;		/* aoi display y offset to physical screen */
 	struct fsl_diu_data *parent;
 	struct fsl_diu_data *parent;
-	u8 *edid_data;
 };
 };
 
 
 /**
 /**
@@ -378,6 +376,8 @@ struct fsl_diu_data {
 	struct diu_ad ad[NUM_AOIS] __aligned(8);
 	struct diu_ad ad[NUM_AOIS] __aligned(8);
 	u8 gamma[256 * 3] __aligned(32);
 	u8 gamma[256 * 3] __aligned(32);
 	u8 cursor[MAX_CURS * MAX_CURS * 2] __aligned(32);
 	u8 cursor[MAX_CURS * MAX_CURS * 2] __aligned(32);
+	uint8_t edid_data[EDID_LENGTH];
+	bool has_edid;
 } __aligned(32);
 } __aligned(32);
 
 
 /* Determine the DMA address of a member of the fsl_diu_data structure */
 /* Determine the DMA address of a member of the fsl_diu_data structure */
@@ -430,6 +430,22 @@ static struct mfb_info mfb_template[] = {
 	},
 	},
 };
 };
 
 
+#ifdef DEBUG
+static void __attribute__ ((unused)) fsl_diu_dump(struct diu __iomem *hw)
+{
+	mb();
+	pr_debug("DIU: desc=%08x,%08x,%08x, gamma=%08x pallete=%08x "
+		 "cursor=%08x curs_pos=%08x diu_mode=%08x bgnd=%08x "
+		 "disp_size=%08x hsyn_para=%08x vsyn_para=%08x syn_pol=%08x "
+		 "thresholds=%08x int_mask=%08x plut=%08x\n",
+		 hw->desc[0], hw->desc[1], hw->desc[2], hw->gamma,
+		 hw->pallete, hw->cursor, hw->curs_pos, hw->diu_mode,
+		 hw->bgnd, hw->disp_size, hw->hsyn_para, hw->vsyn_para,
+		 hw->syn_pol, hw->thresholds, hw->int_mask, hw->plut);
+	rmb();
+}
+#endif
+
 /**
 /**
  * fsl_diu_name_to_port - convert a port name to a monitor port enum
  * fsl_diu_name_to_port - convert a port name to a monitor port enum
  *
  *
@@ -481,8 +497,7 @@ static void fsl_diu_enable_panel(struct fb_info *info)
 
 
 	switch (mfbi->index) {
 	switch (mfbi->index) {
 	case PLANE0:
 	case PLANE0:
-		if (hw->desc[0] != ad->paddr)
-			wr_reg_wa(&hw->desc[0], ad->paddr);
+		wr_reg_wa(&hw->desc[0], ad->paddr);
 		break;
 		break;
 	case PLANE1_AOI0:
 	case PLANE1_AOI0:
 		cmfbi = &data->mfb[2];
 		cmfbi = &data->mfb[2];
@@ -534,8 +549,7 @@ static void fsl_diu_disable_panel(struct fb_info *info)
 
 
 	switch (mfbi->index) {
 	switch (mfbi->index) {
 	case PLANE0:
 	case PLANE0:
-		if (hw->desc[0] != data->dummy_ad.paddr)
-			wr_reg_wa(&hw->desc[0], data->dummy_ad.paddr);
+		wr_reg_wa(&hw->desc[0], 0);
 		break;
 		break;
 	case PLANE1_AOI0:
 	case PLANE1_AOI0:
 		cmfbi = &data->mfb[2];
 		cmfbi = &data->mfb[2];
@@ -792,7 +806,8 @@ static void update_lcdc(struct fb_info *info)
 
 
 	hw = data->diu_reg;
 	hw = data->diu_reg;
 
 
-	diu_ops.set_monitor_port(data->monitor_port);
+	if (diu_ops.set_monitor_port)
+		diu_ops.set_monitor_port(data->monitor_port);
 	gamma_table_base = data->gamma;
 	gamma_table_base = data->gamma;
 
 
 	/* Prep for DIU init  - gamma table, cursor table */
 	/* Prep for DIU init  - gamma table, cursor table */
@@ -811,12 +826,8 @@ static void update_lcdc(struct fb_info *info)
 	out_be32(&hw->gamma, DMA_ADDR(data, gamma));
 	out_be32(&hw->gamma, DMA_ADDR(data, gamma));
 	out_be32(&hw->cursor, DMA_ADDR(data, cursor));
 	out_be32(&hw->cursor, DMA_ADDR(data, cursor));
 
 
-	out_be32(&hw->bgnd, 0x007F7F7F); 	/* BGND */
-	out_be32(&hw->bgnd_wb, 0); 		/* BGND_WB */
-	out_be32(&hw->disp_size, (var->yres << 16 | var->xres));
-						/* DISP SIZE */
-	out_be32(&hw->wb_size, 0); /* WB SIZE */
-	out_be32(&hw->wb_mem_addr, 0); /* WB MEM ADDR */
+	out_be32(&hw->bgnd, 0x007F7F7F); /* Set background to grey */
+	out_be32(&hw->disp_size, (var->yres << 16) | var->xres);
 
 
 	/* Horizontal and vertical configuration register */
 	/* Horizontal and vertical configuration register */
 	temp = var->left_margin << 22 | /* BP_H */
 	temp = var->left_margin << 22 | /* BP_H */
@@ -833,9 +844,20 @@ static void update_lcdc(struct fb_info *info)
 
 
 	diu_ops.set_pixel_clock(var->pixclock);
 	diu_ops.set_pixel_clock(var->pixclock);
 
 
-	out_be32(&hw->syn_pol, 0);	/* SYNC SIGNALS POLARITY */
-	out_be32(&hw->int_status, 0);	/* INTERRUPT STATUS */
+#ifndef CONFIG_PPC_MPC512x
+	/*
+	 * The PLUT register is defined differently on the MPC5121 than it
+	 * is on other SOCs.  Unfortunately, there's no documentation that
+	 * explains how it's supposed to be programmed, so for now, we leave
+	 * it at the default value on the MPC5121.
+	 *
+	 * For other SOCs, program it for the highest priority, which will
+	 * reduce the chance of underrun. Technically, we should scale the
+	 * priority to match the screen resolution, but doing that properly
+	 * requires delicate fine-tuning for each use-case.
+	 */
 	out_be32(&hw->plut, 0x01F5F666);
 	out_be32(&hw->plut, 0x01F5F666);
+#endif
 
 
 	/* Enable the DIU */
 	/* Enable the DIU */
 	enable_lcdc(info);
 	enable_lcdc(info);
@@ -965,7 +987,6 @@ static int fsl_diu_set_par(struct fb_info *info)
 	hw = data->diu_reg;
 	hw = data->diu_reg;
 
 
 	set_fix(info);
 	set_fix(info);
-	mfbi->cursor_reset = 1;
 
 
 	len = info->var.yres_virtual * info->fix.line_length;
 	len = info->var.yres_virtual * info->fix.line_length;
 	/* Alloc & dealloc each time resolution/bpp change */
 	/* Alloc & dealloc each time resolution/bpp change */
@@ -1107,6 +1128,12 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
 
 
 	if (!arg)
 	if (!arg)
 		return -EINVAL;
 		return -EINVAL;
+
+	dev_dbg(info->dev, "ioctl %08x (dir=%s%s type=%u nr=%u size=%u)\n", cmd,
+		_IOC_DIR(cmd) & _IOC_READ ? "R" : "",
+		_IOC_DIR(cmd) & _IOC_WRITE ? "W" : "",
+		_IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
+
 	switch (cmd) {
 	switch (cmd) {
 	case MFB_SET_PIXFMT_OLD:
 	case MFB_SET_PIXFMT_OLD:
 		dev_warn(info->dev,
 		dev_warn(info->dev,
@@ -1180,6 +1207,23 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
 			ad->ckmin_b = ck.blue_min;
 			ad->ckmin_b = ck.blue_min;
 		}
 		}
 		break;
 		break;
+#ifdef CONFIG_PPC_MPC512x
+	case MFB_SET_GAMMA: {
+		struct fsl_diu_data *data = mfbi->parent;
+
+		if (copy_from_user(data->gamma, buf, sizeof(data->gamma)))
+			return -EFAULT;
+		setbits32(&data->diu_reg->gamma, 0); /* Force table reload */
+		break;
+	}
+	case MFB_GET_GAMMA: {
+		struct fsl_diu_data *data = mfbi->parent;
+
+		if (copy_to_user(buf, data->gamma, sizeof(data->gamma)))
+			return -EFAULT;
+		break;
+	}
+#endif
 	default:
 	default:
 		dev_err(info->dev, "unknown ioctl command (0x%08X)\n", cmd);
 		dev_err(info->dev, "unknown ioctl command (0x%08X)\n", cmd);
 		return -ENOIOCTLCMD;
 		return -ENOIOCTLCMD;
@@ -1206,8 +1250,22 @@ static int fsl_diu_open(struct fb_info *info, int user)
 		res = fsl_diu_set_par(info);
 		res = fsl_diu_set_par(info);
 		if (res < 0)
 		if (res < 0)
 			mfbi->count--;
 			mfbi->count--;
-		else
+		else {
+			struct fsl_diu_data *data = mfbi->parent;
+
+#ifdef CONFIG_NOT_COHERENT_CACHE
+			/*
+			 * Enable underrun detection and vertical sync
+			 * interrupts.
+			 */
+			clrbits32(&data->diu_reg->int_mask,
+				  INT_UNDRUN | INT_VSYNC);
+#else
+			/* Enable underrun detection */
+			clrbits32(&data->diu_reg->int_mask, INT_UNDRUN);
+#endif
 			fsl_diu_enable_panel(info);
 			fsl_diu_enable_panel(info);
+		}
 	}
 	}
 
 
 	spin_unlock(&diu_lock);
 	spin_unlock(&diu_lock);
@@ -1223,8 +1281,13 @@ static int fsl_diu_release(struct fb_info *info, int user)
 
 
 	spin_lock(&diu_lock);
 	spin_lock(&diu_lock);
 	mfbi->count--;
 	mfbi->count--;
-	if (mfbi->count == 0)
+	if (mfbi->count == 0) {
+		struct fsl_diu_data *data = mfbi->parent;
+
+		/* Disable interrupts */
+		out_be32(&data->diu_reg->int_mask, 0xffffffff);
 		fsl_diu_disable_panel(info);
 		fsl_diu_disable_panel(info);
+	}
 
 
 	spin_unlock(&diu_lock);
 	spin_unlock(&diu_lock);
 	return res;
 	return res;
@@ -1248,6 +1311,7 @@ static int __devinit install_fb(struct fb_info *info)
 {
 {
 	int rc;
 	int rc;
 	struct mfb_info *mfbi = info->par;
 	struct mfb_info *mfbi = info->par;
+	struct fsl_diu_data *data = mfbi->parent;
 	const char *aoi_mode, *init_aoi_mode = "320x240";
 	const char *aoi_mode, *init_aoi_mode = "320x240";
 	struct fb_videomode *db = fsl_diu_mode_db;
 	struct fb_videomode *db = fsl_diu_mode_db;
 	unsigned int dbsize = ARRAY_SIZE(fsl_diu_mode_db);
 	unsigned int dbsize = ARRAY_SIZE(fsl_diu_mode_db);
@@ -1264,9 +1328,9 @@ static int __devinit install_fb(struct fb_info *info)
 		return rc;
 		return rc;
 
 
 	if (mfbi->index == PLANE0) {
 	if (mfbi->index == PLANE0) {
-		if (mfbi->edid_data) {
+		if (data->has_edid) {
 			/* Now build modedb from EDID */
 			/* Now build modedb from EDID */
-			fb_edid_to_monspecs(mfbi->edid_data, &info->monspecs);
+			fb_edid_to_monspecs(data->edid_data, &info->monspecs);
 			fb_videomode_to_modelist(info->monspecs.modedb,
 			fb_videomode_to_modelist(info->monspecs.modedb,
 						 info->monspecs.modedb_len,
 						 info->monspecs.modedb_len,
 						 &info->modelist);
 						 &info->modelist);
@@ -1284,7 +1348,7 @@ static int __devinit install_fb(struct fb_info *info)
 		 * For plane 0 we continue and look into
 		 * For plane 0 we continue and look into
 		 * driver's internal modedb.
 		 * driver's internal modedb.
 		 */
 		 */
-		if ((mfbi->index == PLANE0) && mfbi->edid_data)
+		if ((mfbi->index == PLANE0) && data->has_edid)
 			has_default_mode = 0;
 			has_default_mode = 0;
 		else
 		else
 			return -EINVAL;
 			return -EINVAL;
@@ -1348,9 +1412,6 @@ static void uninstall_fb(struct fb_info *info)
 	if (!mfbi->registered)
 	if (!mfbi->registered)
 		return;
 		return;
 
 
-	if (mfbi->index == PLANE0)
-		kfree(mfbi->edid_data);
-
 	unregister_framebuffer(info);
 	unregister_framebuffer(info);
 	unmap_video_memory(info);
 	unmap_video_memory(info);
 	if (&info->cmap)
 	if (&info->cmap)
@@ -1362,7 +1423,7 @@ static void uninstall_fb(struct fb_info *info)
 static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
 static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
 {
 {
 	struct diu __iomem *hw = dev_id;
 	struct diu __iomem *hw = dev_id;
-	unsigned int status = in_be32(&hw->int_status);
+	uint32_t status = in_be32(&hw->int_status);
 
 
 	if (status) {
 	if (status) {
 		/* This is the workaround for underrun */
 		/* This is the workaround for underrun */
@@ -1387,40 +1448,6 @@ static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
 	return IRQ_NONE;
 	return IRQ_NONE;
 }
 }
 
 
-static int request_irq_local(struct fsl_diu_data *data)
-{
-	struct diu __iomem *hw = data->diu_reg;
-	u32 ints;
-	int ret;
-
-	/* Read to clear the status */
-	in_be32(&hw->int_status);
-
-	ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb", hw);
-	if (!ret) {
-		ints = INT_PARERR | INT_LS_BF_VS;
-#if !defined(CONFIG_NOT_COHERENT_CACHE)
-		ints |=	INT_VSYNC;
-#endif
-
-		/* Read to clear the status */
-		in_be32(&hw->int_status);
-		out_be32(&hw->int_mask, ints);
-	}
-
-	return ret;
-}
-
-static void free_irq_local(struct fsl_diu_data *data)
-{
-	struct diu __iomem *hw = data->diu_reg;
-
-	/* Disable all LCDC interrupt */
-	out_be32(&hw->int_mask, 0x1f);
-
-	free_irq(data->irq, NULL);
-}
-
 #ifdef CONFIG_PM
 #ifdef CONFIG_PM
 /*
 /*
  * Power management hooks. Note that we won't be called from IRQ context,
  * Power management hooks. Note that we won't be called from IRQ context,
@@ -1496,8 +1523,8 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
 	struct device_node *np = pdev->dev.of_node;
 	struct device_node *np = pdev->dev.of_node;
 	struct mfb_info *mfbi;
 	struct mfb_info *mfbi;
 	struct fsl_diu_data *data;
 	struct fsl_diu_data *data;
-	int diu_mode;
 	dma_addr_t dma_addr; /* DMA addr of fsl_diu_data struct */
 	dma_addr_t dma_addr; /* DMA addr of fsl_diu_data struct */
+	const void *prop;
 	unsigned int i;
 	unsigned int i;
 	int ret;
 	int ret;
 
 
@@ -1541,17 +1568,13 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
 		memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info));
 		memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info));
 		mfbi->parent = data;
 		mfbi->parent = data;
 		mfbi->ad = &data->ad[i];
 		mfbi->ad = &data->ad[i];
+	}
 
 
-		if (mfbi->index == PLANE0) {
-			const u8 *prop;
-			int len;
-
-			/* Get EDID */
-			prop = of_get_property(np, "edid", &len);
-			if (prop && len == EDID_LENGTH)
-				mfbi->edid_data = kmemdup(prop, EDID_LENGTH,
-							  GFP_KERNEL);
-		}
+	/* Get the EDID data from the device tree, if present */
+	prop = of_get_property(np, "edid", &ret);
+	if (prop && ret == EDID_LENGTH) {
+		memcpy(data->edid_data, prop, EDID_LENGTH);
+		data->has_edid = true;
 	}
 	}
 
 
 	data->diu_reg = of_iomap(np, 0);
 	data->diu_reg = of_iomap(np, 0);
@@ -1561,10 +1584,6 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
 		goto error;
 		goto error;
 	}
 	}
 
 
-	diu_mode = in_be32(&data->diu_reg->diu_mode);
-	if (diu_mode == MFB_MODE0)
-		out_be32(&data->diu_reg->diu_mode, 0); /* disable DIU */
-
 	/* Get the IRQ of the DIU */
 	/* Get the IRQ of the DIU */
 	data->irq = irq_of_parse_and_map(np, 0);
 	data->irq = irq_of_parse_and_map(np, 0);
 
 
@@ -1586,11 +1605,11 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
 	data->dummy_ad.paddr = DMA_ADDR(data, dummy_ad);
 	data->dummy_ad.paddr = DMA_ADDR(data, dummy_ad);
 
 
 	/*
 	/*
-	 * Let DIU display splash screen if it was pre-initialized
-	 * by the bootloader, set dummy area descriptor otherwise.
+	 * Let DIU continue to display splash screen if it was pre-initialized
+	 * by the bootloader; otherwise, clear the display.
 	 */
 	 */
-	if (diu_mode == MFB_MODE0)
-		out_be32(&data->diu_reg->desc[0], data->dummy_ad.paddr);
+	if (in_be32(&data->diu_reg->diu_mode) == MFB_MODE0)
+		out_be32(&data->diu_reg->desc[0], 0);
 
 
 	out_be32(&data->diu_reg->desc[1], data->dummy_ad.paddr);
 	out_be32(&data->diu_reg->desc[1], data->dummy_ad.paddr);
 	out_be32(&data->diu_reg->desc[2], data->dummy_ad.paddr);
 	out_be32(&data->diu_reg->desc[2], data->dummy_ad.paddr);
@@ -1603,7 +1622,16 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
 		}
 		}
 	}
 	}
 
 
-	if (request_irq_local(data)) {
+	/*
+	 * Older versions of U-Boot leave interrupts enabled, so disable
+	 * all of them and clear the status register.
+	 */
+	out_be32(&data->diu_reg->int_mask, 0xffffffff);
+	in_be32(&data->diu_reg->int_status);
+
+	ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb",
+			  &data->diu_reg);
+	if (ret) {
 		dev_err(&pdev->dev, "could not claim irq\n");
 		dev_err(&pdev->dev, "could not claim irq\n");
 		goto error;
 		goto error;
 	}
 	}
@@ -1638,7 +1666,8 @@ static int fsl_diu_remove(struct platform_device *pdev)
 
 
 	data = dev_get_drvdata(&pdev->dev);
 	data = dev_get_drvdata(&pdev->dev);
 	disable_lcdc(&data->fsl_diu_info[0]);
 	disable_lcdc(&data->fsl_diu_info[0]);
-	free_irq_local(data);
+
+	free_irq(data->irq, &data->diu_reg);
 
 
 	for (i = 0; i < NUM_AOIS; i++)
 	for (i = 0; i < NUM_AOIS; i++)
 		uninstall_fb(&data->fsl_diu_info[i]);
 		uninstall_fb(&data->fsl_diu_info[i]);
@@ -1741,6 +1770,9 @@ static int __init fsl_diu_init(void)
 	coherence_data_size = be32_to_cpup(prop) * 13;
 	coherence_data_size = be32_to_cpup(prop) * 13;
 	coherence_data_size /= 8;
 	coherence_data_size /= 8;
 
 
+	pr_debug("fsl-diu-fb: coherence data size is %zu bytes\n",
+		 coherence_data_size);
+
 	prop = of_get_property(np, "d-cache-line-size", NULL);
 	prop = of_get_property(np, "d-cache-line-size", NULL);
 	if (prop == NULL) {
 	if (prop == NULL) {
 		pr_err("fsl-diu-fb: missing 'd-cache-line-size' property' "
 		pr_err("fsl-diu-fb: missing 'd-cache-line-size' property' "
@@ -1750,10 +1782,17 @@ static int __init fsl_diu_init(void)
 	}
 	}
 	d_cache_line_size = be32_to_cpup(prop);
 	d_cache_line_size = be32_to_cpup(prop);
 
 
+	pr_debug("fsl-diu-fb: cache lines size is %u bytes\n",
+		 d_cache_line_size);
+
 	of_node_put(np);
 	of_node_put(np);
 	coherence_data = vmalloc(coherence_data_size);
 	coherence_data = vmalloc(coherence_data_size);
-	if (!coherence_data)
+	if (!coherence_data) {
+		pr_err("fsl-diu-fb: could not allocate coherence data "
+		       "(size=%zu)\n", coherence_data_size);
 		return -ENOMEM;
 		return -ENOMEM;
+	}
+
 #endif
 #endif
 
 
 	ret = platform_driver_register(&fsl_diu_driver);
 	ret = platform_driver_register(&fsl_diu_driver);

+ 0 - 3
drivers/video/omap2/Kconfig

@@ -1,6 +1,3 @@
-config OMAP2_VRAM
-	bool
-
 config OMAP2_VRFB
 config OMAP2_VRFB
 	bool
 	bool
 
 

+ 0 - 1
drivers/video/omap2/Makefile

@@ -1,4 +1,3 @@
-obj-$(CONFIG_OMAP2_VRAM) += vram.o
 obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
 obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
 
 
 obj-$(CONFIG_OMAP2_DSS) += dss/
 obj-$(CONFIG_OMAP2_DSS) += dss/

+ 0 - 23
drivers/video/omap2/displays/panel-acx565akm.c

@@ -710,27 +710,6 @@ static void acx_panel_disable(struct omap_dss_device *dssdev)
 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 }
 }
 
 
-static int acx_panel_suspend(struct omap_dss_device *dssdev)
-{
-	dev_dbg(&dssdev->dev, "%s\n", __func__);
-	acx_panel_power_off(dssdev);
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-	return 0;
-}
-
-static int acx_panel_resume(struct omap_dss_device *dssdev)
-{
-	int r;
-
-	dev_dbg(&dssdev->dev, "%s\n", __func__);
-	r = acx_panel_power_on(dssdev);
-	if (r)
-		return r;
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-	return 0;
-}
-
 static void acx_panel_set_timings(struct omap_dss_device *dssdev,
 static void acx_panel_set_timings(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings)
 		struct omap_video_timings *timings)
 {
 {
@@ -752,8 +731,6 @@ static struct omap_dss_driver acx_panel_driver = {
 
 
 	.enable		= acx_panel_enable,
 	.enable		= acx_panel_enable,
 	.disable	= acx_panel_disable,
 	.disable	= acx_panel_disable,
-	.suspend	= acx_panel_suspend,
-	.resume		= acx_panel_resume,
 
 
 	.set_timings	= acx_panel_set_timings,
 	.set_timings	= acx_panel_set_timings,
 	.check_timings	= acx_panel_check_timings,
 	.check_timings	= acx_panel_check_timings,

+ 0 - 36
drivers/video/omap2/displays/panel-generic-dpi.c

@@ -688,40 +688,6 @@ static void generic_dpi_panel_disable(struct omap_dss_device *dssdev)
 	mutex_unlock(&drv_data->lock);
 	mutex_unlock(&drv_data->lock);
 }
 }
 
 
-static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
-
-	mutex_lock(&drv_data->lock);
-
-	generic_dpi_panel_power_off(dssdev);
-
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-	mutex_unlock(&drv_data->lock);
-
-	return 0;
-}
-
-static int generic_dpi_panel_resume(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
-	int r;
-
-	mutex_lock(&drv_data->lock);
-
-	r = generic_dpi_panel_power_on(dssdev);
-	if (r)
-		goto err;
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-err:
-	mutex_unlock(&drv_data->lock);
-
-	return r;
-}
-
 static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
 static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings)
 		struct omap_video_timings *timings)
 {
 {
@@ -769,8 +735,6 @@ static struct omap_dss_driver dpi_driver = {
 
 
 	.enable		= generic_dpi_panel_enable,
 	.enable		= generic_dpi_panel_enable,
 	.disable	= generic_dpi_panel_disable,
 	.disable	= generic_dpi_panel_disable,
-	.suspend	= generic_dpi_panel_suspend,
-	.resume		= generic_dpi_panel_resume,
 
 
 	.set_timings	= generic_dpi_panel_set_timings,
 	.set_timings	= generic_dpi_panel_set_timings,
 	.get_timings	= generic_dpi_panel_get_timings,
 	.get_timings	= generic_dpi_panel_get_timings,

+ 0 - 34
drivers/video/omap2/displays/panel-lgphilips-lb035q02.c

@@ -143,46 +143,12 @@ static void lb035q02_panel_disable(struct omap_dss_device *dssdev)
 	mutex_unlock(&ld->lock);
 	mutex_unlock(&ld->lock);
 }
 }
 
 
-static int lb035q02_panel_suspend(struct omap_dss_device *dssdev)
-{
-	struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
-
-	mutex_lock(&ld->lock);
-
-	lb035q02_panel_power_off(dssdev);
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-	mutex_unlock(&ld->lock);
-	return 0;
-}
-
-static int lb035q02_panel_resume(struct omap_dss_device *dssdev)
-{
-	struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
-	int r;
-
-	mutex_lock(&ld->lock);
-
-	r = lb035q02_panel_power_on(dssdev);
-	if (r)
-		goto err;
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-	mutex_unlock(&ld->lock);
-	return 0;
-err:
-	mutex_unlock(&ld->lock);
-	return r;
-}
-
 static struct omap_dss_driver lb035q02_driver = {
 static struct omap_dss_driver lb035q02_driver = {
 	.probe		= lb035q02_panel_probe,
 	.probe		= lb035q02_panel_probe,
 	.remove		= lb035q02_panel_remove,
 	.remove		= lb035q02_panel_remove,
 
 
 	.enable		= lb035q02_panel_enable,
 	.enable		= lb035q02_panel_enable,
 	.disable	= lb035q02_panel_disable,
 	.disable	= lb035q02_panel_disable,
-	.suspend	= lb035q02_panel_suspend,
-	.resume		= lb035q02_panel_resume,
 
 
 	.driver         = {
 	.driver         = {
 		.name   = "lgphilips_lb035q02_panel",
 		.name   = "lgphilips_lb035q02_panel",

+ 9 - 80
drivers/video/omap2/displays/panel-n8x0.c

@@ -574,54 +574,6 @@ static void n8x0_panel_disable(struct omap_dss_device *dssdev)
 	mutex_unlock(&ddata->lock);
 	mutex_unlock(&ddata->lock);
 }
 }
 
 
-static int n8x0_panel_suspend(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = get_drv_data(dssdev);
-
-	dev_dbg(&dssdev->dev, "suspend\n");
-
-	mutex_lock(&ddata->lock);
-
-	rfbi_bus_lock();
-
-	n8x0_panel_power_off(dssdev);
-
-	rfbi_bus_unlock();
-
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-	mutex_unlock(&ddata->lock);
-
-	return 0;
-}
-
-static int n8x0_panel_resume(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = get_drv_data(dssdev);
-	int r;
-
-	dev_dbg(&dssdev->dev, "resume\n");
-
-	mutex_lock(&ddata->lock);
-
-	rfbi_bus_lock();
-
-	r = n8x0_panel_power_on(dssdev);
-
-	rfbi_bus_unlock();
-
-	if (r) {
-		mutex_unlock(&ddata->lock);
-		return r;
-	}
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-	mutex_unlock(&ddata->lock);
-
-	return 0;
-}
-
 static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
 static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
 		u16 *xres, u16 *yres)
 		u16 *xres, u16 *yres)
 {
 {
@@ -683,8 +635,6 @@ static struct omap_dss_driver n8x0_panel_driver = {
 
 
 	.enable		= n8x0_panel_enable,
 	.enable		= n8x0_panel_enable,
 	.disable	= n8x0_panel_disable,
 	.disable	= n8x0_panel_disable,
-	.suspend	= n8x0_panel_suspend,
-	.resume		= n8x0_panel_resume,
 
 
 	.update		= n8x0_panel_update,
 	.update		= n8x0_panel_update,
 	.sync		= n8x0_panel_sync,
 	.sync		= n8x0_panel_sync,
@@ -702,18 +652,25 @@ static struct omap_dss_driver n8x0_panel_driver = {
 
 
 static int mipid_spi_probe(struct spi_device *spi)
 static int mipid_spi_probe(struct spi_device *spi)
 {
 {
+	int r;
+
 	dev_dbg(&spi->dev, "mipid_spi_probe\n");
 	dev_dbg(&spi->dev, "mipid_spi_probe\n");
 
 
 	spi->mode = SPI_MODE_0;
 	spi->mode = SPI_MODE_0;
 
 
 	s_drv_data.spidev = spi;
 	s_drv_data.spidev = spi;
 
 
-	return 0;
+	r = omap_dss_register_driver(&n8x0_panel_driver);
+	if (r)
+		pr_err("n8x0_panel: dss driver registration failed\n");
+
+	return r;
 }
 }
 
 
 static int mipid_spi_remove(struct spi_device *spi)
 static int mipid_spi_remove(struct spi_device *spi)
 {
 {
 	dev_dbg(&spi->dev, "mipid_spi_remove\n");
 	dev_dbg(&spi->dev, "mipid_spi_remove\n");
+	omap_dss_unregister_driver(&n8x0_panel_driver);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -725,34 +682,6 @@ static struct spi_driver mipid_spi_driver = {
 	.probe	= mipid_spi_probe,
 	.probe	= mipid_spi_probe,
 	.remove	= __devexit_p(mipid_spi_remove),
 	.remove	= __devexit_p(mipid_spi_remove),
 };
 };
+module_spi_driver(mipid_spi_driver);
 
 
-static int __init n8x0_panel_drv_init(void)
-{
-	int r;
-
-	r = spi_register_driver(&mipid_spi_driver);
-	if (r) {
-		pr_err("n8x0_panel: spi driver registration failed\n");
-		return r;
-	}
-
-	r = omap_dss_register_driver(&n8x0_panel_driver);
-	if (r) {
-		pr_err("n8x0_panel: dss driver registration failed\n");
-		spi_unregister_driver(&mipid_spi_driver);
-		return r;
-	}
-
-	return 0;
-}
-
-static void __exit n8x0_panel_drv_exit(void)
-{
-	spi_unregister_driver(&mipid_spi_driver);
-
-	omap_dss_unregister_driver(&n8x0_panel_driver);
-}
-
-module_init(n8x0_panel_drv_init);
-module_exit(n8x0_panel_drv_exit);
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");

+ 0 - 24
drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c

@@ -236,28 +236,6 @@ static void nec_8048_panel_disable(struct omap_dss_device *dssdev)
 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 }
 }
 
 
-static int nec_8048_panel_suspend(struct omap_dss_device *dssdev)
-{
-	nec_8048_panel_power_off(dssdev);
-
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-	return 0;
-}
-
-static int nec_8048_panel_resume(struct omap_dss_device *dssdev)
-{
-	int r;
-
-	r = nec_8048_panel_power_on(dssdev);
-	if (r)
-		return r;
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-	return 0;
-}
-
 static int nec_8048_recommended_bpp(struct omap_dss_device *dssdev)
 static int nec_8048_recommended_bpp(struct omap_dss_device *dssdev)
 {
 {
 	return 16;
 	return 16;
@@ -268,8 +246,6 @@ static struct omap_dss_driver nec_8048_driver = {
 	.remove			= nec_8048_panel_remove,
 	.remove			= nec_8048_panel_remove,
 	.enable			= nec_8048_panel_enable,
 	.enable			= nec_8048_panel_enable,
 	.disable		= nec_8048_panel_disable,
 	.disable		= nec_8048_panel_disable,
-	.suspend		= nec_8048_panel_suspend,
-	.resume			= nec_8048_panel_resume,
 	.get_recommended_bpp	= nec_8048_recommended_bpp,
 	.get_recommended_bpp	= nec_8048_recommended_bpp,
 
 
 	.driver		= {
 	.driver		= {

+ 1 - 44
drivers/video/omap2/displays/panel-picodlp.c

@@ -50,6 +50,7 @@ struct picodlp_i2c_data {
 
 
 static struct i2c_device_id picodlp_i2c_id[] = {
 static struct i2c_device_id picodlp_i2c_id[] = {
 	{ "picodlp_i2c_driver", 0 },
 	{ "picodlp_i2c_driver", 0 },
+	{ }
 };
 };
 
 
 struct picodlp_i2c_command {
 struct picodlp_i2c_command {
@@ -503,47 +504,6 @@ static void picodlp_panel_disable(struct omap_dss_device *dssdev)
 	dev_dbg(&dssdev->dev, "disabling picodlp panel\n");
 	dev_dbg(&dssdev->dev, "disabling picodlp panel\n");
 }
 }
 
 
-static int picodlp_panel_suspend(struct omap_dss_device *dssdev)
-{
-	struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
-
-	mutex_lock(&picod->lock);
-	/* Turn off DLP Power */
-	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
-		mutex_unlock(&picod->lock);
-		dev_err(&dssdev->dev, "unable to suspend picodlp panel,"
-					" panel is not ACTIVE\n");
-		return -EINVAL;
-	}
-
-	picodlp_panel_power_off(dssdev);
-
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-	mutex_unlock(&picod->lock);
-
-	dev_dbg(&dssdev->dev, "suspending picodlp panel\n");
-	return 0;
-}
-
-static int picodlp_panel_resume(struct omap_dss_device *dssdev)
-{
-	struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
-	int r;
-
-	mutex_lock(&picod->lock);
-	if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
-		mutex_unlock(&picod->lock);
-		dev_err(&dssdev->dev, "unable to resume picodlp panel,"
-			" panel is not ACTIVE\n");
-		return -EINVAL;
-	}
-
-	r = picodlp_panel_power_on(dssdev);
-	mutex_unlock(&picod->lock);
-	dev_dbg(&dssdev->dev, "resuming picodlp panel\n");
-	return r;
-}
-
 static void picodlp_get_resolution(struct omap_dss_device *dssdev,
 static void picodlp_get_resolution(struct omap_dss_device *dssdev,
 					u16 *xres, u16 *yres)
 					u16 *xres, u16 *yres)
 {
 {
@@ -560,9 +520,6 @@ static struct omap_dss_driver picodlp_driver = {
 
 
 	.get_resolution	= picodlp_get_resolution,
 	.get_resolution	= picodlp_get_resolution,
 
 
-	.suspend	= picodlp_panel_suspend,
-	.resume		= picodlp_panel_resume,
-
 	.driver		= {
 	.driver		= {
 		.name	= "picodlp_panel",
 		.name	= "picodlp_panel",
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,

+ 0 - 17
drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c

@@ -194,29 +194,12 @@ static void sharp_ls_panel_disable(struct omap_dss_device *dssdev)
 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 }
 }
 
 
-static int sharp_ls_panel_suspend(struct omap_dss_device *dssdev)
-{
-	sharp_ls_power_off(dssdev);
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-	return 0;
-}
-
-static int sharp_ls_panel_resume(struct omap_dss_device *dssdev)
-{
-	int r;
-	r = sharp_ls_power_on(dssdev);
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-	return r;
-}
-
 static struct omap_dss_driver sharp_ls_driver = {
 static struct omap_dss_driver sharp_ls_driver = {
 	.probe		= sharp_ls_panel_probe,
 	.probe		= sharp_ls_panel_probe,
 	.remove		= __exit_p(sharp_ls_panel_remove),
 	.remove		= __exit_p(sharp_ls_panel_remove),
 
 
 	.enable		= sharp_ls_panel_enable,
 	.enable		= sharp_ls_panel_enable,
 	.disable	= sharp_ls_panel_disable,
 	.disable	= sharp_ls_panel_disable,
-	.suspend	= sharp_ls_panel_suspend,
-	.resume		= sharp_ls_panel_resume,
 
 
 	.driver         = {
 	.driver         = {
 		.name   = "sharp_ls_panel",
 		.name   = "sharp_ls_panel",

+ 0 - 72
drivers/video/omap2/displays/panel-taal.c

@@ -1245,76 +1245,6 @@ static void taal_disable(struct omap_dss_device *dssdev)
 	mutex_unlock(&td->lock);
 	mutex_unlock(&td->lock);
 }
 }
 
 
-static int taal_suspend(struct omap_dss_device *dssdev)
-{
-	struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-	int r;
-
-	dev_dbg(&dssdev->dev, "suspend\n");
-
-	mutex_lock(&td->lock);
-
-	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
-		r = -EINVAL;
-		goto err;
-	}
-
-	taal_cancel_ulps_work(dssdev);
-	taal_cancel_esd_work(dssdev);
-
-	dsi_bus_lock(dssdev);
-
-	r = taal_wake_up(dssdev);
-	if (!r)
-		taal_power_off(dssdev);
-
-	dsi_bus_unlock(dssdev);
-
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-	mutex_unlock(&td->lock);
-
-	return 0;
-err:
-	mutex_unlock(&td->lock);
-	return r;
-}
-
-static int taal_resume(struct omap_dss_device *dssdev)
-{
-	struct taal_data *td = dev_get_drvdata(&dssdev->dev);
-	int r;
-
-	dev_dbg(&dssdev->dev, "resume\n");
-
-	mutex_lock(&td->lock);
-
-	if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
-		r = -EINVAL;
-		goto err;
-	}
-
-	dsi_bus_lock(dssdev);
-
-	r = taal_power_on(dssdev);
-
-	dsi_bus_unlock(dssdev);
-
-	if (r) {
-		dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-	} else {
-		dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-		taal_queue_esd_work(dssdev);
-	}
-
-	mutex_unlock(&td->lock);
-
-	return r;
-err:
-	mutex_unlock(&td->lock);
-	return r;
-}
-
 static void taal_framedone_cb(int err, void *data)
 static void taal_framedone_cb(int err, void *data)
 {
 {
 	struct omap_dss_device *dssdev = data;
 	struct omap_dss_device *dssdev = data;
@@ -1818,8 +1748,6 @@ static struct omap_dss_driver taal_driver = {
 
 
 	.enable		= taal_enable,
 	.enable		= taal_enable,
 	.disable	= taal_disable,
 	.disable	= taal_disable,
-	.suspend	= taal_suspend,
-	.resume		= taal_resume,
 
 
 	.update		= taal_update,
 	.update		= taal_update,
 	.sync		= taal_sync,
 	.sync		= taal_sync,

+ 0 - 33
drivers/video/omap2/displays/panel-tfp410.c

@@ -189,37 +189,6 @@ static void tfp410_disable(struct omap_dss_device *dssdev)
 	mutex_unlock(&ddata->lock);
 	mutex_unlock(&ddata->lock);
 }
 }
 
 
-static int tfp410_suspend(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
-
-	mutex_lock(&ddata->lock);
-
-	tfp410_power_off(dssdev);
-
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-	mutex_unlock(&ddata->lock);
-
-	return 0;
-}
-
-static int tfp410_resume(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
-	int r;
-
-	mutex_lock(&ddata->lock);
-
-	r = tfp410_power_on(dssdev);
-	if (r == 0)
-		dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-	mutex_unlock(&ddata->lock);
-
-	return r;
-}
-
 static void tfp410_set_timings(struct omap_dss_device *dssdev,
 static void tfp410_set_timings(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings)
 		struct omap_video_timings *timings)
 {
 {
@@ -355,8 +324,6 @@ static struct omap_dss_driver tfp410_driver = {
 
 
 	.enable		= tfp410_enable,
 	.enable		= tfp410_enable,
 	.disable	= tfp410_disable,
 	.disable	= tfp410_disable,
-	.suspend	= tfp410_suspend,
-	.resume		= tfp410_resume,
 
 
 	.set_timings	= tfp410_set_timings,
 	.set_timings	= tfp410_set_timings,
 	.get_timings	= tfp410_get_timings,
 	.get_timings	= tfp410_get_timings,

+ 0 - 20
drivers/video/omap2/displays/panel-tpo-td043mtea1.c

@@ -401,24 +401,6 @@ static void tpo_td043_disable(struct omap_dss_device *dssdev)
 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 }
 }
 
 
-static int tpo_td043_suspend(struct omap_dss_device *dssdev)
-{
-	dev_dbg(&dssdev->dev, "suspend\n");
-
-	tpo_td043_disable_dss(dssdev);
-
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
-	return 0;
-}
-
-static int tpo_td043_resume(struct omap_dss_device *dssdev)
-{
-	dev_dbg(&dssdev->dev, "resume\n");
-
-	return tpo_td043_enable_dss(dssdev);
-}
-
 static int tpo_td043_probe(struct omap_dss_device *dssdev)
 static int tpo_td043_probe(struct omap_dss_device *dssdev)
 {
 {
 	struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
 	struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
@@ -500,8 +482,6 @@ static struct omap_dss_driver tpo_td043_driver = {
 
 
 	.enable		= tpo_td043_enable,
 	.enable		= tpo_td043_enable,
 	.disable	= tpo_td043_disable,
 	.disable	= tpo_td043_disable,
-	.suspend	= tpo_td043_suspend,
-	.resume		= tpo_td043_resume,
 	.set_mirror	= tpo_td043_set_hmirror,
 	.set_mirror	= tpo_td043_set_hmirror,
 	.get_mirror	= tpo_td043_get_hmirror,
 	.get_mirror	= tpo_td043_get_hmirror,
 
 

+ 14 - 21
drivers/video/omap2/dss/Kconfig

@@ -1,33 +1,30 @@
 menuconfig OMAP2_DSS
 menuconfig OMAP2_DSS
         tristate "OMAP2+ Display Subsystem support"
         tristate "OMAP2+ Display Subsystem support"
-        depends on ARCH_OMAP2PLUS
         help
         help
 	  OMAP2+ Display Subsystem support.
 	  OMAP2+ Display Subsystem support.
 
 
 if OMAP2_DSS
 if OMAP2_DSS
 
 
-config OMAP2_VRAM_SIZE
-	int "VRAM size (MB)"
-	range 0 32
-	default 0
+config OMAP2_DSS_DEBUG
+	bool "Debug support"
+	default n
 	help
 	help
-	  The amount of SDRAM to reserve at boot time for video RAM use.
-	  This VRAM will be used by omapfb and other drivers that need
-	  large continuous RAM area for video use.
+	  This enables printing of debug messages. Alternatively, debug messages
+	  can also be enabled by setting CONFIG_DYNAMIC_DEBUG and then setting
+	  appropriate flags in <debugfs>/dynamic_debug/control.
 
 
-	  You can also set this with "vram=<bytes>" kernel argument, or
-	  in the board file.
-
-config OMAP2_DSS_DEBUG_SUPPORT
-        bool "Debug support"
-	default y
+config OMAP2_DSS_DEBUGFS
+	bool "Debugfs filesystem support"
+	depends on DEBUG_FS
+	default n
 	help
 	help
-	  This enables debug messages. You need to enable printing
-	  with 'debug' module parameter.
+	  This enables debugfs for OMAPDSS at <debugfs>/omapdss. This enables
+	  querying about clock configuration and register configuration of dss,
+	  dispc, dsi, hdmi and rfbi.
 
 
 config OMAP2_DSS_COLLECT_IRQ_STATS
 config OMAP2_DSS_COLLECT_IRQ_STATS
 	bool "Collect DSS IRQ statistics"
 	bool "Collect DSS IRQ statistics"
-	depends on OMAP2_DSS_DEBUG_SUPPORT
+	depends on OMAP2_DSS_DEBUGFS
 	default n
 	default n
 	help
 	help
 	  Collect DSS IRQ statistics, printable via debugfs.
 	  Collect DSS IRQ statistics, printable via debugfs.
@@ -62,7 +59,6 @@ config OMAP2_DSS_VENC
 
 
 config OMAP4_DSS_HDMI
 config OMAP4_DSS_HDMI
 	bool "HDMI support"
 	bool "HDMI support"
-	depends on ARCH_OMAP4
         default y
         default y
 	help
 	help
 	  HDMI Interface. This adds the High Definition Multimedia Interface.
 	  HDMI Interface. This adds the High Definition Multimedia Interface.
@@ -70,11 +66,9 @@ config OMAP4_DSS_HDMI
 
 
 config OMAP4_DSS_HDMI_AUDIO
 config OMAP4_DSS_HDMI_AUDIO
 	bool
 	bool
-	depends on OMAP4_DSS_HDMI
 
 
 config OMAP2_DSS_SDI
 config OMAP2_DSS_SDI
 	bool "SDI support"
 	bool "SDI support"
-	depends on ARCH_OMAP3
         default n
         default n
 	help
 	help
 	  SDI (Serial Display Interface) support.
 	  SDI (Serial Display Interface) support.
@@ -84,7 +78,6 @@ config OMAP2_DSS_SDI
 
 
 config OMAP2_DSS_DSI
 config OMAP2_DSS_DSI
 	bool "DSI support"
 	bool "DSI support"
-	depends on ARCH_OMAP3 || ARCH_OMAP4 || ARCH_OMAP5
         default n
         default n
 	help
 	help
 	  MIPI DSI (Display Serial Interface) support.
 	  MIPI DSI (Display Serial Interface) support.

+ 6 - 1
drivers/video/omap2/dss/Makefile

@@ -1,6 +1,10 @@
 obj-$(CONFIG_OMAP2_DSS) += omapdss.o
 obj-$(CONFIG_OMAP2_DSS) += omapdss.o
+# Core DSS files
 omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
 omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
-	manager.o manager-sysfs.o overlay.o overlay-sysfs.o output.o apply.o
+	output.o
+# DSS compat layer files
+omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \
+	dispc-compat.o display-sysfs.o
 omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
 omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
 omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
 omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
 omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o
 omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o
@@ -8,3 +12,4 @@ omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
 omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
 omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
 omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
 omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
 				    hdmi_panel.o ti_hdmi_4xxx_ip.o
 				    hdmi_panel.o ti_hdmi_4xxx_ip.o
+ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG

+ 264 - 67
drivers/video/omap2/dss/apply.c

@@ -18,6 +18,7 @@
 #define DSS_SUBSYS_NAME "APPLY"
 #define DSS_SUBSYS_NAME "APPLY"
 
 
 #include <linux/kernel.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/spinlock.h>
 #include <linux/jiffies.h>
 #include <linux/jiffies.h>
@@ -26,6 +27,7 @@
 
 
 #include "dss.h"
 #include "dss.h"
 #include "dss_features.h"
 #include "dss_features.h"
+#include "dispc-compat.h"
 
 
 /*
 /*
  * We have 4 levels of cache for the dispc settings. First two are in SW and
  * We have 4 levels of cache for the dispc settings. First two are in SW and
@@ -70,7 +72,6 @@ struct ovl_priv_data {
 	bool shadow_extra_info_dirty;
 	bool shadow_extra_info_dirty;
 
 
 	bool enabled;
 	bool enabled;
-	enum omap_channel channel;
 	u32 fifo_low, fifo_high;
 	u32 fifo_low, fifo_high;
 
 
 	/*
 	/*
@@ -105,6 +106,9 @@ struct mgr_priv_data {
 
 
 	struct omap_video_timings timings;
 	struct omap_video_timings timings;
 	struct dss_lcd_mgr_config lcd_config;
 	struct dss_lcd_mgr_config lcd_config;
+
+	void (*framedone_handler)(void *);
+	void *framedone_handler_data;
 };
 };
 
 
 static struct {
 static struct {
@@ -132,7 +136,7 @@ static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr)
 	return &dss_data.mgr_priv_data_array[mgr->id];
 	return &dss_data.mgr_priv_data_array[mgr->id];
 }
 }
 
 
-void dss_apply_init(void)
+static void apply_init_priv(void)
 {
 {
 	const int num_ovls = dss_feat_get_num_ovls();
 	const int num_ovls = dss_feat_get_num_ovls();
 	struct mgr_priv_data *mp;
 	struct mgr_priv_data *mp;
@@ -414,11 +418,46 @@ static void wait_pending_extra_info_updates(void)
 	r = wait_for_completion_timeout(&extra_updated_completion, t);
 	r = wait_for_completion_timeout(&extra_updated_completion, t);
 	if (r == 0)
 	if (r == 0)
 		DSSWARN("timeout in wait_pending_extra_info_updates\n");
 		DSSWARN("timeout in wait_pending_extra_info_updates\n");
-	else if (r < 0)
-		DSSERR("wait_pending_extra_info_updates failed: %d\n", r);
 }
 }
 
 
-int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
+static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
+{
+	return ovl->manager ?
+		(ovl->manager->output ? ovl->manager->output->device : NULL) :
+		NULL;
+}
+
+static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
+{
+	return mgr->output ? mgr->output->device : NULL;
+}
+
+static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
+{
+	unsigned long timeout = msecs_to_jiffies(500);
+	struct omap_dss_device *dssdev = mgr->get_device(mgr);
+	u32 irq;
+	int r;
+
+	r = dispc_runtime_get();
+	if (r)
+		return r;
+
+	if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
+		irq = DISPC_IRQ_EVSYNC_ODD;
+	else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)
+		irq = DISPC_IRQ_EVSYNC_EVEN;
+	else
+		irq = dispc_mgr_get_vsync_irq(mgr->id);
+
+	r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
+
+	dispc_runtime_put();
+
+	return r;
+}
+
+static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
 {
 {
 	unsigned long timeout = msecs_to_jiffies(500);
 	unsigned long timeout = msecs_to_jiffies(500);
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -488,7 +527,7 @@ int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
 	return r;
 	return r;
 }
 }
 
 
-int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
+static int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
 {
 {
 	unsigned long timeout = msecs_to_jiffies(500);
 	unsigned long timeout = msecs_to_jiffies(500);
 	struct ovl_priv_data *op;
 	struct ovl_priv_data *op;
@@ -573,7 +612,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
 	struct mgr_priv_data *mp;
 	struct mgr_priv_data *mp;
 	int r;
 	int r;
 
 
-	DSSDBGF("%d", ovl->id);
+	DSSDBG("writing ovl %d regs", ovl->id);
 
 
 	if (!op->enabled || !op->info_dirty)
 	if (!op->enabled || !op->info_dirty)
 		return;
 		return;
@@ -608,7 +647,7 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
 	struct ovl_priv_data *op = get_ovl_priv(ovl);
 	struct ovl_priv_data *op = get_ovl_priv(ovl);
 	struct mgr_priv_data *mp;
 	struct mgr_priv_data *mp;
 
 
-	DSSDBGF("%d", ovl->id);
+	DSSDBG("writing ovl %d regs extra", ovl->id);
 
 
 	if (!op->extra_info_dirty)
 	if (!op->extra_info_dirty)
 		return;
 		return;
@@ -617,7 +656,6 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
 	 * disabled */
 	 * disabled */
 
 
 	dispc_ovl_enable(ovl->id, op->enabled);
 	dispc_ovl_enable(ovl->id, op->enabled);
-	dispc_ovl_set_channel_out(ovl->id, op->channel);
 	dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
 	dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
 
 
 	mp = get_mgr_priv(ovl->manager);
 	mp = get_mgr_priv(ovl->manager);
@@ -632,7 +670,7 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 	struct omap_overlay *ovl;
 	struct omap_overlay *ovl;
 
 
-	DSSDBGF("%d", mgr->id);
+	DSSDBG("writing mgr %d regs", mgr->id);
 
 
 	if (!mp->enabled)
 	if (!mp->enabled)
 		return;
 		return;
@@ -658,7 +696,7 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
 {
 {
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 
 
-	DSSDBGF("%d", mgr->id);
+	DSSDBG("writing mgr %d regs extra", mgr->id);
 
 
 	if (!mp->extra_info_dirty)
 	if (!mp->extra_info_dirty)
 		return;
 		return;
@@ -666,22 +704,8 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
 	dispc_mgr_set_timings(mgr->id, &mp->timings);
 	dispc_mgr_set_timings(mgr->id, &mp->timings);
 
 
 	/* lcd_config parameters */
 	/* lcd_config parameters */
-	if (dss_mgr_is_lcd(mgr->id)) {
-		dispc_mgr_set_io_pad_mode(mp->lcd_config.io_pad_mode);
-
-		dispc_mgr_enable_stallmode(mgr->id, mp->lcd_config.stallmode);
-		dispc_mgr_enable_fifohandcheck(mgr->id,
-			mp->lcd_config.fifohandcheck);
-
-		dispc_mgr_set_clock_div(mgr->id, &mp->lcd_config.clock_info);
-
-		dispc_mgr_set_tft_data_lines(mgr->id,
-			mp->lcd_config.video_port_width);
-
-		dispc_lcd_enable_signal_polarity(mp->lcd_config.lcden_sig_polarity);
-
-		dispc_mgr_set_lcd_type_tft(mgr->id);
-	}
+	if (dss_mgr_is_lcd(mgr->id))
+		dispc_mgr_set_lcd_config(mgr->id, &mp->lcd_config);
 
 
 	mp->extra_info_dirty = false;
 	mp->extra_info_dirty = false;
 	if (mp->updating)
 	if (mp->updating)
@@ -761,7 +785,7 @@ static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
 	}
 	}
 }
 }
 
 
-void dss_mgr_start_update(struct omap_overlay_manager *mgr)
+static void dss_mgr_start_update_compat(struct omap_overlay_manager *mgr)
 {
 {
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 	unsigned long flags;
 	unsigned long flags;
@@ -786,9 +810,7 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
 	if (!dss_data.irq_enabled && need_isr())
 	if (!dss_data.irq_enabled && need_isr())
 		dss_register_vsync_isr();
 		dss_register_vsync_isr();
 
 
-	dispc_mgr_enable(mgr->id, true);
-
-	mgr_clear_shadow_dirty(mgr);
+	dispc_mgr_enable_sync(mgr->id);
 
 
 	spin_unlock_irqrestore(&data_lock, flags);
 	spin_unlock_irqrestore(&data_lock, flags);
 }
 }
@@ -845,7 +867,6 @@ static void dss_apply_irq_handler(void *data, u32 mask)
 	for (i = 0; i < num_mgrs; i++) {
 	for (i = 0; i < num_mgrs; i++) {
 		struct omap_overlay_manager *mgr;
 		struct omap_overlay_manager *mgr;
 		struct mgr_priv_data *mp;
 		struct mgr_priv_data *mp;
-		bool was_updating;
 
 
 		mgr = omap_dss_get_overlay_manager(i);
 		mgr = omap_dss_get_overlay_manager(i);
 		mp = get_mgr_priv(mgr);
 		mp = get_mgr_priv(mgr);
@@ -853,7 +874,6 @@ static void dss_apply_irq_handler(void *data, u32 mask)
 		if (!mp->enabled)
 		if (!mp->enabled)
 			continue;
 			continue;
 
 
-		was_updating = mp->updating;
 		mp->updating = dispc_mgr_is_enabled(i);
 		mp->updating = dispc_mgr_is_enabled(i);
 
 
 		if (!mgr_manual_update(mgr)) {
 		if (!mgr_manual_update(mgr)) {
@@ -872,6 +892,21 @@ static void dss_apply_irq_handler(void *data, u32 mask)
 	if (!extra_updating)
 	if (!extra_updating)
 		complete_all(&extra_updated_completion);
 		complete_all(&extra_updated_completion);
 
 
+	/* call framedone handlers for manual update displays */
+	for (i = 0; i < num_mgrs; i++) {
+		struct omap_overlay_manager *mgr;
+		struct mgr_priv_data *mp;
+
+		mgr = omap_dss_get_overlay_manager(i);
+		mp = get_mgr_priv(mgr);
+
+		if (!mgr_manual_update(mgr) || !mp->framedone_handler)
+			continue;
+
+		if (mask & dispc_mgr_get_framedone_irq(i))
+			mp->framedone_handler(mp->framedone_handler_data);
+	}
+
 	if (!need_isr())
 	if (!need_isr())
 		dss_unregister_vsync_isr();
 		dss_unregister_vsync_isr();
 
 
@@ -906,7 +941,7 @@ static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
 	mp->info = mp->user_info;
 	mp->info = mp->user_info;
 }
 }
 
 
-int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
 {
 {
 	unsigned long flags;
 	unsigned long flags;
 	struct omap_overlay *ovl;
 	struct omap_overlay *ovl;
@@ -1005,7 +1040,7 @@ static void dss_setup_fifos(void)
 	}
 	}
 }
 }
 
 
-int dss_mgr_enable(struct omap_overlay_manager *mgr)
+static int dss_mgr_enable_compat(struct omap_overlay_manager *mgr)
 {
 {
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 	unsigned long flags;
 	unsigned long flags;
@@ -1035,10 +1070,13 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
 	if (!mgr_manual_update(mgr))
 	if (!mgr_manual_update(mgr))
 		mp->updating = true;
 		mp->updating = true;
 
 
+	if (!dss_data.irq_enabled && need_isr())
+		dss_register_vsync_isr();
+
 	spin_unlock_irqrestore(&data_lock, flags);
 	spin_unlock_irqrestore(&data_lock, flags);
 
 
 	if (!mgr_manual_update(mgr))
 	if (!mgr_manual_update(mgr))
-		dispc_mgr_enable(mgr->id, true);
+		dispc_mgr_enable_sync(mgr->id);
 
 
 out:
 out:
 	mutex_unlock(&apply_lock);
 	mutex_unlock(&apply_lock);
@@ -1052,7 +1090,7 @@ err:
 	return r;
 	return r;
 }
 }
 
 
-void dss_mgr_disable(struct omap_overlay_manager *mgr)
+static void dss_mgr_disable_compat(struct omap_overlay_manager *mgr)
 {
 {
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 	unsigned long flags;
 	unsigned long flags;
@@ -1063,7 +1101,7 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
 		goto out;
 		goto out;
 
 
 	if (!mgr_manual_update(mgr))
 	if (!mgr_manual_update(mgr))
-		dispc_mgr_enable(mgr->id, false);
+		dispc_mgr_disable_sync(mgr->id);
 
 
 	spin_lock_irqsave(&data_lock, flags);
 	spin_lock_irqsave(&data_lock, flags);
 
 
@@ -1076,7 +1114,7 @@ out:
 	mutex_unlock(&apply_lock);
 	mutex_unlock(&apply_lock);
 }
 }
 
 
-int dss_mgr_set_info(struct omap_overlay_manager *mgr,
+static int dss_mgr_set_info(struct omap_overlay_manager *mgr,
 		struct omap_overlay_manager_info *info)
 		struct omap_overlay_manager_info *info)
 {
 {
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -1097,7 +1135,7 @@ int dss_mgr_set_info(struct omap_overlay_manager *mgr,
 	return 0;
 	return 0;
 }
 }
 
 
-void dss_mgr_get_info(struct omap_overlay_manager *mgr,
+static void dss_mgr_get_info(struct omap_overlay_manager *mgr,
 		struct omap_overlay_manager_info *info)
 		struct omap_overlay_manager_info *info)
 {
 {
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -1110,7 +1148,7 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr,
 	spin_unlock_irqrestore(&data_lock, flags);
 	spin_unlock_irqrestore(&data_lock, flags);
 }
 }
 
 
-int dss_mgr_set_output(struct omap_overlay_manager *mgr,
+static int dss_mgr_set_output(struct omap_overlay_manager *mgr,
 		struct omap_dss_output *output)
 		struct omap_dss_output *output)
 {
 {
 	int r;
 	int r;
@@ -1142,7 +1180,7 @@ err:
 	return r;
 	return r;
 }
 }
 
 
-int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
+static int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
 {
 {
 	int r;
 	int r;
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -1189,7 +1227,7 @@ static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
 	mp->extra_info_dirty = true;
 	mp->extra_info_dirty = true;
 }
 }
 
 
-void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
+static void dss_mgr_set_timings_compat(struct omap_overlay_manager *mgr,
 		const struct omap_video_timings *timings)
 		const struct omap_video_timings *timings)
 {
 {
 	unsigned long flags;
 	unsigned long flags;
@@ -1217,7 +1255,7 @@ static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
 	mp->extra_info_dirty = true;
 	mp->extra_info_dirty = true;
 }
 }
 
 
-void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
+static void dss_mgr_set_lcd_config_compat(struct omap_overlay_manager *mgr,
 		const struct dss_lcd_mgr_config *config)
 		const struct dss_lcd_mgr_config *config)
 {
 {
 	unsigned long flags;
 	unsigned long flags;
@@ -1236,7 +1274,7 @@ out:
 	spin_unlock_irqrestore(&data_lock, flags);
 	spin_unlock_irqrestore(&data_lock, flags);
 }
 }
 
 
-int dss_ovl_set_info(struct omap_overlay *ovl,
+static int dss_ovl_set_info(struct omap_overlay *ovl,
 		struct omap_overlay_info *info)
 		struct omap_overlay_info *info)
 {
 {
 	struct ovl_priv_data *op = get_ovl_priv(ovl);
 	struct ovl_priv_data *op = get_ovl_priv(ovl);
@@ -1257,7 +1295,7 @@ int dss_ovl_set_info(struct omap_overlay *ovl,
 	return 0;
 	return 0;
 }
 }
 
 
-void dss_ovl_get_info(struct omap_overlay *ovl,
+static void dss_ovl_get_info(struct omap_overlay *ovl,
 		struct omap_overlay_info *info)
 		struct omap_overlay_info *info)
 {
 {
 	struct ovl_priv_data *op = get_ovl_priv(ovl);
 	struct ovl_priv_data *op = get_ovl_priv(ovl);
@@ -1270,7 +1308,7 @@ void dss_ovl_get_info(struct omap_overlay *ovl,
 	spin_unlock_irqrestore(&data_lock, flags);
 	spin_unlock_irqrestore(&data_lock, flags);
 }
 }
 
 
-int dss_ovl_set_manager(struct omap_overlay *ovl,
+static int dss_ovl_set_manager(struct omap_overlay *ovl,
 		struct omap_overlay_manager *mgr)
 		struct omap_overlay_manager *mgr)
 {
 {
 	struct ovl_priv_data *op = get_ovl_priv(ovl);
 	struct ovl_priv_data *op = get_ovl_priv(ovl);
@@ -1289,45 +1327,40 @@ int dss_ovl_set_manager(struct omap_overlay *ovl,
 		goto err;
 		goto err;
 	}
 	}
 
 
+	r = dispc_runtime_get();
+	if (r)
+		goto err;
+
 	spin_lock_irqsave(&data_lock, flags);
 	spin_lock_irqsave(&data_lock, flags);
 
 
 	if (op->enabled) {
 	if (op->enabled) {
 		spin_unlock_irqrestore(&data_lock, flags);
 		spin_unlock_irqrestore(&data_lock, flags);
 		DSSERR("overlay has to be disabled to change the manager\n");
 		DSSERR("overlay has to be disabled to change the manager\n");
 		r = -EINVAL;
 		r = -EINVAL;
-		goto err;
+		goto err1;
 	}
 	}
 
 
-	op->channel = mgr->id;
-	op->extra_info_dirty = true;
+	dispc_ovl_set_channel_out(ovl->id, mgr->id);
 
 
 	ovl->manager = mgr;
 	ovl->manager = mgr;
 	list_add_tail(&ovl->list, &mgr->overlays);
 	list_add_tail(&ovl->list, &mgr->overlays);
 
 
 	spin_unlock_irqrestore(&data_lock, flags);
 	spin_unlock_irqrestore(&data_lock, flags);
 
 
-	/* XXX: When there is an overlay on a DSI manual update display, and
-	 * the overlay is first disabled, then moved to tv, and enabled, we
-	 * seem to get SYNC_LOST_DIGIT error.
-	 *
-	 * Waiting doesn't seem to help, but updating the manual update display
-	 * after disabling the overlay seems to fix this. This hints that the
-	 * overlay is perhaps somehow tied to the LCD output until the output
-	 * is updated.
-	 *
-	 * Userspace workaround for this is to update the LCD after disabling
-	 * the overlay, but before moving the overlay to TV.
-	 */
+	dispc_runtime_put();
 
 
 	mutex_unlock(&apply_lock);
 	mutex_unlock(&apply_lock);
 
 
 	return 0;
 	return 0;
+
+err1:
+	dispc_runtime_put();
 err:
 err:
 	mutex_unlock(&apply_lock);
 	mutex_unlock(&apply_lock);
 	return r;
 	return r;
 }
 }
 
 
-int dss_ovl_unset_manager(struct omap_overlay *ovl)
+static int dss_ovl_unset_manager(struct omap_overlay *ovl)
 {
 {
 	struct ovl_priv_data *op = get_ovl_priv(ovl);
 	struct ovl_priv_data *op = get_ovl_priv(ovl);
 	unsigned long flags;
 	unsigned long flags;
@@ -1355,9 +1388,24 @@ int dss_ovl_unset_manager(struct omap_overlay *ovl)
 	/* wait for pending extra_info updates to ensure the ovl is disabled */
 	/* wait for pending extra_info updates to ensure the ovl is disabled */
 	wait_pending_extra_info_updates();
 	wait_pending_extra_info_updates();
 
 
+	/*
+	 * For a manual update display, there is no guarantee that the overlay
+	 * is really disabled in HW, we may need an extra update from this
+	 * manager before the configurations can go in. Return an error if the
+	 * overlay needed an update from the manager.
+	 *
+	 * TODO: Instead of returning an error, try to do a dummy manager update
+	 * here to disable the overlay in hardware. Use the *GATED fields in
+	 * the DISPC_CONFIG registers to do a dummy update.
+	 */
 	spin_lock_irqsave(&data_lock, flags);
 	spin_lock_irqsave(&data_lock, flags);
 
 
-	op->channel = -1;
+	if (ovl_manual_update(ovl) && op->extra_info_dirty) {
+		spin_unlock_irqrestore(&data_lock, flags);
+		DSSERR("need an update to change the manager\n");
+		r = -EINVAL;
+		goto err;
+	}
 
 
 	ovl->manager = NULL;
 	ovl->manager = NULL;
 	list_del(&ovl->list);
 	list_del(&ovl->list);
@@ -1372,7 +1420,7 @@ err:
 	return r;
 	return r;
 }
 }
 
 
-bool dss_ovl_is_enabled(struct omap_overlay *ovl)
+static bool dss_ovl_is_enabled(struct omap_overlay *ovl)
 {
 {
 	struct ovl_priv_data *op = get_ovl_priv(ovl);
 	struct ovl_priv_data *op = get_ovl_priv(ovl);
 	unsigned long flags;
 	unsigned long flags;
@@ -1387,7 +1435,7 @@ bool dss_ovl_is_enabled(struct omap_overlay *ovl)
 	return e;
 	return e;
 }
 }
 
 
-int dss_ovl_enable(struct omap_overlay *ovl)
+static int dss_ovl_enable(struct omap_overlay *ovl)
 {
 {
 	struct ovl_priv_data *op = get_ovl_priv(ovl);
 	struct ovl_priv_data *op = get_ovl_priv(ovl);
 	unsigned long flags;
 	unsigned long flags;
@@ -1437,7 +1485,7 @@ err1:
 	return r;
 	return r;
 }
 }
 
 
-int dss_ovl_disable(struct omap_overlay *ovl)
+static int dss_ovl_disable(struct omap_overlay *ovl)
 {
 {
 	struct ovl_priv_data *op = get_ovl_priv(ovl);
 	struct ovl_priv_data *op = get_ovl_priv(ovl);
 	unsigned long flags;
 	unsigned long flags;
@@ -1472,3 +1520,152 @@ err:
 	return r;
 	return r;
 }
 }
 
 
+static int dss_mgr_register_framedone_handler_compat(struct omap_overlay_manager *mgr,
+		void (*handler)(void *), void *data)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+
+	if (mp->framedone_handler)
+		return -EBUSY;
+
+	mp->framedone_handler = handler;
+	mp->framedone_handler_data = data;
+
+	return 0;
+}
+
+static void dss_mgr_unregister_framedone_handler_compat(struct omap_overlay_manager *mgr,
+		void (*handler)(void *), void *data)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+
+	WARN_ON(mp->framedone_handler != handler ||
+			mp->framedone_handler_data != data);
+
+	mp->framedone_handler = NULL;
+	mp->framedone_handler_data = NULL;
+}
+
+static const struct dss_mgr_ops apply_mgr_ops = {
+	.start_update = dss_mgr_start_update_compat,
+	.enable = dss_mgr_enable_compat,
+	.disable = dss_mgr_disable_compat,
+	.set_timings = dss_mgr_set_timings_compat,
+	.set_lcd_config = dss_mgr_set_lcd_config_compat,
+	.register_framedone_handler = dss_mgr_register_framedone_handler_compat,
+	.unregister_framedone_handler = dss_mgr_unregister_framedone_handler_compat,
+};
+
+static int compat_refcnt;
+static DEFINE_MUTEX(compat_init_lock);
+
+int omapdss_compat_init(void)
+{
+	struct platform_device *pdev = dss_get_core_pdev();
+	struct omap_dss_device *dssdev = NULL;
+	int i, r;
+
+	mutex_lock(&compat_init_lock);
+
+	if (compat_refcnt++ > 0)
+		goto out;
+
+	apply_init_priv();
+
+	dss_init_overlay_managers(pdev);
+	dss_init_overlays(pdev);
+
+	for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
+		struct omap_overlay_manager *mgr;
+
+		mgr = omap_dss_get_overlay_manager(i);
+
+		mgr->set_output = &dss_mgr_set_output;
+		mgr->unset_output = &dss_mgr_unset_output;
+		mgr->apply = &omap_dss_mgr_apply;
+		mgr->set_manager_info = &dss_mgr_set_info;
+		mgr->get_manager_info = &dss_mgr_get_info;
+		mgr->wait_for_go = &dss_mgr_wait_for_go;
+		mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
+		mgr->get_device = &dss_mgr_get_device;
+	}
+
+	for (i = 0; i < omap_dss_get_num_overlays(); i++) {
+		struct omap_overlay *ovl = omap_dss_get_overlay(i);
+
+		ovl->is_enabled = &dss_ovl_is_enabled;
+		ovl->enable = &dss_ovl_enable;
+		ovl->disable = &dss_ovl_disable;
+		ovl->set_manager = &dss_ovl_set_manager;
+		ovl->unset_manager = &dss_ovl_unset_manager;
+		ovl->set_overlay_info = &dss_ovl_set_info;
+		ovl->get_overlay_info = &dss_ovl_get_info;
+		ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
+		ovl->get_device = &dss_ovl_get_device;
+	}
+
+	r = dss_install_mgr_ops(&apply_mgr_ops);
+	if (r)
+		goto err_mgr_ops;
+
+	for_each_dss_dev(dssdev) {
+		r = display_init_sysfs(pdev, dssdev);
+		/* XXX uninit sysfs files on error */
+		if (r)
+			goto err_disp_sysfs;
+	}
+
+	dispc_runtime_get();
+
+	r = dss_dispc_initialize_irq();
+	if (r)
+		goto err_init_irq;
+
+	dispc_runtime_put();
+
+out:
+	mutex_unlock(&compat_init_lock);
+
+	return 0;
+
+err_init_irq:
+	dispc_runtime_put();
+
+err_disp_sysfs:
+	dss_uninstall_mgr_ops();
+
+err_mgr_ops:
+	dss_uninit_overlay_managers(pdev);
+	dss_uninit_overlays(pdev);
+
+	compat_refcnt--;
+
+	mutex_unlock(&compat_init_lock);
+
+	return r;
+}
+EXPORT_SYMBOL(omapdss_compat_init);
+
+void omapdss_compat_uninit(void)
+{
+	struct platform_device *pdev = dss_get_core_pdev();
+	struct omap_dss_device *dssdev = NULL;
+
+	mutex_lock(&compat_init_lock);
+
+	if (--compat_refcnt > 0)
+		goto out;
+
+	dss_dispc_uninitialize_irq();
+
+	for_each_dss_dev(dssdev)
+		display_uninit_sysfs(pdev, dssdev);
+
+	dss_uninstall_mgr_ops();
+
+	dss_uninit_overlay_managers(pdev);
+	dss_uninit_overlays(pdev);
+out:
+	mutex_unlock(&compat_init_lock);
+}
+EXPORT_SYMBOL(omapdss_compat_uninit);

+ 25 - 47
drivers/video/omap2/dss/core.c

@@ -53,15 +53,23 @@ static char *def_disp_name;
 module_param_named(def_disp, def_disp_name, charp, 0);
 module_param_named(def_disp, def_disp_name, charp, 0);
 MODULE_PARM_DESC(def_disp, "default display name");
 MODULE_PARM_DESC(def_disp, "default display name");
 
 
-#ifdef DEBUG
-bool dss_debug;
-module_param_named(debug, dss_debug, bool, 0644);
-#endif
-
-const char *dss_get_default_display_name(void)
+const char *omapdss_get_default_display_name(void)
 {
 {
 	return core.default_display_name;
 	return core.default_display_name;
 }
 }
+EXPORT_SYMBOL(omapdss_get_default_display_name);
+
+enum omapdss_version omapdss_get_version(void)
+{
+	struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
+	return pdata->version;
+}
+EXPORT_SYMBOL(omapdss_get_version);
+
+struct platform_device *dss_get_core_pdev(void)
+{
+	return core.pdev;
+}
 
 
 /* REGULATORS */
 /* REGULATORS */
 
 
@@ -93,21 +101,6 @@ struct regulator *dss_get_vdds_sdi(void)
 	return reg;
 	return reg;
 }
 }
 
 
-int dss_get_ctx_loss_count(struct device *dev)
-{
-	struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
-	int cnt;
-
-	if (!board_data->get_context_loss_count)
-		return -ENOENT;
-
-	cnt = board_data->get_context_loss_count(dev);
-
-	WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
-
-	return cnt;
-}
-
 int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask)
 int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask)
 {
 {
 	struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
 	struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
@@ -122,7 +115,7 @@ void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask)
 {
 {
 	struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
 	struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
 
 
-	if (!board_data->dsi_enable_pads)
+	if (!board_data->dsi_disable_pads)
 		return;
 		return;
 
 
 	return board_data->dsi_disable_pads(dsi_id, lane_mask);
 	return board_data->dsi_disable_pads(dsi_id, lane_mask);
@@ -138,7 +131,7 @@ int dss_set_min_bus_tput(struct device *dev, unsigned long tput)
 		return 0;
 		return 0;
 }
 }
 
 
-#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
 static int dss_debug_show(struct seq_file *s, void *unused)
 static int dss_debug_show(struct seq_file *s, void *unused)
 {
 {
 	void (*func)(struct seq_file *) = s->private;
 	void (*func)(struct seq_file *) = s->private;
@@ -193,7 +186,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
 
 
 	return 0;
 	return 0;
 }
 }
-#else /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
+#else /* CONFIG_OMAP2_DSS_DEBUGFS */
 static inline int dss_initialize_debugfs(void)
 static inline int dss_initialize_debugfs(void)
 {
 {
 	return 0;
 	return 0;
@@ -205,7 +198,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
 {
 {
 	return 0;
 	return 0;
 }
 }
-#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
+#endif /* CONFIG_OMAP2_DSS_DEBUGFS */
 
 
 /* PLATFORM DEVICE */
 /* PLATFORM DEVICE */
 static int omap_dss_pm_notif(struct notifier_block *b, unsigned long v, void *d)
 static int omap_dss_pm_notif(struct notifier_block *b, unsigned long v, void *d)
@@ -237,12 +230,7 @@ static int __init omap_dss_probe(struct platform_device *pdev)
 
 
 	core.pdev = pdev;
 	core.pdev = pdev;
 
 
-	dss_features_init(pdata->version);
-
-	dss_apply_init();
-
-	dss_init_overlay_managers(pdev);
-	dss_init_overlays(pdev);
+	dss_features_init(omapdss_get_version());
 
 
 	r = dss_initialize_debugfs();
 	r = dss_initialize_debugfs();
 	if (r)
 	if (r)
@@ -268,9 +256,6 @@ static int omap_dss_remove(struct platform_device *pdev)
 
 
 	dss_uninitialize_debugfs();
 	dss_uninitialize_debugfs();
 
 
-	dss_uninit_overlays(pdev);
-	dss_uninit_overlay_managers(pdev);
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -358,15 +343,10 @@ static int dss_driver_probe(struct device *dev)
 				dev_name(dev), dssdev->driver_name,
 				dev_name(dev), dssdev->driver_name,
 				dssdrv->driver.name);
 				dssdrv->driver.name);
 
 
-	r = dss_init_device(core.pdev, dssdev);
-	if (r)
-		return r;
-
 	r = dssdrv->probe(dssdev);
 	r = dssdrv->probe(dssdev);
 
 
 	if (r) {
 	if (r) {
 		DSSERR("driver probe failed: %d\n", r);
 		DSSERR("driver probe failed: %d\n", r);
-		dss_uninit_device(core.pdev, dssdev);
 		return r;
 		return r;
 	}
 	}
 
 
@@ -387,8 +367,6 @@ static int dss_driver_remove(struct device *dev)
 
 
 	dssdrv->remove(dssdev);
 	dssdrv->remove(dssdev);
 
 
-	dss_uninit_device(core.pdev, dssdev);
-
 	dssdev->driver = NULL;
 	dssdev->driver = NULL;
 
 
 	return 0;
 	return 0;
@@ -507,6 +485,9 @@ static int __init omap_dss_bus_register(void)
 
 
 /* INIT */
 /* INIT */
 static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
 static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
+#ifdef CONFIG_OMAP2_DSS_DSI
+	dsi_init_platform_driver,
+#endif
 #ifdef CONFIG_OMAP2_DSS_DPI
 #ifdef CONFIG_OMAP2_DSS_DPI
 	dpi_init_platform_driver,
 	dpi_init_platform_driver,
 #endif
 #endif
@@ -519,15 +500,15 @@ static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
 #ifdef CONFIG_OMAP2_DSS_VENC
 #ifdef CONFIG_OMAP2_DSS_VENC
 	venc_init_platform_driver,
 	venc_init_platform_driver,
 #endif
 #endif
-#ifdef CONFIG_OMAP2_DSS_DSI
-	dsi_init_platform_driver,
-#endif
 #ifdef CONFIG_OMAP4_DSS_HDMI
 #ifdef CONFIG_OMAP4_DSS_HDMI
 	hdmi_init_platform_driver,
 	hdmi_init_platform_driver,
 #endif
 #endif
 };
 };
 
 
 static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
 static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
+#ifdef CONFIG_OMAP2_DSS_DSI
+	dsi_uninit_platform_driver,
+#endif
 #ifdef CONFIG_OMAP2_DSS_DPI
 #ifdef CONFIG_OMAP2_DSS_DPI
 	dpi_uninit_platform_driver,
 	dpi_uninit_platform_driver,
 #endif
 #endif
@@ -540,9 +521,6 @@ static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
 #ifdef CONFIG_OMAP2_DSS_VENC
 #ifdef CONFIG_OMAP2_DSS_VENC
 	venc_uninit_platform_driver,
 	venc_uninit_platform_driver,
 #endif
 #endif
-#ifdef CONFIG_OMAP2_DSS_DSI
-	dsi_uninit_platform_driver,
-#endif
 #ifdef CONFIG_OMAP4_DSS_HDMI
 #ifdef CONFIG_OMAP4_DSS_HDMI
 	hdmi_uninit_platform_driver,
 	hdmi_uninit_platform_driver,
 #endif
 #endif

+ 667 - 0
drivers/video/omap2/dss/dispc-compat.c

@@ -0,0 +1,667 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "APPLY"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/seq_file.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+#include "dispc-compat.h"
+
+#define DISPC_IRQ_MASK_ERROR            (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
+					 DISPC_IRQ_OCP_ERR | \
+					 DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
+					 DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
+					 DISPC_IRQ_SYNC_LOST | \
+					 DISPC_IRQ_SYNC_LOST_DIGIT)
+
+#define DISPC_MAX_NR_ISRS		8
+
+struct omap_dispc_isr_data {
+	omap_dispc_isr_t	isr;
+	void			*arg;
+	u32			mask;
+};
+
+struct dispc_irq_stats {
+	unsigned long last_reset;
+	unsigned irq_count;
+	unsigned irqs[32];
+};
+
+static struct {
+	spinlock_t irq_lock;
+	u32 irq_error_mask;
+	struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
+	u32 error_irqs;
+	struct work_struct error_work;
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+	spinlock_t irq_stats_lock;
+	struct dispc_irq_stats irq_stats;
+#endif
+} dispc_compat;
+
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+static void dispc_dump_irqs(struct seq_file *s)
+{
+	unsigned long flags;
+	struct dispc_irq_stats stats;
+
+	spin_lock_irqsave(&dispc_compat.irq_stats_lock, flags);
+
+	stats = dispc_compat.irq_stats;
+	memset(&dispc_compat.irq_stats, 0, sizeof(dispc_compat.irq_stats));
+	dispc_compat.irq_stats.last_reset = jiffies;
+
+	spin_unlock_irqrestore(&dispc_compat.irq_stats_lock, flags);
+
+	seq_printf(s, "period %u ms\n",
+			jiffies_to_msecs(jiffies - stats.last_reset));
+
+	seq_printf(s, "irqs %d\n", stats.irq_count);
+#define PIS(x) \
+	seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
+
+	PIS(FRAMEDONE);
+	PIS(VSYNC);
+	PIS(EVSYNC_EVEN);
+	PIS(EVSYNC_ODD);
+	PIS(ACBIAS_COUNT_STAT);
+	PIS(PROG_LINE_NUM);
+	PIS(GFX_FIFO_UNDERFLOW);
+	PIS(GFX_END_WIN);
+	PIS(PAL_GAMMA_MASK);
+	PIS(OCP_ERR);
+	PIS(VID1_FIFO_UNDERFLOW);
+	PIS(VID1_END_WIN);
+	PIS(VID2_FIFO_UNDERFLOW);
+	PIS(VID2_END_WIN);
+	if (dss_feat_get_num_ovls() > 3) {
+		PIS(VID3_FIFO_UNDERFLOW);
+		PIS(VID3_END_WIN);
+	}
+	PIS(SYNC_LOST);
+	PIS(SYNC_LOST_DIGIT);
+	PIS(WAKEUP);
+	if (dss_has_feature(FEAT_MGR_LCD2)) {
+		PIS(FRAMEDONE2);
+		PIS(VSYNC2);
+		PIS(ACBIAS_COUNT_STAT2);
+		PIS(SYNC_LOST2);
+	}
+	if (dss_has_feature(FEAT_MGR_LCD3)) {
+		PIS(FRAMEDONE3);
+		PIS(VSYNC3);
+		PIS(ACBIAS_COUNT_STAT3);
+		PIS(SYNC_LOST3);
+	}
+#undef PIS
+}
+#endif
+
+/* dispc.irq_lock has to be locked by the caller */
+static void _omap_dispc_set_irqs(void)
+{
+	u32 mask;
+	int i;
+	struct omap_dispc_isr_data *isr_data;
+
+	mask = dispc_compat.irq_error_mask;
+
+	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+		isr_data = &dispc_compat.registered_isr[i];
+
+		if (isr_data->isr == NULL)
+			continue;
+
+		mask |= isr_data->mask;
+	}
+
+	dispc_write_irqenable(mask);
+}
+
+int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
+{
+	int i;
+	int ret;
+	unsigned long flags;
+	struct omap_dispc_isr_data *isr_data;
+
+	if (isr == NULL)
+		return -EINVAL;
+
+	spin_lock_irqsave(&dispc_compat.irq_lock, flags);
+
+	/* check for duplicate entry */
+	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+		isr_data = &dispc_compat.registered_isr[i];
+		if (isr_data->isr == isr && isr_data->arg == arg &&
+				isr_data->mask == mask) {
+			ret = -EINVAL;
+			goto err;
+		}
+	}
+
+	isr_data = NULL;
+	ret = -EBUSY;
+
+	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+		isr_data = &dispc_compat.registered_isr[i];
+
+		if (isr_data->isr != NULL)
+			continue;
+
+		isr_data->isr = isr;
+		isr_data->arg = arg;
+		isr_data->mask = mask;
+		ret = 0;
+
+		break;
+	}
+
+	if (ret)
+		goto err;
+
+	_omap_dispc_set_irqs();
+
+	spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
+
+	return 0;
+err:
+	spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(omap_dispc_register_isr);
+
+int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
+{
+	int i;
+	unsigned long flags;
+	int ret = -EINVAL;
+	struct omap_dispc_isr_data *isr_data;
+
+	spin_lock_irqsave(&dispc_compat.irq_lock, flags);
+
+	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+		isr_data = &dispc_compat.registered_isr[i];
+		if (isr_data->isr != isr || isr_data->arg != arg ||
+				isr_data->mask != mask)
+			continue;
+
+		/* found the correct isr */
+
+		isr_data->isr = NULL;
+		isr_data->arg = NULL;
+		isr_data->mask = 0;
+
+		ret = 0;
+		break;
+	}
+
+	if (ret == 0)
+		_omap_dispc_set_irqs();
+
+	spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(omap_dispc_unregister_isr);
+
+static void print_irq_status(u32 status)
+{
+	if ((status & dispc_compat.irq_error_mask) == 0)
+		return;
+
+#define PIS(x) (status & DISPC_IRQ_##x) ? (#x " ") : ""
+
+	pr_debug("DISPC IRQ: 0x%x: %s%s%s%s%s%s%s%s%s\n",
+		status,
+		PIS(OCP_ERR),
+		PIS(GFX_FIFO_UNDERFLOW),
+		PIS(VID1_FIFO_UNDERFLOW),
+		PIS(VID2_FIFO_UNDERFLOW),
+		dss_feat_get_num_ovls() > 3 ? PIS(VID3_FIFO_UNDERFLOW) : "",
+		PIS(SYNC_LOST),
+		PIS(SYNC_LOST_DIGIT),
+		dss_has_feature(FEAT_MGR_LCD2) ? PIS(SYNC_LOST2) : "",
+		dss_has_feature(FEAT_MGR_LCD3) ? PIS(SYNC_LOST3) : "");
+#undef PIS
+}
+
+/* Called from dss.c. Note that we don't touch clocks here,
+ * but we presume they are on because we got an IRQ. However,
+ * an irq handler may turn the clocks off, so we may not have
+ * clock later in the function. */
+static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
+{
+	int i;
+	u32 irqstatus, irqenable;
+	u32 handledirqs = 0;
+	u32 unhandled_errors;
+	struct omap_dispc_isr_data *isr_data;
+	struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
+
+	spin_lock(&dispc_compat.irq_lock);
+
+	irqstatus = dispc_read_irqstatus();
+	irqenable = dispc_read_irqenable();
+
+	/* IRQ is not for us */
+	if (!(irqstatus & irqenable)) {
+		spin_unlock(&dispc_compat.irq_lock);
+		return IRQ_NONE;
+	}
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+	spin_lock(&dispc_compat.irq_stats_lock);
+	dispc_compat.irq_stats.irq_count++;
+	dss_collect_irq_stats(irqstatus, dispc_compat.irq_stats.irqs);
+	spin_unlock(&dispc_compat.irq_stats_lock);
+#endif
+
+	print_irq_status(irqstatus);
+
+	/* Ack the interrupt. Do it here before clocks are possibly turned
+	 * off */
+	dispc_clear_irqstatus(irqstatus);
+	/* flush posted write */
+	dispc_read_irqstatus();
+
+	/* make a copy and unlock, so that isrs can unregister
+	 * themselves */
+	memcpy(registered_isr, dispc_compat.registered_isr,
+			sizeof(registered_isr));
+
+	spin_unlock(&dispc_compat.irq_lock);
+
+	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+		isr_data = &registered_isr[i];
+
+		if (!isr_data->isr)
+			continue;
+
+		if (isr_data->mask & irqstatus) {
+			isr_data->isr(isr_data->arg, irqstatus);
+			handledirqs |= isr_data->mask;
+		}
+	}
+
+	spin_lock(&dispc_compat.irq_lock);
+
+	unhandled_errors = irqstatus & ~handledirqs & dispc_compat.irq_error_mask;
+
+	if (unhandled_errors) {
+		dispc_compat.error_irqs |= unhandled_errors;
+
+		dispc_compat.irq_error_mask &= ~unhandled_errors;
+		_omap_dispc_set_irqs();
+
+		schedule_work(&dispc_compat.error_work);
+	}
+
+	spin_unlock(&dispc_compat.irq_lock);
+
+	return IRQ_HANDLED;
+}
+
+static void dispc_error_worker(struct work_struct *work)
+{
+	int i;
+	u32 errors;
+	unsigned long flags;
+	static const unsigned fifo_underflow_bits[] = {
+		DISPC_IRQ_GFX_FIFO_UNDERFLOW,
+		DISPC_IRQ_VID1_FIFO_UNDERFLOW,
+		DISPC_IRQ_VID2_FIFO_UNDERFLOW,
+		DISPC_IRQ_VID3_FIFO_UNDERFLOW,
+	};
+
+	spin_lock_irqsave(&dispc_compat.irq_lock, flags);
+	errors = dispc_compat.error_irqs;
+	dispc_compat.error_irqs = 0;
+	spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
+
+	dispc_runtime_get();
+
+	for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+		struct omap_overlay *ovl;
+		unsigned bit;
+
+		ovl = omap_dss_get_overlay(i);
+		bit = fifo_underflow_bits[i];
+
+		if (bit & errors) {
+			DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n",
+					ovl->name);
+			dispc_ovl_enable(ovl->id, false);
+			dispc_mgr_go(ovl->manager->id);
+			msleep(50);
+		}
+	}
+
+	for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
+		struct omap_overlay_manager *mgr;
+		unsigned bit;
+
+		mgr = omap_dss_get_overlay_manager(i);
+		bit = dispc_mgr_get_sync_lost_irq(i);
+
+		if (bit & errors) {
+			int j;
+
+			DSSERR("SYNC_LOST on channel %s, restarting the output "
+					"with video overlays disabled\n",
+					mgr->name);
+
+			dss_mgr_disable(mgr);
+
+			for (j = 0; j < omap_dss_get_num_overlays(); ++j) {
+				struct omap_overlay *ovl;
+				ovl = omap_dss_get_overlay(j);
+
+				if (ovl->id != OMAP_DSS_GFX &&
+						ovl->manager == mgr)
+					ovl->disable(ovl);
+			}
+
+			dss_mgr_enable(mgr);
+		}
+	}
+
+	if (errors & DISPC_IRQ_OCP_ERR) {
+		DSSERR("OCP_ERR\n");
+		for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
+			struct omap_overlay_manager *mgr;
+
+			mgr = omap_dss_get_overlay_manager(i);
+			dss_mgr_disable(mgr);
+		}
+	}
+
+	spin_lock_irqsave(&dispc_compat.irq_lock, flags);
+	dispc_compat.irq_error_mask |= errors;
+	_omap_dispc_set_irqs();
+	spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
+
+	dispc_runtime_put();
+}
+
+int dss_dispc_initialize_irq(void)
+{
+	int r;
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+	spin_lock_init(&dispc_compat.irq_stats_lock);
+	dispc_compat.irq_stats.last_reset = jiffies;
+	dss_debugfs_create_file("dispc_irq", dispc_dump_irqs);
+#endif
+
+	spin_lock_init(&dispc_compat.irq_lock);
+
+	memset(dispc_compat.registered_isr, 0,
+			sizeof(dispc_compat.registered_isr));
+
+	dispc_compat.irq_error_mask = DISPC_IRQ_MASK_ERROR;
+	if (dss_has_feature(FEAT_MGR_LCD2))
+		dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
+	if (dss_has_feature(FEAT_MGR_LCD3))
+		dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST3;
+	if (dss_feat_get_num_ovls() > 3)
+		dispc_compat.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;
+
+	/*
+	 * there's SYNC_LOST_DIGIT waiting after enabling the DSS,
+	 * so clear it
+	 */
+	dispc_clear_irqstatus(dispc_read_irqstatus());
+
+	INIT_WORK(&dispc_compat.error_work, dispc_error_worker);
+
+	_omap_dispc_set_irqs();
+
+	r = dispc_request_irq(omap_dispc_irq_handler, &dispc_compat);
+	if (r) {
+		DSSERR("dispc_request_irq failed\n");
+		return r;
+	}
+
+	return 0;
+}
+
+void dss_dispc_uninitialize_irq(void)
+{
+	dispc_free_irq(&dispc_compat);
+}
+
+static void dispc_mgr_disable_isr(void *data, u32 mask)
+{
+	struct completion *compl = data;
+	complete(compl);
+}
+
+static void dispc_mgr_enable_lcd_out(enum omap_channel channel)
+{
+	dispc_mgr_enable(channel, true);
+}
+
+static void dispc_mgr_disable_lcd_out(enum omap_channel channel)
+{
+	DECLARE_COMPLETION_ONSTACK(framedone_compl);
+	int r;
+	u32 irq;
+
+	if (dispc_mgr_is_enabled(channel) == false)
+		return;
+
+	/*
+	 * When we disable LCD output, we need to wait for FRAMEDONE to know
+	 * that DISPC has finished with the LCD output.
+	 */
+
+	irq = dispc_mgr_get_framedone_irq(channel);
+
+	r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
+			irq);
+	if (r)
+		DSSERR("failed to register FRAMEDONE isr\n");
+
+	dispc_mgr_enable(channel, false);
+
+	/* if we couldn't register for framedone, just sleep and exit */
+	if (r) {
+		msleep(100);
+		return;
+	}
+
+	if (!wait_for_completion_timeout(&framedone_compl,
+				msecs_to_jiffies(100)))
+		DSSERR("timeout waiting for FRAME DONE\n");
+
+	r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
+			irq);
+	if (r)
+		DSSERR("failed to unregister FRAMEDONE isr\n");
+}
+
+static void dispc_digit_out_enable_isr(void *data, u32 mask)
+{
+	struct completion *compl = data;
+
+	/* ignore any sync lost interrupts */
+	if (mask & (DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD))
+		complete(compl);
+}
+
+static void dispc_mgr_enable_digit_out(void)
+{
+	DECLARE_COMPLETION_ONSTACK(vsync_compl);
+	int r;
+	u32 irq_mask;
+
+	if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == true)
+		return;
+
+	/*
+	 * Digit output produces some sync lost interrupts during the first
+	 * frame when enabling. Those need to be ignored, so we register for the
+	 * sync lost irq to prevent the error handler from triggering.
+	 */
+
+	irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT) |
+		dispc_mgr_get_sync_lost_irq(OMAP_DSS_CHANNEL_DIGIT);
+
+	r = omap_dispc_register_isr(dispc_digit_out_enable_isr, &vsync_compl,
+			irq_mask);
+	if (r) {
+		DSSERR("failed to register %x isr\n", irq_mask);
+		return;
+	}
+
+	dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, true);
+
+	/* wait for the first evsync */
+	if (!wait_for_completion_timeout(&vsync_compl, msecs_to_jiffies(100)))
+		DSSERR("timeout waiting for digit out to start\n");
+
+	r = omap_dispc_unregister_isr(dispc_digit_out_enable_isr, &vsync_compl,
+			irq_mask);
+	if (r)
+		DSSERR("failed to unregister %x isr\n", irq_mask);
+}
+
+static void dispc_mgr_disable_digit_out(void)
+{
+	DECLARE_COMPLETION_ONSTACK(framedone_compl);
+	int r, i;
+	u32 irq_mask;
+	int num_irqs;
+
+	if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == false)
+		return;
+
+	/*
+	 * When we disable the digit output, we need to wait for FRAMEDONE to
+	 * know that DISPC has finished with the output.
+	 */
+
+	irq_mask = dispc_mgr_get_framedone_irq(OMAP_DSS_CHANNEL_DIGIT);
+	num_irqs = 1;
+
+	if (!irq_mask) {
+		/*
+		 * omap 2/3 don't have framedone irq for TV, so we need to use
+		 * vsyncs for this.
+		 */
+
+		irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT);
+		/*
+		 * We need to wait for both even and odd vsyncs. Note that this
+		 * is not totally reliable, as we could get a vsync interrupt
+		 * before we disable the output, which leads to timeout in the
+		 * wait_for_completion.
+		 */
+		num_irqs = 2;
+	}
+
+	r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
+			irq_mask);
+	if (r)
+		DSSERR("failed to register %x isr\n", irq_mask);
+
+	dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, false);
+
+	/* if we couldn't register the irq, just sleep and exit */
+	if (r) {
+		msleep(100);
+		return;
+	}
+
+	for (i = 0; i < num_irqs; ++i) {
+		if (!wait_for_completion_timeout(&framedone_compl,
+					msecs_to_jiffies(100)))
+			DSSERR("timeout waiting for digit out to stop\n");
+	}
+
+	r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
+			irq_mask);
+	if (r)
+		DSSERR("failed to unregister %x isr\n", irq_mask);
+}
+
+void dispc_mgr_enable_sync(enum omap_channel channel)
+{
+	if (dss_mgr_is_lcd(channel))
+		dispc_mgr_enable_lcd_out(channel);
+	else if (channel == OMAP_DSS_CHANNEL_DIGIT)
+		dispc_mgr_enable_digit_out();
+	else
+		WARN_ON(1);
+}
+
+void dispc_mgr_disable_sync(enum omap_channel channel)
+{
+	if (dss_mgr_is_lcd(channel))
+		dispc_mgr_disable_lcd_out(channel);
+	else if (channel == OMAP_DSS_CHANNEL_DIGIT)
+		dispc_mgr_disable_digit_out();
+	else
+		WARN_ON(1);
+}
+
+int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
+		unsigned long timeout)
+{
+	void dispc_irq_wait_handler(void *data, u32 mask)
+	{
+		complete((struct completion *)data);
+	}
+
+	int r;
+	DECLARE_COMPLETION_ONSTACK(completion);
+
+	r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
+			irqmask);
+
+	if (r)
+		return r;
+
+	timeout = wait_for_completion_interruptible_timeout(&completion,
+			timeout);
+
+	omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
+
+	if (timeout == 0)
+		return -ETIMEDOUT;
+
+	if (timeout == -ERESTARTSYS)
+		return -ERESTARTSYS;
+
+	return 0;
+}

+ 30 - 0
drivers/video/omap2/dss/dispc-compat.h

@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OMAP2_DSS_DISPC_COMPAT_H
+#define __OMAP2_DSS_DISPC_COMPAT_H
+
+void dispc_mgr_enable_sync(enum omap_channel channel);
+void dispc_mgr_disable_sync(enum omap_channel channel);
+
+int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
+		unsigned long timeout);
+
+int dss_dispc_initialize_irq(void);
+void dss_dispc_uninitialize_irq(void);
+
+#endif

+ 277 - 786
drivers/video/omap2/dss/dispc.c

@@ -33,9 +33,9 @@
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include <linux/workqueue.h>
 #include <linux/workqueue.h>
 #include <linux/hardirq.h>
 #include <linux/hardirq.h>
-#include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_runtime.h>
+#include <linux/sizes.h>
 
 
 #include <video/omapdss.h>
 #include <video/omapdss.h>
 
 
@@ -46,21 +46,6 @@
 /* DISPC */
 /* DISPC */
 #define DISPC_SZ_REGS			SZ_4K
 #define DISPC_SZ_REGS			SZ_4K
 
 
-#define DISPC_IRQ_MASK_ERROR            (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
-					 DISPC_IRQ_OCP_ERR | \
-					 DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
-					 DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
-					 DISPC_IRQ_SYNC_LOST | \
-					 DISPC_IRQ_SYNC_LOST_DIGIT)
-
-#define DISPC_MAX_NR_ISRS		8
-
-struct omap_dispc_isr_data {
-	omap_dispc_isr_t	isr;
-	void			*arg;
-	u32			mask;
-};
-
 enum omap_burst_size {
 enum omap_burst_size {
 	BURST_SIZE_X2 = 0,
 	BURST_SIZE_X2 = 0,
 	BURST_SIZE_X4 = 1,
 	BURST_SIZE_X4 = 1,
@@ -73,12 +58,6 @@ enum omap_burst_size {
 #define REG_FLD_MOD(idx, val, start, end)				\
 #define REG_FLD_MOD(idx, val, start, end)				\
 	dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
 	dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
 
 
-struct dispc_irq_stats {
-	unsigned long last_reset;
-	unsigned irq_count;
-	unsigned irqs[32];
-};
-
 struct dispc_features {
 struct dispc_features {
 	u8 sw_start;
 	u8 sw_start;
 	u8 fp_start;
 	u8 fp_start;
@@ -86,19 +65,26 @@ struct dispc_features {
 	u16 sw_max;
 	u16 sw_max;
 	u16 vp_max;
 	u16 vp_max;
 	u16 hp_max;
 	u16 hp_max;
-	int (*calc_scaling) (enum omap_plane plane,
+	u8 mgr_width_start;
+	u8 mgr_height_start;
+	u16 mgr_width_max;
+	u16 mgr_height_max;
+	int (*calc_scaling) (unsigned long pclk, unsigned long lclk,
 		const struct omap_video_timings *mgr_timings,
 		const struct omap_video_timings *mgr_timings,
 		u16 width, u16 height, u16 out_width, u16 out_height,
 		u16 width, u16 height, u16 out_width, u16 out_height,
 		enum omap_color_mode color_mode, bool *five_taps,
 		enum omap_color_mode color_mode, bool *five_taps,
 		int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
 		int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
 		u16 pos_x, unsigned long *core_clk, bool mem_to_mem);
 		u16 pos_x, unsigned long *core_clk, bool mem_to_mem);
-	unsigned long (*calc_core_clk) (enum omap_plane plane,
+	unsigned long (*calc_core_clk) (unsigned long pclk,
 		u16 width, u16 height, u16 out_width, u16 out_height,
 		u16 width, u16 height, u16 out_width, u16 out_height,
 		bool mem_to_mem);
 		bool mem_to_mem);
 	u8 num_fifos;
 	u8 num_fifos;
 
 
 	/* swap GFX & WB fifos */
 	/* swap GFX & WB fifos */
 	bool gfx_fifo_workaround:1;
 	bool gfx_fifo_workaround:1;
+
+	/* no DISPC_IRQ_FRAMEDONETV on this SoC */
+	bool no_framedone_tv:1;
 };
 };
 
 
 #define DISPC_MAX_NR_FIFOS 5
 #define DISPC_MAX_NR_FIFOS 5
@@ -110,27 +96,15 @@ static struct {
 	int		ctx_loss_cnt;
 	int		ctx_loss_cnt;
 
 
 	int irq;
 	int irq;
-	struct clk *dss_clk;
 
 
 	u32 fifo_size[DISPC_MAX_NR_FIFOS];
 	u32 fifo_size[DISPC_MAX_NR_FIFOS];
 	/* maps which plane is using a fifo. fifo-id -> plane-id */
 	/* maps which plane is using a fifo. fifo-id -> plane-id */
 	int fifo_assignment[DISPC_MAX_NR_FIFOS];
 	int fifo_assignment[DISPC_MAX_NR_FIFOS];
 
 
-	spinlock_t irq_lock;
-	u32 irq_error_mask;
-	struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
-	u32 error_irqs;
-	struct work_struct error_work;
-
 	bool		ctx_valid;
 	bool		ctx_valid;
 	u32		ctx[DISPC_SZ_REGS / sizeof(u32)];
 	u32		ctx[DISPC_SZ_REGS / sizeof(u32)];
 
 
 	const struct dispc_features *feat;
 	const struct dispc_features *feat;
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-	spinlock_t irq_stats_lock;
-	struct dispc_irq_stats irq_stats;
-#endif
 } dispc;
 } dispc;
 
 
 enum omap_color_component {
 enum omap_color_component {
@@ -186,7 +160,7 @@ static const struct {
 	[OMAP_DSS_CHANNEL_DIGIT] = {
 	[OMAP_DSS_CHANNEL_DIGIT] = {
 		.name		= "DIGIT",
 		.name		= "DIGIT",
 		.vsync_irq	= DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN,
 		.vsync_irq	= DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN,
-		.framedone_irq	= 0,
+		.framedone_irq	= DISPC_IRQ_FRAMEDONETV,
 		.sync_lost_irq	= DISPC_IRQ_SYNC_LOST_DIGIT,
 		.sync_lost_irq	= DISPC_IRQ_SYNC_LOST_DIGIT,
 		.reg_desc	= {
 		.reg_desc	= {
 			[DISPC_MGR_FLD_ENABLE]		= { DISPC_CONTROL,  1,  1 },
 			[DISPC_MGR_FLD_ENABLE]		= { DISPC_CONTROL,  1,  1 },
@@ -241,7 +215,6 @@ struct color_conv_coef {
 	int full_range;
 	int full_range;
 };
 };
 
 
-static void _omap_dispc_set_irqs(void);
 static unsigned long dispc_plane_pclk_rate(enum omap_plane plane);
 static unsigned long dispc_plane_pclk_rate(enum omap_plane plane);
 static unsigned long dispc_plane_lclk_rate(enum omap_plane plane);
 static unsigned long dispc_plane_lclk_rate(enum omap_plane plane);
 
 
@@ -374,7 +347,7 @@ static void dispc_save_context(void)
 	if (dss_has_feature(FEAT_CORE_CLK_DIV))
 	if (dss_has_feature(FEAT_CORE_CLK_DIV))
 		SR(DIVISOR);
 		SR(DIVISOR);
 
 
-	dispc.ctx_loss_cnt = dss_get_ctx_loss_count(&dispc.pdev->dev);
+	dispc.ctx_loss_cnt = dss_get_ctx_loss_count();
 	dispc.ctx_valid = true;
 	dispc.ctx_valid = true;
 
 
 	DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
 	DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
@@ -389,7 +362,7 @@ static void dispc_restore_context(void)
 	if (!dispc.ctx_valid)
 	if (!dispc.ctx_valid)
 		return;
 		return;
 
 
-	ctx = dss_get_ctx_loss_count(&dispc.pdev->dev);
+	ctx = dss_get_ctx_loss_count();
 
 
 	if (ctx >= 0 && ctx == dispc.ctx_loss_cnt)
 	if (ctx >= 0 && ctx == dispc.ctx_loss_cnt)
 		return;
 		return;
@@ -496,7 +469,7 @@ static void dispc_restore_context(void)
 	if (dss_has_feature(FEAT_MGR_LCD3))
 	if (dss_has_feature(FEAT_MGR_LCD3))
 		RR(CONTROL3);
 		RR(CONTROL3);
 	/* clear spurious SYNC_LOST_DIGIT interrupts */
 	/* clear spurious SYNC_LOST_DIGIT interrupts */
-	dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
+	dispc_clear_irqstatus(DISPC_IRQ_SYNC_LOST_DIGIT);
 
 
 	/*
 	/*
 	 * enable last so IRQs won't trigger before
 	 * enable last so IRQs won't trigger before
@@ -520,6 +493,7 @@ int dispc_runtime_get(void)
 	WARN_ON(r < 0);
 	WARN_ON(r < 0);
 	return r < 0 ? r : 0;
 	return r < 0 ? r : 0;
 }
 }
+EXPORT_SYMBOL(dispc_runtime_get);
 
 
 void dispc_runtime_put(void)
 void dispc_runtime_put(void)
 {
 {
@@ -530,16 +504,28 @@ void dispc_runtime_put(void)
 	r = pm_runtime_put_sync(&dispc.pdev->dev);
 	r = pm_runtime_put_sync(&dispc.pdev->dev);
 	WARN_ON(r < 0 && r != -ENOSYS);
 	WARN_ON(r < 0 && r != -ENOSYS);
 }
 }
+EXPORT_SYMBOL(dispc_runtime_put);
 
 
 u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
 u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
 {
 {
 	return mgr_desc[channel].vsync_irq;
 	return mgr_desc[channel].vsync_irq;
 }
 }
+EXPORT_SYMBOL(dispc_mgr_get_vsync_irq);
 
 
 u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
 u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
 {
 {
+	if (channel == OMAP_DSS_CHANNEL_DIGIT && dispc.feat->no_framedone_tv)
+		return 0;
+
 	return mgr_desc[channel].framedone_irq;
 	return mgr_desc[channel].framedone_irq;
 }
 }
+EXPORT_SYMBOL(dispc_mgr_get_framedone_irq);
+
+u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel)
+{
+	return mgr_desc[channel].sync_lost_irq;
+}
+EXPORT_SYMBOL(dispc_mgr_get_sync_lost_irq);
 
 
 u32 dispc_wb_get_framedone_irq(void)
 u32 dispc_wb_get_framedone_irq(void)
 {
 {
@@ -550,28 +536,18 @@ bool dispc_mgr_go_busy(enum omap_channel channel)
 {
 {
 	return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
 	return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
 }
 }
+EXPORT_SYMBOL(dispc_mgr_go_busy);
 
 
 void dispc_mgr_go(enum omap_channel channel)
 void dispc_mgr_go(enum omap_channel channel)
 {
 {
-	bool enable_bit, go_bit;
-
-	/* if the channel is not enabled, we don't need GO */
-	enable_bit = mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE) == 1;
-
-	if (!enable_bit)
-		return;
-
-	go_bit = mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
-
-	if (go_bit) {
-		DSSERR("GO bit not down for channel %d\n", channel);
-		return;
-	}
+	WARN_ON(dispc_mgr_is_enabled(channel) == false);
+	WARN_ON(dispc_mgr_go_busy(channel));
 
 
 	DSSDBG("GO %s\n", mgr_desc[channel].name);
 	DSSDBG("GO %s\n", mgr_desc[channel].name);
 
 
 	mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1);
 	mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1);
 }
 }
+EXPORT_SYMBOL(dispc_mgr_go);
 
 
 bool dispc_wb_go_busy(void)
 bool dispc_wb_go_busy(void)
 {
 {
@@ -975,6 +951,7 @@ void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
 	}
 	}
 	dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
 	dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
 }
 }
+EXPORT_SYMBOL(dispc_ovl_set_channel_out);
 
 
 static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
 static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
 {
 {
@@ -1040,7 +1017,7 @@ static void dispc_configure_burst_sizes(void)
 	const int burst_size = BURST_SIZE_X8;
 	const int burst_size = BURST_SIZE_X8;
 
 
 	/* Configure burst size always to maximum size */
 	/* Configure burst size always to maximum size */
-	for (i = 0; i < omap_dss_get_num_overlays(); ++i)
+	for (i = 0; i < dss_feat_get_num_ovls(); ++i)
 		dispc_ovl_set_burst_size(i, burst_size);
 		dispc_ovl_set_burst_size(i, burst_size);
 }
 }
 
 
@@ -1074,7 +1051,7 @@ static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
 }
 }
 
 
 static void dispc_mgr_set_cpr_coef(enum omap_channel channel,
 static void dispc_mgr_set_cpr_coef(enum omap_channel channel,
-		struct omap_dss_cpr_coefs *coefs)
+		const struct omap_dss_cpr_coefs *coefs)
 {
 {
 	u32 coef_r, coef_g, coef_b;
 	u32 coef_r, coef_g, coef_b;
 
 
@@ -1122,7 +1099,9 @@ static void dispc_mgr_set_size(enum omap_channel channel, u16 width,
 {
 {
 	u32 val;
 	u32 val;
 
 
-	val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+	val = FLD_VAL(height - 1, dispc.feat->mgr_height_start, 16) |
+		FLD_VAL(width - 1, dispc.feat->mgr_width_start, 0);
+
 	dispc_write_reg(DISPC_SIZE_MGR(channel), val);
 	dispc_write_reg(DISPC_SIZE_MGR(channel), val);
 }
 }
 
 
@@ -1244,7 +1223,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
 
 
 	if (use_fifomerge) {
 	if (use_fifomerge) {
 		total_fifo_size = 0;
 		total_fifo_size = 0;
-		for (i = 0; i < omap_dss_get_num_overlays(); ++i)
+		for (i = 0; i < dss_feat_get_num_ovls(); ++i)
 			total_fifo_size += dispc_ovl_get_fifo_size(i);
 			total_fifo_size += dispc_ovl_get_fifo_size(i);
 	} else {
 	} else {
 		total_fifo_size = ovl_fifo_size;
 		total_fifo_size = ovl_fifo_size;
@@ -1989,16 +1968,14 @@ static void calc_tiler_rotation_offset(u16 screen_width, u16 width,
  * This function is used to avoid synclosts in OMAP3, because of some
  * This function is used to avoid synclosts in OMAP3, because of some
  * undocumented horizontal position and timing related limitations.
  * undocumented horizontal position and timing related limitations.
  */
  */
-static int check_horiz_timing_omap3(enum omap_plane plane,
+static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk,
 		const struct omap_video_timings *t, u16 pos_x,
 		const struct omap_video_timings *t, u16 pos_x,
 		u16 width, u16 height, u16 out_width, u16 out_height)
 		u16 width, u16 height, u16 out_width, u16 out_height)
 {
 {
-	int DS = DIV_ROUND_UP(height, out_height);
+	const int ds = DIV_ROUND_UP(height, out_height);
 	unsigned long nonactive;
 	unsigned long nonactive;
 	static const u8 limits[3] = { 8, 10, 20 };
 	static const u8 limits[3] = { 8, 10, 20 };
 	u64 val, blank;
 	u64 val, blank;
-	unsigned long pclk = dispc_plane_pclk_rate(plane);
-	unsigned long lclk = dispc_plane_lclk_rate(plane);
 	int i;
 	int i;
 
 
 	nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
 	nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
@@ -2020,8 +1997,8 @@ static int check_horiz_timing_omap3(enum omap_plane plane,
 	 */
 	 */
 	val = div_u64((u64)(nonactive - pos_x) * lclk, pclk);
 	val = div_u64((u64)(nonactive - pos_x) * lclk, pclk);
 	DSSDBG("(nonactive - pos_x) * pcd = %llu max(0, DS - 2) * width = %d\n",
 	DSSDBG("(nonactive - pos_x) * pcd = %llu max(0, DS - 2) * width = %d\n",
-		val, max(0, DS - 2) * width);
-	if (val < max(0, DS - 2) * width)
+		val, max(0, ds - 2) * width);
+	if (val < max(0, ds - 2) * width)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	/*
 	/*
@@ -2031,21 +2008,20 @@ static int check_horiz_timing_omap3(enum omap_plane plane,
 	 */
 	 */
 	val =  div_u64((u64)nonactive * lclk, pclk);
 	val =  div_u64((u64)nonactive * lclk, pclk);
 	DSSDBG("nonactive * pcd  = %llu, max(0, DS - 1) * width = %d\n",
 	DSSDBG("nonactive * pcd  = %llu, max(0, DS - 1) * width = %d\n",
-		val, max(0, DS - 1) * width);
-	if (val < max(0, DS - 1) * width)
+		val, max(0, ds - 1) * width);
+	if (val < max(0, ds - 1) * width)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	return 0;
 	return 0;
 }
 }
 
 
-static unsigned long calc_core_clk_five_taps(enum omap_plane plane,
+static unsigned long calc_core_clk_five_taps(unsigned long pclk,
 		const struct omap_video_timings *mgr_timings, u16 width,
 		const struct omap_video_timings *mgr_timings, u16 width,
 		u16 height, u16 out_width, u16 out_height,
 		u16 height, u16 out_width, u16 out_height,
 		enum omap_color_mode color_mode)
 		enum omap_color_mode color_mode)
 {
 {
 	u32 core_clk = 0;
 	u32 core_clk = 0;
 	u64 tmp;
 	u64 tmp;
-	unsigned long pclk = dispc_plane_pclk_rate(plane);
 
 
 	if (height <= out_height && width <= out_width)
 	if (height <= out_height && width <= out_width)
 		return (unsigned long) pclk;
 		return (unsigned long) pclk;
@@ -2079,22 +2055,19 @@ static unsigned long calc_core_clk_five_taps(enum omap_plane plane,
 	return core_clk;
 	return core_clk;
 }
 }
 
 
-static unsigned long calc_core_clk_24xx(enum omap_plane plane, u16 width,
+static unsigned long calc_core_clk_24xx(unsigned long pclk, u16 width,
 		u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
 		u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
 {
 {
-	unsigned long pclk = dispc_plane_pclk_rate(plane);
-
 	if (height > out_height && width > out_width)
 	if (height > out_height && width > out_width)
 		return pclk * 4;
 		return pclk * 4;
 	else
 	else
 		return pclk * 2;
 		return pclk * 2;
 }
 }
 
 
-static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width,
+static unsigned long calc_core_clk_34xx(unsigned long pclk, u16 width,
 		u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
 		u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
 {
 {
 	unsigned int hf, vf;
 	unsigned int hf, vf;
-	unsigned long pclk = dispc_plane_pclk_rate(plane);
 
 
 	/*
 	/*
 	 * FIXME how to determine the 'A' factor
 	 * FIXME how to determine the 'A' factor
@@ -2117,11 +2090,9 @@ static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width,
 	return pclk * vf * hf;
 	return pclk * vf * hf;
 }
 }
 
 
-static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width,
+static unsigned long calc_core_clk_44xx(unsigned long pclk, u16 width,
 		u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
 		u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
 {
 {
-	unsigned long pclk;
-
 	/*
 	/*
 	 * If the overlay/writeback is in mem to mem mode, there are no
 	 * If the overlay/writeback is in mem to mem mode, there are no
 	 * downscaling limitations with respect to pixel clock, return 1 as
 	 * downscaling limitations with respect to pixel clock, return 1 as
@@ -2131,15 +2102,13 @@ static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width,
 	if (mem_to_mem)
 	if (mem_to_mem)
 		return 1;
 		return 1;
 
 
-	pclk = dispc_plane_pclk_rate(plane);
-
 	if (width > out_width)
 	if (width > out_width)
 		return DIV_ROUND_UP(pclk, out_width) * width;
 		return DIV_ROUND_UP(pclk, out_width) * width;
 	else
 	else
 		return pclk;
 		return pclk;
 }
 }
 
 
-static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
+static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk,
 		const struct omap_video_timings *mgr_timings,
 		const struct omap_video_timings *mgr_timings,
 		u16 width, u16 height, u16 out_width, u16 out_height,
 		u16 width, u16 height, u16 out_width, u16 out_height,
 		enum omap_color_mode color_mode, bool *five_taps,
 		enum omap_color_mode color_mode, bool *five_taps,
@@ -2157,7 +2126,7 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
 	do {
 	do {
 		in_height = DIV_ROUND_UP(height, *decim_y);
 		in_height = DIV_ROUND_UP(height, *decim_y);
 		in_width = DIV_ROUND_UP(width, *decim_x);
 		in_width = DIV_ROUND_UP(width, *decim_x);
-		*core_clk = dispc.feat->calc_core_clk(plane, in_width,
+		*core_clk = dispc.feat->calc_core_clk(pclk, in_width,
 				in_height, out_width, out_height, mem_to_mem);
 				in_height, out_width, out_height, mem_to_mem);
 		error = (in_width > maxsinglelinewidth || !*core_clk ||
 		error = (in_width > maxsinglelinewidth || !*core_clk ||
 			*core_clk > dispc_core_clk_rate());
 			*core_clk > dispc_core_clk_rate());
@@ -2180,7 +2149,7 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
 	return 0;
 	return 0;
 }
 }
 
 
-static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
+static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk,
 		const struct omap_video_timings *mgr_timings,
 		const struct omap_video_timings *mgr_timings,
 		u16 width, u16 height, u16 out_width, u16 out_height,
 		u16 width, u16 height, u16 out_width, u16 out_height,
 		enum omap_color_mode color_mode, bool *five_taps,
 		enum omap_color_mode color_mode, bool *five_taps,
@@ -2196,10 +2165,10 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
 	do {
 	do {
 		in_height = DIV_ROUND_UP(height, *decim_y);
 		in_height = DIV_ROUND_UP(height, *decim_y);
 		in_width = DIV_ROUND_UP(width, *decim_x);
 		in_width = DIV_ROUND_UP(width, *decim_x);
-		*core_clk = calc_core_clk_five_taps(plane, mgr_timings,
+		*core_clk = calc_core_clk_five_taps(pclk, mgr_timings,
 			in_width, in_height, out_width, out_height, color_mode);
 			in_width, in_height, out_width, out_height, color_mode);
 
 
-		error = check_horiz_timing_omap3(plane, mgr_timings,
+		error = check_horiz_timing_omap3(pclk, lclk, mgr_timings,
 				pos_x, in_width, in_height, out_width,
 				pos_x, in_width, in_height, out_width,
 				out_height);
 				out_height);
 
 
@@ -2208,7 +2177,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
 						in_height < out_height * 2)
 						in_height < out_height * 2)
 				*five_taps = false;
 				*five_taps = false;
 		if (!*five_taps)
 		if (!*five_taps)
-			*core_clk = dispc.feat->calc_core_clk(plane, in_width,
+			*core_clk = dispc.feat->calc_core_clk(pclk, in_width,
 					in_height, out_width, out_height,
 					in_height, out_width, out_height,
 					mem_to_mem);
 					mem_to_mem);
 
 
@@ -2227,8 +2196,8 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
 		}
 		}
 	} while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
 	} while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
 
 
-	if (check_horiz_timing_omap3(plane, mgr_timings, pos_x, width, height,
-		out_width, out_height)){
+	if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, width,
+				height, out_width, out_height)){
 			DSSERR("horizontal timing too tight\n");
 			DSSERR("horizontal timing too tight\n");
 			return -EINVAL;
 			return -EINVAL;
 	}
 	}
@@ -2246,7 +2215,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
 	return 0;
 	return 0;
 }
 }
 
 
-static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
+static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk,
 		const struct omap_video_timings *mgr_timings,
 		const struct omap_video_timings *mgr_timings,
 		u16 width, u16 height, u16 out_width, u16 out_height,
 		u16 width, u16 height, u16 out_width, u16 out_height,
 		enum omap_color_mode color_mode, bool *five_taps,
 		enum omap_color_mode color_mode, bool *five_taps,
@@ -2258,14 +2227,14 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
 	u16 in_height = DIV_ROUND_UP(height, *decim_y);
 	u16 in_height = DIV_ROUND_UP(height, *decim_y);
 	const int maxsinglelinewidth =
 	const int maxsinglelinewidth =
 				dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
 				dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
-	unsigned long pclk = dispc_plane_pclk_rate(plane);
 	const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
 	const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
 
 
-	if (mem_to_mem)
-		in_width_max = DIV_ROUND_UP(out_width, maxdownscale);
-	else
+	if (mem_to_mem) {
+		in_width_max = out_width * maxdownscale;
+	} else {
 		in_width_max = dispc_core_clk_rate() /
 		in_width_max = dispc_core_clk_rate() /
 					DIV_ROUND_UP(pclk, out_width);
 					DIV_ROUND_UP(pclk, out_width);
+	}
 
 
 	*decim_x = DIV_ROUND_UP(width, in_width_max);
 	*decim_x = DIV_ROUND_UP(width, in_width_max);
 
 
@@ -2283,12 +2252,12 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	*core_clk = dispc.feat->calc_core_clk(plane, in_width, in_height,
+	*core_clk = dispc.feat->calc_core_clk(pclk, in_width, in_height,
 				out_width, out_height, mem_to_mem);
 				out_width, out_height, mem_to_mem);
 	return 0;
 	return 0;
 }
 }
 
 
-static int dispc_ovl_calc_scaling(enum omap_plane plane,
+static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
 		enum omap_overlay_caps caps,
 		enum omap_overlay_caps caps,
 		const struct omap_video_timings *mgr_timings,
 		const struct omap_video_timings *mgr_timings,
 		u16 width, u16 height, u16 out_width, u16 out_height,
 		u16 width, u16 height, u16 out_width, u16 out_height,
@@ -2307,9 +2276,14 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
 	if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
 	if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	*x_predecim = max_decim_limit;
-	*y_predecim = (rotation_type == OMAP_DSS_ROT_TILER &&
-			dss_has_feature(FEAT_BURST_2D)) ? 2 : max_decim_limit;
+	if (mem_to_mem) {
+		*x_predecim = *y_predecim = 1;
+	} else {
+		*x_predecim = max_decim_limit;
+		*y_predecim = (rotation_type == OMAP_DSS_ROT_TILER &&
+				dss_has_feature(FEAT_BURST_2D)) ?
+				2 : max_decim_limit;
+	}
 
 
 	if (color_mode == OMAP_DSS_COLOR_CLUT1 ||
 	if (color_mode == OMAP_DSS_COLOR_CLUT1 ||
 	    color_mode == OMAP_DSS_COLOR_CLUT2 ||
 	    color_mode == OMAP_DSS_COLOR_CLUT2 ||
@@ -2330,7 +2304,7 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
 	if (decim_y > *y_predecim || out_height > height * 8)
 	if (decim_y > *y_predecim || out_height > height * 8)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	ret = dispc.feat->calc_scaling(plane, mgr_timings, width, height,
+	ret = dispc.feat->calc_scaling(pclk, lclk, mgr_timings, width, height,
 		out_width, out_height, color_mode, five_taps,
 		out_width, out_height, color_mode, five_taps,
 		x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk,
 		x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk,
 		mem_to_mem);
 		mem_to_mem);
@@ -2353,6 +2327,47 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
 	return 0;
 	return 0;
 }
 }
 
 
+int dispc_ovl_check(enum omap_plane plane, enum omap_channel channel,
+		const struct omap_overlay_info *oi,
+		const struct omap_video_timings *timings,
+		int *x_predecim, int *y_predecim)
+{
+	enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
+	bool five_taps = true;
+	bool fieldmode = 0;
+	u16 in_height = oi->height;
+	u16 in_width = oi->width;
+	bool ilace = timings->interlace;
+	u16 out_width, out_height;
+	int pos_x = oi->pos_x;
+	unsigned long pclk = dispc_mgr_pclk_rate(channel);
+	unsigned long lclk = dispc_mgr_lclk_rate(channel);
+
+	out_width = oi->out_width == 0 ? oi->width : oi->out_width;
+	out_height = oi->out_height == 0 ? oi->height : oi->out_height;
+
+	if (ilace && oi->height == out_height)
+		fieldmode = 1;
+
+	if (ilace) {
+		if (fieldmode)
+			in_height /= 2;
+		out_height /= 2;
+
+		DSSDBG("adjusting for ilace: height %d, out_height %d\n",
+				in_height, out_height);
+	}
+
+	if (!dss_feat_color_mode_supported(plane, oi->color_mode))
+		return -EINVAL;
+
+	return dispc_ovl_calc_scaling(pclk, lclk, caps, timings, in_width,
+			in_height, out_width, out_height, oi->color_mode,
+			&five_taps, x_predecim, y_predecim, pos_x,
+			oi->rotation_type, false);
+}
+EXPORT_SYMBOL(dispc_ovl_check);
+
 static int dispc_ovl_setup_common(enum omap_plane plane,
 static int dispc_ovl_setup_common(enum omap_plane plane,
 		enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr,
 		enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr,
 		u16 screen_width, int pos_x, int pos_y, u16 width, u16 height,
 		u16 screen_width, int pos_x, int pos_y, u16 width, u16 height,
@@ -2368,12 +2383,14 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
 	unsigned offset0, offset1;
 	unsigned offset0, offset1;
 	s32 row_inc;
 	s32 row_inc;
 	s32 pix_inc;
 	s32 pix_inc;
-	u16 frame_height = height;
+	u16 frame_width, frame_height;
 	unsigned int field_offset = 0;
 	unsigned int field_offset = 0;
 	u16 in_height = height;
 	u16 in_height = height;
 	u16 in_width = width;
 	u16 in_width = width;
 	int x_predecim = 1, y_predecim = 1;
 	int x_predecim = 1, y_predecim = 1;
 	bool ilace = mgr_timings->interlace;
 	bool ilace = mgr_timings->interlace;
+	unsigned long pclk = dispc_plane_pclk_rate(plane);
+	unsigned long lclk = dispc_plane_lclk_rate(plane);
 
 
 	if (paddr == 0)
 	if (paddr == 0)
 		return -EINVAL;
 		return -EINVAL;
@@ -2398,7 +2415,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
 	if (!dss_feat_color_mode_supported(plane, color_mode))
 	if (!dss_feat_color_mode_supported(plane, color_mode))
 		return -EINVAL;
 		return -EINVAL;
 
 
-	r = dispc_ovl_calc_scaling(plane, caps, mgr_timings, in_width,
+	r = dispc_ovl_calc_scaling(pclk, lclk, caps, mgr_timings, in_width,
 			in_height, out_width, out_height, color_mode,
 			in_height, out_width, out_height, color_mode,
 			&five_taps, &x_predecim, &y_predecim, pos_x,
 			&five_taps, &x_predecim, &y_predecim, pos_x,
 			rotation_type, mem_to_mem);
 			rotation_type, mem_to_mem);
@@ -2436,20 +2453,28 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
 	row_inc = 0;
 	row_inc = 0;
 	pix_inc = 0;
 	pix_inc = 0;
 
 
+	if (plane == OMAP_DSS_WB) {
+		frame_width = out_width;
+		frame_height = out_height;
+	} else {
+		frame_width = in_width;
+		frame_height = height;
+	}
+
 	if (rotation_type == OMAP_DSS_ROT_TILER)
 	if (rotation_type == OMAP_DSS_ROT_TILER)
-		calc_tiler_rotation_offset(screen_width, in_width,
+		calc_tiler_rotation_offset(screen_width, frame_width,
 				color_mode, fieldmode, field_offset,
 				color_mode, fieldmode, field_offset,
 				&offset0, &offset1, &row_inc, &pix_inc,
 				&offset0, &offset1, &row_inc, &pix_inc,
 				x_predecim, y_predecim);
 				x_predecim, y_predecim);
 	else if (rotation_type == OMAP_DSS_ROT_DMA)
 	else if (rotation_type == OMAP_DSS_ROT_DMA)
-		calc_dma_rotation_offset(rotation, mirror,
-				screen_width, in_width, frame_height,
+		calc_dma_rotation_offset(rotation, mirror, screen_width,
+				frame_width, frame_height,
 				color_mode, fieldmode, field_offset,
 				color_mode, fieldmode, field_offset,
 				&offset0, &offset1, &row_inc, &pix_inc,
 				&offset0, &offset1, &row_inc, &pix_inc,
 				x_predecim, y_predecim);
 				x_predecim, y_predecim);
 	else
 	else
 		calc_vrfb_rotation_offset(rotation, mirror,
 		calc_vrfb_rotation_offset(rotation, mirror,
-				screen_width, in_width, frame_height,
+				screen_width, frame_width, frame_height,
 				color_mode, fieldmode, field_offset,
 				color_mode, fieldmode, field_offset,
 				&offset0, &offset1, &row_inc, &pix_inc,
 				&offset0, &offset1, &row_inc, &pix_inc,
 				x_predecim, y_predecim);
 				x_predecim, y_predecim);
@@ -2503,7 +2528,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
 		bool mem_to_mem)
 		bool mem_to_mem)
 {
 {
 	int r;
 	int r;
-	struct omap_overlay *ovl = omap_dss_get_overlay(plane);
+	enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
 	enum omap_channel channel;
 	enum omap_channel channel;
 
 
 	channel = dispc_ovl_get_channel_out(plane);
 	channel = dispc_ovl_get_channel_out(plane);
@@ -2514,7 +2539,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
 		oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height,
 		oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height,
 		oi->color_mode, oi->rotation, oi->mirror, channel, replication);
 		oi->color_mode, oi->rotation, oi->mirror, channel, replication);
 
 
-	r = dispc_ovl_setup_common(plane, ovl->caps, oi->paddr, oi->p_uv_addr,
+	r = dispc_ovl_setup_common(plane, caps, oi->paddr, oi->p_uv_addr,
 		oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
 		oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
 		oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
 		oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
 		oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
 		oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
@@ -2522,6 +2547,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
 
 
 	return r;
 	return r;
 }
 }
+EXPORT_SYMBOL(dispc_ovl_setup);
 
 
 int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
 int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
 		bool mem_to_mem, const struct omap_video_timings *mgr_timings)
 		bool mem_to_mem, const struct omap_video_timings *mgr_timings)
@@ -2582,192 +2608,39 @@ int dispc_ovl_enable(enum omap_plane plane, bool enable)
 
 
 	return 0;
 	return 0;
 }
 }
+EXPORT_SYMBOL(dispc_ovl_enable);
 
 
-static void dispc_disable_isr(void *data, u32 mask)
+bool dispc_ovl_enabled(enum omap_plane plane)
 {
 {
-	struct completion *compl = data;
-	complete(compl);
+	return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
 }
 }
+EXPORT_SYMBOL(dispc_ovl_enabled);
 
 
-static void _enable_lcd_out(enum omap_channel channel, bool enable)
+void dispc_mgr_enable(enum omap_channel channel, bool enable)
 {
 {
 	mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable);
 	mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable);
 	/* flush posted write */
 	/* flush posted write */
 	mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
 	mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
 }
 }
-
-static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable)
-{
-	struct completion frame_done_completion;
-	bool is_on;
-	int r;
-	u32 irq;
-
-	/* When we disable LCD output, we need to wait until frame is done.
-	 * Otherwise the DSS is still working, and turning off the clocks
-	 * prevents DSS from going to OFF mode */
-	is_on = mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
-
-	irq = mgr_desc[channel].framedone_irq;
-
-	if (!enable && is_on) {
-		init_completion(&frame_done_completion);
-
-		r = omap_dispc_register_isr(dispc_disable_isr,
-				&frame_done_completion, irq);
-
-		if (r)
-			DSSERR("failed to register FRAMEDONE isr\n");
-	}
-
-	_enable_lcd_out(channel, enable);
-
-	if (!enable && is_on) {
-		if (!wait_for_completion_timeout(&frame_done_completion,
-					msecs_to_jiffies(100)))
-			DSSERR("timeout waiting for FRAME DONE\n");
-
-		r = omap_dispc_unregister_isr(dispc_disable_isr,
-				&frame_done_completion, irq);
-
-		if (r)
-			DSSERR("failed to unregister FRAMEDONE isr\n");
-	}
-}
-
-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)
-{
-	struct completion frame_done_completion;
-	enum dss_hdmi_venc_clk_source_select src;
-	int r, i;
-	u32 irq_mask;
-	int num_irqs;
-
-	if (REG_GET(DISPC_CONTROL, 1, 1) == enable)
-		return;
-
-	src = dss_get_hdmi_venc_clk_source();
-
-	if (enable) {
-		unsigned long flags;
-		/* When we enable digit output, we'll get an extra digit
-		 * sync lost interrupt, that we need to ignore */
-		spin_lock_irqsave(&dispc.irq_lock, flags);
-		dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
-		_omap_dispc_set_irqs();
-		spin_unlock_irqrestore(&dispc.irq_lock, flags);
-	}
-
-	/* When we disable digit output, we need to wait until fields are done.
-	 * Otherwise the DSS is still working, and turning off the clocks
-	 * prevents DSS from going to OFF mode. And when enabling, we need to
-	 * wait for the extra sync losts */
-	init_completion(&frame_done_completion);
-
-	if (src == DSS_HDMI_M_PCLK && enable == false) {
-		irq_mask = DISPC_IRQ_FRAMEDONETV;
-		num_irqs = 1;
-	} else {
-		irq_mask = DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD;
-		/* XXX I understand from TRM that we should only wait for the
-		 * current field to complete. But it seems we have to wait for
-		 * both fields */
-		num_irqs = 2;
-	}
-
-	r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion,
-			irq_mask);
-	if (r)
-		DSSERR("failed to register %x isr\n", irq_mask);
-
-	_enable_digit_out(enable);
-
-	for (i = 0; i < num_irqs; ++i) {
-		if (!wait_for_completion_timeout(&frame_done_completion,
-					msecs_to_jiffies(100)))
-			DSSERR("timeout waiting for digit out to %s\n",
-					enable ? "start" : "stop");
-	}
-
-	r = omap_dispc_unregister_isr(dispc_disable_isr, &frame_done_completion,
-			irq_mask);
-	if (r)
-		DSSERR("failed to unregister %x isr\n", irq_mask);
-
-	if (enable) {
-		unsigned long flags;
-		spin_lock_irqsave(&dispc.irq_lock, flags);
-		dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST_DIGIT;
-		dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
-		_omap_dispc_set_irqs();
-		spin_unlock_irqrestore(&dispc.irq_lock, flags);
-	}
-}
+EXPORT_SYMBOL(dispc_mgr_enable);
 
 
 bool dispc_mgr_is_enabled(enum omap_channel channel)
 bool dispc_mgr_is_enabled(enum omap_channel channel)
 {
 {
 	return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
 	return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
 }
 }
-
-void dispc_mgr_enable(enum omap_channel channel, bool enable)
-{
-	if (dss_mgr_is_lcd(channel))
-		dispc_mgr_enable_lcd_out(channel, enable);
-	else if (channel == OMAP_DSS_CHANNEL_DIGIT)
-		dispc_mgr_enable_digit_out(enable);
-	else
-		BUG();
-}
+EXPORT_SYMBOL(dispc_mgr_is_enabled);
 
 
 void dispc_wb_enable(bool enable)
 void dispc_wb_enable(bool enable)
 {
 {
-	enum omap_plane plane = OMAP_DSS_WB;
-	struct completion frame_done_completion;
-	bool is_on;
-	int r;
-	u32 irq;
-
-	is_on = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
-	irq = DISPC_IRQ_FRAMEDONEWB;
-
-	if (!enable && is_on) {
-		init_completion(&frame_done_completion);
-
-		r = omap_dispc_register_isr(dispc_disable_isr,
-				&frame_done_completion, irq);
-		if (r)
-			DSSERR("failed to register FRAMEDONEWB isr\n");
-	}
-
-	REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
-
-	if (!enable && is_on) {
-		if (!wait_for_completion_timeout(&frame_done_completion,
-					msecs_to_jiffies(100)))
-			DSSERR("timeout waiting for FRAMEDONEWB\n");
-
-		r = omap_dispc_unregister_isr(dispc_disable_isr,
-				&frame_done_completion, irq);
-		if (r)
-			DSSERR("failed to unregister FRAMEDONEWB isr\n");
-	}
+	dispc_ovl_enable(OMAP_DSS_WB, enable);
 }
 }
 
 
 bool dispc_wb_is_enabled(void)
 bool dispc_wb_is_enabled(void)
 {
 {
-	enum omap_plane plane = OMAP_DSS_WB;
-
-	return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
+	return dispc_ovl_enabled(OMAP_DSS_WB);
 }
 }
 
 
-void dispc_lcd_enable_signal_polarity(bool act_high)
+static void dispc_lcd_enable_signal_polarity(bool act_high)
 {
 {
 	if (!dss_has_feature(FEAT_LCDENABLEPOL))
 	if (!dss_has_feature(FEAT_LCDENABLEPOL))
 		return;
 		return;
@@ -2791,13 +2664,13 @@ void dispc_pck_free_enable(bool enable)
 	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
 	REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
 }
 }
 
 
-void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable)
+static void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable)
 {
 {
 	mgr_fld_write(channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable);
 	mgr_fld_write(channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable);
 }
 }
 
 
 
 
-void dispc_mgr_set_lcd_type_tft(enum omap_channel channel)
+static void dispc_mgr_set_lcd_type_tft(enum omap_channel channel)
 {
 {
 	mgr_fld_write(channel, DISPC_MGR_FLD_STNTFT, 1);
 	mgr_fld_write(channel, DISPC_MGR_FLD_STNTFT, 1);
 }
 }
@@ -2840,7 +2713,7 @@ static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch,
 }
 }
 
 
 void dispc_mgr_setup(enum omap_channel channel,
 void dispc_mgr_setup(enum omap_channel channel,
-		struct omap_overlay_manager_info *info)
+		const struct omap_overlay_manager_info *info)
 {
 {
 	dispc_mgr_set_default_color(channel, info->default_color);
 	dispc_mgr_set_default_color(channel, info->default_color);
 	dispc_mgr_set_trans_key(channel, info->trans_key_type, info->trans_key);
 	dispc_mgr_set_trans_key(channel, info->trans_key_type, info->trans_key);
@@ -2852,8 +2725,9 @@ void dispc_mgr_setup(enum omap_channel channel,
 		dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs);
 		dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs);
 	}
 	}
 }
 }
+EXPORT_SYMBOL(dispc_mgr_setup);
 
 
-void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
+static void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
 {
 {
 	int code;
 	int code;
 
 
@@ -2878,7 +2752,7 @@ void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
 	mgr_fld_write(channel, DISPC_MGR_FLD_TFTDATALINES, code);
 	mgr_fld_write(channel, DISPC_MGR_FLD_TFTDATALINES, code);
 }
 }
 
 
-void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
+static void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
 {
 {
 	u32 l;
 	u32 l;
 	int gpout0, gpout1;
 	int gpout0, gpout1;
@@ -2907,15 +2781,33 @@ void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
 	dispc_write_reg(DISPC_CONTROL, l);
 	dispc_write_reg(DISPC_CONTROL, l);
 }
 }
 
 
-void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable)
+static void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable)
 {
 {
 	mgr_fld_write(channel, DISPC_MGR_FLD_STALLMODE, enable);
 	mgr_fld_write(channel, DISPC_MGR_FLD_STALLMODE, enable);
 }
 }
 
 
+void dispc_mgr_set_lcd_config(enum omap_channel channel,
+		const struct dss_lcd_mgr_config *config)
+{
+	dispc_mgr_set_io_pad_mode(config->io_pad_mode);
+
+	dispc_mgr_enable_stallmode(channel, config->stallmode);
+	dispc_mgr_enable_fifohandcheck(channel, config->fifohandcheck);
+
+	dispc_mgr_set_clock_div(channel, &config->clock_info);
+
+	dispc_mgr_set_tft_data_lines(channel, config->video_port_width);
+
+	dispc_lcd_enable_signal_polarity(config->lcden_sig_polarity);
+
+	dispc_mgr_set_lcd_type_tft(channel);
+}
+EXPORT_SYMBOL(dispc_mgr_set_lcd_config);
+
 static bool _dispc_mgr_size_ok(u16 width, u16 height)
 static bool _dispc_mgr_size_ok(u16 width, u16 height)
 {
 {
-	return width <= dss_feat_get_param_max(FEAT_PARAM_MGR_WIDTH) &&
-		height <= dss_feat_get_param_max(FEAT_PARAM_MGR_HEIGHT);
+	return width <= dispc.feat->mgr_width_max &&
+		height <= dispc.feat->mgr_height_max;
 }
 }
 
 
 static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
 static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
@@ -3010,7 +2902,7 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
 
 
 /* change name to mode? */
 /* change name to mode? */
 void dispc_mgr_set_timings(enum omap_channel channel,
 void dispc_mgr_set_timings(enum omap_channel channel,
-		struct omap_video_timings *timings)
+		const struct omap_video_timings *timings)
 {
 {
 	unsigned xtot, ytot;
 	unsigned xtot, ytot;
 	unsigned long ht, vt;
 	unsigned long ht, vt;
@@ -3049,6 +2941,7 @@ void dispc_mgr_set_timings(enum omap_channel channel,
 
 
 	dispc_mgr_set_size(channel, t.x_res, t.y_res);
 	dispc_mgr_set_size(channel, t.x_res, t.y_res);
 }
 }
+EXPORT_SYMBOL(dispc_mgr_set_timings);
 
 
 static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
 static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
 		u16 pck_div)
 		u16 pck_div)
@@ -3076,7 +2969,7 @@ unsigned long dispc_fclk_rate(void)
 
 
 	switch (dss_get_dispc_clk_source()) {
 	switch (dss_get_dispc_clk_source()) {
 	case OMAP_DSS_CLK_SRC_FCK:
 	case OMAP_DSS_CLK_SRC_FCK:
-		r = clk_get_rate(dispc.dss_clk);
+		r = dss_get_dispc_clk_rate();
 		break;
 		break;
 	case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
 	case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
 		dsidev = dsi_get_dsidev_from_id(0);
 		dsidev = dsi_get_dsidev_from_id(0);
@@ -3101,28 +2994,32 @@ unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
 	unsigned long r;
 	unsigned long r;
 	u32 l;
 	u32 l;
 
 
-	l = dispc_read_reg(DISPC_DIVISORo(channel));
+	if (dss_mgr_is_lcd(channel)) {
+		l = dispc_read_reg(DISPC_DIVISORo(channel));
 
 
-	lcd = FLD_GET(l, 23, 16);
+		lcd = FLD_GET(l, 23, 16);
 
 
-	switch (dss_get_lcd_clk_source(channel)) {
-	case OMAP_DSS_CLK_SRC_FCK:
-		r = clk_get_rate(dispc.dss_clk);
-		break;
-	case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
-		dsidev = dsi_get_dsidev_from_id(0);
-		r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
-		break;
-	case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
-		dsidev = dsi_get_dsidev_from_id(1);
-		r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
-		break;
-	default:
-		BUG();
-		return 0;
-	}
+		switch (dss_get_lcd_clk_source(channel)) {
+		case OMAP_DSS_CLK_SRC_FCK:
+			r = dss_get_dispc_clk_rate();
+			break;
+		case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
+			dsidev = dsi_get_dsidev_from_id(0);
+			r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
+			break;
+		case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
+			dsidev = dsi_get_dsidev_from_id(1);
+			r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
+			break;
+		default:
+			BUG();
+			return 0;
+		}
 
 
-	return r / lcd;
+		return r / lcd;
+	} else {
+		return dispc_fclk_rate();
+	}
 }
 }
 
 
 unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
 unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
@@ -3172,21 +3069,28 @@ unsigned long dispc_core_clk_rate(void)
 
 
 static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
 static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
 {
 {
-	enum omap_channel channel = dispc_ovl_get_channel_out(plane);
+	enum omap_channel channel;
+
+	if (plane == OMAP_DSS_WB)
+		return 0;
+
+	channel = dispc_ovl_get_channel_out(plane);
 
 
 	return dispc_mgr_pclk_rate(channel);
 	return dispc_mgr_pclk_rate(channel);
 }
 }
 
 
 static unsigned long dispc_plane_lclk_rate(enum omap_plane plane)
 static unsigned long dispc_plane_lclk_rate(enum omap_plane plane)
 {
 {
-	enum omap_channel channel = dispc_ovl_get_channel_out(plane);
+	enum omap_channel channel;
 
 
-	if (dss_mgr_is_lcd(channel))
-		return dispc_mgr_lclk_rate(channel);
-	else
-		return dispc_fclk_rate();
+	if (plane == OMAP_DSS_WB)
+		return 0;
+
+	channel	= dispc_ovl_get_channel_out(plane);
 
 
+	return dispc_mgr_lclk_rate(channel);
 }
 }
+
 static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
 static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
 {
 {
 	int lcd, pcd;
 	int lcd, pcd;
@@ -3244,64 +3148,6 @@ void dispc_dump_clocks(struct seq_file *s)
 	dispc_runtime_put();
 	dispc_runtime_put();
 }
 }
 
 
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-void dispc_dump_irqs(struct seq_file *s)
-{
-	unsigned long flags;
-	struct dispc_irq_stats stats;
-
-	spin_lock_irqsave(&dispc.irq_stats_lock, flags);
-
-	stats = dispc.irq_stats;
-	memset(&dispc.irq_stats, 0, sizeof(dispc.irq_stats));
-	dispc.irq_stats.last_reset = jiffies;
-
-	spin_unlock_irqrestore(&dispc.irq_stats_lock, flags);
-
-	seq_printf(s, "period %u ms\n",
-			jiffies_to_msecs(jiffies - stats.last_reset));
-
-	seq_printf(s, "irqs %d\n", stats.irq_count);
-#define PIS(x) \
-	seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
-
-	PIS(FRAMEDONE);
-	PIS(VSYNC);
-	PIS(EVSYNC_EVEN);
-	PIS(EVSYNC_ODD);
-	PIS(ACBIAS_COUNT_STAT);
-	PIS(PROG_LINE_NUM);
-	PIS(GFX_FIFO_UNDERFLOW);
-	PIS(GFX_END_WIN);
-	PIS(PAL_GAMMA_MASK);
-	PIS(OCP_ERR);
-	PIS(VID1_FIFO_UNDERFLOW);
-	PIS(VID1_END_WIN);
-	PIS(VID2_FIFO_UNDERFLOW);
-	PIS(VID2_END_WIN);
-	if (dss_feat_get_num_ovls() > 3) {
-		PIS(VID3_FIFO_UNDERFLOW);
-		PIS(VID3_END_WIN);
-	}
-	PIS(SYNC_LOST);
-	PIS(SYNC_LOST_DIGIT);
-	PIS(WAKEUP);
-	if (dss_has_feature(FEAT_MGR_LCD2)) {
-		PIS(FRAMEDONE2);
-		PIS(VSYNC2);
-		PIS(ACBIAS_COUNT_STAT2);
-		PIS(SYNC_LOST2);
-	}
-	if (dss_has_feature(FEAT_MGR_LCD3)) {
-		PIS(FRAMEDONE3);
-		PIS(VSYNC3);
-		PIS(ACBIAS_COUNT_STAT3);
-		PIS(SYNC_LOST3);
-	}
-#undef PIS
-}
-#endif
-
 static void dispc_dump_regs(struct seq_file *s)
 static void dispc_dump_regs(struct seq_file *s)
 {
 {
 	int i, j;
 	int i, j;
@@ -3351,7 +3197,7 @@ static void dispc_dump_regs(struct seq_file *s)
 
 
 #define DISPC_REG(i, name) name(i)
 #define DISPC_REG(i, name) name(i)
 #define DUMPREG(i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \
 #define DUMPREG(i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \
-	48 - strlen(#r) - strlen(p_names[i]), " ", \
+	(int)(48 - strlen(#r) - strlen(p_names[i])), " ", \
 	dispc_read_reg(DISPC_REG(i, r)))
 	dispc_read_reg(DISPC_REG(i, r)))
 
 
 	p_names = mgr_names;
 	p_names = mgr_names;
@@ -3428,7 +3274,7 @@ static void dispc_dump_regs(struct seq_file *s)
 #define DISPC_REG(plane, name, i) name(plane, i)
 #define DISPC_REG(plane, name, i) name(plane, i)
 #define DUMPREG(plane, name, i) \
 #define DUMPREG(plane, name, i) \
 	seq_printf(s, "%s_%d(%s)%*s %08x\n", #name, i, p_names[plane], \
 	seq_printf(s, "%s_%d(%s)%*s %08x\n", #name, i, p_names[plane], \
-	46 - strlen(#name) - strlen(p_names[plane]), " ", \
+	(int)(46 - strlen(#name) - strlen(p_names[plane])), " ", \
 	dispc_read_reg(DISPC_REG(plane, name, i)))
 	dispc_read_reg(DISPC_REG(plane, name, i)))
 
 
 	/* Video pipeline coefficient registers */
 	/* Video pipeline coefficient registers */
@@ -3531,7 +3377,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
 }
 }
 
 
 void dispc_mgr_set_clock_div(enum omap_channel channel,
 void dispc_mgr_set_clock_div(enum omap_channel channel,
-		struct dispc_clock_info *cinfo)
+		const struct dispc_clock_info *cinfo)
 {
 {
 	DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);
 	DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);
 	DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div);
 	DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div);
@@ -3555,403 +3401,34 @@ int dispc_mgr_get_clock_div(enum omap_channel channel,
 	return 0;
 	return 0;
 }
 }
 
 
-/* dispc.irq_lock has to be locked by the caller */
-static void _omap_dispc_set_irqs(void)
+u32 dispc_read_irqstatus(void)
 {
 {
-	u32 mask;
-	u32 old_mask;
-	int i;
-	struct omap_dispc_isr_data *isr_data;
-
-	mask = dispc.irq_error_mask;
-
-	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
-		isr_data = &dispc.registered_isr[i];
-
-		if (isr_data->isr == NULL)
-			continue;
-
-		mask |= isr_data->mask;
-	}
-
-	old_mask = dispc_read_reg(DISPC_IRQENABLE);
-	/* clear the irqstatus for newly enabled irqs */
-	dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
-
-	dispc_write_reg(DISPC_IRQENABLE, mask);
-}
-
-int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
-{
-	int i;
-	int ret;
-	unsigned long flags;
-	struct omap_dispc_isr_data *isr_data;
-
-	if (isr == NULL)
-		return -EINVAL;
-
-	spin_lock_irqsave(&dispc.irq_lock, flags);
-
-	/* check for duplicate entry */
-	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
-		isr_data = &dispc.registered_isr[i];
-		if (isr_data->isr == isr && isr_data->arg == arg &&
-				isr_data->mask == mask) {
-			ret = -EINVAL;
-			goto err;
-		}
-	}
-
-	isr_data = NULL;
-	ret = -EBUSY;
-
-	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
-		isr_data = &dispc.registered_isr[i];
-
-		if (isr_data->isr != NULL)
-			continue;
-
-		isr_data->isr = isr;
-		isr_data->arg = arg;
-		isr_data->mask = mask;
-		ret = 0;
-
-		break;
-	}
-
-	if (ret)
-		goto err;
-
-	_omap_dispc_set_irqs();
-
-	spin_unlock_irqrestore(&dispc.irq_lock, flags);
-
-	return 0;
-err:
-	spin_unlock_irqrestore(&dispc.irq_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(omap_dispc_register_isr);
-
-int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
-{
-	int i;
-	unsigned long flags;
-	int ret = -EINVAL;
-	struct omap_dispc_isr_data *isr_data;
-
-	spin_lock_irqsave(&dispc.irq_lock, flags);
-
-	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
-		isr_data = &dispc.registered_isr[i];
-		if (isr_data->isr != isr || isr_data->arg != arg ||
-				isr_data->mask != mask)
-			continue;
-
-		/* found the correct isr */
-
-		isr_data->isr = NULL;
-		isr_data->arg = NULL;
-		isr_data->mask = 0;
-
-		ret = 0;
-		break;
-	}
-
-	if (ret == 0)
-		_omap_dispc_set_irqs();
-
-	spin_unlock_irqrestore(&dispc.irq_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(omap_dispc_unregister_isr);
-
-#ifdef DEBUG
-static void print_irq_status(u32 status)
-{
-	if ((status & dispc.irq_error_mask) == 0)
-		return;
-
-	printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status);
-
-#define PIS(x) \
-	if (status & DISPC_IRQ_##x) \
-		printk(#x " ");
-	PIS(GFX_FIFO_UNDERFLOW);
-	PIS(OCP_ERR);
-	PIS(VID1_FIFO_UNDERFLOW);
-	PIS(VID2_FIFO_UNDERFLOW);
-	if (dss_feat_get_num_ovls() > 3)
-		PIS(VID3_FIFO_UNDERFLOW);
-	PIS(SYNC_LOST);
-	PIS(SYNC_LOST_DIGIT);
-	if (dss_has_feature(FEAT_MGR_LCD2))
-		PIS(SYNC_LOST2);
-	if (dss_has_feature(FEAT_MGR_LCD3))
-		PIS(SYNC_LOST3);
-#undef PIS
-
-	printk("\n");
-}
-#endif
-
-/* Called from dss.c. Note that we don't touch clocks here,
- * but we presume they are on because we got an IRQ. However,
- * an irq handler may turn the clocks off, so we may not have
- * clock later in the function. */
-static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
-{
-	int i;
-	u32 irqstatus, irqenable;
-	u32 handledirqs = 0;
-	u32 unhandled_errors;
-	struct omap_dispc_isr_data *isr_data;
-	struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
-
-	spin_lock(&dispc.irq_lock);
-
-	irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
-	irqenable = dispc_read_reg(DISPC_IRQENABLE);
-
-	/* IRQ is not for us */
-	if (!(irqstatus & irqenable)) {
-		spin_unlock(&dispc.irq_lock);
-		return IRQ_NONE;
-	}
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-	spin_lock(&dispc.irq_stats_lock);
-	dispc.irq_stats.irq_count++;
-	dss_collect_irq_stats(irqstatus, dispc.irq_stats.irqs);
-	spin_unlock(&dispc.irq_stats_lock);
-#endif
-
-#ifdef DEBUG
-	if (dss_debug)
-		print_irq_status(irqstatus);
-#endif
-	/* Ack the interrupt. Do it here before clocks are possibly turned
-	 * off */
-	dispc_write_reg(DISPC_IRQSTATUS, irqstatus);
-	/* flush posted write */
-	dispc_read_reg(DISPC_IRQSTATUS);
-
-	/* make a copy and unlock, so that isrs can unregister
-	 * themselves */
-	memcpy(registered_isr, dispc.registered_isr,
-			sizeof(registered_isr));
-
-	spin_unlock(&dispc.irq_lock);
-
-	for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
-		isr_data = &registered_isr[i];
-
-		if (!isr_data->isr)
-			continue;
-
-		if (isr_data->mask & irqstatus) {
-			isr_data->isr(isr_data->arg, irqstatus);
-			handledirqs |= isr_data->mask;
-		}
-	}
-
-	spin_lock(&dispc.irq_lock);
-
-	unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask;
-
-	if (unhandled_errors) {
-		dispc.error_irqs |= unhandled_errors;
-
-		dispc.irq_error_mask &= ~unhandled_errors;
-		_omap_dispc_set_irqs();
-
-		schedule_work(&dispc.error_work);
-	}
-
-	spin_unlock(&dispc.irq_lock);
-
-	return IRQ_HANDLED;
-}
-
-static void dispc_error_worker(struct work_struct *work)
-{
-	int i;
-	u32 errors;
-	unsigned long flags;
-	static const unsigned fifo_underflow_bits[] = {
-		DISPC_IRQ_GFX_FIFO_UNDERFLOW,
-		DISPC_IRQ_VID1_FIFO_UNDERFLOW,
-		DISPC_IRQ_VID2_FIFO_UNDERFLOW,
-		DISPC_IRQ_VID3_FIFO_UNDERFLOW,
-	};
-
-	spin_lock_irqsave(&dispc.irq_lock, flags);
-	errors = dispc.error_irqs;
-	dispc.error_irqs = 0;
-	spin_unlock_irqrestore(&dispc.irq_lock, flags);
-
-	dispc_runtime_get();
-
-	for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
-		struct omap_overlay *ovl;
-		unsigned bit;
-
-		ovl = omap_dss_get_overlay(i);
-		bit = fifo_underflow_bits[i];
-
-		if (bit & errors) {
-			DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n",
-					ovl->name);
-			dispc_ovl_enable(ovl->id, false);
-			dispc_mgr_go(ovl->manager->id);
-			msleep(50);
-		}
-	}
-
-	for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
-		struct omap_overlay_manager *mgr;
-		unsigned bit;
-
-		mgr = omap_dss_get_overlay_manager(i);
-		bit = mgr_desc[i].sync_lost_irq;
-
-		if (bit & errors) {
-			struct omap_dss_device *dssdev = mgr->get_device(mgr);
-			bool enable;
-
-			DSSERR("SYNC_LOST on channel %s, restarting the output "
-					"with video overlays disabled\n",
-					mgr->name);
-
-			enable = dssdev->state == OMAP_DSS_DISPLAY_ACTIVE;
-			dssdev->driver->disable(dssdev);
-
-			for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
-				struct omap_overlay *ovl;
-				ovl = omap_dss_get_overlay(i);
-
-				if (ovl->id != OMAP_DSS_GFX &&
-						ovl->manager == mgr)
-					dispc_ovl_enable(ovl->id, false);
-			}
-
-			dispc_mgr_go(mgr->id);
-			msleep(50);
-
-			if (enable)
-				dssdev->driver->enable(dssdev);
-		}
-	}
-
-	if (errors & DISPC_IRQ_OCP_ERR) {
-		DSSERR("OCP_ERR\n");
-		for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
-			struct omap_overlay_manager *mgr;
-			struct omap_dss_device *dssdev;
-
-			mgr = omap_dss_get_overlay_manager(i);
-			dssdev = mgr->get_device(mgr);
-
-			if (dssdev && dssdev->driver)
-				dssdev->driver->disable(dssdev);
-		}
-	}
-
-	spin_lock_irqsave(&dispc.irq_lock, flags);
-	dispc.irq_error_mask |= errors;
-	_omap_dispc_set_irqs();
-	spin_unlock_irqrestore(&dispc.irq_lock, flags);
-
-	dispc_runtime_put();
+	return dispc_read_reg(DISPC_IRQSTATUS);
 }
 }
+EXPORT_SYMBOL(dispc_read_irqstatus);
 
 
-int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
+void dispc_clear_irqstatus(u32 mask)
 {
 {
-	void dispc_irq_wait_handler(void *data, u32 mask)
-	{
-		complete((struct completion *)data);
-	}
-
-	int r;
-	DECLARE_COMPLETION_ONSTACK(completion);
-
-	r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
-			irqmask);
-
-	if (r)
-		return r;
-
-	timeout = wait_for_completion_timeout(&completion, timeout);
-
-	omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
-
-	if (timeout == 0)
-		return -ETIMEDOUT;
-
-	if (timeout == -ERESTARTSYS)
-		return -ERESTARTSYS;
-
-	return 0;
+	dispc_write_reg(DISPC_IRQSTATUS, mask);
 }
 }
+EXPORT_SYMBOL(dispc_clear_irqstatus);
 
 
-int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
-		unsigned long timeout)
+u32 dispc_read_irqenable(void)
 {
 {
-	void dispc_irq_wait_handler(void *data, u32 mask)
-	{
-		complete((struct completion *)data);
-	}
-
-	int r;
-	DECLARE_COMPLETION_ONSTACK(completion);
-
-	r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
-			irqmask);
-
-	if (r)
-		return r;
-
-	timeout = wait_for_completion_interruptible_timeout(&completion,
-			timeout);
-
-	omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
-
-	if (timeout == 0)
-		return -ETIMEDOUT;
-
-	if (timeout == -ERESTARTSYS)
-		return -ERESTARTSYS;
-
-	return 0;
+	return dispc_read_reg(DISPC_IRQENABLE);
 }
 }
+EXPORT_SYMBOL(dispc_read_irqenable);
 
 
-static void _omap_dispc_initialize_irq(void)
+void dispc_write_irqenable(u32 mask)
 {
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&dispc.irq_lock, flags);
-
-	memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr));
-
-	dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
-	if (dss_has_feature(FEAT_MGR_LCD2))
-		dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
-	if (dss_has_feature(FEAT_MGR_LCD3))
-		dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST3;
-	if (dss_feat_get_num_ovls() > 3)
-		dispc.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;
-
-	/* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
-	 * so clear it */
-	dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS));
+	u32 old_mask = dispc_read_reg(DISPC_IRQENABLE);
 
 
-	_omap_dispc_set_irqs();
+	/* clear the irqstatus for newly enabled irqs */
+	dispc_clear_irqstatus((mask ^ old_mask) & mask);
 
 
-	spin_unlock_irqrestore(&dispc.irq_lock, flags);
+	dispc_write_reg(DISPC_IRQENABLE, mask);
 }
 }
+EXPORT_SYMBOL(dispc_write_irqenable);
 
 
 void dispc_enable_sidle(void)
 void dispc_enable_sidle(void)
 {
 {
@@ -3998,9 +3475,14 @@ static const struct dispc_features omap24xx_dispc_feats __initconst = {
 	.sw_max			=	64,
 	.sw_max			=	64,
 	.vp_max			=	255,
 	.vp_max			=	255,
 	.hp_max			=	256,
 	.hp_max			=	256,
+	.mgr_width_start	=	10,
+	.mgr_height_start	=	26,
+	.mgr_width_max		=	2048,
+	.mgr_height_max		=	2048,
 	.calc_scaling		=	dispc_ovl_calc_scaling_24xx,
 	.calc_scaling		=	dispc_ovl_calc_scaling_24xx,
 	.calc_core_clk		=	calc_core_clk_24xx,
 	.calc_core_clk		=	calc_core_clk_24xx,
 	.num_fifos		=	3,
 	.num_fifos		=	3,
+	.no_framedone_tv	=	true,
 };
 };
 
 
 static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
 static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
@@ -4010,9 +3492,14 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
 	.sw_max			=	64,
 	.sw_max			=	64,
 	.vp_max			=	255,
 	.vp_max			=	255,
 	.hp_max			=	256,
 	.hp_max			=	256,
+	.mgr_width_start	=	10,
+	.mgr_height_start	=	26,
+	.mgr_width_max		=	2048,
+	.mgr_height_max		=	2048,
 	.calc_scaling		=	dispc_ovl_calc_scaling_34xx,
 	.calc_scaling		=	dispc_ovl_calc_scaling_34xx,
 	.calc_core_clk		=	calc_core_clk_34xx,
 	.calc_core_clk		=	calc_core_clk_34xx,
 	.num_fifos		=	3,
 	.num_fifos		=	3,
+	.no_framedone_tv	=	true,
 };
 };
 
 
 static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
 static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
@@ -4022,9 +3509,14 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
 	.sw_max			=	256,
 	.sw_max			=	256,
 	.vp_max			=	4095,
 	.vp_max			=	4095,
 	.hp_max			=	4096,
 	.hp_max			=	4096,
+	.mgr_width_start	=	10,
+	.mgr_height_start	=	26,
+	.mgr_width_max		=	2048,
+	.mgr_height_max		=	2048,
 	.calc_scaling		=	dispc_ovl_calc_scaling_34xx,
 	.calc_scaling		=	dispc_ovl_calc_scaling_34xx,
 	.calc_core_clk		=	calc_core_clk_34xx,
 	.calc_core_clk		=	calc_core_clk_34xx,
 	.num_fifos		=	3,
 	.num_fifos		=	3,
+	.no_framedone_tv	=	true,
 };
 };
 
 
 static const struct dispc_features omap44xx_dispc_feats __initconst = {
 static const struct dispc_features omap44xx_dispc_feats __initconst = {
@@ -4034,6 +3526,27 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = {
 	.sw_max			=	256,
 	.sw_max			=	256,
 	.vp_max			=	4095,
 	.vp_max			=	4095,
 	.hp_max			=	4096,
 	.hp_max			=	4096,
+	.mgr_width_start	=	10,
+	.mgr_height_start	=	26,
+	.mgr_width_max		=	2048,
+	.mgr_height_max		=	2048,
+	.calc_scaling		=	dispc_ovl_calc_scaling_44xx,
+	.calc_core_clk		=	calc_core_clk_44xx,
+	.num_fifos		=	5,
+	.gfx_fifo_workaround	=	true,
+};
+
+static const struct dispc_features omap54xx_dispc_feats __initconst = {
+	.sw_start		=	7,
+	.fp_start		=	19,
+	.bp_start		=	31,
+	.sw_max			=	256,
+	.vp_max			=	4095,
+	.hp_max			=	4096,
+	.mgr_width_start	=	11,
+	.mgr_height_start	=	27,
+	.mgr_width_max		=	4096,
+	.mgr_height_max		=	4096,
 	.calc_scaling		=	dispc_ovl_calc_scaling_44xx,
 	.calc_scaling		=	dispc_ovl_calc_scaling_44xx,
 	.calc_core_clk		=	calc_core_clk_44xx,
 	.calc_core_clk		=	calc_core_clk_44xx,
 	.num_fifos		=	5,
 	.num_fifos		=	5,
@@ -4042,7 +3555,6 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = {
 
 
 static int __init dispc_init_features(struct platform_device *pdev)
 static int __init dispc_init_features(struct platform_device *pdev)
 {
 {
-	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
 	const struct dispc_features *src;
 	const struct dispc_features *src;
 	struct dispc_features *dst;
 	struct dispc_features *dst;
 
 
@@ -4052,7 +3564,7 @@ static int __init dispc_init_features(struct platform_device *pdev)
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
-	switch (pdata->version) {
+	switch (omapdss_get_version()) {
 	case OMAPDSS_VER_OMAP24xx:
 	case OMAPDSS_VER_OMAP24xx:
 		src = &omap24xx_dispc_feats;
 		src = &omap24xx_dispc_feats;
 		break;
 		break;
@@ -4074,7 +3586,7 @@ static int __init dispc_init_features(struct platform_device *pdev)
 		break;
 		break;
 
 
 	case OMAPDSS_VER_OMAP5:
 	case OMAPDSS_VER_OMAP5:
-		src = &omap44xx_dispc_feats;
+		src = &omap54xx_dispc_feats;
 		break;
 		break;
 
 
 	default:
 	default:
@@ -4087,13 +3599,25 @@ static int __init dispc_init_features(struct platform_device *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
+int dispc_request_irq(irq_handler_t handler, void *dev_id)
+{
+	return devm_request_irq(&dispc.pdev->dev, dispc.irq, handler,
+			     IRQF_SHARED, "OMAP DISPC", dev_id);
+}
+EXPORT_SYMBOL(dispc_request_irq);
+
+void dispc_free_irq(void *dev_id)
+{
+	devm_free_irq(&dispc.pdev->dev, dispc.irq, dev_id);
+}
+EXPORT_SYMBOL(dispc_free_irq);
+
 /* DISPC HW IP initialisation */
 /* DISPC HW IP initialisation */
 static int __init omap_dispchw_probe(struct platform_device *pdev)
 static int __init omap_dispchw_probe(struct platform_device *pdev)
 {
 {
 	u32 rev;
 	u32 rev;
 	int r = 0;
 	int r = 0;
 	struct resource *dispc_mem;
 	struct resource *dispc_mem;
-	struct clk *clk;
 
 
 	dispc.pdev = pdev;
 	dispc.pdev = pdev;
 
 
@@ -4101,15 +3625,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
 	if (r)
 	if (r)
 		return r;
 		return r;
 
 
-	spin_lock_init(&dispc.irq_lock);
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-	spin_lock_init(&dispc.irq_stats_lock);
-	dispc.irq_stats.last_reset = jiffies;
-#endif
-
-	INIT_WORK(&dispc.error_work, dispc_error_worker);
-
 	dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
 	dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
 	if (!dispc_mem) {
 	if (!dispc_mem) {
 		DSSERR("can't get IORESOURCE_MEM DISPC\n");
 		DSSERR("can't get IORESOURCE_MEM DISPC\n");
@@ -4129,22 +3644,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
-	r = devm_request_irq(&pdev->dev, dispc.irq, omap_dispc_irq_handler,
-			     IRQF_SHARED, "OMAP DISPC", dispc.pdev);
-	if (r < 0) {
-		DSSERR("request_irq failed\n");
-		return r;
-	}
-
-	clk = clk_get(&pdev->dev, "fck");
-	if (IS_ERR(clk)) {
-		DSSERR("can't get fck\n");
-		r = PTR_ERR(clk);
-		return r;
-	}
-
-	dispc.dss_clk = clk;
-
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 
 
 	r = dispc_runtime_get();
 	r = dispc_runtime_get();
@@ -4153,8 +3652,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
 
 
 	_omap_dispc_initial_config();
 	_omap_dispc_initial_config();
 
 
-	_omap_dispc_initialize_irq();
-
 	rev = dispc_read_reg(DISPC_REVISION);
 	rev = dispc_read_reg(DISPC_REVISION);
 	dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
 	dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
 	       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
 	       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
@@ -4163,14 +3660,10 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
 
 
 	dss_debugfs_create_file("dispc", dispc_dump_regs);
 	dss_debugfs_create_file("dispc", dispc_dump_regs);
 
 
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-	dss_debugfs_create_file("dispc_irq", dispc_dump_irqs);
-#endif
 	return 0;
 	return 0;
 
 
 err_runtime_get:
 err_runtime_get:
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
-	clk_put(dispc.dss_clk);
 	return r;
 	return r;
 }
 }
 
 
@@ -4178,8 +3671,6 @@ static int __exit omap_dispchw_remove(struct platform_device *pdev)
 {
 {
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 
 
-	clk_put(dispc.dss_clk);
-
 	return 0;
 	return 0;
 }
 }
 
 

+ 321 - 0
drivers/video/omap2/dss/display-sysfs.c

@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "DISPLAY"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+
+#include <video/omapdss.h>
+#include "dss.h"
+#include "dss_features.h"
+
+static ssize_t display_enabled_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct omap_dss_device *dssdev = to_dss_device(dev);
+	bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
+}
+
+static ssize_t display_enabled_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t size)
+{
+	struct omap_dss_device *dssdev = to_dss_device(dev);
+	int r;
+	bool enabled;
+
+	r = strtobool(buf, &enabled);
+	if (r)
+		return r;
+
+	if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
+		if (enabled) {
+			r = dssdev->driver->enable(dssdev);
+			if (r)
+				return r;
+		} else {
+			dssdev->driver->disable(dssdev);
+		}
+	}
+
+	return size;
+}
+
+static ssize_t display_tear_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct omap_dss_device *dssdev = to_dss_device(dev);
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			dssdev->driver->get_te ?
+			dssdev->driver->get_te(dssdev) : 0);
+}
+
+static ssize_t display_tear_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct omap_dss_device *dssdev = to_dss_device(dev);
+	int r;
+	bool te;
+
+	if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
+		return -ENOENT;
+
+	r = strtobool(buf, &te);
+	if (r)
+		return r;
+
+	r = dssdev->driver->enable_te(dssdev, te);
+	if (r)
+		return r;
+
+	return size;
+}
+
+static ssize_t display_timings_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct omap_dss_device *dssdev = to_dss_device(dev);
+	struct omap_video_timings t;
+
+	if (!dssdev->driver->get_timings)
+		return -ENOENT;
+
+	dssdev->driver->get_timings(dssdev, &t);
+
+	return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
+			t.pixel_clock,
+			t.x_res, t.hfp, t.hbp, t.hsw,
+			t.y_res, t.vfp, t.vbp, t.vsw);
+}
+
+static ssize_t display_timings_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct omap_dss_device *dssdev = to_dss_device(dev);
+	struct omap_video_timings t = dssdev->panel.timings;
+	int r, found;
+
+	if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
+		return -ENOENT;
+
+	found = 0;
+#ifdef CONFIG_OMAP2_DSS_VENC
+	if (strncmp("pal", buf, 3) == 0) {
+		t = omap_dss_pal_timings;
+		found = 1;
+	} else if (strncmp("ntsc", buf, 4) == 0) {
+		t = omap_dss_ntsc_timings;
+		found = 1;
+	}
+#endif
+	if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
+				&t.pixel_clock,
+				&t.x_res, &t.hfp, &t.hbp, &t.hsw,
+				&t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
+		return -EINVAL;
+
+	r = dssdev->driver->check_timings(dssdev, &t);
+	if (r)
+		return r;
+
+	dssdev->driver->disable(dssdev);
+	dssdev->driver->set_timings(dssdev, &t);
+	r = dssdev->driver->enable(dssdev);
+	if (r)
+		return r;
+
+	return size;
+}
+
+static ssize_t display_rotate_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct omap_dss_device *dssdev = to_dss_device(dev);
+	int rotate;
+	if (!dssdev->driver->get_rotate)
+		return -ENOENT;
+	rotate = dssdev->driver->get_rotate(dssdev);
+	return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
+}
+
+static ssize_t display_rotate_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct omap_dss_device *dssdev = to_dss_device(dev);
+	int rot, r;
+
+	if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
+		return -ENOENT;
+
+	r = kstrtoint(buf, 0, &rot);
+	if (r)
+		return r;
+
+	r = dssdev->driver->set_rotate(dssdev, rot);
+	if (r)
+		return r;
+
+	return size;
+}
+
+static ssize_t display_mirror_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct omap_dss_device *dssdev = to_dss_device(dev);
+	int mirror;
+	if (!dssdev->driver->get_mirror)
+		return -ENOENT;
+	mirror = dssdev->driver->get_mirror(dssdev);
+	return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
+}
+
+static ssize_t display_mirror_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct omap_dss_device *dssdev = to_dss_device(dev);
+	int r;
+	bool mirror;
+
+	if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
+		return -ENOENT;
+
+	r = strtobool(buf, &mirror);
+	if (r)
+		return r;
+
+	r = dssdev->driver->set_mirror(dssdev, mirror);
+	if (r)
+		return r;
+
+	return size;
+}
+
+static ssize_t display_wss_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct omap_dss_device *dssdev = to_dss_device(dev);
+	unsigned int wss;
+
+	if (!dssdev->driver->get_wss)
+		return -ENOENT;
+
+	wss = dssdev->driver->get_wss(dssdev);
+
+	return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
+}
+
+static ssize_t display_wss_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct omap_dss_device *dssdev = to_dss_device(dev);
+	u32 wss;
+	int r;
+
+	if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
+		return -ENOENT;
+
+	r = kstrtou32(buf, 0, &wss);
+	if (r)
+		return r;
+
+	if (wss > 0xfffff)
+		return -EINVAL;
+
+	r = dssdev->driver->set_wss(dssdev, wss);
+	if (r)
+		return r;
+
+	return size;
+}
+
+static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
+		display_enabled_show, display_enabled_store);
+static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
+		display_tear_show, display_tear_store);
+static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
+		display_timings_show, display_timings_store);
+static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
+		display_rotate_show, display_rotate_store);
+static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
+		display_mirror_show, display_mirror_store);
+static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
+		display_wss_show, display_wss_store);
+
+static struct device_attribute *display_sysfs_attrs[] = {
+	&dev_attr_enabled,
+	&dev_attr_tear_elim,
+	&dev_attr_timings,
+	&dev_attr_rotate,
+	&dev_attr_mirror,
+	&dev_attr_wss,
+	NULL
+};
+
+int display_init_sysfs(struct platform_device *pdev,
+		struct omap_dss_device *dssdev)
+{
+	struct device_attribute *attr;
+	int i, r;
+
+	/* create device sysfs files */
+	i = 0;
+	while ((attr = display_sysfs_attrs[i++]) != NULL) {
+		r = device_create_file(&dssdev->dev, attr);
+		if (r) {
+			for (i = i - 2; i >= 0; i--) {
+				attr = display_sysfs_attrs[i];
+				device_remove_file(&dssdev->dev, attr);
+			}
+
+			DSSERR("failed to create sysfs file\n");
+			return r;
+		}
+	}
+
+	/* create display? sysfs links */
+	r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
+			dev_name(&dssdev->dev));
+	if (r) {
+		while ((attr = display_sysfs_attrs[i++]) != NULL)
+			device_remove_file(&dssdev->dev, attr);
+
+		DSSERR("failed to create sysfs display link\n");
+		return r;
+	}
+
+	return 0;
+}
+
+void display_uninit_sysfs(struct platform_device *pdev,
+		struct omap_dss_device *dssdev)
+{
+	struct device_attribute *attr;
+	int i = 0;
+
+	sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
+
+	while ((attr = display_sysfs_attrs[i++]) != NULL)
+		device_remove_file(&dssdev->dev, attr);
+}

+ 3 - 383
drivers/video/omap2/dss/display.c

@@ -31,250 +31,6 @@
 #include "dss.h"
 #include "dss.h"
 #include "dss_features.h"
 #include "dss_features.h"
 
 
-static ssize_t display_enabled_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct omap_dss_device *dssdev = to_dss_device(dev);
-	bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED;
-
-	return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
-}
-
-static ssize_t display_enabled_store(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf, size_t size)
-{
-	struct omap_dss_device *dssdev = to_dss_device(dev);
-	int r;
-	bool enabled;
-
-	r = strtobool(buf, &enabled);
-	if (r)
-		return r;
-
-	if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
-		if (enabled) {
-			r = dssdev->driver->enable(dssdev);
-			if (r)
-				return r;
-		} else {
-			dssdev->driver->disable(dssdev);
-		}
-	}
-
-	return size;
-}
-
-static ssize_t display_tear_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct omap_dss_device *dssdev = to_dss_device(dev);
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-			dssdev->driver->get_te ?
-			dssdev->driver->get_te(dssdev) : 0);
-}
-
-static ssize_t display_tear_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct omap_dss_device *dssdev = to_dss_device(dev);
-	int r;
-	bool te;
-
-	if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
-		return -ENOENT;
-
-	r = strtobool(buf, &te);
-	if (r)
-		return r;
-
-	r = dssdev->driver->enable_te(dssdev, te);
-	if (r)
-		return r;
-
-	return size;
-}
-
-static ssize_t display_timings_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct omap_dss_device *dssdev = to_dss_device(dev);
-	struct omap_video_timings t;
-
-	if (!dssdev->driver->get_timings)
-		return -ENOENT;
-
-	dssdev->driver->get_timings(dssdev, &t);
-
-	return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
-			t.pixel_clock,
-			t.x_res, t.hfp, t.hbp, t.hsw,
-			t.y_res, t.vfp, t.vbp, t.vsw);
-}
-
-static ssize_t display_timings_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct omap_dss_device *dssdev = to_dss_device(dev);
-	struct omap_video_timings t = dssdev->panel.timings;
-	int r, found;
-
-	if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
-		return -ENOENT;
-
-	found = 0;
-#ifdef CONFIG_OMAP2_DSS_VENC
-	if (strncmp("pal", buf, 3) == 0) {
-		t = omap_dss_pal_timings;
-		found = 1;
-	} else if (strncmp("ntsc", buf, 4) == 0) {
-		t = omap_dss_ntsc_timings;
-		found = 1;
-	}
-#endif
-	if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
-				&t.pixel_clock,
-				&t.x_res, &t.hfp, &t.hbp, &t.hsw,
-				&t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
-		return -EINVAL;
-
-	r = dssdev->driver->check_timings(dssdev, &t);
-	if (r)
-		return r;
-
-	dssdev->driver->disable(dssdev);
-	dssdev->driver->set_timings(dssdev, &t);
-	r = dssdev->driver->enable(dssdev);
-	if (r)
-		return r;
-
-	return size;
-}
-
-static ssize_t display_rotate_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct omap_dss_device *dssdev = to_dss_device(dev);
-	int rotate;
-	if (!dssdev->driver->get_rotate)
-		return -ENOENT;
-	rotate = dssdev->driver->get_rotate(dssdev);
-	return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
-}
-
-static ssize_t display_rotate_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct omap_dss_device *dssdev = to_dss_device(dev);
-	int rot, r;
-
-	if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
-		return -ENOENT;
-
-	r = kstrtoint(buf, 0, &rot);
-	if (r)
-		return r;
-
-	r = dssdev->driver->set_rotate(dssdev, rot);
-	if (r)
-		return r;
-
-	return size;
-}
-
-static ssize_t display_mirror_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct omap_dss_device *dssdev = to_dss_device(dev);
-	int mirror;
-	if (!dssdev->driver->get_mirror)
-		return -ENOENT;
-	mirror = dssdev->driver->get_mirror(dssdev);
-	return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
-}
-
-static ssize_t display_mirror_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct omap_dss_device *dssdev = to_dss_device(dev);
-	int r;
-	bool mirror;
-
-	if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
-		return -ENOENT;
-
-	r = strtobool(buf, &mirror);
-	if (r)
-		return r;
-
-	r = dssdev->driver->set_mirror(dssdev, mirror);
-	if (r)
-		return r;
-
-	return size;
-}
-
-static ssize_t display_wss_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct omap_dss_device *dssdev = to_dss_device(dev);
-	unsigned int wss;
-
-	if (!dssdev->driver->get_wss)
-		return -ENOENT;
-
-	wss = dssdev->driver->get_wss(dssdev);
-
-	return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
-}
-
-static ssize_t display_wss_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
-{
-	struct omap_dss_device *dssdev = to_dss_device(dev);
-	u32 wss;
-	int r;
-
-	if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
-		return -ENOENT;
-
-	r = kstrtou32(buf, 0, &wss);
-	if (r)
-		return r;
-
-	if (wss > 0xfffff)
-		return -EINVAL;
-
-	r = dssdev->driver->set_wss(dssdev, wss);
-	if (r)
-		return r;
-
-	return size;
-}
-
-static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
-		display_enabled_show, display_enabled_store);
-static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
-		display_tear_show, display_tear_store);
-static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
-		display_timings_show, display_timings_store);
-static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
-		display_rotate_show, display_rotate_store);
-static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
-		display_mirror_show, display_mirror_store);
-static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
-		display_wss_show, display_wss_store);
-
-static struct device_attribute *display_sysfs_attrs[] = {
-	&dev_attr_enabled,
-	&dev_attr_tear_elim,
-	&dev_attr_timings,
-	&dev_attr_rotate,
-	&dev_attr_mirror,
-	&dev_attr_wss,
-	NULL
-};
-
 void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
 void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
 			u16 *xres, u16 *yres)
 			u16 *xres, u16 *yres)
 {
 {
@@ -320,136 +76,8 @@ void omapdss_default_get_timings(struct omap_dss_device *dssdev,
 }
 }
 EXPORT_SYMBOL(omapdss_default_get_timings);
 EXPORT_SYMBOL(omapdss_default_get_timings);
 
 
-/*
- * Connect dssdev to a manager if the manager is free or if force is specified.
- * Connect all overlays to that manager if they are free or if force is
- * specified.
- */
-static int dss_init_connections(struct omap_dss_device *dssdev, bool force)
-{
-	struct omap_dss_output *out;
-	struct omap_overlay_manager *mgr;
-	int i, r;
-
-	out = omapdss_get_output_from_dssdev(dssdev);
-
-	WARN_ON(dssdev->output);
-	WARN_ON(out->device);
-
-	r = omapdss_output_set_device(out, dssdev);
-	if (r) {
-		DSSERR("failed to connect output to new device\n");
-		return r;
-	}
-
-	mgr = omap_dss_get_overlay_manager(dssdev->channel);
-
-	if (mgr->output && !force)
-		return 0;
-
-	if (mgr->output)
-		mgr->unset_output(mgr);
-
-	r = mgr->set_output(mgr, out);
-	if (r) {
-		DSSERR("failed to connect manager to output of new device\n");
-
-		/* remove the output-device connection we just made */
-		omapdss_output_unset_device(out);
-		return r;
-	}
-
-	for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
-		struct omap_overlay *ovl = omap_dss_get_overlay(i);
-
-		if (!ovl->manager || force) {
-			if (ovl->manager)
-				ovl->unset_manager(ovl);
-
-			r = ovl->set_manager(ovl, mgr);
-			if (r) {
-				DSSERR("failed to set initial overlay\n");
-				return r;
-			}
-		}
-	}
-
-	return 0;
-}
-
-static void dss_uninit_connections(struct omap_dss_device *dssdev)
-{
-	if (dssdev->output) {
-		struct omap_overlay_manager *mgr = dssdev->output->manager;
-
-		if (mgr)
-			mgr->unset_output(mgr);
-
-		omapdss_output_unset_device(dssdev->output);
-	}
-}
-
-int dss_init_device(struct platform_device *pdev,
-		struct omap_dss_device *dssdev)
-{
-	struct device_attribute *attr;
-	int i, r;
-	const char *def_disp_name = dss_get_default_display_name();
-	bool force;
-
-	force = def_disp_name && strcmp(def_disp_name, dssdev->name) == 0;
-	dss_init_connections(dssdev, force);
-
-	/* create device sysfs files */
-	i = 0;
-	while ((attr = display_sysfs_attrs[i++]) != NULL) {
-		r = device_create_file(&dssdev->dev, attr);
-		if (r) {
-			for (i = i - 2; i >= 0; i--) {
-				attr = display_sysfs_attrs[i];
-				device_remove_file(&dssdev->dev, attr);
-			}
-
-			dss_uninit_connections(dssdev);
-
-			DSSERR("failed to create sysfs file\n");
-			return r;
-		}
-	}
-
-	/* create display? sysfs links */
-	r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
-			dev_name(&dssdev->dev));
-	if (r) {
-		while ((attr = display_sysfs_attrs[i++]) != NULL)
-			device_remove_file(&dssdev->dev, attr);
-
-		dss_uninit_connections(dssdev);
-
-		DSSERR("failed to create sysfs display link\n");
-		return r;
-	}
-
-	return 0;
-}
-
-void dss_uninit_device(struct platform_device *pdev,
-		struct omap_dss_device *dssdev)
-{
-	struct device_attribute *attr;
-	int i = 0;
-
-	sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
-
-	while ((attr = display_sysfs_attrs[i++]) != NULL)
-		device_remove_file(&dssdev->dev, attr);
-
-	dss_uninit_connections(dssdev);
-}
-
 static int dss_suspend_device(struct device *dev, void *data)
 static int dss_suspend_device(struct device *dev, void *data)
 {
 {
-	int r;
 	struct omap_dss_device *dssdev = to_dss_device(dev);
 	struct omap_dss_device *dssdev = to_dss_device(dev);
 
 
 	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
 	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
@@ -457,15 +85,7 @@ static int dss_suspend_device(struct device *dev, void *data)
 		return 0;
 		return 0;
 	}
 	}
 
 
-	if (!dssdev->driver->suspend) {
-		DSSERR("display '%s' doesn't implement suspend\n",
-				dssdev->name);
-		return -ENOSYS;
-	}
-
-	r = dssdev->driver->suspend(dssdev);
-	if (r)
-		return r;
+	dssdev->driver->disable(dssdev);
 
 
 	dssdev->activate_after_resume = true;
 	dssdev->activate_after_resume = true;
 
 
@@ -492,8 +112,8 @@ static int dss_resume_device(struct device *dev, void *data)
 	int r;
 	int r;
 	struct omap_dss_device *dssdev = to_dss_device(dev);
 	struct omap_dss_device *dssdev = to_dss_device(dev);
 
 
-	if (dssdev->activate_after_resume && dssdev->driver->resume) {
-		r = dssdev->driver->resume(dssdev);
+	if (dssdev->activate_after_resume) {
+		r = dssdev->driver->enable(dssdev);
 		if (r)
 		if (r)
 			return r;
 			return r;
 	}
 	}

+ 95 - 31
drivers/video/omap2/dss/dpi.c

@@ -49,34 +49,53 @@ static struct {
 	struct omap_dss_output output;
 	struct omap_dss_output output;
 } dpi;
 } dpi;
 
 
-static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk)
+static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
 {
 {
-	int dsi_module;
-
-	dsi_module = clk == OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ? 0 : 1;
+	/*
+	 * XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL
+	 * would also be used for DISPC fclk. Meaning, when the DPI output is
+	 * disabled, DISPC clock will be disabled, and TV out will stop.
+	 */
+	switch (omapdss_get_version()) {
+	case OMAPDSS_VER_OMAP24xx:
+	case OMAPDSS_VER_OMAP34xx_ES1:
+	case OMAPDSS_VER_OMAP34xx_ES3:
+	case OMAPDSS_VER_OMAP3630:
+	case OMAPDSS_VER_AM35xx:
+		return NULL;
+	default:
+		break;
+	}
 
 
-	return dsi_get_dsidev_from_id(dsi_module);
+	switch (channel) {
+	case OMAP_DSS_CHANNEL_LCD:
+		return dsi_get_dsidev_from_id(0);
+	case OMAP_DSS_CHANNEL_LCD2:
+		return dsi_get_dsidev_from_id(1);
+	default:
+		return NULL;
+	}
 }
 }
 
 
-static bool dpi_use_dsi_pll(struct omap_dss_device *dssdev)
+static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
 {
 {
-	if (dssdev->clocks.dispc.dispc_fclk_src ==
-			OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ||
-			dssdev->clocks.dispc.dispc_fclk_src ==
-			OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC ||
-			dssdev->clocks.dispc.channel.lcd_clk_src ==
-			OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ||
-			dssdev->clocks.dispc.channel.lcd_clk_src ==
-			OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC)
-		return true;
-	else
-		return false;
+	switch (channel) {
+	case OMAP_DSS_CHANNEL_LCD:
+		return OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC;
+	case OMAP_DSS_CHANNEL_LCD2:
+		return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
+	default:
+		/* this shouldn't happen */
+		WARN_ON(1);
+		return OMAP_DSS_CLK_SRC_FCK;
+	}
 }
 }
 
 
 static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
 static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
 		unsigned long pck_req, unsigned long *fck, int *lck_div,
 		unsigned long pck_req, unsigned long *fck, int *lck_div,
 		int *pck_div)
 		int *pck_div)
 {
 {
+	struct omap_overlay_manager *mgr = dssdev->output->manager;
 	struct dsi_clock_info dsi_cinfo;
 	struct dsi_clock_info dsi_cinfo;
 	struct dispc_clock_info dispc_cinfo;
 	struct dispc_clock_info dispc_cinfo;
 	int r;
 	int r;
@@ -90,7 +109,8 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
 	if (r)
 	if (r)
 		return r;
 		return r;
 
 
-	dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
+	dss_select_lcd_clk_source(mgr->id,
+			dpi_get_alt_clk_src(mgr->id));
 
 
 	dpi.mgr_config.clock_info = dispc_cinfo;
 	dpi.mgr_config.clock_info = dispc_cinfo;
 
 
@@ -135,7 +155,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
 	unsigned long pck;
 	unsigned long pck;
 	int r = 0;
 	int r = 0;
 
 
-	if (dpi_use_dsi_pll(dssdev))
+	if (dpi.dsidev)
 		r = dpi_set_dsi_clk(dssdev, t->pixel_clock * 1000, &fck,
 		r = dpi_set_dsi_clk(dssdev, t->pixel_clock * 1000, &fck,
 				&lck_div, &pck_div);
 				&lck_div, &pck_div);
 	else
 	else
@@ -214,7 +234,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 	if (r)
 	if (r)
 		goto err_src_sel;
 		goto err_src_sel;
 
 
-	if (dpi_use_dsi_pll(dssdev)) {
+	if (dpi.dsidev) {
 		r = dsi_runtime_get(dpi.dsidev);
 		r = dsi_runtime_get(dpi.dsidev);
 		if (r)
 		if (r)
 			goto err_get_dsi;
 			goto err_get_dsi;
@@ -242,10 +262,10 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 
 
 err_mgr_enable:
 err_mgr_enable:
 err_set_mode:
 err_set_mode:
-	if (dpi_use_dsi_pll(dssdev))
+	if (dpi.dsidev)
 		dsi_pll_uninit(dpi.dsidev, true);
 		dsi_pll_uninit(dpi.dsidev, true);
 err_dsi_pll_init:
 err_dsi_pll_init:
-	if (dpi_use_dsi_pll(dssdev))
+	if (dpi.dsidev)
 		dsi_runtime_put(dpi.dsidev);
 		dsi_runtime_put(dpi.dsidev);
 err_get_dsi:
 err_get_dsi:
 err_src_sel:
 err_src_sel:
@@ -271,8 +291,8 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
 
 
 	dss_mgr_disable(mgr);
 	dss_mgr_disable(mgr);
 
 
-	if (dpi_use_dsi_pll(dssdev)) {
-		dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
+	if (dpi.dsidev) {
+		dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
 		dsi_pll_uninit(dpi.dsidev, true);
 		dsi_pll_uninit(dpi.dsidev, true);
 		dsi_runtime_put(dpi.dsidev);
 		dsi_runtime_put(dpi.dsidev);
 	}
 	}
@@ -311,13 +331,13 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
 	unsigned long pck;
 	unsigned long pck;
 	struct dispc_clock_info dispc_cinfo;
 	struct dispc_clock_info dispc_cinfo;
 
 
-	if (dss_mgr_check_timings(mgr, timings))
+	if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
 		return -EINVAL;
 		return -EINVAL;
 
 
 	if (timings->pixel_clock == 0)
 	if (timings->pixel_clock == 0)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	if (dpi_use_dsi_pll(dssdev)) {
+	if (dpi.dsidev) {
 		struct dsi_clock_info dsi_cinfo;
 		struct dsi_clock_info dsi_cinfo;
 		r = dsi_pll_calc_clock_div_pck(dpi.dsidev,
 		r = dsi_pll_calc_clock_div_pck(dpi.dsidev,
 				timings->pixel_clock * 1000,
 				timings->pixel_clock * 1000,
@@ -359,8 +379,32 @@ void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
 }
 }
 EXPORT_SYMBOL(omapdss_dpi_set_data_lines);
 EXPORT_SYMBOL(omapdss_dpi_set_data_lines);
 
 
+static int __init dpi_verify_dsi_pll(struct platform_device *dsidev)
+{
+	int r;
+
+	/* do initial setup with the PLL to see if it is operational */
+
+	r = dsi_runtime_get(dsidev);
+	if (r)
+		return r;
+
+	r = dsi_pll_init(dsidev, 0, 1);
+	if (r) {
+		dsi_runtime_put(dsidev);
+		return r;
+	}
+
+	dsi_pll_uninit(dsidev, true);
+	dsi_runtime_put(dsidev);
+
+	return 0;
+}
+
 static int __init dpi_init_display(struct omap_dss_device *dssdev)
 static int __init dpi_init_display(struct omap_dss_device *dssdev)
 {
 {
+	struct platform_device *dsidev;
+
 	DSSDBG("init_display\n");
 	DSSDBG("init_display\n");
 
 
 	if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) &&
 	if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) &&
@@ -377,19 +421,30 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev)
 		dpi.vdds_dsi_reg = vdds_dsi;
 		dpi.vdds_dsi_reg = vdds_dsi;
 	}
 	}
 
 
-	if (dpi_use_dsi_pll(dssdev)) {
-		enum omap_dss_clk_source dispc_fclk_src =
-			dssdev->clocks.dispc.dispc_fclk_src;
-		dpi.dsidev = dpi_get_dsidev(dispc_fclk_src);
+	/*
+	 * XXX We shouldn't need dssdev->channel for this. The dsi pll clock
+	 * source for DPI is SoC integration detail, not something that should
+	 * be configured in the dssdev
+	 */
+	dsidev = dpi_get_dsidev(dssdev->channel);
+
+	if (dsidev && dpi_verify_dsi_pll(dsidev)) {
+		dsidev = NULL;
+		DSSWARN("DSI PLL not operational\n");
 	}
 	}
 
 
+	if (dsidev)
+		DSSDBG("using DSI PLL for DPI clock\n");
+
+	dpi.dsidev = dsidev;
+
 	return 0;
 	return 0;
 }
 }
 
 
 static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev)
 static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev)
 {
 {
 	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
 	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-	const char *def_disp_name = dss_get_default_display_name();
+	const char *def_disp_name = omapdss_get_default_display_name();
 	struct omap_dss_device *def_dssdev;
 	struct omap_dss_device *def_dssdev;
 	int i;
 	int i;
 
 
@@ -438,9 +493,18 @@ static void __init dpi_probe_pdata(struct platform_device *dpidev)
 		return;
 		return;
 	}
 	}
 
 
+	r = omapdss_output_set_device(&dpi.output, dssdev);
+	if (r) {
+		DSSERR("failed to connect output to new device: %s\n",
+				dssdev->name);
+		dss_put_device(dssdev);
+		return;
+	}
+
 	r = dss_add_device(dssdev);
 	r = dss_add_device(dssdev);
 	if (r) {
 	if (r) {
 		DSSERR("device %s register failed: %d\n", dssdev->name, r);
 		DSSERR("device %s register failed: %d\n", dssdev->name, r);
+		omapdss_output_unset_device(&dpi.output);
 		dss_put_device(dssdev);
 		dss_put_device(dssdev);
 		return;
 		return;
 	}
 	}

+ 122 - 125
drivers/video/omap2/dss/dsi.c

@@ -45,7 +45,6 @@
 #include "dss.h"
 #include "dss.h"
 #include "dss_features.h"
 #include "dss_features.h"
 
 
-/*#define VERBOSE_IRQ*/
 #define DSI_CATCH_MISSING_TE
 #define DSI_CATCH_MISSING_TE
 
 
 struct dsi_reg { u16 idx; };
 struct dsi_reg { u16 idx; };
@@ -535,42 +534,38 @@ static inline void dsi_perf_show(struct platform_device *dsidev,
 }
 }
 #endif
 #endif
 
 
+static int verbose_irq;
+
 static void print_irq_status(u32 status)
 static void print_irq_status(u32 status)
 {
 {
 	if (status == 0)
 	if (status == 0)
 		return;
 		return;
 
 
-#ifndef VERBOSE_IRQ
-	if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
+	if (!verbose_irq && (status & ~DSI_IRQ_CHANNEL_MASK) == 0)
 		return;
 		return;
-#endif
-	printk(KERN_DEBUG "DSI IRQ: 0x%x: ", status);
 
 
-#define PIS(x) \
-	if (status & DSI_IRQ_##x) \
-		printk(#x " ");
-#ifdef VERBOSE_IRQ
-	PIS(VC0);
-	PIS(VC1);
-	PIS(VC2);
-	PIS(VC3);
-#endif
-	PIS(WAKEUP);
-	PIS(RESYNC);
-	PIS(PLL_LOCK);
-	PIS(PLL_UNLOCK);
-	PIS(PLL_RECALL);
-	PIS(COMPLEXIO_ERR);
-	PIS(HS_TX_TIMEOUT);
-	PIS(LP_RX_TIMEOUT);
-	PIS(TE_TRIGGER);
-	PIS(ACK_TRIGGER);
-	PIS(SYNC_LOST);
-	PIS(LDO_POWER_GOOD);
-	PIS(TA_TIMEOUT);
+#define PIS(x) (status & DSI_IRQ_##x) ? (#x " ") : ""
+
+	pr_debug("DSI IRQ: 0x%x: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+		status,
+		verbose_irq ? PIS(VC0) : "",
+		verbose_irq ? PIS(VC1) : "",
+		verbose_irq ? PIS(VC2) : "",
+		verbose_irq ? PIS(VC3) : "",
+		PIS(WAKEUP),
+		PIS(RESYNC),
+		PIS(PLL_LOCK),
+		PIS(PLL_UNLOCK),
+		PIS(PLL_RECALL),
+		PIS(COMPLEXIO_ERR),
+		PIS(HS_TX_TIMEOUT),
+		PIS(LP_RX_TIMEOUT),
+		PIS(TE_TRIGGER),
+		PIS(ACK_TRIGGER),
+		PIS(SYNC_LOST),
+		PIS(LDO_POWER_GOOD),
+		PIS(TA_TIMEOUT));
 #undef PIS
 #undef PIS
-
-	printk("\n");
 }
 }
 
 
 static void print_irq_status_vc(int channel, u32 status)
 static void print_irq_status_vc(int channel, u32 status)
@@ -578,28 +573,24 @@ static void print_irq_status_vc(int channel, u32 status)
 	if (status == 0)
 	if (status == 0)
 		return;
 		return;
 
 
-#ifndef VERBOSE_IRQ
-	if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
+	if (!verbose_irq && (status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
 		return;
 		return;
-#endif
-	printk(KERN_DEBUG "DSI VC(%d) IRQ 0x%x: ", channel, status);
 
 
-#define PIS(x) \
-	if (status & DSI_VC_IRQ_##x) \
-		printk(#x " ");
-	PIS(CS);
-	PIS(ECC_CORR);
-#ifdef VERBOSE_IRQ
-	PIS(PACKET_SENT);
-#endif
-	PIS(FIFO_TX_OVF);
-	PIS(FIFO_RX_OVF);
-	PIS(BTA);
-	PIS(ECC_NO_CORR);
-	PIS(FIFO_TX_UDF);
-	PIS(PP_BUSY_CHANGE);
+#define PIS(x) (status & DSI_VC_IRQ_##x) ? (#x " ") : ""
+
+	pr_debug("DSI VC(%d) IRQ 0x%x: %s%s%s%s%s%s%s%s%s\n",
+		channel,
+		status,
+		PIS(CS),
+		PIS(ECC_CORR),
+		PIS(ECC_NO_CORR),
+		verbose_irq ? PIS(PACKET_SENT) : "",
+		PIS(BTA),
+		PIS(FIFO_TX_OVF),
+		PIS(FIFO_RX_OVF),
+		PIS(FIFO_TX_UDF),
+		PIS(PP_BUSY_CHANGE));
 #undef PIS
 #undef PIS
-	printk("\n");
 }
 }
 
 
 static void print_irq_status_cio(u32 status)
 static void print_irq_status_cio(u32 status)
@@ -607,34 +598,31 @@ static void print_irq_status_cio(u32 status)
 	if (status == 0)
 	if (status == 0)
 		return;
 		return;
 
 
-	printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status);
-
-#define PIS(x) \
-	if (status & DSI_CIO_IRQ_##x) \
-		printk(#x " ");
-	PIS(ERRSYNCESC1);
-	PIS(ERRSYNCESC2);
-	PIS(ERRSYNCESC3);
-	PIS(ERRESC1);
-	PIS(ERRESC2);
-	PIS(ERRESC3);
-	PIS(ERRCONTROL1);
-	PIS(ERRCONTROL2);
-	PIS(ERRCONTROL3);
-	PIS(STATEULPS1);
-	PIS(STATEULPS2);
-	PIS(STATEULPS3);
-	PIS(ERRCONTENTIONLP0_1);
-	PIS(ERRCONTENTIONLP1_1);
-	PIS(ERRCONTENTIONLP0_2);
-	PIS(ERRCONTENTIONLP1_2);
-	PIS(ERRCONTENTIONLP0_3);
-	PIS(ERRCONTENTIONLP1_3);
-	PIS(ULPSACTIVENOT_ALL0);
-	PIS(ULPSACTIVENOT_ALL1);
+#define PIS(x) (status & DSI_CIO_IRQ_##x) ? (#x " ") : ""
+
+	pr_debug("DSI CIO IRQ 0x%x: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+		status,
+		PIS(ERRSYNCESC1),
+		PIS(ERRSYNCESC2),
+		PIS(ERRSYNCESC3),
+		PIS(ERRESC1),
+		PIS(ERRESC2),
+		PIS(ERRESC3),
+		PIS(ERRCONTROL1),
+		PIS(ERRCONTROL2),
+		PIS(ERRCONTROL3),
+		PIS(STATEULPS1),
+		PIS(STATEULPS2),
+		PIS(STATEULPS3),
+		PIS(ERRCONTENTIONLP0_1),
+		PIS(ERRCONTENTIONLP1_1),
+		PIS(ERRCONTENTIONLP0_2),
+		PIS(ERRCONTENTIONLP1_2),
+		PIS(ERRCONTENTIONLP0_3),
+		PIS(ERRCONTENTIONLP1_3),
+		PIS(ULPSACTIVENOT_ALL0),
+		PIS(ULPSACTIVENOT_ALL1));
 #undef PIS
 #undef PIS
-
-	printk("\n");
 }
 }
 
 
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -1116,28 +1104,16 @@ static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
 	}
 	}
 }
 }
 
 
-#ifdef DEBUG
 static void _dsi_print_reset_status(struct platform_device *dsidev)
 static void _dsi_print_reset_status(struct platform_device *dsidev)
 {
 {
 	u32 l;
 	u32 l;
 	int b0, b1, b2;
 	int b0, b1, b2;
 
 
-	if (!dss_debug)
-		return;
-
 	/* A dummy read using the SCP interface to any DSIPHY register is
 	/* A dummy read using the SCP interface to any DSIPHY register is
 	 * required after DSIPHY reset to complete the reset of the DSI complex
 	 * required after DSIPHY reset to complete the reset of the DSI complex
 	 * I/O. */
 	 * I/O. */
 	l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
 	l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
 
 
-	printk(KERN_DEBUG "DSI resets: ");
-
-	l = dsi_read_reg(dsidev, DSI_PLL_STATUS);
-	printk("PLL (%d) ", FLD_GET(l, 0, 0));
-
-	l = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1);
-	printk("CIO (%d) ", FLD_GET(l, 29, 29));
-
 	if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) {
 	if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) {
 		b0 = 28;
 		b0 = 28;
 		b1 = 27;
 		b1 = 27;
@@ -1148,18 +1124,21 @@ static void _dsi_print_reset_status(struct platform_device *dsidev)
 		b2 = 26;
 		b2 = 26;
 	}
 	}
 
 
-	l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
-	printk("PHY (%x%x%x, %d, %d, %d)\n",
-			FLD_GET(l, b0, b0),
-			FLD_GET(l, b1, b1),
-			FLD_GET(l, b2, b2),
-			FLD_GET(l, 29, 29),
-			FLD_GET(l, 30, 30),
-			FLD_GET(l, 31, 31));
+#define DSI_FLD_GET(fld, start, end)\
+	FLD_GET(dsi_read_reg(dsidev, DSI_##fld), start, end)
+
+	pr_debug("DSI resets: PLL (%d) CIO (%d) PHY (%x%x%x, %d, %d, %d)\n",
+		DSI_FLD_GET(PLL_STATUS, 0, 0),
+		DSI_FLD_GET(COMPLEXIO_CFG1, 29, 29),
+		DSI_FLD_GET(DSIPHY_CFG5, b0, b0),
+		DSI_FLD_GET(DSIPHY_CFG5, b1, b1),
+		DSI_FLD_GET(DSIPHY_CFG5, b2, b2),
+		DSI_FLD_GET(DSIPHY_CFG5, 29, 29),
+		DSI_FLD_GET(DSIPHY_CFG5, 30, 30),
+		DSI_FLD_GET(DSIPHY_CFG5, 31, 31));
+
+#undef DSI_FLD_GET
 }
 }
-#else
-#define _dsi_print_reset_status(x)
-#endif
 
 
 static inline int dsi_if_enable(struct platform_device *dsidev, bool enable)
 static inline int dsi_if_enable(struct platform_device *dsidev, bool enable)
 {
 {
@@ -1407,6 +1386,11 @@ retry:
 				cur.dsi_pll_hsdiv_dispc_clk =
 				cur.dsi_pll_hsdiv_dispc_clk =
 					cur.clkin4ddr / cur.regm_dispc;
 					cur.clkin4ddr / cur.regm_dispc;
 
 
+				if (cur.regm_dispc > 1 &&
+						cur.regm_dispc % 2 != 0 &&
+						req_pck >= 1000000)
+					continue;
+
 				/* this will narrow down the search a bit,
 				/* this will narrow down the search a bit,
 				 * but still give pixclocks below what was
 				 * but still give pixclocks below what was
 				 * requested */
 				 * requested */
@@ -1621,7 +1605,7 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,
 	u8 regn_start, regn_end, regm_start, regm_end;
 	u8 regn_start, regn_end, regm_start, regm_end;
 	u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end;
 	u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end;
 
 
-	DSSDBGF();
+	DSSDBG("DSI PLL clock config starts");
 
 
 	dsi->current_cinfo.clkin = cinfo->clkin;
 	dsi->current_cinfo.clkin = cinfo->clkin;
 	dsi->current_cinfo.fint = cinfo->fint;
 	dsi->current_cinfo.fint = cinfo->fint;
@@ -1757,11 +1741,21 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
 
 
 	DSSDBG("PLL init\n");
 	DSSDBG("PLL init\n");
 
 
+	/*
+	 * It seems that on many OMAPs we need to enable both to have a
+	 * functional HSDivider.
+	 */
+	enable_hsclk = enable_hsdiv = true;
+
 	if (dsi->vdds_dsi_reg == NULL) {
 	if (dsi->vdds_dsi_reg == NULL) {
 		struct regulator *vdds_dsi;
 		struct regulator *vdds_dsi;
 
 
 		vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi");
 		vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi");
 
 
+		/* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */
+		if (IS_ERR(vdds_dsi))
+			vdds_dsi = regulator_get(&dsi->pdev->dev, "VCXIO");
+
 		if (IS_ERR(vdds_dsi)) {
 		if (IS_ERR(vdds_dsi)) {
 			DSSERR("can't get VDDS_DSI regulator\n");
 			DSSERR("can't get VDDS_DSI regulator\n");
 			return PTR_ERR(vdds_dsi);
 			return PTR_ERR(vdds_dsi);
@@ -2440,7 +2434,7 @@ static int dsi_cio_init(struct platform_device *dsidev)
 	int r;
 	int r;
 	u32 l;
 	u32 l;
 
 
-	DSSDBGF();
+	DSSDBG("DSI CIO init starts");
 
 
 	r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
 	r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
 	if (r)
 	if (r)
@@ -2791,7 +2785,7 @@ static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)
 {
 {
 	u32 r;
 	u32 r;
 
 
-	DSSDBGF("%d", channel);
+	DSSDBG("Initial config of virtual channel %d", channel);
 
 
 	r = dsi_read_reg(dsidev, DSI_VC_CTRL(channel));
 	r = dsi_read_reg(dsidev, DSI_VC_CTRL(channel));
 
 
@@ -2823,7 +2817,7 @@ static int dsi_vc_config_source(struct platform_device *dsidev, int channel,
 	if (dsi->vc[channel].source == source)
 	if (dsi->vc[channel].source == source)
 		return 0;
 		return 0;
 
 
-	DSSDBGF("%d", channel);
+	DSSDBG("Source config of virtual channel %d", channel);
 
 
 	dsi_sync_vc(dsidev, channel);
 	dsi_sync_vc(dsidev, channel);
 
 
@@ -3581,7 +3575,7 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
 	int r, i;
 	int r, i;
 	unsigned mask;
 	unsigned mask;
 
 
-	DSSDBGF();
+	DSSDBG("Entering ULPS");
 
 
 	WARN_ON(!dsi_bus_is_locked(dsidev));
 	WARN_ON(!dsi_bus_is_locked(dsidev));
 
 
@@ -4285,7 +4279,7 @@ int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
 	unsigned long pck;
 	unsigned long pck;
 	int r;
 	int r;
 
 
-	DSSDBGF("ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
+	DSSDBG("Setting DSI clocks: ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
 
 
 	mutex_lock(&dsi->lock);
 	mutex_lock(&dsi->lock);
 
 
@@ -4541,7 +4535,7 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work)
 	dsi_handle_framedone(dsi->pdev, -ETIMEDOUT);
 	dsi_handle_framedone(dsi->pdev, -ETIMEDOUT);
 }
 }
 
 
-static void dsi_framedone_irq_callback(void *data, u32 mask)
+static void dsi_framedone_irq_callback(void *data)
 {
 {
 	struct platform_device *dsidev = (struct platform_device *) data;
 	struct platform_device *dsidev = (struct platform_device *) data;
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -4615,7 +4609,6 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	struct omap_overlay_manager *mgr = dssdev->output->manager;
 	struct omap_overlay_manager *mgr = dssdev->output->manager;
 	int r;
 	int r;
-	u32 irq = 0;
 
 
 	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
 	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
 		dsi->timings.hsw = 1;
 		dsi->timings.hsw = 1;
@@ -4625,12 +4618,10 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
 		dsi->timings.vfp = 0;
 		dsi->timings.vfp = 0;
 		dsi->timings.vbp = 0;
 		dsi->timings.vbp = 0;
 
 
-		irq = dispc_mgr_get_framedone_irq(mgr->id);
-
-		r = omap_dispc_register_isr(dsi_framedone_irq_callback,
-			(void *) dsidev, irq);
+		r = dss_mgr_register_framedone_handler(mgr,
+				dsi_framedone_irq_callback, dsidev);
 		if (r) {
 		if (r) {
-			DSSERR("can't get FRAMEDONE irq\n");
+			DSSERR("can't register FRAMEDONE handler\n");
 			goto err;
 			goto err;
 		}
 		}
 
 
@@ -4668,8 +4659,8 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
 	return 0;
 	return 0;
 err1:
 err1:
 	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
 	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
-		omap_dispc_unregister_isr(dsi_framedone_irq_callback,
-			(void *) dsidev, irq);
+		dss_mgr_unregister_framedone_handler(mgr,
+				dsi_framedone_irq_callback, dsidev);
 err:
 err:
 	return r;
 	return r;
 }
 }
@@ -4680,14 +4671,9 @@ static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	struct omap_overlay_manager *mgr = dssdev->output->manager;
 	struct omap_overlay_manager *mgr = dssdev->output->manager;
 
 
-	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
-		u32 irq;
-
-		irq = dispc_mgr_get_framedone_irq(mgr->id);
-
-		omap_dispc_unregister_isr(dsi_framedone_irq_callback,
-			(void *) dsidev, irq);
-	}
+	if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
+		dss_mgr_unregister_framedone_handler(mgr,
+				dsi_framedone_irq_callback, dsidev);
 }
 }
 
 
 static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
 static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
@@ -4730,7 +4716,6 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
 	if (r)
 	if (r)
 		goto err1;
 		goto err1;
 
 
-	dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
 	dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src);
 	dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src);
 	dss_select_lcd_clk_source(mgr->id,
 	dss_select_lcd_clk_source(mgr->id,
 			dssdev->clocks.dispc.channel.lcd_clk_src);
 			dssdev->clocks.dispc.channel.lcd_clk_src);
@@ -4765,7 +4750,6 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
 err3:
 err3:
 	dsi_cio_uninit(dsidev);
 	dsi_cio_uninit(dsidev);
 err2:
 err2:
-	dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
 	dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
 	dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
 	dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
 	dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
 
 
@@ -4792,7 +4776,6 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
 	dsi_vc_enable(dsidev, 2, 0);
 	dsi_vc_enable(dsidev, 2, 0);
 	dsi_vc_enable(dsidev, 3, 0);
 	dsi_vc_enable(dsidev, 3, 0);
 
 
-	dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
 	dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
 	dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
 	dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
 	dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
 	dsi_cio_uninit(dsidev);
 	dsi_cio_uninit(dsidev);
@@ -4981,6 +4964,10 @@ static int __init dsi_init_display(struct omap_dss_device *dssdev)
 
 
 		vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi");
 		vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi");
 
 
+		/* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */
+		if (IS_ERR(vdds_dsi))
+			vdds_dsi = regulator_get(&dsi->pdev->dev, "VCXIO");
+
 		if (IS_ERR(vdds_dsi)) {
 		if (IS_ERR(vdds_dsi)) {
 			DSSERR("can't get VDDS_DSI regulator\n");
 			DSSERR("can't get VDDS_DSI regulator\n");
 			return PTR_ERR(vdds_dsi);
 			return PTR_ERR(vdds_dsi);
@@ -5121,7 +5108,7 @@ static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *p
 {
 {
 	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
 	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
 	struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
 	struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
-	const char *def_disp_name = dss_get_default_display_name();
+	const char *def_disp_name = omapdss_get_default_display_name();
 	struct omap_dss_device *def_dssdev;
 	struct omap_dss_device *def_dssdev;
 	int i;
 	int i;
 
 
@@ -5151,6 +5138,7 @@ static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *p
 
 
 static void __init dsi_probe_pdata(struct platform_device *dsidev)
 static void __init dsi_probe_pdata(struct platform_device *dsidev)
 {
 {
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	struct omap_dss_device *plat_dssdev;
 	struct omap_dss_device *plat_dssdev;
 	struct omap_dss_device *dssdev;
 	struct omap_dss_device *dssdev;
 	int r;
 	int r;
@@ -5173,9 +5161,18 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev)
 		return;
 		return;
 	}
 	}
 
 
+	r = omapdss_output_set_device(&dsi->output, dssdev);
+	if (r) {
+		DSSERR("failed to connect output to new device: %s\n",
+				dssdev->name);
+		dss_put_device(dssdev);
+		return;
+	}
+
 	r = dss_add_device(dssdev);
 	r = dss_add_device(dssdev);
 	if (r) {
 	if (r) {
 		DSSERR("device %s register failed: %d\n", dssdev->name, r);
 		DSSERR("device %s register failed: %d\n", dssdev->name, r);
+		omapdss_output_unset_device(&dsi->output);
 		dss_put_device(dssdev);
 		dss_put_device(dssdev);
 		return;
 		return;
 	}
 	}

+ 96 - 5
drivers/video/omap2/dss/dss.c

@@ -32,6 +32,7 @@
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_runtime.h>
 #include <linux/gfp.h>
 #include <linux/gfp.h>
+#include <linux/sizes.h>
 
 
 #include <video/omapdss.h>
 #include <video/omapdss.h>
 
 
@@ -76,6 +77,7 @@ static struct {
 
 
 	struct clk	*dpll4_m4_ck;
 	struct clk	*dpll4_m4_ck;
 	struct clk	*dss_clk;
 	struct clk	*dss_clk;
+	unsigned long	dss_clk_rate;
 
 
 	unsigned long	cache_req_pck;
 	unsigned long	cache_req_pck;
 	unsigned long	cache_prate;
 	unsigned long	cache_prate;
@@ -96,6 +98,8 @@ static const char * const dss_generic_clk_source_names[] = {
 	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]	= "DSI_PLL_HSDIV_DISPC",
 	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]	= "DSI_PLL_HSDIV_DISPC",
 	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]	= "DSI_PLL_HSDIV_DSI",
 	[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]	= "DSI_PLL_HSDIV_DSI",
 	[OMAP_DSS_CLK_SRC_FCK]			= "DSS_FCK",
 	[OMAP_DSS_CLK_SRC_FCK]			= "DSS_FCK",
+	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC]	= "DSI_PLL2_HSDIV_DISPC",
+	[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI]	= "DSI_PLL2_HSDIV_DSI",
 };
 };
 
 
 static inline void dss_write_reg(const struct dss_reg idx, u32 val)
 static inline void dss_write_reg(const struct dss_reg idx, u32 val)
@@ -151,6 +155,21 @@ static void dss_restore_context(void)
 #undef SR
 #undef SR
 #undef RR
 #undef RR
 
 
+int dss_get_ctx_loss_count(void)
+{
+	struct omap_dss_board_info *board_data = dss.pdev->dev.platform_data;
+	int cnt;
+
+	if (!board_data->get_context_loss_count)
+		return -ENOENT;
+
+	cnt = board_data->get_context_loss_count(&dss.pdev->dev);
+
+	WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
+
+	return cnt;
+}
+
 void dss_sdi_init(int datapairs)
 void dss_sdi_init(int datapairs)
 {
 {
 	u32 l;
 	u32 l;
@@ -301,7 +320,7 @@ static void dss_dump_regs(struct seq_file *s)
 #undef DUMPREG
 #undef DUMPREG
 }
 }
 
 
-void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
+static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
 {
 {
 	struct platform_device *dsidev;
 	struct platform_device *dsidev;
 	int b;
 	int b;
@@ -372,8 +391,10 @@ void dss_select_lcd_clk_source(enum omap_channel channel,
 	struct platform_device *dsidev;
 	struct platform_device *dsidev;
 	int b, ix, pos;
 	int b, ix, pos;
 
 
-	if (!dss_has_feature(FEAT_LCD_CLK_SRC))
+	if (!dss_has_feature(FEAT_LCD_CLK_SRC)) {
+		dss_select_dispc_clk_source(clk_src);
 		return;
 		return;
+	}
 
 
 	switch (clk_src) {
 	switch (clk_src) {
 	case OMAP_DSS_CLK_SRC_FCK:
 	case OMAP_DSS_CLK_SRC_FCK:
@@ -429,6 +450,29 @@ enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
 	}
 	}
 }
 }
 
 
+/* calculate clock rates using dividers in cinfo */
+int dss_calc_clock_rates(struct dss_clock_info *cinfo)
+{
+	if (dss.dpll4_m4_ck) {
+		unsigned long prate;
+
+		if (cinfo->fck_div > dss.feat->fck_div_max ||
+				cinfo->fck_div == 0)
+			return -EINVAL;
+
+		prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
+
+		cinfo->fck = prate / cinfo->fck_div *
+			dss.feat->dss_fck_multiplier;
+	} else {
+		if (cinfo->fck_div != 0)
+			return -EINVAL;
+		cinfo->fck = clk_get_rate(dss.dss_clk);
+	}
+
+	return 0;
+}
+
 int dss_set_clock_div(struct dss_clock_info *cinfo)
 int dss_set_clock_div(struct dss_clock_info *cinfo)
 {
 {
 	if (dss.dpll4_m4_ck) {
 	if (dss.dpll4_m4_ck) {
@@ -446,6 +490,10 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
 			return -EINVAL;
 			return -EINVAL;
 	}
 	}
 
 
+	dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
+
+	WARN_ONCE(dss.dss_clk_rate != cinfo->fck, "clk rate mismatch");
+
 	DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
 	DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
 
 
 	return 0;
 	return 0;
@@ -459,6 +507,41 @@ unsigned long dss_get_dpll4_rate(void)
 		return 0;
 		return 0;
 }
 }
 
 
+unsigned long dss_get_dispc_clk_rate(void)
+{
+	return dss.dss_clk_rate;
+}
+
+static int dss_setup_default_clock(void)
+{
+	unsigned long max_dss_fck, prate;
+	unsigned fck_div;
+	struct dss_clock_info dss_cinfo = { 0 };
+	int r;
+
+	if (dss.dpll4_m4_ck == NULL)
+		return 0;
+
+	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+
+	prate = dss_get_dpll4_rate();
+
+	fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier,
+			max_dss_fck);
+
+	dss_cinfo.fck_div = fck_div;
+
+	r = dss_calc_clock_rates(&dss_cinfo);
+	if (r)
+		return r;
+
+	r = dss_set_clock_div(&dss_cinfo);
+	if (r)
+		return r;
+
+	return 0;
+}
+
 int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
 int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
 		struct dispc_clock_info *dispc_cinfo)
 		struct dispc_clock_info *dispc_cinfo)
 {
 {
@@ -748,7 +831,7 @@ static void dss_runtime_put(void)
 }
 }
 
 
 /* DEBUGFS */
 /* DEBUGFS */
-#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
 void dss_debug_dump_clocks(struct seq_file *s)
 void dss_debug_dump_clocks(struct seq_file *s)
 {
 {
 	dss_dump_clocks(s);
 	dss_dump_clocks(s);
@@ -796,7 +879,6 @@ static const struct dss_features omap54xx_dss_feats __initconst = {
 
 
 static int __init dss_init_features(struct platform_device *pdev)
 static int __init dss_init_features(struct platform_device *pdev)
 {
 {
-	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
 	const struct dss_features *src;
 	const struct dss_features *src;
 	struct dss_features *dst;
 	struct dss_features *dst;
 
 
@@ -806,7 +888,7 @@ static int __init dss_init_features(struct platform_device *pdev)
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
-	switch (pdata->version) {
+	switch (omapdss_get_version()) {
 	case OMAPDSS_VER_OMAP24xx:
 	case OMAPDSS_VER_OMAP24xx:
 		src = &omap24xx_dss_feats;
 		src = &omap24xx_dss_feats;
 		break;
 		break;
@@ -871,15 +953,23 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
 	if (r)
 	if (r)
 		return r;
 		return r;
 
 
+	r = dss_setup_default_clock();
+	if (r)
+		goto err_setup_clocks;
+
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 
 
 	r = dss_runtime_get();
 	r = dss_runtime_get();
 	if (r)
 	if (r)
 		goto err_runtime_get;
 		goto err_runtime_get;
 
 
+	dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
+
 	/* Select DPLL */
 	/* Select DPLL */
 	REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
 	REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
 
 
+	dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
+
 #ifdef CONFIG_OMAP2_DSS_VENC
 #ifdef CONFIG_OMAP2_DSS_VENC
 	REG_FLD_MOD(DSS_CONTROL, 1, 4, 4);	/* venc dac demen */
 	REG_FLD_MOD(DSS_CONTROL, 1, 4, 4);	/* venc dac demen */
 	REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);	/* venc clock 4x enable */
 	REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);	/* venc clock 4x enable */
@@ -903,6 +993,7 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
 
 
 err_runtime_get:
 err_runtime_get:
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
+err_setup_clocks:
 	dss_put_clocks();
 	dss_put_clocks();
 	return r;
 	return r;
 }
 }

+ 19 - 105
drivers/video/omap2/dss/dss.h

@@ -23,44 +23,20 @@
 #ifndef __OMAP2_DSS_H
 #ifndef __OMAP2_DSS_H
 #define __OMAP2_DSS_H
 #define __OMAP2_DSS_H
 
 
-#ifdef CONFIG_OMAP2_DSS_DEBUG_SUPPORT
-#define DEBUG
-#endif
+#include <linux/interrupt.h>
 
 
-#ifdef DEBUG
-extern bool dss_debug;
-#ifdef DSS_SUBSYS_NAME
-#define DSSDBG(format, ...) \
-	if (dss_debug) \
-		printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME ": " format, \
-		## __VA_ARGS__)
-#else
-#define DSSDBG(format, ...) \
-	if (dss_debug) \
-		printk(KERN_DEBUG "omapdss: " format, ## __VA_ARGS__)
+#ifdef pr_fmt
+#undef pr_fmt
 #endif
 #endif
 
 
 #ifdef DSS_SUBSYS_NAME
 #ifdef DSS_SUBSYS_NAME
-#define DSSDBGF(format, ...) \
-	if (dss_debug) \
-		printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME \
-				": %s(" format ")\n", \
-				__func__, \
-				## __VA_ARGS__)
+#define pr_fmt(fmt) DSS_SUBSYS_NAME ": " fmt
 #else
 #else
-#define DSSDBGF(format, ...) \
-	if (dss_debug) \
-		printk(KERN_DEBUG "omapdss: " \
-				": %s(" format ")\n", \
-				__func__, \
-				## __VA_ARGS__)
-#endif
-
-#else /* DEBUG */
-#define DSSDBG(format, ...)
-#define DSSDBGF(format, ...)
+#define pr_fmt(fmt) fmt
 #endif
 #endif
 
 
+#define DSSDBG(format, ...) \
+	pr_debug(format, ## __VA_ARGS__)
 
 
 #ifdef DSS_SUBSYS_NAME
 #ifdef DSS_SUBSYS_NAME
 #define DSSERR(format, ...) \
 #define DSSERR(format, ...) \
@@ -186,11 +162,10 @@ struct seq_file;
 struct platform_device;
 struct platform_device;
 
 
 /* core */
 /* core */
-const char *dss_get_default_display_name(void);
+struct platform_device *dss_get_core_pdev(void);
 struct bus_type *dss_get_bus(void);
 struct bus_type *dss_get_bus(void);
 struct regulator *dss_get_vdds_dsi(void);
 struct regulator *dss_get_vdds_dsi(void);
 struct regulator *dss_get_vdds_sdi(void);
 struct regulator *dss_get_vdds_sdi(void);
-int dss_get_ctx_loss_count(struct device *dev);
 int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask);
 int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask);
 void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
 void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
 int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
 int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
@@ -204,55 +179,18 @@ void dss_put_device(struct omap_dss_device *dssdev);
 void dss_copy_device_pdata(struct omap_dss_device *dst,
 void dss_copy_device_pdata(struct omap_dss_device *dst,
 		const struct omap_dss_device *src);
 		const struct omap_dss_device *src);
 
 
-/* apply */
-void dss_apply_init(void);
-int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr);
-int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
-void dss_mgr_start_update(struct omap_overlay_manager *mgr);
-int omap_dss_mgr_apply(struct omap_overlay_manager *mgr);
-
-int dss_mgr_enable(struct omap_overlay_manager *mgr);
-void dss_mgr_disable(struct omap_overlay_manager *mgr);
-int dss_mgr_set_info(struct omap_overlay_manager *mgr,
-		struct omap_overlay_manager_info *info);
-void dss_mgr_get_info(struct omap_overlay_manager *mgr,
-		struct omap_overlay_manager_info *info);
-int dss_mgr_set_device(struct omap_overlay_manager *mgr,
-		struct omap_dss_device *dssdev);
-int dss_mgr_unset_device(struct omap_overlay_manager *mgr);
-int dss_mgr_set_output(struct omap_overlay_manager *mgr,
-		struct omap_dss_output *output);
-int dss_mgr_unset_output(struct omap_overlay_manager *mgr);
-void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
-		const struct omap_video_timings *timings);
-void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
-		const struct dss_lcd_mgr_config *config);
-const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr);
-
-bool dss_ovl_is_enabled(struct omap_overlay *ovl);
-int dss_ovl_enable(struct omap_overlay *ovl);
-int dss_ovl_disable(struct omap_overlay *ovl);
-int dss_ovl_set_info(struct omap_overlay *ovl,
-		struct omap_overlay_info *info);
-void dss_ovl_get_info(struct omap_overlay *ovl,
-		struct omap_overlay_info *info);
-int dss_ovl_set_manager(struct omap_overlay *ovl,
-		struct omap_overlay_manager *mgr);
-int dss_ovl_unset_manager(struct omap_overlay *ovl);
-
 /* output */
 /* output */
 void dss_register_output(struct omap_dss_output *out);
 void dss_register_output(struct omap_dss_output *out);
 void dss_unregister_output(struct omap_dss_output *out);
 void dss_unregister_output(struct omap_dss_output *out);
-struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev);
 
 
 /* display */
 /* display */
 int dss_suspend_all_devices(void);
 int dss_suspend_all_devices(void);
 int dss_resume_all_devices(void);
 int dss_resume_all_devices(void);
 void dss_disable_all_devices(void);
 void dss_disable_all_devices(void);
 
 
-int dss_init_device(struct platform_device *pdev,
+int display_init_sysfs(struct platform_device *pdev,
 		struct omap_dss_device *dssdev);
 		struct omap_dss_device *dssdev);
-void dss_uninit_device(struct platform_device *pdev,
+void display_uninit_sysfs(struct platform_device *pdev,
 		struct omap_dss_device *dssdev);
 		struct omap_dss_device *dssdev);
 
 
 /* manager */
 /* manager */
@@ -299,21 +237,23 @@ void dss_overlay_kobj_uninit(struct omap_overlay *ovl);
 int dss_init_platform_driver(void) __init;
 int dss_init_platform_driver(void) __init;
 void dss_uninit_platform_driver(void);
 void dss_uninit_platform_driver(void);
 
 
+unsigned long dss_get_dispc_clk_rate(void);
 int dss_dpi_select_source(enum omap_channel channel);
 int dss_dpi_select_source(enum omap_channel channel);
 void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
 void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
 enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
 enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
 const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
 const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
 void dss_dump_clocks(struct seq_file *s);
 void dss_dump_clocks(struct seq_file *s);
 
 
-#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
 void dss_debug_dump_clocks(struct seq_file *s);
 void dss_debug_dump_clocks(struct seq_file *s);
 #endif
 #endif
 
 
+int dss_get_ctx_loss_count(void);
+
 void dss_sdi_init(int datapairs);
 void dss_sdi_init(int datapairs);
 int dss_sdi_enable(void);
 int dss_sdi_enable(void);
 void dss_sdi_disable(void);
 void dss_sdi_disable(void);
 
 
-void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src);
 void dss_select_dsi_clk_source(int dsi_module,
 void dss_select_dsi_clk_source(int dsi_module,
 		enum omap_dss_clk_source clk_src);
 		enum omap_dss_clk_source clk_src);
 void dss_select_lcd_clk_source(enum omap_channel channel,
 void dss_select_lcd_clk_source(enum omap_channel channel,
@@ -326,6 +266,7 @@ void dss_set_venc_output(enum omap_dss_venc_type type);
 void dss_set_dac_pwrdn_bgz(bool enable);
 void dss_set_dac_pwrdn_bgz(bool enable);
 
 
 unsigned long dss_get_dpll4_rate(void);
 unsigned long dss_get_dpll4_rate(void);
+int dss_calc_clock_rates(struct dss_clock_info *cinfo);
 int dss_set_clock_div(struct dss_clock_info *cinfo);
 int dss_set_clock_div(struct dss_clock_info *cinfo);
 int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
 int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
 		struct dispc_clock_info *dispc_cinfo);
 		struct dispc_clock_info *dispc_cinfo);
@@ -413,8 +354,6 @@ static inline void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev)
 }
 }
 static inline struct platform_device *dsi_get_dsidev_from_id(int module)
 static inline struct platform_device *dsi_get_dsidev_from_id(int module)
 {
 {
-	WARN("%s: DSI not compiled in, returning platform device as NULL\n",
-			__func__);
 	return NULL;
 	return NULL;
 }
 }
 #endif
 #endif
@@ -427,15 +366,10 @@ void dpi_uninit_platform_driver(void) __exit;
 int dispc_init_platform_driver(void) __init;
 int dispc_init_platform_driver(void) __init;
 void dispc_uninit_platform_driver(void) __exit;
 void dispc_uninit_platform_driver(void) __exit;
 void dispc_dump_clocks(struct seq_file *s);
 void dispc_dump_clocks(struct seq_file *s);
-void dispc_irq_handler(void);
-
-int dispc_runtime_get(void);
-void dispc_runtime_put(void);
 
 
 void dispc_enable_sidle(void);
 void dispc_enable_sidle(void);
 void dispc_disable_sidle(void);
 void dispc_disable_sidle(void);
 
 
-void dispc_lcd_enable_signal_polarity(bool act_high);
 void dispc_lcd_enable_signal(bool enable);
 void dispc_lcd_enable_signal(bool enable);
 void dispc_pck_free_enable(bool enable);
 void dispc_pck_free_enable(bool enable);
 void dispc_enable_fifomerge(bool enable);
 void dispc_enable_fifomerge(bool enable);
@@ -455,36 +389,14 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
 void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
 void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
 		u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
 		u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
 		bool manual_update);
 		bool manual_update);
-int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
-		bool replication, const struct omap_video_timings *mgr_timings,
-		bool mem_to_mem);
-int dispc_ovl_enable(enum omap_plane plane, bool enable);
-void dispc_ovl_set_channel_out(enum omap_plane plane,
-		enum omap_channel channel);
-
-void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable);
-u32 dispc_mgr_get_vsync_irq(enum omap_channel channel);
-u32 dispc_mgr_get_framedone_irq(enum omap_channel channel);
-bool dispc_mgr_go_busy(enum omap_channel channel);
-void dispc_mgr_go(enum omap_channel channel);
-bool dispc_mgr_is_enabled(enum omap_channel channel);
-void dispc_mgr_enable(enum omap_channel channel, bool enable);
-bool dispc_mgr_is_channel_enabled(enum omap_channel channel);
-void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode);
-void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable);
-void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
-void dispc_mgr_set_lcd_type_tft(enum omap_channel channel);
-void dispc_mgr_set_timings(enum omap_channel channel,
-		struct omap_video_timings *timings);
+
 unsigned long dispc_mgr_lclk_rate(enum omap_channel channel);
 unsigned long dispc_mgr_lclk_rate(enum omap_channel channel);
 unsigned long dispc_mgr_pclk_rate(enum omap_channel channel);
 unsigned long dispc_mgr_pclk_rate(enum omap_channel channel);
 unsigned long dispc_core_clk_rate(void);
 unsigned long dispc_core_clk_rate(void);
 void dispc_mgr_set_clock_div(enum omap_channel channel,
 void dispc_mgr_set_clock_div(enum omap_channel channel,
-		struct dispc_clock_info *cinfo);
+		const struct dispc_clock_info *cinfo);
 int dispc_mgr_get_clock_div(enum omap_channel channel,
 int dispc_mgr_get_clock_div(enum omap_channel channel,
 		struct dispc_clock_info *cinfo);
 		struct dispc_clock_info *cinfo);
-void dispc_mgr_setup(enum omap_channel channel,
-		struct omap_overlay_manager_info *info);
 
 
 u32 dispc_wb_get_framedone_irq(void);
 u32 dispc_wb_get_framedone_irq(void);
 bool dispc_wb_go_busy(void);
 bool dispc_wb_go_busy(void);
@@ -536,6 +448,8 @@ static inline unsigned long hdmi_get_pixel_clock(void)
 #endif
 #endif
 int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
 int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
 void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
 void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
+int omapdss_hdmi_core_enable(struct omap_dss_device *dssdev);
+void omapdss_hdmi_core_disable(struct omap_dss_device *dssdev);
 void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
 void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings);
 		struct omap_video_timings *timings);
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,

+ 7 - 8
drivers/video/omap2/dss/dss_features.c

@@ -18,6 +18,7 @@
  */
  */
 
 
 #include <linux/kernel.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/types.h>
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
@@ -429,8 +430,6 @@ static const struct dss_param_range omap2_dss_param_range[] = {
 	 * scaler cannot scale a image with width more than 768.
 	 * scaler cannot scale a image with width more than 768.
 	 */
 	 */
 	[FEAT_PARAM_LINEWIDTH]			= { 1, 768 },
 	[FEAT_PARAM_LINEWIDTH]			= { 1, 768 },
-	[FEAT_PARAM_MGR_WIDTH]			= { 1, 2048 },
-	[FEAT_PARAM_MGR_HEIGHT]			= { 1, 2048 },
 };
 };
 
 
 static const struct dss_param_range omap3_dss_param_range[] = {
 static const struct dss_param_range omap3_dss_param_range[] = {
@@ -445,8 +444,6 @@ static const struct dss_param_range omap3_dss_param_range[] = {
 	[FEAT_PARAM_DSI_FCK]			= { 0, 173000000 },
 	[FEAT_PARAM_DSI_FCK]			= { 0, 173000000 },
 	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 },
 	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 },
 	[FEAT_PARAM_LINEWIDTH]			= { 1, 1024 },
 	[FEAT_PARAM_LINEWIDTH]			= { 1, 1024 },
-	[FEAT_PARAM_MGR_WIDTH]			= { 1, 2048 },
-	[FEAT_PARAM_MGR_HEIGHT]			= { 1, 2048 },
 };
 };
 
 
 static const struct dss_param_range omap4_dss_param_range[] = {
 static const struct dss_param_range omap4_dss_param_range[] = {
@@ -461,8 +458,6 @@ static const struct dss_param_range omap4_dss_param_range[] = {
 	[FEAT_PARAM_DSI_FCK]			= { 0, 170000000 },
 	[FEAT_PARAM_DSI_FCK]			= { 0, 170000000 },
 	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 },
 	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 },
 	[FEAT_PARAM_LINEWIDTH]			= { 1, 2048 },
 	[FEAT_PARAM_LINEWIDTH]			= { 1, 2048 },
-	[FEAT_PARAM_MGR_WIDTH]			= { 1, 2048 },
-	[FEAT_PARAM_MGR_HEIGHT]			= { 1, 2048 },
 };
 };
 
 
 static const struct dss_param_range omap5_dss_param_range[] = {
 static const struct dss_param_range omap5_dss_param_range[] = {
@@ -477,8 +472,6 @@ static const struct dss_param_range omap5_dss_param_range[] = {
 	[FEAT_PARAM_DSI_FCK]			= { 0, 170000000 },
 	[FEAT_PARAM_DSI_FCK]			= { 0, 170000000 },
 	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 },
 	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 },
 	[FEAT_PARAM_LINEWIDTH]			= { 1, 2048 },
 	[FEAT_PARAM_LINEWIDTH]			= { 1, 2048 },
-	[FEAT_PARAM_MGR_WIDTH]			= { 1, 2048 },
-	[FEAT_PARAM_MGR_HEIGHT]			= { 1, 2048 },
 };
 };
 
 
 static const enum dss_feat_id omap2_dss_feat_list[] = {
 static const enum dss_feat_id omap2_dss_feat_list[] = {
@@ -820,6 +813,7 @@ static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
 	.audio_start		=       ti_hdmi_4xxx_audio_start,
 	.audio_start		=       ti_hdmi_4xxx_audio_start,
 	.audio_stop		=       ti_hdmi_4xxx_audio_stop,
 	.audio_stop		=       ti_hdmi_4xxx_audio_stop,
 	.audio_config		=	ti_hdmi_4xxx_audio_config,
 	.audio_config		=	ti_hdmi_4xxx_audio_config,
+	.audio_get_dma_port	=	ti_hdmi_4xxx_audio_get_dma_port,
 #endif
 #endif
 
 
 };
 };
@@ -846,11 +840,13 @@ int dss_feat_get_num_mgrs(void)
 {
 {
 	return omap_current_dss_features->num_mgrs;
 	return omap_current_dss_features->num_mgrs;
 }
 }
+EXPORT_SYMBOL(dss_feat_get_num_mgrs);
 
 
 int dss_feat_get_num_ovls(void)
 int dss_feat_get_num_ovls(void)
 {
 {
 	return omap_current_dss_features->num_ovls;
 	return omap_current_dss_features->num_ovls;
 }
 }
+EXPORT_SYMBOL(dss_feat_get_num_ovls);
 
 
 int dss_feat_get_num_wbs(void)
 int dss_feat_get_num_wbs(void)
 {
 {
@@ -871,16 +867,19 @@ enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel
 {
 {
 	return omap_current_dss_features->supported_displays[channel];
 	return omap_current_dss_features->supported_displays[channel];
 }
 }
+EXPORT_SYMBOL(dss_feat_get_supported_displays);
 
 
 enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel)
 enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel)
 {
 {
 	return omap_current_dss_features->supported_outputs[channel];
 	return omap_current_dss_features->supported_outputs[channel];
 }
 }
+EXPORT_SYMBOL(dss_feat_get_supported_outputs);
 
 
 enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
 enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
 {
 {
 	return omap_current_dss_features->supported_color_modes[plane];
 	return omap_current_dss_features->supported_color_modes[plane];
 }
 }
+EXPORT_SYMBOL(dss_feat_get_supported_color_modes);
 
 
 enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane)
 enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane)
 {
 {

+ 0 - 7
drivers/video/omap2/dss/dss_features.h

@@ -98,19 +98,12 @@ enum dss_range_param {
 	FEAT_PARAM_DSI_FCK,
 	FEAT_PARAM_DSI_FCK,
 	FEAT_PARAM_DOWNSCALE,
 	FEAT_PARAM_DOWNSCALE,
 	FEAT_PARAM_LINEWIDTH,
 	FEAT_PARAM_LINEWIDTH,
-	FEAT_PARAM_MGR_WIDTH,
-	FEAT_PARAM_MGR_HEIGHT,
 };
 };
 
 
 /* DSS Feature Functions */
 /* DSS Feature Functions */
-int dss_feat_get_num_mgrs(void);
-int dss_feat_get_num_ovls(void);
 int dss_feat_get_num_wbs(void);
 int dss_feat_get_num_wbs(void);
 unsigned long dss_feat_get_param_min(enum dss_range_param param);
 unsigned long dss_feat_get_param_min(enum dss_range_param param);
 unsigned long dss_feat_get_param_max(enum dss_range_param param);
 unsigned long dss_feat_get_param_max(enum dss_range_param param);
-enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
-enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel);
-enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
 enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane);
 enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane);
 bool dss_feat_color_mode_supported(enum omap_plane plane,
 bool dss_feat_color_mode_supported(enum omap_plane plane,
 		enum omap_color_mode color_mode);
 		enum omap_color_mode color_mode);

+ 114 - 45
drivers/video/omap2/dss/hdmi.c

@@ -60,6 +60,7 @@
 static struct {
 static struct {
 	struct mutex lock;
 	struct mutex lock;
 	struct platform_device *pdev;
 	struct platform_device *pdev;
+
 	struct hdmi_ip_data ip_data;
 	struct hdmi_ip_data ip_data;
 
 
 	struct clk *sys_clk;
 	struct clk *sys_clk;
@@ -295,6 +296,12 @@ static const struct hdmi_config vesa_timings[] = {
 			false, },
 			false, },
 		{ 0x55, HDMI_DVI },
 		{ 0x55, HDMI_DVI },
 	},
 	},
+	{
+		{ 1920, 1200, 154000, 32, 48, 80, 6, 3, 26,
+			OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
+			false, },
+		{ 0x44, HDMI_DVI },
+	},
 };
 };
 
 
 static int hdmi_runtime_get(void)
 static int hdmi_runtime_get(void)
@@ -323,7 +330,6 @@ static void hdmi_runtime_put(void)
 
 
 static int __init hdmi_init_display(struct omap_dss_device *dssdev)
 static int __init hdmi_init_display(struct omap_dss_device *dssdev)
 {
 {
-	struct omap_dss_board_info *pdata = hdmi.pdev->dev.platform_data;
 	int r;
 	int r;
 
 
 	struct gpio gpios[] = {
 	struct gpio gpios[] = {
@@ -334,13 +340,17 @@ static int __init hdmi_init_display(struct omap_dss_device *dssdev)
 
 
 	DSSDBG("init_display\n");
 	DSSDBG("init_display\n");
 
 
-	dss_init_hdmi_ip_ops(&hdmi.ip_data, pdata->version);
+	dss_init_hdmi_ip_ops(&hdmi.ip_data, omapdss_get_version());
 
 
 	if (hdmi.vdda_hdmi_dac_reg == NULL) {
 	if (hdmi.vdda_hdmi_dac_reg == NULL) {
 		struct regulator *reg;
 		struct regulator *reg;
 
 
 		reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac");
 		reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac");
 
 
+		/* DT HACK: try VDAC to make omapdss work for o4 sdp/panda */
+		if (IS_ERR(reg))
+			reg = devm_regulator_get(&hdmi.pdev->dev, "VDAC");
+
 		if (IS_ERR(reg)) {
 		if (IS_ERR(reg)) {
 			DSSERR("can't get VDDA_HDMI_DAC regulator\n");
 			DSSERR("can't get VDDA_HDMI_DAC regulator\n");
 			return PTR_ERR(reg);
 			return PTR_ERR(reg);
@@ -356,7 +366,7 @@ static int __init hdmi_init_display(struct omap_dss_device *dssdev)
 	return 0;
 	return 0;
 }
 }
 
 
-static void __exit hdmi_uninit_display(struct omap_dss_device *dssdev)
+static void hdmi_uninit_display(struct omap_dss_device *dssdev)
 {
 {
 	DSSDBG("uninit_display\n");
 	DSSDBG("uninit_display\n");
 
 
@@ -399,7 +409,8 @@ static bool hdmi_timings_compare(struct omap_video_timings *timing1,
 {
 {
 	int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;
 	int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;
 
 
-	if ((timing2->pixel_clock == timing1->pixel_clock) &&
+	if ((DIV_ROUND_CLOSEST(timing2->pixel_clock, 1000) ==
+			DIV_ROUND_CLOSEST(timing1->pixel_clock, 1000)) &&
 		(timing2->x_res == timing1->x_res) &&
 		(timing2->x_res == timing1->x_res) &&
 		(timing2->y_res == timing1->y_res)) {
 		(timing2->y_res == timing1->y_res)) {
 
 
@@ -501,12 +512,9 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
 	DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
 	DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
 }
 }
 
 
-static int hdmi_power_on(struct omap_dss_device *dssdev)
+static int hdmi_power_on_core(struct omap_dss_device *dssdev)
 {
 {
 	int r;
 	int r;
-	struct omap_video_timings *p;
-	struct omap_overlay_manager *mgr = dssdev->output->manager;
-	unsigned long phy;
 
 
 	gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
 	gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
 	gpio_set_value(hdmi.ls_oe_gpio, 1);
 	gpio_set_value(hdmi.ls_oe_gpio, 1);
@@ -522,6 +530,38 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 	if (r)
 	if (r)
 		goto err_runtime_get;
 		goto err_runtime_get;
 
 
+	/* Make selection of HDMI in DSS */
+	dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
+
+	return 0;
+
+err_runtime_get:
+	regulator_disable(hdmi.vdda_hdmi_dac_reg);
+err_vdac_enable:
+	gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
+	gpio_set_value(hdmi.ls_oe_gpio, 0);
+	return r;
+}
+
+static void hdmi_power_off_core(struct omap_dss_device *dssdev)
+{
+	hdmi_runtime_put();
+	regulator_disable(hdmi.vdda_hdmi_dac_reg);
+	gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
+	gpio_set_value(hdmi.ls_oe_gpio, 0);
+}
+
+static int hdmi_power_on_full(struct omap_dss_device *dssdev)
+{
+	int r;
+	struct omap_video_timings *p;
+	struct omap_overlay_manager *mgr = dssdev->output->manager;
+	unsigned long phy;
+
+	r = hdmi_power_on_core(dssdev);
+	if (r)
+		return r;
+
 	dss_mgr_disable(mgr);
 	dss_mgr_disable(mgr);
 
 
 	p = &hdmi.ip_data.cfg.timings;
 	p = &hdmi.ip_data.cfg.timings;
@@ -549,17 +589,6 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 
 
 	hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
 	hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
 
 
-	/* Make selection of HDMI in DSS */
-	dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
-
-	/* Select the dispc clock source as PRCM clock, to ensure that it is not
-	 * DSI PLL source as the clock selected by DSI PLL might not be
-	 * sufficient for the resolution selected / that can be changed
-	 * dynamically by user. This can be moved to single location , say
-	 * Boardfile.
-	 */
-	dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
-
 	/* bypass TV gamma table */
 	/* bypass TV gamma table */
 	dispc_enable_gamma_table(0);
 	dispc_enable_gamma_table(0);
 
 
@@ -583,16 +612,11 @@ err_vid_enable:
 err_phy_enable:
 err_phy_enable:
 	hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
 	hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
 err_pll_enable:
 err_pll_enable:
-	hdmi_runtime_put();
-err_runtime_get:
-	regulator_disable(hdmi.vdda_hdmi_dac_reg);
-err_vdac_enable:
-	gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
-	gpio_set_value(hdmi.ls_oe_gpio, 0);
+	hdmi_power_off_core(dssdev);
 	return -EIO;
 	return -EIO;
 }
 }
 
 
-static void hdmi_power_off(struct omap_dss_device *dssdev)
+static void hdmi_power_off_full(struct omap_dss_device *dssdev)
 {
 {
 	struct omap_overlay_manager *mgr = dssdev->output->manager;
 	struct omap_overlay_manager *mgr = dssdev->output->manager;
 
 
@@ -601,12 +625,8 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
 	hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
 	hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
 	hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
 	hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
 	hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
 	hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
-	hdmi_runtime_put();
-
-	regulator_disable(hdmi.vdda_hdmi_dac_reg);
 
 
-	gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
-	gpio_set_value(hdmi.ls_oe_gpio, 0);
+	hdmi_power_off_core(dssdev);
 }
 }
 
 
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
@@ -716,7 +736,7 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
 		goto err0;
 		goto err0;
 	}
 	}
 
 
-	r = hdmi_power_on(dssdev);
+	r = hdmi_power_on_full(dssdev);
 	if (r) {
 	if (r) {
 		DSSERR("failed to power on device\n");
 		DSSERR("failed to power on device\n");
 		goto err1;
 		goto err1;
@@ -738,13 +758,48 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
 
 
 	mutex_lock(&hdmi.lock);
 	mutex_lock(&hdmi.lock);
 
 
-	hdmi_power_off(dssdev);
+	hdmi_power_off_full(dssdev);
 
 
 	omap_dss_stop_device(dssdev);
 	omap_dss_stop_device(dssdev);
 
 
 	mutex_unlock(&hdmi.lock);
 	mutex_unlock(&hdmi.lock);
 }
 }
 
 
+int omapdss_hdmi_core_enable(struct omap_dss_device *dssdev)
+{
+	int r = 0;
+
+	DSSDBG("ENTER omapdss_hdmi_core_enable\n");
+
+	mutex_lock(&hdmi.lock);
+
+	hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio;
+
+	r = hdmi_power_on_core(dssdev);
+	if (r) {
+		DSSERR("failed to power on device\n");
+		goto err0;
+	}
+
+	mutex_unlock(&hdmi.lock);
+	return 0;
+
+err0:
+	mutex_unlock(&hdmi.lock);
+	return r;
+}
+
+void omapdss_hdmi_core_disable(struct omap_dss_device *dssdev)
+{
+	DSSDBG("Enter omapdss_hdmi_core_disable\n");
+
+	mutex_lock(&hdmi.lock);
+
+	hdmi_power_off_core(dssdev);
+
+	mutex_unlock(&hdmi.lock);
+}
+
 static int hdmi_get_clocks(struct platform_device *pdev)
 static int hdmi_get_clocks(struct platform_device *pdev)
 {
 {
 	struct clk *clk;
 	struct clk *clk;
@@ -913,7 +968,7 @@ int hdmi_audio_config(struct omap_dss_audio *audio)
 static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev)
 static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev)
 {
 {
 	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
 	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-	const char *def_disp_name = dss_get_default_display_name();
+	const char *def_disp_name = omapdss_get_default_display_name();
 	struct omap_dss_device *def_dssdev;
 	struct omap_dss_device *def_dssdev;
 	int i;
 	int i;
 
 
@@ -971,9 +1026,19 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
 		return;
 		return;
 	}
 	}
 
 
+	r = omapdss_output_set_device(&hdmi.output, dssdev);
+	if (r) {
+		DSSERR("failed to connect output to new device: %s\n",
+				dssdev->name);
+		dss_put_device(dssdev);
+		return;
+	}
+
 	r = dss_add_device(dssdev);
 	r = dss_add_device(dssdev);
 	if (r) {
 	if (r) {
 		DSSERR("device %s register failed: %d\n", dssdev->name, r);
 		DSSERR("device %s register failed: %d\n", dssdev->name, r);
+		omapdss_output_unset_device(&hdmi.output);
+		hdmi_uninit_display(dssdev);
 		dss_put_device(dssdev);
 		dss_put_device(dssdev);
 		return;
 		return;
 	}
 	}
@@ -1000,22 +1065,22 @@ static void __exit hdmi_uninit_output(struct platform_device *pdev)
 /* HDMI HW IP initialisation */
 /* HDMI HW IP initialisation */
 static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
 static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
 {
 {
-	struct resource *hdmi_mem;
+	struct resource *res;
 	int r;
 	int r;
 
 
 	hdmi.pdev = pdev;
 	hdmi.pdev = pdev;
 
 
 	mutex_init(&hdmi.lock);
 	mutex_init(&hdmi.lock);
+	mutex_init(&hdmi.ip_data.lock);
 
 
-	hdmi_mem = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0);
-	if (!hdmi_mem) {
+	res = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0);
+	if (!res) {
 		DSSERR("can't get IORESOURCE_MEM HDMI\n");
 		DSSERR("can't get IORESOURCE_MEM HDMI\n");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
 	/* Base address taken from platform */
 	/* Base address taken from platform */
-	hdmi.ip_data.base_wp = ioremap(hdmi_mem->start,
-						resource_size(hdmi_mem));
+	hdmi.ip_data.base_wp = devm_request_and_ioremap(&pdev->dev, res);
 	if (!hdmi.ip_data.base_wp) {
 	if (!hdmi.ip_data.base_wp) {
 		DSSERR("can't ioremap WP\n");
 		DSSERR("can't ioremap WP\n");
 		return -ENOMEM;
 		return -ENOMEM;
@@ -1023,7 +1088,7 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
 
 
 	r = hdmi_get_clocks(pdev);
 	r = hdmi_get_clocks(pdev);
 	if (r) {
 	if (r) {
-		iounmap(hdmi.ip_data.base_wp);
+		DSSERR("can't get clocks\n");
 		return r;
 		return r;
 	}
 	}
 
 
@@ -1034,9 +1099,11 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
 	hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
 	hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
 	hdmi.ip_data.phy_offset = HDMI_PHY;
 	hdmi.ip_data.phy_offset = HDMI_PHY;
 
 
-	mutex_init(&hdmi.ip_data.lock);
-
-	hdmi_panel_init();
+	r = hdmi_panel_init();
+	if (r) {
+		DSSERR("can't init panel\n");
+		goto err_panel_init;
+	}
 
 
 	dss_debugfs_create_file("hdmi", hdmi_dump_regs);
 	dss_debugfs_create_file("hdmi", hdmi_dump_regs);
 
 
@@ -1045,6 +1112,10 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
 	hdmi_probe_pdata(pdev);
 	hdmi_probe_pdata(pdev);
 
 
 	return 0;
 	return 0;
+
+err_panel_init:
+	hdmi_put_clocks();
+	return r;
 }
 }
 
 
 static int __exit hdmi_remove_child(struct device *dev, void *data)
 static int __exit hdmi_remove_child(struct device *dev, void *data)
@@ -1068,8 +1139,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
 
 
 	hdmi_put_clocks();
 	hdmi_put_clocks();
 
 
-	iounmap(hdmi.ip_data.base_wp);
-
 	return 0;
 	return 0;
 }
 }
 
 

+ 15 - 67
drivers/video/omap2/dss/hdmi_panel.c

@@ -280,58 +280,6 @@ static void hdmi_panel_disable(struct omap_dss_device *dssdev)
 	mutex_unlock(&hdmi.lock);
 	mutex_unlock(&hdmi.lock);
 }
 }
 
 
-static int hdmi_panel_suspend(struct omap_dss_device *dssdev)
-{
-	int r = 0;
-
-	mutex_lock(&hdmi.lock);
-
-	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
-		r = -EINVAL;
-		goto err;
-	}
-
-	/*
-	 * TODO: notify audio users that the display was suspended. For now,
-	 * disable audio locally to not break our audio state machine.
-	 */
-	hdmi_panel_audio_disable(dssdev);
-
-	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-	omapdss_hdmi_display_disable(dssdev);
-
-err:
-	mutex_unlock(&hdmi.lock);
-
-	return r;
-}
-
-static int hdmi_panel_resume(struct omap_dss_device *dssdev)
-{
-	int r = 0;
-
-	mutex_lock(&hdmi.lock);
-
-	if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
-		r = -EINVAL;
-		goto err;
-	}
-
-	r = omapdss_hdmi_display_enable(dssdev);
-	if (r) {
-		DSSERR("failed to power on\n");
-		goto err;
-	}
-	/* TODO: notify audio users that the panel resumed. */
-
-	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-err:
-	mutex_unlock(&hdmi.lock);
-
-	return r;
-}
-
 static void hdmi_get_timings(struct omap_dss_device *dssdev,
 static void hdmi_get_timings(struct omap_dss_device *dssdev,
 			struct omap_video_timings *timings)
 			struct omap_video_timings *timings)
 {
 {
@@ -379,20 +327,22 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev,
 static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
 static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
 {
 {
 	int r;
 	int r;
+	bool need_enable;
 
 
 	mutex_lock(&hdmi.lock);
 	mutex_lock(&hdmi.lock);
 
 
-	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
-		r = omapdss_hdmi_display_enable(dssdev);
+	need_enable = dssdev->state == OMAP_DSS_DISPLAY_DISABLED;
+
+	if (need_enable) {
+		r = omapdss_hdmi_core_enable(dssdev);
 		if (r)
 		if (r)
 			goto err;
 			goto err;
 	}
 	}
 
 
 	r = omapdss_hdmi_read_edid(buf, len);
 	r = omapdss_hdmi_read_edid(buf, len);
 
 
-	if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
-			dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
-		omapdss_hdmi_display_disable(dssdev);
+	if (need_enable)
+		omapdss_hdmi_core_disable(dssdev);
 err:
 err:
 	mutex_unlock(&hdmi.lock);
 	mutex_unlock(&hdmi.lock);
 
 
@@ -402,20 +352,22 @@ err:
 static bool hdmi_detect(struct omap_dss_device *dssdev)
 static bool hdmi_detect(struct omap_dss_device *dssdev)
 {
 {
 	int r;
 	int r;
+	bool need_enable;
 
 
 	mutex_lock(&hdmi.lock);
 	mutex_lock(&hdmi.lock);
 
 
-	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
-		r = omapdss_hdmi_display_enable(dssdev);
+	need_enable = dssdev->state == OMAP_DSS_DISPLAY_DISABLED;
+
+	if (need_enable) {
+		r = omapdss_hdmi_core_enable(dssdev);
 		if (r)
 		if (r)
 			goto err;
 			goto err;
 	}
 	}
 
 
 	r = omapdss_hdmi_detect();
 	r = omapdss_hdmi_detect();
 
 
-	if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
-			dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
-		omapdss_hdmi_display_disable(dssdev);
+	if (need_enable)
+		omapdss_hdmi_core_disable(dssdev);
 err:
 err:
 	mutex_unlock(&hdmi.lock);
 	mutex_unlock(&hdmi.lock);
 
 
@@ -427,8 +379,6 @@ static struct omap_dss_driver hdmi_driver = {
 	.remove		= hdmi_panel_remove,
 	.remove		= hdmi_panel_remove,
 	.enable		= hdmi_panel_enable,
 	.enable		= hdmi_panel_enable,
 	.disable	= hdmi_panel_disable,
 	.disable	= hdmi_panel_disable,
-	.suspend	= hdmi_panel_suspend,
-	.resume		= hdmi_panel_resume,
 	.get_timings	= hdmi_get_timings,
 	.get_timings	= hdmi_get_timings,
 	.set_timings	= hdmi_set_timings,
 	.set_timings	= hdmi_set_timings,
 	.check_timings	= hdmi_check_timings,
 	.check_timings	= hdmi_check_timings,
@@ -454,9 +404,7 @@ int hdmi_panel_init(void)
 	spin_lock_init(&hdmi.audio_lock);
 	spin_lock_init(&hdmi.audio_lock);
 #endif
 #endif
 
 
-	omap_dss_register_driver(&hdmi_driver);
-
-	return 0;
+	return omap_dss_register_driver(&hdmi_driver);
 }
 }
 
 
 void hdmi_panel_exit(void)
 void hdmi_panel_exit(void)

+ 0 - 39
drivers/video/omap2/dss/manager.c

@@ -36,36 +36,6 @@
 static int num_managers;
 static int num_managers;
 static struct omap_overlay_manager *managers;
 static struct omap_overlay_manager *managers;
 
 
-static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
-{
-	return mgr->output ? mgr->output->device : NULL;
-}
-
-static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
-{
-	unsigned long timeout = msecs_to_jiffies(500);
-	struct omap_dss_device *dssdev = mgr->get_device(mgr);
-	u32 irq;
-	int r;
-
-	r = dispc_runtime_get();
-	if (r)
-		return r;
-
-	if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
-		irq = DISPC_IRQ_EVSYNC_ODD;
-	else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)
-		irq = DISPC_IRQ_EVSYNC_EVEN;
-	else
-		irq = dispc_mgr_get_vsync_irq(mgr->id);
-
-	r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
-
-	dispc_runtime_put();
-
-	return r;
-}
-
 int dss_init_overlay_managers(struct platform_device *pdev)
 int dss_init_overlay_managers(struct platform_device *pdev)
 {
 {
 	int i, r;
 	int i, r;
@@ -99,15 +69,6 @@ int dss_init_overlay_managers(struct platform_device *pdev)
 			break;
 			break;
 		}
 		}
 
 
-		mgr->set_output = &dss_mgr_set_output;
-		mgr->unset_output = &dss_mgr_unset_output;
-		mgr->apply = &omap_dss_mgr_apply;
-		mgr->set_manager_info = &dss_mgr_set_info;
-		mgr->get_manager_info = &dss_mgr_get_info;
-		mgr->wait_for_go = &dss_mgr_wait_for_go;
-		mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
-		mgr->get_device = &dss_mgr_get_device;
-
 		mgr->caps = 0;
 		mgr->caps = 0;
 		mgr->supported_displays =
 		mgr->supported_displays =
 			dss_feat_get_supported_displays(mgr->id);
 			dss_feat_get_supported_displays(mgr->id);

+ 61 - 29
drivers/video/omap2/dss/output.c

@@ -114,35 +114,67 @@ struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id)
 	return NULL;
 	return NULL;
 }
 }
 
 
-struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev)
+static const struct dss_mgr_ops *dss_mgr_ops;
+
+int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops)
 {
 {
-	struct omap_dss_output *out = NULL;
-	enum omap_dss_output_id id;
-
-	switch (dssdev->type) {
-	case OMAP_DISPLAY_TYPE_DPI:
-		out = omap_dss_get_output(OMAP_DSS_OUTPUT_DPI);
-		break;
-	case OMAP_DISPLAY_TYPE_DBI:
-		out = omap_dss_get_output(OMAP_DSS_OUTPUT_DBI);
-		break;
-	case OMAP_DISPLAY_TYPE_SDI:
-		out = omap_dss_get_output(OMAP_DSS_OUTPUT_SDI);
-		break;
-	case OMAP_DISPLAY_TYPE_VENC:
-		out = omap_dss_get_output(OMAP_DSS_OUTPUT_VENC);
-		break;
-	case OMAP_DISPLAY_TYPE_HDMI:
-		out = omap_dss_get_output(OMAP_DSS_OUTPUT_HDMI);
-		break;
-	case OMAP_DISPLAY_TYPE_DSI:
-		id = dssdev->phy.dsi.module == 0 ? OMAP_DSS_OUTPUT_DSI1 :
-					OMAP_DSS_OUTPUT_DSI2;
-		out = omap_dss_get_output(id);
-		break;
-	default:
-		break;
-	}
+	if (dss_mgr_ops)
+		return -EBUSY;
+
+	dss_mgr_ops = mgr_ops;
+
+	return 0;
+}
+EXPORT_SYMBOL(dss_install_mgr_ops);
+
+void dss_uninstall_mgr_ops(void)
+{
+	dss_mgr_ops = NULL;
+}
+EXPORT_SYMBOL(dss_uninstall_mgr_ops);
+
+void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
+		const struct omap_video_timings *timings)
+{
+	dss_mgr_ops->set_timings(mgr, timings);
+}
+EXPORT_SYMBOL(dss_mgr_set_timings);
+
+void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
+		const struct dss_lcd_mgr_config *config)
+{
+	dss_mgr_ops->set_lcd_config(mgr, config);
+}
+EXPORT_SYMBOL(dss_mgr_set_lcd_config);
+
+int dss_mgr_enable(struct omap_overlay_manager *mgr)
+{
+	return dss_mgr_ops->enable(mgr);
+}
+EXPORT_SYMBOL(dss_mgr_enable);
+
+void dss_mgr_disable(struct omap_overlay_manager *mgr)
+{
+	dss_mgr_ops->disable(mgr);
+}
+EXPORT_SYMBOL(dss_mgr_disable);
 
 
-	return out;
+void dss_mgr_start_update(struct omap_overlay_manager *mgr)
+{
+	dss_mgr_ops->start_update(mgr);
+}
+EXPORT_SYMBOL(dss_mgr_start_update);
+
+int dss_mgr_register_framedone_handler(struct omap_overlay_manager *mgr,
+		void (*handler)(void *), void *data)
+{
+	return dss_mgr_ops->register_framedone_handler(mgr, handler, data);
+}
+EXPORT_SYMBOL(dss_mgr_register_framedone_handler);
+
+void dss_mgr_unregister_framedone_handler(struct omap_overlay_manager *mgr,
+		void (*handler)(void *), void *data)
+{
+	dss_mgr_ops->unregister_framedone_handler(mgr, handler, data);
 }
 }
+EXPORT_SYMBOL(dss_mgr_unregister_framedone_handler);

+ 0 - 17
drivers/video/omap2/dss/overlay.c

@@ -38,13 +38,6 @@
 static int num_overlays;
 static int num_overlays;
 static struct omap_overlay *overlays;
 static struct omap_overlay *overlays;
 
 
-static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
-{
-	return ovl->manager ?
-		(ovl->manager->output ? ovl->manager->output->device : NULL) :
-		NULL;
-}
-
 int omap_dss_get_num_overlays(void)
 int omap_dss_get_num_overlays(void)
 {
 {
 	return num_overlays;
 	return num_overlays;
@@ -93,16 +86,6 @@ void dss_init_overlays(struct platform_device *pdev)
 			break;
 			break;
 		}
 		}
 
 
-		ovl->is_enabled = &dss_ovl_is_enabled;
-		ovl->enable = &dss_ovl_enable;
-		ovl->disable = &dss_ovl_disable;
-		ovl->set_manager = &dss_ovl_set_manager;
-		ovl->unset_manager = &dss_ovl_unset_manager;
-		ovl->set_overlay_info = &dss_ovl_set_info;
-		ovl->get_overlay_info = &dss_ovl_get_info;
-		ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
-		ovl->get_device = &dss_ovl_get_device;
-
 		ovl->caps = dss_feat_get_overlay_caps(ovl->id);
 		ovl->caps = dss_feat_get_overlay_caps(ovl->id);
 		ovl->supported_modes =
 		ovl->supported_modes =
 			dss_feat_get_supported_color_modes(ovl->id);
 			dss_feat_get_supported_color_modes(ovl->id);

+ 17 - 6
drivers/video/omap2/dss/rfbi.c

@@ -342,7 +342,7 @@ static int rfbi_transfer_area(struct omap_dss_device *dssdev,
 	return 0;
 	return 0;
 }
 }
 
 
-static void framedone_callback(void *data, u32 mask)
+static void framedone_callback(void *data)
 {
 {
 	void (*callback)(void *data);
 	void (*callback)(void *data);
 
 
@@ -908,8 +908,8 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
 		goto err0;
 		goto err0;
 	}
 	}
 
 
-	r = omap_dispc_register_isr(framedone_callback, NULL,
-			DISPC_IRQ_FRAMEDONE);
+	r = dss_mgr_register_framedone_handler(out->manager,
+			framedone_callback, NULL);
 	if (r) {
 	if (r) {
 		DSSERR("can't get FRAMEDONE irq\n");
 		DSSERR("can't get FRAMEDONE irq\n");
 		goto err1;
 		goto err1;
@@ -933,8 +933,10 @@ EXPORT_SYMBOL(omapdss_rfbi_display_enable);
 
 
 void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
 void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
 {
 {
-	omap_dispc_unregister_isr(framedone_callback, NULL,
-			DISPC_IRQ_FRAMEDONE);
+	struct omap_dss_output *out = dssdev->output;
+
+	dss_mgr_unregister_framedone_handler(out->manager,
+			framedone_callback, NULL);
 	omap_dss_stop_device(dssdev);
 	omap_dss_stop_device(dssdev);
 
 
 	rfbi_runtime_put();
 	rfbi_runtime_put();
@@ -950,7 +952,7 @@ static int __init rfbi_init_display(struct omap_dss_device *dssdev)
 static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev)
 static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev)
 {
 {
 	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
 	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-	const char *def_disp_name = dss_get_default_display_name();
+	const char *def_disp_name = omapdss_get_default_display_name();
 	struct omap_dss_device *def_dssdev;
 	struct omap_dss_device *def_dssdev;
 	int i;
 	int i;
 
 
@@ -999,9 +1001,18 @@ static void __init rfbi_probe_pdata(struct platform_device *rfbidev)
 		return;
 		return;
 	}
 	}
 
 
+	r = omapdss_output_set_device(&rfbi.output, dssdev);
+	if (r) {
+		DSSERR("failed to connect output to new device: %s\n",
+				dssdev->name);
+		dss_put_device(dssdev);
+		return;
+	}
+
 	r = dss_add_device(dssdev);
 	r = dss_add_device(dssdev);
 	if (r) {
 	if (r) {
 		DSSERR("device %s register failed: %d\n", dssdev->name, r);
 		DSSERR("device %s register failed: %d\n", dssdev->name, r);
+		omapdss_output_unset_device(&rfbi.output);
 		dss_put_device(dssdev);
 		dss_put_device(dssdev);
 		return;
 		return;
 	}
 	}

+ 10 - 1
drivers/video/omap2/dss/sdi.c

@@ -205,7 +205,7 @@ static int __init sdi_init_display(struct omap_dss_device *dssdev)
 static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev)
 static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev)
 {
 {
 	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
 	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-	const char *def_disp_name = dss_get_default_display_name();
+	const char *def_disp_name = omapdss_get_default_display_name();
 	struct omap_dss_device *def_dssdev;
 	struct omap_dss_device *def_dssdev;
 	int i;
 	int i;
 
 
@@ -254,9 +254,18 @@ static void __init sdi_probe_pdata(struct platform_device *sdidev)
 		return;
 		return;
 	}
 	}
 
 
+	r = omapdss_output_set_device(&sdi.output, dssdev);
+	if (r) {
+		DSSERR("failed to connect output to new device: %s\n",
+				dssdev->name);
+		dss_put_device(dssdev);
+		return;
+	}
+
 	r = dss_add_device(dssdev);
 	r = dss_add_device(dssdev);
 	if (r) {
 	if (r) {
 		DSSERR("device %s register failed: %d\n", dssdev->name, r);
 		DSSERR("device %s register failed: %d\n", dssdev->name, r);
+		omapdss_output_unset_device(&sdi.output);
 		dss_put_device(dssdev);
 		dss_put_device(dssdev);
 		return;
 		return;
 	}
 	}

+ 3 - 0
drivers/video/omap2/dss/ti_hdmi.h

@@ -102,6 +102,8 @@ struct ti_hdmi_ip_ops {
 
 
 	int (*audio_config)(struct hdmi_ip_data *ip_data,
 	int (*audio_config)(struct hdmi_ip_data *ip_data,
 		struct omap_dss_audio *audio);
 		struct omap_dss_audio *audio);
+
+	int (*audio_get_dma_port)(u32 *offset, u32 *size);
 #endif
 #endif
 
 
 };
 };
@@ -183,5 +185,6 @@ int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data);
 void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data);
 void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data);
 int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data,
 int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data,
 		struct omap_dss_audio *audio);
 		struct omap_dss_audio *audio);
+int ti_hdmi_4xxx_audio_get_dma_port(u32 *offset, u32 *size);
 #endif
 #endif
 #endif
 #endif

+ 10 - 1
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c

@@ -899,7 +899,7 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
 #define DUMPCOREAV(r) seq_printf(s, "%-35s %08x\n", #r,\
 #define DUMPCOREAV(r) seq_printf(s, "%-35s %08x\n", #r,\
 		hdmi_read_reg(hdmi_av_base(ip_data), r))
 		hdmi_read_reg(hdmi_av_base(ip_data), r))
 #define DUMPCOREAV2(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \
 #define DUMPCOREAV2(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \
-		(i < 10) ? 32 - strlen(#r) : 31 - strlen(#r), " ", \
+		(i < 10) ? 32 - (int)strlen(#r) : 31 - (int)strlen(#r), " ", \
 		hdmi_read_reg(hdmi_av_base(ip_data), CORE_REG(i, r)))
 		hdmi_read_reg(hdmi_av_base(ip_data), CORE_REG(i, r)))
 
 
 	DUMPCORE(HDMI_CORE_SYS_VND_IDL);
 	DUMPCORE(HDMI_CORE_SYS_VND_IDL);
@@ -1418,4 +1418,13 @@ void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data)
 	REG_FLD_MOD(hdmi_wp_base(ip_data),
 	REG_FLD_MOD(hdmi_wp_base(ip_data),
 		    HDMI_WP_AUDIO_CTRL, false, 30, 30);
 		    HDMI_WP_AUDIO_CTRL, false, 30, 30);
 }
 }
+
+int ti_hdmi_4xxx_audio_get_dma_port(u32 *offset, u32 *size)
+{
+	if (!offset || !size)
+		return -EINVAL;
+	*offset = HDMI_WP_AUDIO_DATA;
+	*size = 4;
+	return 0;
+}
 #endif
 #endif

+ 10 - 1
drivers/video/omap2/dss/venc.c

@@ -744,7 +744,7 @@ static void venc_put_clocks(void)
 static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev)
 static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev)
 {
 {
 	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
 	struct omap_dss_board_info *pdata = pdev->dev.platform_data;
-	const char *def_disp_name = dss_get_default_display_name();
+	const char *def_disp_name = omapdss_get_default_display_name();
 	struct omap_dss_device *def_dssdev;
 	struct omap_dss_device *def_dssdev;
 	int i;
 	int i;
 
 
@@ -795,9 +795,18 @@ static void __init venc_probe_pdata(struct platform_device *vencdev)
 		return;
 		return;
 	}
 	}
 
 
+	r = omapdss_output_set_device(&venc.output, dssdev);
+	if (r) {
+		DSSERR("failed to connect output to new device: %s\n",
+				dssdev->name);
+		dss_put_device(dssdev);
+		return;
+	}
+
 	r = dss_add_device(dssdev);
 	r = dss_add_device(dssdev);
 	if (r) {
 	if (r) {
 		DSSERR("device %s register failed: %d\n", dssdev->name, r);
 		DSSERR("device %s register failed: %d\n", dssdev->name, r);
+		omapdss_output_unset_device(&venc.output);
 		dss_put_device(dssdev);
 		dss_put_device(dssdev);
 		return;
 		return;
 	}
 	}

+ 0 - 19
drivers/video/omap2/dss/venc_panel.c

@@ -157,12 +157,6 @@ static void venc_panel_disable(struct omap_dss_device *dssdev)
 	if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
 	if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
 		goto end;
 		goto end;
 
 
-	if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
-		/* suspended is the same as disabled with venc */
-		dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-		goto end;
-	}
-
 	omapdss_venc_display_disable(dssdev);
 	omapdss_venc_display_disable(dssdev);
 
 
 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
@@ -170,17 +164,6 @@ end:
 	mutex_unlock(&venc_panel.lock);
 	mutex_unlock(&venc_panel.lock);
 }
 }
 
 
-static int venc_panel_suspend(struct omap_dss_device *dssdev)
-{
-	venc_panel_disable(dssdev);
-	return 0;
-}
-
-static int venc_panel_resume(struct omap_dss_device *dssdev)
-{
-	return venc_panel_enable(dssdev);
-}
-
 static void venc_panel_set_timings(struct omap_dss_device *dssdev,
 static void venc_panel_set_timings(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings)
 		struct omap_video_timings *timings)
 {
 {
@@ -222,8 +205,6 @@ static struct omap_dss_driver venc_driver = {
 
 
 	.enable		= venc_panel_enable,
 	.enable		= venc_panel_enable,
 	.disable	= venc_panel_disable,
 	.disable	= venc_panel_disable,
-	.suspend	= venc_panel_suspend,
-	.resume		= venc_panel_resume,
 
 
 	.get_resolution	= omapdss_default_get_resolution,
 	.get_resolution	= omapdss_default_get_resolution,
 	.get_recommended_bpp = omapdss_default_get_recommended_bpp,
 	.get_recommended_bpp = omapdss_default_get_recommended_bpp,

+ 0 - 1
drivers/video/omap2/omapfb/Kconfig

@@ -2,7 +2,6 @@ menuconfig FB_OMAP2
         tristate "OMAP2+ frame buffer support"
         tristate "OMAP2+ frame buffer support"
         depends on FB && OMAP2_DSS && !DRM_OMAP
         depends on FB && OMAP2_DSS && !DRM_OMAP
 
 
-	select OMAP2_VRAM
 	select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
 	select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
         select FB_CFB_FILLRECT
         select FB_CFB_FILLRECT
         select FB_CFB_COPYAREA
         select FB_CFB_COPYAREA

+ 15 - 31
drivers/video/omap2/omapfb/omapfb-ioctl.c

@@ -28,10 +28,10 @@
 #include <linux/omapfb.h>
 #include <linux/omapfb.h>
 #include <linux/vmalloc.h>
 #include <linux/vmalloc.h>
 #include <linux/export.h>
 #include <linux/export.h>
+#include <linux/sizes.h>
 
 
 #include <video/omapdss.h>
 #include <video/omapdss.h>
 #include <video/omapvrfb.h>
 #include <video/omapvrfb.h>
-#include <plat/vram.h>
 
 
 #include "omapfb.h"
 #include "omapfb.h"
 
 
@@ -211,6 +211,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
 {
 {
 	struct omapfb_info *ofbi = FB2OFB(fbi);
 	struct omapfb_info *ofbi = FB2OFB(fbi);
 	struct omapfb2_device *fbdev = ofbi->fbdev;
 	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omap_dss_device *display = fb2display(fbi);
 	struct omapfb2_mem_region *rg;
 	struct omapfb2_mem_region *rg;
 	int r = 0, i;
 	int r = 0, i;
 	size_t size;
 	size_t size;
@@ -220,6 +221,9 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
 
 
 	size = PAGE_ALIGN(mi->size);
 	size = PAGE_ALIGN(mi->size);
 
 
+	if (display && display->driver->sync)
+		display->driver->sync(display);
+
 	rg = ofbi->region;
 	rg = ofbi->region;
 
 
 	down_write_nested(&rg->lock, rg->id);
 	down_write_nested(&rg->lock, rg->id);
@@ -279,7 +283,7 @@ static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
 	return 0;
 	return 0;
 }
 }
 
 
-static int omapfb_update_window_nolock(struct fb_info *fbi,
+static int omapfb_update_window(struct fb_info *fbi,
 		u32 x, u32 y, u32 w, u32 h)
 		u32 x, u32 y, u32 w, u32 h)
 {
 {
 	struct omap_dss_device *display = fb2display(fbi);
 	struct omap_dss_device *display = fb2display(fbi);
@@ -299,27 +303,6 @@ static int omapfb_update_window_nolock(struct fb_info *fbi,
 	return display->driver->update(display, x, y, w, h);
 	return display->driver->update(display, x, y, w, h);
 }
 }
 
 
-/* This function is exported for SGX driver use */
-int omapfb_update_window(struct fb_info *fbi,
-		u32 x, u32 y, u32 w, u32 h)
-{
-	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_device *fbdev = ofbi->fbdev;
-	int r;
-
-	if (!lock_fb_info(fbi))
-		return -ENODEV;
-	omapfb_lock(fbdev);
-
-	r = omapfb_update_window_nolock(fbi, x, y, w, h);
-
-	omapfb_unlock(fbdev);
-	unlock_fb_info(fbi);
-
-	return r;
-}
-EXPORT_SYMBOL(omapfb_update_window);
-
 int omapfb_set_update_mode(struct fb_info *fbi,
 int omapfb_set_update_mode(struct fb_info *fbi,
 				   enum omapfb_update_mode mode)
 				   enum omapfb_update_mode mode)
 {
 {
@@ -646,7 +629,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
 			break;
 			break;
 		}
 		}
 
 
-		r = omapfb_update_window_nolock(fbi, p.uwnd_o.x, p.uwnd_o.y,
+		r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y,
 				p.uwnd_o.width, p.uwnd_o.height);
 				p.uwnd_o.width, p.uwnd_o.height);
 		break;
 		break;
 
 
@@ -663,7 +646,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
 			break;
 			break;
 		}
 		}
 
 
-		r = omapfb_update_window_nolock(fbi, p.uwnd.x, p.uwnd.y,
+		r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y,
 				p.uwnd.width, p.uwnd.height);
 				p.uwnd.width, p.uwnd.height);
 		break;
 		break;
 
 
@@ -853,14 +836,15 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
 		break;
 		break;
 
 
 	case OMAPFB_GET_VRAM_INFO: {
 	case OMAPFB_GET_VRAM_INFO: {
-		unsigned long vram, free, largest;
-
 		DBG("ioctl GET_VRAM_INFO\n");
 		DBG("ioctl GET_VRAM_INFO\n");
 
 
-		omap_vram_get_info(&vram, &free, &largest);
-		p.vram_info.total = vram;
-		p.vram_info.free = free;
-		p.vram_info.largest_free_block = largest;
+		/*
+		 * We don't have the ability to get this vram info anymore.
+		 * Fill in something that should keep the applications working.
+		 */
+		p.vram_info.total = SZ_1M * 64;
+		p.vram_info.free = SZ_1M * 64;
+		p.vram_info.largest_free_block = SZ_1M * 64;
 
 
 		if (copy_to_user((void __user *)arg, &p.vram_info,
 		if (copy_to_user((void __user *)arg, &p.vram_info,
 					sizeof(p.vram_info)))
 					sizeof(p.vram_info)))

+ 137 - 67
drivers/video/omap2/omapfb/omapfb-main.c

@@ -31,7 +31,6 @@
 #include <linux/omapfb.h>
 #include <linux/omapfb.h>
 
 
 #include <video/omapdss.h>
 #include <video/omapdss.h>
-#include <plat/vram.h>
 #include <video/omapvrfb.h>
 #include <video/omapvrfb.h>
 
 
 #include "omapfb.h"
 #include "omapfb.h"
@@ -1258,11 +1257,10 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
 
 
 	switch (blank) {
 	switch (blank) {
 	case FB_BLANK_UNBLANK:
 	case FB_BLANK_UNBLANK:
-		if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
+		if (display->state == OMAP_DSS_DISPLAY_ACTIVE)
 			goto exit;
 			goto exit;
 
 
-		if (display->driver->resume)
-			r = display->driver->resume(display);
+		r = display->driver->enable(display);
 
 
 		if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) &&
 		if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) &&
 				d->update_mode == OMAPFB_AUTO_UPDATE &&
 				d->update_mode == OMAPFB_AUTO_UPDATE &&
@@ -1283,8 +1281,7 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
 		if (d->auto_update_work_enabled)
 		if (d->auto_update_work_enabled)
 			omapfb_stop_auto_update(fbdev, display);
 			omapfb_stop_auto_update(fbdev, display);
 
 
-		if (display->driver->suspend)
-			r = display->driver->suspend(display);
+		display->driver->disable(display);
 
 
 		break;
 		break;
 
 
@@ -1335,24 +1332,25 @@ static void omapfb_free_fbmem(struct fb_info *fbi)
 
 
 	rg = ofbi->region;
 	rg = ofbi->region;
 
 
-	WARN_ON(atomic_read(&rg->map_count));
-
-	if (rg->paddr)
-		if (omap_vram_free(rg->paddr, rg->size))
-			dev_err(fbdev->dev, "VRAM FREE failed\n");
+	if (rg->token == NULL)
+		return;
 
 
-	if (rg->vaddr)
-		iounmap(rg->vaddr);
+	WARN_ON(atomic_read(&rg->map_count));
 
 
 	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
 	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
 		/* unmap the 0 angle rotation */
 		/* unmap the 0 angle rotation */
 		if (rg->vrfb.vaddr[0]) {
 		if (rg->vrfb.vaddr[0]) {
 			iounmap(rg->vrfb.vaddr[0]);
 			iounmap(rg->vrfb.vaddr[0]);
-			omap_vrfb_release_ctx(&rg->vrfb);
 			rg->vrfb.vaddr[0] = NULL;
 			rg->vrfb.vaddr[0] = NULL;
 		}
 		}
+
+		omap_vrfb_release_ctx(&rg->vrfb);
 	}
 	}
 
 
+	dma_free_attrs(fbdev->dev, rg->size, rg->token, rg->dma_handle,
+			&rg->attrs);
+
+	rg->token = NULL;
 	rg->vaddr = NULL;
 	rg->vaddr = NULL;
 	rg->paddr = 0;
 	rg->paddr = 0;
 	rg->alloc = 0;
 	rg->alloc = 0;
@@ -1387,7 +1385,9 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
 	struct omapfb_info *ofbi = FB2OFB(fbi);
 	struct omapfb_info *ofbi = FB2OFB(fbi);
 	struct omapfb2_device *fbdev = ofbi->fbdev;
 	struct omapfb2_device *fbdev = ofbi->fbdev;
 	struct omapfb2_mem_region *rg;
 	struct omapfb2_mem_region *rg;
-	void __iomem *vaddr;
+	void *token;
+	DEFINE_DMA_ATTRS(attrs);
+	dma_addr_t dma_handle;
 	int r;
 	int r;
 
 
 	rg = ofbi->region;
 	rg = ofbi->region;
@@ -1402,42 +1402,40 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
 
 
 	size = PAGE_ALIGN(size);
 	size = PAGE_ALIGN(size);
 
 
-	if (!paddr) {
-		DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
-		r = omap_vram_alloc(size, &paddr);
-	} else {
-		DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr,
-				ofbi->id);
-		r = omap_vram_reserve(paddr, size);
-	}
+	dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
 
 
-	if (r) {
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+		dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
+
+	DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
+
+	token = dma_alloc_attrs(fbdev->dev, size, &dma_handle,
+			GFP_KERNEL, &attrs);
+
+	if (token == NULL) {
 		dev_err(fbdev->dev, "failed to allocate framebuffer\n");
 		dev_err(fbdev->dev, "failed to allocate framebuffer\n");
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
-	if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) {
-		vaddr = ioremap_wc(paddr, size);
-
-		if (!vaddr) {
-			dev_err(fbdev->dev, "failed to ioremap framebuffer\n");
-			omap_vram_free(paddr, size);
-			return -ENOMEM;
-		}
+	DBG("allocated VRAM paddr %lx, vaddr %p\n",
+			(unsigned long)dma_handle, token);
 
 
-		DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr);
-	} else {
+	if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
 		r = omap_vrfb_request_ctx(&rg->vrfb);
 		r = omap_vrfb_request_ctx(&rg->vrfb);
 		if (r) {
 		if (r) {
+			dma_free_attrs(fbdev->dev, size, token, dma_handle,
+					&attrs);
 			dev_err(fbdev->dev, "vrfb create ctx failed\n");
 			dev_err(fbdev->dev, "vrfb create ctx failed\n");
 			return r;
 			return r;
 		}
 		}
-
-		vaddr = NULL;
 	}
 	}
 
 
-	rg->paddr = paddr;
-	rg->vaddr = vaddr;
+	rg->attrs = attrs;
+	rg->token = token;
+	rg->dma_handle = dma_handle;
+
+	rg->paddr = (unsigned long)dma_handle;
+	rg->vaddr = (void __iomem *)token;
 	rg->size = size;
 	rg->size = size;
 	rg->alloc = 1;
 	rg->alloc = 1;
 
 
@@ -1531,6 +1529,9 @@ static int omapfb_parse_vram_param(const char *param, int max_entries,
 
 
 		}
 		}
 
 
+		WARN_ONCE(paddr,
+			"reserving memory at predefined address not supported\n");
+
 		paddrs[fbnum] = paddr;
 		paddrs[fbnum] = paddr;
 		sizes[fbnum] = size;
 		sizes[fbnum] = size;
 
 
@@ -1610,7 +1611,6 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
 {
 {
 	struct omapfb_info *ofbi = FB2OFB(fbi);
 	struct omapfb_info *ofbi = FB2OFB(fbi);
 	struct omapfb2_device *fbdev = ofbi->fbdev;
 	struct omapfb2_device *fbdev = ofbi->fbdev;
-	struct omap_dss_device *display = fb2display(fbi);
 	struct omapfb2_mem_region *rg = ofbi->region;
 	struct omapfb2_mem_region *rg = ofbi->region;
 	unsigned long old_size = rg->size;
 	unsigned long old_size = rg->size;
 	unsigned long old_paddr = rg->paddr;
 	unsigned long old_paddr = rg->paddr;
@@ -1625,9 +1625,6 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
 	if (old_size == size && old_type == type)
 	if (old_size == size && old_type == type)
 		return 0;
 		return 0;
 
 
-	if (display && display->driver->sync)
-			display->driver->sync(display);
-
 	omapfb_free_fbmem(fbi);
 	omapfb_free_fbmem(fbi);
 
 
 	if (size == 0) {
 	if (size == 0) {
@@ -1882,7 +1879,6 @@ static void omapfb_free_resources(struct omapfb2_device *fbdev)
 	}
 	}
 
 
 	dev_set_drvdata(fbdev->dev, NULL);
 	dev_set_drvdata(fbdev->dev, NULL);
-	kfree(fbdev);
 }
 }
 
 
 static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
 static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
@@ -2258,26 +2254,28 @@ static int omapfb_find_best_mode(struct omap_dss_device *display,
 {
 {
 	struct fb_monspecs *specs;
 	struct fb_monspecs *specs;
 	u8 *edid;
 	u8 *edid;
-	int r, i, best_xres, best_idx, len;
+	int r, i, best_idx, len;
 
 
 	if (!display->driver->read_edid)
 	if (!display->driver->read_edid)
 		return -ENODEV;
 		return -ENODEV;
 
 
 	len = 0x80 * 2;
 	len = 0x80 * 2;
 	edid = kmalloc(len, GFP_KERNEL);
 	edid = kmalloc(len, GFP_KERNEL);
+	if (edid == NULL)
+		return -ENOMEM;
 
 
 	r = display->driver->read_edid(display, edid, len);
 	r = display->driver->read_edid(display, edid, len);
 	if (r < 0)
 	if (r < 0)
 		goto err1;
 		goto err1;
 
 
 	specs = kzalloc(sizeof(*specs), GFP_KERNEL);
 	specs = kzalloc(sizeof(*specs), GFP_KERNEL);
+	if (specs == NULL) {
+		r = -ENOMEM;
+		goto err1;
+	}
 
 
 	fb_edid_to_monspecs(edid, specs);
 	fb_edid_to_monspecs(edid, specs);
 
 
-	if (edid[126] > 0)
-		fb_edid_add_monspecs(edid + 0x80, specs);
-
-	best_xres = 0;
 	best_idx = -1;
 	best_idx = -1;
 
 
 	for (i = 0; i < specs->modedb_len; ++i) {
 	for (i = 0; i < specs->modedb_len; ++i) {
@@ -2293,16 +2291,20 @@ static int omapfb_find_best_mode(struct omap_dss_device *display,
 		if (m->xres == 2880 || m->xres == 1440)
 		if (m->xres == 2880 || m->xres == 1440)
 			continue;
 			continue;
 
 
+		if (m->vmode & FB_VMODE_INTERLACED ||
+				m->vmode & FB_VMODE_DOUBLE)
+			continue;
+
 		fb_videomode_to_omap_timings(m, display, &t);
 		fb_videomode_to_omap_timings(m, display, &t);
 
 
 		r = display->driver->check_timings(display, &t);
 		r = display->driver->check_timings(display, &t);
-		if (r == 0 && best_xres < m->xres) {
-			best_xres = m->xres;
+		if (r == 0) {
 			best_idx = i;
 			best_idx = i;
+			break;
 		}
 		}
 	}
 	}
 
 
-	if (best_xres == 0) {
+	if (best_idx == -1) {
 		r = -ENOENT;
 		r = -ENOENT;
 		goto err2;
 		goto err2;
 	}
 	}
@@ -2371,15 +2373,62 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
 	return 0;
 	return 0;
 }
 }
 
 
+static int omapfb_init_connections(struct omapfb2_device *fbdev,
+		struct omap_dss_device *def_dssdev)
+{
+	int i, r;
+	struct omap_overlay_manager *mgr;
+
+	if (!def_dssdev->output) {
+		dev_err(fbdev->dev, "no output for the default display\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < fbdev->num_displays; ++i) {
+		struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
+		struct omap_dss_output *out = dssdev->output;
+
+		mgr = omap_dss_get_overlay_manager(dssdev->channel);
+
+		if (!mgr || !out)
+			continue;
+
+		if (mgr->output)
+			mgr->unset_output(mgr);
+
+		mgr->set_output(mgr, out);
+	}
+
+	mgr = def_dssdev->output->manager;
+
+	if (!mgr) {
+		dev_err(fbdev->dev, "no ovl manager for the default display\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < fbdev->num_overlays; i++) {
+		struct omap_overlay *ovl = fbdev->overlays[i];
+
+		if (ovl->manager)
+			ovl->unset_manager(ovl);
+
+		r = ovl->set_manager(ovl, mgr);
+		if (r)
+			dev_warn(fbdev->dev,
+					"failed to connect overlay %s to manager %s\n",
+					ovl->name, mgr->name);
+	}
+
+	return 0;
+}
+
 static int __init omapfb_probe(struct platform_device *pdev)
 static int __init omapfb_probe(struct platform_device *pdev)
 {
 {
 	struct omapfb2_device *fbdev = NULL;
 	struct omapfb2_device *fbdev = NULL;
 	int r = 0;
 	int r = 0;
 	int i;
 	int i;
-	struct omap_overlay *ovl;
 	struct omap_dss_device *def_display;
 	struct omap_dss_device *def_display;
 	struct omap_dss_device *dssdev;
 	struct omap_dss_device *dssdev;
-	struct omap_dss_device *ovl_device;
 
 
 	DBG("omapfb_probe\n");
 	DBG("omapfb_probe\n");
 
 
@@ -2389,7 +2438,8 @@ static int __init omapfb_probe(struct platform_device *pdev)
 		goto err0;
 		goto err0;
 	}
 	}
 
 
-	fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL);
+	fbdev = devm_kzalloc(&pdev->dev, sizeof(struct omapfb2_device),
+			GFP_KERNEL);
 	if (fbdev == NULL) {
 	if (fbdev == NULL) {
 		r = -ENOMEM;
 		r = -ENOMEM;
 		goto err0;
 		goto err0;
@@ -2401,13 +2451,15 @@ static int __init omapfb_probe(struct platform_device *pdev)
 				"ignoring the module parameter vrfb=y\n");
 				"ignoring the module parameter vrfb=y\n");
 	}
 	}
 
 
+	r = omapdss_compat_init();
+	if (r)
+		goto err0;
 
 
 	mutex_init(&fbdev->mtx);
 	mutex_init(&fbdev->mtx);
 
 
 	fbdev->dev = &pdev->dev;
 	fbdev->dev = &pdev->dev;
 	platform_set_drvdata(pdev, fbdev);
 	platform_set_drvdata(pdev, fbdev);
 
 
-	r = 0;
 	fbdev->num_displays = 0;
 	fbdev->num_displays = 0;
 	dssdev = NULL;
 	dssdev = NULL;
 	for_each_dss_dev(dssdev) {
 	for_each_dss_dev(dssdev) {
@@ -2430,9 +2482,6 @@ static int __init omapfb_probe(struct platform_device *pdev)
 			d->update_mode = OMAPFB_AUTO_UPDATE;
 			d->update_mode = OMAPFB_AUTO_UPDATE;
 	}
 	}
 
 
-	if (r)
-		goto cleanup;
-
 	if (fbdev->num_displays == 0) {
 	if (fbdev->num_displays == 0) {
 		dev_err(&pdev->dev, "no displays\n");
 		dev_err(&pdev->dev, "no displays\n");
 		r = -EINVAL;
 		r = -EINVAL;
@@ -2447,15 +2496,33 @@ static int __init omapfb_probe(struct platform_device *pdev)
 	for (i = 0; i < fbdev->num_managers; i++)
 	for (i = 0; i < fbdev->num_managers; i++)
 		fbdev->managers[i] = omap_dss_get_overlay_manager(i);
 		fbdev->managers[i] = omap_dss_get_overlay_manager(i);
 
 
-	/* gfx overlay should be the default one. find a display
-	 * connected to that, and use it as default display */
-	ovl = omap_dss_get_overlay(0);
-	ovl_device = ovl->get_device(ovl);
-	if (ovl_device) {
-		def_display = ovl_device;
-	} else {
-		dev_warn(&pdev->dev, "cannot find default display\n");
-		def_display = NULL;
+	def_display = NULL;
+
+	for (i = 0; i < fbdev->num_displays; ++i) {
+		struct omap_dss_device *dssdev;
+		const char *def_name;
+
+		def_name = omapdss_get_default_display_name();
+
+		dssdev = fbdev->displays[i].dssdev;
+
+		if (def_name == NULL ||
+			(dssdev->name && strcmp(def_name, dssdev->name) == 0)) {
+			def_display = dssdev;
+			break;
+		}
+	}
+
+	if (def_display == NULL) {
+		dev_err(fbdev->dev, "failed to find default display\n");
+		r = -EINVAL;
+		goto cleanup;
+	}
+
+	r = omapfb_init_connections(fbdev, def_display);
+	if (r) {
+		dev_err(fbdev->dev, "failed to init overlay connections\n");
+		goto cleanup;
 	}
 	}
 
 
 	if (def_mode && strlen(def_mode) > 0) {
 	if (def_mode && strlen(def_mode) > 0) {
@@ -2506,6 +2573,7 @@ static int __init omapfb_probe(struct platform_device *pdev)
 
 
 cleanup:
 cleanup:
 	omapfb_free_resources(fbdev);
 	omapfb_free_resources(fbdev);
+	omapdss_compat_uninit();
 err0:
 err0:
 	dev_err(&pdev->dev, "failed to setup omapfb\n");
 	dev_err(&pdev->dev, "failed to setup omapfb\n");
 	return r;
 	return r;
@@ -2521,6 +2589,8 @@ static int __exit omapfb_remove(struct platform_device *pdev)
 
 
 	omapfb_free_resources(fbdev);
 	omapfb_free_resources(fbdev);
 
 
+	omapdss_compat_uninit();
+
 	return 0;
 	return 0;
 }
 }
 
 

+ 4 - 0
drivers/video/omap2/omapfb/omapfb-sysfs.c

@@ -441,6 +441,7 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
 	struct fb_info *fbi = dev_get_drvdata(dev);
 	struct fb_info *fbi = dev_get_drvdata(dev);
 	struct omapfb_info *ofbi = FB2OFB(fbi);
 	struct omapfb_info *ofbi = FB2OFB(fbi);
 	struct omapfb2_device *fbdev = ofbi->fbdev;
 	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omap_dss_device *display = fb2display(fbi);
 	struct omapfb2_mem_region *rg;
 	struct omapfb2_mem_region *rg;
 	unsigned long size;
 	unsigned long size;
 	int r;
 	int r;
@@ -455,6 +456,9 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
 	if (!lock_fb_info(fbi))
 	if (!lock_fb_info(fbi))
 		return -ENODEV;
 		return -ENODEV;
 
 
+	if (display && display->driver->sync)
+		display->driver->sync(display);
+
 	rg = ofbi->region;
 	rg = ofbi->region;
 
 
 	down_write_nested(&rg->lock, rg->id);
 	down_write_nested(&rg->lock, rg->id);

+ 11 - 9
drivers/video/omap2/omapfb/omapfb.h

@@ -28,6 +28,8 @@
 #endif
 #endif
 
 
 #include <linux/rwsem.h>
 #include <linux/rwsem.h>
+#include <linux/dma-attrs.h>
+#include <linux/dma-mapping.h>
 
 
 #include <video/omapdss.h>
 #include <video/omapdss.h>
 
 
@@ -49,6 +51,9 @@ extern bool omapfb_debug;
 
 
 struct omapfb2_mem_region {
 struct omapfb2_mem_region {
 	int             id;
 	int             id;
+	struct dma_attrs attrs;
+	void		*token;
+	dma_addr_t	dma_handle;
 	u32		paddr;
 	u32		paddr;
 	void __iomem	*vaddr;
 	void __iomem	*vaddr;
 	struct vrfb	vrfb;
 	struct vrfb	vrfb;
@@ -124,9 +129,6 @@ void omapfb_remove_sysfs(struct omapfb2_device *fbdev);
 
 
 int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
 int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
 
 
-int omapfb_update_window(struct fb_info *fbi,
-		u32 x, u32 y, u32 w, u32 h);
-
 int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
 int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
 			struct fb_var_screeninfo *var);
 			struct fb_var_screeninfo *var);
 
 
@@ -144,16 +146,16 @@ int omapfb_set_update_mode(struct fb_info *fbi, enum omapfb_update_mode mode);
 static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
 static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
 {
 {
 	struct omapfb_info *ofbi = FB2OFB(fbi);
 	struct omapfb_info *ofbi = FB2OFB(fbi);
-	int i;
+	struct omap_overlay *ovl;
 
 
 	/* XXX: returns the display connected to first attached overlay */
 	/* XXX: returns the display connected to first attached overlay */
-	for (i = 0; i < ofbi->num_overlays; i++) {
-		struct omap_overlay *ovl = ofbi->overlays[i];
 
 
-		return ovl->get_device(ovl);
-	}
+	if (ofbi->num_overlays == 0)
+		return NULL;
 
 
-	return NULL;
+	ovl = ofbi->overlays[0];
+
+	return ovl->get_device(ovl);
 }
 }
 
 
 static inline struct omapfb_display_data *get_display_data(
 static inline struct omapfb_display_data *get_display_data(

+ 0 - 514
drivers/video/omap2/vram.c

@@ -1,514 +0,0 @@
-/*
- * VRAM manager for OMAP
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-/*#define DEBUG*/
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/seq_file.h>
-#include <linux/memblock.h>
-#include <linux/completion.h>
-#include <linux/debugfs.h>
-#include <linux/jiffies.h>
-#include <linux/module.h>
-
-#include <asm/setup.h>
-
-#include <plat/vram.h>
-
-#ifdef DEBUG
-#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__)
-#else
-#define DBG(format, ...)
-#endif
-
-/* postponed regions are used to temporarily store region information at boot
- * time when we cannot yet allocate the region list */
-#define MAX_POSTPONED_REGIONS 10
-
-static bool vram_initialized;
-static int postponed_cnt;
-static struct {
-	unsigned long paddr;
-	size_t size;
-} postponed_regions[MAX_POSTPONED_REGIONS];
-
-struct vram_alloc {
-	struct list_head list;
-	unsigned long paddr;
-	unsigned pages;
-};
-
-struct vram_region {
-	struct list_head list;
-	struct list_head alloc_list;
-	unsigned long paddr;
-	unsigned pages;
-};
-
-static DEFINE_MUTEX(region_mutex);
-static LIST_HEAD(region_list);
-
-static struct vram_region *omap_vram_create_region(unsigned long paddr,
-		unsigned pages)
-{
-	struct vram_region *rm;
-
-	rm = kzalloc(sizeof(*rm), GFP_KERNEL);
-
-	if (rm) {
-		INIT_LIST_HEAD(&rm->alloc_list);
-		rm->paddr = paddr;
-		rm->pages = pages;
-	}
-
-	return rm;
-}
-
-#if 0
-static void omap_vram_free_region(struct vram_region *vr)
-{
-	list_del(&vr->list);
-	kfree(vr);
-}
-#endif
-
-static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr,
-		unsigned long paddr, unsigned pages)
-{
-	struct vram_alloc *va;
-	struct vram_alloc *new;
-
-	new = kzalloc(sizeof(*va), GFP_KERNEL);
-
-	if (!new)
-		return NULL;
-
-	new->paddr = paddr;
-	new->pages = pages;
-
-	list_for_each_entry(va, &vr->alloc_list, list) {
-		if (va->paddr > new->paddr)
-			break;
-	}
-
-	list_add_tail(&new->list, &va->list);
-
-	return new;
-}
-
-static void omap_vram_free_allocation(struct vram_alloc *va)
-{
-	list_del(&va->list);
-	kfree(va);
-}
-
-int omap_vram_add_region(unsigned long paddr, size_t size)
-{
-	struct vram_region *rm;
-	unsigned pages;
-
-	if (vram_initialized) {
-		DBG("adding region paddr %08lx size %d\n",
-				paddr, size);
-
-		size &= PAGE_MASK;
-		pages = size >> PAGE_SHIFT;
-
-		rm = omap_vram_create_region(paddr, pages);
-		if (rm == NULL)
-			return -ENOMEM;
-
-		list_add(&rm->list, &region_list);
-	} else {
-		if (postponed_cnt == MAX_POSTPONED_REGIONS)
-			return -ENOMEM;
-
-		postponed_regions[postponed_cnt].paddr = paddr;
-		postponed_regions[postponed_cnt].size = size;
-
-		++postponed_cnt;
-	}
-	return 0;
-}
-
-int omap_vram_free(unsigned long paddr, size_t size)
-{
-	struct vram_region *rm;
-	struct vram_alloc *alloc;
-	unsigned start, end;
-
-	DBG("free mem paddr %08lx size %d\n", paddr, size);
-
-	size = PAGE_ALIGN(size);
-
-	mutex_lock(&region_mutex);
-
-	list_for_each_entry(rm, &region_list, list) {
-		list_for_each_entry(alloc, &rm->alloc_list, list) {
-			start = alloc->paddr;
-			end = alloc->paddr + (alloc->pages >> PAGE_SHIFT);
-
-			if (start >= paddr && end < paddr + size)
-				goto found;
-		}
-	}
-
-	mutex_unlock(&region_mutex);
-	return -EINVAL;
-
-found:
-	omap_vram_free_allocation(alloc);
-
-	mutex_unlock(&region_mutex);
-	return 0;
-}
-EXPORT_SYMBOL(omap_vram_free);
-
-static int _omap_vram_reserve(unsigned long paddr, unsigned pages)
-{
-	struct vram_region *rm;
-	struct vram_alloc *alloc;
-	size_t size;
-
-	size = pages << PAGE_SHIFT;
-
-	list_for_each_entry(rm, &region_list, list) {
-		unsigned long start, end;
-
-		DBG("checking region %lx %d\n", rm->paddr, rm->pages);
-
-		start = rm->paddr;
-		end = start + (rm->pages << PAGE_SHIFT) - 1;
-		if (start > paddr || end < paddr + size - 1)
-			continue;
-
-		DBG("block ok, checking allocs\n");
-
-		list_for_each_entry(alloc, &rm->alloc_list, list) {
-			end = alloc->paddr - 1;
-
-			if (start <= paddr && end >= paddr + size - 1)
-				goto found;
-
-			start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
-		}
-
-		end = rm->paddr + (rm->pages << PAGE_SHIFT) - 1;
-
-		if (!(start <= paddr && end >= paddr + size - 1))
-			continue;
-found:
-		DBG("found area start %lx, end %lx\n", start, end);
-
-		if (omap_vram_create_allocation(rm, paddr, pages) == NULL)
-			return -ENOMEM;
-
-		return 0;
-	}
-
-	return -ENOMEM;
-}
-
-int omap_vram_reserve(unsigned long paddr, size_t size)
-{
-	unsigned pages;
-	int r;
-
-	DBG("reserve mem paddr %08lx size %d\n", paddr, size);
-
-	size = PAGE_ALIGN(size);
-	pages = size >> PAGE_SHIFT;
-
-	mutex_lock(&region_mutex);
-
-	r = _omap_vram_reserve(paddr, pages);
-
-	mutex_unlock(&region_mutex);
-
-	return r;
-}
-EXPORT_SYMBOL(omap_vram_reserve);
-
-static int _omap_vram_alloc(unsigned pages, unsigned long *paddr)
-{
-	struct vram_region *rm;
-	struct vram_alloc *alloc;
-
-	list_for_each_entry(rm, &region_list, list) {
-		unsigned long start, end;
-
-		DBG("checking region %lx %d\n", rm->paddr, rm->pages);
-
-		start = rm->paddr;
-
-		list_for_each_entry(alloc, &rm->alloc_list, list) {
-			end = alloc->paddr;
-
-			if (end - start >= pages << PAGE_SHIFT)
-				goto found;
-
-			start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
-		}
-
-		end = rm->paddr + (rm->pages << PAGE_SHIFT);
-found:
-		if (end - start < pages << PAGE_SHIFT)
-			continue;
-
-		DBG("found %lx, end %lx\n", start, end);
-
-		alloc = omap_vram_create_allocation(rm, start, pages);
-		if (alloc == NULL)
-			return -ENOMEM;
-
-		*paddr = start;
-
-		return 0;
-	}
-
-	return -ENOMEM;
-}
-
-int omap_vram_alloc(size_t size, unsigned long *paddr)
-{
-	unsigned pages;
-	int r;
-
-	BUG_ON(!size);
-
-	DBG("alloc mem size %d\n", size);
-
-	size = PAGE_ALIGN(size);
-	pages = size >> PAGE_SHIFT;
-
-	mutex_lock(&region_mutex);
-
-	r = _omap_vram_alloc(pages, paddr);
-
-	mutex_unlock(&region_mutex);
-
-	return r;
-}
-EXPORT_SYMBOL(omap_vram_alloc);
-
-void omap_vram_get_info(unsigned long *vram,
-		unsigned long *free_vram,
-		unsigned long *largest_free_block)
-{
-	struct vram_region *vr;
-	struct vram_alloc *va;
-
-	*vram = 0;
-	*free_vram = 0;
-	*largest_free_block = 0;
-
-	mutex_lock(&region_mutex);
-
-	list_for_each_entry(vr, &region_list, list) {
-		unsigned free;
-		unsigned long pa;
-
-		pa = vr->paddr;
-		*vram += vr->pages << PAGE_SHIFT;
-
-		list_for_each_entry(va, &vr->alloc_list, list) {
-			free = va->paddr - pa;
-			*free_vram += free;
-			if (free > *largest_free_block)
-				*largest_free_block = free;
-			pa = va->paddr + (va->pages << PAGE_SHIFT);
-		}
-
-		free = vr->paddr + (vr->pages << PAGE_SHIFT) - pa;
-		*free_vram += free;
-		if (free > *largest_free_block)
-			*largest_free_block = free;
-	}
-
-	mutex_unlock(&region_mutex);
-}
-EXPORT_SYMBOL(omap_vram_get_info);
-
-#if defined(CONFIG_DEBUG_FS)
-static int vram_debug_show(struct seq_file *s, void *unused)
-{
-	struct vram_region *vr;
-	struct vram_alloc *va;
-	unsigned size;
-
-	mutex_lock(&region_mutex);
-
-	list_for_each_entry(vr, &region_list, list) {
-		size = vr->pages << PAGE_SHIFT;
-		seq_printf(s, "%08lx-%08lx (%d bytes)\n",
-				vr->paddr, vr->paddr + size - 1,
-				size);
-
-		list_for_each_entry(va, &vr->alloc_list, list) {
-			size = va->pages << PAGE_SHIFT;
-			seq_printf(s, "    %08lx-%08lx (%d bytes)\n",
-					va->paddr, va->paddr + size - 1,
-					size);
-		}
-	}
-
-	mutex_unlock(&region_mutex);
-
-	return 0;
-}
-
-static int vram_debug_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, vram_debug_show, inode->i_private);
-}
-
-static const struct file_operations vram_debug_fops = {
-	.open           = vram_debug_open,
-	.read           = seq_read,
-	.llseek         = seq_lseek,
-	.release        = single_release,
-};
-
-static int __init omap_vram_create_debugfs(void)
-{
-	struct dentry *d;
-
-	d = debugfs_create_file("vram", S_IRUGO, NULL,
-			NULL, &vram_debug_fops);
-	if (IS_ERR(d))
-		return PTR_ERR(d);
-
-	return 0;
-}
-#endif
-
-static __init int omap_vram_init(void)
-{
-	int i;
-
-	vram_initialized = 1;
-
-	for (i = 0; i < postponed_cnt; i++)
-		omap_vram_add_region(postponed_regions[i].paddr,
-				postponed_regions[i].size);
-
-#ifdef CONFIG_DEBUG_FS
-	if (omap_vram_create_debugfs())
-		pr_err("VRAM: Failed to create debugfs file\n");
-#endif
-
-	return 0;
-}
-
-arch_initcall(omap_vram_init);
-
-/* boottime vram alloc stuff */
-
-/* set from board file */
-static u32 omap_vram_sdram_start __initdata;
-static u32 omap_vram_sdram_size __initdata;
-
-/* set from kernel cmdline */
-static u32 omap_vram_def_sdram_size __initdata;
-static u32 omap_vram_def_sdram_start __initdata;
-
-static int __init omap_vram_early_vram(char *p)
-{
-	omap_vram_def_sdram_size = memparse(p, &p);
-	if (*p == ',')
-		omap_vram_def_sdram_start = simple_strtoul(p + 1, &p, 16);
-	return 0;
-}
-early_param("vram", omap_vram_early_vram);
-
-/*
- * Called from map_io. We need to call to this early enough so that we
- * can reserve the fixed SDRAM regions before VM could get hold of them.
- */
-void __init omap_vram_reserve_sdram_memblock(void)
-{
-	u32 paddr;
-	u32 size = 0;
-
-	/* cmdline arg overrides the board file definition */
-	if (omap_vram_def_sdram_size) {
-		size = omap_vram_def_sdram_size;
-		paddr = omap_vram_def_sdram_start;
-	}
-
-	if (!size) {
-		size = omap_vram_sdram_size;
-		paddr = omap_vram_sdram_start;
-	}
-
-#ifdef CONFIG_OMAP2_VRAM_SIZE
-	if (!size) {
-		size = CONFIG_OMAP2_VRAM_SIZE * 1024 * 1024;
-		paddr = 0;
-	}
-#endif
-
-	if (!size)
-		return;
-
-	size = ALIGN(size, SZ_2M);
-
-	if (paddr) {
-		if (paddr & ~PAGE_MASK) {
-			pr_err("VRAM start address 0x%08x not page aligned\n",
-					paddr);
-			return;
-		}
-
-		if (!memblock_is_region_memory(paddr, size)) {
-			pr_err("Illegal SDRAM region 0x%08x..0x%08x for VRAM\n",
-					paddr, paddr + size - 1);
-			return;
-		}
-
-		if (memblock_is_region_reserved(paddr, size)) {
-			pr_err("FB: failed to reserve VRAM - busy\n");
-			return;
-		}
-
-		if (memblock_reserve(paddr, size) < 0) {
-			pr_err("FB: failed to reserve VRAM - no memory\n");
-			return;
-		}
-	} else {
-		paddr = memblock_alloc(size, SZ_2M);
-	}
-
-	memblock_free(paddr, size);
-	memblock_remove(paddr, size);
-
-	omap_vram_add_region(paddr, size);
-
-	pr_info("Reserving %u bytes SDRAM for VRAM\n", size);
-}
-
-void __init omap_vram_set_sdram_vram(u32 size, u32 start)
-{
-	omap_vram_sdram_start = start;
-	omap_vram_sdram_size = size;
-}

+ 11 - 13
drivers/video/s3c-fb.c

@@ -189,7 +189,7 @@ struct s3c_fb_vsync {
 
 
 /**
 /**
  * struct s3c_fb - overall hardware state of the hardware
  * struct s3c_fb - overall hardware state of the hardware
- * @slock: The spinlock protection for this data sturucture.
+ * @slock: The spinlock protection for this data structure.
  * @dev: The device that we bound to, for printing, etc.
  * @dev: The device that we bound to, for printing, etc.
  * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
  * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
  * @lcd_clk: The clk (sclk) feeding pixclk.
  * @lcd_clk: The clk (sclk) feeding pixclk.
@@ -268,10 +268,10 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
 	case 8:
 	case 8:
 		if (sfb->variant.palette[win->index] != 0) {
 		if (sfb->variant.palette[win->index] != 0) {
 			/* non palletised, A:1,R:2,G:3,B:2 mode */
 			/* non palletised, A:1,R:2,G:3,B:2 mode */
-			var->red.offset		= 4;
+			var->red.offset		= 5;
 			var->green.offset	= 2;
 			var->green.offset	= 2;
 			var->blue.offset	= 0;
 			var->blue.offset	= 0;
-			var->red.length		= 5;
+			var->red.length		= 2;
 			var->green.length	= 3;
 			var->green.length	= 3;
 			var->blue.length	= 2;
 			var->blue.length	= 2;
 			var->transp.offset	= 7;
 			var->transp.offset	= 7;
@@ -288,6 +288,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
 		/* 666 with one bit alpha/transparency */
 		/* 666 with one bit alpha/transparency */
 		var->transp.offset	= 18;
 		var->transp.offset	= 18;
 		var->transp.length	= 1;
 		var->transp.length	= 1;
+		/* drop through */
 	case 18:
 	case 18:
 		var->bits_per_pixel	= 32;
 		var->bits_per_pixel	= 32;
 
 
@@ -329,6 +330,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
 
 
 	default:
 	default:
 		dev_err(sfb->dev, "invalid bpp\n");
 		dev_err(sfb->dev, "invalid bpp\n");
+		return -EINVAL;
 	}
 	}
 
 
 	dev_dbg(sfb->dev, "%s: verified parameters\n", __func__);
 	dev_dbg(sfb->dev, "%s: verified parameters\n", __func__);
@@ -1544,8 +1546,7 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM_SLEEP
 #ifdef CONFIG_PM_SLEEP
 static int s3c_fb_suspend(struct device *dev)
 static int s3c_fb_suspend(struct device *dev)
 {
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct s3c_fb *sfb = platform_get_drvdata(pdev);
+	struct s3c_fb *sfb = dev_get_drvdata(dev);
 	struct s3c_fb_win *win;
 	struct s3c_fb_win *win;
 	int win_no;
 	int win_no;
 
 
@@ -1572,8 +1573,7 @@ static int s3c_fb_suspend(struct device *dev)
 
 
 static int s3c_fb_resume(struct device *dev)
 static int s3c_fb_resume(struct device *dev)
 {
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct s3c_fb *sfb = platform_get_drvdata(pdev);
+	struct s3c_fb *sfb = dev_get_drvdata(dev);
 	struct s3c_fb_platdata *pd = sfb->pdata;
 	struct s3c_fb_platdata *pd = sfb->pdata;
 	struct s3c_fb_win *win;
 	struct s3c_fb_win *win;
 	int win_no;
 	int win_no;
@@ -1623,7 +1623,7 @@ static int s3c_fb_resume(struct device *dev)
 		if (!win)
 		if (!win)
 			continue;
 			continue;
 
 
-		dev_dbg(&pdev->dev, "resuming window %d\n", win_no);
+		dev_dbg(dev, "resuming window %d\n", win_no);
 		s3c_fb_set_par(win->fbinfo);
 		s3c_fb_set_par(win->fbinfo);
 	}
 	}
 
 
@@ -1636,8 +1636,7 @@ static int s3c_fb_resume(struct device *dev)
 #ifdef CONFIG_PM_RUNTIME
 #ifdef CONFIG_PM_RUNTIME
 static int s3c_fb_runtime_suspend(struct device *dev)
 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 *sfb = dev_get_drvdata(dev);
 
 
 	if (!sfb->variant.has_clksel)
 	if (!sfb->variant.has_clksel)
 		clk_disable_unprepare(sfb->lcd_clk);
 		clk_disable_unprepare(sfb->lcd_clk);
@@ -1649,8 +1648,7 @@ static int s3c_fb_runtime_suspend(struct device *dev)
 
 
 static int s3c_fb_runtime_resume(struct device *dev)
 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 *sfb = dev_get_drvdata(dev);
 	struct s3c_fb_platdata *pd = sfb->pdata;
 	struct s3c_fb_platdata *pd = sfb->pdata;
 
 
 	clk_prepare_enable(sfb->bus_clk);
 	clk_prepare_enable(sfb->bus_clk);
@@ -1910,7 +1908,7 @@ static struct s3c_fb_driverdata s3c_fb_data_exynos4 = {
 static struct s3c_fb_driverdata s3c_fb_data_exynos5 = {
 static struct s3c_fb_driverdata s3c_fb_data_exynos5 = {
 	.variant = {
 	.variant = {
 		.nr_windows	= 5,
 		.nr_windows	= 5,
-		.vidtcon	= VIDTCON0,
+		.vidtcon	= FIMD_V8_VIDTCON0,
 		.wincon		= WINCON(0),
 		.wincon		= WINCON(0),
 		.winmap		= WINxMAP(0),
 		.winmap		= WINxMAP(0),
 		.keycon		= WKEYCON,
 		.keycon		= WKEYCON,

+ 26 - 43
drivers/video/sh_mipi_dsi.c

@@ -127,13 +127,12 @@ static void sh_mipi_shutdown(struct platform_device *pdev)
 	sh_mipi_dsi_enable(mipi, false);
 	sh_mipi_dsi_enable(mipi, false);
 }
 }
 
 
-static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
+static int sh_mipi_setup(struct sh_mipi *mipi, const struct fb_videomode *mode)
 {
 {
 	void __iomem *base = mipi->base;
 	void __iomem *base = mipi->base;
-	struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan;
+	struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
 	u32 pctype, datatype, pixfmt, linelength, vmctr2;
 	u32 pctype, datatype, pixfmt, linelength, vmctr2;
 	u32 tmp, top, bottom, delay, div;
 	u32 tmp, top, bottom, delay, div;
-	bool yuv;
 	int bpp;
 	int bpp;
 
 
 	/*
 	/*
@@ -146,95 +145,79 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
 		pctype = 0;
 		pctype = 0;
 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
 		pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
 		pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
-		linelength = ch->lcd_modes[0].xres * 3;
-		yuv = false;
+		linelength = mode->xres * 3;
 		break;
 		break;
 	case MIPI_RGB565:
 	case MIPI_RGB565:
 		pctype = 1;
 		pctype = 1;
 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
 		pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
 		pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
-		linelength = ch->lcd_modes[0].xres * 2;
-		yuv = false;
+		linelength = mode->xres * 2;
 		break;
 		break;
 	case MIPI_RGB666_LP:
 	case MIPI_RGB666_LP:
 		pctype = 2;
 		pctype = 2;
 		datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
 		datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
 		pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
 		pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
-		linelength = ch->lcd_modes[0].xres * 3;
-		yuv = false;
+		linelength = mode->xres * 3;
 		break;
 		break;
 	case MIPI_RGB666:
 	case MIPI_RGB666:
 		pctype = 3;
 		pctype = 3;
 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
 		pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
 		pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
-		linelength = (ch->lcd_modes[0].xres * 18 + 7) / 8;
-		yuv = false;
+		linelength = (mode->xres * 18 + 7) / 8;
 		break;
 		break;
 	case MIPI_BGR888:
 	case MIPI_BGR888:
 		pctype = 8;
 		pctype = 8;
 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
 		pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
 		pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
-		linelength = ch->lcd_modes[0].xres * 3;
-		yuv = false;
+		linelength = mode->xres * 3;
 		break;
 		break;
 	case MIPI_BGR565:
 	case MIPI_BGR565:
 		pctype = 9;
 		pctype = 9;
 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
 		pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
 		pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
-		linelength = ch->lcd_modes[0].xres * 2;
-		yuv = false;
+		linelength = mode->xres * 2;
 		break;
 		break;
 	case MIPI_BGR666_LP:
 	case MIPI_BGR666_LP:
 		pctype = 0xa;
 		pctype = 0xa;
 		datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
 		datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
 		pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
 		pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
-		linelength = ch->lcd_modes[0].xres * 3;
-		yuv = false;
+		linelength = mode->xres * 3;
 		break;
 		break;
 	case MIPI_BGR666:
 	case MIPI_BGR666:
 		pctype = 0xb;
 		pctype = 0xb;
 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
 		pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
 		pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
-		linelength = (ch->lcd_modes[0].xres * 18 + 7) / 8;
-		yuv = false;
+		linelength = (mode->xres * 18 + 7) / 8;
 		break;
 		break;
 	case MIPI_YUYV:
 	case MIPI_YUYV:
 		pctype = 4;
 		pctype = 4;
 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
 		pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
 		pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
-		linelength = ch->lcd_modes[0].xres * 2;
-		yuv = true;
+		linelength = mode->xres * 2;
 		break;
 		break;
 	case MIPI_UYVY:
 	case MIPI_UYVY:
 		pctype = 5;
 		pctype = 5;
 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
 		pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
 		pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
-		linelength = ch->lcd_modes[0].xres * 2;
-		yuv = true;
+		linelength = mode->xres * 2;
 		break;
 		break;
 	case MIPI_YUV420_L:
 	case MIPI_YUV420_L:
 		pctype = 6;
 		pctype = 6;
 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
 		pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
 		pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
-		linelength = (ch->lcd_modes[0].xres * 12 + 7) / 8;
-		yuv = true;
+		linelength = (mode->xres * 12 + 7) / 8;
 		break;
 		break;
 	case MIPI_YUV420:
 	case MIPI_YUV420:
 		pctype = 7;
 		pctype = 7;
 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
 		datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
 		pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
 		pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
 		/* Length of U/V line */
 		/* Length of U/V line */
-		linelength = (ch->lcd_modes[0].xres + 1) / 2;
-		yuv = true;
+		linelength = (mode->xres + 1) / 2;
 		break;
 		break;
 	default:
 	default:
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	if ((yuv && ch->interface_type != YUV422) ||
-	    (!yuv && ch->interface_type != RGB24))
-		return -EINVAL;
-
 	if (!pdata->lane)
 	if (!pdata->lane)
 		return -EINVAL;
 		return -EINVAL;
 
 
@@ -293,7 +276,7 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
 	 */
 	 */
 	iowrite32(0x00000006, mipi->linkbase + DTCTR);
 	iowrite32(0x00000006, mipi->linkbase + DTCTR);
 	/* VSYNC width = 2 (<< 17) */
 	/* VSYNC width = 2 (<< 17) */
-	iowrite32((ch->lcd_modes[0].vsync_len << pdata->vsynw_offset) |
+	iowrite32((mode->vsync_len << pdata->vsynw_offset) |
 		  (pdata->clksrc << 16) | (pctype << 12) | datatype,
 		  (pdata->clksrc << 16) | (pctype << 12) | datatype,
 		  mipi->linkbase + VMCTR1);
 		  mipi->linkbase + VMCTR1);
 
 
@@ -327,7 +310,7 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
 	top = linelength << 16; /* RGBLEN */
 	top = linelength << 16; /* RGBLEN */
 	bottom = 0x00000001;
 	bottom = 0x00000001;
 	if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */
 	if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */
-		bottom = (pdata->lane * ch->lcd_modes[0].hsync_len) - 10;
+		bottom = (pdata->lane * mode->hsync_len) - 10;
 	iowrite32(top | bottom , mipi->linkbase + VMLEN1);
 	iowrite32(top | bottom , mipi->linkbase + VMLEN1);
 
 
 	/*
 	/*
@@ -347,18 +330,18 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
 		div = 2;
 		div = 2;
 
 
 	if (pdata->flags & SH_MIPI_DSI_HFPBM) {	/* HBPLEN */
 	if (pdata->flags & SH_MIPI_DSI_HFPBM) {	/* HBPLEN */
-		top = ch->lcd_modes[0].hsync_len + ch->lcd_modes[0].left_margin;
+		top = mode->hsync_len + mode->left_margin;
 		top = ((pdata->lane * top / div) - 10) << 16;
 		top = ((pdata->lane * top / div) - 10) << 16;
 	}
 	}
 	if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */
 	if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */
-		bottom = ch->lcd_modes[0].right_margin;
+		bottom = mode->right_margin;
 		bottom = (pdata->lane * bottom / div) - 12;
 		bottom = (pdata->lane * bottom / div) - 12;
 	}
 	}
 
 
-	bpp = linelength / ch->lcd_modes[0].xres; /* byte / pixel */
+	bpp = linelength / mode->xres; /* byte / pixel */
 	if ((pdata->lane / div) > bpp) {
 	if ((pdata->lane / div) > bpp) {
-		tmp = ch->lcd_modes[0].xres / bpp; /* output cycle */
-		tmp = ch->lcd_modes[0].xres - tmp; /* (input - output) cycle */
+		tmp = mode->xres / bpp; /* output cycle */
+		tmp = mode->xres - tmp; /* (input - output) cycle */
 		delay = (pdata->lane * tmp);
 		delay = (pdata->lane * tmp);
 	}
 	}
 
 
@@ -369,7 +352,7 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
 	/* setup LCD panel */
 	/* setup LCD panel */
 
 
 	/* cf. drivers/video/omap/lcd_mipid.c */
 	/* cf. drivers/video/omap/lcd_mipid.c */
-	sh_mipi_dcs(ch->chan, MIPI_DCS_EXIT_SLEEP_MODE);
+	sh_mipi_dcs(pdata->channel, MIPI_DCS_EXIT_SLEEP_MODE);
 	msleep(120);
 	msleep(120);
 	/*
 	/*
 	 * [7] - Page Address Mode
 	 * [7] - Page Address Mode
@@ -381,11 +364,11 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
 	 * [1] - Flip Horizontal
 	 * [1] - Flip Horizontal
 	 * [0] - Flip Vertical
 	 * [0] - Flip Vertical
 	 */
 	 */
-	sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
+	sh_mipi_dcs_param(pdata->channel, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
 	/* cf. set_data_lines() */
 	/* cf. set_data_lines() */
-	sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_PIXEL_FORMAT,
+	sh_mipi_dcs_param(pdata->channel, MIPI_DCS_SET_PIXEL_FORMAT,
 			  pixfmt << 4);
 			  pixfmt << 4);
-	sh_mipi_dcs(ch->chan, MIPI_DCS_SET_DISPLAY_ON);
+	sh_mipi_dcs(pdata->channel, MIPI_DCS_SET_DISPLAY_ON);
 
 
 	/* Enable timeout counters */
 	/* Enable timeout counters */
 	iowrite32(0x00000f00, base + DSICTRL);
 	iowrite32(0x00000f00, base + DSICTRL);
@@ -405,7 +388,7 @@ static int mipi_display_on(struct sh_mobile_lcdc_entity *entity)
 	if (ret < 0)
 	if (ret < 0)
 		goto mipi_display_on_fail1;
 		goto mipi_display_on_fail1;
 
 
-	ret = sh_mipi_setup(mipi, pdata);
+	ret = sh_mipi_setup(mipi, &entity->def_mode);
 	if (ret < 0)
 	if (ret < 0)
 		goto mipi_display_on_fail2;
 		goto mipi_display_on_fail2;
 
 

+ 47 - 27
drivers/video/sh_mobile_lcdcfb.c

@@ -438,7 +438,7 @@ static unsigned long lcdc_sys_read_data(void *handle)
 	return lcdc_read(ch->lcdc, _LDDRDR) & LDDRDR_DRD_MASK;
 	return lcdc_read(ch->lcdc, _LDDRDR) & LDDRDR_DRD_MASK;
 }
 }
 
 
-struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
+static struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
 	lcdc_sys_write_index,
 	lcdc_sys_write_index,
 	lcdc_sys_write_data,
 	lcdc_sys_write_data,
 	lcdc_sys_read_data,
 	lcdc_sys_read_data,
@@ -586,8 +586,8 @@ static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch,
 				 * Just turn on, if we run a resume here, the
 				 * Just turn on, if we run a resume here, the
 				 * logo disappears.
 				 * logo disappears.
 				 */
 				 */
-				info->var.width = monspec->max_x * 10;
-				info->var.height = monspec->max_y * 10;
+				info->var.width = ch->display.width;
+				info->var.height = ch->display.height;
 				sh_mobile_lcdc_display_on(ch);
 				sh_mobile_lcdc_display_on(ch);
 			} else {
 			} else {
 				/* New monitor or have to wake up */
 				/* New monitor or have to wake up */
@@ -1614,6 +1614,15 @@ static int sh_mobile_lcdc_overlay_blank(int blank, struct fb_info *info)
 	return 1;
 	return 1;
 }
 }
 
 
+static int
+sh_mobile_lcdc_overlay_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct sh_mobile_lcdc_overlay *ovl = info->par;
+
+	return dma_mmap_coherent(ovl->channel->lcdc->dev, vma, ovl->fb_mem,
+				 ovl->dma_handle, ovl->fb_size);
+}
+
 static struct fb_ops sh_mobile_lcdc_overlay_ops = {
 static struct fb_ops sh_mobile_lcdc_overlay_ops = {
 	.owner          = THIS_MODULE,
 	.owner          = THIS_MODULE,
 	.fb_read        = fb_sys_read,
 	.fb_read        = fb_sys_read,
@@ -1626,6 +1635,7 @@ static struct fb_ops sh_mobile_lcdc_overlay_ops = {
 	.fb_ioctl       = sh_mobile_lcdc_overlay_ioctl,
 	.fb_ioctl       = sh_mobile_lcdc_overlay_ioctl,
 	.fb_check_var	= sh_mobile_lcdc_overlay_check_var,
 	.fb_check_var	= sh_mobile_lcdc_overlay_check_var,
 	.fb_set_par	= sh_mobile_lcdc_overlay_set_par,
 	.fb_set_par	= sh_mobile_lcdc_overlay_set_par,
+	.fb_mmap	= sh_mobile_lcdc_overlay_mmap,
 };
 };
 
 
 static void
 static void
@@ -2093,6 +2103,15 @@ static int sh_mobile_lcdc_blank(int blank, struct fb_info *info)
 	return 0;
 	return 0;
 }
 }
 
 
+static int
+sh_mobile_lcdc_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct sh_mobile_lcdc_chan *ch = info->par;
+
+	return dma_mmap_coherent(ch->lcdc->dev, vma, ch->fb_mem,
+				 ch->dma_handle, ch->fb_size);
+}
+
 static struct fb_ops sh_mobile_lcdc_ops = {
 static struct fb_ops sh_mobile_lcdc_ops = {
 	.owner          = THIS_MODULE,
 	.owner          = THIS_MODULE,
 	.fb_setcolreg	= sh_mobile_lcdc_setcolreg,
 	.fb_setcolreg	= sh_mobile_lcdc_setcolreg,
@@ -2108,6 +2127,7 @@ static struct fb_ops sh_mobile_lcdc_ops = {
 	.fb_release	= sh_mobile_lcdc_release,
 	.fb_release	= sh_mobile_lcdc_release,
 	.fb_check_var	= sh_mobile_lcdc_check_var,
 	.fb_check_var	= sh_mobile_lcdc_check_var,
 	.fb_set_par	= sh_mobile_lcdc_set_par,
 	.fb_set_par	= sh_mobile_lcdc_set_par,
+	.fb_mmap	= sh_mobile_lcdc_mmap,
 };
 };
 
 
 static void
 static void
@@ -2167,7 +2187,7 @@ sh_mobile_lcdc_channel_fb_cleanup(struct sh_mobile_lcdc_chan *ch)
 
 
 static int __devinit
 static int __devinit
 sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
 sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
-			       const struct fb_videomode *mode,
+			       const struct fb_videomode *modes,
 			       unsigned int num_modes)
 			       unsigned int num_modes)
 {
 {
 	struct sh_mobile_lcdc_priv *priv = ch->lcdc;
 	struct sh_mobile_lcdc_priv *priv = ch->lcdc;
@@ -2193,7 +2213,7 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
 	info->pseudo_palette = &ch->pseudo_palette;
 	info->pseudo_palette = &ch->pseudo_palette;
 	info->par = ch;
 	info->par = ch;
 
 
-	fb_videomode_to_modelist(mode, num_modes, &info->modelist);
+	fb_videomode_to_modelist(modes, num_modes, &info->modelist);
 
 
 	ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
 	ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
 	if (ret < 0) {
 	if (ret < 0) {
@@ -2227,9 +2247,9 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
 	 * default.
 	 * default.
 	 */
 	 */
 	var = &info->var;
 	var = &info->var;
-	fb_videomode_to_var(var, mode);
-	var->width = ch->cfg->panel_cfg.width;
-	var->height = ch->cfg->panel_cfg.height;
+	fb_videomode_to_var(var, modes);
+	var->width = ch->display.width;
+	var->height = ch->display.height;
 	var->xres_virtual = ch->xres_virtual;
 	var->xres_virtual = ch->xres_virtual;
 	var->yres_virtual = ch->yres_virtual;
 	var->yres_virtual = ch->yres_virtual;
 	var->activate = FB_ACTIVATE_NOW;
 	var->activate = FB_ACTIVATE_NOW;
@@ -2262,6 +2282,7 @@ static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev)
 	    bdev->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
 	    bdev->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
 		brightness = 0;
 		brightness = 0;
 
 
+	ch->bl_brightness = brightness;
 	return ch->cfg->bl_info.set_brightness(brightness);
 	return ch->cfg->bl_info.set_brightness(brightness);
 }
 }
 
 
@@ -2269,7 +2290,7 @@ static int sh_mobile_lcdc_get_brightness(struct backlight_device *bdev)
 {
 {
 	struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
 	struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
 
 
-	return ch->cfg->bl_info.get_brightness();
+	return ch->bl_brightness;
 }
 }
 
 
 static int sh_mobile_lcdc_check_fb(struct backlight_device *bdev,
 static int sh_mobile_lcdc_check_fb(struct backlight_device *bdev,
@@ -2516,10 +2537,10 @@ static int __devinit sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *
 }
 }
 
 
 static int __devinit
 static int __devinit
-sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv,
-			  struct sh_mobile_lcdc_overlay *ovl)
+sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_overlay *ovl)
 {
 {
 	const struct sh_mobile_lcdc_format_info *format;
 	const struct sh_mobile_lcdc_format_info *format;
+	struct device *dev = ovl->channel->lcdc->dev;
 	int ret;
 	int ret;
 
 
 	if (ovl->cfg->fourcc == 0)
 	if (ovl->cfg->fourcc == 0)
@@ -2528,7 +2549,7 @@ sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv,
 	/* Validate the format. */
 	/* Validate the format. */
 	format = sh_mobile_format_info(ovl->cfg->fourcc);
 	format = sh_mobile_format_info(ovl->cfg->fourcc);
 	if (format == NULL) {
 	if (format == NULL) {
-		dev_err(priv->dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc);
+		dev_err(dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc);
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
@@ -2556,10 +2577,10 @@ sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv,
 	/* Allocate frame buffer memory. */
 	/* Allocate frame buffer memory. */
 	ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres
 	ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres
 		       * format->bpp / 8 * 2;
 		       * format->bpp / 8 * 2;
-	ovl->fb_mem = dma_alloc_coherent(priv->dev, ovl->fb_size,
-					   &ovl->dma_handle, GFP_KERNEL);
+	ovl->fb_mem = dma_alloc_coherent(dev, ovl->fb_size, &ovl->dma_handle,
+					 GFP_KERNEL);
 	if (!ovl->fb_mem) {
 	if (!ovl->fb_mem) {
-		dev_err(priv->dev, "unable to allocate buffer\n");
+		dev_err(dev, "unable to allocate buffer\n");
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
@@ -2571,11 +2592,11 @@ sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv,
 }
 }
 
 
 static int __devinit
 static int __devinit
-sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
-			    struct sh_mobile_lcdc_chan *ch)
+sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch)
 {
 {
 	const struct sh_mobile_lcdc_format_info *format;
 	const struct sh_mobile_lcdc_format_info *format;
 	const struct sh_mobile_lcdc_chan_cfg *cfg = ch->cfg;
 	const struct sh_mobile_lcdc_chan_cfg *cfg = ch->cfg;
+	struct device *dev = ch->lcdc->dev;
 	const struct fb_videomode *max_mode;
 	const struct fb_videomode *max_mode;
 	const struct fb_videomode *mode;
 	const struct fb_videomode *mode;
 	unsigned int num_modes;
 	unsigned int num_modes;
@@ -2588,7 +2609,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
 	/* Validate the format. */
 	/* Validate the format. */
 	format = sh_mobile_format_info(cfg->fourcc);
 	format = sh_mobile_format_info(cfg->fourcc);
 	if (format == NULL) {
 	if (format == NULL) {
-		dev_err(priv->dev, "Invalid FOURCC %08x.\n", cfg->fourcc);
+		dev_err(dev, "Invalid FOURCC %08x.\n", cfg->fourcc);
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
@@ -2604,7 +2625,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
 		/* NV12/NV21 buffers must have even number of lines */
 		/* NV12/NV21 buffers must have even number of lines */
 		if ((cfg->fourcc == V4L2_PIX_FMT_NV12 ||
 		if ((cfg->fourcc == V4L2_PIX_FMT_NV12 ||
 		     cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) {
 		     cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) {
-			dev_err(priv->dev, "yres must be multiple of 2 for "
+			dev_err(dev, "yres must be multiple of 2 for "
 				"YCbCr420 mode.\n");
 				"YCbCr420 mode.\n");
 			return -EINVAL;
 			return -EINVAL;
 		}
 		}
@@ -2618,7 +2639,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
 	if (!max_size)
 	if (!max_size)
 		max_size = MAX_XRES * MAX_YRES;
 		max_size = MAX_XRES * MAX_YRES;
 	else
 	else
-		dev_dbg(priv->dev, "Found largest videomode %ux%u\n",
+		dev_dbg(dev, "Found largest videomode %ux%u\n",
 			max_mode->xres, max_mode->yres);
 			max_mode->xres, max_mode->yres);
 
 
 	if (cfg->lcd_modes == NULL) {
 	if (cfg->lcd_modes == NULL) {
@@ -2652,10 +2673,10 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
 
 
 	/* Allocate frame buffer memory. */
 	/* Allocate frame buffer memory. */
 	ch->fb_size = max_size * format->bpp / 8 * 2;
 	ch->fb_size = max_size * format->bpp / 8 * 2;
-	ch->fb_mem = dma_alloc_coherent(priv->dev, ch->fb_size, &ch->dma_handle,
+	ch->fb_mem = dma_alloc_coherent(dev, ch->fb_size, &ch->dma_handle,
 					GFP_KERNEL);
 					GFP_KERNEL);
 	if (ch->fb_mem == NULL) {
 	if (ch->fb_mem == NULL) {
-		dev_err(priv->dev, "unable to allocate buffer\n");
+		dev_err(dev, "unable to allocate buffer\n");
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
@@ -2663,8 +2684,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
 	if (cfg->tx_dev) {
 	if (cfg->tx_dev) {
 		if (!cfg->tx_dev->dev.driver ||
 		if (!cfg->tx_dev->dev.driver ||
 		    !try_module_get(cfg->tx_dev->dev.driver->owner)) {
 		    !try_module_get(cfg->tx_dev->dev.driver->owner)) {
-			dev_warn(priv->dev,
-				 "unable to get transmitter device\n");
+			dev_warn(dev, "unable to get transmitter device\n");
 			return -EINVAL;
 			return -EINVAL;
 		}
 		}
 		ch->tx_dev = platform_get_drvdata(cfg->tx_dev);
 		ch->tx_dev = platform_get_drvdata(cfg->tx_dev);
@@ -2772,9 +2792,9 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 
 
 	for (i = 0; i < num_channels; i++) {
 	for (i = 0; i < num_channels; i++) {
-		struct sh_mobile_lcdc_chan *ch = priv->ch + i;
+		struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
 
 
-		error = sh_mobile_lcdc_channel_init(priv, ch);
+		error = sh_mobile_lcdc_channel_init(ch);
 		if (error)
 		if (error)
 			goto err1;
 			goto err1;
 	}
 	}
@@ -2785,7 +2805,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
 		ovl->cfg = &pdata->overlays[i];
 		ovl->cfg = &pdata->overlays[i];
 		ovl->channel = &priv->ch[0];
 		ovl->channel = &priv->ch[0];
 
 
-		error = sh_mobile_lcdc_overlay_init(priv, ovl);
+		error = sh_mobile_lcdc_overlay_init(ovl);
 		if (error)
 		if (error)
 			goto err1;
 			goto err1;
 	}
 	}

+ 1 - 0
drivers/video/sh_mobile_lcdcfb.h

@@ -94,6 +94,7 @@ struct sh_mobile_lcdc_chan {
 
 
 	/* Backlight */
 	/* Backlight */
 	struct backlight_device *bl;
 	struct backlight_device *bl;
+	unsigned int bl_brightness;
 
 
 	/* FB */
 	/* FB */
 	struct fb_info *info;
 	struct fb_info *info;

+ 396 - 0
drivers/video/ssd1307fb.c

@@ -0,0 +1,396 @@
+/*
+ * Driver for the Solomon SSD1307 OLED controler
+ *
+ * Copyright 2012 Free Electrons
+ *
+ * Licensed under the GPLv2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/fb.h>
+#include <linux/uaccess.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/pwm.h>
+#include <linux/delay.h>
+
+#define SSD1307FB_WIDTH			96
+#define SSD1307FB_HEIGHT		16
+
+#define SSD1307FB_DATA			0x40
+#define SSD1307FB_COMMAND		0x80
+
+#define SSD1307FB_CONTRAST		0x81
+#define SSD1307FB_SEG_REMAP_ON		0xa1
+#define SSD1307FB_DISPLAY_OFF		0xae
+#define SSD1307FB_DISPLAY_ON		0xaf
+#define SSD1307FB_START_PAGE_ADDRESS	0xb0
+
+struct ssd1307fb_par {
+	struct i2c_client *client;
+	struct fb_info *info;
+	struct pwm_device *pwm;
+	u32 pwm_period;
+	int reset;
+};
+
+static struct fb_fix_screeninfo ssd1307fb_fix __devinitdata = {
+	.id		= "Solomon SSD1307",
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_MONO10,
+	.xpanstep	= 0,
+	.ypanstep	= 0,
+	.ywrapstep	= 0,
+	.line_length	= SSD1307FB_WIDTH / 8,
+	.accel		= FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo ssd1307fb_var __devinitdata = {
+	.xres		= SSD1307FB_WIDTH,
+	.yres		= SSD1307FB_HEIGHT,
+	.xres_virtual	= SSD1307FB_WIDTH,
+	.yres_virtual	= SSD1307FB_HEIGHT,
+	.bits_per_pixel	= 1,
+};
+
+static int ssd1307fb_write_array(struct i2c_client *client, u8 type, u8 *cmd, u32 len)
+{
+	u8 *buf;
+	int ret = 0;
+
+	buf = kzalloc(len + 1, GFP_KERNEL);
+	if (!buf) {
+		dev_err(&client->dev, "Couldn't allocate sending buffer.\n");
+		return -ENOMEM;
+	}
+
+	buf[0] = type;
+	memcpy(buf + 1, cmd, len);
+
+	ret = i2c_master_send(client, buf, len + 1);
+	if (ret != len + 1) {
+		dev_err(&client->dev, "Couldn't send I2C command.\n");
+		goto error;
+	}
+
+error:
+	kfree(buf);
+	return ret;
+}
+
+static inline int ssd1307fb_write_cmd_array(struct i2c_client *client, u8 *cmd, u32 len)
+{
+	return ssd1307fb_write_array(client, SSD1307FB_COMMAND, cmd, len);
+}
+
+static inline int ssd1307fb_write_cmd(struct i2c_client *client, u8 cmd)
+{
+	return ssd1307fb_write_cmd_array(client, &cmd, 1);
+}
+
+static inline int ssd1307fb_write_data_array(struct i2c_client *client, u8 *cmd, u32 len)
+{
+	return ssd1307fb_write_array(client, SSD1307FB_DATA, cmd, len);
+}
+
+static inline int ssd1307fb_write_data(struct i2c_client *client, u8 data)
+{
+	return ssd1307fb_write_data_array(client, &data, 1);
+}
+
+static void ssd1307fb_update_display(struct ssd1307fb_par *par)
+{
+	u8 *vmem = par->info->screen_base;
+	int i, j, k;
+
+	/*
+	 * The screen is divided in pages, each having a height of 8
+	 * pixels, and the width of the screen. When sending a byte of
+	 * data to the controller, it gives the 8 bits for the current
+	 * column. I.e, the first byte are the 8 bits of the first
+	 * column, then the 8 bits for the second column, etc.
+	 *
+	 *
+	 * Representation of the screen, assuming it is 5 bits
+	 * wide. Each letter-number combination is a bit that controls
+	 * one pixel.
+	 *
+	 * A0 A1 A2 A3 A4
+	 * B0 B1 B2 B3 B4
+	 * C0 C1 C2 C3 C4
+	 * D0 D1 D2 D3 D4
+	 * E0 E1 E2 E3 E4
+	 * F0 F1 F2 F3 F4
+	 * G0 G1 G2 G3 G4
+	 * H0 H1 H2 H3 H4
+	 *
+	 * If you want to update this screen, you need to send 5 bytes:
+	 *  (1) A0 B0 C0 D0 E0 F0 G0 H0
+	 *  (2) A1 B1 C1 D1 E1 F1 G1 H1
+	 *  (3) A2 B2 C2 D2 E2 F2 G2 H2
+	 *  (4) A3 B3 C3 D3 E3 F3 G3 H3
+	 *  (5) A4 B4 C4 D4 E4 F4 G4 H4
+	 */
+
+	for (i = 0; i < (SSD1307FB_HEIGHT / 8); i++) {
+		ssd1307fb_write_cmd(par->client, SSD1307FB_START_PAGE_ADDRESS + (i + 1));
+		ssd1307fb_write_cmd(par->client, 0x00);
+		ssd1307fb_write_cmd(par->client, 0x10);
+
+		for (j = 0; j < SSD1307FB_WIDTH; j++) {
+			u8 buf = 0;
+			for (k = 0; k < 8; k++) {
+				u32 page_length = SSD1307FB_WIDTH * i;
+				u32 index = page_length + (SSD1307FB_WIDTH * k + j) / 8;
+				u8 byte = *(vmem + index);
+				u8 bit = byte & (1 << (7 - (j % 8)));
+				bit = bit >> (7 - (j % 8));
+				buf |= bit << k;
+			}
+			ssd1307fb_write_data(par->client, buf);
+		}
+	}
+}
+
+
+static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
+		size_t count, loff_t *ppos)
+{
+	struct ssd1307fb_par *par = info->par;
+	unsigned long total_size;
+	unsigned long p = *ppos;
+	u8 __iomem *dst;
+
+	total_size = info->fix.smem_len;
+
+	if (p > total_size)
+		return -EINVAL;
+
+	if (count + p > total_size)
+		count = total_size - p;
+
+	if (!count)
+		return -EINVAL;
+
+	dst = (void __force *) (info->screen_base + p);
+
+	if (copy_from_user(dst, buf, count))
+		return -EFAULT;
+
+	ssd1307fb_update_display(par);
+
+	*ppos += count;
+
+	return count;
+}
+
+static void ssd1307fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct ssd1307fb_par *par = info->par;
+	sys_fillrect(info, rect);
+	ssd1307fb_update_display(par);
+}
+
+static void ssd1307fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	struct ssd1307fb_par *par = info->par;
+	sys_copyarea(info, area);
+	ssd1307fb_update_display(par);
+}
+
+static void ssd1307fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct ssd1307fb_par *par = info->par;
+	sys_imageblit(info, image);
+	ssd1307fb_update_display(par);
+}
+
+static struct fb_ops ssd1307fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_read	= fb_sys_read,
+	.fb_write	= ssd1307fb_write,
+	.fb_fillrect	= ssd1307fb_fillrect,
+	.fb_copyarea	= ssd1307fb_copyarea,
+	.fb_imageblit	= ssd1307fb_imageblit,
+};
+
+static void ssd1307fb_deferred_io(struct fb_info *info,
+				struct list_head *pagelist)
+{
+	ssd1307fb_update_display(info->par);
+}
+
+static struct fb_deferred_io ssd1307fb_defio = {
+	.delay		= HZ,
+	.deferred_io	= ssd1307fb_deferred_io,
+};
+
+static int __devinit ssd1307fb_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	struct fb_info *info;
+	u32 vmem_size = SSD1307FB_WIDTH * SSD1307FB_HEIGHT / 8;
+	struct ssd1307fb_par *par;
+	u8 *vmem;
+	int ret;
+
+	if (!client->dev.of_node) {
+		dev_err(&client->dev, "No device tree data found!\n");
+		return -EINVAL;
+	}
+
+	info = framebuffer_alloc(sizeof(struct ssd1307fb_par), &client->dev);
+	if (!info) {
+		dev_err(&client->dev, "Couldn't allocate framebuffer.\n");
+		return -ENOMEM;
+	}
+
+	vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
+	if (!vmem) {
+		dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
+		ret = -ENOMEM;
+		goto fb_alloc_error;
+	}
+
+	info->fbops = &ssd1307fb_ops;
+	info->fix = ssd1307fb_fix;
+	info->fbdefio = &ssd1307fb_defio;
+
+	info->var = ssd1307fb_var;
+	info->var.red.length = 1;
+	info->var.red.offset = 0;
+	info->var.green.length = 1;
+	info->var.green.offset = 0;
+	info->var.blue.length = 1;
+	info->var.blue.offset = 0;
+
+	info->screen_base = (u8 __force __iomem *)vmem;
+	info->fix.smem_start = (unsigned long)vmem;
+	info->fix.smem_len = vmem_size;
+
+	fb_deferred_io_init(info);
+
+	par = info->par;
+	par->info = info;
+	par->client = client;
+
+	par->reset = of_get_named_gpio(client->dev.of_node,
+					 "reset-gpios", 0);
+	if (!gpio_is_valid(par->reset)) {
+		ret = -EINVAL;
+		goto reset_oled_error;
+	}
+
+	ret = devm_gpio_request_one(&client->dev, par->reset,
+				    GPIOF_OUT_INIT_HIGH,
+				    "oled-reset");
+	if (ret) {
+		dev_err(&client->dev,
+			"failed to request gpio %d: %d\n",
+			par->reset, ret);
+		goto reset_oled_error;
+	}
+
+	par->pwm = pwm_get(&client->dev, NULL);
+	if (IS_ERR(par->pwm)) {
+		dev_err(&client->dev, "Could not get PWM from device tree!\n");
+		ret = PTR_ERR(par->pwm);
+		goto pwm_error;
+	}
+
+	par->pwm_period = pwm_get_period(par->pwm);
+
+	dev_dbg(&client->dev, "Using PWM%d with a %dns period.\n", par->pwm->pwm, par->pwm_period);
+
+	ret = register_framebuffer(info);
+	if (ret) {
+		dev_err(&client->dev, "Couldn't register the framebuffer\n");
+		goto fbreg_error;
+	}
+
+	i2c_set_clientdata(client, info);
+
+	/* Reset the screen */
+	gpio_set_value(par->reset, 0);
+	udelay(4);
+	gpio_set_value(par->reset, 1);
+	udelay(4);
+
+	/* Enable the PWM */
+	pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
+	pwm_enable(par->pwm);
+
+	/* Map column 127 of the OLED to segment 0 */
+	ret = ssd1307fb_write_cmd(client, SSD1307FB_SEG_REMAP_ON);
+	if (ret < 0) {
+		dev_err(&client->dev, "Couldn't remap the screen.\n");
+		goto remap_error;
+	}
+
+	/* Turn on the display */
+	ret = ssd1307fb_write_cmd(client, SSD1307FB_DISPLAY_ON);
+	if (ret < 0) {
+		dev_err(&client->dev, "Couldn't turn the display on.\n");
+		goto remap_error;
+	}
+
+	dev_info(&client->dev, "fb%d: %s framebuffer device registered, using %d bytes of video memory\n", info->node, info->fix.id, vmem_size);
+
+	return 0;
+
+remap_error:
+	unregister_framebuffer(info);
+	pwm_disable(par->pwm);
+fbreg_error:
+	pwm_put(par->pwm);
+pwm_error:
+reset_oled_error:
+	fb_deferred_io_cleanup(info);
+fb_alloc_error:
+	framebuffer_release(info);
+	return ret;
+}
+
+static int __devexit ssd1307fb_remove(struct i2c_client *client)
+{
+	struct fb_info *info = i2c_get_clientdata(client);
+	struct ssd1307fb_par *par = info->par;
+
+	unregister_framebuffer(info);
+	pwm_disable(par->pwm);
+	pwm_put(par->pwm);
+	fb_deferred_io_cleanup(info);
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static const struct i2c_device_id ssd1307fb_i2c_id[] = {
+	{ "ssd1307fb", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ssd1307fb_i2c_id);
+
+static const struct of_device_id ssd1307fb_of_match[] = {
+	{ .compatible = "solomon,ssd1307fb-i2c" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ssd1307fb_of_match);
+
+static struct i2c_driver ssd1307fb_driver = {
+	.probe = ssd1307fb_probe,
+	.remove = __devexit_p(ssd1307fb_remove),
+	.id_table = ssd1307fb_i2c_id,
+	.driver = {
+		.name = "ssd1307fb",
+		.of_match_table = of_match_ptr(ssd1307fb_of_match),
+		.owner = THIS_MODULE,
+	},
+};
+
+module_i2c_driver(ssd1307fb_driver);
+
+MODULE_DESCRIPTION("FB driver for the Solomon SSD1307 OLED controler");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_LICENSE("GPL");

+ 9 - 0
include/linux/fsl-diu-fb.h

@@ -46,6 +46,15 @@ struct aoi_display_offset {
 #define MFB_SET_PIXFMT		_IOW('M', 8, __u32)
 #define MFB_SET_PIXFMT		_IOW('M', 8, __u32)
 #define MFB_GET_PIXFMT		_IOR('M', 8, __u32)
 #define MFB_GET_PIXFMT		_IOR('M', 8, __u32)
 
 
+/*
+ * The MPC5121 BSP comes with a gamma_set utility that initializes the
+ * gamma table.  Unfortunately, it uses bad values for the IOCTL commands,
+ * but there's nothing we can do about it now.  These ioctls are only
+ * supported on the MPC5121.
+ */
+#define MFB_SET_GAMMA		_IOW('M', 1, __u8)
+#define MFB_GET_GAMMA		_IOR('M', 1, __u8)
+
 /*
 /*
  * The original definitions of MFB_SET_PIXFMT and MFB_GET_PIXFMT used the
  * The original definitions of MFB_SET_PIXFMT and MFB_GET_PIXFMT used the
  * wrong value for 'size' field of the ioctl.  The current macros above use the
  * wrong value for 'size' field of the ioctl.  The current macros above use the

+ 4 - 21
include/video/da8xx-fb.h

@@ -12,10 +12,6 @@
 #ifndef DA8XX_FB_H
 #ifndef DA8XX_FB_H
 #define DA8XX_FB_H
 #define DA8XX_FB_H
 
 
-enum panel_type {
-	QVGA = 0
-};
-
 enum panel_shade {
 enum panel_shade {
 	MONOCHROME = 0,
 	MONOCHROME = 0,
 	COLOR_ACTIVE,
 	COLOR_ACTIVE,
@@ -27,13 +23,6 @@ enum raster_load_mode {
 	LOAD_PALETTE,
 	LOAD_PALETTE,
 };
 };
 
 
-struct display_panel {
-	enum panel_type panel_type; /* QVGA */
-	int max_bpp;
-	int min_bpp;
-	enum panel_shade panel_shade;
-};
-
 struct da8xx_lcdc_platform_data {
 struct da8xx_lcdc_platform_data {
 	const char manu_name[10];
 	const char manu_name[10];
 	void *controller_data;
 	void *controller_data;
@@ -42,7 +31,7 @@ struct da8xx_lcdc_platform_data {
 };
 };
 
 
 struct lcd_ctrl_config {
 struct lcd_ctrl_config {
-	const struct display_panel *p_disp_panel;
+	enum panel_shade panel_shade;
 
 
 	/* AC Bias Pin Frequency */
 	/* AC Bias Pin Frequency */
 	int ac_bias;
 	int ac_bias;
@@ -68,18 +57,9 @@ struct lcd_ctrl_config {
 	/* Mono 8-bit Mode: 1=D0-D7 or 0=D0-D3 */
 	/* Mono 8-bit Mode: 1=D0-D7 or 0=D0-D3 */
 	unsigned char mono_8bit_mode;
 	unsigned char mono_8bit_mode;
 
 
-	/* Invert line clock */
-	unsigned char invert_line_clock;
-
-	/* Invert frame clock  */
-	unsigned char invert_frm_clock;
-
 	/* Horizontal and Vertical Sync Edge: 0=rising 1=falling */
 	/* Horizontal and Vertical Sync Edge: 0=rising 1=falling */
 	unsigned char sync_edge;
 	unsigned char sync_edge;
 
 
-	/* Horizontal and Vertical Sync: Control: 0=ignore */
-	unsigned char sync_ctrl;
-
 	/* Raster Data Order Select: 1=Most-to-least 0=Least-to-most */
 	/* Raster Data Order Select: 1=Most-to-least 0=Least-to-most */
 	unsigned char raster_order;
 	unsigned char raster_order;
 
 
@@ -103,5 +83,8 @@ struct lcd_sync_arg {
 #define FBIPUT_HSYNC		_IOW('F', 9, int)
 #define FBIPUT_HSYNC		_IOW('F', 9, int)
 #define FBIPUT_VSYNC		_IOW('F', 10, int)
 #define FBIPUT_VSYNC		_IOW('F', 10, int)
 
 
+/* Proprietary FB_SYNC_ flags */
+#define FB_SYNC_CLK_INVERT 0x40000000
+
 #endif  /* ifndef DA8XX_FB_H */
 #endif  /* ifndef DA8XX_FB_H */
 
 

+ 81 - 10
include/video/omapdss.h

@@ -21,6 +21,7 @@
 #include <linux/list.h>
 #include <linux/list.h>
 #include <linux/kobject.h>
 #include <linux/kobject.h>
 #include <linux/device.h>
 #include <linux/device.h>
+#include <linux/interrupt.h>
 
 
 #define DISPC_IRQ_FRAMEDONE		(1 << 0)
 #define DISPC_IRQ_FRAMEDONE		(1 << 0)
 #define DISPC_IRQ_VSYNC			(1 << 1)
 #define DISPC_IRQ_VSYNC			(1 << 1)
@@ -55,6 +56,7 @@
 
 
 struct omap_dss_device;
 struct omap_dss_device;
 struct omap_overlay_manager;
 struct omap_overlay_manager;
+struct dss_lcd_mgr_config;
 struct snd_aes_iec958;
 struct snd_aes_iec958;
 struct snd_cea_861_aud_if;
 struct snd_cea_861_aud_if;
 
 
@@ -158,7 +160,6 @@ enum omap_display_caps {
 enum omap_dss_display_state {
 enum omap_dss_display_state {
 	OMAP_DSS_DISPLAY_DISABLED = 0,
 	OMAP_DSS_DISPLAY_DISABLED = 0,
 	OMAP_DSS_DISPLAY_ACTIVE,
 	OMAP_DSS_DISPLAY_ACTIVE,
-	OMAP_DSS_DISPLAY_SUSPENDED,
 };
 };
 
 
 enum omap_dss_audio_state {
 enum omap_dss_audio_state {
@@ -621,10 +622,6 @@ struct omap_dss_device {
 	struct {
 	struct {
 		struct omap_video_timings timings;
 		struct omap_video_timings timings;
 
 
-		int acbi;	/* ac-bias pin transitions per interrupt */
-		/* Unit: line clocks */
-		int acb;	/* ac-bias pin frequency */
-
 		enum omap_dss_dsi_pixel_format dsi_pix_fmt;
 		enum omap_dss_dsi_pixel_format dsi_pix_fmt;
 		enum omap_dss_dsi_mode dsi_mode;
 		enum omap_dss_dsi_mode dsi_mode;
 		struct omap_dss_dsi_videomode_timings dsi_vm_timings;
 		struct omap_dss_dsi_videomode_timings dsi_vm_timings;
@@ -686,8 +683,6 @@ struct omap_dss_driver {
 
 
 	int (*enable)(struct omap_dss_device *display);
 	int (*enable)(struct omap_dss_device *display);
 	void (*disable)(struct omap_dss_device *display);
 	void (*disable)(struct omap_dss_device *display);
-	int (*suspend)(struct omap_dss_device *display);
-	int (*resume)(struct omap_dss_device *display);
 	int (*run_test)(struct omap_dss_device *display, int test);
 	int (*run_test)(struct omap_dss_device *display, int test);
 
 
 	int (*update)(struct omap_dss_device *dssdev,
 	int (*update)(struct omap_dss_device *dssdev,
@@ -745,6 +740,8 @@ struct omap_dss_driver {
 
 
 };
 };
 
 
+enum omapdss_version omapdss_get_version(void);
+
 int omap_dss_register_driver(struct omap_dss_driver *);
 int omap_dss_register_driver(struct omap_dss_driver *);
 void omap_dss_unregister_driver(struct omap_dss_driver *);
 void omap_dss_unregister_driver(struct omap_dss_driver *);
 
 
@@ -754,10 +751,19 @@ void omap_dss_put_device(struct omap_dss_device *dssdev);
 struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from);
 struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from);
 struct omap_dss_device *omap_dss_find_device(void *data,
 struct omap_dss_device *omap_dss_find_device(void *data,
 		int (*match)(struct omap_dss_device *dssdev, void *data));
 		int (*match)(struct omap_dss_device *dssdev, void *data));
+const char *omapdss_get_default_display_name(void);
 
 
 int omap_dss_start_device(struct omap_dss_device *dssdev);
 int omap_dss_start_device(struct omap_dss_device *dssdev);
 void omap_dss_stop_device(struct omap_dss_device *dssdev);
 void omap_dss_stop_device(struct omap_dss_device *dssdev);
 
 
+int dss_feat_get_num_mgrs(void);
+int dss_feat_get_num_ovls(void);
+enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
+enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel);
+enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
+
+
+
 int omap_dss_get_num_overlay_managers(void);
 int omap_dss_get_num_overlay_managers(void);
 struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
 struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
 
 
@@ -779,9 +785,43 @@ typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
 int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
 int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
 int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
 int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
 
 
-int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout);
-int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
-		unsigned long timeout);
+u32 dispc_read_irqstatus(void);
+void dispc_clear_irqstatus(u32 mask);
+u32 dispc_read_irqenable(void);
+void dispc_write_irqenable(u32 mask);
+
+int dispc_request_irq(irq_handler_t handler, void *dev_id);
+void dispc_free_irq(void *dev_id);
+
+int dispc_runtime_get(void);
+void dispc_runtime_put(void);
+
+void dispc_mgr_enable(enum omap_channel channel, bool enable);
+bool dispc_mgr_is_enabled(enum omap_channel channel);
+u32 dispc_mgr_get_vsync_irq(enum omap_channel channel);
+u32 dispc_mgr_get_framedone_irq(enum omap_channel channel);
+u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel);
+bool dispc_mgr_go_busy(enum omap_channel channel);
+void dispc_mgr_go(enum omap_channel channel);
+void dispc_mgr_set_lcd_config(enum omap_channel channel,
+		const struct dss_lcd_mgr_config *config);
+void dispc_mgr_set_timings(enum omap_channel channel,
+		const struct omap_video_timings *timings);
+void dispc_mgr_setup(enum omap_channel channel,
+		const struct omap_overlay_manager_info *info);
+
+int dispc_ovl_check(enum omap_plane plane, enum omap_channel channel,
+		const struct omap_overlay_info *oi,
+		const struct omap_video_timings *timings,
+		int *x_predecim, int *y_predecim);
+
+int dispc_ovl_enable(enum omap_plane plane, bool enable);
+bool dispc_ovl_enabled(enum omap_plane plane);
+void dispc_ovl_set_channel_out(enum omap_plane plane,
+		enum omap_channel channel);
+int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
+		bool replication, const struct omap_video_timings *mgr_timings,
+		bool mem_to_mem);
 
 
 #define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
 #define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
 #define to_dss_device(x) container_of((x), struct omap_dss_device, dev)
 #define to_dss_device(x) container_of((x), struct omap_dss_device, dev)
@@ -840,4 +880,35 @@ void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev,
 void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
 void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
 		struct rfbi_timings *timings);
 		struct rfbi_timings *timings);
 
 
+int omapdss_compat_init(void);
+void omapdss_compat_uninit(void);
+
+struct dss_mgr_ops {
+	void (*start_update)(struct omap_overlay_manager *mgr);
+	int (*enable)(struct omap_overlay_manager *mgr);
+	void (*disable)(struct omap_overlay_manager *mgr);
+	void (*set_timings)(struct omap_overlay_manager *mgr,
+			const struct omap_video_timings *timings);
+	void (*set_lcd_config)(struct omap_overlay_manager *mgr,
+			const struct dss_lcd_mgr_config *config);
+	int (*register_framedone_handler)(struct omap_overlay_manager *mgr,
+			void (*handler)(void *), void *data);
+	void (*unregister_framedone_handler)(struct omap_overlay_manager *mgr,
+			void (*handler)(void *), void *data);
+};
+
+int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops);
+void dss_uninstall_mgr_ops(void);
+
+void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
+		const struct omap_video_timings *timings);
+void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
+		const struct dss_lcd_mgr_config *config);
+int dss_mgr_enable(struct omap_overlay_manager *mgr);
+void dss_mgr_disable(struct omap_overlay_manager *mgr);
+void dss_mgr_start_update(struct omap_overlay_manager *mgr);
+int dss_mgr_register_framedone_handler(struct omap_overlay_manager *mgr,
+		void (*handler)(void *), void *data);
+void dss_mgr_unregister_framedone_handler(struct omap_overlay_manager *mgr,
+		void (*handler)(void *), void *data);
 #endif
 #endif

+ 52 - 116
include/video/samsung_fimd.h

@@ -24,12 +24,15 @@
 
 
 #define VIDCON0					(0x00)
 #define VIDCON0					(0x00)
 #define VIDCON0_INTERLACE			(1 << 29)
 #define VIDCON0_INTERLACE			(1 << 29)
-#define VIDCON0_VIDOUT_MASK			(0x3 << 26)
+#define VIDCON0_VIDOUT_MASK			(0x7 << 26)
 #define VIDCON0_VIDOUT_SHIFT			(26)
 #define VIDCON0_VIDOUT_SHIFT			(26)
 #define VIDCON0_VIDOUT_RGB			(0x0 << 26)
 #define VIDCON0_VIDOUT_RGB			(0x0 << 26)
 #define VIDCON0_VIDOUT_TV			(0x1 << 26)
 #define VIDCON0_VIDOUT_TV			(0x1 << 26)
 #define VIDCON0_VIDOUT_I80_LDI0			(0x2 << 26)
 #define VIDCON0_VIDOUT_I80_LDI0			(0x2 << 26)
 #define VIDCON0_VIDOUT_I80_LDI1			(0x3 << 26)
 #define VIDCON0_VIDOUT_I80_LDI1			(0x3 << 26)
+#define VIDCON0_VIDOUT_WB_RGB			(0x4 << 26)
+#define VIDCON0_VIDOUT_WB_I80_LDI0		(0x6 << 26)
+#define VIDCON0_VIDOUT_WB_I80_LDI1		(0x7 << 26)
 
 
 #define VIDCON0_L1_DATA_MASK			(0x7 << 23)
 #define VIDCON0_L1_DATA_MASK			(0x7 << 23)
 #define VIDCON0_L1_DATA_SHIFT			(23)
 #define VIDCON0_L1_DATA_SHIFT			(23)
@@ -77,6 +80,7 @@
 #define VIDCON1_LINECNT_MASK			(0x7ff << 16)
 #define VIDCON1_LINECNT_MASK			(0x7ff << 16)
 #define VIDCON1_LINECNT_SHIFT			(16)
 #define VIDCON1_LINECNT_SHIFT			(16)
 #define VIDCON1_LINECNT_GET(_v)			(((_v) >> 16) & 0x7ff)
 #define VIDCON1_LINECNT_GET(_v)			(((_v) >> 16) & 0x7ff)
+#define VIDCON1_FSTATUS_EVEN			(1 << 15)
 #define VIDCON1_VSTATUS_MASK			(0x3 << 13)
 #define VIDCON1_VSTATUS_MASK			(0x3 << 13)
 #define VIDCON1_VSTATUS_SHIFT			(13)
 #define VIDCON1_VSTATUS_SHIFT			(13)
 #define VIDCON1_VSTATUS_VSYNC			(0x0 << 13)
 #define VIDCON1_VSTATUS_VSYNC			(0x0 << 13)
@@ -116,6 +120,7 @@
 
 
 /* VIDTCON0 */
 /* VIDTCON0 */
 
 
+#define VIDTCON0				(0x10)
 #define VIDTCON0_VBPDE_MASK			(0xff << 24)
 #define VIDTCON0_VBPDE_MASK			(0xff << 24)
 #define VIDTCON0_VBPDE_SHIFT			(24)
 #define VIDTCON0_VBPDE_SHIFT			(24)
 #define VIDTCON0_VBPDE_LIMIT			(0xff)
 #define VIDTCON0_VBPDE_LIMIT			(0xff)
@@ -138,6 +143,7 @@
 
 
 /* VIDTCON1 */
 /* VIDTCON1 */
 
 
+#define VIDTCON1				(0x14)
 #define VIDTCON1_VFPDE_MASK			(0xff << 24)
 #define VIDTCON1_VFPDE_MASK			(0xff << 24)
 #define VIDTCON1_VFPDE_SHIFT			(24)
 #define VIDTCON1_VFPDE_SHIFT			(24)
 #define VIDTCON1_VFPDE_LIMIT			(0xff)
 #define VIDTCON1_VFPDE_LIMIT			(0xff)
@@ -158,6 +164,7 @@
 #define VIDTCON1_HSPW_LIMIT			(0xff)
 #define VIDTCON1_HSPW_LIMIT			(0xff)
 #define VIDTCON1_HSPW(_x)			((_x) << 0)
 #define VIDTCON1_HSPW(_x)			((_x) << 0)
 
 
+#define VIDTCON2				(0x18)
 #define VIDTCON2				(0x18)
 #define VIDTCON2				(0x18)
 #define VIDTCON2_LINEVAL_E(_x)			((((_x) & 0x800) >> 11) << 23)
 #define VIDTCON2_LINEVAL_E(_x)			((((_x) & 0x800) >> 11) << 23)
 #define VIDTCON2_LINEVAL_MASK			(0x7ff << 11)
 #define VIDTCON2_LINEVAL_MASK			(0x7ff << 11)
@@ -173,18 +180,27 @@
 
 
 /* WINCONx */
 /* WINCONx */
 
 
-
+#define WINCON(_win)				(0x20 + ((_win) * 4))
+#define WINCONx_CSCWIDTH_MASK			(0x3 << 26)
+#define WINCONx_CSCWIDTH_SHIFT			(26)
+#define WINCONx_CSCWIDTH_WIDE			(0x0 << 26)
+#define WINCONx_CSCWIDTH_NARROW			(0x3 << 26)
+#define WINCONx_ENLOCAL				(1 << 22)
+#define WINCONx_BUFSTATUS			(1 << 21)
+#define WINCONx_BUFSEL				(1 << 20)
+#define WINCONx_BUFAUTOEN			(1 << 19)
 #define WINCONx_BITSWP				(1 << 18)
 #define WINCONx_BITSWP				(1 << 18)
 #define WINCONx_BYTSWP				(1 << 17)
 #define WINCONx_BYTSWP				(1 << 17)
 #define WINCONx_HAWSWP				(1 << 16)
 #define WINCONx_HAWSWP				(1 << 16)
 #define WINCONx_WSWP				(1 << 15)
 #define WINCONx_WSWP				(1 << 15)
+#define WINCONx_YCbCr				(1 << 13)
 #define WINCONx_BURSTLEN_MASK			(0x3 << 9)
 #define WINCONx_BURSTLEN_MASK			(0x3 << 9)
 #define WINCONx_BURSTLEN_SHIFT			(9)
 #define WINCONx_BURSTLEN_SHIFT			(9)
 #define WINCONx_BURSTLEN_16WORD			(0x0 << 9)
 #define WINCONx_BURSTLEN_16WORD			(0x0 << 9)
 #define WINCONx_BURSTLEN_8WORD			(0x1 << 9)
 #define WINCONx_BURSTLEN_8WORD			(0x1 << 9)
 #define WINCONx_BURSTLEN_4WORD			(0x2 << 9)
 #define WINCONx_BURSTLEN_4WORD			(0x2 << 9)
-
 #define WINCONx_ENWIN				(1 << 0)
 #define WINCONx_ENWIN				(1 << 0)
+
 #define WINCON0_BPPMODE_MASK			(0xf << 2)
 #define WINCON0_BPPMODE_MASK			(0xf << 2)
 #define WINCON0_BPPMODE_SHIFT			(2)
 #define WINCON0_BPPMODE_SHIFT			(2)
 #define WINCON0_BPPMODE_1BPP			(0x0 << 2)
 #define WINCON0_BPPMODE_1BPP			(0x0 << 2)
@@ -196,9 +212,8 @@
 #define WINCON0_BPPMODE_18BPP_666		(0x8 << 2)
 #define WINCON0_BPPMODE_18BPP_666		(0x8 << 2)
 #define WINCON0_BPPMODE_24BPP_888		(0xb << 2)
 #define WINCON0_BPPMODE_24BPP_888		(0xb << 2)
 
 
+#define WINCON1_LOCALSEL_CAMIF			(1 << 23)
 #define WINCON1_BLD_PIX				(1 << 6)
 #define WINCON1_BLD_PIX				(1 << 6)
-
-#define WINCON1_ALPHA_SEL			(1 << 1)
 #define WINCON1_BPPMODE_MASK			(0xf << 2)
 #define WINCON1_BPPMODE_MASK			(0xf << 2)
 #define WINCON1_BPPMODE_SHIFT			(2)
 #define WINCON1_BPPMODE_SHIFT			(2)
 #define WINCON1_BPPMODE_1BPP			(0x0 << 2)
 #define WINCON1_BPPMODE_1BPP			(0x0 << 2)
@@ -216,6 +231,7 @@
 #define WINCON1_BPPMODE_24BPP_A1887		(0xc << 2)
 #define WINCON1_BPPMODE_24BPP_A1887		(0xc << 2)
 #define WINCON1_BPPMODE_25BPP_A1888		(0xd << 2)
 #define WINCON1_BPPMODE_25BPP_A1888		(0xd << 2)
 #define WINCON1_BPPMODE_28BPP_A4888		(0xd << 2)
 #define WINCON1_BPPMODE_28BPP_A4888		(0xd << 2)
+#define WINCON1_ALPHA_SEL			(1 << 1)
 
 
 /* S5PV210 */
 /* S5PV210 */
 #define SHADOWCON				(0x34)
 #define SHADOWCON				(0x34)
@@ -225,6 +241,9 @@
 /* Local input channels (windows 0-2) */
 /* Local input channels (windows 0-2) */
 #define SHADOWCON_CHx_LOCAL_ENABLE(_win)	(1 << (5 + (_win)))
 #define SHADOWCON_CHx_LOCAL_ENABLE(_win)	(1 << (5 + (_win)))
 
 
+/* VIDOSDx */
+
+#define VIDOSD_BASE				(0x40)
 #define VIDOSDxA_TOPLEFT_X_E(_x)		((((_x) & 0x800) >> 11) << 23)
 #define VIDOSDxA_TOPLEFT_X_E(_x)		((((_x) & 0x800) >> 11) << 23)
 #define VIDOSDxA_TOPLEFT_X_MASK			(0x7ff << 11)
 #define VIDOSDxA_TOPLEFT_X_MASK			(0x7ff << 11)
 #define VIDOSDxA_TOPLEFT_X_SHIFT		(11)
 #define VIDOSDxA_TOPLEFT_X_SHIFT		(11)
@@ -293,6 +312,7 @@
 
 
 /* Interrupt controls and status */
 /* Interrupt controls and status */
 
 
+#define VIDINTCON0				(0x130)
 #define VIDINTCON0_FIFOINTERVAL_MASK		(0x3f << 20)
 #define VIDINTCON0_FIFOINTERVAL_MASK		(0x3f << 20)
 #define VIDINTCON0_FIFOINTERVAL_SHIFT		(20)
 #define VIDINTCON0_FIFOINTERVAL_SHIFT		(20)
 #define VIDINTCON0_FIFOINTERVAL_LIMIT		(0x3f)
 #define VIDINTCON0_FIFOINTERVAL_LIMIT		(0x3f)
@@ -321,6 +341,9 @@
 #define VIDINTCON0_FIFIOSEL_SHIFT		(5)
 #define VIDINTCON0_FIFIOSEL_SHIFT		(5)
 #define VIDINTCON0_FIFIOSEL_WINDOW0		(0x1 << 5)
 #define VIDINTCON0_FIFIOSEL_WINDOW0		(0x1 << 5)
 #define VIDINTCON0_FIFIOSEL_WINDOW1		(0x2 << 5)
 #define VIDINTCON0_FIFIOSEL_WINDOW1		(0x2 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW2		(0x10 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW3		(0x20 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW4		(0x40 << 5)
 
 
 #define VIDINTCON0_FIFOLEVEL_MASK		(0x7 << 2)
 #define VIDINTCON0_FIFOLEVEL_MASK		(0x7 << 2)
 #define VIDINTCON0_FIFOLEVEL_SHIFT		(2)
 #define VIDINTCON0_FIFOLEVEL_SHIFT		(2)
@@ -357,16 +380,39 @@
 #define WxKEYCON1_COLVAL_LIMIT			(0xffffff)
 #define WxKEYCON1_COLVAL_LIMIT			(0xffffff)
 #define WxKEYCON1_COLVAL(_x)			((_x) << 0)
 #define WxKEYCON1_COLVAL(_x)			((_x) << 0)
 
 
+/* Dithering control */
+#define DITHMODE				(0x170)
+#define DITHMODE_R_POS_MASK			(0x3 << 5)
+#define DITHMODE_R_POS_SHIFT			(5)
+#define DITHMODE_R_POS_8BIT			(0x0 << 5)
+#define DITHMODE_R_POS_6BIT			(0x1 << 5)
+#define DITHMODE_R_POS_5BIT			(0x2 << 5)
+#define DITHMODE_G_POS_MASK			(0x3 << 3)
+#define DITHMODE_G_POS_SHIFT			(3)
+#define DITHMODE_G_POS_8BIT			(0x0 << 3)
+#define DITHMODE_G_POS_6BIT			(0x1 << 3)
+#define DITHMODE_G_POS_5BIT			(0x2 << 3)
+#define DITHMODE_B_POS_MASK			(0x3 << 1)
+#define DITHMODE_B_POS_SHIFT			(1)
+#define DITHMODE_B_POS_8BIT			(0x0 << 1)
+#define DITHMODE_B_POS_6BIT			(0x1 << 1)
+#define DITHMODE_B_POS_5BIT			(0x2 << 1)
+#define DITHMODE_DITH_EN			(1 << 0)
 
 
 /* Window blanking (MAP) */
 /* Window blanking (MAP) */
-
+#define WINxMAP(_win)				(0x180 + ((_win) * 4))
 #define WINxMAP_MAP				(1 << 24)
 #define WINxMAP_MAP				(1 << 24)
 #define WINxMAP_MAP_COLOUR_MASK			(0xffffff << 0)
 #define WINxMAP_MAP_COLOUR_MASK			(0xffffff << 0)
 #define WINxMAP_MAP_COLOUR_SHIFT		(0)
 #define WINxMAP_MAP_COLOUR_SHIFT		(0)
 #define WINxMAP_MAP_COLOUR_LIMIT		(0xffffff)
 #define WINxMAP_MAP_COLOUR_LIMIT		(0xffffff)
 #define WINxMAP_MAP_COLOUR(_x)			((_x) << 0)
 #define WINxMAP_MAP_COLOUR(_x)			((_x) << 0)
 
 
+/* Winodw palette control */
+#define WPALCON					(0x1A0)
 #define WPALCON_PAL_UPDATE			(1 << 9)
 #define WPALCON_PAL_UPDATE			(1 << 9)
+#define WPALCON_W4PAL_16BPP_A555		(1 << 8)
+#define WPALCON_W3PAL_16BPP_A555		(1 << 7)
+#define WPALCON_W2PAL_16BPP_A555		(1 << 6)
 #define WPALCON_W1PAL_MASK			(0x7 << 3)
 #define WPALCON_W1PAL_MASK			(0x7 << 3)
 #define WPALCON_W1PAL_SHIFT			(3)
 #define WPALCON_W1PAL_SHIFT			(3)
 #define WPALCON_W1PAL_25BPP_A888		(0x0 << 3)
 #define WPALCON_W1PAL_25BPP_A888		(0x0 << 3)
@@ -376,7 +422,6 @@
 #define WPALCON_W1PAL_18BPP			(0x4 << 3)
 #define WPALCON_W1PAL_18BPP			(0x4 << 3)
 #define WPALCON_W1PAL_16BPP_A555		(0x5 << 3)
 #define WPALCON_W1PAL_16BPP_A555		(0x5 << 3)
 #define WPALCON_W1PAL_16BPP_565			(0x6 << 3)
 #define WPALCON_W1PAL_16BPP_565			(0x6 << 3)
-
 #define WPALCON_W0PAL_MASK			(0x7 << 0)
 #define WPALCON_W0PAL_MASK			(0x7 << 0)
 #define WPALCON_W0PAL_SHIFT			(0)
 #define WPALCON_W0PAL_SHIFT			(0)
 #define WPALCON_W0PAL_25BPP_A888		(0x0 << 0)
 #define WPALCON_W0PAL_25BPP_A888		(0x0 << 0)
@@ -394,115 +439,6 @@
 #define BLENDCON_NEW_4BIT_ALPHA_VALUE		(0 << 0)
 #define BLENDCON_NEW_4BIT_ALPHA_VALUE		(0 << 0)
 
 
 #define S3C_FB_MAX_WIN (5)  /* number of hardware windows available. */
 #define S3C_FB_MAX_WIN (5)  /* number of hardware windows available. */
-#define VIDCON1_FSTATUS_EVEN	(1 << 15)
-
-/* Video timing controls */
-#define VIDTCON0				(0x10)
-#define VIDTCON1				(0x14)
-#define VIDTCON2				(0x18)
-
-/* Window position controls */
-
-#define WINCON(_win)				(0x20 + ((_win) * 4))
-
-/* OSD1 and OSD4 do not have register D */
-
-#define VIDOSD_BASE				(0x40)
-
-#define VIDINTCON0				(0x130)
-
-/* WINCONx */
-
-#define WINCONx_CSCWIDTH_MASK			(0x3 << 26)
-#define WINCONx_CSCWIDTH_SHIFT			(26)
-#define WINCONx_CSCWIDTH_WIDE			(0x0 << 26)
-#define WINCONx_CSCWIDTH_NARROW			(0x3 << 26)
-
-#define WINCONx_ENLOCAL				(1 << 22)
-#define WINCONx_BUFSTATUS			(1 << 21)
-#define WINCONx_BUFSEL				(1 << 20)
-#define WINCONx_BUFAUTOEN			(1 << 19)
-#define WINCONx_YCbCr				(1 << 13)
-
-#define WINCON1_LOCALSEL_CAMIF			(1 << 23)
-
-#define WINCON2_LOCALSEL_CAMIF			(1 << 23)
-#define WINCON2_BLD_PIX				(1 << 6)
-
-#define WINCON2_ALPHA_SEL			(1 << 1)
-#define WINCON2_BPPMODE_MASK			(0xf << 2)
-#define WINCON2_BPPMODE_SHIFT			(2)
-#define WINCON2_BPPMODE_1BPP			(0x0 << 2)
-#define WINCON2_BPPMODE_2BPP			(0x1 << 2)
-#define WINCON2_BPPMODE_4BPP			(0x2 << 2)
-#define WINCON2_BPPMODE_8BPP_1232		(0x4 << 2)
-#define WINCON2_BPPMODE_16BPP_565		(0x5 << 2)
-#define WINCON2_BPPMODE_16BPP_A1555		(0x6 << 2)
-#define WINCON2_BPPMODE_16BPP_I1555		(0x7 << 2)
-#define WINCON2_BPPMODE_18BPP_666		(0x8 << 2)
-#define WINCON2_BPPMODE_18BPP_A1665		(0x9 << 2)
-#define WINCON2_BPPMODE_19BPP_A1666		(0xa << 2)
-#define WINCON2_BPPMODE_24BPP_888		(0xb << 2)
-#define WINCON2_BPPMODE_24BPP_A1887		(0xc << 2)
-#define WINCON2_BPPMODE_25BPP_A1888		(0xd << 2)
-#define WINCON2_BPPMODE_28BPP_A4888		(0xd << 2)
-
-#define WINCON3_BLD_PIX				(1 << 6)
-
-#define WINCON3_ALPHA_SEL			(1 << 1)
-#define WINCON3_BPPMODE_MASK			(0xf << 2)
-#define WINCON3_BPPMODE_SHIFT			(2)
-#define WINCON3_BPPMODE_1BPP			(0x0 << 2)
-#define WINCON3_BPPMODE_2BPP			(0x1 << 2)
-#define WINCON3_BPPMODE_4BPP			(0x2 << 2)
-#define WINCON3_BPPMODE_16BPP_565		(0x5 << 2)
-#define WINCON3_BPPMODE_16BPP_A1555		(0x6 << 2)
-#define WINCON3_BPPMODE_16BPP_I1555		(0x7 << 2)
-#define WINCON3_BPPMODE_18BPP_666		(0x8 << 2)
-#define WINCON3_BPPMODE_18BPP_A1665		(0x9 << 2)
-#define WINCON3_BPPMODE_19BPP_A1666		(0xa << 2)
-#define WINCON3_BPPMODE_24BPP_888		(0xb << 2)
-#define WINCON3_BPPMODE_24BPP_A1887		(0xc << 2)
-#define WINCON3_BPPMODE_25BPP_A1888		(0xd << 2)
-#define WINCON3_BPPMODE_28BPP_A4888		(0xd << 2)
-
-#define VIDINTCON0_FIFIOSEL_WINDOW2		(0x10 << 5)
-#define VIDINTCON0_FIFIOSEL_WINDOW3		(0x20 << 5)
-#define VIDINTCON0_FIFIOSEL_WINDOW4		(0x40 << 5)
-
-#define DITHMODE				(0x170)
-#define WINxMAP(_win)				(0x180 + ((_win) * 4))
-
-
-#define DITHMODE_R_POS_MASK			(0x3 << 5)
-#define DITHMODE_R_POS_SHIFT			(5)
-#define DITHMODE_R_POS_8BIT			(0x0 << 5)
-#define DITHMODE_R_POS_6BIT			(0x1 << 5)
-#define DITHMODE_R_POS_5BIT			(0x2 << 5)
-
-#define DITHMODE_G_POS_MASK			(0x3 << 3)
-#define DITHMODE_G_POS_SHIFT			(3)
-#define DITHMODE_G_POS_8BIT			(0x0 << 3)
-#define DITHMODE_G_POS_6BIT			(0x1 << 3)
-#define DITHMODE_G_POS_5BIT			(0x2 << 3)
-
-#define DITHMODE_B_POS_MASK			(0x3 << 1)
-#define DITHMODE_B_POS_SHIFT			(1)
-#define DITHMODE_B_POS_8BIT			(0x0 << 1)
-#define DITHMODE_B_POS_6BIT			(0x1 << 1)
-#define DITHMODE_B_POS_5BIT			(0x2 << 1)
-
-#define DITHMODE_DITH_EN			(1 << 0)
-
-#define WPALCON					(0x1A0)
-
-/* Palette control */
-/* Note for S5PC100: you can still use those macros on WPALCON (aka WPALCON_L),
- * but make sure that WPALCON_H W2PAL-W4PAL entries are zeroed out */
-#define WPALCON_W4PAL_16BPP_A555		(1 << 8)
-#define WPALCON_W3PAL_16BPP_A555		(1 << 7)
-#define WPALCON_W2PAL_16BPP_A555		(1 << 6)
-
 
 
 /* Notes on per-window bpp settings
 /* Notes on per-window bpp settings
  *
  *

+ 1 - 3
include/video/sh_mipi_dsi.h

@@ -25,8 +25,6 @@ enum sh_mipi_dsi_data_fmt {
 	MIPI_YUV420,
 	MIPI_YUV420,
 };
 };
 
 
-struct sh_mobile_lcdc_chan_cfg;
-
 #define SH_MIPI_DSI_HSABM	(1 << 0)
 #define SH_MIPI_DSI_HSABM	(1 << 0)
 #define SH_MIPI_DSI_HBPBM	(1 << 1)
 #define SH_MIPI_DSI_HBPBM	(1 << 1)
 #define SH_MIPI_DSI_HFPBM	(1 << 2)
 #define SH_MIPI_DSI_HFPBM	(1 << 2)
@@ -47,7 +45,7 @@ struct sh_mobile_lcdc_chan_cfg;
 
 
 struct sh_mipi_dsi_info {
 struct sh_mipi_dsi_info {
 	enum sh_mipi_dsi_data_fmt	data_format;
 	enum sh_mipi_dsi_data_fmt	data_format;
-	struct sh_mobile_lcdc_chan_cfg	*lcd_chan;
+	int				channel;
 	int				lane;
 	int				lane;
 	unsigned long			flags;
 	unsigned long			flags;
 	u32				clksrc;
 	u32				clksrc;

+ 0 - 1
include/video/sh_mobile_lcdc.h

@@ -163,7 +163,6 @@ struct sh_mobile_lcdc_bl_info {
 	const char *name;
 	const char *name;
 	int max_brightness;
 	int max_brightness;
 	int (*set_brightness)(int brightness);
 	int (*set_brightness)(int brightness);
-	int (*get_brightness)(void);
 };
 };
 
 
 struct sh_mobile_lcdc_overlay_cfg {
 struct sh_mobile_lcdc_overlay_cfg {