blob: 74a669454099ebc8b76d707ae47dd6fd1298d130 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
2 *
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>
20#include <sound/apr_audio.h>
21#include <sound/q6afe.h>
22
23struct afe_ctl {
24 void *apr;
25 atomic_t state;
26 atomic_t status;
27 wait_queue_head_t wait;
28 struct task_struct *task;
Laxminath Kasam32657ec2011-08-01 19:26:57 +053029 void (*tx_cb) (uint32_t opcode,
30 uint32_t token, uint32_t *payload, void *priv);
31 void (*rx_cb) (uint32_t opcode,
32 uint32_t token, uint32_t *payload, void *priv);
33 void *tx_private_data;
34 void *rx_private_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070035};
36
37static struct afe_ctl this_afe;
38
39#define TIMEOUT_MS 1000
40#define Q6AFE_MAX_VOLUME 0x3FFF
41
42#define SIZEOF_CFG_CMD(y) \
43 (sizeof(struct apr_hdr) + sizeof(u16) + (sizeof(struct y)))
44
45static int32_t afe_callback(struct apr_client_data *data, void *priv)
46{
47 if (data->opcode == RESET_EVENTS) {
48 pr_debug("q6afe: reset event = %d %d apr[%p]\n",
49 data->reset_event, data->reset_proc, this_afe.apr);
50 if (this_afe.apr) {
51 apr_reset(this_afe.apr);
52 atomic_set(&this_afe.state, 0);
53 this_afe.apr = NULL;
54 }
55 /* send info to user */
56 pr_debug("task_name = %s pid = %d\n",
57 this_afe.task->comm, this_afe.task->pid);
58 send_sig(SIGUSR1, this_afe.task, 0);
Laxminath Kasam9bb28c62012-01-18 21:55:37 +053059 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070060 }
61 if (data->payload_size) {
62 uint32_t *payload;
Laxminath Kasam32657ec2011-08-01 19:26:57 +053063 uint16_t port_id = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070064 payload = data->payload;
Laxminath Kasam32657ec2011-08-01 19:26:57 +053065 pr_debug("%s:opcode = 0x%x cmd = 0x%x status = 0x%x\n",
66 __func__, data->opcode,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070067 payload[0], payload[1]);
68 /* payload[1] contains the error status for response */
69 if (payload[1] != 0) {
70 atomic_set(&this_afe.status, -1);
71 pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
72 __func__, payload[0], payload[1]);
73 }
74 if (data->opcode == APR_BASIC_RSP_RESULT) {
75 switch (payload[0]) {
76 case AFE_PORT_AUDIO_IF_CONFIG:
77 case AFE_PORT_CMD_STOP:
78 case AFE_PORT_CMD_START:
79 case AFE_PORT_CMD_LOOPBACK:
80 case AFE_PORT_CMD_SIDETONE_CTL:
81 case AFE_PORT_CMD_SET_PARAM:
82 case AFE_PSEUDOPORT_CMD_START:
83 case AFE_PSEUDOPORT_CMD_STOP:
Laxminath Kasam885f5102011-07-14 10:20:21 +053084 case AFE_PORT_CMD_APPLY_GAIN:
Laxminath Kasam32657ec2011-08-01 19:26:57 +053085 case AFE_SERVICE_CMD_MEMORY_MAP:
86 case AFE_SERVICE_CMD_MEMORY_UNMAP:
87 case AFE_SERVICE_CMD_UNREG_RTPORT:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070088 atomic_set(&this_afe.state, 0);
89 wake_up(&this_afe.wait);
90 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +053091 case AFE_SERVICE_CMD_REG_RTPORT:
92 break;
93 case AFE_SERVICE_CMD_RTPORT_WR:
94 port_id = RT_PROXY_PORT_001_TX;
95 break;
96 case AFE_SERVICE_CMD_RTPORT_RD:
97 port_id = RT_PROXY_PORT_001_RX;
98 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070099 default:
100 pr_err("Unknown cmd 0x%x\n",
101 payload[0]);
102 break;
103 }
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530104 } else if (data->opcode == AFE_EVENT_RT_PROXY_PORT_STATUS) {
105 port_id = (uint16_t)(0x0000FFFF & payload[0]);
106 }
107 pr_debug("%s:port_id = %x\n", __func__, port_id);
108 switch (port_id) {
109 case RT_PROXY_PORT_001_TX: {
110 if (this_afe.tx_cb) {
111 this_afe.tx_cb(data->opcode, data->token,
112 data->payload,
113 this_afe.tx_private_data);
114 }
115 break;
116 }
117 case RT_PROXY_PORT_001_RX: {
118 if (this_afe.rx_cb) {
119 this_afe.rx_cb(data->opcode, data->token,
120 data->payload,
121 this_afe.rx_private_data);
122 }
123 break;
124 }
125 default:
126 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700127 }
128 }
129 return 0;
130}
131
Neema Shettyfeea7742011-09-11 12:30:36 -0700132int afe_get_port_type(u16 port_id)
133{
134 int ret;
135
136 switch (port_id) {
137 case PRIMARY_I2S_RX:
138 case PCM_RX:
139 case SECONDARY_I2S_RX:
140 case MI2S_RX:
141 case HDMI_RX:
142 case SLIMBUS_0_RX:
143 case INT_BT_SCO_RX:
144 case INT_BT_A2DP_RX:
145 case INT_FM_RX:
146 case VOICE_PLAYBACK_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530147 case RT_PROXY_PORT_001_RX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700148 ret = MSM_AFE_PORT_TYPE_RX;
149 break;
150
151 case PRIMARY_I2S_TX:
152 case PCM_TX:
153 case SECONDARY_I2S_TX:
154 case MI2S_TX:
155 case DIGI_MIC_TX:
156 case VOICE_RECORD_TX:
157 case SLIMBUS_0_TX:
158 case INT_FM_TX:
159 case VOICE_RECORD_RX:
160 case INT_BT_SCO_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530161 case RT_PROXY_PORT_001_TX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700162 ret = MSM_AFE_PORT_TYPE_TX;
163 break;
164
165 default:
166 pr_err("%s: invalid port id\n", __func__);
167 ret = -EINVAL;
168 }
169
170 return ret;
171}
172
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700173int afe_validate_port(u16 port_id)
174{
175 int ret;
176
177 switch (port_id) {
178 case PRIMARY_I2S_RX:
179 case PRIMARY_I2S_TX:
180 case PCM_RX:
181 case PCM_TX:
182 case SECONDARY_I2S_RX:
183 case SECONDARY_I2S_TX:
184 case MI2S_RX:
185 case MI2S_TX:
186 case HDMI_RX:
187 case RSVD_2:
188 case RSVD_3:
189 case DIGI_MIC_TX:
190 case VOICE_RECORD_RX:
191 case VOICE_RECORD_TX:
192 case VOICE_PLAYBACK_TX:
193 case SLIMBUS_0_RX:
194 case SLIMBUS_0_TX:
195 case INT_BT_SCO_RX:
196 case INT_BT_SCO_TX:
197 case INT_BT_A2DP_RX:
198 case INT_FM_RX:
199 case INT_FM_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530200 case RT_PROXY_PORT_001_RX:
201 case RT_PROXY_PORT_001_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700202 {
203 ret = 0;
204 break;
205 }
206
207 default:
208 ret = -EINVAL;
209 }
210
211 return ret;
212}
213
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530214int afe_convert_virtual_to_portid(u16 port_id)
215{
216 int ret;
217
218 /* if port_id is virtual, convert to physical..
219 * if port_id is already physical, return physical
220 */
221 if (afe_validate_port(port_id) < 0) {
222 if (port_id == RT_PROXY_DAI_001_RX ||
223 port_id == RT_PROXY_DAI_001_TX ||
224 port_id == RT_PROXY_DAI_002_RX ||
225 port_id == RT_PROXY_DAI_002_TX)
226 ret = VIRTUAL_ID_TO_PORTID(port_id);
227 else
228 ret = -EINVAL;
229 } else
230 ret = port_id;
231
232 return ret;
233}
234
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700235int afe_get_port_index(u16 port_id)
236{
237 switch (port_id) {
238 case PRIMARY_I2S_RX: return IDX_PRIMARY_I2S_RX;
239 case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
240 case PCM_RX: return IDX_PCM_RX;
241 case PCM_TX: return IDX_PCM_TX;
242 case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
243 case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
244 case MI2S_RX: return IDX_MI2S_RX;
245 case MI2S_TX: return IDX_MI2S_TX;
246 case HDMI_RX: return IDX_HDMI_RX;
247 case RSVD_2: return IDX_RSVD_2;
248 case RSVD_3: return IDX_RSVD_3;
249 case DIGI_MIC_TX: return IDX_DIGI_MIC_TX;
250 case VOICE_RECORD_RX: return IDX_VOICE_RECORD_RX;
251 case VOICE_RECORD_TX: return IDX_VOICE_RECORD_TX;
252 case VOICE_PLAYBACK_TX: return IDX_VOICE_PLAYBACK_TX;
253 case SLIMBUS_0_RX: return IDX_SLIMBUS_0_RX;
254 case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
255 case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
256 case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
257 case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
258 case INT_FM_RX: return IDX_INT_FM_RX;
259 case INT_FM_TX: return IDX_INT_FM_TX;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530260 case RT_PROXY_PORT_001_RX: return IDX_RT_PROXY_PORT_001_RX;
261 case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700262
263 default: return -EINVAL;
264 }
265}
266
267int afe_sizeof_cfg_cmd(u16 port_id)
268{
269 int ret_size;
270 switch (port_id) {
271 case PRIMARY_I2S_RX:
272 case PRIMARY_I2S_TX:
273 case SECONDARY_I2S_RX:
274 case SECONDARY_I2S_TX:
275 case MI2S_RX:
276 case MI2S_TX:
277 ret_size = SIZEOF_CFG_CMD(afe_port_mi2s_cfg);
278 break;
279 case HDMI_RX:
280 ret_size = SIZEOF_CFG_CMD(afe_port_hdmi_cfg);
281 break;
282 case SLIMBUS_0_RX:
283 case SLIMBUS_0_TX:
284 ret_size = SIZEOF_CFG_CMD(afe_port_slimbus_cfg);
285 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530286 case RT_PROXY_PORT_001_RX:
287 case RT_PROXY_PORT_001_TX:
288 ret_size = SIZEOF_CFG_CMD(afe_port_rtproxy_cfg);
289 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700290 case PCM_RX:
291 case PCM_TX:
292 default:
293 ret_size = SIZEOF_CFG_CMD(afe_port_pcm_cfg);
294 break;
295 }
296 return ret_size;
297}
298
Jay Wang6a305432011-08-05 16:01:54 -0700299int afe_q6_interface_prepare(void)
300{
301 int ret = 0;
302
303 pr_debug("%s:", __func__);
304
305 if (this_afe.apr == NULL) {
306 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
307 0xFFFFFFFF, &this_afe);
308 pr_debug("%s: Register AFE\n", __func__);
309 if (this_afe.apr == NULL) {
310 pr_err("%s: Unable to register AFE\n", __func__);
311 ret = -ENODEV;
312 }
313 }
314 return ret;
315}
316
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700317int afe_port_start_nowait(u16 port_id, union afe_port_config *afe_config,
318 u32 rate) /* This function is no blocking */
319{
320 struct afe_port_start_command start;
321 struct afe_audioif_config_command config;
322 int ret;
323
324 if (!afe_config) {
325 pr_err("%s: Error, no configuration data\n", __func__);
326 ret = -EINVAL;
327 return ret;
328 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700329 pr_info("%s: %d %d\n", __func__, port_id, rate);
330
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530331 if ((port_id == RT_PROXY_DAI_001_RX) ||
332 (port_id == RT_PROXY_DAI_002_TX))
333 return -EINVAL;
334 if ((port_id == RT_PROXY_DAI_002_RX) ||
335 (port_id == RT_PROXY_DAI_001_TX))
336 port_id = VIRTUAL_ID_TO_PORTID(port_id);
337
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700338 if (this_afe.apr == NULL) {
Jay Wang6a305432011-08-05 16:01:54 -0700339 pr_err("%s: AFE APR is not registered\n", __func__);
340 ret = -ENODEV;
341 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700342 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700343 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
344 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
345 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
346 config.hdr.src_port = 0;
347 config.hdr.dest_port = 0;
348 config.hdr.token = 0;
349 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
350
351 if (afe_validate_port(port_id) < 0) {
352
353 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
354 port_id);
355 ret = -EINVAL;
356 goto fail_cmd;
357 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700358 config.port_id = port_id;
359 config.port = *afe_config;
360
361 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
362 if (ret < 0) {
363 pr_err("%s: AFE enable for port %d failed\n", __func__,
364 port_id);
365 ret = -EINVAL;
366 goto fail_cmd;
367 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700368 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
369 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
370 start.hdr.pkt_size = sizeof(start);
371 start.hdr.src_port = 0;
372 start.hdr.dest_port = 0;
373 start.hdr.token = 0;
374 start.hdr.opcode = AFE_PORT_CMD_START;
375 start.port_id = port_id;
376 start.gain = 0x2000;
377 start.sample_rate = rate;
378
379 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
380
381 if (IS_ERR_VALUE(ret)) {
382 pr_err("%s: AFE enable for port %d failed\n", __func__,
383 port_id);
384 ret = -EINVAL;
385 goto fail_cmd;
386 }
387
388 if (this_afe.task != current)
389 this_afe.task = current;
390
391 pr_debug("task_name = %s pid = %d\n",
392 this_afe.task->comm, this_afe.task->pid);
393 return 0;
394
395fail_cmd:
396 return ret;
397}
398
399int afe_open(u16 port_id, union afe_port_config *afe_config, int rate)
400{
401 struct afe_port_start_command start;
402 struct afe_audioif_config_command config;
403 int ret = 0;
404
405 if (!afe_config) {
406 pr_err("%s: Error, no configuration data\n", __func__);
407 ret = -EINVAL;
408 return ret;
409 }
410
411 pr_info("%s: %d %d\n", __func__, port_id, rate);
412
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530413 if ((port_id == RT_PROXY_DAI_001_RX) ||
414 (port_id == RT_PROXY_DAI_002_TX))
415 return -EINVAL;
416 if ((port_id == RT_PROXY_DAI_002_RX) ||
417 (port_id == RT_PROXY_DAI_001_TX))
418 port_id = VIRTUAL_ID_TO_PORTID(port_id);
419
Jay Wang6a305432011-08-05 16:01:54 -0700420 ret = afe_q6_interface_prepare();
421 if (ret != 0)
422 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700423
424 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
425 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
426 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
427 config.hdr.src_port = 0;
428 config.hdr.dest_port = 0;
429 config.hdr.token = 0;
430 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
431
432 if (afe_validate_port(port_id) < 0) {
433
434 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
435 port_id);
436 ret = -EINVAL;
437 goto fail_cmd;
438 }
439
440 config.port_id = port_id;
441 config.port = *afe_config;
442
443 atomic_set(&this_afe.state, 1);
444 atomic_set(&this_afe.status, 0);
445 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
446 if (ret < 0) {
447 pr_err("%s: AFE enable for port %d failed\n", __func__,
448 port_id);
449 ret = -EINVAL;
450 goto fail_cmd;
451 }
452
453 ret = wait_event_timeout(this_afe.wait,
454 (atomic_read(&this_afe.state) == 0),
455 msecs_to_jiffies(TIMEOUT_MS));
456 if (!ret) {
457 pr_err("%s: wait_event timeout\n", __func__);
458 ret = -EINVAL;
459 goto fail_cmd;
460 }
461 if (atomic_read(&this_afe.status) != 0) {
462 pr_err("%s: config cmd failed\n", __func__);
463 ret = -EINVAL;
464 goto fail_cmd;
465 }
466 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
467 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
468 start.hdr.pkt_size = sizeof(start);
469 start.hdr.src_port = 0;
470 start.hdr.dest_port = 0;
471 start.hdr.token = 0;
472 start.hdr.opcode = AFE_PORT_CMD_START;
473 start.port_id = port_id;
474 start.gain = 0x2000;
475 start.sample_rate = rate;
476
477 atomic_set(&this_afe.state, 1);
478 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
479 if (ret < 0) {
480 pr_err("%s: AFE enable for port %d failed\n", __func__,
481 port_id);
482 ret = -EINVAL;
483 goto fail_cmd;
484 }
485 ret = wait_event_timeout(this_afe.wait,
486 (atomic_read(&this_afe.state) == 0),
487 msecs_to_jiffies(TIMEOUT_MS));
488 if (!ret) {
489 pr_err("%s: wait_event timeout\n", __func__);
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;
500fail_cmd:
501 return ret;
502}
503
504int afe_loopback(u16 enable, u16 rx_port, u16 tx_port)
505{
506 struct afe_loopback_command lb_cmd;
507 int ret = 0;
Jay Wang6a305432011-08-05 16:01:54 -0700508
509 ret = afe_q6_interface_prepare();
510 if (ret != 0)
511 return ret;
512
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700513 lb_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
514 APR_HDR_LEN(20), APR_PKT_VER);
515 lb_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
516 sizeof(lb_cmd) - APR_HDR_SIZE);
517 lb_cmd.hdr.src_port = 0;
518 lb_cmd.hdr.dest_port = 0;
519 lb_cmd.hdr.token = 0;
520 lb_cmd.hdr.opcode = AFE_PORT_CMD_LOOPBACK;
521 lb_cmd.tx_port_id = tx_port;
522 lb_cmd.rx_port_id = rx_port;
523 lb_cmd.mode = 0xFFFF;
524 lb_cmd.enable = (enable ? 1 : 0);
525 atomic_set(&this_afe.state, 1);
526
527 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &lb_cmd);
528 if (ret < 0) {
529 pr_err("%s: AFE loopback failed\n", __func__);
530 ret = -EINVAL;
531 goto done;
532 }
533 ret = wait_event_timeout(this_afe.wait,
534 (atomic_read(&this_afe.state) == 0),
535 msecs_to_jiffies(TIMEOUT_MS));
536 if (!ret) {
537 pr_err("%s: wait_event timeout\n", __func__);
538 ret = -EINVAL;
539 }
540done:
541 return ret;
542}
543
544
545int afe_loopback_gain(u16 port_id, u16 volume)
546{
547 struct afe_port_cmd_set_param set_param;
548 int ret = 0;
549
550 if (this_afe.apr == NULL) {
Jayasena Sangaraboina82435032011-07-26 15:23:00 -0700551 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
552 0xFFFFFFFF, &this_afe);
553 pr_debug("%s: Register AFE\n", __func__);
554 if (this_afe.apr == NULL) {
555 pr_err("%s: Unable to register AFE\n", __func__);
556 ret = -ENODEV;
557 return ret;
558 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700559 }
560
561 if (afe_validate_port(port_id) < 0) {
562
563 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
564 port_id);
565 ret = -EINVAL;
566 goto fail_cmd;
567 }
568
569 /* RX ports numbers are even .TX ports numbers are odd. */
570 if (port_id % 2 == 0) {
571 pr_err("%s: Failed : afe loopback gain only for TX ports."
572 " port_id %d\n", __func__, port_id);
573 ret = -EINVAL;
574 goto fail_cmd;
575 }
576
577 pr_debug("%s: %d %hX\n", __func__, port_id, volume);
578
579 set_param.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
580 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
581 set_param.hdr.pkt_size = sizeof(set_param);
582 set_param.hdr.src_port = 0;
583 set_param.hdr.dest_port = 0;
584 set_param.hdr.token = 0;
585 set_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
586
587 set_param.port_id = port_id;
588 set_param.payload_size = sizeof(struct afe_param_payload);
589 set_param.payload_address = 0;
590
591 set_param.payload.module_id = AFE_MODULE_ID_PORT_INFO;
592 set_param.payload.param_id = AFE_PARAM_ID_LOOPBACK_GAIN;
593 set_param.payload.param_size = sizeof(struct afe_param_loopback_gain);
594 set_param.payload.reserved = 0;
595
596 set_param.payload.param.loopback_gain.gain = volume;
597 set_param.payload.param.loopback_gain.reserved = 0;
598
599 atomic_set(&this_afe.state, 1);
600 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_param);
601 if (ret < 0) {
602 pr_err("%s: AFE param set failed for port %d\n",
603 __func__, port_id);
604 ret = -EINVAL;
605 goto fail_cmd;
606 }
607
608 ret = wait_event_timeout(this_afe.wait,
609 (atomic_read(&this_afe.state) == 0),
610 msecs_to_jiffies(TIMEOUT_MS));
611 if (ret < 0) {
612 pr_err("%s: wait_event timeout\n", __func__);
613 ret = -EINVAL;
614 goto fail_cmd;
615 }
616 return 0;
617fail_cmd:
618 return ret;
619}
620
Laxminath Kasam885f5102011-07-14 10:20:21 +0530621int afe_apply_gain(u16 port_id, u16 gain)
622{
623 struct afe_port_gain_command set_gain;
624 int ret = 0;
625
626 if (this_afe.apr == NULL) {
627 pr_err("%s: AFE is not opened\n", __func__);
628 ret = -EPERM;
629 goto fail_cmd;
630 }
631
632 if (afe_validate_port(port_id) < 0) {
633 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
634 port_id);
635 ret = -EINVAL;
636 goto fail_cmd;
637 }
638
639 /* RX ports numbers are even .TX ports numbers are odd. */
640 if (port_id % 2 == 0) {
641 pr_err("%s: Failed : afe apply gain only for TX ports."
642 " port_id %d\n", __func__, port_id);
643 ret = -EINVAL;
644 goto fail_cmd;
645 }
646
647 pr_debug("%s: %d %hX\n", __func__, port_id, gain);
648
649 set_gain.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
650 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
651 set_gain.hdr.pkt_size = sizeof(set_gain);
652 set_gain.hdr.src_port = 0;
653 set_gain.hdr.dest_port = 0;
654 set_gain.hdr.token = 0;
655 set_gain.hdr.opcode = AFE_PORT_CMD_APPLY_GAIN;
656
657 set_gain.port_id = port_id;
658 set_gain.gain = gain;
659
660 atomic_set(&this_afe.state, 1);
661 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_gain);
662 if (ret < 0) {
663 pr_err("%s: AFE Gain set failed for port %d\n",
664 __func__, port_id);
665 ret = -EINVAL;
666 goto fail_cmd;
667 }
668
669 ret = wait_event_timeout(this_afe.wait,
670 (atomic_read(&this_afe.state) == 0),
671 msecs_to_jiffies(TIMEOUT_MS));
672 if (ret < 0) {
673 pr_err("%s: wait_event timeout\n", __func__);
674 ret = -EINVAL;
675 goto fail_cmd;
676 }
677 return 0;
678fail_cmd:
679 return ret;
680}
Helen Zeng0705a5f2011-10-14 15:29:52 -0700681
682int afe_pseudo_port_start_nowait(u16 port_id)
683{
684 int ret = 0;
685 struct afe_pseudoport_start_command start;
686
687 pr_debug("%s: port_id=%d\n", __func__, port_id);
688 if (this_afe.apr == NULL) {
689 pr_err("%s: AFE APR is not registered\n", __func__);
690 return -ENODEV;
691 }
692
693
694 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
695 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
696 start.hdr.pkt_size = sizeof(start);
697 start.hdr.src_port = 0;
698 start.hdr.dest_port = 0;
699 start.hdr.token = 0;
700 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
701 start.port_id = port_id;
702 start.timing = 1;
703
704 atomic_set(&this_afe.state, 1);
705 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
706 if (ret < 0) {
707 pr_err("%s: AFE enable for port %d failed %d\n",
708 __func__, port_id, ret);
709 return -EINVAL;
710 }
711 return 0;
712}
713
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700714int afe_start_pseudo_port(u16 port_id)
715{
716 int ret = 0;
717 struct afe_pseudoport_start_command start;
718
719 pr_info("%s: port_id=%d\n", __func__, port_id);
720
Jay Wang6a305432011-08-05 16:01:54 -0700721 ret = afe_q6_interface_prepare();
722 if (ret != 0)
723 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700724
725 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
726 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
727 start.hdr.pkt_size = sizeof(start);
728 start.hdr.src_port = 0;
729 start.hdr.dest_port = 0;
730 start.hdr.token = 0;
731 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
732 start.port_id = port_id;
733 start.timing = 1;
734
735 atomic_set(&this_afe.state, 1);
736 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
737 if (ret < 0) {
738 pr_err("%s: AFE enable for port %d failed %d\n",
739 __func__, port_id, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700740 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700741 }
742
743 ret = wait_event_timeout(this_afe.wait,
744 (atomic_read(&this_afe.state) == 0),
745 msecs_to_jiffies(TIMEOUT_MS));
746 if (!ret) {
747 pr_err("%s: wait_event timeout\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700748 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700749 }
750
751 return 0;
752}
753
Helen Zeng0705a5f2011-10-14 15:29:52 -0700754int afe_pseudo_port_stop_nowait(u16 port_id)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700755{
756 int ret = 0;
757 struct afe_pseudoport_stop_command stop;
758
Helen Zeng0705a5f2011-10-14 15:29:52 -0700759 pr_debug("%s: port_id=%d\n", __func__, port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700760
761 if (this_afe.apr == NULL) {
762 pr_err("%s: AFE is already closed\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700763 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700764 }
765
766 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
767 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
768 stop.hdr.pkt_size = sizeof(stop);
769 stop.hdr.src_port = 0;
770 stop.hdr.dest_port = 0;
771 stop.hdr.token = 0;
772 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
773 stop.port_id = port_id;
774 stop.reserved = 0;
775
776 atomic_set(&this_afe.state, 1);
777 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
778 if (ret < 0) {
779 pr_err("%s: AFE close failed %d\n", __func__, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700780 return -EINVAL;
781 }
782
783 return 0;
784
785}
786
787int afe_stop_pseudo_port(u16 port_id)
788{
789 int ret = 0;
790 struct afe_pseudoport_stop_command stop;
791
792 pr_info("%s: port_id=%d\n", __func__, port_id);
793
794 if (this_afe.apr == NULL) {
795 pr_err("%s: AFE is already closed\n", __func__);
796 return -EINVAL;
797 }
798
799 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
800 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
801 stop.hdr.pkt_size = sizeof(stop);
802 stop.hdr.src_port = 0;
803 stop.hdr.dest_port = 0;
804 stop.hdr.token = 0;
805 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
806 stop.port_id = port_id;
807 stop.reserved = 0;
808
809 atomic_set(&this_afe.state, 1);
810 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
811 if (ret < 0) {
812 pr_err("%s: AFE close failed %d\n", __func__, ret);
813 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700814 }
815
816 ret = wait_event_timeout(this_afe.wait,
817 (atomic_read(&this_afe.state) == 0),
818 msecs_to_jiffies(TIMEOUT_MS));
819 if (!ret) {
820 pr_err("%s: wait_event timeout\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -0700821 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700822 }
823
824 return 0;
825}
826
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530827int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz)
828{
829 int ret = 0;
830 struct afe_cmd_memory_map mregion;
831
832 pr_debug("%s:\n", __func__);
833
834 if (this_afe.apr == NULL) {
835 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
836 0xFFFFFFFF, &this_afe);
837 pr_debug("%s: Register AFE\n", __func__);
838 if (this_afe.apr == NULL) {
839 pr_err("%s: Unable to register AFE\n", __func__);
840 ret = -ENODEV;
841 return ret;
842 }
843 }
844
845 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
846 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
847 mregion.hdr.pkt_size = sizeof(mregion);
848 mregion.hdr.src_port = 0;
849 mregion.hdr.dest_port = 0;
850 mregion.hdr.token = 0;
851 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
852 mregion.phy_addr = dma_addr_p;
853 mregion.mem_sz = dma_buf_sz;
854 mregion.mem_id = 0;
855 mregion.rsvd = 0;
856
857 atomic_set(&this_afe.state, 1);
858 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
859 if (ret < 0) {
860 pr_err("%s: AFE memory map cmd failed %d\n",
861 __func__, ret);
862 ret = -EINVAL;
863 return ret;
864 }
865
866 ret = wait_event_timeout(this_afe.wait,
867 (atomic_read(&this_afe.state) == 0),
868 msecs_to_jiffies(TIMEOUT_MS));
869 if (!ret) {
870 pr_err("%s: wait_event timeout\n", __func__);
871 ret = -EINVAL;
872 return ret;
873 }
874
875 return 0;
876}
877
878int afe_cmd_memory_unmap(u32 dma_addr_p)
879{
880 int ret = 0;
881 struct afe_cmd_memory_unmap mregion;
882
883 pr_debug("%s:\n", __func__);
884
885 if (this_afe.apr == NULL) {
886 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
887 0xFFFFFFFF, &this_afe);
888 pr_debug("%s: Register AFE\n", __func__);
889 if (this_afe.apr == NULL) {
890 pr_err("%s: Unable to register AFE\n", __func__);
891 ret = -ENODEV;
892 return ret;
893 }
894 }
895
896 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
897 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
898 mregion.hdr.pkt_size = sizeof(mregion);
899 mregion.hdr.src_port = 0;
900 mregion.hdr.dest_port = 0;
901 mregion.hdr.token = 0;
902 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
903 mregion.phy_addr = dma_addr_p;
904
905 atomic_set(&this_afe.state, 1);
906 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
907 if (ret < 0) {
908 pr_err("%s: AFE memory map cmd failed %d\n",
909 __func__, ret);
910 ret = -EINVAL;
911 return ret;
912 }
913
914 ret = wait_event_timeout(this_afe.wait,
915 (atomic_read(&this_afe.state) == 0),
916 msecs_to_jiffies(TIMEOUT_MS));
917 if (!ret) {
918 pr_err("%s: wait_event timeout\n", __func__);
919 ret = -EINVAL;
920 return ret;
921 }
922
923 return 0;
924}
925
926int afe_register_get_events(u16 port_id,
927 void (*cb) (uint32_t opcode,
928 uint32_t token, uint32_t *payload, void *priv),
929 void *private_data)
930{
931 int ret = 0;
932 struct afe_cmd_reg_rtport rtproxy;
933
934 pr_debug("%s:\n", __func__);
935
936 if (this_afe.apr == NULL) {
937 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
938 0xFFFFFFFF, &this_afe);
939 pr_debug("%s: Register AFE\n", __func__);
940 if (this_afe.apr == NULL) {
941 pr_err("%s: Unable to register AFE\n", __func__);
942 ret = -ENODEV;
943 return ret;
944 }
945 }
946 if ((port_id == RT_PROXY_DAI_002_RX) ||
947 (port_id == RT_PROXY_DAI_001_TX))
948 port_id = VIRTUAL_ID_TO_PORTID(port_id);
949 else
950 return -EINVAL;
951
952 if (port_id == RT_PROXY_PORT_001_TX) {
953 this_afe.tx_cb = cb;
954 this_afe.tx_private_data = private_data;
955 } else if (port_id == RT_PROXY_PORT_001_RX) {
956 this_afe.rx_cb = cb;
957 this_afe.rx_private_data = private_data;
958 }
959
960 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
961 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
962 rtproxy.hdr.pkt_size = sizeof(rtproxy);
963 rtproxy.hdr.src_port = 1;
964 rtproxy.hdr.dest_port = 1;
965 rtproxy.hdr.token = 0;
966 rtproxy.hdr.opcode = AFE_SERVICE_CMD_REG_RTPORT;
967 rtproxy.port_id = port_id;
968 rtproxy.rsvd = 0;
969
970 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
971 if (ret < 0) {
972 pr_err("%s: AFE reg. rtproxy_event failed %d\n",
973 __func__, ret);
974 ret = -EINVAL;
975 return ret;
976 }
977 return 0;
978}
979
980int afe_unregister_get_events(u16 port_id)
981{
982 int ret = 0;
983 struct afe_cmd_unreg_rtport rtproxy;
984
985 pr_debug("%s:\n", __func__);
986
987 if (this_afe.apr == NULL) {
988 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
989 0xFFFFFFFF, &this_afe);
990 pr_debug("%s: Register AFE\n", __func__);
991 if (this_afe.apr == NULL) {
992 pr_err("%s: Unable to register AFE\n", __func__);
993 ret = -ENODEV;
994 return ret;
995 }
996 }
997 if ((port_id == RT_PROXY_DAI_002_RX) ||
998 (port_id == RT_PROXY_DAI_001_TX))
999 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1000 else
1001 return -EINVAL;
1002
1003 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1004 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1005 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1006 rtproxy.hdr.src_port = 0;
1007 rtproxy.hdr.dest_port = 0;
1008 rtproxy.hdr.token = 0;
1009 rtproxy.hdr.opcode = AFE_SERVICE_CMD_UNREG_RTPORT;
1010 rtproxy.port_id = port_id;
1011 rtproxy.rsvd = 0;
1012
1013 if (port_id == RT_PROXY_PORT_001_TX) {
1014 this_afe.tx_cb = NULL;
1015 this_afe.tx_private_data = NULL;
1016 } else if (port_id == RT_PROXY_PORT_001_RX) {
1017 this_afe.rx_cb = NULL;
1018 this_afe.rx_private_data = NULL;
1019 }
1020
1021 atomic_set(&this_afe.state, 1);
1022 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1023 if (ret < 0) {
1024 pr_err("%s: AFE enable Unreg. rtproxy_event failed %d\n",
1025 __func__, ret);
1026 ret = -EINVAL;
1027 return ret;
1028 }
1029
1030 ret = wait_event_timeout(this_afe.wait,
1031 (atomic_read(&this_afe.state) == 0),
1032 msecs_to_jiffies(TIMEOUT_MS));
1033 if (!ret) {
1034 pr_err("%s: wait_event timeout\n", __func__);
1035 ret = -EINVAL;
1036 return ret;
1037 }
1038 return 0;
1039}
1040
1041int afe_rt_proxy_port_write(u32 buf_addr_p, int bytes)
1042{
1043 int ret = 0;
1044 struct afe_cmd_rtport_wr afecmd_wr;
1045
1046 if (this_afe.apr == NULL) {
1047 pr_err("%s:register to AFE is not done\n", __func__);
1048 ret = -ENODEV;
1049 return ret;
1050 }
1051 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1052 buf_addr_p, bytes);
1053
1054 afecmd_wr.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1055 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1056 afecmd_wr.hdr.pkt_size = sizeof(afecmd_wr);
1057 afecmd_wr.hdr.src_port = 0;
1058 afecmd_wr.hdr.dest_port = 0;
1059 afecmd_wr.hdr.token = 0;
1060 afecmd_wr.hdr.opcode = AFE_SERVICE_CMD_RTPORT_WR;
1061 afecmd_wr.buf_addr = (uint32_t)buf_addr_p;
1062 afecmd_wr.port_id = RT_PROXY_PORT_001_TX;
1063 afecmd_wr.bytes_avail = bytes;
1064 afecmd_wr.rsvd = 0;
1065
1066 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_wr);
1067 if (ret < 0) {
1068 pr_err("%s: AFE rtproxy write to port 0x%x failed %d\n",
1069 __func__, afecmd_wr.port_id, ret);
1070 ret = -EINVAL;
1071 return ret;
1072 }
1073 return 0;
1074
1075}
1076
1077int afe_rt_proxy_port_read(u32 buf_addr_p, int bytes)
1078{
1079 int ret = 0;
1080 struct afe_cmd_rtport_rd afecmd_rd;
1081
1082 if (this_afe.apr == NULL) {
1083 pr_err("%s: register to AFE is not done\n", __func__);
1084 ret = -ENODEV;
1085 return ret;
1086 }
1087 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1088 buf_addr_p, bytes);
1089
1090 afecmd_rd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1091 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1092 afecmd_rd.hdr.pkt_size = sizeof(afecmd_rd);
1093 afecmd_rd.hdr.src_port = 0;
1094 afecmd_rd.hdr.dest_port = 0;
1095 afecmd_rd.hdr.token = 0;
1096 afecmd_rd.hdr.opcode = AFE_SERVICE_CMD_RTPORT_RD;
1097 afecmd_rd.buf_addr = (uint32_t)buf_addr_p;
1098 afecmd_rd.port_id = RT_PROXY_PORT_001_RX;
1099 afecmd_rd.bytes_avail = bytes;
1100 afecmd_rd.rsvd = 0;
1101
1102 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_rd);
1103 if (ret < 0) {
1104 pr_err("%s: AFE rtproxy read cmd to port 0x%x failed %d\n",
1105 __func__, afecmd_rd.port_id, ret);
1106 ret = -EINVAL;
1107 return ret;
1108 }
1109 return 0;
1110}
1111
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001112#ifdef CONFIG_DEBUG_FS
1113static struct dentry *debugfs_afelb;
1114static struct dentry *debugfs_afelb_gain;
1115
1116static int afe_debug_open(struct inode *inode, struct file *file)
1117{
1118 file->private_data = inode->i_private;
1119 pr_info("debug intf %s\n", (char *) file->private_data);
1120 return 0;
1121}
1122
1123static int afe_get_parameters(char *buf, long int *param1, int num_of_par)
1124{
1125 char *token;
1126 int base, cnt;
1127
1128 token = strsep(&buf, " ");
1129
1130 for (cnt = 0; cnt < num_of_par; cnt++) {
1131 if (token != NULL) {
1132 if ((token[1] == 'x') || (token[1] == 'X'))
1133 base = 16;
1134 else
1135 base = 10;
1136
1137 if (strict_strtoul(token, base, &param1[cnt]) != 0)
1138 return -EINVAL;
1139
1140 token = strsep(&buf, " ");
1141 } else
1142 return -EINVAL;
1143 }
1144 return 0;
1145}
1146#define AFE_LOOPBACK_ON (1)
1147#define AFE_LOOPBACK_OFF (0)
1148static ssize_t afe_debug_write(struct file *filp,
1149 const char __user *ubuf, size_t cnt, loff_t *ppos)
1150{
1151 char *lb_str = filp->private_data;
1152 char lbuf[32];
1153 int rc;
1154 unsigned long param[5];
1155
1156 if (cnt > sizeof(lbuf) - 1)
1157 return -EINVAL;
1158
1159 rc = copy_from_user(lbuf, ubuf, cnt);
1160 if (rc)
1161 return -EFAULT;
1162
1163 lbuf[cnt] = '\0';
1164
1165 if (!strcmp(lb_str, "afe_loopback")) {
1166 rc = afe_get_parameters(lbuf, param, 3);
1167 if (!rc) {
1168 pr_info("%s %lu %lu %lu\n", lb_str, param[0], param[1],
1169 param[2]);
1170
1171 if ((param[0] != AFE_LOOPBACK_ON) && (param[0] !=
1172 AFE_LOOPBACK_OFF)) {
1173 pr_err("%s: Error, parameter 0 incorrect\n",
1174 __func__);
1175 rc = -EINVAL;
1176 goto afe_error;
1177 }
1178 if ((afe_validate_port(param[1]) < 0) ||
1179 (afe_validate_port(param[2])) < 0) {
1180 pr_err("%s: Error, invalid afe port\n",
1181 __func__);
1182 }
1183 if (this_afe.apr == NULL) {
1184 pr_err("%s: Error, AFE not opened\n", __func__);
1185 rc = -EINVAL;
1186 } else {
1187 rc = afe_loopback(param[0], param[1], param[2]);
1188 }
1189 } else {
1190 pr_err("%s: Error, invalid parameters\n", __func__);
1191 rc = -EINVAL;
1192 }
1193
1194 } else if (!strcmp(lb_str, "afe_loopback_gain")) {
1195 rc = afe_get_parameters(lbuf, param, 2);
1196 if (!rc) {
1197 pr_info("%s %lu %lu\n", lb_str, param[0], param[1]);
1198
1199 if (afe_validate_port(param[0]) < 0) {
1200 pr_err("%s: Error, invalid afe port\n",
1201 __func__);
1202 rc = -EINVAL;
1203 goto afe_error;
1204 }
1205
1206 if (param[1] < 0 || param[1] > 100) {
1207 pr_err("%s: Error, volume shoud be 0 to 100"
1208 " percentage param = %lu\n",
1209 __func__, param[1]);
1210 rc = -EINVAL;
1211 goto afe_error;
1212 }
1213
1214 param[1] = (Q6AFE_MAX_VOLUME * param[1]) / 100;
1215
1216 if (this_afe.apr == NULL) {
1217 pr_err("%s: Error, AFE not opened\n", __func__);
1218 rc = -EINVAL;
1219 } else {
1220 rc = afe_loopback_gain(param[0], param[1]);
1221 }
1222 } else {
1223 pr_err("%s: Error, invalid parameters\n", __func__);
1224 rc = -EINVAL;
1225 }
1226 }
1227
1228afe_error:
1229 if (rc == 0)
1230 rc = cnt;
1231 else
1232 pr_err("%s: rc = %d\n", __func__, rc);
1233
1234 return rc;
1235}
1236
1237static const struct file_operations afe_debug_fops = {
1238 .open = afe_debug_open,
1239 .write = afe_debug_write
1240};
1241#endif
1242int afe_sidetone(u16 tx_port_id, u16 rx_port_id, u16 enable, uint16_t gain)
1243{
1244 struct afe_port_sidetone_command cmd_sidetone;
1245 int ret = 0;
1246
1247 pr_info("%s: tx_port_id:%d rx_port_id:%d enable:%d gain:%d\n", __func__,
1248 tx_port_id, rx_port_id, enable, gain);
1249 cmd_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1250 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1251 cmd_sidetone.hdr.pkt_size = sizeof(cmd_sidetone);
1252 cmd_sidetone.hdr.src_port = 0;
1253 cmd_sidetone.hdr.dest_port = 0;
1254 cmd_sidetone.hdr.token = 0;
1255 cmd_sidetone.hdr.opcode = AFE_PORT_CMD_SIDETONE_CTL;
1256 cmd_sidetone.tx_port_id = tx_port_id;
1257 cmd_sidetone.rx_port_id = rx_port_id;
1258 cmd_sidetone.gain = gain;
1259 cmd_sidetone.enable = enable;
1260
1261 atomic_set(&this_afe.state, 1);
1262 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_sidetone);
1263 if (ret < 0) {
1264 pr_err("%s: AFE sidetone failed for tx_port:%d rx_port:%d\n",
1265 __func__, tx_port_id, rx_port_id);
1266 ret = -EINVAL;
1267 goto fail_cmd;
1268 }
1269
1270 ret = wait_event_timeout(this_afe.wait,
1271 (atomic_read(&this_afe.state) == 0),
1272 msecs_to_jiffies(TIMEOUT_MS));
1273 if (ret < 0) {
1274 pr_err("%s: wait_event timeout\n", __func__);
1275 ret = -EINVAL;
1276 goto fail_cmd;
1277 }
1278 return 0;
1279fail_cmd:
1280 return ret;
1281}
1282
1283int afe_port_stop_nowait(int port_id)
1284{
1285 struct afe_port_stop_command stop;
1286 int ret = 0;
1287
1288 if (this_afe.apr == NULL) {
1289 pr_err("AFE is already closed\n");
1290 ret = -EINVAL;
1291 goto fail_cmd;
1292 }
1293 pr_info("%s: port_id=%d\n", __func__, port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301294 port_id = afe_convert_virtual_to_portid(port_id);
1295
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001296 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1297 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1298 stop.hdr.pkt_size = sizeof(stop);
1299 stop.hdr.src_port = 0;
1300 stop.hdr.dest_port = 0;
1301 stop.hdr.token = 0;
1302 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1303 stop.port_id = port_id;
1304 stop.reserved = 0;
1305
1306 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1307
1308 if (ret == -ENETRESET) {
1309 pr_info("%s: Need to reset, calling APR deregister", __func__);
1310 return apr_deregister(this_afe.apr);
1311 } else if (IS_ERR_VALUE(ret)) {
1312 pr_err("%s: AFE close failed\n", __func__);
1313 ret = -EINVAL;
1314 }
1315
1316fail_cmd:
1317 return ret;
1318
1319}
1320
1321int afe_close(int port_id)
1322{
1323 struct afe_port_stop_command stop;
1324 int ret = 0;
1325
1326 if (this_afe.apr == NULL) {
1327 pr_err("AFE is already closed\n");
1328 ret = -EINVAL;
1329 goto fail_cmd;
1330 }
1331 pr_info("%s: port_id=%d\n", __func__, port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301332 port_id = afe_convert_virtual_to_portid(port_id);
1333
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001334 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1335 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1336 stop.hdr.pkt_size = sizeof(stop);
1337 stop.hdr.src_port = 0;
1338 stop.hdr.dest_port = 0;
1339 stop.hdr.token = 0;
1340 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1341 stop.port_id = port_id;
1342 stop.reserved = 0;
1343
1344 atomic_set(&this_afe.state, 1);
1345 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1346
1347 if (ret == -ENETRESET) {
1348 pr_info("%s: Need to reset, calling APR deregister", __func__);
1349 return apr_deregister(this_afe.apr);
1350 }
1351
1352 if (ret < 0) {
1353 pr_err("%s: AFE close failed\n", __func__);
1354 ret = -EINVAL;
1355 goto fail_cmd;
1356 }
1357
1358 ret = wait_event_timeout(this_afe.wait,
1359 (atomic_read(&this_afe.state) == 0),
1360 msecs_to_jiffies(TIMEOUT_MS));
1361 if (!ret) {
1362 pr_err("%s: wait_event timeout\n", __func__);
1363 ret = -EINVAL;
1364 goto fail_cmd;
1365 }
1366fail_cmd:
1367 return ret;
1368}
1369
1370static int __init afe_init(void)
1371{
1372 init_waitqueue_head(&this_afe.wait);
1373 atomic_set(&this_afe.state, 0);
1374 atomic_set(&this_afe.status, 0);
1375 this_afe.apr = NULL;
1376#ifdef CONFIG_DEBUG_FS
1377 debugfs_afelb = debugfs_create_file("afe_loopback",
1378 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback",
1379 &afe_debug_fops);
1380
1381 debugfs_afelb_gain = debugfs_create_file("afe_loopback_gain",
1382 S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback_gain",
1383 &afe_debug_fops);
1384
1385
1386#endif
1387 return 0;
1388}
1389
1390static void __exit afe_exit(void)
1391{
1392#ifdef CONFIG_DEBUG_FS
1393 if (debugfs_afelb)
1394 debugfs_remove(debugfs_afelb);
1395 if (debugfs_afelb_gain)
1396 debugfs_remove(debugfs_afelb_gain);
1397#endif
1398}
1399
1400device_initcall(afe_init);
1401__exitcall(afe_exit);