Bläddra i källkod

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

OMAPDSS changes for 3.8, 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

* tag 'omapdss-for-3.8' of git://gitorious.org/linux-omap-dss2/linux: (140 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
  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
  OMAPDSS: manage framedone irq with mgr ops
  OMAPDSS: add manager ops
  ...
Tomi Valkeinen 12 år sedan
förälder
incheckning
e7f5c9a16e
62 ändrade filer med 2860 tillägg och 3021 borttagningar
  1. 4 6
      Documentation/arm/OMAP/DSS
  2. 0 14
      arch/arm/mach-omap2/board-rx51-video.c
  3. 0 3
      arch/arm/mach-omap2/board-rx51.c
  4. 48 5
      arch/arm/mach-omap2/display.c
  5. 0 16
      arch/arm/mach-omap2/sdrc.c
  6. 0 2
      arch/arm/plat-omap/common.c
  7. 64 2
      arch/arm/plat-omap/fb.c
  8. 0 7
      arch/arm/plat-omap/include/plat/sdrc.h
  9. 0 43
      arch/arm/plat-omap/include/plat/vram.h
  10. 16 7
      drivers/media/platform/omap/omap_vout.c
  11. 1 1
      drivers/media/platform/omap/omap_vout_vrfb.c
  12. 1 1
      drivers/media/platform/omap/omap_voutdef.h
  13. 28 10
      drivers/media/platform/omap/omap_voutlib.c
  14. 3 0
      drivers/media/platform/omap/omap_voutlib.h
  15. 11 0
      drivers/staging/omapdrm/omap_drv.c
  16. 0 3
      drivers/video/omap2/Kconfig
  17. 0 1
      drivers/video/omap2/Makefile
  18. 0 23
      drivers/video/omap2/displays/panel-acx565akm.c
  19. 0 36
      drivers/video/omap2/displays/panel-generic-dpi.c
  20. 0 34
      drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
  21. 9 80
      drivers/video/omap2/displays/panel-n8x0.c
  22. 0 24
      drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
  23. 1 44
      drivers/video/omap2/displays/panel-picodlp.c
  24. 0 17
      drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
  25. 0 72
      drivers/video/omap2/displays/panel-taal.c
  26. 0 33
      drivers/video/omap2/displays/panel-tfp410.c
  27. 0 20
      drivers/video/omap2/displays/panel-tpo-td043mtea1.c
  28. 14 21
      drivers/video/omap2/dss/Kconfig
  29. 6 1
      drivers/video/omap2/dss/Makefile
  30. 264 67
      drivers/video/omap2/dss/apply.c
  31. 25 47
      drivers/video/omap2/dss/core.c
  32. 667 0
      drivers/video/omap2/dss/dispc-compat.c
  33. 30 0
      drivers/video/omap2/dss/dispc-compat.h
  34. 303 799
      drivers/video/omap2/dss/dispc.c
  35. 321 0
      drivers/video/omap2/dss/display-sysfs.c
  36. 3 383
      drivers/video/omap2/dss/display.c
  37. 95 31
      drivers/video/omap2/dss/dpi.c
  38. 122 125
      drivers/video/omap2/dss/dsi.c
  39. 122 16
      drivers/video/omap2/dss/dss.c
  40. 19 105
      drivers/video/omap2/dss/dss.h
  41. 51 28
      drivers/video/omap2/dss/dss_features.c
  42. 3 9
      drivers/video/omap2/dss/dss_features.h
  43. 114 44
      drivers/video/omap2/dss/hdmi.c
  44. 15 67
      drivers/video/omap2/dss/hdmi_panel.c
  45. 0 39
      drivers/video/omap2/dss/manager.c
  46. 61 29
      drivers/video/omap2/dss/output.c
  47. 0 17
      drivers/video/omap2/dss/overlay.c
  48. 17 6
      drivers/video/omap2/dss/rfbi.c
  49. 10 1
      drivers/video/omap2/dss/sdi.c
  50. 3 0
      drivers/video/omap2/dss/ti_hdmi.h
  51. 10 1
      drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
  52. 10 1
      drivers/video/omap2/dss/venc.c
  53. 0 19
      drivers/video/omap2/dss/venc_panel.c
  54. 0 1
      drivers/video/omap2/omapfb/Kconfig
  55. 16 32
      drivers/video/omap2/omapfb/omapfb-ioctl.c
  56. 139 73
      drivers/video/omap2/omapfb/omapfb-main.c
  57. 5 1
      drivers/video/omap2/omapfb/omapfb-sysfs.c
  58. 11 9
      drivers/video/omap2/omapfb/omapfb.h
  59. 0 514
      drivers/video/omap2/vram.c
  60. 121 21
      drivers/video/omap2/vrfb.c
  61. 95 10
      include/video/omapdss.h
  62. 2 0
      include/video/omapvrfb.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.

+ 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();
 }
 }
 
 

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

@@ -100,17 +100,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
@@ -161,8 +164,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;
 }
 }
@@ -284,6 +289,35 @@ err:
 	return ERR_PTR(r);
 	return ERR_PTR(r);
 }
 }
 
 
