blob: 756cb1855ba92c80d1b3180cfea1d063137e04b4 [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;
589 lb_cmd.hdr.token = 0;
590 lb_cmd.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
591 lb_cmd.param.port_id = tx_port;
592 lb_cmd.param.payload_size = (sizeof(lb_cmd) -
593 sizeof(struct apr_hdr) -
594 sizeof(struct afe_port_cmd_set_param_v2));
595 lb_cmd.param.payload_address_lsw = 0x00;
596 lb_cmd.param.payload_address_msw = 0x00;
597 lb_cmd.param.mem_map_handle = 0x00;
598 lb_cmd.pdata.module_id = AFE_MODULE_LOOPBACK;
599 lb_cmd.pdata.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
600 lb_cmd.pdata.param_size = lb_cmd.param.payload_size -
601 sizeof(struct afe_port_param_data_v2);
602
603 lb_cmd.dst_port_id = rx_port;
604 lb_cmd.routing_mode = LB_MODE_DEFAULT;
605 lb_cmd.enable = (enable ? 1 : 0);
606 lb_cmd.loopback_cfg_minor_version =
607 AFE_API_VERSION_LOOPBACK_CONFIG;
608 atomic_set(&this_afe.state, 1);
609
610 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &lb_cmd);
611 if (ret < 0) {
612 pr_err("%s: AFE loopback failed\n", __func__);
613 ret = -EINVAL;
614 goto done;
615 }
616 ret = wait_event_timeout(this_afe.wait[index],
617 (atomic_read(&this_afe.state) == 0),
618 msecs_to_jiffies(TIMEOUT_MS));
619 if (!ret) {
620 pr_err("%s: wait_event timeout\n", __func__);
621 ret = -EINVAL;
622 }
623done:
624 return ret;
625}
626
627int afe_loopback_gain(u16 port_id, u16 volume)
628{
629 struct afe_loopback_gain_per_path_param set_param;
630 int ret = 0;
631 int index = 0;
632
633 if (this_afe.apr == NULL) {
634 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
635 0xFFFFFFFF, &this_afe);
636 pr_debug("%s: Register AFE\n", __func__);
637 if (this_afe.apr == NULL) {
638 pr_err("%s: Unable to register AFE\n", __func__);
639 ret = -ENODEV;
640 return ret;
641 }
642 }
643
644 if (q6audio_validate_port(port_id) < 0) {
645
646 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
647 port_id);
648 ret = -EINVAL;
649 goto fail_cmd;
650 }
651 index = q6audio_get_port_index(port_id);
652 if (q6audio_validate_port(port_id) < 0)
653 return -EINVAL;
654
655 /* RX ports numbers are even .TX ports numbers are odd. */
656 if (port_id % 2 == 0) {
657 pr_err("%s: Failed : afe loopback gain only for TX ports."
658 " port_id %d\n", __func__, port_id);
659 ret = -EINVAL;
660 goto fail_cmd;
661 }
662
663 pr_debug("%s: %d %hX\n", __func__, port_id, volume);
664
665 set_param.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
666 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
667 set_param.hdr.pkt_size = sizeof(set_param);
668 set_param.hdr.src_port = 0;
669 set_param.hdr.dest_port = 0;
670 set_param.hdr.token = 0;
671 set_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
672
673 set_param.param.port_id = port_id;
674 set_param.param.payload_size =
675 (sizeof(struct afe_loopback_gain_per_path_param) -
676 sizeof(struct apr_hdr) -
677 sizeof(struct afe_port_cmd_set_param_v2));
678 set_param.param.payload_address_lsw = 0;
679 set_param.param.payload_address_msw = 0;
680 set_param.param.mem_map_handle = 0;
681
682 set_param.pdata.module_id = AFE_MODULE_LOOPBACK;
683 set_param.pdata.param_id = AFE_PARAM_ID_LOOPBACK_GAIN_PER_PATH;
684 set_param.pdata.param_size = (set_param.param.payload_size -
685 sizeof(struct afe_port_param_data_v2));
686 set_param.rx_port_id = port_id;
687 set_param.gain = volume;
688
689 set_param.hdr.token = index;
690
691 atomic_set(&this_afe.state, 1);
692 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_param);
693 if (ret < 0) {
694 pr_err("%s: AFE param set failed for port %d\n",
695 __func__, port_id);
696 ret = -EINVAL;
697 goto fail_cmd;
698 }
699
700 ret = wait_event_timeout(this_afe.wait[index],
701 (atomic_read(&this_afe.state) == 0),
702 msecs_to_jiffies(TIMEOUT_MS));
703 if (ret < 0) {
704 pr_err("%s: wait_event timeout\n", __func__);
705 ret = -EINVAL;
706 goto fail_cmd;
707 }
708 return 0;
709fail_cmd:
710 return ret;
711}
712
713int afe_pseudo_port_start_nowait(u16 port_id)
714{
715 struct afe_pseudoport_start_command start;
716 int ret = 0;
717
718 pr_debug("%s: port_id=%d\n", __func__, port_id);
719 if (this_afe.apr == NULL) {
720 pr_err("%s: AFE APR is not registered\n", __func__);
721 return -ENODEV;
722 }
723
724
725 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
726 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
727 start.hdr.pkt_size = sizeof(start);
728 start.hdr.src_port = 0;
729 start.hdr.dest_port = 0;
730 start.hdr.token = 0;
731 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
732 start.port_id = port_id;
733 start.timing = 1;
734
735 atomic_set(&this_afe.state, 1);
736 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
737 if (ret < 0) {
738 pr_err("%s: AFE enable for port %d failed %d\n",
739 __func__, port_id, ret);
740 return -EINVAL;
741 }
742 return 0;
743}
744
745int afe_start_pseudo_port(u16 port_id)
746{
747 int ret = 0;
748 struct afe_pseudoport_start_command start;
749 int index = 0;
750
751 pr_debug("%s: port_id=%d\n", __func__, port_id);
752
753 ret = afe_q6_interface_prepare();
754 if (ret != 0)
755 return ret;
756
757 index = q6audio_get_port_index(port_id);
758 if (q6audio_validate_port(port_id) < 0)
759 return -EINVAL;
760
761 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
762 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
763 start.hdr.pkt_size = sizeof(start);
764 start.hdr.src_port = 0;
765 start.hdr.dest_port = 0;
766 start.hdr.token = 0;
767 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
768 start.port_id = port_id;
769 start.timing = 1;
770
771 start.hdr.token = index;
772 atomic_set(&this_afe.state, 1);
773 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
774 if (ret < 0) {
775 pr_err("%s: AFE enable for port %d failed %d\n",
776 __func__, port_id, ret);
777 return -EINVAL;
778 }
779
780 ret = wait_event_timeout(this_afe.wait[index],
781 (atomic_read(&this_afe.state) == 0),
782 msecs_to_jiffies(TIMEOUT_MS));
783 if (!ret) {
784 pr_err("%s: wait_event timeout\n", __func__);
785 return -EINVAL;
786 }
787
788 return 0;
789}
790
791int afe_pseudo_port_stop_nowait(u16 port_id)
792{
793 int ret = 0;
794 struct afe_pseudoport_stop_command stop;
795 int index = 0;
796
797 pr_debug("%s: port_id=%d\n", __func__, port_id);
798
799 if (this_afe.apr == NULL) {
800 pr_err("%s: AFE is already closed\n", __func__);
801 return -EINVAL;
802 }
803 index = q6audio_get_port_index(port_id);
804 if (q6audio_validate_port(port_id) < 0)
805 return -EINVAL;
806
807 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
808 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
809 stop.hdr.pkt_size = sizeof(stop);
810 stop.hdr.src_port = 0;
811 stop.hdr.dest_port = 0;
812 stop.hdr.token = 0;
813 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
814 stop.port_id = port_id;
815 stop.reserved = 0;
816
817 stop.hdr.token = index;
818 atomic_set(&this_afe.state, 1);
819 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
820 if (ret < 0) {
821 pr_err("%s: AFE close failed %d\n", __func__, ret);
822 return -EINVAL;
823 }
824
825 return 0;
826
827}
828
829int afe_stop_pseudo_port(u16 port_id)
830{
831 int ret = 0;
832 struct afe_pseudoport_stop_command stop;
833 int index = 0;
834
835 pr_debug("%s: port_id=%d\n", __func__, port_id);
836
837 if (this_afe.apr == NULL) {
838 pr_err("%s: AFE is already closed\n", __func__);
839 return -EINVAL;
840 }
841
842 index = q6audio_get_port_index(port_id);
843 if (q6audio_validate_port(port_id) < 0)
844 return -EINVAL;
845
846 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
847 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
848 stop.hdr.pkt_size = sizeof(stop);
849 stop.hdr.src_port = 0;
850 stop.hdr.dest_port = 0;
851 stop.hdr.token = 0;
852 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
853 stop.port_id = port_id;
854 stop.reserved = 0;
855
856 stop.hdr.token = index;
857 atomic_set(&this_afe.state, 1);
858 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
859 if (ret < 0) {
860 pr_err("%s: AFE close failed %d\n", __func__, ret);
861 return -EINVAL;
862 }
863
864 ret = wait_event_timeout(this_afe.wait[index],
865 (atomic_read(&this_afe.state) == 0),
866 msecs_to_jiffies(TIMEOUT_MS));
867 if (!ret) {
868 pr_err("%s: wait_event timeout\n", __func__);
869 return -EINVAL;
870 }
871
872 return 0;
873}
874
875/*bharath, memory map handle needs to be stored by AFE client */
876int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz)
877{
878 int ret = 0;
879 int cmd_size = 0;
880 void *payload = NULL;
881 void *mmap_region_cmd = NULL;
882 struct afe_service_cmd_shared_mem_map_regions *mregion = NULL;
883 struct afe_service_shared_map_region_payload *mregion_pl = NULL;
884 int index = 0;
885
886 pr_debug("%s:\n", __func__);
887
888 if (this_afe.apr == NULL) {
889 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
890 0xFFFFFFFF, &this_afe);
891 pr_debug("%s: Register AFE\n", __func__);
892 if (this_afe.apr == NULL) {
893 pr_err("%s: Unable to register AFE\n", __func__);
894 ret = -ENODEV;
895 return ret;
896 }
897 }
898
899 cmd_size = sizeof(struct afe_service_cmd_shared_mem_map_regions) \
900 + sizeof(struct afe_service_shared_map_region_payload);
901
902 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
903 if (!mmap_region_cmd) {
904 pr_err("%s: allocate mmap_region_cmd failed\n", __func__);
905 return -ENOMEM;
906 }
907
908 mregion = (struct afe_service_cmd_shared_mem_map_regions *)
909 mmap_region_cmd;
910 mregion->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
911 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
912 mregion->hdr.pkt_size = sizeof(mregion);
913 mregion->hdr.src_port = 0;
914 mregion->hdr.dest_port = 0;
915 mregion->hdr.token = 0;
916 mregion->hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS;
Harmandeep Singhac1671b2012-06-22 15:34:45 -0700917 mregion->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700918 mregion->num_regions = 1;
919 mregion->property_flag = 0x00;
920 /* Todo */
921 index = mregion->hdr.token = IDX_RSVD_2;
922
923 payload = ((u8 *) mmap_region_cmd +
924 sizeof(struct afe_service_cmd_shared_mem_map_regions));
925
926 mregion_pl = (struct afe_service_shared_map_region_payload *)payload;
927
928 mregion_pl->shm_addr_lsw = dma_addr_p;
929 mregion_pl->shm_addr_msw = 0x00;
930 mregion_pl->mem_size_bytes = dma_buf_sz;
931
932 atomic_set(&this_afe.state, 1);
933 ret = apr_send_pkt(this_afe.apr, (uint32_t *) mmap_region_cmd);
934 if (ret < 0) {
935 pr_err("%s: AFE memory map cmd failed %d\n",
936 __func__, ret);
937 ret = -EINVAL;
938 return ret;
939 }
940
941 ret = wait_event_timeout(this_afe.wait[index],
942 (atomic_read(&this_afe.state) == 0),
943 msecs_to_jiffies(TIMEOUT_MS));
944 if (!ret) {
945 pr_err("%s: wait_event timeout\n", __func__);
946 ret = -EINVAL;
947 return ret;
948 }
949
950 return 0;
951}
952
953int afe_cmd_memory_map_nowait(int port_id, u32 dma_addr_p, u32 dma_buf_sz)
954{
955 int ret = 0;
956 int cmd_size = 0;
957 void *payload = NULL;
958 void *mmap_region_cmd = NULL;
959 struct afe_service_cmd_shared_mem_map_regions *mregion = NULL;
960 struct afe_service_shared_map_region_payload *mregion_pl = NULL;
961 int index = 0;
962
963 pr_debug("%s:\n", __func__);
964
965 if (this_afe.apr == NULL) {
966 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
967 0xFFFFFFFF, &this_afe);
968 pr_debug("%s: Register AFE\n", __func__);
969 if (this_afe.apr == NULL) {
970 pr_err("%s: Unable to register AFE\n", __func__);
971 ret = -ENODEV;
972 return ret;
973 }
974 }
975 index = q6audio_get_port_index(port_id);
976 if (q6audio_validate_port(port_id) < 0)
977 return -EINVAL;
978
979 cmd_size = sizeof(struct afe_service_cmd_shared_mem_map_regions)
980 + sizeof(struct afe_service_shared_map_region_payload);
981
982 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
983 if (!mmap_region_cmd) {
984 pr_err("%s: allocate mmap_region_cmd failed\n", __func__);
985 return -ENOMEM;
986 }
987 mregion = (struct afe_service_cmd_shared_mem_map_regions *)
988 mmap_region_cmd;
989 mregion->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
990 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
991 mregion->hdr.pkt_size = sizeof(mregion);
992 mregion->hdr.src_port = 0;
993 mregion->hdr.dest_port = 0;
994 mregion->hdr.token = 0;
995 mregion->hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS;
Harmandeep Singhac1671b2012-06-22 15:34:45 -0700996 mregion->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -0700997 mregion->num_regions = 1;
998 mregion->property_flag = 0x00;
999
1000 payload = ((u8 *) mmap_region_cmd +
1001 sizeof(struct afe_service_cmd_shared_mem_map_regions));
1002 mregion_pl = (struct afe_service_shared_map_region_payload *)payload;
1003
1004 mregion_pl->shm_addr_lsw = dma_addr_p;
1005 mregion_pl->shm_addr_msw = 0x00;
1006 mregion_pl->mem_size_bytes = dma_buf_sz;
1007
1008 atomic_set(&this_afe.state, 1);
1009 ret = apr_send_pkt(this_afe.apr, (uint32_t *) mmap_region_cmd);
1010 if (ret < 0) {
1011 pr_err("%s: AFE memory map cmd failed %d\n",
1012 __func__, ret);
1013 ret = -EINVAL;
1014 return ret;
1015 }
1016 return 0;
1017}
1018
1019int afe_cmd_memory_unmap(u32 mem_map_handle)
1020{
1021 int ret = 0;
1022 struct afe_service_cmd_shared_mem_unmap_regions mregion;
1023 int index = 0;
1024
1025 pr_debug("%s:\n", __func__);
1026
1027 if (this_afe.apr == NULL) {
1028 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1029 0xFFFFFFFF, &this_afe);
1030 pr_debug("%s: Register AFE\n", __func__);
1031 if (this_afe.apr == NULL) {
1032 pr_err("%s: Unable to register AFE\n", __func__);
1033 ret = -ENODEV;
1034 return ret;
1035 }
1036 }
1037
1038 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1039 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1040 mregion.hdr.pkt_size = sizeof(mregion);
1041 mregion.hdr.src_port = 0;
1042 mregion.hdr.dest_port = 0;
1043 mregion.hdr.token = 0;
1044 mregion.hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS;
1045 mregion.mem_map_handle = mem_map_handle;
1046
1047 /* Todo */
1048 index = mregion.hdr.token = IDX_RSVD_2;
1049
1050 atomic_set(&this_afe.state, 1);
1051 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1052 if (ret < 0) {
1053 pr_err("%s: AFE memory unmap cmd failed %d\n",
1054 __func__, ret);
1055 ret = -EINVAL;
1056 return ret;
1057 }
1058
1059 ret = wait_event_timeout(this_afe.wait[index],
1060 (atomic_read(&this_afe.state) == 0),
1061 msecs_to_jiffies(TIMEOUT_MS));
1062 if (!ret) {
1063 pr_err("%s: wait_event timeout\n", __func__);
1064 ret = -EINVAL;
1065 return ret;
1066 }
1067 return 0;
1068}
1069
1070int afe_cmd_memory_unmap_nowait(u32 mem_map_handle)
1071{
1072 int ret = 0;
1073 struct afe_service_cmd_shared_mem_unmap_regions mregion;
1074
1075 pr_debug("%s:\n", __func__);
1076
1077 if (this_afe.apr == NULL) {
1078 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1079 0xFFFFFFFF, &this_afe);
1080 pr_debug("%s: Register AFE\n", __func__);
1081 if (this_afe.apr == NULL) {
1082 pr_err("%s: Unable to register AFE\n", __func__);
1083 ret = -ENODEV;
1084 return ret;
1085 }
1086 }
1087
1088 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1089 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1090 mregion.hdr.pkt_size = sizeof(mregion);
1091 mregion.hdr.src_port = 0;
1092 mregion.hdr.dest_port = 0;
1093 mregion.hdr.token = 0;
1094 mregion.hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_UNMAP_REGIONS;
1095 mregion.mem_map_handle = mem_map_handle;
1096
1097 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1098 if (ret < 0) {
1099 pr_err("%s: AFE memory unmap cmd failed %d\n",
1100 __func__, ret);
1101 ret = -EINVAL;
1102 }
1103 return 0;
1104}
1105
1106int afe_register_get_events(u16 port_id,
1107 void (*cb) (uint32_t opcode,
1108 uint32_t token, uint32_t *payload, void *priv),
1109 void *private_data)
1110{
1111 int ret = 0;
1112 struct afe_service_cmd_register_rt_port_driver rtproxy;
1113
1114 pr_debug("%s:\n", __func__);
1115
1116 if (this_afe.apr == NULL) {
1117 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1118 0xFFFFFFFF, &this_afe);
1119 pr_debug("%s: Register AFE\n", __func__);
1120 if (this_afe.apr == NULL) {
1121 pr_err("%s: Unable to register AFE\n", __func__);
1122 ret = -ENODEV;
1123 return ret;
1124 }
1125 }
1126 if ((port_id == RT_PROXY_DAI_002_RX) ||
1127 (port_id == RT_PROXY_DAI_001_TX))
1128 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1129 else
1130 return -EINVAL;
1131
1132 if (port_id == RT_PROXY_PORT_001_TX) {
1133 this_afe.tx_cb = cb;
1134 this_afe.tx_private_data = private_data;
1135 } else if (port_id == RT_PROXY_PORT_001_RX) {
1136 this_afe.rx_cb = cb;
1137 this_afe.rx_private_data = private_data;
1138 }
1139
1140 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1141 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1142 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1143 rtproxy.hdr.src_port = 1;
1144 rtproxy.hdr.dest_port = 1;
1145 rtproxy.hdr.opcode = AFE_SERVICE_CMD_REGISTER_RT_PORT_DRIVER;
1146 rtproxy.port_id = port_id;
1147 rtproxy.reserved = 0;
1148
1149 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1150 if (ret < 0) {
1151 pr_err("%s: AFE reg. rtproxy_event failed %d\n",
1152 __func__, ret);
1153 ret = -EINVAL;
1154 return ret;
1155 }
1156 return 0;
1157}
1158
1159int afe_unregister_get_events(u16 port_id)
1160{
1161 int ret = 0;
1162 struct afe_service_cmd_unregister_rt_port_driver rtproxy;
1163 int index = 0;
1164
1165 pr_debug("%s:\n", __func__);
1166
1167 if (this_afe.apr == NULL) {
1168 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1169 0xFFFFFFFF, &this_afe);
1170 pr_debug("%s: Register AFE\n", __func__);
1171 if (this_afe.apr == NULL) {
1172 pr_err("%s: Unable to register AFE\n", __func__);
1173 ret = -ENODEV;
1174 return ret;
1175 }
1176 }
1177 index = q6audio_get_port_index(port_id);
1178 if (q6audio_validate_port(port_id) < 0)
1179 return -EINVAL;
1180
1181 if ((port_id == RT_PROXY_DAI_002_RX) ||
1182 (port_id == RT_PROXY_DAI_001_TX))
1183 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1184 else
1185 return -EINVAL;
1186
1187 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1188 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1189 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1190 rtproxy.hdr.src_port = 0;
1191 rtproxy.hdr.dest_port = 0;
1192 rtproxy.hdr.token = 0;
1193 rtproxy.hdr.opcode = AFE_SERVICE_CMD_UNREGISTER_RT_PORT_DRIVER;
1194 rtproxy.port_id = port_id;
1195 rtproxy.reserved = 0;
1196
1197 rtproxy.hdr.token = index;
1198
1199 if (port_id == RT_PROXY_PORT_001_TX) {
1200 this_afe.tx_cb = NULL;
1201 this_afe.tx_private_data = NULL;
1202 } else if (port_id == RT_PROXY_PORT_001_RX) {
1203 this_afe.rx_cb = NULL;
1204 this_afe.rx_private_data = NULL;
1205 }
1206
1207 atomic_set(&this_afe.state, 1);
1208 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1209 if (ret < 0) {
1210 pr_err("%s: AFE enable Unreg. rtproxy_event failed %d\n",
1211 __func__, ret);
1212 ret = -EINVAL;
1213 return ret;
1214 }
1215
1216 ret = wait_event_timeout(this_afe.wait[index],
1217 (atomic_read(&this_afe.state) == 0),
1218 msecs_to_jiffies(TIMEOUT_MS));
1219 if (!ret) {
1220 pr_err("%s: wait_event timeout\n", __func__);
1221 ret = -EINVAL;
1222 return ret;
1223 }
1224 return 0;
1225}
1226
1227int afe_rt_proxy_port_write(u32 buf_addr_p, u32 mem_map_handle, int bytes)
1228{
1229 int ret = 0;
1230 struct afe_port_data_cmd_rt_proxy_port_write_v2 afecmd_wr;
1231
1232 if (this_afe.apr == NULL) {
1233 pr_err("%s:register to AFE is not done\n", __func__);
1234 ret = -ENODEV;
1235 return ret;
1236 }
1237 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1238 buf_addr_p, bytes);
1239
1240 afecmd_wr.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1241 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1242 afecmd_wr.hdr.pkt_size = sizeof(afecmd_wr);
1243 afecmd_wr.hdr.src_port = 0;
1244 afecmd_wr.hdr.dest_port = 0;
1245 afecmd_wr.hdr.token = 0;
1246 afecmd_wr.hdr.opcode = AFE_PORT_DATA_CMD_RT_PROXY_PORT_WRITE_V2;
1247 afecmd_wr.port_id = RT_PROXY_PORT_001_TX;
1248 afecmd_wr.buffer_address_lsw = (uint32_t)buf_addr_p;
1249 afecmd_wr.buffer_address_msw = 0x00;
1250 afecmd_wr.mem_map_handle = mem_map_handle;
1251 afecmd_wr.available_bytes = bytes;
1252 afecmd_wr.reserved = 0;
1253
1254 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_wr);
1255 if (ret < 0) {
1256 pr_err("%s: AFE rtproxy write to port 0x%x failed %d\n",
1257 __func__, afecmd_wr.port_id, ret);
1258 ret = -EINVAL;
1259 return ret;
1260 }
1261 return 0;
1262
1263}
1264
1265int afe_rt_proxy_port_read(u32 buf_addr_p, u32 mem_map_handle, int bytes)
1266{
1267 int ret = 0;
1268 struct afe_port_data_cmd_rt_proxy_port_read_v2 afecmd_rd;
1269
1270 if (this_afe.apr == NULL) {
1271 pr_err("%s: register to AFE is not done\n", __func__);
1272 ret = -ENODEV;
1273 return ret;
1274 }
1275 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1276 buf_addr_p, bytes);
1277
1278 afecmd_rd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1279 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1280 afecmd_rd.hdr.pkt_size = sizeof(afecmd_rd);
1281 afecmd_rd.hdr.src_port = 0;
1282 afecmd_rd.hdr.dest_port = 0;
1283 afecmd_rd.hdr.token = 0;
1284 afecmd_rd.hdr.opcode = AFE_PORT_DATA_CMD_RT_PROXY_PORT_READ_V2;
1285 afecmd_rd.port_id = RT_PROXY_PORT_001_RX;
1286 afecmd_rd.buffer_address_lsw = (uint32_t)buf_addr_p;
1287 afecmd_rd.buffer_address_msw = 0x00;
1288 afecmd_rd.available_bytes = bytes;
1289
1290 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_rd);
1291 if (ret < 0) {
1292 pr_err("%s: AFE rtproxy read cmd to port 0x%x failed %d\n",
1293 __func__, afecmd_rd.port_id, ret);
1294 ret = -EINVAL;
1295 return ret;
1296 }
1297 return 0;
1298}
1299
1300#ifdef CONFIG_DEBUG_FS
1301static struct dentry *debugfs_afelb;
1302static struct dentry *debugfs_afelb_gain;
1303
1304static int afe_debug_open(struct inode *inode, struct file *file)
1305{
1306 file->private_data = inode->i_private;
1307 pr_info("debug intf %s\n", (char *) file->private_data);
1308 return 0;
1309}
1310
1311static int afe_get_parameters(char *buf, long int *param1, int num_of_par)
1312{
1313 char *token;
1314 int base, cnt;
1315
1316 token = strsep(&buf, " ");
1317
1318 for (cnt = 0; cnt < num_of_par; cnt++) {
1319 if (token != NULL) {
1320 if ((token[1] == 'x') || (token[1] == 'X'))
1321 base = 16;
1322 else
1323 base = 10;
1324
1325 if (strict_strtoul(token, base, &param1[cnt]) != 0)
1326 return -EINVAL;
1327
1328 token = strsep(&buf, " ");
1329 } else
1330 return -EINVAL;
1331 }
1332 return 0;
1333}
1334#define AFE_LOOPBACK_ON (1)
1335#define AFE_LOOPBACK_OFF (0)
1336static ssize_t afe_debug_write(struct file *filp,
1337 const char __user *ubuf, size_t cnt, loff_t *ppos)
1338{
1339 char *lb_str = filp->private_data;
1340 char lbuf[32];
1341 int rc;
1342 unsigned long param[5];
1343
1344 if (cnt > sizeof(lbuf) - 1)
1345 return -EINVAL;
1346
1347 rc = copy_from_user(lbuf, ubuf, cnt);
1348 if (rc)
1349 return -EFAULT;
1350
1351 lbuf[cnt] = '\0';
1352
1353 if (!strncmp(lb_str, "afe_loopback", 12)) {
1354 rc = afe_get_parameters(lbuf, param, 3);
1355 if (!rc) {
1356 pr_info("%s %lu %lu %lu\n", lb_str, param[0], param[1],
1357 param[2]);
1358
1359 if ((param[0] != AFE_LOOPBACK_ON) && (param[0] !=
1360 AFE_LOOPBACK_OFF)) {
1361 pr_err("%s: Error, parameter 0 incorrect\n",
1362 __func__);
1363 rc = -EINVAL;
1364 goto afe_error;
1365 }
1366 if ((q6audio_validate_port(param[1]) < 0) ||
1367 (q6audio_validate_port(param[2])) < 0) {
1368 pr_err("%s: Error, invalid afe port\n",
1369 __func__);
1370 }
1371 if (this_afe.apr == NULL) {
1372 pr_err("%s: Error, AFE not opened\n", __func__);
1373 rc = -EINVAL;
1374 } else {
1375 rc = afe_loopback(param[0], param[1], param[2]);
1376 }
1377 } else {
1378 pr_err("%s: Error, invalid parameters\n", __func__);
1379 rc = -EINVAL;
1380 }
1381
1382 } else if (!strncmp(lb_str, "afe_loopback_gain", 17)) {
1383 rc = afe_get_parameters(lbuf, param, 2);
1384 if (!rc) {
1385 pr_info("%s %lu %lu\n", lb_str, param[0], param[1]);
1386
1387 if (q6audio_validate_port(param[0]) < 0) {
1388 pr_err("%s: Error, invalid afe port\n",
1389 __func__);
1390 rc = -EINVAL;
1391 goto afe_error;
1392 }
1393
1394 if (param[1] < 0 || param[1] > 100) {
1395 pr_err("%s: Error, volume shoud be 0 to 100"
1396 " percentage param = %lu\n",
1397 __func__, param[1]);
1398 rc = -EINVAL;
1399 goto afe_error;
1400 }
1401
1402 param[1] = (Q6AFE_MAX_VOLUME * param[1]) / 100;
1403
1404 if (this_afe.apr == NULL) {
1405 pr_err("%s: Error, AFE not opened\n", __func__);
1406 rc = -EINVAL;
1407 } else {
1408 rc = afe_loopback_gain(param[0], param[1]);
1409 }
1410 } else {
1411 pr_err("%s: Error, invalid parameters\n", __func__);
1412 rc = -EINVAL;
1413 }
1414 }
1415
1416afe_error:
1417 if (rc == 0)
1418 rc = cnt;
1419 else
1420 pr_err("%s: rc = %d\n", __func__, rc);
1421
1422 return rc;
1423}
1424
1425static const struct file_operations afe_debug_fops = {
1426 .open = afe_debug_open,
1427 .write = afe_debug_write
1428};
1429
1430static void config_debug_fs_init(void)
1431{
1432 debugfs_afelb = debugfs_create_file("afe_loopback",
1433 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback",
1434 &afe_debug_fops);
1435
1436 debugfs_afelb_gain = debugfs_create_file("afe_loopback_gain",
1437 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback_gain",
1438 &afe_debug_fops);
1439}
1440static void config_debug_fs_exit(void)
1441{
1442 if (debugfs_afelb)
1443 debugfs_remove(debugfs_afelb);
1444 if (debugfs_afelb_gain)
1445 debugfs_remove(debugfs_afelb_gain);
1446}
1447#else
1448static void config_debug_fs_init(void)
1449{
1450 return;
1451}
1452static void config_debug_fs_exit(void)
1453{
1454 return;
1455}
1456#endif
1457int afe_sidetone(u16 tx_port_id, u16 rx_port_id, u16 enable, uint16_t gain)
1458{
1459 struct afe_loopback_cfg_v1 cmd_sidetone;
1460 int ret = 0;
1461 int index = 0;
1462
1463 pr_info("%s: tx_port_id:%d rx_port_id:%d enable:%d gain:%d\n", __func__,
1464 tx_port_id, rx_port_id, enable, gain);
1465 index = q6audio_get_port_index(rx_port_id);
1466 if (q6audio_validate_port(rx_port_id) < 0)
1467 return -EINVAL;
1468
1469 cmd_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1470 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1471 cmd_sidetone.hdr.pkt_size = sizeof(cmd_sidetone);
1472 cmd_sidetone.hdr.src_port = 0;
1473 cmd_sidetone.hdr.dest_port = 0;
1474 cmd_sidetone.hdr.token = 0;
1475 cmd_sidetone.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
1476 /* should it be rx or tx port id ?? , bharath*/
1477 cmd_sidetone.param.port_id = tx_port_id;
1478 /* size of data param & payload */
1479 cmd_sidetone.param.payload_size = (sizeof(cmd_sidetone) -
1480 sizeof(struct apr_hdr) -
1481 sizeof(struct afe_port_cmd_set_param_v2));
1482 cmd_sidetone.param.payload_address_lsw = 0x00;
1483 cmd_sidetone.param.payload_address_msw = 0x00;
1484 cmd_sidetone.param.mem_map_handle = 0x00;
1485 cmd_sidetone.pdata.module_id = AFE_MODULE_LOOPBACK;
1486 cmd_sidetone.pdata.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
1487 /* size of actual payload only */
1488 cmd_sidetone.pdata.param_size = cmd_sidetone.param.payload_size -
1489 sizeof(struct afe_port_param_data_v2);
1490
1491 cmd_sidetone.loopback_cfg_minor_version =
1492 AFE_API_VERSION_LOOPBACK_CONFIG;
1493 cmd_sidetone.dst_port_id = rx_port_id;
1494 cmd_sidetone.routing_mode = LB_MODE_SIDETONE;
1495 cmd_sidetone.enable = enable;
1496
1497 atomic_set(&this_afe.state, 1);
1498 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_sidetone);
1499 if (ret < 0) {
1500 pr_err("%s: AFE sidetone failed for tx_port:%d rx_port:%d\n",
1501 __func__, tx_port_id, rx_port_id);
1502 ret = -EINVAL;
1503 goto fail_cmd;
1504 }
1505
1506 ret = wait_event_timeout(this_afe.wait[index],
1507 (atomic_read(&this_afe.state) == 0),
1508 msecs_to_jiffies(TIMEOUT_MS));
1509 if (ret < 0) {
1510 pr_err("%s: wait_event timeout\n", __func__);
1511 ret = -EINVAL;
1512 goto fail_cmd;
1513 }
1514 return 0;
1515fail_cmd:
1516 return ret;
1517}
1518
Joonwoo Park6572ac52012-07-10 17:17:00 -07001519int afe_validate_port(u16 port_id)
1520{
1521 int ret;
1522
1523 switch (port_id) {
1524 case PRIMARY_I2S_RX:
1525 case PRIMARY_I2S_TX:
1526 case PCM_RX:
1527 case PCM_TX:
1528 case SECONDARY_I2S_RX:
1529 case SECONDARY_I2S_TX:
1530 case MI2S_RX:
1531 case MI2S_TX:
1532 case HDMI_RX:
1533 case RSVD_2:
1534 case RSVD_3:
1535 case DIGI_MIC_TX:
1536 case VOICE_RECORD_RX:
1537 case VOICE_RECORD_TX:
1538 case VOICE_PLAYBACK_TX:
1539 case SLIMBUS_0_RX:
1540 case SLIMBUS_0_TX:
1541 case SLIMBUS_1_RX:
1542 case SLIMBUS_1_TX:
1543 case SLIMBUS_2_RX:
1544 case SLIMBUS_2_TX:
1545 case SLIMBUS_3_RX:
1546 case INT_BT_SCO_RX:
1547 case INT_BT_SCO_TX:
1548 case INT_BT_A2DP_RX:
1549 case INT_FM_RX:
1550 case INT_FM_TX:
1551 case RT_PROXY_PORT_001_RX:
1552 case RT_PROXY_PORT_001_TX:
1553 case SLIMBUS_4_RX:
1554 case SLIMBUS_4_TX:
1555 {
1556 ret = 0;
1557 break;
1558 }
1559
1560 default:
1561 ret = -EINVAL;
1562 }
1563
1564 return ret;
1565}
1566
1567int afe_convert_virtual_to_portid(u16 port_id)
1568{
1569 int ret;
1570
1571 /*
1572 * if port_id is virtual, convert to physical..
1573 * if port_id is already physical, return physical
1574 */
1575 if (afe_validate_port(port_id) < 0) {
1576 if (port_id == RT_PROXY_DAI_001_RX ||
1577 port_id == RT_PROXY_DAI_001_TX ||
1578 port_id == RT_PROXY_DAI_002_RX ||
1579 port_id == RT_PROXY_DAI_002_TX)
1580 ret = VIRTUAL_ID_TO_PORTID(port_id);
1581 else
1582 ret = -EINVAL;
1583 } else
1584 ret = port_id;
1585
1586 return ret;
1587}
Bharath Ramachandramurthy2e3168f2012-05-03 16:29:09 -07001588int afe_port_stop_nowait(int port_id)
1589{
1590 struct afe_port_cmd_device_stop stop;
1591 int ret = 0;
1592
1593 if (this_afe.apr == NULL) {
1594 pr_err("AFE is already closed\n");
1595 ret = -EINVAL;
1596 goto fail_cmd;
1597 }
1598 pr_debug("%s: port_id=%d\n", __func__, port_id);
1599 port_id = q6audio_convert_virtual_to_portid(port_id);
1600
1601 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1602 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1603 stop.hdr.pkt_size = sizeof(stop);
1604 stop.hdr.src_port = 0;
1605 stop.hdr.dest_port = 0;
1606 stop.hdr.token = 0;
1607 stop.hdr.opcode = AFE_PORT_CMD_DEVICE_STOP;
1608 stop.port_id = port_id;
1609 stop.reserved = 0;
1610
1611 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1612
1613 if (IS_ERR_VALUE(ret)) {
1614 pr_err("%s: AFE close failed\n", __func__);
1615 ret = -EINVAL;
1616 }
1617
1618fail_cmd:
1619 return ret;
1620
1621}
1622
1623int afe_close(int port_id)
1624{
1625 struct afe_port_cmd_device_stop stop;
1626 int ret = 0;
1627 int index = 0;
1628
1629
1630 if (this_afe.apr == NULL) {
1631 pr_err("AFE is already closed\n");
1632 ret = -EINVAL;
1633 goto fail_cmd;
1634 }
1635 pr_debug("%s: port_id=%d\n", __func__, port_id);
1636
1637 index = q6audio_get_port_index(port_id);
1638 if (q6audio_validate_port(port_id) < 0)
1639 return -EINVAL;
1640
1641 port_id = q6audio_convert_virtual_to_portid(port_id);
1642
1643 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1644 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1645 stop.hdr.pkt_size = sizeof(stop);
1646 stop.hdr.src_port = 0;
1647 stop.hdr.dest_port = 0;
1648 stop.hdr.token = index;
1649 stop.hdr.opcode = AFE_PORT_CMD_DEVICE_STOP;
1650 stop.port_id = q6audio_get_port_id(port_id);
1651 stop.reserved = 0;
1652
1653 atomic_set(&this_afe.state, 1);
1654 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1655
1656 if (ret < 0) {
1657 pr_err("%s: AFE close failed\n", __func__);
1658 ret = -EINVAL;
1659 goto fail_cmd;
1660 }
1661
1662 ret = wait_event_timeout(this_afe.wait[index],
1663 (atomic_read(&this_afe.state) == 0),
1664 msecs_to_jiffies(TIMEOUT_MS));
1665 if (!ret) {
1666 pr_err("%s: wait_event timeout\n", __func__);
1667 ret = -EINVAL;
1668 goto fail_cmd;
1669 }
1670fail_cmd:
1671 return ret;
1672}
1673
1674static int __init afe_init(void)
1675{
1676 int i = 0;
1677 atomic_set(&this_afe.state, 0);
1678 atomic_set(&this_afe.status, 0);
1679 this_afe.apr = NULL;
1680 for (i = 0; i < AFE_MAX_PORTS; i++)
1681 init_waitqueue_head(&this_afe.wait[i]);
1682
1683 config_debug_fs_init();
1684 return 0;
1685}
1686
1687static void __exit afe_exit(void)
1688{
1689 int i;
1690
1691 config_debug_fs_exit();
1692 for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
1693 if (afe_cal_addr[i].cal_paddr != 0)
1694 afe_cmd_memory_unmap_nowait(
1695 afe_cal_addr[i].cal_paddr);
1696 }
1697}
1698
1699device_initcall(afe_init);
1700__exitcall(afe_exit);