Merge "sensors: Add the class device support for bmp18x sensor"
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index dde7051..9a9654f 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -255,9 +255,6 @@
 		VERIFY(err, 0 != (sg = ion_sg_table(clnt, buf->handle)));
 		if (err)
 			goto bail;
-		VERIFY(err, 1 == sg->nents);
-		if (err)
-			goto bail;
 		buf->phys = sg_dma_address(sg->sgl);
 	}
  bail:
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
index 642975d..3b7bf5a 100644
--- a/drivers/input/misc/mpu3050.c
+++ b/drivers/input/misc/mpu3050.c
@@ -37,6 +37,7 @@
 #include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
+#include <linux/sensors.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
@@ -128,6 +129,20 @@
 	u32    enable;
 };
 
+static struct sensors_classdev sensors_cdev = {
+	.name = "mpu3050-gyro",
+	.vendor = "Invensense",
+	.version = 1,
+	.handle = SENSORS_GYROSCOPE_HANDLE,
+	.type = SENSOR_TYPE_GYROSCOPE,
+	.max_range = "35.0",
+	.resolution = "0.06",
+	.sensor_power = "0.2",
+	.min_delay = 2000,
+	.fifo_reserved_event_count = 0,
+	.fifo_max_event_count = 0,
+};
+
 struct sensor_regulator {
 	struct regulator *vreg;
 	const char *name;
@@ -804,10 +819,16 @@
 		goto err_free_irq;
 	}
 
+	error = sensors_classdev_register(&client->dev, &sensors_cdev);
+	if (error < 0) {
+		dev_err(&client->dev, "failed to create class device\n");
+		goto err_input_cleanup;
+	}
+
 	error = create_sysfs_interfaces(&idev->dev);
 	if (error < 0) {
 		dev_err(&client->dev, "failed to create sysfs\n");
-		goto err_input_cleanup;
+		goto err_class_sysfs;
 	}
 
 	pm_runtime_enable(&client->dev);
@@ -815,6 +836,8 @@
 
 	return 0;
 
+err_class_sysfs:
+	sensors_classdev_unregister(&sensors_cdev);
 err_input_cleanup:
 	input_unregister_device(idev);
 err_free_irq:
diff --git a/drivers/input/misc/stk3x1x.c b/drivers/input/misc/stk3x1x.c
index b753d55..f1b060e 100644
--- a/drivers/input/misc/stk3x1x.c
+++ b/drivers/input/misc/stk3x1x.c
@@ -32,6 +32,7 @@
 #include <linux/kdev_t.h>
 #include <linux/fs.h>
 #include <linux/input.h>
+#include <linux/sensors.h>
 #include <linux/workqueue.h>
 #include <linux/irq.h>
 #include <linux/delay.h>
@@ -181,6 +182,35 @@
 
 #define STK_FIR_LEN 16
 #define MAX_FIR_LEN 32