+static enum omapdss_version __init omap_display_get_version(void)
+{
+	if (cpu_is_omap24xx())
+		return OMAPDSS_VER_OMAP24xx;
+	else if (cpu_is_omap3630())
+		return OMAPDSS_VER_OMAP3630;
+	else if (cpu_is_omap34xx()) {
+		if (soc_is_am35xx()) {
+			return OMAPDSS_VER_AM35xx;
+		} else {
+			if (omap_rev() < OMAP3430_REV_ES3_0)
+				return OMAPDSS_VER_OMAP34xx_ES1;
+			else
+				return OMAPDSS_VER_OMAP34xx_ES3;
+		}
+	} else if (omap_rev() == OMAP4430_REV_ES1_0)
+		return OMAPDSS_VER_OMAP4430_ES1;
+	else if (omap_rev() == OMAP4430_REV_ES2_0 ||
+			omap_rev() == OMAP4430_REV_ES2_1 ||
+			omap_rev() == OMAP4430_REV_ES2_2)
+		return OMAPDSS_VER_OMAP4430_ES2;
+	else if (cpu_is_omap44xx())
+		return OMAPDSS_VER_OMAP4;
+	else if (soc_is_omap54xx())
+		return OMAPDSS_VER_OMAP5;
+	else
+		return OMAPDSS_VER_UNKNOWN;
+}
+
 int __init omap_display_init(struct omap_dss_board_info *board_data)
 int __init omap_display_init(struct omap_dss_board_info *board_data)
 {
 {
 	int r = 0;
 	int r = 0;
@@ -291,9 +325,18 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
 	int i, oh_count;
 	int i, oh_count;
 	const struct omap_dss_hwmod_data *curr_dss_hwmod;
 	const struct omap_dss_hwmod_data *curr_dss_hwmod;
 	struct platform_device *dss_pdev;
 	struct platform_device *dss_pdev;
+	enum omapdss_version ver;
 
 
 	/* create omapdss device */
 	/* create omapdss device */
 
 
+	ver = omap_display_get_version();
+
+	if (ver == OMAPDSS_VER_UNKNOWN) {
+		pr_err("DSS not supported on this SoC\n");
+		return -ENODEV;
+	}
+
+	board_data->version = ver;
 	board_data->dsi_enable_pads = omap_dsi_enable_pads;
 	board_data->dsi_enable_pads = omap_dsi_enable_pads;
 	board_data->dsi_disable_pads = omap_dsi_disable_pads;
 	board_data->dsi_disable_pads = omap_dsi_disable_pads;
 	board_data->get_context_loss_count = omap_pm_get_dev_context_loss_count;
 	board_data->get_context_loss_count = omap_pm_get_dev_context_loss_count;

+ 0 - 16
arch/arm/mach-omap2/sdrc.c

@@ -160,19 +160,3 @@ void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
 	sdrc_write_reg(l, SDRC_POWER);
 	sdrc_write_reg(l, SDRC_POWER);
 	omap2_sms_save_context();
 	omap2_sms_save_context();
 }
 }
-
-void omap2_sms_write_rot_control(u32 val, unsigned ctx)
-{
-	sms_write_reg(val, SMS_ROT_CONTROL(ctx));
-}
-
-void omap2_sms_write_rot_size(u32 val, unsigned ctx)
-{
-	sms_write_reg(val, SMS_ROT_SIZE(ctx));
-}
-
-void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx)
-{
-	sms_write_reg(val, SMS_ROT_PHYSICAL_BA(ctx));
-}
-

+ 0 - 2
arch/arm/plat-omap/common.c

@@ -17,7 +17,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/dma-mapping.h>
 
 
 #include <plat/common.h>
 #include <plat/common.h>
-#include <plat/vram.h>
 #include <linux/platform_data/dsp-omap.h>
 #include <linux/platform_data/dsp-omap.h>
 #include <plat/dma.h>
 #include <plat/dma.h>
 
 
