Merge remote-tracking branch 'agreen/for-nicolas' into linaro-2.6.38
diff --git a/arch/arm/configs/omap4_defconfig b/arch/arm/configs/omap4_defconfig
new file mode 100644
index 0000000..1a0e375
--- /dev/null
+++ b/arch/arm/configs/omap4_defconfig
@@ -0,0 +1,315 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EXPERT=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_PERF_COUNTERS=y
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_OMAP=y
+CONFIG_OMAP_SMARTREFLEX=y
+CONFIG_OMAP_SMARTREFLEX_CLASS3=y
+CONFIG_OMAP_MUX_DEBUG=y
+CONFIG_OMAP_MBOX_FWK=y
+# CONFIG_ARCH_OMAP2 is not set
+# CONFIG_MACH_OMAP3_BEAGLE is not set
+# CONFIG_MACH_DEVKIT8000 is not set
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OMAP3530_LV_SOM is not set
+# CONFIG_MACH_OMAP3_TORPEDO is not set
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP3EVM is not set
+# CONFIG_MACH_OMAP3517EVM is not set
+# CONFIG_MACH_OMAP3_PANDORA is not set
+# CONFIG_MACH_OMAP3_TOUCHBOOK is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_NOKIA_RM680 is not set
+# CONFIG_MACH_NOKIA_RX51 is not set
+# CONFIG_MACH_OMAP_ZOOM2 is not set
+# CONFIG_MACH_OMAP_ZOOM3 is not set
+# CONFIG_MACH_CM_T35 is not set
+# CONFIG_MACH_CM_T3517 is not set
+# CONFIG_MACH_IGEP0020 is not set
+# CONFIG_MACH_IGEP0030 is not set
+# CONFIG_MACH_SBC3530 is not set
+# CONFIG_MACH_OMAP_3630SDP is not set
+CONFIG_ARM_THUMBEE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_HIGHMEM=y
+CONFIG_LEDS=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyO2,115200"
+CONFIG_KEXEC=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_FPE_NWFPE=y
+CONFIG_BINFMT_MISC=y
+CONFIG_PM_DEBUG=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_CFG80211=y
+CONFIG_CFG80211_REG_DEBUG=y
+CONFIG_CFG80211_DEBUGFS=y
+CONFIG_LIB80211=y
+CONFIG_MAC80211=y
+CONFIG_MAC80211_MESH=y
+CONFIG_MAC80211_DEBUGFS=y
+CONFIG_MAC80211_DEBUG_MENU=y
+CONFIG_MAC80211_VERBOSE_DEBUG=y
+CONFIG_RFKILL=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_OOPS=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_ONENAND=y
+CONFIG_MTD_ONENAND_VERIFY_WRITE=y
+CONFIG_MTD_ONENAND_OMAP2=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_MISC_DEVICES=y
+CONFIG_TI_ST=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_MD=y
+CONFIG_NETDEVICES=y
+CONFIG_SMSC_PHY=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMC91X=y
+CONFIG_SMSC911X=y
+CONFIG_KS8851=y
+CONFIG_KS8851_MLL=y
+# CONFIG_NETDEV_10000 is not set
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_LIBERTAS_DEBUG=y
+CONFIG_WL12XX_MENU=m
+CONFIG_WL12XX=m
+CONFIG_WL12XX_HT=y
+CONFIG_WL12XX_SDIO=m
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_INPUT_JOYDEV=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_OMAP4=y
+CONFIG_KEYBOARD_TWL4030=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_TWL4030_PWRBUTTON=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_HW_RANDOM=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_SPI=y
+CONFIG_SPI_OMAP24XX=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_TWL4030=y
+CONFIG_W1=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_WATCHDOG=y
+CONFIG_OMAP_WATCHDOG=y
+CONFIG_TWL4030_WATCHDOG=y
+CONFIG_REGULATOR_DUMMY=y
+CONFIG_REGULATOR_TWL4030=y
+CONFIG_REGULATOR_TPS65023=y
+CONFIG_REGULATOR_TPS6507X=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_VIDEO_DEV=y
+# CONFIG_MEDIA_TUNER_SIMPLE is not set
+# CONFIG_MEDIA_TUNER_TDA8290 is not set
+# CONFIG_MEDIA_TUNER_TDA827X is not set
+# CONFIG_MEDIA_TUNER_TDA18271 is not set
+# CONFIG_MEDIA_TUNER_TDA9887 is not set
+# CONFIG_MEDIA_TUNER_TEA5761 is not set
+CONFIG_VIDEO_OMAP2_VOUT=y
+CONFIG_RADIO_WL1273=m
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_OMAP2_VRAM_SIZE=32
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_FAKE_VSYNC=y
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_NUM_FBS=2
+CONFIG_PANEL_GENERIC_DPI=y
+CONFIG_PANEL_TAAL=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_DISPLAY_SUPPORT=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+CONFIG_SND_DEBUG_VERBOSE=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_SDP4430=y
+CONFIG_SND_OMAP_SOC_OMAP4_HDMI=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG_WHITELIST is not set
+CONFIG_USB_MON=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_OMAP2PLUS=y
+CONFIG_USB_MUSB_OTG=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_WDM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_LIBUSUAL=y
+CONFIG_USB_TEST=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_TWL4030_USB=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_SDIO_UART=y
+CONFIG_MMC_OMAP=y
+CONFIG_MMC_OMAP_HS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_TWL4030=y
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+CONFIG_HWSPINLOCK=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_QUOTA=y
+CONFIG_QFMT_V2=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RUBIN=y
+CONFIG_UBIFS_FS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SECURITY=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRC_CCITT=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 56702c5..7e4bc49 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -311,11 +311,17 @@
 	.id		= -1,
 };
 
