1 /*
2 * aw87xxx_dsp.c
3 *
4 * Copyright (c) 2021 AWINIC Technology CO., LTD
5 *
6 * Author: Barry <zhaozhongbo@awinic.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14 #include <linux/uaccess.h>
15 #include <linux/delay.h>
16 #include <linux/device.h>
17 #include <linux/kernel.h>
18 #include <linux/of.h>
19 #include <linux/slab.h>
20 #include <linux/hrtimer.h>
21 #include <linux/proc_fs.h>
22 #include <linux/init.h>
23 #include "aw_log.h"
24 #include "aw_dsp.h"
25
26 static DEFINE_MUTEX(g_dsp_lock);
27
28 #ifdef AW_MTK_OPEN_DSP_PLATFORM
29 extern int mtk_spk_send_ipi_buf_to_dsp(void *data_buffer,
30 uint32_t data_size);
31 extern int mtk_spk_recv_ipi_buf_from_dsp(int8_t *buffer,
32 int16_t size, uint32_t *buf_len);
33 /*
34 static int mtk_spk_send_ipi_buf_to_dsp(void *data_buffer,
35 uint32_t data_size)
36 {
37 AW_LOGI("enter");
38 return 0;
39 }
40
41 static int mtk_spk_recv_ipi_buf_from_dsp(int8_t *buffer,
42 int16_t size, uint32_t *buf_len)
43 {
44 AW_LOGI("enter");
45 return 0;
46 }
47 */
48 #elif defined AW_QCOM_OPEN_DSP_PLATFORM
49 extern int afe_get_topology(int port_id);
50 extern int aw_send_afe_cal_apr(uint32_t param_id,
51 void *buf, int cmd_size, bool write);
52 /*
53 static int afe_get_topology(int port_id)
54 {
55 return -EPERM;
56 }
57
58 static int aw_send_afe_cal_apr(uint32_t param_id,
59 void *buf, int cmd_size, bool write)
60 {
61 AW_LOGI("enter, no define AWINIC_ADSP_ENABLE", __func__);
62 return 0;
63 }
64 */
65 #endif
66
aw_dsp_isEnable(void)67 uint8_t aw_dsp_isEnable(void)
68 {
69 #if (defined AW_QCOM_OPEN_DSP_PLATFORM) || (defined AW_MTK_OPEN_DSP_PLATFORM)
70 return true;
71 #else
72 return false;
73 #endif
74 }
75
76 /*****************mtk dsp communication function start**********************/
77 #ifdef AW_MTK_OPEN_DSP_PLATFORM
aw_mtk_write_data_to_dsp(int32_t param_id,void * data,int size)78 static int aw_mtk_write_data_to_dsp(int32_t param_id,
79 void *data, int size)
80 {
81 int32_t *dsp_data = NULL;
82 mtk_dsp_hdr_t *hdr = NULL;
83 int ret;
84
85 dsp_data = kzalloc(sizeof(mtk_dsp_hdr_t) + size, GFP_KERNEL);
86 if (!dsp_data) {
87 AW_LOGE("kzalloc dsp_msg error");
88 return -ENOMEM;
89 }
90
91 hdr = (mtk_dsp_hdr_t *)dsp_data;
92 hdr->type = DSP_MSG_TYPE_DATA;
93 hdr->opcode_id = param_id;
94 hdr->version = AW_DSP_MSG_HDR_VER;
95
96 memcpy(((char *)dsp_data) + sizeof(mtk_dsp_hdr_t),
97 data, size);
98
99 ret = mtk_spk_send_ipi_buf_to_dsp(dsp_data,
100 sizeof(mtk_dsp_hdr_t) + size);
101 if (ret < 0) {
102 AW_LOGE("write data failed");
103 kfree(dsp_data);
104 dsp_data = NULL;
105 return ret;
106 }
107
108 kfree(dsp_data);
109 dsp_data = NULL;
110 return 0;
111 }
112
aw_mtk_read_data_from_dsp(int32_t param_id,void * data,int data_size)113 static int aw_mtk_read_data_from_dsp(int32_t param_id, void *data,
114 int data_size)
115 {
116 int ret;
117 mtk_dsp_hdr_t hdr;
118
119 mutex_lock(&g_dsp_lock);
120 hdr.type = DSP_MSG_TYPE_CMD;
121 hdr.opcode_id = param_id;
122 hdr.version = AW_DSP_MSG_HDR_VER;
123
124 ret = mtk_spk_send_ipi_buf_to_dsp(&hdr, sizeof(mtk_dsp_hdr_t));
125 if (ret < 0)
126 goto failed;
127
128 ret = mtk_spk_recv_ipi_buf_from_dsp(data, data_size, &data_size);
129 if (ret < 0)
130 goto failed;
131
132 mutex_unlock(&g_dsp_lock);
133 return 0;
134
135 failed:
136 mutex_unlock(&g_dsp_lock);
137 return ret;
138 }
139
140 #endif
141 /********************mtk dsp communication function end***********************/
142
143 /******************qcom dsp communication function start**********************/
144 #ifdef AW_QCOM_OPEN_DSP_PLATFORM
aw_check_dsp_ready(void)145 static int aw_check_dsp_ready(void)
146 {
147 int ret;
148
149 ret = afe_get_topology(AFE_PORT_ID_AWDSP_RX);
150 AW_LOGD("topo_id 0x%x", ret);
151
152 if (ret <= 0)
153 return 0;
154 else
155 return 1;
156 }
157
aw_qcom_write_data_to_dsp(int32_t param_id,void * data,int data_size)158 static int aw_qcom_write_data_to_dsp(int32_t param_id,
159 void *data, int data_size)
160 {
161 int ret = 0;
162 int try = 0;
163
164 AW_LOGI("enter");
165 mutex_lock(&g_dsp_lock);
166 while (try < AW_DSP_TRY_TIME) {
167 if (aw_check_dsp_ready()) {
168 ret = aw_send_afe_cal_apr(param_id, data,
169 data_size, true);
170 mutex_unlock(&g_dsp_lock);
171 return ret;
172 } else {
173 try++;
174 msleep(AW_DSP_SLEEP_TIME);
175 AW_LOGD("afe not ready try again");
176 }
177 }
178 mutex_unlock(&g_dsp_lock);
179
180 return -EINVAL;
181 }
182
aw_qcom_read_data_from_dsp(int32_t param_id,void * data,int data_size)183 static int aw_qcom_read_data_from_dsp(int32_t param_id,
184 void *data, int data_size)
185 {
186 int ret = 0;
187 int try = 0;
188
189 AW_LOGI("enter");
190
191 mutex_lock(&g_dsp_lock);
192 while (try < AW_DSP_TRY_TIME) {
193 if (aw_check_dsp_ready()) {
194 ret = aw_send_afe_cal_apr(param_id, data,
195 data_size, false);
196 mutex_unlock(&g_dsp_lock);
197 return ret;
198 } else {
199 try++;
200 msleep(AW_DSP_SLEEP_TIME);
201 AW_LOGD("afe not ready try again");
202 }
203 }
204 mutex_unlock(&g_dsp_lock);
205
206 return -EINVAL;
207 }
208
209 #endif
210 /*****************qcom dsp communication function end*********************/
211
aw_dsp_get_rx_module_enable(int * enable)212 int aw_dsp_get_rx_module_enable(int *enable)
213 {
214 int ret = 0;
215
216 if (!enable) {
217 AW_LOGE("enable is NULL");
218 return -EINVAL;
219 }
220
221 #ifdef AW_QCOM_OPEN_DSP_PLATFORM
222 ret = aw_qcom_read_data_from_dsp(AWDSP_RX_SET_ENABLE,
223 (void *)enable, sizeof(uint32_t));
224 #elif defined AW_MTK_OPEN_DSP_PLATFORM
225 ret = aw_mtk_read_data_from_dsp(AWDSP_RX_SET_ENABLE,
226 (void *)enable, sizeof(uint32_t));
227 #endif
228
229 return ret;
230 }
231
aw_dsp_set_rx_module_enable(int enable)232 int aw_dsp_set_rx_module_enable(int enable)
233 {
234 int ret = 0;
235
236 switch (enable) {
237 case AW_RX_MODULE_DISENABLE:
238 AW_LOGD("set enable=%d", enable);
239 break;
240 case AW_RX_MODULE_ENABLE:
241 AW_LOGD("set enable=%d", enable);
242 break;
243 default:
244 AW_LOGE("unsupport enable=%d", enable);
245 return -EINVAL;
246 }
247
248 #ifdef AW_QCOM_OPEN_DSP_PLATFORM
249 ret = aw_qcom_write_data_to_dsp(AWDSP_RX_SET_ENABLE,
250 &enable, sizeof(uint32_t));
251 #elif defined AW_MTK_OPEN_DSP_PLATFORM
252 ret = aw_mtk_write_data_to_dsp(AWDSP_RX_SET_ENABLE,
253 &enable, sizeof(uint32_t));
254 #endif
255
256 return ret;
257 }
258
259
aw_dsp_get_vmax(uint32_t * vmax,int dev_index)260 int aw_dsp_get_vmax(uint32_t *vmax, int dev_index)
261 {
262 int ret = 0;
263 int32_t param_id = 0;
264
265 switch (dev_index % AW_DSP_CHANNEL_MAX) {
266 case AW_DSP_CHANNEL_0:
267 param_id = AWDSP_RX_VMAX_0;
268 break;
269 case AW_DSP_CHANNEL_1:
270 param_id = AWDSP_RX_VMAX_1;
271 break;
272 default:
273 AW_LOGE("algo only support double PA channel:%d unsupport",
274 dev_index);
275 return -EINVAL;
276 }
277 #ifdef AW_QCOM_OPEN_DSP_PLATFORM
278 ret = aw_qcom_read_data_from_dsp(param_id,
279 (void *)vmax, sizeof(uint32_t));
280 #elif defined AW_MTK_OPEN_DSP_PLATFORM
281 ret = aw_mtk_read_data_from_dsp(param_id,
282 (void *)vmax, sizeof(uint32_t));
283 #endif
284
285 return ret;
286 }
287
aw_dsp_set_vmax(uint32_t vmax,int dev_index)288 int aw_dsp_set_vmax(uint32_t vmax, int dev_index)
289 {
290 int ret = 0;
291 int32_t param_id = 0;
292
293 switch (dev_index % AW_DSP_CHANNEL_MAX) {
294 case AW_DSP_CHANNEL_0:
295 param_id = AWDSP_RX_VMAX_0;
296 break;
297 case AW_DSP_CHANNEL_1:
298 param_id = AWDSP_RX_VMAX_1;
299 break;
300 default:
301 AW_LOGE("algo only support double PA channel:%d unsupport",
302 dev_index);
303 return -EINVAL;
304 }
305 #ifdef AW_QCOM_OPEN_DSP_PLATFORM
306 ret = aw_qcom_write_data_to_dsp(param_id, &vmax, sizeof(uint32_t));
307 #elif defined AW_MTK_OPEN_DSP_PLATFORM
308 ret = aw_mtk_write_data_to_dsp(param_id, &vmax, sizeof(uint32_t));
309 #endif
310
311 return ret;
312 }
313
314