@@ -25,7 +24,6 @@
 
 
 void __init omap_reserve(void)
 void __init omap_reserve(void)
 {
 {
-	omap_vram_reserve_sdram_memblock();
 	omap_dsp_reserve_sdram_memblock();
 	omap_dsp_reserve_sdram_memblock();
 	omap_secure_ram_reserve_memblock();
 	omap_secure_ram_reserve_memblock();
 	omap_barrier_reserve_memblock();
 	omap_barrier_reserve_memblock();

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

@@ -29,10 +29,72 @@
 #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 <mach/hardware.h>
 #include <mach/hardware.h>
 #include <asm/mach/map.h>
 #include <asm/mach/map.h>
 
 
+#include <plat/cpu.h>
+
+#ifdef CONFIG_OMAP2_VRFB
+
+/*
+ * The first memory resource is the register region for VRFB,
+ * the rest are VRFB virtual memory areas for each VRFB context.
+ */
+
+static const struct resource omap2_vrfb_resources[] = {
+	DEFINE_RES_MEM_NAMED(0x68008000u, 0x40, "vrfb-regs"),
+	DEFINE_RES_MEM_NAMED(0x70000000u, 0x4000000, "vrfb-area-0"),
+	DEFINE_RES_MEM_NAMED(0x74000000u, 0x4000000, "vrfb-area-1"),
+	DEFINE_RES_MEM_NAMED(0x78000000u, 0x4000000, "vrfb-area-2"),
+	DEFINE_RES_MEM_NAMED(0x7c000000u, 0x4000000, "vrfb-area-3"),
+};
+
+static const struct resource omap3_vrfb_resources[] = {
+	DEFINE_RES_MEM_NAMED(0x6C000180u, 0xc0, "vrfb-regs"),
+	DEFINE_RES_MEM_NAMED(0x70000000u, 0x4000000, "vrfb-area-0"),
+	DEFINE_RES_MEM_NAMED(0x74000000u, 0x4000000, "vrfb-area-1"),
+	DEFINE_RES_MEM_NAMED(0x78000000u, 0x4000000, "vrfb-area-2"),
+	DEFINE_RES_MEM_NAMED(0x7c000000u, 0x4000000, "vrfb-area-3"),
+	DEFINE_RES_MEM_NAMED(0xe0000000u, 0x4000000, "vrfb-area-4"),
+	DEFINE_RES_MEM_NAMED(0xe4000000u, 0x4000000, "vrfb-area-5"),
+	DEFINE_RES_MEM_NAMED(0xe8000000u, 0x4000000, "vrfb-area-6"),
+	DEFINE_RES_MEM_NAMED(0xec000000u, 0x4000000, "vrfb-area-7"),
+	DEFINE_RES_MEM_NAMED(0xf0000000u, 0x4000000, "vrfb-area-8"),
+	DEFINE_RES_MEM_NAMED(0xf4000000u, 0x4000000, "vrfb-area-9"),
+	DEFINE_RES_MEM_NAMED(0xf8000000u, 0x4000000, "vrfb-area-10"),
+	DEFINE_RES_MEM_NAMED(0xfc000000u, 0x4000000, "vrfb-area-11"),
+};
+
+static int __init omap_init_vrfb(void)
+{
+	struct platform_device *pdev;
+	const struct resource *res;
+	unsigned int num_res;
+
+	if (cpu_is_omap24xx()) {
+		res = omap2_vrfb_resources;
+		num_res = ARRAY_SIZE(omap2_vrfb_resources);
+	} else if (cpu_is_omap34xx()) {
+		res = omap3_vrfb_resources;
+		num_res = ARRAY_SIZE(omap3_vrfb_resources);
+	} else {
+		return 0;
+	}
+
+	pdev = platform_device_register_resndata(NULL, "omapvrfb", -1,
+			res, num_res, NULL, 0);
+
+	if (IS_ERR(pdev))
+		return PTR_ERR(pdev);
+	else
+		return 0;
+}
+
+arch_initcall(omap_init_vrfb);
+#endif
+
 #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
 #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
 
 
 static bool omapfb_lcd_configured;
 static bool omapfb_lcd_configured;
@@ -45,7 +107,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,
@@ -81,7 +143,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 - 7
arch/arm/plat-omap/include/plat/sdrc.h

@@ -94,9 +94,6 @@
 /* SMS register offsets - read/write with sms_{read,write}_reg() */
 /* SMS register offsets - read/write with sms_{read,write}_reg() */
 
 
 #define SMS_SYSCONFIG			0x010
 #define SMS_SYSCONFIG			0x010
-#define SMS_ROT_CONTROL(context)	(0x180 + 0x10 * context)
-#define SMS_ROT_SIZE(context)		(0x184 + 0x10 * context)
-#define SMS_ROT_PHYSICAL_BA(context)	(0x188 + 0x10 * context)
 /* REVISIT: fill in other SMS registers here */
 /* REVISIT: fill in other SMS registers here */
 
 
 
 
@@ -137,10 +134,6 @@ int omap2_sdrc_get_params(unsigned long r,
 void omap2_sms_save_context(void);
 void omap2_sms_save_context(void);
 void omap2_sms_restore_context(void);
 void omap2_sms_restore_context(void);
 
 
-void omap2_sms_write_rot_control(u32 val, unsigned ctx);
-void omap2_sms_write_rot_size(u32 val, unsigned ctx);
-void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx);
-
 #ifdef CONFIG_ARCH_OMAP2
 #ifdef CONFIG_ARCH_OMAP2
 
 
 struct memory_timings {
 struct memory_timings {

+ 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

+ 16 - 7
drivers/media/platform/omap/omap_vout.c

@@ -44,9 +44,7 @@
 #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 <plat/dma.h>
-#include <plat/vrfb.h>
+#include <video/omapvrfb.h>
 #include <video/omapdss.h>
 #include <video/omapdss.h>
 
 
 #include "omap_voutlib.h"
 #include "omap_voutlib.h"
@@ -2064,7 +2062,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
@@ -2186,14 +2184,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) {
@@ -2288,6 +2295,8 @@ probe_err1:
 	}
 	}
 probe_err0:
 probe_err0:
 	kfree(vid_dev);
 	kfree(vid_dev);
+err_dss_init:
+	omapdss_compat_uninit();
 	return ret;
 	return ret;
 }
 }
 
 

+ 1 - 1
drivers/media/platform/omap/omap_vout_vrfb.c

@@ -17,7 +17,7 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-device.h>
 
 
 #include <plat/dma.h>
 #include <plat/dma.h>
-#include <plat/vrfb.h>
+#include <video/omapvrfb.h>
 
 
 #include "omap_voutdef.h"
 #include "omap_voutdef.h"
 #include "omap_voutlib.h"
 #include "omap_voutlib.h"

+ 1 - 1
drivers/media/platform/omap/omap_voutdef.h

@@ -12,7 +12,7 @@
 #define OMAP_VOUTDEF_H
 #define OMAP_VOUTDEF_H
 
 
 #include <video/omapdss.h>
 #include <video/omapdss.h>
-#include <plat/vrfb.h>
+#include <video/omapvrfb.h>
 
 
 #define YUYV_BPP        2
 #define YUYV_BPP        2
 #define RGB565_BPP      2
 #define RGB565_BPP      2

+ 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

@@ -572,6 +572,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);
@@ -583,6 +591,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;
 	}
 	}
 
 
@@ -618,6 +627,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;
 
 

+ 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();
-
-	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

+ 303 - 799
drivers/video/omap2/dss/dispc.c

@@ -33,11 +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 <plat/cpu.h>
+#include <linux/sizes.h>
 
 
 #include <video/omapdss.h>
 #include <video/omapdss.h>
 
 