+static struct platform_device sdp4430_hdmi_audio_device = {
+	.name		= "hdmi-audio-dai",
+	.id		= -1,
+};
+
 static struct platform_device *sdp4430_devices[] __initdata = {
 	&sdp4430_lcd_device,
 	&sdp4430_gpio_keys_device,
 	&sdp4430_leds_gpio,
 	&sdp4430_leds_pwm,
+	&sdp4430_hdmi_audio_device,
 };
 
 static struct omap_lcd_config sdp4430_lcd_config __initdata = {
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 920b7ba..a0c7ba8 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -57,16 +57,6 @@
 #define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */
 #define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
 
-/* wl127x BT, FM, GPS connectivity chip */
-static int wl1271_gpios[] = {46, -1, -1};
-static struct platform_device wl1271_device = {
-	.name	= "kim",
-	.id	= -1,
-	.dev	= {
-		.platform_data	= &wl1271_gpios,
-	},
-};
-
 static struct gpio_led gpio_leds[] = {
 	{
 		.name			= "pandaboard::status1",
@@ -93,11 +83,60 @@
 	},
 };
 
+static struct platform_device omap4panda_hdmi_audio_device = {
+	.name		= "hdmi-audio-dai",
+	.id		= -1,
+};
+
 static struct platform_device *panda_devices[] __initdata = {
 	&leds_gpio,
-	&wl1271_device,
+	&omap4panda_hdmi_audio_device,
 };
 
+/* Display DVI */
+#define PANDA_DVI_TFP410_POWER_DOWN_GPIO	0
+
+static int panda_enable_dvi(struct omap_dss_device *dssdev)
+{
+	gpio_set_value(dssdev->reset_gpio, 1);
+	return 0;
+}
+
+static void panda_disable_dvi(struct omap_dss_device *dssdev)
+{
+	gpio_set_value(dssdev->reset_gpio, 0);
+}
+
+/* Using generic display panel */
+static struct panel_generic_dpi_data dvi_panel = {
+	.name			= "generic",
+	.platform_enable	= panda_enable_dvi,
+	.platform_disable	= panda_disable_dvi,
+};
+
+struct omap_dss_device panda_dvi_device = {
+	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.name			= "dvi",
+	.driver_name		= "generic_dpi_panel",
+	.data			= &dvi_panel,
+	.phy.dpi.data_lines	= 24,
+	.reset_gpio		= PANDA_DVI_TFP410_POWER_DOWN_GPIO,
+	.channel		= OMAP_DSS_CHANNEL_LCD2,
+};
+
+int __init panda_dvi_init(void)
+{
+	int r;
+
+	/* Requesting TFP410 DVI GPIO and disabling it, at bootup */
+	r = gpio_request_one(panda_dvi_device.reset_gpio,
+				GPIOF_OUT_INIT_LOW, "DVI PD");
+	if (r)
+		pr_err("Failed to get DVI powerdown GPIO\n");
+
+	return r;
+}
+
 static void __init omap4_panda_init_early(void)
 {
 	omap2_init_common_infrastructure();
@@ -522,6 +561,19 @@
 	OMAP4_MUX(DPM_EMU18, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
 	/* dispc2_data0 */
 	OMAP4_MUX(DPM_EMU19, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* WLAN IRQ - GPIO 53 */
+	OMAP4_MUX(GPMC_NCS3, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
+	/* WLAN POWER ENABLE - GPIO 43 */
+	OMAP4_MUX(GPMC_A19, OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT),
+	/* WLAN SDIO: MMC5 CMD */
+	OMAP4_MUX(SDMMC5_CMD, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	/* WLAN SDIO: MMC5 CLK */
+	OMAP4_MUX(SDMMC5_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	/* WLAN SDIO: MMC5 DAT[0-3] */
+	OMAP4_MUX(SDMMC5_DAT0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP4_MUX(SDMMC5_DAT1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP4_MUX(SDMMC5_DAT2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP4_MUX(SDMMC5_DAT3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
 
@@ -696,13 +748,15 @@
 
 static struct omap_dss_device *omap4_panda_dss_devices[] = {
 	&omap4_panda_dvi_device,
+#ifdef CONFIG_OMAP4_DSS_HDMI
 	&omap4_panda_hdmi_device,
+#endif
 };
 
 static struct omap_dss_board_info omap4_panda_dss_data = {
 	.num_devices	= ARRAY_SIZE(omap4_panda_dss_devices),
 	.devices	= omap4_panda_dss_devices,
-	.default_device	= &omap4_panda_dvi_device,
+	.default_device	= &omap4_panda_hdmi_device,
 };
 
 void omap4_panda_display_init(void)
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index cbd6b35..03b5b78 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -30,6 +30,7 @@
 #include <mach/gpio.h>
 #include <plat/mmc.h>
 #include <plat/dma.h>
+#include <plat/gpu.h>
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
 #include <plat/omap4-keypad.h>
@@ -735,6 +736,63 @@
 static inline void omap_init_vout(void) {}
 #endif
 
+static struct omap_device_pm_latency omap_gpu_latency[] = {
+	[0] = {
+		.deactivate_func	= omap_device_idle_hwmods,
+		.activate_func		= omap_device_enable_hwmods,
+		.flags			= OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	},
+};
+
+static struct platform_device omap_omaplfb_device = {
+	.name		= "omaplfb",
+	.id		= -1,
+};
+
+
+static void omap_init_gpu(void)
+{
+	struct omap_hwmod *oh;
+	struct omap_device *od;
+	int max_omap_gpu_hwmod_name_len = 16;
+	char oh_name[max_omap_gpu_hwmod_name_len];
+	int l;
+	struct gpu_platform_data *pdata;
+	char *name = "pvrsrvkm";
+
+	l = snprintf(oh_name, max_omap_gpu_hwmod_name_len,
+		     "gpu");
+	WARN(l >= max_omap_gpu_hwmod_name_len,
+		"String buffer overflow in GPU device setup\n");
+
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+
+		pr_err("omap_init_gpu: Could not look up %s\n", oh_name);
+		return;
+	}
+
+	pdata = kzalloc(sizeof(struct gpu_platform_data),
+					GFP_KERNEL);
+	if (!pdata) {
+		pr_err("omap_init_gpu: Platform data memory allocation failed\n");
+		return;
+	}
+
+	pdata->device_enable = omap_device_enable;
+	pdata->device_idle = omap_device_idle;
+	pdata->device_shutdown = omap_device_shutdown;
+
+	od = omap_device_build(name, 0, oh, pdata,
+			     sizeof(struct gpu_platform_data),
+			     omap_gpu_latency, ARRAY_SIZE(omap_gpu_latency), 0);
+	WARN(IS_ERR(od), "Could not build omap_device for %s %s\n",
+	     name, oh_name);
+
+	kfree(pdata);
+	platform_device_register(&omap_omaplfb_device);
+}
+
 /*-------------------------------------------------------------------------*/
 
 static int __init omap2_init_devices(void)
@@ -753,6 +811,7 @@
 	omap_init_sham();
 	omap_init_aes();
 	omap_init_vout();
+	omap_init_gpu();
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index e46b430..8887a5e 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -141,14 +141,14 @@
 	dev_type = (prod_id >> 16) & 0x0f;
 	omap_get_die_id(&odi);
 
-	pr_debug("OMAP_TAP_IDCODE 0x%08x REV %i HAWKEYE 0x%04x MANF %03x\n",
+	pr_info("OMAP_TAP_IDCODE 0x%08x REV %i HAWKEYE 0x%04x MANF %03x\n",
 		 idcode, rev, hawkeye, (idcode >> 1) & 0x7ff);
-	pr_debug("OMAP_TAP_DIE_ID_0: 0x%08x\n", odi.id_0);
-	pr_debug("OMAP_TAP_DIE_ID_1: 0x%08x DEV_REV: %i\n",
+	pr_info("OMAP_TAP_DIE_ID_0: 0x%08x\n", odi.id_0);
+	pr_info("OMAP_TAP_DIE_ID_1: 0x%08x DEV_REV: %i\n",
 		 odi.id_1, (odi.id_1 >> 28) & 0xf);
-	pr_debug("OMAP_TAP_DIE_ID_2: 0x%08x\n", odi.id_2);
-	pr_debug("OMAP_TAP_DIE_ID_3: 0x%08x\n", odi.id_3);
-	pr_debug("OMAP_TAP_PROD_ID_0: 0x%08x DEV_TYPE: %i\n",
+	pr_info("OMAP_TAP_DIE_ID_2: 0x%08x\n", odi.id_2);
+	pr_info("OMAP_TAP_DIE_ID_3: 0x%08x\n", odi.id_3);
+	pr_info("OMAP_TAP_PROD_ID_0: 0x%08x DEV_TYPE: %i\n",
 		 prod_id, dev_type);
 
 	/* Check hawkeye ids */
@@ -333,6 +333,14 @@
 	u32 idcode;
 	u16 hawkeye;
 	u8 rev;
+	struct omap_die_id odi;
+
+	omap_get_die_id(&odi);
+
+	pr_info("OMAP_TAP_DIE_ID_0: 0x%08x\n", odi.id_0);
+	pr_info("OMAP_TAP_DIE_ID_1: 0x%08x\n", odi.id_1);
+	pr_info("OMAP_TAP_DIE_ID_2: 0x%08x\n", odi.id_2);
+	pr_info("OMAP_TAP_DIE_ID_3: 0x%08x\n", odi.id_3);
 
 	/*
 	 * The IC rev detection is done with hawkeye and rev.
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index ab73878..4edb3ec 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -22,6 +22,7 @@
 #include <plat/dmtimer.h>
 #include <plat/l3_2xxx.h>
 #include <plat/l4_2xxx.h>
+#include <plat/mmc.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -54,6 +55,7 @@
 static struct omap_hwmod omap2420_dma_system_hwmod;
 static struct omap_hwmod omap2420_mcspi1_hwmod;
 static struct omap_hwmod omap2420_mcspi2_hwmod;
+static struct omap_hwmod omap2420_mmc_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap2420_l3_main__l4_core = {
@@ -156,6 +158,24 @@
 	.user	= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* L4 CORE -> MMC interface */
+static struct omap_hwmod_addr_space omap2420_mmc_addr_space[] = {
+	{
+		.pa_start	= 0x4809c000,
+		.pa_end		= 0x4809c07f,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2420_l4_core__mmc = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_mmc_hwmod,
+	.clk		= "mmc_ick",
+	.addr		= omap2420_mmc_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2420_mmc_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* L4 CORE -> UART1 interface */
 static struct omap_hwmod_addr_space omap2420_uart1_addr_space[] = {
 	{
@@ -257,6 +277,7 @@
 /* Master interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap2420_l4_core_masters[] = {
 	&omap2420_l4_core__l4_wkup,
+	&omap2420_l4_core__mmc,
 	&omap2_l4_core__uart1,
 	&omap2_l4_core__uart2,
 	&omap2_l4_core__uart3,
@@ -1919,6 +1940,17 @@
 	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
 				SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
 				SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+        .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+/* MMC/SD/SDIO common */
+
+static struct omap_hwmod_class_sysconfig mmc_sysc = {
+	.rev_offs	= 0x3c,
+	.sysc_offs	= 0x64,
+	.syss_offs	= 0x68,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
 	.sysc_fields    = &omap_hwmod_sysc_type1,
 };
@@ -2139,6 +2171,54 @@
 	},
 	.slaves		= omap2420_mcbsp2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap2420_mcbsp2_slaves),
+        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+
+static struct omap_hwmod_class mmc_class = {
+	.name = "mmc",
+	.sysc = &mmc_sysc,
+};
+
+/* MMC/SD/SDIO1 */
+
+static struct mmc_dev_attr mmc_dev_attr = {
+	.flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
+};
+
+static struct omap_hwmod_irq_info mmc_mpu_irqs[] = {
+	{ .irq = 83 },
+};
+
+static struct omap_hwmod_dma_info mmc_sdma_reqs[] = {
+	{ .name = "tx",	.dma_req = 61 }, /* DMA_MMC_TX */
+	{ .name = "rx",	.dma_req = 62 }, /* DMA_MMC_RX */
+};
+
+static struct omap_hwmod_ocp_if *omap2420_mmc_slaves[] = {
+	&omap2420_l4_core__mmc,
+};
+
+static struct omap_hwmod omap2420_mmc_hwmod = {
+	.name		= "mmc_hwmod",
+	.mpu_irqs	= mmc_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(mmc_mpu_irqs),
+	.sdma_reqs	= mmc_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(mmc_sdma_reqs),
+	.main_clk	= "mmc_fck",
+	.prcm		= {
+	.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit  = OMAP2420_EN_MMC_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP2420_ST_MMC_SHIFT,
+		},
+	},
+	.slaves		= omap2420_mmc_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_mmc_slaves),
+	.class		= &mmc_class,
+	.dev_attr	= &mmc_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
@@ -2163,6 +2243,7 @@
 	&omap2420_timer12_hwmod,
 
 	&omap2420_wd_timer2_hwmod,
+	&omap2420_mmc_hwmod,
 	&omap2420_uart1_hwmod,
 	&omap2420_uart2_hwmod,
 	&omap2420_uart3_hwmod,
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index c5b6720..750ae60 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -53,6 +53,7 @@
 static struct omap_hwmod omap44xx_hsi_hwmod;
 static struct omap_hwmod omap44xx_ipu_hwmod;
 static struct omap_hwmod omap44xx_iss_hwmod;
+static struct omap_hwmod omap44xx_gpu_hwmod;
 static struct omap_hwmod omap44xx_iva_hwmod;
 static struct omap_hwmod omap44xx_l3_instr_hwmod;
 static struct omap_hwmod omap44xx_l3_main_1_hwmod;
@@ -322,14 +323,21 @@
 /* hsi -> l3_main_2 */
 static struct omap_hwmod_ocp_if omap44xx_hsi__l3_main_2 = {
 	.master		= &omap44xx_hsi_hwmod,
+        .slave          = &omap44xx_l3_main_2_hwmod,
+        .clk            = "l3_div_ck",
+        .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+/* gpu -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_gpu__l3_main_2 = {
+	.master		= &omap44xx_gpu_hwmod,
 	.slave		= &omap44xx_l3_main_2_hwmod,
 	.clk		= "l3_div_ck",
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* ipu -> l3_main_2 */
-static struct omap_hwmod_ocp_if omap44xx_ipu__l3_main_2 = {
-	.master		= &omap44xx_ipu_hwmod,
+/* iva -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_iva__l3_main_2 = {
+	.master		= &omap44xx_iva_hwmod,
 	.slave		= &omap44xx_l3_main_2_hwmod,
 	.clk		= "l3_div_ck",
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
@@ -343,9 +351,9 @@
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* iva -> l3_main_2 */
-static struct omap_hwmod_ocp_if omap44xx_iva__l3_main_2 = {
-	.master		= &omap44xx_iva_hwmod,
+/* ipu -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_ipu__l3_main_2 = {
+	.master		= &omap44xx_ipu_hwmod,
 	.slave		= &omap44xx_l3_main_2_hwmod,
 	.clk		= "l3_div_ck",
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
@@ -393,6 +401,7 @@
 	&omap44xx_iss__l3_main_2,
 	&omap44xx_iva__l3_main_2,
 	&omap44xx_l3_main_1__l3_main_2,
+	&omap44xx_gpu__l3_main_2,
 	&omap44xx_l4_cfg__l3_main_2,
 	&omap44xx_usb_otg_hs__l3_main_2,
 };
@@ -630,7 +639,6 @@
  *  elm
  *  emif1
  *  emif2
- *  fdif
  *  gpmc
  *  gpu
  *  hdq1w
@@ -2070,6 +2078,43 @@
 	{
 		.pa_start	= 0x4a058000,
 		.pa_end		= 0x4a05bfff,
+		.flags          = ADDR_TYPE_RT
+	}
+};
+
+/*
+ * 'gpu' class
+ * 2d/3d graphics accelerator
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_gpu_sysc = {
+	.rev_offs	= 0xfe00,
+	.sysc_offs	= 0xfe10,
+	.sysc_flags	= (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_gpu_hwmod_class = {
+	.name = "gpu",
+	.sysc = &omap44xx_gpu_sysc,
+};
+
+/* gpu */
+static struct omap_hwmod_irq_info omap44xx_gpu_irqs[] = {
+	{ .irq = 21 + OMAP44XX_IRQ_GIC_START },
+};
+
+/* gpu master ports */
+static struct omap_hwmod_ocp_if *omap44xx_gpu_masters[] = {
+	&omap44xx_gpu__l3_main_2,
+};
+
+static struct omap_hwmod_addr_space omap44xx_gpu_addrs[] = {
+	{
+		.pa_start	= 0x56000000,
+		.pa_end		= 0x5600ffff,
 		.flags		= ADDR_TYPE_RT
 	},
 };
@@ -2104,6 +2149,41 @@
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_hsi_slaves),
 	.masters	= omap44xx_hsi_masters,
 	.masters_cnt	= ARRAY_SIZE(omap44xx_hsi_masters),
+        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+
+/* l3_main_2 -> gpu */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__gpu = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_gpu_hwmod,
+	.clk		= "l3_div_ck",
+	.addr		= omap44xx_gpu_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_gpu_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* gpu slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_gpu_slaves[] = {
+	&omap44xx_l3_main_2__gpu,
+};
+
+static struct omap_hwmod omap44xx_gpu_hwmod = {
+	.name		= "gpu",
+	.class		= &omap44xx_gpu_hwmod_class,
+	.mpu_irqs	= omap44xx_gpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpu_irqs),
+	.main_clk	= "gpu_fck",
+	.vdd_name	= "core",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_GFX_GFX_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_gpu_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpu_slaves),
+	.masters	= omap44xx_gpu_masters,
+	.masters_cnt	= ARRAY_SIZE(omap44xx_gpu_masters),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
@@ -5100,6 +5180,9 @@
 	/* hsi class */
 /*	&omap44xx_hsi_hwmod, */
 
+	/* gpu class */
+	&omap44xx_gpu_hwmod,
+
 	/* i2c class */
 	&omap44xx_i2c1_hwmod,
 	&omap44xx_i2c2_hwmod,
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 283f455..87a0eed 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -72,7 +72,7 @@
 
 config OMAP_RESET_CLOCKS
 	bool "Reset unused clocks during boot"
-	depends on ARCH_OMAP
+	depends on ARCH_OMAP && BROKEN
 	help
 	  Say Y if you want to reset unused clocks during boot.
 	  This option saves power, but assumes all drivers are
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index 7d9f815..aa1f677 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -16,6 +16,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/memblock.h>
+#include <linux/err.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
diff --git a/arch/arm/plat-omap/include/plat/display.h b/arch/arm/plat-omap/include/plat/display.h
index 5e04ddc..2cba3d3 100644
--- a/arch/arm/plat-omap/include/plat/display.h
+++ b/arch/arm/plat-omap/include/plat/display.h
@@ -23,6 +23,7 @@
 #include <linux/list.h>
 #include <linux/kobject.h>
 #include <linux/device.h>
+#include <linux/notifier.h>
 #include <linux/platform_device.h>
 #include <asm/atomic.h>
 
@@ -459,6 +460,7 @@
 	struct omap_overlay_manager *manager;
 
 	enum omap_dss_display_state state;
+	struct blocking_notifier_head notifier;
 
 	/* platform specific  */
 	int (*platform_enable)(struct omap_dss_device *dssdev);
@@ -532,6 +534,18 @@
 int omap_dss_start_device(struct omap_dss_device *dssdev);
 void omap_dss_stop_device(struct omap_dss_device *dssdev);
 
+/* the event id of the event that occurred is passed in as the second arg
+ * to the notifier function, and the dssdev is passed as the third.
+ */
+enum omap_dss_event {
+	OMAP_DSS_SIZE_CHANGE
+	/* possibly add additional events, like hot-plug connect/disconnect */
+};
+
+void omap_dss_notify(struct omap_dss_device *dssdev, enum omap_dss_event evt);
+void omap_dss_add_notify(struct omap_dss_device *dssdev, struct notifier_block *nb);
+void omap_dss_remove_notify(struct omap_dss_device *dssdev, struct notifier_block *nb);
+
 int omap_dss_get_num_overlay_managers(void);
 struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
 
diff --git a/arch/arm/plat-omap/include/plat/gpu.h b/arch/arm/plat-omap/include/plat/gpu.h
new file mode 100644
index 0000000..70dcc92
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/gpu.h
@@ -0,0 +1,33 @@
+/*
+ *  arch/arm/plat-omap/include/plat/gpu.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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_GPU_H
+#define OMAP_GPU_H
+
+#include <plat/omap-pm.h>
+#include <linux/platform_device.h>
+
+struct gpu_platform_data {
+	void (*set_min_bus_tput)(struct device *dev, u8 agent_id,
+						unsigned long r);
+	int (*device_enable) (struct platform_device *pdev);
+	int (*device_shutdown) (struct platform_device *pdev);
+	int (*device_idle) (struct platform_device *pdev);
+};
+
+#endif
diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h
index f38fef9..cc0ad22 100644
--- a/arch/arm/plat-omap/include/plat/mmc.h
+++ b/arch/arm/plat-omap/include/plat/mmc.h
@@ -31,6 +31,7 @@
 
 #define OMAP_MMC_MAX_SLOTS	2
 
+/* omap_hwmod integration data */
 #define OMAP_HSMMC_SUPPORTS_DUAL_VOLT	BIT(1)
 
 struct omap_mmc_dev_attr {
diff --git a/arch/arm/plat-omap/include/plat/omap44xx.h b/arch/arm/plat-omap/include/plat/omap44xx.h
index b127a16..ef2c3b8 100644
--- a/arch/arm/plat-omap/include/plat/omap44xx.h
+++ b/arch/arm/plat-omap/include/plat/omap44xx.h
@@ -45,6 +45,7 @@
 #define OMAP44XX_WKUPGEN_BASE		0x48281000
 #define OMAP44XX_MCPDM_BASE		0x40132000
 #define OMAP44XX_MCPDM_L3_BASE		0x49032000
+#define OMAP44XX_DSS_HDMI_L3_BASE	0x58006000
 
 #define OMAP44XX_MAILBOX_BASE		(L4_44XX_BASE + 0xF4000)
 #define OMAP44XX_HSUSB_OTG_BASE		(L4_44XX_BASE + 0xAB000)
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 1adea9c..5bcbca8 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -551,6 +551,8 @@
 
 int __init omap_hwmod_setup_one(const char *name);
 
+int __init omap_hwmod_setup_one(const char *name);
+
 int omap_hwmod_enable(struct omap_hwmod *oh);
 int _omap_hwmod_enable(struct omap_hwmod *oh);
 int omap_hwmod_idle(struct omap_hwmod *oh);
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 271835a..7301d5e 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -262,15 +262,12 @@
 
 void drm_exit(struct drm_driver *driver)
 {
-	struct drm_device *dev, *tmp;
 	DRM_DEBUG("\n");
 
-	if (driver->driver_features & DRIVER_MODESET) {
-		pci_unregister_driver(&driver->pci_driver);
-	} else {
-		list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
-			drm_put_dev(dev);
-	}
+	if (driver->driver_features & DRIVER_USE_PLATFORM_DEVICE)
+		drm_platform_exit(driver);
+	else
+		drm_pci_exit(driver);
 
 	DRM_INFO("Module unloaded\n");
 }
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c
index be9a9c0..73bf493 100644
--- a/drivers/gpu/drm/drm_info.c
+++ b/drivers/gpu/drm/drm_info.c
@@ -54,11 +54,11 @@
 	if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) {
 		if (master->unique) {
 			seq_printf(m, "%s %s %s\n",
-					dev->driver->platform_device->name,
+					dev->platformdev->name,
 					dev_name(dev->dev), master->unique);
 		} else {
 			seq_printf(m, "%s\n",
-				dev->driver->platform_device->name);
+				dev->platformdev->name);
 		}
 	} else {
 		if (master->unique) {
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
index f5bd9e5..6f7e41b 100644
--- a/drivers/gpu/drm/drm_pci.c
+++ b/drivers/gpu/drm/drm_pci.c
@@ -263,6 +263,19 @@
 	return 0;
 }
 
+void drm_pci_exit(struct drm_driver *driver)
+{
+	struct drm_device *dev, *tmp;
+
+	if (driver->driver_features & DRIVER_MODESET) {
+		pci_unregister_driver(&driver->pci_driver);
+	} else {
+		list_for_each_entry_safe(dev, tmp, &driver->device_list,
+				driver_item)
+		drm_put_dev(dev);
+	}
+}
+
 #else
 
 int drm_pci_init(struct drm_driver *driver)
@@ -270,5 +283,9 @@
 	return -1;
 }
 
+void drm_pci_exit(struct drm_driver *driver)
+{
+}
+
 #endif
 /*@}*/
diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c
index 92d1d0f..8f68a54 100644
--- a/drivers/gpu/drm/drm_platform.c
+++ b/drivers/gpu/drm/drm_platform.c
@@ -123,5 +123,10 @@
 
 int drm_platform_init(struct drm_driver *driver)
 {
-	return drm_get_platform_dev(driver->platform_device, driver);
+	return platform_driver_register(&driver->platform_driver);
+}
+
+void drm_platform_exit(struct drm_driver *driver)
+{
+	platform_driver_unregister(&driver->platform_driver);
 }
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c
index 029a4ba..de08878 100644
--- a/drivers/media/video/omap/omap_vout.c
+++ b/drivers/media/video/omap/omap_vout.c
@@ -125,8 +125,8 @@
 MODULE_PARM_DESC(vid2_static_vrfb_alloc,
 	"Static allocation of the VRFB buffer for video2 device");
 
-module_param(debug, bool, S_IRUGO);
-MODULE_PARM_DESC(debug, "Debug level (0-1)");
+module_param(debug, int, S_IRUGO);
+MODULE_PARM_DESC(debug, "Debug level");
 
 /* list of image formats supported by OMAP2 video pipelines */
 const static struct v4l2_fmtdesc omap_formats[] = {
@@ -2235,6 +2235,8 @@
 	mutex_init(&vout->lock);
 
 	vfd->minor = -1;
+	vfd->debug = debug;
+
 	return 0;
 
 }
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 9050dd9..8ceb6a0 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -112,8 +112,8 @@
 				  CFG_RX_CTL_EN | CFG_RX_BCN_EN |     \
 				  CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN)
 
-#define WL1271_FW_NAME "wl1271-fw.bin"
-#define WL1271_NVS_NAME "wl1271-nvs.bin"
+#define WL1271_FW_NAME "ti-connectivity/wl1271-fw.bin"
+#define WL1271_NVS_NAME "ti-connectivity/wl1271-nvs.bin"
 
 #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
 #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index a6d3f2f..c291513 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -555,7 +555,6 @@
 		musb->ep0_stage = MUSB_EP0_START;
 		musb->xceiv->state = OTG_STATE_A_IDLE;
 		MUSB_HST_MODE(musb);
-		musb_platform_set_vbus(musb, 1);
 
 		handled = IRQ_HANDLED;
 	}
@@ -848,12 +847,16 @@
 				DBG(1, "HNP: in %s, %d msec timeout\n",
 						otg_state_string(musb),
 						TA_WAIT_BCON(musb));
+#ifdef  CONFIG_USB_MUSB_OTG
 				mod_timer(&musb->otg_timer, jiffies
 					+ msecs_to_jiffies(TA_WAIT_BCON(musb)));
+#endif
 				break;
 			case OTG_STATE_A_PERIPHERAL:
 				musb->ignore_disconnect = 0;
+#ifdef  CONFIG_USB_MUSB_OTG
 				del_timer(&musb->otg_timer);
+#endif
 				musb_g_reset(musb);
 				break;
 			case OTG_STATE_B_WAIT_ACON:
@@ -1729,6 +1732,8 @@
 	unsigned long	flags;
 	int		status;
 
+	pm_runtime_get_sync(musb->controller);
+
 	spin_lock_irqsave(&musb->lock, flags);
 	if (sysfs_streq(buf, "host"))
 		status = musb_platform_set_mode(musb, MUSB_HOST);
@@ -1740,6 +1745,8 @@
 		status = -EINVAL;
 	spin_unlock_irqrestore(&musb->lock, flags);
 
+	pm_runtime_put_sync(musb->controller);
+
 	return (status == 0) ? n : status;
 }
 static DEVICE_ATTR(mode, 0644, musb_mode_show, musb_mode_store);
@@ -1837,6 +1844,9 @@
 	struct musb *musb = container_of(data, struct musb, irq_work);
 	static int old_state;
 
+	if(musb->xceiv->state = OTG_STATE_A_IDLE)
+		musb_platform_set_vbus(musb, 1);
+
 	if (musb->xceiv->state != old_state) {
 		old_state = musb->xceiv->state;
 		sysfs_notify(&musb->controller->kobj, NULL, "mode");
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 25cb8b0..50d2694 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -259,8 +259,10 @@
 	case USB_EVENT_VBUS:
 		DBG(4, "VBUS Connect\n");
 
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 		if (musb->gadget_driver)
 			pm_runtime_get_sync(musb->controller);
+#endif
 
 		otg_init(musb->xceiv);
 		break;
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index bfc5da0..5c299d5 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -56,6 +56,7 @@
 
 config OMAP2_DSS_VENC
 	bool "VENC support"
+	depends on BROKEN
         default y
 	help
 	  OMAP Video Encoder support for S-Video and composite TV-out.
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 1aa2ed1..1907508 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -491,6 +491,9 @@
 	dssdev->dev.parent = &dss_bus;
 	dssdev->dev.release = omap_dss_dev_release;
 	dev_set_name(&dssdev->dev, "display%d", dev_num++);
+
+	BLOCKING_INIT_NOTIFIER_HEAD(&dssdev->notifier);
+
 	return device_register(&dssdev->dev);
 }
 
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 7804779..abfe4b0 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -128,6 +128,16 @@
 
 #define DISPC_VID_PRELOAD(n)		DISPC_REG(0x230 + (n)*0x04)
 
+/*
+ * The OMAP4 DISPC_DIVISOR1 is backward compatible to OMAP3xxx DISPC_DIVISOR.
+ * However DISPC_DIVISOR is also provided in OMAP4, to control DISPC_CORE_CLK.
+ * This allows DISPC_CORE_CLK to be independent of logical clock dividers (lcd)
+ * of LCD1 (primary) and LCD2 (secondary) displays.
+ *
+ * To derive pixel clocks for Primary and Secondary LCD channels, configure the
+ * lcd and pcd in DISPC_DIVISOR1 and DISPC_DIVISOR2 respectively, using the
+ * DISPC_DIVISORo(ch).
+ */
 #define DISPC_DIVISOR			DISPC_REG(0x0804)
 
 #define DISPC_IRQ_MASK_ERROR            (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index a85a6f3..fa9df60 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -26,6 +26,7 @@
 #include <linux/module.h>
 #include <linux/jiffies.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
 
 #include <plat/display.h>
 #include "dss.h"
@@ -614,3 +615,51 @@
 }
 EXPORT_SYMBOL(omap_dss_stop_device);
 
+/* since omap_dss_update_size can be called in irq context, schedule work from
+ * work-queue to deliver notification to client..
+ */
+struct notify_work {
+	struct work_struct work;
+	struct omap_dss_device *dssdev;
+	enum omap_dss_event evt;
+};
+
+static void notify_worker(struct work_struct *work)
+{
+	struct notify_work *nw =
+		container_of(work, struct notify_work, work);
+	struct omap_dss_device *dssdev = nw->dssdev;
+	blocking_notifier_call_chain(&dssdev->notifier, nw->evt, dssdev);
+	kfree(work);
+}
+
+/**
+ * Called by lower level driver to notify about a change in resolution, etc.
+ */
+void omap_dss_notify(struct omap_dss_device *dssdev, enum omap_dss_event evt)
+{
+	struct notify_work *nw =
+			kmalloc(sizeof(struct notify_work), GFP_KERNEL);
+	if (nw) {
+		INIT_WORK(&nw->work, notify_worker);
+		nw->dssdev = dssdev;
+		nw->evt = evt;
+		schedule_work(&nw->work);
+	}
+}
+EXPORT_SYMBOL(omap_dss_notify);
+
+void omap_dss_add_notify(struct omap_dss_device *dssdev,
+		struct notifier_block *nb)
+{
+	blocking_notifier_chain_register(&dssdev->notifier, nb);
+}
+EXPORT_SYMBOL(omap_dss_add_notify);
+
+void omap_dss_remove_notify(struct omap_dss_device *dssdev,
+		struct notifier_block *nb)
+{
+	blocking_notifier_chain_unregister(&dssdev->notifier, nb);
+}
+EXPORT_SYMBOL(omap_dss_remove_notify);
+
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index e9b734c..0b943f6 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -190,11 +190,19 @@
 #define DSI_MAX_NR_ISRS                2
 
 struct dsi_isr_data {
-	omap_dsi_isr_t	isr;
-	void		*arg;
-	u32		mask;
+       omap_dsi_isr_t  isr;
+       void            *arg;
+       u32             mask;
 };
 
+#define FINT_MAX 2100000
+#define FINT_MIN 750000
+#define REGN_MAX (1 << 7)
+#define REGM_MAX ((1 << 11) - 1)
+#define REGM_DISPC_MAX (1 << 4)
+#define REGM_DSI_MAX (1 << 4)
+#define LP_DIV_MAX ((1 << 13) - 1)
+
 enum fifo_size {
 	DSI_FIFO_SIZE_0		= 0,
 	DSI_FIFO_SIZE_32	= 1,
@@ -249,10 +257,8 @@
 
 	unsigned pll_locked;
 
-	spinlock_t irq_lock;
-	struct dsi_isr_tables isr_tables;
-	/* space for a copy used by the interrupt handler */
-	struct dsi_isr_tables isr_tables_copy;
+	struct completion bta_completion;
+	void (*bta_callback)(void);
 
 	int update_channel;
 	struct dsi_update_region update_region;
@@ -287,11 +293,6 @@
 	spinlock_t irq_stats_lock;
 	struct dsi_irq_stats irq_stats;
 #endif
-	/* DSI PLL Parameter Ranges */
-	unsigned long regm_max, regn_max;
-	unsigned long  regm_dispc_max, regm_dsi_max;
-	unsigned long  fint_min, fint_max;
-	unsigned long lpdiv_max;
 } dsi;
 
 #ifdef DEBUG
@@ -335,11 +336,6 @@
 	return dsi.bus_lock.count == 0;
 }
 
-static void dsi_completion_handler(void *data, u32 mask)
-{
-	complete((struct completion *)data);
-}
-
 static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum,
 		int value)
 {
@@ -409,9 +405,6 @@
 
 static void print_irq_status(u32 status)
 {
-	if (status == 0)
-		return;
-
 #ifndef VERBOSE_IRQ
 	if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
 		return;
@@ -447,9 +440,6 @@
 
 static void print_irq_status_vc(int channel, u32 status)
 {
-	if (status == 0)
-		return;
-
 #ifndef VERBOSE_IRQ
 	if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
 		return;
@@ -509,33 +499,26 @@
 	printk("\n");
 }
 
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-static void dsi_collect_irq_stats(u32 irqstatus, u32 *vcstatus, u32 ciostatus)
-{
-	int i;
-
-	spin_lock(&dsi.irq_stats_lock);
-
-	dsi.irq_stats.irq_count++;
-	dss_collect_irq_stats(irqstatus, dsi.irq_stats.dsi_irqs);
-
-	for (i = 0; i < 4; ++i)
-		dss_collect_irq_stats(vcstatus[i], dsi.irq_stats.vc_irqs[i]);
-
-	dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs);
-
-	spin_unlock(&dsi.irq_stats_lock);
-}
-#else
-#define dsi_collect_irq_stats(irqstatus, vcstatus, ciostatus)
-#endif
-
 static int debug_irq;
 
-static void dsi_handle_irq_errors(u32 irqstatus, u32 *vcstatus, u32 ciostatus)
+/* called from dss */
+static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
 {
+	u32 irqstatus, vcstatus, ciostatus;
 	int i;
 
+	irqstatus = dsi_read_reg(DSI_IRQSTATUS);
+
+	/* IRQ is not for us */
+	if (!irqstatus)
+		return IRQ_NONE;
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+	spin_lock(&dsi.irq_stats_lock);
+	dsi.irq_stats.irq_count++;
+	dss_collect_irq_stats(irqstatus, dsi.irq_stats.dsi_irqs);
+#endif
+
 	if (irqstatus & DSI_IRQ_ERROR_MASK) {
 		DSSERR("DSI error, irqstatus %x\n", irqstatus);
 		print_irq_status(irqstatus);
@@ -546,88 +529,37 @@
 		print_irq_status(irqstatus);
 	}
 
+#ifdef DSI_CATCH_MISSING_TE
+	if (irqstatus & DSI_IRQ_TE_TRIGGER)
+		del_timer(&dsi.te_timer);
+#endif
+
 	for (i = 0; i < 4; ++i) {
-		if (vcstatus[i] & DSI_VC_IRQ_ERROR_MASK) {
+		if ((irqstatus & (1<<i)) == 0)
+			continue;
+
+		vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i));
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+		dss_collect_irq_stats(vcstatus, dsi.irq_stats.vc_irqs[i]);
+#endif
+
+		if (vcstatus & DSI_VC_IRQ_BTA) {
+			complete(&dsi.bta_completion);
+
+			if (dsi.bta_callback)
+				dsi.bta_callback();
+		}
+
+		if (vcstatus & DSI_VC_IRQ_ERROR_MASK) {
 			DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
-				       i, vcstatus[i]);
-			print_irq_status_vc(i, vcstatus[i]);
+				       i, vcstatus);
+			print_irq_status_vc(i, vcstatus);
 		} else if (debug_irq) {
-			print_irq_status_vc(i, vcstatus[i]);
-		}
-	}
-
-	if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) {
-		DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
-		print_irq_status_cio(ciostatus);
-	} else if (debug_irq) {
-		print_irq_status_cio(ciostatus);
-	}
-}
-
-static void dsi_call_isrs(struct dsi_isr_data *isr_array,
-		unsigned isr_array_size, u32 irqstatus)
-{
-	struct dsi_isr_data *isr_data;
-	int i;
-
-	for (i = 0; i < isr_array_size; i++) {
-		isr_data = &isr_array[i];
-		if (isr_data->isr && isr_data->mask & irqstatus)
-			isr_data->isr(isr_data->arg, irqstatus);
-	}
-}
-
-static void dsi_handle_isrs(struct dsi_isr_tables *isr_tables,
-		u32 irqstatus, u32 *vcstatus, u32 ciostatus)
-{
-	int i;
-
-	dsi_call_isrs(isr_tables->isr_table,
-			ARRAY_SIZE(isr_tables->isr_table),
-			irqstatus);
-
-	for (i = 0; i < 4; ++i) {
-		if (vcstatus[i] == 0)
-			continue;
-		dsi_call_isrs(isr_tables->isr_table_vc[i],
-				ARRAY_SIZE(isr_tables->isr_table_vc[i]),
-				vcstatus[i]);
-	}
-
-	if (ciostatus != 0)
-		dsi_call_isrs(isr_tables->isr_table_cio,
-				ARRAY_SIZE(isr_tables->isr_table_cio),
-				ciostatus);
-}
-
-static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
-{
-	u32 irqstatus, vcstatus[4], ciostatus;
-	int i;
-
-	spin_lock(&dsi.irq_lock);
-
-	irqstatus = dsi_read_reg(DSI_IRQSTATUS);
-
-	/* IRQ is not for us */
-	if (!irqstatus) {
-		spin_unlock(&dsi.irq_lock);
-		return IRQ_NONE;
-	}
-
-	dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
-	/* flush posted write */
-	dsi_read_reg(DSI_IRQSTATUS);
-
-	for (i = 0; i < 4; ++i) {
-		if ((irqstatus & (1 << i)) == 0) {
-			vcstatus[i] = 0;
-			continue;
+			print_irq_status_vc(i, vcstatus);
 		}
 
-		vcstatus[i] = dsi_read_reg(DSI_VC_IRQSTATUS(i));
-
-		dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus[i]);
+		dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus);
 		/* flush posted write */
 		dsi_read_reg(DSI_VC_IRQSTATUS(i));
 	}
@@ -635,278 +567,68 @@
 	if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) {
 		ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
 
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+		dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs);
+#endif
+
 		dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus);
 		/* flush posted write */
 		dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
-	} else {
-		ciostatus = 0;
+
+		if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) {
+			DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
+			print_irq_status_cio(ciostatus);
+		} else if (debug_irq) {
+			print_irq_status_cio(ciostatus);
+		}
 	}
 
