Merge "qpnp: pwm: Remove LUT mode dependency of PWM driver"
diff --git a/arch/arm/boot/dts/apq8026-v1-cdp.dts b/arch/arm/boot/dts/apq8026-v1-cdp.dts
new file mode 100644
index 0000000..8c6daa6
--- /dev/null
+++ b/arch/arm/boot/dts/apq8026-v1-cdp.dts
@@ -0,0 +1,22 @@
+/* Copyright (c) 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.
+ */
+
+
+/dts-v1/;
+/include/ "apq8026-v1.dtsi"
+/include/ "msm8226-cdp.dtsi"
+
+/ {
+	model = "Qualcomm APQ 8026 CDP";
+	compatible = "qcom,apq8026-cdp", "qcom,apq8026", "qcom,cdp";
+	qcom,msm-id = <199 1 0>;
+};
diff --git a/arch/arm/boot/dts/apq8026-v2-cdp.dts b/arch/arm/boot/dts/apq8026-v2-cdp.dts
new file mode 100644
index 0000000..74608dd
--- /dev/null
+++ b/arch/arm/boot/dts/apq8026-v2-cdp.dts
@@ -0,0 +1,22 @@
+/* Copyright (c) 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.
+ */
+
+
+/dts-v1/;
+/include/ "apq8026-v2.dtsi"
+/include/ "msm8226-cdp.dtsi"
+
+/ {
+	model = "Qualcomm APQ 8026v2 CDP";
+	compatible = "qcom,apq8026-cdp", "qcom,apq8026", "qcom,cdp";
+	qcom,msm-id = <199 1 0x20000>;
+};
diff --git a/arch/arm/configs/msm9625-perf_defconfig b/arch/arm/configs/msm9625-perf_defconfig
index 6471673..9a5aaf0 100644
--- a/arch/arm/configs/msm9625-perf_defconfig
+++ b/arch/arm/configs/msm9625-perf_defconfig
@@ -115,6 +115,7 @@
 CONFIG_NETFILTER_XT_MATCH_ESP=y
 CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
 CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
 CONFIG_IP_SET=y
 CONFIG_NF_CONNTRACK_IPV4=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 863e14f..3f34690 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -119,6 +119,7 @@
 CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
 CONFIG_NETFILTER_XT_MATCH_LIMIT=y
 CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
 CONFIG_IP_SET=y
 CONFIG_NF_CONNTRACK_IPV4=y
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 8b0acc6..3505afe 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -99,8 +99,10 @@
         dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v1-qrd-skuf.dtb
         dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-qrd-skuf.dtb
         dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v1-xpm.dtb
+        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v1-cdp.dtb
         dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v1-mtp.dtb
         dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v2-xpm.dtb
+        dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v2-cdp.dtb
         dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v2-mtp.dtb
 
 # FSM9XXX
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
index 4c5f258..07a66e6 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -22,7 +22,7 @@
 #include "msm.h"
 #include "msm_camera_io_util.h"
 
-#define VFE32_BURST_LEN 1
+#define VFE32_BURST_LEN 2
 #define VFE32_UB_SIZE 1024
 #define VFE32_EQUAL_SLICE_UB 204
 #define VFE32_WM_BASE(idx) (0x4C + 0x18 * idx)
@@ -146,7 +146,7 @@
 	/* BUS_CFG */
 	msm_camera_io_w(0x00000001, vfe_dev->vfe_base + 0x3C);
 	msm_camera_io_w(0x01000025, vfe_dev->vfe_base + 0x1C);
-	msm_camera_io_w_mb(0x1DFFFFFF, vfe_dev->vfe_base + 0x20);
+	msm_camera_io_w_mb(0x1CFFFFFF, vfe_dev->vfe_base + 0x20);
 	msm_camera_io_w(0xFFFFFFFF, vfe_dev->vfe_base + 0x24);
 	msm_camera_io_w_mb(0x1FFFFFFF, vfe_dev->vfe_base + 0x28);
 }