@@ -48,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,
@@ -75,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;
@@ -88,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
@@ -112,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 {
@@ -188,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 },
@@ -243,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);
 
 
@@ -376,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);
@@ -391,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;
@@ -498,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
@@ -522,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)
 {
 {
@@ -532,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)
 {
 {
@@ -552,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)
 {
 {
@@ -977,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)
 {
 {
@@ -1042,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);
 }
 }
 
 
@@ -1076,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;
 
 
@@ -1124,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);
 }
 }
 
 
@@ -1246,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;
@@ -1991,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;
@@ -2022,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;
 
 
 	/*
 	/*
@@ -2033,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;
@@ -2081,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
@@ -2119,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
@@ -2133,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,
@@ -2159,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());
@@ -2182,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,
@@ -2198,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);
 
 
@@ -2210,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);
 
 
@@ -2229,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;
 	}
 	}
@@ -2248,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,
@@ -2260,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);
 
 
@@ -2285,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,
@@ -2309,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 ||
@@ -2332,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);
@@ -2355,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,
@@ -2370,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;
@@ -2400,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);
@@ -2438,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);
@@ -2505,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);
@@ -2516,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,
@@ -2524,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)
@@ -2584,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;
@@ -2793,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);
 }
 }
@@ -2842,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);
@@ -2854,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;
 
 
@@ -2880,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;
@@ -2909,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,
@@ -3012,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;
@@ -3051,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)
@@ -3078,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);
@@ -3103,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)
@@ -3174,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;
@@ -3246,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;
@@ -3353,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;
@@ -3430,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 */
@@ -3533,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);
@@ -3557,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;
+	return dispc_read_reg(DISPC_IRQSTATUS);
 }
 }
-EXPORT_SYMBOL(omap_dispc_register_isr);
+EXPORT_SYMBOL(dispc_read_irqstatus);
 
 
-int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
+void dispc_clear_irqstatus(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;
+	dispc_write_reg(DISPC_IRQSTATUS, mask);
 }
 }
-EXPORT_SYMBOL(omap_dispc_unregister_isr);
+EXPORT_SYMBOL(dispc_clear_irqstatus);
 
 
-#ifdef DEBUG
-static void print_irq_status(u32 status)
+u32 dispc_read_irqenable(void)
 {
 {
-	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");
+	return dispc_read_reg(DISPC_IRQENABLE);
 }
 }
-#endif
+EXPORT_SYMBOL(dispc_read_irqenable);
 
 
-/* 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)
+void dispc_write_irqenable(u32 mask)
 {
 {
-	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;
+	u32 old_mask = dispc_read_reg(DISPC_IRQENABLE);
 
 
-			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();
-}
-
-int omap_dispc_wait_for_irq_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_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;
-}
-
-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;
-}
-
-static void _omap_dispc_initialize_irq(void)
-{
-	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));
-
-	_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)
 {
 {
@@ -4000,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 = {
@@ -4012,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 = {
@@ -4024,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 = {
@@ -4036,35 +3526,70 @@ 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,
 	.gfx_fifo_workaround	=	true,
 	.gfx_fifo_workaround	=	true,
 };
 };
 
 
-static int __init dispc_init_features(struct device *dev)
+static int __init dispc_init_features(struct platform_device *pdev)
 {
 {
 	const struct dispc_features *src;
 	const struct dispc_features *src;
 	struct dispc_features *dst;
 	struct dispc_features *dst;
 
 
-	dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
+	dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
 	if (!dst) {
 	if (!dst) {
-		dev_err(dev, "Failed to allocate DISPC Features\n");
+		dev_err(&pdev->dev, "Failed to allocate DISPC Features\n");
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
-	if (cpu_is_omap24xx()) {
+	switch (omapdss_get_version()) {
+	case OMAPDSS_VER_OMAP24xx:
 		src = &omap24xx_dispc_feats;
 		src = &omap24xx_dispc_feats;
-	} else if (cpu_is_omap34xx()) {
-		if (omap_rev() < OMAP3430_REV_ES3_0)
-			src = &omap34xx_rev1_0_dispc_feats;
-		else
-			src = &omap34xx_rev3_0_dispc_feats;
-	} else if (cpu_is_omap44xx()) {
-		src = &omap44xx_dispc_feats;
-	} else if (soc_is_omap54xx()) {
+		break;
+
+	case OMAPDSS_VER_OMAP34xx_ES1:
+		src = &omap34xx_rev1_0_dispc_feats;
+		break;
+
+	case OMAPDSS_VER_OMAP34xx_ES3:
+	case OMAPDSS_VER_OMAP3630:
+	case OMAPDSS_VER_AM35xx:
+		src = &omap34xx_rev3_0_dispc_feats;
+		break;
+
+	case OMAPDSS_VER_OMAP4430_ES1:
+	case OMAPDSS_VER_OMAP4430_ES2:
+	case OMAPDSS_VER_OMAP4:
 		src = &omap44xx_dispc_feats;
 		src = &omap44xx_dispc_feats;
-	} else {
+		break;
+
+	case OMAPDSS_VER_OMAP5:
+		src = &omap54xx_dispc_feats;
+		break;
+
+	default:
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
@@ -4074,29 +3599,32 @@ static int __init dispc_init_features(struct device *dev)
 	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;
 
 
-	r = dispc_init_features(&dispc.pdev->dev);
+	r = dispc_init_features(dispc.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");
@@ -4116,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();
@@ -4140,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));
@@ -4150,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;
 }
 }
 
 
@@ -4165,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;
 	}
 	}

+ 122 - 16
drivers/video/omap2/dss/dss.c

@@ -32,11 +32,10 @@
 #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>
 
 
-#include <plat/cpu.h>
-
 #include "dss.h"
 #include "dss.h"
 #include "dss_features.h"
 #include "dss_features.h"
 
 
@@ -78,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;
@@ -98,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)
@@ -153,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;
@@ -303,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;
@@ -374,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:
@@ -431,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) {
@@ -448,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;
@@ -461,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)
 {
 {
@@ -750,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,29 +877,45 @@ static const struct dss_features omap54xx_dss_feats __initconst = {
 	.dpi_select_source	=	&dss_dpi_select_source_omap5,
 	.dpi_select_source	=	&dss_dpi_select_source_omap5,
 };
 };
 
 
-static int __init dss_init_features(struct device *dev)
+static int __init dss_init_features(struct platform_device *pdev)
 {
 {
 	const struct dss_features *src;
 	const struct dss_features *src;
 	struct dss_features *dst;
 	struct dss_features *dst;
 
 
-	dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
+	dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
 	if (!dst) {
 	if (!dst) {
-		dev_err(dev, "Failed to allocate local DSS Features\n");
+		dev_err(&pdev->dev, "Failed to allocate local DSS Features\n");
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
-	if (cpu_is_omap24xx())
+	switch (omapdss_get_version()) {
+	case OMAPDSS_VER_OMAP24xx:
 		src = &omap24xx_dss_feats;
 		src = &omap24xx_dss_feats;
-	else if (cpu_is_omap3630())
-		src = &omap3630_dss_feats;
-	else if (cpu_is_omap34xx())
+		break;
+
+	case OMAPDSS_VER_OMAP34xx_ES1:
+	case OMAPDSS_VER_OMAP34xx_ES3:
+	case OMAPDSS_VER_AM35xx:
 		src = &omap34xx_dss_feats;
 		src = &omap34xx_dss_feats;
-	else if (cpu_is_omap44xx())
+		break;
+
+	case OMAPDSS_VER_OMAP3630:
+		src = &omap3630_dss_feats;
+		break;
+
+	case OMAPDSS_VER_OMAP4430_ES1:
+	case OMAPDSS_VER_OMAP4430_ES2:
+	case OMAPDSS_VER_OMAP4:
 		src = &omap44xx_dss_feats;
 		src = &omap44xx_dss_feats;
-	else if (soc_is_omap54xx())
+		break;
+
+	case OMAPDSS_VER_OMAP5:
 		src = &omap54xx_dss_feats;
 		src = &omap54xx_dss_feats;
-	else
+		break;
+
+	default:
 		return -ENODEV;
 		return -ENODEV;
+	}
 
 
 	memcpy(dst, src, sizeof(*dst));
 	memcpy(dst, src, sizeof(*dst));
 	dss.feat = dst;
 	dss.feat = dst;
@@ -835,7 +932,7 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
 
 
 	dss.pdev = pdev;
 	dss.pdev = pdev;
 
 
-	r = dss_init_features(&dss.pdev->dev);
+	r = dss_init_features(dss.pdev);
 	if (r)
 	if (r)
 		return r;
 		return r;
 
 
@@ -856,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 */
@@ -888,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,

