kernel-brax3-ubuntu-touch/sound/soc/codecs/aw87xxx/aw87xxx_dsp.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

329 lines
7.6 KiB
C
Executable file

// SPDX-License-Identifier: GPL-2.0
/* aw87xxx_dsp.c
*
* Copyright (c) 2021 AWINIC Technology CO., LTD
*
* Author: Barry <zhaozhongbo@awinic.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/uaccess.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/hrtimer.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include "aw87xxx_log.h"
#include "aw87xxx_dsp.h"
static DEFINE_MUTEX(g_dsp_lock);
static unsigned int g_spin_value;
static int g_rx_topo_id = AW_RX_DEFAULT_TOPO_ID;
static int g_rx_port_id = AW_RX_DEFAULT_PORT_ID;
#ifdef AW_MTK_OPEN_DSP_PLATFORM
extern int mtk_spk_send_ipi_buf_to_dsp(void *data_buffer,
uint32_t data_size);
extern int mtk_spk_recv_ipi_buf_from_dsp(int8_t *buffer,
int16_t size, uint32_t *buf_len);
#elif defined AW_QCOM_OPEN_DSP_PLATFORM
extern int afe_get_topology(int port_id);
extern int aw_send_afe_cal_apr(uint32_t param_id,
void *buf, int cmd_size, bool write);
#endif
#ifdef AW_QCOM_OPEN_DSP_PLATFORM
extern void aw_set_port_id(int rx_port_id);
#else
static void aw_set_port_id(int rx_port_id)
{
}
#endif
uint8_t aw87xxx_dsp_isEnable(void)
{
#if (defined AW_QCOM_OPEN_DSP_PLATFORM) || (defined AW_MTK_OPEN_DSP_PLATFORM)
return true;
#else
return false;
#endif
}
/*****************mtk dsp communication function start**********************/
#ifdef AW_MTK_OPEN_DSP_PLATFORM
static int aw_mtk_write_data_to_dsp(int32_t param_id,
void *data, int size)
{
int32_t *dsp_data = NULL;
mtk_dsp_hdr_t *hdr = NULL;
int ret;
dsp_data = kzalloc(sizeof(mtk_dsp_hdr_t) + size, GFP_KERNEL);
if (!dsp_data) {
AW_LOGE("kzalloc dsp_msg error");
return -ENOMEM;
}
hdr = (mtk_dsp_hdr_t *)dsp_data;
hdr->type = DSP_MSG_TYPE_DATA;
hdr->opcode_id = param_id;
hdr->version = AW_DSP_MSG_HDR_VER;
memcpy(((char *)dsp_data) + sizeof(mtk_dsp_hdr_t),
data, size);
ret = mtk_spk_send_ipi_buf_to_dsp(dsp_data,
sizeof(mtk_dsp_hdr_t) + size);
if (ret < 0) {
AW_LOGE("write data failed");
kfree(dsp_data);
dsp_data = NULL;
return ret;
}
kfree(dsp_data);
dsp_data = NULL;
return 0;
}
static int aw_mtk_read_data_from_dsp(int32_t param_id, void *data,
int data_size)
{
int ret;
mtk_dsp_hdr_t hdr;
mutex_lock(&g_dsp_lock);
hdr.type = DSP_MSG_TYPE_CMD;
hdr.opcode_id = param_id;
hdr.version = AW_DSP_MSG_HDR_VER;
ret = mtk_spk_send_ipi_buf_to_dsp(&hdr, sizeof(mtk_dsp_hdr_t));
if (ret < 0)
goto failed;
ret = mtk_spk_recv_ipi_buf_from_dsp(data, data_size, &data_size);
if (ret < 0)
goto failed;
mutex_unlock(&g_dsp_lock);
return 0;
failed:
mutex_unlock(&g_dsp_lock);
return ret;
}
#endif
/********************mtk dsp communication function end***********************/
/******************qcom dsp communication function start**********************/
#ifdef AW_QCOM_OPEN_DSP_PLATFORM
static void aw_check_dsp_ready(void)
{
int ret;
ret = afe_get_topology(g_rx_port_id);
AW_LOGD("topo_id 0x%x", ret);
if (ret != g_rx_topo_id)
AW_LOGE("topo id 0x%x", ret);
}
static int aw_qcom_write_data_to_dsp(int32_t param_id,
void *data, int data_size)
{
int ret = 0;
AW_LOGI("enter");
mutex_lock(&g_dsp_lock);
aw_check_dsp_ready();
ret = aw_send_afe_cal_apr(param_id, data,
data_size, true);
mutex_unlock(&g_dsp_lock);
return ret;
}
static int aw_qcom_read_data_from_dsp(int32_t param_id,
void *data, int data_size)
{
int ret = 0;
AW_LOGI("enter");
mutex_lock(&g_dsp_lock);
aw_check_dsp_ready();
ret = aw_send_afe_cal_apr(param_id, data,
data_size, false);
mutex_unlock(&g_dsp_lock);
return ret;
}
#endif
/*****************qcom dsp communication function end*********************/
/*****************read/write msg communication function*********************/
static int aw_write_data_to_dsp(int32_t param_id, void *data, int data_size)
{
#if defined AW_QCOM_OPEN_DSP_PLATFORM
return aw_qcom_write_data_to_dsp(param_id, data, data_size);
#elif defined AW_MTK_OPEN_DSP_PLATFORM
return aw_mtk_write_data_to_dsp(param_id, data, data_size);
#else
return -EINVAL;
#endif
}
static int aw_read_data_from_dsp(int32_t param_id, void *data, int data_size)
{
#if defined AW_QCOM_OPEN_DSP_PLATFORM
return aw_qcom_read_data_from_dsp(param_id, data, data_size);
#elif defined AW_MTK_OPEN_DSP_PLATFORM
return aw_mtk_read_data_from_dsp(param_id, data, data_size);
#else
return -EINVAL;
#endif
}
/***************read/write msg communication function end*******************/
int aw87xxx_dsp_get_rx_module_enable(int *enable)
{
if (!enable) {
AW_LOGE("enable is NULL");
return -EINVAL;
}
return aw_read_data_from_dsp(AWDSP_RX_SET_ENABLE,
(void *)enable, sizeof(uint32_t));
}
int aw87xxx_dsp_set_rx_module_enable(int enable)
{
switch (enable) {
case AW_RX_MODULE_DISENABLE:
AW_LOGD("set enable=%d", enable);
break;
case AW_RX_MODULE_ENABLE:
AW_LOGD("set enable=%d", enable);
break;
default:
AW_LOGE("unsupport enable=%d", enable);
return -EINVAL;
}
return aw_write_data_to_dsp(AWDSP_RX_SET_ENABLE,
&enable, sizeof(uint32_t));
}
int aw87xxx_dsp_get_vmax(uint32_t *vmax, int dev_index)
{
int32_t param_id = 0;
switch (dev_index % AW_DSP_CHANNEL_MAX) {
case AW_DSP_CHANNEL_0:
param_id = AWDSP_RX_VMAX_0;
break;
case AW_DSP_CHANNEL_1:
param_id = AWDSP_RX_VMAX_1;
break;
default:
AW_LOGE("algo only support double PA channel:%d unsupport",
dev_index);
return -EINVAL;
}
return aw_read_data_from_dsp(param_id,
(void *)vmax, sizeof(uint32_t));
}
int aw87xxx_dsp_set_vmax(uint32_t vmax, int dev_index)
{
int32_t param_id = 0;
switch (dev_index % AW_DSP_CHANNEL_MAX) {
case AW_DSP_CHANNEL_0:
param_id = AWDSP_RX_VMAX_0;
break;
case AW_DSP_CHANNEL_1:
param_id = AWDSP_RX_VMAX_1;
break;
default:
AW_LOGE("algo only support double PA channel:%d unsupport",
dev_index);
return -EINVAL;
}
return aw_write_data_to_dsp(param_id, &vmax, sizeof(uint32_t));
}
int aw87xxx_dsp_set_spin(uint32_t ctrl_value)
{
int ret = 0;
if (ctrl_value >= AW_SPIN_MAX) {
AW_LOGE("spin [%d] unsupported ", ctrl_value);
return -EINVAL;
}
ret = aw_write_data_to_dsp(AW_MSG_ID_SPIN, &ctrl_value,
sizeof(uint32_t));
if (ret) {
AW_LOGE("spin [%d] set failed ", ctrl_value);
return ret;
}
g_spin_value = ctrl_value;
return 0;
}
int aw87xxx_dsp_get_spin(void)
{
return g_spin_value;
}
int aw87xxx_spin_set_record_val(void)
{
AW_LOGD("record write spin enter");
return aw87xxx_dsp_set_spin(g_spin_value);
}
EXPORT_SYMBOL(aw87xxx_spin_set_record_val);
void aw87xxx_device_parse_topo_id_dt(struct aw_device *aw_dev)
{
int ret;
ret = of_property_read_u32(aw_dev->dev->of_node, "aw-rx-topo-id", &g_rx_topo_id);
if (ret < 0) {
g_rx_topo_id = AW_RX_DEFAULT_TOPO_ID;
AW_DEV_LOGI(aw_dev->dev, "read aw-rx-topo-id failed,use default");
}
AW_DEV_LOGI(aw_dev->dev, "rx-topo-id: 0x%x", g_rx_topo_id);
}
void aw87xxx_device_parse_port_id_dt(struct aw_device *aw_dev)
{
int ret;
ret = of_property_read_u32(aw_dev->dev->of_node, "aw-rx-port-id", &g_rx_port_id);
if (ret < 0) {
g_rx_port_id = AW_RX_DEFAULT_PORT_ID;
AW_DEV_LOGI(aw_dev->dev, "read aw-rx-port-id failed,use default");
}
aw_set_port_id(g_rx_port_id);
AW_DEV_LOGI(aw_dev->dev, "rx-port-id: 0x%x", g_rx_port_id);
}