Merge "dev: vadc: Add fast averaging samples configuration"
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index 74e17e0..fc41a24 100644
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -117,6 +117,8 @@
 #define EXPAND(NAME) #NAME
 #define TARGET(NAME) EXPAND(NAME)
 
+#define DISPLAY_PANEL_HDMI "hdmi"
+
 #ifdef MEMBASE
 #define EMMC_BOOT_IMG_HEADER_ADDR (0xFF000+(MEMBASE))
 #else
@@ -132,6 +134,7 @@
 /* make 4096 as default size to ensure EFS,EXT4's erasing */
 #define DEFAULT_ERASE_SIZE  4096
 #define MAX_PANEL_BUF_SIZE 196
+#define FOOTER_SIZE 16384
 
 #define DISPLAY_DEFAULT_PREFIX "mdss_mdp"
 #define BOOT_DEV_MAX_LEN  64
@@ -2501,6 +2504,7 @@
 	unsigned long long size = 0;
 	int index = INVALID_PTN;
 	uint8_t lun = 0;
+	char *footer = NULL;
 
 #if VERIFIED_BOOT
 	if(!strcmp(arg, KEYSTORE_PTN_NAME))
@@ -2543,6 +2547,21 @@
 			fastboot_fail("failed to erase partition");
 			return;
 		}
+		/*Erase FDE metadata at the userdata footer*/
+		if(!(strncmp(arg, "userdata", 8)))
+		{
+			footer = memalign(CACHE_LINE, FOOTER_SIZE);
+			memset((void *)footer, 0, FOOTER_SIZE);
+
+			size = partition_get_size(index);
+
+			if (mmc_write((ptn + size) - FOOTER_SIZE , FOOTER_SIZE, (unsigned int *)footer)) {
+				fastboot_fail("failed to erase userdata footer");
+				free(footer);
+				return;
+			}
+			free(footer);
+		}
 	}
 #if VERIFIED_BOOT
 #if !VBOOT_MOTA
@@ -3166,6 +3185,7 @@
 	struct ptentry *ptn;
 	struct ptable *ptable;
 	unsigned extra = 0;
+	uint64_t partition_size = 0;
 
 	ptable = flash_get_ptable();
 	if (ptable == NULL) {
@@ -3197,6 +3217,17 @@
 	else
 		sz = ROUND_TO_PAGE(sz, page_mask);
 
+	partition_size = (uint64_t)ptn->length * (uint64_t)flash_num_pages_per_blk() *  (uint64_t)flash_page_size();
+	if (partition_size > UINT_MAX) {
+		fastboot_fail("Invalid partition size");
+		return;
+	}
+
+	if (sz > partition_size) {
+		fastboot_fail("Image size too large");
+		return;
+	}
+
 	dprintf(INFO, "writing %d bytes to '%s'\n", sz, ptn->name);
 	if (!memcmp((void *)data, UBI_MAGIC, UBI_MAGIC_SIZE)) {
 		if (flash_ubi_img(ptn, data, sz)) {
@@ -3786,6 +3817,11 @@
 	if (!check_alarm_boot()) {
 #endif
 		dprintf(SPEW, "Display Init: Start\n");
+#if DISPLAY_HDMI_PRIMARY
+	if (!strlen(device.display_panel))
+		strlcpy(device.display_panel, DISPLAY_PANEL_HDMI,
+			sizeof(device.display_panel));
+#endif
 #if ENABLE_WBC
 		/* Wait if the display shutdown is in progress */
 		while(pm_app_display_shutdown_in_prgs());
diff --git a/app/aboot/mdtp.c b/app/aboot/mdtp.c
index f02eae9..136fab5 100644
--- a/app/aboot/mdtp.c
+++ b/app/aboot/mdtp.c
@@ -40,6 +40,7 @@
 #include <stdlib.h>
 #include <boot_verifier.h>
 #include <image_verify.h>
+#include <qtimer.h>
 #include "scm.h"
 #include "mdtp.h"
 #include "mdtp_fs.h"
@@ -74,7 +75,6 @@
 
 extern int check_aboot_addr_range_overlap(uintptr_t start, uint32_t size);
 int scm_random(uint32_t * rbuf, uint32_t  r_len);
-extern void mdelay(unsigned msecs);
 void free_mdtp_image(void);
 
 /********************************************************************************/
@@ -240,10 +240,10 @@
 
 /* Validate a hash table calculated per block of a given partition */
 static int verify_partition_block_hash(char *name,
-								uint64_t size,
-								uint32_t verify_num_blocks,
-								DIP_hash_table_entry_t *hash_table,
-								uint8_t *force_verify_block)
+									uint64_t size,
+									uint32_t verify_num_blocks,
+									DIP_hash_table_entry_t *hash_table,
+									uint8_t *force_verify_block)
 {
 	unsigned char digest[HASH_LEN]={0};
 	unsigned long long ptn = 0;
@@ -334,14 +334,14 @@
 
 /* Validate the partition parameters read from DIP */
 static int validate_partition_params(uint64_t size,
-						mdtp_fwlock_mode_t hash_mode,
-						uint32_t verify_ratio)
+									mdtp_fwlock_mode_t hash_mode,
+									uint32_t verify_ratio)
 {
 	if (size == 0 || size > (uint64_t)MDTP_FWLOCK_BLOCK_SIZE * (uint64_t)MAX_BLOCKS ||
-		hash_mode > MDTP_FWLOCK_MODE_FILES || verify_ratio > 100)
+			hash_mode > MDTP_FWLOCK_MODE_FILES || verify_ratio > 100)
 	{
 		dprintf(CRITICAL, "mdtp: validate_partition_params: error, size=%llu, hash_mode=%d, verify_ratio=%d\n",
-			size, hash_mode, verify_ratio);
+				size, hash_mode, verify_ratio);
 		return -1;
 	}
 
@@ -350,11 +350,11 @@
 
 /* Verify a given partitinon */
 static int verify_partition(char *name,
-						uint64_t size,
-						mdtp_fwlock_mode_t hash_mode,
-						uint32_t verify_num_blocks,
-						DIP_hash_table_entry_t *hash_table,
-						uint8_t *force_verify_block)
+							uint64_t size,
+							mdtp_fwlock_mode_t hash_mode,
+							uint32_t verify_num_blocks,
+							DIP_hash_table_entry_t *hash_table,
+							uint8_t *force_verify_block)
 {
 	if (hash_mode == MDTP_FWLOCK_MODE_SINGLE)
 	{
@@ -524,14 +524,14 @@
 			ptn = partition_get_offset(index);
 			if(ptn == 0) {
 				dprintf(CRITICAL, "ERROR: partition %s not found\n",
-					ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
+						ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
 				return -1;
 			}
 
 			if(mmc_read(ptn + ext_partition->image_size, (void *)(ext_partition->image_addr + ext_partition->image_size), ext_partition->page_size))
 			{
 				dprintf(CRITICAL, "ERROR: Cannot read %s image signature\n",
-					ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
+						ext_partition->partition == MDTP_PARTITION_BOOT ? "boot" : "recovery");
 				return -1;
 			}
 		}
@@ -570,8 +570,8 @@
 
 /* Verify all protected partitinons according to the DIP */
 static void verify_all_partitions(DIP_t *dip,
-								 mdtp_ext_partition_verification_t *ext_partition,
-								 verify_result_t *verify_result)
+								mdtp_ext_partition_verification_t *ext_partition,
+								verify_result_t *verify_result)
 {
 	int i;
 	int verify_failure = 0;
@@ -810,8 +810,8 @@
 	arch_invalidate_cache_range((addr_t)dec_dip, sizeof(DIP_t));
 
 	ret = mdtp_cipher_dip_cmd((uint8_t*)enc_dip, sizeof(DIP_t),
-								(uint8_t*)dec_dip, sizeof(DIP_t),
-								DIP_DECRYPT);
+							(uint8_t*)dec_dip, sizeof(DIP_t),
+							DIP_DECRYPT);
 	if (ret)
 	{
 		dprintf(CRITICAL, "mdtp: mdtp_tzbsp_dec_verify_DIP: ERROR, cannot cipher DIP\n");
@@ -856,8 +856,8 @@
 	arch_invalidate_cache_range((addr_t)enc_dip, sizeof(DIP_t));
 
 	ret = mdtp_cipher_dip_cmd((uint8_t*)dec_dip, sizeof(DIP_t),
-								(uint8_t*)enc_dip, sizeof(DIP_t),
-								DIP_ENCRYPT);
+							(uint8_t*)enc_dip, sizeof(DIP_t),
+							DIP_ENCRYPT);
 	if (ret)
 	{
 		dprintf(CRITICAL, "mdtp: mdtp_tzbsp_enc_hash_DIP: ERROR, cannot cipher DIP\n");
@@ -886,11 +886,7 @@
 	/* Disallow the CIPHER_DIP SCM by calling it MAX_CIPHER_DIP_SCM_CALLS times */
 	for (i=0; i<MAX_CIPHER_DIP_SCM_CALLS; i++)
 	{
-		if(mdtp_tzbsp_enc_hash_DIP(dip, dip) != 0)
-		{
-			/* Couldn't disallowd CIPHER_DIP SCM - stop device from booting */
-			display_error_msg(); /* This will never return */
-		}
+		mdtp_tzbsp_enc_hash_DIP(dip, dip);
 	}
 
 	free(dip);
@@ -947,7 +943,7 @@
 
 	//Bad size
 	if(validate_partition_params((uint64_t)MDTP_FWLOCK_BLOCK_SIZE * (uint64_t)MAX_BLOCKS + 1,
-		MDTP_FWLOCK_MODE_SINGLE, 1) != -1){
+			MDTP_FWLOCK_MODE_SINGLE, 1) != -1){
 		dprintf(INFO, "validate_partition_params_ut: [FAIL (2)].\n");
 		return -1;
 	}
@@ -969,7 +965,7 @@
 
 	//Unkown hashing mode
 	if(verify_partition("system", partition_size, BAD_HASH_MODE, verify_num_blocks,
-		&partition_hash_table, &partition_force_verify_block) != -1){
+			&partition_hash_table, &partition_force_verify_block) != -1){
 		dprintf(INFO, "verify_partition_ut: Failed Test 1.\n");
 		dprintf(INFO, "MDTP LK UT: verify_partition_ut [ FAIL ]\n");
 		return -1;
diff --git a/app/aboot/mdtp_fs.c b/app/aboot/mdtp_fs.c
index b848c7a..f52fda9 100644
--- a/app/aboot/mdtp_fs.c
+++ b/app/aboot/mdtp_fs.c
@@ -44,6 +44,63 @@
 static mdtp_image_t mdtp_img;
 
 /*---------------------------------------------------------
+ * Internal Functions
+ *-------------------------------------------------------*/
+
+static int mdtp_read_metadata(uint32_t offset){
+	int index = INVALID_PTN;
+	unsigned long long ptn = 0;
+	int i = 0;
+	uint32_t block_size = mmc_get_device_blocksize();
+
+	index = partition_get_index("mdtp");
+	if (index == 0) {
+		dprintf(CRITICAL, "ERROR: mdtp Partition table not found\n");
+		return -1;
+	}
+
+	ptn = partition_get_offset(index);
+	mmc_set_lun(partition_get_lun(index));
+
+	if (ptn == 0) {
+		dprintf(CRITICAL, "ERROR: mdtp Partition invalid\n");
+		return -1;
+	}
+
+	for(i = 0; i< MAX_PARAMS; i++) {
+		mdtp_img.meta_data.params[i] = MDTP_PARAM_UNSET_VALUE; //Initialize params for error check
+	}
+
+	uint8_t *base = memalign(block_size, ROUNDUP(MDTP_HEADER_LEN, block_size));
+	if (!base) {
+		dprintf(CRITICAL, "ERROR: mdtp malloc failed\n");
+		return -1;
+	}
+
+	// read image meta data
+	if (mmc_read(ptn+offset, (void*)base, MDTP_HEADER_LEN)) {
+		dprintf(CRITICAL, "ERROR: mdtp meta data read failed\n");
+		free(base);
+		return -1;
+	}
+
+	uint32_t params_size = MAX_PARAMS * sizeof(uint32_t);
+	uint32_t images_params_size = MAX_IMAGES*sizeof(mdtp_image_params_t);
+	memscpy(mdtp_img.meta_data.params, sizeof(mdtp_img.meta_data.params), base, params_size);
+	memscpy(mdtp_img.meta_data.image_params, META_DATA_PARTITION_LEN,
+			base + sizeof(mdtp_img.meta_data.params), images_params_size);
+
+	dprintf(INFO, "mdtp: metadata loaded\n");
+
+	free(base);
+	return 0;
+}
+
+static void mdtp_fs_set_param(mdtp_parameter_id_t param, uint32_t value){
+	mdtp_img.meta_data.params[param] = value;
+}
+
+/*---------------------------------------------------------
  * External Functions
  *-------------------------------------------------------*/
 
@@ -63,53 +120,90 @@
 	return mdtp_img.meta_data.params[param];
 }
 
-
 int mdtp_fs_init(){
-	int index = INVALID_PTN;
-	unsigned long long ptn = 0;
-	int i = 0;
-	uint32_t block_size = mmc_get_device_blocksize();
+	uint32_t i;
+	struct fbcon_config *fb_config = NULL;
+	mdtp_image_params_t image_params;
+	mdtp_image_t mdtp_image_sets_metadata;
+	uint32_t image_sets_num;
+	uint32_t metadata_offset = 0;
 
-	index = partition_get_index("mdtp");
-	if (index == 0) {
-		dprintf(CRITICAL, "ERROR: mdtp Partition table not found\n");
-		return 1;
+	// Read image sets metadata
+	if (mdtp_read_metadata(metadata_offset)){
+		dprintf(CRITICAL, "ERROR: failed to read image sets metadata\n");
+		return -1;
 	}
 
-	ptn = partition_get_offset(index);
-	mmc_set_lun(partition_get_lun(index));
-
-	if (ptn == 0) {
-		dprintf(CRITICAL, "ERROR: mdtp Partition invalid\n");
-		return 1;
+	// Verify that metadata version is supported
+	if (mdtp_fs_get_param(VERSION) != SUPPORTED_METADATA_VERSION){
+		dprintf(CRITICAL, "ERROR: metadata version is not supported: %d\n", mdtp_fs_get_param(VERSION));
+		return -1;
 	}
 
-	for(i = 0; i< MAX_PARAMS; i++) {
-		mdtp_img.meta_data.params[i] = -1; //Initiate params for errors check
+	// Verify that metadata version is as expected
+	if (mdtp_fs_get_param(TYPE) != IMAGE_SETS){
+		dprintf(CRITICAL, "ERROR: unexpected type for image sets metadata: %d\n", mdtp_fs_get_param(TYPE));
+		return -1;
 	}
 
-	uint8_t *base = memalign(block_size, ROUNDUP(MDTP_HEADER_LEN, block_size));
-	if (!base) {
-		dprintf(CRITICAL, "ERROR: mdtp malloc failed\n");
-		return 1;
+	image_sets_num = mdtp_fs_get_param(IMAGE_SETS_NUM);
+	if (image_sets_num < 1) {
+		dprintf(CRITICAL, "ERROR: invalid number of image sets: %d\n", image_sets_num);
+		return -1;
 	}
 
-	// read image meta data
-	if (mmc_read(ptn, (void*)base, MDTP_HEADER_LEN)) {
-		dprintf(CRITICAL, "ERROR: mdtp meta data read failed\n");
-		free(base);
-		return 1;
+	// Get screen configuration
+	fb_config = fbcon_display();
+
+	// Image sets are sorted by screen resolution (width, height), from low to high.
+	// We begin with the smallest image set, and check if bigger image sets also fit the screen.
+	image_params = mdtp_img.meta_data.image_params[0];
+
+	for (i=1; i<image_sets_num; i++){
+
+		//if both width and height still fit the screen, update image_params
+		if (mdtp_img.meta_data.image_params[i].width <= fb_config->width &&
+				mdtp_img.meta_data.image_params[i].height <= fb_config->height)
+		{
+			image_params = mdtp_img.meta_data.image_params[i];
+		}
+
+		// if we reached an image set in which the width is larger than
+		// the screen width, no point in checking additional image sets.
+		else if (mdtp_img.meta_data.image_params[i].width > fb_config->width)
+			break;
 	}
 
-	uint32_t params_size = MAX_PARAMS * sizeof(uint32_t);
-	uint32_t images_params_size = MAX_IMAGES*sizeof(mdtp_image_params_t);
-	memscpy(mdtp_img.meta_data.params, sizeof(mdtp_img.meta_data.params), base, params_size);
-	memscpy(mdtp_img.meta_data.image_params, META_DATA_PARTITION_LEN,
-			base + sizeof(mdtp_img.meta_data.params), images_params_size);
+	dprintf(INFO, "mdtp: image set offset: 0x%x\n", image_params.offset);
+	dprintf(INFO, "mdtp: image set width: %d, screen width: %d\n", image_params.width, fb_config->width);
+	dprintf(INFO, "mdtp: image set height: %d, screen height: %d\n", image_params.height, fb_config->height);
+
+	// Backup image sets metadata for required parameters
+	mdtp_image_sets_metadata = mdtp_img;
+
+	// Read images metadata
+	if (mdtp_read_metadata(image_params.offset)){
+		dprintf(CRITICAL, "ERROR: failed to read images metadata\n");
+		return -1;
+	}
+
+	// Verify that metadata version is supported
+	if (mdtp_fs_get_param(VERSION) != SUPPORTED_METADATA_VERSION){
+		dprintf(CRITICAL, "ERROR: metadata version is not supported: %d\n", mdtp_fs_get_param(VERSION));
+		return -1;
+	}
+
+	// Verify that metadata version is as expected
+	if (mdtp_fs_get_param(TYPE) != IMAGES){
+		dprintf(CRITICAL, "ERROR: unexpected type for images metadata: %d\n", mdtp_fs_get_param(TYPE));
+		return -1;
+	}
+
+	// Copy eFuse from image sets metadata
+	mdtp_fs_set_param(VIRTUAL_FUSE, mdtp_image_sets_metadata.meta_data.params[VIRTUAL_FUSE]);
 
 	dprintf(INFO, "mdtp: mdtp_img loaded\n");
 
-	free(base);
 	return 0;
 }
 
diff --git a/app/aboot/mdtp_fs.h b/app/aboot/mdtp_fs.h
index 33ddf55..e131c12 100644
--- a/app/aboot/mdtp_fs.h
+++ b/app/aboot/mdtp_fs.h
@@ -29,19 +29,26 @@
 #ifndef MDTP_FS_H
 #define MDTP_FS_H
 
-#define MAX_IMAGES					(40)
-#define MDTP_HEADER_LEN 			(4096)
-#define META_DATA_PARTITION_LEN		(2048)
-#define MAX_PARAMS 					(512)
+#define MAX_IMAGES                      (40)
+#define MDTP_HEADER_LEN                 (4096)
+#define META_DATA_PARTITION_LEN         (2048)
+#define MAX_PARAMS                      (512)
+#define MDTP_PARAM_UNSET_VALUE          (111)
+#define SUPPORTED_METADATA_VERSION      (1)
+
 /*
-MDTP header layout:
+MDTP image layout:
+-The mdtp image file contains two layers that both include mdtp_img headers:
+	1. The first header includes the image sets metadata.
+	2. Once we decided which image set we would like to display, we read the metadata
+	   of that specific image set (contains metadata of the actual images).
 -The mdtp_img header is a fixed length of 4096 Bytes.
--The mdtp_img header is devided into 2 partitions:
+-The mdtp_img header is divided into 2 partitions:
 	1.MDTP parameters (eFuse, digit-space, etc..)
-	2.Images meta-data (offset, width, height)
+	2.Images/image sets meta-data (offset, width, height)
 -Each partition size is 2048 Bytes.
--Each parameter is 4 Bytes long, 512 params MAX.
--Each meta-data part (offset/width/height) is 4 Bytes long.
+-Each parameter is 4 Bytes long, 512 params max.
+-Each meta-data parameter (offset/width/height) is 4 Bytes long.
 */
 
 
@@ -76,7 +83,9 @@
 	PIN_UNSELECTED_6 = 24, PIN_UNSELECTED_7 = 25,
 	PIN_UNSELECTED_8 = 26, PIN_UNSELECTED_9 = 27} mdtp_image_id_t;
 
-typedef enum {VIRTUAL_FUSE = 0, DIGIT_SPACE = 1} mdtp_parameter_id_t ;
+typedef enum {VIRTUAL_FUSE = 0, DIGIT_SPACE = 1, VERSION = 2, TYPE = 3, IMAGE_SETS_NUM = 4} mdtp_parameter_id_t;
+
+typedef enum {IMAGES = 1, IMAGE_SETS = 2} mdtp_metadata_type_t;
 
 /*---------------------------------------------------------
  * External Functions
diff --git a/app/aboot/mdtp_fuse.c b/app/aboot/mdtp_fuse.c
index 439fb73..44d2eb5 100644
--- a/app/aboot/mdtp_fuse.c
+++ b/app/aboot/mdtp_fuse.c
@@ -43,7 +43,7 @@
 
 typedef union
 {
-    struct {
+	struct {
 		uint8_t enable1       : 1;
 		uint8_t disable1      : 1;
 		uint8_t enable2       : 1;
@@ -79,7 +79,7 @@
 #define SHK_FUSE           0x02
 #define DEBUG_FUSE         0x04
 
-    /* Make sure we only read the test mode once */
+	/* Make sure we only read the test mode once */
 	if (test_mode_set)
 		return test_mode;
 
@@ -95,7 +95,7 @@
 	{
 		dprintf(CRITICAL, "mdtp: is_test_mode: qsee_get_secure_state returned error: %d, status.value[0]: %d\n", ret, status_low);
 		test_mode = 0;
-    }
+	}
 
 	test_mode_set = 1;
 	dprintf(INFO, "mdtp: is_test_mode: test mode is set to %d\n", test_mode);
@@ -111,7 +111,7 @@
 static int read_metadata(metadata_t *metadata)
 {
 	int eFuse = mdtp_fs_get_param(VIRTUAL_FUSE);
-	if(eFuse == -1){ //Error initiating eFuse
+	if(eFuse == MDTP_PARAM_UNSET_VALUE){      //Error initializing eFuse
 		dprintf(CRITICAL, "mdtp: eFuse reading error\n");
 		return -1;
 	}
@@ -215,8 +215,8 @@
 	}
 
 	if (!(eFuses.bitwise.enable1 && !eFuses.bitwise.disable1) &&
-		!(eFuses.bitwise.enable2 && !eFuses.bitwise.disable2) &&
-		!(eFuses.bitwise.enable3 && !eFuses.bitwise.disable3))
+			!(eFuses.bitwise.enable2 && !eFuses.bitwise.disable2) &&
+			!(eFuses.bitwise.enable3 && !eFuses.bitwise.disable3))
 	{
 		*enabled = 0;
 	}
diff --git a/app/aboot/mdtp_ui.c b/app/aboot/mdtp_ui.c
index fafb787..ed14e65 100644
--- a/app/aboot/mdtp_ui.c
+++ b/app/aboot/mdtp_ui.c
@@ -33,10 +33,11 @@
 #include <partition_parser.h>
 #include <stdlib.h>
 #include <string.h>
+#include <display_menu.h>
+#include <qtimer.h>
 #include "mdtp.h"
 #include "mdtp_defs.h"
 #include "mdtp_fs.h"
-#include <display_menu.h>
 
 // Image releative locations
 #define ERROR_MESSAGE_RELATIVE_Y_LOCATION   (0.18)
@@ -54,15 +55,14 @@
 
 #define CENTER_IMAGE_ON_X_AXIS(image_width,screen_width)         (((screen_width)-(image_width))/2)
 
-extern void mdelay(unsigned msecs);
 extern uint32_t target_volume_up();
 extern uint32_t target_volume_down();
 extern int msm_display_on();
 
 struct mdtp_fbimage {
-    uint32_t width;
-    uint32_t height;
-    uint8_t image[MDTP_MAX_IMAGE_SIZE];
+	uint32_t width;
+	uint32_t height;
+	uint8_t image[MDTP_MAX_IMAGE_SIZE];
 };
 
 /*----------------------------------------------------------------------------
@@ -71,6 +71,7 @@
 
 static uint32_t g_pin_frames_x_location[MDTP_PIN_LEN] = {0};
 static uint32_t g_pin_frames_y_location = 0;
+static bool g_diplay_pin = false;
 
 static bool g_initial_screen_displayed = false;
 
@@ -130,9 +131,9 @@
 		unsigned bytes_per_bpp = ((fb_config->bpp) / BITS_PER_BYTE);
 
 		if (mmc_read(ptn+offset, (void*)base, ROUNDUP(width*height*bytes_per_bpp, block_size))) {
-				fbcon_clear();
-				dprintf(CRITICAL, "ERROR: mdtp image read failed\n");
-				return NULL;
+			fbcon_clear();
+			dprintf(CRITICAL, "ERROR: mdtp image read failed\n");
+			return NULL;
 		}
 
 		logo->width = width;
@@ -167,7 +168,7 @@
 
 	if (fb_config)
 	{
-	    image_base = (y *(fb_config->width));
+		image_base = (y *(fb_config->width));
 		bytes_per_bpp = ((fb_config->bpp) / BITS_PER_BYTE);
 
 		unsigned count = fb_config->width*section_height;
@@ -177,8 +178,8 @@
 	}
 	else
 	{
-	    dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
-	    display_error_msg(); /* This will never return */
+		dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
+		display_error_msg(); /* This will never return */
 	}
 }
 
@@ -189,13 +190,13 @@
  */
 static void fbcon_putImage_in_location(struct mdtp_fbimage *fbimg, uint32_t x, uint32_t y)
 {
-    unsigned i = 0;
-    unsigned bytes_per_bpp;
-    unsigned image_base;
-    unsigned width, pitch, height;
-    unsigned char *logo_base = NULL;
+	unsigned i = 0;
+	unsigned bytes_per_bpp;
+	unsigned image_base;
+	unsigned width, pitch, height;
+	unsigned char *logo_base = NULL;
 
-    if (!fb_config) {
+	if (!fb_config) {
 		dprintf(CRITICAL,"ERROR: NULL configuration, image cannot be displayed\n");
 		return;
 	}
@@ -206,8 +207,8 @@
 		logo_base = (unsigned char *)fbimg->image;
 	}
 	else {
-	    dprintf(CRITICAL,"ERROR: invalid image struct\n");
-	    return;
+		dprintf(CRITICAL,"ERROR: invalid image struct\n");
+		return;
 	}
 
 	bytes_per_bpp = ((fb_config->bpp) / BITS_PER_BYTE);
@@ -222,16 +223,16 @@
 		}
 
 		if (fbimg->width > fb_config->width || fbimg->height > fb_config->height ||
-				 (x > (fb_config->width - fbimg->width)) || (y > (fb_config->height - fbimg->height)))
+				(x > (fb_config->width - fbimg->width)) || (y > (fb_config->height - fbimg->height)))
 		{
-		    dprintf(CRITICAL,"ERROR: invalid image size, larger than the screen or exceeds its margins\n");
-		    return;
+			dprintf(CRITICAL,"ERROR: invalid image size, larger than the screen or exceeds its margins\n");
+			return;
 		}
 
 		image_base = ( (y *(fb_config->width)) + x);
 		for (i = 0; i < height; i++) {
 			memcpy (fb_config->base + ((image_base + (i * (fb_config->width))) * bytes_per_bpp),
-				logo_base + ((height - 1 - i) * pitch * bytes_per_bpp), width * bytes_per_bpp);
+					logo_base + ((height - 1 - i) * pitch * bytes_per_bpp), width * bytes_per_bpp);
 		}
 	}
 	else