+
+static struct sensors_classdev sensors_light_cdev = {
+	.name = "stk3x1x-light",
+	.vendor = "Sensortek",
+	.version = 1,
+	.handle = SENSORS_LIGHT_HANDLE,
+	.type = SENSOR_TYPE_LIGHT,
+	.max_range = "6500",
+	.resolution = "0.0625",
+	.sensor_power = "0.09",
+	.min_delay = 0,
+	.fifo_reserved_event_count = 0,
+	.fifo_max_event_count = 0,
+};
+
+static struct sensors_classdev sensors_proximity_cdev = {
+	.name = "stk3x1x-proximity",
+	.vendor = "Sensortek",
+	.version = 1,
+	.handle = SENSORS_PROXIMITY_HANDLE,
+	.type = SENSOR_TYPE_PROXIMITY,
+	.max_range = "5.0",
+	.resolution = "5.0",
+	.sensor_power = "0.1",
+	.min_delay = 0,
+	.fifo_reserved_event_count = 0,
+	.fifo_max_event_count = 0,
+};
+
 struct data_filter {
 	u16 raw[MAX_FIR_LEN];
 	int sum;
@@ -2363,6 +2393,14 @@
 	ps_data->stk_early_suspend.resume = stk3x1x_late_resume;
 	register_early_suspend(&ps_data->stk_early_suspend);
 #endif
+	/* make sure everything is ok before registering the class device */
+	err = sensors_classdev_register(&client->dev, &sensors_light_cdev);
+	if (err)
+		goto err_power_on;
+	err = sensors_classdev_register(&client->dev, &sensors_proximity_cdev);
+	if (err)
+		goto err_class_sysfs;
+
 	/* enable device power only when it is enabled */
 	err = stk3x1x_power_ctl(ps_data, false);
 	if (err)
@@ -2373,6 +2411,9 @@
 
 err_init_all_setting:
 	stk3x1x_power_ctl(ps_data, false);
+	sensors_classdev_unregister(&sensors_proximity_cdev);
+err_class_sysfs:
+	sensors_classdev_unregister(&sensors_light_cdev);
 err_power_on:
 	stk3x1x_power_init(ps_data, false);
 err_power_init:
diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c
index 7282c2e..ad62d5e 100644
--- a/drivers/input/touchscreen/synaptics_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_fw_update.c
@@ -2054,26 +2054,26 @@
 	__ATTR(fw_name, S_IRUGO | S_IWUSR | S_IWGRP,
 			fwu_sysfs_image_name_show,
 			fwu_sysfs_image_name_store),
-	__ATTR(force_update_fw, S_IRUGO | S_IWUSR | S_IWGRP,
-			synaptics_rmi4_show_error,
+	__ATTR(force_update_fw, S_IWUSR | S_IWGRP,
+			NULL,
 			fwu_sysfs_force_reflash_store),
-	__ATTR(update_fw, S_IRUGO | S_IWUSR | S_IWGRP,
-			synaptics_rmi4_show_error,
+	__ATTR(update_fw, S_IWUSR | S_IWGRP,
+			NULL,
 			fwu_sysfs_do_reflash_store),
-	__ATTR(writeconfig, S_IRUGO | S_IWUSR | S_IWGRP,
-			synaptics_rmi4_show_error,
+	__ATTR(writeconfig, S_IWUSR | S_IWGRP,
+			NULL,
 			fwu_sysfs_write_config_store),
-	__ATTR(writelockdown, S_IRUGO | S_IWUSR | S_IWGRP,
-			synaptics_rmi4_show_error,
+	__ATTR(writelockdown, S_IWUSR | S_IWGRP,
+			NULL,
 			fwu_sysfs_write_lockdown_store),
-	__ATTR(readconfig, S_IRUGO | S_IWUSR | S_IWGRP,
-			synaptics_rmi4_show_error,
+	__ATTR(readconfig, S_IWUSR | S_IWGRP,
+			NULL,
 			fwu_sysfs_read_config_store),
-	__ATTR(configarea, S_IRUGO | S_IWUSR | S_IWGRP,
-			synaptics_rmi4_show_error,
+	__ATTR(configarea, S_IWUSR | S_IWGRP,
+			NULL,
 			fwu_sysfs_config_area_store),
-	__ATTR(imagesize, S_IRUGO | S_IWUSR | S_IWGRP,
-			synaptics_rmi4_show_error,
+	__ATTR(imagesize, S_IWUSR | S_IWGRP,
+			NULL,
 			fwu_sysfs_image_size_store),
 	__ATTR(blocksize, S_IRUGO,
 			fwu_sysfs_block_size_show,
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index d21b6c1..b011315 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -392,8 +392,8 @@
 			synaptics_rmi4_full_pm_cycle_show,
 			synaptics_rmi4_full_pm_cycle_store),
 #endif
-	__ATTR(reset, S_IRUGO | S_IWUSR | S_IWGRP,
-			synaptics_rmi4_show_error,
+	__ATTR(reset, S_IWUSR | S_IWGRP,
+			NULL,
 			synaptics_rmi4_f01_reset_store),
 	__ATTR(productinfo, S_IRUGO,
 			synaptics_rmi4_f01_productinfo_show,
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.h b/drivers/input/touchscreen/synaptics_i2c_rmi4.h
index ef39bb7..f77378a 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.h
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.h
@@ -286,14 +286,6 @@
 		void (*func_attn)(struct synaptics_rmi4_data *rmi4_data,
 				unsigned char intr_mask));
 
-static inline ssize_t synaptics_rmi4_show_error(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	dev_warn(dev, "%s Attempted to read from write-only attribute %s\n",
-			__func__, attr->attr.name);
-	return -EPERM;
-}
-
 static inline ssize_t synaptics_rmi4_store_error(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
diff --git a/drivers/input/touchscreen/synaptics_rmi_dev.c b/drivers/input/touchscreen/synaptics_rmi_dev.c
index c60ca23..7abd909 100644
--- a/drivers/input/touchscreen/synaptics_rmi_dev.c
+++ b/drivers/input/touchscreen/synaptics_rmi_dev.c
@@ -73,19 +73,19 @@
 };
 
 static struct device_attribute attrs[] = {
-	__ATTR(open, S_IRUGO | S_IWUSR | S_IWGRP,
-			synaptics_rmi4_show_error,
+	__ATTR(open, S_IWUSR | S_IWGRP,
+			NULL,
 			rmidev_sysfs_open_store),
-	__ATTR(release, S_IRUGO | S_IWUSR | S_IWGRP,
-			synaptics_rmi4_show_error,
+	__ATTR(release, S_IWUSR | S_IWGRP,
+			NULL,
 			rmidev_sysfs_release_store),
-	__ATTR(address, S_IRUGO | S_IWUSR | S_IWGRP,
-			synaptics_rmi4_show_error,
+	__ATTR(address, S_IWUSR | S_IWGRP,
+			NULL,
 			rmidev_sysfs_address_store),
-	__ATTR(length, S_IRUGO | S_IWUSR | S_IWGRP,
-			synaptics_rmi4_show_error,
+	__ATTR(length, S_IWUSR | S_IWGRP,
+			NULL,
 			rmidev_sysfs_length_store),
-	__ATTR(data, (S_IRUGO | S_IWUSR | S_IWGRP),
+	__ATTR(data, (S_IWUSR | S_IWGRP),
 			rmidev_sysfs_data_show,
 			rmidev_sysfs_data_store),
 };
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 8ae5671..7954296 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -2761,7 +2761,7 @@
 
 	rc = of_property_read_u32(node, "qcom,duration", &val);
 	if (!rc)
-		led->flash_cfg->duration = (((u8) val) - 10) / 10;
+		led->flash_cfg->duration = (u8)((val - 10) / 10);
 	else if (rc == -EINVAL)
 		led->flash_cfg->duration = FLASH_DURATION_200ms;
 	else
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_common.h b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_common.h
index 04af6b6..634beca 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_common.h
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_common.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -20,7 +20,7 @@
 #endif
 
 #define JPEG_PR_ERR   pr_err
-#define JPEG_DBG_HIGH   pr_err
+#define JPEG_DBG_HIGH   pr_debug
 
 enum JPEG_MODE {
 	JPEG_MODE_DISABLE,
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c
index 0a0fa04..77df737 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -216,15 +216,15 @@
 	if (pingpong_index == 0) {
 		hw_cmd_p = &hw_cmd_we_ping_update[0];
 		hw_cmd_p->data = p_input->y_buffer_addr;
-		JPEG_PR_ERR("%s Output pln0 buffer address is %x\n", __func__,
+		JPEG_DBG_HIGH("%s Output pln0 buffer address is %x\n", __func__,
 			p_input->y_buffer_addr);
 		msm_jpeg_hw_write(hw_cmd_p++, base);
 		hw_cmd_p->data = p_input->cbcr_buffer_addr;
-		JPEG_PR_ERR("%s Output pln1 buffer address is %x\n", __func__,
+		JPEG_DBG_HIGH("%s Output pln1 buffer address is %x\n", __func__,
 			p_input->cbcr_buffer_addr);
 		msm_jpeg_hw_write(hw_cmd_p++, base);
 		hw_cmd_p->data = p_input->pln2_addr;
-		JPEG_PR_ERR("%s Output pln2 buffer address is %x\n", __func__,
+		JPEG_DBG_HIGH("%s Output pln2 buffer address is %x\n", __func__,
 			p_input->pln2_addr);
 		msm_jpeg_hw_write(hw_cmd_p++, base);
 	}
diff --git a/drivers/media/platform/msm/vidc/msm_smem.h b/drivers/media/platform/msm/vidc/msm_smem.h
index 7bd6443..ca92e73 100644
--- a/drivers/media/platform/msm/vidc/msm_smem.h
+++ b/drivers/media/platform/msm/vidc/msm_smem.h
@@ -28,41 +28,6 @@
 	SMEM_SECURE = ION_FLAG_SECURE,
 };
 
-/* NOTE: if you change this enum you MUST update the
- * "buffer-type-tz-usage-table" for any affected target
- * in arch/arm/boot/dts/<arch>.dtsi
- */
-enum hal_buffer {
-	HAL_BUFFER_INPUT = 0x1,
-	HAL_BUFFER_OUTPUT = 0x2,
-	HAL_BUFFER_OUTPUT2 = 0x4,
-	HAL_BUFFER_EXTRADATA_INPUT = 0x8,
-	HAL_BUFFER_EXTRADATA_OUTPUT = 0x10,
-	HAL_BUFFER_EXTRADATA_OUTPUT2 = 0x20,
-	HAL_BUFFER_INTERNAL_SCRATCH = 0x40,
-	HAL_BUFFER_INTERNAL_SCRATCH_1 = 0x80,
-	HAL_BUFFER_INTERNAL_SCRATCH_2 = 0x100,
-	HAL_BUFFER_INTERNAL_PERSIST = 0x200,
-	HAL_BUFFER_INTERNAL_PERSIST_1 = 0x400,
-	HAL_BUFFER_INTERNAL_CMD_QUEUE = 0x800,
-};
-
-struct msm_smem {
-	int mem_type;
-	size_t size;
-	void *kvaddr;
-	unsigned long device_addr;
-	u32 flags;
-	void *smem_priv;
-	enum hal_buffer buffer_type;
-};
-
-enum smem_cache_ops {
-	SMEM_CACHE_CLEAN,
-	SMEM_CACHE_INVALIDATE,
-	SMEM_CACHE_CLEAN_INVALIDATE,
-};
-
 void *msm_smem_new_client(enum smem_type mtype,
 				struct msm_vidc_platform_resources *res);
 struct msm_smem *msm_smem_alloc(void *clt, size_t size, u32 align, u32 flags,
@@ -73,7 +38,6 @@
 		enum smem_cache_ops);
 struct msm_smem *msm_smem_user_to_kernel(void *clt, int fd, u32 offset,
 				enum hal_buffer buffer_type);
-int msm_smem_clean_invalidate(void *clt, struct msm_smem *mem);
 int msm_smem_get_domain_partition(void *clt, u32 flags, enum hal_buffer
 		buffer_type, int *domain_num, int *partition_num);
 #endif
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index efa195e..9dd4e93 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -971,6 +971,14 @@
 			rc = -EINVAL;
 			goto err_invalid_fmt;
 		}
+		if (!(get_hal_codec_type(fmt->fourcc) &
+			inst->core->dec_codec_supported)) {
+			dprintk(VIDC_ERR,
+				"Codec(0x%x) not supported\n",
+				get_hal_codec_type(fmt->fourcc));
+			rc = -EINVAL;
+			goto err_invalid_fmt;
+		}
 		inst->fmts[fmt->type] = fmt;
 		rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE);
 		if (rc) {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 6ed94e4..25917c1 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -356,7 +356,7 @@
 		struct v4l2_plane *p, enum hal_buffer buffer_type)
 {
 	struct msm_smem *handle = NULL;
-	handle = msm_smem_user_to_kernel(inst->mem_client,
+	handle = msm_comm_smem_user_to_kernel(inst,
 				p->reserved[0],
 				p->reserved[1],
 				buffer_type);
@@ -365,7 +365,7 @@
 			"%s: Failed to get device buffer address\n", __func__);
 		return NULL;
 	}
-	if (msm_smem_cache_operations(inst->mem_client, handle,
+	if (msm_comm_smem_cache_operations(inst, handle,
 			SMEM_CACHE_CLEAN))
 		dprintk(VIDC_WARN,
 			"CACHE Clean failed: %d, %d, %d\n",
@@ -584,7 +584,7 @@
 			dprintk(VIDC_DBG,
 				"[UNMAP] - handle[%d] = %p fd[%d] = %d",
 				i, temp->handle[i], i, temp->fd[i]);
-			msm_smem_free(inst->mem_client,
+			msm_comm_smem_free(inst,
 				temp->handle[i]);
 		}
 
@@ -660,7 +660,7 @@
 
 	for (i = 0; i < binfo->num_planes; i++) {
 		if (binfo->handle[i]) {
-			rc = msm_smem_cache_operations(inst->mem_client,
+			rc = msm_comm_smem_cache_operations(inst,
 				binfo->handle[i], SMEM_CACHE_INVALIDATE);
 			if (rc) {
 				dprintk(VIDC_ERR,
@@ -745,7 +745,7 @@
 			list_del(&bi->list);
 			for (i = 0; i < bi->num_planes; i++) {
 				if (bi->handle[i])
-					msm_smem_free(inst->mem_client,
+					msm_comm_smem_free(inst,
 							bi->handle[i]);
 			}
 			kfree(bi);
@@ -824,7 +824,7 @@
 		if ((inst->fmts[OUTPUT_PORT]->fourcc ==
 			V4L2_PIX_FMT_HEVC_HYBRID) &&  binfo->handle[i] &&
 			(b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) {
-			rc = msm_smem_cache_operations(inst->mem_client,
+			rc = msm_comm_smem_cache_operations(inst,
 				binfo->handle[i], SMEM_CACHE_INVALIDATE);
 			if (rc) {
 				dprintk(VIDC_ERR,
@@ -835,7 +835,7 @@
 
 		if (binfo->handle[i] &&
 			(b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)) {
-			rc = msm_smem_cache_operations(inst->mem_client,
+			rc = msm_comm_smem_cache_operations(inst,
 					binfo->handle[i], SMEM_CACHE_CLEAN);
 			if (rc) {
 				dprintk(VIDC_ERR,
@@ -970,6 +970,57 @@
 	fsize->stepwise.step_height = capability->height.step_size;
 	return 0;
 }
+
+struct msm_smem *msm_vidc_smem_alloc(void *instance,
+			size_t size, u32 align, u32 flags,
+			enum hal_buffer buffer_type, int map_kernel)
+{
+	return msm_comm_smem_alloc((struct msm_vidc_inst *)instance,
+			size, align, flags, buffer_type, map_kernel);
+
+}
+
+void msm_vidc_smem_free(void *instance, struct msm_smem *mem)
+{
+	msm_comm_smem_free((struct msm_vidc_inst *)instance, mem);
+}
+
+int msm_vidc_smem_cache_operations(void *instance, struct msm_smem *mem,
+		enum smem_cache_ops cache_ops)
+{
+	return msm_comm_smem_cache_operations(
+		(struct msm_vidc_inst *)instance, mem, cache_ops);
+}
+
+struct msm_smem *msm_vidc_smem_user_to_kernel(void *instance, int fd,
+			u32 offset, enum hal_buffer buffer_type)
+{
+	return msm_comm_smem_user_to_kernel(
+			(struct msm_vidc_inst *)instance,
+			fd, offset, buffer_type);
+}
+
+int msm_vidc_smem_get_domain_partition(void *instance, u32 flags,
+		enum hal_buffer buffer_type, int *domain_num,
+		int *partition_num)
+{
+	return msm_comm_smem_get_domain_partition(
+		(struct msm_vidc_inst *)instance,
+		flags, buffer_type, domain_num, partition_num);
+}
+
+void *msm_vidc_smem_get_client(void *instance)
+{
+	struct msm_vidc_inst *inst = instance;
+
+	if (!inst || !inst->mem_client) {
+		dprintk(VIDC_ERR, "%s: invalid instance or client = %p %p\n",
+				__func__, inst, inst->mem_client);
+		return NULL;
+	}
+
+	return inst->mem_client;
+}
 static void *vidc_get_userptr(void *alloc_ctx, unsigned long vaddr,
 				unsigned long size, int write)
 {
@@ -1189,7 +1240,7 @@
 						list);
 				list_del(&buf->list);
 				mutex_unlock(&inst->lock);
-				msm_smem_free(inst->mem_client, buf->handle);
+				msm_comm_smem_free(inst, buf->handle);
 				kfree(buf);
 				mutex_lock(&inst->lock);
 			}
@@ -1200,7 +1251,7 @@
 						list);
 				list_del(&buf->list);
 				mutex_unlock(&inst->lock);
-				msm_smem_free(inst->mem_client, buf->handle);
+				msm_comm_smem_free(inst, buf->handle);
 				kfree(buf);
 				mutex_lock(&inst->lock);
 			}
@@ -1211,14 +1262,14 @@
 						list);
 				list_del(&buf->list);
 				mutex_unlock(&inst->lock);
-				msm_smem_free(inst->mem_client, buf->handle);
+				msm_comm_smem_free(inst, buf->handle);
 				kfree(buf);
 				mutex_lock(&inst->lock);
 			}
 		}
 		if (inst->extradata_handle) {
 			mutex_unlock(&inst->lock);
-			msm_smem_free(inst->mem_client, inst->extradata_handle);
+			msm_comm_smem_free(inst, inst->extradata_handle);
 			mutex_lock(&inst->lock);
 		}
 		mutex_unlock(&inst->lock);
@@ -1247,8 +1298,7 @@
 			for (i = 0; (i < bi->num_planes)
 				&& (i < VIDEO_MAX_PLANES); i++) {
 				if (bi->handle[i])
-					msm_smem_free(inst->mem_client,
-							bi->handle[i]);
+					msm_comm_smem_free(inst, bi->handle[i]);
 			}
 			kfree(bi);
 		}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index e127dc1..9387a17 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -277,14 +277,17 @@
 		dprintk(VIDC_ERR, "Wrong device_id received\n");
 		return;
 	}
-	dprintk(VIDC_DBG, "index = %d\n", index);
-	dprintk(VIDC_DBG, "ptr = %p\n", &(core->completions[index]));
-	complete(&(core->completions[index]));
 	sys_init_msg = response->data;
 	if (!sys_init_msg) {
 		dprintk(VIDC_ERR, "sys_init_done message not proper\n");
 		return;
 	}
+	core->enc_codec_supported = sys_init_msg->enc_codec_supported;
+	core->dec_codec_supported = sys_init_msg->dec_codec_supported;
+	dprintk(VIDC_DBG, "supported_codecs: enc = 0x%x, dec = 0x%x\n",
+		core->enc_codec_supported, core->dec_codec_supported);
+	dprintk(VIDC_DBG, "ptr[%d] = %p\n", index, &(core->completions[index]));
+	complete(&(core->completions[index]));
 }
 
 static void handle_session_release_buf_done(enum command_response cmd,
@@ -1598,7 +1601,7 @@
 	return domain;
 }
 
-static enum hal_video_codec get_hal_codec_type(int fourcc)
+enum hal_video_codec get_hal_codec_type(int fourcc)
 {
 	enum hal_video_codec codec;
 	dprintk(VIDC_DBG, "codec is 0x%x", fourcc);
@@ -1998,7 +2001,7 @@
 	if (output_buf->buffer_size) {
 		for (i = 0; i < output_buf->buffer_count_actual;
 				i++) {
-			handle = msm_smem_alloc(inst->mem_client,
+			handle = msm_comm_smem_alloc(inst,
 					buffer_size, 1, smem_flags,
 					buffer_type, 0);
 			if (!handle) {
@@ -2007,7 +2010,7 @@
 				rc = -ENOMEM;
 				goto err_no_mem;
 			}
-			rc = msm_smem_cache_operations(inst->mem_client,
+			rc = msm_comm_smem_cache_operations(inst,
 					handle, SMEM_CACHE_CLEAN);
 			if (rc) {
 				dprintk(VIDC_WARN,
@@ -2052,7 +2055,7 @@
 fail_set_buffers:
 	kfree(binfo);
 fail_kzalloc:
-	msm_smem_free(inst->mem_client, handle);
+	msm_comm_smem_free(inst, handle);
 err_no_mem:
 	return rc;
 }
@@ -2089,7 +2092,7 @@
 	if (scratch_buf->buffer_size) {
 		for (i = 0; i < scratch_buf->buffer_count_actual;
 				i++) {
-			handle = msm_smem_alloc(inst->mem_client,
+			handle = msm_comm_smem_alloc(inst,
 				scratch_buf->buffer_size, 1, smem_flags,
 				buffer_type, 0);
 			if (!handle) {
@@ -2098,7 +2101,7 @@
 				rc = -ENOMEM;
 				goto err_no_mem;
 			}
-			rc = msm_smem_cache_operations(inst->mem_client,
+			rc = msm_comm_smem_cache_operations(inst,
 					handle, SMEM_CACHE_CLEAN);
 			if (rc) {
 				dprintk(VIDC_WARN,
@@ -2134,7 +2137,7 @@
 fail_set_buffers:
 	kfree(binfo);
 fail_kzalloc:
-	msm_smem_free(inst->mem_client, handle);
+	msm_comm_smem_free(inst, handle);
 err_no_mem:
 	return rc;
 }
@@ -2176,7 +2179,7 @@
 
 	if (persist_buf->buffer_size) {
 		for (i = 0; i < persist_buf->buffer_count_actual; i++) {
-			handle = msm_smem_alloc(inst->mem_client,
+			handle = msm_comm_smem_alloc(inst,
 				persist_buf->buffer_size, 1, smem_flags,
 				buffer_type, 0);
 			if (!handle) {
@@ -2185,7 +2188,7 @@
 				rc = -ENOMEM;
 				goto err_no_mem;
 			}
-			rc = msm_smem_cache_operations(inst->mem_client,
+			rc = msm_comm_smem_cache_operations(inst,
 					handle, SMEM_CACHE_CLEAN);
 			if (rc) {
 				dprintk(VIDC_WARN,
@@ -2221,7 +2224,7 @@
 fail_set_buffers:
 	kfree(binfo);
 fail_kzalloc:
-	msm_smem_free(inst->mem_client, handle);
+	msm_comm_smem_free(inst, handle);
 err_no_mem:
 	return rc;
 }
@@ -2593,7 +2596,7 @@
 			}
 			list_del(&buf->list);
 			mutex_unlock(&inst->lock);
-			msm_smem_free(inst->mem_client, buf->handle);
+			msm_comm_smem_free(inst, buf->handle);
 			kfree(buf);
 			mutex_lock(&inst->lock);
 		}
@@ -2664,7 +2667,7 @@
 			}
 			list_del(&buf->list);
 			mutex_unlock(&inst->lock);
-			msm_smem_free(inst->mem_client, buf->handle);
+			msm_comm_smem_free(inst, buf->handle);
 			kfree(buf);
 			mutex_lock(&inst->lock);
 		}
@@ -2735,7 +2738,7 @@
 			}
 			list_del(&buf->list);
 			mutex_unlock(&inst->lock);
-			msm_smem_free(inst->mem_client, buf->handle);
+			msm_comm_smem_free(inst, buf->handle);
 			kfree(buf);
 			mutex_lock(&inst->lock);
 		}
@@ -3343,3 +3346,85 @@
 		change_inst_state(inst, MSM_VIDC_CLOSE_DONE);
 	return rc;
 }
+
+static inline int power_on_for_smem(struct msm_vidc_inst *inst)
+{
+	struct hfi_device *hdev = NULL;
+	int rc = 0;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s: invalid inst handle\n", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
+	rc = call_hfi_op(hdev, power_enable, hdev->hfi_device_data);
+	if (rc)
+		dprintk(VIDC_ERR, "%s: failed to power on fw\n", __func__);
+	return rc;
+}
+
+struct msm_smem *msm_comm_smem_alloc(struct msm_vidc_inst *inst,
+			size_t size, u32 align, u32 flags,
+			enum hal_buffer buffer_type, int map_kernel)
+{
+	if (!inst) {
+		dprintk(VIDC_ERR, "%s: invalid inst: %p\n", __func__, inst);
+		return NULL;
+	}
+	if (power_on_for_smem(inst))
+		return NULL;
+
+	return msm_smem_alloc(inst->mem_client, size, align,
+				flags, buffer_type, map_kernel);
+}
+
+void msm_comm_smem_free(struct msm_vidc_inst *inst, struct msm_smem *mem)
+{
+	if (!inst || !mem) {
+		dprintk(VIDC_ERR,
+			"%s: invalid params: %p %p\n", __func__, inst, mem);
+		return;
+	}
+	if (power_on_for_smem(inst))
+		return;
+
+	return msm_smem_free(inst->mem_client, mem);
+}
+
+int msm_comm_smem_cache_operations(struct msm_vidc_inst *inst,
+		struct msm_smem *mem, enum smem_cache_ops cache_ops)
+{
+	if (!inst || !mem) {
+		dprintk(VIDC_ERR,
+			"%s: invalid params: %p %p\n", __func__, inst, mem);
+		return -EINVAL;
+	}
+	return msm_smem_cache_operations(inst->mem_client, mem, cache_ops);
+}
+
+struct msm_smem *msm_comm_smem_user_to_kernel(struct msm_vidc_inst *inst,
+			int fd, u32 offset, enum hal_buffer buffer_type)
+{
+	if (!inst) {
+		dprintk(VIDC_ERR, "%s: invalid inst: %p\n", __func__, inst);
+		return NULL;
+	}
+	if (power_on_for_smem(inst))
+		return NULL;
+
+	return msm_smem_user_to_kernel(inst->mem_client,
+			fd, offset, buffer_type);
+}
+
+int msm_comm_smem_get_domain_partition(struct msm_vidc_inst *inst,
+			u32 flags, enum hal_buffer buffer_type,
+			int *domain_num, int *partition_num)
+{
+	if (!inst || !domain_num || !partition_num) {
+		dprintk(VIDC_ERR, "%s: invalid params: %p %p %p\n",
+			__func__, inst, domain_num, partition_num);
+		return -EINVAL;
+	}
+	return msm_smem_get_domain_partition(inst->mem_client, flags,
+			buffer_type, domain_num, partition_num);
+}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h
index 195fa7e..e2f7b61 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h
@@ -52,5 +52,16 @@
 int msm_comm_recover_from_session_error(struct msm_vidc_inst *inst);
 enum multi_stream msm_comm_get_stream_output_mode(struct msm_vidc_inst *inst);
 enum hal_buffer msm_comm_get_hal_output_buffer(struct msm_vidc_inst *inst);
-
+struct msm_smem *msm_comm_smem_alloc(struct msm_vidc_inst *inst,
+			size_t size, u32 align, u32 flags,
+			enum hal_buffer buffer_type, int map_kernel);
+void msm_comm_smem_free(struct msm_vidc_inst *inst, struct msm_smem *mem);
+int msm_comm_smem_cache_operations(struct msm_vidc_inst *inst,
+		struct msm_smem *mem, enum smem_cache_ops cache_ops);
+struct msm_smem *msm_comm_smem_user_to_kernel(struct msm_vidc_inst *inst,
+			int fd, u32 offset, enum hal_buffer buffer_type);
+int msm_comm_smem_get_domain_partition(struct msm_vidc_inst *inst,
+			u32 flags, enum hal_buffer buffer_type,
+			int *domain_num, int *partition_num);
+enum hal_video_codec get_hal_codec_type(int fourcc);
 #endif
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index 2b1471c..e4f920f 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -207,6 +207,8 @@
 	struct completion completions[SYS_MSG_END - SYS_MSG_START + 1];
 	enum msm_vidc_hfi_type hfi_type;
 	struct msm_vidc_platform_resources resources;
+	u32 enc_codec_supported;
+	u32 dec_codec_supported;
 };
 
 struct msm_vidc_inst {
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 8cd3889..9d23d12 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -25,6 +25,7 @@
 #include <mach/subsystem_restart.h>
 #include <mach/msm_smem.h>
 #include <asm/memory.h>
+#include <linux/iopoll.h>
 #include "hfi_packetization.h"
 #include "venus_hfi.h"
 #include "vidc_hfi_io.h"
@@ -65,6 +66,9 @@
 
 #define TZBSP_VIDEO_SET_STATE 0xa
 
+/* Poll interval in uS */
+#define POLL_INTERVAL_US 50
+
 enum tzbsp_video_state {
 	TZBSP_VIDEO_STATE_SUSPEND = 0,
 	TZBSP_VIDEO_STATE_RESUME
@@ -75,6 +79,11 @@
 	u32 spare; /*reserved for future, should be zero*/
 };
 
+
+static inline int venus_hfi_clk_gating_off(struct venus_hfi_device *device);
+
+static int venus_hfi_power_enable(void *dev);
+
 static void venus_hfi_dump_packet(u8 *packet)
 {
 	u32 c = 0, packet_size = *(u32 *)packet;
@@ -402,21 +411,24 @@
 	return rc;
 }
 
-static int venus_hfi_alloc(void *mem, void *clnt, u32 size, u32 align,
-		u32 flags, u32 usage)
+static int venus_hfi_alloc(struct venus_hfi_device *dev, void *mem,
+			u32 size, u32 align, u32 flags, u32 usage)
 {
-	struct vidc_mem_addr *vmem;
-	struct msm_smem *alloc;
+	struct vidc_mem_addr *vmem = NULL;
+	struct msm_smem *alloc = NULL;
 	int rc = 0;
 
-	if (!mem || !clnt || !size) {
+	if (!dev || !dev->hal_client || !mem || !size) {
 		dprintk(VIDC_ERR, "Invalid Params");
 		return -EINVAL;
 	}
+
 	vmem = (struct vidc_mem_addr *)mem;
 	dprintk(VIDC_INFO, "start to alloc: size:%d, Flags: %d", size, flags);
 
-	alloc = msm_smem_alloc(clnt, size, align, flags, usage, 1);
+	venus_hfi_power_enable(dev);
+
+	alloc = msm_smem_alloc(dev->hal_client, size, align, flags, usage, 1);
 	dprintk(VIDC_DBG, "Alloc done");
 	if (!alloc) {
 		dprintk(VIDC_ERR, "Alloc failed\n");
@@ -425,7 +437,7 @@
 	}
 	dprintk(VIDC_DBG, "venus_hfi_alloc:ptr=%p,size=%d",
 			alloc->kvaddr, size);
-	rc = msm_smem_cache_operations(clnt, alloc,
+	rc = msm_smem_cache_operations(dev->hal_client, alloc,
 		SMEM_CACHE_CLEAN);
 	if (rc) {
 		dprintk(VIDC_WARN, "Failed to clean cache\n");
@@ -440,9 +452,14 @@
 	return rc;
 }
 
-static void venus_hfi_free(struct smem_client *clnt, struct msm_smem *mem)
+static void venus_hfi_free(struct venus_hfi_device *dev, struct msm_smem *mem)
 {
-	msm_smem_free(clnt, mem);
+	if (!dev || !mem) {
+		dprintk(VIDC_ERR, "invalid param %p %p\n", dev, mem);
+		return;
+	}
+	venus_hfi_power_enable(dev);
+	msm_smem_free(dev->hal_client, mem);
 }
 
 static void venus_hfi_write_register(struct venus_hfi_device *device, u32 reg,
@@ -865,6 +882,34 @@
 
 static DECLARE_COMPLETION(pc_prep_done);
 
+static int venus_hfi_halt_axi(struct venus_hfi_device *device)
+{
+	u32 reg;
+	int rc = 0;
+	if (!device) {
+		dprintk(VIDC_ERR, "Invalid input: %p\n", device);
+		return -EINVAL;
+	}
+	if (venus_hfi_clk_gating_off(device)) {
+		dprintk(VIDC_ERR, "Failed to turn off clk gating\n");
+		return -EIO;
+	}
+	/* Halt AXI and AXI OCMEM VBIF Access */
+	reg = venus_hfi_read_register(device, VENUS_VBIF_AXI_HALT_CTRL0);
+	reg |= VENUS_VBIF_AXI_HALT_CTRL0_HALT_REQ;
+	venus_hfi_write_register(device, VENUS_VBIF_AXI_HALT_CTRL0, reg, 0);
+
+	/* Request for AXI bus port halt */
+	rc = readl_poll_timeout((u32)device->hal_data->register_base_addr
+			+ VENUS_VBIF_AXI_HALT_CTRL1,
+			reg, reg & VENUS_VBIF_AXI_HALT_CTRL1_HALT_ACK,
+			POLL_INTERVAL_US,
+			VENUS_VBIF_AXI_HALT_ACK_TIMEOUT_US);
+	if (rc)
+		dprintk(VIDC_WARN, "AXI bus port halt timeout\n");
+	return rc;
+}
+
 static inline int venus_hfi_power_off(struct venus_hfi_device *device)
 {
 	int rc = 0;
@@ -972,6 +1017,22 @@
 	return rc;
 }
 
+static int venus_hfi_power_enable(void *dev)
+{
+	int rc = 0;
+	struct venus_hfi_device *device = dev;
+	if (!device) {
+		dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+		return -EINVAL;
+	}
+	mutex_lock(&device->clk_pwr_lock);
+	if (!device->power_enabled)
+		rc = venus_hfi_power_on(device);
+	mutex_unlock(&device->clk_pwr_lock);
+
+	return rc;
+}
+
 static void venus_hfi_pm_hndlr(struct work_struct *work);
 static DECLARE_DELAYED_WORK(venus_hfi_pm_work, venus_hfi_pm_hndlr);
 
@@ -1217,10 +1278,10 @@
 				(unsigned long)(mem_map[i].virtual_addr),
 				domain, partition, SZ_4K);
 		}
-		venus_hfi_free(device->hal_client, device->qdss.mem_data);
+		venus_hfi_free(device, device->qdss.mem_data);
 	}
-	venus_hfi_free(device->hal_client, device->iface_q_table.mem_data);
-	venus_hfi_free(device->hal_client, device->sfr.mem_data);
+	venus_hfi_free(device, device->iface_q_table.mem_data);
+	venus_hfi_free(device, device->sfr.mem_data);
 
 	for (i = 0; i < VIDC_IFACEQ_NUMQ; i++) {
 		device->iface_queues[i].q_hdr = NULL;
@@ -1296,8 +1357,8 @@
 	int num_entries = sizeof(venus_qdss_entries)/(2 * sizeof(u32));
 	int domain, partition;
 	mem_addr = &dev->mem_addr;
-	rc = venus_hfi_alloc((void *) mem_addr,
-			dev->hal_client, QUEUE_SIZE, 1, 0,
+	rc = venus_hfi_alloc(dev, (void *) mem_addr,
+			QUEUE_SIZE, 1, 0,
 			HAL_BUFFER_INTERNAL_CMD_QUEUE);
 	if (rc) {
 		dprintk(VIDC_ERR, "iface_q_table_alloc_fail");
@@ -1323,8 +1384,8 @@
 		venus_hfi_set_queue_hdr_defaults(iface_q->q_hdr);
 	}
 
-	rc = venus_hfi_alloc((void *) mem_addr,
-			dev->hal_client, QDSS_SIZE, 1, 0,
+	rc = venus_hfi_alloc(dev, (void *) mem_addr,
+			QDSS_SIZE, 1, 0,
 			HAL_BUFFER_INTERNAL_CMD_QUEUE);
 	if (rc) {
 		dprintk(VIDC_WARN,
@@ -1336,8 +1397,8 @@
 		dev->qdss.mem_size = QDSS_SIZE;
 		dev->qdss.mem_data = mem_addr->mem_data;
 	}
-	rc = venus_hfi_alloc((void *) mem_addr,
-			dev->hal_client, SFR_SIZE, 1, 0,
+	rc = venus_hfi_alloc(dev, (void *) mem_addr,
+			SFR_SIZE, 1, 0,
 			HAL_BUFFER_INTERNAL_CMD_QUEUE);
 	if (rc) {
 		dprintk(VIDC_WARN, "sfr_alloc_fail: SFR not will work");
@@ -1402,7 +1463,7 @@
 	if (rc) {
 		dprintk(VIDC_ERR,
 			"IOMMU mapping failed, Freeing qdss memdata");
-		venus_hfi_free(dev->hal_client, dev->qdss.mem_data);
+		venus_hfi_free(dev, dev->qdss.mem_data);
 		dev->qdss.mem_data = NULL;
 	}
 	if (!IS_ERR_OR_NULL(dev->qdss.align_device_addr))
@@ -3280,15 +3341,21 @@
 	if (device->resources.fw.cookie) {
 		flush_workqueue(device->vidc_workq);
 		flush_workqueue(device->venus_pm_workq);
+		subsystem_put(device->resources.fw.cookie);
+		venus_hfi_interface_queues_release(dev);
+		/* IOMMU operations need to be done before AXI halt.*/
+		venus_hfi_iommu_detach(device);
+		/* Halt the AXI to make sure there are no pending transactions.
+		 * Clocks should be unprepared after making sure axi is halted.
+		 */
+		if(venus_hfi_halt_axi(device))
+			dprintk(VIDC_WARN, "Failed to halt AXI\n");
 		venus_hfi_disable_clks(device);
 		mutex_lock(&device->clk_pwr_lock);
-		subsystem_put(device->resources.fw.cookie);
 		regulator_disable(device->gdsc);
 		device->power_enabled = 0;
 		--device->pwr_cnt;
 		mutex_unlock(&device->clk_pwr_lock);
-		venus_hfi_interface_queues_release(dev);
-		venus_hfi_iommu_detach(device);
 		device->resources.fw.cookie = NULL;
 	}
 }
@@ -3581,6 +3648,7 @@
 	hdev->get_stride_scanline = venus_hfi_get_stride_scanline;
 	hdev->capability_check = venus_hfi_capability_check;
 	hdev->get_core_capabilities = venus_hfi_get_core_capabilities;
+	hdev->power_enable = venus_hfi_power_enable;
 }
 
 int venus_hfi_initialize(struct hfi_device *hdev, u32 device_id,
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index ee83eee..846171e 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -1130,6 +1130,7 @@
 		u32 *max_width, u32 *max_height);
 	int (*session_clean)(void *sess);
 	int (*get_core_capabilities)(void);
+	int (*power_enable)(void *dev);
 };
 
 typedef void (*hfi_cmd_response_callback) (enum command_response cmd,
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_io.h b/drivers/media/platform/msm/vidc/vidc_hfi_io.h
index 6377fbf..90163b9 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_io.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_io.h
@@ -131,6 +131,12 @@
 #define VIDC_VBIF_AT_OLD_HIGH           (VIDC_VBIF_BASE_OFFS + 0xC08)
 #define VIDC_VBIF_AT_NEW_BASE           (VIDC_VBIF_BASE_OFFS + 0xC10)
 #define VIDC_VBIF_AT_NEW_HIGH           (VIDC_VBIF_BASE_OFFS + 0xC18)
+#define VENUS_VBIF_AXI_HALT_CTRL0   (VIDC_VBIF_BASE_OFFS + 0x208)
+#define VENUS_VBIF_AXI_HALT_CTRL1   (VIDC_VBIF_BASE_OFFS + 0x20C)
+
+#define VENUS_VBIF_AXI_HALT_CTRL0_HALT_REQ		BIT(0)
+#define VENUS_VBIF_AXI_HALT_CTRL1_HALT_ACK		BIT(0)
+#define VENUS_VBIF_AXI_HALT_ACK_TIMEOUT_US		500000
 
 #define VIDC_VENUS0_WRAPPER_VBIF_REQ_PRIORITY \
 	(VIDC_WRAPPER_BASE_OFFS + 0x20)
diff --git a/drivers/video/msm/mdss/Makefile b/drivers/video/msm/mdss/Makefile
index 8f5fa26..0fc6245 100644
--- a/drivers/video/msm/mdss/Makefile
+++ b/drivers/video/msm/mdss/Makefile
@@ -19,7 +19,7 @@
 dsi-v2-objs = dsi_v2.o dsi_host_v2.o dsi_io_v2.o
 obj-$(CONFIG_FB_MSM_MDSS) += dsi-v2.o
 
-mdss-dsi-objs := mdss_dsi.o mdss_dsi_host.o
+mdss-dsi-objs := mdss_dsi.o mdss_dsi_host.o mdss_dsi_cmd.o
 mdss-dsi-objs += mdss_dsi_panel.o
 mdss-dsi-objs += msm_mdss_io_8974.o
 obj-$(CONFIG_FB_MSM_MDSS) += mdss-dsi.o
diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
index 452e63a..aa41cb2 100644
--- a/drivers/video/msm/mdss/dsi_host_v2.c
+++ b/drivers/video/msm/mdss/dsi_host_v2.c
@@ -31,21 +31,24 @@
 #define DSI_POLL_TIMEOUT_US 16000
 #define DSI_ESC_CLK_RATE 19200000
 #define DSI_DMA_CMD_TIMEOUT_MS 200
+#define VSYNC_PERIOD 17
+#define DSI_MAX_PKT_SIZE 10
+#define DSI_SHORT_PKT_DATA_SIZE 2
+#define DSI_MAX_BYTES_TO_READ 16
 
 struct dsi_host_v2_private {
-	struct completion dma_comp;
-	int irq_enabled;
-	spinlock_t irq_lock;
-
 	int irq_no;
 	unsigned char *dsi_base;
 	size_t dsi_reg_size;
 	struct device dis_dev;
+	int clk_count;
+	int dsi_on;
 
 	void (*debug_enable_clk)(int on);
 };
 
 static struct dsi_host_v2_private *dsi_host_private;
+static int msm_dsi_clk_ctrl(struct mdss_panel_data *pdata, int enable);
 
 int msm_dsi_init(void)
 {
@@ -58,8 +61,6 @@
 		}
 	}
 
-	init_completion(&dsi_host_private->dma_comp);
-	spin_lock_init(&dsi_host_private->irq_lock);
 	return 0;
 }
 
@@ -137,61 +138,98 @@
 	msm_dsi_dln0_phy_err(ctrl_base);
 }
 
-void msm_dsi_enable_irq(void)
+static void msm_dsi_set_irq_mask(struct mdss_dsi_ctrl_pdata *ctrl, u32 mask)
+{
+	u32 intr_ctrl;
+	intr_ctrl = MIPI_INP(dsi_host_private->dsi_base + DSI_INT_CTRL);
+	intr_ctrl |= mask;
+	MIPI_OUTP(dsi_host_private->dsi_base + DSI_INT_CTRL, intr_ctrl);
+}
+
+static void msm_dsi_clear_irq_mask(struct mdss_dsi_ctrl_pdata *ctrl, u32 mask)
+{
+	u32 intr_ctrl;
+	intr_ctrl = MIPI_INP(dsi_host_private->dsi_base + DSI_INT_CTRL);
+	intr_ctrl &= ~mask;
+	MIPI_OUTP(dsi_host_private->dsi_base + DSI_INT_CTRL, intr_ctrl);
+}
+
+static void msm_dsi_set_irq(struct mdss_dsi_ctrl_pdata *ctrl, u32 mask)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&dsi_host_private->irq_lock, flags);
-	dsi_host_private->irq_enabled++;
-	if (dsi_host_private->irq_enabled == 1)
+	spin_lock_irqsave(&ctrl->irq_lock, flags);
+	if (ctrl->dsi_irq_mask & mask) {
+		spin_unlock_irqrestore(&ctrl->irq_lock, flags);
+		return;
+	}
+	if (ctrl->dsi_irq_mask == 0) {
 		enable_irq(dsi_host_private->irq_no);
+		pr_debug("%s: IRQ Enable, mask=%x term=%x\n", __func__,
+			(int)ctrl->dsi_irq_mask, (int)mask);
+	}
 
-	spin_unlock_irqrestore(&dsi_host_private->irq_lock, flags);
+	msm_dsi_set_irq_mask(ctrl, mask);
+	ctrl->dsi_irq_mask |= mask;
+	spin_unlock_irqrestore(&ctrl->irq_lock, flags);
 }
 
-void msm_dsi_disable_irq(void)
+static void msm_dsi_clear_irq(struct mdss_dsi_ctrl_pdata *ctrl, u32 mask)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&dsi_host_private->irq_lock, flags);
-	dsi_host_private->irq_enabled--;
-	if (dsi_host_private->irq_enabled == 0)
+	spin_lock_irqsave(&ctrl->irq_lock, flags);
+	if (!(ctrl->dsi_irq_mask & mask)) {
+		spin_unlock_irqrestore(&ctrl->irq_lock, flags);
+		return;
+	}
+	ctrl->dsi_irq_mask &= ~mask;
+	if (ctrl->dsi_irq_mask == 0) {
 		disable_irq(dsi_host_private->irq_no);
-
-	spin_unlock_irqrestore(&dsi_host_private->irq_lock, flags);
+		pr_debug("%s: IRQ Disable, mask=%x term=%x\n", __func__,
+			(int)ctrl->dsi_irq_mask, (int)mask);
+	}
+	msm_dsi_clear_irq_mask(ctrl, mask);
+	spin_unlock_irqrestore(&ctrl->irq_lock, flags);
 }
 
-void msm_dsi_disable_irq_nosync(void)
-{
-	spin_lock(&dsi_host_private->irq_lock);
-	dsi_host_private->irq_enabled--;
-	if (dsi_host_private->irq_enabled == 0)
-		disable_irq_nosync(dsi_host_private->irq_no);
-	spin_unlock(&dsi_host_private->irq_lock);
-}
-
-irqreturn_t msm_dsi_isr(int irq, void *ptr)
+irqreturn_t msm_dsi_isr_handler(int irq, void *ptr)
 {
 	u32 isr;
 
+	struct mdss_dsi_ctrl_pdata *ctrl =
+		(struct mdss_dsi_ctrl_pdata *)ptr;
+
 	isr = MIPI_INP(dsi_host_private->dsi_base + DSI_INT_CTRL);
 	MIPI_OUTP(dsi_host_private->dsi_base + DSI_INT_CTRL, isr);
 
-	if (isr & DSI_INTR_ERROR)
+	pr_debug("%s: isr=%x", __func__, isr);
+
+	if (isr & DSI_INTR_ERROR) {
+		pr_err("%s: isr=%x %x", __func__, isr, (int)DSI_INTR_ERROR);
 		msm_dsi_error(dsi_host_private->dsi_base);
+	}
+
+	spin_lock(&ctrl->mdp_lock);
+
+	if (isr & DSI_INTR_VIDEO_DONE)
+		complete(&ctrl->video_comp);
 
 	if (isr & DSI_INTR_CMD_DMA_DONE)
-		complete(&dsi_host_private->dma_comp);
+		complete(&ctrl->dma_comp);
+
+	spin_unlock(&ctrl->mdp_lock);
 
 	return IRQ_HANDLED;
 }
 
-int msm_dsi_irq_init(struct device *dev, int irq_no)
+int msm_dsi_irq_init(struct device *dev, int irq_no,
+			struct mdss_dsi_ctrl_pdata *ctrl)
 {
 	int ret;
 
-	ret = devm_request_irq(dev, irq_no, msm_dsi_isr,
-				IRQF_DISABLED, "DSI", NULL);
+	ret = devm_request_irq(dev, irq_no, msm_dsi_isr_handler,
+				IRQF_DISABLED, "DSI", ctrl);
 	if (ret) {
 		pr_err("msm_dsi_irq_init request_irq() failed!\n");
 		return ret;
@@ -201,9 +239,76 @@
 	return 0;
 }
 
+static void msm_dsi_get_cmd_engine(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	unsigned char *ctrl_base = dsi_host_private->dsi_base;
+	u32 dsi_ctrl;
+
+	if (ctrl->panel_mode == DSI_VIDEO_MODE) {
+		dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
+		MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl | 0x04);
+	}
+}
+
+static void msm_dsi_release_cmd_engine(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	unsigned char *ctrl_base = dsi_host_private->dsi_base;
+	u32 dsi_ctrl;
+	if (ctrl->panel_mode == DSI_VIDEO_MODE) {
+		dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
+		dsi_ctrl &= ~0x04;
+		MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
+	}
+}
+
+static int msm_dsi_wait4video_done(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	int rc;
+	unsigned long flag;
+
+	spin_lock_irqsave(&ctrl->mdp_lock, flag);
+	INIT_COMPLETION(ctrl->video_comp);
+	msm_dsi_set_irq(ctrl, DSI_INTR_VIDEO_DONE_MASK);
+	spin_unlock_irqrestore(&ctrl->mdp_lock, flag);
+
+	rc = wait_for_completion_timeout(&ctrl->video_comp,
+				msecs_to_jiffies(VSYNC_PERIOD * 4));
+
+	if (rc == 0) {
+		pr_err("DSI wait 4 video done time out\n");
+		rc = -ETIME;
+	} else if (!IS_ERR_VALUE(rc)) {
+		rc = 0;
+	}
+
+	msm_dsi_clear_irq(ctrl, DSI_INTR_VIDEO_DONE_MASK);
+
+	return rc;
+}
+
+static int msm_dsi_wait4video_eng_busy(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	int rc = 0;
+	u32 dsi_status;
+	unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+	if (ctrl->panel_mode == DSI_CMD_MODE)
+		return rc;
+
+	dsi_status = MIPI_INP(ctrl_base + DSI_STATUS);
+	if (dsi_status & 0x08) {
+		pr_debug("dsi command in video mode wait for active region\n");
+		rc = msm_dsi_wait4video_done(ctrl);
+		/* delay 4-5 ms to skip BLLP */
+		if (!rc)
+			usleep_range(4000, 5000);
+	}
+	return rc;
+}
+
 void msm_dsi_host_init(struct mipi_panel_info *pinfo)
 {
-	u32 dsi_ctrl, intr_ctrl, data;
+	u32 dsi_ctrl, data;
 	unsigned char *ctrl_base = dsi_host_private->dsi_base;
 
 	pr_debug("msm_dsi_host_init\n");
@@ -262,8 +367,6 @@
 		pr_err("%s: Unknown DSI mode=%d\n", __func__, pinfo->mode);
 
 	dsi_ctrl = BIT(8) | BIT(2); /* clock enable & cmd mode */
-	intr_ctrl = 0;
-	intr_ctrl = (DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_CMD_MDP_DONE_MASK);
 
 	if (pinfo->crc_check)
 		dsi_ctrl |= BIT(24);
@@ -312,9 +415,6 @@
 	/* DSI_ERR_INT_MASK0 */
 	MIPI_OUTP(ctrl_base + DSI_ERR_INT_MASK0, 0x13ff3fe0);
 
-	intr_ctrl |= DSI_INTR_ERROR_MASK;
-	MIPI_OUTP(ctrl_base + DSI_INT_CTRL, intr_ctrl);
-
 	/* turn esc, byte, dsi, pclk, sclk, hclk on */
 	MIPI_OUTP(ctrl_base + DSI_CLK_CTRL, 0x23f);
 
@@ -404,7 +504,7 @@
 
 void msm_dsi_op_mode_config(int mode, struct mdss_panel_data *pdata)
 {
-	u32 dsi_ctrl, intr_ctrl;
+	u32 dsi_ctrl;
 	unsigned char *ctrl_base = dsi_host_private->dsi_base;
 
 	pr_debug("msm_dsi_op_mode_config\n");
@@ -415,46 +515,24 @@
 
 	dsi_ctrl &= ~0x06;
 
-	if (mode == DSI_VIDEO_MODE) {
+	if (mode == DSI_VIDEO_MODE)
 		dsi_ctrl |= 0x02;
-		intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK;
-	} else {		/* command mode */
+	else
 		dsi_ctrl |= 0x04;
 
-		intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_ERROR_MASK |
-				DSI_INTR_CMD_MDP_DONE_MASK;
-	}
+	pr_debug("%s: dsi_ctrl=%x\n", __func__, dsi_ctrl);
 
-	pr_debug("%s: dsi_ctrl=%x intr=%x\n", __func__, dsi_ctrl, intr_ctrl);
-
-	MIPI_OUTP(ctrl_base + DSI_INT_CTRL, intr_ctrl);
 	MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
 	wmb();
 }
 
-int msm_dsi_cmd_reg_tx(u32 data)
-{
-	unsigned char *ctrl_base = dsi_host_private->dsi_base;
-
-	MIPI_OUTP(ctrl_base + DSI_TRIG_CTRL, 0x04);/* sw trigger */
-	MIPI_OUTP(ctrl_base + DSI_CTRL, 0x135);
-	wmb();
-
-	MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_DMA_CTRL, data);
-	wmb();
-	MIPI_OUTP(ctrl_base + DSI_CMD_MODE_DMA_SW_TRIGGER, 0x01);
-	wmb();
-
-	udelay(300); /*per spec*/
-
-	return 0;
-}
-
-int msm_dsi_cmd_dma_tx(struct dsi_buf *tp)
+int msm_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl,
+				struct dsi_buf *tp)
 {
 	int len, rc;
 	unsigned long size, addr;
 	unsigned char *ctrl_base = dsi_host_private->dsi_base;
+	unsigned long flag;
 
 	len = ALIGN(tp->len, 4);
 	size = ALIGN(tp->len, SZ_4K);
@@ -468,7 +546,12 @@
 
 	addr = tp->dmap;
 
-	INIT_COMPLETION(dsi_host_private->dma_comp);
+	msm_dsi_get_cmd_engine(ctrl);
+
+	spin_lock_irqsave(&ctrl->mdp_lock, flag);
+	INIT_COMPLETION(ctrl->dma_comp);
+	msm_dsi_set_irq(ctrl, DSI_INTR_CMD_DMA_DONE_MASK);
+	spin_unlock_irqrestore(&ctrl->mdp_lock, flag);
 
 	MIPI_OUTP(ctrl_base + DSI_DMA_CMD_OFFSET, addr);
 	MIPI_OUTP(ctrl_base + DSI_DMA_CMD_LENGTH, len);
@@ -477,7 +560,7 @@
 	MIPI_OUTP(ctrl_base + DSI_CMD_MODE_DMA_SW_TRIGGER, 0x01);
 	wmb();
 
-	rc = wait_for_completion_timeout(&dsi_host_private->dma_comp,
+	rc = wait_for_completion_timeout(&ctrl->dma_comp,
 				msecs_to_jiffies(DSI_DMA_CMD_TIMEOUT_MS));
 	if (rc == 0) {
 		pr_err("DSI command transaction time out\n");
@@ -489,10 +572,16 @@
 	dma_unmap_single(&dsi_host_private->dis_dev, tp->dmap, size,
 			DMA_TO_DEVICE);
 	tp->dmap = 0;
+
+	msm_dsi_clear_irq(ctrl, DSI_INTR_CMD_DMA_DONE_MASK);
+
+	msm_dsi_release_cmd_engine(ctrl);
+
 	return rc;
 }
 
-int msm_dsi_cmd_dma_rx(struct dsi_buf *rp, int rlen)
+int msm_dsi_cmd_dma_rx(struct mdss_dsi_ctrl_pdata *ctrl,
+			struct dsi_buf *rp, int rlen)
 {
 	u32 *lp, data;
 	int i, off, cnt;
@@ -518,202 +607,315 @@
 		rp->len += sizeof(*lp);
 	}
 
-	return 0;
+	return rlen;
 }
 
-int msm_dsi_cmds_tx(struct mdss_panel_data *pdata,
-			struct dsi_buf *tp, struct dsi_cmd_desc *cmds, int cnt)
+static int msm_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl,
+			struct dsi_cmd_desc *cmds, int cnt)
 {
+	struct dsi_buf *tp;
 	struct dsi_cmd_desc *cm;
-	u32 dsi_ctrl, ctrl;
-	int i, video_mode, rc = 0;
-	unsigned char *ctrl_base = dsi_host_private->dsi_base;
+	struct dsi_ctrl_hdr *dchdr;
+	int len;
+	int rc = 0;
 
-	/* turn on cmd mode
-	* for video mode, do not send cmds more than
-	* one pixel line, since it only transmit it
-	* during BLLP.
-	*/
-	dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
-	video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
-	if (video_mode) {
-		ctrl = dsi_ctrl | 0x04; /* CMD_MODE_EN */
-		MIPI_OUTP(ctrl_base + DSI_CTRL, ctrl);
-	}
 
-	msm_dsi_enable_irq();
-
+	tp = &ctrl->tx_buf;
+	mdss_dsi_buf_init(tp);
 	cm = cmds;
-	for (i = 0; i < cnt; i++) {
-		dsi_buf_init(tp);
-		dsi_cmd_dma_add(tp, cm);
-		rc = msm_dsi_cmd_dma_tx(tp);
-		if (IS_ERR_VALUE(rc)) {
-			pr_err("%s: failed to call cmd_dma_tx\n", __func__);
-			break;
+	len = 0;
+	while (cnt--) {
+		dchdr = &cm->dchdr;
+		mdss_dsi_buf_reserve(tp, len);
+		len = mdss_dsi_cmd_dma_add(tp, cm);
+		if (!len) {
+			pr_err("%s: failed to add cmd = 0x%x\n",
+				__func__,  cm->payload[0]);
+			rc = -EINVAL;
+			goto dsi_cmds_tx_err;
 		}
-		if (cm->dchdr.wait)
-			msleep(cm->dchdr.wait);
+
+		if (dchdr->last) {
+			tp->data = tp->start; /* begin of buf */
+			rc = msm_dsi_wait4video_eng_busy(ctrl);
+			if (rc) {
+				pr_err("%s: wait4video_eng failed\n", __func__);
+				goto dsi_cmds_tx_err;
+
+			}
+
+			rc = msm_dsi_cmd_dma_tx(ctrl, tp);
+			if (IS_ERR_VALUE(len)) {
+				pr_err("%s: failed to call cmd_dma_tx for cmd = 0x%x\n",
+					__func__,  cmds->payload[0]);
+				goto dsi_cmds_tx_err;
+			}
+
+			if (dchdr->wait)
+				usleep(dchdr->wait * 1000);
+
+			mdss_dsi_buf_init(tp);
+			len = 0;
+		}
 		cm++;
 	}
 
-	msm_dsi_disable_irq();
-
-	if (video_mode)
-		MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
+dsi_cmds_tx_err:
 	return rc;
 }
 
-/* MDSS_DSI_MRPS, Maximum Return Packet Size */
-static char max_pktsize[2] = {0x00, 0x00}; /* LSB tx first, 10 bytes */
-
-static struct dsi_cmd_desc pkt_size_cmd[] = {
-	{{DTYPE_MAX_PKTSIZE, 1, 0, 0, 0,
-		sizeof(max_pktsize)}, max_pktsize}
-};
-
-/*
- * DSI panel reply with  MAX_RETURN_PACKET_SIZE bytes of data
- * plus DCS header, ECC and CRC for DCS long read response
- * mdss_dsi_controller only have 4x32 bits register ( 16 bytes) to
- * hold data per transaction.
- * MDSS_DSI_LEN equal to 8
- * len should be either 4 or 8
- * any return data more than MDSS_DSI_LEN need to be break down
- * to multiple transactions.
- *
- * ov_mutex need to be acquired before call this function.
- */
-int msm_dsi_cmds_rx(struct mdss_panel_data *pdata,
-			struct dsi_buf *tp, struct dsi_buf *rp,
-			struct dsi_cmd_desc *cmds, int rlen)
+static int msm_dsi_parse_rx_response(struct dsi_buf *rp)
 {
-	int cnt, len, diff, pkt_size, rc = 0;
-	char cmd;
-	unsigned char *ctrl_base = dsi_host_private->dsi_base;
-	u32 dsi_ctrl, data;
-	int video_mode;
-
-	/* turn on cmd mode for video mode */
-	dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
-	video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
-	if (video_mode) {
-		data = dsi_ctrl | 0x04; /* CMD_MODE_EN */
-		MIPI_OUTP(ctrl_base + DSI_CTRL, data);
-	}
-
-	if (pdata->panel_info.mipi.no_max_pkt_size)
-		rlen = ALIGN(rlen, 4); /* Only support rlen = 4*n */
-
-	len = rlen;
-	diff = 0;
-
-	if (len <= 2) {
-		cnt = 4;	/* short read */
-	} else {
-		if (len > MDSS_DSI_LEN)
-			len = MDSS_DSI_LEN;	/* 8 bytes at most */
-
-		len = ALIGN(len, 4); /* len 4 bytes align */
-		diff = len - rlen;
-		/*
-		 * add extra 2 bytes to len to have overall
-		 * packet size is multipe by 4. This also make
-		 * sure 4 bytes dcs headerlocates within a
-		 * 32 bits register after shift in.
-		 * after all, len should be either 6 or 10.
-		 */
-		len += 2;
-		cnt = len + 6; /* 4 bytes header + 2 bytes crc */
-	}
-
-	msm_dsi_enable_irq();
-
-	if (!pdata->panel_info.mipi.no_max_pkt_size) {
-		/* packet size need to be set at every read */
-		pkt_size = len;
-		max_pktsize[0] = pkt_size;
-		dsi_buf_init(tp);
-		dsi_cmd_dma_add(tp, pkt_size_cmd);
-		rc = msm_dsi_cmd_dma_tx(tp);
-		if (IS_ERR_VALUE(rc)) {
-			msm_dsi_disable_irq();
-			pr_err("%s: dma_tx failed\n", __func__);
-			rp->len = 0;
-			goto end;
-		}
-		pr_debug("%s: Max packet size sent\n", __func__);
-	}
-
-	dsi_buf_init(tp);
-	dsi_cmd_dma_add(tp, cmds);
-
-	/* transmit read comamnd to client */
-	msm_dsi_cmd_dma_tx(tp);
-	if (IS_ERR_VALUE(rc)) {
-		msm_dsi_disable_irq();
-		pr_err("%s: dma_tx failed\n", __func__);
-		rp->len = 0;
-		goto end;
-	}
-	/*
-	 * once cmd_dma_done interrupt received,
-	 * return data from client is ready and stored
-	 * at RDBK_DATA register already
-	 */
-	dsi_buf_init(rp);
-	if (pdata->panel_info.mipi.no_max_pkt_size) {
-		/*
-		 * expect rlen = n * 4
-		 * short alignement for start addr
-		 */
-		rp->data += 2;
-	}
-
-	msm_dsi_cmd_dma_rx(rp, cnt);
-
-	msm_dsi_disable_irq();
-
-	if (pdata->panel_info.mipi.no_max_pkt_size) {
-		/*
-		 * remove extra 2 bytes from previous
-		 * rx transaction at shift register
-		 * which was inserted during copy
-		 * shift registers to rx buffer
-		 * rx payload start from long alignment addr
-		 */
-		rp->data += 2;
-	}
+	int rc = 0;
+	unsigned char cmd;
 
 	cmd = rp->data[0];
 	switch (cmd) {
 	case DTYPE_ACK_ERR_RESP:
 		pr_debug("%s: rx ACK_ERR_PACLAGE\n", __func__);
+		rc = -EINVAL;
 		break;
 	case DTYPE_GEN_READ1_RESP:
 	case DTYPE_DCS_READ1_RESP:
-		dsi_short_read1_resp(rp);
+		mdss_dsi_short_read1_resp(rp);
 		break;
 	case DTYPE_GEN_READ2_RESP:
 	case DTYPE_DCS_READ2_RESP:
-		dsi_short_read2_resp(rp);
+		mdss_dsi_short_read2_resp(rp);
 		break;
 	case DTYPE_GEN_LREAD_RESP:
 	case DTYPE_DCS_LREAD_RESP:
-		dsi_long_read_resp(rp);
-		rp->len -= 2; /* extra 2 bytes added */
-		rp->len -= diff; /* align bytes */
+		mdss_dsi_long_read_resp(rp);
 		break;
 	default:
-		pr_debug("%s: Unknown cmd received\n", __func__);
+		rc = -EINVAL;
+		pr_warn("%s: Unknown cmd received\n", __func__);
 		break;
 	}
 
-	if (video_mode)
-		MIPI_OUTP(ctrl_base + DSI_CTRL,
-					dsi_ctrl); /* restore */
-end:
-	return rp->len;
+	return rc;
+}
+
+/* MIPI_DSI_MRPS, Maximum Return Packet Size */
+static char max_pktsize[2] = {0x00, 0x00}; /* LSB tx first, 10 bytes */
+
+static struct dsi_cmd_desc pkt_size_cmd = {
+	{DTYPE_MAX_PKTSIZE, 1, 0, 0, 0, sizeof(max_pktsize)},
+	max_pktsize,
+};
+
+static int msm_dsi_set_max_packet_size(struct mdss_dsi_ctrl_pdata *ctrl,
+						int size)
+{
+	struct dsi_buf *tp;
+	int rc;
+
+	tp = &ctrl->tx_buf;
+	mdss_dsi_buf_init(tp);
+	max_pktsize[0] = size;
+
+	rc = mdss_dsi_cmd_dma_add(tp, &pkt_size_cmd);
+	if (!rc) {
+		pr_err("%s: failed to add max_pkt_size\n", __func__);
+		return -EINVAL;
+	}
+
+	rc = msm_dsi_wait4video_eng_busy(ctrl);
+	if (rc) {
+		pr_err("%s: failed to wait4video_eng\n", __func__);
+		return rc;
+	}
+
+	rc = msm_dsi_cmd_dma_tx(ctrl, tp);
+	if (IS_ERR_VALUE(rc)) {
+		pr_err("%s: failed to tx max_pkt_size\n", __func__);
+		return rc;
+	}
+	pr_debug("%s: max_pkt_size=%d sent\n", __func__, size);
+	return rc;
+}
+
+/* read data length is less than or equal to 10 bytes*/
+static int msm_dsi_cmds_rx_1(struct mdss_dsi_ctrl_pdata *ctrl,
+				struct dsi_cmd_desc *cmds, int rlen)
+{
+	int rc;
+	struct dsi_buf *tp, *rp;
+
+	tp = &ctrl->tx_buf;
+	rp = &ctrl->rx_buf;
+	mdss_dsi_buf_init(rp);
+	mdss_dsi_buf_init(tp);
+
+	rc = mdss_dsi_cmd_dma_add(tp, cmds);
+	if (!rc) {
+		pr_err("%s: dsi_cmd_dma_add failed\n", __func__);
+		rc = -EINVAL;
+		goto dsi_cmds_rx_1_error;
+	}
+
+	rc = msm_dsi_wait4video_eng_busy(ctrl);
+	if (rc) {
+		pr_err("%s: wait4video_eng failed\n", __func__);
+		goto dsi_cmds_rx_1_error;
+	}
+
+	rc = msm_dsi_cmd_dma_tx(ctrl, tp);
+	if (IS_ERR_VALUE(rc)) {
+		pr_err("%s: msm_dsi_cmd_dma_tx failed\n", __func__);
+		goto dsi_cmds_rx_1_error;
+	}
+
+	if (rlen <= DSI_SHORT_PKT_DATA_SIZE) {
+		msm_dsi_cmd_dma_rx(ctrl, rp, rlen);
+	} else {
+		msm_dsi_cmd_dma_rx(ctrl, rp, rlen + DSI_HOST_HDR_SIZE);
+		rp->len = rlen + DSI_HOST_HDR_SIZE;
+	}
+	rc = msm_dsi_parse_rx_response(rp);
+
+dsi_cmds_rx_1_error:
+	if (rc)
+		rp->len = 0;
+
+	return rc;
+}
+
+/* read data length is more than 10 bytes, which requires multiple DSI read*/
+static int msm_dsi_cmds_rx_2(struct mdss_dsi_ctrl_pdata *ctrl,
+				struct dsi_cmd_desc *cmds, int rlen)
+{
+	int rc;
+	struct dsi_buf *tp, *rp;
+	int pkt_size, data_bytes, total;
+
+	tp = &ctrl->tx_buf;
+	rp = &ctrl->rx_buf;
+	mdss_dsi_buf_init(rp);
+	pkt_size = DSI_MAX_PKT_SIZE;
+	data_bytes = MDSS_DSI_LEN;
+	total = 0;
+
+	while (true) {
+		rc = msm_dsi_set_max_packet_size(ctrl, pkt_size);
+		if (rc)
+			break;
+
+		mdss_dsi_buf_init(tp);
+		rc = mdss_dsi_cmd_dma_add(tp, cmds);
+		if (!rc) {
+			pr_err("%s: dsi_cmd_dma_add failed\n", __func__);
+			rc = -EINVAL;
+			break;
+	}
+		rc = msm_dsi_wait4video_eng_busy(ctrl);
+		if (rc) {
+			pr_err("%s: wait4video_eng failed\n", __func__);
+			break;
+		}
+
+		rc = msm_dsi_cmd_dma_tx(ctrl, tp);
+		if (IS_ERR_VALUE(rc)) {
+			pr_err("%s: msm_dsi_cmd_dma_tx failed\n", __func__);
+			break;
+		}
+
+		msm_dsi_cmd_dma_rx(ctrl, rp, DSI_MAX_BYTES_TO_READ);
+
+		rp->data += DSI_MAX_BYTES_TO_READ - DSI_HOST_HDR_SIZE;
+		total += data_bytes;
+		if (total >= rlen)
+			break;
+
+		data_bytes = DSI_MAX_BYTES_TO_READ - DSI_HOST_HDR_SIZE;
+		pkt_size += data_bytes;
+	}
+
+	if (!rc) {
+		rp->data = rp->start;
+		rp->len = rlen + DSI_HOST_HDR_SIZE;
+		rc = msm_dsi_parse_rx_response(rp);
+	}
+
+	if (rc)
+		rp->len = 0;
+
+	return rc;
+}
+
+int msm_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl,
+			struct dsi_cmd_desc *cmds, int rlen)
+{
+	int rc;
+	if (rlen <= DSI_MAX_PKT_SIZE)
+		rc = msm_dsi_cmds_rx_1(ctrl, cmds, rlen);
+	else
+		rc = msm_dsi_cmds_rx_2(ctrl, cmds, rlen);
+
+	return rc;
+}
+
+void msm_dsi_cmdlist_tx(struct mdss_dsi_ctrl_pdata *ctrl,
+				struct dcs_cmd_req *req)
+{
+	int ret;
+
+	ret = msm_dsi_cmds_tx(ctrl, req->cmds, req->cmds_cnt);
+
+	if (req->cb)
+		req->cb(ret);
+}
+
+void msm_dsi_cmdlist_rx(struct mdss_dsi_ctrl_pdata *ctrl,
+				struct dcs_cmd_req *req)
+{
+	struct dsi_buf *rp;
+	int len = 0;
+
+	if (req->rbuf) {
+		rp = &ctrl->rx_buf;
+		len = msm_dsi_cmds_rx(ctrl, req->cmds, req->rlen);
+		memcpy(req->rbuf, rp->data, rp->len);
+	} else {
+		pr_err("%s: No rx buffer provided\n", __func__);
+	}
+
+	if (req->cb)
+		req->cb(len);
+}
+void msm_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
+{
+	struct dcs_cmd_req *req;
+	int dsi_on;
+
+	mutex_lock(&ctrl->mutex);
+	dsi_on = dsi_host_private->dsi_on;
+	mutex_unlock(&ctrl->mutex);
+	if (!dsi_on) {
+		pr_err("try to send DSI commands while dsi is off\n");
+		return;
+	}
+
+	mutex_lock(&ctrl->cmd_mutex);
+	req = mdss_dsi_cmdlist_get(ctrl);
+
+	if (!req) {
+		mutex_unlock(&ctrl->cmd_mutex);
+		return;
+	}
+
+	msm_dsi_clk_ctrl(&ctrl->panel_data, 1);
+	dsi_set_tx_power_mode(0);
+
+	if (req->flags & CMD_REQ_RX)
+		msm_dsi_cmdlist_rx(ctrl, req);
+	else
+		msm_dsi_cmdlist_tx(ctrl, req);
+
+	dsi_set_tx_power_mode(1);
+	msm_dsi_clk_ctrl(&ctrl->panel_data, 0);
+
+	mutex_unlock(&ctrl->cmd_mutex);
 }
 
 static int msm_dsi_cal_clk_rate(struct mdss_panel_data *pdata,
@@ -785,11 +987,14 @@
 	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
 				panel_data);
 
+	mutex_lock(&ctrl_pdata->mutex);
+
 	ret = msm_dss_enable_vreg(
 		ctrl_pdata->power_data.vreg_config,
 		ctrl_pdata->power_data.num_vreg, 1);
 	if (ret) {
 		pr_err("%s: DSI power on failed\n", __func__);
+		mutex_unlock(&ctrl_pdata->mutex);
 		return ret;
 	}
 
@@ -876,6 +1081,11 @@
 
 	msm_dsi_op_mode_config(mipi->mode, pdata);
 
+	msm_dsi_set_irq(ctrl_pdata, DSI_INTR_ERROR_MASK);
+	dsi_host_private->clk_count = 1;
+	dsi_host_private->dsi_on = 1;
+	mutex_unlock(&ctrl_pdata->mutex);
+
 	return ret;
 }
 
@@ -894,6 +1104,8 @@
 				panel_data);
 
 	pr_debug("msm_dsi_off\n");
+	mutex_lock(&ctrl_pdata->mutex);
+	msm_dsi_clear_irq(ctrl_pdata, ctrl_pdata->dsi_irq_mask);
 	msm_dsi_controller_cfg(0);
 	msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, 0, 0, 0);
 	msm_dsi_clk_disable();
@@ -906,8 +1118,11 @@
 		ctrl_pdata->power_data.num_vreg, 0);
 	if (ret) {
 		pr_err("%s: Panel power off failed\n", __func__);
-		return ret;
 	}
+	dsi_host_private->clk_count = 0;
+	dsi_host_private->dsi_on = 0;
+
+	mutex_unlock(&ctrl_pdata->mutex);
 
 	return ret;
 }
@@ -931,17 +1146,23 @@
 				panel_data);
 
 	pinfo = &pdata->panel_info;
+	mutex_lock(&ctrl_pdata->mutex);
 	ret = msm_dss_enable_vreg(
 		ctrl_pdata->power_data.vreg_config,
 		ctrl_pdata->power_data.num_vreg, 1);
 	if (ret) {
 		pr_err("%s: DSI power on failed\n", __func__);
+		mutex_unlock(&ctrl_pdata->mutex);
 		return ret;
 	}
 
 	msm_dsi_ahb_ctrl(1);
 	msm_dsi_prepare_clocks();
 	msm_dsi_clk_enable();
+	msm_dsi_set_irq(ctrl_pdata, DSI_INTR_ERROR_MASK);
+	dsi_host_private->clk_count = 1;
+	dsi_host_private->dsi_on = 1;
+	mutex_unlock(&ctrl_pdata->mutex);
 	return 0;
 }
 
@@ -1073,24 +1294,53 @@
 static int msm_dsi_clk_ctrl(struct mdss_panel_data *pdata, int enable)
 {
 	u32 bitclk_rate = 0, byteclk_rate = 0, pclk_rate = 0, dsiclk_rate = 0;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
 	pr_debug("%s:\n", __func__);
 
+	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+				panel_data);
+
+	mutex_lock(&ctrl_pdata->mutex);
+
 	if (enable) {
-		msm_dsi_ahb_ctrl(1);
-		msm_dsi_cal_clk_rate(pdata, &bitclk_rate, &dsiclk_rate,
-					&byteclk_rate, &pclk_rate);
-		msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, dsiclk_rate,
-					byteclk_rate, pclk_rate);
-		msm_dsi_clk_enable();
+		dsi_host_private->clk_count++;
+		if (dsi_host_private->clk_count == 1) {
+			msm_dsi_ahb_ctrl(1);
+			msm_dsi_cal_clk_rate(pdata, &bitclk_rate, &dsiclk_rate,
+						&byteclk_rate, &pclk_rate);
+			msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, dsiclk_rate,
+						byteclk_rate, pclk_rate);
+			msm_dsi_clk_enable();
+		}
 	} else {
-		msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, 0, 0, 0);
-		msm_dsi_clk_disable();
-		msm_dsi_ahb_ctrl(0);
+		dsi_host_private->clk_count--;
+		if (dsi_host_private->clk_count == 0) {
+			msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, 0, 0, 0);
+			msm_dsi_clk_disable();
+			msm_dsi_ahb_ctrl(0);
+		}
 	}
+	mutex_unlock(&ctrl_pdata->mutex);
 	return 0;
 }
 
+void msm_dsi_ctrl_init(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	init_completion(&ctrl->dma_comp);
+	init_completion(&ctrl->mdp_comp);
+	init_completion(&ctrl->video_comp);
+	spin_lock_init(&ctrl->irq_lock);
+	spin_lock_init(&ctrl->mdp_lock);
+	mutex_init(&ctrl->mutex);
+	mutex_init(&ctrl->cmd_mutex);
+	complete(&ctrl->mdp_comp);
+	dsi_buf_alloc(&ctrl->tx_buf, SZ_4K);
+	dsi_buf_alloc(&ctrl->rx_buf, SZ_4K);
+	ctrl->cmdlist_commit = msm_dsi_cmdlist_commit;
+	ctrl->panel_mode = ctrl->panel_data.panel_info.mipi.mode;
+}
+
 static int __devinit msm_dsi_probe(struct platform_device *pdev)
 {
 	struct dsi_interface intf;
@@ -1151,7 +1401,8 @@
 		rc = -ENODEV;
 		goto error_irq_resource;
 	} else {
-		rc = msm_dsi_irq_init(&pdev->dev, mdss_dsi_mres->start);
+		rc = msm_dsi_irq_init(&pdev->dev, mdss_dsi_mres->start,
+					ctrl_pdata);
 		if (rc) {
 			dev_err(&pdev->dev, "%s: failed to init irq, rc=%d\n",
 								__func__, rc);
@@ -1211,14 +1462,14 @@
 	intf.cont_on = msm_dsi_cont_on;
 	intf.clk_ctrl = msm_dsi_clk_ctrl;
 	intf.op_mode_config = msm_dsi_op_mode_config;
-	intf.tx = msm_dsi_cmds_tx;
-	intf.rx = msm_dsi_cmds_rx;
 	intf.index = 0;
 	intf.private = NULL;
 	dsi_register_interface(&intf);
 
 	msm_dsi_debug_init();
 
+	msm_dsi_ctrl_init(ctrl_pdata);
+
 	rc = dsi_panel_device_register_v2(pdev, ctrl_pdata);
 	if (rc) {
 		pr_err("%s: dsi panel dev reg failed\n", __func__);
@@ -1233,7 +1484,7 @@
 error_pan_node:
 	of_node_put(dsi_pan_node);
 error_platform_pop:
-	msm_dsi_disable_irq();
+	msm_dsi_clear_irq(ctrl_pdata, ctrl_pdata->dsi_irq_mask);
 error_irq_resource:
 	if (dsi_host_private->dsi_base) {
 		iounmap(dsi_host_private->dsi_base);
@@ -1255,7 +1506,7 @@
 		return -ENODEV;
 	}
 
-	msm_dsi_disable_irq();
+	msm_dsi_clear_irq(ctrl_pdata, ctrl_pdata->dsi_irq_mask);
 	msm_dsi_io_deinit(pdev, &(ctrl_pdata->power_data));
 	dsi_ctrl_config_deinit(pdev, ctrl_pdata);
 	iounmap(dsi_host_private->dsi_base);
diff --git a/drivers/video/msm/mdss/dsi_v2.c b/drivers/video/msm/mdss/dsi_v2.c
index f3d0ad4..ccde545 100644
--- a/drivers/video/msm/mdss/dsi_v2.c
+++ b/drivers/video/msm/mdss/dsi_v2.c
@@ -21,7 +21,6 @@
 #include "dsi_v2.h"
 
 static struct dsi_interface dsi_intf;
-static struct dsi_buf dsi_panel_tx_buf;
 
 static int dsi_off(struct mdss_panel_data *pdata)
 {
@@ -67,21 +66,13 @@
 	if (enable) {
 		dsi_ctrl_gpio_request(ctrl_pdata);
 		mdss_dsi_panel_reset(pdata, 1);
-
-		rc = dsi_cmds_tx_v2(pdata, &dsi_panel_tx_buf,
-					ctrl_pdata->on_cmds.cmds,
-					ctrl_pdata->on_cmds.cmd_cnt);
-
+		rc = ctrl_pdata->on(pdata);
 		if (rc)
 			pr_err("dsi_panel_handler panel on failed %d\n", rc);
 	} else {
 		if (dsi_intf.op_mode_config)
 			dsi_intf.op_mode_config(DSI_CMD_MODE, pdata);
-
-		dsi_cmds_tx_v2(pdata, &dsi_panel_tx_buf,
-					ctrl_pdata->off_cmds.cmds,
-					ctrl_pdata->off_cmds.cmd_cnt);
-
+		rc = ctrl_pdata->off(pdata);
 		mdss_dsi_panel_reset(pdata, 0);
 		dsi_ctrl_gpio_free(ctrl_pdata);
 	}
@@ -572,19 +563,12 @@
 
 	ctrl_pdata->panel_data.event_handler = dsi_event_handler;
 
-	rc = dsi_buf_alloc(&dsi_panel_tx_buf,
-				ALIGN(DSI_BUF_SIZE,
-				SZ_4K));
-	if (rc)
-		return rc;
-
 	/*
 	 * register in mdp driver
 	 */
 	rc = mdss_register_panel(dev, &(ctrl_pdata->panel_data));
 	if (rc) {
 		dev_err(&dev->dev, "unable to register MIPI DSI panel\n");
-		kfree(dsi_panel_tx_buf.start);
 		return rc;
 	}
 
@@ -597,72 +581,6 @@
 	dsi_intf = *intf;
 }
 
-int dsi_cmds_tx_v2(struct mdss_panel_data *pdata,
-			struct dsi_buf *tp, struct dsi_cmd_desc *cmds,
-			int cnt)
-{
-	int rc = 0;
-
-	if (!dsi_intf.tx)
-		return -EINVAL;
-
-	rc = dsi_intf.tx(pdata, tp, cmds, cnt);
-	return rc;
-}
-
-int dsi_cmds_rx_v2(struct mdss_panel_data *pdata,
-			struct dsi_buf *tp, struct dsi_buf *rp,
-			struct dsi_cmd_desc *cmds, int rlen)
-{
-	int rc = 0;
-
-	if (pdata == NULL) {
-		pr_err("%s: Invalid input data\n", __func__);
-		return -EINVAL;
-	}
-
-	if (!dsi_intf.rx)
-		return -EINVAL;
-
-	rc = dsi_intf.rx(pdata, tp, rp, cmds, rlen);
-	return rc;
-}
-
-static char *dsi_buf_reserve(struct dsi_buf *dp, int len)
-{
-	dp->data += len;
-	return dp->data;
-}
-
-
-static char *dsi_buf_push(struct dsi_buf *dp, int len)
-{
-	dp->data -= len;
-	dp->len += len;
-	return dp->data;
-}
-
-static char *dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen)
-{
-	dp->hdr = (u32 *)dp->data;
-	return dsi_buf_reserve(dp, hlen);
-}
-
-char *dsi_buf_init(struct dsi_buf *dp)
-{
-	int off;
-
-	dp->data = dp->start;
-	off = (int)dp->data;
-	/* 8 byte align */
-	off &= 0x07;
-	if (off)
-		off = 8 - off;
-	dp->data += off;
-	dp->len = 0;
-	return dp->data;
-}
-
 int dsi_buf_alloc(struct dsi_buf *dp, int size)
 {
 	dp->start = kmalloc(size, GFP_KERNEL);
@@ -684,507 +602,3 @@
 	return 0;
 }
 
-/*
- * mipi dsi generic long write
- */
-static int dsi_generic_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	char *bp;
-	u32 *hp;
-	int i, len;
-	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
-	bp = dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-
-	/* fill up payload */
-	if (cm->payload) {
-		len = dchdr->dlen;
-		len += 3;
-		len &= ~0x03; /* multipled by 4 */
-		for (i = 0; i < dchdr->dlen; i++)
-			*bp++ = cm->payload[i];
-
-		/* append 0xff to the end */
-		for (; i < len; i++)
-			*bp++ = 0xff;
-
-		dp->len += len;
-	}
-
-	/* fill up header */
-	hp = dp->hdr;
-	*hp = 0;
-	*hp = DSI_HDR_WC(dchdr->dlen);
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_LONG_PKT;
-	*hp |= DSI_HDR_DTYPE(DTYPE_GEN_LWRITE);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
-	return dp->len;
-}
-
-/*
- * mipi dsi generic short write with 0, 1 2 parameters
- */
-static int dsi_generic_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	u32 *hp;
-	int len;
-	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
-	if (dchdr->dlen && cm->payload == 0) {
-		pr_err("%s: NO payload error\n", __func__);
-		return 0;
-	}
-
-	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	len = (dchdr->dlen > 2) ? 2 : dchdr->dlen;
-
-	if (len == 1) {
-		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE1);
-		*hp |= DSI_HDR_DATA1(cm->payload[0]);
-		*hp |= DSI_HDR_DATA2(0);
-	} else if (len == 2) {
-		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE2);
-		*hp |= DSI_HDR_DATA1(cm->payload[0]);
-		*hp |= DSI_HDR_DATA2(cm->payload[1]);
-	} else {
-		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE);
-		*hp |= DSI_HDR_DATA1(0);
-		*hp |= DSI_HDR_DATA2(0);
-	}
-
-	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
-	return dp->len;
-}
-
-/*
- * mipi dsi gerneric read with 0, 1 2 parameters
- */
-static int dsi_generic_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	u32 *hp;
-	int len;
-	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
-	if (dchdr->dlen && cm->payload == 0) {
-		pr_err("%s: NO payload error\n", __func__);
-		return 0;
-	}
-
-	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_BTA;
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	len = (dchdr->dlen > 2) ? 2 : dchdr->dlen;
-
-	if (len == 1) {
-		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ1);
-		*hp |= DSI_HDR_DATA1(cm->payload[0]);
-		*hp |= DSI_HDR_DATA2(0);
-	} else if (len == 2) {
-		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ2);
-		*hp |= DSI_HDR_DATA1(cm->payload[0]);
-		*hp |= DSI_HDR_DATA2(cm->payload[1]);
-	} else {
-		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ);
-		*hp |= DSI_HDR_DATA1(0);
-		*hp |= DSI_HDR_DATA2(0);
-	}
-
-	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-	return dp->len;
-}
-
-/*
- * mipi dsi dcs long write
- */
-static int dsi_dcs_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	char *bp;
-	u32 *hp;
-	int i, len;
-	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
-	bp = dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-
-	/*
-	 * fill up payload
-	 * dcs command byte (first byte) followed by payload
-	 */
-	if (cm->payload) {
-		len = dchdr->dlen;
-		len += 3;
-		len &= ~0x03; /* multipled by 4 */
-		for (i = 0; i < dchdr->dlen; i++)
-			*bp++ = cm->payload[i];
-
-		/* append 0xff to the end */
-		for (; i < len; i++)
-			*bp++ = 0xff;
-
-		dp->len += len;
-	}
-
-	/* fill up header */
-	hp = dp->hdr;
-	*hp = 0;
-	*hp = DSI_HDR_WC(dchdr->dlen);
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_LONG_PKT;
-	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_LWRITE);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
-	return dp->len;
-}
-
-/*
- * mipi dsi dcs short write with 0 parameters
- */
-static int dsi_dcs_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	u32 *hp;
-	int len;
-	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
-	if (cm->payload == 0) {
-		pr_err("%s: NO payload error\n", __func__);
-		return -EINVAL;
-	}
-
-	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	if (dchdr->ack)
-		*hp |= DSI_HDR_BTA;
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	len = (dchdr->dlen > 1) ? 1 : dchdr->dlen;
-
-	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE);
-	*hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs command byte */
-	*hp |= DSI_HDR_DATA2(0);
-
-	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-	return dp->len;
-}
-
-/*
- * mipi dsi dcs short write with 1 parameters
- */
-static int dsi_dcs_swrite1(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	u32 *hp;
-	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
-	if (dchdr->dlen < 2 || cm->payload == 0) {
-		pr_err("%s: NO payload error\n", __func__);
-		return -EINVAL;
-	}
-
-	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	if (dchdr->ack)
-		*hp |= DSI_HDR_BTA;
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE1);
-	*hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs comamnd byte */
-	*hp |= DSI_HDR_DATA2(cm->payload[1]); /* parameter */
-
-	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
-	return dp->len;
-}
-
-/*
- * mipi dsi dcs read with 0 parameters
- */
-static int dsi_dcs_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	u32 *hp;
-	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
-	if (cm->payload == 0) {
-		pr_err("%s: NO payload error\n", __func__);
-		return -EINVAL;
-	}
-
-	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_BTA;
-	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_READ);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	*hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs command byte */
-	*hp |= DSI_HDR_DATA2(0);
-
-	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
-	return dp->len; /* 4 bytes */
-}
-
-static int dsi_cm_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	u32 *hp;
-	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
-	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_DTYPE(DTYPE_CM_ON);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
-	return dp->len; /* 4 bytes */
-}
-
-static int dsi_cm_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	u32 *hp;
-	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
-	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_DTYPE(DTYPE_CM_OFF);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
-	return dp->len; /* 4 bytes */
-}
-
-static int dsi_peripheral_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	u32 *hp;
-	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
-	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_ON);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
-	return dp->len; /* 4 bytes */
-}
-
-static int dsi_peripheral_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	u32 *hp;
-	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
-	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_OFF);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
-	return dp->len; /* 4 bytes */
-}
-
-static int dsi_set_max_pktsize(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	u32 *hp;
-	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
-	if (cm->payload == 0) {
-		pr_err("%s: NO payload error\n", __func__);
-		return 0;
-	}
-
-	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_DTYPE(DTYPE_MAX_PKTSIZE);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	*hp |= DSI_HDR_DATA1(cm->payload[0]);
-	*hp |= DSI_HDR_DATA2(cm->payload[1]);
-
-	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
-	return dp->len; /* 4 bytes */
-}
-
-static int dsi_null_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	u32 *hp;
-	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
-	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp = DSI_HDR_WC(dchdr->dlen);
-	*hp |= DSI_HDR_LONG_PKT;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_DTYPE(DTYPE_NULL_PKT);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
-	return dp->len; /* 4 bytes */
-}
-
-static int dsi_blank_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	u32 *hp;
-	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
-	dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp = DSI_HDR_WC(dchdr->dlen);
-	*hp |= DSI_HDR_LONG_PKT;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_DTYPE(DTYPE_BLANK_PKT);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
-	return dp->len; /* 4 bytes */
-}
-
-/*
- * prepare cmd buffer to be txed
- */
-int dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	int len = 0;
-	struct dsi_ctrl_hdr *dchdr = &cm->dchdr;
-
-	switch (dchdr->dtype) {
-	case DTYPE_GEN_WRITE:
-	case DTYPE_GEN_WRITE1:
-	case DTYPE_GEN_WRITE2:
-		len = dsi_generic_swrite(dp, cm);
-		break;
-	case DTYPE_GEN_LWRITE:
-		len = dsi_generic_lwrite(dp, cm);
-		break;
-	case DTYPE_GEN_READ:
-	case DTYPE_GEN_READ1:
-	case DTYPE_GEN_READ2:
-		len = dsi_generic_read(dp, cm);
-		break;
-	case DTYPE_DCS_LWRITE:
-		len = dsi_dcs_lwrite(dp, cm);
-		break;
-	case DTYPE_DCS_WRITE:
-		len = dsi_dcs_swrite(dp, cm);
-		break;
-	case DTYPE_DCS_WRITE1:
-		len = dsi_dcs_swrite1(dp, cm);
-		break;
-	case DTYPE_DCS_READ:
-		len = dsi_dcs_read(dp, cm);
-		break;
-	case DTYPE_MAX_PKTSIZE:
-		len = dsi_set_max_pktsize(dp, cm);
-		break;
-	case DTYPE_NULL_PKT:
-		len = dsi_null_pkt(dp, cm);
-		break;
-	case DTYPE_BLANK_PKT:
-		len = dsi_blank_pkt(dp, cm);
-		break;
-	case DTYPE_CM_ON:
-		len = dsi_cm_on(dp, cm);
-		break;
-	case DTYPE_CM_OFF:
-		len = dsi_cm_off(dp, cm);
-		break;
-	case DTYPE_PERIPHERAL_ON:
-		len = dsi_peripheral_on(dp, cm);
-		break;
-	case DTYPE_PERIPHERAL_OFF:
-		len = dsi_peripheral_off(dp, cm);
-		break;
-	default:
-		pr_debug("%s: dtype=%x NOT supported\n",
-					__func__, dchdr->dtype);
-		break;
-
-	}
-
-	return len;
-}
-
-/*
- * mdss_dsi_short_read1_resp: 1 parameter
- */
-int dsi_short_read1_resp(struct dsi_buf *rp)
-{
-	/* strip out dcs type */
-	rp->data++;
-	rp->len = 1;
-	return rp->len;
-}
-
-/*
- * mdss_dsi_short_read2_resp: 2 parameter
- */
-int dsi_short_read2_resp(struct dsi_buf *rp)
-{
-	/* strip out dcs type */
-	rp->data++;
-	rp->len = 2;
-	return rp->len;
-}
-
-int dsi_long_read_resp(struct dsi_buf *rp)
-{
-	short len;
-
-	len = rp->data[2];
-	len <<= 8;
-	len |= rp->data[1];
-	/* strip out dcs header */
-	rp->data += 4;
-	rp->len -= 4;
-	/* strip out 2 bytes of checksum */
-	rp->len -= 2;
-	return len;
-}
diff --git a/drivers/video/msm/mdss/dsi_v2.h b/drivers/video/msm/mdss/dsi_v2.h
index cb007e3..b8c91da 100644
--- a/drivers/video/msm/mdss/dsi_v2.h
+++ b/drivers/video/msm/mdss/dsi_v2.h
@@ -29,11 +29,6 @@
 	int (*cont_on)(struct mdss_panel_data *pdata);
 	int (*clk_ctrl)(struct mdss_panel_data *pdata, int enable);
 	void (*op_mode_config)(int mode, struct mdss_panel_data *pdata);
