Merge "ASoC: Update routing driver for FFV and AFE Loopback"
diff --git a/asoc/codecs/sdm660_cdc/msm-digital-cdc.c b/asoc/codecs/sdm660_cdc/msm-digital-cdc.c
index f1f1ed4..8519e67 100644
--- a/asoc/codecs/sdm660_cdc/msm-digital-cdc.c
+++ b/asoc/codecs/sdm660_cdc/msm-digital-cdc.c
@@ -1391,7 +1391,21 @@
 	atomic_set(&msm_dig_cdc->on_demand_list[ON_DEMAND_DIGITAL].ref, 0);
 
 	registered_digcodec = codec;
+	if (msm_dig_cdc->no_analog_codec) {
+		msm_dig_cdc->fw_data = devm_kzalloc(codec->dev,
+					    sizeof(*(msm_dig_cdc->fw_data)),
+					    GFP_KERNEL);
+		if (!msm_dig_cdc->fw_data)
+			return -ENOMEM;
 
+		ret = wcd_cal_create_hwdep(msm_dig_cdc->fw_data,
+			WCD9XXX_CODEC_HWDEP_NODE, codec);
+		if (ret < 0) {
+			dev_err(codec->dev, "%s hwdep failed %d\n", __func__,
+				ret);
+			return ret;
+		}
+	}
 	snd_soc_dapm_ignore_suspend(dapm, "AIF1 Playback");
 	snd_soc_dapm_ignore_suspend(dapm, "AIF1 Capture");
 	snd_soc_dapm_ignore_suspend(dapm, "ADC1_IN");
@@ -2469,7 +2483,6 @@
 	u32 dig_cdc_addr;
 	struct msm_dig_priv *msm_dig_cdc;
 	struct dig_ctrl_platform_data *pdata = NULL;
-	bool no_analog_codec = false;
 	int adsp_state;
 
 	adsp_state = apr_get_subsys_state();
@@ -2491,10 +2504,11 @@
 		return -EINVAL;
 
 	if (pdev->dev.of_node)