-#ifdef DSI_CATCH_MISSING_TE
-	if (irqstatus & DSI_IRQ_TE_TRIGGER)
-		del_timer(&dsi.te_timer);
+	dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
+	/* flush posted write */
+	dsi_read_reg(DSI_IRQSTATUS);
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+	spin_unlock(&dsi.irq_stats_lock);
 #endif
-
-	/* make a copy and unlock, so that isrs can unregister
-	 * themselves */
-	memcpy(&dsi.isr_tables_copy, &dsi.isr_tables, sizeof(dsi.isr_tables));
-
-	spin_unlock(&dsi.irq_lock);
-
-	dsi_handle_isrs(&dsi.isr_tables_copy, irqstatus, vcstatus, ciostatus);
-
-	dsi_handle_irq_errors(irqstatus, vcstatus, ciostatus);
-
-	dsi_collect_irq_stats(irqstatus, vcstatus, ciostatus);
-
 	return IRQ_HANDLED;
 }
 
-/* dsi.irq_lock has to be locked by the caller */
-static void _omap_dsi_configure_irqs(struct dsi_isr_data *isr_array,
-		unsigned isr_array_size, u32 default_mask,
-		const struct dsi_reg enable_reg,
-		const struct dsi_reg status_reg)
-{
-	struct dsi_isr_data *isr_data;
-	u32 mask;
-	u32 old_mask;
-	int i;
-
-	mask = default_mask;
-
-	for (i = 0; i < isr_array_size; i++) {
-		isr_data = &isr_array[i];
-
-		if (isr_data->isr == NULL)
-			continue;
-
-		mask |= isr_data->mask;
-	}
-
-	old_mask = dsi_read_reg(enable_reg);
-	/* clear the irqstatus for newly enabled irqs */
-	dsi_write_reg(status_reg, (mask ^ old_mask) & mask);
-	dsi_write_reg(enable_reg, mask);
-
-	/* flush posted writes */
-	dsi_read_reg(enable_reg);
-	dsi_read_reg(status_reg);
-}
-
-/* dsi.irq_lock has to be locked by the caller */
-static void _omap_dsi_set_irqs(void)
-{
-	u32 mask = DSI_IRQ_ERROR_MASK;
-#ifdef DSI_CATCH_MISSING_TE
-	mask |= DSI_IRQ_TE_TRIGGER;
-#endif
-	_omap_dsi_configure_irqs(dsi.isr_tables.isr_table,
-			ARRAY_SIZE(dsi.isr_tables.isr_table), mask,
-			DSI_IRQENABLE, DSI_IRQSTATUS);
-}
-
-/* dsi.irq_lock has to be locked by the caller */
-static void _omap_dsi_set_irqs_vc(int vc)
-{
-	_omap_dsi_configure_irqs(dsi.isr_tables.isr_table_vc[vc],
-			ARRAY_SIZE(dsi.isr_tables.isr_table_vc[vc]),
-			DSI_VC_IRQ_ERROR_MASK,
-			DSI_VC_IRQENABLE(vc), DSI_VC_IRQSTATUS(vc));
-}
-
-/* dsi.irq_lock has to be locked by the caller */
-static void _omap_dsi_set_irqs_cio(void)
-{
-	_omap_dsi_configure_irqs(dsi.isr_tables.isr_table_cio,
-			ARRAY_SIZE(dsi.isr_tables.isr_table_cio),
-			DSI_CIO_IRQ_ERROR_MASK,
-			DSI_COMPLEXIO_IRQ_ENABLE, DSI_COMPLEXIO_IRQ_STATUS);
-}
-
 static void _dsi_initialize_irq(void)
 {
-	unsigned long flags;
-	int vc;
-
-	spin_lock_irqsave(&dsi.irq_lock, flags);
-
-	memset(&dsi.isr_tables, 0, sizeof(dsi.isr_tables));
-
-	_omap_dsi_set_irqs();
-	for (vc = 0; vc < 4; ++vc)
-		_omap_dsi_set_irqs_vc(vc);
-	_omap_dsi_set_irqs_cio();
-
-	spin_unlock_irqrestore(&dsi.irq_lock, flags);
-}
-
-static int _dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask,
-		struct dsi_isr_data *isr_array, unsigned isr_array_size)
-{
-	struct dsi_isr_data *isr_data;
-	int free_idx;
+	u32 l;
 	int i;
 
-	BUG_ON(isr == NULL);
+	/* disable all interrupts */
+	dsi_write_reg(DSI_IRQENABLE, 0);
+	for (i = 0; i < 4; ++i)
+		dsi_write_reg(DSI_VC_IRQENABLE(i), 0);
+	dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0);
 
-	/* check for duplicate entry and find a free slot */
-	free_idx = -1;
-	for (i = 0; i < isr_array_size; i++) {
-		isr_data = &isr_array[i];
+	/* clear interrupt status */
+	l = dsi_read_reg(DSI_IRQSTATUS);
+	dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK);
 
-		if (isr_data->isr == isr && isr_data->arg == arg &&
-				isr_data->mask == mask) {
-			return -EINVAL;
-		}
-
-		if (isr_data->isr == NULL && free_idx == -1)
-			free_idx = i;
+	for (i = 0; i < 4; ++i) {
+		l = dsi_read_reg(DSI_VC_IRQSTATUS(i));
+		dsi_write_reg(DSI_VC_IRQSTATUS(i), l);
 	}
 
-	if (free_idx == -1)
-		return -EBUSY;
+	l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
+	dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l);
 
-	isr_data = &isr_array[free_idx];
-	isr_data->isr = isr;
-	isr_data->arg = arg;
-	isr_data->mask = mask;
+	/* enable error irqs */
+	l = DSI_IRQ_ERROR_MASK;
+#ifdef DSI_CATCH_MISSING_TE
+	l |= DSI_IRQ_TE_TRIGGER;
+#endif
+	dsi_write_reg(DSI_IRQENABLE, l);
 
-	return 0;
-}
+	l = DSI_VC_IRQ_ERROR_MASK;
+	for (i = 0; i < 4; ++i)
+		dsi_write_reg(DSI_VC_IRQENABLE(i), l);
 