-	int (*tx)(struct mdss_panel_data *pdata,
-		struct dsi_buf *tp, struct dsi_cmd_desc *cmds, int cnt);
-	int (*rx)(struct mdss_panel_data *pdata,
-		 struct dsi_buf *tp, struct dsi_buf *rp,
-		struct dsi_cmd_desc *cmds, int len);
 	int index;
 	void *private;
 };
@@ -43,26 +38,8 @@
 
 void dsi_register_interface(struct dsi_interface *intf);
 
-int dsi_cmds_rx_v2(struct mdss_panel_data *pdata,
-			struct dsi_buf *tp, struct dsi_buf *rp,
-			struct dsi_cmd_desc *cmds, int len);
-
-int dsi_cmds_tx_v2(struct mdss_panel_data *pdata,
-			struct dsi_buf *tp, struct dsi_cmd_desc *cmds,
-			int cnt);
-
-char *dsi_buf_init(struct dsi_buf *dp);
-
 int dsi_buf_alloc(struct dsi_buf *dp, int size);
 
-int dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm);
-
-int dsi_short_read1_resp(struct dsi_buf *rp);
-
-int dsi_short_read2_resp(struct dsi_buf *rp);
-
-int dsi_long_read_resp(struct dsi_buf *rp);
-
 void dsi_set_tx_power_mode(int mode);
 
 void dsi_ctrl_config_deinit(struct platform_device *pdev,
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index 947923a..d743c42 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -19,6 +19,7 @@
 
 #include "mdss_panel.h"
 #include "mdss_io_util.h"
+#include "mdss_dsi_cmd.h"
 
 #define MMSS_SERDES_BASE_PHY 0x04f01000 /* mmss (De)Serializer CFG */
 
@@ -194,81 +195,6 @@
 	u32 pre_div_func;
 };
 
