From f6bee9a0da1f083b262e00eeea9c42aa07885793 Mon Sep 17 00:00:00 2001 From: Dechen Chai Date: Mon, 11 Apr 2022 12:13:09 +0530 Subject: [PATCH] asoc: Update machine driver for kona -Update machine driver on kernel-5.4 for kona. -update and affine qos value. -update wsa component init function. -update rx_tx codec init function. -remove msm_init_aux_dev function. Change-Id: Id0934adcd0e41968d9f9f3c8341525f3a7152858 --- Makefile.am | 9 + asoc/kona.c | 873 +++++++++++++++++++--------------------------------- 2 files changed, 331 insertions(+), 551 deletions(-) diff --git a/Makefile.am b/Makefile.am index 5e3faccf5492..81c13f2d1c51 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,6 +42,12 @@ 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/ 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; }