kernel-brax3-ubuntu-touch/sound/soc/mediatek/audio_scp/scp_audio_ipi.c
erascape f319b992b1 kernel-5.15: Initial import brax3 UT kernel
* halium configs enabled

Signed-off-by: erascape <erascape@proton.me>
2025-09-23 15:17:10 +00:00

137 lines
3.2 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2020 MediaTek Inc.
*/
#include <linux/errno.h>
#include <linux/printk.h>
#include <linux/soc/mediatek/mtk-mbox.h>
#include "scp.h"
#include "audio_mbox.h"
#include "scp_audio_ipi.h"
#define SHARE_BUF_SIZE 128
static recv_queue_handler_t recv_queue_callback;
struct scp_audio_ipi_desc {
scp_audio_ipi_handler_t handler;
const char *name;
} ipi_descs[SCP_AUDIO_NR_IPI];
int scp_send_message(unsigned int id, void *buf, unsigned int len,
unsigned int wait, unsigned int cid)
{
struct mtk_ipi_msg msg;
if (!buf || (len > (SHARE_BUF_SIZE - sizeof(struct mtk_ipi_msg_hd)))) {
pr_info("%s(), buffer error, len:%u", __func__, len);
return SCP_IPI_ERROR;
}
msg.ipihd.id = id;
msg.ipihd.len = len;
msg.ipihd.options = 0xffff0000;
msg.ipihd.reserved = 0xdeadbeef;
msg.data = buf;
return audio_mbox_send(&msg, wait);
}
EXPORT_SYMBOL_GPL(scp_send_message);
bool is_scp_audio_ready(void)
{
return is_audio_mbox_init_done() && is_scp_ready(SCP_A_ID);
}
EXPORT_SYMBOL_GPL(is_scp_audio_ready);
int scp_audio_ipi_registration(unsigned int id,
scp_audio_ipi_handler_t handler,
const char *name)
{
if (id >= SCP_AUDIO_NR_IPI || !handler)
return SCP_IPI_ERROR;
ipi_descs[id].name = name;
ipi_descs[id].handler = handler;
return SCP_IPI_DONE;
}
EXPORT_SYMBOL_GPL(scp_audio_ipi_registration);
/*
* API let apps unregister an ipi handler
* @param id: IPI ID
*/
int scp_audio_ipi_unregistration(unsigned int id)
{
if (id >= SCP_AUDIO_NR_IPI)
return SCP_IPI_ERROR;
ipi_descs[id].name = "";
ipi_descs[id].handler = NULL;
return SCP_IPI_DONE;
}
EXPORT_SYMBOL_GPL(scp_audio_ipi_unregistration);
void hook_scp_ipi_queue_recv_msg_handler(recv_queue_handler_t queue_handler)
{
recv_queue_callback = queue_handler;
}
EXPORT_SYMBOL_GPL(hook_scp_ipi_queue_recv_msg_handler);
void unhook_scp_ipi_queue_recv_msg_handler(void)
{
recv_queue_callback = NULL;
}
EXPORT_SYMBOL_GPL(unhook_scp_ipi_queue_recv_msg_handler);
int audio_mbox_pin_cb(unsigned int id, void *prdata, void *buf, unsigned int len)
{
int ret = -EPIPE;
if (id >= SCP_AUDIO_NR_IPI) {
pr_err("%s() invalid ipi_id %d\n", __func__, id);
return SCP_IPI_ERROR;
}
if (!ipi_descs[id].handler) {
pr_err("%s() invalid ipi handler %d\n", __func__, id);
return SCP_IPI_ERROR;
}
if (recv_queue_callback != NULL)
ret = recv_queue_callback(0, id, buf, len, ipi_descs[id].handler);
if (ret != 0) {
pr_info("ipi recv_queue not ready(%d), directly handle ipi %d", ret, id);
ipi_descs[id].handler(id, buf, len);
}
return SCP_IPI_DONE;
}
static void audio_ipi_test_recv(int id, void *data, unsigned int len)
{
int *value = (int *)data;
pr_info("%s, MBOX receive from scp, id %d, value %d, len %d",
__func__, id, *value, len);
}
static inline ssize_t audio_ipi_test_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int value = 0;
int ret = 0;
if (kstrtoint(buf, 10, &value))
return -EINVAL;
scp_audio_ipi_registration(SCP_AUDIO_IPI_TEST1, audio_ipi_test_recv, "ipi_test");
ret = scp_send_message(SCP_AUDIO_IPI_TEST1, &value, sizeof(value), 20, 0);
pr_info("audio_ipi_test value:%d, ret:%d\n", value, ret);
return count;
}
DEVICE_ATTR_WO(audio_ipi_test);