@@ -254,26 +255,26 @@
  */
 static int display_error_message()
 {
-    struct mdtp_fbimage *fbimg;
+	struct mdtp_fbimage *fbimg;
 
-    if (fb_config)
+	if (fb_config)
 	{
-        uint32_t x = CENTER_IMAGE_ON_X_AXIS(get_image_width(ALERT_MESSAGE),fb_config->width);
+		uint32_t x = CENTER_IMAGE_ON_X_AXIS(get_image_width(ALERT_MESSAGE),fb_config->width);
 		uint32_t y = ((fb_config->height)*ERROR_MESSAGE_RELATIVE_Y_LOCATION);
-        fbimg = mdtp_read_mmc_image(get_image_offset(ALERT_MESSAGE),get_image_width(ALERT_MESSAGE), get_image_height(ALERT_MESSAGE));
-        if (NULL == fbimg)
-        {
-            dprintf(CRITICAL,"ERROR: failed to read error image from mmc\n");
-            return -1;
-        }
+		fbimg = mdtp_read_mmc_image(get_image_offset(ALERT_MESSAGE),get_image_width(ALERT_MESSAGE), get_image_height(ALERT_MESSAGE));
+		if (NULL == fbimg)
+		{
+			dprintf(CRITICAL,"ERROR: failed to read error image from mmc\n");
+			return -1;
+		}
 
-        fbcon_putImage_in_location(fbimg, x, y);
+		fbcon_putImage_in_location(fbimg, x, y);
 
 		return 0;
 	}
 	else
 	{
-	    dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
+		dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
 		return -1;
 	}
 }
@@ -284,24 +285,24 @@
  */
 static void display_image(uint32_t offset, uint32_t width, uint32_t height, uint32_t x, uint32_t y)
 {
-    struct mdtp_fbimage *fbimg;
+	struct mdtp_fbimage *fbimg;
 
-    if (fb_config)
-    {
-        fbimg = mdtp_read_mmc_image(offset, width, height);
-        if (NULL == fbimg)
-        {
-            dprintf(CRITICAL,"ERROR: failed to read image from mmc\n");
-            display_error_msg(); /* This will never return */
-        }
+	if (fb_config)
+	{
+		fbimg = mdtp_read_mmc_image(offset, width, height);
+		if (NULL == fbimg)
+		{
+			dprintf(CRITICAL,"ERROR: failed to read image from mmc\n");
+			display_error_msg(); /* This will never return */
+		}
 
-        fbcon_putImage_in_location(fbimg, x, y);
-    }
-    else
-    {
-        dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
-        display_error_msg(); /* This will never return */
-    }
+		fbcon_putImage_in_location(fbimg, x, y);
+	}
+	else
+	{
+		dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
+		display_error_msg(); /* This will never return */
+	}
 }
 
 /**
@@ -329,7 +330,7 @@
  */
 static void display_invalid_pin()
 {
-    uint32_t x = CENTER_IMAGE_ON_X_AXIS(get_image_width(MAINTEXT_INCORRECTPIN),fb_config->width);
+	uint32_t x = CENTER_IMAGE_ON_X_AXIS(get_image_width(MAINTEXT_INCORRECTPIN),fb_config->width);
 	uint32_t y = (fb_config->height)*MAIN_TEXT_RELATIVE_Y_LOCATION;
 
 	display_image(get_image_offset(MAINTEXT_INCORRECTPIN), get_image_width(MAINTEXT_INCORRECTPIN), get_image_height(MAINTEXT_INCORRECTPIN), x, y);
@@ -340,7 +341,7 @@
  */
 static void display_digits_instructions()
 {
-    uint32_t x = CENTER_IMAGE_ON_X_AXIS(get_image_width(PINTEXT),fb_config->width);
+	uint32_t x = CENTER_IMAGE_ON_X_AXIS(get_image_width(PINTEXT),fb_config->width);
 	uint32_t y = (fb_config->height)*PIN_TEXT_RELATIVE_Y_LOCATION;
 
 	display_image(get_image_offset(PINTEXT), get_image_width(PINTEXT), get_image_height(PINTEXT), x, y);
@@ -351,8 +352,8 @@
  */
 static void clear_digits_instructions()
 {
-    uint32_t y = (fb_config->height)*PIN_TEXT_RELATIVE_Y_LOCATION;
-    fbcon_clear_section(y, get_image_height(PINTEXT));
+	uint32_t y = (fb_config->height)*PIN_TEXT_RELATIVE_Y_LOCATION;
+	fbcon_clear_section(y, get_image_height(PINTEXT));
 }
 
 /**
@@ -360,8 +361,11 @@
  */
 static void display_digit(uint32_t x, uint32_t y, uint32_t digit)
 {
-    display_image(get_image_offset(PIN_UNSELECTED_0 + digit),
-    get_image_width(PIN_UNSELECTED_0 + digit), get_image_height(PIN_UNSELECTED_0 + digit), x, y);
+	if (g_diplay_pin == false)
+		return;
+
+	display_image(get_image_offset(PIN_UNSELECTED_0 + digit),
+			get_image_width(PIN_UNSELECTED_0 + digit), get_image_height(PIN_UNSELECTED_0 + digit), x, y);
 }
 
 /**
@@ -369,6 +373,9 @@
  */
 static void display_selected_digit(uint32_t x, uint32_t y, uint32_t digit)
 {
+	if (g_diplay_pin == false)
+		return;
+
 	display_image(get_image_offset(PIN_SELECTED_0 + digit),
 			get_image_width(PIN_SELECTED_0 + digit),
 			get_image_height(PIN_SELECTED_0 + digit), x, y);
@@ -379,7 +386,7 @@
  */
 static void display_ok_button()
 {
-    uint32_t ok_x = CENTER_IMAGE_ON_X_AXIS(get_image_width(BTN_OK_OFF),fb_config->width);
+	uint32_t ok_x = CENTER_IMAGE_ON_X_AXIS(get_image_width(BTN_OK_OFF),fb_config->width);
 	uint32_t ok_y = (fb_config->height)*OK_BUTTON_RELATIVE_Y_LOCATION;
 
 	display_image(get_image_offset(BTN_OK_OFF), get_image_width(BTN_OK_OFF),get_image_height(BTN_OK_OFF), ok_x, ok_y);
@@ -390,7 +397,7 @@
  */
 static void display_selected_ok_button()
 {
-    uint32_t ok_x = CENTER_IMAGE_ON_X_AXIS(get_image_width(BTN_OK_ON),fb_config->width);
+	uint32_t ok_x = CENTER_IMAGE_ON_X_AXIS(get_image_width(BTN_OK_ON),fb_config->width);
 	uint32_t ok_y = (fb_config->height)*OK_BUTTON_RELATIVE_Y_LOCATION;
 
 	display_image(get_image_offset(BTN_OK_ON), get_image_width(BTN_OK_ON), get_image_height(BTN_OK_ON),  ok_x, ok_y);
@@ -402,7 +409,7 @@
  */
 static void display_pin_instructions()
 {
-    uint32_t x = CENTER_IMAGE_ON_X_AXIS(get_image_width(ACCEPTEDIT_TEXT),fb_config->width);
+	uint32_t x = CENTER_IMAGE_ON_X_AXIS(get_image_width(ACCEPTEDIT_TEXT),fb_config->width);
 	uint32_t y = (fb_config->height)*OK_TEXT_RELATIVE_Y_LOCATION;
 
 	display_image(get_image_offset(ACCEPTEDIT_TEXT), get_image_width(ACCEPTEDIT_TEXT), get_image_height(ACCEPTEDIT_TEXT), x, y);
@@ -413,7 +420,7 @@
  */
 static void clear_pin_message()
 {
-    uint32_t y = (fb_config->height)*OK_TEXT_RELATIVE_Y_LOCATION;
+	uint32_t y = (fb_config->height)*OK_TEXT_RELATIVE_Y_LOCATION;
 
 	fbcon_clear_section(y,get_image_height(ACCEPTEDIT_TEXT));
 }
@@ -442,7 +449,7 @@
 		fbcon_clear();
 
 		if (display_error_message())
-		    display_error_msg(); /* This will never return */
+			display_error_msg(); /* This will never return */
 		display_initial_delay();
 
 		mdelay(INITIAL_DELAY_MSECONDS);
@@ -450,16 +457,26 @@
 		g_pin_frames_y_location = ((fb_config->height)*PIN_RELATIVE_Y_LOCATION);
 
 		uint32_t total_pin_length = pin_length*get_image_width(PIN_UNSELECTED_0) + mdtp_fs_get_param(DIGIT_SPACE)*(pin_length - 1);
-		uint32_t complete_pin_centered = (fb_config->width - total_pin_length)/2;
 
-		for (uint32_t i=0; i<pin_length; i++)
+		if (fb_config->width > total_pin_length)
 		{
-			g_pin_frames_x_location[i] = complete_pin_centered + i*(mdtp_fs_get_param(DIGIT_SPACE) + get_image_width(PIN_UNSELECTED_0));
+			g_diplay_pin = true;
+
+			uint32_t complete_pin_centered = (fb_config->width - total_pin_length)/2;
+
+			for (uint32_t i=0; i<pin_length; i++)
+			{
+				g_pin_frames_x_location[i] = complete_pin_centered + i*(mdtp_fs_get_param(DIGIT_SPACE) + get_image_width(PIN_UNSELECTED_0));
+			}
+
+			for (uint32_t i=0; i<pin_length; i++)
+			{
+				display_digit(g_pin_frames_x_location[i], g_pin_frames_y_location, 0);
+			}
 		}
-
-		for (uint32_t i=0; i<pin_length; i++)
+		else
 		{
-			display_digit(g_pin_frames_x_location[i], g_pin_frames_y_location, 0);
+			dprintf(CRITICAL,"ERROR: screen is not wide enough, PIN digits can't be displayed\n");
 		}
 
 		display_ok_button();
@@ -468,8 +485,8 @@
 	}
 	else
 	{
-	    dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
-	    display_error_msg(); /* This will never return */
+		dprintf(CRITICAL,"ERROR: fbcon_config struct is NULL\n");
+		display_error_msg(); /* This will never return */
 	}
 }
 
@@ -574,12 +591,12 @@
  */
 void display_invalid_pin_msg()
 {
-    clear_pin_message();
-    display_ok_button();
+	clear_pin_message();
+	display_ok_button();
 
-    display_invalid_pin();
+	display_invalid_pin();
 
-    mdelay(INVALID_PIN_DELAY_MSECONDS);
+	mdelay(INVALID_PIN_DELAY_MSECONDS);
 }
 
 /**
diff --git a/dev/qpnp_wled/include/qpnp_wled.h b/dev/qpnp_wled/include/qpnp_wled.h
index 64e85e0..d90ca0b 100644
--- a/dev/qpnp_wled/include/qpnp_wled.h
+++ b/dev/qpnp_wled/include/qpnp_wled.h
@@ -47,8 +47,11 @@
 #define QPNP_WLED_VLOOP_COMP_RES(b)            (b + 0x55)
 #define QPNP_WLED_VLOOP_COMP_GM(b)             (b + 0x56)
 #define QPNP_WLED_PSM_CTRL(b)                  (b + 0x5B)
-#define QPNP_WLED_TEST4(b)		       (b + 0xE5)
+#define QPNP_WLED_TEST4(b)                     (b + 0xE5)
+#define QPNP_WLED_CTRL_SPARE_REG(b)            (b + 0xDF)
+#define QPNP_WLED_REF_7P7_TRIM_REG(b)          (b + 0xF2)
 
+#define QPNP_WLED_7P7_TRIM_MASK                0xF
 #define QPNP_WLED_EN_MASK                      0x7F
 #define QPNP_WLED_EN_SHIFT                     7
 #define QPNP_WLED_FDBK_OP_MASK                 0xF8
@@ -183,6 +186,19 @@
 
 #define PWRDN_DLY2_MASK                        0x3
 
+#define NUM_SUPPORTED_AVDD_VOLTAGES 		   6
+
+/* Supported values  7900, 7600, 7300, 6400, 6100, 5800 */
+#if TARGET_QPNP_WLED_AVDD_DEFAULT_VOLTAGE_MV
+#define QPNP_WLED_AVDD_DEFAULT_VOLTAGE_MV	   TARGET_QPNP_WLED_AVDD_DEFAULT_VOLTAGE_MV
+#else
+#define QPNP_WLED_AVDD_DEFAULT_VOLTAGE_MV	   7600
+#endif
+
+#define QPNP_WLED_AVDD_MIN_TRIM_VALUE          0x0
+#define QPNP_WLED_AVDD_MAX_TRIM_VALUE          0xF
+#define QPNP_WLED_AVDD_SET_BIT                 BIT(4)
+
 /* output feedback mode */
 enum qpnp_wled_fdbk_op {
        QPNP_WLED_FDBK_AUTO,
diff --git a/dev/qpnp_wled/qpnp_wled.c b/dev/qpnp_wled/qpnp_wled.c
index 3aa41f8..ad2f5d5 100644
--- a/dev/qpnp_wled/qpnp_wled.c
+++ b/dev/qpnp_wled/qpnp_wled.c
@@ -34,6 +34,18 @@
 #include <pm8x41_wled.h>
 #include <qtimer.h>
 
+static int qpnp_wled_avdd_target_voltages[NUM_SUPPORTED_AVDD_VOLTAGES] = {
+	7900, 7600, 7300, 6400, 6100, 5800,
+};
+
+static uint8_t qpnp_wled_ovp_reg_settings[NUM_SUPPORTED_AVDD_VOLTAGES] = {
+	0x0, 0x0, 0x1, 0x2, 0x2, 0x3,
+};
+
+static int qpnp_wled_avdd_trim_adjustments[NUM_SUPPORTED_AVDD_VOLTAGES] = {
+	3, 0, -2, 7, 3, 3,
+};
+
 static int fls(uint16_t n)
 {
 	int i = 0;
@@ -311,6 +323,44 @@
 	reg |= temp;
 	pm8x41_wled_reg_write(QPNP_WLED_OVP_REG(wled->ctrl_base), reg);
 
+	if (wled->disp_type_amoled) {
+		for (i = 0; i < NUM_SUPPORTED_AVDD_VOLTAGES; i++) {
+			if (QPNP_WLED_AVDD_DEFAULT_VOLTAGE_MV == qpnp_wled_avdd_target_voltages[i])
+				break;
+		}
+		if (i == NUM_SUPPORTED_AVDD_VOLTAGES)
+		{
+			dprintf(CRITICAL, "Invalid avdd target voltage specified \n");
+			return ERR_NOT_VALID;
+		}
+		/* Update WLED_OVP register based on desired target voltage */
+		reg = qpnp_wled_ovp_reg_settings[i];
+		pm8x41_wled_reg_write(QPNP_WLED_OVP_REG(wled->ctrl_base), reg);
+		/* Update WLED_TRIM register based on desired target voltage */
+		reg = pm8x41_wled_reg_read(
+			QPNP_WLED_REF_7P7_TRIM_REG(wled->ctrl_base));
+		reg += qpnp_wled_avdd_trim_adjustments[i];
+		if ((int8_t)reg < QPNP_WLED_AVDD_MIN_TRIM_VALUE)
+			reg = QPNP_WLED_AVDD_MIN_TRIM_VALUE;
+		else if((int8_t)reg > QPNP_WLED_AVDD_MAX_TRIM_VALUE)
+			reg = QPNP_WLED_AVDD_MAX_TRIM_VALUE;
+
+		rc = qpnp_wled_sec_access(wled, wled->ctrl_base);
+		if (rc)
+			return rc;
+
+		temp = pm8x41_wled_reg_read(
+			QPNP_WLED_REF_7P7_TRIM_REG(wled->ctrl_base));
+		temp &= ~QPNP_WLED_7P7_TRIM_MASK;
+		temp |= (reg & QPNP_WLED_7P7_TRIM_MASK);
+		pm8x41_wled_reg_write(QPNP_WLED_REF_7P7_TRIM_REG(wled->ctrl_base), temp);
+		/* Write to spare to avoid reconfiguration in HLOS */
+		reg = pm8x41_wled_reg_read(
+			QPNP_WLED_CTRL_SPARE_REG(wled->ctrl_base));
+		reg |= QPNP_WLED_AVDD_SET_BIT;
+		pm8x41_wled_reg_write(QPNP_WLED_CTRL_SPARE_REG(wled->ctrl_base), reg);
+	}
+
 	/* Configure the MODULATION register */
 	if (wled->mod_freq_khz <= QPNP_WLED_MOD_FREQ_1200_KHZ) {
 		wled->mod_freq_khz = QPNP_WLED_MOD_FREQ_1200_KHZ;
diff --git a/include/dev/flash.h b/include/dev/flash.h
index 9c41561..f908db8 100644
--- a/include/dev/flash.h
+++ b/include/dev/flash.h
@@ -77,6 +77,8 @@
 {
 	return flash_read_ext(ptn, 0, offset, data, bytes);
 }
+
+unsigned flash_num_pages_per_blk(void);
 unsigned flash_page_size(void);
 unsigned flash_block_size(void);
 unsigned flash_spare_size(void);
diff --git a/include/target.h b/include/target.h
index e0a0264..d0d830d 100644
--- a/include/target.h
+++ b/include/target.h
@@ -70,6 +70,7 @@
 
 const char * target_usb_controller();
 void target_usb_phy_reset(void);
+void target_usb_phy_sec_reset(void);
 void target_usb_phy_mux_configure(void);
 target_usb_iface_t * target_usb30_init();
 bool target_is_cdp_qvga();
diff --git a/lib/heap/heap.c b/lib/heap/heap.c
index a4835f9..2f41f6c 100644
--- a/lib/heap/heap.c
+++ b/lib/heap/heap.c
@@ -156,19 +156,19 @@
 // nearby ones if possible. Returns base of whatever chunk it became in the list.
 static struct free_heap_chunk *heap_insert_free_chunk(struct free_heap_chunk *chunk)
 {
-#if DEBUGLEVEL > INFO
+#if DEBUG_HEAP
 	vaddr_t chunk_end = (vaddr_t)chunk + chunk->len;
+	dprintf(CRITICAL,"%s: chunk ptr %p, size 0x%lx, chunk_end 0x%x\n",
+				__FUNCTION__, chunk, chunk->len, chunk_end);
 #endif
 
-//	dprintf("%s: chunk ptr %p, size 0x%lx, chunk_end 0x%x\n", __FUNCTION__, chunk, chunk->len, chunk_end);
-
 	struct free_heap_chunk *next_chunk;
 	struct free_heap_chunk *last_chunk;
 
 	// walk through the list, finding the node to insert before
 	list_for_every_entry(&theheap.free_list, next_chunk, struct free_heap_chunk, node) {
 		if (chunk < next_chunk) {
-			DEBUG_ASSERT(chunk_end <= (vaddr_t)next_chunk);
+			DEBUG_ASSERT(((vaddr_t)chunk + chunk->len) <= (vaddr_t)next_chunk);
 
 			list_add_before(&next_chunk->node, &chunk->node);
 
diff --git a/platform/msm8952/include/platform/iomap.h b/platform/msm8952/include/platform/iomap.h
index 8643113..5b9bab8 100644
--- a/platform/msm8952/include/platform/iomap.h
+++ b/platform/msm8952/include/platform/iomap.h
@@ -163,7 +163,7 @@
  * as device memory, define the start address
  * and size in MB
  */
-#define RPMB_SND_RCV_BUF            0x90000000
+#define RPMB_SND_RCV_BUF            0xA0000000
 #define RPMB_SND_RCV_BUF_SZ         0x1
 
 /* QSEECOM: Secure app region notification */
diff --git a/platform/msm8952/platform.c b/platform/msm8952/platform.c
index df7bbfa..242f4f4 100644
--- a/platform/msm8952/platform.c
+++ b/platform/msm8952/platform.c
@@ -66,7 +66,7 @@
 	{    MSM_IOMAP_BASE,        MSM_IOMAP_BASE,          MSM_IOMAP_SIZE,         IOMAP_MEMORY},
 	{    APPS_SS_BASE,          APPS_SS_BASE,            APPS_SS_SIZE,           IOMAP_MEMORY},
 	{    MSM_SHARED_IMEM_BASE,  MSM_SHARED_IMEM_BASE,    1,                      COMMON_MEMORY},
-	{    SCRATCH_ADDR,          SCRATCH_ADDR,            512,                    SCRATCH_MEMORY},
+	{    SCRATCH_ADDR,          SCRATCH_ADDR,            511,                    SCRATCH_MEMORY},
 	{    MIPI_FB_ADDR,          MIPI_FB_ADDR,            20,                     COMMON_MEMORY},
 	{    RPMB_SND_RCV_BUF,      RPMB_SND_RCV_BUF,        RPMB_SND_RCV_BUF_SZ,    IOMAP_MEMORY},
 };
diff --git a/platform/msm8996/acpuclock.c b/platform/msm8996/acpuclock.c
index 7ed7ff6..c74e2e6 100644
--- a/platform/msm8996/acpuclock.c
+++ b/platform/msm8996/acpuclock.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -208,6 +208,40 @@
 	writel(reg, GCC_USB30_GDSCR);
 }
 
+/* enables usb20 clocks */
+void clock_usb20_init(void)
+{
+	int ret;
+
+	ret = clk_get_set_enable("usb20_noc_usb20_clk", 0, true);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set usb20_noc_clk. ret = %d\n", ret);
+		ASSERT(0);
+	}
+
+	ret = clk_get_set_enable("usb20_master_clk", 120000000, true);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set usb20_master_clk. ret = %d\n", ret);
+		ASSERT(0);
+	}
+
+	ret = clk_get_set_enable("usb20_mock_utmi_clk", 60000000, true);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set usb20_mock_utmi_clk ret = %d\n", ret);
+		ASSERT(0);
+	}
+
+	ret = clk_get_set_enable("usb20_sleep_clk", 0, true);
+	if(ret)
+	{
+		dprintf(CRITICAL, "failed to set usb2_sleep_clk ret = %d\n", ret);
+		ASSERT(0);
+	}
+}
+
 /* enables usb30 clocks */
 void clock_usb30_init(void)
 {
@@ -653,4 +687,45 @@
 		dprintf(CRITICAL, "Failed to enable %s\n", clk_name);
 		return;
 	}
-}
\ No newline at end of file
+}
+
+void hdmi_ahb_core_clk_enable(void)
+{
+	int ret;
+
+	/* Configure hdmi ahb clock */
+	ret = clk_get_set_enable("hdmi_ahb_clk", 0, 1);
+	if(ret) {
+		dprintf(CRITICAL, "failed to set hdmi_ahb_clk ret = %d\n", ret);
+		ASSERT(0);
+	}
+
+	/* Configure hdmi core clock */
+	ret = clk_get_set_enable("hdmi_core_clk", 19200000, 1);
+	if(ret) {
+		dprintf(CRITICAL, "failed to set hdmi_core_clk ret = %d\n", ret);
+		ASSERT(0);
+	}
+}
+
+void hdmi_pixel_clk_enable(uint32_t rate) {
+	int ret;
+
+	/* Configure hdmi pixel clock */
+	ret = clk_get_set_enable("hdmi_extp_clk", rate, 1);
+	if(ret) {
+		dprintf(CRITICAL, "failed to set hdmi_extp_clk ret = %d\n", ret);
+		ASSERT(0);
+	}
+}
+
+void hdmi_pixel_clk_disable(void)
+{
+	clk_disable(clk_get("hdmi_extp_clk"));
+}
+
+void hdmi_core_ahb_clk_disable(void)
+{
+	clk_disable(clk_get("hdmi_core_clk"));
+	clk_disable(clk_get("hdmi_ahb_clk"));
+}
diff --git a/platform/msm8996/include/platform/clock.h b/platform/msm8996/include/platform/clock.h
index 01a551e..f2b0455 100644
--- a/platform/msm8996/include/platform/clock.h
+++ b/platform/msm8996/include/platform/clock.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -58,6 +58,13 @@
 #define MMSS_MMAGIC_AHB_CBCR            REG_MM(0x5024)
 #define SMMU_MDP_AHB_CBCR               REG_MM(0x2454)
 #define MDSS_AHB_CBCR                   REG_MM(0x2308)
+#define MDSS_HDMI_AHB_CBCR              REG_MM(0x230C)
+#define MDSS_HDMI_CBCR                  REG_MM(0x2338)
+#define MDSS_EXTPCLK_CBCR               REG_MM(0x2324)
+#define EXTPCLK_CMD_RCGR                REG_MM(0x2060)
+#define EXTPCLK_CFG_RCGR                REG_MM(0x2064)
+#define HDMI_CMD_RCGR                   REG_MM(0x2100)
+#define HDMI_CFG_RCGR                   REG_MM(0x2104)
 
 #define AXI_CMD_RCGR                    REG_MM(0x5040)
 #define AXI_CFG_RCGR                    REG_MM(0x5044)
@@ -111,6 +118,7 @@
 void clock_ce_enable(uint8_t instance);
 void clock_ce_disable(uint8_t instance);
 void clock_usb30_init(void);
+void clock_usb20_init(void);
 void clock_reset_usb_phy();
 
 void mmss_dsi_clock_enable(uint32_t cfg_rcgr, uint32_t dual_dsi);
@@ -125,4 +133,8 @@
 void video_gdsc_disable();
 void clock_config_blsp_i2c(uint8_t blsp_id, uint8_t qup_id);
 
+void hdmi_ahb_core_clk_enable(void);
+void hdmi_pixel_clk_enable(uint32_t rate);
+void hdmi_pixel_clk_disable(void);
+void hdmi_core_ahb_clk_disable(void);
 #endif
diff --git a/platform/msm8996/include/platform/iomap.h b/platform/msm8996/include/platform/iomap.h
index 2fb9c8a..63dca93 100644
--- a/platform/msm8996/include/platform/iomap.h
+++ b/platform/msm8996/include/platform/iomap.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -75,15 +75,33 @@
 #define GCC_BLSP2_QUP2_CFG_RCGR     (CLK_CTL_BASE + 0x28010)
 #define GCC_BLSP2_QUP2_CMD_RCGR     (CLK_CTL_BASE + 0x2800C)
 
+/* USB platform specific bases*/
+unsigned int usb_ctrl_base();
+unsigned int usb_qscratch_base();
+unsigned int usb_phy_base();
+unsigned int usb_phy_bcr();
+
+#define MSM_USB30_BASE              (usb_ctrl_base())
+#define MSM_USB30_QSCRATCH_BASE     (usb_qscratch_base())
+#define QUSB2_PHY_BASE              (usb_phy_base())
+#define GCC_QUSB2_PHY_BCR           (usb_phy_bcr())
+
 /* USB3.0 */
-#define MSM_USB30_BASE              0x6A00000
-#define MSM_USB30_QSCRATCH_BASE     0x6AF8800
+#define MSM_USB30_PRIM_BASE              0x6A00000
+#define MSM_USB30_QSCRATCH_PRIM_BASE     0x6AF8800
+/* USB2.0 */
+#define MSM_USB20_SEC_BASE              0x7600000
+#define MSM_USB20_SEC_QSCRATCH_BASE     0x76F8800
 /* SS QMP (Qulacomm Multi Protocol) */
 #define QMP_PHY_BASE                0x7410000
 
-/* QUSB2 PHY */
-#define QUSB2_PHY_BASE              0x7411000
-#define GCC_QUSB2_PHY_BCR           (CLK_CTL_BASE + 0x00012038)
+/* QUSB2 PHY primary */
+#define QUSB2_PRIM_PHY_BASE              0x7411000
+#define GCC_QUSB2_PRIM_PHY_BCR           (CLK_CTL_BASE + 0x00012038)
+
+/* QUSB2 PHY secondary */
+#define QUSB2_SEC_PHY_BASE              0x7412000
+#define GCC_QUSB2_SEC_PHY_BCR           (CLK_CTL_BASE + 0x0001203C)
 
 #define AHB2_PHY_BASE               0x7416000
 #define PERIPH_SS_AHB2PHY_TOP_CFG   (AHB2_PHY_BASE + 0x10)
@@ -138,6 +156,20 @@
 #define USB_PHY_CFG_AHB2PHY_CBCR    (CLK_CTL_BASE + 0x6A004)
 #define GCC_AGGRE2_USB3_AXI_CBCR    (CLK_CTL_BASE + 0x83018)
 
+/* USB20 clocks */
+#define USB_20_BCR                  (CLK_CTL_BASE + 0x12000)
+#define USB20_MASTER_CBCR           (CLK_CTL_BASE + 0x12004)
+#define USB20_SLEEP_CBCR            (CLK_CTL_BASE + 0x12008)
+#define USB20_MOCK_UTMI_CBCR        (CLK_CTL_BASE + 0x1200C)
+#define USB20_MASTER_CMD_RCGR       (CLK_CTL_BASE + 0x12010)
+#define USB20_MASTER_CFG_RCGR       (CLK_CTL_BASE + 0x12014)
+#define USB20_MASTER_M              (CLK_CTL_BASE + 0x12018)
+#define USB20_MASTER_N              (CLK_CTL_BASE + 0x1201c)
+#define USB20_MASTER_D              (CLK_CTL_BASE + 0x12020)
+#define USB20_MOCK_UTMI_CMD_RCGR    (CLK_CTL_BASE + 0x12024)
+#define USB20_MOCK_UTMI_CFG_RCGR    (CLK_CTL_BASE + 0x12028)
+#define PERIPH_NOC_USB20_AHB_CBCR   (CLK_CTL_BASE + 0x06010)
+
 /* SDCC */
 #define SDCC1_BCR                   (CLK_CTL_BASE + 0x13000) /* block reset */
 #define SDCC1_APPS_CBCR             (CLK_CTL_BASE + 0x13004) /* branch control */
@@ -209,7 +241,7 @@
  * as device memory, define the start address
  * and size in MB
  */
-#define RPMB_SND_RCV_BUF            0x91A00000
+#define RPMB_SND_RCV_BUF            0x91C00000
 #define RPMB_SND_RCV_BUF_SZ         0x2
 
 #define TCSR_BOOT_MISC_DETECT       0x007B3000
@@ -308,6 +340,11 @@
 #endif
 #define MDP_INTF_2_TIMING_ENGINE_EN             REG_MDP(0x6C000)
 
+#ifdef MDP_INTF_3_TIMING_ENGINE_EN
+#undef MDP_INTF_3_TIMING_ENGINE_EN
+#endif
+#define MDP_INTF_3_TIMING_ENGINE_EN             REG_MDP(0x6C800)
+
 #ifdef MDP_CTL_0_BASE
 #undef MDP_CTL_0_BASE
 #endif
@@ -348,6 +385,11 @@
 #endif
 #define MDP_INTF_2_BASE                         REG_MDP(0x6c000)
 
+#ifdef MDP_INTF_3_BASE
+#undef MDP_INTF_3_BASE
+#endif
+#define MDP_INTF_3_BASE                         REG_MDP(0x6c800)
+
 #ifdef MDP_CLK_CTRL0
 #undef MDP_CLK_CTRL0
 #endif
@@ -565,4 +607,77 @@
 #define APPS_WDOG_RESET_REG         (APSS_WDOG_BASE + 0x04)
 #define APPS_WDOG_CTL_REG           (APSS_WDOG_BASE + 0x08)
 
+/* HDMI reg addresses */
+#define HDMI_BASE               0x9A0000
+#define REG_HDMI(off)           (HDMI_BASE + (off))
+
+#define HDMI_ACR_32_0           REG_HDMI(0xC4)
+#define HDMI_ACR_32_1           REG_HDMI(0xC8)
+#define HDMI_ACR_44_0           REG_HDMI(0xCC)
+#define HDMI_ACR_44_1           REG_HDMI(0xD0)
+#define HDMI_ACR_48_0           REG_HDMI(0xD4)
+#define HDMI_ACR_48_1           REG_HDMI(0xD8)
+#define HDMI_AUDIO_PKT_CTRL2    REG_HDMI(0x44)
+#define HDMI_ACR_PKT_CTRL       REG_HDMI(0x24)
+#define HDMI_INFOFRAME_CTRL0    REG_HDMI(0x2C)
+#define HDMI_INFOFRAME_CTRL1    REG_HDMI(0x30)
+#define HDMI_AUDIO_INFO0        REG_HDMI(0xE4)
+#define HDMI_AUDIO_INFO1        REG_HDMI(0xE8)
+#define HDMI_AUDIO_PKT_CTRL     REG_HDMI(0x20)
+#define HDMI_VBI_PKT_CTRL       REG_HDMI(0x28)
+#define HDMI_GEN_PKT_CTRL       REG_HDMI(0x34)
+#define HDMI_GC                 REG_HDMI(0x40)
+#define HDMI_AUDIO_CFG          REG_HDMI(0x1D0)
+
+#define HDMI_DDC_SPEED          REG_HDMI(0x220)
+#define HDMI_DDC_SETUP          REG_HDMI(0x224)
+#define HDMI_DDC_REF            REG_HDMI(0x27C)
+#define HDMI_DDC_DATA           REG_HDMI(0x238)
+#define HDMI_DDC_TRANS0         REG_HDMI(0x228)
+#define HDMI_DDC_TRANS1         REG_HDMI(0x22C)
+#define HDMI_DDC_TRANS2         REG_HDMI(0x230)
+#define HDMI_DDC_TRANS3         REG_HDMI(0x234)
+#define HDMI_DDC_CTRL           REG_HDMI(0x20C)
+#define HDMI_DDC_INT_CTRL       REG_HDMI(0x214)
+#define HDMI_DDC_SW_STATUS      REG_HDMI(0x218)
+#define HDMI_DDC_ARBITRATION    REG_HDMI(0x210)
+#define HDMI_HW_DDC_CTRL        REG_HDMI(0x4CC)
+#define HDMI_DDC_INT_CTRL0      REG_HDMI(0x430)
+#define HDMI_DDC_INT_CTRL1      REG_HDMI(0x434)
+#define HDMI_DDC_INT_CTRL2      REG_HDMI(0x438)
+#define HDMI_DDC_INT_CTRL3      REG_HDMI(0x43C)
+#define HDMI_DDC_INT_CTRL4      REG_HDMI(0x440)
+#define HDMI_DDC_INT_CTRL5      REG_HDMI(0x444)
+#define HDMI_DDC_HW_STATUS      REG_HDMI(0x21C)
+#define HDMI_SCRAMBLER_STATUS_DDC_CTRL   REG_HDMI(0x464)
+#define HDMI_SCRAMBLER_STATUS_DDC_TIMER_CTRL    REG_HDMI(0x468)
+#define HDMI_SCRAMBLER_STATUS_DDC_TIMER_CTRL2   REG_HDMI(0x46C)
+#define HDMI_SCRAMBLER_STATUS_DDC_STATUS        REG_HDMI(0x470)
+#define HDMI_SCRAMBLER_STATUS_DDC_TIMER_STATUS  REG_HDMI(0x474)
+#define HDMI_SCRAMBLER_STATUS_DDC_TIMER_STATUS2 REG_HDMI(0x478)
+
+#define HDMI_USEC_REFTIMER      REG_HDMI(0x208)
+#define HDMI_CTRL               REG_HDMI(0x000)
+#define HDMI_VERSION            REG_HDMI(0x2E4)
+#define HDMI_HPD_INT_STATUS     REG_HDMI(0x250)
+#define HDMI_HPD_INT_CTRL       REG_HDMI(0x254)
+#define HDMI_HPD_CTRL           REG_HDMI(0x258)
+#define HDMI_PHY_CTRL           REG_HDMI(0x2D4)
+#define HDMI_TOTAL              REG_HDMI(0x2C0)
+#define HDMI_ACTIVE_H           REG_HDMI(0x2B4)
+#define HDMI_ACTIVE_V           REG_HDMI(0x2B8)
+#define HDMI_V_TOTAL_F2         REG_HDMI(0x2C4)
+#define HDMI_ACTIVE_V_F2        REG_HDMI(0x2BC)
+#define HDMI_FRAME_CTRL         REG_HDMI(0x2C8)
+
+#define HDMI_AVI_INFO0          REG_HDMI(0x06C)
+#define HDMI_AVI_INFO1          REG_HDMI(0x070)
+#define HDMI_AVI_INFO2          REG_HDMI(0x074)
+#define HDMI_AVI_INFO3          REG_HDMI(0x078)
+
+#define LPASS_LPAIF_RDDMA_CTL0       0x0910D000
+#define LPASS_LPAIF_RDDMA_BASE0      0x0910D004
+#define LPASS_LPAIF_RDDMA_BUFF_LEN0  0x0910D008
+#define LPASS_LPAIF_RDDMA_PER_LEN0   0x0910D010
+#define LPASS_LPAIF_DEBUG_CTL        0x0910000C
 #endif
diff --git a/platform/msm8996/include/platform/irqs.h b/platform/msm8996/include/platform/irqs.h
index 61d267b..e5cc23d 100644
--- a/platform/msm8996/include/platform/irqs.h
+++ b/platform/msm8996/include/platform/irqs.h
@@ -45,7 +45,13 @@
 
 #define INT_QTMR_FRM_0_PHYSICAL_TIMER_EXP      (GIC_SPI_START + 31)
 
-#define USB30_EE1_IRQ                          (GIC_SPI_START + 131)
+/* to support secondary port usage, secondary port Interrupt*/
+int usb_irq();
+
+#define USB30_EE1_IRQ  			   (usb_irq())
+
+#define USB30_IRQ                          (GIC_SPI_START + 131)
+#define USB20_IRQ                          (GIC_SPI_START + 138)
 
 #define GLINK_IPC_IRQ                          (GIC_SPI_START + 168)
 
diff --git a/platform/msm8996/msm8996-clock.c b/platform/msm8996/msm8996-clock.c
index 782a624..c92974a 100644
--- a/platform/msm8996/msm8996-clock.c
+++ b/platform/msm8996/msm8996-clock.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -46,6 +46,7 @@
 #define mmpll1_mm_source_val 2
 #define mmpll3_mm_source_val 3
 #define gpll0_mm_source_val 5
+#define hdmipll_mm_source_val 1
 
 struct clk_freq_tbl rcg_dummy_freq = F_END;
 
@@ -335,6 +336,16 @@
 	},
 };
 
+static struct branch_clk gcc_periph_noc_usb20_ahb_clk = {
+	.cbcr_reg    = (uint32_t *) PERIPH_NOC_USB20_AHB_CBCR,
+	.has_sibling = 1,
+
+	.c = {
+		.dbg_name = "periph_noc_usb20_ahb_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
 static struct clk_freq_tbl ftbl_gcc_usb30_master_clk[] = {
 	F(  19200000, cxo,    1,    0,    0),
 	F( 120000000, gpll0,    5,    0,    0),
@@ -342,6 +353,13 @@
 	F_END
 };
 
+static struct clk_freq_tbl ftbl_gcc_usb20_master_clk[] = {
+	F(  19200000, cxo,    1,    0,    0),
+	F( 120000000, gpll0,    5,    0,    0),
+	F( 150000000, gpll0,    4,    0,    0),
+	F_END
+};
+
 static struct rcg_clk usb30_master_clk_src = {
 	.cmd_reg      = (uint32_t *) USB30_MASTER_CMD_RCGR,
 	.cfg_reg      = (uint32_t *) USB30_MASTER_CFG_RCGR,
@@ -359,6 +377,23 @@
 	},
 };
 
+static struct rcg_clk usb20_master_clk_src = {
+	.cmd_reg      = (uint32_t *) USB20_MASTER_CMD_RCGR,
+	.cfg_reg      = (uint32_t *) USB20_MASTER_CFG_RCGR,
+	.m_reg        = (uint32_t *) USB20_MASTER_M,
+	.n_reg        = (uint32_t *) USB20_MASTER_N,
+	.d_reg        = (uint32_t *) USB20_MASTER_D,
+
+	.set_rate     = clock_lib2_rcg_set_rate_mnd,
+	.freq_tbl     = ftbl_gcc_usb20_master_clk,
+	.current_freq = &rcg_dummy_freq,
+
+	.c = {
+		.dbg_name = "usb20_master_clk_src",
+		.ops      = &clk_ops_rcg,
+	},
+};
+
 static struct branch_clk gcc_usb30_master_clk = {
 	.cbcr_reg = (uint32_t *) USB30_MASTER_CBCR,
 	.bcr_reg  = (uint32_t *) USB_30_BCR,
@@ -370,6 +405,17 @@
 	},
 };
 
+static struct branch_clk gcc_usb20_master_clk = {
+	.cbcr_reg = (uint32_t *) USB20_MASTER_CBCR,
+	.bcr_reg  = (uint32_t *) USB_20_BCR,
+	.parent   = &usb20_master_clk_src.c,
+
+	.c = {
+		.dbg_name = "usb20_master_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
 static struct branch_clk gcc_aggre2_usb3_axi_clk = {
 	.cbcr_reg     = (uint32_t *) GCC_AGGRE2_USB3_AXI_CBCR,
 	.parent       = &usb30_master_clk_src.c,
@@ -385,6 +431,11 @@
 	F_END
 };
 
+static struct clk_freq_tbl ftbl_gcc_usb20_mock_utmi_clk_src[] = {
+	F(  60000000, gpll0,   10,    0,     0),
+	F_END
+};
+
 static struct rcg_clk usb30_mock_utmi_clk_src = {
 	.cmd_reg      = (uint32_t *) USB30_MOCK_UTMI_CMD_RCGR,
 	.cfg_reg      = (uint32_t *) USB30_MOCK_UTMI_CFG_RCGR,
@@ -398,6 +449,19 @@
 	},
 };
 
+static struct rcg_clk usb20_mock_utmi_clk_src = {
+	.cmd_reg      = (uint32_t *) USB20_MOCK_UTMI_CMD_RCGR,
+	.cfg_reg      = (uint32_t *) USB20_MOCK_UTMI_CFG_RCGR,
+	.set_rate     = clock_lib2_rcg_set_rate_hid,
+	.freq_tbl     = ftbl_gcc_usb20_mock_utmi_clk_src,
+	.current_freq = &rcg_dummy_freq,
+
+	.c = {
+		.dbg_name = "usb20_mock_utmi_clk_src",
+		.ops      = &clk_ops_rcg,
+	},
+};
+
 static struct branch_clk gcc_usb30_mock_utmi_clk = {
 	.cbcr_reg    = (uint32_t *) USB30_MOCK_UTMI_CBCR,
 	.has_sibling = 0,
@@ -409,6 +473,18 @@
 	},
 };
 
+static struct branch_clk gcc_usb20_mock_utmi_clk = {
+	.cbcr_reg    = (uint32_t *) USB20_MOCK_UTMI_CBCR,
+	.has_sibling = 0,
+	.parent      = &usb20_mock_utmi_clk_src.c,
+
+	.c = {
+		.dbg_name = "usb20_mock_utmi_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
+
 static struct branch_clk gcc_usb30_sleep_clk = {
 	.cbcr_reg    = (uint32_t *) USB30_SLEEP_CBCR,
 	.has_sibling = 1,
@@ -419,6 +495,16 @@
 	},
 };
 
+static struct branch_clk gcc_usb20_sleep_clk = {
+	.cbcr_reg    = (uint32_t *) USB20_SLEEP_CBCR,
+	.has_sibling = 1,
+
+	.c = {
+		.dbg_name = "usb20_sleep_clk",
+		.ops      = &clk_ops_branch,
+	},
+};
+
 static struct clk_freq_tbl ftbl_gcc_usb30_phy_aux_clk_src[] = {
 	F(   1200000,         cxo,   16,    0,     0),
 	F_END
@@ -728,6 +814,78 @@
 	},
 };
 
+static struct branch_clk mdss_hdmi_ahb_clk = {
+	.cbcr_reg = (uint32_t *) MDSS_HDMI_AHB_CBCR,
+	.has_sibling = 1,
+	.c = {
+		.dbg_name = "mdss_hdmi_ahb_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+
+static struct clk_freq_tbl ftbl_mdss_hdmi_clk[] = {
+	F_MM( 19200000,  cxo,    1, 0, 0),
+	F_END
+};
+
+static struct rcg_clk hdmi_clk_src = {
+	.cmd_reg = (uint32_t *) HDMI_CMD_RCGR,
+	.cfg_reg = (uint32_t *) HDMI_CFG_RCGR,
+	.set_rate = clock_lib2_rcg_set_rate_hid,
+	.freq_tbl = ftbl_mdss_hdmi_clk,
+	.current_freq = &rcg_dummy_freq,
+	.c = {
+		.dbg_name = "hdmi_clk_src",
+		.ops = &clk_ops_rcg,
+	},
+};
+
+static struct branch_clk mdss_hdmi_clk = {
+	.cbcr_reg = (uint32_t *) MDSS_HDMI_CBCR,
+	.has_sibling = 0,
+	.parent = &hdmi_clk_src.c,
+	.c = {
+		.dbg_name = "mdss_hdmi_clk",
+		.ops = &clk_ops_branch,
+	},
+};
+
+static struct clk_freq_tbl ftbl_mdss_extpclk_clk[] = {
+	F_MDSS( 74250000, hdmipll, 1, 0, 0),
+	F_MDSS( 25200000, hdmipll, 1, 0, 0),
+	F_MDSS( 27000000, hdmipll, 1, 0, 0),
+	F_MDSS( 27030000, hdmipll, 1, 0, 0),
+	F_MDSS( 27070000, hdmipll, 1, 0, 0),
+	F_MDSS( 65000000, hdmipll, 1, 0, 0),
+	F_MDSS(108000000, hdmipll, 1, 0, 0),
+	F_MDSS(148500000, hdmipll, 1, 0, 0),
+	F_MDSS(268500000, hdmipll, 1, 0, 0),
+	F_MDSS(297000000, hdmipll, 1, 0, 0),
+	F_MDSS(594000000, hdmipll, 1, 0, 0),
+	F_END
+};
+
+static struct rcg_clk extpclk_clk_src = {
+	.cmd_reg = (uint32_t *) EXTPCLK_CMD_RCGR,
+	.cfg_reg = (uint32_t *) EXTPCLK_CFG_RCGR,
+	.set_rate = clock_lib2_rcg_set_rate_hid,
+	.freq_tbl = ftbl_mdss_extpclk_clk,
+	.current_freq = &rcg_dummy_freq,
+	.c = {
+		.dbg_name = "extpclk_clk_src",
+		.ops = &clk_ops_rcg,
+	},
+};
+
+static struct branch_clk mdss_extpclk_clk = {
+	.cbcr_reg = (uint32_t *) MDSS_EXTPCLK_CBCR,
+	.has_sibling = 0,
+	.parent = &extpclk_clk_src.c,
+	.c = {
+		.dbg_name = "mdss_extpclk_clk",
+		.ops = &clk_ops_branch,
+	},
+};
 
 /* Clock lookup table */
 static struct clk_lookup msm_msm8996_clocks[] =
@@ -750,6 +908,12 @@
 
 	CLK_LOOKUP("usb_phy_cfg_ahb2phy_clk",     gcc_usb_phy_cfg_ahb2phy_clk.c),
 
+	/* USB20 clocks */
+	CLK_LOOKUP("usb20_noc_usb20_clk",     gcc_periph_noc_usb20_ahb_clk.c),
+	CLK_LOOKUP("usb20_master_clk",    gcc_usb20_master_clk.c),
+	CLK_LOOKUP("usb20_mock_utmi_clk", gcc_usb20_mock_utmi_clk.c),
+	CLK_LOOKUP("usb20_sleep_clk",     gcc_usb20_sleep_clk.c),
+
 	/* mdss clocks */
 	CLK_LOOKUP("mdss_mdp_clk",     mdss_mdp_clk.c),
 	CLK_LOOKUP("mdss_vsync_clk",       mdss_vsync_clk.c),
@@ -772,6 +936,11 @@
 		gcc_blsp2_qup2_i2c_apps_clk_src.c),
 	CLK_LOOKUP("gcc_blsp2_qup2_i2c_apps_clk",
 		gcc_blsp2_qup2_i2c_apps_clk.c),
+
+	/* HDMI clocks*/
+	CLK_LOOKUP("hdmi_ahb_clk",         mdss_hdmi_ahb_clk.c),
+	CLK_LOOKUP("hdmi_core_clk",        mdss_hdmi_clk.c),
+	CLK_LOOKUP("hdmi_extp_clk",        mdss_extpclk_clk.c),
 };
 
 void platform_clock_init(void)
diff --git a/platform/msm8996/platform.c b/platform/msm8996/platform.c
index 79bf7c9..a3c2d3e 100644
--- a/platform/msm8996/platform.c
+++ b/platform/msm8996/platform.c
@@ -181,3 +181,46 @@
 
 	return false;
 }
+
+
+/* USB platform specific bases*/
+uint32_t usb_ctrl_base()
+{
+	if (board_hardware_id() == HW_PLATFORM_SBC)
+		return	MSM_USB20_SEC_BASE;
+	else
+		return	MSM_USB30_PRIM_BASE;
+
+}
+
+uint32_t usb_qscratch_base()
+{
+	if (board_hardware_id() == HW_PLATFORM_SBC)
+		return	MSM_USB20_SEC_QSCRATCH_BASE;
+	else
+		return	MSM_USB30_QSCRATCH_PRIM_BASE;
+}
+
+uint32_t usb_phy_base()
+{
+	if (board_hardware_id() == HW_PLATFORM_SBC)
+		return	QUSB2_SEC_PHY_BASE;
+	else
+		return	QUSB2_PRIM_PHY_BASE;
+}
+
+uint32_t usb_phy_bcr()
+{
+	if (board_hardware_id() == HW_PLATFORM_SBC)
+		return	GCC_QUSB2_SEC_PHY_BCR;
+	else
+		return	GCC_QUSB2_PRIM_PHY_BCR;
+}
+
+int usb_irq()
+{
+	if (board_hardware_id() == HW_PLATFORM_SBC)
+		return	USB20_IRQ;
+	else
+		return	USB30_IRQ;
+}
diff --git a/platform/msm_shared/board.c b/platform/msm_shared/board.c
index 19ec937..a4d3be4 100644
--- a/platform/msm_shared/board.c
+++ b/platform/msm_shared/board.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -289,30 +289,26 @@
 
 void pmic_info_populate()
 {
-	struct smem_board_info_v11 *bi_v11=NULL;
-	unsigned int board_info_len = 0;
-	unsigned ret = 0;
 	uint32_t pmic_type = 0;
+	void *smem_board_info_addr = NULL;
+	uint32_t smem_board_info_size = 0;
 
 	if (format_minor < 0xB)
 	{
 		// not needed for smem versions < 0xB
 		return;
 	}
-
-	board_info_len = sizeof(struct smem_board_info_v11) + board.num_pmics * sizeof(struct smem_pmic_info);
-	if(!(bi_v11 = malloc(board_info_len)))
+	smem_board_info_addr = smem_get_alloc_entry(SMEM_BOARD_INFO_LOCATION, &smem_board_info_size);
+	if (smem_board_info_addr == NULL)
 	{
-		dprintf(CRITICAL, "Error allocating memory for board structure\n");
+		dprintf(CRITICAL, "Error reading the smem board info address\n");
 		ASSERT(0);
 	}
-	ret = smem_read_alloc_entry(SMEM_BOARD_INFO_LOCATION,
-					bi_v11,
-					board_info_len);
-	if (ret)
+
+	if (smem_board_info_size < board.pmic_array_offset)
 	{
-		dprintf(CRITICAL, "Error reading from SMEM for populating pmic info\n");
-		goto free_bi_v11;
+		dprintf(CRITICAL, "Invalid SMEM board info\n");
+		ASSERT(0);
 	}
 
 	if(!(board.pmic_info_array = malloc(board.num_pmics * sizeof(struct board_pmic_data))))
@@ -320,10 +316,11 @@
 		dprintf(CRITICAL, "Error allocating memory for pmic info array\n");
 		ASSERT(0);
 	}
+
 	struct board_pmic_data *info = board.pmic_info_array;
 	for (uint8_t i = 0; i < board.num_pmics; i++)
 	{
-		memcpy(info, (void *)(bi_v11) + board.pmic_array_offset + (i * sizeof(struct smem_pmic_info)), sizeof(struct smem_pmic_info));
+		memcpy(info, smem_board_info_addr + board.pmic_array_offset + (i * sizeof(struct smem_pmic_info)), sizeof(struct smem_pmic_info));
 		/*
 		 * fill in pimc_board_info with pmic type and pmic version information
 		 * bit no  		  	    |31  24|23         16|15          8|7		 0|
@@ -335,8 +332,6 @@
 			   ((info->pmic_version & 0xff) << 8) | (pmic_type & 0xff);
 		info++;
 	}
-free_bi_v11:
-	free(bi_v11);
 }
 
 void board_init()
diff --git a/platform/msm_shared/display.c b/platform/msm_shared/display.c
index fcf6ad3..8733afa 100644
--- a/platform/msm_shared/display.c
+++ b/platform/msm_shared/display.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -411,6 +411,11 @@
 		if (ret)
 			goto msm_display_off_out;
 		break;
+	case HDMI_PANEL:
+		dprintf(INFO, "Turn off HDMI PANEL.\n");
+		ret = mdss_hdmi_off(pinfo);
+		break;
+
 #endif
 #ifdef DISPLAY_TYPE_QPIC
 	case QPIC_PANEL:
diff --git a/platform/msm_shared/hsusb.c b/platform/msm_shared/hsusb.c
index 5f8d3e4..9ebe36e 100644
--- a/platform/msm_shared/hsusb.c
+++ b/platform/msm_shared/hsusb.c
@@ -2,7 +2,7 @@
  * Copyright (c) 2008, Google Inc.
  * All rights reserved.
  *
- * Copyright (c) 2009-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2016, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -62,7 +62,10 @@
 {
 	struct udc_descriptor *desc;
 	if ((len > 255) || (len < 2) || (num > 255) || (type > 255))
-		return 0;
+	{
+		dprintf(CRITICAL, "Invalid parameters for descriptor allocation\n");
+		ASSERT(0);
+	}
 
 	desc = malloc(sizeof(struct udc_descriptor) + len);
 	ASSERT(desc);
diff --git a/platform/msm_shared/include/mdp4.h b/platform/msm_shared/include/mdp4.h
index ee4e4fc..e463302 100644
--- a/platform/msm_shared/include/mdp4.h
+++ b/platform/msm_shared/include/mdp4.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -122,5 +122,6 @@
 
 int mdss_hdmi_init(void);
 int mdss_hdmi_on(struct msm_panel_info *pinfo);
+int mdss_hdmi_off(struct msm_panel_info *pinfo);
 int mdss_hdmi_config(struct msm_panel_info *pinfo, struct fbcon_config *fb);
 #endif
diff --git a/platform/msm_shared/include/mdp5.h b/platform/msm_shared/include/mdp5.h
index 2a72772..00baac3 100644
--- a/platform/msm_shared/include/mdp5.h
+++ b/platform/msm_shared/include/mdp5.h
@@ -235,6 +235,15 @@
 #define MDP_REG_PP_1_AUTOREFRESH_CONFIG		REG_MDP(0x71830)
 #define MDP_REG_PP_SLAVE_AUTOREFRESH_CONFIG	REG_MDP(0x73030)
 
+/* Registers for programming the CDM hardware in bypass mode. */
+#define CDM_HDMI_PACK_OP_MODE 		REG_MDP(0x7A400)
+#define MDP_OUT_CTL_0 			REG_MDP(0x01410)
+#define MDP_INTF_3_INTF_CONFIG 		REG_MDP(0x6C804)
+#define CDM_CDWN2_OUT_SIZE 		REG_MDP(0x7A330)
+#define CDM_CDWN2_OP_MODE 		REG_MDP(0x7A300)
+#define CDM_CDWN2_CLAMP_OUT 		REG_MDP(0x7A304)
+#define CDM_CSC_10_OP_MODE 		REG_MDP(0x7A200)
+
 void mdp_set_revision(int rev);
 int mdp_get_revision();
 int mdp_dsi_video_config(struct msm_panel_info *pinfo, struct fbcon_config *fb);
@@ -256,9 +265,12 @@
 int target_edp_panel_disable(void);
 int target_edp_bl_ctrl(int enable);
 int mdss_hdmi_init(void);
+void mdss_hdmi_display_init(uint32_t rev, void *base);
 int mdss_hdmi_on(struct msm_panel_info *pinfo);
+int mdss_hdmi_off(struct msm_panel_info *pinfo);
 int mdss_hdmi_config(struct msm_panel_info *pinfo, struct fbcon_config *fb);
 void mdss_hdmi_get_vic(char *buf);
+void hdmi_phy_init(void);
 int msm_display_off();
 void display_shutdown(void);
 
diff --git a/platform/msm_shared/include/mdss_hdmi.h b/platform/msm_shared/include/mdss_hdmi.h
index 6786a85..e38f0d7 100644
--- a/platform/msm_shared/include/mdss_hdmi.h
+++ b/platform/msm_shared/include/mdss_hdmi.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -31,7 +31,7 @@
 #define _PLATFORM_MSM_SHARED_MDSS_HDMI_H_
 
 void hdmi_phy_reset(void);
-uint32_t hdmi_pll_config(uint32_t tmds_clk_rate);
+int hdmi_pll_config(uint32_t tmds_clk_rate);
 int hdmi_vco_enable(void);
 int hdmi_vco_disable(void);
 void mdss_hdmi_display_init(uint32_t rev, void *base);
diff --git a/platform/msm_shared/mdp5.c b/platform/msm_shared/mdp5.c
index 1bcb69f..a5db243 100755
--- a/platform/msm_shared/mdp5.c
+++ b/platform/msm_shared/mdp5.c
@@ -547,9 +547,8 @@
 		writel(BIT(16) | (0x3 << 20), REG_MDP(ppb_offset + 0x4)); /* MMSS_MDP_PPB0_CONFIG */
 	}
 
