blob: ef01fb3e27fae73eb1deb938503a58375171cd67 [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:
Kiran Kandi5e809b02012-01-31 00:24:33 -080080 case AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070081 case AFE_PORT_CMD_STOP:
82 case AFE_PORT_CMD_START:
83 case AFE_PORT_CMD_LOOPBACK:
84 case AFE_PORT_CMD_SIDETONE_CTL:
85 case AFE_PORT_CMD_SET_PARAM:
86 case AFE_PSEUDOPORT_CMD_START:
87 case AFE_PSEUDOPORT_CMD_STOP:
Laxminath Kasam885f5102011-07-14 10:20:21 +053088 case AFE_PORT_CMD_APPLY_GAIN:
Laxminath Kasam32657ec2011-08-01 19:26:57 +053089 case AFE_SERVICE_CMD_MEMORY_MAP:
90 case AFE_SERVICE_CMD_MEMORY_UNMAP:
91 case AFE_SERVICE_CMD_UNREG_RTPORT:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070092 atomic_set(&this_afe.state, 0);
93 wake_up(&this_afe.wait);
94 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +053095 case AFE_SERVICE_CMD_REG_RTPORT:
96 break;
97 case AFE_SERVICE_CMD_RTPORT_WR:
98 port_id = RT_PROXY_PORT_001_TX;
99 break;
100 case AFE_SERVICE_CMD_RTPORT_RD:
101 port_id = RT_PROXY_PORT_001_RX;
102 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700103 default:
104 pr_err("Unknown cmd 0x%x\n",
105 payload[0]);
106 break;
107 }
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530108 } else if (data->opcode == AFE_EVENT_RT_PROXY_PORT_STATUS) {
109 port_id = (uint16_t)(0x0000FFFF & payload[0]);
110 }
111 pr_debug("%s:port_id = %x\n", __func__, port_id);
112 switch (port_id) {
113 case RT_PROXY_PORT_001_TX: {
114 if (this_afe.tx_cb) {
115 this_afe.tx_cb(data->opcode, data->token,
116 data->payload,
117 this_afe.tx_private_data);
118 }
119 break;
120 }
121 case RT_PROXY_PORT_001_RX: {
122 if (this_afe.rx_cb) {
123 this_afe.rx_cb(data->opcode, data->token,
124 data->payload,
125 this_afe.rx_private_data);
126 }
127 break;
128 }
129 default:
130 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700131 }
132 }
133 return 0;
134}
135
Neema Shettyfeea7742011-09-11 12:30:36 -0700136int afe_get_port_type(u16 port_id)
137{
138 int ret;
139
140 switch (port_id) {
141 case PRIMARY_I2S_RX:
142 case PCM_RX:
143 case SECONDARY_I2S_RX:
144 case MI2S_RX:
145 case HDMI_RX:
146 case SLIMBUS_0_RX:
147 case INT_BT_SCO_RX:
148 case INT_BT_A2DP_RX:
149 case INT_FM_RX:
150 case VOICE_PLAYBACK_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530151 case RT_PROXY_PORT_001_RX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700152 ret = MSM_AFE_PORT_TYPE_RX;
153 break;
154
155 case PRIMARY_I2S_TX:
156 case PCM_TX:
157 case SECONDARY_I2S_TX:
158 case MI2S_TX:
159 case DIGI_MIC_TX:
160 case VOICE_RECORD_TX:
161 case SLIMBUS_0_TX:
162 case INT_FM_TX:
163 case VOICE_RECORD_RX:
164 case INT_BT_SCO_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530165 case RT_PROXY_PORT_001_TX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700166 ret = MSM_AFE_PORT_TYPE_TX;
167 break;
168
169 default:
170 pr_err("%s: invalid port id\n", __func__);
171 ret = -EINVAL;
172 }
173
174 return ret;
175}
176
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700177int afe_validate_port(u16 port_id)
178{
179 int ret;
180
181 switch (port_id) {
182 case PRIMARY_I2S_RX:
183 case PRIMARY_I2S_TX:
184 case PCM_RX:
185 case PCM_TX:
186 case SECONDARY_I2S_RX:
187 case SECONDARY_I2S_TX:
188 case MI2S_RX:
189 case MI2S_TX:
190 case HDMI_RX:
191 case RSVD_2:
192 case RSVD_3:
193 case DIGI_MIC_TX:
194 case VOICE_RECORD_RX:
195 case VOICE_RECORD_TX:
196 case VOICE_PLAYBACK_TX:
197 case SLIMBUS_0_RX:
198 case SLIMBUS_0_TX:
199 case INT_BT_SCO_RX:
200 case INT_BT_SCO_TX:
201 case INT_BT_A2DP_RX:
202 case INT_FM_RX:
203 case INT_FM_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530204 case RT_PROXY_PORT_001_RX:
205 case RT_PROXY_PORT_001_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700206 {
207 ret = 0;
208 break;
209 }
210
211 default:
212 ret = -EINVAL;
213 }
214
215 return ret;
216}
217
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530218int afe_convert_virtual_to_portid(u16 port_id)
219{
220 int ret;
221
222 /* if port_id is virtual, convert to physical..
223 * if port_id is already physical, return physical
224 */
225 if (afe_validate_port(port_id) < 0) {
226 if (port_id == RT_PROXY_DAI_001_RX ||
227 port_id == RT_PROXY_DAI_001_TX ||
228 port_id == RT_PROXY_DAI_002_RX ||
229 port_id == RT_PROXY_DAI_002_TX)
230 ret = VIRTUAL_ID_TO_PORTID(port_id);
231 else
232 ret = -EINVAL;
233 } else
234 ret = port_id;
235
236 return ret;
237}
238
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700239int afe_get_port_index(u16 port_id)
240{
241 switch (port_id) {
242 case PRIMARY_I2S_RX: return IDX_PRIMARY_I2S_RX;
243 case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
244 case PCM_RX: return IDX_PCM_RX;
245 case PCM_TX: return IDX_PCM_TX;
246 case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
247 case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
248 case MI2S_RX: return IDX_MI2S_RX;
249 case MI2S_TX: return IDX_MI2S_TX;
250 case HDMI_RX: return IDX_HDMI_RX;
251 case RSVD_2: return IDX_RSVD_2;
252 case RSVD_3: return IDX_RSVD_3;
253 case DIGI_MIC_TX: return IDX_DIGI_MIC_TX;
254 case VOICE_RECORD_RX: return IDX_VOICE_RECORD_RX;
255 case VOICE_RECORD_TX: return IDX_VOICE_RECORD_TX;
256 case VOICE_PLAYBACK_TX: return IDX_VOICE_PLAYBACK_TX;
257 case SLIMBUS_0_RX: return IDX_SLIMBUS_0_RX;
258 case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
259 case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
260 case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
261 case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
262 case INT_FM_RX: return IDX_INT_FM_RX;
263 case INT_FM_TX: return IDX_INT_FM_TX;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530264 case RT_PROXY_PORT_001_RX: return IDX_RT_PROXY_PORT_001_RX;
265 case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700266
267 default: return -EINVAL;
268 }
269}
270
271int afe_sizeof_cfg_cmd(u16 port_id)
272{
273 int ret_size;
274 switch (port_id) {
275 case PRIMARY_I2S_RX:
276 case PRIMARY_I2S_TX:
277 case SECONDARY_I2S_RX:
278 case SECONDARY_I2S_TX:
279 case MI2S_RX:
280 case MI2S_TX:
281 ret_size = SIZEOF_CFG_CMD(afe_port_mi2s_cfg);
282 break;
283 case HDMI_RX:
Kiran Kandi5e809b02012-01-31 00:24:33 -0800284 ret_size = SIZEOF_CFG_CMD(afe_port_hdmi_multi_ch_cfg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700285 break;
286 case SLIMBUS_0_RX:
287 case SLIMBUS_0_TX:
288 ret_size = SIZEOF_CFG_CMD(afe_port_slimbus_cfg);
289 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530290 case RT_PROXY_PORT_001_RX:
291 case RT_PROXY_PORT_001_TX:
292 ret_size = SIZEOF_CFG_CMD(afe_port_rtproxy_cfg);
293 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700294 case PCM_RX:
295 case PCM_TX:
296 default:
297 ret_size = SIZEOF_CFG_CMD(afe_port_pcm_cfg);
298 break;
299 }
300 return ret_size;
301}
302
Jay Wang6a305432011-08-05 16:01:54 -0700303int afe_q6_interface_prepare(void)
304{
305 int ret = 0;
306
307 pr_debug("%s:", __func__);
308
309 if (this_afe.apr == NULL) {
310 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
311 0xFFFFFFFF, &this_afe);
312 pr_debug("%s: Register AFE\n", __func__);
313 if (this_afe.apr == NULL) {
314 pr_err("%s: Unable to register AFE\n", __func__);
315 ret = -ENODEV;
316 }
317 }
318 return ret;
319}
320
Ben Rombergerb7603232011-11-23 17:16:27 -0800321static void afe_send_cal_block(int32_t path, u16 port_id)
322{
323 int result = 0;
324 struct acdb_cal_block cal_block;
325 struct afe_port_cmd_set_param_no_payload afe_cal;
326 pr_debug("%s: path %d\n", __func__, path);
327
328 get_afe_cal(path, &cal_block);
329 if (cal_block.cal_size <= 0) {
330 pr_debug("%s: No AFE cal to send!\n", __func__);
331 goto done;
332 }
333
334 if (afe_cal_addr[path] != cal_block.cal_paddr) {
335 if (afe_cal_addr[path] != 0)
336 afe_cmd_memory_unmap_nowait(afe_cal_addr[path]);
337 afe_cmd_memory_map_nowait(cal_block.cal_paddr,
338 cal_block.cal_size);
339 afe_cal_addr[path] = cal_block.cal_paddr;
340 }
341
342 afe_cal.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
343 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
344 afe_cal.hdr.pkt_size = sizeof(afe_cal);
345 afe_cal.hdr.src_port = 0;
346 afe_cal.hdr.dest_port = 0;
347 afe_cal.hdr.token = 0;
348 afe_cal.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
349 afe_cal.port_id = port_id;
350 afe_cal.payload_size = cal_block.cal_size;
351 afe_cal.payload_address = cal_block.cal_paddr;
352
353 pr_debug("%s: AFE cal sent for device port = %d, path = %d, "
354 "cal size = %d, cal addr = 0x%x\n", __func__,
355 port_id, path, cal_block.cal_size, cal_block.cal_paddr);
356
357 result = apr_send_pkt(this_afe.apr, (uint32_t *) &afe_cal);
358 if (result < 0) {
359 pr_err("%s: AFE cal for port %d failed\n",
360 __func__, port_id);
361 }
362
363 pr_debug("%s: AFE cal sent for path %d device!\n", __func__, path);
364done:
365 return;
366}
367
368void afe_send_cal(u16 port_id)
369{
370 pr_debug("%s\n", __func__);
371
372 if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX)
373 afe_send_cal_block(TX_CAL, port_id);
374 else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX)
375 afe_send_cal_block(RX_CAL, port_id);
376}
377
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700378int afe_port_start_nowait(u16 port_id, union afe_port_config *afe_config,
379 u32 rate) /* This function is no blocking */
380{
381 struct afe_port_start_command start;
382 struct afe_audioif_config_command config;
383 int ret;
384
385 if (!afe_config) {
386 pr_err("%s: Error, no configuration data\n", __func__);
387 ret = -EINVAL;
388 return ret;
389 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -0800390 pr_debug("%s: %d %d\n", __func__, port_id, rate);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700391
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530392 if ((port_id == RT_PROXY_DAI_001_RX) ||
393 (port_id == RT_PROXY_DAI_002_TX))
394 return -EINVAL;
395 if ((port_id == RT_PROXY_DAI_002_RX) ||
396 (port_id == RT_PROXY_DAI_001_TX))
397 port_id = VIRTUAL_ID_TO_PORTID(port_id);
398
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700399 if (this_afe.apr == NULL) {
Jay Wang6a305432011-08-05 16:01:54 -0700400 pr_err("%s: AFE APR is not registered\n", __func__);
401 ret = -ENODEV;
402 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700403 }
Kiran Kandi5e809b02012-01-31 00:24:33 -0800404
405 if (port_id == HDMI_RX) {
406 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700407 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
Kiran Kandi5e809b02012-01-31 00:24:33 -0800408 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
409 config.hdr.src_port = 0;
410 config.hdr.dest_port = 0;
411 config.hdr.token = 0;
412 config.hdr.opcode = AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG;
413 } else {
414
415 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
416 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
417 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
418 config.hdr.src_port = 0;
419 config.hdr.dest_port = 0;
420 config.hdr.token = 0;
421 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
422 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700423
424 if (afe_validate_port(port_id) < 0) {
425
426 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
427 port_id);
428 ret = -EINVAL;
429 goto fail_cmd;
430 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700431 config.port_id = port_id;
432 config.port = *afe_config;
433
434 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
435 if (ret < 0) {
436 pr_err("%s: AFE enable for port %d failed\n", __func__,
437 port_id);
438 ret = -EINVAL;
439 goto fail_cmd;
440 }
Ben Rombergerb7603232011-11-23 17:16:27 -0800441
442 /* send AFE cal */
443 afe_send_cal(port_id);
444
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700445 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
446 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
447 start.hdr.pkt_size = sizeof(start);
448 start.hdr.src_port = 0;
449 start.hdr.dest_port = 0;
450 start.hdr.token = 0;
451 start.hdr.opcode = AFE_PORT_CMD_START;
452 start.port_id = port_id;
453 start.gain = 0x2000;
454 start.sample_rate = rate;
455
456 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
457
458 if (IS_ERR_VALUE(ret)) {
459 pr_err("%s: AFE enable for port %d failed\n", __func__,
460 port_id);
461 ret = -EINVAL;
462 goto fail_cmd;
463 }
464
465 if (this_afe.task != current)
466 this_afe.task = current;
467
468 pr_debug("task_name = %s pid = %d\n",
469 this_afe.task->comm, this_afe.task->pid);
470 return 0;
471
472fail_cmd:
473 return ret;
474}
475
476int afe_open(u16 port_id, union afe_port_config *afe_config, int rate)
477{
478 struct afe_port_start_command start;
479 struct afe_audioif_config_command config;
480 int ret = 0;
481
482 if (!afe_config) {
483 pr_err("%s: Error, no configuration data\n", __func__);
484 ret = -EINVAL;
485 return ret;
486 }
487
488 pr_info("%s: %d %d\n", __func__, port_id, rate);
489
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530490 if ((port_id == RT_PROXY_DAI_001_RX) ||
491 (port_id == RT_PROXY_DAI_002_TX))
492 return -EINVAL;
493 if ((port_id == RT_PROXY_DAI_002_RX) ||
494 (port_id == RT_PROXY_DAI_001_TX))
495 port_id = VIRTUAL_ID_TO_PORTID(port_id);
496
Jay Wang6a305432011-08-05 16:01:54 -0700497 ret = afe_q6_interface_prepare();
498 if (ret != 0)
499 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700500
501 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
502 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
503 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
504 config.hdr.src_port = 0;
505 config.hdr.dest_port = 0;
506 config.hdr.token = 0;
507 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
508
509 if (afe_validate_port(port_id) < 0) {
510
511 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
512 port_id);
513 ret = -EINVAL;
514 goto fail_cmd;
515 }
516
517 config.port_id = port_id;
518 config.port = *afe_config;
519
520 atomic_set(&this_afe.state, 1);
521 atomic_set(&this_afe.status, 0);
522 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
523 if (ret < 0) {
524 pr_err("%s: AFE enable for port %d failed\n", __func__,
525 port_id);
526 ret = -EINVAL;
527 goto fail_cmd;
528 }
529
530 ret = wait_event_timeout(this_afe.wait,
531 (atomic_read(&this_afe.state) == 0),
532 msecs_to_jiffies(TIMEOUT_MS));
533 if (!ret) {
534 pr_err("%s: wait_event timeout\n", __func__);
535 ret = -EINVAL;
536 goto fail_cmd;
537 }
538 if (atomic_read(&this_afe.status) != 0) {
539 pr_err("%s: config cmd failed\n", __func__);
540 ret = -EINVAL;
541 goto fail_cmd;
542 }
543 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
544 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
545 start.hdr.pkt_size = sizeof(start);
546 start.hdr.src_port = 0;
547 start.hdr.dest_port = 0;
548 start.hdr.token = 0;
549 start.hdr.opcode = AFE_PORT_CMD_START;
550 start.port_id = port_id;
551 start.gain = 0x2000;
552 start.sample_rate = rate;
553
554 atomic_set(&this_afe.state, 1);
555 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
556 if (ret < 0) {
557 pr_err("%s: AFE enable for port %d failed\n", __func__,
558 port_id);
559 ret = -EINVAL;
560 goto fail_cmd;
561 }
562 ret = wait_event_timeout(this_afe.wait,
563 (atomic_read(&this_afe.state) == 0),
564 msecs_to_jiffies(TIMEOUT_MS));
565 if (!ret) {
566 pr_err("%s: wait_event timeout\n", __func__);
567 ret = -EINVAL;
568 goto fail_cmd;
569 }
570
571 if (this_afe.task != current)
572 this_afe.task = current;
573
574 pr_debug("task_name = %s pid = %d\n",
575 this_afe.task->comm, this_afe.task->pid);
576 return 0;
577fail_cmd:
578 return ret;
579}
580
581int afe_loopback(u16 enable, u16 rx_port, u16 tx_port)
582{
583 struct afe_loopback_command lb_cmd;
584 int ret = 0;
Jay Wang6a305432011-08-05 16:01:54 -0700585
586 ret = afe_q6_interface_prepare();
587 if (ret != 0)
588 return ret;
589
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700590 lb_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
591 APR_HDR_LEN(20), APR_PKT_VER);
592 lb_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
593 sizeof(lb_cmd) - APR_HDR_SIZE);
594 lb_cmd.hdr.src_port = 0;
595 lb_cmd.hdr.dest_port = 0;
596 lb_cmd.hdr.token = 0;
597 lb_cmd.hdr.opcode = AFE_PORT_CMD_LOOPBACK;
598 lb_cmd.tx_port_id = tx_port;
599 lb_cmd.rx_port_id = rx_port;
600 lb_cmd.mode = 0xFFFF;
601 lb_cmd.enable = (enable ? 1 : 0);
602 atomic_set(&this_afe.state, 1);
603
604 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &lb_cmd);
605 if (ret < 0) {
606 pr_err("%s: AFE loopback failed\n", __func__);
607 ret = -EINVAL;
608 goto done;
609 }
610 ret = wait_event_timeout(this_afe.wait,
611 (atomic_read(&this_afe.state) == 0),
612 msecs_to_jiffies(TIMEOUT_MS));
613 if (!ret) {
614 pr_err("%s: wait_event timeout\n", __func__);
615 ret = -EINVAL;
616 }
617done:
618 return ret;
619}
620
621
622int afe_loopback_gain(u16 port_id, u16 volume)
623{
624 struct afe_port_cmd_set_param set_param;
625 int ret = 0;
626
627 if (this_afe.apr == NULL) {
Jayasena Sangaraboina82435032011-07-26 15:23:00 -0700628 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
629 0xFFFFFFFF, &this_afe);
630 pr_debug("%s: Register AFE\n", __func__);
631 if (this_afe.apr == NULL) {
632 pr_err("%s: Unable to register AFE\n", __func__);
633 ret = -ENODEV;
634 return ret;
635 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700636 }
637
638 if (afe_validate_port(port_id) < 0) {
639
640 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
641 port_id);
642 ret = -EINVAL;
643 goto fail_cmd;
644 }
645
646 /* RX ports numbers are even .TX ports numbers are odd. */
647 if (port_id % 2 == 0) {
648 pr_err("%s: Failed : afe loopback gain only for TX ports."
649 " port_id %d\n", __func__, port_id);
650 ret = -EINVAL;
651 goto fail_cmd;
652 }
653
654 pr_debug("%s: %d %hX\n", __func__, port_id, volume);
655
656 set_param.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
657 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
658 set_param.hdr.pkt_size = sizeof(set_param);
659 set_param.hdr.src_port = 0;
660 set_param.hdr.dest_port = 0;
661 set_param.hdr.token = 0;
662 set_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
663
664 set_param.port_id = port_id;
665 set_param.payload_size = sizeof(struct afe_param_payload);
666 set_param.payload_address = 0;
667
668 set_param.payload.module_id = AFE_MODULE_ID_PORT_INFO;
669 set_param.payload.param_id = AFE_PARAM_ID_LOOPBACK_GAIN;
670 set_param.payload.param_size = sizeof(struct afe_param_loopback_gain);
671 set_param.payload.reserved = 0;
672
673 set_param.payload.param.loopback_gain.gain = volume;
674 set_param.payload.param.loopback_gain.reserved = 0;
675
676 atomic_set(&this_afe.state, 1);
677 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_param);
678 if (ret < 0) {
679 pr_err("%s: AFE param set failed for port %d\n",
680 __func__, port_id);
681 ret = -EINVAL;
682 goto fail_cmd;
683 }
684
685 ret = wait_event_timeout(this_afe.wait,
686 (atomic_read(&this_afe.state) == 0),
687 msecs_to_jiffies(TIMEOUT_MS));
688 if (ret < 0) {
689 pr_err("%s: wait_event timeout\n", __func__);
690 ret = -EINVAL;
691 goto fail_cmd;
692 }
693 return 0;
694fail_cmd:
695 return ret;
696}
697
Laxminath Kasam885f5102011-07-14 10:20:21 +0530698int afe_apply_gain(u16 port_id, u16 gain)
699{
700 struct afe_port_gain_command set_gain;
701 int ret = 0;
702
703 if (this_afe.apr == NULL) {
704 pr_err("%s: AFE is not opened\n", __func__);
705 ret = -EPERM;
706 goto fail_cmd;
707 }
708
709 if (afe_validate_port(port_id) < 0) {
710 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
711 port_id);
712 ret = -EINVAL;
713 goto fail_cmd;
714 }
715
716 /* RX ports numbers are even .TX ports numbers are odd. */
717 if (port_id % 2 == 0) {
718 pr_err("%s: Failed : afe apply gain only for TX ports."
719 " port_id %d\n", __func__, port_id);
720 ret = -EINVAL;
721 goto fail_cmd;
722 }
723
724 pr_debug("%s: %d %hX\n", __func__, port_id, gain);
725
726 set_gain.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
727 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
728 set_gain.hdr.pkt_size = sizeof(set_gain);
729 set_gain.hdr.src_port = 0;
730 set_gain.hdr.dest_port = 0;
731 set_gain.hdr.token = 0;
732 set_gain.hdr.opcode = AFE_PORT_CMD_APPLY_GAIN;
733
734 set_gain.port_id = port_id;
735 set_gain.gain = gain;
736
737 atomic_set(&this_afe.state, 1);
738 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_gain);
739 if (ret < 0) {
740 pr_err("%s: AFE Gain set failed for port %d\n",
741 __func__, port_id);
742 ret = -EINVAL;
743 goto fail_cmd;
744 }
745
746 ret = wait_event_timeout(this_afe.wait,
747 (atomic_read(&this_afe.state) == 0),
748 msecs_to_jiffies(TIMEOUT_MS));
749 if (ret < 0) {
750 pr_err("%s: wait_event timeout\n", __func__);
751 ret = -EINVAL;
752 goto fail_cmd;
753 }
754 return 0;
755fail_cmd:
756 return ret;
757}
Helen Zeng0705a5f2011-10-14 15:29:52 -0700758
759int afe_pseudo_port_start_nowait(u16 port_id)
760{
761 int ret = 0;
762 struct afe_pseudoport_start_command start;
763
764 pr_debug("%s: port_id=%d\n", __func__, port_id);
765 if (this_afe.apr == NULL) {
766 pr_err("%s: AFE APR is not registered\n", __func__);
767 return -ENODEV;
768 }
769
770
771 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
772 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
773 start.hdr.pkt_size = sizeof(start);
774 start.hdr.src_port = 0;
775 start.hdr.dest_port = 0;
776 start.hdr.token = 0;
777 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
778 start.port_id = port_id;
779 start.timing = 1;
780
781 atomic_set(&this_afe.state, 1);
782 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
783 if (ret < 0) {
784 pr_err("%s: AFE enable for port %d failed %d\n",
785 __func__, port_id, ret);
786 return -EINVAL;
787 }
788 return 0;
789}
790
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700791int afe_start_pseudo_port(u16 port_id)
792{
793 int ret = 0;
794 struct afe_pseudoport_start_command start;
795
796 pr_info("%s: port_id=%d\n", __func__, port_id);
797
Jay Wang6a305432011-08-05 16:01:54 -0700798 ret = afe_q6_interface_prepare();
799 if (ret != 0)
800 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700801
802 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
803 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
804 start.hdr.pkt_size = sizeof(start);
805 start.hdr.src_port = 0;
806 start.hdr.dest_port = 0;
807 start.hdr.token = 0;
808 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
809 start.port_id = port_id;
810 start.timing = 1;
811
812 atomic_set(&this_afe.state, 1);
813 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
814 if (ret < 0) {
815 pr_err("%s: AFE enable for port %d failed %d\n",
816 __func__, port_id, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700817 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700818 }
819
820 ret = wait_event_timeout(this_afe.wait,
821 (atomic_read(&this_afe.state) == 0),
822 msecs_to_jiffies(TIMEOUT_MS));
823 if (!ret) {
824 pr_err("%s: wait_event timeout\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700825 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700826 }
827
828 return 0;
829}
830
Helen Zeng0705a5f2011-10-14 15:29:52 -0700831int afe_pseudo_port_stop_nowait(u16 port_id)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700832{
833 int ret = 0;
834 struct afe_pseudoport_stop_command stop;
835
Helen Zeng0705a5f2011-10-14 15:29:52 -0700836 pr_debug("%s: port_id=%d\n", __func__, port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700837
838 if (this_afe.apr == NULL) {
839 pr_err("%s: AFE is already closed\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700840 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700841 }
842
843 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
844 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
845 stop.hdr.pkt_size = sizeof(stop);
846 stop.hdr.src_port = 0;
847 stop.hdr.dest_port = 0;
848 stop.hdr.token = 0;
849 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
850 stop.port_id = port_id;
851 stop.reserved = 0;
852
853 atomic_set(&this_afe.state, 1);
854 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
855 if (ret < 0) {
856 pr_err("%s: AFE close failed %d\n", __func__, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700857 return -EINVAL;
858 }
859
860 return 0;
861
862}
863
864int afe_stop_pseudo_port(u16 port_id)
865{
866 int ret = 0;
867 struct afe_pseudoport_stop_command stop;
868
869 pr_info("%s: port_id=%d\n", __func__, port_id);
870
871 if (this_afe.apr == NULL) {
872 pr_err("%s: AFE is already closed\n", __func__);
873 return -EINVAL;
874 }
875
876 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
877 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
878 stop.hdr.pkt_size = sizeof(stop);
879 stop.hdr.src_port = 0;
880 stop.hdr.dest_port = 0;
881 stop.hdr.token = 0;
882 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
883 stop.port_id = port_id;
884 stop.reserved = 0;
885
886 atomic_set(&this_afe.state, 1);
887 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
888 if (ret < 0) {
889 pr_err("%s: AFE close failed %d\n", __func__, ret);
890 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700891 }
892
893 ret = wait_event_timeout(this_afe.wait,
894 (atomic_read(&this_afe.state) == 0),
895 msecs_to_jiffies(TIMEOUT_MS));
896 if (!ret) {
897 pr_err("%s: wait_event timeout\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700898 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700899 }
900
901 return 0;
902}
903
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530904int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz)
905{
906 int ret = 0;
907 struct afe_cmd_memory_map mregion;
908
909 pr_debug("%s:\n", __func__);
910
911 if (this_afe.apr == NULL) {
912 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
913 0xFFFFFFFF, &this_afe);
914 pr_debug("%s: Register AFE\n", __func__);
915 if (this_afe.apr == NULL) {
916 pr_err("%s: Unable to register AFE\n", __func__);
917 ret = -ENODEV;
918 return ret;
919 }
920 }
921
922 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
923 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
924 mregion.hdr.pkt_size = sizeof(mregion);
925 mregion.hdr.src_port = 0;
926 mregion.hdr.dest_port = 0;
927 mregion.hdr.token = 0;
928 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
929 mregion.phy_addr = dma_addr_p;
930 mregion.mem_sz = dma_buf_sz;
931 mregion.mem_id = 0;
932 mregion.rsvd = 0;
933
934 atomic_set(&this_afe.state, 1);
935 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
936 if (ret < 0) {
937 pr_err("%s: AFE memory map cmd failed %d\n",
938 __func__, ret);
939 ret = -EINVAL;
940 return ret;
941 }
942
943 ret = wait_event_timeout(this_afe.wait,
944 (atomic_read(&this_afe.state) == 0),
945 msecs_to_jiffies(TIMEOUT_MS));
946 if (!ret) {
947 pr_err("%s: wait_event timeout\n", __func__);
948 ret = -EINVAL;
949 return ret;
950 }
951
952 return 0;
953}
954
Ben Rombergerb7603232011-11-23 17:16:27 -0800955int afe_cmd_memory_map_nowait(u32 dma_addr_p, u32 dma_buf_sz)
956{
957 int ret = 0;
958 struct afe_cmd_memory_map mregion;
959
960 pr_debug("%s:\n", __func__);
961
962 if (this_afe.apr == NULL) {
963 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
964 0xFFFFFFFF, &this_afe);
965 pr_debug("%s: Register AFE\n", __func__);
966 if (this_afe.apr == NULL) {
967 pr_err("%s: Unable to register AFE\n", __func__);
968 ret = -ENODEV;
969 return ret;
970 }
971 }
972
973 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
974 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
975 mregion.hdr.pkt_size = sizeof(mregion);
976 mregion.hdr.src_port = 0;
977 mregion.hdr.dest_port = 0;
978 mregion.hdr.token = 0;
979 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
980 mregion.phy_addr = dma_addr_p;
981 mregion.mem_sz = dma_buf_sz;
982 mregion.mem_id = 0;
983 mregion.rsvd = 0;
984
985 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
986 if (ret < 0) {
987 pr_err("%s: AFE memory map cmd failed %d\n",
988 __func__, ret);
989 ret = -EINVAL;
990 }
991 return 0;
992}
993
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530994int afe_cmd_memory_unmap(u32 dma_addr_p)
995{
996 int ret = 0;
997 struct afe_cmd_memory_unmap mregion;
998
999 pr_debug("%s:\n", __func__);
1000
1001 if (this_afe.apr == NULL) {
1002 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1003 0xFFFFFFFF, &this_afe);
1004 pr_debug("%s: Register AFE\n", __func__);
1005 if (this_afe.apr == NULL) {
1006 pr_err("%s: Unable to register AFE\n", __func__);
1007 ret = -ENODEV;
1008 return ret;
1009 }
1010 }
1011
1012 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1013 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1014 mregion.hdr.pkt_size = sizeof(mregion);
1015 mregion.hdr.src_port = 0;
1016 mregion.hdr.dest_port = 0;
1017 mregion.hdr.token = 0;
1018 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
1019 mregion.phy_addr = dma_addr_p;
1020
1021 atomic_set(&this_afe.state, 1);
1022 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1023 if (ret < 0) {
Ben Rombergerb7603232011-11-23 17:16:27 -08001024 pr_err("%s: AFE memory unmap cmd failed %d\n",
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301025 __func__, ret);
1026 ret = -EINVAL;
1027 return ret;
1028 }
1029
1030 ret = wait_event_timeout(this_afe.wait,
1031 (atomic_read(&this_afe.state) == 0),
1032 msecs_to_jiffies(TIMEOUT_MS));
1033 if (!ret) {
1034 pr_err("%s: wait_event timeout\n", __func__);
1035 ret = -EINVAL;
1036 return ret;
1037 }
Ben Rombergerb7603232011-11-23 17:16:27 -08001038 return 0;
1039}
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301040
Ben Rombergerb7603232011-11-23 17:16:27 -08001041int afe_cmd_memory_unmap_nowait(u32 dma_addr_p)
1042{
1043 int ret = 0;
1044 struct afe_cmd_memory_unmap mregion;
1045
1046 pr_debug("%s:\n", __func__);
1047
1048 if (this_afe.apr == NULL) {
1049 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1050 0xFFFFFFFF, &this_afe);
1051 pr_debug("%s: Register AFE\n", __func__);
1052 if (this_afe.apr == NULL) {
1053 pr_err("%s: Unable to register AFE\n", __func__);
1054 ret = -ENODEV;
1055 return ret;
1056 }
1057 }
1058
1059 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1060 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1061 mregion.hdr.pkt_size = sizeof(mregion);
1062 mregion.hdr.src_port = 0;
1063 mregion.hdr.dest_port = 0;
1064 mregion.hdr.token = 0;
1065 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
1066 mregion.phy_addr = dma_addr_p;
1067
1068 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1069 if (ret < 0) {
1070 pr_err("%s: AFE memory unmap cmd failed %d\n",
1071 __func__, ret);
1072 ret = -EINVAL;
1073 }
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301074 return 0;
1075}
1076
1077int afe_register_get_events(u16 port_id,
1078 void (*cb) (uint32_t opcode,
1079 uint32_t token, uint32_t *payload, void *priv),
1080 void *private_data)
1081{
1082 int ret = 0;
1083 struct afe_cmd_reg_rtport rtproxy;
1084
1085 pr_debug("%s:\n", __func__);
1086
1087 if (this_afe.apr == NULL) {
1088 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1089 0xFFFFFFFF, &this_afe);
1090 pr_debug("%s: Register AFE\n", __func__);
1091 if (this_afe.apr == NULL) {
1092 pr_err("%s: Unable to register AFE\n", __func__);
1093 ret = -ENODEV;
1094 return ret;
1095 }
1096 }
1097 if ((port_id == RT_PROXY_DAI_002_RX) ||
1098 (port_id == RT_PROXY_DAI_001_TX))
1099 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1100 else
1101 return -EINVAL;
1102
1103 if (port_id == RT_PROXY_PORT_001_TX) {
1104 this_afe.tx_cb = cb;
1105 this_afe.tx_private_data = private_data;
1106 } else if (port_id == RT_PROXY_PORT_001_RX) {
1107 this_afe.rx_cb = cb;
1108 this_afe.rx_private_data = private_data;
1109 }
1110
1111 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1112 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1113 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1114 rtproxy.hdr.src_port = 1;
1115 rtproxy.hdr.dest_port = 1;
1116 rtproxy.hdr.token = 0;
1117 rtproxy.hdr.opcode = AFE_SERVICE_CMD_REG_RTPORT;
1118 rtproxy.port_id = port_id;
1119 rtproxy.rsvd = 0;
1120
1121 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1122 if (ret < 0) {
1123 pr_err("%s: AFE reg. rtproxy_event failed %d\n",
1124 __func__, ret);
1125 ret = -EINVAL;
1126 return ret;
1127 }
1128 return 0;
1129}
1130
1131int afe_unregister_get_events(u16 port_id)
1132{
1133 int ret = 0;
1134 struct afe_cmd_unreg_rtport rtproxy;
1135
1136 pr_debug("%s:\n", __func__);
1137
1138 if (this_afe.apr == NULL) {
1139 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1140 0xFFFFFFFF, &this_afe);
1141 pr_debug("%s: Register AFE\n", __func__);
1142 if (this_afe.apr == NULL) {
1143 pr_err("%s: Unable to register AFE\n", __func__);
1144 ret = -ENODEV;
1145 return ret;
1146 }
1147 }
1148 if ((port_id == RT_PROXY_DAI_002_RX) ||
1149 (port_id == RT_PROXY_DAI_001_TX))
1150 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1151 else
1152 return -EINVAL;
1153
1154 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1155 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1156 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1157 rtproxy.hdr.src_port = 0;
1158 rtproxy.hdr.dest_port = 0;
1159 rtproxy.hdr.token = 0;
1160 rtproxy.hdr.opcode = AFE_SERVICE_CMD_UNREG_RTPORT;
1161 rtproxy.port_id = port_id;
1162 rtproxy.rsvd = 0;
1163
1164 if (port_id == RT_PROXY_PORT_001_TX) {
1165 this_afe.tx_cb = NULL;
1166 this_afe.tx_private_data = NULL;
1167 } else if (port_id == RT_PROXY_PORT_001_RX) {
1168 this_afe.rx_cb = NULL;
1169 this_afe.rx_private_data = NULL;
1170 }
1171
1172 atomic_set(&this_afe.state, 1);
1173 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1174 if (ret < 0) {
1175 pr_err("%s: AFE enable Unreg. rtproxy_event failed %d\n",
1176 __func__, ret);
1177 ret = -EINVAL;
1178 return ret;
1179 }
1180
1181 ret = wait_event_timeout(this_afe.wait,
1182 (atomic_read(&this_afe.state) == 0),
1183 msecs_to_jiffies(TIMEOUT_MS));
1184 if (!ret) {
1185 pr_err("%s: wait_event timeout\n", __func__);
1186 ret = -EINVAL;
1187 return ret;
1188 }
1189 return 0;
1190}
1191
1192int afe_rt_proxy_port_write(u32 buf_addr_p, int bytes)
1193{
1194 int ret = 0;
1195 struct afe_cmd_rtport_wr afecmd_wr;
1196
1197 if (this_afe.apr == NULL) {
1198 pr_err("%s:register to AFE is not done\n", __func__);
1199 ret = -ENODEV;
1200 return ret;
1201 }
1202 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1203 buf_addr_p, bytes);
1204
1205 afecmd_wr.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1206 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1207 afecmd_wr.hdr.pkt_size = sizeof(afecmd_wr);
1208 afecmd_wr.hdr.src_port = 0;
1209 afecmd_wr.hdr.dest_port = 0;
1210 afecmd_wr.hdr.token = 0;
1211 afecmd_wr.hdr.opcode = AFE_SERVICE_CMD_RTPORT_WR;
1212 afecmd_wr.buf_addr = (uint32_t)buf_addr_p;
1213 afecmd_wr.port_id = RT_PROXY_PORT_001_TX;
1214 afecmd_wr.bytes_avail = bytes;
1215 afecmd_wr.rsvd = 0;
1216
1217 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_wr);
1218 if (ret < 0) {
1219 pr_err("%s: AFE rtproxy write to port 0x%x failed %d\n",
1220 __func__, afecmd_wr.port_id, ret);
1221 ret = -EINVAL;
1222 return ret;
1223 }
1224 return 0;
1225
1226}
1227
1228int afe_rt_proxy_port_read(u32 buf_addr_p, int bytes)
1229{
1230 int ret = 0;
1231 struct afe_cmd_rtport_rd afecmd_rd;
1232
1233 if (this_afe.apr == NULL) {
1234 pr_err("%s: register to AFE is not done\n", __func__);
1235 ret = -ENODEV;
1236 return ret;
1237 }
1238 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1239 buf_addr_p, bytes);
1240
1241 afecmd_rd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1242 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1243 afecmd_rd.hdr.pkt_size = sizeof(afecmd_rd);
1244 afecmd_rd.hdr.src_port = 0;
1245 afecmd_rd.hdr.dest_port = 0;
1246 afecmd_rd.hdr.token = 0;
1247 afecmd_rd.hdr.opcode = AFE_SERVICE_CMD_RTPORT_RD;
1248 afecmd_rd.buf_addr = (uint32_t)buf_addr_p;
1249 afecmd_rd.port_id = RT_PROXY_PORT_001_RX;
1250 afecmd_rd.bytes_avail = bytes;
1251 afecmd_rd.rsvd = 0;
1252
1253 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_rd);
1254 if (ret < 0) {
1255 pr_err("%s: AFE rtproxy read cmd to port 0x%x failed %d\n",
1256 __func__, afecmd_rd.port_id, ret);
1257 ret = -EINVAL;
1258 return ret;
1259 }
1260 return 0;
1261}
1262
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001263#ifdef CONFIG_DEBUG_FS
1264static struct dentry *debugfs_afelb;
1265static struct dentry *debugfs_afelb_gain;
1266
1267static int afe_debug_open(struct inode *inode, struct file *file)
1268{
1269 file->private_data = inode->i_private;
1270 pr_info("debug intf %s\n", (char *) file->private_data);
1271 return 0;
1272}
1273
1274static int afe_get_parameters(char *buf, long int *param1, int num_of_par)
1275{
1276 char *token;
1277 int base, cnt;
1278
1279 token = strsep(&buf, " ");
1280
1281 for (cnt = 0; cnt < num_of_par; cnt++) {
1282 if (token != NULL) {
1283 if ((token[1] == 'x') || (token[1] == 'X'))
1284 base = 16;
1285 else
1286 base = 10;
1287
1288 if (strict_strtoul(token, base, &param1[cnt]) != 0)
1289 return -EINVAL;
1290
1291 token = strsep(&buf, " ");
1292 } else
1293 return -EINVAL;
1294 }
1295 return 0;
1296}
1297#define AFE_LOOPBACK_ON (1)
1298#define AFE_LOOPBACK_OFF (0)
1299static ssize_t afe_debug_write(struct file *filp,
1300 const char __user *ubuf, size_t cnt, loff_t *ppos)
1301{
1302 char *lb_str = filp->private_data;
1303 char lbuf[32];
1304 int rc;
1305 unsigned long param[5];
1306
1307 if (cnt > sizeof(lbuf) - 1)
1308 return -EINVAL;
1309
1310 rc = copy_from_user(lbuf, ubuf, cnt);
1311 if (rc)
1312 return -EFAULT;
1313
1314 lbuf[cnt] = '\0';
1315
1316 if (!strcmp(lb_str, "afe_loopback")) {
1317 rc = afe_get_parameters(lbuf, param, 3);
1318 if (!rc) {
1319 pr_info("%s %lu %lu %lu\n", lb_str, param[0], param[1],
1320 param[2]);
1321
1322 if ((param[0] != AFE_LOOPBACK_ON) && (param[0] !=
1323 AFE_LOOPBACK_OFF)) {
1324 pr_err("%s: Error, parameter 0 incorrect\n",
1325 __func__);
1326 rc = -EINVAL;
1327 goto afe_error;
1328 }
1329 if ((afe_validate_port(param[1]) < 0) ||
1330 (afe_validate_port(param[2])) < 0) {
1331 pr_err("%s: Error, invalid afe port\n",
1332 __func__);
1333 }
1334 if (this_afe.apr == NULL) {
1335 pr_err("%s: Error, AFE not opened\n", __func__);
1336 rc = -EINVAL;
1337 } else {
1338 rc = afe_loopback(param[0], param[1], param[2]);
1339 }
1340 } else {
1341 pr_err("%s: Error, invalid parameters\n", __func__);
1342 rc = -EINVAL;
1343 }
1344
1345 } else if (!strcmp(lb_str, "afe_loopback_gain")) {
1346 rc = afe_get_parameters(lbuf, param, 2);
1347 if (!rc) {
1348 pr_info("%s %lu %lu\n", lb_str, param[0], param[1]);
1349
1350 if (afe_validate_port(param[0]) < 0) {
1351 pr_err("%s: Error, invalid afe port\n",
1352 __func__);
1353 rc = -EINVAL;
1354 goto afe_error;
1355 }
1356
1357 if (param[1] < 0 || param[1] > 100) {
1358 pr_err("%s: Error, volume shoud be 0 to 100"
1359 " percentage param = %lu\n",
1360 __func__, param[1]);
1361 rc = -EINVAL;
1362 goto afe_error;
1363 }
1364
1365 param[1] = (Q6AFE_MAX_VOLUME * param[1]) / 100;
1366
1367 if (this_afe.apr == NULL) {
1368 pr_err("%s: Error, AFE not opened\n", __func__);
1369 rc = -EINVAL;
1370 } else {
1371 rc = afe_loopback_gain(param[0], param[1]);
1372 }
1373 } else {
1374 pr_err("%s: Error, invalid parameters\n", __func__);
1375 rc = -EINVAL;
1376 }
1377 }
1378
1379afe_error:
1380 if (rc == 0)
1381 rc = cnt;
1382 else
1383 pr_err("%s: rc = %d\n", __func__, rc);
1384
1385 return rc;
1386}
1387
1388static const struct file_operations afe_debug_fops = {
1389 .open = afe_debug_open,
1390 .write = afe_debug_write
1391};
1392#endif
1393int afe_sidetone(u16 tx_port_id, u16 rx_port_id, u16 enable, uint16_t gain)
1394{
1395 struct afe_port_sidetone_command cmd_sidetone;
1396 int ret = 0;
1397
1398 pr_info("%s: tx_port_id:%d rx_port_id:%d enable:%d gain:%d\n", __func__,
1399 tx_port_id, rx_port_id, enable, gain);
1400 cmd_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1401 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1402 cmd_sidetone.hdr.pkt_size = sizeof(cmd_sidetone);
1403 cmd_sidetone.hdr.src_port = 0;
1404 cmd_sidetone.hdr.dest_port = 0;
1405 cmd_sidetone.hdr.token = 0;
1406 cmd_sidetone.hdr.opcode = AFE_PORT_CMD_SIDETONE_CTL;
1407 cmd_sidetone.tx_port_id = tx_port_id;
1408 cmd_sidetone.rx_port_id = rx_port_id;
1409 cmd_sidetone.gain = gain;
1410 cmd_sidetone.enable = enable;
1411
1412 atomic_set(&this_afe.state, 1);
1413 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_sidetone);
1414 if (ret < 0) {
1415 pr_err("%s: AFE sidetone failed for tx_port:%d rx_port:%d\n",
1416 __func__, tx_port_id, rx_port_id);
1417 ret = -EINVAL;
1418 goto fail_cmd;
1419 }
1420
1421 ret = wait_event_timeout(this_afe.wait,
1422 (atomic_read(&this_afe.state) == 0),
1423 msecs_to_jiffies(TIMEOUT_MS));
1424 if (ret < 0) {
1425 pr_err("%s: wait_event timeout\n", __func__);
1426 ret = -EINVAL;
1427 goto fail_cmd;
1428 }
1429 return 0;
1430fail_cmd:
1431 return ret;
1432}
1433
1434int afe_port_stop_nowait(int port_id)
1435{
1436 struct afe_port_stop_command stop;
1437 int ret = 0;
1438
1439 if (this_afe.apr == NULL) {
1440 pr_err("AFE is already closed\n");
1441 ret = -EINVAL;
1442 goto fail_cmd;
1443 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001444 pr_debug("%s: port_id=%d\n", __func__, port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301445 port_id = afe_convert_virtual_to_portid(port_id);
1446
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001447 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1448 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1449 stop.hdr.pkt_size = sizeof(stop);
1450 stop.hdr.src_port = 0;
1451 stop.hdr.dest_port = 0;
1452 stop.hdr.token = 0;
1453 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1454 stop.port_id = port_id;
1455 stop.reserved = 0;
1456
1457 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1458
1459 if (ret == -ENETRESET) {
1460 pr_info("%s: Need to reset, calling APR deregister", __func__);
1461 return apr_deregister(this_afe.apr);
1462 } else if (IS_ERR_VALUE(ret)) {
1463 pr_err("%s: AFE close failed\n", __func__);
1464 ret = -EINVAL;
1465 }
1466
1467fail_cmd:
1468 return ret;
1469
1470}
1471
1472int afe_close(int port_id)
1473{
1474 struct afe_port_stop_command stop;
1475 int ret = 0;
1476
1477 if (this_afe.apr == NULL) {
1478 pr_err("AFE is already closed\n");
1479 ret = -EINVAL;
1480 goto fail_cmd;
1481 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001482 pr_debug("%s: port_id=%d\n", __func__, port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301483 port_id = afe_convert_virtual_to_portid(port_id);
1484
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001485 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1486 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1487 stop.hdr.pkt_size = sizeof(stop);
1488 stop.hdr.src_port = 0;
1489 stop.hdr.dest_port = 0;
1490 stop.hdr.token = 0;
1491 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1492 stop.port_id = port_id;
1493 stop.reserved = 0;
1494
1495 atomic_set(&this_afe.state, 1);
1496 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1497
1498 if (ret == -ENETRESET) {
1499 pr_info("%s: Need to reset, calling APR deregister", __func__);
1500 return apr_deregister(this_afe.apr);
1501 }
1502
1503 if (ret < 0) {
1504 pr_err("%s: AFE close failed\n", __func__);
1505 ret = -EINVAL;
1506 goto fail_cmd;
1507 }
1508
1509 ret = wait_event_timeout(this_afe.wait,
1510 (atomic_read(&this_afe.state) == 0),
1511 msecs_to_jiffies(TIMEOUT_MS));
1512 if (!ret) {
1513 pr_err("%s: wait_event timeout\n", __func__);
1514 ret = -EINVAL;
1515 goto fail_cmd;
1516 }
1517fail_cmd:
1518 return ret;
1519}
1520
1521static int __init afe_init(void)
1522{
1523 init_waitqueue_head(&this_afe.wait);
1524 atomic_set(&this_afe.state, 0);
1525 atomic_set(&this_afe.status, 0);
1526 this_afe.apr = NULL;
1527#ifdef CONFIG_DEBUG_FS
1528 debugfs_afelb = debugfs_create_file("afe_loopback",
1529 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback",
1530 &afe_debug_fops);
1531
1532 debugfs_afelb_gain = debugfs_create_file("afe_loopback_gain",
1533 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback_gain",
1534 &afe_debug_fops);
1535
1536
1537#endif
1538 return 0;
1539}
1540
1541static void __exit afe_exit(void)
1542{
Ben Rombergerb7603232011-11-23 17:16:27 -08001543 int i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001544#ifdef CONFIG_DEBUG_FS
1545 if (debugfs_afelb)
1546 debugfs_remove(debugfs_afelb);
1547 if (debugfs_afelb_gain)
1548 debugfs_remove(debugfs_afelb_gain);
1549#endif
Ben Rombergerb7603232011-11-23 17:16:27 -08001550 for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
1551 if (afe_cal_addr[i] != 0)
1552 afe_cmd_memory_unmap_nowait(afe_cal_addr[i]);
1553 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001554}
1555
1556device_initcall(afe_init);
1557__exitcall(afe_exit);