audio-kernel: Enable new PDR interface
Migrate to upstream PDR interface Add audio-notifer as a platform driver Change-Id: Ia07e12f134e77c4a63744052d060c589f5fb6d29 Signed-off-by: Jyotirmoi Sarma <jyosarma@codeaurora.org>
This commit is contained in:
parent
9fc4437cd8
commit
b1797ef8b8
@ -3,20 +3,35 @@
|
||||
* Copyright (c) 2016-2017, 2020 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <soc/qcom/subsystem_notif.h>
|
||||
#include <soc/qcom/service-notifier.h>
|
||||
#include <linux/remoteproc.h>
|
||||
#include <linux/remoteproc/qcom_rproc.h>
|
||||
#include <dsp/audio_notifier.h>
|
||||
#include "audio_ssr.h"
|
||||
#include "audio_pdr.h"
|
||||
|
||||
|
||||
|
||||
/* Audio states internal to notifier. Client */
|
||||
/* used states defined in audio_notifier.h */
|
||||
/* for AUDIO_NOTIFIER_SERVICE_DOWN & UP */
|
||||
#define NO_SERVICE -2
|
||||
#define UNINIT_SERVICE -1
|
||||
|
||||
static struct platform_device *adsp_private;
|
||||
|
||||
struct adsp_notify_private {
|
||||
struct rproc *rproc_h;
|
||||
};
|
||||
|
||||
/*
|
||||
* Used for each client registered with audio notifier
|
||||
*/
|
||||
@ -39,8 +54,11 @@ struct service_info {
|
||||
int domain_id;
|
||||
int state;
|
||||
void *handle;
|
||||
/* Notifier block registered to service */
|
||||
struct notifier_block *nb;
|
||||
/* Hook registered to service */
|
||||
union {
|
||||
void (*cb)(int, char *, void *);
|
||||
struct notifier_block *nb;
|
||||
} hook;
|
||||
/* Used to determine when to register and deregister service */
|
||||
int num_of_clients;
|
||||
/* List of all clients registered to the service and domain */
|
||||
@ -51,8 +69,7 @@ static int audio_notifier_ssr_adsp_cb(struct notifier_block *this,
|
||||
unsigned long opcode, void *data);
|
||||
static int audio_notifier_ssr_modem_cb(struct notifier_block *this,
|
||||
unsigned long opcode, void *data);
|
||||
static int audio_notifier_pdr_adsp_cb(struct notifier_block *this,
|
||||
unsigned long opcode, void *data);
|
||||
static void audio_notifier_pdr_adsp_cb(int status, char *service_name, void *priv);
|
||||
|
||||
static struct notifier_block notifier_ssr_adsp_nb = {
|
||||
.notifier_call = audio_notifier_ssr_adsp_cb,
|
||||
@ -64,11 +81,6 @@ static struct notifier_block notifier_ssr_modem_nb = {
|
||||
.priority = 0,
|
||||
};
|
||||
|
||||
static struct notifier_block notifier_pdr_adsp_nb = {
|
||||
.notifier_call = audio_notifier_pdr_adsp_cb,
|
||||
.priority = 0,
|
||||
};
|
||||
|
||||
static struct service_info service_data[AUDIO_NOTIFIER_MAX_SERVICES]
|
||||
[AUDIO_NOTIFIER_MAX_DOMAINS] = {
|
||||
|
||||
@ -76,25 +88,25 @@ static struct service_info service_data[AUDIO_NOTIFIER_MAX_SERVICES]
|
||||
.name = "SSR_ADSP",
|
||||
.domain_id = AUDIO_SSR_DOMAIN_ADSP,
|
||||
.state = AUDIO_NOTIFIER_SERVICE_DOWN,
|
||||
.nb = ¬ifier_ssr_adsp_nb
|
||||
.hook.nb = ¬ifier_ssr_adsp_nb
|
||||
},
|
||||
{
|
||||
.name = "SSR_MODEM",
|
||||
.domain_id = AUDIO_SSR_DOMAIN_MODEM,
|
||||
.state = AUDIO_NOTIFIER_SERVICE_DOWN,
|
||||
.nb = ¬ifier_ssr_modem_nb
|
||||
.hook.nb = ¬ifier_ssr_modem_nb
|
||||
} },
|
||||
|
||||
{{
|
||||
.name = "PDR_ADSP",
|
||||
.domain_id = AUDIO_PDR_DOMAIN_ADSP,
|
||||
.state = UNINIT_SERVICE,
|
||||
.nb = ¬ifier_pdr_adsp_nb
|
||||
.hook.cb = &audio_notifier_pdr_adsp_cb
|
||||
},
|
||||
{ /* PDR MODEM service not enabled */
|
||||
.name = "INVALID",
|
||||
.state = NO_SERVICE,
|
||||
.nb = NULL
|
||||
.hook.nb = NULL
|
||||
} }
|
||||
};
|
||||
|
||||
@ -119,13 +131,26 @@ static int audio_notifier_get_default_service(int domain)
|
||||
return service;
|
||||
}
|
||||
|
||||
static void audio_notifier_disable_service(int service)
|
||||
#ifdef CONFIG_MSM_QDSP6_PDR
|
||||
static void audio_notifier_init_service(int service)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < AUDIO_NOTIFIER_MAX_DOMAINS; i++) {
|
||||
if (service_data[service][i].state == UNINIT_SERVICE)
|
||||
service_data[service][i].state =
|
||||
AUDIO_NOTIFIER_SERVICE_DOWN;
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void audio_notifier_init_service(int service)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < AUDIO_NOTIFIER_MAX_DOMAINS; i++)
|
||||
service_data[service][i].state = NO_SERVICE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool audio_notifier_is_service_enabled(int service)
|
||||
{
|
||||
@ -137,38 +162,34 @@ static bool audio_notifier_is_service_enabled(int service)
|
||||
return false;
|
||||
}
|
||||
|
||||
static void audio_notifier_init_service(int service)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < AUDIO_NOTIFIER_MAX_DOMAINS; i++) {
|
||||
if (service_data[service][i].state == UNINIT_SERVICE)
|
||||
service_data[service][i].state =
|
||||
AUDIO_NOTIFIER_SERVICE_DOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static int audio_notifier_reg_service(int service, int domain)
|
||||
{
|
||||
void *handle;
|
||||
int ret = 0;
|
||||
int ret = -EINVAL;
|
||||
int curr_state = AUDIO_NOTIFIER_SERVICE_DOWN;
|
||||
struct platform_device *pdev = adsp_private;
|
||||
struct adsp_notify_private *priv = NULL;
|
||||
struct rproc *rproc;
|
||||
|
||||
priv = platform_get_drvdata(pdev);
|
||||
if (!priv) {
|
||||
dev_err(&pdev->dev," %s: Private data get failed\n", __func__);
|
||||
return ret;;
|
||||
}
|
||||
|
||||
rproc = priv->rproc_h;
|
||||
|
||||
switch (service) {
|
||||
case AUDIO_NOTIFIER_SSR_SERVICE:
|
||||
handle = audio_ssr_register(
|
||||
service_data[service][domain].domain_id,
|
||||
service_data[service][domain].nb);
|
||||
handle = audio_ssr_register(rproc->name,
|
||||
service_data[service][domain].hook.nb);
|
||||
break;
|
||||
case AUDIO_NOTIFIER_PDR_SERVICE:
|
||||
handle = audio_pdr_service_register(
|
||||
service_data[service][domain].domain_id,
|
||||
service_data[service][domain].nb, &curr_state);
|
||||
service_data[service][domain].hook.cb);
|
||||
|
||||
if (curr_state == SERVREG_NOTIF_SERVICE_STATE_UP_V01)
|
||||
curr_state = AUDIO_NOTIFIER_SERVICE_UP;
|
||||
else
|
||||
curr_state = AUDIO_NOTIFIER_SERVICE_DOWN;
|
||||
curr_state = AUDIO_NOTIFIER_SERVICE_DOWN;
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: Invalid service %d\n",
|
||||
@ -203,12 +224,11 @@ static int audio_notifier_dereg_service(int service, int domain)
|
||||
case AUDIO_NOTIFIER_SSR_SERVICE:
|
||||
ret = audio_ssr_deregister(
|
||||
service_data[service][domain].handle,
|
||||
service_data[service][domain].nb);
|
||||
service_data[service][domain].hook.nb);
|
||||
break;
|
||||
case AUDIO_NOTIFIER_PDR_SERVICE:
|
||||
ret = audio_pdr_service_deregister(
|
||||
service_data[service][domain].handle,
|
||||
service_data[service][domain].nb);
|
||||
service_data[service][domain].domain_id);
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: Invalid service %d\n",
|
||||
@ -396,39 +416,18 @@ static void audio_notifier_reg_all_clients(void)
|
||||
}
|
||||
}
|
||||
|
||||
static int audio_notifier_pdr_callback(struct notifier_block *this,
|
||||
unsigned long opcode, void *data)
|
||||
{
|
||||
pr_debug("%s: Audio PDR framework state 0x%lx\n",
|
||||
__func__, opcode);
|
||||
mutex_lock(¬ifier_mutex);
|
||||
if (opcode == AUDIO_PDR_FRAMEWORK_DOWN)
|
||||
audio_notifier_disable_service(AUDIO_NOTIFIER_PDR_SERVICE);
|
||||
else
|
||||
audio_notifier_init_service(AUDIO_NOTIFIER_PDR_SERVICE);
|
||||
|
||||
audio_notifier_reg_all_clients();
|
||||
mutex_unlock(¬ifier_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct notifier_block pdr_nb = {
|
||||
.notifier_call = audio_notifier_pdr_callback,
|
||||
.priority = 0,
|
||||
};
|
||||
|
||||
static int audio_notifier_convert_opcode(unsigned long opcode,
|
||||
unsigned long *notifier_opcode)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (opcode) {
|
||||
case SUBSYS_BEFORE_SHUTDOWN:
|
||||
case SERVREG_NOTIF_SERVICE_STATE_DOWN_V01:
|
||||
case QCOM_SSR_BEFORE_SHUTDOWN:
|
||||
case SERVREG_SERVICE_STATE_DOWN:
|
||||
*notifier_opcode = AUDIO_NOTIFIER_SERVICE_DOWN;
|
||||
break;
|
||||
case SUBSYS_AFTER_POWERUP:
|
||||
case SERVREG_NOTIF_SERVICE_STATE_UP_V01:
|
||||
case QCOM_SSR_AFTER_POWERUP:
|
||||
case SERVREG_SERVICE_STATE_UP:
|
||||
*notifier_opcode = AUDIO_NOTIFIER_SERVICE_UP;
|
||||
break;
|
||||
default:
|
||||
@ -470,12 +469,9 @@ done:
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static int audio_notifier_pdr_adsp_cb(struct notifier_block *this,
|
||||
unsigned long opcode, void *data)
|
||||
static void audio_notifier_pdr_adsp_cb(int status, char *service_name, void *priv)
|
||||
{
|
||||
return audio_notifier_service_cb(opcode,
|
||||
AUDIO_NOTIFIER_PDR_SERVICE,
|
||||
AUDIO_NOTIFIER_ADSP_DOMAIN);
|
||||
audio_notifier_service_cb(status, AUDIO_NOTIFIER_PDR_SERVICE, AUDIO_NOTIFIER_ADSP_DOMAIN);
|
||||
}
|
||||
|
||||
static int audio_notifier_ssr_adsp_cb(struct notifier_block *this,
|
||||
@ -573,7 +569,7 @@ done:
|
||||
}
|
||||
EXPORT_SYMBOL(audio_notifier_register);
|
||||
|
||||
static int __init audio_notifier_subsys_init(void)
|
||||
static int audio_notifier_subsys_init(void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
@ -592,7 +588,7 @@ static int __init audio_notifier_subsys_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init audio_notifier_late_init(void)
|
||||
static int audio_notifier_late_init(void)
|
||||
{
|
||||
/*
|
||||
* If pdr registration failed, register clients on next service
|
||||
@ -606,41 +602,78 @@ static int __init audio_notifier_late_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MSM_QDSP6_PDR
|
||||
static int __init audio_notifier_init(void)
|
||||
|
||||
static int audio_notify_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
int ret = -EINVAL;
|
||||
struct adsp_notify_private *priv = NULL;
|
||||
struct property *prop;
|
||||
int size;
|
||||
phandle rproc_phandle;
|
||||
|
||||
adsp_private = NULL;
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv) {
|
||||
ret = -ENOMEM;
|
||||
return ret;
|
||||
}
|
||||
platform_set_drvdata(pdev, priv);
|
||||
prop = of_find_property(pdev->dev.of_node, "qcom,rproc-handle", &size);
|
||||
if (!prop) {
|
||||
dev_err(&pdev->dev, "Missing remotproc handle\n");
|
||||
return ret;
|
||||
}
|
||||
rproc_phandle = be32_to_cpup(prop->value);
|
||||
|
||||
priv->rproc_h = rproc_get_by_phandle(rproc_phandle);
|
||||
if (!priv->rproc_h) {
|
||||
dev_err(&pdev->dev, "remotproc handle NULL\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
adsp_private = pdev;
|
||||
|
||||
|
||||
audio_notifier_subsys_init();
|
||||
|
||||
ret = audio_pdr_register(&pdr_nb);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: PDR register failed, ret = %d, disable service\n",
|
||||
__func__, ret);
|
||||
audio_notifier_disable_service(AUDIO_NOTIFIER_PDR_SERVICE);
|
||||
}
|
||||
|
||||
audio_notifier_init_service(AUDIO_NOTIFIER_PDR_SERVICE);
|
||||
/* Do not return error since PDR enablement is not critical */
|
||||
audio_notifier_late_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int __init audio_notifier_init(void)
|
||||
|
||||
static int audio_notify_remove(struct platform_device *pdev)
|
||||
{
|
||||
audio_notifier_subsys_init();
|
||||
audio_notifier_disable_service(AUDIO_NOTIFIER_PDR_SERVICE);
|
||||
|
||||
audio_notifier_late_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct of_device_id adsp_notify_dt_match[] = {
|
||||
{ .compatible = "qcom,adsp-notify" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, adsp_notify_dt_match);
|
||||
|
||||
static struct platform_driver adsp_notify_driver = {
|
||||
.driver = {
|
||||
.name = "adsp-notify",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = adsp_notify_dt_match,
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.probe = audio_notify_probe,
|
||||
.remove = audio_notify_remove,
|
||||
};
|
||||
|
||||
static int __init audio_notifier_init(void)
|
||||
{
|
||||
return platform_driver_register(&adsp_notify_driver);
|
||||
}
|
||||
module_init(audio_notifier_init);
|
||||
|
||||
static void __exit audio_notifier_exit(void)
|
||||
{
|
||||
audio_pdr_deregister(&pdr_nb);
|
||||
platform_driver_unregister(&adsp_notify_driver);
|
||||
}
|
||||
module_exit(audio_notifier_exit);
|
||||
|
||||
|
189
dsp/audio_pdr.c
189
dsp/audio_pdr.c
@ -1,203 +1,62 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2016-2017, 2020 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <soc/qcom/service-locator.h>
|
||||
#include <soc/qcom/service-notifier.h>
|
||||
#include "audio_pdr.h"
|
||||
|
||||
static struct pd_qmi_client_data audio_pdr_services[AUDIO_PDR_DOMAIN_MAX] = {
|
||||
struct audio_pdr_service {
|
||||
void *pdr_handle;
|
||||
char service_name[SERVREG_NAME_LENGTH + 1];
|
||||
char service_path[SERVREG_NAME_LENGTH + 1];
|
||||
};
|
||||
|
||||
static struct audio_pdr_service audio_pdr_services[AUDIO_PDR_DOMAIN_MAX] = {
|
||||
{ /* AUDIO_PDR_DOMAIN_ADSP */
|
||||
.client_name = "audio_pdr_adsp",
|
||||
.service_name = "avs/audio"
|
||||
.service_name = "avs/audio",
|
||||
.service_path = "msm/adsp/audio_pd",
|
||||
}
|
||||
};
|
||||
|
||||
struct srcu_notifier_head audio_pdr_cb_list;
|
||||
|
||||
static int audio_pdr_locator_callback(struct notifier_block *this,
|
||||
unsigned long opcode, void *data)
|
||||
void *audio_pdr_service_register(int domain_id, void (*cb)(int, char *, void *))
|
||||
{
|
||||
unsigned long pdr_state = AUDIO_PDR_FRAMEWORK_DOWN;
|
||||
|
||||
if (opcode == LOCATOR_DOWN) {
|
||||
pr_debug("%s: Service %s is down!", __func__,
|
||||
audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].
|
||||
service_name);
|
||||
goto done;
|
||||
}
|
||||
|
||||
memcpy(&audio_pdr_services, data,
|
||||
sizeof(audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP]));
|
||||
if (audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].total_domains == 1) {
|
||||
int domain_list_size = (sizeof(struct servreg_loc_entry_v01)) *
|
||||
(audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].total_domains);
|
||||
struct servreg_loc_entry_v01 *domain_list_temp = NULL;
|
||||
|
||||
pr_debug("%s: Service %s, returned total domains %d, ",
|
||||
__func__,
|
||||
audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].service_name,
|
||||
audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].
|
||||
total_domains);
|
||||
|
||||
domain_list_temp = (struct servreg_loc_entry_v01 *)kzalloc(
|
||||
sizeof(domain_list_size), GFP_KERNEL);
|
||||
|
||||
if(!domain_list_size)
|
||||
{
|
||||
pr_err("%s: Service %s total domains %d could not allocate memory",
|
||||
__func__,
|
||||
audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].service_name,
|
||||
audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].
|
||||
total_domains);
|
||||
goto done;
|
||||
} else {
|
||||
memcpy(domain_list_temp,
|
||||
audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].domain_list,
|
||||
domain_list_size);
|
||||
audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].domain_list = domain_list_temp;
|
||||
}
|
||||
|
||||
pdr_state = AUDIO_PDR_FRAMEWORK_UP;
|
||||
goto done;
|
||||
} else
|
||||
pr_err("%s: Service %s returned invalid total domains %d",
|
||||
__func__,
|
||||
audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].service_name,
|
||||
audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].
|
||||
total_domains);
|
||||
done:
|
||||
srcu_notifier_call_chain(&audio_pdr_cb_list, pdr_state, NULL);
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block audio_pdr_locator_nb = {
|
||||
.notifier_call = audio_pdr_locator_callback,
|
||||
.priority = 0,
|
||||
};
|
||||
|
||||
/**
|
||||
* audio_pdr_register -
|
||||
* register to PDR framework
|
||||
*
|
||||
* @nb: notifier block
|
||||
*
|
||||
* Returns 0 on success or error on failure
|
||||
*/
|
||||
int audio_pdr_register(struct notifier_block *nb)
|
||||
{
|
||||
if (nb == NULL) {
|
||||
pr_err("%s: Notifier block is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
return srcu_notifier_chain_register(&audio_pdr_cb_list, nb);
|
||||
}
|
||||
EXPORT_SYMBOL(audio_pdr_register);
|
||||
|
||||
/**
|
||||
* audio_pdr_deregister -
|
||||
* Deregister from PDR framework
|
||||
*
|
||||
* @nb: notifier block
|
||||
*
|
||||
* Returns 0 on success or error on failure
|
||||
*/
|
||||
int audio_pdr_deregister(struct notifier_block *nb)
|
||||
{
|
||||
if (nb == NULL) {
|
||||
pr_err("%s: Notifier block is NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
return srcu_notifier_chain_unregister(&audio_pdr_cb_list, nb);
|
||||
}
|
||||
EXPORT_SYMBOL(audio_pdr_deregister);
|
||||
|
||||
void *audio_pdr_service_register(int domain_id,
|
||||
struct notifier_block *nb, int *curr_state)
|
||||
{
|
||||
void *handle;
|
||||
|
||||
if ((domain_id < 0) ||
|
||||
(domain_id >= AUDIO_PDR_DOMAIN_MAX)) {
|
||||
pr_err("%s: Invalid service ID %d\n", __func__, domain_id);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
handle = service_notif_register_notifier(
|
||||
audio_pdr_services[domain_id].domain_list[0].name,
|
||||
audio_pdr_services[domain_id].domain_list[0].instance_id,
|
||||
nb, curr_state);
|
||||
if (IS_ERR_OR_NULL(handle)) {
|
||||
pr_err("%s: Failed to register for domain %s, instance %d\n",
|
||||
__func__,
|
||||
audio_pdr_services[domain_id].domain_list[0].name,
|
||||
audio_pdr_services[domain_id].domain_list[0].
|
||||
instance_id);
|
||||
}
|
||||
return handle;
|
||||
audio_pdr_services[domain_id].pdr_handle = pdr_handle_alloc(cb, NULL);
|
||||
|
||||
return pdr_add_lookup(audio_pdr_services[domain_id].pdr_handle,
|
||||
audio_pdr_services[domain_id].service_name,
|
||||
audio_pdr_services[domain_id].service_path);
|
||||
}
|
||||
EXPORT_SYMBOL(audio_pdr_service_register);
|
||||
|
||||
int audio_pdr_service_deregister(void *service_handle,
|
||||
struct notifier_block *nb)
|
||||
int audio_pdr_service_deregister(int domain_id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (service_handle == NULL) {
|
||||
pr_err("%s: service handle is NULL\n", __func__);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
if ((domain_id < 0) ||
|
||||
(domain_id >= AUDIO_PDR_DOMAIN_MAX)) {
|
||||
pr_err("%s: Invalid service ID %d\n", __func__, domain_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
pdr_handle_release(audio_pdr_services[domain_id].pdr_handle);
|
||||
|
||||
ret = service_notif_unregister_notifier(
|
||||
service_handle, nb);
|
||||
if (ret < 0)
|
||||
pr_err("%s: Failed to deregister service ret %d\n",
|
||||
__func__, ret);
|
||||
done:
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(audio_pdr_service_deregister);
|
||||
|
||||
static int __init audio_pdr_subsys_init(void)
|
||||
{
|
||||
srcu_init_notifier_head(&audio_pdr_cb_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init audio_pdr_late_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
audio_pdr_subsys_init();
|
||||
|
||||
ret = get_service_location(
|
||||
audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].client_name,
|
||||
audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].service_name,
|
||||
&audio_pdr_locator_nb);
|
||||
if (ret < 0) {
|
||||
pr_err("%s get_service_location failed ret %d\n",
|
||||
__func__, ret);
|
||||
srcu_notifier_call_chain(&audio_pdr_cb_list,
|
||||
AUDIO_PDR_FRAMEWORK_DOWN, NULL);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
module_init(audio_pdr_late_init);
|
||||
|
||||
static void __exit audio_pdr_late_exit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < AUDIO_PDR_DOMAIN_MAX; i++)
|
||||
{
|
||||
if (audio_pdr_services[i].domain_list != NULL)
|
||||
kfree(audio_pdr_services[i].domain_list);
|
||||
}
|
||||
|
||||
}
|
||||
module_exit(audio_pdr_late_exit);
|
||||
|
@ -1,40 +1,20 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2016-2018, 2020 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __AUDIO_PDR_H_
|
||||
#define __AUDIO_PDR_H_
|
||||
|
||||
#include <linux/soc/qcom/pdr.h>
|
||||
|
||||
enum {
|
||||
AUDIO_PDR_DOMAIN_ADSP,
|
||||
AUDIO_PDR_DOMAIN_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
AUDIO_PDR_FRAMEWORK_DOWN,
|
||||
AUDIO_PDR_FRAMEWORK_UP
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MSM_QDSP6_PDR
|
||||
|
||||
/*
|
||||
* Use audio_pdr_register to register with the PDR subsystem this
|
||||
* should be done before module late init otherwise notification
|
||||
* of the AUDIO_PDR_FRAMEWORK_UP cannot be guaranteed.
|
||||
*
|
||||
* *nb - Pointer to a notifier block. Provide a callback function
|
||||
* to be notified once the PDR framework has been initialized.
|
||||
* Callback will receive either the AUDIO_PDR_FRAMEWORK_DOWN
|
||||
* or AUDIO_PDR_FRAMEWORK_UP ioctl depending on the state of
|
||||
* the PDR framework.
|
||||
*
|
||||
* Returns: Success: 0
|
||||
* Failure: Error code
|
||||
*/
|
||||
int audio_pdr_register(struct notifier_block *nb);
|
||||
int audio_pdr_deregister(struct notifier_block *nb);
|
||||
|
||||
/*
|
||||
* Use audio_pdr_service_register to register with a PDR service
|
||||
* Function should be called after nb callback registered with
|
||||
@ -42,53 +22,35 @@ int audio_pdr_deregister(struct notifier_block *nb);
|
||||
* AUDIO_PDR_FRAMEWORK_UP ioctl.
|
||||
*
|
||||
* domain_id - Domain to use, example: AUDIO_PDR_ADSP
|
||||
* *nb - Pointer to a notifier block. Provide a callback function
|
||||
* that will be notified of the state of the domain
|
||||
* requested. The ioctls received by the callback are
|
||||
* defined in service-notifier.h.
|
||||
* *cb - Pointer to a callback function that will be notified of the state
|
||||
* of the domain requested. The ioctls received by the callback are
|
||||
* defined in pdr.h.
|
||||
*
|
||||
* Returns: Success: Client handle
|
||||
* Failure: Pointer error code
|
||||
*/
|
||||
void *audio_pdr_service_register(int domain_id,
|
||||
struct notifier_block *nb, int *curr_state);
|
||||
void *audio_pdr_service_register(int domain_id, void (*cb)(int, char *, void *));
|
||||
|
||||
/*
|
||||
* Use audio_pdr_service_deregister to deregister with a PDR
|
||||
* service that was registered using the audio_pdr_service_register
|
||||
* API.
|
||||
*
|
||||
* *service_handle - Service handle returned by audio_pdr_service_register
|
||||
* *nb - Pointer to the notifier block. Used in the call to
|
||||
* audio_pdr_service_register.
|
||||
* domain_id - Domain to use, example: AUDIO_PDR_ADSP
|
||||
*
|
||||
* Returns: Success: Client handle
|
||||
* Returns: Success: zero
|
||||
* Failure: Error code
|
||||
*/
|
||||
int audio_pdr_service_deregister(void *service_handle,
|
||||
struct notifier_block *nb);
|
||||
int audio_pdr_service_deregister(int domain_id);
|
||||
|
||||
#else
|
||||
|
||||
static inline int audio_pdr_register(struct notifier_block *nb)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int audio_pdr_deregister(struct notifier_block *nb)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline void *audio_pdr_service_register(int domain_id,
|
||||
struct notifier_block *nb,
|
||||
int *curr_state)
|
||||
static inline void *audio_pdr_service_register(int domain_id, void (*cb)(int, char *, void *))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int audio_pdr_service_deregister(void *service_handle,
|
||||
struct notifier_block *nb)
|
||||
static inline int audio_pdr_service_deregister(int domain_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,17 +1,13 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2016, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2016, 2020 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <soc/qcom/subsystem_restart.h>
|
||||
#include <soc/qcom/subsystem_notif.h>
|
||||
#include <linux/remoteproc.h>
|
||||
#include <linux/remoteproc/qcom_rproc.h>
|
||||
#include "audio_ssr.h"
|
||||
|
||||
static char *audio_ssr_domains[] = {
|
||||
"adsp",
|
||||
"modem"
|
||||
};
|
||||
|
||||
/**
|
||||
* audio_ssr_register -
|
||||
@ -22,16 +18,14 @@ static char *audio_ssr_domains[] = {
|
||||
*
|
||||
* Returns handle pointer on success or error PTR on failure
|
||||
*/
|
||||
void *audio_ssr_register(int domain_id, struct notifier_block *nb)
|
||||
void *audio_ssr_register(const char *domain_name, struct notifier_block *nb)
|
||||
{
|
||||
if ((domain_id < 0) ||
|
||||
(domain_id >= AUDIO_SSR_DOMAIN_MAX)) {
|
||||
pr_err("%s: Invalid service ID %d\n", __func__, domain_id);
|
||||
if (domain_name == NULL) {
|
||||
pr_err("%s: Invalid domain name %d\n", __func__);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
return subsys_notif_register_notifier(
|
||||
audio_ssr_domains[domain_id], nb);
|
||||
return qcom_register_ssr_notifier(domain_name, nb);
|
||||
}
|
||||
EXPORT_SYMBOL(audio_ssr_register);
|
||||
|
||||
@ -46,7 +40,7 @@ EXPORT_SYMBOL(audio_ssr_register);
|
||||
*/
|
||||
int audio_ssr_deregister(void *handle, struct notifier_block *nb)
|
||||
{
|
||||
return subsys_notif_unregister_notifier(handle, nb);
|
||||
return qcom_unregister_ssr_notifier(handle, nb);
|
||||
}
|
||||
EXPORT_SYMBOL(audio_ssr_deregister);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2016, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2016, 2020 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __AUDIO_SSR_H_
|
||||
@ -25,7 +25,7 @@ enum {
|
||||
* Returns: Success: Client handle
|
||||
* Failure: Pointer error code
|
||||
*/
|
||||
void *audio_ssr_register(int domain_id, struct notifier_block *nb);
|
||||
void *audio_ssr_register(const char *domain_name, struct notifier_block *nb);
|
||||
|
||||
/*
|
||||
* Use audio_ssr_deregister to register with the SSR subsystem
|
||||
|
Loading…
Reference in New Issue
Block a user