Merge changes I90c121b2,I6d994720 into msm-3.0

* changes:
  msm: kgsl: Change the base virtual address of MMU
  msm: kgsl: Return the correct value of pagetable base address for IOMMU
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index ceae29c..df041f0 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -2139,6 +2139,7 @@
 	&apq_cpudai_slimbus_1_rx,
 	&apq_cpudai_slimbus_1_tx,
 	&apq_cpudai_slimbus_2_tx,
+	&apq_cpudai_slimbus_3_rx,
 	&apq8064_rpm_device,
 	&apq8064_rpm_log_device,
 	&apq8064_rpm_stat_device,
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 9ada0dd..2c533d9 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -582,6 +582,11 @@
 	.id = 0x4005,
 };
 
+struct platform_device apq_cpudai_slimbus_3_rx = {
+	.name = "msm-dai-q6",
+	.id = 0x4006,
+};
+
 static struct resource resources_ssbi_pmic1[] = {
 	{
 		.start  = MSM_PMIC1_SSBI_CMD_PHYS,
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 6a56c04..31142c1 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -264,6 +264,7 @@
 extern struct platform_device apq_cpudai_slimbus_1_rx;
 extern struct platform_device apq_cpudai_slimbus_1_tx;
 extern struct platform_device apq_cpudai_slimbus_2_tx;
+extern struct platform_device apq_cpudai_slimbus_3_rx;
 extern struct platform_device apq_cpudai_slim_4_rx;
 extern struct platform_device apq_cpudai_slim_4_tx;
 
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index c888815..0eabd1b 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -214,9 +214,9 @@
 		global*global_timer_offset;
 
 	if (!(clock->flags & MSM_CLOCK_FLAGS_UNSTABLE_COUNT))
-		return __raw_readl(addr);
+		return __raw_readl_no_log(addr);
 
-	t1 = __raw_readl(addr);
+	t1 = __raw_readl_no_log(addr);
 	t2 = __raw_readl_no_log(addr);
 	if ((t2-t1) <= 1)
 		return t2;
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
index e643def..c04ece2 100644
--- a/drivers/media/video/msm/csi/msm_csid.c
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -211,10 +211,11 @@
 
 	init_completion(&csid_dev->reset_complete);
 
-	enable_irq(csid_dev->irq->start);
+	rc = request_irq(csid_dev->irq->start, msm_csid_irq,
+		IRQF_TRIGGER_RISING, "csid", csid_dev);
 
 	msm_csid_reset(csid_dev);
-	return 0;
+	return rc;
 
 clk_enable_failed:
 	msm_camera_enable_vreg(&csid_dev->pdev->dev, csid_vreg_info,
@@ -230,10 +231,15 @@
 
 static int msm_csid_release(struct v4l2_subdev *sd)
 {
+	uint32_t irq;
 	struct csid_device *csid_dev;
 	csid_dev = v4l2_get_subdevdata(sd);
 
-	disable_irq(csid_dev->irq->start);
+	irq = msm_camera_io_r(csid_dev->base + CSID_IRQ_STATUS_ADDR);
+	msm_camera_io_w(irq, csid_dev->base + CSID_IRQ_CLEAR_CMD_ADDR);
+	msm_camera_io_w(0, csid_dev->base + CSID_IRQ_MASK_ADDR);
+
+	free_irq(csid_dev->irq->start, csid_dev);
 
 	msm_cam_clk_enable(&csid_dev->pdev->dev, csid_clk_info,
 		csid_dev->csid_clk, ARRAY_SIZE(csid_clk_info), 0);
@@ -328,17 +334,6 @@
 		goto csid_no_resource;
 	}
 
-	rc = request_irq(new_csid_dev->irq->start, msm_csid_irq,
-		IRQF_TRIGGER_RISING, "csid", new_csid_dev);
-	if (rc < 0) {
-		release_mem_region(new_csid_dev->mem->start,
-			resource_size(new_csid_dev->mem));
-		pr_err("%s: irq request fail\n", __func__);
-		rc = -EBUSY;
-		goto csid_no_resource;
-	}
-	disable_irq(new_csid_dev->irq->start);
-
 	new_csid_dev->pdev = pdev;
 	msm_cam_register_subdev_node(&new_csid_dev->subdev, CSID_DEV, pdev->id);
 	return 0;
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 254cf3a..8720d70 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -1568,6 +1568,7 @@
 	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	struct msm_cam_media_controller *pmctl = NULL;
+	struct msm_cam_server_queue *queue = NULL;
 
 	D("%s\n", __func__);
 
@@ -1609,12 +1610,11 @@
 			pcam->vnode_id, pcam->use_count);
 	pcam->use_count++;
 	if (pcam->use_count == 1) {
-		struct msm_cam_server_queue *queue;
 		pcam->server_queue_idx = server_q_idx;
 		queue = &g_server_dev.server_queue[server_q_idx];
 		queue->ctrl = NULL;
 		queue->ctrl_data = kzalloc(sizeof(uint8_t) *
-				max_control_command_size, GFP_KERNEL);
+			max_control_command_size, GFP_KERNEL);
 		msm_queue_init(&queue->ctrl_q, "control");
 		msm_queue_init(&queue->eventData_q, "eventdata");
 		queue->queue_active = 1;
@@ -1623,7 +1623,7 @@
 		if (rc < 0) {
 			pr_err("%s: cam_server_open_session failed %d\n",
 			__func__, rc);
-			goto err;
+			goto msm_cam_server_open_session_failed;
 		}
 
 		pmctl = msm_camera_get_mctl(pcam->mctl_handle);
@@ -1636,26 +1636,26 @@
 
 		/* Should be set to sensor ops if any but right now its OK!! */
 		if (!pmctl->mctl_open) {
-			D("%s: media contoller is not inited\n",
-				 __func__);
+			D("%s: media contoller is not inited\n", __func__);
 			rc = -ENODEV;
-			goto err;
+			goto mctl_open_failed;
 		}
 
 		/* Now we really have to activate the camera */
 		D("%s: call mctl_open\n", __func__);
 		rc = pmctl->mctl_open(pmctl, MSM_APPS_ID_V4L2);
-
 		if (rc < 0) {
 			pr_err("%s: HW open failed rc = 0x%x\n",  __func__, rc);
-			goto err;
+			goto mctl_open_failed;
 		}
 		pmctl->pcam_ptr = pcam;
 
 		rc = msm_setup_v4l2_event_queue(&pcam_inst->eventHandle,
-							pcam->pvdev);
+			pcam->pvdev);
 		if (rc < 0) {
-			goto err;
+			pr_err("%s: msm_setup_v4l2_event_queue failed %d",
+				__func__, rc);
+			goto mctl_event_q_setup_failed;
 		}
 	}
 	pcam_inst->vbqueue_initialized = 0;