-static int _dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask,
-		struct dsi_isr_data *isr_array, unsigned isr_array_size)
-{
-	struct dsi_isr_data *isr_data;
-	int i;
-
-	for (i = 0; i < isr_array_size; i++) {
-		isr_data = &isr_array[i];
-		if (isr_data->isr != isr || isr_data->arg != arg ||
-				isr_data->mask != mask)
-			continue;
-
-		isr_data->isr = NULL;
-		isr_data->arg = NULL;
-		isr_data->mask = 0;
-
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-static int dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask)
-{
-	unsigned long flags;
-	int r;
-
-	spin_lock_irqsave(&dsi.irq_lock, flags);
-
-	r = _dsi_register_isr(isr, arg, mask, dsi.isr_tables.isr_table,
-			ARRAY_SIZE(dsi.isr_tables.isr_table));
-
-	if (r == 0)
-		_omap_dsi_set_irqs();
-
-	spin_unlock_irqrestore(&dsi.irq_lock, flags);
-
-	return r;
-}
-
-static int dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask)
-{
-	unsigned long flags;
-	int r;
-
-	spin_lock_irqsave(&dsi.irq_lock, flags);
-
-	r = _dsi_unregister_isr(isr, arg, mask, dsi.isr_tables.isr_table,
-			ARRAY_SIZE(dsi.isr_tables.isr_table));
-
-	if (r == 0)
-		_omap_dsi_set_irqs();
-
-	spin_unlock_irqrestore(&dsi.irq_lock, flags);
-
-	return r;
-}
-
-static int dsi_register_isr_vc(int channel, omap_dsi_isr_t isr, void *arg,
-		u32 mask)
-{
-	unsigned long flags;
-	int r;
-
-	spin_lock_irqsave(&dsi.irq_lock, flags);
-
-	r = _dsi_register_isr(isr, arg, mask,
-			dsi.isr_tables.isr_table_vc[channel],
-			ARRAY_SIZE(dsi.isr_tables.isr_table_vc[channel]));
-
-	if (r == 0)
-		_omap_dsi_set_irqs_vc(channel);
-
-	spin_unlock_irqrestore(&dsi.irq_lock, flags);
-
-	return r;
-}
-
-static int dsi_unregister_isr_vc(int channel, omap_dsi_isr_t isr, void *arg,
-		u32 mask)
-{
-	unsigned long flags;
-	int r;
-
-	spin_lock_irqsave(&dsi.irq_lock, flags);
-
-	r = _dsi_unregister_isr(isr, arg, mask,
-			dsi.isr_tables.isr_table_vc[channel],
-			ARRAY_SIZE(dsi.isr_tables.isr_table_vc[channel]));
-
-	if (r == 0)
-		_omap_dsi_set_irqs_vc(channel);
-
-	spin_unlock_irqrestore(&dsi.irq_lock, flags);
-
-	return r;
-}
-
-static int dsi_register_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask)
-{
-	unsigned long flags;
-	int r;
-
-	spin_lock_irqsave(&dsi.irq_lock, flags);
-
-	r = _dsi_register_isr(isr, arg, mask, dsi.isr_tables.isr_table_cio,
-			ARRAY_SIZE(dsi.isr_tables.isr_table_cio));
-
-	if (r == 0)
-		_omap_dsi_set_irqs_cio();
-
-	spin_unlock_irqrestore(&dsi.irq_lock, flags);
-
-	return r;
-}
-
-static int dsi_unregister_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask)
-{
-	unsigned long flags;
-	int r;
-
-	spin_lock_irqsave(&dsi.irq_lock, flags);
-
-	r = _dsi_unregister_isr(isr, arg, mask, dsi.isr_tables.isr_table_cio,
-			ARRAY_SIZE(dsi.isr_tables.isr_table_cio));
-
-	if (r == 0)
-		_omap_dsi_set_irqs_cio();
-
-	spin_unlock_irqrestore(&dsi.irq_lock, flags);
-
-	return r;
+	l = DSI_CIO_IRQ_ERROR_MASK;
+	dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, l);
 }
 
 static u32 dsi_get_errors(void)
@@ -920,6 +642,26 @@
 	return e;
 }
 
+static void dsi_vc_enable_bta_irq(int channel)
+{
+	u32 l;
+
+	dsi_write_reg(DSI_VC_IRQSTATUS(channel), DSI_VC_IRQ_BTA);
+
+	l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
+	l |= DSI_VC_IRQ_BTA;
+	dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
+}
+
+static void dsi_vc_disable_bta_irq(int channel)
+{
+	u32 l;
+
+	l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
+	l &= ~DSI_VC_IRQ_BTA;
+	dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
+}
+
 /* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */
 static inline void enable_clocks(bool enable)
 {
@@ -1028,7 +770,7 @@
 
 	lp_clk_div = dssdev->phy.dsi.div.lp_clk_div;
 
-	if (lp_clk_div == 0 || lp_clk_div > dsi.lpdiv_max)
+	if (lp_clk_div == 0 || lp_clk_div > LP_DIV_MAX)
 		return -EINVAL;
 
 	dsi_fclk = dsi_fclk_rate();
@@ -1078,16 +820,16 @@
 static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
 		struct dsi_clock_info *cinfo)
 {
-	if (cinfo->regn == 0 || cinfo->regn > dsi.regn_max)
+	if (cinfo->regn == 0 || cinfo->regn > REGN_MAX)
 		return -EINVAL;
 
-	if (cinfo->regm == 0 || cinfo->regm > dsi.regm_max)
+	if (cinfo->regm == 0 || cinfo->regm > REGM_MAX)
 		return -EINVAL;
 
-	if (cinfo->regm_dispc > dsi.regm_dispc_max)
+	if (cinfo->regm_dispc > REGM_DISPC_MAX)
 		return -EINVAL;
 
-	if (cinfo->regm_dsi > dsi.regm_dsi_max)
+	if (cinfo->regm_dsi > REGM_DSI_MAX)
 		return -EINVAL;
 
 	if (cinfo->use_sys_clk) {
@@ -1106,7 +848,7 @@
 
 	cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1));
 
-	if (cinfo->fint > dsi.fint_max || cinfo->fint < dsi.fint_min)
+	if (cinfo->fint > FINT_MAX || cinfo->fint < FINT_MIN)
 		return -EINVAL;
 
 	cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint;
@@ -1141,7 +883,7 @@
 
 	dss_sys_clk = dss_clk_get_rate(DSS_CLK_SYSCK);
 
-	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+	max_dss_fck = dss_feat_get_max_dss_fck();
 
 	if (req_pck == dsi.cache_req_pck &&
 			dsi.cache_cinfo.clkin == dss_sys_clk) {
@@ -1176,17 +918,17 @@
 	/* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
 	/* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
 	/* To reduce PLL lock time, keep Fint high (around 2 MHz) */
-	for (cur.regn = 1; cur.regn < dsi.regn_max; ++cur.regn) {
+	for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) {
 		if (cur.highfreq == 0)
 			cur.fint = cur.clkin / cur.regn;
 		else
 			cur.fint = cur.clkin / (2 * cur.regn);
 
-		if (cur.fint > dsi.fint_max || cur.fint < dsi.fint_min)
+		if (cur.fint > FINT_MAX || cur.fint < FINT_MIN)
 			continue;
 
 		/* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
-		for (cur.regm = 1; cur.regm < dsi.regm_max; ++cur.regm) {
+		for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) {
 			unsigned long a, b;
 
 			a = 2 * cur.regm * (cur.clkin/1000);
@@ -1198,7 +940,7 @@
 
 			/* dsi_pll_hsdiv_dispc_clk(MHz) =
 			 * DSIPHY(MHz) / regm_dispc  < 173MHz/186Mhz */
-			for (cur.regm_dispc = 1; cur.regm_dispc < dsi.regm_dispc_max;
+			for (cur.regm_dispc = 1; cur.regm_dispc < REGM_DISPC_MAX;
 					++cur.regm_dispc) {
 				struct dispc_clock_info cur_dispc;
 				cur.dsi_pll_hsdiv_dispc_clk =
@@ -1270,9 +1012,7 @@
 {
 	int r = 0;
 	u32 l;
-	int f = 0;
-	u8 regn_start, regn_end, regm_start, regm_end;
-	u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end;
+	int f;
 
 	DSSDBGF();
 
@@ -1317,43 +1057,32 @@
 		dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
 		cinfo->dsi_pll_hsdiv_dsi_clk);
 
-	dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGN, &regn_start, &regn_end);
-	dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM, &regm_start, &regm_end);
-	dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DISPC, &regm_dispc_start,
-			&regm_dispc_end);
-	dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DSI, &regm_dsi_start,
-			&regm_dsi_end);
-
 	REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */
 
 	l = dsi_read_reg(DSI_PLL_CONFIGURATION1);
 	l = FLD_MOD(l, 1, 0, 0);		/* DSI_PLL_STOPMODE */
-	/* DSI_PLL_REGN */
-	l = FLD_MOD(l, cinfo->regn - 1, regn_start, regn_end);
-	/* DSI_PLL_REGM */
-	l = FLD_MOD(l, cinfo->regm, regm_start, regm_end);
-	/* DSI_CLOCK_DIV */
+	l = FLD_MOD(l, cinfo->regn - 1, 7, 1);	/* DSI_PLL_REGN */
+	l = FLD_MOD(l, cinfo->regm, 18, 8);	/* DSI_PLL_REGM */
 	l = FLD_MOD(l, cinfo->regm_dispc > 0 ? cinfo->regm_dispc - 1 : 0,
-			regm_dispc_start, regm_dispc_end);
-	/* DSIPROTO_CLOCK_DIV */
+			22, 19);		/* DSI_CLOCK_DIV */
 	l = FLD_MOD(l, cinfo->regm_dsi > 0 ? cinfo->regm_dsi - 1 : 0,
-			regm_dsi_start, regm_dsi_end);
+			26, 23);		/* DSIPROTO_CLOCK_DIV */
 	dsi_write_reg(DSI_PLL_CONFIGURATION1, l);
 
-	BUG_ON(cinfo->fint < dsi.fint_min || cinfo->fint > dsi.fint_max);
-
-	if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) {
-		f = cinfo->fint < 1000000 ? 0x3 :
-			cinfo->fint < 1250000 ? 0x4 :
-			cinfo->fint < 1500000 ? 0x5 :
-			cinfo->fint < 1750000 ? 0x6 :
-			0x7;
-	}
+	BUG_ON(cinfo->fint < 750000 || cinfo->fint > 2100000);
+	if (cinfo->fint < 1000000)
+		f = 0x3;
+	else if (cinfo->fint < 1250000)
+		f = 0x4;
+	else if (cinfo->fint < 1500000)
+		f = 0x5;
+	else if (cinfo->fint < 1750000)
+		f = 0x6;
+	else
+		f = 0x7;
 
 	l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
-
-	if (dss_has_feature(FEAT_DSI_PLL_FREQSEL))
-		l = FLD_MOD(l, f, 4, 1);	/* DSI_PLL_FREQSEL */
+	l = FLD_MOD(l, f, 4, 1);		/* DSI_PLL_FREQSEL */
 	l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1,
 			11, 11);		/* DSI_PLL_CLKSEL */
 	l = FLD_MOD(l, cinfo->highfreq,
@@ -1873,6 +1602,9 @@
 
 	DSSDBG("dsi_complexio_init\n");
 
+	/* CIO_CLK_ICG, enable L3 clk to CIO */
+	REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14);
+
 	/* A dummy read using the SCP interface to any DSIPHY register is
 	 * required after DSIPHY reset to complete the reset of the DSI complex
 	 * I/O. */
@@ -1897,12 +1629,10 @@
 		goto err;
 	}
 
-	if (dss_has_feature(FEAT_DSI_LDO_STATUS)) {
-		if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) {
-			DSSERR("ComplexIO LDO power down.\n");
-			r = -ENODEV;
-			goto err;
-		}
+	if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) {
+		DSSERR("ComplexIO LDO power down.\n");
+		r = -ENODEV;
+		goto err;
 	}
 
 	dsi_complexio_timings();
@@ -2069,8 +1799,6 @@
 	r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
 	r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
 	r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */
-	if (dss_has_feature(FEAT_DSI_VC_OCP_WIDTH))
-		r = FLD_MOD(r, 3, 11, 10);	/* OCP_WIDTH = 32 bit */
 
 	r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
 	r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
@@ -2095,10 +1823,6 @@
 
 	REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */
 
-	/* DCS_CMD_ENABLE */
-	if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC))
-		REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 30, 30);
-
 	dsi_vc_enable(channel, 1);
 
 	dsi.vc[channel].mode = DSI_VC_MODE_L4;
@@ -2123,10 +1847,6 @@
 
 	REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */
 
-	/* DCS_CMD_ENABLE */
-	if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC))
-		REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 30, 30);
-
 	dsi_vc_enable(channel, 1);
 
 	dsi.vc[channel].mode = DSI_VC_MODE_VP;
@@ -2251,44 +1971,33 @@
 
 int dsi_vc_send_bta_sync(int channel)
 {
-	DECLARE_COMPLETION_ONSTACK(completion);
 	int r = 0;
 	u32 err;
 
-	r = dsi_register_isr_vc(channel, dsi_completion_handler,
-			&completion, DSI_VC_IRQ_BTA);
-	if (r)
-		goto err0;
+	INIT_COMPLETION(dsi.bta_completion);
 
-	r = dsi_register_isr(dsi_completion_handler, &completion,
-			DSI_IRQ_ERROR_MASK);
-	if (r)
-		goto err1;
+	dsi_vc_enable_bta_irq(channel);
 
 	r = dsi_vc_send_bta(channel);
 	if (r)
-		goto err2;
+		goto err;
 
-	if (wait_for_completion_timeout(&completion,
+	if (wait_for_completion_timeout(&dsi.bta_completion,
 				msecs_to_jiffies(500)) == 0) {
 		DSSERR("Failed to receive BTA\n");
 		r = -EIO;
-		goto err2;
+		goto err;
 	}
 
 	err = dsi_get_errors();
 	if (err) {
 		DSSERR("Error while sending BTA: %x\n", err);
 		r = -EIO;
-		goto err2;
+		goto err;
 	}
-err2:
-	dsi_unregister_isr(dsi_completion_handler, &completion,
-			DSI_IRQ_ERROR_MASK);
-err1:
-	dsi_unregister_isr_vc(channel, dsi_completion_handler,
-			&completion, DSI_VC_IRQ_BTA);
-err0:
+err:
+	dsi_vc_disable_bta_irq(channel);
+
 	return r;
 }
 EXPORT_SYMBOL(dsi_vc_send_bta_sync);
@@ -2782,11 +2491,8 @@
 	r = FLD_MOD(r, 2, 13, 12);	/* LINE_BUFFER, 2 lines */
 	r = FLD_MOD(r, 1, 14, 14);	/* TRIGGER_RESET_MODE */
 	r = FLD_MOD(r, 1, 19, 19);	/* EOT_ENABLE */
-	if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) {
-		r = FLD_MOD(r, 1, 24, 24);	/* DCS_CMD_ENABLE */
-		/* DCS_CMD_CODE, 1=start, 0=continue */
-		r = FLD_MOD(r, 0, 25, 25);
-	}
+	r = FLD_MOD(r, 1, 24, 24);	/* DCS_CMD_ENABLE */
+	r = FLD_MOD(r, 0, 25, 25);	/* DCS_CMD_CODE, 1=start, 0=continue */
 
 	dsi_write_reg(DSI_CTRL, r);
 
@@ -3105,20 +2811,19 @@
 }
 #endif
 
-static void dsi_framedone_bta_callback(void *data, u32 mask);
-
 static void dsi_handle_framedone(int error)
 {
 	const int channel = dsi.update_channel;
 
-	dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback,
-			NULL, DSI_VC_IRQ_BTA);
-
 	cancel_delayed_work(&dsi.framedone_timeout_work);
 
+	dsi_vc_disable_bta_irq(channel);
+
 	/* SIDLEMODE back to smart-idle */
 	dispc_enable_sidle();
 
+	dsi.bta_callback = NULL;
+
 	if (dsi.te_enabled) {
 		/* enable LP_RX_TO again after the TE */
 		REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
@@ -3152,7 +2857,7 @@
 	dsi_handle_framedone(-ETIMEDOUT);
 }
 
-static void dsi_framedone_bta_callback(void *data, u32 mask)
+static void dsi_framedone_bta_callback(void)
 {
 	dsi_handle_framedone(0);
 
@@ -3192,19 +2897,15 @@
 	 * asynchronously.
 	 * */
 
-	r = dsi_register_isr_vc(channel, dsi_framedone_bta_callback,
-			NULL, DSI_VC_IRQ_BTA);
-	if (r) {
-		DSSERR("Failed to register BTA ISR\n");
-		dsi_handle_framedone(-EIO);
-		return;
-	}
+	dsi.bta_callback = dsi_framedone_bta_callback;
+
+	barrier();
+
+	dsi_vc_enable_bta_irq(channel);
 
 	r = dsi_vc_send_bta(channel);
 	if (r) {
 		DSSERR("BTA after framedone failed\n");
-		dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback,
-				NULL, DSI_VC_IRQ_BTA);
 		dsi_handle_framedone(-EIO);
 	}
 }
@@ -3383,10 +3084,6 @@
 {
 	int r;
 
-	/* The SCPClk is required for both PLL and CIO registers on OMAP4 */
-	/* CIO_CLK_ICG, enable L3 clk to CIO */
-	REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14);
-
 	_dsi_print_reset_status();
 
 	r = dsi_pll_init(dssdev, true, true);
