blob: f4745426d9a8b870cc40bcc973c6d692c5ac7521 [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 Shettyfeea7742011-09-11 12:30:36 -0700150 case INT_BT_SCO_RX:
151 case INT_BT_A2DP_RX:
152 case INT_FM_RX:
153 case VOICE_PLAYBACK_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530154 case RT_PROXY_PORT_001_RX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700155 ret = MSM_AFE_PORT_TYPE_RX;
156 break;
157
158 case PRIMARY_I2S_TX:
159 case PCM_TX:
160 case SECONDARY_I2S_TX:
161 case MI2S_TX:
162 case DIGI_MIC_TX:
163 case VOICE_RECORD_TX:
164 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800165 case SLIMBUS_1_TX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700166 case SLIMBUS_2_TX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700167 case INT_FM_TX:
168 case VOICE_RECORD_RX:
169 case INT_BT_SCO_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530170 case RT_PROXY_PORT_001_TX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700171 ret = MSM_AFE_PORT_TYPE_TX;
172 break;
173
174 default:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800175 pr_err("%s: invalid port id %d\n", __func__, port_id);
Neema Shettyfeea7742011-09-11 12:30:36 -0700176 ret = -EINVAL;
177 }
178
179 return ret;
180}
181
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700182int afe_validate_port(u16 port_id)
183{
184 int ret;
185
186 switch (port_id) {
187 case PRIMARY_I2S_RX:
188 case PRIMARY_I2S_TX:
189 case PCM_RX:
190 case PCM_TX:
191 case SECONDARY_I2S_RX:
192 case SECONDARY_I2S_TX:
193 case MI2S_RX:
194 case MI2S_TX:
195 case HDMI_RX:
196 case RSVD_2:
197 case RSVD_3:
198 case DIGI_MIC_TX:
199 case VOICE_RECORD_RX:
200 case VOICE_RECORD_TX:
201 case VOICE_PLAYBACK_TX:
202 case SLIMBUS_0_RX:
203 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800204 case SLIMBUS_1_RX:
205 case SLIMBUS_1_TX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700206 case SLIMBUS_2_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700207 case INT_BT_SCO_RX:
208 case INT_BT_SCO_TX:
209 case INT_BT_A2DP_RX:
210 case INT_FM_RX:
211 case INT_FM_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530212 case RT_PROXY_PORT_001_RX:
213 case RT_PROXY_PORT_001_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700214 {
215 ret = 0;
216 break;
217 }
218
219 default:
220 ret = -EINVAL;
221 }
222
223 return ret;
224}
225
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530226int afe_convert_virtual_to_portid(u16 port_id)
227{
228 int ret;
229
230 /* if port_id is virtual, convert to physical..
231 * if port_id is already physical, return physical
232 */
233 if (afe_validate_port(port_id) < 0) {
234 if (port_id == RT_PROXY_DAI_001_RX ||
235 port_id == RT_PROXY_DAI_001_TX ||
236 port_id == RT_PROXY_DAI_002_RX ||
237 port_id == RT_PROXY_DAI_002_TX)
238 ret = VIRTUAL_ID_TO_PORTID(port_id);
239 else
240 ret = -EINVAL;
241 } else
242 ret = port_id;
243
244 return ret;
245}
246
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700247int afe_get_port_index(u16 port_id)
248{
249 switch (port_id) {
250 case PRIMARY_I2S_RX: return IDX_PRIMARY_I2S_RX;
251 case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
252 case PCM_RX: return IDX_PCM_RX;
253 case PCM_TX: return IDX_PCM_TX;
254 case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
255 case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
256 case MI2S_RX: return IDX_MI2S_RX;
257 case MI2S_TX: return IDX_MI2S_TX;
258 case HDMI_RX: return IDX_HDMI_RX;
259 case RSVD_2: return IDX_RSVD_2;
260 case RSVD_3: return IDX_RSVD_3;
261 case DIGI_MIC_TX: return IDX_DIGI_MIC_TX;
262 case VOICE_RECORD_RX: return IDX_VOICE_RECORD_RX;
263 case VOICE_RECORD_TX: return IDX_VOICE_RECORD_TX;
264 case VOICE_PLAYBACK_TX: return IDX_VOICE_PLAYBACK_TX;
265 case SLIMBUS_0_RX: return IDX_SLIMBUS_0_RX;
266 case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
Neema Shetty3c9d2862012-03-11 01:25:32 -0800267 case SLIMBUS_1_RX: return IDX_SLIMBUS_1_RX;
268 case SLIMBUS_1_TX: return IDX_SLIMBUS_1_TX;
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700269 case SLIMBUS_2_TX: return IDX_SLIMBUS_2_TX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700270 case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
271 case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
272 case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
273 case INT_FM_RX: return IDX_INT_FM_RX;
274 case INT_FM_TX: return IDX_INT_FM_TX;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530275 case RT_PROXY_PORT_001_RX: return IDX_RT_PROXY_PORT_001_RX;
276 case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700277
278 default: return -EINVAL;
279 }
280}
281
282int afe_sizeof_cfg_cmd(u16 port_id)
283{
284 int ret_size;
285 switch (port_id) {
286 case PRIMARY_I2S_RX:
287 case PRIMARY_I2S_TX:
288 case SECONDARY_I2S_RX:
289 case SECONDARY_I2S_TX:
290 case MI2S_RX:
291 case MI2S_TX:
292 ret_size = SIZEOF_CFG_CMD(afe_port_mi2s_cfg);
293 break;
294 case HDMI_RX:
Kiran Kandi5e809b02012-01-31 00:24:33 -0800295 ret_size = SIZEOF_CFG_CMD(afe_port_hdmi_multi_ch_cfg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700296 break;
297 case SLIMBUS_0_RX:
298 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800299 case SLIMBUS_1_RX:
300 case SLIMBUS_1_TX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700301 case SLIMBUS_2_TX:
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800302 ret_size = SIZEOF_CFG_CMD(afe_port_slimbus_sch_cfg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700303 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530304 case RT_PROXY_PORT_001_RX:
305 case RT_PROXY_PORT_001_TX:
306 ret_size = SIZEOF_CFG_CMD(afe_port_rtproxy_cfg);
307 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700308 case PCM_RX:
309 case PCM_TX:
310 default:
311 ret_size = SIZEOF_CFG_CMD(afe_port_pcm_cfg);
312 break;
313 }
314 return ret_size;
315}
316
Jay Wang6a305432011-08-05 16:01:54 -0700317int afe_q6_interface_prepare(void)
318{
319 int ret = 0;
320
321 pr_debug("%s:", __func__);
322
323 if (this_afe.apr == NULL) {
324 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
325 0xFFFFFFFF, &this_afe);
326 pr_debug("%s: Register AFE\n", __func__);
327 if (this_afe.apr == NULL) {
328 pr_err("%s: Unable to register AFE\n", __func__);
329 ret = -ENODEV;
330 }
331 }
332 return ret;
333}
334
Ben Rombergerb7603232011-11-23 17:16:27 -0800335static void afe_send_cal_block(int32_t path, u16 port_id)
336{
337 int result = 0;
338 struct acdb_cal_block cal_block;
339 struct afe_port_cmd_set_param_no_payload afe_cal;
340 pr_debug("%s: path %d\n", __func__, path);
341
342 get_afe_cal(path, &cal_block);
343 if (cal_block.cal_size <= 0) {
344 pr_debug("%s: No AFE cal to send!\n", __func__);
345 goto done;
346 }
347
Ben Romberger9e792562012-02-24 12:29:01 -0800348 if ((afe_cal_addr[path].cal_paddr != cal_block.cal_paddr) ||
349 (cal_block.cal_size > afe_cal_addr[path].cal_size)) {
350 if (afe_cal_addr[path].cal_paddr != 0)
351 afe_cmd_memory_unmap_nowait(
352 afe_cal_addr[path].cal_paddr);
353
Ben Rombergerb7603232011-11-23 17:16:27 -0800354 afe_cmd_memory_map_nowait(cal_block.cal_paddr,
355 cal_block.cal_size);
Ben Romberger9e792562012-02-24 12:29:01 -0800356 afe_cal_addr[path].cal_paddr = cal_block.cal_paddr;
357 afe_cal_addr[path].cal_size = cal_block.cal_size;
Ben Rombergerb7603232011-11-23 17:16:27 -0800358 }
359
360 afe_cal.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
361 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
362 afe_cal.hdr.pkt_size = sizeof(afe_cal);
363 afe_cal.hdr.src_port = 0;
364 afe_cal.hdr.dest_port = 0;
365 afe_cal.hdr.token = 0;
366 afe_cal.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
367 afe_cal.port_id = port_id;
368 afe_cal.payload_size = cal_block.cal_size;
369 afe_cal.payload_address = cal_block.cal_paddr;
370
371 pr_debug("%s: AFE cal sent for device port = %d, path = %d, "
372 "cal size = %d, cal addr = 0x%x\n", __func__,
373 port_id, path, cal_block.cal_size, cal_block.cal_paddr);
374
375 result = apr_send_pkt(this_afe.apr, (uint32_t *) &afe_cal);
376 if (result < 0) {
377 pr_err("%s: AFE cal for port %d failed\n",
378 __func__, port_id);
379 }
380
381 pr_debug("%s: AFE cal sent for path %d device!\n", __func__, path);
382done:
383 return;
384}
385
386void afe_send_cal(u16 port_id)
387{
388 pr_debug("%s\n", __func__);
389
390 if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX)
391 afe_send_cal_block(TX_CAL, port_id);
392 else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX)
393 afe_send_cal_block(RX_CAL, port_id);
394}
395
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700396int afe_port_start_nowait(u16 port_id, union afe_port_config *afe_config,
397 u32 rate) /* This function is no blocking */
398{
399 struct afe_port_start_command start;
400 struct afe_audioif_config_command config;
401 int ret;
402
403 if (!afe_config) {
404 pr_err("%s: Error, no configuration data\n", __func__);
405 ret = -EINVAL;
406 return ret;
407 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -0800408 pr_debug("%s: %d %d\n", __func__, port_id, rate);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700409
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530410 if ((port_id == RT_PROXY_DAI_001_RX) ||
411 (port_id == RT_PROXY_DAI_002_TX))
412 return -EINVAL;
413 if ((port_id == RT_PROXY_DAI_002_RX) ||
414 (port_id == RT_PROXY_DAI_001_TX))
415 port_id = VIRTUAL_ID_TO_PORTID(port_id);
416
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700417 if (this_afe.apr == NULL) {
Jay Wang6a305432011-08-05 16:01:54 -0700418 pr_err("%s: AFE APR is not registered\n", __func__);
419 ret = -ENODEV;
420 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700421 }
Kiran Kandi5e809b02012-01-31 00:24:33 -0800422
423 if (port_id == HDMI_RX) {
424 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700425 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
Kiran Kandi5e809b02012-01-31 00:24:33 -0800426 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
427 config.hdr.src_port = 0;
428 config.hdr.dest_port = 0;
429 config.hdr.token = 0;
430 config.hdr.opcode = AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG;
431 } else {
432
433 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
434 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
435 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
436 config.hdr.src_port = 0;
437 config.hdr.dest_port = 0;
438 config.hdr.token = 0;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800439 switch (port_id) {
440 case SLIMBUS_0_RX:
441 case SLIMBUS_0_TX:
442 case SLIMBUS_1_RX:
443 case SLIMBUS_1_TX:
444 case SLIMBUS_2_RX:
445 case SLIMBUS_2_TX:
446 case SLIMBUS_3_RX:
447 case SLIMBUS_3_TX:
448 case SLIMBUS_4_RX:
449 case SLIMBUS_4_TX:
450 config.hdr.opcode = AFE_PORT_AUDIO_SLIM_SCH_CONFIG;
451 break;
Kuirong Wanga36f2882012-04-02 19:45:26 -0700452 case MI2S_TX:
453 case MI2S_RX:
454 case SECONDARY_I2S_RX:
455 case SECONDARY_I2S_TX:
456 case PRIMARY_I2S_RX:
457 case PRIMARY_I2S_TX:
458 /* AFE_PORT_CMD_I2S_CONFIG command is not supported
459 * in the LPASS EL 1.0. So we have to distiguish
460 * which AFE command, AFE_PORT_CMD_I2S_CONFIG or
461 * AFE_PORT_AUDIO_IF_CONFIG to use. If the format
462 * is L-PCM, the AFE_PORT_AUDIO_IF_CONFIG is used
463 * to make the backward compatible.
464 */
465 pr_debug("%s: afe_config->mi2s.format = %d\n", __func__,
466 afe_config->mi2s.format);
467 if (afe_config->mi2s.format == MSM_AFE_I2S_FORMAT_LPCM)
468 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
469 else
470 config.hdr.opcode = AFE_PORT_CMD_I2S_CONFIG;
471 break;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800472 default:
473 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
474 break;
475 }
Kiran Kandi5e809b02012-01-31 00:24:33 -0800476 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700477
478 if (afe_validate_port(port_id) < 0) {
479
480 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
481 port_id);
482 ret = -EINVAL;
483 goto fail_cmd;
484 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700485 config.port_id = port_id;
486 config.port = *afe_config;
487
488 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
489 if (ret < 0) {
490 pr_err("%s: AFE enable for port %d failed\n", __func__,
491 port_id);
492 ret = -EINVAL;
493 goto fail_cmd;
494 }
Ben Rombergerb7603232011-11-23 17:16:27 -0800495
496 /* send AFE cal */
497 afe_send_cal(port_id);
498
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700499 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
500 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
501 start.hdr.pkt_size = sizeof(start);
502 start.hdr.src_port = 0;
503 start.hdr.dest_port = 0;
504 start.hdr.token = 0;
505 start.hdr.opcode = AFE_PORT_CMD_START;
506 start.port_id = port_id;
507 start.gain = 0x2000;
508 start.sample_rate = rate;
509
510 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
511
512 if (IS_ERR_VALUE(ret)) {
513 pr_err("%s: AFE enable for port %d failed\n", __func__,
514 port_id);
515 ret = -EINVAL;
516 goto fail_cmd;
517 }
518
519 if (this_afe.task != current)
520 this_afe.task = current;
521
522 pr_debug("task_name = %s pid = %d\n",
523 this_afe.task->comm, this_afe.task->pid);
524 return 0;
525
526fail_cmd:
527 return ret;
528}
529
530int afe_open(u16 port_id, union afe_port_config *afe_config, int rate)
531{
532 struct afe_port_start_command start;
533 struct afe_audioif_config_command config;
534 int ret = 0;
535
536 if (!afe_config) {
537 pr_err("%s: Error, no configuration data\n", __func__);
538 ret = -EINVAL;
539 return ret;
540 }
541
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800542 pr_debug("%s: %d %d\n", __func__, port_id, rate);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700543
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530544 if ((port_id == RT_PROXY_DAI_001_RX) ||
545 (port_id == RT_PROXY_DAI_002_TX))
546 return -EINVAL;
547 if ((port_id == RT_PROXY_DAI_002_RX) ||
548 (port_id == RT_PROXY_DAI_001_TX))
549 port_id = VIRTUAL_ID_TO_PORTID(port_id);
550
Jay Wang6a305432011-08-05 16:01:54 -0700551 ret = afe_q6_interface_prepare();
552 if (ret != 0)
553 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700554
555 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
556 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
557 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
558 config.hdr.src_port = 0;
559 config.hdr.dest_port = 0;
560 config.hdr.token = 0;
Kuirong Wanga36f2882012-04-02 19:45:26 -0700561 switch (port_id) {
562 case SLIMBUS_0_RX:
563 case SLIMBUS_0_TX:
564 case SLIMBUS_1_RX:
565 case SLIMBUS_1_TX:
566 case SLIMBUS_2_RX:
567 case SLIMBUS_2_TX:
568 case SLIMBUS_3_RX:
569 case SLIMBUS_3_TX:
570 case SLIMBUS_4_RX:
571 case SLIMBUS_4_TX:
572 config.hdr.opcode = AFE_PORT_AUDIO_SLIM_SCH_CONFIG;
573 break;
574 case MI2S_TX:
575 case MI2S_RX:
576 case SECONDARY_I2S_RX:
577 case SECONDARY_I2S_TX:
578 case PRIMARY_I2S_RX:
579 case PRIMARY_I2S_TX:
580 /* AFE_PORT_CMD_I2S_CONFIG command is not supported
581 * in the LPASS EL 1.0. So we have to distiguish
582 * which AFE command, AFE_PORT_CMD_I2S_CONFIG or
583 * AFE_PORT_AUDIO_IF_CONFIG to use. If the format
584 * is L-PCM, the AFE_PORT_AUDIO_IF_CONFIG is used
585 * to make the backward compatible.
586 */
587 pr_debug("%s: afe_config->mi2s.format = %d\n", __func__,
588 afe_config->mi2s.format);
589 if (afe_config->mi2s.format == MSM_AFE_I2S_FORMAT_LPCM)
590 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
591 else
592 config.hdr.opcode = AFE_PORT_CMD_I2S_CONFIG;
593 break;
594 default:
595 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
596 break;
597 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700598
599 if (afe_validate_port(port_id) < 0) {
600
601 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
602 port_id);
603 ret = -EINVAL;
604 goto fail_cmd;
605 }
606
607 config.port_id = port_id;
608 config.port = *afe_config;
609
610 atomic_set(&this_afe.state, 1);
611 atomic_set(&this_afe.status, 0);
612 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
613 if (ret < 0) {
614 pr_err("%s: AFE enable for port %d failed\n", __func__,
615 port_id);
616 ret = -EINVAL;
617 goto fail_cmd;
618 }
619
620 ret = wait_event_timeout(this_afe.wait,
621 (atomic_read(&this_afe.state) == 0),
622 msecs_to_jiffies(TIMEOUT_MS));
623 if (!ret) {
624 pr_err("%s: wait_event timeout\n", __func__);
625 ret = -EINVAL;
626 goto fail_cmd;
627 }
628 if (atomic_read(&this_afe.status) != 0) {
629 pr_err("%s: config cmd failed\n", __func__);
630 ret = -EINVAL;
631 goto fail_cmd;
632 }
633 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
634 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
635 start.hdr.pkt_size = sizeof(start);
636 start.hdr.src_port = 0;
637 start.hdr.dest_port = 0;
638 start.hdr.token = 0;
639 start.hdr.opcode = AFE_PORT_CMD_START;
640 start.port_id = port_id;
641 start.gain = 0x2000;
642 start.sample_rate = rate;
643
644 atomic_set(&this_afe.state, 1);
645 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
646 if (ret < 0) {
647 pr_err("%s: AFE enable for port %d failed\n", __func__,
648 port_id);
649 ret = -EINVAL;
650 goto fail_cmd;
651 }
652 ret = wait_event_timeout(this_afe.wait,
653 (atomic_read(&this_afe.state) == 0),
654 msecs_to_jiffies(TIMEOUT_MS));
655 if (!ret) {
656 pr_err("%s: wait_event timeout\n", __func__);
657 ret = -EINVAL;
658 goto fail_cmd;
659 }
660
661 if (this_afe.task != current)
662 this_afe.task = current;
663
664 pr_debug("task_name = %s pid = %d\n",
665 this_afe.task->comm, this_afe.task->pid);
666 return 0;
667fail_cmd:
668 return ret;
669}
670
671int afe_loopback(u16 enable, u16 rx_port, u16 tx_port)
672{
673 struct afe_loopback_command lb_cmd;
674 int ret = 0;
Jay Wang6a305432011-08-05 16:01:54 -0700675
676 ret = afe_q6_interface_prepare();
677 if (ret != 0)
678 return ret;
679
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700680 lb_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
681 APR_HDR_LEN(20), APR_PKT_VER);
682 lb_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
683 sizeof(lb_cmd) - APR_HDR_SIZE);
684 lb_cmd.hdr.src_port = 0;
685 lb_cmd.hdr.dest_port = 0;
686 lb_cmd.hdr.token = 0;
687 lb_cmd.hdr.opcode = AFE_PORT_CMD_LOOPBACK;
688 lb_cmd.tx_port_id = tx_port;
689 lb_cmd.rx_port_id = rx_port;
690 lb_cmd.mode = 0xFFFF;
691 lb_cmd.enable = (enable ? 1 : 0);
692 atomic_set(&this_afe.state, 1);
693
694 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &lb_cmd);
695 if (ret < 0) {
696 pr_err("%s: AFE loopback failed\n", __func__);
697 ret = -EINVAL;
698 goto done;
699 }
700 ret = wait_event_timeout(this_afe.wait,
701 (atomic_read(&this_afe.state) == 0),
702 msecs_to_jiffies(TIMEOUT_MS));
703 if (!ret) {
704 pr_err("%s: wait_event timeout\n", __func__);
705 ret = -EINVAL;
706 }
707done:
708 return ret;
709}
710
711
712int afe_loopback_gain(u16 port_id, u16 volume)
713{
714 struct afe_port_cmd_set_param set_param;
715 int ret = 0;
716
717 if (this_afe.apr == NULL) {
Jayasena Sangaraboina82435032011-07-26 15:23:00 -0700718 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
719 0xFFFFFFFF, &this_afe);
720 pr_debug("%s: Register AFE\n", __func__);
721 if (this_afe.apr == NULL) {
722 pr_err("%s: Unable to register AFE\n", __func__);
723 ret = -ENODEV;
724 return ret;
725 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700726 }
727
728 if (afe_validate_port(port_id) < 0) {
729
730 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
731 port_id);
732 ret = -EINVAL;
733 goto fail_cmd;
734 }
735
736 /* RX ports numbers are even .TX ports numbers are odd. */
737 if (port_id % 2 == 0) {
738 pr_err("%s: Failed : afe loopback gain only for TX ports."
739 " port_id %d\n", __func__, port_id);
740 ret = -EINVAL;
741 goto fail_cmd;
742 }
743
744 pr_debug("%s: %d %hX\n", __func__, port_id, volume);
745
746 set_param.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
747 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
748 set_param.hdr.pkt_size = sizeof(set_param);
749 set_param.hdr.src_port = 0;
750 set_param.hdr.dest_port = 0;
751 set_param.hdr.token = 0;
752 set_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
753
754 set_param.port_id = port_id;
755 set_param.payload_size = sizeof(struct afe_param_payload);
756 set_param.payload_address = 0;
757
758 set_param.payload.module_id = AFE_MODULE_ID_PORT_INFO;
759 set_param.payload.param_id = AFE_PARAM_ID_LOOPBACK_GAIN;
760 set_param.payload.param_size = sizeof(struct afe_param_loopback_gain);
761 set_param.payload.reserved = 0;
762
763 set_param.payload.param.loopback_gain.gain = volume;
764 set_param.payload.param.loopback_gain.reserved = 0;
765
766 atomic_set(&this_afe.state, 1);
767 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_param);
768 if (ret < 0) {
769 pr_err("%s: AFE param set failed for port %d\n",
770 __func__, port_id);
771 ret = -EINVAL;
772 goto fail_cmd;
773 }
774
775 ret = wait_event_timeout(this_afe.wait,
776 (atomic_read(&this_afe.state) == 0),
777 msecs_to_jiffies(TIMEOUT_MS));
778 if (ret < 0) {
779 pr_err("%s: wait_event timeout\n", __func__);
780 ret = -EINVAL;
781 goto fail_cmd;
782 }
783 return 0;
784fail_cmd:
785 return ret;
786}
787
Laxminath Kasam885f5102011-07-14 10:20:21 +0530788int afe_apply_gain(u16 port_id, u16 gain)
789{
790 struct afe_port_gain_command set_gain;
791 int ret = 0;
792
793 if (this_afe.apr == NULL) {
794 pr_err("%s: AFE is not opened\n", __func__);
795 ret = -EPERM;
796 goto fail_cmd;
797 }
798
799 if (afe_validate_port(port_id) < 0) {
800 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
801 port_id);
802 ret = -EINVAL;
803 goto fail_cmd;
804 }
805
806 /* RX ports numbers are even .TX ports numbers are odd. */
807 if (port_id % 2 == 0) {
808 pr_err("%s: Failed : afe apply gain only for TX ports."
809 " port_id %d\n", __func__, port_id);
810 ret = -EINVAL;
811 goto fail_cmd;
812 }
813
814 pr_debug("%s: %d %hX\n", __func__, port_id, gain);
815
816 set_gain.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
817 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
818 set_gain.hdr.pkt_size = sizeof(set_gain);
819 set_gain.hdr.src_port = 0;
820 set_gain.hdr.dest_port = 0;
821 set_gain.hdr.token = 0;
822 set_gain.hdr.opcode = AFE_PORT_CMD_APPLY_GAIN;
823
824 set_gain.port_id = port_id;
825 set_gain.gain = gain;
826
827 atomic_set(&this_afe.state, 1);
828 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_gain);
829 if (ret < 0) {
830 pr_err("%s: AFE Gain set failed for port %d\n",
831 __func__, port_id);
832 ret = -EINVAL;
833 goto fail_cmd;
834 }
835
836 ret = wait_event_timeout(this_afe.wait,
837 (atomic_read(&this_afe.state) == 0),
838 msecs_to_jiffies(TIMEOUT_MS));
839 if (ret < 0) {
840 pr_err("%s: wait_event timeout\n", __func__);
841 ret = -EINVAL;
842 goto fail_cmd;
843 }
844 return 0;
845fail_cmd:
846 return ret;
847}
Helen Zeng0705a5f2011-10-14 15:29:52 -0700848
849int afe_pseudo_port_start_nowait(u16 port_id)
850{
851 int ret = 0;
852 struct afe_pseudoport_start_command start;
853
854 pr_debug("%s: port_id=%d\n", __func__, port_id);
855 if (this_afe.apr == NULL) {
856 pr_err("%s: AFE APR is not registered\n", __func__);
857 return -ENODEV;
858 }
859
860
861 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
862 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
863 start.hdr.pkt_size = sizeof(start);
864 start.hdr.src_port = 0;
865 start.hdr.dest_port = 0;
866 start.hdr.token = 0;
867 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
868 start.port_id = port_id;
869 start.timing = 1;
870
871 atomic_set(&this_afe.state, 1);
872 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
873 if (ret < 0) {
874 pr_err("%s: AFE enable for port %d failed %d\n",
875 __func__, port_id, ret);
876 return -EINVAL;
877 }
878 return 0;
879}
880
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700881int afe_start_pseudo_port(u16 port_id)
882{
883 int ret = 0;
884 struct afe_pseudoport_start_command start;
885
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800886 pr_debug("%s: port_id=%d\n", __func__, port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700887
Jay Wang6a305432011-08-05 16:01:54 -0700888 ret = afe_q6_interface_prepare();
889 if (ret != 0)
890 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700891
892 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
893 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
894 start.hdr.pkt_size = sizeof(start);
895 start.hdr.src_port = 0;
896 start.hdr.dest_port = 0;
897 start.hdr.token = 0;
898 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
899 start.port_id = port_id;
900 start.timing = 1;
901
902 atomic_set(&this_afe.state, 1);
903 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
904 if (ret < 0) {
905 pr_err("%s: AFE enable for port %d failed %d\n",
906 __func__, port_id, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700907 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
Helen Zeng0705a5f2011-10-14 15:29:52 -0700921int afe_pseudo_port_stop_nowait(u16 port_id)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700922{
923 int ret = 0;
924 struct afe_pseudoport_stop_command stop;
925
Helen Zeng0705a5f2011-10-14 15:29:52 -0700926 pr_debug("%s: port_id=%d\n", __func__, port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700927
928 if (this_afe.apr == NULL) {
929 pr_err("%s: AFE is already closed\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700930 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700931 }
932
933 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
934 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
935 stop.hdr.pkt_size = sizeof(stop);
936 stop.hdr.src_port = 0;
937 stop.hdr.dest_port = 0;
938 stop.hdr.token = 0;
939 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
940 stop.port_id = port_id;
941 stop.reserved = 0;
942
943 atomic_set(&this_afe.state, 1);
944 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
945 if (ret < 0) {
946 pr_err("%s: AFE close failed %d\n", __func__, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700947 return -EINVAL;
948 }
949
950 return 0;
951
952}
953
954int afe_stop_pseudo_port(u16 port_id)
955{
956 int ret = 0;
957 struct afe_pseudoport_stop_command stop;
958
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800959 pr_debug("%s: port_id=%d\n", __func__, port_id);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700960
961 if (this_afe.apr == NULL) {
962 pr_err("%s: AFE is already closed\n", __func__);
963 return -EINVAL;
964 }
965
966 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
967 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
968 stop.hdr.pkt_size = sizeof(stop);
969 stop.hdr.src_port = 0;
970 stop.hdr.dest_port = 0;
971 stop.hdr.token = 0;
972 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
973 stop.port_id = port_id;
974 stop.reserved = 0;
975
976 atomic_set(&this_afe.state, 1);
977 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
978 if (ret < 0) {
979 pr_err("%s: AFE close failed %d\n", __func__, ret);
980 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700981 }
982
983 ret = wait_event_timeout(this_afe.wait,
984 (atomic_read(&this_afe.state) == 0),
985 msecs_to_jiffies(TIMEOUT_MS));
986 if (!ret) {
987 pr_err("%s: wait_event timeout\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700988 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700989 }
990
991 return 0;
992}
993
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530994int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz)
995{
996 int ret = 0;
997 struct afe_cmd_memory_map mregion;
998
999 pr_debug("%s:\n", __func__);
1000
1001 if (this_afe.apr == NULL) {
1002 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1003 0xFFFFFFFF, &this_afe);
1004 pr_debug("%s: Register AFE\n", __func__);
1005 if (this_afe.apr == NULL) {
1006 pr_err("%s: Unable to register AFE\n", __func__);
1007 ret = -ENODEV;
1008 return ret;
1009 }
1010 }
1011
1012 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1013 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1014 mregion.hdr.pkt_size = sizeof(mregion);
1015 mregion.hdr.src_port = 0;
1016 mregion.hdr.dest_port = 0;
1017 mregion.hdr.token = 0;
1018 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
1019 mregion.phy_addr = dma_addr_p;
1020 mregion.mem_sz = dma_buf_sz;
1021 mregion.mem_id = 0;
1022 mregion.rsvd = 0;
1023
1024 atomic_set(&this_afe.state, 1);
1025 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1026 if (ret < 0) {
1027 pr_err("%s: AFE memory map cmd failed %d\n",
1028 __func__, ret);
1029 ret = -EINVAL;
1030 return ret;
1031 }
1032
1033 ret = wait_event_timeout(this_afe.wait,
1034 (atomic_read(&this_afe.state) == 0),
1035 msecs_to_jiffies(TIMEOUT_MS));
1036 if (!ret) {
1037 pr_err("%s: wait_event timeout\n", __func__);
1038 ret = -EINVAL;
1039 return ret;
1040 }
1041
1042 return 0;
1043}
1044
Ben Rombergerb7603232011-11-23 17:16:27 -08001045int afe_cmd_memory_map_nowait(u32 dma_addr_p, u32 dma_buf_sz)
1046{
1047 int ret = 0;
1048 struct afe_cmd_memory_map mregion;
1049
1050 pr_debug("%s:\n", __func__);
1051
1052 if (this_afe.apr == NULL) {
1053 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1054 0xFFFFFFFF, &this_afe);
1055 pr_debug("%s: Register AFE\n", __func__);
1056 if (this_afe.apr == NULL) {
1057 pr_err("%s: Unable to register AFE\n", __func__);
1058 ret = -ENODEV;
1059 return ret;
1060 }
1061 }
1062
1063 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1064 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1065 mregion.hdr.pkt_size = sizeof(mregion);
1066 mregion.hdr.src_port = 0;
1067 mregion.hdr.dest_port = 0;
1068 mregion.hdr.token = 0;
1069 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
1070 mregion.phy_addr = dma_addr_p;
1071 mregion.mem_sz = dma_buf_sz;
1072 mregion.mem_id = 0;
1073 mregion.rsvd = 0;
1074
1075 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1076 if (ret < 0) {
1077 pr_err("%s: AFE memory map cmd failed %d\n",
1078 __func__, ret);
1079 ret = -EINVAL;
1080 }
1081 return 0;
1082}
1083
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301084int afe_cmd_memory_unmap(u32 dma_addr_p)
1085{
1086 int ret = 0;
1087 struct afe_cmd_memory_unmap mregion;
1088
1089 pr_debug("%s:\n", __func__);
1090
1091 if (this_afe.apr == NULL) {
1092 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1093 0xFFFFFFFF, &this_afe);
1094 pr_debug("%s: Register AFE\n", __func__);
1095 if (this_afe.apr == NULL) {
1096 pr_err("%s: Unable to register AFE\n", __func__);
1097 ret = -ENODEV;
1098 return ret;
1099 }
1100 }
1101
1102 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1103 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1104 mregion.hdr.pkt_size = sizeof(mregion);
1105 mregion.hdr.src_port = 0;
1106 mregion.hdr.dest_port = 0;
1107 mregion.hdr.token = 0;
1108 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
1109 mregion.phy_addr = dma_addr_p;
1110
1111 atomic_set(&this_afe.state, 1);
1112 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1113 if (ret < 0) {
Ben Rombergerb7603232011-11-23 17:16:27 -08001114 pr_err("%s: AFE memory unmap cmd failed %d\n",
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301115 __func__, ret);
1116 ret = -EINVAL;
1117 return ret;
1118 }
1119
1120 ret = wait_event_timeout(this_afe.wait,
1121 (atomic_read(&this_afe.state) == 0),
1122 msecs_to_jiffies(TIMEOUT_MS));
1123 if (!ret) {
1124 pr_err("%s: wait_event timeout\n", __func__);
1125 ret = -EINVAL;
1126 return ret;
1127 }
Ben Rombergerb7603232011-11-23 17:16:27 -08001128 return 0;
1129}
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301130
Ben Rombergerb7603232011-11-23 17:16:27 -08001131int afe_cmd_memory_unmap_nowait(u32 dma_addr_p)
1132{
1133 int ret = 0;
1134 struct afe_cmd_memory_unmap mregion;
1135
1136 pr_debug("%s:\n", __func__);
1137
1138 if (this_afe.apr == NULL) {
1139 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1140 0xFFFFFFFF, &this_afe);
1141 pr_debug("%s: Register AFE\n", __func__);
1142 if (this_afe.apr == NULL) {
1143 pr_err("%s: Unable to register AFE\n", __func__);
1144 ret = -ENODEV;
1145 return ret;
1146 }
1147 }
1148
1149 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1150 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1151 mregion.hdr.pkt_size = sizeof(mregion);
1152 mregion.hdr.src_port = 0;
1153 mregion.hdr.dest_port = 0;
1154 mregion.hdr.token = 0;
1155 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
1156 mregion.phy_addr = dma_addr_p;
1157
1158 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1159 if (ret < 0) {
1160 pr_err("%s: AFE memory unmap cmd failed %d\n",
1161 __func__, ret);
1162 ret = -EINVAL;
1163 }
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301164 return 0;
1165}
1166
1167int afe_register_get_events(u16 port_id,
1168 void (*cb) (uint32_t opcode,
1169 uint32_t token, uint32_t *payload, void *priv),
1170 void *private_data)
1171{
1172 int ret = 0;
1173 struct afe_cmd_reg_rtport rtproxy;
1174
1175 pr_debug("%s:\n", __func__);
1176
1177 if (this_afe.apr == NULL) {
1178 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1179 0xFFFFFFFF, &this_afe);
1180 pr_debug("%s: Register AFE\n", __func__);
1181 if (this_afe.apr == NULL) {
1182 pr_err("%s: Unable to register AFE\n", __func__);
1183 ret = -ENODEV;
1184 return ret;
1185 }
1186 }
1187 if ((port_id == RT_PROXY_DAI_002_RX) ||
1188 (port_id == RT_PROXY_DAI_001_TX))
1189 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1190 else
1191 return -EINVAL;
1192
1193 if (port_id == RT_PROXY_PORT_001_TX) {
1194 this_afe.tx_cb = cb;
1195 this_afe.tx_private_data = private_data;
1196 } else if (port_id == RT_PROXY_PORT_001_RX) {
1197 this_afe.rx_cb = cb;
1198 this_afe.rx_private_data = private_data;
1199 }
1200
1201 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1202 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1203 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1204 rtproxy.hdr.src_port = 1;
1205 rtproxy.hdr.dest_port = 1;
1206 rtproxy.hdr.token = 0;
1207 rtproxy.hdr.opcode = AFE_SERVICE_CMD_REG_RTPORT;
1208 rtproxy.port_id = port_id;
1209 rtproxy.rsvd = 0;
1210
1211 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1212 if (ret < 0) {
1213 pr_err("%s: AFE reg. rtproxy_event failed %d\n",
1214 __func__, ret);
1215 ret = -EINVAL;
1216 return ret;
1217 }
1218 return 0;
1219}
1220
1221int afe_unregister_get_events(u16 port_id)
1222{
1223 int ret = 0;
1224 struct afe_cmd_unreg_rtport rtproxy;
1225
1226 pr_debug("%s:\n", __func__);
1227
1228 if (this_afe.apr == NULL) {
1229 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1230 0xFFFFFFFF, &this_afe);
1231 pr_debug("%s: Register AFE\n", __func__);
1232 if (this_afe.apr == NULL) {
1233 pr_err("%s: Unable to register AFE\n", __func__);
1234 ret = -ENODEV;
1235 return ret;
1236 }
1237 }
1238 if ((port_id == RT_PROXY_DAI_002_RX) ||
1239 (port_id == RT_PROXY_DAI_001_TX))
1240 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1241 else
1242 return -EINVAL;
1243
1244 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1245 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1246 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1247 rtproxy.hdr.src_port = 0;
1248 rtproxy.hdr.dest_port = 0;
1249 rtproxy.hdr.token = 0;
1250 rtproxy.hdr.opcode = AFE_SERVICE_CMD_UNREG_RTPORT;
1251 rtproxy.port_id = port_id;
1252 rtproxy.rsvd = 0;
1253
1254 if (port_id == RT_PROXY_PORT_001_TX) {
1255 this_afe.tx_cb = NULL;
1256 this_afe.tx_private_data = NULL;
1257 } else if (port_id == RT_PROXY_PORT_001_RX) {
1258 this_afe.rx_cb = NULL;
1259 this_afe.rx_private_data = NULL;
1260 }
1261
1262 atomic_set(&this_afe.state, 1);
1263 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1264 if (ret < 0) {
1265 pr_err("%s: AFE enable Unreg. rtproxy_event failed %d\n",
1266 __func__, ret);
1267 ret = -EINVAL;
1268 return ret;
1269 }
1270
1271 ret = wait_event_timeout(this_afe.wait,
1272 (atomic_read(&this_afe.state) == 0),
1273 msecs_to_jiffies(TIMEOUT_MS));
1274 if (!ret) {
1275 pr_err("%s: wait_event timeout\n", __func__);
1276 ret = -EINVAL;
1277 return ret;
1278 }
1279 return 0;
1280}
1281
1282int afe_rt_proxy_port_write(u32 buf_addr_p, int bytes)
1283{
1284 int ret = 0;
1285 struct afe_cmd_rtport_wr afecmd_wr;
1286
1287 if (this_afe.apr == NULL) {
1288 pr_err("%s:register to AFE is not done\n", __func__);
1289 ret = -ENODEV;
1290 return ret;
1291 }
1292 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1293 buf_addr_p, bytes);
1294
1295 afecmd_wr.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1296 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1297 afecmd_wr.hdr.pkt_size = sizeof(afecmd_wr);
1298 afecmd_wr.hdr.src_port = 0;
1299 afecmd_wr.hdr.dest_port = 0;
1300 afecmd_wr.hdr.token = 0;
1301 afecmd_wr.hdr.opcode = AFE_SERVICE_CMD_RTPORT_WR;
1302 afecmd_wr.buf_addr = (uint32_t)buf_addr_p;
1303 afecmd_wr.port_id = RT_PROXY_PORT_001_TX;
1304 afecmd_wr.bytes_avail = bytes;
1305 afecmd_wr.rsvd = 0;
1306
1307 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_wr);
1308 if (ret < 0) {
1309 pr_err("%s: AFE rtproxy write to port 0x%x failed %d\n",
1310 __func__, afecmd_wr.port_id, ret);
1311 ret = -EINVAL;
1312 return ret;
1313 }
1314 return 0;
1315
1316}
1317
1318int afe_rt_proxy_port_read(u32 buf_addr_p, int bytes)
1319{
1320 int ret = 0;
1321 struct afe_cmd_rtport_rd afecmd_rd;
1322
1323 if (this_afe.apr == NULL) {
1324 pr_err("%s: register to AFE is not done\n", __func__);
1325 ret = -ENODEV;
1326 return ret;
1327 }
1328 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1329 buf_addr_p, bytes);
1330
1331 afecmd_rd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1332 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1333 afecmd_rd.hdr.pkt_size = sizeof(afecmd_rd);
1334 afecmd_rd.hdr.src_port = 0;
1335 afecmd_rd.hdr.dest_port = 0;
1336 afecmd_rd.hdr.token = 0;
1337 afecmd_rd.hdr.opcode = AFE_SERVICE_CMD_RTPORT_RD;
1338 afecmd_rd.buf_addr = (uint32_t)buf_addr_p;
1339 afecmd_rd.port_id = RT_PROXY_PORT_001_RX;
1340 afecmd_rd.bytes_avail = bytes;
1341 afecmd_rd.rsvd = 0;
1342
1343 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_rd);
1344 if (ret < 0) {
1345 pr_err("%s: AFE rtproxy read cmd to port 0x%x failed %d\n",
1346 __func__, afecmd_rd.port_id, ret);
1347 ret = -EINVAL;
1348 return ret;
1349 }
1350 return 0;
1351}
1352
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001353#ifdef CONFIG_DEBUG_FS
1354static struct dentry *debugfs_afelb;
1355static struct dentry *debugfs_afelb_gain;
1356
1357static int afe_debug_open(struct inode *inode, struct file *file)
1358{
1359 file->private_data = inode->i_private;
1360 pr_info("debug intf %s\n", (char *) file->private_data);
1361 return 0;
1362}
1363
1364static int afe_get_parameters(char *buf, long int *param1, int num_of_par)
1365{
1366 char *token;
1367 int base, cnt;
1368
1369 token = strsep(&buf, " ");
1370
1371 for (cnt = 0; cnt < num_of_par; cnt++) {
1372 if (token != NULL) {
1373 if ((token[1] == 'x') || (token[1] == 'X'))
1374 base = 16;
1375 else
1376 base = 10;
1377
1378 if (strict_strtoul(token, base, &param1[cnt]) != 0)
1379 return -EINVAL;
1380
1381 token = strsep(&buf, " ");
1382 } else
1383 return -EINVAL;
1384 }
1385 return 0;
1386}
1387#define AFE_LOOPBACK_ON (1)
1388#define AFE_LOOPBACK_OFF (0)
1389static ssize_t afe_debug_write(struct file *filp,
1390 const char __user *ubuf, size_t cnt, loff_t *ppos)
1391{
1392 char *lb_str = filp->private_data;
1393 char lbuf[32];
1394 int rc;
1395 unsigned long param[5];
1396
1397 if (cnt > sizeof(lbuf) - 1)
1398 return -EINVAL;
1399
1400 rc = copy_from_user(lbuf, ubuf, cnt);
1401 if (rc)
1402 return -EFAULT;
1403
1404 lbuf[cnt] = '\0';
1405
1406 if (!strcmp(lb_str, "afe_loopback")) {
1407 rc = afe_get_parameters(lbuf, param, 3);
1408 if (!rc) {
1409 pr_info("%s %lu %lu %lu\n", lb_str, param[0], param[1],
1410 param[2]);
1411
1412 if ((param[0] != AFE_LOOPBACK_ON) && (param[0] !=
1413 AFE_LOOPBACK_OFF)) {
1414 pr_err("%s: Error, parameter 0 incorrect\n",
1415 __func__);
1416 rc = -EINVAL;
1417 goto afe_error;
1418 }
1419 if ((afe_validate_port(param[1]) < 0) ||
1420 (afe_validate_port(param[2])) < 0) {
1421 pr_err("%s: Error, invalid afe port\n",
1422 __func__);
1423 }
1424 if (this_afe.apr == NULL) {
1425 pr_err("%s: Error, AFE not opened\n", __func__);
1426 rc = -EINVAL;
1427 } else {
1428 rc = afe_loopback(param[0], param[1], param[2]);
1429 }
1430 } else {
1431 pr_err("%s: Error, invalid parameters\n", __func__);
1432 rc = -EINVAL;
1433 }
1434
1435 } else if (!strcmp(lb_str, "afe_loopback_gain")) {
1436 rc = afe_get_parameters(lbuf, param, 2);
1437 if (!rc) {
1438 pr_info("%s %lu %lu\n", lb_str, param[0], param[1]);
1439
1440 if (afe_validate_port(param[0]) < 0) {
1441 pr_err("%s: Error, invalid afe port\n",
1442 __func__);
1443 rc = -EINVAL;
1444 goto afe_error;
1445 }
1446
1447 if (param[1] < 0 || param[1] > 100) {
1448 pr_err("%s: Error, volume shoud be 0 to 100"
1449 " percentage param = %lu\n",
1450 __func__, param[1]);
1451 rc = -EINVAL;
1452 goto afe_error;
1453 }
1454
1455 param[1] = (Q6AFE_MAX_VOLUME * param[1]) / 100;
1456
1457 if (this_afe.apr == NULL) {
1458 pr_err("%s: Error, AFE not opened\n", __func__);
1459 rc = -EINVAL;
1460 } else {
1461 rc = afe_loopback_gain(param[0], param[1]);
1462 }
1463 } else {
1464 pr_err("%s: Error, invalid parameters\n", __func__);
1465 rc = -EINVAL;
1466 }
1467 }
1468
1469afe_error:
1470 if (rc == 0)
1471 rc = cnt;
1472 else
1473 pr_err("%s: rc = %d\n", __func__, rc);
1474
1475 return rc;
1476}
1477
1478static const struct file_operations afe_debug_fops = {
1479 .open = afe_debug_open,
1480 .write = afe_debug_write
1481};
1482#endif
1483int afe_sidetone(u16 tx_port_id, u16 rx_port_id, u16 enable, uint16_t gain)
1484{
1485 struct afe_port_sidetone_command cmd_sidetone;
1486 int ret = 0;
1487
1488 pr_info("%s: tx_port_id:%d rx_port_id:%d enable:%d gain:%d\n", __func__,
1489 tx_port_id, rx_port_id, enable, gain);
1490 cmd_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1491 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1492 cmd_sidetone.hdr.pkt_size = sizeof(cmd_sidetone);
1493 cmd_sidetone.hdr.src_port = 0;
1494 cmd_sidetone.hdr.dest_port = 0;
1495 cmd_sidetone.hdr.token = 0;
1496 cmd_sidetone.hdr.opcode = AFE_PORT_CMD_SIDETONE_CTL;
1497 cmd_sidetone.tx_port_id = tx_port_id;
1498 cmd_sidetone.rx_port_id = rx_port_id;
1499 cmd_sidetone.gain = gain;
1500 cmd_sidetone.enable = enable;
1501
1502 atomic_set(&this_afe.state, 1);
1503 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_sidetone);
1504 if (ret < 0) {
1505 pr_err("%s: AFE sidetone failed for tx_port:%d rx_port:%d\n",
1506 __func__, tx_port_id, rx_port_id);
1507 ret = -EINVAL;
1508 goto fail_cmd;
1509 }
1510
1511 ret = wait_event_timeout(this_afe.wait,
1512 (atomic_read(&this_afe.state) == 0),
1513 msecs_to_jiffies(TIMEOUT_MS));
1514 if (ret < 0) {
1515 pr_err("%s: wait_event timeout\n", __func__);
1516 ret = -EINVAL;
1517 goto fail_cmd;
1518 }
1519 return 0;
1520fail_cmd:
1521 return ret;
1522}
1523
1524int afe_port_stop_nowait(int port_id)
1525{
1526 struct afe_port_stop_command stop;
1527 int ret = 0;
1528
1529 if (this_afe.apr == NULL) {
1530 pr_err("AFE is already closed\n");
1531 ret = -EINVAL;
1532 goto fail_cmd;
1533 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001534 pr_debug("%s: port_id=%d\n", __func__, port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301535 port_id = afe_convert_virtual_to_portid(port_id);
1536
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001537 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1538 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1539 stop.hdr.pkt_size = sizeof(stop);
1540 stop.hdr.src_port = 0;
1541 stop.hdr.dest_port = 0;
1542 stop.hdr.token = 0;
1543 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1544 stop.port_id = port_id;
1545 stop.reserved = 0;
1546
1547 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1548
1549 if (ret == -ENETRESET) {
1550 pr_info("%s: Need to reset, calling APR deregister", __func__);
1551 return apr_deregister(this_afe.apr);
1552 } else if (IS_ERR_VALUE(ret)) {
1553 pr_err("%s: AFE close failed\n", __func__);
1554 ret = -EINVAL;
1555 }
1556
1557fail_cmd:
1558 return ret;
1559
1560}
1561
1562int afe_close(int port_id)
1563{
1564 struct afe_port_stop_command stop;
1565 int ret = 0;
1566
1567 if (this_afe.apr == NULL) {
1568 pr_err("AFE is already closed\n");
1569 ret = -EINVAL;
1570 goto fail_cmd;
1571 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001572 pr_debug("%s: port_id=%d\n", __func__, port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301573 port_id = afe_convert_virtual_to_portid(port_id);
1574
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001575 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1576 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1577 stop.hdr.pkt_size = sizeof(stop);
1578 stop.hdr.src_port = 0;
1579 stop.hdr.dest_port = 0;
1580 stop.hdr.token = 0;
1581 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1582 stop.port_id = port_id;
1583 stop.reserved = 0;
1584
1585 atomic_set(&this_afe.state, 1);
1586 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1587
1588 if (ret == -ENETRESET) {
1589 pr_info("%s: Need to reset, calling APR deregister", __func__);
1590 return apr_deregister(this_afe.apr);
1591 }
1592
1593 if (ret < 0) {
1594 pr_err("%s: AFE close failed\n", __func__);
1595 ret = -EINVAL;
1596 goto fail_cmd;
1597 }
1598
1599 ret = wait_event_timeout(this_afe.wait,
1600 (atomic_read(&this_afe.state) == 0),
1601 msecs_to_jiffies(TIMEOUT_MS));
1602 if (!ret) {
1603 pr_err("%s: wait_event timeout\n", __func__);
1604 ret = -EINVAL;
1605 goto fail_cmd;
1606 }
1607fail_cmd:
1608 return ret;
1609}
1610
1611static int __init afe_init(void)
1612{
1613 init_waitqueue_head(&this_afe.wait);
1614 atomic_set(&this_afe.state, 0);
1615 atomic_set(&this_afe.status, 0);
1616 this_afe.apr = NULL;
1617#ifdef CONFIG_DEBUG_FS
1618 debugfs_afelb = debugfs_create_file("afe_loopback",
1619 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback",
1620 &afe_debug_fops);
1621
1622 debugfs_afelb_gain = debugfs_create_file("afe_loopback_gain",
1623 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback_gain",
1624 &afe_debug_fops);
1625
1626
1627#endif
1628 return 0;
1629}
1630
1631static void __exit afe_exit(void)
1632{
Ben Rombergerb7603232011-11-23 17:16:27 -08001633 int i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001634#ifdef CONFIG_DEBUG_FS
1635 if (debugfs_afelb)
1636 debugfs_remove(debugfs_afelb);
1637 if (debugfs_afelb_gain)
1638 debugfs_remove(debugfs_afelb_gain);
1639#endif
Ben Rombergerb7603232011-11-23 17:16:27 -08001640 for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
Ben Romberger9e792562012-02-24 12:29:01 -08001641 if (afe_cal_addr[i].cal_paddr != 0)
1642 afe_cmd_memory_unmap_nowait(
1643 afe_cal_addr[i].cal_paddr);
Ben Rombergerb7603232011-11-23 17:16:27 -08001644 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001645}
1646
1647device_initcall(afe_init);
1648__exitcall(afe_exit);