Merge "ASoC: msm: Fix sound card registration failure"
This commit is contained in:
commit
6f4c99dfce
6 changed files with 2173 additions and 73 deletions
File diff suppressed because it is too large
Load diff
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue