diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2023-03-13 14:48:08 -0700 |
---|---|---|
committer | Linux Build Service Account <lnxbuild@localhost> | 2023-03-13 14:48:08 -0700 |
commit | 8034b967ded5d437871f09b60fe4fee9e9cd7cdd (patch) | |
tree | 016f6ddeb3571d624c597cae599a8f0d91a74194 | |
parent | 811602cdcc3fdac1038ac103c411740d178df601 (diff) | |
parent | b8a40052aede8eaeb6ba4f03fbcefc6f8c68832a (diff) | |
download | msm-extra-8034b967ded5d437871f09b60fe4fee9e9cd7cdd.tar.gz |
Merge b8a40052aede8eaeb6ba4f03fbcefc6f8c68832a on remote branch
Change-Id: I92fa760d5b3af415a71f0446605b1c8e1491dae6
35 files changed, 1329 insertions, 266 deletions
@@ -20,13 +20,14 @@ endif ifeq ($(ENABLE_AUDIO_LEGACY_TECHPACK),true) include $(call all-subdir-makefiles) +LOCAL_PATH := vendor/qcom/opensource/audio-kernel endif BOARD_OPENSOURCE_DIR ?= vendor/qcom/opensource BOARD_COMMON_DIR ?= device/qcom/common # Build/Package only in case of supported target -ifeq ($(call is-board-platform-in-list,taro kalama bengal monaco), true) +ifeq ($(call is-board-platform-in-list,taro kalama bengal monaco msmnile), true) # This makefile is only for DLKM ifneq ($(findstring vendor,$(LOCAL_PATH)),) @@ -49,6 +50,15 @@ KBUILD_OPTIONS := AUDIO_ROOT=$(AUDIO_BLD_DIR) KBUILD_OPTIONS += MODNAME=audio_dlkm KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM) KBUILD_OPTIONS += $(AUDIO_SELECT) +ifeq ($(call is-board-platform-in-list, msmnile),true) +KBUILD_OPTIONS += CONFIG_SND_SOC_AUTO=y +ifneq (,$(filter $(TARGET_BOARD_PLATFORM)$(TARGET_BOARD_SUFFIX), msmnile_gvmq)) +KBUILD_OPTIONS +=CONFIG_SND_SOC_GVM=y +else +KBUILD_OPTIONS += CONFIG_SND_SOC_SA8155=m +endif +endif + KBUILD_OPTIONS += KBUILD_EXTRA_SYMBOLS=$(PWD)/$(call intermediates-dir-for,DLKM,msm-ext-disp-module-symvers)/Module.symvers AUDIO_SRC_FILES := \ @@ -57,8 +67,27 @@ AUDIO_SRC_FILES := \ $(wildcard $(LOCAL_PATH)/*/*/*) \ $(wildcard $(LOCAL_PATH)/*/*/*/*) +ifneq (,$(filter $(TARGET_BOARD_PLATFORM)$(TARGET_BOARD_SUFFIX), msmnile_gvmq)) +include $(CLEAR_VARS) +LOCAL_SRC_FILES := $(AUDIO_SRC_FILES) +LOCAL_MODULE := stub_dlkm.ko +LOCAL_MODULE_KBUILD_NAME := asoc/codecs/stub_dlkm.ko +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_DEBUG_ENABLE := true +LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) +include $(DLKM_DIR)/Build_external_kernelmodule.mk +########################### ASOC MACHINE ################################ +include $(CLEAR_VARS) +LOCAL_SRC_FILES := $(AUDIO_SRC_FILES) +LOCAL_MODULE := machine_dlkm.ko +LOCAL_MODULE_KBUILD_NAME := asoc/spf_machine_dlkm.ko +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_DEBUG_ENABLE := true +LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) +include $(DLKM_DIR)/Build_external_kernelmodule.mk +########################### LPASS-CDC CODEC ########################### +else ########################### dsp ################################ - include $(CLEAR_VARS) LOCAL_SRC_FILES := $(AUDIO_SRC_FILES) LOCAL_MODULE := q6_notifier_dlkm.ko @@ -155,6 +184,7 @@ LOCAL_MODULE_DEBUG_ENABLE := true LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) include $(DLKM_DIR)/Build_external_kernelmodule.mk +ifneq ($(call is-board-platform-in-list, msmnile),true) ############################ soc ############################### include $(CLEAR_VARS) LOCAL_SRC_FILES := $(AUDIO_SRC_FILES) @@ -182,6 +212,7 @@ LOCAL_MODULE_TAGS := optional LOCAL_MODULE_DEBUG_ENABLE := true LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) include $(DLKM_DIR)/Build_external_kernelmodule.mk +endif ########################################################### include $(CLEAR_VARS) LOCAL_SRC_FILES := $(AUDIO_SRC_FILES) @@ -192,6 +223,7 @@ LOCAL_MODULE_DEBUG_ENABLE := true LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) include $(DLKM_DIR)/Build_external_kernelmodule.mk ########################### ASOC CODEC ################################ +ifneq ($(call is-board-platform-in-list, msmnile),true) include $(CLEAR_VARS) LOCAL_SRC_FILES := $(AUDIO_SRC_FILES) LOCAL_MODULE := wcd_core_dlkm.ko @@ -229,6 +261,7 @@ LOCAL_MODULE_TAGS := optional LOCAL_MODULE_DEBUG_ENABLE := true LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) include $(DLKM_DIR)/Build_external_kernelmodule.mk +endif ########################################################### ifeq ($(call is-board-platform-in-list, kalama),true) include $(CLEAR_VARS) @@ -489,3 +522,4 @@ endif ########################################################### endif # DLKM check endif # supported target check +endif @@ -8,7 +8,7 @@ KBUILD_OPTIONS += CONFIG_SND_SOC_AUTO=y KBUILD_OPTIONS += CONFIG_SND_SOC_GVM=y endif -ifeq ($(TARGET_SUPPORT), $(filter $(TARGET_SUPPORT), sdxpinn sdxbaagha)) +ifeq ($(TARGET_SUPPORT), $(filter $(TARGET_SUPPORT), sdxpinn sdxpinn-cpe-wkk sdxbaagha)) AUDIO_ROOT=$(KERNEL_SRC)/$(M) UAPI_OUT=$(KERNEL_SRC)/$(M) @@ -26,6 +26,10 @@ ifeq ($(TARGET_SUPPORT), sdxpinn) KBUILD_OPTIONS += CONFIG_ARCH_SDXPINN=y endif +ifeq ($(TARGET_SUPPORT), sdxpinn-cpe-wkk) +KBUILD_OPTIONS += CONFIG_ARCH_SDXPINN=y +endif + ifeq ($(TARGET_SUPPORT), sdxbaagha) KBUILD_OPTIONS += CONFIG_ARCH_SDXBAAGHA=y endif diff --git a/asoc/Kbuild b/asoc/Kbuild index 689f5fec..236f0867 100644 --- a/asoc/Kbuild +++ b/asoc/Kbuild @@ -9,8 +9,12 @@ endif ifeq ($(KERNEL_BUILD), 1) # These are configurable via Kconfig for kernel-based builds # Need to explicitly configure for Android-based builds - AUDIO_BLD_DIR := $(shell pwd)/kernel/msm-5.4 - AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio + ifeq ($(TARGET_SUPPORT), sa525m) + AUDIO_ROOT := $(shell pwd)/../../../../vendor/qcom/opensource/audio-kernel + else + AUDIO_BLD_DIR := $(shell pwd)/kernel/msm-5.4 + AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio + endif endif ifeq ($(TARGET_SUPPORT), sa525m) @@ -225,12 +229,13 @@ endif # for sa8155 sound card driver ifdef CONFIG_SND_SOC_SA8155 - MACHINE_OBJS += sa8155.o + MACHINE_OBJS += auto_spf_dummy.o endif # for sa8255 sound card driver ifdef CONFIG_SND_SOC_SA8255_AUTO_SPF - MACHINE_OBJS += auto_spf_dummy.o + SPF_MACHINE_OBJS += msm_common.o + SPF_MACHINE_OBJS += auto_spf_dummy.o endif # for gvm sound card driver @@ -335,7 +340,7 @@ obj-$(CONFIG_SND_SOC_SA525M) += machine_dlkm.o machine_dlkm-y := $(MACHINE_OBJS) obj-$(CONFIG_SND_SOC_SA8255_AUTO_SPF) += spf_machine_dlkm.o -spf_machine_dlkm-y := $(MACHINE_OBJS) +spf_machine_dlkm-y := $(SPF_MACHINE_OBJS) obj-$(CONFIG_SND_SOC_GVM_AUTO_SPF) += spf_machine_dlkm.o spf_machine_dlkm-y := $(SPF_MACHINE_OBJS) diff --git a/asoc/auto_spf_dummy.c b/asoc/auto_spf_dummy.c index a1a4a17e..ed72d36c 100644 --- a/asoc/auto_spf_dummy.c +++ b/asoc/auto_spf_dummy.c @@ -1,5 +1,5 @@ /* Copyright (c) 2014-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -155,6 +155,34 @@ enum { }; enum { + IDX_PRIMARY_TDM_RX_0, + IDX_PRIMARY_TDM_TX_0, + IDX_SECONDARY_TDM_RX_0, + IDX_SECONDARY_TDM_TX_0, + IDX_TERTIARY_TDM_RX_0, + IDX_TERTIARY_TDM_TX_0, + IDX_QUATERNARY_TDM_RX_0, + IDX_QUATERNARY_TDM_TX_0, + IDX_QUINARY_TDM_RX_0, + IDX_QUINARY_TDM_TX_0, + IDX_SENARY_TDM_RX_0, + IDX_SENARY_TDM_TX_0, + IDX_SEPTENARY_TDM_RX_0, + IDX_SEPTENARY_TDM_TX_0, + IDX_HSIF0_TDM_RX_0, + IDX_HSIF0_TDM_TX_0, + IDX_HSIF1_TDM_RX_0, + IDX_HSIF1_TDM_TX_0, + IDX_HSIF2_TDM_RX_0, + IDX_HSIF2_TDM_TX_0, + IDX_HSIF3_TDM_RX_0, + IDX_HSIF3_TDM_TX_0, + IDX_HSIF4_TDM_RX_0, + IDX_HSIF4_TDM_TX_0, + IDX_GROUP_TDM_MAX, +}; + +enum { MCLK1 = 0, MCLK_MAX, }; @@ -625,38 +653,259 @@ struct snd_soc_card sa8255_snd_soc_card_auto_msm = { .name = "sa8255-adp-star-snd-card", }; +static int msm_tdm_get_intf_idx(u16 id) +{ + switch (id) { + case IDX_PRIMARY_TDM_RX_0: + case IDX_PRIMARY_TDM_TX_0: + return TDM_PRI; + case IDX_SECONDARY_TDM_RX_0: + case IDX_SECONDARY_TDM_TX_0: + return TDM_SEC; + case IDX_TERTIARY_TDM_RX_0: + case IDX_TERTIARY_TDM_TX_0: + return TDM_TERT; + case IDX_QUATERNARY_TDM_RX_0: + case IDX_QUATERNARY_TDM_TX_0: + return TDM_QUAT; + case IDX_QUINARY_TDM_RX_0: + case IDX_QUINARY_TDM_TX_0: + return TDM_QUIN; + case IDX_SENARY_TDM_RX_0: + case IDX_SENARY_TDM_TX_0: + return TDM_SEN; + case IDX_SEPTENARY_TDM_RX_0: + case IDX_SEPTENARY_TDM_TX_0: + return TDM_SEP; + case IDX_HSIF0_TDM_RX_0: + case IDX_HSIF0_TDM_TX_0: + return TDM_HSIF0; + case IDX_HSIF1_TDM_RX_0: + case IDX_HSIF1_TDM_TX_0: + return TDM_HSIF1; + case IDX_HSIF2_TDM_RX_0: + case IDX_HSIF2_TDM_TX_0: + return TDM_HSIF2; + case IDX_HSIF3_TDM_RX_0: + case IDX_HSIF3_TDM_TX_0: + return TDM_HSIF3; + case IDX_HSIF4_TDM_RX_0: + case IDX_HSIF4_TDM_TX_0: + return TDM_HSIF4; + + default: return -EINVAL; + } +} + +static int auto_adsp_notifier_service_cb(struct notifier_block *this, + unsigned long opcode, void *ptr) +{ + pr_debug("%s: Service opcode 0x%lx\n", __func__, opcode); + + switch (opcode) { + case AUDIO_NOTIFIER_SERVICE_DOWN: + snd_card_notify_user(SND_CARD_STATUS_OFFLINE); + break; + case AUDIO_NOTIFIER_SERVICE_UP: + snd_card_notify_user(SND_CARD_STATUS_ONLINE); + break; + default: + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block service_nb = { + .notifier_call = auto_adsp_notifier_service_cb, + .priority = -INT_MAX, +}; + +static int msm_set_pinctrl(struct msm_pinctrl_info *pinctrl_info, + enum pinctrl_pin_state new_state) +{ + int ret = 0; + int curr_state = 0; + + if (pinctrl_info == NULL) { + pr_err("%s: pinctrl info is NULL\n", __func__); + ret = -EINVAL; + goto err; + } + + if (pinctrl_info->pinctrl == NULL) { + pr_err("%s: pinctrl handle is NULL\n", __func__); + ret = -EINVAL; + goto err; + } + + curr_state = pinctrl_info->curr_state; + pinctrl_info->curr_state = new_state; + pr_debug("%s: curr_state = %s new_state = %s\n", __func__, + pin_states[curr_state], pin_states[pinctrl_info->curr_state]); + + if (curr_state == pinctrl_info->curr_state) { + pr_err("%s: pin already in same state\n", __func__); + goto err; + } + + if (curr_state != STATE_SLEEP && + pinctrl_info->curr_state != STATE_SLEEP) { + pr_err("%s: pin state is already active, cannot switch\n", __func__); + ret = -EIO; + goto err; + } + switch (pinctrl_info->curr_state) { + case STATE_ACTIVE: + ret = pinctrl_select_state(pinctrl_info->pinctrl, + pinctrl_info->active); + if (ret) { + pr_err("%s: state select to active failed with %d\n", + __func__, ret); + ret = -EIO; + goto err; + } + break; + case STATE_SLEEP: + ret = pinctrl_select_state(pinctrl_info->pinctrl, + pinctrl_info->sleep); + if (ret) { + pr_err("%s: state select to sleep failed with %d\n", + __func__, ret); + ret = -EIO; + goto err; + } + break; + default: + pr_err("%s: pin state is invalid\n", __func__); + return -EINVAL; + } + +err: + return ret; +} + +static int tdm_snd_startup(struct snd_pcm_substream *substream) +{ + int ret = 0; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai_link *dai_link = rtd->dai_link; + struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); + struct tdm_conf *intf_conf = NULL; + struct msm_pinctrl_info *pinctrl_info = NULL; + int ret_pinctrl = 0; + int index; + + index = msm_tdm_get_intf_idx(dai_link->id); + if (index < 0) { + ret = -EINVAL; + pr_err("%s: DAI link id (%d) out of range\n", + __func__, dai_link->id); + goto err; + } + + /* + * Mutex protection in case the same TDM + * interface using for both TX and RX so + * that the same clock won't be enable twice. + */ + intf_conf = &pdata->tdm_intf_conf[index]; + mutex_lock(&intf_conf->lock); + if (++intf_conf->ref_cnt == 1) { + pinctrl_info = &pdata->pinctrl_info[index]; + if (pinctrl_info->pinctrl) { + ret_pinctrl = msm_set_pinctrl(pinctrl_info, + STATE_ACTIVE); + if (ret_pinctrl) + pr_err("%s: TDM TLMM pinctrl set failed with %d\n", + __func__, ret_pinctrl); + } + } + mutex_unlock(&intf_conf->lock); + +err: + return ret; +} + +static void tdm_snd_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai_link *dai_link = rtd->dai_link; + struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); + struct msm_pinctrl_info *pinctrl_info = NULL; + struct tdm_conf *intf_conf = NULL; + int ret_pinctrl = 0; + int index; + + pr_debug("%s: substream = %s, stream = %d\n", __func__, + substream->name, substream->stream); + + index = msm_tdm_get_intf_idx(dai_link->id); + if (index < 0) { + pr_err("%s: DAI link id (%d) out of range\n", + __func__, dai_link->id); + return; + } + + intf_conf = &pdata->tdm_intf_conf[index]; + mutex_lock(&intf_conf->lock); + if (--intf_conf->ref_cnt == 0) { + pinctrl_info = &pdata->pinctrl_info[index]; + if (pinctrl_info->pinctrl) { + ret_pinctrl = msm_set_pinctrl(pinctrl_info, + STATE_SLEEP); + if (ret_pinctrl) + pr_err("%s: TDM TLMM pinctrl set failed with %d\n", + __func__, ret_pinctrl); + } + } + mutex_unlock(&intf_conf->lock); +} + +static struct snd_soc_ops tdm_be_ops = { + .startup = tdm_snd_startup, + .shutdown = tdm_snd_shutdown +}; + /* Digital audio interface glue - connects codec <---> CPU */ static struct snd_soc_dai_link msm_common_dai_links[] = { /* BackEnd DAI Links */ { - .name = "PRI_TDM_RX_0", - .stream_name = "TDM-LPAIF-RX-PRIMARY", + .name = "LPASS_BE_AUXPCM_RX_DUMMY", + .stream_name = "AUXPCM-LPAIF-RX-PRIMARY", .dpcm_playback = 1, + .ops = &tdm_be_ops, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .ignore_suspend = 1, .ignore_pmdown_time = 1, - SND_SOC_DAILINK_REG(pri_tdm_rx_0), + .id = IDX_PRIMARY_TDM_RX_0, + SND_SOC_DAILINK_REG(lpass_be_auxpcm_rx_dummy), }, { - .name = "PRI_TDM_TX_0", - .stream_name = "TDM-LPAIF-TX-PRIMARY", + .name = "LPASS_BE_AUXPCM_TX_DUMMY", + .stream_name = "AUXPCM-LPAIF-TX-PRIMARY", .dpcm_capture = 1, + .ops = &tdm_be_ops, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .ignore_suspend = 1, .ignore_pmdown_time = 1, - SND_SOC_DAILINK_REG(pri_tdm_tx_0), + .id = IDX_PRIMARY_TDM_TX_0, + SND_SOC_DAILINK_REG(lpass_be_auxpcm_tx_dummy), }, { .name = "SEC_TDM_RX_0", .stream_name = "TDM-LPAIF-RX-SECONDARY", .dpcm_playback = 1, + .ops = &tdm_be_ops, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .ignore_suspend = 1, .ignore_pmdown_time = 1, + .id = IDX_SECONDARY_TDM_RX_0, SND_SOC_DAILINK_REG(sec_tdm_rx_0), }, { @@ -665,8 +914,10 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { .dpcm_capture = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .ops = &tdm_be_ops, .ignore_suspend = 1, .ignore_pmdown_time = 1, + .id = IDX_SECONDARY_TDM_TX_0, SND_SOC_DAILINK_REG(sec_tdm_tx_0), }, { @@ -675,8 +926,10 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { .dpcm_playback = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .ops = &tdm_be_ops, .ignore_suspend = 1, .ignore_pmdown_time = 1, + .id = IDX_TERTIARY_TDM_RX_0, SND_SOC_DAILINK_REG(tert_tdm_rx_0), }, { @@ -685,18 +938,122 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { .dpcm_capture = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .ops = &tdm_be_ops, .ignore_suspend = 1, .ignore_pmdown_time = 1, + .id = IDX_TERTIARY_TDM_TX_0, SND_SOC_DAILINK_REG(tert_tdm_tx_0), }, { + .name = "QUAT_TDM_RX_0", + .stream_name = "TDM-LPAIF_RXTX-RX-PRIMARY", + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + SND_SOC_DAILINK_REG(quat_tdm_rx_0), +}, +{ + .name = "QUAT_TDM_TX_0", + .stream_name = "TDM-LPAIF_RXTX-TX-PRIMARY", + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + SND_SOC_DAILINK_REG(quat_tdm_tx_0), +}, +{ + .name = "QUIN_TDM_RX_0", + .stream_name = "TDM-LPAIF_VA-RX-PRIMARY", + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + SND_SOC_DAILINK_REG(quin_tdm_rx_0), +}, +{ + .name = "QUIN_TDM_TX_0", + .stream_name = "TDM-LPAIF_VA-TX-PRIMARY", + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + SND_SOC_DAILINK_REG(quin_tdm_tx_0), +}, +{ + .name = "SEN_TDM_RX_0", + .stream_name = "TDM-LPAIF_WSA-RX-PRIMARY", + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + SND_SOC_DAILINK_REG(sen_tdm_rx_0), +}, +{ + .name = "SEN_TDM_TX_0", + .stream_name = "TDM-LPAIF_WSA-TX-PRIMARY", + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + SND_SOC_DAILINK_REG(sen_tdm_tx_0), +}, +{ + .name = "SEP_TDM_RX_0", + .stream_name = "TDM-LPAIF_AUD-RX-PRIMARY", + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + SND_SOC_DAILINK_REG(sep_tdm_rx_0), +}, +{ + .name = "SEP_TDM_TX_0", + .stream_name = "TDM-LPAIF_AUD-TX-PRIMARY", + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + SND_SOC_DAILINK_REG(sep_tdm_tx_0), +}, +{ + .name = "OCT_TDM_RX_0", + .stream_name = "TDM-LPAIF_WSA2-RX-PRIMARY", + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + SND_SOC_DAILINK_REG(oct_tdm_rx_0), +}, +{ + .name = "OCT_TDM_TX_0", + .stream_name = "TDM-LPAIF_WSA2-TX-PRIMARY", + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + SND_SOC_DAILINK_REG(oct_tdm_tx_0), +}, +{ .name = "HS_IF0_TDM_RX_0", .stream_name = "TDM-LPAIF_SDR-RX-PRIMARY", .dpcm_playback = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .ops = &tdm_be_ops, .ignore_suspend = 1, .ignore_pmdown_time = 1, + .id = IDX_HSIF0_TDM_RX_0, SND_SOC_DAILINK_REG(hs_if0_tdm_rx_0), }, { @@ -705,8 +1062,10 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { .dpcm_capture = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .ops = &tdm_be_ops, .ignore_suspend = 1, .ignore_pmdown_time = 1, + .id = IDX_HSIF0_TDM_TX_0, SND_SOC_DAILINK_REG(hs_if0_tdm_tx_0), }, { @@ -715,8 +1074,10 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { .dpcm_playback = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .ops = &tdm_be_ops, .ignore_suspend = 1, .ignore_pmdown_time = 1, + .id = IDX_HSIF1_TDM_RX_0, SND_SOC_DAILINK_REG(hs_if1_tdm_rx_0), }, { @@ -725,8 +1086,10 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { .dpcm_capture = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .ops = &tdm_be_ops, .ignore_suspend = 1, .ignore_pmdown_time = 1, + .id = IDX_HSIF1_TDM_TX_0, SND_SOC_DAILINK_REG(hs_if1_tdm_tx_0), }, { @@ -735,8 +1098,10 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { .dpcm_playback = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .ops = &tdm_be_ops, .ignore_suspend = 1, .ignore_pmdown_time = 1, + .id = IDX_HSIF2_TDM_RX_0, SND_SOC_DAILINK_REG(hs_if2_tdm_rx_0), }, { @@ -745,8 +1110,10 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { .dpcm_capture = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .ops = &tdm_be_ops, .ignore_suspend = 1, .ignore_pmdown_time = 1, + .id = IDX_HSIF2_TDM_TX_0, SND_SOC_DAILINK_REG(hs_if2_tdm_tx_0), }, { @@ -755,8 +1122,10 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { .dpcm_playback = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .ops = &tdm_be_ops, .ignore_suspend = 1, .ignore_pmdown_time = 1, + .id = IDX_HSIF3_TDM_RX_0, SND_SOC_DAILINK_REG(hs_if3_tdm_rx_0), }, { @@ -765,8 +1134,10 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { .dpcm_capture = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .ops = &tdm_be_ops, .ignore_suspend = 1, .ignore_pmdown_time = 1, + .id = IDX_HSIF3_TDM_TX_0, SND_SOC_DAILINK_REG(hs_if3_tdm_tx_0), }, { @@ -775,8 +1146,10 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { .dpcm_playback = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .ops = &tdm_be_ops, .ignore_suspend = 1, .ignore_pmdown_time = 1, + .id = IDX_HSIF4_TDM_RX_0, SND_SOC_DAILINK_REG(hs_if4_tdm_rx_0), }, { @@ -785,10 +1158,52 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { .dpcm_capture = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, + .ops = &tdm_be_ops, .ignore_suspend = 1, .ignore_pmdown_time = 1, + .id = IDX_HSIF4_TDM_TX_0, SND_SOC_DAILINK_REG(hs_if4_tdm_tx_0), -} +}, +{ + .name = "QUAT_TDM_RX_0_DUMMY", + .stream_name = "TDM-LPAIF-RX-QUATERNARY", + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + SND_SOC_DAILINK_REG(quat_tdm_rx_0_dummy), +}, +{ + .name = "QUAT_TDM_TX_0_DUMMY", + .stream_name = "TDM-LPAIF-TX-QUATERNARY", + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + SND_SOC_DAILINK_REG(quat_tdm_tx_0_dummy), +}, +{ + .name = "QUIN_TDM_RX_0_DUMMY", + .stream_name = "TDM-LPAIF-RX-QUINARY", + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + SND_SOC_DAILINK_REG(quin_tdm_rx_0_dummy), +}, +{ + .name = "QUIN_TDM_TX_0_DUMMY", + .stream_name = "TDM-LPAIF-TX-QUINARY", + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + SND_SOC_DAILINK_REG(quin_tdm_tx_0_dummy), +}, }; @@ -1116,13 +1531,13 @@ static int msm_get_pinctrl(struct platform_device *pdev) /* get all the states handles from Device Tree */ pinctrl_info->sleep = pinctrl_lookup_state(pinctrl, - "sleep"); + "default"); if (IS_ERR(pinctrl_info->sleep)) { pr_err("%s: could not get sleep pin state\n", __func__); goto err; } pinctrl_info->active = pinctrl_lookup_state(pinctrl, - "default"); + "active"); if (IS_ERR(pinctrl_info->active)) { pr_err("%s: could not get active pin state\n", __func__); @@ -1131,14 +1546,14 @@ static int msm_get_pinctrl(struct platform_device *pdev) /* Reset the TLMM pins to a sleep state */ ret = pinctrl_select_state(pinctrl_info->pinctrl, - pinctrl_info->active); + pinctrl_info->sleep); if (ret != 0) { pr_err("%s: set pin state to sleep failed with %d\n", __func__, ret); ret = -EIO; goto err; } - pinctrl_info->curr_state = STATE_ACTIVE; + pinctrl_info->curr_state = STATE_SLEEP; } return 0; @@ -1353,6 +1768,10 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) pr_err("Sound card %s registered\n", card->name); spdev = pdev; + snd_card_set_card_status(SND_CARD_STATUS_ONLINE); + ret = audio_notifier_register("auto_spf", AUDIO_NOTIFIER_ADSP_DOMAIN, + &service_nb); + return 0; err: msm_release_pinctrl(pdev); @@ -1383,6 +1802,7 @@ static struct platform_driver asoc_machine_driver = { int __init auto_spf_init(void) { pr_err("%s\n", __func__); + snd_card_sysfs_init(); return platform_driver_register(&asoc_machine_driver); } diff --git a/asoc/codecs/Kbuild b/asoc/codecs/Kbuild index 8e11e9e2..3d9c6b16 100644 --- a/asoc/codecs/Kbuild +++ b/asoc/codecs/Kbuild @@ -9,8 +9,12 @@ endif ifeq ($(KERNEL_BUILD), 1) # These are configurable via Kconfig for kernel-based builds # Need to explicitly configure for Android-based builds - AUDIO_BLD_DIR := $(shell pwd)/kernel/msm-5.4 - AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio + ifeq ($(TARGET_SUPPORT), sa525m) + AUDIO_ROOT := $(shell pwd)/../../../../vendor/qcom/opensource/audio-kernel + else + AUDIO_BLD_DIR := $(shell pwd)/kernel/msm-5.4 + AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio + endif endif ifeq ($(TARGET_SUPPORT), sa525m) diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c index 59e13a09..94a68359 100644 --- a/asoc/codecs/bolero/tx-macro.c +++ b/asoc/codecs/bolero/tx-macro.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include <linux/module.h> @@ -1310,6 +1310,10 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, dec_cfg_reg, 0x06, 0x00); snd_soc_component_update_bits(component, tx_vol_ctl_reg, + 0x40, 0x40); + snd_soc_component_update_bits(component, tx_vol_ctl_reg, + 0x40, 0x00); + snd_soc_component_update_bits(component, tx_vol_ctl_reg, 0x10, 0x00); if (tx_priv->bcs_enable) { snd_soc_component_update_bits(component, dec_cfg_reg, diff --git a/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c index 83bbbdb8..5435ed6a 100644 --- a/asoc/codecs/bolero/va-macro.c +++ b/asoc/codecs/bolero/va-macro.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include <linux/module.h> @@ -1339,6 +1339,10 @@ static int va_macro_enable_dec(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, tx_vol_ctl_reg, 0x20, 0x00); snd_soc_component_update_bits(component, tx_vol_ctl_reg, + 0x40, 0x40); + snd_soc_component_update_bits(component, tx_vol_ctl_reg, + 0x40, 0x00); + snd_soc_component_update_bits(component, tx_vol_ctl_reg, 0x10, 0x00); break; } diff --git a/asoc/codecs/lpass-cdc/lpass-cdc-va-macro.c b/asoc/codecs/lpass-cdc/lpass-cdc-va-macro.c index e023965f..bfd134be 100644 --- a/asoc/codecs/lpass-cdc/lpass-cdc-va-macro.c +++ b/asoc/codecs/lpass-cdc/lpass-cdc-va-macro.c @@ -450,14 +450,7 @@ static int lpass_cdc_va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w, &va_priv, __func__)) return -EINVAL; - if (!va_priv->use_lpi_mixer_control) - return 0; - - dev_dbg(va_dev, "%s: event = %d, lpi_enable = %d\n", - __func__, event, va_priv->lpi_enable); - - if (!va_priv->lpi_enable) - return ret; + dev_dbg(va_dev, "%s: event = %d\n",__func__, event); switch (event) { case SND_SOC_DAPM_PRE_PMU: diff --git a/asoc/codecs/msm_stub.c b/asoc/codecs/msm_stub.c index 5fba493a..2b5d771c 100644 --- a/asoc/codecs/msm_stub.c +++ b/asoc/codecs/msm_stub.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2011-2014, 2017-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include <linux/platform_device.h> @@ -20,7 +20,7 @@ static struct snd_soc_dai_driver msm_stub_dais[] = { .playback = { /* Support maximum range */ .stream_name = "Playback", .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rates = SNDRV_PCM_RATE_8000_48000, .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | @@ -33,7 +33,7 @@ static struct snd_soc_dai_driver msm_stub_dais[] = { .capture = { /* Support maximum range */ .stream_name = "Record", .channels_min = 1, - .channels_max = 8, + .channels_max = 32, .rates = SNDRV_PCM_RATE_8000_48000, .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | diff --git a/asoc/codecs/wcd937x/internal.h b/asoc/codecs/wcd937x/internal.h index 128d3f77..a47dfeaa 100644 --- a/asoc/codecs/wcd937x/internal.h +++ b/asoc/codecs/wcd937x/internal.h @@ -95,6 +95,7 @@ struct wcd937x_priv { struct snd_info_entry *variant_entry; int ear_rx_path; int ana_clk_count; + int adc_count; struct mutex ana_tx_clk_lock; u8 tx_master_ch_map[WCD937X_MAX_SLAVE_CH_TYPES]; bool usbc_hs_status; diff --git a/asoc/codecs/wcd937x/wcd937x.c b/asoc/codecs/wcd937x/wcd937x.c index 8f42ea1b..51520716 100644 --- a/asoc/codecs/wcd937x/wcd937x.c +++ b/asoc/codecs/wcd937x/wcd937x.c @@ -1449,6 +1449,7 @@ static int wcd937x_codec_enable_adc(struct snd_soc_dapm_widget *w, mutex_lock(&wcd937x->ana_tx_clk_lock); wcd937x->ana_clk_count++; mutex_unlock(&wcd937x->ana_tx_clk_lock); + wcd937x->adc_count++; snd_soc_component_update_bits(component, WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 0x80, 0x80); snd_soc_component_update_bits(component, @@ -1466,8 +1467,13 @@ static int wcd937x_codec_enable_adc(struct snd_soc_dapm_widget *w, wcd937x_tx_connect_port(component, MBHC, false); clear_bit(AMIC2_BCS_ENABLE, &wcd937x->status_mask); } - snd_soc_component_update_bits(component, - WCD937X_DIGITAL_CDC_ANA_CLK_CTL, 0x08, 0x00); + + wcd937x->adc_count--; + if (wcd937x->adc_count <= 0) { + snd_soc_component_update_bits(component, + WCD937X_DIGITAL_CDC_ANA_CLK_CTL, 0x08, 0x00); + wcd937x->adc_count = 0; + } break; }; @@ -1507,14 +1513,19 @@ static int wcd937x_enable_req(struct snd_soc_dapm_widget *w, WCD937X_ANA_TX_CH3, 0x80, 0x80); break; case SND_SOC_DAPM_POST_PMD: - snd_soc_component_update_bits(component, + if (wcd937x->adc_count == 0) { + snd_soc_component_update_bits(component, WCD937X_ANA_TX_CH1, 0x80, 0x00); - snd_soc_component_update_bits(component, + snd_soc_component_update_bits(component, WCD937X_ANA_TX_CH2, 0x80, 0x00); - snd_soc_component_update_bits(component, + snd_soc_component_update_bits(component, WCD937X_ANA_TX_CH3, 0x80, 0x00); - snd_soc_component_update_bits(component, + snd_soc_component_update_bits(component, WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 0x10, 0x00); + snd_soc_component_update_bits(component, + WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 0x80, 0x00); + } + mutex_lock(&wcd937x->ana_tx_clk_lock); wcd937x->ana_clk_count--; if (wcd937x->ana_clk_count <= 0) { @@ -1524,8 +1535,6 @@ static int wcd937x_enable_req(struct snd_soc_dapm_widget *w, } mutex_unlock(&wcd937x->ana_tx_clk_lock); - snd_soc_component_update_bits(component, - WCD937X_DIGITAL_CDC_DIG_CLK_CTL, 0x80, 0x00); break; }; return 0; @@ -2871,6 +2880,8 @@ static int wcd937x_soc_codec_probe(struct snd_soc_component *component) component, WCD937X_DIGITAL_EFUSE_REG_0) & 0x1E) >> 1; wcd937x->variant = variant; + wcd937x->adc_count = 0; + wcd937x->fw_data = devm_kzalloc(component->dev, sizeof(*(wcd937x->fw_data)), GFP_KERNEL); diff --git a/asoc/codecs/wsa881x-analog.c b/asoc/codecs/wsa881x-analog.c index 364ad9aa..6945815f 100644 --- a/asoc/codecs/wsa881x-analog.c +++ b/asoc/codecs/wsa881x-analog.c @@ -1234,12 +1234,12 @@ static const struct snd_soc_component_driver soc_codec_dev_wsa881x = { static struct snd_soc_dai_driver wsa_dai[] = { { - .name = "", + .name = "wsa_rx0", .playback = { .stream_name = "", .rates = WSA881X_RATES | WSA881X_FRAC_RATES, .formats = WSA881X_FORMATS, - .rate_max = 192000, + .rate_max = 384000, .rate_min = 8000, .channels_min = 1, .channels_max = 2, diff --git a/asoc/gvm_auto_spf_dummy.c b/asoc/gvm_auto_spf_dummy.c index 74b265ae..1e01fa47 100644..100755 --- a/asoc/gvm_auto_spf_dummy.c +++ b/asoc/gvm_auto_spf_dummy.c @@ -1,5 +1,5 @@ /* Copyright (c) 2014-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022, 2023 Qualcomm Innovation Center, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -32,6 +32,7 @@ #include <dsp/audio_notifier.h> #include "msm_dailink.h" #include <soc/qcom/boot_stats.h> +#include "msm_common.h" #define DRV_NAME "spf-asoc-snd" @@ -66,6 +67,18 @@ #define ADSP_STATE_READY_TIMEOUT_MS 3000 #define MSM_LL_QOS_VALUE 300 /* time in us to ensure LPM doesn't go in C3/C4 */ #define MSM_HIFI_ON 1 +#define BUF_SZ 32 +#define DIR_SZ 10 + +struct snd_card_pdata { + struct kobject snd_card_kobj; + int card_status; +}*snd_card_pdata; + +static struct attribute card_state_attr = { + .name = "card_state", + .mode = 0660, +}; enum { SLIM_RX_0 = 0, @@ -691,6 +704,71 @@ static struct snd_soc_dai_link msm_talos_dai_links[] = { }, }; +int snd_card_notify_user(snd_card_status_t card_status) +{ + snd_card_pdata->card_status = card_status; + sysfs_notify(&snd_card_pdata->snd_card_kobj, NULL, "card_state"); + return 0; +} + +int snd_card_set_card_status(snd_card_status_t card_status) +{ + snd_card_pdata->card_status = card_status; + return 0; +} + +static ssize_t snd_card_sysfs_show(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + return snprintf(buf, BUF_SZ, "%d", snd_card_pdata->card_status); +} + +static ssize_t snd_card_sysfs_store(struct kobject *kobj, + struct attribute *attr, const char *buf, size_t count) +{ + sscanf(buf, "%d", &snd_card_pdata->card_status); + sysfs_notify(&snd_card_pdata->snd_card_kobj, NULL, "card_state"); + return 0; +} + +static const struct sysfs_ops snd_card_sysfs_ops = { + .show = snd_card_sysfs_show, + .store = snd_card_sysfs_store, +}; + +static struct kobj_type snd_card_ktype = { + .sysfs_ops = &snd_card_sysfs_ops, +}; + +int snd_card_sysfs_init(void) +{ + int ret = 0; + char dir[DIR_SZ] = "snd_card"; + + snd_card_pdata = kcalloc(1, sizeof(struct snd_card_pdata), GFP_KERNEL); + ret = kobject_init_and_add(&snd_card_pdata->snd_card_kobj, &snd_card_ktype, + kernel_kobj, dir); + if (ret < 0) { + pr_err("%s: Failed to add kobject %s, err = %d\n", + __func__, dir, ret); + goto done; + } + + ret = sysfs_create_file(&snd_card_pdata->snd_card_kobj, &card_state_attr); + if (ret < 0) { + pr_err("%s: Failed to add snd_card sysfs entry to %s\n", + __func__, dir); + goto fail_create_file; + } + + return ret; + +fail_create_file: + kobject_put(&snd_card_pdata->snd_card_kobj); +done: + return ret; +} + struct snd_soc_card snd_soc_card_gvm_auto_dummy_msm; static int msm_populate_dai_link_component_of_node( @@ -857,24 +935,21 @@ static long virt_sndcard_ioctl(struct file *f, unsigned int cmd, unsigned long arg) { int ret = 0; -#if IS_ENABLED(CONFIG_AUDIO_QGKI) - struct snd_soc_card *card = platform_get_drvdata(spdev); switch (cmd) { case AUTO_VIRT_SNDCARD_OFFLINE: - snd_soc_card_change_online_state(card, 0); // change sndcard status to OFFLINE - dev_info(&spdev->dev, "ssr restart, mark sndcard offline\n"); + snd_card_notify_user(SND_CARD_STATUS_OFFLINE); + pr_debug("%s: mark sndcard offline\n", __func__); break; case AUTO_VIRT_SNDCARD_ONLINE: - snd_soc_card_change_online_state(card, 1); // change sndcard status to ONLINE - dev_info(&spdev->dev, "ssr complete, mark sndcard online\n"); + snd_card_notify_user(SND_CARD_STATUS_ONLINE); + pr_debug("%s: mark sndcard online\n", __func__); break; default: pr_err("%s: ioctl not found\n", __func__); ret = -EFAULT; break; } -#endif /* CONFIG_AUDIO_QGKI */ return ret; } @@ -959,6 +1034,15 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) } dev_info(&pdev->dev, "Audio virtual sndcard ctrl register complete\n"); + ret = snd_card_sysfs_init(); + if (ret) { + pr_err("snd_card_sysfs_init fail, ret=%d\n", ret); + } + + ret = snd_card_set_card_status(SND_CARD_STATUS_ONLINE); + if (ret) { + pr_err("snd_card_set_card_status fail, ret=%d\n", ret); + } return 0; err: devm_kfree(&pdev->dev, pdata); diff --git a/asoc/monaco.c b/asoc/monaco.c index 23ac3d54..31e3a1af 100644 --- a/asoc/monaco.c +++ b/asoc/monaco.c @@ -85,6 +85,13 @@ /* Slimbus device id for SLIMBUS_DEVICE_1 */ #define BT_SLIMBUS_DEV_ID 0 + +struct card_status { + int state_counter; + int prev_state_counter; + struct mutex lock; +}; + struct msm_asoc_mach_data { struct snd_info_entry *codec_root; struct msm_common_pdata *common_pdata; @@ -97,6 +104,9 @@ struct msm_asoc_mach_data { struct device_node *fsa_handle; bool visense_enable; struct srcu_notifier_head *slatecom_notifier_chain; + struct notifier_block notifier_cc_dsp_nb; + struct card_status cs; + bool is_standby_mode_supported; }; enum bt_slimbus_clk_src { @@ -110,7 +120,72 @@ static struct snd_soc_card snd_soc_card_monaco_msm; static int dmic_0_1_gpio_cnt; static int dmic_2_3_gpio_cnt; static atomic_t bt_slim_clk_src_value = ATOMIC_INIT(SLIMBUS_CLOCK_SRC_XO); -static atomic_t card_status; + +static const char *get_domain_str(int domain) +{ + const char *domain_name = NULL; + + switch (domain) { + case AUDIO_NOTIFIER_ADSP_DOMAIN: + domain_name = "ADSP"; + break; + case AUDIO_NOTIFIER_MODEM_DOMAIN: + domain_name = "MODEM"; + break; + case AUDIO_NOTIFIER_CC_DOMAIN: + domain_name = "CC"; + break; + case AUDIO_NOTIFIER_CCDSP_DOMAIN: + domain_name = "CCDSP"; + break; + default: + domain_name = "UNKNOWN"; + break; + } + + return domain_name; +} + +static const char *get_opcode_str(int opcode) +{ + const char *notifier_state = NULL; + + switch (opcode) { + case AUDIO_NOTIFIER_SERVICE_DOWN: + notifier_state = "DOWN"; + break; + case AUDIO_NOTIFIER_SERVICE_UP: + notifier_state = "UP"; + break; + default: + notifier_state = "UNKNOWN"; + break; + } + + return notifier_state; +} + +static const char *get_snd_card_state_str(int cs) +{ + const char *card_state = NULL; + + switch (cs) { + case SND_CARD_STATUS_OFFLINE: + card_state = "OFFLINE"; + break; + case SND_CARD_STATUS_ONLINE: + card_state = "ONLINE"; + break; + case SND_CARD_STATUS_STANDBY: + card_state = "STANDBY"; + break; + default: + card_state = "INVALID"; + break; + } + + return card_state; +} static void check_userspace_service_state(struct snd_soc_pcm_runtime *rtd, struct msm_common_pdata *pdata) @@ -1007,7 +1082,6 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) "asoc-codec-names", &codec_name); if (!rc && !strcmp(codec_name, "cc_codec")) { - rc = of_property_read_u32(dev->of_node, "qcom,cc-va-intf-enable", &val); if (!rc && val) { @@ -1095,38 +1169,93 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) return card; } -static void monaco_update_snd_card_status(unsigned long opcode) +static void monaco_update_snd_card_status(struct msm_asoc_mach_data *pdata, + int domain, int opcode, + bool is_standby_mode_supported) { - pr_debug("%s: Service opcode 0x%lx\n", __func__, opcode); + int cur_state = SND_CARD_STATUS_INVALID; + pr_debug("%s: Subsys-domain %s(%d), Service-opcode %s(%d)\n", __func__, + get_domain_str(domain), domain, get_opcode_str(opcode), opcode); + + if (!pdata) + return; + + mutex_lock(&pdata->cs.lock); switch (opcode) { case AUDIO_NOTIFIER_SERVICE_DOWN: + pdata->cs.state_counter--; + /** + * On 1st service down(ADSP SSR) event, MSM which has companion + * chip, API updates soundcard status as STANDBY so that userspace + * handles stream accordingly. + */ + if (pdata->cs.state_counter == SND_CARD_STATUS_OFFLINE) { + if (domain == AUDIO_NOTIFIER_ADSP_DOMAIN && + is_standby_mode_supported) { + cur_state = SND_CARD_STATUS_STANDBY; + } else { + cur_state = SND_CARD_STATUS_OFFLINE; + } + /** + * On 2nd service down event(When CC goes down post ADSP SSR), + * API updates current card state as OFFLINE. + */ + } else if (pdata->cs.state_counter == SND_CARD_STATUS_INVALID) { + if (pdata->cs.prev_state_counter == SND_CARD_STATUS_STANDBY) + cur_state = SND_CARD_STATUS_OFFLINE; + } else { + break; + } - if (atomic_inc_return(&card_status) == 1) { - snd_card_notify_user(0); + /* Update previous card state */ + if (cur_state == SND_CARD_STATUS_OFFLINE || + cur_state == SND_CARD_STATUS_STANDBY) { + pdata->cs.prev_state_counter = cur_state; + snd_card_notify_user(cur_state); + pr_info("%s: Sound card is in %s\n", __func__, + get_snd_card_state_str(cur_state)); } break; case AUDIO_NOTIFIER_SERVICE_UP: - if (atomic_dec_return(&card_status) == 0) { - snd_card_notify_user(1); + /** + * Up notification comes once for ADSP and CC/CC_DSP as part + * of bootup. Post bootup as part of SSR, API counts ADSP and + * CC/CC_DSP's notification independently. + */ + pdata->cs.state_counter++; + if (pdata->cs.state_counter == SND_CARD_STATUS_ONLINE) { + snd_card_notify_user(SND_CARD_STATUS_ONLINE); + pr_info("%s: Sound card is in ONLINE\n", __func__); } break; default: break; } + mutex_unlock(&pdata->cs.lock); } static int monaco_cc_dsp_notifier_service_cb(struct notifier_block *this, unsigned long opcode, void *ptr) { + struct msm_asoc_mach_data *pdata = NULL; + pr_debug("%s: Service opcode 0x%lx\n", __func__, opcode); + if (!this) + return NOTIFY_STOP; + + pdata = container_of(this, struct msm_asoc_mach_data, + notifier_cc_dsp_nb); + switch (opcode) { case DSP_ERROR: - monaco_update_snd_card_status(AUDIO_NOTIFIER_SERVICE_DOWN); + monaco_update_snd_card_status(pdata, AUDIO_NOTIFIER_CCDSP_DOMAIN, + AUDIO_NOTIFIER_SERVICE_DOWN, false); break; case DSP_READY: - monaco_update_snd_card_status(AUDIO_NOTIFIER_SERVICE_UP); + monaco_update_snd_card_status(pdata, AUDIO_NOTIFIER_CCDSP_DOMAIN, + AUDIO_NOTIFIER_SERVICE_UP, false); break; default: break; @@ -1135,13 +1264,9 @@ static int monaco_cc_dsp_notifier_service_cb(struct notifier_block *this, return NOTIFY_OK; } -static struct notifier_block notifier_cc_dsp_nb = { - .notifier_call = monaco_cc_dsp_notifier_service_cb, - .priority = 0, -}; - -static int monaco_ssr_enable(struct device *dev, void *data) +static int monaco_ssr_enable(struct device *dev, void *data, int domain) { + struct msm_asoc_mach_data *pdata = NULL; struct platform_device *pdev = to_platform_device(dev); struct snd_soc_card *card = platform_get_drvdata(pdev); int ret = 0; @@ -1152,33 +1277,38 @@ static int monaco_ssr_enable(struct device *dev, void *data) goto err; } + pdata = snd_soc_card_get_drvdata(card); + if (!strcmp(card->name, "monaco-stub-snd-card")) { /* TODO */ dev_dbg(dev, "%s: TODO\n", __func__); } atomic_set(&bt_slim_clk_src_value, SLIMBUS_CLOCK_SRC_XO); - dev_dbg(dev, "%s: reset bt_slim_clk_src_value = %d\n", __func__, - atomic_read(&bt_slim_clk_src_value)); - monaco_update_snd_card_status(AUDIO_NOTIFIER_SERVICE_UP); - dev_dbg(dev, "%s: setting snd_card to ONLINE\n", __func__); + dev_dbg(dev, "%s: reset bt_slim_clk_src_value = %d, domain %d\n", __func__, + atomic_read(&bt_slim_clk_src_value), domain); + monaco_update_snd_card_status(pdata, domain, AUDIO_NOTIFIER_SERVICE_UP, false); err: return ret; } -static void monaco_ssr_disable(struct device *dev, void *data) +static void monaco_ssr_disable(struct device *dev, void *data, int domain) { struct platform_device *pdev = to_platform_device(dev); struct snd_soc_card *card = platform_get_drvdata(pdev); + struct msm_asoc_mach_data *pdata = NULL; if (!card) { dev_err(dev, "%s: card is NULL\n", __func__); return; } - dev_dbg(dev, "%s: setting snd_card to OFFLINE\n", __func__); - monaco_update_snd_card_status(AUDIO_NOTIFIER_SERVICE_DOWN); + pdata = snd_soc_card_get_drvdata(card); + + if (pdata) + monaco_update_snd_card_status(pdata, domain, AUDIO_NOTIFIER_SERVICE_DOWN, + pdata->is_standby_mode_supported); if (!strcmp(card->name, "monaco-stub-snd-card")) { /* TODO */ @@ -1186,7 +1316,7 @@ static void monaco_ssr_disable(struct device *dev, void *data) } } -static const struct snd_event_ops monaco_ssr_ops = { +static const struct snd_event_ops_v2 monaco_ssr_ops = { .enable = monaco_ssr_enable, .disable = monaco_ssr_disable, }; @@ -1216,8 +1346,8 @@ static int msm_audio_ssr_register(struct device *dev) msm_audio_ssr_compare, node); } - ret = snd_event_master_register(dev, &monaco_ssr_ops, - ssr_clients, NULL); + ret = snd_event_master_register_v2(dev, &monaco_ssr_ops, + ssr_clients, NULL); if (!ret) snd_event_notify(dev, SND_EVENT_UP); @@ -1284,6 +1414,7 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) ret = of_property_read_string(pdev->dev.of_node, "asoc-codec-names", &codec_name); if (!ret && !strcmp(codec_name, "cc_codec")) { + pdata->is_standby_mode_supported = true; dev_info(&pdev->dev, "%s: Routing comes from companion chip\n", __func__); } else { ret = snd_soc_of_parse_audio_routing(card, "qcom,audio-routing"); @@ -1391,14 +1522,24 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) else pdata->visense_enable = val; - atomic_set(&card_status, 1); + mutex_init(&pdata->cs.lock); + /** + * By default state is OFFLINE, once ADSP is up post registration + * to snd event, state_counter moves to ONLINE using + * monaco_update_snd_card_status API. + */ + pdata->cs.state_counter = SND_CARD_STATUS_OFFLINE; + ret = msm_audio_ssr_register(&pdev->dev); if (ret) pr_err("%s: Registration with SND event FWK failed ret = %d\n", __func__, ret); + pdata->notifier_cc_dsp_nb.notifier_call = monaco_cc_dsp_notifier_service_cb; + pdata->notifier_cc_dsp_nb.priority = 0; pdata->slatecom_notifier_chain = - (struct srcu_notifier_head *)slatecom_register_notifier(¬ifier_cc_dsp_nb); + (struct srcu_notifier_head *)slatecom_register_notifier( + &pdata->notifier_cc_dsp_nb); is_initial_boot = true; return 0; err: @@ -1418,7 +1559,8 @@ static int msm_asoc_machine_remove(struct platform_device *pdev) if (pdata) { common_pdata = pdata->common_pdata; - slatecom_unregister_notifier(pdata->slatecom_notifier_chain, ¬ifier_cc_dsp_nb); + slatecom_unregister_notifier(pdata->slatecom_notifier_chain, + &pdata->notifier_cc_dsp_nb); if (common_pdata) msm_common_snd_deinit(common_pdata); @@ -1427,6 +1569,9 @@ static int msm_asoc_machine_remove(struct platform_device *pdev) if(card) snd_soc_unregister_card(card); + pdata->cs.state_counter = SND_CARD_STATUS_OFFLINE; + mutex_destroy(&pdata->cs.lock); + return 0; } diff --git a/asoc/msm_common.h b/asoc/msm_common.h index 5cf318a4..251dd8b8 100644 --- a/asoc/msm_common.h +++ b/asoc/msm_common.h @@ -1,14 +1,7 @@ -/* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _MSM_COMMON_H_ #define _MSM_COMMON_H_ @@ -37,8 +30,10 @@ enum { }; typedef enum snd_card_status_t { + SND_CARD_STATUS_INVALID = -1, SND_CARD_STATUS_OFFLINE = 0, - SND_CARD_STATUS_ONLINE = 1, + SND_CARD_STATUS_ONLINE, + SND_CARD_STATUS_STANDBY, } snd_card_status_t; struct msm_common_pdata { diff --git a/asoc/msm_dailink.h b/asoc/msm_dailink.h index 6633e23a..09ba38c8 100644 --- a/asoc/msm_dailink.h +++ b/asoc/msm_dailink.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include <sound/soc.h> @@ -346,6 +346,16 @@ SND_SOC_DAILINK_DEFS(sep_tdm_tx_0, DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")), DAILINK_COMP_ARRAY(COMP_PLATFORM("snd-soc-dummy"))); +SND_SOC_DAILINK_DEFS(oct_tdm_rx_0, + DAILINK_COMP_ARRAY(COMP_CPU("snd-soc-dummy-dai")), + DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("snd-soc-dummy"))); + +SND_SOC_DAILINK_DEFS(oct_tdm_tx_0, + DAILINK_COMP_ARRAY(COMP_CPU("snd-soc-dummy-dai")), + DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("snd-soc-dummy"))); + SND_SOC_DAILINK_DEFS(hs_if0_tdm_rx_0, DAILINK_COMP_ARRAY(COMP_CPU("snd-soc-dummy-dai")), DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")), diff --git a/asoc/sdx-auto-target.c b/asoc/sdx-auto-target.c index 9bd17a30..de300728 100644 --- a/asoc/sdx-auto-target.c +++ b/asoc/sdx-auto-target.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include <linux/clk.h> @@ -92,22 +92,30 @@ struct msm_asoc_mach_data { int core_audio_vote_count; u32 wsa_max_devs; u16 prim_mi2s_mode; + u16 sec_mi2s_mode; u16 tert_mi2s_mode; + u16 prim_auxpcm_mode; + u16 sec_auxpcm_mode; struct device_node *prim_master_p; + struct device_node *sec_master_p; struct device_node *tert_master_p; void __iomem *lpaif_pri_muxsel_virt_addr; void __iomem *lpaif_sec_muxsel_virt_addr; void __iomem *lpaif_tert_muxsel_virt_addr; void __iomem *lpass_mux_spkr_ctl_virt_addr; + void __iomem *lpass_sec_mux_spkr_ctl_virt_addr; void __iomem *lpass_tert_mux_spkr_ctl_virt_addr; void __iomem *lpass_mux_mic_ctl_virt_addr; }; static bool is_initial_boot; static atomic_t mi2s_ref_count; +static atomic_t sec_mi2s_ref_count; static atomic_t tert_mi2s_ref_count; static int sdx_mi2s_mode = I2S_PCM_MASTER_MODE; static int sdx_tert_mi2s_mode = I2S_PCM_MASTER_MODE; +static int sdx_auxpcm_mode = I2S_PCM_MASTER_MODE; +static int sdx_sec_auxpcm_mode = I2S_PCM_MASTER_MODE; static struct snd_soc_card snd_soc_card_sdx_msm; static int msm_aux_codec_init(struct snd_soc_pcm_runtime*); @@ -384,6 +392,175 @@ static struct snd_soc_ops sdx_tert_mi2s_be_ops = { .shutdown = sdx_tert_mi2s_shutdown, }; + +static void sdx_auxpcm_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + int ret; + struct snd_soc_card *card = rtd->card; + struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); + + if (pdata->prim_auxpcm_mode == 1) { + ret = msm_cdc_pinctrl_select_sleep_state(pdata->prim_master_p); + if (ret) + pr_err("%s: failed to set pri gpios to sleep: %d\n", + __func__, ret); + } +} + +static int sdx_auxpcm_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *card = rtd->card; + struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); + int ret = 0; + + pdata->prim_auxpcm_mode = sdx_auxpcm_mode; + if (pdata->lpaif_pri_muxsel_virt_addr != NULL) { + + ret = audio_prm_set_lpass_core_clk_req( NULL, 1, 1); + if (ret < 0) { + dev_err(card->dev, + "%s:set lpass core clk failed ret: %d\n", + __func__, ret); + ret = -EINVAL; + goto done; + } + + iowrite32(PCM_SEL << I2S_PCM_SEL_OFFSET, + pdata->lpaif_pri_muxsel_virt_addr); + if (pdata->lpass_mux_spkr_ctl_virt_addr != NULL) { + if (pdata->prim_auxpcm_mode == 1) + iowrite32(PRI_TLMM_CLKS_EN_MASTER, + pdata->lpass_mux_spkr_ctl_virt_addr); + else + iowrite32(PRI_TLMM_CLKS_EN_SLAVE, + pdata->lpass_mux_spkr_ctl_virt_addr); + } else { + dev_err(card->dev, "%s: mux spkr ctl virt addr is NULL\n", + __func__); + + ret = -EINVAL; + goto done; + } + } else { + dev_err(card->dev, "%s lpaif_pri_muxsel_virt_addr is NULL\n", + __func__); + ret = -EINVAL; + goto done; + } + /* + * This sets the CONFIG PARAMETER WS_SRC. + * 1 means internal clock master mode. + * 0 means external clock slave mode. + */ + if (pdata->prim_auxpcm_mode == 1) { + + ret = msm_cdc_pinctrl_select_active_state(pdata->prim_master_p); + if (ret < 0) { + pr_err("%s pinctrl set failed\n", __func__); + goto done; + } + } else { + /* + * Disable bit clk in slave mode for QC codec. + * Enable only mclk. + */ + } + audio_prm_set_lpass_core_clk_req( NULL, 1, 0); +done: + return ret; +} + +static void sdx_sec_auxpcm_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + int ret; + struct snd_soc_card *card = rtd->card; + struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); + + if (pdata->sec_auxpcm_mode == 1) { + ret = msm_cdc_pinctrl_select_sleep_state(pdata->sec_master_p); + if (ret) + pr_err("%s: failed to set sec gpios to sleep: %d\n", + __func__, ret); + } +} + +static int sdx_sec_auxpcm_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *card = rtd->card; + struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); + int ret = 0; + + pdata->sec_auxpcm_mode = sdx_sec_auxpcm_mode; + if (pdata->lpaif_sec_muxsel_virt_addr != NULL) { + + ret = audio_prm_set_lpass_core_clk_req( NULL, 1, 1); + if (ret < 0) { + dev_err(card->dev, + "%s:set lpass core clk failed ret: %d\n", + __func__, ret); + ret = -EINVAL; + goto done; + } + + iowrite32(PCM_SEL << I2S_PCM_SEL_OFFSET, + pdata->lpaif_sec_muxsel_virt_addr); + if (pdata->lpass_mux_spkr_ctl_virt_addr != NULL) { + if (pdata->sec_auxpcm_mode == 1) + iowrite32(SEC_TLMM_CLKS_EN_MASTER, + pdata->lpass_mux_spkr_ctl_virt_addr); + else + iowrite32(SEC_TLMM_CLKS_EN_SLAVE, + pdata->lpass_mux_spkr_ctl_virt_addr); + } else { + dev_err(card->dev, "%s: mux spkr ctl virt addr is NULL\n", + __func__); + + ret = -EINVAL; + goto done; + } + } else { + dev_err(card->dev, "%s lpaif_sec_muxsel_virt_addr is NULL\n", + __func__); + ret = -EINVAL; + goto done; + } + /* + * This sets the CONFIG PARAMETER WS_SRC. + * 1 means internal clock master mode. + * 0 means external clock slave mode. + */ + if (pdata->sec_auxpcm_mode == 1) { + + ret = msm_cdc_pinctrl_select_active_state(pdata->sec_master_p); + if (ret < 0) { + pr_err("%s pinctrl set failed\n", __func__); + goto done; + } + } else { + /* + * Disable bit clk in slave mode for QC codec. + * Enable only mclk. + */ + } + audio_prm_set_lpass_core_clk_req( NULL, 1, 0); +done: + return ret; +} + +static struct snd_soc_ops sdx_auxpcm_be_ops = { + .startup = sdx_auxpcm_startup, + .shutdown = sdx_auxpcm_shutdown, +}; + +static struct snd_soc_ops sdx_sec_auxpcm_be_ops = { + .startup = sdx_sec_auxpcm_startup, + .shutdown = sdx_sec_auxpcm_shutdown, +}; + static struct snd_info_entry *msm_snd_info_create_subdir(struct module *mod, const char *name, struct snd_info_entry *parent) @@ -499,6 +676,54 @@ static struct snd_soc_dai_link msm_rx_tx_cdc_dma_be_dai_links[] = { }, }; +static struct snd_soc_dai_link sdx_auxpcm_be_dai_links[] = { + /* Primary AUX PCM Backend DAI Links */ + { + .name = LPASS_BE_PRI_AUXPCM_RX, + .stream_name = LPASS_BE_PRI_AUXPCM_RX, + .playback_only = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + .ops = &sdx_auxpcm_be_ops, + SND_SOC_DAILINK_REG(auxpcm_rx), + }, + { + .name = LPASS_BE_PRI_AUXPCM_TX, + .stream_name = LPASS_BE_PRI_AUXPCM_TX, + .capture_only = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + .ops = &sdx_auxpcm_be_ops, + SND_SOC_DAILINK_REG(auxpcm_tx), + }, + { + .name = LPASS_BE_SEC_AUXPCM_RX, + .stream_name = LPASS_BE_SEC_AUXPCM_RX, + .playback_only = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + .ops = &sdx_sec_auxpcm_be_ops, + SND_SOC_DAILINK_REG(auxpcm_rx), + }, + { + .name = LPASS_BE_SEC_AUXPCM_TX, + .stream_name = LPASS_BE_SEC_AUXPCM_TX, + .capture_only = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + .ops = &sdx_sec_auxpcm_be_ops, + SND_SOC_DAILINK_REG(auxpcm_tx), + }, +}; + static struct snd_soc_dai_link msm_tdm_dai_links[] = { { .name = LPASS_BE_PRI_TDM_RX_0, @@ -525,6 +750,7 @@ static struct snd_soc_dai_link msm_tdm_dai_links[] = { static struct snd_soc_dai_link msm_sdx_dai_links[ ARRAY_SIZE(msm_rx_tx_cdc_dma_be_dai_links) + + ARRAY_SIZE(sdx_auxpcm_be_dai_links) + ARRAY_SIZE(msm_common_be_dai_links) + ARRAY_SIZE(msm_tdm_dai_links)]; @@ -703,6 +929,12 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) ARRAY_SIZE(msm_rx_tx_cdc_dma_be_dai_links); memcpy(msm_sdx_dai_links + total_links, + sdx_auxpcm_be_dai_links, + sizeof(sdx_auxpcm_be_dai_links)); + total_links += + ARRAY_SIZE(sdx_auxpcm_be_dai_links); + + memcpy(msm_sdx_dai_links + total_links, msm_common_be_dai_links, sizeof(msm_common_be_dai_links)); total_links += @@ -935,6 +1167,17 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) pdata->prim_master_p = of_parse_phandle(pdev->dev.of_node, "qcom,prim_mi2s_aux_master", 0); + atomic_set(&mi2s_ref_count, 0); + + pdata->sec_master_p = of_parse_phandle(pdev->dev.of_node, + "qcom,sec_mi2s_aux_master", + 0); + atomic_set(&sec_mi2s_ref_count, 0); + + pdata->tert_master_p = of_parse_phandle(pdev->dev.of_node, + "qcom,tert_mi2s_aux_master", + 0); + atomic_set(&tert_mi2s_ref_count, 0); pdata->lpaif_pri_muxsel_virt_addr = ioremap(LPAIF_PRI_MODE_MUXSEL, 4); if (pdata->lpaif_pri_muxsel_virt_addr == NULL) { @@ -952,18 +1195,30 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) ret = -EINVAL; goto err1; } - atomic_set(&mi2s_ref_count, 0); - pdata->tert_master_p = of_parse_phandle(pdev->dev.of_node, - "qcom,tert_mi2s_aux_master", - 0); + pdata->lpaif_sec_muxsel_virt_addr = ioremap(LPAIF_SEC_MODE_MUXSEL, 4); + if (pdata->lpaif_sec_muxsel_virt_addr == NULL) { + pr_err("%s Sec muxsel virt addr is null\n", __func__); + + ret = -EINVAL; + goto err2; + } + + pdata->lpass_sec_mux_spkr_ctl_virt_addr = + ioremap(LPASS_CSR_GP_IO_MUX_MIC_CTL, 4); + if (pdata->lpass_sec_mux_spkr_ctl_virt_addr == NULL) { + pr_err("%s lpass secondary spkr ctl virt addr is null\n", __func__); + + ret = -EINVAL; + goto err3; + } pdata->lpaif_tert_muxsel_virt_addr = ioremap(LPAIF_TERTIARY_MODE_MUXSEL, 4); if (pdata->lpaif_tert_muxsel_virt_addr == NULL) { pr_err("%s Tertiary muxsel virt addr is null\n", __func__); ret = -EINVAL; - goto err; + goto err4; } pdata->lpass_tert_mux_spkr_ctl_virt_addr = @@ -972,9 +1227,8 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) pr_err("%s lpass spkr ctl virt addr is null\n", __func__); ret = -EINVAL; - goto err2; + goto err5; } - atomic_set(&tert_mi2s_ref_count, 0); ret = msm_audio_ssr_register(&pdev->dev); if (ret) @@ -984,12 +1238,17 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) is_initial_boot = true; return 0; +err5: + iounmap(pdata->lpaif_tert_muxsel_virt_addr); +err4: + iounmap(pdata->lpass_sec_mux_spkr_ctl_virt_addr); +err3: + iounmap(pdata->lpaif_sec_muxsel_virt_addr); err2: - iounmap(pdata->lpass_tert_mux_spkr_ctl_virt_addr); -err1: iounmap(pdata->lpass_mux_spkr_ctl_virt_addr); -err: +err1: iounmap(pdata->lpaif_pri_muxsel_virt_addr); +err: devm_kfree(&pdev->dev, pdata); return ret; } diff --git a/asoc/sdx-target.c b/asoc/sdx-target.c index 6b89bed6..8d5693a5 100644 --- a/asoc/sdx-target.c +++ b/asoc/sdx-target.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include <linux/clk.h> @@ -93,10 +93,6 @@ struct msm_asoc_mach_data { u32 wsa_max_devs; u16 prim_mi2s_mode; struct device_node *prim_master_p; - void __iomem *lpaif_pri_muxsel_virt_addr; - void __iomem *lpaif_sec_muxsel_virt_addr; - void __iomem *lpass_mux_spkr_ctl_virt_addr; - void __iomem *lpass_mux_mic_ctl_virt_addr; }; static bool is_initial_boot; @@ -268,36 +264,25 @@ static int sdx_mi2s_startup(struct snd_pcm_substream *substream) pdata->prim_mi2s_mode = sdx_mi2s_mode; if (atomic_inc_return(&mi2s_ref_count) == 1) { - if (pdata->lpaif_pri_muxsel_virt_addr != NULL) { - - ret = audio_prm_set_lpass_core_clk_req( NULL, 1, 1); - if (ret < 0) { - dev_err(card->dev, - "%s:set lpass core clk failed ret: %d\n", - __func__, ret); - ret = -EINVAL; - goto done; - } + ret = audio_prm_set_lpass_core_clk_req( NULL, 1, 1); + if (ret < 0) { + dev_err(card->dev,"%s:set lpass core clk failed ret: %d\n", + __func__, ret); + ret = -EINVAL; + goto done; + } - iowrite32(I2S_SEL << I2S_PCM_SEL_OFFSET, - pdata->lpaif_pri_muxsel_virt_addr); - if (pdata->lpass_mux_spkr_ctl_virt_addr != NULL) { - if (pdata->prim_mi2s_mode == 1) - iowrite32(PRI_TLMM_CLKS_EN_MASTER, - pdata->lpass_mux_spkr_ctl_virt_addr); - else - iowrite32(PRI_TLMM_CLKS_EN_SLAVE, - pdata->lpass_mux_spkr_ctl_virt_addr); - } else { - dev_err(card->dev, "%s: mux spkr ctl virt addr is NULL\n", - __func__); + if (pdata->prim_mi2s_mode == 1) + ret = audio_prm_set_rsc_hw_csr_update((LPAIF_OFFSET + 0x2004), + 0xffff,PRI_TLMM_CLKS_EN_MASTER); + else + ret = audio_prm_set_rsc_hw_csr_update((LPAIF_OFFSET + 0x2004), + 0xffff,PRI_TLMM_CLKS_EN_SLAVE); - ret = -EINVAL; - goto done; - } - } else { - dev_err(card->dev, "%s lpaif_pri_muxsel_virt_addr is NULL\n", - __func__); + if (ret < 0) { + dev_err(card->dev, + "%s:set hw csr update failed ret: %d\n", + __func__, ret); ret = -EINVAL; goto done; } @@ -1285,22 +1270,6 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) pdata->prim_master_p = of_parse_phandle(pdev->dev.of_node, "qcom,prim_mi2s_master", 0); - - pdata->lpaif_pri_muxsel_virt_addr = ioremap(LPAIF_PRI_MODE_MUXSEL, 4); - if (pdata->lpaif_pri_muxsel_virt_addr == NULL) { - pr_err("%s Pri muxsel virt addr is null\n", __func__); - - ret = -EINVAL; - goto err; - } - pdata->lpass_mux_spkr_ctl_virt_addr = - ioremap(LPASS_CSR_GP_IO_MUX_SPKR_CTL, 4); - if (pdata->lpass_mux_spkr_ctl_virt_addr == NULL) { - pr_err("%s lpass spkr ctl virt addr is null\n", __func__); - - ret = -EINVAL; - goto err1; - } atomic_set(&mi2s_ref_count, 0); #ifndef CONFIG_WCD934X_I2S /* Register LPASS audio hw vote */ @@ -1325,10 +1294,7 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) /* Add QoS request for audio tasks */ msm_audio_add_qos_request(); return 0; -err1: - iounmap(pdata->lpass_mux_spkr_ctl_virt_addr); err: - iounmap(pdata->lpaif_pri_muxsel_virt_addr); devm_kfree(&pdev->dev, pdata); return ret; } diff --git a/audio_kernel_modules.mk b/audio_kernel_modules.mk index 9aad7ca7..8a60ed03 100644 --- a/audio_kernel_modules.mk +++ b/audio_kernel_modules.mk @@ -109,5 +109,25 @@ endif #wear_aon endif #monaco endif +else +ifeq ($(call is-board-platform-in-list,msmnile), true) +ifneq (,$(filter $(TARGET_BOARD_PLATFORM)$(TARGET_BOARD_SUFFIX), msmnile_gvmq)) +AUDIO_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/machine_dlkm.ko\ + $(KERNEL_MODULES_OUT)/stub_dlkm.ko +else +AUDIO_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/q6_notifier_dlkm.ko\ + $(KERNEL_MODULES_OUT)/spf_core_dlkm.ko \ + $(KERNEL_MODULES_OUT)/audpkt_ion_dlkm.ko \ + $(KERNEL_MODULES_OUT)/gpr_dlkm.ko \ + $(KERNEL_MODULES_OUT)/audio_pkt_dlkm.ko \ + $(KERNEL_MODULES_OUT)/q6_dlkm.ko \ + $(KERNEL_MODULES_OUT)/adsp_loader_dlkm.ko \ + $(KERNEL_MODULES_OUT)/audio_prm_dlkm.ko \ + $(KERNEL_MODULES_OUT)/snd_event_dlkm.ko \ + $(KERNEL_MODULES_OUT)/stub_dlkm.ko \ + $(KERNEL_MODULES_OUT)/machine_dlkm.ko \ + $(KERNEL_MODULES_OUT)/q6_pdr_dlkm.ko +endif #msmnile +endif endif endif diff --git a/audio_kernel_product_board.mk b/audio_kernel_product_board.mk index afbaabf4..f4e770e2 100644 --- a/audio_kernel_product_board.mk +++ b/audio_kernel_product_board.mk @@ -94,3 +94,22 @@ PRODUCT_PACKAGES += \ $(KERNEL_MODULES_OUT)/audio_cc_ipc_dlkm.ko endif #wear_aon endif #monaco +ifeq ($(call is-board-platform-in-list,msmnile), true) +ifneq (,$(filter $(TARGET_BOARD_PLATFORM)$(TARGET_BOARD_SUFFIX), msmnile_gvmq)) +PRODUCT_PACKAGES += $(KERNEL_MODULES_OUT)/machine_dlkm.ko \ + $(KERNEL_MODULES_OUT)/stub_dlkm.ko +else +PRODUCT_PACKAGES += $(KERNEL_MODULES_OUT)/q6_notifier_dlkm.ko\ + $(KERNEL_MODULES_OUT)/spf_core_dlkm.ko \ + $(KERNEL_MODULES_OUT)/audpkt_ion_dlkm.ko \ + $(KERNEL_MODULES_OUT)/gpr_dlkm.ko \ + $(KERNEL_MODULES_OUT)/audio_pkt_dlkm.ko \ + $(KERNEL_MODULES_OUT)/q6_dlkm.ko \ + $(KERNEL_MODULES_OUT)/adsp_loader_dlkm.ko \ + $(KERNEL_MODULES_OUT)/audio_prm_dlkm.ko \ + $(KERNEL_MODULES_OUT)/snd_event_dlkm.ko \ + $(KERNEL_MODULES_OUT)/stub_dlkm.ko \ + $(KERNEL_MODULES_OUT)/machine_dlkm.ko \ + $(KERNEL_MODULES_OUT)/q6_pdr_dlkm.ko +endif #msmnile +endif diff --git a/audio_kernel_vendor_board.mk b/audio_kernel_vendor_board.mk index 7d44d04f..de8e960d 100644 --- a/audio_kernel_vendor_board.mk +++ b/audio_kernel_vendor_board.mk @@ -4,15 +4,13 @@ ifeq ($(TARGET_KERNEL_DLKM_DISABLE), true) AUDIO_DLKM_ENABLE := true endif else - ifeq ($(TARGET_KERNEL_DLKM_AUDIO_OVERRIDE),true) - AUDIO_DLKM_ENABLE := true - endif + AUDIO_DLKM_ENABLE := true endif BOARD_OPENSOURCE_DIR ?= vendor/qcom/opensource ifeq ($(AUDIO_DLKM_ENABLE), true) - ifeq ($(call is-board-platform-in-list,taro kalama bengal monaco), true) + ifeq ($(call is-board-platform-in-list,taro kalama bengal monaco msmnile), true) include vendor/qcom/opensource/audio-kernel/audio_kernel_modules.mk endif ifeq ($(ENABLE_AUDIO_LEGACY_TECHPACK),true) diff --git a/config/sa8155auto.conf b/config/sa8155auto.conf index e6506760..b7309601 100644 --- a/config/sa8155auto.conf +++ b/config/sa8155auto.conf @@ -1,16 +1,14 @@ -CONFIG_MSM_QDSP6_APRV2_RPMSG=m -CONFIG_MSM_QDSP6_SSR=m -CONFIG_MSM_ADSP_LOADER=m -CONFIG_MSM_QDSP6_NOTIFIER=m -CONFIG_SND_SOC_MSM_QDSP6V2_INTF=m -CONFIG_SND_SOC_QDSP6V2=m -CONFIG_QTI_PP=m -CONFIG_SND_HWDEP_ROUTING=m -CONFIG_DTS_EAGLE=m -CONFIG_DOLBY_DS2=m -CONFIG_DOLBY_LICENSE=m -CONFIG_SND_SOC_MSM_STUB=m -CONFIG_SND_SOC_MSM_HDMI_CODEC_RX=m -CONFIG_MSM_QDSP6V2_CODECS=m -CONFIG_SND_EVENT=m -CONFIG_SND_SOC_SA8155=m +export CONFIG_MSM_ADSP_LOADER=m +export CONFIG_MSM_QDSP6_SSR=m +export CONFIG_MSM_QDSP6_NOTIFIER=m +export CONFIG_SND_SOC_MSM_QDSP6V2_INTF=m +export CONFIG_SND_EVENT=m +export CONFIG_MSM_QDSP6_GPR_RPMSG=m +export CONFIG_AUDIO_PKT=m +export CONFIG_AUDIO_PKT_ION=m +export CONFIG_AUDIO_PRM=m +export CONFIG_SPF_CORE=m +export CONFIG_SND_SOC_QDSP6V2=m +export CONFIG_SND_SOC_MSM_STUB=m +export CONFIG_SND_SOC_SA8155=m +export CONFIG_MSM_QDSP6_PDR=m diff --git a/config/sa8155autoconf.h b/config/sa8155autoconf.h index 7470fc6b..519badf1 100644 --- a/config/sa8155autoconf.h +++ b/config/sa8155autoconf.h @@ -1,20 +1,18 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ - -#define CONFIG_MSM_QDSP6_APRV2_RPMSG 1 #define CONFIG_MSM_QDSP6_SSR 1 #define CONFIG_MSM_ADSP_LOADER 1 #define CONFIG_MSM_QDSP6_NOTIFIER 1 #define CONFIG_SND_SOC_MSM_QDSP6V2_INTF 1 #define CONFIG_SND_SOC_QDSP6V2 1 -#define CONFIG_QTI_PP 1 -#define CONFIG_SND_HWDEP_ROUTING 1 -#define CONFIG_DTS_EAGLE 1 -#define CONFIG_DOLBY_DS2 1 -#define CONFIG_DOLBY_LICENSE 1 -#define CONFIG_SND_SOC_MSM_STUB 1 -#define CONFIG_SND_SOC_MSM_HDMI_CODEC_RX 1 -#define CONFIG_MSM_QDSP6V2_CODECS 1 +#define CONFIG_MSM_QDSP6_GPR_RPMSG 1 +#define CONFIG_AUDIO_PKT 1 +#define CONFIG_AUDIO_PKT_ION 1 +#define CONFIG_AUDIO_PRM 1 +#define CONFIG_SPF_CORE 1 #define CONFIG_SND_EVENT 1 +#define CONFIG_SND_SOC_MSM_STUB 1 #define CONFIG_SND_SOC_SA8155 1 +#define CONFIG_MSM_QDSP6_PDR 1 diff --git a/config/sa8255auto.conf b/config/sa8255auto.conf index eb76f01f..6d71f309 100644 --- a/config/sa8255auto.conf +++ b/config/sa8255auto.conf @@ -11,3 +11,5 @@ export CONFIG_SPF_CORE=m export CONFIG_SND_SOC_QDSP6V2=m export CONFIG_SND_SOC_MSM_STUB=m export CONFIG_SND_SOC_SA8255_AUTO_SPF=m +export CONFIG_PINCTRL_LPI=m +export CONFIG_SND_SOC_WCD9XXX_V2=m diff --git a/config/sa8255autoconf.h b/config/sa8255autoconf.h index a22e8815..3bda3fd0 100644 --- a/config/sa8255autoconf.h +++ b/config/sa8255autoconf.h @@ -22,3 +22,5 @@ #define CONFIG_SND_EVENT 1 #define CONFIG_SND_SOC_MSM_STUB 1 #define CONFIG_SND_SOC_SA8255_AUTO_SPF 1 +#define CONFIG_PINCTRL_LPI 1 +#define CONFIG_SND_SOC_WCD9XXX_V2 1 diff --git a/config/sdxbaaghaauto.h b/config/sdxbaaghaautoconf.h index 4d60bd37..4d60bd37 100644 --- a/config/sdxbaaghaauto.h +++ b/config/sdxbaaghaautoconf.h @@ -9,8 +9,12 @@ endif ifeq ($(KERNEL_BUILD), 1) # These are configurable via Kconfig for kernel-based builds # Need to explicitly configure for Android-based builds - AUDIO_BLD_DIR := $(shell pwd)/kernel/msm-5.4 - AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio + ifeq ($(TARGET_SUPPORT), sa525m) + AUDIO_ROOT := $(shell pwd)/../../../../vendor/qcom/opensource/audio-kernel + else + AUDIO_BLD_DIR := $(shell pwd)/kernel/msm-5.4 + AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio + endif endif ifeq ($(TARGET_SUPPORT), sa525m) diff --git a/dsp/msm_audio_ion.c b/dsp/msm_audio_ion.c index f7bfbfce..3119e6d5 100644 --- a/dsp/msm_audio_ion.c +++ b/dsp/msm_audio_ion.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #include <linux/init.h> @@ -102,6 +102,7 @@ static void msm_audio_ion_add_allocation( mutex_unlock(&(msm_audio_ion_data->list_mutex)); } +/* This function is called with ion_data list mutex lock */ static int msm_audio_ion_map_kernel(struct dma_buf *dma_buf, struct msm_audio_ion_private *ion_data, struct dma_buf_map *dma_vmap) { @@ -139,6 +140,7 @@ exit: return rc; } +/* This function is called with ion_data list mutex lock */ static int msm_audio_dma_buf_map(struct dma_buf *dma_buf, dma_addr_t *addr, size_t *len, bool is_iova, struct msm_audio_ion_private *ion_data) @@ -231,7 +233,6 @@ static int msm_audio_dma_buf_unmap(struct dma_buf *dma_buf, struct msm_audio_ion * should be explicitly acquired to avoid race condition * on adding elements to the list. */ - mutex_lock(&(ion_data->list_mutex)); list_for_each_safe(ptr, next, &(ion_data->alloc_list)) { @@ -256,7 +257,6 @@ static int msm_audio_dma_buf_unmap(struct dma_buf *dma_buf, struct msm_audio_ion break; } } - mutex_unlock(&(ion_data->list_mutex)); if (!found) { dev_err(cb_dev, @@ -303,7 +303,6 @@ static int msm_audio_ion_unmap_kernel(struct dma_buf *dma_buf, struct msm_audio_ * TBD: remove the below section once new API * for unmapping kernel virtual address is available. */ - mutex_lock(&(ion_data->list_mutex)); list_for_each_entry(alloc_data, &(ion_data->alloc_list), list) { if (alloc_data->dma_buf == dma_buf) { @@ -311,7 +310,6 @@ static int msm_audio_ion_unmap_kernel(struct dma_buf *dma_buf, struct msm_audio_ break; } } - mutex_unlock(&(ion_data->list_mutex)); if (!dma_vmap) { dev_err(cb_dev, @@ -334,7 +332,8 @@ err: return rc; } -static int msm_audio_ion_map_buf(struct dma_buf *dma_buf, u64 *paddr, +/* This function is called with ion_data list mutex lock */ +static int msm_audio_ion_buf_map(struct dma_buf *dma_buf, dma_addr_t *paddr, size_t *plen, struct dma_buf_map *dma_vmap, struct msm_audio_ion_private *ion_data) { @@ -359,7 +358,9 @@ static int msm_audio_ion_map_buf(struct dma_buf *dma_buf, u64 *paddr, pr_err("%s: ION memory mapping for AUDIO failed, err:%d\n", __func__, rc); rc = -ENOMEM; + mutex_lock(&(ion_data->list_mutex)); msm_audio_dma_buf_unmap(dma_buf, ion_data); + mutex_unlock(&(ion_data->list_mutex)); goto err; } @@ -402,6 +403,11 @@ void msm_audio_delete_fd_entry(void *handle) struct msm_audio_fd_data *msm_audio_fd_data = NULL; struct list_head *ptr, *next; + if (!handle) { + pr_err("%s Invalid handle\n", __func__); + return; + } + mutex_lock(&(msm_audio_ion_fd_list.list_mutex)); list_for_each_safe(ptr, next, &msm_audio_ion_fd_list.fd_list) { @@ -472,6 +478,7 @@ void msm_audio_get_handle(int fd, void **handle) pr_debug("%s fd %d\n", __func__, fd); mutex_lock(&(msm_audio_ion_fd_list.list_mutex)); + *handle = NULL; list_for_each_entry(msm_audio_fd_data, &msm_audio_ion_fd_list.fd_list, list) { if (msm_audio_fd_data->fd == fd) { @@ -533,7 +540,7 @@ static int msm_audio_ion_import(struct dma_buf **dma_buf, int fd, } } if (ion_data->smmu_enabled) { - rc = msm_audio_ion_map_buf(*dma_buf, paddr, plen, dma_vmap, ion_data); + rc = msm_audio_ion_buf_map(*dma_buf, paddr, plen, dma_vmap, ion_data); if (rc) { pr_err("%s: failed to map ION buf, rc = %d\n", __func__, rc); goto err; @@ -561,6 +568,7 @@ err: * * Returns 0 on success or error on failure */ +/* This funtion is called with ion_data list mutex lock */ static int msm_audio_ion_free(struct dma_buf *dma_buf, struct msm_audio_ion_private *ion_data) { int ret = 0; @@ -570,14 +578,18 @@ static int msm_audio_ion_free(struct dma_buf *dma_buf, struct msm_audio_ion_priv return -EINVAL; } + mutex_lock(&(ion_data->list_mutex)); if (ion_data->smmu_enabled) { ret = msm_audio_ion_unmap_kernel(dma_buf, ion_data); - if (ret) + if (ret) { + mutex_unlock(&(ion_data->list_mutex)); return ret; + } } msm_audio_dma_buf_unmap(dma_buf, ion_data); + mutex_unlock(&(ion_data->list_mutex)); return 0; } diff --git a/include/dsp/audio_notifier.h b/include/dsp/audio_notifier.h index 784fc9d9..0284ae9c 100644 --- a/include/dsp/audio_notifier.h +++ b/include/dsp/audio_notifier.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2016, 2018, 2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef __AUDIO_NOTIFIER_H_ @@ -26,6 +26,7 @@ enum { AUDIO_NOTIFIER_ADSP_DOMAIN, AUDIO_NOTIFIER_MODEM_DOMAIN, AUDIO_NOTIFIER_CC_DOMAIN, + AUDIO_NOTIFIER_CCDSP_DOMAIN, AUDIO_NOTIFIER_MAX_DOMAINS }; diff --git a/include/dsp/audio_prm.h b/include/dsp/audio_prm.h index 874a2ab1..ac164b24 100644 --- a/include/dsp/audio_prm.h +++ b/include/dsp/audio_prm.h @@ -1,5 +1,5 @@ /* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -301,7 +301,7 @@ typedef struct prm_cmd_request_rsc_hw_csr_update { } prm_cmd_request_rsc_hw_csr_update_t; /* Param ID for HW CSR update */ -#define PARAM_ID_RSC_HW_CSR_UPDATE 0x0800131B +#define PARAM_ID_RSC_HW_CSR_UPDATE 0x08001509 #define HW_CODEC_DIG_REG_ID_MUTE_CTRL 0x1 #define HW_CODEC_OP_DIG_MUTE_ENABLE 0x1 diff --git a/include/soc/snd_event.h b/include/soc/snd_event.h index f0dbfdb6..528fe246 100644 --- a/include/soc/snd_event.h +++ b/include/soc/snd_event.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2018-2019, 2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _SND_EVENT_H_ @@ -19,6 +19,11 @@ struct snd_event_ops { void (*disable)(struct device *dev, void *data); }; +struct snd_event_ops_v2 { + int (*enable)(struct device *dev, void *data, int domain); + void (*disable)(struct device *dev, void *data, int domain); +}; + #ifdef CONFIG_SND_EVENT int snd_event_client_register(struct device *dev, const struct snd_event_ops *snd_ev_ops, @@ -31,6 +36,10 @@ int snd_event_master_register(struct device *dev, const struct snd_event_ops *ops, struct snd_event_clients *clients, void *data); +int snd_event_master_register_v2(struct device *dev, + const struct snd_event_ops_v2 *ops_v2, + struct snd_event_clients *clients, + void *data); int snd_event_master_deregister(struct device *dev); int snd_event_notify(struct device *dev, unsigned int state); int snd_event_notify_v2(struct device *dev, unsigned int state, int domain); @@ -11,7 +11,11 @@ endif KDIR := $(TOP)/kernel/msm-5.4 ifeq ($(KERNEL_BUILD), 1) - AUDIO_ROOT := $(KDIR)/techpack/audio + ifeq ($(TARGET_SUPPORT), sa525m) + AUDIO_ROOT := $(shell pwd)/../../../../vendor/qcom/opensource/audio-kernel + else + AUDIO_ROOT := $(KDIR)/techpack/audio + endif endif ifeq ($(TARGET_SUPPORT), sa525m) diff --git a/ipc/audio-pkt.c b/ipc/audio-pkt.c index 37d9ead0..883f7854 100755 --- a/ipc/audio-pkt.c +++ b/ipc/audio-pkt.c @@ -1,5 +1,5 @@ /* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -412,6 +412,8 @@ ssize_t audio_pkt_write(struct file *file, const char __user *buf, ret = gpr_send_pkt(ap_priv->adev,(struct gpr_pkt *) kbuf); if (ret < 0) { AUDIO_PKT_ERR("APR Send Packet Failed ret -%d\n", ret); + if (ret == -ECONNRESET) + ret = -ENETRESET; } mutex_unlock(&audpkt_dev->lock); @@ -9,8 +9,12 @@ endif ifeq ($(KERNEL_BUILD), 1) # These are configurable via Kconfig for kernel-based builds # Need to explicitly configure for Android-based builds - AUDIO_BLD_DIR := $(shell pwd)/kernel/msm-5.4 - AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio + ifeq ($(TARGET_SUPPORT), sa525m) + AUDIO_ROOT := $(shell pwd)/../../../../vendor/qcom/opensource/audio-kernel + else + AUDIO_BLD_DIR := $(shell pwd)/kernel/msm-5.4 + AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio + endif endif ifeq ($(TARGET_SUPPORT), sa525m) diff --git a/soc/snd_event.c b/soc/snd_event.c index b75620f7..dbde6200 100644 --- a/soc/snd_event.c +++ b/soc/snd_event.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018, 2020-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #include <linux/platform_device.h> @@ -11,10 +11,12 @@ #include <soc/snd_event.h> #include <dsp/audio_notifier.h> - #define BROADCAST_MASTER_EVENT 1 #define BROADCAST_SUBSYSTEM_EVENT 0 +#define SND_EVENT_MASTER_OPS_V1 1 +#define SND_EVENT_MASTER_OPS_V2 2 + struct snd_event_client { struct list_head node; @@ -42,6 +44,7 @@ struct snd_event_clients { struct snd_master { struct device *dev; const struct snd_event_ops *ops; + const struct snd_event_ops_v2 *ops_v2; void *data; bool state; @@ -92,20 +95,25 @@ static int check_and_update_fwk_state(int domain, bool event) } } } - if (master->ops->enable) { + if (master->ops && master->ops->enable) { ret = master->ops->enable(master->dev, master->data); - if (ret) { - dev_err_ratelimited(master->dev, - "%s: enable failed\n", - __func__); - goto mstr_en_failed; - } + } else if (master->ops_v2 && master->ops_v2->enable) { + ret = master->ops_v2->enable(master->dev, + master->data, domain); + } + if (ret) { + dev_err_ratelimited(master->dev, "%s: enable failed\n", __func__); + goto mstr_en_failed; } } else { - if (master->ops->disable) + if (master->ops && master->ops->disable) { master->ops->disable(master->dev, master->data); + } else if (master->ops_v2 && master->ops_v2->disable) { + master->ops_v2->disable(master->dev, + master->data, domain); + } for (i = 0; i < master->clients->num_clients; i++) { c = master->clients->cl_arr[i].clnt; if (c->ops->disable && (c->domain == domain || event)) @@ -171,6 +179,67 @@ static int snd_event_find_clients(struct snd_master *master) return ret; } +static int snd_event_master_register_internal(struct device *dev, + const void *ops, int ops_version, + struct snd_event_clients *clients, + void *data) +{ + struct snd_master *new_master; + int ret = 0; + + if (!dev) { + pr_err_ratelimited("%s: dev is NULL\n", __func__); + return -EINVAL; + } + + mutex_lock(&snd_event_mutex); + if (master) { + dev_err(dev, "%s: master already allocated with %pK\n", + __func__, master->dev); + ret = -EALREADY; + goto exit; + } + mutex_unlock(&snd_event_mutex); + + if (!clients || IS_ERR(clients)) { + dev_err(dev, "%s: Invalid clients ptr\n", __func__); + return -EINVAL; + } + + new_master = kzalloc(sizeof(*new_master), GFP_KERNEL); + if (!new_master) + return -ENOMEM; + + new_master->dev = dev; + if (ops_version == SND_EVENT_MASTER_OPS_V2) { + new_master->ops_v2 = (struct snd_event_ops_v2 *)ops; + new_master->ops = NULL; + } else { + new_master->ops = (struct snd_event_ops *)ops; + new_master->ops_v2 = NULL; + } + new_master->data = data; + new_master->clients = clients; + + dev_dbg(dev, "adding master to SND event FW (ops %pK)\n", ops); + + mutex_lock(&snd_event_mutex); + + master = new_master; + + ret = snd_event_find_clients(master); + if (ret) { + dev_dbg(dev, "%s: Failed to find all clients\n", __func__); + ret = 0; + goto exit; + } + master->clients_found = true; + +exit: + mutex_unlock(&snd_event_mutex); + return ret; +} + /* * snd_event_client_register_v2 - Register a client with the SND event FW * @@ -386,58 +455,40 @@ int snd_event_master_register(struct device *dev, struct snd_event_clients *clients, void *data) { - struct snd_master *new_master; - int ret = 0; - - if (!dev) { - pr_err_ratelimited("%s: dev is NULL\n", __func__); - return -EINVAL; - } - - mutex_lock(&snd_event_mutex); - if (master) { - dev_err(dev, "%s: master already allocated with %pK\n", - __func__, master->dev); - ret = -EALREADY; - goto exit; - } - mutex_unlock(&snd_event_mutex); - - if (!clients || IS_ERR(clients)) { - dev_err(dev, "%s: Invalid clients ptr\n", __func__); - return -EINVAL; - } - - new_master = kzalloc(sizeof(*new_master), GFP_KERNEL); - if (!new_master) - return -ENOMEM; - - new_master->dev = dev; - new_master->ops = ops; - new_master->data = data; - new_master->clients = clients; - - dev_dbg(dev, "adding master to SND event FW (ops %pK)\n", ops); - - mutex_lock(&snd_event_mutex); - - master = new_master; - - ret = snd_event_find_clients(master); - if (ret) { - dev_dbg(dev, "%s: Failed to find all clients\n", __func__); - ret = 0; - goto exit; - } - master->clients_found = true; - -exit: - mutex_unlock(&snd_event_mutex); - return ret; + return snd_event_master_register_internal(dev, ops, + SND_EVENT_MASTER_OPS_V1, clients, data); } EXPORT_SYMBOL(snd_event_master_register); /* + * snd_event_master_register_v2 - Register a master with the SND event FW + * + * @dev: Pointer to the "struct device" associated with the master + * @ops_v2: Pointer to the snd_event_ops_v2 struct for the master containing + * callback functions which triggers for specific subsystem domain. + * @clients: List of clients for the master + * @data: Pointer to any additional data that the caller wants to get back + * with callback functions + * + * Returns 0 on success or error on failure. + * + * Prerequisite: + * clients list must not be empty. + * All clients for the master must have to be registered by calling + * snd_event_mstr_add_client() before calling this API to register a + * master with SND event fwk. + */ +int snd_event_master_register_v2(struct device *dev, + const struct snd_event_ops_v2 *ops_v2, + struct snd_event_clients *clients, + void *data) +{ + return snd_event_master_register_internal(dev, ops_v2, + SND_EVENT_MASTER_OPS_V2, clients, data); +} +EXPORT_SYMBOL(snd_event_master_register_v2); + +/* * snd_event_master_deregister - Remove a master from the SND event FW * * @dev: Pointer to the "struct device" associated with the master |