Merge "ASoC: Bolero: Vote for LPASS HW core during register access"
diff --git a/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c
index 217800a..a4f3c7d 100644
--- a/asoc/codecs/bolero/va-macro.c
+++ b/asoc/codecs/bolero/va-macro.c
@@ -248,6 +248,10 @@
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
 		ret = va_macro_mclk_enable(va_priv, 1, true);
+		ret = bolero_clk_rsc_request_clock(va_priv->dev,
+						   va_priv->default_clk_id,
+						   TX_CORE_CLK,
+						   true);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		va_macro_mclk_enable(va_priv, 0, true);
@@ -584,6 +588,10 @@
 		/* apply gain after decimator is enabled */
 		snd_soc_component_write(component, tx_gain_ctl_reg,
 			snd_soc_component_read32(component, tx_gain_ctl_reg));
+		bolero_clk_rsc_request_clock(va_priv->dev,
+					   va_priv->default_clk_id,
+					   TX_CORE_CLK,
+					   false);
 		break;
 	case SND_SOC_DAPM_PRE_PMD:
 		hpf_cut_off_freq =
diff --git a/asoc/codecs/wcd938x/wcd938x.c b/asoc/codecs/wcd938x/wcd938x.c
index 6412fd9..ca20bc4 100644
--- a/asoc/codecs/wcd938x/wcd938x.c
+++ b/asoc/codecs/wcd938x/wcd938x.c
@@ -39,8 +39,7 @@
 
 enum {
 	WCD9380 = 0,
-	WCD9385,
-	WCD9385FX,
+	WCD9385 = 5,
 };
 
 enum {
@@ -1355,6 +1354,13 @@
 			__func__, micb_index);
 		return -EINVAL;
 	}
+
+	if (NULL == wcd938x) {
+		dev_err(component->dev,
+			"%s: wcd938x private data is NULL\n", __func__);
+		return -EINVAL;
+	}
+
 	switch (micb_num) {
 	case MIC_BIAS_1:
 		micb_reg = WCD938X_ANA_MICB1;
@@ -1755,6 +1761,14 @@
 	return 0;
 }
 
+static const char * const tx_mode_mux_text_wcd9380[] = {
+	"ADC_INVALID", "ADC_HIFI", "ADC_LO_HIF", "ADC_NORMAL", "ADC_LP",
+};
+
+static const struct soc_enum tx_mode_mux_enum_wcd9380 =
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tx_mode_mux_text_wcd9380),
+			    tx_mode_mux_text_wcd9380);
+
 static const char * const tx_mode_mux_text[] = {
 	"ADC_INVALID", "ADC_HIFI", "ADC_LO_HIF", "ADC_NORMAL", "ADC_LP",
 	"ADC_ULP1", "ADC_ULP2",
@@ -1773,10 +1787,18 @@
 	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_hph_mode_mux_text),
 			    rx_hph_mode_mux_text);
 
-static const struct snd_kcontrol_new wcd938x_snd_controls[] = {
-	SOC_ENUM_EXT("RX HPH Mode", rx_hph_mode_mux_enum,
-		wcd938x_rx_hph_mode_get, wcd938x_rx_hph_mode_put),
+static const struct snd_kcontrol_new wcd9380_snd_controls[] = {
+	SOC_ENUM_EXT("TX0 MODE", tx_mode_mux_enum_wcd9380,
+			wcd938x_tx_mode_get, wcd938x_tx_mode_put),
+	SOC_ENUM_EXT("TX1 MODE", tx_mode_mux_enum_wcd9380,
+			wcd938x_tx_mode_get, wcd938x_tx_mode_put),
+	SOC_ENUM_EXT("TX2 MODE", tx_mode_mux_enum_wcd9380,
+			wcd938x_tx_mode_get, wcd938x_tx_mode_put),
+	SOC_ENUM_EXT("TX3 MODE", tx_mode_mux_enum_wcd9380,
+			wcd938x_tx_mode_get, wcd938x_tx_mode_put),
+};
 
+static const struct snd_kcontrol_new wcd9385_snd_controls[] = {
 	SOC_ENUM_EXT("TX0 MODE", tx_mode_mux_enum,
 			wcd938x_tx_mode_get, wcd938x_tx_mode_put),
 	SOC_ENUM_EXT("TX1 MODE", tx_mode_mux_enum,
@@ -1785,6 +1807,11 @@
 			wcd938x_tx_mode_get, wcd938x_tx_mode_put),
 	SOC_ENUM_EXT("TX3 MODE", tx_mode_mux_enum,
 			wcd938x_tx_mode_get, wcd938x_tx_mode_put),
+};
+
+static const struct snd_kcontrol_new wcd938x_snd_controls[] = {
+	SOC_ENUM_EXT("RX HPH Mode", rx_hph_mode_mux_enum,
+		wcd938x_rx_hph_mode_get, wcd938x_rx_hph_mode_put),
 
 	SOC_SINGLE_EXT("HPHL_COMP Switch", SND_SOC_NOPM, 0, 1, 0,
 		wcd938x_get_compander, wcd938x_set_compander),
@@ -2406,6 +2433,26 @@
 	wcd_cls_h_init(&wcd938x->clsh_info);
 	wcd938x_init_reg(component);
 
+	if (wcd938x->variant == WCD9380) {
+		ret = snd_soc_add_component_controls(component, wcd9380_snd_controls,
+					ARRAY_SIZE(wcd9380_snd_controls));
+		if (ret < 0) {
+			dev_err(component->dev,
+				"%s: Failed to add snd ctrls for variant: %d\n",
+				__func__, wcd938x->variant);
+			goto err_hwdep;
+		}
+	}
+	if (wcd938x->variant == WCD9385) {
+		ret = snd_soc_add_component_controls(component, wcd9385_snd_controls,
+					ARRAY_SIZE(wcd9385_snd_controls));
+		if (ret < 0) {
+			dev_err(component->dev,
+				"%s: Failed to add snd ctrls for variant: %d\n",
+				__func__, wcd938x->variant);
+			goto err_hwdep;
+		}
+	}
 	wcd938x->version = WCD938X_VERSION_1_0;
        /* Register event notifier */
 	wcd938x->nblock.notifier_call = wcd938x_event_notify;
diff --git a/dsp/q6adm.c b/dsp/q6adm.c
index f081065..8848b22 100644
--- a/dsp/q6adm.c
+++ b/dsp/q6adm.c
@@ -1510,7 +1510,7 @@
 	}
 
 	adm_callback_debug_print(data);
-	if (data->payload_size) {
+	if (data->payload_size >= sizeof(uint32_t)) {
 		copp_idx = (data->token) & 0XFF;
 		port_idx = ((data->token) >> 16) & 0xFF;
 		client_id = ((data->token) >> 8) & 0xFF;
@@ -1530,13 +1530,20 @@
 			return 0;
 		}
 		if (data->opcode == APR_BASIC_RSP_RESULT) {
-			if (data->payload_size < (2 * sizeof(uint32_t))) {
-				pr_err("%s: Invalid payload size %d\n", __func__,
-					data->payload_size);
-				return 0;
-			}
 			pr_debug("%s: APR_BASIC_RSP_RESULT id 0x%x\n",
 				__func__, payload[0]);
+
+			if (!((client_id != ADM_CLIENT_ID_SOURCE_TRACKING) &&
+			     ((payload[0] == ADM_CMD_SET_PP_PARAMS_V5) ||
+			      (payload[0] == ADM_CMD_SET_PP_PARAMS_V6)))) {
+				if (data->payload_size <
+						(2 * sizeof(uint32_t))) {
+					pr_err("%s: Invalid payload size %d\n",
+						__func__, data->payload_size);
+					return 0;
+				}
+			}
+
 			if (payload[1] != 0) {
 				pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
 					__func__, payload[0], payload[1]);
@@ -1718,21 +1725,28 @@
 		case ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST_V2:
 			pr_debug("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST\n",
 				 __func__);
-			num_modules = payload[1];
-			pr_debug("%s: Num modules %d\n", __func__, num_modules);
-			if (payload[0]) {
-				pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST, error = %d\n",
-				       __func__, payload[0]);
-			} else if (num_modules > MAX_MODULES_IN_TOPO) {
-				pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST invalid num modules received, num modules = %d\n",
-				       __func__, num_modules);
+			if (data->payload_size >= (2 * sizeof(uint32_t))) {
+				num_modules = payload[1];
+				pr_debug("%s: Num modules %d\n", __func__,
+					 num_modules);
+				if (payload[0]) {
+					pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST, error = %d\n",
+					       __func__, payload[0]);
+				} else if (num_modules > MAX_MODULES_IN_TOPO) {
+					pr_err("%s: ADM_CMDRSP_GET_PP_TOPO_MODULE_LIST invalid num modules received, num modules = %d\n",
+					       __func__, num_modules);
+				} else {
+					ret = adm_process_get_topo_list_response(
+						data->opcode, copp_idx,
+						num_modules, payload,
+						data->payload_size);
+					if (ret)
+						pr_err("%s: Failed to process get topo modules list response, error %d\n",
+						       __func__, ret);
+				}
 			} else {
-				ret = adm_process_get_topo_list_response(
-					data->opcode, copp_idx, num_modules,
-					payload, data->payload_size);
-				if (ret)
-					pr_err("%s: Failed to process get topo modules list response, error %d\n",
-					       __func__, ret);
+				pr_err("%s: Invalid payload size %d\n",
+					__func__, data->payload_size);
 			}
 			atomic_set(&this_adm.copp.stat[port_idx][copp_idx],
 				   payload[0]);
diff --git a/dsp/q6afe.c b/dsp/q6afe.c
index fd66571..0002d82 100644
--- a/dsp/q6afe.c
+++ b/dsp/q6afe.c
@@ -400,6 +400,11 @@
 	/* Set command specific details */
 	switch (opcode) {
 	case AFE_PORT_CMDRSP_GET_PARAM_V2:
+		if (payload_size < (5 * sizeof(uint32_t))) {
+			pr_err("%s: Error: size %d is less than expected\n",
+				__func__, payload_size);
+			return -EINVAL;
+		}
 		expected_size += sizeof(struct param_hdr_v1);
 		param_hdr.module_id = payload[1];
 		param_hdr.instance_id = INSTANCE_ID_0;
@@ -408,7 +413,17 @@
 		data_start = &payload[4];
 		break;
 	case AFE_PORT_CMDRSP_GET_PARAM_V3:
+		if (payload_size < (6 * sizeof(uint32_t))) {
+			pr_err("%s: Error: size %d is less than expected\n",
+				__func__, payload_size);
+			return -EINVAL;
+		}
 		expected_size += sizeof(struct param_hdr_v3);
+		if (payload_size < expected_size) {
+			pr_err("%s: Error: size %d is less than expected\n",
+				__func__, payload_size);
+			return -EINVAL;
+		}
 		memcpy(&param_hdr, &payload[1], sizeof(struct param_hdr_v3));
 		data_start = &payload[5];
 		break;
@@ -597,6 +612,7 @@
 	    data->opcode == AFE_PORT_CMDRSP_GET_PARAM_V3) {
 		uint32_t *payload = data->payload;
 		uint32_t param_id;
+		uint32_t param_id_pos = 0;
 
 		if (!payload || (data->token >= AFE_MAX_PORTS)) {
 			pr_err("%s: Error: size %d payload %pK token %d\n",
@@ -605,9 +621,23 @@
 			return -EINVAL;
 		}
 
-		param_id = (data->opcode == AFE_PORT_CMDRSP_GET_PARAM_V3) ?
-				   payload[3] :
-				   payload[2];
+		if (rtac_make_afe_callback(data->payload,
+					   data->payload_size))
+			return 0;
+
+		if (data->opcode == AFE_PORT_CMDRSP_GET_PARAM_V3)
+			param_id_pos = 4;
+		else
+			param_id_pos = 3;
+
+		if (data->payload_size >= param_id_pos * sizeof(uint32_t))
+				param_id = payload[param_id_pos - 1];
+		else {
+			pr_err("%s: Error: size %d is less than expected\n",
+				__func__, data->payload_size);
+			return -EINVAL;
+		}
+
 		if (param_id == AUDPROC_PARAM_ID_FFV_DOA_TRACKING_MONITOR) {
 			doa_tracking_mon_afe_cb_handler(data->opcode,
 				data->payload, data->payload_size);
@@ -615,10 +645,6 @@
 			av_dev_drift_afe_cb_handler(data->opcode, data->payload,
 						    data->payload_size);
 		} else {
-			if (rtac_make_afe_callback(data->payload,
-						   data->payload_size))
-				return 0;
-
 			if (sp_make_afe_callback(data->opcode, data->payload,
 						 data->payload_size))
 				return -EINVAL;
@@ -645,6 +671,11 @@
 
 		payload = data->payload;
 		if (data->opcode == APR_BASIC_RSP_RESULT) {
+			if (data->payload_size < (2 * sizeof(uint32_t))) {
+				pr_err("%s: Error: size %d is less than expected\n",
+					__func__, data->payload_size);
+				return -EINVAL;
+			}
 			pr_debug("%s:opcode = 0x%x cmd = 0x%x status = 0x%x token=%d\n",
 				__func__, data->opcode,
 				payload[0], payload[1], data->token);
diff --git a/dsp/q6core.c b/dsp/q6core.c
index 283f785..3f15f10 100644
--- a/dsp/q6core.c
+++ b/dsp/q6core.c
@@ -194,7 +194,7 @@
 }
 EXPORT_SYMBOL(q6core_send_uevent);
 
-static int parse_fwk_version_info(uint32_t *payload)
+static int parse_fwk_version_info(uint32_t *payload, uint16_t payload_size)
 {
 	size_t ver_size;
 	int num_services;
@@ -207,6 +207,11 @@
 	 * Based on this info, we copy the payload into core
 	 * avcs version info structure.
 	 */
+	if (payload_size < 5 * sizeof(uint32_t)) {
+		pr_err("%s: payload has invalid size %d\n",
+			__func__, payload_size);
+		return -EINVAL;
+	}
 	num_services = payload[4];
 	if (num_services > VSS_MAX_AVCS_NUM_SERVICES) {
 		pr_err("%s: num_services: %d greater than max services: %d\n",
@@ -221,6 +226,12 @@
 	ver_size = sizeof(struct avcs_get_fwk_version) +
 		   num_services * sizeof(struct avs_svc_api_info);
 
+	if (payload_size < ver_size) {
+		pr_err("%s: payload has invalid size %d, expected size %zu\n",
+			__func__, payload_size, ver_size);
+		return -EINVAL;
+	}
+
 	q6core_lcl.q6core_avcs_ver_info.ver_info =
 		kzalloc(ver_size, GFP_ATOMIC);
 	if (q6core_lcl.q6core_avcs_ver_info.ver_info == NULL)
@@ -257,6 +268,12 @@
 
 		payload1 = data->payload;
 
+		if (data->payload_size < 2 * sizeof(uint32_t)) {
+			pr_err("%s: payload has invalid size %d\n",
+				__func__, data->payload_size);
+			return -EINVAL;
+		}
+
 		switch (payload1[0]) {
 
 		case AVCS_CMD_SHARED_MEM_UNMAP_REGIONS:
@@ -347,6 +364,11 @@
 		break;
 	}
 	case AVCS_CMDRSP_SHARED_MEM_MAP_REGIONS:
+		if (data->payload_size < sizeof(uint32_t)) {
+			pr_err("%s: payload has invalid size %d\n",
+				__func__, data->payload_size);
+			return -EINVAL;
+		}
 		payload1 = data->payload;
 		pr_debug("%s: AVCS_CMDRSP_SHARED_MEM_MAP_REGIONS handle %d\n",
 			__func__, payload1[0]);
@@ -361,6 +383,11 @@
 		}
 		break;
 	case AVCS_CMDRSP_CREATE_LPASS_NPA_CLIENT:
+		if (data->payload_size < 2 * sizeof(uint32_t)) {
+			pr_err("%s: payload has invalid size %d\n",
+				__func__, data->payload_size);
+			return -EINVAL;
+		}
 		payload1 = data->payload;
 		pr_debug("%s: AVCS_CMDRSP_CREATE_LPASS_NPA_CLIENT handle %d\n",
 			__func__, payload1[1]);
@@ -370,6 +397,11 @@
 		wake_up(&q6core_lcl.lpass_npa_rsc_wait);
 		break;
 	case AVCS_CMDRSP_ADSP_EVENT_GET_STATE:
+		if (data->payload_size < sizeof(uint32_t)) {
+			pr_err("%s: payload has invalid size %d\n",
+				__func__, data->payload_size);
+			return -EINVAL;
+		}
 		payload1 = data->payload;
 		q6core_lcl.param = payload1[0];
 		pr_debug("%s: Received ADSP get state response 0x%x\n",
@@ -380,6 +412,11 @@
 		wake_up(&q6core_lcl.bus_bw_req_wait);
 		break;
 	case AVCS_CMDRSP_GET_LICENSE_VALIDATION_RESULT:
+		if (data->payload_size < sizeof(uint32_t)) {
+			pr_err("%s: payload has invalid size %d\n",
+				__func__, data->payload_size);
+			return -EINVAL;
+		}
 		payload1 = data->payload;
 		pr_debug("%s: cmd = LICENSE_VALIDATION_RESULT, result = 0x%x\n",
 				__func__, payload1[0]);
@@ -392,7 +429,7 @@
 		pr_debug("%s: Received AVCS_CMDRSP_GET_FWK_VERSION\n",
 			 __func__);
 		payload1 = data->payload;
-		ret = parse_fwk_version_info(payload1);
+		ret = parse_fwk_version_info(payload1, data->payload_size);
 		if (ret < 0) {
 			q6core_lcl.adsp_status = ret;
 			pr_err("%s: Failed to parse payload:%d\n",
diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c
index 8d82ff1..bddf30a 100644
--- a/soc/swr-mstr-ctrl.c
+++ b/soc/swr-mstr-ctrl.c
@@ -1441,6 +1441,8 @@
 	}
 
 	mutex_lock(&swrm->reslock);
+	if (swrm->lpass_core_hw_vote)
+		clk_prepare_enable(swrm->lpass_core_hw_vote);
 	swrm_clk_request(swrm, true);
 	mutex_unlock(&swrm->reslock);
 
@@ -1608,6 +1610,8 @@
 
 	mutex_lock(&swrm->reslock);
 	swrm_clk_request(swrm, false);
+	if (swrm->lpass_core_hw_vote)
+		clk_disable_unprepare(swrm->lpass_core_hw_vote);
 	mutex_unlock(&swrm->reslock);
 	swrm_unlock_sleep(swrm);
 	return ret;
@@ -1897,6 +1901,7 @@
 	u32 i, num_ports, port_num, port_type, ch_mask;
 	u32 *temp, map_size, map_length, ch_iter = 0, old_port_num = 0;
 	int ret = 0;
+	struct clk *lpass_core_hw_vote = NULL;
 
 	/* Allocate soundwire master driver structure */
 	swrm = devm_kzalloc(&pdev->dev, sizeof(struct swr_mstr_ctrl),
@@ -2055,6 +2060,7 @@
 	swrm->slave_status = 0;
 	swrm->num_rx_chs = 0;
 	swrm->clk_ref_count = 0;
+	swrm->swr_irq_wakeup_capable = 0;
 	swrm->mclk_freq = MCLK_FREQ;
 	swrm->dev_up = true;
 	swrm->state = SWR_MSTR_UP;
@@ -2107,7 +2113,15 @@
 		}
 
 	}
-
+	/* Make inband tx interrupts as wakeup capable for slave irq */
+	ret = of_property_read_u32(pdev->dev.of_node,
+				   "qcom,swr-mstr-irq-wakeup-capable",
+				   &swrm->swr_irq_wakeup_capable);
+	if (ret)
+		dev_dbg(swrm->dev, "%s: swrm irq wakeup capable not defined\n",
+			__func__);
+	if (swrm->swr_irq_wakeup_capable)
+		irq_set_irq_wake(swrm->irq, 1);
 	ret = swr_register_master(&swrm->master);
 	if (ret) {
 		dev_err(&pdev->dev, "%s: error adding swr master\n", __func__);
@@ -2136,6 +2150,17 @@
 	if (pdev->dev.of_node)
 		of_register_swr_devices(&swrm->master);
 
+	/* Register LPASS core hw vote */
+	lpass_core_hw_vote = devm_clk_get(&pdev->dev, "lpass_core_hw_vote");
+	if (IS_ERR(lpass_core_hw_vote)) {
+		ret = PTR_ERR(lpass_core_hw_vote);
+		dev_dbg(&pdev->dev, "%s: clk get %s failed %d\n",
+			__func__, "lpass_core_hw_vote", ret);
+		lpass_core_hw_vote = NULL;
+		ret = 0;
+	}
+	swrm->lpass_core_hw_vote = lpass_core_hw_vote;
+
 	dbgswrm = swrm;
 	debugfs_swrm_dent = debugfs_create_dir(dev_name(&pdev->dev), 0);
 	if (!IS_ERR(debugfs_swrm_dent)) {
@@ -2152,6 +2177,13 @@
 				   (void *) "swrm_reg_dump",
 				   &swrm_debug_ops);
 	}
+
+	ret = device_init_wakeup(swrm->dev, true);
+	if (ret) {
+		dev_err(swrm->dev, "Device wakeup init failed: %d\n", ret);
+		goto err_irq_wakeup_fail;
+	}
+
 	pm_runtime_set_autosuspend_delay(&pdev->dev, auto_suspend_timer);
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_set_active(&pdev->dev);
@@ -2163,6 +2195,8 @@
 	msm_aud_evt_register_client(&swrm->event_notifier);
 
 	return 0;
+err_irq_wakeup_fail:
+	device_init_wakeup(swrm->dev, false);
 err_mstr_fail:
 	if (swrm->reg_irq)
 		swrm->reg_irq(swrm->handle, swr_mstr_interrupt,
@@ -2194,11 +2228,14 @@
 		free_irq(swrm->irq, swrm);
 	else if (swrm->wake_irq > 0)
 		free_irq(swrm->wake_irq, swrm);
+	if (swrm->swr_irq_wakeup_capable)
+		irq_set_irq_wake(swrm->irq, 0);
 	cancel_work_sync(&swrm->wakeup_work);
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
 	swr_unregister_master(&swrm->master);
 	msm_aud_evt_unregister_client(&swrm->event_notifier);
+	device_init_wakeup(swrm->dev, false);
 	mutex_destroy(&swrm->mlock);
 	mutex_destroy(&swrm->reslock);
 	mutex_destroy(&swrm->iolock);
@@ -2236,6 +2273,12 @@
 		__func__, swrm->state);
 	mutex_lock(&swrm->reslock);
 
+	if (swrm->lpass_core_hw_vote)
+		ret = clk_prepare_enable(swrm->lpass_core_hw_vote);
+		if (ret < 0)
+			dev_err(dev, "%s:lpass core hw enable failed\n",
+				__func__);
+
 	if ((swrm->state == SWR_MSTR_DOWN) ||
 	    (swrm->state == SWR_MSTR_SSR && swrm->dev_up)) {
 		if (swrm->clk_stop_mode0_supp) {
@@ -2272,6 +2315,8 @@
 		swrm->state = SWR_MSTR_UP;
 	}
 exit:
+	if (swrm->lpass_core_hw_vote)
+		clk_disable_unprepare(swrm->lpass_core_hw_vote);
 	pm_runtime_set_autosuspend_delay(&pdev->dev, auto_suspend_timer);
 	mutex_unlock(&swrm->reslock);
 	return ret;
@@ -2292,6 +2337,12 @@
 	mutex_lock(&swrm->force_down_lock);
 	current_state = swrm->state;
 	mutex_unlock(&swrm->force_down_lock);
+	if (swrm->lpass_core_hw_vote)
+		ret = clk_prepare_enable(swrm->lpass_core_hw_vote);
+		if (ret < 0)
+			dev_err(dev, "%s:lpass core hw enable failed\n",
+				__func__);
+
 	if ((current_state == SWR_MSTR_UP) ||
 	    (current_state == SWR_MSTR_SSR)) {
 
@@ -2337,6 +2388,8 @@
 	if (current_state != SWR_MSTR_SSR)
 		swrm->state = SWR_MSTR_DOWN;
 exit:
+	if (swrm->lpass_core_hw_vote)
+		clk_disable_unprepare(swrm->lpass_core_hw_vote);
 	mutex_unlock(&swrm->reslock);
 	return ret;
 }
diff --git a/soc/swr-mstr-ctrl.h b/soc/swr-mstr-ctrl.h
index fab66c3..4a48571 100644
--- a/soc/swr-mstr-ctrl.h
+++ b/soc/swr-mstr-ctrl.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _SWR_WCD_CTRL_H
@@ -154,7 +154,9 @@
 	int wlock_holders;
 	u32 intr_mask;
 	struct port_params **port_param;
+	struct clk *lpass_core_hw_vote;
 	u8 num_usecase;
+	u32 swr_irq_wakeup_capable;
 };
 
 #endif /* _SWR_WCD_CTRL_H */