@@ -1666,21 +1666,26 @@
 	D("f->private_data = 0x%x, pcam = 0x%x\n",
 		(u32)f->private_data, (u32)pcam_inst);
 
-
 	if (pcam->use_count == 1) {
 		rc = msm_send_open_server(pcam);
 		if (rc < 0) {
-			mutex_unlock(&pcam->vid_lock);
-			pr_err("%s failed\n", __func__);
-			return rc;
+			pr_err("%s: msm_send_open_server failed %d\n",
+				__func__, rc);
+			goto msm_send_open_server_failed;
 		}
 	}
 	mutex_unlock(&pcam->vid_lock);
 	D("%s: end", __func__);
-	/* rc = msm_cam_server_open_session(g_server_dev, pcam);*/
 	return rc;
 
-err:
+msm_send_open_server_failed:
+	v4l2_fh_del(&pcam_inst->eventHandle);
+	v4l2_fh_exit(&pcam_inst->eventHandle);
+mctl_event_q_setup_failed:
+	if (pmctl->mctl_release)
+		if (pmctl->mctl_release(pmctl) < 0)
+			pr_err("%s: mctl_release failed\n", __func__);
+mctl_open_failed:
 	if (pcam->use_count == 1) {
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 		if (ion_client_created) {
@@ -1688,6 +1693,20 @@
 			kref_put(&pmctl->refcount, msm_release_ion_client);
 		}
 #endif
+		if (msm_cam_server_close_session(&g_server_dev, pcam) < 0)
+			pr_err("%s: msm_cam_server_close_session failed\n",
+				__func__);
+	}
+msm_cam_server_open_session_failed:
+	if (pcam->use_count == 1) {
+		queue->queue_active = 0;
+		msm_drain_eventq(&queue->eventData_q);
+		kfree(queue->ctrl_data);
+		queue->ctrl_data = NULL;
+		msm_queue_drain(&queue->ctrl_q, list_control);
+		msm_drain_eventq(&queue->eventData_q);
+		queue = NULL;
+
 		pcam->dev_inst[i] = NULL;
 		pcam->use_count = 0;
 	}
@@ -1909,16 +1928,18 @@
 	switch (cmd) {
 	case MSM_CAM_V4L2_IOCTL_GET_CAMERA_INFO:
 		if (copy_from_user(&temp_cam_info,
-				(void __user *)ioctl_ptr->ioctl_ptr,
-				sizeof(struct msm_camera_info))) {
+			(void __user *)ioctl_ptr->ioctl_ptr,
+			sizeof(struct msm_camera_info))) {
 			rc = -EINVAL;
 			return rc;
 		}
 		for (i = 0; i < g_server_dev.camera_info.num_cameras; i++) {
 			if (copy_to_user((void __user *)
-			temp_cam_info.video_dev_name[i],
-			 g_server_dev.camera_info.video_dev_name[i],
-			strlen(g_server_dev.camera_info.video_dev_name[i]))) {
+				temp_cam_info.video_dev_name[i],
+				g_server_dev.camera_info.video_dev_name[i],
+				strnlen(
+				g_server_dev.camera_info.video_dev_name[i],
+				MAX_DEV_NAME_LEN))) {
 				rc = -EINVAL;
 				return rc;
 			}
@@ -2059,6 +2080,7 @@
 		break;
 	}
 	default:
+		pr_err("%s: Invalid IOCTL = %d", __func__, cmd);
 		break;
 	}
 	return rc;
@@ -2152,7 +2174,7 @@
 	D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
 
 	switch (cmd) {
-		/* memory management shall be handeld here*/
+	/* memory management shall be handeld here*/
 	case MSM_CAM_IOCTL_REGISTER_PMEM:
 		return msm_register_pmem(
 			&config_cam->p_mctl->stats_info.pmem_stats_list,
@@ -2164,31 +2186,38 @@
 			&config_cam->p_mctl->stats_info.pmem_stats_list,
 			(void __user *)arg, config_cam->p_mctl->client);
 		break;
+
 	case VIDIOC_SUBSCRIBE_EVENT:
 		if (copy_from_user(&temp_sub,
 			(void __user *)arg,
 			sizeof(struct v4l2_event_subscription))) {
-				rc = -EINVAL;
-				return rc;
+			rc = -EINVAL;
+			return rc;
 		}
 		rc = msm_server_v4l2_subscribe_event
 			(&config_cam->config_stat_event_queue.eventHandle,
-				 &temp_sub);
-		if (rc < 0)
+			&temp_sub);
+		if (rc < 0) {
+			pr_err("%s: cam_v4l2_subscribe_event failed rc=%d\n",
+				__func__, rc);
 			return rc;
+		}
 		break;
 
 	case VIDIOC_UNSUBSCRIBE_EVENT:
 		if (copy_from_user(&temp_sub, (void __user *)arg,
-			  sizeof(struct v4l2_event_subscription))) {
+			sizeof(struct v4l2_event_subscription))) {
 			rc = -EINVAL;
 			return rc;
 		}
 		rc = msm_server_v4l2_unsubscribe_event
 			(&config_cam->config_stat_event_queue.eventHandle,
-			 &temp_sub);
-		if (rc < 0)
+			&temp_sub);
+		if (rc < 0) {
+			pr_err("%s: server_unsubscribe_event failed rc=%d\n",
+				__func__, rc);
 			return rc;
+		}
 		break;
 
 	case VIDIOC_DQEVENT: {
@@ -2334,8 +2363,8 @@
 static int msm_open_config(struct inode *inode, struct file *fp)
 {
 	int rc;
-	struct msm_cam_config_dev *config_cam =
-	container_of(inode->i_cdev, struct msm_cam_config_dev, config_cdev);
+	struct msm_cam_config_dev *config_cam = container_of(inode->i_cdev,
+		struct msm_cam_config_dev, config_cdev);
 
 	D("%s: open %s\n", __func__, fp->f_path.dentry->d_name.name);
 
@@ -2404,7 +2433,7 @@
 };
 
 int msm_setup_v4l2_event_queue(struct v4l2_fh *eventHandle,
-					struct video_device *pvdev)
+	struct video_device *pvdev)
 {
 	int rc = 0;
 	/* v4l2_fh support */
@@ -2414,6 +2443,7 @@
 	rc = v4l2_fh_init(eventHandle, pvdev);
 	if (rc < 0)
 		return rc;
+
 	if (eventHandle->events == NULL) {
 		rc = v4l2_event_init(eventHandle);
 		if (rc < 0)
@@ -2427,7 +2457,6 @@
 
 	v4l2_fh_add(eventHandle);
 	return rc;
-
 }
 
 static int msm_setup_config_dev(int node, char *device_name)
@@ -2448,8 +2477,8 @@
 	D("%s\n", __func__);
 
 	devno = MKDEV(MAJOR(msm_devno), dev_num+1);
-	device_config = device_create(msm_class, NULL, devno, NULL,
-					"%s%d", device_name, dev_num);
+	device_config = device_create(msm_class, NULL, devno, NULL, "%s%d",
+		device_name, dev_num);
 
 	if (IS_ERR(device_config)) {
 		rc = PTR_ERR(device_config);
@@ -2457,8 +2486,7 @@
 		goto config_setup_fail;
 	}
 
-	cdev_init(&config_cam->config_cdev,
-			&msm_fops_config);
+	cdev_init(&config_cam->config_cdev, &msm_fops_config);
 	config_cam->config_cdev.owner = THIS_MODULE;
 
 	rc = cdev_add(&config_cam->config_cdev, devno, 1);
@@ -2467,12 +2495,12 @@
 		device_destroy(msm_class, devno);
 		goto config_setup_fail;
 	}
