diff --git a/asoc/qcs405.c b/asoc/qcs405.c index cadcd405cb9a..36fbfad5c3ed 100644 --- a/asoc/qcs405.c +++ b/asoc/qcs405.c @@ -105,6 +105,12 @@ enum { MI2S_MAX, }; +enum { + PRIM_META_MI2S = 0, + SEC_META_MI2S, + META_MI2S_MAX, +}; + enum { PRIM_AUX_PCM = 0, SEC_AUX_PCM, @@ -157,6 +163,12 @@ static u32 mi2s_ebit_clk[MI2S_MAX] = { Q6AFE_LPASS_CLK_ID_SEN_MI2S_EBIT }; +struct meta_mi2s_conf { + u32 num_member_ports; + u32 member_port[MAX_NUM_I2S_META_PORT_MEMBER_PORTS]; + bool clk_enable[MAX_NUM_I2S_META_PORT_MEMBER_PORTS]; +}; + struct dev_config { u32 sample_rate; u32 bit_format; @@ -402,6 +414,11 @@ static struct dev_config mi2s_rx_cfg[] = { [SEN_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, }; +static struct dev_config meta_mi2s_rx_cfg[] = { + [PRIM_META_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, + [SEC_META_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, +}; + /* Default configuration of SPDIF channels */ static struct dev_config spdif_rx_cfg[] = { [PRIM_SPDIF_RX] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, @@ -487,6 +504,14 @@ static const char *const mi2s_ch_text[] = { "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen" }; +static const char *const meta_mi2s_ch_text[] = { + "One", "Two", "Three", "Four", "Five", "Six", "Seven", + "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", + "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", + "Nineteen", "Twenty", "TwentyOne", "TwentyTwo", "TwentyThree", + "TwentyFour", "TwentyFive", "TwentySix", "TwentySeven", + "TwentyEight", "TwentyNine", "Thirty", "ThirtyOne", "ThirtyTwo" +}; static const char *const qos_text[] = {"Disable", "Enable"}; static const char *const cdc_dma_rx_ch_text[] = {"One", "Two"}; @@ -576,6 +601,12 @@ static SOC_ENUM_SINGLE_EXT_DECL(mi2s_rx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(mi2s_tx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(aux_pcm_rx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(aux_pcm_tx_format, bit_format_text); +static SOC_ENUM_SINGLE_EXT_DECL(prim_meta_mi2s_rx_sample_rate, mi2s_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(sec_meta_mi2s_rx_sample_rate, mi2s_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(prim_meta_mi2s_rx_chs, meta_mi2s_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(sec_meta_mi2s_rx_chs, meta_mi2s_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(prim_meta_mi2s_rx_format, bit_format_text); +static SOC_ENUM_SINGLE_EXT_DECL(sec_meta_mi2s_rx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(wsa_cdc_dma_rx_0_chs, cdc_dma_rx_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(wsa_cdc_dma_rx_1_chs, cdc_dma_rx_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(wsa_cdc_dma_tx_0_chs, cdc_dma_tx_ch_text); @@ -689,6 +720,8 @@ static struct afe_clk_set mi2s_clk[MI2S_MAX] = { static struct mi2s_conf mi2s_intf_conf[MI2S_MAX]; +static struct meta_mi2s_conf meta_mi2s_intf_conf[META_MI2S_MAX]; + static int msm_island_vad_get_portid_from_beid(int32_t be_id, int *port_id) { *port_id = 0xFFFF; @@ -3070,6 +3103,143 @@ static int msm_mi2s_tx_format_put(struct snd_kcontrol *kcontrol, return 0; } +static int msm_meta_mi2s_get_port_idx(struct snd_kcontrol *kcontrol) +{ + int idx = 0; + + if (strnstr(kcontrol->id.name, "PRIM_META_MI2S_RX", + sizeof("PRIM_META_MI2S_RX"))) { + idx = PRIM_META_MI2S; + } else if (strnstr(kcontrol->id.name, "SEC_META_MI2S_RX", + sizeof("SEC_META_MI2S_RX"))) { + idx = SEC_META_MI2S; + } else { + pr_err("%s: unsupported port: %s", + __func__, kcontrol->id.name); + idx = -EINVAL; + } + + return idx; +} + +static int msm_meta_mi2s_rx_sample_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = msm_meta_mi2s_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + ucontrol->value.enumerated.item[0] = + mi2s_get_sample_rate_val(meta_mi2s_rx_cfg[idx].sample_rate); + + pr_debug("%s: idx[%d]_rx_sample_rate = %d, item = %d\n", __func__, + idx, meta_mi2s_rx_cfg[idx].sample_rate, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int msm_meta_mi2s_rx_sample_rate_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = msm_meta_mi2s_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + meta_mi2s_rx_cfg[idx].sample_rate = + mi2s_get_sample_rate(ucontrol->value.enumerated.item[0]); + + pr_debug("%s: idx[%d]_rx_sample_rate = %d, item = %d\n", __func__, + idx, meta_mi2s_rx_cfg[idx].sample_rate, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int msm_meta_mi2s_rx_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = msm_meta_mi2s_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + ucontrol->value.enumerated.item[0] = meta_mi2s_rx_cfg[idx].channels - 1; + + pr_debug("%s: meta_mi2s_[%d]_rx_ch = %d\n", __func__, + idx, meta_mi2s_rx_cfg[idx].channels); + + return 0; +} + +static int msm_meta_mi2s_rx_ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = msm_meta_mi2s_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + meta_mi2s_rx_cfg[idx].channels = ucontrol->value.enumerated.item[0] + 1; + + pr_debug("%s: meta_mi2s_[%d]_rx_ch = %d\n", __func__, + idx, meta_mi2s_rx_cfg[idx].channels); + + return 1; +} + +static int msm_meta_mi2s_rx_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = msm_meta_mi2s_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + ucontrol->value.enumerated.item[0] = + mi2s_auxpcm_get_format_value(meta_mi2s_rx_cfg[idx].bit_format); + + pr_debug("%s: idx[%d]_rx_format = %d, item = %d\n", __func__, + idx, meta_mi2s_rx_cfg[idx].bit_format, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int msm_meta_mi2s_rx_format_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct msm_asoc_mach_data *pdata = NULL; + struct snd_soc_card *card = NULL; + int idx = msm_meta_mi2s_get_port_idx(kcontrol); + + card = kcontrol->private_data; + pdata = snd_soc_card_get_drvdata(card); + + if (idx < 0) + return idx; + + /* check for PRIM_META_MI2S and CSRAx to allow 24bit BE config only */ + if ((idx == PRIM_META_MI2S) && pdata->codec_is_csra) { + meta_mi2s_rx_cfg[idx].bit_format = SNDRV_PCM_FORMAT_S24_LE; + pr_debug("%s: Keeping default format idx[%d]_rx_format = %d, item = %d\n", + __func__, idx, meta_mi2s_rx_cfg[idx].bit_format, + ucontrol->value.enumerated.item[0]); + } else { + meta_mi2s_rx_cfg[idx].bit_format = + mi2s_auxpcm_get_format( + ucontrol->value.enumerated.item[0]); + + pr_debug("%s: idx[%d]_rx_format = %d, item = %d\n", __func__, + idx, meta_mi2s_rx_cfg[idx].bit_format, + ucontrol->value.enumerated.item[0]); + } + + return 0; +} + static int msm_aux_pcm_rx_format_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -3979,6 +4149,26 @@ static const struct snd_kcontrol_new msm_snd_controls[] = { msm_mi2s_rx_format_get, msm_mi2s_rx_format_put), SOC_ENUM_EXT("SEN_MI2S_TX Format", mi2s_tx_format, msm_mi2s_tx_format_get, msm_mi2s_tx_format_put), + SOC_ENUM_EXT("PRIM_META_MI2S_RX SampleRate", + prim_meta_mi2s_rx_sample_rate, + msm_meta_mi2s_rx_sample_rate_get, + msm_meta_mi2s_rx_sample_rate_put), + SOC_ENUM_EXT("SEC_META_MI2S_RX SampleRate", + sec_meta_mi2s_rx_sample_rate, + msm_meta_mi2s_rx_sample_rate_get, + msm_meta_mi2s_rx_sample_rate_put), + SOC_ENUM_EXT("PRIM_META_MI2S_RX Channels", prim_meta_mi2s_rx_chs, + msm_meta_mi2s_rx_ch_get, + msm_meta_mi2s_rx_ch_put), + SOC_ENUM_EXT("SEC_META_MI2S_RX Channels", sec_meta_mi2s_rx_chs, + msm_meta_mi2s_rx_ch_get, + msm_meta_mi2s_rx_ch_put), + SOC_ENUM_EXT("PRIM_META_MI2S_RX Format", mi2s_rx_format, + msm_meta_mi2s_rx_format_get, + msm_meta_mi2s_rx_format_put), + SOC_ENUM_EXT("SEC_META_MI2S_RX Format", mi2s_rx_format, + msm_meta_mi2s_rx_format_get, + msm_meta_mi2s_rx_format_put), SOC_ENUM_EXT("PRIM_AUX_PCM_RX Format", aux_pcm_rx_format, msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put), SOC_ENUM_EXT("PRIM_AUX_PCM_TX Format", aux_pcm_tx_format, @@ -4761,6 +4951,25 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, channels->min = channels->max = mi2s_tx_cfg[SEN_MI2S].channels; break; + + case MSM_BACKEND_DAI_PRI_META_MI2S_RX: + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + meta_mi2s_rx_cfg[PRIM_META_MI2S].bit_format); + rate->min = rate->max = + meta_mi2s_rx_cfg[PRIM_META_MI2S].sample_rate; + channels->min = channels->max = + meta_mi2s_rx_cfg[PRIM_META_MI2S].channels; + break; + + case MSM_BACKEND_DAI_SEC_META_MI2S_RX: + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + meta_mi2s_rx_cfg[SEC_META_MI2S].bit_format); + rate->min = rate->max = + meta_mi2s_rx_cfg[SEC_META_MI2S].sample_rate; + channels->min = channels->max = + meta_mi2s_rx_cfg[SEC_META_MI2S].channels; + break; + case MSM_BACKEND_DAI_WSA_CDC_DMA_RX_0: case MSM_BACKEND_DAI_WSA_CDC_DMA_RX_1: idx = msm_cdc_dma_get_idx_from_beid(dai_link->id); @@ -5996,6 +6205,172 @@ static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream) mutex_unlock(&mi2s_intf_conf[index].lock); } +static int msm_meta_mi2s_set_sclk(struct snd_pcm_substream *substream, + int member_id, bool enable) +{ + int ret = 0; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int be_id = 0; + int port_id = 0; + int index = cpu_dai->id; + u32 bit_per_sample = 0; + + switch (member_id) { + case PRIM_MI2S: + be_id = MSM_BACKEND_DAI_PRI_MI2S_RX; + break; + case SEC_MI2S: + be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX; + break; + case TERT_MI2S: + be_id = MSM_BACKEND_DAI_TERTIARY_MI2S_RX; + break; + case QUAT_MI2S: + be_id = MSM_BACKEND_DAI_QUATERNARY_MI2S_RX; + break; + default: + dev_err(rtd->card->dev, "%s: Invalid member_id\n", __func__); + ret = -EINVAL; + goto err; + } + + port_id = msm_get_port_id(be_id); + if (port_id < 0) { + dev_err(rtd->card->dev, "%s: Invalid port_id\n", __func__); + ret = port_id; + goto err; + } + + if (enable) { + bit_per_sample = + get_mi2s_bits_per_sample( + meta_mi2s_rx_cfg[index].bit_format); + mi2s_clk[member_id].clk_freq_in_hz = + meta_mi2s_rx_cfg[index].sample_rate * 2 * + bit_per_sample; + + dev_dbg(rtd->card->dev, "%s: clock rate %ul\n", __func__, + mi2s_clk[member_id].clk_freq_in_hz); + } + + mi2s_clk[member_id].enable = enable; + ret = afe_set_lpass_clock_v2(port_id, &mi2s_clk[member_id]); + if (ret < 0) { + dev_err(rtd->card->dev, + "%s: afe lpass clock failed for port 0x%x , err:%d\n", + __func__, port_id, ret); + goto err; + } + +err: + return ret; +} + +static int msm_meta_mi2s_snd_startup(struct snd_pcm_substream *substream) +{ + int ret = 0; + int i = 0; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int index = cpu_dai->id; + int member_port = 0; + unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS; + struct snd_soc_card *card = rtd->card; + struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); + + dev_dbg(rtd->card->dev, + "%s: substream = %s stream = %d, dai name %s, dai ID %d\n", + __func__, substream->name, substream->stream, + cpu_dai->name, cpu_dai->id); + + if (index < PRIM_META_MI2S || index >= META_MI2S_MAX) { + ret = -EINVAL; + dev_err(rtd->card->dev, + "%s: CPU DAI id (%d) out of range\n", + __func__, cpu_dai->id); + goto err; + } + + for (i = 0; i < meta_mi2s_intf_conf[index].num_member_ports; i++) { + member_port = meta_mi2s_intf_conf[index].member_port[i]; + + if (!mi2s_intf_conf[member_port].msm_is_mi2s_master) { + mi2s_clk[member_port].clk_id = + mi2s_ebit_clk[member_port]; + fmt = SND_SOC_DAIFMT_CBM_CFM; + } + + ret = msm_meta_mi2s_set_sclk(substream, member_port, true); + if (ret < 0) { + dev_err(rtd->card->dev, + "%s: afe lpass clock failed to enable MI2S clock, err:%d\n", + __func__, ret); + goto clk_off; + } + meta_mi2s_intf_conf[index].clk_enable[i] = true; + + if (i == 0) { + ret = snd_soc_dai_set_fmt(cpu_dai, fmt); + if (ret < 0) { + pr_err("%s: set fmt cpu dai failed for META_MI2S (%d), err:%d\n", + __func__, index, ret); + goto clk_off; + } + } + if (pdata->mi2s_gpio_p[member_port]) + msm_cdc_pinctrl_select_active_state( + pdata->mi2s_gpio_p[member_port]); + } + return 0; + +clk_off: + for (i = 0; i < meta_mi2s_intf_conf[index].num_member_ports; i++) { + member_port = meta_mi2s_intf_conf[index].member_port[i]; + if (pdata->mi2s_gpio_p[member_port]) + msm_cdc_pinctrl_select_sleep_state( + pdata->mi2s_gpio_p[member_port]); + + if (meta_mi2s_intf_conf[index].clk_enable[i]) { + msm_meta_mi2s_set_sclk(substream, member_port, false); + meta_mi2s_intf_conf[index].clk_enable[i] = false; + } + } +err: + return ret; +} + +static void msm_meta_mi2s_snd_shutdown(struct snd_pcm_substream *substream) +{ + int ret = 0; + int i = 0; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + int index = rtd->cpu_dai->id; + int member_port = 0; + struct snd_soc_card *card = rtd->card; + struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); + + pr_debug("%s(): substream = %s stream = %d\n", __func__, + substream->name, substream->stream); + if (index < PRIM_MI2S || index >= MI2S_MAX) { + pr_err("%s:invalid MI2S DAI(%d)\n", __func__, index); + return; + } + + for (i = 0; i < meta_mi2s_intf_conf[index].num_member_ports; i++) { + member_port = meta_mi2s_intf_conf[index].member_port[i]; + + if (pdata->mi2s_gpio_p[member_port]) + msm_cdc_pinctrl_select_sleep_state( + pdata->mi2s_gpio_p[member_port]); + + ret = msm_meta_mi2s_set_sclk(substream, member_port, false); + if (ret < 0) + pr_err("%s:clock disable failed for META MI2S (%d); ret=%d\n", + __func__, index, ret); + } +} + static int msm_spdif_set_clk(struct snd_pcm_substream *substream, bool enable) { int ret = 0; @@ -6131,6 +6506,11 @@ static struct snd_soc_ops msm_mi2s_be_ops = { .shutdown = msm_mi2s_snd_shutdown, }; +static struct snd_soc_ops msm_meta_mi2s_be_ops = { + .startup = msm_meta_mi2s_snd_startup, + .shutdown = msm_meta_mi2s_snd_shutdown, +}; + static struct snd_soc_ops msm_auxpcm_be_ops = { .startup = msm_snd_auxpcm_startup, }; @@ -7567,6 +7947,39 @@ static struct snd_soc_dai_link msm_mi2s_be_dai_links[] = { }; +static struct snd_soc_dai_link msm_meta_mi2s_be_dai_links[] = { + { + .name = LPASS_BE_PRI_META_MI2S_RX, + .stream_name = "Primary META MI2S Playback", + .cpu_dai_name = "msm-dai-q6-meta-mi2s.4864", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .id = MSM_BACKEND_DAI_PRI_META_MI2S_RX, + .be_hw_params_fixup = msm_be_hw_params_fixup, + .ops = &msm_meta_mi2s_be_ops, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + }, + { + .name = LPASS_BE_SEC_META_MI2S_RX, + .stream_name = "Secondary META MI2S Playback", + .cpu_dai_name = "msm-dai-q6-meta-mi2s.4866", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .id = MSM_BACKEND_DAI_SEC_META_MI2S_RX, + .be_hw_params_fixup = msm_be_hw_params_fixup, + .ops = &msm_meta_mi2s_be_ops, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + }, +}; + static struct snd_soc_dai_link msm_auxpcm_be_dai_links[] = { /* Primary AUX PCM Backend DAI Links */ { @@ -7885,6 +8298,7 @@ static struct snd_soc_dai_link msm_qcs405_dai_links[ ARRAY_SIZE(msm_tasha_be_dai_links) + ARRAY_SIZE(msm_wcn_be_dai_links) + ARRAY_SIZE(msm_mi2s_be_dai_links) + + ARRAY_SIZE(msm_meta_mi2s_be_dai_links) + ARRAY_SIZE(msm_auxpcm_be_dai_links) + ARRAY_SIZE(msm_va_cdc_dma_be_dai_links) + ARRAY_SIZE(msm_wsa_cdc_dma_be_dai_links) + @@ -8140,7 +8554,7 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) uint32_t tasha_codec = 0, auxpcm_audio_intf = 0; uint32_t va_bolero_codec = 0, wsa_bolero_codec = 0, mi2s_audio_intf = 0; uint32_t spdif_audio_intf = 0, wcn_audio_intf = 0; - uint32_t afe_loopback_intf = 0; + uint32_t afe_loopback_intf = 0, meta_mi2s_intf = 0; const struct of_device_id *match; char __iomem *spdif_cfg, *spdif_pin_ctl; int rc = 0; @@ -8248,6 +8662,22 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) ARRAY_SIZE(msm_mi2s_be_dai_links); } } + + rc = of_property_read_u32(dev->of_node, "qcom,meta-mi2s-intf", + &meta_mi2s_intf); + if (rc) { + dev_dbg(dev, "%s: No DT match META-MI2S interface\n", + __func__); + } else { + if (meta_mi2s_intf) { + memcpy(msm_qcs405_dai_links + total_links, + msm_meta_mi2s_be_dai_links, + sizeof(msm_meta_mi2s_be_dai_links)); + total_links += + ARRAY_SIZE(msm_meta_mi2s_be_dai_links); + } + } + rc = of_property_read_u32(dev->of_node, "qcom,auxpcm-audio-intf", &auxpcm_audio_intf); @@ -8807,6 +9237,81 @@ static void msm_i2s_auxpcm_deinit(void) } } +static void msm_meta_mi2s_init(struct platform_device *pdev) +{ + int rc = 0; + int i = 0; + int index = 0; + bool parse_of = false; + struct snd_soc_card *card = platform_get_drvdata(pdev); + struct snd_soc_dai_link *dai_link = card->dai_link; + + dev_dbg(&pdev->dev, "%s: read from DT\n", __func__); + + for (index = 0; index < META_MI2S_MAX; index++) { + meta_mi2s_intf_conf[index].num_member_ports = 0; + meta_mi2s_intf_conf[index].member_port[0] = 0; + meta_mi2s_intf_conf[index].member_port[1] = 0; + meta_mi2s_intf_conf[index].member_port[2] = 0; + meta_mi2s_intf_conf[index].member_port[3] = 0; + meta_mi2s_intf_conf[index].clk_enable[0] = false; + meta_mi2s_intf_conf[index].clk_enable[1] = false; + meta_mi2s_intf_conf[index].clk_enable[2] = false; + meta_mi2s_intf_conf[index].clk_enable[3] = false; + } + + /* get member port info to set matching clocks for involved ports */ + for (i = 0; i < card->num_links; i++) { + if (dai_link[i].id == MSM_BACKEND_DAI_PRI_META_MI2S_RX) { + parse_of = true; + index = PRIM_META_MI2S; + } else if (dai_link[i].id == MSM_BACKEND_DAI_SEC_META_MI2S_RX) { + parse_of = true; + index = SEC_META_MI2S; + } else { + parse_of = false; + } + if (parse_of && dai_link[i].cpu_of_node) { + rc = of_property_read_u32(dai_link[i].cpu_of_node, + "qcom,msm-mi2s-num-members", + &meta_mi2s_intf_conf[index].num_member_ports); + if (rc) { + dev_err(&pdev->dev, "%s: invalid num from DT file %s\n", + __func__, "qcom,msm-mi2s-num-members"); + } + + if (meta_mi2s_intf_conf[index].num_member_ports > + MAX_NUM_I2S_META_PORT_MEMBER_PORTS) { + dev_err(&pdev->dev, "%s: num-members %d too large from DT file\n", + __func__, + meta_mi2s_intf_conf[index].num_member_ports); + } + + if (meta_mi2s_intf_conf[index].num_member_ports > 0) { + rc = of_property_read_u32_array( + dai_link[i].cpu_of_node, + "qcom,msm-mi2s-member-id", + meta_mi2s_intf_conf[index].member_port, + meta_mi2s_intf_conf[index].num_member_ports); + if (rc) { + dev_err(&pdev->dev, "%s: member-id from DT file %s\n", + __func__, + "qcom,msm-mi2s-member-id"); + } + } + + dev_dbg(&pdev->dev, "dev name %s num-members=%d\n", + dev_name(&pdev->dev), + meta_mi2s_intf_conf[index].num_member_ports); + dev_dbg(&pdev->dev, "member array (%d, %d, %d, %d)\n", + meta_mi2s_intf_conf[index].member_port[0], + meta_mi2s_intf_conf[index].member_port[1], + meta_mi2s_intf_conf[index].member_port[2], + meta_mi2s_intf_conf[index].member_port[3]); + } + } +} + static int msm_scan_i2c_addr(struct platform_device *pdev, uint32_t busnum, uint32_t addr) { @@ -8984,6 +9489,8 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) if (val) { pdata->codec_is_csra = true; mi2s_rx_cfg[PRIM_MI2S].bit_format = SNDRV_PCM_FORMAT_S24_LE; + meta_mi2s_rx_cfg[PRIM_META_MI2S].bit_format = + SNDRV_PCM_FORMAT_S24_LE; ret = msm_init_csra_dev(pdev, card); if (ret) goto err; @@ -9065,6 +9572,8 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) msm_i2s_auxpcm_init(pdev); + msm_meta_mi2s_init(pdev); + is_initial_boot = true; return 0; err: