dsp: wait for apm_ready in audio_prm

Wait for spf_core_is_apm_ready before sending first command to
spf after bootup and after SSR.

Change-Id: I7c3a7fbb9e190310554ae716937fd6a0d036ce6f
Signed-off-by: Ritu Sharma <ritushar@codeaurora.org>
此提交包含在:
Ritu Sharma
2020-07-14 19:16:09 +05:30
提交者 Gerrit - the friendly Code Review server
父節點 54961362cb
當前提交 380d126f2a

查看文件

@@ -15,14 +15,19 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/jiffies.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <ipc/gpr-lite.h>
#include <soc/snd_event.h>
#include <dsp/audio_prm.h>
#include <dsp/spf-core.h>
#include <dsp/audio_notifier.h>
#define TIMEOUT_MS 500
#define MAX_RETRY_COUNT 3
#define APM_READY_WAIT_DURATION 2
struct audio_prm {
struct gpr_device *adev;
@@ -36,6 +41,8 @@ struct audio_prm {
static struct audio_prm g_prm;
static bool is_apm_ready_check_done = false;
static int audio_prm_callback(struct gpr_device *adev, void *data)
{
struct gpr_hdr *hdr = (struct gpr_hdr *)data;
@@ -82,6 +89,7 @@ static int audio_prm_callback(struct gpr_device *adev, void *data)
static int prm_gpr_send_pkt(struct gpr_pkt *pkt, wait_queue_head_t *wait)
{
int ret = 0;
int retry;
if (wait)
atomic_set(&g_prm.state, 1);
@@ -95,6 +103,16 @@ static int prm_gpr_send_pkt(struct gpr_pkt *pkt, wait_queue_head_t *wait)
mutex_unlock(&g_prm.lock);
return -ENODEV;
}
if (!is_apm_ready_check_done && g_prm.is_adsp_up) {
pr_info("%s: apm ready check not done\n", __func__);
retry = 0;
while (!spf_core_is_apm_ready() || retry < MAX_RETRY_COUNT) {
msleep(APM_READY_WAIT_DURATION);
retry++;
}
is_apm_ready_check_done = true;
pr_info("%s: apm ready check done\n", __func__);
}
g_prm.resp_received = false;
ret = gpr_send_pkt(g_prm.adev, pkt);
if (ret < 0) {
@@ -295,7 +313,34 @@ int audio_prm_set_lpass_clk_cfg (struct clk_cfg *clk, uint8_t enable)
}
EXPORT_SYMBOL(audio_prm_set_lpass_clk_cfg);
static int audio_prm_service_cb(struct notifier_block *this,
unsigned long opcode, void *data)
{
pr_info("%s: Service opcode 0x%lx\n", __func__, opcode);
switch (opcode) {
case AUDIO_NOTIFIER_SERVICE_DOWN:
mutex_lock(&g_prm.lock);
pr_debug("%s: making apm_ready check false\n", __func__);
is_apm_ready_check_done = false;
g_prm.is_adsp_up = false;
mutex_unlock(&g_prm.lock);
break;
case AUDIO_NOTIFIER_SERVICE_UP:
mutex_lock(&g_prm.lock);
g_prm.is_adsp_up = true;
mutex_unlock(&g_prm.lock);
break;
default:
break;
}
return NOTIFY_OK;
}
static struct notifier_block service_nb = {
.notifier_call = audio_prm_service_cb,
.priority = -INT_MAX,
};
static int audio_prm_probe(struct gpr_device *adev)
{
@@ -307,8 +352,7 @@ static int audio_prm_probe(struct gpr_device *adev)
g_prm.adev = adev;
init_waitqueue_head(&g_prm.wait);
g_prm.is_adsp_up = true;
pr_err("%s: prm probe success\n", __func__);
return ret;
}
@@ -318,6 +362,7 @@ static int audio_prm_remove(struct gpr_device *adev)
int ret = 0;
mutex_lock(&g_prm.lock);
g_prm.is_adsp_up = false;
g_prm.adev = NULL;
mutex_unlock(&g_prm.lock);
return ret;
@@ -339,6 +384,31 @@ static struct gpr_driver qcom_audio_prm_driver = {
},
};
module_gpr_driver(qcom_audio_prm_driver);
static int __init audio_prm_module_init(void)
{
int ret;
ret = gpr_driver_register(&qcom_audio_prm_driver);
if (ret) {
pr_err("%s: gpr driver register failed = %d\n", __func__, ret);
return ret;
}
ret = audio_notifier_register("audio_prm", AUDIO_NOTIFIER_ADSP_DOMAIN,
&service_nb);
if (ret < 0) {
pr_err("%s: Audio notifier register failed ret = %d\n",
__func__, ret);
return ret;
}
return ret;
}
static void __exit audio_prm_module_exit(void)
{
audio_notifier_deregister("audio_prm");
gpr_driver_unregister(&qcom_audio_prm_driver);
}
module_init(audio_prm_module_init);
module_exit(audio_prm_module_exit);
MODULE_DESCRIPTION("audio prm");
MODULE_LICENSE("GPL v2");