-	if (pinfo->compression_mode == COMPRESSION_FBC)
-		if (!pinfo->fbc.enabled || !pinfo->fbc.comp_ratio)
-			pinfo->fbc.comp_ratio = 1;
+	if (!pinfo->fbc.enabled || !pinfo->fbc.comp_ratio)
+		pinfo->fbc.comp_ratio = 1;
 
 	itp.xres = (adjust_xres / pinfo->fbc.comp_ratio);
 	itp.yres = pinfo->yres;
@@ -1090,10 +1089,10 @@
 
 int mdss_hdmi_config(struct msm_panel_info *pinfo, struct fbcon_config *fb)
 {
-	uint32_t left_pipe, right_pipe;
-	dprintf(SPEW, "ENTER: %s\n", __func__);
+	uint32_t left_pipe, right_pipe, out_size;
 
 	mdss_intf_tg_setup(pinfo, MDP_INTF_3_BASE + mdss_mdp_intf_offset());
+	mdss_intf_fetch_start_config(pinfo, MDP_INTF_3_BASE + mdss_mdp_intf_offset());
 	pinfo->pipe_type = MDSS_MDP_PIPE_TYPE_RGB;
 	mdp_select_pipe_type(pinfo, &left_pipe, &right_pipe);
 
@@ -1116,10 +1115,23 @@
 		writel(0x40, MDP_CTL_0_BASE + CTL_TOP);
 
 	writel(BIT(24) | BIT(25), MDP_DISP_INTF_SEL);
-	writel(0x1111, MDP_VIDEO_INTF_UNDERFLOW_CTL);
+	writel(0x11111, MDP_VIDEO_INTF_UNDERFLOW_CTL);
 	writel(0x01, MDP_UPPER_NEW_ROI_PRIOR_RO_START);
 	writel(0x01, MDP_LOWER_NEW_ROI_PRIOR_TO_START);
 
+	/**
+	 * Program the CDM hardware block in HDMI bypass mode, and enable
+	 * the HDMI packer.
+	 */
+	writel(0x01, CDM_HDMI_PACK_OP_MODE);
+	writel(0x00, MDP_OUT_CTL_0);
+	writel(0x00, MDP_INTF_3_INTF_CONFIG);
+	out_size = (pinfo->xres & 0xFFFF) | ((pinfo->yres & 0xFFFF) << 16);
+	writel(out_size, CDM_CDWN2_OUT_SIZE);
+	writel(0x80, CDM_CDWN2_OP_MODE);
+	writel(0x3FF0000, CDM_CDWN2_CLAMP_OUT);
+	writel(0x0, CDM_CSC_10_OP_MODE);
+
 	return 0;
 }
 
@@ -1358,6 +1370,21 @@
 	return NO_ERROR;
 }
 
+int mdss_hdmi_off(struct msm_panel_info *pinfo)
+{
+	if(!target_cont_splash_screen())
+	{
+		writel(0x00000000, MDP_INTF_3_TIMING_ENGINE_EN + mdss_mdp_intf_offset());
+		mdelay(60);
+		/* Underrun(Interface 0/1/2/3) VSYNC Interrupt Enable  */
+		writel(0xFF777713, MDP_INTR_CLEAR);
+	}
+
+	writel(0x00000000, MDP_INTR_EN);
+
+	return NO_ERROR;
+}
+
 int mdp_edp_off(void)
 {
 	if (!target_cont_splash_screen()) {
diff --git a/platform/msm_shared/mdss_hdmi.c b/platform/msm_shared/mdss_hdmi.c
index 0741308..00bf5f1 100644
--- a/platform/msm_shared/mdss_hdmi.c
+++ b/platform/msm_shared/mdss_hdmi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -99,8 +99,14 @@
 	HDMI_MSM_AUDIO_ARCS(297000, {
 		{3072, 222750}, {4704, 247500}, {5120, 247500}, {9408, 247500},
 		{10240, 247500}, {18816, 247500}, {20480, 247500} }),
+	/* 594.000MHz */
+	HDMI_MSM_AUDIO_ARCS(594000, {{3072, 445500}, {9408, 990000}, {6144, 594000},
+		{18816, 990000}, {12288, 594000}, {37632, 990000},
+		{24576, 594000} } ),
 };
 
+extern int msm_display_init(struct msm_fb_panel_data *pdata);
+
 /* AVI INFOFRAME DATA */
 #define NUM_MODES_AVI 20
 #define AVI_MAX_DATA_BYTES 13
@@ -135,6 +141,7 @@
  */
 #define AVI_IFRAME_TYPE 0x2
 #define AVI_IFRAME_VERSION 0x2
+#define AVI_IFRAME_LINE_NUMBER 1
 #define LEFT_SHIFT_BYTE(x) ((x) << 8)
 #define LEFT_SHIFT_WORD(x) ((x) << 16)
 #define LEFT_SHIFT_24BITS(x) ((x) << 24)
@@ -142,7 +149,8 @@
 #define MAX_AUDIO_DATA_BLOCK_SIZE       0x80
 #define DBC_START_OFFSET                4
 #define VIC_INDEX                       3
-#define HDMI_VIC_STR_MAX                3
+#define HDMI_VIC_STR_MAX                4
+#define MAX_EDID_BLOCK_SIZE             0x80
 
 enum edid_data_block_type {
 	RESERVED_DATA_BLOCK1 = 0,
@@ -160,7 +168,35 @@
 #define HDMI_VFRMT_640x480p60_4_3       1
 #define HDMI_VFRMT_1280x720p60_16_9     4
 #define HDMI_VFRMT_1920x1080p60_16_9    16
-#define HDMI_VFRMT_MAX                  3
+#define HDMI_VFRMT_4096x2160p24_256_135 98
+#define HDMI_VFRMT_4096x2160p25_256_135 99
+#define HDMI_VFRMT_4096x2160p30_256_135 100
+#define HDMI_VFRMT_3840x2160p24_64_27   103
+#define HDMI_VFRMT_3840x2160p25_64_27   104
+#define HDMI_VFRMT_3840x2160p30_64_27   105
+#define HDMI_EVFRMT_4096x2160p24_16_9   131
+#define HDMI_VFRMT_4096x2160p60_256_135 102
+#define HDMI_VFRMT_COUNT                11
+#define HDMI_VFRMT_END                  127
+#define HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd) \
+	(!((vsd)[8] & BIT(7)) ? 9 : (!((vsd)[8] & BIT(6)) ? 11 : 13))
+#define MSM_MDP_MAX_PIPE_WIDTH          2560
+/* TX major version that supports scrambling */
+#define HDMI_TX_SCRAMBLER_MIN_TX_VERSION 0x04
+#define HDMI_TX_SCRAMBLER_THRESHOLD_RATE_KHZ 340000
+#define HDMI_TX_SCRAMBLER_TIMEOUT_MSEC  200
+/* default hsyncs for 4k@60 for 200ms */
+#define HDMI_DEFAULT_TIMEOUT_HSYNC      28571
+#define HDMI_SCDC_TMDS_CONFIG           0x20
+#define HDMI_SCDC_CONFIG_0              0x30
+#define HDMI_SCDC_UNKNOWN_REGISTER      "Unknown register"
+#define HDMI_SEC_TO_MS                  1000
+#define HDMI_MS_TO_US                   1000
+#define HDMI_SEC_TO_US (HDMI_SEC_TO_MS * HDMI_MS_TO_US)
+#define HDMI_KHZ_TO_HZ                  1000
+#define HDMI_DDC_TRANSACTION_DELAY_US      468
+static uint8_t mdss_hdmi_video_formats[HDMI_VFRMT_COUNT];
+static uint8_t mdss_hdmi_mode_count;
 
 #define DEFAULT_RESOLUTION HDMI_VFRMT_1920x1080p60_16_9
 static uint8_t mdss_hdmi_video_fmt = HDMI_VFRMT_UNKNOWN;
@@ -169,17 +205,98 @@
 static uint8_t it_scan_info;
 static uint8_t ce_scan_info;
 
-static uint8_t mdss_hdmi_edid_buf[0x80];
+static uint8_t mdss_hdmi_edid_buf[MAX_EDID_BLOCK_SIZE];
+
+enum scdc_access_type {
+	SCDC_SCRAMBLING_STATUS,
+	SCDC_SCRAMBLING_ENABLE,
+	SCDC_TMDS_BIT_CLOCK_RATIO_UPDATE,
+	SCDC_CLOCK_DET_STATUS,
+	SCDC_CH0_LOCK_STATUS,
+	SCDC_CH1_LOCK_STATUS,
+	SCDC_CH2_LOCK_STATUS,
+	SCDC_CH0_ERROR_COUNT,
+	SCDC_CH1_ERROR_COUNT,
+	SCDC_CH2_ERROR_COUNT,
+	SCDC_READ_ENABLE,
+	SCDC_MAX,
+};
+
+enum ddc_timer_type {
+	DDC_TIMER_HDCP2P2_RD_MSG,
+	DDC_TIMER_SCRAMBLER_STATUS,
+	DDC_TIMER_UPDATE_FLAGS,
+	DDC_TIMER_STATUS_FLAGS,
+	DDC_TIMER_CED,
+	DDC_TIMER_MAX,
+};
+
+struct hdmi_tx_ddc_data {
+	char *what;
+	uint8_t *data_buf;
+	uint32_t data_len;
+	uint32_t dev_addr;
+	uint32_t offset;
+	uint32_t request_len;
+	uint32_t retry_align;
+	uint32_t hard_timeout;
+	uint32_t timeout_left;
+	int retry;
+};
+
+enum trigger_mode {
+	TRIGGER_WRITE,
+	TRIGGER_READ
+};
 
 enum aspect_ratio {
 	HDMI_RES_AR_INVALID,
 	HDMI_RES_AR_4_3,
 	HDMI_RES_AR_5_4,
 	HDMI_RES_AR_16_9,
+	HDMI_RES_AR_64_27,
 	HDMI_RES_AR_16_10,
+	HDMI_RES_AR_256_135,
 	HDMI_RES_AR_MAX,
 };
 
+enum hdmi_quantization_range {
+	HDMI_QUANTIZATION_DEFAULT,
+	HDMI_QUANTIZATION_LIMITED_RANGE,
+	HDMI_QUANTIZATION_FULL_RANGE
+};
+
+enum hdmi_scaling_info {
+	HDMI_SCALING_NONE,
+	HDMI_SCALING_HORZ,
+	HDMI_SCALING_VERT,
+	HDMI_SCALING_HORZ_VERT,
+};
+
+struct hdmi_avi_iframe_bar_info {
+	bool vert_binfo_present;
+	bool horz_binfo_present;
+	uint32_t end_of_top_bar;
+	uint32_t start_of_bottom_bar;
+	uint32_t end_of_left_bar;
+	uint32_t start_of_right_bar;
+};
+
+struct hdmi_avi_infoframe_config {
+	uint32_t pixel_format;
+	uint32_t scan_info;
+	bool act_fmt_info_present;
+	uint32_t colorimetry_info;
+	uint32_t ext_colorimetry_info;
+	uint32_t rgb_quantization_range;
+	uint32_t yuv_quantization_range;
+	uint32_t scaling_info;
+	bool is_it_content;
+	uint8_t content_type;
+	uint8_t pixel_rpt_factor;
+	struct hdmi_avi_iframe_bar_info bar_info;
+};
+
 struct mdss_hdmi_timing_info {
 	uint32_t	video_format;
 	uint32_t	active_h;
@@ -213,6 +330,46 @@
 	{HDMI_VFRMT_1920x1080p60_16_9, 1920, 88, 44, 148, false,	\
 	 1080, 4, 5, 36, false, 148500, 60000, false, true, HDMI_RES_AR_16_9}
 
+#define HDMI_VFRMT_4096x2160p24_256_135_TIMING				\
+	{HDMI_VFRMT_4096x2160p24_256_135, 4096, 1020, 88, 296, false,	\
+	 2160, 8, 10, 72, false, 297000, 24000, false, true, 		\
+		HDMI_RES_AR_256_135}
+
+#define HDMI_VFRMT_4096x2160p25_256_135_TIMING				\
+	{HDMI_VFRMT_4096x2160p25_256_135, 4096, 968, 88, 128, false,	\
+	 2160, 8, 10, 72, false, 297000, 25000, false, true,		\
+		HDMI_RES_AR_256_135}
+
+#define HDMI_VFRMT_4096x2160p30_256_135_TIMING				\
+	{HDMI_VFRMT_4096x2160p30_256_135, 4096, 88, 88, 128, false,	\
+	 2160, 8, 10, 72, false, 297000, 30000, false, true,		\
+		HDMI_RES_AR_256_135}
+
+#define HDMI_EVFRMT_4096x2160p24_16_9_TIMING				\
+	{HDMI_EVFRMT_4096x2160p24_16_9, 4096, 1020, 88, 296, false,	\
+	 2160, 8, 10, 72, false, 297000, 24000, false, true,		\
+		HDMI_RES_AR_16_9}
+
+#define HDMI_VFRMT_3840x2160p24_64_27_TIMING				\
+	{HDMI_VFRMT_3840x2160p24_64_27, 3840, 1276, 88, 296, false,	\
+	 2160, 8, 10, 72, false, 297000, 24000, false, true,		\
+		HDMI_RES_AR_64_27}
+
+#define HDMI_VFRMT_3840x2160p25_64_27_TIMING				\
+	{HDMI_VFRMT_3840x2160p25_64_27, 3840, 1056, 88, 296, false,	\
+	 2160, 8, 10, 72, false, 297000, 25000, false, true,		\
+		HDMI_RES_AR_64_27}
+
+#define HDMI_VFRMT_3840x2160p30_64_27_TIMING				\
+	{HDMI_VFRMT_3840x2160p30_64_27, 3840, 176, 88, 296, false,	\
+	 2160, 8, 10, 72, false, 297000, 30000, false, true,		\
+		HDMI_RES_AR_64_27}
+
+#define HDMI_VFRMT_4096x2160p60_256_135_TIMING				\
+	{HDMI_VFRMT_4096x2160p60_256_135, 4096, 88, 88, 128, false,	\
+	 2160, 8, 10, 72, false, 594000, 60000, false, true,		\
+		HDMI_RES_AR_256_135}
+
 #define MSM_HDMI_MODES_GET_DETAILS(mode, MODE) do {		\
 	struct mdss_hdmi_timing_info info = MODE##_TIMING;	\
 	*mode = info;						\
@@ -236,6 +393,38 @@
 		MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_1920x1080p60_16_9);
 		break;
 
+	case HDMI_VFRMT_4096x2160p24_256_135:
+		MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_4096x2160p24_256_135);
+		break;
+
+	case HDMI_VFRMT_4096x2160p25_256_135:
+		MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_4096x2160p25_256_135);
+		break;
+
+	case HDMI_VFRMT_4096x2160p30_256_135:
+		MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_4096x2160p30_256_135);
+		break;
+
+	case HDMI_EVFRMT_4096x2160p24_16_9:
+		MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_EVFRMT_4096x2160p24_16_9);
+		break;
+
+	case HDMI_VFRMT_3840x2160p24_64_27:
+		MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_3840x2160p24_64_27);
+		break;
+
+	case HDMI_VFRMT_3840x2160p25_64_27:
+		MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_3840x2160p25_64_27);
+		break;
+
+	case HDMI_VFRMT_3840x2160p30_64_27:
+		MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_3840x2160p30_64_27);
+		break;
+
+	case HDMI_VFRMT_4096x2160p60_256_135:
+		MSM_HDMI_MODES_GET_DETAILS(mode, HDMI_VFRMT_4096x2160p60_256_135);
+		break;
+
 	default:
 		ret = ERROR;
 	}
@@ -243,35 +432,6 @@
 	return ret;
 }
 