-		no_analog_codec = of_property_read_bool(pdev->dev.of_node,
+		msm_dig_cdc->no_analog_codec = of_property_read_bool(
+					pdev->dev.of_node,
 					"qcom,no-analog-codec");
 
-	if (no_analog_codec) {
+	if (msm_dig_cdc->no_analog_codec) {
 		dev_dbg(&pdev->dev, "%s:Platform data from device tree\n",
 				__func__);
 		if (msm_digital_cdc_populate_dt_pdata(&pdev->dev,
@@ -2549,7 +2563,7 @@
 			__func__, dig_cdc_addr);
 	return ret;
 err_supplies:
-	if (no_analog_codec)
+	if (msm_dig_cdc->no_analog_codec)
 		msm_digital_cdc_disable_supplies(msm_dig_cdc);
 rtn:
 	return ret;
diff --git a/asoc/codecs/sdm660_cdc/msm-digital-cdc.h b/asoc/codecs/sdm660_cdc/msm-digital-cdc.h
index a841a09..f230cac 100644
--- a/asoc/codecs/sdm660_cdc/msm-digital-cdc.h
+++ b/asoc/codecs/sdm660_cdc/msm-digital-cdc.h
@@ -73,6 +73,9 @@
 	s32 dmic_3_4_clk_cnt;
 	bool dec_active[NUM_DECIMATORS];
 	int version;
+	/* cal info for codec */
+	struct fw_info *fw_data;
+	bool no_analog_codec;
 	/* Entry for version info */
 	struct snd_info_entry *entry;
 	struct snd_info_entry *version_entry;
diff --git a/asoc/codecs/wcd934x/wcd934x.c b/asoc/codecs/wcd934x/wcd934x.c
index 7ff8179..8a70ea3 100644
--- a/asoc/codecs/wcd934x/wcd934x.c
+++ b/asoc/codecs/wcd934x/wcd934x.c
@@ -8911,6 +8911,8 @@
 
 static void tavil_codec_power_gate_digital_core(struct tavil_priv *tavil)
 {
+	if (!tavil)
+		return;
 	mutex_lock(&tavil->power_lock);
 	dev_dbg(tavil->dev, "%s: Entering power gating function, %d\n",
 		__func__, tavil->power_active_ref);
diff --git a/asoc/msm-compress-q6-v2.c b/asoc/msm-compress-q6-v2.c
index f03433c..c98c1cf 100644
--- a/asoc/msm-compress-q6-v2.c
+++ b/asoc/msm-compress-q6-v2.c
@@ -540,7 +540,7 @@
 			__func__, ret);
 		return ret;
 	}
-	prtd->bytes_read += buffer_length;
+	prtd->bytes_read += buffer_length + prtd->ts_header_offset;
 	prtd->bytes_read_offset += buffer_length + prtd->ts_header_offset;
 	if (prtd->bytes_read_offset >= prtd->buffer_size)
 		prtd->bytes_read_offset -= prtd->buffer_size;
diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c
index 1c16ac9..826981d 100644
--- a/asoc/msm-pcm-routing-v2.c
+++ b/asoc/msm-pcm-routing-v2.c
@@ -2469,13 +2469,13 @@
 		lsm_port = ADM_LSM_PORT_ID;
 		break;
 	case 10:
-		lsm_port = AFE_PORT_ID_PRIMARY_TDM_TX_2;
+		lsm_port = AFE_PORT_ID_INT3_MI2S_TX;
 		break;
 	case 11:
-		lsm_port = AFE_PORT_ID_PRIMARY_TDM_TX_3;
+		lsm_port = AFE_PORT_ID_PRIMARY_TDM_TX_2;
 		break;
 	case 12:
-		lsm_port = AFE_PORT_ID_INT3_MI2S_TX;
+		lsm_port = AFE_PORT_ID_PRIMARY_TDM_TX_3;
 		break;
 	default:
 		pr_err("Default lsm port");
@@ -12315,6 +12315,9 @@
 	} else if (!strcmp(kcontrol->id.name + strlen(prefix),
 					"INT3_MI2S")) {
 		*port_id = AFE_PORT_ID_INT3_MI2S_TX;
+	} else if (!strcmp(kcontrol->id.name + strlen(prefix),
+					"PRIMARY_TDM")) {
+		*port_id = AFE_PORT_ID_PRIMARY_TDM_TX;
 	} else {
 		pr_err("%s: mixer ctl name=%s, could not derive valid port id\n",
 			__func__, kcontrol->id.name);
@@ -12549,6 +12552,21 @@
 		.info	= msm_source_tracking_info,
 		.get	= msm_audio_source_tracking_get,
 	},
+	{
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+		.iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name   = "Sound Focus Audio Tx PRIMARY_TDM",
+		.info   = msm_sound_focus_info,
+		.get    = msm_audio_sound_focus_get,
+		.put    = msm_audio_sound_focus_put,
+	},
+	{
+		.access = SNDRV_CTL_ELEM_ACCESS_READ,
+		.iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name   = "Source Tracking Audio Tx PRIMARY_TDM",
+		.info   = msm_source_tracking_info,
+		.get    = msm_audio_source_tracking_get,
+	},
 };
 
 static int spkr_prot_put_vi_lch_port(struct snd_kcontrol *kcontrol,
diff --git a/asoc/sdm660-external.c b/asoc/sdm660-external.c
index 8ff98ed..91accff 100644
--- a/asoc/sdm660-external.c
+++ b/asoc/sdm660-external.c
@@ -124,7 +124,12 @@
 static char const *bt_sample_rate_text[] = {"KHZ_8", "KHZ_16",
 					"KHZ_44P1", "KHZ_48",
 					"KHZ_88P2", "KHZ_96"};
-
+static char const *bt_sample_rate_rx_text[] = {"KHZ_8", "KHZ_16",
+					"KHZ_44P1", "KHZ_48",
+					"KHZ_88P2", "KHZ_96"};
+static char const *bt_sample_rate_tx_text[] = {"KHZ_8", "KHZ_16",
+					"KHZ_44P1", "KHZ_48",
+					"KHZ_88P2", "KHZ_96"};
 static SOC_ENUM_SINGLE_EXT_DECL(spk_func_en, spk_function_text);
 static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_chs, slim_rx_ch_text);
 static SOC_ENUM_SINGLE_EXT_DECL(slim_2_rx_chs, slim_rx_ch_text);
@@ -143,6 +148,8 @@
 static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_sample_rate, slim_sample_rate_text);
 static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_sample_rate, slim_sample_rate_text);
 static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate, bt_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate_rx, bt_sample_rate_rx_text);
+static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate_tx, bt_sample_rate_tx_text);
 
 static int slim_get_sample_rate_val(int sample_rate)
 {
@@ -379,6 +386,130 @@
 	return 0;
 }
 