+ 51 - 28
drivers/video/omap2/dss/dss_features.c

@@ -18,12 +18,12 @@
  */
  */
 
 
 #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>
 
 
 #include <video/omapdss.h>
 #include <video/omapdss.h>
-#include <plat/cpu.h>
 
 
 #include "dss.h"
 #include "dss.h"
 #include "dss_features.h"
 #include "dss_features.h"
@@ -430,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[] = {
@@ -446,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[] = {
@@ -462,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[] = {
@@ -478,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[] = {
@@ -821,14 +813,25 @@ 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
 
 
 };
 };
 
 
-void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data)
+void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data,
+		enum omapdss_version version)
 {
 {
-	if (cpu_is_omap44xx())
+	switch (version) {
+	case OMAPDSS_VER_OMAP4430_ES1:
+	case OMAPDSS_VER_OMAP4430_ES2:
+	case OMAPDSS_VER_OMAP4:
 		ip_data->ops = &omap4_hdmi_functions;
 		ip_data->ops = &omap4_hdmi_functions;
+		break;
+	default:
+		ip_data->ops = NULL;
+	}
+
+	WARN_ON(ip_data->ops == NULL);
 }
 }
 #endif
 #endif
 
 
@@ -837,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)
 {
 {
@@ -862,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)
 {
 {
@@ -929,29 +937,44 @@ bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type)
 	return omap_current_dss_features->supported_rotation_types & rot_type;
 	return omap_current_dss_features->supported_rotation_types & rot_type;
 }
 }
 
 
