blob: 302ef57ee0df64d364dc57b62ceeec60bf01c38c [file] [log] [blame]
Ben Rombergerb7603232011-11-23 17:16:27 -08001/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/debugfs.h>
14#include <linux/kernel.h>
15#include <linux/kthread.h>
16#include <linux/uaccess.h>
17#include <linux/wait.h>
18#include <linux/jiffies.h>
19#include <linux/sched.h>
Ben Rombergerb7603232011-11-23 17:16:27 -080020#include <mach/qdsp6v2/audio_acdb.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070021#include <sound/apr_audio.h>
22#include <sound/q6afe.h>
23
24struct afe_ctl {
25 void *apr;
26 atomic_t state;
27 atomic_t status;
28 wait_queue_head_t wait;
29 struct task_struct *task;
Laxminath Kasam32657ec2011-08-01 19:26:57 +053030 void (*tx_cb) (uint32_t opcode,
31 uint32_t token, uint32_t *payload, void *priv);
32 void (*rx_cb) (uint32_t opcode,
33 uint32_t token, uint32_t *payload, void *priv);
34 void *tx_private_data;
35 void *rx_private_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070036};
37
38static struct afe_ctl this_afe;
39
Ben Rombergerb7603232011-11-23 17:16:27 -080040static uint32_t afe_cal_addr[MAX_AUDPROC_TYPES];
41
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070042#define TIMEOUT_MS 1000
43#define Q6AFE_MAX_VOLUME 0x3FFF
44
45#define SIZEOF_CFG_CMD(y) \
46 (sizeof(struct apr_hdr) + sizeof(u16) + (sizeof(struct y)))
47
48static int32_t afe_callback(struct apr_client_data *data, void *priv)
49{
50 if (data->opcode == RESET_EVENTS) {
51 pr_debug("q6afe: reset event = %d %d apr[%p]\n",
52 data->reset_event, data->reset_proc, this_afe.apr);
53 if (this_afe.apr) {
54 apr_reset(this_afe.apr);
55 atomic_set(&this_afe.state, 0);
56 this_afe.apr = NULL;
57 }
58 /* send info to user */
59 pr_debug("task_name = %s pid = %d\n",
60 this_afe.task->comm, this_afe.task->pid);
61 send_sig(SIGUSR1, this_afe.task, 0);
Laxminath Kasam9bb28c62012-01-18 21:55:37 +053062 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070063 }
64 if (data->payload_size) {
65 uint32_t *payload;
Laxminath Kasam32657ec2011-08-01 19:26:57 +053066 uint16_t port_id = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070067 payload = data->payload;
Laxminath Kasam32657ec2011-08-01 19:26:57 +053068 pr_debug("%s:opcode = 0x%x cmd = 0x%x status = 0x%x\n",
69 __func__, data->opcode,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070070 payload[0], payload[1]);
71 /* payload[1] contains the error status for response */
72 if (payload[1] != 0) {
73 atomic_set(&this_afe.status, -1);
74 pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
75 __func__, payload[0], payload[1]);
76 }
77 if (data->opcode == APR_BASIC_RSP_RESULT) {
78 switch (payload[0]) {
79 case AFE_PORT_AUDIO_IF_CONFIG:
80 case AFE_PORT_CMD_STOP:
81 case AFE_PORT_CMD_START:
82 case AFE_PORT_CMD_LOOPBACK:
83 case AFE_PORT_CMD_SIDETONE_CTL:
84 case AFE_PORT_CMD_SET_PARAM:
85 case AFE_PSEUDOPORT_CMD_START:
86 case AFE_PSEUDOPORT_CMD_STOP:
Laxminath Kasam885f5102011-07-14 10:20:21 +053087 case AFE_PORT_CMD_APPLY_GAIN:
Laxminath Kasam32657ec2011-08-01 19:26:57 +053088 case AFE_SERVICE_CMD_MEMORY_MAP:
89 case AFE_SERVICE_CMD_MEMORY_UNMAP:
90 case AFE_SERVICE_CMD_UNREG_RTPORT:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070091 atomic_set(&this_afe.state, 0);
92 wake_up(&this_afe.wait);
93 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +053094 case AFE_SERVICE_CMD_REG_RTPORT:
95 break;
96 case AFE_SERVICE_CMD_RTPORT_WR:
97 port_id = RT_PROXY_PORT_001_TX;
98 break;
99 case AFE_SERVICE_CMD_RTPORT_RD:
100 port_id = RT_PROXY_PORT_001_RX;
101 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700102 default:
103 pr_err("Unknown cmd 0x%x\n",
104 payload[0]);
105 break;
106 }
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530107 } else if (data->opcode == AFE_EVENT_RT_PROXY_PORT_STATUS) {
108 port_id = (uint16_t)(0x0000FFFF & payload[0]);
109 }
110 pr_debug("%s:port_id = %x\n", __func__, port_id);
111 switch (port_id) {
112 case RT_PROXY_PORT_001_TX: {
113 if (this_afe.tx_cb) {
114 this_afe.tx_cb(data->opcode, data->token,
115 data->payload,
116 this_afe.tx_private_data);
117 }
118 break;
119 }
120 case RT_PROXY_PORT_001_RX: {
121 if (this_afe.rx_cb) {
122 this_afe.rx_cb(data->opcode, data->token,
123 data->payload,
124 this_afe.rx_private_data);
125 }
126 break;
127 }
128 default:
129 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700130 }
131 }
132 return 0;
133}
134
Neema Shettyfeea7742011-09-11 12:30:36 -0700135int 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 INT_BT_SCO_RX:
147 case INT_BT_A2DP_RX:
148 case INT_FM_RX:
149 case VOICE_PLAYBACK_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530150 case RT_PROXY_PORT_001_RX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700151 ret = MSM_AFE_PORT_TYPE_RX;
152 break;
153
154 case PRIMARY_I2S_TX:
155 case PCM_TX:
156 case SECONDARY_I2S_TX:
157 case MI2S_TX:
158 case DIGI_MIC_TX:
159 case VOICE_RECORD_TX:
160 case SLIMBUS_0_TX:
161 case INT_FM_TX:
162 case VOICE_RECORD_RX:
163 case INT_BT_SCO_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530164 case RT_PROXY_PORT_001_TX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700165 ret = MSM_AFE_PORT_TYPE_TX;
166 break;
167
168 default:
169 pr_err("%s: invalid port id\n", __func__);
170 ret = -EINVAL;
171 }
172
173 return ret;
174}
175
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700176int afe_validate_port(u16 port_id)
177{
178 int ret;
179
180 switch (port_id) {
181 case PRIMARY_I2S_RX:
182 case PRIMARY_I2S_TX:
183 case PCM_RX:
184 case PCM_TX:
185 case SECONDARY_I2S_RX:
186 case SECONDARY_I2S_TX:
187 case MI2S_RX:
188 case MI2S_TX:
189 case HDMI_RX:
190 case RSVD_2:
191 case RSVD_3:
192 case DIGI_MIC_TX:
193 case VOICE_RECORD_RX:
194 case VOICE_RECORD_TX:
195 case VOICE_PLAYBACK_TX:
196 case SLIMBUS_0_RX:
197 case SLIMBUS_0_TX:
198 case INT_BT_SCO_RX:
199 case INT_BT_SCO_TX:
200 case INT_BT_A2DP_RX:
201 case INT_FM_RX:
202 case INT_FM_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530203 case RT_PROXY_PORT_001_RX:
204 case RT_PROXY_PORT_001_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700205 {
206 ret = 0;
207 break;
208 }
209
210 default:
211 ret = -EINVAL;
212 }
213
214 return ret;
215}
216
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530217int afe_convert_virtual_to_portid(u16 port_id)
218{
219 int ret;
220
221 /* if port_id is virtual, convert to physical..
222 * if port_id is already physical, return physical
223 */
224 if (afe_validate_port(port_id) < 0) {
225 if (port_id == RT_PROXY_DAI_001_RX ||
226 port_id == RT_PROXY_DAI_001_TX ||
227 port_id == RT_PROXY_DAI_002_RX ||
228 port_id == RT_PROXY_DAI_002_TX)
229 ret = VIRTUAL_ID_TO_PORTID(port_id);
230 else
231 ret = -EINVAL;
232 } else
233 ret = port_id;
234
235 return ret;
236}
237
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700238int afe_get_port_index(u16 port_id)
239{
240 switch (port_id) {
241 case PRIMARY_I2S_RX: return IDX_PRIMARY_I2S_RX;
242 case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
243 case PCM_RX: return IDX_PCM_RX;
244 case PCM_TX: return IDX_PCM_TX;
245 case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
246 case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
247 case MI2S_RX: return IDX_MI2S_RX;
248 case MI2S_TX: return IDX_MI2S_TX;
249 case HDMI_RX: return IDX_HDMI_RX;
250 case RSVD_2: return IDX_RSVD_2;
251 case RSVD_3: return IDX_RSVD_3;
252 case DIGI_MIC_TX: return IDX_DIGI_MIC_TX;
253 case VOICE_RECORD_RX: return IDX_VOICE_RECORD_RX;
254 case VOICE_RECORD_TX: return IDX_VOICE_RECORD_TX;
255 case VOICE_PLAYBACK_TX: return IDX_VOICE_PLAYBACK_TX;
256 case SLIMBUS_0_RX: return IDX_SLIMBUS_0_RX;
257 case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
258 case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
259 case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
260 case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
261 case INT_FM_RX: return IDX_INT_FM_RX;
262 case INT_FM_TX: return IDX_INT_FM_TX;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530263 case RT_PROXY_PORT_001_RX: return IDX_RT_PROXY_PORT_001_RX;
264 case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700265
266 default: return -EINVAL;
267 }
268}
269
270int afe_sizeof_cfg_cmd(u16 port_id)
271{
272 int ret_size;
273 switch (port_id) {
274 case PRIMARY_I2S_RX:
275 case PRIMARY_I2S_TX:
276 case SECONDARY_I2S_RX:
277 case SECONDARY_I2S_TX:
278 case MI2S_RX:
279 case MI2S_TX:
280 ret_size = SIZEOF_CFG_CMD(afe_port_mi2s_cfg);
281 break;
282 case HDMI_RX:
283 ret_size = SIZEOF_CFG_CMD(afe_port_hdmi_cfg);
284 break;
285 case SLIMBUS_0_RX:
286 case SLIMBUS_0_TX:
287 ret_size = SIZEOF_CFG_CMD(afe_port_slimbus_cfg);
288 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530289 case RT_PROXY_PORT_001_RX:
290 case RT_PROXY_PORT_001_TX:
291 ret_size = SIZEOF_CFG_CMD(afe_port_rtproxy_cfg);
292 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700293 case PCM_RX:
294 case PCM_TX:
295 default:
296 ret_size = SIZEOF_CFG_CMD(afe_port_pcm_cfg);
297 break;
298 }
299 return ret_size;
300}
301
Jay Wang6a305432011-08-05 16:01:54 -0700302int afe_q6_interface_prepare(void)
303{
304 int ret = 0;
305
306 pr_debug("%s:", __func__);
307
308 if (this_afe.apr == NULL) {
309 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
310 0xFFFFFFFF, &this_afe);
311 pr_debug("%s: Register AFE\n", __func__);
312 if (this_afe.apr == NULL) {
313 pr_err("%s: Unable to register AFE\n", __func__);
314 ret = -ENODEV;
315 }
316 }
317 return ret;
318}
319
Ben Rombergerb7603232011-11-23 17:16:27 -0800320static void afe_send_cal_block(int32_t path, u16 port_id)
321{
322 int result = 0;
323 struct acdb_cal_block cal_block;
324 struct afe_port_cmd_set_param_no_payload afe_cal;
325 pr_debug("%s: path %d\n", __func__, path);
326
327 get_afe_cal(path, &cal_block);
328 if (cal_block.cal_size <= 0) {
329 pr_debug("%s: No AFE cal to send!\n", __func__);
330 goto done;
331 }
332
333 if (afe_cal_addr[path] != cal_block.cal_paddr) {
334 if (afe_cal_addr[path] != 0)
335 afe_cmd_memory_unmap_nowait(afe_cal_addr[path]);
336 afe_cmd_memory_map_nowait(cal_block.cal_paddr,
337 cal_block.cal_size);
338 afe_cal_addr[path] = cal_block.cal_paddr;
339 }
340
341 afe_cal.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
342 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
343 afe_cal.hdr.pkt_size = sizeof(afe_cal);
344 afe_cal.hdr.src_port = 0;
345 afe_cal.hdr.dest_port = 0;
346 afe_cal.hdr.token = 0;
347 afe_cal.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
348 afe_cal.port_id = port_id;
349 afe_cal.payload_size = cal_block.cal_size;
350 afe_cal.payload_address = cal_block.cal_paddr;
351
352 pr_debug("%s: AFE cal sent for device port = %d, path = %d, "
353 "cal size = %d, cal addr = 0x%x\n", __func__,
354 port_id, path, cal_block.cal_size, cal_block.cal_paddr);
355
356 result = apr_send_pkt(this_afe.apr, (uint32_t *) &afe_cal);
357 if (result < 0) {
358 pr_err("%s: AFE cal for port %d failed\n",
359 __func__, port_id);
360 }
361
362 pr_debug("%s: AFE cal sent for path %d device!\n", __func__, path);
363done:
364 return;
365}
366
367void afe_send_cal(u16 port_id)
368{
369 pr_debug("%s\n", __func__);
370
371 if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX)
372 afe_send_cal_block(TX_CAL, port_id);
373 else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX)
374 afe_send_cal_block(RX_CAL, port_id);
375}
376
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700377int afe_port_start_nowait(u16 port_id, union afe_port_config *afe_config,
378 u32 rate) /* This function is no blocking */
379{
380 struct afe_port_start_command start;
381 struct afe_audioif_config_command config;
382 int ret;
383
384 if (!afe_config) {
385 pr_err("%s: Error, no configuration data\n", __func__);
386 ret = -EINVAL;
387 return ret;
388 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -0800389 pr_debug("%s: %d %d\n", __func__, port_id, rate);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700390
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530391 if ((port_id == RT_PROXY_DAI_001_RX) ||
392 (port_id == RT_PROXY_DAI_002_TX))
393 return -EINVAL;
394 if ((port_id == RT_PROXY_DAI_002_RX) ||
395 (port_id == RT_PROXY_DAI_001_TX))
396 port_id = VIRTUAL_ID_TO_PORTID(port_id);
397
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700398 if (this_afe.apr == NULL) {
Jay Wang6a305432011-08-05 16:01:54 -0700399 pr_err("%s: AFE APR is not registered\n", __func__);
400 ret = -ENODEV;
401 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700402 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700403 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
404 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
405 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
406 config.hdr.src_port = 0;
407 config.hdr.dest_port = 0;
408 config.hdr.token = 0;
409 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
410
411 if (afe_validate_port(port_id) < 0) {
412
413 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
414 port_id);
415 ret = -EINVAL;
416 goto fail_cmd;
417 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700418 config.port_id = port_id;
419 config.port = *afe_config;
420
421 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
422 if (ret < 0) {
423 pr_err("%s: AFE enable for port %d failed\n", __func__,
424 port_id);
425 ret = -EINVAL;
426 goto fail_cmd;
427 }
Ben Rombergerb7603232011-11-23 17:16:27 -0800428
429 /* send AFE cal */
430 afe_send_cal(port_id);
431
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700432 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
433 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
434 start.hdr.pkt_size = sizeof(start);
435 start.hdr.src_port = 0;
436 start.hdr.dest_port = 0;
437 start.hdr.token = 0;
438 start.hdr.opcode = AFE_PORT_CMD_START;
439 start.port_id = port_id;
440 start.gain = 0x2000;
441 start.sample_rate = rate;
442
443 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
444
445 if (IS_ERR_VALUE(ret)) {
446 pr_err("%s: AFE enable for port %d failed\n", __func__,
447 port_id);
448 ret = -EINVAL;
449 goto fail_cmd;
450 }
451
452 if (this_afe.task != current)
453 this_afe.task = current;
454
455 pr_debug("task_name = %s pid = %d\n",
456 this_afe.task->comm, this_afe.task->pid);
457 return 0;
458
459fail_cmd:
460 return ret;
461}
462
463int afe_open(u16 port_id, union afe_port_config *afe_config, int rate)
464{
465 struct afe_port_start_command start;
466 struct afe_audioif_config_command config;
467 int ret = 0;
468
469 if (!afe_config) {
470 pr_err("%s: Error, no configuration data\n", __func__);
471 ret = -EINVAL;
472 return ret;
473 }
474
475 pr_info("%s: %d %d\n", __func__, port_id, rate);
476
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530477 if ((port_id == RT_PROXY_DAI_001_RX) ||
478 (port_id == RT_PROXY_DAI_002_TX))
479 return -EINVAL;
480 if ((port_id == RT_PROXY_DAI_002_RX) ||
481 (port_id == RT_PROXY_DAI_001_TX))
482 port_id = VIRTUAL_ID_TO_PORTID(port_id);
483
Jay Wang6a305432011-08-05 16:01:54 -0700484 ret = afe_q6_interface_prepare();
485 if (ret != 0)
486 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700487
488 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
489 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
490 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
491 config.hdr.src_port = 0;
492 config.hdr.dest_port = 0;
493 config.hdr.token = 0;
494 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
495
496 if (afe_validate_port(port_id) < 0) {
497
498 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
499 port_id);
500 ret = -EINVAL;
501 goto fail_cmd;
502 }
503
504 config.port_id = port_id;
505 config.port = *afe_config;
506
507 atomic_set(&this_afe.state, 1);
508 atomic_set(&this_afe.status, 0);
509 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
510 if (ret < 0) {
511 pr_err("%s: AFE enable for port %d failed\n", __func__,
512 port_id);
513 ret = -EINVAL;
514 goto fail_cmd;
515 }
516
517 ret = wait_event_timeout(this_afe.wait,
518 (atomic_read(&this_afe.state) == 0),
519 msecs_to_jiffies(TIMEOUT_MS));
520 if (!ret) {
521 pr_err("%s: wait_event timeout\n", __func__);
522 ret = -EINVAL;
523 goto fail_cmd;
524 }
525 if (atomic_read(&this_afe.status) != 0) {
526 pr_err("%s: config cmd failed\n", __func__);
527 ret = -EINVAL;
528 goto fail_cmd;
529 }
530 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
531 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
532 start.hdr.pkt_size = sizeof(start);
533 start.hdr.src_port = 0;
534 start.hdr.dest_port = 0;
535 start.hdr.token = 0;
536 start.hdr.opcode = AFE_PORT_CMD_START;
537 start.port_id = port_id;
538 start.gain = 0x2000;
539 start.sample_rate = rate;
540
541 atomic_set(&this_afe.state, 1);
542 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
543 if (ret < 0) {
544 pr_err("%s: AFE enable for port %d failed\n", __func__,
545 port_id);
546 ret = -EINVAL;
547 goto fail_cmd;
548 }
549 ret = wait_event_timeout(this_afe.wait,
550 (atomic_read(&this_afe.state) == 0),
551 msecs_to_jiffies(TIMEOUT_MS));
552 if (!ret) {
553 pr_err("%s: wait_event timeout\n", __func__);
554 ret = -EINVAL;
555 goto fail_cmd;
556 }
557
558 if (this_afe.task != current)
559 this_afe.task = current;
560
561 pr_debug("task_name = %s pid = %d\n",
562 this_afe.task->comm, this_afe.task->pid);
563 return 0;
564fail_cmd:
565 return ret;
566}
567
568int afe_loopback(u16 enable, u16 rx_port, u16 tx_port)
569{
570 struct afe_loopback_command lb_cmd;
571 int ret = 0;
Jay Wang6a305432011-08-05 16:01:54 -0700572
573 ret = afe_q6_interface_prepare();
574 if (ret != 0)
575 return ret;
576
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700577 lb_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
578 APR_HDR_LEN(20), APR_PKT_VER);
579 lb_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
580 sizeof(lb_cmd) - APR_HDR_SIZE);
581 lb_cmd.hdr.src_port = 0;
582 lb_cmd.hdr.dest_port = 0;
583 lb_cmd.hdr.token = 0;
584 lb_cmd.hdr.opcode = AFE_PORT_CMD_LOOPBACK;
585 lb_cmd.tx_port_id = tx_port;
586 lb_cmd.rx_port_id = rx_port;
587 lb_cmd.mode = 0xFFFF;
588 lb_cmd.enable = (enable ? 1 : 0);
589 atomic_set(&this_afe.state, 1);
590
591 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &lb_cmd);
592 if (ret < 0) {
593 pr_err("%s: AFE loopback failed\n", __func__);
594 ret = -EINVAL;
595 goto done;
596 }
597 ret = wait_event_timeout(this_afe.wait,
598 (atomic_read(&this_afe.state) == 0),
599 msecs_to_jiffies(TIMEOUT_MS));
600 if (!ret) {
601 pr_err("%s: wait_event timeout\n", __func__);
602 ret = -EINVAL;
603 }
604done:
605 return ret;
606}
607
608
609int afe_loopback_gain(u16 port_id, u16 volume)
610{
611 struct afe_port_cmd_set_param set_param;
612 int ret = 0;
613
614 if (this_afe.apr == NULL) {
Jayasena Sangaraboina82435032011-07-26 15:23:00 -0700615 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
616 0xFFFFFFFF, &this_afe);
617 pr_debug("%s: Register AFE\n", __func__);
618 if (this_afe.apr == NULL) {
619 pr_err("%s: Unable to register AFE\n", __func__);
620 ret = -ENODEV;
621 return ret;
622 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700623 }
624
625 if (afe_validate_port(port_id) < 0) {
626
627 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
628 port_id);
629 ret = -EINVAL;
630 goto fail_cmd;
631 }
632
633 /* RX ports numbers are even .TX ports numbers are odd. */
634 if (port_id % 2 == 0) {
635 pr_err("%s: Failed : afe loopback gain only for TX ports."
636 " port_id %d\n", __func__, port_id);
637 ret = -EINVAL;
638 goto fail_cmd;
639 }
640
641 pr_debug("%s: %d %hX\n", __func__, port_id, volume);
642
643 set_param.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
644 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
645 set_param.hdr.pkt_size = sizeof(set_param);
646 set_param.hdr.src_port = 0;
647 set_param.hdr.dest_port = 0;
648 set_param.hdr.token = 0;
649 set_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
650
651 set_param.port_id = port_id;
652 set_param.payload_size = sizeof(struct afe_param_payload);
653 set_param.payload_address = 0;
654
655 set_param.payload.module_id = AFE_MODULE_ID_PORT_INFO;
656 set_param.payload.param_id = AFE_PARAM_ID_LOOPBACK_GAIN;
657 set_param.payload.param_size = sizeof(struct afe_param_loopback_gain);
658 set_param.payload.reserved = 0;
659
660 set_param.payload.param.loopback_gain.gain = volume;
661 set_param.payload.param.loopback_gain.reserved = 0;
662
663 atomic_set(&this_afe.state, 1);
664 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_param);
665 if (ret < 0) {
666 pr_err("%s: AFE param set failed for port %d\n",
667 __func__, port_id);
668 ret = -EINVAL;
669 goto fail_cmd;
670 }
671
672 ret = wait_event_timeout(this_afe.wait,
673 (atomic_read(&this_afe.state) == 0),
674 msecs_to_jiffies(TIMEOUT_MS));
675 if (ret < 0) {
676 pr_err("%s: wait_event timeout\n", __func__);
677 ret = -EINVAL;
678 goto fail_cmd;
679 }
680 return 0;
681fail_cmd:
682 return ret;
683}
684
Laxminath Kasam885f5102011-07-14 10:20:21 +0530685int afe_apply_gain(u16 port_id, u16 gain)
686{
687 struct afe_port_gain_command set_gain;
688 int ret = 0;
689
690 if (this_afe.apr == NULL) {
691 pr_err("%s: AFE is not opened\n", __func__);
692 ret = -EPERM;
693 goto fail_cmd;
694 }
695
696 if (afe_validate_port(port_id) < 0) {
697 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
698 port_id);
699 ret = -EINVAL;
700 goto fail_cmd;
701 }
702
703 /* RX ports numbers are even .TX ports numbers are odd. */
704 if (port_id % 2 == 0) {
705 pr_err("%s: Failed : afe apply gain only for TX ports."
706 " port_id %d\n", __func__, port_id);
707 ret = -EINVAL;
708 goto fail_cmd;
709 }
710
711 pr_debug("%s: %d %hX\n", __func__, port_id, gain);
712
713 set_gain.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
714 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
715 set_gain.hdr.pkt_size = sizeof(set_gain);
716 set_gain.hdr.src_port = 0;
717 set_gain.hdr.dest_port = 0;
718 set_gain.hdr.token = 0;
719 set_gain.hdr.opcode = AFE_PORT_CMD_APPLY_GAIN;
720
721 set_gain.port_id = port_id;
722 set_gain.gain = gain;
723
724 atomic_set(&this_afe.state, 1);
725 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_gain);
726 if (ret < 0) {
727 pr_err("%s: AFE Gain set failed for port %d\n",
728 __func__, port_id);
729 ret = -EINVAL;
730 goto fail_cmd;
731 }
732
733 ret = wait_event_timeout(this_afe.wait,
734 (atomic_read(&this_afe.state) == 0),
735 msecs_to_jiffies(TIMEOUT_MS));
736 if (ret < 0) {
737 pr_err("%s: wait_event timeout\n", __func__);
738 ret = -EINVAL;
739 goto fail_cmd;
740 }
741 return 0;
742fail_cmd:
743 return ret;
744}
Helen Zeng0705a5f2011-10-14 15:29:52 -0700745
746int afe_pseudo_port_start_nowait(u16 port_id)
747{
748 int ret = 0;
749 struct afe_pseudoport_start_command start;
750
751 pr_debug("%s: port_id=%d\n", __func__, port_id);
752 if (this_afe.apr == NULL) {
753 pr_err("%s: AFE APR is not registered\n", __func__);
754 return -ENODEV;
755 }
756
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 atomic_set(&this_afe.state, 1);
769 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
770 if (ret < 0) {
771 pr_err("%s: AFE enable for port %d failed %d\n",
772 __func__, port_id, ret);
773 return -EINVAL;
774 }
775 return 0;
776}
777
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700778int afe_start_pseudo_port(u16 port_id)
779{
780 int ret = 0;
781 struct afe_pseudoport_start_command start;
782
783 pr_info("%s: port_id=%d\n", __func__, port_id);
784
Jay Wang6a305432011-08-05 16:01:54 -0700785 ret = afe_q6_interface_prepare();
786 if (ret != 0)
787 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700788
789 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
790 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
791 start.hdr.pkt_size = sizeof(start);
792 start.hdr.src_port = 0;
793 start.hdr.dest_port = 0;
794 start.hdr.token = 0;
795 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
796 start.port_id = port_id;
797 start.timing = 1;
798
799 atomic_set(&this_afe.state, 1);
800 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
801 if (ret < 0) {
802 pr_err("%s: AFE enable for port %d failed %d\n",
803 __func__, port_id, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700804 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700805 }
806
807 ret = wait_event_timeout(this_afe.wait,
808 (atomic_read(&this_afe.state) == 0),
809 msecs_to_jiffies(TIMEOUT_MS));
810 if (!ret) {
811 pr_err("%s: wait_event timeout\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700812 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700813 }
814
815 return 0;
816}
817
Helen Zeng0705a5f2011-10-14 15:29:52 -0700818int afe_pseudo_port_stop_nowait(u16 port_id)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700819{
820 int ret = 0;
821 struct afe_pseudoport_stop_command stop;
822
Helen Zeng0705a5f2011-10-14 15:29:52 -0700823 pr_debug("%s: port_id=%d\n", __func__, port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700824
825 if (this_afe.apr == NULL) {
826 pr_err("%s: AFE is already closed\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700827 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700828 }
829
830 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
831 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
832 stop.hdr.pkt_size = sizeof(stop);
833 stop.hdr.src_port = 0;
834 stop.hdr.dest_port = 0;
835 stop.hdr.token = 0;
836 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
837 stop.port_id = port_id;
838 stop.reserved = 0;
839
840 atomic_set(&this_afe.state, 1);
841 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
842 if (ret < 0) {
843 pr_err("%s: AFE close failed %d\n", __func__, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700844 return -EINVAL;
845 }
846
847 return 0;
848
849}
850
851int afe_stop_pseudo_port(u16 port_id)
852{
853 int ret = 0;
854 struct afe_pseudoport_stop_command stop;
855
856 pr_info("%s: port_id=%d\n", __func__, port_id);
857
858 if (this_afe.apr == NULL) {
859 pr_err("%s: AFE is already closed\n", __func__);
860 return -EINVAL;
861 }
862
863 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
864 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
865 stop.hdr.pkt_size = sizeof(stop);
866 stop.hdr.src_port = 0;
867 stop.hdr.dest_port = 0;
868 stop.hdr.token = 0;
869 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
870 stop.port_id = port_id;
871 stop.reserved = 0;
872
873 atomic_set(&this_afe.state, 1);
874 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
875 if (ret < 0) {
876 pr_err("%s: AFE close failed %d\n", __func__, ret);
877 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700878 }
879
880 ret = wait_event_timeout(this_afe.wait,
881 (atomic_read(&this_afe.state) == 0),
882 msecs_to_jiffies(TIMEOUT_MS));
883 if (!ret) {
884 pr_err("%s: wait_event timeout\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700885 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700886 }
887
888 return 0;
889}
890
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530891int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz)
892{
893 int ret = 0;
894 struct afe_cmd_memory_map mregion;
895
896 pr_debug("%s:\n", __func__);
897
898 if (this_afe.apr == NULL) {
899 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
900 0xFFFFFFFF, &this_afe);
901 pr_debug("%s: Register AFE\n", __func__);
902 if (this_afe.apr == NULL) {
903 pr_err("%s: Unable to register AFE\n", __func__);
904 ret = -ENODEV;
905 return ret;
906 }
907 }
908
909 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
910 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
911 mregion.hdr.pkt_size = sizeof(mregion);
912 mregion.hdr.src_port = 0;
913 mregion.hdr.dest_port = 0;
914 mregion.hdr.token = 0;
915 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
916 mregion.phy_addr = dma_addr_p;
917 mregion.mem_sz = dma_buf_sz;
918 mregion.mem_id = 0;
919 mregion.rsvd = 0;
920
921 atomic_set(&this_afe.state, 1);
922 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
923 if (ret < 0) {
924 pr_err("%s: AFE memory map cmd failed %d\n",
925 __func__, ret);
926 ret = -EINVAL;
927 return ret;
928 }
929
930 ret = wait_event_timeout(this_afe.wait,
931 (atomic_read(&this_afe.state) == 0),
932 msecs_to_jiffies(TIMEOUT_MS));
933 if (!ret) {
934 pr_err("%s: wait_event timeout\n", __func__);
935 ret = -EINVAL;
936 return ret;
937 }
938
939 return 0;
940}
941
Ben Rombergerb7603232011-11-23 17:16:27 -0800942int afe_cmd_memory_map_nowait(u32 dma_addr_p, u32 dma_buf_sz)
943{
944 int ret = 0;
945 struct afe_cmd_memory_map mregion;
946
947 pr_debug("%s:\n", __func__);
948
949 if (this_afe.apr == NULL) {
950 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
951 0xFFFFFFFF, &this_afe);
952 pr_debug("%s: Register AFE\n", __func__);
953 if (this_afe.apr == NULL) {
954 pr_err("%s: Unable to register AFE\n", __func__);
955 ret = -ENODEV;
956 return ret;
957 }
958 }
959
960 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
961 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
962 mregion.hdr.pkt_size = sizeof(mregion);
963 mregion.hdr.src_port = 0;
964 mregion.hdr.dest_port = 0;
965 mregion.hdr.token = 0;
966 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
967 mregion.phy_addr = dma_addr_p;
968 mregion.mem_sz = dma_buf_sz;
969 mregion.mem_id = 0;
970 mregion.rsvd = 0;
971
972 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
973 if (ret < 0) {
974 pr_err("%s: AFE memory map cmd failed %d\n",
975 __func__, ret);
976 ret = -EINVAL;
977 }
978 return 0;
979}
980
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530981int afe_cmd_memory_unmap(u32 dma_addr_p)
982{
983 int ret = 0;
984 struct afe_cmd_memory_unmap mregion;
985
986 pr_debug("%s:\n", __func__);
987
988 if (this_afe.apr == NULL) {
989 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
990 0xFFFFFFFF, &this_afe);
991 pr_debug("%s: Register AFE\n", __func__);
992 if (this_afe.apr == NULL) {
993 pr_err("%s: Unable to register AFE\n", __func__);
994 ret = -ENODEV;
995 return ret;
996 }
997 }
998
999 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1000 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1001 mregion.hdr.pkt_size = sizeof(mregion);
1002 mregion.hdr.src_port = 0;
1003 mregion.hdr.dest_port = 0;
1004 mregion.hdr.token = 0;
1005 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
1006 mregion.phy_addr = dma_addr_p;
1007
1008 atomic_set(&this_afe.state, 1);
1009 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1010 if (ret < 0) {
Ben Rombergerb7603232011-11-23 17:16:27 -08001011 pr_err("%s: AFE memory unmap cmd failed %d\n",
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301012 __func__, ret);
1013 ret = -EINVAL;
1014 return ret;
1015 }
1016
1017 ret = wait_event_timeout(this_afe.wait,
1018 (atomic_read(&this_afe.state) == 0),
1019 msecs_to_jiffies(TIMEOUT_MS));
1020 if (!ret) {
1021 pr_err("%s: wait_event timeout\n", __func__);
1022 ret = -EINVAL;
1023 return ret;
1024 }
Ben Rombergerb7603232011-11-23 17:16:27 -08001025 return 0;
1026}
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301027
Ben Rombergerb7603232011-11-23 17:16:27 -08001028int afe_cmd_memory_unmap_nowait(u32 dma_addr_p)
1029{
1030 int ret = 0;
1031 struct afe_cmd_memory_unmap mregion;
1032
1033 pr_debug("%s:\n", __func__);
1034
1035 if (this_afe.apr == NULL) {
1036 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1037 0xFFFFFFFF, &this_afe);
1038 pr_debug("%s: Register AFE\n", __func__);
1039 if (this_afe.apr == NULL) {
1040 pr_err("%s: Unable to register AFE\n", __func__);
1041 ret = -ENODEV;
1042 return ret;
1043 }
1044 }
1045
1046 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1047 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1048 mregion.hdr.pkt_size = sizeof(mregion);
1049 mregion.hdr.src_port = 0;
1050 mregion.hdr.dest_port = 0;
1051 mregion.hdr.token = 0;
1052 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
1053 mregion.phy_addr = dma_addr_p;
1054
1055 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1056 if (ret < 0) {
1057 pr_err("%s: AFE memory unmap cmd failed %d\n",
1058 __func__, ret);
1059 ret = -EINVAL;
1060 }
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301061 return 0;
1062}
1063
1064int afe_register_get_events(u16 port_id,
1065 void (*cb) (uint32_t opcode,
1066 uint32_t token, uint32_t *payload, void *priv),
1067 void *private_data)
1068{
1069 int ret = 0;
1070 struct afe_cmd_reg_rtport rtproxy;
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 if ((port_id == RT_PROXY_DAI_002_RX) ||
1085 (port_id == RT_PROXY_DAI_001_TX))
1086 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1087 else
1088 return -EINVAL;
1089
1090 if (port_id == RT_PROXY_PORT_001_TX) {
1091 this_afe.tx_cb = cb;
1092 this_afe.tx_private_data = private_data;
1093 } else if (port_id == RT_PROXY_PORT_001_RX) {
1094 this_afe.rx_cb = cb;
1095 this_afe.rx_private_data = private_data;
1096 }
1097
1098 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1099 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1100 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1101 rtproxy.hdr.src_port = 1;
1102 rtproxy.hdr.dest_port = 1;
1103 rtproxy.hdr.token = 0;
1104 rtproxy.hdr.opcode = AFE_SERVICE_CMD_REG_RTPORT;
1105 rtproxy.port_id = port_id;
1106 rtproxy.rsvd = 0;
1107
1108 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1109 if (ret < 0) {
1110 pr_err("%s: AFE reg. rtproxy_event failed %d\n",
1111 __func__, ret);
1112 ret = -EINVAL;
1113 return ret;
1114 }
1115 return 0;
1116}
1117
1118int afe_unregister_get_events(u16 port_id)
1119{
1120 int ret = 0;
1121 struct afe_cmd_unreg_rtport rtproxy;
1122
1123 pr_debug("%s:\n", __func__);
1124
1125 if (this_afe.apr == NULL) {
1126 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1127 0xFFFFFFFF, &this_afe);
1128 pr_debug("%s: Register AFE\n", __func__);
1129 if (this_afe.apr == NULL) {
1130 pr_err("%s: Unable to register AFE\n", __func__);
1131 ret = -ENODEV;
1132 return ret;
1133 }
1134 }
1135 if ((port_id == RT_PROXY_DAI_002_RX) ||
1136 (port_id == RT_PROXY_DAI_001_TX))
1137 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1138 else
1139 return -EINVAL;
1140
1141 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1142 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1143 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1144 rtproxy.hdr.src_port = 0;
1145 rtproxy.hdr.dest_port = 0;
1146 rtproxy.hdr.token = 0;
1147 rtproxy.hdr.opcode = AFE_SERVICE_CMD_UNREG_RTPORT;
1148 rtproxy.port_id = port_id;
1149 rtproxy.rsvd = 0;
1150
1151 if (port_id == RT_PROXY_PORT_001_TX) {
1152 this_afe.tx_cb = NULL;
1153 this_afe.tx_private_data = NULL;
1154 } else if (port_id == RT_PROXY_PORT_001_RX) {
1155 this_afe.rx_cb = NULL;
1156 this_afe.rx_private_data = NULL;
1157 }
1158
1159 atomic_set(&this_afe.state, 1);
1160 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1161 if (ret < 0) {
1162 pr_err("%s: AFE enable Unreg. rtproxy_event failed %d\n",
1163 __func__, ret);
1164 ret = -EINVAL;
1165 return ret;
1166 }
1167
1168 ret = wait_event_timeout(this_afe.wait,
1169 (atomic_read(&this_afe.state) == 0),
1170 msecs_to_jiffies(TIMEOUT_MS));
1171 if (!ret) {
1172 pr_err("%s: wait_event timeout\n", __func__);
1173 ret = -EINVAL;
1174 return ret;
1175 }
1176 return 0;
1177}
1178
1179int afe_rt_proxy_port_write(u32 buf_addr_p, int bytes)
1180{
1181 int ret = 0;
1182 struct afe_cmd_rtport_wr afecmd_wr;
1183
1184 if (this_afe.apr == NULL) {
1185 pr_err("%s:register to AFE is not done\n", __func__);
1186 ret = -ENODEV;
1187 return ret;
1188 }
1189 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1190 buf_addr_p, bytes);
1191
1192 afecmd_wr.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1193 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1194 afecmd_wr.hdr.pkt_size = sizeof(afecmd_wr);
1195 afecmd_wr.hdr.src_port = 0;
1196 afecmd_wr.hdr.dest_port = 0;
1197 afecmd_wr.hdr.token = 0;
1198 afecmd_wr.hdr.opcode = AFE_SERVICE_CMD_RTPORT_WR;
1199 afecmd_wr.buf_addr = (uint32_t)buf_addr_p;
1200 afecmd_wr.port_id = RT_PROXY_PORT_001_TX;
1201 afecmd_wr.bytes_avail = bytes;
1202 afecmd_wr.rsvd = 0;
1203
1204 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_wr);
1205 if (ret < 0) {
1206 pr_err("%s: AFE rtproxy write to port 0x%x failed %d\n",
1207 __func__, afecmd_wr.port_id, ret);
1208 ret = -EINVAL;
1209 return ret;
1210 }
1211 return 0;
1212
1213}
1214
1215int afe_rt_proxy_port_read(u32 buf_addr_p, int bytes)
1216{
1217 int ret = 0;
1218 struct afe_cmd_rtport_rd afecmd_rd;
1219
1220 if (this_afe.apr == NULL) {
1221 pr_err("%s: register to AFE is not done\n", __func__);
1222 ret = -ENODEV;
1223 return ret;
1224 }
1225 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1226 buf_addr_p, bytes);
1227
1228 afecmd_rd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1229 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1230 afecmd_rd.hdr.pkt_size = sizeof(afecmd_rd);
1231 afecmd_rd.hdr.src_port = 0;
1232 afecmd_rd.hdr.dest_port = 0;
1233 afecmd_rd.hdr.token = 0;
1234 afecmd_rd.hdr.opcode = AFE_SERVICE_CMD_RTPORT_RD;
1235 afecmd_rd.buf_addr = (uint32_t)buf_addr_p;
1236 afecmd_rd.port_id = RT_PROXY_PORT_001_RX;
1237 afecmd_rd.bytes_avail = bytes;
1238 afecmd_rd.rsvd = 0;
1239
1240 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_rd);
1241 if (ret < 0) {
1242 pr_err("%s: AFE rtproxy read cmd to port 0x%x failed %d\n",
1243 __func__, afecmd_rd.port_id, ret);
1244 ret = -EINVAL;
1245 return ret;
1246 }
1247 return 0;
1248}
1249
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001250#ifdef CONFIG_DEBUG_FS
1251static struct dentry *debugfs_afelb;
1252static struct dentry *debugfs_afelb_gain;
1253
1254static int afe_debug_open(struct inode *inode, struct file *file)
1255{
1256 file->private_data = inode->i_private;
1257 pr_info("debug intf %s\n", (char *) file->private_data);
1258 return 0;
1259}
1260
1261static int afe_get_parameters(char *buf, long int *param1, int num_of_par)
1262{
1263 char *token;
1264 int base, cnt;
1265
1266 token = strsep(&buf, " ");
1267
1268 for (cnt = 0; cnt < num_of_par; cnt++) {
1269 if (token != NULL) {
1270 if ((token[1] == 'x') || (token[1] == 'X'))
1271 base = 16;
1272 else
1273 base = 10;
1274
1275 if (strict_strtoul(token, base, &param1[cnt]) != 0)
1276 return -EINVAL;
1277
1278 token = strsep(&buf, " ");
1279 } else
1280 return -EINVAL;
1281 }
1282 return 0;
1283}
1284#define AFE_LOOPBACK_ON (1)
1285#define AFE_LOOPBACK_OFF (0)
1286static ssize_t afe_debug_write(struct file *filp,
1287 const char __user *ubuf, size_t cnt, loff_t *ppos)
1288{
1289 char *lb_str = filp->private_data;
1290 char lbuf[32];
1291 int rc;
1292 unsigned long param[5];
1293
1294 if (cnt > sizeof(lbuf) - 1)
1295 return -EINVAL;
1296
1297 rc = copy_from_user(lbuf, ubuf, cnt);
1298 if (rc)
1299 return -EFAULT;
1300
1301 lbuf[cnt] = '\0';
1302
1303 if (!strcmp(lb_str, "afe_loopback")) {
1304 rc = afe_get_parameters(lbuf, param, 3);
1305 if (!rc) {
1306 pr_info("%s %lu %lu %lu\n", lb_str, param[0], param[1],
1307 param[2]);
1308
1309 if ((param[0] != AFE_LOOPBACK_ON) && (param[0] !=
1310 AFE_LOOPBACK_OFF)) {
1311 pr_err("%s: Error, parameter 0 incorrect\n",
1312 __func__);
1313 rc = -EINVAL;
1314 goto afe_error;
1315 }
1316 if ((afe_validate_port(param[1]) < 0) ||
1317 (afe_validate_port(param[2])) < 0) {
1318 pr_err("%s: Error, invalid afe port\n",
1319 __func__);
1320 }
1321 if (this_afe.apr == NULL) {
1322 pr_err("%s: Error, AFE not opened\n", __func__);
1323 rc = -EINVAL;
1324 } else {
1325 rc = afe_loopback(param[0], param[1], param[2]);
1326 }
1327 } else {
1328 pr_err("%s: Error, invalid parameters\n", __func__);
1329 rc = -EINVAL;
1330 }
1331
1332 } else if (!strcmp(lb_str, "afe_loopback_gain")) {
1333 rc = afe_get_parameters(lbuf, param, 2);
1334 if (!rc) {
1335 pr_info("%s %lu %lu\n", lb_str, param[0], param[1]);
1336
1337 if (afe_validate_port(param[0]) < 0) {
1338 pr_err("%s: Error, invalid afe port\n",
1339 __func__);
1340 rc = -EINVAL;
1341 goto afe_error;
1342 }
1343
1344 if (param[1] < 0 || param[1] > 100) {
1345 pr_err("%s: Error, volume shoud be 0 to 100"
1346 " percentage param = %lu\n",
1347 __func__, param[1]);
1348 rc = -EINVAL;
1349 goto afe_error;
1350 }
1351
1352 param[1] = (Q6AFE_MAX_VOLUME * param[1]) / 100;
1353
1354 if (this_afe.apr == NULL) {
1355 pr_err("%s: Error, AFE not opened\n", __func__);
1356 rc = -EINVAL;
1357 } else {
1358 rc = afe_loopback_gain(param[0], param[1]);
1359 }
1360 } else {
1361 pr_err("%s: Error, invalid parameters\n", __func__);
1362 rc = -EINVAL;
1363 }
1364 }
1365
1366afe_error:
1367 if (rc == 0)
1368 rc = cnt;
1369 else
1370 pr_err("%s: rc = %d\n", __func__, rc);
1371
1372 return rc;
1373}
1374
1375static const struct file_operations afe_debug_fops = {
1376 .open = afe_debug_open,
1377 .write = afe_debug_write
1378};
1379#endif
1380int afe_sidetone(u16 tx_port_id, u16 rx_port_id, u16 enable, uint16_t gain)
1381{
1382 struct afe_port_sidetone_command cmd_sidetone;
1383 int ret = 0;
1384
1385 pr_info("%s: tx_port_id:%d rx_port_id:%d enable:%d gain:%d\n", __func__,
1386 tx_port_id, rx_port_id, enable, gain);
1387 cmd_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1388 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1389 cmd_sidetone.hdr.pkt_size = sizeof(cmd_sidetone);
1390 cmd_sidetone.hdr.src_port = 0;
1391 cmd_sidetone.hdr.dest_port = 0;
1392 cmd_sidetone.hdr.token = 0;
1393 cmd_sidetone.hdr.opcode = AFE_PORT_CMD_SIDETONE_CTL;
1394 cmd_sidetone.tx_port_id = tx_port_id;
1395 cmd_sidetone.rx_port_id = rx_port_id;
1396 cmd_sidetone.gain = gain;
1397 cmd_sidetone.enable = enable;
1398
1399 atomic_set(&this_afe.state, 1);
1400 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_sidetone);
1401 if (ret < 0) {
1402 pr_err("%s: AFE sidetone failed for tx_port:%d rx_port:%d\n",
1403 __func__, tx_port_id, rx_port_id);
1404 ret = -EINVAL;
1405 goto fail_cmd;
1406 }
1407
1408 ret = wait_event_timeout(this_afe.wait,
1409 (atomic_read(&this_afe.state) == 0),
1410 msecs_to_jiffies(TIMEOUT_MS));
1411 if (ret < 0) {
1412 pr_err("%s: wait_event timeout\n", __func__);
1413 ret = -EINVAL;
1414 goto fail_cmd;
1415 }
1416 return 0;
1417fail_cmd:
1418 return ret;
1419}
1420
1421int afe_port_stop_nowait(int port_id)
1422{
1423 struct afe_port_stop_command stop;
1424 int ret = 0;
1425
1426 if (this_afe.apr == NULL) {
1427 pr_err("AFE is already closed\n");
1428 ret = -EINVAL;
1429 goto fail_cmd;
1430 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001431 pr_debug("%s: port_id=%d\n", __func__, port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301432 port_id = afe_convert_virtual_to_portid(port_id);
1433
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001434 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1435 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1436 stop.hdr.pkt_size = sizeof(stop);
1437 stop.hdr.src_port = 0;
1438 stop.hdr.dest_port = 0;
1439 stop.hdr.token = 0;
1440 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1441 stop.port_id = port_id;
1442 stop.reserved = 0;
1443
1444 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1445
1446 if (ret == -ENETRESET) {
1447 pr_info("%s: Need to reset, calling APR deregister", __func__);
1448 return apr_deregister(this_afe.apr);
1449 } else if (IS_ERR_VALUE(ret)) {
1450 pr_err("%s: AFE close failed\n", __func__);
1451 ret = -EINVAL;
1452 }
1453
1454fail_cmd:
1455 return ret;
1456
1457}
1458
1459int afe_close(int port_id)
1460{
1461 struct afe_port_stop_command stop;
1462 int ret = 0;
1463
1464 if (this_afe.apr == NULL) {
1465 pr_err("AFE is already closed\n");
1466 ret = -EINVAL;
1467 goto fail_cmd;
1468 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001469 pr_debug("%s: port_id=%d\n", __func__, port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301470 port_id = afe_convert_virtual_to_portid(port_id);
1471
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001472 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1473 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1474 stop.hdr.pkt_size = sizeof(stop);
1475 stop.hdr.src_port = 0;
1476 stop.hdr.dest_port = 0;
1477 stop.hdr.token = 0;
1478 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1479 stop.port_id = port_id;
1480 stop.reserved = 0;
1481
1482 atomic_set(&this_afe.state, 1);
1483 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1484
1485 if (ret == -ENETRESET) {
1486 pr_info("%s: Need to reset, calling APR deregister", __func__);
1487 return apr_deregister(this_afe.apr);
1488 }
1489
1490 if (ret < 0) {
1491 pr_err("%s: AFE close failed\n", __func__);
1492 ret = -EINVAL;
1493 goto fail_cmd;
1494 }
1495
1496 ret = wait_event_timeout(this_afe.wait,
1497 (atomic_read(&this_afe.state) == 0),
1498 msecs_to_jiffies(TIMEOUT_MS));
1499 if (!ret) {
1500 pr_err("%s: wait_event timeout\n", __func__);
1501 ret = -EINVAL;
1502 goto fail_cmd;
1503 }
1504fail_cmd:
1505 return ret;
1506}
1507
1508static int __init afe_init(void)
1509{
1510 init_waitqueue_head(&this_afe.wait);
1511 atomic_set(&this_afe.state, 0);
1512 atomic_set(&this_afe.status, 0);
1513 this_afe.apr = NULL;
1514#ifdef CONFIG_DEBUG_FS
1515 debugfs_afelb = debugfs_create_file("afe_loopback",
1516 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback",
1517 &afe_debug_fops);
1518
1519 debugfs_afelb_gain = debugfs_create_file("afe_loopback_gain",
1520 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback_gain",
1521 &afe_debug_fops);
1522
1523
1524#endif
1525 return 0;
1526}
1527
1528static void __exit afe_exit(void)
1529{
Ben Rombergerb7603232011-11-23 17:16:27 -08001530 int i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001531#ifdef CONFIG_DEBUG_FS
1532 if (debugfs_afelb)
1533 debugfs_remove(debugfs_afelb);
1534 if (debugfs_afelb_gain)
1535 debugfs_remove(debugfs_afelb_gain);
1536#endif
Ben Rombergerb7603232011-11-23 17:16:27 -08001537 for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
1538 if (afe_cal_addr[i] != 0)
1539 afe_cmd_memory_unmap_nowait(afe_cal_addr[i]);
1540 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001541}
1542
1543device_initcall(afe_init);
1544__exitcall(afe_exit);