+static int msm_bt_sample_rate_rx_get(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	switch (slim_rx_cfg[SLIM_RX_7].sample_rate) {
+	case SAMPLING_RATE_96KHZ:
+		ucontrol->value.integer.value[0] = 5;
+		break;
+	case SAMPLING_RATE_88P2KHZ:
+		ucontrol->value.integer.value[0] = 4;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		ucontrol->value.integer.value[0] = 3;
+		break;
+	case SAMPLING_RATE_44P1KHZ:
+		ucontrol->value.integer.value[0] = 2;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		ucontrol->value.integer.value[0] = 1;
+		break;
+	case SAMPLING_RATE_8KHZ:
+	default:
+		ucontrol->value.integer.value[0] = 0;
+		break;
+	}
+	pr_debug("%s: sample rate = %d", __func__,
+		 slim_rx_cfg[SLIM_RX_7].sample_rate);
+
+	return 0;
+}
+
+static int msm_bt_sample_rate_rx_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	switch (ucontrol->value.integer.value[0]) {
+	case 1:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 2:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 3:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 4:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_88P2KHZ;
+		break;
+	case 5:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 0:
+	default:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	}
+	pr_debug("%s: sample rates: slim7_rx = %d, value = %d\n",
+		 __func__,
+		 slim_rx_cfg[SLIM_RX_7].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_bt_sample_rate_tx_get(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	switch (slim_tx_cfg[SLIM_TX_7].sample_rate) {
+	case SAMPLING_RATE_96KHZ:
+		ucontrol->value.integer.value[0] = 5;
+		break;
+	case SAMPLING_RATE_88P2KHZ:
+		ucontrol->value.integer.value[0] = 4;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		ucontrol->value.integer.value[0] = 3;
+		break;
+	case SAMPLING_RATE_44P1KHZ:
+		ucontrol->value.integer.value[0] = 2;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		ucontrol->value.integer.value[0] = 1;
+		break;
+	case SAMPLING_RATE_8KHZ:
+	default:
+		ucontrol->value.integer.value[0] = 0;
+		break;
+	}
+	pr_debug("%s: sample rate = %d", __func__,
+		 slim_tx_cfg[SLIM_TX_7].sample_rate);
+
+	return 0;
+}
+
+static int msm_bt_sample_rate_tx_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	switch (ucontrol->value.integer.value[0]) {
+	case 1:
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 2:
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 3:
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 4:
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_88P2KHZ;
+		break;
+	case 5:
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 0:
+	default:
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	}
+	pr_debug("%s: sample rates: slim7_tx = %d, value = %d\n",
+		 __func__,
+		 slim_tx_cfg[SLIM_TX_7].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
 static int slim_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
 				   struct snd_ctl_elem_value *ucontrol)
 {
@@ -750,6 +881,12 @@
 	SOC_ENUM_EXT("BT SampleRate", bt_sample_rate,
 			msm_bt_sample_rate_get,
 			msm_bt_sample_rate_put),
+	SOC_ENUM_EXT("BT SampleRate RX", bt_sample_rate_rx,
+			msm_bt_sample_rate_rx_get,
+			msm_bt_sample_rate_rx_put),
+	SOC_ENUM_EXT("BT SampleRate TX", bt_sample_rate_tx,
+			msm_bt_sample_rate_tx_get,
+			msm_bt_sample_rate_tx_put),
 };
 
 static int msm_slim_get_ch_from_beid(int32_t id)
diff --git a/dsp/q6lsm.c b/dsp/q6lsm.c
index d03f24c..a702661 100644
--- a/dsp/q6lsm.c
+++ b/dsp/q6lsm.c
@@ -78,6 +78,7 @@
 	uint32_t param_id;
 };
 
+static DEFINE_MUTEX(session_lock);
 static struct lsm_common lsm_common;
 /*
  * mmap_handle_p can point either client->sound_model.mem_map_handle or
@@ -130,6 +131,24 @@
 	}
 }
 
+static int q6lsm_get_session_id_from_lsm_client(struct lsm_client *client)
+{
+	int n;
+
+	for (n = LSM_MIN_SESSION_ID; n <= LSM_MAX_SESSION_ID; n++) {
+		if (lsm_session[n] == client)
+			return n;
+	}
+	pr_err("%s: cannot find matching lsm client. client = %pa\n",
+		__func__, client);
+	return LSM_INVALID_SESSION_ID;
+}
+
+static bool q6lsm_is_valid_lsm_client(struct lsm_client *client)
+{
+	return q6lsm_get_session_id_from_lsm_client(client) ? 1 : 0;
+}
+
 static int q6lsm_callback(struct apr_client_data *data, void *priv)
 {
 	struct lsm_client *client = (struct lsm_client *)priv;
@@ -148,6 +167,13 @@
 			 __func__, data->opcode, data->reset_event,
 			 data->reset_proc);
 
+		mutex_lock(&session_lock);
+		if (!client || !q6lsm_is_valid_lsm_client(client)) {
+			pr_err("%s: client already freed/invalid, return\n",
+				__func__);
+			mutex_unlock(&session_lock);
+			return 0;
+		}
 		apr_reset(client->apr);
 		client->apr = NULL;
 		atomic_set(&client->cmd_state, CMD_STATE_CLEARED);
@@ -157,6 +183,7 @@
 		mutex_lock(&lsm_common.cal_data[LSM_CUSTOM_TOP_IDX]->lock);
 		lsm_common.set_custom_topology = 1;
 		mutex_unlock(&lsm_common.cal_data[LSM_CUSTOM_TOP_IDX]->lock);
+		mutex_unlock(&session_lock);
 		return 0;
 	}
 
@@ -369,6 +396,7 @@
 		pr_err("%s: Invalid Session %d\n", __func__, client->session);
 		return;
 	}
+	mutex_lock(&session_lock);
 	apr_deregister(client->apr);
 	client->mmap_apr = NULL;
 	q6lsm_session_free(client);
@@ -376,6 +404,7 @@
 	mutex_destroy(&client->cmd_lock);
 	kfree(client);
 	client = NULL;
+	mutex_unlock(&session_lock);
 }
 EXPORT_SYMBOL(q6lsm_client_free);