unplugged-kernel/sound/soc/mediatek/scp_ultra/audio_ipi/ultra_ipi.c

130 lines
3.6 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2019 MediaTek Inc.
*/
/*****************************************************************************
* Header Files
*****************************************************************************/
#include <linux/delay.h>
#include <linux/notifier.h>
#include "ultra_ipi.h"
#include "audio_messenger_ipi.h"
#include "audio_task_manager.h"
#include "audio_task.h"
#include "scp.h"
static void ultra_ipi_IPICmd_Received(struct ipi_msg_t *ipi_msg);
static bool ultra_ipi_IPICmd_ReceiveAck(struct ipi_msg_t *ipi_msg);
static void ultra_ipi_Unloaded_Handling(void);
static bool scp_recovering;
struct ultra_ipi_receive_info ultra_ipi_receive;
struct ultra_ipi_ack_info ultra_ipi_send_ack;
void (*ultra_ipi_rx_handle)(unsigned int a, void *b);
bool (*ultra_ipi_tx_ack_handle)(unsigned int a, unsigned int b);
/*****************************************************************************
* Function
****************************************************************************/
unsigned int ultra_check_scp_status(void)
{
#ifdef CONFIG_MTK_TINYSYS_SCP_SUPPORT
return is_scp_ready(SCP_A_ID);
#else
return 0;
#endif
}
bool ultra_GetScpRecoverStatus(void)
{
return scp_recovering;
}
void ultra_SetScpRecoverStatus(bool recovering)
{
scp_recovering = recovering;
}
static void ultra_ipi_Unloaded_Handling(void)
{
pr_info("%s()\n", __func__);
}
static void ultra_ipi_IPICmd_Received(struct ipi_msg_t *ipi_msg)
{
pr_info("%s(),msg_id=%d\n", ipi_msg->msg_id);
ultra_ipi_rx_handle(ipi_msg->msg_id, (void *)ipi_msg->payload);
}
static bool ultra_ipi_IPICmd_ReceiveAck(struct ipi_msg_t *ipi_msg)
{
pr_info("%s(),msg_id=%d\n", ipi_msg->msg_id);
ultra_ipi_tx_ack_handle(ipi_msg->msg_id, 0);
return true;
}
void ultra_ipi_register(void (*ipi_rx_call)(unsigned int, void *),
bool (*ipi_tx_ack_call)(unsigned int, unsigned int))
{
audio_task_register_callback(TASK_SCENE_VOICE_ULTRASOUND,
ultra_ipi_IPICmd_Received, ultra_ipi_Unloaded_Handling);
ultra_ipi_rx_handle = ipi_rx_call;
ultra_ipi_tx_ack_handle = ipi_tx_ack_call;
}
bool ultra_ipi_send(unsigned int msg_id,
bool polling_mode,
unsigned int payload_len,
int *payload,
unsigned int need_ack)
{
bool ret = false;
struct ipi_msg_t ipi_msg;
int ipi_result = -1;
unsigned int retry_time = ULTRA_IPI_SEND_CNT_TIMEOUT;
unsigned int retry_cnt;
uint8_t data_type = 0;
uint8_t ack_type = AUDIO_IPI_MSG_BYPASS_ACK;
uint32_t param1 = sizeof(unsigned int) * payload_len;
uint32_t param2 = 0;
if (!ultra_check_scp_status()) {
pr_err("SCP is off, bypass send ipi id(%d)\n", msg_id);
return false;
}
// TODO: Should handle scp resovery
if (ultra_GetScpRecoverStatus() == true) {
pr_info("scp is recovering, then break\n");
return false;
}
ack_type = need_ack;
if (payload == NULL)
data_type = AUDIO_IPI_MSG_ONLY;
else
data_type = AUDIO_IPI_PAYLOAD;
for (retry_cnt = 0; retry_cnt <= retry_time; retry_cnt++) {
ipi_result = audio_send_ipi_msg(&ipi_msg,
TASK_SCENE_VOICE_ULTRASOUND,
AUDIO_IPI_LAYER_TO_DSP,
data_type,
ack_type,
msg_id,
param1,
param2,
payload);
if (ipi_result == 0)
break;
if (ultra_GetScpRecoverStatus() == true) {
pr_debug("scp is recovering, then break\n");
break;
}
if (!polling_mode)
msleep(ULTRA_WAITCHECK_INTERVAL_MS);
}
if (ipi_result == 0) {
/* ipi send pass */
if (ipi_msg.ack_type == AUDIO_IPI_MSG_ACK_BACK)
ret = ultra_ipi_IPICmd_ReceiveAck(&ipi_msg);
else
ret = true;
}
pr_info("%s(), ipi_id=%d,ret=%d,need_ack=%d,ack_return=%d\n",
__func__, msg_id, ipi_result, need_ack, ret);
return ret;
}