blob: c6970f1c4ad6a5d3b90b55856bb8771fa17eae23 [file] [log] [blame]
Ben Romberger48fabc32012-01-06 17:39:39 -08001/* Copyright (c) 2010-2012, Code Aurora Forum. 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>
Ben Rombergerfce8f512011-07-18 16:46:09 -070019
20#include <mach/qdsp6v2/audio_dev_ctl.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070021#include <mach/qdsp6v2/audio_acdb.h>
Ben Rombergerfce8f512011-07-18 16:46:09 -070022#include <mach/qdsp6v2/rtac.h>
23
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070024#include <sound/apr_audio.h>
25#include <sound/q6afe.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070026
27#define TIMEOUT_MS 1000
28#define AUDIO_RX 0x0
29#define AUDIO_TX 0x1
Patrick Laicf999112011-08-23 11:27:20 -070030
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070031#define ASM_MAX_SESSION 0x8 /* To do: define in a header */
32#define RESET_COPP_ID 99
33#define INVALID_COPP_ID 0xFF
34
35struct adm_ctl {
36 void *apr;
37 atomic_t copp_id[AFE_MAX_PORTS];
38 atomic_t copp_cnt[AFE_MAX_PORTS];
39 atomic_t copp_stat[AFE_MAX_PORTS];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070040 wait_queue_head_t wait;
Jayasena Sangaraboinaf4ab0df2012-06-06 22:38:40 -070041 int ec_ref_rx;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070042};
43
Ben Romberger48fabc32012-01-06 17:39:39 -080044static struct acdb_cal_block mem_addr_audproc[MAX_AUDPROC_TYPES];
45static struct acdb_cal_block mem_addr_audvol[MAX_AUDPROC_TYPES];
46
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070047static struct adm_ctl this_adm;
48
Jayasena Sangaraboinaf4ab0df2012-06-06 22:38:40 -070049
Sriranjan Srikantam22bee8b2012-05-31 15:21:53 -070050int srs_trumedia_open(int port_id, int srs_tech_id, void *srs_params)
51{
52 struct asm_pp_params_command *open = NULL;
53 int ret = 0, sz = 0;
54 int index;
55
56 pr_debug("SRS - %s", __func__);
57 switch (srs_tech_id) {
58 case SRS_ID_GLOBAL: {
59 struct srs_trumedia_params_GLOBAL *glb_params = NULL;
60 sz = sizeof(struct asm_pp_params_command) +
61 sizeof(struct srs_trumedia_params_GLOBAL);
62 open = kzalloc(sz, GFP_KERNEL);
63 open->payload_size = sizeof(struct srs_trumedia_params_GLOBAL) +
64 sizeof(struct asm_pp_param_data_hdr);
65 open->params.param_id = SRS_TRUMEDIA_PARAMS;
66 open->params.param_size =
67 sizeof(struct srs_trumedia_params_GLOBAL);
68 glb_params = (struct srs_trumedia_params_GLOBAL *)((u8 *)open +
69 sizeof(struct asm_pp_params_command));
70 memcpy(glb_params, srs_params,
71 sizeof(struct srs_trumedia_params_GLOBAL));
72 pr_debug("SRS - %s: Global params - 1 = %x, 2 = %x, 3 = %x,"
73 " 4 = %x, 5 = %x, 6 = %x, 7 = %x, 8 = %x\n",
74 __func__, (int)glb_params->v1,
75 (int)glb_params->v2, (int)glb_params->v3,
76 (int)glb_params->v4, (int)glb_params->v5,
77 (int)glb_params->v6, (int)glb_params->v7,
78 (int)glb_params->v8);
79 break;
80 }
81 case SRS_ID_WOWHD: {
82 struct srs_trumedia_params_WOWHD *whd_params = NULL;
83 sz = sizeof(struct asm_pp_params_command) +
84 sizeof(struct srs_trumedia_params_WOWHD);
85 open = kzalloc(sz, GFP_KERNEL);
86 open->payload_size = sizeof(struct srs_trumedia_params_WOWHD) +
87 sizeof(struct asm_pp_param_data_hdr);
88 open->params.param_id = SRS_TRUMEDIA_PARAMS_WOWHD;
89 open->params.param_size =
90 sizeof(struct srs_trumedia_params_WOWHD);
91 whd_params = (struct srs_trumedia_params_WOWHD *)((u8 *)open +
92 sizeof(struct asm_pp_params_command));
93 memcpy(whd_params, srs_params,
94 sizeof(struct srs_trumedia_params_WOWHD));
95 pr_debug("SRS - %s: WOWHD params - 1 = %x, 2 = %x, 3 = %x,"
96 " 4 = %x, 5 = %x, 6 = %x, 7 = %x, 8 = %x, 9 = %x,"
97 " 10 = %x, 11 = %x\n", __func__, (int)whd_params->v1,
98 (int)whd_params->v2, (int)whd_params->v3,
99 (int)whd_params->v4, (int)whd_params->v5,
100 (int)whd_params->v6, (int)whd_params->v7,
101 (int)whd_params->v8, (int)whd_params->v9,
102 (int)whd_params->v10, (int)whd_params->v11);
103 break;
104 }
105 case SRS_ID_CSHP: {
106 struct srs_trumedia_params_CSHP *chp_params = NULL;
107 sz = sizeof(struct asm_pp_params_command) +
108 sizeof(struct srs_trumedia_params_CSHP);
109 open = kzalloc(sz, GFP_KERNEL);
110 open->payload_size = sizeof(struct srs_trumedia_params_CSHP) +
111 sizeof(struct asm_pp_param_data_hdr);
112 open->params.param_id = SRS_TRUMEDIA_PARAMS_CSHP;
113 open->params.param_size =
114 sizeof(struct srs_trumedia_params_CSHP);
115 chp_params = (struct srs_trumedia_params_CSHP *)((u8 *)open +
116 sizeof(struct asm_pp_params_command));
117 memcpy(chp_params, srs_params,
118 sizeof(struct srs_trumedia_params_CSHP));
119 pr_debug("SRS - %s: CSHP params - 1 = %x, 2 = %x, 3 = %x,"
120 " 4 = %x, 5 = %x, 6 = %x, 7 = %x, 8 = %x,"
121 " 9 = %x\n", __func__, (int)chp_params->v1,
122 (int)chp_params->v2, (int)chp_params->v3,
123 (int)chp_params->v4, (int)chp_params->v5,
124 (int)chp_params->v6, (int)chp_params->v7,
125 (int)chp_params->v8, (int)chp_params->v9);
126 break;
127 }
128 case SRS_ID_HPF: {
129 struct srs_trumedia_params_HPF *hpf_params = NULL;
130 sz = sizeof(struct asm_pp_params_command) +
131 sizeof(struct srs_trumedia_params_HPF);
132 open = kzalloc(sz, GFP_KERNEL);
133 open->payload_size = sizeof(struct srs_trumedia_params_HPF) +
134 sizeof(struct asm_pp_param_data_hdr);
135 open->params.param_id = SRS_TRUMEDIA_PARAMS_HPF;
136 open->params.param_size =
137 sizeof(struct srs_trumedia_params_HPF);
138 hpf_params = (struct srs_trumedia_params_HPF *)((u8 *)open +
139 sizeof(struct asm_pp_params_command));
140 memcpy(hpf_params, srs_params,
141 sizeof(struct srs_trumedia_params_HPF));
142 pr_debug("SRS - %s: HPF params - 1 = %x\n", __func__,
143 (int)hpf_params->v1);
144 break;
145 }
146 case SRS_ID_PEQ: {
147 struct srs_trumedia_params_PEQ *peq_params = NULL;
148 sz = sizeof(struct asm_pp_params_command) +
149 sizeof(struct srs_trumedia_params_PEQ);
150 open = kzalloc(sz, GFP_KERNEL);
151 open->payload_size = sizeof(struct srs_trumedia_params_PEQ) +
152 sizeof(struct asm_pp_param_data_hdr);
153 open->params.param_id = SRS_TRUMEDIA_PARAMS_PEQ;
154 open->params.param_size =
155 sizeof(struct srs_trumedia_params_PEQ);
156 peq_params = (struct srs_trumedia_params_PEQ *)((u8 *)open +
157 sizeof(struct asm_pp_params_command));
158 memcpy(peq_params, srs_params,
159 sizeof(struct srs_trumedia_params_PEQ));
160 pr_debug("SRS - %s: PEQ params - 1 = %x 2 = %x, 3 = %x,"
161 " 4 = %x\n", __func__, (int)peq_params->v1,
162 (int)peq_params->v2, (int)peq_params->v3,
163 (int)peq_params->v4);
164 break;
165 }
166 case SRS_ID_HL: {
167 struct srs_trumedia_params_HL *hl_params = NULL;
168 sz = sizeof(struct asm_pp_params_command) +
169 sizeof(struct srs_trumedia_params_HL);
170 open = kzalloc(sz, GFP_KERNEL);
171 open->payload_size = sizeof(struct srs_trumedia_params_HL) +
172 sizeof(struct asm_pp_param_data_hdr);
173 open->params.param_id = SRS_TRUMEDIA_PARAMS_HL;
174 open->params.param_size = sizeof(struct srs_trumedia_params_HL);
175 hl_params = (struct srs_trumedia_params_HL *)((u8 *)open +
176 sizeof(struct asm_pp_params_command));
177 memcpy(hl_params, srs_params,
178 sizeof(struct srs_trumedia_params_HL));
179 pr_debug("SRS - %s: HL params - 1 = %x, 2 = %x, 3 = %x, 4 = %x,"
180 " 5 = %x, 6 = %x, 7 = %x\n", __func__,
181 (int)hl_params->v1, (int)hl_params->v2,
182 (int)hl_params->v3, (int)hl_params->v4,
183 (int)hl_params->v5, (int)hl_params->v6,
184 (int)hl_params->v7);
185 break;
186 }
187 default:
188 goto fail_cmd;
189 }
190
191 open->payload = NULL;
192 open->params.module_id = SRS_TRUMEDIA_MODULE_ID;
193 open->params.reserved = 0;
194 open->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
195 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
196 open->hdr.pkt_size = sz;
197 open->hdr.src_svc = APR_SVC_ADM;
198 open->hdr.src_domain = APR_DOMAIN_APPS;
199 open->hdr.src_port = port_id;
200 open->hdr.dest_svc = APR_SVC_ADM;
201 open->hdr.dest_domain = APR_DOMAIN_ADSP;
202 index = afe_get_port_index(port_id);
203 open->hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
204 open->hdr.token = port_id;
205 open->hdr.opcode = ADM_CMD_SET_PARAMS;
206 pr_debug("SRS - %s: Command was sent now check Q6 - port id = %d,"
207 " size %d, module id %x, param id %x.\n", __func__,
208 open->hdr.dest_port, open->payload_size,
209 open->params.module_id, open->params.param_id);
210
211 ret = apr_send_pkt(this_adm.apr, (uint32_t *)open);
212 if (ret < 0) {
213 pr_err("SRS - %s: ADM enable for port %d failed\n", __func__,
214 port_id);
215 ret = -EINVAL;
216 goto fail_cmd;
217 }
218 /* Wait for the callback with copp id */
219 ret = wait_event_timeout(this_adm.wait, 1,
220 msecs_to_jiffies(TIMEOUT_MS));
221 if (!ret) {
222 pr_err("SRS - %s: ADM open failed for port %d\n", __func__,
223 port_id);
224 ret = -EINVAL;
225 goto fail_cmd;
226 }
227
228fail_cmd:
229 kfree(open);
230 return ret;
231}
232
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700233static int32_t adm_callback(struct apr_client_data *data, void *priv)
234{
235 uint32_t *payload;
236 int i, index;
237 payload = data->payload;
238
239 if (data->opcode == RESET_EVENTS) {
240 pr_debug("adm_callback: Reset event is received: %d %d apr[%p]\n",
241 data->reset_event, data->reset_proc,
242 this_adm.apr);
243 if (this_adm.apr) {
244 apr_reset(this_adm.apr);
245 for (i = 0; i < AFE_MAX_PORTS; i++) {
246 atomic_set(&this_adm.copp_id[i],
247 RESET_COPP_ID);
248 atomic_set(&this_adm.copp_cnt[i], 0);
249 atomic_set(&this_adm.copp_stat[i], 0);
250 }
251 this_adm.apr = NULL;
252 }
Deepa Madiregama4c054d22012-08-23 15:05:29 +0530253 pr_debug("Resetting calibration blocks");
254 for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
255 /* Device calibration */
256 mem_addr_audproc[i].cal_size = 0;
257 mem_addr_audproc[i].cal_kvaddr = 0;
258 mem_addr_audproc[i].cal_paddr = 0;
259
260 /* Volume calibration */
261 mem_addr_audvol[i].cal_size = 0;
262 mem_addr_audvol[i].cal_kvaddr = 0;
263 mem_addr_audvol[i].cal_paddr = 0;
264 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700265 return 0;
266 }
267
268 pr_debug("%s: code = 0x%x %x %x size = %d\n", __func__,
269 data->opcode, payload[0], payload[1],
270 data->payload_size);
271
272 if (data->payload_size) {
273 index = afe_get_port_index(data->token);
274 pr_debug("%s: Port ID %d, index %d\n", __func__,
275 data->token, index);
Bharath Ramachandramurthy94ad7e22012-02-28 18:44:07 -0800276 if (index < 0 || index >= AFE_MAX_PORTS) {
277 pr_err("%s: invalid port idx %d token %d\n",
278 __func__, index, data->token);
279 return 0;
280 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700281 if (data->opcode == APR_BASIC_RSP_RESULT) {
Santosh Mardi23321202012-03-22 04:33:25 +0530282 pr_debug("APR_BASIC_RSP_RESULT id %x\n", payload[0]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700283 switch (payload[0]) {
284 case ADM_CMD_SET_PARAMS:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700285 if (rtac_make_adm_callback(payload,
286 data->payload_size))
287 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700288 case ADM_CMD_COPP_CLOSE:
289 case ADM_CMD_MEMORY_MAP:
290 case ADM_CMD_MEMORY_UNMAP:
291 case ADM_CMD_MEMORY_MAP_REGIONS:
292 case ADM_CMD_MEMORY_UNMAP_REGIONS:
293 case ADM_CMD_MATRIX_MAP_ROUTINGS:
Santosh Mardi23321202012-03-22 04:33:25 +0530294 case ADM_CMD_CONNECT_AFE_PORT:
Santosh Mardid1760792012-06-12 16:23:19 +0530295 case ADM_CMD_DISCONNECT_AFE_PORT:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700296 atomic_set(&this_adm.copp_stat[index], 1);
297 wake_up(&this_adm.wait);
298 break;
299 default:
300 pr_err("%s: Unknown Cmd: 0x%x\n", __func__,
301 payload[0]);
302 break;
303 }
304 return 0;
305 }
306
307 switch (data->opcode) {
Kiran Kandi5e809b02012-01-31 00:24:33 -0800308 case ADM_CMDRSP_COPP_OPEN:
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -0700309 case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN:
310 case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN_V3: {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700311 struct adm_copp_open_respond *open = data->payload;
312 if (open->copp_id == INVALID_COPP_ID) {
313 pr_err("%s: invalid coppid rxed %d\n",
314 __func__, open->copp_id);
315 atomic_set(&this_adm.copp_stat[index], 1);
316 wake_up(&this_adm.wait);
317 break;
318 }
319 atomic_set(&this_adm.copp_id[index], open->copp_id);
320 atomic_set(&this_adm.copp_stat[index], 1);
321 pr_debug("%s: coppid rxed=%d\n", __func__,
322 open->copp_id);
323 wake_up(&this_adm.wait);
324 }
325 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700326 case ADM_CMDRSP_GET_PARAMS:
Swaminathan Sathappan88163a72011-08-01 16:01:14 -0700327 pr_debug("%s: ADM_CMDRSP_GET_PARAMS\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700328 rtac_make_adm_callback(payload,
329 data->payload_size);
330 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700331 default:
332 pr_err("%s: Unknown cmd:0x%x\n", __func__,
333 data->opcode);
334 break;
335 }
336 }
337 return 0;
338}
339
Ben Romberger48fabc32012-01-06 17:39:39 -0800340static int send_adm_cal_block(int port_id, struct acdb_cal_block *aud_cal)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700341{
Ben Rombergerdcab5472011-12-08 19:20:12 -0800342 s32 result = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700343 struct adm_set_params_command adm_params;
344 int index = afe_get_port_index(port_id);
Ben Romberger09dc65f2012-03-22 20:06:55 -0700345 if (index < 0 || index >= AFE_MAX_PORTS) {
346 pr_err("%s: invalid port idx %d portid %d\n",
347 __func__, index, port_id);
Mingming Yinc09967e2012-04-27 15:09:43 -0700348 return 0;
Ben Romberger09dc65f2012-03-22 20:06:55 -0700349 }
Mingming Yinc09967e2012-04-27 15:09:43 -0700350
351 pr_debug("%s: Port id %d, index %d\n", __func__, port_id, index);
352
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700353 if (!aud_cal || aud_cal->cal_size == 0) {
Ben Rombergerdcab5472011-12-08 19:20:12 -0800354 pr_debug("%s: No ADM cal to send for port_id = %d!\n",
355 __func__, port_id);
356 result = -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700357 goto done;
358 }
359
360 adm_params.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
361 APR_HDR_LEN(20), APR_PKT_VER);
362 adm_params.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
363 sizeof(adm_params));
364 adm_params.hdr.src_svc = APR_SVC_ADM;
365 adm_params.hdr.src_domain = APR_DOMAIN_APPS;
366 adm_params.hdr.src_port = port_id;
367 adm_params.hdr.dest_svc = APR_SVC_ADM;
368 adm_params.hdr.dest_domain = APR_DOMAIN_ADSP;
369 adm_params.hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
370 adm_params.hdr.token = port_id;
371 adm_params.hdr.opcode = ADM_CMD_SET_PARAMS;
372 adm_params.payload = aud_cal->cal_paddr;
373 adm_params.payload_size = aud_cal->cal_size;
374
375 atomic_set(&this_adm.copp_stat[index], 0);
376 pr_debug("%s: Sending SET_PARAMS payload = 0x%x, size = %d\n",
377 __func__, adm_params.payload, adm_params.payload_size);
378 result = apr_send_pkt(this_adm.apr, (uint32_t *)&adm_params);
379 if (result < 0) {
380 pr_err("%s: Set params failed port = %d payload = 0x%x\n",
381 __func__, port_id, aud_cal->cal_paddr);
Ben Rombergerdcab5472011-12-08 19:20:12 -0800382 result = -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700383 goto done;
384 }
385 /* Wait for the callback */
386 result = wait_event_timeout(this_adm.wait,
387 atomic_read(&this_adm.copp_stat[index]),
388 msecs_to_jiffies(TIMEOUT_MS));
Ben Rombergerdcab5472011-12-08 19:20:12 -0800389 if (!result) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700390 pr_err("%s: Set params timed out port = %d, payload = 0x%x\n",
391 __func__, port_id, aud_cal->cal_paddr);
Ben Rombergerdcab5472011-12-08 19:20:12 -0800392 result = -EINVAL;
393 goto done;
394 }
395
396 result = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700397done:
Ben Rombergerdcab5472011-12-08 19:20:12 -0800398 return result;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700399}
400
Ben Romberger48fabc32012-01-06 17:39:39 -0800401static void send_adm_cal(int port_id, int path)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700402{
Ben Romberger48fabc32012-01-06 17:39:39 -0800403 int result = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700404 s32 acdb_path;
405 struct acdb_cal_block aud_cal;
406
407 pr_debug("%s\n", __func__);
408
409 /* Maps audio_dev_ctrl path definition to ACDB definition */
410 acdb_path = path - 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700411
412 pr_debug("%s: Sending audproc cal\n", __func__);
413 get_audproc_cal(acdb_path, &aud_cal);
Ben Romberger48fabc32012-01-06 17:39:39 -0800414
415 /* map & cache buffers used */
Ben Romberger9e792562012-02-24 12:29:01 -0800416 if (((mem_addr_audproc[acdb_path].cal_paddr != aud_cal.cal_paddr) &&
417 (aud_cal.cal_size > 0)) ||
418 (aud_cal.cal_size > mem_addr_audproc[acdb_path].cal_size)) {
419
Ben Romberger48fabc32012-01-06 17:39:39 -0800420 if (mem_addr_audproc[acdb_path].cal_paddr != 0)
421 adm_memory_unmap_regions(
422 &mem_addr_audproc[acdb_path].cal_paddr,
423 &mem_addr_audproc[acdb_path].cal_size, 1);
424
425 result = adm_memory_map_regions(&aud_cal.cal_paddr, 0,
426 &aud_cal.cal_size, 1);
427 if (result < 0)
428 pr_err("ADM audproc mmap did not work! path = %d, "
429 "addr = 0x%x, size = %d\n", acdb_path,
430 aud_cal.cal_paddr, aud_cal.cal_size);
431 else
432 mem_addr_audproc[acdb_path] = aud_cal;
433 }
434
Ben Rombergerdcab5472011-12-08 19:20:12 -0800435 if (!send_adm_cal_block(port_id, &aud_cal))
Ben Romberger48fabc32012-01-06 17:39:39 -0800436 pr_debug("%s: Audproc cal sent for port id: %d, path %d\n",
Ben Rombergerdcab5472011-12-08 19:20:12 -0800437 __func__, port_id, acdb_path);
438 else
Ben Romberger48fabc32012-01-06 17:39:39 -0800439 pr_debug("%s: Audproc cal not sent for port id: %d, path %d\n",
Ben Rombergerdcab5472011-12-08 19:20:12 -0800440 __func__, port_id, acdb_path);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700441
442 pr_debug("%s: Sending audvol cal\n", __func__);
443 get_audvol_cal(acdb_path, &aud_cal);
Ben Romberger48fabc32012-01-06 17:39:39 -0800444
445 /* map & cache buffers used */
Ben Romberger9e792562012-02-24 12:29:01 -0800446 if (((mem_addr_audvol[acdb_path].cal_paddr != aud_cal.cal_paddr) &&
447 (aud_cal.cal_size > 0)) ||
448 (aud_cal.cal_size > mem_addr_audvol[acdb_path].cal_size)) {
Ben Romberger48fabc32012-01-06 17:39:39 -0800449 if (mem_addr_audvol[acdb_path].cal_paddr != 0)
450 adm_memory_unmap_regions(
451 &mem_addr_audvol[acdb_path].cal_paddr,
452 &mem_addr_audvol[acdb_path].cal_size, 1);
453
454 result = adm_memory_map_regions(&aud_cal.cal_paddr, 0,
455 &aud_cal.cal_size, 1);
456 if (result < 0)
457 pr_err("ADM audvol mmap did not work! path = %d, "
458 "addr = 0x%x, size = %d\n", acdb_path,
459 aud_cal.cal_paddr, aud_cal.cal_size);
460 else
461 mem_addr_audvol[acdb_path] = aud_cal;
462 }
463
Ben Rombergerdcab5472011-12-08 19:20:12 -0800464 if (!send_adm_cal_block(port_id, &aud_cal))
Ben Romberger48fabc32012-01-06 17:39:39 -0800465 pr_debug("%s: Audvol cal sent for port id: %d, path %d\n",
Ben Rombergerdcab5472011-12-08 19:20:12 -0800466 __func__, port_id, acdb_path);
467 else
Ben Romberger48fabc32012-01-06 17:39:39 -0800468 pr_debug("%s: Audvol cal not sent for port id: %d, path %d\n",
Ben Rombergerdcab5472011-12-08 19:20:12 -0800469 __func__, port_id, acdb_path);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700470}
471
Santosh Mardi23321202012-03-22 04:33:25 +0530472int adm_connect_afe_port(int mode, int session_id, int port_id)
473{
474 struct adm_cmd_connect_afe_port cmd;
475 int ret = 0;
476 int index;
477
478 pr_debug("%s: port %d session id:%d mode:%d\n", __func__,
479 port_id, session_id, mode);
480
481 port_id = afe_convert_virtual_to_portid(port_id);
482
483 if (afe_validate_port(port_id) < 0) {
484 pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
485 return -ENODEV;
486 }
487 if (this_adm.apr == NULL) {
488 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
489 0xFFFFFFFF, &this_adm);
490 if (this_adm.apr == NULL) {
491 pr_err("%s: Unable to register ADM\n", __func__);
492 ret = -ENODEV;
493 return ret;
494 }
495 rtac_set_adm_handle(this_adm.apr);
496 }
497 index = afe_get_port_index(port_id);
498 pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
499
500 cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
501 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
502 cmd.hdr.pkt_size = sizeof(cmd);
503 cmd.hdr.src_svc = APR_SVC_ADM;
504 cmd.hdr.src_domain = APR_DOMAIN_APPS;
505 cmd.hdr.src_port = port_id;
506 cmd.hdr.dest_svc = APR_SVC_ADM;
507 cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
508 cmd.hdr.dest_port = port_id;
509 cmd.hdr.token = port_id;
510 cmd.hdr.opcode = ADM_CMD_CONNECT_AFE_PORT;
511
512 cmd.mode = mode;
513 cmd.session_id = session_id;
514 cmd.afe_port_id = port_id;
515
516 atomic_set(&this_adm.copp_stat[index], 0);
517 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd);
518 if (ret < 0) {
519 pr_err("%s:ADM enable for port %d failed\n",
520 __func__, port_id);
521 ret = -EINVAL;
522 goto fail_cmd;
523 }
524 /* Wait for the callback with copp id */
525 ret = wait_event_timeout(this_adm.wait,
526 atomic_read(&this_adm.copp_stat[index]),
527 msecs_to_jiffies(TIMEOUT_MS));
528 if (!ret) {
529 pr_err("%s ADM connect AFE failed for port %d\n", __func__,
530 port_id);
531 ret = -EINVAL;
532 goto fail_cmd;
533 }
534 atomic_inc(&this_adm.copp_cnt[index]);
535 return 0;
536
537fail_cmd:
538
539 return ret;
540}
541
Santosh Mardid1760792012-06-12 16:23:19 +0530542int adm_disconnect_afe_port(int mode, int session_id, int port_id)
543{
544 struct adm_cmd_connect_afe_port cmd;
545 int ret = 0;
546 int index;
547
548 pr_debug("%s: port %d session id:%d mode:%d\n", __func__,
549 port_id, session_id, mode);
550
551 port_id = afe_convert_virtual_to_portid(port_id);
552
553 if (afe_validate_port(port_id) < 0) {
554 pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
555 return -ENODEV;
556 }
557 if (this_adm.apr == NULL) {
558 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
559 0xFFFFFFFF, &this_adm);
560 if (this_adm.apr == NULL) {
561 pr_err("%s: Unable to register ADM\n", __func__);
562 ret = -ENODEV;
563 return ret;
564 }
565 rtac_set_adm_handle(this_adm.apr);
566 }
567 index = afe_get_port_index(port_id);
568 pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
569
570 cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
571 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
572 cmd.hdr.pkt_size = sizeof(cmd);
573 cmd.hdr.src_svc = APR_SVC_ADM;
574 cmd.hdr.src_domain = APR_DOMAIN_APPS;
575 cmd.hdr.src_port = port_id;
576 cmd.hdr.dest_svc = APR_SVC_ADM;
577 cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
578 cmd.hdr.dest_port = port_id;
579 cmd.hdr.token = port_id;
580 cmd.hdr.opcode = ADM_CMD_DISCONNECT_AFE_PORT;
581
582 cmd.mode = mode;
583 cmd.session_id = session_id;
584 cmd.afe_port_id = port_id;
585
586 atomic_set(&this_adm.copp_stat[index], 0);
587 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd);
588 if (ret < 0) {
589 pr_err("%s:ADM enable for port %d failed\n",
590 __func__, port_id);
591 ret = -EINVAL;
592 goto fail_cmd;
593 }
594 /* Wait for the callback with copp id */
595 ret = wait_event_timeout(this_adm.wait,
596 atomic_read(&this_adm.copp_stat[index]),
597 msecs_to_jiffies(TIMEOUT_MS));
598 if (!ret) {
599 pr_err("%s ADM connect AFE failed for port %d\n", __func__,
600 port_id);
601 ret = -EINVAL;
602 goto fail_cmd;
603 }
604 atomic_dec(&this_adm.copp_cnt[index]);
605 return 0;
606
607fail_cmd:
608
609 return ret;
610}
611
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700612int adm_open(int port_id, int path, int rate, int channel_mode, int topology)
613{
614 struct adm_copp_open_command open;
615 int ret = 0;
616 int index;
617
618 pr_debug("%s: port %d path:%d rate:%d mode:%d\n", __func__,
619 port_id, path, rate, channel_mode);
620
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530621 port_id = afe_convert_virtual_to_portid(port_id);
622
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700623 if (afe_validate_port(port_id) < 0) {
624 pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
625 return -ENODEV;
626 }
627
628 index = afe_get_port_index(port_id);
629 pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
630
631 if (this_adm.apr == NULL) {
632 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
633 0xFFFFFFFF, &this_adm);
634 if (this_adm.apr == NULL) {
635 pr_err("%s: Unable to register ADM\n", __func__);
636 ret = -ENODEV;
637 return ret;
638 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700639 rtac_set_adm_handle(this_adm.apr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700640 }
641
642
643 /* Create a COPP if port id are not enabled */
644 if (atomic_read(&this_adm.copp_cnt[index]) == 0) {
645
646 open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
647 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
648 open.hdr.pkt_size = sizeof(open);
649 open.hdr.src_svc = APR_SVC_ADM;
650 open.hdr.src_domain = APR_DOMAIN_APPS;
651 open.hdr.src_port = port_id;
652 open.hdr.dest_svc = APR_SVC_ADM;
653 open.hdr.dest_domain = APR_DOMAIN_ADSP;
654 open.hdr.dest_port = port_id;
655 open.hdr.token = port_id;
656 open.hdr.opcode = ADM_CMD_COPP_OPEN;
657
658 open.mode = path;
659 open.endpoint_id1 = port_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700660
Jayasena Sangaraboinaf4ab0df2012-06-06 22:38:40 -0700661 if (this_adm.ec_ref_rx == 0) {
662 open.endpoint_id2 = 0xFFFF;
663 } else if (this_adm.ec_ref_rx && (path != 1)) {
664 open.endpoint_id2 = this_adm.ec_ref_rx;
665 this_adm.ec_ref_rx = 0;
666 }
667
668 pr_debug("%s open.endpoint_id1:%d open.endpoint_id2:%d",
669 __func__, open.endpoint_id1, open.endpoint_id2);
Ben Rombergerc49b85d2011-07-15 18:55:34 -0700670 /* convert path to acdb path */
Ben Romberger974a40d2011-07-18 15:08:21 -0700671 if (path == ADM_PATH_PLAYBACK)
Ben Rombergerc49b85d2011-07-15 18:55:34 -0700672 open.topology_id = get_adm_rx_topology();
Jay Wang4fa2ee42011-07-18 00:21:22 -0700673 else {
Ben Rombergerc49b85d2011-07-15 18:55:34 -0700674 open.topology_id = get_adm_tx_topology();
Jay Wang4fa2ee42011-07-18 00:21:22 -0700675 if ((open.topology_id ==
676 VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
677 (open.topology_id ==
Jay Wang17283132012-03-30 15:18:12 -0700678 VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
Jay Wang4fa2ee42011-07-18 00:21:22 -0700679 rate = 16000;
680 }
Ben Rombergerc49b85d2011-07-15 18:55:34 -0700681
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700682 if (open.topology_id == 0)
683 open.topology_id = topology;
684
685 open.channel_config = channel_mode & 0x00FF;
686 open.rate = rate;
687
Bharath Ramachandramurthy94ad7e22012-02-28 18:44:07 -0800688 pr_debug("%s: channel_config=%d port_id=%d rate=%d"
689 "topology_id=0x%X\n", __func__, open.channel_config,\
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700690 open.endpoint_id1, open.rate,\
691 open.topology_id);
692
693 atomic_set(&this_adm.copp_stat[index], 0);
694
695 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
696 if (ret < 0) {
697 pr_err("%s:ADM enable for port %d failed\n",
698 __func__, port_id);
699 ret = -EINVAL;
700 goto fail_cmd;
701 }
702 /* Wait for the callback with copp id */
703 ret = wait_event_timeout(this_adm.wait,
704 atomic_read(&this_adm.copp_stat[index]),
705 msecs_to_jiffies(TIMEOUT_MS));
706 if (!ret) {
707 pr_err("%s ADM open failed for port %d\n", __func__,
708 port_id);
709 ret = -EINVAL;
710 goto fail_cmd;
711 }
712 }
713 atomic_inc(&this_adm.copp_cnt[index]);
714 return 0;
715
716fail_cmd:
717
718 return ret;
719}
720
Kiran Kandi5e809b02012-01-31 00:24:33 -0800721
722int adm_multi_ch_copp_open(int port_id, int path, int rate, int channel_mode,
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -0700723 int topology, int perfmode)
Kiran Kandi5e809b02012-01-31 00:24:33 -0800724{
725 struct adm_multi_ch_copp_open_command open;
726 int ret = 0;
727 int index;
728
729 pr_debug("%s: port %d path:%d rate:%d channel :%d\n", __func__,
730 port_id, path, rate, channel_mode);
731
732 port_id = afe_convert_virtual_to_portid(port_id);
733
734 if (afe_validate_port(port_id) < 0) {
735 pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
736 return -ENODEV;
737 }
738
739 index = afe_get_port_index(port_id);
740 pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
741
742 if (this_adm.apr == NULL) {
743 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
744 0xFFFFFFFF, &this_adm);
745 if (this_adm.apr == NULL) {
746 pr_err("%s: Unable to register ADM\n", __func__);
747 ret = -ENODEV;
748 return ret;
749 }
750 rtac_set_adm_handle(this_adm.apr);
751 }
752
753 /* Create a COPP if port id are not enabled */
754 if (atomic_read(&this_adm.copp_cnt[index]) == 0) {
755
756 open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
757 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
758
759 open.hdr.pkt_size =
760 sizeof(struct adm_multi_ch_copp_open_command);
Jayasena Sangaraboina99bf09c2012-07-17 12:03:08 -0700761
762 if (perfmode) {
763 pr_debug("%s Performance mode", __func__);
764 open.hdr.opcode = ADM_CMD_MULTI_CHANNEL_COPP_OPEN_V3;
765 open.flags = ADM_MULTI_CH_COPP_OPEN_PERF_MODE_BIT;
766 open.reserved = PCM_BITS_PER_SAMPLE;
767 } else {
768 open.hdr.opcode = ADM_CMD_MULTI_CHANNEL_COPP_OPEN;
769 open.reserved = 0;
770 }
771
Kiran Kandi5e809b02012-01-31 00:24:33 -0800772 memset(open.dev_channel_mapping, 0, 8);
773
774 if (channel_mode == 1) {
775 open.dev_channel_mapping[0] = PCM_CHANNEL_FC;
776 } else if (channel_mode == 2) {
777 open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
778 open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
Mingming Yin647e9ea2012-03-17 19:56:10 -0700779 } else if (channel_mode == 4) {
780 open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
781 open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
782 open.dev_channel_mapping[2] = PCM_CHANNEL_RB;
783 open.dev_channel_mapping[3] = PCM_CHANNEL_LB;
Kiran Kandi5e809b02012-01-31 00:24:33 -0800784 } else if (channel_mode == 6) {
785 open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
786 open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
787 open.dev_channel_mapping[2] = PCM_CHANNEL_LFE;
788 open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
789 open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
790 open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
Subhash Chandra Bose Naripeddy8477d222012-06-12 00:30:54 -0700791 } else if (channel_mode == 8) {
792 open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
793 open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
794 open.dev_channel_mapping[2] = PCM_CHANNEL_LFE;
795 open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
796 open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
797 open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
798 open.dev_channel_mapping[6] = PCM_CHANNEL_FLC;
799 open.dev_channel_mapping[7] = PCM_CHANNEL_FRC;
Kiran Kandi5e809b02012-01-31 00:24:33 -0800800 } else {
801 pr_err("%s invalid num_chan %d\n", __func__,
802 channel_mode);
803 return -EINVAL;
804 }
Kiran Kandi5e809b02012-01-31 00:24:33 -0800805 open.hdr.src_svc = APR_SVC_ADM;
806 open.hdr.src_domain = APR_DOMAIN_APPS;
807 open.hdr.src_port = port_id;
808 open.hdr.dest_svc = APR_SVC_ADM;
809 open.hdr.dest_domain = APR_DOMAIN_ADSP;
810 open.hdr.dest_port = port_id;
811 open.hdr.token = port_id;
812
813 open.mode = path;
814 open.endpoint_id1 = port_id;
Kiran Kandi5e809b02012-01-31 00:24:33 -0800815
Jayasena Sangaraboinaf4ab0df2012-06-06 22:38:40 -0700816 if (this_adm.ec_ref_rx == 0) {
817 open.endpoint_id2 = 0xFFFF;
818 } else if (this_adm.ec_ref_rx && (path != 1)) {
819 open.endpoint_id2 = this_adm.ec_ref_rx;
820 this_adm.ec_ref_rx = 0;
821 }
822
823 pr_debug("%s open.endpoint_id1:%d open.endpoint_id2:%d",
824 __func__, open.endpoint_id1, open.endpoint_id2);
Kiran Kandi5e809b02012-01-31 00:24:33 -0800825 /* convert path to acdb path */
826 if (path == ADM_PATH_PLAYBACK)
827 open.topology_id = get_adm_rx_topology();
828 else {
829 open.topology_id = get_adm_tx_topology();
830 if ((open.topology_id ==
831 VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
832 (open.topology_id ==
Jay Wang0124d872012-05-23 14:10:36 -0700833 VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
Kiran Kandi5e809b02012-01-31 00:24:33 -0800834 rate = 16000;
835 }
836
837 if (open.topology_id == 0)
838 open.topology_id = topology;
839
840 open.channel_config = channel_mode & 0x00FF;
841 open.rate = rate;
842
843 pr_debug("%s: channel_config=%d port_id=%d rate=%d"
844 " topology_id=0x%X\n", __func__, open.channel_config,
845 open.endpoint_id1, open.rate,
846 open.topology_id);
847
848 atomic_set(&this_adm.copp_stat[index], 0);
849
850 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
851 if (ret < 0) {
852 pr_err("%s:ADM enable for port %d failed\n",
853 __func__, port_id);
854 ret = -EINVAL;
855 goto fail_cmd;
856 }
857 /* Wait for the callback with copp id */
858 ret = wait_event_timeout(this_adm.wait,
859 atomic_read(&this_adm.copp_stat[index]),
860 msecs_to_jiffies(TIMEOUT_MS));
861 if (!ret) {
862 pr_err("%s ADM open failed for port %d\n", __func__,
863 port_id);
864 ret = -EINVAL;
865 goto fail_cmd;
866 }
867 }
868 atomic_inc(&this_adm.copp_cnt[index]);
869 return 0;
870
871fail_cmd:
872
873 return ret;
874}
875
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700876int adm_matrix_map(int session_id, int path, int num_copps,
877 unsigned int *port_id, int copp_id)
878{
879 struct adm_routings_command route;
880 int ret = 0, i = 0;
881 /* Assumes port_ids have already been validated during adm_open */
882 int index = afe_get_port_index(copp_id);
Mingming Yinc09967e2012-04-27 15:09:43 -0700883 if (index < 0 || index >= AFE_MAX_PORTS) {
884 pr_err("%s: invalid port idx %d token %d\n",
885 __func__, index, copp_id);
886 return 0;
887 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700888
889 pr_debug("%s: session 0x%x path:%d num_copps:%d port_id[0]:%d\n",
890 __func__, session_id, path, num_copps, port_id[0]);
891
892 route.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
893 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
894 route.hdr.pkt_size = sizeof(route);
895 route.hdr.src_svc = 0;
896 route.hdr.src_domain = APR_DOMAIN_APPS;
897 route.hdr.src_port = copp_id;
898 route.hdr.dest_svc = APR_SVC_ADM;
899 route.hdr.dest_domain = APR_DOMAIN_ADSP;
900 route.hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
901 route.hdr.token = copp_id;
902 route.hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS;
903 route.num_sessions = 1;
904 route.session[0].id = session_id;
905 route.session[0].num_copps = num_copps;
906
907 for (i = 0; i < num_copps; i++) {
908 int tmp;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530909 port_id[i] = afe_convert_virtual_to_portid(port_id[i]);
910
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700911 tmp = afe_get_port_index(port_id[i]);
912
913 pr_debug("%s: port_id[%d]: %d, index: %d\n", __func__, i,
914 port_id[i], tmp);
915
Mingming Yinc09967e2012-04-27 15:09:43 -0700916 if (tmp >= 0 && tmp < AFE_MAX_PORTS)
Bharath Ramachandramurthy94ad7e22012-02-28 18:44:07 -0800917 route.session[0].copp_id[i] =
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700918 atomic_read(&this_adm.copp_id[tmp]);
919 }
920 if (num_copps % 2)
921 route.session[0].copp_id[i] = 0;
922
923 switch (path) {
924 case 0x1:
925 route.path = AUDIO_RX;
926 break;
927 case 0x2:
928 case 0x3:
929 route.path = AUDIO_TX;
930 break;
931 default:
932 pr_err("%s: Wrong path set[%d]\n", __func__, path);
933 break;
934 }
935 atomic_set(&this_adm.copp_stat[index], 0);
936
937 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&route);
938 if (ret < 0) {
939 pr_err("%s: ADM routing for port %d failed\n",
940 __func__, port_id[0]);
941 ret = -EINVAL;
942 goto fail_cmd;
943 }
944 ret = wait_event_timeout(this_adm.wait,
945 atomic_read(&this_adm.copp_stat[index]),
946 msecs_to_jiffies(TIMEOUT_MS));
947 if (!ret) {
948 pr_err("%s: ADM cmd Route failed for port %d\n",
949 __func__, port_id[0]);
950 ret = -EINVAL;
951 goto fail_cmd;
952 }
953
954 for (i = 0; i < num_copps; i++)
955 send_adm_cal(port_id[i], path);
956
Ben Romberger974a40d2011-07-18 15:08:21 -0700957 for (i = 0; i < num_copps; i++)
958 rtac_add_adm_device(port_id[i], atomic_read(&this_adm.copp_id
959 [afe_get_port_index(port_id[i])]),
960 path, session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700961 return 0;
962
963fail_cmd:
964
965 return ret;
966}
967
968int adm_memory_map_regions(uint32_t *buf_add, uint32_t mempool_id,
969 uint32_t *bufsz, uint32_t bufcnt)
970{
971 struct adm_cmd_memory_map_regions *mmap_regions = NULL;
972 struct adm_memory_map_regions *mregions = NULL;
973 void *mmap_region_cmd = NULL;
974 void *payload = NULL;
975 int ret = 0;
976 int i = 0;
977 int cmd_size = 0;
978
Ben Rombergerb7603232011-11-23 17:16:27 -0800979 pr_debug("%s\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700980 if (this_adm.apr == NULL) {
981 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
982 0xFFFFFFFF, &this_adm);
983 if (this_adm.apr == NULL) {
984 pr_err("%s: Unable to register ADM\n", __func__);
985 ret = -ENODEV;
986 return ret;
987 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700988 rtac_set_adm_handle(this_adm.apr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700989 }
990
991 cmd_size = sizeof(struct adm_cmd_memory_map_regions)
992 + sizeof(struct adm_memory_map_regions) * bufcnt;
993
994 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
995 if (!mmap_region_cmd) {
996 pr_err("%s: allocate mmap_region_cmd failed\n", __func__);
997 return -ENOMEM;
998 }
999 mmap_regions = (struct adm_cmd_memory_map_regions *)mmap_region_cmd;
1000 mmap_regions->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1001 APR_HDR_LEN(APR_HDR_SIZE),
1002 APR_PKT_VER);
1003 mmap_regions->hdr.pkt_size = cmd_size;
1004 mmap_regions->hdr.src_port = 0;
1005 mmap_regions->hdr.dest_port = 0;
1006 mmap_regions->hdr.token = 0;
1007 mmap_regions->hdr.opcode = ADM_CMD_MEMORY_MAP_REGIONS;
1008 mmap_regions->mempool_id = mempool_id & 0x00ff;
1009 mmap_regions->nregions = bufcnt & 0x00ff;
1010 pr_debug("%s: map_regions->nregions = %d\n", __func__,
1011 mmap_regions->nregions);
1012 payload = ((u8 *) mmap_region_cmd +
1013 sizeof(struct adm_cmd_memory_map_regions));
1014 mregions = (struct adm_memory_map_regions *)payload;
1015
1016 for (i = 0; i < bufcnt; i++) {
1017 mregions->phys = buf_add[i];
1018 mregions->buf_size = bufsz[i];
1019 ++mregions;
1020 }
1021
1022 atomic_set(&this_adm.copp_stat[0], 0);
1023 ret = apr_send_pkt(this_adm.apr, (uint32_t *) mmap_region_cmd);
1024 if (ret < 0) {
1025 pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
1026 mmap_regions->hdr.opcode, ret);
1027 ret = -EINVAL;
1028 goto fail_cmd;
1029 }
1030
1031 ret = wait_event_timeout(this_adm.wait,
1032 atomic_read(&this_adm.copp_stat[0]), 5 * HZ);
1033 if (!ret) {
1034 pr_err("%s: timeout. waited for memory_map\n", __func__);
1035 ret = -EINVAL;
1036 goto fail_cmd;
1037 }
1038fail_cmd:
1039 kfree(mmap_region_cmd);
1040 return ret;
1041}
1042
1043int adm_memory_unmap_regions(uint32_t *buf_add, uint32_t *bufsz,
1044 uint32_t bufcnt)
1045{
1046 struct adm_cmd_memory_unmap_regions *unmap_regions = NULL;
1047 struct adm_memory_unmap_regions *mregions = NULL;
1048 void *unmap_region_cmd = NULL;
1049 void *payload = NULL;
1050 int ret = 0;
1051 int i = 0;
1052 int cmd_size = 0;
1053
Ben Rombergerb7603232011-11-23 17:16:27 -08001054 pr_debug("%s\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001055
1056 if (this_adm.apr == NULL) {
1057 pr_err("%s APR handle NULL\n", __func__);
1058 return -EINVAL;
1059 }
1060
1061 cmd_size = sizeof(struct adm_cmd_memory_unmap_regions)
1062 + sizeof(struct adm_memory_unmap_regions) * bufcnt;
1063
1064 unmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
1065 if (!unmap_region_cmd) {
1066 pr_err("%s: allocate unmap_region_cmd failed\n", __func__);
1067 return -ENOMEM;
1068 }
1069 unmap_regions = (struct adm_cmd_memory_unmap_regions *)
1070 unmap_region_cmd;
1071 unmap_regions->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1072 APR_HDR_LEN(APR_HDR_SIZE),
1073 APR_PKT_VER);
1074 unmap_regions->hdr.pkt_size = cmd_size;
1075 unmap_regions->hdr.src_port = 0;
1076 unmap_regions->hdr.dest_port = 0;
1077 unmap_regions->hdr.token = 0;
1078 unmap_regions->hdr.opcode = ADM_CMD_MEMORY_UNMAP_REGIONS;
1079 unmap_regions->nregions = bufcnt & 0x00ff;
1080 unmap_regions->reserved = 0;
1081 pr_debug("%s: unmap_regions->nregions = %d\n", __func__,
1082 unmap_regions->nregions);
1083 payload = ((u8 *) unmap_region_cmd +
1084 sizeof(struct adm_cmd_memory_unmap_regions));
1085 mregions = (struct adm_memory_unmap_regions *)payload;
1086
1087 for (i = 0; i < bufcnt; i++) {
1088 mregions->phys = buf_add[i];
1089 ++mregions;
1090 }
1091 atomic_set(&this_adm.copp_stat[0], 0);
1092 ret = apr_send_pkt(this_adm.apr, (uint32_t *) unmap_region_cmd);
1093 if (ret < 0) {
1094 pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
1095 unmap_regions->hdr.opcode, ret);
1096 ret = -EINVAL;
1097 goto fail_cmd;
1098 }
1099
1100 ret = wait_event_timeout(this_adm.wait,
1101 atomic_read(&this_adm.copp_stat[0]), 5 * HZ);
1102 if (!ret) {
1103 pr_err("%s: timeout. waited for memory_unmap\n", __func__);
1104 ret = -EINVAL;
1105 goto fail_cmd;
1106 }
1107fail_cmd:
1108 kfree(unmap_region_cmd);
1109 return ret;
1110}
1111
Ben Romberger974a40d2011-07-18 15:08:21 -07001112int adm_get_copp_id(int port_index)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001113{
1114 pr_debug("%s\n", __func__);
1115
Ben Romberger974a40d2011-07-18 15:08:21 -07001116 if (port_index < 0) {
1117 pr_err("%s: invalid port_id = %d\n", __func__, port_index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001118 return -EINVAL;
1119 }
1120
Ben Romberger974a40d2011-07-18 15:08:21 -07001121 return atomic_read(&this_adm.copp_id[port_index]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001122}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001123
Jayasena Sangaraboinaf4ab0df2012-06-06 22:38:40 -07001124void adm_ec_ref_rx_id(int port_id)
1125{
1126 this_adm.ec_ref_rx = port_id;
1127 pr_debug("%s ec_ref_rx:%d", __func__, this_adm.ec_ref_rx);
1128}
1129
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001130int adm_close(int port_id)
1131{
1132 struct apr_hdr close;
1133
1134 int ret = 0;
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301135 int index = 0;
1136
1137 port_id = afe_convert_virtual_to_portid(port_id);
1138
1139 index = afe_get_port_index(port_id);
Bharath Ramachandramurthy51a86212011-07-29 12:43:43 -07001140 if (afe_validate_port(port_id) < 0)
1141 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001142
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001143 pr_debug("%s port_id=%d index %d\n", __func__, port_id, index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001144
1145 if (!(atomic_read(&this_adm.copp_cnt[index]))) {
1146 pr_err("%s: copp count for port[%d]is 0\n", __func__, port_id);
1147
1148 goto fail_cmd;
1149 }
1150 atomic_dec(&this_adm.copp_cnt[index]);
1151 if (!(atomic_read(&this_adm.copp_cnt[index]))) {
1152
1153 close.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1154 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1155 close.pkt_size = sizeof(close);
1156 close.src_svc = APR_SVC_ADM;
1157 close.src_domain = APR_DOMAIN_APPS;
1158 close.src_port = port_id;
1159 close.dest_svc = APR_SVC_ADM;
1160 close.dest_domain = APR_DOMAIN_ADSP;
1161 close.dest_port = atomic_read(&this_adm.copp_id[index]);
1162 close.token = port_id;
1163 close.opcode = ADM_CMD_COPP_CLOSE;
1164
1165 atomic_set(&this_adm.copp_id[index], RESET_COPP_ID);
1166 atomic_set(&this_adm.copp_stat[index], 0);
1167
1168
1169 pr_debug("%s:coppid %d portid=%d index=%d coppcnt=%d\n",
1170 __func__,
1171 atomic_read(&this_adm.copp_id[index]),
1172 port_id, index,
1173 atomic_read(&this_adm.copp_cnt[index]));
1174
1175 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&close);
1176 if (ret < 0) {
1177 pr_err("%s ADM close failed\n", __func__);
1178 ret = -EINVAL;
1179 goto fail_cmd;
1180 }
1181
1182 ret = wait_event_timeout(this_adm.wait,
1183 atomic_read(&this_adm.copp_stat[index]),
1184 msecs_to_jiffies(TIMEOUT_MS));
1185 if (!ret) {
1186 pr_err("%s: ADM cmd Route failed for port %d\n",
1187 __func__, port_id);
1188 ret = -EINVAL;
1189 goto fail_cmd;
1190 }
Ben Romberger93d4d2d2011-10-19 23:04:02 -07001191
1192 rtac_remove_adm_device(port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001193 }
1194
1195fail_cmd:
1196 return ret;
1197}
1198
1199static int __init adm_init(void)
1200{
1201 int i = 0;
1202 init_waitqueue_head(&this_adm.wait);
1203 this_adm.apr = NULL;
1204
1205 for (i = 0; i < AFE_MAX_PORTS; i++) {
1206 atomic_set(&this_adm.copp_id[i], RESET_COPP_ID);
1207 atomic_set(&this_adm.copp_cnt[i], 0);
1208 atomic_set(&this_adm.copp_stat[i], 0);
1209 }
1210 return 0;
1211}
1212
1213device_initcall(adm_init);