@@ -3399,8 +3096,6 @@
 
 	dss_select_dispc_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC);
 	dss_select_dsi_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI);
-	dss_select_lcd_clk_source(dssdev->manager->id,
-		DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC);
 
 	DSSDBG("PLL OK\n");
 
@@ -3657,24 +3352,12 @@
 			dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI));
 }
 
-static void dsi_calc_clock_param_ranges(void)
-{
-	dsi.regn_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGN);
-	dsi.regm_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM);
-	dsi.regm_dispc_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DISPC);
-	dsi.regm_dsi_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DSI);
-	dsi.fint_min = dss_feat_get_param_min(FEAT_PARAM_DSIPLL_FINT);
-	dsi.fint_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_FINT);
-	dsi.lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV);
-}
-
 static int dsi_init(struct platform_device *pdev)
 {
 	u32 rev;
 	int r, i;
 	struct resource *dsi_mem;
 
-	spin_lock_init(&dsi.irq_lock);
 	spin_lock_init(&dsi.errors_lock);
 	dsi.errors = 0;
 
@@ -3683,6 +3366,8 @@
 	dsi.irq_stats.last_reset = jiffies;
 #endif
 
+	init_completion(&dsi.bta_completion);
+
 	mutex_init(&dsi.lock);
 	sema_init(&dsi.bus_lock, 1);
 
@@ -3731,8 +3416,6 @@
 		dsi.vc[i].vc_id = 0;
 	}
 
-	dsi_calc_clock_param_ranges();
-
 	enable_clocks(1);
 
 	rev = dsi_read_reg(DSI_REVISION);
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 3f1fee6..7f84699 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -82,10 +82,10 @@
 	u32		ctx[DSS_SZ_REGS / sizeof(u32)];
 } dss;
 
-static const char * const dss_generic_clk_source_names[] = {
-	[DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]	= "DSI_PLL_HSDIV_DISPC",
-	[DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]		= "DSI_PLL_HSDIV_DSI",
-	[DSS_CLK_SRC_FCK]			= "DSS_FCK",
+static const struct dss_clk_source_name dss_generic_clk_source_names[] = {
+	{ DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, "DSI_PLL_HSDIV_DISPC" },
+	{ DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, "DSI_PLL_HSDIV_DSI" },
+	{ DSS_CLK_SRC_FCK, "DSS_FCK" },
 };
 
 static void dss_clk_enable_all_no_ctx(void);
@@ -232,47 +232,37 @@
 
 const char *dss_get_generic_clk_source_name(enum dss_clk_source clk_src)
 {
-	return dss_generic_clk_source_names[clk_src];
+	return dss_generic_clk_source_names[clk_src].clksrc_name;
 }
 
 void dss_dump_clocks(struct seq_file *s)
 {
 	unsigned long dpll4_ck_rate;
 	unsigned long dpll4_m4_ck_rate;
-	const char *fclk_name, *fclk_real_name;
-	unsigned long fclk_rate;
 
 	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
 
+	dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
+	dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck);
+
 	seq_printf(s, "- DSS -\n");
 
-	fclk_name = dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK);
-	fclk_real_name = dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK);
-	fclk_rate = dss_clk_get_rate(DSS_CLK_FCK);
+	seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
 
-	if (dss.dpll4_m4_ck) {
-		dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
-		dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck);
-
-		seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
-
-		if (cpu_is_omap3630() || cpu_is_omap44xx())
-			seq_printf(s, "%s (%s) = %lu / %lu  = %lu\n",
-					fclk_name, fclk_real_name,
-					dpll4_ck_rate,
-					dpll4_ck_rate / dpll4_m4_ck_rate,
-					fclk_rate);
-		else
-			seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n",
-					fclk_name, fclk_real_name,
-					dpll4_ck_rate,
-					dpll4_ck_rate / dpll4_m4_ck_rate,
-					fclk_rate);
-	} else {
-		seq_printf(s, "%s (%s) = %lu\n",
-				fclk_name, fclk_real_name,
-				fclk_rate);
-	}
+	if (cpu_is_omap3630() || cpu_is_omap44xx())
+		seq_printf(s, "%s (%s) = %lu / %lu  = %lu\n",
+			dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK),
+			dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK),
+			dpll4_ck_rate,
+			dpll4_ck_rate / dpll4_m4_ck_rate,
+			dss_clk_get_rate(DSS_CLK_FCK));
+	else
+		seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n",
+			dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK),
+			dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK),
+			dpll4_ck_rate,
+			dpll4_ck_rate / dpll4_m4_ck_rate,
+			dss_clk_get_rate(DSS_CLK_FCK));
 
 	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
 }
@@ -392,43 +382,34 @@
 /* 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;
-		u16 fck_div_max = 16;
+	unsigned long prate;
+	u16 fck_div_max = 16;
 
-		if (cpu_is_omap3630() || cpu_is_omap44xx())
-			fck_div_max = 32;
+	if (cpu_is_omap3630() || cpu_is_omap44xx())
+		fck_div_max = 32;
 
-		if (cinfo->fck_div > fck_div_max || cinfo->fck_div == 0)
-			return -EINVAL;
+	if ((cinfo->fck_div > fck_div_max) || cinfo->fck_div == 0)
+		return -EINVAL;
 
-		prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
+	prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
 
-		cinfo->fck = prate / cinfo->fck_div;
-	} else {
-		if (cinfo->fck_div != 0)
-			return -EINVAL;
-		cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
-	}
+	cinfo->fck = prate / cinfo->fck_div;
 
 	return 0;
 }
 
 int dss_set_clock_div(struct dss_clock_info *cinfo)
 {
-	if (dss.dpll4_m4_ck) {
-		unsigned long prate;
-		int r;
+	unsigned long prate;
+	int r;
 
+	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
 		prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
 		DSSDBG("dpll4_m4 = %ld\n", prate);
 
 		r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div);
 		if (r)
 			return r;
-	} else {
-		if (cinfo->fck_div != 0)
-			return -EINVAL;
 	}
 
 	DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
@@ -440,11 +421,9 @@
 {
 	cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
 
-	if (dss.dpll4_m4_ck) {
+	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
 		unsigned long prate;
-
 		prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
-
 		if (cpu_is_omap3630() || cpu_is_omap44xx())
 			cinfo->fck_div = prate / (cinfo->fck);
 		else
@@ -458,7 +437,7 @@
 
 unsigned long dss_get_dpll4_rate(void)
 {
-	if (dss.dpll4_m4_ck)
+	if (cpu_is_omap34xx() || cpu_is_omap44xx())
 		return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
 	else
 		return 0;
@@ -481,7 +460,7 @@
 
 	prate = dss_get_dpll4_rate();
 
-	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+	max_dss_fck = dss_feat_get_max_dss_fck();
 
 	fck = dss_clk_get_rate(DSS_CLK_FCK);
 	if (req_pck == dss.cache_req_pck &&
@@ -507,7 +486,7 @@
 	memset(&best_dss, 0, sizeof(best_dss));
 	memset(&best_dispc, 0, sizeof(best_dispc));
 
-	if (dss.dpll4_m4_ck == NULL) {
+	if (cpu_is_omap24xx()) {
 		struct dispc_clock_info cur_dispc;
 		/* XXX can we change the clock on omap2? */
 		fck = dss_clk_get_rate(DSS_CLK_FCK);
@@ -522,7 +501,8 @@
 		best_dispc = cur_dispc;
 
 		goto found;
-	} else {
+	} else if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
+
 		if (cpu_is_omap3630() || cpu_is_omap44xx())
 			fck_div_max = 32;
 
@@ -557,6 +537,8 @@
 					goto found;
 			}
 		}
+	} else {
+		BUG();
 	}
 
 found:
@@ -639,7 +621,6 @@
 	int r;
 	u32 rev;
 	struct resource *dss_mem;
