blob: 9f058b9e0f2fc08f16024c01c536730194350a97 [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:
Kuirong Wanga36f2882012-04-02 19:45:26 -070080 case AFE_PORT_CMD_I2S_CONFIG:
Kiran Kandi5e809b02012-01-31 00:24:33 -080081 case AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG:
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -080082 case AFE_PORT_AUDIO_SLIM_SCH_CONFIG:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070083 case AFE_PORT_CMD_STOP:
84 case AFE_PORT_CMD_START:
85 case AFE_PORT_CMD_LOOPBACK:
86 case AFE_PORT_CMD_SIDETONE_CTL:
87 case AFE_PORT_CMD_SET_PARAM:
88 case AFE_PSEUDOPORT_CMD_START:
89 case AFE_PSEUDOPORT_CMD_STOP:
Laxminath Kasam885f5102011-07-14 10:20:21 +053090 case AFE_PORT_CMD_APPLY_GAIN:
Laxminath Kasam32657ec2011-08-01 19:26:57 +053091 case AFE_SERVICE_CMD_MEMORY_MAP:
92 case AFE_SERVICE_CMD_MEMORY_UNMAP:
93 case AFE_SERVICE_CMD_UNREG_RTPORT:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070094 atomic_set(&this_afe.state, 0);
95 wake_up(&this_afe.wait);
96 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +053097 case AFE_SERVICE_CMD_REG_RTPORT:
98 break;
99 case AFE_SERVICE_CMD_RTPORT_WR:
100 port_id = RT_PROXY_PORT_001_TX;
101 break;
102 case AFE_SERVICE_CMD_RTPORT_RD:
103 port_id = RT_PROXY_PORT_001_RX;
104 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700105 default:
106 pr_err("Unknown cmd 0x%x\n",
107 payload[0]);
108 break;
109 }
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530110 } else if (data->opcode == AFE_EVENT_RT_PROXY_PORT_STATUS) {
111 port_id = (uint16_t)(0x0000FFFF & payload[0]);
112 }
113 pr_debug("%s:port_id = %x\n", __func__, port_id);
114 switch (port_id) {
115 case RT_PROXY_PORT_001_TX: {
116 if (this_afe.tx_cb) {
117 this_afe.tx_cb(data->opcode, data->token,
118 data->payload,
119 this_afe.tx_private_data);
120 }
121 break;
122 }
123 case RT_PROXY_PORT_001_RX: {
124 if (this_afe.rx_cb) {
125 this_afe.rx_cb(data->opcode, data->token,
126 data->payload,
127 this_afe.rx_private_data);
128 }
129 break;
130 }
131 default:
132 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700133 }
134 }
135 return 0;
136}
137
Neema Shettyfeea7742011-09-11 12:30:36 -0700138int afe_get_port_type(u16 port_id)
139{
140 int ret;
141
142 switch (port_id) {
143 case PRIMARY_I2S_RX:
144 case PCM_RX:
145 case SECONDARY_I2S_RX:
146 case MI2S_RX:
147 case HDMI_RX:
148 case SLIMBUS_0_RX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800149 case SLIMBUS_1_RX:
Neema Shetty74131ac2012-05-09 13:35:26 -0700150 case SLIMBUS_3_RX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700151 case INT_BT_SCO_RX:
152 case INT_BT_A2DP_RX:
153 case INT_FM_RX:
154 case VOICE_PLAYBACK_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530155 case RT_PROXY_PORT_001_RX:
Helen Zeng8f925502012-03-05 16:50:17 -0800156 case SLIMBUS_4_RX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700157 ret = MSM_AFE_PORT_TYPE_RX;
158 break;
159
160 case PRIMARY_I2S_TX:
161 case PCM_TX:
162 case SECONDARY_I2S_TX:
163 case MI2S_TX:
164 case DIGI_MIC_TX:
165 case VOICE_RECORD_TX:
166 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800167 case SLIMBUS_1_TX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700168 case SLIMBUS_2_TX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700169 case INT_FM_TX:
170 case VOICE_RECORD_RX:
171 case INT_BT_SCO_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530172 case RT_PROXY_PORT_001_TX:
Helen Zeng8f925502012-03-05 16:50:17 -0800173 case SLIMBUS_4_TX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700174 ret = MSM_AFE_PORT_TYPE_TX;
175 break;
176
177 default:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800178 pr_err("%s: invalid port id %d\n", __func__, port_id);
Neema Shettyfeea7742011-09-11 12:30:36 -0700179 ret = -EINVAL;
180 }
181
182 return ret;
183}
184
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700185int afe_validate_port(u16 port_id)
186{
187 int ret;
188
189 switch (port_id) {
190 case PRIMARY_I2S_RX:
191 case PRIMARY_I2S_TX:
192 case PCM_RX:
193 case PCM_TX:
194 case SECONDARY_I2S_RX:
195 case SECONDARY_I2S_TX:
196 case MI2S_RX:
197 case MI2S_TX:
198 case HDMI_RX:
199 case RSVD_2:
200 case RSVD_3:
201 case DIGI_MIC_TX:
202 case VOICE_RECORD_RX:
203 case VOICE_RECORD_TX:
204 case VOICE_PLAYBACK_TX:
205 case SLIMBUS_0_RX:
206 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800207 case SLIMBUS_1_RX:
208 case SLIMBUS_1_TX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700209 case SLIMBUS_2_TX:
Neema Shetty74131ac2012-05-09 13:35:26 -0700210 case SLIMBUS_3_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700211 case INT_BT_SCO_RX:
212 case INT_BT_SCO_TX:
213 case INT_BT_A2DP_RX:
214 case INT_FM_RX:
215 case INT_FM_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530216 case RT_PROXY_PORT_001_RX:
217 case RT_PROXY_PORT_001_TX:
Helen Zeng8f925502012-03-05 16:50:17 -0800218 case SLIMBUS_4_RX:
219 case SLIMBUS_4_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700220 {
221 ret = 0;
222 break;
223 }
224
225 default:
226 ret = -EINVAL;
227 }
228
229 return ret;
230}
231
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530232int afe_convert_virtual_to_portid(u16 port_id)
233{
234 int ret;
235
236 /* if port_id is virtual, convert to physical..
237 * if port_id is already physical, return physical
238 */
239 if (afe_validate_port(port_id) < 0) {
240 if (port_id == RT_PROXY_DAI_001_RX ||
241 port_id == RT_PROXY_DAI_001_TX ||
242 port_id == RT_PROXY_DAI_002_RX ||
243 port_id == RT_PROXY_DAI_002_TX)
244 ret = VIRTUAL_ID_TO_PORTID(port_id);
245 else
246 ret = -EINVAL;
247 } else
248 ret = port_id;
249
250 return ret;
251}
252
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700253int afe_get_port_index(u16 port_id)
254{
255 switch (port_id) {
256 case PRIMARY_I2S_RX: return IDX_PRIMARY_I2S_RX;
257 case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
258 case PCM_RX: return IDX_PCM_RX;
259 case PCM_TX: return IDX_PCM_TX;
260 case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
261 case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
262 case MI2S_RX: return IDX_MI2S_RX;
263 case MI2S_TX: return IDX_MI2S_TX;
264 case HDMI_RX: return IDX_HDMI_RX;
265 case RSVD_2: return IDX_RSVD_2;
266 case RSVD_3: return IDX_RSVD_3;
267 case DIGI_MIC_TX: return IDX_DIGI_MIC_TX;
268 case VOICE_RECORD_RX: return IDX_VOICE_RECORD_RX;
269 case VOICE_RECORD_TX: return IDX_VOICE_RECORD_TX;
270 case VOICE_PLAYBACK_TX: return IDX_VOICE_PLAYBACK_TX;
271 case SLIMBUS_0_RX: return IDX_SLIMBUS_0_RX;
272 case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
Neema Shetty3c9d2862012-03-11 01:25:32 -0800273 case SLIMBUS_1_RX: return IDX_SLIMBUS_1_RX;
274 case SLIMBUS_1_TX: return IDX_SLIMBUS_1_TX;
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700275 case SLIMBUS_2_TX: return IDX_SLIMBUS_2_TX;
Neema Shetty74131ac2012-05-09 13:35:26 -0700276 case SLIMBUS_3_RX: return IDX_SLIMBUS_3_RX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700277 case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
278 case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
279 case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
280 case INT_FM_RX: return IDX_INT_FM_RX;
281 case INT_FM_TX: return IDX_INT_FM_TX;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530282 case RT_PROXY_PORT_001_RX: return IDX_RT_PROXY_PORT_001_RX;
283 case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
Helen Zeng8f925502012-03-05 16:50:17 -0800284 case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX;
285 case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700286
287 default: return -EINVAL;
288 }
289}
290
291int afe_sizeof_cfg_cmd(u16 port_id)
292{
293 int ret_size;
294 switch (port_id) {
295 case PRIMARY_I2S_RX:
296 case PRIMARY_I2S_TX:
297 case SECONDARY_I2S_RX:
298 case SECONDARY_I2S_TX:
299 case MI2S_RX:
300 case MI2S_TX:
301 ret_size = SIZEOF_CFG_CMD(afe_port_mi2s_cfg);
302 break;
303 case HDMI_RX:
Kiran Kandi5e809b02012-01-31 00:24:33 -0800304 ret_size = SIZEOF_CFG_CMD(afe_port_hdmi_multi_ch_cfg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700305 break;
306 case SLIMBUS_0_RX:
307 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800308 case SLIMBUS_1_RX:
309 case SLIMBUS_1_TX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700310 case SLIMBUS_2_TX:
Neema Shetty74131ac2012-05-09 13:35:26 -0700311 case SLIMBUS_3_RX:
Helen Zeng8f925502012-03-05 16:50:17 -0800312 case SLIMBUS_4_RX:
313 case SLIMBUS_4_TX:
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800314 ret_size = SIZEOF_CFG_CMD(afe_port_slimbus_sch_cfg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700315 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530316 case RT_PROXY_PORT_001_RX:
317 case RT_PROXY_PORT_001_TX:
318 ret_size = SIZEOF_CFG_CMD(afe_port_rtproxy_cfg);
319 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700320 case PCM_RX:
321 case PCM_TX:
322 default:
323 ret_size = SIZEOF_CFG_CMD(afe_port_pcm_cfg);
324 break;
325 }
326 return ret_size;
327}
328
Jay Wang6a305432011-08-05 16:01:54 -0700329int afe_q6_interface_prepare(void)
330{
331 int ret = 0;
332
333 pr_debug("%s:", __func__);
334
335 if (this_afe.apr == NULL) {
336 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
337 0xFFFFFFFF, &this_afe);
338 pr_debug("%s: Register AFE\n", __func__);
339 if (this_afe.apr == NULL) {
340 pr_err("%s: Unable to register AFE\n", __func__);
341 ret = -ENODEV;
342 }
343 }
344 return ret;
345}
346
Ben Rombergerb7603232011-11-23 17:16:27 -0800347static void afe_send_cal_block(int32_t path, u16 port_id)
348{
349 int result = 0;
350 struct acdb_cal_block cal_block;
351 struct afe_port_cmd_set_param_no_payload afe_cal;
352 pr_debug("%s: path %d\n", __func__, path);
353
354 get_afe_cal(path, &cal_block);
355 if (cal_block.cal_size <= 0) {
356 pr_debug("%s: No AFE cal to send!\n", __func__);
357 goto done;
358 }
359
Ben Romberger9e792562012-02-24 12:29:01 -0800360 if ((afe_cal_addr[path].cal_paddr != cal_block.cal_paddr) ||
361 (cal_block.cal_size > afe_cal_addr[path].cal_size)) {
362 if (afe_cal_addr[path].cal_paddr != 0)
363 afe_cmd_memory_unmap_nowait(
364 afe_cal_addr[path].cal_paddr);
365
Ben Rombergerb7603232011-11-23 17:16:27 -0800366 afe_cmd_memory_map_nowait(cal_block.cal_paddr,
367 cal_block.cal_size);
Ben Romberger9e792562012-02-24 12:29:01 -0800368 afe_cal_addr[path].cal_paddr = cal_block.cal_paddr;
369 afe_cal_addr[path].cal_size = cal_block.cal_size;
Ben Rombergerb7603232011-11-23 17:16:27 -0800370 }
371
372 afe_cal.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
373 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
374 afe_cal.hdr.pkt_size = sizeof(afe_cal);
375 afe_cal.hdr.src_port = 0;
376 afe_cal.hdr.dest_port = 0;
377 afe_cal.hdr.token = 0;
378 afe_cal.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
379 afe_cal.port_id = port_id;
380 afe_cal.payload_size = cal_block.cal_size;
381 afe_cal.payload_address = cal_block.cal_paddr;
382
383 pr_debug("%s: AFE cal sent for device port = %d, path = %d, "
384 "cal size = %d, cal addr = 0x%x\n", __func__,
385 port_id, path, cal_block.cal_size, cal_block.cal_paddr);
386
387 result = apr_send_pkt(this_afe.apr, (uint32_t *) &afe_cal);
388 if (result < 0) {
389 pr_err("%s: AFE cal for port %d failed\n",
390 __func__, port_id);
391 }
392
393 pr_debug("%s: AFE cal sent for path %d device!\n", __func__, path);
394done:
395 return;
396}
397
398void afe_send_cal(u16 port_id)
399{
400 pr_debug("%s\n", __func__);
401
402 if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX)
403 afe_send_cal_block(TX_CAL, port_id);
404 else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX)
405 afe_send_cal_block(RX_CAL, port_id);
406}
407
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700408int afe_port_start_nowait(u16 port_id, union afe_port_config *afe_config,
409 u32 rate) /* This function is no blocking */
410{
411 struct afe_port_start_command start;
412 struct afe_audioif_config_command config;
413 int ret;
414
415 if (!afe_config) {
416 pr_err("%s: Error, no configuration data\n", __func__);
417 ret = -EINVAL;
418 return ret;
419 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -0800420 pr_debug("%s: %d %d\n", __func__, port_id, rate);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700421
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530422 if ((port_id == RT_PROXY_DAI_001_RX) ||
423 (port_id == RT_PROXY_DAI_002_TX))
424 return -EINVAL;
425 if ((port_id == RT_PROXY_DAI_002_RX) ||
426 (port_id == RT_PROXY_DAI_001_TX))
427 port_id = VIRTUAL_ID_TO_PORTID(port_id);
428
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700429 if (this_afe.apr == NULL) {
Jay Wang6a305432011-08-05 16:01:54 -0700430 pr_err("%s: AFE APR is not registered\n", __func__);
431 ret = -ENODEV;
432 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700433 }
Kiran Kandi5e809b02012-01-31 00:24:33 -0800434
435 if (port_id == HDMI_RX) {
436 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700437 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
Kiran Kandi5e809b02012-01-31 00:24:33 -0800438 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
439 config.hdr.src_port = 0;
440 config.hdr.dest_port = 0;
441 config.hdr.token = 0;
442 config.hdr.opcode = AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG;
443 } else {
444
445 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
446 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
447 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
448 config.hdr.src_port = 0;
449 config.hdr.dest_port = 0;
450 config.hdr.token = 0;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800451 switch (port_id) {
452 case SLIMBUS_0_RX:
453 case SLIMBUS_0_TX:
454 case SLIMBUS_1_RX:
455 case SLIMBUS_1_TX:
456 case SLIMBUS_2_RX:
457 case SLIMBUS_2_TX:
458 case SLIMBUS_3_RX:
459 case SLIMBUS_3_TX:
460 case SLIMBUS_4_RX:
461 case SLIMBUS_4_TX:
462 config.hdr.opcode = AFE_PORT_AUDIO_SLIM_SCH_CONFIG;
463 break;
Kuirong Wanga36f2882012-04-02 19:45:26 -0700464 case MI2S_TX:
465 case MI2S_RX:
466 case SECONDARY_I2S_RX:
467 case SECONDARY_I2S_TX:
468 case PRIMARY_I2S_RX:
469 case PRIMARY_I2S_TX:
470 /* AFE_PORT_CMD_I2S_CONFIG command is not supported
471 * in the LPASS EL 1.0. So we have to distiguish
472 * which AFE command, AFE_PORT_CMD_I2S_CONFIG or
473 * AFE_PORT_AUDIO_IF_CONFIG to use. If the format
474 * is L-PCM, the AFE_PORT_AUDIO_IF_CONFIG is used
475 * to make the backward compatible.
476 */
477 pr_debug("%s: afe_config->mi2s.format = %d\n", __func__,
478 afe_config->mi2s.format);
479 if (afe_config->mi2s.format == MSM_AFE_I2S_FORMAT_LPCM)
480 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
481 else
482 config.hdr.opcode = AFE_PORT_CMD_I2S_CONFIG;
483 break;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800484 default:
485 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
486 break;
487 }
Kiran Kandi5e809b02012-01-31 00:24:33 -0800488 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700489
490 if (afe_validate_port(port_id) < 0) {
491
492 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
493 port_id);
494 ret = -EINVAL;
495 goto fail_cmd;
496 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700497 config.port_id = port_id;
498 config.port = *afe_config;
499
500 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
501 if (ret < 0) {
502 pr_err("%s: AFE enable for port %d failed\n", __func__,
503 port_id);
504 ret = -EINVAL;
505 goto fail_cmd;
506 }
Ben Rombergerb7603232011-11-23 17:16:27 -0800507
508 /* send AFE cal */
509 afe_send_cal(port_id);
510
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700511 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
512 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
513 start.hdr.pkt_size = sizeof(start);
514 start.hdr.src_port = 0;
515 start.hdr.dest_port = 0;
516 start.hdr.token = 0;
517 start.hdr.opcode = AFE_PORT_CMD_START;
518 start.port_id = port_id;
519 start.gain = 0x2000;
520 start.sample_rate = rate;
521
522 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
523
524 if (IS_ERR_VALUE(ret)) {
525 pr_err("%s: AFE enable for port %d failed\n", __func__,
526 port_id);
527 ret = -EINVAL;
528 goto fail_cmd;
529 }
530
531 if (this_afe.task != current)
532 this_afe.task = current;
533
534 pr_debug("task_name = %s pid = %d\n",
535 this_afe.task->comm, this_afe.task->pid);
536 return 0;
537
538fail_cmd:
539 return ret;
540}
541
542int afe_open(u16 port_id, union afe_port_config *afe_config, int rate)
543{
544 struct afe_port_start_command start;
545 struct afe_audioif_config_command config;
546 int ret = 0;
547
548 if (!afe_config) {
549 pr_err("%s: Error, no configuration data\n", __func__);
550 ret = -EINVAL;
551 return ret;
552 }
553
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800554 pr_debug("%s: %d %d\n", __func__, port_id, rate);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700555
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530556 if ((port_id == RT_PROXY_DAI_001_RX) ||
557 (port_id == RT_PROXY_DAI_002_TX))
558 return -EINVAL;
559 if ((port_id == RT_PROXY_DAI_002_RX) ||
560 (port_id == RT_PROXY_DAI_001_TX))
561 port_id = VIRTUAL_ID_TO_PORTID(port_id);
562
Jay Wang6a305432011-08-05 16:01:54 -0700563 ret = afe_q6_interface_prepare();
564 if (ret != 0)
565 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700566
567 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
568 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
569 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
570 config.hdr.src_port = 0;
571 config.hdr.dest_port = 0;
572 config.hdr.token = 0;
Kuirong Wanga36f2882012-04-02 19:45:26 -0700573 switch (port_id) {
574 case SLIMBUS_0_RX:
575 case SLIMBUS_0_TX:
576 case SLIMBUS_1_RX:
577 case SLIMBUS_1_TX:
578 case SLIMBUS_2_RX:
579 case SLIMBUS_2_TX:
580 case SLIMBUS_3_RX:
581 case SLIMBUS_3_TX:
582 case SLIMBUS_4_RX:
583 case SLIMBUS_4_TX:
584 config.hdr.opcode = AFE_PORT_AUDIO_SLIM_SCH_CONFIG;
585 break;
586 case MI2S_TX:
587 case MI2S_RX:
588 case SECONDARY_I2S_RX:
589 case SECONDARY_I2S_TX:
590 case PRIMARY_I2S_RX:
591 case PRIMARY_I2S_TX:
592 /* AFE_PORT_CMD_I2S_CONFIG command is not supported
593 * in the LPASS EL 1.0. So we have to distiguish
594 * which AFE command, AFE_PORT_CMD_I2S_CONFIG or
595 * AFE_PORT_AUDIO_IF_CONFIG to use. If the format
596 * is L-PCM, the AFE_PORT_AUDIO_IF_CONFIG is used
597 * to make the backward compatible.
598 */
599 pr_debug("%s: afe_config->mi2s.format = %d\n", __func__,
600 afe_config->mi2s.format);
601 if (afe_config->mi2s.format == MSM_AFE_I2S_FORMAT_LPCM)
602 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
603 else
604 config.hdr.opcode = AFE_PORT_CMD_I2S_CONFIG;
605 break;
606 default:
607 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
608 break;
609 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700610
611 if (afe_validate_port(port_id) < 0) {
612
613 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
614 port_id);
615 ret = -EINVAL;
616 goto fail_cmd;
617 }
618
619 config.port_id = port_id;
620 config.port = *afe_config;
621
622 atomic_set(&this_afe.state, 1);
623 atomic_set(&this_afe.status, 0);
624 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
625 if (ret < 0) {
626 pr_err("%s: AFE enable for port %d failed\n", __func__,
627 port_id);
628 ret = -EINVAL;
629 goto fail_cmd;
630 }
631
632 ret = wait_event_timeout(this_afe.wait,
633 (atomic_read(&this_afe.state) == 0),
634 msecs_to_jiffies(TIMEOUT_MS));
635 if (!ret) {
636 pr_err("%s: wait_event timeout\n", __func__);
637 ret = -EINVAL;
638 goto fail_cmd;
639 }
640 if (atomic_read(&this_afe.status) != 0) {
641 pr_err("%s: config cmd failed\n", __func__);
642 ret = -EINVAL;
643 goto fail_cmd;
644 }
645 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
646 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
647 start.hdr.pkt_size = sizeof(start);
648 start.hdr.src_port = 0;
649 start.hdr.dest_port = 0;
650 start.hdr.token = 0;
651 start.hdr.opcode = AFE_PORT_CMD_START;
652 start.port_id = port_id;
653 start.gain = 0x2000;
654 start.sample_rate = rate;
655
656 atomic_set(&this_afe.state, 1);
657 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
658 if (ret < 0) {
659 pr_err("%s: AFE enable for port %d failed\n", __func__,
660 port_id);
661 ret = -EINVAL;
662 goto fail_cmd;
663 }
664 ret = wait_event_timeout(this_afe.wait,
665 (atomic_read(&this_afe.state) == 0),
666 msecs_to_jiffies(TIMEOUT_MS));
667 if (!ret) {
668 pr_err("%s: wait_event timeout\n", __func__);
669 ret = -EINVAL;
670 goto fail_cmd;
671 }
672
673 if (this_afe.task != current)
674 this_afe.task = current;
675
676 pr_debug("task_name = %s pid = %d\n",
677 this_afe.task->comm, this_afe.task->pid);
678 return 0;
679fail_cmd:
680 return ret;
681}
682
Neema Shetty74131ac2012-05-09 13:35:26 -0700683int afe_loopback(u16 enable, u16 dst_port, u16 src_port)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700684{
685 struct afe_loopback_command lb_cmd;
686 int ret = 0;
Jay Wang6a305432011-08-05 16:01:54 -0700687
688 ret = afe_q6_interface_prepare();
689 if (ret != 0)
690 return ret;
691
Neema Shetty74131ac2012-05-09 13:35:26 -0700692 if ((afe_get_port_type(dst_port) == MSM_AFE_PORT_TYPE_RX) &&
693 (afe_get_port_type(src_port) == MSM_AFE_PORT_TYPE_RX))
694 return afe_loopback_cfg(enable, dst_port, src_port,
695 LB_MODE_EC_REF_VOICE_AUDIO);
696
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700697 lb_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
698 APR_HDR_LEN(20), APR_PKT_VER);
699 lb_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
700 sizeof(lb_cmd) - APR_HDR_SIZE);
701 lb_cmd.hdr.src_port = 0;
702 lb_cmd.hdr.dest_port = 0;
703 lb_cmd.hdr.token = 0;
704 lb_cmd.hdr.opcode = AFE_PORT_CMD_LOOPBACK;
Neema Shetty74131ac2012-05-09 13:35:26 -0700705 lb_cmd.tx_port_id = src_port;
706 lb_cmd.rx_port_id = dst_port;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700707 lb_cmd.mode = 0xFFFF;
708 lb_cmd.enable = (enable ? 1 : 0);
709 atomic_set(&this_afe.state, 1);
710
711 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &lb_cmd);
712 if (ret < 0) {
713 pr_err("%s: AFE loopback failed\n", __func__);
714 ret = -EINVAL;
715 goto done;
716 }
717 ret = wait_event_timeout(this_afe.wait,
718 (atomic_read(&this_afe.state) == 0),
719 msecs_to_jiffies(TIMEOUT_MS));
720 if (!ret) {
721 pr_err("%s: wait_event timeout\n", __func__);
722 ret = -EINVAL;
723 }
724done:
725 return ret;
726}
727
Neema Shetty74131ac2012-05-09 13:35:26 -0700728int afe_loopback_cfg(u16 enable, u16 dst_port, u16 src_port, u16 mode)
729{
730 struct afe_port_cmd_set_param lp_cfg;
731 int ret = 0;
732
733 ret = afe_q6_interface_prepare();
734 if (ret != 0)
735 return ret;
736
737 pr_debug("%s: src_port %d, dst_port %d\n",
738 __func__, src_port, dst_port);
739
740 lp_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
741 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
742 lp_cfg.hdr.pkt_size = sizeof(lp_cfg);
743 lp_cfg.hdr.src_port = 0;
744 lp_cfg.hdr.dest_port = 0;
745 lp_cfg.hdr.token = 0;
746 lp_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
747
748 lp_cfg.port_id = src_port;
749 lp_cfg.payload_size = sizeof(struct afe_param_payload);
750 lp_cfg.payload_address = 0;
751
752 lp_cfg.payload.module_id = AFE_MODULE_LOOPBACK;
753 lp_cfg.payload.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
754 lp_cfg.payload.param_size = sizeof(struct afe_param_loopback_cfg);
755 lp_cfg.payload.reserved = 0;
756
757 lp_cfg.payload.param.loopback_cfg.loopback_cfg_minor_version =
758 AFE_API_VERSION_LOOPBACK_CONFIG;
759 lp_cfg.payload.param.loopback_cfg.dst_port_id = dst_port;
760 lp_cfg.payload.param.loopback_cfg.routing_mode = mode;
761 lp_cfg.payload.param.loopback_cfg.enable = enable;
762 lp_cfg.payload.param.loopback_cfg.reserved = 0;
763
764 atomic_set(&this_afe.state, 1);
765 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &lp_cfg);
766 if (ret < 0) {
767 pr_err("%s: AFE loopback config failed for src_port %d, dst_port %d\n",
768 __func__, src_port, dst_port);
769 ret = -EINVAL;
770 goto fail_cmd;
771 }
772
773 ret = wait_event_timeout(this_afe.wait,
774 (atomic_read(&this_afe.state) == 0),
775 msecs_to_jiffies(TIMEOUT_MS));
776 if (ret < 0) {
777 pr_err("%s: wait_event timeout\n", __func__);
778 ret = -EINVAL;
779 goto fail_cmd;
780 }
781 return 0;
782fail_cmd:
783 return ret;
784}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700785
786int afe_loopback_gain(u16 port_id, u16 volume)
787{
788 struct afe_port_cmd_set_param set_param;
789 int ret = 0;
790
791 if (this_afe.apr == NULL) {
Jayasena Sangaraboina82435032011-07-26 15:23:00 -0700792 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
793 0xFFFFFFFF, &this_afe);
794 pr_debug("%s: Register AFE\n", __func__);
795 if (this_afe.apr == NULL) {
796 pr_err("%s: Unable to register AFE\n", __func__);
797 ret = -ENODEV;
798 return ret;
799 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700800 }
801
802 if (afe_validate_port(port_id) < 0) {
803
804 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
805 port_id);
806 ret = -EINVAL;
807 goto fail_cmd;
808 }
809
810 /* RX ports numbers are even .TX ports numbers are odd. */
811 if (port_id % 2 == 0) {
812 pr_err("%s: Failed : afe loopback gain only for TX ports."
813 " port_id %d\n", __func__, port_id);
814 ret = -EINVAL;
815 goto fail_cmd;
816 }
817
818 pr_debug("%s: %d %hX\n", __func__, port_id, volume);
819
820 set_param.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
821 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
822 set_param.hdr.pkt_size = sizeof(set_param);
823 set_param.hdr.src_port = 0;
824 set_param.hdr.dest_port = 0;
825 set_param.hdr.token = 0;
826 set_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
827
828 set_param.port_id = port_id;
829 set_param.payload_size = sizeof(struct afe_param_payload);
830 set_param.payload_address = 0;
831
832 set_param.payload.module_id = AFE_MODULE_ID_PORT_INFO;
833 set_param.payload.param_id = AFE_PARAM_ID_LOOPBACK_GAIN;
834 set_param.payload.param_size = sizeof(struct afe_param_loopback_gain);
835 set_param.payload.reserved = 0;
836
837 set_param.payload.param.loopback_gain.gain = volume;
838 set_param.payload.param.loopback_gain.reserved = 0;
839
840 atomic_set(&this_afe.state, 1);
841 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_param);
842 if (ret < 0) {
843 pr_err("%s: AFE param set failed for port %d\n",
844 __func__, port_id);
845 ret = -EINVAL;
846 goto fail_cmd;
847 }
848
849 ret = wait_event_timeout(this_afe.wait,
850 (atomic_read(&this_afe.state) == 0),
851 msecs_to_jiffies(TIMEOUT_MS));
852 if (ret < 0) {
853 pr_err("%s: wait_event timeout\n", __func__);
854 ret = -EINVAL;
855 goto fail_cmd;
856 }
857 return 0;
858fail_cmd:
859 return ret;
860}
861
Laxminath Kasam885f5102011-07-14 10:20:21 +0530862int afe_apply_gain(u16 port_id, u16 gain)
863{
864 struct afe_port_gain_command set_gain;
865 int ret = 0;
866
867 if (this_afe.apr == NULL) {
868 pr_err("%s: AFE is not opened\n", __func__);
869 ret = -EPERM;
870 goto fail_cmd;
871 }
872
873 if (afe_validate_port(port_id) < 0) {
874 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
875 port_id);
876 ret = -EINVAL;
877 goto fail_cmd;
878 }
879
880 /* RX ports numbers are even .TX ports numbers are odd. */
881 if (port_id % 2 == 0) {
882 pr_err("%s: Failed : afe apply gain only for TX ports."
883 " port_id %d\n", __func__, port_id);
884 ret = -EINVAL;
885 goto fail_cmd;
886 }
887
888 pr_debug("%s: %d %hX\n", __func__, port_id, gain);
889
890 set_gain.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
891 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
892 set_gain.hdr.pkt_size = sizeof(set_gain);
893 set_gain.hdr.src_port = 0;
894 set_gain.hdr.dest_port = 0;
895 set_gain.hdr.token = 0;
896 set_gain.hdr.opcode = AFE_PORT_CMD_APPLY_GAIN;
897
898 set_gain.port_id = port_id;
899 set_gain.gain = gain;
900
901 atomic_set(&this_afe.state, 1);
902 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_gain);
903 if (ret < 0) {
904 pr_err("%s: AFE Gain set failed for port %d\n",
905 __func__, port_id);
906 ret = -EINVAL;
907 goto fail_cmd;
908 }
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 < 0) {
914 pr_err("%s: wait_event timeout\n", __func__);
915 ret = -EINVAL;
916 goto fail_cmd;
917 }
918 return 0;
919fail_cmd:
920 return ret;
921}
Helen Zeng0705a5f2011-10-14 15:29:52 -0700922
923int afe_pseudo_port_start_nowait(u16 port_id)
924{
925 int ret = 0;
926 struct afe_pseudoport_start_command start;
927
928 pr_debug("%s: port_id=%d\n", __func__, port_id);
929 if (this_afe.apr == NULL) {
930 pr_err("%s: AFE APR is not registered\n", __func__);
931 return -ENODEV;
932 }
933
934
935 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
936 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
937 start.hdr.pkt_size = sizeof(start);
938 start.hdr.src_port = 0;
939 start.hdr.dest_port = 0;
940 start.hdr.token = 0;
941 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
942 start.port_id = port_id;
943 start.timing = 1;
944
945 atomic_set(&this_afe.state, 1);
946 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
947 if (ret < 0) {
948 pr_err("%s: AFE enable for port %d failed %d\n",
949 __func__, port_id, ret);
950 return -EINVAL;
951 }
952 return 0;
953}
954
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700955int afe_start_pseudo_port(u16 port_id)
956{
957 int ret = 0;
958 struct afe_pseudoport_start_command start;
959
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800960 pr_debug("%s: port_id=%d\n", __func__, port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700961
Jay Wang6a305432011-08-05 16:01:54 -0700962 ret = afe_q6_interface_prepare();
963 if (ret != 0)
964 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700965
966 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
967 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
968 start.hdr.pkt_size = sizeof(start);
969 start.hdr.src_port = 0;
970 start.hdr.dest_port = 0;
971 start.hdr.token = 0;
972 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
973 start.port_id = port_id;
974 start.timing = 1;
975
976 atomic_set(&this_afe.state, 1);
977 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
978 if (ret < 0) {
979 pr_err("%s: AFE enable for port %d failed %d\n",
980 __func__, port_id, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700981 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700982 }
983
984 ret = wait_event_timeout(this_afe.wait,
985 (atomic_read(&this_afe.state) == 0),
986 msecs_to_jiffies(TIMEOUT_MS));
987 if (!ret) {
988 pr_err("%s: wait_event timeout\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700989 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700990 }
991
992 return 0;
993}
994
Helen Zeng0705a5f2011-10-14 15:29:52 -0700995int afe_pseudo_port_stop_nowait(u16 port_id)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700996{
997 int ret = 0;
998 struct afe_pseudoport_stop_command stop;
999
Helen Zeng0705a5f2011-10-14 15:29:52 -07001000 pr_debug("%s: port_id=%d\n", __func__, port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001001
1002 if (this_afe.apr == NULL) {
1003 pr_err("%s: AFE is already closed\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001004 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001005 }
1006
1007 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1008 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1009 stop.hdr.pkt_size = sizeof(stop);
1010 stop.hdr.src_port = 0;
1011 stop.hdr.dest_port = 0;
1012 stop.hdr.token = 0;
1013 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
1014 stop.port_id = port_id;
1015 stop.reserved = 0;
1016
1017 atomic_set(&this_afe.state, 1);
1018 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1019 if (ret < 0) {
1020 pr_err("%s: AFE close failed %d\n", __func__, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001021 return -EINVAL;
1022 }
1023
1024 return 0;
1025
1026}
1027
1028int afe_stop_pseudo_port(u16 port_id)
1029{
1030 int ret = 0;
1031 struct afe_pseudoport_stop_command stop;
1032
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001033 pr_debug("%s: port_id=%d\n", __func__, port_id);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001034
1035 if (this_afe.apr == NULL) {
1036 pr_err("%s: AFE is already closed\n", __func__);
1037 return -EINVAL;
1038 }
1039
1040 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1041 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1042 stop.hdr.pkt_size = sizeof(stop);
1043 stop.hdr.src_port = 0;
1044 stop.hdr.dest_port = 0;
1045 stop.hdr.token = 0;
1046 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
1047 stop.port_id = port_id;
1048 stop.reserved = 0;
1049
1050 atomic_set(&this_afe.state, 1);
1051 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1052 if (ret < 0) {
1053 pr_err("%s: AFE close failed %d\n", __func__, ret);
1054 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001055 }
1056
1057 ret = wait_event_timeout(this_afe.wait,
1058 (atomic_read(&this_afe.state) == 0),
1059 msecs_to_jiffies(TIMEOUT_MS));
1060 if (!ret) {
1061 pr_err("%s: wait_event timeout\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001062 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001063 }
1064
1065 return 0;
1066}
1067
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301068int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz)
1069{
1070 int ret = 0;
1071 struct afe_cmd_memory_map mregion;
1072
1073 pr_debug("%s:\n", __func__);
1074
1075 if (this_afe.apr == NULL) {
1076 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1077 0xFFFFFFFF, &this_afe);
1078 pr_debug("%s: Register AFE\n", __func__);
1079 if (this_afe.apr == NULL) {
1080 pr_err("%s: Unable to register AFE\n", __func__);
1081 ret = -ENODEV;
1082 return ret;
1083 }
1084 }
1085
1086 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1087 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1088 mregion.hdr.pkt_size = sizeof(mregion);
1089 mregion.hdr.src_port = 0;
1090 mregion.hdr.dest_port = 0;
1091 mregion.hdr.token = 0;
1092 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
1093 mregion.phy_addr = dma_addr_p;
1094 mregion.mem_sz = dma_buf_sz;
1095 mregion.mem_id = 0;
1096 mregion.rsvd = 0;
1097
1098 atomic_set(&this_afe.state, 1);
1099 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1100 if (ret < 0) {
1101 pr_err("%s: AFE memory map cmd failed %d\n",
1102 __func__, ret);
1103 ret = -EINVAL;
1104 return ret;
1105 }
1106
1107 ret = wait_event_timeout(this_afe.wait,
1108 (atomic_read(&this_afe.state) == 0),
1109 msecs_to_jiffies(TIMEOUT_MS));
1110 if (!ret) {
1111 pr_err("%s: wait_event timeout\n", __func__);
1112 ret = -EINVAL;
1113 return ret;
1114 }
1115
1116 return 0;
1117}
1118
Ben Rombergerb7603232011-11-23 17:16:27 -08001119int afe_cmd_memory_map_nowait(u32 dma_addr_p, u32 dma_buf_sz)
1120{
1121 int ret = 0;
1122 struct afe_cmd_memory_map mregion;
1123
1124 pr_debug("%s:\n", __func__);
1125
1126 if (this_afe.apr == NULL) {
1127 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1128 0xFFFFFFFF, &this_afe);
1129 pr_debug("%s: Register AFE\n", __func__);
1130 if (this_afe.apr == NULL) {
1131 pr_err("%s: Unable to register AFE\n", __func__);
1132 ret = -ENODEV;
1133 return ret;
1134 }
1135 }
1136
1137 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1138 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1139 mregion.hdr.pkt_size = sizeof(mregion);
1140 mregion.hdr.src_port = 0;
1141 mregion.hdr.dest_port = 0;
1142 mregion.hdr.token = 0;
1143 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
1144 mregion.phy_addr = dma_addr_p;
1145 mregion.mem_sz = dma_buf_sz;
1146 mregion.mem_id = 0;
1147 mregion.rsvd = 0;
1148
1149 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1150 if (ret < 0) {
1151 pr_err("%s: AFE memory map cmd failed %d\n",
1152 __func__, ret);
1153 ret = -EINVAL;
1154 }
1155 return 0;
1156}
1157
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301158int afe_cmd_memory_unmap(u32 dma_addr_p)
1159{
1160 int ret = 0;
1161 struct afe_cmd_memory_unmap mregion;
1162
1163 pr_debug("%s:\n", __func__);
1164
1165 if (this_afe.apr == NULL) {
1166 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1167 0xFFFFFFFF, &this_afe);
1168 pr_debug("%s: Register AFE\n", __func__);
1169 if (this_afe.apr == NULL) {
1170 pr_err("%s: Unable to register AFE\n", __func__);
1171 ret = -ENODEV;
1172 return ret;
1173 }
1174 }
1175
1176 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1177 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1178 mregion.hdr.pkt_size = sizeof(mregion);
1179 mregion.hdr.src_port = 0;
1180 mregion.hdr.dest_port = 0;
1181 mregion.hdr.token = 0;
1182 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
1183 mregion.phy_addr = dma_addr_p;
1184
1185 atomic_set(&this_afe.state, 1);
1186 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1187 if (ret < 0) {
Ben Rombergerb7603232011-11-23 17:16:27 -08001188 pr_err("%s: AFE memory unmap cmd failed %d\n",
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301189 __func__, ret);
1190 ret = -EINVAL;
1191 return ret;
1192 }
1193
1194 ret = wait_event_timeout(this_afe.wait,
1195 (atomic_read(&this_afe.state) == 0),
1196 msecs_to_jiffies(TIMEOUT_MS));
1197 if (!ret) {
1198 pr_err("%s: wait_event timeout\n", __func__);
1199 ret = -EINVAL;
1200 return ret;
1201 }
Ben Rombergerb7603232011-11-23 17:16:27 -08001202 return 0;
1203}
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301204
Ben Rombergerb7603232011-11-23 17:16:27 -08001205int afe_cmd_memory_unmap_nowait(u32 dma_addr_p)
1206{
1207 int ret = 0;
1208 struct afe_cmd_memory_unmap mregion;
1209
1210 pr_debug("%s:\n", __func__);
1211
1212 if (this_afe.apr == NULL) {
1213 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1214 0xFFFFFFFF, &this_afe);
1215 pr_debug("%s: Register AFE\n", __func__);
1216 if (this_afe.apr == NULL) {
1217 pr_err("%s: Unable to register AFE\n", __func__);
1218 ret = -ENODEV;
1219 return ret;
1220 }
1221 }
1222
1223 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1224 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1225 mregion.hdr.pkt_size = sizeof(mregion);
1226 mregion.hdr.src_port = 0;
1227 mregion.hdr.dest_port = 0;
1228 mregion.hdr.token = 0;
1229 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
1230 mregion.phy_addr = dma_addr_p;
1231
1232 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1233 if (ret < 0) {
1234 pr_err("%s: AFE memory unmap cmd failed %d\n",
1235 __func__, ret);
1236 ret = -EINVAL;
1237 }
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301238 return 0;
1239}
1240
1241int afe_register_get_events(u16 port_id,
1242 void (*cb) (uint32_t opcode,
1243 uint32_t token, uint32_t *payload, void *priv),
1244 void *private_data)
1245{
1246 int ret = 0;
1247 struct afe_cmd_reg_rtport rtproxy;
1248
1249 pr_debug("%s:\n", __func__);
1250
1251 if (this_afe.apr == NULL) {
1252 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1253 0xFFFFFFFF, &this_afe);
1254 pr_debug("%s: Register AFE\n", __func__);
1255 if (this_afe.apr == NULL) {
1256 pr_err("%s: Unable to register AFE\n", __func__);
1257 ret = -ENODEV;
1258 return ret;
1259 }
1260 }
1261 if ((port_id == RT_PROXY_DAI_002_RX) ||
1262 (port_id == RT_PROXY_DAI_001_TX))
1263 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1264 else
1265 return -EINVAL;
1266
1267 if (port_id == RT_PROXY_PORT_001_TX) {
1268 this_afe.tx_cb = cb;
1269 this_afe.tx_private_data = private_data;
1270 } else if (port_id == RT_PROXY_PORT_001_RX) {
1271 this_afe.rx_cb = cb;
1272 this_afe.rx_private_data = private_data;
1273 }
1274
1275 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1276 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1277 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1278 rtproxy.hdr.src_port = 1;
1279 rtproxy.hdr.dest_port = 1;
1280 rtproxy.hdr.token = 0;
1281 rtproxy.hdr.opcode = AFE_SERVICE_CMD_REG_RTPORT;
1282 rtproxy.port_id = port_id;
1283 rtproxy.rsvd = 0;
1284
1285 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1286 if (ret < 0) {
1287 pr_err("%s: AFE reg. rtproxy_event failed %d\n",
1288 __func__, ret);
1289 ret = -EINVAL;
1290 return ret;
1291 }
1292 return 0;
1293}
1294
1295int afe_unregister_get_events(u16 port_id)
1296{
1297 int ret = 0;
1298 struct afe_cmd_unreg_rtport rtproxy;
1299
1300 pr_debug("%s:\n", __func__);
1301
1302 if (this_afe.apr == NULL) {
1303 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1304 0xFFFFFFFF, &this_afe);
1305 pr_debug("%s: Register AFE\n", __func__);
1306 if (this_afe.apr == NULL) {
1307 pr_err("%s: Unable to register AFE\n", __func__);
1308 ret = -ENODEV;
1309 return ret;
1310 }
1311 }
1312 if ((port_id == RT_PROXY_DAI_002_RX) ||
1313 (port_id == RT_PROXY_DAI_001_TX))
1314 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1315 else
1316 return -EINVAL;
1317
1318 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1319 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1320 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1321 rtproxy.hdr.src_port = 0;
1322 rtproxy.hdr.dest_port = 0;
1323 rtproxy.hdr.token = 0;
1324 rtproxy.hdr.opcode = AFE_SERVICE_CMD_UNREG_RTPORT;
1325 rtproxy.port_id = port_id;
1326 rtproxy.rsvd = 0;
1327
1328 if (port_id == RT_PROXY_PORT_001_TX) {
1329 this_afe.tx_cb = NULL;
1330 this_afe.tx_private_data = NULL;
1331 } else if (port_id == RT_PROXY_PORT_001_RX) {
1332 this_afe.rx_cb = NULL;
1333 this_afe.rx_private_data = NULL;
1334 }
1335
1336 atomic_set(&this_afe.state, 1);
1337 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1338 if (ret < 0) {
1339 pr_err("%s: AFE enable Unreg. rtproxy_event failed %d\n",
1340 __func__, ret);
1341 ret = -EINVAL;
1342 return ret;
1343 }
1344
1345 ret = wait_event_timeout(this_afe.wait,
1346 (atomic_read(&this_afe.state) == 0),
1347 msecs_to_jiffies(TIMEOUT_MS));
1348 if (!ret) {
1349 pr_err("%s: wait_event timeout\n", __func__);
1350 ret = -EINVAL;
1351 return ret;
1352 }
1353 return 0;
1354}
1355
1356int afe_rt_proxy_port_write(u32 buf_addr_p, int bytes)
1357{
1358 int ret = 0;
1359 struct afe_cmd_rtport_wr afecmd_wr;
1360
1361 if (this_afe.apr == NULL) {
1362 pr_err("%s:register to AFE is not done\n", __func__);
1363 ret = -ENODEV;
1364 return ret;
1365 }
1366 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1367 buf_addr_p, bytes);
1368
1369 afecmd_wr.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1370 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1371 afecmd_wr.hdr.pkt_size = sizeof(afecmd_wr);
1372 afecmd_wr.hdr.src_port = 0;
1373 afecmd_wr.hdr.dest_port = 0;
1374 afecmd_wr.hdr.token = 0;
1375 afecmd_wr.hdr.opcode = AFE_SERVICE_CMD_RTPORT_WR;
1376 afecmd_wr.buf_addr = (uint32_t)buf_addr_p;
1377 afecmd_wr.port_id = RT_PROXY_PORT_001_TX;
1378 afecmd_wr.bytes_avail = bytes;
1379 afecmd_wr.rsvd = 0;
1380
1381 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_wr);
1382 if (ret < 0) {
1383 pr_err("%s: AFE rtproxy write to port 0x%x failed %d\n",
1384 __func__, afecmd_wr.port_id, ret);
1385 ret = -EINVAL;
1386 return ret;
1387 }
1388 return 0;
1389
1390}
1391
1392int afe_rt_proxy_port_read(u32 buf_addr_p, int bytes)
1393{
1394 int ret = 0;
1395 struct afe_cmd_rtport_rd afecmd_rd;
1396
1397 if (this_afe.apr == NULL) {
1398 pr_err("%s: register to AFE is not done\n", __func__);
1399 ret = -ENODEV;
1400 return ret;
1401 }
1402 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1403 buf_addr_p, bytes);
1404
1405 afecmd_rd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1406 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1407 afecmd_rd.hdr.pkt_size = sizeof(afecmd_rd);
1408 afecmd_rd.hdr.src_port = 0;
1409 afecmd_rd.hdr.dest_port = 0;
1410 afecmd_rd.hdr.token = 0;
1411 afecmd_rd.hdr.opcode = AFE_SERVICE_CMD_RTPORT_RD;
1412 afecmd_rd.buf_addr = (uint32_t)buf_addr_p;
1413 afecmd_rd.port_id = RT_PROXY_PORT_001_RX;
1414 afecmd_rd.bytes_avail = bytes;
1415 afecmd_rd.rsvd = 0;
1416
1417 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_rd);
1418 if (ret < 0) {
1419 pr_err("%s: AFE rtproxy read cmd to port 0x%x failed %d\n",
1420 __func__, afecmd_rd.port_id, ret);
1421 ret = -EINVAL;
1422 return ret;
1423 }
1424 return 0;
1425}
1426
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001427#ifdef CONFIG_DEBUG_FS
1428static struct dentry *debugfs_afelb;
1429static struct dentry *debugfs_afelb_gain;
1430
1431static int afe_debug_open(struct inode *inode, struct file *file)
1432{
1433 file->private_data = inode->i_private;
1434 pr_info("debug intf %s\n", (char *) file->private_data);
1435 return 0;
1436}
1437
1438static int afe_get_parameters(char *buf, long int *param1, int num_of_par)
1439{
1440 char *token;
1441 int base, cnt;
1442
1443 token = strsep(&buf, " ");
1444
1445 for (cnt = 0; cnt < num_of_par; cnt++) {
1446 if (token != NULL) {
1447 if ((token[1] == 'x') || (token[1] == 'X'))
1448 base = 16;
1449 else
1450 base = 10;
1451
1452 if (strict_strtoul(token, base, &param1[cnt]) != 0)
1453 return -EINVAL;
1454
1455 token = strsep(&buf, " ");
1456 } else
1457 return -EINVAL;
1458 }
1459 return 0;
1460}
1461#define AFE_LOOPBACK_ON (1)
1462#define AFE_LOOPBACK_OFF (0)
1463static ssize_t afe_debug_write(struct file *filp,
1464 const char __user *ubuf, size_t cnt, loff_t *ppos)
1465{
1466 char *lb_str = filp->private_data;
1467 char lbuf[32];
1468 int rc;
1469 unsigned long param[5];
1470
1471 if (cnt > sizeof(lbuf) - 1)
1472 return -EINVAL;
1473
1474 rc = copy_from_user(lbuf, ubuf, cnt);
1475 if (rc)
1476 return -EFAULT;
1477
1478 lbuf[cnt] = '\0';
1479
1480 if (!strcmp(lb_str, "afe_loopback")) {
1481 rc = afe_get_parameters(lbuf, param, 3);
1482 if (!rc) {
1483 pr_info("%s %lu %lu %lu\n", lb_str, param[0], param[1],
1484 param[2]);
1485
1486 if ((param[0] != AFE_LOOPBACK_ON) && (param[0] !=
1487 AFE_LOOPBACK_OFF)) {
1488 pr_err("%s: Error, parameter 0 incorrect\n",
1489 __func__);
1490 rc = -EINVAL;
1491 goto afe_error;
1492 }
1493 if ((afe_validate_port(param[1]) < 0) ||
1494 (afe_validate_port(param[2])) < 0) {
1495 pr_err("%s: Error, invalid afe port\n",
1496 __func__);
1497 }
1498 if (this_afe.apr == NULL) {
1499 pr_err("%s: Error, AFE not opened\n", __func__);
1500 rc = -EINVAL;
1501 } else {
1502 rc = afe_loopback(param[0], param[1], param[2]);
1503 }
1504 } else {
1505 pr_err("%s: Error, invalid parameters\n", __func__);
1506 rc = -EINVAL;
1507 }
1508
1509 } else if (!strcmp(lb_str, "afe_loopback_gain")) {
1510 rc = afe_get_parameters(lbuf, param, 2);
1511 if (!rc) {
1512 pr_info("%s %lu %lu\n", lb_str, param[0], param[1]);
1513
1514 if (afe_validate_port(param[0]) < 0) {
1515 pr_err("%s: Error, invalid afe port\n",
1516 __func__);
1517 rc = -EINVAL;
1518 goto afe_error;
1519 }
1520
1521 if (param[1] < 0 || param[1] > 100) {
1522 pr_err("%s: Error, volume shoud be 0 to 100"
1523 " percentage param = %lu\n",
1524 __func__, param[1]);
1525 rc = -EINVAL;
1526 goto afe_error;
1527 }
1528
1529 param[1] = (Q6AFE_MAX_VOLUME * param[1]) / 100;
1530
1531 if (this_afe.apr == NULL) {
1532 pr_err("%s: Error, AFE not opened\n", __func__);
1533 rc = -EINVAL;
1534 } else {
1535 rc = afe_loopback_gain(param[0], param[1]);
1536 }
1537 } else {
1538 pr_err("%s: Error, invalid parameters\n", __func__);
1539 rc = -EINVAL;
1540 }
1541 }
1542
1543afe_error:
1544 if (rc == 0)
1545 rc = cnt;
1546 else
1547 pr_err("%s: rc = %d\n", __func__, rc);
1548
1549 return rc;
1550}
1551
1552static const struct file_operations afe_debug_fops = {
1553 .open = afe_debug_open,
1554 .write = afe_debug_write
1555};
1556#endif
1557int afe_sidetone(u16 tx_port_id, u16 rx_port_id, u16 enable, uint16_t gain)
1558{
1559 struct afe_port_sidetone_command cmd_sidetone;
1560 int ret = 0;
1561
1562 pr_info("%s: tx_port_id:%d rx_port_id:%d enable:%d gain:%d\n", __func__,
1563 tx_port_id, rx_port_id, enable, gain);
1564 cmd_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1565 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1566 cmd_sidetone.hdr.pkt_size = sizeof(cmd_sidetone);
1567 cmd_sidetone.hdr.src_port = 0;
1568 cmd_sidetone.hdr.dest_port = 0;
1569 cmd_sidetone.hdr.token = 0;
1570 cmd_sidetone.hdr.opcode = AFE_PORT_CMD_SIDETONE_CTL;
1571 cmd_sidetone.tx_port_id = tx_port_id;
1572 cmd_sidetone.rx_port_id = rx_port_id;
1573 cmd_sidetone.gain = gain;
1574 cmd_sidetone.enable = enable;
1575
1576 atomic_set(&this_afe.state, 1);
1577 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_sidetone);
1578 if (ret < 0) {
1579 pr_err("%s: AFE sidetone failed for tx_port:%d rx_port:%d\n",
1580 __func__, tx_port_id, rx_port_id);
1581 ret = -EINVAL;
1582 goto fail_cmd;
1583 }
1584
1585 ret = wait_event_timeout(this_afe.wait,
1586 (atomic_read(&this_afe.state) == 0),
1587 msecs_to_jiffies(TIMEOUT_MS));
1588 if (ret < 0) {
1589 pr_err("%s: wait_event timeout\n", __func__);
1590 ret = -EINVAL;
1591 goto fail_cmd;
1592 }
1593 return 0;
1594fail_cmd:
1595 return ret;
1596}
1597
1598int afe_port_stop_nowait(int port_id)
1599{
1600 struct afe_port_stop_command stop;
1601 int ret = 0;
1602
1603 if (this_afe.apr == NULL) {
1604 pr_err("AFE is already closed\n");
1605 ret = -EINVAL;
1606 goto fail_cmd;
1607 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001608 pr_debug("%s: port_id=%d\n", __func__, port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301609 port_id = afe_convert_virtual_to_portid(port_id);
1610
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001611 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1612 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1613 stop.hdr.pkt_size = sizeof(stop);
1614 stop.hdr.src_port = 0;
1615 stop.hdr.dest_port = 0;
1616 stop.hdr.token = 0;
1617 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1618 stop.port_id = port_id;
1619 stop.reserved = 0;
1620
1621 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1622
1623 if (ret == -ENETRESET) {
1624 pr_info("%s: Need to reset, calling APR deregister", __func__);
1625 return apr_deregister(this_afe.apr);
1626 } else if (IS_ERR_VALUE(ret)) {
1627 pr_err("%s: AFE close failed\n", __func__);
1628 ret = -EINVAL;
1629 }
1630
1631fail_cmd:
1632 return ret;
1633
1634}
1635
1636int afe_close(int port_id)
1637{
1638 struct afe_port_stop_command stop;
1639 int ret = 0;
1640
1641 if (this_afe.apr == NULL) {
1642 pr_err("AFE is already closed\n");
1643 ret = -EINVAL;
1644 goto fail_cmd;
1645 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001646 pr_debug("%s: port_id=%d\n", __func__, port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301647 port_id = afe_convert_virtual_to_portid(port_id);
1648
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001649 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1650 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1651 stop.hdr.pkt_size = sizeof(stop);
1652 stop.hdr.src_port = 0;
1653 stop.hdr.dest_port = 0;
1654 stop.hdr.token = 0;
1655 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1656 stop.port_id = port_id;
1657 stop.reserved = 0;
1658
1659 atomic_set(&this_afe.state, 1);
1660 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1661
1662 if (ret == -ENETRESET) {
1663 pr_info("%s: Need to reset, calling APR deregister", __func__);
1664 return apr_deregister(this_afe.apr);
1665 }
1666
1667 if (ret < 0) {
1668 pr_err("%s: AFE close failed\n", __func__);
1669 ret = -EINVAL;
1670 goto fail_cmd;
1671 }
1672
1673 ret = wait_event_timeout(this_afe.wait,
1674 (atomic_read(&this_afe.state) == 0),
1675 msecs_to_jiffies(TIMEOUT_MS));
1676 if (!ret) {
1677 pr_err("%s: wait_event timeout\n", __func__);
1678 ret = -EINVAL;
1679 goto fail_cmd;
1680 }
1681fail_cmd:
1682 return ret;
1683}
1684
1685static int __init afe_init(void)
1686{
1687 init_waitqueue_head(&this_afe.wait);
1688 atomic_set(&this_afe.state, 0);
1689 atomic_set(&this_afe.status, 0);
1690 this_afe.apr = NULL;
1691#ifdef CONFIG_DEBUG_FS
1692 debugfs_afelb = debugfs_create_file("afe_loopback",
1693 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback",
1694 &afe_debug_fops);
1695
1696 debugfs_afelb_gain = debugfs_create_file("afe_loopback_gain",
1697 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback_gain",
1698 &afe_debug_fops);
1699
1700
1701#endif
1702 return 0;
1703}
1704
1705static void __exit afe_exit(void)
1706{
Ben Rombergerb7603232011-11-23 17:16:27 -08001707 int i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001708#ifdef CONFIG_DEBUG_FS
1709 if (debugfs_afelb)
1710 debugfs_remove(debugfs_afelb);
1711 if (debugfs_afelb_gain)
1712 debugfs_remove(debugfs_afelb_gain);
1713#endif
Ben Rombergerb7603232011-11-23 17:16:27 -08001714 for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
Ben Romberger9e792562012-02-24 12:29:01 -08001715 if (afe_cal_addr[i].cal_paddr != 0)
1716 afe_cmd_memory_unmap_nowait(
1717 afe_cal_addr[i].cal_paddr);
Ben Rombergerb7603232011-11-23 17:16:27 -08001718 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001719}
1720
1721device_initcall(afe_init);
1722__exitcall(afe_exit);