diff --git a/asoc/kona.c b/asoc/kona.c index 82e8b6a710..498abb04cb 100644 --- a/asoc/kona.c +++ b/asoc/kona.c @@ -34,6 +34,7 @@ #include "codecs/bolero/wsa-macro.h" #include "kona-port-config.h" #include "msm-audio-defs.h" +#include "msm_common.h" #define DRV_NAME "kona-asoc-snd" #define __CHIPSET__ "KONA " @@ -53,6 +54,7 @@ struct msm_asoc_mach_data { struct snd_info_entry *codec_root; + struct msm_common_pdata *common_pdata; int lito_v2_enabled; struct device_node *dmic01_gpio_p; /* used by pinctrl API */ struct device_node *dmic23_gpio_p; /* used by pinctrl API */ @@ -413,6 +415,11 @@ static int msm_wcn_init(struct snd_soc_pcm_runtime *rtd) tx_ch, ARRAY_SIZE(rx_ch), rx_ch); } +static struct snd_soc_ops msm_common_be_ops = { + .startup = msm_common_snd_startup, + .shutdown = msm_common_snd_shutdown, +}; + /* Digital audio interface glue - connects codec <---> CPU */ static struct snd_soc_dai_link msm_common_dai_links[] = { { @@ -426,6 +433,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { .codec_dai_name = "wsa_macro_rx1", .codec_name = "bolero_codec", .init = &msm_int_audrx_init, + .ops = &msm_common_be_ops, .be_hw_params_fixup = msm_be_hw_params_fixup, .ignore_suspend = 1, /* this dainlink has playback support */ @@ -441,6 +449,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { SND_SOC_DPCM_TRIGGER_POST}, .codec_dai_name = "wsa_macro_rx_mix", .codec_name = "bolero_codec", + .ops = &msm_common_be_ops, .be_hw_params_fixup = msm_be_hw_params_fixup, .ignore_suspend = 1, /* this dainlink has playback support */ @@ -456,6 +465,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { SND_SOC_DPCM_TRIGGER_POST}, .codec_dai_name = "wsa_macro_echo", .codec_name = "bolero_codec", + .ops = &msm_common_be_ops, .be_hw_params_fixup = msm_be_hw_params_fixup, .ignore_suspend = 1, /* this dainlink has playback support */ @@ -471,6 +481,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { SND_SOC_DPCM_TRIGGER_POST}, .codec_dai_name = "rx_macro_rx1", .codec_name = "bolero_codec", + .ops = &msm_common_be_ops, .be_hw_params_fixup = msm_be_hw_params_fixup, .ignore_suspend = 1, /* this dainlink has playback support */ @@ -486,6 +497,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { SND_SOC_DPCM_TRIGGER_POST}, .codec_dai_name = "rx_macro_rx2", .codec_name = "bolero_codec", + .ops = &msm_common_be_ops, .be_hw_params_fixup = msm_be_hw_params_fixup, .ignore_suspend = 1, /* this dainlink has playback support */ @@ -501,6 +513,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { SND_SOC_DPCM_TRIGGER_POST}, .codec_dai_name = "rx_macro_rx3", .codec_name = "bolero_codec", + .ops = &msm_common_be_ops, .be_hw_params_fixup = msm_be_hw_params_fixup, .ignore_suspend = 1, /* this dainlink has playback support */ @@ -516,6 +529,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { SND_SOC_DPCM_TRIGGER_POST}, .codec_dai_name = "rx_macro_rx4", .codec_name = "bolero_codec", + .ops = &msm_common_be_ops, .be_hw_params_fixup = msm_be_hw_params_fixup, .ignore_suspend = 1, /* this dainlink has playback support */ @@ -531,6 +545,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { SND_SOC_DPCM_TRIGGER_POST}, .codec_dai_name = "tx_macro_tx1", .codec_name = "bolero_codec", + .ops = &msm_common_be_ops, .be_hw_params_fixup = msm_be_hw_params_fixup, .ignore_suspend = 1, /* this dainlink has playback support */ @@ -546,6 +561,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { SND_SOC_DPCM_TRIGGER_POST}, .codec_dai_name = "tx_macro_tx2", .codec_name = "bolero_codec", + .ops = &msm_common_be_ops, .be_hw_params_fixup = msm_be_hw_params_fixup, .ignore_suspend = 1, /* this dainlink has playback support */ @@ -561,6 +577,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { SND_SOC_DPCM_TRIGGER_POST}, .codec_dai_name = "va_macro_tx1", .codec_name = "bolero_codec", + .ops = &msm_common_be_ops, .be_hw_params_fixup = msm_be_hw_params_fixup, .ignore_suspend = 1, /* this dainlink has playback support */ @@ -576,6 +593,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { SND_SOC_DPCM_TRIGGER_POST}, .codec_dai_name = "va_macro_tx2", .codec_name = "bolero_codec", + .ops = &msm_common_be_ops, .be_hw_params_fixup = msm_be_hw_params_fixup, .ignore_suspend = 1, /* this dainlink has playback support */ @@ -591,6 +609,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { SND_SOC_DPCM_TRIGGER_POST}, .codec_dai_name = "va_macro_tx3", .codec_name = "bolero_codec", + .ops = &msm_common_be_ops, .be_hw_params_fixup = msm_be_hw_params_fixup, .ignore_suspend = 1, /* this dainlink has playback support */ @@ -605,6 +624,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .codec_name = "btfmslim_slave", + .ops = &msm_common_be_ops, .codec_dai_name = "btfm_bt_sco_a2dp_slim_rx", .ignore_suspend = 1, /* this dainlink has playback support */ @@ -619,6 +639,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .codec_name = "btfmslim_slave", + .ops = &msm_common_be_ops, .codec_dai_name = "btfm_bt_sco_slim_tx", .ignore_suspend = 1, .ignore_pmdown_time = 1, @@ -636,6 +657,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { SND_SOC_DPCM_TRIGGER_POST}, .ignore_pmdown_time = 1, .ignore_suspend = 1, + .ops = &msm_common_be_ops, }, { .name = LPASS_BE_USB_AUDIO_RX, @@ -649,6 +671,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { SND_SOC_DPCM_TRIGGER_POST}, .ignore_pmdown_time = 1, .ignore_suspend = 1, + .ops = &msm_common_be_ops, }, { .name = LPASS_BE_USB_AUDIO_TX, @@ -661,6 +684,7 @@ static struct snd_soc_dai_link msm_common_dai_links[] = { .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .ignore_suspend = 1, + .ops = &msm_common_be_ops, }, }; @@ -1346,6 +1370,27 @@ static int msm_audio_ssr_register(struct device *dev) return ret; } +struct msm_common_pdata *msm_common_get_pdata(struct snd_soc_card *card) +{ + struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); + + if (!pdata) + return NULL; + + return pdata->common_pdata; +} + +void msm_common_set_pdata(struct snd_soc_card *card, + struct msm_common_pdata *common_pdata) +{ + struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); + + if (!pdata) + return; + + pdata->common_pdata = common_pdata; +} + static int msm_asoc_machine_probe(struct platform_device *pdev) { struct snd_soc_card *card = NULL; @@ -1415,6 +1460,8 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) dev_info(&pdev->dev, "%s: Sound card %s registered\n", __func__, card->name); + msm_common_snd_init(pdev, card); + pdata->hph_en1_gpio_p = of_parse_phandle(pdev->dev.of_node, "qcom,hph-en1-gpio", 0); if (!pdata->hph_en1_gpio_p) { @@ -1510,6 +1557,16 @@ err: static int msm_asoc_machine_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); + struct msm_asoc_mach_data *pdata = NULL; + struct msm_common_pdata *common_pdata = NULL; + + if (card) + pdata = snd_soc_card_get_drvdata(card); + + if (pdata) + common_pdata = pdata->common_pdata; + + msm_common_snd_deinit(common_pdata); snd_event_master_deregister(&pdev->dev); snd_soc_unregister_card(card); diff --git a/asoc/msm_common.c b/asoc/msm_common.c index e8b2bd9a0e..d9860d94f4 100644 --- a/asoc/msm_common.c +++ b/asoc/msm_common.c @@ -15,9 +15,116 @@ #include #include #include -#include "asoc/msm-cdc-pinctrl.h" +#include +#include +#include #include "msm_common.h" +#define to_asoc_mach_common_pdata(kobj) \ + container_of((kobj), struct msm_common_pdata, aud_dev_kobj) + +#define DEVICE_ENABLE 1 +#define DEVICE_DISABLE 0 + +static struct attribute device_state_attr = { + .name = "state", + .mode = 0660, +}; + +#define MAX_USR_INPUT 10 + +static ssize_t aud_dev_sysfs_store(struct kobject *kobj, + struct attribute *attr, + const char *buf, size_t count) +{ + ssize_t ret = -EINVAL; + struct msm_common_pdata *pdata = to_asoc_mach_common_pdata(kobj); + uint32_t pcm_id, state = 0; + + if (count > MAX_USR_INPUT) { + pr_err("%s: invalid string written", __func__); + goto done; + } + + sscanf(buf, "%d %d", &pcm_id, &state); + + if ((pcm_id > pdata->num_aud_devs) || (pcm_id < 0)) { + pr_err("%s: invalid pcm id %d \n", __func__, pcm_id); + goto done; + } + + if ((state > DEVICE_ENABLE) || (state < DEVICE_DISABLE)) { + pr_err("%s: invalid state %d \n", __func__, state); + goto done; + } + pr_info("%s: pcm_id %d state %d \n", __func__, pcm_id, state); + + pdata->aud_dev_state[pcm_id] = state; + if ( state == DEVICE_ENABLE && (pdata->dsp_sessions_closed != 0)) + pdata->dsp_sessions_closed = 0; + + ret = count; +done: + return ret; +} + +static const struct sysfs_ops aud_dev_sysfs_ops = { + .store = aud_dev_sysfs_store, +}; + +static struct kobj_type aud_dev_ktype = { + .sysfs_ops = &aud_dev_sysfs_ops, +}; + +static int aud_dev_sysfs_init(struct msm_common_pdata *pdata) +{ + int ret = 0; + char dir[10] = "aud_dev"; + + ret = kobject_init_and_add(&pdata->aud_dev_kobj, &aud_dev_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(&pdata->aud_dev_kobj, &device_state_attr); + if (ret < 0) { + pr_err("%s: Failed to add wdsp_boot sysfs entry to %s\n", + __func__, dir); + goto fail_create_file; + } + + return ret; + +fail_create_file: + kobject_put(&pdata->aud_dev_kobj); +done: + return ret; +} + +static void check_userspace_service_state(struct snd_soc_pcm_runtime *rtd, + struct msm_common_pdata *pdata) +{ + dev_info(rtd->card->dev,"%s: pcm_id %d state %d\n", __func__, + rtd->num, pdata->aud_dev_state[rtd->num]); + + if (pdata->aud_dev_state[rtd->num] == DEVICE_ENABLE) { + dev_info(rtd->card->dev, "%s userspace service crashed\n", + __func__); + if (pdata->dsp_sessions_closed == 0) { + /*Issue close all graph cmd to DSP*/ + gecko_core_apm_close_all(); + /*unmap all dma mapped buffers*/ + msm_audio_ion_crash_handler(); + pdata->dsp_sessions_closed = 1; + } + /*Reset the state as sysfs node wont be triggred*/ + pdata->aud_dev_state[rtd->num] = 0; + } +} + static int get_intf_index(const char *stream_name) { if (strnstr(stream_name, "PRIMARY", strlen("PRIMARY"))) @@ -54,27 +161,23 @@ int msm_common_snd_startup(struct snd_pcm_substream *substream) return -EINVAL; } - if (index < 0) { - dev_err(rtd->card->dev, - "%s: Invalid Backend interface %d\n", __func__, index); - return -EINVAL; - } - - mutex_lock(&pdata->lock[index]); - if (pdata->mi2s_gpio_p[index]) { - if (atomic_read(&(pdata->mi2s_gpio_ref_cnt[index])) == 0) { - ret = msm_cdc_pinctrl_select_active_state( - pdata->mi2s_gpio_p[index]); - if (ret) { - pr_err("%s: GPIO pinctrl set active failed with %d\n", - __func__, ret); - goto done; + if (index >= 0) { + mutex_lock(&pdata->lock[index]); + if (pdata->mi2s_gpio_p[index]) { + if (atomic_read(&(pdata->mi2s_gpio_ref_cnt[index])) == 0) { + ret = msm_cdc_pinctrl_select_active_state( + pdata->mi2s_gpio_p[index]); + if (ret) { + pr_err("%s:pinctrl set actve fail with %d\n", + __func__, ret); + goto done; + } } + atomic_inc(&(pdata->mi2s_gpio_ref_cnt[index])); } - atomic_inc(&(pdata->mi2s_gpio_ref_cnt[index])); - } done: - mutex_unlock(&pdata->lock[index]); + mutex_unlock(&pdata->lock[index]); + } return ret; } @@ -95,24 +198,23 @@ void msm_common_snd_shutdown(struct snd_pcm_substream *substream) return; } - if (index < 0) { - dev_err(card->dev, - "%s: Invalid Backend interface %d\n", __func__, index); - return; - } + check_userspace_service_state(rtd, pdata); - mutex_lock(&pdata->lock[index]); - if (pdata->mi2s_gpio_p[index]) { - atomic_dec(&pdata->mi2s_gpio_ref_cnt[index]); - if (atomic_read(&pdata->mi2s_gpio_ref_cnt[index]) == 0) { - ret = msm_cdc_pinctrl_select_active_state( - pdata->mi2s_gpio_p[index]); - if (ret) - dev_err(card->dev, "%s: GPIO pinctrl set active failed with %d\n", - __func__, ret); + if (index >= 0) { + mutex_lock(&pdata->lock[index]); + if (pdata->mi2s_gpio_p[index]) { + atomic_dec(&pdata->mi2s_gpio_ref_cnt[index]); + if (atomic_read(&pdata->mi2s_gpio_ref_cnt[index]) == 0) { + ret = msm_cdc_pinctrl_select_active_state( + pdata->mi2s_gpio_p[index]); + if (ret) + dev_err(card->dev, + "%s: pinctrl set actv fail %d\n", + __func__, ret); + } } + mutex_unlock(&pdata->lock[index]); } - mutex_unlock(&pdata->lock[index]); } int msm_common_snd_init(struct platform_device *pdev, struct snd_soc_card *card) @@ -141,6 +243,12 @@ int msm_common_snd_init(struct platform_device *pdev, struct snd_soc_card *card) "qcom,quin-mi2s-gpios", 0); common_pdata->mi2s_gpio_p[SEN_MI2S_TDM_AUXPCM] = of_parse_phandle(pdev->dev.of_node, "qcom,sen-mi2s-gpios", 0); + common_pdata->aud_dev_state = devm_kcalloc(&pdev->dev, card->num_links, + sizeof(uint8_t), GFP_KERNEL); + dev_info(&pdev->dev, "num_links %d \n", card->num_links); + common_pdata->num_aud_devs = card->num_links; + + aud_dev_sysfs_init(common_pdata); msm_common_set_pdata(card, common_pdata); return 0; diff --git a/asoc/msm_common.h b/asoc/msm_common.h index 9b9c008434..7a905c5a48 100644 --- a/asoc/msm_common.h +++ b/asoc/msm_common.h @@ -32,6 +32,10 @@ enum { }; struct msm_common_pdata { + uint8_t *aud_dev_state; + struct kobject aud_dev_kobj; + uint8_t dsp_sessions_closed; + uint32_t num_aud_devs; struct device_node *mi2s_gpio_p[MI2S_TDM_AUXPCM_MAX]; struct mutex lock[MI2S_TDM_AUXPCM_MAX]; atomic_t mi2s_gpio_ref_cnt[MI2S_TDM_AUXPCM_MAX]; diff --git a/dsp/gecko-core.c b/dsp/gecko-core.c index 1c4e05e88d..e5675e5061 100644 --- a/dsp/gecko-core.c +++ b/dsp/gecko-core.c @@ -25,6 +25,7 @@ #define APM_STATE_READY_TIMEOUT_MS 10000 #define Q6_READY_TIMEOUT_MS 1000 #define APM_CMD_GET_GECKO_STATE 0x01001021 +#define APM_CMD_CLOSE_ALL 0x01001013 #define APM_CMD_RSP_GET_GECKO_STATE 0x02001007 #define APM_MODULE_INSTANCE_ID 0x00000001 #define GPR_SVC_ADSP_CORE 0x3 @@ -34,7 +35,7 @@ struct gecko_core { wait_queue_head_t wait; struct mutex lock; bool resp_received; - bool is_ready; + int32_t status; }; struct gecko_core_private { @@ -46,6 +47,13 @@ struct gecko_core_private { }; static struct gecko_core_private *gecko_core_priv; + +/* used to decode basic responses from Gecko */ +struct gecko_cmd_basic_rsp { + uint32_t opcode; + int32_t status; +}; + struct apm_cmd_rsp_get_gecko_status_t { @@ -61,20 +69,34 @@ struct apm_cmd_rsp_get_gecko_status_t static int gecko_core_callback(struct gpr_device *adev, void *data) { struct gecko_core *core = dev_get_drvdata(&adev->dev); - struct apm_cmd_rsp_get_gecko_status_t *result; + struct apm_cmd_rsp_get_gecko_status_t *gecko_status_rsp; + struct gecko_cmd_basic_rsp *basic_rsp; struct gpr_hdr *hdr = data; - result = GPR_PKT_GET_PAYLOAD(struct apm_cmd_rsp_get_gecko_status_t, data); - dev_err(&adev->dev ,"%s: Payload %x",__func__, hdr->opcode); + dev_info(&adev->dev ,"%s: Payload %x",__func__, hdr->opcode); switch (hdr->opcode) { case GPR_IBASIC_RSP_RESULT: - dev_err(&adev->dev ,"%s: Failed response received",__func__); + basic_rsp = GPR_PKT_GET_PAYLOAD( + struct gecko_cmd_basic_rsp, + data); + dev_info(&adev->dev ,"%s: op %x status %d", __func__, + basic_rsp->opcode, basic_rsp->status); + if (basic_rsp->opcode == APM_CMD_CLOSE_ALL) { + core->status = basic_rsp->status; + } else { + dev_err(&adev->dev ,"%s: Failed response received", + __func__); + } core->resp_received = true; break; case APM_CMD_RSP_GET_GECKO_STATE: - dev_err(&adev->dev ,"%s: sucess response received",__func__); - core->is_ready = result->status; + gecko_status_rsp = + GPR_PKT_GET_PAYLOAD( + struct apm_cmd_rsp_get_gecko_status_t, + data); + dev_info(&adev->dev ,"%s: sucess response received",__func__); + core->status = gecko_status_rsp->status; core->resp_received = true; break; default: @@ -93,12 +115,12 @@ static bool __gecko_core_is_apm_ready(struct gecko_core *core) struct gpr_device *adev = core->adev; struct gpr_pkt pkt; int rc; + bool ret = false; pkt.hdr.header = GPR_SET_FIELD(GPR_PKT_VERSION, GPR_PKT_VER) | GPR_SET_FIELD(GPR_PKT_HEADER_SIZE, GPR_PKT_HEADER_WORD_SIZE_V) | GPR_SET_FIELD(GPR_PKT_PACKET_SIZE, GPR_PKT_HEADER_BYTE_SIZE_V); - pkt.hdr.opcode = APM_CMD_GET_GECKO_STATE; pkt.hdr.dst_port = APM_MODULE_INSTANCE_ID; pkt.hdr.src_port = GPR_SVC_ADSP_CORE; pkt.hdr.dst_domain_id = GPR_IDS_DOMAIN_ID_ADSP_V; @@ -108,31 +130,30 @@ static bool __gecko_core_is_apm_ready(struct gecko_core *core) dev_err(gecko_core_priv->dev, "%s: send_command ret\n", __func__); rc = gpr_send_pkt(adev, &pkt); - if (rc < 0) - return false; + if (rc < 0) { + ret = false; + goto done; + } rc = wait_event_timeout(core->wait, (core->resp_received), msecs_to_jiffies(Q6_READY_TIMEOUT_MS)); - dev_err(gecko_core_priv->dev, "%s: wait event unblocked \n", __func__); -// core->resp_received = true; -// core->is_ready = true; - if (rc > 0 && core->resp_received) { - core->resp_received = false; + dev_dbg(gecko_core_priv->dev, "%s: wait event unblocked \n", __func__); - if (core->is_ready) - return true; + if (rc > 0 && core->resp_received) { + ret = core->status; } else { dev_err(gecko_core_priv->dev, "%s: command timedout, ret\n", __func__); } - - return false; +done: + core->resp_received = false; + return ret; } /** * gecko_core_is_apm_ready() - Get status of adsp * - * Return: Will be an true if apm is ready and false if not. + * Return: Will return true if apm is ready and false if not. */ bool gecko_core_is_apm_ready(void) { @@ -141,14 +162,15 @@ bool gecko_core_is_apm_ready(void) struct gecko_core *core; if (!gecko_core_priv) - return 0; + return ret; + mutex_lock(&gecko_core_priv->lock); core = gecko_core_priv->gecko_core_drv; if (!core) - return 0; + goto done; - mutex_lock(&core->lock); timeout = jiffies + msecs_to_jiffies(APM_STATE_READY_TIMEOUT_MS); + mutex_lock(&core->lock); for (;;) { if (__gecko_core_is_apm_ready(core)) { ret = true; @@ -162,10 +184,80 @@ bool gecko_core_is_apm_ready(void) } mutex_unlock(&core->lock); +done: + mutex_unlock(&gecko_core_priv->lock); return ret; } EXPORT_SYMBOL_GPL(gecko_core_is_apm_ready); +/** + * gecko_core_apm_close_all() - Get status of adsp + * + * Return: Will be return true if apm is ready and false if not. + */ +void gecko_core_apm_close_all(void) +{ + int rc = 0; + struct gecko_core *core; + struct gpr_pkt pkt; + struct gpr_device *adev = NULL; + + if (!gecko_core_priv) + return; + + mutex_lock(&gecko_core_priv->lock); + core = gecko_core_priv->gecko_core_drv; + if (!core) { + mutex_unlock(&gecko_core_priv->lock); + return; + } + + mutex_lock(&core->lock); + + adev = core->adev; + + pkt.hdr.header = GPR_SET_FIELD(GPR_PKT_VERSION, GPR_PKT_VER) | + GPR_SET_FIELD(GPR_PKT_HEADER_SIZE, + GPR_PKT_HEADER_WORD_SIZE_V) | + GPR_SET_FIELD(GPR_PKT_PACKET_SIZE, + GPR_PKT_HEADER_BYTE_SIZE_V); + + pkt.hdr.dst_port = APM_MODULE_INSTANCE_ID; + pkt.hdr.src_port = GPR_SVC_ADSP_CORE; + pkt.hdr.dst_domain_id = GPR_IDS_DOMAIN_ID_ADSP_V; + pkt.hdr.src_domain_id = GPR_IDS_DOMAIN_ID_APPS_V; + pkt.hdr.opcode = APM_CMD_CLOSE_ALL; + + dev_info(gecko_core_priv->dev, "%s: send_command \n", __func__); + + rc = gpr_send_pkt(adev, &pkt); + if (rc < 0) { + dev_err(gecko_core_priv->dev, "%s: send_pkt_failed %d\n", + __func__, rc); + goto done; + } + + rc = wait_event_timeout(core->wait, (core->resp_received), + msecs_to_jiffies(Q6_READY_TIMEOUT_MS)); + dev_info(gecko_core_priv->dev, "%s: wait event unblocked \n", __func__); + if (rc > 0 && core->resp_received) { + if (core->status != 0) + dev_err(gecko_core_priv->dev, "%s, cmd failed status %d", + __func__, core->status); + } else { + dev_err(gecko_core_priv->dev, "%s: command timedout, ret\n", + __func__); + } + +done: + core->resp_received = false; + mutex_unlock(&core->lock); + mutex_unlock(&gecko_core_priv->lock); + return; +} +EXPORT_SYMBOL_GPL(gecko_core_apm_close_all); + + static int gecko_core_probe(struct gpr_device *adev) { struct gecko_core *core; @@ -176,8 +268,10 @@ static int gecko_core_probe(struct gpr_device *adev) } mutex_lock(&gecko_core_priv->lock); core = kzalloc(sizeof(*core), GFP_KERNEL); - if (!core) + if (!core) { + mutex_unlock(&gecko_core_priv->lock); return -ENOMEM; + } dev_set_drvdata(&adev->dev, core); diff --git a/include/dsp/gecko-core.h b/include/dsp/gecko-core.h index 051094efae..8e78ae7ae9 100644 --- a/include/dsp/gecko-core.h +++ b/include/dsp/gecko-core.h @@ -15,5 +15,6 @@ #include bool gecko_core_is_apm_ready(void); +void gecko_core_apm_close_all(void); #endif diff --git a/ipc/audio-pkt.c b/ipc/audio-pkt.c index c14792b05f..9ce00c6381 100644 --- a/ipc/audio-pkt.c +++ b/ipc/audio-pkt.c @@ -27,6 +27,7 @@ #include #include #include +#include #include /* Define IPC Logging Macros */ @@ -192,6 +193,8 @@ int audio_pkt_release(struct inode *inode, struct file *file) spin_unlock_irqrestore(&audpkt_dev->queue_lock, flags); file->private_data = NULL; + gecko_core_apm_close_all(); + msm_audio_ion_crash_handler(); return 0; }