Merge "msm: board-8930: Add platform device for multi channel session." into msm-3.4
diff --git a/Documentation/devicetree/bindings/gpio/qpnp-pin.txt b/Documentation/devicetree/bindings/gpio/qpnp-pin.txt
index c58e073..31c3bc2 100644
--- a/Documentation/devicetree/bindings/gpio/qpnp-pin.txt
+++ b/Documentation/devicetree/bindings/gpio/qpnp-pin.txt
@@ -94,7 +94,7 @@
 			QPNP_PIN_OUT_STRENGTH_MED  = 2, (GPIO)
 			QPNP_PIN_OUT_STRENGTH_HIGH = 3, (GPIO)
 
-  - qcom,select:	select a function for the pin. Certain pins
+  - qcom,src-select:	select a function for the pin. Certain pins
 			can be paired (shorted) with each other. Some gpio pins
 			can act as alternate functions.
 			In the context of gpio, this acts as a source select.
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index b35e949..04e751a 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -47,16 +47,29 @@
 #define BAM_MUX_HDR_CMD_STATUS		3 /* unused */
 #define BAM_MUX_HDR_CMD_OPEN_NO_A2_PC	4
 
-#define POLLING_MIN_SLEEP	950	/* 0.95 ms */
-#define POLLING_MAX_SLEEP	1050	/* 1.05 ms */
-#define POLLING_INACTIVITY	40	/* cycles before switch to intr mode */
 
 #define LOW_WATERMARK		2
 #define HIGH_WATERMARK		4
+#define DEFAULT_POLLING_MIN_SLEEP (950)
+#define MAX_POLLING_SLEEP (6050)
+#define MIN_POLLING_SLEEP (950)
 
 static int msm_bam_dmux_debug_enable;
 module_param_named(debug_enable, msm_bam_dmux_debug_enable,
 		   int, S_IRUGO | S_IWUSR | S_IWGRP);
+static int POLLING_MIN_SLEEP = 950;
+module_param_named(min_sleep, POLLING_MIN_SLEEP,
+		   int, S_IRUGO | S_IWUSR | S_IWGRP);
+static int POLLING_MAX_SLEEP = 1050;
+module_param_named(max_sleep, POLLING_MAX_SLEEP,
+		   int, S_IRUGO | S_IWUSR | S_IWGRP);
+static int POLLING_INACTIVITY = 40;
+module_param_named(inactivity, POLLING_INACTIVITY,
+		   int, S_IRUGO | S_IWUSR | S_IWGRP);
+static int bam_adaptive_timer_enabled = 1;
+module_param_named(adaptive_timer_enabled,
+			bam_adaptive_timer_enabled,
+		   int, S_IRUGO | S_IWUSR | S_IWGRP);
 
 #if defined(DEBUG)
 static uint32_t bam_dmux_read_cnt;
@@ -177,6 +190,7 @@
 static int bam_mux_initialized;
 
 static int polling_mode;
+static unsigned long rx_timer_interval;
 
 static LIST_HEAD(bam_rx_pool);
 static DEFINE_MUTEX(bam_rx_pool_mutexlock);
@@ -1116,6 +1130,7 @@
 	struct rx_pkt_info *info;
 	int inactive_cycles = 0;
 	int ret;
+	u32 buffs_unused, buffs_used;
 
 	while (bam_connection_is_active) { /* timer loop */
 		++inactive_cycles;
@@ -1162,12 +1177,47 @@
 			handle_bam_mux_cmd(&info->work);
 		}
 
-		if (inactive_cycles == POLLING_INACTIVITY) {
+		if (inactive_cycles >= POLLING_INACTIVITY) {
 			rx_switch_to_interrupt_mode();
 			break;
 		}
 
-		usleep_range(POLLING_MIN_SLEEP, POLLING_MAX_SLEEP);
+		if (bam_adaptive_timer_enabled) {
+			usleep_range(rx_timer_interval, rx_timer_interval + 50);
+
+			ret = sps_get_unused_desc_num(bam_rx_pipe,
+						&buffs_unused);
+
+			if (ret) {
+				pr_err("%s: error getting num buffers unused after sleep\n",
+					__func__);
+
+				break;
+			}
+
+			buffs_used = NUM_BUFFERS - buffs_unused;
+
+			if (buffs_unused == 0) {
+				rx_timer_interval = MIN_POLLING_SLEEP;
+			} else {
+				if (buffs_used > 0) {
+					rx_timer_interval =
+						(2 * NUM_BUFFERS *
+							rx_timer_interval)/
+						(3 * buffs_used);
+				} else {
+					rx_timer_interval =
+						MAX_POLLING_SLEEP;
+				}
+			}
+
+			if (rx_timer_interval > MAX_POLLING_SLEEP)
+				rx_timer_interval = MAX_POLLING_SLEEP;
+			else if (rx_timer_interval < MIN_POLLING_SLEEP)
+				rx_timer_interval = MIN_POLLING_SLEEP;
+		} else {
+			usleep_range(POLLING_MIN_SLEEP, POLLING_MAX_SLEEP);
+		}
 	}
 }
 