@@ -161,8 +161,6 @@
 static void msm_vfe32_process_halt_irq(struct vfe_device *vfe_dev,
 	uint32_t irq_status0, uint32_t irq_status1)
 {
-	if (irq_status1 & BIT(24))
-		complete(&vfe_dev->halt_complete);
 }
 
 static void msm_vfe32_process_camif_irq(struct vfe_device *vfe_dev,
@@ -304,7 +302,7 @@
 	*irq_status0 = msm_camera_io_r(vfe_dev->vfe_base + 0x2C);
 	*irq_status1 = msm_camera_io_r(vfe_dev->vfe_base + 0x30);
 	msm_camera_io_w(*irq_status0, vfe_dev->vfe_base + 0x24);
-	msm_camera_io_w(*irq_status1, vfe_dev->vfe_base + 0x28);
+	msm_camera_io_w_mb(*irq_status1, vfe_dev->vfe_base + 0x28);
 	msm_camera_io_w_mb(1, vfe_dev->vfe_base + 0x18);
 
 	if (*irq_status1 & BIT(0))
@@ -750,14 +748,20 @@
 static long msm_vfe32_axi_halt(struct vfe_device *vfe_dev)
 {
 	uint32_t halt_mask;
+	uint32_t axi_busy_flag = true;
+
+	msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x1D8);
+	while (axi_busy_flag) {
+		if (msm_camera_io_r(
+			vfe_dev->vfe_base + 0x1DC) & 0x1)
+			axi_busy_flag = false;
+	}
+	msm_camera_io_w_mb(0, vfe_dev->vfe_base + 0x1D8);
 	halt_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x20);
-	halt_mask |= BIT(24);
+	halt_mask &= 0xFEFFFFFF;
+	/* Disable AXI IRQ */
 	msm_camera_io_w_mb(halt_mask, vfe_dev->vfe_base + 0x20);