-#define DSI_HOST_HDR_SIZE	4
-#define DSI_HDR_LAST		BIT(31)
-#define DSI_HDR_LONG_PKT	BIT(30)
-#define DSI_HDR_BTA		BIT(29)
-#define DSI_HDR_VC(vc)		(((vc) & 0x03) << 22)
-#define DSI_HDR_DTYPE(dtype)	(((dtype) & 0x03f) << 16)
-#define DSI_HDR_DATA2(data)	(((data) & 0x0ff) << 8)
-#define DSI_HDR_DATA1(data)	((data) & 0x0ff)
-#define DSI_HDR_WC(wc)		((wc) & 0x0ffff)
-
-#define MDSS_DSI_MRPS	0x04  /* Maximum Return Packet Size */
-
-#define MDSS_DSI_LEN 8 /* 4 x 4 - 6 - 2, bytes dcs header+crc-align  */
-
-struct dsi_buf {
-	u32 *hdr;	/* dsi host header */
-	char *start;	/* buffer start addr */
-	char *end;	/* buffer end addr */
-	int size;	/* size of buffer */
-	char *data;	/* buffer */
-	int len;	/* data length */
-	dma_addr_t dmap; /* mapped dma addr */
-};
-
-/* dcs read/write */
-#define DTYPE_DCS_WRITE		0x05	/* short write, 0 parameter */
-#define DTYPE_DCS_WRITE1	0x15	/* short write, 1 parameter */
-#define DTYPE_DCS_READ		0x06	/* read */
-#define DTYPE_DCS_LWRITE	0x39	/* long write */
-
-/* generic read/write */
-#define DTYPE_GEN_WRITE		0x03	/* short write, 0 parameter */
-#define DTYPE_GEN_WRITE1	0x13	/* short write, 1 parameter */
-#define DTYPE_GEN_WRITE2	0x23	/* short write, 2 parameter */
-#define DTYPE_GEN_LWRITE	0x29	/* long write */
-#define DTYPE_GEN_READ		0x04	/* long read, 0 parameter */
-#define DTYPE_GEN_READ1		0x14	/* long read, 1 parameter */
-#define DTYPE_GEN_READ2		0x24	/* long read, 2 parameter */
-
-#define DTYPE_TEAR_ON		0x35	/* set tear on */
-#define DTYPE_MAX_PKTSIZE	0x37	/* set max packet size */
-#define DTYPE_NULL_PKT		0x09	/* null packet, no data */
-#define DTYPE_BLANK_PKT		0x19	/* blankiing packet, no data */
-
-#define DTYPE_CM_ON		0x02	/* color mode off */
-#define DTYPE_CM_OFF		0x12	/* color mode on */
-#define DTYPE_PERIPHERAL_OFF	0x22
-#define DTYPE_PERIPHERAL_ON	0x32
-
-/*
- * dcs response
- */
-#define DTYPE_ACK_ERR_RESP      0x02
-#define DTYPE_EOT_RESP          0x08    /* end of tx */
-#define DTYPE_GEN_READ1_RESP    0x11    /* 1 parameter, short */
-#define DTYPE_GEN_READ2_RESP    0x12    /* 2 parameter, short */
-#define DTYPE_GEN_LREAD_RESP    0x1a
-#define DTYPE_DCS_LREAD_RESP    0x1c
-#define DTYPE_DCS_READ1_RESP    0x21    /* 1 parameter, short */
-#define DTYPE_DCS_READ2_RESP    0x22    /* 2 parameter, short */
-
-
-struct dsi_ctrl_hdr {
-	char dtype;	/* data type */
-	char last;	/* last in chain */
-	char vc;	/* virtual chan */
-	char ack;	/* ask ACK from peripheral */
-	char wait;	/* ms */
-	short dlen;	/* 16 bits */
-} __packed;
-
-struct dsi_cmd_desc {
-	struct dsi_ctrl_hdr dchdr;
-	char *payload;
-};
 
 struct dsi_panel_cmds {
 	char *buf;
@@ -278,29 +204,6 @@
 	int link_state;
 };
 