-	g_server_dev.config_info.config_dev_name[dev_num]
-		= dev_name(device_config);
+
+	g_server_dev.config_info.config_dev_name[dev_num] =
+		dev_name(device_config);
 	D("%s Connected config device %s\n", __func__,
 		g_server_dev.config_info.config_dev_name[dev_num]);
-	g_server_dev.config_info.config_dev_id[dev_num]
-		= dev_num;
+	g_server_dev.config_info.config_dev_id[dev_num] = dev_num;
 
 	config_cam->config_stat_event_queue.pvdev = video_device_alloc();
 	if (config_cam->config_stat_event_queue.pvdev == NULL) {
@@ -2485,6 +2513,7 @@
 		config_cam->config_stat_event_queue.pvdev);
 	if (rc < 0) {
 		pr_err("%s failed to initialize event queue\n", __func__);
+		video_device_release(config_cam->config_stat_event_queue.pvdev);
 		goto config_setup_fail;
 	}
 
@@ -2493,7 +2522,6 @@
 config_setup_fail:
 	kfree(config_cam);
 	return rc;
-
 }
 
 static void msm_cam_server_subdev_notify(struct v4l2_subdev *sd,
@@ -2697,13 +2725,13 @@
 	video_set_drvdata(g_server_dev.video_dev, &g_server_dev);
 
 	strlcpy(g_server_dev.media_dev.model, "qcamera",
-			sizeof(g_server_dev.media_dev.model));
+		sizeof(g_server_dev.media_dev.model));
 	g_server_dev.media_dev.dev = &pdev->dev;
 	rc = media_device_register(&g_server_dev.media_dev);
 	g_server_dev.v4l2_dev.mdev = &g_server_dev.media_dev;
 
 	rc = video_register_device(g_server_dev.video_dev,
-			VFL_TYPE_GRABBER, 100);
+		VFL_TYPE_GRABBER, 100);
 
 	mutex_init(&g_server_dev.server_lock);
 	mutex_init(&g_server_dev.server_queue_lock);
@@ -2719,8 +2747,11 @@
 		&g_server_dev.server_command_queue.eventHandle,
 		g_server_dev.server_command_queue.pvdev);
 
-	if (rc < 0)
+	if (rc < 0) {
 		pr_err("%s failed to initialize event queue\n", __func__);
+		video_device_release(g_server_dev.server_command_queue.pvdev);
+		return rc;
+	}
 
 	for (i = 0; i < MAX_NUM_ACTIVE_CAMERA; i++) {
 		struct msm_cam_server_queue *queue;
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 671dfd7..04e224c 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -244,7 +244,7 @@
 	struct v4l2_subdev *ispif_sdev; /* ispif sub device */
 	struct v4l2_subdev *gemini_sdev; /* gemini sub device */
 	struct v4l2_subdev *vpe_sdev; /* vpe sub device */
-	struct v4l2_subdev *axi_sdev; /* vpe sub device */
+	struct v4l2_subdev *axi_sdev; /* axi sub device */
 	struct v4l2_subdev *eeprom_sdev; /* eeprom sub device */
 
 	struct msm_isp_ops *isp_sdev;    /* isp sub device : camif/VFE */
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index d791771..e878063 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -583,23 +583,22 @@
 		if (rc < 0) {
 			pr_err("%s: msm_mctl_register_subdevs failed:%d\n",
 				__func__, rc);
-			goto msm_open_done;
+			goto register_sdev_failed;
 		}
 
-		/* then sensor - move sub dev later*/
+		/* then sensor - move sub dev later */
 		rc = v4l2_subdev_call(p_mctl->sensor_sdev, core, s_power, 1);
-
 		if (rc < 0) {
-			pr_err("%s: isp init failed: %d\n", __func__, rc);
-			goto msm_open_done;
+			pr_err("%s: sensor powerup failed: %d\n", __func__, rc);
+			goto sensor_sdev_failed;
 		}
+
 		if (p_mctl->act_sdev)
 			rc = v4l2_subdev_call(p_mctl->act_sdev,
-					core, s_power, 1);
-
+				core, s_power, 1);
 		if (rc < 0) {
 			pr_err("%s: act power failed:%d\n", __func__, rc);
-			goto msm_open_done;
+			goto act_power_up_failed;
 		}
 
 		if (camdev->is_csiphy) {
@@ -607,8 +606,8 @@
 				VIDIOC_MSM_CSIPHY_INIT, NULL);
 			if (rc < 0) {
 				pr_err("%s: csiphy initialization failed %d\n",
-				__func__, rc);
-				goto msm_open_done;
+					__func__, rc);
+				goto csiphy_init_failed;
 			}
 		}
 
@@ -617,17 +616,18 @@
 				VIDIOC_MSM_CSID_INIT, &csid_version);
 			if (rc < 0) {
 				pr_err("%s: csid initialization failed %d\n",
-				__func__, rc);
-				goto msm_open_done;
+					__func__, rc);
+				goto csid_init_failed;
 			}
 		}
+
 		if (camdev->is_csic) {
 			rc = v4l2_subdev_call(p_mctl->csic_sdev, core, ioctl,
 				VIDIOC_MSM_CSIC_INIT, &csid_version);
 			if (rc < 0) {
 				pr_err("%s: csic initialization failed %d\n",
-				__func__, rc);
-				goto msm_open_done;
+					__func__, rc);
+				goto csic_init_failed;
 			}
 		}
 
@@ -638,7 +638,7 @@
 			if (rc < 0) {
 				pr_err("%s: isp init failed: %d\n",
 					__func__, rc);
-				goto msm_open_done;
+				goto isp_open_failed;
 			}
 		}
 
@@ -646,9 +646,9 @@
 			rc = v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
 				VIDIOC_MSM_AXI_INIT, p_mctl);
 			if (rc < 0) {
-				pr_err("%s: vpe initialization failed %d\n",
-				__func__, rc);
-				goto msm_open_done;
+				pr_err("%s: axi initialization failed %d\n",
+					__func__, rc);
+				goto axi_init_failed;
 			}
 		}
 
