Merge "ASoC: msm: Fix sound card registration failure"

This commit is contained in:
Linux Build Service Account 2016-11-18 01:54:58 -08:00 committed by Gerrit - the friendly Code Review server
commit 6f4c99dfce
6 changed files with 2173 additions and 73 deletions

File diff suppressed because it is too large Load diff

View file

@ -31,12 +31,46 @@
#define SAMPLING_RATE_352P8KHZ 352800
#define SAMPLING_RATE_384KHZ 384000
#define TDM_CHANNEL_MAX 8
#define TDM_SLOT_OFFSET_MAX 8
enum {
TDM_0 = 0,
TDM_1,
TDM_2,
TDM_3,
TDM_4,
TDM_5,
TDM_6,
TDM_7,
TDM_PORT_MAX,
};
enum {
TDM_PRI = 0,
TDM_SEC,
TDM_TERT,
TDM_QUAT,
TDM_INTERFACE_MAX,
};
struct tdm_port {
u32 mode;
u32 channel;
};
extern const struct snd_kcontrol_new msm_common_snd_controls[];
struct msmfalcon_codec {
void* (*get_afe_config_fn)(struct snd_soc_codec *codec,
enum afe_config_type config_type);
};
enum {
INT_SND_CARD,
EXT_SND_CARD_TASHA,
EXT_SND_CARD_TAVIL,
};
struct msm_asoc_mach_data {
int us_euro_gpio; /* used by gpio driver API */
int hph_en1_gpio;
@ -50,6 +84,7 @@ struct msm_asoc_mach_data {
int spk_ext_pa_gpio;
int mclk_freq;
int lb_mode;
int snd_card_val;
u8 micbias1_cap_mode;
u8 micbias2_cap_mode;
atomic_t int_mclk0_rsc_ref;
@ -57,7 +92,6 @@ struct msm_asoc_mach_data {
struct mutex cdc_int_mclk0_mutex;
struct delayed_work disable_int_mclk0_work;
struct afe_clk_set digital_cdc_core_clk;
bool int_codec;
};
int msm_common_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,

View file

@ -16,6 +16,7 @@
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include "qdsp6v2/msm-pcm-routing-v2.h"
#include "../codecs/wcd9335.h"
#include "msmfalcon-common.h"
@ -25,7 +26,11 @@
#define __CHIPSET__ "MSMFALCON "
#define MSM_DAILINK_NAME(name) (__CHIPSET__#name)
static struct snd_soc_card snd_soc_card_msm_card;
#define WCN_CDC_SLIM_RX_CH_MAX 2
#define WCN_CDC_SLIM_TX_CH_MAX 3
static struct snd_soc_card snd_soc_card_msm_card_tavil;
static struct snd_soc_card snd_soc_card_msm_card_tasha;
static struct snd_soc_ops msm_ext_slimbus_be_ops = {
.hw_params = msm_snd_hw_params,
@ -49,6 +54,222 @@ static struct snd_soc_ops msm_aux_pcm_be_ops = {
.shutdown = msm_aux_pcm_snd_shutdown,
};
static int msm_wcn_init(struct snd_soc_pcm_runtime *rtd)
{
unsigned int rx_ch[WCN_CDC_SLIM_RX_CH_MAX] = {157, 158};
unsigned int tx_ch[WCN_CDC_SLIM_TX_CH_MAX] = {159, 160, 161};
struct snd_soc_dai *codec_dai = rtd->codec_dai;
return snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
}
static int msm_wcn_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;
u32 rx_ch[WCN_CDC_SLIM_RX_CH_MAX], tx_ch[WCN_CDC_SLIM_TX_CH_MAX];
u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
int ret;
dev_dbg(rtd->dev, "%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, &rx_ch_cnt, rx_ch);
if (ret) {
dev_err(rtd->dev,
"%s: failed to get BTFM codec chan map\n, err:%d\n",
__func__, ret);
goto exit;
}
dev_dbg(rtd->dev, "%s: tx_ch_cnt(%d) be_id %d\n",
__func__, tx_ch_cnt, dai_link->be_id);
ret = snd_soc_dai_set_channel_map(cpu_dai,
tx_ch_cnt, tx_ch, rx_ch_cnt, rx_ch);
if (ret)
dev_err(rtd->dev, "%s: failed to set cpu chan map, err:%d\n",
__func__, ret);
exit:
return ret;
}
static struct snd_soc_ops msm_wcn_ops = {
.hw_params = msm_wcn_hw_params,
};
/*TDM default offset currently only supporting TDM_RX_0 and TDM_TX_0 */
static unsigned int tdm_slot_offset[TDM_PORT_MAX][TDM_SLOT_OFFSET_MAX] = {
{0, 4, 8, 12, 16, 20, 24, 28},/* TX_0 | RX_0 */
{AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_1 | RX_1 */
{AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_2 | RX_2 */
{AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_3 | RX_3 */
{AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_4 | RX_4 */
{AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_5 | RX_5 */
{AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_6 | RX_6 */
{AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_7 | RX_7 */
};
static unsigned int tdm_param_set_slot_mask(u16 port_id, int slot_width,
int slots)
{
unsigned int slot_mask = 0;
int i, j;
unsigned int *slot_offset;
for (i = TDM_0; i < TDM_PORT_MAX; i++) {
slot_offset = tdm_slot_offset[i];
for (j = 0; j < TDM_SLOT_OFFSET_MAX; j++) {
if (slot_offset[j] != AFE_SLOT_MAPPING_OFFSET_INVALID)
slot_mask |=
(1 << ((slot_offset[j] * 8) / slot_width));
else
break;
}
}
return slot_mask;
}
static int msm_tdm_snd_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 *cpu_dai = rtd->cpu_dai;
int ret = 0;
int channels, slot_width, slots;
unsigned int slot_mask;
unsigned int *slot_offset;
int offset_channels = 0;
int i;
pr_debug("%s: dai id = 0x%x\n", __func__, cpu_dai->id);
channels = params_channels(params);
switch (channels) {
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S32_LE:
case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S16_LE:
/*
* up to 8 channels HW config should
* use 32 bit slot width for max support of
* stream bit width. (slot_width > bit_width)
*/
slot_width = 32;
break;
default:
pr_err("%s: invalid param format 0x%x\n",
__func__, params_format(params));
return -EINVAL;
}
slots = 8;
slot_mask = tdm_param_set_slot_mask(cpu_dai->id,
slot_width,
slots);
if (!slot_mask) {
pr_err("%s: invalid slot_mask 0x%x\n",
__func__, slot_mask);
return -EINVAL;
}
break;
default:
pr_err("%s: invalid param channels %d\n",
__func__, channels);
return -EINVAL;
}
/* currently only supporting TDM_RX_0 and TDM_TX_0 */
switch (cpu_dai->id) {
case AFE_PORT_ID_PRIMARY_TDM_RX:
case AFE_PORT_ID_SECONDARY_TDM_RX:
case AFE_PORT_ID_TERTIARY_TDM_RX:
case AFE_PORT_ID_QUATERNARY_TDM_RX:
case AFE_PORT_ID_PRIMARY_TDM_TX:
case AFE_PORT_ID_SECONDARY_TDM_TX:
case AFE_PORT_ID_TERTIARY_TDM_TX:
case AFE_PORT_ID_QUATERNARY_TDM_TX:
slot_offset = tdm_slot_offset[TDM_0];
break;
default:
pr_err("%s: dai id 0x%x not supported\n",
__func__, cpu_dai->id);
return -EINVAL;
}
for (i = 0; i < TDM_SLOT_OFFSET_MAX; i++) {
if (slot_offset[i] != AFE_SLOT_MAPPING_OFFSET_INVALID)
offset_channels++;
else
break;
}
if (offset_channels == 0) {
pr_err("%s: slot offset not supported, offset_channels %d\n",
__func__, offset_channels);
return -EINVAL;
}
if (channels > offset_channels) {
pr_err("%s: channels %d exceed offset_channels %d\n",
__func__, channels, offset_channels);
return -EINVAL;
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, slot_mask,
slots, slot_width);
if (ret < 0) {
pr_err("%s: failed to set tdm slot, err:%d\n",
__func__, ret);
goto end;
}
ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL,
channels, slot_offset);
if (ret < 0) {
pr_err("%s: failed to set channel map, err:%d\n",
__func__, ret);
goto end;
}
} else {
ret = snd_soc_dai_set_tdm_slot(cpu_dai, slot_mask, 0,
slots, slot_width);
if (ret < 0) {
pr_err("%s: failed to set tdm slot, err:%d\n",
__func__, ret);
goto end;
}
ret = snd_soc_dai_set_channel_map(cpu_dai, channels,
slot_offset, 0, NULL);
if (ret < 0) {
pr_err("%s: failed to set channel map, err:%d\n",
__func__, ret);
goto end;
}
}
end:
return ret;
}
static struct snd_soc_ops msm_tdm_be_ops = {
.hw_params = msm_tdm_snd_hw_params
};
static struct snd_soc_dai_link msm_ext_tasha_fe_dai[] = {
/* tasha_vifeedback for speaker protection */
{
@ -1167,6 +1388,145 @@ static struct snd_soc_dai_link msm_ext_common_be_dai[] = {
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_USB_AUDIO_RX,
.stream_name = "USB Audio Playback",
.cpu_dai_name = "msm-dai-q6-dev.28672",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
.be_id = MSM_BACKEND_DAI_USB_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_USB_AUDIO_TX,
.stream_name = "USB Audio Capture",
.cpu_dai_name = "msm-dai-q6-dev.28673",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
.be_id = MSM_BACKEND_DAI_USB_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_PRI_TDM_RX_0,
.stream_name = "Primary TDM0 Playback",
.cpu_dai_name = "msm-dai-q6-tdm.36864",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
.be_id = MSM_BACKEND_DAI_PRI_TDM_RX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_PRI_TDM_TX_0,
.stream_name = "Primary TDM0 Capture",
.cpu_dai_name = "msm-dai-q6-tdm.36865",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
.be_id = MSM_BACKEND_DAI_PRI_TDM_TX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_SEC_TDM_RX_0,
.stream_name = "Secondary TDM0 Playback",
.cpu_dai_name = "msm-dai-q6-tdm.36880",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
.be_id = MSM_BACKEND_DAI_SEC_TDM_RX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_SEC_TDM_TX_0,
.stream_name = "Secondary TDM0 Capture",
.cpu_dai_name = "msm-dai-q6-tdm.36881",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
.be_id = MSM_BACKEND_DAI_SEC_TDM_TX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_TERT_TDM_RX_0,
.stream_name = "Tertiary TDM0 Playback",
.cpu_dai_name = "msm-dai-q6-tdm.36896",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
.be_id = MSM_BACKEND_DAI_TERT_TDM_RX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_TERT_TDM_TX_0,
.stream_name = "Tertiary TDM0 Capture",
.cpu_dai_name = "msm-dai-q6-tdm.36897",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
.be_id = MSM_BACKEND_DAI_TERT_TDM_TX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_QUAT_TDM_RX_0,
.stream_name = "Quaternary TDM0 Playback",
.cpu_dai_name = "msm-dai-q6-tdm.36912",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
.be_id = MSM_BACKEND_DAI_QUAT_TDM_RX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_QUAT_TDM_TX_0,
.stream_name = "Quaternary TDM0 Capture",
.cpu_dai_name = "msm-dai-q6-tdm.36913",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
.be_id = MSM_BACKEND_DAI_QUAT_TDM_TX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
},
};
static struct snd_soc_dai_link msm_mi2s_be_dai_links[] = {
@ -1415,13 +1775,66 @@ static struct snd_soc_dai_link msm_auxpcm_be_dai_links[] = {
},
};
static struct snd_soc_dai_link msm_wcn_be_dai_links[] = {
{
.name = LPASS_BE_SLIMBUS_7_RX,
.stream_name = "Slimbus7 Playback",
.cpu_dai_name = "msm-dai-q6-dev.16398",
.platform_name = "msm-pcm-routing",
.codec_name = "btfmslim_slave",
/* BT codec driver determines capabilities based on
* dai name, bt codecdai name should always contains
* supported usecase information
*/
.codec_dai_name = "btfm_bt_sco_a2dp_slim_rx",
.no_pcm = 1,
.dpcm_playback = 1,
.be_id = MSM_BACKEND_DAI_SLIMBUS_7_RX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_wcn_ops,
/* dai link has playback support */
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_SLIMBUS_7_TX,
.stream_name = "Slimbus7 Capture",
.cpu_dai_name = "msm-dai-q6-dev.16399",
.platform_name = "msm-pcm-routing",
.codec_name = "btfmslim_slave",
.codec_dai_name = "btfm_bt_sco_slim_tx",
.no_pcm = 1,
.dpcm_capture = 1,
.be_id = MSM_BACKEND_DAI_SLIMBUS_7_TX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_wcn_ops,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_SLIMBUS_8_TX,
.stream_name = "Slimbus8 Capture",
.cpu_dai_name = "msm-dai-q6-dev.16401",
.platform_name = "msm-pcm-routing",
.codec_name = "btfmslim_slave",
.codec_dai_name = "btfm_fm_slim_tx",
.no_pcm = 1,
.dpcm_capture = 1,
.be_id = MSM_BACKEND_DAI_SLIMBUS_8_TX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.init = &msm_wcn_init,
.ops = &msm_wcn_ops,
.ignore_suspend = 1,
},
};
static struct snd_soc_dai_link msm_ext_tasha_dai_links[
ARRAY_SIZE(msm_ext_common_fe_dai) +
ARRAY_SIZE(msm_ext_tasha_fe_dai) +
ARRAY_SIZE(msm_ext_common_be_dai) +
ARRAY_SIZE(msm_ext_tasha_be_dai) +
ARRAY_SIZE(msm_mi2s_be_dai_links) +
ARRAY_SIZE(msm_auxpcm_be_dai_links)];
ARRAY_SIZE(msm_auxpcm_be_dai_links) +
ARRAY_SIZE(msm_wcn_be_dai_links)];
static struct snd_soc_dai_link msm_ext_tavil_dai_links[
ARRAY_SIZE(msm_ext_common_fe_dai) +
@ -1429,7 +1842,8 @@ ARRAY_SIZE(msm_ext_tavil_fe_dai) +
ARRAY_SIZE(msm_ext_common_be_dai) +
ARRAY_SIZE(msm_ext_tavil_be_dai) +
ARRAY_SIZE(msm_mi2s_be_dai_links) +
ARRAY_SIZE(msm_auxpcm_be_dai_links)];
ARRAY_SIZE(msm_auxpcm_be_dai_links) +
ARRAY_SIZE(msm_wcn_be_dai_links)];
/**
* populate_snd_card_dailinks - prepares dailink array and initializes card.
@ -1438,13 +1852,24 @@ ARRAY_SIZE(msm_auxpcm_be_dai_links)];
*
* Returns card on success or NULL on failure.
*/
struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
struct snd_soc_card *populate_snd_card_dailinks(struct device *dev,
int snd_card_val)
{
struct snd_soc_card *card = &snd_soc_card_msm_card;
struct snd_soc_card *card;
struct snd_soc_dai_link *msm_ext_dai_links = NULL;
int ret, len1, len2, len3, len4;
enum codec_variant codec_ver = 0;
if (snd_card_val == EXT_SND_CARD_TASHA) {
card = &snd_soc_card_msm_card_tasha;
} else if (snd_card_val == EXT_SND_CARD_TAVIL) {
card = &snd_soc_card_msm_card_tavil;
} else {
dev_err(dev, "%s: failing as no matching card name\n",
__func__);
return NULL;
}
card->dev = dev;
ret = snd_soc_of_parse_card_name(card, "qcom,model");
if (ret) {
@ -1484,6 +1909,14 @@ struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
sizeof(msm_auxpcm_be_dai_links));
len4 += ARRAY_SIZE(msm_auxpcm_be_dai_links);
}
if (of_property_read_bool(dev->of_node, "qcom,wcn-btfm")) {
dev_dbg(dev, "%s(): WCN BTFM support present\n",
__func__);
memcpy(msm_ext_tasha_dai_links + len4,
msm_wcn_be_dai_links,
sizeof(msm_wcn_be_dai_links));
len4 += ARRAY_SIZE(msm_wcn_be_dai_links);
}
msm_ext_dai_links = msm_ext_tasha_dai_links;
} else if (strnstr(card->name, "tavil", strlen(card->name))) {
len1 = ARRAY_SIZE(msm_ext_common_fe_dai);
@ -1512,6 +1945,14 @@ struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
sizeof(msm_auxpcm_be_dai_links));
len4 += ARRAY_SIZE(msm_auxpcm_be_dai_links);
}
if (of_property_read_bool(dev->of_node, "qcom,wcn-btfm")) {
dev_dbg(dev, "%s(): WCN BTFM support present\n",
__func__);
memcpy(msm_ext_tavil_dai_links + len4,
msm_wcn_be_dai_links,
sizeof(msm_wcn_be_dai_links));
len4 += ARRAY_SIZE(msm_wcn_be_dai_links);
}
msm_ext_dai_links = msm_ext_tavil_dai_links;
} else {
dev_err(dev, "%s: failing as no matching card name\n",
@ -1520,7 +1961,6 @@ struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
}
card->dai_link = msm_ext_dai_links;
card->num_links = len4;
card->dev = dev;
return card;
}

View file

@ -122,6 +122,7 @@ static char const *slim_sample_rate_text[] = {"KHZ_8", "KHZ_16",
"KHZ_88P2", "KHZ_96", "KHZ_176P4",
"KHZ_192", "KHZ_352P8", "KHZ_384"};
static const char *const spk_function_text[] = {"Off", "On"};
static char const *bt_sample_rate_text[] = {"KHZ_8", "KHZ_16", "KHZ_48"};
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);
@ -140,6 +141,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(slim_2_rx_sample_rate, slim_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_sample_rate, slim_sample_rate_text);
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 int slim_get_sample_rate_val(int sample_rate)
{
@ -302,6 +304,59 @@ static int slim_get_port_idx(struct snd_kcontrol *kcontrol)
return port_id;
}
static int msm_bt_sample_rate_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
/*
* Slimbus_7_Rx/Tx sample rate values should always be in sync (same)
* when used for BT_SCO use case. Return either Rx or Tx sample rate
* value.
*/
switch (slim_rx_cfg[SLIM_RX_7].sample_rate) {
case SAMPLING_RATE_48KHZ:
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_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;
slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_16KHZ;
break;
case 2:
slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_48KHZ;
slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_48KHZ;
break;
case 0:
default:
slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_8KHZ;
slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_8KHZ;
break;
}
pr_debug("%s: sample rates: slim7_rx = %d, slim7_tx = %d, value = %d\n",
__func__,
slim_rx_cfg[SLIM_RX_7].sample_rate,
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)
{
@ -670,6 +725,9 @@ static const struct snd_kcontrol_new msm_snd_controls[] = {
slim_rx_sample_rate_get, slim_rx_sample_rate_put),
SOC_ENUM_EXT("SLIM_6_RX SampleRate", slim_6_rx_sample_rate,
slim_rx_sample_rate_get, slim_rx_sample_rate_put),
SOC_ENUM_EXT("BT SampleRate", bt_sample_rate,
msm_bt_sample_rate_get,
msm_bt_sample_rate_put),
};
static int msm_slim_get_ch_from_beid(int32_t be_id)
@ -1626,6 +1684,21 @@ err_mbhc_cal:
}
EXPORT_SYMBOL(msm_audrx_init);
/**
* msm_ext_register_audio_notifier - register SSR notifier.
*/
void msm_ext_register_audio_notifier(void)
{
int ret;
ret = audio_notifier_register("msmfalcon", AUDIO_NOTIFIER_ADSP_DOMAIN,
&service_nb);
if (ret < 0)
pr_err("%s: Audio notifier register failed ret = %d\n",
__func__, ret);
}
EXPORT_SYMBOL(msm_ext_register_audio_notifier);
/**
* msm_ext_cdc_init - external codec machine specific init.
*
@ -1650,24 +1723,16 @@ int msm_ext_cdc_init(struct platform_device *pdev,
wcd_mbhc_cfg_ptr->anc_micbias = MIC_BIAS_2;
wcd_mbhc_cfg_ptr->enable_anc_mic_detect = false;
*card = populate_snd_card_dailinks(&pdev->dev);
*card = populate_snd_card_dailinks(&pdev->dev, pdata->snd_card_val);
if (!(*card)) {
dev_err(&pdev->dev, "%s: Card uninitialized\n", __func__);
ret = -EPROBE_DEFER;
goto err;
}
(*card)->dev = &pdev->dev;
spdev = pdev;
platform_set_drvdata(pdev, *card);
snd_soc_card_set_drvdata(*card, pdata);
is_initial_boot = true;
ret = audio_notifier_register("msmfalcon", AUDIO_NOTIFIER_ADSP_DOMAIN,
&service_nb);
if (ret < 0) {
pr_err("%s: Audio notifier register failed ret = %d\n",
__func__, ret);
goto err;
}
pdata->hph_en1_gpio = of_get_named_gpio(pdev->dev.of_node,
"qcom,hph-en1-gpio", 0);
if (!gpio_is_valid(pdata->hph_en1_gpio))

View file

@ -26,12 +26,14 @@ int msm_proxy_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
int msm_audrx_init(struct snd_soc_pcm_runtime *rtd);
int msm_snd_cpe_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params);
struct snd_soc_card *populate_snd_card_dailinks(struct device *dev);
struct snd_soc_card *populate_snd_card_dailinks(struct device *dev,
int snd_card_val);
int msm_ext_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params);
#ifdef CONFIG_SND_SOC_EXT_CODEC
int msm_ext_cdc_init(struct platform_device *, struct msm_asoc_mach_data *,
struct snd_soc_card **, struct wcd_mbhc_config *);
void msm_ext_register_audio_notifier(void);
#else
inline int msm_ext_cdc_init(struct platform_device *pdev,
struct msm_asoc_mach_data *pdata,
@ -40,5 +42,9 @@ inline int msm_ext_cdc_init(struct platform_device *pdev,
{
return 0;
}
inline void msm_ext_register_audio_notifier(void)
{
}
#endif
#endif

View file

@ -27,6 +27,9 @@
#define WCD_MBHC_DEF_RLOADS 5
#define WCN_CDC_SLIM_RX_CH_MAX 2
#define WCN_CDC_SLIM_TX_CH_MAX 3
enum {
INT0_MI2S = 0,
INT1_MI2S,
@ -38,6 +41,24 @@ enum {
INT_MI2S_MAX,
};
enum {
BT_SLIM7,
FM_SLIM8,
SLIM_MAX,
};
/*TDM default offset currently only supporting TDM_RX_0 and TDM_TX_0 */
static unsigned int tdm_slot_offset[TDM_PORT_MAX][TDM_SLOT_OFFSET_MAX] = {
{0, 4, 8, 12, 16, 20, 24, 28},/* TX_0 | RX_0 */
{AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_1 | RX_1 */
{AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_2 | RX_2 */
{AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_3 | RX_3 */
{AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_4 | RX_4 */
{AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_5 | RX_5 */
{AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_6 | RX_6 */
{AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_7 | RX_7 */
};
static struct afe_clk_set int_mi2s_clk[INT_MI2S_MAX] = {
{
AFE_API_VERSION_I2S_CONFIG,
@ -114,6 +135,11 @@ static struct dev_config int_mi2s_cfg[] = {
[INT6_MI2S] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
};
static struct dev_config bt_fm_cfg[] = {
[BT_SLIM7] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
[FM_SLIM8] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
};
static char const *int_mi2s_rate_text[] = {"KHZ_8", "KHZ_16",
"KHZ_32", "KHZ_44P1", "KHZ_48",
"KHZ_96", "KHZ_192"};
@ -122,6 +148,7 @@ static const char *const int_mi2s_tx_ch_text[] = {"One", "Two",
"Three", "Four"};
static char const *bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE"};
static const char *const loopback_mclk_text[] = {"DISABLE", "ENABLE"};
static char const *bt_sample_rate_text[] = {"KHZ_8", "KHZ_16", "KHZ_48"};
static SOC_ENUM_SINGLE_EXT_DECL(int0_mi2s_rx_sample_rate, int_mi2s_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(int0_mi2s_rx_chs, int_mi2s_ch_text);
@ -137,6 +164,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(int4_mi2s_rx_chs, int_mi2s_ch_text);
static SOC_ENUM_SINGLE_EXT_DECL(int4_mi2s_rx_format, bit_format_text);
static SOC_ENUM_SINGLE_EXT_DECL(int5_mi2s_tx_chs, int_mi2s_ch_text);
static SOC_ENUM_SINGLE_EXT_DECL(loopback_mclk_en, loopback_mclk_text);
static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate, bt_sample_rate_text);
static int msm_dmic_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
@ -544,7 +572,7 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
return 0;
}
int int_mi2s_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
static int int_mi2s_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
struct snd_soc_dai_link *dai_link = rtd->dai_link;
@ -577,6 +605,38 @@ int int_mi2s_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
return 0;
}
static int msm_btfm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
struct snd_soc_dai_link *dai_link = rtd->dai_link;
struct snd_interval *rate = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_RATE);
struct snd_interval *channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS);
switch (dai_link->be_id) {
case MSM_BACKEND_DAI_SLIMBUS_7_RX:
case MSM_BACKEND_DAI_SLIMBUS_7_TX:
param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
bt_fm_cfg[BT_SLIM7].bit_format);
rate->min = rate->max = bt_fm_cfg[BT_SLIM7].sample_rate;
channels->min = channels->max =
bt_fm_cfg[BT_SLIM7].channels;
break;
case MSM_BACKEND_DAI_SLIMBUS_8_TX:
rate->min = rate->max = bt_fm_cfg[FM_SLIM8].sample_rate;
channels->min = channels->max =
bt_fm_cfg[FM_SLIM8].channels;
break;
default:
rate->min = rate->max = SAMPLING_RATE_48KHZ;
break;
}
return 0;
}
static int msm_vi_feed_tx_ch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@ -746,6 +806,55 @@ static int loopback_mclk_put(struct snd_kcontrol *kcontrol,
return ret;
}
static int msm_bt_sample_rate_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
/*
* Slimbus_7_Rx/Tx sample rate values should always be in sync (same)
* when used for BT_SCO use case. Return either Rx or Tx sample rate
* value.
*/
switch (bt_fm_cfg[BT_SLIM7].sample_rate) {
case SAMPLING_RATE_48KHZ:
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__,
bt_fm_cfg[BT_SLIM7].sample_rate);
return 0;
}
static int msm_bt_sample_rate_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
switch (ucontrol->value.integer.value[0]) {
case 1:
bt_fm_cfg[BT_SLIM7].sample_rate = SAMPLING_RATE_16KHZ;
break;
case 2:
bt_fm_cfg[BT_SLIM7].sample_rate = SAMPLING_RATE_48KHZ;
break;
case 0:
default:
bt_fm_cfg[BT_SLIM7].sample_rate = SAMPLING_RATE_8KHZ;
break;
}
pr_debug("%s: sample rates: slim7_rx = %d, value = %d\n",
__func__,
bt_fm_cfg[BT_SLIM7].sample_rate,
ucontrol->value.enumerated.item[0]);
return 0;
}
static const struct snd_kcontrol_new msm_snd_controls[] = {
SOC_ENUM_EXT("INT0_MI2S_RX Format", int0_mi2s_rx_format,
int_mi2s_bit_format_get, int_mi2s_bit_format_put),
@ -779,6 +888,9 @@ static const struct snd_kcontrol_new msm_snd_controls[] = {
int_mi2s_ch_get, int_mi2s_ch_put),
SOC_ENUM_EXT("Loopback MCLK", loopback_mclk_en,
loopback_mclk_get, loopback_mclk_put),
SOC_ENUM_EXT("BT SampleRate", bt_sample_rate,
msm_bt_sample_rate_get,
msm_bt_sample_rate_put),
};
static const struct snd_kcontrol_new msm_swr_controls[] = {
@ -1209,6 +1321,210 @@ static int msm_swr_audrx_init(struct snd_soc_pcm_runtime *rtd)
return 0;
}
static int msm_wcn_init(struct snd_soc_pcm_runtime *rtd)
{
unsigned int rx_ch[WCN_CDC_SLIM_RX_CH_MAX] = {157, 158};
unsigned int tx_ch[WCN_CDC_SLIM_TX_CH_MAX] = {159, 160, 161};
struct snd_soc_dai *codec_dai = rtd->codec_dai;
return snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
}
static int msm_wcn_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;
u32 rx_ch[WCN_CDC_SLIM_RX_CH_MAX], tx_ch[WCN_CDC_SLIM_TX_CH_MAX];
u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
int ret;
dev_dbg(rtd->dev, "%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, &rx_ch_cnt, rx_ch);
if (ret) {
dev_err(rtd->dev,
"%s: failed to get BTFM codec chan map\n, err:%d\n",
__func__, ret);
goto exit;
}
dev_dbg(rtd->dev, "%s: tx_ch_cnt(%d) be_id %d\n",
__func__, tx_ch_cnt, dai_link->be_id);
ret = snd_soc_dai_set_channel_map(cpu_dai,
tx_ch_cnt, tx_ch, rx_ch_cnt, rx_ch);
if (ret)
dev_err(rtd->dev, "%s: failed to set cpu chan map, err:%d\n",
__func__, ret);
exit:
return ret;
}
static unsigned int tdm_param_set_slot_mask(u16 port_id, int slot_width,
int slots)
{
unsigned int slot_mask = 0;
int i, j;
unsigned int *slot_offset;
for (i = TDM_0; i < TDM_PORT_MAX; i++) {
slot_offset = tdm_slot_offset[i];
for (j = 0; j < TDM_SLOT_OFFSET_MAX; j++) {
if (slot_offset[j] != AFE_SLOT_MAPPING_OFFSET_INVALID)
slot_mask |=
(1 << ((slot_offset[j] * 8) / slot_width));
else
break;
}
}
return slot_mask;
}
static int msm_tdm_snd_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 *cpu_dai = rtd->cpu_dai;
int ret = 0;
int channels, slot_width, slots;
unsigned int slot_mask;
unsigned int *slot_offset;
int offset_channels = 0;
int i;
pr_debug("%s: dai id = 0x%x\n", __func__, cpu_dai->id);
channels = params_channels(params);
switch (channels) {
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S32_LE:
case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S16_LE:
/*
* up to 8 channels HW config should
* use 32 bit slot width for max support of
* stream bit width. (slot_width > bit_width)
*/
slot_width = 32;
break;
default:
pr_err("%s: invalid param format 0x%x\n",
__func__, params_format(params));
return -EINVAL;
}
slots = 8;
slot_mask = tdm_param_set_slot_mask(cpu_dai->id,
slot_width,
slots);
if (!slot_mask) {
pr_err("%s: invalid slot_mask 0x%x\n",
__func__, slot_mask);
return -EINVAL;
}
break;
default:
pr_err("%s: invalid param channels %d\n",
__func__, channels);
return -EINVAL;
}
/* currently only supporting TDM_RX_0 and TDM_TX_0 */
switch (cpu_dai->id) {
case AFE_PORT_ID_PRIMARY_TDM_RX:
case AFE_PORT_ID_SECONDARY_TDM_RX:
case AFE_PORT_ID_TERTIARY_TDM_RX:
case AFE_PORT_ID_QUATERNARY_TDM_RX:
case AFE_PORT_ID_PRIMARY_TDM_TX:
case AFE_PORT_ID_SECONDARY_TDM_TX:
case AFE_PORT_ID_TERTIARY_TDM_TX:
case AFE_PORT_ID_QUATERNARY_TDM_TX:
slot_offset = tdm_slot_offset[TDM_0];
break;
default:
pr_err("%s: dai id 0x%x not supported\n",
__func__, cpu_dai->id);
return -EINVAL;
}
for (i = 0; i < TDM_SLOT_OFFSET_MAX; i++) {
if (slot_offset[i] != AFE_SLOT_MAPPING_OFFSET_INVALID)
offset_channels++;
else
break;
}
if (offset_channels == 0) {
pr_err("%s: slot offset not supported, offset_channels %d\n",
__func__, offset_channels);
return -EINVAL;
}
if (channels > offset_channels) {
pr_err("%s: channels %d exceed offset_channels %d\n",
__func__, channels, offset_channels);
return -EINVAL;
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, slot_mask,
slots, slot_width);
if (ret < 0) {
pr_err("%s: failed to set tdm slot, err:%d\n",
__func__, ret);
goto end;
}
ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL,
channels, slot_offset);
if (ret < 0) {
pr_err("%s: failed to set channel map, err:%d\n",
__func__, ret);
goto end;
}
} else {
ret = snd_soc_dai_set_tdm_slot(cpu_dai, slot_mask, 0,
slots, slot_width);
if (ret < 0) {
pr_err("%s: failed to set tdm slot, err:%d\n",
__func__, ret);
goto end;
}
ret = snd_soc_dai_set_channel_map(cpu_dai, channels,
slot_offset, 0, NULL);
if (ret < 0) {
pr_err("%s: failed to set channel map, err:%d\n",
__func__, ret);
goto end;
}
}
end:
return ret;
}
static struct snd_soc_ops msm_tdm_be_ops = {
.hw_params = msm_tdm_snd_hw_params
};
static struct snd_soc_ops msm_wcn_ops = {
.hw_params = msm_wcn_hw_params,
};
static struct snd_soc_ops msm_mi2s_be_ops = {
.startup = msm_mi2s_snd_startup,
.shutdown = msm_mi2s_snd_shutdown,
@ -2029,6 +2345,145 @@ static struct snd_soc_dai_link msm_int_dai[] = {
.be_hw_params_fixup = msm_be_hw_params_fixup,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_USB_AUDIO_RX,
.stream_name = "USB Audio Playback",
.cpu_dai_name = "msm-dai-q6-dev.28672",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
.be_id = MSM_BACKEND_DAI_USB_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_USB_AUDIO_TX,
.stream_name = "USB Audio Capture",
.cpu_dai_name = "msm-dai-q6-dev.28673",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
.be_id = MSM_BACKEND_DAI_USB_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_PRI_TDM_RX_0,
.stream_name = "Primary TDM0 Playback",
.cpu_dai_name = "msm-dai-q6-tdm.36864",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
.be_id = MSM_BACKEND_DAI_PRI_TDM_RX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_PRI_TDM_TX_0,
.stream_name = "Primary TDM0 Capture",
.cpu_dai_name = "msm-dai-q6-tdm.36865",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
.be_id = MSM_BACKEND_DAI_PRI_TDM_TX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_SEC_TDM_RX_0,
.stream_name = "Secondary TDM0 Playback",
.cpu_dai_name = "msm-dai-q6-tdm.36880",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
.be_id = MSM_BACKEND_DAI_SEC_TDM_RX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_SEC_TDM_TX_0,
.stream_name = "Secondary TDM0 Capture",
.cpu_dai_name = "msm-dai-q6-tdm.36881",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
.be_id = MSM_BACKEND_DAI_SEC_TDM_TX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_TERT_TDM_RX_0,
.stream_name = "Tertiary TDM0 Playback",
.cpu_dai_name = "msm-dai-q6-tdm.36896",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
.be_id = MSM_BACKEND_DAI_TERT_TDM_RX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_TERT_TDM_TX_0,
.stream_name = "Tertiary TDM0 Capture",
.cpu_dai_name = "msm-dai-q6-tdm.36897",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
.be_id = MSM_BACKEND_DAI_TERT_TDM_TX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_QUAT_TDM_RX_0,
.stream_name = "Quaternary TDM0 Playback",
.cpu_dai_name = "msm-dai-q6-tdm.36912",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
.be_id = MSM_BACKEND_DAI_QUAT_TDM_RX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_QUAT_TDM_TX_0,
.stream_name = "Quaternary TDM0 Capture",
.cpu_dai_name = "msm-dai-q6-tdm.36913",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
.be_id = MSM_BACKEND_DAI_QUAT_TDM_TX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
},
};
static struct snd_soc_dai_link msm_mi2s_be_dai_links[] = {
@ -2277,10 +2732,64 @@ static struct snd_soc_dai_link msm_auxpcm_be_dai_links[] = {
},
};
static struct snd_soc_dai_link msm_wcn_be_dai_links[] = {
{
.name = LPASS_BE_SLIMBUS_7_RX,
.stream_name = "Slimbus7 Playback",
.cpu_dai_name = "msm-dai-q6-dev.16398",
.platform_name = "msm-pcm-routing",
.codec_name = "btfmslim_slave",
/* BT codec driver determines capabilities based on
* dai name, bt codecdai name should always contains
* supported usecase information
*/
.codec_dai_name = "btfm_bt_sco_a2dp_slim_rx",
.no_pcm = 1,
.dpcm_playback = 1,
.be_id = MSM_BACKEND_DAI_SLIMBUS_7_RX,
.be_hw_params_fixup = msm_btfm_be_hw_params_fixup,
.ops = &msm_wcn_ops,
/* dai link has playback support */
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_SLIMBUS_7_TX,
.stream_name = "Slimbus7 Capture",
.cpu_dai_name = "msm-dai-q6-dev.16399",
.platform_name = "msm-pcm-routing",
.codec_name = "btfmslim_slave",
.codec_dai_name = "btfm_bt_sco_slim_tx",
.no_pcm = 1,
.dpcm_capture = 1,
.be_id = MSM_BACKEND_DAI_SLIMBUS_7_TX,
.be_hw_params_fixup = msm_btfm_be_hw_params_fixup,
.ops = &msm_wcn_ops,
.ignore_suspend = 1,
},
{
.name = LPASS_BE_SLIMBUS_8_TX,
.stream_name = "Slimbus8 Capture",
.cpu_dai_name = "msm-dai-q6-dev.16401",
.platform_name = "msm-pcm-routing",
.codec_name = "btfmslim_slave",
.codec_dai_name = "btfm_fm_slim_tx",
.no_pcm = 1,
.dpcm_capture = 1,
.be_id = MSM_BACKEND_DAI_SLIMBUS_8_TX,
.be_hw_params_fixup = msm_btfm_be_hw_params_fixup,
.init = &msm_wcn_init,
.ops = &msm_wcn_ops,
.ignore_suspend = 1,
},
};
static struct snd_soc_dai_link msm_int_dai_links[
ARRAY_SIZE(msm_int_dai) +
ARRAY_SIZE(msm_mi2s_be_dai_links) +
ARRAY_SIZE(msm_auxpcm_be_dai_links)];
ARRAY_SIZE(msm_auxpcm_be_dai_links)+
ARRAY_SIZE(msm_wcn_be_dai_links)];
static struct snd_soc_card msmfalcon_card = {
/* snd_soc_card_msmfalcon */
@ -2357,6 +2866,14 @@ static struct snd_soc_card *msm_int_populate_sndcard_dailinks(
sizeof(msm_auxpcm_be_dai_links));
len1 += ARRAY_SIZE(msm_auxpcm_be_dai_links);
}
if (of_property_read_bool(dev->of_node, "qcom,wcn-btfm")) {
dev_dbg(dev, "%s(): WCN BTFM support present\n",
__func__);
memcpy(dailink + len1,
msm_wcn_be_dai_links,
sizeof(msm_wcn_be_dai_links));
len1 += ARRAY_SIZE(msm_wcn_be_dai_links);
}
card->dai_link = dailink;
card->num_links = len1;
return card;