blob: 51ef359d7a4187142b03ed83697c3a8900ed3ae2 [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:
Kiran Kandifd30c892012-05-21 23:03:26 -0700150 case SLIMBUS_2_RX:
Neema Shetty74131ac2012-05-09 13:35:26 -0700151 case SLIMBUS_3_RX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700152 case INT_BT_SCO_RX:
153 case INT_BT_A2DP_RX:
154 case INT_FM_RX:
155 case VOICE_PLAYBACK_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530156 case RT_PROXY_PORT_001_RX:
Helen Zeng8f925502012-03-05 16:50:17 -0800157 case SLIMBUS_4_RX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700158 ret = MSM_AFE_PORT_TYPE_RX;
159 break;
160
161 case PRIMARY_I2S_TX:
162 case PCM_TX:
163 case SECONDARY_I2S_TX:
164 case MI2S_TX:
165 case DIGI_MIC_TX:
166 case VOICE_RECORD_TX:
167 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800168 case SLIMBUS_1_TX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700169 case SLIMBUS_2_TX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700170 case INT_FM_TX:
171 case VOICE_RECORD_RX:
172 case INT_BT_SCO_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530173 case RT_PROXY_PORT_001_TX:
Helen Zeng8f925502012-03-05 16:50:17 -0800174 case SLIMBUS_4_TX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700175 ret = MSM_AFE_PORT_TYPE_TX;
176 break;
177
178 default:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800179 pr_err("%s: invalid port id %d\n", __func__, port_id);
Neema Shettyfeea7742011-09-11 12:30:36 -0700180 ret = -EINVAL;
181 }
182
183 return ret;
184}
185
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700186int afe_validate_port(u16 port_id)
187{
188 int ret;
189
190 switch (port_id) {
191 case PRIMARY_I2S_RX:
192 case PRIMARY_I2S_TX:
193 case PCM_RX:
194 case PCM_TX:
195 case SECONDARY_I2S_RX:
196 case SECONDARY_I2S_TX:
197 case MI2S_RX:
198 case MI2S_TX:
199 case HDMI_RX:
200 case RSVD_2:
201 case RSVD_3:
202 case DIGI_MIC_TX:
203 case VOICE_RECORD_RX:
204 case VOICE_RECORD_TX:
205 case VOICE_PLAYBACK_TX:
206 case SLIMBUS_0_RX:
207 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800208 case SLIMBUS_1_RX:
209 case SLIMBUS_1_TX:
Kiran Kandifd30c892012-05-21 23:03:26 -0700210 case SLIMBUS_2_RX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700211 case SLIMBUS_2_TX:
Neema Shetty74131ac2012-05-09 13:35:26 -0700212 case SLIMBUS_3_RX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700213 case INT_BT_SCO_RX:
214 case INT_BT_SCO_TX:
215 case INT_BT_A2DP_RX:
216 case INT_FM_RX:
217 case INT_FM_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530218 case RT_PROXY_PORT_001_RX:
219 case RT_PROXY_PORT_001_TX:
Helen Zeng8f925502012-03-05 16:50:17 -0800220 case SLIMBUS_4_RX:
221 case SLIMBUS_4_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700222 {
223 ret = 0;
224 break;
225 }
226
227 default:
228 ret = -EINVAL;
229 }
230
231 return ret;
232}
233
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530234int afe_convert_virtual_to_portid(u16 port_id)
235{
236 int ret;
237
238 /* if port_id is virtual, convert to physical..
239 * if port_id is already physical, return physical
240 */
241 if (afe_validate_port(port_id) < 0) {
242 if (port_id == RT_PROXY_DAI_001_RX ||
243 port_id == RT_PROXY_DAI_001_TX ||
244 port_id == RT_PROXY_DAI_002_RX ||
245 port_id == RT_PROXY_DAI_002_TX)
246 ret = VIRTUAL_ID_TO_PORTID(port_id);
247 else
248 ret = -EINVAL;
249 } else
250 ret = port_id;
251
252 return ret;
253}
254
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700255int afe_get_port_index(u16 port_id)
256{
257 switch (port_id) {
258 case PRIMARY_I2S_RX: return IDX_PRIMARY_I2S_RX;
259 case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
260 case PCM_RX: return IDX_PCM_RX;
261 case PCM_TX: return IDX_PCM_TX;
262 case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
263 case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
264 case MI2S_RX: return IDX_MI2S_RX;
265 case MI2S_TX: return IDX_MI2S_TX;
266 case HDMI_RX: return IDX_HDMI_RX;
267 case RSVD_2: return IDX_RSVD_2;
268 case RSVD_3: return IDX_RSVD_3;
269 case DIGI_MIC_TX: return IDX_DIGI_MIC_TX;
270 case VOICE_RECORD_RX: return IDX_VOICE_RECORD_RX;
271 case VOICE_RECORD_TX: return IDX_VOICE_RECORD_TX;
272 case VOICE_PLAYBACK_TX: return IDX_VOICE_PLAYBACK_TX;
273 case SLIMBUS_0_RX: return IDX_SLIMBUS_0_RX;
274 case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
Neema Shetty3c9d2862012-03-11 01:25:32 -0800275 case SLIMBUS_1_RX: return IDX_SLIMBUS_1_RX;
276 case SLIMBUS_1_TX: return IDX_SLIMBUS_1_TX;
Kiran Kandifd30c892012-05-21 23:03:26 -0700277 case SLIMBUS_2_RX: return IDX_SLIMBUS_2_RX;
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700278 case SLIMBUS_2_TX: return IDX_SLIMBUS_2_TX;
Neema Shetty74131ac2012-05-09 13:35:26 -0700279 case SLIMBUS_3_RX: return IDX_SLIMBUS_3_RX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700280 case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
281 case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
282 case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
283 case INT_FM_RX: return IDX_INT_FM_RX;
284 case INT_FM_TX: return IDX_INT_FM_TX;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530285 case RT_PROXY_PORT_001_RX: return IDX_RT_PROXY_PORT_001_RX;
286 case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
Helen Zeng8f925502012-03-05 16:50:17 -0800287 case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX;
288 case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700289
290 default: return -EINVAL;
291 }
292}
293
294int afe_sizeof_cfg_cmd(u16 port_id)
295{
296 int ret_size;
297 switch (port_id) {
298 case PRIMARY_I2S_RX:
299 case PRIMARY_I2S_TX:
300 case SECONDARY_I2S_RX:
301 case SECONDARY_I2S_TX:
302 case MI2S_RX:
303 case MI2S_TX:
304 ret_size = SIZEOF_CFG_CMD(afe_port_mi2s_cfg);
305 break;
306 case HDMI_RX:
Kiran Kandi5e809b02012-01-31 00:24:33 -0800307 ret_size = SIZEOF_CFG_CMD(afe_port_hdmi_multi_ch_cfg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700308 break;
309 case SLIMBUS_0_RX:
310 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800311 case SLIMBUS_1_RX:
312 case SLIMBUS_1_TX:
Kiran Kandifd30c892012-05-21 23:03:26 -0700313 case SLIMBUS_2_RX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700314 case SLIMBUS_2_TX:
Neema Shetty74131ac2012-05-09 13:35:26 -0700315 case SLIMBUS_3_RX:
Helen Zeng8f925502012-03-05 16:50:17 -0800316 case SLIMBUS_4_RX:
317 case SLIMBUS_4_TX:
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800318 ret_size = SIZEOF_CFG_CMD(afe_port_slimbus_sch_cfg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700319 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530320 case RT_PROXY_PORT_001_RX:
321 case RT_PROXY_PORT_001_TX:
322 ret_size = SIZEOF_CFG_CMD(afe_port_rtproxy_cfg);
323 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700324 case PCM_RX:
325 case PCM_TX:
326 default:
327 ret_size = SIZEOF_CFG_CMD(afe_port_pcm_cfg);
328 break;
329 }
330 return ret_size;
331}
332
Jay Wang6a305432011-08-05 16:01:54 -0700333int afe_q6_interface_prepare(void)
334{
335 int ret = 0;
336
337 pr_debug("%s:", __func__);
338
339 if (this_afe.apr == NULL) {
340 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
341 0xFFFFFFFF, &this_afe);
342 pr_debug("%s: Register AFE\n", __func__);
343 if (this_afe.apr == NULL) {
344 pr_err("%s: Unable to register AFE\n", __func__);
345 ret = -ENODEV;
346 }
347 }
348 return ret;
349}
350
Ben Rombergerb7603232011-11-23 17:16:27 -0800351static void afe_send_cal_block(int32_t path, u16 port_id)
352{
353 int result = 0;
354 struct acdb_cal_block cal_block;
355 struct afe_port_cmd_set_param_no_payload afe_cal;
356 pr_debug("%s: path %d\n", __func__, path);
357
358 get_afe_cal(path, &cal_block);
359 if (cal_block.cal_size <= 0) {
360 pr_debug("%s: No AFE cal to send!\n", __func__);
361 goto done;
362 }
363
Ben Romberger9e792562012-02-24 12:29:01 -0800364 if ((afe_cal_addr[path].cal_paddr != cal_block.cal_paddr) ||
365 (cal_block.cal_size > afe_cal_addr[path].cal_size)) {
366 if (afe_cal_addr[path].cal_paddr != 0)
367 afe_cmd_memory_unmap_nowait(
368 afe_cal_addr[path].cal_paddr);
369
Ben Rombergerb7603232011-11-23 17:16:27 -0800370 afe_cmd_memory_map_nowait(cal_block.cal_paddr,
371 cal_block.cal_size);
Ben Romberger9e792562012-02-24 12:29:01 -0800372 afe_cal_addr[path].cal_paddr = cal_block.cal_paddr;
373 afe_cal_addr[path].cal_size = cal_block.cal_size;
Ben Rombergerb7603232011-11-23 17:16:27 -0800374 }
375
376 afe_cal.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
377 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
378 afe_cal.hdr.pkt_size = sizeof(afe_cal);
379 afe_cal.hdr.src_port = 0;
380 afe_cal.hdr.dest_port = 0;
381 afe_cal.hdr.token = 0;
382 afe_cal.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
383 afe_cal.port_id = port_id;
384 afe_cal.payload_size = cal_block.cal_size;
385 afe_cal.payload_address = cal_block.cal_paddr;
386
387 pr_debug("%s: AFE cal sent for device port = %d, path = %d, "
388 "cal size = %d, cal addr = 0x%x\n", __func__,
389 port_id, path, cal_block.cal_size, cal_block.cal_paddr);
390
391 result = apr_send_pkt(this_afe.apr, (uint32_t *) &afe_cal);
392 if (result < 0) {
393 pr_err("%s: AFE cal for port %d failed\n",
394 __func__, port_id);
395 }
396
397 pr_debug("%s: AFE cal sent for path %d device!\n", __func__, path);
398done:
399 return;
400}
401
402void afe_send_cal(u16 port_id)
403{
404 pr_debug("%s\n", __func__);
405
406 if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX)
407 afe_send_cal_block(TX_CAL, port_id);
408 else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX)
409 afe_send_cal_block(RX_CAL, port_id);
410}
411
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700412int afe_port_start_nowait(u16 port_id, union afe_port_config *afe_config,
413 u32 rate) /* This function is no blocking */
414{
415 struct afe_port_start_command start;
416 struct afe_audioif_config_command config;
417 int ret;
418
419 if (!afe_config) {
420 pr_err("%s: Error, no configuration data\n", __func__);
421 ret = -EINVAL;
422 return ret;
423 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -0800424 pr_debug("%s: %d %d\n", __func__, port_id, rate);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700425
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530426 if ((port_id == RT_PROXY_DAI_001_RX) ||
427 (port_id == RT_PROXY_DAI_002_TX))
428 return -EINVAL;
429 if ((port_id == RT_PROXY_DAI_002_RX) ||
430 (port_id == RT_PROXY_DAI_001_TX))
431 port_id = VIRTUAL_ID_TO_PORTID(port_id);
432
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700433 if (this_afe.apr == NULL) {
Jay Wang6a305432011-08-05 16:01:54 -0700434 pr_err("%s: AFE APR is not registered\n", __func__);
435 ret = -ENODEV;
436 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700437 }
Kiran Kandi5e809b02012-01-31 00:24:33 -0800438
439 if (port_id == HDMI_RX) {
440 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700441 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
Kiran Kandi5e809b02012-01-31 00:24:33 -0800442 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
443 config.hdr.src_port = 0;
444 config.hdr.dest_port = 0;
445 config.hdr.token = 0;
446 config.hdr.opcode = AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG;
447 } else {
448
449 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
450 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
451 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
452 config.hdr.src_port = 0;
453 config.hdr.dest_port = 0;
454 config.hdr.token = 0;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800455 switch (port_id) {
456 case SLIMBUS_0_RX:
457 case SLIMBUS_0_TX:
458 case SLIMBUS_1_RX:
459 case SLIMBUS_1_TX:
460 case SLIMBUS_2_RX:
461 case SLIMBUS_2_TX:
462 case SLIMBUS_3_RX:
463 case SLIMBUS_3_TX:
464 case SLIMBUS_4_RX:
465 case SLIMBUS_4_TX:
466 config.hdr.opcode = AFE_PORT_AUDIO_SLIM_SCH_CONFIG;
467 break;
Kuirong Wanga36f2882012-04-02 19:45:26 -0700468 case MI2S_TX:
469 case MI2S_RX:
470 case SECONDARY_I2S_RX:
471 case SECONDARY_I2S_TX:
472 case PRIMARY_I2S_RX:
473 case PRIMARY_I2S_TX:
474 /* AFE_PORT_CMD_I2S_CONFIG command is not supported
475 * in the LPASS EL 1.0. So we have to distiguish
476 * which AFE command, AFE_PORT_CMD_I2S_CONFIG or
477 * AFE_PORT_AUDIO_IF_CONFIG to use. If the format
478 * is L-PCM, the AFE_PORT_AUDIO_IF_CONFIG is used
479 * to make the backward compatible.
480 */
481 pr_debug("%s: afe_config->mi2s.format = %d\n", __func__,
482 afe_config->mi2s.format);
483 if (afe_config->mi2s.format == MSM_AFE_I2S_FORMAT_LPCM)
484 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
485 else
486 config.hdr.opcode = AFE_PORT_CMD_I2S_CONFIG;
487 break;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800488 default:
489 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
490 break;
491 }
Kiran Kandi5e809b02012-01-31 00:24:33 -0800492 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700493
494 if (afe_validate_port(port_id) < 0) {
495
496 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
497 port_id);
498 ret = -EINVAL;
499 goto fail_cmd;
500 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700501 config.port_id = port_id;
502 config.port = *afe_config;
503
504 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
505 if (ret < 0) {
506 pr_err("%s: AFE enable for port %d failed\n", __func__,
507 port_id);
508 ret = -EINVAL;
509 goto fail_cmd;
510 }
Ben Rombergerb7603232011-11-23 17:16:27 -0800511
512 /* send AFE cal */
513 afe_send_cal(port_id);
514
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700515 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
516 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
517 start.hdr.pkt_size = sizeof(start);
518 start.hdr.src_port = 0;
519 start.hdr.dest_port = 0;
520 start.hdr.token = 0;
521 start.hdr.opcode = AFE_PORT_CMD_START;
522 start.port_id = port_id;
523 start.gain = 0x2000;
524 start.sample_rate = rate;
525
526 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
527
528 if (IS_ERR_VALUE(ret)) {
529 pr_err("%s: AFE enable for port %d failed\n", __func__,
530 port_id);
531 ret = -EINVAL;
532 goto fail_cmd;
533 }
534
535 if (this_afe.task != current)
536 this_afe.task = current;
537
538 pr_debug("task_name = %s pid = %d\n",
539 this_afe.task->comm, this_afe.task->pid);
540 return 0;
541
542fail_cmd:
543 return ret;
544}
545
546int afe_open(u16 port_id, union afe_port_config *afe_config, int rate)
547{
548 struct afe_port_start_command start;
549 struct afe_audioif_config_command config;
550 int ret = 0;
551
552 if (!afe_config) {
553 pr_err("%s: Error, no configuration data\n", __func__);
554 ret = -EINVAL;
555 return ret;
556 }
557
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800558 pr_debug("%s: %d %d\n", __func__, port_id, rate);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700559
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530560 if ((port_id == RT_PROXY_DAI_001_RX) ||
561 (port_id == RT_PROXY_DAI_002_TX))
562 return -EINVAL;
563 if ((port_id == RT_PROXY_DAI_002_RX) ||
564 (port_id == RT_PROXY_DAI_001_TX))
565 port_id = VIRTUAL_ID_TO_PORTID(port_id);
566
Jay Wang6a305432011-08-05 16:01:54 -0700567 ret = afe_q6_interface_prepare();
568 if (ret != 0)
569 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700570
571 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
572 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
573 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
574 config.hdr.src_port = 0;
575 config.hdr.dest_port = 0;
576 config.hdr.token = 0;
Kuirong Wanga36f2882012-04-02 19:45:26 -0700577 switch (port_id) {
578 case SLIMBUS_0_RX:
579 case SLIMBUS_0_TX:
580 case SLIMBUS_1_RX:
581 case SLIMBUS_1_TX:
582 case SLIMBUS_2_RX:
583 case SLIMBUS_2_TX:
584 case SLIMBUS_3_RX:
585 case SLIMBUS_3_TX:
586 case SLIMBUS_4_RX:
587 case SLIMBUS_4_TX:
588 config.hdr.opcode = AFE_PORT_AUDIO_SLIM_SCH_CONFIG;
589 break;
590 case MI2S_TX:
591 case MI2S_RX:
592 case SECONDARY_I2S_RX:
593 case SECONDARY_I2S_TX:
594 case PRIMARY_I2S_RX:
595 case PRIMARY_I2S_TX:
596 /* AFE_PORT_CMD_I2S_CONFIG command is not supported
597 * in the LPASS EL 1.0. So we have to distiguish
598 * which AFE command, AFE_PORT_CMD_I2S_CONFIG or
599 * AFE_PORT_AUDIO_IF_CONFIG to use. If the format
600 * is L-PCM, the AFE_PORT_AUDIO_IF_CONFIG is used
601 * to make the backward compatible.
602 */
603 pr_debug("%s: afe_config->mi2s.format = %d\n", __func__,
604 afe_config->mi2s.format);
605 if (afe_config->mi2s.format == MSM_AFE_I2S_FORMAT_LPCM)
606 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
607 else
608 config.hdr.opcode = AFE_PORT_CMD_I2S_CONFIG;
609 break;
610 default:
611 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
612 break;
613 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700614
615 if (afe_validate_port(port_id) < 0) {
616
617 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
618 port_id);
619 ret = -EINVAL;
620 goto fail_cmd;
621 }
622
623 config.port_id = port_id;
624 config.port = *afe_config;
625
626 atomic_set(&this_afe.state, 1);
627 atomic_set(&this_afe.status, 0);
628 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
629 if (ret < 0) {
630 pr_err("%s: AFE enable for port %d failed\n", __func__,
631 port_id);
632 ret = -EINVAL;
633 goto fail_cmd;
634 }
635
636 ret = wait_event_timeout(this_afe.wait,
637 (atomic_read(&this_afe.state) == 0),
638 msecs_to_jiffies(TIMEOUT_MS));
639 if (!ret) {
640 pr_err("%s: wait_event timeout\n", __func__);
641 ret = -EINVAL;
642 goto fail_cmd;
643 }
644 if (atomic_read(&this_afe.status) != 0) {
645 pr_err("%s: config cmd failed\n", __func__);
646 ret = -EINVAL;
647 goto fail_cmd;
648 }
649 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
650 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
651 start.hdr.pkt_size = sizeof(start);
652 start.hdr.src_port = 0;
653 start.hdr.dest_port = 0;
654 start.hdr.token = 0;
655 start.hdr.opcode = AFE_PORT_CMD_START;
656 start.port_id = port_id;
657 start.gain = 0x2000;
658 start.sample_rate = rate;
659
660 atomic_set(&this_afe.state, 1);
661 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
662 if (ret < 0) {
663 pr_err("%s: AFE enable for port %d failed\n", __func__,
664 port_id);
665 ret = -EINVAL;
666 goto fail_cmd;
667 }
668 ret = wait_event_timeout(this_afe.wait,
669 (atomic_read(&this_afe.state) == 0),
670 msecs_to_jiffies(TIMEOUT_MS));
671 if (!ret) {
672 pr_err("%s: wait_event timeout\n", __func__);
673 ret = -EINVAL;
674 goto fail_cmd;
675 }
676
677 if (this_afe.task != current)
678 this_afe.task = current;
679
680 pr_debug("task_name = %s pid = %d\n",
681 this_afe.task->comm, this_afe.task->pid);
682 return 0;
683fail_cmd:
684 return ret;
685}
686
Neema Shetty74131ac2012-05-09 13:35:26 -0700687int afe_loopback(u16 enable, u16 dst_port, u16 src_port)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700688{
689 struct afe_loopback_command lb_cmd;
690 int ret = 0;
Jay Wang6a305432011-08-05 16:01:54 -0700691
692 ret = afe_q6_interface_prepare();
693 if (ret != 0)
694 return ret;
695
Neema Shetty74131ac2012-05-09 13:35:26 -0700696 if ((afe_get_port_type(dst_port) == MSM_AFE_PORT_TYPE_RX) &&
697 (afe_get_port_type(src_port) == MSM_AFE_PORT_TYPE_RX))
698 return afe_loopback_cfg(enable, dst_port, src_port,
699 LB_MODE_EC_REF_VOICE_AUDIO);
700
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700701 lb_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
702 APR_HDR_LEN(20), APR_PKT_VER);
703 lb_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
704 sizeof(lb_cmd) - APR_HDR_SIZE);
705 lb_cmd.hdr.src_port = 0;
706 lb_cmd.hdr.dest_port = 0;
707 lb_cmd.hdr.token = 0;
708 lb_cmd.hdr.opcode = AFE_PORT_CMD_LOOPBACK;
Neema Shetty74131ac2012-05-09 13:35:26 -0700709 lb_cmd.tx_port_id = src_port;
710 lb_cmd.rx_port_id = dst_port;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700711 lb_cmd.mode = 0xFFFF;
712 lb_cmd.enable = (enable ? 1 : 0);
713 atomic_set(&this_afe.state, 1);
714
715 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &lb_cmd);
716 if (ret < 0) {
717 pr_err("%s: AFE loopback failed\n", __func__);
718 ret = -EINVAL;
719 goto done;
720 }
721 ret = wait_event_timeout(this_afe.wait,
722 (atomic_read(&this_afe.state) == 0),
723 msecs_to_jiffies(TIMEOUT_MS));
724 if (!ret) {
725 pr_err("%s: wait_event timeout\n", __func__);
726 ret = -EINVAL;
727 }
728done:
729 return ret;
730}
731
Neema Shetty74131ac2012-05-09 13:35:26 -0700732int afe_loopback_cfg(u16 enable, u16 dst_port, u16 src_port, u16 mode)
733{
734 struct afe_port_cmd_set_param lp_cfg;
735 int ret = 0;
736
737 ret = afe_q6_interface_prepare();
738 if (ret != 0)
739 return ret;
740
741 pr_debug("%s: src_port %d, dst_port %d\n",
742 __func__, src_port, dst_port);
743
744 lp_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
745 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
746 lp_cfg.hdr.pkt_size = sizeof(lp_cfg);
747 lp_cfg.hdr.src_port = 0;
748 lp_cfg.hdr.dest_port = 0;
749 lp_cfg.hdr.token = 0;
750 lp_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
751
752 lp_cfg.port_id = src_port;
753 lp_cfg.payload_size = sizeof(struct afe_param_payload);
754 lp_cfg.payload_address = 0;
755
756 lp_cfg.payload.module_id = AFE_MODULE_LOOPBACK;
757 lp_cfg.payload.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
758 lp_cfg.payload.param_size = sizeof(struct afe_param_loopback_cfg);
759 lp_cfg.payload.reserved = 0;
760
761 lp_cfg.payload.param.loopback_cfg.loopback_cfg_minor_version =
762 AFE_API_VERSION_LOOPBACK_CONFIG;
763 lp_cfg.payload.param.loopback_cfg.dst_port_id = dst_port;
764 lp_cfg.payload.param.loopback_cfg.routing_mode = mode;
765 lp_cfg.payload.param.loopback_cfg.enable = enable;
766 lp_cfg.payload.param.loopback_cfg.reserved = 0;
767
768 atomic_set(&this_afe.state, 1);
769 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &lp_cfg);
770 if (ret < 0) {
771 pr_err("%s: AFE loopback config failed for src_port %d, dst_port %d\n",
772 __func__, src_port, dst_port);
773 ret = -EINVAL;
774 goto fail_cmd;
775 }
776
777 ret = wait_event_timeout(this_afe.wait,
778 (atomic_read(&this_afe.state) == 0),
779 msecs_to_jiffies(TIMEOUT_MS));
780 if (ret < 0) {
781 pr_err("%s: wait_event timeout\n", __func__);
782 ret = -EINVAL;
783 goto fail_cmd;
784 }
785 return 0;
786fail_cmd:
787 return ret;
788}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700789
790int afe_loopback_gain(u16 port_id, u16 volume)
791{
792 struct afe_port_cmd_set_param set_param;
793 int ret = 0;
794
795 if (this_afe.apr == NULL) {
Jayasena Sangaraboina82435032011-07-26 15:23:00 -0700796 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
797 0xFFFFFFFF, &this_afe);
798 pr_debug("%s: Register AFE\n", __func__);
799 if (this_afe.apr == NULL) {
800 pr_err("%s: Unable to register AFE\n", __func__);
801 ret = -ENODEV;
802 return ret;
803 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700804 }
805
806 if (afe_validate_port(port_id) < 0) {
807
808 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
809 port_id);
810 ret = -EINVAL;
811 goto fail_cmd;
812 }
813
814 /* RX ports numbers are even .TX ports numbers are odd. */
815 if (port_id % 2 == 0) {
816 pr_err("%s: Failed : afe loopback gain only for TX ports."
817 " port_id %d\n", __func__, port_id);
818 ret = -EINVAL;
819 goto fail_cmd;
820 }
821
822 pr_debug("%s: %d %hX\n", __func__, port_id, volume);
823
824 set_param.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
825 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
826 set_param.hdr.pkt_size = sizeof(set_param);
827 set_param.hdr.src_port = 0;
828 set_param.hdr.dest_port = 0;
829 set_param.hdr.token = 0;
830 set_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
831
832 set_param.port_id = port_id;
833 set_param.payload_size = sizeof(struct afe_param_payload);
834 set_param.payload_address = 0;
835
836 set_param.payload.module_id = AFE_MODULE_ID_PORT_INFO;
837 set_param.payload.param_id = AFE_PARAM_ID_LOOPBACK_GAIN;
838 set_param.payload.param_size = sizeof(struct afe_param_loopback_gain);
839 set_param.payload.reserved = 0;
840
841 set_param.payload.param.loopback_gain.gain = volume;
842 set_param.payload.param.loopback_gain.reserved = 0;
843
844 atomic_set(&this_afe.state, 1);
845 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_param);
846 if (ret < 0) {
847 pr_err("%s: AFE param set failed for port %d\n",
848 __func__, port_id);
849 ret = -EINVAL;
850 goto fail_cmd;
851 }
852
853 ret = wait_event_timeout(this_afe.wait,
854 (atomic_read(&this_afe.state) == 0),
855 msecs_to_jiffies(TIMEOUT_MS));
856 if (ret < 0) {
857 pr_err("%s: wait_event timeout\n", __func__);
858 ret = -EINVAL;
859 goto fail_cmd;
860 }
861 return 0;
862fail_cmd:
863 return ret;
864}
865
Laxminath Kasam885f5102011-07-14 10:20:21 +0530866int afe_apply_gain(u16 port_id, u16 gain)
867{
868 struct afe_port_gain_command set_gain;
869 int ret = 0;
870
871 if (this_afe.apr == NULL) {
872 pr_err("%s: AFE is not opened\n", __func__);
873 ret = -EPERM;
874 goto fail_cmd;
875 }
876
877 if (afe_validate_port(port_id) < 0) {
878 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
879 port_id);
880 ret = -EINVAL;
881 goto fail_cmd;
882 }
883
884 /* RX ports numbers are even .TX ports numbers are odd. */
885 if (port_id % 2 == 0) {
886 pr_err("%s: Failed : afe apply gain only for TX ports."
887 " port_id %d\n", __func__, port_id);
888 ret = -EINVAL;
889 goto fail_cmd;
890 }
891
892 pr_debug("%s: %d %hX\n", __func__, port_id, gain);
893
894 set_gain.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
895 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
896 set_gain.hdr.pkt_size = sizeof(set_gain);
897 set_gain.hdr.src_port = 0;
898 set_gain.hdr.dest_port = 0;
899 set_gain.hdr.token = 0;
900 set_gain.hdr.opcode = AFE_PORT_CMD_APPLY_GAIN;
901
902 set_gain.port_id = port_id;
903 set_gain.gain = gain;
904
905 atomic_set(&this_afe.state, 1);
906 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_gain);
907 if (ret < 0) {
908 pr_err("%s: AFE Gain set failed for port %d\n",
909 __func__, port_id);
910 ret = -EINVAL;
911 goto fail_cmd;
912 }
913
914 ret = wait_event_timeout(this_afe.wait,
915 (atomic_read(&this_afe.state) == 0),
916 msecs_to_jiffies(TIMEOUT_MS));
917 if (ret < 0) {
918 pr_err("%s: wait_event timeout\n", __func__);
919 ret = -EINVAL;
920 goto fail_cmd;
921 }
922 return 0;
923fail_cmd:
924 return ret;
925}
Helen Zeng0705a5f2011-10-14 15:29:52 -0700926
927int afe_pseudo_port_start_nowait(u16 port_id)
928{
929 int ret = 0;
930 struct afe_pseudoport_start_command start;
931
932 pr_debug("%s: port_id=%d\n", __func__, port_id);
933 if (this_afe.apr == NULL) {
934 pr_err("%s: AFE APR is not registered\n", __func__);
935 return -ENODEV;
936 }
937
938
939 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
940 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
941 start.hdr.pkt_size = sizeof(start);
942 start.hdr.src_port = 0;
943 start.hdr.dest_port = 0;
944 start.hdr.token = 0;
945 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
946 start.port_id = port_id;
947 start.timing = 1;
948
949 atomic_set(&this_afe.state, 1);
950 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
951 if (ret < 0) {
952 pr_err("%s: AFE enable for port %d failed %d\n",
953 __func__, port_id, ret);
954 return -EINVAL;
955 }
956 return 0;
957}
958
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700959int afe_start_pseudo_port(u16 port_id)
960{
961 int ret = 0;
962 struct afe_pseudoport_start_command start;
963
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800964 pr_debug("%s: port_id=%d\n", __func__, port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700965
Jay Wang6a305432011-08-05 16:01:54 -0700966 ret = afe_q6_interface_prepare();
967 if (ret != 0)
968 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700969
970 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
971 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
972 start.hdr.pkt_size = sizeof(start);
973 start.hdr.src_port = 0;
974 start.hdr.dest_port = 0;
975 start.hdr.token = 0;
976 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
977 start.port_id = port_id;
978 start.timing = 1;
979
980 atomic_set(&this_afe.state, 1);
981 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
982 if (ret < 0) {
983 pr_err("%s: AFE enable for port %d failed %d\n",
984 __func__, port_id, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700985 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700986 }
987
988 ret = wait_event_timeout(this_afe.wait,
989 (atomic_read(&this_afe.state) == 0),
990 msecs_to_jiffies(TIMEOUT_MS));
991 if (!ret) {
992 pr_err("%s: wait_event timeout\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700993 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700994 }
995
996 return 0;
997}
998
Helen Zeng0705a5f2011-10-14 15:29:52 -0700999int afe_pseudo_port_stop_nowait(u16 port_id)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001000{
1001 int ret = 0;
1002 struct afe_pseudoport_stop_command stop;
1003
Helen Zeng0705a5f2011-10-14 15:29:52 -07001004 pr_debug("%s: port_id=%d\n", __func__, port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001005
1006 if (this_afe.apr == NULL) {
1007 pr_err("%s: AFE is already closed\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001008 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001009 }
1010
1011 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1012 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1013 stop.hdr.pkt_size = sizeof(stop);
1014 stop.hdr.src_port = 0;
1015 stop.hdr.dest_port = 0;
1016 stop.hdr.token = 0;
1017 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
1018 stop.port_id = port_id;
1019 stop.reserved = 0;
1020
1021 atomic_set(&this_afe.state, 1);
1022 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1023 if (ret < 0) {
1024 pr_err("%s: AFE close failed %d\n", __func__, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001025 return -EINVAL;
1026 }
1027
1028 return 0;
1029
1030}
1031
1032int afe_stop_pseudo_port(u16 port_id)
1033{
1034 int ret = 0;
1035 struct afe_pseudoport_stop_command stop;
1036
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001037 pr_debug("%s: port_id=%d\n", __func__, port_id);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001038
1039 if (this_afe.apr == NULL) {
1040 pr_err("%s: AFE is already closed\n", __func__);
1041 return -EINVAL;
1042 }
1043
1044 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1045 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1046 stop.hdr.pkt_size = sizeof(stop);
1047 stop.hdr.src_port = 0;
1048 stop.hdr.dest_port = 0;
1049 stop.hdr.token = 0;
1050 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
1051 stop.port_id = port_id;
1052 stop.reserved = 0;
1053
1054 atomic_set(&this_afe.state, 1);
1055 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1056 if (ret < 0) {
1057 pr_err("%s: AFE close failed %d\n", __func__, ret);
1058 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001059 }
1060
1061 ret = wait_event_timeout(this_afe.wait,
1062 (atomic_read(&this_afe.state) == 0),
1063 msecs_to_jiffies(TIMEOUT_MS));
1064 if (!ret) {
1065 pr_err("%s: wait_event timeout\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001066 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001067 }
1068
1069 return 0;
1070}
1071
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301072int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz)
1073{
1074 int ret = 0;
1075 struct afe_cmd_memory_map mregion;
1076
1077 pr_debug("%s:\n", __func__);
1078
1079 if (this_afe.apr == NULL) {
1080 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1081 0xFFFFFFFF, &this_afe);
1082 pr_debug("%s: Register AFE\n", __func__);
1083 if (this_afe.apr == NULL) {
1084 pr_err("%s: Unable to register AFE\n", __func__);
1085 ret = -ENODEV;
1086 return ret;
1087 }
1088 }
1089
1090 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1091 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1092 mregion.hdr.pkt_size = sizeof(mregion);
1093 mregion.hdr.src_port = 0;
1094 mregion.hdr.dest_port = 0;
1095 mregion.hdr.token = 0;
1096 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
1097 mregion.phy_addr = dma_addr_p;
1098 mregion.mem_sz = dma_buf_sz;
1099 mregion.mem_id = 0;
1100 mregion.rsvd = 0;
1101
1102 atomic_set(&this_afe.state, 1);
1103 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1104 if (ret < 0) {
1105 pr_err("%s: AFE memory map cmd failed %d\n",
1106 __func__, ret);
1107 ret = -EINVAL;
1108 return ret;
1109 }
1110
1111 ret = wait_event_timeout(this_afe.wait,
1112 (atomic_read(&this_afe.state) == 0),
1113 msecs_to_jiffies(TIMEOUT_MS));
1114 if (!ret) {
1115 pr_err("%s: wait_event timeout\n", __func__);
1116 ret = -EINVAL;
1117 return ret;
1118 }
1119
1120 return 0;
1121}
1122
Ben Rombergerb7603232011-11-23 17:16:27 -08001123int afe_cmd_memory_map_nowait(u32 dma_addr_p, u32 dma_buf_sz)
1124{
1125 int ret = 0;
1126 struct afe_cmd_memory_map mregion;
1127
1128 pr_debug("%s:\n", __func__);
1129
1130 if (this_afe.apr == NULL) {
1131 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1132 0xFFFFFFFF, &this_afe);
1133 pr_debug("%s: Register AFE\n", __func__);
1134 if (this_afe.apr == NULL) {
1135 pr_err("%s: Unable to register AFE\n", __func__);
1136 ret = -ENODEV;
1137 return ret;
1138 }
1139 }
1140
1141 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1142 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1143 mregion.hdr.pkt_size = sizeof(mregion);
1144 mregion.hdr.src_port = 0;
1145 mregion.hdr.dest_port = 0;
1146 mregion.hdr.token = 0;
1147 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
1148 mregion.phy_addr = dma_addr_p;
1149 mregion.mem_sz = dma_buf_sz;
1150 mregion.mem_id = 0;
1151 mregion.rsvd = 0;
1152
1153 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1154 if (ret < 0) {
1155 pr_err("%s: AFE memory map cmd failed %d\n",
1156 __func__, ret);
1157 ret = -EINVAL;
1158 }
1159 return 0;
1160}
1161
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301162int afe_cmd_memory_unmap(u32 dma_addr_p)
1163{
1164 int ret = 0;
1165 struct afe_cmd_memory_unmap mregion;
1166
1167 pr_debug("%s:\n", __func__);
1168
1169 if (this_afe.apr == NULL) {
1170 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1171 0xFFFFFFFF, &this_afe);
1172 pr_debug("%s: Register AFE\n", __func__);
1173 if (this_afe.apr == NULL) {
1174 pr_err("%s: Unable to register AFE\n", __func__);
1175 ret = -ENODEV;
1176 return ret;
1177 }
1178 }
1179
1180 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1181 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1182 mregion.hdr.pkt_size = sizeof(mregion);
1183 mregion.hdr.src_port = 0;
1184 mregion.hdr.dest_port = 0;
1185 mregion.hdr.token = 0;
1186 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
1187 mregion.phy_addr = dma_addr_p;
1188
1189 atomic_set(&this_afe.state, 1);
1190 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1191 if (ret < 0) {
Ben Rombergerb7603232011-11-23 17:16:27 -08001192 pr_err("%s: AFE memory unmap cmd failed %d\n",
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301193 __func__, ret);
1194 ret = -EINVAL;
1195 return ret;
1196 }
1197
1198 ret = wait_event_timeout(this_afe.wait,
1199 (atomic_read(&this_afe.state) == 0),
1200 msecs_to_jiffies(TIMEOUT_MS));
1201 if (!ret) {
1202 pr_err("%s: wait_event timeout\n", __func__);
1203 ret = -EINVAL;
1204 return ret;
1205 }
Ben Rombergerb7603232011-11-23 17:16:27 -08001206 return 0;
1207}
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301208
Ben Rombergerb7603232011-11-23 17:16:27 -08001209int afe_cmd_memory_unmap_nowait(u32 dma_addr_p)
1210{
1211 int ret = 0;
1212 struct afe_cmd_memory_unmap mregion;
1213
1214 pr_debug("%s:\n", __func__);
1215
1216 if (this_afe.apr == NULL) {
1217 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1218 0xFFFFFFFF, &this_afe);
1219 pr_debug("%s: Register AFE\n", __func__);
1220 if (this_afe.apr == NULL) {
1221 pr_err("%s: Unable to register AFE\n", __func__);
1222 ret = -ENODEV;
1223 return ret;
1224 }
1225 }
1226
1227 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1228 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1229 mregion.hdr.pkt_size = sizeof(mregion);
1230 mregion.hdr.src_port = 0;
1231 mregion.hdr.dest_port = 0;
1232 mregion.hdr.token = 0;
1233 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
1234 mregion.phy_addr = dma_addr_p;
1235
1236 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1237 if (ret < 0) {
1238 pr_err("%s: AFE memory unmap cmd failed %d\n",
1239 __func__, ret);
1240 ret = -EINVAL;
1241 }
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301242 return 0;
1243}
1244
1245int afe_register_get_events(u16 port_id,
1246 void (*cb) (uint32_t opcode,
1247 uint32_t token, uint32_t *payload, void *priv),
1248 void *private_data)
1249{
1250 int ret = 0;
1251 struct afe_cmd_reg_rtport rtproxy;
1252
1253 pr_debug("%s:\n", __func__);
1254
1255 if (this_afe.apr == NULL) {
1256 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1257 0xFFFFFFFF, &this_afe);
1258 pr_debug("%s: Register AFE\n", __func__);
1259 if (this_afe.apr == NULL) {
1260 pr_err("%s: Unable to register AFE\n", __func__);
1261 ret = -ENODEV;
1262 return ret;
1263 }
1264 }
1265 if ((port_id == RT_PROXY_DAI_002_RX) ||
1266 (port_id == RT_PROXY_DAI_001_TX))
1267 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1268 else
1269 return -EINVAL;
1270
1271 if (port_id == RT_PROXY_PORT_001_TX) {
1272 this_afe.tx_cb = cb;
1273 this_afe.tx_private_data = private_data;
1274 } else if (port_id == RT_PROXY_PORT_001_RX) {
1275 this_afe.rx_cb = cb;
1276 this_afe.rx_private_data = private_data;
1277 }
1278
1279 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1280 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1281 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1282 rtproxy.hdr.src_port = 1;
1283 rtproxy.hdr.dest_port = 1;
1284 rtproxy.hdr.token = 0;
1285 rtproxy.hdr.opcode = AFE_SERVICE_CMD_REG_RTPORT;
1286 rtproxy.port_id = port_id;
1287 rtproxy.rsvd = 0;
1288
1289 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1290 if (ret < 0) {
1291 pr_err("%s: AFE reg. rtproxy_event failed %d\n",
1292 __func__, ret);
1293 ret = -EINVAL;
1294 return ret;
1295 }
1296 return 0;
1297}
1298
1299int afe_unregister_get_events(u16 port_id)
1300{
1301 int ret = 0;
1302 struct afe_cmd_unreg_rtport rtproxy;
1303
1304 pr_debug("%s:\n", __func__);
1305
1306 if (this_afe.apr == NULL) {
1307 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1308 0xFFFFFFFF, &this_afe);
1309 pr_debug("%s: Register AFE\n", __func__);
1310 if (this_afe.apr == NULL) {
1311 pr_err("%s: Unable to register AFE\n", __func__);
1312 ret = -ENODEV;
1313 return ret;
1314 }
1315 }
1316 if ((port_id == RT_PROXY_DAI_002_RX) ||
1317 (port_id == RT_PROXY_DAI_001_TX))
1318 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1319 else
1320 return -EINVAL;
1321
1322 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1323 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1324 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1325 rtproxy.hdr.src_port = 0;
1326 rtproxy.hdr.dest_port = 0;
1327 rtproxy.hdr.token = 0;
1328 rtproxy.hdr.opcode = AFE_SERVICE_CMD_UNREG_RTPORT;
1329 rtproxy.port_id = port_id;
1330 rtproxy.rsvd = 0;
1331
1332 if (port_id == RT_PROXY_PORT_001_TX) {
1333 this_afe.tx_cb = NULL;
1334 this_afe.tx_private_data = NULL;
1335 } else if (port_id == RT_PROXY_PORT_001_RX) {
1336 this_afe.rx_cb = NULL;
1337 this_afe.rx_private_data = NULL;
1338 }
1339
1340 atomic_set(&this_afe.state, 1);
1341 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1342 if (ret < 0) {
1343 pr_err("%s: AFE enable Unreg. rtproxy_event failed %d\n",
1344 __func__, ret);
1345 ret = -EINVAL;
1346 return ret;
1347 }
1348
1349 ret = wait_event_timeout(this_afe.wait,
1350 (atomic_read(&this_afe.state) == 0),
1351 msecs_to_jiffies(TIMEOUT_MS));
1352 if (!ret) {
1353 pr_err("%s: wait_event timeout\n", __func__);
1354 ret = -EINVAL;
1355 return ret;
1356 }
1357 return 0;
1358}
1359
1360int afe_rt_proxy_port_write(u32 buf_addr_p, int bytes)
1361{
1362 int ret = 0;
1363 struct afe_cmd_rtport_wr afecmd_wr;
1364
1365 if (this_afe.apr == NULL) {
1366 pr_err("%s:register to AFE is not done\n", __func__);
1367 ret = -ENODEV;
1368 return ret;
1369 }
1370 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1371 buf_addr_p, bytes);
1372
1373 afecmd_wr.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1374 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1375 afecmd_wr.hdr.pkt_size = sizeof(afecmd_wr);
1376 afecmd_wr.hdr.src_port = 0;
1377 afecmd_wr.hdr.dest_port = 0;
1378 afecmd_wr.hdr.token = 0;
1379 afecmd_wr.hdr.opcode = AFE_SERVICE_CMD_RTPORT_WR;
1380 afecmd_wr.buf_addr = (uint32_t)buf_addr_p;
1381 afecmd_wr.port_id = RT_PROXY_PORT_001_TX;
1382 afecmd_wr.bytes_avail = bytes;
1383 afecmd_wr.rsvd = 0;
1384
1385 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_wr);
1386 if (ret < 0) {
1387 pr_err("%s: AFE rtproxy write to port 0x%x failed %d\n",
1388 __func__, afecmd_wr.port_id, ret);
1389 ret = -EINVAL;
1390 return ret;
1391 }
1392 return 0;
1393
1394}
1395
1396int afe_rt_proxy_port_read(u32 buf_addr_p, int bytes)
1397{
1398 int ret = 0;
1399 struct afe_cmd_rtport_rd afecmd_rd;
1400
1401 if (this_afe.apr == NULL) {
1402 pr_err("%s: register to AFE is not done\n", __func__);
1403 ret = -ENODEV;
1404 return ret;
1405 }
1406 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1407 buf_addr_p, bytes);
1408
1409 afecmd_rd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1410 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1411 afecmd_rd.hdr.pkt_size = sizeof(afecmd_rd);
1412 afecmd_rd.hdr.src_port = 0;
1413 afecmd_rd.hdr.dest_port = 0;
1414 afecmd_rd.hdr.token = 0;
1415 afecmd_rd.hdr.opcode = AFE_SERVICE_CMD_RTPORT_RD;
1416 afecmd_rd.buf_addr = (uint32_t)buf_addr_p;
1417 afecmd_rd.port_id = RT_PROXY_PORT_001_RX;
1418 afecmd_rd.bytes_avail = bytes;
1419 afecmd_rd.rsvd = 0;
1420
1421 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_rd);
1422 if (ret < 0) {
1423 pr_err("%s: AFE rtproxy read cmd to port 0x%x failed %d\n",
1424 __func__, afecmd_rd.port_id, ret);
1425 ret = -EINVAL;
1426 return ret;
1427 }
1428 return 0;
1429}
1430
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001431#ifdef CONFIG_DEBUG_FS
1432static struct dentry *debugfs_afelb;
1433static struct dentry *debugfs_afelb_gain;
1434
1435static int afe_debug_open(struct inode *inode, struct file *file)
1436{
1437 file->private_data = inode->i_private;
1438 pr_info("debug intf %s\n", (char *) file->private_data);
1439 return 0;
1440}
1441
1442static int afe_get_parameters(char *buf, long int *param1, int num_of_par)
1443{
1444 char *token;
1445 int base, cnt;
1446
1447 token = strsep(&buf, " ");
1448
1449 for (cnt = 0; cnt < num_of_par; cnt++) {
1450 if (token != NULL) {
1451 if ((token[1] == 'x') || (token[1] == 'X'))
1452 base = 16;
1453 else
1454 base = 10;
1455
1456 if (strict_strtoul(token, base, &param1[cnt]) != 0)
1457 return -EINVAL;
1458
1459 token = strsep(&buf, " ");
1460 } else
1461 return -EINVAL;
1462 }
1463 return 0;
1464}
1465#define AFE_LOOPBACK_ON (1)
1466#define AFE_LOOPBACK_OFF (0)
1467static ssize_t afe_debug_write(struct file *filp,
1468 const char __user *ubuf, size_t cnt, loff_t *ppos)
1469{
1470 char *lb_str = filp->private_data;
1471 char lbuf[32];
1472 int rc;
1473 unsigned long param[5];
1474
1475 if (cnt > sizeof(lbuf) - 1)
1476 return -EINVAL;
1477
1478 rc = copy_from_user(lbuf, ubuf, cnt);
1479 if (rc)
1480 return -EFAULT;
1481
1482 lbuf[cnt] = '\0';
1483
1484 if (!strcmp(lb_str, "afe_loopback")) {
1485 rc = afe_get_parameters(lbuf, param, 3);
1486 if (!rc) {
1487 pr_info("%s %lu %lu %lu\n", lb_str, param[0], param[1],
1488 param[2]);
1489
1490 if ((param[0] != AFE_LOOPBACK_ON) && (param[0] !=
1491 AFE_LOOPBACK_OFF)) {
1492 pr_err("%s: Error, parameter 0 incorrect\n",
1493 __func__);
1494 rc = -EINVAL;
1495 goto afe_error;
1496 }
1497 if ((afe_validate_port(param[1]) < 0) ||
1498 (afe_validate_port(param[2])) < 0) {
1499 pr_err("%s: Error, invalid afe port\n",
1500 __func__);
1501 }
1502 if (this_afe.apr == NULL) {
1503 pr_err("%s: Error, AFE not opened\n", __func__);
1504 rc = -EINVAL;
1505 } else {
1506 rc = afe_loopback(param[0], param[1], param[2]);
1507 }
1508 } else {
1509 pr_err("%s: Error, invalid parameters\n", __func__);
1510 rc = -EINVAL;
1511 }
1512
1513 } else if (!strcmp(lb_str, "afe_loopback_gain")) {
1514 rc = afe_get_parameters(lbuf, param, 2);
1515 if (!rc) {
1516 pr_info("%s %lu %lu\n", lb_str, param[0], param[1]);
1517
1518 if (afe_validate_port(param[0]) < 0) {
1519 pr_err("%s: Error, invalid afe port\n",
1520 __func__);
1521 rc = -EINVAL;
1522 goto afe_error;
1523 }
1524
1525 if (param[1] < 0 || param[1] > 100) {
1526 pr_err("%s: Error, volume shoud be 0 to 100"
1527 " percentage param = %lu\n",
1528 __func__, param[1]);
1529 rc = -EINVAL;
1530 goto afe_error;
1531 }
1532
1533 param[1] = (Q6AFE_MAX_VOLUME * param[1]) / 100;
1534
1535 if (this_afe.apr == NULL) {
1536 pr_err("%s: Error, AFE not opened\n", __func__);
1537 rc = -EINVAL;
1538 } else {
1539 rc = afe_loopback_gain(param[0], param[1]);
1540 }
1541 } else {
1542 pr_err("%s: Error, invalid parameters\n", __func__);
1543 rc = -EINVAL;
1544 }
1545 }
1546
1547afe_error:
1548 if (rc == 0)
1549 rc = cnt;
1550 else
1551 pr_err("%s: rc = %d\n", __func__, rc);
1552
1553 return rc;
1554}
1555
1556static const struct file_operations afe_debug_fops = {
1557 .open = afe_debug_open,
1558 .write = afe_debug_write
1559};
1560#endif
1561int afe_sidetone(u16 tx_port_id, u16 rx_port_id, u16 enable, uint16_t gain)
1562{
1563 struct afe_port_sidetone_command cmd_sidetone;
1564 int ret = 0;
1565
1566 pr_info("%s: tx_port_id:%d rx_port_id:%d enable:%d gain:%d\n", __func__,
1567 tx_port_id, rx_port_id, enable, gain);
1568 cmd_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1569 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1570 cmd_sidetone.hdr.pkt_size = sizeof(cmd_sidetone);
1571 cmd_sidetone.hdr.src_port = 0;
1572 cmd_sidetone.hdr.dest_port = 0;
1573 cmd_sidetone.hdr.token = 0;
1574 cmd_sidetone.hdr.opcode = AFE_PORT_CMD_SIDETONE_CTL;
1575 cmd_sidetone.tx_port_id = tx_port_id;
1576 cmd_sidetone.rx_port_id = rx_port_id;
1577 cmd_sidetone.gain = gain;
1578 cmd_sidetone.enable = enable;
1579
1580 atomic_set(&this_afe.state, 1);
1581 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_sidetone);
1582 if (ret < 0) {
1583 pr_err("%s: AFE sidetone failed for tx_port:%d rx_port:%d\n",
1584 __func__, tx_port_id, rx_port_id);
1585 ret = -EINVAL;
1586 goto fail_cmd;
1587 }
1588
1589 ret = wait_event_timeout(this_afe.wait,
1590 (atomic_read(&this_afe.state) == 0),
1591 msecs_to_jiffies(TIMEOUT_MS));
1592 if (ret < 0) {
1593 pr_err("%s: wait_event timeout\n", __func__);
1594 ret = -EINVAL;
1595 goto fail_cmd;
1596 }
1597 return 0;
1598fail_cmd:
1599 return ret;
1600}
1601
1602int afe_port_stop_nowait(int port_id)
1603{
1604 struct afe_port_stop_command stop;
1605 int ret = 0;
1606
1607 if (this_afe.apr == NULL) {
1608 pr_err("AFE is already closed\n");
1609 ret = -EINVAL;
1610 goto fail_cmd;
1611 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001612 pr_debug("%s: port_id=%d\n", __func__, port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301613 port_id = afe_convert_virtual_to_portid(port_id);
1614
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001615 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1616 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1617 stop.hdr.pkt_size = sizeof(stop);
1618 stop.hdr.src_port = 0;
1619 stop.hdr.dest_port = 0;
1620 stop.hdr.token = 0;
1621 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1622 stop.port_id = port_id;
1623 stop.reserved = 0;
1624
1625 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1626
1627 if (ret == -ENETRESET) {
1628 pr_info("%s: Need to reset, calling APR deregister", __func__);
1629 return apr_deregister(this_afe.apr);
1630 } else if (IS_ERR_VALUE(ret)) {
1631 pr_err("%s: AFE close failed\n", __func__);
1632 ret = -EINVAL;
1633 }
1634
1635fail_cmd:
1636 return ret;
1637
1638}
1639
1640int afe_close(int port_id)
1641{
1642 struct afe_port_stop_command stop;
1643 int ret = 0;
1644
1645 if (this_afe.apr == NULL) {
1646 pr_err("AFE is already closed\n");
1647 ret = -EINVAL;
1648 goto fail_cmd;
1649 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001650 pr_debug("%s: port_id=%d\n", __func__, port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301651 port_id = afe_convert_virtual_to_portid(port_id);
1652
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001653 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1654 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1655 stop.hdr.pkt_size = sizeof(stop);
1656 stop.hdr.src_port = 0;
1657 stop.hdr.dest_port = 0;
1658 stop.hdr.token = 0;
1659 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1660 stop.port_id = port_id;
1661 stop.reserved = 0;
1662
1663 atomic_set(&this_afe.state, 1);
1664 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1665
1666 if (ret == -ENETRESET) {
1667 pr_info("%s: Need to reset, calling APR deregister", __func__);
1668 return apr_deregister(this_afe.apr);
1669 }
1670
1671 if (ret < 0) {
1672 pr_err("%s: AFE close failed\n", __func__);
1673 ret = -EINVAL;
1674 goto fail_cmd;
1675 }
1676
1677 ret = wait_event_timeout(this_afe.wait,
1678 (atomic_read(&this_afe.state) == 0),
1679 msecs_to_jiffies(TIMEOUT_MS));
1680 if (!ret) {
1681 pr_err("%s: wait_event timeout\n", __func__);
1682 ret = -EINVAL;
1683 goto fail_cmd;
1684 }
1685fail_cmd:
1686 return ret;
1687}
1688
1689static int __init afe_init(void)
1690{
1691 init_waitqueue_head(&this_afe.wait);
1692 atomic_set(&this_afe.state, 0);
1693 atomic_set(&this_afe.status, 0);
1694 this_afe.apr = NULL;
1695#ifdef CONFIG_DEBUG_FS
1696 debugfs_afelb = debugfs_create_file("afe_loopback",
1697 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback",
1698 &afe_debug_fops);
1699
1700 debugfs_afelb_gain = debugfs_create_file("afe_loopback_gain",
1701 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback_gain",
1702 &afe_debug_fops);
1703
1704
1705#endif
1706 return 0;
1707}
1708
1709static void __exit afe_exit(void)
1710{
Ben Rombergerb7603232011-11-23 17:16:27 -08001711 int i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001712#ifdef CONFIG_DEBUG_FS
1713 if (debugfs_afelb)
1714 debugfs_remove(debugfs_afelb);
1715 if (debugfs_afelb_gain)
1716 debugfs_remove(debugfs_afelb_gain);
1717#endif
Ben Rombergerb7603232011-11-23 17:16:27 -08001718 for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
Ben Romberger9e792562012-02-24 12:29:01 -08001719 if (afe_cal_addr[i].cal_paddr != 0)
1720 afe_cmd_memory_unmap_nowait(
1721 afe_cal_addr[i].cal_paddr);
Ben Rombergerb7603232011-11-23 17:16:27 -08001722 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001723}
1724
1725device_initcall(afe_init);
1726__exitcall(afe_exit);