-	struct clk *dpll4_m4_ck;
 
 	dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
 	if (!dss_mem) {
@@ -680,26 +661,23 @@
 	REG_FLD_MOD(DSS_CONTROL, 1, 3, 3);	/* venc clock 4x enable */
 	REG_FLD_MOD(DSS_CONTROL, 0, 2, 2);	/* venc clock mode = normal */
 #endif
+
 	if (cpu_is_omap34xx()) {
-		dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
-		if (IS_ERR(dpll4_m4_ck)) {
+		dss.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
+		if (IS_ERR(dss.dpll4_m4_ck)) {
 			DSSERR("Failed to get dpll4_m4_ck\n");
-			r = PTR_ERR(dpll4_m4_ck);
+			r = PTR_ERR(dss.dpll4_m4_ck);
 			goto fail1;
 		}
 	} else if (cpu_is_omap44xx()) {
-		dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck");
-		if (IS_ERR(dpll4_m4_ck)) {
+		dss.dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck");
+		if (IS_ERR(dss.dpll4_m4_ck)) {
 			DSSERR("Failed to get dpll4_m4_ck\n");
-			r = PTR_ERR(dpll4_m4_ck);
+			r = PTR_ERR(dss.dpll4_m4_ck);
 			goto fail1;
 		}
-	} else { /* omap24xx */
-		dpll4_m4_ck = NULL;
 	}
 
-	dss.dpll4_m4_ck = dpll4_m4_ck;
-
 	dss.dsi_clk_source = DSS_CLK_SRC_FCK;
 	dss.dispc_clk_source = DSS_CLK_SRC_FCK;
 	dss.lcd_clk_source[0] = DSS_CLK_SRC_FCK;
@@ -721,7 +699,7 @@
 
 static void dss_exit(void)
 {
-	if (dss.dpll4_m4_ck)
+	if (cpu_is_omap34xx() || cpu_is_omap44xx())
 		clk_put(dss.dpll4_m4_ck);
 
 	iounmap(dss.base);
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index c2f582b..05ccd00 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -126,6 +126,12 @@
 						 * OMAP4: DSS_FCLK */
 };
 
+/* Correlates clock source name and dss_clk_source member */
+struct dss_clk_source_name {
+	enum dss_clk_source clksrc;
+	const char *clksrc_name;
+};
+
 enum dss_hdmi_venc_clk_source_select {
 	DSS_VENC_TV_CLK = 0,
 	DSS_HDMI_M_PCLK = 1,
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index 179a7a4..86dc848 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -30,13 +30,10 @@
 
 /* Defines a generic omap register field */
 struct dss_reg_field {
+	enum dss_feat_reg_field id;
 	u8 start, end;
 };
 
-struct dss_param_range {
-	int min, max;
-};
-
 struct omap_dss_features {
 	const struct dss_reg_field *reg_fields;
 	const int num_reg_fields;
@@ -45,58 +42,46 @@
 
 	const int num_mgrs;
 	const int num_ovls;
+	const unsigned long max_dss_fck;
 	const enum omap_display_type *supported_displays;
 	const enum omap_color_mode *supported_color_modes;
-	const char * const *clksrc_names;
-	const struct dss_param_range *dss_params;
+	const struct dss_clk_source_name *clksrc_names;
 };
 
 /* This struct is assigned to one of the below during initialization */
 static struct omap_dss_features *omap_current_dss_features;
 
 static const struct dss_reg_field omap2_dss_reg_fields[] = {
-	[FEAT_REG_FIRHINC]			= { 11, 0 },
-	[FEAT_REG_FIRVINC]			= { 27, 16 },
-	[FEAT_REG_FIFOLOWTHRESHOLD]		= { 8, 0 },
-	[FEAT_REG_FIFOHIGHTHRESHOLD]		= { 24, 16 },
-	[FEAT_REG_FIFOSIZE]			= { 8, 0 },
-	[FEAT_REG_HORIZONTALACCU]		= { 9, 0 },
-	[FEAT_REG_VERTICALACCU]			= { 25, 16 },
-	[FEAT_REG_DISPC_CLK_SWITCH]		= { 0, 0 },
-	[FEAT_REG_DSIPLL_REGN]			= { 0, 0 },
-	[FEAT_REG_DSIPLL_REGM]			= { 0, 0 },
-	[FEAT_REG_DSIPLL_REGM_DISPC]		= { 0, 0 },
-	[FEAT_REG_DSIPLL_REGM_DSI]		= { 0, 0 },
+	{ FEAT_REG_FIRHINC, 11, 0 },
+	{ FEAT_REG_FIRVINC, 27, 16 },
+	{ FEAT_REG_FIFOLOWTHRESHOLD, 8, 0 },
+	{ FEAT_REG_FIFOHIGHTHRESHOLD, 24, 16 },
+	{ FEAT_REG_FIFOSIZE, 8, 0 },
+	{ FEAT_REG_HORIZONTALACCU, 9, 0 },
+	{ FEAT_REG_VERTICALACCU, 25, 16 },
+	{ FEAT_REG_DISPC_CLK_SWITCH, 0, 0 },
 };
 
 static const struct dss_reg_field omap3_dss_reg_fields[] = {
-	[FEAT_REG_FIRHINC]			= { 12, 0 },
-	[FEAT_REG_FIRVINC]			= { 28, 16 },
-	[FEAT_REG_FIFOLOWTHRESHOLD]		= { 11, 0 },
-	[FEAT_REG_FIFOHIGHTHRESHOLD]		= { 27, 16 },
-	[FEAT_REG_FIFOSIZE]			= { 10, 0 },
-	[FEAT_REG_HORIZONTALACCU]		= { 9, 0 },
-	[FEAT_REG_VERTICALACCU]			= { 25, 16 },
-	[FEAT_REG_DISPC_CLK_SWITCH]		= { 0, 0 },
-	[FEAT_REG_DSIPLL_REGN]			= { 7, 1 },
-	[FEAT_REG_DSIPLL_REGM]			= { 18, 8 },
-	[FEAT_REG_DSIPLL_REGM_DISPC]		= { 22, 19 },
-	[FEAT_REG_DSIPLL_REGM_DSI]		= { 26, 23 },
+	{ FEAT_REG_FIRHINC, 12, 0 },
+	{ FEAT_REG_FIRVINC, 28, 16 },
+	{ FEAT_REG_FIFOLOWTHRESHOLD, 11, 0 },
+	{ FEAT_REG_FIFOHIGHTHRESHOLD, 27, 16 },
+	{ FEAT_REG_FIFOSIZE, 10, 0 },
+	{ FEAT_REG_HORIZONTALACCU, 9, 0 },
+	{ FEAT_REG_VERTICALACCU, 25, 16 },
+	{ FEAT_REG_DISPC_CLK_SWITCH, 0, 0 },
 };
 
 static const struct dss_reg_field omap4_dss_reg_fields[] = {
-	[FEAT_REG_FIRHINC]			= { 12, 0 },
-	[FEAT_REG_FIRVINC]			= { 28, 16 },
-	[FEAT_REG_FIFOLOWTHRESHOLD]		= { 15, 0 },
-	[FEAT_REG_FIFOHIGHTHRESHOLD]		= { 31, 16 },
-	[FEAT_REG_FIFOSIZE]			= { 15, 0 },
-	[FEAT_REG_HORIZONTALACCU]		= { 10, 0 },
-	[FEAT_REG_VERTICALACCU]			= { 26, 16 },
-	[FEAT_REG_DISPC_CLK_SWITCH]		= { 9, 8 },
-	[FEAT_REG_DSIPLL_REGN]			= { 8, 1 },
-	[FEAT_REG_DSIPLL_REGM]			= { 20, 9 },
-	[FEAT_REG_DSIPLL_REGM_DISPC]		= { 25, 21 },
-	[FEAT_REG_DSIPLL_REGM_DSI]		= { 30, 26 },
+	{ FEAT_REG_FIRHINC, 12, 0 },
+	{ FEAT_REG_FIRVINC, 28, 16 },
+	{ FEAT_REG_FIFOLOWTHRESHOLD, 15, 0 },
+	{ FEAT_REG_FIFOHIGHTHRESHOLD, 31, 16 },
+	{ FEAT_REG_FIFOSIZE, 15, 0 },
+	{ FEAT_REG_HORIZONTALACCU, 10, 0 },
+	{ FEAT_REG_VERTICALACCU, 26, 16 },
+	{ FEAT_REG_DISPC_CLK_SWITCH, 9, 8 },
 };
 
 static const enum omap_display_type omap2_dss_supported_displays[] = {
@@ -177,52 +162,22 @@
 	OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
 };
 
-static const char * const omap2_dss_clk_source_names[] = {
-	[DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]	= "N/A",
-	[DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]		= "N/A",
-	[DSS_CLK_SRC_FCK]			= "DSS_FCLK1",
+static const struct dss_clk_source_name omap2_dss_clk_source_names[] = {
+	{ DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, "N/A" },
+	{ DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, "N/A" },
+	{ DSS_CLK_SRC_FCK, "DSS_FCLK1" },
 };
 
-static const char * const omap3_dss_clk_source_names[] = {
-	[DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]	= "DSI1_PLL_FCLK",
-	[DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]		= "DSI2_PLL_FCLK",
-	[DSS_CLK_SRC_FCK]			= "DSS1_ALWON_FCLK",
+static const struct dss_clk_source_name omap3_dss_clk_source_names[] = {
+	{ DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, "DSI1_PLL_FCLK" },
+	{ DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, "DSI2_PLL_FCLK" },
+	{ DSS_CLK_SRC_FCK, "DSS1_ALWON_FCLK" },
 };
 
-static const char * const omap4_dss_clk_source_names[] = {
-	[DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC]	= "PLL1_CLK1",
-	[DSS_CLK_SRC_DSI_PLL_HSDIV_DSI]		= "PLL1_CLK2",
-	[DSS_CLK_SRC_FCK]			= "DSS_FCLK",
-};
-
-static const struct dss_param_range omap2_dss_param_range[] = {
-	[FEAT_PARAM_DSS_FCK]			= { 0, 173000000 },
-	[FEAT_PARAM_DSIPLL_REGN]		= { 0, 0 },
-	[FEAT_PARAM_DSIPLL_REGM]		= { 0, 0 },
-	[FEAT_PARAM_DSIPLL_REGM_DISPC]		= { 0, 0 },
-	[FEAT_PARAM_DSIPLL_REGM_DSI]		= { 0, 0 },
-	[FEAT_PARAM_DSIPLL_FINT]		= { 0, 0 },
-	[FEAT_PARAM_DSIPLL_LPDIV]		= { 0, 0 },
-};
-
-static const struct dss_param_range omap3_dss_param_range[] = {
-	[FEAT_PARAM_DSS_FCK]			= { 0, 173000000 },
-	[FEAT_PARAM_DSIPLL_REGN]		= { 0, (1 << 7) - 1 },
-	[FEAT_PARAM_DSIPLL_REGM]		= { 0, (1 << 11) - 1 },
-	[FEAT_PARAM_DSIPLL_REGM_DISPC]		= { 0, (1 << 4) - 1 },
-	[FEAT_PARAM_DSIPLL_REGM_DSI]		= { 0, (1 << 4) - 1 },
-	[FEAT_PARAM_DSIPLL_FINT]		= { 750000, 2100000 },
-	[FEAT_PARAM_DSIPLL_LPDIV]		= { 1, (1 << 13) - 1},
-};
-
-static const struct dss_param_range omap4_dss_param_range[] = {
-	[FEAT_PARAM_DSS_FCK]			= { 0, 186000000 },
-	[FEAT_PARAM_DSIPLL_REGN]		= { 0, (1 << 8) - 1 },
-	[FEAT_PARAM_DSIPLL_REGM]		= { 0, (1 << 12) - 1 },
-	[FEAT_PARAM_DSIPLL_REGM_DISPC]		= { 0, (1 << 5) - 1 },
-	[FEAT_PARAM_DSIPLL_REGM_DSI]		= { 0, (1 << 5) - 1 },
-	[FEAT_PARAM_DSIPLL_FINT]		= { 500000, 2500000 },
-	[FEAT_PARAM_DSIPLL_LPDIV]		= { 0, (1 << 13) - 1 },
+static const struct dss_clk_source_name omap4_dss_clk_source_names[] = {
+	{ DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, "PLL1_CLK1" },
+	{ DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, "PLL1_CLK2" },
+	{ DSS_CLK_SRC_FCK, "DSS_FCLK" },
 };
 
 /* OMAP2 DSS Features */
@@ -237,10 +192,10 @@
 
 	.num_mgrs = 2,
 	.num_ovls = 3,
+	.max_dss_fck = 173000000,
 	.supported_displays = omap2_dss_supported_displays,
 	.supported_color_modes = omap2_dss_supported_color_modes,
 	.clksrc_names = omap2_dss_clk_source_names,
-	.dss_params = omap2_dss_param_range,
 };
 
 /* OMAP3 DSS Features */
@@ -252,15 +207,14 @@
 		FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL |
 		FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
 		FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
-		FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
-		FEAT_DSI_PLL_FREQSEL | FEAT_DSI_LDO_STATUS,
+		FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF,
 
 	.num_mgrs = 2,
 	.num_ovls = 3,
+	.max_dss_fck = 173000000,
 	.supported_displays = omap3430_dss_supported_displays,
 	.supported_color_modes = omap3_dss_supported_color_modes,
 	.clksrc_names = omap3_dss_clk_source_names,
-	.dss_params = omap3_dss_param_range,
 };
 
 static struct omap_dss_features omap3630_dss_features = {
@@ -272,15 +226,14 @@
 		FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
 		FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED |
 		FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |
-		FEAT_RESIZECONF | FEAT_DSI_PLL_FREQSEL |
-		FEAT_DSI_LDO_STATUS,
+		FEAT_RESIZECONF,
 
 	.num_mgrs = 2,
 	.num_ovls = 3,
+	.max_dss_fck = 173000000,
 	.supported_displays = omap3630_dss_supported_displays,
 	.supported_color_modes = omap3_dss_supported_color_modes,
 	.clksrc_names = omap3_dss_clk_source_names,
-	.dss_params = omap3_dss_param_range,
 };
 
 /* OMAP4 DSS Features */
@@ -291,15 +244,14 @@
 	.has_feature	=
 		FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA |
 		FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
-		FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
-		FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH,
+		FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC,
 
 	.num_mgrs = 3,
 	.num_ovls = 3,
+	.max_dss_fck = 186000000,
 	.supported_displays = omap4_dss_supported_displays,
 	.supported_color_modes = omap3_dss_supported_color_modes,
 	.clksrc_names = omap4_dss_clk_source_names,
-	.dss_params = omap4_dss_param_range,
 };
 
 /* Functions returning values related to a DSS feature */
@@ -313,14 +265,10 @@
 	return omap_current_dss_features->num_ovls;
 }
 
-unsigned long dss_feat_get_param_min(enum dss_range_param param)
+/* Max supported DSS FCK in Hz */
+unsigned long dss_feat_get_max_dss_fck(void)
 {
-	return omap_current_dss_features->dss_params[param].min;
-}
-
-unsigned long dss_feat_get_param_max(enum dss_range_param param)
-{
-	return omap_current_dss_features->dss_params[param].max;
+	return omap_current_dss_features->max_dss_fck;
 }
 
 enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel)
@@ -342,7 +290,7 @@
 
 const char *dss_feat_get_clk_source_name(enum dss_clk_source id)
 {
-	return omap_current_dss_features->clksrc_names[id];
+	return omap_current_dss_features->clksrc_names[id].clksrc_name;
 }
 
 /* DSS has_feature check */
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index c5c0b40..2601626 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -77,6 +77,8 @@
 int dss_feat_get_num_ovls(void);
 unsigned long dss_feat_get_param_min(enum dss_range_param param);
 unsigned long dss_feat_get_param_max(enum dss_range_param param);
+/* HDMI from Seb comapat */
+unsigned long dss_feat_get_max_dss_fck(void);
 enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
 enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
 bool dss_feat_color_mode_supported(enum omap_plane plane,
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 0d44f07..aa5b3dc 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -30,6 +30,11 @@
 #include <linux/delay.h>
 #include <linux/string.h>
 #include <plat/display.h>
+#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
+	defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+#endif
 
 #include "dss.h"
 #include "hdmi.h"
@@ -1104,6 +1109,7 @@
 static int hdmi_power_on(struct omap_dss_device *dssdev)
 {
 	int r, code = 0;
+	int dirty = true;
 	struct hdmi_pll_info pll_data;
 	struct omap_video_timings *p;
 	int clkin, n, phy;
@@ -1119,8 +1125,10 @@
 		dssdev->panel.timings.y_res);
 
 	if (!hdmi.custom_set) {
+		code = get_timings_index();
 		DSSDBG("Read EDID as no EDID is not set on poweron\n");
 		hdmi_read_edid(p);
+		dirty = get_timings_index() != code;
 	}
 	code = get_timings_index();
 	dssdev->panel.timings = cea_vesa_timings[code].timings;
@@ -1134,7 +1142,11 @@
 
 	hdmi_wp_video_start(0);
 
-	/* config the PLL and PHY first */
+ 	if (dirty) {
+		omap_dss_notify(dssdev, OMAP_DSS_SIZE_CHANGE);
+ 	}
+ 
+ 	/* config the PLL and PHY first */
 	r = hdmi_pll_program(&pll_data);
 	if (r) {
 		DSSDBG("Failed to lock PLL\n");
@@ -1275,11 +1287,392 @@
 	mutex_unlock(&hdmi.lock);
 }
 
+#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
+	defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
+static void hdmi_wp_audio_config_format(
+		struct hdmi_audio_format *aud_fmt)
+{
+	u32 r;
+
+	DSSDBG("Enter hdmi_wp_audio_config_format\n");
+
+	r = hdmi_read_reg(HDMI_WP_AUDIO_CFG);
+	r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
+	r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
+	r = FLD_MOD(r, aud_fmt->sig_blk_strt_end, 5, 5);
+	r = FLD_MOD(r, aud_fmt->type, 4, 4);
+	r = FLD_MOD(r, aud_fmt->justif, 3, 3);
+	r = FLD_MOD(r, aud_fmt->sample_order, 2, 2);
+	r = FLD_MOD(r, aud_fmt->samples_p_word, 1, 1);
+	r = FLD_MOD(r, aud_fmt->sample_size, 0, 0);
+	hdmi_write_reg(HDMI_WP_AUDIO_CFG, r);
+}
+
+static void hdmi_wp_audio_config_dma(struct hdmi_audio_dma *aud_dma)
+{
+	u32 r;
+
+	DSSDBG("Enter hdmi_wp_audio_config_dma\n");
+
+	r = hdmi_read_reg(HDMI_WP_AUDIO_CFG2);
+	r = FLD_MOD(r, aud_dma->transfer_size, 15, 8);
+	r = FLD_MOD(r, aud_dma->block_size, 7, 0);
+	hdmi_write_reg(HDMI_WP_AUDIO_CFG2, r);
+
+	r = hdmi_read_reg(HDMI_WP_AUDIO_CTRL);
+	r = FLD_MOD(r, aud_dma->mode, 9, 9);
+	r = FLD_MOD(r, aud_dma->threshold, 8, 0);
+	hdmi_write_reg(HDMI_WP_AUDIO_CTRL, r);
+}
+
+static void hdmi_core_audio_config(struct hdmi_core_audio_config *cfg)
+{
+	u32 r;
+
+	/* audio clock recovery parameters */
+	r = hdmi_read_reg(HDMI_CORE_AV_ACR_CTRL);
+	r = FLD_MOD(r, cfg->use_mclk, 2, 2);
+	r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1);
+	r = FLD_MOD(r, cfg->cts_mode, 0, 0);
+	hdmi_write_reg(HDMI_CORE_AV_ACR_CTRL, r);
+
+	REG_FLD_MOD(HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0);
+	REG_FLD_MOD(HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0);
+	REG_FLD_MOD(HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0);
+	REG_FLD_MOD(HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0);
+	REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0);
+	REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0);
+	REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0);
+
+	REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_1, cfg->aud_par_busclk, 7, 0);
+	REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_2,
+		(cfg->aud_par_busclk >> 8), 7, 0);
+	REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_3,
+		(cfg->aud_par_busclk >> 16), 7, 0);
+	REG_FLD_MOD(HDMI_CORE_AV_SPDIF_CTRL, cfg->fs_override, 1, 1);
+
+	/* I2S parameters */
+	REG_FLD_MOD(HDMI_CORE_AV_I2S_CHST4, cfg->freq_sample, 3, 0);
+
+	r = FLD_MOD(r, cfg->i2s_cfg.en_high_br_aud, 7, 7);
+	r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6);
+	r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5);
+	r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4);
+	r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3);
+	r = FLD_MOD(r, cfg->i2s_cfg.justif, 2, 2);
+	r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1);
+	r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0);
+	hdmi_write_reg(HDMI_CORE_AV_I2S_IN_CTRL, r);
+
+	r = hdmi_read_reg(HDMI_CORE_AV_I2S_CHST5);
+	r = FLD_MOD(r, cfg->freq_sample, 7, 4);
+	r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1);
+	r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0);
+	hdmi_write_reg(HDMI_CORE_AV_I2S_CHST5, r);
+
+	REG_FLD_MOD(HDMI_CORE_AV_I2S_IN_LEN, cfg->i2s_cfg.in_length_bits, 3, 0);
+
+	/* audio channels and mode parameters */
+	REG_FLD_MOD(HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1);
+	r = hdmi_read_reg(HDMI_CORE_AV_AUD_MODE);
+	r = FLD_MOD(r, 0, 7, 7);
+	r = FLD_MOD(r, 0, 6, 6);
+	r = FLD_MOD(r, 0, 5, 5);
+	r = FLD_MOD(r, 1, 4, 4);
+	r = FLD_MOD(r, cfg->en_direct_strm_dig_aud, 3, 3);
+	r = FLD_MOD(r, cfg->en_parallel_aud, 2, 2);
+	r = FLD_MOD(r, cfg->en_spdif, 1, 1);
+	hdmi_write_reg(HDMI_CORE_AV_AUD_MODE, r);
+}
+
+static void hdmi_core_audio_infoframe_config(
+		struct hdmi_core_infoframe_audio *info_aud)
+{
+	u8 val;
+	u8 sum = 0, checksum = 0;
+
+	sum += 0x84 + 0x001 + 0x00a;
+	hdmi_write_reg(HDMI_CORE_AV_AUDIO_TYPE, 0x84);
+	hdmi_write_reg(HDMI_CORE_AV_AUDIO_VERS, 0x01);
+	hdmi_write_reg(HDMI_CORE_AV_AUDIO_LEN, 0x0a);
+
+	val = (info_aud->db1_coding_type << 4)
+			| (info_aud->db1_channel_count - 1);
+	hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(0), val);
+	sum += val;
+
+	val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size;
+	hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(1), val);
+	sum += val;
+
+	hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(2), 0x00);
+
+	val = info_aud->db4_channel_alloc;
+	hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(3), val);
+	sum += val;
+
+	val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3);
+	hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(4), val);
+	sum += val;
+
+	hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(5), 0x00);
+	hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(6), 0x00);
+	hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(7), 0x00);
+	hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(8), 0x00);
+	hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(9), 0x00);
+
+	checksum = 0x100 - sum;
+	hdmi_write_reg(HDMI_CORE_AV_AUDIO_CHSUM, checksum);
+
+	/*
+	 * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing
+	 * is available.
+	 */
+}
+
+static int hdmi_config_audio_acr(u32 sample_freq, u32 *n, u32 *cts)
+{
+	u32 r;
+	u32 deep_color = 0;
+	u32 pclk = hdmi.cfg.timings.timings.pixel_clock;
+
+	if (n == NULL || cts == NULL)
+		return -EINVAL;
+	if (omap_rev() == OMAP4430_REV_ES1_0)
+		deep_color = 100;
+	else {
+		r = hdmi_read_reg(HDMI_WP_VIDEO_CFG);
+		switch (r & 0x03) {
+		case 1:
+			deep_color = 100;
+			break;
+		case 2:
+			deep_color = 125;
+			break;
+		case 3:
+			deep_color = 150;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	switch (sample_freq) {
+	case 32000:
+		if ((deep_color == 125) && ((pclk == 54054)
+				|| (pclk == 74250)))
+			*n = 8192;
+		else
+			*n = 4096;
+		break;
+	case 44100:
+		*n = 6272;
+		break;
+	case 48000:
+		if ((deep_color == 125) && ((pclk == 54054)
+				|| (pclk == 74250)))
+			*n = 8192;
+		else
+			*n = 6144;
+		break;
+	default:
+		*n = 0;
+		return -EINVAL;
+	}
+
+	/* calculate CTS */
+	*cts = pclk*(*n/128)*deep_color / (sample_freq/10);
+
+	return 0;
+}
+
+static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
+				    struct snd_pcm_hw_params *params,
+				    struct snd_soc_dai *dai)
+{
+	struct hdmi_audio_format audio_format;
+	struct hdmi_audio_dma audio_dma;
+	struct hdmi_core_audio_config core_cfg;
+	struct hdmi_core_infoframe_audio aud_if_cfg;
+	int err, n, cts;
+	enum hdmi_core_audio_sample_freq sample_freq;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		core_cfg.i2s_cfg.word_max_length =
+			HDMI_AUDIO_I2S_MAX_WORD_20BITS;
+		core_cfg.i2s_cfg.word_length = HDMI_AUDIO_I2S_CHST_WORD_16_BITS;
+		core_cfg.i2s_cfg.in_length_bits =
+			HDMI_AUDIO_I2S_INPUT_LENGTH_16;
+		core_cfg.i2s_cfg.justif = HDMI_AUDIO_JUSTIFY_LEFT;
+		audio_format.samples_p_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES;
+		audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS;
+		audio_format.justif = HDMI_AUDIO_JUSTIFY_LEFT;
+		audio_dma.transfer_size = 0x10;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		core_cfg.i2s_cfg.word_max_length =
+			HDMI_AUDIO_I2S_MAX_WORD_24BITS;
+		core_cfg.i2s_cfg.word_length = HDMI_AUDIO_I2S_CHST_WORD_24_BITS;
+		core_cfg.i2s_cfg.in_length_bits =
+			HDMI_AUDIO_I2S_INPUT_LENGTH_24;
+		audio_format.samples_p_word = HDMI_AUDIO_ONEWORD_ONESAMPLE;
+		audio_format.sample_size = HDMI_AUDIO_SAMPLE_24BITS;
+		audio_format.justif = HDMI_AUDIO_JUSTIFY_RIGHT;
+		core_cfg.i2s_cfg.justif = HDMI_AUDIO_JUSTIFY_RIGHT;
+		audio_dma.transfer_size = 0x20;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (params_rate(params)) {
+	case 32000:
+		sample_freq = HDMI_AUDIO_FS_32000;
+		break;
+	case 44100:
+		sample_freq = HDMI_AUDIO_FS_44100;
+		break;
+	case 48000:
+		sample_freq = HDMI_AUDIO_FS_48000;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	err = hdmi_config_audio_acr(params_rate(params), &n, &cts);
+	if (err < 0)
+		return err;
+
+	/* audio wrapper config */
+	audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL;
+	audio_format.active_chnnls_msk = 0x03;
+	audio_format.type = HDMI_AUDIO_TYPE_LPCM;
+	audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST;
+	audio_format.sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_ON;
+
+	audio_dma.block_size = 0xC0;
+	audio_dma.mode = HDMI_AUDIO_TRANSF_DMA;
+	audio_dma.threshold = 0x20;
+
+	hdmi_wp_audio_config_dma(&audio_dma);
+	hdmi_wp_audio_config_format(&audio_format);
+
+	/* I2S config */
+	core_cfg.i2s_cfg.en_high_br_aud = false;
+	core_cfg.i2s_cfg.sck_edge_mode =
+		HDMI_AUDIO_I2S_SCK_SAMPLE_EDGE_RISING;
+	core_cfg.i2s_cfg.cbit_order = false;
+	core_cfg.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_PCM;
+	core_cfg.i2s_cfg.ws_polarity = HDMI_AUDIO_I2S_WS_POLARITY_LOW_IS_LEFT;
+	core_cfg.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST;
+	core_cfg.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT;
+
+	/* core audio config */
+	core_cfg.freq_sample = sample_freq;
+	core_cfg.n = n;
+	core_cfg.cts = cts;
+	if (omap_rev() == OMAP4430_REV_ES1_0) {
+		core_cfg.aud_par_busclk = (((128 * 31) - 1) << 8);
+		core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_HW;
+	} else {
+		core_cfg.aud_par_busclk = 0;
+		core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_SW;
+	}
+	core_cfg.layout = HDMI_AUDIO_LAYOUT_2CH;
+	core_cfg.use_mclk = false;
+	core_cfg.mclk_mode = HDMI_AUDIO_MCLK_128FS;
+	core_cfg.fs_override = true;
+	core_cfg.en_acr_pkt = true;
+	core_cfg.en_direct_strm_dig_aud = false;
+	core_cfg.en_parallel_aud = true;
+	core_cfg.en_spdif = false;
+
+	hdmi_core_audio_config(&core_cfg);
+
+	/*
+	 * configure packet
+	 * info frame audio see doc CEA861-D page 74
+	 */
+	aud_if_cfg.db1_coding_type = HDMI_INFOFRAME_AUDIO_DB1CT_FROM_STREAM;
+	aud_if_cfg.db1_channel_count = 2;
+	aud_if_cfg.db2_sample_freq = HDMI_INFOFRAME_AUDIO_DB2SF_FROM_STREAM;
+	aud_if_cfg.db2_sample_size = HDMI_INFOFRAME_AUDIO_DB2SS_FROM_STREAM;
+	aud_if_cfg.db4_channel_alloc = 0x00;
+	aud_if_cfg.db5_downmix_inh = false;
+	aud_if_cfg.db5_lsv = 0;
+
+	hdmi_core_audio_infoframe_config(&aud_if_cfg);
+	return 0;
+}
+
+static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
+				  struct snd_soc_dai *dai)
+{
+	int err = 0;
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 1, 0, 0);
+		REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 31, 31);
+		REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 30, 30);
+		break;
+
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 0, 0, 0);
+		REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 30, 30);
+		REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 31, 31);
+		break;
+	default:
+		err = -EINVAL;
+	}
+	return err;
+}
+
+static struct snd_soc_codec_driver hdmi_audio_codec_drv = {
+};
+
+static struct snd_soc_dai_ops hdmi_audio_codec_ops = {
+	.hw_params = hdmi_audio_hw_params,
+	.trigger = hdmi_audio_trigger,
+};
+
+static struct snd_soc_dai_driver hdmi_codec_dai_drv = {
+		.name = "omap4-hdmi-audio-codec",
+		.playback = {
+			.channels_min = 2,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_32000 |
+				SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				SNDRV_PCM_FMTBIT_S24_LE,
+		},
+		.ops = &hdmi_audio_codec_ops,
+};
+#endif
+
+
 /* HDMI HW IP initialisation */
 static int omapdss_hdmihw_probe(struct platform_device *pdev)
 {
 	struct resource *hdmi_mem;
 
+#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
+	defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
+	int ret;
+
+	/* Register ASoC codec DAI */
+	ret = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
+					&hdmi_codec_dai_drv, 1);
+	if (ret) {
+		DSSERR("can't register ASoC HDMI audio codec\n");
+		return ret;
+	}
+#endif
+
 	hdmi.pdata = pdev->dev.platform_data;
 	hdmi.pdev = pdev;
 
