blob: f6d12a8377d0050713127227089232eca3fcd2d2 [file] [log] [blame]
Patrick Lai5fa8aa72013-01-05 21:16:20 -08001/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/slab.h>
14#include <linux/wait.h>
15#include <linux/sched.h>
16#include <linux/jiffies.h>
17#include <linux/uaccess.h>
18#include <linux/atomic.h>
Patrick Lai5fa8aa72013-01-05 21:16:20 -080019#include <linux/err.h>
Ben Rombergerfce8f512011-07-18 16:46:09 -070020
21#include <mach/qdsp6v2/audio_dev_ctl.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070022#include <mach/qdsp6v2/audio_acdb.h>
Ben Rombergerfce8f512011-07-18 16:46:09 -070023#include <mach/qdsp6v2/rtac.h>
24
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070025#include <sound/apr_audio.h>
26#include <sound/q6afe.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070027
28#define TIMEOUT_MS 1000
29#define AUDIO_RX 0x0
30#define AUDIO_TX 0x1
Patrick Laicf999112011-08-23 11:27:20 -070031
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070032#define ASM_MAX_SESSION 0x8 /* To do: define in a header */
33#define RESET_COPP_ID 99
34#define INVALID_COPP_ID 0xFF
35
36struct adm_ctl {
37 void *apr;
38 atomic_t copp_id[AFE_MAX_PORTS];
39 atomic_t copp_cnt[AFE_MAX_PORTS];
40 atomic_t copp_stat[AFE_MAX_PORTS];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070041 wait_queue_head_t wait;
Jayasena Sangaraboinaf4ab0df2012-06-06 22:38:40 -070042 int ec_ref_rx;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070043};
44
Ben Romberger48fabc32012-01-06 17:39:39 -080045static struct acdb_cal_block mem_addr_audproc[MAX_AUDPROC_TYPES];
46static struct acdb_cal_block mem_addr_audvol[MAX_AUDPROC_TYPES];
47
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070048static struct adm_ctl this_adm;
49
Jayasena Sangaraboinaf4ab0df2012-06-06 22:38:40 -070050
Sriranjan Srikantam22bee8b2012-05-31 15:21:53 -070051int srs_trumedia_open(int port_id, int srs_tech_id, void *srs_params)
52{
53 struct asm_pp_params_command *open = NULL;
54 int ret = 0, sz = 0;
55 int index;
56
57 pr_debug("SRS - %s", __func__);
Patrick Lai5fa8aa72013-01-05 21:16:20 -080058
59 index = afe_get_port_index(port_id);
60
61 if (IS_ERR_VALUE(index)) {
62 pr_err("%s: invald port id\n", __func__);
63 return index;
64 }
65
Sriranjan Srikantam22bee8b2012-05-31 15:21:53 -070066 switch (srs_tech_id) {
67 case SRS_ID_GLOBAL: {
68 struct srs_trumedia_params_GLOBAL *glb_params = NULL;
69 sz = sizeof(struct asm_pp_params_command) +
70 sizeof(struct srs_trumedia_params_GLOBAL);
71 open = kzalloc(sz, GFP_KERNEL);
72 open->payload_size = sizeof(struct srs_trumedia_params_GLOBAL) +
73 sizeof(struct asm_pp_param_data_hdr);
74 open->params.param_id = SRS_TRUMEDIA_PARAMS;
75 open->params.param_size =
76 sizeof(struct srs_trumedia_params_GLOBAL);
77 glb_params = (struct srs_trumedia_params_GLOBAL *)((u8 *)open +
78 sizeof(struct asm_pp_params_command));
79 memcpy(glb_params, srs_params,
80 sizeof(struct srs_trumedia_params_GLOBAL));
81 pr_debug("SRS - %s: Global params - 1 = %x, 2 = %x, 3 = %x,"
82 " 4 = %x, 5 = %x, 6 = %x, 7 = %x, 8 = %x\n",
83 __func__, (int)glb_params->v1,
84 (int)glb_params->v2, (int)glb_params->v3,
85 (int)glb_params->v4, (int)glb_params->v5,
86 (int)glb_params->v6, (int)glb_params->v7,
87 (int)glb_params->v8);
88 break;
89 }
90 case SRS_ID_WOWHD: {
91 struct srs_trumedia_params_WOWHD *whd_params = NULL;
92 sz = sizeof(struct asm_pp_params_command) +
93 sizeof(struct srs_trumedia_params_WOWHD);
94 open = kzalloc(sz, GFP_KERNEL);
95 open->payload_size = sizeof(struct srs_trumedia_params_WOWHD) +
96 sizeof(struct asm_pp_param_data_hdr);
97 open->params.param_id = SRS_TRUMEDIA_PARAMS_WOWHD;
98 open->params.param_size =
99 sizeof(struct srs_trumedia_params_WOWHD);
100 whd_params = (struct srs_trumedia_params_WOWHD *)((u8 *)open +
101 sizeof(struct asm_pp_params_command));
102 memcpy(whd_params, srs_params,
103 sizeof(struct srs_trumedia_params_WOWHD));
104 pr_debug("SRS - %s: WOWHD params - 1 = %x, 2 = %x, 3 = %x,"
105 " 4 = %x, 5 = %x, 6 = %x, 7 = %x, 8 = %x, 9 = %x,"
106 " 10 = %x, 11 = %x\n", __func__, (int)whd_params->v1,
107 (int)whd_params->v2, (int)whd_params->v3,
108 (int)whd_params->v4, (int)whd_params->v5,
109 (int)whd_params->v6, (int)whd_params->v7,
110 (int)whd_params->v8, (int)whd_params->v9,
111 (int)whd_params->v10, (int)whd_params->v11);
112 break;
113 }
114 case SRS_ID_CSHP: {
115 struct srs_trumedia_params_CSHP *chp_params = NULL;
116 sz = sizeof(struct asm_pp_params_command) +
117 sizeof(struct srs_trumedia_params_CSHP);
118 open = kzalloc(sz, GFP_KERNEL);
119 open->payload_size = sizeof(struct srs_trumedia_params_CSHP) +
120 sizeof(struct asm_pp_param_data_hdr);
121 open->params.param_id = SRS_TRUMEDIA_PARAMS_CSHP;
122 open->params.param_size =
123 sizeof(struct srs_trumedia_params_CSHP);
124 chp_params = (struct srs_trumedia_params_CSHP *)((u8 *)open +
125 sizeof(struct asm_pp_params_command));
126 memcpy(chp_params, srs_params,
127 sizeof(struct srs_trumedia_params_CSHP));
128 pr_debug("SRS - %s: CSHP params - 1 = %x, 2 = %x, 3 = %x,"
129 " 4 = %x, 5 = %x, 6 = %x, 7 = %x, 8 = %x,"
130 " 9 = %x\n", __func__, (int)chp_params->v1,
131 (int)chp_params->v2, (int)chp_params->v3,
132 (int)chp_params->v4, (int)chp_params->v5,
133 (int)chp_params->v6, (int)chp_params->v7,
134 (int)chp_params->v8, (int)chp_params->v9);
135 break;
136 }
137 case SRS_ID_HPF: {
138 struct srs_trumedia_params_HPF *hpf_params = NULL;
139 sz = sizeof(struct asm_pp_params_command) +
140 sizeof(struct srs_trumedia_params_HPF);
141 open = kzalloc(sz, GFP_KERNEL);
142 open->payload_size = sizeof(struct srs_trumedia_params_HPF) +
143 sizeof(struct asm_pp_param_data_hdr);
144 open->params.param_id = SRS_TRUMEDIA_PARAMS_HPF;
145 open->params.param_size =
146 sizeof(struct srs_trumedia_params_HPF);
147 hpf_params = (struct srs_trumedia_params_HPF *)((u8 *)open +
148 sizeof(struct asm_pp_params_command));
149 memcpy(hpf_params, srs_params,
150 sizeof(struct srs_trumedia_params_HPF));
151 pr_debug("SRS - %s: HPF params - 1 = %x\n", __func__,
152 (int)hpf_params->v1);
153 break;
154 }
155 case SRS_ID_PEQ: {
156 struct srs_trumedia_params_PEQ *peq_params = NULL;
157 sz = sizeof(struct asm_pp_params_command) +
158 sizeof(struct srs_trumedia_params_PEQ);
159 open = kzalloc(sz, GFP_KERNEL);
160 open->payload_size = sizeof(struct srs_trumedia_params_PEQ) +
161 sizeof(struct asm_pp_param_data_hdr);
162 open->params.param_id = SRS_TRUMEDIA_PARAMS_PEQ;
163 open->params.param_size =
164 sizeof(struct srs_trumedia_params_PEQ);
165 peq_params = (struct srs_trumedia_params_PEQ *)((u8 *)open +
166 sizeof(struct asm_pp_params_command));
167 memcpy(peq_params, srs_params,
168 sizeof(struct srs_trumedia_params_PEQ));
169 pr_debug("SRS - %s: PEQ params - 1 = %x 2 = %x, 3 = %x,"
170 " 4 = %x\n", __func__, (int)peq_params->v1,
171 (int)peq_params->v2, (int)peq_params->v3,
172 (int)peq_params->v4);
173 break;
174 }
175 case SRS_ID_HL: {
176 struct srs_trumedia_params_HL *hl_params = NULL;
177 sz = sizeof(struct asm_pp_params_command) +
178 sizeof(struct srs_trumedia_params_HL);
179 open = kzalloc(sz, GFP_KERNEL);
180 open->payload_size = sizeof(struct srs_trumedia_params_HL) +
181 sizeof(struct asm_pp_param_data_hdr);
182 open->params.param_id = SRS_TRUMEDIA_PARAMS_HL;
183 open->params.param_size = sizeof(struct srs_trumedia_params_HL);
184 hl_params = (struct srs_trumedia_params_HL *)((u8 *)open +
185 sizeof(struct asm_pp_params_command));
186 memcpy(hl_params, srs_params,
187 sizeof(struct srs_trumedia_params_HL));
188 pr_debug("SRS - %s: HL params - 1 = %x, 2 = %x, 3 = %x, 4 = %x,"
189 " 5 = %x, 6 = %x, 7 = %x\n", __func__,
190 (int)hl_params->v1, (int)hl_params->v2,
191 (int)hl_params->v3, (int)hl_params->v4,
192 (int)hl_params->v5, (int)hl_params->v6,
193 (int)hl_params->v7);
194 break;
195 }
196 default:
197 goto fail_cmd;
198 }
199
200 open->payload = NULL;
201 open->params.module_id = SRS_TRUMEDIA_MODULE_ID;
202 open->params.reserved = 0;
203 open->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
204 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
205 open->hdr.pkt_size = sz;
206 open->hdr.src_svc = APR_SVC_ADM;
207 open->hdr.src_domain = APR_DOMAIN_APPS;
208 open->hdr.src_port = port_id;
209 open->hdr.dest_svc = APR_SVC_ADM;
210 open->hdr.dest_domain = APR_DOMAIN_ADSP;
Sriranjan Srikantam22bee8b2012-05-31 15:21:53 -0700211 open->hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
212 open->hdr.token = port_id;
213 open->hdr.opcode = ADM_CMD_SET_PARAMS;
214 pr_debug("SRS - %s: Command was sent now check Q6 - port id = %d,"
215 " size %d, module id %x, param id %x.\n", __func__,
216 open->hdr.dest_port, open->payload_size,
217 open->params.module_id, open->params.param_id);
218
219 ret = apr_send_pkt(this_adm.apr, (uint32_t *)open);
220 if (ret < 0) {
221 pr_err("SRS - %s: ADM enable for port %d failed\n", __func__,
222 port_id);
223 ret = -EINVAL;
224 goto fail_cmd;
225 }
226 /* Wait for the callback with copp id */
227 ret = wait_event_timeout(this_adm.wait, 1,
228 msecs_to_jiffies(TIMEOUT_MS));
229 if (!ret) {
230 pr_err("SRS - %s: ADM open failed for port %d\n", __func__,
231 port_id);
232 ret = -EINVAL;
233 goto fail_cmd;
234 }
235
236fail_cmd:
237 kfree(open);
238 return ret;
239}
240
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700241static int32_t adm_callback(struct apr_client_data *data, void *priv)
242{
243 uint32_t *payload;
244 int i, index;
245 payload = data->payload;
246
247 if (data->opcode == RESET_EVENTS) {
248 pr_debug("adm_callback: Reset event is received: %d %d apr[%p]\n",
249 data->reset_event, data->reset_proc,
250 this_adm.apr);
251 if (this_adm.apr) {
252 apr_reset(this_adm.apr);
253 for (i = 0; i < AFE_MAX_PORTS; i++) {
254 atomic_set(&this_adm.copp_id[i],
255 RESET_COPP_ID);
256 atomic_set(&this_adm.copp_cnt[i], 0);
257 atomic_set(&this_adm.copp_stat[i], 0);
258 }
259 this_adm.apr = NULL;
260 }
Deepa Madiregama4c054d22012-08-23 15:05:29 +0530261 pr_debug("Resetting calibration blocks");
262 for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
263 /* Device calibration */
264 mem_addr_audproc[i].cal_size = 0;
265 mem_addr_audproc[i].cal_kvaddr = 0;
266 mem_addr_audproc[i].cal_paddr = 0;
267
268 /* Volume calibration */
269 mem_addr_audvol[i].cal_size = 0;
270 mem_addr_audvol[i].cal_kvaddr = 0;
271 mem_addr_audvol[i].cal_paddr = 0;
272 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700273 return 0;
274 }
275
276 pr_debug("%s: code = 0x%x %x %x size = %d\n", __func__,
277 data->opcode, payload[0], payload[1],
278 data->payload_size);
279
280 if (data->payload_size) {
281 index = afe_get_port_index(data->token);
282 pr_debug("%s: Port ID %d, index %d\n", __func__,
283 data->token, index);
Bharath Ramachandramurthy94ad7e22012-02-28 18:44:07 -0800284 if (index < 0 || index >= AFE_MAX_PORTS) {
285 pr_err("%s: invalid port idx %d token %d\n",
286 __func__, index, data->token);
287 return 0;
288 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700289 if (data->opcode == APR_BASIC_RSP_RESULT) {
Santosh Mardi23321202012-03-22 04:33:25 +0530290 pr_debug("APR_BASIC_RSP_RESULT id %x\n", payload[0]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700291 switch (payload[0]) {
292 case ADM_CMD_SET_PARAMS:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700293 if (rtac_make_adm_callback(payload,
294 data->payload_size))
295 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700296 case ADM_CMD_COPP_CLOSE:
297 case ADM_CMD_MEMORY_MAP:
298 case ADM_CMD_MEMORY_UNMAP:
299 case ADM_CMD_MEMORY_MAP_REGIONS:
300 case ADM_CMD_MEMORY_UNMAP_REGIONS:
301 case ADM_CMD_MATRIX_MAP_ROUTINGS:
Santosh Mardi23321202012-03-22 04:33:25 +0530302 case ADM_CMD_CONNECT_AFE_PORT:
Santosh Mardid1760792012-06-12 16:23:19 +0530303 case ADM_CMD_DISCONNECT_AFE_PORT:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700304 atomic_set(&this_adm.copp_stat[index], 1);
305 wake_up(&this_adm.wait);
306 break;
307 default:
308 pr_err("%s: Unknown Cmd: 0x%x\n", __func__,
309 payload[0]);
310 break;
311 }
312 return 0;
313 }
314
315 switch (data->opcode) {
Kiran Kandi5e809b02012-01-31 00:24:33 -0800316 case ADM_CMDRSP_COPP_OPEN:
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -0700317 case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN:
318 case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN_V3: {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700319 struct adm_copp_open_respond *open = data->payload;
320 if (open->copp_id == INVALID_COPP_ID) {
321 pr_err("%s: invalid coppid rxed %d\n",
322 __func__, open->copp_id);
323 atomic_set(&this_adm.copp_stat[index], 1);
324 wake_up(&this_adm.wait);
325 break;
326 }
327 atomic_set(&this_adm.copp_id[index], open->copp_id);
328 atomic_set(&this_adm.copp_stat[index], 1);
329 pr_debug("%s: coppid rxed=%d\n", __func__,
330 open->copp_id);
331 wake_up(&this_adm.wait);
332 }
333 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700334 case ADM_CMDRSP_GET_PARAMS:
Swaminathan Sathappan88163a72011-08-01 16:01:14 -0700335 pr_debug("%s: ADM_CMDRSP_GET_PARAMS\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700336 rtac_make_adm_callback(payload,
337 data->payload_size);
338 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700339 default:
340 pr_err("%s: Unknown cmd:0x%x\n", __func__,
341 data->opcode);
342 break;
343 }
344 }
345 return 0;
346}
347
Ben Romberger48fabc32012-01-06 17:39:39 -0800348static int send_adm_cal_block(int port_id, struct acdb_cal_block *aud_cal)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700349{
Ben Rombergerdcab5472011-12-08 19:20:12 -0800350 s32 result = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700351 struct adm_set_params_command adm_params;
352 int index = afe_get_port_index(port_id);
Ben Romberger09dc65f2012-03-22 20:06:55 -0700353 if (index < 0 || index >= AFE_MAX_PORTS) {
354 pr_err("%s: invalid port idx %d portid %d\n",
355 __func__, index, port_id);
Mingming Yinc09967e2012-04-27 15:09:43 -0700356 return 0;
Ben Romberger09dc65f2012-03-22 20:06:55 -0700357 }
Mingming Yinc09967e2012-04-27 15:09:43 -0700358
359 pr_debug("%s: Port id %d, index %d\n", __func__, port_id, index);
360
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700361 if (!aud_cal || aud_cal->cal_size == 0) {
Ben Rombergerdcab5472011-12-08 19:20:12 -0800362 pr_debug("%s: No ADM cal to send for port_id = %d!\n",
363 __func__, port_id);
364 result = -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700365 goto done;
366 }
367
368 adm_params.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
369 APR_HDR_LEN(20), APR_PKT_VER);
370 adm_params.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
371 sizeof(adm_params));
372 adm_params.hdr.src_svc = APR_SVC_ADM;
373 adm_params.hdr.src_domain = APR_DOMAIN_APPS;
374 adm_params.hdr.src_port = port_id;
375 adm_params.hdr.dest_svc = APR_SVC_ADM;
376 adm_params.hdr.dest_domain = APR_DOMAIN_ADSP;
377 adm_params.hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
378 adm_params.hdr.token = port_id;
379 adm_params.hdr.opcode = ADM_CMD_SET_PARAMS;
380 adm_params.payload = aud_cal->cal_paddr;
381 adm_params.payload_size = aud_cal->cal_size;
382
383 atomic_set(&this_adm.copp_stat[index], 0);
384 pr_debug("%s: Sending SET_PARAMS payload = 0x%x, size = %d\n",
385 __func__, adm_params.payload, adm_params.payload_size);
386 result = apr_send_pkt(this_adm.apr, (uint32_t *)&adm_params);
387 if (result < 0) {
388 pr_err("%s: Set params failed port = %d payload = 0x%x\n",
389 __func__, port_id, aud_cal->cal_paddr);
Ben Rombergerdcab5472011-12-08 19:20:12 -0800390 result = -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700391 goto done;
392 }
393 /* Wait for the callback */
394 result = wait_event_timeout(this_adm.wait,
395 atomic_read(&this_adm.copp_stat[index]),
396 msecs_to_jiffies(TIMEOUT_MS));
Ben Rombergerdcab5472011-12-08 19:20:12 -0800397 if (!result) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700398 pr_err("%s: Set params timed out port = %d, payload = 0x%x\n",
399 __func__, port_id, aud_cal->cal_paddr);
Ben Rombergerdcab5472011-12-08 19:20:12 -0800400 result = -EINVAL;
401 goto done;
402 }
403
404 result = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700405done:
Ben Rombergerdcab5472011-12-08 19:20:12 -0800406 return result;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700407}
408
Ben Romberger48fabc32012-01-06 17:39:39 -0800409static void send_adm_cal(int port_id, int path)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700410{
Ben Romberger48fabc32012-01-06 17:39:39 -0800411 int result = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700412 s32 acdb_path;
413 struct acdb_cal_block aud_cal;
414
415 pr_debug("%s\n", __func__);
416
417 /* Maps audio_dev_ctrl path definition to ACDB definition */
418 acdb_path = path - 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700419
420 pr_debug("%s: Sending audproc cal\n", __func__);
421 get_audproc_cal(acdb_path, &aud_cal);
Ben Romberger48fabc32012-01-06 17:39:39 -0800422
423 /* map & cache buffers used */
Ben Romberger9e792562012-02-24 12:29:01 -0800424 if (((mem_addr_audproc[acdb_path].cal_paddr != aud_cal.cal_paddr) &&
425 (aud_cal.cal_size > 0)) ||
426 (aud_cal.cal_size > mem_addr_audproc[acdb_path].cal_size)) {
427
Ben Romberger48fabc32012-01-06 17:39:39 -0800428 if (mem_addr_audproc[acdb_path].cal_paddr != 0)
429 adm_memory_unmap_regions(
430 &mem_addr_audproc[acdb_path].cal_paddr,
431 &mem_addr_audproc[acdb_path].cal_size, 1);
432
433 result = adm_memory_map_regions(&aud_cal.cal_paddr, 0,
434 &aud_cal.cal_size, 1);
435 if (result < 0)
436 pr_err("ADM audproc mmap did not work! path = %d, "
437 "addr = 0x%x, size = %d\n", acdb_path,
438 aud_cal.cal_paddr, aud_cal.cal_size);
439 else
440 mem_addr_audproc[acdb_path] = aud_cal;
441 }
442
Ben Rombergerdcab5472011-12-08 19:20:12 -0800443 if (!send_adm_cal_block(port_id, &aud_cal))
Ben Romberger48fabc32012-01-06 17:39:39 -0800444 pr_debug("%s: Audproc cal sent for port id: %d, path %d\n",
Ben Rombergerdcab5472011-12-08 19:20:12 -0800445 __func__, port_id, acdb_path);
446 else
Ben Romberger48fabc32012-01-06 17:39:39 -0800447 pr_debug("%s: Audproc cal not sent for port id: %d, path %d\n",
Ben Rombergerdcab5472011-12-08 19:20:12 -0800448 __func__, port_id, acdb_path);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700449
450 pr_debug("%s: Sending audvol cal\n", __func__);
451 get_audvol_cal(acdb_path, &aud_cal);
Ben Romberger48fabc32012-01-06 17:39:39 -0800452
453 /* map & cache buffers used */
Ben Romberger9e792562012-02-24 12:29:01 -0800454 if (((mem_addr_audvol[acdb_path].cal_paddr != aud_cal.cal_paddr) &&
455 (aud_cal.cal_size > 0)) ||
456 (aud_cal.cal_size > mem_addr_audvol[acdb_path].cal_size)) {
Ben Romberger48fabc32012-01-06 17:39:39 -0800457 if (mem_addr_audvol[acdb_path].cal_paddr != 0)
458 adm_memory_unmap_regions(
459 &mem_addr_audvol[acdb_path].cal_paddr,
460 &mem_addr_audvol[acdb_path].cal_size, 1);
461
462 result = adm_memory_map_regions(&aud_cal.cal_paddr, 0,
463 &aud_cal.cal_size, 1);
464 if (result < 0)
465 pr_err("ADM audvol mmap did not work! path = %d, "
466 "addr = 0x%x, size = %d\n", acdb_path,
467 aud_cal.cal_paddr, aud_cal.cal_size);
468 else
469 mem_addr_audvol[acdb_path] = aud_cal;
470 }
471
Ben Rombergerdcab5472011-12-08 19:20:12 -0800472 if (!send_adm_cal_block(port_id, &aud_cal))
Ben Romberger48fabc32012-01-06 17:39:39 -0800473 pr_debug("%s: Audvol cal sent for port id: %d, path %d\n",
Ben Rombergerdcab5472011-12-08 19:20:12 -0800474 __func__, port_id, acdb_path);
475 else
Ben Romberger48fabc32012-01-06 17:39:39 -0800476 pr_debug("%s: Audvol cal not sent for port id: %d, path %d\n",
Ben Rombergerdcab5472011-12-08 19:20:12 -0800477 __func__, port_id, acdb_path);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700478}
479
Santosh Mardi23321202012-03-22 04:33:25 +0530480int adm_connect_afe_port(int mode, int session_id, int port_id)
481{
482 struct adm_cmd_connect_afe_port cmd;
483 int ret = 0;
484 int index;
485
486 pr_debug("%s: port %d session id:%d mode:%d\n", __func__,
487 port_id, session_id, mode);
488
489 port_id = afe_convert_virtual_to_portid(port_id);
490
491 if (afe_validate_port(port_id) < 0) {
492 pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
493 return -ENODEV;
494 }
495 if (this_adm.apr == NULL) {
496 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
497 0xFFFFFFFF, &this_adm);
498 if (this_adm.apr == NULL) {
499 pr_err("%s: Unable to register ADM\n", __func__);
500 ret = -ENODEV;
501 return ret;
502 }
503 rtac_set_adm_handle(this_adm.apr);
504 }
505 index = afe_get_port_index(port_id);
506 pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
507
508 cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
509 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
510 cmd.hdr.pkt_size = sizeof(cmd);
511 cmd.hdr.src_svc = APR_SVC_ADM;
512 cmd.hdr.src_domain = APR_DOMAIN_APPS;
513 cmd.hdr.src_port = port_id;
514 cmd.hdr.dest_svc = APR_SVC_ADM;
515 cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
516 cmd.hdr.dest_port = port_id;
517 cmd.hdr.token = port_id;
518 cmd.hdr.opcode = ADM_CMD_CONNECT_AFE_PORT;
519
520 cmd.mode = mode;
521 cmd.session_id = session_id;
522 cmd.afe_port_id = port_id;
523
524 atomic_set(&this_adm.copp_stat[index], 0);
525 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd);
526 if (ret < 0) {
527 pr_err("%s:ADM enable for port %d failed\n",
528 __func__, port_id);
529 ret = -EINVAL;
530 goto fail_cmd;
531 }
532 /* Wait for the callback with copp id */
533 ret = wait_event_timeout(this_adm.wait,
534 atomic_read(&this_adm.copp_stat[index]),
535 msecs_to_jiffies(TIMEOUT_MS));
536 if (!ret) {
537 pr_err("%s ADM connect AFE failed for port %d\n", __func__,
538 port_id);
539 ret = -EINVAL;
540 goto fail_cmd;
541 }
542 atomic_inc(&this_adm.copp_cnt[index]);
543 return 0;
544
545fail_cmd:
546
547 return ret;
548}
549
Santosh Mardid1760792012-06-12 16:23:19 +0530550int adm_disconnect_afe_port(int mode, int session_id, int port_id)
551{
552 struct adm_cmd_connect_afe_port cmd;
553 int ret = 0;
554 int index;
555
556 pr_debug("%s: port %d session id:%d mode:%d\n", __func__,
557 port_id, session_id, mode);
558
559 port_id = afe_convert_virtual_to_portid(port_id);
560
561 if (afe_validate_port(port_id) < 0) {
562 pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
563 return -ENODEV;
564 }
565 if (this_adm.apr == NULL) {
566 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
567 0xFFFFFFFF, &this_adm);
568 if (this_adm.apr == NULL) {
569 pr_err("%s: Unable to register ADM\n", __func__);
570 ret = -ENODEV;
571 return ret;
572 }
573 rtac_set_adm_handle(this_adm.apr);
574 }
575 index = afe_get_port_index(port_id);
576 pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
577
578 cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
579 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
580 cmd.hdr.pkt_size = sizeof(cmd);
581 cmd.hdr.src_svc = APR_SVC_ADM;
582 cmd.hdr.src_domain = APR_DOMAIN_APPS;
583 cmd.hdr.src_port = port_id;
584 cmd.hdr.dest_svc = APR_SVC_ADM;
585 cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
586 cmd.hdr.dest_port = port_id;
587 cmd.hdr.token = port_id;
588 cmd.hdr.opcode = ADM_CMD_DISCONNECT_AFE_PORT;
589
590 cmd.mode = mode;
591 cmd.session_id = session_id;
592 cmd.afe_port_id = port_id;
593
594 atomic_set(&this_adm.copp_stat[index], 0);
595 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd);
596 if (ret < 0) {
597 pr_err("%s:ADM enable for port %d failed\n",
598 __func__, port_id);
599 ret = -EINVAL;
600 goto fail_cmd;
601 }
602 /* Wait for the callback with copp id */
603 ret = wait_event_timeout(this_adm.wait,
604 atomic_read(&this_adm.copp_stat[index]),
605 msecs_to_jiffies(TIMEOUT_MS));
606 if (!ret) {
607 pr_err("%s ADM connect AFE failed for port %d\n", __func__,
608 port_id);
609 ret = -EINVAL;
610 goto fail_cmd;
611 }
612 atomic_dec(&this_adm.copp_cnt[index]);
613 return 0;
614
615fail_cmd:
616
617 return ret;
618}
619
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700620int adm_open(int port_id, int path, int rate, int channel_mode, int topology)
621{
622 struct adm_copp_open_command open;
623 int ret = 0;
624 int index;
625
626 pr_debug("%s: port %d path:%d rate:%d mode:%d\n", __func__,
627 port_id, path, rate, channel_mode);
628
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530629 port_id = afe_convert_virtual_to_portid(port_id);
630
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700631 if (afe_validate_port(port_id) < 0) {
632 pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
633 return -ENODEV;
634 }
635
636 index = afe_get_port_index(port_id);
637 pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
638
639 if (this_adm.apr == NULL) {
640 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
641 0xFFFFFFFF, &this_adm);
642 if (this_adm.apr == NULL) {
643 pr_err("%s: Unable to register ADM\n", __func__);
644 ret = -ENODEV;
645 return ret;
646 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700647 rtac_set_adm_handle(this_adm.apr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700648 }
649
650
651 /* Create a COPP if port id are not enabled */
652 if (atomic_read(&this_adm.copp_cnt[index]) == 0) {
653
654 open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
655 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
656 open.hdr.pkt_size = sizeof(open);
657 open.hdr.src_svc = APR_SVC_ADM;
658 open.hdr.src_domain = APR_DOMAIN_APPS;
659 open.hdr.src_port = port_id;
660 open.hdr.dest_svc = APR_SVC_ADM;
661 open.hdr.dest_domain = APR_DOMAIN_ADSP;
662 open.hdr.dest_port = port_id;
663 open.hdr.token = port_id;
664 open.hdr.opcode = ADM_CMD_COPP_OPEN;
665
666 open.mode = path;
667 open.endpoint_id1 = port_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700668
Jayasena Sangaraboinaf4ab0df2012-06-06 22:38:40 -0700669 if (this_adm.ec_ref_rx == 0) {
670 open.endpoint_id2 = 0xFFFF;
671 } else if (this_adm.ec_ref_rx && (path != 1)) {
672 open.endpoint_id2 = this_adm.ec_ref_rx;
673 this_adm.ec_ref_rx = 0;
674 }
675
676 pr_debug("%s open.endpoint_id1:%d open.endpoint_id2:%d",
677 __func__, open.endpoint_id1, open.endpoint_id2);
Ben Rombergerc49b85d2011-07-15 18:55:34 -0700678 /* convert path to acdb path */
Ben Romberger974a40d2011-07-18 15:08:21 -0700679 if (path == ADM_PATH_PLAYBACK)
Ben Rombergerc49b85d2011-07-15 18:55:34 -0700680 open.topology_id = get_adm_rx_topology();
Jay Wang4fa2ee42011-07-18 00:21:22 -0700681 else {
Ben Rombergerc49b85d2011-07-15 18:55:34 -0700682 open.topology_id = get_adm_tx_topology();
Jay Wang4fa2ee42011-07-18 00:21:22 -0700683 if ((open.topology_id ==
684 VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
685 (open.topology_id ==
Jay Wang17283132012-03-30 15:18:12 -0700686 VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
Jay Wang4fa2ee42011-07-18 00:21:22 -0700687 rate = 16000;
688 }
Ben Rombergerc49b85d2011-07-15 18:55:34 -0700689
Sidipotu Ashok21d1db32013-03-11 20:51:09 +0530690 if ((open.topology_id == 0) || (port_id == VOICE_RECORD_RX) || (port_id == VOICE_RECORD_TX))
691 open.topology_id = topology;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700692
693 open.channel_config = channel_mode & 0x00FF;
694 open.rate = rate;
695
Bharath Ramachandramurthy94ad7e22012-02-28 18:44:07 -0800696 pr_debug("%s: channel_config=%d port_id=%d rate=%d"
697 "topology_id=0x%X\n", __func__, open.channel_config,\
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700698 open.endpoint_id1, open.rate,\
699 open.topology_id);
700
701 atomic_set(&this_adm.copp_stat[index], 0);
702
703 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
704 if (ret < 0) {
705 pr_err("%s:ADM enable for port %d failed\n",
706 __func__, port_id);
707 ret = -EINVAL;
708 goto fail_cmd;
709 }
710 /* Wait for the callback with copp id */
711 ret = wait_event_timeout(this_adm.wait,
712 atomic_read(&this_adm.copp_stat[index]),
713 msecs_to_jiffies(TIMEOUT_MS));
714 if (!ret) {
715 pr_err("%s ADM open failed for port %d\n", __func__,
716 port_id);
717 ret = -EINVAL;
718 goto fail_cmd;
719 }
720 }
721 atomic_inc(&this_adm.copp_cnt[index]);
722 return 0;
723
724fail_cmd:
725
726 return ret;
727}
728
Kiran Kandi5e809b02012-01-31 00:24:33 -0800729
730int adm_multi_ch_copp_open(int port_id, int path, int rate, int channel_mode,
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -0700731 int topology, int perfmode)
Kiran Kandi5e809b02012-01-31 00:24:33 -0800732{
733 struct adm_multi_ch_copp_open_command open;
734 int ret = 0;
735 int index;
736
737 pr_debug("%s: port %d path:%d rate:%d channel :%d\n", __func__,
738 port_id, path, rate, channel_mode);
739
740 port_id = afe_convert_virtual_to_portid(port_id);
741
742 if (afe_validate_port(port_id) < 0) {
743 pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
744 return -ENODEV;
745 }
746
747 index = afe_get_port_index(port_id);
748 pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
749
750 if (this_adm.apr == NULL) {
751 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
752 0xFFFFFFFF, &this_adm);
753 if (this_adm.apr == NULL) {
754 pr_err("%s: Unable to register ADM\n", __func__);
755 ret = -ENODEV;
756 return ret;
757 }
758 rtac_set_adm_handle(this_adm.apr);
759 }
760
761 /* Create a COPP if port id are not enabled */
762 if (atomic_read(&this_adm.copp_cnt[index]) == 0) {
763
764 open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
765 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
766
767 open.hdr.pkt_size =
768 sizeof(struct adm_multi_ch_copp_open_command);
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -0700769
770 if (perfmode) {
771 pr_debug("%s Performance mode", __func__);
772 open.hdr.opcode = ADM_CMD_MULTI_CHANNEL_COPP_OPEN_V3;
773 open.flags = ADM_MULTI_CH_COPP_OPEN_PERF_MODE_BIT;
774 open.reserved = PCM_BITS_PER_SAMPLE;
775 } else {
776 open.hdr.opcode = ADM_CMD_MULTI_CHANNEL_COPP_OPEN;
777 open.reserved = 0;
778 }
779
Kiran Kandi5e809b02012-01-31 00:24:33 -0800780 memset(open.dev_channel_mapping, 0, 8);
781
782 if (channel_mode == 1) {
783 open.dev_channel_mapping[0] = PCM_CHANNEL_FC;
784 } else if (channel_mode == 2) {
785 open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
786 open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
Mingming Yin647e9ea2012-03-17 19:56:10 -0700787 } else if (channel_mode == 4) {
788 open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
789 open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
790 open.dev_channel_mapping[2] = PCM_CHANNEL_RB;
791 open.dev_channel_mapping[3] = PCM_CHANNEL_LB;
Kiran Kandi5e809b02012-01-31 00:24:33 -0800792 } else if (channel_mode == 6) {
793 open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
794 open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
795 open.dev_channel_mapping[2] = PCM_CHANNEL_LFE;
796 open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
797 open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
798 open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
Subhash Chandra Bose Naripeddy8477d222012-06-12 00:30:54 -0700799 } else if (channel_mode == 8) {
800 open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
801 open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
802 open.dev_channel_mapping[2] = PCM_CHANNEL_LFE;
803 open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
804 open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
805 open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
806 open.dev_channel_mapping[6] = PCM_CHANNEL_FLC;
807 open.dev_channel_mapping[7] = PCM_CHANNEL_FRC;
Kiran Kandi5e809b02012-01-31 00:24:33 -0800808 } else {
809 pr_err("%s invalid num_chan %d\n", __func__,
810 channel_mode);
811 return -EINVAL;
812 }
Kiran Kandi5e809b02012-01-31 00:24:33 -0800813 open.hdr.src_svc = APR_SVC_ADM;
814 open.hdr.src_domain = APR_DOMAIN_APPS;
815 open.hdr.src_port = port_id;
816 open.hdr.dest_svc = APR_SVC_ADM;
817 open.hdr.dest_domain = APR_DOMAIN_ADSP;
818 open.hdr.dest_port = port_id;
819 open.hdr.token = port_id;
820
821 open.mode = path;
822 open.endpoint_id1 = port_id;
Kiran Kandi5e809b02012-01-31 00:24:33 -0800823
Jayasena Sangaraboinaf4ab0df2012-06-06 22:38:40 -0700824 if (this_adm.ec_ref_rx == 0) {
825 open.endpoint_id2 = 0xFFFF;
826 } else if (this_adm.ec_ref_rx && (path != 1)) {
827 open.endpoint_id2 = this_adm.ec_ref_rx;
828 this_adm.ec_ref_rx = 0;
829 }
830
831 pr_debug("%s open.endpoint_id1:%d open.endpoint_id2:%d",
832 __func__, open.endpoint_id1, open.endpoint_id2);
Kiran Kandi5e809b02012-01-31 00:24:33 -0800833 /* convert path to acdb path */
834 if (path == ADM_PATH_PLAYBACK)
835 open.topology_id = get_adm_rx_topology();
836 else {
837 open.topology_id = get_adm_tx_topology();
838 if ((open.topology_id ==
839 VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
840 (open.topology_id ==
Jay Wang0124d872012-05-23 14:10:36 -0700841 VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
Kiran Kandi5e809b02012-01-31 00:24:33 -0800842 rate = 16000;
843 }
844
Sidipotu Ashok21d1db32013-03-11 20:51:09 +0530845 if ((open.topology_id == 0) || (port_id == VOICE_RECORD_RX) || (port_id == VOICE_RECORD_TX))
846 open.topology_id = topology;
Kiran Kandi5e809b02012-01-31 00:24:33 -0800847
848 open.channel_config = channel_mode & 0x00FF;
849 open.rate = rate;
850
851 pr_debug("%s: channel_config=%d port_id=%d rate=%d"
852 " topology_id=0x%X\n", __func__, open.channel_config,
853 open.endpoint_id1, open.rate,
854 open.topology_id);
855
856 atomic_set(&this_adm.copp_stat[index], 0);
857
858 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
859 if (ret < 0) {
860 pr_err("%s:ADM enable for port %d failed\n",
861 __func__, port_id);
862 ret = -EINVAL;
863 goto fail_cmd;
864 }
865 /* Wait for the callback with copp id */
866 ret = wait_event_timeout(this_adm.wait,
867 atomic_read(&this_adm.copp_stat[index]),
868 msecs_to_jiffies(TIMEOUT_MS));
869 if (!ret) {
870 pr_err("%s ADM open failed for port %d\n", __func__,
871 port_id);
872 ret = -EINVAL;
873 goto fail_cmd;
874 }
875 }
876 atomic_inc(&this_adm.copp_cnt[index]);
877 return 0;
878
879fail_cmd:
880
881 return ret;
882}
883
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700884int adm_matrix_map(int session_id, int path, int num_copps,
885 unsigned int *port_id, int copp_id)
886{
887 struct adm_routings_command route;
888 int ret = 0, i = 0;
889 /* Assumes port_ids have already been validated during adm_open */
890 int index = afe_get_port_index(copp_id);
Patrick Lai3e9d3362013-01-07 16:35:28 -0800891 int copp_cnt;
892
Mingming Yinc09967e2012-04-27 15:09:43 -0700893 if (index < 0 || index >= AFE_MAX_PORTS) {
894 pr_err("%s: invalid port idx %d token %d\n",
895 __func__, index, copp_id);
896 return 0;
897 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700898
899 pr_debug("%s: session 0x%x path:%d num_copps:%d port_id[0]:%d\n",
900 __func__, session_id, path, num_copps, port_id[0]);
901
902 route.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
903 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
904 route.hdr.pkt_size = sizeof(route);
905 route.hdr.src_svc = 0;
906 route.hdr.src_domain = APR_DOMAIN_APPS;
907 route.hdr.src_port = copp_id;
908 route.hdr.dest_svc = APR_SVC_ADM;
909 route.hdr.dest_domain = APR_DOMAIN_ADSP;
910 route.hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
911 route.hdr.token = copp_id;
912 route.hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS;
913 route.num_sessions = 1;
914 route.session[0].id = session_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700915
Patrick Lai3e9d3362013-01-07 16:35:28 -0800916 if (num_copps < ADM_MAX_COPPS) {
917 copp_cnt = num_copps;
918 } else {
919 copp_cnt = ADM_MAX_COPPS;
920 /* print out warning for now as playback/capture to/from
921 * COPPs more than maximum allowed is extremely unlikely
922 */
923 pr_warn("%s: max out routable COPPs\n", __func__);
924 }
925
926 route.session[0].num_copps = copp_cnt;
927 for (i = 0; i < copp_cnt; i++) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700928 int tmp;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530929 port_id[i] = afe_convert_virtual_to_portid(port_id[i]);
930
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700931 tmp = afe_get_port_index(port_id[i]);
932
933 pr_debug("%s: port_id[%d]: %d, index: %d\n", __func__, i,
934 port_id[i], tmp);
935
Mingming Yinc09967e2012-04-27 15:09:43 -0700936 if (tmp >= 0 && tmp < AFE_MAX_PORTS)
Bharath Ramachandramurthy94ad7e22012-02-28 18:44:07 -0800937 route.session[0].copp_id[i] =
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700938 atomic_read(&this_adm.copp_id[tmp]);
939 }
Patrick Lai3e9d3362013-01-07 16:35:28 -0800940
941 if (copp_cnt % 2)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700942 route.session[0].copp_id[i] = 0;
943
944 switch (path) {
945 case 0x1:
946 route.path = AUDIO_RX;
947 break;
948 case 0x2:
949 case 0x3:
950 route.path = AUDIO_TX;
951 break;
952 default:
953 pr_err("%s: Wrong path set[%d]\n", __func__, path);
954 break;
955 }
956 atomic_set(&this_adm.copp_stat[index], 0);
957
958 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&route);
959 if (ret < 0) {
960 pr_err("%s: ADM routing for port %d failed\n",
961 __func__, port_id[0]);
962 ret = -EINVAL;
963 goto fail_cmd;
964 }
965 ret = wait_event_timeout(this_adm.wait,
966 atomic_read(&this_adm.copp_stat[index]),
967 msecs_to_jiffies(TIMEOUT_MS));
968 if (!ret) {
969 pr_err("%s: ADM cmd Route failed for port %d\n",
970 __func__, port_id[0]);
971 ret = -EINVAL;
972 goto fail_cmd;
973 }
974
975 for (i = 0; i < num_copps; i++)
976 send_adm_cal(port_id[i], path);
977
Jay Wang8feb3f02013-02-28 15:24:44 -0800978 for (i = 0; i < num_copps; i++) {
979 int tmp;
980 tmp = afe_get_port_index(port_id[i]);
981 if (tmp >= 0 && tmp < AFE_MAX_PORTS)
982 rtac_add_adm_device(port_id[i],
983 atomic_read(&this_adm.copp_id[tmp]),
984 path, session_id);
985 else
986 pr_debug("%s: Invalid port index %d",
987 __func__, tmp);
988 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700989 return 0;
990
991fail_cmd:
992
993 return ret;
994}
995
996int adm_memory_map_regions(uint32_t *buf_add, uint32_t mempool_id,
997 uint32_t *bufsz, uint32_t bufcnt)
998{
999 struct adm_cmd_memory_map_regions *mmap_regions = NULL;
1000 struct adm_memory_map_regions *mregions = NULL;
1001 void *mmap_region_cmd = NULL;
1002 void *payload = NULL;
1003 int ret = 0;
1004 int i = 0;
1005 int cmd_size = 0;
1006
Ben Rombergerb7603232011-11-23 17:16:27 -08001007 pr_debug("%s\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001008 if (this_adm.apr == NULL) {
1009 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
1010 0xFFFFFFFF, &this_adm);
1011 if (this_adm.apr == NULL) {
1012 pr_err("%s: Unable to register ADM\n", __func__);
1013 ret = -ENODEV;
1014 return ret;
1015 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001016 rtac_set_adm_handle(this_adm.apr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001017 }
1018
1019 cmd_size = sizeof(struct adm_cmd_memory_map_regions)
1020 + sizeof(struct adm_memory_map_regions) * bufcnt;
1021
1022 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
1023 if (!mmap_region_cmd) {
1024 pr_err("%s: allocate mmap_region_cmd failed\n", __func__);
1025 return -ENOMEM;
1026 }
1027 mmap_regions = (struct adm_cmd_memory_map_regions *)mmap_region_cmd;
1028 mmap_regions->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1029 APR_HDR_LEN(APR_HDR_SIZE),
1030 APR_PKT_VER);
1031 mmap_regions->hdr.pkt_size = cmd_size;
1032 mmap_regions->hdr.src_port = 0;
1033 mmap_regions->hdr.dest_port = 0;
1034 mmap_regions->hdr.token = 0;
1035 mmap_regions->hdr.opcode = ADM_CMD_MEMORY_MAP_REGIONS;
1036 mmap_regions->mempool_id = mempool_id & 0x00ff;
1037 mmap_regions->nregions = bufcnt & 0x00ff;
1038 pr_debug("%s: map_regions->nregions = %d\n", __func__,
1039 mmap_regions->nregions);
1040 payload = ((u8 *) mmap_region_cmd +
1041 sizeof(struct adm_cmd_memory_map_regions));
1042 mregions = (struct adm_memory_map_regions *)payload;
1043
1044 for (i = 0; i < bufcnt; i++) {
1045 mregions->phys = buf_add[i];
1046 mregions->buf_size = bufsz[i];
1047 ++mregions;
1048 }
1049
1050 atomic_set(&this_adm.copp_stat[0], 0);
1051 ret = apr_send_pkt(this_adm.apr, (uint32_t *) mmap_region_cmd);
1052 if (ret < 0) {
1053 pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
1054 mmap_regions->hdr.opcode, ret);
1055 ret = -EINVAL;
1056 goto fail_cmd;
1057 }
1058
1059 ret = wait_event_timeout(this_adm.wait,
1060 atomic_read(&this_adm.copp_stat[0]), 5 * HZ);
1061 if (!ret) {
1062 pr_err("%s: timeout. waited for memory_map\n", __func__);
1063 ret = -EINVAL;
1064 goto fail_cmd;
1065 }
1066fail_cmd:
1067 kfree(mmap_region_cmd);
1068 return ret;
1069}
1070
1071int adm_memory_unmap_regions(uint32_t *buf_add, uint32_t *bufsz,
1072 uint32_t bufcnt)
1073{
1074 struct adm_cmd_memory_unmap_regions *unmap_regions = NULL;
1075 struct adm_memory_unmap_regions *mregions = NULL;
1076 void *unmap_region_cmd = NULL;
1077 void *payload = NULL;
1078 int ret = 0;
1079 int i = 0;
1080 int cmd_size = 0;
1081
Ben Rombergerb7603232011-11-23 17:16:27 -08001082 pr_debug("%s\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001083
1084 if (this_adm.apr == NULL) {
1085 pr_err("%s APR handle NULL\n", __func__);
1086 return -EINVAL;
1087 }
1088
1089 cmd_size = sizeof(struct adm_cmd_memory_unmap_regions)
1090 + sizeof(struct adm_memory_unmap_regions) * bufcnt;
1091
1092 unmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
1093 if (!unmap_region_cmd) {
1094 pr_err("%s: allocate unmap_region_cmd failed\n", __func__);
1095 return -ENOMEM;
1096 }
1097 unmap_regions = (struct adm_cmd_memory_unmap_regions *)
1098 unmap_region_cmd;
1099 unmap_regions->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1100 APR_HDR_LEN(APR_HDR_SIZE),
1101 APR_PKT_VER);
1102 unmap_regions->hdr.pkt_size = cmd_size;
1103 unmap_regions->hdr.src_port = 0;
1104 unmap_regions->hdr.dest_port = 0;
1105 unmap_regions->hdr.token = 0;
1106 unmap_regions->hdr.opcode = ADM_CMD_MEMORY_UNMAP_REGIONS;
1107 unmap_regions->nregions = bufcnt & 0x00ff;
1108 unmap_regions->reserved = 0;
1109 pr_debug("%s: unmap_regions->nregions = %d\n", __func__,
1110 unmap_regions->nregions);
1111 payload = ((u8 *) unmap_region_cmd +
1112 sizeof(struct adm_cmd_memory_unmap_regions));
1113 mregions = (struct adm_memory_unmap_regions *)payload;
1114
1115 for (i = 0; i < bufcnt; i++) {
1116 mregions->phys = buf_add[i];
1117 ++mregions;
1118 }
1119 atomic_set(&this_adm.copp_stat[0], 0);
1120 ret = apr_send_pkt(this_adm.apr, (uint32_t *) unmap_region_cmd);
1121 if (ret < 0) {
1122 pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
1123 unmap_regions->hdr.opcode, ret);
1124 ret = -EINVAL;
1125 goto fail_cmd;
1126 }
1127
1128 ret = wait_event_timeout(this_adm.wait,
1129 atomic_read(&this_adm.copp_stat[0]), 5 * HZ);
1130 if (!ret) {
1131 pr_err("%s: timeout. waited for memory_unmap\n", __func__);
1132 ret = -EINVAL;
1133 goto fail_cmd;
1134 }
1135fail_cmd:
1136 kfree(unmap_region_cmd);
1137 return ret;
1138}
1139
Ben Romberger974a40d2011-07-18 15:08:21 -07001140int adm_get_copp_id(int port_index)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001141{
1142 pr_debug("%s\n", __func__);
1143
Ben Romberger974a40d2011-07-18 15:08:21 -07001144 if (port_index < 0) {
1145 pr_err("%s: invalid port_id = %d\n", __func__, port_index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001146 return -EINVAL;
1147 }
1148
Ben Romberger974a40d2011-07-18 15:08:21 -07001149 return atomic_read(&this_adm.copp_id[port_index]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001150}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001151
Jayasena Sangaraboinaf4ab0df2012-06-06 22:38:40 -07001152void adm_ec_ref_rx_id(int port_id)
1153{
1154 this_adm.ec_ref_rx = port_id;
1155 pr_debug("%s ec_ref_rx:%d", __func__, this_adm.ec_ref_rx);
1156}
1157
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001158int adm_close(int port_id)
1159{
1160 struct apr_hdr close;
1161
1162 int ret = 0;
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301163 int index = 0;
1164
1165 port_id = afe_convert_virtual_to_portid(port_id);
1166
1167 index = afe_get_port_index(port_id);
Bharath Ramachandramurthy51a86212011-07-29 12:43:43 -07001168 if (afe_validate_port(port_id) < 0)
1169 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001170
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001171 pr_debug("%s port_id=%d index %d\n", __func__, port_id, index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001172
1173 if (!(atomic_read(&this_adm.copp_cnt[index]))) {
1174 pr_err("%s: copp count for port[%d]is 0\n", __func__, port_id);
1175
1176 goto fail_cmd;
1177 }
1178 atomic_dec(&this_adm.copp_cnt[index]);
1179 if (!(atomic_read(&this_adm.copp_cnt[index]))) {
1180
1181 close.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1182 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1183 close.pkt_size = sizeof(close);
1184 close.src_svc = APR_SVC_ADM;
1185 close.src_domain = APR_DOMAIN_APPS;
1186 close.src_port = port_id;
1187 close.dest_svc = APR_SVC_ADM;
1188 close.dest_domain = APR_DOMAIN_ADSP;
1189 close.dest_port = atomic_read(&this_adm.copp_id[index]);
1190 close.token = port_id;
1191 close.opcode = ADM_CMD_COPP_CLOSE;
1192
1193 atomic_set(&this_adm.copp_id[index], RESET_COPP_ID);
1194 atomic_set(&this_adm.copp_stat[index], 0);
1195
1196
1197 pr_debug("%s:coppid %d portid=%d index=%d coppcnt=%d\n",
1198 __func__,
1199 atomic_read(&this_adm.copp_id[index]),
1200 port_id, index,
1201 atomic_read(&this_adm.copp_cnt[index]));
1202
1203 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&close);
1204 if (ret < 0) {
1205 pr_err("%s ADM close failed\n", __func__);
1206 ret = -EINVAL;
1207 goto fail_cmd;
1208 }
1209
1210 ret = wait_event_timeout(this_adm.wait,
1211 atomic_read(&this_adm.copp_stat[index]),
1212 msecs_to_jiffies(TIMEOUT_MS));
1213 if (!ret) {
1214 pr_err("%s: ADM cmd Route failed for port %d\n",
1215 __func__, port_id);
1216 ret = -EINVAL;
1217 goto fail_cmd;
1218 }
Ben Romberger93d4d2d2011-10-19 23:04:02 -07001219
1220 rtac_remove_adm_device(port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001221 }
1222
1223fail_cmd:
1224 return ret;
1225}
1226
1227static int __init adm_init(void)
1228{
1229 int i = 0;
1230 init_waitqueue_head(&this_adm.wait);
1231 this_adm.apr = NULL;
1232
1233 for (i = 0; i < AFE_MAX_PORTS; i++) {
1234 atomic_set(&this_adm.copp_id[i], RESET_COPP_ID);
1235 atomic_set(&this_adm.copp_cnt[i], 0);
1236 atomic_set(&this_adm.copp_stat[i], 0);
1237 }
1238 return 0;
1239}
1240
1241device_initcall(adm_init);