-void dss_features_init(void)
+void dss_features_init(enum omapdss_version version)
 {
 {
-	if (cpu_is_omap24xx())
+	switch (version) {
+	case OMAPDSS_VER_OMAP24xx:
 		omap_current_dss_features = &omap2_dss_features;
 		omap_current_dss_features = &omap2_dss_features;
-	else if (cpu_is_omap3630())
+		break;
+
+	case OMAPDSS_VER_OMAP34xx_ES1:
+	case OMAPDSS_VER_OMAP34xx_ES3:
+		omap_current_dss_features = &omap3430_dss_features;
+		break;
+
+	case OMAPDSS_VER_OMAP3630:
 		omap_current_dss_features = &omap3630_dss_features;
 		omap_current_dss_features = &omap3630_dss_features;
-	else if (cpu_is_omap34xx()) {
-		if (soc_is_am35xx()) {
-			omap_current_dss_features = &am35xx_dss_features;
-		} else {
-			omap_current_dss_features = &omap3430_dss_features;
-		}
-	}
-	else if (omap_rev() == OMAP4430_REV_ES1_0)
+		break;
+
+	case OMAPDSS_VER_OMAP4430_ES1:
 		omap_current_dss_features = &omap4430_es1_0_dss_features;
 		omap_current_dss_features = &omap4430_es1_0_dss_features;
-	else if (omap_rev() == OMAP4430_REV_ES2_0 ||
-		omap_rev() == OMAP4430_REV_ES2_1 ||
-		omap_rev() == OMAP4430_REV_ES2_2)
+		break;
+
+	case OMAPDSS_VER_OMAP4430_ES2:
 		omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;
 		omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;
-	else if (cpu_is_omap44xx())
+		break;
+
+	case OMAPDSS_VER_OMAP4:
 		omap_current_dss_features = &omap4_dss_features;
 		omap_current_dss_features = &omap4_dss_features;
-	else if (soc_is_omap54xx())
+		break;
+
+	case OMAPDSS_VER_OMAP5:
 		omap_current_dss_features = &omap5_dss_features;
 		omap_current_dss_features = &omap5_dss_features;
-	else
+		break;
+
+	case OMAPDSS_VER_AM35xx:
+		omap_current_dss_features = &am35xx_dss_features;
+		break;
+
+	default:
 		DSSWARN("Unsupported OMAP version");
 		DSSWARN("Unsupported OMAP version");
+		break;
+	}
 }
 }

+ 3 - 9
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);
@@ -123,8 +116,9 @@ bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type);
 
 
 bool dss_has_feature(enum dss_feat_id id);
 bool dss_has_feature(enum dss_feat_id id);
 void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
 void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
-void dss_features_init(void);
+void dss_features_init(enum omapdss_version version);
 #if defined(CONFIG_OMAP4_DSS_HDMI)
 #if defined(CONFIG_OMAP4_DSS_HDMI)
-void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data);
+void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data,
+		enum omapdss_version version);
 #endif
 #endif
 #endif
 #endif

+ 114 - 44
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)
@@ -333,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);
+	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);
@@ -355,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");
 
 
@@ -398,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)) {
 
 
@@ -500,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);
@@ -521,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;
@@ -548,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);
 
 
@@ -582,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;
 
 
@@ -600,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,
@@ -715,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;
@@ -737,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;
@@ -912,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;
 
 
@@ -970,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;
 	}
 	}
@@ -999,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;
@@ -1022,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;
 	}
 	}
 
 
@@ -1033,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);
 
 
@@ -1044,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)
@@ -1067,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

+ 16 - 32
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 <plat/vrfb.h>
-#include <plat/vram.h>
+#include <video/omapvrfb.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)))

+ 139 - 73
drivers/video/omap2/omapfb/omapfb-main.c

@@ -31,9 +31,7 @@
 #include <linux/omapfb.h>
 #include <linux/omapfb.h>
 
 
 #include <video/omapdss.h>
 #include <video/omapdss.h>
-#include <plat/cpu.h>
-#include <plat/vram.h>
-#include <plat/vrfb.h>
+#include <video/omapvrfb.h>
 
 
 #include "omapfb.h"
 #include "omapfb.h"
 
 
@@ -1259,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 &&
@@ -1284,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;
 
 
@@ -1336,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;
@@ -1388,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;
@@ -1403,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;
 
 
@@ -1532,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;
 
 
@@ -1611,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;
@@ -1626,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) {
@@ -1883,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)
@@ -2259,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) {
@@ -2294,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;
 	}
 	}
@@ -2372,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");
 
 
@@ -2390,28 +2438,28 @@ 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;
 	}
 	}
 
 
-	/* TODO : Replace cpu check with omap_has_vrfb once HAS_FEATURE
-	*	 available for OMAP2 and OMAP3
-	*/
-	if (def_vrfb && !cpu_is_omap24xx() && !cpu_is_omap34xx()) {
+	if (def_vrfb && !omap_vrfb_supported()) {
 		def_vrfb = 0;
 		def_vrfb = 0;
 		dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
 		dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
 				"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) {
@@ -2434,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;
@@ -2451,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) {
@@ -2510,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;
@@ -2525,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;
 }
 }
 
 

+ 5 - 1
drivers/video/omap2/omapfb/omapfb-sysfs.c

@@ -30,7 +30,7 @@
 #include <linux/omapfb.h>
 #include <linux/omapfb.h>
 
 
 #include <video/omapdss.h>
 #include <video/omapdss.h>
-#include <plat/vrfb.h>
+#include <video/omapvrfb.h>
 
 
 #include "omapfb.h"
 #include "omapfb.h"
 
 
@@ -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;
-}

+ 121 - 21
drivers/video/omap2/vrfb.c

@@ -26,9 +26,9 @@
 #include <linux/io.h>
 #include <linux/io.h>
 #include <linux/bitops.h>
 #include <linux/bitops.h>
 #include <linux/mutex.h>
 #include <linux/mutex.h>
+#include <linux/platform_device.h>
 
 
-#include <plat/vrfb.h>
-#include <plat/sdrc.h>
+#include <video/omapvrfb.h>
 
 
 #ifdef DEBUG
 #ifdef DEBUG
 #define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__)
 #define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__)
@@ -36,10 +36,10 @@
 #define DBG(format, ...)
 #define DBG(format, ...)
 #endif
 #endif
 
 
-#define SMS_ROT_VIRT_BASE(context, rot) \
-	(((context >= 4) ? 0xD0000000 : 0x70000000) \
-	 + (0x4000000 * (context)) \
-	 + (0x1000000 * (rot)))
+#define SMS_ROT_CONTROL(context)	(0x0 + 0x10 * context)
+#define SMS_ROT_SIZE(context)		(0x4 + 0x10 * context)
+#define SMS_ROT_PHYSICAL_BA(context)	(0x8 + 0x10 * context)
+#define SMS_ROT_VIRT_BASE(rot)		(0x1000000 * (rot))
 
 
 #define OMAP_VRFB_SIZE			(2048 * 2048 * 4)
 #define OMAP_VRFB_SIZE			(2048 * 2048 * 4)
 
 
