diff --git a/Makefile.am b/Makefile.am index 5e3faccf5492..5a1b82f16a5f 100755 --- a/Makefile.am +++ b/Makefile.am @@ -15,6 +15,9 @@ endif ifeq ($(TARGET_SUPPORT), qrbx210) KBUILD_OPTIONS += CONFIG_ARCH_BENGAL=y endif +ifeq ($(TARGET_SUPPORT), qrb5165) +KBUILD_OPTIONS += CONFIG_ARCH_KONA=y +endif subdir-ccflags-y += -I$(AUDIO_ROOT)/include/uapi/ @@ -39,12 +42,18 @@ obj-m += asoc/codecs/bolero/ obj-m += asoc/codecs/wcd937x/ KBUILD_CFLAGS += -Wno-error endif +ifeq ($(TARGET_SUPPORT), $(filter $(TARGET_SUPPORT), qrb5165)) +obj-m += asoc/codecs/bolero/ +obj-m += asoc/codecs/wcd938x/ +bj-m += asoc/codecs/wsa883x/ +KBUILD_CFLAGS += -Wno-error +endif ifeq ($(TARGET_SUPPORT), sdmsteppe) obj-m += asoc/codecs/bolero/ obj-m += asoc/codecs/wcd937x/ endif -ifeq ($(TARGET_SUPPORT), $(filter $(TARGET_SUPPORT), sa8155 sa8155ivi sa6155 sa8195 qtiquingvm qtiquingvm8295 sa8295 qtigvmi3)) +ifeq ($(TARGET_SUPPORT), $(filter $(TARGET_SUPPORT), sa8155 sa8155ivi sa6155 sa8195 qtiquingvm qtiquingvm8295 sa8295)) KBUILD_OPTIONS += CONFIG_SND_SOC_AUTO=y obj-m := ipc/ obj-m += dsp/ @@ -57,14 +66,22 @@ endif ifeq ($(TARGET_SUPPORT), $(filter $(TARGET_SUPPORT), sa6155)) KBUILD_OPTIONS += CONFIG_SND_SOC_SA6155=m endif -ifeq ($(TARGET_SUPPORT), $(filter $(TARGET_SUPPORT), qtiquingvm qtigvmi3)) +ifeq ($(TARGET_SUPPORT), $(filter $(TARGET_SUPPORT), qtiquingvm)) KBUILD_OPTIONS += CONFIG_SND_SOC_GVM=m endif ifeq ($(TARGET_SUPPORT), $(filter $(TARGET_SUPPORT), qtiquingvm8295)) KBUILD_OPTIONS += CONFIG_SND_SOC_GVM_SA8295=m endif endif - +ifeq ($(AR_SUPPORT), $(filter $(AR_SUPPORT), yes)) +obj-m := ipc/ +obj-m += dsp/ +obj-m += asoc/ +obj-m += asoc/codecs/ +obj-m += soc/ +KBUILD_OPTIONS += CONFIG_SND_SOC_AUTO=y +KBUILD_OPTIONS += CONFIG_SND_SOC_AR=m +endif all: $(shell rm -fr $(shell pwd)/soc/core.h) $(shell ln -s $(KERNEL_SRC)/drivers/pinctrl/core.h $(shell pwd)/soc/core.h) diff --git a/asoc/Kbuild b/asoc/Kbuild old mode 100644 new mode 100755 index 8f105ae11d28..84aaa73b3eeb --- a/asoc/Kbuild +++ b/asoc/Kbuild @@ -29,6 +29,11 @@ ifeq ($(CONFIG_SND_SOC_AUTO), y) export INCS += -include $(AUDIO_ROOT)/config/gvmautoconf.h endif + ifdef CONFIG_SND_SOC_AR + include $(AUDIO_ROOT)/config/arauto.conf + export + INCS += -include $(AUDIO_ROOT)/config/arautoconf.h + endif ifdef CONFIG_SND_SOC_GVM_SA8295 include $(AUDIO_ROOT)/config/sa8295gvmauto.conf export diff --git a/asoc/codecs/Kbuild b/asoc/codecs/Kbuild index 0e842ee1bf6c..8f19011f6f02 100755 --- a/asoc/codecs/Kbuild +++ b/asoc/codecs/Kbuild @@ -29,6 +29,11 @@ ifeq ($(CONFIG_SND_SOC_AUTO), y) export INCS += -include $(AUDIO_ROOT)/config/gvmautoconf.h endif + ifdef CONFIG_SND_SOC_AR + include $(AUDIO_ROOT)/config/arauto.conf + export + INCS += -include $(AUDIO_ROOT)/config/arautoconf.h + endif ifdef CONFIG_SND_SOC_GVM_SA8295 include $(AUDIO_ROOT)/config/sa8295gvmauto.conf export diff --git a/asoc/codecs/wcd937x/wcd937x.c b/asoc/codecs/wcd937x/wcd937x.c index a563dca20e81..24de137ad11f 100644 --- a/asoc/codecs/wcd937x/wcd937x.c +++ b/asoc/codecs/wcd937x/wcd937x.c @@ -505,7 +505,8 @@ static int wcd937x_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMU: if ((snd_soc_component_read32(component, WCD937X_DIGITAL_EFUSE_REG_16) == 0x02) && - hph_mode == CLS_H_ULP) + ((snd_soc_component_read32(component, + WCD937X_ANA_HPH) & 0x0C) == 0x0C)) snd_soc_component_update_bits(component, WCD937X_RX_BIAS_HPH_LOWPOWER, 0xF0, 0x90); if (hph_mode == CLS_AB_HIFI || hph_mode == CLS_H_HIFI) @@ -551,7 +552,8 @@ static int wcd937x_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMD: if ((snd_soc_component_read32(component, WCD937X_DIGITAL_EFUSE_REG_16) == 0x02) && - hph_mode == CLS_H_ULP) + ((snd_soc_component_read32(component, + WCD937X_ANA_HPH) & 0x0C) == 0x0C)) snd_soc_component_update_bits(component, WCD937X_RX_BIAS_HPH_LOWPOWER, 0xF0, 0x80); snd_soc_component_update_bits(component, @@ -589,7 +591,8 @@ static int wcd937x_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMU: if ((snd_soc_component_read32(component, WCD937X_DIGITAL_EFUSE_REG_16) == 0x02) && - hph_mode == CLS_H_ULP) + ((snd_soc_component_read32(component, + WCD937X_ANA_HPH) & 0x0C) == 0x0C)) snd_soc_component_update_bits(component, WCD937X_RX_BIAS_HPH_LOWPOWER, 0xF0, 0x90); if (hph_mode == CLS_AB_HIFI || hph_mode == CLS_H_HIFI) @@ -635,7 +638,8 @@ static int wcd937x_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMD: if ((snd_soc_component_read32(component, WCD937X_DIGITAL_EFUSE_REG_16) == 0x02) && - hph_mode == CLS_H_ULP) + ((snd_soc_component_read32(component, + WCD937X_ANA_HPH) & 0x0C) == 0x0C)) snd_soc_component_update_bits(component, WCD937X_RX_BIAS_HPH_LOWPOWER, 0xF0, 0x80); snd_soc_component_update_bits(component, diff --git a/asoc/codecs/wcd938x/internal.h b/asoc/codecs/wcd938x/internal.h index 7da5b36875f7..9a86ddf4bf8f 100644 --- a/asoc/codecs/wcd938x/internal.h +++ b/asoc/codecs/wcd938x/internal.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _WCD938X_INTERNAL_H @@ -110,6 +111,7 @@ struct wcd938x_priv { /* wcd to swr dmic notification */ bool notify_swr_dmic; struct blocking_notifier_head notifier; + int micb_enabled[WCD938X_MAX_MICBIAS]; }; struct wcd938x_micbias_setting { diff --git a/asoc/codecs/wcd938x/wcd938x.c b/asoc/codecs/wcd938x/wcd938x.c index b8e05ae02f33..eae9dfb280b2 100644 --- a/asoc/codecs/wcd938x/wcd938x.c +++ b/asoc/codecs/wcd938x/wcd938x.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -2919,6 +2920,95 @@ static int wcd938x_bcs_put(struct snd_kcontrol *kcontrol, return 0; } +/* + * wcd938x_codec_enable_standalone_micbias - enable micbias standalone + * @component: pointer to component instance + * @micb_num: number of micbias to be enabled + * @enable: true to enable micbias or false to disable + * + * This function is used to enable micbias (1, 2, 3 or 4) during + * standalone independent of whether TX use-case is running or not + * + * Return: error code in case of failure or 0 for success + */ + +int wcd938x_codec_enable_standalone_micbias(struct snd_soc_component *component, + int micb_num, + bool enable) +{ + const char * const micb_names[] = { + DAPM_MICBIAS1_STANDALONE, DAPM_MICBIAS2_STANDALONE, + DAPM_MICBIAS3_STANDALONE, DAPM_MICBIAS4_STANDALONE + }; + int micb_index = micb_num - 1; + int rc; + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + + if ((micb_index < 0) || (micb_index > WCD938X_MAX_MICBIAS - 1)) { + dev_err(component->dev, "%s: Invalid micbias index, micb_ind:%d\n", + __func__, micb_index); + return -EINVAL; + } + + if (enable) + rc = snd_soc_dapm_force_enable_pin( + dapm, + micb_names[micb_index]); + else + rc = snd_soc_dapm_disable_pin( + dapm, + micb_names[micb_index]); + if (!rc) + snd_soc_dapm_sync(dapm); + else + dev_err(component->dev, "%s: micbias%d force %s pin failed\n", + __func__, micb_num, (enable ? "enable" : "disable")); + + return rc; +} +EXPORT_SYMBOL(wcd938x_codec_enable_standalone_micbias); + +static int wcd938x_get_micbias(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + int micb_num = ((struct soc_multi_mixer_control *) + kcontrol->private_value)->shift; + + ucontrol->value.integer.value[0] = wcd938x->micb_enabled[micb_num - 1]; + return 0; +} + +static int wcd938x_set_micbias(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + int micb_num = ((struct soc_multi_mixer_control *) + kcontrol->private_value)->shift; + int value = ucontrol->value.integer.value[0]; + bool enable; + int ret; + + if ((micb_num != MIC_BIAS_1) && (micb_num != MIC_BIAS_2) && + (micb_num != MIC_BIAS_3) && (micb_num != MIC_BIAS_4)) + return -EINVAL; + + enable = !!value; + ret = wcd938x_codec_enable_standalone_micbias(component, micb_num, + enable); + if (ret) { + dev_err(component->dev, "%s: Failed to enable standalone micb:%d\n", + __func__, micb_num); + return ret; + } + + wcd938x->micb_enabled[micb_num - 1] = enable; + return ret; +} + static const char * const tx_mode_mux_text_wcd9380[] = { "ADC_INVALID", "ADC_HIFI", "ADC_LO_HIF", "ADC_NORMAL", "ADC_LP", }; @@ -3045,6 +3135,14 @@ static const struct snd_kcontrol_new wcd938x_snd_controls[] = { wcd938x_tx_master_ch_get, wcd938x_tx_master_ch_put), SOC_ENUM_EXT("DMIC7 ChMap", tx_master_ch_enum, wcd938x_tx_master_ch_get, wcd938x_tx_master_ch_put), + SOC_SINGLE_EXT("MIC BIAS1 Standalone", SND_SOC_NOPM, MIC_BIAS_1, 1, 0, + wcd938x_get_micbias, wcd938x_set_micbias), + SOC_SINGLE_EXT("MIC BIAS2 Standalone", SND_SOC_NOPM, MIC_BIAS_2, 1, 0, + wcd938x_get_micbias, wcd938x_set_micbias), + SOC_SINGLE_EXT("MIC BIAS3 Standalone", SND_SOC_NOPM, MIC_BIAS_3, 1, 0, + wcd938x_get_micbias, wcd938x_set_micbias), + SOC_SINGLE_EXT("MIC BIAS4 Standalone", SND_SOC_NOPM, MIC_BIAS_4, 1, 0, + wcd938x_get_micbias, wcd938x_set_micbias), }; static const struct snd_kcontrol_new adc1_switch[] = { diff --git a/asoc/codecs/wsa881x-analog.c b/asoc/codecs/wsa881x-analog.c index 14d027ac141f..965fc56831ed 100755 --- a/asoc/codecs/wsa881x-analog.c +++ b/asoc/codecs/wsa881x-analog.c @@ -274,7 +274,8 @@ static int wsa881x_i2c_read_device(struct wsa881x_pdata *wsa881x, } pr_debug("read success reg = %x val = %x\n", reg, val); - } else { + } else if (wsa881x->client[wsa881x_index]) { + reg_addr = (u8)reg; msg = &wsa881x->xfer_msg[0]; msg->addr = wsa881x->client[wsa881x_index]->addr; @@ -302,6 +303,9 @@ static int wsa881x_i2c_read_device(struct wsa881x_pdata *wsa881x, } } val = dest[0]; + } else { + pr_err("failed for i2c client is not initilized\n"); + return -EINVAL; } return val; } @@ -1202,15 +1206,16 @@ static int wsa881x_probe(struct snd_soc_component *component) wsa881x_temp_reg_read; snd_soc_component_set_drvdata(component, &wsa_pdata[wsa881x_index]); while (retry) { - if (wsa_pdata[wsa881x_index].regmap[WSA881X_ANALOG_SLAVE] - != NULL) + if (wsa_pdata[wsa881x_index].regmap_flag) break; msleep(100); retry--; } - if (!retry) + if (!retry) { dev_err(&client->dev, "%s: max retry expired and regmap of\n" "analog slave not initilized\n", __func__); + return -EPROBE_DEFER; + } wsa881x_init_thermal(&wsa_pdata[wsa881x_index].tz_pdata); INIT_DELAYED_WORK(&wsa_pdata[wsa881x_index].ocp_ctl_work, wsa881x_ocp_ctl_work); diff --git a/asoc/kona.c b/asoc/kona.c index 06b4fd167299..93ae611b8aa4 100644 --- a/asoc/kona.c +++ b/asoc/kona.c @@ -198,6 +198,8 @@ struct msm_asoc_mach_data { struct clk *lpass_audio_hw_vote; int core_audio_vote_count; u32 tdm_max_slots; /* Max TDM slots used */ + int wcd_disabled; + u32 wsa_max_devs; }; struct tdm_port { @@ -905,6 +907,9 @@ static int dmic_4_5_gpio_cnt; static void *def_wcd_mbhc_cal(void); +static int msm_rx_tx_codec_init(struct snd_soc_pcm_runtime*); +static int msm_int_wsa_init(struct snd_soc_pcm_runtime*); + /* * Need to report LINEIN * if R/L channel impedance is larger than 5K ohm @@ -932,6 +937,68 @@ static struct wcd_mbhc_config wcd_mbhc_cfg = { .moisture_duty_cycle_en = true, }; +/* set audio task affinity to core 1 & 2 */ +static const unsigned int audio_core_list[] = {1, 2}; +static cpumask_t audio_cpu_map = CPU_MASK_NONE; +static struct dev_pm_qos_request *msm_audio_req; +static unsigned int qos_client_active_cnt; + +static void msm_audio_add_qos_request(void) +{ + int i; + int cpu = 0; + + msm_audio_req = kcalloc(num_possible_cpus(), + sizeof(struct dev_pm_qos_request), GFP_KERNEL); + if (!msm_audio_req) + return; + + for (i = 0; i < ARRAY_SIZE(audio_core_list); i++) { + if (audio_core_list[i] >= num_possible_cpus()) + pr_err("%s incorrect cpu id: %d specified.\n", + __func__, audio_core_list[i]); + else + cpumask_set_cpu(audio_core_list[i], &audio_cpu_map); + } + + for_each_cpu(cpu, &audio_cpu_map) { + dev_pm_qos_add_request(get_cpu_device(cpu), + &msm_audio_req[cpu], + DEV_PM_QOS_RESUME_LATENCY, + PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE); + pr_debug("%s set cpu affinity to core %d.\n", __func__, cpu); + } +} + +static void msm_audio_remove_qos_request(void) +{ + int cpu = 0; + + if (msm_audio_req) { + for_each_cpu(cpu, &audio_cpu_map) { + dev_pm_qos_remove_request( + &msm_audio_req[cpu]); + pr_debug("%s remove cpu affinity of core %d.\n", + __func__, cpu); + } + kfree(msm_audio_req); + } +} + +static void msm_audio_update_qos_request(u32 latency) +{ + int cpu = 0; + + if (msm_audio_req) { + for_each_cpu(cpu, &audio_cpu_map) { + dev_pm_qos_update_request( + &msm_audio_req[cpu], latency); + pr_debug("%s update latency of core %d to %ul.\n", + __func__, cpu, latency); + } + } +} + static inline int param_is_mask(int p) { return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) && @@ -4990,24 +5057,26 @@ err: static int msm_fe_qos_prepare(struct snd_pcm_substream *substream) { - cpumask_t mask; - if (pm_qos_request_active(&substream->latency_pm_qos_req)) pm_qos_remove_request(&substream->latency_pm_qos_req); - cpumask_clear(&mask); - cpumask_set_cpu(1, &mask); /* affine to core 1 */ - cpumask_set_cpu(2, &mask); /* affine to core 2 */ - cpumask_copy(&substream->latency_pm_qos_req.cpus_affine, &mask); + qos_client_active_cnt++; + if (qos_client_active_cnt == 1) + msm_audio_update_qos_request(MSM_LL_QOS_VALUE); - substream->latency_pm_qos_req.type = PM_QOS_REQ_AFFINE_CORES; - - pm_qos_add_request(&substream->latency_pm_qos_req, - PM_QOS_CPU_DMA_LATENCY, - MSM_LL_QOS_VALUE); return 0; } +static void msm_fe_qos_shutdown(struct snd_pcm_substream *substream) +{ + (void)substream; + + if (qos_client_active_cnt > 0) + qos_client_active_cnt--; + if (qos_client_active_cnt == 0) + msm_audio_update_qos_request(PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE); +} + void mi2s_disable_audio_vote(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; @@ -5275,6 +5344,7 @@ static struct snd_soc_ops msm_mi2s_be_ops = { static struct snd_soc_ops msm_fe_qos_ops = { .prepare = msm_fe_qos_prepare, + .shutdown = msm_fe_qos_shutdown, }; static struct snd_soc_ops msm_cdc_dma_be_ops = { @@ -5466,17 +5536,86 @@ static void msm_add_auxpcm_snd_controls(struct snd_soc_component *component) } #endif -static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd) +static int msm_int_wsa_init(struct snd_soc_pcm_runtime *rtd) +{ + u8 spkleft_ports[WSA881X_MAX_SWR_PORTS] = {0, 1, 2, 3}; + u8 spkright_ports[WSA881X_MAX_SWR_PORTS] = {0, 1, 2, 3}; + u8 spkleft_port_types[WSA881X_MAX_SWR_PORTS] = {SPKR_L, SPKR_L_COMP, + SPKR_L_BOOST, SPKR_L_VI}; + u8 spkright_port_types[WSA881X_MAX_SWR_PORTS] = {SPKR_R, SPKR_R_COMP, + SPKR_R_BOOST, SPKR_R_VI}; + unsigned int ch_rate[WSA881X_MAX_SWR_PORTS] = {2400, 600, 300, 1200}; + unsigned int ch_mask[WSA881X_MAX_SWR_PORTS] = {0x1, 0xF, 0x3, 0x3}; + struct snd_soc_component *component = NULL; + struct snd_soc_dapm_context *dapm = NULL; + struct msm_asoc_mach_data *pdata = + snd_soc_card_get_drvdata(rtd->card); + int wsa_active_devs = 0; + + if (pdata->wsa_max_devs > 0) { + component = snd_soc_rtdcom_lookup(rtd, "wsa-codec.1"); + if (component) { + dapm = snd_soc_component_get_dapm(component); + + wsa881x_set_channel_map(component, &spkleft_ports[0], + WSA883X_MAX_SWR_PORTS, &ch_mask[0], + &ch_rate[0], &spkleft_port_types[0]); + + if (dapm->component) { + snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft IN"); + snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft SPKR"); + } + /* + * Send speaker configuration only for WSA8810. + * Default configuration is for WSA8815. + */ + wsa_macro_set_spkr_mode(component,WSA_MACRO_SPKR_MODE_1); + wsa_macro_set_spkr_gain_offset(component,WSA_MACRO_GAIN_OFFSET_M1P5_DB); + wsa881x_codec_info_create_codec_entry(pdata->codec_root, + component); + + wsa_active_devs++; + } else { + pr_info("%s: wsa-codec.1 component is NULL\n", __func__); + } + } + + /* If current platform has more than one WSA */ + if (pdata->wsa_max_devs > wsa_active_devs) { + component = snd_soc_rtdcom_lookup(rtd, "wsa-codec.2"); + if (!component) { + pr_err("%s: wsa-codec.2 component is NULL\n", __func__); + pr_err("%s: %d WSA is found. Expect %d WSA.", + __func__, wsa_active_devs, pdata->wsa_max_devs); + return -EINVAL; + } + + dapm = snd_soc_component_get_dapm(component); + + wsa881x_set_channel_map(component, &spkright_ports[0], + WSA883X_MAX_SWR_PORTS, &ch_mask[0], + &ch_rate[0], &spkright_port_types[0]); + + if (dapm->component) { + snd_soc_dapm_ignore_suspend(dapm, "SpkrRight IN"); + snd_soc_dapm_ignore_suspend(dapm, "SpkrRight SPKR"); + } + wsa881x_codec_info_create_codec_entry(pdata->codec_root, + component); + } + + return 0; +} + +static int msm_rx_tx_codec_init(struct snd_soc_pcm_runtime *rtd) { int ret = -EINVAL; - struct snd_soc_component *component; - struct snd_soc_dapm_context *dapm; - struct snd_card *card; + struct snd_soc_component *component = NULL; + struct snd_soc_component *bolero_component = NULL; + struct snd_soc_dapm_context *dapm = NULL; + struct snd_card *card = NULL; struct snd_info_entry *entry; - struct snd_soc_component *aux_comp; - struct platform_device *pdev = NULL; - int i = 0; - bool is_wcd937x_used = false; + int codec_variant = -1; char *data = NULL; struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(rtd->card); @@ -5486,6 +5625,8 @@ static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd) pr_err("%s: could not find component for bolero_codec\n", __func__); return ret; + } else { + bolero_component = component; } dapm = snd_soc_component_get_dapm(component); @@ -5534,87 +5675,104 @@ static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_sync(dapm); - /* - * Send speaker configuration only for WSA8810. - * Default configuration is for WSA8815. - */ - dev_dbg(component->dev, "%s: Number of aux devices: %d\n", - __func__, rtd->card->num_aux_devs); - if (rtd->card->num_aux_devs && - !list_empty(&rtd->card->component_dev_list)) { - list_for_each_entry(aux_comp, - &rtd->card->aux_comp_list, - card_aux_list) { - if (aux_comp->name != NULL && ( - !strcmp(aux_comp->name, WSA8810_NAME_1) || - !strcmp(aux_comp->name, WSA8810_NAME_2))) { - wsa_macro_set_spkr_mode(component, - WSA_MACRO_SPKR_MODE_1); - wsa_macro_set_spkr_gain_offset(component, - WSA_MACRO_GAIN_OFFSET_M1P5_DB); - } else if (aux_comp->name != NULL && ( - !strcmp(aux_comp->name, WSA8815_NAME_1) || - !strcmp(aux_comp->name, WSA8815_NAME_2))) { - wsa_macro_set_spkr_mode(component, - WSA_MACRO_SPKR_MODE_DEFAULT); - } - } - } - - for (i = 0; i < rtd->card->num_aux_devs; i++) - { - if (msm_aux_dev[i].name != NULL ) { - if (strstr(msm_aux_dev[i].name, "wsa")) - continue; - } - - if (msm_aux_dev[i].codec_of_node) { - pdev = of_find_device_by_node( - msm_aux_dev[i].codec_of_node); - - if (pdev) - data = (char*) of_device_get_match_data( - &pdev->dev); - if (data != NULL) { - if (!strncmp(data, "wcd937x", - sizeof("wcd937x"))) { - is_wcd937x_used = true; - break; - } - } - } - } - - if (is_wcd937x_used) { - bolero_set_port_map(component, - ARRAY_SIZE(sm_port_map_wcd937x), - sm_port_map_wcd937x); - } else if (pdata->lito_v2_enabled) { - /* - * Enable tx data line3 for saipan version v2 and - * write corresponding lpi register. - */ - bolero_set_port_map(component, ARRAY_SIZE(sm_port_map_v2), - sm_port_map_v2); - } else { - bolero_set_port_map(component, ARRAY_SIZE(sm_port_map), - sm_port_map); - } - card = rtd->card->snd_card; + if (!pdata->codec_root) { entry = msm_snd_info_create_subdir(card->module, "codecs", card->proc_root); if (!entry) { pr_debug("%s: Cannot create codecs module entry\n", __func__); - ret = 0; - goto err; + return 0; } pdata->codec_root = entry; } bolero_info_create_codec_entry(pdata->codec_root, component); bolero_register_wake_irq(component, false); + + /* + * Send speaker configuration only for WSA8810. + * Default configuration is for WSA8815. + */ + component = snd_soc_rtdcom_lookup(rtd, "wsa-codec.1"); + if (!component) { + component = snd_soc_rtdcom_lookup(rtd, "wsa-codec.3"); + if (!component) { + pr_debug("%s: wsa-codec.3 component is NULL\n", + __func__); + } else { + wsa_macro_set_spkr_mode(bolero_component,WSA_MACRO_SPKR_MODE_DEFAULT); + } + } else { + wsa_macro_set_spkr_mode(bolero_component,WSA_MACRO_SPKR_MODE_1); + wsa_macro_set_spkr_gain_offset(bolero_component,WSA_MACRO_GAIN_OFFSET_M1P5_DB); + } + + if (pdata->wcd_disabled) { + codec_reg_done = true; + return 0; + } + + component = snd_soc_rtdcom_lookup(rtd, WCD938X_DRV_NAME); + if (!component) { + component = snd_soc_rtdcom_lookup(rtd, WCD937X_DRV_NAME); + if (!component) { + pr_err("%s component is NULL\n", __func__); + return -EINVAL; + } + } + dapm = snd_soc_component_get_dapm(component); + card = component->card->snd_card; + + snd_soc_dapm_ignore_suspend(dapm, "EAR"); + snd_soc_dapm_ignore_suspend(dapm, "AUX"); + snd_soc_dapm_ignore_suspend(dapm, "HPHL"); + snd_soc_dapm_ignore_suspend(dapm, "HPHR"); + snd_soc_dapm_ignore_suspend(dapm, "AMIC1"); + snd_soc_dapm_ignore_suspend(dapm, "AMIC2"); + snd_soc_dapm_ignore_suspend(dapm, "AMIC3"); + snd_soc_dapm_ignore_suspend(dapm, "AMIC4"); + snd_soc_dapm_sync(dapm); + + if (!strncmp(component->driver->name, "wcd937x", 7)) { + wcd937x_info_create_codec_entry(pdata->codec_root, component); + ret = snd_soc_add_component_controls(component, + msm_int_wcd937x_snd_controls, + ARRAY_SIZE(msm_int_wcd937x_snd_controls)); + bolero_set_port_map(bolero_component, + ARRAY_SIZE(sm_port_map_wcd937x), + sm_port_map_wcd937x); + } else { + wcd938x_info_create_codec_entry(pdata->codec_root, component); + codec_variant = wcd938x_get_codec_variant(component); + dev_dbg(component->dev, "%s: variant %d\n", __func__, codec_variant); + if (codec_variant == WCD9380) + ret = snd_soc_add_component_controls(bolero_component, + msm_int_wcd9380_snd_controls, + ARRAY_SIZE(msm_int_wcd9380_snd_controls)); + else if (codec_variant == WCD9385) + ret = snd_soc_add_component_controls(bolero_component, + msm_int_wcd9385_snd_controls, + ARRAY_SIZE(msm_int_wcd9385_snd_controls)); + if (pdata->lito_v2_enabled) { + /* + * Enable tx data line3 for saipan version v2 and + * write corresponding lpi register. + */ + bolero_set_port_map(component, ARRAY_SIZE(sm_port_map_v2), + sm_port_map_v2); + } else { + bolero_set_port_map(component, ARRAY_SIZE(sm_port_map), + sm_port_map); + } + } + + if (ret < 0) { + dev_err(component->dev, "%s: add codec specific snd controls failed: %d\n", + __func__, ret); + return ret; + } + codec_reg_done = true; return 0; err: @@ -6811,7 +6969,7 @@ static struct snd_soc_dai_link msm_wsa_cdc_dma_be_dai_links[] = { .stream_name = "WSA CDC DMA0 Playback", .no_pcm = 1, .dpcm_playback = 1, - .init = &msm_int_audrx_init, + .init = &msm_int_wsa_init, .id = MSM_BACKEND_DAI_WSA_CDC_DMA_RX_0, .be_hw_params_fixup = msm_be_hw_params_fixup, .ignore_pmdown_time = 1, @@ -6869,6 +7027,7 @@ static struct snd_soc_dai_link msm_rx_tx_cdc_dma_be_dai_links[] = { .ignore_suspend = 1, .ops = &msm_cdc_dma_be_ops, SND_SOC_DAILINK_REG(rx_dma_rx0), + .init = &msm_rx_tx_codec_init, }, { .name = LPASS_BE_RX_CDC_DMA_RX_1, @@ -7181,6 +7340,62 @@ static const struct of_device_id kona_asoc_machine_of_match[] = { {}, }; +static int msm_snd_card_late_probe(struct snd_soc_card *card) +{ + struct snd_soc_component *component = NULL; + const char *be_dl_name = LPASS_BE_RX_CDC_DMA_RX_0; + struct snd_soc_pcm_runtime *rtd; + struct msm_asoc_mach_data *pdata; + int ret = 0; + void *mbhc_calibration; + bool is_wcd937x = false; + + pdata = snd_soc_card_get_drvdata(card); + if (!pdata) + return -EINVAL; + + if (pdata->wcd_disabled) + return 0; + + rtd = snd_soc_get_pcm_runtime(card, be_dl_name); + if (!rtd) { + dev_err(card->dev, + "%s: snd_soc_get_pcm_runtime for %s failed!\n", + __func__, be_dl_name); + return -EINVAL; + } + + component = snd_soc_rtdcom_lookup(rtd, WCD938X_DRV_NAME); + if (!component) { + component = snd_soc_rtdcom_lookup(rtd, WCD937X_DRV_NAME); + if (!component) { + pr_err("%s component is NULL\n", __func__); + return -EINVAL; + } else { + is_wcd937x = true; + } + } + + mbhc_calibration = def_wcd_mbhc_cal(); + if (!mbhc_calibration) + return -ENOMEM; + wcd_mbhc_cfg.calibration = mbhc_calibration; + if (!is_wcd937x) + ret = wcd938x_mbhc_hs_detect(component, &wcd_mbhc_cfg); + else + ret = wcd937x_mbhc_hs_detect(component, &wcd_mbhc_cfg); + if (ret) { + dev_err(component->dev, "%s: mbhc hs detect failed, err:%d\n", + __func__, ret); + goto err_hs_detect; + } + return 0; + +err_hs_detect: + kfree(mbhc_calibration); + return ret; +} + static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) { struct snd_soc_card *card = NULL; @@ -7350,470 +7565,12 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) if (card) { card->dai_link = dailink; card->num_links = total_links; + card->late_probe = msm_snd_card_late_probe; } return card; } -static int msm_wsa881x_init(struct snd_soc_component *component) -{ - u8 spkleft_ports[WSA881X_MAX_SWR_PORTS] = {0, 1, 2, 3}; - u8 spkright_ports[WSA881X_MAX_SWR_PORTS] = {0, 1, 2, 3}; - u8 spkleft_port_types[WSA881X_MAX_SWR_PORTS] = {SPKR_L, SPKR_L_COMP, - SPKR_L_BOOST, SPKR_L_VI}; - u8 spkright_port_types[WSA881X_MAX_SWR_PORTS] = {SPKR_R, SPKR_R_COMP, - SPKR_R_BOOST, SPKR_R_VI}; - unsigned int ch_rate[WSA881X_MAX_SWR_PORTS] = {2400, 600, 300, 1200}; - unsigned int ch_mask[WSA881X_MAX_SWR_PORTS] = {0x1, 0xF, 0x3, 0x3}; - struct msm_asoc_mach_data *pdata; - struct snd_soc_dapm_context *dapm; - struct snd_card *card; - struct snd_info_entry *entry; - int ret = 0; - - if (!component) { - pr_err("%s component is NULL\n", __func__); - return -EINVAL; - } - - card = component->card->snd_card; - dapm = snd_soc_component_get_dapm(component); - - if (!strcmp(component->name_prefix, "SpkrLeft")) { - dev_dbg(component->dev, "%s: setting left ch map to codec %s\n", - __func__, component->name); - if (strnstr(component->name, "wsa883x", sizeof(component->name))) - wsa883x_set_channel_map(component, &spkleft_ports[0], - WSA881X_MAX_SWR_PORTS, &ch_mask[0], - &ch_rate[0], &spkleft_port_types[0]); - else - wsa881x_set_channel_map(component, &spkleft_ports[0], - WSA881X_MAX_SWR_PORTS, &ch_mask[0], - &ch_rate[0], &spkleft_port_types[0]); - if (dapm->component) { - snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft IN"); - snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft SPKR"); - } - } else if (!strcmp(component->name_prefix, "SpkrRight")) { - dev_dbg(component->dev, "%s: setting right ch map to codec %s\n", - __func__, component->name); - if (strnstr(component->name, "wsa883x", sizeof(component->name))) - wsa883x_set_channel_map(component, &spkright_ports[0], - WSA881X_MAX_SWR_PORTS, &ch_mask[0], - &ch_rate[0], &spkright_port_types[0]); - else - wsa881x_set_channel_map(component, &spkright_ports[0], - WSA881X_MAX_SWR_PORTS, &ch_mask[0], - &ch_rate[0], &spkright_port_types[0]); - if (dapm->component) { - snd_soc_dapm_ignore_suspend(dapm, "SpkrRight IN"); - snd_soc_dapm_ignore_suspend(dapm, "SpkrRight SPKR"); - } - } else { - dev_err(component->dev, "%s: wrong codec name %s\n", __func__, - component->name); - ret = -EINVAL; - goto err; - } - pdata = snd_soc_card_get_drvdata(component->card); - if (!pdata->codec_root) { - entry = msm_snd_info_create_subdir(card->module, "codecs", - card->proc_root); - if (!entry) { - pr_err("%s: Cannot create codecs module entry\n", - __func__); - ret = 0; - goto err; - } - pdata->codec_root = entry; - } - if (strnstr(component->name, "wsa883x", sizeof(component->name))) - wsa883x_codec_info_create_codec_entry(pdata->codec_root, - component); - else - wsa881x_codec_info_create_codec_entry(pdata->codec_root, - component); -err: - return ret; -} - -static int msm_aux_codec_init(struct snd_soc_component *component) -{ - struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); - int ret = 0; - int codec_variant = -1; - void *mbhc_calibration; - struct snd_info_entry *entry; - struct snd_card *card = component->card->snd_card; - struct msm_asoc_mach_data *pdata; - - snd_soc_dapm_ignore_suspend(dapm, "EAR"); - snd_soc_dapm_ignore_suspend(dapm, "AUX"); - snd_soc_dapm_ignore_suspend(dapm, "HPHL"); - snd_soc_dapm_ignore_suspend(dapm, "HPHR"); - snd_soc_dapm_ignore_suspend(dapm, "AMIC1"); - snd_soc_dapm_ignore_suspend(dapm, "AMIC2"); - snd_soc_dapm_ignore_suspend(dapm, "AMIC3"); - snd_soc_dapm_ignore_suspend(dapm, "AMIC4"); - snd_soc_dapm_sync(dapm); - - pdata = snd_soc_card_get_drvdata(component->card); - if (!pdata->codec_root) { - entry = msm_snd_info_create_subdir(card->module, "codecs", - card->proc_root); - if (!entry) { - dev_dbg(component->dev, "%s: Cannot create codecs module entry\n", - __func__); - ret = 0; - goto mbhc_cfg_cal; - } - pdata->codec_root = entry; - } - if (!strncmp(component->driver->name, "wcd937x", 7)) { - wcd937x_info_create_codec_entry(pdata->codec_root, component); - ret = snd_soc_add_component_controls(component, - msm_int_wcd937x_snd_controls, - ARRAY_SIZE(msm_int_wcd937x_snd_controls)); - } else { - wcd938x_info_create_codec_entry(pdata->codec_root, component); - codec_variant = wcd938x_get_codec_variant(component); - dev_dbg(component->dev, "%s: variant %d\n", __func__, codec_variant); - if (codec_variant == WCD9380) - ret = snd_soc_add_component_controls(component, - msm_int_wcd9380_snd_controls, - ARRAY_SIZE(msm_int_wcd9380_snd_controls)); - else if (codec_variant == WCD9385) - ret = snd_soc_add_component_controls(component, - msm_int_wcd9385_snd_controls, - ARRAY_SIZE(msm_int_wcd9385_snd_controls)); - } - - if (ret < 0) { - dev_err(component->dev, "%s: add codec specific snd controls failed: %d\n", - __func__, ret); - return ret; - } - -mbhc_cfg_cal: - mbhc_calibration = def_wcd_mbhc_cal(); - if (!mbhc_calibration) - return -ENOMEM; - wcd_mbhc_cfg.calibration = mbhc_calibration; - if (!strncmp(component->driver->name, "wcd937x", 7)) - ret = wcd937x_mbhc_hs_detect(component, &wcd_mbhc_cfg); - else - ret = wcd938x_mbhc_hs_detect(component, &wcd_mbhc_cfg); - if (ret) { - dev_err(component->dev, "%s: mbhc hs detect failed, err:%d\n", - __func__, ret); - goto err_hs_detect; - } - return 0; - -err_hs_detect: - kfree(mbhc_calibration); - return ret; -} - -static int msm_init_aux_dev(struct platform_device *pdev, - struct snd_soc_card *card) -{ - struct device_node *wsa_of_node; - struct device_node *aux_codec_of_node; - u32 wsa_max_devs; - u32 wsa_dev_cnt; - u32 codec_max_aux_devs = 0; - u32 codec_aux_dev_cnt = 0; - int i; - struct msm_wsa881x_dev_info *wsa881x_dev_info; - struct aux_codec_dev_info *aux_cdc_dev_info; - struct snd_soc_dai_link_component *dlc; - const char *auxdev_name_prefix[1]; - char *dev_name_str = NULL; - int found = 0; - int codecs_found = 0; - int ret = 0; - - dlc = devm_kcalloc(&pdev->dev, 1, - sizeof(struct snd_soc_dai_link_component), - GFP_KERNEL); - /* Get maximum WSA device count for this platform */ - ret = of_property_read_u32(pdev->dev.of_node, - "qcom,wsa-max-devs", &wsa_max_devs); - if (ret) { - dev_info(&pdev->dev, - "%s: wsa-max-devs property missing in DT %s, ret = %d\n", - __func__, pdev->dev.of_node->full_name, ret); - wsa_max_devs = 0; - goto codec_aux_dev; - } - if (wsa_max_devs == 0) { - dev_warn(&pdev->dev, - "%s: Max WSA devices is 0 for this target?\n", - __func__); - goto codec_aux_dev; - } - - /* Get count of WSA device phandles for this platform */ - wsa_dev_cnt = of_count_phandle_with_args(pdev->dev.of_node, - "qcom,wsa-devs", NULL); - if (wsa_dev_cnt == -ENOENT) { - dev_warn(&pdev->dev, "%s: No wsa device defined in DT.\n", - __func__); - goto err; - } else if (wsa_dev_cnt <= 0) { - dev_err(&pdev->dev, - "%s: Error reading wsa device from DT. wsa_dev_cnt = %d\n", - __func__, wsa_dev_cnt); - ret = -EINVAL; - goto err; - } - - /* - * Expect total phandles count to be NOT less than maximum possible - * WSA count. However, if it is less, then assign same value to - * max count as well. - */ - if (wsa_dev_cnt < wsa_max_devs) { - dev_dbg(&pdev->dev, - "%s: wsa_max_devs = %d cannot exceed wsa_dev_cnt = %d\n", - __func__, wsa_max_devs, wsa_dev_cnt); - wsa_max_devs = wsa_dev_cnt; - } - - /* Make sure prefix string passed for each WSA device */ - ret = of_property_count_strings(pdev->dev.of_node, - "qcom,wsa-aux-dev-prefix"); - if (ret != wsa_dev_cnt) { - dev_err(&pdev->dev, - "%s: expecting %d wsa prefix. Defined only %d in DT\n", - __func__, wsa_dev_cnt, ret); - ret = -EINVAL; - goto err; - } - - /* - * Alloc mem to store phandle and index info of WSA device, if already - * registered with ALSA core - */ - wsa881x_dev_info = devm_kcalloc(&pdev->dev, wsa_max_devs, - sizeof(struct msm_wsa881x_dev_info), - GFP_KERNEL); - if (!wsa881x_dev_info) { - ret = -ENOMEM; - goto err; - } - - /* - * search and check whether all WSA devices are already - * registered with ALSA core or not. If found a node, store - * the node and the index in a local array of struct for later - * use. - */ - for (i = 0; i < wsa_dev_cnt; i++) { - wsa_of_node = of_parse_phandle(pdev->dev.of_node, - "qcom,wsa-devs", i); - if (unlikely(!wsa_of_node)) { - /* we should not be here */ - dev_err(&pdev->dev, - "%s: wsa dev node is not present\n", - __func__); - ret = -EINVAL; - goto err; - } - dlc->of_node = wsa_of_node; - dlc->name = NULL; - if (soc_find_component(dlc)) { - /* WSA device registered with ALSA core */ - wsa881x_dev_info[found].of_node = wsa_of_node; - wsa881x_dev_info[found].index = i; - found++; - if (found == wsa_max_devs) - break; - } - } - - if (found < wsa_max_devs) { - dev_dbg(&pdev->dev, - "%s: failed to find %d components. Found only %d\n", - __func__, wsa_max_devs, found); - return -EPROBE_DEFER; - } - dev_info(&pdev->dev, - "%s: found %d wsa881x devices registered with ALSA core\n", - __func__, found); - -codec_aux_dev: - /* Get maximum aux codec device count for this platform */ - ret = of_property_read_u32(pdev->dev.of_node, - "qcom,codec-max-aux-devs", - &codec_max_aux_devs); - if (ret) { - dev_err(&pdev->dev, - "%s: codec-max-aux-devs property missing in DT %s, ret = %d\n", - __func__, pdev->dev.of_node->full_name, ret); - codec_max_aux_devs = 0; - goto aux_dev_register; - } - if (codec_max_aux_devs == 0) { - dev_dbg(&pdev->dev, - "%s: Max aux codec devices is 0 for this target?\n", - __func__); - goto aux_dev_register; - } - - /* Get count of aux codec device phandles for this platform */ - codec_aux_dev_cnt = of_count_phandle_with_args( - pdev->dev.of_node, - "qcom,codec-aux-devs", NULL); - if (codec_aux_dev_cnt == -ENOENT) { - dev_warn(&pdev->dev, "%s: No aux codec defined in DT.\n", - __func__); - goto err; - } else if (codec_aux_dev_cnt <= 0) { - dev_err(&pdev->dev, - "%s: Error reading aux codec device from DT, dev_cnt=%d\n", - __func__, codec_aux_dev_cnt); - ret = -EINVAL; - goto err; - } - - /* - * Expect total phandles count to be NOT less than maximum possible - * AUX device count. However, if it is less, then assign same value to - * max count as well. - */ - if (codec_aux_dev_cnt < codec_max_aux_devs) { - dev_dbg(&pdev->dev, - "%s: codec_max_aux_devs = %d cannot exceed codec_aux_dev_cnt = %d\n", - __func__, codec_max_aux_devs, - codec_aux_dev_cnt); - codec_max_aux_devs = codec_aux_dev_cnt; - } - - /* - * Alloc mem to store phandle and index info of aux codec - * if already registered with ALSA core - */ - aux_cdc_dev_info = devm_kcalloc(&pdev->dev, codec_aux_dev_cnt, - sizeof(struct aux_codec_dev_info), - GFP_KERNEL); - if (!aux_cdc_dev_info) { - ret = -ENOMEM; - goto err; - } - - /* - * search and check whether all aux codecs are already - * registered with ALSA core or not. If found a node, store - * the node and the index in a local array of struct for later - * use. - */ - for (i = 0; i < codec_aux_dev_cnt; i++) { - aux_codec_of_node = of_parse_phandle(pdev->dev.of_node, - "qcom,codec-aux-devs", i); - if (unlikely(!aux_codec_of_node)) { - /* we should not be here */ - dev_err(&pdev->dev, - "%s: aux codec dev node is not present\n", - __func__); - ret = -EINVAL; - goto err; - } - dlc->of_node = aux_codec_of_node; - dlc->name = NULL; - if (soc_find_component(dlc)) { - /* AUX codec registered with ALSA core */ - aux_cdc_dev_info[codecs_found].of_node = - aux_codec_of_node; - aux_cdc_dev_info[codecs_found].index = i; - codecs_found++; - } - } - - if (codecs_found < codec_aux_dev_cnt) { - dev_dbg(&pdev->dev, - "%s: failed to find %d components. Found only %d\n", - __func__, codec_aux_dev_cnt, codecs_found); - return -EPROBE_DEFER; - } - dev_info(&pdev->dev, - "%s: found %d AUX codecs registered with ALSA core\n", - __func__, codecs_found); - -aux_dev_register: - card->num_aux_devs = wsa_max_devs + codec_aux_dev_cnt; - card->num_configs = wsa_max_devs + codec_aux_dev_cnt; - - /* Alloc array of AUX devs struct */ - msm_aux_dev = devm_kcalloc(&pdev->dev, card->num_aux_devs, - sizeof(struct snd_soc_aux_dev), - GFP_KERNEL); - if (!msm_aux_dev) { - ret = -ENOMEM; - goto err; - } - - /* Alloc array of codec conf struct */ - msm_codec_conf = devm_kcalloc(&pdev->dev, card->num_configs, - sizeof(struct snd_soc_codec_conf), - GFP_KERNEL); - if (!msm_codec_conf) { - ret = -ENOMEM; - goto err; - } - - for (i = 0; i < wsa_max_devs; i++) { - dev_name_str = devm_kzalloc(&pdev->dev, DEV_NAME_STR_LEN, - GFP_KERNEL); - if (!dev_name_str) { - ret = -ENOMEM; - goto err; - } - - ret = of_property_read_string_index(pdev->dev.of_node, - "qcom,wsa-aux-dev-prefix", - wsa881x_dev_info[i].index, - auxdev_name_prefix); - if (ret) { - dev_err(&pdev->dev, - "%s: failed to read wsa aux dev prefix, ret = %d\n", - __func__, ret); - ret = -EINVAL; - goto err; - } - - snprintf(dev_name_str, strlen("wsa881x.%d"), "wsa881x.%d", i); - msm_aux_dev[i].dlc.name = dev_name_str; - msm_aux_dev[i].dlc.dai_name = NULL; - msm_aux_dev[i].dlc.of_node = - wsa881x_dev_info[i].of_node; - msm_aux_dev[i].init = msm_wsa881x_init; - msm_codec_conf[i].dev_name = NULL; - msm_codec_conf[i].name_prefix = auxdev_name_prefix[0]; - msm_codec_conf[i].of_node = - wsa881x_dev_info[i].of_node; - } - - for (i = 0; i < codec_aux_dev_cnt; i++) { - msm_aux_dev[wsa_max_devs + i].dlc.name = NULL; - msm_aux_dev[wsa_max_devs + i].dlc.dai_name = NULL; - msm_aux_dev[wsa_max_devs + i].dlc.of_node = - aux_cdc_dev_info[i].of_node; - msm_aux_dev[wsa_max_devs + i].init = msm_aux_codec_init; - msm_codec_conf[wsa_max_devs + i].dev_name = NULL; - msm_codec_conf[wsa_max_devs + i].name_prefix = - NULL; - msm_codec_conf[wsa_max_devs + i].of_node = - aux_cdc_dev_info[i].of_node; - } - - card->codec_conf = msm_codec_conf; - card->aux_dev = msm_aux_dev; -err: - return ret; -} - static void msm_i2s_auxpcm_init(struct platform_device *pdev) { int count = 0; @@ -7954,6 +7711,10 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) "qcom,lito-is-v2-enabled", &pdata->lito_v2_enabled); + of_property_read_u32(pdev->dev.of_node, + "qcom,wcd-disabled", + &pdata->wcd_disabled); + card = populate_snd_card_dailinks(&pdev->dev); if (!card) { dev_err(&pdev->dev, "%s: Card uninitialized\n", __func__); @@ -7985,9 +7746,15 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) goto err; } - ret = msm_init_aux_dev(pdev, card); - if (ret) - goto err; + /* Get maximum WSA device count for this platform */ + ret = of_property_read_u32(pdev->dev.of_node, + "qcom,wsa-max-devs", &pdata->wsa_max_devs); + if (ret) { + dev_info(&pdev->dev, + "%s: wsa-max-devs property missing in DT %s, ret = %d\n", + __func__, pdev->dev.of_node->full_name, ret); + pdata->wsa_max_devs = 0; + } ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret == -EPROBE_DEFER) { @@ -8132,6 +7899,9 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) is_initial_boot = true; + /* Add QoS request for audio tasks */ + msm_audio_add_qos_request(); + return 0; err: devm_kfree(&pdev->dev, pdata); @@ -8145,6 +7915,7 @@ static int msm_asoc_machine_remove(struct platform_device *pdev) snd_event_master_deregister(&pdev->dev); snd_soc_unregister_card(card); msm_i2s_auxpcm_deinit(); + msm_audio_remove_qos_request(); return 0; } diff --git a/asoc/msm-pcm-q6-v2.c b/asoc/msm-pcm-q6-v2.c old mode 100755 new mode 100644 index 70fc54190027..037885635cce --- a/asoc/msm-pcm-q6-v2.c +++ b/asoc/msm-pcm-q6-v2.c @@ -751,9 +751,11 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream) else if (params_format(params) == SNDRV_PCM_FORMAT_S32_LE) bits_per_sample = 32; - /* ULL mode is not supported in capture path */ + /* ULL mode is not supported in capture path so using LLNP insted of ULL */ if (pdata->perf_mode == LEGACY_PCM_MODE) prtd->audio_client->perf_mode = LEGACY_PCM_MODE; + else if (pdata->perf_mode == ULTRA_LOW_LATENCY_PCM_MODE) + prtd->audio_client->perf_mode = LOW_LATENCY_PCM_NOPROC_MODE; else prtd->audio_client->perf_mode = LOW_LATENCY_PCM_MODE; @@ -3774,6 +3776,9 @@ static int msm_pcm_probe(struct platform_device *pdev) else if (!strcmp(latency_level, "ull-pp")) pdata->perf_mode = ULL_POST_PROCESSING_PCM_MODE; + else if (!strcmp(latency_level, "llnp")) + pdata->perf_mode = + LOW_LATENCY_PCM_NOPROC_MODE; } } else { pdata->perf_mode = LEGACY_PCM_MODE; diff --git a/asoc/msm-pcm-routing-auto.c b/asoc/msm-pcm-routing-auto.c index dd40eb0c5c31..3e5f8feabd25 100755 --- a/asoc/msm-pcm-routing-auto.c +++ b/asoc/msm-pcm-routing-auto.c @@ -1456,6 +1456,8 @@ int msm_pcm_routing_set_channel_mixer_cfg( struct msm_pcm_channel_mixer *params) { int i, j = 0; + int num_ch_input_map = 0; + int num_ch_out_map = 0; channel_mixer_v2[fe_id][type].enable = params->enable; channel_mixer_v2[fe_id][type].rule = params->rule; @@ -1465,12 +1467,18 @@ int msm_pcm_routing_set_channel_mixer_cfg( params->output_channel; channel_mixer_v2[fe_id][type].port_idx = params->port_idx; - for (i = 0; i < ADM_MAX_CHANNELS; i++) + for (i = 0; i < ADM_MAX_CHANNELS; i++) { channel_mixer_v2[fe_id][type].in_ch_map[i] = params->in_ch_map[i]; - for (i = 0; i < ADM_MAX_CHANNELS; i++) + if (channel_mixer_v2[fe_id][type].in_ch_map[i] > 0) + num_ch_input_map++; + } + for (i = 0; i < ADM_MAX_CHANNELS; i++) { channel_mixer_v2[fe_id][type].out_ch_map[i] = params->out_ch_map[i]; + if (channel_mixer_v2[fe_id][type].out_ch_map[i] > 0) + num_ch_out_map++; + } for (i = 0; i < ADM_MAX_CHANNELS; i++) for (j = 0; j < ADM_MAX_CHANNELS; j++) @@ -1481,7 +1489,14 @@ int msm_pcm_routing_set_channel_mixer_cfg( params->override_in_ch_map; channel_mixer_v2[fe_id][type].override_out_ch_map = params->override_out_ch_map; - + if (channel_mixer_v2[fe_id][type].input_channel != num_ch_input_map && channel_mixer_v2[fe_id][type].override_in_ch_map) { + channel_mixer_v2[fe_id][type].override_in_ch_map =false; + pr_info("%s: mismatched with num_ch_input_map %d override_in_ch_map set to false \n", __func__,num_ch_input_map); + } + if (channel_mixer_v2[fe_id][type].output_channel != num_ch_out_map && channel_mixer_v2[fe_id][type].override_out_ch_map) { + channel_mixer_v2[fe_id][type].override_out_ch_map =false; + pr_info("%s: mismatched with num_ch_out_map %d override_out_ch_map set to false \n", __func__,num_ch_out_map); + } return 0; } EXPORT_SYMBOL(msm_pcm_routing_set_channel_mixer_cfg); @@ -2209,7 +2224,7 @@ static int msm_pcm_routing_channel_mixer_v2(int fe_id, bool perf_mode, int j = 0, be_id = 0; int ret = 0; - if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) { + if (fe_id >= MSM_FRONTEND_DAI_MAX) { pr_err("%s: invalid FE %d\n", __func__, fe_id); return 0; } @@ -2276,7 +2291,7 @@ static int msm_pcm_routing_channel_mixer(int fe_id, bool perf_mode, return ret; } - if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) { + if (fe_id >= MSM_FRONTEND_DAI_MAX) { pr_err("%s: invalid FE %d\n", __func__, fe_id); return 0; } @@ -3702,6 +3717,12 @@ static int msm_routing_adm_get_backend_idx(struct snd_kcontrol *kcontrol) backend_id = MSM_BACKEND_DAI_SLIMBUS_7_TX; } else if (strnstr(kcontrol->id.name, "TERT_TDM_TX_0", sizeof("TERT_TDM_TX_0"))) { backend_id = MSM_BACKEND_DAI_TERT_TDM_TX_0; + } else if (strnstr(kcontrol->id.name, "TERT_TDM_RX_0", sizeof("TERT_TDM_RX_0"))) { + backend_id = MSM_BACKEND_DAI_TERT_TDM_RX_0; + } else if (strnstr(kcontrol->id.name, "SEC_TDM_TX_0", sizeof("SEC_TDM_TX_0"))) { + backend_id = MSM_BACKEND_DAI_SEC_TDM_TX_0; + } else if (strnstr(kcontrol->id.name, "SEC_TDM_RX_0", sizeof("SEC_TDM_RX_0"))) { + backend_id = MSM_BACKEND_DAI_SEC_TDM_RX_0; } else { pr_err("%s: unsupported backend id: %s", __func__, kcontrol->id.name); @@ -3752,6 +3773,15 @@ static const struct snd_kcontrol_new adm_channel_config_controls[] = { SOC_ENUM_EXT("TERT_TDM_TX_0 ADM Channels", adm_override_chs, msm_routing_adm_channel_config_get, msm_routing_adm_channel_config_put), + SOC_ENUM_EXT("TERT_TDM_RX_0 ADM Channels", adm_override_chs, + msm_routing_adm_channel_config_get, + msm_routing_adm_channel_config_put), + SOC_ENUM_EXT("SEC_TDM_TX_0 ADM Channels", adm_override_chs, + msm_routing_adm_channel_config_get, + msm_routing_adm_channel_config_put), + SOC_ENUM_EXT("SEC_TDM_RX_0 ADM Channels", adm_override_chs, + msm_routing_adm_channel_config_get, + msm_routing_adm_channel_config_put), }; static int msm_routing_get_port_mixer(struct snd_kcontrol *kcontrol, @@ -32041,6 +32071,10 @@ static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, for_each_set_bit(i, &msm_bedais[be_idx].fe_sessions[0], MSM_FRONTEND_DAI_MM_SIZE) { + if (i >= MSM_FRONTEND_DAI_MAX) { + pr_debug("%s: Invalid FE id %d\n", __func__, i); + return -EINVAL; + } if ((fe_dai_map[i][session_type].passthr_mode == LEGACY_PCM) || (fe_dai_map[i][session_type].passthr_mode == LISTEN)) compr_passthr_mode = false; @@ -32747,6 +32781,10 @@ static void get_drift_and_put_asrc(struct work_struct *work) else pr_debug("%s: Succeed to get drift\n", __func__); + if (NULL == &p_asrc_cfg->modules) { + pr_err("%s: Failed to get asrc config modules\n", __func__); + goto exit; + } list_for_each_safe(ptr, next, &p_asrc_cfg->modules) { config_node = list_entry(ptr, struct asrc_module_config_node, list); diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c index 0d482e3de41c..d7196fd50ae8 100755 --- a/asoc/msm-pcm-routing-v2.c +++ b/asoc/msm-pcm-routing-v2.c @@ -1721,10 +1721,13 @@ done: EXPORT_SYMBOL(msm_pcm_routing_get_stream_app_type_cfg); static struct cal_block_data *msm_routing_find_topology_by_path(int path, - int cal_index) + int cal_index, + int app_type, + int acdb_id) { struct list_head *ptr, *next; struct cal_block_data *cal_block = NULL; + struct audio_cal_info_adm_top *cal_info; pr_debug("%s\n", __func__); list_for_each_safe(ptr, next, @@ -1735,9 +1738,11 @@ static struct cal_block_data *msm_routing_find_topology_by_path(int path, if (cal_utils_is_cal_stale(cal_block)) continue; - - if (((struct audio_cal_info_adm_top *)cal_block - ->cal_info)->path == path) { + cal_info = (struct audio_cal_info_adm_top *) + cal_block->cal_info; + if ((cal_info->path == path) && + (cal_info->app_type == app_type) && + (cal_info->acdb_id == acdb_id)) { return cal_block; } } @@ -1778,7 +1783,9 @@ static struct cal_block_data *msm_routing_find_topology(int path, "acdb_id %d %s\n", __func__, path, app_type, acdb_id, exact ? "fail" : "defaulting to search by path"); return exact ? NULL : msm_routing_find_topology_by_path(path, - cal_index); + cal_index, + app_type, + acdb_id); } static struct cal_block_data *msm_routing_find_topology_by_buf_number(int usecase, int path, diff --git a/asoc/sa8155.c b/asoc/sa8155.c index 138df88a73d2..e0292f83bd79 100644 --- a/asoc/sa8155.c +++ b/asoc/sa8155.c @@ -7582,6 +7582,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { .async_ops = ASYNC_DPCM_SND_SOC_PREPARE, #endif /* CONFIG_AUDIO_QGKI */ .dpcm_playback = 1, + .dpcm_capture = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .ignore_suspend = 1, diff --git a/asoc/sm6150.c b/asoc/sm6150.c index 40e36b9e9c18..f3afe9138999 100644 --- a/asoc/sm6150.c +++ b/asoc/sm6150.c @@ -7208,7 +7208,7 @@ static struct snd_soc_dai_link msm_tasha_be_dai_links[] = { static struct snd_soc_dai_link msm_wcn_be_dai_links[] = { { - .name = LPASS_BE_SLIMBUS_TX_VI, + .name = LPASS_BE_SLIMBUS_7_RX, .stream_name = "Slimbus7 Playback", /* BT codec driver determines capabilities based on * dai name, bt codecdai name should always contains diff --git a/config/arauto.conf b/config/arauto.conf new file mode 100755 index 000000000000..36eb6be8a26f --- /dev/null +++ b/config/arauto.conf @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2021, The Linux Foundation. All rights reserved. + +ifeq ($(CONFIG_QGKI), y) +export CONFIG_SND_SOC_GVM_AUTO_SPF=m +export CONFIG_MSM_QDSP6_APRV2_VM=m +export CONFIG_MSM_QDSP6_SSR=m +export CONFIG_MSM_ADSP_LOADER=m +export CONFIG_MSM_QDSP6_NOTIFIER=m +export CONFIG_SND_SOC_MSM_QDSP6V2_VM=m +export CONFIG_SND_SOC_QDSP6V2=m +export CONFIG_QTI_PP=m +export CONFIG_SND_HWDEP_ROUTING=m +export CONFIG_SND_SOC_MSM_STUB=m +export CONFIG_SND_SOC_MSM_HDMI_CODEC_RX=m +export CONFIG_MSM_QDSP6V2_CODECS=m +export CONFIG_SND_EVENT=m +export CONFIG_SND_SOC_SA8155=m +endif \ No newline at end of file diff --git a/config/arautoconf.h b/config/arautoconf.h new file mode 100755 index 000000000000..6e28cae199ca --- /dev/null +++ b/config/arautoconf.h @@ -0,0 +1,27 @@ +/* Copyright (c) 2018-2019, 2021 The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define CONFIG_SND_SOC_GVM_AUTO_SPF 1 +#define CONFIG_MSM_QDSP6_APRV2_VM 1 +#define CONFIG_MSM_ADSP_LOADER 1 +#define CONFIG_MSM_QDSP6_SSR 1 +#define CONFIG_MSM_QDSP6_NOTIFIER 1 +#define CONFIG_SND_SOC_MSM_QDSP6V2_VM 1 +#define CONFIG_SND_SOC_QDSP6V2 1 +#define CONFIG_QTI_PP 1 +#define CONFIG_SND_HWDEP_ROUTING 1 +#define CONFIG_SND_SOC_MSM_STUB 1 +#define CONFIG_SND_SOC_MSM_HDMI_CODEC_RX 1 +#define CONFIG_MSM_QDSP6V2_CODECS 1 +#define CONFIG_SND_EVENT 1 +#define CONFIG_SND_SOC_SA8155 1 + diff --git a/dsp/Kbuild b/dsp/Kbuild index 788a7d3c5a28..2c5506ff7c5c 100755 --- a/dsp/Kbuild +++ b/dsp/Kbuild @@ -29,6 +29,11 @@ ifeq ($(CONFIG_SND_SOC_AUTO), y) export INCS += -include $(AUDIO_ROOT)/config/gvmautoconf.h endif + ifdef CONFIG_SND_SOC_AR + include $(AUDIO_ROOT)/config/arauto.conf + export + INCS += -include $(AUDIO_ROOT)/config/arautoconf.h + endif ifdef CONFIG_SND_SOC_GVM_SA8295 include $(AUDIO_ROOT)/config/sa8295gvmauto.conf export diff --git a/dsp/q6asm.c b/dsp/q6asm.c old mode 100755 new mode 100644 index 9bcf3a0eaeb8..167ea186fff3 --- a/dsp/q6asm.c +++ b/dsp/q6asm.c @@ -3367,7 +3367,12 @@ static int __q6asm_open_read(struct audio_client *ac, if (ac->perf_mode == LOW_LATENCY_PCM_MODE) { open.mode_flags |= ASM_LOW_LATENCY_TX_STREAM_SESSION << ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_READ; - } else { + } + else if (ac->perf_mode == LOW_LATENCY_PCM_NOPROC_MODE) { + open.mode_flags |= ASM_LOW_LATENCY_NPROC_TX_STREAM_SESSION << + ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_READ; + } + else { open.mode_flags |= ASM_LEGACY_STREAM_SESSION << ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_READ; } diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h old mode 100755 new mode 100644 index c742d20aea54..f37ce1c96371 --- a/include/dsp/apr_audio-v2.h +++ b/include/dsp/apr_audio-v2.h @@ -8281,6 +8281,9 @@ struct asm_stream_cmd_open_shared_io { /* Bit value for Low Latency Tx stream subfield */ #define ASM_LOW_LATENCY_TX_STREAM_SESSION 1 +/* Bit value for Low Latency No Post Processing Tx stream subfield */ +#define ASM_LOW_LATENCY_NPROC_TX_STREAM_SESSION 3 + /* Bit shift for the stream_perf_mode subfield. */ #define ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_READ 29 diff --git a/ipc/Kbuild b/ipc/Kbuild index 1d76bae1069e..06a1f42b9063 100755 --- a/ipc/Kbuild +++ b/ipc/Kbuild @@ -30,6 +30,11 @@ ifeq ($(CONFIG_SND_SOC_AUTO), y) export INCS += -include $(AUDIO_ROOT)/config/gvmautoconf.h endif + ifdef CONFIG_SND_SOC_AR + include $(AUDIO_ROOT)/config/arauto.conf + export + INCS += -include $(AUDIO_ROOT)/config/arautoconf.h + endif ifdef CONFIG_SND_SOC_GVM_SA8295 include $(AUDIO_ROOT)/config/sa8295gvmauto.conf export diff --git a/ipc/apr.c b/ipc/apr.c index 25a052014de6..55d834de0e00 100755 --- a/ipc/apr.c +++ b/ipc/apr.c @@ -1214,10 +1214,12 @@ static int apr_probe(struct platform_device *pdev) return -ENOMEM; } +#ifdef CONFIG_IPC_LOGGING apr_pkt_ctx = ipc_log_context_create(APR_PKT_IPC_LOG_PAGE_CNT, "apr", 0); if (!apr_pkt_ctx) pr_err("%s: Unable to create ipc log context\n", __func__); +#endif /* CONFIG_IPC_LOGGING */ spin_lock(&apr_priv->apr_lock); apr_priv->is_initial_boot = true; diff --git a/ipc/apr_vm.c b/ipc/apr_vm.c index 6f4d4580d79a..a79f64d0bcbd 100644 --- a/ipc/apr_vm.c +++ b/ipc/apr_vm.c @@ -1421,10 +1421,12 @@ static int apr_probe(struct platform_device *pdev) return -ENOMEM; } +#ifdef CONFIG_IPC_LOGGING apr_pkt_ctx = ipc_log_context_create(APR_PKT_IPC_LOG_PAGE_CNT, "apr", 0); if (!apr_pkt_ctx) pr_err("%s: Unable to create ipc log context\n", __func__); +#endif /* CONFIG_IPC_LOGGING */ ret = of_property_read_string(pdev->dev.of_node, "qcom,subsys-name", diff --git a/soc/Kbuild b/soc/Kbuild index 8ddec0d2625e..edb9aeee478b 100755 --- a/soc/Kbuild +++ b/soc/Kbuild @@ -29,6 +29,11 @@ ifeq ($(CONFIG_SND_SOC_AUTO), y) export INCS += -include $(AUDIO_ROOT)/config/gvmautoconf.h endif + ifdef CONFIG_SND_SOC_AR + include $(AUDIO_ROOT)/config/arauto.conf + export + INCS += -include $(AUDIO_ROOT)/config/arautoconf.h + endif ifdef CONFIG_SND_SOC_GVM_SA8295 include $(AUDIO_ROOT)/config/sa8295gvmauto.conf export