@@ -2379,6 +2429,8 @@
 		bam_dmux_state_logging_disabled = 1;
 	}
 
+	rx_timer_interval = DEFAULT_POLLING_MIN_SLEEP;
+
 	subsys_notif_register_notifier("modem", &restart_notifier);
 	return platform_driver_register(&bam_dmux_driver);
 }
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 38e8d18..68a85c0 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -2292,6 +2292,7 @@
 	&apq8064_iommu_domain_device,
 	&msm_tsens_device,
 	&apq8064_cache_dump_device,
+	&msm_8064_device_tspp,
 };
 
 static struct platform_device *cdp_devices[] __initdata = {
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
index 318523b..cbf1d72 100644
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ b/arch/arm/mach-msm/wcnss-ssr-8960.c
@@ -180,8 +180,13 @@
 static void riva_crash_shutdown(const struct subsys_desc *subsys)
 {
 	pr_err("%s: crash shutdown : %d\n", MODULE_NAME, riva_crash);
-	if (riva_crash != true)
+	if (riva_crash != true) {
 		smsm_riva_reset();
+		/* give sufficient time for wcnss to finish it's error
+		 * fatal routine */
+		msleep(3000);
+	}
+
 }
 
 static struct subsys_desc riva_8960 = {
diff --git a/drivers/gpio/gpio-msm-v3.c b/drivers/gpio/gpio-msm-v3.c
index e041bfd..26716a0 100644
--- a/drivers/gpio/gpio-msm-v3.c
+++ b/drivers/gpio/gpio-msm-v3.c
@@ -183,10 +183,10 @@
 	else
 		cfg |= INTR_DECT_CTL_LEVEL;
 
-	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
-		cfg |= INTR_POL_CTL_HI;
-	else
+	if (type & IRQ_TYPE_LEVEL_LOW)
 		cfg &= ~INTR_POL_CTL_HI;
+	else
+		cfg |= INTR_POL_CTL_HI;
 
 	__raw_writel(cfg, GPIO_INTR_CFG(gpio));
 	/* Sometimes it might take a little while to update
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index e7f5935..0426339 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -824,3 +824,13 @@
 		kgsl_mmu_type = KGSL_MMU_TYPE_NONE;
 }
 EXPORT_SYMBOL(kgsl_mmu_set_mmutype);
+
+int kgsl_mmu_gpuaddr_in_range(unsigned int gpuaddr)
+{
+	if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
+		return 1;
+	return ((gpuaddr >= KGSL_PAGETABLE_BASE) &&
+		(gpuaddr < (KGSL_PAGETABLE_BASE + kgsl_mmu_get_ptsize())));
+}
+EXPORT_SYMBOL(kgsl_mmu_gpuaddr_in_range);
+
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 5293d66..8221b80 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -205,6 +205,7 @@
 void kgsl_mmu_set_mmutype(char *mmutype);
 enum kgsl_mmutype kgsl_mmu_get_mmutype(void);
 unsigned int kgsl_mmu_get_ptsize(void);
+int kgsl_mmu_gpuaddr_in_range(unsigned int gpuaddr);
 
 /*
  * Static inline functions of MMU that simply call the SMMU specific
@@ -293,12 +294,6 @@
 		mmu->mmu_ops->mmu_disable_clk_on_ts(mmu, ts, ts_valid);
 }
 
-static inline int kgsl_mmu_gpuaddr_in_range(unsigned int gpuaddr)
-{
-	return ((gpuaddr >= KGSL_PAGETABLE_BASE) &&
-		(gpuaddr < (KGSL_PAGETABLE_BASE + kgsl_mmu_get_ptsize())));
-}
-
 static inline unsigned int kgsl_mmu_get_int_mask(void)
 {
 	/* Dont enable gpummu interrupts, if iommu is enabled */
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 4dd6d68..465e512 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -47,6 +47,8 @@
 #define USB_REG_START_OFFSET 0x90
 #define USB_REG_END_OFFSET 0x250
 
+static struct workqueue_struct  *ehci_wq;
+
 struct msm_hsic_hcd {
 	struct ehci_hcd		ehci;
 	struct device		*dev;
@@ -66,6 +68,9 @@
 	uint32_t		bus_perf_client;
 	uint32_t		wakeup_int_cnt;
 	enum usb_vdd_type	vdd_type;
+
+	struct work_struct	bus_vote_w;
+	bool			bus_vote;
 };
 
 struct msm_hsic_hcd *__mehci;
@@ -658,11 +663,8 @@
 		dev_err(mehci->dev, "unable to set vddcx voltage for VDD MIN\n");
 
 	if (mehci->bus_perf_client && debug_bus_voting_enabled) {
-		ret = msm_bus_scale_client_update_request(
-				mehci->bus_perf_client, 0);
-		if (ret)
-			dev_err(mehci->dev, "%s: Failed to dvote for "
-				   "bus bandwidth %d\n", __func__, ret);
+		mehci->bus_vote = false;
+		queue_work(ehci_wq, &mehci->bus_vote_w);
 	}
 
 	atomic_set(&mehci->in_lpm, 1);
@@ -697,11 +699,8 @@
 	}
 
 	if (mehci->bus_perf_client && debug_bus_voting_enabled) {
-		ret = msm_bus_scale_client_update_request(
-				mehci->bus_perf_client, 1);
-		if (ret)
-			dev_err(mehci->dev, "%s: Failed to vote for "
-				   "bus bandwidth %d\n", __func__, ret);
+		mehci->bus_vote = true;
+		queue_work(ehci_wq, &mehci->bus_vote_w);
 	}
 
 	min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
@@ -769,6 +768,19 @@
 }
 #endif
 
