blob: 59506f18d11e9a6d18616a2a1012272597080b4e [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:
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
335 if (afe_cal_addr[path] != cal_block.cal_paddr) {
336 if (afe_cal_addr[path] != 0)
337 afe_cmd_memory_unmap_nowait(afe_cal_addr[path]);
338 afe_cmd_memory_map_nowait(cal_block.cal_paddr,
339 cal_block.cal_size);
340 afe_cal_addr[path] = cal_block.cal_paddr;
341 }
342
343 afe_cal.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
344 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
345 afe_cal.hdr.pkt_size = sizeof(afe_cal);
346 afe_cal.hdr.src_port = 0;
347 afe_cal.hdr.dest_port = 0;
348 afe_cal.hdr.token = 0;
349 afe_cal.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
350 afe_cal.port_id = port_id;
351 afe_cal.payload_size = cal_block.cal_size;
352 afe_cal.payload_address = cal_block.cal_paddr;
353
354 pr_debug("%s: AFE cal sent for device port = %d, path = %d, "
355 "cal size = %d, cal addr = 0x%x\n", __func__,
356 port_id, path, cal_block.cal_size, cal_block.cal_paddr);
357
358 result = apr_send_pkt(this_afe.apr, (uint32_t *) &afe_cal);
359 if (result < 0) {
360 pr_err("%s: AFE cal for port %d failed\n",
361 __func__, port_id);
362 }
363
364 pr_debug("%s: AFE cal sent for path %d device!\n", __func__, path);
365done:
366 return;
367}
368
369void afe_send_cal(u16 port_id)
370{
371 pr_debug("%s\n", __func__);
372
373 if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX)
374 afe_send_cal_block(TX_CAL, port_id);
375 else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX)
376 afe_send_cal_block(RX_CAL, port_id);
377}
378
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700379int afe_port_start_nowait(u16 port_id, union afe_port_config *afe_config,
380 u32 rate) /* This function is no blocking */
381{
382 struct afe_port_start_command start;
383 struct afe_audioif_config_command config;
384 int ret;
385
386 if (!afe_config) {
387 pr_err("%s: Error, no configuration data\n", __func__);
388 ret = -EINVAL;
389 return ret;
390 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -0800391 pr_debug("%s: %d %d\n", __func__, port_id, rate);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700392
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530393 if ((port_id == RT_PROXY_DAI_001_RX) ||
394 (port_id == RT_PROXY_DAI_002_TX))
395 return -EINVAL;
396 if ((port_id == RT_PROXY_DAI_002_RX) ||
397 (port_id == RT_PROXY_DAI_001_TX))
398 port_id = VIRTUAL_ID_TO_PORTID(port_id);
399
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700400 if (this_afe.apr == NULL) {
Jay Wang6a305432011-08-05 16:01:54 -0700401 pr_err("%s: AFE APR is not registered\n", __func__);
402 ret = -ENODEV;
403 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700404 }
Kiran Kandi5e809b02012-01-31 00:24:33 -0800405
406 if (port_id == HDMI_RX) {
407 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700408 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
Kiran Kandi5e809b02012-01-31 00:24:33 -0800409 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
410 config.hdr.src_port = 0;
411 config.hdr.dest_port = 0;
412 config.hdr.token = 0;
413 config.hdr.opcode = AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG;
414 } else {
415
416 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
417 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
418 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
419 config.hdr.src_port = 0;
420 config.hdr.dest_port = 0;
421 config.hdr.token = 0;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800422 switch (port_id) {
423 case SLIMBUS_0_RX:
424 case SLIMBUS_0_TX:
425 case SLIMBUS_1_RX:
426 case SLIMBUS_1_TX:
427 case SLIMBUS_2_RX:
428 case SLIMBUS_2_TX:
429 case SLIMBUS_3_RX:
430 case SLIMBUS_3_TX:
431 case SLIMBUS_4_RX:
432 case SLIMBUS_4_TX:
433 config.hdr.opcode = AFE_PORT_AUDIO_SLIM_SCH_CONFIG;
434 break;
435 default:
436 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
437 break;
438 }
Kiran Kandi5e809b02012-01-31 00:24:33 -0800439 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700440
441 if (afe_validate_port(port_id) < 0) {
442
443 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
444 port_id);
445 ret = -EINVAL;
446 goto fail_cmd;
447 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700448 config.port_id = port_id;
449 config.port = *afe_config;
450
451 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
452 if (ret < 0) {
453 pr_err("%s: AFE enable for port %d failed\n", __func__,
454 port_id);
455 ret = -EINVAL;
456 goto fail_cmd;
457 }
Ben Rombergerb7603232011-11-23 17:16:27 -0800458
459 /* send AFE cal */
460 afe_send_cal(port_id);
461
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700462 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
463 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
464 start.hdr.pkt_size = sizeof(start);
465 start.hdr.src_port = 0;
466 start.hdr.dest_port = 0;
467 start.hdr.token = 0;
468 start.hdr.opcode = AFE_PORT_CMD_START;
469 start.port_id = port_id;
470 start.gain = 0x2000;
471 start.sample_rate = rate;
472
473 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
474
475 if (IS_ERR_VALUE(ret)) {
476 pr_err("%s: AFE enable for port %d failed\n", __func__,
477 port_id);
478 ret = -EINVAL;
479 goto fail_cmd;
480 }
481
482 if (this_afe.task != current)
483 this_afe.task = current;
484
485 pr_debug("task_name = %s pid = %d\n",
486 this_afe.task->comm, this_afe.task->pid);
487 return 0;
488
489fail_cmd:
490 return ret;
491}
492
493int afe_open(u16 port_id, union afe_port_config *afe_config, int rate)
494{
495 struct afe_port_start_command start;
496 struct afe_audioif_config_command config;
497 int ret = 0;
498
499 if (!afe_config) {
500 pr_err("%s: Error, no configuration data\n", __func__);
501 ret = -EINVAL;
502 return ret;
503 }
504
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800505 pr_debug("%s: %d %d\n", __func__, port_id, rate);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700506
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530507 if ((port_id == RT_PROXY_DAI_001_RX) ||
508 (port_id == RT_PROXY_DAI_002_TX))
509 return -EINVAL;
510 if ((port_id == RT_PROXY_DAI_002_RX) ||
511 (port_id == RT_PROXY_DAI_001_TX))
512 port_id = VIRTUAL_ID_TO_PORTID(port_id);
513
Jay Wang6a305432011-08-05 16:01:54 -0700514 ret = afe_q6_interface_prepare();
515 if (ret != 0)
516 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700517
518 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
519 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
520 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
521 config.hdr.src_port = 0;
522 config.hdr.dest_port = 0;
523 config.hdr.token = 0;
524 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
525
526 if (afe_validate_port(port_id) < 0) {
527
528 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
529 port_id);
530 ret = -EINVAL;
531 goto fail_cmd;
532 }
533
534 config.port_id = port_id;
535 config.port = *afe_config;
536
537 atomic_set(&this_afe.state, 1);
538 atomic_set(&this_afe.status, 0);
539 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
540 if (ret < 0) {
541 pr_err("%s: AFE enable for port %d failed\n", __func__,
542 port_id);
543 ret = -EINVAL;
544 goto fail_cmd;
545 }
546
547 ret = wait_event_timeout(this_afe.wait,
548 (atomic_read(&this_afe.state) == 0),
549 msecs_to_jiffies(TIMEOUT_MS));
550 if (!ret) {
551 pr_err("%s: wait_event timeout\n", __func__);
552 ret = -EINVAL;
553 goto fail_cmd;
554 }
555 if (atomic_read(&this_afe.status) != 0) {
556 pr_err("%s: config cmd failed\n", __func__);
557 ret = -EINVAL;
558 goto fail_cmd;
559 }
560 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
561 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
562 start.hdr.pkt_size = sizeof(start);
563 start.hdr.src_port = 0;
564 start.hdr.dest_port = 0;
565 start.hdr.token = 0;
566 start.hdr.opcode = AFE_PORT_CMD_START;
567 start.port_id = port_id;
568 start.gain = 0x2000;
569 start.sample_rate = rate;
570
571 atomic_set(&this_afe.state, 1);
572 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
573 if (ret < 0) {
574 pr_err("%s: AFE enable for port %d failed\n", __func__,
575 port_id);
576 ret = -EINVAL;
577 goto fail_cmd;
578 }
579 ret = wait_event_timeout(this_afe.wait,
580 (atomic_read(&this_afe.state) == 0),
581 msecs_to_jiffies(TIMEOUT_MS));
582 if (!ret) {
583 pr_err("%s: wait_event timeout\n", __func__);
584 ret = -EINVAL;
585 goto fail_cmd;
586 }
587
588 if (this_afe.task != current)
589 this_afe.task = current;
590
591 pr_debug("task_name = %s pid = %d\n",
592 this_afe.task->comm, this_afe.task->pid);
593 return 0;
594fail_cmd:
595 return ret;
596}
597
598int afe_loopback(u16 enable, u16 rx_port, u16 tx_port)
599{
600 struct afe_loopback_command lb_cmd;
601 int ret = 0;
Jay Wang6a305432011-08-05 16:01:54 -0700602
603 ret = afe_q6_interface_prepare();
604 if (ret != 0)
605 return ret;
606
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700607 lb_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
608 APR_HDR_LEN(20), APR_PKT_VER);
609 lb_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
610 sizeof(lb_cmd) - APR_HDR_SIZE);
611 lb_cmd.hdr.src_port = 0;
612 lb_cmd.hdr.dest_port = 0;
613 lb_cmd.hdr.token = 0;
614 lb_cmd.hdr.opcode = AFE_PORT_CMD_LOOPBACK;
615 lb_cmd.tx_port_id = tx_port;
616 lb_cmd.rx_port_id = rx_port;
617 lb_cmd.mode = 0xFFFF;
618 lb_cmd.enable = (enable ? 1 : 0);
619 atomic_set(&this_afe.state, 1);
620
621 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &lb_cmd);
622 if (ret < 0) {
623 pr_err("%s: AFE loopback failed\n", __func__);
624 ret = -EINVAL;
625 goto done;
626 }
627 ret = wait_event_timeout(this_afe.wait,
628 (atomic_read(&this_afe.state) == 0),
629 msecs_to_jiffies(TIMEOUT_MS));
630 if (!ret) {
631 pr_err("%s: wait_event timeout\n", __func__);
632 ret = -EINVAL;
633 }
634done:
635 return ret;
636}
637
638
639int afe_loopback_gain(u16 port_id, u16 volume)
640{
641 struct afe_port_cmd_set_param set_param;
642 int ret = 0;
643
644 if (this_afe.apr == NULL) {
Jayasena Sangaraboina82435032011-07-26 15:23:00 -0700645 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
646 0xFFFFFFFF, &this_afe);
647 pr_debug("%s: Register AFE\n", __func__);
648 if (this_afe.apr == NULL) {
649 pr_err("%s: Unable to register AFE\n", __func__);
650 ret = -ENODEV;
651 return ret;
652 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700653 }
654
655 if (afe_validate_port(port_id) < 0) {
656
657 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
658 port_id);
659 ret = -EINVAL;
660 goto fail_cmd;
661 }
662
663 /* RX ports numbers are even .TX ports numbers are odd. */
664 if (port_id % 2 == 0) {
665 pr_err("%s: Failed : afe loopback gain only for TX ports."
666 " port_id %d\n", __func__, port_id);
667 ret = -EINVAL;
668 goto fail_cmd;
669 }
670
671 pr_debug("%s: %d %hX\n", __func__, port_id, volume);
672
673 set_param.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
674 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
675 set_param.hdr.pkt_size = sizeof(set_param);
676 set_param.hdr.src_port = 0;
677 set_param.hdr.dest_port = 0;
678 set_param.hdr.token = 0;
679 set_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
680
681 set_param.port_id = port_id;
682 set_param.payload_size = sizeof(struct afe_param_payload);
683 set_param.payload_address = 0;
684
685 set_param.payload.module_id = AFE_MODULE_ID_PORT_INFO;
686 set_param.payload.param_id = AFE_PARAM_ID_LOOPBACK_GAIN;
687 set_param.payload.param_size = sizeof(struct afe_param_loopback_gain);
688 set_param.payload.reserved = 0;
689
690 set_param.payload.param.loopback_gain.gain = volume;
691 set_param.payload.param.loopback_gain.reserved = 0;
692
693 atomic_set(&this_afe.state, 1);
694 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_param);
695 if (ret < 0) {
696 pr_err("%s: AFE param set failed for port %d\n",
697 __func__, port_id);
698 ret = -EINVAL;
699 goto fail_cmd;
700 }
701
702 ret = wait_event_timeout(this_afe.wait,
703 (atomic_read(&this_afe.state) == 0),
704 msecs_to_jiffies(TIMEOUT_MS));
705 if (ret < 0) {
706 pr_err("%s: wait_event timeout\n", __func__);
707 ret = -EINVAL;
708 goto fail_cmd;
709 }
710 return 0;
711fail_cmd:
712 return ret;
713}
714
Laxminath Kasam885f5102011-07-14 10:20:21 +0530715int afe_apply_gain(u16 port_id, u16 gain)
716{
717 struct afe_port_gain_command set_gain;
718 int ret = 0;
719
720 if (this_afe.apr == NULL) {
721 pr_err("%s: AFE is not opened\n", __func__);
722 ret = -EPERM;
723 goto fail_cmd;
724 }
725
726 if (afe_validate_port(port_id) < 0) {
727 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
728 port_id);
729 ret = -EINVAL;
730 goto fail_cmd;
731 }
732
733 /* RX ports numbers are even .TX ports numbers are odd. */
734 if (port_id % 2 == 0) {
735 pr_err("%s: Failed : afe apply gain only for TX ports."
736 " port_id %d\n", __func__, port_id);
737 ret = -EINVAL;
738 goto fail_cmd;
739 }
740
741 pr_debug("%s: %d %hX\n", __func__, port_id, gain);
742
743 set_gain.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
744 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
745 set_gain.hdr.pkt_size = sizeof(set_gain);
746 set_gain.hdr.src_port = 0;
747 set_gain.hdr.dest_port = 0;
748 set_gain.hdr.token = 0;
749 set_gain.hdr.opcode = AFE_PORT_CMD_APPLY_GAIN;
750
751 set_gain.port_id = port_id;
752 set_gain.gain = gain;
753
754 atomic_set(&this_afe.state, 1);
755 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_gain);
756 if (ret < 0) {
757 pr_err("%s: AFE Gain set failed for port %d\n",
758 __func__, port_id);
759 ret = -EINVAL;
760 goto fail_cmd;
761 }
762
763 ret = wait_event_timeout(this_afe.wait,
764 (atomic_read(&this_afe.state) == 0),
765 msecs_to_jiffies(TIMEOUT_MS));
766 if (ret < 0) {
767 pr_err("%s: wait_event timeout\n", __func__);
768 ret = -EINVAL;
769 goto fail_cmd;
770 }
771 return 0;
772fail_cmd:
773 return ret;
774}
Helen Zeng0705a5f2011-10-14 15:29:52 -0700775
776int afe_pseudo_port_start_nowait(u16 port_id)
777{
778 int ret = 0;
779 struct afe_pseudoport_start_command start;
780
781 pr_debug("%s: port_id=%d\n", __func__, port_id);
782 if (this_afe.apr == NULL) {
783 pr_err("%s: AFE APR is not registered\n", __func__);
784 return -ENODEV;
785 }
786
787
788 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
789 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
790 start.hdr.pkt_size = sizeof(start);
791 start.hdr.src_port = 0;
792 start.hdr.dest_port = 0;
793 start.hdr.token = 0;
794 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
795 start.port_id = port_id;
796 start.timing = 1;
797
798 atomic_set(&this_afe.state, 1);
799 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
800 if (ret < 0) {
801 pr_err("%s: AFE enable for port %d failed %d\n",
802 __func__, port_id, ret);
803 return -EINVAL;
804 }
805 return 0;
806}
807
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700808int afe_start_pseudo_port(u16 port_id)
809{
810 int ret = 0;
811 struct afe_pseudoport_start_command start;
812
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800813 pr_debug("%s: port_id=%d\n", __func__, port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700814
Jay Wang6a305432011-08-05 16:01:54 -0700815 ret = afe_q6_interface_prepare();
816 if (ret != 0)
817 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700818
819 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
820 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
821 start.hdr.pkt_size = sizeof(start);
822 start.hdr.src_port = 0;
823 start.hdr.dest_port = 0;
824 start.hdr.token = 0;
825 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
826 start.port_id = port_id;
827 start.timing = 1;
828
829 atomic_set(&this_afe.state, 1);
830 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
831 if (ret < 0) {
832 pr_err("%s: AFE enable for port %d failed %d\n",
833 __func__, port_id, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700834 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700835 }
836
837 ret = wait_event_timeout(this_afe.wait,
838 (atomic_read(&this_afe.state) == 0),
839 msecs_to_jiffies(TIMEOUT_MS));
840 if (!ret) {
841 pr_err("%s: wait_event timeout\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700842 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700843 }
844
845 return 0;
846}
847
Helen Zeng0705a5f2011-10-14 15:29:52 -0700848int afe_pseudo_port_stop_nowait(u16 port_id)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700849{
850 int ret = 0;
851 struct afe_pseudoport_stop_command stop;
852
Helen Zeng0705a5f2011-10-14 15:29:52 -0700853 pr_debug("%s: port_id=%d\n", __func__, port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700854
855 if (this_afe.apr == NULL) {
856 pr_err("%s: AFE is already closed\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700857 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700858 }
859
860 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
861 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
862 stop.hdr.pkt_size = sizeof(stop);
863 stop.hdr.src_port = 0;
864 stop.hdr.dest_port = 0;
865 stop.hdr.token = 0;
866 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
867 stop.port_id = port_id;
868 stop.reserved = 0;
869
870 atomic_set(&this_afe.state, 1);
871 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
872 if (ret < 0) {
873 pr_err("%s: AFE close failed %d\n", __func__, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700874 return -EINVAL;
875 }
876
877 return 0;
878
879}
880
881int afe_stop_pseudo_port(u16 port_id)
882{
883 int ret = 0;
884 struct afe_pseudoport_stop_command stop;
885
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800886 pr_debug("%s: port_id=%d\n", __func__, port_id);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700887
888 if (this_afe.apr == NULL) {
889 pr_err("%s: AFE is already closed\n", __func__);
890 return -EINVAL;
891 }
892
893 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
894 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
895 stop.hdr.pkt_size = sizeof(stop);
896 stop.hdr.src_port = 0;
897 stop.hdr.dest_port = 0;
898 stop.hdr.token = 0;
899 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
900 stop.port_id = port_id;
901 stop.reserved = 0;
902
903 atomic_set(&this_afe.state, 1);
904 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
905 if (ret < 0) {
906 pr_err("%s: AFE close failed %d\n", __func__, ret);
907 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700908 }
909
910 ret = wait_event_timeout(this_afe.wait,
911 (atomic_read(&this_afe.state) == 0),
912 msecs_to_jiffies(TIMEOUT_MS));
913 if (!ret) {
914 pr_err("%s: wait_event timeout\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700915 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700916 }
917
918 return 0;
919}
920
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530921int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz)
922{
923 int ret = 0;
924 struct afe_cmd_memory_map mregion;
925
926 pr_debug("%s:\n", __func__);
927
928 if (this_afe.apr == NULL) {
929 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
930 0xFFFFFFFF, &this_afe);
931 pr_debug("%s: Register AFE\n", __func__);
932 if (this_afe.apr == NULL) {
933 pr_err("%s: Unable to register AFE\n", __func__);
934 ret = -ENODEV;
935 return ret;
936 }
937 }
938
939 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
940 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
941 mregion.hdr.pkt_size = sizeof(mregion);
942 mregion.hdr.src_port = 0;
943 mregion.hdr.dest_port = 0;
944 mregion.hdr.token = 0;
945 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
946 mregion.phy_addr = dma_addr_p;
947 mregion.mem_sz = dma_buf_sz;
948 mregion.mem_id = 0;
949 mregion.rsvd = 0;
950
951 atomic_set(&this_afe.state, 1);
952 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
953 if (ret < 0) {
954 pr_err("%s: AFE memory map cmd failed %d\n",
955 __func__, ret);
956 ret = -EINVAL;
957 return ret;
958 }
959
960 ret = wait_event_timeout(this_afe.wait,
961 (atomic_read(&this_afe.state) == 0),
962 msecs_to_jiffies(TIMEOUT_MS));
963 if (!ret) {
964 pr_err("%s: wait_event timeout\n", __func__);
965 ret = -EINVAL;
966 return ret;
967 }
968
969 return 0;
970}
971
Ben Rombergerb7603232011-11-23 17:16:27 -0800972int afe_cmd_memory_map_nowait(u32 dma_addr_p, u32 dma_buf_sz)
973{
974 int ret = 0;
975 struct afe_cmd_memory_map mregion;
976
977 pr_debug("%s:\n", __func__);
978
979 if (this_afe.apr == NULL) {
980 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
981 0xFFFFFFFF, &this_afe);
982 pr_debug("%s: Register AFE\n", __func__);
983 if (this_afe.apr == NULL) {
984 pr_err("%s: Unable to register AFE\n", __func__);
985 ret = -ENODEV;
986 return ret;
987 }
988 }
989
990 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
991 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
992 mregion.hdr.pkt_size = sizeof(mregion);
993 mregion.hdr.src_port = 0;
994 mregion.hdr.dest_port = 0;
995 mregion.hdr.token = 0;
996 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
997 mregion.phy_addr = dma_addr_p;
998 mregion.mem_sz = dma_buf_sz;
999 mregion.mem_id = 0;
1000 mregion.rsvd = 0;
1001
1002 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1003 if (ret < 0) {
1004 pr_err("%s: AFE memory map cmd failed %d\n",
1005 __func__, ret);
1006 ret = -EINVAL;
1007 }
1008 return 0;
1009}
1010
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301011int afe_cmd_memory_unmap(u32 dma_addr_p)
1012{
1013 int ret = 0;
1014 struct afe_cmd_memory_unmap mregion;
1015
1016 pr_debug("%s:\n", __func__);
1017
1018 if (this_afe.apr == NULL) {
1019 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1020 0xFFFFFFFF, &this_afe);
1021 pr_debug("%s: Register AFE\n", __func__);
1022 if (this_afe.apr == NULL) {
1023 pr_err("%s: Unable to register AFE\n", __func__);
1024 ret = -ENODEV;
1025 return ret;
1026 }
1027 }
1028
1029 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1030 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1031 mregion.hdr.pkt_size = sizeof(mregion);
1032 mregion.hdr.src_port = 0;
1033 mregion.hdr.dest_port = 0;
1034 mregion.hdr.token = 0;
1035 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
1036 mregion.phy_addr = dma_addr_p;
1037
1038 atomic_set(&this_afe.state, 1);
1039 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1040 if (ret < 0) {
Ben Rombergerb7603232011-11-23 17:16:27 -08001041 pr_err("%s: AFE memory unmap cmd failed %d\n",
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301042 __func__, ret);
1043 ret = -EINVAL;
1044 return ret;
1045 }
1046
1047 ret = wait_event_timeout(this_afe.wait,
1048 (atomic_read(&this_afe.state) == 0),
1049 msecs_to_jiffies(TIMEOUT_MS));
1050 if (!ret) {
1051 pr_err("%s: wait_event timeout\n", __func__);
1052 ret = -EINVAL;
1053 return ret;
1054 }
Ben Rombergerb7603232011-11-23 17:16:27 -08001055 return 0;
1056}
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301057
Ben Rombergerb7603232011-11-23 17:16:27 -08001058int afe_cmd_memory_unmap_nowait(u32 dma_addr_p)
1059{
1060 int ret = 0;
1061 struct afe_cmd_memory_unmap mregion;
1062
1063 pr_debug("%s:\n", __func__);
1064
1065 if (this_afe.apr == NULL) {
1066 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1067 0xFFFFFFFF, &this_afe);
1068 pr_debug("%s: Register AFE\n", __func__);
1069 if (this_afe.apr == NULL) {
1070 pr_err("%s: Unable to register AFE\n", __func__);
1071 ret = -ENODEV;
1072 return ret;
1073 }
1074 }
1075
1076 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1077 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1078 mregion.hdr.pkt_size = sizeof(mregion);
1079 mregion.hdr.src_port = 0;
1080 mregion.hdr.dest_port = 0;
1081 mregion.hdr.token = 0;
1082 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
1083 mregion.phy_addr = dma_addr_p;
1084
1085 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1086 if (ret < 0) {
1087 pr_err("%s: AFE memory unmap cmd failed %d\n",
1088 __func__, ret);
1089 ret = -EINVAL;
1090 }
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301091 return 0;
1092}
1093
1094int afe_register_get_events(u16 port_id,
1095 void (*cb) (uint32_t opcode,
1096 uint32_t token, uint32_t *payload, void *priv),
1097 void *private_data)
1098{
1099 int ret = 0;
1100 struct afe_cmd_reg_rtport rtproxy;
1101
1102 pr_debug("%s:\n", __func__);
1103
1104 if (this_afe.apr == NULL) {
1105 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1106 0xFFFFFFFF, &this_afe);
1107 pr_debug("%s: Register AFE\n", __func__);
1108 if (this_afe.apr == NULL) {
1109 pr_err("%s: Unable to register AFE\n", __func__);
1110 ret = -ENODEV;
1111 return ret;
1112 }
1113 }
1114 if ((port_id == RT_PROXY_DAI_002_RX) ||
1115 (port_id == RT_PROXY_DAI_001_TX))
1116 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1117 else
1118 return -EINVAL;
1119
1120 if (port_id == RT_PROXY_PORT_001_TX) {
1121 this_afe.tx_cb = cb;
1122 this_afe.tx_private_data = private_data;
1123 } else if (port_id == RT_PROXY_PORT_001_RX) {
1124 this_afe.rx_cb = cb;
1125 this_afe.rx_private_data = private_data;
1126 }
1127
1128 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1129 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1130 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1131 rtproxy.hdr.src_port = 1;
1132 rtproxy.hdr.dest_port = 1;
1133 rtproxy.hdr.token = 0;
1134 rtproxy.hdr.opcode = AFE_SERVICE_CMD_REG_RTPORT;
1135 rtproxy.port_id = port_id;
1136 rtproxy.rsvd = 0;
1137
1138 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1139 if (ret < 0) {
1140 pr_err("%s: AFE reg. rtproxy_event failed %d\n",
1141 __func__, ret);
1142 ret = -EINVAL;
1143 return ret;
1144 }
1145 return 0;
1146}
1147
1148int afe_unregister_get_events(u16 port_id)
1149{
1150 int ret = 0;
1151 struct afe_cmd_unreg_rtport rtproxy;
1152
1153 pr_debug("%s:\n", __func__);
1154
1155 if (this_afe.apr == NULL) {
1156 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1157 0xFFFFFFFF, &this_afe);
1158 pr_debug("%s: Register AFE\n", __func__);
1159 if (this_afe.apr == NULL) {
1160 pr_err("%s: Unable to register AFE\n", __func__);
1161 ret = -ENODEV;
1162 return ret;
1163 }
1164 }
1165 if ((port_id == RT_PROXY_DAI_002_RX) ||
1166 (port_id == RT_PROXY_DAI_001_TX))
1167 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1168 else
1169 return -EINVAL;
1170
1171 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1172 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1173 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1174 rtproxy.hdr.src_port = 0;
1175 rtproxy.hdr.dest_port = 0;
1176 rtproxy.hdr.token = 0;
1177 rtproxy.hdr.opcode = AFE_SERVICE_CMD_UNREG_RTPORT;
1178 rtproxy.port_id = port_id;
1179 rtproxy.rsvd = 0;
1180
1181 if (port_id == RT_PROXY_PORT_001_TX) {
1182 this_afe.tx_cb = NULL;
1183 this_afe.tx_private_data = NULL;
1184 } else if (port_id == RT_PROXY_PORT_001_RX) {
1185 this_afe.rx_cb = NULL;
1186 this_afe.rx_private_data = NULL;
1187 }
1188
1189 atomic_set(&this_afe.state, 1);
1190 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1191 if (ret < 0) {
1192 pr_err("%s: AFE enable Unreg. rtproxy_event failed %d\n",
1193 __func__, ret);
1194 ret = -EINVAL;
1195 return ret;
1196 }
1197
1198 ret = wait_event_timeout(this_afe.wait,
1199 (atomic_read(&this_afe.state) == 0),
1200 msecs_to_jiffies(TIMEOUT_MS));
1201 if (!ret) {
1202 pr_err("%s: wait_event timeout\n", __func__);
1203 ret = -EINVAL;
1204 return ret;
1205 }
1206 return 0;
1207}
1208
1209int afe_rt_proxy_port_write(u32 buf_addr_p, int bytes)
1210{
1211 int ret = 0;
1212 struct afe_cmd_rtport_wr afecmd_wr;
1213
1214 if (this_afe.apr == NULL) {
1215 pr_err("%s:register to AFE is not done\n", __func__);
1216 ret = -ENODEV;
1217 return ret;
1218 }
1219 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1220 buf_addr_p, bytes);
1221
1222 afecmd_wr.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1223 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1224 afecmd_wr.hdr.pkt_size = sizeof(afecmd_wr);
1225 afecmd_wr.hdr.src_port = 0;
1226 afecmd_wr.hdr.dest_port = 0;
1227 afecmd_wr.hdr.token = 0;
1228 afecmd_wr.hdr.opcode = AFE_SERVICE_CMD_RTPORT_WR;
1229 afecmd_wr.buf_addr = (uint32_t)buf_addr_p;
1230 afecmd_wr.port_id = RT_PROXY_PORT_001_TX;
1231 afecmd_wr.bytes_avail = bytes;
1232 afecmd_wr.rsvd = 0;
1233
1234 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_wr);
1235 if (ret < 0) {
1236 pr_err("%s: AFE rtproxy write to port 0x%x failed %d\n",
1237 __func__, afecmd_wr.port_id, ret);
1238 ret = -EINVAL;
1239 return ret;
1240 }
1241 return 0;
1242
1243}
1244
1245int afe_rt_proxy_port_read(u32 buf_addr_p, int bytes)
1246{
1247 int ret = 0;
1248 struct afe_cmd_rtport_rd afecmd_rd;
1249
1250 if (this_afe.apr == NULL) {
1251 pr_err("%s: register to AFE is not done\n", __func__);
1252 ret = -ENODEV;
1253 return ret;
1254 }
1255 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1256 buf_addr_p, bytes);
1257
1258 afecmd_rd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1259 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1260 afecmd_rd.hdr.pkt_size = sizeof(afecmd_rd);
1261 afecmd_rd.hdr.src_port = 0;
1262 afecmd_rd.hdr.dest_port = 0;
1263 afecmd_rd.hdr.token = 0;
1264 afecmd_rd.hdr.opcode = AFE_SERVICE_CMD_RTPORT_RD;
1265 afecmd_rd.buf_addr = (uint32_t)buf_addr_p;
1266 afecmd_rd.port_id = RT_PROXY_PORT_001_RX;
1267 afecmd_rd.bytes_avail = bytes;
1268 afecmd_rd.rsvd = 0;
1269
1270 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_rd);
1271 if (ret < 0) {
1272 pr_err("%s: AFE rtproxy read cmd to port 0x%x failed %d\n",
1273 __func__, afecmd_rd.port_id, ret);
1274 ret = -EINVAL;
1275 return ret;
1276 }
1277 return 0;
1278}
1279
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001280#ifdef CONFIG_DEBUG_FS
1281static struct dentry *debugfs_afelb;
1282static struct dentry *debugfs_afelb_gain;
1283
1284static int afe_debug_open(struct inode *inode, struct file *file)
1285{
1286 file->private_data = inode->i_private;
1287 pr_info("debug intf %s\n", (char *) file->private_data);
1288 return 0;
1289}
1290
1291static int afe_get_parameters(char *buf, long int *param1, int num_of_par)
1292{
1293 char *token;
1294 int base, cnt;
1295
1296 token = strsep(&buf, " ");
1297
1298 for (cnt = 0; cnt < num_of_par; cnt++) {
1299 if (token != NULL) {
1300 if ((token[1] == 'x') || (token[1] == 'X'))
1301 base = 16;
1302 else
1303 base = 10;
1304
1305 if (strict_strtoul(token, base, &param1[cnt]) != 0)
1306 return -EINVAL;
1307
1308 token = strsep(&buf, " ");
1309 } else
1310 return -EINVAL;
1311 }
1312 return 0;
1313}
1314#define AFE_LOOPBACK_ON (1)
1315#define AFE_LOOPBACK_OFF (0)
1316static ssize_t afe_debug_write(struct file *filp,
1317 const char __user *ubuf, size_t cnt, loff_t *ppos)
1318{
1319 char *lb_str = filp->private_data;
1320 char lbuf[32];
1321 int rc;
1322 unsigned long param[5];
1323
1324 if (cnt > sizeof(lbuf) - 1)
1325 return -EINVAL;
1326
1327 rc = copy_from_user(lbuf, ubuf, cnt);
1328 if (rc)
1329 return -EFAULT;
1330
1331 lbuf[cnt] = '\0';
1332
1333 if (!strcmp(lb_str, "afe_loopback")) {
1334 rc = afe_get_parameters(lbuf, param, 3);
1335 if (!rc) {
1336 pr_info("%s %lu %lu %lu\n", lb_str, param[0], param[1],
1337 param[2]);
1338
1339 if ((param[0] != AFE_LOOPBACK_ON) && (param[0] !=
1340 AFE_LOOPBACK_OFF)) {
1341 pr_err("%s: Error, parameter 0 incorrect\n",
1342 __func__);
1343 rc = -EINVAL;
1344 goto afe_error;
1345 }
1346 if ((afe_validate_port(param[1]) < 0) ||
1347 (afe_validate_port(param[2])) < 0) {
1348 pr_err("%s: Error, invalid afe port\n",
1349 __func__);
1350 }
1351 if (this_afe.apr == NULL) {
1352 pr_err("%s: Error, AFE not opened\n", __func__);
1353 rc = -EINVAL;
1354 } else {
1355 rc = afe_loopback(param[0], param[1], param[2]);
1356 }
1357 } else {
1358 pr_err("%s: Error, invalid parameters\n", __func__);
1359 rc = -EINVAL;
1360 }
1361
1362 } else if (!strcmp(lb_str, "afe_loopback_gain")) {
1363 rc = afe_get_parameters(lbuf, param, 2);
1364 if (!rc) {
1365 pr_info("%s %lu %lu\n", lb_str, param[0], param[1]);
1366
1367 if (afe_validate_port(param[0]) < 0) {
1368 pr_err("%s: Error, invalid afe port\n",
1369 __func__);
1370 rc = -EINVAL;
1371 goto afe_error;
1372 }
1373
1374 if (param[1] < 0 || param[1] > 100) {
1375 pr_err("%s: Error, volume shoud be 0 to 100"
1376 " percentage param = %lu\n",
1377 __func__, param[1]);
1378 rc = -EINVAL;
1379 goto afe_error;
1380 }
1381
1382 param[1] = (Q6AFE_MAX_VOLUME * param[1]) / 100;
1383
1384 if (this_afe.apr == NULL) {
1385 pr_err("%s: Error, AFE not opened\n", __func__);
1386 rc = -EINVAL;
1387 } else {
1388 rc = afe_loopback_gain(param[0], param[1]);
1389 }
1390 } else {
1391 pr_err("%s: Error, invalid parameters\n", __func__);
1392 rc = -EINVAL;
1393 }
1394 }
1395
1396afe_error:
1397 if (rc == 0)
1398 rc = cnt;
1399 else
1400 pr_err("%s: rc = %d\n", __func__, rc);
1401
1402 return rc;
1403}
1404
1405static const struct file_operations afe_debug_fops = {
1406 .open = afe_debug_open,
1407 .write = afe_debug_write
1408};
1409#endif
1410int afe_sidetone(u16 tx_port_id, u16 rx_port_id, u16 enable, uint16_t gain)
1411{
1412 struct afe_port_sidetone_command cmd_sidetone;
1413 int ret = 0;
1414
1415 pr_info("%s: tx_port_id:%d rx_port_id:%d enable:%d gain:%d\n", __func__,
1416 tx_port_id, rx_port_id, enable, gain);
1417 cmd_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1418 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1419 cmd_sidetone.hdr.pkt_size = sizeof(cmd_sidetone);
1420 cmd_sidetone.hdr.src_port = 0;
1421 cmd_sidetone.hdr.dest_port = 0;
1422 cmd_sidetone.hdr.token = 0;
1423 cmd_sidetone.hdr.opcode = AFE_PORT_CMD_SIDETONE_CTL;
1424 cmd_sidetone.tx_port_id = tx_port_id;
1425 cmd_sidetone.rx_port_id = rx_port_id;
1426 cmd_sidetone.gain = gain;
1427 cmd_sidetone.enable = enable;
1428
1429 atomic_set(&this_afe.state, 1);
1430 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_sidetone);
1431 if (ret < 0) {
1432 pr_err("%s: AFE sidetone failed for tx_port:%d rx_port:%d\n",
1433 __func__, tx_port_id, rx_port_id);
1434 ret = -EINVAL;
1435 goto fail_cmd;
1436 }
1437
1438 ret = wait_event_timeout(this_afe.wait,
1439 (atomic_read(&this_afe.state) == 0),
1440 msecs_to_jiffies(TIMEOUT_MS));
1441 if (ret < 0) {
1442 pr_err("%s: wait_event timeout\n", __func__);
1443 ret = -EINVAL;
1444 goto fail_cmd;
1445 }
1446 return 0;
1447fail_cmd:
1448 return ret;
1449}
1450
1451int afe_port_stop_nowait(int port_id)
1452{
1453 struct afe_port_stop_command stop;
1454 int ret = 0;
1455
1456 if (this_afe.apr == NULL) {
1457 pr_err("AFE is already closed\n");
1458 ret = -EINVAL;
1459 goto fail_cmd;
1460 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001461 pr_debug("%s: port_id=%d\n", __func__, port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301462 port_id = afe_convert_virtual_to_portid(port_id);
1463
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001464 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1465 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1466 stop.hdr.pkt_size = sizeof(stop);
1467 stop.hdr.src_port = 0;
1468 stop.hdr.dest_port = 0;
1469 stop.hdr.token = 0;
1470 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1471 stop.port_id = port_id;
1472 stop.reserved = 0;
1473
1474 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1475
1476 if (ret == -ENETRESET) {
1477 pr_info("%s: Need to reset, calling APR deregister", __func__);
1478 return apr_deregister(this_afe.apr);
1479 } else if (IS_ERR_VALUE(ret)) {
1480 pr_err("%s: AFE close failed\n", __func__);
1481 ret = -EINVAL;
1482 }
1483
1484fail_cmd:
1485 return ret;
1486
1487}
1488
1489int afe_close(int port_id)
1490{
1491 struct afe_port_stop_command stop;
1492 int ret = 0;
1493
1494 if (this_afe.apr == NULL) {
1495 pr_err("AFE is already closed\n");
1496 ret = -EINVAL;
1497 goto fail_cmd;
1498 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001499 pr_debug("%s: port_id=%d\n", __func__, port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301500 port_id = afe_convert_virtual_to_portid(port_id);
1501
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001502 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1503 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1504 stop.hdr.pkt_size = sizeof(stop);
1505 stop.hdr.src_port = 0;
1506 stop.hdr.dest_port = 0;
1507 stop.hdr.token = 0;
1508 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1509 stop.port_id = port_id;
1510 stop.reserved = 0;
1511
1512 atomic_set(&this_afe.state, 1);
1513 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1514
1515 if (ret == -ENETRESET) {
1516 pr_info("%s: Need to reset, calling APR deregister", __func__);
1517 return apr_deregister(this_afe.apr);
1518 }
1519
1520 if (ret < 0) {
1521 pr_err("%s: AFE close failed\n", __func__);
1522 ret = -EINVAL;
1523 goto fail_cmd;
1524 }
1525
1526 ret = wait_event_timeout(this_afe.wait,
1527 (atomic_read(&this_afe.state) == 0),
1528 msecs_to_jiffies(TIMEOUT_MS));
1529 if (!ret) {
1530 pr_err("%s: wait_event timeout\n", __func__);
1531 ret = -EINVAL;
1532 goto fail_cmd;
1533 }
1534fail_cmd:
1535 return ret;
1536}
1537
1538static int __init afe_init(void)
1539{
1540 init_waitqueue_head(&this_afe.wait);
1541 atomic_set(&this_afe.state, 0);
1542 atomic_set(&this_afe.status, 0);
1543 this_afe.apr = NULL;
1544#ifdef CONFIG_DEBUG_FS
1545 debugfs_afelb = debugfs_create_file("afe_loopback",
1546 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback",
1547 &afe_debug_fops);
1548
1549 debugfs_afelb_gain = debugfs_create_file("afe_loopback_gain",
1550 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback_gain",
1551 &afe_debug_fops);
1552
1553
1554#endif
1555 return 0;
1556}
1557
1558static void __exit afe_exit(void)
1559{
Ben Rombergerb7603232011-11-23 17:16:27 -08001560 int i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001561#ifdef CONFIG_DEBUG_FS
1562 if (debugfs_afelb)
1563 debugfs_remove(debugfs_afelb);
1564 if (debugfs_afelb_gain)
1565 debugfs_remove(debugfs_afelb_gain);
1566#endif
Ben Rombergerb7603232011-11-23 17:16:27 -08001567 for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
1568 if (afe_cal_addr[i] != 0)
1569 afe_cmd_memory_unmap_nowait(afe_cal_addr[i]);
1570 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001571}
1572
1573device_initcall(afe_init);
1574__exitcall(afe_exit);