@@ -658,7 +658,7 @@
 			if (rc < 0) {
 				pr_err("%s: vpe initialization failed %d\n",
 				__func__, rc);
-				goto msm_open_done;
+				goto vpe_init_failed;
 			}
 		}
 
@@ -667,23 +667,65 @@
 				VIDIOC_MSM_ISPIF_INIT, &csid_version);
 			if (rc < 0) {
 				pr_err("%s: ispif initialization failed %d\n",
-				__func__, rc);
-				goto msm_open_done;
+					__func__, rc);
+				goto ispif_init_failed;
 			}
 		}
 
 		if (camdev->is_ispif) {
 			pm_qos_add_request(&p_mctl->pm_qos_req_list,
-					PM_QOS_CPU_DMA_LATENCY,
-					PM_QOS_DEFAULT_VALUE);
+				PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
 			pm_qos_update_request(&p_mctl->pm_qos_req_list,
-					MSM_V4L2_SWFI_LATENCY);
+				MSM_V4L2_SWFI_LATENCY);
 		}
 		p_mctl->apps_id = apps_id;
 		p_mctl->opencnt++;
+	} else {
+		D("%s: camera is already open", __func__);
 	}
+	mutex_unlock(&p_mctl->lock);
 
-msm_open_done:
+	return rc;
+
+ispif_init_failed:
+	if (camdev->is_vpe)
+		if (v4l2_subdev_call(p_mctl->vpe_sdev, core, ioctl,
+			VIDIOC_MSM_VPE_RELEASE, NULL) < 0)
+			pr_err("%s: vpe release failed %d\n", __func__, rc);
+vpe_init_failed:
+	if (p_mctl->axi_sdev)
+		if (v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
+			VIDIOC_MSM_AXI_RELEASE, NULL) < 0)
+			pr_err("%s: axi release failed %d\n", __func__, rc);
+axi_init_failed:
+	if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_release)
+		p_mctl->isp_sdev->isp_release(p_mctl->isp_sdev->sd);
+isp_open_failed:
+	if (camdev->is_csic)
+		if (v4l2_subdev_call(p_mctl->csic_sdev, core, ioctl,
+			VIDIOC_MSM_CSIC_RELEASE, NULL) < 0)
+			pr_err("%s: csic release failed %d\n", __func__, rc);
+csic_init_failed:
+	if (camdev->is_csid)
+		if (v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
+			VIDIOC_MSM_CSID_RELEASE, NULL) < 0)
+			pr_err("%s: csid release failed %d\n", __func__, rc);
+csid_init_failed:
+	if (camdev->is_csiphy)
+		if (v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
+			VIDIOC_MSM_CSIPHY_RELEASE, NULL) < 0)
+			pr_err("%s: csiphy release failed %d\n", __func__, rc);
+csiphy_init_failed:
+	if (p_mctl->act_sdev)
+		if (v4l2_subdev_call(p_mctl->act_sdev, core,
+			s_power, 0) < 0)
+			pr_err("%s: act power down failed:%d\n", __func__, rc);
+act_power_up_failed:
+	if (v4l2_subdev_call(p_mctl->sensor_sdev, core, s_power, 0) < 0)
+		pr_err("%s: sensor powerdown failed: %d\n", __func__, rc);
+sensor_sdev_failed:
+register_sdev_failed:
+	wake_unlock(&p_mctl->wake_lock);
 	mutex_unlock(&p_mctl->lock);
 	return rc;
 }
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index e265b25..becdd95 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -4177,16 +4177,18 @@
 	switch (cmd) {
 	case VIDIOC_MSM_AXI_INIT:
 		rc = msm_axi_subdev_init(sd,
-				(struct msm_cam_media_controller *)arg);
+			(struct msm_cam_media_controller *)arg);
 		break;
 	case VIDIOC_MSM_AXI_CFG:
 		rc = msm_axi_config(sd, arg);
 		break;
 	case VIDIOC_MSM_AXI_IRQ:
 		msm_axi_process_irq(sd, arg);
+		rc = 0;
 		break;
 	case VIDIOC_MSM_AXI_RELEASE:
 		msm_axi_subdev_release(sd);
+		rc = 0;
 		break;
 	default:
 		pr_err("%s: command not found\n", __func__);
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index d4d07cd..ff5bb49 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -587,6 +587,7 @@
 		msm_sensor_enable_i2c_mux(data->sensor_platform_info->i2c_conf);
 
 	return rc;
+
 enable_clk_failed:
 		msm_camera_config_gpio_table(data, 0);
 config_gpio_failed:
@@ -643,13 +644,14 @@
 			s_ctrl->sensor_id_info->sensor_id_reg_addr, &chipid,
 			MSM_CAMERA_I2C_WORD_DATA);
 	if (rc < 0) {
-		CDBG("%s: read id failed\n", __func__);
+		pr_err("%s: %s: read id failed\n", __func__,
+			s_ctrl->sensordata->sensor_name);
 		return rc;
 	}
 
 	CDBG("msm_sensor id: %d\n", chipid);
 	if (chipid != s_ctrl->sensor_id_info->sensor_id) {
-		CDBG("msm_sensor_match_id chip id doesnot match\n");
+		pr_err("msm_sensor_match_id chip id doesnot match\n");
 		return -ENODEV;
 	}
 	return rc;
@@ -726,10 +728,30 @@
 	int rc = 0;
 	struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(sd);
 	mutex_lock(s_ctrl->msm_sensor_mutex);
-	if (on)
+	if (on) {
 		rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
-	else
+		if (rc < 0) {
+			pr_err("%s: %s power_up failed rc = %d\n", __func__,
+				s_ctrl->sensordata->sensor_name, rc);
+		} else {
+			if (s_ctrl->func_tbl->sensor_match_id)
+				rc = s_ctrl->func_tbl->sensor_match_id(s_ctrl);
+			else
+				rc = msm_sensor_match_id(s_ctrl);
+			if (rc < 0) {
+				pr_err("%s: %s match_id failed  rc=%d\n",
+					__func__,
+					s_ctrl->sensordata->sensor_name, rc);
+				if (s_ctrl->func_tbl->sensor_power_down(s_ctrl)
+					< 0)
+					pr_err("%s: %s power_down failed\n",
+					__func__,
+					s_ctrl->sensordata->sensor_name);
+			}
+		}
+	} else {
 		rc = s_ctrl->func_tbl->sensor_power_down(s_ctrl);
+	}
 	mutex_unlock(s_ctrl->msm_sensor_mutex);
 	return rc;
 }