-	init_completion(&vfe_dev->halt_complete);
-	/*TD: Need to fix crashes with this*/
-	/*msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x1D8);*/
-	return wait_for_completion_interruptible_timeout(
-		&vfe_dev->halt_complete, msecs_to_jiffies(500));
+	return 0;
 }
 
 static uint32_t msm_vfe32_get_wm_mask(
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index b85527d..2ffd653 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -1478,7 +1478,7 @@
 		k_stream_buff_info.buffer_info =
 			kzalloc(k_stream_buff_info.num_buffs *
 			sizeof(struct msm_cpp_buffer_info_t), GFP_KERNEL);
-		if (!k_stream_buff_info.buffer_info) {
+		if (ZERO_OR_NULL_PTR(k_stream_buff_info.buffer_info)) {
 			pr_err("%s:%d: malloc error\n", __func__, __LINE__);
 			kfree(u_stream_buff_info);
 			mutex_unlock(&cpp_dev->mutex);
diff --git a/drivers/media/radio/radio-tavarua.c b/drivers/media/radio/radio-tavarua.c
index ea7032b..e0a99e2 100644
--- a/drivers/media/radio/radio-tavarua.c
+++ b/drivers/media/radio/radio-tavarua.c
@@ -1932,6 +1932,7 @@
 	if (bahama_present == -ENODEV)
 		return -ENODEV;
 
+	marimba_set_fm_status(radio->marimba, true);
 	if (bahama_present)
 		radio->marimba->mod_id = SLAVE_ID_BAHAMA;
 	else
@@ -2066,7 +2067,6 @@
 
 	radio->handle_irq = 0;
 	radio->marimba->mod_id = SLAVE_ID_BAHAMA;
-	marimba_set_fm_status(radio->marimba, true);
 	return 0;
 
 
@@ -2082,6 +2082,7 @@
 config_i2s_err:
 	radio->pdata->fm_shutdown(radio->pdata);
 open_err_setup:
+	marimba_set_fm_status(radio->marimba, false);
 	radio->handle_irq = 1;
 	atomic_inc(&radio->users);
 	return retval;
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 4889a79..9911750 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -140,6 +140,7 @@
 	int bus_suspend;
 	bool disconnected;
 	bool in_lpm[MAX_BAMS];
+	bool pending_lpm;
 
 	int (*wake_cb)(void *);
 	void *wake_param;
@@ -634,15 +635,25 @@
 static void usb_bam_start_lpm(bool disconnect)
 {
 	struct usb_phy *trans = usb_get_transceiver();
+
 	BUG_ON(trans == NULL);
-		pr_debug("%s: Going to LPM\n", __func__);
+
 	spin_lock(&usb_bam_ipa_handshake_info_lock);
+
 	info.lpm_wait_handshake[HSUSB_BAM] = false;
 	info.lpm_wait_pipes = 0;
+
 	if (disconnect)
 		pm_runtime_put_noidle(trans->dev);
-	spin_unlock(&usb_bam_ipa_handshake_info_lock);
-	pm_runtime_suspend(trans->dev);
+
+	if (info.pending_lpm) {
+		info.pending_lpm = 0;
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+		pr_debug("%s: Going to LPM\n", __func__);
+		pm_runtime_suspend(trans->dev);
+	} else
+		spin_unlock(&usb_bam_ipa_handshake_info_lock);
+
 }
 
 int usb_bam_connect(u8 idx, u32 *bam_pipe_idx)
@@ -1438,6 +1449,7 @@
 			info.lpm_wait_handshake[HSUSB_BAM] = true;
 			info.connect_complete = 0;
 			info.disconnected = 0;
+			info.pending_lpm = 0;
 			info.lpm_wait_pipes = 1;
 			info.bus_suspend = 0;
 			info.cons_stopped = 0;
@@ -1998,8 +2010,18 @@
 			ipa_rm_notify_completion(IPA_RM_RESOURCE_RELEASED,
 				ipa_rm_resource_cons[cur_bam]);
 		}
-		pr_debug("%s Ended disconnect sequence\n", __func__);
-		usb_bam_start_lpm(1);
+
+		if (cur_bam == HSUSB_BAM) {
+			/*
+			 * Currently we have for HSUSB BAM only one consumer
+			 * pipe. Therefore ending disconnect sequence and
+			 * starting hsusb lpm. This limitation will be changed
+			 * in future patch.
+			 */
+			pr_debug("%s Ended disconnect sequence\n", __func__);
+			usb_bam_start_lpm(1);
+		}
+
 		mutex_unlock(&info.suspend_resume_mutex);
 		return 0;
 	}
@@ -2629,10 +2651,12 @@
 {
 	spin_lock(&usb_bam_ipa_handshake_info_lock);
 	if (info.lpm_wait_handshake[HSUSB_BAM] || info.lpm_wait_pipes) {
+		info.pending_lpm = 1;
 		spin_unlock(&usb_bam_ipa_handshake_info_lock);
 		pr_err("%s: Scheduling LPM for later\n", __func__);
 		return 0;
 	} else {
+		info.pending_lpm = 0;
 		info.in_lpm[HSUSB_BAM] = true;
 		spin_unlock(&usb_bam_ipa_handshake_info_lock);
 		pr_err("%s: Going to LPM now\n", __func__);
@@ -2641,6 +2665,16 @@
 }
 EXPORT_SYMBOL(msm_bam_lpm_ok);
 
+void msm_bam_notify_lpm_resume()
+{
+	/*
+	 * If core was resumed from lpm, just clear the
+	 * pending indication, in case it is set.
+	*/
+	info.pending_lpm = 0;
+}
+EXPORT_SYMBOL(msm_bam_notify_lpm_resume);
+
 static int usb_bam_remove(struct platform_device *pdev)
 {
 	destroy_workqueue(ctx.usb_bam_wq);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index fa1932b..104ee5f 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1005,7 +1005,8 @@
 	 * PHY retention and collapse can not happen with VDP_SRC enabled.
 	 */
 	if (motg->caps & ALLOW_PHY_RETENTION && !device_bus_suspend && !dcp &&
-		 (!host_bus_suspend || motg->caps & ALLOW_HOST_PHY_RETENTION)) {
+		 (!host_bus_suspend || ((motg->caps & ALLOW_HOST_PHY_RETENTION)
+		&& (pdata->dpdm_pulldown_added || !(portsc & PORTSC_CCS))))) {
 		phy_ctrl_val = readl_relaxed(USB_PHY_CTRL);
 		if (motg->pdata->otg_control == OTG_PHY_CONTROL) {
 			/* Enable PHY HV interrupts to wake MPM/Link */
@@ -1034,7 +1035,8 @@
 	}
 
 	/* usb phy no more require TCXO clock, hence vote for TCXO disable */
-	if (!host_bus_suspend || (motg->caps & ALLOW_HOST_PHY_RETENTION)) {
+	if (!host_bus_suspend || ((motg->caps & ALLOW_HOST_PHY_RETENTION) &&
+		(pdata->dpdm_pulldown_added || !(portsc & PORTSC_CCS)))) {
 		if (!IS_ERR(motg->xo_clk)) {
 			clk_disable_unprepare(motg->xo_clk);
 			motg->lpm_flags |= XO_SHUTDOWN;
@@ -1111,6 +1113,9 @@
 	if (!atomic_read(&motg->in_lpm))
 		return 0;
 
+	if (motg->pdata->delay_lpm_hndshk_on_disconnect)
+		msm_bam_notify_lpm_resume();
+
 	disable_irq(motg->irq);
 	wake_lock(&motg->wlock);
 
@@ -4053,6 +4058,37 @@
 	return ret;
 }
 
+static ssize_t dpdm_pulldown_enable_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	struct msm_otg *motg = the_msm_otg;
+	struct msm_otg_platform_data *pdata = motg->pdata;
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", pdata->dpdm_pulldown_added ?
+							"enabled" : "disabled");
+}
+
+static ssize_t dpdm_pulldown_enable_store(struct device *dev,
+		struct device_attribute *attr, const char
+		*buf, size_t size)
+{
+	struct msm_otg *motg = the_msm_otg;
+	struct msm_otg_platform_data *pdata = motg->pdata;
+
+	if (!strnicmp(buf, "enable", 6)) {
+		pdata->dpdm_pulldown_added = true;
+		return size;
+	} else if (!strnicmp(buf, "disable", 7)) {
+		pdata->dpdm_pulldown_added = false;
+		return size;
+	}
+
+	return -EINVAL;
+}
+
+static DEVICE_ATTR(dpdm_pulldown_enable, S_IRUGO | S_IWUSR,
+		dpdm_pulldown_enable_show, dpdm_pulldown_enable_store);
+
 struct msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev)
 {
 	struct device_node *node = pdev->dev.of_node;
@@ -4479,6 +4515,8 @@
 
 		if (motg->pdata->mpm_dpshv_int || motg->pdata->mpm_dmshv_int)
 			motg->caps |= ALLOW_HOST_PHY_RETENTION;
+			device_create_file(&pdev->dev,
+					&dev_attr_dpdm_pulldown_enable);
 	}
 
 	if (motg->pdata->enable_lpm_on_dev_suspend)
@@ -4613,6 +4651,10 @@
 	usb_set_transceiver(NULL);
 	free_irq(motg->irq, motg);
 
+	if ((motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY) &&
+		(motg->pdata->mpm_dpshv_int || motg->pdata->mpm_dmshv_int))
+			device_remove_file(&pdev->dev,
+					&dev_attr_dpdm_pulldown_enable);
 	if (motg->pdata->otg_control == OTG_PHY_CONTROL &&
 		motg->pdata->mpm_otgsessvld_int)
 		msm_mpm_enable_pin(motg->pdata->mpm_otgsessvld_int, 0);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index f04d2bf..cb2162e 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -228,6 +228,8 @@
  *              interrupt threshold (ITC), when log2_itc is
  *              between 1 to 7.
  * @l1_supported: enable link power management support.
+ * @dpdm_pulldown_added: Indicates whether pull down resistors are
+		connected on data lines or not.
  */
 struct msm_otg_platform_data {
 	int *phy_init_seq;
@@ -255,6 +257,7 @@
 	const char *mhl_dev_name;
 	int log2_itc;
 	bool l1_supported;
+	bool dpdm_pulldown_added;
 };
 
 /* phy related flags */
@@ -525,12 +528,14 @@
 };
 #ifdef CONFIG_USB_BAM
 bool msm_bam_lpm_ok(void);
+void msm_bam_notify_lpm_resume(void);
 void msm_bam_set_hsic_host_dev(struct device *dev);
 void msm_bam_wait_for_hsic_prod_granted(void);
 bool msm_bam_hsic_lpm_ok(void);
 void msm_bam_hsic_notify_on_resume(void);
 #else
 static inline bool msm_bam_lpm_ok(void) { return true; }
+static inline void msm_bam_notify_lpm_resume(void) {}
 static inline void msm_bam_set_hsic_host_dev(struct device *dev) {}
 static inline void msm_bam_wait_for_hsic_prod_granted(void) {}
 static inline bool msm_bam_hsic_lpm_ok(void) { return true; }