blob: a4f4b60cb1ba34373f669e9cc8f1e10743d8b3cf [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))
Asish Bhattacharyad482c992012-07-31 20:58:18 +0530451 return 0;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530452 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))
Asish Bhattacharyad482c992012-07-31 20:58:18 +0530611 return 0;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530612 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;
Patrick Lai48da1492012-07-04 20:48:24 -0700802 lp_cfg.payload_size = sizeof(struct afe_param_payload_base) +
803 sizeof(struct afe_param_loopback_cfg);
Neema Shetty74131ac2012-05-09 13:35:26 -0700804 lp_cfg.payload_address = 0;
805
Patrick Lai48da1492012-07-04 20:48:24 -0700806 lp_cfg.payload.base.module_id = AFE_MODULE_LOOPBACK;
807 lp_cfg.payload.base.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
808 lp_cfg.payload.base.param_size = sizeof(struct afe_param_loopback_cfg);
809 lp_cfg.payload.base.reserved = 0;
Neema Shetty74131ac2012-05-09 13:35:26 -0700810
811 lp_cfg.payload.param.loopback_cfg.loopback_cfg_minor_version =
812 AFE_API_VERSION_LOOPBACK_CONFIG;
813 lp_cfg.payload.param.loopback_cfg.dst_port_id = dst_port;
814 lp_cfg.payload.param.loopback_cfg.routing_mode = mode;
815 lp_cfg.payload.param.loopback_cfg.enable = enable;
816 lp_cfg.payload.param.loopback_cfg.reserved = 0;
817
818 atomic_set(&this_afe.state, 1);
819 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &lp_cfg);
820 if (ret < 0) {
821 pr_err("%s: AFE loopback config failed for src_port %d, dst_port %d\n",
822 __func__, src_port, dst_port);
823 ret = -EINVAL;
824 goto fail_cmd;
825 }
826
827 ret = wait_event_timeout(this_afe.wait,
828 (atomic_read(&this_afe.state) == 0),
829 msecs_to_jiffies(TIMEOUT_MS));
830 if (ret < 0) {
831 pr_err("%s: wait_event timeout\n", __func__);
832 ret = -EINVAL;
833 goto fail_cmd;
834 }
835 return 0;
836fail_cmd:
837 return ret;
838}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700839
840int afe_loopback_gain(u16 port_id, u16 volume)
841{
842 struct afe_port_cmd_set_param set_param;
843 int ret = 0;
844
845 if (this_afe.apr == NULL) {
Jayasena Sangaraboina82435032011-07-26 15:23:00 -0700846 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
847 0xFFFFFFFF, &this_afe);
848 pr_debug("%s: Register AFE\n", __func__);
849 if (this_afe.apr == NULL) {
850 pr_err("%s: Unable to register AFE\n", __func__);
851 ret = -ENODEV;
852 return ret;
853 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700854 }
855
856 if (afe_validate_port(port_id) < 0) {
857
858 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
859 port_id);
860 ret = -EINVAL;
861 goto fail_cmd;
862 }
863
864 /* RX ports numbers are even .TX ports numbers are odd. */
865 if (port_id % 2 == 0) {
866 pr_err("%s: Failed : afe loopback gain only for TX ports."
867 " port_id %d\n", __func__, port_id);
868 ret = -EINVAL;
869 goto fail_cmd;
870 }
871
872 pr_debug("%s: %d %hX\n", __func__, port_id, volume);
873
874 set_param.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
875 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
876 set_param.hdr.pkt_size = sizeof(set_param);
877 set_param.hdr.src_port = 0;
878 set_param.hdr.dest_port = 0;
879 set_param.hdr.token = 0;
880 set_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
881
882 set_param.port_id = port_id;
Patrick Lai48da1492012-07-04 20:48:24 -0700883 set_param.payload_size = sizeof(struct afe_param_payload_base) +
884 sizeof(struct afe_param_loopback_gain);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700885 set_param.payload_address = 0;
886
Patrick Lai48da1492012-07-04 20:48:24 -0700887 set_param.payload.base.module_id = AFE_MODULE_ID_PORT_INFO;
888 set_param.payload.base.param_id = AFE_PARAM_ID_LOOPBACK_GAIN;
889 set_param.payload.base.param_size =
890 sizeof(struct afe_param_loopback_gain);
891 set_param.payload.base.reserved = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700892
893 set_param.payload.param.loopback_gain.gain = volume;
894 set_param.payload.param.loopback_gain.reserved = 0;
895
896 atomic_set(&this_afe.state, 1);
897 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_param);
898 if (ret < 0) {
899 pr_err("%s: AFE param set failed for port %d\n",
900 __func__, port_id);
901 ret = -EINVAL;
902 goto fail_cmd;
903 }
904
905 ret = wait_event_timeout(this_afe.wait,
906 (atomic_read(&this_afe.state) == 0),
907 msecs_to_jiffies(TIMEOUT_MS));
908 if (ret < 0) {
909 pr_err("%s: wait_event timeout\n", __func__);
910 ret = -EINVAL;
911 goto fail_cmd;
912 }
913 return 0;
914fail_cmd:
915 return ret;
916}
917
Laxminath Kasam885f5102011-07-14 10:20:21 +0530918int afe_apply_gain(u16 port_id, u16 gain)
919{
920 struct afe_port_gain_command set_gain;
921 int ret = 0;
922
923 if (this_afe.apr == NULL) {
924 pr_err("%s: AFE is not opened\n", __func__);
925 ret = -EPERM;
926 goto fail_cmd;
927 }
928
929 if (afe_validate_port(port_id) < 0) {
930 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
931 port_id);
932 ret = -EINVAL;
933 goto fail_cmd;
934 }
935
936 /* RX ports numbers are even .TX ports numbers are odd. */
937 if (port_id % 2 == 0) {
938 pr_err("%s: Failed : afe apply gain only for TX ports."
939 " port_id %d\n", __func__, port_id);
940 ret = -EINVAL;
941 goto fail_cmd;
942 }
943
944 pr_debug("%s: %d %hX\n", __func__, port_id, gain);
945
946 set_gain.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
947 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
948 set_gain.hdr.pkt_size = sizeof(set_gain);
949 set_gain.hdr.src_port = 0;
950 set_gain.hdr.dest_port = 0;
951 set_gain.hdr.token = 0;
952 set_gain.hdr.opcode = AFE_PORT_CMD_APPLY_GAIN;
953
954 set_gain.port_id = port_id;
955 set_gain.gain = gain;
956
957 atomic_set(&this_afe.state, 1);
958 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_gain);
959 if (ret < 0) {
960 pr_err("%s: AFE Gain set failed for port %d\n",
961 __func__, port_id);
962 ret = -EINVAL;
963 goto fail_cmd;
964 }
965
966 ret = wait_event_timeout(this_afe.wait,
967 (atomic_read(&this_afe.state) == 0),
968 msecs_to_jiffies(TIMEOUT_MS));
969 if (ret < 0) {
970 pr_err("%s: wait_event timeout\n", __func__);
971 ret = -EINVAL;
972 goto fail_cmd;
973 }
974 return 0;
975fail_cmd:
976 return ret;
977}
Helen Zeng0705a5f2011-10-14 15:29:52 -0700978
979int afe_pseudo_port_start_nowait(u16 port_id)
980{
981 int ret = 0;
982 struct afe_pseudoport_start_command start;
983
984 pr_debug("%s: port_id=%d\n", __func__, port_id);
985 if (this_afe.apr == NULL) {
986 pr_err("%s: AFE APR is not registered\n", __func__);
987 return -ENODEV;
988 }
989
990
991 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
992 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
993 start.hdr.pkt_size = sizeof(start);
994 start.hdr.src_port = 0;
995 start.hdr.dest_port = 0;
996 start.hdr.token = 0;
997 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
998 start.port_id = port_id;
999 start.timing = 1;
1000
1001 atomic_set(&this_afe.state, 1);
1002 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
1003 if (ret < 0) {
1004 pr_err("%s: AFE enable for port %d failed %d\n",
1005 __func__, port_id, ret);
1006 return -EINVAL;
1007 }
1008 return 0;
1009}
1010
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001011int afe_start_pseudo_port(u16 port_id)
1012{
1013 int ret = 0;
1014 struct afe_pseudoport_start_command start;
1015
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001016 pr_debug("%s: port_id=%d\n", __func__, port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001017
Jay Wang6a305432011-08-05 16:01:54 -07001018 ret = afe_q6_interface_prepare();
1019 if (ret != 0)
1020 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001021
1022 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1023 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1024 start.hdr.pkt_size = sizeof(start);
1025 start.hdr.src_port = 0;
1026 start.hdr.dest_port = 0;
1027 start.hdr.token = 0;
1028 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
1029 start.port_id = port_id;
1030 start.timing = 1;
1031
1032 atomic_set(&this_afe.state, 1);
1033 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
1034 if (ret < 0) {
1035 pr_err("%s: AFE enable for port %d failed %d\n",
1036 __func__, port_id, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001037 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001038 }
1039
1040 ret = wait_event_timeout(this_afe.wait,
1041 (atomic_read(&this_afe.state) == 0),
1042 msecs_to_jiffies(TIMEOUT_MS));
1043 if (!ret) {
1044 pr_err("%s: wait_event timeout\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001045 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001046 }
1047
1048 return 0;
1049}
1050
Helen Zeng0705a5f2011-10-14 15:29:52 -07001051int afe_pseudo_port_stop_nowait(u16 port_id)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001052{
1053 int ret = 0;
1054 struct afe_pseudoport_stop_command stop;
1055
Helen Zeng0705a5f2011-10-14 15:29:52 -07001056 pr_debug("%s: port_id=%d\n", __func__, port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001057
1058 if (this_afe.apr == NULL) {
1059 pr_err("%s: AFE is already closed\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001060 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001061 }
1062
1063 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1064 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1065 stop.hdr.pkt_size = sizeof(stop);
1066 stop.hdr.src_port = 0;
1067 stop.hdr.dest_port = 0;
1068 stop.hdr.token = 0;
1069 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
1070 stop.port_id = port_id;
1071 stop.reserved = 0;
1072
1073 atomic_set(&this_afe.state, 1);
1074 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1075 if (ret < 0) {
1076 pr_err("%s: AFE close failed %d\n", __func__, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001077 return -EINVAL;
1078 }
1079
1080 return 0;
1081
1082}
1083
1084int afe_stop_pseudo_port(u16 port_id)
1085{
1086 int ret = 0;
1087 struct afe_pseudoport_stop_command stop;
1088
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001089 pr_debug("%s: port_id=%d\n", __func__, port_id);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001090
1091 if (this_afe.apr == NULL) {
1092 pr_err("%s: AFE is already closed\n", __func__);
1093 return -EINVAL;
1094 }
1095
1096 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1097 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1098 stop.hdr.pkt_size = sizeof(stop);
1099 stop.hdr.src_port = 0;
1100 stop.hdr.dest_port = 0;
1101 stop.hdr.token = 0;
1102 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
1103 stop.port_id = port_id;
1104 stop.reserved = 0;
1105
1106 atomic_set(&this_afe.state, 1);
1107 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1108 if (ret < 0) {
1109 pr_err("%s: AFE close failed %d\n", __func__, ret);
1110 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001111 }
1112
1113 ret = wait_event_timeout(this_afe.wait,
1114 (atomic_read(&this_afe.state) == 0),
1115 msecs_to_jiffies(TIMEOUT_MS));
1116 if (!ret) {
1117 pr_err("%s: wait_event timeout\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001118 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001119 }
1120
1121 return 0;
1122}
1123
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301124int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz)
1125{
1126 int ret = 0;
1127 struct afe_cmd_memory_map mregion;
1128
1129 pr_debug("%s:\n", __func__);
1130
1131 if (this_afe.apr == NULL) {
1132 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1133 0xFFFFFFFF, &this_afe);
1134 pr_debug("%s: Register AFE\n", __func__);
1135 if (this_afe.apr == NULL) {
1136 pr_err("%s: Unable to register AFE\n", __func__);
1137 ret = -ENODEV;
1138 return ret;
1139 }
1140 }
1141
1142 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1143 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1144 mregion.hdr.pkt_size = sizeof(mregion);
1145 mregion.hdr.src_port = 0;
1146 mregion.hdr.dest_port = 0;
1147 mregion.hdr.token = 0;
1148 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
1149 mregion.phy_addr = dma_addr_p;
1150 mregion.mem_sz = dma_buf_sz;
1151 mregion.mem_id = 0;
1152 mregion.rsvd = 0;
1153
1154 atomic_set(&this_afe.state, 1);
1155 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1156 if (ret < 0) {
1157 pr_err("%s: AFE memory map cmd failed %d\n",
1158 __func__, ret);
1159 ret = -EINVAL;
1160 return ret;
1161 }
1162
1163 ret = wait_event_timeout(this_afe.wait,
1164 (atomic_read(&this_afe.state) == 0),
1165 msecs_to_jiffies(TIMEOUT_MS));
1166 if (!ret) {
1167 pr_err("%s: wait_event timeout\n", __func__);
1168 ret = -EINVAL;
1169 return ret;
1170 }
1171
1172 return 0;
1173}
1174
Ben Rombergerb7603232011-11-23 17:16:27 -08001175int afe_cmd_memory_map_nowait(u32 dma_addr_p, u32 dma_buf_sz)
1176{
1177 int ret = 0;
1178 struct afe_cmd_memory_map mregion;
1179
1180 pr_debug("%s:\n", __func__);
1181
1182 if (this_afe.apr == NULL) {
1183 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1184 0xFFFFFFFF, &this_afe);
1185 pr_debug("%s: Register AFE\n", __func__);
1186 if (this_afe.apr == NULL) {
1187 pr_err("%s: Unable to register AFE\n", __func__);
1188 ret = -ENODEV;
1189 return ret;
1190 }
1191 }
1192
1193 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1194 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1195 mregion.hdr.pkt_size = sizeof(mregion);
1196 mregion.hdr.src_port = 0;
1197 mregion.hdr.dest_port = 0;
1198 mregion.hdr.token = 0;
1199 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
1200 mregion.phy_addr = dma_addr_p;
1201 mregion.mem_sz = dma_buf_sz;
1202 mregion.mem_id = 0;
1203 mregion.rsvd = 0;
1204
1205 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1206 if (ret < 0) {
1207 pr_err("%s: AFE memory map cmd failed %d\n",
1208 __func__, ret);
1209 ret = -EINVAL;
1210 }
1211 return 0;
1212}
1213
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301214int afe_cmd_memory_unmap(u32 dma_addr_p)
1215{
1216 int ret = 0;
1217 struct afe_cmd_memory_unmap mregion;
1218
1219 pr_debug("%s:\n", __func__);
1220
1221 if (this_afe.apr == NULL) {
1222 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1223 0xFFFFFFFF, &this_afe);
1224 pr_debug("%s: Register AFE\n", __func__);
1225 if (this_afe.apr == NULL) {
1226 pr_err("%s: Unable to register AFE\n", __func__);
1227 ret = -ENODEV;
1228 return ret;
1229 }
1230 }
1231
1232 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1233 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1234 mregion.hdr.pkt_size = sizeof(mregion);
1235 mregion.hdr.src_port = 0;
1236 mregion.hdr.dest_port = 0;
1237 mregion.hdr.token = 0;
1238 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
1239 mregion.phy_addr = dma_addr_p;
1240
1241 atomic_set(&this_afe.state, 1);
1242 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1243 if (ret < 0) {
Ben Rombergerb7603232011-11-23 17:16:27 -08001244 pr_err("%s: AFE memory unmap cmd failed %d\n",
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301245 __func__, ret);
1246 ret = -EINVAL;
1247 return ret;
1248 }
1249
1250 ret = wait_event_timeout(this_afe.wait,
1251 (atomic_read(&this_afe.state) == 0),
1252 msecs_to_jiffies(TIMEOUT_MS));
1253 if (!ret) {
1254 pr_err("%s: wait_event timeout\n", __func__);
1255 ret = -EINVAL;
1256 return ret;
1257 }
Ben Rombergerb7603232011-11-23 17:16:27 -08001258 return 0;
1259}
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301260
Ben Rombergerb7603232011-11-23 17:16:27 -08001261int afe_cmd_memory_unmap_nowait(u32 dma_addr_p)
1262{
1263 int ret = 0;
1264 struct afe_cmd_memory_unmap mregion;
1265
1266 pr_debug("%s:\n", __func__);
1267
1268 if (this_afe.apr == NULL) {
1269 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1270 0xFFFFFFFF, &this_afe);
1271 pr_debug("%s: Register AFE\n", __func__);
1272 if (this_afe.apr == NULL) {
1273 pr_err("%s: Unable to register AFE\n", __func__);
1274 ret = -ENODEV;
1275 return ret;
1276 }
1277 }
1278
1279 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1280 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1281 mregion.hdr.pkt_size = sizeof(mregion);
1282 mregion.hdr.src_port = 0;
1283 mregion.hdr.dest_port = 0;
1284 mregion.hdr.token = 0;
1285 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
1286 mregion.phy_addr = dma_addr_p;
1287
1288 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1289 if (ret < 0) {
1290 pr_err("%s: AFE memory unmap cmd failed %d\n",
1291 __func__, ret);
1292 ret = -EINVAL;
1293 }
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301294 return 0;
1295}
1296
1297int afe_register_get_events(u16 port_id,
1298 void (*cb) (uint32_t opcode,
1299 uint32_t token, uint32_t *payload, void *priv),
1300 void *private_data)
1301{
1302 int ret = 0;
1303 struct afe_cmd_reg_rtport rtproxy;
1304
1305 pr_debug("%s:\n", __func__);
1306
1307 if (this_afe.apr == NULL) {
1308 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1309 0xFFFFFFFF, &this_afe);
1310 pr_debug("%s: Register AFE\n", __func__);
1311 if (this_afe.apr == NULL) {
1312 pr_err("%s: Unable to register AFE\n", __func__);
1313 ret = -ENODEV;
1314 return ret;
1315 }
1316 }
1317 if ((port_id == RT_PROXY_DAI_002_RX) ||
1318 (port_id == RT_PROXY_DAI_001_TX))
1319 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1320 else
1321 return -EINVAL;
1322
1323 if (port_id == RT_PROXY_PORT_001_TX) {
1324 this_afe.tx_cb = cb;
1325 this_afe.tx_private_data = private_data;
1326 } else if (port_id == RT_PROXY_PORT_001_RX) {
1327 this_afe.rx_cb = cb;
1328 this_afe.rx_private_data = private_data;
1329 }
1330
1331 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1332 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1333 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1334 rtproxy.hdr.src_port = 1;
1335 rtproxy.hdr.dest_port = 1;
1336 rtproxy.hdr.token = 0;
1337 rtproxy.hdr.opcode = AFE_SERVICE_CMD_REG_RTPORT;
1338 rtproxy.port_id = port_id;
1339 rtproxy.rsvd = 0;
1340
1341 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1342 if (ret < 0) {
1343 pr_err("%s: AFE reg. rtproxy_event failed %d\n",
1344 __func__, ret);
1345 ret = -EINVAL;
1346 return ret;
1347 }
1348 return 0;
1349}
1350
1351int afe_unregister_get_events(u16 port_id)
1352{
1353 int ret = 0;
1354 struct afe_cmd_unreg_rtport rtproxy;
1355
1356 pr_debug("%s:\n", __func__);
1357
1358 if (this_afe.apr == NULL) {
1359 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1360 0xFFFFFFFF, &this_afe);
1361 pr_debug("%s: Register AFE\n", __func__);
1362 if (this_afe.apr == NULL) {
1363 pr_err("%s: Unable to register AFE\n", __func__);
1364 ret = -ENODEV;
1365 return ret;
1366 }
1367 }
1368 if ((port_id == RT_PROXY_DAI_002_RX) ||
1369 (port_id == RT_PROXY_DAI_001_TX))
1370 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1371 else
1372 return -EINVAL;
1373
1374 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1375 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1376 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1377 rtproxy.hdr.src_port = 0;
1378 rtproxy.hdr.dest_port = 0;
1379 rtproxy.hdr.token = 0;
1380 rtproxy.hdr.opcode = AFE_SERVICE_CMD_UNREG_RTPORT;
1381 rtproxy.port_id = port_id;
1382 rtproxy.rsvd = 0;
1383
1384 if (port_id == RT_PROXY_PORT_001_TX) {
1385 this_afe.tx_cb = NULL;
1386 this_afe.tx_private_data = NULL;
1387 } else if (port_id == RT_PROXY_PORT_001_RX) {
1388 this_afe.rx_cb = NULL;
1389 this_afe.rx_private_data = NULL;
1390 }
1391
1392 atomic_set(&this_afe.state, 1);
1393 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1394 if (ret < 0) {
1395 pr_err("%s: AFE enable Unreg. rtproxy_event failed %d\n",
1396 __func__, ret);
1397 ret = -EINVAL;
1398 return ret;
1399 }
1400
1401 ret = wait_event_timeout(this_afe.wait,
1402 (atomic_read(&this_afe.state) == 0),
1403 msecs_to_jiffies(TIMEOUT_MS));
1404 if (!ret) {
1405 pr_err("%s: wait_event timeout\n", __func__);
1406 ret = -EINVAL;
1407 return ret;
1408 }
1409 return 0;
1410}
1411
1412int afe_rt_proxy_port_write(u32 buf_addr_p, int bytes)
1413{
1414 int ret = 0;
1415 struct afe_cmd_rtport_wr afecmd_wr;
1416
1417 if (this_afe.apr == NULL) {
1418 pr_err("%s:register to AFE is not done\n", __func__);
1419 ret = -ENODEV;
1420 return ret;
1421 }
1422 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1423 buf_addr_p, bytes);
1424
1425 afecmd_wr.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1426 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1427 afecmd_wr.hdr.pkt_size = sizeof(afecmd_wr);
1428 afecmd_wr.hdr.src_port = 0;
1429 afecmd_wr.hdr.dest_port = 0;
1430 afecmd_wr.hdr.token = 0;
1431 afecmd_wr.hdr.opcode = AFE_SERVICE_CMD_RTPORT_WR;
1432 afecmd_wr.buf_addr = (uint32_t)buf_addr_p;
1433 afecmd_wr.port_id = RT_PROXY_PORT_001_TX;
1434 afecmd_wr.bytes_avail = bytes;
1435 afecmd_wr.rsvd = 0;
1436
1437 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_wr);
1438 if (ret < 0) {
1439 pr_err("%s: AFE rtproxy write to port 0x%x failed %d\n",
1440 __func__, afecmd_wr.port_id, ret);
1441 ret = -EINVAL;
1442 return ret;
1443 }
1444 return 0;
1445
1446}
1447
1448int afe_rt_proxy_port_read(u32 buf_addr_p, int bytes)
1449{
1450 int ret = 0;
1451 struct afe_cmd_rtport_rd afecmd_rd;
1452
1453 if (this_afe.apr == NULL) {
1454 pr_err("%s: register to AFE is not done\n", __func__);
1455 ret = -ENODEV;
1456 return ret;
1457 }
1458 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1459 buf_addr_p, bytes);
1460
1461 afecmd_rd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1462 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1463 afecmd_rd.hdr.pkt_size = sizeof(afecmd_rd);
1464 afecmd_rd.hdr.src_port = 0;
1465 afecmd_rd.hdr.dest_port = 0;
1466 afecmd_rd.hdr.token = 0;
1467 afecmd_rd.hdr.opcode = AFE_SERVICE_CMD_RTPORT_RD;
1468 afecmd_rd.buf_addr = (uint32_t)buf_addr_p;
1469 afecmd_rd.port_id = RT_PROXY_PORT_001_RX;
1470 afecmd_rd.bytes_avail = bytes;
1471 afecmd_rd.rsvd = 0;
1472
1473 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_rd);
1474 if (ret < 0) {
1475 pr_err("%s: AFE rtproxy read cmd to port 0x%x failed %d\n",
1476 __func__, afecmd_rd.port_id, ret);
1477 ret = -EINVAL;
1478 return ret;
1479 }
1480 return 0;
1481}
1482
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001483#ifdef CONFIG_DEBUG_FS
1484static struct dentry *debugfs_afelb;
1485static struct dentry *debugfs_afelb_gain;
1486
1487static int afe_debug_open(struct inode *inode, struct file *file)
1488{
1489 file->private_data = inode->i_private;
1490 pr_info("debug intf %s\n", (char *) file->private_data);
1491 return 0;
1492}
1493
1494static int afe_get_parameters(char *buf, long int *param1, int num_of_par)
1495{
1496 char *token;
1497 int base, cnt;
1498
1499 token = strsep(&buf, " ");
1500
1501 for (cnt = 0; cnt < num_of_par; cnt++) {
1502 if (token != NULL) {
1503 if ((token[1] == 'x') || (token[1] == 'X'))
1504 base = 16;
1505 else
1506 base = 10;
1507
1508 if (strict_strtoul(token, base, &param1[cnt]) != 0)
1509 return -EINVAL;
1510
1511 token = strsep(&buf, " ");
1512 } else
1513 return -EINVAL;
1514 }
1515 return 0;
1516}
1517#define AFE_LOOPBACK_ON (1)
1518#define AFE_LOOPBACK_OFF (0)
1519static ssize_t afe_debug_write(struct file *filp,
1520 const char __user *ubuf, size_t cnt, loff_t *ppos)
1521{
1522 char *lb_str = filp->private_data;
1523 char lbuf[32];
1524 int rc;
1525 unsigned long param[5];
1526
1527 if (cnt > sizeof(lbuf) - 1)
1528 return -EINVAL;
1529
1530 rc = copy_from_user(lbuf, ubuf, cnt);
1531 if (rc)
1532 return -EFAULT;
1533
1534 lbuf[cnt] = '\0';
1535
1536 if (!strcmp(lb_str, "afe_loopback")) {
1537 rc = afe_get_parameters(lbuf, param, 3);
1538 if (!rc) {
1539 pr_info("%s %lu %lu %lu\n", lb_str, param[0], param[1],
1540 param[2]);
1541
1542 if ((param[0] != AFE_LOOPBACK_ON) && (param[0] !=
1543 AFE_LOOPBACK_OFF)) {
1544 pr_err("%s: Error, parameter 0 incorrect\n",
1545 __func__);
1546 rc = -EINVAL;
1547 goto afe_error;
1548 }
1549 if ((afe_validate_port(param[1]) < 0) ||
1550 (afe_validate_port(param[2])) < 0) {
1551 pr_err("%s: Error, invalid afe port\n",
1552 __func__);
1553 }
1554 if (this_afe.apr == NULL) {
1555 pr_err("%s: Error, AFE not opened\n", __func__);
1556 rc = -EINVAL;
1557 } else {
1558 rc = afe_loopback(param[0], param[1], param[2]);
1559 }
1560 } else {
1561 pr_err("%s: Error, invalid parameters\n", __func__);
1562 rc = -EINVAL;
1563 }
1564
1565 } else if (!strcmp(lb_str, "afe_loopback_gain")) {
1566 rc = afe_get_parameters(lbuf, param, 2);
1567 if (!rc) {
1568 pr_info("%s %lu %lu\n", lb_str, param[0], param[1]);
1569
1570 if (afe_validate_port(param[0]) < 0) {
1571 pr_err("%s: Error, invalid afe port\n",
1572 __func__);
1573 rc = -EINVAL;
1574 goto afe_error;
1575 }
1576
1577 if (param[1] < 0 || param[1] > 100) {
1578 pr_err("%s: Error, volume shoud be 0 to 100"
1579 " percentage param = %lu\n",
1580 __func__, param[1]);
1581 rc = -EINVAL;
1582 goto afe_error;
1583 }
1584
1585 param[1] = (Q6AFE_MAX_VOLUME * param[1]) / 100;
1586
1587 if (this_afe.apr == NULL) {
1588 pr_err("%s: Error, AFE not opened\n", __func__);
1589 rc = -EINVAL;
1590 } else {
1591 rc = afe_loopback_gain(param[0], param[1]);
1592 }
1593 } else {
1594 pr_err("%s: Error, invalid parameters\n", __func__);
1595 rc = -EINVAL;
1596 }
1597 }
1598
1599afe_error:
1600 if (rc == 0)
1601 rc = cnt;
1602 else
1603 pr_err("%s: rc = %d\n", __func__, rc);
1604
1605 return rc;
1606}
1607
1608static const struct file_operations afe_debug_fops = {
1609 .open = afe_debug_open,
1610 .write = afe_debug_write
1611};
1612#endif
1613int afe_sidetone(u16 tx_port_id, u16 rx_port_id, u16 enable, uint16_t gain)
1614{
1615 struct afe_port_sidetone_command cmd_sidetone;
1616 int ret = 0;
1617
1618 pr_info("%s: tx_port_id:%d rx_port_id:%d enable:%d gain:%d\n", __func__,
1619 tx_port_id, rx_port_id, enable, gain);
1620 cmd_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1621 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1622 cmd_sidetone.hdr.pkt_size = sizeof(cmd_sidetone);
1623 cmd_sidetone.hdr.src_port = 0;
1624 cmd_sidetone.hdr.dest_port = 0;
1625 cmd_sidetone.hdr.token = 0;
1626 cmd_sidetone.hdr.opcode = AFE_PORT_CMD_SIDETONE_CTL;
1627 cmd_sidetone.tx_port_id = tx_port_id;
1628 cmd_sidetone.rx_port_id = rx_port_id;
1629 cmd_sidetone.gain = gain;
1630 cmd_sidetone.enable = enable;
1631
1632 atomic_set(&this_afe.state, 1);
1633 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_sidetone);
1634 if (ret < 0) {
1635 pr_err("%s: AFE sidetone failed for tx_port:%d rx_port:%d\n",
1636 __func__, tx_port_id, rx_port_id);
1637 ret = -EINVAL;
1638 goto fail_cmd;
1639 }
1640
1641 ret = wait_event_timeout(this_afe.wait,
1642 (atomic_read(&this_afe.state) == 0),
1643 msecs_to_jiffies(TIMEOUT_MS));
1644 if (ret < 0) {
1645 pr_err("%s: wait_event timeout\n", __func__);
1646 ret = -EINVAL;
1647 goto fail_cmd;
1648 }
1649 return 0;
1650fail_cmd:
1651 return ret;
1652}
1653
1654int afe_port_stop_nowait(int port_id)
1655{
1656 struct afe_port_stop_command stop;
1657 int ret = 0;
1658
1659 if (this_afe.apr == NULL) {
1660 pr_err("AFE is already closed\n");
1661 ret = -EINVAL;
1662 goto fail_cmd;
1663 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001664 pr_debug("%s: port_id=%d\n", __func__, port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301665 port_id = afe_convert_virtual_to_portid(port_id);
1666
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001667 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1668 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1669 stop.hdr.pkt_size = sizeof(stop);
1670 stop.hdr.src_port = 0;
1671 stop.hdr.dest_port = 0;
1672 stop.hdr.token = 0;
1673 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1674 stop.port_id = port_id;
1675 stop.reserved = 0;
1676
1677 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1678
1679 if (ret == -ENETRESET) {
1680 pr_info("%s: Need to reset, calling APR deregister", __func__);
1681 return apr_deregister(this_afe.apr);
1682 } else if (IS_ERR_VALUE(ret)) {
1683 pr_err("%s: AFE close failed\n", __func__);
1684 ret = -EINVAL;
1685 }
1686
1687fail_cmd:
1688 return ret;
1689
1690}
1691
1692int afe_close(int port_id)
1693{
1694 struct afe_port_stop_command stop;
1695 int ret = 0;
1696
1697 if (this_afe.apr == NULL) {
1698 pr_err("AFE is already closed\n");
1699 ret = -EINVAL;
1700 goto fail_cmd;
1701 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001702 pr_debug("%s: port_id=%d\n", __func__, port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301703 port_id = afe_convert_virtual_to_portid(port_id);
1704
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001705 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1706 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1707 stop.hdr.pkt_size = sizeof(stop);
1708 stop.hdr.src_port = 0;
1709 stop.hdr.dest_port = 0;
1710 stop.hdr.token = 0;
1711 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1712 stop.port_id = port_id;
1713 stop.reserved = 0;
1714
1715 atomic_set(&this_afe.state, 1);
1716 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1717
1718 if (ret == -ENETRESET) {
1719 pr_info("%s: Need to reset, calling APR deregister", __func__);
1720 return apr_deregister(this_afe.apr);
1721 }
1722
1723 if (ret < 0) {
1724 pr_err("%s: AFE close failed\n", __func__);
1725 ret = -EINVAL;
1726 goto fail_cmd;
1727 }
1728
1729 ret = wait_event_timeout(this_afe.wait,
1730 (atomic_read(&this_afe.state) == 0),
1731 msecs_to_jiffies(TIMEOUT_MS));
1732 if (!ret) {
1733 pr_err("%s: wait_event timeout\n", __func__);
1734 ret = -EINVAL;
1735 goto fail_cmd;
1736 }
1737fail_cmd:
1738 return ret;
1739}
1740
1741static int __init afe_init(void)
1742{
1743 init_waitqueue_head(&this_afe.wait);
1744 atomic_set(&this_afe.state, 0);
1745 atomic_set(&this_afe.status, 0);
1746 this_afe.apr = NULL;
1747#ifdef CONFIG_DEBUG_FS
1748 debugfs_afelb = debugfs_create_file("afe_loopback",
1749 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback",
1750 &afe_debug_fops);
1751
1752 debugfs_afelb_gain = debugfs_create_file("afe_loopback_gain",
1753 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback_gain",
1754 &afe_debug_fops);
1755
1756
1757#endif
1758 return 0;
1759}
1760
1761static void __exit afe_exit(void)
1762{
Ben Rombergerb7603232011-11-23 17:16:27 -08001763 int i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001764#ifdef CONFIG_DEBUG_FS
1765 if (debugfs_afelb)
1766 debugfs_remove(debugfs_afelb);
1767 if (debugfs_afelb_gain)
1768 debugfs_remove(debugfs_afelb_gain);
1769#endif
Ben Rombergerb7603232011-11-23 17:16:27 -08001770 for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
Ben Romberger9e792562012-02-24 12:29:01 -08001771 if (afe_cal_addr[i].cal_paddr != 0)
1772 afe_cmd_memory_unmap_nowait(
1773 afe_cal_addr[i].cal_paddr);
Ben Rombergerb7603232011-11-23 17:16:27 -08001774 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001775}
1776
1777device_initcall(afe_init);
1778__exitcall(afe_exit);