@@ -53,10 +53,16 @@
 #define SMS_PW_OFFSET		4
 #define SMS_PW_OFFSET		4
 #define SMS_PS_OFFSET		0
 #define SMS_PS_OFFSET		0
 
 
-#define VRFB_NUM_CTXS 12
 /* bitmap of reserved contexts */
 /* bitmap of reserved contexts */
 static unsigned long ctx_map;
 static unsigned long ctx_map;
 
 
+struct vrfb_ctx {
+	u32 base;
+	u32 physical_ba;
+	u32 control;
+	u32 size;
+};
+
 static DEFINE_MUTEX(ctx_lock);
 static DEFINE_MUTEX(ctx_lock);
 
 
 /*
 /*
@@ -65,17 +71,34 @@ static DEFINE_MUTEX(ctx_lock);
  * we don't need locking, since no drivers will run until after the wake-up
  * we don't need locking, since no drivers will run until after the wake-up
  * has finished.
  * has finished.
  */
  */
-static struct {
-	u32 physical_ba;
-	u32 control;
-	u32 size;
-} vrfb_hw_context[VRFB_NUM_CTXS];
+
+static void __iomem *vrfb_base;
+
+static int num_ctxs;
+static struct vrfb_ctx *ctxs;
+
+static bool vrfb_loaded;
+
+static void omap2_sms_write_rot_control(u32 val, unsigned ctx)
+{
+	__raw_writel(val, vrfb_base + SMS_ROT_CONTROL(ctx));
+}
+
+static void omap2_sms_write_rot_size(u32 val, unsigned ctx)
+{
+	__raw_writel(val, vrfb_base + SMS_ROT_SIZE(ctx));
+}
+
+static void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx)
+{
+	__raw_writel(val, vrfb_base + SMS_ROT_PHYSICAL_BA(ctx));
+}
 
 
 static inline void restore_hw_context(int ctx)
 static inline void restore_hw_context(int ctx)
 {
 {
-	omap2_sms_write_rot_control(vrfb_hw_context[ctx].control, ctx);
-	omap2_sms_write_rot_size(vrfb_hw_context[ctx].size, ctx);
-	omap2_sms_write_rot_physical_ba(vrfb_hw_context[ctx].physical_ba, ctx);
+	omap2_sms_write_rot_control(ctxs[ctx].control, ctx);
+	omap2_sms_write_rot_size(ctxs[ctx].size, ctx);
+	omap2_sms_write_rot_physical_ba(ctxs[ctx].physical_ba, ctx);
 }
 }
 
 
 static u32 get_image_width_roundup(u16 width, u8 bytespp)
 static u32 get_image_width_roundup(u16 width, u8 bytespp)
@@ -196,9 +219,9 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
 	control |= VRFB_PAGE_WIDTH_EXP  << SMS_PW_OFFSET;
 	control |= VRFB_PAGE_WIDTH_EXP  << SMS_PW_OFFSET;
 	control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET;
 	control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET;
 
 
-	vrfb_hw_context[ctx].physical_ba = paddr;
-	vrfb_hw_context[ctx].size = size;
-	vrfb_hw_context[ctx].control = control;
+	ctxs[ctx].physical_ba = paddr;
+	ctxs[ctx].size = size;
+	ctxs[ctx].control = control;
 
 
 	omap2_sms_write_rot_physical_ba(paddr, ctx);
 	omap2_sms_write_rot_physical_ba(paddr, ctx);
 	omap2_sms_write_rot_size(size, ctx);
 	omap2_sms_write_rot_size(size, ctx);
@@ -274,11 +297,11 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
 
 
 	mutex_lock(&ctx_lock);
 	mutex_lock(&ctx_lock);
 
 
-	for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx)
+	for (ctx = 0; ctx < num_ctxs; ++ctx)
 		if ((ctx_map & (1 << ctx)) == 0)
 		if ((ctx_map & (1 << ctx)) == 0)
 			break;
 			break;
 
 
