blob: 2f6772d069feab9f4d1888ab170c337ac5899b20 [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:
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700145 case SECONDARY_PCM_RX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700146 case SECONDARY_I2S_RX:
147 case MI2S_RX:
148 case HDMI_RX:
149 case SLIMBUS_0_RX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800150 case SLIMBUS_1_RX:
Kiran Kandifd30c892012-05-21 23:03:26 -0700151 case SLIMBUS_2_RX:
Neema Shetty74131ac2012-05-09 13:35:26 -0700152 case SLIMBUS_3_RX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700153 case INT_BT_SCO_RX:
154 case INT_BT_A2DP_RX:
155 case INT_FM_RX:
156 case VOICE_PLAYBACK_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530157 case RT_PROXY_PORT_001_RX:
Helen Zeng8f925502012-03-05 16:50:17 -0800158 case SLIMBUS_4_RX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700159 ret = MSM_AFE_PORT_TYPE_RX;
160 break;
161
162 case PRIMARY_I2S_TX:
163 case PCM_TX:
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700164 case SECONDARY_PCM_TX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700165 case SECONDARY_I2S_TX:
166 case MI2S_TX:
167 case DIGI_MIC_TX:
168 case VOICE_RECORD_TX:
169 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800170 case SLIMBUS_1_TX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700171 case SLIMBUS_2_TX:
Helen Zeng38c3c962012-05-17 14:56:20 -0700172 case SLIMBUS_3_TX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700173 case INT_FM_TX:
174 case VOICE_RECORD_RX:
175 case INT_BT_SCO_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530176 case RT_PROXY_PORT_001_TX:
Helen Zeng8f925502012-03-05 16:50:17 -0800177 case SLIMBUS_4_TX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700178 ret = MSM_AFE_PORT_TYPE_TX;
179 break;
180
181 default:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800182 pr_err("%s: invalid port id %d\n", __func__, port_id);
Neema Shettyfeea7742011-09-11 12:30:36 -0700183 ret = -EINVAL;
184 }
185
186 return ret;
187}
188
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700189int afe_validate_port(u16 port_id)
190{
191 int ret;
192
193 switch (port_id) {
194 case PRIMARY_I2S_RX:
195 case PRIMARY_I2S_TX:
196 case PCM_RX:
197 case PCM_TX:
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700198 case SECONDARY_PCM_RX:
199 case SECONDARY_PCM_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700200 case SECONDARY_I2S_RX:
201 case SECONDARY_I2S_TX:
202 case MI2S_RX:
203 case MI2S_TX:
204 case HDMI_RX:
205 case RSVD_2:
206 case RSVD_3:
207 case DIGI_MIC_TX:
208 case VOICE_RECORD_RX:
209 case VOICE_RECORD_TX:
210 case VOICE_PLAYBACK_TX:
211 case SLIMBUS_0_RX:
212 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800213 case SLIMBUS_1_RX:
214 case SLIMBUS_1_TX:
Kiran Kandifd30c892012-05-21 23:03:26 -0700215 case SLIMBUS_2_RX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700216 case SLIMBUS_2_TX:
Neema Shetty74131ac2012-05-09 13:35:26 -0700217 case SLIMBUS_3_RX:
Helen Zeng38c3c962012-05-17 14:56:20 -0700218 case SLIMBUS_3_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700219 case INT_BT_SCO_RX:
220 case INT_BT_SCO_TX:
221 case INT_BT_A2DP_RX:
222 case INT_FM_RX:
223 case INT_FM_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530224 case RT_PROXY_PORT_001_RX:
225 case RT_PROXY_PORT_001_TX:
Helen Zeng8f925502012-03-05 16:50:17 -0800226 case SLIMBUS_4_RX:
227 case SLIMBUS_4_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700228 {
229 ret = 0;
230 break;
231 }
232
233 default:
234 ret = -EINVAL;
235 }
236
237 return ret;
238}
239
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530240int afe_convert_virtual_to_portid(u16 port_id)
241{
242 int ret;
243
244 /* if port_id is virtual, convert to physical..
245 * if port_id is already physical, return physical
246 */
247 if (afe_validate_port(port_id) < 0) {
248 if (port_id == RT_PROXY_DAI_001_RX ||
249 port_id == RT_PROXY_DAI_001_TX ||
250 port_id == RT_PROXY_DAI_002_RX ||
251 port_id == RT_PROXY_DAI_002_TX)
252 ret = VIRTUAL_ID_TO_PORTID(port_id);
253 else
254 ret = -EINVAL;
255 } else
256 ret = port_id;
257
258 return ret;
259}
260
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700261int afe_get_port_index(u16 port_id)
262{
263 switch (port_id) {
264 case PRIMARY_I2S_RX: return IDX_PRIMARY_I2S_RX;
265 case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
266 case PCM_RX: return IDX_PCM_RX;
267 case PCM_TX: return IDX_PCM_TX;
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700268 case SECONDARY_PCM_RX: return IDX_SECONDARY_PCM_RX;
269 case SECONDARY_PCM_TX: return IDX_SECONDARY_PCM_TX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700270 case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
271 case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
272 case MI2S_RX: return IDX_MI2S_RX;
273 case MI2S_TX: return IDX_MI2S_TX;
274 case HDMI_RX: return IDX_HDMI_RX;
275 case RSVD_2: return IDX_RSVD_2;
276 case RSVD_3: return IDX_RSVD_3;
277 case DIGI_MIC_TX: return IDX_DIGI_MIC_TX;
278 case VOICE_RECORD_RX: return IDX_VOICE_RECORD_RX;
279 case VOICE_RECORD_TX: return IDX_VOICE_RECORD_TX;
280 case VOICE_PLAYBACK_TX: return IDX_VOICE_PLAYBACK_TX;
281 case SLIMBUS_0_RX: return IDX_SLIMBUS_0_RX;
282 case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
Neema Shetty3c9d2862012-03-11 01:25:32 -0800283 case SLIMBUS_1_RX: return IDX_SLIMBUS_1_RX;
284 case SLIMBUS_1_TX: return IDX_SLIMBUS_1_TX;
Kiran Kandifd30c892012-05-21 23:03:26 -0700285 case SLIMBUS_2_RX: return IDX_SLIMBUS_2_RX;
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700286 case SLIMBUS_2_TX: return IDX_SLIMBUS_2_TX;
Neema Shetty74131ac2012-05-09 13:35:26 -0700287 case SLIMBUS_3_RX: return IDX_SLIMBUS_3_RX;
Helen Zeng38c3c962012-05-17 14:56:20 -0700288 case SLIMBUS_3_TX: return IDX_SLIMBUS_3_TX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700289 case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
290 case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
291 case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
292 case INT_FM_RX: return IDX_INT_FM_RX;
293 case INT_FM_TX: return IDX_INT_FM_TX;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530294 case RT_PROXY_PORT_001_RX: return IDX_RT_PROXY_PORT_001_RX;
295 case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
Helen Zeng8f925502012-03-05 16:50:17 -0800296 case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX;
297 case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700298
299 default: return -EINVAL;
300 }
301}
302
303int afe_sizeof_cfg_cmd(u16 port_id)
304{
305 int ret_size;
306 switch (port_id) {
307 case PRIMARY_I2S_RX:
308 case PRIMARY_I2S_TX:
309 case SECONDARY_I2S_RX:
310 case SECONDARY_I2S_TX:
311 case MI2S_RX:
312 case MI2S_TX:
313 ret_size = SIZEOF_CFG_CMD(afe_port_mi2s_cfg);
314 break;
315 case HDMI_RX:
Kiran Kandi5e809b02012-01-31 00:24:33 -0800316 ret_size = SIZEOF_CFG_CMD(afe_port_hdmi_multi_ch_cfg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700317 break;
318 case SLIMBUS_0_RX:
319 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800320 case SLIMBUS_1_RX:
321 case SLIMBUS_1_TX:
Kiran Kandifd30c892012-05-21 23:03:26 -0700322 case SLIMBUS_2_RX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700323 case SLIMBUS_2_TX:
Neema Shetty74131ac2012-05-09 13:35:26 -0700324 case SLIMBUS_3_RX:
Helen Zeng38c3c962012-05-17 14:56:20 -0700325 case SLIMBUS_3_TX:
Helen Zeng8f925502012-03-05 16:50:17 -0800326 case SLIMBUS_4_RX:
327 case SLIMBUS_4_TX:
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800328 ret_size = SIZEOF_CFG_CMD(afe_port_slimbus_sch_cfg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700329 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530330 case RT_PROXY_PORT_001_RX:
331 case RT_PROXY_PORT_001_TX:
332 ret_size = SIZEOF_CFG_CMD(afe_port_rtproxy_cfg);
333 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700334 case PCM_RX:
335 case PCM_TX:
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700336 case SECONDARY_PCM_RX:
337 case SECONDARY_PCM_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700338 default:
339 ret_size = SIZEOF_CFG_CMD(afe_port_pcm_cfg);
340 break;
341 }
342 return ret_size;
343}
344
Jay Wang6a305432011-08-05 16:01:54 -0700345int afe_q6_interface_prepare(void)
346{
347 int ret = 0;
348
349 pr_debug("%s:", __func__);
350
351 if (this_afe.apr == NULL) {
352 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
353 0xFFFFFFFF, &this_afe);
354 pr_debug("%s: Register AFE\n", __func__);
355 if (this_afe.apr == NULL) {
356 pr_err("%s: Unable to register AFE\n", __func__);
357 ret = -ENODEV;
358 }
359 }
360 return ret;
361}
362
Ben Rombergerb7603232011-11-23 17:16:27 -0800363static void afe_send_cal_block(int32_t path, u16 port_id)
364{
365 int result = 0;
366 struct acdb_cal_block cal_block;
367 struct afe_port_cmd_set_param_no_payload afe_cal;
368 pr_debug("%s: path %d\n", __func__, path);
369
370 get_afe_cal(path, &cal_block);
371 if (cal_block.cal_size <= 0) {
372 pr_debug("%s: No AFE cal to send!\n", __func__);
373 goto done;
374 }
375
Ben Romberger9e792562012-02-24 12:29:01 -0800376 if ((afe_cal_addr[path].cal_paddr != cal_block.cal_paddr) ||
377 (cal_block.cal_size > afe_cal_addr[path].cal_size)) {
378 if (afe_cal_addr[path].cal_paddr != 0)
Patrick Laibf978952012-06-29 09:20:42 -0700379 afe_cmd_memory_unmap(
Ben Romberger9e792562012-02-24 12:29:01 -0800380 afe_cal_addr[path].cal_paddr);
381
Patrick Laibf978952012-06-29 09:20:42 -0700382 afe_cmd_memory_map(cal_block.cal_paddr, cal_block.cal_size);
Ben Romberger9e792562012-02-24 12:29:01 -0800383 afe_cal_addr[path].cal_paddr = cal_block.cal_paddr;
384 afe_cal_addr[path].cal_size = cal_block.cal_size;
Ben Rombergerb7603232011-11-23 17:16:27 -0800385 }
386
387 afe_cal.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
388 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
389 afe_cal.hdr.pkt_size = sizeof(afe_cal);
390 afe_cal.hdr.src_port = 0;
391 afe_cal.hdr.dest_port = 0;
392 afe_cal.hdr.token = 0;
393 afe_cal.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
394 afe_cal.port_id = port_id;
395 afe_cal.payload_size = cal_block.cal_size;
396 afe_cal.payload_address = cal_block.cal_paddr;
397
398 pr_debug("%s: AFE cal sent for device port = %d, path = %d, "
399 "cal size = %d, cal addr = 0x%x\n", __func__,
400 port_id, path, cal_block.cal_size, cal_block.cal_paddr);
401
Patrick Laibf978952012-06-29 09:20:42 -0700402 atomic_set(&this_afe.state, 1);
Ben Rombergerb7603232011-11-23 17:16:27 -0800403 result = apr_send_pkt(this_afe.apr, (uint32_t *) &afe_cal);
404 if (result < 0) {
405 pr_err("%s: AFE cal for port %d failed\n",
406 __func__, port_id);
407 }
408
Patrick Laibf978952012-06-29 09:20:42 -0700409 result = wait_event_timeout(this_afe.wait,
410 (atomic_read(&this_afe.state) == 0),
411 msecs_to_jiffies(TIMEOUT_MS));
412 if (!result) {
413 pr_err("%s: wait_event timeout SET AFE CAL\n", __func__);
414 goto done;
415 }
416
Ben Rombergerb7603232011-11-23 17:16:27 -0800417 pr_debug("%s: AFE cal sent for path %d device!\n", __func__, path);
418done:
419 return;
420}
421
422void afe_send_cal(u16 port_id)
423{
424 pr_debug("%s\n", __func__);
425
426 if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX)
427 afe_send_cal_block(TX_CAL, port_id);
428 else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX)
429 afe_send_cal_block(RX_CAL, port_id);
430}
431
Patrick Laibf978952012-06-29 09:20:42 -0700432/* This function sends multi-channel HDMI configuration command and AFE
433 * calibration which is only supported by QDSP6 on 8960 and onward.
434 */
435int afe_port_start(u16 port_id, union afe_port_config *afe_config,
436 u32 rate)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700437{
438 struct afe_port_start_command start;
439 struct afe_audioif_config_command config;
440 int ret;
441
442 if (!afe_config) {
443 pr_err("%s: Error, no configuration data\n", __func__);
444 ret = -EINVAL;
445 return ret;
446 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -0800447 pr_debug("%s: %d %d\n", __func__, port_id, rate);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700448
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530449 if ((port_id == RT_PROXY_DAI_001_RX) ||
450 (port_id == RT_PROXY_DAI_002_TX))
451 return -EINVAL;
452 if ((port_id == RT_PROXY_DAI_002_RX) ||
453 (port_id == RT_PROXY_DAI_001_TX))
454 port_id = VIRTUAL_ID_TO_PORTID(port_id);
455
Patrick Laibf978952012-06-29 09:20:42 -0700456 ret = afe_q6_interface_prepare();
457 if (IS_ERR_VALUE(ret))
Jay Wang6a305432011-08-05 16:01:54 -0700458 return ret;
Kiran Kandi5e809b02012-01-31 00:24:33 -0800459
460 if (port_id == HDMI_RX) {
461 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700462 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
Kiran Kandi5e809b02012-01-31 00:24:33 -0800463 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
464 config.hdr.src_port = 0;
465 config.hdr.dest_port = 0;
466 config.hdr.token = 0;
467 config.hdr.opcode = AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG;
468 } else {
469
470 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
471 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
472 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
473 config.hdr.src_port = 0;
474 config.hdr.dest_port = 0;
475 config.hdr.token = 0;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800476 switch (port_id) {
477 case SLIMBUS_0_RX:
478 case SLIMBUS_0_TX:
479 case SLIMBUS_1_RX:
480 case SLIMBUS_1_TX:
481 case SLIMBUS_2_RX:
482 case SLIMBUS_2_TX:
483 case SLIMBUS_3_RX:
484 case SLIMBUS_3_TX:
485 case SLIMBUS_4_RX:
486 case SLIMBUS_4_TX:
487 config.hdr.opcode = AFE_PORT_AUDIO_SLIM_SCH_CONFIG;
488 break;
Kuirong Wanga36f2882012-04-02 19:45:26 -0700489 case MI2S_TX:
490 case MI2S_RX:
491 case SECONDARY_I2S_RX:
492 case SECONDARY_I2S_TX:
493 case PRIMARY_I2S_RX:
494 case PRIMARY_I2S_TX:
495 /* AFE_PORT_CMD_I2S_CONFIG command is not supported
496 * in the LPASS EL 1.0. So we have to distiguish
497 * which AFE command, AFE_PORT_CMD_I2S_CONFIG or
498 * AFE_PORT_AUDIO_IF_CONFIG to use. If the format
499 * is L-PCM, the AFE_PORT_AUDIO_IF_CONFIG is used
500 * to make the backward compatible.
501 */
502 pr_debug("%s: afe_config->mi2s.format = %d\n", __func__,
503 afe_config->mi2s.format);
504 if (afe_config->mi2s.format == MSM_AFE_I2S_FORMAT_LPCM)
505 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
506 else
507 config.hdr.opcode = AFE_PORT_CMD_I2S_CONFIG;
508 break;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800509 default:
510 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
511 break;
512 }
Kiran Kandi5e809b02012-01-31 00:24:33 -0800513 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700514
515 if (afe_validate_port(port_id) < 0) {
516
517 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
518 port_id);
519 ret = -EINVAL;
520 goto fail_cmd;
521 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700522 config.port_id = port_id;
523 config.port = *afe_config;
524
Patrick Laibf978952012-06-29 09:20:42 -0700525 atomic_set(&this_afe.state, 1);
526 atomic_set(&this_afe.status, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700527 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
528 if (ret < 0) {
529 pr_err("%s: AFE enable for port %d failed\n", __func__,
530 port_id);
531 ret = -EINVAL;
532 goto fail_cmd;
533 }
Ben Rombergerb7603232011-11-23 17:16:27 -0800534
Patrick Laibf978952012-06-29 09:20:42 -0700535 ret = wait_event_timeout(this_afe.wait,
536 (atomic_read(&this_afe.state) == 0),
537 msecs_to_jiffies(TIMEOUT_MS));
538
539 if (!ret) {
540 pr_err("%s: wait_event timeout IF CONFIG\n", __func__);
541 ret = -EINVAL;
542 goto fail_cmd;
543 }
544 if (atomic_read(&this_afe.status) != 0) {
545 pr_err("%s: config cmd failed\n", __func__);
546 ret = -EINVAL;
547 goto fail_cmd;
548 }
549
Ben Rombergerb7603232011-11-23 17:16:27 -0800550 /* send AFE cal */
551 afe_send_cal(port_id);
552
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700553 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
554 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
555 start.hdr.pkt_size = sizeof(start);
556 start.hdr.src_port = 0;
557 start.hdr.dest_port = 0;
558 start.hdr.token = 0;
559 start.hdr.opcode = AFE_PORT_CMD_START;
560 start.port_id = port_id;
561 start.gain = 0x2000;
562 start.sample_rate = rate;
563
Patrick Laibf978952012-06-29 09:20:42 -0700564 atomic_set(&this_afe.state, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700565 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
566
567 if (IS_ERR_VALUE(ret)) {
568 pr_err("%s: AFE enable for port %d failed\n", __func__,
569 port_id);
570 ret = -EINVAL;
571 goto fail_cmd;
572 }
573
Patrick Laibf978952012-06-29 09:20:42 -0700574 ret = wait_event_timeout(this_afe.wait,
575 (atomic_read(&this_afe.state) == 0),
576 msecs_to_jiffies(TIMEOUT_MS));
577 if (!ret) {
578 pr_err("%s: wait_event timeout PORT START\n", __func__);
579 ret = -EINVAL;
580 goto fail_cmd;
581 }
582
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700583 if (this_afe.task != current)
584 this_afe.task = current;
585
586 pr_debug("task_name = %s pid = %d\n",
587 this_afe.task->comm, this_afe.task->pid);
588 return 0;
589
590fail_cmd:
591 return ret;
592}
593
Patrick Laibf978952012-06-29 09:20:42 -0700594/* This function should be used by 8660 exclusively */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700595int afe_open(u16 port_id, union afe_port_config *afe_config, int rate)
596{
597 struct afe_port_start_command start;
598 struct afe_audioif_config_command config;
599 int ret = 0;
600
601 if (!afe_config) {
602 pr_err("%s: Error, no configuration data\n", __func__);
603 ret = -EINVAL;
604 return ret;
605 }
606
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800607 pr_debug("%s: %d %d\n", __func__, port_id, rate);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700608
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530609 if ((port_id == RT_PROXY_DAI_001_RX) ||
610 (port_id == RT_PROXY_DAI_002_TX))
611 return -EINVAL;
612 if ((port_id == RT_PROXY_DAI_002_RX) ||
613 (port_id == RT_PROXY_DAI_001_TX))
614 port_id = VIRTUAL_ID_TO_PORTID(port_id);
615
Jay Wang6a305432011-08-05 16:01:54 -0700616 ret = afe_q6_interface_prepare();
617 if (ret != 0)
618 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700619
620 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
621 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
622 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
623 config.hdr.src_port = 0;
624 config.hdr.dest_port = 0;
625 config.hdr.token = 0;
Kuirong Wanga36f2882012-04-02 19:45:26 -0700626 switch (port_id) {
627 case SLIMBUS_0_RX:
628 case SLIMBUS_0_TX:
629 case SLIMBUS_1_RX:
630 case SLIMBUS_1_TX:
631 case SLIMBUS_2_RX:
632 case SLIMBUS_2_TX:
633 case SLIMBUS_3_RX:
634 case SLIMBUS_3_TX:
635 case SLIMBUS_4_RX:
636 case SLIMBUS_4_TX:
637 config.hdr.opcode = AFE_PORT_AUDIO_SLIM_SCH_CONFIG;
638 break;
639 case MI2S_TX:
640 case MI2S_RX:
641 case SECONDARY_I2S_RX:
642 case SECONDARY_I2S_TX:
643 case PRIMARY_I2S_RX:
644 case PRIMARY_I2S_TX:
645 /* AFE_PORT_CMD_I2S_CONFIG command is not supported
646 * in the LPASS EL 1.0. So we have to distiguish
647 * which AFE command, AFE_PORT_CMD_I2S_CONFIG or
648 * AFE_PORT_AUDIO_IF_CONFIG to use. If the format
649 * is L-PCM, the AFE_PORT_AUDIO_IF_CONFIG is used
650 * to make the backward compatible.
651 */
652 pr_debug("%s: afe_config->mi2s.format = %d\n", __func__,
653 afe_config->mi2s.format);
654 if (afe_config->mi2s.format == MSM_AFE_I2S_FORMAT_LPCM)
655 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
656 else
657 config.hdr.opcode = AFE_PORT_CMD_I2S_CONFIG;
658 break;
659 default:
660 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
661 break;
662 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700663
664 if (afe_validate_port(port_id) < 0) {
665
666 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
667 port_id);
668 ret = -EINVAL;
669 goto fail_cmd;
670 }
671
672 config.port_id = port_id;
673 config.port = *afe_config;
674
675 atomic_set(&this_afe.state, 1);
676 atomic_set(&this_afe.status, 0);
677 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
678 if (ret < 0) {
679 pr_err("%s: AFE enable for port %d failed\n", __func__,
680 port_id);
681 ret = -EINVAL;
682 goto fail_cmd;
683 }
684
685 ret = wait_event_timeout(this_afe.wait,
686 (atomic_read(&this_afe.state) == 0),
687 msecs_to_jiffies(TIMEOUT_MS));
688 if (!ret) {
689 pr_err("%s: wait_event timeout\n", __func__);
690 ret = -EINVAL;
691 goto fail_cmd;
692 }
693 if (atomic_read(&this_afe.status) != 0) {
694 pr_err("%s: config cmd failed\n", __func__);
695 ret = -EINVAL;
696 goto fail_cmd;
697 }
698 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
699 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
700 start.hdr.pkt_size = sizeof(start);
701 start.hdr.src_port = 0;
702 start.hdr.dest_port = 0;
703 start.hdr.token = 0;
704 start.hdr.opcode = AFE_PORT_CMD_START;
705 start.port_id = port_id;
706 start.gain = 0x2000;
707 start.sample_rate = rate;
708
709 atomic_set(&this_afe.state, 1);
710 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
711 if (ret < 0) {
712 pr_err("%s: AFE enable for port %d failed\n", __func__,
713 port_id);
714 ret = -EINVAL;
715 goto fail_cmd;
716 }
717 ret = wait_event_timeout(this_afe.wait,
718 (atomic_read(&this_afe.state) == 0),
719 msecs_to_jiffies(TIMEOUT_MS));
720 if (!ret) {
721 pr_err("%s: wait_event timeout\n", __func__);
722 ret = -EINVAL;
723 goto fail_cmd;
724 }
725
726 if (this_afe.task != current)
727 this_afe.task = current;
728
729 pr_debug("task_name = %s pid = %d\n",
730 this_afe.task->comm, this_afe.task->pid);
731 return 0;
732fail_cmd:
733 return ret;
734}
735
Neema Shetty74131ac2012-05-09 13:35:26 -0700736int afe_loopback(u16 enable, u16 dst_port, u16 src_port)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700737{
738 struct afe_loopback_command lb_cmd;
739 int ret = 0;
Jay Wang6a305432011-08-05 16:01:54 -0700740
741 ret = afe_q6_interface_prepare();
742 if (ret != 0)
743 return ret;
744
Neema Shetty74131ac2012-05-09 13:35:26 -0700745 if ((afe_get_port_type(dst_port) == MSM_AFE_PORT_TYPE_RX) &&
746 (afe_get_port_type(src_port) == MSM_AFE_PORT_TYPE_RX))
747 return afe_loopback_cfg(enable, dst_port, src_port,
748 LB_MODE_EC_REF_VOICE_AUDIO);
749
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700750 lb_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
751 APR_HDR_LEN(20), APR_PKT_VER);
752 lb_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
753 sizeof(lb_cmd) - APR_HDR_SIZE);
754 lb_cmd.hdr.src_port = 0;
755 lb_cmd.hdr.dest_port = 0;
756 lb_cmd.hdr.token = 0;
757 lb_cmd.hdr.opcode = AFE_PORT_CMD_LOOPBACK;
Neema Shetty74131ac2012-05-09 13:35:26 -0700758 lb_cmd.tx_port_id = src_port;
759 lb_cmd.rx_port_id = dst_port;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700760 lb_cmd.mode = 0xFFFF;
761 lb_cmd.enable = (enable ? 1 : 0);
762 atomic_set(&this_afe.state, 1);
763
764 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &lb_cmd);
765 if (ret < 0) {
766 pr_err("%s: AFE loopback failed\n", __func__);
767 ret = -EINVAL;
768 goto done;
769 }
770 ret = wait_event_timeout(this_afe.wait,
771 (atomic_read(&this_afe.state) == 0),
772 msecs_to_jiffies(TIMEOUT_MS));
773 if (!ret) {
774 pr_err("%s: wait_event timeout\n", __func__);
775 ret = -EINVAL;
776 }
777done:
778 return ret;
779}
780
Neema Shetty74131ac2012-05-09 13:35:26 -0700781int afe_loopback_cfg(u16 enable, u16 dst_port, u16 src_port, u16 mode)
782{
783 struct afe_port_cmd_set_param lp_cfg;
784 int ret = 0;
785
786 ret = afe_q6_interface_prepare();
787 if (ret != 0)
788 return ret;
789
790 pr_debug("%s: src_port %d, dst_port %d\n",
791 __func__, src_port, dst_port);
792
793 lp_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
794 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
795 lp_cfg.hdr.pkt_size = sizeof(lp_cfg);
796 lp_cfg.hdr.src_port = 0;
797 lp_cfg.hdr.dest_port = 0;
798 lp_cfg.hdr.token = 0;
799 lp_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
800
801 lp_cfg.port_id = src_port;
802 lp_cfg.payload_size = sizeof(struct afe_param_payload);
803 lp_cfg.payload_address = 0;
804
805 lp_cfg.payload.module_id = AFE_MODULE_LOOPBACK;
806 lp_cfg.payload.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
807 lp_cfg.payload.param_size = sizeof(struct afe_param_loopback_cfg);
808 lp_cfg.payload.reserved = 0;
809
810 lp_cfg.payload.param.loopback_cfg.loopback_cfg_minor_version =
811 AFE_API_VERSION_LOOPBACK_CONFIG;
812 lp_cfg.payload.param.loopback_cfg.dst_port_id = dst_port;
813 lp_cfg.payload.param.loopback_cfg.routing_mode = mode;
814 lp_cfg.payload.param.loopback_cfg.enable = enable;
815 lp_cfg.payload.param.loopback_cfg.reserved = 0;
816
817 atomic_set(&this_afe.state, 1);
818 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &lp_cfg);
819 if (ret < 0) {
820 pr_err("%s: AFE loopback config failed for src_port %d, dst_port %d\n",
821 __func__, src_port, dst_port);
822 ret = -EINVAL;
823 goto fail_cmd;
824 }
825
826 ret = wait_event_timeout(this_afe.wait,
827 (atomic_read(&this_afe.state) == 0),
828 msecs_to_jiffies(TIMEOUT_MS));
829 if (ret < 0) {
830 pr_err("%s: wait_event timeout\n", __func__);
831 ret = -EINVAL;
832 goto fail_cmd;
833 }
834 return 0;
835fail_cmd:
836 return ret;
837}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700838
839int afe_loopback_gain(u16 port_id, u16 volume)
840{
841 struct afe_port_cmd_set_param set_param;
842 int ret = 0;
843
844 if (this_afe.apr == NULL) {
Jayasena Sangaraboina82435032011-07-26 15:23:00 -0700845 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
846 0xFFFFFFFF, &this_afe);
847 pr_debug("%s: Register AFE\n", __func__);
848 if (this_afe.apr == NULL) {
849 pr_err("%s: Unable to register AFE\n", __func__);
850 ret = -ENODEV;
851 return ret;
852 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700853 }
854
855 if (afe_validate_port(port_id) < 0) {
856
857 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
858 port_id);
859 ret = -EINVAL;
860 goto fail_cmd;
861 }
862
863 /* RX ports numbers are even .TX ports numbers are odd. */
864 if (port_id % 2 == 0) {
865 pr_err("%s: Failed : afe loopback gain only for TX ports."
866 " port_id %d\n", __func__, port_id);
867 ret = -EINVAL;
868 goto fail_cmd;
869 }
870
871 pr_debug("%s: %d %hX\n", __func__, port_id, volume);
872
873 set_param.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
874 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
875 set_param.hdr.pkt_size = sizeof(set_param);
876 set_param.hdr.src_port = 0;
877 set_param.hdr.dest_port = 0;
878 set_param.hdr.token = 0;
879 set_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
880
881 set_param.port_id = port_id;
882 set_param.payload_size = sizeof(struct afe_param_payload);
883 set_param.payload_address = 0;
884
885 set_param.payload.module_id = AFE_MODULE_ID_PORT_INFO;
886 set_param.payload.param_id = AFE_PARAM_ID_LOOPBACK_GAIN;
887 set_param.payload.param_size = sizeof(struct afe_param_loopback_gain);
888 set_param.payload.reserved = 0;
889
890 set_param.payload.param.loopback_gain.gain = volume;
891 set_param.payload.param.loopback_gain.reserved = 0;
892
893 atomic_set(&this_afe.state, 1);
894 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_param);
895 if (ret < 0) {
896 pr_err("%s: AFE param set failed for port %d\n",
897 __func__, port_id);
898 ret = -EINVAL;
899 goto fail_cmd;
900 }
901
902 ret = wait_event_timeout(this_afe.wait,
903 (atomic_read(&this_afe.state) == 0),
904 msecs_to_jiffies(TIMEOUT_MS));
905 if (ret < 0) {
906 pr_err("%s: wait_event timeout\n", __func__);
907 ret = -EINVAL;
908 goto fail_cmd;
909 }
910 return 0;
911fail_cmd:
912 return ret;
913}
914
Laxminath Kasam885f5102011-07-14 10:20:21 +0530915int afe_apply_gain(u16 port_id, u16 gain)
916{
917 struct afe_port_gain_command set_gain;
918 int ret = 0;
919
920 if (this_afe.apr == NULL) {
921 pr_err("%s: AFE is not opened\n", __func__);
922 ret = -EPERM;
923 goto fail_cmd;
924 }
925
926 if (afe_validate_port(port_id) < 0) {
927 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
928 port_id);
929 ret = -EINVAL;
930 goto fail_cmd;
931 }
932
933 /* RX ports numbers are even .TX ports numbers are odd. */
934 if (port_id % 2 == 0) {
935 pr_err("%s: Failed : afe apply gain only for TX ports."
936 " port_id %d\n", __func__, port_id);
937 ret = -EINVAL;
938 goto fail_cmd;
939 }
940
941 pr_debug("%s: %d %hX\n", __func__, port_id, gain);
942
943 set_gain.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
944 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
945 set_gain.hdr.pkt_size = sizeof(set_gain);
946 set_gain.hdr.src_port = 0;
947 set_gain.hdr.dest_port = 0;
948 set_gain.hdr.token = 0;
949 set_gain.hdr.opcode = AFE_PORT_CMD_APPLY_GAIN;
950
951 set_gain.port_id = port_id;
952 set_gain.gain = gain;
953
954 atomic_set(&this_afe.state, 1);
955 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_gain);
956 if (ret < 0) {
957 pr_err("%s: AFE Gain set failed for port %d\n",
958 __func__, port_id);
959 ret = -EINVAL;
960 goto fail_cmd;
961 }
962
963 ret = wait_event_timeout(this_afe.wait,
964 (atomic_read(&this_afe.state) == 0),
965 msecs_to_jiffies(TIMEOUT_MS));
966 if (ret < 0) {
967 pr_err("%s: wait_event timeout\n", __func__);
968 ret = -EINVAL;
969 goto fail_cmd;
970 }
971 return 0;
972fail_cmd:
973 return ret;
974}
Helen Zeng0705a5f2011-10-14 15:29:52 -0700975
976int afe_pseudo_port_start_nowait(u16 port_id)
977{
978 int ret = 0;
979 struct afe_pseudoport_start_command start;
980
981 pr_debug("%s: port_id=%d\n", __func__, port_id);
982 if (this_afe.apr == NULL) {
983 pr_err("%s: AFE APR is not registered\n", __func__);
984 return -ENODEV;
985 }
986
987
988 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
989 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
990 start.hdr.pkt_size = sizeof(start);
991 start.hdr.src_port = 0;
992 start.hdr.dest_port = 0;
993 start.hdr.token = 0;
994 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
995 start.port_id = port_id;
996 start.timing = 1;
997
998 atomic_set(&this_afe.state, 1);
999 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
1000 if (ret < 0) {
1001 pr_err("%s: AFE enable for port %d failed %d\n",
1002 __func__, port_id, ret);
1003 return -EINVAL;
1004 }
1005 return 0;
1006}
1007
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001008int afe_start_pseudo_port(u16 port_id)
1009{
1010 int ret = 0;
1011 struct afe_pseudoport_start_command start;
1012
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001013 pr_debug("%s: port_id=%d\n", __func__, port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001014
Jay Wang6a305432011-08-05 16:01:54 -07001015 ret = afe_q6_interface_prepare();
1016 if (ret != 0)
1017 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001018
1019 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1020 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1021 start.hdr.pkt_size = sizeof(start);
1022 start.hdr.src_port = 0;
1023 start.hdr.dest_port = 0;
1024 start.hdr.token = 0;
1025 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
1026 start.port_id = port_id;
1027 start.timing = 1;
1028
1029 atomic_set(&this_afe.state, 1);
1030 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
1031 if (ret < 0) {
1032 pr_err("%s: AFE enable for port %d failed %d\n",
1033 __func__, port_id, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001034 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001035 }
1036
1037 ret = wait_event_timeout(this_afe.wait,
1038 (atomic_read(&this_afe.state) == 0),
1039 msecs_to_jiffies(TIMEOUT_MS));
1040 if (!ret) {
1041 pr_err("%s: wait_event timeout\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001042 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001043 }
1044
1045 return 0;
1046}
1047
Helen Zeng0705a5f2011-10-14 15:29:52 -07001048int afe_pseudo_port_stop_nowait(u16 port_id)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001049{
1050 int ret = 0;
1051 struct afe_pseudoport_stop_command stop;
1052
Helen Zeng0705a5f2011-10-14 15:29:52 -07001053 pr_debug("%s: port_id=%d\n", __func__, port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001054
1055 if (this_afe.apr == NULL) {
1056 pr_err("%s: AFE is already closed\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001057 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001058 }
1059
1060 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1061 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1062 stop.hdr.pkt_size = sizeof(stop);
1063 stop.hdr.src_port = 0;
1064 stop.hdr.dest_port = 0;
1065 stop.hdr.token = 0;
1066 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
1067 stop.port_id = port_id;
1068 stop.reserved = 0;
1069
1070 atomic_set(&this_afe.state, 1);
1071 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1072 if (ret < 0) {
1073 pr_err("%s: AFE close failed %d\n", __func__, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001074 return -EINVAL;
1075 }
1076
1077 return 0;
1078
1079}
1080
1081int afe_stop_pseudo_port(u16 port_id)
1082{
1083 int ret = 0;
1084 struct afe_pseudoport_stop_command stop;
1085
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001086 pr_debug("%s: port_id=%d\n", __func__, port_id);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001087
1088 if (this_afe.apr == NULL) {
1089 pr_err("%s: AFE is already closed\n", __func__);
1090 return -EINVAL;
1091 }
1092
1093 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1094 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1095 stop.hdr.pkt_size = sizeof(stop);
1096 stop.hdr.src_port = 0;
1097 stop.hdr.dest_port = 0;
1098 stop.hdr.token = 0;
1099 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
1100 stop.port_id = port_id;
1101 stop.reserved = 0;
1102
1103 atomic_set(&this_afe.state, 1);
1104 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1105 if (ret < 0) {
1106 pr_err("%s: AFE close failed %d\n", __func__, ret);
1107 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001108 }
1109
1110 ret = wait_event_timeout(this_afe.wait,
1111 (atomic_read(&this_afe.state) == 0),
1112 msecs_to_jiffies(TIMEOUT_MS));
1113 if (!ret) {
1114 pr_err("%s: wait_event timeout\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001115 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001116 }
1117
1118 return 0;
1119}
1120
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301121int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz)
1122{
1123 int ret = 0;
1124 struct afe_cmd_memory_map mregion;
1125
1126 pr_debug("%s:\n", __func__);
1127
1128 if (this_afe.apr == NULL) {
1129 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1130 0xFFFFFFFF, &this_afe);
1131 pr_debug("%s: Register AFE\n", __func__);
1132 if (this_afe.apr == NULL) {
1133 pr_err("%s: Unable to register AFE\n", __func__);
1134 ret = -ENODEV;
1135 return ret;
1136 }
1137 }
1138
1139 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1140 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1141 mregion.hdr.pkt_size = sizeof(mregion);
1142 mregion.hdr.src_port = 0;
1143 mregion.hdr.dest_port = 0;
1144 mregion.hdr.token = 0;
1145 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
1146 mregion.phy_addr = dma_addr_p;
1147 mregion.mem_sz = dma_buf_sz;
1148 mregion.mem_id = 0;
1149 mregion.rsvd = 0;
1150
1151 atomic_set(&this_afe.state, 1);
1152 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1153 if (ret < 0) {
1154 pr_err("%s: AFE memory map cmd failed %d\n",
1155 __func__, ret);
1156 ret = -EINVAL;
1157 return ret;
1158 }
1159
1160 ret = wait_event_timeout(this_afe.wait,
1161 (atomic_read(&this_afe.state) == 0),
1162 msecs_to_jiffies(TIMEOUT_MS));
1163 if (!ret) {
1164 pr_err("%s: wait_event timeout\n", __func__);
1165 ret = -EINVAL;
1166 return ret;
1167 }
1168
1169 return 0;
1170}
1171
Ben Rombergerb7603232011-11-23 17:16:27 -08001172int afe_cmd_memory_map_nowait(u32 dma_addr_p, u32 dma_buf_sz)
1173{
1174 int ret = 0;
1175 struct afe_cmd_memory_map mregion;
1176
1177 pr_debug("%s:\n", __func__);
1178
1179 if (this_afe.apr == NULL) {
1180 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1181 0xFFFFFFFF, &this_afe);
1182 pr_debug("%s: Register AFE\n", __func__);
1183 if (this_afe.apr == NULL) {
1184 pr_err("%s: Unable to register AFE\n", __func__);
1185 ret = -ENODEV;
1186 return ret;
1187 }
1188 }
1189
1190 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1191 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1192 mregion.hdr.pkt_size = sizeof(mregion);
1193 mregion.hdr.src_port = 0;
1194 mregion.hdr.dest_port = 0;
1195 mregion.hdr.token = 0;
1196 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
1197 mregion.phy_addr = dma_addr_p;
1198 mregion.mem_sz = dma_buf_sz;
1199 mregion.mem_id = 0;
1200 mregion.rsvd = 0;
1201
1202 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1203 if (ret < 0) {
1204 pr_err("%s: AFE memory map cmd failed %d\n",
1205 __func__, ret);
1206 ret = -EINVAL;
1207 }
1208 return 0;
1209}
1210
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301211int afe_cmd_memory_unmap(u32 dma_addr_p)
1212{
1213 int ret = 0;
1214 struct afe_cmd_memory_unmap mregion;
1215
1216 pr_debug("%s:\n", __func__);
1217
1218 if (this_afe.apr == NULL) {
1219 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1220 0xFFFFFFFF, &this_afe);
1221 pr_debug("%s: Register AFE\n", __func__);
1222 if (this_afe.apr == NULL) {
1223 pr_err("%s: Unable to register AFE\n", __func__);
1224 ret = -ENODEV;
1225 return ret;
1226 }
1227 }
1228
1229 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1230 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1231 mregion.hdr.pkt_size = sizeof(mregion);
1232 mregion.hdr.src_port = 0;
1233 mregion.hdr.dest_port = 0;
1234 mregion.hdr.token = 0;
1235 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
1236 mregion.phy_addr = dma_addr_p;
1237
1238 atomic_set(&this_afe.state, 1);
1239 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1240 if (ret < 0) {
Ben Rombergerb7603232011-11-23 17:16:27 -08001241 pr_err("%s: AFE memory unmap cmd failed %d\n",
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301242 __func__, ret);
1243 ret = -EINVAL;
1244 return ret;
1245 }
1246
1247 ret = wait_event_timeout(this_afe.wait,
1248 (atomic_read(&this_afe.state) == 0),
1249 msecs_to_jiffies(TIMEOUT_MS));
1250 if (!ret) {
1251 pr_err("%s: wait_event timeout\n", __func__);
1252 ret = -EINVAL;
1253 return ret;
1254 }
Ben Rombergerb7603232011-11-23 17:16:27 -08001255 return 0;
1256}
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301257
Ben Rombergerb7603232011-11-23 17:16:27 -08001258int afe_cmd_memory_unmap_nowait(u32 dma_addr_p)
1259{
1260 int ret = 0;
1261 struct afe_cmd_memory_unmap mregion;
1262
1263 pr_debug("%s:\n", __func__);
1264
1265 if (this_afe.apr == NULL) {
1266 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1267 0xFFFFFFFF, &this_afe);
1268 pr_debug("%s: Register AFE\n", __func__);
1269 if (this_afe.apr == NULL) {
1270 pr_err("%s: Unable to register AFE\n", __func__);
1271 ret = -ENODEV;
1272 return ret;
1273 }
1274 }
1275
1276 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1277 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1278 mregion.hdr.pkt_size = sizeof(mregion);
1279 mregion.hdr.src_port = 0;
1280 mregion.hdr.dest_port = 0;
1281 mregion.hdr.token = 0;
1282 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
1283 mregion.phy_addr = dma_addr_p;
1284
1285 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1286 if (ret < 0) {
1287 pr_err("%s: AFE memory unmap cmd failed %d\n",
1288 __func__, ret);
1289 ret = -EINVAL;
1290 }
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301291 return 0;
1292}
1293
1294int afe_register_get_events(u16 port_id,
1295 void (*cb) (uint32_t opcode,
1296 uint32_t token, uint32_t *payload, void *priv),
1297 void *private_data)
1298{
1299 int ret = 0;
1300 struct afe_cmd_reg_rtport rtproxy;
1301
1302 pr_debug("%s:\n", __func__);
1303
1304 if (this_afe.apr == NULL) {
1305 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1306 0xFFFFFFFF, &this_afe);
1307 pr_debug("%s: Register AFE\n", __func__);
1308 if (this_afe.apr == NULL) {
1309 pr_err("%s: Unable to register AFE\n", __func__);
1310 ret = -ENODEV;
1311 return ret;
1312 }
1313 }
1314 if ((port_id == RT_PROXY_DAI_002_RX) ||
1315 (port_id == RT_PROXY_DAI_001_TX))
1316 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1317 else
1318 return -EINVAL;
1319
1320 if (port_id == RT_PROXY_PORT_001_TX) {
1321 this_afe.tx_cb = cb;
1322 this_afe.tx_private_data = private_data;
1323 } else if (port_id == RT_PROXY_PORT_001_RX) {
1324 this_afe.rx_cb = cb;
1325 this_afe.rx_private_data = private_data;
1326 }
1327
1328 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1329 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1330 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1331 rtproxy.hdr.src_port = 1;
1332 rtproxy.hdr.dest_port = 1;
1333 rtproxy.hdr.token = 0;
1334 rtproxy.hdr.opcode = AFE_SERVICE_CMD_REG_RTPORT;
1335 rtproxy.port_id = port_id;
1336 rtproxy.rsvd = 0;
1337
1338 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1339 if (ret < 0) {
1340 pr_err("%s: AFE reg. rtproxy_event failed %d\n",
1341 __func__, ret);
1342 ret = -EINVAL;
1343 return ret;
1344 }
1345 return 0;
1346}
1347
1348int afe_unregister_get_events(u16 port_id)
1349{
1350 int ret = 0;
1351 struct afe_cmd_unreg_rtport rtproxy;
1352
1353 pr_debug("%s:\n", __func__);
1354
1355 if (this_afe.apr == NULL) {
1356 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1357 0xFFFFFFFF, &this_afe);
1358 pr_debug("%s: Register AFE\n", __func__);
1359 if (this_afe.apr == NULL) {
1360 pr_err("%s: Unable to register AFE\n", __func__);
1361 ret = -ENODEV;
1362 return ret;
1363 }
1364 }
1365 if ((port_id == RT_PROXY_DAI_002_RX) ||
1366 (port_id == RT_PROXY_DAI_001_TX))
1367 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1368 else
1369 return -EINVAL;
1370
1371 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1372 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1373 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1374 rtproxy.hdr.src_port = 0;
1375 rtproxy.hdr.dest_port = 0;
1376 rtproxy.hdr.token = 0;
1377 rtproxy.hdr.opcode = AFE_SERVICE_CMD_UNREG_RTPORT;
1378 rtproxy.port_id = port_id;
1379 rtproxy.rsvd = 0;
1380
1381 if (port_id == RT_PROXY_PORT_001_TX) {
1382 this_afe.tx_cb = NULL;
1383 this_afe.tx_private_data = NULL;
1384 } else if (port_id == RT_PROXY_PORT_001_RX) {
1385 this_afe.rx_cb = NULL;
1386 this_afe.rx_private_data = NULL;
1387 }
1388
1389 atomic_set(&this_afe.state, 1);
1390 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1391 if (ret < 0) {
1392 pr_err("%s: AFE enable Unreg. rtproxy_event failed %d\n",
1393 __func__, ret);
1394 ret = -EINVAL;
1395 return ret;
1396 }
1397
1398 ret = wait_event_timeout(this_afe.wait,
1399 (atomic_read(&this_afe.state) == 0),
1400 msecs_to_jiffies(TIMEOUT_MS));
1401 if (!ret) {
1402 pr_err("%s: wait_event timeout\n", __func__);
1403 ret = -EINVAL;
1404 return ret;
1405 }
1406 return 0;
1407}
1408
1409int afe_rt_proxy_port_write(u32 buf_addr_p, int bytes)
1410{
1411 int ret = 0;
1412 struct afe_cmd_rtport_wr afecmd_wr;
1413
1414 if (this_afe.apr == NULL) {
1415 pr_err("%s:register to AFE is not done\n", __func__);
1416 ret = -ENODEV;
1417 return ret;
1418 }
1419 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1420 buf_addr_p, bytes);
1421
1422 afecmd_wr.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1423 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1424 afecmd_wr.hdr.pkt_size = sizeof(afecmd_wr);
1425 afecmd_wr.hdr.src_port = 0;
1426 afecmd_wr.hdr.dest_port = 0;
1427 afecmd_wr.hdr.token = 0;
1428 afecmd_wr.hdr.opcode = AFE_SERVICE_CMD_RTPORT_WR;
1429 afecmd_wr.buf_addr = (uint32_t)buf_addr_p;
1430 afecmd_wr.port_id = RT_PROXY_PORT_001_TX;
1431 afecmd_wr.bytes_avail = bytes;
1432 afecmd_wr.rsvd = 0;
1433
1434 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_wr);
1435 if (ret < 0) {
1436 pr_err("%s: AFE rtproxy write to port 0x%x failed %d\n",
1437 __func__, afecmd_wr.port_id, ret);
1438 ret = -EINVAL;
1439 return ret;
1440 }
1441 return 0;
1442
1443}
1444
1445int afe_rt_proxy_port_read(u32 buf_addr_p, int bytes)
1446{
1447 int ret = 0;
1448 struct afe_cmd_rtport_rd afecmd_rd;
1449
1450 if (this_afe.apr == NULL) {
1451 pr_err("%s: register to AFE is not done\n", __func__);
1452 ret = -ENODEV;
1453 return ret;
1454 }
1455 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1456 buf_addr_p, bytes);
1457
1458 afecmd_rd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1459 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1460 afecmd_rd.hdr.pkt_size = sizeof(afecmd_rd);
1461 afecmd_rd.hdr.src_port = 0;
1462 afecmd_rd.hdr.dest_port = 0;
1463 afecmd_rd.hdr.token = 0;
1464 afecmd_rd.hdr.opcode = AFE_SERVICE_CMD_RTPORT_RD;
1465 afecmd_rd.buf_addr = (uint32_t)buf_addr_p;
1466 afecmd_rd.port_id = RT_PROXY_PORT_001_RX;
1467 afecmd_rd.bytes_avail = bytes;
1468 afecmd_rd.rsvd = 0;
1469
1470 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_rd);
1471 if (ret < 0) {
1472 pr_err("%s: AFE rtproxy read cmd to port 0x%x failed %d\n",
1473 __func__, afecmd_rd.port_id, ret);
1474 ret = -EINVAL;
1475 return ret;
1476 }
1477 return 0;
1478}
1479
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001480#ifdef CONFIG_DEBUG_FS
1481static struct dentry *debugfs_afelb;
1482static struct dentry *debugfs_afelb_gain;
1483
1484static int afe_debug_open(struct inode *inode, struct file *file)
1485{
1486 file->private_data = inode->i_private;
1487 pr_info("debug intf %s\n", (char *) file->private_data);
1488 return 0;
1489}
1490
1491static int afe_get_parameters(char *buf, long int *param1, int num_of_par)
1492{
1493 char *token;
1494 int base, cnt;
1495
1496 token = strsep(&buf, " ");
1497
1498 for (cnt = 0; cnt < num_of_par; cnt++) {
1499 if (token != NULL) {
1500 if ((token[1] == 'x') || (token[1] == 'X'))
1501 base = 16;
1502 else
1503 base = 10;
1504
1505 if (strict_strtoul(token, base, &param1[cnt]) != 0)
1506 return -EINVAL;
1507
1508 token = strsep(&buf, " ");
1509 } else
1510 return -EINVAL;
1511 }
1512 return 0;
1513}
1514#define AFE_LOOPBACK_ON (1)
1515#define AFE_LOOPBACK_OFF (0)
1516static ssize_t afe_debug_write(struct file *filp,
1517 const char __user *ubuf, size_t cnt, loff_t *ppos)
1518{
1519 char *lb_str = filp->private_data;
1520 char lbuf[32];
1521 int rc;
1522 unsigned long param[5];
1523
1524 if (cnt > sizeof(lbuf) - 1)
1525 return -EINVAL;
1526
1527 rc = copy_from_user(lbuf, ubuf, cnt);
1528 if (rc)
1529 return -EFAULT;
1530
1531 lbuf[cnt] = '\0';
1532
1533 if (!strcmp(lb_str, "afe_loopback")) {
1534 rc = afe_get_parameters(lbuf, param, 3);
1535 if (!rc) {
1536 pr_info("%s %lu %lu %lu\n", lb_str, param[0], param[1],
1537 param[2]);
1538
1539 if ((param[0] != AFE_LOOPBACK_ON) && (param[0] !=
1540 AFE_LOOPBACK_OFF)) {
1541 pr_err("%s: Error, parameter 0 incorrect\n",
1542 __func__);
1543 rc = -EINVAL;
1544 goto afe_error;
1545 }
1546 if ((afe_validate_port(param[1]) < 0) ||
1547 (afe_validate_port(param[2])) < 0) {
1548 pr_err("%s: Error, invalid afe port\n",
1549 __func__);
1550 }
1551 if (this_afe.apr == NULL) {
1552 pr_err("%s: Error, AFE not opened\n", __func__);
1553 rc = -EINVAL;
1554 } else {
1555 rc = afe_loopback(param[0], param[1], param[2]);
1556 }
1557 } else {
1558 pr_err("%s: Error, invalid parameters\n", __func__);
1559 rc = -EINVAL;
1560 }
1561
1562 } else if (!strcmp(lb_str, "afe_loopback_gain")) {
1563 rc = afe_get_parameters(lbuf, param, 2);
1564 if (!rc) {
1565 pr_info("%s %lu %lu\n", lb_str, param[0], param[1]);
1566
1567 if (afe_validate_port(param[0]) < 0) {
1568 pr_err("%s: Error, invalid afe port\n",
1569 __func__);
1570 rc = -EINVAL;
1571 goto afe_error;
1572 }
1573
1574 if (param[1] < 0 || param[1] > 100) {
1575 pr_err("%s: Error, volume shoud be 0 to 100"
1576 " percentage param = %lu\n",
1577 __func__, param[1]);
1578 rc = -EINVAL;
1579 goto afe_error;
1580 }
1581
1582 param[1] = (Q6AFE_MAX_VOLUME * param[1]) / 100;
1583
1584 if (this_afe.apr == NULL) {
1585 pr_err("%s: Error, AFE not opened\n", __func__);
1586 rc = -EINVAL;
1587 } else {
1588 rc = afe_loopback_gain(param[0], param[1]);
1589 }
1590 } else {
1591 pr_err("%s: Error, invalid parameters\n", __func__);
1592 rc = -EINVAL;
1593 }
1594 }
1595
1596afe_error:
1597 if (rc == 0)
1598 rc = cnt;
1599 else
1600 pr_err("%s: rc = %d\n", __func__, rc);
1601
1602 return rc;
1603}
1604
1605static const struct file_operations afe_debug_fops = {
1606 .open = afe_debug_open,
1607 .write = afe_debug_write
1608};
1609#endif
1610int afe_sidetone(u16 tx_port_id, u16 rx_port_id, u16 enable, uint16_t gain)
1611{
1612 struct afe_port_sidetone_command cmd_sidetone;
1613 int ret = 0;
1614
1615 pr_info("%s: tx_port_id:%d rx_port_id:%d enable:%d gain:%d\n", __func__,
1616 tx_port_id, rx_port_id, enable, gain);
1617 cmd_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1618 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1619 cmd_sidetone.hdr.pkt_size = sizeof(cmd_sidetone);
1620 cmd_sidetone.hdr.src_port = 0;
1621 cmd_sidetone.hdr.dest_port = 0;
1622 cmd_sidetone.hdr.token = 0;
1623 cmd_sidetone.hdr.opcode = AFE_PORT_CMD_SIDETONE_CTL;
1624 cmd_sidetone.tx_port_id = tx_port_id;
1625 cmd_sidetone.rx_port_id = rx_port_id;
1626 cmd_sidetone.gain = gain;
1627 cmd_sidetone.enable = enable;
1628
1629 atomic_set(&this_afe.state, 1);
1630 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_sidetone);
1631 if (ret < 0) {
1632 pr_err("%s: AFE sidetone failed for tx_port:%d rx_port:%d\n",
1633 __func__, tx_port_id, rx_port_id);
1634 ret = -EINVAL;
1635 goto fail_cmd;
1636 }
1637
1638 ret = wait_event_timeout(this_afe.wait,
1639 (atomic_read(&this_afe.state) == 0),
1640 msecs_to_jiffies(TIMEOUT_MS));
1641 if (ret < 0) {
1642 pr_err("%s: wait_event timeout\n", __func__);
1643 ret = -EINVAL;
1644 goto fail_cmd;
1645 }
1646 return 0;
1647fail_cmd:
1648 return ret;
1649}
1650
1651int afe_port_stop_nowait(int port_id)
1652{
1653 struct afe_port_stop_command stop;
1654 int ret = 0;
1655
1656 if (this_afe.apr == NULL) {
1657 pr_err("AFE is already closed\n");
1658 ret = -EINVAL;
1659 goto fail_cmd;
1660 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001661 pr_debug("%s: port_id=%d\n", __func__, port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301662 port_id = afe_convert_virtual_to_portid(port_id);
1663
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001664 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1665 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1666 stop.hdr.pkt_size = sizeof(stop);
1667 stop.hdr.src_port = 0;
1668 stop.hdr.dest_port = 0;
1669 stop.hdr.token = 0;
1670 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1671 stop.port_id = port_id;
1672 stop.reserved = 0;
1673
1674 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1675
1676 if (ret == -ENETRESET) {
1677 pr_info("%s: Need to reset, calling APR deregister", __func__);
1678 return apr_deregister(this_afe.apr);
1679 } else if (IS_ERR_VALUE(ret)) {
1680 pr_err("%s: AFE close failed\n", __func__);
1681 ret = -EINVAL;
1682 }
1683
1684fail_cmd:
1685 return ret;
1686
1687}
1688
1689int afe_close(int port_id)
1690{
1691 struct afe_port_stop_command stop;
1692 int ret = 0;
1693
1694 if (this_afe.apr == NULL) {
1695 pr_err("AFE is already closed\n");
1696 ret = -EINVAL;
1697 goto fail_cmd;
1698 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001699 pr_debug("%s: port_id=%d\n", __func__, port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301700 port_id = afe_convert_virtual_to_portid(port_id);
1701
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001702 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1703 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1704 stop.hdr.pkt_size = sizeof(stop);
1705 stop.hdr.src_port = 0;
1706 stop.hdr.dest_port = 0;
1707 stop.hdr.token = 0;
1708 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1709 stop.port_id = port_id;
1710 stop.reserved = 0;
1711
1712 atomic_set(&this_afe.state, 1);
1713 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1714
1715 if (ret == -ENETRESET) {
1716 pr_info("%s: Need to reset, calling APR deregister", __func__);
1717 return apr_deregister(this_afe.apr);
1718 }
1719
1720 if (ret < 0) {
1721 pr_err("%s: AFE close failed\n", __func__);
1722 ret = -EINVAL;
1723 goto fail_cmd;
1724 }
1725
1726 ret = wait_event_timeout(this_afe.wait,
1727 (atomic_read(&this_afe.state) == 0),
1728 msecs_to_jiffies(TIMEOUT_MS));
1729 if (!ret) {
1730 pr_err("%s: wait_event timeout\n", __func__);
1731 ret = -EINVAL;
1732 goto fail_cmd;
1733 }
1734fail_cmd:
1735 return ret;
1736}
1737
1738static int __init afe_init(void)
1739{
1740 init_waitqueue_head(&this_afe.wait);
1741 atomic_set(&this_afe.state, 0);
1742 atomic_set(&this_afe.status, 0);
1743 this_afe.apr = NULL;
1744#ifdef CONFIG_DEBUG_FS
1745 debugfs_afelb = debugfs_create_file("afe_loopback",
1746 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback",
1747 &afe_debug_fops);
1748
1749 debugfs_afelb_gain = debugfs_create_file("afe_loopback_gain",
1750 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback_gain",
1751 &afe_debug_fops);
1752
1753
1754#endif
1755 return 0;
1756}
1757
1758static void __exit afe_exit(void)
1759{
Ben Rombergerb7603232011-11-23 17:16:27 -08001760 int i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001761#ifdef CONFIG_DEBUG_FS
1762 if (debugfs_afelb)
1763 debugfs_remove(debugfs_afelb);
1764 if (debugfs_afelb_gain)
1765 debugfs_remove(debugfs_afelb_gain);
1766#endif
Ben Rombergerb7603232011-11-23 17:16:27 -08001767 for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
Ben Romberger9e792562012-02-24 12:29:01 -08001768 if (afe_cal_addr[i].cal_paddr != 0)
1769 afe_cmd_memory_unmap_nowait(
1770 afe_cal_addr[i].cal_paddr);
Ben Rombergerb7603232011-11-23 17:16:27 -08001771 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001772}
1773
1774device_initcall(afe_init);
1775__exitcall(afe_exit);