-
-/*
- * 13 Bytes of AVI infoframe data wrt each resolution
- * Data Byte 01: 0 Y1 Y0 A0 B1 B0 S1 S0
- * Data Byte 02: C1 C0 M1 M0 R3 R2 R1 R0
- * Data Byte 03: ITC EC2 EC1 EC0 Q1 Q0 SC1 SC0
- * Data Byte 04: 0 VIC6 VIC5 VIC4 VIC3 VIC2 VIC1 VIC0
- * Data Byte 05: 0 0 0 0 PR3 PR2 PR1 PR0
- * Data Byte 06: LSB Line No of End of Top Bar
- * Data Byte 07: MSB Line No of End of Top Bar
- * Data Byte 08: LSB Line No of Start of Bottom Bar
- * Data Byte 09: MSB Line No of Start of Bottom Bar
- * Data Byte 10: LSB Pixel Number of End of Left Bar
- * Data Byte 11: MSB Pixel Number of End of Left Bar
- * Data Byte 12: LSB Pixel Number of Start of Right Bar
- * Data Byte 13: MSB Pixel Number of Start of Right Bar
- */
-static uint8_t mdss_hdmi_avi_info_db[HDMI_VFRMT_MAX][AVI_MAX_DATA_BYTES] = {
-	/* 480p */
-	{0x10, 0x18, 0x00, 0x01, 0x00, 0x00, 0x00,
-		0xE1, 0x01, 0x00, 0x00, 0x81, 0x02},
-	/* 720p */
-	{0x10, 0x28, 0x00, 0x04, 0x00, 0x00, 0x00,
-		0xD1, 0x02, 0x00, 0x00, 0x01, 0x05},
-	/* 1080p */
-	{0x10, 0x28, 0x00, 0x10, 0x00, 0x00, 0x00,
-		0x39, 0x04, 0x00, 0x00, 0x81, 0x07},
-};
-
 static void mdss_hdmi_audio_acr_setup(uint32_t sample_rate)
 {
 	/* Read first before writing */
@@ -460,7 +620,8 @@
 	 * edid buffer 1, byte 2 being 0 means no non-DTD/DATA block collection
 	 * present and no DTD data present.
 	 */
-	if ((end_dbc_offset == 0) || (end_dbc_offset == 4))
+	if ((end_dbc_offset == 0) || (end_dbc_offset == 4) ||
+			(end_dbc_offset >= MAX_EDID_BLOCK_SIZE))
 		return NULL;
 
 	while (offset < end_dbc_offset) {
@@ -654,13 +815,14 @@
 static void mdss_hdmi_set_mode(bool on)
 {
 	uint32_t val = 0;
-
 	if (on) {
 		/* tx on */
-		val = 0x1;
+		val |= BIT(0);
+		/* hdcp legacy mode*/
+		val |= BIT(31);
 
 		if (!mdss_hdmi_is_dvi_mode())
-			val |= 0x2;
+			val |= BIT(1);
 	}
 
 	writel(val, HDMI_CTRL);
@@ -751,19 +913,72 @@
 	return NO_ERROR;
 }
 
-static void mdss_hdmi_parse_res(void)
+static void mdss_hdmi_add_video_format(uint32_t video_format)
+{
+	if (mdss_hdmi_mode_count >= HDMI_VFRMT_COUNT) {
+		dprintf(SPEW, "%s: unsupported format (%d)", __func__,
+				video_format);
+		return;
+	}
+
+	dprintf(SPEW, "%s: vic=%d\n", __func__, video_format);
+	mdss_hdmi_video_formats[mdss_hdmi_mode_count] = video_format;
+	mdss_hdmi_mode_count++;
+}
+
+static void mdss_hdmi_get_extended_video_formats()
+{
+	uint8_t db_len, offset, i;
+	uint8_t hdmi_vic_len;
+	uint32_t video_format;
+	const uint8_t *vsd = NULL;
+
+	vsd = hdmi_edid_find_block(DBC_START_OFFSET,
+			VENDOR_SPECIFIC_DATA_BLOCK, &db_len);
+
+	if (!vsd || db_len == 0) {
+		dprintf(SPEW, "%s: No/Invalid Vendor Specific Data Block\n",
+				__func__);
+		return;
+	}
+
+	/* check if HDMI_Video_present flag is set or not */
+	if (!(vsd[8] & BIT(5))) {
+		dprintf(SPEW, "%s: extended vfmts not supported by the sink.\n",
+				__func__);
+		return;
+	}
+
+	offset = HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd);
+
+	hdmi_vic_len = vsd[offset + 1] >> 5;
+	if (hdmi_vic_len) {
+		for (i = 0; i < hdmi_vic_len; i++) {
+			struct mdss_hdmi_timing_info tinfo = {0};
+			uint32_t ret = 0;
+
+			video_format = HDMI_VFRMT_END + vsd[offset + 2 + i];
+			ret = mdss_hdmi_get_timing_info(&tinfo, video_format);
+
+			if (ret || !tinfo.supported)
+				continue;
+
+			mdss_hdmi_add_video_format(video_format);
+		}
+	}
+}
+
+static void mdss_hdmi_get_cea_video_formats()
 {
 	uint8_t len, i;
 	uint32_t video_format;
-	struct mdss_hdmi_timing_info tinfo_fmt = {0};
 
 	uint8_t *svd = hdmi_edid_find_block(DBC_START_OFFSET,
 			VIDEO_DATA_BLOCK, &len);
 
-	mdss_hdmi_video_fmt = HDMI_VFRMT_UNKNOWN;
-
-	if (!svd) {
-		mdss_hdmi_video_fmt = DEFAULT_RESOLUTION;
+	if (!svd || len == 0) {
+		dprintf(SPEW, "%s: No/Invalid Video Data Block\n",
+				__func__);
 		return;
 	}
 
@@ -783,20 +998,55 @@
 		if (ret || !tinfo.supported)
 			continue;
 
-		if (!tinfo_fmt.video_format) {
-			memcpy(&tinfo_fmt, &tinfo, sizeof(tinfo));
-			mdss_hdmi_video_fmt = video_format;
+		mdss_hdmi_add_video_format(video_format);
+	}
+}
+
+static void mdss_hdmi_parse_res(void)
+{
+	int index, ret;
+	uint8_t current_video_format;
+	struct mdss_hdmi_timing_info current_timing_info = {0};
+
+	mdss_hdmi_mode_count = 0;
+	mdss_hdmi_video_fmt = DEFAULT_RESOLUTION;
+	current_video_format = mdss_hdmi_video_fmt;
+	mdss_hdmi_get_timing_info(&current_timing_info, mdss_hdmi_video_fmt);
+
+	mdss_hdmi_get_extended_video_formats();
+	mdss_hdmi_get_cea_video_formats();
+
+	for (index = 0; index < mdss_hdmi_mode_count; index++) {
+		struct mdss_hdmi_timing_info new_timing_info = {0};
+
+		if (!mdss_hdmi_video_formats[index])
+			break;
+
+		ret = mdss_hdmi_get_timing_info(&new_timing_info, mdss_hdmi_video_formats[index]);
+		if (ret || !new_timing_info.supported)
 			continue;
+
+		if (new_timing_info.active_h > current_timing_info.active_h) {
+			current_video_format = mdss_hdmi_video_formats[index];
+		} else if (new_timing_info.active_h ==
+				current_timing_info.active_h) {
+			if (new_timing_info.active_v >
+					current_timing_info.active_v) {
+				current_video_format = mdss_hdmi_video_formats[index];
+			} else if (new_timing_info.active_v ==
+					current_timing_info.active_v) {
+				if (new_timing_info.refresh_rate >
+						current_timing_info.refresh_rate) {
+					current_video_format = mdss_hdmi_video_formats[index];
+				}
+			}
 		}
 
-		if (tinfo.active_v > tinfo_fmt.active_v) {
-			memcpy(&tinfo_fmt, &tinfo, sizeof(tinfo));
-			mdss_hdmi_video_fmt = video_format;
-		}
+		mdss_hdmi_get_timing_info(&current_timing_info, current_video_format);
 	}
 
-	if (mdss_hdmi_video_fmt == HDMI_VFRMT_UNKNOWN)
-		mdss_hdmi_video_fmt = DEFAULT_RESOLUTION;
+	if (mdss_hdmi_video_fmt != current_video_format)
+		mdss_hdmi_video_fmt = current_video_format;
 }
 
 void mdss_hdmi_get_vic(char *buf)
@@ -835,7 +1085,15 @@
 	pinfo->lcdc.hsync_skew = 0;
 	pinfo->lcdc.xres_pad   = 0;
 	pinfo->lcdc.yres_pad   = 0;
-	pinfo->lcdc.dual_pipe  = 0;
+
+	/* Add dual pipe configuration for resultions greater than
+	 * MSM_MDP_MAX_PIPE_WIDTH.
+	 */
+	if (pinfo->xres > MSM_MDP_MAX_PIPE_WIDTH) {
+		pinfo->lcdc.dual_pipe  = 1;
+		pinfo->lm_split[0] = pinfo->xres / 2;
+		pinfo->lm_split[1] = pinfo->xres - pinfo->lm_split[0];
+	}
 }
 
 static uint8_t mdss_hdmi_cable_status(void)
@@ -1067,58 +1325,716 @@
 	uint32_t sum;
 	uint32_t reg_val;
 	uint8_t checksum;
-	uint8_t scaninfo;
-	uint32_t i, index;
+	uint32_t i;
+	struct hdmi_avi_infoframe_config avi_info = {0};
+	struct mdss_hdmi_timing_info tinfo = {0};
+	uint8_t avi_iframe[AVI_MAX_DATA_BYTES] = {0};
 
-	scaninfo = mdss_hdmi_get_scan_info();
+	mdss_hdmi_get_timing_info(&tinfo, mdss_hdmi_video_fmt);
+
+	/* Setup AVI Infoframe content */
+	avi_info.scan_info = mdss_hdmi_get_scan_info();
+	avi_info.bar_info.end_of_top_bar = 0x0;
+	avi_info.bar_info.start_of_bottom_bar = tinfo.active_v + 1;
+	avi_info.bar_info.end_of_left_bar = 0;
+	avi_info.bar_info.start_of_right_bar = tinfo.active_h + 1;
+	avi_info.act_fmt_info_present = true;
+	avi_info.rgb_quantization_range = HDMI_QUANTIZATION_DEFAULT;
+	avi_info.yuv_quantization_range = HDMI_QUANTIZATION_DEFAULT;
+	avi_info.scaling_info = HDMI_SCALING_NONE;
+	avi_info.colorimetry_info = 0;
+	avi_info.ext_colorimetry_info = 0;
+	avi_info.pixel_rpt_factor = 0;
+
+	/*
+	 * BYTE - 1:
+	 * 	0:1 - Scan Information
+	 * 	2:3 - Bar Info
+	 * 	4   - Active Format Info present
+	 * 	5:6 - Pixel format type;
+	 * 	7   - Reserved;
+	 */
+	avi_iframe[0] = (avi_info.scan_info & 0x3) |
+		(avi_info.bar_info.vert_binfo_present ? BIT(2) : 0) |
+		(avi_info.bar_info.horz_binfo_present ? BIT(3) : 0) |
+		(avi_info.act_fmt_info_present ? BIT(4) : 0);
+
+	/*
+	 * BYTE - 2:
+	 * 	0:3 - Active format info
+	 * 	4:5 - Picture aspect ratio
+	 * 	6:7 - Colorimetry info
+	 */
+	avi_iframe[1] |= 0x08;
+	if (tinfo.ar == HDMI_RES_AR_4_3)
+		avi_iframe[1] |= (0x1 << 4);
+	else if (tinfo.ar == HDMI_RES_AR_16_9)
+		avi_iframe[1] |= (0x2 << 4);
+
+	avi_iframe[1] |= (avi_info.colorimetry_info & 0x3) << 6;
+
+	/*
+	 * BYTE - 3:
+	 *	0:1 - Scaling info
+	 *	2:3 - Quantization range
+	 *	4:6 - Extended Colorimetry
+	 *	7   - IT content
+	 */
+	avi_iframe[2] |= (avi_info.scaling_info & 0x3) |
+		((avi_info.rgb_quantization_range & 0x3) << 2) |
+		((avi_info.ext_colorimetry_info & 0x7) << 4) |
+		((avi_info.is_it_content ? 0x1 : 0x0) << 7);
+	/*
+	 * BYTE - 4:
+	 *	0:7 - VIC
+	 */
+	if (tinfo.video_format < HDMI_VFRMT_END)
+		avi_iframe[3] = tinfo.video_format;
+
+	/*
+	 * BYTE - 5:
+	 *	0:3 - Pixel Repeat factor
+	 *	4:5 - Content type
+	 *	6:7 - YCC Quantization range
+	 */
+	avi_iframe[4] = (avi_info.pixel_rpt_factor & 0xF) |
+		((avi_info.content_type & 0x3) << 4) |
+		((avi_info.yuv_quantization_range & 0x3) << 6);
+
+	/* BYTE - 6,7: End of top bar */
+	avi_iframe[5] = avi_info.bar_info.end_of_top_bar & 0xFF;
+	avi_iframe[6] = ((avi_info.bar_info.end_of_top_bar & 0xFF00) >> 8);
+
+	/* BYTE - 8,9: Start of bottom bar */
+	avi_iframe[7] = avi_info.bar_info.start_of_bottom_bar & 0xFF;
+	avi_iframe[8] = ((avi_info.bar_info.start_of_bottom_bar & 0xFF00) >> 8);
+
+	/* BYTE - 10,11: Endof of left bar */
+	avi_iframe[9] = avi_info.bar_info.end_of_left_bar & 0xFF;
+	avi_iframe[10] = ((avi_info.bar_info.end_of_left_bar & 0xFF00) >> 8);
+
+	/* BYTE - 12,13: Start of right bar */
+	avi_iframe[11] = avi_info.bar_info.start_of_right_bar & 0xFF;
+	avi_iframe[12] = ((avi_info.bar_info.start_of_right_bar & 0xFF00) >> 8);
 
 	sum = IFRAME_PACKET_OFFSET + AVI_IFRAME_TYPE +
 		AVI_IFRAME_VERSION + AVI_MAX_DATA_BYTES;
 
-	for (index = 0; index < HDMI_VFRMT_MAX; index++) {
-		if (mdss_hdmi_avi_info_db[index][VIC_INDEX] == mdss_hdmi_video_fmt)
-			break;
-	}
-
-	if (index == VIC_INDEX)
-		return;
-
-	mdss_hdmi_avi_info_db[index][DATA_BYTE_1] |=
-		scaninfo & (BIT(1) | BIT(0));
-
 	for (i = 0; i < AVI_MAX_DATA_BYTES; i++)
-		sum += mdss_hdmi_avi_info_db[index][i];
-
+		sum += avi_iframe[i];
 	sum &= 0xFF;
 	sum = 256 - sum;
 	checksum = (uint8_t) sum;
 
 	reg_val = checksum |
-		LEFT_SHIFT_BYTE(mdss_hdmi_avi_info_db[index][DATA_BYTE_1]) |
-		LEFT_SHIFT_WORD(mdss_hdmi_avi_info_db[index][DATA_BYTE_2]) |
-		LEFT_SHIFT_24BITS(mdss_hdmi_avi_info_db[index][DATA_BYTE_3]);
+		LEFT_SHIFT_BYTE(avi_iframe[DATA_BYTE_1]) |
+		LEFT_SHIFT_WORD(avi_iframe[DATA_BYTE_2]) |
+		LEFT_SHIFT_24BITS(avi_iframe[DATA_BYTE_3]);
 	writel(reg_val, HDMI_AVI_INFO0);
 
-	reg_val = mdss_hdmi_avi_info_db[index][DATA_BYTE_4] |
-		LEFT_SHIFT_BYTE(mdss_hdmi_avi_info_db[index][DATA_BYTE_5]) |
-		LEFT_SHIFT_WORD(mdss_hdmi_avi_info_db[index][DATA_BYTE_6]) |
-		LEFT_SHIFT_24BITS(mdss_hdmi_avi_info_db[index][DATA_BYTE_7]);
+	reg_val = avi_iframe[DATA_BYTE_4] |
+		LEFT_SHIFT_BYTE(avi_iframe[DATA_BYTE_5]) |
+		LEFT_SHIFT_WORD(avi_iframe[DATA_BYTE_6]) |
+		LEFT_SHIFT_24BITS(avi_iframe[DATA_BYTE_7]);
 	writel(reg_val, HDMI_AVI_INFO1);
 
-	reg_val = mdss_hdmi_avi_info_db[index][DATA_BYTE_8] |
-		LEFT_SHIFT_BYTE(mdss_hdmi_avi_info_db[index][DATA_BYTE_9]) |
-		LEFT_SHIFT_WORD(mdss_hdmi_avi_info_db[index][DATA_BYTE_10]) |
-		LEFT_SHIFT_24BITS(mdss_hdmi_avi_info_db[index][DATA_BYTE_11]);
+	reg_val = avi_iframe[DATA_BYTE_8] |
+		LEFT_SHIFT_BYTE(avi_iframe[DATA_BYTE_9]) |
+		LEFT_SHIFT_WORD(avi_iframe[DATA_BYTE_10]) |
+		LEFT_SHIFT_24BITS(avi_iframe[DATA_BYTE_11]);
 	writel(reg_val, HDMI_AVI_INFO2);
 
-	reg_val = mdss_hdmi_avi_info_db[index][DATA_BYTE_12] |
-		LEFT_SHIFT_BYTE(mdss_hdmi_avi_info_db[index][DATA_BYTE_13]) |
+	reg_val = avi_iframe[DATA_BYTE_12] |
+		LEFT_SHIFT_BYTE(avi_iframe[DATA_BYTE_13]) |
 		LEFT_SHIFT_24BITS(AVI_IFRAME_VERSION);
 	writel(reg_val, HDMI_AVI_INFO3);
 
 	/* AVI InfFrame enable (every frame) */
 	writel(readl(HDMI_INFOFRAME_CTRL0) | BIT(1) | BIT(0),
-		HDMI_INFOFRAME_CTRL0);
+			HDMI_INFOFRAME_CTRL0);
+
+	reg_val = readl(HDMI_INFOFRAME_CTRL1);
+	reg_val &= ~0x3F;
+	reg_val |= AVI_IFRAME_LINE_NUMBER;
+	writel(reg_val, HDMI_INFOFRAME_CTRL1);
+}
+
+static int mdss_hdmi_ddc_check_status(char *what)
+{
+	uint32_t reg_val;
+	int rc = 0;
+
+	/* Read DDC status */
+	reg_val = readl(HDMI_DDC_SW_STATUS);
+	reg_val &= BIT(12) | BIT(13) | BIT(14) | BIT(15);
+
+	/* Check if any NACK occurred */
+	if (reg_val) {
+		dprintf(SPEW, "%s: %s: NACK: HDMI_DDC_SW_STATUS 0x%x\n",
+			__func__, what, reg_val);
+
+		/* SW_STATUS_RESET, SOFT_RESET */
+		reg_val = BIT(3) | BIT(1);
+
+		writel(reg_val, HDMI_DDC_CTRL);
+
+		rc = ERROR;
+	}
+
+	return rc;
+}
+
+static void mdss_hdmi_ddc_trigger(struct hdmi_tx_ddc_data *ddc_data,
+		enum trigger_mode mode, bool seg)
+{
+	uint32_t const seg_addr = 0x60, seg_num = 0x01;
+	uint32_t ddc_ctrl_reg_val;
+
+	ddc_data->dev_addr &= 0xFE;
+
+	if (mode == TRIGGER_READ && seg) {
+		writel(BIT(31) | (seg_addr << 8), HDMI_DDC_DATA);
+		writel(seg_num << 8, HDMI_DDC_DATA);
+	}
+
+	/* handle portion #1 */
+	writel(BIT(31) | (ddc_data->dev_addr << 8), HDMI_DDC_DATA);
+
+	/* handle portion #2 */
+	writel(ddc_data->offset << 8, HDMI_DDC_DATA);
+
+	if (mode == TRIGGER_READ) {
+		/* handle portion #3 */
+		writel((ddc_data->dev_addr | BIT(0)) << 8, HDMI_DDC_DATA);
+
+		/* HDMI_I2C_TRANSACTION0 */
+		writel(BIT(12) | BIT(16), HDMI_DDC_TRANS0);
+
+		/* Write to HDMI_I2C_TRANSACTION1 */
+		if (seg) {
+			writel(BIT(12) | BIT(16), HDMI_DDC_TRANS1);
+			writel(BIT(0) | BIT(12) | BIT(13) |
+				(ddc_data->request_len << 16), HDMI_DDC_TRANS2);
+
+			ddc_ctrl_reg_val = BIT(0) | BIT(21);
+		} else {
+			writel(BIT(0) | BIT(12) | BIT(13) |
+				(ddc_data->request_len << 16), HDMI_DDC_TRANS1);
+
+			ddc_ctrl_reg_val = BIT(0) | BIT(20);
+		}
+	} else {
+		uint32_t ndx;
+
+		/* write buffer */
+		for (ndx = 0; ndx < ddc_data->data_len; ++ndx)
+			writel(((uint32_t)ddc_data->data_buf[ndx]) << 8,
+					HDMI_DDC_DATA);
+
+		writel((ddc_data->data_len + 1) << 16 | BIT(12) | BIT(13),
+				HDMI_DDC_TRANS0);
+
+		ddc_ctrl_reg_val = BIT(0);
+	}
+
+	/* Trigger the I2C transfer */
+	writel(ddc_ctrl_reg_val, HDMI_DDC_CTRL);
+}
+
+static int mdss_hdmi_ddc_clear_irq(char *what)
+{
+	uint32_t ddc_int_ctrl, ddc_status, in_use, timeout;
+	uint32_t sw_done_mask = BIT(2);
+	uint32_t sw_done_ack  = BIT(1);
+	uint32_t in_use_by_sw = BIT(0);
+	uint32_t in_use_by_hw = BIT(1);
+
+	/* clear and enable interrutps */
+	ddc_int_ctrl = sw_done_mask | sw_done_ack;
+
+	writel(ddc_int_ctrl, HDMI_DDC_INT_CTRL);
+
+	/* wait until DDC HW is free */
+	timeout = 100;
+	do {
+		ddc_status = readl(HDMI_DDC_HW_STATUS);
+		in_use = ddc_status & (in_use_by_sw | in_use_by_hw);
+		if (in_use) {
+			dprintf(INFO, "%s: ddc is in use by %s, timeout(%d)\n",
+					__func__,
+					ddc_status & in_use_by_sw ? "sw" : "hw",
+					timeout);
+			udelay(100);
+		}
+	} while (in_use && --timeout);
+
+	if (!timeout) {
+		dprintf(CRITICAL, "%s: %s: timed out\n", __func__, what);
+		return ERROR;
+	}
+
+	return 0;
+}
+
+static int mdss_hdmi_ddc_read_retry(struct hdmi_tx_ddc_data *ddc_data)
+{
+	uint32_t reg_val, ndx;
+	int status, rc;
+
+	if (!ddc_data) {
+		dprintf(CRITICAL, "%s: invalid input\n", __func__);
+		return ERROR;
+	}
+
+	if (!ddc_data->data_buf) {
+		status = ERROR;
+		dprintf(CRITICAL, "%s: %s: invalid buf\n",
+				__func__, ddc_data->what);
+		goto error;
+	}
+
+	if (ddc_data->retry < 0) {
+		dprintf(CRITICAL, "%s: invalid no. of retries %d\n",
+				__func__, ddc_data->retry);
+		status = ERROR;
+		goto error;
+	}
+
+	do {
+		status = mdss_hdmi_ddc_clear_irq(ddc_data->what);
+		if (status)
+			continue;
+
+		mdss_hdmi_ddc_trigger(ddc_data, TRIGGER_READ, false);
+
+		dprintf(SPEW, "%s: ddc read done\n", __func__);
+
+		rc = mdss_hdmi_ddc_check_status(ddc_data->what);
+
+		if (!status)
+			status = rc;
+
+		udelay(HDMI_DDC_TRANSACTION_DELAY_US);
+	} while (status && ddc_data->retry--);
+
+	if (status)
+		goto error;
+
+	/* Write data to DDC buffer */
+	writel(BIT(0) | (3 << 16) | BIT(31), HDMI_DDC_DATA);
+
+	/* Discard first byte */
+	readl(HDMI_DDC_DATA);
+	for (ndx = 0; ndx < ddc_data->data_len; ++ndx) {
+		reg_val = readl(HDMI_DDC_DATA);
+		ddc_data->data_buf[ndx] = (uint8_t)((reg_val & 0x0000FF00) >> 8);
+	}
+
+	dprintf(SPEW, "%s: %s: success\n", __func__, ddc_data->what);
+error:
+	return status;
+}
+
+static int mdss_hdmi_ddc_read(struct hdmi_tx_ddc_data *ddc_data)
+{
+	int rc = 0;
+	int retry;
+
+	if (!ddc_data) {
+		dprintf(CRITICAL, "%s: invalid ddc data\n", __func__);
+		return ERROR;
+	}
+
+	retry = ddc_data->retry;
+
+	rc = mdss_hdmi_ddc_read_retry(ddc_data);
+	if (!rc)
+		return rc;
+
+	if (ddc_data->retry_align) {
+		ddc_data->retry = retry;
+
+		ddc_data->request_len = 32 * ((ddc_data->data_len + 31) / 32);
+		rc = mdss_hdmi_ddc_read_retry(ddc_data);
+	}
+
+	return rc;
+}
+
+static int mdss_hdmi_ddc_write(struct hdmi_tx_ddc_data *ddc_data)
+{
+	int status, rc;
+
+	if (!ddc_data->data_buf) {
+		status = ERROR;
+		dprintf(CRITICAL, "%s: %s: invalid buf\n",
+				__func__, ddc_data->what);
+		goto error;
+	}
+
+	if (ddc_data->retry < 0) {
+		dprintf(CRITICAL, "%s: invalid no. of retries %d\n",
+				__func__, ddc_data->retry);
+		status = ERROR;
+		goto error;
+	}
+
+	do {
+		status = mdss_hdmi_ddc_clear_irq(ddc_data->what);
+		if (status)
+			continue;
+
+		mdss_hdmi_ddc_trigger(ddc_data, TRIGGER_WRITE, false);
+
+		dprintf(SPEW, "%s: DDC write done\n", __func__);
+
+		rc = mdss_hdmi_ddc_check_status(ddc_data->what);
+
+		if (!status)
+			status = rc;
+
+		udelay(HDMI_DDC_TRANSACTION_DELAY_US);
+	} while (status && ddc_data->retry--);
+
+	if (status)
+		goto error;
+
+	dprintf(SPEW, "%s: %s: success\n", __func__, ddc_data->what);
+error:
+	return status;
+}
+
+static inline char *mdss_hdmi_scdc_reg2string(uint32_t type)
+{
+	switch (type) {
+	case SCDC_SCRAMBLING_STATUS:
+		return "SCDC_SCRAMBLING_STATUS";
+	case SCDC_SCRAMBLING_ENABLE:
+		return "SCDC_SCRAMBLING_ENABLE";
+	case SCDC_TMDS_BIT_CLOCK_RATIO_UPDATE:
+		return "SCDC_TMDS_BIT_CLOCK_RATIO_UPDATE";
+	case SCDC_CLOCK_DET_STATUS:
+		return "SCDC_CLOCK_DET_STATUS";
+	case SCDC_CH0_LOCK_STATUS:
+		return "SCDC_CH0_LOCK_STATUS";
+	case SCDC_CH1_LOCK_STATUS:
+		return "SCDC_CH1_LOCK_STATUS";
+	case SCDC_CH2_LOCK_STATUS:
+		return "SCDC_CH2_LOCK_STATUS";
+	case SCDC_CH0_ERROR_COUNT:
+		return "SCDC_CH0_ERROR_COUNT";
+	case SCDC_CH1_ERROR_COUNT:
+		return "SCDC_CH1_ERROR_COUNT";
+	case SCDC_CH2_ERROR_COUNT:
+		return "SCDC_CH2_ERROR_COUNT";
+	case SCDC_READ_ENABLE:
+		return"SCDC_READ_ENABLE";
+	default:
+		return HDMI_SCDC_UNKNOWN_REGISTER;
+	}
+}
+
+static int mdss_hdmi_scdc_write(uint32_t data_type, uint32_t val)
+{
+	struct hdmi_tx_ddc_data data = {0};
+	struct hdmi_tx_ddc_data rdata = {0};
+	int rc = 0;
+	uint8_t data_buf[2] = {0};
+	uint8_t read_val = 0;
+
+	if (data_type >= SCDC_MAX) {
+		dprintf(CRITICAL, "Unsupported data type\n");
+		return ERROR;
+	}
+
+	data.what = mdss_hdmi_scdc_reg2string(data_type);
+	data.dev_addr = 0xA8;
+	data.retry = 1;
+	data.data_buf = data_buf;
+
+	switch (data_type) {
+	case SCDC_SCRAMBLING_ENABLE:
+	case SCDC_TMDS_BIT_CLOCK_RATIO_UPDATE:
+		rdata.what = "TMDS CONFIG";
+		rdata.dev_addr = 0xA8;
+		rdata.retry = 2;
+		rdata.data_buf = &read_val;
+		rdata.data_len = 1;
+		rdata.offset = HDMI_SCDC_TMDS_CONFIG;
+		rdata.request_len = 1;
+		rc = mdss_hdmi_ddc_read(&rdata);
+		if (rc) {
+			dprintf(CRITICAL, "scdc read failed\n");
+			return rc;
+		}
+		if (data_type == SCDC_SCRAMBLING_ENABLE) {
+			data_buf[0] = ((((uint8_t)(read_val & 0xFF)) & (~BIT(0))) |
+					((uint8_t)(val & BIT(0))));
+		} else {
+			data_buf[0] = ((((uint8_t)(read_val & 0xFF)) & (~BIT(1))) |
+					(((uint8_t)(val & BIT(0))) << 1));
+		}
+		data.data_len = 1;
+		data.request_len = 1;
+		data.offset = HDMI_SCDC_TMDS_CONFIG;
+		break;
+	case SCDC_READ_ENABLE:
+		data.data_len = 1;
+		data.request_len = 1;
+		data.offset = HDMI_SCDC_CONFIG_0;
+		data_buf[0] = (uint8_t)(val & 0x1);
+		break;
+	default:
+		dprintf(CRITICAL, "Cannot write to read only reg (%d)\n",
+			data_type);
+		return ERROR;
+	}
+
+	rc = mdss_hdmi_ddc_write(&data);
+	if (rc) {
+		dprintf(CRITICAL, "DDC Read failed for %s\n", data.what);
+		return rc;
+	}
+
+	return 0;
+}
+
+static inline int mdss_hdmi_get_v_total(const struct mdss_hdmi_timing_info *t)
+{
+	if (t) {
+		return t->active_v + t->front_porch_v + t->pulse_width_v +
+			t->back_porch_v;
+	}
+
+	return 0;
+}
+
+static int mdss_hdmi_get_timeout_in_hysnc(struct mdss_hdmi_timing_info *timing,
+		uint32_t timeout_ms)
+{
+	uint32_t fps, v_total;
+	uint32_t time_taken_by_one_line_us, lines_needed_for_given_time;
+
+	if (!timing || !timeout_ms) {
+		dprintf(CRITICAL, "invalid input\n");
+		return ERROR;
+	}
+
+	fps = timing->refresh_rate / HDMI_KHZ_TO_HZ;
+	v_total = mdss_hdmi_get_v_total(timing);
+
+	/*
+	 * pixel clock  = h_total * v_total * fps
+	 * 1 sec = pixel clock number of pixels are transmitted.
+	 * time taken by one line (h_total) = 1 / (v_total * fps).
+	 */
+	time_taken_by_one_line_us = HDMI_SEC_TO_US / (v_total * fps);
+	lines_needed_for_given_time = (timeout_ms * HDMI_MS_TO_US) /
+		time_taken_by_one_line_us;
+
+	return lines_needed_for_given_time;
+}
+
+static void mdss_hdmi_scrambler_ddc_reset()
+{
+	uint32_t reg_val;
+
+	/* clear ack and disable interrupts */
+	reg_val = BIT(14) | BIT(9) | BIT(5) | BIT(1);
+	writel(reg_val, HDMI_DDC_INT_CTRL2);
+
+	/* Reset DDC timers */
+	reg_val = BIT(0) | readl(HDMI_SCRAMBLER_STATUS_DDC_CTRL);
+	writel(reg_val, HDMI_SCRAMBLER_STATUS_DDC_CTRL);
+
+	reg_val = readl(HDMI_SCRAMBLER_STATUS_DDC_CTRL);
+	reg_val &= ~BIT(0);
+	writel(reg_val, HDMI_SCRAMBLER_STATUS_DDC_CTRL);
+}
+
+static void mdss_hdmi_scrambler_ddc_disable()
+{
+	uint32_t reg_val;
+
+	mdss_hdmi_scrambler_ddc_reset();
+
+	/* Disable HW DDC access to RxStatus register */
+	reg_val = readl(HDMI_HW_DDC_CTRL);
+	reg_val &= ~(BIT(8) | BIT(9));
+
+	writel(reg_val, HDMI_HW_DDC_CTRL);
+}
+
+static int mdss_hdmi_scrambler_ddc_check_status()
+{
+	int rc = 0;
+	uint32_t reg_val;
+
+	/* check for errors and clear status */
+	reg_val = readl(HDMI_SCRAMBLER_STATUS_DDC_STATUS);
+
+	if (reg_val & BIT(4)) {
+		dprintf(CRITICAL, "ddc aborted\n");
+		reg_val |= BIT(5);
+		rc = ERROR;
+	}
+
+	if (reg_val & BIT(8)) {
+		dprintf(CRITICAL, "timed out\n");
+		reg_val |= BIT(9);
+		rc = ERROR;
+	}
+
+	if (reg_val & BIT(12)) {
+		dprintf(CRITICAL, "NACK0\n");
+		reg_val |= BIT(13);
+		rc = ERROR;
+	}
+
+	if (reg_val & BIT(14)) {
+		dprintf(CRITICAL, "NACK1\n");
+		reg_val |= BIT(15);
+		rc = ERROR;
+	}
+
+	writel(reg_val, HDMI_SCRAMBLER_STATUS_DDC_STATUS);
+
+	return rc;
+}
+
+static int mdss_hdmi_scrambler_status_timer_setup(uint32_t timeout_hsync)
+{
+	uint32_t reg_val;
+	int rc;
+
+	mdss_hdmi_ddc_clear_irq("scrambler");
+
+	writel(timeout_hsync, HDMI_SCRAMBLER_STATUS_DDC_TIMER_CTRL);
+	writel(timeout_hsync, HDMI_SCRAMBLER_STATUS_DDC_TIMER_CTRL2);
+
+	reg_val = readl(HDMI_DDC_INT_CTRL5);
+	reg_val |= BIT(10);
+	writel(reg_val, HDMI_DDC_INT_CTRL5);
+
+	reg_val = readl(HDMI_DDC_INT_CTRL2);
+	/* Trigger interrupt if scrambler status is 0 or DDC failure */
+	reg_val |= BIT(10);
+	reg_val &= ~(BIT(15) | BIT(16));
+	reg_val |= BIT(16);
+	writel(reg_val, HDMI_DDC_INT_CTRL2);
+
+	/* Enable DDC access */
+	reg_val = readl(HDMI_HW_DDC_CTRL);
+
+	reg_val &= ~(BIT(8) | BIT(9));
+	reg_val |= BIT(8);
+	writel(reg_val, HDMI_HW_DDC_CTRL);
+
+	/* WAIT for 200ms as per HDMI 2.0 standard for sink to respond */
+	udelay(2000);
+
+	/* clear the scrambler status */
+	rc = mdss_hdmi_scrambler_ddc_check_status();
+	if (rc)
+		dprintf(CRITICAL, "scrambling ddc error %d\n", rc);
+
+	mdss_hdmi_scrambler_ddc_disable();
+
+	return rc;
+}
+
+static int mdss_hdmi_setup_ddc_timers(uint32_t type, uint32_t to_in_num_lines)
+{
+	if (type >= DDC_TIMER_MAX) {
+		dprintf(CRITICAL, "Invalid timer type %d\n", type);
+		return ERROR;
+	}
+
+	switch (type) {
+	case DDC_TIMER_SCRAMBLER_STATUS:
+		mdss_hdmi_scrambler_status_timer_setup(to_in_num_lines);
+		break;
+	default:
+		dprintf(CRITICAL, "%d type not supported\n", type);
+		return ERROR;
+	}
+
+	return 0;
+}
+
+static int mdss_hdmi_setup_scrambler()
+{
+	int rc = 0;
+	uint32_t reg_val = 0;
+	uint32_t tmds_clock_ratio = 0;
+	bool scrambler_on = false;
+	struct mdss_hdmi_timing_info timing = {0};
+	mdss_hdmi_get_timing_info(&timing, mdss_hdmi_video_fmt);
+	int timeout_hsync;
+
+	/* Scrambling is supported from HDMI TX 4.0 */
+	reg_val = readl(HDMI_VERSION);
+	reg_val = (reg_val & 0xF0000000) >> 28;
+	if (reg_val < HDMI_TX_SCRAMBLER_MIN_TX_VERSION) {
+		dprintf(INFO, "%s: HDMI TX does not support scrambling\n",
+				__func__);
+		return 0;
+	}
+
+	if (timing.pixel_freq > HDMI_TX_SCRAMBLER_THRESHOLD_RATE_KHZ) {
+		scrambler_on = true;
+		tmds_clock_ratio = 1;
+	}
+
+	dprintf(SPEW, "%s: freq=%d, scrambler=%d, clock_ratio=%d\n",
+			__func__, timing.pixel_freq, scrambler_on,
+			tmds_clock_ratio);
+
+	if (scrambler_on) {
+		rc = mdss_hdmi_scdc_write(SCDC_TMDS_BIT_CLOCK_RATIO_UPDATE,
+				tmds_clock_ratio);
+		if (rc) {
+			dprintf(CRITICAL, "%s: TMDS CLK RATIO ERR\n", __func__);
+			return rc;
+		}
+
+		reg_val = readl(HDMI_CTRL);
+		reg_val |= BIT(31); /* Enable Update DATAPATH_MODE */
+		reg_val |= BIT(28); /* Set SCRAMBLER_EN bit */
+
+		writel(reg_val, HDMI_CTRL);
+
+		rc = mdss_hdmi_scdc_write(SCDC_SCRAMBLING_ENABLE, 0x1);
+		if (rc) {
+			dprintf(CRITICAL, "%s: failed to enable scrambling\n",
+				__func__);
+			return rc;
+		}
+
+		/*
+		 * Setup hardware to periodically check for scrambler
+		 * status bit on the sink. Sink should set this bit
+		 * with in 200ms after scrambler is enabled.
+		 */
+		timeout_hsync = mdss_hdmi_get_timeout_in_hysnc(&timing,
+				HDMI_TX_SCRAMBLER_TIMEOUT_MSEC);
+
+		if (timeout_hsync <= 0) {
+			dprintf(CRITICAL, "%s: err in timeout hsync calc\n",
+					__func__);
+			timeout_hsync = HDMI_DEFAULT_TIMEOUT_HSYNC;
+		}
+
+		dprintf(SPEW, "%s: timeout for scrambling en: %d hsyncs\n",
+				__func__, timeout_hsync);
+
+		rc = mdss_hdmi_setup_ddc_timers(DDC_TIMER_SCRAMBLER_STATUS,
+				timeout_hsync);
+	} else {
+		mdss_hdmi_scdc_write(SCDC_SCRAMBLING_ENABLE, 0x0);
+	}
+
+	return rc;
 }
 
 int mdss_hdmi_init(void)
@@ -1127,6 +2043,9 @@
 
 	mdss_hdmi_set_mode(false);
 
+	/* Enable USEC REF timer */
+	writel(0x0001001B, HDMI_USEC_REFTIMER);
+
 	/* Audio settings */
 	if (!is_dvi_mode)
 		mdss_hdmi_audio_playback();