+static void ehci_hsic_bus_vote_w(struct work_struct *w)
+{
+	struct msm_hsic_hcd *mehci =
+			container_of(w, struct msm_hsic_hcd, bus_vote_w);
+	int ret;
+
+	ret = msm_bus_scale_client_update_request(mehci->bus_perf_client,
+			mehci->bus_vote);
+	if (ret)
+		dev_err(mehci->dev, "%s: Failed to vote for bus bandwidth %d\n",
+				__func__, ret);
+}
+
 static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
 {
 	struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
@@ -1294,6 +1306,15 @@
 		goto deinit_vddcx;
 	}
 
+	ehci_wq = create_singlethread_workqueue("ehci_wq");
+	if (!ehci_wq) {
+		dev_err(&pdev->dev, "unable to create workqueue\n");
+		ret = -ENOMEM;
+		goto deinit_vddcx;
+	}
+
+	INIT_WORK(&mehci->bus_vote_w, ehci_hsic_bus_vote_w);
+
 	ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to register HCD\n");
@@ -1339,11 +1360,8 @@
 		    msm_bus_scale_register_client(pdata->bus_scale_table);
 		/* Configure BUS performance parameters for MAX bandwidth */
 		if (mehci->bus_perf_client) {
-			ret = msm_bus_scale_client_update_request(
-					mehci->bus_perf_client, 1);
-			if (ret)
-				dev_err(&pdev->dev, "%s: Failed to vote for "
-					   "bus bandwidth %d\n", __func__, ret);
+			mehci->bus_vote = true;
+			queue_work(ehci_wq, &mehci->bus_vote_w);
 		} else {
 			dev_err(&pdev->dev, "%s: Failed to register BUS "
 						"scaling client!!\n", __func__);
@@ -1369,6 +1387,7 @@
 	return 0;
 
 unconfig_gpio:
+	destroy_workqueue(ehci_wq);
 	msm_hsic_config_gpios(mehci, 0);
 deinit_vddcx:
 	msm_hsic_init_vddcx(mehci, 0);
@@ -1396,6 +1415,14 @@
 		free_irq(mehci->wakeup_irq, mehci);
 	}
 
+	/*
+	 * If the update request is called after unregister, the request will
+	 * fail. Results are undefined if unregister is called in the middle of
+	 * update request.
+	 */
+	mehci->bus_vote = false;
+	cancel_work_sync(&mehci->bus_vote_w);
+
 	if (mehci->bus_perf_client)
 		msm_bus_scale_unregister_client(mehci->bus_perf_client);
 
@@ -1403,6 +1430,8 @@
 	device_init_wakeup(&pdev->dev, 0);
 	pm_runtime_set_suspended(&pdev->dev);
 
+	destroy_workqueue(ehci_wq);
+
 	usb_remove_hcd(hcd);
 	msm_hsic_config_gpios(mehci, 0);
 	msm_hsic_init_vddcx(mehci, 0);
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index 2f0a1f5..bc64d2e 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -304,7 +304,7 @@
 	itp.h_back_porch =  pinfo->lcdc.h_back_porch;
 	itp.h_front_porch =  pinfo->lcdc.h_front_porch;
 	itp.v_back_porch =  pinfo->lcdc.v_back_porch;
-	itp.v_front_porch = pinfo->lcdc.h_front_porch;
+	itp.v_front_porch = pinfo->lcdc.v_front_porch;
 	itp.hsync_pulse_width = pinfo->lcdc.h_pulse_width;
 	itp.vsync_pulse_width = pinfo->lcdc.v_pulse_width;