blob: 2e58e1b255576fd981b0721b4af26f59c9db4ba0 [file] [log] [blame]
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -07001/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
2 *
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/debugfs.h>
15#include <linux/kernel.h>
16#include <linux/kthread.h>
17#include <linux/uaccess.h>
18#include <linux/wait.h>
19#include <linux/jiffies.h>
20#include <linux/sched.h>
21#include <mach/qdsp6v2/audio_acdb.h>
22#include <sound/apr_audio-v2.h>
23#include <sound/q6afe-v2.h>
24
25#include <sound/q6audio-v2.h>
26
27
28struct afe_ctl {
29 void *apr;
30 atomic_t state;
31 atomic_t status;
32 wait_queue_head_t wait[AFE_MAX_PORTS];
33 void (*tx_cb) (uint32_t opcode,
34 uint32_t token, uint32_t *payload, void *priv);
35 void (*rx_cb) (uint32_t opcode,
36 uint32_t token, uint32_t *payload, void *priv);
37 void *tx_private_data;
38 void *rx_private_data;
39};
40
41static struct afe_ctl this_afe;
42
43static struct acdb_cal_block afe_cal_addr[MAX_AUDPROC_TYPES];
44
45#define TIMEOUT_MS 1000
46#define Q6AFE_MAX_VOLUME 0x3FFF
47
48#define SIZEOF_CFG_CMD(y) \
49 (sizeof(struct apr_hdr) + sizeof(u16) + (sizeof(struct y)))
50
51static int32_t afe_callback(struct apr_client_data *data, void *priv)
52{
53 if (data->opcode == RESET_EVENTS) {
54 pr_debug("q6afe: reset event = %d %d apr[%p]\n",
55 data->reset_event, data->reset_proc, this_afe.apr);
56 if (this_afe.apr) {
57 apr_reset(this_afe.apr);
58 atomic_set(&this_afe.state, 0);
59 this_afe.apr = NULL;
60 }
61 return 0;
62 }
63 pr_debug("%s:opcode = 0x%x cmd = 0x%x status = 0x%x\n",
64 __func__, data->opcode,
65 ((uint32_t *)(data->payload))[0],
66 ((uint32_t *)(data->payload))[1]);
67 if (data->payload_size) {
68 uint32_t *payload;
69 uint16_t port_id = 0;
70 payload = data->payload;
71 pr_debug("%s:opcode = 0x%x cmd = 0x%x status = 0x%x token=%d\n",
72 __func__, data->opcode,
73 payload[0], payload[1], data->token);
74 /* payload[1] contains the error status for response */
75 if (payload[1] != 0) {
76 atomic_set(&this_afe.status, -1);
77 pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
78 __func__, payload[0], payload[1]);
79 }
80 if (data->opcode == APR_BASIC_RSP_RESULT) {
81 switch (payload[0]) {
82 case AFE_PORT_CMD_DEVICE_STOP:
83 case AFE_PORT_CMD_DEVICE_START:
84 case AFE_PORT_CMD_SET_PARAM_V2:
85 case AFE_PSEUDOPORT_CMD_START:
86 case AFE_PSEUDOPORT_CMD_STOP:
87 case AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS:
88 case AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS:
89 case AFE_SERVICE_CMD_UNREGISTER_RT_PORT_DRIVER:
90 atomic_set(&this_afe.state, 0);
91 wake_up(&this_afe.wait[data->token]);
92 break;
93 case AFE_SERVICE_CMD_REGISTER_RT_PORT_DRIVER:
94 break;
95 case AFE_PORT_DATA_CMD_RT_PROXY_PORT_WRITE_V2:
96 port_id = RT_PROXY_PORT_001_TX;
97 break;
98 case AFE_PORT_DATA_CMD_RT_PROXY_PORT_READ_V2:
99 port_id = RT_PROXY_PORT_001_RX;
100 break;
101 default:
102 pr_err("%s:Unknown cmd 0x%x\n", __func__,
103 payload[0]);
104 break;
105 }
106 } else if (data->opcode == AFE_EVENT_RT_PROXY_PORT_STATUS) {
107 port_id = (uint16_t)(0x0000FFFF & payload[0]);
108 }
109 pr_debug("%s:port_id = %x\n", __func__, port_id);
110 switch (port_id) {
111 case RT_PROXY_PORT_001_TX: {
112 if (this_afe.tx_cb) {
113 this_afe.tx_cb(data->opcode, data->token,
114 data->payload,
115 this_afe.tx_private_data);
116 }
117 break;
118 }
119 case RT_PROXY_PORT_001_RX: {
120 if (this_afe.rx_cb) {
121 this_afe.rx_cb(data->opcode, data->token,
122 data->payload,
123 this_afe.rx_private_data);
124 }
125 break;
126 }
127 default:
128 break;
129 }
130 }
131 return 0;
132}
133
134
135int afe_get_port_type(u16 port_id)
136{
137 int ret;
138
139 switch (port_id) {
140 case PRIMARY_I2S_RX:
141 case PCM_RX:
142 case SECONDARY_I2S_RX:
143 case MI2S_RX:
144 case HDMI_RX:
145 case SLIMBUS_0_RX:
146 case SLIMBUS_1_RX:
Joonwoo Park6572ac52012-07-10 17:17:00 -0700147 case SLIMBUS_2_RX:
148 case SLIMBUS_3_RX:
149 case SLIMBUS_4_RX:
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700150 case INT_BT_SCO_RX:
151 case INT_BT_A2DP_RX:
152 case INT_FM_RX:
153 case VOICE_PLAYBACK_TX:
154 case RT_PROXY_PORT_001_RX:
155 ret = MSM_AFE_PORT_TYPE_RX;
156 break;
157
158 case PRIMARY_I2S_TX:
159 case PCM_TX:
160 case SECONDARY_I2S_TX:
161 case MI2S_TX:
162 case DIGI_MIC_TX:
163 case VOICE_RECORD_TX:
164 case SLIMBUS_0_TX:
165 case SLIMBUS_1_TX:
Joonwoo Park6572ac52012-07-10 17:17:00 -0700166 case SLIMBUS_2_TX:
167 case SLIMBUS_3_TX:
168 case SLIMBUS_4_TX:
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700169 case INT_FM_TX:
170 case VOICE_RECORD_RX:
171 case INT_BT_SCO_TX:
172 case RT_PROXY_PORT_001_TX:
173 ret = MSM_AFE_PORT_TYPE_TX;
174 break;
175
176 default:
Joonwoo Park6572ac52012-07-10 17:17:00 -0700177 WARN_ON(1);
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700178 pr_err("%s: invalid port id %d\n", __func__, port_id);
179 ret = -EINVAL;
180 }
181
182 return ret;
183}
184
185int afe_sizeof_cfg_cmd(u16 port_id)
186{
187 int ret_size;
188 switch (port_id) {
189 case PRIMARY_I2S_RX:
190 case PRIMARY_I2S_TX:
191 case SECONDARY_I2S_RX:
192 case SECONDARY_I2S_TX:
193 case MI2S_RX:
194 case MI2S_TX:
195 ret_size = SIZEOF_CFG_CMD(afe_param_id_i2s_cfg);
196 break;
197 case HDMI_RX:
198 ret_size =
199 SIZEOF_CFG_CMD(afe_param_id_hdmi_multi_chan_audio_cfg);
200 break;
201 case SLIMBUS_0_RX:
202 case SLIMBUS_0_TX:
203 case SLIMBUS_1_RX:
204 case SLIMBUS_1_TX:
205 ret_size = SIZEOF_CFG_CMD(afe_param_id_slimbus_cfg);
206 break;
207 case RT_PROXY_PORT_001_RX:
208 case RT_PROXY_PORT_001_TX:
209 ret_size = SIZEOF_CFG_CMD(afe_param_id_rt_proxy_port_cfg);
210 break;
211 case PCM_RX:
212 case PCM_TX:
213 default:
214 ret_size = SIZEOF_CFG_CMD(afe_param_id_pcm_cfg);
215 break;
216 }
217 return ret_size;
218}
219
220int afe_q6_interface_prepare(void)
221{
222 int ret = 0;
223
224 pr_debug("%s:", __func__);
225
226 if (this_afe.apr == NULL) {
227 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
228 0xFFFFFFFF, &this_afe);
229 if (this_afe.apr == NULL) {
230 pr_err("%s: Unable to register AFE\n", __func__);
231 ret = -ENODEV;
232 }
233 }
234 return ret;
235}
236static void afe_send_cal_block(int32_t path, u16 port_id)
237{
238 /* To come back */
239}
240
241void afe_send_cal(u16 port_id)
242{
243 pr_debug("%s\n", __func__);
244
245 if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX)
246 afe_send_cal_block(TX_CAL, port_id);
247 else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX)
248 afe_send_cal_block(RX_CAL, port_id);
249}
250
251int afe_port_start_nowait(u16 port_id, union afe_port_config *afe_config,
252 u32 rate) /* This function is no blocking */
253{
254 struct afe_port_cmd_device_start start;
255 struct afe_audioif_config_command config;
256 int ret;
257 int cfg_type;
258 int index = 0;
259
260 if (!afe_config) {
261 pr_err("%s: Error, no configuration data\n", __func__);
262 ret = -EINVAL;
263 return ret;
264 }
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700265 index = q6audio_get_port_index(port_id);
266 if (q6audio_validate_port(port_id) < 0)
267 return -EINVAL;
268
269 if ((port_id == RT_PROXY_DAI_001_RX) ||
270 (port_id == RT_PROXY_DAI_002_TX))
271 return -EINVAL;
272 if ((port_id == RT_PROXY_DAI_002_RX) ||
273 (port_id == RT_PROXY_DAI_001_TX))
274 port_id = VIRTUAL_ID_TO_PORTID(port_id);
275
276 ret = afe_q6_interface_prepare();
277 if (ret != 0)
278 return ret;
279 if (q6audio_validate_port(port_id) < 0) {
280 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
281 port_id);
282 ret = -EINVAL;
283 goto fail_cmd;
284 }
285
286 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
287 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
Joonwoo Park6572ac52012-07-10 17:17:00 -0700288 config.hdr.pkt_size = sizeof(config);
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700289 config.hdr.src_port = 0;
290 config.hdr.dest_port = 0;
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700291 config.hdr.token = index;
Joonwoo Park6572ac52012-07-10 17:17:00 -0700292
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700293 switch (port_id) {
294 case PRIMARY_I2S_RX:
295 case PRIMARY_I2S_TX:
296 cfg_type = AFE_PARAM_ID_PCM_CONFIG;
297 break;
298 case PCM_RX:
299 case PCM_TX:
300 cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
301 break;
302 case SECONDARY_I2S_RX:
303 case SECONDARY_I2S_TX:
304 case MI2S_RX:
305 case MI2S_TX:
306 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
307 break;
308 case HDMI_RX:
309 cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
310 break;
311 case SLIMBUS_0_RX:
312 case SLIMBUS_0_TX:
313 case SLIMBUS_1_RX:
314 case SLIMBUS_1_TX:
315 case SLIMBUS_2_RX:
316 case SLIMBUS_2_TX:
317 case SLIMBUS_3_RX:
318 case SLIMBUS_3_TX:
319 case SLIMBUS_4_RX:
320 case SLIMBUS_4_TX:
321 cfg_type = AFE_PARAM_ID_SLIMBUS_CONFIG;
322 break;
323 default:
324 pr_err("%s: Invalid port id 0x%x\n", __func__, port_id);
325 ret = -EINVAL;
326 goto fail_cmd;
327 }
328 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
Joonwoo Park6572ac52012-07-10 17:17:00 -0700329 config.param.port_id = q6audio_get_port_id(port_id);
330 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
331 sizeof(config.param);
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700332 config.param.payload_address_lsw = 0x00;
333 config.param.payload_address_msw = 0x00;
334 config.param.mem_map_handle = 0x00;
335 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
336 config.pdata.param_id = cfg_type;
Joonwoo Park6572ac52012-07-10 17:17:00 -0700337 config.pdata.param_size = sizeof(config.port);
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700338
339 config.port = *afe_config;
340
341 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
342 if (ret < 0) {
343 pr_err("%s: AFE enable for port %d failed\n", __func__,
344 port_id);
345 ret = -EINVAL;
346 goto fail_cmd;
347 }
348
349 /* send AFE cal */
350 afe_send_cal(port_id);
351
352 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
353 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
354 start.hdr.pkt_size = sizeof(start);
355 start.hdr.src_port = 0;
356 start.hdr.dest_port = 0;
Joonwoo Park6572ac52012-07-10 17:17:00 -0700357 start.hdr.token = index;
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700358 start.hdr.opcode = AFE_PORT_CMD_DEVICE_START;
Joonwoo Park6572ac52012-07-10 17:17:00 -0700359 start.port_id = q6audio_get_port_id(port_id);
360 pr_debug("%s: cmd device start opcode[0x%x] port id[0x%x]\n",
361 __func__, start.hdr.opcode, start.port_id);
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700362
363 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
364
365 if (IS_ERR_VALUE(ret)) {
366 pr_err("%s: AFE enable for port %d failed\n", __func__,
367 port_id);
368 ret = -EINVAL;
369 goto fail_cmd;
370 }
371
372 return 0;
373
374fail_cmd:
375 return ret;
376}
377
Joonwoo Park6572ac52012-07-10 17:17:00 -0700378int afe_get_port_index(u16 port_id)
379{
380 switch (port_id) {
381 case PRIMARY_I2S_RX: return IDX_PRIMARY_I2S_RX;
382 case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
383 case PCM_RX: return IDX_PCM_RX;
384 case PCM_TX: return IDX_PCM_TX;
385 case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
386 case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
387 case MI2S_RX: return IDX_MI2S_RX;
388 case MI2S_TX: return IDX_MI2S_TX;
389 case HDMI_RX: return IDX_HDMI_RX;
390 case RSVD_2: return IDX_RSVD_2;
391 case RSVD_3: return IDX_RSVD_3;
392 case DIGI_MIC_TX: return IDX_DIGI_MIC_TX;
393 case VOICE_RECORD_RX: return IDX_VOICE_RECORD_RX;
394 case VOICE_RECORD_TX: return IDX_VOICE_RECORD_TX;
395 case VOICE_PLAYBACK_TX: return IDX_VOICE_PLAYBACK_TX;
396 case SLIMBUS_0_RX: return IDX_SLIMBUS_0_RX;
397 case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
398 case SLIMBUS_1_RX: return IDX_SLIMBUS_1_RX;
399 case SLIMBUS_1_TX: return IDX_SLIMBUS_1_TX;
400 case SLIMBUS_2_RX: return IDX_SLIMBUS_2_RX;
401 case SLIMBUS_2_TX: return IDX_SLIMBUS_2_TX;
402 case SLIMBUS_3_RX: return IDX_SLIMBUS_3_RX;
403 case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
404 case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
405 case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
406 case INT_FM_RX: return IDX_INT_FM_RX;
407 case INT_FM_TX: return IDX_INT_FM_TX;
408 case RT_PROXY_PORT_001_RX: return IDX_RT_PROXY_PORT_001_RX;
409 case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
410 case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX;
411 case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
412
413 default: return -EINVAL;
414 }
415}
416
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700417int afe_open(u16 port_id,
418 union afe_port_config *afe_config, int rate)
419{
420 struct afe_port_cmd_device_start start;
421 struct afe_audioif_config_command config;
422 int ret = 0;
423 int cfg_type;
424 int index = 0;
425
426 if (!afe_config) {
427 pr_err("%s: Error, no configuration data\n", __func__);
428 ret = -EINVAL;
429 return ret;
430 }
431
432 pr_err("%s: %d %d\n", __func__, port_id, rate);
433
434 index = q6audio_get_port_index(port_id);
435 if (q6audio_validate_port(port_id) < 0)
436 return -EINVAL;
437
438 if ((port_id == RT_PROXY_DAI_001_RX) ||
439 (port_id == RT_PROXY_DAI_002_TX))
440 return -EINVAL;
441 if ((port_id == RT_PROXY_DAI_002_RX) ||
442 (port_id == RT_PROXY_DAI_001_TX))
443 port_id = VIRTUAL_ID_TO_PORTID(port_id);
444
445 ret = afe_q6_interface_prepare();
446 if (ret != 0)
447 return ret;
448
449 if (q6audio_validate_port(port_id) < 0) {
450 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
451 port_id);
452 ret = -EINVAL;
453 goto fail_cmd;
454 }
455
456 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
457 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
458 config.hdr.pkt_size = sizeof(config);
459 config.hdr.src_port = 0;
460 config.hdr.dest_port = 0;
461 config.hdr.token = index;
462 switch (port_id) {
463 case PRIMARY_I2S_RX:
464 case PRIMARY_I2S_TX:
465 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
466 break;
467 case PCM_RX:
468 case PCM_TX:
469 cfg_type = AFE_PARAM_ID_PCM_CONFIG;
470 break;
471 case SECONDARY_I2S_RX:
472 case SECONDARY_I2S_TX:
473 case MI2S_RX:
474 case MI2S_TX:
475 cfg_type = AFE_PARAM_ID_I2S_CONFIG;
476 break;
477 case HDMI_RX:
478 cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
479 break;
480 case SLIMBUS_0_RX:
481 case SLIMBUS_0_TX:
482 case SLIMBUS_1_RX:
483 case SLIMBUS_1_TX:
484 case SLIMBUS_2_RX:
485 case SLIMBUS_2_TX:
486 case SLIMBUS_3_RX:
487 case SLIMBUS_3_TX:
488 case SLIMBUS_4_RX:
489 case SLIMBUS_4_TX:
490 cfg_type = AFE_PARAM_ID_SLIMBUS_CONFIG;
491 break;
492 default:
493 pr_err("%s: Invalid port id 0x%x\n", __func__, port_id);
494 ret = -EINVAL;
495 goto fail_cmd;
496 }
497 config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
498 config.param.port_id = q6audio_get_port_id(port_id);
499 config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr)
500 - sizeof(config.param);
501 config.param.payload_address_lsw = 0x00;
502 config.param.payload_address_msw = 0x00;
503 config.param.mem_map_handle = 0x00;
504 config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
505 config.pdata.param_id = cfg_type;
506 config.pdata.param_size = sizeof(config.port);
507
508 config.port = *afe_config;
509 pr_debug("%s: param PL size=%d iparam_size[%d][%d %d %d %d]"
510 " param_id[%x]\n",
511 __func__, config.param.payload_size, config.pdata.param_size,
512 sizeof(config), sizeof(config.param), sizeof(config.port),
513 sizeof(struct apr_hdr), config.pdata.param_id);
514 atomic_set(&this_afe.state, 1);
515 atomic_set(&this_afe.status, 0);
516 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
517 if (ret < 0) {
518 pr_err("%s: AFE enable for port %d opcode[0x%x]failed\n",
519 __func__, port_id, cfg_type);
520 ret = -EINVAL;
521 goto fail_cmd;
522 }
523
524 ret = wait_event_timeout(this_afe.wait[index],
525 (atomic_read(&this_afe.state) == 0),
526 msecs_to_jiffies(TIMEOUT_MS));
527 if (!ret) {
528 pr_err("%s: wait_event timeout\n", __func__);
529 ret = -EINVAL;
530 goto fail_cmd;
531 }
532 if (atomic_read(&this_afe.status) != 0) {
533 pr_err("%s: config cmd failed\n", __func__);
534 ret = -EINVAL;
535 goto fail_cmd;
536 }
537 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
538 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
539 start.hdr.pkt_size = sizeof(start);
540 start.hdr.src_port = 0;
541 start.hdr.dest_port = 0;
542 start.hdr.token = index;
543 start.hdr.opcode = AFE_PORT_CMD_DEVICE_START;
544 start.port_id = q6audio_get_port_id(port_id);
545 pr_debug("%s: cmd device start opcode[0x%x] port id[0x%x]\n",
546 __func__, start.hdr.opcode, start.port_id);
547 atomic_set(&this_afe.state, 1);
548 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
549 if (ret < 0) {
550 pr_err("%s: AFE enable for port %d failed\n", __func__,
551 port_id);
552 ret = -EINVAL;
553 goto fail_cmd;
554 }
555 ret = wait_event_timeout(this_afe.wait[index],
556 (atomic_read(&this_afe.state) == 0),
557 msecs_to_jiffies(TIMEOUT_MS));
558 if (!ret) {
559 pr_err("%s: wait_event timeout\n", __func__);
560 ret = -EINVAL;
561 goto fail_cmd;
562 }
563
564 return 0;
565fail_cmd:
566 return ret;
567}
568
569int afe_loopback(u16 enable, u16 rx_port, u16 tx_port)
570{
571 struct afe_loopback_cfg_v1 lb_cmd;
572 int ret = 0;
573 int index = 0;
574
575 ret = afe_q6_interface_prepare();
576 if (ret != 0)
577 return ret;
578
579 index = q6audio_get_port_index(rx_port);
580 if (q6audio_validate_port(rx_port) < 0)
581 return -EINVAL;
582
583 lb_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
584 APR_HDR_LEN(20), APR_PKT_VER);
585 lb_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
586 sizeof(lb_cmd) - APR_HDR_SIZE);
587 lb_cmd.hdr.src_port = 0;
588 lb_cmd.hdr.dest_port = 0;
Joonwoo Parkc76ad882012-08-14 18:05:33 -0700589 lb_cmd.hdr.token = index;
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700590 lb_cmd.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
591 lb_cmd.param.port_id = tx_port;
Joonwoo Parkc76ad882012-08-14 18:05:33 -0700592 lb_cmd.param.payload_size = (sizeof(lb_cmd) - sizeof(struct apr_hdr) -
593 sizeof(struct afe_port_cmd_set_param_v2));
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700594 lb_cmd.param.payload_address_lsw = 0x00;
595 lb_cmd.param.payload_address_msw = 0x00;
596 lb_cmd.param.mem_map_handle = 0x00;
597 lb_cmd.pdata.module_id = AFE_MODULE_LOOPBACK;
598 lb_cmd.pdata.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
Joonwoo Parkc76ad882012-08-14 18:05:33 -0700599 lb_cmd.pdata.param_size = lb_cmd.param.payload_size -
600 sizeof(struct afe_port_param_data_v2);
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700601
602 lb_cmd.dst_port_id = rx_port;
603 lb_cmd.routing_mode = LB_MODE_DEFAULT;
604 lb_cmd.enable = (enable ? 1 : 0);
Joonwoo Parkc76ad882012-08-14 18:05:33 -0700605 lb_cmd.loopback_cfg_minor_version = AFE_API_VERSION_LOOPBACK_CONFIG;
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700606 atomic_set(&this_afe.state, 1);
607
608 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &lb_cmd);
609 if (ret < 0) {
610 pr_err("%s: AFE loopback failed\n", __func__);
611 ret = -EINVAL;
612 goto done;
613 }
Joonwoo Parkc76ad882012-08-14 18:05:33 -0700614 pr_debug("%s: waiting for this_afe.wait[%d]\n", __func__, index);
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700615 ret = wait_event_timeout(this_afe.wait[index],
Joonwoo Parkc76ad882012-08-14 18:05:33 -0700616 (atomic_read(&this_afe.state) == 0),
617 msecs_to_jiffies(TIMEOUT_MS));
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700618 if (!ret) {
619 pr_err("%s: wait_event timeout\n", __func__);
620 ret = -EINVAL;
621 }
622done:
623 return ret;
624}
625
626int afe_loopback_gain(u16 port_id, u16 volume)
627{
628 struct afe_loopback_gain_per_path_param set_param;
629 int ret = 0;
630 int index = 0;
631
632 if (this_afe.apr == NULL) {
633 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
634 0xFFFFFFFF, &this_afe);
635 pr_debug("%s: Register AFE\n", __func__);
636 if (this_afe.apr == NULL) {
637 pr_err("%s: Unable to register AFE\n", __func__);
638 ret = -ENODEV;
639 return ret;
640 }
641 }
642
643 if (q6audio_validate_port(port_id) < 0) {
644
645 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
646 port_id);
647 ret = -EINVAL;
648 goto fail_cmd;
649 }
650 index = q6audio_get_port_index(port_id);
651 if (q6audio_validate_port(port_id) < 0)
652 return -EINVAL;
653
654 /* RX ports numbers are even .TX ports numbers are odd. */
655 if (port_id % 2 == 0) {
656 pr_err("%s: Failed : afe loopback gain only for TX ports."
657 " port_id %d\n", __func__, port_id);
658 ret = -EINVAL;
659 goto fail_cmd;
660 }
661
662 pr_debug("%s: %d %hX\n", __func__, port_id, volume);
663
664 set_param.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
665 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
666 set_param.hdr.pkt_size = sizeof(set_param);
667 set_param.hdr.src_port = 0;
668 set_param.hdr.dest_port = 0;
Joonwoo Parkc76ad882012-08-14 18:05:33 -0700669 set_param.hdr.token = index;
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700670 set_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
671
Joonwoo Parkc76ad882012-08-14 18:05:33 -0700672 set_param.param.port_id = port_id;
673 set_param.param.payload_size =
674 (sizeof(struct afe_loopback_gain_per_path_param) -
675 sizeof(struct apr_hdr) - sizeof(struct afe_port_cmd_set_param_v2));
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700676 set_param.param.payload_address_lsw = 0;
677 set_param.param.payload_address_msw = 0;
678 set_param.param.mem_map_handle = 0;
679
Joonwoo Parkc76ad882012-08-14 18:05:33 -0700680 set_param.pdata.module_id = AFE_MODULE_LOOPBACK;
681 set_param.pdata.param_id = AFE_PARAM_ID_LOOPBACK_GAIN_PER_PATH;
682 set_param.pdata.param_size =
683 (set_param.param.payload_size -
684 sizeof(struct afe_port_param_data_v2));
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700685 set_param.rx_port_id = port_id;
Joonwoo Parkc76ad882012-08-14 18:05:33 -0700686 set_param.gain = volume;
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700687
688 atomic_set(&this_afe.state, 1);
689 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_param);
690 if (ret < 0) {
691 pr_err("%s: AFE param set failed for port %d\n",
692 __func__, port_id);
693 ret = -EINVAL;
694 goto fail_cmd;
695 }
696
697 ret = wait_event_timeout(this_afe.wait[index],
Joonwoo Parkc76ad882012-08-14 18:05:33 -0700698 (atomic_read(&this_afe.state) == 0),
699 msecs_to_jiffies(TIMEOUT_MS));
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700700 if (ret < 0) {
701 pr_err("%s: wait_event timeout\n", __func__);
702 ret = -EINVAL;
703 goto fail_cmd;
704 }
705 return 0;
706fail_cmd:
707 return ret;
708}
709
710int afe_pseudo_port_start_nowait(u16 port_id)
711{
712 struct afe_pseudoport_start_command start;
713 int ret = 0;
714
715 pr_debug("%s: port_id=%d\n", __func__, port_id);
716 if (this_afe.apr == NULL) {
717 pr_err("%s: AFE APR is not registered\n", __func__);
718 return -ENODEV;
719 }
720
721
722 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
723 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
724 start.hdr.pkt_size = sizeof(start);
725 start.hdr.src_port = 0;
726 start.hdr.dest_port = 0;
727 start.hdr.token = 0;
728 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
729 start.port_id = port_id;
730 start.timing = 1;
731
732 atomic_set(&this_afe.state, 1);
733 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
734 if (ret < 0) {
735 pr_err("%s: AFE enable for port %d failed %d\n",
736 __func__, port_id, ret);
737 return -EINVAL;
738 }
739 return 0;
740}
741
742int afe_start_pseudo_port(u16 port_id)
743{
744 int ret = 0;
745 struct afe_pseudoport_start_command start;
746 int index = 0;
747
748 pr_debug("%s: port_id=%d\n", __func__, port_id);
749
750 ret = afe_q6_interface_prepare();
751 if (ret != 0)
752 return ret;
753
754 index = q6audio_get_port_index(port_id);
755 if (q6audio_validate_port(port_id) < 0)
756 return -EINVAL;
757
758 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
759 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
760 start.hdr.pkt_size = sizeof(start);
761 start.hdr.src_port = 0;
762 start.hdr.dest_port = 0;
763 start.hdr.token = 0;
764 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
765 start.port_id = port_id;
766 start.timing = 1;
767
768 start.hdr.token = index;
769 atomic_set(&this_afe.state, 1);
770 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
771 if (ret < 0) {
772 pr_err("%s: AFE enable for port %d failed %d\n",
773 __func__, port_id, ret);
774 return -EINVAL;
775 }
776
777 ret = wait_event_timeout(this_afe.wait[index],
778 (atomic_read(&this_afe.state) == 0),
779 msecs_to_jiffies(TIMEOUT_MS));
780 if (!ret) {
781 pr_err("%s: wait_event timeout\n", __func__);
782 return -EINVAL;
783 }
784
785 return 0;
786}
787
788int afe_pseudo_port_stop_nowait(u16 port_id)
789{
790 int ret = 0;
791 struct afe_pseudoport_stop_command stop;
792 int index = 0;
793
794 pr_debug("%s: port_id=%d\n", __func__, port_id);
795
796 if (this_afe.apr == NULL) {
797 pr_err("%s: AFE is already closed\n", __func__);
798 return -EINVAL;
799 }
800 index = q6audio_get_port_index(port_id);
801 if (q6audio_validate_port(port_id) < 0)
802 return -EINVAL;
803
804 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
805 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
806 stop.hdr.pkt_size = sizeof(stop);
807 stop.hdr.src_port = 0;
808 stop.hdr.dest_port = 0;
809 stop.hdr.token = 0;
810 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
811 stop.port_id = port_id;
812 stop.reserved = 0;
813
814 stop.hdr.token = index;
815 atomic_set(&this_afe.state, 1);
816 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
817 if (ret < 0) {
818 pr_err("%s: AFE close failed %d\n", __func__, ret);
819 return -EINVAL;
820 }
821
822 return 0;
823
824}
825
826int afe_stop_pseudo_port(u16 port_id)
827{
828 int ret = 0;
829 struct afe_pseudoport_stop_command stop;
830 int index = 0;
831
832 pr_debug("%s: port_id=%d\n", __func__, port_id);
833
834 if (this_afe.apr == NULL) {
835 pr_err("%s: AFE is already closed\n", __func__);
836 return -EINVAL;
837 }
838
839 index = q6audio_get_port_index(port_id);
840 if (q6audio_validate_port(port_id) < 0)
841 return -EINVAL;
842
843 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
844 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
845 stop.hdr.pkt_size = sizeof(stop);
846 stop.hdr.src_port = 0;
847 stop.hdr.dest_port = 0;
848 stop.hdr.token = 0;
849 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
850 stop.port_id = port_id;
851 stop.reserved = 0;
852
853 stop.hdr.token = index;
854 atomic_set(&this_afe.state, 1);
855 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
856 if (ret < 0) {
857 pr_err("%s: AFE close failed %d\n", __func__, ret);
858 return -EINVAL;
859 }
860
861 ret = wait_event_timeout(this_afe.wait[index],
862 (atomic_read(&this_afe.state) == 0),
863 msecs_to_jiffies(TIMEOUT_MS));
864 if (!ret) {
865 pr_err("%s: wait_event timeout\n", __func__);
866 return -EINVAL;
867 }
868
869 return 0;
870}
871
872/*bharath, memory map handle needs to be stored by AFE client */
873int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz)
874{
875 int ret = 0;
876 int cmd_size = 0;
877 void *payload = NULL;
878 void *mmap_region_cmd = NULL;
879 struct afe_service_cmd_shared_mem_map_regions *mregion = NULL;
880 struct afe_service_shared_map_region_payload *mregion_pl = NULL;
881 int index = 0;
882
883 pr_debug("%s:\n", __func__);
884
885 if (this_afe.apr == NULL) {
886 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
887 0xFFFFFFFF, &this_afe);
888 pr_debug("%s: Register AFE\n", __func__);
889 if (this_afe.apr == NULL) {
890 pr_err("%s: Unable to register AFE\n", __func__);
891 ret = -ENODEV;
892 return ret;
893 }
894 }
895
896 cmd_size = sizeof(struct afe_service_cmd_shared_mem_map_regions) \
897 + sizeof(struct afe_service_shared_map_region_payload);
898
899 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
900 if (!mmap_region_cmd) {
901 pr_err("%s: allocate mmap_region_cmd failed\n", __func__);
902 return -ENOMEM;
903 }
904
905 mregion = (struct afe_service_cmd_shared_mem_map_regions *)
906 mmap_region_cmd;
907 mregion->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
908 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
909 mregion->hdr.pkt_size = sizeof(mregion);
910 mregion->hdr.src_port = 0;
911 mregion->hdr.dest_port = 0;
912 mregion->hdr.token = 0;
913 mregion->hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS;
Harmandeep Singhac1671b2012-06-22 15:34:45 -0700914 mregion->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700915 mregion->num_regions = 1;
916 mregion->property_flag = 0x00;
917 /* Todo */
918 index = mregion->hdr.token = IDX_RSVD_2;
919
920 payload = ((u8 *) mmap_region_cmd +
921 sizeof(struct afe_service_cmd_shared_mem_map_regions));
922
923 mregion_pl = (struct afe_service_shared_map_region_payload *)payload;
924
925 mregion_pl->shm_addr_lsw = dma_addr_p;
926 mregion_pl->shm_addr_msw = 0x00;
927 mregion_pl->mem_size_bytes = dma_buf_sz;
928
929 atomic_set(&this_afe.state, 1);
930 ret = apr_send_pkt(this_afe.apr, (uint32_t *) mmap_region_cmd);
931 if (ret < 0) {
932 pr_err("%s: AFE memory map cmd failed %d\n",
933 __func__, ret);
934 ret = -EINVAL;
935 return ret;
936 }
937
938 ret = wait_event_timeout(this_afe.wait[index],
939 (atomic_read(&this_afe.state) == 0),
940 msecs_to_jiffies(TIMEOUT_MS));
941 if (!ret) {
942 pr_err("%s: wait_event timeout\n", __func__);
943 ret = -EINVAL;
944 return ret;
945 }
946
947 return 0;
948}
949
950int afe_cmd_memory_map_nowait(int port_id, u32 dma_addr_p, u32 dma_buf_sz)
951{
952 int ret = 0;
953 int cmd_size = 0;
954 void *payload = NULL;
955 void *mmap_region_cmd = NULL;
956 struct afe_service_cmd_shared_mem_map_regions *mregion = NULL;
957 struct afe_service_shared_map_region_payload *mregion_pl = NULL;
958 int index = 0;
959
960 pr_debug("%s:\n", __func__);
961
962 if (this_afe.apr == NULL) {
963 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
964 0xFFFFFFFF, &this_afe);
965 pr_debug("%s: Register AFE\n", __func__);
966 if (this_afe.apr == NULL) {
967 pr_err("%s: Unable to register AFE\n", __func__);
968 ret = -ENODEV;
969 return ret;
970 }
971 }
972 index = q6audio_get_port_index(port_id);
973 if (q6audio_validate_port(port_id) < 0)
974 return -EINVAL;
975
976 cmd_size = sizeof(struct afe_service_cmd_shared_mem_map_regions)
977 + sizeof(struct afe_service_shared_map_region_payload);
978
979 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
980 if (!mmap_region_cmd) {
981 pr_err("%s: allocate mmap_region_cmd failed\n", __func__);
982 return -ENOMEM;
983 }
984 mregion = (struct afe_service_cmd_shared_mem_map_regions *)
985 mmap_region_cmd;
986 mregion->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
987 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
988 mregion->hdr.pkt_size = sizeof(mregion);
989 mregion->hdr.src_port = 0;
990 mregion->hdr.dest_port = 0;
991 mregion->hdr.token = 0;
992 mregion->hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS;
Harmandeep Singhac1671b2012-06-22 15:34:45 -0700993 mregion->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700994 mregion->num_regions = 1;
995 mregion->property_flag = 0x00;
996
997 payload = ((u8 *) mmap_region_cmd +
998 sizeof(struct afe_service_cmd_shared_mem_map_regions));
999 mregion_pl = (struct afe_service_shared_map_region_payload *)payload;
1000
1001 mregion_pl->shm_addr_lsw = dma_addr_p;
1002 mregion_pl->shm_addr_msw = 0x00;
1003 mregion_pl->mem_size_bytes = dma_buf_sz;
1004
1005 atomic_set(&this_afe.state, 1);
1006 ret = apr_send_pkt(this_afe.apr, (uint32_t *) mmap_region_cmd);
1007 if (ret < 0) {
1008 pr_err("%s: AFE memory map cmd failed %d\n",
1009 __func__, ret);
1010 ret = -EINVAL;
1011 return ret;
1012 }
1013 return 0;
1014}
1015
1016int afe_cmd_memory_unmap(u32 mem_map_handle)
1017{
1018 int ret = 0;
1019 struct afe_service_cmd_shared_mem_unmap_regions mregion;
1020 int index = 0;
1021
1022 pr_debug("%s:\n", __func__);
1023
1024 if (this_afe.apr == NULL) {
1025 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1026 0xFFFFFFFF, &this_afe);
1027 pr_debug("%s: Register AFE\n", __func__);
1028 if (this_afe.apr == NULL) {
1029 pr_err("%s: Unable to register AFE\n", __func__);
1030 ret = -ENODEV;
1031 return ret;
1032 }
1033 }
1034
1035 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1036 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1037 mregion.hdr.pkt_size = sizeof(mregion);
1038 mregion.hdr.src_port = 0;
1039 mregion.hdr.dest_port = 0;
1040 mregion.hdr.token = 0;
1041 mregion.hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS;
1042 mregion.mem_map_handle = mem_map_handle;
1043
1044 /* Todo */
1045 index = mregion.hdr.token = IDX_RSVD_2;
1046
1047 atomic_set(&this_afe.state, 1);
1048 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1049 if (ret < 0) {
1050 pr_err("%s: AFE memory unmap cmd failed %d\n",
1051 __func__, ret);
1052 ret = -EINVAL;
1053 return ret;
1054 }
1055
1056 ret = wait_event_timeout(this_afe.wait[index],
1057 (atomic_read(&this_afe.state) == 0),
1058 msecs_to_jiffies(TIMEOUT_MS));
1059 if (!ret) {
1060 pr_err("%s: wait_event timeout\n", __func__);
1061 ret = -EINVAL;
1062 return ret;
1063 }
1064 return 0;
1065}
1066
1067int afe_cmd_memory_unmap_nowait(u32 mem_map_handle)
1068{
1069 int ret = 0;
1070 struct afe_service_cmd_shared_mem_unmap_regions mregion;
1071
1072 pr_debug("%s:\n", __func__);
1073
1074 if (this_afe.apr == NULL) {
1075 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1076 0xFFFFFFFF, &this_afe);
1077 pr_debug("%s: Register AFE\n", __func__);
1078 if (this_afe.apr == NULL) {
1079 pr_err("%s: Unable to register AFE\n", __func__);
1080 ret = -ENODEV;
1081 return ret;
1082 }
1083 }
1084
1085 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1086 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1087 mregion.hdr.pkt_size = sizeof(mregion);
1088 mregion.hdr.src_port = 0;
1089 mregion.hdr.dest_port = 0;
1090 mregion.hdr.token = 0;
1091 mregion.hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS;
1092 mregion.mem_map_handle = mem_map_handle;
1093
1094 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1095 if (ret < 0) {
1096 pr_err("%s: AFE memory unmap cmd failed %d\n",
1097 __func__, ret);
1098 ret = -EINVAL;
1099 }
1100 return 0;
1101}
1102
1103int afe_register_get_events(u16 port_id,
1104 void (*cb) (uint32_t opcode,
1105 uint32_t token, uint32_t *payload, void *priv),
1106 void *private_data)
1107{
1108 int ret = 0;
1109 struct afe_service_cmd_register_rt_port_driver rtproxy;
1110
1111 pr_debug("%s:\n", __func__);
1112
1113 if (this_afe.apr == NULL) {
1114 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1115 0xFFFFFFFF, &this_afe);
1116 pr_debug("%s: Register AFE\n", __func__);
1117 if (this_afe.apr == NULL) {
1118 pr_err("%s: Unable to register AFE\n", __func__);
1119 ret = -ENODEV;
1120 return ret;
1121 }
1122 }
1123 if ((port_id == RT_PROXY_DAI_002_RX) ||
1124 (port_id == RT_PROXY_DAI_001_TX))
1125 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1126 else
1127 return -EINVAL;
1128
1129 if (port_id == RT_PROXY_PORT_001_TX) {
1130 this_afe.tx_cb = cb;
1131 this_afe.tx_private_data = private_data;
1132 } else if (port_id == RT_PROXY_PORT_001_RX) {
1133 this_afe.rx_cb = cb;
1134 this_afe.rx_private_data = private_data;
1135 }
1136
1137 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1138 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1139 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1140 rtproxy.hdr.src_port = 1;
1141 rtproxy.hdr.dest_port = 1;
1142 rtproxy.hdr.opcode = AFE_SERVICE_CMD_REGISTER_RT_PORT_DRIVER;
1143 rtproxy.port_id = port_id;
1144 rtproxy.reserved = 0;
1145
1146 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1147 if (ret < 0) {
1148 pr_err("%s: AFE reg. rtproxy_event failed %d\n",
1149 __func__, ret);
1150 ret = -EINVAL;
1151 return ret;
1152 }
1153 return 0;
1154}
1155
1156int afe_unregister_get_events(u16 port_id)
1157{
1158 int ret = 0;
1159 struct afe_service_cmd_unregister_rt_port_driver rtproxy;
1160 int index = 0;
1161
1162 pr_debug("%s:\n", __func__);
1163
1164 if (this_afe.apr == NULL) {
1165 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1166 0xFFFFFFFF, &this_afe);
1167 pr_debug("%s: Register AFE\n", __func__);
1168 if (this_afe.apr == NULL) {
1169 pr_err("%s: Unable to register AFE\n", __func__);
1170 ret = -ENODEV;
1171 return ret;
1172 }
1173 }
1174 index = q6audio_get_port_index(port_id);
1175 if (q6audio_validate_port(port_id) < 0)
1176 return -EINVAL;
1177
1178 if ((port_id == RT_PROXY_DAI_002_RX) ||
1179 (port_id == RT_PROXY_DAI_001_TX))
1180 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1181 else
1182 return -EINVAL;
1183
1184 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1185 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1186 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1187 rtproxy.hdr.src_port = 0;
1188 rtproxy.hdr.dest_port = 0;
1189 rtproxy.hdr.token = 0;
1190 rtproxy.hdr.opcode = AFE_SERVICE_CMD_UNREGISTER_RT_PORT_DRIVER;
1191 rtproxy.port_id = port_id;
1192 rtproxy.reserved = 0;
1193
1194 rtproxy.hdr.token = index;
1195
1196 if (port_id == RT_PROXY_PORT_001_TX) {
1197 this_afe.tx_cb = NULL;
1198 this_afe.tx_private_data = NULL;
1199 } else if (port_id == RT_PROXY_PORT_001_RX) {
1200 this_afe.rx_cb = NULL;
1201 this_afe.rx_private_data = NULL;
1202 }
1203
1204 atomic_set(&this_afe.state, 1);
1205 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1206 if (ret < 0) {
1207 pr_err("%s: AFE enable Unreg. rtproxy_event failed %d\n",
1208 __func__, ret);
1209 ret = -EINVAL;
1210 return ret;
1211 }
1212
1213 ret = wait_event_timeout(this_afe.wait[index],
1214 (atomic_read(&this_afe.state) == 0),
1215 msecs_to_jiffies(TIMEOUT_MS));
1216 if (!ret) {
1217 pr_err("%s: wait_event timeout\n", __func__);
1218 ret = -EINVAL;
1219 return ret;
1220 }
1221 return 0;
1222}
1223
1224int afe_rt_proxy_port_write(u32 buf_addr_p, u32 mem_map_handle, int bytes)
1225{
1226 int ret = 0;
1227 struct afe_port_data_cmd_rt_proxy_port_write_v2 afecmd_wr;
1228
1229 if (this_afe.apr == NULL) {
1230 pr_err("%s:register to AFE is not done\n", __func__);
1231 ret = -ENODEV;
1232 return ret;
1233 }
1234 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1235 buf_addr_p, bytes);
1236
1237 afecmd_wr.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1238 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1239 afecmd_wr.hdr.pkt_size = sizeof(afecmd_wr);
1240 afecmd_wr.hdr.src_port = 0;
1241 afecmd_wr.hdr.dest_port = 0;
1242 afecmd_wr.hdr.token = 0;
1243 afecmd_wr.hdr.opcode = AFE_PORT_DATA_CMD_RT_PROXY_PORT_WRITE_V2;
1244 afecmd_wr.port_id = RT_PROXY_PORT_001_TX;
1245 afecmd_wr.buffer_address_lsw = (uint32_t)buf_addr_p;
1246 afecmd_wr.buffer_address_msw = 0x00;
1247 afecmd_wr.mem_map_handle = mem_map_handle;
1248 afecmd_wr.available_bytes = bytes;
1249 afecmd_wr.reserved = 0;
1250
1251 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_wr);
1252 if (ret < 0) {
1253 pr_err("%s: AFE rtproxy write to port 0x%x failed %d\n",
1254 __func__, afecmd_wr.port_id, ret);
1255 ret = -EINVAL;
1256 return ret;
1257 }
1258 return 0;
1259
1260}
1261
1262int afe_rt_proxy_port_read(u32 buf_addr_p, u32 mem_map_handle, int bytes)
1263{
1264 int ret = 0;
1265 struct afe_port_data_cmd_rt_proxy_port_read_v2 afecmd_rd;
1266
1267 if (this_afe.apr == NULL) {
1268 pr_err("%s: register to AFE is not done\n", __func__);
1269 ret = -ENODEV;
1270 return ret;
1271 }
1272 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1273 buf_addr_p, bytes);
1274
1275 afecmd_rd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1276 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1277 afecmd_rd.hdr.pkt_size = sizeof(afecmd_rd);
1278 afecmd_rd.hdr.src_port = 0;
1279 afecmd_rd.hdr.dest_port = 0;
1280 afecmd_rd.hdr.token = 0;
1281 afecmd_rd.hdr.opcode = AFE_PORT_DATA_CMD_RT_PROXY_PORT_READ_V2;
1282 afecmd_rd.port_id = RT_PROXY_PORT_001_RX;
1283 afecmd_rd.buffer_address_lsw = (uint32_t)buf_addr_p;
1284 afecmd_rd.buffer_address_msw = 0x00;
1285 afecmd_rd.available_bytes = bytes;
1286
1287 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_rd);
1288 if (ret < 0) {
1289 pr_err("%s: AFE rtproxy read cmd to port 0x%x failed %d\n",
1290 __func__, afecmd_rd.port_id, ret);
1291 ret = -EINVAL;
1292 return ret;
1293 }
1294 return 0;
1295}
1296
1297#ifdef CONFIG_DEBUG_FS
1298static struct dentry *debugfs_afelb;
1299static struct dentry *debugfs_afelb_gain;
1300
1301static int afe_debug_open(struct inode *inode, struct file *file)
1302{
1303 file->private_data = inode->i_private;
1304 pr_info("debug intf %s\n", (char *) file->private_data);
1305 return 0;
1306}
1307
1308static int afe_get_parameters(char *buf, long int *param1, int num_of_par)
1309{
1310 char *token;
1311 int base, cnt;
1312
1313 token = strsep(&buf, " ");
1314
1315 for (cnt = 0; cnt < num_of_par; cnt++) {
1316 if (token != NULL) {
1317 if ((token[1] == 'x') || (token[1] == 'X'))
1318 base = 16;
1319 else
1320 base = 10;
1321
1322 if (strict_strtoul(token, base, &param1[cnt]) != 0)
1323 return -EINVAL;
1324
1325 token = strsep(&buf, " ");
1326 } else
1327 return -EINVAL;
1328 }
1329 return 0;
1330}
1331#define AFE_LOOPBACK_ON (1)
1332#define AFE_LOOPBACK_OFF (0)
1333static ssize_t afe_debug_write(struct file *filp,
1334 const char __user *ubuf, size_t cnt, loff_t *ppos)
1335{
1336 char *lb_str = filp->private_data;
1337 char lbuf[32];
1338 int rc;
1339 unsigned long param[5];
1340
1341 if (cnt > sizeof(lbuf) - 1)
1342 return -EINVAL;
1343
1344 rc = copy_from_user(lbuf, ubuf, cnt);
1345 if (rc)
1346 return -EFAULT;
1347
1348 lbuf[cnt] = '\0';
1349
1350 if (!strncmp(lb_str, "afe_loopback", 12)) {
1351 rc = afe_get_parameters(lbuf, param, 3);
1352 if (!rc) {
1353 pr_info("%s %lu %lu %lu\n", lb_str, param[0], param[1],
1354 param[2]);
1355
1356 if ((param[0] != AFE_LOOPBACK_ON) && (param[0] !=
1357 AFE_LOOPBACK_OFF)) {
1358 pr_err("%s: Error, parameter 0 incorrect\n",
1359 __func__);
1360 rc = -EINVAL;
1361 goto afe_error;
1362 }
1363 if ((q6audio_validate_port(param[1]) < 0) ||
1364 (q6audio_validate_port(param[2])) < 0) {
1365 pr_err("%s: Error, invalid afe port\n",
1366 __func__);
1367 }
1368 if (this_afe.apr == NULL) {
1369 pr_err("%s: Error, AFE not opened\n", __func__);
1370 rc = -EINVAL;
1371 } else {
1372 rc = afe_loopback(param[0], param[1], param[2]);
1373 }
1374 } else {
1375 pr_err("%s: Error, invalid parameters\n", __func__);
1376 rc = -EINVAL;
1377 }
1378
1379 } else if (!strncmp(lb_str, "afe_loopback_gain", 17)) {
1380 rc = afe_get_parameters(lbuf, param, 2);
1381 if (!rc) {
1382 pr_info("%s %lu %lu\n", lb_str, param[0], param[1]);
1383
1384 if (q6audio_validate_port(param[0]) < 0) {
1385 pr_err("%s: Error, invalid afe port\n",
1386 __func__);
1387 rc = -EINVAL;
1388 goto afe_error;
1389 }
1390
1391 if (param[1] < 0 || param[1] > 100) {
1392 pr_err("%s: Error, volume shoud be 0 to 100"
1393 " percentage param = %lu\n",
1394 __func__, param[1]);
1395 rc = -EINVAL;
1396 goto afe_error;
1397 }
1398
1399 param[1] = (Q6AFE_MAX_VOLUME * param[1]) / 100;
1400
1401 if (this_afe.apr == NULL) {
1402 pr_err("%s: Error, AFE not opened\n", __func__);
1403 rc = -EINVAL;
1404 } else {
1405 rc = afe_loopback_gain(param[0], param[1]);
1406 }
1407 } else {
1408 pr_err("%s: Error, invalid parameters\n", __func__);
1409 rc = -EINVAL;
1410 }
1411 }
1412
1413afe_error:
1414 if (rc == 0)
1415 rc = cnt;
1416 else
1417 pr_err("%s: rc = %d\n", __func__, rc);
1418
1419 return rc;
1420}
1421
1422static const struct file_operations afe_debug_fops = {
1423 .open = afe_debug_open,
1424 .write = afe_debug_write
1425};
1426
1427static void config_debug_fs_init(void)
1428{
1429 debugfs_afelb = debugfs_create_file("afe_loopback",
1430 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback",
1431 &afe_debug_fops);
1432
1433 debugfs_afelb_gain = debugfs_create_file("afe_loopback_gain",
1434 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback_gain",
1435 &afe_debug_fops);
1436}
1437static void config_debug_fs_exit(void)
1438{
1439 if (debugfs_afelb)
1440 debugfs_remove(debugfs_afelb);
1441 if (debugfs_afelb_gain)
1442 debugfs_remove(debugfs_afelb_gain);
1443}
1444#else
1445static void config_debug_fs_init(void)
1446{
1447 return;
1448}
1449static void config_debug_fs_exit(void)
1450{
1451 return;
1452}
1453#endif
1454int afe_sidetone(u16 tx_port_id, u16 rx_port_id, u16 enable, uint16_t gain)
1455{
1456 struct afe_loopback_cfg_v1 cmd_sidetone;
1457 int ret = 0;
1458 int index = 0;
1459
1460 pr_info("%s: tx_port_id:%d rx_port_id:%d enable:%d gain:%d\n", __func__,
1461 tx_port_id, rx_port_id, enable, gain);
1462 index = q6audio_get_port_index(rx_port_id);
1463 if (q6audio_validate_port(rx_port_id) < 0)
1464 return -EINVAL;
1465
1466 cmd_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1467 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1468 cmd_sidetone.hdr.pkt_size = sizeof(cmd_sidetone);
1469 cmd_sidetone.hdr.src_port = 0;
1470 cmd_sidetone.hdr.dest_port = 0;
1471 cmd_sidetone.hdr.token = 0;
1472 cmd_sidetone.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
1473 /* should it be rx or tx port id ?? , bharath*/
1474 cmd_sidetone.param.port_id = tx_port_id;
1475 /* size of data param & payload */
1476 cmd_sidetone.param.payload_size = (sizeof(cmd_sidetone) -
1477 sizeof(struct apr_hdr) -
1478 sizeof(struct afe_port_cmd_set_param_v2));
1479 cmd_sidetone.param.payload_address_lsw = 0x00;
1480 cmd_sidetone.param.payload_address_msw = 0x00;
1481 cmd_sidetone.param.mem_map_handle = 0x00;
1482 cmd_sidetone.pdata.module_id = AFE_MODULE_LOOPBACK;
1483 cmd_sidetone.pdata.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
1484 /* size of actual payload only */
1485 cmd_sidetone.pdata.param_size = cmd_sidetone.param.payload_size -
1486 sizeof(struct afe_port_param_data_v2);
1487
1488 cmd_sidetone.loopback_cfg_minor_version =
1489 AFE_API_VERSION_LOOPBACK_CONFIG;
1490 cmd_sidetone.dst_port_id = rx_port_id;
1491 cmd_sidetone.routing_mode = LB_MODE_SIDETONE;
1492 cmd_sidetone.enable = enable;
1493
1494 atomic_set(&this_afe.state, 1);
1495 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_sidetone);
1496 if (ret < 0) {
1497 pr_err("%s: AFE sidetone failed for tx_port:%d rx_port:%d\n",
1498 __func__, tx_port_id, rx_port_id);
1499 ret = -EINVAL;
1500 goto fail_cmd;
1501 }
1502
1503 ret = wait_event_timeout(this_afe.wait[index],
1504 (atomic_read(&this_afe.state) == 0),
1505 msecs_to_jiffies(TIMEOUT_MS));
1506 if (ret < 0) {
1507 pr_err("%s: wait_event timeout\n", __func__);
1508 ret = -EINVAL;
1509 goto fail_cmd;
1510 }
1511 return 0;
1512fail_cmd:
1513 return ret;
1514}
1515
Joonwoo Park6572ac52012-07-10 17:17:00 -07001516int afe_validate_port(u16 port_id)
1517{
1518 int ret;
1519
1520 switch (port_id) {
1521 case PRIMARY_I2S_RX:
1522 case PRIMARY_I2S_TX:
1523 case PCM_RX:
1524 case PCM_TX:
1525 case SECONDARY_I2S_RX:
1526 case SECONDARY_I2S_TX:
1527 case MI2S_RX:
1528 case MI2S_TX:
1529 case HDMI_RX:
1530 case RSVD_2:
1531 case RSVD_3:
1532 case DIGI_MIC_TX:
1533 case VOICE_RECORD_RX:
1534 case VOICE_RECORD_TX:
1535 case VOICE_PLAYBACK_TX:
1536 case SLIMBUS_0_RX:
1537 case SLIMBUS_0_TX:
1538 case SLIMBUS_1_RX:
1539 case SLIMBUS_1_TX:
1540 case SLIMBUS_2_RX:
1541 case SLIMBUS_2_TX:
1542 case SLIMBUS_3_RX:
1543 case INT_BT_SCO_RX:
1544 case INT_BT_SCO_TX:
1545 case INT_BT_A2DP_RX:
1546 case INT_FM_RX:
1547 case INT_FM_TX:
1548 case RT_PROXY_PORT_001_RX:
1549 case RT_PROXY_PORT_001_TX:
1550 case SLIMBUS_4_RX:
1551 case SLIMBUS_4_TX:
1552 {
1553 ret = 0;
1554 break;
1555 }
1556
1557 default:
1558 ret = -EINVAL;
1559 }
1560
1561 return ret;
1562}
1563
1564int afe_convert_virtual_to_portid(u16 port_id)
1565{
1566 int ret;
1567
1568 /*
1569 * if port_id is virtual, convert to physical..
1570 * if port_id is already physical, return physical
1571 */
1572 if (afe_validate_port(port_id) < 0) {
1573 if (port_id == RT_PROXY_DAI_001_RX ||
1574 port_id == RT_PROXY_DAI_001_TX ||
1575 port_id == RT_PROXY_DAI_002_RX ||
1576 port_id == RT_PROXY_DAI_002_TX)
1577 ret = VIRTUAL_ID_TO_PORTID(port_id);
1578 else
1579 ret = -EINVAL;
1580 } else
1581 ret = port_id;
1582
1583 return ret;
1584}
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -07001585int afe_port_stop_nowait(int port_id)
1586{
1587 struct afe_port_cmd_device_stop stop;
1588 int ret = 0;
1589
1590 if (this_afe.apr == NULL) {
1591 pr_err("AFE is already closed\n");
1592 ret = -EINVAL;
1593 goto fail_cmd;
1594 }
1595 pr_debug("%s: port_id=%d\n", __func__, port_id);
1596 port_id = q6audio_convert_virtual_to_portid(port_id);
1597
1598 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1599 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1600 stop.hdr.pkt_size = sizeof(stop);
1601 stop.hdr.src_port = 0;
1602 stop.hdr.dest_port = 0;
1603 stop.hdr.token = 0;
1604 stop.hdr.opcode = AFE_PORT_CMD_DEVICE_STOP;
1605 stop.port_id = port_id;
1606 stop.reserved = 0;
1607
1608 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1609
1610 if (IS_ERR_VALUE(ret)) {
1611 pr_err("%s: AFE close failed\n", __func__);
1612 ret = -EINVAL;
1613 }
1614
1615fail_cmd:
1616 return ret;
1617
1618}
1619
1620int afe_close(int port_id)
1621{
1622 struct afe_port_cmd_device_stop stop;
1623 int ret = 0;
1624 int index = 0;
1625
1626
1627 if (this_afe.apr == NULL) {
1628 pr_err("AFE is already closed\n");
1629 ret = -EINVAL;
1630 goto fail_cmd;
1631 }
1632 pr_debug("%s: port_id=%d\n", __func__, port_id);
1633
1634 index = q6audio_get_port_index(port_id);
1635 if (q6audio_validate_port(port_id) < 0)
1636 return -EINVAL;
1637
1638 port_id = q6audio_convert_virtual_to_portid(port_id);
1639
1640 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1641 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1642 stop.hdr.pkt_size = sizeof(stop);
1643 stop.hdr.src_port = 0;
1644 stop.hdr.dest_port = 0;
1645 stop.hdr.token = index;
1646 stop.hdr.opcode = AFE_PORT_CMD_DEVICE_STOP;
1647 stop.port_id = q6audio_get_port_id(port_id);
1648 stop.reserved = 0;
1649
1650 atomic_set(&this_afe.state, 1);
1651 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1652
1653 if (ret < 0) {
1654 pr_err("%s: AFE close failed\n", __func__);
1655 ret = -EINVAL;
1656 goto fail_cmd;
1657 }
1658
1659 ret = wait_event_timeout(this_afe.wait[index],
1660 (atomic_read(&this_afe.state) == 0),
1661 msecs_to_jiffies(TIMEOUT_MS));
1662 if (!ret) {
1663 pr_err("%s: wait_event timeout\n", __func__);
1664 ret = -EINVAL;
1665 goto fail_cmd;
1666 }
1667fail_cmd:
1668 return ret;
1669}
1670
1671static int __init afe_init(void)
1672{
1673 int i = 0;
1674 atomic_set(&this_afe.state, 0);
1675 atomic_set(&this_afe.status, 0);
1676 this_afe.apr = NULL;
1677 for (i = 0; i < AFE_MAX_PORTS; i++)
1678 init_waitqueue_head(&this_afe.wait[i]);
1679
1680 config_debug_fs_init();
1681 return 0;
1682}
1683
1684static void __exit afe_exit(void)
1685{
1686 int i;
1687
1688 config_debug_fs_exit();
1689 for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
1690 if (afe_cal_addr[i].cal_paddr != 0)
1691 afe_cmd_memory_unmap_nowait(
1692 afe_cal_addr[i].cal_paddr);
1693 }
1694}
1695
1696device_initcall(afe_init);
1697__exitcall(afe_exit);