@@ -1141,5 +2060,7 @@
 	/* Enable HDMI */
 	mdss_hdmi_set_mode(true);
 
+	mdss_hdmi_setup_scrambler();
+
 	return 0;
 }
diff --git a/platform/msm_shared/mdss_hdmi_pll_8996.c b/platform/msm_shared/mdss_hdmi_pll_8996.c
new file mode 100644
index 0000000..ef0a6d9
--- /dev/null
+++ b/platform/msm_shared/mdss_hdmi_pll_8996.c
@@ -0,0 +1,910 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name of The Linux Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <debug.h>
+#include <err.h>
+#include <reg.h>
+#include <smem.h>
+#include <bits.h>
+#include <msm_panel.h>
+#include <platform/timer.h>
+#include <platform/iomap.h>
+
+/* PLL REGISTERS */
+#define HDMI_PLL_BASE_OFFSET                     (0x9A0600)
+#define QSERDES_COM_ATB_SEL1                     (HDMI_PLL_BASE_OFFSET + 0x000)
+#define QSERDES_COM_ATB_SEL2                     (HDMI_PLL_BASE_OFFSET + 0x004)
+#define QSERDES_COM_FREQ_UPDATE                  (HDMI_PLL_BASE_OFFSET + 0x008)
+#define QSERDES_COM_BG_TIMER                     (HDMI_PLL_BASE_OFFSET + 0x00C)
+#define QSERDES_COM_SSC_EN_CENTER                (HDMI_PLL_BASE_OFFSET + 0x010)
+#define QSERDES_COM_SSC_ADJ_PER1                 (HDMI_PLL_BASE_OFFSET + 0x014)
+#define QSERDES_COM_SSC_ADJ_PER2                 (HDMI_PLL_BASE_OFFSET + 0x018)
+#define QSERDES_COM_SSC_PER1                     (HDMI_PLL_BASE_OFFSET + 0x01C)
+#define QSERDES_COM_SSC_PER2                     (HDMI_PLL_BASE_OFFSET + 0x020)
+#define QSERDES_COM_SSC_STEP_SIZE1               (HDMI_PLL_BASE_OFFSET + 0x024)
+#define QSERDES_COM_SSC_STEP_SIZE2               (HDMI_PLL_BASE_OFFSET + 0x028)
+#define QSERDES_COM_POST_DIV                     (HDMI_PLL_BASE_OFFSET + 0x02C)
+#define QSERDES_COM_POST_DIV_MUX                 (HDMI_PLL_BASE_OFFSET + 0x030)
+#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN          (HDMI_PLL_BASE_OFFSET + 0x034)
+#define QSERDES_COM_CLK_ENABLE1                  (HDMI_PLL_BASE_OFFSET + 0x038)
+#define QSERDES_COM_SYS_CLK_CTRL                 (HDMI_PLL_BASE_OFFSET + 0x03C)
+#define QSERDES_COM_SYSCLK_BUF_ENABLE            (HDMI_PLL_BASE_OFFSET + 0x040)
+#define QSERDES_COM_PLL_EN                       (HDMI_PLL_BASE_OFFSET + 0x044)
+#define QSERDES_COM_PLL_IVCO                     (HDMI_PLL_BASE_OFFSET + 0x048)
+#define QSERDES_COM_LOCK_CMP1_MODE0              (HDMI_PLL_BASE_OFFSET + 0x04C)
+#define QSERDES_COM_LOCK_CMP2_MODE0              (HDMI_PLL_BASE_OFFSET + 0x050)
+#define QSERDES_COM_LOCK_CMP3_MODE0              (HDMI_PLL_BASE_OFFSET + 0x054)
+#define QSERDES_COM_LOCK_CMP1_MODE1              (HDMI_PLL_BASE_OFFSET + 0x058)
+#define QSERDES_COM_LOCK_CMP2_MODE1              (HDMI_PLL_BASE_OFFSET + 0x05C)
+#define QSERDES_COM_LOCK_CMP3_MODE1              (HDMI_PLL_BASE_OFFSET + 0x060)
+#define QSERDES_COM_LOCK_CMP1_MODE2              (HDMI_PLL_BASE_OFFSET + 0x064)
+#define QSERDES_COM_CMN_RSVD0                    (HDMI_PLL_BASE_OFFSET + 0x064)
+#define QSERDES_COM_LOCK_CMP2_MODE2              (HDMI_PLL_BASE_OFFSET + 0x068)
+#define QSERDES_COM_EP_CLOCK_DETECT_CTRL         (HDMI_PLL_BASE_OFFSET + 0x068)
+#define QSERDES_COM_LOCK_CMP3_MODE2              (HDMI_PLL_BASE_OFFSET + 0x06C)
+#define QSERDES_COM_SYSCLK_DET_COMP_STATUS       (HDMI_PLL_BASE_OFFSET + 0x06C)
+#define QSERDES_COM_BG_TRIM                      (HDMI_PLL_BASE_OFFSET + 0x070)
+#define QSERDES_COM_CLK_EP_DIV                   (HDMI_PLL_BASE_OFFSET + 0x074)
+#define QSERDES_COM_CP_CTRL_MODE0                (HDMI_PLL_BASE_OFFSET + 0x078)
+#define QSERDES_COM_CP_CTRL_MODE1                (HDMI_PLL_BASE_OFFSET + 0x07C)
+#define QSERDES_COM_CP_CTRL_MODE2                (HDMI_PLL_BASE_OFFSET + 0x080)
+#define QSERDES_COM_CMN_RSVD1                    (HDMI_PLL_BASE_OFFSET + 0x080)
+#define QSERDES_COM_PLL_RCTRL_MODE0              (HDMI_PLL_BASE_OFFSET + 0x084)
+#define QSERDES_COM_PLL_RCTRL_MODE1              (HDMI_PLL_BASE_OFFSET + 0x088)
+#define QSERDES_COM_PLL_RCTRL_MODE2              (HDMI_PLL_BASE_OFFSET + 0x08C)
+#define QSERDES_COM_CMN_RSVD2                    (HDMI_PLL_BASE_OFFSET + 0x08C)
+#define QSERDES_COM_PLL_CCTRL_MODE0              (HDMI_PLL_BASE_OFFSET + 0x090)
+#define QSERDES_COM_PLL_CCTRL_MODE1              (HDMI_PLL_BASE_OFFSET + 0x094)
+#define QSERDES_COM_PLL_CCTRL_MODE2              (HDMI_PLL_BASE_OFFSET + 0x098)
+#define QSERDES_COM_CMN_RSVD3                    (HDMI_PLL_BASE_OFFSET + 0x098)
+#define QSERDES_COM_PLL_CNTRL                    (HDMI_PLL_BASE_OFFSET + 0x09C)
+#define QSERDES_COM_PHASE_SEL_CTRL               (HDMI_PLL_BASE_OFFSET + 0x0A0)
+#define QSERDES_COM_PHASE_SEL_DC                 (HDMI_PLL_BASE_OFFSET + 0x0A4)
+#define QSERDES_COM_CORE_CLK_IN_SYNC_SEL         (HDMI_PLL_BASE_OFFSET + 0x0A8)
+#define QSERDES_COM_BIAS_EN_CTRL_BY_PSM          (HDMI_PLL_BASE_OFFSET + 0x0A8)
+#define QSERDES_COM_SYSCLK_EN_SEL                (HDMI_PLL_BASE_OFFSET + 0x0AC)
+#define QSERDES_COM_CML_SYSCLK_SEL               (HDMI_PLL_BASE_OFFSET + 0x0B0)
+#define QSERDES_COM_RESETSM_CNTRL                (HDMI_PLL_BASE_OFFSET + 0x0B4)
+#define QSERDES_COM_RESETSM_CNTRL2               (HDMI_PLL_BASE_OFFSET + 0x0B8)
+#define QSERDES_COM_RESTRIM_CTRL                 (HDMI_PLL_BASE_OFFSET + 0x0BC)
+#define QSERDES_COM_RESTRIM_CTRL2                (HDMI_PLL_BASE_OFFSET + 0x0C0)
+#define QSERDES_COM_RESCODE_DIV_NUM              (HDMI_PLL_BASE_OFFSET + 0x0C4)
+#define QSERDES_COM_LOCK_CMP_EN                  (HDMI_PLL_BASE_OFFSET + 0x0C8)
+#define QSERDES_COM_LOCK_CMP_CFG                 (HDMI_PLL_BASE_OFFSET + 0x0CC)
+#define QSERDES_COM_DEC_START_MODE0              (HDMI_PLL_BASE_OFFSET + 0x0D0)
+#define QSERDES_COM_DEC_START_MODE1              (HDMI_PLL_BASE_OFFSET + 0x0D4)
+#define QSERDES_COM_DEC_START_MODE2              (HDMI_PLL_BASE_OFFSET + 0x0D8)
+#define QSERDES_COM_VCOCAL_DEADMAN_CTRL          (HDMI_PLL_BASE_OFFSET + 0x0D8)
+#define QSERDES_COM_DIV_FRAC_START1_MODE0        (HDMI_PLL_BASE_OFFSET + 0x0DC)
+#define QSERDES_COM_DIV_FRAC_START2_MODE0        (HDMI_PLL_BASE_OFFSET + 0x0E0)
+#define QSERDES_COM_DIV_FRAC_START3_MODE0        (HDMI_PLL_BASE_OFFSET + 0x0E4)
+#define QSERDES_COM_DIV_FRAC_START1_MODE1        (HDMI_PLL_BASE_OFFSET + 0x0E8)
+#define QSERDES_COM_DIV_FRAC_START2_MODE1        (HDMI_PLL_BASE_OFFSET + 0x0EC)
+#define QSERDES_COM_DIV_FRAC_START3_MODE1        (HDMI_PLL_BASE_OFFSET + 0x0F0)
+#define QSERDES_COM_DIV_FRAC_START1_MODE2        (HDMI_PLL_BASE_OFFSET + 0x0F4)
+#define QSERDES_COM_VCO_TUNE_MINVAL1             (HDMI_PLL_BASE_OFFSET + 0x0F4)
+#define QSERDES_COM_DIV_FRAC_START2_MODE2        (HDMI_PLL_BASE_OFFSET + 0x0F8)
+#define QSERDES_COM_VCO_TUNE_MINVAL2             (HDMI_PLL_BASE_OFFSET + 0x0F8)
+#define QSERDES_COM_DIV_FRAC_START3_MODE2        (HDMI_PLL_BASE_OFFSET + 0x0FC)
+#define QSERDES_COM_CMN_RSVD4                    (HDMI_PLL_BASE_OFFSET + 0x0FC)
+#define QSERDES_COM_INTEGLOOP_INITVAL            (HDMI_PLL_BASE_OFFSET + 0x100)
+#define QSERDES_COM_INTEGLOOP_EN                 (HDMI_PLL_BASE_OFFSET + 0x104)
+#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0        (HDMI_PLL_BASE_OFFSET + 0x108)
+#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0        (HDMI_PLL_BASE_OFFSET + 0x10C)
+#define QSERDES_COM_INTEGLOOP_GAIN0_MODE1        (HDMI_PLL_BASE_OFFSET + 0x110)
+#define QSERDES_COM_INTEGLOOP_GAIN1_MODE1        (HDMI_PLL_BASE_OFFSET + 0x114)
+#define QSERDES_COM_INTEGLOOP_GAIN0_MODE2        (HDMI_PLL_BASE_OFFSET + 0x118)
+#define QSERDES_COM_VCO_TUNE_MAXVAL1             (HDMI_PLL_BASE_OFFSET + 0x118)
+#define QSERDES_COM_INTEGLOOP_GAIN1_MODE2        (HDMI_PLL_BASE_OFFSET + 0x11C)
+#define QSERDES_COM_VCO_TUNE_MAXVAL2             (HDMI_PLL_BASE_OFFSET + 0x11C)
+#define QSERDES_COM_RES_TRIM_CONTROL2            (HDMI_PLL_BASE_OFFSET + 0x120)
+#define QSERDES_COM_VCO_TUNE_CTRL                (HDMI_PLL_BASE_OFFSET + 0x124)
+#define QSERDES_COM_VCO_TUNE_MAP                 (HDMI_PLL_BASE_OFFSET + 0x128)
+#define QSERDES_COM_VCO_TUNE1_MODE0              (HDMI_PLL_BASE_OFFSET + 0x12C)
+#define QSERDES_COM_VCO_TUNE2_MODE0              (HDMI_PLL_BASE_OFFSET + 0x130)
+#define QSERDES_COM_VCO_TUNE1_MODE1              (HDMI_PLL_BASE_OFFSET + 0x134)
+#define QSERDES_COM_VCO_TUNE2_MODE1              (HDMI_PLL_BASE_OFFSET + 0x138)
+#define QSERDES_COM_VCO_TUNE1_MODE2              (HDMI_PLL_BASE_OFFSET + 0x13C)
+#define QSERDES_COM_VCO_TUNE_INITVAL1            (HDMI_PLL_BASE_OFFSET + 0x13C)
+#define QSERDES_COM_VCO_TUNE2_MODE2              (HDMI_PLL_BASE_OFFSET + 0x140)
+#define QSERDES_COM_VCO_TUNE_INITVAL2            (HDMI_PLL_BASE_OFFSET + 0x140)
+#define QSERDES_COM_VCO_TUNE_TIMER1              (HDMI_PLL_BASE_OFFSET + 0x144)
+#define QSERDES_COM_VCO_TUNE_TIMER2              (HDMI_PLL_BASE_OFFSET + 0x148)
+#define QSERDES_COM_SAR                          (HDMI_PLL_BASE_OFFSET + 0x14C)
+#define QSERDES_COM_SAR_CLK                      (HDMI_PLL_BASE_OFFSET + 0x150)
+#define QSERDES_COM_SAR_CODE_OUT_STATUS          (HDMI_PLL_BASE_OFFSET + 0x154)
+#define QSERDES_COM_SAR_CODE_READY_STATUS        (HDMI_PLL_BASE_OFFSET + 0x158)
+#define QSERDES_COM_CMN_STATUS                   (HDMI_PLL_BASE_OFFSET + 0x15C)
+#define QSERDES_COM_RESET_SM_STATUS              (HDMI_PLL_BASE_OFFSET + 0x160)
+#define QSERDES_COM_RESTRIM_CODE_STATUS          (HDMI_PLL_BASE_OFFSET + 0x164)
+#define QSERDES_COM_PLLCAL_CODE1_STATUS          (HDMI_PLL_BASE_OFFSET + 0x168)
+#define QSERDES_COM_PLLCAL_CODE2_STATUS          (HDMI_PLL_BASE_OFFSET + 0x16C)
+#define QSERDES_COM_BG_CTRL                      (HDMI_PLL_BASE_OFFSET + 0x170)
+#define QSERDES_COM_CLK_SELECT                   (HDMI_PLL_BASE_OFFSET + 0x174)
+#define QSERDES_COM_HSCLK_SEL                    (HDMI_PLL_BASE_OFFSET + 0x178)
+#define QSERDES_COM_INTEGLOOP_BINCODE_STATUS     (HDMI_PLL_BASE_OFFSET + 0x17C)
+#define QSERDES_COM_PLL_ANALOG                   (HDMI_PLL_BASE_OFFSET + 0x180)
+#define QSERDES_COM_CORECLK_DIV                  (HDMI_PLL_BASE_OFFSET + 0x184)
+#define QSERDES_COM_SW_RESET                     (HDMI_PLL_BASE_OFFSET + 0x188)
+#define QSERDES_COM_CORE_CLK_EN                  (HDMI_PLL_BASE_OFFSET + 0x18C)
+#define QSERDES_COM_C_READY_STATUS               (HDMI_PLL_BASE_OFFSET + 0x190)
+#define QSERDES_COM_CMN_CONFIG                   (HDMI_PLL_BASE_OFFSET + 0x194)
+#define QSERDES_COM_CMN_RATE_OVERRIDE            (HDMI_PLL_BASE_OFFSET + 0x198)
+#define QSERDES_COM_SVS_MODE_CLK_SEL             (HDMI_PLL_BASE_OFFSET + 0x19C)
+#define QSERDES_COM_DEBUG_BUS0                   (HDMI_PLL_BASE_OFFSET + 0x1A0)
+#define QSERDES_COM_DEBUG_BUS1                   (HDMI_PLL_BASE_OFFSET + 0x1A4)
+#define QSERDES_COM_DEBUG_BUS2                   (HDMI_PLL_BASE_OFFSET + 0x1A8)
+#define QSERDES_COM_DEBUG_BUS3                   (HDMI_PLL_BASE_OFFSET + 0x1AC)
+#define QSERDES_COM_DEBUG_BUS_SEL                (HDMI_PLL_BASE_OFFSET + 0x1B0)
+#define QSERDES_COM_CMN_MISC1                    (HDMI_PLL_BASE_OFFSET + 0x1B4)
+#define QSERDES_COM_CMN_MISC2                    (HDMI_PLL_BASE_OFFSET + 0x1B8)
+#define QSERDES_COM_CORECLK_DIV_MODE1            (HDMI_PLL_BASE_OFFSET + 0x1BC)
+#define QSERDES_COM_CORECLK_DIV_MODE2            (HDMI_PLL_BASE_OFFSET + 0x1C0)
+#define QSERDES_COM_CMN_RSVD5                    (HDMI_PLL_BASE_OFFSET + 0x1C0)
+
+/* Tx Channel base addresses */
+#define HDMI_TX_L0_BASE_OFFSET                   (HDMI_PLL_BASE_OFFSET + 0x400)
+#define HDMI_TX_L1_BASE_OFFSET                   (HDMI_PLL_BASE_OFFSET + 0x600)
+#define HDMI_TX_L2_BASE_OFFSET                   (HDMI_PLL_BASE_OFFSET + 0x800)
+#define HDMI_TX_L3_BASE_OFFSET                   (HDMI_PLL_BASE_OFFSET + 0xA00)
+
+/* Tx Channel PHY registers */
+#define QSERDES_TX_L0_BIST_MODE_LANENO                    (0x000)
+#define QSERDES_TX_L0_BIST_INVERT                         (0x004)
+#define QSERDES_TX_L0_CLKBUF_ENABLE                       (0x008)
+#define QSERDES_TX_L0_CMN_CONTROL_ONE                     (0x00C)
+#define QSERDES_TX_L0_CMN_CONTROL_TWO                     (0x010)
+#define QSERDES_TX_L0_CMN_CONTROL_THREE                   (0x014)
+#define QSERDES_TX_L0_TX_EMP_POST1_LVL                    (0x018)
+#define QSERDES_TX_L0_TX_POST2_EMPH                       (0x01C)
+#define QSERDES_TX_L0_TX_BOOST_LVL_UP_DN                  (0x020)
+#define QSERDES_TX_L0_HP_PD_ENABLES                       (0x024)
+#define QSERDES_TX_L0_TX_IDLE_LVL_LARGE_AMP               (0x028)
+#define QSERDES_TX_L0_TX_DRV_LVL                          (0x02C)
+#define QSERDES_TX_L0_TX_DRV_LVL_OFFSET                   (0x030)
+#define QSERDES_TX_L0_RESET_TSYNC_EN                      (0x034)
+#define QSERDES_TX_L0_PRE_STALL_LDO_BOOST_EN              (0x038)
+#define QSERDES_TX_L0_TX_BAND                             (0x03C)
+#define QSERDES_TX_L0_SLEW_CNTL                           (0x040)
+#define QSERDES_TX_L0_INTERFACE_SELECT                    (0x044)
+#define QSERDES_TX_L0_LPB_EN                              (0x048)
+#define QSERDES_TX_L0_RES_CODE_LANE_TX                    (0x04C)
+#define QSERDES_TX_L0_RES_CODE_LANE_RX                    (0x050)
+#define QSERDES_TX_L0_RES_CODE_LANE_OFFSET                (0x054)
+#define QSERDES_TX_L0_PERL_LENGTH1                        (0x058)
+#define QSERDES_TX_L0_PERL_LENGTH2                        (0x05C)
+#define QSERDES_TX_L0_SERDES_BYP_EN_OUT                   (0x060)
+#define QSERDES_TX_L0_DEBUG_BUS_SEL                       (0x064)
+#define QSERDES_TX_L0_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN    (0x068)
+#define QSERDES_TX_L0_TX_POL_INV                          (0x06C)
+#define QSERDES_TX_L0_PARRATE_REC_DETECT_IDLE_EN          (0x070)
+#define QSERDES_TX_L0_BIST_PATTERN1                       (0x074)
+#define QSERDES_TX_L0_BIST_PATTERN2                       (0x078)
+#define QSERDES_TX_L0_BIST_PATTERN3                       (0x07C)
+#define QSERDES_TX_L0_BIST_PATTERN4                       (0x080)
+#define QSERDES_TX_L0_BIST_PATTERN5                       (0x084)
+#define QSERDES_TX_L0_BIST_PATTERN6                       (0x088)
+#define QSERDES_TX_L0_BIST_PATTERN7                       (0x08C)
+#define QSERDES_TX_L0_BIST_PATTERN8                       (0x090)
+#define QSERDES_TX_L0_LANE_MODE                           (0x094)
+#define QSERDES_TX_L0_IDAC_CAL_LANE_MODE                  (0x098)
+#define QSERDES_TX_L0_IDAC_CAL_LANE_MODE_CONFIGURATION    (0x09C)
+#define QSERDES_TX_L0_ATB_SEL1                            (0x0A0)
+#define QSERDES_TX_L0_ATB_SEL2                            (0x0A4)
+#define QSERDES_TX_L0_RCV_DETECT_LVL                      (0x0A8)
+#define QSERDES_TX_L0_RCV_DETECT_LVL_2                    (0x0AC)
+#define QSERDES_TX_L0_PRBS_SEED1                          (0x0B0)
+#define QSERDES_TX_L0_PRBS_SEED2                          (0x0B4)
+#define QSERDES_TX_L0_PRBS_SEED3                          (0x0B8)
+#define QSERDES_TX_L0_PRBS_SEED4                          (0x0BC)
+#define QSERDES_TX_L0_RESET_GEN                           (0x0C0)
+#define QSERDES_TX_L0_RESET_GEN_MUXES                     (0x0C4)
+#define QSERDES_TX_L0_TRAN_DRVR_EMP_EN                    (0x0C8)
+#define QSERDES_TX_L0_TX_INTERFACE_MODE                   (0x0CC)
+#define QSERDES_TX_L0_PWM_CTRL                            (0x0D0)
+#define QSERDES_TX_L0_PWM_ENCODED_OR_DATA                 (0x0D4)
+#define QSERDES_TX_L0_PWM_GEAR_1_DIVIDER_BAND2            (0x0D8)
+#define QSERDES_TX_L0_PWM_GEAR_2_DIVIDER_BAND2            (0x0DC)
+#define QSERDES_TX_L0_PWM_GEAR_3_DIVIDER_BAND2            (0x0E0)
+#define QSERDES_TX_L0_PWM_GEAR_4_DIVIDER_BAND2            (0x0E4)
+#define QSERDES_TX_L0_PWM_GEAR_1_DIVIDER_BAND0_1          (0x0E8)
+#define QSERDES_TX_L0_PWM_GEAR_2_DIVIDER_BAND0_1          (0x0EC)
+#define QSERDES_TX_L0_PWM_GEAR_3_DIVIDER_BAND0_1          (0x0F0)
+#define QSERDES_TX_L0_PWM_GEAR_4_DIVIDER_BAND0_1          (0x0F4)
+#define QSERDES_TX_L0_VMODE_CTRL1                         (0x0F8)
+#define QSERDES_TX_L0_VMODE_CTRL2                         (0x0FC)
+#define QSERDES_TX_L0_TX_ALOG_INTF_OBSV_CNTL              (0x100)
+#define QSERDES_TX_L0_BIST_STATUS                         (0x104)
+#define QSERDES_TX_L0_BIST_ERROR_COUNT1                   (0x108)
+#define QSERDES_TX_L0_BIST_ERROR_COUNT2                   (0x10C)
+#define QSERDES_TX_L0_TX_ALOG_INTF_OBSV                   (0x110)
+
+/* HDMI PHY REGISTERS */
+#define HDMI_PHY_BASE_OFFSET                  (0x9A1200)
+#define HDMI_PHY_CFG                          (HDMI_PHY_BASE_OFFSET + 0x00)
+#define HDMI_PHY_PD_CTL                       (HDMI_PHY_BASE_OFFSET + 0x04)
+#define HDMI_PHY_MODE                         (HDMI_PHY_BASE_OFFSET + 0x08)
+#define HDMI_PHY_MISR_CLEAR                   (HDMI_PHY_BASE_OFFSET + 0x0C)
+#define HDMI_PHY_TX0_TX1_BIST_CFG0            (HDMI_PHY_BASE_OFFSET + 0x10)
+#define HDMI_PHY_TX0_TX1_BIST_CFG1            (HDMI_PHY_BASE_OFFSET + 0x14)
+#define HDMI_PHY_TX0_TX1_PRBS_SEED_BYTE0      (HDMI_PHY_BASE_OFFSET + 0x18)
+#define HDMI_PHY_TX0_TX1_PRBS_SEED_BYTE1      (HDMI_PHY_BASE_OFFSET + 0x1C)
+#define HDMI_PHY_TX0_TX1_BIST_PATTERN0        (HDMI_PHY_BASE_OFFSET + 0x20)
+#define HDMI_PHY_TX0_TX1_BIST_PATTERN1        (HDMI_PHY_BASE_OFFSET + 0x24)
+#define HDMI_PHY_TX2_TX3_BIST_CFG0            (HDMI_PHY_BASE_OFFSET + 0x28)
+#define HDMI_PHY_TX2_TX3_BIST_CFG1            (HDMI_PHY_BASE_OFFSET + 0x2C)
+#define HDMI_PHY_TX2_TX3_PRBS_SEED_BYTE0      (HDMI_PHY_BASE_OFFSET + 0x30)
+#define HDMI_PHY_TX2_TX3_PRBS_SEED_BYTE1      (HDMI_PHY_BASE_OFFSET + 0x34)
+#define HDMI_PHY_TX2_TX3_BIST_PATTERN0        (HDMI_PHY_BASE_OFFSET + 0x38)
+#define HDMI_PHY_TX2_TX3_BIST_PATTERN1        (HDMI_PHY_BASE_OFFSET + 0x3C)
+#define HDMI_PHY_DEBUG_BUS_SEL                (HDMI_PHY_BASE_OFFSET + 0x40)
+#define HDMI_PHY_TXCAL_CFG0                   (HDMI_PHY_BASE_OFFSET + 0x44)
+#define HDMI_PHY_TXCAL_CFG1                   (HDMI_PHY_BASE_OFFSET + 0x48)
+#define HDMI_PHY_TX0_TX1_LANE_CTL             (HDMI_PHY_BASE_OFFSET + 0x4C)
+#define HDMI_PHY_TX2_TX3_LANE_CTL             (HDMI_PHY_BASE_OFFSET + 0x50)
+#define HDMI_PHY_LANE_BIST_CONFIG             (HDMI_PHY_BASE_OFFSET + 0x54)
+#define HDMI_PHY_CLOCK                        (HDMI_PHY_BASE_OFFSET + 0x58)
+#define HDMI_PHY_MISC1                        (HDMI_PHY_BASE_OFFSET + 0x5C)
+#define HDMI_PHY_MISC2                        (HDMI_PHY_BASE_OFFSET + 0x60)
+#define HDMI_PHY_TX0_TX1_BIST_STATUS0         (HDMI_PHY_BASE_OFFSET + 0x64)
+#define HDMI_PHY_TX0_TX1_BIST_STATUS1         (HDMI_PHY_BASE_OFFSET + 0x68)
+#define HDMI_PHY_TX0_TX1_BIST_STATUS2         (HDMI_PHY_BASE_OFFSET + 0x6C)
+#define HDMI_PHY_TX2_TX3_BIST_STATUS0         (HDMI_PHY_BASE_OFFSET + 0x70)
+#define HDMI_PHY_TX2_TX3_BIST_STATUS1         (HDMI_PHY_BASE_OFFSET + 0x74)
+#define HDMI_PHY_TX2_TX3_BIST_STATUS2         (HDMI_PHY_BASE_OFFSET + 0x78)
+#define HDMI_PHY_PRE_MISR_STATUS0             (HDMI_PHY_BASE_OFFSET + 0x7C)
+#define HDMI_PHY_PRE_MISR_STATUS1             (HDMI_PHY_BASE_OFFSET + 0x80)
+#define HDMI_PHY_PRE_MISR_STATUS2             (HDMI_PHY_BASE_OFFSET + 0x84)
+#define HDMI_PHY_PRE_MISR_STATUS3             (HDMI_PHY_BASE_OFFSET + 0x88)
+#define HDMI_PHY_POST_MISR_STATUS0            (HDMI_PHY_BASE_OFFSET + 0x8C)
+#define HDMI_PHY_POST_MISR_STATUS1            (HDMI_PHY_BASE_OFFSET + 0x90)
+#define HDMI_PHY_POST_MISR_STATUS2            (HDMI_PHY_BASE_OFFSET + 0x94)
+#define HDMI_PHY_POST_MISR_STATUS3            (HDMI_PHY_BASE_OFFSET + 0x98)
+#define HDMI_PHY_STATUS                       (HDMI_PHY_BASE_OFFSET + 0x9C)
+#define HDMI_PHY_MISC3_STATUS                 (HDMI_PHY_BASE_OFFSET + 0xA0)
+#define HDMI_PHY_MISC4_STATUS                 (HDMI_PHY_BASE_OFFSET + 0xA4)
+#define HDMI_PHY_DEBUG_BUS0                   (HDMI_PHY_BASE_OFFSET + 0xA8)
+#define HDMI_PHY_DEBUG_BUS1                   (HDMI_PHY_BASE_OFFSET + 0xAC)
+#define HDMI_PHY_DEBUG_BUS2                   (HDMI_PHY_BASE_OFFSET + 0xB0)
+#define HDMI_PHY_DEBUG_BUS3                   (HDMI_PHY_BASE_OFFSET + 0xB4)
+#define HDMI_PHY_PHY_REVISION_ID0             (HDMI_PHY_BASE_OFFSET + 0xB8)
+#define HDMI_PHY_PHY_REVISION_ID1             (HDMI_PHY_BASE_OFFSET + 0xBC)
+#define HDMI_PHY_PHY_REVISION_ID2             (HDMI_PHY_BASE_OFFSET + 0xC0)
+#define HDMI_PHY_PHY_REVISION_ID3             (HDMI_PHY_BASE_OFFSET + 0xC4)
+
+#define HDMI_PLL_POLL_MAX_READS                2500
+#define HDMI_PLL_POLL_TIMEOUT_US               150000
+#define HDMI_CLK_RATE_148_MHZ		       148500000
+#define HDMI_CLK_RATE_74_MHZ		       74250000
+#define HDMI_CLK_RATE_25_MHZ		       25200000
+#define HDMI_CLK_RATE_297_MHZ		       297000000
+#define HDMI_CLK_RATE_594_MHZ		       594000000
+
+#define SW_RESET BIT(2)
+#define SW_RESET_PLL BIT(0)
+
+struct hdmi_8996_phy_pll_reg_cfg {
+	uint32_t tx_l0_lane_mode;
+	uint32_t tx_l2_lane_mode;
+	uint32_t tx_l0_tx_band;
+	uint32_t tx_l1_tx_band;
+	uint32_t tx_l2_tx_band;
+	uint32_t tx_l3_tx_band;
+	uint32_t com_svs_mode_clk_sel;
+	uint32_t com_hsclk_sel;
+	uint32_t com_pll_cctrl_mode0;
+	uint32_t com_pll_rctrl_mode0;
+	uint32_t com_cp_ctrl_mode0;
+	uint32_t com_dec_start_mode0;
+	uint32_t com_div_frac_start1_mode0;
+	uint32_t com_div_frac_start2_mode0;
+	uint32_t com_div_frac_start3_mode0;
+	uint32_t com_integloop_gain0_mode0;
+	uint32_t com_integloop_gain1_mode0;
+	uint32_t com_lock_cmp_en;
+	uint32_t com_lock_cmp1_mode0;
+	uint32_t com_lock_cmp2_mode0;
+	uint32_t com_lock_cmp3_mode0;
+	uint32_t com_core_clk_en;
+	uint32_t com_coreclk_div;
+	uint32_t com_restrim_ctrl;
+	uint32_t com_vco_tune_ctrl;
+	uint32_t tx_l0_tx_drv_lvl;
+	uint32_t tx_l0_tx_emp_post1_lvl;
+	uint32_t tx_l1_tx_drv_lvl;
+	uint32_t tx_l1_tx_emp_post1_lvl;
+	uint32_t tx_l2_tx_drv_lvl;
+	uint32_t tx_l2_tx_emp_post1_lvl;
+	uint32_t tx_l3_tx_drv_lvl;
+	uint32_t tx_l3_tx_emp_post1_lvl;
+	uint32_t tx_l0_vmode_ctrl1;
+	uint32_t tx_l0_vmode_ctrl2;
+	uint32_t tx_l1_vmode_ctrl1;
+	uint32_t tx_l1_vmode_ctrl2;
+	uint32_t tx_l2_vmode_ctrl1;
+	uint32_t tx_l2_vmode_ctrl2;
+	uint32_t tx_l3_vmode_ctrl1;
+	uint32_t tx_l3_vmode_ctrl2;
+	uint32_t tx_l0_res_code_lane_tx;
+	uint32_t tx_l1_res_code_lane_tx;
+	uint32_t tx_l2_res_code_lane_tx;
+	uint32_t tx_l3_res_code_lane_tx;
+	uint32_t phy_mode;
+};
+
+void hdmi_phy_reset(void)
+{
+	uint32_t phy_reset_polarity = 0x0;
+	uint32_t pll_reset_polarity = 0x0;
+	uint32_t val;
+
+	val = readl(HDMI_PHY_CTRL);
+
+	phy_reset_polarity = val >> 3 & 0x1;
+	pll_reset_polarity = val >> 1 & 0x1;
+
+	if (phy_reset_polarity == 0)
+		writel(val | SW_RESET, HDMI_PHY_CTRL);
+	else
+		writel(val & (~SW_RESET), HDMI_PHY_CTRL);
+
+	if (pll_reset_polarity == 0)
+		writel(val | SW_RESET_PLL, HDMI_PHY_CTRL);
+	else
+		writel(val & (~SW_RESET_PLL), HDMI_PHY_CTRL);
+
+	if (phy_reset_polarity == 0)
+		writel(val & (~SW_RESET), HDMI_PHY_CTRL);
+	else
+		writel(val | SW_RESET, HDMI_PHY_CTRL);
+
+	if (pll_reset_polarity == 0)
+		writel(val & (~SW_RESET_PLL), HDMI_PHY_CTRL);
+	else
+		writel(val | SW_RESET_PLL, HDMI_PHY_CTRL);
+
+	udelay(100);
+}
+
+static int get_pll_settings(uint32_t tmds_clk_rate,
+		struct hdmi_8996_phy_pll_reg_cfg *cfg)
+{
+	switch (tmds_clk_rate) {
+	case HDMI_CLK_RATE_148_MHZ:
+		cfg->tx_l0_lane_mode = 0x43;
+		cfg->tx_l2_lane_mode = 0x43;
+		cfg->tx_l0_tx_band = 0x04;
+		cfg->tx_l1_tx_band = 0x04;
+		cfg->tx_l2_tx_band = 0x04;
+		cfg->tx_l3_tx_band = 0x04;
+		cfg->com_svs_mode_clk_sel = 0x2;
+		cfg->com_hsclk_sel = 0x21;
+		cfg->com_pll_cctrl_mode0 = 0x28;
+		cfg->com_pll_rctrl_mode0 = 0x16;
+		cfg->com_cp_ctrl_mode0 = 0xb;
+		cfg->com_dec_start_mode0 = 0x74;
+		cfg->com_div_frac_start1_mode0 = 0x0;
+		cfg->com_div_frac_start2_mode0 = 0x40;
+		cfg->com_div_frac_start3_mode0 = 0x0;
+		cfg->com_integloop_gain0_mode0 = 0x0;
+		cfg->com_integloop_gain1_mode0 = 0x1;
+		cfg->com_lock_cmp_en = 0x0;
+		cfg->com_lock_cmp1_mode0 = 0xef;
+		cfg->com_lock_cmp2_mode0 = 0x1e;
+		cfg->com_lock_cmp3_mode0 = 0x0;
+		cfg->com_core_clk_en = 0x2c;
+		cfg->com_coreclk_div = 0x5;
+		cfg->com_restrim_ctrl = 0x0;
+		cfg->com_vco_tune_ctrl = 0x0;
+		cfg->tx_l0_tx_drv_lvl = 0x25;
+		cfg->tx_l0_tx_emp_post1_lvl = 0x23;
+		cfg->tx_l1_tx_drv_lvl = 0x25;
+		cfg->tx_l1_tx_emp_post1_lvl = 0x23;
+		cfg->tx_l2_tx_drv_lvl = 0x25;
+		cfg->tx_l2_tx_emp_post1_lvl = 0x23;
+		cfg->tx_l3_tx_drv_lvl = 0x25;
+		cfg->tx_l3_tx_emp_post1_lvl = 0x23;
+		cfg->tx_l0_vmode_ctrl1 = 0x0;
+		cfg->tx_l0_vmode_ctrl2 = 0xd;
+		cfg->tx_l1_vmode_ctrl1 = 0x0;
+		cfg->tx_l1_vmode_ctrl2 = 0xd;
+		cfg->tx_l2_vmode_ctrl1 = 0x0;
+		cfg->tx_l2_vmode_ctrl2 = 0xd;
+		cfg->tx_l3_vmode_ctrl1 = 0x0;
+		cfg->tx_l3_vmode_ctrl2 = 0x0;
+		cfg->tx_l0_res_code_lane_tx = 0x0;
+		cfg->tx_l1_res_code_lane_tx = 0x0;
+		cfg->tx_l2_res_code_lane_tx = 0x0;
+		cfg->tx_l3_res_code_lane_tx = 0x0;
+		cfg->phy_mode = 0x0;
+		break;
+	case HDMI_CLK_RATE_74_MHZ:
+		cfg->tx_l0_lane_mode = 0x43;
+		cfg->tx_l2_lane_mode = 0x43;
+		cfg->tx_l0_tx_band = 0x04;
+		cfg->tx_l1_tx_band = 0x04;
+		cfg->tx_l2_tx_band = 0x04;
+		cfg->tx_l3_tx_band = 0x04;
+		cfg->com_svs_mode_clk_sel = 0x2;
+		cfg->com_hsclk_sel = 0x29;
+		cfg->com_pll_cctrl_mode0 = 0x28;
+		cfg->com_pll_rctrl_mode0 = 0x16;
+		cfg->com_cp_ctrl_mode0 = 0xb;
+		cfg->com_dec_start_mode0 = 0x74;
+		cfg->com_div_frac_start1_mode0 = 0x0;
+		cfg->com_div_frac_start2_mode0 = 0x40;
+		cfg->com_div_frac_start3_mode0 = 0x0;
+		cfg->com_integloop_gain0_mode0 = 0x0;
+		cfg->com_integloop_gain1_mode0 = 0x1;
+		cfg->com_lock_cmp_en = 0x0;
+		cfg->com_lock_cmp1_mode0 = 0x77;
+		cfg->com_lock_cmp2_mode0 = 0xf;
+		cfg->com_lock_cmp3_mode0 = 0x0;
+		cfg->com_core_clk_en = 0x2c;
+		cfg->com_coreclk_div = 0x5;
+		cfg->com_restrim_ctrl = 0x0;
+		cfg->com_vco_tune_ctrl = 0x0;
+		cfg->tx_l0_tx_drv_lvl = 0x20;
+		cfg->tx_l0_tx_emp_post1_lvl = 0x20;
+		cfg->tx_l1_tx_drv_lvl = 0x20;
+		cfg->tx_l1_tx_emp_post1_lvl = 0x20;
+		cfg->tx_l2_tx_drv_lvl = 0x20;
+		cfg->tx_l2_tx_emp_post1_lvl = 0x20;
+		cfg->tx_l3_tx_drv_lvl = 0x20;
+		cfg->tx_l3_tx_emp_post1_lvl = 0x20;
+		cfg->tx_l0_vmode_ctrl1 = 0x0;
+		cfg->tx_l0_vmode_ctrl2 = 0xe;
+		cfg->tx_l1_vmode_ctrl1 = 0x0;
+		cfg->tx_l1_vmode_ctrl2 = 0xe;
+		cfg->tx_l2_vmode_ctrl1 = 0x0;
+		cfg->tx_l2_vmode_ctrl2 = 0xe;
+		cfg->tx_l3_vmode_ctrl1 = 0x0;
+		cfg->tx_l3_vmode_ctrl2 = 0xe;
+		cfg->tx_l0_res_code_lane_tx = 0x0;
+		cfg->tx_l1_res_code_lane_tx = 0x0;
+		cfg->tx_l2_res_code_lane_tx = 0x0;
+		cfg->tx_l3_res_code_lane_tx = 0x0;
+		cfg->phy_mode = 0x0;
+		break;
+	case HDMI_CLK_RATE_25_MHZ:
+		cfg->tx_l0_lane_mode = 0x43;
+		cfg->tx_l2_lane_mode = 0x43;
+		cfg->tx_l0_tx_band = 0x7;
+		cfg->tx_l1_tx_band = 0x7;
+		cfg->tx_l2_tx_band = 0x7;
+		cfg->tx_l3_tx_band = 0x7;
+		cfg->com_svs_mode_clk_sel = 0x2;
+		cfg->com_hsclk_sel = 0x28;
+		cfg->com_pll_cctrl_mode0 = 0x1;
+		cfg->com_pll_rctrl_mode0 = 0x10;
+		cfg->com_cp_ctrl_mode0 = 0x23;
+		cfg->com_dec_start_mode0 = 0x69;
+		cfg->com_div_frac_start1_mode0 = 0x0;
+		cfg->com_div_frac_start2_mode0 = 0x0;
+		cfg->com_div_frac_start3_mode0 = 0x0;
+		cfg->com_integloop_gain0_mode0 = 0x10;
+		cfg->com_integloop_gain1_mode0 = 0x3;
+		cfg->com_lock_cmp_en = 0x0;
+		cfg->com_lock_cmp1_mode0 = 0xff;
+		cfg->com_lock_cmp2_mode0 = 0x29;
+		cfg->com_lock_cmp3_mode0 = 0x0;
+		cfg->com_core_clk_en = 0x2c;
+		cfg->com_coreclk_div = 0x5;
+		cfg->com_restrim_ctrl = 0x0;
+		cfg->com_vco_tune_ctrl = 0x0;
+		cfg->tx_l0_tx_drv_lvl = 0x20;
+		cfg->tx_l0_tx_emp_post1_lvl = 0x20;
+		cfg->tx_l1_tx_drv_lvl = 0x20;
+		cfg->tx_l1_tx_emp_post1_lvl = 0x20;
+		cfg->tx_l2_tx_drv_lvl = 0x20;
+		cfg->tx_l2_tx_emp_post1_lvl = 0x20;
+		cfg->tx_l3_tx_drv_lvl = 0x20;
+		cfg->tx_l3_tx_emp_post1_lvl = 0x20;
+		cfg->tx_l0_vmode_ctrl1 = 0x0;
+		cfg->tx_l0_vmode_ctrl2 = 0xe;
+		cfg->tx_l1_vmode_ctrl1 = 0x0;
+		cfg->tx_l1_vmode_ctrl2 = 0xe;
+		cfg->tx_l2_vmode_ctrl1 = 0x0;
+		cfg->tx_l2_vmode_ctrl2 = 0xe;
+		cfg->tx_l3_vmode_ctrl1 = 0x0;
+		cfg->tx_l3_vmode_ctrl2 = 0xe;
+		cfg->tx_l0_res_code_lane_tx = 0x0;
+		cfg->tx_l1_res_code_lane_tx = 0x0;
+		cfg->tx_l2_res_code_lane_tx = 0x0;
+		cfg->tx_l3_res_code_lane_tx = 0x0;
+		cfg->phy_mode = 0x0;
+		break;
+	case HDMI_CLK_RATE_297_MHZ:
+		cfg->tx_l0_lane_mode = 0x43;
+		cfg->tx_l2_lane_mode = 0x43;
+		cfg->tx_l0_tx_band = 0x4;
+		cfg->tx_l1_tx_band = 0x4;
+		cfg->tx_l2_tx_band = 0x4;
+		cfg->tx_l3_tx_band = 0x4;
+		cfg->com_svs_mode_clk_sel = 0x1;
+		cfg->com_hsclk_sel = 0x24;
+		cfg->com_pll_cctrl_mode0 = 0x28;
+		cfg->com_pll_rctrl_mode0 = 0x16;
+		cfg->com_cp_ctrl_mode0 = 0xb;
+		cfg->com_dec_start_mode0 = 0x74;
+		cfg->com_div_frac_start1_mode0 = 0x0;
+		cfg->com_div_frac_start2_mode0 = 0x40;
+		cfg->com_div_frac_start3_mode0 = 0x0;
+		cfg->com_integloop_gain0_mode0 = 0x80;
+		cfg->com_integloop_gain1_mode0 = 0x0;
+		cfg->com_lock_cmp_en = 0x0;
+		cfg->com_lock_cmp1_mode0 = 0xdf;
+		cfg->com_lock_cmp2_mode0 = 0x3d;
+		cfg->com_lock_cmp3_mode0 = 0x0;
+		cfg->com_core_clk_en = 0x2c;
+		cfg->com_coreclk_div = 0x5;
+		cfg->com_restrim_ctrl = 0x0;
+		cfg->com_vco_tune_ctrl = 0x0;
+		cfg->tx_l0_tx_drv_lvl = 0x25;
+		cfg->tx_l0_tx_emp_post1_lvl = 0x23;
+		cfg->tx_l1_tx_drv_lvl = 0x25;
+		cfg->tx_l1_tx_emp_post1_lvl = 0x23;
+		cfg->tx_l2_tx_drv_lvl = 0x25;
+		cfg->tx_l2_tx_emp_post1_lvl = 0x23;
+		cfg->tx_l3_tx_drv_lvl = 0x25;
+		cfg->tx_l3_tx_emp_post1_lvl = 0x23;
+		cfg->tx_l0_vmode_ctrl1 = 0x0;
+		cfg->tx_l0_vmode_ctrl2 = 0xd;
+		cfg->tx_l1_vmode_ctrl1 = 0x0;
+		cfg->tx_l1_vmode_ctrl2 = 0xd;
+		cfg->tx_l2_vmode_ctrl1 = 0x0;
+		cfg->tx_l2_vmode_ctrl2 = 0xd;
+		cfg->tx_l3_vmode_ctrl1 = 0x0;
+		cfg->tx_l3_vmode_ctrl2 = 0x0;
+		cfg->tx_l0_res_code_lane_tx = 0x0;
+		cfg->tx_l1_res_code_lane_tx = 0x0;
+		cfg->tx_l2_res_code_lane_tx = 0x0;
+		cfg->tx_l3_res_code_lane_tx = 0x0;
+		cfg->phy_mode = 0x00;
+		break;
+	case HDMI_CLK_RATE_594_MHZ:
+		cfg->tx_l0_lane_mode = 0x43;
+		cfg->tx_l2_lane_mode = 0x43;
+		cfg->tx_l0_tx_band = 0x4;
+		cfg->tx_l1_tx_band = 0x4;
+		cfg->tx_l2_tx_band = 0x4;
+		cfg->tx_l3_tx_band = 0x4;
+		cfg->com_svs_mode_clk_sel = 0x1;
+		cfg->com_hsclk_sel = 0x20;
+		cfg->com_pll_cctrl_mode0 = 0x28;
+		cfg->com_pll_rctrl_mode0 = 0x16;
+		cfg->com_cp_ctrl_mode0 = 0xb;
+		cfg->com_dec_start_mode0 = 0x9a;
+		cfg->com_div_frac_start1_mode0 = 0x0;
+		cfg->com_div_frac_start2_mode0 = 0x0;
+		cfg->com_div_frac_start3_mode0 = 0xb;
+		cfg->com_integloop_gain0_mode0 = 0x80;
+		cfg->com_integloop_gain1_mode0 = 0x0;
+		cfg->com_lock_cmp_en = 0x0;
+		cfg->com_lock_cmp1_mode0 = 0xbf;
+		cfg->com_lock_cmp2_mode0 = 0x7b;
+		cfg->com_lock_cmp3_mode0 = 0x0;
+		cfg->com_core_clk_en = 0x2c;
+		cfg->com_coreclk_div = 0x5;
+		cfg->com_restrim_ctrl = 0x0;
+		cfg->com_vco_tune_ctrl = 0x0;
+		cfg->tx_l0_tx_drv_lvl = 0x25;
+		cfg->tx_l0_tx_emp_post1_lvl = 0x23;
+		cfg->tx_l1_tx_drv_lvl = 0x25;
+		cfg->tx_l1_tx_emp_post1_lvl = 0x23;
+		cfg->tx_l2_tx_drv_lvl = 0x25;
+		cfg->tx_l2_tx_emp_post1_lvl = 0x23;
+		cfg->tx_l3_tx_drv_lvl = 0x22;
+		cfg->tx_l3_tx_emp_post1_lvl = 0x27;
+		cfg->tx_l0_vmode_ctrl1 = 0x0;
+		cfg->tx_l0_vmode_ctrl2 = 0xd;
+		cfg->tx_l1_vmode_ctrl1 = 0x0;
+		cfg->tx_l1_vmode_ctrl2 = 0xd;
+		cfg->tx_l2_vmode_ctrl1 = 0x0;
+		cfg->tx_l2_vmode_ctrl2 = 0xd;
+		cfg->tx_l3_vmode_ctrl1 = 0x0;
+		cfg->tx_l3_vmode_ctrl2 = 0x0;
+		cfg->tx_l0_res_code_lane_tx = 0x0;
+		cfg->tx_l1_res_code_lane_tx = 0x0;
+		cfg->tx_l2_res_code_lane_tx = 0x0;
+		cfg->tx_l3_res_code_lane_tx = 0x0;
+		cfg->phy_mode = 0x10;
+		break;
+	default:
+		return ERROR;
+	}
+
+	return NO_ERROR;
+
+}
+
+uint32_t hdmi_pll_config(uint32_t tmds_clk_rate)
+{
+	struct hdmi_8996_phy_pll_reg_cfg cfg = {0};
+	int rc = NO_ERROR;
+
+	rc = get_pll_settings(tmds_clk_rate, &cfg);
+	if (rc) {
+		dprintf(CRITICAL, "%s: Unsupported clock rate %u\n", __func__, tmds_clk_rate);
+		return rc;
+	}
+
+	/* Initially shut down PHY */
+	writel(0x0, HDMI_PHY_PD_CTL);
+	udelay(500);
+
+	/* Power up sequence */
+	writel(0x04, QSERDES_COM_BG_CTRL);
+
+	writel(0x1, HDMI_PHY_PD_CTL);
+	writel(0x20, QSERDES_COM_RESETSM_CNTRL);
+	writel(0x0F, HDMI_PHY_TX0_TX1_LANE_CTL);
+	writel(0x0F, HDMI_PHY_TX2_TX3_LANE_CTL);
+	writel(0x03, HDMI_TX_L0_BASE_OFFSET +
+			QSERDES_TX_L0_CLKBUF_ENABLE);
+	writel(0x03, HDMI_TX_L1_BASE_OFFSET +
+			QSERDES_TX_L0_CLKBUF_ENABLE);
+	writel(0x03, HDMI_TX_L2_BASE_OFFSET +
+			QSERDES_TX_L0_CLKBUF_ENABLE);
+	writel(0x03, HDMI_TX_L3_BASE_OFFSET +
+			QSERDES_TX_L0_CLKBUF_ENABLE);
+
+	writel(cfg.tx_l0_lane_mode, HDMI_TX_L0_BASE_OFFSET +
+			QSERDES_TX_L0_LANE_MODE);
+	writel(cfg.tx_l2_lane_mode, HDMI_TX_L2_BASE_OFFSET +
+			QSERDES_TX_L0_LANE_MODE);
+
+	writel(cfg.tx_l0_tx_band, HDMI_TX_L0_BASE_OFFSET +
+			QSERDES_TX_L0_TX_BAND);
+	writel(cfg.tx_l1_tx_band, HDMI_TX_L1_BASE_OFFSET +
+			QSERDES_TX_L0_TX_BAND);
+	writel(cfg.tx_l2_tx_band, HDMI_TX_L2_BASE_OFFSET +
+		    QSERDES_TX_L0_TX_BAND);
+	writel(cfg.tx_l3_tx_band, HDMI_TX_L3_BASE_OFFSET +
+			QSERDES_TX_L0_TX_BAND);
+
+	writel(0x03, HDMI_TX_L0_BASE_OFFSET +
+			QSERDES_TX_L0_RESET_TSYNC_EN);
+	writel(0x03, HDMI_TX_L1_BASE_OFFSET +
+			QSERDES_TX_L0_RESET_TSYNC_EN);
+	writel(0x03, HDMI_TX_L2_BASE_OFFSET +
+			QSERDES_TX_L0_RESET_TSYNC_EN);
+	writel(0x03, HDMI_TX_L3_BASE_OFFSET +
+			QSERDES_TX_L0_RESET_TSYNC_EN);
+
+	writel(0x1E, QSERDES_COM_SYSCLK_BUF_ENABLE);
+	writel(0x07, QSERDES_COM_BIAS_EN_CLKBUFLR_EN);
+	writel(0x37, QSERDES_COM_SYSCLK_EN_SEL);
+	writel(0x02, QSERDES_COM_SYS_CLK_CTRL);
+	writel(0x0E, QSERDES_COM_CLK_ENABLE1);
+
+	/* Bypass VCO calibration */
+	writel(cfg.com_svs_mode_clk_sel, QSERDES_COM_SVS_MODE_CLK_SEL);
+
+	writel(0x0F, QSERDES_COM_BG_TRIM);
+	writel(0x0F, QSERDES_COM_PLL_IVCO);
+	writel(cfg.com_vco_tune_ctrl, QSERDES_COM_VCO_TUNE_CTRL);
+
+	writel(0x06, QSERDES_COM_BG_CTRL);
+
+	writel(0x30, QSERDES_COM_CLK_SELECT);
+	writel(cfg.com_hsclk_sel, QSERDES_COM_HSCLK_SEL);
+
+	writel(cfg.com_lock_cmp_en, QSERDES_COM_LOCK_CMP_EN);
+
+	writel(cfg.com_pll_cctrl_mode0, QSERDES_COM_PLL_CCTRL_MODE0);
+	writel(cfg.com_pll_rctrl_mode0, QSERDES_COM_PLL_RCTRL_MODE0);
+	writel(cfg.com_cp_ctrl_mode0, QSERDES_COM_CP_CTRL_MODE0);
+	writel(cfg.com_dec_start_mode0, QSERDES_COM_DEC_START_MODE0);
+	writel(cfg.com_div_frac_start1_mode0, QSERDES_COM_DIV_FRAC_START1_MODE0);
+	writel(cfg.com_div_frac_start2_mode0, QSERDES_COM_DIV_FRAC_START2_MODE0);
+	writel(cfg.com_div_frac_start3_mode0, QSERDES_COM_DIV_FRAC_START3_MODE0);
+
+	writel(cfg.com_integloop_gain0_mode0, QSERDES_COM_INTEGLOOP_GAIN0_MODE0);
+	writel(cfg.com_integloop_gain1_mode0, QSERDES_COM_INTEGLOOP_GAIN1_MODE0);
+
+	writel(cfg.com_lock_cmp1_mode0, QSERDES_COM_LOCK_CMP1_MODE0);
+	writel(cfg.com_lock_cmp2_mode0, QSERDES_COM_LOCK_CMP2_MODE0);
+	writel(cfg.com_lock_cmp3_mode0, QSERDES_COM_LOCK_CMP3_MODE0);
+
+	writel(0x00, QSERDES_COM_VCO_TUNE_MAP);
+	writel(cfg.com_core_clk_en, QSERDES_COM_CORE_CLK_EN);
+	writel(cfg.com_coreclk_div, QSERDES_COM_CORECLK_DIV);
+	writel(0x02, QSERDES_COM_CMN_CONFIG);
+
+	writel(0x15, QSERDES_COM_RESCODE_DIV_NUM);
+
+	/* TX lanes setup (TX 0/1/2/3) */
+	writel(cfg.tx_l0_tx_drv_lvl, HDMI_TX_L0_BASE_OFFSET +
+			QSERDES_TX_L0_TX_DRV_LVL);
+	writel(cfg.tx_l0_tx_emp_post1_lvl, HDMI_TX_L0_BASE_OFFSET +
+			QSERDES_TX_L0_TX_EMP_POST1_LVL);
+
+	writel(cfg.tx_l1_tx_drv_lvl, HDMI_TX_L1_BASE_OFFSET +
+			QSERDES_TX_L0_TX_DRV_LVL);
+	writel(cfg.tx_l1_tx_emp_post1_lvl, HDMI_TX_L1_BASE_OFFSET +
+			QSERDES_TX_L0_TX_EMP_POST1_LVL);
+
+	writel(cfg.tx_l2_tx_drv_lvl, HDMI_TX_L2_BASE_OFFSET +
+			QSERDES_TX_L0_TX_DRV_LVL);
+	writel(cfg.tx_l2_tx_emp_post1_lvl, HDMI_TX_L2_BASE_OFFSET +
+			QSERDES_TX_L0_TX_EMP_POST1_LVL);
+
+	writel(cfg.tx_l3_tx_drv_lvl, HDMI_TX_L3_BASE_OFFSET +
+			QSERDES_TX_L0_TX_DRV_LVL);
+	writel(cfg.tx_l3_tx_emp_post1_lvl, HDMI_TX_L3_BASE_OFFSET +
+		    QSERDES_TX_L0_TX_EMP_POST1_LVL);
+
+	writel(cfg.tx_l0_vmode_ctrl1, HDMI_TX_L0_BASE_OFFSET +
+			QSERDES_TX_L0_VMODE_CTRL1);
+	writel(cfg.tx_l0_vmode_ctrl2, HDMI_TX_L0_BASE_OFFSET +
+			QSERDES_TX_L0_VMODE_CTRL2);
+
+	writel(cfg.tx_l1_vmode_ctrl1, HDMI_TX_L1_BASE_OFFSET +
+			QSERDES_TX_L0_VMODE_CTRL1);
+	writel(cfg.tx_l1_vmode_ctrl2, HDMI_TX_L1_BASE_OFFSET +
+			QSERDES_TX_L0_VMODE_CTRL2);
+
+	writel(cfg.tx_l2_vmode_ctrl1, HDMI_TX_L2_BASE_OFFSET +
+			QSERDES_TX_L0_VMODE_CTRL1);
+	writel(cfg.tx_l2_vmode_ctrl2, HDMI_TX_L2_BASE_OFFSET +
+			QSERDES_TX_L0_VMODE_CTRL2);
+
+	writel(cfg.tx_l3_vmode_ctrl1, HDMI_TX_L3_BASE_OFFSET +
+			QSERDES_TX_L0_VMODE_CTRL1);
+	writel(cfg.tx_l3_vmode_ctrl2, HDMI_TX_L3_BASE_OFFSET +
+			QSERDES_TX_L0_VMODE_CTRL2);
+
+	writel(0x00, HDMI_TX_L0_BASE_OFFSET +
+		       QSERDES_TX_L0_TX_DRV_LVL_OFFSET);
+	writel(0x00, HDMI_TX_L1_BASE_OFFSET +
+		       QSERDES_TX_L0_TX_DRV_LVL_OFFSET);
+	writel(0x00, HDMI_TX_L2_BASE_OFFSET +
+		       QSERDES_TX_L0_TX_DRV_LVL_OFFSET);
+	writel(0x00, HDMI_TX_L3_BASE_OFFSET +
+		       QSERDES_TX_L0_TX_DRV_LVL_OFFSET);
+
+	writel(0x00, HDMI_TX_L0_BASE_OFFSET +
+		       QSERDES_TX_L0_RES_CODE_LANE_OFFSET);
+	writel(0x00, HDMI_TX_L1_BASE_OFFSET +
+		       QSERDES_TX_L0_RES_CODE_LANE_OFFSET);
+	writel(0x00, HDMI_TX_L2_BASE_OFFSET +
+		       QSERDES_TX_L0_RES_CODE_LANE_OFFSET);
+	writel(0x00, HDMI_TX_L3_BASE_OFFSET +
+		       QSERDES_TX_L0_RES_CODE_LANE_OFFSET);
+
+	writel(cfg.phy_mode, HDMI_PHY_MODE);
+	writel(0x1F, HDMI_PHY_PD_CTL);
+
+	writel(0x03, HDMI_TX_L0_BASE_OFFSET +
+			QSERDES_TX_L0_TRAN_DRVR_EMP_EN);
+	writel(0x03, HDMI_TX_L1_BASE_OFFSET +
+			QSERDES_TX_L0_TRAN_DRVR_EMP_EN);
+	writel(0x03, HDMI_TX_L2_BASE_OFFSET +
+			QSERDES_TX_L0_TRAN_DRVR_EMP_EN);
+	writel(0x03, HDMI_TX_L3_BASE_OFFSET +
+			QSERDES_TX_L0_TRAN_DRVR_EMP_EN);
+
+	writel(0x40, HDMI_TX_L0_BASE_OFFSET +
+			QSERDES_TX_L0_PARRATE_REC_DETECT_IDLE_EN);
+	writel(0x40, HDMI_TX_L1_BASE_OFFSET +
+			QSERDES_TX_L0_PARRATE_REC_DETECT_IDLE_EN);
+	writel(0x40, HDMI_TX_L2_BASE_OFFSET +
+			QSERDES_TX_L0_PARRATE_REC_DETECT_IDLE_EN);
+	writel(0x40, HDMI_TX_L3_BASE_OFFSET +
+			QSERDES_TX_L0_PARRATE_REC_DETECT_IDLE_EN);
+
+	writel(0x0C, HDMI_TX_L0_BASE_OFFSET +
+			QSERDES_TX_L0_HP_PD_ENABLES);
+	writel(0x0C, HDMI_TX_L1_BASE_OFFSET +
+			QSERDES_TX_L0_HP_PD_ENABLES);
+	writel(0x0C, HDMI_TX_L2_BASE_OFFSET +
+			QSERDES_TX_L0_HP_PD_ENABLES);
+	writel(0x03, HDMI_TX_L3_BASE_OFFSET +
+			QSERDES_TX_L0_HP_PD_ENABLES);
+
+	return NO_ERROR;
+}
+
+int hdmi_vco_enable(void)
+{
+	uint32_t pll_locked = 0;
+	uint32_t phy_ready = 0;
+	uint32_t status = 0;
+	uint32_t num_reads = 0;
+
+	writel(0x1, HDMI_PHY_CFG);
+	udelay(100);
+
+	writel(0x19, HDMI_PHY_CFG);
+	udelay(100);
+
+	num_reads = HDMI_PLL_POLL_MAX_READS;
+	status = readl(QSERDES_COM_C_READY_STATUS);
+	while (!(status & BIT(0)) && num_reads) {
+		status = readl(QSERDES_COM_C_READY_STATUS);
+		num_reads--;
+		udelay(HDMI_PLL_POLL_TIMEOUT_US);
+	}
+
+	if ((status & BIT(0)) == 1 && num_reads) {
+		pll_locked = 1;
+	} else {
+		pll_locked = 0;
+	}
+
+	dprintf(INFO, "%s: pll_locked = %d\n", __func__, pll_locked);
+
+	writel(0x6F, HDMI_TX_L0_BASE_OFFSET +
+			QSERDES_TX_L0_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN);
+	writel(0x6F, HDMI_TX_L1_BASE_OFFSET +
+			QSERDES_TX_L0_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN);
+	writel(0x6F, HDMI_TX_L2_BASE_OFFSET +
+			QSERDES_TX_L0_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN);
+	writel(0x6F, HDMI_TX_L3_BASE_OFFSET +
+			QSERDES_TX_L0_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN);
+
+	/* Disable SSC */
+	writel(0x0, QSERDES_COM_SSC_PER1);
+	writel(0x0, QSERDES_COM_SSC_PER2);
+	writel(0x0, QSERDES_COM_SSC_STEP_SIZE1);
+	writel(0x0, QSERDES_COM_SSC_STEP_SIZE2);
+	writel(0x2, QSERDES_COM_SSC_EN_CENTER);
+
+	num_reads = HDMI_PLL_POLL_MAX_READS;
+	status = readl(HDMI_PHY_STATUS);
+	while (!(status & BIT(0)) && num_reads) {
+		status = readl(HDMI_PHY_STATUS);
+		num_reads--;
+		udelay(HDMI_PLL_POLL_TIMEOUT_US);
+	}
+
+	if ((status & BIT(0)) == 1 && num_reads) {
+		phy_ready = 1;
+	} else {
+		phy_ready = 0;
+	}
+
+	dprintf(INFO, "%s: phy_ready = %d\n", __func__, phy_ready);
+
+	/* Restart the retiming buffer */
+	writel(0x18, HDMI_PHY_CFG);
+	udelay(1);
+	writel(0x19, HDMI_PHY_CFG);
+
+	return NO_ERROR;
+}
+
+int hdmi_vco_disable(void)
+{
+	writel(0x0, HDMI_PHY_PD_CTL);
+	udelay(500);
+
+	return NO_ERROR;
+}
diff --git a/platform/msm_shared/qpic_nand.c b/platform/msm_shared/qpic_nand.c
index baba30d..3fec647 100644
--- a/platform/msm_shared/qpic_nand.c
+++ b/platform/msm_shared/qpic_nand.c
@@ -1378,6 +1378,12 @@
 }
 
 unsigned
