From 2c4bc0683f1c68e3e0b3c7b696fcbb8e521054ea Mon Sep 17 00:00:00 2001 From: Sudheer Papothi Date: Fri, 10 Apr 2020 04:28:03 +0530 Subject: [PATCH 001/116] ASoC: lahaina: Add soft dependencies for BT Audio driver expects BT to be probed first before machine driver probe. Changes ensures BT dependency for audio. Change-Id: I82004f464ed9e7bb90d24bf2762c99b9817f95a3 Signed-off-by: Sudheer Papothi --- asoc/lahaina.c | 1 + 1 file changed, 1 insertion(+) diff --git a/asoc/lahaina.c b/asoc/lahaina.c index a15edfc452..06a90d8bd5 100644 --- a/asoc/lahaina.c +++ b/asoc/lahaina.c @@ -7602,6 +7602,7 @@ static struct platform_driver lahaina_asoc_machine_driver = { }; module_platform_driver(lahaina_asoc_machine_driver); +MODULE_SOFTDEP("pre: bt_fm_slim"); MODULE_DESCRIPTION("ALSA SoC msm"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:" DRV_NAME); From 5865f8c1828f3da84e10db349bd0cc3781e33db4 Mon Sep 17 00:00:00 2001 From: Meng Wang Date: Fri, 1 May 2020 15:33:17 +0800 Subject: [PATCH 002/116] asoc: remove asound.h from include list There's no need to include sound/asound.h directly. Remove it to work with KERNEL_HEADER_TEST and UAPI_HEADER_TEST. Change-Id: If09b58f683ad224b549f6f53dd34157ba0956ea4 Signed-off-by: Meng Wang --- asoc/msm-pcm-routing-v2.c | 1 - asoc/msm-qti-pp-config.c | 1 - dsp/msm-dts-srs-tm-config.c | 3 +-- dsp/q6adm.c | 1 - include/uapi/audio/sound/lsm_params.h | 1 - include/uapi/audio/sound/voice_params.h | 1 - 6 files changed, 1 insertion(+), 7 deletions(-) diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c index a49a48cd88..4649d24c99 100644 --- a/asoc/msm-pcm-routing-v2.c +++ b/asoc/msm-pcm-routing-v2.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/asoc/msm-qti-pp-config.c b/asoc/msm-qti-pp-config.c index 1bafb20275..27faecbe18 100644 --- a/asoc/msm-qti-pp-config.c +++ b/asoc/msm-qti-pp-config.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include diff --git a/dsp/msm-dts-srs-tm-config.c b/dsp/msm-dts-srs-tm-config.c index b507d02af7..54a3ab06b5 100644 --- a/dsp/msm-dts-srs-tm-config.c +++ b/dsp/msm-dts-srs-tm-config.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2014, 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2014, 2016-2018, 2020, The Linux Foundation. All rights reserved. */ #include @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include diff --git a/dsp/q6adm.c b/dsp/q6adm.c index 9a4a7f914a..49f3934a99 100644 --- a/dsp/q6adm.c +++ b/dsp/q6adm.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include diff --git a/include/uapi/audio/sound/lsm_params.h b/include/uapi/audio/sound/lsm_params.h index 57dc3be5d4..c73a92fbd6 100644 --- a/include/uapi/audio/sound/lsm_params.h +++ b/include/uapi/audio/sound/lsm_params.h @@ -5,7 +5,6 @@ #define LSM_EVENT_TIMESTAMP_MODE_SUPPORT #include -#include #define SNDRV_LSM_VERSION SNDRV_PROTOCOL_VERSION(0, 3, 1) diff --git a/include/uapi/audio/sound/voice_params.h b/include/uapi/audio/sound/voice_params.h index 43e3b9d0aa..357a6fac3b 100644 --- a/include/uapi/audio/sound/voice_params.h +++ b/include/uapi/audio/sound/voice_params.h @@ -2,7 +2,6 @@ #define __VOICE_PARAMS_H__ #include -#include enum voice_lch_mode { VOICE_LCH_START = 1, From f3e5ce1e666cfa7863c57c3bfa15a2846a92058a Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Wed, 1 Apr 2020 18:14:05 +0530 Subject: [PATCH 003/116] asoc: kona: Update wsa8815 default config With wsa883x supported in lagoon, need to set wsa8815 default config also. Change-Id: I7e247cb564c893f7fbbc715de68821c6b91d559a Signed-off-by: Laxminath Kasam --- asoc/kona.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/asoc/kona.c b/asoc/kona.c index 0cc60ead59..2fe560c32d 100644 --- a/asoc/kona.c +++ b/asoc/kona.c @@ -81,8 +81,10 @@ #define ADSP_STATE_READY_TIMEOUT_MS 3000 -#define WSA8810_NAME_1 "wsa881x.20170211" -#define WSA8810_NAME_2 "wsa881x.20170212" +#define WSA8810_NAME_1 "wsa881x.1020170211" +#define WSA8810_NAME_2 "wsa881x.1020170212" +#define WSA8815_NAME_1 "wsa881x.1021170213" +#define WSA8815_NAME_2 "wsa881x.1021170214" #define WCN_CDC_SLIM_RX_CH_MAX 2 #define WCN_CDC_SLIM_TX_CH_MAX 2 #define WCN_CDC_SLIM_TX_CH_MAX_LITO 3 @@ -5517,6 +5519,11 @@ static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd) 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); } } } From aa730ef49225bddbdd3b4ade5fe82086d67ebd5d Mon Sep 17 00:00:00 2001 From: Sudheer Papothi Date: Thu, 30 Apr 2020 11:00:06 +0530 Subject: [PATCH 004/116] soc: soundwire: Fix soundwire bus clock frequency Soundwire bus clock frequency should not exceed MCLK. Fix the soundwire bus clock frequency to MCLK during clock scaling for proper SSP calculation. Change-Id: I347c8ee0f63f34428160a3408eaa0e999142bc78 Signed-off-by: Sudheer Papothi --- soc/swr-mstr-ctrl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index 7deb11b2ba..b41fcd8e9b 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -1104,6 +1104,8 @@ int swrm_get_clk_div_rate(int mclk_freq, int bus_clk_freq) bus_clk_freq = SWR_CLK_RATE_4P8MHZ; else if(bus_clk_freq <= SWR_CLK_RATE_9P6MHZ) bus_clk_freq = SWR_CLK_RATE_9P6MHZ; + else + bus_clk_freq = SWR_CLK_RATE_9P6MHZ; } else if (mclk_freq == SWR_CLK_RATE_11P2896MHZ) bus_clk_freq = SWR_CLK_RATE_11P2896MHZ; From e497a31d29e375246cad887d01380230f4b556e2 Mon Sep 17 00:00:00 2001 From: Sanjana B Date: Sun, 5 Apr 2020 18:24:24 +0530 Subject: [PATCH 005/116] asoc: csra: update mute register of csra66x0 codec Update mute register of csra66x0 codec when called from hw_free api. Change-Id: I728d1ca3076899ad0e6dea4dcac28416b3e40b18 Signed-off-by: Sanjana B --- asoc/codecs/csra66x0/csra66x0.c | 21 ++++++++++++++++++++- asoc/codecs/csra66x0/csra66x0.h | 4 +++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/asoc/codecs/csra66x0/csra66x0.c b/asoc/codecs/csra66x0/csra66x0.c index e0e702f565..9cdbbdaaab 100644 --- a/asoc/codecs/csra66x0/csra66x0.c +++ b/asoc/codecs/csra66x0/csra66x0.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #include #include @@ -602,6 +602,25 @@ static const struct snd_soc_dapm_route csra66x0_dapm_routes[] = { {"PGA", NULL, "DAC"}, {"SPKR", NULL, "PGA"}, }; +/* + * csra66x0_hw_free_mute - Update csra66x0 mute register + * + * @component - csra66x0 component + * + */ +void csra66x0_hw_free_mute(struct snd_soc_component *component) +{ + int val = 0; + + if (component == NULL) + return; + + val = snd_soc_component_read32(component, + CSRA66X0_MISC_CONTROL_STATUS_1_FA); + snd_soc_component_write(component, CSRA66X0_MISC_CONTROL_STATUS_1_FA, + val | 0x04); +} +EXPORT_SYMBOL(csra66x0_hw_free_mute); static int csra66x0_wait_for_config_state(struct snd_soc_component *component) { diff --git a/asoc/codecs/csra66x0/csra66x0.h b/asoc/codecs/csra66x0/csra66x0.h index 04d9ef836d..2bde3cc06b 100644 --- a/asoc/codecs/csra66x0/csra66x0.h +++ b/asoc/codecs/csra66x0/csra66x0.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _CSRA66X0_H @@ -226,4 +226,6 @@ #define FAULT_STATUS_TEMP 0x10 #define FAULT_STATUS_PROTECT 0x20 + +void csra66x0_hw_free_mute(struct snd_soc_component *component); #endif /* _CSRA66X0_H */ From fa2b1d308933f13076d3d0a185f4af0c169d4f2b Mon Sep 17 00:00:00 2001 From: Sanjana Date: Mon, 16 Mar 2020 10:21:54 +0530 Subject: [PATCH 006/116] asoc: qcs405: fix pop at end of DSD playback Fix pop at end of DSD playback by muting csra devices during hw_free. Change-Id: Ie084ade6aeb310ee28e4478b4673075ca69153c9 Signed-off-by: Sanjana --- asoc/qcs405.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/asoc/qcs405.c b/asoc/qcs405.c index 18dfb82207..d6fd14a725 100644 --- a/asoc/qcs405.c +++ b/asoc/qcs405.c @@ -6177,6 +6177,36 @@ err: return ret; } +static int msm_mi2s_snd_hw_free(struct snd_pcm_substream *substream) +{ + int i, data_format = 0; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + int index = rtd->cpu_dai->id; + struct snd_soc_card *card = rtd->card; + struct snd_soc_component *component; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + data_format = mi2s_rx_cfg[index].data_format; + else + data_format = mi2s_tx_cfg[index].data_format; + + pr_debug("%s(): substream = %s stream = %d\n", __func__, + substream->name, substream->stream); + + /* Call csra mute function if data format is DSD, else return */ + if (data_format != AFE_DSD_DATA) + return 0; + + for (i = 0; i < card->num_aux_devs; i++) { + component = + soc_find_component(card->aux_dev[i].codec_of_node, + NULL); + csra66x0_hw_free_mute(component); + } + + return 0; +} + static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream) { int ret; @@ -6504,6 +6534,7 @@ static void msm_spdif_snd_shutdown(struct snd_pcm_substream *substream) static struct snd_soc_ops msm_mi2s_be_ops = { .startup = msm_mi2s_snd_startup, + .hw_free = msm_mi2s_snd_hw_free, .shutdown = msm_mi2s_snd_shutdown, }; From ec8b554e4d47ffd29824bf860e64eedd84afaad6 Mon Sep 17 00:00:00 2001 From: Vatsal Bucha Date: Tue, 21 Apr 2020 14:16:51 +0530 Subject: [PATCH 007/116] bolero: rx-macro: Resolve noise on ear path during hph ear concurrency There is noise on ear path during hph and ear concurrency. Set proper HPH_V_PA voltage when both hph PA is in class-H mode to resolve noise. Change-Id: Ifbbfb5691687dcb2202358c1e387252954d58db2 Signed-off-by: Vatsal Bucha --- asoc/codecs/bolero/rx-macro.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c index 62da031f26..cb4534af31 100644 --- a/asoc/codecs/bolero/rx-macro.c +++ b/asoc/codecs/bolero/rx-macro.c @@ -1930,7 +1930,12 @@ static int rx_macro_config_classh(struct snd_soc_component *component, 0x40, 0x40); break; case INTERP_HPHR: - snd_soc_component_update_bits(component, + if (rx_priv->is_ear_mode_on) + snd_soc_component_update_bits(component, + BOLERO_CDC_RX_CLSH_HPH_V_PA, + 0x3F, 0x39); + else + snd_soc_component_update_bits(component, BOLERO_CDC_RX_CLSH_HPH_V_PA, 0x3F, 0x1C); snd_soc_component_update_bits(component, From d46f27c4beaa0c7a42bdaf812e36ddfd5b7df03a Mon Sep 17 00:00:00 2001 From: Samyak Jain Date: Sun, 5 Apr 2020 21:41:23 +0530 Subject: [PATCH 008/116] soc:bengal: add proxy ports for call screening in machine driver add machine driver changes for proxy port changes. Change-Id: I95e269953fa482002d028c60165ba5ad95521f6f Signed-off-by: Samyak Jain --- asoc/bengal.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/asoc/bengal.c b/asoc/bengal.c index 22677cb258..0947166b25 100644 --- a/asoc/bengal.c +++ b/asoc/bengal.c @@ -5075,6 +5075,33 @@ static struct snd_soc_dai_link msm_common_be_dai_links[] = { .ignore_suspend = 1, .ignore_pmdown_time = 1, }, + /* Proxy Tx BACK END DAI Link */ + { + .name = LPASS_BE_PROXY_TX, + .stream_name = "Proxy Capture", + .cpu_dai_name = "msm-dai-q6-dev.8195", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .id = MSM_BACKEND_DAI_PROXY_TX, + .ignore_suspend = 1, + }, + /* Proxy Rx BACK END DAI Link */ + { + .name = LPASS_BE_PROXY_RX, + .stream_name = "Proxy Playback", + .cpu_dai_name = "msm-dai-q6-dev.8194", + .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_PROXY_RX, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + }, { .name = LPASS_BE_USB_AUDIO_RX, .stream_name = "USB Audio Playback", From 19363f7321489c2b8c52109442fa5e32a45fd303 Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Sat, 18 Apr 2020 11:21:43 +0530 Subject: [PATCH 009/116] asoc: Add Rx swr master port config for scuba target Add port config for Rx swr master in order to support the rouleur codec in scuba target. Change-Id: Ic278d02f222686afc6ff976c4b1c3bb499ed903f Signed-off-by: Aditya Bavanari --- asoc/bengal-port-config.h | 16 +++++++++++++++- asoc/bengal.c | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/asoc/bengal-port-config.h b/asoc/bengal-port-config.h index a20a6d5448..37d4f740aa 100644 --- a/asoc/bengal-port-config.h +++ b/asoc/bengal-port-config.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _BENGAL_PORT_CONFIG @@ -21,6 +21,15 @@ static struct port_params rx_frame_params_default[SWR_MSTR_PORT_LEN] = { {0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0}, }; +static struct port_params rx_frame_params_rouleur[SWR_MSTR_PORT_LEN] = { + {3, 0, 0, 0xFF, 0xFF, 1, 0xFF, 0xFF, 1}, + {31, 0, 0, 3, 6, 7, 0, 0xFF, 0}, + {31, 1, 0, 0xFF, 0xFF, 4, 1, 0xFF, 0}, + {7, 1, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0}, + {0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0}, +}; + + static struct port_params rx_frame_params_dsd[SWR_MSTR_PORT_LEN] = { {3, 0, 0, 0xFF, 0xFF, 1, 0xFF, 0xFF, 1}, {31, 0, 0, 3, 6, 7, 0, 0xFF, 0}, @@ -42,4 +51,9 @@ static struct swr_mstr_port_map sm_port_map[] = { {RX_MACRO, SWR_UC1, rx_frame_params_dsd}, }; +static struct swr_mstr_port_map sm_port_map_rouleur[] = { + {VA_MACRO, SWR_UC0, tx_frame_params_default}, + {RX_MACRO, SWR_UC0, rx_frame_params_rouleur}, + {RX_MACRO, SWR_UC1, rx_frame_params_dsd}, +}; #endif /* _BENGAL_PORT_CONFIG */ diff --git a/asoc/bengal.c b/asoc/bengal.c index 22677cb258..8123152b43 100644 --- a/asoc/bengal.c +++ b/asoc/bengal.c @@ -4259,6 +4259,9 @@ static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_dapm_context *dapm; struct snd_card *card; struct snd_info_entry *entry; + struct platform_device *pdev = NULL; + int i = 0; + char *data = NULL; struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(rtd->card); @@ -4305,8 +4308,38 @@ static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_sync(dapm); - bolero_set_port_map(component, ARRAY_SIZE(sm_port_map), - sm_port_map); + 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"))) { + bolero_set_port_map(component, + ARRAY_SIZE(sm_port_map), + sm_port_map); + break; + } else if (!strncmp( data, "rouleur", + sizeof("rouleur"))) { + bolero_set_port_map(component, + ARRAY_SIZE(sm_port_map_rouleur), + sm_port_map_rouleur); + break; + } + } + } + } + card = rtd->card->snd_card; if (!pdata->codec_root) { entry = snd_info_create_subdir(card->module, "codecs", From 3382d068820062e0d07a34064c5653b86e8cdd93 Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Wed, 29 Apr 2020 20:40:53 +0530 Subject: [PATCH 010/116] asoc: Add a separate mbhc config for rouleur codec As rouleur codec supports only 5 buttons and headset vref max value is 1.7V, use a separate mbhc config structure to initizlize mbhc. Change-Id: Icd78d8c10f3d4dd3585c76c407d2d323c20cbe3f Signed-off-by: Aditya Bavanari --- asoc/bengal.c | 54 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/asoc/bengal.c b/asoc/bengal.c index 22677cb258..49e606634f 100644 --- a/asoc/bengal.c +++ b/asoc/bengal.c @@ -59,10 +59,12 @@ #define WCD9XXX_MBHC_DEF_RLOADS 5 #define WCD9XXX_MBHC_DEF_BUTTONS 8 +#define ROULEUR_MBHC_DEF_BUTTONS 5 #define CODEC_EXT_CLK_RATE 9600000 #define ADSP_STATE_READY_TIMEOUT_MS 3000 #define DEV_NAME_STR_LEN 32 #define WCD_MBHC_HS_V_MAX 1600 +#define ROULEUR_MBHC_HS_V_MAX 1700 #define TDM_CHANNEL_MAX 8 #define DEV_NAME_STR_LEN 32 @@ -555,6 +557,7 @@ static int dmic_0_1_gpio_cnt; static int dmic_2_3_gpio_cnt; static void *def_wcd_mbhc_cal(void); +static void *def_rouleur_mbhc_cal(void); /* * Need to report LINEIN @@ -4356,6 +4359,34 @@ static void *def_wcd_mbhc_cal(void) return wcd_mbhc_cal; } +static void *def_rouleur_mbhc_cal(void) +{ + void *wcd_mbhc_cal; + struct wcd_mbhc_btn_detect_cfg *btn_cfg; + u16 *btn_high; + + wcd_mbhc_cal = kzalloc(WCD_MBHC_CAL_SIZE(ROULEUR_MBHC_DEF_BUTTONS, + WCD9XXX_MBHC_DEF_RLOADS), GFP_KERNEL); + if (!wcd_mbhc_cal) + return NULL; + + WCD_MBHC_CAL_PLUG_TYPE_PTR(wcd_mbhc_cal)->v_hs_max = + ROULEUR_MBHC_HS_V_MAX; + WCD_MBHC_CAL_BTN_DET_PTR(wcd_mbhc_cal)->num_btn = + ROULEUR_MBHC_DEF_BUTTONS; + btn_cfg = WCD_MBHC_CAL_BTN_DET_PTR(wcd_mbhc_cal); + btn_high = ((void *)&btn_cfg->_v_btn_low) + + (sizeof(btn_cfg->_v_btn_low[0]) * btn_cfg->num_btn); + + btn_high[0] = 75; + btn_high[1] = 150; + btn_high[2] = 237; + btn_high[3] = 500; + btn_high[4] = 500; + + return wcd_mbhc_cal; +} + /* Digital audio interface glue - connects codec <---> CPU */ static struct snd_soc_dai_link msm_common_dai_links[] = { /* FrontEnd DAI Links */ @@ -6115,16 +6146,21 @@ static int msm_aux_codec_init(struct snd_soc_component *component) } mbhc_cfg_cal: - mbhc_calibration = def_wcd_mbhc_cal(); - if (!mbhc_calibration) - return -ENOMEM; - wcd_mbhc_cfg.calibration = mbhc_calibration; if (data != NULL) { - if (!strncmp(data, "wcd937x", sizeof("wcd937x"))) - ret = wcd937x_mbhc_hs_detect(component, &wcd_mbhc_cfg); - else if (!strncmp( data, "rouleur", sizeof("rouleur"))) - ret = rouleur_mbhc_hs_detect(component, &wcd_mbhc_cfg); - } + if (!strncmp(data, "wcd937x", sizeof("wcd937x"))) { + mbhc_calibration = def_wcd_mbhc_cal(); + if (!mbhc_calibration) + return -ENOMEM; + wcd_mbhc_cfg.calibration = mbhc_calibration; + ret = wcd937x_mbhc_hs_detect(component, &wcd_mbhc_cfg); + } else if (!strncmp( data, "rouleur", sizeof("rouleur"))) { + mbhc_calibration = def_rouleur_mbhc_cal(); + if (!mbhc_calibration) + return -ENOMEM; + wcd_mbhc_cfg.calibration = mbhc_calibration; + ret = rouleur_mbhc_hs_detect(component, &wcd_mbhc_cfg); + } + } if (ret) { dev_err(component->dev, "%s: mbhc hs detect failed, err:%d\n", From 9f50810d7f372cd5a4d1b20f0cc86bcee8b63583 Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Fri, 10 Apr 2020 16:38:29 +0530 Subject: [PATCH 011/116] asoc: codecs: Update rouleur watchdog interrupt sequence Update PDM watchdog interrupt sequence for rouleur codec. Add HPH PA gain registers in regmap and update defaults. Update mic bias register bits and rouleur version for ADIE RTC to work. Change-Id: I1bbb41efcdd9a0a8b38fcd4beadbd5d639a4b858 Signed-off-by: Aditya Bavanari --- asoc/codecs/rouleur/rouleur-mbhc.c | 2 +- asoc/codecs/rouleur/rouleur-regmap.c | 2 + asoc/codecs/rouleur/rouleur-tables.c | 2 + asoc/codecs/rouleur/rouleur.c | 73 +++++++++++----------------- 4 files changed, 33 insertions(+), 46 deletions(-) diff --git a/asoc/codecs/rouleur/rouleur-mbhc.c b/asoc/codecs/rouleur/rouleur-mbhc.c index 91ddc104ac..caf6d4a04f 100644 --- a/asoc/codecs/rouleur/rouleur-mbhc.c +++ b/asoc/codecs/rouleur/rouleur-mbhc.c @@ -88,7 +88,7 @@ static struct wcd_mbhc_register WCD_MBHC_REGISTER("WCD_MBHC_ELECT_RESULT", ROULEUR_ANA_MBHC_RESULT_3, 0xFF, 0, 0), WCD_MBHC_REGISTER("WCD_MBHC_MICB_CTRL", - ROULEUR_ANA_MICBIAS_MICB_1_2_EN, 0x04, 2, 0), + ROULEUR_ANA_MICBIAS_MICB_1_2_EN, 0x06, 1, 0), WCD_MBHC_REGISTER("WCD_MBHC_HPH_CNP_WG_TIME", SND_SOC_NOPM, 0x00, 0, 0), WCD_MBHC_REGISTER("WCD_MBHC_HPHR_PA_EN", diff --git a/asoc/codecs/rouleur/rouleur-regmap.c b/asoc/codecs/rouleur/rouleur-regmap.c index 71e5e1901f..08b490db3a 100644 --- a/asoc/codecs/rouleur/rouleur-regmap.c +++ b/asoc/codecs/rouleur/rouleur-regmap.c @@ -45,6 +45,8 @@ static const struct reg_default rouleur_defaults[] = { { ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x2B }, { ROULEUR_ANA_HPHPA_PA_STATUS, 0x00 }, { ROULEUR_ANA_HPHPA_FSM_CLK, 0x12 }, + { ROULEUR_ANA_HPHPA_L_GAIN, 0x00 }, + { ROULEUR_ANA_HPHPA_R_GAIN, 0x00 }, { ROULEUR_SWR_HPHPA_HD2, 0x1B }, { ROULEUR_ANA_HPHPA_SPARE_CTL, 0x02 }, { ROULEUR_ANA_SURGE_EN, 0x38 }, diff --git a/asoc/codecs/rouleur/rouleur-tables.c b/asoc/codecs/rouleur/rouleur-tables.c index ba2fa9a40a..59b7cf2d33 100644 --- a/asoc/codecs/rouleur/rouleur-tables.c +++ b/asoc/codecs/rouleur/rouleur-tables.c @@ -40,6 +40,8 @@ const u8 rouleur_reg_access_analog[ROULEUR_REG( [ROULEUR_REG(ROULEUR_ANA_HPHPA_CNP_CTL_2)] = RD_WR_REG, [ROULEUR_REG(ROULEUR_ANA_HPHPA_PA_STATUS)] = RD_REG, [ROULEUR_REG(ROULEUR_ANA_HPHPA_FSM_CLK)] = RD_WR_REG, + [ROULEUR_REG(ROULEUR_ANA_HPHPA_L_GAIN)] = RD_WR_REG, + [ROULEUR_REG(ROULEUR_ANA_HPHPA_R_GAIN)] = RD_WR_REG, [ROULEUR_REG(ROULEUR_ANA_HPHPA_SPARE_CTL)] = RD_WR_REG, [ROULEUR_REG(ROULEUR_SWR_HPHPA_HD2)] = RD_WR_REG, [ROULEUR_REG(ROULEUR_ANA_SURGE_EN)] = RD_WR_REG, diff --git a/asoc/codecs/rouleur/rouleur.c b/asoc/codecs/rouleur/rouleur.c index d028ed48b5..3f039c4082 100644 --- a/asoc/codecs/rouleur/rouleur.c +++ b/asoc/codecs/rouleur/rouleur.c @@ -475,14 +475,8 @@ static int rouleur_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, 0x04, 0x04); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x01, 0x01); - snd_soc_component_update_bits(component, - ROULEUR_DIG_SWR_PDM_WD_CTL0, - 0x03, 0x03); break; case SND_SOC_DAPM_POST_PMD: - snd_soc_component_update_bits(component, - ROULEUR_DIG_SWR_PDM_WD_CTL0, - 0x03, 0x00); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x01, 0x00); @@ -546,14 +540,8 @@ static int rouleur_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, 0x08, 0x08); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x02, 0x02); - snd_soc_component_update_bits(component, - ROULEUR_DIG_SWR_PDM_WD_CTL1, - 0x03, 0x03); break; case SND_SOC_DAPM_POST_PMD: - snd_soc_component_update_bits(component, - ROULEUR_DIG_SWR_PDM_WD_CTL1, - 0x03, 0x00); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x02, 0x00); break; @@ -582,18 +570,12 @@ static int rouleur_codec_ear_lo_dac_event(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x01, 0x01); - snd_soc_component_update_bits(component, - ROULEUR_DIG_SWR_PDM_WD_CTL0, - 0x03, 0x03); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, 0x04, 0x04); break; case SND_SOC_DAPM_POST_PMD: - snd_soc_component_update_bits(component, - ROULEUR_DIG_SWR_PDM_WD_CTL0, - 0x03, 0x00); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x01, 0x00); @@ -622,14 +604,11 @@ static int rouleur_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, rouleur->rx_swr_dev->dev_num, true); - snd_soc_component_update_bits(component, - ROULEUR_ANA_HPHPA_CNP_CTL_2, - 0x40, 0x40); set_bit(HPH_PA_DELAY, &rouleur->status_mask); - /* TODO: WHY SECOND TIME */ - ret = swr_slvdev_datapath_control(rouleur->rx_swr_dev, - rouleur->rx_swr_dev->dev_num, - true); + usleep_range(5000, 5100); + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_PDM_WD_CTL1, + 0x03, 0x03); break; case SND_SOC_DAPM_POST_PMU: /* @@ -676,8 +655,8 @@ static int rouleur_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, WCD_EVENT_POST_HPHR_PA_OFF, &rouleur->mbhc->wcd_mbhc); snd_soc_component_update_bits(component, - ROULEUR_ANA_HPHPA_CNP_CTL_2, - 0x40, 0x00); + ROULEUR_DIG_SWR_PDM_WD_CTL1, + 0x03, 0x00); break; }; return ret; @@ -700,10 +679,11 @@ static int rouleur_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, ret = swr_slvdev_datapath_control(rouleur->rx_swr_dev, rouleur->rx_swr_dev->dev_num, true); - snd_soc_component_update_bits(component, - ROULEUR_ANA_HPHPA_CNP_CTL_2, - 0x80, 0x80); set_bit(HPH_PA_DELAY, &rouleur->status_mask); + usleep_range(5000, 5100); + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_PDM_WD_CTL0, + 0x03, 0x03); break; case SND_SOC_DAPM_POST_PMU: /* @@ -748,8 +728,8 @@ static int rouleur_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, WCD_EVENT_POST_HPHL_PA_OFF, &rouleur->mbhc->wcd_mbhc); snd_soc_component_update_bits(component, - ROULEUR_ANA_HPHPA_CNP_CTL_2, - 0x80, 0x00); + ROULEUR_DIG_SWR_PDM_WD_CTL0, + 0x03, 0x00); break; }; @@ -773,10 +753,10 @@ static int rouleur_codec_enable_ear_pa(struct snd_soc_dapm_widget *w, ret = swr_slvdev_datapath_control(rouleur->rx_swr_dev, rouleur->rx_swr_dev->dev_num, true); - snd_soc_component_update_bits(component, - ROULEUR_ANA_COMBOPA_CTL, - 0x80, 0x80); usleep_range(5000, 5100); + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_PDM_WD_CTL0, + 0x03, 0x03); break; case SND_SOC_DAPM_POST_PMU: if (rouleur->update_wcd_event) @@ -795,10 +775,10 @@ static int rouleur_codec_enable_ear_pa(struct snd_soc_dapm_widget *w, (WCD_RX1 << 0x10 | 0x1)); break; case SND_SOC_DAPM_POST_PMD: - snd_soc_component_update_bits(component, - ROULEUR_ANA_COMBOPA_CTL, - 0x80, 0x00); usleep_range(5000, 5100); + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_PDM_WD_CTL0, + 0x03, 0x00); }; return ret; } @@ -823,10 +803,10 @@ static int rouleur_codec_enable_lo_pa(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, ROULEUR_ANA_COMBOPA_CTL, 0x40, 0x40); - snd_soc_component_update_bits(component, - ROULEUR_ANA_COMBOPA_CTL, - 0x80, 0x80); usleep_range(5000, 5100); + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_PDM_WD_CTL0, + 0x03, 0x03); break; case SND_SOC_DAPM_POST_PMU: if (rouleur->update_wcd_event) @@ -845,13 +825,13 @@ static int rouleur_codec_enable_lo_pa(struct snd_soc_dapm_widget *w, (WCD_RX1 << 0x10 | 0x1)); break; case SND_SOC_DAPM_POST_PMD: - snd_soc_component_update_bits(component, - ROULEUR_ANA_COMBOPA_CTL, - 0x80, 0x00); snd_soc_component_update_bits(component, ROULEUR_ANA_COMBOPA_CTL, 0x40, 0x00); usleep_range(5000, 5100); + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_PDM_WD_CTL0, + 0x03, 0x00); }; return ret; } @@ -1552,6 +1532,9 @@ static int rouleur_codec_enable_pa_vpos(struct snd_soc_dapm_widget *w, break; case SND_SOC_DAPM_POST_PMD: set_bit(ALLOW_VPOS_DISABLE, &rouleur->status_mask); + ret = swr_slvdev_datapath_control(rouleur->rx_swr_dev, + rouleur->rx_swr_dev->dev_num, + false); break; } return 0; @@ -1822,7 +1805,7 @@ static ssize_t rouleur_version_read(struct snd_info_entry *entry, switch (priv->version) { case ROULEUR_VERSION_1_0: - len = snprintf(buffer, sizeof(buffer), "rouleur_1_0\n"); + len = snprintf(buffer, sizeof(buffer), "ROULEUR_1_0\n"); break; default: len = snprintf(buffer, sizeof(buffer), "VER_UNDEFINED\n"); From 06f7fcd942c21bfc4c9b6193383269c950b2fd6a Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Tue, 14 Apr 2020 18:10:28 +0530 Subject: [PATCH 012/116] asoc: bolero: Update rx dc droop register setting For RX DC droop setting, ensure update proper value during powerup/powerdown based on sample rate. Change-Id: I269d41452911e1999b2dbdf4fa22e383aa973848 Signed-off-by: Laxminath Kasam --- asoc/codecs/bolero/rx-macro.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c index 62da031f26..61f781f934 100644 --- a/asoc/codecs/bolero/rx-macro.c +++ b/asoc/codecs/bolero/rx-macro.c @@ -1709,13 +1709,6 @@ static int rx_macro_config_compander(struct snd_soc_component *component, dev_dbg(component->dev, "%s: event %d compander %d, enabled %d\n", __func__, event, comp + 1, rx_priv->comp_enabled[comp]); - if (!rx_priv->comp_enabled[comp]) - return 0; - - comp_ctl0_reg = BOLERO_CDC_RX_COMPANDER0_CTL0 + - (comp * RX_MACRO_COMP_OFFSET); - rx_path_cfg0_reg = BOLERO_CDC_RX_RX0_RX_PATH_CFG0 + - (comp * RX_MACRO_RX_PATH_OFFSET); rx_path_cfg3_reg = BOLERO_CDC_RX_RX0_RX_PATH_CFG3 + (comp * RX_MACRO_RX_PATH_OFFSET); rx0_path_ctl_reg = BOLERO_CDC_RX_RX0_RX_PATH_CTL + @@ -1731,6 +1724,19 @@ static int rx_macro_config_compander(struct snd_soc_component *component, else val = 0x00; + if (SND_SOC_DAPM_EVENT_ON(event)) + snd_soc_component_update_bits(component, rx_path_cfg3_reg, + 0x03, val); + if (SND_SOC_DAPM_EVENT_OFF(event)) + snd_soc_component_update_bits(component, rx_path_cfg3_reg, + 0x03, 0x03); + if (!rx_priv->comp_enabled[comp]) + return 0; + + comp_ctl0_reg = BOLERO_CDC_RX_COMPANDER0_CTL0 + + (comp * RX_MACRO_COMP_OFFSET); + rx_path_cfg0_reg = BOLERO_CDC_RX_RX0_RX_PATH_CFG0 + + (comp * RX_MACRO_RX_PATH_OFFSET); if (SND_SOC_DAPM_EVENT_ON(event)) { /* Enable Compander Clock */ snd_soc_component_update_bits(component, comp_ctl0_reg, @@ -1741,8 +1747,6 @@ static int rx_macro_config_compander(struct snd_soc_component *component, 0x02, 0x00); snd_soc_component_update_bits(component, rx_path_cfg0_reg, 0x02, 0x02); - snd_soc_component_update_bits(component, rx_path_cfg3_reg, - 0x03, val); } if (SND_SOC_DAPM_EVENT_OFF(event)) { @@ -1754,8 +1758,6 @@ static int rx_macro_config_compander(struct snd_soc_component *component, 0x01, 0x00); snd_soc_component_update_bits(component, comp_ctl0_reg, 0x04, 0x00); - snd_soc_component_update_bits(component, rx_path_cfg3_reg, - 0x03, 0x03); } return 0; From 315e4b16e2ce043d0e3a4926da5313e3e4b0d1c3 Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Sat, 18 Apr 2020 13:53:19 +0530 Subject: [PATCH 013/116] adsp-loader: Add support to load adsp fw name When adsp variant read from fuse registers is not supported, add support to read the fw name and load the same. Change-Id: Icf9aeee8b4c607a6f768f0d73ab0e55d78dc8ac9 Signed-off-by: Aditya Bavanari --- dsp/adsp-loader.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/dsp/adsp-loader.c b/dsp/adsp-loader.c index 8316f003bc..c8e1270b02 100644 --- a/dsp/adsp-loader.c +++ b/dsp/adsp-loader.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2014, 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2014, 2017-2020, The Linux Foundation. All rights reserved. */ #include @@ -333,6 +333,8 @@ static int adsp_loader_probe(struct platform_device *pdev) int fw_name_size; u32 adsp_var_idx = 0; int ret = 0; + u32 adsp_fuse_not_supported = 0; + const char *adsp_fw_name; ret = adsp_loader_init_sysfs(pdev); if (ret != 0) { @@ -344,7 +346,44 @@ static int adsp_loader_probe(struct platform_device *pdev) /* get adsp variant idx */ cell = nvmem_cell_get(&pdev->dev, "adsp_variant"); if (IS_ERR_OR_NULL(cell)) { - dev_dbg(&pdev->dev, "%s: FAILED to get nvmem cell \n", __func__); + dev_dbg(&pdev->dev, "%s: FAILED to get nvmem cell \n", + __func__); + + /* + * When ADSP variant read from fuse register is not + * supported, check if image with different fw image + * name needs to be loaded + */ + ret = of_property_read_u32(pdev->dev.of_node, + "adsp-fuse-not-supported", + &adsp_fuse_not_supported); + if (ret) { + dev_dbg(&pdev->dev, + "%s: adsp_fuse_not_supported prop not found", + __func__, ret); + goto wqueue; + } + + if (adsp_fuse_not_supported) { + /* Read ADSP firmware image name */ + ret = of_property_read_string(pdev->dev.of_node, + "adsp-fw-name", + &adsp_fw_name); + if (ret < 0) { + dev_dbg(&pdev->dev, "%s: unable to read fw-name\n", + __func__); + goto wqueue; + } + + fw_name_size = strlen(adsp_fw_name) + 1; + priv->adsp_fw_name = devm_kzalloc(&pdev->dev, + fw_name_size, + GFP_KERNEL); + if (!priv->adsp_fw_name) + goto wqueue; + strlcpy(priv->adsp_fw_name, adsp_fw_name, + fw_name_size); + } goto wqueue; } buf = nvmem_cell_read(cell, &len); From fbe5306c0288128b53a4bebd221642f0ff53a18e Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Tue, 14 Apr 2020 21:30:47 +0530 Subject: [PATCH 014/116] asoc: codecs: Add support to dump rouleur swr slave regs Add support to dump rouleur swr slave regs. Change-Id: I7bb3664ba4a81ab83dae12534dfe403ac1db6013 Signed-off-by: Aditya Bavanari --- asoc/codecs/rouleur/rouleur_slave.c | 324 ++++++++++++++++++++++++++-- 1 file changed, 312 insertions(+), 12 deletions(-) diff --git a/asoc/codecs/rouleur/rouleur_slave.c b/asoc/codecs/rouleur/rouleur_slave.c index 8fac8a6fbf..5ea4fe4522 100644 --- a/asoc/codecs/rouleur/rouleur_slave.c +++ b/asoc/codecs/rouleur/rouleur_slave.c @@ -11,15 +11,276 @@ #include #include +#ifdef CONFIG_DEBUG_FS +#include +#include + +#define SWR_SLV_MAX_REG_ADDR 0x2009 +#define SWR_SLV_START_REG_ADDR 0x40 +#define SWR_SLV_MAX_BUF_LEN 20 +#define BYTES_PER_LINE 12 +#define SWR_SLV_RD_BUF_LEN 8 +#define SWR_SLV_WR_BUF_LEN 32 +#define SWR_SLV_MAX_DEVICES 2 +#endif /* CONFIG_DEBUG_FS */ + struct rouleur_slave_priv { struct swr_device *swr_slave; +#ifdef CONFIG_DEBUG_FS + struct dentry *debugfs_rouleur_dent; + struct dentry *debugfs_peek; + struct dentry *debugfs_poke; + struct dentry *debugfs_reg_dump; + unsigned int read_data; +#endif }; +#ifdef CONFIG_DEBUG_FS +static int codec_debug_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static int get_parameters(char *buf, u32 *param1, int num_of_par) +{ + char *token = NULL; + int base = 0, cnt = 0; + + token = strsep(&buf, " "); + for (cnt = 0; cnt < num_of_par; cnt++) { + if (token) { + if ((token[1] == 'x') || (token[1] == 'X')) + base = 16; + else + base = 10; + + if (kstrtou32(token, base, ¶m1[cnt]) != 0) + return -EINVAL; + + token = strsep(&buf, " "); + } else { + return -EINVAL; + } + } + return 0; +} + +static bool is_swr_slv_reg_readable(int reg) +{ + int ret = true; + + if (((reg > 0x46) && (reg < 0x4A)) || + ((reg > 0x4A) && (reg < 0x50)) || + ((reg > 0x55) && (reg < 0xD0)) || + ((reg > 0xD0) && (reg < 0xE0)) || + ((reg > 0xE0) && (reg < 0xF0)) || + ((reg > 0xF0) && (reg < 0x100)) || + ((reg > 0x105) && (reg < 0x120)) || + ((reg > 0x205) && (reg < 0x220)) || + ((reg > 0x305) && (reg < 0x320)) || + ((reg > 0x405) && (reg < 0x420)) || + ((reg > 0x128) && (reg < 0x130)) || + ((reg > 0x228) && (reg < 0x230)) || + ((reg > 0x328) && (reg < 0x330)) || + ((reg > 0x428) && (reg < 0x430)) || + ((reg > 0x138) && (reg < 0x205)) || + ((reg > 0x238) && (reg < 0x305)) || + ((reg > 0x338) && (reg < 0x405)) || + ((reg > 0x405) && (reg < 0xF00)) || + ((reg > 0xF05) && (reg < 0xF20)) || + ((reg > 0xF25) && (reg < 0xF30)) || + ((reg > 0xF35) && (reg < 0x2000))) + ret = false; + + return ret; +} + +static ssize_t rouleur_swrslave_reg_show(struct swr_device *pdev, + char __user *ubuf, + size_t count, loff_t *ppos) +{ + int i, reg_val, len; + ssize_t total = 0; + char tmp_buf[SWR_SLV_MAX_BUF_LEN]; + + if (!ubuf || !ppos) + return 0; + + for (i = (((int) *ppos/BYTES_PER_LINE) + SWR_SLV_START_REG_ADDR); + i <= SWR_SLV_MAX_REG_ADDR; i++) { + if (!is_swr_slv_reg_readable(i)) + continue; + swr_read(pdev, pdev->dev_num, i, ®_val, 1); + len = snprintf(tmp_buf, sizeof(tmp_buf), "0x%.3x: 0x%.2x\n", i, + (reg_val & 0xFF)); + if (len < 0) { + pr_err("%s: fail to fill the buffer\n", __func__); + total = -EFAULT; + goto copy_err; + } + if (((total + len) >= count - 1) || (len < 0)) + break; + if (copy_to_user((ubuf + total), tmp_buf, len)) { + pr_err("%s: fail to copy reg dump\n", __func__); + total = -EFAULT; + goto copy_err; + } + total += len; + *ppos += len; + } + +copy_err: + *ppos = SWR_SLV_MAX_REG_ADDR * BYTES_PER_LINE; + return total; +} + +static ssize_t codec_debug_dump(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct swr_device *pdev; + + if (!count || !file || !ppos || !ubuf) + return -EINVAL; + + pdev = file->private_data; + if (!pdev) + return -EINVAL; + + if (*ppos < 0) + return -EINVAL; + + return rouleur_swrslave_reg_show(pdev, ubuf, count, ppos); +} + +static ssize_t codec_debug_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + char lbuf[SWR_SLV_RD_BUF_LEN]; + struct swr_device *pdev = NULL; + struct rouleur_slave_priv *rouleur_slave = NULL; + + if (!count || !file || !ppos || !ubuf) + return -EINVAL; + + pdev = file->private_data; + if (!pdev) + return -EINVAL; + + rouleur_slave = swr_get_dev_data(pdev); + if (!rouleur_slave) + return -EINVAL; + + if (*ppos < 0) + return -EINVAL; + + snprintf(lbuf, sizeof(lbuf), "0x%x\n", + (rouleur_slave->read_data & 0xFF)); + + return simple_read_from_buffer(ubuf, count, ppos, lbuf, + strnlen(lbuf, 7)); +} + +static ssize_t codec_debug_peek_write(struct file *file, + const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + char lbuf[SWR_SLV_WR_BUF_LEN]; + int rc = 0; + u32 param[5]; + struct swr_device *pdev = NULL; + struct rouleur_slave_priv *rouleur_slave = NULL; + + if (!cnt || !file || !ppos || !ubuf) + return -EINVAL; + + pdev = file->private_data; + if (!pdev) + return -EINVAL; + + rouleur_slave = swr_get_dev_data(pdev); + if (!rouleur_slave) + return -EINVAL; + + if (*ppos < 0) + return -EINVAL; + + if (cnt > sizeof(lbuf) - 1) + return -EINVAL; + + rc = copy_from_user(lbuf, ubuf, cnt); + if (rc) + return -EFAULT; + + lbuf[cnt] = '\0'; + rc = get_parameters(lbuf, param, 1); + if (!((param[0] <= SWR_SLV_MAX_REG_ADDR) && (rc == 0))) + return -EINVAL; + swr_read(pdev, pdev->dev_num, param[0], &rouleur_slave->read_data, 1); + if (rc == 0) + rc = cnt; + else + pr_err("%s: rc = %d\n", __func__, rc); + + return rc; +} + +static ssize_t codec_debug_write(struct file *file, + const char __user *ubuf, size_t cnt, loff_t *ppos) +{ + char lbuf[SWR_SLV_WR_BUF_LEN]; + int rc = 0; + u32 param[5]; + struct swr_device *pdev; + + if (!file || !ppos || !ubuf) + return -EINVAL; + + pdev = file->private_data; + if (!pdev) + return -EINVAL; + + if (cnt > sizeof(lbuf) - 1) + return -EINVAL; + + rc = copy_from_user(lbuf, ubuf, cnt); + if (rc) + return -EFAULT; + + lbuf[cnt] = '\0'; + rc = get_parameters(lbuf, param, 2); + if (!((param[0] <= SWR_SLV_MAX_REG_ADDR) && + (param[1] <= 0xFF) && (rc == 0))) + return -EINVAL; + swr_write(pdev, pdev->dev_num, param[0], ¶m[1]); + if (rc == 0) + rc = cnt; + else + pr_err("%s: rc = %d\n", __func__, rc); + + return rc; +} + +static const struct file_operations codec_debug_write_ops = { + .open = codec_debug_open, + .write = codec_debug_write, +}; + +static const struct file_operations codec_debug_read_ops = { + .open = codec_debug_open, + .read = codec_debug_read, + .write = codec_debug_peek_write, +}; + +static const struct file_operations codec_debug_dump_ops = { + .open = codec_debug_open, + .read = codec_debug_dump, +}; +#endif + static int rouleur_slave_bind(struct device *dev, struct device *master, void *data) { int ret = 0; - struct rouleur_slave_priv *rouleur_slave = NULL; uint8_t devnum = 0; struct swr_device *pdev = to_swr_device(dev); @@ -28,15 +289,6 @@ static int rouleur_slave_bind(struct device *dev, return -EINVAL; } - rouleur_slave = devm_kzalloc(&pdev->dev, - sizeof(struct rouleur_slave_priv), GFP_KERNEL); - if (!rouleur_slave) - return -ENOMEM; - - swr_set_dev_data(pdev, rouleur_slave); - - rouleur_slave->swr_slave = pdev; - ret = swr_get_logical_dev_num(pdev, pdev->addr, &devnum); if (ret) { dev_dbg(&pdev->dev, @@ -67,7 +319,6 @@ static void rouleur_slave_unbind(struct device *dev, return; } - swr_set_dev_data(pdev, NULL); } static const struct swr_device_id rouleur_swr_id[] = { @@ -104,12 +355,61 @@ static int rouleur_swr_reset(struct swr_device *pdev) static int rouleur_swr_probe(struct swr_device *pdev) { + struct rouleur_slave_priv *rouleur_slave = NULL; + + rouleur_slave = devm_kzalloc(&pdev->dev, + sizeof(struct rouleur_slave_priv), GFP_KERNEL); + if (!rouleur_slave) + return -ENOMEM; + + swr_set_dev_data(pdev, rouleur_slave); + + rouleur_slave->swr_slave = pdev; +#ifdef CONFIG_DEBUG_FS + if (!rouleur_slave->debugfs_rouleur_dent) { + rouleur_slave->debugfs_rouleur_dent = debugfs_create_dir( + dev_name(&pdev->dev), 0); + if (!IS_ERR(rouleur_slave->debugfs_rouleur_dent)) { + rouleur_slave->debugfs_peek = + debugfs_create_file("swrslave_peek", + S_IFREG | 0444, + rouleur_slave->debugfs_rouleur_dent, + (void *) pdev, + &codec_debug_read_ops); + + rouleur_slave->debugfs_poke = + debugfs_create_file("swrslave_poke", + S_IFREG | 0444, + rouleur_slave->debugfs_rouleur_dent, + (void *) pdev, + &codec_debug_write_ops); + + rouleur_slave->debugfs_reg_dump = + debugfs_create_file( + "swrslave_reg_dump", + S_IFREG | 0444, + rouleur_slave->debugfs_rouleur_dent, + (void *) pdev, + &codec_debug_dump_ops); + } + } +#endif return component_add(&pdev->dev, &rouleur_slave_comp_ops); } static int rouleur_swr_remove(struct swr_device *pdev) { +#ifdef CONFIG_DEBUG_FS + struct rouleur_slave_priv *rouleur_slave = swr_get_dev_data(pdev); + + if (rouleur_slave) { + debugfs_remove_recursive(rouleur_slave->debugfs_rouleur_dent); + rouleur_slave->debugfs_rouleur_dent = NULL; + } +#endif component_del(&pdev->dev, &rouleur_slave_comp_ops); + swr_set_dev_data(pdev, NULL); + swr_remove_device(pdev); return 0; } @@ -140,5 +440,5 @@ static void __exit rouleur_slave_exit(void) module_init(rouleur_slave_init); module_exit(rouleur_slave_exit); -MODULE_DESCRIPTION("WCD937X Swr Slave driver"); +MODULE_DESCRIPTION("Rouleur Swr Slave driver"); MODULE_LICENSE("GPL v2"); From c238fc0d7496e7d938af4a5925d0a5fade0478b2 Mon Sep 17 00:00:00 2001 From: Surendar Karka Date: Tue, 12 Feb 2019 12:46:05 +0530 Subject: [PATCH 015/116] asoc: enable TTP generator Add support to enable TTP generator in AFE. Change-Id: I0186dc18809b87a912a1c3ec9dd7fcd26aa726f5 Signed-off-by: Surendar Karka --- asoc/msm-dai-q6-v2.c | 142 +++++++++++++++++++++++++++++++++++-- dsp/q6afe.c | 99 ++++++++++++++++++++++++-- include/dsp/apr_audio-v2.h | 50 +++++++++++++ include/dsp/q6afe-v2.h | 5 ++ 4 files changed, 284 insertions(+), 12 deletions(-) diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c index 82a627aea0..2d98ec481b 100644 --- a/asoc/msm-dai-q6-v2.c +++ b/asoc/msm-dai-q6-v2.c @@ -232,6 +232,7 @@ struct msm_dai_q6_dai_data { u16 afe_tx_out_bitformat; struct afe_enc_config enc_config; struct afe_dec_config dec_config; + struct afe_ttp_config ttp_config; union afe_port_config port_config; u16 vi_feed_mono; u32 xt_logging_disable; @@ -2229,6 +2230,7 @@ static int msm_dai_q6_prepare(struct snd_pcm_substream *substream, { struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev); int rc = 0; + uint16_t ttp_gen_enable = dai_data->ttp_config.ttp_gen_enable.enable; if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) { if (dai_data->enc_config.format != ENC_FMT_NONE) { @@ -2278,13 +2280,27 @@ static int msm_dai_q6_prepare(struct snd_pcm_substream *substream, bitwidth = 0; break; } - pr_debug("%s: calling AFE_PORT_START_V2 with dec format: %d\n", - __func__, dai_data->dec_config.format); - rc = afe_port_start_v2(dai->id, &dai_data->port_config, - dai_data->rate, - dai_data->afe_tx_out_channels, - bitwidth, - NULL, &dai_data->dec_config); + + if (ttp_gen_enable == true) { + pr_debug("%s: calling AFE_PORT_START_V3 with dec format: %d\n", + __func__, dai_data->dec_config.format); + rc = afe_port_start_v3(dai->id, + &dai_data->port_config, + dai_data->rate, + dai_data->afe_tx_out_channels, + bitwidth, + NULL, &dai_data->dec_config, + &dai_data->ttp_config); + } else { + pr_debug("%s: calling AFE_PORT_START_V2 with dec format: %d\n", + __func__, dai_data->dec_config.format); + rc = afe_port_start_v2(dai->id, + &dai_data->port_config, + dai_data->rate, + dai_data->afe_tx_out_channels, + bitwidth, + NULL, &dai_data->dec_config); + } if (rc < 0) { pr_err("%s: fail to open AFE port 0x%x\n", __func__, dai->id); @@ -3668,6 +3684,91 @@ static int msm_dai_q6_afe_dec_cfg_put(struct snd_kcontrol *kcontrol, return ret; } +static int msm_dai_q6_afe_enable_ttp_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; + uinfo->count = sizeof(struct afe_ttp_gen_enable_t); + + return 0; +} + +static int msm_dai_q6_afe_enable_ttp_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data; + + pr_debug("%s:\n", __func__); + if (!dai_data) { + pr_err("%s: Invalid dai data\n", __func__); + return -EINVAL; + } + + memcpy(ucontrol->value.bytes.data, + &dai_data->ttp_config.ttp_gen_enable, + sizeof(struct afe_ttp_gen_enable_t)); + return 0; +} + +static int msm_dai_q6_afe_enable_ttp_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data; + + pr_debug("%s:\n", __func__); + if (!dai_data) { + pr_err("%s: Invalid dai data\n", __func__); + return -EINVAL; + } + + memcpy(&dai_data->ttp_config.ttp_gen_enable, + ucontrol->value.bytes.data, + sizeof(struct afe_ttp_gen_enable_t)); + return 0; +} + +static int msm_dai_q6_afe_ttp_cfg_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; + uinfo->count = sizeof(struct afe_ttp_gen_cfg_t); + + return 0; +} + +static int msm_dai_q6_afe_ttp_cfg_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data; + + pr_debug("%s:\n", __func__); + if (!dai_data) { + pr_err("%s: Invalid dai data\n", __func__); + return -EINVAL; + } + + memcpy(ucontrol->value.bytes.data, + &dai_data->ttp_config.ttp_gen_cfg, + sizeof(struct afe_ttp_gen_cfg_t)); + return 0; +} + +static int msm_dai_q6_afe_ttp_cfg_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct msm_dai_q6_dai_data *dai_data = kcontrol->private_data; + + pr_debug("%s: Received ttp config\n", __func__); + if (!dai_data) { + pr_err("%s: Invalid dai data\n", __func__); + return -EINVAL; + } + + memcpy(&dai_data->ttp_config.ttp_gen_cfg, + ucontrol->value.bytes.data, sizeof(struct afe_ttp_gen_cfg_t)); + return 0; +} + static const struct snd_kcontrol_new afe_dec_config_controls[] = { { .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | @@ -3695,6 +3796,27 @@ static const struct snd_kcontrol_new afe_dec_config_controls[] = { msm_dai_q6_afe_output_bit_format_put), }; +static const struct snd_kcontrol_new afe_ttp_config_controls[] = { + { + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_INACTIVE), + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "TTP Enable", + .info = msm_dai_q6_afe_enable_ttp_info, + .get = msm_dai_q6_afe_enable_ttp_get, + .put = msm_dai_q6_afe_enable_ttp_put, + }, + { + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_INACTIVE), + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "AFE TTP config", + .info = msm_dai_q6_afe_ttp_cfg_info, + .get = msm_dai_q6_afe_ttp_cfg_get, + .put = msm_dai_q6_afe_ttp_cfg_put, + }, +}; + static int msm_dai_q6_slim_rx_drift_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -3918,6 +4040,12 @@ static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai) rc = snd_ctl_add(dai->component->card->snd_card, snd_ctl_new1(&afe_dec_config_controls[3], dai_data)); + rc = snd_ctl_add(dai->component->card->snd_card, + snd_ctl_new1(&afe_ttp_config_controls[0], + dai_data)); + rc = snd_ctl_add(dai->component->card->snd_card, + snd_ctl_new1(&afe_ttp_config_controls[1], + dai_data)); break; case RT_PROXY_DAI_001_RX: rc = snd_ctl_add(dai->component->card->snd_card, diff --git a/dsp/q6afe.c b/dsp/q6afe.c index 97521002e9..39e67da2b8 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -3886,6 +3886,51 @@ exit: return ret; } +static int q6afe_send_ttp_config(u16 port_id, + union afe_port_config afe_config, + struct afe_ttp_config *ttp_cfg) +{ + struct afe_ttp_gen_enable_t ttp_gen_enable; + struct afe_ttp_gen_cfg_t ttp_gen_cfg; + struct param_hdr_v3 param_hdr; + int ret; + + memset(&ttp_gen_enable, 0, sizeof(ttp_gen_enable)); + memset(&ttp_gen_cfg, 0, sizeof(ttp_gen_cfg)); + memset(¶m_hdr, 0, sizeof(param_hdr)); + + param_hdr.module_id = AFE_MODULE_ID_DECODER; + param_hdr.instance_id = INSTANCE_ID_0; + + pr_debug("%s: Enable TTP generator\n", __func__); + ttp_gen_enable = ttp_cfg->ttp_gen_enable; + param_hdr.param_id = AVS_DEPACKETIZER_PARAM_ID_TTP_GEN_STATE; + param_hdr.param_size = sizeof(struct afe_ttp_gen_enable_t); + ret = q6afe_pack_and_set_param_in_band(port_id, + q6audio_get_port_index(port_id), + param_hdr, + (u8 *) &ttp_gen_enable); + if (ret) { + pr_err("%s: AVS_DEPACKETIZER_PARAM_ID_TTP_GEN_STATE for port 0x%x failed %d\n", + __func__, port_id, ret); + goto exit; + } + + pr_debug("%s: sending TTP generator config\n", __func__); + ttp_gen_cfg = ttp_cfg->ttp_gen_cfg; + param_hdr.param_id = AVS_DEPACKETIZER_PARAM_ID_TTP_GEN_CFG; + param_hdr.param_size = sizeof(struct afe_ttp_gen_cfg_t); + ret = q6afe_pack_and_set_param_in_band(port_id, + q6audio_get_port_index(port_id), + param_hdr, + (u8 *) &ttp_gen_cfg); + if (ret) + pr_err("%s: AVS_DEPACKETIZER_PARAM_ID_TTP_GEN_CFG for port 0x%x failed %d\n", + __func__, port_id, ret); +exit: + return ret; +} + static int q6afe_send_dec_config(u16 port_id, union afe_port_config afe_config, struct afe_dec_config *cfg, @@ -4556,7 +4601,8 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config, u32 rate, u16 afe_in_channels, u16 afe_in_bit_width, union afe_enc_config_data *enc_cfg, u32 codec_format, u32 scrambler_mode, u32 mono_mode, - struct afe_dec_config *dec_cfg) + struct afe_dec_config *dec_cfg, + struct afe_ttp_config *ttp_cfg) { union afe_port_config port_cfg; struct param_hdr_v3 param_hdr; @@ -4873,6 +4919,15 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config, goto fail_cmd; } } + if (ttp_cfg != NULL) { + ret = q6afe_send_ttp_config(port_id, *afe_config, + ttp_cfg); + if (ret) { + pr_err("%s: AFE TTP config for port 0x%x failed %d\n", + __func__, port_id, ret); + goto fail_cmd; + } + } } port_index = afe_get_port_index(port_id); @@ -4919,8 +4974,8 @@ fail_cmd: int afe_port_start(u16 port_id, union afe_port_config *afe_config, u32 rate) { - return __afe_port_start(port_id, afe_config, rate, - 0, 0, NULL, ASM_MEDIA_FMT_NONE, 0, 0, NULL); + return __afe_port_start(port_id, afe_config, rate, 0, 0, NULL, + ASM_MEDIA_FMT_NONE, 0, 0, NULL, NULL); } EXPORT_SYMBOL(afe_port_start); @@ -4950,16 +5005,50 @@ int afe_port_start_v2(u16 port_id, union afe_port_config *afe_config, afe_in_channels, afe_in_bit_width, &enc_cfg->data, enc_cfg->format, enc_cfg->scrambler_mode, - enc_cfg->mono_mode, dec_cfg); + enc_cfg->mono_mode, dec_cfg, NULL); else if (dec_cfg != NULL) ret = __afe_port_start(port_id, afe_config, rate, afe_in_channels, afe_in_bit_width, - NULL, dec_cfg->format, 0, 0, dec_cfg); + NULL, dec_cfg->format, 0, 0, + dec_cfg, NULL); return ret; } EXPORT_SYMBOL(afe_port_start_v2); +/** + * afe_port_start_v3 - to configure AFE session with + * specified port configuration and encoder /decoder params + * + * @port_id: AFE port id number + * @afe_config: port configuration + * @rate: sampling rate of port + * @enc_cfg: AFE enc configuration information to setup encoder + * @afe_in_channels: AFE input channel configuration, this needs + * update only if input channel is differ from AFE output + * @dec_cfg: AFE dec configuration information to set up decoder + * @ttp_cfg: TTP generator configuration to enable TTP in AFE + * + * Returns 0 on success or error value on port start failure. + */ +int afe_port_start_v3(u16 port_id, union afe_port_config *afe_config, + u32 rate, u16 afe_in_channels, u16 afe_in_bit_width, + struct afe_enc_config *enc_cfg, + struct afe_dec_config *dec_cfg, + struct afe_ttp_config *ttp_cfg) +{ + int ret = 0; + + if (dec_cfg != NULL && ttp_cfg != NULL) + ret = __afe_port_start(port_id, afe_config, rate, + afe_in_channels, afe_in_bit_width, + NULL, dec_cfg->format, 0, 0, + dec_cfg, ttp_cfg); + + return ret; +} +EXPORT_SYMBOL(afe_port_start_v3); + int afe_get_port_index(u16 port_id) { switch (port_id) { diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h index 7a686349a4..f3b7ade102 100644 --- a/include/dsp/apr_audio-v2.h +++ b/include/dsp/apr_audio-v2.h @@ -4728,6 +4728,56 @@ struct afe_enc_config { union afe_enc_config_data data; }; +/* + * Enable TTP generator in AFE. + */ +#define AVS_DEPACKETIZER_PARAM_ID_TTP_GEN_STATE 0x000132EF +/* + * Configure TTP generator params in AFE. + */ +#define AVS_DEPACKETIZER_PARAM_ID_TTP_GEN_CFG 0x000132F0 +#define MAX_TTP_OFFSET_PAIRS 4 +struct afe_ttp_gen_enable_t { + uint16_t enable; + uint16_t reserved; +} __packed; + +struct afe_ttp_ssrc_offset_pair_t { + uint32_t ssrc; + uint32_t offset; +} __packed; + +struct afe_ttp_gen_cfg_t { + uint32_t ttp_offset_default; + /* + * TTP offset uses for all other cases + * where no valid SSRC is received. + */ + uint32_t settling_time; + /* + * If settling_mode==0x00: time in [us] + * after first received packet until + * packets are no longer dropped. + */ + uint16_t settling_mode; + /* + * 0x00(Drop), 0x01(Settle) + */ + uint16_t num_ssrc_offsets; + /* + * Number of SSRC/TTPOFFSET pairs to follow + */ + struct afe_ttp_ssrc_offset_pair_t ssrc_ttp_offset[MAX_TTP_OFFSET_PAIRS]; + /* + * Array of ssrc/offset pairs + */ +} __packed; + +struct afe_ttp_config { + struct afe_ttp_gen_enable_t ttp_gen_enable; + struct afe_ttp_gen_cfg_t ttp_gen_cfg; +}; + union afe_dec_config_data { struct asm_sbc_dec_cfg_t sbc_config; struct asm_aac_dec_cfg_v2_t aac_config; diff --git a/include/dsp/q6afe-v2.h b/include/dsp/q6afe-v2.h index 73a7cf872a..035da1f469 100644 --- a/include/dsp/q6afe-v2.h +++ b/include/dsp/q6afe-v2.h @@ -400,6 +400,11 @@ int afe_port_start_v2(u16 port_id, union afe_port_config *afe_config, u32 rate, u16 afe_in_channels, u16 afe_in_bit_width, struct afe_enc_config *enc_config, struct afe_dec_config *dec_config); +int afe_port_start_v3(u16 port_id, union afe_port_config *afe_config, + u32 rate, u16 afe_in_channels, u16 afe_in_bit_width, + struct afe_enc_config *enc_config, + struct afe_dec_config *dec_config, + struct afe_ttp_config *ttp_config); int afe_spk_prot_feed_back_cfg(int src_port, int dst_port, int l_ch, int r_ch, u32 enable); int afe_spk_prot_get_calib_data(struct afe_spkr_prot_get_vi_calib *calib); From 6ea98f1cae39453ad76c4cd4dbb332cd2128ece2 Mon Sep 17 00:00:00 2001 From: Surendar Karka Date: Fri, 24 Jan 2020 14:35:07 +0530 Subject: [PATCH 016/116] dsp: Add support to set clock drift - Add support to adjust drift in audio interface clock source PLL. - ADSP adjusts the source clock based on clk id. Add support in AFE driver to get clk id based on the AFE port. Change-Id: I45ceb6579bb15e32541051e0ba936a2d903e4923 Signed-off-by: Surendar Karka --- dsp/q6afe.c | 191 +++++++++++++++++++++++++++++++++++++ include/dsp/apr_audio-v2.h | 29 ++++++ include/dsp/q6afe-v2.h | 3 + 3 files changed, 223 insertions(+) diff --git a/dsp/q6afe.c b/dsp/q6afe.c index 1eced32258..ec212acb78 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -184,6 +184,43 @@ struct afe_ctl { uint32_t v_vali_flag; }; +struct afe_clkinfo_per_port { + u16 port_id; /* AFE port ID */ + uint32_t clk_id; /* Clock ID */ +}; + +struct afe_clkinfo_per_port clkinfo_per_port[] = { + { AFE_PORT_ID_PRIMARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT}, + { AFE_PORT_ID_SECONDARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT}, + { AFE_PORT_ID_TERTIARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT}, + { AFE_PORT_ID_QUATERNARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT}, + { AFE_PORT_ID_QUINARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_QUI_MI2S_IBIT}, + { AFE_PORT_ID_SENARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_SEN_MI2S_IBIT}, + { AFE_PORT_ID_PRIMARY_PCM_RX, Q6AFE_LPASS_CLK_ID_PRI_PCM_IBIT}, + { AFE_PORT_ID_SECONDARY_PCM_RX, Q6AFE_LPASS_CLK_ID_SEC_PCM_IBIT}, + { AFE_PORT_ID_TERTIARY_PCM_RX, Q6AFE_LPASS_CLK_ID_TER_PCM_IBIT}, + { AFE_PORT_ID_QUATERNARY_PCM_RX, Q6AFE_LPASS_CLK_ID_QUAD_PCM_IBIT}, + { AFE_PORT_ID_QUINARY_PCM_RX, Q6AFE_LPASS_CLK_ID_QUIN_PCM_IBIT}, + { AFE_PORT_ID_SENARY_PCM_RX, Q6AFE_LPASS_CLK_ID_SEN_PCM_IBIT}, + { AFE_PORT_ID_PRIMARY_TDM_RX, Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT}, + { AFE_PORT_ID_SECONDARY_TDM_RX, Q6AFE_LPASS_CLK_ID_SEC_TDM_IBIT}, + { AFE_PORT_ID_TERTIARY_TDM_RX, Q6AFE_LPASS_CLK_ID_TER_TDM_IBIT}, + { AFE_PORT_ID_QUATERNARY_TDM_RX, Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT}, + { AFE_PORT_ID_QUINARY_TDM_RX, Q6AFE_LPASS_CLK_ID_QUIN_TDM_IBIT}, + { AFE_PORT_ID_PRIMARY_SPDIF_RX, + AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_OUTPUT_CORE}, + { AFE_PORT_ID_PRIMARY_SPDIF_TX, + AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_INPUT_CORE}, + { AFE_PORT_ID_SECONDARY_SPDIF_RX, + AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_OUTPUT_CORE}, + { AFE_PORT_ID_SECONDARY_SPDIF_TX, + AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_INPUT_CORE}, + { AFE_PORT_ID_PRIMARY_META_MI2S_RX, + Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT}, + { AFE_PORT_ID_SECONDARY_META_MI2S_RX, + Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT}, +}; + static atomic_t afe_ports_mad_type[SLIMBUS_PORT_LAST - SLIMBUS_0_RX]; static unsigned long afe_configured_cmd; @@ -8264,6 +8301,156 @@ int afe_set_lpass_clock(u16 port_id, struct afe_clk_cfg *cfg) } EXPORT_SYMBOL(afe_set_lpass_clock); +static int afe_get_port_idx(u16 port_id) +{ + u16 afe_port = 0; + int i = -EINVAL; + + pr_debug("%s: port id 0x%x\n", __func__, port_id); + + if ((port_id >= AFE_PORT_ID_TDM_PORT_RANGE_START) && + (port_id <= AFE_PORT_ID_TDM_PORT_RANGE_END)) + afe_port = port_id & 0xFFF0; + else if ((port_id == AFE_PORT_ID_PRIMARY_SPDIF_RX) || + (port_id == AFE_PORT_ID_PRIMARY_SPDIF_TX) || + (port_id == AFE_PORT_ID_SECONDARY_SPDIF_RX) || + (port_id == AFE_PORT_ID_SECONDARY_SPDIF_TX)) + afe_port = port_id; + else + afe_port = port_id & 0xFFFE; + + for (i = 0; i < ARRAY_SIZE(clkinfo_per_port); i++) { + if (afe_port == clkinfo_per_port[i].port_id) { + pr_debug("%s: idx 0x%x port id 0x%x\n", __func__, + i, afe_port); + return i; + } + } + + pr_debug("%s: cannot get idx for port id 0x%x\n", __func__, + afe_port); + + return -EINVAL; +} + +static int afe_get_clk_id(u16 port_id) +{ + u16 afe_port = 0; + uint32_t clk_id = -EINVAL; + int idx = 0; + + idx = afe_get_port_idx(port_id); + if (idx < 0) { + pr_err("%s: cannot get clock id for port id 0x%x\n", __func__, + afe_port); + return -EINVAL; + } + + clk_id = clkinfo_per_port[idx].clk_id; + pr_debug("%s: clk id 0x%x port id 0x%x\n", __func__, clk_id, + afe_port); + + return clk_id; +} + +/** + * afe_set_clk_id - Update clock id for AFE port + * + * @port_id: AFE port id + * @clk_id: CLock ID + * + * Returns 0 on success, appropriate error code otherwise + */ +int afe_set_clk_id(u16 port_id, uint32_t clk_id) +{ + u16 afe_port = 0; + int idx = 0; + + idx = afe_get_port_idx(port_id); + if (idx < 0) { + pr_debug("%s: cannot set clock id for port id 0x%x\n", __func__, + afe_port); + return -EINVAL; + } + + clkinfo_per_port[idx].clk_id = clk_id; + pr_debug("%s: updated clk id 0x%x port id 0x%x\n", __func__, + clkinfo_per_port[idx].clk_id, afe_port); + + return 0; +} +EXPORT_SYMBOL(afe_set_clk_id); + +/** + * afe_set_pll_clk_drift - Set audio interface PLL clock drift + * + * @port_id: AFE port id + * @set_clk_drift: clk drift to adjust PLL + * @clk_reset: reset Interface clock to original value + * + * Returns 0 on success, appropriate error code otherwise + */ +int afe_set_pll_clk_drift(u16 port_id, int32_t set_clk_drift, + uint32_t clk_reset) +{ + struct afe_set_clk_drift clk_drift; + struct param_hdr_v3 param_hdr; + uint32_t clk_id; + int index = 0, ret = 0; + + memset(¶m_hdr, 0, sizeof(param_hdr)); + memset(&clk_drift, 0, sizeof(clk_drift)); + + index = q6audio_get_port_index(port_id); + if (index < 0 || index >= AFE_MAX_PORTS) { + pr_err("%s: index[%d] invalid!\n", __func__, index); + return -EINVAL; + } + + ret = afe_q6_interface_prepare(); + if (ret != 0) { + pr_err_ratelimited("%s: Q6 interface prepare failed %d\n", + __func__, ret); + return ret; + } + + clk_id = afe_get_clk_id(port_id); + if (clk_id < 0) { + pr_err("%s: cannot get clk id for port id 0x%x\n", + __func__, port_id); + return -EINVAL; + } + + if (clk_id & 0x01) { + pr_err("%s: cannot adjust clock drift for external clock id 0x%x\n", + __func__, clk_id); + return -EINVAL; + } + + clk_drift.clk_drift = set_clk_drift; + clk_drift.clk_reset = clk_reset; + clk_drift.clk_id = clk_id; + pr_debug("%s: clk id = 0x%x clk drift = %d clk reset = %d port id 0x%x\n", + __func__, clk_drift.clk_id, clk_drift.clk_drift, + clk_drift.clk_reset, port_id); + + mutex_lock(&this_afe.afe_clk_lock); + param_hdr.module_id = AFE_MODULE_CLOCK_SET; + param_hdr.instance_id = INSTANCE_ID_0; + param_hdr.param_id = AFE_PARAM_ID_CLOCK_ADJUST; + param_hdr.param_size = sizeof(struct afe_set_clk_drift); + + ret = q6afe_svc_pack_and_set_param_in_band(index, param_hdr, + (u8 *) &clk_drift); + if (ret < 0) + pr_err_ratelimited("%s: AFE PLL clk drift failed with ret %d\n", + __func__, ret); + + mutex_unlock(&this_afe.afe_clk_lock); + return ret; +} +EXPORT_SYMBOL(afe_set_pll_clk_drift); + /** * afe_set_lpass_clk_cfg - Set AFE clk config * @@ -8350,6 +8537,10 @@ int afe_set_lpass_clock_v2(u16 port_id, struct afe_clk_set *cfg) return -EINVAL; } + ret = afe_set_clk_id(port_id, cfg->clk_id); + if (ret < 0) + pr_debug("%s: afe_set_clk_id fail %d\n", __func__, ret); + ret = afe_set_lpass_clk_cfg(index, cfg); if (ret) pr_err("%s: afe_set_lpass_clk_cfg_v2 failed %d\n", diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h index 45ff23ed2f..82be8ebacd 100644 --- a/include/dsp/apr_audio-v2.h +++ b/include/dsp/apr_audio-v2.h @@ -12096,6 +12096,35 @@ struct afe_clk_cfg { #define AFE_MODULE_CLOCK_SET 0x0001028F #define AFE_PARAM_ID_CLOCK_SET 0x00010290 +struct afe_set_clk_drift { + /* + * Clock ID + * @values + * - 0x100 to 0x10E + * - 0x200 to 0x20C + * - 0x500 to 0x505 + */ + uint32_t clk_id; + + /* + * Clock drift (in PPB) to be set. + * @values + * - need to get values from DSP team + */ + int32_t clk_drift; + + /* + * Clock rest. + * @values + * - 1 -- Reset PLL with the original frequency + * - 0 -- Adjust the clock with the clk drift value + */ + uint32_t clk_reset; +} __packed; + +/* This param id is used to adjust audio interface PLL*/ +#define AFE_PARAM_ID_CLOCK_ADJUST 0x000102C6 + enum afe_lpass_digital_clk_src { Q6AFE_LPASS_DIGITAL_ROOT_INVALID, Q6AFE_LPASS_DIGITAL_ROOT_PRI_MI2S_OSR, diff --git a/include/dsp/q6afe-v2.h b/include/dsp/q6afe-v2.h index dd3d934d6f..dc8f918788 100644 --- a/include/dsp/q6afe-v2.h +++ b/include/dsp/q6afe-v2.h @@ -487,6 +487,9 @@ void afe_register_wakeup_irq_callback( void (*afe_cb_wakeup_irq)(void *handle)); int afe_get_doa_tracking_mon(u16 port_id, struct doa_tracking_mon_param *doa_tracking_data); +int afe_set_pll_clk_drift(u16 port_id, int32_t set_clk_drift, + uint32_t clk_reset); +int afe_set_clk_id(u16 port_id, uint32_t clk_id); enum { AFE_LPASS_CORE_HW_BLOCK_ID_NONE, From a44c97046674f03f17cb60c17ee2d12aaf95732a Mon Sep 17 00:00:00 2001 From: Surendar Karka Date: Fri, 24 Jan 2020 14:41:46 +0530 Subject: [PATCH 017/116] asoc: add mixer control to set clock drift Add mixer controls support in routing driver to adjust the source PLL clock drift. Change-Id: I211330793f8650902130905f308dc5d4b73e09fa Signed-off-by: Surendar Karka --- asoc/msm-pcm-routing-v2.c | 47 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c index 35b2a8bc31..05443f09f3 100644 --- a/asoc/msm-pcm-routing-v2.c +++ b/asoc/msm-pcm-routing-v2.c @@ -30180,6 +30180,50 @@ static const struct snd_kcontrol_new aptx_dec_license_controls[] = { msm_aptx_dec_license_control_put), }; +static int msm_routing_get_pll_clk_drift(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static int msm_routing_put_pll_clk_drift(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u16 port_id = 0; + int32_t clk_drift = 0; + uint32_t clk_reset = 0; + int be_idx, ret = -EINVAL; + + be_idx = ucontrol->value.integer.value[0]; + clk_drift = ucontrol->value.integer.value[1]; + clk_reset = ucontrol->value.integer.value[2]; + + if (be_idx < 0 && be_idx >= MSM_BACKEND_DAI_MAX) { + pr_err("%s: Invalid be id %d\n", __func__, be_idx); + return -EINVAL; + } + + if (!msm_bedais[be_idx].active && !clk_reset) { + pr_err("%s:BE is not active %d, cannot set clock drift\n", + __func__, be_idx); + return -EINVAL; + } + + port_id = msm_bedais[be_idx].port_id; + pr_debug("%s: clk drift %d be idx %d clk reset %d port id 0x%x\n", + __func__, clk_drift, be_idx, clk_reset, port_id); + ret = afe_set_pll_clk_drift(port_id, clk_drift, clk_reset); + if (ret < 0) + pr_err("%s: failed to set pll clk drift\n", __func__); + + return ret; +} + +static const struct snd_kcontrol_new pll_clk_drift_controls[] = { + SOC_SINGLE_MULTI_EXT("PLL config data", SND_SOC_NOPM, 0, 0xFFFFFFFF, + 0, 128, msm_routing_get_pll_clk_drift, msm_routing_put_pll_clk_drift), +}; + static int msm_routing_put_port_chmap_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -30480,6 +30524,9 @@ static int msm_routing_probe(struct snd_soc_component *component) port_multi_channel_map_mixer_controls, ARRAY_SIZE(port_multi_channel_map_mixer_controls)); + snd_soc_add_component_controls(component, pll_clk_drift_controls, + ARRAY_SIZE(pll_clk_drift_controls)); + return 0; } From 98a6eda6316a8f2c5d92983717f148ea9efc8364 Mon Sep 17 00:00:00 2001 From: Surendar Karka Date: Fri, 24 Jan 2020 14:44:13 +0530 Subject: [PATCH 018/116] asoc: qcs405: add support to set clock drift AFE driver maintains the clk id for each port. AFE driver has no clue of the master port in META I2S port. Add support to set the clk id for META I2S port. Change-Id: Ic531e94df5503f5ff95364830c5177e9cd86af6c Signed-off-by: Surendar Karka --- asoc/qcs405.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/asoc/qcs405.c b/asoc/qcs405.c index 18dfb82207..2c4c5fab03 100644 --- a/asoc/qcs405.c +++ b/asoc/qcs405.c @@ -6279,6 +6279,7 @@ static int msm_meta_mi2s_snd_startup(struct snd_pcm_substream *substream) 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); + u16 port_id = 0; dev_dbg(rtd->card->dev, "%s: substream = %s stream = %d, dai name %s, dai ID %d\n", @@ -6312,6 +6313,13 @@ static int msm_meta_mi2s_snd_startup(struct snd_pcm_substream *substream) meta_mi2s_intf_conf[index].clk_enable[i] = true; if (i == 0) { + port_id = msm_get_port_id(rtd->dai_link->id); + ret = afe_set_clk_id(port_id, + mi2s_clk[member_port].clk_id); + if (ret < 0) + pr_err("%s: afe_set_clk_id fail %d\n", + __func__, ret); + 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", From f03085692d71e4475d31c1e1b74286adc438161c Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Wed, 29 Apr 2020 09:40:56 +0530 Subject: [PATCH 019/116] asoc: Add digital mute callback function for cdc dma Add a new digital mute callback function for cdc dma as it uses a different dai structure. Change-Id: I8db4e9610aee0d519ccc50975a779b9d2d8c671e Signed-off-by: Aditya Bavanari --- asoc/msm-dai-q6-v2.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c index ca39487c8c..2bc20e4f17 100644 --- a/asoc/msm-dai-q6-v2.c +++ b/asoc/msm-dai-q6-v2.c @@ -2795,7 +2795,6 @@ static int msm_dai_q6_set_channel_map(struct snd_soc_dai *dai, return rc; } -/* all ports with excursion logging requirement can use this digital_mute api */ static int msm_dai_q6_spk_digital_mute(struct snd_soc_dai *dai, int mute) { @@ -12357,7 +12356,8 @@ static int msm_dai_q6_cdc_dma_prepare(struct snd_pcm_substream *substream, static void msm_dai_q6_cdc_dma_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev); + struct msm_dai_q6_cdc_dma_dai_data *dai_data = + dev_get_drvdata(dai->dev); int rc = 0; if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) { @@ -12376,6 +12376,19 @@ static void msm_dai_q6_cdc_dma_shutdown(struct snd_pcm_substream *substream, clear_bit(STATUS_PORT_STARTED, dai_data->hwfree_status); } +static int msm_dai_q6_cdc_dma_digital_mute(struct snd_soc_dai *dai, + int mute) +{ + int port_id = dai->id; + struct msm_dai_q6_cdc_dma_dai_data *dai_data = + dev_get_drvdata(dai->dev); + + if (mute && !dai_data->xt_logging_disable) + afe_get_sp_xt_logging_data(port_id); + + return 0; +} + static struct snd_soc_dai_ops msm_dai_q6_cdc_dma_ops = { .prepare = msm_dai_q6_cdc_dma_prepare, .hw_params = msm_dai_q6_cdc_dma_hw_params, @@ -12388,7 +12401,7 @@ static struct snd_soc_dai_ops msm_dai_q6_cdc_wsa_dma_ops = { .hw_params = msm_dai_q6_cdc_dma_hw_params, .shutdown = msm_dai_q6_cdc_dma_shutdown, .set_channel_map = msm_dai_q6_cdc_dma_set_channel_map, - .digital_mute = msm_dai_q6_spk_digital_mute, + .digital_mute = msm_dai_q6_cdc_dma_digital_mute, }; static struct snd_soc_dai_driver msm_dai_q6_cdc_dma_dai[] = { From 31aa87540582c80a4e808bed73490c5cc66d3fa9 Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Thu, 19 Mar 2020 18:30:10 +0530 Subject: [PATCH 020/116] audio-kernel: Synchronize hw vote and unvote requests HW vote and unvote is currently called from multiple clients leading to synchronization issues during SSR/PDR scenarios. Synchronize all the vote requests by using digital codec resource manager. Change-Id: I7e63f69ab5d761a3bb4c7ce70bbef2e8bfd76cfb Signed-off-by: Aditya Bavanari --- asoc/codecs/bolero/bolero-cdc.c | 11 ++-- asoc/codecs/bolero/va-macro.c | 7 ++- dsp/Kbuild | 4 ++ dsp/digital-cdc-rsc-mgr.c | 100 ++++++++++++++++++++++++++++++ dsp/q6_init.c | 4 +- dsp/q6_init.h | 14 +++++ include/dsp/digital-cdc-rsc-mgr.h | 32 ++++++++++ soc/pinctrl-lpi.c | 19 +++++- soc/swr-mstr-ctrl.c | 19 +++--- 9 files changed, 192 insertions(+), 18 deletions(-) create mode 100644 dsp/digital-cdc-rsc-mgr.c create mode 100644 include/dsp/digital-cdc-rsc-mgr.h diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c index ec2a304034..8546aca4de 100644 --- a/asoc/codecs/bolero/bolero-cdc.c +++ b/asoc/codecs/bolero/bolero-cdc.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "bolero-cdc.h" #include "internal.h" #include "bolero-clk-rsc.h" @@ -1388,7 +1389,7 @@ int bolero_runtime_resume(struct device *dev) } if (priv->core_hw_vote_count == 0) { - ret = clk_prepare_enable(priv->lpass_core_hw_vote); + ret = digital_cdc_rsc_mgr_hw_vote_enable(priv->lpass_core_hw_vote); if (ret < 0) { dev_err(dev, "%s:lpass core hw enable failed\n", __func__); @@ -1406,7 +1407,7 @@ audio_vote: } if (priv->core_audio_vote_count == 0) { - ret = clk_prepare_enable(priv->lpass_audio_hw_vote); + ret = digital_cdc_rsc_mgr_hw_vote_enable(priv->lpass_audio_hw_vote); if (ret < 0) { dev_err(dev, "%s:lpass audio hw enable failed\n", __func__); @@ -1431,7 +1432,8 @@ int bolero_runtime_suspend(struct device *dev) mutex_lock(&priv->vote_lock); if (priv->lpass_core_hw_vote != NULL) { if (--priv->core_hw_vote_count == 0) - clk_disable_unprepare(priv->lpass_core_hw_vote); + digital_cdc_rsc_mgr_hw_vote_disable( + priv->lpass_core_hw_vote); if (priv->core_hw_vote_count < 0) priv->core_hw_vote_count = 0; } else { @@ -1443,7 +1445,8 @@ int bolero_runtime_suspend(struct device *dev) if (priv->lpass_audio_hw_vote != NULL) { if (--priv->core_audio_vote_count == 0) - clk_disable_unprepare(priv->lpass_audio_hw_vote); + digital_cdc_rsc_mgr_hw_vote_disable( + priv->lpass_audio_hw_vote); if (priv->core_audio_vote_count < 0) priv->core_audio_vote_count = 0; } else { diff --git a/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c index a96f14efc1..edef14dc24 100644 --- a/asoc/codecs/bolero/va-macro.c +++ b/asoc/codecs/bolero/va-macro.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "bolero-cdc.h" #include "bolero-cdc-registers.h" #include "bolero-clk-rsc.h" @@ -444,7 +445,8 @@ static int va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: if (va_priv->lpass_audio_hw_vote) { - ret = clk_prepare_enable(va_priv->lpass_audio_hw_vote); + ret = digital_cdc_rsc_mgr_hw_vote_enable( + va_priv->lpass_audio_hw_vote); if (ret) dev_err(va_dev, "%s: lpass audio hw enable failed\n", @@ -467,7 +469,8 @@ static int va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w, if (bolero_tx_clk_switch(component, CLK_SRC_TX_RCG)) dev_dbg(va_dev, "%s: clock switch failed\n",__func__); if (va_priv->lpass_audio_hw_vote) - clk_disable_unprepare(va_priv->lpass_audio_hw_vote); + digital_cdc_rsc_mgr_hw_vote_disable( + va_priv->lpass_audio_hw_vote); break; default: dev_err(va_priv->dev, diff --git a/dsp/Kbuild b/dsp/Kbuild index bafd111adb..f01337cf23 100644 --- a/dsp/Kbuild +++ b/dsp/Kbuild @@ -186,6 +186,10 @@ ifdef CONFIG_VOICE_MHI Q6_OBJS += voice_mhi.o endif +ifdef CONFIG_DIGITAL_CDC_RSC_MGR + Q6_OBJS += digital-cdc-rsc-mgr.o +endif + LINUX_INC += -Iinclude/linux INCS += $(COMMON_INC) \ diff --git a/dsp/digital-cdc-rsc-mgr.c b/dsp/digital-cdc-rsc-mgr.c new file mode 100644 index 0000000000..4206523ea8 --- /dev/null +++ b/dsp/digital-cdc-rsc-mgr.c @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include + +struct mutex hw_vote_lock; +static bool is_init_done; + +/** + * digital_cdc_rsc_mgr_hw_vote_enable - Enables hw vote in DSP + * + * @vote_handle: vote handle for which voting needs to be done + * + * Returns 0 on success or -EINVAL/error code on failure + */ +int digital_cdc_rsc_mgr_hw_vote_enable(struct clk* vote_handle) +{ + int ret = 0; + + if (!is_init_done || vote_handle == NULL) { + pr_err_ratelimited("%s: init failed or vote handle NULL\n", + __func__); + return -EINVAL; + } + + mutex_lock(&hw_vote_lock); + ret = clk_prepare_enable(vote_handle); + mutex_unlock(&hw_vote_lock); + + pr_debug("%s: return %d\n", __func__, ret); + trace_printk("%s: return %d\n", __func__, ret); + return ret; +} +EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_enable); + +/** + * digital_cdc_rsc_mgr_hw_vote_disable - Disables hw vote in DSP + * + * @vote_handle: vote handle for which voting needs to be disabled + * + */ +void digital_cdc_rsc_mgr_hw_vote_disable(struct clk* vote_handle) +{ + if (!is_init_done || vote_handle == NULL) { + pr_err_ratelimited("%s: init failed or vote handle NULL\n", + __func__); + return; + } + + mutex_lock(&hw_vote_lock); + clk_disable_unprepare(vote_handle); + mutex_unlock(&hw_vote_lock); + trace_printk("%s\n", __func__); +} +EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_disable); + +/** + * digital_cdc_rsc_mgr_hw_vote_reset - Resets hw vote count + * + */ +void digital_cdc_rsc_mgr_hw_vote_reset(struct clk* vote_handle) +{ + int count = 0; + + if (!is_init_done || vote_handle == NULL) { + pr_err_ratelimited("%s: init failed or vote handle NULL\n", + __func__); + return; + } + + mutex_lock(&hw_vote_lock); + while (__clk_is_enabled(vote_handle)) { + clk_disable_unprepare(vote_handle); + count++; + } + pr_debug("%s: Vote count after SSR: %d\n", __func__, count); + trace_printk("%s: Vote count after SSR: %d\n", __func__, count); + + while (count--) + clk_prepare_enable(vote_handle); + mutex_unlock(&hw_vote_lock); +} +EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_reset); + +void digital_cdc_rsc_mgr_init() +{ + mutex_init(&hw_vote_lock); + is_init_done = true; +} + +void digital_cdc_rsc_mgr_exit() +{ + mutex_destroy(&hw_vote_lock); + is_init_done = false; +} diff --git a/dsp/q6_init.c b/dsp/q6_init.c index fb18741d38..e990f2a151 100644 --- a/dsp/q6_init.c +++ b/dsp/q6_init.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017, 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017, 2019-2020 The Linux Foundation. All rights reserved. */ #include @@ -24,11 +24,13 @@ static int __init audio_q6_init(void) avtimer_init(); msm_mdf_init(); voice_mhi_init(); + digital_cdc_rsc_mgr_init(); return 0; } static void __exit audio_q6_exit(void) { + digital_cdc_rsc_mgr_exit(); msm_mdf_exit(); avtimer_exit(); audio_slimslave_exit(); diff --git a/dsp/q6_init.h b/dsp/q6_init.h index 57439d16a2..17decdfeb3 100644 --- a/dsp/q6_init.h +++ b/dsp/q6_init.h @@ -94,5 +94,19 @@ static inline void voice_mhi_exit(void) return; } #endif + +#ifdef CONFIG_DIGITAL_CDC_RSC_MGR +void digital_cdc_rsc_mgr_init(void); +void digital_cdc_rsc_mgr_exit(void); +#else +static inline void digital_cdc_rsc_mgr_init(void) +{ +} + +static inline void digital_cdc_rsc_mgr_exit(void) +{ +} +#endif /* CONFIG_DIGITAL_CDC_RSC_MGR */ + #endif diff --git a/include/dsp/digital-cdc-rsc-mgr.h b/include/dsp/digital-cdc-rsc-mgr.h new file mode 100644 index 0000000000..685cd5c1fc --- /dev/null +++ b/include/dsp/digital-cdc-rsc-mgr.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef DIGITAL_CDC_RSC_MGR_H +#define DIGITAL_CDC_RSC_MGR_H + +#ifdef CONFIG_DIGITAL_CDC_RSC_MGR + +int digital_cdc_rsc_mgr_hw_vote_enable(struct clk* vote_handle); +void digital_cdc_rsc_mgr_hw_vote_disable(struct clk* vote_handle); +void digital_cdc_rsc_mgr_hw_vote_reset(struct clk* vote_handle); + +#else + +static inline int digital_cdc_rsc_mgr_hw_vote_enable(struct clk* vote_handle) +{ + return 0; +} + +static inline void digital_cdc_rsc_mgr_hw_vote_disable(struct clk* vote_handle) +{ +} + +static inline void digital_cdc_rsc_mgr_hw_vote_reset(struct clk* vote_handle) +{ +} + +#endif /* CONFIG_DIGITAL_CDC_RSC_MGR */ + +#endif /* DIGITAL_CDC_RSC_MGR_H */ diff --git a/soc/pinctrl-lpi.c b/soc/pinctrl-lpi.c index fdcaeab449..b9699c6a58 100644 --- a/soc/pinctrl-lpi.c +++ b/soc/pinctrl-lpi.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #include @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -469,6 +470,7 @@ static int lpi_notifier_service_cb(struct notifier_block *this, unsigned long opcode, void *ptr) { static bool initial_boot = true; + struct lpi_gpio_state *state = dev_get_drvdata(lpi_dev); pr_debug("%s: Service opcode 0x%lx\n", __func__, opcode); @@ -484,6 +486,17 @@ static int lpi_notifier_service_cb(struct notifier_block *this, case AUDIO_NOTIFIER_SERVICE_UP: if (initial_boot) initial_boot = false; + + /* Reset HW votes after SSR */ + if (!lpi_dev_up) { + if (state->lpass_core_hw_vote) + digital_cdc_rsc_mgr_hw_vote_reset( + state->lpass_core_hw_vote); + if (state->lpass_audio_hw_vote) + digital_cdc_rsc_mgr_hw_vote_reset( + state->lpass_audio_hw_vote); + } + lpi_dev_up = true; snd_event_notify(lpi_dev, SND_EVENT_UP); break; @@ -870,7 +883,7 @@ int lpi_pinctrl_runtime_resume(struct device *dev) } mutex_lock(&state->core_hw_vote_lock); - ret = clk_prepare_enable(hw_vote); + ret = digital_cdc_rsc_mgr_hw_vote_enable(hw_vote); if (ret < 0) { pm_runtime_set_autosuspend_delay(dev, LPI_AUTO_SUSPEND_DELAY_ERROR); @@ -906,7 +919,7 @@ int lpi_pinctrl_runtime_suspend(struct device *dev) mutex_lock(&state->core_hw_vote_lock); if (state->core_hw_vote_status) { - clk_disable_unprepare(hw_vote); + digital_cdc_rsc_mgr_hw_vote_disable(hw_vote); state->core_hw_vote_status = false; } mutex_unlock(&state->core_hw_vote_lock); diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index 2762d08b29..5a4238ac97 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -24,6 +24,7 @@ #include #include "swr-mstr-registers.h" #include "swr-slave-registers.h" +#include #include "swr-mstr-ctrl.h" #define SWR_NUM_PORTS 4 /* TODO - Get this info from DT */ @@ -403,8 +404,8 @@ static int swrm_request_hw_vote(struct swr_mstr_ctrl *swrm, } if (++swrm->hw_core_clk_en == 1) { ret = - clk_prepare_enable( - swrm->lpass_core_hw_vote); + digital_cdc_rsc_mgr_hw_vote_enable( + swrm->lpass_core_hw_vote); if (ret < 0) { dev_err(swrm->dev, "%s:lpass core hw enable failed\n", @@ -417,8 +418,8 @@ static int swrm_request_hw_vote(struct swr_mstr_ctrl *swrm, if (swrm->hw_core_clk_en < 0) swrm->hw_core_clk_en = 0; else if (swrm->hw_core_clk_en == 0) - clk_disable_unprepare( - swrm->lpass_core_hw_vote); + digital_cdc_rsc_mgr_hw_vote_disable( + swrm->lpass_core_hw_vote); } } } @@ -435,8 +436,8 @@ static int swrm_request_hw_vote(struct swr_mstr_ctrl *swrm, } if (++swrm->aud_core_clk_en == 1) { ret = - clk_prepare_enable( - swrm->lpass_core_audio); + digital_cdc_rsc_mgr_hw_vote_enable( + swrm->lpass_core_audio); if (ret < 0) { dev_err(swrm->dev, "%s:lpass audio hw enable failed\n", @@ -449,8 +450,8 @@ static int swrm_request_hw_vote(struct swr_mstr_ctrl *swrm, if (swrm->aud_core_clk_en < 0) swrm->aud_core_clk_en = 0; else if (swrm->aud_core_clk_en == 0) - clk_disable_unprepare( - swrm->lpass_core_audio); + digital_cdc_rsc_mgr_hw_vote_disable( + swrm->lpass_core_audio); } } } @@ -3235,6 +3236,8 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data) swrm_device_down(&pdev->dev); mutex_lock(&swrm->devlock); swrm->dev_up = false; + swrm->hw_core_clk_en = 0; + swrm->aud_core_clk_en = 0; mutex_unlock(&swrm->devlock); mutex_lock(&swrm->reslock); swrm->state = SWR_MSTR_SSR; From 30fad2dc200153ade17ccb17301f2c4d42adb1ac Mon Sep 17 00:00:00 2001 From: Meng Wang Date: Mon, 27 Apr 2020 09:18:27 +0800 Subject: [PATCH 021/116] asoc: codec: update SOC_SINGLE_SX_TLV to SOC_SINGLE_S8_TLV Update SOC_SINGLE_SX_TLV to SOC_SINGLE_S8_TLV to make codec driver compatiable with upstream driver. Change-Id: I4061b015d715978f3b294ad630f53b64bf66c2b7 Signed-off-by: Meng Wang --- asoc/codecs/bolero/rx-macro.c | 59 ++++++++-------- asoc/codecs/bolero/tx-macro.c | 64 ++++++++--------- asoc/codecs/bolero/va-macro.c | 48 ++++++------- asoc/codecs/bolero/wsa-macro.c | 8 +-- asoc/codecs/wcd9335.c | 122 ++++++++++++++++----------------- asoc/codecs/wcd934x/wcd934x.c | 106 ++++++++++++++-------------- 6 files changed, 205 insertions(+), 202 deletions(-) diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c index 62da031f26..ce86f15506 100644 --- a/asoc/codecs/bolero/rx-macro.c +++ b/asoc/codecs/bolero/rx-macro.c @@ -2988,21 +2988,24 @@ static int rx_macro_set_iir_gain(struct snd_soc_dapm_widget *w, } static const struct snd_kcontrol_new rx_macro_snd_controls[] = { - SOC_SINGLE_SX_TLV("RX_RX0 Digital Volume", + SOC_SINGLE_S8_TLV("RX_RX0 Digital Volume", BOLERO_CDC_RX_RX0_RX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX_RX1 Digital Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX_RX1 Digital Volume", BOLERO_CDC_RX_RX1_RX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX_RX2 Digital Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX_RX2 Digital Volume", BOLERO_CDC_RX_RX2_RX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX_RX0 Mix Digital Volume", - BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX_RX1 Mix Digital Volume", - BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX_RX2 Mix Digital Volume", - BOLERO_CDC_RX_RX2_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain), + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX_RX0 Mix Digital Volume", + BOLERO_CDC_RX_RX0_RX_VOL_MIX_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX_RX1 Mix Digital Volume", + BOLERO_CDC_RX_RX1_RX_VOL_MIX_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX_RX2 Mix Digital Volume", + BOLERO_CDC_RX_RX2_RX_VOL_MIX_CTL, + -84, 40, digital_gain), SOC_SINGLE_EXT("RX_COMP1 Switch", SND_SOC_NOPM, RX_MACRO_COMP1, 1, 0, rx_macro_get_compander, rx_macro_set_compander), @@ -3031,29 +3034,29 @@ static const struct snd_kcontrol_new rx_macro_snd_controls[] = { rx_macro_aux_hpf_mode_get, rx_macro_aux_hpf_mode_put), - SOC_SINGLE_SX_TLV("IIR0 INP0 Volume", - BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL, 0, -84, 40, + SOC_SINGLE_S8_TLV("IIR0 INP0 Volume", + BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B1_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR0 INP1 Volume", - BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL, 0, -84, 40, + SOC_SINGLE_S8_TLV("IIR0 INP1 Volume", + BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B2_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR0 INP2 Volume", - BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL, 0, -84, 40, + SOC_SINGLE_S8_TLV("IIR0 INP2 Volume", + BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B3_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR0 INP3 Volume", - BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL, 0, -84, 40, + SOC_SINGLE_S8_TLV("IIR0 INP3 Volume", + BOLERO_CDC_RX_SIDETONE_IIR0_IIR_GAIN_B4_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR1 INP0 Volume", - BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL, 0, -84, 40, + SOC_SINGLE_S8_TLV("IIR1 INP0 Volume", + BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B1_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR1 INP1 Volume", - BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL, 0, -84, 40, + SOC_SINGLE_S8_TLV("IIR1 INP1 Volume", + BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B2_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR1 INP2 Volume", - BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL, 0, -84, 40, + SOC_SINGLE_S8_TLV("IIR1 INP2 Volume", + BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B3_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR1 INP3 Volume", - BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL, 0, -84, 40, + SOC_SINGLE_S8_TLV("IIR1 INP3 Volume", + BOLERO_CDC_RX_SIDETONE_IIR1_IIR_GAIN_B4_CTL, -84, 40, digital_gain), SOC_SINGLE_EXT("IIR0 Enable Band1", IIR0, BAND1, 1, 0, diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c index 2539577678..1178df6c23 100644 --- a/asoc/codecs/bolero/tx-macro.c +++ b/asoc/codecs/bolero/tx-macro.c @@ -2362,18 +2362,18 @@ static const struct snd_soc_dapm_route tx_audio_map[] = { }; static const struct snd_kcontrol_new tx_macro_snd_controls_common[] = { - SOC_SINGLE_SX_TLV("TX_DEC0 Volume", + SOC_SINGLE_S8_TLV("TX_DEC0 Volume", BOLERO_CDC_TX0_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("TX_DEC1 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC1 Volume", BOLERO_CDC_TX1_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("TX_DEC2 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC2 Volume", BOLERO_CDC_TX2_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("TX_DEC3 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC3 Volume", BOLERO_CDC_TX3_TX_VOL_CTL, - 0, -84, 40, digital_gain), + -84, 40, digital_gain), SOC_ENUM_EXT("DEC0 MODE", dec_mode_mux_enum, tx_macro_dec_mode_get, tx_macro_dec_mode_put), @@ -2398,18 +2398,18 @@ static const struct snd_kcontrol_new tx_macro_snd_controls_common[] = { }; static const struct snd_kcontrol_new tx_macro_snd_controls_v3[] = { - SOC_SINGLE_SX_TLV("TX_DEC4 Volume", + SOC_SINGLE_S8_TLV("TX_DEC4 Volume", BOLERO_CDC_TX4_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("TX_DEC5 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC5 Volume", BOLERO_CDC_TX5_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("TX_DEC6 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC6 Volume", BOLERO_CDC_TX6_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("TX_DEC7 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC7 Volume", BOLERO_CDC_TX7_TX_VOL_CTL, - 0, -84, 40, digital_gain), + -84, 40, digital_gain), SOC_ENUM_EXT("DEC4 MODE", dec_mode_mux_enum, tx_macro_dec_mode_get, tx_macro_dec_mode_put), @@ -2425,30 +2425,30 @@ static const struct snd_kcontrol_new tx_macro_snd_controls_v3[] = { }; static const struct snd_kcontrol_new tx_macro_snd_controls[] = { - SOC_SINGLE_SX_TLV("TX_DEC0 Volume", + SOC_SINGLE_S8_TLV("TX_DEC0 Volume", BOLERO_CDC_TX0_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("TX_DEC1 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC1 Volume", BOLERO_CDC_TX1_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("TX_DEC2 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC2 Volume", BOLERO_CDC_TX2_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("TX_DEC3 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC3 Volume", BOLERO_CDC_TX3_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("TX_DEC4 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC4 Volume", BOLERO_CDC_TX4_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("TX_DEC5 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC5 Volume", BOLERO_CDC_TX5_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("TX_DEC6 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC6 Volume", BOLERO_CDC_TX6_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("TX_DEC7 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("TX_DEC7 Volume", BOLERO_CDC_TX7_TX_VOL_CTL, - 0, -84, 40, digital_gain), + -84, 40, digital_gain), SOC_ENUM_EXT("DEC0 MODE", dec_mode_mux_enum, tx_macro_dec_mode_get, tx_macro_dec_mode_put), diff --git a/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c index a96f14efc1..e83e1139ea 100644 --- a/asoc/codecs/bolero/va-macro.c +++ b/asoc/codecs/bolero/va-macro.c @@ -2533,30 +2533,30 @@ static const struct soc_enum dec_mode_mux_enum = dec_mode_mux_text); static const struct snd_kcontrol_new va_macro_snd_controls[] = { - SOC_SINGLE_SX_TLV("VA_DEC0 Volume", + SOC_SINGLE_S8_TLV("VA_DEC0 Volume", BOLERO_CDC_VA_TX0_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("VA_DEC1 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("VA_DEC1 Volume", BOLERO_CDC_VA_TX1_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("VA_DEC2 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("VA_DEC2 Volume", BOLERO_CDC_VA_TX2_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("VA_DEC3 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("VA_DEC3 Volume", BOLERO_CDC_VA_TX3_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("VA_DEC4 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("VA_DEC4 Volume", BOLERO_CDC_VA_TX4_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("VA_DEC5 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("VA_DEC5 Volume", BOLERO_CDC_VA_TX5_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("VA_DEC6 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("VA_DEC6 Volume", BOLERO_CDC_VA_TX6_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("VA_DEC7 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("VA_DEC7 Volume", BOLERO_CDC_VA_TX7_TX_VOL_CTL, - 0, -84, 40, digital_gain), + -84, 40, digital_gain), SOC_SINGLE_EXT("LPI Enable", 0, 0, 1, 0, va_macro_lpi_get, va_macro_lpi_put), @@ -2574,23 +2574,23 @@ static const struct snd_kcontrol_new va_macro_snd_controls[] = { }; static const struct snd_kcontrol_new va_macro_snd_controls_common[] = { - SOC_SINGLE_SX_TLV("VA_DEC0 Volume", + SOC_SINGLE_S8_TLV("VA_DEC0 Volume", BOLERO_CDC_VA_TX0_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("VA_DEC1 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("VA_DEC1 Volume", BOLERO_CDC_VA_TX1_TX_VOL_CTL, - 0, -84, 40, digital_gain), + -84, 40, digital_gain), SOC_SINGLE_EXT("LPI Enable", 0, 0, 1, 0, va_macro_lpi_get, va_macro_lpi_put), }; static const struct snd_kcontrol_new va_macro_snd_controls_v3[] = { - SOC_SINGLE_SX_TLV("VA_DEC2 Volume", + SOC_SINGLE_S8_TLV("VA_DEC2 Volume", BOLERO_CDC_VA_TX2_TX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("VA_DEC3 Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("VA_DEC3 Volume", BOLERO_CDC_VA_TX3_TX_VOL_CTL, - 0, -84, 40, digital_gain), + -84, 40, digital_gain), }; static int va_macro_validate_dmic_sample_rate(u32 dmic_sample_rate, diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c index 7579957aa4..024b303263 100644 --- a/asoc/codecs/bolero/wsa-macro.c +++ b/asoc/codecs/bolero/wsa-macro.c @@ -2370,12 +2370,12 @@ static const struct snd_kcontrol_new wsa_macro_snd_controls[] = { WSA_MACRO_SOFTCLIP1, 1, 0, wsa_macro_soft_clip_enable_get, wsa_macro_soft_clip_enable_put), - SOC_SINGLE_SX_TLV("WSA_RX0 Digital Volume", + SOC_SINGLE_S8_TLV("WSA_RX0 Digital Volume", BOLERO_CDC_WSA_RX0_RX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("WSA_RX1 Digital Volume", + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("WSA_RX1 Digital Volume", BOLERO_CDC_WSA_RX1_RX_VOL_CTL, - 0, -84, 40, digital_gain), + -84, 40, digital_gain), SOC_SINGLE_EXT("WSA_RX0 Digital Mute", SND_SOC_NOPM, WSA_MACRO_RX0, 1, 0, wsa_macro_get_rx_mute_status, wsa_macro_set_rx_mute_status), diff --git a/asoc/codecs/wcd9335.c b/asoc/codecs/wcd9335.c index 054a56dc3c..cfe328ba8b 100644 --- a/asoc/codecs/wcd9335.c +++ b/asoc/codecs/wcd9335.c @@ -8608,95 +8608,95 @@ static const struct soc_enum amic_pwr_lvl_enum = amic_pwr_lvl_text); static const struct snd_kcontrol_new tasha_snd_controls[] = { - SOC_SINGLE_SX_TLV("RX0 Digital Volume", WCD9335_CDC_RX0_RX_VOL_CTL, - 0, -84, 40, digital_gain), /* -84dB min - 40dB max */ - SOC_SINGLE_SX_TLV("RX1 Digital Volume", WCD9335_CDC_RX1_RX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX2 Digital Volume", WCD9335_CDC_RX2_RX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX3 Digital Volume", WCD9335_CDC_RX3_RX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX4 Digital Volume", WCD9335_CDC_RX4_RX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX5 Digital Volume", WCD9335_CDC_RX5_RX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX6 Digital Volume", WCD9335_CDC_RX6_RX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX7 Digital Volume", WCD9335_CDC_RX7_RX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX8 Digital Volume", WCD9335_CDC_RX8_RX_VOL_CTL, - 0, -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX0 Digital Volume", WCD9335_CDC_RX0_RX_VOL_CTL, + -84, 40, digital_gain), /* -84dB min - 40dB max */ + SOC_SINGLE_S8_TLV("RX1 Digital Volume", WCD9335_CDC_RX1_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX2 Digital Volume", WCD9335_CDC_RX2_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX3 Digital Volume", WCD9335_CDC_RX3_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX4 Digital Volume", WCD9335_CDC_RX4_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX5 Digital Volume", WCD9335_CDC_RX5_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX6 Digital Volume", WCD9335_CDC_RX6_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX7 Digital Volume", WCD9335_CDC_RX7_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX8 Digital Volume", WCD9335_CDC_RX8_RX_VOL_CTL, + -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX0 Mix Digital Volume", + SOC_SINGLE_S8_TLV("RX0 Mix Digital Volume", WCD9335_CDC_RX0_RX_VOL_MIX_CTL, - 0, -84, 40, digital_gain), /* -84dB min - 40dB max */ - SOC_SINGLE_SX_TLV("RX1 Mix Digital Volume", + -84, 40, digital_gain), /* -84dB min - 40dB max */ + SOC_SINGLE_S8_TLV("RX1 Mix Digital Volume", WCD9335_CDC_RX1_RX_VOL_MIX_CTL, - 0, -84, 40, digital_gain), /* -84dB min - 40dB max */ - SOC_SINGLE_SX_TLV("RX2 Mix Digital Volume", + -84, 40, digital_gain), /* -84dB min - 40dB max */ + SOC_SINGLE_S8_TLV("RX2 Mix Digital Volume", WCD9335_CDC_RX2_RX_VOL_MIX_CTL, - 0, -84, 40, digital_gain), /* -84dB min - 40dB max */ - SOC_SINGLE_SX_TLV("RX3 Mix Digital Volume", + -84, 40, digital_gain), /* -84dB min - 40dB max */ + SOC_SINGLE_S8_TLV("RX3 Mix Digital Volume", WCD9335_CDC_RX3_RX_VOL_MIX_CTL, - 0, -84, 40, digital_gain), /* -84dB min - 40dB max */ - SOC_SINGLE_SX_TLV("RX4 Mix Digital Volume", + -84, 40, digital_gain), /* -84dB min - 40dB max */ + SOC_SINGLE_S8_TLV("RX4 Mix Digital Volume", WCD9335_CDC_RX4_RX_VOL_MIX_CTL, - 0, -84, 40, digital_gain), /* -84dB min - 40dB max */ - SOC_SINGLE_SX_TLV("RX5 Mix Digital Volume", + -84, 40, digital_gain), /* -84dB min - 40dB max */ + SOC_SINGLE_S8_TLV("RX5 Mix Digital Volume", WCD9335_CDC_RX5_RX_VOL_MIX_CTL, - 0, -84, 40, digital_gain), /* -84dB min - 40dB max */ - SOC_SINGLE_SX_TLV("RX6 Mix Digital Volume", + -84, 40, digital_gain), /* -84dB min - 40dB max */ + SOC_SINGLE_S8_TLV("RX6 Mix Digital Volume", WCD9335_CDC_RX6_RX_VOL_MIX_CTL, - 0, -84, 40, digital_gain), /* -84dB min - 40dB max */ - SOC_SINGLE_SX_TLV("RX7 Mix Digital Volume", + -84, 40, digital_gain), /* -84dB min - 40dB max */ + SOC_SINGLE_S8_TLV("RX7 Mix Digital Volume", WCD9335_CDC_RX7_RX_VOL_MIX_CTL, - 0, -84, 40, digital_gain), /* -84dB min - 40dB max */ - SOC_SINGLE_SX_TLV("RX8 Mix Digital Volume", + -84, 40, digital_gain), /* -84dB min - 40dB max */ + SOC_SINGLE_S8_TLV("RX8 Mix Digital Volume", WCD9335_CDC_RX8_RX_VOL_MIX_CTL, - 0, -84, 40, digital_gain), /* -84dB min - 40dB max */ + -84, 40, digital_gain), /* -84dB min - 40dB max */ - SOC_SINGLE_SX_TLV("DEC0 Volume", WCD9335_CDC_TX0_TX_VOL_CTL, 0, + SOC_SINGLE_S8_TLV("DEC0 Volume", WCD9335_CDC_TX0_TX_VOL_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("DEC1 Volume", WCD9335_CDC_TX1_TX_VOL_CTL, 0, + SOC_SINGLE_S8_TLV("DEC1 Volume", WCD9335_CDC_TX1_TX_VOL_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("DEC2 Volume", WCD9335_CDC_TX2_TX_VOL_CTL, 0, + SOC_SINGLE_S8_TLV("DEC2 Volume", WCD9335_CDC_TX2_TX_VOL_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("DEC3 Volume", WCD9335_CDC_TX3_TX_VOL_CTL, 0, + SOC_SINGLE_S8_TLV("DEC3 Volume", WCD9335_CDC_TX3_TX_VOL_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("DEC4 Volume", WCD9335_CDC_TX4_TX_VOL_CTL, 0, + SOC_SINGLE_S8_TLV("DEC4 Volume", WCD9335_CDC_TX4_TX_VOL_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("DEC5 Volume", WCD9335_CDC_TX5_TX_VOL_CTL, 0, + SOC_SINGLE_S8_TLV("DEC5 Volume", WCD9335_CDC_TX5_TX_VOL_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("DEC6 Volume", WCD9335_CDC_TX6_TX_VOL_CTL, 0, + SOC_SINGLE_S8_TLV("DEC6 Volume", WCD9335_CDC_TX6_TX_VOL_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("DEC7 Volume", WCD9335_CDC_TX7_TX_VOL_CTL, 0, + SOC_SINGLE_S8_TLV("DEC7 Volume", WCD9335_CDC_TX7_TX_VOL_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("DEC8 Volume", WCD9335_CDC_TX8_TX_VOL_CTL, 0, + SOC_SINGLE_S8_TLV("DEC8 Volume", WCD9335_CDC_TX8_TX_VOL_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR0 INP0 Volume", - WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL, 0, -84, + SOC_SINGLE_S8_TLV("IIR0 INP0 Volume", + WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR0 INP1 Volume", - WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL, 0, -84, + SOC_SINGLE_S8_TLV("IIR0 INP1 Volume", + WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR0 INP2 Volume", - WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL, 0, -84, + SOC_SINGLE_S8_TLV("IIR0 INP2 Volume", + WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR0 INP3 Volume", - WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL, 0, -84, + SOC_SINGLE_S8_TLV("IIR0 INP3 Volume", + WCD9335_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR1 INP0 Volume", - WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL, 0, -84, + SOC_SINGLE_S8_TLV("IIR1 INP0 Volume", + WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR1 INP1 Volume", - WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL, 0, -84, + SOC_SINGLE_S8_TLV("IIR1 INP1 Volume", + WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR1 INP2 Volume", - WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL, 0, -84, + SOC_SINGLE_S8_TLV("IIR1 INP2 Volume", + WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR1 INP3 Volume", - WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B4_CTL, 0, -84, + SOC_SINGLE_S8_TLV("IIR1 INP3 Volume", + WCD9335_CDC_SIDETONE_IIR1_IIR_GAIN_B4_CTL, -84, 40, digital_gain), SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, tasha_get_anc_slot, diff --git a/asoc/codecs/wcd934x/wcd934x.c b/asoc/codecs/wcd934x/wcd934x.c index 4fa5c3414c..3d7d39bb28 100644 --- a/asoc/codecs/wcd934x/wcd934x.c +++ b/asoc/codecs/wcd934x/wcd934x.c @@ -6548,77 +6548,77 @@ static const struct snd_kcontrol_new tavil_snd_controls[] = { SOC_SINGLE_TLV("ADC3 Volume", WCD934X_ANA_AMIC3, 0, 20, 0, analog_gain), SOC_SINGLE_TLV("ADC4 Volume", WCD934X_ANA_AMIC4, 0, 20, 0, analog_gain), - SOC_SINGLE_SX_TLV("RX0 Digital Volume", WCD934X_CDC_RX0_RX_VOL_CTL, - 0, -84, 40, digital_gain), /* -84dB min - 40dB max */ - SOC_SINGLE_SX_TLV("RX1 Digital Volume", WCD934X_CDC_RX1_RX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX2 Digital Volume", WCD934X_CDC_RX2_RX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX3 Digital Volume", WCD934X_CDC_RX3_RX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX4 Digital Volume", WCD934X_CDC_RX4_RX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX7 Digital Volume", WCD934X_CDC_RX7_RX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX8 Digital Volume", WCD934X_CDC_RX8_RX_VOL_CTL, - 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX0 Mix Digital Volume", - WCD934X_CDC_RX0_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX1 Mix Digital Volume", - WCD934X_CDC_RX1_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX2 Mix Digital Volume", - WCD934X_CDC_RX2_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX3 Mix Digital Volume", - WCD934X_CDC_RX3_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX4 Mix Digital Volume", - WCD934X_CDC_RX4_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX7 Mix Digital Volume", - WCD934X_CDC_RX7_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("RX8 Mix Digital Volume", - WCD934X_CDC_RX8_RX_VOL_MIX_CTL, 0, -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX0 Digital Volume", WCD934X_CDC_RX0_RX_VOL_CTL, + -84, 40, digital_gain), /* -84dB min - 40dB max */ + SOC_SINGLE_S8_TLV("RX1 Digital Volume", WCD934X_CDC_RX1_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX2 Digital Volume", WCD934X_CDC_RX2_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX3 Digital Volume", WCD934X_CDC_RX3_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX4 Digital Volume", WCD934X_CDC_RX4_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX7 Digital Volume", WCD934X_CDC_RX7_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX8 Digital Volume", WCD934X_CDC_RX8_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX0 Mix Digital Volume", + WCD934X_CDC_RX0_RX_VOL_MIX_CTL, -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX1 Mix Digital Volume", + WCD934X_CDC_RX1_RX_VOL_MIX_CTL, -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX2 Mix Digital Volume", + WCD934X_CDC_RX2_RX_VOL_MIX_CTL, -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX3 Mix Digital Volume", + WCD934X_CDC_RX3_RX_VOL_MIX_CTL, -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX4 Mix Digital Volume", + WCD934X_CDC_RX4_RX_VOL_MIX_CTL, -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX7 Mix Digital Volume", + WCD934X_CDC_RX7_RX_VOL_MIX_CTL, -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX8 Mix Digital Volume", + WCD934X_CDC_RX8_RX_VOL_MIX_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("DEC0 Volume", WCD934X_CDC_TX0_TX_VOL_CTL, 0, + SOC_SINGLE_S8_TLV("DEC0 Volume", WCD934X_CDC_TX0_TX_VOL_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("DEC1 Volume", WCD934X_CDC_TX1_TX_VOL_CTL, 0, + SOC_SINGLE_S8_TLV("DEC1 Volume", WCD934X_CDC_TX1_TX_VOL_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("DEC2 Volume", WCD934X_CDC_TX2_TX_VOL_CTL, 0, + SOC_SINGLE_S8_TLV("DEC2 Volume", WCD934X_CDC_TX2_TX_VOL_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("DEC3 Volume", WCD934X_CDC_TX3_TX_VOL_CTL, 0, + SOC_SINGLE_S8_TLV("DEC3 Volume", WCD934X_CDC_TX3_TX_VOL_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("DEC4 Volume", WCD934X_CDC_TX4_TX_VOL_CTL, 0, + SOC_SINGLE_S8_TLV("DEC4 Volume", WCD934X_CDC_TX4_TX_VOL_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("DEC5 Volume", WCD934X_CDC_TX5_TX_VOL_CTL, 0, + SOC_SINGLE_S8_TLV("DEC5 Volume", WCD934X_CDC_TX5_TX_VOL_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("DEC6 Volume", WCD934X_CDC_TX6_TX_VOL_CTL, 0, + SOC_SINGLE_S8_TLV("DEC6 Volume", WCD934X_CDC_TX6_TX_VOL_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("DEC7 Volume", WCD934X_CDC_TX7_TX_VOL_CTL, 0, + SOC_SINGLE_S8_TLV("DEC7 Volume", WCD934X_CDC_TX7_TX_VOL_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("DEC8 Volume", WCD934X_CDC_TX8_TX_VOL_CTL, 0, + SOC_SINGLE_S8_TLV("DEC8 Volume", WCD934X_CDC_TX8_TX_VOL_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR0 INP0 Volume", - WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL, 0, -84, 40, + SOC_SINGLE_S8_TLV("IIR0 INP0 Volume", + WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR0 INP1 Volume", - WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL, 0, -84, 40, + SOC_SINGLE_S8_TLV("IIR0 INP1 Volume", + WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B2_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR0 INP2 Volume", - WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL, 0, -84, 40, + SOC_SINGLE_S8_TLV("IIR0 INP2 Volume", + WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B3_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR0 INP3 Volume", - WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL, 0, -84, 40, + SOC_SINGLE_S8_TLV("IIR0 INP3 Volume", + WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B4_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR1 INP0 Volume", - WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL, 0, -84, 40, + SOC_SINGLE_S8_TLV("IIR1 INP0 Volume", + WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR1 INP1 Volume", - WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL, 0, -84, 40, + SOC_SINGLE_S8_TLV("IIR1 INP1 Volume", + WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B2_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR1 INP2 Volume", - WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL, 0, -84, 40, + SOC_SINGLE_S8_TLV("IIR1 INP2 Volume", + WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B3_CTL, -84, 40, digital_gain), - SOC_SINGLE_SX_TLV("IIR1 INP3 Volume", - WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B4_CTL, 0, -84, 40, + SOC_SINGLE_S8_TLV("IIR1 INP3 Volume", + WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B4_CTL, -84, 40, digital_gain), SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, tavil_get_anc_slot, From 6d071a4372abad04f5becd1a613d511580b166f7 Mon Sep 17 00:00:00 2001 From: "Vangala, Amarnath" Date: Wed, 13 May 2020 23:11:14 +0530 Subject: [PATCH 022/116] ASOC: SPV4 set correct number of speakers. Set correct number of speakers for Speaker Protection V4. Change-Id: I66c656174bef64d3cdd64b17d994073e9ee58472 Signed-off-by: Vangala, Amarnath --- dsp/q6afe.c | 89 +++++++++++++++++++++++++---------------------------- 1 file changed, 42 insertions(+), 47 deletions(-) diff --git a/dsp/q6afe.c b/dsp/q6afe.c index 13379ce1c5..4f4e50e1a1 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -182,6 +182,7 @@ struct afe_ctl { /* FTM spk params */ uint32_t initial_cal; uint32_t v_vali_flag; + uint32_t num_spkrs; }; static atomic_t afe_ports_mad_type[SLIMBUS_PORT_LAST - SLIMBUS_0_RX]; @@ -2121,6 +2122,7 @@ static void afe_send_cal_spv4_tx(int port_id) struct afe_sp_v4_channel_v_vali_cfg *ch_v_vali_cfg = NULL; struct afe_sp_v4_param_ex_vi_ftm_cfg *ex_vi_ftm_cfg = NULL; struct afe_sp_v4_channel_ex_vi_ftm *ch_ex_vi_ftm_cfg = NULL; + uint32_t i = 0; pr_debug("%s: Entry.. port_id %d\n", __func__, port_id); @@ -2181,7 +2183,7 @@ static void afe_send_cal_spv4_tx(int port_id) v4_vi_op_mode->th_r0t0_selection_flag[SP_V2_SPKR_2] = USE_SAFE_R0TO; } - afe_spk_config.v4_vi_op_mode.num_speakers = SP_V2_NUM_MAX_SPKRS; + afe_spk_config.v4_vi_op_mode.num_speakers = this_afe.num_spkrs; if (afe_spk_prot_prepare(port_id, 0, AFE_PARAM_ID_SP_V4_VI_OP_MODE_CFG, &afe_spk_config, @@ -2190,7 +2192,7 @@ static void afe_send_cal_spv4_tx(int port_id) __func__); size = sizeof(struct afe_sp_v4_param_th_vi_r0t0_cfg) + - (SP_V2_NUM_MAX_SPKRS * sizeof(struct afe_sp_v4_channel_r0t0)); + (this_afe.num_spkrs * sizeof(struct afe_sp_v4_channel_r0t0)); tmp_ptr = kzalloc(size, GFP_KERNEL); if (!tmp_ptr) { mutex_unlock( @@ -2204,15 +2206,13 @@ static void afe_send_cal_spv4_tx(int port_id) ch_r0t0_cfg = (struct afe_sp_v4_channel_r0t0 *)(th_vi_r0t0_cfg + 1); - th_vi_r0t0_cfg->num_speakers = SP_V2_NUM_MAX_SPKRS; - ch_r0t0_cfg[SP_V2_SPKR_1].r0_cali_q24 = - (uint32_t) this_afe.prot_cfg.r0[SP_V2_SPKR_1]; - ch_r0t0_cfg[SP_V2_SPKR_2].r0_cali_q24 = - (uint32_t) this_afe.prot_cfg.r0[SP_V2_SPKR_2]; - ch_r0t0_cfg[SP_V2_SPKR_1].t0_cali_q6 = - (uint32_t) this_afe.prot_cfg.t0[SP_V2_SPKR_1]; - ch_r0t0_cfg[SP_V2_SPKR_2].t0_cali_q6 = - (uint32_t) this_afe.prot_cfg.t0[SP_V2_SPKR_2]; + th_vi_r0t0_cfg->num_speakers = this_afe.num_spkrs; + for (i = 0; i < this_afe.num_spkrs; i++) { + ch_r0t0_cfg[i].r0_cali_q24 = + (uint32_t) this_afe.prot_cfg.r0[i]; + ch_r0t0_cfg[i].t0_cali_q6 = + (uint32_t) this_afe.prot_cfg.t0[i]; + } if (afe_spk_prot_prepare(port_id, 0, AFE_PARAM_ID_SP_V4_VI_R0T0_CFG, (union afe_spkr_prot_config *)tmp_ptr, size)) @@ -2227,7 +2227,7 @@ static void afe_send_cal_spv4_tx(int port_id) (this_afe.vi_tx_port == port_id) && (this_afe.prot_cfg.sp_version >= AFE_API_VERSION_V9)) { size = sizeof(struct afe_sp_v4_param_th_vi_ftm_cfg) + - (SP_V2_NUM_MAX_SPKRS*sizeof(struct afe_sp_v4_channel_ftm_cfg)); + (this_afe.num_spkrs * sizeof(struct afe_sp_v4_channel_ftm_cfg)); tmp_ptr = kzalloc(size, GFP_KERNEL); if (!tmp_ptr) { mutex_unlock( @@ -2240,16 +2240,13 @@ static void afe_send_cal_spv4_tx(int port_id) ch_ftm_cfg = (struct afe_sp_v4_channel_ftm_cfg *)(th_vi_ftm_cfg+1); - th_vi_ftm_cfg->num_ch = SP_V2_NUM_MAX_SPKRS; - ch_ftm_cfg[SP_V2_SPKR_1].wait_time_ms = - this_afe.th_ftm_cfg.wait_time[SP_V2_SPKR_1]; - ch_ftm_cfg[SP_V2_SPKR_2].wait_time_ms = - this_afe.th_ftm_cfg.wait_time[SP_V2_SPKR_2]; - ch_ftm_cfg[SP_V2_SPKR_1].ftm_time_ms = - this_afe.th_ftm_cfg.ftm_time[SP_V2_SPKR_1]; - ch_ftm_cfg[SP_V2_SPKR_2].ftm_time_ms = - this_afe.th_ftm_cfg.ftm_time[SP_V2_SPKR_2]; - + th_vi_ftm_cfg->num_ch = this_afe.num_spkrs; + for (i = 0; i < this_afe.num_spkrs; i++) { + ch_ftm_cfg[i].wait_time_ms = + this_afe.th_ftm_cfg.wait_time[i]; + ch_ftm_cfg[i].ftm_time_ms = + this_afe.th_ftm_cfg.ftm_time[i]; + } if (afe_spk_prot_prepare(port_id, 0, AFE_PARAM_ID_SP_V4_TH_VI_FTM_CFG, (union afe_spkr_prot_config *)tmp_ptr, size)) @@ -2261,8 +2258,8 @@ static void afe_send_cal_spv4_tx(int port_id) MSM_SPKR_PROT_IN_V_VALI_MODE) && (this_afe.vi_tx_port == port_id)) { size = sizeof(struct afe_sp_v4_param_th_vi_v_vali_cfg) + - (SP_V2_NUM_MAX_SPKRS * - sizeof(struct afe_sp_v4_channel_v_vali_cfg)); + (this_afe.num_spkrs * + sizeof(struct afe_sp_v4_channel_v_vali_cfg)); tmp_ptr = kzalloc(size, GFP_KERNEL); if (!tmp_ptr) { mutex_unlock( @@ -2276,16 +2273,13 @@ static void afe_send_cal_spv4_tx(int port_id) ch_v_vali_cfg = (struct afe_sp_v4_channel_v_vali_cfg *)(th_vi_v_vali_cfg + 1); - th_vi_v_vali_cfg->num_ch = SP_V2_NUM_MAX_SPKRS; - ch_v_vali_cfg[SP_V2_SPKR_1].wait_time_ms = - this_afe.v_vali_cfg.wait_time[SP_V2_SPKR_1]; - ch_v_vali_cfg[SP_V2_SPKR_2].wait_time_ms = - this_afe.v_vali_cfg.wait_time[SP_V2_SPKR_2]; - ch_v_vali_cfg[SP_V2_SPKR_1].vali_time_ms = - this_afe.v_vali_cfg.vali_time[SP_V2_SPKR_1]; - ch_v_vali_cfg[SP_V2_SPKR_2].vali_time_ms = - this_afe.v_vali_cfg.vali_time[SP_V2_SPKR_2]; - + th_vi_v_vali_cfg->num_ch = this_afe.num_spkrs; + for (i = 0; i < this_afe.num_spkrs; i++) { + ch_v_vali_cfg[i].wait_time_ms = + this_afe.v_vali_cfg.wait_time[i]; + ch_v_vali_cfg[i].vali_time_ms = + this_afe.v_vali_cfg.vali_time[i]; + } if (afe_spk_prot_prepare(port_id, 0, AFE_PARAM_ID_SP_V4_TH_VI_V_VALI_CFG, (union afe_spkr_prot_config *)tmp_ptr, size)) @@ -2301,7 +2295,7 @@ static void afe_send_cal_spv4_tx(int port_id) (this_afe.vi_tx_port == port_id) && (this_afe.prot_cfg.sp_version >= AFE_API_VERSION_V9)) { size = sizeof(struct afe_sp_v4_param_ex_vi_ftm_cfg) + - (SP_V2_NUM_MAX_SPKRS * + (this_afe.num_spkrs * sizeof(struct afe_sp_v4_channel_ex_vi_ftm)); tmp_ptr = kzalloc(size, GFP_KERNEL); if (!tmp_ptr) { @@ -2323,17 +2317,14 @@ static void afe_send_cal_spv4_tx(int port_id) sizeof(struct afe_sp_v4_param_ex_vi_mode_cfg))) pr_info("%s: ex vi mode cfg failed\n", __func__); - ex_vi_ftm_cfg->num_ch = SP_V2_NUM_MAX_SPKRS; - - ch_ex_vi_ftm_cfg[SP_V2_SPKR_1].wait_time_ms = - this_afe.ex_ftm_cfg.wait_time[SP_V2_SPKR_1]; - ch_ex_vi_ftm_cfg[SP_V2_SPKR_2].wait_time_ms = - this_afe.ex_ftm_cfg.wait_time[SP_V2_SPKR_2]; - ch_ex_vi_ftm_cfg[SP_V2_SPKR_1].ftm_time_ms = - this_afe.ex_ftm_cfg.ftm_time[SP_V2_SPKR_1]; - ch_ex_vi_ftm_cfg[SP_V2_SPKR_2].ftm_time_ms = - this_afe.ex_ftm_cfg.ftm_time[SP_V2_SPKR_2]; + ex_vi_ftm_cfg->num_ch = this_afe.num_spkrs; + for (i = 0; i < this_afe.num_spkrs; i++) { + ch_ex_vi_ftm_cfg[i].wait_time_ms = + this_afe.ex_ftm_cfg.wait_time[i]; + ch_ex_vi_ftm_cfg[i].ftm_time_ms = + this_afe.ex_ftm_cfg.ftm_time[i]; + } if (afe_spk_prot_prepare(port_id, 0, AFE_PARAM_ID_SP_V4_EX_VI_FTM_CFG, (union afe_spkr_prot_config *)tmp_ptr, size)) @@ -8182,8 +8173,11 @@ int afe_close(int port_id) * even if ramp down configuration failed it is not serious enough to * warrant bailaing out. */ - if (afe_spk_ramp_dn_cfg(port_id) < 0) - pr_err("%s: ramp down configuration failed\n", __func__); + if (q6core_get_avcs_api_version_per_service( + APRV2_IDS_SERVICE_ID_ADSP_AFE_V) < AFE_API_VERSION_V9) { + if (afe_spk_ramp_dn_cfg(port_id) < 0) + pr_err("%s: ramp down config failed\n", __func__); + } stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); @@ -9171,6 +9165,7 @@ int afe_spk_prot_feed_back_cfg(int src_port, int dst_port, this_afe.v4_ch_map_cfg.chan_info[index++] = 4; } this_afe.v4_ch_map_cfg.num_channels = index; + this_afe.num_spkrs = index / 2; pr_debug("%s no of channels: %d\n", __func__, index); this_afe.vi_tx_port = src_port; this_afe.vi_rx_port = dst_port; From 84d85e958f7dfd78ab6c2839765c36b8ba15b939 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Fri, 15 May 2020 10:54:32 +0800 Subject: [PATCH 023/116] asoc: swr-haptics: close SWR data channel after stoping playing Per HW recommendation, when stopping SWR playing, SWR_PLAY register need to get deasserted before disconnecting SWR data channel. Hence adjust the sequence. Change-Id: I15f33fefc8b847c9a7f6abd627217f21f8ddee89 Signed-off-by: Fenglin Wu --- asoc/codecs/swr-haptics.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/asoc/codecs/swr-haptics.c b/asoc/codecs/swr-haptics.c index 4cc8cd8f88..3377f51346 100644 --- a/asoc/codecs/swr-haptics.c +++ b/asoc/codecs/swr-haptics.c @@ -186,12 +186,6 @@ static int hap_enable_swr_dac_port(struct snd_soc_dapm_widget *w, } break; case SND_SOC_DAPM_PRE_PMD: - swr_disconnect_port(swr_hap->swr_slave, &port_id, num_port, - &ch_mask, &port_type); - break; - case SND_SOC_DAPM_POST_PMD: - swr_slvdev_datapath_control(swr_hap->swr_slave, - swr_hap->swr_slave->dev_num, false); /* stop SWR play */ val = 0; rc = regmap_write(swr_hap->regmap, SWR_PLAY_REG, val); @@ -200,6 +194,12 @@ static int hap_enable_swr_dac_port(struct snd_soc_dapm_widget *w, __func__, rc); return rc; } + break; + case SND_SOC_DAPM_POST_PMD: + swr_disconnect_port(swr_hap->swr_slave, &port_id, num_port, + &ch_mask, &port_type); + swr_slvdev_datapath_control(swr_hap->swr_slave, + swr_hap->swr_slave->dev_num, false); swr_device_wakeup_unvote(swr_hap->swr_slave); break; default: From e65c93c8f122dcdee4b70bff1eab39ef3380a9ad Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Wed, 20 May 2020 10:10:21 +0530 Subject: [PATCH 024/116] audio-kernel: Fix compile with CONFIG_DEBUG_FS removed Add fix for compilation failure after remove CONFIG_DEBUG_FS. Change-Id: I94f851916e1c397848aa5d107774f7480a74270f Signed-off-by: Laxminath Kasam --- ipc/apr_vm.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ipc/apr_vm.c b/ipc/apr_vm.c index f94e3a22db..1b66013b8c 100644 --- a/ipc/apr_vm.c +++ b/ipc/apr_vm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2010-2014, 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2010-2014, 2016-2020 The Linux Foundation. All rights reserved. */ #include @@ -1308,9 +1308,9 @@ static int __init apr_debug_init(void) } #else static int __init apr_debug_init(void) -( +{ return 0; -) +} #endif static void apr_cleanup(void) @@ -1331,7 +1331,9 @@ static void apr_cleanup(void) mutex_destroy(&client[i][j].svc[k].m_lock); } } +#ifdef CONFIG_DEBUG_FS debugfs_remove(debugfs_apr_debug); +#endif } static int apr_probe(struct platform_device *pdev) From bbf44eeba1967425a0915317e55a300ec5728d2c Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Mon, 20 Jan 2020 20:38:05 +0530 Subject: [PATCH 025/116] asoc: codecs: Update muxsel registers only when clock counts are not stale During SSR/PDR use cases, core clock count in different macros becomes stale and muxsel registers are accessed leading to NOC errors. Update muxsel registers only after clock counts are reset after SSR/PDR recovery. Change-Id: I656f8e7ddc8a92a325c2ba644f1a945cbafb08a0 Signed-off-by: Aditya Bavanari --- asoc/codecs/bolero/bolero-cdc.c | 4 ++++ asoc/codecs/bolero/bolero-cdc.h | 3 ++- asoc/codecs/bolero/bolero-clk-rsc.c | 30 +++++++++++++++++++---------- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c index ec2a304034..0918652d32 100644 --- a/asoc/codecs/bolero/bolero-cdc.c +++ b/asoc/codecs/bolero/bolero-cdc.c @@ -834,6 +834,10 @@ static int bolero_ssr_enable(struct device *dev, void *data) priv->component, BOLERO_MACRO_EVT_CLK_RESET, 0x0); } + + if (priv->rsc_clk_cb) + priv->rsc_clk_cb(priv->clk_dev, BOLERO_MACRO_EVT_SSR_GFMUX_UP); + trace_printk("%s: clk count reset\n", __func__); regcache_cache_only(priv->regmap, false); mutex_lock(&priv->clk_lock); diff --git a/asoc/codecs/bolero/bolero-cdc.h b/asoc/codecs/bolero/bolero-cdc.h index ca4324ac4a..a1a2b71586 100644 --- a/asoc/codecs/bolero/bolero-cdc.h +++ b/asoc/codecs/bolero/bolero-cdc.h @@ -52,7 +52,8 @@ enum { BOLERO_MACRO_EVT_CLK_RESET, BOLERO_MACRO_EVT_REG_WAKE_IRQ, BOLERO_MACRO_EVT_RX_COMPANDER_SOFT_RST, - BOLERO_MACRO_EVT_BCS_CLK_OFF + BOLERO_MACRO_EVT_BCS_CLK_OFF, + BOLERO_MACRO_EVT_SSR_GFMUX_UP, }; enum { diff --git a/asoc/codecs/bolero/bolero-clk-rsc.c b/asoc/codecs/bolero/bolero-clk-rsc.c index 7e28c5bfeb..b134819e0c 100644 --- a/asoc/codecs/bolero/bolero-clk-rsc.c +++ b/asoc/codecs/bolero/bolero-clk-rsc.c @@ -38,6 +38,7 @@ struct bolero_clk_rsc { int reg_seq_en_cnt; int va_tx_clk_cnt; bool dev_up; + bool dev_up_gfmux; u32 num_fs_reg; u32 *fs_gen_seq; int default_clk_id[MAX_CLK]; @@ -65,10 +66,14 @@ static int bolero_clk_rsc_cb(struct device *dev, u16 event) } mutex_lock(&priv->rsc_clk_lock); - if (event == BOLERO_MACRO_EVT_SSR_UP) + if (event == BOLERO_MACRO_EVT_SSR_UP) { priv->dev_up = true; - else if (event == BOLERO_MACRO_EVT_SSR_DOWN) + } else if (event == BOLERO_MACRO_EVT_SSR_DOWN) { priv->dev_up = false; + priv->dev_up_gfmux = false; + } else if (event == BOLERO_MACRO_EVT_SSR_GFMUX_UP) { + priv->dev_up_gfmux = true; + } mutex_unlock(&priv->rsc_clk_lock); return 0; @@ -282,10 +287,12 @@ static int bolero_clk_rsc_mux1_clk_request(struct bolero_clk_rsc *priv, * care in DSP itself */ if (clk_id != VA_CORE_CLK) { - iowrite32(0x1, clk_muxsel); - muxsel = ioread32(clk_muxsel); - trace_printk("%s: muxsel value after enable: %d\n", - __func__, muxsel); + if (priv->dev_up_gfmux) { + iowrite32(0x1, clk_muxsel); + muxsel = ioread32(clk_muxsel); + trace_printk("%s: muxsel value after enable: %d\n", + __func__, muxsel); + } bolero_clk_rsc_mux0_clk_request(priv, default_clk_id, false); @@ -313,10 +320,12 @@ static int bolero_clk_rsc_mux1_clk_request(struct bolero_clk_rsc *priv, * This configuration would be taken * care in DSP itself. */ - iowrite32(0x0, clk_muxsel); - muxsel = ioread32(clk_muxsel); - trace_printk("%s: muxsel value after disable: %d\n", - __func__, muxsel); + if (priv->dev_up_gfmux) { + iowrite32(0x0, clk_muxsel); + muxsel = ioread32(clk_muxsel); + trace_printk("%s: muxsel value after disable: %d\n", + __func__, muxsel); + } } } if (priv->clk[clk_id + NPL_CLK_OFFSET]) @@ -706,6 +715,7 @@ static int bolero_clk_rsc_probe(struct platform_device *pdev) } priv->dev = &pdev->dev; priv->dev_up = true; + priv->dev_up_gfmux = true; mutex_init(&priv->rsc_clk_lock); mutex_init(&priv->fs_gen_lock); dev_set_drvdata(&pdev->dev, priv); From ec8a0b507c9fb4813b564eeea99de9328d0956cc Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Wed, 29 Apr 2020 17:57:00 +0530 Subject: [PATCH 026/116] asoc: codecs: Update LPM voting support in codec supplies For power saving during RBSC, need to vote for minimum or zero current on load for respective regulator to enter LPM mode. Add required support from audio WCD/WSA to vote accordingly during suspend/resume. Change-Id: I578195b84ba18a0b69dde3b93a3f6461efa85f7f Signed-off-by: Laxminath Kasam --- asoc/codecs/msm-cdc-supply.c | 70 +++++++++++++++++++++++++++++++++- asoc/codecs/wcd938x/internal.h | 1 + asoc/codecs/wcd938x/wcd938x.c | 63 ++++++++++++++++++++++++++++-- asoc/codecs/wsa883x/internal.h | 1 + asoc/codecs/wsa883x/wsa883x.c | 48 ++++++++++++++++++++++- include/asoc/msm-cdc-supply.h | 6 +++ 6 files changed, 182 insertions(+), 7 deletions(-) diff --git a/asoc/codecs/msm-cdc-supply.c b/asoc/codecs/msm-cdc-supply.c index 230a7f9981..1618b83a55 100644 --- a/asoc/codecs/msm-cdc-supply.c +++ b/asoc/codecs/msm-cdc-supply.c @@ -60,9 +60,22 @@ static int msm_cdc_dt_parse_vreg_info(struct device *dev, } cdc_vreg->optimum_uA = prop_val; - dev_info(dev, "%s: %s: vol=[%d %d]uV, curr=[%d]uA, ond %d\n", + /* Parse supply - LPM or NOM mode(default NOM) */ + snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "qcom,%s-lpm-supported", name); + rc = of_property_read_u32(dev->of_node, prop_name, &prop_val); + if (rc) { + dev_dbg(dev, "%s: Looking up %s property in node %s failed", + __func__, prop_name, dev->of_node->full_name); + cdc_vreg->lpm_supported = 0; + rc = 0; + } else { + cdc_vreg->lpm_supported = prop_val; + } + + dev_info(dev, "%s: %s: vol=[%d %d]uV, curr=[%d]uA, ond %d lpm %d\n", __func__, cdc_vreg->name, cdc_vreg->min_uV, cdc_vreg->max_uV, - cdc_vreg->optimum_uA, cdc_vreg->ondemand); + cdc_vreg->optimum_uA, cdc_vreg->ondemand, + cdc_vreg->lpm_supported); done: return rc; @@ -260,6 +273,59 @@ int msm_cdc_enable_ondemand_supply(struct device *dev, } EXPORT_SYMBOL(msm_cdc_enable_ondemand_supply); +/* + * msm_cdc_set_supplies_lpm_mode: + * Update load for given supply string + * + * @dev: pointer to codec device + * @supplies: pointer to regulator bulk data + * @cdc_vreg: pointer to platform regulator data + * @num_supplies: number of supplies + * @supply_name: supply name to be checked + * @min_max: Apply optimum or 0 current + * + * Return error code if set current fail + */ +int msm_cdc_set_supplies_lpm_mode(struct device *dev, + struct regulator_bulk_data *supplies, + struct cdc_regulator *cdc_vreg, + int num_supplies, + bool flag) +{ + int rc = 0, i; + + if (!supplies) { + pr_err("%s: supplies is NULL\n", + __func__); + return -EINVAL; + } + /* input parameter validation */ + rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies); + if (rc) + return rc; + + for (i = 0; i < num_supplies; i++) { + if (cdc_vreg[i].lpm_supported) { + rc = regulator_set_load( + supplies[i].consumer, + flag ? 0 : cdc_vreg[i].optimum_uA); + if (rc) + dev_err(dev, + "%s: failed to set supply %s to %s, err:%d\n", + __func__, supplies[i].supply, + flag ? "LPM" : "NOM", + rc); + else + dev_dbg(dev, "%s: regulator %s load set to %s\n", + __func__, supplies[i].supply, + flag ? "LPM" : "NOM"); + } + } + + return rc; +} +EXPORT_SYMBOL(msm_cdc_set_supplies_lpm_mode); + /* * msm_cdc_disable_static_supplies: * Disable codec static supplies diff --git a/asoc/codecs/wcd938x/internal.h b/asoc/codecs/wcd938x/internal.h index 0baf0ded9b..84a8a42409 100644 --- a/asoc/codecs/wcd938x/internal.h +++ b/asoc/codecs/wcd938x/internal.h @@ -73,6 +73,7 @@ struct wcd938x_priv { bool comp2_enable; bool ldoh; bool bcs_dis; + bool dapm_bias_off; struct irq_domain *virq; struct wcd_irq_info irq_info; u32 rx_clk_cnt; diff --git a/asoc/codecs/wcd938x/wcd938x.c b/asoc/codecs/wcd938x/wcd938x.c index a6652bd4e4..2ed99ea0c5 100644 --- a/asoc/codecs/wcd938x/wcd938x.c +++ b/asoc/codecs/wcd938x/wcd938x.c @@ -72,6 +72,7 @@ enum { HPH_COMP_DELAY, HPH_PA_DELAY, AMIC2_BCS_ENABLE, + WCD_SUPPLIES_LPM_MODE, }; enum { @@ -3713,6 +3714,26 @@ static void wcd938x_soc_codec_remove(struct snd_soc_component *component) false); } +static int wcd938x_soc_codec_suspend(struct snd_soc_component *component) +{ + struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + + if (!wcd938x) + return 0; + wcd938x->dapm_bias_off = true; + return 0; +} + +static int wcd938x_soc_codec_resume(struct snd_soc_component *component) +{ + struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + + if (!wcd938x) + return 0; + wcd938x->dapm_bias_off = false; + return 0; +} + static struct snd_soc_component_driver soc_codec_dev_wcd938x = { .name = WCD938X_DRV_NAME, .probe = wcd938x_soc_codec_probe, @@ -3723,6 +3744,8 @@ static struct snd_soc_component_driver soc_codec_dev_wcd938x = { .num_dapm_widgets = ARRAY_SIZE(wcd938x_dapm_widgets), .dapm_routes = wcd938x_audio_map, .num_dapm_routes = ARRAY_SIZE(wcd938x_audio_map), + .suspend = wcd938x_soc_codec_suspend, + .resume = wcd938x_soc_codec_resume, }; static int wcd938x_reset(struct device *dev) @@ -4242,19 +4265,51 @@ static int wcd938x_suspend(struct device *dev) } clear_bit(ALLOW_BUCK_DISABLE, &wcd938x->status_mask); } + if (wcd938x->dapm_bias_off) { + msm_cdc_set_supplies_lpm_mode(wcd938x->dev, + wcd938x->supplies, + pdata->regulator, + pdata->num_supplies, + true); + set_bit(WCD_SUPPLIES_LPM_MODE, &wcd938x->status_mask); + } return 0; } static int wcd938x_resume(struct device *dev) { + struct wcd938x_priv *wcd938x = NULL; + struct wcd938x_pdata *pdata = NULL; + + if (!dev) + return -ENODEV; + + wcd938x = dev_get_drvdata(dev); + if (!wcd938x) + return -EINVAL; + + pdata = dev_get_platdata(wcd938x->dev); + + if (!pdata) { + dev_err(dev, "%s: pdata is NULL\n", __func__); + return -EINVAL; + } + + if (test_bit(WCD_SUPPLIES_LPM_MODE, &wcd938x->status_mask)) { + msm_cdc_set_supplies_lpm_mode(wcd938x->dev, + wcd938x->supplies, + pdata->regulator, + pdata->num_supplies, + false); + clear_bit(WCD_SUPPLIES_LPM_MODE, &wcd938x->status_mask); + } + return 0; } static const struct dev_pm_ops wcd938x_dev_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS( - wcd938x_suspend, - wcd938x_resume - ) + .suspend_late = wcd938x_suspend, + .resume_early = wcd938x_resume, }; #endif diff --git a/asoc/codecs/wsa883x/internal.h b/asoc/codecs/wsa883x/internal.h index 4868d2df83..3dc362784d 100644 --- a/asoc/codecs/wsa883x/internal.h +++ b/asoc/codecs/wsa883x/internal.h @@ -97,6 +97,7 @@ struct wsa883x_priv { bool comp_enable; bool visense_enable; bool ext_vdd_spk; + bool dapm_bias_off; struct swr_port port[WSA883X_MAX_SWR_PORTS]; int global_pa_cnt; int dev_mode; diff --git a/asoc/codecs/wsa883x/wsa883x.c b/asoc/codecs/wsa883x/wsa883x.c index de83f2c535..8b3d588130 100644 --- a/asoc/codecs/wsa883x/wsa883x.c +++ b/asoc/codecs/wsa883x/wsa883x.c @@ -132,6 +132,7 @@ enum { enum { SPKR_STATUS = 0, + WSA_SUPPLIES_LPM_MODE, }; enum { @@ -1220,6 +1221,28 @@ static void wsa883x_codec_remove(struct snd_soc_component *component) return; } +static int wsa883x_soc_codec_suspend(struct snd_soc_component *component) +{ + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + + if (!wsa883x) + return 0; + + wsa883x->dapm_bias_off = true; + return 0; +} + +static int wsa883x_soc_codec_resume(struct snd_soc_component *component) +{ + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); + + if (!wsa883x) + return 0; + + wsa883x->dapm_bias_off = false; + return 0; +} + static const struct snd_soc_component_driver soc_codec_dev_wsa883x_wsa = { .name = "", .probe = wsa883x_codec_probe, @@ -1230,6 +1253,8 @@ static const struct snd_soc_component_driver soc_codec_dev_wsa883x_wsa = { .num_dapm_widgets = ARRAY_SIZE(wsa883x_dapm_widgets), .dapm_routes = wsa883x_audio_map, .num_dapm_routes = ARRAY_SIZE(wsa883x_audio_map), + .suspend = wsa883x_soc_codec_suspend, + .resume = wsa883x_soc_codec_resume, }; static int wsa883x_gpio_ctrl(struct wsa883x_priv *wsa883x, bool enable) @@ -1692,7 +1717,20 @@ static int wsa883x_swr_remove(struct swr_device *pdev) #ifdef CONFIG_PM_SLEEP static int wsa883x_swr_suspend(struct device *dev) { + struct wsa883x_priv *wsa883x = swr_get_dev_data(to_swr_device(dev)); + + if (!wsa883x) { + dev_err(dev, "%s: wsa883x private data is NULL\n", __func__); + return -EINVAL; + } dev_dbg(dev, "%s: system suspend\n", __func__); + if (wsa883x->dapm_bias_off) { + msm_cdc_set_supplies_lpm_mode(dev, wsa883x->supplies, + wsa883x->regulator, + wsa883x->num_supplies, + true); + set_bit(WSA_SUPPLIES_LPM_MODE, &wsa883x->status_mask); + } return 0; } @@ -1704,13 +1742,21 @@ static int wsa883x_swr_resume(struct device *dev) dev_err(dev, "%s: wsa883x private data is NULL\n", __func__); return -EINVAL; } + if (test_bit(WSA_SUPPLIES_LPM_MODE, &wsa883x->status_mask)) { + msm_cdc_set_supplies_lpm_mode(dev, wsa883x->supplies, + wsa883x->regulator, + wsa883x->num_supplies, + false); + clear_bit(WSA_SUPPLIES_LPM_MODE, &wsa883x->status_mask); + } dev_dbg(dev, "%s: system resume\n", __func__); return 0; } #endif /* CONFIG_PM_SLEEP */ static const struct dev_pm_ops wsa883x_swr_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(wsa883x_swr_suspend, wsa883x_swr_resume) + .suspend_late = wsa883x_swr_suspend, + .resume_early = wsa883x_swr_resume, }; static const struct swr_device_id wsa883x_swr_id[] = { diff --git a/include/asoc/msm-cdc-supply.h b/include/asoc/msm-cdc-supply.h index f7fec21c03..c740400754 100644 --- a/include/asoc/msm-cdc-supply.h +++ b/include/asoc/msm-cdc-supply.h @@ -15,6 +15,7 @@ struct cdc_regulator { int max_uV; int optimum_uA; bool ondemand; + bool lpm_supported; struct regulator *regulator; }; @@ -51,6 +52,11 @@ extern int msm_cdc_enable_static_supplies(struct device *dev, struct regulator_bulk_data *supplies, struct cdc_regulator *cdc_vreg, int num_supplies); +extern int msm_cdc_set_supplies_lpm_mode(struct device *dev, + struct regulator_bulk_data *supplies, + struct cdc_regulator *cdc_vreg, + int num_supplies, + bool flag); extern int msm_cdc_init_supplies(struct device *dev, struct regulator_bulk_data **supplies, struct cdc_regulator *cdc_vreg, From 5423077cb86e1417c744091e2ea48e2661cbf379 Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Wed, 20 May 2020 14:12:20 +0530 Subject: [PATCH 027/116] asoc: codecs: Update LPM voting support for vdd-mic-bias-supply For power saving during RBSC, need to vote for minimum or zero current on load for respective regulator to enter LPM mode. Add required support from rouleur to vote for mic bias accordingly during suspend/resume. Change-Id: Idb2accbc77241e19f688225081e1b68b99c19e29 Signed-off-by: Aditya Bavanari --- asoc/codecs/rouleur/internal.h | 1 + asoc/codecs/rouleur/rouleur.c | 63 +++++++++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/asoc/codecs/rouleur/internal.h b/asoc/codecs/rouleur/internal.h index 7104685d7c..bdade7f26c 100644 --- a/asoc/codecs/rouleur/internal.h +++ b/asoc/codecs/rouleur/internal.h @@ -50,6 +50,7 @@ struct rouleur_priv { bool comp1_enable; bool comp2_enable; + bool dapm_bias_off; struct irq_domain *virq; struct wcd_irq_info irq_info; diff --git a/asoc/codecs/rouleur/rouleur.c b/asoc/codecs/rouleur/rouleur.c index d028ed48b5..45b43e80d1 100644 --- a/asoc/codecs/rouleur/rouleur.c +++ b/asoc/codecs/rouleur/rouleur.c @@ -46,6 +46,7 @@ enum { HPH_COMP_DELAY, HPH_PA_DELAY, AMIC2_BCS_ENABLE, + WCD_SUPPLIES_LPM_MODE, }; /* TODO: Check on the step values */ @@ -2003,6 +2004,26 @@ static void rouleur_soc_codec_remove(struct snd_soc_component *component) false); } +static int rouleur_soc_codec_suspend(struct snd_soc_component *component) +{ + struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component); + + if (!rouleur) + return 0; + rouleur->dapm_bias_off = true; + return 0; +} + +static int rouleur_soc_codec_resume(struct snd_soc_component *component) +{ + struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component); + + if (!rouleur) + return 0; + rouleur->dapm_bias_off = false; + return 0; +} + static const struct snd_soc_component_driver soc_codec_dev_rouleur = { .name = DRV_NAME, .probe = rouleur_soc_codec_probe, @@ -2013,6 +2034,8 @@ static const struct snd_soc_component_driver soc_codec_dev_rouleur = { .num_dapm_widgets = ARRAY_SIZE(rouleur_dapm_widgets), .dapm_routes = rouleur_audio_map, .num_dapm_routes = ARRAY_SIZE(rouleur_audio_map), + .suspend = rouleur_soc_codec_suspend, + .resume = rouleur_soc_codec_resume, }; #ifdef CONFIG_PM_SLEEP @@ -2049,11 +2072,45 @@ static int rouleur_suspend(struct device *dev) } clear_bit(ALLOW_VPOS_DISABLE, &rouleur->status_mask); } + if (rouleur->dapm_bias_off) { + msm_cdc_set_supplies_lpm_mode(rouleur->dev, + rouleur->supplies, + pdata->regulator, + pdata->num_supplies, + true); + set_bit(WCD_SUPPLIES_LPM_MODE, &rouleur->status_mask); + } return 0; } static int rouleur_resume(struct device *dev) { + struct rouleur_priv *rouleur = NULL; + struct rouleur_pdata *pdata = NULL; + + if (!dev) + return -ENODEV; + + rouleur = dev_get_drvdata(dev); + if (!rouleur) + return -EINVAL; + + pdata = dev_get_platdata(rouleur->dev); + + if (!pdata) { + dev_err(dev, "%s: pdata is NULL\n", __func__); + return -EINVAL; + } + + if (test_bit(WCD_SUPPLIES_LPM_MODE, &rouleur->status_mask)) { + msm_cdc_set_supplies_lpm_mode(rouleur->dev, + rouleur->supplies, + pdata->regulator, + pdata->num_supplies, + false); + clear_bit(WCD_SUPPLIES_LPM_MODE, &rouleur->status_mask); + } + return 0; } #endif @@ -2484,10 +2541,8 @@ static int rouleur_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static const struct dev_pm_ops rouleur_dev_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS( - rouleur_suspend, - rouleur_resume - ) + .suspend_late = rouleur_suspend, + .resume_early = rouleur_resume }; #endif From 515fc228eeda84acb0dbc86a84a57f5cd4c7efa0 Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Wed, 13 May 2020 18:55:32 +0530 Subject: [PATCH 028/116] asoc: codec: Add pre ssr up event for all macros Add a pre ssr up event in all macros ,where GFMUX reset to done before set the dev_up flag to true. Change-Id: I77229ccd0ed68aac841146a89fe7f76961260aea Signed-off-by: Prasad Kumpatla --- asoc/codecs/bolero/bolero-cdc.c | 10 +++++++++- asoc/codecs/bolero/bolero-cdc.h | 1 + asoc/codecs/bolero/rx-macro.c | 12 +++++++----- asoc/codecs/bolero/tx-macro.c | 3 +++ asoc/codecs/bolero/va-macro.c | 6 ++++-- asoc/codecs/bolero/wsa-macro.c | 10 ++++++---- 6 files changed, 30 insertions(+), 12 deletions(-) diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c index 0918652d32..6244c417dd 100644 --- a/asoc/codecs/bolero/bolero-cdc.c +++ b/asoc/codecs/bolero/bolero-cdc.c @@ -834,11 +834,19 @@ static int bolero_ssr_enable(struct device *dev, void *data) priv->component, BOLERO_MACRO_EVT_CLK_RESET, 0x0); } + trace_printk("%s: clk count reset\n", __func__); if (priv->rsc_clk_cb) priv->rsc_clk_cb(priv->clk_dev, BOLERO_MACRO_EVT_SSR_GFMUX_UP); - trace_printk("%s: clk count reset\n", __func__); + for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) { + if (!priv->macro_params[macro_idx].event_handler) + continue; + priv->macro_params[macro_idx].event_handler( + priv->component, + BOLERO_MACRO_EVT_PRE_SSR_UP, 0x0); + } + regcache_cache_only(priv->regmap, false); mutex_lock(&priv->clk_lock); priv->dev_up = true; diff --git a/asoc/codecs/bolero/bolero-cdc.h b/asoc/codecs/bolero/bolero-cdc.h index a1a2b71586..1f21fd69c8 100644 --- a/asoc/codecs/bolero/bolero-cdc.h +++ b/asoc/codecs/bolero/bolero-cdc.h @@ -54,6 +54,7 @@ enum { BOLERO_MACRO_EVT_RX_COMPANDER_SOFT_RST, BOLERO_MACRO_EVT_BCS_CLK_OFF, BOLERO_MACRO_EVT_SSR_GFMUX_UP, + BOLERO_MACRO_EVT_PRE_SSR_UP, }; enum { diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c index 62da031f26..11aa9b1059 100644 --- a/asoc/codecs/bolero/rx-macro.c +++ b/asoc/codecs/bolero/rx-macro.c @@ -1410,11 +1410,7 @@ static int rx_macro_event_handler(struct snd_soc_component *component, } } break; - case BOLERO_MACRO_EVT_SSR_UP: - trace_printk("%s, enter SSR up\n", __func__); - rx_priv->dev_up = true; - /* reset swr after ssr/pdr */ - rx_priv->reset_swr = true; + case BOLERO_MACRO_EVT_PRE_SSR_UP: /* enable&disable RX_CORE_CLK to reset GFMUX reg */ ret = bolero_clk_rsc_request_clock(rx_priv->dev, rx_priv->default_clk_id, @@ -1427,6 +1423,12 @@ static int rx_macro_event_handler(struct snd_soc_component *component, bolero_clk_rsc_request_clock(rx_priv->dev, rx_priv->default_clk_id, RX_CORE_CLK, false); + break; + case BOLERO_MACRO_EVT_SSR_UP: + trace_printk("%s, enter SSR up\n", __func__); + rx_priv->dev_up = true; + /* reset swr after ssr/pdr */ + rx_priv->reset_swr = true; if (rx_priv->swr_ctrl_data) swrm_wcd_notify( diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c index 2539577678..cc03e6121c 100644 --- a/asoc/codecs/bolero/tx-macro.c +++ b/asoc/codecs/bolero/tx-macro.c @@ -411,6 +411,9 @@ static int tx_macro_event_handler(struct snd_soc_component *component, else tx_priv->hs_slow_insert_complete = false; break; + default: + pr_debug("%s Invalid Event\n", __func__); + break; } return 0; } diff --git a/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c index a96f14efc1..f60598cca7 100644 --- a/asoc/codecs/bolero/va-macro.c +++ b/asoc/codecs/bolero/va-macro.c @@ -297,8 +297,7 @@ static int va_macro_event_handler(struct snd_soc_component *component, "%s: va_mclk_users is non-zero still, audio SSR fail!!\n", __func__); break; - case BOLERO_MACRO_EVT_SSR_UP: - trace_printk("%s, enter SSR up\n", __func__); + case BOLERO_MACRO_EVT_PRE_SSR_UP: /* enable&disable VA_CORE_CLK to reset GFMUX reg */ ret = bolero_clk_rsc_request_clock(va_priv->dev, va_priv->default_clk_id, @@ -311,6 +310,9 @@ static int va_macro_event_handler(struct snd_soc_component *component, bolero_clk_rsc_request_clock(va_priv->dev, va_priv->default_clk_id, VA_CORE_CLK, false); + break; + case BOLERO_MACRO_EVT_SSR_UP: + trace_printk("%s, enter SSR up\n", __func__); /* reset swr after ssr/pdr */ va_priv->reset_swr = true; if (va_priv->swr_ctrl_data) diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c index 7579957aa4..719020b172 100644 --- a/asoc/codecs/bolero/wsa-macro.c +++ b/asoc/codecs/bolero/wsa-macro.c @@ -1022,10 +1022,7 @@ static int wsa_macro_event_handler(struct snd_soc_component *component, } } break; - case BOLERO_MACRO_EVT_SSR_UP: - trace_printk("%s, enter SSR up\n", __func__); - /* reset swr after ssr/pdr */ - wsa_priv->reset_swr = true; + case BOLERO_MACRO_EVT_PRE_SSR_UP: /* enable&disable WSA_CORE_CLK to reset GFMUX reg */ ret = bolero_clk_rsc_request_clock(wsa_priv->dev, wsa_priv->default_clk_id, @@ -1038,6 +1035,11 @@ static int wsa_macro_event_handler(struct snd_soc_component *component, bolero_clk_rsc_request_clock(wsa_priv->dev, wsa_priv->default_clk_id, WSA_CORE_CLK, false); + break; + case BOLERO_MACRO_EVT_SSR_UP: + trace_printk("%s, enter SSR up\n", __func__); + /* reset swr after ssr/pdr */ + wsa_priv->reset_swr = true; if (wsa_priv->swr_ctrl_data) swrm_wcd_notify( wsa_priv->swr_ctrl_data[0].wsa_swr_pdev, From 83b1aba6b682f1db39d4e5520ae0641a2842ed0b Mon Sep 17 00:00:00 2001 From: Sudheer Papothi Date: Wed, 27 May 2020 01:35:48 +0530 Subject: [PATCH 029/116] ASoC: pcm-routing: Add WSA VI sense macro to support capture Add WSA VI sense macro to support VI sense capture. Change-Id: I704aa6fbcb3908c0b76c82c941818b64e1d4598b Signed-off-by: Sudheer Papothi --- asoc/msm-pcm-routing-v2.h | 1 + 1 file changed, 1 insertion(+) diff --git a/asoc/msm-pcm-routing-v2.h b/asoc/msm-pcm-routing-v2.h index 337875909a..e85197d409 100644 --- a/asoc/msm-pcm-routing-v2.h +++ b/asoc/msm-pcm-routing-v2.h @@ -211,6 +211,7 @@ #define LPASS_BE_WSA_CDC_DMA_RX_0 "WSA_CDC_DMA_RX_0" #define LPASS_BE_WSA_CDC_DMA_TX_0 "WSA_CDC_DMA_TX_0" +#define LPASS_BE_WSA_CDC_DMA_TX_0_VI "WSA_CDC_DMA_TX_0_VI" #define LPASS_BE_WSA_CDC_DMA_RX_1 "WSA_CDC_DMA_RX_1" #define LPASS_BE_WSA_CDC_DMA_TX_1 "WSA_CDC_DMA_TX_1" #define LPASS_BE_WSA_CDC_DMA_TX_2 "WSA_CDC_DMA_TX_2" From d053d56f5030c8e75ed7c3ec1a2abf553c8afca7 Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Wed, 27 May 2020 13:00:33 +0530 Subject: [PATCH 030/116] dsp: Fix a memory leak issue when nvmem read returns invalid length When nvmem cell read returns invalid length the allocated buffer is not freed. Free the buffer in this scenario to fix memory leak issue. Change-Id: I2e0010c1cfb2ea03cb4f25abf55e94ce4f0c5fcf Signed-off-by: Aditya Bavanari --- dsp/adsp-loader.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/dsp/adsp-loader.c b/dsp/adsp-loader.c index c8e1270b02..e99d6a3c72 100644 --- a/dsp/adsp-loader.c +++ b/dsp/adsp-loader.c @@ -388,10 +388,16 @@ static int adsp_loader_probe(struct platform_device *pdev) } buf = nvmem_cell_read(cell, &len); nvmem_cell_put(cell); - if (IS_ERR_OR_NULL(buf) || len <= 0 || len > sizeof(u32)) { + if (IS_ERR_OR_NULL(buf)) { dev_dbg(&pdev->dev, "%s: FAILED to read nvmem cell \n", __func__); goto wqueue; } + if (len <= 0 || len > sizeof(u32)) { + dev_dbg(&pdev->dev, "%s: nvmem cell length out of range: %d\n", + __func__, len); + kfree(buf); + goto wqueue; + } memcpy(&adsp_var_idx, buf, len); kfree(buf); From d8864856e7f998f55519d8bfb72d5562b891febf Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Wed, 27 May 2020 13:09:33 +0530 Subject: [PATCH 031/116] asoc: Fix a memory leak issue when nvmem read returns invalid length When nvmem cell read returns invalid length the allocated buffer is not freed. Free the buffer in this scenario to fix memory leak issue. Change-Id: I68585c1dd45b0a40c471bf42dea201cd0ebb497f Signed-off-by: Aditya Bavanari --- asoc/bengal.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/asoc/bengal.c b/asoc/bengal.c index 22677cb258..e82736e611 100644 --- a/asoc/bengal.c +++ b/asoc/bengal.c @@ -6714,10 +6714,16 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) } buf = nvmem_cell_read(cell, &len); nvmem_cell_put(cell); - if (IS_ERR_OR_NULL(buf) || len <= 0 || len > sizeof(32)) { + if (IS_ERR_OR_NULL(buf)) { dev_dbg(&pdev->dev, "%s: FAILED to read nvmem cell \n", __func__); goto ret; } + if (len <= 0 || len > sizeof(u32)) { + dev_dbg(&pdev->dev, "%s: nvmem cell length out of range: %d\n", + __func__, len); + kfree(buf); + goto ret; + } memcpy(&adsp_var_idx, buf, len); kfree(buf); va_disable = adsp_var_idx; From b466b00787f832e7f6acb6f93b5d9bf16f13d96a Mon Sep 17 00:00:00 2001 From: Kunlei Zhang Date: Wed, 27 May 2020 17:58:10 +0800 Subject: [PATCH 032/116] dsp: adm: change channel number for FLUENCE_SM module FLUENCE_SM module in COPreP topology doesn't support stereo input. Update channel number to mono for VPM_TX_VOICE_FLUENCE_SM_COPP_TOPOLOGY. Change-Id: I7de7b49706387b09031f67e1a0271db1825cb81d Signed-off-by: Kunlei Zhang --- dsp/q6adm.c | 3 ++- include/dsp/apr_audio-v2.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/dsp/q6adm.c b/dsp/q6adm.c index f62f03a07e..e9581a2888 100644 --- a/dsp/q6adm.c +++ b/dsp/q6adm.c @@ -3082,7 +3082,8 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology, this_adm.ffecns_port_id); } - if (topology == VPM_TX_VOICE_SMECNS_V2_COPP_TOPOLOGY) + if (topology == VPM_TX_VOICE_SMECNS_V2_COPP_TOPOLOGY || + topology == VPM_TX_VOICE_FLUENCE_SM_COPP_TOPOLOGY) channel_mode = 1; /* diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h index 2860016c6e..a4aeb7923b 100644 --- a/include/dsp/apr_audio-v2.h +++ b/include/dsp/apr_audio-v2.h @@ -5380,6 +5380,7 @@ struct afe_param_id_lpass_core_shared_clk_cfg { #define COMPRESSED_PASSTHROUGH_NONE_TOPOLOGY 0x00010774 #define VPM_TX_SM_ECNS_V2_COPP_TOPOLOGY 0x00010F89 #define VPM_TX_VOICE_SMECNS_V2_COPP_TOPOLOGY 0x10000003 +#define VPM_TX_VOICE_FLUENCE_SM_COPP_TOPOLOGY 0x10000004 #define VPM_TX_DM_FLUENCE_COPP_TOPOLOGY 0x00010F72 #define VPM_TX_QMIC_FLUENCE_COPP_TOPOLOGY 0x00010F75 #define VPM_TX_DM_RFECNS_COPP_TOPOLOGY 0x00010F86 From a151ba4e135621c2a35aaa2824ddaa6fb6e685c6 Mon Sep 17 00:00:00 2001 From: Sudheer Papothi Date: Wed, 27 May 2020 13:17:17 +0530 Subject: [PATCH 033/116] ASoC: swr-haptics: Avoid soundwire resume during subsystem restart Soundwire register write from haptics resumes soundwire master during subsystem down. Avoid soundwire slave register writes when the subsystem is already down. Change-Id: I78304b84bfaf882df1b76dbd04a8e063185d3963 Signed-off-by: Sudheer Papothi --- asoc/codecs/swr-haptics.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/asoc/codecs/swr-haptics.c b/asoc/codecs/swr-haptics.c index 4cc8cd8f88..b4d3b17bc5 100644 --- a/asoc/codecs/swr-haptics.c +++ b/asoc/codecs/swr-haptics.c @@ -431,22 +431,12 @@ static int swr_haptics_device_down(struct swr_device *sdev) { struct swr_haptics_dev *swr_hap = swr_get_dev_data(sdev); int rc; - unsigned int val; if (!swr_hap) { dev_err(&sdev->dev, "%s: no data for swr_hap\n", __func__); return -ENODEV; } - /* Stop SWR play in SSR */ - val = 0; - rc = regmap_write(swr_hap->regmap, SWR_PLAY_REG, val); - if (rc) { - dev_err(swr_hap->dev, "%s: disable SWR_PLAY failed, rc=%d\n", - __func__, rc); - return rc; - } - /* Put SWR slave into reset */ rc = regulator_disable(swr_hap->vdd); if (rc < 0) { From c3fc0ba8b55b0dd30ffb2d430591b72865e12068 Mon Sep 17 00:00:00 2001 From: Vignesh Kulothungan Date: Wed, 27 May 2020 17:53:41 -0700 Subject: [PATCH 034/116] include: uapi: update header for upstream compliance Include types.h when using __uX data type. Change-Id: Icafb5a0a5fe68fc95c50883bf6b19c09041a95b8 Signed-off-by: Vignesh Kulothungan --- include/uapi/audio/sound/msmcal-hwdep.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/uapi/audio/sound/msmcal-hwdep.h b/include/uapi/audio/sound/msmcal-hwdep.h index f2891863fa..eb05fa97dd 100644 --- a/include/uapi/audio/sound/msmcal-hwdep.h +++ b/include/uapi/audio/sound/msmcal-hwdep.h @@ -1,6 +1,8 @@ #ifndef _CALIB_HWDEP_H #define _CALIB_HWDEP_H +#include + #define WCD9XXX_CODEC_HWDEP_NODE 1000 #define AQT1000_CODEC_HWDEP_NODE 1001 #define Q6AFE_HWDEP_NODE 1002 From ff2d021fb6ebaabf42282e7310bb789f54ea2111 Mon Sep 17 00:00:00 2001 From: Mingshu Pang Date: Wed, 27 May 2020 15:55:38 +0800 Subject: [PATCH 035/116] ASoC: add dai link for playback compress3 add dai link for playback compress3 CRs-fixed: 2695615 Change-Id: I8076dc0c6383adf1404a22a577c55d8dcd11a089 Signed-off-by: Mingshu Pang --- asoc/bengal.c | 16 ++++++++++++++++ asoc/kona.c | 13 +++++++++++++ asoc/lahaina.c | 13 +++++++++++++ 3 files changed, 42 insertions(+) diff --git a/asoc/bengal.c b/asoc/bengal.c index 22677cb258..c657d249b1 100644 --- a/asoc/bengal.c +++ b/asoc/bengal.c @@ -4985,6 +4985,22 @@ static struct snd_soc_dai_link msm_common_misc_fe_dai_links[] = { .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, .ops = &msm_cdc_dma_be_ops, }, + {/* hw:x,39 */ + .name = MSM_DAILINK_NAME(Compress3), + .stream_name = "Compress3", + .cpu_dai_name = "MultiMedia10", + .platform_name = "msm-compress-dsp", + .dynamic = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dainlink has playback support */ + .id = MSM_FRONTEND_DAI_MULTIMEDIA10, + }, }; static struct snd_soc_dai_link msm_common_be_dai_links[] = { diff --git a/asoc/kona.c b/asoc/kona.c index 0cc60ead59..27585b85c4 100644 --- a/asoc/kona.c +++ b/asoc/kona.c @@ -6139,6 +6139,19 @@ static struct snd_soc_dai_link msm_common_misc_fe_dai_links[] = { .ops = &msm_cdc_dma_be_ops, SND_SOC_DAILINK_REG(tx_cdcdma5_tx), }, + {/* hw:x,40 */ + .name = MSM_DAILINK_NAME(Compress3), + .stream_name = "Compress3", + .dynamic = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dainlink has playback support */ + .id = MSM_FRONTEND_DAI_MULTIMEDIA10, + SND_SOC_DAILINK_REG(multimedia10), + }, }; static struct snd_soc_dai_link msm_common_be_dai_links[] = { diff --git a/asoc/lahaina.c b/asoc/lahaina.c index f026c5c3d3..04c0bd4a95 100644 --- a/asoc/lahaina.c +++ b/asoc/lahaina.c @@ -6019,6 +6019,19 @@ static struct snd_soc_dai_link msm_common_misc_fe_dai_links[] = { .ignore_suspend = 1, SND_SOC_DAILINK_REG(afepcm_tx1), }, + {/* hw:x,43 */ + .name = MSM_DAILINK_NAME(Compress3), + .stream_name = "Compress3", + .dynamic = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + /* this dainlink has playback support */ + .id = MSM_FRONTEND_DAI_MULTIMEDIA10, + SND_SOC_DAILINK_REG(multimedia10), + }, }; static struct snd_soc_dai_link msm_common_be_dai_links[] = { From 44c6cc4fdcd255a53db882e747f95b3c465855e2 Mon Sep 17 00:00:00 2001 From: Kunlei Zhang Date: Fri, 17 Apr 2020 15:42:32 +0800 Subject: [PATCH 036/116] dsp: Add support to set island cfg and power mode Add new APIs to set/reset power mode along with island config before afe_port_start. Change-Id: Ibd9487b04b691be5ab829cfa32c89953838f3192 Signed-off-by: Kunlei Zhang --- asoc/msm-dai-q6-v2.c | 137 +++++++++++++++++++++++++++++++++++++ dsp/q6afe.c | 131 +++++++++++++++++++++++++++++++++++ include/dsp/apr_audio-v2.h | 16 +++++ include/dsp/q6afe-v2.h | 3 + 4 files changed, 287 insertions(+) diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c index dbedb55d2e..fc8c672e4b 100644 --- a/asoc/msm-dai-q6-v2.c +++ b/asoc/msm-dai-q6-v2.c @@ -1279,6 +1279,83 @@ static int msm_dai_q6_dai_auxpcm_remove(struct snd_soc_dai *dai) return 0; } +static int msm_dai_q6_power_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int value = ucontrol->value.integer.value[0]; + u16 port_id = (u16)kcontrol->private_value; + + pr_debug("%s: power mode = %d\n", __func__, value); + trace_printk("%s: power mode = %d\n", __func__, value); + + afe_set_power_mode_cfg(port_id, value); + return 0; +} + +static int msm_dai_q6_power_mode_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int value; + u16 port_id = (u16)kcontrol->private_value; + + afe_get_power_mode_cfg(port_id, &value); + ucontrol->value.integer.value[0] = value; + return 0; +} + +static void power_mode_mx_ctl_private_free(struct snd_kcontrol *kcontrol) +{ + struct snd_kcontrol_new *knew = snd_kcontrol_chip(kcontrol); + kfree(knew); +} + +static int msm_dai_q6_add_power_mode_mx_ctls(struct snd_card *card, + const char *dai_name, + int dai_id, void *dai_data) +{ + const char *mx_ctl_name = "Power Mode"; + char *mixer_str = NULL; + int dai_str_len = 0, ctl_len = 0; + int rc = 0; + struct snd_kcontrol_new *knew = NULL; + struct snd_kcontrol *kctl = NULL; + + dai_str_len = strlen(dai_name) + 1; + + ctl_len = dai_str_len + strlen(mx_ctl_name) + 1; + mixer_str = kzalloc(ctl_len, GFP_KERNEL); + if (!mixer_str) + return -ENOMEM; + + snprintf(mixer_str, ctl_len, "%s %s", dai_name, mx_ctl_name); + + knew = kzalloc(sizeof(struct snd_kcontrol_new), GFP_KERNEL); + if (!knew) { + kfree(mixer_str); + return -ENOMEM; + } + knew->iface = SNDRV_CTL_ELEM_IFACE_MIXER; + knew->info = snd_ctl_boolean_mono_info; + knew->get = msm_dai_q6_power_mode_get; + knew->put = msm_dai_q6_power_mode_put; + knew->name = mixer_str; + knew->private_value = dai_id; + kctl = snd_ctl_new1(knew, knew); + if (!kctl) { + kfree(knew); + kfree(mixer_str); + return -ENOMEM; + } + kctl->private_free = power_mode_mx_ctl_private_free; + rc = snd_ctl_add(card, kctl); + if (rc < 0) + pr_err("%s: err add config ctl, DAI = %s\n", + __func__, dai_name); + kfree(mixer_str); + + return rc; +} + static int msm_dai_q6_island_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1358,6 +1435,54 @@ static int msm_dai_q6_add_island_mx_ctls(struct snd_card *card, return rc; } +static int msm_dai_q6_add_isconfig_config_mx_ctls(struct snd_card *card, + const char *dai_name, + int dai_id, void *dai_data) + +{ + const char *mx_ctl_name = "Island Config"; + char *mixer_str = NULL; + int dai_str_len = 0, ctl_len = 0; + int rc = 0; + struct snd_kcontrol_new *knew = NULL; + struct snd_kcontrol *kctl = NULL; + + dai_str_len = strlen(dai_name) + 1; + + ctl_len = dai_str_len + strlen(mx_ctl_name) + 1; + mixer_str = kzalloc(ctl_len, GFP_KERNEL); + if (!mixer_str) + return -ENOMEM; + + snprintf(mixer_str, ctl_len, "%s %s", dai_name, mx_ctl_name); + + knew = kzalloc(sizeof(struct snd_kcontrol_new), GFP_KERNEL); + if (!knew) { + kfree(mixer_str); + return -ENOMEM; + } + knew->iface = SNDRV_CTL_ELEM_IFACE_MIXER; + knew->info = snd_ctl_boolean_mono_info; + knew->get = msm_dai_q6_island_mode_get; + knew->put = msm_dai_q6_island_mode_put; + knew->name = mixer_str; + knew->private_value = dai_id; + kctl = snd_ctl_new1(knew, knew); + if (!kctl) { + kfree(knew); + kfree(mixer_str); + return -ENOMEM; + } + kctl->private_free = island_mx_ctl_private_free; + rc = snd_ctl_add(card, kctl); + if (rc < 0) + pr_err("%s: err add config ctl, DAI = %s\n", + __func__, dai_name); + kfree(mixer_str); + + return rc; +} + /* * For single CPU DAI registration, the dai id needs to be * set explicitly in the dai probe as ASoC does not read @@ -12195,6 +12320,14 @@ static int msm_dai_q6_dai_cdc_dma_probe(struct snd_soc_dai *dai) dai->component->card->snd_card, dai->name, dai->id, (void *)dai_data); + rc = msm_dai_q6_add_power_mode_mx_ctls( + dai->component->card->snd_card, + dai->name, dai->id, + (void *)dai_data); + rc= msm_dai_q6_add_isconfig_config_mx_ctls( + dai->component->card->snd_card, + dai->name, dai->id, + (void *)dai_data); rc = msm_dai_q6_dai_add_route(dai); return rc; @@ -12624,6 +12757,7 @@ static struct snd_soc_dai_driver msm_dai_q6_cdc_dma_dai[] = { .rate_min = 8000, .rate_max = 384000, }, + .name = "RX_CDC_DMA_RX_0", .ops = &msm_dai_q6_cdc_dma_ops, .id = AFE_PORT_ID_RX_CODEC_DMA_RX_0, .probe = msm_dai_q6_dai_cdc_dma_probe, @@ -12674,6 +12808,7 @@ static struct snd_soc_dai_driver msm_dai_q6_cdc_dma_dai[] = { .rate_min = 8000, .rate_max = 384000, }, + .name = "RX_CDC_DMA_RX_1", .ops = &msm_dai_q6_cdc_dma_ops, .id = AFE_PORT_ID_RX_CODEC_DMA_RX_1, .probe = msm_dai_q6_dai_cdc_dma_probe, @@ -12798,6 +12933,7 @@ static struct snd_soc_dai_driver msm_dai_q6_cdc_dma_dai[] = { .rate_min = 8000, .rate_max = 384000, }, + .name = "TX_CDC_DMA_TX_3", .ops = &msm_dai_q6_cdc_dma_ops, .id = AFE_PORT_ID_TX_CODEC_DMA_TX_3, .probe = msm_dai_q6_dai_cdc_dma_probe, @@ -12848,6 +12984,7 @@ static struct snd_soc_dai_driver msm_dai_q6_cdc_dma_dai[] = { .rate_min = 8000, .rate_max = 384000, }, + .name = "TX_CDC_DMA_TX_4", .ops = &msm_dai_q6_cdc_dma_ops, .id = AFE_PORT_ID_TX_CODEC_DMA_TX_4, .probe = msm_dai_q6_dai_cdc_dma_probe, diff --git a/dsp/q6afe.c b/dsp/q6afe.c index 13379ce1c5..9fe94891fc 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -176,6 +176,7 @@ struct afe_ctl { /* cal info for AFE */ struct afe_fw_info *fw_data; u32 island_mode[AFE_MAX_PORTS]; + u32 power_mode[AFE_MAX_PORTS]; struct vad_config vad_cfg[AFE_MAX_PORTS]; struct work_struct afe_dc_work; struct notifier_block event_notifier; @@ -2843,6 +2844,81 @@ done: } +static int afe_get_power_mode(u16 port_id, u32 *power_mode) +{ + int ret = 0; + int index = 0; + *power_mode = 0; + + index = q6audio_get_port_index(port_id); + if (index < 0 || index >= AFE_MAX_PORTS) { + pr_err("%s: AFE port index[%d] invalid!\n", + __func__, index); + return -EINVAL; + } + *power_mode = this_afe.power_mode[index]; + return ret; +} + +/** + * afe_send_port_power_mode - + * for sending power mode to AFE + * + * @port_id: AFE port id number + * Returns 0 on success or error on failure. + */ +int afe_send_port_power_mode(u16 port_id) +{ + struct afe_param_id_power_mode_cfg_t power_mode_cfg; + struct param_hdr_v3 param_info; + u32 power_mode = 0; + int ret = 0; + + if (!(q6core_get_avcs_api_version_per_service( + APRV2_IDS_SERVICE_ID_ADSP_AFE_V) >= AFE_API_VERSION_V4)) { + pr_debug("%s: AFE port[%d] API version is invalid!\n", + __func__, port_id); + return 0; + } + + memset(&power_mode_cfg, 0, sizeof(power_mode_cfg)); + memset(¶m_info, 0, sizeof(param_info)); + + ret = afe_get_power_mode(port_id, &power_mode); + if (ret) { + pr_err("%s: AFE port[%d] get power mode is invalid!\n", + __func__, port_id); + return ret; + } + if (power_mode == 0) { + pr_debug("%s: AFE port[%d] power mode is not enabled\n", + __func__, port_id); + return ret; + } + param_info.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE; + param_info.instance_id = INSTANCE_ID_0; + param_info.param_id = AFE_PARAM_ID_POWER_MODE_CONFIG; + param_info.param_size = sizeof(power_mode_cfg); + + power_mode_cfg.power_mode_cfg_minor_version = + AFE_API_VERSION_POWER_MODE_CONFIG; + power_mode_cfg.power_mode_enable = power_mode; + + ret = q6afe_pack_and_set_param_in_band(port_id, + q6audio_get_port_index(port_id), + param_info, (u8 *) &power_mode_cfg); + if (ret) { + pr_err("%s: AFE set power mode enable for port 0x%x failed %d\n", + __func__, port_id, ret); + return ret; + } + pr_debug("%s: AFE set power mode 0x%x enable for port 0x%x ret %d\n", + __func__, power_mode, port_id, ret); + trace_printk("%s: AFE set power mode 0x%x enable for port 0x%x ret %d\n", + __func__, power_mode, port_id, ret); + return ret; +} +EXPORT_SYMBOL(afe_send_port_power_mode); static int afe_get_island_mode(u16 port_id, u32 *island_mode) { @@ -2892,6 +2968,11 @@ int afe_send_port_island_mode(u16 port_id) __func__, port_id); return ret; } + if (island_mode == 0) { + pr_debug("%s: AFE port[%d] island mode is not enabled\n", + __func__, port_id); + return ret; + } param_info.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE; param_info.instance_id = INSTANCE_ID_0; param_info.param_id = AFE_PARAM_ID_ISLAND_CONFIG; @@ -4239,6 +4320,55 @@ void afe_set_island_mode_cfg(u16 port_id, u32 enable_flag) } EXPORT_SYMBOL(afe_set_island_mode_cfg); +/** + * afe_get_power_mode_cfg - + * get power mode configuration + * @port_id: AFE port id number + * @enable_flag: Enable or Disable + */ +int afe_get_power_mode_cfg(u16 port_id, u32 *enable_flag) +{ + uint16_t port_index; + int ret = 0; + + if (enable_flag) { + port_index = afe_get_port_index(port_id); + if (port_index < 0 || port_index >= AFE_MAX_PORTS) { + pr_err("%s: AFE port index[%d] invalid!\n", + __func__, port_index); + return -EINVAL; + } + *enable_flag = this_afe.power_mode[port_index]; + } + return ret; +} +EXPORT_SYMBOL(afe_get_power_mode_cfg); + +/** + * afe_set_power_mode_cfg - + * set power mode configuration + * @port_id: AFE port id number + * @enable_flag: Enable or Disable + */ +int afe_set_power_mode_cfg(u16 port_id, u32 enable_flag) +{ + uint16_t port_index; + int ret= 0; + + port_index = afe_get_port_index(port_id); + if (port_index < 0 || port_index >= AFE_MAX_PORTS) { + pr_err("%s: AFE port index[%d] invalid!\n", + __func__, port_index); + return -EINVAL; + } + this_afe.power_mode[port_index] = enable_flag; + + trace_printk("%s: set power mode cfg 0x%x for port 0x%x\n", + __func__, this_afe.power_mode[port_index], port_id); + return ret; +} +EXPORT_SYMBOL(afe_set_power_mode_cfg); + /** * afe_set_routing_callback - * Update callback function for routing @@ -10199,6 +10329,7 @@ int __init afe_init(void) this_afe.afe_sample_rates[i] = 0; this_afe.dev_acdb_id[i] = 0; this_afe.island_mode[i] = 0; + this_afe.power_mode[i] = 0; this_afe.vad_cfg[i].is_enable = 0; this_afe.vad_cfg[i].pre_roll = 0; init_waitqueue_head(&this_afe.wait[i]); diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h index 2860016c6e..54892a7687 100644 --- a/include/dsp/apr_audio-v2.h +++ b/include/dsp/apr_audio-v2.h @@ -4876,6 +4876,9 @@ struct avs_dec_congestion_buffer_param_t { /* Payload of the AFE_PARAM_ID_ISLAND_CONFIG parameter used by * AFE_MODULE_AUDIO_DEV_INTERFACE. */ + +#define AFE_PARAM_ID_POWER_MODE_CONFIG 0x0002002c +#define AFE_API_VERSION_POWER_MODE_CONFIG 0x1 struct afe_param_id_island_cfg_t { uint32_t island_cfg_minor_version; /* Tracks the configuration of this parameter. @@ -4889,6 +4892,19 @@ struct afe_param_id_island_cfg_t { */ } __packed; +struct afe_param_id_power_mode_cfg_t { + uint32_t power_mode_cfg_minor_version; + /* Tracks the configuration of this parameter + * Supported values: #AFE_API_VERSION_POWER_MODE_CONFIG + */ + + uint32_t power_mode_enable; + /* Specifies whether island mode should be enabled or disabled for the + * use-case being setup. + * Supported values: 0 - Disable, 1 - Enable + */ +} __packed; + /* ID of the parameter used by #AFE_MODULE_AUDIO_DEV_INTERFACE to configure * the Codec DMA interface. */ diff --git a/include/dsp/q6afe-v2.h b/include/dsp/q6afe-v2.h index d8fcaeaf6c..3d3fa00e4d 100644 --- a/include/dsp/q6afe-v2.h +++ b/include/dsp/q6afe-v2.h @@ -396,6 +396,8 @@ void afe_set_vad_cfg(u32 vad_enable, u32 preroll_config, void afe_set_island_mode_cfg(u16 port_id, u32 enable_flag); void afe_get_island_mode_cfg(u16 port_id, u32 *enable_flag); int afe_send_cdc_dma_data_align(u16 port_id, u32 cdc_dma_data_align); +int afe_set_power_mode_cfg(u16 port_id, u32 enable_flag); +int afe_get_power_mode_cfg(u16 port_id, u32 *enable_flag); int afe_port_start(u16 port_id, union afe_port_config *afe_config, u32 rate); int afe_set_tws_channel_mode(u32 foramt, u16 port_id, u32 channel_mode); @@ -482,6 +484,7 @@ int afe_get_sp_rx_tmax_xmax_logging_data( u16 port_id); int afe_cal_init_hwdep(void *card); int afe_send_port_island_mode(u16 port_id); +int afe_send_port_power_mode(u16 port_id); int afe_send_port_vad_cfg_params(u16 port_id); int afe_send_cmd_wakeup_register(void *handle, bool enable); void afe_register_wakeup_irq_callback( From 02b06f5634d3623acab501c135e16ab34e5207b3 Mon Sep 17 00:00:00 2001 From: Kunlei Zhang Date: Thu, 28 May 2020 15:46:33 +0800 Subject: [PATCH 037/116] asoc: lahaina: add support to send power mode for voice usecase Add support in lahaina machine driver to send power mode along with island for voice usecase. Change-Id: I4223bc7e36644e3843995832798683017de22ece Signed-off-by: Kunlei Zhang --- asoc/lahaina.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/asoc/lahaina.c b/asoc/lahaina.c index f026c5c3d3..9387f95903 100644 --- a/asoc/lahaina.c +++ b/asoc/lahaina.c @@ -2723,6 +2723,63 @@ static int msm_get_port_id(int be_id) case MSM_BACKEND_DAI_VA_CDC_DMA_TX_2: afe_port_id = AFE_PORT_ID_VA_CODEC_DMA_TX_2; break; + case MSM_BACKEND_DAI_WSA_CDC_DMA_RX_0: + afe_port_id = AFE_PORT_ID_WSA_CODEC_DMA_RX_0; + break; + case MSM_BACKEND_DAI_WSA_CDC_DMA_TX_0: + afe_port_id = AFE_PORT_ID_WSA_CODEC_DMA_TX_0; + break; + case MSM_BACKEND_DAI_WSA_CDC_DMA_RX_1: + afe_port_id = AFE_PORT_ID_WSA_CODEC_DMA_RX_1; + break; + case MSM_BACKEND_DAI_WSA_CDC_DMA_TX_1: + afe_port_id = AFE_PORT_ID_WSA_CODEC_DMA_TX_1; + break; + case MSM_BACKEND_DAI_WSA_CDC_DMA_TX_2: + afe_port_id = AFE_PORT_ID_WSA_CODEC_DMA_TX_2; + break; + case MSM_BACKEND_DAI_RX_CDC_DMA_RX_0: + afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_0; + break; + case MSM_BACKEND_DAI_TX_CDC_DMA_TX_0: + afe_port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_0; + break; + case MSM_BACKEND_DAI_RX_CDC_DMA_RX_1: + afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_1; + break; + case MSM_BACKEND_DAI_TX_CDC_DMA_TX_1: + afe_port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_1; + break; + case MSM_BACKEND_DAI_RX_CDC_DMA_RX_2: + afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_2; + break; + case MSM_BACKEND_DAI_TX_CDC_DMA_TX_2: + afe_port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_2; + break; + case MSM_BACKEND_DAI_RX_CDC_DMA_RX_3: + afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_3; + break; + case MSM_BACKEND_DAI_TX_CDC_DMA_TX_3: + afe_port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_3; + break; + case MSM_BACKEND_DAI_RX_CDC_DMA_RX_4: + afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_4; + break; + case MSM_BACKEND_DAI_TX_CDC_DMA_TX_4: + afe_port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_4; + break; + case MSM_BACKEND_DAI_RX_CDC_DMA_RX_5: + afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_5; + break; + case MSM_BACKEND_DAI_TX_CDC_DMA_TX_5: + afe_port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_5; + break; + case MSM_BACKEND_DAI_RX_CDC_DMA_RX_6: + afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_6; + break; + case MSM_BACKEND_DAI_RX_CDC_DMA_RX_7: + afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_7; + break; default: pr_err("%s: Invalid BE id: %d\n", __func__, be_id); afe_port_id = -EINVAL; @@ -4124,6 +4181,38 @@ static int lahaina_send_island_va_config(int32_t be_id) return rc; } +static int lahaina_send_power_mode(int32_t be_id) +{ + int rc = 0; + int port_id = 0xFFFF; + + port_id = msm_get_port_id(be_id); + if (port_id < 0) { + pr_err("%s: Invalid power interface, be_id: %d\n", + __func__, be_id); + rc = -EINVAL; + } else { + /* + * send island mode config + * This should be the first configuration + * + */ + rc = afe_send_port_island_mode(port_id); + if (rc) + pr_err("%s: afe send island mode failed %d\n", + __func__, rc); + /* + * send power mode config + * This should be set after island configuration + */ + rc = afe_send_port_power_mode(port_id); + if (rc) + pr_err("%s: afe send power mode failed %d\n", + __func__, rc); + } + return rc; +} + static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -4887,6 +4976,12 @@ static int msm_snd_cdc_dma_startup(struct snd_pcm_substream *substream) pr_err("%s: send island va cfg failed, err: %d\n", __func__, ret); break; + default: + ret = lahaina_send_power_mode(dai_link->id); + if (ret) + pr_err("%s: send power mode failed, err: %d\n", + __func__, ret); + break; } return ret; From 346cb8b0e9ce16dd91b94a0b0ece99ab7421369f Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Wed, 13 May 2020 18:44:49 +0530 Subject: [PATCH 038/116] asoc: wsa-macro: Fix mixing path on WSA Standalone mixing path on WSA is mute. Enable soundwire path is not happening, add respective call in mixing path widget callback to setup soundwire and WSA. Change-Id: Ia8df0fdcc4a022e4b86c11283dd3606412a2fb69 Signed-off-by: Laxminath Kasam --- asoc/codecs/bolero/wsa-macro.c | 81 +++++++++++++++++----------------- 1 file changed, 40 insertions(+), 41 deletions(-) diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c index 7579957aa4..697a704555 100644 --- a/asoc/codecs/bolero/wsa-macro.c +++ b/asoc/codecs/bolero/wsa-macro.c @@ -1178,45 +1178,6 @@ static int wsa_macro_enable_vi_feedback(struct snd_soc_dapm_widget *w, return 0; } -static int wsa_macro_enable_mix_path(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_component *component = - snd_soc_dapm_to_component(w->dapm); - u16 gain_reg; - int offset_val = 0; - int val = 0; - - dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name); - - switch (w->reg) { - case BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL: - gain_reg = BOLERO_CDC_WSA_RX0_RX_VOL_MIX_CTL; - break; - case BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL: - gain_reg = BOLERO_CDC_WSA_RX1_RX_VOL_MIX_CTL; - break; - default: - dev_err(component->dev, "%s: No gain register avail for %s\n", - __func__, w->name); - return 0; - } - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - val = snd_soc_component_read32(component, gain_reg); - val += offset_val; - snd_soc_component_write(component, gain_reg, val); - break; - case SND_SOC_DAPM_POST_PMD: - snd_soc_component_update_bits(component, - w->reg, 0x20, 0x00); - break; - } - - return 0; -} - static void wsa_macro_hd2_control(struct snd_soc_component *component, u16 reg, int event) { @@ -1303,6 +1264,44 @@ static int wsa_macro_enable_swr(struct snd_soc_dapm_widget *w, return 0; } +static int wsa_macro_enable_mix_path(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + u16 gain_reg; + int offset_val = 0; + int val = 0; + + dev_dbg(component->dev, "%s %d %s\n", __func__, event, w->name); + + if (!(strcmp(w->name, "WSA_RX0 MIX INP"))) { + gain_reg = BOLERO_CDC_WSA_RX0_RX_VOL_MIX_CTL; + } else if (!(strcmp(w->name, "WSA_RX1 MIX INP"))) { + gain_reg = BOLERO_CDC_WSA_RX1_RX_VOL_MIX_CTL; + } else { + dev_err(component->dev, "%s: No gain register avail for %s\n", + __func__, w->name); + return 0; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + wsa_macro_enable_swr(w, kcontrol, event); + val = snd_soc_component_read32(component, gain_reg); + val += offset_val; + snd_soc_component_write(component, gain_reg, val); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_component_update_bits(component, + w->reg, 0x20, 0x00); + wsa_macro_enable_swr(w, kcontrol, event); + break; + } + + return 0; +} + static int wsa_macro_config_compander(struct snd_soc_component *component, int comp, int event) { @@ -2550,7 +2549,7 @@ static const struct snd_soc_dapm_widget wsa_macro_dapm_widgets[] = { SND_SOC_DAPM_MUX_E("WSA_RX0 INP2", SND_SOC_NOPM, 0, 0, &rx0_prim_inp2_mux, wsa_macro_enable_swr, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL, + SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", SND_SOC_NOPM, 0, 0, &rx0_mix_mux, wsa_macro_enable_mix_path, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MUX_E("WSA_RX1 INP0", SND_SOC_NOPM, 0, 0, @@ -2562,7 +2561,7 @@ static const struct snd_soc_dapm_widget wsa_macro_dapm_widgets[] = { SND_SOC_DAPM_MUX_E("WSA_RX1 INP2", SND_SOC_NOPM, 0, 0, &rx1_prim_inp2_mux, wsa_macro_enable_swr, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL, + SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", SND_SOC_NOPM, 0, 0, &rx1_mix_mux, wsa_macro_enable_mix_path, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MIXER_E("WSA_RX INT0 MIX", SND_SOC_NOPM, From fe3356fa53976c562833fae8b07aaae03462214b Mon Sep 17 00:00:00 2001 From: Sanjana B Date: Wed, 11 Sep 2019 09:28:32 +0530 Subject: [PATCH 039/116] asoc: ep92: add support for DSD input Add sysfs nodes for dsd rate and update audio format sysfs node. Change-Id: Iefa09f0042bb244e42ee0bf788344d31df690af8 Signed-off-by: Sanjana B --- asoc/codecs/ep92/ep92.c | 50 +++++++++++++++++++++++++++++++++++++++-- asoc/codecs/ep92/ep92.h | 6 ++++- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/asoc/codecs/ep92/ep92.c b/asoc/codecs/ep92/ep92.c index 6077070441..07a3281893 100644 --- a/asoc/codecs/ep92/ep92.c +++ b/asoc/codecs/ep92/ep92.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #include @@ -40,6 +40,10 @@ static const unsigned int ep92_samp_freq_table[8] = { 32000, 44100, 48000, 88200, 96000, 176400, 192000, 768000 }; +static const unsigned int ep92_dsd_freq_table[4] = { + 64, 128, 256, 0 +}; + static bool ep92_volatile_register(struct device *dev, unsigned int reg) { /* do not cache register state in regmap */ @@ -549,6 +553,23 @@ static void ep92_read_audio_info(struct snd_soc_component *component, send_uevent = true; } + old = ep92->ai.system_status_1; + ep92->ai.system_status_1 = snd_soc_read(codec, + EP92_AUDIO_INFO_SYSTEM_STATUS_1); + if (ep92->ai.system_status_1 == 0xff) { + dev_dbg(codec->dev, + "ep92 EP92_AUDIO_INFO_SYSTEM_STATUS_1 read 0xff\n"); + ep92->ai.system_status_1 = old; + } + change = ep92->ai.system_status_1 ^ old; + if (change & EP92_AI_DSD_RATE_MASK) { + dev_dbg(codec->dev, "ep92 dsd rate changed to %d\n", + ep92_dsd_freq_table[(ep92->ai.system_status_1 & + EP92_AI_DSD_RATE_MASK) + >> EP92_AI_DSD_RATE_SHIFT]); + send_uevent = true; + } + old = ep92->ai.audio_status; ep92->ai.audio_status = snd_soc_component_read32(component, EP92_AUDIO_INFO_AUDIO_STATUS); @@ -580,7 +601,9 @@ static void ep92_read_audio_info(struct snd_soc_component *component, } new_mode = ep92->old_mode; - if (ep92->ai.audio_status & EP92_AI_STD_ADO_MASK) { + if (ep92->ai.audio_status & EP92_AI_DSD_ADO_MASK) + new_mode = 2; /* One bit audio */ + else if (ep92->ai.audio_status & EP92_AI_STD_ADO_MASK) { if (ep92->ai.cs[0] & EP92_AI_NPCM_MASK) new_mode = 1; /* Compr */ else @@ -897,6 +920,27 @@ static ssize_t ep92_sysfs_rda_audio_format(struct device *dev, return ret; } +static ssize_t ep92_sysfs_rda_dsd_rate(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + int val; + struct ep92_pdata *ep92 = dev_get_drvdata(dev); + + if (!ep92 || !ep92->codec) { + dev_err(dev, "%s: device error\n", __func__); + return -ENODEV; + } + + val = ep92_dsd_freq_table[(ep92->ai.system_status_1 & + EP92_AI_DSD_RATE_MASK) >> EP92_AI_DSD_RATE_SHIFT]; + + ret = snprintf(buf, EP92_SYSFS_ENTRY_MAX_LEN, "%d\n", val); + dev_dbg(dev, "%s: '%d'\n", __func__, val); + + return ret; +} + static ssize_t ep92_sysfs_rda_audio_rate(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1621,6 +1665,7 @@ static DEVICE_ATTR(cec_volume, 0644, ep92_sysfs_rda_cec_volume, static DEVICE_ATTR(runout, 0444, ep92_sysfs_rda_runout, NULL); static DEVICE_ATTR(force_inactive, 0644, ep92_sysfs_rda_force_inactive, ep92_sysfs_wta_force_inactive); +static DEVICE_ATTR(dsd_rate, 0444, ep92_sysfs_rda_dsd_rate, NULL); static struct attribute *ep92_fs_attrs[] = { &dev_attr_chipid.attr, @@ -1647,6 +1692,7 @@ static struct attribute *ep92_fs_attrs[] = { &dev_attr_cec_volume.attr, &dev_attr_runout.attr, &dev_attr_force_inactive.attr, + &dev_attr_dsd_rate.attr, NULL, }; diff --git a/asoc/codecs/ep92/ep92.h b/asoc/codecs/ep92/ep92.h index 18cb0105f5..22384fbb67 100644 --- a/asoc/codecs/ep92/ep92.h +++ b/asoc/codecs/ep92/ep92.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef __EP92_H__ @@ -175,6 +175,10 @@ static struct reg_default ep92_reg_defaults[] = { #define EP92_AI_PREEMPH_MASK 0x38 #define EP92_AI_CH_COUNT_MASK 0x07 #define EP92_AI_CH_ALLOC_MASK 0xff +#define EP92_AI_DSD_ADO_SHIFT 4 +#define EP92_AI_DSD_ADO_MASK 0x10 +#define EP92_AI_DSD_RATE_SHIFT 4 +#define EP92_AI_DSD_RATE_MASK 0x30 #define EP92_2CHOICE_MASK 1 #define EP92_GC_CEC_VOLUME_MIN 0 From 79fba80fa6a8ff441dbc40d00db4503bde8b9a89 Mon Sep 17 00:00:00 2001 From: Sanjana B Date: Thu, 28 Nov 2019 14:45:10 +0530 Subject: [PATCH 040/116] asoc: msm-cdc-pinctrl: Add alternate pinctrl state for DSD input Add additional pinctrl states to support alternative function. This change enables support of alternative pins through pinctrl framework. Change-Id: I1f3f9a13345846f1714b4ecaeecde975b5cf6813 Signed-off-by: Sanjana B --- asoc/codecs/msm-cdc-pinctrl.c | 36 +++++++++++++++++++++++++++++++++- include/asoc/msm-cdc-pinctrl.h | 7 ++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/asoc/codecs/msm-cdc-pinctrl.c b/asoc/codecs/msm-cdc-pinctrl.c index 88121fd1e7..9f90a84337 100644 --- a/asoc/codecs/msm-cdc-pinctrl.c +++ b/asoc/codecs/msm-cdc-pinctrl.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #include @@ -21,6 +21,7 @@ struct msm_cdc_pinctrl_info { struct pinctrl *pinctrl; struct pinctrl_state *pinctrl_active; struct pinctrl_state *pinctrl_sleep; + struct pinctrl_state *pinctrl_alt_active; int gpio; bool state; u32 tlmm_gpio[MAX_GPIOS]; @@ -104,6 +105,31 @@ int msm_cdc_pinctrl_select_sleep_state(struct device_node *np) } EXPORT_SYMBOL(msm_cdc_pinctrl_select_sleep_state); +/* + * msm_cdc_pinctrl_select_alt_active_state: select pinctrl alt_active state + * @np: pointer to struct device_node + * + * Returns error code for failure + */ +int msm_cdc_pinctrl_select_alt_active_state(struct device_node *np) +{ + struct msm_cdc_pinctrl_info *gpio_data; + + gpio_data = msm_cdc_pinctrl_get_gpiodata(np); + if (!gpio_data) + return -EINVAL; + + if (!gpio_data->pinctrl_alt_active) { + pr_err("%s: pinctrl alt_active state is null\n", __func__); + return -EINVAL; + } + gpio_data->state = true; + + return pinctrl_select_state(gpio_data->pinctrl, + gpio_data->pinctrl_alt_active); +} +EXPORT_SYMBOL(msm_cdc_pinctrl_select_alt_active_state); + /* * msm_cdc_pinctrl_select_active_state: select pinctrl active state * @np: pointer to struct device_node @@ -231,6 +257,14 @@ static int msm_cdc_pinctrl_probe(struct platform_device *pdev) ret = PTR_ERR(gpio_data->pinctrl_sleep); goto err_lookup_state; } + + gpio_data->pinctrl_alt_active = pinctrl_lookup_state( + gpio_data->pinctrl, "aud_alt_active"); + if (IS_ERR_OR_NULL(gpio_data->pinctrl_alt_active)) { + dev_dbg(&pdev->dev, "%s: Cannot get aud_alt_active pinctrl state:%ld\n", + __func__, PTR_ERR(gpio_data->pinctrl_alt_active)); + } + /* skip setting to sleep state for LPI_TLMM GPIOs */ if (!of_property_read_bool(pdev->dev.of_node, "qcom,lpi-gpios")) { /* Set pinctrl state to aud_sleep by default */ diff --git a/include/asoc/msm-cdc-pinctrl.h b/include/asoc/msm-cdc-pinctrl.h index 89fe699ccb..3179a8408e 100644 --- a/include/asoc/msm-cdc-pinctrl.h +++ b/include/asoc/msm-cdc-pinctrl.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef __MFD_CDC_PINCTRL_H_ @@ -11,6 +11,7 @@ #if IS_ENABLED(CONFIG_MSM_CDC_PINCTRL) extern int msm_cdc_pinctrl_select_sleep_state(struct device_node *np); extern int msm_cdc_pinctrl_select_active_state(struct device_node *np); +extern int msm_cdc_pinctrl_select_alt_active_state(struct device_node *np); extern int msm_cdc_pinctrl_get_state(struct device_node *np); extern int msm_cdc_get_gpio_state(struct device_node *np); extern int msm_cdc_pinctrl_set_wakeup_capable(struct device_node *np, @@ -27,6 +28,10 @@ int msm_cdc_pinctrl_select_active_state(struct device_node *np) { return 0; } +int msm_cdc_pinctrl_select_alt_active_state(struct device_node *np) +{ + return 0; +} int msm_cdc_get_gpio_state(struct device_node *np) { return 0; From 7f953e1270c7ef244fc79a89f5a96536c8e29860 Mon Sep 17 00:00:00 2001 From: Sanjana B Date: Mon, 20 Jan 2020 19:31:18 +0530 Subject: [PATCH 041/116] asoc: support for audio over hdmi tx Add support for audio over hdmi tx. Change-Id: I4f2108fd14eb22ec4e226220787e0defe512bb5f Signed-off-by: Sanjana B --- asoc/codecs/msm_hdmi_codec_rx.c | 99 ++++++++++++++++++---- asoc/msm-dai-q6-hdmi-v2.c | 34 +++++++- asoc/msm-pcm-routing-v2.c | 141 +++++++++++++++++++++++++++++++- asoc/msm-pcm-routing-v2.h | 4 +- dsp/q6afe.c | 5 ++ dsp/q6audio-v2.c | 4 + include/dsp/apr_audio-v2.h | 3 + include/dsp/q6afe-v2.h | 2 + 8 files changed, 271 insertions(+), 21 deletions(-) diff --git a/asoc/codecs/msm_hdmi_codec_rx.c b/asoc/codecs/msm_hdmi_codec_rx.c index 1588c56767..609dd45ea3 100644 --- a/asoc/codecs/msm_hdmi_codec_rx.c +++ b/asoc/codecs/msm_hdmi_codec_rx.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. */ #include #include @@ -25,8 +25,8 @@ static SOC_ENUM_SINGLE_DECL(ext_disp_audio_ack_state##index, \ SND_SOC_NOPM, index, ext_disp_audio_ack_text) -#define SWITCH_DP_CODEC(codec_info, codec_data, dai_id) \ - codec_info.type = EXT_DISPLAY_TYPE_DP; \ +#define SWITCH_DP_CODEC(codec_info, codec_data, dai_id, type) \ + codec_info.type = type; \ codec_info.ctrl_id = codec_data->ctl[dai_id]; \ codec_info.stream_id = codec_data->stream[dai_id]; \ @@ -38,6 +38,7 @@ enum { enum { DP_STREAM0 = 0, DP_STREAM1, + HDMI, DP_STREAM_MAX, }; @@ -49,6 +50,7 @@ enum { DP_DAI1 = 1, DP_DAI2, HDMI_DAI, + HDMI_MS_DAI, DP_DAI_MAX, }; @@ -60,6 +62,8 @@ SOC_EXT_DISP_AUDIO_TYPE(1); SOC_EXT_DISP_AUDIO_ACK_STATE(1); SOC_EXT_DISP_AUDIO_TYPE(2); SOC_EXT_DISP_AUDIO_ACK_STATE(2); +SOC_EXT_DISP_AUDIO_TYPE(3); +SOC_EXT_DISP_AUDIO_ACK_STATE(3); struct msm_ext_disp_audio_codec_rx_data { struct platform_device *ext_disp_core_pdev; @@ -80,6 +84,7 @@ static int msm_ext_disp_edid_ctl_info(struct snd_kcontrol *kcontrol, int rc = 0; struct msm_ext_disp_codec_id codec_info; int dai_id = kcontrol->private_value; + int type; codec_data = snd_soc_component_get_drvdata(component); if (!codec_data) { @@ -91,7 +96,11 @@ static int msm_ext_disp_edid_ctl_info(struct snd_kcontrol *kcontrol, codec_data->ctl[dai_id], codec_data->stream[dai_id]); mutex_lock(&codec_data->dp_ops_lock); - SWITCH_DP_CODEC(codec_info, codec_data, dai_id); + if (dai_id == HDMI_MS_DAI) + type = EXT_DISPLAY_TYPE_HDMI; + else + type = EXT_DISPLAY_TYPE_DP; + SWITCH_DP_CODEC(codec_info, codec_data, dai_id, type); rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev, &codec_info); if (!codec_data->ext_disp_ops.get_audio_edid_blk || rc) { @@ -126,6 +135,7 @@ static int msm_ext_disp_edid_get(struct snd_kcontrol *kcontrol, struct msm_ext_disp_codec_id codec_info; int rc = 0; int dai_id = kcontrol->private_value; + int type; codec_data = snd_soc_component_get_drvdata(component); if (!codec_data) { @@ -138,7 +148,11 @@ static int msm_ext_disp_edid_get(struct snd_kcontrol *kcontrol, codec_data->ctl[dai_id], codec_data->stream[dai_id]); mutex_lock(&codec_data->dp_ops_lock); - SWITCH_DP_CODEC(codec_info, codec_data, dai_id); + if (dai_id == HDMI_MS_DAI) + type = EXT_DISPLAY_TYPE_HDMI; + else + type = EXT_DISPLAY_TYPE_DP; + SWITCH_DP_CODEC(codec_info, codec_data, dai_id, type); rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev, &codec_info); if (!codec_data->ext_disp_ops.get_audio_edid_blk || rc) { @@ -147,7 +161,6 @@ static int msm_ext_disp_edid_get(struct snd_kcontrol *kcontrol, mutex_unlock(&codec_data->dp_ops_lock); return -EINVAL; } - rc = codec_data->ext_disp_ops.get_audio_edid_blk( codec_data->ext_disp_core_pdev, &edid_blk); mutex_unlock(&codec_data->dp_ops_lock); @@ -188,6 +201,7 @@ static int msm_ext_disp_audio_type_get(struct snd_kcontrol *kcontrol, struct msm_ext_disp_codec_id codec_info; int rc = 0; int dai_id = ((struct soc_enum *) kcontrol->private_value)->shift_l; + int type; codec_data = snd_soc_component_get_drvdata(component); if (!codec_data) { @@ -200,7 +214,11 @@ static int msm_ext_disp_audio_type_get(struct snd_kcontrol *kcontrol, codec_data->ctl[dai_id], codec_data->stream[dai_id]); mutex_lock(&codec_data->dp_ops_lock); - SWITCH_DP_CODEC(codec_info, codec_data, dai_id); + if (dai_id == HDMI_MS_DAI) + type = EXT_DISPLAY_TYPE_HDMI; + else + type = EXT_DISPLAY_TYPE_DP; + SWITCH_DP_CODEC(codec_info, codec_data, dai_id, type); rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev, &codec_info); @@ -213,7 +231,7 @@ static int msm_ext_disp_audio_type_get(struct snd_kcontrol *kcontrol, } cable_state = codec_data->ext_disp_ops.cable_status( - codec_data->ext_disp_core_pdev, 1); + codec_data->ext_disp_core_pdev, 1); if (cable_state < 0) { dev_err(component->dev, "%s: Error retrieving cable state from ext_disp, err:%d\n", __func__, cable_state); @@ -274,6 +292,7 @@ static int msm_ext_disp_audio_ack_set(struct snd_kcontrol *kcontrol, struct msm_ext_disp_codec_id codec_info; int rc = 0; int dai_id = ((struct soc_enum *) kcontrol->private_value)->shift_l; + int type; codec_data = snd_soc_component_get_drvdata(component); if (!codec_data) { @@ -287,7 +306,11 @@ static int msm_ext_disp_audio_ack_set(struct snd_kcontrol *kcontrol, codec_data->ctl[dai_id], codec_data->stream[dai_id]); mutex_lock(&codec_data->dp_ops_lock); - SWITCH_DP_CODEC(codec_info, codec_data, dai_id); + if (dai_id == HDMI_MS_DAI) + type = EXT_DISPLAY_TYPE_HDMI; + else + type = EXT_DISPLAY_TYPE_DP; + SWITCH_DP_CODEC(codec_info, codec_data, dai_id, type); rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev, &codec_info); @@ -421,6 +444,15 @@ static const struct snd_kcontrol_new msm_ext_disp_codec_rx_controls[] = { .get = msm_ext_disp_edid_get, .private_value = HDMI_DAI, }, + { + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "HDMI MS EDID", + .info = msm_ext_disp_edid_ctl_info, + .get = msm_ext_disp_edid_get, + .private_value = HDMI_MS_DAI, + }, { .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, @@ -445,12 +477,18 @@ static const struct snd_kcontrol_new msm_ext_disp_codec_rx_controls[] = { SOC_ENUM_EXT("External Display1 Type", ext_disp_audio_type2, msm_ext_disp_audio_type_get, NULL), + SOC_ENUM_EXT("External HDMI Type", + ext_disp_audio_type3, + msm_ext_disp_audio_type_get, NULL), SOC_ENUM_EXT("External Display Audio Ack", ext_disp_audio_ack_state1, NULL, msm_ext_disp_audio_ack_set), SOC_ENUM_EXT("External Display1 Audio Ack", ext_disp_audio_ack_state2, NULL, msm_ext_disp_audio_ack_set), + SOC_ENUM_EXT("External HDMI Audio Ack", + ext_disp_audio_ack_state3, + NULL, msm_ext_disp_audio_ack_set), SOC_SINGLE_MULTI_EXT("External Display Audio Device", SND_SOC_NOPM, DP_DAI1, DP_STREAM_MAX - 1, 0, 2, @@ -460,6 +498,11 @@ static const struct snd_kcontrol_new msm_ext_disp_codec_rx_controls[] = { SND_SOC_NOPM, DP_DAI2, DP_STREAM_MAX - 1, 0, 2, msm_ext_disp_audio_device_get, msm_ext_disp_audio_device_set), + SOC_SINGLE_MULTI_EXT("External HDMI Device", + SND_SOC_NOPM, HDMI_MS_DAI, DP_STREAM_MAX - 1, 0, 2, + msm_ext_disp_audio_device_get, + msm_ext_disp_audio_device_set), + }; static int msm_ext_disp_audio_codec_rx_dai_startup( @@ -470,6 +513,7 @@ static int msm_ext_disp_audio_codec_rx_dai_startup( struct msm_ext_disp_codec_id codec_info; struct msm_ext_disp_audio_codec_rx_data *codec_data = dev_get_drvdata(dai->component->dev); + int type; if (!codec_data) { dev_err(dai->dev, "%s() codec_data is null\n", @@ -482,7 +526,11 @@ static int msm_ext_disp_audio_codec_rx_dai_startup( codec_data->ctl[dai->id], codec_data->stream[dai->id]); mutex_lock(&codec_data->dp_ops_lock); - SWITCH_DP_CODEC(codec_info, codec_data, dai->id); + if (dai->id == HDMI_MS_DAI) + type = EXT_DISPLAY_TYPE_HDMI; + else + type = EXT_DISPLAY_TYPE_DP; + SWITCH_DP_CODEC(codec_info, codec_data, dai->id, type); rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev, &codec_info); @@ -524,7 +572,7 @@ static int msm_ext_disp_audio_codec_rx_dai_hw_params( struct msm_ext_disp_codec_id codec_info; int rc = 0; struct msm_ext_disp_audio_setup_params audio_setup_params = {0}; - + int type; struct msm_ext_disp_audio_codec_rx_data *codec_data = dev_get_drvdata(dai->component->dev); @@ -539,7 +587,11 @@ static int msm_ext_disp_audio_codec_rx_dai_hw_params( codec_data->ctl[dai->id], codec_data->stream[dai->id]); mutex_lock(&codec_data->dp_ops_lock); - SWITCH_DP_CODEC(codec_info, codec_data, dai->id); + if (dai->id == HDMI_MS_DAI) + type = EXT_DISPLAY_TYPE_HDMI; + else + type = EXT_DISPLAY_TYPE_DP; + SWITCH_DP_CODEC(codec_info, codec_data, dai->id, type); rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev, &codec_info); @@ -609,7 +661,7 @@ static int msm_ext_disp_audio_codec_rx_dai_hw_params( audio_setup_params.down_mix = down_mix; mutex_lock(&codec_data->dp_ops_lock); - SWITCH_DP_CODEC(codec_info, codec_data, dai->id); + SWITCH_DP_CODEC(codec_info, codec_data, dai->id, type); rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev, &codec_info); if (rc) @@ -636,6 +688,7 @@ static void msm_ext_disp_audio_codec_rx_dai_shutdown( struct msm_ext_disp_audio_codec_rx_data *codec_data = dev_get_drvdata(dai->component->dev); + int type; if (!codec_data) { dev_err(dai->dev, "%s() codec_data is null\n", @@ -648,7 +701,11 @@ static void msm_ext_disp_audio_codec_rx_dai_shutdown( codec_data->ctl[dai->id], codec_data->stream[dai->id]); mutex_lock(&codec_data->dp_ops_lock); - SWITCH_DP_CODEC(codec_info, codec_data, dai->id); + if (dai->id == HDMI_MS_DAI) + type = EXT_DISPLAY_TYPE_HDMI; + else + type = EXT_DISPLAY_TYPE_DP; + SWITCH_DP_CODEC(codec_info, codec_data, dai->id, type); rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev, &codec_info); @@ -754,6 +811,20 @@ static struct snd_soc_dai_driver msm_ext_disp_audio_codec_rx_dais[] = { }, .ops = &msm_ext_disp_audio_codec_rx_dai_ops, }, + { + .name = "msm_hdmi_ms_audio_codec_rx_dai", + .id = HDMI_MS_DAI, + .playback = { + .stream_name = "HDMI MS Playback", + .channels_min = 1, + .channels_max = 8, + .rate_min = 48000, + .rate_max = 48000, + .rates = MSM_EXT_DISP_PCM_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .ops = &msm_ext_disp_audio_codec_rx_dai_ops, + }, { .name = "msm_dp_audio_codec_rx_dai", .id = DP_DAI1, diff --git a/asoc/msm-dai-q6-hdmi-v2.c b/asoc/msm-dai-q6-hdmi-v2.c index 664169bd8b..42d53e7219 100644 --- a/asoc/msm-dai-q6-hdmi-v2.c +++ b/asoc/msm-dai-q6-hdmi-v2.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. */ #include @@ -54,7 +54,7 @@ struct msm_dai_q6_hdmi_dai_data { static int get_port_id(int dai_id) { /* Currently, display devices share a common AFE port */ - if (dai_id != HDMI_RX) + if (dai_id != HDMI_RX || dai_id != HDMI_RX_MS) return DISPLAY_PORT_RX; return dai_id; @@ -436,7 +436,7 @@ static int msm_dai_q6_hdmi_dai_probe(struct snd_soc_dai *dai) msm_dai_q6_hdmi_set_dai_id(dai); - if (dai->driver->id == HDMI_RX) { + if (dai->driver->id == HDMI_RX || dai->driver->id == HDMI_RX_MS) { kcontrol = &hdmi_config_controls[0]; rc = snd_ctl_add(dai->component->card->snd_card, snd_ctl_new1(kcontrol, dai_data)); @@ -563,6 +563,28 @@ static struct snd_soc_dai_driver msm_dai_q6_hdmi_hdmi_rx_dai = { .remove = msm_dai_q6_hdmi_dai_remove, }; +static struct snd_soc_dai_driver msm_dai_q6_hdmi_hdmi_ms_rx_dai = { + .playback = { + .stream_name = "HDMI MS Playback", + .aif_name = "HDMI_MS", + .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .channels_min = 2, + .channels_max = 8, + .rate_max = 192000, + .rate_min = 48000, + }, + .ops = &msm_dai_q6_hdmi_ops, + .id = HDMI_RX_MS, + .probe = msm_dai_q6_hdmi_dai_probe, + .remove = msm_dai_q6_hdmi_dai_remove, +}; + static struct snd_soc_dai_driver msm_dai_q6_display_port_rx_dai[] = { { .playback = { @@ -646,6 +668,12 @@ static int msm_dai_q6_hdmi_dev_probe(struct platform_device *pdev) &msm_dai_hdmi_q6_component, &msm_dai_q6_display_port_rx_dai[1], 1); break; + case HDMI_RX_MS: + rc = snd_soc_register_component(&pdev->dev, + &msm_dai_hdmi_q6_component, + &msm_dai_q6_hdmi_hdmi_ms_rx_dai, 1); + break; + default: dev_err(&pdev->dev, "invalid device ID %d\n", pdev->id); rc = -ENODEV; diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c index 35b2a8bc31..82dc51bf51 100644 --- a/asoc/msm-pcm-routing-v2.c +++ b/asoc/msm-pcm-routing-v2.c @@ -147,6 +147,7 @@ struct msm_pcm_route_bdai_pp_params { static struct msm_pcm_route_bdai_pp_params msm_bedais_pp_params[MSM_BACKEND_DAI_PP_PARAMS_REQ_MAX] = { {HDMI_RX, 0, 0, 0}, + {HDMI_RX_MS, 0, 0, 0}, {DISPLAY_PORT_RX, 0, 0, 0}, }; @@ -699,6 +700,7 @@ struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = { LPASS_BE_SEC_META_MI2S_RX}, { RT_PROXY_PORT_002_RX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_PROXY_RX}, { RT_PROXY_PORT_002_TX, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_PROXY_TX}, + { HDMI_RX_MS, 0, {0}, {0}, 0, 0, 0, 0, LPASS_BE_HDMI_MS}, }; /* Track ASM playback & capture sessions of DAI @@ -3534,7 +3536,7 @@ static const char *const be_name[] = { "RX_CDC_DMA_RX_6", "RX_CDC_DMA_RX_7", "PRI_SPDIF_TX", "SEC_SPDIF_RX", "SEC_SPDIF_TX", "SLIM_9_RX", "SLIM_9_TX", "AFE_LOOPBACK_TX", "PRI_META_MI2S_RX", -"SEC_META_MI2S_RX", "PROXY_RX", "PROXY_TX" +"SEC_META_MI2S_RX", "PROXY_RX", "PROXY_TX", "HDMI_RX_MS" }; static SOC_ENUM_SINGLE_DECL(mm1_channel_mux, @@ -7549,6 +7551,101 @@ static const struct snd_kcontrol_new hdmi_mixer_controls[] = { msm_routing_put_audio_mixer), }; +static const struct snd_kcontrol_new hdmi_ms_mixer_controls[] = { + SOC_DOUBLE_EXT("MultiMedia1", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia2", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia3", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia4", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia5", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia6", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia7", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia8", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia9", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia10", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia11", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia12", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia13", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia14", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia15", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia16", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia17", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia18", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia19", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia26", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia28", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia29", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia30", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_FRONTEND_DAI_MULTIMEDIA30, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + static const struct snd_kcontrol_new display_port_mixer_controls[] = { SOC_DOUBLE_EXT("MultiMedia1", SND_SOC_NOPM, MSM_BACKEND_DAI_DISPLAY_PORT_RX, @@ -18458,6 +18555,13 @@ static const struct snd_kcontrol_new hdmi_rx_port_mixer_controls[] = { msm_routing_put_port_mixer), }; +static const struct snd_kcontrol_new hdmi_rx_ms_port_mixer_controls[] = { + SOC_DOUBLE_EXT("MI2S_TX", SND_SOC_NOPM, + MSM_BACKEND_DAI_HDMI_RX_MS, + MSM_BACKEND_DAI_MI2S_TX, 1, 0, msm_routing_get_port_mixer, + msm_routing_put_port_mixer), +}; + static const struct snd_kcontrol_new display_port_rx_port_mixer_controls[] = { SOC_DOUBLE_EXT("MI2S_TX", SND_SOC_NOPM, MSM_BACKEND_DAI_DISPLAY_PORT_RX, @@ -24225,6 +24329,7 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_AIF_OUT("SLIMBUS_2_RX", "Slimbus2 Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("SLIMBUS_5_RX", "Slimbus5 Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("HDMI", "HDMI Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("HDMI_MS", "HDMI MS Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("DISPLAY_PORT", "Display Port Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("DISPLAY_PORT1", "Display Port1 Playback", @@ -24673,6 +24778,8 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { slimbus_9_rx_mixer_controls, ARRAY_SIZE(slimbus_9_rx_mixer_controls)), SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0, hdmi_mixer_controls, ARRAY_SIZE(hdmi_mixer_controls)), + SND_SOC_DAPM_MIXER("HDMI_MS Mixer", SND_SOC_NOPM, 0, 0, + hdmi_ms_mixer_controls, ARRAY_SIZE(hdmi_ms_mixer_controls)), SND_SOC_DAPM_MIXER("DISPLAY_PORT Mixer", SND_SOC_NOPM, 0, 0, display_port_mixer_controls, ARRAY_SIZE(display_port_mixer_controls)), SND_SOC_DAPM_MIXER("DISPLAY_PORT1 Mixer", SND_SOC_NOPM, 0, 0, @@ -25125,6 +25232,9 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_MIXER("HDMI_RX Port Mixer", SND_SOC_NOPM, 0, 0, hdmi_rx_port_mixer_controls, ARRAY_SIZE(hdmi_rx_port_mixer_controls)), + SND_SOC_DAPM_MIXER("HDMI_RX_MS Port Mixer", + SND_SOC_NOPM, 0, 0, hdmi_rx_ms_port_mixer_controls, + ARRAY_SIZE(hdmi_rx_ms_port_mixer_controls)), SND_SOC_DAPM_MIXER("DISPLAY_PORT_RX Port Mixer", SND_SOC_NOPM, 0, 0, display_port_rx_port_mixer_controls, ARRAY_SIZE(display_port_rx_port_mixer_controls)), @@ -25666,6 +25776,25 @@ static const struct snd_soc_dapm_route intercon[] = { {"HDMI Mixer", "MultiMedia26", "MM_DL26"}, {"HDMI", NULL, "HDMI Mixer"}, + {"HDMI_MS Mixer", "MultiMedia1", "MM_DL1"}, + {"HDMI_MS Mixer", "MultiMedia2", "MM_DL2"}, + {"HDMI_MS Mixer", "MultiMedia3", "MM_DL3"}, + {"HDMI_MS Mixer", "MultiMedia4", "MM_DL4"}, + {"HDMI_MS Mixer", "MultiMedia5", "MM_DL5"}, + {"HDMI_MS Mixer", "MultiMedia6", "MM_DL6"}, + {"HDMI_MS Mixer", "MultiMedia7", "MM_DL7"}, + {"HDMI_MS Mixer", "MultiMedia8", "MM_DL8"}, + {"HDMI_MS Mixer", "MultiMedia9", "MM_DL9"}, + {"HDMI_MS Mixer", "MultiMedia10", "MM_DL10"}, + {"HDMI_MS Mixer", "MultiMedia11", "MM_DL11"}, + {"HDMI_MS Mixer", "MultiMedia12", "MM_DL12"}, + {"HDMI_MS Mixer", "MultiMedia13", "MM_DL13"}, + {"HDMI_MS Mixer", "MultiMedia14", "MM_DL14"}, + {"HDMI_MS Mixer", "MultiMedia15", "MM_DL15"}, + {"HDMI_MS Mixer", "MultiMedia16", "MM_DL16"}, + {"HDMI_MS Mixer", "MultiMedia26", "MM_DL26"}, + {"HDMI_MS", NULL, "HDMI_MS Mixer"}, + {"DISPLAY_PORT Mixer", "MultiMedia1", "MM_DL1"}, {"DISPLAY_PORT Mixer", "MultiMedia2", "MM_DL2"}, {"DISPLAY_PORT Mixer", "MultiMedia3", "MM_DL3"}, @@ -29345,6 +29474,9 @@ static const struct snd_soc_dapm_route intercon[] = { {"HDMI_RX Port Mixer", "MI2S_TX", "MI2S_TX"}, {"HDMI", NULL, "HDMI_RX Port Mixer"}, + {"HDMI_RX_MS Port Mixer", "MI2S_TX", "MI2S_TX"}, + {"HDMI_MS", NULL, "HDMI_RX_MS Port Mixer"}, + {"DISPLAY_PORT_RX Port Mixer", "MI2S_TX", "MI2S_TX"}, {"DISPLAY_PORT", NULL, "DISPLAY_PORT_RX Port Mixer"}, @@ -29440,6 +29572,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"BE_OUT", NULL, "SLIMBUS_9_RX"}, {"BE_OUT", NULL, "USB_AUDIO_RX"}, {"BE_OUT", NULL, "HDMI"}, + {"BE_OUT", NULL, "HDMI_MS"}, {"BE_OUT", NULL, "DISPLAY_PORT"}, {"BE_OUT", NULL, "DISPLAY_PORT1"}, {"BE_OUT", NULL, "PRI_SPDIF_RX"}, @@ -29928,7 +30061,8 @@ static int msm_routing_send_device_pp_params(int port_id, int copp_idx, pr_debug("%s: port_id %d, copp_idx %d\n", __func__, port_id, copp_idx); - if (port_id != HDMI_RX && port_id != DISPLAY_PORT_RX) { + if (port_id != HDMI_RX && port_id != DISPLAY_PORT_RX + && port_id != HDMI_RX_MS) { pr_err("%s: Device pp params on invalid port %d, copp_idx %d, fe_id %d\n", __func__, port_id, copp_idx, fe_id); return -EINVAL; @@ -30065,7 +30199,8 @@ static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, for (be_idx = 0; be_idx < MSM_BACKEND_DAI_MAX; be_idx++) { port_id = msm_bedais[be_idx].port_id; - if (port_id == HDMI_RX || port_id == DISPLAY_PORT_RX) + if (port_id == HDMI_RX || port_id == DISPLAY_PORT_RX + || port_id == HDMI_RX_MS) break; } diff --git a/asoc/msm-pcm-routing-v2.h b/asoc/msm-pcm-routing-v2.h index 337875909a..16943d70c5 100644 --- a/asoc/msm-pcm-routing-v2.h +++ b/asoc/msm-pcm-routing-v2.h @@ -17,6 +17,7 @@ #define LPASS_BE_SLIMBUS_0_RX "SLIMBUS_0_RX" #define LPASS_BE_SLIMBUS_0_TX "SLIMBUS_0_TX" #define LPASS_BE_HDMI "HDMI" +#define LPASS_BE_HDMI_MS "HDMI_MS" #define LPASS_BE_DISPLAY_PORT "DISPLAY_PORT" #define LPASS_BE_DISPLAY_PORT1 "DISPLAY_PORT1" #define LPASS_BE_INT_BT_SCO_RX "INT_BT_SCO_RX" @@ -508,6 +509,7 @@ enum { MSM_BACKEND_DAI_SEC_META_MI2S_RX, MSM_BACKEND_DAI_PROXY_RX, MSM_BACKEND_DAI_PROXY_TX, + MSM_BACKEND_DAI_HDMI_RX_MS, MSM_BACKEND_DAI_MAX, }; @@ -539,7 +541,7 @@ enum { #define RELEASE_LOCK 0 #define ACQUIRE_LOCK 1 -#define MSM_BACKEND_DAI_PP_PARAMS_REQ_MAX 2 +#define MSM_BACKEND_DAI_PP_PARAMS_REQ_MAX 3 #define HDMI_RX_ID 0x8001 #define ADM_PP_PARAM_MUTE_ID 0 #define ADM_PP_PARAM_MUTE_BIT 1 diff --git a/dsp/q6afe.c b/dsp/q6afe.c index 13379ce1c5..e5e4fb335c 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -1045,6 +1045,7 @@ int afe_sizeof_cfg_cmd(u16 port_id) ret_size = SIZEOF_CFG_CMD(afe_param_id_meta_i2s_cfg); break; case HDMI_RX: + case HDMI_RX_MS: case DISPLAY_PORT_RX: ret_size = SIZEOF_CFG_CMD(afe_param_id_hdmi_multi_chan_audio_cfg); @@ -5204,6 +5205,7 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config, cfg_type = AFE_PARAM_ID_META_I2S_CONFIG; break; case HDMI_RX: + case HDMI_RX_MS: case DISPLAY_PORT_RX: cfg_type = AFE_PARAM_ID_HDMI_CONFIG; break; @@ -5453,6 +5455,7 @@ int afe_get_port_index(u16 port_id) case MI2S_RX: return IDX_MI2S_RX; case MI2S_TX: return IDX_MI2S_TX; case HDMI_RX: return IDX_HDMI_RX; + case HDMI_RX_MS: return IDX_HDMI_RX_MS; case DISPLAY_PORT_RX: return IDX_DISPLAY_PORT_RX; case AFE_PORT_ID_PRIMARY_SPDIF_RX: return IDX_PRIMARY_SPDIF_RX; case AFE_PORT_ID_PRIMARY_SPDIF_TX: return IDX_PRIMARY_SPDIF_TX; @@ -5916,6 +5919,7 @@ int afe_open(u16 port_id, cfg_type = AFE_PARAM_ID_META_I2S_CONFIG; break; case HDMI_RX: + case HDMI_RX_MS: case DISPLAY_PORT_RX: cfg_type = AFE_PARAM_ID_HDMI_CONFIG; break; @@ -7812,6 +7816,7 @@ int afe_validate_port(u16 port_id) case MI2S_RX: case MI2S_TX: case HDMI_RX: + case HDMI_RX_MS: case DISPLAY_PORT_RX: case AFE_PORT_ID_PRIMARY_SPDIF_RX: case AFE_PORT_ID_PRIMARY_SPDIF_TX: diff --git a/dsp/q6audio-v2.c b/dsp/q6audio-v2.c index 15770fb94b..4a741000aa 100644 --- a/dsp/q6audio-v2.c +++ b/dsp/q6audio-v2.c @@ -46,6 +46,7 @@ int q6audio_get_port_index(u16 port_id) case MI2S_RX: return IDX_MI2S_RX; case MI2S_TX: return IDX_MI2S_TX; case HDMI_RX: return IDX_HDMI_RX; + case HDMI_RX_MS: return IDX_HDMI_RX_MS; case DISPLAY_PORT_RX: return IDX_DISPLAY_PORT_RX; case AFE_PORT_ID_PRIMARY_SPDIF_RX: return IDX_PRIMARY_SPDIF_RX; case AFE_PORT_ID_PRIMARY_SPDIF_TX: return IDX_PRIMARY_SPDIF_TX; @@ -427,6 +428,8 @@ int q6audio_get_port_id(u16 port_id) case MI2S_RX: return AFE_PORT_ID_PRIMARY_MI2S_RX; case MI2S_TX: return AFE_PORT_ID_PRIMARY_MI2S_TX; case HDMI_RX: return AFE_PORT_ID_MULTICHAN_HDMI_RX; + case HDMI_RX_MS: + return AFE_PORT_ID_HDMI_MS; case DISPLAY_PORT_RX: return AFE_PORT_ID_HDMI_OVER_DP_RX; case AFE_PORT_ID_PRIMARY_SPDIF_RX: @@ -1017,6 +1020,7 @@ int q6audio_validate_port(u16 port_id) case MI2S_RX: case MI2S_TX: case HDMI_RX: + case HDMI_RX_MS: case DISPLAY_PORT_RX: case RSVD_2: case RSVD_3: diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h index 2860016c6e..616c96737a 100644 --- a/include/dsp/apr_audio-v2.h +++ b/include/dsp/apr_audio-v2.h @@ -1356,6 +1356,7 @@ struct adm_cmd_connect_afe_port_v5 { #define RT_PROXY_PORT_001_RX 0x2000 #define RT_PROXY_PORT_001_TX 0x2001 #define AFE_LOOPBACK_TX 0x6001 +#define HDMI_RX_MS 0x6002 #define DISPLAY_PORT_RX 0x6020 #define AFE_LANE_MASK_INVALID 0 @@ -1562,6 +1563,8 @@ struct adm_cmd_connect_afe_port_v5 { #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_9_RX 0x4012 /* SLIMbus Tx port on channel 9. */ #define AFE_PORT_ID_SLIMBUS_MULTI_CHAN_9_TX 0x4013 +/*AFE Rx port for audio over hdmi*/ +#define AFE_PORT_ID_HDMI_MS 0x6002 /* AFE Rx port for audio over Display port */ #define AFE_PORT_ID_HDMI_OVER_DP_RX 0x6020 /*USB AFE port */ diff --git a/include/dsp/q6afe-v2.h b/include/dsp/q6afe-v2.h index d8fcaeaf6c..9abe736b3c 100644 --- a/include/dsp/q6afe-v2.h +++ b/include/dsp/q6afe-v2.h @@ -289,6 +289,8 @@ enum { /* IDX 210-> 211 */ IDX_RT_PROXY_PORT_002_RX, IDX_RT_PROXY_PORT_002_TX, + /* IDX 212 */ + IDX_HDMI_RX_MS, AFE_MAX_PORTS }; From 23efc09986224abe450470fea9a1db3302f20570 Mon Sep 17 00:00:00 2001 From: Sanjana B Date: Mon, 16 Dec 2019 11:30:28 +0530 Subject: [PATCH 042/116] asoc: qcs405: Add dai links for hdmi tx Add machine driver dai links for hdmi tx. Change-Id: Id699d9d0421349418dbb75ffcb6ed5069d15c0a1 Signed-off-by: Sanjana B --- asoc/qcs405.c | 287 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 281 insertions(+), 6 deletions(-) diff --git a/asoc/qcs405.c b/asoc/qcs405.c index 18dfb82207..982b1f2789 100644 --- a/asoc/qcs405.c +++ b/asoc/qcs405.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #include #include @@ -148,6 +148,11 @@ enum { SPDIF_TX_MAX, }; +enum { + HDMI_RX_IDX = 0, + EXT_HDMI_RX_IDX_MAX, +}; + struct mi2s_conf { struct mutex lock; u32 ref_cnt; @@ -344,7 +349,9 @@ static struct dev_config tdm_tx_cfg[TDM_INTERFACE_MAX][TDM_PORT_MAX] = { {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_7 */ } }; - +static struct dev_config ext_hdmi_rx_cfg[] = { + [HDMI_RX_IDX] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, +}; /* Default configuration of slimbus channels */ static struct dev_config slim_rx_cfg[] = { @@ -488,6 +495,12 @@ static char const *usb_sample_rate_text[] = {"KHZ_8", "KHZ_11P025", "KHZ_32", "KHZ_44P1", "KHZ_48", "KHZ_88P2", "KHZ_96", "KHZ_176P4", "KHZ_192", "KHZ_352P8", "KHZ_384"}; +static char const *ext_hdmi_sample_rate_text[] = {"KHZ_48", "KHZ_96", + "KHZ_192", "KHZ_32", "KHZ_44P1", + "KHZ_88P2", "KHZ_176P4"}; +static char const *ext_hdmi_bit_format_text[] = {"S16_LE", "S24_LE", + "S24_3LE"}; + static char const *tdm_ch_text[] = {"One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight"}; static char const *tdm_bit_format_text[] = {"S16_LE", "S24_LE", "S32_LE"}; @@ -539,6 +552,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_chs, slim_rx_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_chs, usb_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_chs, usb_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(vi_feed_tx_chs, vi_feed_ch_text); +static SOC_ENUM_SINGLE_EXT_DECL(ext_hdmi_rx_chs, ch_text); static SOC_ENUM_SINGLE_EXT_DECL(proxy_rx_chs, ch_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_format, bit_format_text); @@ -546,6 +560,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_format, bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_format, bit_format_text); +static SOC_ENUM_SINGLE_EXT_DECL(ext_hdmi_rx_format, ext_hdmi_bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_sample_rate, slim_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_2_rx_sample_rate, slim_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_sample_rate, slim_sample_rate_text); @@ -553,6 +568,8 @@ static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_sample_rate, slim_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_sample_rate, slim_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate, bt_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate_sink, bt_sample_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(ext_hdmi_rx_sample_rate, + ext_hdmi_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_sample_rate, usb_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_sample_rate, usb_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(tdm_tx_chs, tdm_ch_text); @@ -2110,6 +2127,191 @@ static int usb_audio_tx_format_put(struct snd_kcontrol *kcontrol, return rc; } +static int ext_hdmi_get_port_idx(struct snd_kcontrol *kcontrol) +{ + int idx; + + if (strnstr(kcontrol->id.name, "HDMI_RX", + sizeof("HDMI_RX"))) { + idx = HDMI_RX_IDX; + } else { + pr_err("%s: unsupported BE: %s", + __func__, kcontrol->id.name); + idx = -EINVAL; + } + + return idx; +} + +static int ext_hdmi_rx_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = ext_hdmi_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + switch (ext_hdmi_rx_cfg[idx].bit_format) { + case SNDRV_PCM_FORMAT_S24_LE: + ucontrol->value.integer.value[0] = 1; + break; + + case SNDRV_PCM_FORMAT_S16_LE: + default: + ucontrol->value.integer.value[0] = 0; + break; + } + + pr_debug("%s: ext_hdmi_rx[%d].format = %d, ucontrol value = %ld\n", + __func__, idx, ext_hdmi_rx_cfg[idx].bit_format, + ucontrol->value.integer.value[0]); + return 0; +} + +static int ext_hdmi_rx_format_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = ext_hdmi_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + switch (ucontrol->value.integer.value[0]) { + case 1: + ext_hdmi_rx_cfg[idx].bit_format = SNDRV_PCM_FORMAT_S24_LE; + break; + case 0: + default: + ext_hdmi_rx_cfg[idx].bit_format = SNDRV_PCM_FORMAT_S16_LE; + break; + } + pr_debug("%s: ext_hdmi_rx[%d].format = %d, ucontrol value = %ld\n", + __func__, idx, ext_hdmi_rx_cfg[idx].bit_format, + ucontrol->value.integer.value[0]); + + return 0; +} + +static int ext_hdmi_rx_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = ext_hdmi_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + ucontrol->value.integer.value[0] = + ext_hdmi_rx_cfg[idx].channels - 2; + + pr_debug("%s: ext_hdmi_rx[%d].ch = %d\n", __func__, + idx, ext_hdmi_rx_cfg[idx].channels); + + return 0; +} + +static int ext_hdmi_rx_ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = ext_hdmi_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + ext_hdmi_rx_cfg[idx].channels = + ucontrol->value.integer.value[0] + 2; + + pr_debug("%s: ext_hdmi_rx[%d].ch = %d\n", __func__, + idx, ext_hdmi_rx_cfg[idx].channels); + return 0; +} + +static int ext_hdmi_rx_sample_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int sample_rate_val; + int idx = ext_hdmi_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + switch (ext_hdmi_rx_cfg[idx].sample_rate) { + case SAMPLING_RATE_176P4KHZ: + sample_rate_val = 6; + break; + + case SAMPLING_RATE_88P2KHZ: + sample_rate_val = 5; + break; + + case SAMPLING_RATE_44P1KHZ: + sample_rate_val = 4; + break; + + case SAMPLING_RATE_32KHZ: + sample_rate_val = 3; + break; + + case SAMPLING_RATE_192KHZ: + sample_rate_val = 2; + break; + + case SAMPLING_RATE_96KHZ: + sample_rate_val = 1; + break; + + case SAMPLING_RATE_48KHZ: + default: + sample_rate_val = 0; + break; + } + + ucontrol->value.integer.value[0] = sample_rate_val; + pr_debug("%s: ext_hdmi_rx[%d].sample_rate = %d\n", __func__, + idx, ext_hdmi_rx_cfg[idx].sample_rate); + + return 0; +} + + +static int ext_hdmi_rx_sample_rate_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int idx = ext_hdmi_get_port_idx(kcontrol); + + if (idx < 0) + return idx; + + switch (ucontrol->value.integer.value[0]) { + case 6: + ext_hdmi_rx_cfg[idx].sample_rate = SAMPLING_RATE_176P4KHZ; + break; + case 5: + ext_hdmi_rx_cfg[idx].sample_rate = SAMPLING_RATE_88P2KHZ; + break; + case 4: + ext_hdmi_rx_cfg[idx].sample_rate = SAMPLING_RATE_44P1KHZ; + break; + case 3: + ext_hdmi_rx_cfg[idx].sample_rate = SAMPLING_RATE_32KHZ; + break; + case 2: + ext_hdmi_rx_cfg[idx].sample_rate = SAMPLING_RATE_192KHZ; + break; + case 1: + ext_hdmi_rx_cfg[idx].sample_rate = SAMPLING_RATE_96KHZ; + break; + case 0: + default: + ext_hdmi_rx_cfg[idx].sample_rate = SAMPLING_RATE_48KHZ; + break; + } + + pr_debug("%s: control value = %ld, ext_hdmi_rx[%d].sample_rate = %d\n", + __func__, ucontrol->value.integer.value[0], idx, + ext_hdmi_rx_cfg[idx].sample_rate); + return 0; +} + static int proxy_rx_ch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -3842,6 +4044,14 @@ static const struct snd_kcontrol_new msm_snd_sb_controls[] = { slim_rx_bit_format_get, slim_rx_bit_format_put), SOC_ENUM_EXT("SLIM_0_TX Format", slim_0_tx_format, slim_tx_bit_format_get, slim_tx_bit_format_put), + SOC_ENUM_EXT("HDMI_RX Bit Format", ext_hdmi_rx_format, + ext_hdmi_rx_format_get, ext_hdmi_rx_format_put), + SOC_ENUM_EXT("HDMI_RX SampleRate", ext_hdmi_rx_sample_rate, + ext_hdmi_rx_sample_rate_get, + ext_hdmi_rx_sample_rate_put), + SOC_ENUM_EXT("HDMI_RX Channels", ext_hdmi_rx_chs, + ext_hdmi_rx_ch_get, + ext_hdmi_rx_ch_put), SOC_ENUM_EXT("SLIM_0_RX SampleRate", slim_0_rx_sample_rate, slim_rx_sample_rate_get, slim_rx_sample_rate_put), SOC_ENUM_EXT("SLIM_2_RX SampleRate", slim_2_rx_sample_rate, @@ -4506,6 +4716,23 @@ static int msm_slim_get_ch_from_beid(int32_t be_id) return ch_id; } +static int msm_ext_hdmi_get_idx_from_beid(int32_t be_id) +{ + int idx; + + switch (be_id) { + case MSM_BACKEND_DAI_HDMI_RX_MS: + idx = HDMI_RX_IDX; + break; + default: + pr_err("%s: Incorrect ext_hdmi BE id %d\n", __func__, be_id); + idx = -EINVAL; + break; + } + + return idx; +} + static int msm_cdc_dma_get_idx_from_beid(int32_t be_id) { int idx = 0; @@ -5040,11 +5267,27 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, channels->min = channels->max = afe_lb_tx_cfg.channels; break; + case MSM_BACKEND_DAI_HDMI_RX_MS: + idx = msm_ext_hdmi_get_idx_from_beid(dai_link->id); + + if (idx < 0) { + pr_err("%s: Incorrect ext hdmi idx %d\n", + __func__, idx); + rc = idx; + goto done; + } + + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + ext_hdmi_rx_cfg[idx].bit_format); + rate->min = rate->max = ext_hdmi_rx_cfg[idx].sample_rate; + channels->min = channels->max = ext_hdmi_rx_cfg[idx].channels; + break; + default: rate->min = rate->max = SAMPLING_RATE_48KHZ; break; } - +done: return rc; } @@ -6104,7 +6347,6 @@ static struct snd_soc_ops msm_fe_qos_ops = { .prepare = msm_fe_qos_prepare, }; - static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream) { int ret = 0; @@ -7298,6 +7540,24 @@ static struct snd_soc_dai_link msm_common_misc_fe_dai_links[] = { }, }; +static struct snd_soc_dai_link ext_hdmi_be_dai_link[] = { + /* HDMI RX BACK END DAI Link */ + { + .name = LPASS_BE_HDMI_MS, + .stream_name = "HDMI MS Playback", + .cpu_dai_name = "msm-dai-q6-hdmi.24578", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-ext-disp-audio-codec-rx", + .codec_dai_name = "msm_hdmi_ms_audio_codec_rx_dai", + .no_pcm = 1, + .dpcm_playback = 1, + .id = MSM_BACKEND_DAI_HDMI_RX_MS, + .be_hw_params_fixup = msm_be_hw_params_fixup, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + }, +}; + static struct snd_soc_dai_link msm_common_be_dai_links[] = { /* Backend AFE DAI Links */ { @@ -8305,7 +8565,8 @@ static struct snd_soc_dai_link msm_qcs405_dai_links[ ARRAY_SIZE(msm_wsa_cdc_dma_be_dai_links) + ARRAY_SIZE(msm_bolero_fe_dai_links) + ARRAY_SIZE(msm_spdif_be_dai_links) + - ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link)]; + ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link) + + ARRAY_SIZE(ext_hdmi_be_dai_link)]; static int msm_snd_card_tasha_late_probe(struct snd_soc_card *card) { @@ -8556,6 +8817,7 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) 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, meta_mi2s_intf = 0; + uint32_t ext_disp_hdmi_rx = 0; const struct of_device_id *match; char __iomem *spdif_cfg, *spdif_pin_ctl; int rc = 0; @@ -8743,6 +9005,20 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link); } } + rc = of_property_read_u32(dev->of_node, + "qcom,ext-disp-audio-rx", &ext_disp_hdmi_rx); + if (rc) { + dev_dbg(dev, "%s: No DT match ext disp hdmi rx\n", + __func__); + } else { + if (ext_disp_hdmi_rx) { + memcpy(msm_qcs405_dai_links + total_links, + ext_hdmi_be_dai_link, + sizeof(ext_hdmi_be_dai_link)); + total_links += ARRAY_SIZE(ext_hdmi_be_dai_link); + } + } + dailink = msm_qcs405_dai_links; } else if (!strcmp(match->data, "stub_codec")) { card = &snd_soc_card_stub_msm; @@ -8756,7 +9032,6 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) msm_stub_be_dai_links, sizeof(msm_stub_be_dai_links)); total_links += ARRAY_SIZE(msm_stub_be_dai_links); - dailink = msm_stub_dai_links; } From a12af78a6b4b0a54ba442a851d936fd3d8c8bf15 Mon Sep 17 00:00:00 2001 From: Xiaojun Sang Date: Thu, 17 Jan 2019 15:45:13 +0800 Subject: [PATCH 043/116] Revert "asoc: check payload length against structure size" This reverts commit 2f35e4997c3e78a83fcdc459f4dcbbbaddc85d2d. Payload size is specified in ASM callback, which allocates memory consequently. The check was unnecessary and incorrect. Change-Id: I130870148db9c31a885b86f7ea495a8e843958d8 --- asoc/msm-qti-pp-config.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/asoc/msm-qti-pp-config.c b/asoc/msm-qti-pp-config.c index 1bafb20275..ee053a848b 100644 --- a/asoc/msm-qti-pp-config.c +++ b/asoc/msm-qti-pp-config.c @@ -1238,13 +1238,6 @@ int msm_adsp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd, } event_data = (struct msm_adsp_event_data *)payload; - if (event_data->payload_len < sizeof(struct msm_adsp_event_data)) { - pr_err("%s: event_data size of %x is less than expected.\n", - __func__, event_data->payload_len); - ret = -EINVAL; - goto done; - } - kctl->info(kctl, &kctl_info); if (event_data->payload_len > From eabe747ee3b105c5845d1105003dc441b2456f88 Mon Sep 17 00:00:00 2001 From: Akhil Karuturi Date: Tue, 19 May 2020 21:47:02 -0700 Subject: [PATCH 044/116] ASoC: update audio effects config names Update audio effects config names to be more descriptive to avoid conflict with kernel config naming convention. Change-Id: Ie4d9bd0128a9f52138b3a1b94abccc81b8432c1d Signed-off-by: Akhil Karuturi --- asoc/msm-audio-effects-q6-v2.c | 50 ++++++++++++------------ include/uapi/audio/sound/audio_effects.h | 9 +++-- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/asoc/msm-audio-effects-q6-v2.c b/asoc/msm-audio-effects-q6-v2.c index c25791ed4b..68701ff47c 100644 --- a/asoc/msm-audio-effects-q6-v2.c +++ b/asoc/msm-audio-effects-q6-v2.c @@ -184,7 +184,7 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac, GET_NEXT(values, param_max_offset, rc); pr_debug("%s: VIRT STRENGTH val: %d\n", __func__, virtualizer->strength); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -208,7 +208,7 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac, GET_NEXT(values, param_max_offset, rc); pr_debug("%s: VIRT OUT_TYPE val:%d\n", __func__, virtualizer->out_type); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -232,7 +232,7 @@ int msm_audio_effects_virtualizer_handler(struct audio_client *ac, GET_NEXT(values, param_max_offset, rc); pr_debug("%s: VIRT GAIN_ADJUST val:%d\n", __func__, virtualizer->gain_adjust); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -362,7 +362,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_MODE val:%d\n", __func__, reverb->mode); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -385,7 +385,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_PRESET val:%d\n", __func__, reverb->preset); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -408,7 +408,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_WET_MIX val:%d\n", __func__, reverb->wet_mix); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -431,7 +431,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_GAIN_ADJUST val:%d\n", __func__, reverb->gain_adjust); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -455,7 +455,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_ROOM_LEVEL val:%d\n", __func__, reverb->room_level); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -478,7 +478,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_ROOM_HF_LEVEL val%d\n", __func__, reverb->room_hf_level); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -502,7 +502,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_DECAY_TIME val:%d\n", __func__, reverb->decay_time); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -525,7 +525,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_DECAY_HF_RATIO val%d\n", __func__, reverb->decay_hf_ratio); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -549,7 +549,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_REFLECTIONS_LEVEL val:%d\n", __func__, reverb->reflections_level); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -574,7 +574,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_REFLECTIONS_DELAY val:%d\n", __func__, reverb->reflections_delay); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -599,7 +599,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_LEVEL val:%d\n", __func__, reverb->level); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -622,7 +622,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, GET_NEXT(values, param_max_offset, rc); pr_debug("%s:REVERB_DELAY val:%d\n", __func__, reverb->delay); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -645,7 +645,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_DIFFUSION val:%d\n", __func__, reverb->diffusion); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -668,7 +668,7 @@ int msm_audio_effects_reverb_handler(struct audio_client *ac, GET_NEXT(values, param_max_offset, rc); pr_debug("%s: REVERB_DENSITY val:%d\n", __func__, reverb->density); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -798,7 +798,7 @@ int msm_audio_effects_bass_boost_handler(struct audio_client *ac, GET_NEXT(values, param_max_offset, rc); pr_debug("%s: BASS_BOOST_MODE val:%d\n", __func__, bass_boost->mode); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -821,7 +821,7 @@ int msm_audio_effects_bass_boost_handler(struct audio_client *ac, GET_NEXT(values, param_max_offset, rc); pr_debug("%s: BASS_BOOST_STRENGTH val:%d\n", __func__, bass_boost->strength); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -1014,7 +1014,7 @@ int msm_audio_effects_pbe_handler(struct audio_client *ac, *p_coeffs++ = GET_NEXT(values, param_max_offset, rc); } - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = @@ -1184,7 +1184,7 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, eq->per_band_cfg[idx].quality_factor = GET_NEXT(values, param_max_offset, rc); } - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; config_param_length = EQ_CONFIG_PARAM_SZ + (EQ_CONFIG_PER_BAND_PARAM_SZ * @@ -1245,7 +1245,7 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, eq->band_index = idx; pr_debug("%s: EQ_BAND_INDEX val:%d\n", __func__, eq->band_index); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -1272,7 +1272,7 @@ int msm_audio_effects_popless_eq_handler(struct audio_client *ac, GET_NEXT(values, param_max_offset, rc); pr_debug("%s: EQ_SINGLE_BAND_FREQ idx:%d, val:%d\n", __func__, eq->band_index, eq->freq_millihertz); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -1377,7 +1377,7 @@ static int __msm_audio_effects_volume_handler(struct audio_client *ac, vol->right_gain = GET_NEXT(values, param_max_offset, rc); vol->master_gain = 0x2000; - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + @@ -1398,7 +1398,7 @@ static int __msm_audio_effects_volume_handler(struct audio_client *ac, vol->right_gain = 0x2000; vol->master_gain = GET_NEXT(values, param_max_offset, rc); - if (command_config_state != CONFIG_SET) + if (command_config_state != AUDIO_EFFECTS_CONFIG_SET) break; max_params_length = params_length + COMMAND_IID_PAYLOAD_SZ + diff --git a/include/uapi/audio/sound/audio_effects.h b/include/uapi/audio/sound/audio_effects.h index a2dcea96f9..6279e0c2d0 100644 --- a/include/uapi/audio/sound/audio_effects.h +++ b/include/uapi/audio/sound/audio_effects.h @@ -7,9 +7,10 @@ /* CONFIG GET/SET */ -#define CONFIG_CACHE 0 +#define AUDIO_EFFECTS_CONFIG_CACHE 0 +#define AUDIO_EFFECTS_CONFIG_SET 1 +#define AUDIO_EFFECTS_CONFIG_GET 2 #define CONFIG_SET 1 -#define CONFIG_GET 2 /* CONFIG HEADER */ /* @@ -17,14 +18,14 @@ * DEVICE, * NUM_COMMANDS, * COMMAND_ID_1, - * CONFIG_CACHE/SET/GET, + * AUDIO_EFFECTS_CONFIG_CACHE/SET/GET, * OFFSET_1, * LENGTH_1, * VALUES_1, * ..., * ..., * COMMAND_ID_2, - * CONFIG_CACHE/SET/GET, + * AUDIO_EFFECTS_CONFIG_CACHE/SET/GET, * OFFSET_2, * LENGTH_2, * VALUES_2, From 6358c06e4d9806a03260e74a013d7c15f54da274 Mon Sep 17 00:00:00 2001 From: Satish Babu Patakokila Date: Thu, 28 May 2020 21:05:23 +0530 Subject: [PATCH 045/116] ASoC: Update Compress driver as per ASoC framework expecatations Update compress platform driver to match ASoC framework expectation. Drain and Partial Drain commands should not wait as the wait needed is already taken care of in the SoC framework. Change-Id: I44be253204a69a005b208d8a805d8e9108c0846c Signed-off-by: Satish Babu Patakokila --- asoc/msm-compress-q6-v2.c | 177 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) diff --git a/asoc/msm-compress-q6-v2.c b/asoc/msm-compress-q6-v2.c index ce525c1261..db75b180bd 100644 --- a/asoc/msm-compress-q6-v2.c +++ b/asoc/msm-compress-q6-v2.c @@ -137,6 +137,9 @@ struct msm_compr_audio { int32_t first_buffer; int32_t last_buffer; +#if !IS_ENABLED(CONFIG_AUDIO_QGKI) + int32_t zero_buffer; +#endif int32_t partial_drain_delay; uint16_t session_id; @@ -168,6 +171,9 @@ struct msm_compr_audio { atomic_t start; atomic_t eos; atomic_t drain; +#if !IS_ENABLED(CONFIG_AUDIO_QGKI) + atomic_t partial_drain; +#endif atomic_t xrun; atomic_t close; atomic_t wait_on_close; @@ -622,8 +628,10 @@ static void compr_event_handler(uint32_t opcode, if (atomic_cmpxchg(&prtd->drain, 1, 0) && prtd->last_buffer) { pr_debug("%s: wake up on drain\n", __func__); +#if IS_ENABLED(CONFIG_AUDIO_QGKI) prtd->drain_ready = 1; wake_up(&prtd->drain_wait); +#endif prtd->last_buffer = 0; } else { atomic_set(&prtd->start, 0); @@ -666,6 +674,103 @@ static void compr_event_handler(uint32_t opcode, break; } +#if !IS_ENABLED(CONFIG_AUDIO_QGKI) + if (prtd->zero_buffer) { + pr_debug("write_done for zero buffer\n"); + prtd->zero_buffer = 0; + + /* move to next stream and reset vars */ + pr_debug("%s: Moving to next stream in gapless\n", + __func__); + ac->stream_id = NEXT_STREAM_ID(ac->stream_id); + prtd->byte_offset = 0; + prtd->app_pointer = 0; + prtd->first_buffer = 1; + prtd->last_buffer = 0; + /* + * Set gapless transition flag only if EOS hasn't been + * acknowledged already. + */ + if (atomic_read(&prtd->eos)) + prtd->gapless_state.gapless_transition = 1; + prtd->marker_timestamp = 0; + + /* + * Don't reset these as these vars map to + * total_bytes_transferred and total_bytes_available + * directly, only total_bytes_transferred will be + * updated in the next avail() ioctl + * prtd->copied_total = 0; + * prtd->bytes_received = 0; + */ + atomic_set(&prtd->drain, 0); + atomic_set(&prtd->xrun, 1); + pr_debug("%s: issue CMD_RUN", __func__); + q6asm_run_nowait(prtd->audio_client, 0, 0, 0); + snd_compr_drain_notify(cstream); + spin_unlock_irqrestore(&prtd->lock, flags); + break; + } + + bytes_available = prtd->bytes_received - prtd->copied_total; + if (bytes_available == 0) { + pr_debug("%s:bytes_available is 0\n", __func__); + if (prtd->last_buffer) + prtd->last_buffer = 0; + + if (atomic_read(&prtd->partial_drain) && + prtd->gapless_state.set_next_stream_id && + !prtd->zero_buffer) { + + pr_debug("%s:Partial Drain Case\n", __func__); + pr_debug("%s:Send EOS command\n", __func__); + /* send EOS */ + prtd->eos_ack = 0; + atomic_set(&prtd->eos, 1); + atomic_set(&prtd->drain, 0); + q6asm_stream_cmd_nowait(ac, CMD_EOS, ac->stream_id); + + /* send a zero length buffer in case of partial drain*/ + atomic_set(&prtd->xrun, 0); + pr_debug("%s:Send zero size buffer\n", __func__); + msm_compr_send_buffer(prtd); + prtd->zero_buffer = 1; + } else { + /* + * moving to next stream failed, so reset the gapless state + * set next stream id for the same session so that the same + * stream can be used for gapless playback + */ + pr_debug("%s:Drain Case\n", __func__); + pr_debug("%s:Reset Gapless params \n", __func__); + + prtd->gapless_state.set_next_stream_id = false; + prtd->gapless_state.gapless_transition = 0; + + pr_debug("%s:Send EOS command\n", __func__); + prtd->eos_ack = 0; + atomic_set(&prtd->eos, 1); + atomic_set(&prtd->drain, 0); + q6asm_stream_cmd_nowait(ac, CMD_EOS, ac->stream_id); + + prtd->cmd_interrupt = 0; + } + } else if (bytes_available < cstream->runtime->fragment_size) { + pr_debug("%s:Partial Buffer Case \n", __func__); + atomic_set(&prtd->xrun, 1); + + if (prtd->last_buffer) + prtd->last_buffer = 0; + if (atomic_read(&prtd->drain)) { + if (bytes_available > 0) { + pr_debug("%s: send %d partial bytes at the end", + __func__, bytes_available); + atomic_set(&prtd->xrun, 0); + prtd->last_buffer = 1; + msm_compr_send_buffer(prtd); + } + } +#else bytes_available = prtd->bytes_received - prtd->copied_total; if (bytes_available < cstream->runtime->fragment_size) { pr_debug("WRITE_DONE Insufficient data to send. break out\n"); @@ -679,6 +784,7 @@ static void compr_event_handler(uint32_t opcode, wake_up(&prtd->drain_wait); atomic_set(&prtd->drain, 0); } +#endif } else if ((bytes_available == cstream->runtime->fragment_size) && atomic_read(&prtd->drain)) { prtd->last_buffer = 1; @@ -740,7 +846,40 @@ static void compr_event_handler(uint32_t opcode, !prtd->gapless_state.set_next_stream_id) { pr_debug("ASM_DATA_CMDRSP_EOS wake up\n"); prtd->eos_ack = 1; +#if IS_ENABLED(CONFIG_AUDIO_QGKI) wake_up(&prtd->eos_wait); +#else + pr_debug("%s:issue CMD_PAUSE stream_id %d", + __func__, ac->stream_id); + q6asm_stream_cmd_nowait(ac, CMD_PAUSE, ac->stream_id); + prtd->cmd_ack = 0; + + pr_debug("%s:DRAIN,don't wait for EOS ack\n", __func__); + /* + * Don't reset these as these vars map to + * total_bytes_transferred and total_bytes_available. + * Just total_bytes_transferred will be updated + * in the next avail() ioctl. + * prtd->copied_total = 0; + * prtd->bytes_received = 0; + * do not reset prtd->bytes_sent as well as the same + * session is used for gapless playback + */ + prtd->byte_offset = 0; + + prtd->app_pointer = 0; + prtd->first_buffer = 1; + prtd->last_buffer = 0; + atomic_set(&prtd->drain, 0); + atomic_set(&prtd->xrun, 1); + + pr_debug("%s:issue CMD_FLUSH ac->stream_id %d", + __func__, ac->stream_id); + + q6asm_run_nowait(prtd->audio_client, 0, 0, 0); + + snd_compr_drain_notify(cstream); +#endif } atomic_set(&prtd->eos, 0); stream_index = STREAM_ARRAY_INDEX(stream_id); @@ -841,7 +980,9 @@ static void compr_event_handler(uint32_t opcode, prtd->last_buffer = 0; prtd->drain_ready = 1; +#if IS_ENABLED(CONFIG_AUDIO_QGKI) wake_up(&prtd->drain_wait); +#endif atomic_set(&prtd->drain, 0); } else if (atomic_read(&prtd->xrun)) { pr_debug("%s: RUN ack, continue write cycle\n", __func__); @@ -916,11 +1057,13 @@ static void compr_event_handler(uint32_t opcode, prtd->copied_total = prtd->bytes_received; snd_compr_fragment_elapsed(cstream); atomic_set(&prtd->error, 1); +#if IS_ENABLED(CONFIG_AUDIO_QGKI) wake_up(&prtd->drain_wait); if (atomic_cmpxchg(&prtd->eos, 1, 0)) { pr_debug("%s:unblock eos wait queues", __func__); wake_up(&prtd->eos_wait); } +#endif spin_unlock_irqrestore(&prtd->lock, flags); break; default: @@ -1754,6 +1897,9 @@ static int msm_compr_playback_open(struct snd_compr_stream *cstream) atomic_set(&prtd->eos, 0); atomic_set(&prtd->start, 0); atomic_set(&prtd->drain, 0); +#if !IS_ENABLED(CONFIG_AUDIO_QGKI) + atomic_set(&prtd->partial_drain, 0); +#endif atomic_set(&prtd->xrun, 0); atomic_set(&prtd->close, 0); atomic_set(&prtd->wait_on_close, 0); @@ -1849,6 +1995,9 @@ static int msm_compr_capture_open(struct snd_compr_stream *cstream) atomic_set(&prtd->eos, 0); atomic_set(&prtd->start, 0); atomic_set(&prtd->drain, 0); +#if !IS_ENABLED(CONFIG_AUDIO_QGKI) + atomic_set(&prtd->partial_drain, 0); +#endif atomic_set(&prtd->xrun, 0); atomic_set(&prtd->close, 0); atomic_set(&prtd->wait_on_close, 0); @@ -1911,7 +2060,9 @@ static int msm_compr_playback_free(struct snd_compr_stream *cstream) return 0; } prtd->cmd_interrupt = 1; +#if IS_ENABLED(CONFIG_AUDIO_QGKI) wake_up(&prtd->drain_wait); +#endif pdata = snd_soc_component_get_drvdata(component); ac = prtd->audio_client; if (!pdata || !ac) { @@ -2293,6 +2444,7 @@ static int msm_compr_set_params(struct snd_compr_stream *cstream, return ret; } +#if IS_ENABLED(CONFIG_AUDIO_QGKI) static int msm_compr_drain_buffer(struct msm_compr_audio *prtd, unsigned long *flags) { @@ -2321,6 +2473,7 @@ static int msm_compr_drain_buffer(struct msm_compr_audio *prtd, } return rc; } +#endif static int msm_compr_wait_for_stream_avail(struct msm_compr_audio *prtd, unsigned long *flags) @@ -2373,7 +2526,9 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd) struct audio_client *ac = prtd->audio_client; unsigned long fe_id = rtd->dai_link->id; int rc = 0; +#if IS_ENABLED(CONFIG_AUDIO_QGKI) int bytes_to_write; +#endif unsigned long flags; int stream_id; uint32_t stream_index; @@ -2465,17 +2620,21 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd) * cmd_int and do not wake up eos_wait during gapless * transition */ +#if IS_ENABLED(CONFIG_AUDIO_QGKI) if (!prtd->gapless_state.gapless_transition) { prtd->cmd_interrupt = 1; wake_up(&prtd->eos_wait); } +#endif atomic_set(&prtd->eos, 0); } if (atomic_read(&prtd->drain)) { pr_debug("%s: interrupt drain wait queues", __func__); prtd->cmd_interrupt = 1; prtd->drain_ready = 1; +#if IS_ENABLED(CONFIG_AUDIO_QGKI) wake_up(&prtd->drain_wait); +#endif atomic_set(&prtd->drain, 0); } prtd->last_buffer = 0; @@ -2521,10 +2680,20 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd) break; case SND_COMPR_TRIGGER_PARTIAL_DRAIN: pr_debug("%s: SND_COMPR_TRIGGER_PARTIAL_DRAIN\n", __func__); +#if !IS_ENABLED(CONFIG_AUDIO_QGKI) + spin_lock_irqsave(&prtd->lock, flags); + atomic_set(&prtd->partial_drain, 1); +#endif if (!prtd->gapless_state.use_dsp_gapless_mode) { pr_debug("%s: set partial drain as drain\n", __func__); cmd = SND_COMPR_TRIGGER_DRAIN; +#if !IS_ENABLED(CONFIG_AUDIO_QGKI) + atomic_set(&prtd->partial_drain, 0); +#endif } +#if !IS_ENABLED(CONFIG_AUDIO_QGKI) + spin_unlock_irqrestore(&prtd->lock, flags); +#endif case SND_COMPR_TRIGGER_DRAIN: pr_debug("%s: SNDRV_COMPRESS_DRAIN\n", __func__); /* Make sure all the data is sent to DSP before sending EOS */ @@ -2534,9 +2703,13 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd) pr_err("%s: stream is not in started state\n", __func__); rc = -EPERM; +#if !IS_ENABLED(CONFIG_AUDIO_QGKI) + atomic_set(&prtd->partial_drain, 0); +#endif spin_unlock_irqrestore(&prtd->lock, flags); break; } +#if IS_ENABLED(CONFIG_AUDIO_QGKI) if (prtd->bytes_received > prtd->copied_total) { pr_debug("%s: wait till all the data is sent to dsp\n", __func__); @@ -2743,6 +2916,10 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd) q6asm_run_nowait(prtd->audio_client, 0, 0, 0); } +#else + atomic_set(&prtd->drain, 1); + spin_unlock_irqrestore(&prtd->lock, flags); +#endif prtd->cmd_interrupt = 0; break; case SND_COMPR_TRIGGER_NEXT_TRACK: From d941fe254b28c01cdfe2172a9632f5aa8c72ffc6 Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Mon, 1 Jun 2020 19:23:48 +0530 Subject: [PATCH 046/116] Soc: soundwire: Update hw_ctl on HCLK at bootup For soundwire version 1.6, HCLK remove HW controlled at bootup before soundwire frame generation status check. Change-Id: Idc2420d086261766ea4e79f69320f12c4d6b2259 Signed-off-by: Laxminath Kasam --- soc/swr-mstr-ctrl.c | 50 ++++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index b2853b399a..8a49f5acae 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -2237,7 +2237,7 @@ static void swrm_device_wakeup_unvote(struct swr_master *mstr) static int swrm_master_init(struct swr_mstr_ctrl *swrm) { - int ret = 0; + int ret = 0, i = 0; u32 val; u8 row_ctrl = SWR_ROW_50; u8 col_ctrl = SWR_MIN_COL; @@ -2248,6 +2248,18 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm) u32 temp = 0; int len = 0; + /* SW workaround to gate hw_ctl for SWR version >=1.6 */ + if (swrm->version >= SWRM_VERSION_1_6) { + if (swrm->swrm_hctl_reg) { + temp = ioread32(swrm->swrm_hctl_reg); + temp &= 0xFFFFFFFD; + iowrite32(temp, swrm->swrm_hctl_reg); + usleep_range(500, 505); + temp = ioread32(swrm->swrm_hctl_reg); + dev_dbg(swrm->dev, "%s: hctl_reg val: 0x%x\n", + __func__, temp); + } + } ssp_period = swrm_get_ssp_period(swrm, SWRM_ROW_50, SWRM_COL_02, SWRM_FRAME_SYNC_SEL); dev_dbg(swrm->dev, "%s: ssp_period: %d\n", __func__, ssp_period); @@ -2303,6 +2315,13 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm) dev_err(swrm->dev, "%s: swr link failed to connect\n", __func__); + for (i = 0; i < len; i++) { + usleep_range(50, 55); + dev_err(swrm->dev, + "%s:reg:0x%x val:0x%x\n", + __func__, + reg[i], swr_master_read(swrm, reg[i])); + } return -EINVAL; } @@ -2312,14 +2331,6 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm) (swr_master_read(swrm, SWRM_CMD_FIFO_CFG) | 0x80000000)); - /* SW workaround to gate hw_ctl for SWR version >=1.6 */ - if (swrm->version >= SWRM_VERSION_1_6) { - if (swrm->swrm_hctl_reg) { - temp = ioread32(swrm->swrm_hctl_reg); - temp &= 0xFFFFFFFD; - iowrite32(temp, swrm->swrm_hctl_reg); - } - } return ret; } @@ -2659,6 +2670,7 @@ static int swrm_probe(struct platform_device *pdev) "%s: Error in master Initialization , err %d\n", __func__, ret); mutex_unlock(&swrm->mlock); + ret = -EPROBE_DEFER; goto err_mstr_init_fail; } @@ -2707,11 +2719,17 @@ err_irq_wakeup_fail: err_mstr_init_fail: swr_unregister_master(&swrm->master); err_mstr_fail: - if (swrm->reg_irq) + if (swrm->reg_irq) { swrm->reg_irq(swrm->handle, swr_mstr_interrupt, swrm, SWR_IRQ_FREE); - else if (swrm->irq) + } else if (swrm->irq) { free_irq(swrm->irq, swrm); + irqd_set_trigger_type( + irq_get_irq_data(swrm->irq), + IRQ_TYPE_NONE); + } + if (swrm->swr_irq_wakeup_capable) + irq_set_irq_wake(swrm->irq, 0); err_irq_fail: mutex_destroy(&swrm->irq_lock); mutex_destroy(&swrm->mlock); @@ -2731,13 +2749,17 @@ static int swrm_remove(struct platform_device *pdev) { struct swr_mstr_ctrl *swrm = platform_get_drvdata(pdev); - if (swrm->reg_irq) + if (swrm->reg_irq) { swrm->reg_irq(swrm->handle, swr_mstr_interrupt, swrm, SWR_IRQ_FREE); - else if (swrm->irq) + } else if (swrm->irq) { free_irq(swrm->irq, swrm); - else if (swrm->wake_irq > 0) + irqd_set_trigger_type( + irq_get_irq_data(swrm->irq), + IRQ_TYPE_NONE); + } else if (swrm->wake_irq > 0) { free_irq(swrm->wake_irq, swrm); + } if (swrm->swr_irq_wakeup_capable) irq_set_irq_wake(swrm->irq, 0); cancel_work_sync(&swrm->wakeup_work); From c3fd6cc3055ad98bc030ac936cfba4c24397c715 Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Thu, 23 Apr 2020 18:57:27 +0530 Subject: [PATCH 047/116] asoc: codecs: Fix button interrupts issue in rouleur Current source mode in rouleur does not work properly leading to issues in button interrupts and fake electrical removal interrupts. Enable pull up mode instead of current source mode to fix these issues. Modify the headset max vref voltage to 1.7 volts and micbias calculation logic. Change-Id: If3e4a2fdcf080b07fe3c363b6eb6115f101b91f4 Signed-off-by: Aditya Bavanari --- asoc/codecs/rouleur/internal.h | 1 + asoc/codecs/rouleur/rouleur-mbhc.c | 39 +++++++++++++++++++++++++++ asoc/codecs/rouleur/rouleur.c | 43 +++++++++++++++++++++++++----- asoc/codecs/wcd-mbhc-adc.c | 22 ++++++++------- asoc/codecs/wcd-mbhc-v2.c | 26 +++++++++++++++--- include/asoc/wcd-mbhc-v2.h | 6 +++++ 6 files changed, 118 insertions(+), 19 deletions(-) diff --git a/asoc/codecs/rouleur/internal.h b/asoc/codecs/rouleur/internal.h index 7104685d7c..df8541e340 100644 --- a/asoc/codecs/rouleur/internal.h +++ b/asoc/codecs/rouleur/internal.h @@ -82,6 +82,7 @@ struct rouleur_priv { int mbias_cnt; struct mutex rx_clk_lock; struct mutex main_bias_lock; + bool dev_up; }; struct rouleur_micbias_setting { diff --git a/asoc/codecs/rouleur/rouleur-mbhc.c b/asoc/codecs/rouleur/rouleur-mbhc.c index caf6d4a04f..78bef6a8ed 100644 --- a/asoc/codecs/rouleur/rouleur-mbhc.c +++ b/asoc/codecs/rouleur/rouleur-mbhc.c @@ -820,6 +820,42 @@ static void rouleur_mbhc_bcs_enable(struct wcd_mbhc *mbhc, rouleur_disable_bcs_before_slow_insert(mbhc->component, true); } +static void rouleur_mbhc_hs_vref_max_update(struct wcd_mbhc *mbhc) +{ + struct snd_soc_component *component = mbhc->component; + + /* Update the HS Vref max voltage to 1.7V */ + snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_CTL_2, + 0x03, 0x03); +} + +static void rouleur_mbhc_get_micbias_val(struct wcd_mbhc *mbhc, int *mb) +{ + u8 vout_ctl = 0; + + /* Read MBHC Micbias (Mic Bias2) voltage */ + WCD_MBHC_REG_READ(WCD_MBHC_MICB2_VOUT, vout_ctl); + + /* Formula for getting micbias from vout + * micbias = 1.6V + VOUT_CTL * 50mV + */ + *mb = 1600 + (vout_ctl * 50); + pr_debug("%s: vout_ctl: %d, micbias: %d\n", __func__, vout_ctl, *mb); +} + +static void rouleur_mbhc_micb_pullup_control( + struct snd_soc_component *component, + bool pullup_enable) +{ + if (pullup_enable) + rouleur_micbias_control(component, MIC_BIAS_2, + MICB_PULLUP_ENABLE, false); + else + rouleur_micbias_control(component, MIC_BIAS_2, + MICB_PULLUP_DISABLE, false); + +} + static const struct wcd_mbhc_cb mbhc_cb = { .request_irq = rouleur_mbhc_request_irq, .irq_control = rouleur_mbhc_irq_control, @@ -844,6 +880,9 @@ static const struct wcd_mbhc_cb mbhc_cb = { .mbhc_get_moisture_status = rouleur_mbhc_get_moisture_status, .mbhc_moisture_detect_en = rouleur_mbhc_moisture_detect_en, .bcs_enable = rouleur_mbhc_bcs_enable, + .hs_vref_max_update = rouleur_mbhc_hs_vref_max_update, + .get_micbias_val = rouleur_mbhc_get_micbias_val, + .mbhc_micb_pullup_control = rouleur_mbhc_micb_pullup_control, }; static int rouleur_get_hph_type(struct snd_kcontrol *kcontrol, diff --git a/asoc/codecs/rouleur/rouleur.c b/asoc/codecs/rouleur/rouleur.c index 3f039c4082..cdb1de2c69 100644 --- a/asoc/codecs/rouleur/rouleur.c +++ b/asoc/codecs/rouleur/rouleur.c @@ -1146,6 +1146,7 @@ int rouleur_micbias_control(struct snd_soc_component *component, int post_on_event = 0, post_dapm_off = 0; int post_dapm_on = 0; u8 pullup_mask = 0, enable_mask = 0; + int ret = 0; if ((micb_index < 0) || (micb_index > ROULEUR_MAX_MICBIAS - 1)) { dev_err(component->dev, "%s: Invalid micbias index, micb_ind:%d\n", @@ -1181,6 +1182,12 @@ int rouleur_micbias_control(struct snd_soc_component *component, switch (req) { case MICB_PULLUP_ENABLE: + if (!rouleur->dev_up) { + dev_dbg(component->dev, "%s: enable req %d wcd device down\n", + __func__, req); + ret = -ENODEV; + goto done; + } rouleur->pullup_ref[micb_index]++; if ((rouleur->pullup_ref[micb_index] == 1) && (rouleur->micb_ref[micb_index] == 0)) @@ -1188,6 +1195,12 @@ int rouleur_micbias_control(struct snd_soc_component *component, pullup_mask, pullup_mask); break; case MICB_PULLUP_DISABLE: + if (!rouleur->dev_up) { + dev_dbg(component->dev, "%s: enable req %d wcd device down\n", + __func__, req); + ret = -ENODEV; + goto done; + } if (rouleur->pullup_ref[micb_index] > 0) rouleur->pullup_ref[micb_index]--; if ((rouleur->pullup_ref[micb_index] == 0) && @@ -1196,11 +1209,15 @@ int rouleur_micbias_control(struct snd_soc_component *component, pullup_mask, 0x00); break; case MICB_ENABLE: + if (!rouleur->dev_up) { + dev_dbg(component->dev, "%s: enable req %d wcd device down\n", + __func__, req); + ret = -ENODEV; + goto done; + } rouleur->micb_ref[micb_index]++; if (rouleur->micb_ref[micb_index] == 1) { rouleur_global_mbias_enable(component); - snd_soc_component_update_bits(component, micb_reg, - 0x80, 0x80); snd_soc_component_update_bits(component, micb_reg, enable_mask, enable_mask); if (post_on_event) @@ -1216,16 +1233,27 @@ int rouleur_micbias_control(struct snd_soc_component *component, case MICB_DISABLE: if (rouleur->micb_ref[micb_index] > 0) rouleur->micb_ref[micb_index]--; + if (!rouleur->dev_up) { + dev_dbg(component->dev, "%s: enable req %d wcd device down\n", + __func__, req); + ret = -ENODEV; + goto done; + } if ((rouleur->micb_ref[micb_index] == 0) && - (rouleur->pullup_ref[micb_index] == 0)) { + (rouleur->pullup_ref[micb_index] > 0)) { + snd_soc_component_update_bits(component, micb_reg, + pullup_mask, pullup_mask); + snd_soc_component_update_bits(component, micb_reg, + enable_mask, 0x00); + rouleur_global_mbias_disable(component); + } else if ((rouleur->micb_ref[micb_index] == 0) && + (rouleur->pullup_ref[micb_index] == 0)) { if (pre_off_event && rouleur->mbhc) blocking_notifier_call_chain( &rouleur->mbhc->notifier, pre_off_event, &rouleur->mbhc->wcd_mbhc); snd_soc_component_update_bits(component, micb_reg, enable_mask, 0x00); - snd_soc_component_update_bits(component, micb_reg, - 0x80, 0x00); rouleur_global_mbias_disable(component); if (post_off_event && rouleur->mbhc) blocking_notifier_call_chain( @@ -1243,8 +1271,8 @@ int rouleur_micbias_control(struct snd_soc_component *component, dev_dbg(component->dev, "%s: micb_num:%d, micb_ref: %d, pullup_ref: %d\n", __func__, micb_num, rouleur->micb_ref[micb_index], rouleur->pullup_ref[micb_index]); +done: mutex_unlock(&rouleur->micb_lock); - return 0; } EXPORT_SYMBOL(rouleur_micbias_control); @@ -1313,6 +1341,7 @@ static int rouleur_event_notify(struct notifier_block *block, 0x80, 0x00); break; case BOLERO_WCD_EVT_SSR_DOWN: + rouleur->dev_up = false; rouleur->mbhc->wcd_mbhc.deinit_in_progress = true; mbhc = &rouleur->mbhc->wcd_mbhc; rouleur_mbhc_ssr_down(rouleur->mbhc, component); @@ -1338,6 +1367,7 @@ static int rouleur_event_notify(struct notifier_block *block, rouleur_mbhc_hs_detect(component, mbhc->mbhc_cfg); } rouleur->mbhc->wcd_mbhc.deinit_in_progress = false; + rouleur->dev_up = true; break; default: dev_err(component->dev, "%s: invalid event %d\n", __func__, @@ -1969,6 +1999,7 @@ static int rouleur_soc_codec_probe(struct snd_soc_component *component) return ret; } } + rouleur->dev_up = true; done: return ret; } diff --git a/asoc/codecs/wcd-mbhc-adc.c b/asoc/codecs/wcd-mbhc-adc.c index c57c011dfd..47c7ebf62f 100644 --- a/asoc/codecs/wcd-mbhc-adc.c +++ b/asoc/codecs/wcd-mbhc-adc.c @@ -33,16 +33,20 @@ static int wcd_mbhc_get_micbias(struct wcd_mbhc *mbhc) int micbias = 0; u8 vout_ctl = 0; - /* Read MBHC Micbias (Mic Bias2) voltage */ - WCD_MBHC_REG_READ(WCD_MBHC_MICB2_VOUT, vout_ctl); - - /* Formula for getting micbias from vout - * micbias = 1.0V + VOUT_CTL * 50mV - */ - micbias = 1000 + (vout_ctl * 50); - pr_debug("%s: vout_ctl: %d, micbias: %d\n", - __func__, vout_ctl, micbias); + if (mbhc->mbhc_cb->get_micbias_val) { + mbhc->mbhc_cb->get_micbias_val(mbhc, &micbias); + pr_debug("%s: micbias: %d\n", __func__, micbias); + } else { + /* Read MBHC Micbias (Mic Bias2) voltage */ + WCD_MBHC_REG_READ(WCD_MBHC_MICB2_VOUT, vout_ctl); + /* Formula for getting micbias from vout + * micbias = 1.0V + VOUT_CTL * 50mV + */ + micbias = 1000 + (vout_ctl * 50); + pr_debug("%s: vout_ctl: %d, micbias: %d\n", + __func__, vout_ctl, micbias); + } return micbias; } diff --git a/asoc/codecs/wcd-mbhc-v2.c b/asoc/codecs/wcd-mbhc-v2.c index 0da12eb653..5b07fcca23 100644 --- a/asoc/codecs/wcd-mbhc-v2.c +++ b/asoc/codecs/wcd-mbhc-v2.c @@ -80,11 +80,17 @@ static void wcd_program_hs_vref(struct wcd_mbhc *mbhc) struct snd_soc_component *component = mbhc->component; u32 reg_val; - plug_type_cfg = WCD_MBHC_CAL_PLUG_TYPE_PTR(mbhc->mbhc_cfg->calibration); - reg_val = ((plug_type_cfg->v_hs_max - HS_VREF_MIN_VAL) / 100); + if (mbhc->mbhc_cb->hs_vref_max_update) { + mbhc->mbhc_cb->hs_vref_max_update(mbhc); + } else { + plug_type_cfg = WCD_MBHC_CAL_PLUG_TYPE_PTR( + mbhc->mbhc_cfg->calibration); + reg_val = ((plug_type_cfg->v_hs_max - HS_VREF_MIN_VAL) / 100); - dev_dbg(component->dev, "%s: reg_val = %x\n", __func__, reg_val); - WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_VREF, reg_val); + dev_dbg(component->dev, "%s: reg_val = %x\n", + __func__, reg_val); + WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_VREF, reg_val); + } } static void wcd_program_btn_threshold(const struct wcd_mbhc *mbhc, bool micbias) @@ -993,6 +999,14 @@ static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc) mbhc->mbhc_cb->enable_mb_source(mbhc, true); mbhc->btn_press_intr = false; mbhc->is_btn_press = false; + /* + * When current source mode doesn't work properly + * use mic bias pull up mode for button interrupts + * to function properly + */ + if (mbhc->mbhc_cb->mbhc_micb_pullup_control) + mbhc->mbhc_cb->mbhc_micb_pullup_control(component, + true); if (mbhc->mbhc_fn) mbhc->mbhc_fn->wcd_mbhc_detect_plug_type(mbhc); } else if ((mbhc->current_plug != MBHC_PLUG_TYPE_NONE) @@ -1070,6 +1084,10 @@ static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc) false); } + if (mbhc->mbhc_cb->mbhc_micb_pullup_control) + mbhc->mbhc_cb->mbhc_micb_pullup_control(component, + false); + } else if (!detection_type) { /* Disable external voltage source to micbias if present */ if (mbhc->mbhc_cb->enable_mb_source) diff --git a/include/asoc/wcd-mbhc-v2.h b/include/asoc/wcd-mbhc-v2.h index c7e412b344..392e59418d 100644 --- a/include/asoc/wcd-mbhc-v2.h +++ b/include/asoc/wcd-mbhc-v2.h @@ -456,6 +456,12 @@ struct wcd_mbhc_register { }; struct wcd_mbhc_cb { + void (*mbhc_micb_pullup_control) + (struct snd_soc_component *component, bool enable); + void (*get_micbias_val) + (struct wcd_mbhc *mbhc, int *mb); + void (*hs_vref_max_update) + (struct wcd_mbhc *mbhc); void (*bcs_enable) (struct wcd_mbhc *mbhc, bool bcs_enable); int (*enable_mb_source)(struct wcd_mbhc *mbhc, bool turn_on); From 18ab3445283af4a21232a818fe4b958ac67e343d Mon Sep 17 00:00:00 2001 From: Xiaoyu Ye Date: Mon, 13 Apr 2020 10:42:00 -0700 Subject: [PATCH 048/116] lsm: add support for SVA multi sound model Add support in audio drivers to support multiple sound models to be registered individually to the same module within a single instance in ADSP. Change-Id: I7d1abb206c7505ed10f0384b8286d5000416e1be Signed-off-by: Xiaoyu Ye --- asoc/msm-lsm-client.c | 438 +++++++++++++++++++------- dsp/q6lsm.c | 234 +++++++++----- include/dsp/q6lsm.h | 23 +- include/uapi/audio/sound/lsm_params.h | 9 +- 4 files changed, 513 insertions(+), 191 deletions(-) diff --git a/asoc/msm-lsm-client.c b/asoc/msm-lsm-client.c index 96fbee5bde..017323161d 100644 --- a/asoc/msm-lsm-client.c +++ b/asoc/msm-lsm-client.c @@ -499,38 +499,71 @@ static int msm_lsm_get_conf_levels(struct lsm_client *client, { int rc = 0; - if (client->num_confidence_levels == 0) { - pr_debug("%s: no confidence levels provided\n", - __func__); - client->confidence_levels = NULL; - goto done; - } - - client->confidence_levels = - kzalloc((sizeof(uint8_t) * client->num_confidence_levels), - GFP_KERNEL); - if (!client->confidence_levels) { - pr_err("%s: No memory for confidence\n" - "levels num of level from user = %d\n", - __func__, client->num_confidence_levels); - rc = -ENOMEM; + if (client->num_sound_models != 0) { + if (client->num_keywords == 0) { + pr_debug("%s: no number of confidence_values provided\n", + __func__); + client->multi_snd_model_confidence_levels = NULL; goto done; - } + } - if (copy_from_user(client->confidence_levels, - conf_levels_ptr, - client->num_confidence_levels)) { - pr_err("%s: copy from user failed, size = %d\n", - __func__, client->num_confidence_levels); - rc = -EFAULT; - goto copy_err; - } + client->multi_snd_model_confidence_levels = + kzalloc((sizeof(uint32_t) * client->num_keywords), + GFP_KERNEL); + if (!client->multi_snd_model_confidence_levels) { + pr_err("%s: No memory for confidence\n" + "levels num of level from user = %d\n", + __func__, client->num_keywords); + rc = -ENOMEM; + goto done; + } + if (copy_from_user((u8 *)client->multi_snd_model_confidence_levels, + conf_levels_ptr, + sizeof(uint32_t) * client->num_keywords)) { + pr_err("%s: copy from user failed, number of keywords = %d\n", + __func__, client->num_keywords); + rc = -EFAULT; + goto copy_err; + } + } else { + if (client->num_confidence_levels == 0) { + pr_debug("%s: no confidence levels provided\n", + __func__); + client->confidence_levels = NULL; + goto done; + } + + client->confidence_levels = + kzalloc((sizeof(uint8_t) * client->num_confidence_levels), + GFP_KERNEL); + if (!client->confidence_levels) { + pr_err("%s: No memory for confidence\n" + "levels num of level from user = %d\n", + __func__, client->num_confidence_levels); + rc = -ENOMEM; + goto done; + } + + if (copy_from_user(client->confidence_levels, + conf_levels_ptr, + client->num_confidence_levels)) { + pr_err("%s: copy from user failed, size = %d\n", + __func__, client->num_confidence_levels); + rc = -EFAULT; + goto copy_err; + } + } return rc; copy_err: - kfree(client->confidence_levels); - client->confidence_levels = NULL; + if (client->num_sound_models != 0) { + kfree(client->multi_snd_model_confidence_levels); + client->multi_snd_model_confidence_levels = NULL; + } else { + kfree(client->confidence_levels); + client->confidence_levels = NULL; + } done: return rc; @@ -652,35 +685,67 @@ static int msm_lsm_set_conf(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; int rc = 0; - if (p_info->param_size > MAX_NUM_CONFIDENCE) { - dev_err(rtd->dev, - "%s: invalid confidence levels %d\n", - __func__, p_info->param_size); - return -EINVAL; - } + if (p_info->param_type == LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS) { + if (p_info->param_size > MAX_KEYWORDS_SUPPORTED) { + dev_err(rtd->dev, + "%s: invalid number of snd_model keywords %d, the max is %d\n", + __func__, p_info->param_size, MAX_KEYWORDS_SUPPORTED); + return -EINVAL; + } - prtd->lsm_client->num_confidence_levels = - p_info->param_size; - rc = msm_lsm_get_conf_levels(prtd->lsm_client, - p_info->param_data); - if (rc) { - dev_err(rtd->dev, - "%s: get_conf_levels failed, err = %d\n", - __func__, rc); - return rc; - } + prtd->lsm_client->num_keywords = p_info->param_size; + rc = msm_lsm_get_conf_levels(prtd->lsm_client, + p_info->param_data); + if (rc) { + dev_err(rtd->dev, + "%s: get_conf_levels failed for snd_model %d, err = %d\n", + __func__, p_info->model_id, rc); + return rc; + } - rc = q6lsm_set_one_param(prtd->lsm_client, p_info, - prtd->lsm_client->confidence_levels, - LSM_MIN_CONFIDENCE_LEVELS); - if (rc) - dev_err(rtd->dev, - "%s: Failed to set min_conf_levels, err = %d\n", - __func__, rc); + rc = q6lsm_set_one_param(prtd->lsm_client, p_info, + prtd->lsm_client->multi_snd_model_confidence_levels, + LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS); + if (rc) + dev_err(rtd->dev, + "%s: Failed to set multi_snd_model_confidence_levels, err = %d\n", + __func__, rc); - if (prtd->lsm_client->confidence_levels) { - kfree(prtd->lsm_client->confidence_levels); - prtd->lsm_client->confidence_levels = NULL; + if (prtd->lsm_client->multi_snd_model_confidence_levels) { + kfree(prtd->lsm_client->multi_snd_model_confidence_levels); + prtd->lsm_client->multi_snd_model_confidence_levels = NULL; + } + } else { + if (p_info->param_size > MAX_NUM_CONFIDENCE) { + dev_err(rtd->dev, + "%s: invalid confidence levels %d\n", + __func__, p_info->param_size); + return -EINVAL; + } + + prtd->lsm_client->num_confidence_levels = + p_info->param_size; + rc = msm_lsm_get_conf_levels(prtd->lsm_client, + p_info->param_data); + if (rc) { + dev_err(rtd->dev, + "%s: get_conf_levels failed, err = %d\n", + __func__, rc); + return rc; + } + + rc = q6lsm_set_one_param(prtd->lsm_client, p_info, + prtd->lsm_client->confidence_levels, + LSM_MIN_CONFIDENCE_LEVELS); + if (rc) + dev_err(rtd->dev, + "%s: Failed to set min_conf_levels, err = %d\n", + __func__, rc); + + if (prtd->lsm_client->confidence_levels) { + kfree(prtd->lsm_client->confidence_levels); + prtd->lsm_client->confidence_levels = NULL; + } } return rc; } @@ -691,66 +756,166 @@ static int msm_lsm_reg_model(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; struct lsm_priv *prtd = runtime->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data; - int rc = 0; + int rc = 0, stage_idx = p_info->stage_idx; struct lsm_sound_model *sm = NULL; size_t offset = sizeof(union param_hdrs); + struct lsm_client *client = prtd->lsm_client; - rc = q6lsm_snd_model_buf_alloc(prtd->lsm_client, - p_info->param_size, p_info); - if (rc) { + if (p_info->model_id != 0 && + p_info->param_type == LSM_REG_MULTI_SND_MODEL) { + sm = kzalloc(sizeof(*sm), GFP_KERNEL); + if (sm == NULL) { + dev_err(rtd->dev, "%s: snd_model kzalloc failed\n", __func__); + return -ENOMEM; + } + + INIT_LIST_HEAD(&sm->list); + + rc = q6lsm_snd_model_buf_alloc(client, p_info->param_size, p_info, sm); + if (rc) { + dev_err(rtd->dev, "%s: snd_model buf alloc failed, size = %d\n", + __func__, p_info->param_size); + goto err_buf_alloc; + } + + q6lsm_sm_set_param_data(client, p_info, &offset, sm); + + /* + * For set_param, advance the sound model data with the + * number of bytes required by param_data. + */ + if (copy_from_user((u8 *)sm->data + offset, + p_info->param_data, p_info->param_size)) { + dev_err(rtd->dev, + "%s: copy_from_user for snd_model %d failed, size = %d\n", + __func__, p_info->model_id, p_info->param_size); + rc = -EFAULT; + goto err_copy; + } + /* Add this sound model to the list of multi sound models */ + list_add_tail(&sm->list, &client->stage_cfg[stage_idx].sound_models); + + rc = q6lsm_set_one_param(client, p_info, NULL, + LSM_REG_MULTI_SND_MODEL); + if (rc) { + dev_err(rtd->dev, + "%s: Failed to register snd_model %d, err = %d\n", + __func__, p_info->model_id, rc); + goto err_copy; + } + + client->num_sound_models++; + dev_dbg(rtd->dev, + "%s: registered snd_model: %d, total num of snd_model: %d\n", + __func__, p_info->model_id, client->num_sound_models); + } else if (p_info->model_id == 0 && + p_info->param_type == LSM_REG_SND_MODEL) { + sm = &client->stage_cfg[stage_idx].sound_model; + + rc = q6lsm_snd_model_buf_alloc(client, p_info->param_size, p_info, sm); + if (rc) { + dev_err(rtd->dev, "%s: snd_model buf alloc failed, size = %d\n", + __func__, p_info->param_size); + return rc; + } + + q6lsm_sm_set_param_data(client, p_info, &offset, sm); + + /* + * For set_param, advance the sound model data with the + * number of bytes required by param_data. + */ + + if (copy_from_user((u8 *)sm->data + offset, + p_info->param_data, p_info->param_size)) { + dev_err(rtd->dev, + "%s: copy_from_user for snd_model failed, size = %d\n", + __func__, p_info->param_size); + rc = -EFAULT; + goto err_copy; + } + rc = q6lsm_set_one_param(client, p_info, NULL, LSM_REG_SND_MODEL); + if (rc) { + dev_err(rtd->dev, "%s: Failed to register snd_model, err = %d\n", + __func__, rc); + goto err_copy; + } + } else { dev_err(rtd->dev, - "%s: snd_model buf alloc failed, size = %d\n", - __func__, p_info->param_size); - return rc; - } - - q6lsm_sm_set_param_data(prtd->lsm_client, p_info, &offset); - - /* - * For set_param, advance the sound model data with the - * number of bytes required by param_data. - */ - - sm = &prtd->lsm_client->stage_cfg[p_info->stage_idx].sound_model; - if (copy_from_user((u8 *)sm->data + offset, - p_info->param_data, p_info->param_size)) { - dev_err(rtd->dev, - "%s: copy_from_user for snd_model failed, size = %d\n", - __func__, p_info->param_size); - rc = -EFAULT; - goto err_copy; - } - rc = q6lsm_set_one_param(prtd->lsm_client, p_info, NULL, - LSM_REG_SND_MODEL); - if (rc) { - dev_err(rtd->dev, - "%s: Failed to set sound_model, err = %d\n", - __func__, rc); - goto err_copy; + "%s: snd_model id %d is invalid for param type %d\n", + __func__, p_info->model_id, p_info->param_type); } return rc; err_copy: - q6lsm_snd_model_buf_free(prtd->lsm_client, p_info); + q6lsm_snd_model_buf_free(client, p_info, sm); +err_buf_alloc: + if (p_info->model_id != 0) { + list_del(&sm->list); + kfree(sm); + sm = NULL; + } return rc; } static int msm_lsm_dereg_model(struct snd_pcm_substream *substream, - struct lsm_params_info_v2 *p_info) + struct lsm_params_info_v2 *p_info) { struct snd_pcm_runtime *runtime = substream->runtime; struct lsm_priv *prtd = runtime->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct lsm_sound_model *sm = NULL; + struct lsm_client *client = prtd->lsm_client; int rc = 0; - rc = q6lsm_set_one_param(prtd->lsm_client, p_info, - NULL, LSM_DEREG_SND_MODEL); - if (rc) - dev_err(rtd->dev, - "%s: Failed to set det_mode param, err = %d\n", - __func__, rc); + if (p_info->model_id != 0 && + p_info->param_type == LSM_DEREG_MULTI_SND_MODEL) { + list_for_each_entry(sm, + &client->stage_cfg[p_info->stage_idx].sound_models, + list) { + dev_dbg(rtd->dev, + "%s: current snd_model: %d, looking for snd_model %d\n", + __func__, sm->model_id, p_info->model_id); + if (sm->model_id == p_info->model_id) + break; + } - q6lsm_snd_model_buf_free(prtd->lsm_client, p_info); + if (sm->model_id == p_info->model_id) { + rc = q6lsm_set_one_param(client, p_info, NULL, + LSM_DEREG_MULTI_SND_MODEL); + if (rc) + dev_err(rtd->dev, + "%s: Failed to deregister snd_model %d, err = %d\n", + __func__, p_info->model_id, rc); + + q6lsm_snd_model_buf_free(client, p_info, sm); + list_del(&sm->list); + kfree(sm); + sm = NULL; + client->num_sound_models--; + } else { + rc = -EINVAL; + dev_err(rtd->dev, + "%s: Failed to find snd_model, invalid model_id %d\n", + __func__, p_info->model_id); + } + } else if (p_info->model_id == 0 && + p_info->param_type == LSM_DEREG_SND_MODEL) { + rc = q6lsm_set_one_param(client, p_info, NULL, + LSM_DEREG_SND_MODEL); + if (rc) + dev_err(rtd->dev, + "%s: Failed to deregister snd_model, err = %d\n", + __func__, rc); + + sm = &client->stage_cfg[p_info->stage_idx].sound_model; + q6lsm_snd_model_buf_free(client, p_info, sm); + } else { + rc = -EINVAL; + dev_err(rtd->dev, + "%s: snd_model id %d is invalid for param type %d\n", + __func__, p_info->model_id, p_info->param_type); + } return rc; } @@ -992,6 +1157,22 @@ static int msm_lsm_process_params(struct snd_pcm_substream *substream, return -EINVAL; } + if (p_info->param_type == LSM_REG_MULTI_SND_MODEL && + prtd->lsm_client->num_sound_models == LSM_MAX_SOUND_MODELS_SUPPORTED) { + dev_err(rtd->dev, + "%s: maximum supported sound models(8) have already reached\n", + __func__); + return -EINVAL; + } + + if (p_info->param_type == LSM_DEREG_MULTI_SND_MODEL && + prtd->lsm_client->num_sound_models == 0) { + dev_err(rtd->dev, + "%s: no available sound model to be deregistered\n", + __func__); + return -EINVAL; + } + switch (p_info->param_type) { case LSM_ENDPOINT_DETECT_THRESHOLD: rc = msm_lsm_set_epd(substream, p_info); @@ -1003,12 +1184,15 @@ static int msm_lsm_process_params(struct snd_pcm_substream *substream, rc = msm_lsm_set_gain(substream, p_info); break; case LSM_MIN_CONFIDENCE_LEVELS: + case LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS: rc = msm_lsm_set_conf(substream, p_info); break; case LSM_REG_SND_MODEL: + case LSM_REG_MULTI_SND_MODEL: rc = msm_lsm_reg_model(substream, p_info); break; case LSM_DEREG_SND_MODEL: + case LSM_DEREG_MULTI_SND_MODEL: rc = msm_lsm_dereg_model(substream, p_info); break; case LSM_CUSTOM_PARAMS: @@ -1176,7 +1360,10 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, * also set stage index to LSM_STAGE_INDEX_FIRST. */ struct lsm_params_info_v2 p_info = {0}; + struct lsm_sound_model *sm = NULL; p_info.stage_idx = LSM_STAGE_INDEX_FIRST; + p_info.param_type = LSM_DEREG_SND_MODEL; + sm = &prtd->lsm_client->stage_cfg[p_info.stage_idx].sound_model; dev_dbg(rtd->dev, "%s: Registering sound model V2\n", __func__); @@ -1192,21 +1379,20 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, break; } rc = q6lsm_snd_model_buf_alloc(prtd->lsm_client, - snd_model_v2.data_size, &p_info); + snd_model_v2.data_size, &p_info, sm); if (rc) { dev_err(rtd->dev, "%s: q6lsm buffer alloc failed V2, size %d\n", __func__, snd_model_v2.data_size); break; } - if (copy_from_user( - prtd->lsm_client->stage_cfg[p_info.stage_idx].sound_model.data, - snd_model_v2.data, snd_model_v2.data_size)) { + if (copy_from_user(sm->data, snd_model_v2.data, + snd_model_v2.data_size)) { dev_err(rtd->dev, "%s: copy from user data failed\n" "data %pK size %d\n", __func__, snd_model_v2.data, snd_model_v2.data_size); - q6lsm_snd_model_buf_free(prtd->lsm_client, &p_info); + q6lsm_snd_model_buf_free(prtd->lsm_client, &p_info, sm); rc = -EFAULT; break; } @@ -1234,7 +1420,7 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, dev_err(rtd->dev, "%s: Register snd Model v2 failed =%d\n", __func__, rc); - q6lsm_snd_model_buf_free(prtd->lsm_client, &p_info); + q6lsm_snd_model_buf_free(prtd->lsm_client, &p_info, sm); } if (prtd->lsm_client->confidence_levels) { kfree(prtd->lsm_client->confidence_levels); @@ -1697,6 +1883,7 @@ struct lsm_params_info_v2_32 { uint32_t param_type; u16 instance_id; u16 stage_idx; + u32 model_id; }; struct snd_lsm_module_params_32 { @@ -2033,9 +2220,9 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, if (p_data.data_size != expected_size) { dev_err(rtd->dev, - "%s: %s: Invalid size %d\n", + "%s: %s: Invalid size %d, expected_size %d\n", __func__, "SET_MODULE_PARAMS(_V2)_32", - p_data.data_size); + p_data.data_size, expected_size); err = -EINVAL; goto done; } @@ -2071,6 +2258,7 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, p_info.instance_id = INSTANCE_ID_0; p_info.stage_idx = LSM_STAGE_INDEX_FIRST; + p_info.model_id = 0; p_info_32++; } else { @@ -2082,6 +2270,14 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, p_info.instance_id = p_info_v2_32->instance_id; p_info.stage_idx = p_info_v2_32->stage_idx; + /* set sound model id to 0 for backward compatibility */ + p_info.model_id = 0; + + if (LSM_REG_MULTI_SND_MODEL == p_info_v2_32->param_type || + LSM_DEREG_MULTI_SND_MODEL == p_info_v2_32->param_type || + LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS == + p_info_v2_32->param_type) + p_info.model_id = p_info_v2_32->model_id; p_info_v2_32++; } @@ -2208,7 +2404,6 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, case SNDRV_LSM_SET_MODULE_PARAMS_V2: { struct snd_lsm_module_params p_data; struct lsm_params_info *temp_ptr_info = NULL; - struct lsm_params_info_v2 info_v2; struct lsm_params_info_v2 *ptr_info_v2 = NULL, *temp_ptr_info_v2 = NULL; size_t p_size = 0, count; u8 *params; @@ -2277,26 +2472,37 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, for (count = 0; count < p_data.num_params; count++) { if (cmd == SNDRV_LSM_SET_MODULE_PARAMS) { /* convert to V2 param info struct from legacy param info */ - info_v2.module_id = temp_ptr_info->module_id; - info_v2.param_id = temp_ptr_info->param_id; - info_v2.param_size = temp_ptr_info->param_size; - info_v2.param_data = temp_ptr_info->param_data; - info_v2.param_type = temp_ptr_info->param_type; + ptr_info_v2->module_id = temp_ptr_info->module_id; + ptr_info_v2->param_id = temp_ptr_info->param_id; + ptr_info_v2->param_size = temp_ptr_info->param_size; + ptr_info_v2->param_data = temp_ptr_info->param_data; + ptr_info_v2->param_type = temp_ptr_info->param_type; - info_v2.instance_id = INSTANCE_ID_0; - info_v2.stage_idx = LSM_STAGE_INDEX_FIRST; + ptr_info_v2->instance_id = INSTANCE_ID_0; + ptr_info_v2->stage_idx = LSM_STAGE_INDEX_FIRST; + ptr_info_v2->model_id = 0; - ptr_info_v2 = &info_v2; temp_ptr_info++; } else { - /* Just copy the pointer as user already provided v2 params */ + if (LSM_REG_MULTI_SND_MODEL != temp_ptr_info_v2->param_type || + LSM_DEREG_MULTI_SND_MODEL != + temp_ptr_info_v2->param_type || + LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS != + temp_ptr_info_v2->param_type) { + /* set sound model id to 0 for backward compatibility */ + temp_ptr_info_v2->model_id = 0; + } + /* + * Just copy the pointer as user + * already provided sound model id + */ ptr_info_v2 = temp_ptr_info_v2; temp_ptr_info_v2++; } err = msm_lsm_process_params(substream, ptr_info_v2); if (err) dev_err(rtd->dev, - "%s: Failed to process param, type%d stage=%d err=%d\n", + "%s: Failed to process param, type=%d stage=%d err=%d\n", __func__, ptr_info_v2->param_type, ptr_info_v2->stage_idx, err); } @@ -2464,7 +2670,7 @@ static int msm_lsm_open(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct lsm_priv *prtd; struct snd_soc_pcm_runtime *rtd = substream->private_data; - int ret = 0; + int ret = 0, i; pr_debug("%s\n", __func__); prtd = kzalloc(sizeof(struct lsm_priv), GFP_KERNEL); @@ -2530,6 +2736,12 @@ static int msm_lsm_open(struct snd_pcm_substream *substream) prtd->lsm_client->event_type = LSM_DET_EVENT_TYPE_LEGACY; prtd->lsm_client->fe_id = rtd->dai_link->id; prtd->lsm_client->unprocessed_data = 0; + prtd->lsm_client->num_sound_models = 0; + prtd->lsm_client->num_keywords = 0; + prtd->lsm_client->multi_snd_model_confidence_levels = NULL; + + for (i = 0; i < LSM_MAX_STAGES_PER_SESSION; i++) + INIT_LIST_HEAD(&prtd->lsm_client->stage_cfg[i].sound_models); prtd->ws = wakeup_source_register(rtd->dev, "lsm-client"); diff --git a/dsp/q6lsm.c b/dsp/q6lsm.c index 4332629d9b..b44a7f474f 100644 --- a/dsp/q6lsm.c +++ b/dsp/q6lsm.c @@ -908,17 +908,15 @@ done: * @client: LSM client handle * @p_info: param info * @offset: pointer to retrieve size - * + * @sm: pointer to sound model */ void q6lsm_sm_set_param_data(struct lsm_client *client, - struct lsm_params_info_v2 *p_info, - size_t *offset) + struct lsm_params_info_v2 *p_info, + size_t *offset, struct lsm_sound_model *sm) { struct param_hdr_v3 param_hdr; int ret; - struct lsm_sound_model *sm; - sm = &client->stage_cfg[p_info->stage_idx].sound_model; memset(¶m_hdr, 0, sizeof(param_hdr)); param_hdr.module_id = p_info->module_id; @@ -926,6 +924,8 @@ void q6lsm_sm_set_param_data(struct lsm_client *client, param_hdr.param_id = p_info->param_id; param_hdr.param_size = p_info->param_size; + sm->model_id = p_info->model_id; + ret = q6lsm_pack_params(sm->data, ¶m_hdr, NULL, offset, LSM_SESSION_CMD_SET_PARAMS_V2); if (ret) @@ -1010,42 +1010,78 @@ EXPORT_SYMBOL(q6lsm_open); static int q6lsm_send_confidence_levels(struct lsm_client *client, struct param_hdr_v3 *param_info, - uint32_t set_param_opcode) + uint32_t set_param_opcode, uint32_t model_id) { struct lsm_param_confidence_levels *conf_levels = NULL; uint32_t num_conf_levels = client->num_confidence_levels; + struct lsm_param_multi_snd_model_conf_levels *multi_sm_conf_levels = NULL; + uint32_t num_keywords = client->num_keywords; uint8_t i = 0; uint8_t padd_size = 0; uint32_t param_size = 0; int rc = 0; - /* Data must be 4 byte aligned so add any necessary padding. */ - padd_size = (4 - (num_conf_levels % 4)) - 1; - param_size = (sizeof(uint8_t) + num_conf_levels + padd_size) * - sizeof(uint8_t); - param_info->param_size = param_size; - pr_debug("%s: Set Conf Levels PARAM SIZE = %d\n", __func__, param_size); + if (model_id != 0) { + /* No padding is need since the structure is always 4 byte aligend. + * The number "2" below represents the first two u32 variables in + * struct lsm_param_multi_snd_model_conf_levels. + */ + param_size = (2 + num_keywords) * sizeof(uint32_t); + param_info->param_size = param_size; + pr_debug("%s: Set Conf Levels PARAM SIZE: %d\n", __func__, param_size); - conf_levels = kzalloc(param_size, GFP_KERNEL); - if (!conf_levels) - return -ENOMEM; + multi_sm_conf_levels = kzalloc(param_size, GFP_KERNEL); + if (!multi_sm_conf_levels) + return -ENOMEM; - conf_levels->num_confidence_levels = num_conf_levels; - pr_debug("%s: Num conf_level = %d\n", __func__, num_conf_levels); + multi_sm_conf_levels->model_id = model_id; + multi_sm_conf_levels->num_keywords = num_keywords; + pr_debug("%s: snd_model id: %d, num_keywords: %d\n", + __func__, model_id, num_keywords); - memcpy(conf_levels->confidence_levels, client->confidence_levels, - num_conf_levels); - for (i = 0; i < num_conf_levels; i++) - pr_debug("%s: Confidence_level[%d] = %d\n", __func__, i, - conf_levels->confidence_levels[i]); + memcpy(multi_sm_conf_levels->confidence_levels, + client->multi_snd_model_confidence_levels, + sizeof(uint32_t) * num_keywords); + for (i = 0; i < num_keywords; i++) + pr_debug("%s: Confidence_level[%d] = %d\n", __func__, i, + multi_sm_conf_levels->confidence_levels[i]); - rc = q6lsm_pack_and_set_params(client, param_info, - (uint8_t *) conf_levels, - set_param_opcode); - if (rc) - pr_err("%s: Send confidence_levels cmd failed, err = %d\n", - __func__, rc); - kfree(conf_levels); + rc = q6lsm_pack_and_set_params(client, param_info, + (uint8_t *) multi_sm_conf_levels, + set_param_opcode); + if (rc) + pr_err("%s: Send multi_snd_model_conf_levels cmd failed, err %d\n", + __func__, rc); + kfree(multi_sm_conf_levels); + } else { + /* Data must be 4 byte aligned so add any necessary padding. */ + padd_size = (4 - (num_conf_levels % 4)) - 1; + param_size = (sizeof(uint8_t) + num_conf_levels + padd_size) * + sizeof(uint8_t); + param_info->param_size = param_size; + pr_debug("%s: Set Conf Levels PARAM SIZE = %d\n", __func__, param_size); + + conf_levels = kzalloc(param_size, GFP_KERNEL); + if (!conf_levels) + return -ENOMEM; + + conf_levels->num_confidence_levels = num_conf_levels; + pr_debug("%s: Num conf_level = %d\n", __func__, num_conf_levels); + + memcpy(conf_levels->confidence_levels, client->confidence_levels, + num_conf_levels); + for (i = 0; i < num_conf_levels; i++) + pr_debug("%s: Confidence_level[%d] = %d\n", __func__, i, + conf_levels->confidence_levels[i]); + + rc = q6lsm_pack_and_set_params(client, param_info, + (uint8_t *) conf_levels, + set_param_opcode); + if (rc) + pr_err("%s: Send confidence_levels cmd failed, err = %d\n", + __func__, rc); + kfree(conf_levels); + } return rc; } @@ -1459,7 +1495,7 @@ int q6lsm_set_data(struct lsm_client *client, param_hdr.param_id = LSM_PARAM_ID_MIN_CONFIDENCE_LEVELS; rc = q6lsm_send_confidence_levels(client, ¶m_hdr, - LSM_SESSION_CMD_SET_PARAMS); + LSM_SESSION_CMD_SET_PARAMS, 0); if (rc) { pr_err("%s: Failed to send conf_levels, err = %d\n", __func__, rc); @@ -1537,8 +1573,9 @@ EXPORT_SYMBOL(q6lsm_register_sound_model); */ int q6lsm_deregister_sound_model(struct lsm_client *client) { - int rc; + int rc = 0; struct lsm_cmd_reg_snd_model cmd; + struct lsm_sound_model *sm = NULL, *next = NULL; /* * With multi-stage support sm buff allocation/free usage param info * to check stage index for which this sound model is being set, and @@ -1564,19 +1601,39 @@ int q6lsm_deregister_sound_model(struct lsm_client *client) return -EINVAL; } - memset(&cmd, 0, sizeof(cmd)); - q6lsm_add_hdr(client, &cmd.hdr, sizeof(cmd.hdr), false); - cmd.hdr.opcode = LSM_SESSION_CMD_DEREGISTER_SOUND_MODEL; + if (client->num_sound_models > 0) { + p_info.param_type = LSM_DEREG_MULTI_SND_MODEL; + list_for_each_entry_safe(sm, next, + &client->stage_cfg[p_info.stage_idx].sound_models, + list) { + pr_debug("%s: current snd_model: %d, num of sound models left %d\n", + __func__, sm->model_id, client->num_sound_models); + q6lsm_snd_model_buf_free(client, &p_info, sm); + list_del(&sm->list); + kfree(sm); + sm = NULL; + client->num_sound_models--; - rc = q6lsm_apr_send_pkt(client, client->apr, &cmd.hdr, true, NULL); - if (rc) { - pr_err("%s: Failed cmd opcode 0x%x, rc %d\n", __func__, - cmd.hdr.opcode, rc); + if (0 == client->num_sound_models) + break; + } } else { - pr_debug("%s: Deregister sound model succeeded\n", __func__); - } + memset(&cmd, 0, sizeof(cmd)); + q6lsm_add_hdr(client, &cmd.hdr, sizeof(cmd.hdr), false); + cmd.hdr.opcode = LSM_SESSION_CMD_DEREGISTER_SOUND_MODEL; - q6lsm_snd_model_buf_free(client, &p_info); + rc = q6lsm_apr_send_pkt(client, client->apr, &cmd.hdr, true, NULL); + if (rc) { + pr_err("%s: Failed cmd opcode 0x%x, rc %d\n", __func__, + cmd.hdr.opcode, rc); + } else { + pr_debug("%s: Deregister sound model succeeded\n", __func__); + } + + p_info.param_type = LSM_DEREG_SND_MODEL; + sm = &client->stage_cfg[p_info.stage_idx].sound_model; + q6lsm_snd_model_buf_free(client, &p_info, sm); + } return rc; } @@ -1825,14 +1882,15 @@ fail: * * @client: LSM client handle * @p_info: sound model param info + * @sm: pointer to sound model * * Returns 0 on success or error on failure */ int q6lsm_snd_model_buf_free(struct lsm_client *client, - struct lsm_params_info_v2 *p_info) + struct lsm_params_info_v2 *p_info, + struct lsm_sound_model *sm) { int rc = 0, stage_idx = p_info->stage_idx; - struct lsm_sound_model *sm = NULL; pr_debug("%s: Session id %d\n", __func__, client->session); if (CHECK_SESSION(client->session)) { @@ -1840,11 +1898,11 @@ int q6lsm_snd_model_buf_free(struct lsm_client *client, return -EINVAL; } - if (!client->stage_cfg[stage_idx].sound_model.data) + if (p_info->param_type == LSM_DEREG_SND_MODEL && + !client->stage_cfg[stage_idx].sound_model.data) return 0; mutex_lock(&client->cmd_lock); - sm = &client->stage_cfg[stage_idx].sound_model; if (sm->mem_map_handle != 0) { rc = q6lsm_memory_unmap_regions(client, sm->mem_map_handle); if (rc) @@ -1858,7 +1916,10 @@ int q6lsm_snd_model_buf_free(struct lsm_client *client, sm->phys = 0; mutex_unlock(&client->cmd_lock); - rc = q6lsm_snd_cal_free(client, p_info); + if ((p_info->param_type == LSM_DEREG_MULTI_SND_MODEL && + client->num_sound_models == 1) || + p_info->param_type == LSM_DEREG_SND_MODEL) + rc = q6lsm_snd_cal_free(client, p_info); return rc; } EXPORT_SYMBOL(q6lsm_snd_model_buf_free); @@ -1980,20 +2041,20 @@ static int q6lsm_mmapcallback(struct apr_client_data *data, void *priv) * Returns 0 on success or error on failure */ int q6lsm_snd_model_buf_alloc(struct lsm_client *client, size_t len, - struct lsm_params_info_v2 *p_info) + struct lsm_params_info_v2 *p_info, + struct lsm_sound_model *sm) { int rc = -EINVAL, stage_idx = p_info->stage_idx; + int model_id = p_info->model_id; size_t total_mem = 0; - struct lsm_sound_model *sm = NULL; if (!client) return rc; - pr_debug("%s:Snd Model len = %zd, stage idx %d\n", - __func__, len, stage_idx); + pr_debug("%s:Snd Model len %zd, stage_idx %d, model_id %d\n", + __func__, len, stage_idx, model_id); mutex_lock(&client->cmd_lock); - sm = &client->stage_cfg[stage_idx].sound_model; if (!sm->data) { /* * If sound model is sent as set_param, i.e. param_id != 0, @@ -2008,7 +2069,7 @@ int q6lsm_snd_model_buf_alloc(struct lsm_client *client, size_t len, pr_debug("%s: sm param size %zd Total mem %zd, stage_idx %d\n", __func__, len, total_mem, stage_idx); rc = msm_audio_ion_alloc(&sm->dma_buf, total_mem, - &sm->phys, &len, &sm->data); + &sm->phys, &len, &sm->data); if (rc) { pr_err("%s: Audio ION alloc is failed, rc = %d, stage_idx = %d\n", __func__, rc, stage_idx); @@ -2040,7 +2101,7 @@ int q6lsm_snd_model_buf_alloc(struct lsm_client *client, size_t len, fail: mutex_unlock(&client->cmd_lock); fail_1: - q6lsm_snd_model_buf_free(client, p_info); + q6lsm_snd_model_buf_free(client, p_info, sm); return rc; } EXPORT_SYMBOL(q6lsm_snd_model_buf_alloc); @@ -2126,8 +2187,8 @@ static int q6lsm_send_param_gain(struct lsm_client *client, u16 gain, * Returns 0 on success or error on failure */ int q6lsm_set_one_param(struct lsm_client *client, - struct lsm_params_info_v2 *p_info, void *data, - uint32_t param_type) + struct lsm_params_info_v2 *p_info, + void *data, uint32_t param_type) { struct param_hdr_v3 param_info; int rc = 0; @@ -2186,14 +2247,19 @@ int q6lsm_set_one_param(struct lsm_client *client, } case LSM_MIN_CONFIDENCE_LEVELS: + case LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS: param_info.module_id = p_info->module_id; param_info.instance_id = p_info->instance_id; param_info.param_id = p_info->param_id; rc = q6lsm_send_confidence_levels( - client, ¶m_info, LSM_SESSION_CMD_SET_PARAMS_V2); + client, ¶m_info, LSM_SESSION_CMD_SET_PARAMS_V2, + p_info->model_id); if (rc) - pr_err("%s: CONFIDENCE_LEVELS cmd failed, rc %d\n", - __func__, rc); + pr_err("%s: %s cmd failed, rc %d\n", + __func__, + param_type == LSM_MIN_CONFIDENCE_LEVELS ? + "LSM_MIN_CONFIDENCE_LEVELS" : + "LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS", rc); break; case LSM_POLLING_ENABLE: { struct snd_lsm_poll_enable *lsm_poll_enable = @@ -2210,7 +2276,8 @@ int q6lsm_set_one_param(struct lsm_client *client, break; } - case LSM_REG_SND_MODEL: { + case LSM_REG_SND_MODEL: + case LSM_REG_MULTI_SND_MODEL: { struct mem_mapping_hdr mem_hdr; u32 payload_size; struct lsm_sound_model *sm = NULL; @@ -2224,8 +2291,18 @@ int q6lsm_set_one_param(struct lsm_client *client, payload_size = p_info->param_size + sizeof(struct param_hdr_v2); - sm = &client->stage_cfg[p_info->stage_idx].sound_model; - + if (param_type == LSM_REG_MULTI_SND_MODEL) { + list_for_each_entry(sm, + &client->stage_cfg[p_info->stage_idx].sound_models, + list) { + pr_debug("%s: current snd_model: %d, looking for snd_model %d\n", + __func__, sm->model_id, p_info->model_id); + if (sm->model_id == p_info->model_id) + break; + } + } else { + sm = &client->stage_cfg[p_info->stage_idx].sound_model; + } mem_hdr.data_payload_addr_lsw = lower_32_bits(sm->phys); mem_hdr.data_payload_addr_msw = @@ -2236,28 +2313,41 @@ int q6lsm_set_one_param(struct lsm_client *client, rc = q6lsm_set_params(client, &mem_hdr, NULL, payload_size, LSM_SESSION_CMD_SET_PARAMS_V2); if (rc) { - pr_err("%s: REG_SND_MODEL failed, rc %d\n", - __func__, rc); + pr_err("%s: %s failed, rc %d\n", + __func__, param_type == LSM_REG_SND_MODEL ? + "LSM_REG_SND_MODEL" : "LSM_REG_MULTI_SND_MODEL", rc); return rc; } - rc = q6lsm_send_cal(client, LSM_SESSION_CMD_SET_PARAMS, p_info); - if (rc) - pr_err("%s: Failed to send lsm cal, err = %d\n", - __func__, rc); + if (client->num_sound_models == 0) { + rc = q6lsm_send_cal(client, LSM_SESSION_CMD_SET_PARAMS, p_info); + if (rc) + pr_err("%s: Failed to send lsm cal, err = %d\n", + __func__, rc); + } break; } - case LSM_DEREG_SND_MODEL: { + case LSM_DEREG_SND_MODEL: + case LSM_DEREG_MULTI_SND_MODEL: { param_info.module_id = p_info->module_id; param_info.instance_id = p_info->instance_id; param_info.param_id = p_info->param_id; param_info.param_size = 0; - rc = q6lsm_pack_and_set_params(client, ¶m_info, NULL, - LSM_SESSION_CMD_SET_PARAMS_V2); + + if (param_type == LSM_DEREG_MULTI_SND_MODEL) { + param_info.param_size = p_info->param_size; + rc = q6lsm_pack_and_set_params(client, ¶m_info, + (uint8_t *)&p_info->model_id, + LSM_SESSION_CMD_SET_PARAMS_V2); + } else { + rc = q6lsm_pack_and_set_params(client, ¶m_info, NULL, + LSM_SESSION_CMD_SET_PARAMS_V2); + } if (rc) - pr_err("%s: DEREG_SND_MODEL failed, rc %d\n", - __func__, rc); + pr_err("%s: %s failed, rc %d\n", + __func__, param_type == LSM_DEREG_SND_MODEL ? + "LSM_DEREG_SND_MODEL" : "LSM_DEREG_MULTI_SND_MODEL", rc); break; } diff --git a/include/dsp/q6lsm.h b/include/dsp/q6lsm.h index 1eaeb3e586..e4431bc912 100644 --- a/include/dsp/q6lsm.h +++ b/include/dsp/q6lsm.h @@ -22,6 +22,10 @@ #define MAX_LSM_SESSIONS 8 +#define MAX_KEYWORDS_SUPPORTED 8 + +#define LSM_MAX_SOUND_MODELS_SUPPORTED 8 + typedef void (*lsm_app_cb)(uint32_t opcode, uint32_t token, uint32_t *payload, uint16_t client_size, void *priv); @@ -32,6 +36,8 @@ struct lsm_sound_model { uint32_t actual_size; /* actual number of bytes read by DSP */ struct dma_buf *dma_buf; uint32_t mem_map_handle; + uint32_t model_id; + struct list_head list; }; struct snd_lsm_event_status_v2 { @@ -71,6 +77,7 @@ struct lsm_stage_config { bool lab_enable; struct lsm_sound_model sound_model; struct lsm_cal_data_info cal_info; + struct list_head sound_models; }; @@ -106,6 +113,9 @@ struct lsm_client { struct lsm_stage_config stage_cfg[LSM_MAX_STAGES_PER_SESSION]; uint64_t fe_id; uint16_t unprocessed_data; + uint32_t num_sound_models; + uint32_t num_keywords; + uint32_t *multi_snd_model_confidence_levels; }; struct lsm_stream_cmd_open_tx { @@ -193,6 +203,11 @@ struct lsm_param_media_fmt_v2 { uint8_t channel_mapping[0]; } __packed; +struct lsm_param_multi_snd_model_conf_levels { + uint32_t model_id; + uint32_t num_keywords; + uint32_t confidence_levels[0]; +} __packed; struct lsm_param_confidence_levels { uint8_t num_confidence_levels; @@ -268,9 +283,9 @@ int q6lsm_open(struct lsm_client *client, uint16_t app_id); int q6lsm_start(struct lsm_client *client, bool wait); int q6lsm_stop(struct lsm_client *client, bool wait); int q6lsm_snd_model_buf_alloc(struct lsm_client *client, size_t len, - struct lsm_params_info_v2 *p_info); + struct lsm_params_info_v2 *p_info, struct lsm_sound_model *sm); int q6lsm_snd_model_buf_free(struct lsm_client *client, - struct lsm_params_info_v2 *p_info); + struct lsm_params_info_v2 *p_info, struct lsm_sound_model *sm); int q6lsm_close(struct lsm_client *client); int q6lsm_register_sound_model(struct lsm_client *client, enum lsm_detection_mode mode, @@ -290,8 +305,8 @@ int q6lsm_set_one_param(struct lsm_client *client, struct lsm_params_info_v2 *p_info, void *data, uint32_t param_type); void q6lsm_sm_set_param_data(struct lsm_client *client, - struct lsm_params_info_v2 *p_info, - size_t *offset); + struct lsm_params_info_v2 *p_info, size_t *offset, + struct lsm_sound_model *sm); int q6lsm_set_port_connected(struct lsm_client *client); int q6lsm_set_fwk_mode_cfg(struct lsm_client *client, uint32_t event_mode); int q6lsm_set_media_fmt_params(struct lsm_client *client); diff --git a/include/uapi/audio/sound/lsm_params.h b/include/uapi/audio/sound/lsm_params.h index fa435204fa..722d3ba726 100644 --- a/include/uapi/audio/sound/lsm_params.h +++ b/include/uapi/audio/sound/lsm_params.h @@ -6,7 +6,7 @@ #include -#define SNDRV_LSM_VERSION SNDRV_PROTOCOL_VERSION(0, 3, 1) +#define SNDRV_LSM_VERSION SNDRV_PROTOCOL_VERSION(0, 3, 2) #define LSM_MAX_STAGES_PER_SESSION 2 #define LSM_STAGE_INDEX_FIRST 0 @@ -33,7 +33,10 @@ #define LSM_POLLING_ENABLE (7) #define LSM_DET_EVENT_TYPE (8) #define LSM_LAB_CONTROL (9) -#define LSM_PARAMS_MAX (LSM_LAB_CONTROL + 1) +#define LSM_REG_MULTI_SND_MODEL (10) +#define LSM_DEREG_MULTI_SND_MODEL (11) +#define LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS (12) +#define LSM_PARAMS_MAX (LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS + 1) #define LSM_EVENT_NON_TIME_STAMP_MODE (0) #define LSM_EVENT_TIME_STAMP_MODE (1) @@ -226,6 +229,7 @@ struct lsm_params_info { * Member variables applicable only to V2: * @instance_id: instance id of the param to which parameter is to be set * @stage_idx: detection stage for which the param is applicable + * @model_id: an unique number to identify sound models in DSP */ struct lsm_params_info_v2 { __u32 module_id; @@ -235,6 +239,7 @@ struct lsm_params_info_v2 { __u32 param_type; __u16 instance_id; __u16 stage_idx; + __u32 model_id; }; /* From 313aa17ac428f67a027bc06d020a514ac7e18342 Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Wed, 29 Apr 2020 20:43:53 +0530 Subject: [PATCH 049/116] asoc: codecs: Add comparator autozeroing support for rouleur When current source mode is enabled, comparator auto zeroing should be turned ON by HW. As rouleur codec HW doesn't do this automatically, add this support in SW to set the auto zero enable before FSM enable and reset to auto once FSM is enabled. Disable surge protection before ADC measurements and change HPHL and HPHR thresholds while identifying cross connection for proper accessory identification. Change-Id: Ib775de0f0bdb6c655a3c0eb4775276acfbca1e84 Signed-off-by: Aditya Bavanari --- asoc/codecs/rouleur/rouleur-mbhc.c | 59 +++++++++++++++++++----------- asoc/codecs/rouleur/rouleur.c | 36 ++++++++++++++---- asoc/codecs/wcd-mbhc-adc.c | 29 ++++++++++++++- asoc/codecs/wcd-mbhc-v2.c | 30 ++++----------- include/asoc/wcd-mbhc-v2.h | 14 +++++-- 5 files changed, 112 insertions(+), 56 deletions(-) diff --git a/asoc/codecs/rouleur/rouleur-mbhc.c b/asoc/codecs/rouleur/rouleur-mbhc.c index 78bef6a8ed..2f8e954b5a 100644 --- a/asoc/codecs/rouleur/rouleur-mbhc.c +++ b/asoc/codecs/rouleur/rouleur-mbhc.c @@ -37,6 +37,10 @@ #define ROULEUR_MBHC_ZDET_CONST (86 * 16384) #define ROULEUR_MBHC_MOISTURE_RREF R_24_KOHM +/* Cross connection thresholds in mV */ +#define ROULEUR_HPHL_CROSS_CONN_THRESHOLD 200 +#define ROULEUR_HPHR_CROSS_CONN_THRESHOLD 200 + static struct wcd_mbhc_register wcd_mbhc_registers[WCD_MBHC_REG_FUNC_MAX] = { WCD_MBHC_REGISTER("WCD_MBHC_L_DET_EN", @@ -320,11 +324,11 @@ static void rouleur_mbhc_micb_ramp_control(struct snd_soc_component *component, 0x1C, 0x0C); snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_MICB2_RAMP, - 0xA0, 0x80); + 0x80, 0x80); } else { snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_MICB2_RAMP, - 0xA0, 0x00); + 0x80, 0x00); snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_MICB2_RAMP, 0x1C, 0x00); @@ -820,15 +824,6 @@ static void rouleur_mbhc_bcs_enable(struct wcd_mbhc *mbhc, rouleur_disable_bcs_before_slow_insert(mbhc->component, true); } -static void rouleur_mbhc_hs_vref_max_update(struct wcd_mbhc *mbhc) -{ - struct snd_soc_component *component = mbhc->component; - - /* Update the HS Vref max voltage to 1.7V */ - snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_CTL_2, - 0x03, 0x03); -} - static void rouleur_mbhc_get_micbias_val(struct wcd_mbhc *mbhc, int *mb) { u8 vout_ctl = 0; @@ -843,19 +838,40 @@ static void rouleur_mbhc_get_micbias_val(struct wcd_mbhc *mbhc, int *mb) pr_debug("%s: vout_ctl: %d, micbias: %d\n", __func__, vout_ctl, *mb); } -static void rouleur_mbhc_micb_pullup_control( - struct snd_soc_component *component, - bool pullup_enable) +static void rouleur_mbhc_comp_autozero_control(struct wcd_mbhc *mbhc, + bool az_enable) { - if (pullup_enable) - rouleur_micbias_control(component, MIC_BIAS_2, - MICB_PULLUP_ENABLE, false); + if (az_enable) + snd_soc_component_update_bits(mbhc->component, + ROULEUR_ANA_MBHC_MCLK, 0x08, 0x08); else - rouleur_micbias_control(component, MIC_BIAS_2, - MICB_PULLUP_DISABLE, false); + snd_soc_component_update_bits(mbhc->component, + ROULEUR_ANA_MBHC_MCLK, 0x08, 0x00); } +static void rouleur_mbhc_surge_control(struct wcd_mbhc *mbhc, + bool surge_enable) +{ + if (surge_enable) + snd_soc_component_update_bits(mbhc->component, + ROULEUR_ANA_SURGE_EN, 0xC0, 0xC0); + else + snd_soc_component_update_bits(mbhc->component, + ROULEUR_ANA_SURGE_EN, 0xC0, 0x00); + +} + +static void rouleur_mbhc_update_cross_conn_thr(struct wcd_mbhc *mbhc) +{ + mbhc->hphl_cross_conn_thr = ROULEUR_HPHL_CROSS_CONN_THRESHOLD; + mbhc->hphr_cross_conn_thr = ROULEUR_HPHR_CROSS_CONN_THRESHOLD; + + pr_debug("%s: Cross connection threshold for hphl: %d, hphr: %d\n", + __func__, mbhc->hphl_cross_conn_thr, + mbhc->hphr_cross_conn_thr); +} + static const struct wcd_mbhc_cb mbhc_cb = { .request_irq = rouleur_mbhc_request_irq, .irq_control = rouleur_mbhc_irq_control, @@ -880,9 +896,10 @@ static const struct wcd_mbhc_cb mbhc_cb = { .mbhc_get_moisture_status = rouleur_mbhc_get_moisture_status, .mbhc_moisture_detect_en = rouleur_mbhc_moisture_detect_en, .bcs_enable = rouleur_mbhc_bcs_enable, - .hs_vref_max_update = rouleur_mbhc_hs_vref_max_update, .get_micbias_val = rouleur_mbhc_get_micbias_val, - .mbhc_micb_pullup_control = rouleur_mbhc_micb_pullup_control, + .mbhc_comp_autozero_control = rouleur_mbhc_comp_autozero_control, + .mbhc_surge_ctl = rouleur_mbhc_surge_control, + .update_cross_conn_thr = rouleur_mbhc_update_cross_conn_thr, }; static int rouleur_get_hph_type(struct snd_kcontrol *kcontrol, diff --git a/asoc/codecs/rouleur/rouleur.c b/asoc/codecs/rouleur/rouleur.c index cdb1de2c69..e1ecdba83f 100644 --- a/asoc/codecs/rouleur/rouleur.c +++ b/asoc/codecs/rouleur/rouleur.c @@ -107,6 +107,9 @@ static int rouleur_handle_post_irq(void *data) static int rouleur_init_reg(struct snd_soc_component *component) { + /* Disable HPH OCP */ + snd_soc_component_update_bits(component, ROULEUR_ANA_HPHPA_CNP_CTL_2, + 0x03, 0x00); /* Enable surge protection */ snd_soc_component_update_bits(component, ROULEUR_ANA_SURGE_EN, 0xC0, 0xC0); @@ -354,7 +357,7 @@ static int rouleur_rx_clk_enable(struct snd_soc_component *component) usleep_range(5000, 5100); rouleur_global_mbias_enable(component); snd_soc_component_update_bits(component, - ROULEUR_ANA_HPHPA_FSM_CLK, 0x11, 0x11); + ROULEUR_ANA_HPHPA_FSM_CLK, 0x7F, 0x11); snd_soc_component_update_bits(component, ROULEUR_ANA_HPHPA_FSM_CLK, 0x80, 0x80); snd_soc_component_update_bits(component, @@ -382,14 +385,14 @@ static int rouleur_rx_clk_disable(struct snd_soc_component *component) snd_soc_component_update_bits(component, ROULEUR_ANA_HPHPA_FSM_CLK, 0x80, 0x00); snd_soc_component_update_bits(component, - ROULEUR_ANA_HPHPA_FSM_CLK, 0x11, 0x00); + ROULEUR_ANA_HPHPA_FSM_CLK, 0x7F, 0x00); snd_soc_component_update_bits(component, ROULEUR_ANA_NCP_EN, 0x01, 0x00); - rouleur_global_mbias_disable(component); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x20, 0x00); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x10, 0x00); + rouleur_global_mbias_disable(component); } mutex_unlock(&rouleur->rx_clk_lock); @@ -478,8 +481,15 @@ static int rouleur_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, break; case SND_SOC_DAPM_POST_PMD: snd_soc_component_update_bits(component, - ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, - 0x01, 0x00); + ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, + 0x01, 0x00); + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, + 0x04, 0x00); + if (rouleur->comp1_enable) + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_CDC_COMP_CTL_0, + 0x02, 0x00); break; } @@ -544,6 +554,13 @@ static int rouleur_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMD: snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x02, 0x00); + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, + 0x08, 0x00); + if (rouleur->comp2_enable) + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_CDC_COMP_CTL_0, + 0x01, 0x00); break; } @@ -567,18 +584,21 @@ static int rouleur_codec_ear_lo_dac_event(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX0_CTL, 0x7C, 0x7C); - snd_soc_component_update_bits(component, - ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, - 0x01, 0x01); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, 0x04, 0x04); + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, + 0x01, 0x01); break; case SND_SOC_DAPM_POST_PMD: snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x01, 0x00); + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, + 0x04, 0x00); break; }; diff --git a/asoc/codecs/wcd-mbhc-adc.c b/asoc/codecs/wcd-mbhc-adc.c index 47c7ebf62f..89f0f7ed19 100644 --- a/asoc/codecs/wcd-mbhc-adc.c +++ b/asoc/codecs/wcd-mbhc-adc.c @@ -80,8 +80,22 @@ static int wcd_measure_adc_continuous(struct wcd_mbhc *mbhc) WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0); /* Set the MUX selection to IN2P */ WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MUX_CTL, MUX_CTL_IN2P); + + /* + * Current source mode requires Auto zeroing to be enabled + * automatically. If HW doesn't do it, SW has to take care of this + * for button interrupts to work fine and to avoid + * fake electrical removal interrupts by enabling autozero before FSM + * enable and disable it after FSM enable + */ + if (mbhc->mbhc_cb->mbhc_comp_autozero_control) + mbhc->mbhc_cb->mbhc_comp_autozero_control(mbhc, + true); /* Enable MBHC FSM */ WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 1); + if (mbhc->mbhc_cb->mbhc_comp_autozero_control) + mbhc->mbhc_cb->mbhc_comp_autozero_control(mbhc, + false); /* Enable ADC_ENABLE bit */ WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_EN, 1); @@ -294,6 +308,10 @@ static int wcd_check_cross_conn(struct wcd_mbhc *mbhc) WCD_MBHC_REG_READ(WCD_MBHC_ELECT_SCHMT_ISRC, elect_ctl); WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, 0x00); + /* Disable surge detection before ADC measurement */ + if (mbhc->mbhc_cb->mbhc_surge_ctl) + mbhc->mbhc_cb->mbhc_surge_ctl(mbhc, false); + /* Read and set ADC to single measurement */ WCD_MBHC_REG_READ(WCD_MBHC_ADC_MODE, adc_mode); /* Read ADC Enable bit to restore after adc measurement */ @@ -317,7 +335,12 @@ static int wcd_check_cross_conn(struct wcd_mbhc *mbhc) goto done; } - if (hphl_adc_res > 100 || hphr_adc_res > 100) { + /* Update cross connection threshold voltages if needed */ + if (mbhc->mbhc_cb->update_cross_conn_thr) + mbhc->mbhc_cb->update_cross_conn_thr(mbhc); + + if (hphl_adc_res > mbhc->hphl_cross_conn_thr || + hphr_adc_res > mbhc->hphr_cross_conn_thr) { plug_type = MBHC_PLUG_TYPE_GND_MIC_SWAP; pr_debug("%s: Cross connection identified\n", __func__); } else { @@ -339,6 +362,10 @@ done: /* Restore FSM state */ WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, fsm_en); + /* Restore surge detection */ + if (mbhc->mbhc_cb->mbhc_surge_ctl) + mbhc->mbhc_cb->mbhc_surge_ctl(mbhc, true); + /* Restore electrical detection */ WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, elect_ctl); diff --git a/asoc/codecs/wcd-mbhc-v2.c b/asoc/codecs/wcd-mbhc-v2.c index 5b07fcca23..17ce0ef790 100644 --- a/asoc/codecs/wcd-mbhc-v2.c +++ b/asoc/codecs/wcd-mbhc-v2.c @@ -80,17 +80,13 @@ static void wcd_program_hs_vref(struct wcd_mbhc *mbhc) struct snd_soc_component *component = mbhc->component; u32 reg_val; - if (mbhc->mbhc_cb->hs_vref_max_update) { - mbhc->mbhc_cb->hs_vref_max_update(mbhc); - } else { - plug_type_cfg = WCD_MBHC_CAL_PLUG_TYPE_PTR( - mbhc->mbhc_cfg->calibration); - reg_val = ((plug_type_cfg->v_hs_max - HS_VREF_MIN_VAL) / 100); + plug_type_cfg = WCD_MBHC_CAL_PLUG_TYPE_PTR( + mbhc->mbhc_cfg->calibration); + reg_val = ((plug_type_cfg->v_hs_max - HS_VREF_MIN_VAL) / 100); - dev_dbg(component->dev, "%s: reg_val = %x\n", - __func__, reg_val); - WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_VREF, reg_val); - } + dev_dbg(component->dev, "%s: reg_val = %x\n", + __func__, reg_val); + WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_VREF, reg_val); } static void wcd_program_btn_threshold(const struct wcd_mbhc *mbhc, bool micbias) @@ -999,14 +995,6 @@ static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc) mbhc->mbhc_cb->enable_mb_source(mbhc, true); mbhc->btn_press_intr = false; mbhc->is_btn_press = false; - /* - * When current source mode doesn't work properly - * use mic bias pull up mode for button interrupts - * to function properly - */ - if (mbhc->mbhc_cb->mbhc_micb_pullup_control) - mbhc->mbhc_cb->mbhc_micb_pullup_control(component, - true); if (mbhc->mbhc_fn) mbhc->mbhc_fn->wcd_mbhc_detect_plug_type(mbhc); } else if ((mbhc->current_plug != MBHC_PLUG_TYPE_NONE) @@ -1084,10 +1072,6 @@ static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc) false); } - if (mbhc->mbhc_cb->mbhc_micb_pullup_control) - mbhc->mbhc_cb->mbhc_micb_pullup_control(component, - false); - } else if (!detection_type) { /* Disable external voltage source to micbias if present */ if (mbhc->mbhc_cb->enable_mb_source) @@ -1856,6 +1840,8 @@ int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_component *component, mbhc->hph_type = WCD_MBHC_HPH_NONE; mbhc->wcd_mbhc_regs = wcd_mbhc_regs; mbhc->swap_thr = GND_MIC_SWAP_THRESHOLD; + mbhc->hphl_cross_conn_thr = HPHL_CROSS_CONN_THRESHOLD; + mbhc->hphr_cross_conn_thr = HPHR_CROSS_CONN_THRESHOLD; if (mbhc->intr_ids == NULL) { pr_err("%s: Interrupt mapping not provided\n", __func__); diff --git a/include/asoc/wcd-mbhc-v2.h b/include/asoc/wcd-mbhc-v2.h index 392e59418d..1c351f8012 100644 --- a/include/asoc/wcd-mbhc-v2.h +++ b/include/asoc/wcd-mbhc-v2.h @@ -145,6 +145,8 @@ do { \ #define FW_READ_ATTEMPTS 15 #define FW_READ_TIMEOUT 4000000 #define FAKE_REM_RETRY_ATTEMPTS 3 +#define HPHL_CROSS_CONN_THRESHOLD 100 +#define HPHR_CROSS_CONN_THRESHOLD 100 #define WCD_MBHC_BTN_PRESS_COMPL_TIMEOUT_MS 50 #define ANC_DETECT_RETRY_CNT 7 @@ -456,12 +458,14 @@ struct wcd_mbhc_register { }; struct wcd_mbhc_cb { - void (*mbhc_micb_pullup_control) - (struct snd_soc_component *component, bool enable); + void (*update_cross_conn_thr) + (struct wcd_mbhc *mbhc); + void (*mbhc_surge_ctl) + (struct wcd_mbhc *mbhc, bool surge_en); + void (*mbhc_comp_autozero_control) + (struct wcd_mbhc *mbhc, bool az_enable); void (*get_micbias_val) (struct wcd_mbhc *mbhc, int *mb); - void (*hs_vref_max_update) - (struct wcd_mbhc *mbhc); void (*bcs_enable) (struct wcd_mbhc *mbhc, bool bcs_enable); int (*enable_mb_source)(struct wcd_mbhc *mbhc, bool turn_on); @@ -557,6 +561,8 @@ struct wcd_mbhc { u32 moist_vref; u32 moist_iref; u32 moist_rref; + u32 hphl_cross_conn_thr; + u32 hphr_cross_conn_thr; u8 micbias1_cap_mode; /* track ext cap setting */ u8 micbias2_cap_mode; /* track ext cap setting */ bool hs_detect_work_stop; From 050e7403209b1add4fe51ce592f48f39b237c74f Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Sat, 28 Mar 2020 13:09:08 +0530 Subject: [PATCH 050/116] asoc: codecs: Enable impedance detection for rouleur codec Implement the impedance calculation logic for rouleur codec. Change-Id: I2b62e8c1109f949a12d2f31b4c1f6035a1bc2bba Signed-off-by: Aditya Bavanari --- asoc/codecs/rouleur/internal.h | 2 + asoc/codecs/rouleur/rouleur-mbhc.c | 363 ++++++++++-------------- asoc/codecs/rouleur/rouleur-registers.h | 2 +- asoc/codecs/rouleur/rouleur-regmap.c | 2 +- asoc/codecs/rouleur/rouleur-tables.c | 2 +- asoc/codecs/rouleur/rouleur.c | 4 +- 6 files changed, 157 insertions(+), 218 deletions(-) diff --git a/asoc/codecs/rouleur/internal.h b/asoc/codecs/rouleur/internal.h index df8541e340..233ca519be 100644 --- a/asoc/codecs/rouleur/internal.h +++ b/asoc/codecs/rouleur/internal.h @@ -170,4 +170,6 @@ extern int rouleur_mbhc_micb_adjust_voltage(struct snd_soc_component *component, extern int rouleur_get_micb_vout_ctl_val(u32 micb_mv); extern int rouleur_micbias_control(struct snd_soc_component *component, int micb_num, int req, bool is_dapm); +extern int rouleur_global_mbias_enable(struct snd_soc_component *component); +extern int rouleur_global_mbias_disable(struct snd_soc_component *component); #endif diff --git a/asoc/codecs/rouleur/rouleur-mbhc.c b/asoc/codecs/rouleur/rouleur-mbhc.c index 2f8e954b5a..b5a1ac52ff 100644 --- a/asoc/codecs/rouleur/rouleur-mbhc.c +++ b/asoc/codecs/rouleur/rouleur-mbhc.c @@ -22,20 +22,15 @@ #define ROULEUR_ZDET_SUPPORTED true /* Z value defined in milliohm */ -#define ROULEUR_ZDET_VAL_32 32000 -#define ROULEUR_ZDET_VAL_400 400000 -#define ROULEUR_ZDET_VAL_1200 1200000 #define ROULEUR_ZDET_VAL_100K 100000000 /* Z floating defined in ohms */ #define ROULEUR_ZDET_FLOATING_IMPEDANCE 0x0FFFFFFE -#define ROULEUR_ZDET_NUM_MEASUREMENTS 900 -#define ROULEUR_MBHC_GET_C1(c) ((c & 0xC000) >> 14) -#define ROULEUR_MBHC_GET_X1(x) (x & 0x3FFF) -/* Z value compared in milliOhm */ -#define ROULEUR_MBHC_IS_SECOND_RAMP_REQUIRED(z) ((z > 400000) || (z < 32000)) -#define ROULEUR_MBHC_ZDET_CONST (86 * 16384) -#define ROULEUR_MBHC_MOISTURE_RREF R_24_KOHM +#define ROULEUR_ZDET_NUM_MEASUREMENTS 100 +#define ROULEUR_ZDET_RMAX 1280000 +#define ROULEUR_ZDET_C1 7500000 +#define ROULEUR_ZDET_C2 187 +#define ROULEUR_ZDET_C3 4500 /* Cross connection thresholds in mV */ #define ROULEUR_HPHL_CROSS_CONN_THRESHOLD 200 @@ -157,9 +152,6 @@ struct rouleur_mbhc_zdet_param { u16 ldo_ctl; u16 noff; u16 nshift; - u16 btn5; - u16 btn6; - u16 btn7; }; static int rouleur_mbhc_request_irq(struct snd_soc_component *component, @@ -380,174 +372,180 @@ static int rouleur_mbhc_micb_ctrl_threshold_mic( return rc; } -static inline void rouleur_mbhc_get_result_params(struct rouleur_priv *rouleur, - s16 *d1_a, u16 noff, - int32_t *zdet) +static void rouleur_mbhc_get_result_params(struct rouleur_priv *rouleur, + struct snd_soc_component *component, + int32_t *zdet) { int i; - int val = 0, val1 = 0; - s16 c1 = 0; - s32 x1 = 0, d1 = 0; - int32_t denom; - int minCode_param[] = { - 3277, 1639, 820, 410, 205, 103, 52, 26 - }; + int zcode = 0, zcode1 = 0, zdet_cal_result = 0, zdet_est_range = 0; + int noff = 0, ndac = 14; + int zdet_cal_coeff = 0, div_ratio = 0; + int num = 0, denom = 0; + /* Charge enable and wait for zcode to be updated */ regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, 0x20, 0x20); for (i = 0; i < ROULEUR_ZDET_NUM_MEASUREMENTS; i++) { - regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_2, &val); - if (val & 0x80) + regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_2, &zcode); + if (zcode & 0x80) break; + usleep_range(200, 210); } - val = val << 0x8; - regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_1, &val1); - val |= val1; - regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, 0x20, 0x00); - x1 = ROULEUR_MBHC_GET_X1(val); - c1 = ROULEUR_MBHC_GET_C1(val); - /* If ramp is not complete, give additional 5ms */ - if ((c1 < 2) && x1) - usleep_range(5000, 5050); - if (!c1 || !x1) { + /* If zcode updation is not complete, give additional 10ms */ + if (!(zcode & 0x80)) + usleep_range(10000, 10100); + + regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_2, &zcode); + if (!(zcode & 0x80)) { dev_dbg(rouleur->dev, - "%s: Impedance detect ramp error, c1=%d, x1=0x%x\n", - __func__, c1, x1); - goto ramp_down; + "%s: Impedance detect calculation error, zcode=0x%x\n", + __func__, zcode); + regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, + 0x20, 0x00); + return; } - d1 = d1_a[c1]; - denom = (x1 * d1) - (1 << (14 - noff)); + zcode = zcode << 0x8; + zcode = zcode & 0x3FFF; + regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_1, &zcode1); + zcode |= zcode1; + + dev_dbg(rouleur->dev, + "%s: zcode: %d, zcode1: %d\n", __func__, zcode, zcode1); + + /* Calculate calibration coefficient */ + zdet_cal_result = (snd_soc_component_read32(component, + ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT)) & 0x1F; + zdet_cal_coeff = ROULEUR_ZDET_C1 / + ((ROULEUR_ZDET_C2 * zdet_cal_result) + ROULEUR_ZDET_C3); + /* Rload calculation */ + zdet_est_range = (snd_soc_component_read32(component, + ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT) & 0x60) >> 5; + + dev_dbg(rouleur->dev, + "%s: zdet_cal_result: %d, zdet_cal_coeff: %d, zdet_est_range: %d\n", + __func__, zdet_cal_result, zdet_cal_coeff, zdet_est_range); + switch (zdet_est_range) { + case 0: + default: + noff = 0; + div_ratio = 320; + break; + case 1: + noff = 0; + div_ratio = 64; + break; + case 2: + noff = 4; + div_ratio = 64; + break; + case 3: + noff = 5; + div_ratio = 40; + break; + } + + num = zdet_cal_coeff * ROULEUR_ZDET_RMAX; + denom = ((zcode * div_ratio * 100) - (1 << (ndac - noff)) * 1000); + dev_dbg(rouleur->dev, + "%s: num: %d, denom: %d\n", __func__, num, denom); if (denom > 0) - *zdet = (ROULEUR_MBHC_ZDET_CONST * 1000) / denom; - else if (x1 < minCode_param[noff]) + *zdet = (int32_t) ((num / denom) * 1000); + else *zdet = ROULEUR_ZDET_FLOATING_IMPEDANCE; - dev_dbg(rouleur->dev, "%s: d1=%d, c1=%d, x1=0x%x, z_val=%d(milliOhm)\n", - __func__, d1, c1, x1, *zdet); -ramp_down: - i = 0; - while (x1) { - regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_1, &val); - regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_2, &val1); - val = val << 0x8; - val |= val1; - x1 = ROULEUR_MBHC_GET_X1(val); - i++; - if (i == ROULEUR_ZDET_NUM_MEASUREMENTS) - break; - } + dev_dbg(rouleur->dev, "%s: z_val=%d(milliOhm)\n", + __func__, *zdet); + /* Start discharge */ + regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, 0x20, 0x00); } -#if 0 -static void rouleur_mbhc_zdet_ramp(struct snd_soc_component *component, - struct rouleur_mbhc_zdet_param *zdet_param, - int32_t *zl, int32_t *zr, s16 *d1_a) +static void rouleur_mbhc_zdet_start(struct snd_soc_component *component, + int32_t *zl, int32_t *zr) { struct rouleur_priv *rouleur = dev_get_drvdata(component->dev); int32_t zdet = 0; - snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_ZDET_ANA_CTL, - 0x70, zdet_param->ldo_ctl << 4); - snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_BTN5, 0xFC, - zdet_param->btn5); - snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_BTN6, 0xFC, - zdet_param->btn6); - snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_BTN7, 0xFC, - zdet_param->btn7); - snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_ZDET_ANA_CTL, - 0x0F, zdet_param->noff); - snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_ZDET_RAMP_CTL, - 0x0F, zdet_param->nshift); - if (!zl) goto z_right; - /* Start impedance measurement for HPH_L */ + + /* HPHL pull down switch to force OFF */ + regmap_update_bits(rouleur->regmap, + ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x30, 0x00); + /* Averaging enable for reliable results */ + regmap_update_bits(rouleur->regmap, + ROULEUR_ANA_MBHC_ZDET_ANA_CTL, 0x80, 0x80); + /* ZDET left measurement enable */ regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, 0x80, 0x80); - dev_dbg(rouleur->dev, "%s: ramp for HPH_L, noff = %d\n", - __func__, zdet_param->noff); - rouleur_mbhc_get_result_params(rouleur, d1_a, zdet_param->noff, &zdet); + /* Calculate the left Rload result */ + rouleur_mbhc_get_result_params(rouleur, component, &zdet); + regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, 0x80, 0x00); + regmap_update_bits(rouleur->regmap, + ROULEUR_ANA_MBHC_ZDET_ANA_CTL, 0x80, 0x00); + regmap_update_bits(rouleur->regmap, + ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x30, 0x20); *zl = zdet; z_right: if (!zr) return; - /* Start impedance measurement for HPH_R */ + /* HPHR pull down switch to force OFF */ + regmap_update_bits(rouleur->regmap, + ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x0C, 0x00); + /* Averaging enable for reliable results */ + regmap_update_bits(rouleur->regmap, + ROULEUR_ANA_MBHC_ZDET_ANA_CTL, 0x80, 0x80); + /* ZDET right measurement enable */ regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, 0x40, 0x40); - dev_dbg(rouleur->dev, "%s: ramp for HPH_R, noff = %d\n", - __func__, zdet_param->noff); - rouleur_mbhc_get_result_params(rouleur, d1_a, zdet_param->noff, &zdet); + + /* Calculate the right Rload result */ + rouleur_mbhc_get_result_params(rouleur, component, &zdet); + regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, 0x40, 0x00); + regmap_update_bits(rouleur->regmap, + ROULEUR_ANA_MBHC_ZDET_ANA_CTL, 0x80, 0x00); + regmap_update_bits(rouleur->regmap, + ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x0C, 0x08); *zr = zdet; } -static inline void rouleur_wcd_mbhc_qfuse_cal( - struct snd_soc_component *component, - int32_t *z_val, int flag_l_r) -{ - s16 q1; - int q1_cal; - - if (*z_val < (ROULEUR_ZDET_VAL_400/1000)) - q1 = snd_soc_component_read32(component, - ROULEUR_DIGITAL_EFUSE_REG_23 + (2 * flag_l_r)); - else - q1 = snd_soc_component_read32(component, - ROULEUR_DIGITAL_EFUSE_REG_24 + (2 * flag_l_r)); - if (q1 & 0x80) - q1_cal = (10000 - ((q1 & 0x7F) * 25)); - else - q1_cal = (10000 + (q1 * 25)); - if (q1_cal > 0) - *z_val = ((*z_val) * 10000) / q1_cal; -} - static void rouleur_wcd_mbhc_calc_impedance(struct wcd_mbhc *mbhc, uint32_t *zl, uint32_t *zr) { struct snd_soc_component *component = mbhc->component; struct rouleur_priv *rouleur = dev_get_drvdata(component->dev); - s16 reg0, reg1, reg2, reg3, reg4; + s16 reg0; int32_t z1L, z1R, z1Ls; int zMono, z_diff1, z_diff2; bool is_fsm_disable = false; - struct rouleur_mbhc_zdet_param zdet_param[] = { - {4, 0, 4, 0x08, 0x14, 0x18}, /* < 32ohm */ - {2, 0, 3, 0x18, 0x7C, 0x90}, /* 32ohm < Z < 400ohm */ - {1, 4, 5, 0x18, 0x7C, 0x90}, /* 400ohm < Z < 1200ohm */ - {1, 6, 7, 0x18, 0x7C, 0x90}, /* >1200ohm */ - }; - struct rouleur_mbhc_zdet_param *zdet_param_ptr = NULL; - s16 d1_a[][4] = { - {0, 30, 90, 30}, - {0, 30, 30, 5}, - {0, 30, 30, 5}, - {0, 30, 30, 5}, - }; - s16 *d1 = NULL; WCD_MBHC_RSC_ASSERT_LOCKED(mbhc); - reg0 = snd_soc_component_read32(component, ROULEUR_ANA_MBHC_BTN5); - reg1 = snd_soc_component_read32(component, ROULEUR_ANA_MBHC_BTN6); - reg2 = snd_soc_component_read32(component, ROULEUR_ANA_MBHC_BTN7); - reg3 = snd_soc_component_read32(component, ROULEUR_MBHC_CTL_CLK); - reg4 = snd_soc_component_read32(component, - ROULEUR_ANA_MBHC_ZDET_ANA_CTL); + reg0 = snd_soc_component_read32(component, ROULEUR_ANA_MBHC_ELECT); - if (snd_soc_component_read32(component, ROULEUR_ANA_MBHC_ELECT) & - 0x80) { + if (reg0 & 0x80) { is_fsm_disable = true; regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ELECT, 0x80, 0x00); } + /* Enable electrical bias */ + snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_ELECT, + 0x01, 0x01); + + /* Enable codec main bias */ + rouleur_global_mbias_enable(component); + + /* Enable RCO clock */ + snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_CTL_1, + 0x80, 0x80); + /* For NO-jack, disable L_DET_EN before Z-det measurements */ if (mbhc->hphl_swh) regmap_update_bits(rouleur->regmap, @@ -557,79 +555,34 @@ static void rouleur_wcd_mbhc_calc_impedance(struct wcd_mbhc *mbhc, uint32_t *zl, regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_MECH, 0x01, 0x00); - /* Disable surge protection before impedance detection. + /* + * Disable surge protection before impedance detection. * This is done to give correct value for high impedance. */ - regmap_update_bits(rouleur->regmap, - ROULEUR_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0x00); + snd_soc_component_update_bits(component, ROULEUR_ANA_SURGE_EN, + 0xC0, 0x00); /* 1ms delay needed after disable surge protection */ usleep_range(1000, 1010); - /* First get impedance on Left */ - d1 = d1_a[1]; - zdet_param_ptr = &zdet_param[1]; - rouleur_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1); - - if (!ROULEUR_MBHC_IS_SECOND_RAMP_REQUIRED(z1L)) - goto left_ch_impedance; - - /* Second ramp for left ch */ - if (z1L < ROULEUR_ZDET_VAL_32) { - zdet_param_ptr = &zdet_param[0]; - d1 = d1_a[0]; - } else if ((z1L > ROULEUR_ZDET_VAL_400) && - (z1L <= ROULEUR_ZDET_VAL_1200)) { - zdet_param_ptr = &zdet_param[2]; - d1 = d1_a[2]; - } else if (z1L > ROULEUR_ZDET_VAL_1200) { - zdet_param_ptr = &zdet_param[3]; - d1 = d1_a[3]; - } - rouleur_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1); - -left_ch_impedance: + /* Start of left ch impedance calculation */ + rouleur_mbhc_zdet_start(component, &z1L, NULL); if ((z1L == ROULEUR_ZDET_FLOATING_IMPEDANCE) || - (z1L > ROULEUR_ZDET_VAL_100K)) { + (z1L > ROULEUR_ZDET_VAL_100K)) *zl = ROULEUR_ZDET_FLOATING_IMPEDANCE; - zdet_param_ptr = &zdet_param[1]; - d1 = d1_a[1]; - } else { + else *zl = z1L/1000; - rouleur_wcd_mbhc_qfuse_cal(component, zl, 0); - } + dev_dbg(component->dev, "%s: impedance on HPH_L = %d(ohms)\n", __func__, *zl); - /* Start of right impedance ramp and calculation */ - rouleur_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, &z1R, d1); - if (ROULEUR_MBHC_IS_SECOND_RAMP_REQUIRED(z1R)) { - if (((z1R > ROULEUR_ZDET_VAL_1200) && - (zdet_param_ptr->noff == 0x6)) || - ((*zl) != ROULEUR_ZDET_FLOATING_IMPEDANCE)) - goto right_ch_impedance; - /* Second ramp for right ch */ - if (z1R < ROULEUR_ZDET_VAL_32) { - zdet_param_ptr = &zdet_param[0]; - d1 = d1_a[0]; - } else if ((z1R > ROULEUR_ZDET_VAL_400) && - (z1R <= ROULEUR_ZDET_VAL_1200)) { - zdet_param_ptr = &zdet_param[2]; - d1 = d1_a[2]; - } else if (z1R > ROULEUR_ZDET_VAL_1200) { - zdet_param_ptr = &zdet_param[3]; - d1 = d1_a[3]; - } - rouleur_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, - &z1R, d1); - } -right_ch_impedance: + /* Start of right ch impedance calculation */ + rouleur_mbhc_zdet_start(component, NULL, &z1R); if ((z1R == ROULEUR_ZDET_FLOATING_IMPEDANCE) || - (z1R > ROULEUR_ZDET_VAL_100K)) { + (z1R > ROULEUR_ZDET_VAL_100K)) *zr = ROULEUR_ZDET_FLOATING_IMPEDANCE; - } else { + else *zr = z1R/1000; - rouleur_wcd_mbhc_qfuse_cal(component, zr, 1); - } + dev_dbg(component->dev, "%s: impedance on HPH_R = %d(ohms)\n", __func__, *zr); @@ -651,24 +604,10 @@ right_ch_impedance: mbhc->hph_type = WCD_MBHC_HPH_MONO; goto zdet_complete; } - snd_soc_component_update_bits(component, ROULEUR_HPH_R_ATEST, - 0x02, 0x02); - snd_soc_component_update_bits(component, ROULEUR_HPH_PA_CTL2, - 0x40, 0x01); - if (*zl < (ROULEUR_ZDET_VAL_32/1000)) - rouleur_mbhc_zdet_ramp(component, &zdet_param[0], &z1Ls, - NULL, d1); - else - rouleur_mbhc_zdet_ramp(component, &zdet_param[1], &z1Ls, - NULL, d1); - snd_soc_component_update_bits(component, ROULEUR_HPH_PA_CTL2, - 0x40, 0x00); - snd_soc_component_update_bits(component, ROULEUR_HPH_R_ATEST, - 0x02, 0x00); - z1Ls /= 1000; - rouleur_wcd_mbhc_qfuse_cal(component, &z1Ls, 0); - /* Parallel of left Z and 9 ohm pull down resistor */ - zMono = ((*zl) * 9) / ((*zl) + 9); + + z1Ls = z1L/1000; + /* Parallel of left Z and 20 ohm pull down resistor */ + zMono = ((*zl) * 20) / ((*zl) + 20); z_diff1 = (z1Ls > zMono) ? (z1Ls - zMono) : (zMono - z1Ls); z_diff2 = ((*zl) > z1Ls) ? ((*zl) - z1Ls) : (z1Ls - (*zl)); if ((z_diff1 * (*zl + z1Ls)) > (z_diff2 * (z1Ls + zMono))) { @@ -681,13 +620,10 @@ right_ch_impedance: mbhc->hph_type = WCD_MBHC_HPH_MONO; } +zdet_complete: /* Enable surge protection again after impedance detection */ regmap_update_bits(rouleur->regmap, - ROULEUR_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0xC0); -zdet_complete: - snd_soc_component_write(component, ROULEUR_ANA_MBHC_BTN5, reg0); - snd_soc_component_write(component, ROULEUR_ANA_MBHC_BTN6, reg1); - snd_soc_component_write(component, ROULEUR_ANA_MBHC_BTN7, reg2); + ROULEUR_ANA_SURGE_EN, 0xC0, 0xC0); /* Turn on 100k pull down on HPHL */ regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_MECH, 0x01, 0x01); @@ -697,13 +633,14 @@ zdet_complete: regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_MECH, 0x80, 0x80); - snd_soc_component_write(component, ROULEUR_ANA_MBHC_ZDET_ANA_CTL, reg4); - snd_soc_component_write(component, ROULEUR_MBHC_CTL_CLK, reg3); + /* Restore electrical bias state */ + snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_ELECT, 0x01, + reg0 >> 7); if (is_fsm_disable) regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ELECT, 0x80, 0x80); + rouleur_global_mbias_disable(component); } -#endif static void rouleur_mbhc_gnd_det_ctrl(struct snd_soc_component *component, bool enable) @@ -843,10 +780,10 @@ static void rouleur_mbhc_comp_autozero_control(struct wcd_mbhc *mbhc, { if (az_enable) snd_soc_component_update_bits(mbhc->component, - ROULEUR_ANA_MBHC_MCLK, 0x08, 0x08); + ROULEUR_ANA_MBHC_CTL_CLK, 0x08, 0x08); else snd_soc_component_update_bits(mbhc->component, - ROULEUR_ANA_MBHC_MCLK, 0x08, 0x00); + ROULEUR_ANA_MBHC_CTL_CLK, 0x08, 0x00); } @@ -889,7 +826,7 @@ static const struct wcd_mbhc_cb mbhc_cb = { .mbhc_micb_ramp_control = rouleur_mbhc_micb_ramp_control, .get_hwdep_fw_cal = rouleur_get_hwdep_fw_cal, .mbhc_micb_ctrl_thr_mic = rouleur_mbhc_micb_ctrl_threshold_mic, - //.compute_impedance = rouleur_wcd_mbhc_calc_impedance, + .compute_impedance = rouleur_wcd_mbhc_calc_impedance, .mbhc_gnd_det_ctrl = rouleur_mbhc_gnd_det_ctrl, .hph_pull_down_ctrl = rouleur_mbhc_hph_pull_down_ctrl, .mbhc_moisture_config = rouleur_mbhc_moisture_config, diff --git a/asoc/codecs/rouleur/rouleur-registers.h b/asoc/codecs/rouleur/rouleur-registers.h index 816e49237d..8cc0ae473a 100644 --- a/asoc/codecs/rouleur/rouleur-registers.h +++ b/asoc/codecs/rouleur/rouleur-registers.h @@ -45,7 +45,7 @@ enum { #define ROULEUR_ANA_MBHC_ZDET_RAMP_CTL (ROULEUR_ANA_BASE_ADDR+0x06A) #define ROULEUR_ANA_MBHC_FSM_STATUS (ROULEUR_ANA_BASE_ADDR+0x06B) #define ROULEUR_ANA_MBHC_ADC_RESULT (ROULEUR_ANA_BASE_ADDR+0x06C) -#define ROULEUR_ANA_MBHC_MCLK (ROULEUR_ANA_BASE_ADDR+0x06D) +#define ROULEUR_ANA_MBHC_CTL_CLK (ROULEUR_ANA_BASE_ADDR+0x06D) #define ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT (ROULEUR_ANA_BASE_ADDR+0x072) #define ROULEUR_ANA_NCP_EN (ROULEUR_ANA_BASE_ADDR+0x077) #define ROULEUR_ANA_HPHPA_CNP_CTL_1 (ROULEUR_ANA_BASE_ADDR+0x083) diff --git a/asoc/codecs/rouleur/rouleur-regmap.c b/asoc/codecs/rouleur/rouleur-regmap.c index 08b490db3a..23b8ddc967 100644 --- a/asoc/codecs/rouleur/rouleur-regmap.c +++ b/asoc/codecs/rouleur/rouleur-regmap.c @@ -38,7 +38,7 @@ static const struct reg_default rouleur_defaults[] = { { ROULEUR_ANA_MBHC_ZDET_RAMP_CTL, 0x00 }, { ROULEUR_ANA_MBHC_FSM_STATUS, 0x00 }, { ROULEUR_ANA_MBHC_ADC_RESULT, 0x00 }, - { ROULEUR_ANA_MBHC_MCLK, 0x30 }, + { ROULEUR_ANA_MBHC_CTL_CLK, 0x30 }, { ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT, 0x00 }, { ROULEUR_ANA_NCP_EN, 0x00 }, { ROULEUR_ANA_HPHPA_CNP_CTL_1, 0x54 }, diff --git a/asoc/codecs/rouleur/rouleur-tables.c b/asoc/codecs/rouleur/rouleur-tables.c index 59b7cf2d33..7912267dac 100644 --- a/asoc/codecs/rouleur/rouleur-tables.c +++ b/asoc/codecs/rouleur/rouleur-tables.c @@ -33,7 +33,7 @@ const u8 rouleur_reg_access_analog[ROULEUR_REG( [ROULEUR_REG(ROULEUR_ANA_MBHC_ZDET_RAMP_CTL)] = RD_WR_REG, [ROULEUR_REG(ROULEUR_ANA_MBHC_FSM_STATUS)] = RD_REG, [ROULEUR_REG(ROULEUR_ANA_MBHC_ADC_RESULT)] = RD_REG, - [ROULEUR_REG(ROULEUR_ANA_MBHC_MCLK)] = RD_WR_REG, + [ROULEUR_REG(ROULEUR_ANA_MBHC_CTL_CLK)] = RD_WR_REG, [ROULEUR_REG(ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT)] = RD_REG, [ROULEUR_REG(ROULEUR_ANA_NCP_EN)] = RD_WR_REG, [ROULEUR_REG(ROULEUR_ANA_HPHPA_CNP_CTL_1)] = RD_WR_REG, diff --git a/asoc/codecs/rouleur/rouleur.c b/asoc/codecs/rouleur/rouleur.c index e1ecdba83f..418ed6711d 100644 --- a/asoc/codecs/rouleur/rouleur.c +++ b/asoc/codecs/rouleur/rouleur.c @@ -304,7 +304,7 @@ static int rouleur_rx_connect_port(struct snd_soc_component *component, return ret; } -static int rouleur_global_mbias_enable(struct snd_soc_component *component) +int rouleur_global_mbias_enable(struct snd_soc_component *component) { struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component); @@ -322,7 +322,7 @@ static int rouleur_global_mbias_enable(struct snd_soc_component *component) return 0; } -static int rouleur_global_mbias_disable(struct snd_soc_component *component) +int rouleur_global_mbias_disable(struct snd_soc_component *component) { struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component); From cbe9426358674e2bb2680b0de43b6b97b22deb7b Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Wed, 6 May 2020 14:09:09 +0530 Subject: [PATCH 051/116] asoc: codecs: Fix volume fluctuation issue in headphone playback HPH PA pull down control is set to force ON instead of auto due of which saturation/noise is observed in headset playback at highest volumes. Set pull down control to Auto to fix this issue. Change-Id: I465588f46b04bbb32d84f76b8b5bedd2ef21bd2a Signed-off-by: Aditya Bavanari --- asoc/codecs/rouleur/rouleur-mbhc.c | 4 ++-- asoc/codecs/rouleur/rouleur.c | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/asoc/codecs/rouleur/rouleur-mbhc.c b/asoc/codecs/rouleur/rouleur-mbhc.c index b5a1ac52ff..f0eea091cb 100644 --- a/asoc/codecs/rouleur/rouleur-mbhc.c +++ b/asoc/codecs/rouleur/rouleur-mbhc.c @@ -664,10 +664,10 @@ static void rouleur_mbhc_hph_pull_down_ctrl(struct snd_soc_component *component, if (enable) { snd_soc_component_update_bits(component, ROULEUR_ANA_HPHPA_CNP_CTL_2, - 0x30, 0x10); + 0x30, 0x20); snd_soc_component_update_bits(component, ROULEUR_ANA_HPHPA_CNP_CTL_2, - 0x0C, 0x04); + 0x0C, 0x08); } else { snd_soc_component_update_bits(component, ROULEUR_ANA_HPHPA_CNP_CTL_2, diff --git a/asoc/codecs/rouleur/rouleur.c b/asoc/codecs/rouleur/rouleur.c index 418ed6711d..480e0ce7a5 100644 --- a/asoc/codecs/rouleur/rouleur.c +++ b/asoc/codecs/rouleur/rouleur.c @@ -472,7 +472,7 @@ static int rouleur_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, } snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX0_CTL, - 0x7C, 0x7C); + 0x80, 0x00); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, 0x04, 0x04); @@ -486,6 +486,9 @@ static int rouleur_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, 0x04, 0x00); + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_CDC_RX0_CTL, + 0x80, 0x80); if (rouleur->comp1_enable) snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_COMP_CTL_0, @@ -544,7 +547,7 @@ static int rouleur_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, } snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX1_CTL, - 0x7C, 0x7C); + 0x80, 0x00); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, 0x08, 0x08); @@ -557,6 +560,9 @@ static int rouleur_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, 0x08, 0x00); + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_CDC_RX1_CTL, + 0x80, 0x80); if (rouleur->comp2_enable) snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_COMP_CTL_0, @@ -583,7 +589,7 @@ static int rouleur_codec_ear_lo_dac_event(struct snd_soc_dapm_widget *w, rouleur_rx_clk_enable(component); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX0_CTL, - 0x7C, 0x7C); + 0x80, 0x00); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, 0x04, 0x04); @@ -599,6 +605,9 @@ static int rouleur_codec_ear_lo_dac_event(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, 0x04, 0x00); + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_CDC_RX0_CTL, + 0x80, 0x80); break; }; From 7dfadb9409b0046e6f9ac1fc5930146b41d6562d Mon Sep 17 00:00:00 2001 From: Meng Wang Date: Mon, 13 Apr 2020 10:41:16 +0800 Subject: [PATCH 052/116] asoc: routing: move volume and app type cfg controls from asoc to driver Move volume and app type cfg controls from asoc to audio drivers. Change-Id: I5c5d84a9a0536c7d8d95a8ca20cc176b31ca5b63 Signed-off-by: Meng Wang --- asoc/msm-pcm-routing-v2.c | 184 ++++++++++++++++++++++++++++++++++++++ asoc/msm-pcm-routing-v2.h | 51 +++++++++++ 2 files changed, 235 insertions(+) diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c index e8dbaf402c..2d6a4d5a55 100644 --- a/asoc/msm-pcm-routing-v2.c +++ b/asoc/msm-pcm-routing-v2.c @@ -49,6 +49,9 @@ #define DS2_ADM_COPP_TOPOLOGY_ID 0xFFFFFFFF #endif +#define STRING_LENGTH_OF_INT 12 +#define MAX_USR_CTRL_CNT 128 + static struct mutex routing_lock; static struct cal_type_data *cal_data[MAX_ROUTING_CAL_TYPES]; @@ -167,6 +170,187 @@ static int msm_routing_send_device_pp_params(int port_id, int copp_idx, static void msm_routing_load_topology(size_t data_size, void *data); static void msm_routing_unload_topology(uint32_t topology_id); +#ifndef SND_PCM_ADD_VOLUME_CTL +static int pcm_volume_ctl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 0x2000; + return 0; +} + +static void pcm_volume_ctl_private_free(struct snd_kcontrol *kcontrol) +{ + struct snd_pcm_volume *info = snd_kcontrol_chip(kcontrol); + + kfree(info); +} + +/** + * snd_pcm_add_volume_ctls - create volume control elements + * @pcm: the assigned PCM instance + * @stream: stream direction + * @max_length: the max length of the volume parameter of stream + * @private_value: the value passed to each kcontrol's private_value field + * @info_ret: store struct snd_pcm_volume instance if non-NULL + * + * Create volume control elements assigned to the given PCM stream(s). + * Returns zero if succeed, or a negative error value. + */ +int snd_pcm_add_volume_ctls(struct snd_pcm *pcm, int stream, + const struct snd_pcm_volume_elem *volume, + int max_length, + unsigned long private_value, + struct snd_pcm_volume **info_ret) +{ + int err = 0; + int size = 0; + struct snd_pcm_volume *info; + struct snd_kcontrol_new knew = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | + SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = pcm_volume_ctl_info, + }; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + info->pcm = pcm; + info->stream = stream; + info->volume = volume; + info->max_length = max_length; + size = sizeof("Playback ") + sizeof(" Volume") + + STRING_LENGTH_OF_INT*sizeof(char) + 1; + knew.name = kzalloc(size, GFP_KERNEL); + if (!knew.name) { + kfree(info); + return -ENOMEM; + } + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + snprintf((char *)knew.name, size, "%s %d %s", + "Playback", pcm->device, "Volume"); + else + snprintf((char *)knew.name, size, "%s %d %s", + "Capture", pcm->device, "Volume"); + knew.device = pcm->device; + knew.count = pcm->streams[stream].substream_count; + knew.private_value = private_value; + info->kctl = snd_ctl_new1(&knew, info); + if (!info->kctl) { + kfree(info); + kfree(knew.name); + return -ENOMEM; + } + info->kctl->private_free = pcm_volume_ctl_private_free; + err = snd_ctl_add(pcm->card, info->kctl); + if (err < 0) { + kfree(info); + kfree(knew.name); + return -ENOMEM; + } + if (info_ret) + *info_ret = info; + kfree(knew.name); + return 0; +} +EXPORT_SYMBOL(snd_pcm_add_volume_ctls); +#endif + +#ifndef SND_PCM_ADD_USR_CTL +static int pcm_usr_ctl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = MAX_USR_CTRL_CNT; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = INT_MAX; + return 0; +} + +static void pcm_usr_ctl_private_free(struct snd_kcontrol *kcontrol) +{ + struct snd_pcm_usr *info = snd_kcontrol_chip(kcontrol); + + kfree(info); +} + +/** + * snd_pcm_add_usr_ctls - create user control elements + * @pcm: the assigned PCM instance + * @stream: stream direction + * @max_length: the max length of the user parameter of stream + * @private_value: the value passed to each kcontrol's private_value field + * @info_ret: store struct snd_pcm_usr instance if non-NULL + * + * Create usr control elements assigned to the given PCM stream(s). + * Returns zero if succeed, or a negative error value. + */ +int snd_pcm_add_usr_ctls(struct snd_pcm *pcm, int stream, + const struct snd_pcm_usr_elem *usr, + int max_length, int max_kctrl_str_len, + unsigned long private_value, + struct snd_pcm_usr **info_ret) +{ + int err = 0; + char *buf = NULL; + struct snd_pcm_usr *info; + struct snd_kcontrol_new knew = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = pcm_usr_ctl_info, + }; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->pcm = pcm; + info->stream = stream; + info->usr = usr; + info->max_length = max_length; + buf = kzalloc(max_kctrl_str_len, GFP_KERNEL); + if (!buf) { + pr_err("%s: buffer allocation failed\n", __func__); + kfree(info); + return -ENOMEM; + } + knew.name = buf; + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + snprintf(buf, max_kctrl_str_len, "%s %d %s", + "Playback", pcm->device, "User kcontrol"); + else + snprintf(buf, max_kctrl_str_len, "%s %d %s", + "Capture", pcm->device, "User kcontrol"); + knew.device = pcm->device; + knew.count = pcm->streams[stream].substream_count; + knew.private_value = private_value; + info->kctl = snd_ctl_new1(&knew, info); + if (!info->kctl) { + kfree(info); + kfree(knew.name); + pr_err("%s: snd_ctl_new failed\n", __func__); + return -ENOMEM; + } + info->kctl->private_free = pcm_usr_ctl_private_free; + err = snd_ctl_add(pcm->card, info->kctl); + if (err < 0) { + kfree(info); + kfree(knew.name); + pr_err("%s: snd_ctl_add failed:%d\n", __func__, + err); + return -ENOMEM; + } + if (info_ret) + *info_ret = info; + kfree(knew.name); + return 0; +} +EXPORT_SYMBOL(snd_pcm_add_usr_ctls); +#endif + static int msm_routing_get_bit_width(unsigned int format) { int bit_width; diff --git a/asoc/msm-pcm-routing-v2.h b/asoc/msm-pcm-routing-v2.h index 337875909a..fafe0eba26 100644 --- a/asoc/msm-pcm-routing-v2.h +++ b/asoc/msm-pcm-routing-v2.h @@ -653,4 +653,55 @@ int msm_pcm_routing_set_channel_mixer_runtime( int be_id, int session_id, int session_type, struct msm_pcm_channel_mixer *params); + +#ifndef SND_PCM_ADD_VOLUME_CTL +/* PCM Volume control API + */ +/* array element of volume */ +struct snd_pcm_volume_elem { + int volume; +}; + /* pp information; retrieved via snd_kcontrol_chip() */ +struct snd_pcm_volume { + struct snd_pcm *pcm; /* assigned PCM instance */ + int stream; /* PLAYBACK or CAPTURE */ + struct snd_kcontrol *kctl; + const struct snd_pcm_volume_elem *volume; + int max_length; + void *private_data; /* optional: private data pointer */ +}; + +int snd_pcm_add_volume_ctls(struct snd_pcm *pcm, int stream, + const struct snd_pcm_volume_elem *volume, + int max_length, + unsigned long private_value, + struct snd_pcm_volume **info_ret); + +#endif + +#ifndef SND_PCM_ADD_USR_CTL +/* + * PCM User control API 1450 + */ +/* array element of usr elem */ +struct snd_pcm_usr_elem { + int val[128]; +}; + +/* pp information; retrieved via snd_kcontrol_chip() */ +struct snd_pcm_usr { + struct snd_pcm *pcm; /* assigned PCM instance */ + int stream; /* PLAYBACK or CAPTURE */ + struct snd_kcontrol *kctl; + const struct snd_pcm_usr_elem *usr; + int max_length; + void *private_data; /* optional: private data pointer */ +}; + +int snd_pcm_add_usr_ctls(struct snd_pcm *pcm, int stream, + const struct snd_pcm_usr_elem *usr, + int max_length, int max_control_str_len, + unsigned long private_value, + struct snd_pcm_usr **info_ret); +#endif #endif /*_MSM_PCM_H*/ From f1035cd51c4a46dc041f0440e3ca092488596e31 Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Tue, 19 May 2020 10:41:35 +0530 Subject: [PATCH 053/116] asoc: codecs: Add delay to eliminate playback pause post SSR on hs Add delay in post ssr to eliminate playback pause on euro usbc headset. Post ssr, headset is detected as headphone as HPH PA gets turned ON before the completion of wcd_correct_swch_plug workqueue in MBHC. Change-Id: Ib0334b37aa12b7e7371146b26eb3a1f4484656a3 Signed-off-by: Aditya Bavanari --- asoc/codecs/rouleur/internal.h | 1 + asoc/codecs/rouleur/rouleur.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/asoc/codecs/rouleur/internal.h b/asoc/codecs/rouleur/internal.h index 233ca519be..c6e7d112ee 100644 --- a/asoc/codecs/rouleur/internal.h +++ b/asoc/codecs/rouleur/internal.h @@ -83,6 +83,7 @@ struct rouleur_priv { struct mutex rx_clk_lock; struct mutex main_bias_lock; bool dev_up; + bool usbc_hs_status; }; struct rouleur_micbias_setting { diff --git a/asoc/codecs/rouleur/rouleur.c b/asoc/codecs/rouleur/rouleur.c index 480e0ce7a5..7d4e68c57f 100644 --- a/asoc/codecs/rouleur/rouleur.c +++ b/asoc/codecs/rouleur/rouleur.c @@ -1341,6 +1341,17 @@ static int rouleur_get_logical_addr(struct swr_device *swr_dev) return 0; } +static bool get_usbc_hs_status(struct snd_soc_component *component, + struct wcd_mbhc_config *mbhc_cfg) +{ + if (mbhc_cfg->enable_usbc_analog) { + if (!(snd_soc_component_read32(component, ROULEUR_ANA_MBHC_MECH) + & 0x20)) + return true; + } + return false; +} + static int rouleur_event_notify(struct notifier_block *block, unsigned long val, void *data) @@ -1373,6 +1384,8 @@ static int rouleur_event_notify(struct notifier_block *block, rouleur->dev_up = false; rouleur->mbhc->wcd_mbhc.deinit_in_progress = true; mbhc = &rouleur->mbhc->wcd_mbhc; + rouleur->usbc_hs_status = get_usbc_hs_status(component, + mbhc->mbhc_cfg); rouleur_mbhc_ssr_down(rouleur->mbhc, component); rouleur_reset(rouleur->dev, 0x01); break; @@ -1394,6 +1407,8 @@ static int rouleur_event_notify(struct notifier_block *block, __func__); } else { rouleur_mbhc_hs_detect(component, mbhc->mbhc_cfg); + if (rouleur->usbc_hs_status) + mdelay(500); } rouleur->mbhc->wcd_mbhc.deinit_in_progress = false; rouleur->dev_up = true; From b0e4323d6a5ff921df8bdb9540183e066ddf3ac5 Mon Sep 17 00:00:00 2001 From: Sudheer Papothi Date: Fri, 5 Jun 2020 06:06:51 +0530 Subject: [PATCH 054/116] ASoC: bolero: Disable wsa swr gpio as wakeup capable Disable wsa swr gpio as wakeup capable to avoid waking up system during power collapse. Change-Id: I54d769d63c9e7c13d2920f038c64353a92556cfe Signed-off-by: Sudheer Papothi --- asoc/codecs/bolero/wsa-macro.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c index c145ad9051..e2b0666a1c 100644 --- a/asoc/codecs/bolero/wsa-macro.c +++ b/asoc/codecs/bolero/wsa-macro.c @@ -3177,6 +3177,8 @@ static int wsa_macro_probe(struct platform_device *pdev) __func__); return -EPROBE_DEFER; } + msm_cdc_pinctrl_set_wakeup_capable( + wsa_priv->wsa_swr_gpio_p, false); wsa_io_base = devm_ioremap(&pdev->dev, wsa_base_addr, WSA_MACRO_MAX_OFFSET); From 3764c5231a04ae4cc74896a5c9c6ea2aab2dc904 Mon Sep 17 00:00:00 2001 From: Sudheer Papothi Date: Fri, 5 Jun 2020 10:02:20 +0530 Subject: [PATCH 055/116] ASoC: wsa883x: Update interrupt handling on WSA883x driver Update interrupt handling on WSA883x driver to avoid fake interrupts during power collapse. Change-Id: I3128e2c2d9bf84f90f472a03d2b23ca1d3b70838 Signed-off-by: Sudheer Papothi --- asoc/codecs/wsa883x/wsa883x.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/asoc/codecs/wsa883x/wsa883x.c b/asoc/codecs/wsa883x/wsa883x.c index de83f2c535..93b33893c4 100644 --- a/asoc/codecs/wsa883x/wsa883x.c +++ b/asoc/codecs/wsa883x/wsa883x.c @@ -123,6 +123,7 @@ static const struct wsa_reg_mask_val reg_init[] = { {WSA883X_GMAMP_SUP1, 0x60, 0x60}, }; +static int wsa883x_handle_post_irq(void *data); static int wsa883x_get_temperature(struct snd_soc_component *component, int *temp); enum { @@ -172,9 +173,24 @@ static struct regmap_irq_chip wsa883x_regmap_irq_chip = { .ack_base = WSA883X_INTR_CLEAR0, .use_ack = 1, .runtime_pm = false, + .handle_post_irq = wsa883x_handle_post_irq, .irq_drv_data = NULL, }; +static int wsa883x_handle_post_irq(void *data) +{ + struct wsa883x_priv *wsa883x = data; + u32 sts1 = 0, sts2 = 0; + + regmap_read(wsa883x->regmap, WSA883X_INTR_STATUS0, &sts1); + regmap_read(wsa883x->regmap, WSA883X_INTR_STATUS1, &sts2); + + wsa883x->swr_slave->slave_irq_pending = + ((sts1 || sts2) ? true : false); + + return IRQ_HANDLED; +} + #ifdef CONFIG_DEBUG_FS static int codec_debug_open(struct inode *inode, struct file *file) { @@ -989,6 +1005,7 @@ static int wsa883x_spkr_event(struct snd_soc_dapm_widget *w, wsa883x->swr_slave->dev_num, true); wcd_enable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PDM_WD); + wcd_enable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_UVLO); /* Force remove group */ swr_remove_from_group(wsa883x->swr_slave, wsa883x->swr_slave->dev_num); @@ -998,6 +1015,7 @@ static int wsa883x_spkr_event(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, WSA883X_PA_FSM_CTL, 0x01, 0x00); wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PDM_WD); + wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_UVLO); clear_bit(SPKR_STATUS, &wsa883x->status_mask); break; } @@ -1186,6 +1204,8 @@ static int wsa883x_codec_probe(struct snd_soc_component *component) struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); struct swr_device *dev; int variant = 0, version = 0; + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); if (!wsa883x) return -EINVAL; @@ -1205,6 +1225,10 @@ static int wsa883x_codec_probe(struct snd_soc_component *component) wsa883x_codec_init(component); wsa883x->global_pa_cnt = 0; + snd_soc_dapm_ignore_suspend(dapm, + wsa883x->dai_driver->playback.stream_name); + snd_soc_dapm_sync(dapm); + return 0; } @@ -1454,12 +1478,18 @@ static int wsa883x_swr_probe(struct swr_device *pdev) wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_SAF2WAR, "WSA SAF2WAR", wsa883x_saf2war_handle_irq, NULL); + wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_SAF2WAR); + wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_WAR2SAF, "WSA WAR2SAF", wsa883x_war2saf_handle_irq, NULL); + wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_WAR2SAF); + wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_DISABLE, "WSA OTP", wsa883x_otp_handle_irq, NULL); + wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_DISABLE); + wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_OCP, "WSA OCP", wsa883x_ocp_handle_irq, NULL); @@ -1483,10 +1513,14 @@ static int wsa883x_swr_probe(struct swr_device *pdev) wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_INTR_PIN, "WSA EXT INT", wsa883x_ext_int_handle_irq, NULL); + wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_INTR_PIN); + /* Under Voltage Lock out (UVLO) interrupt handle */ wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_UVLO, "WSA UVLO", wsa883x_uvlo_handle_irq, NULL); + wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_UVLO); + wcd_request_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PA_ON_ERR, "WSA PA ERR", wsa883x_pa_on_err_handle_irq, NULL); From 211f4896cea3ca1dd6710723d46d73a657bec237 Mon Sep 17 00:00:00 2001 From: Sudheer Papothi Date: Fri, 5 Jun 2020 06:10:48 +0530 Subject: [PATCH 056/116] ASoC: wcd938x: Add dapm ignore suspend for DAIs Add dapm ignore suspend for playback and capture DAIs to avoid wakeup during power collapse. Change-Id: If023597542423253a565dcf0f13ee9f08b357b93 Signed-off-by: Sudheer Papothi --- asoc/codecs/wcd938x/wcd938x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/asoc/codecs/wcd938x/wcd938x.c b/asoc/codecs/wcd938x/wcd938x.c index a6652bd4e4..c0e19be963 100644 --- a/asoc/codecs/wcd938x/wcd938x.c +++ b/asoc/codecs/wcd938x/wcd938x.c @@ -3634,6 +3634,8 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component) goto err_hwdep; } + snd_soc_dapm_ignore_suspend(dapm, "WCD938X_AIF Playback"); + snd_soc_dapm_ignore_suspend(dapm, "WCD938X_AIF Capture"); snd_soc_dapm_ignore_suspend(dapm, "AMIC1"); snd_soc_dapm_ignore_suspend(dapm, "AMIC2"); snd_soc_dapm_ignore_suspend(dapm, "AMIC3"); From 6f0a3e6cb81c4802a08c36d73883830051086991 Mon Sep 17 00:00:00 2001 From: Sudheer Papothi Date: Fri, 5 Jun 2020 10:15:18 +0530 Subject: [PATCH 057/116] ASoC: swr-dmic: Add ignore suspend for dapm widgets Add ignore suspend for dapm widgets to avoid waking up the system during power collapse. Change-Id: I4eec9785f2e722d1fbcbf26c2635af9825b30115 Signed-off-by: Sudheer Papothi --- asoc/codecs/swr-dmic.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/asoc/codecs/swr-dmic.c b/asoc/codecs/swr-dmic.c index 4f5b23c2f2..c9d69f293a 100644 --- a/asoc/codecs/swr-dmic.c +++ b/asoc/codecs/swr-dmic.c @@ -325,11 +325,38 @@ static int swr_dmic_codec_probe(struct snd_soc_component *component) { struct swr_dmic_priv *swr_dmic = snd_soc_component_get_drvdata(component); + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + char w_name[100]; if (!swr_dmic) return -EINVAL; swr_dmic->component = component; + snd_soc_dapm_ignore_suspend(dapm, + swr_dmic->dai_driver->capture.stream_name); + memset(w_name, 0, 100); + strlcpy(w_name, component->name_prefix, 100); + strlcat(w_name, " SWR_DMIC", 100); + snd_soc_dapm_ignore_suspend(dapm, w_name); + + memset(w_name, 0, 100); + strlcpy(w_name, component->name_prefix, 100); + strlcat(w_name, " SMIC_SUPPLY", 100); + snd_soc_dapm_ignore_suspend(dapm, w_name); + + memset(w_name, 0, 100); + strlcpy(w_name, component->name_prefix, 100); + strlcat(w_name, " SMIC_PORT_EN", 100); + snd_soc_dapm_ignore_suspend(dapm, w_name); + + memset(w_name, 0, 100); + strlcpy(w_name, component->name_prefix, 100); + strlcat(w_name, " SWR_DMIC_OUTPUT", 100); + snd_soc_dapm_ignore_suspend(dapm, w_name); + + snd_soc_dapm_sync(dapm); + return 0; } @@ -624,6 +651,8 @@ static int swr_dmic_down(struct swr_device *pdev) return -EINVAL; } + dev_dbg(&pdev->dev, "%s: is_en_supply: %d\n", + __func__, swr_dmic->is_en_supply); --swr_dmic->is_en_supply; if (swr_dmic->is_en_supply < 0) { dev_warn(&pdev->dev, "%s: mismatch in supply count %d\n", From 3d88fa349ab3281b16e879cca421ad1669b723bf Mon Sep 17 00:00:00 2001 From: Sudheer Papothi Date: Wed, 27 May 2020 01:30:38 +0530 Subject: [PATCH 058/116] ASoC: lahaina: Add support for VI sense backend Add changes for VI sense WSA_CDC_DMA_TX_0 as backend dailink to support recording of VI sense data. Change-Id: Iea90290f2189d669ca5660373849a7e987483fc4 Signed-off-by: Sudheer Papothi --- asoc/lahaina.c | 11 +++++++++++ asoc/msm_dailink.h | 5 +++++ 2 files changed, 16 insertions(+) diff --git a/asoc/lahaina.c b/asoc/lahaina.c index 42d817341d..a206ac2b4e 100644 --- a/asoc/lahaina.c +++ b/asoc/lahaina.c @@ -6694,6 +6694,17 @@ static struct snd_soc_dai_link msm_wsa_cdc_dma_be_dai_links[] = { .ops = &msm_cdc_dma_be_ops, SND_SOC_DAILINK_REG(wsa_dma_tx1), }, + { + .name = LPASS_BE_WSA_CDC_DMA_TX_0_VI, + .stream_name = "WSA CDC DMA0 Capture", + .no_pcm = 1, + .dpcm_capture = 1, + .id = MSM_BACKEND_DAI_WSA_CDC_DMA_TX_0, + .be_hw_params_fixup = msm_be_hw_params_fixup, + .ops = &msm_cdc_dma_be_ops, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(wsa_dma_tx0_vi), + }, }; static struct snd_soc_dai_link msm_rx_tx_cdc_dma_be_dai_links[] = { diff --git a/asoc/msm_dailink.h b/asoc/msm_dailink.h index 35159cf382..bfc56d41da 100644 --- a/asoc/msm_dailink.h +++ b/asoc/msm_dailink.h @@ -323,6 +323,11 @@ SND_SOC_DAILINK_DEFS(sen_tdm_tx_0, DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")), DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing"))); +SND_SOC_DAILINK_DEFS(wsa_dma_tx0_vi, + DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-cdc-dma-dev.45057")), + DAILINK_COMP_ARRAY(COMP_CODEC("bolero_codec", "wsa_macro_vifeedback")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing"))); + SND_SOC_DAILINK_DEFS(slimbus_7_rx, DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-dev.16398")), DAILINK_COMP_ARRAY(COMP_CODEC("btfmslim_slave", From d173af6770ed3e1069054400c2d1a0580c188846 Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Thu, 9 Apr 2020 17:24:02 +0530 Subject: [PATCH 059/116] asoc: codecs: Fix out of bounds access in register show function In register show function, when snprintf returns a negative value out of bounds access occurs while copying the data to user. Add return value check on snprintf before copy_to_user to fix this and add sizeof() for tmp_buff to avoid buffer overflow. Change-Id: I15f1add37987d2176a165669d7a5b40bd576004c Signed-off-by: Prasad Kumpatla --- asoc/codecs/wsa883x/wsa883x.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/asoc/codecs/wsa883x/wsa883x.c b/asoc/codecs/wsa883x/wsa883x.c index 8b3d588130..138e019b46 100644 --- a/asoc/codecs/wsa883x/wsa883x.c +++ b/asoc/codecs/wsa883x/wsa883x.c @@ -254,7 +254,12 @@ static ssize_t swr_slave_reg_show(struct swr_device *pdev, char __user *ubuf, swr_read(pdev, pdev->dev_num, i, ®_val, 1); len = snprintf(tmp_buf, sizeof(tmp_buf), "0x%.3x: 0x%.2x\n", i, (reg_val & 0xFF)); - if (((total + len) >= count - 1) || (len < 0)) + if (len < 0) { + pr_err("%s: fail to fill the buffer\n", __func__); + total = -EFAULT; + goto copy_err; + } + if ((total + len) >= count - 1) break; if (copy_to_user((ubuf + total), tmp_buf, len)) { pr_err("%s: fail to copy reg dump\n", __func__); From 4eed73be7108087a5af12ed365101efd49f99483 Mon Sep 17 00:00:00 2001 From: Akhil Karuturi Date: Fri, 5 Jun 2020 09:57:26 -0700 Subject: [PATCH 060/116] ASoC: Remove unused config Config variables are no longer supported and are replaced by audio effects config in Lahaina. Change-Id: Ic817791a470a7e4b0fac280115edf849fecc91c7 Signed-off-by: Akhil Karuturi --- include/uapi/audio/sound/audio_effects.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/uapi/audio/sound/audio_effects.h b/include/uapi/audio/sound/audio_effects.h index 6279e0c2d0..3cd98b7881 100644 --- a/include/uapi/audio/sound/audio_effects.h +++ b/include/uapi/audio/sound/audio_effects.h @@ -10,7 +10,6 @@ #define AUDIO_EFFECTS_CONFIG_CACHE 0 #define AUDIO_EFFECTS_CONFIG_SET 1 #define AUDIO_EFFECTS_CONFIG_GET 2 -#define CONFIG_SET 1 /* CONFIG HEADER */ /* From f4c77b97fa1f1673f236efdbb1f2170744d23291 Mon Sep 17 00:00:00 2001 From: Meng Wang Date: Mon, 8 Jun 2020 07:59:11 +0800 Subject: [PATCH 061/116] asoc: send codec dma data alignment when it's set Only send codec dma data alignment cmd when it's set. Change-Id: I413c28bc01b4f49aa0291b868852dfb5835add8e Signed-off-by: Meng Wang --- asoc/msm-dai-q6-v2.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c index 4e3f2581c2..7e1b1bae15 100644 --- a/asoc/msm-dai-q6-v2.c +++ b/asoc/msm-dai-q6-v2.c @@ -12602,12 +12602,13 @@ static int msm_dai_q6_cdc_dma_prepare(struct snd_pcm_substream *substream, dai_data->port_config.cdc_dma.data_format = AFE_LINEAR_PCM_DATA_PACKED_16BIT; - rc = afe_send_cdc_dma_data_align(dai->id, + if (dai_data->cdc_dma_data_align) { + rc = afe_send_cdc_dma_data_align(dai->id, dai_data->cdc_dma_data_align); - if (rc) - pr_debug("%s: afe send data alignment failed %d\n", - __func__, rc); - + if (rc) + pr_debug("%s: afe send data alignment failed %d\n", + __func__, rc); + } rc = afe_port_start(dai->id, &dai_data->port_config, dai_data->rate); if (rc < 0) From 61f235e5bdfdb7993b78b372bbc054d3defe7e2c Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Fri, 27 Mar 2020 12:46:38 +0530 Subject: [PATCH 062/116] asoc: bolero: Register for AFE event for all SVA usecases For island SVA usecase, ensure register for AFE in-band interrupt. Change-Id: I24e6dfadfaa38919114000fb09a7906264020cd9 Signed-off-by: Laxminath Kasam --- asoc/codecs/bolero/bolero-cdc.c | 5 ++- asoc/codecs/bolero/bolero-cdc.h | 7 ++-- asoc/codecs/bolero/tx-macro.c | 8 ++-- asoc/codecs/bolero/va-macro.c | 69 ++++++++++++++++++++++++++++++++- 4 files changed, 79 insertions(+), 10 deletions(-) diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c index c46bcad0cd..32a3380f88 100644 --- a/asoc/codecs/bolero/bolero-cdc.c +++ b/asoc/codecs/bolero/bolero-cdc.c @@ -1094,7 +1094,7 @@ EXPORT_SYMBOL(bolero_tx_mclk_enable); * Returns 0 on success or -EINVAL on error. */ int bolero_register_event_listener(struct snd_soc_component *component, - bool enable) + bool enable, bool is_dmic_sva) { struct bolero_priv *priv = NULL; int ret = 0; @@ -1113,7 +1113,8 @@ int bolero_register_event_listener(struct snd_soc_component *component, if (priv->macro_params[TX_MACRO].reg_evt_listener) ret = priv->macro_params[TX_MACRO].reg_evt_listener(component, - enable); + enable, + is_dmic_sva); return ret; } diff --git a/asoc/codecs/bolero/bolero-cdc.h b/asoc/codecs/bolero/bolero-cdc.h index 1f21fd69c8..ba0f3ce57a 100644 --- a/asoc/codecs/bolero/bolero-cdc.h +++ b/asoc/codecs/bolero/bolero-cdc.h @@ -77,7 +77,8 @@ struct macro_ops { u32 size, void *data); int (*clk_div_get)(struct snd_soc_component *component); int (*clk_switch)(struct snd_soc_component *component, int clk_src); - int (*reg_evt_listener)(struct snd_soc_component *component, bool en); + int (*reg_evt_listener)(struct snd_soc_component *component, + bool en, bool is_dmic_sva); int (*clk_enable)(struct snd_soc_component *c, bool en); char __iomem *io_base; u16 clk_id_req; @@ -104,7 +105,7 @@ int bolero_runtime_suspend(struct device *dev); int bolero_set_port_map(struct snd_soc_component *component, u32 size, void *data); int bolero_tx_clk_switch(struct snd_soc_component *component, int clk_src); int bolero_register_event_listener(struct snd_soc_component *component, - bool enable); + bool enable, bool is_dmic_sva); void bolero_wsa_pa_on(struct device *dev); bool bolero_check_core_votes(struct device *dev); int bolero_tx_mclk_enable(struct snd_soc_component *c, bool enable); @@ -178,7 +179,7 @@ static inline int bolero_tx_clk_switch(struct snd_soc_component *component, static inline int bolero_register_event_listener( struct snd_soc_component *component, - bool enable) + bool enable, bool is_dmic_sva) { return 0; } diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c index 55b2c3017b..4c3b507fec 100644 --- a/asoc/codecs/bolero/tx-macro.c +++ b/asoc/codecs/bolero/tx-macro.c @@ -2497,7 +2497,7 @@ static const struct snd_kcontrol_new tx_macro_snd_controls[] = { }; static int tx_macro_register_event_listener(struct snd_soc_component *component, - bool enable) + bool enable, bool is_dmic_sva) { struct device *tx_dev = NULL; struct tx_macro_priv *tx_priv = NULL; @@ -2524,10 +2524,12 @@ static int tx_macro_register_event_listener(struct snd_soc_component *component, ret = swrm_wcd_notify( tx_priv->swr_ctrl_data[0].tx_swr_pdev, SWR_REGISTER_WAKEUP, NULL); - msm_cdc_pinctrl_set_wakeup_capable( + if (!is_dmic_sva) + msm_cdc_pinctrl_set_wakeup_capable( tx_priv->tx_swr_gpio_p, false); } else { - msm_cdc_pinctrl_set_wakeup_capable( + if (!is_dmic_sva) + msm_cdc_pinctrl_set_wakeup_capable( tx_priv->tx_swr_gpio_p, true); ret = swrm_wcd_notify( tx_priv->swr_ctrl_data[0].tx_swr_pdev, diff --git a/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c index 710eb7190d..a37eb16322 100644 --- a/asoc/codecs/bolero/va-macro.c +++ b/asoc/codecs/bolero/va-macro.c @@ -459,14 +459,14 @@ static int va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w, dev_dbg(va_dev, "%s: clock switch failed\n", __func__); if (va_priv->lpi_enable) { - bolero_register_event_listener(component, true); + bolero_register_event_listener(component, true, false); va_priv->register_event_listener = true; } break; case SND_SOC_DAPM_POST_PMD: if (va_priv->register_event_listener) { va_priv->register_event_listener = false; - bolero_register_event_listener(component, false); + bolero_register_event_listener(component, false, false); } if (bolero_tx_clk_switch(component, CLK_SRC_TX_RCG)) dev_dbg(va_dev, "%s: clock switch failed\n",__func__); @@ -482,6 +482,45 @@ static int va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w, return ret; } +static int va_macro_swr_intr_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + int ret = 0; + struct device *va_dev = NULL; + struct va_macro_priv *va_priv = NULL; + + if (!va_macro_get_data(component, &va_dev, &va_priv, __func__)) + return -EINVAL; + + dev_dbg(va_dev, "%s: event = %d, lpi_enable = %d\n", + __func__, event, va_priv->lpi_enable); + + if (!va_priv->lpi_enable) + return ret; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (va_priv->lpi_enable) { + bolero_register_event_listener(component, true, true); + va_priv->register_event_listener = true; + } + break; + case SND_SOC_DAPM_POST_PMD: + if (va_priv->register_event_listener) { + va_priv->register_event_listener = false; + bolero_register_event_listener(component, false, true); + } + break; + default: + dev_err(va_priv->dev, + "%s: invalid DAPM event %d\n", __func__, event); + ret = -EINVAL; + } + return ret; +} + static int va_macro_tx_swr_clk_event_v2(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -1989,6 +2028,10 @@ static const struct snd_soc_dapm_widget va_macro_dapm_widgets_v3[] = { SND_SOC_DAPM_SUPPLY_S("VA_SWR_PWR", -1, SND_SOC_NOPM, 0, 0, va_macro_swr_pwr_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("VA_SWR_INTR", 0, SND_SOC_NOPM, 0, 0, + va_macro_swr_intr_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), }; static const struct snd_soc_dapm_widget va_macro_dapm_widgets[] = { @@ -2133,6 +2176,10 @@ static const struct snd_soc_dapm_widget va_macro_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY_S("VA_MCLK", -1, SND_SOC_NOPM, 0, 0, va_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("VA_SWR_INTR", 0, SND_SOC_NOPM, 0, 0, + va_macro_swr_intr_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), }; static const struct snd_soc_dapm_widget va_macro_wod_dapm_widgets[] = { @@ -2279,6 +2326,15 @@ static const struct snd_soc_dapm_route va_audio_map_v3[] = { {"VA SMIC MUX3", "SWR_MIC9", "VA SWR_INPUT"}, {"VA SMIC MUX3", "SWR_MIC10", "VA SWR_INPUT"}, {"VA SMIC MUX3", "SWR_MIC11", "VA SWR_INPUT"}, + + {"VA DMIC0", NULL, "VA_SWR_INTR"}, + {"VA DMIC1", NULL, "VA_SWR_INTR"}, + {"VA DMIC2", NULL, "VA_SWR_INTR"}, + {"VA DMIC3", NULL, "VA_SWR_INTR"}, + {"VA DMIC4", NULL, "VA_SWR_INTR"}, + {"VA DMIC5", NULL, "VA_SWR_INTR"}, + {"VA DMIC6", NULL, "VA_SWR_INTR"}, + {"VA DMIC7", NULL, "VA_SWR_INTR"}, }; static const struct snd_soc_dapm_route va_audio_map_v2[] = { @@ -2515,6 +2571,15 @@ static const struct snd_soc_dapm_route va_audio_map[] = { {"VA SMIC MUX7", "SWR_DMIC6", "VA SWR_MIC6"}, {"VA SMIC MUX7", "SWR_DMIC7", "VA SWR_MIC7"}, + {"VA DMIC0", NULL, "VA_SWR_INTR"}, + {"VA DMIC1", NULL, "VA_SWR_INTR"}, + {"VA DMIC2", NULL, "VA_SWR_INTR"}, + {"VA DMIC3", NULL, "VA_SWR_INTR"}, + {"VA DMIC4", NULL, "VA_SWR_INTR"}, + {"VA DMIC5", NULL, "VA_SWR_INTR"}, + {"VA DMIC6", NULL, "VA_SWR_INTR"}, + {"VA DMIC7", NULL, "VA_SWR_INTR"}, + {"VA SWR_ADC0", NULL, "VA_SWR_PWR"}, {"VA SWR_ADC1", NULL, "VA_SWR_PWR"}, {"VA SWR_ADC2", NULL, "VA_SWR_PWR"}, From d02c7efb3591bdca22f06a0744835fb48d1b0660 Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Tue, 28 Apr 2020 00:02:32 +0530 Subject: [PATCH 063/116] soc: mstr-ctrl: Retain Audio_HM voting until suspend Restore change to retain audio_hm voting and ensure AOP hang issue not seen by masking interrupt wakeup of swr pinctrl pins. Change-Id: I51bf36d6d6b0999abf10a4bc94cce900d1adf1d5 Signed-off-by: Laxminath Kasam --- asoc/codecs/bolero/rx-macro.c | 2 ++ asoc/codecs/bolero/tx-macro.c | 36 ++++++++++++++++++++++++++-------- asoc/codecs/bolero/va-macro.c | 2 ++ asoc/codecs/bolero/wsa-macro.c | 2 ++ soc/swr-mstr-ctrl.c | 23 ++++++++++++---------- soc/swr-mstr-ctrl.h | 4 ++++ 6 files changed, 51 insertions(+), 18 deletions(-) diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c index 87c9477ad1..46c0937ea4 100644 --- a/asoc/codecs/bolero/rx-macro.c +++ b/asoc/codecs/bolero/rx-macro.c @@ -378,6 +378,7 @@ struct rx_swr_ctrl_platform_data { void *data), void *swrm_handle, int action); + int (*pinctrl_setup)(void *handle, bool enable); }; enum { @@ -4104,6 +4105,7 @@ static int rx_macro_probe(struct platform_device *pdev) rx_priv->swr_plat_data.clk = rx_swrm_clock; rx_priv->swr_plat_data.core_vote = rx_macro_core_vote; rx_priv->swr_plat_data.handle_irq = NULL; + rx_priv->swr_plat_data.pinctrl_setup = NULL; ret = of_property_read_u8_array(pdev->dev.of_node, "qcom,rx-bcl-pmic-params", bcl_pmic_params, diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c index 4c3b507fec..6fb76a9362 100644 --- a/asoc/codecs/bolero/tx-macro.c +++ b/asoc/codecs/bolero/tx-macro.c @@ -81,6 +81,7 @@ struct tx_macro_swr_ctrl_platform_data { void *data), void *swrm_handle, int action); + int (*pinctrl_setup)(void *handle, bool enable); }; enum { @@ -2496,12 +2497,30 @@ static const struct snd_kcontrol_new tx_macro_snd_controls[] = { tx_macro_get_bcs, tx_macro_set_bcs), }; +static int tx_macro_pinctrl_setup(void *handle, bool enable) +{ + struct tx_macro_priv *tx_priv = (struct tx_macro_priv *) handle; + + if (tx_priv == NULL) { + pr_err("%s: tx priv data is NULL\n", __func__); + return -EINVAL; + } + if (enable) + msm_cdc_pinctrl_set_wakeup_capable( + tx_priv->tx_swr_gpio_p, true); + else + msm_cdc_pinctrl_set_wakeup_capable( + tx_priv->tx_swr_gpio_p, false); + return 0; +} + static int tx_macro_register_event_listener(struct snd_soc_component *component, bool enable, bool is_dmic_sva) { struct device *tx_dev = NULL; struct tx_macro_priv *tx_priv = NULL; int ret = 0; + u32 dmic_sva = is_dmic_sva; if (!component) return -EINVAL; @@ -2523,17 +2542,17 @@ static int tx_macro_register_event_listener(struct snd_soc_component *component, if (enable) { ret = swrm_wcd_notify( tx_priv->swr_ctrl_data[0].tx_swr_pdev, - SWR_REGISTER_WAKEUP, NULL); - if (!is_dmic_sva) - msm_cdc_pinctrl_set_wakeup_capable( - tx_priv->tx_swr_gpio_p, false); + SWR_REGISTER_WAKEUP, &dmic_sva); + msm_cdc_pinctrl_set_wakeup_capable( + tx_priv->tx_swr_gpio_p, false); } else { - if (!is_dmic_sva) - msm_cdc_pinctrl_set_wakeup_capable( - tx_priv->tx_swr_gpio_p, true); + /* while teardown we can reset the flag */ + dmic_sva = 0; + msm_cdc_pinctrl_set_wakeup_capable( + tx_priv->tx_swr_gpio_p, true); ret = swrm_wcd_notify( tx_priv->swr_ctrl_data[0].tx_swr_pdev, - SWR_DEREGISTER_WAKEUP, NULL); + SWR_DEREGISTER_WAKEUP, &dmic_sva); } } @@ -3324,6 +3343,7 @@ static int tx_macro_probe(struct platform_device *pdev) tx_priv->swr_plat_data.clk = tx_macro_swrm_clock; tx_priv->swr_plat_data.core_vote = tx_macro_core_vote; tx_priv->swr_plat_data.handle_irq = NULL; + tx_priv->swr_plat_data.pinctrl_setup = tx_macro_pinctrl_setup; mutex_init(&tx_priv->swr_clk_lock); } tx_priv->is_used_tx_swr_gpio = is_used_tx_swr_gpio; diff --git a/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c index a37eb16322..760537b623 100644 --- a/asoc/codecs/bolero/va-macro.c +++ b/asoc/codecs/bolero/va-macro.c @@ -130,6 +130,7 @@ struct va_macro_swr_ctrl_platform_data { void *data), void *swrm_handle, int action); + int (*pinctrl_setup)(void *handle, bool enable); }; struct va_macro_priv { @@ -3229,6 +3230,7 @@ static int va_macro_probe(struct platform_device *pdev) va_priv->swr_plat_data.clk = va_macro_swrm_clock; va_priv->swr_plat_data.core_vote = va_macro_core_vote; va_priv->swr_plat_data.handle_irq = NULL; + va_priv->swr_plat_data.pinctrl_setup = NULL; mutex_init(&va_priv->swr_clk_lock); } va_priv->is_used_va_swr_gpio = is_used_va_swr_gpio; diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c index 41981aa593..9ac809b198 100644 --- a/asoc/codecs/bolero/wsa-macro.c +++ b/asoc/codecs/bolero/wsa-macro.c @@ -166,6 +166,7 @@ struct wsa_macro_swr_ctrl_platform_data { void *data), void *swrm_handle, int action); + int (*pinctrl_setup)(void *handle, bool enable); }; struct wsa_macro_bcl_pmic_params { @@ -3194,6 +3195,7 @@ static int wsa_macro_probe(struct platform_device *pdev) wsa_priv->swr_plat_data.clk = wsa_swrm_clock; wsa_priv->swr_plat_data.core_vote = wsa_macro_core_vote; wsa_priv->swr_plat_data.handle_irq = NULL; + wsa_priv->swr_plat_data.pinctrl_setup = NULL; ret = of_property_read_u32(pdev->dev.of_node, "qcom,default-clk-id", &default_clk_id); diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index b2853b399a..4f2080cb32 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -2458,6 +2458,8 @@ static int swrm_probe(struct platform_device *pdev) ret = -EINVAL; goto err_pdata_fail; } + swrm->pinctrl_setup = pdata->pinctrl_setup; + if (of_property_read_u32(pdev->dev.of_node, "qcom,swr-clock-stop-mode0", &swrm->clk_stop_mode0_supp)) { @@ -2779,7 +2781,6 @@ static int swrm_runtime_resume(struct device *dev) int ret = 0; bool swrm_clk_req_err = false; bool hw_core_err = false; - bool aud_core_err = false; struct swr_master *mstr = &swrm->master; struct swr_device *swr_dev; u32 temp = 0; @@ -2798,7 +2799,7 @@ static int swrm_runtime_resume(struct device *dev) if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, true)) { dev_err(dev, "%s:lpass audio hw enable failed\n", __func__); - aud_core_err = true; + swrm->aud_core_err = true; } if ((swrm->state == SWR_MSTR_DOWN) || @@ -2817,6 +2818,9 @@ static int swrm_runtime_resume(struct device *dev) irq_get_irq_data(swrm->wake_irq))) disable_irq_nosync(swrm->wake_irq); mutex_unlock(&swrm->irq_lock); + if (swrm->dmic_sva && swrm->pinctrl_setup) + swrm->pinctrl_setup(swrm->handle, + false); } if (swrm->ipc_wakeup) msm_aud_evt_blocking_notifier_call_chain( @@ -2890,7 +2894,7 @@ static int swrm_runtime_resume(struct device *dev) swrm->state = SWR_MSTR_UP; } exit: - if (!aud_core_err) + if (ret && !swrm->aud_core_err) swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false); if (!hw_core_err) swrm_request_hw_vote(swrm, LPASS_HW_CORE, false); @@ -2913,7 +2917,6 @@ static int swrm_runtime_suspend(struct device *dev) struct swr_mstr_ctrl *swrm = platform_get_drvdata(pdev); int ret = 0; bool hw_core_err = false; - bool aud_core_err = false; struct swr_master *mstr = &swrm->master; struct swr_device *swr_dev; int current_state = 0; @@ -2932,11 +2935,6 @@ static int swrm_runtime_suspend(struct device *dev) __func__); hw_core_err = true; } - if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, true)) { - dev_err(dev, "%s:lpass audio hw enable failed\n", - __func__); - aud_core_err = true; - } if ((current_state == SWR_MSTR_UP) || (current_state == SWR_MSTR_SSR)) { @@ -3005,6 +3003,8 @@ static int swrm_runtime_suspend(struct device *dev) if (swrm->clk_stop_mode0_supp) { if (swrm->wake_irq > 0) { + if (swrm->dmic_sva && swrm->pinctrl_setup) + swrm->pinctrl_setup(swrm->handle, true); enable_irq(swrm->wake_irq); } else if (swrm->ipc_wakeup) { msm_aud_evt_blocking_notifier_call_chain( @@ -3018,10 +3018,11 @@ static int swrm_runtime_suspend(struct device *dev) if (current_state != SWR_MSTR_SSR) swrm->state = SWR_MSTR_DOWN; exit: - if (!aud_core_err) + if (!swrm->aud_core_err) swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false); if (!hw_core_err) swrm_request_hw_vote(swrm, LPASS_HW_CORE, false); + swrm->aud_core_err = false; mutex_unlock(&swrm->reslock); trace_printk("%s: pm_runtime: suspend done state: %d\n", __func__, swrm->state); @@ -3353,10 +3354,12 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data) case SWR_REGISTER_WAKEUP: msm_aud_evt_blocking_notifier_call_chain( SWR_WAKE_IRQ_REGISTER, (void *)swrm); + swrm->dmic_sva = *(u32 *)data; break; case SWR_DEREGISTER_WAKEUP: msm_aud_evt_blocking_notifier_call_chain( SWR_WAKE_IRQ_DEREGISTER, (void *)swrm); + swrm->dmic_sva = 0; break; case SWR_SET_PORT_MAP: if (!data) { diff --git a/soc/swr-mstr-ctrl.h b/soc/swr-mstr-ctrl.h index c8444032d8..f6d5a186d6 100644 --- a/soc/swr-mstr-ctrl.h +++ b/soc/swr-mstr-ctrl.h @@ -115,6 +115,7 @@ struct swr_ctrl_platform_data { int (*core_vote)(void *handle, bool enable); int (*reg_irq)(void *handle, irqreturn_t(*irq_handler)(int irq, void *data), void *swr_handle, int type); + int (*pinctrl_setup)(void *handle, bool enable); }; struct swr_mstr_ctrl { @@ -148,6 +149,7 @@ struct swr_mstr_ctrl { int (*core_vote)(void *handle, bool enable); int (*reg_irq)(void *handle, irqreturn_t(*irq_handler)(int irq, void *data), void *swr_handle, int type); + int (*pinctrl_setup)(void *handle, bool enable); int irq; int wake_irq; int version; @@ -173,8 +175,10 @@ struct swr_mstr_ctrl { u32 clk_stop_mode0_supp; struct work_struct wakeup_work; u32 ipc_wakeup; + u32 dmic_sva; bool dev_up; bool ipc_wakeup_triggered; + bool aud_core_err; struct pm_qos_request pm_qos_req; enum swrm_pm_state pm_state; wait_queue_head_t pm_wq; From 4dc669fa7e8e75db2250eab9359e2d838f9a4785 Mon Sep 17 00:00:00 2001 From: Sudheer Papothi Date: Wed, 3 Jun 2020 08:36:36 +0530 Subject: [PATCH 064/116] soc: soundwire: update soundwire debug logs Update soundwire debug logs to avoid confusion during soundwire enumeration of slaves. Change-Id: Ib265fb3bf777a1461a9041bb269cdcb5c9ac5e2b Signed-off-by: Sudheer Papothi --- soc/soundwire.c | 6 +----- soc/swr-mstr-ctrl.c | 14 ++++++++------ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/soc/soundwire.c b/soc/soundwire.c index 72a94ace14..04b74f8270 100644 --- a/soc/soundwire.c +++ b/soc/soundwire.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #include @@ -473,10 +473,6 @@ int swr_get_logical_dev_num(struct swr_device *dev, u64 dev_id, } mutex_lock(&master->mlock); ret = master->get_logical_dev_num(master, dev_id, dev_num); - if (ret) { - pr_err("%s: Error %d to get logical addr for device %llx\n", - __func__, ret, dev_id); - } mutex_unlock(&master->mlock); return ret; } diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index b2853b399a..f2030a17c7 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -1873,7 +1873,7 @@ handle_irq: swrm_enable_slave_irq(swrm); if (status == swrm->slave_status) { dev_dbg(swrm->dev, - "%s: No change in slave status: %d\n", + "%s: No change in slave status: 0x%x\n", __func__, status); break; } @@ -2177,17 +2177,19 @@ static int swrm_get_logical_dev_num(struct swr_master *mstr, u64 dev_id, if ((id & SWR_DEV_ID_MASK) == dev_id) { *dev_num = i; ret = 0; + dev_info(swrm->dev, + "%s: devnum %d assigned for dev %llx\n", + __func__, i, + swr_dev->addr); } - dev_dbg(swrm->dev, - "%s: devnum %d is assigned for dev addr %lx\n", - __func__, i, swr_dev->addr); } } } } if (ret) - dev_err(swrm->dev, "%s: device 0x%llx is not ready\n", - __func__, dev_id); + dev_err_ratelimited(swrm->dev, + "%s: device 0x%llx is not ready\n", + __func__, dev_id); pm_runtime_mark_last_busy(swrm->dev); pm_runtime_put_autosuspend(swrm->dev); From 0a79d427705d342e4fdcdefe7dedec3e0d56f019 Mon Sep 17 00:00:00 2001 From: Zhou Song Date: Tue, 2 Jun 2020 23:30:57 +0800 Subject: [PATCH 065/116] q6afe: add support for handling rx proxy ports concurrency In case of two concurrent active rx proxy ports, add separate callback data to handle proxy reading. Change-Id: I4de631b9cfead777c970103a79578964e5950eb9 Signed-off-by: Zhou Song --- dsp/q6afe.c | 32 ++++++++++++++++++++------------ include/dsp/q6afe-v2.h | 2 ++ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/dsp/q6afe.c b/dsp/q6afe.c index cbc2035aca..51b8919ec1 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -126,7 +126,7 @@ struct afe_ctl { void (*rx_cb)(uint32_t opcode, uint32_t token, uint32_t *payload, void *priv); void *tx_private_data; - void *rx_private_data; + void *rx_private_data[NUM_RX_PROXY_PORTS]; uint32_t mmap_handle; void (*pri_spdif_tx_cb)(uint32_t opcode, @@ -737,12 +737,14 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv) this_afe.tx_private_data); this_afe.tx_cb = NULL; } - if (this_afe.rx_cb) { - this_afe.rx_cb(data->opcode, data->token, - data->payload, - this_afe.rx_private_data); - this_afe.rx_cb = NULL; + for (i = 0; i < NUM_RX_PROXY_PORTS; i++) { + if (this_afe.rx_cb && this_afe.rx_private_data[i]) { + this_afe.rx_cb(data->opcode, data->token, + data->payload, + this_afe.rx_private_data[i]); + } } + this_afe.rx_cb = NULL; return 0; } @@ -863,7 +865,7 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv) port_id = RT_PROXY_PORT_001_TX; break; case AFE_PORT_DATA_CMD_RT_PROXY_PORT_READ_V2: - port_id = RT_PROXY_PORT_001_RX; + port_id = data->src_port; break; case AFE_CMD_ADD_TOPOLOGIES: atomic_set(&this_afe.state, 0); @@ -1011,7 +1013,7 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv) if (this_afe.rx_cb) { this_afe.rx_cb(data->opcode, data->token, data->payload, - this_afe.rx_private_data); + this_afe.rx_private_data[PORTID_TO_IDX(port_id)]); } break; } @@ -7095,7 +7097,7 @@ int afe_register_get_events(u16 port_id, } else if (port_id == RT_PROXY_PORT_001_RX || port_id == RT_PROXY_PORT_002_RX) { this_afe.rx_cb = cb; - this_afe.rx_private_data = private_data; + this_afe.rx_private_data[PORTID_TO_IDX(port_id)] = private_data; } rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, @@ -7128,6 +7130,7 @@ int afe_unregister_get_events(u16 port_id) int ret = 0; struct afe_service_cmd_unregister_rt_port_driver rtproxy; int index = 0; + uint16_t i = 0; pr_debug("%s:\n", __func__); @@ -7181,8 +7184,13 @@ int afe_unregister_get_events(u16 port_id) this_afe.tx_private_data = NULL; } else if (port_id == RT_PROXY_PORT_001_RX || port_id == RT_PROXY_PORT_002_RX) { - this_afe.rx_cb = NULL; - this_afe.rx_private_data = NULL; + this_afe.rx_private_data[PORTID_TO_IDX(port_id)] = NULL; + for (i = 0; i < NUM_RX_PROXY_PORTS; i++) { + if (this_afe.rx_private_data[i] != NULL) + break; + } + if (i == NUM_RX_PROXY_PORTS) + this_afe.rx_cb = NULL; } ret = afe_apr_send_pkt(&rtproxy, &this_afe.wait[index]); @@ -7281,7 +7289,7 @@ int afe_rt_proxy_port_read(phys_addr_t buf_addr_p, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); afecmd_rd.hdr.pkt_size = sizeof(afecmd_rd); afecmd_rd.hdr.src_port = 0; - afecmd_rd.hdr.dest_port = 0; + afecmd_rd.hdr.dest_port = port_id; afecmd_rd.hdr.token = 0; afecmd_rd.hdr.opcode = AFE_PORT_DATA_CMD_RT_PROXY_PORT_READ_V2; afecmd_rd.port_id = port_id; diff --git a/include/dsp/q6afe-v2.h b/include/dsp/q6afe-v2.h index 808113d18c..c55a2a0b3c 100644 --- a/include/dsp/q6afe-v2.h +++ b/include/dsp/q6afe-v2.h @@ -36,6 +36,8 @@ #define RT_PROXY_DAI_002_TX 0xE1 #define RT_PROXY_DAI_003_TX 0xF2 #define VIRTUAL_ID_TO_PORTID(val) ((val & 0xF) | 0x2000) +#define PORTID_TO_IDX(val) ((val & 0xF) >> 1) +#define NUM_RX_PROXY_PORTS 2 #define AFE_CLK_VERSION_V1 1 #define AFE_CLK_VERSION_V2 2 From 1e558673c62affe2e92e36725d385756848d5009 Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Fri, 5 Jun 2020 20:36:44 +0530 Subject: [PATCH 066/116] asoc: wcd938x: Add WCD ADC Mode mask to control modes To set correct swr clk rate in concurrency, use WCD ADC modes as status mask bit to confirm ADC paths active and control set clock rate. Change-Id: Id3401d6ed59bd617e0751e7c704268346b36dac4 Signed-off-by: Laxminath Kasam --- asoc/codecs/wcd938x/wcd938x.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/asoc/codecs/wcd938x/wcd938x.c b/asoc/codecs/wcd938x/wcd938x.c index 2ed99ea0c5..5b5012da2d 100644 --- a/asoc/codecs/wcd938x/wcd938x.c +++ b/asoc/codecs/wcd938x/wcd938x.c @@ -73,6 +73,10 @@ enum { HPH_PA_DELAY, AMIC2_BCS_ENABLE, WCD_SUPPLIES_LPM_MODE, + WCD_ADC1_MODE, + WCD_ADC2_MODE, + WCD_ADC3_MODE, + WCD_ADC4_MODE, }; enum { @@ -1541,13 +1545,17 @@ static int wcd938x_tx_swr_ctrl(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: if (strnstr(w->name, "ADC", sizeof("ADC"))) { - if (test_bit(WCD_ADC1, &wcd938x->status_mask)) + if (test_bit(WCD_ADC1, &wcd938x->status_mask) || + test_bit(WCD_ADC1_MODE, &wcd938x->status_mask)) mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC1]]; - if (test_bit(WCD_ADC2, &wcd938x->status_mask)) + if (test_bit(WCD_ADC2, &wcd938x->status_mask) || + test_bit(WCD_ADC2_MODE, &wcd938x->status_mask)) mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC2]]; - if (test_bit(WCD_ADC3, &wcd938x->status_mask)) + if (test_bit(WCD_ADC3, &wcd938x->status_mask) || + test_bit(WCD_ADC3_MODE, &wcd938x->status_mask)) mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC3]]; - if (test_bit(WCD_ADC4, &wcd938x->status_mask)) + if (test_bit(WCD_ADC4, &wcd938x->status_mask) || + test_bit(WCD_ADC4_MODE, &wcd938x->status_mask)) mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC4]]; if (mode != 0) { @@ -1594,6 +1602,14 @@ static int wcd938x_tx_swr_ctrl(struct snd_soc_dapm_widget *w, if (strnstr(w->name, "ADC", sizeof("ADC"))) wcd938x_set_swr_clk_rate(component, rate, bank); + if (strnstr(w->name, "ADC1", sizeof("ADC1"))) + clear_bit(WCD_ADC1_MODE, &wcd938x->status_mask); + else if (strnstr(w->name, "ADC2", sizeof("ADC2"))) + clear_bit(WCD_ADC2_MODE, &wcd938x->status_mask); + else if (strnstr(w->name, "ADC3", sizeof("ADC3"))) + clear_bit(WCD_ADC3_MODE, &wcd938x->status_mask); + else if (strnstr(w->name, "ADC4", sizeof("ADC4"))) + clear_bit(WCD_ADC4_MODE, &wcd938x->status_mask); break; }; @@ -2031,21 +2047,25 @@ static int wcd938x_event_notify(struct notifier_block *block, if (test_bit(WCD_ADC1, &wcd938x->status_mask)) { snd_soc_component_update_bits(component, WCD938X_ANA_TX_CH2, 0x40, 0x00); + set_bit(WCD_ADC1_MODE, &wcd938x->status_mask); clear_bit(WCD_ADC1, &wcd938x->status_mask); } if (test_bit(WCD_ADC2, &wcd938x->status_mask)) { snd_soc_component_update_bits(component, WCD938X_ANA_TX_CH2, 0x20, 0x00); + set_bit(WCD_ADC2_MODE, &wcd938x->status_mask); clear_bit(WCD_ADC2, &wcd938x->status_mask); } if (test_bit(WCD_ADC3, &wcd938x->status_mask)) { snd_soc_component_update_bits(component, WCD938X_ANA_TX_CH4, 0x40, 0x00); + set_bit(WCD_ADC3_MODE, &wcd938x->status_mask); clear_bit(WCD_ADC3, &wcd938x->status_mask); } if (test_bit(WCD_ADC4, &wcd938x->status_mask)) { snd_soc_component_update_bits(component, WCD938X_ANA_TX_CH4, 0x20, 0x00); + set_bit(WCD_ADC4_MODE, &wcd938x->status_mask); clear_bit(WCD_ADC4, &wcd938x->status_mask); } break; From 12aec928b63aba063105dad9f6d61a2ea5950571 Mon Sep 17 00:00:00 2001 From: Soumya Managoli Date: Fri, 13 Sep 2019 19:11:17 +0530 Subject: [PATCH 067/116] ipc: apr: Support ADSP restart recovery when stuck Add interface to register callback with adsp loader client. When adsp is stuck and does not respond for apr_send_pkt, resulting in continuous EAGAIN error, trigger this callback to enable adsp subsystem restart. Change-Id: Ib59cfdfba3313581d6612b872a2b7f1e19f8a76d Signed-off-by: Soumya Managoli --- include/ipc/apr.h | 11 ++++++++++- ipc/apr.c | 38 +++++++++++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/include/ipc/apr.h b/include/ipc/apr.h index 7aecee2655..40fc92c7d8 100644 --- a/include/ipc/apr.h +++ b/include/ipc/apr.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2010-2017, 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2010-2017, 2019, 2020, The Linux Foundation. All rights reserved. */ #ifndef __APR_H_ #define __APR_H_ @@ -12,6 +12,7 @@ enum apr_subsys_state { APR_SUBSYS_DOWN, APR_SUBSYS_UP, APR_SUBSYS_LOADED, + APR_SUBSYS_UNKNOWN, }; struct apr_q6 { @@ -19,6 +20,13 @@ struct apr_q6 { atomic_t q6_state; atomic_t modem_state; struct mutex lock; +/* + * ToDo - Multiple client support to be added. + * And checking for state UNKNOWN currently. + */ + void (*state_notify_cb)(enum apr_subsys_state state, + void *client_handle); + void *client_handle; }; struct apr_hdr { @@ -186,4 +194,5 @@ const char *apr_get_lpass_subsys_name(void); uint16_t apr_get_reset_domain(uint16_t proc); int apr_start_rx_rt(void *handle); int apr_end_rx_rt(void *handle); +void apr_register_adsp_state_cb(void *adsp_cb, void *client_handle); #endif diff --git a/ipc/apr.c b/ipc/apr.c index 6adb8ef42f..a8419d4460 100644 --- a/ipc/apr.c +++ b/ipc/apr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2010-2014, 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2010-2014, 2016-2020 The Linux Foundation. All rights reserved. */ #include @@ -32,9 +32,14 @@ #define APR_PKT_IPC_LOG_PAGE_CNT 2 +static int apr_pkt_cnt_adsp_restart = 20; +module_param(apr_pkt_cnt_adsp_restart, int, 0664); +MODULE_PARM_DESC(apr_pkt_cnt_adsp_restart, "set apr pktcount for adsp restart feature"); + static struct apr_q6 q6; static struct apr_client client[APR_DEST_MAX][APR_CLIENT_MAX]; static void *apr_pkt_ctx; +static int apr_send_pkt_count; static wait_queue_head_t modem_wait; static bool is_modem_up; static char *subsys_name = NULL; @@ -61,6 +66,8 @@ struct apr_private { static struct apr_private *apr_priv; static bool apr_cf_debug; +static struct work_struct apr_cb_work; +static void state_notify_cb(struct work_struct *work); #ifdef CONFIG_DEBUG_FS static struct dentry *debugfs_apr_debug; @@ -313,6 +320,7 @@ static void apr_adsp_up(void) schedule_work(&apr_priv->add_chld_dev_work); spin_unlock(&apr_priv->apr_lock); snd_event_notify(apr_priv->dev, SND_EVENT_UP); + cancel_work_sync(&apr_cb_work); } int apr_load_adsp_image(void) @@ -415,7 +423,7 @@ int apr_send_pkt(void *handle, uint32_t *buf) w_len = rc; if (w_len != hdr->pkt_size) { pr_err("%s: Unable to write whole APR pkt successfully: %d\n", - __func__, rc); + __func__, rc); rc = -EINVAL; } } else { @@ -426,6 +434,17 @@ int apr_send_pkt(void *handle, uint32_t *buf) __func__); rc = -ENETRESET; } + if (rc == -EAGAIN || rc == -ETIMEDOUT) { + apr_send_pkt_count++; + pr_err("%s:: send pkt timedout apr_send_pkt_count %d\n", + __func__, apr_send_pkt_count); + } + } + if (apr_send_pkt_count == apr_pkt_cnt_adsp_restart) { + pr_debug("%s:: schedule work for adsp loader restart cb\n", + __func__); + schedule_work(&apr_cb_work); + apr_send_pkt_count = 0; } spin_unlock_irqrestore(&svc->w_lock, flags); @@ -800,6 +819,19 @@ static void apr_reset_deregister(struct work_struct *work) kfree(apr_reset); } +static void state_notify_cb(struct work_struct *work) +{ + if (q6.state_notify_cb) + q6.state_notify_cb(APR_SUBSYS_UNKNOWN, q6.client_handle); +} + +void apr_register_adsp_state_cb(void *adsp_cb, void *client_handle) +{ + q6.state_notify_cb = adsp_cb; + q6.client_handle = client_handle; +} +EXPORT_SYMBOL(apr_register_adsp_state_cb); + /** * apr_start_rx_rt - Clients call to vote for thread * priority upgrade whenever needed. @@ -1212,7 +1244,7 @@ static int apr_probe(struct platform_device *pdev) __func__, ret); ret = 0; } - + INIT_WORK(&apr_cb_work, state_notify_cb); return apr_debug_init(); } From aea784377cd79de1568de0e7b9a23901ab33ee3c Mon Sep 17 00:00:00 2001 From: Sudheer Papothi Date: Wed, 10 Jun 2020 00:32:52 +0530 Subject: [PATCH 068/116] ASoC: wsa883x: Avoid temperature read during playback Avoid reading temperature during playback usecase. Change-Id: If471e19ea0ca5856d17f694ce084145d7132e365 Signed-off-by: Sudheer Papothi --- asoc/codecs/wsa883x/wsa883x.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/asoc/codecs/wsa883x/wsa883x.c b/asoc/codecs/wsa883x/wsa883x.c index 8b3d588130..95901e849a 100644 --- a/asoc/codecs/wsa883x/wsa883x.c +++ b/asoc/codecs/wsa883x/wsa883x.c @@ -599,9 +599,14 @@ static int wsa_get_temp(struct snd_kcontrol *kcontrol, { struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); int temp = 0; - wsa883x_get_temperature(component, &temp); + if (test_bit(SPKR_STATUS, &wsa883x->status_mask)) + temp = wsa883x->curr_temp; + else + wsa883x_get_temperature(component, &temp); + ucontrol->value.integer.value[0] = temp; return 0; From 4a38ad6bdc97d807a7bba391225e67ca5832c8b0 Mon Sep 17 00:00:00 2001 From: Vignesh Kulothungan Date: Mon, 8 Jun 2020 14:30:02 -0700 Subject: [PATCH 069/116] wcd938x: add dummy widgets to codec inputs/output With multicodec approach, codec widgets are added much earlier during sound card registration than aux codec approach. The connections between bolero and wcd938x are done via device tree at a later point. DAPM does power checkup for codec widgets before the codec-codec path is connected. This results in wcd938x dapm inputs/output to be considered as endpoints, which results in playback/record failure once after bootup. Hence, add dummy output/input widgets to wcd938x dapm inputs/output which are not codec endpoints. Change-Id: I5ab4839e9b76adba24c9254ae56dc784b4448af7 Signed-off-by: Vignesh Kulothungan --- asoc/codecs/wcd938x/wcd938x.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/asoc/codecs/wcd938x/wcd938x.c b/asoc/codecs/wcd938x/wcd938x.c index 2ed99ea0c5..2b4dd7d584 100644 --- a/asoc/codecs/wcd938x/wcd938x.c +++ b/asoc/codecs/wcd938x/wcd938x.c @@ -3051,9 +3051,17 @@ static const struct snd_soc_dapm_widget wcd938x_dapm_widgets[] = { SND_SOC_DAPM_INPUT("AMIC5"), SND_SOC_DAPM_INPUT("AMIC6"), SND_SOC_DAPM_INPUT("AMIC7"), + SND_SOC_DAPM_INPUT("IN1_HPHL"), SND_SOC_DAPM_INPUT("IN2_HPHR"), SND_SOC_DAPM_INPUT("IN3_AUX"), + /* + * These dummy widgets are null connected to WCD938x dapm input and + * output widgets which are not actual path endpoints. This ensures + * dapm doesnt set these dapm input and output widgets as endpoints. + */ + SND_SOC_DAPM_INPUT("WCD_TX_DUMMY"), + SND_SOC_DAPM_OUTPUT("WCD_RX_DUMMY"), /*tx widgets*/ SND_SOC_DAPM_ADC_E("ADC1", NULL, SND_SOC_NOPM, 0, 0, @@ -3290,6 +3298,7 @@ static const struct snd_soc_dapm_widget wcd938x_dapm_widgets[] = { static const struct snd_soc_dapm_route wcd938x_audio_map[] = { + {"WCD_TX_DUMMY", NULL, "WCD_TX_OUTPUT"}, {"WCD_TX_OUTPUT", NULL, "ADC1_MIXER"}, {"ADC1_MIXER", "Switch", "ADC1 REQ"}, {"ADC1 REQ", NULL, "ADC1"}, @@ -3344,6 +3353,7 @@ static const struct snd_soc_dapm_route wcd938x_audio_map[] = { {"WCD_TX_OUTPUT", NULL, "DMIC8_MIXER"}, {"DMIC8_MIXER", "Switch", "DMIC8"}, + {"IN1_HPHL", NULL, "WCD_RX_DUMMY"}, {"IN1_HPHL", NULL, "VDD_BUCK"}, {"IN1_HPHL", NULL, "CLS_H_PORT"}, {"RX1", NULL, "IN1_HPHL"}, @@ -3352,6 +3362,7 @@ static const struct snd_soc_dapm_route wcd938x_audio_map[] = { {"HPHL PGA", NULL, "HPHL_RDAC"}, {"HPHL", NULL, "HPHL PGA"}, + {"IN2_HPHR", NULL, "WCD_RX_DUMMY"}, {"IN2_HPHR", NULL, "VDD_BUCK"}, {"IN2_HPHR", NULL, "CLS_H_PORT"}, {"RX2", NULL, "IN2_HPHR"}, @@ -3360,6 +3371,7 @@ static const struct snd_soc_dapm_route wcd938x_audio_map[] = { {"HPHR PGA", NULL, "HPHR_RDAC"}, {"HPHR", NULL, "HPHR PGA"}, + {"IN3_AUX", NULL, "WCD_RX_DUMMY"}, {"IN3_AUX", NULL, "VDD_BUCK"}, {"IN3_AUX", NULL, "CLS_H_PORT"}, {"RX3", NULL, "IN3_AUX"}, @@ -3650,6 +3662,8 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component) 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, "WCD_TX_DUMMY"); + snd_soc_dapm_ignore_suspend(dapm, "WCD_RX_DUMMY"); snd_soc_dapm_sync(dapm); wcd_cls_h_init(&wcd938x->clsh_info); From 02d1c6dc1193a13c7de89f8c77335a1d5bb1a5a4 Mon Sep 17 00:00:00 2001 From: Sanjana B Date: Tue, 12 Nov 2019 23:09:27 +0530 Subject: [PATCH 070/116] asoc:support for DSD on MI2S interface Add support for DSD in MI2S interface and corresponding api updates from ADSP. Change-Id: I494205763fa429f95e43497ed5b8f91332f5a2a3 Signed-off-by: Sanjana B --- asoc/msm-compress-q6-v2.c | 2 +- asoc/msm-dai-q6-v2.c | 6 ++++-- asoc/msm-pcm-routing-v2.c | 8 ++++---- dsp/q6adm.c | 6 ++++-- dsp/q6asm.c | 4 ++++ include/dsp/apr_audio-v2.h | 19 ++++++++++++++++++- include/dsp/q6adm-v2.h | 3 ++- 7 files changed, 37 insertions(+), 11 deletions(-) diff --git a/asoc/msm-compress-q6-v2.c b/asoc/msm-compress-q6-v2.c index db75b180bd..589f6b98a6 100644 --- a/asoc/msm-compress-q6-v2.c +++ b/asoc/msm-compress-q6-v2.c @@ -1388,7 +1388,7 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream, dsd_cfg.dsd_data_rate = prtd->sample_rate; dsd_cfg.num_version = 0; dsd_cfg.is_bitwise_big_endian = 1; - dsd_cfg.dsd_channel_block_size = 1; + dsd_cfg.dsd_channel_block_size = 4; ret = q6asm_media_format_block_dsd(prtd->audio_client, &dsd_cfg, stream_id); if (ret < 0) diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c index 4e3f2581c2..11190dcfec 100644 --- a/asoc/msm-dai-q6-v2.c +++ b/asoc/msm-dai-q6-v2.c @@ -331,7 +331,8 @@ static const char *const mi2s_format[] = { "NA6", "NA7", "NA8", - "DSD_DOP_W_MARKER" + "DSD_DOP_W_MARKER", + "NATIVE_DSD_DATA" }; static const char *const mi2s_vi_feed_mono[] = { @@ -340,7 +341,7 @@ static const char *const mi2s_vi_feed_mono[] = { }; static const struct soc_enum mi2s_config_enum[] = { - SOC_ENUM_SINGLE_EXT(10, mi2s_format), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mi2s_format), mi2s_format), SOC_ENUM_SINGLE_EXT(2, mi2s_vi_feed_mono), }; @@ -5895,6 +5896,7 @@ static int msm_dai_q6_mi2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBM_CFS: mi2s_dai_data->rx_dai.mi2s_dai_data.port_config.i2s.ws_src = 1; mi2s_dai_data->tx_dai.mi2s_dai_data.port_config.i2s.ws_src = 1; break; diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c index 6867f32edb..139d404760 100644 --- a/asoc/msm-pcm-routing-v2.c +++ b/asoc/msm-pcm-routing-v2.c @@ -1739,7 +1739,7 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, adm_open(port_id, path_type, sample_rate, channels, topology, perf_mode, bit_width, app_type, acdb_dev_id, - session_type); + session_type, passthr_mode); if ((copp_idx < 0) || (copp_idx >= MAX_COPPS_PER_PORT)) { pr_err("%s:adm open failed coppid:%d\n", @@ -2091,7 +2091,7 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode, sample_rate, channels, topology, perf_mode, bits_per_sample, app_type, acdb_dev_id, - session_type); + session_type, passthr_mode); if ((copp_idx < 0) || (copp_idx >= MAX_COPPS_PER_PORT)) { pr_err("%s: adm open failed copp_idx:%d\n", @@ -2372,7 +2372,7 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set) sample_rate, channels, topology, fdai->perf_mode, bits_per_sample, app_type, acdb_dev_id, - session_type); + session_type, passthr_mode); if ((copp_idx < 0) || (copp_idx >= MAX_COPPS_PER_PORT)) { pr_err("%s: adm open failed\n", __func__); @@ -30147,7 +30147,7 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream) sample_rate, channels, topology, fdai->perf_mode, bits_per_sample, app_type, acdb_dev_id, - session_type); + session_type, fdai->passthr_mode); if ((copp_idx < 0) || (copp_idx >= MAX_COPPS_PER_PORT)) { pr_err("%s: adm open failed\n", __func__); diff --git a/dsp/q6adm.c b/dsp/q6adm.c index c49e0d08bf..cd01952a13 100644 --- a/dsp/q6adm.c +++ b/dsp/q6adm.c @@ -2991,7 +2991,7 @@ exit: */ int adm_open(int port_id, int path, int rate, int channel_mode, int topology, int perf_mode, uint16_t bit_width, int app_type, int acdb_id, - int session_type) + int session_type, uint32_t passthr_mode) { struct adm_cmd_device_open_v5 open; struct adm_cmd_device_open_v6 open_v6; @@ -3205,7 +3205,9 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology, } open_v8.topology_id = topology; - open_v8.reserved = 0; + open_v8.compressed_data_type = 0; + if (passthr_mode == COMPRESSED_PASSTHROUGH_DSD) + open_v8.compressed_data_type = 1; /* variable endpoint payload */ ep1_payload.dev_num_channel = channel_mode & 0x00FF; diff --git a/dsp/q6asm.c b/dsp/q6asm.c index aa0b4cb3ec..5e9b826ff7 100644 --- a/dsp/q6asm.c +++ b/dsp/q6asm.c @@ -3097,6 +3097,10 @@ int q6asm_open_read_compressed(struct audio_client *ac, uint32_t format, open.mode_flags = 0x1; open.frames_per_buf = 1; pr_debug("%s: Flag 1 IEC61937 output\n", __func__); + } else if (format == FORMAT_DSD) { + open.mode_flags = ASM_DSD_FORMAT_FLAG; + open.frames_per_buf = 1; + pr_debug("%s: Flag 2 DSD output\n", __func__); } else { open.mode_flags = 0; open.frames_per_buf = 1; diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h index c8ee7313bf..27be181b63 100644 --- a/include/dsp/apr_audio-v2.h +++ b/include/dsp/apr_audio-v2.h @@ -598,7 +598,7 @@ struct adm_cmd_device_open_v8 { * In all other use cases this should be set to 0xffff */ - u16 reserved; + u16 compressed_data_type; } __packed; /* @@ -2557,6 +2557,7 @@ struct afe_port_data_cmd_rt_proxy_port_read_v2 { #define AFE_GENERIC_COMPRESSED 0x8 #define AFE_LINEAR_PCM_DATA_PACKED_16BIT 0X6 #define AFE_DSD_DOP_W_MARKER_DATA 0x9 +#define AFE_DSD_DATA 0xA /* This param id is used to configure I2S interface */ #define AFE_PARAM_ID_I2S_CONFIG 0x0001020D @@ -8957,6 +8958,13 @@ struct asm_data_cmd_remove_silence { /* Shift value for the IEC 61937 to 61937 pass-through capture. */ #define ASM_SHIFT_IEC_61937_PASS_THROUGH_FLAG 0 +/* Bitmask for the DSD pass-through capture. */ +#define ASM_BIT_MASK_COMPRESSED_FORMAT_FLAG (0x00000003UL) + +/* Shift value for the DSD pass-through capture. */ +#define ASM_SHIFT_DSD_COMPRESSED_FORMAT_FLAG 0 + +#define ASM_DSD_FORMAT_FLAG 2 struct asm_stream_cmd_open_read_compressed { struct apr_hdr hdr; u32 mode_flags; @@ -8968,6 +8976,12 @@ struct asm_stream_cmd_open_read_compressed { * - Use #ASM_BIT_MASK_IEC_61937_PASS_THROUGH_FLAG to set the bitmask * and #ASM_SHIFT_IEC_61937_PASS_THROUGH_FLAG to set the shift value * for this bit. + * Supported values for bit 1: (DSD native pass-through mode) + * 0 -- non DSD operation + * 1 -- Pass-through transfer of the DSD format stream + * To set this bit, use #ASM_BIT_MASK_DSD_PASS_THROUGH_FLAG and + * use #ASM_SHIFT_DSD_PASS_THROUGH_FLAG to set the shift value for + * this bit * Supported values for bit 4: * - 0 -- Return data buffer contains all encoded frames only; it does * not contain frame metadata. @@ -8984,6 +8998,9 @@ struct asm_stream_cmd_open_read_compressed { * Supported values: should be greater than 0 for IEC to RAW compressed * unpack mode. * Value is don't care for IEC 61937 pass-through mode. + * @values + * - >0 -- For IEC 61937-to-RAW Compressed Unpack mode + * - 1 -- For IEC 61937 or DSD Pass-through mode */ } __packed; diff --git a/include/dsp/q6adm-v2.h b/include/dsp/q6adm-v2.h index efc1d38238..644855d0bb 100644 --- a/include/dsp/q6adm-v2.h +++ b/include/dsp/q6adm-v2.h @@ -119,7 +119,8 @@ int adm_pack_and_set_one_pp_param(int port_id, int copp_idx, int adm_open(int port, int path, int rate, int mode, int topology, int perf_mode, uint16_t bits_per_sample, - int app_type, int acdbdev_id, int session_type); + int app_type, int acdbdev_id, int session_type, + uint32_t pass_thr); int adm_map_rtac_block(struct rtac_cal_block_data *cal_block); From c702957fa224e16d9b03790abffd4df0e52caa88 Mon Sep 17 00:00:00 2001 From: Harshal Ahire Date: Fri, 27 Mar 2020 04:37:23 +0530 Subject: [PATCH 071/116] dsp: Add support to dynamically load and unload BT modules Add new APIs to enable dynamic load and unload of BT modules before afe_port_start and afe_close. Change-Id: I74da9a49aac754d4557c7206155de65cf9b6bdaf Signed-off-by: Harshal Ahire --- dsp/q6afe.c | 173 ++++++++++++++++++++++++++++++++++++- dsp/q6core.c | 137 ++++++++++++++++++++++++++++- include/dsp/apr_audio-v2.h | 10 +++ include/dsp/q6core.h | 121 ++++++++++++++++++++++++++ 4 files changed, 437 insertions(+), 4 deletions(-) diff --git a/dsp/q6afe.c b/dsp/q6afe.c index 2810fca7c7..ba84bd82ad 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -24,6 +24,21 @@ #define WAKELOCK_TIMEOUT 5000 #define AFE_CLK_TOKEN 1024 + +struct afe_avcs_payload_port_mapping { + u16 port_id; + struct avcs_load_unload_modules_payload *payload; +} __packed; + +enum { + ENCODER_CASE, + DECODER_CASE, + /* Add new use case here */ + MAX_ALLOWED_USE_CASES +}; + +static struct afe_avcs_payload_port_mapping *pm[MAX_ALLOWED_USE_CASES]; + enum { AFE_COMMON_RX_CAL = 0, AFE_COMMON_TX_CAL, @@ -240,6 +255,120 @@ static bool proxy_afe_started = false; #define SIZEOF_CFG_CMD(y) \ (sizeof(struct apr_hdr) + sizeof(u16) + (sizeof(struct y))) +static void q6afe_unload_avcs_modules(u16 port_id, int index) +{ + int ret = 0; + + ret = q6core_avcs_load_unload_modules(pm[index]->payload, + AVCS_UNLOAD_MODULES); + + if (ret < 0) + pr_err("%s: avcs module unload failed %d\n", __func__, ret); + + kfree(pm[index]->payload); + pm[index]->payload = NULL; + kfree(pm[index]); + pm[index] = NULL; +} + +static int q6afe_load_avcs_modules(int num_modules, u16 port_id, + uint32_t use_case, u32 format_id) +{ + int i = 0; + int32_t ret = 0; + size_t payload_size = 0, port_struct_size = 0; + struct afe_avcs_payload_port_mapping payload_map; + struct avcs_load_unload_modules_sec_payload sec_payload; + + if (num_modules <= 0) { + pr_err("%s: Invalid number of modules to load\n"); + return -EINVAL; + } + + for (i = 0; i < MAX_ALLOWED_USE_CASES; i++) { + if (pm[i] == NULL) { + port_struct_size = sizeof(payload_map); + pm[i] = kzalloc(port_struct_size, GFP_KERNEL); + if (!pm[i]) + return -ENOMEM; + + pm[i]->port_id = port_id; + payload_size = sizeof(uint32_t) + (sizeof(sec_payload) + * num_modules); + pm[i]->payload = kzalloc(payload_size, GFP_KERNEL); + if (!pm[i]->payload) { + kfree(pm[i]); + pm[i] = NULL; + return -ENOMEM; + } + + /* + * index 0 : packetizer/de-packetizer + * index 1 : encoder/decoder + */ + + pm[i]->payload->num_modules = num_modules; + + /* + * Remaining fields of payload + * are initialized to zero + */ + + if (use_case == ENCODER_CASE) { + pm[i]->payload->load_unload_info[0].module_type = + AMDB_MODULE_TYPE_PACKETIZER; + pm[i]->payload->load_unload_info[0].id1 = + AVS_MODULE_ID_PACKETIZER_COP; + pm[i]->payload->load_unload_info[1].module_type = + AMDB_MODULE_TYPE_ENCODER; + pm[i]->payload->load_unload_info[1].id1 = + format_id; + } else if (use_case == DECODER_CASE) { + pm[i]->payload->load_unload_info[0].module_type = + AMDB_MODULE_TYPE_DEPACKETIZER; + pm[i]->payload->load_unload_info[0].id1 = + AVS_MODULE_ID_DEPACKETIZER_COP_V1; + + if (format_id == ENC_CODEC_TYPE_LDAC) { + pm[i]->payload->load_unload_info[0].id1 = + AVS_MODULE_ID_DEPACKETIZER_COP; + goto load_unload; + } + + pm[i]->payload->load_unload_info[1].module_type = + AMDB_MODULE_TYPE_DECODER; + pm[i]->payload->load_unload_info[1].id1 = + format_id; + + } else { + pr_err("%s:load usecase %d not supported\n", + __func__, use_case); + ret = -EINVAL; + goto fail; + } + +load_unload: + ret = q6core_avcs_load_unload_modules(pm[i]->payload, + AVCS_LOAD_MODULES); + + if (ret < 0) { + pr_err("%s: load failed %d\n", __func__, ret); + goto fail; + } + return 0; + } + + } + pr_err("%s: Not enough ports available\n", __func__); + ret = -EINVAL; +fail: + kfree(pm[i]->payload); + pm[i]->payload = NULL; + kfree(pm[i]); + pm[i] = NULL; + return ret; +} + static int afe_get_cal_hw_delay(int32_t path, struct audio_cal_hw_delay_entry *entry); static int remap_cal_data(struct cal_block_data *cal_block, int cal_index); @@ -5512,8 +5641,21 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config, if ((codec_format != ASM_MEDIA_FMT_NONE) && (cfg_type == AFE_PARAM_ID_SLIMBUS_CONFIG)) { if (enc_cfg != NULL) { - pr_debug("%s: Found AFE encoder support for SLIMBUS format = %d\n", + pr_debug("%s: Found AFE encoder support for SLIMBUS format = %d\n", __func__, codec_format); + + if ((q6core_get_avcs_api_version_per_service( + APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= + AVCS_API_VERSION_V5)) { + ret = q6afe_load_avcs_modules(2, port_id, + ENCODER_CASE, codec_format); + if (ret < 0) { + pr_err("%s:encoder load for port 0x%x failed %d\n", + __func__, port_id, ret); + goto fail_cmd; + } + } + ret = q6afe_send_enc_config(port_id, enc_cfg, codec_format, *afe_config, afe_in_channels, @@ -5527,7 +5669,24 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config, } if (dec_cfg != NULL) { pr_debug("%s: Found AFE decoder support for SLIMBUS format = %d\n", - __func__, codec_format); + __func__, codec_format); + + if ((q6core_get_avcs_api_version_per_service( + APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= + AVCS_API_VERSION_V5)) { + /* LDAC doesn't require decoder */ + if (codec_format == ENC_CODEC_TYPE_LDAC) + ret = q6afe_load_avcs_modules(1, port_id, + DECODER_CASE, codec_format); + else + ret = q6afe_load_avcs_modules(2, port_id, + DECODER_CASE, codec_format); + if (ret < 0) { + pr_err("%s:decoder load for port 0x%x failed %d\n", + __func__, port_id, ret); + goto fail_cmd; + } + } ret = q6afe_send_dec_config(port_id, *afe_config, dec_cfg, codec_format, afe_in_channels, @@ -8333,6 +8492,7 @@ int afe_close(int port_id) struct afe_port_cmd_device_stop stop; enum afe_mad_type mad_type; int ret = 0; + u16 i; int index = 0; uint16_t port_index; @@ -8455,6 +8615,15 @@ int afe_close(int port_id) pr_err("%s: AFE close failed %d\n", __func__, ret); fail_cmd: + if ((q6core_get_avcs_api_version_per_service( + APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V5)) { + for (i = 0; i < MAX_ALLOWED_USE_CASES; i++) { + if (pm[i] && pm[i]->port_id == port_id) { + q6afe_unload_avcs_modules(port_id, i); + break; + } + } + } mutex_unlock(&this_afe.afe_cmd_lock); return ret; } diff --git a/dsp/q6core.c b/dsp/q6core.c index 15c00bdec7..6748b91951 100644 --- a/dsp/q6core.c +++ b/dsp/q6core.c @@ -61,9 +61,11 @@ struct q6core_str { wait_queue_head_t cmd_req_wait; wait_queue_head_t avcs_fwk_ver_req_wait; wait_queue_head_t lpass_npa_rsc_wait; + wait_queue_head_t avcs_module_load_unload_wait; u32 lpass_npa_rsc_rsp_rcvd; u32 bus_bw_resp_received; u32 mdf_map_resp_received; + u32 avcs_module_resp_received; enum cmd_flags { FLAG_NONE, FLAG_CMDRSP_LICENSE_RESULT @@ -87,6 +89,9 @@ struct q6core_str { static struct q6core_str q6core_lcl; +/* Global payload used for AVCS_CMD_RSP_MODULES command */ +static struct avcs_load_unload_modules_payload *rsp_payload; + struct generic_get_data_ { int valid; int size_in_ints; @@ -343,6 +348,29 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv) q6core_lcl.lpass_npa_rsc_rsp_rcvd = 1; wake_up(&q6core_lcl.lpass_npa_rsc_wait); break; + case AVCS_CMD_LOAD_MODULES: + pr_err("%s: Cmd = %s failed status[%s]\n", + __func__, "AVCS_CMD_LOAD__MODULES", + adsp_err_get_err_str(payload1[1])); + q6core_lcl.avcs_module_resp_received = 1; + q6core_lcl.adsp_status = -payload1[1]; + wake_up(&q6core_lcl.avcs_module_load_unload_wait); + break; + case AVCS_CMD_UNLOAD_MODULES: + if (payload1[1] == ADSP_EOK) { + pr_debug("%s: Cmd = %s success status[%s]\n", + __func__, "AVCS_CMD_UNLOAD_MODULES", + "ADSP_EOK"); + } else { + pr_err("%s: Cmd = %s failed status[%s]\n", + __func__, "AVCS_CMD_UNLOAD_MODULES", + adsp_err_get_err_str(payload1[1])); + q6core_lcl.adsp_status = -payload1[1]; + } + q6core_lcl.avcs_module_resp_received = 1; + wake_up(&q6core_lcl.avcs_module_load_unload_wait); + break; + default: pr_err("%s: Invalid cmd rsp[0x%x][0x%x] opcode %d\n", __func__, @@ -441,6 +469,13 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv) q6core_lcl.avcs_fwk_ver_resp_received = 1; wake_up(&q6core_lcl.avcs_fwk_ver_req_wait); break; + case AVCS_CMD_RSP_LOAD_MODULES: + pr_debug("%s: Received AVCS_CMD_RSP_LOAD_MODULES\n", + __func__); + memcpy(rsp_payload, data->payload, data->payload_size); + q6core_lcl.avcs_module_resp_received = 1; + wake_up(&q6core_lcl.avcs_module_load_unload_wait); + break; default: pr_err("%s: Message id from adsp core svc: 0x%x\n", __func__, data->opcode); @@ -821,7 +856,6 @@ int32_t core_get_license_status(uint32_t module_id) get_lvr_cmd.hdr.opcode = AVCS_CMD_GET_LICENSE_VALIDATION_RESULT; get_lvr_cmd.id = module_id; - ret = apr_send_pkt(q6core_lcl.core_handle_q, (uint32_t *) &get_lvr_cmd); if (ret < 0) { pr_err("%s: license_validation request failed, err %d\n", @@ -894,6 +928,105 @@ uint32_t core_set_dolby_manufacturer_id(int manufacturer_id) } EXPORT_SYMBOL(core_set_dolby_manufacturer_id); +int32_t q6core_avcs_load_unload_modules(struct avcs_load_unload_modules_payload + *payload, uint32_t preload_type) +{ + int ret = 0; + size_t packet_size = 0, payload_size = 0; + struct avcs_cmd_dynamic_modules *mod = NULL; + int num_modules; + + if (payload == NULL) { + pr_err("%s: payload is null\n"); + return -EINVAL; + } + + mutex_lock(&(q6core_lcl.cmd_lock)); + num_modules = payload->num_modules; + ocm_core_open(); + + if (q6core_lcl.core_handle_q == NULL) { + pr_err("%s: apr registration for CORE failed\n", __func__); + mutex_unlock(&(q6core_lcl.cmd_lock)); + return -ENODEV; + } + + payload_size = (sizeof(struct avcs_load_unload_modules_sec_payload) + * num_modules) + sizeof(uint32_t); + packet_size = sizeof(struct avcs_cmd_dynamic_modules) + + payload_size - sizeof(uint32_t); + mod = kzalloc(packet_size, GFP_KERNEL); + + if (!mod) { + mutex_unlock(&(q6core_lcl.cmd_lock)); + return -ENOMEM; + } + + rsp_payload = kzalloc(payload_size, GFP_KERNEL); + if (!rsp_payload) { + kfree(mod); + mutex_unlock(&(q6core_lcl.cmd_lock)); + return -ENOMEM; + } + + memcpy((uint8_t *)mod + sizeof(struct apr_hdr) + + sizeof(struct avcs_load_unload_modules_meminfo), + payload, payload_size); + + mod->hdr.hdr_field = + APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); + mod->hdr.pkt_size = packet_size; + mod->hdr.src_port = 0; + mod->hdr.dest_port = 0; + mod->hdr.token = 0; + mod->meminfo.data_payload_addr_lsw = 0; + mod->meminfo.data_payload_addr_msw = 0; + mod->meminfo.mem_map_handle = 0; + mod->meminfo.buffer_size = payload_size; + + if (preload_type == AVCS_LOAD_MODULES) + mod->hdr.opcode = AVCS_CMD_LOAD_MODULES; + else + mod->hdr.opcode = AVCS_CMD_UNLOAD_MODULES; + + q6core_lcl.avcs_module_resp_received = 0; + ret = apr_send_pkt(q6core_lcl.core_handle_q, + (uint32_t *)mod); + + if (ret < 0) { + pr_err("%s: modules load/unload failed ret = %d\n", + __func__, ret); + goto done; + } + + ret = wait_event_timeout(q6core_lcl.avcs_module_load_unload_wait, + (q6core_lcl.avcs_module_resp_received == 1), + msecs_to_jiffies(TIMEOUT_MS)); + if (!ret) { + pr_err("%s wait event timeout for avcs load/unload module\n", + __func__); + ret = -ETIMEDOUT; + goto done; + } + + if (q6core_lcl.adsp_status < 0) { + pr_err("%s: modules load/unload failed %d\n", __func__, + q6core_lcl.adsp_status); + ret = q6core_lcl.adsp_status; + goto done; + } else { + if (mod->hdr.opcode == AVCS_CMD_LOAD_MODULES) + memcpy(payload, rsp_payload, payload_size); + } +done: + kfree(mod); + kfree(rsp_payload); + mutex_unlock(&(q6core_lcl.cmd_lock)); + return ret; +} +EXPORT_SYMBOL(q6core_avcs_load_unload_modules); + int32_t q6core_load_unload_topo_modules(uint32_t topo_id, bool preload_type) { @@ -1871,7 +2004,6 @@ static int q6core_probe(struct platform_device *pdev) if (rc < 0) goto err; q6core_lcl.avs_state = avs_state; - rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); if (rc) { dev_err(&pdev->dev, "%s: failed to add child nodes, rc=%d\n", @@ -1926,6 +2058,7 @@ int __init core_init(void) init_waitqueue_head(&q6core_lcl.avcs_fwk_ver_req_wait); init_waitqueue_head(&q6core_lcl.mdf_map_resp_wait); init_waitqueue_head(&q6core_lcl.lpass_npa_rsc_wait); + init_waitqueue_head(&q6core_lcl.avcs_module_load_unload_wait); q6core_lcl.cmd_resp_received_flag = FLAG_NONE; mutex_init(&q6core_lcl.cmd_lock); mutex_init(&q6core_lcl.ver_lock); diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h index c8ee7313bf..c941272be2 100644 --- a/include/dsp/apr_audio-v2.h +++ b/include/dsp/apr_audio-v2.h @@ -4142,6 +4142,16 @@ struct afe_id_aptx_adaptive_enc_init #define AFE_MODULE_ID_DEPACKETIZER_COP 0x00013233 #define AFE_MODULE_ID_DEPACKETIZER_COP_V1 0x000132E9 +/* Macros for dynamic loading of modules by AVCS */ + +#define AVS_MODULE_ID_PACKETIZER_COP 0x0001322A + +#define AVS_MODULE_ID_PACKETIZER_COP_V1 0x000132E8 + +#define AVS_MODULE_ID_DEPACKETIZER_COP 0x00013233 + +#define AVS_MODULE_ID_DEPACKETIZER_COP_V1 0x000132E9 + /* * Depacketizer type parameter for the #AVS_MODULE_ID_DECODER module. * This parameter cannot be set runtime. diff --git a/include/dsp/q6core.h b/include/dsp/q6core.h index 45ecd4f79c..52722d6583 100644 --- a/include/dsp/q6core.h +++ b/include/dsp/q6core.h @@ -13,6 +13,7 @@ #define AVCS_CMD_ADSP_EVENT_GET_STATE 0x0001290C #define AVCS_CMDRSP_ADSP_EVENT_GET_STATE 0x0001290D #define AVCS_API_VERSION_V4 4 +#define AVCS_API_VERSION_V5 5 #define APRV2_IDS_SERVICE_ID_ADSP_CORE_V (0x3) bool q6core_is_adsp_ready(void); @@ -198,6 +199,126 @@ struct avcs_cmd_load_unload_topo_modules { uint32_t topology_id; } __packed; +#define AVCS_LOAD_MODULES 1 + +#define AVCS_UNLOAD_MODULES 0 + +#define AVCS_CMD_LOAD_MODULES 0x00012989 + +#define AVCS_CMD_UNLOAD_MODULES 0x0001298A + +#define AVCS_CMD_RSP_LOAD_MODULES 0x0001298B + +/* + * Module is generic, such as a preprocessor, + * postprocessor, or volume control + * module. + */ +#define AMDB_MODULE_TYPE_GENERIC 0 + +/** Module is a decoder. */ +#define AMDB_MODULE_TYPE_DECODER 1 + +/** Module is an encoder. */ +#define AMDB_MODULE_TYPE_ENCODER 2 + +/** Module is a converter. */ +#define AMDB_MODULE_TYPE_CONVERTER 3 + +/** Module is a packetizer. */ +#define AMDB_MODULE_TYPE_PACKETIZER 4 + +/** Module is a depacketizer. */ +#define AMDB_MODULE_TYPE_DEPACKETIZER 5 + + +struct avcs_load_unload_modules_sec_payload { + uint32_t module_type; + /* + * < Type of module. + + * @values + * - #AMDB_MODULE_TYPE_GENERIC + * - #AMDB_MODULE_TYPE_DECODER + * - #AMDB_MODULE_TYPE_ENCODER + * - #AMDB_MODULE_TYPE_CONVERTER + * - #AMDB_MODULE_TYPE_PACKETIZER + * - #AMDB_MODULE_TYPE_DEPACKETIZER + */ + + + uint32_t id1; + /* + * < One of the following types of IDs: + * - Format ID for the encoder, decoder, and packetizer module types + * - Module ID for the generic module type + * - Source format ID for the converter module type + */ + + uint32_t id2; + /* + * < Sink format ID for the converter module type. + * Zero for other module types + */ + + uint32_t handle_lsw; + /* < LSW of the Handle to the module loaded */ + + uint32_t handle_msw; + /* < MSW of the Handle to the module loaded. */ +} __packed; + +struct avcs_load_unload_modules_payload { + uint32_t num_modules; + /**< Number of modules being registered */ + + struct avcs_load_unload_modules_sec_payload load_unload_info[0]; + /* + * < Load/unload information for num_modules. + * It will be of type avcs_load_unload_info_t[num_modules] + */ +} __packed; + +struct avcs_load_unload_modules_meminfo { + uint32_t data_payload_addr_lsw; + /**< Lower 32 bits of the 64-bit data payload address. */ + + uint32_t data_payload_addr_msw; + /**< Upper 32 bits of the 64-bit data payload address. */ + + uint32_t mem_map_handle; + /* + * < Unique identifier for an address. The aDSP returns this memory map + * handle through the #AVCS_CMD_SHARED_MEM_MAP_REGIONS command. + + * @values @vertspace{-2} + * - NULL -- Parameter data payloads are within the message payload + * (in-band). + * - Non-NULL -- Parameter data payloads begin at the address specified + * in the data_payload_addr_lsw and data_payload_addr_msw fields + * (out-of-band). + + * The client can choose in-band or out-of-band + */ + + uint32_t buffer_size; + /* + * < Actual size (in bytes) of the valid data + * in the data payload address. + */ +} __packed; + +struct avcs_cmd_dynamic_modules { + struct apr_hdr hdr; + struct avcs_load_unload_modules_meminfo meminfo; + struct avcs_load_unload_modules_payload payload; +} __packed; + + +int32_t q6core_avcs_load_unload_modules(struct avcs_load_unload_modules_payload *payload, + uint32_t preload_type); + + /* This command allows a remote client(HLOS) creates a client to LPASS NPA * resource node. Currently, this command supports only the NPA Sleep resource * "/island/core/drivers" node ID. From e7ca214c29dc37f0175a22306f6ba4df04599d98 Mon Sep 17 00:00:00 2001 From: Harshal Ahire Date: Fri, 5 Jun 2020 14:15:21 +0530 Subject: [PATCH 072/116] dsp: Fix out of bound memory access. Fix out of bound memory access in q6afe_load_avcs_modules() for afe_avcs_payload_port_mapping structure. Change-Id: Ibe0e90e4fbedc2cf6a88abd9f3845643020a904a --- dsp/q6afe.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dsp/q6afe.c b/dsp/q6afe.c index ba84bd82ad..b00952708f 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -359,8 +359,12 @@ load_unload: } } - pr_err("%s: Not enough ports available\n", __func__); + ret = -EINVAL; + if (i == MAX_ALLOWED_USE_CASES) { + pr_err("%s: Not enough ports available\n", __func__); + return ret; + } fail: kfree(pm[i]->payload); pm[i]->payload = NULL; From d1a006c81e37aaf59fb80f57798f16d079ef7c8f Mon Sep 17 00:00:00 2001 From: Soumya Managoli Date: Fri, 13 Sep 2019 19:32:03 +0530 Subject: [PATCH 073/116] dsp: adsp-loader: Support ADSP restart recovery when stuck Changes to support silent restart of adsp subsys based on the apr callback when packet transfer to adsp timesout. Change-Id: Icedb76907a441792d1953a08dd071791e5b08706 Signed-off-by: Soumya Managoli --- dsp/adsp-loader.c | 80 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 58 insertions(+), 22 deletions(-) diff --git a/dsp/adsp-loader.c b/dsp/adsp-loader.c index e99d6a3c72..4be1c0d9c6 100644 --- a/dsp/adsp-loader.c +++ b/dsp/adsp-loader.c @@ -55,6 +55,51 @@ static struct work_struct adsp_ldr_work; static struct platform_device *adsp_private; static void adsp_loader_unload(struct platform_device *pdev); +static int adsp_restart_subsys(void) +{ + struct subsys_device *adsp_dev = NULL; + struct platform_device *pdev = adsp_private; + struct adsp_loader_private *priv = NULL; + int rc = -EINVAL; + + priv = platform_get_drvdata(pdev); + if (!priv) + return rc; + + adsp_dev = (struct subsys_device *)priv->pil_h; + if (!adsp_dev) + return rc; + + /* subsystem_restart_dev has worker queue to handle */ + rc = subsystem_restart_dev(adsp_dev); + if (rc) { + dev_err(&pdev->dev, "subsystem_restart_dev failed\n"); + return rc; + } + pr_debug("%s :: Restart Success %d\n", __func__, rc); + return rc; +} + +static void adsp_load_state_notify_cb(enum apr_subsys_state state, + void *phandle) +{ + struct platform_device *pdev = adsp_private; + struct adsp_loader_private *priv = NULL; + + priv = platform_get_drvdata(pdev); + if (!priv) + return; + if (phandle != adsp_private) { + pr_err("%s:callback is not for adsp-loader client\n", __func__); + return; + } + pr_debug("%s:: Received cb for ADSP restart\n", __func__); + if (state == APR_SUBSYS_UNKNOWN) + adsp_restart_subsys(); + else + pr_debug("%s:Ignore restart request for ADSP", __func__); +} + static void adsp_load_fw(struct work_struct *adsp_ldr_work) { struct platform_device *pdev = adsp_private; @@ -63,6 +108,7 @@ static void adsp_load_fw(struct work_struct *adsp_ldr_work) int rc = 0; u32 adsp_state; const char *img_name; + void *padsp_restart_cb = &adsp_load_state_notify_cb; if (!pdev) { dev_err(&pdev->dev, "%s: Platform device null\n", __func__); @@ -119,7 +165,7 @@ static void adsp_load_fw(struct work_struct *adsp_ldr_work) } dev_dbg(&pdev->dev, "%s: Q6/MDSP image is loaded\n", __func__); - return; + goto success; } load_adsp: @@ -153,10 +199,13 @@ load_adsp: } dev_dbg(&pdev->dev, "%s: Q6/ADSP image is loaded\n", __func__); - return; + apr_register_adsp_state_cb(padsp_restart_cb, adsp_private); + goto success; } fail: dev_err(&pdev->dev, "%s: Q6 image loading failed\n", __func__); +success: + return; } static void adsp_loader_do(struct platform_device *pdev) @@ -170,37 +219,24 @@ static ssize_t adsp_ssr_store(struct kobject *kobj, size_t count) { int ssr_command = 0; - struct subsys_device *adsp_dev = NULL; struct platform_device *pdev = adsp_private; struct adsp_loader_private *priv = NULL; - int rc; + int rc = -EINVAL; dev_dbg(&pdev->dev, "%s: going to call adsp ssr\n ", __func__); + priv = platform_get_drvdata(pdev); + if (!priv) + return rc; + if (kstrtoint(buf, 10, &ssr_command) < 0) return -EINVAL; if (ssr_command != SSR_RESET_CMD) return -EINVAL; - priv = platform_get_drvdata(pdev); - if (!priv) - return -EINVAL; - - adsp_dev = (struct subsys_device *)priv->pil_h; - if (!adsp_dev) - return -EINVAL; - - dev_err(&pdev->dev, "requesting for ADSP restart\n"); - - /* subsystem_restart_dev has worker queue to handle */ - rc = subsystem_restart_dev(adsp_dev); - if (rc) { - dev_err(&pdev->dev, "subsystem_restart_dev failed\n"); - return rc; - } - - dev_dbg(&pdev->dev, "ADSP restarted\n"); + adsp_restart_subsys(); + dev_dbg(&pdev->dev, "%s :: ADSP restarted\n", __func__); return count; } From 5638ecaf5d5755eb6d777cdeb42ba1a0423a41b1 Mon Sep 17 00:00:00 2001 From: Avinash Chandra Date: Mon, 27 Apr 2020 19:23:49 +0530 Subject: [PATCH 074/116] dsp: q6adm: Update the proper param_hdr for offset For Source Tracking adm_get_param, param_hdr (struct param_hdr_v3) size being sent was different as param_hdr(struct param_hdr_v1)size used for offset of virtual memory to copy the param data in out-band case get_param. Change-Id: I01dd4f704cc5b6994f1203a0e28199a6936cba7f Signed-off-by: Avinash Chandra --- dsp/q6adm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dsp/q6adm.c b/dsp/q6adm.c index c49e0d08bf..ab667fb747 100644 --- a/dsp/q6adm.c +++ b/dsp/q6adm.c @@ -5358,7 +5358,7 @@ int adm_get_source_tracking(int port_id, int copp_idx, */ param_hdr.param_size = sizeof(struct adm_param_fluence_sourcetracking_t) + - sizeof(union param_hdrs); + sizeof(struct param_hdr_v3); /* * Retrieving parameters out of band, so no need to provide a buffer for @@ -5387,7 +5387,7 @@ int adm_get_source_tracking(int port_id, int copp_idx, source_tracking_params = (struct adm_param_fluence_sourcetracking_t *) (this_adm.sourceTrackingData.memmap.kvaddr + - sizeof(struct param_hdr_v1)); + sizeof(struct param_hdr_v3)); for (i = 0; i < MAX_SECTORS; i++) { sourceTrackingData->vad[i] = source_tracking_params->vad[i]; pr_debug("%s: vad[%d] = %d\n", From 6bacce4b9ce2e8d271f5e569af00ea99af6fc787 Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Mon, 27 Apr 2020 13:02:03 +0530 Subject: [PATCH 075/116] audio-kernel: Add void param in function definition Add void param in function definition to avoid compilation errors when strict prototypes flag is defined. Change-Id: I4515c730139fff18638805cd70db24ec1886f127 --- dsp/digital-cdc-rsc-mgr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dsp/digital-cdc-rsc-mgr.c b/dsp/digital-cdc-rsc-mgr.c index 4206523ea8..be5d5cad79 100644 --- a/dsp/digital-cdc-rsc-mgr.c +++ b/dsp/digital-cdc-rsc-mgr.c @@ -87,13 +87,13 @@ void digital_cdc_rsc_mgr_hw_vote_reset(struct clk* vote_handle) } EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_reset); -void digital_cdc_rsc_mgr_init() +void digital_cdc_rsc_mgr_init(void) { mutex_init(&hw_vote_lock); is_init_done = true; } -void digital_cdc_rsc_mgr_exit() +void digital_cdc_rsc_mgr_exit(void) { mutex_destroy(&hw_vote_lock); is_init_done = false; From f1a7ecab50058d43ce207ec17384f437ee77373a Mon Sep 17 00:00:00 2001 From: Deru Wang Date: Tue, 19 May 2020 20:55:01 +0800 Subject: [PATCH 076/116] asoc: flags is used but is uninitialized initialize flags to resolve static code analysis issue Change-Id: I23e74050e69db6894b02cbc00605861abdce0e56 Signed-off-by: Deru Wang --- asoc/msm-lsm-client.c | 2 +- asoc/msm-pcm-afe-v2.c | 4 ++-- asoc/msm-pcm-dtmf-v2.c | 6 +++--- asoc/msm-pcm-host-voice-v2.c | 10 +++++----- asoc/msm-pcm-voip-v2.c | 10 +++++----- asoc/msm-qti-pp-config.c | 4 ++-- ipc/apr_tal_rpmsg.c | 6 +++--- 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/asoc/msm-lsm-client.c b/asoc/msm-lsm-client.c index 017323161d..1265d5c997 100644 --- a/asoc/msm-lsm-client.c +++ b/asoc/msm-lsm-client.c @@ -1252,7 +1252,7 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, unsigned int cmd, void *arg) { struct snd_soc_pcm_runtime *rtd; - unsigned long flags; + unsigned long flags = 0; int ret; struct snd_lsm_sound_model_v2 snd_model_v2; struct snd_lsm_session_data session_data; diff --git a/asoc/msm-pcm-afe-v2.c b/asoc/msm-pcm-afe-v2.c index 5fe3b34a79..db21565120 100644 --- a/asoc/msm-pcm-afe-v2.c +++ b/asoc/msm-pcm-afe-v2.c @@ -161,7 +161,7 @@ static void pcm_afe_process_tx_pkt(uint32_t opcode, void *priv) { struct pcm_afe_info *prtd = priv; - unsigned long dsp_flags; + unsigned long dsp_flags = 0; struct snd_pcm_substream *substream = NULL; struct snd_pcm_runtime *runtime = NULL; uint16_t event; @@ -255,7 +255,7 @@ static void pcm_afe_process_rx_pkt(uint32_t opcode, void *priv) { struct pcm_afe_info *prtd = priv; - unsigned long dsp_flags; + unsigned long dsp_flags = 0; struct snd_pcm_substream *substream = NULL; struct snd_pcm_runtime *runtime = NULL; struct snd_soc_pcm_runtime *rtd = NULL; diff --git a/asoc/msm-pcm-dtmf-v2.c b/asoc/msm-pcm-dtmf-v2.c index 3dc7a26a54..cda75b8fd9 100644 --- a/asoc/msm-pcm-dtmf-v2.c +++ b/asoc/msm-pcm-dtmf-v2.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2013-2014, 2017-2019 The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2014, 2017-2020 The Linux Foundation. All rights reserved. */ #include @@ -224,7 +224,7 @@ static int msm_pcm_capture_copy(struct snd_pcm_substream *substream, struct dtmf_buf_node *buf_node = NULL; struct snd_pcm_runtime *runtime = substream->runtime; struct dtmf_drv_info *prtd = runtime->private_data; - unsigned long dsp_flags; + unsigned long dsp_flags = 0; ret = wait_event_interruptible_timeout(prtd->out_wait, (!list_empty(&prtd->out_queue)), @@ -324,7 +324,7 @@ static int msm_pcm_close(struct snd_pcm_substream *substream) struct snd_pcm_substream *c_substream; struct snd_pcm_runtime *runtime = substream->runtime; struct dtmf_drv_info *prtd = runtime->private_data; - unsigned long dsp_flags; + unsigned long dsp_flags = 0; pr_debug("%s() DTMF\n", __func__); diff --git a/asoc/msm-pcm-host-voice-v2.c b/asoc/msm-pcm-host-voice-v2.c index 41c3982dd3..a5d44edbaf 100644 --- a/asoc/msm-pcm-host-voice-v2.c +++ b/asoc/msm-pcm-host-voice-v2.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2020, The Linux Foundation. All rights reserved. */ #include @@ -678,7 +678,7 @@ static void hpcm_copy_capture_data_to_queue(struct dai_data *dai_data, uint32_t len) { struct hpcm_buf_node *buf_node = NULL; - unsigned long dsp_flags; + unsigned long dsp_flags = 0; if (dai_data->substream == NULL) return; @@ -987,7 +987,7 @@ static int msm_pcm_close(struct snd_pcm_substream *substream) struct snd_dma_buffer *dma_buf; struct snd_pcm_runtime *runtime; struct hpcm_drv *prtd; - unsigned long dsp_flags; + unsigned long dsp_flags = 0; struct dai_data *dai_data = NULL; struct tap_point *tp = NULL; struct tappnt_mxr_data *tmd = NULL; @@ -1077,7 +1077,7 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a, struct snd_pcm_runtime *runtime = substream->runtime; struct hpcm_drv *prtd = runtime->private_data; struct dai_data *dai_data = hpcm_get_dai_data(substream->pcm->id, prtd); - unsigned long dsp_flags; + unsigned long dsp_flags = 0; if (dai_data == NULL) { pr_err("%s, dai_data is null\n", __func__); @@ -1129,7 +1129,7 @@ static int msm_pcm_capture_copy(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; struct hpcm_drv *prtd = runtime->private_data; struct dai_data *dai_data = hpcm_get_dai_data(substream->pcm->id, prtd); - unsigned long dsp_flags; + unsigned long dsp_flags = 0; if (dai_data == NULL) { pr_err("%s, dai_data is null\n", __func__); diff --git a/asoc/msm-pcm-voip-v2.c b/asoc/msm-pcm-voip-v2.c index e2ad13b4cc..f635a2b63f 100644 --- a/asoc/msm-pcm-voip-v2.c +++ b/asoc/msm-pcm-voip-v2.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. */ #include @@ -508,7 +508,7 @@ static void voip_process_dl_pkt(uint8_t *voc_pkt, void *private_data) { struct voip_buf_node *buf_node = NULL; struct voip_drv_info *prtd = private_data; - unsigned long dsp_flags; + unsigned long dsp_flags = 0; uint32_t rate_type; uint32_t frame_rate; u32 pkt_len; @@ -778,7 +778,7 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a, struct voip_buf_node *buf_node = NULL; struct snd_pcm_runtime *runtime = substream->runtime; struct voip_drv_info *prtd = runtime->private_data; - unsigned long dsp_flags; + unsigned long dsp_flags = 0; pr_debug("%s: fbytes=%lu\n", __func__, fbytes); @@ -852,7 +852,7 @@ static int msm_pcm_capture_copy(struct snd_pcm_substream *substream, struct voip_buf_node *buf_node = NULL; struct snd_pcm_runtime *runtime = substream->runtime; struct voip_drv_info *prtd = runtime->private_data; - unsigned long dsp_flags; + unsigned long dsp_flags = 0; int size; pr_debug("%s: fbytes = %lu\n", __func__, fbytes); @@ -941,7 +941,7 @@ static int msm_pcm_close(struct snd_pcm_substream *substream) struct snd_pcm_substream *p_substream, *c_substream; struct snd_pcm_runtime *runtime; struct voip_drv_info *prtd; - unsigned long dsp_flags; + unsigned long dsp_flags = 0; if (substream == NULL) { pr_err("substream is NULL\n"); diff --git a/asoc/msm-qti-pp-config.c b/asoc/msm-qti-pp-config.c index 8a5ebce6ec..e26e421fe3 100644 --- a/asoc/msm-qti-pp-config.c +++ b/asoc/msm-qti-pp-config.c @@ -1200,7 +1200,7 @@ int msm_adsp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd, int ctl_len = 0, ret = 0; struct dsp_stream_callback_list *new_event; struct dsp_stream_callback_list *oldest_event; - unsigned long spin_flags; + unsigned long spin_flags = 0; struct dsp_stream_callback_prtd *kctl_prtd = NULL; struct msm_adsp_event_data *event_data = NULL; const char *mixer_ctl_name = DSP_STREAM_CALLBACK; @@ -1309,7 +1309,7 @@ int msm_adsp_stream_callback_get(struct snd_kcontrol *kcontrol, { uint32_t payload_size = 0; struct dsp_stream_callback_list *oldest_event; - unsigned long spin_flags; + unsigned long spin_flags = 0; struct dsp_stream_callback_prtd *kctl_prtd = NULL; int ret = 0; diff --git a/ipc/apr_tal_rpmsg.c b/ipc/apr_tal_rpmsg.c index c8830d1c25..bb894e2f4b 100644 --- a/ipc/apr_tal_rpmsg.c +++ b/ipc/apr_tal_rpmsg.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. */ #include @@ -36,7 +36,7 @@ int apr_tal_write(struct apr_svc_ch_dev *apr_ch, void *data, struct apr_pkt_priv *pkt_priv, int len) { int rc = 0, retries = 0; - unsigned long flags; + unsigned long flags = 0; struct rpmsg_device *rpdev = NULL; if (!apr_ch || len > APR_MAX_BUF || @@ -186,7 +186,7 @@ static int apr_tal_rpmsg_callback(struct rpmsg_device *rpdev, void *data, int len, void *priv, u32 addr) { struct apr_svc_ch_dev *apr_ch = dev_get_drvdata(&rpdev->dev); - unsigned long flags; + unsigned long flags = 0; if (!apr_ch || !data) { pr_err("%s: Invalid apr_ch or ptr\n", __func__); From b3fa5a0dc519745d9a4a4b33cfa320660c66ccd5 Mon Sep 17 00:00:00 2001 From: Sudheer Papothi Date: Wed, 3 Jun 2020 11:46:05 +0530 Subject: [PATCH 077/116] asoc: codecs: retry for soundwire slave enumeration Retry for soundwire slave enumeration during bootup before EPROBE_DEFER to avoid soundcard enumeration failures. Change-Id: I083ec76fc84a2b367f93a2dc166a1419a75ff8b4 Signed-off-by: Sudheer Papothi --- asoc/codecs/swr-dmic.c | 16 ++++++++++++---- asoc/codecs/swr-haptics.c | 7 ++++++- asoc/codecs/wcd938x/wcd938x-slave.c | 13 +++++++++++-- asoc/codecs/wcd938x/wcd938x.c | 15 ++++++++------- 4 files changed, 37 insertions(+), 14 deletions(-) diff --git a/asoc/codecs/swr-dmic.c b/asoc/codecs/swr-dmic.c index c9d69f293a..20ae002d42 100644 --- a/asoc/codecs/swr-dmic.c +++ b/asoc/codecs/swr-dmic.c @@ -30,6 +30,8 @@ #include "wcd938x/wcd938x.h" #include "swr-dmic.h" +#define NUM_ATTEMPTS 5 + static int swr_master_channel_map[] = { ZERO, SWRM_TX1_CH1, @@ -450,6 +452,7 @@ static int swr_dmic_probe(struct swr_device *pdev) const char *swr_dmic_name_prefix_of = NULL; const char *swr_dmic_codec_name_of = NULL; struct snd_soc_component *component = NULL; + int num_retry = NUM_ATTEMPTS; swr_dmic = devm_kzalloc(&pdev->dev, sizeof(struct swr_dmic_priv), GFP_KERNEL); @@ -512,10 +515,15 @@ static int swr_dmic_probe(struct swr_device *pdev) * as per HW requirement. */ usleep_range(5000, 5010); - ret = swr_get_logical_dev_num(pdev, pdev->addr, &swr_devnum); + do { + /* Add delay for soundwire enumeration */ + usleep_range(100, 110); + ret = swr_get_logical_dev_num(pdev, pdev->addr, &swr_devnum); + } while (ret && --num_retry); + if (ret) { - dev_dbg(&pdev->dev, - "%s get devnum %d for dev addr %lx failed\n", + dev_info(&pdev->dev, + "%s get devnum %d for dev addr %llx failed\n", __func__, swr_devnum, pdev->addr); ret = -EPROBE_DEFER; goto err; @@ -670,7 +678,7 @@ done: static int swr_dmic_reset(struct swr_device *pdev) { struct swr_dmic_priv *swr_dmic; - u8 retry = 5; + u8 retry = NUM_ATTEMPTS; u8 devnum = 0; swr_dmic = swr_get_dev_data(pdev); diff --git a/asoc/codecs/swr-haptics.c b/asoc/codecs/swr-haptics.c index 4b22562912..4e1a576930 100644 --- a/asoc/codecs/swr-haptics.c +++ b/asoc/codecs/swr-haptics.c @@ -314,6 +314,7 @@ static int swr_haptics_probe(struct swr_device *sdev) struct swr_haptics_dev *swr_hap; int rc; u8 devnum; + int retry = 5; swr_hap = devm_kzalloc(&sdev->dev, sizeof(struct swr_haptics_dev), GFP_KERNEL); @@ -346,8 +347,12 @@ static int swr_haptics_probe(struct swr_device *sdev) __func__, rc); goto clean; } + do { + /* Add delay for soundwire enumeration */ + usleep_range(500, 510); + rc = swr_get_logical_dev_num(sdev, sdev->addr, &devnum); + } while (rc && --retry); - rc = swr_get_logical_dev_num(sdev, sdev->addr, &devnum); if (rc) { dev_err(swr_hap->dev, "%s: failed to get devnum for swr-haptics, rc=%d\n", __func__, rc); diff --git a/asoc/codecs/wcd938x/wcd938x-slave.c b/asoc/codecs/wcd938x/wcd938x-slave.c index 75cc7839c6..9ea5bac282 100644 --- a/asoc/codecs/wcd938x/wcd938x-slave.c +++ b/asoc/codecs/wcd938x/wcd938x-slave.c @@ -24,6 +24,8 @@ #define SWR_SLV_MAX_DEVICES 2 #endif /* CONFIG_DEBUG_FS */ +#define SWR_MAX_RETRY 5 + struct wcd938x_slave_priv { struct swr_device *swr_slave; #ifdef CONFIG_DEBUG_FS @@ -278,17 +280,24 @@ static int wcd938x_slave_bind(struct device *dev, int ret = 0; uint8_t devnum = 0; struct swr_device *pdev = to_swr_device(dev); + int retry = SWR_MAX_RETRY; if (!pdev) { pr_err("%s: invalid swr device handle\n", __func__); return -EINVAL; } - ret = swr_get_logical_dev_num(pdev, pdev->addr, &devnum); + do { + /* Add delay for soundwire enumeration */ + usleep_range(100, 110); + ret = swr_get_logical_dev_num(pdev, pdev->addr, &devnum); + } while (ret && --retry); + if (ret) { dev_dbg(&pdev->dev, - "%s get devnum %d for dev addr %lx failed\n", + "%s get devnum %d for dev addr %llx failed\n", __func__, devnum, pdev->addr); + ret = -EPROBE_DEFER; return ret; } pdev->dev_num = devnum; diff --git a/asoc/codecs/wcd938x/wcd938x.c b/asoc/codecs/wcd938x/wcd938x.c index ee225c3c56..d2701d1370 100644 --- a/asoc/codecs/wcd938x/wcd938x.c +++ b/asoc/codecs/wcd938x/wcd938x.c @@ -1992,15 +1992,16 @@ static int wcd938x_get_logical_addr(struct swr_device *swr_dev) int num_retry = NUM_ATTEMPTS; do { + /* retry after 1ms */ + usleep_range(1000, 1010); ret = swr_get_logical_dev_num(swr_dev, swr_dev->addr, &devnum); - if (ret) { - dev_err(&swr_dev->dev, - "%s get devnum %d for dev addr %lx failed\n", - __func__, devnum, swr_dev->addr); - /* retry after 1ms */ - usleep_range(1000, 1010); - } } while (ret && --num_retry); + + if (ret) + dev_err(&swr_dev->dev, + "%s get devnum %d for dev addr %llx failed\n", + __func__, devnum, swr_dev->addr); + swr_dev->dev_num = devnum; return 0; } From 91572c78904404f62e5748fbf0be806a6f34a54a Mon Sep 17 00:00:00 2001 From: Meng Wang Date: Mon, 1 Jun 2020 11:42:01 +0800 Subject: [PATCH 078/116] asoc: lahaina: add stub fe for wsa capture When WSA is disabled, WSA related widgets is not registered and it causes soundcard registeration fail. Add stub fe for wsa capture to avoid soundcard registeration failure. Change-Id: I282d843d02544aaf2f2b646aba4fca731fc6f47e Signed-off-by: Meng Wang --- asoc/lahaina.c | 58 ++++++++++++++++++++++++++++++++++++---------- asoc/msm_dailink.h | 5 ++++ 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/asoc/lahaina.c b/asoc/lahaina.c index b50581987b..2dd1624797 100644 --- a/asoc/lahaina.c +++ b/asoc/lahaina.c @@ -5999,6 +5999,19 @@ static struct snd_soc_dai_link msm_bolero_fe_dai_links[] = { }, }; +static struct snd_soc_dai_link msm_bolero_fe_stub_dai_links[] = { + {/* hw:x,33 */ + .name = LPASS_BE_WSA_CDC_DMA_TX_0, + .stream_name = "WSA CDC DMA0 Capture", + .id = MSM_BACKEND_DAI_WSA_CDC_DMA_TX_0, + .be_hw_params_fixup = msm_be_hw_params_fixup, + .ignore_suspend = 1, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ops = &msm_cdc_dma_be_ops, + SND_SOC_DAILINK_REG(wsa_cdcdma0_capture_stub), + }, +}; + static struct snd_soc_dai_link msm_common_misc_fe_dai_links[] = { {/* hw:x,34 */ .name = MSM_DAILINK_NAME(ASM Loopback), @@ -6847,6 +6860,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_rx1), + .init = &msm_int_audrx_init, }, { .name = LPASS_BE_RX_CDC_DMA_RX_2, @@ -7238,6 +7252,7 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) u32 val = 0; u32 wcn_btfm_intf = 0; const struct of_device_id *match; + u32 wsa_max_devs = 0; match = of_match_node(lahaina_asoc_machine_of_match, dev->of_node); if (!match) { @@ -7254,12 +7269,27 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) sizeof(msm_common_dai_links)); total_links += ARRAY_SIZE(msm_common_dai_links); - memcpy(msm_lahaina_dai_links + total_links, - msm_bolero_fe_dai_links, - sizeof(msm_bolero_fe_dai_links)); - total_links += - ARRAY_SIZE(msm_bolero_fe_dai_links); - + rc = of_property_read_u32(dev->of_node, + "qcom,wsa-max-devs", &wsa_max_devs); + if (rc) { + dev_info(dev, + "%s: wsa-max-devs property missing in DT %s, ret = %d\n", + __func__, dev->of_node->full_name, rc); + wsa_max_devs = 0; + } + if (!wsa_max_devs) { + memcpy(msm_lahaina_dai_links + total_links, + msm_bolero_fe_stub_dai_links, + sizeof(msm_bolero_fe_stub_dai_links)); + total_links += + ARRAY_SIZE(msm_bolero_fe_stub_dai_links); + } else { + memcpy(msm_lahaina_dai_links + total_links, + msm_bolero_fe_dai_links, + sizeof(msm_bolero_fe_dai_links)); + total_links += + ARRAY_SIZE(msm_bolero_fe_dai_links); + } memcpy(msm_lahaina_dai_links + total_links, msm_common_misc_fe_dai_links, sizeof(msm_common_misc_fe_dai_links)); @@ -7276,12 +7306,13 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) total_links += ARRAY_SIZE(msm_rx_tx_cdc_dma_be_dai_links); - memcpy(msm_lahaina_dai_links + total_links, - msm_wsa_cdc_dma_be_dai_links, - sizeof(msm_wsa_cdc_dma_be_dai_links)); - total_links += - ARRAY_SIZE(msm_wsa_cdc_dma_be_dai_links); - + if (wsa_max_devs) { + memcpy(msm_lahaina_dai_links + total_links, + msm_wsa_cdc_dma_be_dai_links, + sizeof(msm_wsa_cdc_dma_be_dai_links)); + total_links += + ARRAY_SIZE(msm_wsa_cdc_dma_be_dai_links); + } memcpy(msm_lahaina_dai_links + total_links, msm_va_cdc_dma_be_dai_links, sizeof(msm_va_cdc_dma_be_dai_links)); @@ -7410,6 +7441,9 @@ static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd) snd_soc_card_get_drvdata(rtd->card); int ret = 0; + if (codec_reg_done) { + return 0; + } if (pdata->wsa_max_devs > 0) { component = snd_soc_rtdcom_lookup(rtd, "wsa-codec.1"); if (!component) { diff --git a/asoc/msm_dailink.h b/asoc/msm_dailink.h index bfc56d41da..113a14e479 100644 --- a/asoc/msm_dailink.h +++ b/asoc/msm_dailink.h @@ -176,6 +176,11 @@ SND_SOC_DAILINK_DEFS(wsa_cdcdma0_capture, DAILINK_COMP_ARRAY(COMP_CODEC("bolero_codec", "wsa_macro_vifeedback")), DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-hostless"))); +SND_SOC_DAILINK_DEFS(wsa_cdcdma0_capture_stub, + DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-cdc-dma-dev.45057")), + DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-hostless"))); + SND_SOC_DAILINK_DEFS(multimedia6, DAILINK_COMP_ARRAY(COMP_CPU("MultiMedia6")), DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")), From d8005c664b1c66785adc8bd7b65df00a3ec4b661 Mon Sep 17 00:00:00 2001 From: Zhou Song Date: Mon, 15 Jun 2020 20:46:17 +0800 Subject: [PATCH 079/116] dsp: don't reset rx ec ref channel after adm open Remove reset of rx ec ref channel for adm after using, if the channel value is not changed, user space won't set it to driver again, then causing adm opening failed. --- dsp/q6adm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/dsp/q6adm.c b/dsp/q6adm.c index c49e0d08bf..44f739428b 100644 --- a/dsp/q6adm.c +++ b/dsp/q6adm.c @@ -3278,7 +3278,6 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology, if ((this_adm.num_ec_ref_rx_chans != 0) && (path != ADM_PATH_PLAYBACK) && (open_v8.endpoint_id_2 != 0xFFFF)) { - this_adm.num_ec_ref_rx_chans = 0; memcpy(adm_params + sizeof(open_v8) + ep1_payload_size, (void *)&ep2_payload, From f0c7f88868772ce336b2f56c18bfb54f745edd55 Mon Sep 17 00:00:00 2001 From: Vatsal Bucha Date: Mon, 8 Jun 2020 10:41:56 +0530 Subject: [PATCH 080/116] soc: swr-mstr: Fix headset detection during sva clk switch Headset insertion/removal is not detected sometime due to fifo read failure due to swr underflow. This is because if headset sva is enabled, during clk switch swr force stop happens and if mbhc has already taken pm vote for 3sec further mbhc reads/writes will fail. If swr is in clk switch mode then call swrm runtime_resume during reads/writes to resolve issue. Change-Id: I0d65869bd1c645bbf7ded9c0265f8d7de0dc624b Signed-off-by: Vatsal Bucha --- soc/swr-mstr-ctrl.c | 32 ++++++++++++++++++++++++-------- soc/swr-mstr-ctrl.h | 1 + 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index b9913e4480..69cce11809 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -121,7 +121,7 @@ static bool swrm_lock_sleep(struct swr_mstr_ctrl *swrm); static void swrm_unlock_sleep(struct swr_mstr_ctrl *swrm); static u32 swr_master_read(struct swr_mstr_ctrl *swrm, unsigned int reg_addr); static void swr_master_write(struct swr_mstr_ctrl *swrm, u16 reg_addr, u32 val); - +static int swrm_runtime_resume(struct device *dev); static u8 swrm_get_clk_div(int mclk_freq, int bus_clk_freq) { @@ -901,6 +901,8 @@ static int swrm_read(struct swr_master *master, u8 dev_num, u16 reg_addr, mutex_unlock(&swrm->devlock); pm_runtime_get_sync(swrm->dev); + if (swrm->req_clk_switch) + swrm_runtime_resume(swrm->dev); ret = swrm_cmd_fifo_rd_cmd(swrm, &val, dev_num, 0, reg_addr, len); if (!ret) @@ -934,6 +936,8 @@ static int swrm_write(struct swr_master *master, u8 dev_num, u16 reg_addr, mutex_unlock(&swrm->devlock); pm_runtime_get_sync(swrm->dev); + if (swrm->req_clk_switch) + swrm_runtime_resume(swrm->dev); ret = swrm_cmd_fifo_wr_cmd(swrm, reg_val, dev_num, 0, reg_addr); pm_runtime_put_autosuspend(swrm->dev); @@ -1925,16 +1929,22 @@ handle_irq: swrm->intr_mask); break; case SWRM_INTERRUPT_STATUS_RD_FIFO_OVERFLOW: - dev_dbg(swrm->dev, "%s: SWR read FIFO overflow\n", - __func__); + value = swr_master_read(swrm, SWRM_CMD_FIFO_STATUS); + dev_err(swrm->dev, + "%s: SWR read FIFO overflow fifo status\n", + __func__, value); break; case SWRM_INTERRUPT_STATUS_RD_FIFO_UNDERFLOW: - dev_dbg(swrm->dev, "%s: SWR read FIFO underflow\n", - __func__); + value = swr_master_read(swrm, SWRM_CMD_FIFO_STATUS); + dev_err(swrm->dev, + "%s: SWR read FIFO underflow fifo status\n", + __func__, value); break; case SWRM_INTERRUPT_STATUS_WR_CMD_FIFO_OVERFLOW: - dev_dbg(swrm->dev, "%s: SWR write FIFO overflow\n", - __func__); + value = swr_master_read(swrm, SWRM_CMD_FIFO_STATUS); + dev_err(swrm->dev, + "%s: SWR write FIFO overflow fifo status\n", + __func__, value); swr_master_write(swrm, SWRM_CMD_FIFO_CMD, 0x1); break; case SWRM_INTERRUPT_STATUS_CMD_ERROR: @@ -2928,6 +2938,8 @@ exit: else pm_runtime_set_autosuspend_delay(&pdev->dev, auto_suspend_timer); + if (swrm->req_clk_switch) + swrm->req_clk_switch = false; mutex_unlock(&swrm->reslock); trace_printk("%s: pm_runtime: resume done, state:%d\n", @@ -3217,8 +3229,12 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data) } mutex_lock(&swrm->mlock); if (swrm->clk_src != *(int *)data) { - if (swrm->state == SWR_MSTR_UP) + if (swrm->state == SWR_MSTR_UP) { + swrm->req_clk_switch = true; swrm_device_suspend(&pdev->dev); + if (swrm->state == SWR_MSTR_UP) + swrm->req_clk_switch = false; + } swrm->clk_src = *(int *)data; } mutex_unlock(&swrm->mlock); diff --git a/soc/swr-mstr-ctrl.h b/soc/swr-mstr-ctrl.h index f6d5a186d6..bc4ae4b045 100644 --- a/soc/swr-mstr-ctrl.h +++ b/soc/swr-mstr-ctrl.h @@ -179,6 +179,7 @@ struct swr_mstr_ctrl { bool dev_up; bool ipc_wakeup_triggered; bool aud_core_err; + bool req_clk_switch; struct pm_qos_request pm_qos_req; enum swrm_pm_state pm_state; wait_queue_head_t pm_wq; From 32482607bc0896f844cf8e73de91f3c301c58916 Mon Sep 17 00:00:00 2001 From: Xiaoyu Ye Date: Mon, 1 Jun 2020 09:12:34 -0700 Subject: [PATCH 081/116] asoc: convert pr_info to pr_debug to reduce kernel logs To reduce kernel logs, change unnecessary pr_info to pr_debug in audio drivers. Change-Id: I32e2e31b87bf0486352c99c04d455f3fdd2677da Signed-off-by: Xiaoyu Ye --- asoc/msm-pcm-host-voice-v2.c | 4 ++-- asoc/msm-qti-pp-config.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/asoc/msm-pcm-host-voice-v2.c b/asoc/msm-pcm-host-voice-v2.c index 41c3982dd3..f40c9ab0db 100644 --- a/asoc/msm-pcm-host-voice-v2.c +++ b/asoc/msm-pcm-host-voice-v2.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2020, The Linux Foundation. All rights reserved. */ #include @@ -1455,7 +1455,7 @@ static struct snd_soc_component_driver msm_soc_component = { static int msm_pcm_probe(struct platform_device *pdev) { - pr_info("%s: dev name %s\n", __func__, dev_name(&pdev->dev)); + pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev)); return snd_soc_register_component(&pdev->dev, &msm_soc_component, NULL, 0); } diff --git a/asoc/msm-qti-pp-config.c b/asoc/msm-qti-pp-config.c index 8a5ebce6ec..b3898c6445 100644 --- a/asoc/msm-qti-pp-config.c +++ b/asoc/msm-qti-pp-config.c @@ -1269,11 +1269,11 @@ int msm_adsp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd, spin_lock_irqsave(&kctl_prtd->prtd_spin_lock, spin_flags); while (kctl_prtd->event_count >= DSP_STREAM_CALLBACK_QUEUE_SIZE) { - pr_info("%s: queue of size %d is full. delete oldest one.\n", + pr_debug("%s: queue of size %d is full. delete oldest one.\n", __func__, DSP_STREAM_CALLBACK_QUEUE_SIZE); oldest_event = list_first_entry(&kctl_prtd->event_queue, struct dsp_stream_callback_list, list); - pr_info("%s: event deleted: type %d length %d\n", + pr_debug("%s: event deleted: type %d length %d\n", __func__, oldest_event->event.event_type, oldest_event->event.payload_len); list_del(&oldest_event->list); From 298c198b3700a768db9d9c7a19d474293cb3a570 Mon Sep 17 00:00:00 2001 From: Vatsal Bucha Date: Thu, 4 Jun 2020 13:12:48 +0530 Subject: [PATCH 082/116] ASoC: wcd937x: Add mixer ctl for TX CH power level Add mixer ctl for tx channel power level. CRs-Fixed: 2703598 Change-Id: Iecb0dfe491afaface4c4dd1995aa13c7efd9df82 Signed-off-by: Vatsal Bucha --- asoc/codecs/wcd937x/internal.h | 2 ++ asoc/codecs/wcd937x/wcd937x.c | 57 +++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/asoc/codecs/wcd937x/internal.h b/asoc/codecs/wcd937x/internal.h index 77a93b91d3..e7cf9eb75d 100644 --- a/asoc/codecs/wcd937x/internal.h +++ b/asoc/codecs/wcd937x/internal.h @@ -17,6 +17,7 @@ #define WCD_VOUT_CTL_TO_MICB(v) (1000 + v * 50) #define MAX_PORT 8 #define MAX_CH_PER_PORT 8 +#define MAX_TX_PWR_CH 2 #define WCD937X_MAX_SLAVE_PORT_TYPES 10 extern struct regmap_config wcd937x_regmap_config; @@ -91,6 +92,7 @@ struct wcd937x_priv { struct mutex ana_tx_clk_lock; u8 tx_master_ch_map[WCD937X_MAX_SLAVE_CH_TYPES]; bool usbc_hs_status; + u32 tx_ch_pwr[MAX_TX_PWR_CH]; }; struct wcd937x_micbias_setting { diff --git a/asoc/codecs/wcd937x/wcd937x.c b/asoc/codecs/wcd937x/wcd937x.c index 2e3d27df0f..daf7a3d7a2 100644 --- a/asoc/codecs/wcd937x/wcd937x.c +++ b/asoc/codecs/wcd937x/wcd937x.c @@ -1777,6 +1777,48 @@ static int wcd937x_rx_hph_mode_put(struct snd_kcontrol *kcontrol, return 0; } +static int wcd937x_tx_ch_pwr_level_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); + + if (strnstr(kcontrol->id.name, "CH1", sizeof(kcontrol->id.name))) + ucontrol->value.integer.value[0] = wcd937x->tx_ch_pwr[0]; + else if (strnstr(kcontrol->id.name, "CH3", sizeof(kcontrol->id.name))) + ucontrol->value.integer.value[0] = wcd937x->tx_ch_pwr[1]; + + return 0; +} + +static int wcd937x_tx_ch_pwr_level_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); + u32 pwr_level = ucontrol->value.enumerated.item[0]; + + dev_dbg(component->dev, "%s: tx ch pwr_level: %d\n", + __func__, pwr_level); + + if (strnstr(kcontrol->id.name, "CH1", + sizeof(kcontrol->id.name))) { + snd_soc_component_update_bits(component, + WCD937X_ANA_TX_CH1, 0x60, + pwr_level << 0x5); + wcd937x->tx_ch_pwr[0] = pwr_level; + } else if (strnstr(kcontrol->id.name, "CH3", + sizeof(kcontrol->id.name))) { + snd_soc_component_update_bits(component, + WCD937X_ANA_TX_CH3, 0x60, + pwr_level << 0x5); + wcd937x->tx_ch_pwr[1] = pwr_level; + } + return 0; +} + static int wcd937x_ear_pa_gain_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -2001,6 +2043,10 @@ static int wcd937x_tx_master_ch_put(struct snd_kcontrol *kcontrol, return 0; } +static const char * const wcd937x_tx_ch_pwr_level_text[] = { + "L0", "L1", "L2", "L3", +}; + static const char * const wcd937x_ear_pa_gain_text[] = { "G_6_DB", "G_4P5_DB", "G_3_DB", "G_1P5_DB", "G_0_DB", "G_M1P5_DB", "G_M3_DB", "G_M4P5_DB", @@ -2016,6 +2062,9 @@ static const struct soc_enum rx_hph_mode_mux_enum = static SOC_ENUM_SINGLE_EXT_DECL(wcd937x_ear_pa_gain_enum, wcd937x_ear_pa_gain_text); +static SOC_ENUM_SINGLE_EXT_DECL(wcd937x_tx_ch_pwr_level_enum, + wcd937x_tx_ch_pwr_level_text); + static const struct snd_kcontrol_new wcd937x_snd_controls[] = { SOC_ENUM_EXT("EAR PA GAIN", wcd937x_ear_pa_gain_enum, wcd937x_ear_pa_gain_get, wcd937x_ear_pa_gain_put), @@ -2054,6 +2103,10 @@ static const struct snd_kcontrol_new wcd937x_snd_controls[] = { wcd937x_tx_master_ch_get, wcd937x_tx_master_ch_put), SOC_ENUM_EXT("DMIC5 ChMap", tx_master_ch_enum, wcd937x_tx_master_ch_get, wcd937x_tx_master_ch_put), + SOC_ENUM_EXT("TX CH1 PWR", wcd937x_tx_ch_pwr_level_enum, + wcd937x_tx_ch_pwr_level_get, wcd937x_tx_ch_pwr_level_put), + SOC_ENUM_EXT("TX CH3 PWR", wcd937x_tx_ch_pwr_level_enum, + wcd937x_tx_ch_pwr_level_get, wcd937x_tx_ch_pwr_level_put), }; static const struct snd_kcontrol_new adc1_switch[] = { @@ -3114,7 +3167,9 @@ static int wcd937x_bind(struct device *dev) dev_err(dev, "%s: bad micbias pdata\n", __func__); goto err_irq; } - + /* default L1 power setting */ + wcd937x->tx_ch_pwr[0] = 1; + wcd937x->tx_ch_pwr[1] = 1; mutex_init(&wcd937x->micb_lock); mutex_init(&wcd937x->ana_tx_clk_lock); /* Request for watchdog interrupt */ From 42e9d9cebdba90a1334d02f47d3e0b2ff08a5a62 Mon Sep 17 00:00:00 2001 From: Sanjana B Date: Fri, 6 Dec 2019 17:16:36 +0530 Subject: [PATCH 083/116] asoc: update block size for dsd input Update dsd channel block size from codec options. Change-Id: I54011f1092eb8a687d1d4899928daad6746c7aed Signed-off-by: Sanjana B --- asoc/msm-compress-q6-v2.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/asoc/msm-compress-q6-v2.c b/asoc/msm-compress-q6-v2.c index 589f6b98a6..c2d8271f10 100644 --- a/asoc/msm-compress-q6-v2.c +++ b/asoc/msm-compress-q6-v2.c @@ -81,6 +81,8 @@ const DECLARE_TLV_DB_LINEAR(msm_compr_vol_gain, 0, #define COMPRESSED_PERF_MODE_FLAG 0 #endif +#define DSD_BLOCK_SIZE_4 4 + struct msm_compr_gapless_state { bool set_next_stream_id; int32_t stream_opened[MAX_NUMBER_OF_STREAMS]; @@ -1388,7 +1390,12 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream, dsd_cfg.dsd_data_rate = prtd->sample_rate; dsd_cfg.num_version = 0; dsd_cfg.is_bitwise_big_endian = 1; - dsd_cfg.dsd_channel_block_size = 4; + dsd_cfg.dsd_channel_block_size = 1; + + if (codec_options->dsd_dec.blk_size == DSD_BLOCK_SIZE_4) + dsd_cfg.dsd_channel_block_size = + codec_options->dsd_dec.blk_size; + ret = q6asm_media_format_block_dsd(prtd->audio_client, &dsd_cfg, stream_id); if (ret < 0) From 204e309fad75c8474a80a01408948de72b4def32 Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Thu, 16 Apr 2020 11:16:12 +0530 Subject: [PATCH 084/116] soc: pinctrl-lpi: Add 100msec before resetting hw votes Add 100msec delay before resetting hw vote counts in SSR up sequence in order to ensure AVS is up when votes are requested. Change-Id: I0f46c60555f6bf833b1cac76f86a54afdcb78ba0 Signed-off-by: Aditya Bavanari --- soc/pinctrl-lpi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/soc/pinctrl-lpi.c b/soc/pinctrl-lpi.c index b9699c6a58..03d9112880 100644 --- a/soc/pinctrl-lpi.c +++ b/soc/pinctrl-lpi.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -489,6 +490,8 @@ static int lpi_notifier_service_cb(struct notifier_block *this, /* Reset HW votes after SSR */ if (!lpi_dev_up) { + /* Add 100ms sleep to ensure AVS is up after SSR */ + msleep(100); if (state->lpass_core_hw_vote) digital_cdc_rsc_mgr_hw_vote_reset( state->lpass_core_hw_vote); From db5ae827eb98fb42affe1c75fe2cd1cf8bd355f5 Mon Sep 17 00:00:00 2001 From: Xiaoyu Ye Date: Mon, 1 Jun 2020 08:39:16 -0700 Subject: [PATCH 085/116] dsp: convert pr_info to pr_debug to reduce kernel logs To reduce kernel logs, change unnecessary pr_info to pr_debug in audio drivers. Change-Id: I6df096b50c81b2fe7e315e7f278708bc9d46a050 Signed-off-by: Xiaoyu Ye --- dsp/q6afe.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/dsp/q6afe.c b/dsp/q6afe.c index a6ac17ce8b..a4137ae17d 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -2871,7 +2871,7 @@ static struct cal_block_data *afe_find_cal_topo_id_by_port( /* Skip cal_block if it is already marked stale */ if (cal_utils_is_cal_stale(cal_block)) continue; - pr_info("%s: port id: 0x%x, dev_acdb_id: %d\n", __func__, + pr_debug("%s: port id: 0x%x, dev_acdb_id: %d\n", __func__, port_id, this_afe.dev_acdb_id[afe_port_index]); path = ((afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX)?(TX_DEVICE):(RX_DEVICE)); @@ -2881,14 +2881,14 @@ static struct cal_block_data *afe_find_cal_topo_id_by_port( if (this_afe.dev_acdb_id[afe_port_index] > 0) { if (afe_top->acdb_id == this_afe.dev_acdb_id[afe_port_index]) { - pr_info("%s: top_id:%x acdb_id:%d afe_port_id:0x%x\n", + pr_debug("%s: top_id:%x acdb_id:%d afe_port_id:0x%x\n", __func__, afe_top->topology, afe_top->acdb_id, q6audio_get_port_id(port_id)); return cal_block; } } else { - pr_info("%s: top_id:%x acdb_id:%d afe_port:0x%x\n", + pr_debug("%s: top_id:%x acdb_id:%d afe_port:0x%x\n", __func__, afe_top->topology, afe_top->acdb_id, q6audio_get_port_id(port_id)); return cal_block; @@ -3002,7 +3002,7 @@ static int afe_send_port_topology_id(u16 port_id) this_afe.topology[index] = topology_id; rtac_update_afe_topology(port_id); done: - pr_info("%s: AFE set topology id 0x%x enable for port 0x%x ret %d\n", + pr_debug("%s: AFE set topology id 0x%x enable for port 0x%x ret %d\n", __func__, topology_id, port_id, ret); return ret; @@ -3319,7 +3319,7 @@ static struct cal_block_data *afe_find_cal(int cal_index, int port_id) struct audio_cal_info_afe *afe_cal_info = NULL; int afe_port_index = q6audio_get_port_index(port_id); - pr_info("%s: cal_index %d port_id 0x%x port_index %d\n", __func__, + pr_debug("%s: cal_index %d port_id 0x%x port_index %d\n", __func__, cal_index, port_id, afe_port_index); if (afe_port_index < 0) { pr_err("%s: Error getting AFE port index %d\n", @@ -3331,7 +3331,7 @@ static struct cal_block_data *afe_find_cal(int cal_index, int port_id) &this_afe.cal_data[cal_index]->cal_blocks) { cal_block = list_entry(ptr, struct cal_block_data, list); afe_cal_info = cal_block->cal_info; - pr_info("%s: acdb_id %d dev_acdb_id %d sample_rate %d afe_sample_rates %d\n", + pr_debug("%s: acdb_id %d dev_acdb_id %d sample_rate %d afe_sample_rates %d\n", __func__, afe_cal_info->acdb_id, this_afe.dev_acdb_id[afe_port_index], afe_cal_info->sample_rate, @@ -3340,7 +3340,7 @@ static struct cal_block_data *afe_find_cal(int cal_index, int port_id) this_afe.dev_acdb_id[afe_port_index]) && (afe_cal_info->sample_rate == this_afe.afe_sample_rates[afe_port_index])) { - pr_info("%s: cal block is a match, size is %zd\n", + pr_debug("%s: cal block is a match, size is %zd\n", __func__, cal_block->cal_data.size); goto exit; } @@ -3358,7 +3358,7 @@ static int send_afe_cal_type(int cal_index, int port_id) int ret; int afe_port_index = q6audio_get_port_index(port_id); - pr_info("%s: cal_index is %d\n", __func__, cal_index); + pr_debug("%s: cal_index is %d\n", __func__, cal_index); if (this_afe.cal_data[cal_index] == NULL) { pr_warn("%s: cal_index %d not allocated!\n", @@ -3375,7 +3375,7 @@ static int send_afe_cal_type(int cal_index, int port_id) } mutex_lock(&this_afe.cal_data[cal_index]->lock); - pr_info("%s: dev_acdb_id[%d] is %d\n", + pr_debug("%s: dev_acdb_id[%d] is %d\n", __func__, afe_port_index, this_afe.dev_acdb_id[afe_port_index]); if (((cal_index == AFE_COMMON_RX_CAL) || @@ -3393,7 +3393,7 @@ static int send_afe_cal_type(int cal_index, int port_id) goto unlock; } - pr_info("%s: Sending cal_index cal %d\n", __func__, cal_index); + pr_debug("%s: Sending cal_index cal %d\n", __func__, cal_index); ret = remap_cal_data(cal_block, cal_index); if (ret) { @@ -5400,7 +5400,7 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config, port_id = VIRTUAL_ID_TO_PORTID(port_id); } - pr_info("%s: port id: 0x%x\n", __func__, port_id); + pr_debug("%s: port id: 0x%x\n", __func__, port_id); index = q6audio_get_port_index(port_id); if (index < 0 || index >= AFE_MAX_PORTS) { @@ -8520,7 +8520,7 @@ int afe_close(int port_id) ret = -EINVAL; goto fail_cmd; } - pr_info("%s: port_id = 0x%x\n", __func__, port_id); + pr_debug("%s: port_id = 0x%x\n", __func__, port_id); if ((port_id == RT_PROXY_DAI_001_RX) || (port_id == RT_PROXY_DAI_002_TX)) { pr_debug("%s: before decrementing pcm_afe_instance %d\n", From 269c76b335cdb049a7cf7a9a452584ebe06046c8 Mon Sep 17 00:00:00 2001 From: Vatsal Bucha Date: Thu, 18 Jun 2020 08:57:27 +0530 Subject: [PATCH 086/116] soc: swr-mstr: Fix KW issue in swrm_remove Irq pointer is first freed and then used in irq_set_trigger_type and set wakeup capable. This may lead to Null pointer dereference if irq is NULL. Free irq after using it. Change-Id: I86339e9995922cc8111f12593eb781226bb07a2a Signed-off-by: Vatsal Bucha --- soc/swr-mstr-ctrl.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index b9913e4480..63c25c8252 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -2727,13 +2727,13 @@ err_mstr_fail: swrm->reg_irq(swrm->handle, swr_mstr_interrupt, swrm, SWR_IRQ_FREE); } else if (swrm->irq) { - free_irq(swrm->irq, swrm); irqd_set_trigger_type( irq_get_irq_data(swrm->irq), IRQ_TYPE_NONE); + if (swrm->swr_irq_wakeup_capable) + irq_set_irq_wake(swrm->irq, 0); + free_irq(swrm->irq, swrm); } - if (swrm->swr_irq_wakeup_capable) - irq_set_irq_wake(swrm->irq, 0); err_irq_fail: mutex_destroy(&swrm->irq_lock); mutex_destroy(&swrm->mlock); @@ -2757,15 +2757,15 @@ static int swrm_remove(struct platform_device *pdev) swrm->reg_irq(swrm->handle, swr_mstr_interrupt, swrm, SWR_IRQ_FREE); } else if (swrm->irq) { - free_irq(swrm->irq, swrm); irqd_set_trigger_type( irq_get_irq_data(swrm->irq), IRQ_TYPE_NONE); + if (swrm->swr_irq_wakeup_capable) + irq_set_irq_wake(swrm->irq, 0); + free_irq(swrm->irq, swrm); } else if (swrm->wake_irq > 0) { free_irq(swrm->wake_irq, swrm); } - if (swrm->swr_irq_wakeup_capable) - irq_set_irq_wake(swrm->irq, 0); cancel_work_sync(&swrm->wakeup_work); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); From 75f229237a51f8c0de070cbcc560f383de176215 Mon Sep 17 00:00:00 2001 From: Vignesh Kulothungan Date: Wed, 20 May 2020 15:50:14 -0700 Subject: [PATCH 087/116] ASoC: codecs: handle device disconnect during SSR During SSR, when usbc analog device is disconnected, the respective disconnect interrupt is not handled and hence userspace is not notified. When ADSP recovers, fsa driver sends a disconnect notification. So handle device disconnect and notify jack/userspace through this notification. Change-Id: Ic695c2267c9289f9528d50202938ec09f634de8a Signed-off-by: Vignesh Kulothungan --- asoc/codecs/wcd-mbhc-v2.c | 19 +++++++++++++++++++ asoc/codecs/wcd938x/wcd938x.c | 2 ++ include/asoc/wcd-mbhc-v2.h | 1 + 3 files changed, 22 insertions(+) diff --git a/asoc/codecs/wcd-mbhc-v2.c b/asoc/codecs/wcd-mbhc-v2.c index 17ce0ef790..08d7678b7d 100644 --- a/asoc/codecs/wcd-mbhc-v2.c +++ b/asoc/codecs/wcd-mbhc-v2.c @@ -1621,6 +1621,8 @@ static int wcd_mbhc_set_keycode(struct wcd_mbhc *mbhc) static int wcd_mbhc_usbc_ana_event_handler(struct notifier_block *nb, unsigned long mode, void *ptr) { + unsigned int l_det_en = 0; + unsigned int detection_type = 0; struct wcd_mbhc *mbhc = container_of(nb, struct wcd_mbhc, fsa_nb); if (!mbhc) @@ -1633,6 +1635,23 @@ static int wcd_mbhc_usbc_ana_event_handler(struct notifier_block *nb, mbhc->mbhc_cb->clk_setup(mbhc->component, true); /* insertion detected, enable L_DET_EN */ WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_L_DET_EN, 1); + } else { + WCD_MBHC_REG_READ(WCD_MBHC_MECH_DETECTION_TYPE, detection_type); + WCD_MBHC_REG_READ(WCD_MBHC_L_DET_EN, l_det_en); + /* If both l_det_en and detection type are set, it means device was + * unplugged during SSR and detection interrupt was not handled. + * So trigger device disconnect */ + if (detection_type && l_det_en) { + /* Set the detection type appropriately */ + WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MECH_DETECTION_TYPE, + !detection_type); + /* Set current plug type to the state before SSR */ + mbhc->current_plug = mbhc->plug_before_ssr; + + wcd_mbhc_swch_irq_handler(mbhc); + mbhc->mbhc_cb->lock_sleep(mbhc, false); + mbhc->plug_before_ssr = MBHC_PLUG_TYPE_NONE; + } } return 0; } diff --git a/asoc/codecs/wcd938x/wcd938x.c b/asoc/codecs/wcd938x/wcd938x.c index 22bea4cb65..6a044bd6f1 100644 --- a/asoc/codecs/wcd938x/wcd938x.c +++ b/asoc/codecs/wcd938x/wcd938x.c @@ -2061,6 +2061,8 @@ static int wcd938x_event_notify(struct notifier_block *block, case BOLERO_WCD_EVT_SSR_DOWN: wcd938x->dev_up = false; wcd938x->mbhc->wcd_mbhc.deinit_in_progress = true; + wcd938x->mbhc->wcd_mbhc.plug_before_ssr = + wcd938x->mbhc->wcd_mbhc.current_plug; mbhc = &wcd938x->mbhc->wcd_mbhc; wcd938x->usbc_hs_status = get_usbc_hs_status(component, mbhc->mbhc_cfg); diff --git a/include/asoc/wcd-mbhc-v2.h b/include/asoc/wcd-mbhc-v2.h index 1c351f8012..e9dd2ae165 100644 --- a/include/asoc/wcd-mbhc-v2.h +++ b/include/asoc/wcd-mbhc-v2.h @@ -551,6 +551,7 @@ struct wcd_mbhc { wait_queue_head_t wait_btn_press; bool is_btn_press; u8 current_plug; + u8 plug_before_ssr; bool in_swch_irq_handler; bool hphl_swh; /*track HPHL switch NC / NO */ bool gnd_swh; /*track GND switch NC / NO */ From ba1abdc2021e6c2066862af4e39b49d78994d84e Mon Sep 17 00:00:00 2001 From: Xiaoyu Ye Date: Wed, 17 Jun 2020 19:42:54 -0700 Subject: [PATCH 088/116] lsm: fix potential Null pointer dereference Pointer "ptr_info_v2" in function msm_lsm_ioctl may be dereferenced when it's Null. Add a local structure "info_v2" to avoid this potential Null pointer dereference. Change-Id: Iabf5c3b1017b4a44b924c80e4d8e6f2c3d2d5f57 Signed-off-by: Xiaoyu Ye --- asoc/msm-lsm-client.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/asoc/msm-lsm-client.c b/asoc/msm-lsm-client.c index 1265d5c997..5965355eac 100644 --- a/asoc/msm-lsm-client.c +++ b/asoc/msm-lsm-client.c @@ -2404,10 +2404,13 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, case SNDRV_LSM_SET_MODULE_PARAMS_V2: { struct snd_lsm_module_params p_data; struct lsm_params_info *temp_ptr_info = NULL; + struct lsm_params_info_v2 info_v2; struct lsm_params_info_v2 *ptr_info_v2 = NULL, *temp_ptr_info_v2 = NULL; size_t p_size = 0, count; u8 *params; + memset(&info_v2, 0, sizeof(info_v2)); + if (!prtd->lsm_client->use_topology) { dev_err(rtd->dev, "%s: %s: not supported if not using topology\n", @@ -2472,16 +2475,17 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, for (count = 0; count < p_data.num_params; count++) { if (cmd == SNDRV_LSM_SET_MODULE_PARAMS) { /* convert to V2 param info struct from legacy param info */ - ptr_info_v2->module_id = temp_ptr_info->module_id; - ptr_info_v2->param_id = temp_ptr_info->param_id; - ptr_info_v2->param_size = temp_ptr_info->param_size; - ptr_info_v2->param_data = temp_ptr_info->param_data; - ptr_info_v2->param_type = temp_ptr_info->param_type; + info_v2.module_id = temp_ptr_info->module_id; + info_v2.param_id = temp_ptr_info->param_id; + info_v2.param_size = temp_ptr_info->param_size; + info_v2.param_data = temp_ptr_info->param_data; + info_v2.param_type = temp_ptr_info->param_type; - ptr_info_v2->instance_id = INSTANCE_ID_0; - ptr_info_v2->stage_idx = LSM_STAGE_INDEX_FIRST; - ptr_info_v2->model_id = 0; + info_v2.instance_id = INSTANCE_ID_0; + info_v2.stage_idx = LSM_STAGE_INDEX_FIRST; + info_v2.model_id = 0; + ptr_info_v2 = &info_v2; temp_ptr_info++; } else { if (LSM_REG_MULTI_SND_MODEL != temp_ptr_info_v2->param_type || From 4d71a88b6941d0ee6d22e0bcf3bd7f6b00051035 Mon Sep 17 00:00:00 2001 From: Guodong Hu Date: Thu, 21 May 2020 13:07:12 +0800 Subject: [PATCH 089/116] dsp: redefine audio_notifier_init to silence PDR error CONFIG_MSM_QDSP6_PDR is not enabled on Auto targets. Change-Id: If7ac374bbe88635eeb328593b4d3a9f01a716c5c Signed-off-by: Guodong Hu --- dsp/audio_notifier.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/dsp/audio_notifier.c b/dsp/audio_notifier.c index 888d162d43..9f2d4d5c10 100644 --- a/dsp/audio_notifier.c +++ b/dsp/audio_notifier.c @@ -606,6 +606,7 @@ static int __init audio_notifier_late_init(void) return 0; } +#ifdef CONFIG_MSM_QDSP6_PDR static int __init audio_notifier_init(void) { int ret; @@ -624,6 +625,17 @@ static int __init audio_notifier_init(void) return 0; } +#else +static int __init audio_notifier_init(void) +{ + audio_notifier_subsys_init(); + audio_notifier_disable_service(AUDIO_NOTIFIER_PDR_SERVICE); + + audio_notifier_late_init(); + + return 0; +} +#endif module_init(audio_notifier_init); static void __exit audio_notifier_exit(void) From c7cc20abc095d326ea86cf853f14fb3c9cff4e50 Mon Sep 17 00:00:00 2001 From: Sudheer Papothi Date: Wed, 17 Jun 2020 02:50:43 +0530 Subject: [PATCH 090/116] soc: soundwire: Reduce soundwire runtime suspend delay Reduce soundwire runtime suspend delay for soundwire to enter into sleep early once the usecase ends. Change-Id: Idbace0fbe9363f487165865eacf5b85d3be86477 Signed-off-by: Sudheer Papothi --- soc/swr-mstr-ctrl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index b9913e4480..49b82cfb17 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -41,7 +41,6 @@ #define SWRM_DSD_PARAMS_PORT 4 #define SWR_BROADCAST_CMD_ID 0x0F -#define SWR_AUTO_SUSPEND_DELAY 1 /* delay in sec */ #define SWR_DEV_ID_MASK 0xFFFFFFFFFFFF #define SWR_REG_VAL_PACK(data, dev, id, reg) \ ((reg) | ((id) << 16) | ((dev) << 20) | ((data) << 24)) @@ -82,7 +81,7 @@ #define SWRM_DP_PORT_CTRL_OFFSET1_SHFT 0x08 /* pm runtime auto suspend timer in msecs */ -static int auto_suspend_timer = SWR_AUTO_SUSPEND_DELAY * 1000; +static int auto_suspend_timer = 500; module_param(auto_suspend_timer, int, 0664); MODULE_PARM_DESC(auto_suspend_timer, "timer for auto suspend"); From a1f8374cf590e97520931a0c6cc9f641f40f02db Mon Sep 17 00:00:00 2001 From: Vatsal Bucha Date: Fri, 19 Jun 2020 08:49:35 +0530 Subject: [PATCH 091/116] ASoC: wcd938x: Reduce glitch during headset record Enable ADC Mode and tx channel cfg as part of enable_adc. This should be enabled before enabling bolero dec so as to reduce glitch or saturation for headset. Change-Id: I94045d0c3b7b96744afb9e6a9a3eecf0abc5a55f Signed-off-by: Vatsal Bucha --- asoc/codecs/wcd938x/wcd938x.c | 115 +++++++++++++++++----------------- 1 file changed, 57 insertions(+), 58 deletions(-) diff --git a/asoc/codecs/wcd938x/wcd938x.c b/asoc/codecs/wcd938x/wcd938x.c index 22bea4cb65..c81df9d726 100644 --- a/asoc/codecs/wcd938x/wcd938x.c +++ b/asoc/codecs/wcd938x/wcd938x.c @@ -1634,57 +1634,6 @@ static int wcd938x_get_adc_mode(int val) return ret; } -static int wcd938x_codec_enable_adc(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, - int event){ - struct snd_soc_component *component = - snd_soc_dapm_to_component(w->dapm); - struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); - int clk_rate = 0, ret = 0; - - dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__, - w->name, event); - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - snd_soc_component_update_bits(component, - WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x08, 0x08); - snd_soc_component_update_bits(component, - WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x10); - set_bit(w->shift, &wcd938x->status_mask); - clk_rate = wcd938x_get_clk_rate(wcd938x->tx_mode[w->shift]); - ret = swr_slvdev_datapath_control(wcd938x->tx_swr_dev, - wcd938x->tx_swr_dev->dev_num, - true); - break; - case SND_SOC_DAPM_POST_PMD: - ret = swr_slvdev_datapath_control(wcd938x->tx_swr_dev, - wcd938x->tx_swr_dev->dev_num, - false); - snd_soc_component_update_bits(component, - WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x08, 0x00); - clear_bit(w->shift, &wcd938x->status_mask); - break; - }; - - return ret; -} - -void wcd938x_disable_bcs_before_slow_insert(struct snd_soc_component *component, - bool bcs_disable) -{ - struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); - - if (wcd938x->update_wcd_event) { - if (bcs_disable) - wcd938x->update_wcd_event(wcd938x->handle, - WCD_BOLERO_EVT_BCS_CLK_OFF, 0); - else - wcd938x->update_wcd_event(wcd938x->handle, - WCD_BOLERO_EVT_BCS_CLK_OFF, 1); - } -} - int wcd938x_tx_channel_config(struct snd_soc_component *component, int channel, int mode) { @@ -1725,14 +1674,14 @@ int wcd938x_tx_channel_config(struct snd_soc_component *component, return ret; } -static int wcd938x_enable_req(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ +static int wcd938x_codec_enable_adc(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event){ struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - int mode; - int ret = 0; struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + int clk_rate = 0, ret = 0; + int mode; dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__, w->name, event); @@ -1740,9 +1689,14 @@ static int wcd938x_enable_req(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: snd_soc_component_update_bits(component, - WCD938X_DIGITAL_CDC_REQ_CTL, 0x02, 0x02); + WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x08, 0x08); snd_soc_component_update_bits(component, - WCD938X_DIGITAL_CDC_REQ_CTL, 0x01, 0x00); + WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x10); + set_bit(w->shift, &wcd938x->status_mask); + clk_rate = wcd938x_get_clk_rate(wcd938x->tx_mode[w->shift]); + ret = swr_slvdev_datapath_control(wcd938x->tx_swr_dev, + wcd938x->tx_swr_dev->dev_num, + true); ret = wcd938x_tx_channel_config(component, w->shift, 1); mode = wcd938x_get_adc_mode(wcd938x->tx_mode[w->shift]); if (mode < 0) { @@ -1818,6 +1772,51 @@ static int wcd938x_enable_req(struct snd_soc_dapm_widget *w, default: break; } + ret = swr_slvdev_datapath_control(wcd938x->tx_swr_dev, + wcd938x->tx_swr_dev->dev_num, + false); + snd_soc_component_update_bits(component, + WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x08, 0x00); + clear_bit(w->shift, &wcd938x->status_mask); + break; + }; + + return ret; +} + +void wcd938x_disable_bcs_before_slow_insert(struct snd_soc_component *component, + bool bcs_disable) +{ + struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + + if (wcd938x->update_wcd_event) { + if (bcs_disable) + wcd938x->update_wcd_event(wcd938x->handle, + WCD_BOLERO_EVT_BCS_CLK_OFF, 0); + else + wcd938x->update_wcd_event(wcd938x->handle, + WCD_BOLERO_EVT_BCS_CLK_OFF, 1); + } +} + +static int wcd938x_enable_req(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + int ret = 0; + + dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__, + w->name, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + snd_soc_component_update_bits(component, + WCD938X_DIGITAL_CDC_REQ_CTL, 0x02, 0x02); + snd_soc_component_update_bits(component, + WCD938X_DIGITAL_CDC_REQ_CTL, 0x01, 0x00); + break; + case SND_SOC_DAPM_POST_PMD: snd_soc_component_update_bits(component, WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x00); break; From b588d829ad7620e62ce9112273bfdb2e4a2d4adb Mon Sep 17 00:00:00 2001 From: xsang Date: Fri, 19 Jun 2020 19:46:57 +0800 Subject: [PATCH 092/116] asoc: add null check for pcm pointer of snd_pcm_volume In platform driver volume controls, add null check for pcm pointer of struct snd_pcm_volume. Change-Id: I511a79422eaeced6240849cbb665a289afdc5984 Signed-off-by: Xiaojun Sang --- asoc/msm-pcm-q6-noirq.c | 6 ++++++ asoc/msm-pcm-q6-v2.c | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/asoc/msm-pcm-q6-noirq.c b/asoc/msm-pcm-q6-noirq.c index 47b48a2c34..59520581b8 100644 --- a/asoc/msm-pcm-q6-noirq.c +++ b/asoc/msm-pcm-q6-noirq.c @@ -732,6 +732,12 @@ static int msm_pcm_volume_ctl_get(struct snd_kcontrol *kcontrol, pr_err("%s: vol is NULL\n", __func__); return -ENODEV; } + + if (!vol->pcm) { + pr_err("%s: vol->pcm is NULL\n", __func__); + return -ENODEV; + } + substream = vol->pcm->streams[vol->stream].substream; if (!substream) { pr_err("%s substream not found\n", __func__); diff --git a/asoc/msm-pcm-q6-v2.c b/asoc/msm-pcm-q6-v2.c index 37369f6737..5762a95edb 100644 --- a/asoc/msm-pcm-q6-v2.c +++ b/asoc/msm-pcm-q6-v2.c @@ -1530,6 +1530,12 @@ static int msm_pcm_volume_ctl_get(struct snd_kcontrol *kcontrol, pr_err("%s: vol is NULL\n", __func__); return -ENODEV; } + + if (!vol->pcm) { + pr_err("%s: vol->pcm is NULL\n", __func__); + return -ENODEV; + } + substream = vol->pcm->streams[vol->stream].substream; if (!substream) { pr_err("%s substream not found\n", __func__); From 034cd15ba84a750f12d3ddb74bb97b0ea8febc73 Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Tue, 16 Jun 2020 20:06:22 +0530 Subject: [PATCH 093/116] Revert "soc: mstr-ctrl: Retain Audio_HM voting until suspend" This reverts commit d02c7efb3591bdca22f06a0744835fb48d1b0660. and commit 61f235e5bdfdb7993b78b372bbc054d3defe7e2c to avoid AOP related issues. Change-Id: I0b8b44bc5cca6bef6bc18c228f08a9c585c79c1c Signed-off-by: Laxminath Kasam --- asoc/codecs/bolero/bolero-cdc.c | 5 +-- asoc/codecs/bolero/bolero-cdc.h | 7 ++-- asoc/codecs/bolero/rx-macro.c | 2 - asoc/codecs/bolero/tx-macro.c | 32 +++------------ asoc/codecs/bolero/va-macro.c | 71 +-------------------------------- asoc/codecs/bolero/wsa-macro.c | 2 - soc/swr-mstr-ctrl.c | 23 +++++------ soc/swr-mstr-ctrl.h | 4 -- 8 files changed, 22 insertions(+), 124 deletions(-) diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c index 32a3380f88..c46bcad0cd 100644 --- a/asoc/codecs/bolero/bolero-cdc.c +++ b/asoc/codecs/bolero/bolero-cdc.c @@ -1094,7 +1094,7 @@ EXPORT_SYMBOL(bolero_tx_mclk_enable); * Returns 0 on success or -EINVAL on error. */ int bolero_register_event_listener(struct snd_soc_component *component, - bool enable, bool is_dmic_sva) + bool enable) { struct bolero_priv *priv = NULL; int ret = 0; @@ -1113,8 +1113,7 @@ int bolero_register_event_listener(struct snd_soc_component *component, if (priv->macro_params[TX_MACRO].reg_evt_listener) ret = priv->macro_params[TX_MACRO].reg_evt_listener(component, - enable, - is_dmic_sva); + enable); return ret; } diff --git a/asoc/codecs/bolero/bolero-cdc.h b/asoc/codecs/bolero/bolero-cdc.h index ba0f3ce57a..1f21fd69c8 100644 --- a/asoc/codecs/bolero/bolero-cdc.h +++ b/asoc/codecs/bolero/bolero-cdc.h @@ -77,8 +77,7 @@ struct macro_ops { u32 size, void *data); int (*clk_div_get)(struct snd_soc_component *component); int (*clk_switch)(struct snd_soc_component *component, int clk_src); - int (*reg_evt_listener)(struct snd_soc_component *component, - bool en, bool is_dmic_sva); + int (*reg_evt_listener)(struct snd_soc_component *component, bool en); int (*clk_enable)(struct snd_soc_component *c, bool en); char __iomem *io_base; u16 clk_id_req; @@ -105,7 +104,7 @@ int bolero_runtime_suspend(struct device *dev); int bolero_set_port_map(struct snd_soc_component *component, u32 size, void *data); int bolero_tx_clk_switch(struct snd_soc_component *component, int clk_src); int bolero_register_event_listener(struct snd_soc_component *component, - bool enable, bool is_dmic_sva); + bool enable); void bolero_wsa_pa_on(struct device *dev); bool bolero_check_core_votes(struct device *dev); int bolero_tx_mclk_enable(struct snd_soc_component *c, bool enable); @@ -179,7 +178,7 @@ static inline int bolero_tx_clk_switch(struct snd_soc_component *component, static inline int bolero_register_event_listener( struct snd_soc_component *component, - bool enable, bool is_dmic_sva) + bool enable) { return 0; } diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c index 46c0937ea4..87c9477ad1 100644 --- a/asoc/codecs/bolero/rx-macro.c +++ b/asoc/codecs/bolero/rx-macro.c @@ -378,7 +378,6 @@ struct rx_swr_ctrl_platform_data { void *data), void *swrm_handle, int action); - int (*pinctrl_setup)(void *handle, bool enable); }; enum { @@ -4105,7 +4104,6 @@ static int rx_macro_probe(struct platform_device *pdev) rx_priv->swr_plat_data.clk = rx_swrm_clock; rx_priv->swr_plat_data.core_vote = rx_macro_core_vote; rx_priv->swr_plat_data.handle_irq = NULL; - rx_priv->swr_plat_data.pinctrl_setup = NULL; ret = of_property_read_u8_array(pdev->dev.of_node, "qcom,rx-bcl-pmic-params", bcl_pmic_params, diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c index 6fb76a9362..55b2c3017b 100644 --- a/asoc/codecs/bolero/tx-macro.c +++ b/asoc/codecs/bolero/tx-macro.c @@ -81,7 +81,6 @@ struct tx_macro_swr_ctrl_platform_data { void *data), void *swrm_handle, int action); - int (*pinctrl_setup)(void *handle, bool enable); }; enum { @@ -2497,30 +2496,12 @@ static const struct snd_kcontrol_new tx_macro_snd_controls[] = { tx_macro_get_bcs, tx_macro_set_bcs), }; -static int tx_macro_pinctrl_setup(void *handle, bool enable) -{ - struct tx_macro_priv *tx_priv = (struct tx_macro_priv *) handle; - - if (tx_priv == NULL) { - pr_err("%s: tx priv data is NULL\n", __func__); - return -EINVAL; - } - if (enable) - msm_cdc_pinctrl_set_wakeup_capable( - tx_priv->tx_swr_gpio_p, true); - else - msm_cdc_pinctrl_set_wakeup_capable( - tx_priv->tx_swr_gpio_p, false); - return 0; -} - static int tx_macro_register_event_listener(struct snd_soc_component *component, - bool enable, bool is_dmic_sva) + bool enable) { struct device *tx_dev = NULL; struct tx_macro_priv *tx_priv = NULL; int ret = 0; - u32 dmic_sva = is_dmic_sva; if (!component) return -EINVAL; @@ -2542,17 +2523,15 @@ static int tx_macro_register_event_listener(struct snd_soc_component *component, if (enable) { ret = swrm_wcd_notify( tx_priv->swr_ctrl_data[0].tx_swr_pdev, - SWR_REGISTER_WAKEUP, &dmic_sva); + SWR_REGISTER_WAKEUP, NULL); msm_cdc_pinctrl_set_wakeup_capable( - tx_priv->tx_swr_gpio_p, false); + tx_priv->tx_swr_gpio_p, false); } else { - /* while teardown we can reset the flag */ - dmic_sva = 0; msm_cdc_pinctrl_set_wakeup_capable( - tx_priv->tx_swr_gpio_p, true); + tx_priv->tx_swr_gpio_p, true); ret = swrm_wcd_notify( tx_priv->swr_ctrl_data[0].tx_swr_pdev, - SWR_DEREGISTER_WAKEUP, &dmic_sva); + SWR_DEREGISTER_WAKEUP, NULL); } } @@ -3343,7 +3322,6 @@ static int tx_macro_probe(struct platform_device *pdev) tx_priv->swr_plat_data.clk = tx_macro_swrm_clock; tx_priv->swr_plat_data.core_vote = tx_macro_core_vote; tx_priv->swr_plat_data.handle_irq = NULL; - tx_priv->swr_plat_data.pinctrl_setup = tx_macro_pinctrl_setup; mutex_init(&tx_priv->swr_clk_lock); } tx_priv->is_used_tx_swr_gpio = is_used_tx_swr_gpio; diff --git a/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c index 760537b623..710eb7190d 100644 --- a/asoc/codecs/bolero/va-macro.c +++ b/asoc/codecs/bolero/va-macro.c @@ -130,7 +130,6 @@ struct va_macro_swr_ctrl_platform_data { void *data), void *swrm_handle, int action); - int (*pinctrl_setup)(void *handle, bool enable); }; struct va_macro_priv { @@ -460,14 +459,14 @@ static int va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w, dev_dbg(va_dev, "%s: clock switch failed\n", __func__); if (va_priv->lpi_enable) { - bolero_register_event_listener(component, true, false); + bolero_register_event_listener(component, true); va_priv->register_event_listener = true; } break; case SND_SOC_DAPM_POST_PMD: if (va_priv->register_event_listener) { va_priv->register_event_listener = false; - bolero_register_event_listener(component, false, false); + bolero_register_event_listener(component, false); } if (bolero_tx_clk_switch(component, CLK_SRC_TX_RCG)) dev_dbg(va_dev, "%s: clock switch failed\n",__func__); @@ -483,45 +482,6 @@ static int va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w, return ret; } -static int va_macro_swr_intr_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_component *component = - snd_soc_dapm_to_component(w->dapm); - int ret = 0; - struct device *va_dev = NULL; - struct va_macro_priv *va_priv = NULL; - - if (!va_macro_get_data(component, &va_dev, &va_priv, __func__)) - return -EINVAL; - - dev_dbg(va_dev, "%s: event = %d, lpi_enable = %d\n", - __func__, event, va_priv->lpi_enable); - - if (!va_priv->lpi_enable) - return ret; - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - if (va_priv->lpi_enable) { - bolero_register_event_listener(component, true, true); - va_priv->register_event_listener = true; - } - break; - case SND_SOC_DAPM_POST_PMD: - if (va_priv->register_event_listener) { - va_priv->register_event_listener = false; - bolero_register_event_listener(component, false, true); - } - break; - default: - dev_err(va_priv->dev, - "%s: invalid DAPM event %d\n", __func__, event); - ret = -EINVAL; - } - return ret; -} - static int va_macro_tx_swr_clk_event_v2(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -2029,10 +1989,6 @@ static const struct snd_soc_dapm_widget va_macro_dapm_widgets_v3[] = { SND_SOC_DAPM_SUPPLY_S("VA_SWR_PWR", -1, SND_SOC_NOPM, 0, 0, va_macro_swr_pwr_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - - SND_SOC_DAPM_SUPPLY_S("VA_SWR_INTR", 0, SND_SOC_NOPM, 0, 0, - va_macro_swr_intr_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), }; static const struct snd_soc_dapm_widget va_macro_dapm_widgets[] = { @@ -2177,10 +2133,6 @@ static const struct snd_soc_dapm_widget va_macro_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY_S("VA_MCLK", -1, SND_SOC_NOPM, 0, 0, va_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - - SND_SOC_DAPM_SUPPLY_S("VA_SWR_INTR", 0, SND_SOC_NOPM, 0, 0, - va_macro_swr_intr_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), }; static const struct snd_soc_dapm_widget va_macro_wod_dapm_widgets[] = { @@ -2327,15 +2279,6 @@ static const struct snd_soc_dapm_route va_audio_map_v3[] = { {"VA SMIC MUX3", "SWR_MIC9", "VA SWR_INPUT"}, {"VA SMIC MUX3", "SWR_MIC10", "VA SWR_INPUT"}, {"VA SMIC MUX3", "SWR_MIC11", "VA SWR_INPUT"}, - - {"VA DMIC0", NULL, "VA_SWR_INTR"}, - {"VA DMIC1", NULL, "VA_SWR_INTR"}, - {"VA DMIC2", NULL, "VA_SWR_INTR"}, - {"VA DMIC3", NULL, "VA_SWR_INTR"}, - {"VA DMIC4", NULL, "VA_SWR_INTR"}, - {"VA DMIC5", NULL, "VA_SWR_INTR"}, - {"VA DMIC6", NULL, "VA_SWR_INTR"}, - {"VA DMIC7", NULL, "VA_SWR_INTR"}, }; static const struct snd_soc_dapm_route va_audio_map_v2[] = { @@ -2572,15 +2515,6 @@ static const struct snd_soc_dapm_route va_audio_map[] = { {"VA SMIC MUX7", "SWR_DMIC6", "VA SWR_MIC6"}, {"VA SMIC MUX7", "SWR_DMIC7", "VA SWR_MIC7"}, - {"VA DMIC0", NULL, "VA_SWR_INTR"}, - {"VA DMIC1", NULL, "VA_SWR_INTR"}, - {"VA DMIC2", NULL, "VA_SWR_INTR"}, - {"VA DMIC3", NULL, "VA_SWR_INTR"}, - {"VA DMIC4", NULL, "VA_SWR_INTR"}, - {"VA DMIC5", NULL, "VA_SWR_INTR"}, - {"VA DMIC6", NULL, "VA_SWR_INTR"}, - {"VA DMIC7", NULL, "VA_SWR_INTR"}, - {"VA SWR_ADC0", NULL, "VA_SWR_PWR"}, {"VA SWR_ADC1", NULL, "VA_SWR_PWR"}, {"VA SWR_ADC2", NULL, "VA_SWR_PWR"}, @@ -3230,7 +3164,6 @@ static int va_macro_probe(struct platform_device *pdev) va_priv->swr_plat_data.clk = va_macro_swrm_clock; va_priv->swr_plat_data.core_vote = va_macro_core_vote; va_priv->swr_plat_data.handle_irq = NULL; - va_priv->swr_plat_data.pinctrl_setup = NULL; mutex_init(&va_priv->swr_clk_lock); } va_priv->is_used_va_swr_gpio = is_used_va_swr_gpio; diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c index 12a2960c5d..5c59d6de4f 100644 --- a/asoc/codecs/bolero/wsa-macro.c +++ b/asoc/codecs/bolero/wsa-macro.c @@ -166,7 +166,6 @@ struct wsa_macro_swr_ctrl_platform_data { void *data), void *swrm_handle, int action); - int (*pinctrl_setup)(void *handle, bool enable); }; struct wsa_macro_bcl_pmic_params { @@ -3197,7 +3196,6 @@ static int wsa_macro_probe(struct platform_device *pdev) wsa_priv->swr_plat_data.clk = wsa_swrm_clock; wsa_priv->swr_plat_data.core_vote = wsa_macro_core_vote; wsa_priv->swr_plat_data.handle_irq = NULL; - wsa_priv->swr_plat_data.pinctrl_setup = NULL; ret = of_property_read_u32(pdev->dev.of_node, "qcom,default-clk-id", &default_clk_id); diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index 69cce11809..56fc8f3eb4 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -2481,8 +2481,6 @@ static int swrm_probe(struct platform_device *pdev) ret = -EINVAL; goto err_pdata_fail; } - swrm->pinctrl_setup = pdata->pinctrl_setup; - if (of_property_read_u32(pdev->dev.of_node, "qcom,swr-clock-stop-mode0", &swrm->clk_stop_mode0_supp)) { @@ -2815,6 +2813,7 @@ static int swrm_runtime_resume(struct device *dev) int ret = 0; bool swrm_clk_req_err = false; bool hw_core_err = false; + bool aud_core_err = false; struct swr_master *mstr = &swrm->master; struct swr_device *swr_dev; u32 temp = 0; @@ -2833,7 +2832,7 @@ static int swrm_runtime_resume(struct device *dev) if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, true)) { dev_err(dev, "%s:lpass audio hw enable failed\n", __func__); - swrm->aud_core_err = true; + aud_core_err = true; } if ((swrm->state == SWR_MSTR_DOWN) || @@ -2852,9 +2851,6 @@ static int swrm_runtime_resume(struct device *dev) irq_get_irq_data(swrm->wake_irq))) disable_irq_nosync(swrm->wake_irq); mutex_unlock(&swrm->irq_lock); - if (swrm->dmic_sva && swrm->pinctrl_setup) - swrm->pinctrl_setup(swrm->handle, - false); } if (swrm->ipc_wakeup) msm_aud_evt_blocking_notifier_call_chain( @@ -2928,7 +2924,7 @@ static int swrm_runtime_resume(struct device *dev) swrm->state = SWR_MSTR_UP; } exit: - if (ret && !swrm->aud_core_err) + if (!aud_core_err) swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false); if (!hw_core_err) swrm_request_hw_vote(swrm, LPASS_HW_CORE, false); @@ -2953,6 +2949,7 @@ static int swrm_runtime_suspend(struct device *dev) struct swr_mstr_ctrl *swrm = platform_get_drvdata(pdev); int ret = 0; bool hw_core_err = false; + bool aud_core_err = false; struct swr_master *mstr = &swrm->master; struct swr_device *swr_dev; int current_state = 0; @@ -2971,6 +2968,11 @@ static int swrm_runtime_suspend(struct device *dev) __func__); hw_core_err = true; } + if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, true)) { + dev_err(dev, "%s:lpass audio hw enable failed\n", + __func__); + aud_core_err = true; + } if ((current_state == SWR_MSTR_UP) || (current_state == SWR_MSTR_SSR)) { @@ -3039,8 +3041,6 @@ static int swrm_runtime_suspend(struct device *dev) if (swrm->clk_stop_mode0_supp) { if (swrm->wake_irq > 0) { - if (swrm->dmic_sva && swrm->pinctrl_setup) - swrm->pinctrl_setup(swrm->handle, true); enable_irq(swrm->wake_irq); } else if (swrm->ipc_wakeup) { msm_aud_evt_blocking_notifier_call_chain( @@ -3054,11 +3054,10 @@ static int swrm_runtime_suspend(struct device *dev) if (current_state != SWR_MSTR_SSR) swrm->state = SWR_MSTR_DOWN; exit: - if (!swrm->aud_core_err) + if (!aud_core_err) swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false); if (!hw_core_err) swrm_request_hw_vote(swrm, LPASS_HW_CORE, false); - swrm->aud_core_err = false; mutex_unlock(&swrm->reslock); trace_printk("%s: pm_runtime: suspend done state: %d\n", __func__, swrm->state); @@ -3394,12 +3393,10 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data) case SWR_REGISTER_WAKEUP: msm_aud_evt_blocking_notifier_call_chain( SWR_WAKE_IRQ_REGISTER, (void *)swrm); - swrm->dmic_sva = *(u32 *)data; break; case SWR_DEREGISTER_WAKEUP: msm_aud_evt_blocking_notifier_call_chain( SWR_WAKE_IRQ_DEREGISTER, (void *)swrm); - swrm->dmic_sva = 0; break; case SWR_SET_PORT_MAP: if (!data) { diff --git a/soc/swr-mstr-ctrl.h b/soc/swr-mstr-ctrl.h index bc4ae4b045..89d35b5423 100644 --- a/soc/swr-mstr-ctrl.h +++ b/soc/swr-mstr-ctrl.h @@ -115,7 +115,6 @@ struct swr_ctrl_platform_data { int (*core_vote)(void *handle, bool enable); int (*reg_irq)(void *handle, irqreturn_t(*irq_handler)(int irq, void *data), void *swr_handle, int type); - int (*pinctrl_setup)(void *handle, bool enable); }; struct swr_mstr_ctrl { @@ -149,7 +148,6 @@ struct swr_mstr_ctrl { int (*core_vote)(void *handle, bool enable); int (*reg_irq)(void *handle, irqreturn_t(*irq_handler)(int irq, void *data), void *swr_handle, int type); - int (*pinctrl_setup)(void *handle, bool enable); int irq; int wake_irq; int version; @@ -175,10 +173,8 @@ struct swr_mstr_ctrl { u32 clk_stop_mode0_supp; struct work_struct wakeup_work; u32 ipc_wakeup; - u32 dmic_sva; bool dev_up; bool ipc_wakeup_triggered; - bool aud_core_err; bool req_clk_switch; struct pm_qos_request pm_qos_req; enum swrm_pm_state pm_state; From 4bb46e759d4e98fb73e93888ea8231154abe43dd Mon Sep 17 00:00:00 2001 From: Vatsal Bucha Date: Mon, 22 Jun 2020 11:19:10 +0530 Subject: [PATCH 094/116] ASoC: Resolve error logs printed at bootup Error logs are printed by default during bootup due to get function called for all controls. Remove error logs and not used controls. Change-Id: I7d73432bcdd0c527ea78b0ec1c9650056eadcfe5 Signed-off-by: Vatsal Bucha --- asoc/msm-pcm-routing-v2.c | 1 - asoc/msm-qti-pp-config.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c index 139d404760..c397dc4175 100644 --- a/asoc/msm-pcm-routing-v2.c +++ b/asoc/msm-pcm-routing-v2.c @@ -27962,7 +27962,6 @@ static const struct snd_soc_dapm_route intercon[] = { {"MM_UL20", NULL, "MultiMedia20 Mixer"}, {"MM_UL21", NULL, "MultiMedia21 Mixer"}, {"MM_UL22", NULL, "MultiMedia22 Mixer"}, - {"MM_UL23", NULL, "MultiMedia23 Mixer"}, {"MM_UL24", NULL, "MultiMedia24 Mixer"}, {"MM_UL25", NULL, "MultiMedia25 Mixer"}, {"MM_UL27", NULL, "MultiMedia27 Mixer"}, diff --git a/asoc/msm-qti-pp-config.c b/asoc/msm-qti-pp-config.c index e26e421fe3..e5f07d0e43 100644 --- a/asoc/msm-qti-pp-config.c +++ b/asoc/msm-qti-pp-config.c @@ -536,7 +536,7 @@ static int msm_qti_pp_get_rms_value_control(struct snd_kcontrol *kcontrol, break; } if ((be_idx >= MSM_BACKEND_DAI_MAX) || !msm_bedai.active) { - pr_err("%s, back not active to query rms be_idx:%d\n", + pr_debug("%s, back not active to query rms be_idx:%d\n", __func__, be_idx); rc = -EINVAL; goto get_rms_value_err; From 86907313a38e2bf425a7941d6e73112040ccdd25 Mon Sep 17 00:00:00 2001 From: Meng Wang Date: Thu, 21 May 2020 11:18:10 +0800 Subject: [PATCH 095/116] asoc: compress: move compress controls to compress_new Move compress controls to compress_new API to initialize compress related mixer controls. Change-Id: I7038d3c4644d0071477016b186ea0550e92f6214 Signed-off-by: Meng Wang --- asoc/msm-compress-q6-v2.c | 14 +++++++++++--- asoc/msm-compress-q6-v2.h | 4 ++++ asoc/msm-dai-fe.c | 32 +++++++++++++++++--------------- 3 files changed, 32 insertions(+), 18 deletions(-) create mode 100644 asoc/msm-compress-q6-v2.h diff --git a/asoc/msm-compress-q6-v2.c b/asoc/msm-compress-q6-v2.c index c2d8271f10..3321c2d9de 100644 --- a/asoc/msm-compress-q6-v2.c +++ b/asoc/msm-compress-q6-v2.c @@ -5621,9 +5621,17 @@ fail: return ret; } -static int msm_compr_new(struct snd_soc_pcm_runtime *rtd) +int msm_compr_new(struct snd_soc_pcm_runtime *rtd, int num) { - int rc; + int rc = 0; + + if (rtd == NULL) { + pr_err("%s: RTD is NULL\n", __func__); + return 0; + } + rc = snd_soc_new_compress(rtd, num); + if (rc) + pr_err("%s: Fail to create pcm for compress\n", __func__); rc = msm_compr_add_volume_control(rtd); if (rc) @@ -5677,6 +5685,7 @@ static int msm_compr_new(struct snd_soc_pcm_runtime *rtd) __func__); return 0; } +EXPORT_SYMBOL(msm_compr_new); static struct snd_compr_ops msm_compr_ops = { .open = msm_compr_open, @@ -5699,7 +5708,6 @@ static struct snd_soc_component_driver msm_soc_component = { .name = DRV_NAME, .probe = msm_compr_probe, .compr_ops = &msm_compr_ops, - .pcm_new = msm_compr_new, }; static int msm_compr_dev_probe(struct platform_device *pdev) diff --git a/asoc/msm-compress-q6-v2.h b/asoc/msm-compress-q6-v2.h new file mode 100644 index 0000000000..86d12879e8 --- /dev/null +++ b/asoc/msm-compress-q6-v2.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2020 The Linux Foundation. All rights reserved. +*/ +int msm_compr_new(struct snd_soc_pcm_runtime *rtd, int num); diff --git a/asoc/msm-dai-fe.c b/asoc/msm-dai-fe.c index c711d23741..81210f7d2e 100644 --- a/asoc/msm-dai-fe.c +++ b/asoc/msm-dai-fe.c @@ -12,6 +12,8 @@ #include #include +#include "msm-compress-q6-v2.h" + static struct snd_soc_dai_ops msm_fe_dai_ops = {}; /* Conventional and unconventional sample rate supported */ @@ -222,7 +224,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .rate_max = 384000, }, .ops = &msm_fe_Multimedia_dai_ops, - .compress_new = snd_soc_new_compress, + .compress_new = msm_compr_new, .name = "MultiMedia4", .probe = fe_dai_probe, }, @@ -308,7 +310,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .rate_max = 384000, }, .ops = &msm_fe_Multimedia_dai_ops, - .compress_new = snd_soc_new_compress, + .compress_new = msm_compr_new, .name = "MultiMedia7", .probe = fe_dai_probe, }, @@ -2401,7 +2403,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .rate_max = 384000, }, .ops = &msm_fe_Multimedia_dai_ops, - .compress_new = snd_soc_new_compress, + .compress_new = msm_compr_new, .name = "MultiMedia11", .probe = fe_dai_probe, }, @@ -2421,7 +2423,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .rate_max = 384000, }, .ops = &msm_fe_Multimedia_dai_ops, - .compress_new = snd_soc_new_compress, + .compress_new = msm_compr_new, .name = "MultiMedia12", .probe = fe_dai_probe, }, @@ -2441,7 +2443,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .rate_max = 384000, }, .ops = &msm_fe_Multimedia_dai_ops, - .compress_new = snd_soc_new_compress, + .compress_new = msm_compr_new, .name = "MultiMedia13", .probe = fe_dai_probe, }, @@ -2461,7 +2463,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .rate_max = 384000, }, .ops = &msm_fe_Multimedia_dai_ops, - .compress_new = snd_soc_new_compress, + .compress_new = msm_compr_new, .name = "MultiMedia14", .probe = fe_dai_probe, }, @@ -2481,7 +2483,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .rate_max = 384000, }, .ops = &msm_fe_Multimedia_dai_ops, - .compress_new = snd_soc_new_compress, + .compress_new = msm_compr_new, .name = "MultiMedia15", .probe = fe_dai_probe, }, @@ -2583,7 +2585,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .rate_max = 192000, }, .ops = &msm_fe_Multimedia_dai_ops, - .compress_new = snd_soc_new_compress, + .compress_new = msm_compr_new, .name = "MultiMedia17", .probe = fe_dai_probe, }, @@ -2602,7 +2604,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .rate_max = 192000, }, .ops = &msm_fe_Multimedia_dai_ops, - .compress_new = snd_soc_new_compress, + .compress_new = msm_compr_new, .name = "MultiMedia18", .probe = fe_dai_probe, }, @@ -2621,7 +2623,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .rate_max = 192000, }, .ops = &msm_fe_Multimedia_dai_ops, - .compress_new = snd_soc_new_compress, + .compress_new = msm_compr_new, .name = "MultiMedia19", .probe = fe_dai_probe, }, @@ -2839,7 +2841,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .rate_max = 384000, }, .ops = &msm_fe_Multimedia_dai_ops, - .compress_new = snd_soc_new_compress, + .compress_new = msm_compr_new, .name = "MultiMedia26", .probe = fe_dai_probe, }, @@ -2858,7 +2860,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .rate_max = 192000, }, .ops = &msm_fe_Multimedia_dai_ops, - .compress_new = snd_soc_new_compress, + .compress_new = msm_compr_new, .name = "MultiMedia27", .probe = fe_dai_probe, }, @@ -2877,7 +2879,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .rate_max = 192000, }, .ops = &msm_fe_Multimedia_dai_ops, - .compress_new = snd_soc_new_compress, + .compress_new = msm_compr_new, .name = "MultiMedia28", .probe = fe_dai_probe, }, @@ -2896,7 +2898,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .rate_max = 192000, }, .ops = &msm_fe_Multimedia_dai_ops, - .compress_new = snd_soc_new_compress, + .compress_new = msm_compr_new, .name = "MultiMedia29", .probe = fe_dai_probe, }, @@ -2915,7 +2917,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .rate_max = 192000, }, .ops = &msm_fe_Multimedia_dai_ops, - .compress_new = snd_soc_new_compress, + .compress_new = msm_compr_new, .name = "MultiMedia30", .probe = fe_dai_probe, }, From 366f76d21c94bdb4208d0f5540c75acf0bb502f9 Mon Sep 17 00:00:00 2001 From: "Vangala, Amarnath" Date: Tue, 23 Jun 2020 13:40:04 +0530 Subject: [PATCH 096/116] dsp: Feedback path cfg to support 3rd party spkr protection algorithms. Backward compatibility change to set 'feedback path cfg' to AFE_MODULE_FEEDBACK, to support 3rd party spkr protection algorithms. Change-Id: I9af731902fbc5bc69f130a4f30d8fc5f18ceaace Signed-off-by: Vangala, Amarnath --- dsp/q6afe.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/dsp/q6afe.c b/dsp/q6afe.c index a6ac17ce8b..c3f396314f 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -9762,30 +9762,28 @@ int afe_spk_prot_feed_back_cfg(int src_port, int dst_port, } this_afe.v4_ch_map_cfg.num_channels = index; this_afe.num_spkrs = index / 2; - pr_debug("%s no of channels: %d\n", __func__, index); - this_afe.vi_tx_port = src_port; - this_afe.vi_rx_port = dst_port; - ret = 0; - } else { - memset(&prot_config, 0, sizeof(prot_config)); - prot_config.feedback_path_cfg.dst_portid = - q6audio_get_port_id(dst_port); - if (l_ch) { - prot_config.feedback_path_cfg.chan_info[index++] = 1; - prot_config.feedback_path_cfg.chan_info[index++] = 2; - } - if (r_ch) { - prot_config.feedback_path_cfg.chan_info[index++] = 3; - prot_config.feedback_path_cfg.chan_info[index++] = 4; - } - prot_config.feedback_path_cfg.num_channels = index; - pr_debug("%s no of channels: %d\n", __func__, index); - prot_config.feedback_path_cfg.minor_version = 1; - ret = afe_spk_prot_prepare(src_port, dst_port, - AFE_PARAM_ID_FEEDBACK_PATH_CFG, &prot_config, - sizeof(union afe_spkr_prot_config)); } + index = 0; + memset(&prot_config, 0, sizeof(prot_config)); + prot_config.feedback_path_cfg.dst_portid = + q6audio_get_port_id(dst_port); + if (l_ch) { + prot_config.feedback_path_cfg.chan_info[index++] = 1; + prot_config.feedback_path_cfg.chan_info[index++] = 2; + } + if (r_ch) { + prot_config.feedback_path_cfg.chan_info[index++] = 3; + prot_config.feedback_path_cfg.chan_info[index++] = 4; + } + + prot_config.feedback_path_cfg.num_channels = index; + pr_debug("%s no of channels: %d\n", __func__, index); + prot_config.feedback_path_cfg.minor_version = 1; + ret = afe_spk_prot_prepare(src_port, dst_port, + AFE_PARAM_ID_FEEDBACK_PATH_CFG, &prot_config, + sizeof(union afe_spkr_prot_config)); + fail_cmd: return ret; } From a20b914402920c00095640305e57d68b9a18d59e Mon Sep 17 00:00:00 2001 From: Vatsal Bucha Date: Thu, 25 Jun 2020 11:43:18 +0530 Subject: [PATCH 097/116] soc: swr-mstr: Add delay of 100us after last write during bulk write There is no delay after last write during bulk write. Add 100us delay so as to ensure that last write goes fine. Change-Id: Ifc1585f30eec639ffd6b80dde2e0365f368349d7 Signed-off-by: Vatsal Bucha --- soc/swr-mstr-ctrl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index 0207a9e3fc..4a5d571d56 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -646,6 +646,7 @@ static int swr_master_bulk_write(struct swr_mstr_ctrl *swrm, u32 *reg_addr, usleep_range(50, 55); swr_master_write(swrm, reg_addr[i], val[i]); } + usleep_range(100, 110); mutex_unlock(&swrm->iolock); } return 0; From e1e34edd166877a475f18dc7076e5d5c12098ccf Mon Sep 17 00:00:00 2001 From: Xiaoyu Ye Date: Mon, 29 Jun 2020 04:16:17 -0700 Subject: [PATCH 098/116] asoc: check param_size before use it in memcpy If param_size is not the correct size when it's passed to memcpy, it could result wrong parameter to be sent to ADSP by audio driver. Change-Id: Iaf66a87c405bd0508bb0771c5fe20626f2b75dda Signed-off-by: Xiaoyu Ye --- asoc/msm-lsm-client.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/asoc/msm-lsm-client.c b/asoc/msm-lsm-client.c index 5965355eac..be997b4a74 100644 --- a/asoc/msm-lsm-client.c +++ b/asoc/msm-lsm-client.c @@ -881,8 +881,16 @@ static int msm_lsm_dereg_model(struct snd_pcm_substream *substream, } if (sm->model_id == p_info->model_id) { - rc = q6lsm_set_one_param(client, p_info, NULL, - LSM_DEREG_MULTI_SND_MODEL); + if (p_info->param_size != sizeof(p_info->model_id)) { + rc = -EINVAL; + pr_err("%s: %s failed, p_info->param_size is invalid: %d\n", + __func__, "LSM_DEREG_MULTI_SND_MODEL", + p_info->param_size); + } else { + rc = q6lsm_set_one_param(client, p_info, NULL, + LSM_DEREG_MULTI_SND_MODEL); + } + if (rc) dev_err(rtd->dev, "%s: Failed to deregister snd_model %d, err = %d\n", From 070b8d25a13c1a621c9302a7ae700420905f80bc Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Wed, 1 Jul 2020 17:01:55 +0530 Subject: [PATCH 099/116] asoc: wsa881x: Disable WSA ADC register when teardown To ensure mono/stereo speaker usecases with speaker protection enabled switch properly and apply register during powerup, update disable sequence of ADC register. CRs-Fixed: 2705914 Change-Id: If9ceb4436ed6ce236a4e529d65b0acc8f9f6cd0e Signed-off-by: Laxminath Kasam --- asoc/codecs/wsa881x.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/asoc/codecs/wsa881x.c b/asoc/codecs/wsa881x.c index adb4d91baf..a591429ed3 100644 --- a/asoc/codecs/wsa881x.c +++ b/asoc/codecs/wsa881x.c @@ -1083,6 +1083,9 @@ static int wsa881x_spkr_pa_event(struct snd_soc_dapm_widget *w, 0x80, 0x00); if (wsa881x->visense_enable) { wsa881x_visense_adc_ctrl(component, DISABLE); + snd_soc_component_update_bits(component, + WSA881X_ADC_EN_SEL_IBAIS, + 0x07, 0x00); wsa881x_visense_txfe_ctrl(component, DISABLE, 0x00, 0x01, 0x01); } From b629237a0ecc49da6c8ef63b579b4f605fe194c7 Mon Sep 17 00:00:00 2001 From: Vignesh Kulothungan Date: Wed, 1 Jul 2020 12:56:59 -0700 Subject: [PATCH 100/116] ASoC: bolero: add rx_macro_rx5 dai for dsd Add rx_macro_rx5 dai for native dsd playback support. Change-Id: I52a47e1d908fddda4c9d1a5546f9a00d6b8a7ba4 Signed-off-by: Vignesh Kulothungan --- asoc/codecs/bolero/rx-macro.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c index 87c9477ad1..53ad129d46 100644 --- a/asoc/codecs/bolero/rx-macro.c +++ b/asoc/codecs/bolero/rx-macro.c @@ -387,6 +387,7 @@ enum { RX_MACRO_AIF3_PB, RX_MACRO_AIF4_PB, RX_MACRO_AIF_ECHO, + RX_MACRO_AIF5_PB, RX_MACRO_AIF6_PB, RX_MACRO_MAX_DAIS, }; @@ -719,6 +720,20 @@ static struct snd_soc_dai_driver rx_macro_dai[] = { }, .ops = &rx_macro_dai_ops, }, + { + .name = "rx_macro_rx5", + .id = RX_MACRO_AIF5_PB, + .playback = { + .stream_name = "RX_MACRO_AIF5 Playback", + .rates = RX_MACRO_RATES | RX_MACRO_FRAC_RATES, + .formats = RX_MACRO_FORMATS, + .rate_max = 384000, + .rate_min = 8000, + .channels_min = 1, + .channels_max = 4, + }, + .ops = &rx_macro_dai_ops, + }, { .name = "rx_macro_rx6", .id = RX_MACRO_AIF6_PB, @@ -1138,6 +1153,13 @@ static int rx_macro_get_channel_map(struct snd_soc_dai *dai, "%s: dai->id:%d, ch_mask:0x%x, active_ch_cnt:%d active_mask: 0x%x\n", __func__, dai->id, *rx_slot, *rx_num, rx_priv->active_ch_mask[dai->id]); break; + case RX_MACRO_AIF5_PB: + *rx_slot = 0x1; + *rx_num = 0x01; + dev_dbg(rx_priv->dev, + "%s: dai->id:%d, ch_mask:0x%x, active_ch_cnt:%d\n", + __func__, dai->id, *rx_slot, *rx_num); + break; case RX_MACRO_AIF6_PB: *rx_slot = 0x1; *rx_num = 0x01; @@ -3191,6 +3213,9 @@ static const struct snd_soc_dapm_widget rx_macro_dapm_widgets[] = { SND_SOC_DAPM_AIF_OUT("RX AIF_ECHO", "RX_AIF_ECHO Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("RX AIF5 PB", "RX_MACRO_AIF5 Playback", 0, + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("RX AIF6 PB", "RX_MACRO_AIF6 Playback", 0, SND_SOC_NOPM, 0, 0), @@ -3861,6 +3886,7 @@ static int rx_macro_init(struct snd_soc_component *component) snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF2 Playback"); snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF3 Playback"); snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF4 Playback"); + snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF5 Playback"); snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF6 Playback"); snd_soc_dapm_ignore_suspend(dapm, "HPHL_OUT"); snd_soc_dapm_ignore_suspend(dapm, "HPHR_OUT"); From 8508b1a1032ae60eb4e4ee5e753381662ac082ae Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Wed, 24 Jun 2020 20:38:03 +0530 Subject: [PATCH 101/116] asoc: codecs: remove cancel_delayed_work_sync to avoid race condition Remove cancel_delayed_work_sync in swr_down,to avoid race condition between skr_pa_event POST_PMD and swr_down.we are taking care of schedule_delayed_work and cancel_delayed_work_sync in PMU and PMD. Change-Id: I4f43ffc354ec930dabd7c4a8b2382f6064a24653 Signed-off-by: Prasad Kumpatla --- asoc/codecs/wsa881x.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/asoc/codecs/wsa881x.c b/asoc/codecs/wsa881x.c index adb4d91baf..401607731e 100644 --- a/asoc/codecs/wsa881x.c +++ b/asoc/codecs/wsa881x.c @@ -1614,8 +1614,6 @@ static int wsa881x_swr_down(struct swr_device *pdev) else wsa881x->state = WSA881X_DEV_DOWN; - if (delayed_work_pending(&wsa881x->ocp_ctl_work)) - cancel_delayed_work_sync(&wsa881x->ocp_ctl_work); return ret; } From 7b1cfaca64622112bdd703e5a20e2bf181dc592a Mon Sep 17 00:00:00 2001 From: Vignesh Kulothungan Date: Mon, 22 Jun 2020 23:47:41 -0700 Subject: [PATCH 102/116] ASoC: lahaina: add be dai link for DSD Add BE dai link LPASS_BE_RX_CDC_DMA_RX_5 for DSD playback usecase. Change-Id: Iacafab0131100ce6631c376b304f8a5006c326b7 Signed-off-by: Vignesh Kulothungan --- asoc/lahaina.c | 16 ++++++++++++++++ asoc/msm_dailink.h | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/asoc/lahaina.c b/asoc/lahaina.c index b50581987b..13aed6d546 100644 --- a/asoc/lahaina.c +++ b/asoc/lahaina.c @@ -4569,6 +4569,7 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, case MSM_BACKEND_DAI_RX_CDC_DMA_RX_1: case MSM_BACKEND_DAI_RX_CDC_DMA_RX_2: case MSM_BACKEND_DAI_RX_CDC_DMA_RX_3: + case MSM_BACKEND_DAI_RX_CDC_DMA_RX_5: case MSM_BACKEND_DAI_RX_CDC_DMA_RX_6: idx = msm_cdc_dma_get_idx_from_beid(dai_link->id); param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, @@ -6878,6 +6879,21 @@ static struct snd_soc_dai_link msm_rx_tx_cdc_dma_be_dai_links[] = { .ops = &msm_cdc_dma_be_ops, SND_SOC_DAILINK_REG(rx_dma_rx3), }, + { + .name = LPASS_BE_RX_CDC_DMA_RX_5, + .stream_name = "RX CDC DMA5 Playback", +#if IS_ENABLED(CONFIG_AUDIO_QGKI) + .dynamic_be = 1, +#endif /* CONFIG_AUDIO_QGKI */ + .no_pcm = 1, + .dpcm_playback = 1, + .id = MSM_BACKEND_DAI_RX_CDC_DMA_RX_5, + .be_hw_params_fixup = msm_be_hw_params_fixup, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + .ops = &msm_cdc_dma_be_ops, + SND_SOC_DAILINK_REG(rx_dma_rx5), + }, { .name = LPASS_BE_RX_CDC_DMA_RX_6, .stream_name = "RX CDC DMA6 Playback", diff --git a/asoc/msm_dailink.h b/asoc/msm_dailink.h index bfc56d41da..97d0f88d61 100644 --- a/asoc/msm_dailink.h +++ b/asoc/msm_dailink.h @@ -523,6 +523,12 @@ SND_SOC_DAILINK_DEFS(rx_dma_rx3, COMP_CODEC("wcd938x_codec", "wcd938x_cdc")), DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing"))); +SND_SOC_DAILINK_DEFS(rx_dma_rx5, + DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-cdc-dma-dev.45114")), + DAILINK_COMP_ARRAY(COMP_CODEC("bolero_codec", "rx_macro_rx5"), + COMP_CODEC("wcd938x_codec", "wcd938x_cdc")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing"))); + SND_SOC_DAILINK_DEFS(rx_dma_rx6, DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-cdc-dma-dev.45116")), DAILINK_COMP_ARRAY(COMP_CODEC("bolero_codec", "rx_macro_rx6"), From 39b18cbd388ac650cadf573b2facc8b3a24547a9 Mon Sep 17 00:00:00 2001 From: Vatsal Bucha Date: Mon, 22 Jun 2020 09:46:36 +0530 Subject: [PATCH 103/116] ASoC: bolero: Resolve glitch during amic record Glitch is observed during amic record due to improper sequence being followed. Reduce delay between toggle of hpf gate to depending on sample rate to resolve glitch. Change-Id: I8d9810dbc00264662f24532be9338198e6d7316d Signed-off-by: Vatsal Bucha --- asoc/codecs/bolero/tx-macro.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c index 55b2c3017b..903beb0a26 100644 --- a/asoc/codecs/bolero/tx-macro.c +++ b/asoc/codecs/bolero/tx-macro.c @@ -176,6 +176,7 @@ struct tx_macro_priv { int bcs_ch; bool bcs_clk_en; bool hs_slow_insert_complete; + int amic_sample_rate; }; static bool tx_macro_get_data(struct snd_soc_component *component, @@ -500,6 +501,29 @@ static void tx_macro_tx_hpf_corner_freq_callback(struct work_struct *work) hpf_cut_off_freq << 5); snd_soc_component_update_bits(component, hpf_gate_reg, 0x03, 0x02); + /* Add delay between toggle hpf gate based on sample rate */ + switch(tx_priv->amic_sample_rate) { + case 8000: + usleep_range(125, 130); + break; + case 16000: + usleep_range(62, 65); + break; + case 32000: + usleep_range(31, 32); + break; + case 48000: + usleep_range(20, 21); + break; + case 96000: + usleep_range(10, 11); + break; + case 192000: + usleep_range(5, 6); + break; + default: + usleep_range(125, 130); + } snd_soc_component_update_bits(component, hpf_gate_reg, 0x03, 0x01); } else { @@ -935,6 +959,7 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, u16 dec_cfg_reg = 0; u16 hpf_gate_reg = 0; u16 tx_gain_ctl_reg = 0; + u16 tx_fs_reg = 0; u8 hpf_cut_off_freq = 0; u16 adc_mux_reg = 0; int hpf_delay = TX_MACRO_DMIC_HPF_DELAY_MS; @@ -960,6 +985,11 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, TX_MACRO_TX_PATH_OFFSET * decimator; adc_mux_reg = BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1 + TX_MACRO_ADC_MUX_CFG_OFFSET * decimator; + tx_fs_reg = BOLERO_CDC_TX0_TX_PATH_CTL + + TX_MACRO_TX_PATH_OFFSET * decimator; + + tx_priv->amic_sample_rate = (snd_soc_component_read32(component, + tx_fs_reg) & 0x0F); switch (event) { case SND_SOC_DAPM_PRE_PMU: From ef02f940aeff568c0f89be6c7db84bda56e14ecf Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Thu, 25 Jun 2020 19:38:34 +0530 Subject: [PATCH 104/116] asoc: Add check for substream ref_count before access the substream. Add check for substream ref count before access the substream. Change-Id: Iccb6226519e8fddf624f82160a0d8d22641944db Signed-off-by: Prasad Kumpatla --- asoc/msm-pcm-loopback-v2.c | 34 ++++++++++++-------- asoc/msm-pcm-q6-noirq.c | 18 ++++++----- asoc/msm-pcm-q6-v2.c | 63 ++++++++++++++++++++++++++++---------- 3 files changed, 80 insertions(+), 35 deletions(-) diff --git a/asoc/msm-pcm-loopback-v2.c b/asoc/msm-pcm-loopback-v2.c index 2a48f19839..e62ae038a8 100644 --- a/asoc/msm-pcm-loopback-v2.c +++ b/asoc/msm-pcm-loopback-v2.c @@ -552,13 +552,15 @@ static int msm_pcm_volume_ctl_put(struct snd_kcontrol *kcontrol, goto exit; } mutex_lock(&loopback_session_lock); - prtd = substream->runtime->private_data; - if (!prtd) { - rc = -ENODEV; - mutex_unlock(&loopback_session_lock); - goto exit; + if (substream->ref_count > 0) { + prtd = substream->runtime->private_data; + if (!prtd) { + rc = -ENODEV; + mutex_unlock(&loopback_session_lock); + goto exit; + } + rc = pcm_loopback_set_volume(prtd, volume); } - rc = pcm_loopback_set_volume(prtd, volume); mutex_unlock(&loopback_session_lock); exit: return rc; @@ -584,13 +586,15 @@ static int msm_pcm_volume_ctl_get(struct snd_kcontrol *kcontrol, goto exit; } mutex_lock(&loopback_session_lock); - prtd = substream->runtime->private_data; - if (!prtd) { - rc = -ENODEV; - mutex_unlock(&loopback_session_lock); - goto exit; + if (substream->ref_count > 0) { + prtd = substream->runtime->private_data; + if (!prtd) { + rc = -ENODEV; + mutex_unlock(&loopback_session_lock); + goto exit; + } + ucontrol->value.integer.value[0] = prtd->volume; } - ucontrol->value.integer.value[0] = prtd->volume; mutex_unlock(&loopback_session_lock); exit: return rc; @@ -888,6 +892,12 @@ static int msm_pcm_channel_mixer_cfg_ctl_put(struct snd_kcontrol *kcontrol, chmixer_pspd); mutex_lock(&loopback_session_lock); + if (substream->ref_count <= 0) { + pr_err_ratelimited("%s: substream ref_count:%d invalid\n", + __func__, substream->ref_count); + mutex_unlock(&loopback_session_lock); + return -EINVAL; + } if (chmixer_pspd->enable && substream->runtime) { prtd = substream->runtime->private_data; if (!prtd) { diff --git a/asoc/msm-pcm-q6-noirq.c b/asoc/msm-pcm-q6-noirq.c index 59520581b8..1bccd9af2e 100644 --- a/asoc/msm-pcm-q6-noirq.c +++ b/asoc/msm-pcm-q6-noirq.c @@ -762,9 +762,11 @@ static int msm_pcm_volume_ctl_get(struct snd_kcontrol *kcontrol, return -ENODEV; } mutex_lock(&pdata->lock); - prtd = substream->runtime->private_data; - if (prtd) - ucontrol->value.integer.value[0] = prtd->volume; + if (substream->ref_count > 0) { + prtd = substream->runtime->private_data; + if (prtd) + ucontrol->value.integer.value[0] = prtd->volume; + } mutex_unlock(&pdata->lock); return 0; } @@ -807,10 +809,12 @@ static int msm_pcm_volume_ctl_put(struct snd_kcontrol *kcontrol, } mutex_lock(&pdata->lock); - prtd = substream->runtime->private_data; - if (prtd) { - rc = msm_pcm_set_volume(prtd, volume); - prtd->volume = volume; + if (substream->ref_count > 0) { + prtd = substream->runtime->private_data; + if (prtd) { + rc = msm_pcm_set_volume(prtd, volume); + prtd->volume = volume; + } } mutex_unlock(&pdata->lock); return rc; diff --git a/asoc/msm-pcm-q6-v2.c b/asoc/msm-pcm-q6-v2.c index 5762a95edb..d59148992f 100644 --- a/asoc/msm-pcm-q6-v2.c +++ b/asoc/msm-pcm-q6-v2.c @@ -1330,7 +1330,12 @@ static int msm_pcm_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol, ret = -EINVAL; goto done; } - + if (substream->ref_count <= 0) { + pr_err_ratelimited("%s substream ref_count:%d invalid\n", + __func__, substream->ref_count); + ret = -EINVAL; + goto done; + } prtd = substream->runtime->private_data; if (prtd == NULL) { pr_err("%s prtd is null.\n", __func__); @@ -1561,9 +1566,11 @@ static int msm_pcm_volume_ctl_get(struct snd_kcontrol *kcontrol, } mutex_lock(&pdata->lock); - prtd = substream->runtime->private_data; - if (prtd) - ucontrol->value.integer.value[0] = prtd->volume; + if (substream->ref_count > 0) { + prtd = substream->runtime->private_data; + if (prtd) + ucontrol->value.integer.value[0] = prtd->volume; + } mutex_unlock(&pdata->lock); return 0; } @@ -1607,10 +1614,12 @@ static int msm_pcm_volume_ctl_put(struct snd_kcontrol *kcontrol, } mutex_lock(&pdata->lock); - prtd = substream->runtime->private_data; - if (prtd) { - rc = msm_pcm_set_volume(prtd, volume); - prtd->volume = volume; + if (substream->ref_count > 0) { + prtd = substream->runtime->private_data; + if (prtd) { + rc = msm_pcm_set_volume(prtd, volume); + prtd->volume = volume; + } } mutex_unlock(&pdata->lock); return rc; @@ -1678,9 +1687,11 @@ static int msm_pcm_compress_ctl_get(struct snd_kcontrol *kcontrol, return 0; } mutex_lock(&pdata->lock); - prtd = substream->runtime->private_data; - if (prtd) - ucontrol->value.integer.value[0] = prtd->compress_enable; + if (substream->ref_count > 0) { + prtd = substream->runtime->private_data; + if (prtd) + ucontrol->value.integer.value[0] = prtd->compress_enable; + } mutex_unlock(&pdata->lock); return 0; } @@ -1710,11 +1721,13 @@ static int msm_pcm_compress_ctl_put(struct snd_kcontrol *kcontrol, return 0; } mutex_lock(&pdata->lock); - prtd = substream->runtime->private_data; - if (prtd) { - pr_debug("%s: setting compress flag to 0x%x\n", - __func__, compress); - prtd->compress_enable = compress; + if (substream->ref_count > 0) { + prtd = substream->runtime->private_data; + if (prtd) { + pr_debug("%s: setting compress flag to 0x%x\n", + __func__, compress); + prtd->compress_enable = compress; + } } mutex_unlock(&pdata->lock); return rc; @@ -1824,6 +1837,12 @@ static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol, return 0; mutex_lock(&pdata->lock); + if (substream->ref_count <= 0) { + pr_err_ratelimited("%s: substream ref_count:%d invalid\n", + __func__, substream->ref_count); + mutex_unlock(&pdata->lock); + return -EINVAL; + } prtd = substream->runtime ? substream->runtime->private_data : NULL; if (prtd) { prtd->set_channel_map = true; @@ -1891,6 +1910,12 @@ static int msm_pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol, return 0; /* no channels set */ mutex_lock(&pdata->lock); + if (substream->ref_count <= 0) { + pr_err_ratelimited("%s: substream ref_count:%d invalid\n", + __func__, substream->ref_count); + mutex_unlock(&pdata->lock); + return -EINVAL; + } prtd = substream->runtime ? substream->runtime->private_data : NULL; if (prtd && prtd->set_channel_map == true) { @@ -2180,6 +2205,12 @@ static int msm_pcm_channel_mixer_cfg_ctl_put(struct snd_kcontrol *kcontrol, } mutex_lock(&pdata->lock); + if (substream->ref_count <= 0) { + pr_err_ratelimited("%s: substream ref_count:%d invalid\n", + __func__, substream->ref_count); + mutex_unlock(&pdata->lock); + return -EINVAL; + } prtd = substream->runtime ? substream->runtime->private_data : NULL; if (chmixer_pspd->enable && prtd) { if (session_type == SESSION_TYPE_RX && From b5449b40d7e22dddf528b5afa34fcb41f4187afc Mon Sep 17 00:00:00 2001 From: Vatsal Bucha Date: Thu, 2 Jul 2020 18:52:46 +0530 Subject: [PATCH 105/116] ASoC: rouleur-mbhc: Fix aux cable detected as unsupported sometimes Aux cable is detected as unsupported sometimes due to it being detected as cross conn. Increase hph cross conn threshold to 350mV so that it detects fine. Change-Id: I87e4bd36f80d7cd62e06c76acf9c9d06bb6f148a Signed-off-by: Vatsal Bucha --- asoc/codecs/rouleur/rouleur-mbhc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/asoc/codecs/rouleur/rouleur-mbhc.c b/asoc/codecs/rouleur/rouleur-mbhc.c index f0eea091cb..c7ba03cd2b 100644 --- a/asoc/codecs/rouleur/rouleur-mbhc.c +++ b/asoc/codecs/rouleur/rouleur-mbhc.c @@ -33,8 +33,8 @@ #define ROULEUR_ZDET_C3 4500 /* Cross connection thresholds in mV */ -#define ROULEUR_HPHL_CROSS_CONN_THRESHOLD 200 -#define ROULEUR_HPHR_CROSS_CONN_THRESHOLD 200 +#define ROULEUR_HPHL_CROSS_CONN_THRESHOLD 350 +#define ROULEUR_HPHR_CROSS_CONN_THRESHOLD 350 static struct wcd_mbhc_register wcd_mbhc_registers[WCD_MBHC_REG_FUNC_MAX] = { From 248a1909811102ae6bc9c75055e26c1e928dd47f Mon Sep 17 00:00:00 2001 From: Meng Wang Date: Wed, 17 Jun 2020 14:54:05 +0800 Subject: [PATCH 106/116] ASoC: lahaina: start headset detection after soundcard is registered When soundcard registeration fails after headset IRQ is triggered, kernel panic may happen. Start headset detection after soundcard is registered in late_probe. Change-Id: Ibc5cebbf0e3331db1ec89fdcb9082029c510aaf7 Signed-off-by: Meng Wang --- asoc/lahaina.c | 59 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/asoc/lahaina.c b/asoc/lahaina.c index 2dd1624797..9c0129c2e6 100644 --- a/asoc/lahaina.c +++ b/asoc/lahaina.c @@ -7239,6 +7239,45 @@ static const struct of_device_id lahaina_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; + int ret = 0; + void *mbhc_calibration; + + 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) { + pr_err("%s component is NULL\n", __func__); + return -EINVAL; + } + + mbhc_calibration = def_wcd_mbhc_cal(); + if (!mbhc_calibration) + return -ENOMEM; + wcd_mbhc_cfg.calibration = mbhc_calibration; + 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 struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) { struct snd_soc_card *card = NULL; @@ -7417,6 +7456,7 @@ 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; @@ -7566,7 +7606,6 @@ static int msm_aux_codec_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_dapm_context *dapm = NULL; int ret = 0; int codec_variant = -1; - void *mbhc_calibration; struct snd_info_entry *entry; struct snd_card *card = NULL; struct msm_asoc_mach_data *pdata; @@ -7596,8 +7635,7 @@ static int msm_aux_codec_init(struct snd_soc_pcm_runtime *rtd) if (!entry) { dev_dbg(component->dev, "%s: Cannot create codecs module entry\n", __func__); - ret = 0; - goto mbhc_cfg_cal; + return 0; } pdata->codec_root = entry; } @@ -7620,22 +7658,7 @@ static int msm_aux_codec_init(struct snd_soc_pcm_runtime *rtd) return ret; } -mbhc_cfg_cal: - mbhc_calibration = def_wcd_mbhc_cal(); - if (!mbhc_calibration) - return -ENOMEM; - wcd_mbhc_cfg.calibration = mbhc_calibration; - 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 void msm_i2s_auxpcm_init(struct platform_device *pdev) From ed505121384d7a9ddeba79a5fc17ae4b0531c18c Mon Sep 17 00:00:00 2001 From: Harshal Ahire Date: Tue, 23 Jun 2020 11:18:01 +0530 Subject: [PATCH 107/116] dsp: fix compilation issue in dynamic load/unload BT modules Compilation issue addressed in failure case to load num_modules. Change-Id: Ieb923074a71f4ddc4c8da379b1169a06ce9267b6 --- dsp/q6afe.c | 2 +- dsp/q6core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dsp/q6afe.c b/dsp/q6afe.c index d20de05ca9..98f1aefd7c 100644 --- a/dsp/q6afe.c +++ b/dsp/q6afe.c @@ -281,7 +281,7 @@ static int q6afe_load_avcs_modules(int num_modules, u16 port_id, struct avcs_load_unload_modules_sec_payload sec_payload; if (num_modules <= 0) { - pr_err("%s: Invalid number of modules to load\n"); + pr_err("%s: Invalid number of modules to load\n", __func__); return -EINVAL; } diff --git a/dsp/q6core.c b/dsp/q6core.c index 6748b91951..8e8bedff42 100644 --- a/dsp/q6core.c +++ b/dsp/q6core.c @@ -937,7 +937,7 @@ int32_t q6core_avcs_load_unload_modules(struct avcs_load_unload_modules_payload int num_modules; if (payload == NULL) { - pr_err("%s: payload is null\n"); + pr_err("%s: payload is null\n", __func__); return -EINVAL; } From 68cbba47d0758a685535a28f3401bf0925e73039 Mon Sep 17 00:00:00 2001 From: Sudheer Papothi Date: Sat, 20 Jun 2020 07:53:09 -0700 Subject: [PATCH 108/116] Revert "ASoC: bolero: check clock source before clock switch" This reverts commit 93bc6299f399c0d1f2b333c9b57e0a772629d4c9 and 6cc7f52a6def45a332438209a9ee6804fa515a32. Change-Id: I614b650d6e071b9d1867988ebc88246b9fdc8f91 Signed-off-by: Sudheer Papothi --- asoc/codecs/bolero/bolero-cdc.c | 36 ------------------------- asoc/codecs/bolero/bolero-cdc.h | 13 --------- asoc/codecs/bolero/tx-macro.c | 31 ---------------------- asoc/codecs/bolero/va-macro.c | 47 ++------------------------------- 4 files changed, 2 insertions(+), 125 deletions(-) diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c index c46bcad0cd..df119c8847 100644 --- a/asoc/codecs/bolero/bolero-cdc.c +++ b/asoc/codecs/bolero/bolero-cdc.c @@ -644,7 +644,6 @@ int bolero_register_macro(struct device *dev, u16 macro_id, bolero_mclk_mux_tbl[macro_id][MCLK_MUX0]; if (macro_id == TX_MACRO) { priv->macro_params[macro_id].reg_wake_irq = ops->reg_wake_irq; - priv->macro_params[macro_id].clk_switch = ops->clk_switch; priv->macro_params[macro_id].reg_evt_listener = ops->reg_evt_listener; priv->macro_params[macro_id].clk_enable = ops->clk_enable; @@ -719,7 +718,6 @@ void bolero_unregister_macro(struct device *dev, u16 macro_id) priv->macro_params[macro_id].dev = NULL; if (macro_id == TX_MACRO) { priv->macro_params[macro_id].reg_wake_irq = NULL; - priv->macro_params[macro_id].clk_switch = NULL; priv->macro_params[macro_id].reg_evt_listener = NULL; priv->macro_params[macro_id].clk_enable = NULL; } @@ -1016,40 +1014,6 @@ int bolero_register_wake_irq(struct snd_soc_component *component, } EXPORT_SYMBOL(bolero_register_wake_irq); -/** - * bolero_tx_clk_switch - Switch tx macro clock - * - * @component: pointer to codec component instance. - * - * @clk_src: 0 for TX_RCG and 1 for VA_RCG - * - * Returns 0 on success or -EINVAL on error. - */ -int bolero_tx_clk_switch(struct snd_soc_component *component, int clk_src) -{ - struct bolero_priv *priv = NULL; - int ret = 0; - - if (!component) - return -EINVAL; - - priv = snd_soc_component_get_drvdata(component); - if (!priv) - return -EINVAL; - - if (!bolero_is_valid_codec_dev(priv->dev)) { - dev_err(component->dev, "%s: invalid codec\n", __func__); - return -EINVAL; - } - - if (priv->macro_params[TX_MACRO].clk_switch) - ret = priv->macro_params[TX_MACRO].clk_switch(component, - clk_src); - - return ret; -} -EXPORT_SYMBOL(bolero_tx_clk_switch); - /** * bolero_tx_mclk_enable - Enable/Disable TX Macro mclk * diff --git a/asoc/codecs/bolero/bolero-cdc.h b/asoc/codecs/bolero/bolero-cdc.h index 1f21fd69c8..f33589db56 100644 --- a/asoc/codecs/bolero/bolero-cdc.h +++ b/asoc/codecs/bolero/bolero-cdc.h @@ -37,11 +37,6 @@ enum { BOLERO_ADC_MAX }; -enum { - CLK_SRC_TX_RCG = 0, - CLK_SRC_VA_RCG, -}; - enum { BOLERO_MACRO_EVT_RX_MUTE = 1, /* for RX mute/unmute */ BOLERO_MACRO_EVT_IMPED_TRUE, /* for imped true */ @@ -76,7 +71,6 @@ struct macro_ops { int (*set_port_map)(struct snd_soc_component *component, u32 uc, u32 size, void *data); int (*clk_div_get)(struct snd_soc_component *component); - int (*clk_switch)(struct snd_soc_component *component, int clk_src); int (*reg_evt_listener)(struct snd_soc_component *component, bool en); int (*clk_enable)(struct snd_soc_component *c, bool en); char __iomem *io_base; @@ -102,7 +96,6 @@ void bolero_clear_amic_tx_hold(struct device *dev, u16 adc_n); int bolero_runtime_resume(struct device *dev); int bolero_runtime_suspend(struct device *dev); int bolero_set_port_map(struct snd_soc_component *component, u32 size, void *data); -int bolero_tx_clk_switch(struct snd_soc_component *component, int clk_src); int bolero_register_event_listener(struct snd_soc_component *component, bool enable); void bolero_wsa_pa_on(struct device *dev); @@ -170,12 +163,6 @@ static inline int bolero_set_port_map(struct snd_soc_component *component, return 0; } -static inline int bolero_tx_clk_switch(struct snd_soc_component *component, - int clk_src) -{ - return 0; -} - static inline int bolero_register_event_listener( struct snd_soc_component *component, bool enable) diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c index 55b2c3017b..1ae975e10b 100644 --- a/asoc/codecs/bolero/tx-macro.c +++ b/asoc/codecs/bolero/tx-macro.c @@ -2725,36 +2725,6 @@ static int tx_macro_clk_div_get(struct snd_soc_component *component) return tx_priv->dmic_clk_div; } -static int tx_macro_clk_switch(struct snd_soc_component *component, int clk_src) -{ - struct device *tx_dev = NULL; - struct tx_macro_priv *tx_priv = NULL; - int ret = 0; - - if (!component) - return -EINVAL; - - tx_dev = bolero_get_device_ptr(component->dev, TX_MACRO); - if (!tx_dev) { - dev_err(component->dev, - "%s: null device for macro!\n", __func__); - return -EINVAL; - } - tx_priv = dev_get_drvdata(tx_dev); - if (!tx_priv) { - dev_err(component->dev, - "%s: priv is null for macro!\n", __func__); - return -EINVAL; - } - if (tx_priv->swr_ctrl_data) { - ret = swrm_wcd_notify( - tx_priv->swr_ctrl_data[0].tx_swr_pdev, - SWR_REQ_CLK_SWITCH, &clk_src); - } - - return ret; -} - static int tx_macro_core_vote(void *handle, bool enable) { struct tx_macro_priv *tx_priv = (struct tx_macro_priv *) handle; @@ -3236,7 +3206,6 @@ static void tx_macro_init_ops(struct macro_ops *ops, ops->reg_wake_irq = tx_macro_reg_wake_irq; ops->set_port_map = tx_macro_set_port_map; ops->clk_div_get = tx_macro_clk_div_get; - ops->clk_switch = tx_macro_clk_switch; ops->reg_evt_listener = tx_macro_register_event_listener; ops->clk_enable = __tx_macro_mclk_enable; } diff --git a/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c index 710eb7190d..9efebe6c78 100644 --- a/asoc/codecs/bolero/va-macro.c +++ b/asoc/codecs/bolero/va-macro.c @@ -380,7 +380,6 @@ static int va_macro_swr_pwr_event_v2(struct snd_soc_dapm_widget *w, int ret = 0; struct device *va_dev = NULL; struct va_macro_priv *va_priv = NULL; - int clk_src = 0; if (!va_macro_get_data(component, &va_dev, &va_priv, __func__)) return -EINVAL; @@ -393,30 +392,12 @@ static int va_macro_swr_pwr_event_v2(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: - if (va_priv->swr_ctrl_data) { - clk_src = CLK_SRC_VA_RCG; - ret = swrm_wcd_notify( - va_priv->swr_ctrl_data[0].va_swr_pdev, - SWR_REQ_CLK_SWITCH, &clk_src); - if (ret) - dev_dbg(va_dev, "%s: clock switch failed\n", - __func__); - } msm_cdc_pinctrl_set_wakeup_capable( va_priv->va_swr_gpio_p, false); break; case SND_SOC_DAPM_POST_PMD: msm_cdc_pinctrl_set_wakeup_capable( va_priv->va_swr_gpio_p, true); - if (va_priv->swr_ctrl_data) { - clk_src = CLK_SRC_TX_RCG; - ret = swrm_wcd_notify( - va_priv->swr_ctrl_data[0].va_swr_pdev, - SWR_REQ_CLK_SWITCH, &clk_src); - if (ret) - dev_dbg(va_dev, "%s: clock switch failed\n", - __func__); - } break; default: dev_err(va_priv->dev, @@ -454,10 +435,6 @@ static int va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w, "%s: lpass audio hw enable failed\n", __func__); } - if (!ret) - if (bolero_tx_clk_switch(component, CLK_SRC_VA_RCG)) - dev_dbg(va_dev, "%s: clock switch failed\n", - __func__); if (va_priv->lpi_enable) { bolero_register_event_listener(component, true); va_priv->register_event_listener = true; @@ -468,8 +445,6 @@ static int va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w, va_priv->register_event_listener = false; bolero_register_event_listener(component, false); } - if (bolero_tx_clk_switch(component, CLK_SRC_TX_RCG)) - dev_dbg(va_dev, "%s: clock switch failed\n",__func__); if (va_priv->lpass_audio_hw_vote) digital_cdc_rsc_mgr_hw_vote_disable( va_priv->lpass_audio_hw_vote); @@ -509,7 +484,6 @@ static int va_macro_mclk_event(struct snd_soc_dapm_widget *w, int ret = 0; struct device *va_dev = NULL; struct va_macro_priv *va_priv = NULL; - int clk_src = 0; if (!va_macro_get_data(component, &va_dev, &va_priv, __func__)) return -EINVAL; @@ -530,27 +504,10 @@ static int va_macro_mclk_event(struct snd_soc_dapm_widget *w, ret = bolero_tx_mclk_enable(component, 1); break; case SND_SOC_DAPM_POST_PMD: - if (va_priv->lpi_enable) { - if (va_priv->version == BOLERO_VERSION_2_1) { - if (va_priv->swr_ctrl_data) { - clk_src = CLK_SRC_TX_RCG; - ret = swrm_wcd_notify( - va_priv->swr_ctrl_data[0].va_swr_pdev, - SWR_REQ_CLK_SWITCH, &clk_src); - if (ret) - dev_dbg(va_dev, - "%s: clock switch failed\n", - __func__); - } - } else if (bolero_tx_clk_switch(component, - CLK_SRC_TX_RCG)) { - dev_dbg(va_dev, "%s: clock switch failed\n", - __func__); - } + if (va_priv->lpi_enable) va_macro_mclk_enable(va_priv, 0, true); - } else { + else bolero_tx_mclk_enable(component, 0); - } if (va_priv->tx_clk_status > 0) { bolero_clk_rsc_request_clock(va_priv->dev, From b50df74ac48b7724ac9f062ba3a340c1af589eb8 Mon Sep 17 00:00:00 2001 From: Vignesh Kulothungan Date: Thu, 25 Jun 2020 23:46:12 -0700 Subject: [PATCH 109/116] ASoC: update swr dmic device down mechanism Add notification from wcd938x to sound wire dmics during SSR. Remove device down from dev ops to avoid deadlock scenarios. Change-Id: Ifdcbebb748c10deb89ad51ada1a8ce1cf33f2462 Signed-off-by: Vignesh Kulothungan --- asoc/codecs/swr-dmic.c | 79 +++++++++++++++------------------- asoc/codecs/wcd938x/internal.h | 3 ++ asoc/codecs/wcd938x/wcd938x.c | 48 ++++++++++++++++++++- asoc/codecs/wcd938x/wcd938x.h | 9 ++++ 4 files changed, 93 insertions(+), 46 deletions(-) diff --git a/asoc/codecs/swr-dmic.c b/asoc/codecs/swr-dmic.c index 20ae002d42..e7269e2729 100644 --- a/asoc/codecs/swr-dmic.c +++ b/asoc/codecs/swr-dmic.c @@ -31,6 +31,7 @@ #include "swr-dmic.h" #define NUM_ATTEMPTS 5 +#define SWRS_SCP_CONTROL 0x44 static int swr_master_channel_map[] = { ZERO, @@ -66,6 +67,7 @@ struct swr_dmic_priv { int is_en_supply; int port_type; u8 tx_master_port_map[SWR_DMIC_MAX_PORTS]; + struct notifier_block nblock; }; const char *codec_name_list[] = { @@ -245,38 +247,6 @@ static int dmic_swr_ctrl(struct snd_soc_dapm_widget *w, return ret; } -static int swr_dmic_enable_supply(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, - int event) -{ - struct snd_soc_component *component = - snd_soc_dapm_to_component(w->dapm); - struct swr_dmic_priv *swr_dmic = - snd_soc_component_get_drvdata(component); - int ret = 0; - - dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__, - w->name, event); - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - ret = swr_dmic_up(swr_dmic->swr_slave); - break; - case SND_SOC_DAPM_POST_PMU: - ret = swr_dmic_reset(swr_dmic->swr_slave); - break; - case SND_SOC_DAPM_POST_PMD: - ret = swr_dmic_down(swr_dmic->swr_slave); - break; - } - - if (ret) - dev_dbg(component->dev, "%s wname: %s event: %d ret : %d\n", - __func__, w->name, event, ret); - - return ret; -} - static const char * const tx_master_port_text[] = { "ZERO", "SWRM_TX1_CH1", "SWRM_TX1_CH2", "SWRM_TX1_CH3", "SWRM_TX1_CH4", "SWRM_TX2_CH1", "SWRM_TX2_CH2", "SWRM_TX2_CH3", "SWRM_TX2_CH4", @@ -306,10 +276,6 @@ static const struct snd_soc_dapm_widget swr_dmic_dapm_widgets[] = { SND_SOC_DAPM_INPUT("SWR_DMIC"), - SND_SOC_DAPM_SUPPLY_S("SMIC_SUPPLY", 1, SND_SOC_NOPM, 0, 0, - swr_dmic_enable_supply, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | - SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_OUT_DRV_E("SMIC_PORT_EN", SND_SOC_NOPM, 0, 0, NULL, 0, swr_dmic_port_enable, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), @@ -317,7 +283,6 @@ static const struct snd_soc_dapm_widget swr_dmic_dapm_widgets[] = { }; static const struct snd_soc_dapm_route swr_dmic_audio_map[] = { - {"SWR_DMIC", NULL, "SMIC_SUPPLY"}, {"SWR_DMIC_MIXER", "Switch", "SWR_DMIC"}, {"SMIC_PORT_EN", NULL, "SWR_DMIC_MIXER"}, {"SWR_DMIC_OUTPUT", NULL, "SMIC_PORT_EN"}, @@ -393,6 +358,8 @@ static int enable_wcd_codec_supply(struct swr_dmic_priv *swr_dmic, bool enable) pr_err("%s: component is NULL\n", __func__); return -EINVAL; } + dev_dbg(component->dev, "%s: supply %d micbias: %d enable: %d\n", + __func__, swr_dmic->is_en_supply, micb_num, enable); if (enable) rc = wcd938x_codec_force_enable_micbias_v2(component, @@ -441,6 +408,29 @@ static struct snd_soc_dai_driver swr_dmic_dai[] = { }, }; +static int swr_dmic_event_notify(struct notifier_block *block, + unsigned long val, + void *data) +{ + u16 event = (val & 0xffff); + int ret = 0; + struct swr_dmic_priv *swr_dmic = container_of(block, + struct swr_dmic_priv, + nblock); + switch (event) { + case WCD938X_EVT_SSR_DOWN: + ret = swr_dmic_down(swr_dmic->swr_slave); + break; + case WCD938X_EVT_SSR_UP: + ret = swr_dmic_up(swr_dmic->swr_slave); + if (!ret) + ret = swr_dmic_reset(swr_dmic->swr_slave); + break; + } + + return ret; +} + static int swr_dmic_probe(struct swr_device *pdev) { int ret = 0; @@ -526,7 +516,7 @@ static int swr_dmic_probe(struct swr_device *pdev) "%s get devnum %d for dev addr %llx failed\n", __func__, swr_devnum, pdev->addr); ret = -EPROBE_DEFER; - goto err; + goto dev_err; } pdev->dev_num = swr_devnum; @@ -596,10 +586,9 @@ static int swr_dmic_probe(struct swr_device *pdev) strlen(swr_dmic_name_prefix_of) + 1); component->name_prefix = prefix_name; - if (swr_dmic->is_en_supply == 1) { - enable_wcd_codec_supply(swr_dmic, false); - --swr_dmic->is_en_supply; - } + swr_dmic->nblock.notifier_call = swr_dmic_event_notify; + wcd938x_swr_dmic_register_notifier(swr_dmic->supply_component, + &swr_dmic->nblock, true); return 0; @@ -624,7 +613,10 @@ static int swr_dmic_remove(struct swr_device *pdev) dev_err(&pdev->dev, "%s: swr_dmic is NULL\n", __func__); return -EINVAL; } - + if (swr_dmic->is_en_supply == 1) { + enable_wcd_codec_supply(swr_dmic, false); + --swr_dmic->is_en_supply; + } snd_soc_unregister_component(&pdev->dev); swr_set_dev_data(pdev, NULL); return 0; @@ -743,7 +735,6 @@ static struct swr_driver swr_dmic_driver = { .probe = swr_dmic_probe, .remove = swr_dmic_remove, .id_table = swr_dmic_id, - .device_down = swr_dmic_down, }; static int __init swr_dmic_init(void) diff --git a/asoc/codecs/wcd938x/internal.h b/asoc/codecs/wcd938x/internal.h index 84a8a42409..dc668e95a0 100644 --- a/asoc/codecs/wcd938x/internal.h +++ b/asoc/codecs/wcd938x/internal.h @@ -106,6 +106,9 @@ struct wcd938x_priv { bool dev_up; u8 tx_master_ch_map[WCD938X_MAX_SLAVE_CH_TYPES]; bool usbc_hs_status; + /* wcd to swr dmic notification */ + bool notify_swr_dmic; + struct blocking_notifier_head notifier; }; struct wcd938x_micbias_setting { diff --git a/asoc/codecs/wcd938x/wcd938x.c b/asoc/codecs/wcd938x/wcd938x.c index bb07fb9cec..e738264dc0 100644 --- a/asoc/codecs/wcd938x/wcd938x.c +++ b/asoc/codecs/wcd938x/wcd938x.c @@ -2033,6 +2033,27 @@ static bool get_usbc_hs_status(struct snd_soc_component *component, return false; } +int wcd938x_swr_dmic_register_notifier(struct snd_soc_component *component, + struct notifier_block *nblock, + bool enable) +{ + struct wcd938x_priv *wcd938x_priv; + if(NULL == component) { + pr_err("%s: wcd938x component is NULL\n", __func__); + return -EINVAL; + } + + wcd938x_priv = snd_soc_component_get_drvdata(component); + wcd938x_priv->notify_swr_dmic = enable; + if (enable) + return blocking_notifier_chain_register(&wcd938x_priv->notifier, + nblock); + else + return blocking_notifier_chain_unregister( + &wcd938x_priv->notifier, nblock); +} +EXPORT_SYMBOL(wcd938x_swr_dmic_register_notifier); + static int wcd938x_event_notify(struct notifier_block *block, unsigned long val, void *data) @@ -2080,6 +2101,10 @@ static int wcd938x_event_notify(struct notifier_block *block, break; case BOLERO_WCD_EVT_SSR_DOWN: wcd938x->dev_up = false; + if(wcd938x->notify_swr_dmic) + blocking_notifier_call_chain(&wcd938x->notifier, + WCD938X_EVT_SSR_DOWN, + NULL); wcd938x->mbhc->wcd_mbhc.deinit_in_progress = true; wcd938x->mbhc->wcd_mbhc.plug_before_ssr = wcd938x->mbhc->wcd_mbhc.current_plug; @@ -2113,6 +2138,10 @@ static int wcd938x_event_notify(struct notifier_block *block, } wcd938x->mbhc->wcd_mbhc.deinit_in_progress = false; wcd938x->dev_up = true; + if(wcd938x->notify_swr_dmic) + blocking_notifier_call_chain(&wcd938x->notifier, + WCD938X_EVT_SSR_UP, + NULL); break; case BOLERO_WCD_EVT_CLK_NOTIFY: snd_soc_component_update_bits(component, @@ -2296,6 +2325,9 @@ static int wcd938x_enable_micbias(struct wcd938x_priv *wcd938x, return -EINVAL; }; + pr_debug("%s: req: %d micb_num: %d micb_ref: %d pullup_ref: %d\n", + __func__, req, micb_num, wcd938x->micb_ref[micb_index], + wcd938x->pullup_ref[micb_index]); mutex_lock(&wcd938x->micb_lock); switch (req) { @@ -2360,6 +2392,8 @@ int wcd938x_codec_force_enable_micbias_v2(struct snd_soc_component *component, int event, int micb_num) { struct wcd938x_priv *wcd938x_priv = NULL; + int ret = 0; + int micb_index = micb_num - 1; if(NULL == component) { pr_err("%s: wcd938x component is NULL\n", __func__); @@ -2376,6 +2410,15 @@ int wcd938x_codec_force_enable_micbias_v2(struct snd_soc_component *component, wcd938x_priv = snd_soc_component_get_drvdata(component); + if (!wcd938x_priv->dev_up) { + if ((wcd938x_priv->pullup_ref[micb_index] > 0) && + (event == SND_SOC_DAPM_POST_PMD)) { + wcd938x_priv->pullup_ref[micb_index]--; + ret = -ENODEV; + goto done; + } + } + switch (event) { case SND_SOC_DAPM_PRE_PMU: wcd938x_wakeup(wcd938x_priv, true); @@ -2389,7 +2432,8 @@ int wcd938x_codec_force_enable_micbias_v2(struct snd_soc_component *component, break; } - return 0; +done: + return ret; } EXPORT_SYMBOL(wcd938x_codec_force_enable_micbias_v2); @@ -3728,7 +3772,6 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component) return ret; } } - wcd938x->dev_up = true; return ret; err_hwdep: @@ -4088,6 +4131,7 @@ static int wcd938x_bind(struct device *dev) __func__); goto err_irq; } + wcd938x->dev_up = true; return ret; err_irq: diff --git a/asoc/codecs/wcd938x/wcd938x.h b/asoc/codecs/wcd938x/wcd938x.h index bf952055e8..1cc8c7d859 100644 --- a/asoc/codecs/wcd938x/wcd938x.h +++ b/asoc/codecs/wcd938x/wcd938x.h @@ -17,6 +17,12 @@ enum { WCD9385 = 5, }; +/* from WCD to SWR DMIC events */ +enum { + WCD938X_EVT_SSR_DOWN, + WCD938X_EVT_SSR_UP, +}; + struct swr_slave_ch_map { u8 ch_type; u8 index; @@ -62,6 +68,9 @@ int wcd938x_info_create_codec_entry(struct snd_info_entry *codec_root, int wcd938x_get_codec_variant(struct snd_soc_component *component); int wcd938x_codec_force_enable_micbias_v2(struct snd_soc_component *wcd938x, int event, int micb_num); +int wcd938x_swr_dmic_register_notifier(struct snd_soc_component *wcd938x, + struct notifier_block *nblock, + bool enable); static inline int wcd938x_slave_get_master_ch_val(int ch) { From db0cc84eb7bcb5066684a45d1a49a3045495f990 Mon Sep 17 00:00:00 2001 From: Sudheer Papothi Date: Sat, 20 Jun 2020 20:56:41 +0530 Subject: [PATCH 110/116] soc: soundwire: Enable audio core voting Audio core vote enables soundwire master and establishes soundwire link without which soundwire master will not power up. This change votes for audio core during soundwire runtime resume and unvotes during soundwire runtime suspend. Change-Id: I3ca283be42670a56102c4f08c0f207ae9dc4e5c3 Signed-off-by: Sudheer Papothi --- soc/swr-mstr-ctrl.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index 0207a9e3fc..540608dad4 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -2672,6 +2672,8 @@ static int swrm_probe(struct platform_device *pdev) * controller will be up now */ swr_master_add_boarddevices(&swrm->master); + if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, true)) + dev_dbg(&pdev->dev, "%s: Audio HW Vote is failed\n", __func__); mutex_lock(&swrm->mlock); swrm_clk_request(swrm, true); swrm->version = swr_master_read(swrm, SWRM_COMP_HW_VERSION); @@ -2812,7 +2814,6 @@ static int swrm_runtime_resume(struct device *dev) int ret = 0; bool swrm_clk_req_err = false; bool hw_core_err = false; - bool aud_core_err = false; struct swr_master *mstr = &swrm->master; struct swr_device *swr_dev; u32 temp = 0; @@ -2828,11 +2829,9 @@ static int swrm_runtime_resume(struct device *dev) __func__); hw_core_err = true; } - if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, true)) { + if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, true)) dev_err(dev, "%s:lpass audio hw enable failed\n", __func__); - aud_core_err = true; - } if ((swrm->state == SWR_MSTR_DOWN) || (swrm->state == SWR_MSTR_SSR && swrm->dev_up)) { @@ -2923,8 +2922,6 @@ static int swrm_runtime_resume(struct device *dev) swrm->state = SWR_MSTR_UP; } exit: - if (!aud_core_err) - swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false); if (!hw_core_err) swrm_request_hw_vote(swrm, LPASS_HW_CORE, false); if (swrm_clk_req_err) @@ -2948,7 +2945,6 @@ static int swrm_runtime_suspend(struct device *dev) struct swr_mstr_ctrl *swrm = platform_get_drvdata(pdev); int ret = 0; bool hw_core_err = false; - bool aud_core_err = false; struct swr_master *mstr = &swrm->master; struct swr_device *swr_dev; int current_state = 0; @@ -2967,11 +2963,6 @@ static int swrm_runtime_suspend(struct device *dev) __func__); hw_core_err = true; } - if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, true)) { - dev_err(dev, "%s:lpass audio hw enable failed\n", - __func__); - aud_core_err = true; - } if ((current_state == SWR_MSTR_UP) || (current_state == SWR_MSTR_SSR)) { @@ -3049,12 +3040,14 @@ static int swrm_runtime_suspend(struct device *dev) } } + if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false)) + dev_dbg(dev, "%s:lpass audio hw enable failed\n", + __func__); + /* Retain SSR state until resume */ if (current_state != SWR_MSTR_SSR) swrm->state = SWR_MSTR_DOWN; exit: - if (!aud_core_err) - swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false); if (!hw_core_err) swrm_request_hw_vote(swrm, LPASS_HW_CORE, false); mutex_unlock(&swrm->reslock); From b9ff5ac5b0f7e9a29df86a128c29fe22575f7881 Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Wed, 1 Jul 2020 23:37:33 +0530 Subject: [PATCH 111/116] asoc: bolero: Ensure va-macro is registered before other macros As va-macro has fs_clk gen, ensure va-macro is registered before other macros. Change-Id: I8283dc11817caf0c208fe231132951a7a79b7d51 Signed-off-by: Laxminath Kasam --- asoc/codecs/bolero/bolero-cdc.c | 24 +++++++++++++++++++++++- asoc/codecs/bolero/bolero-cdc.h | 6 ++++++ asoc/codecs/bolero/rx-macro.c | 6 ++++++ asoc/codecs/bolero/tx-macro.c | 6 ++++++ asoc/codecs/bolero/wsa-macro.c | 7 +++++++ 5 files changed, 48 insertions(+), 1 deletion(-) diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c index c46bcad0cd..7bde8430ac 100644 --- a/asoc/codecs/bolero/bolero-cdc.c +++ b/asoc/codecs/bolero/bolero-cdc.c @@ -600,6 +600,28 @@ int bolero_dmic_clk_enable(struct snd_soc_component *component, } EXPORT_SYMBOL(bolero_dmic_clk_enable); +bool bolero_is_va_macro_registered(struct device *dev) +{ + struct bolero_priv *priv; + + if (!dev) { + pr_err("%s: dev is null\n", __func__); + return false; + } + if (!bolero_is_valid_child_dev(dev)) { + dev_err(dev, "%s: child device calling is not added yet\n", + __func__); + return false; + } + priv = dev_get_drvdata(dev->parent); + if (!priv) { + dev_err(dev, "%s: priv is null\n", __func__); + return false; + } + return priv->macros_supported[VA_MACRO]; +} +EXPORT_SYMBOL(bolero_is_va_macro_registered); + /** * bolero_register_macro - Registers macro to bolero * @@ -661,7 +683,7 @@ int bolero_register_macro(struct device *dev, u16 macro_id, priv->num_macros_registered++; priv->macros_supported[macro_id] = true; - dev_dbg(dev, "%s: register macro successful:%d\n", macro_id); + dev_info(dev, "%s: register macro successful:%d\n", __func__, macro_id); if (priv->num_macros_registered == priv->num_macros) { ret = bolero_copy_dais_from_macro(priv); diff --git a/asoc/codecs/bolero/bolero-cdc.h b/asoc/codecs/bolero/bolero-cdc.h index 1f21fd69c8..0a4101eca0 100644 --- a/asoc/codecs/bolero/bolero-cdc.h +++ b/asoc/codecs/bolero/bolero-cdc.h @@ -89,6 +89,7 @@ typedef int (*rsc_clk_cb_t)(struct device *dev, u16 event); #if IS_ENABLED(CONFIG_SND_SOC_BOLERO) int bolero_register_res_clk(struct device *dev, rsc_clk_cb_t cb); void bolero_unregister_res_clk(struct device *dev); +bool bolero_is_va_macro_registered(struct device *dev); int bolero_register_macro(struct device *dev, u16 macro_id, struct macro_ops *ops); void bolero_unregister_macro(struct device *dev, u16 macro_id); @@ -120,6 +121,11 @@ static inline void bolero_unregister_res_clk(struct device *dev) { } +static bool bolero_is_va_macro_registered(struct device *dev) +{ + return false; +} + static inline int bolero_register_macro(struct device *dev, u16 macro_id, struct macro_ops *ops) diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c index 87c9477ad1..dd78cf0baf 100644 --- a/asoc/codecs/bolero/rx-macro.c +++ b/asoc/codecs/bolero/rx-macro.c @@ -4028,6 +4028,12 @@ static int rx_macro_probe(struct platform_device *pdev) u32 is_used_rx_swr_gpio = 1; const char *is_used_rx_swr_gpio_dt = "qcom,is-used-swr-gpio"; + if (!bolero_is_va_macro_registered(&pdev->dev)) { + dev_err(&pdev->dev, + "%s: va-macro not registered yet, defer\n", __func__); + return -EPROBE_DEFER; + } + rx_priv = devm_kzalloc(&pdev->dev, sizeof(struct rx_macro_priv), GFP_KERNEL); if (!rx_priv) diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c index 55b2c3017b..a2816c42d4 100644 --- a/asoc/codecs/bolero/tx-macro.c +++ b/asoc/codecs/bolero/tx-macro.c @@ -3252,6 +3252,12 @@ static int tx_macro_probe(struct platform_device *pdev) u32 is_used_tx_swr_gpio = 1; const char *is_used_tx_swr_gpio_dt = "qcom,is-used-swr-gpio"; + if (!bolero_is_va_macro_registered(&pdev->dev)) { + dev_err(&pdev->dev, + "%s: va-macro not registered yet, defer\n", __func__); + return -EPROBE_DEFER; + } + tx_priv = devm_kzalloc(&pdev->dev, sizeof(struct tx_macro_priv), GFP_KERNEL); if (!tx_priv) diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c index 5c59d6de4f..b8ef8afabc 100644 --- a/asoc/codecs/bolero/wsa-macro.c +++ b/asoc/codecs/bolero/wsa-macro.c @@ -3139,6 +3139,12 @@ static int wsa_macro_probe(struct platform_device *pdev) u32 is_used_wsa_swr_gpio = 1; const char *is_used_wsa_swr_gpio_dt = "qcom,is-used-swr-gpio"; + if (!bolero_is_va_macro_registered(&pdev->dev)) { + dev_err(&pdev->dev, + "%s: va-macro not registered yet, defer\n", __func__); + return -EPROBE_DEFER; + } + wsa_priv = devm_kzalloc(&pdev->dev, sizeof(struct wsa_macro_priv), GFP_KERNEL); if (!wsa_priv) @@ -3224,6 +3230,7 @@ static int wsa_macro_probe(struct platform_device *pdev) wsa_macro_init_ops(&ops, wsa_io_base); ops.clk_id_req = wsa_priv->default_clk_id; ops.default_clk_id = wsa_priv->default_clk_id; + ret = bolero_register_macro(&pdev->dev, WSA_MACRO, &ops); if (ret < 0) { dev_err(&pdev->dev, "%s: register macro failed\n", __func__); From 02aa9f5f33245d9a0ac638384292c9dab8053e8d Mon Sep 17 00:00:00 2001 From: Dhananjay Kumar Date: Thu, 9 Jul 2020 00:01:35 +0530 Subject: [PATCH 112/116] dsp: voice: Reset music_info on SSR Reset music_info playback states during SSR to fix incall music session failure after SSR. Music delivery session requests are getting ignored if the state is not reset. Change-Id: I7dd736baa538fb3697c874230c5a9c02f90b6a06 Signed-off-by: Dhananjay Kumar --- dsp/q6voice.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dsp/q6voice.c b/dsp/q6voice.c index 5e90104bee..dbf038dfcf 100644 --- a/dsp/q6voice.c +++ b/dsp/q6voice.c @@ -515,6 +515,8 @@ static void voc_set_error_state(uint16_t reset_proc) if (v != NULL) { v->voc_state = VOC_ERROR; v->rec_info.recording = 0; + v->music_info.playing = 0; + v->music_info.force = 0; } } } From 87f632b0bed388a2200cfd89e41aea4d4b1c02f2 Mon Sep 17 00:00:00 2001 From: Meng Wang Date: Thu, 9 Jul 2020 08:37:07 +0800 Subject: [PATCH 113/116] asoc: add MM31 playback on USB and BT devices Add MM31 playback on USB and BT devices. Change-Id: I6b3f4b615b4b3923569e14b57ce091e015b7f493 Signed-off-by: Meng Wang --- asoc/msm-pcm-routing-v2.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c index c397dc4175..549f5fbef0 100644 --- a/asoc/msm-pcm-routing-v2.c +++ b/asoc/msm-pcm-routing-v2.c @@ -9106,6 +9106,10 @@ static const struct snd_kcontrol_new usb_audio_rx_mixer_controls[] = { MSM_BACKEND_DAI_USB_RX, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia31", SND_SOC_NOPM, + MSM_BACKEND_DAI_USB_RX, + MSM_FRONTEND_DAI_MULTIMEDIA31, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new int_bt_sco_rx_mixer_controls[] = { @@ -9201,6 +9205,10 @@ static const struct snd_kcontrol_new int_bt_sco_rx_mixer_controls[] = { MSM_BACKEND_DAI_INT_BT_SCO_RX, MSM_FRONTEND_DAI_MULTIMEDIA30, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia31", SND_SOC_NOPM, + MSM_BACKEND_DAI_INT_BT_SCO_RX, + MSM_FRONTEND_DAI_MULTIMEDIA31, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new int_bt_a2dp_rx_mixer_controls[] = { @@ -9272,6 +9280,10 @@ static const struct snd_kcontrol_new int_bt_a2dp_rx_mixer_controls[] = { MSM_BACKEND_DAI_INT_BT_A2DP_RX, MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_DOUBLE_EXT("MultiMedia31", SND_SOC_NOPM, + MSM_BACKEND_DAI_INT_BT_A2DP_RX, + MSM_FRONTEND_DAI_MULTIMEDIA31, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new int_fm_rx_mixer_controls[] = { @@ -26108,6 +26120,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"SLIMBUS_7_RX Audio Mixer", "MultiMedia15", "MM_DL15"}, {"SLIMBUS_7_RX Audio Mixer", "MultiMedia16", "MM_DL16"}, {"SLIMBUS_7_RX Audio Mixer", "MultiMedia26", "MM_DL26"}, + {"SLIMBUS_7_RX Audio Mixer", "MultiMedia31", "MM_DL31"}, {"SLIMBUS_7_RX", NULL, "SLIMBUS_7_RX Audio Mixer"}, {"SLIMBUS_9_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, @@ -26146,6 +26159,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"USB_AUDIO_RX Audio Mixer", "MultiMedia15", "MM_DL15"}, {"USB_AUDIO_RX Audio Mixer", "MultiMedia16", "MM_DL16"}, {"USB_AUDIO_RX Audio Mixer", "MultiMedia26", "MM_DL26"}, + {"USB_AUDIO_RX Audio Mixer", "MultiMedia31", "MM_DL31"}, {"USB_AUDIO_RX", NULL, "USB_AUDIO_RX Audio Mixer"}, {"MultiMedia1 Mixer", "VOC_REC_UL", "INCALL_RECORD_TX"}, From f82b056a61d23639a739eff35dc218bbedb85970 Mon Sep 17 00:00:00 2001 From: Surendar karka Date: Fri, 10 Jul 2020 15:58:21 +0530 Subject: [PATCH 114/116] asoc: update error check to avoid fix crash issues During negative test case if the backend index is out of range we will observe crash issues, update error check to avoid crashes. Change-Id: I07531ee538013841f93acd02537ac5a7c1e350ba Signed-off-by: Surendar karka --- asoc/msm-pcm-routing-v2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c index c397dc4175..e95e17c740 100644 --- a/asoc/msm-pcm-routing-v2.c +++ b/asoc/msm-pcm-routing-v2.c @@ -30515,7 +30515,7 @@ static int msm_routing_put_pll_clk_drift(struct snd_kcontrol *kcontrol, clk_drift = ucontrol->value.integer.value[1]; clk_reset = ucontrol->value.integer.value[2]; - if (be_idx < 0 && be_idx >= MSM_BACKEND_DAI_MAX) { + if (be_idx < 0 || be_idx >= MSM_BACKEND_DAI_MAX) { pr_err("%s: Invalid be id %d\n", __func__, be_idx); return -EINVAL; } From de83e87f07f614f7008361a62016bd8c20fb1c2b Mon Sep 17 00:00:00 2001 From: Sudheer Papothi Date: Wed, 1 Jul 2020 13:43:31 +0530 Subject: [PATCH 115/116] ASoC: wsa-macro: Add core vote before accessing registers Add core vote before accessing registers to avoid unclocked access. Change-Id: I02ce78d71787f5a12c44cd3194dde62682f20037 Signed-off-by: Sudheer Papothi --- asoc/codecs/bolero/wsa-macro.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c index 5c59d6de4f..ca25ff8ac4 100644 --- a/asoc/codecs/bolero/wsa-macro.c +++ b/asoc/codecs/bolero/wsa-macro.c @@ -2008,10 +2008,12 @@ static int wsa_macro_set_rx_mute_status(struct snd_kcontrol *kcontrol, int value = ucontrol->value.integer.value[0]; int wsa_rx_shift = ((struct soc_multi_mixer_control *) kcontrol->private_value)->shift; + int ret = 0; if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__)) return -EINVAL; + pm_runtime_get_sync(wsa_priv->dev); switch (wsa_rx_shift) { case 0: snd_soc_component_update_bits(component, @@ -2036,13 +2038,16 @@ static int wsa_macro_set_rx_mute_status(struct snd_kcontrol *kcontrol, default: pr_err("%s: invalid argument rx_shift = %d\n", __func__, wsa_rx_shift); - return -EINVAL; + ret = -EINVAL; } + pm_runtime_mark_last_busy(wsa_priv->dev); + pm_runtime_put_autosuspend(wsa_priv->dev); dev_dbg(component->dev, "%s: WSA Digital Mute RX %d Enable %d\n", __func__, wsa_rx_shift, value); wsa_priv->wsa_digital_mute_status[wsa_rx_shift] = value; - return 0; + + return ret; } static int wsa_macro_get_compander(struct snd_kcontrol *kcontrol, From e0e3201a645b245c0216a0e1c9251fc23d0c9ccc Mon Sep 17 00:00:00 2001 From: Kunlei Zhang Date: Tue, 30 Jun 2020 21:05:46 +0800 Subject: [PATCH 116/116] asoc: kona: update sound wire port frame config routing update sound wire port frame config routing to ensure use correct port config for device with no WCD. Change-Id: I1746323230064f51020850cf8e1dbf2c29977bed Signed-off-by: Kunlei Zhang --- asoc/kona.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/asoc/kona.c b/asoc/kona.c index 0184e95c6d..5ac16783f1 100644 --- a/asoc/kona.c +++ b/asoc/kona.c @@ -5444,6 +5444,7 @@ static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_component *aux_comp; struct platform_device *pdev = NULL; int i = 0; + bool is_wcd937x_used = false; char *data = NULL; struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(rtd->card); @@ -5545,33 +5546,29 @@ static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd) if (data != NULL) { if (!strncmp(data, "wcd937x", sizeof("wcd937x"))) { - bolero_set_port_map(component, - ARRAY_SIZE(sm_port_map_wcd937x), - sm_port_map_wcd937x); - break; - } else if (!strncmp( data, "wcd938x", - sizeof("wcd938x"))) { - 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); - } + 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",