-#define CMD_REQ_MAX     4
-
-#define CMD_REQ_RX      0x0001
-#define CMD_REQ_COMMIT  0x0002
-#define CMD_CLK_CTRL    0x0004
-#define CMD_REQ_NO_MAX_PKT_SIZE 0x0008
-
-struct dcs_cmd_req {
-	struct dsi_cmd_desc *cmds;
-	int cmds_cnt;
-	u32 flags;
-	int rlen;       /* rx length */
-	char *rbuf;	/* rx buf */
-	void (*cb)(int data);
-};
-
-struct dcs_cmd_list {
-	int put;
-	int get;
-	int tot;
-	struct dcs_cmd_req list[CMD_REQ_MAX];
-};
-
 struct dsi_kickoff_action {
 	struct list_head act_entry;
 	void (*action) (void *);
@@ -330,6 +233,7 @@
 	int (*off) (struct mdss_panel_data *pdata);
 	int (*partial_update_fnc) (struct mdss_panel_data *pdata);
 	int (*check_status) (struct mdss_dsi_ctrl_pdata *pdata);
+	void (*cmdlist_commit)(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp);
 	struct mdss_panel_data panel_data;
 	unsigned char *ctrl_base;
 	int reg_size;
@@ -389,11 +293,6 @@
 int dsi_panel_device_register(struct device_node *pan_node,
 				struct mdss_dsi_ctrl_pdata *ctrl_pdata);
 
-char *mdss_dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen);
-char *mdss_dsi_buf_init(struct dsi_buf *dp);
-void mdss_dsi_init(void);
-int mdss_dsi_buf_alloc(struct dsi_buf *, int size);
-int mdss_dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm);
 int mdss_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl,
 		struct dsi_cmd_desc *cmds, int cnt);
 
@@ -402,8 +301,6 @@
 
 void mdss_dsi_host_init(struct mipi_panel_info *pinfo,
 				struct mdss_panel_data *pdata);
-void mdss_dsi_set_tear_on(struct mdss_dsi_ctrl_pdata *ctrl);
-void mdss_dsi_set_tear_off(struct mdss_dsi_ctrl_pdata *ctrl);
 void mdss_dsi_op_mode_config(int mode,
 				struct mdss_panel_data *pdata);
 void mdss_dsi_cmd_mode_ctrl(int enable);
@@ -440,9 +337,6 @@
 void mdss_dsi_cmd_mdp_busy(struct mdss_dsi_ctrl_pdata *ctrl);
 void mdss_dsi_wait4video_done(struct mdss_dsi_ctrl_pdata *ctrl);
 void mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp);
-int mdss_dsi_cmdlist_put(struct mdss_dsi_ctrl_pdata *ctrl,
-				struct dcs_cmd_req *cmdreq);
-struct dcs_cmd_req *mdss_dsi_cmdlist_get(struct mdss_dsi_ctrl_pdata *ctrl);
 void mdss_dsi_cmdlist_kickoff(int intf);
 int mdss_dsi_bta_status_check(struct mdss_dsi_ctrl_pdata *ctrl);
 