diff --git a/drivers/mfd/pm8xxx-misc.c b/drivers/mfd/pm8xxx-misc.c
index a311029..080a87c 100644
--- a/drivers/mfd/pm8xxx-misc.c
+++ b/drivers/mfd/pm8xxx-misc.c
@@ -145,6 +145,11 @@
 #define MP3_1_SHIFT	5
 #define MP3_2_SHIFT	2
 
+#define REG_HSED_BIAS0_CNTL2		0xA1
+#define REG_HSED_BIAS1_CNTL2		0x135
+#define REG_HSED_BIAS2_CNTL2		0x138
+#define HSED_EN_MASK			0xC0
+
 struct pm8xxx_misc_chip {
 	struct list_head			link;
 	struct pm8xxx_misc_platform_data	pdata;
@@ -1100,6 +1105,52 @@
 }
 EXPORT_SYMBOL_GPL(pm8xxx_aux_clk_control);
 
+int pm8xxx_hsed_bias_control(enum pm8xxx_hsed_bias bias, bool enable)
+{
+	struct pm8xxx_misc_chip *chip;
+	unsigned long flags;
+	int rc = 0;
+	u16 addr;
+
+	switch (bias) {
+	case PM8XXX_HSED_BIAS0:
+		addr = REG_HSED_BIAS0_CNTL2;
+		break;
+	case PM8XXX_HSED_BIAS1:
+		addr = REG_HSED_BIAS1_CNTL2;
+		break;
+	case PM8XXX_HSED_BIAS2:
+		addr = REG_HSED_BIAS2_CNTL2;
+		break;
+	default:
+		pr_err("Invalid BIAS line\n");
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
+
+	/* Loop over all attached PMICs and call specific functions for them. */
+	list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
+		switch (chip->version) {
+		case PM8XXX_VERSION_8058:
+		case PM8XXX_VERSION_8921:
+			rc = pm8xxx_misc_masked_write(chip, addr,
+				HSED_EN_MASK, enable ? HSED_EN_MASK : 0);
+			if (rc < 0)
+				pr_err("Enable HSED BIAS failed rc=%d\n", rc);
+			break;
+		default:
+			/* Functionality not supported */
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
+
+	return rc;
+}
+EXPORT_SYMBOL(pm8xxx_hsed_bias_control);
+
 static int __devinit pm8xxx_misc_probe(struct platform_device *pdev)
 {
 	const struct pm8xxx_misc_platform_data *pdata = pdev->dev.platform_data;
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 0d6c5f1..73a31716 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -79,6 +79,9 @@
 static int  msmsdcc_dbg_init(void);
 #endif
 
+static int msmsdcc_prep_xfer(struct msmsdcc_host *host, struct mmc_data
+			     *data);
+
 static u64 dma_mask = DMA_BIT_MASK(32);
 static unsigned int msmsdcc_pwrsave = 1;
 
@@ -482,8 +485,9 @@
 		if (!mrq->data->error)
 			mrq->data->error = -EIO;
 	}
-	dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg, host->dma.num_ents,
-		     host->dma.dir);
+	if (!mrq->data->host_cookie)
+		dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg,
+			     host->dma.num_ents, host->dma.dir);
 
 	if (host->curr.user_pages) {
 		struct scatterlist *sg = host->dma.sg;
@@ -649,9 +653,9 @@
 	}
 
 	/* Unmap sg buffers */
-	dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg, host->sps.num_ents,
-			 host->sps.dir);
-
+	if (!mrq->data->host_cookie)
+		dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg,
+			     host->sps.num_ents, host->sps.dir);
 	host->sps.sg = NULL;
 	host->sps.busy = 0;
 
@@ -720,8 +724,9 @@
 		mrq->data->error = -EIO;
 
 	/* Unmap sg buffers */
-	dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg, host->sps.num_ents,
-			 host->sps.dir);
+	if (!mrq->data->host_cookie)
+		dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg,
+			     host->sps.num_ents, host->sps.dir);
 
 	host->sps.sg = NULL;
 	host->sps.busy = 0;
@@ -816,15 +821,13 @@
 	else
 		host->dma.dir = DMA_TO_DEVICE;
 
-	n = dma_map_sg(mmc_dev(host->mmc), host->dma.sg,
-			host->dma.num_ents, host->dma.dir);
-
-	if (n != host->dma.num_ents) {
-		pr_err("%s: Unable to map in all sg elements\n",
-		       mmc_hostname(host->mmc));
-		host->dma.sg = NULL;
-		host->dma.num_ents = 0;
-		return -ENOMEM;
+	if (!data->host_cookie) {
+		n = msmsdcc_prep_xfer(host, data);
+		if (unlikely(n < 0)) {
+			host->dma.sg = NULL;
+			host->dma.num_ents = 0;
+			return -ENOMEM;
+		}
 	}
 
 	/* host->curr.user_pages = (data->flags & MMC_DATA_USERPAGE); */
@@ -893,8 +896,9 @@
 
 unmap:
 	if (err) {
-		dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg,
-				host->dma.num_ents, host->dma.dir);
+		if (!data->host_cookie)
+			dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg,
+				     host->dma.num_ents, host->dma.dir);
 		pr_err("%s: cannot do DMA, fall back to PIO mode err=%d\n",
 				mmc_hostname(host->mmc), err);
 	}
@@ -902,6 +906,44 @@
 	return err;
 }
 
+static int msmsdcc_prep_xfer(struct msmsdcc_host *host,
+			     struct mmc_data *data)
+{
+	int rc = 0;
+	unsigned int dir;
+
+	/* Prevent memory corruption */
+	BUG_ON(data->sg_len > msmsdcc_get_nr_sg(host));
+
+	if (data->flags & MMC_DATA_READ)
+		dir = DMA_FROM_DEVICE;
+	else
+		dir = DMA_TO_DEVICE;
+
+	/* Make sg buffers DMA ready */
+	rc = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+			dir);
+
+	if (unlikely(rc != data->sg_len)) {
+		pr_err("%s: Unable to map in all sg elements, rc=%d\n",
+		       mmc_hostname(host->mmc), rc);
+		rc = -ENOMEM;
+		goto dma_map_err;
+	}
+
+	pr_debug("%s: %s: %s: sg_len=%d\n",
+		mmc_hostname(host->mmc), __func__,
+		dir == DMA_FROM_DEVICE ? "READ" : "WRITE",
+		data->sg_len);
+
+	goto out;
+
+dma_map_err:
+	dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+		     data->flags);
+out:
+	return rc;
+}
 #ifdef CONFIG_MMC_MSM_SPS_SUPPORT
 /**
  * Submits data transfer request to SPS driver
@@ -916,7 +958,7 @@
  * @return 0 if success else negative value
  */
 static int msmsdcc_sps_start_xfer(struct msmsdcc_host *host,
-				struct mmc_data *data)
+				  struct mmc_data *data)
 {
 	int rc = 0;
 	u32 flags;
@@ -925,9 +967,6 @@
 	struct scatterlist *sg = data->sg;
 	struct sps_pipe *sps_pipe_handle;
 
-	/* Prevent memory corruption */
-	BUG_ON(data->sg_len > msmsdcc_get_nr_sg(host));
-
 	host->sps.sg = data->sg;
 	host->sps.num_ents = data->sg_len;
 	host->sps.xfer_req_cnt = 0;
@@ -939,24 +978,15 @@
 		sps_pipe_handle = host->sps.cons.pipe_handle;
 	}
 