+flash_num_pages_per_blk(void)
+{
+	return flash.num_pages_per_blk;
+}
+
+unsigned
 flash_spare_size(void)
 {
     return flash.spare_size;
diff --git a/platform/msm_shared/reboot.c b/platform/msm_shared/reboot.c
index f3441cd..d9a1310 100644
--- a/platform/msm_shared/reboot.c
+++ b/platform/msm_shared/reboot.c
@@ -109,13 +109,16 @@
 		return;
 	}
 
+	if (reboot_reason != NORMAL_DLOAD && reboot_reason != EMERGENCY_DLOAD) {
 #if USE_PON_REBOOT_REG
-	value = REG_READ(PON_SOFT_RB_SPARE);
-	value |= (reboot_reason << 2);
-	REG_WRITE(PON_SOFT_RB_SPARE, value);
+		value = REG_READ(PON_SOFT_RB_SPARE);
+		value |= (reboot_reason << 2);
+		REG_WRITE(PON_SOFT_RB_SPARE, value);
 #else
-	writel(reboot_reason, RESTART_REASON_ADDR);
+		writel(reboot_reason, RESTART_REASON_ADDR);
 #endif
+	}
+
 	/* For Dload cases do a warm reset
 	 * For other cases do a hard reset
 	 */
diff --git a/platform/msm_shared/reboot.h b/platform/msm_shared/reboot.h
index 58085df..2794d72 100644
--- a/platform/msm_shared/reboot.h
+++ b/platform/msm_shared/reboot.h
@@ -48,7 +48,9 @@
 	DM_VERITY_ENFORCING	= 0x77665509,
 	DM_VERITY_KEYSCLEAR	= 0x7766550A,
 #endif