@@ -1307,6 +1700,11 @@
 {
 	hdmi_panel_exit();
 
+#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
+	defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
+	snd_soc_unregister_codec(&pdev->dev);
+#endif
+
 	iounmap(hdmi.base_wp);
 
 	return 0;
diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/hdmi.h
index 9887ab9..6c79a57 100644
--- a/drivers/video/omap2/dss/hdmi.h
+++ b/drivers/video/omap2/dss/hdmi.h
@@ -48,6 +48,10 @@
 #define HDMI_WP_VIDEO_TIMING_H			HDMI_WP_REG(0x68)
 #define HDMI_WP_VIDEO_TIMING_V			HDMI_WP_REG(0x6C)
 #define HDMI_WP_WP_CLK				HDMI_WP_REG(0x70)
+#define HDMI_WP_AUDIO_CFG			HDMI_WP_REG(0x80)
+#define HDMI_WP_AUDIO_CFG2			HDMI_WP_REG(0x84)
+#define HDMI_WP_AUDIO_CTRL			HDMI_WP_REG(0x88)
+#define HDMI_WP_AUDIO_DATA			HDMI_WP_REG(0x8C)
 
 /* HDMI IP Core System */
 #define HDMI_CORE_SYS_REG(idx)			HDMI_REG(HDMI_CORE_SYS + idx)
@@ -105,6 +109,8 @@
 #define HDMI_CORE_AV_AVI_DBYTE_NELEMS		HDMI_CORE_AV_REG(15)
 #define HDMI_CORE_AV_SPD_DBYTE			HDMI_CORE_AV_REG(0x190)
 #define HDMI_CORE_AV_SPD_DBYTE_NELEMS		HDMI_CORE_AV_REG(27)
+#define HDMI_CORE_AV_AUD_DBYTE(n)		HDMI_CORE_AV_REG(n * 4 + 0x210)
+#define HDMI_CORE_AV_AUD_DBYTE_NELEMS		HDMI_CORE_AV_REG(10)
 #define HDMI_CORE_AV_MPEG_DBYTE		HDMI_CORE_AV_REG(0x290)
 #define HDMI_CORE_AV_MPEG_DBYTE_NELEMS		HDMI_CORE_AV_REG(27)
 #define HDMI_CORE_AV_GEN_DBYTE			HDMI_CORE_AV_REG(0x300)
@@ -153,6 +159,10 @@
 #define HDMI_CORE_AV_SPD_VERS			HDMI_CORE_AV_REG(0x184)
 #define HDMI_CORE_AV_SPD_LEN			HDMI_CORE_AV_REG(0x188)
 #define HDMI_CORE_AV_SPD_CHSUM			HDMI_CORE_AV_REG(0x18C)
+#define HDMI_CORE_AV_AUDIO_TYPE		HDMI_CORE_AV_REG(0x200)
+#define HDMI_CORE_AV_AUDIO_VERS		HDMI_CORE_AV_REG(0x204)
+#define HDMI_CORE_AV_AUDIO_LEN			HDMI_CORE_AV_REG(0x208)
+#define HDMI_CORE_AV_AUDIO_CHSUM		HDMI_CORE_AV_REG(0x20C)
 #define HDMI_CORE_AV_MPEG_TYPE			HDMI_CORE_AV_REG(0x280)
 #define HDMI_CORE_AV_MPEG_VERS			HDMI_CORE_AV_REG(0x284)
 #define HDMI_CORE_AV_MPEG_LEN			HDMI_CORE_AV_REG(0x288)
@@ -272,7 +282,7 @@
 	HDMI_PACKETREPEATOFF = 0
 };
 
-/* INFOFRAME_AVI_ definitions */
+/* INFOFRAME_AVI_ and INFOFRAME_AUDIO_ definitions */
 enum hdmi_core_infoframe {
 	HDMI_INFOFRAME_AVI_DB1Y_RGB = 0,
 	HDMI_INFOFRAME_AVI_DB1Y_YUV422 = 1,
@@ -317,7 +327,36 @@
 	HDMI_INFOFRAME_AVI_DB5PR_7 = 6,
 	HDMI_INFOFRAME_AVI_DB5PR_8 = 7,
 	HDMI_INFOFRAME_AVI_DB5PR_9 = 8,
-	HDMI_INFOFRAME_AVI_DB5PR_10 = 9
+	HDMI_INFOFRAME_AVI_DB5PR_10 = 9,
+	HDMI_INFOFRAME_AUDIO_DB1CT_FROM_STREAM = 0,
+	HDMI_INFOFRAME_AUDIO_DB1CT_IEC60958 = 1,
+	HDMI_INFOFRAME_AUDIO_DB1CT_AC3 = 2,
+	HDMI_INFOFRAME_AUDIO_DB1CT_MPEG1 = 3,
+	HDMI_INFOFRAME_AUDIO_DB1CT_MP3 = 4,
+	HDMI_INFOFRAME_AUDIO_DB1CT_MPEG2_MULTICH = 5,
+	HDMI_INFOFRAME_AUDIO_DB1CT_AAC = 6,
+	HDMI_INFOFRAME_AUDIO_DB1CT_DTS = 7,
+	HDMI_INFOFRAME_AUDIO_DB1CT_ATRAC = 8,
+	HDMI_INFOFRAME_AUDIO_DB1CT_ONEBIT = 9,
+	HDMI_INFOFRAME_AUDIO_DB1CT_DOLBY_DIGITAL_PLUS = 10,
+	HDMI_INFOFRAME_AUDIO_DB1CT_DTS_HD = 11,
+	HDMI_INFOFRAME_AUDIO_DB1CT_MAT = 12,
+	HDMI_INFOFRAME_AUDIO_DB1CT_DST = 13,
+	HDMI_INFOFRAME_AUDIO_DB1CT_WMA_PRO = 14,
+	HDMI_INFOFRAME_AUDIO_DB2SF_FROM_STREAM = 0,
+	HDMI_INFOFRAME_AUDIO_DB2SF_32000 = 1,
+	HDMI_INFOFRAME_AUDIO_DB2SF_44100 = 2,
+	HDMI_INFOFRAME_AUDIO_DB2SF_48000 = 3,
+	HDMI_INFOFRAME_AUDIO_DB2SF_88200 = 4,
+	HDMI_INFOFRAME_AUDIO_DB2SF_96000 = 5,
+	HDMI_INFOFRAME_AUDIO_DB2SF_176400 = 6,
+	HDMI_INFOFRAME_AUDIO_DB2SF_192000 = 7,
+	HDMI_INFOFRAME_AUDIO_DB2SS_FROM_STREAM = 0,
+	HDMI_INFOFRAME_AUDIO_DB2SS_16BIT = 1,
+	HDMI_INFOFRAME_AUDIO_DB2SS_20BIT = 2,
+	HDMI_INFOFRAME_AUDIO_DB2SS_24BIT = 3,
+	HDMI_INFOFRAME_AUDIO_DB5_DM_INH_PERMITTED = 0,
+	HDMI_INFOFRAME_AUDIO_DB5_DM_INH_PROHIBITED = 1
 };
 
 enum hdmi_packing_mode {
@@ -327,6 +366,117 @@
 	HDMI_PACK_ALREADYPACKED = 7
 };
 
+enum hdmi_core_audio_sample_freq {
+	HDMI_AUDIO_FS_32000 = 0x3,
+	HDMI_AUDIO_FS_44100 = 0x0,
+	HDMI_AUDIO_FS_48000 = 0x2,
+	HDMI_AUDIO_FS_88200 = 0x8,
+	HDMI_AUDIO_FS_96000 = 0xA,
+	HDMI_AUDIO_FS_176400 = 0xC,
+	HDMI_AUDIO_FS_192000 = 0xE,
+	HDMI_AUDIO_FS_NOT_INDICATED = 0x1
+};
+
+enum hdmi_core_audio_layout {
+	HDMI_AUDIO_LAYOUT_2CH = 0,
+	HDMI_AUDIO_LAYOUT_8CH = 1
+};
+
+enum hdmi_core_cts_mode {
+	HDMI_AUDIO_CTS_MODE_HW = 0,
+	HDMI_AUDIO_CTS_MODE_SW = 1
+};
+
+enum hdmi_stereo_channels {
+	HDMI_AUDIO_STEREO_NOCHANNELS = 0,
+	HDMI_AUDIO_STEREO_ONECHANNEL = 1,
+	HDMI_AUDIO_STEREO_TWOCHANNELS = 2,
+	HDMI_AUDIO_STEREO_THREECHANNELS = 3,
+	HDMI_AUDIO_STEREO_FOURCHANNELS = 4
+};
+
+enum hdmi_audio_type {
+	HDMI_AUDIO_TYPE_LPCM = 0,
+	HDMI_AUDIO_TYPE_IEC = 1
+};
+
+enum hdmi_audio_justif {
+	HDMI_AUDIO_JUSTIFY_LEFT = 0,
+	HDMI_AUDIO_JUSTIFY_RIGHT = 1
+};
+
+enum hdmi_audio_sample_order {
+	HDMI_AUDIO_SAMPLE_RIGHT_FIRST = 0,
+	HDMI_AUDIO_SAMPLE_LEFT_FIRST = 1
+};
+
+enum hdmi_audio_samples_perword {
+	HDMI_AUDIO_ONEWORD_ONESAMPLE = 0,
+	HDMI_AUDIO_ONEWORD_TWOSAMPLES = 1
+};
+
+enum hdmi_audio_sample_size {
+	HDMI_AUDIO_SAMPLE_16BITS = 0,
+	HDMI_AUDIO_SAMPLE_24BITS = 1
+};
+
+enum hdmi_audio_transf_mode {
+	HDMI_AUDIO_TRANSF_DMA = 0,
+	HDMI_AUDIO_TRANSF_IRQ = 1
+};
+
+enum hdmi_audio_blk_strt_end_sig {
+	HDMI_AUDIO_BLOCK_SIG_STARTEND_ON = 0,
+	HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF = 1
+};
+
+enum hdmi_audio_i2s_config {
+	HDMI_AUDIO_I2S_WS_POLARITY_LOW_IS_LEFT = 0,
+	HDMI_AUDIO_I2S_WS_POLARIT_YLOW_IS_RIGHT = 1,
+	HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST = 0,
+	HDMI_AUDIO_I2S_LSB_SHIFTED_FIRST = 1,
+	HDMI_AUDIO_I2S_MAX_WORD_20BITS = 0,
+	HDMI_AUDIO_I2S_MAX_WORD_24BITS = 1,
+	HDMI_AUDIO_I2S_CHST_WORD_NOT_SPECIFIED = 0,
+	HDMI_AUDIO_I2S_CHST_WORD_16_BITS = 1,
+	HDMI_AUDIO_I2S_CHST_WORD_17_BITS = 6,
+	HDMI_AUDIO_I2S_CHST_WORD_18_BITS = 2,
+	HDMI_AUDIO_I2S_CHST_WORD_19_BITS = 4,
+	HDMI_AUDIO_I2S_CHST_WORD_20_BITS_20MAX = 5,
+	HDMI_AUDIO_I2S_CHST_WORD_20_BITS_24MAX = 1,
+	HDMI_AUDIO_I2S_CHST_WORD_21_BITS = 6,
+	HDMI_AUDIO_I2S_CHST_WORD_22_BITS = 2,
+	HDMI_AUDIO_I2S_CHST_WORD_23_BITS = 4,
+	HDMI_AUDIO_I2S_CHST_WORD_24_BITS = 5,
+	HDMI_AUDIO_I2S_SCK_SAMPLE_EDGE_FALLING = 0,
+	HDMI_AUDIO_I2S_SCK_SAMPLE_EDGE_RISING = 1,
+	HDMI_AUDIO_I2S_VBIT_PCM = 0,
+	HDMI_AUDIO_I2S_VBIT_COMPRESSED = 1,
+	HDMI_AUDIO_I2S_INPUT_LENGTH_NA = 0,
+	HDMI_AUDIO_I2S_INPUT_LENGTH_16 = 2,
+	HDMI_AUDIO_I2S_INPUT_LENGTH_17 = 12,
+	HDMI_AUDIO_I2S_INPUT_LENGTH_18 = 4,
+	HDMI_AUDIO_I2S_INPUT_LENGTH_19 = 8,
+	HDMI_AUDIO_I2S_INPUT_LENGTH_20 = 10,
+	HDMI_AUDIO_I2S_INPUT_LENGTH_21 = 13,
+	HDMI_AUDIO_I2S_INPUT_LENGTH_22 = 5,
+	HDMI_AUDIO_I2S_INPUT_LENGTH_23 = 9,
+	HDMI_AUDIO_I2S_INPUT_LENGTH_24 = 11,
+	HDMI_AUDIO_I2S_FIRST_BIT_SHIFT = 0,
+	HDMI_AUDIO_I2S_FIRST_BIT_NO_SHIFT = 1
+};
+
+enum hdmi_audio_mclk_mode {
+	HDMI_AUDIO_MCLK_128FS = 0,
+	HDMI_AUDIO_MCLK_256FS = 1,
+	HDMI_AUDIO_MCLK_384FS = 2,
+	HDMI_AUDIO_MCLK_512FS = 3,
+	HDMI_AUDIO_MCLK_768FS = 4,
+	HDMI_AUDIO_MCLK_1024FS = 5,
+	HDMI_AUDIO_MCLK_1152FS = 6,
+	HDMI_AUDIO_MCLK_192FS = 7
+};
+
 struct hdmi_core_video_config {
 	enum hdmi_core_inputbus_width	ip_bus_width;
 	enum hdmi_core_dither_trunc	op_dither_truc;
@@ -376,6 +526,26 @@
 	u16	db12_13_pixel_sofright;
 		/* Pixel number start of right bar */
 };
