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