-	/* warm reset start from  0xF0000000 */
+	/* Don't write the reason to PON reg or SMEM
+	 * if the value is more than 0xF0000000
+	 */
 	NORMAL_DLOAD		= 0xF0000001,
 	EMERGENCY_DLOAD,
 };
diff --git a/platform/msm_shared/rules.mk b/platform/msm_shared/rules.mk
index f426e93..7a9e688 100755
--- a/platform/msm_shared/rules.mk
+++ b/platform/msm_shared/rules.mk
@@ -582,7 +582,9 @@
 			$(LOCAL_DIR)/mipi_dsi_autopll_thulium.o \
 			$(LOCAL_DIR)/shutdown_detect.o \
 			$(LOCAL_DIR)/i2c_qup.o \
-			$(LOCAL_DIR)/mipi_dsi_i2c.o
+			$(LOCAL_DIR)/mipi_dsi_i2c.o \
+			$(LOCAL_DIR)/mdss_hdmi.o \
+			$(LOCAL_DIR)/mdss_hdmi_pll_8996.o
 endif
 
 ifeq ($(ENABLE_UFS_SUPPORT), 1)
diff --git a/platform/msm_shared/usb30_udc.c b/platform/msm_shared/usb30_udc.c
index f175cb8..a2923f1 100644
--- a/platform/msm_shared/usb30_udc.c
+++ b/platform/msm_shared/usb30_udc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -1380,7 +1380,10 @@
 {
 	struct udc_descriptor *desc;
 	if ((len > 255) || (len < 2) || (num > 255) || (type > 255))
-		return 0;
+	{
+		dprintf(CRITICAL, "Invalid parameters for descriptor allocation\n");
+		ASSERT(0);
+	}
 
 	desc = malloc(sizeof(struct udc_descriptor) + len);
 	ASSERT(desc);
diff --git a/target/msm8952/include/target/display.h b/target/msm8952/include/target/display.h
index 65f689a..97aadf2 100644
--- a/target/msm8952/include/target/display.h
+++ b/target/msm8952/include/target/display.h
@@ -81,7 +81,7 @@
 /*---------------------------------------------------------------------------*/
 #define DISPLAY_CMDLINE_PREFIX " mdss_mdp.panel="
 
-#define MIPI_FB_ADDR 0x8DD00000
+#define MIPI_FB_ADDR 0x90000000
 
 #define MIPI_HSYNC_PULSE_WIDTH       12
 #define MIPI_HSYNC_BACK_PORCH_DCLK   32
diff --git a/target/msm8952/meminfo.c b/target/msm8952/meminfo.c
index b2f46df..bb23004 100644
--- a/target/msm8952/meminfo.c
+++ b/target/msm8952/meminfo.c
@@ -81,5 +81,5 @@
 
 unsigned target_get_max_flash_size(void)
 {
-	return (512 * 1024 * 1024);
+	return (511 * 1024 * 1024);
 }
diff --git a/target/msm8952/rules.mk b/target/msm8952/rules.mk
index c199e56..e6ecd1b 100644
--- a/target/msm8952/rules.mk
+++ b/target/msm8952/rules.mk
@@ -12,7 +12,7 @@
 MEMSIZE := 0x00300000 # 3MB
 
 BASE_ADDR        := 0x80000000
-SCRATCH_ADDR     := 0x90100000
+SCRATCH_ADDR     := 0xA0100000
 
 DEFINES += DISPLAY_SPLASH_SCREEN=1
 DEFINES += DISPLAY_TYPE_MIPI=1
diff --git a/target/msm8996/include/target/display.h b/target/msm8996/include/target/display.h
index 5b21a1f..9ee5ec3 100644
--- a/target/msm8996/include/target/display.h
+++ b/target/msm8996/include/target/display.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -33,6 +33,7 @@
 /* HEADER files                                                              */
 /*---------------------------------------------------------------------------*/
 #include <display_resource.h>
+#include <msm_panel.h>
 
 /*---------------------------------------------------------------------------*/
 /* Target Physical configuration                                             */
@@ -67,6 +68,7 @@
 #define DISPLAY_CMDLINE_PREFIX " mdss_mdp.panel="
 
 #define MIPI_FB_ADDR  0x83400000
+#define HDMI_FB_ADDR  0xB1C00000
 
 #define MIPI_HSYNC_PULSE_WIDTH       16
 #define MIPI_HSYNC_BACK_PORCH_DCLK   32
@@ -79,7 +81,8 @@
 #define PWM_BL_LPG_CHAN_ID           4	/* lpg_out<3> */
 
 #define HDMI_PANEL_NAME              "hdmi"
-#define HDMI_CONTROLLER_STRING       "hdmi:0"
+#define HDMI_CONTROLLER_STRING       "hdmi:"
+#define HDMI_VIC_LEN                 5
 
 /*---------------------------------------------------------------------------*/
 /* Functions		                                                     */
@@ -93,5 +96,9 @@
 void target_force_cont_splash_disable(uint8_t override);
 uint8_t target_panel_auto_detect_enabled();
 void target_set_switch_gpio(int enable_dsi2hdmibridge);
+int target_hdmi_pll_clock(uint8_t enable, struct msm_panel_info *pinfo);
+int target_hdmi_panel_clock(uint8_t enable, struct msm_panel_info *pinfo);
+int target_hdmi_regulator_ctrl(uint8_t enable);
+int target_hdmi_gpio_ctrl(uint8_t enable);
 
 #endif
diff --git a/target/msm8996/init.c b/target/msm8996/init.c
index 25c1b14..51051c9 100644
--- a/target/msm8996/init.c
+++ b/target/msm8996/init.c
@@ -500,6 +500,11 @@
 	qusb2_phy_reset();
 }
 
+void target_usb_phy_sec_reset()
+{
+	qusb2_phy_reset();
+}
+
 target_usb_iface_t* target_usb30_init()
 {
 	target_usb_iface_t *t_usb_iface;
@@ -507,9 +512,20 @@
 	t_usb_iface = calloc(1, sizeof(target_usb_iface_t));
 	ASSERT(t_usb_iface);
 
-	t_usb_iface->phy_init   = usb30_qmp_phy_init;
-	t_usb_iface->phy_reset  = target_usb_phy_reset;
-	t_usb_iface->clock_init = clock_usb30_init;
+
+	/* for SBC we use secondary port */
+	if (board_hardware_id() == HW_PLATFORM_SBC)
+	{
+		/* secondary port have no QMP phy,use only QUSB2 phy that have only reset */
+		t_usb_iface->phy_init   = NULL;
+		t_usb_iface->phy_reset  = target_usb_phy_sec_reset;
+		t_usb_iface->clock_init = clock_usb20_init;
+	} else {
+		t_usb_iface->phy_init   = usb30_qmp_phy_init;
+		t_usb_iface->phy_reset  = target_usb_phy_reset;
+		t_usb_iface->clock_init = clock_usb30_init;
+	}
+
 	t_usb_iface->vbus_override = 1;
 
 	return t_usb_iface;
diff --git a/target/msm8996/regulator.c b/target/msm8996/regulator.c
index 909082d..a95a42f 100644
--- a/target/msm8996/regulator.c
+++ b/target/msm8996/regulator.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -48,6 +48,23 @@
 	},
 };
 
+static uint32_t ldo12[][11]=
+{
+	{
+		LDOA_RES_TYPE, 12,
+		KEY_SOFTWARE_ENABLE, 4, GENERIC_DISABLE,
+		KEY_MICRO_VOLT, 4, 0,
+		KEY_CURRENT, 4, 0,
+	},
+
+	{
+		LDOA_RES_TYPE, 12,
+		KEY_SOFTWARE_ENABLE, 4, GENERIC_ENABLE,
+		KEY_MICRO_VOLT, 4, 1800000,
+		KEY_CURRENT, 4, 11,
+	},
+};
+
 static uint32_t ldo14[][11]=
 {
 	{
@@ -88,6 +105,9 @@
 	if (enable & REG_LDO2)
 		rpm_send_data(&ldo2[GENERIC_ENABLE][0], 36, RPM_REQUEST_TYPE);
 
+	if (enable & REG_LDO12)
+		rpm_send_data(&ldo12[GENERIC_ENABLE][0], 36, RPM_REQUEST_TYPE);
+
 	if (enable & REG_LDO14)
 		rpm_send_data(&ldo14[GENERIC_ENABLE][0], 36, RPM_REQUEST_TYPE);
 
@@ -100,6 +120,9 @@
 	if (enable & REG_LDO2)
 		rpm_send_data(&ldo2[GENERIC_DISABLE][0], 36, RPM_REQUEST_TYPE);
 
+	if (enable & REG_LDO12)
+		rpm_send_data(&ldo12[GENERIC_DISABLE][0], 36, RPM_REQUEST_TYPE);
+
 	if (enable & REG_LDO14)
 		rpm_send_data(&ldo14[GENERIC_DISABLE][0], 36, RPM_REQUEST_TYPE);
 
diff --git a/target/msm8996/rules.mk b/target/msm8996/rules.mk
index e59bfc2..c6918f7 100644
--- a/target/msm8996/rules.mk
+++ b/target/msm8996/rules.mk
@@ -8,13 +8,13 @@
 
 PLATFORM := msm8996
 
-MEMBASE := 0x91600000 # SDRAM
+MEMBASE := 0x91800000 # SDRAM
 MEMSIZE := 0x00400000 # 4MB
 
 BASE_ADDR    := 0x0000000
 
-SCRATCH_ADDR := 0x91C00000
-SCRATCH_SIZE := 740
+SCRATCH_ADDR := 0x91E00000
+SCRATCH_SIZE := 738
 KERNEL_ADDR  := 0x80000000
 KERNEL_SIZE  := 88
 
diff --git a/target/msm8996/target_display.c b/target/msm8996/target_display.c
index 5086451..e7cc537 100644
--- a/target/msm8996/target_display.c
+++ b/target/msm8996/target_display.c
@@ -33,6 +33,7 @@
 #include <err.h>
 #include <msm_panel.h>
 #include <mipi_dsi.h>
+#include <mdss_hdmi.h>
 #include <pm8x41.h>
 #include <pm8x41_wled.h>
 #include <qpnp_wled.h>
@@ -92,6 +93,130 @@
   "msmgpio", 105, 3, 1, 0, 1
 };
 
+/* gpio name, id, strength, direction, pull, state. */
+static struct gpio_pin hdmi_cec_gpio = {        /* CEC */
+  "msmgpio", 31, 0, 2, 3, 1
+};
+
+static struct gpio_pin hdmi_ddc_clk_gpio = {   /* DDC CLK */
+  "msmgpio", 32, 0, 2, 3, 1
+};
+
+static struct gpio_pin hdmi_ddc_data_gpio = {  /* DDC DATA */
+  "msmgpio", 33, 0, 2, 3, 1
+};
+
+static struct gpio_pin hdmi_hpd_gpio = {       /* HPD, input */
+  "msmgpio", 34, 7, 0, 1, 1
+};
+
+static void target_hdmi_ldo_enable(uint8_t enable)
+{
+	if (enable)
+		regulator_enable(REG_LDO12);
+	else
+		regulator_disable(REG_LDO12);
+}
+
+static void target_hdmi_mpp4_enable(uint8_t enable)
+{
+	struct pm8x41_mpp mpp;
+
+	/* Enable MPP4 */
+	pmi8994_config_mpp_slave_id(0);
+
+        mpp.base = PM8x41_MMP4_BASE;
+	mpp.vin = MPP_VIN2;
+	mpp.mode = MPP_HIGH;;
+	if (enable) {
+		pm8x41_config_output_mpp(&mpp);
+		pm8x41_enable_mpp(&mpp, MPP_ENABLE);
+	} else {
+		pm8x41_enable_mpp(&mpp, MPP_DISABLE);
+	}
+
+	/* Need delay before power on regulators */
+	mdelay(20);
+}
+
+int target_hdmi_regulator_ctrl(uint8_t enable)
+{
+	target_hdmi_ldo_enable(enable);
+
+	target_hdmi_mpp4_enable(enable);
+
+	return 0;
+}
+
+int target_hdmi_gpio_ctrl(uint8_t enable)
+{
+	gpio_tlmm_config(hdmi_cec_gpio.pin_id, 1,	/* gpio 31, CEC */
+		hdmi_cec_gpio.pin_direction, hdmi_cec_gpio.pin_pull,
+		hdmi_cec_gpio.pin_strength, hdmi_cec_gpio.pin_state);
+
+	gpio_tlmm_config(hdmi_ddc_clk_gpio.pin_id, 1,	/* gpio 32, DDC CLK */
+		hdmi_ddc_clk_gpio.pin_direction, hdmi_ddc_clk_gpio.pin_pull,
+		hdmi_ddc_clk_gpio.pin_strength, hdmi_ddc_clk_gpio.pin_state);
+
+
+	gpio_tlmm_config(hdmi_ddc_data_gpio.pin_id, 1,	/* gpio 33, DDC DATA */
+		hdmi_ddc_data_gpio.pin_direction, hdmi_ddc_data_gpio.pin_pull,
+		hdmi_ddc_data_gpio.pin_strength, hdmi_ddc_data_gpio.pin_state);
+
+	gpio_tlmm_config(hdmi_hpd_gpio.pin_id, 1,	/* gpio 34, HPD */
+		hdmi_hpd_gpio.pin_direction, hdmi_hpd_gpio.pin_pull,
+		hdmi_hpd_gpio.pin_strength, hdmi_hpd_gpio.pin_state);
+
+	gpio_set(hdmi_cec_gpio.pin_id,      hdmi_cec_gpio.pin_direction);
+	gpio_set(hdmi_ddc_clk_gpio.pin_id,  hdmi_ddc_clk_gpio.pin_direction);
+	gpio_set(hdmi_ddc_data_gpio.pin_id, hdmi_ddc_data_gpio.pin_direction);
+	gpio_set(hdmi_hpd_gpio.pin_id,      hdmi_hpd_gpio.pin_direction);
+
+	return NO_ERROR;
+}
+
+int target_hdmi_pll_clock(uint8_t enable, struct msm_panel_info *pinfo)
+{
+    if (enable) {
+        hdmi_phy_reset();
+        hdmi_pll_config(pinfo->clk_rate);
+        hdmi_vco_enable();
+        hdmi_pixel_clk_enable(pinfo->clk_rate);
+    } else if(!target_cont_splash_screen()) {
+        /* Disable clocks if continuous splash off */
+        hdmi_pixel_clk_disable();
+        hdmi_vco_disable();
+    }
+
+    return NO_ERROR;
+}
+
+int target_hdmi_panel_clock(uint8_t enable, struct msm_panel_info *pinfo)
+{
+	dprintf(SPEW, "%s: target_panel_clock\n", __func__);
+
+	uint32_t board_version = board_soc_version();
+
+	if (board_version == 0x20000 || board_version == 0x20001)
+		video_gdsc_enable();
+
+	if (enable) {
+		mmss_gdsc_enable();
+		mmss_bus_clock_enable();
+		mdp_clock_enable();
+		hdmi_ahb_core_clk_enable();
+	} else if(!target_cont_splash_screen()) {
+		hdmi_core_ahb_clk_disable();
+		mdp_clock_disable();
+		mmss_bus_clock_disable();
+		mmss_gdsc_disable();
+		if (board_version == 0x20000 || board_version == 0x20001)
+			video_gdsc_disable();
+	}
+
+	return NO_ERROR;
+}
+
 static uint32_t thulium_dsi_pll_lock_status(uint32_t pll_base, uint32_t off,
 	uint32_t bit)
 {
@@ -579,6 +704,7 @@
 	int prefix_string_len = strlen(DISPLAY_CMDLINE_PREFIX);
 	bool ret = true;
 	struct oem_panel_data oem = mdss_dsi_get_oem_data();
+	char vic_buf[HDMI_VIC_LEN] = "0";
 
 	if (!strcmp(oem.panel, HDMI_PANEL_NAME)) {
 		if (buf_size < (prefix_string_len + LK_OVERRIDE_PANEL_LEN +
@@ -592,6 +718,9 @@
 		strlcat(pbuf, LK_OVERRIDE_PANEL, buf_size);
 		buf_size -= LK_OVERRIDE_PANEL_LEN;
 		strlcat(pbuf, HDMI_CONTROLLER_STRING, buf_size);
+		buf_size -= strlen(HDMI_CONTROLLER_STRING);
+		mdss_hdmi_get_vic(vic_buf);
+		strlcat(pbuf, vic_buf, buf_size);
 	} else {
 		ret = gcdb_display_cmdline_arg(pbuf, buf_size);
 	}
@@ -629,6 +758,8 @@
 			oem.panel);
 		return;
 	} else if (!strcmp(oem.panel, HDMI_PANEL_NAME)) {
+		dprintf(INFO, "%s: HDMI is primary\n", __func__);
+		mdss_hdmi_display_init(MDP_REV_50, (void *) HDMI_FB_ADDR);
 		return;
 	}
 
@@ -645,5 +776,10 @@
 
 void target_display_shutdown(void)
 {
-	gcdb_display_shutdown();
+	struct oem_panel_data oem = mdss_dsi_get_oem_data();
+	if (!strcmp(oem.panel, HDMI_PANEL_NAME)) {
+		msm_display_off();
+	} else {
+		gcdb_display_shutdown();
+	}
 }