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>
此提交包含在:
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);
|
||||
|
新增問題並參考
封鎖使用者