-	if (ctx == VRFB_NUM_CTXS) {
+	if (ctx == num_ctxs) {
 		pr_err("vrfb: no free contexts\n");
 		pr_err("vrfb: no free contexts\n");
 		r = -EBUSY;
 		r = -EBUSY;
 		goto out;
 		goto out;
@@ -293,7 +316,7 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
 	vrfb->context = ctx;
 	vrfb->context = ctx;
 
 
 	for (rot = 0; rot < 4; ++rot) {
 	for (rot = 0; rot < 4; ++rot) {
-		paddr = SMS_ROT_VIRT_BASE(ctx, rot);
+		paddr = ctxs[ctx].base + SMS_ROT_VIRT_BASE(rot);
 		if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
 		if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
 			pr_err("vrfb: failed to reserve VRFB "
 			pr_err("vrfb: failed to reserve VRFB "
 					"area for ctx %d, rotation %d\n",
 					"area for ctx %d, rotation %d\n",
@@ -314,3 +337,80 @@ out:
 	return r;
 	return r;
 }
 }
 EXPORT_SYMBOL(omap_vrfb_request_ctx);
 EXPORT_SYMBOL(omap_vrfb_request_ctx);
+
+bool omap_vrfb_supported(void)
+{
+	return vrfb_loaded;
+}
+EXPORT_SYMBOL(omap_vrfb_supported);
+
+static int __init vrfb_probe(struct platform_device *pdev)
+{
+	struct resource *mem;
+	int i;
+
+	/* first resource is the register res, the rest are vrfb contexts */
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "can't get vrfb base address\n");
+		return -EINVAL;
+	}
+
+	vrfb_base = devm_request_and_ioremap(&pdev->dev, mem);
+	if (!vrfb_base) {
+		dev_err(&pdev->dev, "can't ioremap vrfb memory\n");
+		return -ENOMEM;
+	}
+
+	num_ctxs = pdev->num_resources - 1;
+
+	ctxs = devm_kzalloc(&pdev->dev,
+			sizeof(struct vrfb_ctx) * num_ctxs,
+			GFP_KERNEL);
+
+	if (!ctxs)
+		return -ENOMEM;
+
+	for (i = 0; i < num_ctxs; ++i) {
+		mem = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
+		if (!mem) {
+			dev_err(&pdev->dev, "can't get vrfb ctx %d address\n",
+					i);
+			return -EINVAL;
+		}
+
+		ctxs[i].base = mem->start;
+	}
+
+	vrfb_loaded = true;
+
+	return 0;
+}
+
+static void __exit vrfb_remove(struct platform_device *pdev)
+{
+	vrfb_loaded = false;
+}
+
+static struct platform_driver vrfb_driver = {
+	.driver.name	= "omapvrfb",
+	.remove		= __exit_p(vrfb_remove),
+};
+
+static int __init vrfb_init(void)
+{
+	return platform_driver_probe(&vrfb_driver, &vrfb_probe);
+}
+
+static void __exit vrfb_exit(void)
+{
+	platform_driver_unregister(&vrfb_driver);
+}
+
+module_init(vrfb_init);
+module_exit(vrfb_exit);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
+MODULE_DESCRIPTION("OMAP VRFB");
+MODULE_LICENSE("GPL v2");

+ 95 - 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 {
@@ -314,6 +315,19 @@ int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel);
 int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel);
 int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel);
 void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel);
 void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel);
 
 
+enum omapdss_version {
+	OMAPDSS_VER_UNKNOWN = 0,
+	OMAPDSS_VER_OMAP24xx,
+	OMAPDSS_VER_OMAP34xx_ES1,	/* OMAP3430 ES1.0, 2.0 */
+	OMAPDSS_VER_OMAP34xx_ES3,	/* OMAP3430 ES3.0+ */
+	OMAPDSS_VER_OMAP3630,
+	OMAPDSS_VER_AM35xx,
+	OMAPDSS_VER_OMAP4430_ES1,	/* OMAP4430 ES1.0 */
+	OMAPDSS_VER_OMAP4430_ES2,	/* OMAP4430 ES2.0, 2.1, 2.2 */
+	OMAPDSS_VER_OMAP4,		/* All other OMAP4s */
+	OMAPDSS_VER_OMAP5,
+};
+
 /* Board specific data */
 /* Board specific data */
 struct omap_dss_board_info {
 struct omap_dss_board_info {
 	int (*get_context_loss_count)(struct device *dev);
 	int (*get_context_loss_count)(struct device *dev);
@@ -323,6 +337,7 @@ struct omap_dss_board_info {
 	int (*dsi_enable_pads)(int dsi_id, unsigned lane_mask);
 	int (*dsi_enable_pads)(int dsi_id, unsigned lane_mask);
 	void (*dsi_disable_pads)(int dsi_id, unsigned lane_mask);
 	void (*dsi_disable_pads)(int dsi_id, unsigned lane_mask);
 	int (*set_min_bus_tput)(struct device *dev, unsigned long r);
 	int (*set_min_bus_tput)(struct device *dev, unsigned long r);
+	enum omapdss_version version;
 };
 };
 
 
 /* Init with the board info */
 /* Init with the board info */
@@ -607,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;
@@ -672,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,
@@ -731,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 *);
 
 
@@ -740,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);
 
 
@@ -765,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)
@@ -826,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

+ 2 - 0
arch/arm/plat-omap/include/plat/vrfb.h → include/video/omapvrfb.h

@@ -36,6 +36,7 @@ struct vrfb {
 };
 };
 
 
 #ifdef CONFIG_OMAP2_VRFB
 #ifdef CONFIG_OMAP2_VRFB
+extern bool omap_vrfb_supported(void);
 extern int omap_vrfb_request_ctx(struct vrfb *vrfb);
 extern int omap_vrfb_request_ctx(struct vrfb *vrfb);
 extern void omap_vrfb_release_ctx(struct vrfb *vrfb);
 extern void omap_vrfb_release_ctx(struct vrfb *vrfb);
 extern void omap_vrfb_adjust_size(u16 *width, u16 *height,
 extern void omap_vrfb_adjust_size(u16 *width, u16 *height,
@@ -49,6 +50,7 @@ extern int omap_vrfb_map_angle(struct vrfb *vrfb, u16 height, u8 rot);
 extern void omap_vrfb_restore_context(void);
 extern void omap_vrfb_restore_context(void);
 
 
 #else
 #else
+static inline bool omap_vrfb_supported(void) { return false; }
 static inline int omap_vrfb_request_ctx(struct vrfb *vrfb) { return 0; }
 static inline int omap_vrfb_request_ctx(struct vrfb *vrfb) { return 0; }
 static inline void omap_vrfb_release_ctx(struct vrfb *vrfb) {}
 static inline void omap_vrfb_release_ctx(struct vrfb *vrfb) {}
 static inline void omap_vrfb_adjust_size(u16 *width, u16 *height,
 static inline void omap_vrfb_adjust_size(u16 *width, u16 *height,