+/*
+ * Refer to section 8.2 in HDMI 1.3 specification for
+ * details about infoframe databytes
+ */
+struct hdmi_core_infoframe_audio {
+	u8 db1_coding_type;
+		/* Audio coding type */
+	u8 db1_channel_count;
+		/* Number of channels */
+	u8 db2_sample_freq;
+		/* Sample frequency */
+	u8 db2_sample_size;
+		/* Sample size */
+	u8 db4_channel_alloc;
+		/* Channel allocation code */
+	bool db5_downmix_inh;
+		/* Downmix inhibit flag */
+	u8 db5_lsv;
+		/* Level shift values for downmix */
+};
 
 struct hdmi_core_packet_enable_repeat {
 	u32	audio_pkt;
@@ -412,4 +582,52 @@
 	struct hdmi_cm cm;
 };
 
+struct hdmi_audio_format {
+	enum hdmi_stereo_channels		stereo_channels;
+	u8					active_chnnls_msk;
+	enum hdmi_audio_type			type;
+	enum hdmi_audio_justif			justif;
+	enum hdmi_audio_sample_order		sample_order;
+	enum hdmi_audio_samples_perword		samples_p_word;
+	enum hdmi_audio_sample_size		sample_size;
+	enum hdmi_audio_blk_strt_end_sig	sig_blk_strt_end;
+};
+
+struct hdmi_audio_dma {
+	u8				transfer_size;
+	u8				block_size;
+	enum hdmi_audio_transf_mode	mode;
+	u16				threshold;
+};
+
+struct hdmi_core_audio_i2s_config {
+	u8 word_max_length;
+	u8 word_length;
+	u8 in_length_bits;
+	u8 justif;
+	u8 en_high_br_aud;
+	u8 sck_edge_mode;
+	u8 cbit_order;
+	u8 vbit;
+	u8 ws_polarity;
+	u8 direction;
+	u8 shift;
+};
+
+struct hdmi_core_audio_config {
+	struct hdmi_core_audio_i2s_config	i2s_cfg;
+	enum hdmi_core_audio_sample_freq	freq_sample;
+	bool					fs_override;
+	u32					n;
+	u32					cts;
+	u32					aud_par_busclk;
+	enum hdmi_core_audio_layout		layout;
+	enum hdmi_core_cts_mode			cts_mode;
+	bool					use_mclk;
+	enum hdmi_audio_mclk_mode		mclk_mode;
+	bool					en_acr_pkt;
+	bool					en_direct_strm_dig_aud;
+	bool					en_parallel_aud;
+	bool					en_spdif;
+};
 #endif
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 8e35a5b..43009e5 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -769,16 +769,10 @@
 
 int venc_init_platform_driver(void)
 {
-	if (cpu_is_omap44xx())
-		return 0;
-
 	return platform_driver_register(&omap_venchw_driver);
 }
 
 void venc_uninit_platform_driver(void)
 {
-	if (cpu_is_omap44xx())
-		return;
-
 	return platform_driver_unregister(&omap_venchw_driver);
 }
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 505ec66..2bd90ca 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -29,6 +29,7 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/omapfb.h>
+#include <linux/console.h>
 
 #include <plat/display.h>
 #include <plat/vram.h>
@@ -1902,6 +1903,94 @@
 	kfree(fbdev);
 }
 
+static void size_notify(struct fb_info *fbi, int w, int h)
+{
+	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct fb_var_screeninfo var = fbi->var;
+	struct fb_var_screeninfo saved_var = fbi->var;
+	int orig_flags;
+	int new_size = (w * var.bits_per_pixel >> 3) * h;
+
+	DBG("size_notify: %dx%d\n", w, h);
+
+	var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_ALL | FB_ACTIVATE_NOW;
+	var.xres = w;
+	var.yres = h;
+	var.xres_virtual = w;
+	var.yres_virtual = h;
+
+	console_lock();
+
+	/* Try to increase memory allocated for FB, if needed */
+	if (new_size > ofbi->region->size) {
+		DBG("re-allocating FB - old size: %ld - new size: %d\n", ofbi->region->size, new_size);
+		omapfb_get_mem_region(ofbi->region);
+		omapfb_realloc_fbmem(fbi, new_size, 0);
+		omapfb_put_mem_region(ofbi->region);
+	}
+
+	/* this ensures fbdev clients, like the console driver, get notified about
+	 * the change:
+	 */
+	orig_flags = fbi->flags;
+	fbi->flags |= FBINFO_MISC_USEREVENT;
+	fb_set_var(fbi, &var);
+	fbi->flags &= ~FBINFO_MISC_USEREVENT;
+
+	/* now delete old mode:
+	 */
+	saved_var.activate |= FB_ACTIVATE_INV_MODE;
+	fbi->flags |= FBINFO_MISC_USEREVENT;
+	fb_set_var(fbi, &saved_var);
+	fbi->flags = orig_flags;
+
+	console_unlock();
+}
+
+struct omapfb_notifier_block {
+	struct notifier_block notifier;
+	struct omapfb2_device *fbdev;
+};
+
+static int omapfb_notifier(struct notifier_block *nb,
+		unsigned long evt, void *arg)
+{
+	struct omapfb_notifier_block *notifier =
+			container_of(nb, struct omapfb_notifier_block, notifier);
+	struct omap_dss_device *dssdev = arg;
+	struct omapfb2_device *fbdev = notifier->fbdev;
+	int keep = false;
+	int i;
+
+	/* figure out if this event pertains to this omapfb device:
+	 */
+	for (i = 0; i < fbdev->num_managers; i++) {
+		if (fbdev->managers[i]->device == dssdev) {
+			keep = true;
+			break;
+		}
+	}
+
+	if (!keep)
+		return NOTIFY_DONE;
+
+	/* the event pertains to us.. see if we care:
+	 */
+	switch (evt) {
+		case OMAP_DSS_SIZE_CHANGE: {
+			u16 w, h;
+			dssdev->driver->get_resolution(dssdev, &w, &h);
+			for (i = 0; i < fbdev->num_fbs; i++)
+				size_notify(fbdev->fbs[i], w, h);
+			break;
+		}
+		default:  /* don't care about other events for now */
+			break;
+	}
+
+	return NOTIFY_OK;
+}
+
 static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
 {
 	int r, i;
@@ -2227,6 +2316,7 @@
 	fbdev->num_displays = 0;
 	dssdev = NULL;
 	for_each_dss_dev(dssdev) {
+		struct omapfb_notifier_block *notifier;
 		omap_dss_get_device(dssdev);
 
 		if (!dssdev->driver) {
@@ -2235,7 +2325,12 @@
 		}
 
 		fbdev->displays[fbdev->num_displays++] = dssdev;
-	}
+
+		notifier = kzalloc(sizeof(struct omapfb_notifier_block), GFP_KERNEL);
+		notifier->notifier.notifier_call = omapfb_notifier;
+		notifier->fbdev = fbdev;
+		omap_dss_add_notify(dssdev, &notifier->notifier);
+ 	}
 
 	if (r)
 		goto cleanup;
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 348843b..5edb344 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -896,7 +896,7 @@
 	int num_ioctls;
 	struct file_operations fops;
 	struct pci_driver pci_driver;
-	struct platform_device *platform_device;
+	struct platform_driver platform_driver;
 	/* List of devices hanging off this driver */
 	struct list_head device_list;
 };
@@ -1656,6 +1656,8 @@
 
 extern int drm_platform_init(struct drm_driver *driver);
 extern int drm_pci_init(struct drm_driver *driver);
+extern void drm_platform_exit(struct drm_driver *driver);
+extern void drm_pci_exit(struct drm_driver *driver);
 extern int drm_fill_in_dev(struct drm_device *dev,
 			   const struct pci_device_id *ent,
 			   struct drm_driver *driver);
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index a088db6..ab12c5e 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -107,6 +107,15 @@
 	  Say Y if you want to add support for SoC audio on Texas Instruments
 	  SDP4430.
 
+config SND_OMAP_SOC_OMAP4_HDMI
+	tristate "SoC Audio support for Texas Instruments SDP4430 or Panda HDMI port"
+	depends on SND_OMAP_SOC && OMAP4_DSS_HDMI && OMAP2_DSS
+	depends on (MACH_OMAP_4430SDP || MACH_OMAP4_PANDA)
+	select SND_OMAP_SOC_HDMI
+	help
+	  Say Y if you want to add support for SoC HDMI audio on Texas Instruments
+	  SDP4430 or Panda
+
 config SND_OMAP_SOC_OMAP3_PANDORA
 	tristate "SoC Audio support for OMAP3 Pandora"
 	depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_PANDORA
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index ba9fc65..de364ae 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -22,6 +22,7 @@
 snd-soc-omap3beagle-objs := omap3beagle.o
 snd-soc-zoom2-objs := zoom2.o
 snd-soc-igep0020-objs := igep0020.o
+snd-soc-omap4-hdmi-objs := omap-hdmi.o omap4-hdmi-card.o
 
 obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
 obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o
@@ -37,3 +38,4 @@
 obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
 obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o
 obj-$(CONFIG_SND_OMAP_SOC_IGEP0020) += snd-soc-igep0020.o
+obj-$(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) += snd-soc-omap4-hdmi.o
diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c
new file mode 100644
index 0000000..e19f062
--- /dev/null
+++ b/sound/soc/omap/omap-hdmi.c
@@ -0,0 +1,150 @@
+/*
+ * omap-hdmi.c
+ *
+ * OMAP ALSA SoC DAI driver for HDMI audio on OMAP4 processors.
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Authors: Jorge Candelaria <jorge.candelaria@gmail.com>
+ *          Ricardo Neri <ricardo.neri@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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <plat/dma.h>
+#include <plat/display.h>
+#include <plat/omap44xx.h>
+#include "omap-pcm.h"
+#include "omap-hdmi.h"
+
+static struct omap_pcm_dma_data omap_hdmi_dai_dma_params = {
+	.name = "HDMI playback",
+	.dma_req = OMAP44XX_DMA_DSS_HDMI_REQ,
+	.port_addr = OMAP44XX_DSS_HDMI_L3_BASE + OMAP44XX_HDMI_AUDIO_DMA_PORT,
+	.sync_mode = OMAP_DMA_SYNC_PACKET,
+};
+
+static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream,
+				  struct snd_soc_dai *dai)
+{
+	int err = 0, i;
+	struct omap_overlay *ovl = NULL;
+
+	/*
+	 * Make sure that the period bytes are multiple of the DMA packet size.
+	 * Largest packet size we use is 32 32-bit words = 128 bytes
+	 */
+	err = snd_pcm_hw_constraint_step(substream->runtime, 0,
+				 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128);
+	if (err < 0)
+		return err;
+
+	/* find DSS HDMI device */
+	for (i = 0; i < omap_dss_get_num_overlays(); i++) {
+		ovl = omap_dss_get_overlay(i);
+		if (strcmp(ovl->manager->device->name, "hdmi") == 0)
+			break;
+	}
+	if (ovl->manager->device->state != OMAP_DSS_DISPLAY_ACTIVE) {
+		printk(KERN_ERR "HDMI display is not active!");
+		return -EIO;
+	}
+	return err;
+}
+
+static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
+				    struct snd_pcm_hw_params *params,
+				    struct snd_soc_dai *dai)
+{
+	int err = 0;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		omap_hdmi_dai_dma_params.data_type = OMAP_DMA_DATA_TYPE_S32;
+		omap_hdmi_dai_dma_params.packet_size = 16;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		omap_hdmi_dai_dma_params.data_type = OMAP_DMA_DATA_TYPE_S32;
+		omap_hdmi_dai_dma_params.packet_size = 32;
+		break;
+	default:
+		err = -EINVAL;
+	}
+
+	snd_soc_dai_set_dma_data(dai, substream,
+				 &omap_hdmi_dai_dma_params);
+
+	return err;
+}
+
+static struct snd_soc_dai_ops omap_hdmi_dai_ops = {
+	.startup	= omap_hdmi_dai_startup,
+	.hw_params	= omap_hdmi_dai_hw_params,
+};
+
+static struct snd_soc_dai_driver omap_hdmi_dai = {
+	.playback = {
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = OMAP_HDMI_RATES,
+		.formats = OMAP_HDMI_FORMATS,
+	},
+	.ops = &omap_hdmi_dai_ops,
+};
+
+static __devinit int omap_hdmi_probe(struct platform_device *pdev)
+{
+	return snd_soc_register_dai(&pdev->dev, &omap_hdmi_dai);
+}
+
+static int __devexit omap_hdmi_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_dai(&pdev->dev);
+	return 0;
+}
+
+static struct platform_driver hdmi_dai_driver = {
+	.driver = {
+		.name = "hdmi-audio-dai",
+		.owner = THIS_MODULE,
+	},
+	.probe = omap_hdmi_probe,
+	.remove = __devexit_p(omap_hdmi_remove),
+};
+
+static int __init hdmi_dai_init(void)
+{
+	return platform_driver_register(&hdmi_dai_driver);
+}
+module_init(hdmi_dai_init);
+
+static void __exit hdmi_dai_exit(void)
+{
+	platform_driver_unregister(&hdmi_dai_driver);
+}
+module_exit(hdmi_dai_exit);
+
+MODULE_AUTHOR("Jorge Candelaria <jorge.candelaria@gmail.com>");
+MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
+MODULE_DESCRIPTION("OMAP HDMI SoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-hdmi.h b/sound/soc/omap/omap-hdmi.h
new file mode 100644
index 0000000..77bc785
--- /dev/null
+++ b/sound/soc/omap/omap-hdmi.h
@@ -0,0 +1,36 @@
+/*
+ * omap-hdmi.h
+ *
+ * Definitions for OMAP ALSA SoC DAI driver for HDMI audio on OMAP4 processors.
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Autors: Jorge Candelaria <jorge.candelaria@gmail.com>
+ *         Ricardo Neri <ricardo.neri@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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_HDMI_H__
+#define __OMAP_HDMI_H__
+
+#define OMAP44XX_HDMI_AUDIO_DMA_PORT 0x8c
+
+#define OMAP_HDMI_RATES	(SNDRV_PCM_RATE_32000 | \
+				SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
+
+#define OMAP_HDMI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+				SNDRV_PCM_FMTBIT_S24_LE)
+
+#endif
diff --git a/sound/soc/omap/omap4-hdmi-card.c b/sound/soc/omap/omap4-hdmi-card.c
new file mode 100644
index 0000000..b5cf150
--- /dev/null
+++ b/sound/soc/omap/omap4-hdmi-card.c
@@ -0,0 +1,89 @@
+/*
+ * sdp4430-hdmi.c
+ *
+ * OMAP ALSA SoC machine driver for TI OMAP4 HDMI
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Ricardo Neri <ricardo.neri@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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <asm/mach-types.h>
+
+#define OMAP4_HDMI_SND_DEV_ID 0
+
+static struct snd_soc_dai_link omap4_hdmi_dai = {
+		.name = "HDMI",
+		.stream_name = "HDMI",
+		.cpu_dai_name = "hdmi-audio-dai",
+		.platform_name = "omap-pcm-audio",
+		.codec_name = "omapdss_hdmi",
+		.codec_dai_name = "omap4-hdmi-audio-codec"
+};
+
+/* Audio machine driver */
+static struct snd_soc_card snd_soc_omap4_hdmi = {
+	.name = "SDP4430HDMI",
+	/* .long_name = "TI OMAP4 HDMI Board", */
+	.dai_link = &omap4_hdmi_dai,
+	.num_links = 1,
+};
+
+static struct platform_device *omap4_hdmi_snd_device;
+
+static int __init omap4_hdmi_soc_init(void)
+{
+	int ret;
+
+	if (!(machine_is_omap_4430sdp() || machine_is_omap4_panda()))
+		return -ENODEV;
+	printk(KERN_INFO "OMAP4 HDMI audio SoC init\n");
+
+	if (machine_is_omap4_panda())
+		snd_soc_omap4_hdmi.name = "PandaHDMI";
+
+	omap4_hdmi_snd_device = platform_device_alloc("soc-audio",
+		OMAP4_HDMI_SND_DEV_ID);
+	if (!omap4_hdmi_snd_device) {
+		printk(KERN_ERR "Platform device allocation failed\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(omap4_hdmi_snd_device, &snd_soc_omap4_hdmi);
+
+	ret = platform_device_add(omap4_hdmi_snd_device);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	printk(KERN_ERR "Unable to add platform device\n");
+	platform_device_put(omap4_hdmi_snd_device);
+	return ret;
+}
+module_init(omap4_hdmi_soc_init);
+
+static void __exit omap4_hdmi_soc_exit(void)
+{
+	platform_device_unregister(omap4_hdmi_snd_device);
+}
+module_exit(omap4_hdmi_soc_exit);
+
+MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
+MODULE_DESCRIPTION("ALSA SoC OMAP4 HDMI AUDIO");
+MODULE_LICENSE("GPL");