blob: bc57ef3a0cb54799dbbf21348a9169eeb5f370b2 [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;
41};
42
Ben Romberger48fabc32012-01-06 17:39:39 -080043static struct acdb_cal_block mem_addr_audproc[MAX_AUDPROC_TYPES];
44static struct acdb_cal_block mem_addr_audvol[MAX_AUDPROC_TYPES];
45
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070046static struct adm_ctl this_adm;
47
Sriranjan Srikantam22bee8b2012-05-31 15:21:53 -070048int srs_trumedia_open(int port_id, int srs_tech_id, void *srs_params)
49{
50 struct asm_pp_params_command *open = NULL;
51 int ret = 0, sz = 0;
52 int index;
53
54 pr_debug("SRS - %s", __func__);
55 switch (srs_tech_id) {
56 case SRS_ID_GLOBAL: {
57 struct srs_trumedia_params_GLOBAL *glb_params = NULL;
58 sz = sizeof(struct asm_pp_params_command) +
59 sizeof(struct srs_trumedia_params_GLOBAL);
60 open = kzalloc(sz, GFP_KERNEL);
61 open->payload_size = sizeof(struct srs_trumedia_params_GLOBAL) +
62 sizeof(struct asm_pp_param_data_hdr);
63 open->params.param_id = SRS_TRUMEDIA_PARAMS;
64 open->params.param_size =
65 sizeof(struct srs_trumedia_params_GLOBAL);
66 glb_params = (struct srs_trumedia_params_GLOBAL *)((u8 *)open +
67 sizeof(struct asm_pp_params_command));
68 memcpy(glb_params, srs_params,
69 sizeof(struct srs_trumedia_params_GLOBAL));
70 pr_debug("SRS - %s: Global params - 1 = %x, 2 = %x, 3 = %x,"
71 " 4 = %x, 5 = %x, 6 = %x, 7 = %x, 8 = %x\n",
72 __func__, (int)glb_params->v1,
73 (int)glb_params->v2, (int)glb_params->v3,
74 (int)glb_params->v4, (int)glb_params->v5,
75 (int)glb_params->v6, (int)glb_params->v7,
76 (int)glb_params->v8);
77 break;
78 }
79 case SRS_ID_WOWHD: {
80 struct srs_trumedia_params_WOWHD *whd_params = NULL;
81 sz = sizeof(struct asm_pp_params_command) +
82 sizeof(struct srs_trumedia_params_WOWHD);
83 open = kzalloc(sz, GFP_KERNEL);
84 open->payload_size = sizeof(struct srs_trumedia_params_WOWHD) +
85 sizeof(struct asm_pp_param_data_hdr);
86 open->params.param_id = SRS_TRUMEDIA_PARAMS_WOWHD;
87 open->params.param_size =
88 sizeof(struct srs_trumedia_params_WOWHD);
89 whd_params = (struct srs_trumedia_params_WOWHD *)((u8 *)open +
90 sizeof(struct asm_pp_params_command));
91 memcpy(whd_params, srs_params,
92 sizeof(struct srs_trumedia_params_WOWHD));
93 pr_debug("SRS - %s: WOWHD params - 1 = %x, 2 = %x, 3 = %x,"
94 " 4 = %x, 5 = %x, 6 = %x, 7 = %x, 8 = %x, 9 = %x,"
95 " 10 = %x, 11 = %x\n", __func__, (int)whd_params->v1,
96 (int)whd_params->v2, (int)whd_params->v3,
97 (int)whd_params->v4, (int)whd_params->v5,
98 (int)whd_params->v6, (int)whd_params->v7,
99 (int)whd_params->v8, (int)whd_params->v9,
100 (int)whd_params->v10, (int)whd_params->v11);
101 break;
102 }
103 case SRS_ID_CSHP: {
104 struct srs_trumedia_params_CSHP *chp_params = NULL;
105 sz = sizeof(struct asm_pp_params_command) +
106 sizeof(struct srs_trumedia_params_CSHP);
107 open = kzalloc(sz, GFP_KERNEL);
108 open->payload_size = sizeof(struct srs_trumedia_params_CSHP) +
109 sizeof(struct asm_pp_param_data_hdr);
110 open->params.param_id = SRS_TRUMEDIA_PARAMS_CSHP;
111 open->params.param_size =
112 sizeof(struct srs_trumedia_params_CSHP);
113 chp_params = (struct srs_trumedia_params_CSHP *)((u8 *)open +
114 sizeof(struct asm_pp_params_command));
115 memcpy(chp_params, srs_params,
116 sizeof(struct srs_trumedia_params_CSHP));
117 pr_debug("SRS - %s: CSHP params - 1 = %x, 2 = %x, 3 = %x,"
118 " 4 = %x, 5 = %x, 6 = %x, 7 = %x, 8 = %x,"
119 " 9 = %x\n", __func__, (int)chp_params->v1,
120 (int)chp_params->v2, (int)chp_params->v3,
121 (int)chp_params->v4, (int)chp_params->v5,
122 (int)chp_params->v6, (int)chp_params->v7,
123 (int)chp_params->v8, (int)chp_params->v9);
124 break;
125 }
126 case SRS_ID_HPF: {
127 struct srs_trumedia_params_HPF *hpf_params = NULL;
128 sz = sizeof(struct asm_pp_params_command) +
129 sizeof(struct srs_trumedia_params_HPF);
130 open = kzalloc(sz, GFP_KERNEL);
131 open->payload_size = sizeof(struct srs_trumedia_params_HPF) +
132 sizeof(struct asm_pp_param_data_hdr);
133 open->params.param_id = SRS_TRUMEDIA_PARAMS_HPF;
134 open->params.param_size =
135 sizeof(struct srs_trumedia_params_HPF);
136 hpf_params = (struct srs_trumedia_params_HPF *)((u8 *)open +
137 sizeof(struct asm_pp_params_command));
138 memcpy(hpf_params, srs_params,
139 sizeof(struct srs_trumedia_params_HPF));
140 pr_debug("SRS - %s: HPF params - 1 = %x\n", __func__,
141 (int)hpf_params->v1);
142 break;
143 }
144 case SRS_ID_PEQ: {
145 struct srs_trumedia_params_PEQ *peq_params = NULL;
146 sz = sizeof(struct asm_pp_params_command) +
147 sizeof(struct srs_trumedia_params_PEQ);
148 open = kzalloc(sz, GFP_KERNEL);
149 open->payload_size = sizeof(struct srs_trumedia_params_PEQ) +
150 sizeof(struct asm_pp_param_data_hdr);
151 open->params.param_id = SRS_TRUMEDIA_PARAMS_PEQ;
152 open->params.param_size =
153 sizeof(struct srs_trumedia_params_PEQ);
154 peq_params = (struct srs_trumedia_params_PEQ *)((u8 *)open +
155 sizeof(struct asm_pp_params_command));
156 memcpy(peq_params, srs_params,
157 sizeof(struct srs_trumedia_params_PEQ));
158 pr_debug("SRS - %s: PEQ params - 1 = %x 2 = %x, 3 = %x,"
159 " 4 = %x\n", __func__, (int)peq_params->v1,
160 (int)peq_params->v2, (int)peq_params->v3,
161 (int)peq_params->v4);
162 break;
163 }
164 case SRS_ID_HL: {
165 struct srs_trumedia_params_HL *hl_params = NULL;
166 sz = sizeof(struct asm_pp_params_command) +
167 sizeof(struct srs_trumedia_params_HL);
168 open = kzalloc(sz, GFP_KERNEL);
169 open->payload_size = sizeof(struct srs_trumedia_params_HL) +
170 sizeof(struct asm_pp_param_data_hdr);
171 open->params.param_id = SRS_TRUMEDIA_PARAMS_HL;
172 open->params.param_size = sizeof(struct srs_trumedia_params_HL);
173 hl_params = (struct srs_trumedia_params_HL *)((u8 *)open +
174 sizeof(struct asm_pp_params_command));
175 memcpy(hl_params, srs_params,
176 sizeof(struct srs_trumedia_params_HL));
177 pr_debug("SRS - %s: HL params - 1 = %x, 2 = %x, 3 = %x, 4 = %x,"
178 " 5 = %x, 6 = %x, 7 = %x\n", __func__,
179 (int)hl_params->v1, (int)hl_params->v2,
180 (int)hl_params->v3, (int)hl_params->v4,
181 (int)hl_params->v5, (int)hl_params->v6,
182 (int)hl_params->v7);
183 break;
184 }
185 default:
186 goto fail_cmd;
187 }
188
189 open->payload = NULL;
190 open->params.module_id = SRS_TRUMEDIA_MODULE_ID;
191 open->params.reserved = 0;
192 open->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
193 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
194 open->hdr.pkt_size = sz;
195 open->hdr.src_svc = APR_SVC_ADM;
196 open->hdr.src_domain = APR_DOMAIN_APPS;
197 open->hdr.src_port = port_id;
198 open->hdr.dest_svc = APR_SVC_ADM;
199 open->hdr.dest_domain = APR_DOMAIN_ADSP;
200 index = afe_get_port_index(port_id);
201 open->hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
202 open->hdr.token = port_id;
203 open->hdr.opcode = ADM_CMD_SET_PARAMS;
204 pr_debug("SRS - %s: Command was sent now check Q6 - port id = %d,"
205 " size %d, module id %x, param id %x.\n", __func__,
206 open->hdr.dest_port, open->payload_size,
207 open->params.module_id, open->params.param_id);
208
209 ret = apr_send_pkt(this_adm.apr, (uint32_t *)open);
210 if (ret < 0) {
211 pr_err("SRS - %s: ADM enable for port %d failed\n", __func__,
212 port_id);
213 ret = -EINVAL;
214 goto fail_cmd;
215 }
216 /* Wait for the callback with copp id */
217 ret = wait_event_timeout(this_adm.wait, 1,
218 msecs_to_jiffies(TIMEOUT_MS));
219 if (!ret) {
220 pr_err("SRS - %s: ADM open failed for port %d\n", __func__,
221 port_id);
222 ret = -EINVAL;
223 goto fail_cmd;
224 }
225
226fail_cmd:
227 kfree(open);
228 return ret;
229}
230
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700231static int32_t adm_callback(struct apr_client_data *data, void *priv)
232{
233 uint32_t *payload;
234 int i, index;
235 payload = data->payload;
236
237 if (data->opcode == RESET_EVENTS) {
238 pr_debug("adm_callback: Reset event is received: %d %d apr[%p]\n",
239 data->reset_event, data->reset_proc,
240 this_adm.apr);
241 if (this_adm.apr) {
242 apr_reset(this_adm.apr);
243 for (i = 0; i < AFE_MAX_PORTS; i++) {
244 atomic_set(&this_adm.copp_id[i],
245 RESET_COPP_ID);
246 atomic_set(&this_adm.copp_cnt[i], 0);
247 atomic_set(&this_adm.copp_stat[i], 0);
248 }
249 this_adm.apr = NULL;
250 }
251 return 0;
252 }
253
254 pr_debug("%s: code = 0x%x %x %x size = %d\n", __func__,
255 data->opcode, payload[0], payload[1],
256 data->payload_size);
257
258 if (data->payload_size) {
259 index = afe_get_port_index(data->token);
260 pr_debug("%s: Port ID %d, index %d\n", __func__,
261 data->token, index);
Bharath Ramachandramurthy94ad7e22012-02-28 18:44:07 -0800262 if (index < 0 || index >= AFE_MAX_PORTS) {
263 pr_err("%s: invalid port idx %d token %d\n",
264 __func__, index, data->token);
265 return 0;
266 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700267 if (data->opcode == APR_BASIC_RSP_RESULT) {
Santosh Mardi23321202012-03-22 04:33:25 +0530268 pr_debug("APR_BASIC_RSP_RESULT id %x\n", payload[0]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700269 switch (payload[0]) {
270 case ADM_CMD_SET_PARAMS:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700271 if (rtac_make_adm_callback(payload,
272 data->payload_size))
273 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700274 case ADM_CMD_COPP_CLOSE:
275 case ADM_CMD_MEMORY_MAP:
276 case ADM_CMD_MEMORY_UNMAP:
277 case ADM_CMD_MEMORY_MAP_REGIONS:
278 case ADM_CMD_MEMORY_UNMAP_REGIONS:
279 case ADM_CMD_MATRIX_MAP_ROUTINGS:
Santosh Mardi23321202012-03-22 04:33:25 +0530280 case ADM_CMD_CONNECT_AFE_PORT:
Santosh Mardid1760792012-06-12 16:23:19 +0530281 case ADM_CMD_DISCONNECT_AFE_PORT:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700282 atomic_set(&this_adm.copp_stat[index], 1);
283 wake_up(&this_adm.wait);
284 break;
285 default:
286 pr_err("%s: Unknown Cmd: 0x%x\n", __func__,
287 payload[0]);
288 break;
289 }
290 return 0;
291 }
292
293 switch (data->opcode) {
Kiran Kandi5e809b02012-01-31 00:24:33 -0800294 case ADM_CMDRSP_COPP_OPEN:
295 case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN: {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700296 struct adm_copp_open_respond *open = data->payload;
297 if (open->copp_id == INVALID_COPP_ID) {
298 pr_err("%s: invalid coppid rxed %d\n",
299 __func__, open->copp_id);
300 atomic_set(&this_adm.copp_stat[index], 1);
301 wake_up(&this_adm.wait);
302 break;
303 }
304 atomic_set(&this_adm.copp_id[index], open->copp_id);
305 atomic_set(&this_adm.copp_stat[index], 1);
306 pr_debug("%s: coppid rxed=%d\n", __func__,
307 open->copp_id);
308 wake_up(&this_adm.wait);
309 }
310 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700311 case ADM_CMDRSP_GET_PARAMS:
Swaminathan Sathappan88163a72011-08-01 16:01:14 -0700312 pr_debug("%s: ADM_CMDRSP_GET_PARAMS\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700313 rtac_make_adm_callback(payload,
314 data->payload_size);
315 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700316 default:
317 pr_err("%s: Unknown cmd:0x%x\n", __func__,
318 data->opcode);
319 break;
320 }
321 }
322 return 0;
323}
324
Ben Romberger48fabc32012-01-06 17:39:39 -0800325static int send_adm_cal_block(int port_id, struct acdb_cal_block *aud_cal)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700326{
Ben Rombergerdcab5472011-12-08 19:20:12 -0800327 s32 result = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700328 struct adm_set_params_command adm_params;
329 int index = afe_get_port_index(port_id);
Ben Romberger09dc65f2012-03-22 20:06:55 -0700330 if (index < 0 || index >= AFE_MAX_PORTS) {
331 pr_err("%s: invalid port idx %d portid %d\n",
332 __func__, index, port_id);
Mingming Yinc09967e2012-04-27 15:09:43 -0700333 return 0;
Ben Romberger09dc65f2012-03-22 20:06:55 -0700334 }
Mingming Yinc09967e2012-04-27 15:09:43 -0700335
336 pr_debug("%s: Port id %d, index %d\n", __func__, port_id, index);
337
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700338 if (!aud_cal || aud_cal->cal_size == 0) {
Ben Rombergerdcab5472011-12-08 19:20:12 -0800339 pr_debug("%s: No ADM cal to send for port_id = %d!\n",
340 __func__, port_id);
341 result = -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700342 goto done;
343 }
344
345 adm_params.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
346 APR_HDR_LEN(20), APR_PKT_VER);
347 adm_params.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
348 sizeof(adm_params));
349 adm_params.hdr.src_svc = APR_SVC_ADM;
350 adm_params.hdr.src_domain = APR_DOMAIN_APPS;
351 adm_params.hdr.src_port = port_id;
352 adm_params.hdr.dest_svc = APR_SVC_ADM;
353 adm_params.hdr.dest_domain = APR_DOMAIN_ADSP;
354 adm_params.hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
355 adm_params.hdr.token = port_id;
356 adm_params.hdr.opcode = ADM_CMD_SET_PARAMS;
357 adm_params.payload = aud_cal->cal_paddr;
358 adm_params.payload_size = aud_cal->cal_size;
359
360 atomic_set(&this_adm.copp_stat[index], 0);
361 pr_debug("%s: Sending SET_PARAMS payload = 0x%x, size = %d\n",
362 __func__, adm_params.payload, adm_params.payload_size);
363 result = apr_send_pkt(this_adm.apr, (uint32_t *)&adm_params);
364 if (result < 0) {
365 pr_err("%s: Set params failed port = %d payload = 0x%x\n",
366 __func__, port_id, aud_cal->cal_paddr);
Ben Rombergerdcab5472011-12-08 19:20:12 -0800367 result = -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700368 goto done;
369 }
370 /* Wait for the callback */
371 result = wait_event_timeout(this_adm.wait,
372 atomic_read(&this_adm.copp_stat[index]),
373 msecs_to_jiffies(TIMEOUT_MS));
Ben Rombergerdcab5472011-12-08 19:20:12 -0800374 if (!result) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700375 pr_err("%s: Set params timed out port = %d, payload = 0x%x\n",
376 __func__, port_id, aud_cal->cal_paddr);
Ben Rombergerdcab5472011-12-08 19:20:12 -0800377 result = -EINVAL;
378 goto done;
379 }
380
381 result = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700382done:
Ben Rombergerdcab5472011-12-08 19:20:12 -0800383 return result;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700384}
385
Ben Romberger48fabc32012-01-06 17:39:39 -0800386static void send_adm_cal(int port_id, int path)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700387{
Ben Romberger48fabc32012-01-06 17:39:39 -0800388 int result = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700389 s32 acdb_path;
390 struct acdb_cal_block aud_cal;
391
392 pr_debug("%s\n", __func__);
393
394 /* Maps audio_dev_ctrl path definition to ACDB definition */
395 acdb_path = path - 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700396
397 pr_debug("%s: Sending audproc cal\n", __func__);
398 get_audproc_cal(acdb_path, &aud_cal);
Ben Romberger48fabc32012-01-06 17:39:39 -0800399
400 /* map & cache buffers used */
Ben Romberger9e792562012-02-24 12:29:01 -0800401 if (((mem_addr_audproc[acdb_path].cal_paddr != aud_cal.cal_paddr) &&
402 (aud_cal.cal_size > 0)) ||
403 (aud_cal.cal_size > mem_addr_audproc[acdb_path].cal_size)) {
404
Ben Romberger48fabc32012-01-06 17:39:39 -0800405 if (mem_addr_audproc[acdb_path].cal_paddr != 0)
406 adm_memory_unmap_regions(
407 &mem_addr_audproc[acdb_path].cal_paddr,
408 &mem_addr_audproc[acdb_path].cal_size, 1);
409
410 result = adm_memory_map_regions(&aud_cal.cal_paddr, 0,
411 &aud_cal.cal_size, 1);
412 if (result < 0)
413 pr_err("ADM audproc mmap did not work! path = %d, "
414 "addr = 0x%x, size = %d\n", acdb_path,
415 aud_cal.cal_paddr, aud_cal.cal_size);
416 else
417 mem_addr_audproc[acdb_path] = aud_cal;
418 }
419
Ben Rombergerdcab5472011-12-08 19:20:12 -0800420 if (!send_adm_cal_block(port_id, &aud_cal))
Ben Romberger48fabc32012-01-06 17:39:39 -0800421 pr_debug("%s: Audproc cal sent for port id: %d, path %d\n",
Ben Rombergerdcab5472011-12-08 19:20:12 -0800422 __func__, port_id, acdb_path);
423 else
Ben Romberger48fabc32012-01-06 17:39:39 -0800424 pr_debug("%s: Audproc cal not sent for port id: %d, path %d\n",
Ben Rombergerdcab5472011-12-08 19:20:12 -0800425 __func__, port_id, acdb_path);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700426
427 pr_debug("%s: Sending audvol cal\n", __func__);
428 get_audvol_cal(acdb_path, &aud_cal);
Ben Romberger48fabc32012-01-06 17:39:39 -0800429
430 /* map & cache buffers used */
Ben Romberger9e792562012-02-24 12:29:01 -0800431 if (((mem_addr_audvol[acdb_path].cal_paddr != aud_cal.cal_paddr) &&
432 (aud_cal.cal_size > 0)) ||
433 (aud_cal.cal_size > mem_addr_audvol[acdb_path].cal_size)) {
Ben Romberger48fabc32012-01-06 17:39:39 -0800434 if (mem_addr_audvol[acdb_path].cal_paddr != 0)
435 adm_memory_unmap_regions(
436 &mem_addr_audvol[acdb_path].cal_paddr,
437 &mem_addr_audvol[acdb_path].cal_size, 1);
438
439 result = adm_memory_map_regions(&aud_cal.cal_paddr, 0,
440 &aud_cal.cal_size, 1);
441 if (result < 0)
442 pr_err("ADM audvol mmap did not work! path = %d, "
443 "addr = 0x%x, size = %d\n", acdb_path,
444 aud_cal.cal_paddr, aud_cal.cal_size);
445 else
446 mem_addr_audvol[acdb_path] = aud_cal;
447 }
448
Ben Rombergerdcab5472011-12-08 19:20:12 -0800449 if (!send_adm_cal_block(port_id, &aud_cal))
Ben Romberger48fabc32012-01-06 17:39:39 -0800450 pr_debug("%s: Audvol cal sent for port id: %d, path %d\n",
Ben Rombergerdcab5472011-12-08 19:20:12 -0800451 __func__, port_id, acdb_path);
452 else
Ben Romberger48fabc32012-01-06 17:39:39 -0800453 pr_debug("%s: Audvol cal not sent for port id: %d, path %d\n",
Ben Rombergerdcab5472011-12-08 19:20:12 -0800454 __func__, port_id, acdb_path);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700455}
456
Santosh Mardi23321202012-03-22 04:33:25 +0530457int adm_connect_afe_port(int mode, int session_id, int port_id)
458{
459 struct adm_cmd_connect_afe_port cmd;
460 int ret = 0;
461 int index;
462
463 pr_debug("%s: port %d session id:%d mode:%d\n", __func__,
464 port_id, session_id, mode);
465
466 port_id = afe_convert_virtual_to_portid(port_id);
467
468 if (afe_validate_port(port_id) < 0) {
469 pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
470 return -ENODEV;
471 }
472 if (this_adm.apr == NULL) {
473 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
474 0xFFFFFFFF, &this_adm);
475 if (this_adm.apr == NULL) {
476 pr_err("%s: Unable to register ADM\n", __func__);
477 ret = -ENODEV;
478 return ret;
479 }
480 rtac_set_adm_handle(this_adm.apr);
481 }
482 index = afe_get_port_index(port_id);
483 pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
484
485 cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
486 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
487 cmd.hdr.pkt_size = sizeof(cmd);
488 cmd.hdr.src_svc = APR_SVC_ADM;
489 cmd.hdr.src_domain = APR_DOMAIN_APPS;
490 cmd.hdr.src_port = port_id;
491 cmd.hdr.dest_svc = APR_SVC_ADM;
492 cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
493 cmd.hdr.dest_port = port_id;
494 cmd.hdr.token = port_id;
495 cmd.hdr.opcode = ADM_CMD_CONNECT_AFE_PORT;
496
497 cmd.mode = mode;
498 cmd.session_id = session_id;
499 cmd.afe_port_id = port_id;
500
501 atomic_set(&this_adm.copp_stat[index], 0);
502 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd);
503 if (ret < 0) {
504 pr_err("%s:ADM enable for port %d failed\n",
505 __func__, port_id);
506 ret = -EINVAL;
507 goto fail_cmd;
508 }
509 /* Wait for the callback with copp id */
510 ret = wait_event_timeout(this_adm.wait,
511 atomic_read(&this_adm.copp_stat[index]),
512 msecs_to_jiffies(TIMEOUT_MS));
513 if (!ret) {
514 pr_err("%s ADM connect AFE failed for port %d\n", __func__,
515 port_id);
516 ret = -EINVAL;
517 goto fail_cmd;
518 }
519 atomic_inc(&this_adm.copp_cnt[index]);
520 return 0;
521
522fail_cmd:
523
524 return ret;
525}
526
Santosh Mardid1760792012-06-12 16:23:19 +0530527int adm_disconnect_afe_port(int mode, int session_id, int port_id)
528{
529 struct adm_cmd_connect_afe_port cmd;
530 int ret = 0;
531 int index;
532
533 pr_debug("%s: port %d session id:%d mode:%d\n", __func__,
534 port_id, session_id, mode);
535
536 port_id = afe_convert_virtual_to_portid(port_id);
537
538 if (afe_validate_port(port_id) < 0) {
539 pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
540 return -ENODEV;
541 }
542 if (this_adm.apr == NULL) {
543 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
544 0xFFFFFFFF, &this_adm);
545 if (this_adm.apr == NULL) {
546 pr_err("%s: Unable to register ADM\n", __func__);
547 ret = -ENODEV;
548 return ret;
549 }
550 rtac_set_adm_handle(this_adm.apr);
551 }
552 index = afe_get_port_index(port_id);
553 pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
554
555 cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
556 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
557 cmd.hdr.pkt_size = sizeof(cmd);
558 cmd.hdr.src_svc = APR_SVC_ADM;
559 cmd.hdr.src_domain = APR_DOMAIN_APPS;
560 cmd.hdr.src_port = port_id;
561 cmd.hdr.dest_svc = APR_SVC_ADM;
562 cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
563 cmd.hdr.dest_port = port_id;
564 cmd.hdr.token = port_id;
565 cmd.hdr.opcode = ADM_CMD_DISCONNECT_AFE_PORT;
566
567 cmd.mode = mode;
568 cmd.session_id = session_id;
569 cmd.afe_port_id = port_id;
570
571 atomic_set(&this_adm.copp_stat[index], 0);
572 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd);
573 if (ret < 0) {
574 pr_err("%s:ADM enable for port %d failed\n",
575 __func__, port_id);
576 ret = -EINVAL;
577 goto fail_cmd;
578 }
579 /* Wait for the callback with copp id */
580 ret = wait_event_timeout(this_adm.wait,
581 atomic_read(&this_adm.copp_stat[index]),
582 msecs_to_jiffies(TIMEOUT_MS));
583 if (!ret) {
584 pr_err("%s ADM connect AFE failed for port %d\n", __func__,
585 port_id);
586 ret = -EINVAL;
587 goto fail_cmd;
588 }
589 atomic_dec(&this_adm.copp_cnt[index]);
590 return 0;
591
592fail_cmd:
593
594 return ret;
595}
596
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700597int adm_open(int port_id, int path, int rate, int channel_mode, int topology)
598{
599 struct adm_copp_open_command open;
600 int ret = 0;
601 int index;
602
603 pr_debug("%s: port %d path:%d rate:%d mode:%d\n", __func__,
604 port_id, path, rate, channel_mode);
605
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530606 port_id = afe_convert_virtual_to_portid(port_id);
607
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700608 if (afe_validate_port(port_id) < 0) {
609 pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
610 return -ENODEV;
611 }
612
613 index = afe_get_port_index(port_id);
614 pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
615
616 if (this_adm.apr == NULL) {
617 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
618 0xFFFFFFFF, &this_adm);
619 if (this_adm.apr == NULL) {
620 pr_err("%s: Unable to register ADM\n", __func__);
621 ret = -ENODEV;
622 return ret;
623 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700624 rtac_set_adm_handle(this_adm.apr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700625 }
626
627
628 /* Create a COPP if port id are not enabled */
629 if (atomic_read(&this_adm.copp_cnt[index]) == 0) {
630
631 open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
632 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
633 open.hdr.pkt_size = sizeof(open);
634 open.hdr.src_svc = APR_SVC_ADM;
635 open.hdr.src_domain = APR_DOMAIN_APPS;
636 open.hdr.src_port = port_id;
637 open.hdr.dest_svc = APR_SVC_ADM;
638 open.hdr.dest_domain = APR_DOMAIN_ADSP;
639 open.hdr.dest_port = port_id;
640 open.hdr.token = port_id;
641 open.hdr.opcode = ADM_CMD_COPP_OPEN;
642
643 open.mode = path;
644 open.endpoint_id1 = port_id;
645 open.endpoint_id2 = 0xFFFF;
646
Ben Rombergerc49b85d2011-07-15 18:55:34 -0700647 /* convert path to acdb path */
Ben Romberger974a40d2011-07-18 15:08:21 -0700648 if (path == ADM_PATH_PLAYBACK)
Ben Rombergerc49b85d2011-07-15 18:55:34 -0700649 open.topology_id = get_adm_rx_topology();
Jay Wang4fa2ee42011-07-18 00:21:22 -0700650 else {
Ben Rombergerc49b85d2011-07-15 18:55:34 -0700651 open.topology_id = get_adm_tx_topology();
Jay Wang4fa2ee42011-07-18 00:21:22 -0700652 if ((open.topology_id ==
653 VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
654 (open.topology_id ==
Jay Wang17283132012-03-30 15:18:12 -0700655 VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
Jay Wang4fa2ee42011-07-18 00:21:22 -0700656 rate = 16000;
657 }
Ben Rombergerc49b85d2011-07-15 18:55:34 -0700658
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700659 if (open.topology_id == 0)
660 open.topology_id = topology;
661
662 open.channel_config = channel_mode & 0x00FF;
663 open.rate = rate;
664
Bharath Ramachandramurthy94ad7e22012-02-28 18:44:07 -0800665 pr_debug("%s: channel_config=%d port_id=%d rate=%d"
666 "topology_id=0x%X\n", __func__, open.channel_config,\
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700667 open.endpoint_id1, open.rate,\
668 open.topology_id);
669
670 atomic_set(&this_adm.copp_stat[index], 0);
671
672 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
673 if (ret < 0) {
674 pr_err("%s:ADM enable for port %d failed\n",
675 __func__, port_id);
676 ret = -EINVAL;
677 goto fail_cmd;
678 }
679 /* Wait for the callback with copp id */
680 ret = wait_event_timeout(this_adm.wait,
681 atomic_read(&this_adm.copp_stat[index]),
682 msecs_to_jiffies(TIMEOUT_MS));
683 if (!ret) {
684 pr_err("%s ADM open failed for port %d\n", __func__,
685 port_id);
686 ret = -EINVAL;
687 goto fail_cmd;
688 }
689 }
690 atomic_inc(&this_adm.copp_cnt[index]);
691 return 0;
692
693fail_cmd:
694
695 return ret;
696}
697
Kiran Kandi5e809b02012-01-31 00:24:33 -0800698
699int adm_multi_ch_copp_open(int port_id, int path, int rate, int channel_mode,
700 int topology)
701{
702 struct adm_multi_ch_copp_open_command open;
703 int ret = 0;
704 int index;
705
706 pr_debug("%s: port %d path:%d rate:%d channel :%d\n", __func__,
707 port_id, path, rate, channel_mode);
708
709 port_id = afe_convert_virtual_to_portid(port_id);
710
711 if (afe_validate_port(port_id) < 0) {
712 pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
713 return -ENODEV;
714 }
715
716 index = afe_get_port_index(port_id);
717 pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
718
719 if (this_adm.apr == NULL) {
720 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
721 0xFFFFFFFF, &this_adm);
722 if (this_adm.apr == NULL) {
723 pr_err("%s: Unable to register ADM\n", __func__);
724 ret = -ENODEV;
725 return ret;
726 }
727 rtac_set_adm_handle(this_adm.apr);
728 }
729
730 /* Create a COPP if port id are not enabled */
731 if (atomic_read(&this_adm.copp_cnt[index]) == 0) {
732
733 open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
734 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
735
736 open.hdr.pkt_size =
737 sizeof(struct adm_multi_ch_copp_open_command);
738 open.hdr.opcode = ADM_CMD_MULTI_CHANNEL_COPP_OPEN;
739 memset(open.dev_channel_mapping, 0, 8);
740
741 if (channel_mode == 1) {
742 open.dev_channel_mapping[0] = PCM_CHANNEL_FC;
743 } else if (channel_mode == 2) {
744 open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
745 open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
Mingming Yin647e9ea2012-03-17 19:56:10 -0700746 } else if (channel_mode == 4) {
747 open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
748 open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
749 open.dev_channel_mapping[2] = PCM_CHANNEL_RB;
750 open.dev_channel_mapping[3] = PCM_CHANNEL_LB;
Kiran Kandi5e809b02012-01-31 00:24:33 -0800751 } else if (channel_mode == 6) {
752 open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
753 open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
754 open.dev_channel_mapping[2] = PCM_CHANNEL_LFE;
755 open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
756 open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
757 open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
758 } else {
759 pr_err("%s invalid num_chan %d\n", __func__,
760 channel_mode);
761 return -EINVAL;
762 }
763
764
765 open.hdr.src_svc = APR_SVC_ADM;
766 open.hdr.src_domain = APR_DOMAIN_APPS;
767 open.hdr.src_port = port_id;
768 open.hdr.dest_svc = APR_SVC_ADM;
769 open.hdr.dest_domain = APR_DOMAIN_ADSP;
770 open.hdr.dest_port = port_id;
771 open.hdr.token = port_id;
772
773 open.mode = path;
774 open.endpoint_id1 = port_id;
775 open.endpoint_id2 = 0xFFFF;
776
777 /* convert path to acdb path */
778 if (path == ADM_PATH_PLAYBACK)
779 open.topology_id = get_adm_rx_topology();
780 else {
781 open.topology_id = get_adm_tx_topology();
782 if ((open.topology_id ==
783 VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
784 (open.topology_id ==
Jay Wang0124d872012-05-23 14:10:36 -0700785 VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
Kiran Kandi5e809b02012-01-31 00:24:33 -0800786 rate = 16000;
787 }
788
789 if (open.topology_id == 0)
790 open.topology_id = topology;
791
792 open.channel_config = channel_mode & 0x00FF;
793 open.rate = rate;
794
795 pr_debug("%s: channel_config=%d port_id=%d rate=%d"
796 " topology_id=0x%X\n", __func__, open.channel_config,
797 open.endpoint_id1, open.rate,
798 open.topology_id);
799
800 atomic_set(&this_adm.copp_stat[index], 0);
801
802 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
803 if (ret < 0) {
804 pr_err("%s:ADM enable for port %d failed\n",
805 __func__, port_id);
806 ret = -EINVAL;
807 goto fail_cmd;
808 }
809 /* Wait for the callback with copp id */
810 ret = wait_event_timeout(this_adm.wait,
811 atomic_read(&this_adm.copp_stat[index]),
812 msecs_to_jiffies(TIMEOUT_MS));
813 if (!ret) {
814 pr_err("%s ADM open failed for port %d\n", __func__,
815 port_id);
816 ret = -EINVAL;
817 goto fail_cmd;
818 }
819 }
820 atomic_inc(&this_adm.copp_cnt[index]);
821 return 0;
822
823fail_cmd:
824
825 return ret;
826}
827
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700828int adm_matrix_map(int session_id, int path, int num_copps,
829 unsigned int *port_id, int copp_id)
830{
831 struct adm_routings_command route;
832 int ret = 0, i = 0;
833 /* Assumes port_ids have already been validated during adm_open */
834 int index = afe_get_port_index(copp_id);
Mingming Yinc09967e2012-04-27 15:09:43 -0700835 if (index < 0 || index >= AFE_MAX_PORTS) {
836 pr_err("%s: invalid port idx %d token %d\n",
837 __func__, index, copp_id);
838 return 0;
839 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700840
841 pr_debug("%s: session 0x%x path:%d num_copps:%d port_id[0]:%d\n",
842 __func__, session_id, path, num_copps, port_id[0]);
843
844 route.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
845 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
846 route.hdr.pkt_size = sizeof(route);
847 route.hdr.src_svc = 0;
848 route.hdr.src_domain = APR_DOMAIN_APPS;
849 route.hdr.src_port = copp_id;
850 route.hdr.dest_svc = APR_SVC_ADM;
851 route.hdr.dest_domain = APR_DOMAIN_ADSP;
852 route.hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
853 route.hdr.token = copp_id;
854 route.hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS;
855 route.num_sessions = 1;
856 route.session[0].id = session_id;
857 route.session[0].num_copps = num_copps;
858
859 for (i = 0; i < num_copps; i++) {
860 int tmp;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530861 port_id[i] = afe_convert_virtual_to_portid(port_id[i]);
862
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700863 tmp = afe_get_port_index(port_id[i]);
864
865 pr_debug("%s: port_id[%d]: %d, index: %d\n", __func__, i,
866 port_id[i], tmp);
867
Mingming Yinc09967e2012-04-27 15:09:43 -0700868 if (tmp >= 0 && tmp < AFE_MAX_PORTS)
Bharath Ramachandramurthy94ad7e22012-02-28 18:44:07 -0800869 route.session[0].copp_id[i] =
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700870 atomic_read(&this_adm.copp_id[tmp]);
871 }
872 if (num_copps % 2)
873 route.session[0].copp_id[i] = 0;
874
875 switch (path) {
876 case 0x1:
877 route.path = AUDIO_RX;
878 break;
879 case 0x2:
880 case 0x3:
881 route.path = AUDIO_TX;
882 break;
883 default:
884 pr_err("%s: Wrong path set[%d]\n", __func__, path);
885 break;
886 }
887 atomic_set(&this_adm.copp_stat[index], 0);
888
889 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&route);
890 if (ret < 0) {
891 pr_err("%s: ADM routing for port %d failed\n",
892 __func__, port_id[0]);
893 ret = -EINVAL;
894 goto fail_cmd;
895 }
896 ret = wait_event_timeout(this_adm.wait,
897 atomic_read(&this_adm.copp_stat[index]),
898 msecs_to_jiffies(TIMEOUT_MS));
899 if (!ret) {
900 pr_err("%s: ADM cmd Route failed for port %d\n",
901 __func__, port_id[0]);
902 ret = -EINVAL;
903 goto fail_cmd;
904 }
905
906 for (i = 0; i < num_copps; i++)
907 send_adm_cal(port_id[i], path);
908
Ben Romberger974a40d2011-07-18 15:08:21 -0700909 for (i = 0; i < num_copps; i++)
910 rtac_add_adm_device(port_id[i], atomic_read(&this_adm.copp_id
911 [afe_get_port_index(port_id[i])]),
912 path, session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700913 return 0;
914
915fail_cmd:
916
917 return ret;
918}
919
920int adm_memory_map_regions(uint32_t *buf_add, uint32_t mempool_id,
921 uint32_t *bufsz, uint32_t bufcnt)
922{
923 struct adm_cmd_memory_map_regions *mmap_regions = NULL;
924 struct adm_memory_map_regions *mregions = NULL;
925 void *mmap_region_cmd = NULL;
926 void *payload = NULL;
927 int ret = 0;
928 int i = 0;
929 int cmd_size = 0;
930
Ben Rombergerb7603232011-11-23 17:16:27 -0800931 pr_debug("%s\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700932 if (this_adm.apr == NULL) {
933 this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
934 0xFFFFFFFF, &this_adm);
935 if (this_adm.apr == NULL) {
936 pr_err("%s: Unable to register ADM\n", __func__);
937 ret = -ENODEV;
938 return ret;
939 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700940 rtac_set_adm_handle(this_adm.apr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700941 }
942
943 cmd_size = sizeof(struct adm_cmd_memory_map_regions)
944 + sizeof(struct adm_memory_map_regions) * bufcnt;
945
946 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
947 if (!mmap_region_cmd) {
948 pr_err("%s: allocate mmap_region_cmd failed\n", __func__);
949 return -ENOMEM;
950 }
951 mmap_regions = (struct adm_cmd_memory_map_regions *)mmap_region_cmd;
952 mmap_regions->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
953 APR_HDR_LEN(APR_HDR_SIZE),
954 APR_PKT_VER);
955 mmap_regions->hdr.pkt_size = cmd_size;
956 mmap_regions->hdr.src_port = 0;
957 mmap_regions->hdr.dest_port = 0;
958 mmap_regions->hdr.token = 0;
959 mmap_regions->hdr.opcode = ADM_CMD_MEMORY_MAP_REGIONS;
960 mmap_regions->mempool_id = mempool_id & 0x00ff;
961 mmap_regions->nregions = bufcnt & 0x00ff;
962 pr_debug("%s: map_regions->nregions = %d\n", __func__,
963 mmap_regions->nregions);
964 payload = ((u8 *) mmap_region_cmd +
965 sizeof(struct adm_cmd_memory_map_regions));
966 mregions = (struct adm_memory_map_regions *)payload;
967
968 for (i = 0; i < bufcnt; i++) {
969 mregions->phys = buf_add[i];
970 mregions->buf_size = bufsz[i];
971 ++mregions;
972 }
973
974 atomic_set(&this_adm.copp_stat[0], 0);
975 ret = apr_send_pkt(this_adm.apr, (uint32_t *) mmap_region_cmd);
976 if (ret < 0) {
977 pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
978 mmap_regions->hdr.opcode, ret);
979 ret = -EINVAL;
980 goto fail_cmd;
981 }
982
983 ret = wait_event_timeout(this_adm.wait,
984 atomic_read(&this_adm.copp_stat[0]), 5 * HZ);
985 if (!ret) {
986 pr_err("%s: timeout. waited for memory_map\n", __func__);
987 ret = -EINVAL;
988 goto fail_cmd;
989 }
990fail_cmd:
991 kfree(mmap_region_cmd);
992 return ret;
993}
994
995int adm_memory_unmap_regions(uint32_t *buf_add, uint32_t *bufsz,
996 uint32_t bufcnt)
997{
998 struct adm_cmd_memory_unmap_regions *unmap_regions = NULL;
999 struct adm_memory_unmap_regions *mregions = NULL;
1000 void *unmap_region_cmd = NULL;
1001 void *payload = NULL;
1002 int ret = 0;
1003 int i = 0;
1004 int cmd_size = 0;
1005
Ben Rombergerb7603232011-11-23 17:16:27 -08001006 pr_debug("%s\n", __func__);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001007
1008 if (this_adm.apr == NULL) {
1009 pr_err("%s APR handle NULL\n", __func__);
1010 return -EINVAL;
1011 }
1012
1013 cmd_size = sizeof(struct adm_cmd_memory_unmap_regions)
1014 + sizeof(struct adm_memory_unmap_regions) * bufcnt;
1015
1016 unmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
1017 if (!unmap_region_cmd) {
1018 pr_err("%s: allocate unmap_region_cmd failed\n", __func__);
1019 return -ENOMEM;
1020 }
1021 unmap_regions = (struct adm_cmd_memory_unmap_regions *)
1022 unmap_region_cmd;
1023 unmap_regions->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1024 APR_HDR_LEN(APR_HDR_SIZE),
1025 APR_PKT_VER);
1026 unmap_regions->hdr.pkt_size = cmd_size;
1027 unmap_regions->hdr.src_port = 0;
1028 unmap_regions->hdr.dest_port = 0;
1029 unmap_regions->hdr.token = 0;
1030 unmap_regions->hdr.opcode = ADM_CMD_MEMORY_UNMAP_REGIONS;
1031 unmap_regions->nregions = bufcnt & 0x00ff;
1032 unmap_regions->reserved = 0;
1033 pr_debug("%s: unmap_regions->nregions = %d\n", __func__,
1034 unmap_regions->nregions);
1035 payload = ((u8 *) unmap_region_cmd +
1036 sizeof(struct adm_cmd_memory_unmap_regions));
1037 mregions = (struct adm_memory_unmap_regions *)payload;
1038
1039 for (i = 0; i < bufcnt; i++) {
1040 mregions->phys = buf_add[i];
1041 ++mregions;
1042 }
1043 atomic_set(&this_adm.copp_stat[0], 0);
1044 ret = apr_send_pkt(this_adm.apr, (uint32_t *) unmap_region_cmd);
1045 if (ret < 0) {
1046 pr_err("%s: mmap_regions op[0x%x]rc[%d]\n", __func__,
1047 unmap_regions->hdr.opcode, ret);
1048 ret = -EINVAL;
1049 goto fail_cmd;
1050 }
1051
1052 ret = wait_event_timeout(this_adm.wait,
1053 atomic_read(&this_adm.copp_stat[0]), 5 * HZ);
1054 if (!ret) {
1055 pr_err("%s: timeout. waited for memory_unmap\n", __func__);
1056 ret = -EINVAL;
1057 goto fail_cmd;
1058 }
1059fail_cmd:
1060 kfree(unmap_region_cmd);
1061 return ret;
1062}
1063
Ben Romberger974a40d2011-07-18 15:08:21 -07001064int adm_get_copp_id(int port_index)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001065{
1066 pr_debug("%s\n", __func__);
1067
Ben Romberger974a40d2011-07-18 15:08:21 -07001068 if (port_index < 0) {
1069 pr_err("%s: invalid port_id = %d\n", __func__, port_index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001070 return -EINVAL;
1071 }
1072
Ben Romberger974a40d2011-07-18 15:08:21 -07001073 return atomic_read(&this_adm.copp_id[port_index]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001074}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001075
1076int adm_close(int port_id)
1077{
1078 struct apr_hdr close;
1079
1080 int ret = 0;
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301081 int index = 0;
1082
1083 port_id = afe_convert_virtual_to_portid(port_id);
1084
1085 index = afe_get_port_index(port_id);
Bharath Ramachandramurthy51a86212011-07-29 12:43:43 -07001086 if (afe_validate_port(port_id) < 0)
1087 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001088
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001089 pr_debug("%s port_id=%d index %d\n", __func__, port_id, index);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001090
1091 if (!(atomic_read(&this_adm.copp_cnt[index]))) {
1092 pr_err("%s: copp count for port[%d]is 0\n", __func__, port_id);
1093
1094 goto fail_cmd;
1095 }
1096 atomic_dec(&this_adm.copp_cnt[index]);
1097 if (!(atomic_read(&this_adm.copp_cnt[index]))) {
1098
1099 close.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1100 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1101 close.pkt_size = sizeof(close);
1102 close.src_svc = APR_SVC_ADM;
1103 close.src_domain = APR_DOMAIN_APPS;
1104 close.src_port = port_id;
1105 close.dest_svc = APR_SVC_ADM;
1106 close.dest_domain = APR_DOMAIN_ADSP;
1107 close.dest_port = atomic_read(&this_adm.copp_id[index]);
1108 close.token = port_id;
1109 close.opcode = ADM_CMD_COPP_CLOSE;
1110
1111 atomic_set(&this_adm.copp_id[index], RESET_COPP_ID);
1112 atomic_set(&this_adm.copp_stat[index], 0);
1113
1114
1115 pr_debug("%s:coppid %d portid=%d index=%d coppcnt=%d\n",
1116 __func__,
1117 atomic_read(&this_adm.copp_id[index]),
1118 port_id, index,
1119 atomic_read(&this_adm.copp_cnt[index]));
1120
1121 ret = apr_send_pkt(this_adm.apr, (uint32_t *)&close);
1122 if (ret < 0) {
1123 pr_err("%s ADM close failed\n", __func__);
1124 ret = -EINVAL;
1125 goto fail_cmd;
1126 }
1127
1128 ret = wait_event_timeout(this_adm.wait,
1129 atomic_read(&this_adm.copp_stat[index]),
1130 msecs_to_jiffies(TIMEOUT_MS));
1131 if (!ret) {
1132 pr_err("%s: ADM cmd Route failed for port %d\n",
1133 __func__, port_id);
1134 ret = -EINVAL;
1135 goto fail_cmd;
1136 }
Ben Romberger93d4d2d2011-10-19 23:04:02 -07001137
1138 rtac_remove_adm_device(port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001139 }
1140
1141fail_cmd:
1142 return ret;
1143}
1144
1145static int __init adm_init(void)
1146{
1147 int i = 0;
1148 init_waitqueue_head(&this_adm.wait);
1149 this_adm.apr = NULL;
1150
1151 for (i = 0; i < AFE_MAX_PORTS; i++) {
1152 atomic_set(&this_adm.copp_id[i], RESET_COPP_ID);
1153 atomic_set(&this_adm.copp_cnt[i], 0);
1154 atomic_set(&this_adm.copp_stat[i], 0);
1155 }
1156 return 0;
1157}
1158
1159device_initcall(adm_init);