diff --git a/drivers/video/msm/mdss/mdss_dsi_cmd.c b/drivers/video/msm/mdss/mdss_dsi_cmd.c
new file mode 100644
index 0000000..9a3e638
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_dsi_cmd.c
@@ -0,0 +1,689 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/iopoll.h>
+#include <linux/kthread.h>
+
+#include <mach/iommu_domains.h>
+
+#include "mdss_dsi_cmd.h"
+#include "mdss_dsi.h"
+
+/*
+ * mipi dsi buf mechanism
+ */
+char *mdss_dsi_buf_reserve(struct dsi_buf *dp, int len)
+{
+	dp->data += len;
+	return dp->data;
+}
+
+char *mdss_dsi_buf_unreserve(struct dsi_buf *dp, int len)
+{
+	dp->data -= len;
+	return dp->data;
+}
+
+char *mdss_dsi_buf_push(struct dsi_buf *dp, int len)
+{
+	dp->data -= len;
+	dp->len += len;
+	return dp->data;
+}
+
+char *mdss_dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen)
+{
+	dp->hdr = (u32 *)dp->data;
+	return mdss_dsi_buf_reserve(dp, hlen);
+}
+
+char *mdss_dsi_buf_init(struct dsi_buf *dp)
+{
+	int off;
+
+	dp->data = dp->start;
+	off = (int)dp->data;
+	/* 8 byte align */
+	off &= 0x07;
+	if (off)
+		off = 8 - off;
+	dp->data += off;
+	dp->len = 0;
+	return dp->data;
+}
+
+int mdss_dsi_buf_alloc(struct dsi_buf *dp, int size)
+{
+
+	dp->start = dma_alloc_writecombine(NULL, size, &dp->dmap, GFP_KERNEL);
+	if (dp->start == NULL) {
+		pr_err("%s:%u\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	dp->end = dp->start + size;
+	dp->size = size;
+
+	if ((int)dp->start & 0x07)
+		pr_err("%s: buf NOT 8 bytes aligned\n", __func__);
+
+	dp->data = dp->start;
+	dp->len = 0;
+	return size;
+}
+
+/*
+ * mipi dsi generic long write
+ */
+static int mdss_dsi_generic_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	struct dsi_ctrl_hdr *dchdr;
+	char *bp;
+	u32 *hp;
+	int i, len = 0;
+
+	dchdr = &cm->dchdr;
+	bp = mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+
+	/* fill up payload */
+	if (cm->payload) {
+		len = dchdr->dlen;
+		len += 3;
+		len &= ~0x03;	/* multipled by 4 */
+		for (i = 0; i < dchdr->dlen; i++)
+			*bp++ = cm->payload[i];
+
+		/* append 0xff to the end */
+		for (; i < len; i++)
+			*bp++ = 0xff;
+
+		dp->len += len;
+	}
+
+	/* fill up header */
+	hp = dp->hdr;
+	*hp = 0;
+	*hp = DSI_HDR_WC(dchdr->dlen);
+	*hp |= DSI_HDR_VC(dchdr->vc);
+	*hp |= DSI_HDR_LONG_PKT;
+	*hp |= DSI_HDR_DTYPE(DTYPE_GEN_LWRITE);
+	if (dchdr->last)
+		*hp |= DSI_HDR_LAST;
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+	len += DSI_HOST_HDR_SIZE;
+
+	return len;
+}
+
+/*
+ * mipi dsi generic short write with 0, 1 2 parameters
+ */
+static int mdss_dsi_generic_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	struct dsi_ctrl_hdr *dchdr;
+	u32 *hp;
+	int len;
+
+	dchdr = &cm->dchdr;
+	if (dchdr->dlen && cm->payload == 0) {
+		pr_err("%s: NO payload error\n", __func__);
+		return 0;
+	}
+
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(dchdr->vc);
+	if (dchdr->last)
+		*hp |= DSI_HDR_LAST;
+
+
+	len = (dchdr->dlen > 2) ? 2 : dchdr->dlen;
+
+	if (len == 1) {
+		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE1);
+		*hp |= DSI_HDR_DATA1(cm->payload[0]);
+		*hp |= DSI_HDR_DATA2(0);
+	} else if (len == 2) {
+		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE2);
+		*hp |= DSI_HDR_DATA1(cm->payload[0]);
+		*hp |= DSI_HDR_DATA2(cm->payload[1]);
+	} else {
+		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE);
+		*hp |= DSI_HDR_DATA1(0);
+		*hp |= DSI_HDR_DATA2(0);
+	}
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+	return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+/*
+ * mipi dsi gerneric read with 0, 1 2 parameters
+ */
+static int mdss_dsi_generic_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	struct dsi_ctrl_hdr *dchdr;
+	u32 *hp;
+	int len;
+
+	dchdr = &cm->dchdr;
+	if (dchdr->dlen && cm->payload == 0) {
+		pr_err("%s: NO payload error\n", __func__);
+		return 0;
+	}
+
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(dchdr->vc);
+	*hp |= DSI_HDR_BTA;
+	if (dchdr->last)
+		*hp |= DSI_HDR_LAST;
+
+	len = (dchdr->dlen > 2) ? 2 : dchdr->dlen;
+
+	if (len == 1) {
+		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ1);
+		*hp |= DSI_HDR_DATA1(cm->payload[0]);
+		*hp |= DSI_HDR_DATA2(0);
+	} else if (len == 2) {
+		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ2);
+		*hp |= DSI_HDR_DATA1(cm->payload[0]);
+		*hp |= DSI_HDR_DATA2(cm->payload[1]);
+	} else {
+		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ);
+		*hp |= DSI_HDR_DATA1(0);
+		*hp |= DSI_HDR_DATA2(0);
+	}
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+	return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+/*
+ * mipi dsi dcs long write
+ */
+static int mdss_dsi_dcs_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	struct dsi_ctrl_hdr *dchdr;
+	char *bp;
+	u32 *hp;
+	int i, len = 0;
+
+	dchdr = &cm->dchdr;
+	bp = mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+
+	/*
+	 * fill up payload
+	 * dcs command byte (first byte) followed by payload
+	 */
+	if (cm->payload) {
+		len = dchdr->dlen;
+		len += 3;
+		len &= ~0x03;	/* multipled by 4 */
+		for (i = 0; i < dchdr->dlen; i++)
+			*bp++ = cm->payload[i];
+
+		/* append 0xff to the end */
+		for (; i < len; i++)
+			*bp++ = 0xff;
+
+		dp->len += len;
+	}
+
+	/* fill up header */
+	hp = dp->hdr;
+	*hp = 0;
+	*hp = DSI_HDR_WC(dchdr->dlen);
+	*hp |= DSI_HDR_VC(dchdr->vc);
+	*hp |= DSI_HDR_LONG_PKT;
+	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_LWRITE);
+	if (dchdr->last)
+		*hp |= DSI_HDR_LAST;
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+	len += DSI_HOST_HDR_SIZE;
+	return len;
+}
+
+/*
+ * mipi dsi dcs short write with 0 parameters
+ */
+static int mdss_dsi_dcs_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	struct dsi_ctrl_hdr *dchdr;
+	u32 *hp;
+	int len;
+
+	dchdr = &cm->dchdr;
+	if (cm->payload == 0) {
+		pr_err("%s: NO payload error\n", __func__);
+		return -EINVAL;
+	}
+
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(dchdr->vc);
+	if (dchdr->ack)		/* ask ACK trigger msg from peripeheral */
+		*hp |= DSI_HDR_BTA;
+	if (dchdr->last)
+		*hp |= DSI_HDR_LAST;
+
+	len = (dchdr->dlen > 1) ? 1 : dchdr->dlen;
+
+	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE);
+	*hp |= DSI_HDR_DATA1(cm->payload[0]);	/* dcs command byte */
+	*hp |= DSI_HDR_DATA2(0);
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+	return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+/*
+ * mipi dsi dcs short write with 1 parameters
+ */
+static int mdss_dsi_dcs_swrite1(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	struct dsi_ctrl_hdr *dchdr;
+	u32 *hp;
+
+	dchdr = &cm->dchdr;
+	if (dchdr->dlen < 2 || cm->payload == 0) {
+		pr_err("%s: NO payload error\n", __func__);
+		return -EINVAL;
+	}
+
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(dchdr->vc);
+	if (dchdr->ack)		/* ask ACK trigger msg from peripeheral */
+		*hp |= DSI_HDR_BTA;
+	if (dchdr->last)
+		*hp |= DSI_HDR_LAST;
+
+	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE1);
+	*hp |= DSI_HDR_DATA1(cm->payload[0]);	/* dcs comamnd byte */
+	*hp |= DSI_HDR_DATA2(cm->payload[1]);	/* parameter */
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+	return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+/*
+ * mipi dsi dcs read with 0 parameters
+ */
+
+static int mdss_dsi_dcs_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	struct dsi_ctrl_hdr *dchdr;
+	u32 *hp;
+
+	dchdr = &cm->dchdr;
+	if (cm->payload == 0) {
+		pr_err("%s: NO payload error\n", __func__);
+		return -EINVAL;
+	}
+
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(dchdr->vc);
+	*hp |= DSI_HDR_BTA;
+	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_READ);
+	if (dchdr->last)
+		*hp |= DSI_HDR_LAST;
+
+	*hp |= DSI_HDR_DATA1(cm->payload[0]);	/* dcs command byte */
+	*hp |= DSI_HDR_DATA2(0);
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+	return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+static int mdss_dsi_cm_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	struct dsi_ctrl_hdr *dchdr;
+	u32 *hp;
+
+	dchdr = &cm->dchdr;
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(dchdr->vc);
+	*hp |= DSI_HDR_DTYPE(DTYPE_CM_ON);
+	if (dchdr->last)
+		*hp |= DSI_HDR_LAST;
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+	return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+static int mdss_dsi_cm_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	struct dsi_ctrl_hdr *dchdr;
+	u32 *hp;
+
+	dchdr = &cm->dchdr;
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(dchdr->vc);
+	*hp |= DSI_HDR_DTYPE(DTYPE_CM_OFF);
+	if (dchdr->last)
+		*hp |= DSI_HDR_LAST;
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+	return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+static int mdss_dsi_peripheral_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	struct dsi_ctrl_hdr *dchdr;
+	u32 *hp;
+
+	dchdr = &cm->dchdr;
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(dchdr->vc);
+	*hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_ON);
+	if (dchdr->last)
+		*hp |= DSI_HDR_LAST;
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+	return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+static int mdss_dsi_peripheral_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	struct dsi_ctrl_hdr *dchdr;
+	u32 *hp;
+
+	dchdr = &cm->dchdr;
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(dchdr->vc);
+	*hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_OFF);
+	if (dchdr->last)
+		*hp |= DSI_HDR_LAST;
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+	return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+static int mdss_dsi_set_max_pktsize(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	struct dsi_ctrl_hdr *dchdr;
+	u32 *hp;
+
+	dchdr = &cm->dchdr;
+	if (cm->payload == 0) {
+		pr_err("%s: NO payload error\n", __func__);
+		return 0;
+	}
+
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp |= DSI_HDR_VC(dchdr->vc);
+	*hp |= DSI_HDR_DTYPE(DTYPE_MAX_PKTSIZE);
+	if (dchdr->last)
+		*hp |= DSI_HDR_LAST;
+
+	*hp |= DSI_HDR_DATA1(cm->payload[0]);
+	*hp |= DSI_HDR_DATA2(cm->payload[1]);
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+	return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+static int mdss_dsi_null_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	struct dsi_ctrl_hdr *dchdr;
+	u32 *hp;
+
+	dchdr = &cm->dchdr;
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp = DSI_HDR_WC(dchdr->dlen);
+	*hp |= DSI_HDR_LONG_PKT;
+	*hp |= DSI_HDR_VC(dchdr->vc);
+	*hp |= DSI_HDR_DTYPE(DTYPE_NULL_PKT);
+	if (dchdr->last)
+		*hp |= DSI_HDR_LAST;
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+	return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+static int mdss_dsi_blank_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	struct dsi_ctrl_hdr *dchdr;
+	u32 *hp;
+
+	dchdr = &cm->dchdr;
+	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+	hp = dp->hdr;
+	*hp = 0;
+	*hp = DSI_HDR_WC(dchdr->dlen);
+	*hp |= DSI_HDR_LONG_PKT;
+	*hp |= DSI_HDR_VC(dchdr->vc);
+	*hp |= DSI_HDR_DTYPE(DTYPE_BLANK_PKT);
+	if (dchdr->last)
+		*hp |= DSI_HDR_LAST;
+
+	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+	return DSI_HOST_HDR_SIZE; /* 4 bytes */
+}
+
+/*
+ * prepare cmd buffer to be txed
+ */
+int mdss_dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+	struct dsi_ctrl_hdr *dchdr;
+	int len = 0;
+
+	dchdr = &cm->dchdr;
+
+	switch (dchdr->dtype) {
+	case DTYPE_GEN_WRITE:
+	case DTYPE_GEN_WRITE1:
+	case DTYPE_GEN_WRITE2:
+		len = mdss_dsi_generic_swrite(dp, cm);
+		break;
+	case DTYPE_GEN_LWRITE:
+		len = mdss_dsi_generic_lwrite(dp, cm);
+		break;
+	case DTYPE_GEN_READ:
+	case DTYPE_GEN_READ1:
+	case DTYPE_GEN_READ2:
+		len = mdss_dsi_generic_read(dp, cm);
+		break;
+	case DTYPE_DCS_LWRITE:
+		len = mdss_dsi_dcs_lwrite(dp, cm);
+		break;
+	case DTYPE_DCS_WRITE:
+		len = mdss_dsi_dcs_swrite(dp, cm);
+		break;
+	case DTYPE_DCS_WRITE1:
+		len = mdss_dsi_dcs_swrite1(dp, cm);
+		break;
+	case DTYPE_DCS_READ:
+		len = mdss_dsi_dcs_read(dp, cm);
+		break;
+	case DTYPE_MAX_PKTSIZE:
+		len = mdss_dsi_set_max_pktsize(dp, cm);
+		break;
+	case DTYPE_NULL_PKT:
+		len = mdss_dsi_null_pkt(dp, cm);
+		break;
+	case DTYPE_BLANK_PKT:
+		len = mdss_dsi_blank_pkt(dp, cm);
+		break;
+	case DTYPE_CM_ON:
+		len = mdss_dsi_cm_on(dp, cm);
+		break;
+	case DTYPE_CM_OFF:
+		len = mdss_dsi_cm_off(dp, cm);
+		break;
+	case DTYPE_PERIPHERAL_ON:
+		len = mdss_dsi_peripheral_on(dp, cm);
+		break;
+	case DTYPE_PERIPHERAL_OFF:
+		len = mdss_dsi_peripheral_off(dp, cm);
+		break;
+	default:
+		pr_debug("%s: dtype=%x NOT supported\n",
+					__func__, dchdr->dtype);
+		break;
+
+	}
+
+	return len;
+}
+
+/*
+ * mdss_dsi_short_read1_resp: 1 parameter
+ */
+int mdss_dsi_short_read1_resp(struct dsi_buf *rp)
+{
+	/* strip out dcs type */
+	rp->data++;
+	rp->len = 1;
+	return rp->len;
+}
+
+/*
+ * mdss_dsi_short_read2_resp: 2 parameter
+ */
+int mdss_dsi_short_read2_resp(struct dsi_buf *rp)
+{
+	/* strip out dcs type */
+	rp->data++;
+	rp->len = 2;
+	return rp->len;
+}
+
+int mdss_dsi_long_read_resp(struct dsi_buf *rp)
+{
+	/* strip out dcs header */
+	rp->data += 4;
+	rp->len -= 4;
+	return rp->len;
+}
+
+static char set_tear_on[2] = {0x35, 0x00};
+static struct dsi_cmd_desc dsi_tear_on_cmd = {
+	{DTYPE_DCS_WRITE1, 1, 0, 0, 0, sizeof(set_tear_on)}, set_tear_on};
+
+static char set_tear_off[2] = {0x34, 0x00};
+static struct dsi_cmd_desc dsi_tear_off_cmd = {
+	{DTYPE_DCS_WRITE, 1, 0, 0, 0, sizeof(set_tear_off)}, set_tear_off};
+
+void mdss_dsi_set_tear_on(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	struct dcs_cmd_req cmdreq;
+
+	cmdreq.cmds = &dsi_tear_on_cmd;
+	cmdreq.cmds_cnt = 1;
+	cmdreq.flags = CMD_REQ_COMMIT;
+	cmdreq.rlen = 0;
+	cmdreq.cb = NULL;
+
+	mdss_dsi_cmdlist_put(ctrl, &cmdreq);
+}
+
+void mdss_dsi_set_tear_off(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	struct dcs_cmd_req cmdreq;
+
+	cmdreq.cmds = &dsi_tear_off_cmd;
+	cmdreq.cmds_cnt = 1;
+	cmdreq.flags = CMD_REQ_COMMIT;
+	cmdreq.rlen = 0;
+	cmdreq.cb = NULL;
+
+	mdss_dsi_cmdlist_put(ctrl, &cmdreq);
+}
+
+/*
+ * mdss_dsi_cmd_get: ctrl->cmd_mutex acquired by caller
+ */
+struct dcs_cmd_req *mdss_dsi_cmdlist_get(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	struct dcs_cmd_list *clist;
+	struct dcs_cmd_req *req = NULL;
+
+	clist = &ctrl->cmdlist;
+	if (clist->get != clist->put) {
+		req = &clist->list[clist->get];
+		clist->get++;
+		clist->get %= CMD_REQ_MAX;
+		clist->tot--;
+		pr_debug("%s: tot=%d put=%d get=%d\n", __func__,
+		clist->tot, clist->put, clist->get);
+	}
+	return req;
+}
+
+int mdss_dsi_cmdlist_put(struct mdss_dsi_ctrl_pdata *ctrl,
+				struct dcs_cmd_req *cmdreq)
+{
+	struct dcs_cmd_req *req;
+	struct dcs_cmd_list *clist;
+	int ret = 0;
+
+	mutex_lock(&ctrl->cmd_mutex);
+	clist = &ctrl->cmdlist;
+	req = &clist->list[clist->put];
+	*req = *cmdreq;
+	clist->put++;
+	clist->put %= CMD_REQ_MAX;
+	clist->tot++;
+	if (clist->put == clist->get) {
+		/* drop the oldest one */
+		pr_debug("%s: DROP, tot=%d put=%d get=%d\n", __func__,
+			clist->tot, clist->put, clist->get);
+		clist->get++;
+		clist->get %= CMD_REQ_MAX;
+		clist->tot--;
+	}
+	mutex_unlock(&ctrl->cmd_mutex);
+
+	ret++;
+	pr_debug("%s: tot=%d put=%d get=%d\n", __func__,
+		clist->tot, clist->put, clist->get);
+
+	if (req->flags & CMD_REQ_COMMIT) {
+		if (!ctrl->cmdlist_commit)
+			pr_err("cmdlist_commit not implemented!\n");
+		else
+			ctrl->cmdlist_commit(ctrl, 0);
+	}
+	return ret;
+}
+
diff --git a/drivers/video/msm/mdss/mdss_dsi_cmd.h b/drivers/video/msm/mdss/mdss_dsi_cmd.h
new file mode 100644
index 0000000..c480756
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_dsi_cmd.h
@@ -0,0 +1,133 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MDSS_DSI_CMD_H
+#define MDSS_DSI_CMD_H
+
+#include "mdss.h"
+
+struct mdss_dsi_ctrl_pdata;
+
+#define DSI_HOST_HDR_SIZE	4
+#define DSI_HDR_LAST		BIT(31)
+#define DSI_HDR_LONG_PKT	BIT(30)
+#define DSI_HDR_BTA		BIT(29)
+#define DSI_HDR_VC(vc)		(((vc) & 0x03) << 22)
+#define DSI_HDR_DTYPE(dtype)	(((dtype) & 0x03f) << 16)
+#define DSI_HDR_DATA2(data)	(((data) & 0x0ff) << 8)
+#define DSI_HDR_DATA1(data)	((data) & 0x0ff)
+#define DSI_HDR_WC(wc)		((wc) & 0x0ffff)
+
+#define MDSS_DSI_MRPS	0x04  /* Maximum Return Packet Size */
+
+#define MDSS_DSI_LEN 8 /* 4 x 4 - 6 - 2, bytes dcs header+crc-align  */
+
+struct dsi_buf {
+	u32 *hdr;	/* dsi host header */
+	char *start;	/* buffer start addr */
+	char *end;	/* buffer end addr */
+	int size;	/* size of buffer */
+	char *data;	/* buffer */
+	int len;	/* data length */
+	dma_addr_t dmap; /* mapped dma addr */
+};
+
+/* dcs read/write */
+#define DTYPE_DCS_WRITE		0x05	/* short write, 0 parameter */
+#define DTYPE_DCS_WRITE1	0x15	/* short write, 1 parameter */
+#define DTYPE_DCS_READ		0x06	/* read */
+#define DTYPE_DCS_LWRITE	0x39	/* long write */
+
+/* generic read/write */
+#define DTYPE_GEN_WRITE		0x03	/* short write, 0 parameter */
+#define DTYPE_GEN_WRITE1	0x13	/* short write, 1 parameter */
+#define DTYPE_GEN_WRITE2	0x23	/* short write, 2 parameter */
+#define DTYPE_GEN_LWRITE	0x29	/* long write */
+#define DTYPE_GEN_READ		0x04	/* long read, 0 parameter */
+#define DTYPE_GEN_READ1		0x14	/* long read, 1 parameter */
+#define DTYPE_GEN_READ2		0x24	/* long read, 2 parameter */
+
+#define DTYPE_TEAR_ON		0x35	/* set tear on */
+#define DTYPE_MAX_PKTSIZE	0x37	/* set max packet size */
+#define DTYPE_NULL_PKT		0x09	/* null packet, no data */
+#define DTYPE_BLANK_PKT		0x19	/* blankiing packet, no data */
+
+#define DTYPE_CM_ON		0x02	/* color mode off */
+#define DTYPE_CM_OFF		0x12	/* color mode on */
+#define DTYPE_PERIPHERAL_OFF	0x22
+#define DTYPE_PERIPHERAL_ON	0x32
+
+/*
+ * dcs response
+ */
+#define DTYPE_ACK_ERR_RESP      0x02
+#define DTYPE_EOT_RESP          0x08    /* end of tx */
+#define DTYPE_GEN_READ1_RESP    0x11    /* 1 parameter, short */
+#define DTYPE_GEN_READ2_RESP    0x12    /* 2 parameter, short */
+#define DTYPE_GEN_LREAD_RESP    0x1a
+#define DTYPE_DCS_LREAD_RESP    0x1c
+#define DTYPE_DCS_READ1_RESP    0x21    /* 1 parameter, short */
+#define DTYPE_DCS_READ2_RESP    0x22    /* 2 parameter, short */
+
+struct dsi_ctrl_hdr {
+	char dtype;	/* data type */
+	char last;	/* last in chain */
+	char vc;	/* virtual chan */
+	char ack;	/* ask ACK from peripheral */
+	char wait;	/* ms */
+	short dlen;	/* 16 bits */
+} __packed;
+
+struct dsi_cmd_desc {
+	struct dsi_ctrl_hdr dchdr;
+	char *payload;
+};
+
+#define CMD_REQ_MAX     4
+#define CMD_REQ_RX      0x0001
+#define CMD_REQ_COMMIT  0x0002
+#define CMD_CLK_CTRL    0x0004
+#define CMD_REQ_NO_MAX_PKT_SIZE 0x0008
+
+struct dcs_cmd_req {
+	struct dsi_cmd_desc *cmds;
+	int cmds_cnt;
+	u32 flags;
+	int rlen;       /* rx length */
+	char *rbuf;	/* rx buf */
+	void (*cb)(int data);
+};
+
+struct dcs_cmd_list {
+	int put;
+	int get;
+	int tot;
+	struct dcs_cmd_req list[CMD_REQ_MAX];
+};
+
+char *mdss_dsi_buf_reserve(struct dsi_buf *dp, int len);
+char *mdss_dsi_buf_unreserve(struct dsi_buf *dp, int len);
+char *mdss_dsi_buf_push(struct dsi_buf *dp, int len);
+char *mdss_dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen);
+char *mdss_dsi_buf_init(struct dsi_buf *dp);
+int mdss_dsi_buf_alloc(struct dsi_buf *dp, int size);
+int mdss_dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm);
+int mdss_dsi_short_read1_resp(struct dsi_buf *rp);
+int mdss_dsi_short_read2_resp(struct dsi_buf *rp);
+int mdss_dsi_long_read_resp(struct dsi_buf *rp);
+void mdss_dsi_set_tear_on(struct mdss_dsi_ctrl_pdata *ctrl);
+void mdss_dsi_set_tear_off(struct mdss_dsi_ctrl_pdata *ctrl);
+struct dcs_cmd_req *mdss_dsi_cmdlist_get(struct mdss_dsi_ctrl_pdata *ctrl);
+int mdss_dsi_cmdlist_put(struct mdss_dsi_ctrl_pdata *ctrl,
+				struct dcs_cmd_req *cmdreq);
+#endif
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index 750fbf3..43065ec 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -107,6 +107,7 @@
 	mutex_init(&ctrl->cmd_mutex);
 	mdss_dsi_buf_alloc(&ctrl->tx_buf, SZ_4K);
 	mdss_dsi_buf_alloc(&ctrl->rx_buf, SZ_4K);
+	ctrl->cmdlist_commit = mdss_dsi_cmdlist_commit;
 
 
 	if (dsi_event.inited == 0) {
@@ -199,576 +200,6 @@
 	spin_unlock(&ctrl->irq_lock);
 }
 
