Loading asoc/codecs/wcd934x/wcd934x.c +40 −2 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h> #include <linux/mfd/wcd9xxx/wcd9xxx_registers.h> #include <linux/mfd/wcd9xxx/wcd9xxx_registers.h> #include <soc/swr-wcd.h> #include <soc/swr-wcd.h> #include <soc/snd_event.h> #include <sound/pcm.h> #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/pcm_params.h> #include <sound/soc.h> #include <sound/soc.h> Loading Loading @@ -9979,6 +9980,7 @@ static int tavil_device_down(struct wcd9xxx *wcd9xxx) priv = snd_soc_codec_get_drvdata(codec); priv = snd_soc_codec_get_drvdata(codec); for (count = 0; count < NUM_CODEC_DAIS; count++) for (count = 0; count < NUM_CODEC_DAIS; count++) priv->dai[count].bus_down_in_recovery = true; priv->dai[count].bus_down_in_recovery = true; snd_event_notify(priv->dev->parent, SND_EVENT_DOWN); priv->mbhc->wcd_mbhc.deinit_in_progress = true; priv->mbhc->wcd_mbhc.deinit_in_progress = true; if (delayed_work_pending(&priv->spk_anc_dwork.dwork)) if (delayed_work_pending(&priv->spk_anc_dwork.dwork)) Loading Loading @@ -10006,6 +10008,7 @@ static int tavil_device_down(struct wcd9xxx *wcd9xxx) swrm_wcd_notify(priv->swr.ctrl_data[0].swr_pdev, swrm_wcd_notify(priv->swr.ctrl_data[0].swr_pdev, SWR_DEVICE_DOWN, NULL); SWR_DEVICE_DOWN, NULL); tavil_dsd_reset(priv->dsd_config); tavil_dsd_reset(priv->dsd_config); if (!is_snd_event_fwk_enabled()) snd_soc_card_change_online_state(codec->component.card, 0); snd_soc_card_change_online_state(codec->component.card, 0); wcd_dsp_ssr_event(priv->wdsp_cntl, WCD_CDC_DOWN_EVENT); wcd_dsp_ssr_event(priv->wdsp_cntl, WCD_CDC_DOWN_EVENT); wcd_resmgr_set_sido_input_src_locked(priv->resmgr, wcd_resmgr_set_sido_input_src_locked(priv->resmgr, Loading Loading @@ -10039,6 +10042,7 @@ static int tavil_post_reset_cb(struct wcd9xxx *wcd9xxx) tavil_slimbus_slave_port_cfg.slave_dev_pgd_la = tavil_slimbus_slave_port_cfg.slave_dev_pgd_la = control->slim->laddr; control->slim->laddr; tavil_init_slim_slave_cfg(codec); tavil_init_slim_slave_cfg(codec); if (!is_snd_event_fwk_enabled()) snd_soc_card_change_online_state(codec->component.card, 1); snd_soc_card_change_online_state(codec->component.card, 1); for (i = 0; i < TAVIL_MAX_MICBIAS; i++) for (i = 0; i < TAVIL_MAX_MICBIAS; i++) Loading Loading @@ -10102,6 +10106,7 @@ static int tavil_post_reset_cb(struct wcd9xxx *wcd9xxx) */ */ tavil_vote_svs(tavil, false); tavil_vote_svs(tavil, false); wcd_dsp_ssr_event(tavil->wdsp_cntl, WCD_CDC_UP_EVENT); wcd_dsp_ssr_event(tavil->wdsp_cntl, WCD_CDC_UP_EVENT); snd_event_notify(tavil->dev->parent, SND_EVENT_UP); done: done: mutex_unlock(&tavil->codec_mutex); mutex_unlock(&tavil->codec_mutex); Loading Loading @@ -10900,6 +10905,28 @@ struct wcd_dsp_cntl *tavil_get_wcd_dsp_cntl(struct device *dev) } } EXPORT_SYMBOL(tavil_get_wcd_dsp_cntl); EXPORT_SYMBOL(tavil_get_wcd_dsp_cntl); static void wcd934x_ssr_disable(struct device *dev, void *data) { struct wcd9xxx *wcd9xxx = dev_get_drvdata(dev); struct tavil_priv *tavil; struct snd_soc_codec *codec; int count = 0; if (!wcd9xxx) { dev_dbg(dev, "%s: wcd9xxx pointer NULL.\n", __func__); return; } codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv); tavil = snd_soc_codec_get_drvdata(codec); for (count = 0; count < NUM_CODEC_DAIS; count++) tavil->dai[count].bus_down_in_recovery = true; } static const struct snd_event_ops wcd934x_ssr_ops = { .disable = wcd934x_ssr_disable, }; static int tavil_probe(struct platform_device *pdev) static int tavil_probe(struct platform_device *pdev) { { int ret = 0; int ret = 0; Loading Loading @@ -11024,6 +11051,15 @@ static int tavil_probe(struct platform_device *pdev) } } schedule_work(&tavil->tavil_add_child_devices_work); schedule_work(&tavil->tavil_add_child_devices_work); ret = snd_event_client_register(pdev->dev.parent, &wcd934x_ssr_ops, NULL); if (!ret) { snd_event_notify(pdev->dev.parent, SND_EVENT_UP); } else { pr_err("%s: Registration with SND event fwk failed ret = %d\n", __func__, ret); ret = 0; } return ret; return ret; err_cdc_reg: err_cdc_reg: Loading Loading @@ -11057,6 +11093,8 @@ static int tavil_remove(struct platform_device *pdev) tavil->dsd_config = NULL; tavil->dsd_config = NULL; } } snd_event_client_deregister(pdev->dev.parent); if (tavil->spi) if (tavil->spi) spi_unregister_device(tavil->spi); spi_unregister_device(tavil->spi); for (count = 0; count < tavil->child_count && for (count = 0; count < tavil->child_count && Loading dsp/q6core.c +79 −16 Original line number Original line Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include <dsp/q6core.h> #include <dsp/q6core.h> #include <dsp/audio_cal_utils.h> #include <dsp/audio_cal_utils.h> #include <dsp/apr_audio-v2.h> #include <dsp/apr_audio-v2.h> #include <soc/snd_event.h> #include <ipc/apr.h> #include <ipc/apr.h> #include "adsp_err.h" #include "adsp_err.h" Loading Loading @@ -79,6 +80,7 @@ struct q6core_str { struct cal_type_data *cal_data[CORE_MAX_CAL]; struct cal_type_data *cal_data[CORE_MAX_CAL]; uint32_t mem_map_cal_handle; uint32_t mem_map_cal_handle; int32_t adsp_status; int32_t adsp_status; int32_t avs_state; struct q6core_avcs_ver_info q6core_avcs_ver_info; struct q6core_avcs_ver_info q6core_avcs_ver_info; }; }; Loading Loading @@ -1448,50 +1450,111 @@ static int q6core_init_cal_data(void) return ret; return ret; } } static int q6core_probe(struct platform_device *pdev) static int q6core_is_avs_up(int32_t *avs_state) { { unsigned long timeout; unsigned long timeout; int adsp_ready = 0, rc; int32_t adsp_ready = 0; int ret = 0; timeout = jiffies + timeout = jiffies + msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS); msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS); do { do { if (!adsp_ready) { adsp_ready = q6core_is_adsp_ready(); adsp_ready = q6core_is_adsp_ready(); dev_dbg(&pdev->dev, "%s: ADSP Audio is %s\n", __func__, pr_debug("%s: ADSP Audio is %s\n", __func__, adsp_ready ? "ready" : "not ready"); adsp_ready ? "ready" : "not ready"); } if (adsp_ready) if (adsp_ready) break; break; /* /* * ADSP will be coming up after loading (PD up event) and * ADSP will be coming up after boot up and AVS might * it might not be fully up when the control reaches * not be fully up when the control reaches here. * here. So, wait for 50msec before checking ADSP state * So, wait for 50msec before checking ADSP state again. */ */ msleep(50); msleep(50); } while (time_after(timeout, jiffies)); } while (time_after(timeout, jiffies)); if (!adsp_ready) { *avs_state = adsp_ready; dev_err(&pdev->dev, "%s: Timeout. ADSP Audio is %s\n", pr_debug("%s: ADSP Audio is %s\n", __func__, __func__, adsp_ready ? "ready" : "not ready"); adsp_ready ? "ready" : "not ready"); return -ETIMEDOUT; if (!adsp_ready) { pr_err_ratelimited("%s: Timeout. ADSP Audio is not ready\n", __func__); ret = -ETIMEDOUT; } return ret; } } static int q6core_ssr_enable(struct device *dev, void *data) { int32_t avs_state = 0; int ret = 0; if (!dev) { pr_err("%s: dev is NULL\n", __func__); return -EINVAL; } if (!q6core_lcl.avs_state) { ret = q6core_is_avs_up(&avs_state); if (ret < 0) goto err; q6core_lcl.avs_state = avs_state; } err: return ret; } static void q6core_ssr_disable(struct device *dev, void *data) { /* Reset AVS state to 0 */ q6core_lcl.avs_state = 0; } static const struct snd_event_ops q6core_ssr_ops = { .enable = q6core_ssr_enable, .disable = q6core_ssr_disable, }; static int q6core_probe(struct platform_device *pdev) { int32_t avs_state = 0; int rc = 0; rc = q6core_is_avs_up(&avs_state); if (rc < 0) goto err; q6core_lcl.avs_state = avs_state; rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); if (rc) { if (rc) { dev_err(&pdev->dev, "%s: failed to add child nodes, rc=%d\n", dev_err(&pdev->dev, "%s: failed to add child nodes, rc=%d\n", __func__, rc); __func__, rc); return -EINVAL; rc = -EINVAL; goto err; } } dev_dbg(&pdev->dev, "%s: added child node\n", __func__); dev_dbg(&pdev->dev, "%s: added child node\n", __func__); return 0; rc = snd_event_client_register(&pdev->dev, &q6core_ssr_ops, NULL); if (!rc) { snd_event_notify(&pdev->dev, SND_EVENT_UP); } else { dev_err(&pdev->dev, "%s: Registration with SND event fwk failed rc = %d\n", __func__, rc); rc = 0; } err: return rc; } } static int q6core_remove(struct platform_device *pdev) static int q6core_remove(struct platform_device *pdev) { { snd_event_client_deregister(&pdev->dev); of_platform_depopulate(&pdev->dev); of_platform_depopulate(&pdev->dev); return 0; return 0; } } Loading include/soc/snd_event.h 0 → 100644 +79 −0 Original line number Original line Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2018, The Linux Foundation. All rights reserved. */ #ifndef _SND_EVENT_H_ #define _SND_EVENT_H_ enum { SND_EVENT_DOWN = 0, SND_EVENT_UP, }; struct snd_event_clients; struct snd_event_ops { int (*enable)(struct device *dev, void *data); void (*disable)(struct device *dev, void *data); }; #ifdef CONFIG_SND_EVENT int snd_event_client_register(struct device *dev, const struct snd_event_ops *snd_ev_ops, void *data); int snd_event_client_deregister(struct device *dev); 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_deregister(struct device *dev); int snd_event_notify(struct device *dev, unsigned int state); void snd_event_mstr_add_client(struct snd_event_clients **snd_clients, int (*compare)(struct device *, void *), void *data); inline bool is_snd_event_fwk_enabled(void) { return 1; } #else int snd_event_client_register(struct device *dev, const struct snd_event_ops *snd_ev_ops, void *data) { return 0; } int snd_event_client_deregister(struct device *dev) { return 0; } int snd_event_master_register(struct device *dev, const struct snd_event_ops *ops, struct snd_event_clients *clients, void *data) { return 0; } int snd_event_master_deregister(struct device *dev) { return 0; } int snd_event_notify(struct device *dev, unsigned int state) { return 0; } void snd_event_mstr_add_client(struct snd_event_clients **snd_clients, int (*compare)(struct device *, void *), void *data) { return; } inline bool is_snd_event_fwk_enabled(void) { return 0; } #endif /* CONFIG_SND_EVENT */ #endif /* _SND_EVENT_H_ */ ipc/apr.c +21 −0 Original line number Original line Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include <linux/of_platform.h> #include <linux/of_platform.h> #include <soc/qcom/subsystem_restart.h> #include <soc/qcom/subsystem_restart.h> #include <soc/qcom/scm.h> #include <soc/qcom/scm.h> #include <soc/snd_event.h> #include <dsp/apr_audio-v2.h> #include <dsp/apr_audio-v2.h> #include <dsp/audio_notifier.h> #include <dsp/audio_notifier.h> #include <ipc/apr.h> #include <ipc/apr.h> Loading Loading @@ -281,9 +282,19 @@ int apr_set_q6_state(enum apr_subsys_state state) } } EXPORT_SYMBOL(apr_set_q6_state); EXPORT_SYMBOL(apr_set_q6_state); static void apr_ssr_disable(struct device *dev, void *data) { apr_set_q6_state(APR_SUBSYS_DOWN); } static const struct snd_event_ops apr_ssr_ops = { .disable = apr_ssr_disable, }; static void apr_adsp_down(unsigned long opcode) static void apr_adsp_down(unsigned long opcode) { { pr_info("%s: Q6 is Down\n", __func__); pr_info("%s: Q6 is Down\n", __func__); snd_event_notify(apr_priv->dev, SND_EVENT_DOWN); apr_set_q6_state(APR_SUBSYS_DOWN); apr_set_q6_state(APR_SUBSYS_DOWN); dispatch_event(opcode, APR_DEST_QDSP6); dispatch_event(opcode, APR_DEST_QDSP6); } } Loading @@ -308,6 +319,7 @@ static void apr_adsp_up(void) if (apr_priv->is_initial_boot) if (apr_priv->is_initial_boot) schedule_work(&apr_priv->add_chld_dev_work); schedule_work(&apr_priv->add_chld_dev_work); spin_unlock(&apr_priv->apr_lock); spin_unlock(&apr_priv->apr_lock); snd_event_notify(apr_priv->dev, SND_EVENT_UP); } } int apr_load_adsp_image(void) int apr_load_adsp_image(void) Loading Loading @@ -1186,11 +1198,20 @@ static int apr_probe(struct platform_device *pdev) } } apr_tal_init(); apr_tal_init(); ret = snd_event_client_register(&pdev->dev, &apr_ssr_ops, NULL); if (ret) { pr_err("%s: Registration with Audio SSR FW failed ret = %d\n", __func__, ret); ret = 0; } return apr_debug_init(); return apr_debug_init(); } } static int apr_remove(struct platform_device *pdev) static int apr_remove(struct platform_device *pdev) { { snd_event_client_deregister(&pdev->dev); apr_cleanup(); apr_cleanup(); apr_tal_exit(); apr_tal_exit(); apr_priv = NULL; apr_priv = NULL; Loading soc/Android.mk +10 −0 Original line number Original line Diff line number Diff line Loading @@ -82,6 +82,16 @@ LOCAL_MODULE_DEBUG_ENABLE := true LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) include $(DLKM_DIR)/AndroidKernelModule.mk include $(DLKM_DIR)/AndroidKernelModule.mk ########################################################### ########################################################### ifeq ($(call is-board-platform-in-list, ),true) include $(CLEAR_VARS) LOCAL_MODULE := $(AUDIO_CHIPSET)_snd_event.ko LOCAL_MODULE_KBUILD_NAME := snd_event_dlkm.ko LOCAL_MODULE_TAGS := optional LOCAL_MODULE_DEBUG_ENABLE := true LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) include $(DLKM_DIR)/AndroidKernelModule.mk endif ########################################################### endif # DLKM check endif # DLKM check endif # supported target check endif # supported target check Loading
asoc/codecs/wcd934x/wcd934x.c +40 −2 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h> #include <linux/mfd/wcd9xxx/wcd9xxx_registers.h> #include <linux/mfd/wcd9xxx/wcd9xxx_registers.h> #include <soc/swr-wcd.h> #include <soc/swr-wcd.h> #include <soc/snd_event.h> #include <sound/pcm.h> #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/pcm_params.h> #include <sound/soc.h> #include <sound/soc.h> Loading Loading @@ -9979,6 +9980,7 @@ static int tavil_device_down(struct wcd9xxx *wcd9xxx) priv = snd_soc_codec_get_drvdata(codec); priv = snd_soc_codec_get_drvdata(codec); for (count = 0; count < NUM_CODEC_DAIS; count++) for (count = 0; count < NUM_CODEC_DAIS; count++) priv->dai[count].bus_down_in_recovery = true; priv->dai[count].bus_down_in_recovery = true; snd_event_notify(priv->dev->parent, SND_EVENT_DOWN); priv->mbhc->wcd_mbhc.deinit_in_progress = true; priv->mbhc->wcd_mbhc.deinit_in_progress = true; if (delayed_work_pending(&priv->spk_anc_dwork.dwork)) if (delayed_work_pending(&priv->spk_anc_dwork.dwork)) Loading Loading @@ -10006,6 +10008,7 @@ static int tavil_device_down(struct wcd9xxx *wcd9xxx) swrm_wcd_notify(priv->swr.ctrl_data[0].swr_pdev, swrm_wcd_notify(priv->swr.ctrl_data[0].swr_pdev, SWR_DEVICE_DOWN, NULL); SWR_DEVICE_DOWN, NULL); tavil_dsd_reset(priv->dsd_config); tavil_dsd_reset(priv->dsd_config); if (!is_snd_event_fwk_enabled()) snd_soc_card_change_online_state(codec->component.card, 0); snd_soc_card_change_online_state(codec->component.card, 0); wcd_dsp_ssr_event(priv->wdsp_cntl, WCD_CDC_DOWN_EVENT); wcd_dsp_ssr_event(priv->wdsp_cntl, WCD_CDC_DOWN_EVENT); wcd_resmgr_set_sido_input_src_locked(priv->resmgr, wcd_resmgr_set_sido_input_src_locked(priv->resmgr, Loading Loading @@ -10039,6 +10042,7 @@ static int tavil_post_reset_cb(struct wcd9xxx *wcd9xxx) tavil_slimbus_slave_port_cfg.slave_dev_pgd_la = tavil_slimbus_slave_port_cfg.slave_dev_pgd_la = control->slim->laddr; control->slim->laddr; tavil_init_slim_slave_cfg(codec); tavil_init_slim_slave_cfg(codec); if (!is_snd_event_fwk_enabled()) snd_soc_card_change_online_state(codec->component.card, 1); snd_soc_card_change_online_state(codec->component.card, 1); for (i = 0; i < TAVIL_MAX_MICBIAS; i++) for (i = 0; i < TAVIL_MAX_MICBIAS; i++) Loading Loading @@ -10102,6 +10106,7 @@ static int tavil_post_reset_cb(struct wcd9xxx *wcd9xxx) */ */ tavil_vote_svs(tavil, false); tavil_vote_svs(tavil, false); wcd_dsp_ssr_event(tavil->wdsp_cntl, WCD_CDC_UP_EVENT); wcd_dsp_ssr_event(tavil->wdsp_cntl, WCD_CDC_UP_EVENT); snd_event_notify(tavil->dev->parent, SND_EVENT_UP); done: done: mutex_unlock(&tavil->codec_mutex); mutex_unlock(&tavil->codec_mutex); Loading Loading @@ -10900,6 +10905,28 @@ struct wcd_dsp_cntl *tavil_get_wcd_dsp_cntl(struct device *dev) } } EXPORT_SYMBOL(tavil_get_wcd_dsp_cntl); EXPORT_SYMBOL(tavil_get_wcd_dsp_cntl); static void wcd934x_ssr_disable(struct device *dev, void *data) { struct wcd9xxx *wcd9xxx = dev_get_drvdata(dev); struct tavil_priv *tavil; struct snd_soc_codec *codec; int count = 0; if (!wcd9xxx) { dev_dbg(dev, "%s: wcd9xxx pointer NULL.\n", __func__); return; } codec = (struct snd_soc_codec *)(wcd9xxx->ssr_priv); tavil = snd_soc_codec_get_drvdata(codec); for (count = 0; count < NUM_CODEC_DAIS; count++) tavil->dai[count].bus_down_in_recovery = true; } static const struct snd_event_ops wcd934x_ssr_ops = { .disable = wcd934x_ssr_disable, }; static int tavil_probe(struct platform_device *pdev) static int tavil_probe(struct platform_device *pdev) { { int ret = 0; int ret = 0; Loading Loading @@ -11024,6 +11051,15 @@ static int tavil_probe(struct platform_device *pdev) } } schedule_work(&tavil->tavil_add_child_devices_work); schedule_work(&tavil->tavil_add_child_devices_work); ret = snd_event_client_register(pdev->dev.parent, &wcd934x_ssr_ops, NULL); if (!ret) { snd_event_notify(pdev->dev.parent, SND_EVENT_UP); } else { pr_err("%s: Registration with SND event fwk failed ret = %d\n", __func__, ret); ret = 0; } return ret; return ret; err_cdc_reg: err_cdc_reg: Loading Loading @@ -11057,6 +11093,8 @@ static int tavil_remove(struct platform_device *pdev) tavil->dsd_config = NULL; tavil->dsd_config = NULL; } } snd_event_client_deregister(pdev->dev.parent); if (tavil->spi) if (tavil->spi) spi_unregister_device(tavil->spi); spi_unregister_device(tavil->spi); for (count = 0; count < tavil->child_count && for (count = 0; count < tavil->child_count && Loading
dsp/q6core.c +79 −16 Original line number Original line Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include <dsp/q6core.h> #include <dsp/q6core.h> #include <dsp/audio_cal_utils.h> #include <dsp/audio_cal_utils.h> #include <dsp/apr_audio-v2.h> #include <dsp/apr_audio-v2.h> #include <soc/snd_event.h> #include <ipc/apr.h> #include <ipc/apr.h> #include "adsp_err.h" #include "adsp_err.h" Loading Loading @@ -79,6 +80,7 @@ struct q6core_str { struct cal_type_data *cal_data[CORE_MAX_CAL]; struct cal_type_data *cal_data[CORE_MAX_CAL]; uint32_t mem_map_cal_handle; uint32_t mem_map_cal_handle; int32_t adsp_status; int32_t adsp_status; int32_t avs_state; struct q6core_avcs_ver_info q6core_avcs_ver_info; struct q6core_avcs_ver_info q6core_avcs_ver_info; }; }; Loading Loading @@ -1448,50 +1450,111 @@ static int q6core_init_cal_data(void) return ret; return ret; } } static int q6core_probe(struct platform_device *pdev) static int q6core_is_avs_up(int32_t *avs_state) { { unsigned long timeout; unsigned long timeout; int adsp_ready = 0, rc; int32_t adsp_ready = 0; int ret = 0; timeout = jiffies + timeout = jiffies + msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS); msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS); do { do { if (!adsp_ready) { adsp_ready = q6core_is_adsp_ready(); adsp_ready = q6core_is_adsp_ready(); dev_dbg(&pdev->dev, "%s: ADSP Audio is %s\n", __func__, pr_debug("%s: ADSP Audio is %s\n", __func__, adsp_ready ? "ready" : "not ready"); adsp_ready ? "ready" : "not ready"); } if (adsp_ready) if (adsp_ready) break; break; /* /* * ADSP will be coming up after loading (PD up event) and * ADSP will be coming up after boot up and AVS might * it might not be fully up when the control reaches * not be fully up when the control reaches here. * here. So, wait for 50msec before checking ADSP state * So, wait for 50msec before checking ADSP state again. */ */ msleep(50); msleep(50); } while (time_after(timeout, jiffies)); } while (time_after(timeout, jiffies)); if (!adsp_ready) { *avs_state = adsp_ready; dev_err(&pdev->dev, "%s: Timeout. ADSP Audio is %s\n", pr_debug("%s: ADSP Audio is %s\n", __func__, __func__, adsp_ready ? "ready" : "not ready"); adsp_ready ? "ready" : "not ready"); return -ETIMEDOUT; if (!adsp_ready) { pr_err_ratelimited("%s: Timeout. ADSP Audio is not ready\n", __func__); ret = -ETIMEDOUT; } return ret; } } static int q6core_ssr_enable(struct device *dev, void *data) { int32_t avs_state = 0; int ret = 0; if (!dev) { pr_err("%s: dev is NULL\n", __func__); return -EINVAL; } if (!q6core_lcl.avs_state) { ret = q6core_is_avs_up(&avs_state); if (ret < 0) goto err; q6core_lcl.avs_state = avs_state; } err: return ret; } static void q6core_ssr_disable(struct device *dev, void *data) { /* Reset AVS state to 0 */ q6core_lcl.avs_state = 0; } static const struct snd_event_ops q6core_ssr_ops = { .enable = q6core_ssr_enable, .disable = q6core_ssr_disable, }; static int q6core_probe(struct platform_device *pdev) { int32_t avs_state = 0; int rc = 0; rc = q6core_is_avs_up(&avs_state); if (rc < 0) goto err; q6core_lcl.avs_state = avs_state; rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); if (rc) { if (rc) { dev_err(&pdev->dev, "%s: failed to add child nodes, rc=%d\n", dev_err(&pdev->dev, "%s: failed to add child nodes, rc=%d\n", __func__, rc); __func__, rc); return -EINVAL; rc = -EINVAL; goto err; } } dev_dbg(&pdev->dev, "%s: added child node\n", __func__); dev_dbg(&pdev->dev, "%s: added child node\n", __func__); return 0; rc = snd_event_client_register(&pdev->dev, &q6core_ssr_ops, NULL); if (!rc) { snd_event_notify(&pdev->dev, SND_EVENT_UP); } else { dev_err(&pdev->dev, "%s: Registration with SND event fwk failed rc = %d\n", __func__, rc); rc = 0; } err: return rc; } } static int q6core_remove(struct platform_device *pdev) static int q6core_remove(struct platform_device *pdev) { { snd_event_client_deregister(&pdev->dev); of_platform_depopulate(&pdev->dev); of_platform_depopulate(&pdev->dev); return 0; return 0; } } Loading
include/soc/snd_event.h 0 → 100644 +79 −0 Original line number Original line Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2018, The Linux Foundation. All rights reserved. */ #ifndef _SND_EVENT_H_ #define _SND_EVENT_H_ enum { SND_EVENT_DOWN = 0, SND_EVENT_UP, }; struct snd_event_clients; struct snd_event_ops { int (*enable)(struct device *dev, void *data); void (*disable)(struct device *dev, void *data); }; #ifdef CONFIG_SND_EVENT int snd_event_client_register(struct device *dev, const struct snd_event_ops *snd_ev_ops, void *data); int snd_event_client_deregister(struct device *dev); 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_deregister(struct device *dev); int snd_event_notify(struct device *dev, unsigned int state); void snd_event_mstr_add_client(struct snd_event_clients **snd_clients, int (*compare)(struct device *, void *), void *data); inline bool is_snd_event_fwk_enabled(void) { return 1; } #else int snd_event_client_register(struct device *dev, const struct snd_event_ops *snd_ev_ops, void *data) { return 0; } int snd_event_client_deregister(struct device *dev) { return 0; } int snd_event_master_register(struct device *dev, const struct snd_event_ops *ops, struct snd_event_clients *clients, void *data) { return 0; } int snd_event_master_deregister(struct device *dev) { return 0; } int snd_event_notify(struct device *dev, unsigned int state) { return 0; } void snd_event_mstr_add_client(struct snd_event_clients **snd_clients, int (*compare)(struct device *, void *), void *data) { return; } inline bool is_snd_event_fwk_enabled(void) { return 0; } #endif /* CONFIG_SND_EVENT */ #endif /* _SND_EVENT_H_ */
ipc/apr.c +21 −0 Original line number Original line Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include <linux/of_platform.h> #include <linux/of_platform.h> #include <soc/qcom/subsystem_restart.h> #include <soc/qcom/subsystem_restart.h> #include <soc/qcom/scm.h> #include <soc/qcom/scm.h> #include <soc/snd_event.h> #include <dsp/apr_audio-v2.h> #include <dsp/apr_audio-v2.h> #include <dsp/audio_notifier.h> #include <dsp/audio_notifier.h> #include <ipc/apr.h> #include <ipc/apr.h> Loading Loading @@ -281,9 +282,19 @@ int apr_set_q6_state(enum apr_subsys_state state) } } EXPORT_SYMBOL(apr_set_q6_state); EXPORT_SYMBOL(apr_set_q6_state); static void apr_ssr_disable(struct device *dev, void *data) { apr_set_q6_state(APR_SUBSYS_DOWN); } static const struct snd_event_ops apr_ssr_ops = { .disable = apr_ssr_disable, }; static void apr_adsp_down(unsigned long opcode) static void apr_adsp_down(unsigned long opcode) { { pr_info("%s: Q6 is Down\n", __func__); pr_info("%s: Q6 is Down\n", __func__); snd_event_notify(apr_priv->dev, SND_EVENT_DOWN); apr_set_q6_state(APR_SUBSYS_DOWN); apr_set_q6_state(APR_SUBSYS_DOWN); dispatch_event(opcode, APR_DEST_QDSP6); dispatch_event(opcode, APR_DEST_QDSP6); } } Loading @@ -308,6 +319,7 @@ static void apr_adsp_up(void) if (apr_priv->is_initial_boot) if (apr_priv->is_initial_boot) schedule_work(&apr_priv->add_chld_dev_work); schedule_work(&apr_priv->add_chld_dev_work); spin_unlock(&apr_priv->apr_lock); spin_unlock(&apr_priv->apr_lock); snd_event_notify(apr_priv->dev, SND_EVENT_UP); } } int apr_load_adsp_image(void) int apr_load_adsp_image(void) Loading Loading @@ -1186,11 +1198,20 @@ static int apr_probe(struct platform_device *pdev) } } apr_tal_init(); apr_tal_init(); ret = snd_event_client_register(&pdev->dev, &apr_ssr_ops, NULL); if (ret) { pr_err("%s: Registration with Audio SSR FW failed ret = %d\n", __func__, ret); ret = 0; } return apr_debug_init(); return apr_debug_init(); } } static int apr_remove(struct platform_device *pdev) static int apr_remove(struct platform_device *pdev) { { snd_event_client_deregister(&pdev->dev); apr_cleanup(); apr_cleanup(); apr_tal_exit(); apr_tal_exit(); apr_priv = NULL; apr_priv = NULL; Loading
soc/Android.mk +10 −0 Original line number Original line Diff line number Diff line Loading @@ -82,6 +82,16 @@ LOCAL_MODULE_DEBUG_ENABLE := true LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) include $(DLKM_DIR)/AndroidKernelModule.mk include $(DLKM_DIR)/AndroidKernelModule.mk ########################################################### ########################################################### ifeq ($(call is-board-platform-in-list, ),true) include $(CLEAR_VARS) LOCAL_MODULE := $(AUDIO_CHIPSET)_snd_event.ko LOCAL_MODULE_KBUILD_NAME := snd_event_dlkm.ko LOCAL_MODULE_TAGS := optional LOCAL_MODULE_DEBUG_ENABLE := true LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) include $(DLKM_DIR)/AndroidKernelModule.mk endif ########################################################### endif # DLKM check endif # DLKM check endif # supported target check endif # supported target check