314 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			314 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * 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 "aw_log.h"
 | |
| #include "aw_dsp.h"
 | |
| 
 | |
| static DEFINE_MUTEX(g_dsp_lock);
 | |
| 
 | |
| #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);
 | |
| /*
 | |
| static int mtk_spk_send_ipi_buf_to_dsp(void *data_buffer,
 | |
| 				uint32_t data_size)
 | |
| {
 | |
| 	AW_LOGI("enter");
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int mtk_spk_recv_ipi_buf_from_dsp(int8_t *buffer,
 | |
| 				int16_t size, uint32_t *buf_len)
 | |
| {
 | |
| 	AW_LOGI("enter");
 | |
| 	return 0;
 | |
| }
 | |
| */
 | |
| #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);
 | |
| /*
 | |
| static int afe_get_topology(int port_id)
 | |
| {
 | |
| 	return -EPERM;
 | |
| }
 | |
| 
 | |
| static int aw_send_afe_cal_apr(uint32_t param_id,
 | |
| 	void *buf, int cmd_size, bool write)
 | |
| {
 | |
| 	AW_LOGI("enter, no define AWINIC_ADSP_ENABLE", __func__);
 | |
| 	return 0;
 | |
| }
 | |
| */
 | |
| #endif
 | |
| 
 | |
| uint8_t aw_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 int aw_check_dsp_ready(void)
 | |
| {
 | |
| 	int ret;
 | |
| 
 | |
| 	ret = afe_get_topology(AFE_PORT_ID_AWDSP_RX);
 | |
| 	AW_LOGD("topo_id 0x%x", ret);
 | |
| 
 | |
| 	if (ret <= 0)
 | |
| 		return 0;
 | |
| 	else
 | |
| 		return 1;
 | |
| }
 | |
| 
 | |
| static int aw_qcom_write_data_to_dsp(int32_t param_id,
 | |
| 				void *data, int data_size)
 | |
| {
 | |
| 	int ret = 0;
 | |
| 	int try = 0;
 | |
| 
 | |
| 	AW_LOGI("enter");
 | |
| 	mutex_lock(&g_dsp_lock);
 | |
| 	while (try < AW_DSP_TRY_TIME) {
 | |
| 		if (aw_check_dsp_ready()) {
 | |
| 			ret = aw_send_afe_cal_apr(param_id, data,
 | |
| 				data_size, true);
 | |
| 			mutex_unlock(&g_dsp_lock);
 | |
| 			return ret;
 | |
| 		} else {
 | |
| 			try++;
 | |
| 			msleep(AW_DSP_SLEEP_TIME);
 | |
| 			AW_LOGD("afe not ready try again");
 | |
| 		}
 | |
| 	}
 | |
| 	mutex_unlock(&g_dsp_lock);
 | |
| 
 | |
| 	return -EINVAL;
 | |
| }
 | |
| 
 | |
| static int aw_qcom_read_data_from_dsp(int32_t param_id,
 | |
| 				void *data, int data_size)
 | |
| {
 | |
| 	int ret = 0;
 | |
| 	int try = 0;
 | |
| 
 | |
| 	AW_LOGI("enter");
 | |
| 
 | |
| 	mutex_lock(&g_dsp_lock);
 | |
| 	while (try < AW_DSP_TRY_TIME) {
 | |
| 		if (aw_check_dsp_ready()) {
 | |
| 			ret = aw_send_afe_cal_apr(param_id, data,
 | |
| 					data_size, false);
 | |
| 			mutex_unlock(&g_dsp_lock);
 | |
| 			return ret;
 | |
| 		} else {
 | |
| 			try++;
 | |
| 			msleep(AW_DSP_SLEEP_TIME);
 | |
| 			AW_LOGD("afe not ready try again");
 | |
| 		}
 | |
| 	}
 | |
| 	mutex_unlock(&g_dsp_lock);
 | |
| 
 | |
| 	return -EINVAL;
 | |
| }
 | |
| 
 | |
| #endif
 | |
| /*****************qcom dsp communication function end*********************/
 | |
| 
 | |
| int aw_dsp_get_rx_module_enable(int *enable)
 | |
| {
 | |
| 	int ret = 0;
 | |
| 
 | |
| 	if (!enable) {
 | |
| 		AW_LOGE("enable is NULL");
 | |
| 		return -EINVAL;
 | |
| 	}
 | |
| 
 | |
| #ifdef AW_QCOM_OPEN_DSP_PLATFORM
 | |
| 	ret = aw_qcom_read_data_from_dsp(AWDSP_RX_SET_ENABLE,
 | |
| 			(void *)enable, sizeof(uint32_t));
 | |
| #elif defined AW_MTK_OPEN_DSP_PLATFORM
 | |
| 	ret = aw_mtk_read_data_from_dsp(AWDSP_RX_SET_ENABLE,
 | |
| 			(void *)enable, sizeof(uint32_t));
 | |
| #endif
 | |
| 
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| int aw_dsp_set_rx_module_enable(int enable)
 | |
| {
 | |
| 	int ret = 0;
 | |
| 
 | |
| 	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;
 | |
| 	}
 | |
| 
 | |
| #ifdef AW_QCOM_OPEN_DSP_PLATFORM
 | |
| 	ret = aw_qcom_write_data_to_dsp(AWDSP_RX_SET_ENABLE,
 | |
| 			&enable, sizeof(uint32_t));
 | |
| #elif defined AW_MTK_OPEN_DSP_PLATFORM
 | |
| 	ret = aw_mtk_write_data_to_dsp(AWDSP_RX_SET_ENABLE,
 | |
| 			&enable, sizeof(uint32_t));
 | |
| #endif
 | |
| 
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| int aw_dsp_get_vmax(uint32_t *vmax, int dev_index)
 | |
| {
 | |
| 	int ret  = 0;
 | |
| 	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;
 | |
| 	}
 | |
| #ifdef AW_QCOM_OPEN_DSP_PLATFORM
 | |
| 	ret = aw_qcom_read_data_from_dsp(param_id,
 | |
| 			(void *)vmax, sizeof(uint32_t));
 | |
| #elif defined AW_MTK_OPEN_DSP_PLATFORM
 | |
| 	ret = aw_mtk_read_data_from_dsp(param_id,
 | |
| 			(void *)vmax, sizeof(uint32_t));
 | |
| #endif
 | |
| 
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| int aw_dsp_set_vmax(uint32_t vmax, int dev_index)
 | |
| {
 | |
| 	int ret = 0;
 | |
| 	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;
 | |
| 	}
 | |
| #ifdef AW_QCOM_OPEN_DSP_PLATFORM
 | |
| 	ret = aw_qcom_write_data_to_dsp(param_id, &vmax, sizeof(uint32_t));
 | |
| #elif defined AW_MTK_OPEN_DSP_PLATFORM
 | |
| 	ret = aw_mtk_write_data_to_dsp(param_id, &vmax, sizeof(uint32_t));
 | |
| #endif
 | |
| 
 | |
| 	return ret;
 | |
| }
 | |
| 
 |