asoc: sm6150: Add support for tasha snd card variants

Add DAI links and sound card registration support
for tasha sound card variants.

Change-Id: If93dc1dae2f10f9ac6b8e2e80a9e38cadc14289b
Signed-off-by: Aditya Bavanari <abavanar@codeaurora.org>
This commit is contained in:
Aditya Bavanari 2019-01-11 20:18:55 +05:30 committed by Meng Wang
parent 2b5cb6ac75
commit 45e2e65529

View File

@ -29,6 +29,7 @@
#include "msm-pcm-routing-v2.h"
#include <asoc/msm-cdc-pinctrl.h>
#include "codecs/wcd934x/wcd934x.h"
#include "codecs/wcd9335.h"
#include "codecs/wcd934x/wcd934x-mbhc.h"
#include "codecs/wcd937x/wcd937x-mbhc.h"
#include "codecs/wsa881x.h"
@ -204,6 +205,8 @@ struct msm_asoc_mach_data {
struct snd_info_entry *codec_root;
int usbc_en2_gpio; /* used by gpio driver API */
struct device_node *mi2s_gpio_p[MI2S_MAX]; /* used by pinctrl API */
int hph_en1_gpio;
int hph_en0_gpio;
struct device_node *dmic01_gpio_p; /* used by pinctrl API */
struct device_node *dmic23_gpio_p; /* used by pinctrl API */
struct device_node *us_euro_gpio_p; /* used by pinctrl API */
@ -659,7 +662,7 @@ static struct wcd_mbhc_config wcd_mbhc_cfg = {
.enable_anc_mic_detect = false,
};
static struct snd_soc_dapm_route wcd_audio_paths_tavil[] = {
static struct snd_soc_dapm_route wcd_audio_paths[] = {
{"MIC BIAS1", NULL, "MCLK TX"},
{"MIC BIAS2", NULL, "MCLK TX"},
{"MIC BIAS3", NULL, "MCLK TX"},
@ -3578,7 +3581,7 @@ static const struct snd_kcontrol_new msm_int_snd_controls[] = {
cdc_dma_tx_sample_rate_put),
};
static const struct snd_kcontrol_new msm_tavil_snd_controls[] = {
static const struct snd_kcontrol_new msm_ext_snd_controls[] = {
SOC_ENUM_EXT("SLIM_0_RX Channels", slim_0_rx_chs,
slim_rx_ch_get, slim_rx_ch_put),
SOC_ENUM_EXT("SLIM_2_RX Channels", slim_2_rx_chs,
@ -3867,6 +3870,8 @@ static int msm_snd_enable_codec_ext_clk(struct snd_soc_component *component,
if (!strcmp(component->name, "tavil_codec")) {
ret = tavil_cdc_mclk_enable(component, enable);
} else if (!strcmp(dev_name(component->dev), "tasha_codec")) {
ret = tasha_cdc_mclk_enable(component, enable, dapm);
} else {
dev_err(component->dev, "%s: unknown codec to enable ext clk\n",
__func__);
@ -3882,6 +3887,8 @@ static int msm_snd_enable_codec_ext_tx_clk(struct snd_soc_component *component,
if (!strcmp(component->name, "tavil_codec")) {
ret = tavil_cdc_mclk_tx_enable(component, enable);
} else if (!strcmp(dev_name(component->dev), "tasha_codec")) {
ret = tasha_cdc_mclk_tx_enable(component, enable, dapm);
} else {
dev_err(component->dev, "%s: unknown codec to enable TX ext clk\n",
__func__);
@ -3961,7 +3968,7 @@ static int msm_hifi_ctrl_event(struct snd_soc_dapm_widget *w,
return 0;
}
static const struct snd_soc_dapm_widget msm_dapm_widgets_tavil[] = {
static const struct snd_soc_dapm_widget msm_ext_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
msm_mclk_event,
@ -3972,12 +3979,19 @@ static const struct snd_soc_dapm_widget msm_dapm_widgets_tavil[] = {
SND_SOC_DAPM_SPK("Lineout_1 amp", NULL),
SND_SOC_DAPM_SPK("Lineout_2 amp", NULL),
SND_SOC_DAPM_SPK("Lineout_3 amp", NULL),
SND_SOC_DAPM_SPK("Lineout_4 amp", NULL),
SND_SOC_DAPM_SPK("hifi amp", msm_hifi_ctrl_event),
SND_SOC_DAPM_MIC("Handset Mic", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_MIC("Secondary Mic", NULL),
SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
SND_SOC_DAPM_MIC("Analog Mic4", NULL),
SND_SOC_DAPM_MIC("Analog Mic5", NULL),
SND_SOC_DAPM_MIC("Analog Mic6", NULL),
SND_SOC_DAPM_MIC("Analog Mic7", NULL),
SND_SOC_DAPM_MIC("Analog Mic8", NULL),
SND_SOC_DAPM_MIC("Digital Mic0", NULL),
SND_SOC_DAPM_MIC("Digital Mic1", NULL),
@ -3985,6 +3999,7 @@ static const struct snd_soc_dapm_widget msm_dapm_widgets_tavil[] = {
SND_SOC_DAPM_MIC("Digital Mic3", NULL),
SND_SOC_DAPM_MIC("Digital Mic4", NULL),
SND_SOC_DAPM_MIC("Digital Mic5", NULL),
SND_SOC_DAPM_MIC("Digital Mic6", NULL),
};
static int msm_dmic_event(struct snd_soc_dapm_widget *w,
@ -4744,6 +4759,28 @@ static void msm_afe_clear_config(void)
afe_clear_config(AFE_SLIMBUS_SLAVE_CONFIG);
}
static int msm_config_hph_en0_gpio(struct snd_soc_component *component, bool high)
{
struct snd_soc_card *card = component->card;
struct msm_asoc_mach_data *pdata;
int val;
if (!card)
return 0;
pdata = snd_soc_card_get_drvdata(card);
if (!pdata || !gpio_is_valid(pdata->hph_en0_gpio))
return 0;
val = gpio_get_value_cansleep(pdata->hph_en0_gpio);
if ((!!val) == high)
return 0;
gpio_direction_output(pdata->hph_en0_gpio, (int)high);
return 1;
}
static int msm_audrx_tavil_init(struct snd_soc_pcm_runtime *rtd)
{
int ret = 0;
@ -4781,8 +4818,8 @@ static int msm_audrx_tavil_init(struct snd_soc_pcm_runtime *rtd)
}
dapm = snd_soc_component_get_dapm(component);
ret = snd_soc_add_component_controls(component, msm_tavil_snd_controls,
ARRAY_SIZE(msm_tavil_snd_controls));
ret = snd_soc_add_component_controls(component, msm_ext_snd_controls,
ARRAY_SIZE(msm_ext_snd_controls));
if (ret < 0) {
pr_err("%s: add_codec_controls failed, err %d\n",
__func__, ret);
@ -4797,11 +4834,11 @@ static int msm_audrx_tavil_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
snd_soc_dapm_new_controls(dapm, msm_dapm_widgets_tavil,
ARRAY_SIZE(msm_dapm_widgets_tavil));
snd_soc_dapm_new_controls(dapm, msm_ext_dapm_widgets,
ARRAY_SIZE(msm_ext_dapm_widgets));
snd_soc_dapm_add_routes(dapm, wcd_audio_paths_tavil,
ARRAY_SIZE(wcd_audio_paths_tavil));
snd_soc_dapm_add_routes(dapm, wcd_audio_paths,
ARRAY_SIZE(wcd_audio_paths));
snd_soc_dapm_ignore_suspend(dapm, "Handset Mic");
snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
@ -4892,6 +4929,183 @@ err:
return ret;
}
static int msm_audrx_tasha_init(struct snd_soc_pcm_runtime *rtd)
{
int ret = 0;
void *config_data;
struct snd_soc_component *component = NULL;
struct snd_soc_dapm_context *dapm;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_component *aux_comp;
struct snd_card *card;
struct snd_info_entry *entry;
struct msm_asoc_mach_data *pdata =
snd_soc_card_get_drvdata(rtd->card);
/* Codec SLIMBUS configuration
* RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8, RX9, RX10, RX11, RX12, RX13
* TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10, TX11, TX12, TX13
* TX14, TX15, TX16
*/
unsigned int rx_ch[TASHA_RX_MAX] = {144, 145, 146, 147, 148, 149, 150,
151, 152, 153, 154, 155, 156};
unsigned int tx_ch[TASHA_TX_MAX] = {128, 129, 130, 131, 132, 133,
134, 135, 136, 137, 138, 139,
140, 141, 142, 143};
pr_info("%s: dev_name:%s\n", __func__, dev_name(cpu_dai->dev));
rtd->pmdown_time = 0;
component = snd_soc_rtdcom_lookup(rtd, "tasha_codec");
if (!component) {
pr_err("%s: component is NULL\n", __func__);
return -EINVAL;
}
dapm = snd_soc_component_get_dapm(component);
ret = snd_soc_add_component_controls(component, msm_ext_snd_controls,
ARRAY_SIZE(msm_ext_snd_controls));
if (ret < 0) {
pr_err("%s: add_component_controls failed, err %d\n",
__func__, ret);
return ret;
}
ret = snd_soc_add_component_controls(component, msm_common_snd_controls,
ARRAY_SIZE(msm_common_snd_controls));
if (ret < 0) {
pr_err("%s: add_component_controls failed, err %d\n",
__func__, ret);
return ret;
}
snd_soc_dapm_new_controls(dapm, msm_ext_dapm_widgets,
ARRAY_SIZE(msm_ext_dapm_widgets));
snd_soc_dapm_add_routes(dapm, wcd_audio_paths,
ARRAY_SIZE(wcd_audio_paths));
snd_soc_dapm_enable_pin(dapm, "Lineout_1 amp");
snd_soc_dapm_enable_pin(dapm, "Lineout_2 amp");
snd_soc_dapm_enable_pin(dapm, "Lineout_3 amp");
snd_soc_dapm_enable_pin(dapm, "Lineout_4 amp");
snd_soc_dapm_ignore_suspend(dapm, "MADINPUT");
snd_soc_dapm_ignore_suspend(dapm, "MAD_CPE_INPUT");
snd_soc_dapm_ignore_suspend(dapm, "Handset Mic");
snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
snd_soc_dapm_ignore_suspend(dapm, "Secondary Mic");
snd_soc_dapm_ignore_suspend(dapm, "Lineout_1 amp");
snd_soc_dapm_ignore_suspend(dapm, "Lineout_2 amp");
snd_soc_dapm_ignore_suspend(dapm, "Lineout_3 amp");
snd_soc_dapm_ignore_suspend(dapm, "Lineout_4 amp");
snd_soc_dapm_ignore_suspend(dapm, "ANCRight Headset Mic");
snd_soc_dapm_ignore_suspend(dapm, "ANCLeft Headset Mic");
snd_soc_dapm_ignore_suspend(dapm, "Digital Mic0");
snd_soc_dapm_ignore_suspend(dapm, "Digital Mic1");
snd_soc_dapm_ignore_suspend(dapm, "Digital Mic2");
snd_soc_dapm_ignore_suspend(dapm, "Digital Mic3");
snd_soc_dapm_ignore_suspend(dapm, "Digital Mic4");
snd_soc_dapm_ignore_suspend(dapm, "Digital Mic5");
snd_soc_dapm_ignore_suspend(dapm, "Analog Mic4");
snd_soc_dapm_ignore_suspend(dapm, "Analog Mic6");
snd_soc_dapm_ignore_suspend(dapm, "Analog Mic7");
snd_soc_dapm_ignore_suspend(dapm, "Analog Mic8");
snd_soc_dapm_ignore_suspend(dapm, "EAR");
snd_soc_dapm_ignore_suspend(dapm, "LINEOUT1");
snd_soc_dapm_ignore_suspend(dapm, "LINEOUT2");
snd_soc_dapm_ignore_suspend(dapm, "AMIC1");
snd_soc_dapm_ignore_suspend(dapm, "AMIC2");
snd_soc_dapm_ignore_suspend(dapm, "AMIC3");
snd_soc_dapm_ignore_suspend(dapm, "AMIC4");
snd_soc_dapm_ignore_suspend(dapm, "AMIC5");
snd_soc_dapm_ignore_suspend(dapm, "DMIC0");
snd_soc_dapm_ignore_suspend(dapm, "DMIC1");
snd_soc_dapm_ignore_suspend(dapm, "DMIC2");
snd_soc_dapm_ignore_suspend(dapm, "DMIC3");
snd_soc_dapm_ignore_suspend(dapm, "DMIC4");
snd_soc_dapm_ignore_suspend(dapm, "DMIC5");
snd_soc_dapm_ignore_suspend(dapm, "ANC EAR");
snd_soc_dapm_ignore_suspend(dapm, "SPK1 OUT");
snd_soc_dapm_ignore_suspend(dapm, "SPK2 OUT");
snd_soc_dapm_ignore_suspend(dapm, "HPHL");
snd_soc_dapm_ignore_suspend(dapm, "HPHR");
snd_soc_dapm_ignore_suspend(dapm, "AIF4 VI");
snd_soc_dapm_ignore_suspend(dapm, "VIINPUT");
snd_soc_dapm_ignore_suspend(dapm, "LINEOUT3");
snd_soc_dapm_ignore_suspend(dapm, "LINEOUT4");
snd_soc_dapm_ignore_suspend(dapm, "ANC HPHL");
snd_soc_dapm_ignore_suspend(dapm, "ANC HPHR");
snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT1");
snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT2");
snd_soc_dapm_sync(dapm);
snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
msm_codec_fn.get_afe_config_fn = tasha_get_afe_config;
ret = msm_afe_set_config(component);
if (ret) {
pr_err("%s: Failed to set AFE config %d\n", __func__, ret);
goto err;
}
pdata->is_afe_config_done = true;
config_data = msm_codec_fn.get_afe_config_fn(component,
AFE_AANC_VERSION);
if (config_data) {
ret = afe_set_config(AFE_AANC_VERSION, config_data, 0);
if (ret) {
pr_err("%s: Failed to set aanc version %d\n",
__func__, ret);
goto err;
}
}
/*
* Send speaker configuration only for WSA8810.
* Default configuration is for WSA8815.
*/
pr_debug("%s: Number of aux devices: %d\n",
__func__, rtd->card->num_aux_devs);
if (rtd->card->num_aux_devs &&
!list_empty(&rtd->card->aux_comp_list)) {
aux_comp = list_first_entry(&rtd->card->aux_comp_list,
struct snd_soc_component, card_aux_list);
if (!strcmp(aux_comp->name, WSA8810_NAME_1) ||
!strcmp(aux_comp->name, WSA8810_NAME_2)) {
tasha_set_spkr_mode(component, SPKR_MODE_1);
tasha_set_spkr_gain_offset(component,
RX_GAIN_OFFSET_M1P5_DB);
}
}
card = rtd->card->snd_card;
entry = snd_info_create_subdir(card->module, "codecs",
card->proc_root);
if (!entry) {
pr_debug("%s: Cannot create codecs module entry\n",
__func__);
ret = 0;
goto err;
}
pdata->codec_root = entry;
tasha_codec_info_create_codec_entry(pdata->codec_root, component);
tasha_mbhc_zdet_gpio_ctrl(msm_config_hph_en0_gpio, component);
codec_reg_done = true;
return 0;
err:
return ret;
}
static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd)
{
int ret = 0;
@ -5297,6 +5511,48 @@ err:
return ret;
}
int msm_snd_cpe_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai_link *dai_link = rtd->dai_link;
int ret = 0;
u32 tx_ch[SLIM_MAX_TX_PORTS];
u32 tx_ch_cnt = 0;
if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) {
pr_err("%s: Invalid stream type %d\n",
__func__, substream->stream);
ret = -EINVAL;
goto end;
}
pr_debug("%s: %s_tx_dai_id_%d\n", __func__,
codec_dai->name, codec_dai->id);
ret = snd_soc_dai_get_channel_map(codec_dai,
&tx_ch_cnt, tx_ch, NULL, NULL);
if (ret < 0) {
pr_err("%s: failed to get codec chan map\n, err:%d\n",
__func__, ret);
goto end;
}
pr_debug("%s: tx_ch_cnt(%d) id %d\n",
__func__, tx_ch_cnt, dai_link->id);
ret = snd_soc_dai_set_channel_map(cpu_dai,
tx_ch_cnt, tx_ch, 0, 0);
if (ret < 0) {
pr_err("%s: failed to set cpu chan map, err:%d\n",
__func__, ret);
goto end;
}
end:
return ret;
}
static int msm_get_port_id(int be_id)
{
int afe_port_id;
@ -5780,6 +6036,9 @@ static struct snd_soc_ops msm_wcn_ops = {
.hw_params = msm_wcn_hw_params,
};
static struct snd_soc_ops msm_ext_cpe_ops = {
.hw_params = msm_snd_cpe_hw_params,
};
/* Digital audio interface glue - connects codec <---> CPU */
static struct snd_soc_dai_link msm_common_dai_links[] = {
@ -6382,7 +6641,6 @@ static struct snd_soc_dai_link msm_common_dai_links[] = {
},
};
static struct snd_soc_dai_link msm_tavil_fe_dai_links[] = {
{/* hw:x,37 */
.name = LPASS_BE_SLIMBUS_4_TX,
@ -6513,6 +6771,96 @@ static struct snd_soc_dai_link msm_bolero_fe_dai_links[] = {
},
};
static struct snd_soc_dai_link msm_tasha_fe_dai_links[] = {
/* tasha_vifeedback for speaker protection */
{
.name = LPASS_BE_SLIMBUS_4_TX,
.stream_name = "Slimbus4 Capture",
.cpu_dai_name = "msm-dai-q6-dev.16393",
.platform_name = "msm-pcm-hostless",
.codec_name = "tasha_codec",
.codec_dai_name = "tasha_vifeedback",
.id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
.be_hw_params_fixup = msm_be_hw_params_fixup,
.ops = &msm_be_ops,
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
.ignore_suspend = 1,
},
/* Ultrasound RX DAI Link */
{
.name = "SLIMBUS_2 Hostless Playback",
.stream_name = "SLIMBUS_2 Hostless Playback",
.cpu_dai_name = "msm-dai-q6-dev.16388",
.platform_name = "msm-pcm-hostless",
.codec_name = "tasha_codec",
.codec_dai_name = "tasha_rx2",
.ignore_suspend = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
.ignore_pmdown_time = 1,
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
.ops = &msm_slimbus_2_be_ops,
},
/* Ultrasound TX DAI Link */
{
.name = "SLIMBUS_2 Hostless Capture",
.stream_name = "SLIMBUS_2 Hostless Capture",
.cpu_dai_name = "msm-dai-q6-dev.16389",
.platform_name = "msm-pcm-hostless",
.codec_name = "tasha_codec",
.codec_dai_name = "tasha_tx2",
.ignore_suspend = 1,
.dpcm_capture = 1,
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
.ops = &msm_slimbus_2_be_ops,
},
/* CPE LSM direct dai-link */
{
.name = "CPE Listen service",
.stream_name = "CPE Listen Audio Service",
.cpu_dai_name = "msm-dai-slim",
.platform_name = "msm-cpe-lsm",
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST},
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
.ignore_suspend = 1,
.dpcm_capture = 1,
.codec_dai_name = "tasha_mad1",
.codec_name = "tasha_codec",
.ops = &msm_ext_cpe_ops,
},
{
.name = "SLIMBUS_6 Hostless Playback",
.stream_name = "SLIMBUS_6 Hostless",
.cpu_dai_name = "SLIMBUS6_HOSTLESS",
.platform_name = "msm-pcm-hostless",
.dynamic = 1,
.dpcm_playback = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST},
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
.ignore_suspend = 1,
/* this dailink has playback support */
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
},
/* CPE LSM EC PP direct dai-link */
{
.name = "CPE Listen service ECPP",
.stream_name = "CPE Listen Audio Service ECPP",
.cpu_dai_name = "CPE_LSM_NOHOST",
.platform_name = "msm-cpe-lsm.3",
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST},
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
.codec_dai_name = "tasha_cpe",
.codec_name = "tasha_codec",
},
};
static struct snd_soc_dai_link msm_common_misc_fe_dai_links[] = {
{
.name = MSM_DAILINK_NAME(ASM Loopback),
@ -6998,6 +7346,165 @@ static struct snd_soc_dai_link msm_tavil_be_dai_links[] = {
},
};
static struct snd_soc_dai_link msm_tasha_be_dai_links[] = {
/* Backend DAI Links */
{
.name = LPASS_BE_SLIMBUS_0_RX,
.stream_name = "Slimbus Playback",
.cpu_dai_name = "msm-dai-q6-dev.16384",
.platform_name = "msm-pcm-routing",
.codec_name = "tasha_codec",
.codec_dai_name = "tasha_mix_rx1",
.no_pcm = 1,
.dpcm_playback = 1,
.id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
.init = &msm_audrx_tasha_init,
.be_hw_params_fixup = msm_be_hw_params_fixup,
/* this dainlink has playback support */
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
.ops = &msm_be_ops,
},
{
.name = LPASS_BE_SLIMBUS_0_TX,
.stream_name = "Slimbus Capture",
.cpu_dai_name = "msm-dai-q6-dev.16385",
.platform_name = "msm-pcm-routing",
.codec_name = "tasha_codec",
.codec_dai_name = "tasha_tx1",
.no_pcm = 1,
.dpcm_capture = 1,
.id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
.be_hw_params_fixup = msm_be_hw_params_fixup,
.ignore_suspend = 1,
.ops = &msm_be_ops,
},
{
.name = LPASS_BE_SLIMBUS_1_RX,
.stream_name = "Slimbus1 Playback",
.cpu_dai_name = "msm-dai-q6-dev.16386",
.platform_name = "msm-pcm-routing",
.codec_name = "tasha_codec",
.codec_dai_name = "tasha_mix_rx1",
.no_pcm = 1,
.dpcm_playback = 1,
.id = MSM_BACKEND_DAI_SLIMBUS_1_RX,
.be_hw_params_fixup = msm_be_hw_params_fixup,
.ops = &msm_be_ops,
/* dai link has playback support */
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_SLIMBUS_1_TX,
.stream_name = "Slimbus1 Capture",
.cpu_dai_name = "msm-dai-q6-dev.16387",
.platform_name = "msm-pcm-routing",
.codec_name = "tasha_codec",
.codec_dai_name = "tasha_tx3",
.no_pcm = 1,
.dpcm_capture = 1,
.id = MSM_BACKEND_DAI_SLIMBUS_1_TX,
.be_hw_params_fixup = msm_be_hw_params_fixup,
.ops = &msm_be_ops,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_SLIMBUS_3_RX,
.stream_name = "Slimbus3 Playback",
.cpu_dai_name = "msm-dai-q6-dev.16390",
.platform_name = "msm-pcm-routing",
.codec_name = "tasha_codec",
.codec_dai_name = "tasha_mix_rx1",
.no_pcm = 1,
.dpcm_playback = 1,
.id = MSM_BACKEND_DAI_SLIMBUS_3_RX,
.be_hw_params_fixup = msm_be_hw_params_fixup,
.ops = &msm_be_ops,
/* dai link has playback support */
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_SLIMBUS_3_TX,
.stream_name = "Slimbus3 Capture",
.cpu_dai_name = "msm-dai-q6-dev.16391",
.platform_name = "msm-pcm-routing",
.codec_name = "tasha_codec",
.codec_dai_name = "tasha_tx1",
.no_pcm = 1,
.dpcm_capture = 1,
.dpcm_playback = 1,
.id = MSM_BACKEND_DAI_SLIMBUS_3_TX,
.be_hw_params_fixup = msm_be_hw_params_fixup,
.ops = &msm_be_ops,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_SLIMBUS_4_RX,
.stream_name = "Slimbus4 Playback",
.cpu_dai_name = "msm-dai-q6-dev.16392",
.platform_name = "msm-pcm-routing",
.codec_name = "tasha_codec",
.codec_dai_name = "tasha_mix_rx1",
.no_pcm = 1,
.dpcm_playback = 1,
.id = MSM_BACKEND_DAI_SLIMBUS_4_RX,
.be_hw_params_fixup = msm_be_hw_params_fixup,
.ops = &msm_be_ops,
/* dai link has playback support */
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_SLIMBUS_5_RX,
.stream_name = "Slimbus5 Playback",
.cpu_dai_name = "msm-dai-q6-dev.16394",
.platform_name = "msm-pcm-routing",
.codec_name = "tasha_codec",
.codec_dai_name = "tasha_rx3",
.no_pcm = 1,
.dpcm_playback = 1,
.id = MSM_BACKEND_DAI_SLIMBUS_5_RX,
.be_hw_params_fixup = msm_be_hw_params_fixup,
.ops = &msm_be_ops,
/* dai link has playback support */
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
},
/* MAD BE */
{
.name = LPASS_BE_SLIMBUS_5_TX,
.stream_name = "Slimbus5 Capture",
.cpu_dai_name = "msm-dai-q6-dev.16395",
.platform_name = "msm-pcm-routing",
.codec_name = "tasha_codec",
.codec_dai_name = "tasha_mad1",
.no_pcm = 1,
.dpcm_capture = 1,
.id = MSM_BACKEND_DAI_SLIMBUS_5_TX,
.be_hw_params_fixup = msm_be_hw_params_fixup,
.ops = &msm_be_ops,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_SLIMBUS_6_RX,
.stream_name = "Slimbus6 Playback",
.cpu_dai_name = "msm-dai-q6-dev.16396",
.platform_name = "msm-pcm-routing",
.codec_name = "tasha_codec",
.codec_dai_name = "tasha_rx4",
.no_pcm = 1,
.dpcm_playback = 1,
.id = MSM_BACKEND_DAI_SLIMBUS_6_RX,
.be_hw_params_fixup = msm_be_hw_params_fixup,
.ops = &msm_be_ops,
/* dai link has playback support */
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
},
};
static struct snd_soc_dai_link msm_wcn_be_dai_links[] = {
{
.name = LPASS_BE_SLIMBUS_7_RX,
@ -7519,10 +8026,12 @@ static struct snd_soc_dai_link msm_sm6150_dai_links[
ARRAY_SIZE(msm_common_dai_links) +
ARRAY_SIZE(msm_tavil_fe_dai_links) +
ARRAY_SIZE(msm_bolero_fe_dai_links) +
ARRAY_SIZE(msm_tasha_fe_dai_links) +
ARRAY_SIZE(msm_common_misc_fe_dai_links) +
ARRAY_SIZE(msm_int_compress_capture_dai) +
ARRAY_SIZE(msm_common_be_dai_links) +
ARRAY_SIZE(msm_tavil_be_dai_links) +
ARRAY_SIZE(msm_tasha_be_dai_links) +
ARRAY_SIZE(msm_wcn_be_dai_links) +
ARRAY_SIZE(ext_disp_be_dai_link) +
ARRAY_SIZE(msm_mi2s_be_dai_links) +
@ -7574,6 +8083,50 @@ err_pcm_runtime:
return ret;
}
static int msm_snd_card_tasha_late_probe(struct snd_soc_card *card)
{
const char *be_dl_name = LPASS_BE_SLIMBUS_0_RX;
struct snd_soc_pcm_runtime *rtd;
struct snd_soc_component *component;
int ret = 0;
void *mbhc_calibration;
rtd = snd_soc_get_pcm_runtime(card, be_dl_name);
if (!rtd) {
dev_err(card->dev,
"%s: snd_soc_get_pcm_runtime for %s failed!\n",
__func__, be_dl_name);
ret = -EINVAL;
goto err_pcm_runtime;
}
component = snd_soc_rtdcom_lookup(rtd, "tasha_codec");
if (!component) {
pr_err("%s: component is NULL\n", __func__);
ret = -EINVAL;
goto err_pcm_runtime;
}
mbhc_calibration = def_wcd_mbhc_cal();
if (!mbhc_calibration) {
ret = -ENOMEM;
goto err_mbhc_cal;
}
wcd_mbhc_cfg.calibration = mbhc_calibration;
ret = tasha_mbhc_hs_detect(component, &wcd_mbhc_cfg);
if (ret) {
dev_err(card->dev, "%s: mbhc hs detect failed, err:%d\n",
__func__, ret);
goto err_hs_detect;
}
return 0;
err_hs_detect:
kfree(mbhc_calibration);
err_mbhc_cal:
err_pcm_runtime:
return ret;
}
static int msm_populate_dai_link_component_of_node(
struct snd_soc_card *card)
@ -7667,8 +8220,8 @@ static int msm_audrx_stub_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_component *component =
snd_soc_rtdcom_lookup(rtd, "msm-stub-codec");
ret = snd_soc_add_component_controls(component, msm_tavil_snd_controls,
ARRAY_SIZE(msm_tavil_snd_controls));
ret = snd_soc_add_component_controls(component, msm_ext_snd_controls,
ARRAY_SIZE(msm_ext_snd_controls));
if (ret < 0) {
dev_err(component->dev,
"%s: add_codec_controls failed, err = %d\n",
@ -7798,6 +8351,7 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
u32 mi2s_audio_intf = 0, ext_disp_audio_intf = 0;
u32 wcn_btfm_intf = 0;
const struct of_device_id *match;
u32 tasha_codec = 0;
match = of_match_node(sm6150_asoc_machine_of_match, dev->of_node);
if (!match) {
@ -7822,22 +8376,33 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
rc = of_property_read_u32(dev->of_node, "qcom,tavil_codec",
&tavil_codec);
if (rc) {
if (rc)
dev_dbg(dev, "%s: No DT match for tavil codec\n",
__func__);
} else {
if (tavil_codec) {
card->late_probe =
msm_snd_card_tavil_late_probe;
memcpy(msm_sm6150_dai_links + total_links,
msm_tavil_fe_dai_links,
sizeof(msm_tavil_fe_dai_links));
total_links +=
ARRAY_SIZE(msm_tavil_fe_dai_links);
}
}
if (!tavil_codec) {
rc = of_property_read_u32(dev->of_node, "qcom,tasha_codec",
&tasha_codec);
if (rc)
dev_dbg(dev, "%s: No DT match for tasha codec\n",
__func__);
if (tavil_codec) {
card->late_probe =
msm_snd_card_tavil_late_probe;
memcpy(msm_sm6150_dai_links + total_links,
msm_tavil_fe_dai_links,
sizeof(msm_tavil_fe_dai_links));
total_links +=
ARRAY_SIZE(msm_tavil_fe_dai_links);
} else if (tasha_codec) {
card->late_probe =
msm_snd_card_tasha_late_probe;
memcpy(msm_sm6150_dai_links + total_links,
msm_tasha_fe_dai_links,
sizeof(msm_tasha_fe_dai_links));
total_links +=
ARRAY_SIZE(msm_tasha_fe_dai_links);
} else {
memcpy(msm_sm6150_dai_links + total_links,
msm_bolero_fe_dai_links,
sizeof(msm_bolero_fe_dai_links));
@ -7862,6 +8427,11 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
msm_tavil_be_dai_links,
sizeof(msm_tavil_be_dai_links));
total_links += ARRAY_SIZE(msm_tavil_be_dai_links);
} else if (tasha_codec) {
memcpy(msm_sm6150_dai_links + total_links,
msm_tasha_be_dai_links,
sizeof(msm_tasha_be_dai_links));
total_links += ARRAY_SIZE(msm_tasha_be_dai_links);
} else {
memcpy(msm_sm6150_dai_links + total_links,
msm_wsa_cdc_dma_be_dai_links,
@ -8196,7 +8766,8 @@ static int msm_init_aux_dev(struct platform_device *pdev,
__func__, found);
codec_aux_dev:
if (strcmp(card->name, "sm6150-tavil-snd-card")) {
if (!strnstr(card->name, "tavil", sizeof("tavil")) &&
!strnstr(card->name, "tasha", sizeof("tasha"))) {
/* Get maximum aux codec device count for this platform */
ret = of_property_read_u32(pdev->dev.of_node,
"qcom,codec-max-aux-devs",
@ -8431,7 +9002,8 @@ static int sm6150_ssr_enable(struct device *dev, void *data)
goto err;
}
if (!strcmp(card->name, "sm6150-tavil-snd-card")) {
if (strnstr(card->name, "tavil", sizeof("tavil")) ||
strnstr(card->name, "tasha", sizeof("tasha"))) {
pdata = snd_soc_card_get_drvdata(card);
if (!pdata->is_afe_config_done) {
const char *be_dl_name = LPASS_BE_SLIMBUS_0_RX;
@ -8481,13 +9053,41 @@ static void sm6150_ssr_disable(struct device *dev, void *data)
dev_dbg(dev, "%s: setting snd_card to OFFLINE\n", __func__);
snd_soc_card_change_online_state(card, 0);
if (!strcmp(card->name, "sm6150-tavil-snd-card")) {
if (strnstr(card->name, "tavil", sizeof("tavil")) ||
strnstr(card->name, "tasha", sizeof("tasha"))) {
pdata = snd_soc_card_get_drvdata(card);
msm_afe_clear_config();
pdata->is_afe_config_done = false;
}
}
static int msm_ext_prepare_hifi(struct msm_asoc_mach_data *pdata)
{
int ret = 0;
if (gpio_is_valid(pdata->hph_en1_gpio)) {
pr_debug("%s: hph_en1_gpio request %d\n", __func__,
pdata->hph_en1_gpio);
ret = gpio_request(pdata->hph_en1_gpio, "hph_en1_gpio");
if (ret) {
pr_err("%s: hph_en1_gpio request failed, ret:%d\n",
__func__, ret);
goto err;
}
}
if (gpio_is_valid(pdata->hph_en0_gpio)) {
pr_debug("%s: hph_en0_gpio request %d\n", __func__,
pdata->hph_en0_gpio);
ret = gpio_request(pdata->hph_en0_gpio, "hph_en0_gpio");
if (ret)
pr_err("%s: hph_en0_gpio request failed, ret:%d\n",
__func__, ret);
}
err:
return ret;
}
static const struct snd_event_ops sm6150_ssr_ops = {
.enable = sm6150_ssr_enable,
.disable = sm6150_ssr_disable,
@ -8589,20 +9189,31 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
}
dev_info(&pdev->dev, "Sound card %s registered\n", card->name);
pdata->hph_en1_gpio_p = of_parse_phandle(pdev->dev.of_node,
pdata->hph_en1_gpio = of_get_named_gpio(pdev->dev.of_node,
"qcom,hph-en1-gpio", 0);
if (!pdata->hph_en1_gpio_p) {
dev_dbg(&pdev->dev, "property %s not detected in node %s\n",
"qcom,hph-en1-gpio",
pdev->dev.of_node->full_name);
if (!gpio_is_valid(pdata->hph_en1_gpio))
pdata->hph_en1_gpio_p = of_parse_phandle(pdev->dev.of_node,
"qcom,hph-en1-gpio", 0);
if (!gpio_is_valid(pdata->hph_en1_gpio) && (!pdata->hph_en1_gpio_p)) {
dev_dbg(&pdev->dev, "property %s not detected in node %s",
"qcom,hph-en1-gpio", pdev->dev.of_node->full_name);
}
pdata->hph_en0_gpio_p = of_parse_phandle(pdev->dev.of_node,
pdata->hph_en0_gpio = of_get_named_gpio(pdev->dev.of_node,
"qcom,hph-en0-gpio", 0);
if (!pdata->hph_en0_gpio_p) {
dev_dbg(&pdev->dev, "property %s not detected in node %s\n",
"qcom,hph-en0-gpio",
pdev->dev.of_node->full_name);
if (!gpio_is_valid(pdata->hph_en0_gpio))
pdata->hph_en0_gpio_p = of_parse_phandle(pdev->dev.of_node,
"qcom,hph-en0-gpio", 0);
if (!gpio_is_valid(pdata->hph_en0_gpio) && (!pdata->hph_en0_gpio_p)) {
dev_dbg(&pdev->dev, "property %s not detected in node %s",
"qcom,hph-en0-gpio", pdev->dev.of_node->full_name);
}
ret = msm_ext_prepare_hifi(pdata);
if (ret) {
dev_dbg(&pdev->dev, "msm_ext_prepare_hifi failed (%d)\n",
ret);
ret = 0;
}
ret = of_property_read_string(pdev->dev.of_node,
@ -8669,7 +9280,8 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
}
msm_i2s_auxpcm_init(pdev);
if (strcmp(card->name, "sm6150-tavil-snd-card")) {
if (!strnstr(card->name, "tavil", sizeof("tavil")) &&
!strnstr(card->name, "tasha", sizeof("tasha"))) {
pdata->dmic01_gpio_p = of_parse_phandle(pdev->dev.of_node,
"qcom,cdc-dmic01-gpios",
0);