-	/* Make sg buffers DMA ready */
-	rc = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
-			host->sps.dir);
-
-	if (rc != data->sg_len) {
-		pr_err("%s: Unable to map in all sg elements, rc=%d\n",
-		       mmc_hostname(host->mmc), rc);
-		host->sps.sg = NULL;
-		host->sps.num_ents = 0;
-		rc = -ENOMEM;
-		goto dma_map_err;
+	if (!data->host_cookie) {
+		rc = msmsdcc_prep_xfer(host, data);
+		if (unlikely(rc < 0)) {
+			host->dma.sg = NULL;
+			host->dma.num_ents = 0;
+			goto out;
+		}
 	}
 
-	pr_debug("%s: %s: %s: pipe=0x%x, total_xfer=0x%x, sg_len=%d\n",
-		mmc_hostname(host->mmc), __func__,
-		host->sps.dir == DMA_FROM_DEVICE ? "READ" : "WRITE",
-		(u32)sps_pipe_handle, host->curr.xfer_size, data->sg_len);
-
 	for (i = 0; i < data->sg_len; i++) {
 		/*
 		 * Check if this is the last buffer to transfer?
@@ -993,8 +1023,9 @@
 
 dma_map_err:
 	/* unmap sg buffers */
-	dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg, host->sps.num_ents,
-			host->sps.dir);
+	if (!data->host_cookie)
+		dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg,
+			     host->sps.num_ents, host->sps.dir);
 out:
 	return rc;
 }
@@ -1833,6 +1864,63 @@
 }
 
 static void