-/*
- * mipi dsi buf mechanism
- */
-char *mdss_dsi_buf_reserve(struct dsi_buf *dp, int len)
-{
-	dp->data += len;
-	return dp->data;
-}
-
-char *mdss_dsi_buf_unreserve(struct dsi_buf *dp, int len)
-{
-	dp->data -= len;
-	return dp->data;
-}
-
-char *mdss_dsi_buf_push(struct dsi_buf *dp, int len)
-{
-	dp->data -= len;
-	dp->len += len;
-	return dp->data;
-}
-
-char *mdss_dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen)
-{
-	dp->hdr = (u32 *)dp->data;
-	return mdss_dsi_buf_reserve(dp, hlen);
-}
-
-char *mdss_dsi_buf_init(struct dsi_buf *dp)
-{
-	int off;
-
-	dp->data = dp->start;
-	off = (int)dp->data;
-	/* 8 byte align */
-	off &= 0x07;
-	if (off)
-		off = 8 - off;
-	dp->data += off;
-	dp->len = 0;
-	return dp->data;
-}
-
-int mdss_dsi_buf_alloc(struct dsi_buf *dp, int size)
-{
-
-	dp->start = dma_alloc_writecombine(NULL, size, &dp->dmap, GFP_KERNEL);
-	if (dp->start == NULL) {
-		pr_err("%s:%u\n", __func__, __LINE__);
-		return -ENOMEM;
-	}
-
-	dp->end = dp->start + size;
-	dp->size = size;
-
-	if ((int)dp->start & 0x07)
-		pr_err("%s: buf NOT 8 bytes aligned\n", __func__);
-
-	dp->data = dp->start;
-	dp->len = 0;
-	return size;
-}
-
-/*
- * mipi dsi generic long write
- */
-static int mdss_dsi_generic_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	struct dsi_ctrl_hdr *dchdr;
-	char *bp;
-	u32 *hp;
-	int i, len = 0;
-
-	dchdr = &cm->dchdr;
-	bp = mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-
-	/* fill up payload */
-	if (cm->payload) {
-		len = dchdr->dlen;
-		len += 3;
-		len &= ~0x03;	/* multipled by 4 */
-		for (i = 0; i < dchdr->dlen; i++)
-			*bp++ = cm->payload[i];
-
-		/* append 0xff to the end */
-		for (; i < len; i++)
-			*bp++ = 0xff;
-
-		dp->len += len;
-	}
-
-	/* fill up header */
-	hp = dp->hdr;
-	*hp = 0;
-	*hp = DSI_HDR_WC(dchdr->dlen);
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_LONG_PKT;
-	*hp |= DSI_HDR_DTYPE(DTYPE_GEN_LWRITE);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-	len += DSI_HOST_HDR_SIZE;
-
-	return len;
-}
-
-/*
- * mipi dsi generic short write with 0, 1 2 parameters
- */
-static int mdss_dsi_generic_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	struct dsi_ctrl_hdr *dchdr;
-	u32 *hp;
-	int len;
-
-	dchdr = &cm->dchdr;
-	if (dchdr->dlen && cm->payload == 0) {
-		pr_err("%s: NO payload error\n", __func__);
-		return 0;
-	}
-
-	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-
-	len = (dchdr->dlen > 2) ? 2 : dchdr->dlen;
-
-	if (len == 1) {
-		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE1);
-		*hp |= DSI_HDR_DATA1(cm->payload[0]);
-		*hp |= DSI_HDR_DATA2(0);
-	} else if (len == 2) {
-		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE2);
-		*hp |= DSI_HDR_DATA1(cm->payload[0]);
-		*hp |= DSI_HDR_DATA2(cm->payload[1]);
-	} else {
-		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE);
-		*hp |= DSI_HDR_DATA1(0);
-		*hp |= DSI_HDR_DATA2(0);
-	}
-
-	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-	return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-/*
- * mipi dsi gerneric read with 0, 1 2 parameters
- */
-static int mdss_dsi_generic_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	struct dsi_ctrl_hdr *dchdr;
-	u32 *hp;
-	int len;
-
-	dchdr = &cm->dchdr;
-	if (dchdr->dlen && cm->payload == 0) {
-		pr_err("%s: NO payload error\n", __func__);
-		return 0;
-	}
-
-	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_BTA;
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	len = (dchdr->dlen > 2) ? 2 : dchdr->dlen;
-
-	if (len == 1) {
-		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ1);
-		*hp |= DSI_HDR_DATA1(cm->payload[0]);
-		*hp |= DSI_HDR_DATA2(0);
-	} else if (len == 2) {
-		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ2);
-		*hp |= DSI_HDR_DATA1(cm->payload[0]);
-		*hp |= DSI_HDR_DATA2(cm->payload[1]);
-	} else {
-		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ);
-		*hp |= DSI_HDR_DATA1(0);
-		*hp |= DSI_HDR_DATA2(0);
-	}
-
-	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-	return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-/*
- * mipi dsi dcs long write
- */
-static int mdss_dsi_dcs_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	struct dsi_ctrl_hdr *dchdr;
-	char *bp;
-	u32 *hp;
-	int i, len = 0;
-
-	dchdr = &cm->dchdr;
-	bp = mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-
-	/*
-	 * fill up payload
-	 * dcs command byte (first byte) followed by payload
-	 */
-	if (cm->payload) {
-		len = dchdr->dlen;
-		len += 3;
-		len &= ~0x03;	/* multipled by 4 */
-		for (i = 0; i < dchdr->dlen; i++)
-			*bp++ = cm->payload[i];
-
-		/* append 0xff to the end */
-		for (; i < len; i++)
-			*bp++ = 0xff;
-
-		dp->len += len;
-	}
-
-	/* fill up header */
-	hp = dp->hdr;
-	*hp = 0;
-	*hp = DSI_HDR_WC(dchdr->dlen);
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_LONG_PKT;
-	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_LWRITE);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-
-	len += DSI_HOST_HDR_SIZE;
-	return len;
-}
-
-/*
- * mipi dsi dcs short write with 0 parameters
- */
-static int mdss_dsi_dcs_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	struct dsi_ctrl_hdr *dchdr;
-	u32 *hp;
-	int len;
-
-	dchdr = &cm->dchdr;
-	if (cm->payload == 0) {
-		pr_err("%s: NO payload error\n", __func__);
-		return -EINVAL;
-	}
-
-	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	if (dchdr->ack)		/* ask ACK trigger msg from peripeheral */
-		*hp |= DSI_HDR_BTA;
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	len = (dchdr->dlen > 1) ? 1 : dchdr->dlen;
-
-	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE);
-	*hp |= DSI_HDR_DATA1(cm->payload[0]);	/* dcs command byte */
-	*hp |= DSI_HDR_DATA2(0);
-
-	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-	return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-/*
- * mipi dsi dcs short write with 1 parameters
- */
-static int mdss_dsi_dcs_swrite1(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	struct dsi_ctrl_hdr *dchdr;
-	u32 *hp;
-
-	dchdr = &cm->dchdr;
-	if (dchdr->dlen < 2 || cm->payload == 0) {
-		pr_err("%s: NO payload error\n", __func__);
-		return -EINVAL;
-	}
-
-	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	if (dchdr->ack)		/* ask ACK trigger msg from peripeheral */
-		*hp |= DSI_HDR_BTA;
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE1);
-	*hp |= DSI_HDR_DATA1(cm->payload[0]);	/* dcs comamnd byte */
-	*hp |= DSI_HDR_DATA2(cm->payload[1]);	/* parameter */
-
-	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-	return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-/*
- * mipi dsi dcs read with 0 parameters
- */
-
-static int mdss_dsi_dcs_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	struct dsi_ctrl_hdr *dchdr;
-	u32 *hp;
-
-	dchdr = &cm->dchdr;
-	if (cm->payload == 0) {
-		pr_err("%s: NO payload error\n", __func__);
-		return -EINVAL;
-	}
-
-	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_BTA;
-	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_READ);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	*hp |= DSI_HDR_DATA1(cm->payload[0]);	/* dcs command byte */
-	*hp |= DSI_HDR_DATA2(0);
-
-	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-	return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-static int mdss_dsi_cm_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	struct dsi_ctrl_hdr *dchdr;
-	u32 *hp;
-
-	dchdr = &cm->dchdr;
-	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_DTYPE(DTYPE_CM_ON);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-	return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-static int mdss_dsi_cm_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	struct dsi_ctrl_hdr *dchdr;
-	u32 *hp;
-
-	dchdr = &cm->dchdr;
-	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_DTYPE(DTYPE_CM_OFF);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-	return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-static int mdss_dsi_peripheral_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	struct dsi_ctrl_hdr *dchdr;
-	u32 *hp;
-
-	dchdr = &cm->dchdr;
-	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_ON);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-	return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-static int mdss_dsi_peripheral_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	struct dsi_ctrl_hdr *dchdr;
-	u32 *hp;
-
-	dchdr = &cm->dchdr;
-	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_OFF);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-	return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-static int mdss_dsi_set_max_pktsize(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	struct dsi_ctrl_hdr *dchdr;
-	u32 *hp;
-
-	dchdr = &cm->dchdr;
-	if (cm->payload == 0) {
-		pr_err("%s: NO payload error\n", __func__);
-		return 0;
-	}
-
-	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_DTYPE(DTYPE_MAX_PKTSIZE);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	*hp |= DSI_HDR_DATA1(cm->payload[0]);
-	*hp |= DSI_HDR_DATA2(cm->payload[1]);
-
-	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-	return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-static int mdss_dsi_null_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	struct dsi_ctrl_hdr *dchdr;
-	u32 *hp;
-
-	dchdr = &cm->dchdr;
-	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp = DSI_HDR_WC(dchdr->dlen);
-	*hp |= DSI_HDR_LONG_PKT;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_DTYPE(DTYPE_NULL_PKT);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-	return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-static int mdss_dsi_blank_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	struct dsi_ctrl_hdr *dchdr;
-	u32 *hp;
-
-	dchdr = &cm->dchdr;
-	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
-	hp = dp->hdr;
-	*hp = 0;
-	*hp = DSI_HDR_WC(dchdr->dlen);
-	*hp |= DSI_HDR_LONG_PKT;
-	*hp |= DSI_HDR_VC(dchdr->vc);
-	*hp |= DSI_HDR_DTYPE(DTYPE_BLANK_PKT);
-	if (dchdr->last)
-		*hp |= DSI_HDR_LAST;
-
-	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
-	return DSI_HOST_HDR_SIZE; /* 4 bytes */
-}
-
-/*
- * prepare cmd buffer to be txed
- */
-int mdss_dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
-{
-	struct dsi_ctrl_hdr *dchdr;
-	int len = 0;
-
-	dchdr = &cm->dchdr;
-
-	switch (dchdr->dtype) {
-	case DTYPE_GEN_WRITE:
-	case DTYPE_GEN_WRITE1:
-	case DTYPE_GEN_WRITE2:
-		len = mdss_dsi_generic_swrite(dp, cm);
-		break;
-	case DTYPE_GEN_LWRITE:
-		len = mdss_dsi_generic_lwrite(dp, cm);
-		break;
-	case DTYPE_GEN_READ:
-	case DTYPE_GEN_READ1:
-	case DTYPE_GEN_READ2:
-		len = mdss_dsi_generic_read(dp, cm);
-		break;
-	case DTYPE_DCS_LWRITE:
-		len = mdss_dsi_dcs_lwrite(dp, cm);
-		break;
-	case DTYPE_DCS_WRITE:
-		len = mdss_dsi_dcs_swrite(dp, cm);
-		break;
-	case DTYPE_DCS_WRITE1:
-		len = mdss_dsi_dcs_swrite1(dp, cm);
-		break;
-	case DTYPE_DCS_READ:
-		len = mdss_dsi_dcs_read(dp, cm);
-		break;
-	case DTYPE_MAX_PKTSIZE:
-		len = mdss_dsi_set_max_pktsize(dp, cm);
-		break;
-	case DTYPE_NULL_PKT:
-		len = mdss_dsi_null_pkt(dp, cm);
-		break;
-	case DTYPE_BLANK_PKT:
-		len = mdss_dsi_blank_pkt(dp, cm);
-		break;
-	case DTYPE_CM_ON:
-		len = mdss_dsi_cm_on(dp, cm);
-		break;
-	case DTYPE_CM_OFF:
-		len = mdss_dsi_cm_off(dp, cm);
-		break;
-	case DTYPE_PERIPHERAL_ON:
-		len = mdss_dsi_peripheral_on(dp, cm);
-		break;
-	case DTYPE_PERIPHERAL_OFF:
-		len = mdss_dsi_peripheral_off(dp, cm);
-		break;
-	default:
-		pr_debug("%s: dtype=%x NOT supported\n",
-					__func__, dchdr->dtype);
-		break;
-
-	}
-
-	return len;
-}
-
-/*
- * mdss_dsi_short_read1_resp: 1 parameter
- */
-static int mdss_dsi_short_read1_resp(struct dsi_buf *rp)
-{
-	/* strip out dcs type */
-	rp->data++;
-	rp->len = 1;
-	return rp->len;
-}
-
-/*
- * mdss_dsi_short_read2_resp: 2 parameter
- */
-static int mdss_dsi_short_read2_resp(struct dsi_buf *rp)
-{
-	/* strip out dcs type */
-	rp->data++;
-	rp->len = 2;
-	return rp->len;
-}
-
-static int mdss_dsi_long_read_resp(struct dsi_buf *rp)
-{
-	/* strip out dcs header */
-	rp->data += 4;
-	rp->len -= 4;
-	return rp->len;
-}
-
 void mdss_dsi_cmd_test_pattern(struct mdss_panel_data *pdata)
 {
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
@@ -1202,40 +633,6 @@
 	return ret;
 }
 
-static char set_tear_on[2] = {0x35, 0x00};
-static struct dsi_cmd_desc dsi_tear_on_cmd = {
-	{DTYPE_DCS_WRITE1, 1, 0, 0, 0, sizeof(set_tear_on)}, set_tear_on};
-
-static char set_tear_off[2] = {0x34, 0x00};
-static struct dsi_cmd_desc dsi_tear_off_cmd = {
-	{DTYPE_DCS_WRITE, 1, 0, 0, 0, sizeof(set_tear_off)}, set_tear_off};
-
-void mdss_dsi_set_tear_on(struct mdss_dsi_ctrl_pdata *ctrl)
-{
-	struct dcs_cmd_req cmdreq;
-
-	cmdreq.cmds = &dsi_tear_on_cmd;
-	cmdreq.cmds_cnt = 1;
-	cmdreq.flags = CMD_REQ_COMMIT;
-	cmdreq.rlen = 0;
-	cmdreq.cb = NULL;
-
-	mdss_dsi_cmdlist_put(ctrl, &cmdreq);
-}
-
-void mdss_dsi_set_tear_off(struct mdss_dsi_ctrl_pdata *ctrl)
-{
-	struct dcs_cmd_req cmdreq;
-
-	cmdreq.cmds = &dsi_tear_off_cmd;
-	cmdreq.cmds_cnt = 1;
-	cmdreq.flags = CMD_REQ_COMMIT;
-	cmdreq.rlen = 0;
-	cmdreq.cb = NULL;
-
-	mdss_dsi_cmdlist_put(ctrl, &cmdreq);
-}
-
 int mdss_dsi_cmd_reg_tx(u32 data,
 			unsigned char *ctrl_base)
 {
@@ -1765,7 +1162,6 @@
 
 	if (req->cb)
 		req->cb(ret);
-
 }
 
 void mdss_dsi_cmdlist_rx(struct mdss_dsi_ctrl_pdata *ctrl,
@@ -1828,61 +1224,6 @@
 	mutex_unlock(&ctrl->cmd_mutex);
 }
 
-/*
- * mdss_dsi_cmd_get: ctrl->cmd_mutex acquired by caller
- */
-struct dcs_cmd_req *mdss_dsi_cmdlist_get(struct mdss_dsi_ctrl_pdata *ctrl)
-{
-	struct dcs_cmd_list *clist;
-	struct dcs_cmd_req *req = NULL;
-
-	clist = &ctrl->cmdlist;
-	if (clist->get != clist->put) {
-		req = &clist->list[clist->get];
-		clist->get++;
-		clist->get %= CMD_REQ_MAX;
-		clist->tot--;
-		pr_debug("%s: tot=%d put=%d get=%d\n", __func__,
-		clist->tot, clist->put, clist->get);
-	}
-	return req;
-}
-
-int mdss_dsi_cmdlist_put(struct mdss_dsi_ctrl_pdata *ctrl,
-				struct dcs_cmd_req *cmdreq)
-{
-	struct dcs_cmd_req *req;
-	struct dcs_cmd_list *clist;
-	int ret = 0;
-
-	mutex_lock(&ctrl->cmd_mutex);
-	clist = &ctrl->cmdlist;
-	req = &clist->list[clist->put];
-	*req = *cmdreq;
-	clist->put++;
-	clist->put %= CMD_REQ_MAX;
-	clist->tot++;
-	if (clist->put == clist->get) {
-		/* drop the oldest one */
-		pr_debug("%s: DROP, tot=%d put=%d get=%d\n", __func__,
-			clist->tot, clist->put, clist->get);
-		clist->get++;
-		clist->get %= CMD_REQ_MAX;
-		clist->tot--;
-	}
-	mutex_unlock(&ctrl->cmd_mutex);
-
-	ret++;
-	pr_debug("%s: tot=%d put=%d get=%d\n", __func__,
-		clist->tot, clist->put, clist->get);
-
-	if (req->flags & CMD_REQ_COMMIT)
-		mdss_dsi_cmdlist_commit(ctrl, 0);
-
-	return ret;
-}
-
-
 static void dsi_send_events(struct mdss_dsi_ctrl_pdata *ctrl, u32 events)
 {
 	struct dsi_event_q *evq;
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index c15c02b..5408bc3 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -1172,7 +1172,6 @@
 			pr_err("unable to start display thread %d\n",
 				mfd->index);
 			result = PTR_ERR(mfd->disp_thread);
-			mfd->disp_thread = NULL;
 			goto thread_error;
 		}
 
@@ -1192,7 +1191,6 @@
 
 blank_error:
 	kthread_stop(mfd->disp_thread);
-	mfd->disp_thread = NULL;
 
 thread_error:
 	if (pinfo && !pinfo->ref_cnt) {
@@ -1244,10 +1242,8 @@
 			pm_runtime_put(info->dev);
 		} while (release_all && pinfo->ref_cnt);
 
