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