+msmsdcc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
+		bool is_first_request)
+{
+	struct msmsdcc_host *host = mmc_priv(mmc);
+	struct mmc_data *data = mrq->data;
+	int rc = 0;
+
+	if (unlikely(!data)) {
+		pr_err("%s: %s cannot prepare null data\n", mmc_hostname(mmc),
+		       __func__);
+		return;
+	}
+	if (unlikely(data->host_cookie)) {
+		/* Very wrong */
+		data->host_cookie = 0;
+		pr_err("%s: %s Request reposted for prepare\n",
+		       mmc_hostname(mmc), __func__);
+		return;
+	}
+
+	if (!msmsdcc_is_dma_possible(host, data))
+		return;
+
+	rc = msmsdcc_prep_xfer(host, data);
+	if (unlikely(rc < 0)) {
+		data->host_cookie = 0;
+		return;
+	}
+
+	data->host_cookie = 1;
+}
+
+static void
+msmsdcc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, int err)
+{
+	struct msmsdcc_host *host = mmc_priv(mmc);
+	unsigned int dir;
+	struct mmc_data *data = mrq->data;
+
+	if (unlikely(!data)) {
+		pr_err("%s: %s cannot cleanup null data\n", mmc_hostname(mmc),
+		       __func__);
+		return;
+	}
+	if (data->flags & MMC_DATA_READ)
+		dir = DMA_FROM_DEVICE;
+	else
+		dir = DMA_TO_DEVICE;
+
+	if (data->host_cookie)
+		dma_unmap_sg(mmc_dev(host->mmc), data->sg,
+			     data->sg_len, dir);
+
+	data->host_cookie = 0;
+}
+
+static void
 msmsdcc_request_start(struct msmsdcc_host *host, struct mmc_request *mrq)
 {
 	if (mrq->data && mrq->data->flags & MMC_DATA_READ) {
@@ -3561,6 +3649,8 @@
 static const struct mmc_host_ops msmsdcc_ops = {
 	.enable		= msmsdcc_enable,
 	.disable	= msmsdcc_disable,
+	.pre_req        = msmsdcc_pre_req,
+	.post_req       = msmsdcc_post_req,
 	.request	= msmsdcc_request,
 	.set_ios	= msmsdcc_set_ios,
 	.get_ro		= msmsdcc_get_ro,
diff --git a/drivers/video/msm/mipi_toshiba.h b/drivers/video/msm/mipi_toshiba.h
index 632bbd3..4107161 100644
--- a/drivers/video/msm/mipi_toshiba.h
+++ b/drivers/video/msm/mipi_toshiba.h
@@ -21,9 +21,9 @@
 int mipi_toshiba_device_register(struct msm_panel_info *pinfo,
 					u32 channel, u32 panel);
 
-#define MIPI_TOSHIBA_PWM_FREQ_HZ 300
+#define MIPI_TOSHIBA_PWM_FREQ_HZ 3921
 #define MIPI_TOSHIBA_PWM_PERIOD_USEC (USEC_PER_SEC / MIPI_TOSHIBA_PWM_FREQ_HZ)
-#define MIPI_TOSHIBA_PWM_LEVEL 100
+#define MIPI_TOSHIBA_PWM_LEVEL 255
 #define MIPI_TOSHIBA_PWM_DUTY_LEVEL \
 	(MIPI_TOSHIBA_PWM_PERIOD_USEC / MIPI_TOSHIBA_PWM_LEVEL)
 
diff --git a/include/linux/mfd/pm8xxx/misc.h b/include/linux/mfd/pm8xxx/misc.h
index 77683ce..c4b0ea4 100644
--- a/include/linux/mfd/pm8xxx/misc.h
+++ b/include/linux/mfd/pm8xxx/misc.h
@@ -89,6 +89,12 @@
 	XO_DIV_64,
 };
 
+enum pm8xxx_hsed_bias {
+	PM8XXX_HSED_BIAS0,
+	PM8XXX_HSED_BIAS1,
+	PM8XXX_HSED_BIAS2,
+};
+
 #if defined(CONFIG_MFD_PM8XXX_MISC) || defined(CONFIG_MFD_PM8XXX_MISC_MODULE)
 
 /**
@@ -210,6 +216,14 @@
 				enum pm8xxx_aux_clk_div divider,
 				bool enable);
 
+/**
+ * pm8xxx_hsed_bias_control - Control the HSED_BIAS signal
+ * @bias: the bias line to be controlled (of the 3)
+ * @enable: enable/disable the bias line
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_hsed_bias_control(enum pm8xxx_hsed_bias bias, bool enable);
 #else
 
 static inline int pm8xxx_reset_pwr_off(int reset)
@@ -259,6 +273,11 @@
 {
 	return -ENODEV;
 }
+static inline int pm8xxx_hsed_bias_control(enum pm8xxx_hsed_bias bias,
+							bool enable)
+{
+	return -ENODEV;
+}
 
 #endif
 
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index b920a72..f13b52b 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1370,6 +1370,16 @@
 }
 #endif /* NET_SKBUFF_DATA_USES_OFFSET */
 
+static inline void skb_mac_header_rebuild(struct sk_buff *skb)
+{
+	if (skb_mac_header_was_set(skb)) {
+		const unsigned char *old_mac = skb_mac_header(skb);
+
+		skb_set_mac_header(skb, -skb->mac_len);
+		memmove(skb_mac_header(skb), old_mac, skb->mac_len);
+	}
+}
+
 static inline int skb_checksum_start_offset(const struct sk_buff *skb)
 {
 	return skb->csum_start - skb_headroom(skb);
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index 6341818..e3db3f9 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -110,10 +110,7 @@
 
 	skb_push(skb, sizeof(*iph));
 	skb_reset_network_header(skb);
-
-	memmove(skb->data - skb->mac_len, skb_mac_header(skb),
-		skb->mac_len);
-	skb_set_mac_header(skb, -skb->mac_len);
+	skb_mac_header_rebuild(skb);
 
 	xfrm4_beet_make_header(skb);
 
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index 534972e..ed4bf11 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -66,7 +66,6 @@
 
 static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
 {
-	const unsigned char *old_mac;
 	int err = -EINVAL;
 
 	if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP)
@@ -84,10 +83,9 @@
 	if (!(x->props.flags & XFRM_STATE_NOECN))
 		ipip_ecn_decapsulate(skb);
 
-	old_mac = skb_mac_header(skb);
-	skb_set_mac_header(skb, -skb->mac_len);
-	memmove(skb_mac_header(skb), old_mac, skb->mac_len);
 	skb_reset_network_header(skb);
+	skb_mac_header_rebuild(skb);
+
 	err = 0;
 
 out:
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
index 3437d7d..f37cba9 100644
--- a/net/ipv6/xfrm6_mode_beet.c
+++ b/net/ipv6/xfrm6_mode_beet.c
@@ -80,7 +80,6 @@
 static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb)
 {
 	struct ipv6hdr *ip6h;
-	const unsigned char *old_mac;
 	int size = sizeof(struct ipv6hdr);
 	int err;
 
@@ -90,10 +89,7 @@
 
 	__skb_push(skb, size);
 	skb_reset_network_header(skb);
-
-	old_mac = skb_mac_header(skb);
-	skb_set_mac_header(skb, -skb->mac_len);
-	memmove(skb_mac_header(skb), old_mac, skb->mac_len);
+	skb_mac_header_rebuild(skb);
 
 	xfrm6_beet_make_header(skb);
 
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index 4d6edff..23ecd68 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -63,7 +63,6 @@
 static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
 {
 	int err = -EINVAL;
-	const unsigned char *old_mac;
 
 	if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6)
 		goto out;
@@ -80,10 +79,9 @@
 	if (!(x->props.flags & XFRM_STATE_NOECN))
 		ipip6_ecn_decapsulate(skb);
 
-	old_mac = skb_mac_header(skb);
-	skb_set_mac_header(skb, -skb->mac_len);
-	memmove(skb_mac_header(skb), old_mac, skb->mac_len);
 	skb_reset_network_header(skb);
+	skb_mac_header_rebuild(skb);
+
 	err = 0;
 
 out:
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 4b6d83b..9041bd7 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -1498,7 +1498,7 @@
 	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
 	unsigned int cfilt;
 
-	switch (sitar->micbias) {
+	switch (sitar->mbhc_cfg.micbias) {
 	case SITAR_MICBIAS1:
 		cfilt = sitar->pdata->micbias.bias1_cfilt_sel;
 		micbias_regs->mbhc_reg = SITAR_A_MICB_1_MBHC;
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index b0244af..f8ddb0b 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -845,6 +845,13 @@
 			user_set_tx_ch =  msm_slim_0_tx_ch;
 		else if (codec_dai->id  == 4)
 			user_set_tx_ch =  params_channels(params);
+		else if (codec_dai->id == 5) {
+			/* DAI 5 is used for external EC reference from codec.
+			 * Since Rx is fed as reference for EC, the config of
+			 * this DAI is based on that of the Rx path.
+			 */
+			user_set_tx_ch =  msm_slim_0_rx_ch;
+		}
 
 		pr_debug("%s: %s_tx_dai_id_%d_ch=%d\n", __func__,
 			codec_dai->name, codec_dai->id, user_set_tx_ch);
@@ -1505,7 +1512,7 @@
 		.codec_name = "tabla_codec",
 		.codec_dai_name = "tabla_rx2",
 		.no_pcm = 1,
-		/* .be_id = do not care */
+		.be_id = MSM_BACKEND_DAI_EXTPROC_RX,
 		.be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
 		.init = &msm_stubrx_init,
 		.ops = &msm_be_ops,
@@ -1518,7 +1525,7 @@
 		.codec_name = "tabla_codec",
 		.codec_dai_name = "tabla_tx1",
 		.no_pcm = 1,
-		/* .be_id = do not care */
+		.be_id = MSM_BACKEND_DAI_EXTPROC_TX,
 		.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
 		.ops = &msm_be_ops,
 	},
@@ -1588,6 +1595,22 @@
 		.init = &msm_incall_rec_init,
 		.ops = &msm_slimbus_4_be_ops,
 	},
+	{
+		.name = LPASS_BE_STUB_1_TX,
+		.stream_name = "Stub1 Capture",
+		.cpu_dai_name = "msm-dai-stub",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "tabla_codec",
+		.codec_dai_name	= "tabla_tx3",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_EXTPROC_EC_TX,
+		/* This BE is used for external EC reference from codec. Since
+		 * Rx is fed as reference for EC, the config of this DAI is
+		 * based on that of the Rx path.
+		 */
+		.be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
+		.ops = &msm_be_ops,
+	},
 };
 
 struct snd_soc_card snd_soc_card_msm = {
diff --git a/sound/soc/msm/msm-pcm-q6.c b/sound/soc/msm/msm-pcm-q6.c
index 39ce436..ec0d947 100644
--- a/sound/soc/msm/msm-pcm-q6.c
+++ b/sound/soc/msm/msm-pcm-q6.c
@@ -333,21 +333,20 @@
 			kfree(prtd);
 			return -ENOMEM;
 		}
+
+		pr_debug("%s: session ID %d\n", __func__,
+			prtd->audio_client->session);
+		prtd->session_id = prtd->audio_client->session;
+		msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
+			prtd->session_id, substream->stream);
+		prtd->cmd_ack = 1;
+
 	}
 	/* Capture path */
 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
 		runtime->hw = msm_pcm_hardware_capture;
 	}
 