-		if (release_all && mfd->disp_thread) {
+		if (release_all)
 			kthread_stop(mfd->disp_thread);
-			mfd->disp_thread = NULL;
-		}
 
 		if (pinfo->ref_cnt == 0) {
 			list_del(&pinfo->list);
@@ -1285,10 +1281,7 @@
 	}
 
 	if (!mfd->ref_cnt) {
-		if (mfd->disp_thread) {
-			kthread_stop(mfd->disp_thread);
-			mfd->disp_thread = NULL;
-		}
+		kthread_stop(mfd->disp_thread);
 
 		ret = mdss_fb_blank_sub(FB_BLANK_POWERDOWN, info,
 			mfd->op_enable);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 87b7526..4a51987 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -63,8 +63,11 @@
 
 /* Supported HDMI Audio channels */
 #define MSM_HDMI_AUDIO_CHANNEL_2	2
+#define MSM_HDMI_AUDIO_CHANNEL_3	3
 #define MSM_HDMI_AUDIO_CHANNEL_4	4
+#define MSM_HDMI_AUDIO_CHANNEL_5	5
 #define MSM_HDMI_AUDIO_CHANNEL_6	6
+#define MSM_HDMI_AUDIO_CHANNEL_7	7
 #define MSM_HDMI_AUDIO_CHANNEL_8	8
 
 enum msm_hdmi_supported_audio_sample_rates {
@@ -2051,12 +2054,15 @@
 		switch (num_of_channels) {
 		case MSM_HDMI_AUDIO_CHANNEL_2:
 			break;
+		case MSM_HDMI_AUDIO_CHANNEL_3:
 		case MSM_HDMI_AUDIO_CHANNEL_4:
 			channel_count = 3;
 			break;
+		case MSM_HDMI_AUDIO_CHANNEL_5:
 		case MSM_HDMI_AUDIO_CHANNEL_6:
 			channel_count = 5;
 			break;
+		case MSM_HDMI_AUDIO_CHANNEL_7:
 		case MSM_HDMI_AUDIO_CHANNEL_8:
 			channel_count = 7;
 			break;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 8dc6c56..0448063 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -1551,6 +1551,8 @@
 									ret);
 		goto exit;
 	}
+	if (mdata->nad_cfgs == 0)
+		valid_mixers = false;
 	for (i = 0; i < mixer_cnt && valid_mixers; i++) {
 		if (mixer_id[i] > mdata->nad_cfgs)
 			valid_mixers = false;
diff --git a/include/media/msm_vidc.h b/include/media/msm_vidc.h
index ef7d118..bc85ebb 100644
--- a/include/media/msm_vidc.h
+++ b/include/media/msm_vidc.h
@@ -18,6 +18,41 @@
 	MSM_VIDC_MAX_DEVICES,
 };
 
+/* NOTE: if you change this enum you MUST update the
+ * "buffer-type-tz-usage-table" for any affected target
+ * in arch/arm/boot/dts/<arch>.dtsi
+ */
+enum hal_buffer {
+	HAL_BUFFER_INPUT = 0x1,
+	HAL_BUFFER_OUTPUT = 0x2,
+	HAL_BUFFER_OUTPUT2 = 0x4,
+	HAL_BUFFER_EXTRADATA_INPUT = 0x8,
+	HAL_BUFFER_EXTRADATA_OUTPUT = 0x10,
+	HAL_BUFFER_EXTRADATA_OUTPUT2 = 0x20,
+	HAL_BUFFER_INTERNAL_SCRATCH = 0x40,
+	HAL_BUFFER_INTERNAL_SCRATCH_1 = 0x80,
+	HAL_BUFFER_INTERNAL_SCRATCH_2 = 0x100,
+	HAL_BUFFER_INTERNAL_PERSIST = 0x200,
+	HAL_BUFFER_INTERNAL_PERSIST_1 = 0x400,
+	HAL_BUFFER_INTERNAL_CMD_QUEUE = 0x800,
+};
+
+struct msm_smem {
+	int mem_type;
+	size_t size;
+	void *kvaddr;
+	unsigned long device_addr;
+	u32 flags;
+	void *smem_priv;
+	enum hal_buffer buffer_type;
+};
+
+enum smem_cache_ops {
+	SMEM_CACHE_CLEAN,
+	SMEM_CACHE_INVALIDATE,
+	SMEM_CACHE_CLEAN_INVALIDATE,
+};
+
 void *msm_vidc_open(int core_id, int session_type);
 int msm_vidc_close(void *instance);
 int msm_vidc_querycap(void *instance, struct v4l2_capability *cap);
@@ -47,6 +82,18 @@
 int msm_vidc_wait(void *instance);
 int msm_vidc_s_parm(void *instance, struct v4l2_streamparm *a);
 int msm_vidc_enum_framesizes(void *instance, struct v4l2_frmsizeenum *fsize);
+struct msm_smem *msm_vidc_smem_alloc(void *instance,
+			size_t size, u32 align, u32 flags,
+			enum hal_buffer buffer_type, int map_kernel);
+void msm_vidc_smem_free(void *instance, struct msm_smem *mem);
+int msm_vidc_smem_cache_operations(void *instance,
+		struct msm_smem *mem, enum smem_cache_ops);
+struct msm_smem *msm_vidc_smem_user_to_kernel(void *instance,
+			int fd, u32 offset, enum hal_buffer buffer_type);
+int msm_vidc_smem_get_domain_partition(void *instance,
+		u32 flags, enum hal_buffer buffer_type,
+		int *domain_num, int *partition_num);
+void *msm_vidc_smem_get_client(void *instance);
 #endif
 struct msm_vidc_interlace_payload {
 	unsigned int format;
diff --git a/lib/idr.c b/lib/idr.c
index 4046e29..e90d2d0 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -625,7 +625,14 @@
 			return p;
 		}
 
-		id += 1 << n;
+		/*
+		 * Proceed to the next layer at the current level.  Unlike
+		 * idr_for_each(), @id isn't guaranteed to be aligned to
+		 * layer boundary at this point and adding 1 << n may
+		 * incorrectly skip IDs.  Make sure we jump to the
+		 * beginning of the next layer using round_up().
+		 */
+		id = round_up(id + 1, 1 << n);
 		while (n < fls(id)) {
 			n += IDR_BITS;
 			p = *--paa;
diff --git a/sound/soc/codecs/msm_hdmi_codec_rx.c b/sound/soc/codecs/msm_hdmi_codec_rx.c
index e5d5c32..ae6bfbe 100644
--- a/sound/soc/codecs/msm_hdmi_codec_rx.c
+++ b/sound/soc/codecs/msm_hdmi_codec_rx.c
@@ -93,13 +93,26 @@
 	struct msm_hdmi_audio_codec_rx_data *codec_data =
 			dev_get_drvdata(dai->codec->dev);
 
+	/*refer to HDMI spec CEA-861-E: Table 28 Audio InfoFrame Data Byte 4*/
 	switch (num_channels) {
 	case 2:
 		channel_allocation  = 0;
 		break;
+	case 3:
+		channel_allocation  = 0x02;//default to FL/FR/FC
+		break;
+	case 4:
+		channel_allocation  = 0x06;//default to FL/FR/FC/RC
+		break;
+	case 5:
+		channel_allocation  = 0x0A;//default to FL/FR/FC/RR/RL
+		break;
 	case 6:
 		channel_allocation  = 0x0B;
 		break;
+	case 7:
+		channel_allocation  = 0x12;//default to FL/FR/FC/RL/RR/RRC/RLC
+		break;
 	case 8:
 		channel_allocation  = 0x13;
 		break;
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index caae9c6..6de310a 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -42,6 +42,8 @@
 #define TAPAN_HPH_PA_SETTLE_COMP_ON 3000
 #define TAPAN_HPH_PA_SETTLE_COMP_OFF 13000
 
+#define DAPM_MICBIAS2_EXTERNAL_STANDALONE "MIC BIAS2 External Standalone"
+
 #define TAPAN_VDD_CX_OPTIMAL_UA 10000
 #define TAPAN_VDD_CX_SLEEP_UA 2000
 
@@ -281,6 +283,8 @@
 	s32 dmic_1_2_clk_cnt;
 	s32 dmic_3_4_clk_cnt;
 	s32 dmic_5_6_clk_cnt;
+	s32 ldo_h_users;
+	s32 micb_2_users;
 
 	u32 anc_slot;
 	bool anc_func;
@@ -2146,38 +2150,37 @@
 {
 	struct snd_soc_codec *codec = w->codec;
 	struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
-	u16 micb_int_reg;
+	u16 micb_int_reg = 0, micb_ctl_reg = 0;
 	u8 cfilt_sel_val = 0;
 	char *internal1_text = "Internal1";
 	char *internal2_text = "Internal2";
 	char *internal3_text = "Internal3";
 	enum wcd9xxx_notify_event e_post_off, e_pre_on, e_post_on;
 
-	dev_dbg(codec->dev, "%s %d\n", __func__, event);
-	switch (w->reg) {
-	case TAPAN_A_MICB_1_CTL:
+	pr_debug("%s: w->name %s event %d\n", __func__, w->name, event);
+	if (strnstr(w->name, "MIC BIAS1", sizeof("MIC BIAS1"))) {
+		micb_ctl_reg = TAPAN_A_MICB_1_CTL;
 		micb_int_reg = TAPAN_A_MICB_1_INT_RBIAS;
 		cfilt_sel_val = tapan->resmgr.pdata->micbias.bias1_cfilt_sel;
 		e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_1_ON;
 		e_post_on = WCD9XXX_EVENT_POST_MICBIAS_1_ON;
 		e_post_off = WCD9XXX_EVENT_POST_MICBIAS_1_OFF;
-		break;
-	case TAPAN_A_MICB_2_CTL:
+	} else if (strnstr(w->name, "MIC BIAS2", sizeof("MIC BIAS2"))) {
+		micb_ctl_reg = TAPAN_A_MICB_2_CTL;
 		micb_int_reg = TAPAN_A_MICB_2_INT_RBIAS;
 		cfilt_sel_val = tapan->resmgr.pdata->micbias.bias2_cfilt_sel;
 		e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_2_ON;
 		e_post_on = WCD9XXX_EVENT_POST_MICBIAS_2_ON;
 		e_post_off = WCD9XXX_EVENT_POST_MICBIAS_2_OFF;
-		break;
-	case TAPAN_A_MICB_3_CTL:
+	} else if (strnstr(w->name, "MIC BIAS3", sizeof("MIC BIAS3"))) {
+		micb_ctl_reg = TAPAN_A_MICB_3_CTL;
 		micb_int_reg = TAPAN_A_MICB_3_INT_RBIAS;
 		cfilt_sel_val = tapan->resmgr.pdata->micbias.bias3_cfilt_sel;
 		e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_3_ON;
 		e_post_on = WCD9XXX_EVENT_POST_MICBIAS_3_ON;
 		e_post_off = WCD9XXX_EVENT_POST_MICBIAS_3_OFF;
-		break;
-	default:
-		pr_err("%s: Error, invalid micbias register\n", __func__);
+	} else {
+		pr_err("%s: Error, invalid micbias %s\n", __func__, w->name);
 		return -EINVAL;
 	}
 
@@ -2196,6 +2199,20 @@
 		else if (strnstr(w->name, internal3_text, 30))
 			snd_soc_update_bits(codec, micb_int_reg, 0x3, 0x3);
 
+		if (micb_ctl_reg == TAPAN_A_MICB_2_CTL) {
+			if (++tapan->micb_2_users == 1)
+				wcd9xxx_resmgr_add_cond_update_bits(
+						&tapan->resmgr,
+						WCD9XXX_COND_HPH_MIC,
+						micb_ctl_reg, w->shift,
+						false);
+			pr_debug("%s: micb_2_users %d\n", __func__,
+				 tapan->micb_2_users);
+		} else
+			snd_soc_update_bits(codec, micb_ctl_reg, 1 << w->shift,
+						1 << w->shift);
+
+
 		break;
 	case SND_SOC_DAPM_POST_PMU:
 		usleep_range(20000, 20000);
@@ -2203,6 +2220,22 @@
 		wcd9xxx_resmgr_notifier_call(&tapan->resmgr, e_post_on);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
+		if (micb_ctl_reg == TAPAN_A_MICB_2_CTL) {
+			if (--tapan->micb_2_users == 0)
+				wcd9xxx_resmgr_rm_cond_update_bits(
+						&tapan->resmgr,
+						WCD9XXX_COND_HPH_MIC,
+						micb_ctl_reg, 7,
+						false);
+			pr_debug("%s: micb_2_users %d\n", __func__,
+				 tapan->micb_2_users);
+			WARN(tapan->micb_2_users < 0,
+				"Unexpected micbias users %d\n",
+				tapan->micb_2_users);
+		} else
+			snd_soc_update_bits(codec, micb_ctl_reg, 1 << w->shift,
+					    0);
+
 		/* Let MBHC module know so micbias switch to be off */
 		wcd9xxx_resmgr_notifier_call(&tapan->resmgr, e_post_off);
 
@@ -2221,6 +2254,23 @@
 	return 0;
 }
 
+/* called under codec_resource_lock acquisition */
+static int tapan_enable_mbhc_micbias(struct snd_soc_codec *codec, bool enable)
+{
+	int rc;
+
+	if (enable)
+		rc = snd_soc_dapm_force_enable_pin(&codec->dapm,
+					     DAPM_MICBIAS2_EXTERNAL_STANDALONE);
+	else
+		rc = snd_soc_dapm_disable_pin(&codec->dapm,
+					     DAPM_MICBIAS2_EXTERNAL_STANDALONE);
+	if (!rc)
+		snd_soc_dapm_sync(&codec->dapm);
+	pr_debug("%s: leave ret %d\n", __func__, rc);
+	return rc;
+}
+
 static void tx_hpf_corner_freq_callback(struct work_struct *work)
 {
 	struct delayed_work *hpf_delayed_work;
@@ -2435,16 +2485,66 @@
 	return 0;
 }
 
+/* called under codec_resource_lock acquisition */
+static int __tapan_codec_enable_ldo_h(struct snd_soc_dapm_widget *w,
+				      struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct tapan_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+	pr_debug("%s: enter\n", __func__);
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/*
+		 * ldo_h_users is protected by codec->mutex, don't need
+		 * additional mutex
+		 */
+		if (++priv->ldo_h_users == 1) {
+			WCD9XXX_BG_CLK_LOCK(&priv->resmgr);
+			wcd9xxx_resmgr_get_bandgap(&priv->resmgr,
+						   WCD9XXX_BANDGAP_AUDIO_MODE);
+			wcd9xxx_resmgr_get_clk_block(&priv->resmgr,
+						     WCD9XXX_CLK_RCO);
+			snd_soc_update_bits(codec, TAPAN_A_LDO_H_MODE_1, 1 << 7,
+					    1 << 7);
+			wcd9xxx_resmgr_put_clk_block(&priv->resmgr,
+						     WCD9XXX_CLK_RCO);
+			WCD9XXX_BG_CLK_UNLOCK(&priv->resmgr);
+			pr_debug("%s: ldo_h_users %d\n", __func__,
+				 priv->ldo_h_users);
+			/* LDO enable requires 1ms to settle down */
+			usleep_range(1000, 1010);
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (--priv->ldo_h_users == 0) {
+			WCD9XXX_BG_CLK_LOCK(&priv->resmgr);
+			wcd9xxx_resmgr_get_clk_block(&priv->resmgr,
+						     WCD9XXX_CLK_RCO);
+			snd_soc_update_bits(codec, TAPAN_A_LDO_H_MODE_1, 1 << 7,
+					    0);
+			wcd9xxx_resmgr_put_clk_block(&priv->resmgr,
+						     WCD9XXX_CLK_RCO);
+			wcd9xxx_resmgr_put_bandgap(&priv->resmgr,
+						   WCD9XXX_BANDGAP_AUDIO_MODE);
+			WCD9XXX_BG_CLK_UNLOCK(&priv->resmgr);
+			pr_debug("%s: ldo_h_users %d\n", __func__,
+				 priv->ldo_h_users);
+		}
+		WARN(priv->ldo_h_users < 0, "Unexpected ldo_h users %d\n",
+		     priv->ldo_h_users);
+		break;
+	}
+	pr_debug("%s: leave\n", __func__);
+	return 0;
+}
+
 static int tapan_codec_enable_ldo_h(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
-	switch (event) {
-	case SND_SOC_DAPM_POST_PMU:
-	case SND_SOC_DAPM_POST_PMD:
-		usleep_range(1000, 1000);
-		break;
-	}
-	return 0;
+	int rc;
+	rc = __tapan_codec_enable_ldo_h(w, kcontrol, event);
+	return rc;
 }
 
 static int tapan_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
@@ -3017,6 +3117,7 @@
 	{"MIC BIAS2 Internal2", NULL, "LDO_H"},
 	{"MIC BIAS2 Internal3", NULL, "LDO_H"},
 	{"MIC BIAS2 External", NULL, "LDO_H"},
+	{DAPM_MICBIAS2_EXTERNAL_STANDALONE, NULL, "LDO_H Standalone"},
 };
 
 static const struct snd_soc_dapm_route wcd9302_map[] = {
@@ -4233,13 +4334,13 @@
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 	SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
 
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", TAPAN_A_MICB_3_CTL, 7, 0,
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", SND_SOC_NOPM, 7, 0,
 		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", TAPAN_A_MICB_3_CTL, 7, 0,
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", SND_SOC_NOPM, 7, 0,
 		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", TAPAN_A_MICB_3_CTL, 7, 0,
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", SND_SOC_NOPM, 7, 0,
 		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
@@ -4462,17 +4563,27 @@
 		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
 		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 
-	SND_SOC_DAPM_SUPPLY("LDO_H", TAPAN_A_LDO_H_MODE_1, 7, 0,
-		tapan_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU),
+	SND_SOC_DAPM_SUPPLY("LDO_H", SND_SOC_NOPM, 7, 0,
+		tapan_codec_enable_ldo_h,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/*
+	 * DAPM 'LDO_H Standalone' is to be powered by mbhc driver after
+	 * acquring codec_resource lock.
+	 * So call __tapan_codec_enable_ldo_h instead and avoid deadlock.
+	 */
+	SND_SOC_DAPM_SUPPLY("LDO_H Standalone", SND_SOC_NOPM, 7, 0,
+			    __tapan_codec_enable_ldo_h,
+			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_INPUT("AMIC1"),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TAPAN_A_MICB_1_CTL, 7, 0,
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", SND_SOC_NOPM, 7, 0,
 		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", TAPAN_A_MICB_1_CTL, 7, 0,
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", SND_SOC_NOPM, 7, 0,
 		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", TAPAN_A_MICB_1_CTL, 7, 0,
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", SND_SOC_NOPM, 7, 0,
 		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
@@ -4494,19 +4605,24 @@
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_INPUT("AMIC2"),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", TAPAN_A_MICB_2_CTL, 7, 0,
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", SND_SOC_NOPM, 7, 0,
 		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU |	SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", TAPAN_A_MICB_2_CTL, 7, 0,
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", SND_SOC_NOPM, 7, 0,
 		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", TAPAN_A_MICB_2_CTL, 7, 0,
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", SND_SOC_NOPM, 7, 0,
 		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", TAPAN_A_MICB_2_CTL, 7, 0,
+	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", SND_SOC_NOPM, 7, 0,
 		tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
+	SND_SOC_DAPM_MICBIAS_E(DAPM_MICBIAS2_EXTERNAL_STANDALONE, SND_SOC_NOPM,
+			       7, 0, tapan_codec_enable_micbias,
+			       SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+			       SND_SOC_DAPM_POST_PMD),
+
 	SND_SOC_DAPM_AIF_OUT_E("AIF1 CAP", "AIF1 Capture", 0, SND_SOC_NOPM,
 		AIF1_CAP, 0, tapan_codec_enable_slimtx,
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
@@ -5504,7 +5620,8 @@
 	else
 		rco_clk_rate = TAPAN_MCLK_CLK_9P6MHZ;
 
-	ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, NULL,
+	ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec,
+				tapan_enable_mbhc_micbias,
 				&mbhc_cb, &cdc_intr_ids, rco_clk_rate,
 				TAPAN_CDC_ZDET_SUPPORTED);
 	if (ret)
@@ -5711,7 +5828,8 @@
 	else
 		rco_clk_rate = TAPAN_MCLK_CLK_9P6MHZ;
 
-	ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec, NULL,
+	ret = wcd9xxx_mbhc_init(&tapan->mbhc, &tapan->resmgr, codec,
+				tapan_enable_mbhc_micbias,
 				&mbhc_cb, &cdc_intr_ids, rco_clk_rate,
 				TAPAN_CDC_ZDET_SUPPORTED);
 
@@ -5729,6 +5847,8 @@
 	tapan->aux_pga_cnt = 0;
 	tapan->aux_l_gain = 0x1F;
 	tapan->aux_r_gain = 0x1F;
+	tapan->ldo_h_users = 0;
+	tapan->micb_2_users = 0;
 	tapan_update_reg_defaults(codec);
 	tapan_update_reg_mclk_rate(wcd9xxx);
 	tapan_codec_init_reg(codec);
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index 61ae859..28d4c84 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -3746,6 +3746,7 @@
 	gain = wcd9xxx_mbhc_cal_btn_det_mp(btn_det, MBHC_BTN_DET_GAIN);
 	snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B2_CTL, 0x78,
 			    gain[idx] << 3);
+	snd_soc_update_bits(codec, WCD9XXX_A_MICB_2_MBHC, 0x04, 0x04);
 
 	pr_debug("%s: leave\n", __func__);
 }
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
index 0cf044c..9de15d9 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
@@ -129,13 +129,26 @@
 		break;
 	}
 
+	/*refer to HDMI spec CEA-861-E: Table 28 Audio InfoFrame Data Byte 4*/
 	switch (dai_data->channels) {
 	case 2:
 		dai_data->port_config.hdmi_multi_ch.channel_allocation = 0;
 		break;
+	case 3:
+		dai_data->port_config.hdmi_multi_ch.channel_allocation = 0x02;
+		break;
+	case 4:
+		dai_data->port_config.hdmi_multi_ch.channel_allocation = 0x06;
+		break;
+	case 5:
+		dai_data->port_config.hdmi_multi_ch.channel_allocation = 0x0A;
+		break;
 	case 6:
 		dai_data->port_config.hdmi_multi_ch.channel_allocation = 0x0B;
 		break;
+	case 7:
+		dai_data->port_config.hdmi_multi_ch.channel_allocation = 0x12;
+		break;
 	case 8:
 		dai_data->port_config.hdmi_multi_ch.channel_allocation = 0x13;
 		break;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 121c2ea..8a9a877 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -3354,6 +3354,9 @@
 	{"QUAT_MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
 	{"QUAT_MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
 	{"QUAT_MI2S_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+	{"QUAT_MI2S_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
+	{"QUAT_MI2S_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
+	{"QUAT_MI2S_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
 	{"QUAT_MI2S_RX", NULL, "QUAT_MI2S_RX Audio Mixer"},
 
 	{"TERT_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index 3ee6f6e..6cb7ce1 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -1160,10 +1160,10 @@
 		} else if (channel_mode == 6) {
 			open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
 			open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
-			open.dev_channel_mapping[2] = PCM_CHANNEL_FC;
-			open.dev_channel_mapping[3] = PCM_CHANNEL_LFE;
-			open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
-			open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
+			open.dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+			open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
+			open.dev_channel_mapping[4] = PCM_CHANNEL_LS;
+			open.dev_channel_mapping[5] = PCM_CHANNEL_RS;
 		} else if (channel_mode == 8) {
 			open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
 			open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
@@ -1171,8 +1171,8 @@
 			open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
 			open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
 			open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
-			open.dev_channel_mapping[6] = PCM_CHANNEL_RLC;
-			open.dev_channel_mapping[7] = PCM_CHANNEL_RRC;
+			open.dev_channel_mapping[6] = PCM_CHANNEL_FLC;
+			open.dev_channel_mapping[7] = PCM_CHANNEL_FRC;
 		} else {
 			pr_err("%s invalid num_chan %d\n", __func__,
 					channel_mode);
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index d9353c2..95114e0 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -2276,21 +2276,21 @@
 		lchannel_mapping[3] = PCM_CHANNEL_LB;
 		lchannel_mapping[4] = PCM_CHANNEL_RB;
 	} else if (channels == 6) {
-		lchannel_mapping[0] = PCM_CHANNEL_FC;
-		lchannel_mapping[1] = PCM_CHANNEL_FL;
-		lchannel_mapping[2] = PCM_CHANNEL_FR;
-		lchannel_mapping[3] = PCM_CHANNEL_LB;
-		lchannel_mapping[4] = PCM_CHANNEL_RB;
-		lchannel_mapping[5] = PCM_CHANNEL_LFE;
+		lchannel_mapping[0] = PCM_CHANNEL_FL;
+		lchannel_mapping[1] = PCM_CHANNEL_FR;
+		lchannel_mapping[2] = PCM_CHANNEL_FC;
+		lchannel_mapping[3] = PCM_CHANNEL_LFE;
+		lchannel_mapping[4] = PCM_CHANNEL_LS;
+		lchannel_mapping[5] = PCM_CHANNEL_RS;
 	} else if (channels == 8) {
 		lchannel_mapping[0] = PCM_CHANNEL_FL;
 		lchannel_mapping[1] = PCM_CHANNEL_FR;
-		lchannel_mapping[2] = PCM_CHANNEL_LFE;
-		lchannel_mapping[3] = PCM_CHANNEL_FC;
+		lchannel_mapping[2] = PCM_CHANNEL_FC;
+		lchannel_mapping[3] = PCM_CHANNEL_LFE;
 		lchannel_mapping[4] = PCM_CHANNEL_LB;
 		lchannel_mapping[5] = PCM_CHANNEL_RB;
-		lchannel_mapping[6] = PCM_CHANNEL_RLC;
-		lchannel_mapping[7] = PCM_CHANNEL_RRC;
+		lchannel_mapping[6] = PCM_CHANNEL_FLC;
+		lchannel_mapping[7] = PCM_CHANNEL_FRC;
 	} else {
 		pr_err("%s: ERROR.unsupported num_ch = %u\n",
 		 __func__, channels);