blob: bac432dc3f8004e622bd84cc8a517d0d64be8b12 [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:
Kiran Kandi5e809b02012-01-31 00:24:33 -080080 case AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG:
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -080081 case AFE_PORT_AUDIO_SLIM_SCH_CONFIG:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070082 case AFE_PORT_CMD_STOP:
83 case AFE_PORT_CMD_START:
84 case AFE_PORT_CMD_LOOPBACK:
85 case AFE_PORT_CMD_SIDETONE_CTL:
86 case AFE_PORT_CMD_SET_PARAM:
87 case AFE_PSEUDOPORT_CMD_START:
88 case AFE_PSEUDOPORT_CMD_STOP:
Laxminath Kasam885f5102011-07-14 10:20:21 +053089 case AFE_PORT_CMD_APPLY_GAIN:
Laxminath Kasam32657ec2011-08-01 19:26:57 +053090 case AFE_SERVICE_CMD_MEMORY_MAP:
91 case AFE_SERVICE_CMD_MEMORY_UNMAP:
92 case AFE_SERVICE_CMD_UNREG_RTPORT:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070093 atomic_set(&this_afe.state, 0);
94 wake_up(&this_afe.wait);
95 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +053096 case AFE_SERVICE_CMD_REG_RTPORT:
97 break;
98 case AFE_SERVICE_CMD_RTPORT_WR:
99 port_id = RT_PROXY_PORT_001_TX;
100 break;
101 case AFE_SERVICE_CMD_RTPORT_RD:
102 port_id = RT_PROXY_PORT_001_RX;
103 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700104 default:
105 pr_err("Unknown cmd 0x%x\n",
106 payload[0]);
107 break;
108 }
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530109 } else if (data->opcode == AFE_EVENT_RT_PROXY_PORT_STATUS) {
110 port_id = (uint16_t)(0x0000FFFF & payload[0]);
111 }
112 pr_debug("%s:port_id = %x\n", __func__, port_id);
113 switch (port_id) {
114 case RT_PROXY_PORT_001_TX: {
115 if (this_afe.tx_cb) {
116 this_afe.tx_cb(data->opcode, data->token,
117 data->payload,
118 this_afe.tx_private_data);
119 }
120 break;
121 }
122 case RT_PROXY_PORT_001_RX: {
123 if (this_afe.rx_cb) {
124 this_afe.rx_cb(data->opcode, data->token,
125 data->payload,
126 this_afe.rx_private_data);
127 }
128 break;
129 }
130 default:
131 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700132 }
133 }
134 return 0;
135}
136
Neema Shettyfeea7742011-09-11 12:30:36 -0700137int afe_get_port_type(u16 port_id)
138{
139 int ret;
140
141 switch (port_id) {
142 case PRIMARY_I2S_RX:
143 case PCM_RX:
144 case SECONDARY_I2S_RX:
145 case MI2S_RX:
146 case HDMI_RX:
147 case SLIMBUS_0_RX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800148 case SLIMBUS_1_RX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700149 case INT_BT_SCO_RX:
150 case INT_BT_A2DP_RX:
151 case INT_FM_RX:
152 case VOICE_PLAYBACK_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530153 case RT_PROXY_PORT_001_RX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700154 ret = MSM_AFE_PORT_TYPE_RX;
155 break;
156
157 case PRIMARY_I2S_TX:
158 case PCM_TX:
159 case SECONDARY_I2S_TX:
160 case MI2S_TX:
161 case DIGI_MIC_TX:
162 case VOICE_RECORD_TX:
163 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800164 case SLIMBUS_1_TX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700165 case INT_FM_TX:
166 case VOICE_RECORD_RX:
167 case INT_BT_SCO_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530168 case RT_PROXY_PORT_001_TX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700169 ret = MSM_AFE_PORT_TYPE_TX;
170 break;
171
172 default:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800173 pr_err("%s: invalid port id %d\n", __func__, port_id);
Neema Shettyfeea7742011-09-11 12:30:36 -0700174 ret = -EINVAL;
175 }
176
177 return ret;
178}
179
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700180int afe_validate_port(u16 port_id)
181{
182 int ret;
183
184 switch (port_id) {
185 case PRIMARY_I2S_RX:
186 case PRIMARY_I2S_TX:
187 case PCM_RX:
188 case PCM_TX:
189 case SECONDARY_I2S_RX:
190 case SECONDARY_I2S_TX:
191 case MI2S_RX:
192 case MI2S_TX:
193 case HDMI_RX:
194 case RSVD_2:
195 case RSVD_3:
196 case DIGI_MIC_TX:
197 case VOICE_RECORD_RX:
198 case VOICE_RECORD_TX:
199 case VOICE_PLAYBACK_TX:
200 case SLIMBUS_0_RX:
201 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800202 case SLIMBUS_1_RX:
203 case SLIMBUS_1_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700204 case INT_BT_SCO_RX:
205 case INT_BT_SCO_TX:
206 case INT_BT_A2DP_RX:
207 case INT_FM_RX:
208 case INT_FM_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530209 case RT_PROXY_PORT_001_RX:
210 case RT_PROXY_PORT_001_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700211 {
212 ret = 0;
213 break;
214 }
215
216 default:
217 ret = -EINVAL;
218 }
219
220 return ret;
221}
222
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530223int afe_convert_virtual_to_portid(u16 port_id)
224{
225 int ret;
226
227 /* if port_id is virtual, convert to physical..
228 * if port_id is already physical, return physical
229 */
230 if (afe_validate_port(port_id) < 0) {
231 if (port_id == RT_PROXY_DAI_001_RX ||
232 port_id == RT_PROXY_DAI_001_TX ||
233 port_id == RT_PROXY_DAI_002_RX ||
234 port_id == RT_PROXY_DAI_002_TX)
235 ret = VIRTUAL_ID_TO_PORTID(port_id);
236 else
237 ret = -EINVAL;
238 } else
239 ret = port_id;
240
241 return ret;
242}
243
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700244int afe_get_port_index(u16 port_id)
245{
246 switch (port_id) {
247 case PRIMARY_I2S_RX: return IDX_PRIMARY_I2S_RX;
248 case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
249 case PCM_RX: return IDX_PCM_RX;
250 case PCM_TX: return IDX_PCM_TX;
251 case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
252 case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
253 case MI2S_RX: return IDX_MI2S_RX;
254 case MI2S_TX: return IDX_MI2S_TX;
255 case HDMI_RX: return IDX_HDMI_RX;
256 case RSVD_2: return IDX_RSVD_2;
257 case RSVD_3: return IDX_RSVD_3;
258 case DIGI_MIC_TX: return IDX_DIGI_MIC_TX;
259 case VOICE_RECORD_RX: return IDX_VOICE_RECORD_RX;
260 case VOICE_RECORD_TX: return IDX_VOICE_RECORD_TX;
261 case VOICE_PLAYBACK_TX: return IDX_VOICE_PLAYBACK_TX;
262 case SLIMBUS_0_RX: return IDX_SLIMBUS_0_RX;
263 case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
Neema Shetty3c9d2862012-03-11 01:25:32 -0800264 case SLIMBUS_1_RX: return IDX_SLIMBUS_1_RX;
265 case SLIMBUS_1_TX: return IDX_SLIMBUS_1_TX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700266 case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
267 case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
268 case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
269 case INT_FM_RX: return IDX_INT_FM_RX;
270 case INT_FM_TX: return IDX_INT_FM_TX;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530271 case RT_PROXY_PORT_001_RX: return IDX_RT_PROXY_PORT_001_RX;
272 case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700273
274 default: return -EINVAL;
275 }
276}
277
278int afe_sizeof_cfg_cmd(u16 port_id)
279{
280 int ret_size;
281 switch (port_id) {
282 case PRIMARY_I2S_RX:
283 case PRIMARY_I2S_TX:
284 case SECONDARY_I2S_RX:
285 case SECONDARY_I2S_TX:
286 case MI2S_RX:
287 case MI2S_TX:
288 ret_size = SIZEOF_CFG_CMD(afe_port_mi2s_cfg);
289 break;
290 case HDMI_RX:
Kiran Kandi5e809b02012-01-31 00:24:33 -0800291 ret_size = SIZEOF_CFG_CMD(afe_port_hdmi_multi_ch_cfg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700292 break;
293 case SLIMBUS_0_RX:
294 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800295 case SLIMBUS_1_RX:
296 case SLIMBUS_1_TX:
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800297 ret_size = SIZEOF_CFG_CMD(afe_port_slimbus_sch_cfg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700298 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530299 case RT_PROXY_PORT_001_RX:
300 case RT_PROXY_PORT_001_TX:
301 ret_size = SIZEOF_CFG_CMD(afe_port_rtproxy_cfg);
302 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700303 case PCM_RX:
304 case PCM_TX:
305 default:
306 ret_size = SIZEOF_CFG_CMD(afe_port_pcm_cfg);
307 break;
308 }
309 return ret_size;
310}
311
Jay Wang6a305432011-08-05 16:01:54 -0700312int afe_q6_interface_prepare(void)
313{
314 int ret = 0;
315
316 pr_debug("%s:", __func__);
317
318 if (this_afe.apr == NULL) {
319 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
320 0xFFFFFFFF, &this_afe);
321 pr_debug("%s: Register AFE\n", __func__);
322 if (this_afe.apr == NULL) {
323 pr_err("%s: Unable to register AFE\n", __func__);
324 ret = -ENODEV;
325 }
326 }
327 return ret;
328}
329
Ben Rombergerb7603232011-11-23 17:16:27 -0800330static void afe_send_cal_block(int32_t path, u16 port_id)
331{
332 int result = 0;
333 struct acdb_cal_block cal_block;
334 struct afe_port_cmd_set_param_no_payload afe_cal;
335 pr_debug("%s: path %d\n", __func__, path);
336
337 get_afe_cal(path, &cal_block);
338 if (cal_block.cal_size <= 0) {
339 pr_debug("%s: No AFE cal to send!\n", __func__);
340 goto done;
341 }
342
Ben Romberger9e792562012-02-24 12:29:01 -0800343 if ((afe_cal_addr[path].cal_paddr != cal_block.cal_paddr) ||
344 (cal_block.cal_size > afe_cal_addr[path].cal_size)) {
345 if (afe_cal_addr[path].cal_paddr != 0)
346 afe_cmd_memory_unmap_nowait(
347 afe_cal_addr[path].cal_paddr);
348
Ben Rombergerb7603232011-11-23 17:16:27 -0800349 afe_cmd_memory_map_nowait(cal_block.cal_paddr,
350 cal_block.cal_size);
Ben Romberger9e792562012-02-24 12:29:01 -0800351 afe_cal_addr[path].cal_paddr = cal_block.cal_paddr;
352 afe_cal_addr[path].cal_size = cal_block.cal_size;
Ben Rombergerb7603232011-11-23 17:16:27 -0800353 }
354
355 afe_cal.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
356 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
357 afe_cal.hdr.pkt_size = sizeof(afe_cal);
358 afe_cal.hdr.src_port = 0;
359 afe_cal.hdr.dest_port = 0;
360 afe_cal.hdr.token = 0;
361 afe_cal.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
362 afe_cal.port_id = port_id;
363 afe_cal.payload_size = cal_block.cal_size;
364 afe_cal.payload_address = cal_block.cal_paddr;
365
366 pr_debug("%s: AFE cal sent for device port = %d, path = %d, "
367 "cal size = %d, cal addr = 0x%x\n", __func__,
368 port_id, path, cal_block.cal_size, cal_block.cal_paddr);
369
370 result = apr_send_pkt(this_afe.apr, (uint32_t *) &afe_cal);
371 if (result < 0) {
372 pr_err("%s: AFE cal for port %d failed\n",
373 __func__, port_id);
374 }
375
376 pr_debug("%s: AFE cal sent for path %d device!\n", __func__, path);
377done:
378 return;
379}
380
381void afe_send_cal(u16 port_id)
382{
383 pr_debug("%s\n", __func__);
384
385 if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX)
386 afe_send_cal_block(TX_CAL, port_id);
387 else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX)
388 afe_send_cal_block(RX_CAL, port_id);
389}
390
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700391int afe_port_start_nowait(u16 port_id, union afe_port_config *afe_config,
392 u32 rate) /* This function is no blocking */
393{
394 struct afe_port_start_command start;
395 struct afe_audioif_config_command config;
396 int ret;
397
398 if (!afe_config) {
399 pr_err("%s: Error, no configuration data\n", __func__);
400 ret = -EINVAL;
401 return ret;
402 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -0800403 pr_debug("%s: %d %d\n", __func__, port_id, rate);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700404
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530405 if ((port_id == RT_PROXY_DAI_001_RX) ||
406 (port_id == RT_PROXY_DAI_002_TX))
407 return -EINVAL;
408 if ((port_id == RT_PROXY_DAI_002_RX) ||
409 (port_id == RT_PROXY_DAI_001_TX))
410 port_id = VIRTUAL_ID_TO_PORTID(port_id);
411
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700412 if (this_afe.apr == NULL) {
Jay Wang6a305432011-08-05 16:01:54 -0700413 pr_err("%s: AFE APR is not registered\n", __func__);
414 ret = -ENODEV;
415 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700416 }
Kiran Kandi5e809b02012-01-31 00:24:33 -0800417
418 if (port_id == HDMI_RX) {
419 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700420 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
Kiran Kandi5e809b02012-01-31 00:24:33 -0800421 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
422 config.hdr.src_port = 0;
423 config.hdr.dest_port = 0;
424 config.hdr.token = 0;
425 config.hdr.opcode = AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG;
426 } else {
427
428 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
429 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
430 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
431 config.hdr.src_port = 0;
432 config.hdr.dest_port = 0;
433 config.hdr.token = 0;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800434 switch (port_id) {
435 case SLIMBUS_0_RX:
436 case SLIMBUS_0_TX:
437 case SLIMBUS_1_RX:
438 case SLIMBUS_1_TX:
439 case SLIMBUS_2_RX:
440 case SLIMBUS_2_TX:
441 case SLIMBUS_3_RX:
442 case SLIMBUS_3_TX:
443 case SLIMBUS_4_RX:
444 case SLIMBUS_4_TX:
445 config.hdr.opcode = AFE_PORT_AUDIO_SLIM_SCH_CONFIG;
446 break;
447 default:
448 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
449 break;
450 }
Kiran Kandi5e809b02012-01-31 00:24:33 -0800451 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700452
453 if (afe_validate_port(port_id) < 0) {
454
455 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
456 port_id);
457 ret = -EINVAL;
458 goto fail_cmd;
459 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700460 config.port_id = port_id;
461 config.port = *afe_config;
462
463 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
464 if (ret < 0) {
465 pr_err("%s: AFE enable for port %d failed\n", __func__,
466 port_id);
467 ret = -EINVAL;
468 goto fail_cmd;
469 }
Ben Rombergerb7603232011-11-23 17:16:27 -0800470
471 /* send AFE cal */
472 afe_send_cal(port_id);
473
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700474 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
475 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
476 start.hdr.pkt_size = sizeof(start);
477 start.hdr.src_port = 0;
478 start.hdr.dest_port = 0;
479 start.hdr.token = 0;
480 start.hdr.opcode = AFE_PORT_CMD_START;
481 start.port_id = port_id;
482 start.gain = 0x2000;
483 start.sample_rate = rate;
484
485 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
486
487 if (IS_ERR_VALUE(ret)) {
488 pr_err("%s: AFE enable for port %d failed\n", __func__,
489 port_id);
490 ret = -EINVAL;
491 goto fail_cmd;
492 }
493
494 if (this_afe.task != current)
495 this_afe.task = current;
496
497 pr_debug("task_name = %s pid = %d\n",
498 this_afe.task->comm, this_afe.task->pid);
499 return 0;
500
501fail_cmd:
502 return ret;
503}
504
505int afe_open(u16 port_id, union afe_port_config *afe_config, int rate)
506{
507 struct afe_port_start_command start;
508 struct afe_audioif_config_command config;
509 int ret = 0;
510
511 if (!afe_config) {
512 pr_err("%s: Error, no configuration data\n", __func__);
513 ret = -EINVAL;
514 return ret;
515 }
516
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800517 pr_debug("%s: %d %d\n", __func__, port_id, rate);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700518
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530519 if ((port_id == RT_PROXY_DAI_001_RX) ||
520 (port_id == RT_PROXY_DAI_002_TX))
521 return -EINVAL;
522 if ((port_id == RT_PROXY_DAI_002_RX) ||
523 (port_id == RT_PROXY_DAI_001_TX))
524 port_id = VIRTUAL_ID_TO_PORTID(port_id);
525
Jay Wang6a305432011-08-05 16:01:54 -0700526 ret = afe_q6_interface_prepare();
527 if (ret != 0)
528 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700529
530 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
531 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
532 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
533 config.hdr.src_port = 0;
534 config.hdr.dest_port = 0;
535 config.hdr.token = 0;
536 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
537
538 if (afe_validate_port(port_id) < 0) {
539
540 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
541 port_id);
542 ret = -EINVAL;
543 goto fail_cmd;
544 }
545
546 config.port_id = port_id;
547 config.port = *afe_config;
548
549 atomic_set(&this_afe.state, 1);
550 atomic_set(&this_afe.status, 0);
551 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
552 if (ret < 0) {
553 pr_err("%s: AFE enable for port %d failed\n", __func__,
554 port_id);
555 ret = -EINVAL;
556 goto fail_cmd;
557 }
558
559 ret = wait_event_timeout(this_afe.wait,
560 (atomic_read(&this_afe.state) == 0),
561 msecs_to_jiffies(TIMEOUT_MS));
562 if (!ret) {
563 pr_err("%s: wait_event timeout\n", __func__);
564 ret = -EINVAL;
565 goto fail_cmd;
566 }
567 if (atomic_read(&this_afe.status) != 0) {
568 pr_err("%s: config cmd failed\n", __func__);
569 ret = -EINVAL;
570 goto fail_cmd;
571 }
572 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
573 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
574 start.hdr.pkt_size = sizeof(start);
575 start.hdr.src_port = 0;
576 start.hdr.dest_port = 0;
577 start.hdr.token = 0;
578 start.hdr.opcode = AFE_PORT_CMD_START;
579 start.port_id = port_id;
580 start.gain = 0x2000;
581 start.sample_rate = rate;
582
583 atomic_set(&this_afe.state, 1);
584 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
585 if (ret < 0) {
586 pr_err("%s: AFE enable for port %d failed\n", __func__,
587 port_id);
588 ret = -EINVAL;
589 goto fail_cmd;
590 }
591 ret = wait_event_timeout(this_afe.wait,
592 (atomic_read(&this_afe.state) == 0),
593 msecs_to_jiffies(TIMEOUT_MS));
594 if (!ret) {
595 pr_err("%s: wait_event timeout\n", __func__);
596 ret = -EINVAL;
597 goto fail_cmd;
598 }
599
600 if (this_afe.task != current)
601 this_afe.task = current;
602
603 pr_debug("task_name = %s pid = %d\n",
604 this_afe.task->comm, this_afe.task->pid);
605 return 0;
606fail_cmd:
607 return ret;
608}
609
610int afe_loopback(u16 enable, u16 rx_port, u16 tx_port)
611{
612 struct afe_loopback_command lb_cmd;
613 int ret = 0;
Jay Wang6a305432011-08-05 16:01:54 -0700614
615 ret = afe_q6_interface_prepare();
616 if (ret != 0)
617 return ret;
618
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700619 lb_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
620 APR_HDR_LEN(20), APR_PKT_VER);
621 lb_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
622 sizeof(lb_cmd) - APR_HDR_SIZE);
623 lb_cmd.hdr.src_port = 0;
624 lb_cmd.hdr.dest_port = 0;
625 lb_cmd.hdr.token = 0;
626 lb_cmd.hdr.opcode = AFE_PORT_CMD_LOOPBACK;
627 lb_cmd.tx_port_id = tx_port;
628 lb_cmd.rx_port_id = rx_port;
629 lb_cmd.mode = 0xFFFF;
630 lb_cmd.enable = (enable ? 1 : 0);
631 atomic_set(&this_afe.state, 1);
632
633 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &lb_cmd);
634 if (ret < 0) {
635 pr_err("%s: AFE loopback failed\n", __func__);
636 ret = -EINVAL;
637 goto done;
638 }
639 ret = wait_event_timeout(this_afe.wait,
640 (atomic_read(&this_afe.state) == 0),
641 msecs_to_jiffies(TIMEOUT_MS));
642 if (!ret) {
643 pr_err("%s: wait_event timeout\n", __func__);
644 ret = -EINVAL;
645 }
646done:
647 return ret;
648}
649
650
651int afe_loopback_gain(u16 port_id, u16 volume)
652{
653 struct afe_port_cmd_set_param set_param;
654 int ret = 0;
655
656 if (this_afe.apr == NULL) {
Jayasena Sangaraboina82435032011-07-26 15:23:00 -0700657 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
658 0xFFFFFFFF, &this_afe);
659 pr_debug("%s: Register AFE\n", __func__);
660 if (this_afe.apr == NULL) {
661 pr_err("%s: Unable to register AFE\n", __func__);
662 ret = -ENODEV;
663 return ret;
664 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700665 }
666
667 if (afe_validate_port(port_id) < 0) {
668
669 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
670 port_id);
671 ret = -EINVAL;
672 goto fail_cmd;
673 }
674
675 /* RX ports numbers are even .TX ports numbers are odd. */
676 if (port_id % 2 == 0) {
677 pr_err("%s: Failed : afe loopback gain only for TX ports."
678 " port_id %d\n", __func__, port_id);
679 ret = -EINVAL;
680 goto fail_cmd;
681 }
682
683 pr_debug("%s: %d %hX\n", __func__, port_id, volume);
684
685 set_param.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
686 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
687 set_param.hdr.pkt_size = sizeof(set_param);
688 set_param.hdr.src_port = 0;
689 set_param.hdr.dest_port = 0;
690 set_param.hdr.token = 0;
691 set_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
692
693 set_param.port_id = port_id;
694 set_param.payload_size = sizeof(struct afe_param_payload);
695 set_param.payload_address = 0;
696
697 set_param.payload.module_id = AFE_MODULE_ID_PORT_INFO;
698 set_param.payload.param_id = AFE_PARAM_ID_LOOPBACK_GAIN;
699 set_param.payload.param_size = sizeof(struct afe_param_loopback_gain);
700 set_param.payload.reserved = 0;
701
702 set_param.payload.param.loopback_gain.gain = volume;
703 set_param.payload.param.loopback_gain.reserved = 0;
704
705 atomic_set(&this_afe.state, 1);
706 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_param);
707 if (ret < 0) {
708 pr_err("%s: AFE param set failed for port %d\n",
709 __func__, port_id);
710 ret = -EINVAL;
711 goto fail_cmd;
712 }
713
714 ret = wait_event_timeout(this_afe.wait,
715 (atomic_read(&this_afe.state) == 0),
716 msecs_to_jiffies(TIMEOUT_MS));
717 if (ret < 0) {
718 pr_err("%s: wait_event timeout\n", __func__);
719 ret = -EINVAL;
720 goto fail_cmd;
721 }
722 return 0;
723fail_cmd:
724 return ret;
725}
726
Laxminath Kasam885f5102011-07-14 10:20:21 +0530727int afe_apply_gain(u16 port_id, u16 gain)
728{
729 struct afe_port_gain_command set_gain;
730 int ret = 0;
731
732 if (this_afe.apr == NULL) {
733 pr_err("%s: AFE is not opened\n", __func__);
734 ret = -EPERM;
735 goto fail_cmd;
736 }
737
738 if (afe_validate_port(port_id) < 0) {
739 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
740 port_id);
741 ret = -EINVAL;
742 goto fail_cmd;
743 }
744
745 /* RX ports numbers are even .TX ports numbers are odd. */
746 if (port_id % 2 == 0) {
747 pr_err("%s: Failed : afe apply gain only for TX ports."
748 " port_id %d\n", __func__, port_id);
749 ret = -EINVAL;
750 goto fail_cmd;
751 }
752
753 pr_debug("%s: %d %hX\n", __func__, port_id, gain);
754
755 set_gain.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
756 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
757 set_gain.hdr.pkt_size = sizeof(set_gain);
758 set_gain.hdr.src_port = 0;
759 set_gain.hdr.dest_port = 0;
760 set_gain.hdr.token = 0;
761 set_gain.hdr.opcode = AFE_PORT_CMD_APPLY_GAIN;
762
763 set_gain.port_id = port_id;
764 set_gain.gain = gain;
765
766 atomic_set(&this_afe.state, 1);
767 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_gain);
768 if (ret < 0) {
769 pr_err("%s: AFE Gain set failed for port %d\n",
770 __func__, port_id);
771 ret = -EINVAL;
772 goto fail_cmd;
773 }
774
775 ret = wait_event_timeout(this_afe.wait,
776 (atomic_read(&this_afe.state) == 0),
777 msecs_to_jiffies(TIMEOUT_MS));
778 if (ret < 0) {
779 pr_err("%s: wait_event timeout\n", __func__);
780 ret = -EINVAL;
781 goto fail_cmd;
782 }
783 return 0;
784fail_cmd:
785 return ret;
786}
Helen Zeng0705a5f2011-10-14 15:29:52 -0700787
788int afe_pseudo_port_start_nowait(u16 port_id)
789{
790 int ret = 0;
791 struct afe_pseudoport_start_command start;
792
793 pr_debug("%s: port_id=%d\n", __func__, port_id);
794 if (this_afe.apr == NULL) {
795 pr_err("%s: AFE APR is not registered\n", __func__);
796 return -ENODEV;
797 }
798
799
800 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
801 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
802 start.hdr.pkt_size = sizeof(start);
803 start.hdr.src_port = 0;
804 start.hdr.dest_port = 0;
805 start.hdr.token = 0;
806 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
807 start.port_id = port_id;
808 start.timing = 1;
809
810 atomic_set(&this_afe.state, 1);
811 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
812 if (ret < 0) {
813 pr_err("%s: AFE enable for port %d failed %d\n",
814 __func__, port_id, ret);
815 return -EINVAL;
816 }
817 return 0;
818}
819
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700820int afe_start_pseudo_port(u16 port_id)
821{
822 int ret = 0;
823 struct afe_pseudoport_start_command start;
824
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800825 pr_debug("%s: port_id=%d\n", __func__, port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700826
Jay Wang6a305432011-08-05 16:01:54 -0700827 ret = afe_q6_interface_prepare();
828 if (ret != 0)
829 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700830
831 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
832 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
833 start.hdr.pkt_size = sizeof(start);
834 start.hdr.src_port = 0;
835 start.hdr.dest_port = 0;
836 start.hdr.token = 0;
837 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
838 start.port_id = port_id;
839 start.timing = 1;
840
841 atomic_set(&this_afe.state, 1);
842 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
843 if (ret < 0) {
844 pr_err("%s: AFE enable for port %d failed %d\n",
845 __func__, port_id, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700846 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700847 }
848
849 ret = wait_event_timeout(this_afe.wait,
850 (atomic_read(&this_afe.state) == 0),
851 msecs_to_jiffies(TIMEOUT_MS));
852 if (!ret) {
853 pr_err("%s: wait_event timeout\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700854 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700855 }
856
857 return 0;
858}
859
Helen Zeng0705a5f2011-10-14 15:29:52 -0700860int afe_pseudo_port_stop_nowait(u16 port_id)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700861{
862 int ret = 0;
863 struct afe_pseudoport_stop_command stop;
864
Helen Zeng0705a5f2011-10-14 15:29:52 -0700865 pr_debug("%s: port_id=%d\n", __func__, port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700866
867 if (this_afe.apr == NULL) {
868 pr_err("%s: AFE is already closed\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700869 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700870 }
871
872 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
873 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
874 stop.hdr.pkt_size = sizeof(stop);
875 stop.hdr.src_port = 0;
876 stop.hdr.dest_port = 0;
877 stop.hdr.token = 0;
878 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
879 stop.port_id = port_id;
880 stop.reserved = 0;
881
882 atomic_set(&this_afe.state, 1);
883 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
884 if (ret < 0) {
885 pr_err("%s: AFE close failed %d\n", __func__, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700886 return -EINVAL;
887 }
888
889 return 0;
890
891}
892
893int afe_stop_pseudo_port(u16 port_id)
894{
895 int ret = 0;
896 struct afe_pseudoport_stop_command stop;
897
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800898 pr_debug("%s: port_id=%d\n", __func__, port_id);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700899
900 if (this_afe.apr == NULL) {
901 pr_err("%s: AFE is already closed\n", __func__);
902 return -EINVAL;
903 }
904
905 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
906 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
907 stop.hdr.pkt_size = sizeof(stop);
908 stop.hdr.src_port = 0;
909 stop.hdr.dest_port = 0;
910 stop.hdr.token = 0;
911 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
912 stop.port_id = port_id;
913 stop.reserved = 0;
914
915 atomic_set(&this_afe.state, 1);
916 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
917 if (ret < 0) {
918 pr_err("%s: AFE close failed %d\n", __func__, ret);
919 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700920 }
921
922 ret = wait_event_timeout(this_afe.wait,
923 (atomic_read(&this_afe.state) == 0),
924 msecs_to_jiffies(TIMEOUT_MS));
925 if (!ret) {
926 pr_err("%s: wait_event timeout\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700927 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700928 }
929
930 return 0;
931}
932
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530933int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz)
934{
935 int ret = 0;
936 struct afe_cmd_memory_map mregion;
937
938 pr_debug("%s:\n", __func__);
939
940 if (this_afe.apr == NULL) {
941 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
942 0xFFFFFFFF, &this_afe);
943 pr_debug("%s: Register AFE\n", __func__);
944 if (this_afe.apr == NULL) {
945 pr_err("%s: Unable to register AFE\n", __func__);
946 ret = -ENODEV;
947 return ret;
948 }
949 }
950
951 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
952 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
953 mregion.hdr.pkt_size = sizeof(mregion);
954 mregion.hdr.src_port = 0;
955 mregion.hdr.dest_port = 0;
956 mregion.hdr.token = 0;
957 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
958 mregion.phy_addr = dma_addr_p;
959 mregion.mem_sz = dma_buf_sz;
960 mregion.mem_id = 0;
961 mregion.rsvd = 0;
962
963 atomic_set(&this_afe.state, 1);
964 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
965 if (ret < 0) {
966 pr_err("%s: AFE memory map cmd failed %d\n",
967 __func__, ret);
968 ret = -EINVAL;
969 return ret;
970 }
971
972 ret = wait_event_timeout(this_afe.wait,
973 (atomic_read(&this_afe.state) == 0),
974 msecs_to_jiffies(TIMEOUT_MS));
975 if (!ret) {
976 pr_err("%s: wait_event timeout\n", __func__);
977 ret = -EINVAL;
978 return ret;
979 }
980
981 return 0;
982}
983
Ben Rombergerb7603232011-11-23 17:16:27 -0800984int afe_cmd_memory_map_nowait(u32 dma_addr_p, u32 dma_buf_sz)
985{
986 int ret = 0;
987 struct afe_cmd_memory_map mregion;
988
989 pr_debug("%s:\n", __func__);
990
991 if (this_afe.apr == NULL) {
992 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
993 0xFFFFFFFF, &this_afe);
994 pr_debug("%s: Register AFE\n", __func__);
995 if (this_afe.apr == NULL) {
996 pr_err("%s: Unable to register AFE\n", __func__);
997 ret = -ENODEV;
998 return ret;
999 }
1000 }
1001
1002 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1003 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1004 mregion.hdr.pkt_size = sizeof(mregion);
1005 mregion.hdr.src_port = 0;
1006 mregion.hdr.dest_port = 0;
1007 mregion.hdr.token = 0;
1008 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
1009 mregion.phy_addr = dma_addr_p;
1010 mregion.mem_sz = dma_buf_sz;
1011 mregion.mem_id = 0;
1012 mregion.rsvd = 0;
1013
1014 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1015 if (ret < 0) {
1016 pr_err("%s: AFE memory map cmd failed %d\n",
1017 __func__, ret);
1018 ret = -EINVAL;
1019 }
1020 return 0;
1021}
1022
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301023int afe_cmd_memory_unmap(u32 dma_addr_p)
1024{
1025 int ret = 0;
1026 struct afe_cmd_memory_unmap mregion;
1027
1028 pr_debug("%s:\n", __func__);
1029
1030 if (this_afe.apr == NULL) {
1031 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1032 0xFFFFFFFF, &this_afe);
1033 pr_debug("%s: Register AFE\n", __func__);
1034 if (this_afe.apr == NULL) {
1035 pr_err("%s: Unable to register AFE\n", __func__);
1036 ret = -ENODEV;
1037 return ret;
1038 }
1039 }
1040
1041 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1042 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1043 mregion.hdr.pkt_size = sizeof(mregion);
1044 mregion.hdr.src_port = 0;
1045 mregion.hdr.dest_port = 0;
1046 mregion.hdr.token = 0;
1047 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
1048 mregion.phy_addr = dma_addr_p;
1049
1050 atomic_set(&this_afe.state, 1);
1051 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1052 if (ret < 0) {
Ben Rombergerb7603232011-11-23 17:16:27 -08001053 pr_err("%s: AFE memory unmap cmd failed %d\n",
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301054 __func__, ret);
1055 ret = -EINVAL;
1056 return ret;
1057 }
1058
1059 ret = wait_event_timeout(this_afe.wait,
1060 (atomic_read(&this_afe.state) == 0),
1061 msecs_to_jiffies(TIMEOUT_MS));
1062 if (!ret) {
1063 pr_err("%s: wait_event timeout\n", __func__);
1064 ret = -EINVAL;
1065 return ret;
1066 }
Ben Rombergerb7603232011-11-23 17:16:27 -08001067 return 0;
1068}
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301069
Ben Rombergerb7603232011-11-23 17:16:27 -08001070int afe_cmd_memory_unmap_nowait(u32 dma_addr_p)
1071{
1072 int ret = 0;
1073 struct afe_cmd_memory_unmap mregion;
1074
1075 pr_debug("%s:\n", __func__);
1076
1077 if (this_afe.apr == NULL) {
1078 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1079 0xFFFFFFFF, &this_afe);
1080 pr_debug("%s: Register AFE\n", __func__);
1081 if (this_afe.apr == NULL) {
1082 pr_err("%s: Unable to register AFE\n", __func__);
1083 ret = -ENODEV;
1084 return ret;
1085 }
1086 }
1087
1088 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1089 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1090 mregion.hdr.pkt_size = sizeof(mregion);
1091 mregion.hdr.src_port = 0;
1092 mregion.hdr.dest_port = 0;
1093 mregion.hdr.token = 0;
1094 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
1095 mregion.phy_addr = dma_addr_p;
1096
1097 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1098 if (ret < 0) {
1099 pr_err("%s: AFE memory unmap cmd failed %d\n",
1100 __func__, ret);
1101 ret = -EINVAL;
1102 }
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301103 return 0;
1104}
1105
1106int afe_register_get_events(u16 port_id,
1107 void (*cb) (uint32_t opcode,
1108 uint32_t token, uint32_t *payload, void *priv),
1109 void *private_data)
1110{
1111 int ret = 0;
1112 struct afe_cmd_reg_rtport rtproxy;
1113
1114 pr_debug("%s:\n", __func__);
1115
1116 if (this_afe.apr == NULL) {
1117 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1118 0xFFFFFFFF, &this_afe);
1119 pr_debug("%s: Register AFE\n", __func__);
1120 if (this_afe.apr == NULL) {
1121 pr_err("%s: Unable to register AFE\n", __func__);
1122 ret = -ENODEV;
1123 return ret;
1124 }
1125 }
1126 if ((port_id == RT_PROXY_DAI_002_RX) ||
1127 (port_id == RT_PROXY_DAI_001_TX))
1128 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1129 else
1130 return -EINVAL;
1131
1132 if (port_id == RT_PROXY_PORT_001_TX) {
1133 this_afe.tx_cb = cb;
1134 this_afe.tx_private_data = private_data;
1135 } else if (port_id == RT_PROXY_PORT_001_RX) {
1136 this_afe.rx_cb = cb;
1137 this_afe.rx_private_data = private_data;
1138 }
1139
1140 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1141 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1142 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1143 rtproxy.hdr.src_port = 1;
1144 rtproxy.hdr.dest_port = 1;
1145 rtproxy.hdr.token = 0;
1146 rtproxy.hdr.opcode = AFE_SERVICE_CMD_REG_RTPORT;
1147 rtproxy.port_id = port_id;
1148 rtproxy.rsvd = 0;
1149
1150 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1151 if (ret < 0) {
1152 pr_err("%s: AFE reg. rtproxy_event failed %d\n",
1153 __func__, ret);
1154 ret = -EINVAL;
1155 return ret;
1156 }
1157 return 0;
1158}
1159
1160int afe_unregister_get_events(u16 port_id)
1161{
1162 int ret = 0;
1163 struct afe_cmd_unreg_rtport rtproxy;
1164
1165 pr_debug("%s:\n", __func__);
1166
1167 if (this_afe.apr == NULL) {
1168 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1169 0xFFFFFFFF, &this_afe);
1170 pr_debug("%s: Register AFE\n", __func__);
1171 if (this_afe.apr == NULL) {
1172 pr_err("%s: Unable to register AFE\n", __func__);
1173 ret = -ENODEV;
1174 return ret;
1175 }
1176 }
1177 if ((port_id == RT_PROXY_DAI_002_RX) ||
1178 (port_id == RT_PROXY_DAI_001_TX))
1179 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1180 else
1181 return -EINVAL;
1182
1183 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1184 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1185 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1186 rtproxy.hdr.src_port = 0;
1187 rtproxy.hdr.dest_port = 0;
1188 rtproxy.hdr.token = 0;
1189 rtproxy.hdr.opcode = AFE_SERVICE_CMD_UNREG_RTPORT;
1190 rtproxy.port_id = port_id;
1191 rtproxy.rsvd = 0;
1192
1193 if (port_id == RT_PROXY_PORT_001_TX) {
1194 this_afe.tx_cb = NULL;
1195 this_afe.tx_private_data = NULL;
1196 } else if (port_id == RT_PROXY_PORT_001_RX) {
1197 this_afe.rx_cb = NULL;
1198 this_afe.rx_private_data = NULL;
1199 }
1200
1201 atomic_set(&this_afe.state, 1);
1202 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1203 if (ret < 0) {
1204 pr_err("%s: AFE enable Unreg. rtproxy_event failed %d\n",
1205 __func__, ret);
1206 ret = -EINVAL;
1207 return ret;
1208 }
1209
1210 ret = wait_event_timeout(this_afe.wait,
1211 (atomic_read(&this_afe.state) == 0),
1212 msecs_to_jiffies(TIMEOUT_MS));
1213 if (!ret) {
1214 pr_err("%s: wait_event timeout\n", __func__);
1215 ret = -EINVAL;
1216 return ret;
1217 }
1218 return 0;
1219}
1220
1221int afe_rt_proxy_port_write(u32 buf_addr_p, int bytes)
1222{
1223 int ret = 0;
1224 struct afe_cmd_rtport_wr afecmd_wr;
1225
1226 if (this_afe.apr == NULL) {
1227 pr_err("%s:register to AFE is not done\n", __func__);
1228 ret = -ENODEV;
1229 return ret;
1230 }
1231 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1232 buf_addr_p, bytes);
1233
1234 afecmd_wr.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1235 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1236 afecmd_wr.hdr.pkt_size = sizeof(afecmd_wr);
1237 afecmd_wr.hdr.src_port = 0;
1238 afecmd_wr.hdr.dest_port = 0;
1239 afecmd_wr.hdr.token = 0;
1240 afecmd_wr.hdr.opcode = AFE_SERVICE_CMD_RTPORT_WR;
1241 afecmd_wr.buf_addr = (uint32_t)buf_addr_p;
1242 afecmd_wr.port_id = RT_PROXY_PORT_001_TX;
1243 afecmd_wr.bytes_avail = bytes;
1244 afecmd_wr.rsvd = 0;
1245
1246 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_wr);
1247 if (ret < 0) {
1248 pr_err("%s: AFE rtproxy write to port 0x%x failed %d\n",
1249 __func__, afecmd_wr.port_id, ret);
1250 ret = -EINVAL;
1251 return ret;
1252 }
1253 return 0;
1254
1255}
1256
1257int afe_rt_proxy_port_read(u32 buf_addr_p, int bytes)
1258{
1259 int ret = 0;
1260 struct afe_cmd_rtport_rd afecmd_rd;
1261
1262 if (this_afe.apr == NULL) {
1263 pr_err("%s: register to AFE is not done\n", __func__);
1264 ret = -ENODEV;
1265 return ret;
1266 }
1267 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1268 buf_addr_p, bytes);
1269
1270 afecmd_rd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1271 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1272 afecmd_rd.hdr.pkt_size = sizeof(afecmd_rd);
1273 afecmd_rd.hdr.src_port = 0;
1274 afecmd_rd.hdr.dest_port = 0;
1275 afecmd_rd.hdr.token = 0;
1276 afecmd_rd.hdr.opcode = AFE_SERVICE_CMD_RTPORT_RD;
1277 afecmd_rd.buf_addr = (uint32_t)buf_addr_p;
1278 afecmd_rd.port_id = RT_PROXY_PORT_001_RX;
1279 afecmd_rd.bytes_avail = bytes;
1280 afecmd_rd.rsvd = 0;
1281
1282 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_rd);
1283 if (ret < 0) {
1284 pr_err("%s: AFE rtproxy read cmd to port 0x%x failed %d\n",
1285 __func__, afecmd_rd.port_id, ret);
1286 ret = -EINVAL;
1287 return ret;
1288 }
1289 return 0;
1290}
1291
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001292#ifdef CONFIG_DEBUG_FS
1293static struct dentry *debugfs_afelb;
1294static struct dentry *debugfs_afelb_gain;
1295
1296static int afe_debug_open(struct inode *inode, struct file *file)
1297{
1298 file->private_data = inode->i_private;
1299 pr_info("debug intf %s\n", (char *) file->private_data);
1300 return 0;
1301}
1302
1303static int afe_get_parameters(char *buf, long int *param1, int num_of_par)
1304{
1305 char *token;
1306 int base, cnt;
1307
1308 token = strsep(&buf, " ");
1309
1310 for (cnt = 0; cnt < num_of_par; cnt++) {
1311 if (token != NULL) {
1312 if ((token[1] == 'x') || (token[1] == 'X'))
1313 base = 16;
1314 else
1315 base = 10;
1316
1317 if (strict_strtoul(token, base, &param1[cnt]) != 0)
1318 return -EINVAL;
1319
1320 token = strsep(&buf, " ");
1321 } else
1322 return -EINVAL;
1323 }
1324 return 0;
1325}
1326#define AFE_LOOPBACK_ON (1)
1327#define AFE_LOOPBACK_OFF (0)
1328static ssize_t afe_debug_write(struct file *filp,
1329 const char __user *ubuf, size_t cnt, loff_t *ppos)
1330{
1331 char *lb_str = filp->private_data;
1332 char lbuf[32];
1333 int rc;
1334 unsigned long param[5];
1335
1336 if (cnt > sizeof(lbuf) - 1)
1337 return -EINVAL;
1338
1339 rc = copy_from_user(lbuf, ubuf, cnt);
1340 if (rc)
1341 return -EFAULT;
1342
1343 lbuf[cnt] = '\0';
1344
1345 if (!strcmp(lb_str, "afe_loopback")) {
1346 rc = afe_get_parameters(lbuf, param, 3);
1347 if (!rc) {
1348 pr_info("%s %lu %lu %lu\n", lb_str, param[0], param[1],
1349 param[2]);
1350
1351 if ((param[0] != AFE_LOOPBACK_ON) && (param[0] !=
1352 AFE_LOOPBACK_OFF)) {
1353 pr_err("%s: Error, parameter 0 incorrect\n",
1354 __func__);
1355 rc = -EINVAL;
1356 goto afe_error;
1357 }
1358 if ((afe_validate_port(param[1]) < 0) ||
1359 (afe_validate_port(param[2])) < 0) {
1360 pr_err("%s: Error, invalid afe port\n",
1361 __func__);
1362 }
1363 if (this_afe.apr == NULL) {
1364 pr_err("%s: Error, AFE not opened\n", __func__);
1365 rc = -EINVAL;
1366 } else {
1367 rc = afe_loopback(param[0], param[1], param[2]);
1368 }
1369 } else {
1370 pr_err("%s: Error, invalid parameters\n", __func__);
1371 rc = -EINVAL;
1372 }
1373
1374 } else if (!strcmp(lb_str, "afe_loopback_gain")) {
1375 rc = afe_get_parameters(lbuf, param, 2);
1376 if (!rc) {
1377 pr_info("%s %lu %lu\n", lb_str, param[0], param[1]);
1378
1379 if (afe_validate_port(param[0]) < 0) {
1380 pr_err("%s: Error, invalid afe port\n",
1381 __func__);
1382 rc = -EINVAL;
1383 goto afe_error;
1384 }
1385
1386 if (param[1] < 0 || param[1] > 100) {
1387 pr_err("%s: Error, volume shoud be 0 to 100"
1388 " percentage param = %lu\n",
1389 __func__, param[1]);
1390 rc = -EINVAL;
1391 goto afe_error;
1392 }
1393
1394 param[1] = (Q6AFE_MAX_VOLUME * param[1]) / 100;
1395
1396 if (this_afe.apr == NULL) {
1397 pr_err("%s: Error, AFE not opened\n", __func__);
1398 rc = -EINVAL;
1399 } else {
1400 rc = afe_loopback_gain(param[0], param[1]);
1401 }
1402 } else {
1403 pr_err("%s: Error, invalid parameters\n", __func__);
1404 rc = -EINVAL;
1405 }
1406 }
1407
1408afe_error:
1409 if (rc == 0)
1410 rc = cnt;
1411 else
1412 pr_err("%s: rc = %d\n", __func__, rc);
1413
1414 return rc;
1415}
1416
1417static const struct file_operations afe_debug_fops = {
1418 .open = afe_debug_open,
1419 .write = afe_debug_write
1420};
1421#endif
1422int afe_sidetone(u16 tx_port_id, u16 rx_port_id, u16 enable, uint16_t gain)
1423{
1424 struct afe_port_sidetone_command cmd_sidetone;
1425 int ret = 0;
1426
1427 pr_info("%s: tx_port_id:%d rx_port_id:%d enable:%d gain:%d\n", __func__,
1428 tx_port_id, rx_port_id, enable, gain);
1429 cmd_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1430 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1431 cmd_sidetone.hdr.pkt_size = sizeof(cmd_sidetone);
1432 cmd_sidetone.hdr.src_port = 0;
1433 cmd_sidetone.hdr.dest_port = 0;
1434 cmd_sidetone.hdr.token = 0;
1435 cmd_sidetone.hdr.opcode = AFE_PORT_CMD_SIDETONE_CTL;
1436 cmd_sidetone.tx_port_id = tx_port_id;
1437 cmd_sidetone.rx_port_id = rx_port_id;
1438 cmd_sidetone.gain = gain;
1439 cmd_sidetone.enable = enable;
1440
1441 atomic_set(&this_afe.state, 1);
1442 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_sidetone);
1443 if (ret < 0) {
1444 pr_err("%s: AFE sidetone failed for tx_port:%d rx_port:%d\n",
1445 __func__, tx_port_id, rx_port_id);
1446 ret = -EINVAL;
1447 goto fail_cmd;
1448 }
1449
1450 ret = wait_event_timeout(this_afe.wait,
1451 (atomic_read(&this_afe.state) == 0),
1452 msecs_to_jiffies(TIMEOUT_MS));
1453 if (ret < 0) {
1454 pr_err("%s: wait_event timeout\n", __func__);
1455 ret = -EINVAL;
1456 goto fail_cmd;
1457 }
1458 return 0;
1459fail_cmd:
1460 return ret;
1461}
1462
1463int afe_port_stop_nowait(int port_id)
1464{
1465 struct afe_port_stop_command stop;
1466 int ret = 0;
1467
1468 if (this_afe.apr == NULL) {
1469 pr_err("AFE is already closed\n");
1470 ret = -EINVAL;
1471 goto fail_cmd;
1472 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001473 pr_debug("%s: port_id=%d\n", __func__, port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301474 port_id = afe_convert_virtual_to_portid(port_id);
1475
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001476 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1477 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1478 stop.hdr.pkt_size = sizeof(stop);
1479 stop.hdr.src_port = 0;
1480 stop.hdr.dest_port = 0;
1481 stop.hdr.token = 0;
1482 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1483 stop.port_id = port_id;
1484 stop.reserved = 0;
1485
1486 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1487
1488 if (ret == -ENETRESET) {
1489 pr_info("%s: Need to reset, calling APR deregister", __func__);
1490 return apr_deregister(this_afe.apr);
1491 } else if (IS_ERR_VALUE(ret)) {
1492 pr_err("%s: AFE close failed\n", __func__);
1493 ret = -EINVAL;
1494 }
1495
1496fail_cmd:
1497 return ret;
1498
1499}
1500
1501int afe_close(int port_id)
1502{
1503 struct afe_port_stop_command stop;
1504 int ret = 0;
1505
1506 if (this_afe.apr == NULL) {
1507 pr_err("AFE is already closed\n");
1508 ret = -EINVAL;
1509 goto fail_cmd;
1510 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001511 pr_debug("%s: port_id=%d\n", __func__, port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301512 port_id = afe_convert_virtual_to_portid(port_id);
1513
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001514 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1515 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1516 stop.hdr.pkt_size = sizeof(stop);
1517 stop.hdr.src_port = 0;
1518 stop.hdr.dest_port = 0;
1519 stop.hdr.token = 0;
1520 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1521 stop.port_id = port_id;
1522 stop.reserved = 0;
1523
1524 atomic_set(&this_afe.state, 1);
1525 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1526
1527 if (ret == -ENETRESET) {
1528 pr_info("%s: Need to reset, calling APR deregister", __func__);
1529 return apr_deregister(this_afe.apr);
1530 }
1531
1532 if (ret < 0) {
1533 pr_err("%s: AFE close failed\n", __func__);
1534 ret = -EINVAL;
1535 goto fail_cmd;
1536 }
1537
1538 ret = wait_event_timeout(this_afe.wait,
1539 (atomic_read(&this_afe.state) == 0),
1540 msecs_to_jiffies(TIMEOUT_MS));
1541 if (!ret) {
1542 pr_err("%s: wait_event timeout\n", __func__);
1543 ret = -EINVAL;
1544 goto fail_cmd;
1545 }
1546fail_cmd:
1547 return ret;
1548}
1549
1550static int __init afe_init(void)
1551{
1552 init_waitqueue_head(&this_afe.wait);
1553 atomic_set(&this_afe.state, 0);
1554 atomic_set(&this_afe.status, 0);
1555 this_afe.apr = NULL;
1556#ifdef CONFIG_DEBUG_FS
1557 debugfs_afelb = debugfs_create_file("afe_loopback",
1558 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback",
1559 &afe_debug_fops);
1560
1561 debugfs_afelb_gain = debugfs_create_file("afe_loopback_gain",
1562 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback_gain",
1563 &afe_debug_fops);
1564
1565
1566#endif
1567 return 0;
1568}
1569
1570static void __exit afe_exit(void)
1571{
Ben Rombergerb7603232011-11-23 17:16:27 -08001572 int i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001573#ifdef CONFIG_DEBUG_FS
1574 if (debugfs_afelb)
1575 debugfs_remove(debugfs_afelb);
1576 if (debugfs_afelb_gain)
1577 debugfs_remove(debugfs_afelb_gain);
1578#endif
Ben Rombergerb7603232011-11-23 17:16:27 -08001579 for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
Ben Romberger9e792562012-02-24 12:29:01 -08001580 if (afe_cal_addr[i].cal_paddr != 0)
1581 afe_cmd_memory_unmap_nowait(
1582 afe_cal_addr[i].cal_paddr);
Ben Rombergerb7603232011-11-23 17:16:27 -08001583 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001584}
1585
1586device_initcall(afe_init);
1587__exitcall(afe_exit);