-	pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
-
-	prtd->session_id = prtd->audio_client->session;
-	msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
-			prtd->session_id, substream->stream);
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		prtd->cmd_ack = 1;
-
 	ret = snd_pcm_hw_constraint_list(runtime, 0,
 				SNDRV_PCM_HW_PARAM_RATE,
 				&constraints_sample_rates);
@@ -619,6 +618,7 @@
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct msm_audio *prtd = runtime->private_data;
 	struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
+	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
 	struct audio_buffer *buf;
 	int dir, ret;
 	int format = FORMAT_LINEAR_PCM;
@@ -641,6 +641,12 @@
 			kfree(prtd);
 			return -ENOMEM;
 		}
+
+		pr_debug("%s: session ID %d\n", __func__,
+			prtd->audio_client->session);
+		prtd->session_id = prtd->audio_client->session;
+		msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
+			prtd->session_id, substream->stream);
 	}
 
 	ret = q6asm_audio_client_buf_alloc_contiguous(dir,
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 4f0e952..7cb58cb 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -135,6 +135,8 @@
 	{ SLIMBUS_4_RX, 0, 0, 0, 0, 0},
 	{ SLIMBUS_4_TX, 0, 0, 0, 0, 0},
 	{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
+	{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
+	{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
 };
 
 
@@ -150,6 +152,16 @@
 	{INVALID_SESSION, INVALID_SESSION},
 };
 
+static uint8_t is_be_dai_extproc(int be_dai)
+{
+	if (be_dai == MSM_BACKEND_DAI_EXTPROC_RX ||
+	    be_dai == MSM_BACKEND_DAI_EXTPROC_TX ||
+	    be_dai == MSM_BACKEND_DAI_EXTPROC_EC_TX)
+		return 1;
+	else
+		return 0;
+}
+
 static void msm_pcm_routing_build_matrix(int fedai_id, int dspst_id,
 	int path_type)
 {
@@ -161,7 +173,7 @@
 		MSM_AFE_PORT_TYPE_RX : MSM_AFE_PORT_TYPE_TX);
 
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
-		if ((i != MSM_BACKEND_DAI_EXTPROC_RX) &&
+		if (!is_be_dai_extproc(i) &&
 		    (afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
 		    (msm_bedais[i].active) &&
 		    (test_bit(fedai_id, &msm_bedais[i].fe_sessions)))
@@ -200,7 +212,7 @@
 
 	fe_dai_map[fedai_id][session_type] = dspst_id;
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
-		if ((i != MSM_BACKEND_DAI_EXTPROC_RX) &&
+		if (!is_be_dai_extproc(i) &&
 		    (afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
 		    (msm_bedais[i].active) &&
 		    (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
@@ -243,7 +255,7 @@
 	if (eq_data[fedai_id].enable)
 		msm_send_eq_values(fedai_id);
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
-		if ((i != MSM_BACKEND_DAI_EXTPROC_RX) &&
+		if (!is_be_dai_extproc(i) &&
 		    (afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
 		    (msm_bedais[i].active) &&
 		    (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
@@ -296,7 +308,7 @@
 	mutex_lock(&routing_lock);
 
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
-		if ((i != MSM_BACKEND_DAI_EXTPROC_RX) &&
+		if (!is_be_dai_extproc(i) &&
 		    (afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
 		    (msm_bedais[i].active) &&
 		    (test_bit(fedai_id, &msm_bedais[i].fe_sessions)))
@@ -1227,7 +1239,7 @@
 };
 
 static const struct snd_kcontrol_new tx_voice_stub_mixer_controls[] = {
-	SOC_SINGLE_EXT("STUB_TX_HL", MSM_BACKEND_DAI_EXTPROC_RX,
+	SOC_SINGLE_EXT("STUB_TX_HL", MSM_BACKEND_DAI_EXTPROC_TX,
 	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
 	msm_routing_put_voice_stub_mixer),
 	SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX,
@@ -1236,6 +1248,9 @@
 	SOC_SINGLE_EXT("SLIM_1_TX", MSM_BACKEND_DAI_SLIMBUS_1_TX,
 	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
 	msm_routing_put_voice_stub_mixer),
+	SOC_SINGLE_EXT("STUB_1_TX_HL", MSM_BACKEND_DAI_EXTPROC_EC_TX,
+	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+	msm_routing_put_voice_stub_mixer),
 };
 
 static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = {
@@ -1580,6 +1595,7 @@
 	SND_SOC_DAPM_AIF_IN("STUB_TX", "Stub Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("SLIMBUS_1_RX", "Slimbus1 Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("SLIMBUS_1_TX", "Slimbus1 Capture", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("STUB_1_TX", "Stub1 Capture", 0, 0, 0, 0),
 
 	/* Switch Definitions */
 	SND_SOC_DAPM_SWITCH("SLIMBUS_DL_HL", SND_SOC_NOPM, 0, 0,
@@ -1845,6 +1861,7 @@
 	{"Voice Stub Tx Mixer", "STUB_TX_HL", "STUB_TX"},
 	{"Voice Stub Tx Mixer", "SLIM_1_TX", "SLIMBUS_1_TX"},
 	{"Voice Stub Tx Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
+	{"Voice Stub Tx Mixer", "STUB_1_TX_HL", "STUB_1_TX"},
 	{"VOICE_STUB_UL", NULL, "Voice Stub Tx Mixer"},
 
 	{"STUB_RX Mixer", "Voice Stub", "VOICE_STUB_DL"},
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index b7c7631..26ce53c 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -37,6 +37,7 @@
 #define LPASS_BE_STUB_TX "(Backend) STUB_TX"
 #define LPASS_BE_SLIMBUS_1_RX "(Backend) SLIMBUS_1_RX"
 #define LPASS_BE_SLIMBUS_1_TX "(Backend) SLIMBUS_1_TX"
+#define LPASS_BE_STUB_1_TX "(Backend) STUB_1_TX"
 
 #define LPASS_BE_SLIMBUS_4_RX "(Backend) SLIMBUS_4_RX"
 #define LPASS_BE_SLIMBUS_4_TX "(Backend) SLIMBUS_4_TX"
@@ -89,6 +90,8 @@
 	MSM_BACKEND_DAI_SLIMBUS_4_RX,
 	MSM_BACKEND_DAI_SLIMBUS_4_TX,
 	MSM_BACKEND_DAI_EXTPROC_RX,
+	MSM_BACKEND_DAI_EXTPROC_TX,
+	MSM_BACKEND_DAI_EXTPROC_EC_TX,
 	MSM_BACKEND_DAI_MAX,
 };