blob: 0edcde0a8cd6cc1191e8cd7089a7acfefbeb26ea [file] [log] [blame]
Satya Krishna Pindiprolie8b84552013-01-24 09:46:10 +05301/* Copyright (c) 2010-2013, The Linux Foundation. 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];
Satya Krishna Pindiprolie8b84552013-01-24 09:46:10 +053041static int pcm_afe_instance[2];
42static int proxy_afe_instance[2];
Ben Rombergerb7603232011-11-23 17:16:27 -080043
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070044#define TIMEOUT_MS 1000
45#define Q6AFE_MAX_VOLUME 0x3FFF
46
47#define SIZEOF_CFG_CMD(y) \
48 (sizeof(struct apr_hdr) + sizeof(u16) + (sizeof(struct y)))
49
50static int32_t afe_callback(struct apr_client_data *data, void *priv)
51{
52 if (data->opcode == RESET_EVENTS) {
53 pr_debug("q6afe: reset event = %d %d apr[%p]\n",
54 data->reset_event, data->reset_proc, this_afe.apr);
55 if (this_afe.apr) {
56 apr_reset(this_afe.apr);
57 atomic_set(&this_afe.state, 0);
58 this_afe.apr = NULL;
59 }
60 /* send info to user */
61 pr_debug("task_name = %s pid = %d\n",
62 this_afe.task->comm, this_afe.task->pid);
63 send_sig(SIGUSR1, this_afe.task, 0);
Laxminath Kasam9bb28c62012-01-18 21:55:37 +053064 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070065 }
66 if (data->payload_size) {
67 uint32_t *payload;
Laxminath Kasam32657ec2011-08-01 19:26:57 +053068 uint16_t port_id = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070069 payload = data->payload;
Laxminath Kasam32657ec2011-08-01 19:26:57 +053070 pr_debug("%s:opcode = 0x%x cmd = 0x%x status = 0x%x\n",
71 __func__, data->opcode,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070072 payload[0], payload[1]);
73 /* payload[1] contains the error status for response */
74 if (payload[1] != 0) {
75 atomic_set(&this_afe.status, -1);
76 pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
77 __func__, payload[0], payload[1]);
78 }
79 if (data->opcode == APR_BASIC_RSP_RESULT) {
80 switch (payload[0]) {
81 case AFE_PORT_AUDIO_IF_CONFIG:
Kuirong Wanga36f2882012-04-02 19:45:26 -070082 case AFE_PORT_CMD_I2S_CONFIG:
Kiran Kandi5e809b02012-01-31 00:24:33 -080083 case AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG:
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -080084 case AFE_PORT_AUDIO_SLIM_SCH_CONFIG:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070085 case AFE_PORT_CMD_STOP:
86 case AFE_PORT_CMD_START:
87 case AFE_PORT_CMD_LOOPBACK:
88 case AFE_PORT_CMD_SIDETONE_CTL:
89 case AFE_PORT_CMD_SET_PARAM:
90 case AFE_PSEUDOPORT_CMD_START:
91 case AFE_PSEUDOPORT_CMD_STOP:
Laxminath Kasam885f5102011-07-14 10:20:21 +053092 case AFE_PORT_CMD_APPLY_GAIN:
Laxminath Kasam32657ec2011-08-01 19:26:57 +053093 case AFE_SERVICE_CMD_MEMORY_MAP:
94 case AFE_SERVICE_CMD_MEMORY_UNMAP:
95 case AFE_SERVICE_CMD_UNREG_RTPORT:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070096 atomic_set(&this_afe.state, 0);
97 wake_up(&this_afe.wait);
98 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +053099 case AFE_SERVICE_CMD_REG_RTPORT:
100 break;
101 case AFE_SERVICE_CMD_RTPORT_WR:
102 port_id = RT_PROXY_PORT_001_TX;
103 break;
104 case AFE_SERVICE_CMD_RTPORT_RD:
105 port_id = RT_PROXY_PORT_001_RX;
106 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700107 default:
108 pr_err("Unknown cmd 0x%x\n",
109 payload[0]);
110 break;
111 }
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530112 } else if (data->opcode == AFE_EVENT_RT_PROXY_PORT_STATUS) {
113 port_id = (uint16_t)(0x0000FFFF & payload[0]);
114 }
115 pr_debug("%s:port_id = %x\n", __func__, port_id);
116 switch (port_id) {
117 case RT_PROXY_PORT_001_TX: {
118 if (this_afe.tx_cb) {
119 this_afe.tx_cb(data->opcode, data->token,
120 data->payload,
121 this_afe.tx_private_data);
122 }
123 break;
124 }
125 case RT_PROXY_PORT_001_RX: {
126 if (this_afe.rx_cb) {
127 this_afe.rx_cb(data->opcode, data->token,
128 data->payload,
129 this_afe.rx_private_data);
130 }
131 break;
132 }
133 default:
134 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700135 }
136 }
137 return 0;
138}
139
Neema Shettyfeea7742011-09-11 12:30:36 -0700140int afe_get_port_type(u16 port_id)
141{
142 int ret;
143
144 switch (port_id) {
145 case PRIMARY_I2S_RX:
146 case PCM_RX:
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700147 case SECONDARY_PCM_RX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700148 case SECONDARY_I2S_RX:
149 case MI2S_RX:
150 case HDMI_RX:
151 case SLIMBUS_0_RX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800152 case SLIMBUS_1_RX:
Kiran Kandifd30c892012-05-21 23:03:26 -0700153 case SLIMBUS_2_RX:
Neema Shetty74131ac2012-05-09 13:35:26 -0700154 case SLIMBUS_3_RX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700155 case INT_BT_SCO_RX:
156 case INT_BT_A2DP_RX:
157 case INT_FM_RX:
158 case VOICE_PLAYBACK_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530159 case RT_PROXY_PORT_001_RX:
Helen Zeng8f925502012-03-05 16:50:17 -0800160 case SLIMBUS_4_RX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700161 ret = MSM_AFE_PORT_TYPE_RX;
162 break;
163
164 case PRIMARY_I2S_TX:
165 case PCM_TX:
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700166 case SECONDARY_PCM_TX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700167 case SECONDARY_I2S_TX:
168 case MI2S_TX:
169 case DIGI_MIC_TX:
170 case VOICE_RECORD_TX:
171 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800172 case SLIMBUS_1_TX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700173 case SLIMBUS_2_TX:
Helen Zeng38c3c962012-05-17 14:56:20 -0700174 case SLIMBUS_3_TX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700175 case INT_FM_TX:
176 case VOICE_RECORD_RX:
177 case INT_BT_SCO_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530178 case RT_PROXY_PORT_001_TX:
Helen Zeng8f925502012-03-05 16:50:17 -0800179 case SLIMBUS_4_TX:
Neema Shettyfeea7742011-09-11 12:30:36 -0700180 ret = MSM_AFE_PORT_TYPE_TX;
181 break;
182
183 default:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800184 pr_err("%s: invalid port id %d\n", __func__, port_id);
Neema Shettyfeea7742011-09-11 12:30:36 -0700185 ret = -EINVAL;
186 }
187
188 return ret;
189}
190
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700191int afe_validate_port(u16 port_id)
192{
193 int ret;
194
195 switch (port_id) {
196 case PRIMARY_I2S_RX:
197 case PRIMARY_I2S_TX:
198 case PCM_RX:
199 case PCM_TX:
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700200 case SECONDARY_PCM_RX:
201 case SECONDARY_PCM_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700202 case SECONDARY_I2S_RX:
203 case SECONDARY_I2S_TX:
204 case MI2S_RX:
205 case MI2S_TX:
206 case HDMI_RX:
207 case RSVD_2:
208 case RSVD_3:
209 case DIGI_MIC_TX:
210 case VOICE_RECORD_RX:
211 case VOICE_RECORD_TX:
212 case VOICE_PLAYBACK_TX:
213 case SLIMBUS_0_RX:
214 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800215 case SLIMBUS_1_RX:
216 case SLIMBUS_1_TX:
Kiran Kandifd30c892012-05-21 23:03:26 -0700217 case SLIMBUS_2_RX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700218 case SLIMBUS_2_TX:
Neema Shetty74131ac2012-05-09 13:35:26 -0700219 case SLIMBUS_3_RX:
Helen Zeng38c3c962012-05-17 14:56:20 -0700220 case SLIMBUS_3_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700221 case INT_BT_SCO_RX:
222 case INT_BT_SCO_TX:
223 case INT_BT_A2DP_RX:
224 case INT_FM_RX:
225 case INT_FM_TX:
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530226 case RT_PROXY_PORT_001_RX:
227 case RT_PROXY_PORT_001_TX:
Helen Zeng8f925502012-03-05 16:50:17 -0800228 case SLIMBUS_4_RX:
229 case SLIMBUS_4_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700230 {
231 ret = 0;
232 break;
233 }
234
235 default:
236 ret = -EINVAL;
237 }
238
239 return ret;
240}
241
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530242int afe_convert_virtual_to_portid(u16 port_id)
243{
244 int ret;
245
246 /* if port_id is virtual, convert to physical..
247 * if port_id is already physical, return physical
248 */
249 if (afe_validate_port(port_id) < 0) {
250 if (port_id == RT_PROXY_DAI_001_RX ||
251 port_id == RT_PROXY_DAI_001_TX ||
252 port_id == RT_PROXY_DAI_002_RX ||
253 port_id == RT_PROXY_DAI_002_TX)
254 ret = VIRTUAL_ID_TO_PORTID(port_id);
255 else
256 ret = -EINVAL;
257 } else
258 ret = port_id;
259
260 return ret;
261}
262
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700263int afe_get_port_index(u16 port_id)
264{
265 switch (port_id) {
266 case PRIMARY_I2S_RX: return IDX_PRIMARY_I2S_RX;
267 case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
268 case PCM_RX: return IDX_PCM_RX;
269 case PCM_TX: return IDX_PCM_TX;
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700270 case SECONDARY_PCM_RX: return IDX_SECONDARY_PCM_RX;
271 case SECONDARY_PCM_TX: return IDX_SECONDARY_PCM_TX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700272 case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
273 case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
274 case MI2S_RX: return IDX_MI2S_RX;
275 case MI2S_TX: return IDX_MI2S_TX;
276 case HDMI_RX: return IDX_HDMI_RX;
277 case RSVD_2: return IDX_RSVD_2;
278 case RSVD_3: return IDX_RSVD_3;
279 case DIGI_MIC_TX: return IDX_DIGI_MIC_TX;
280 case VOICE_RECORD_RX: return IDX_VOICE_RECORD_RX;
281 case VOICE_RECORD_TX: return IDX_VOICE_RECORD_TX;
282 case VOICE_PLAYBACK_TX: return IDX_VOICE_PLAYBACK_TX;
283 case SLIMBUS_0_RX: return IDX_SLIMBUS_0_RX;
284 case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
Neema Shetty3c9d2862012-03-11 01:25:32 -0800285 case SLIMBUS_1_RX: return IDX_SLIMBUS_1_RX;
286 case SLIMBUS_1_TX: return IDX_SLIMBUS_1_TX;
Kiran Kandifd30c892012-05-21 23:03:26 -0700287 case SLIMBUS_2_RX: return IDX_SLIMBUS_2_RX;
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700288 case SLIMBUS_2_TX: return IDX_SLIMBUS_2_TX;
Neema Shetty74131ac2012-05-09 13:35:26 -0700289 case SLIMBUS_3_RX: return IDX_SLIMBUS_3_RX;
Helen Zeng38c3c962012-05-17 14:56:20 -0700290 case SLIMBUS_3_TX: return IDX_SLIMBUS_3_TX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700291 case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
292 case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
293 case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
294 case INT_FM_RX: return IDX_INT_FM_RX;
295 case INT_FM_TX: return IDX_INT_FM_TX;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530296 case RT_PROXY_PORT_001_RX: return IDX_RT_PROXY_PORT_001_RX;
297 case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
Helen Zeng8f925502012-03-05 16:50:17 -0800298 case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX;
299 case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700300
301 default: return -EINVAL;
302 }
303}
304
305int afe_sizeof_cfg_cmd(u16 port_id)
306{
307 int ret_size;
308 switch (port_id) {
309 case PRIMARY_I2S_RX:
310 case PRIMARY_I2S_TX:
311 case SECONDARY_I2S_RX:
312 case SECONDARY_I2S_TX:
313 case MI2S_RX:
314 case MI2S_TX:
315 ret_size = SIZEOF_CFG_CMD(afe_port_mi2s_cfg);
316 break;
317 case HDMI_RX:
Kiran Kandi5e809b02012-01-31 00:24:33 -0800318 ret_size = SIZEOF_CFG_CMD(afe_port_hdmi_multi_ch_cfg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700319 break;
320 case SLIMBUS_0_RX:
321 case SLIMBUS_0_TX:
Neema Shetty3c9d2862012-03-11 01:25:32 -0800322 case SLIMBUS_1_RX:
323 case SLIMBUS_1_TX:
Kiran Kandifd30c892012-05-21 23:03:26 -0700324 case SLIMBUS_2_RX:
Kiran Kandi1e6371d2012-03-29 11:48:57 -0700325 case SLIMBUS_2_TX:
Neema Shetty74131ac2012-05-09 13:35:26 -0700326 case SLIMBUS_3_RX:
Helen Zeng38c3c962012-05-17 14:56:20 -0700327 case SLIMBUS_3_TX:
Helen Zeng8f925502012-03-05 16:50:17 -0800328 case SLIMBUS_4_RX:
329 case SLIMBUS_4_TX:
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800330 ret_size = SIZEOF_CFG_CMD(afe_port_slimbus_sch_cfg);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700331 break;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530332 case RT_PROXY_PORT_001_RX:
333 case RT_PROXY_PORT_001_TX:
334 ret_size = SIZEOF_CFG_CMD(afe_port_rtproxy_cfg);
335 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700336 case PCM_RX:
337 case PCM_TX:
Shiv Maliyappanahallia416ee22012-06-01 16:02:35 -0700338 case SECONDARY_PCM_RX:
339 case SECONDARY_PCM_TX:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700340 default:
341 ret_size = SIZEOF_CFG_CMD(afe_port_pcm_cfg);
342 break;
343 }
344 return ret_size;
345}
346
Jay Wang6a305432011-08-05 16:01:54 -0700347int afe_q6_interface_prepare(void)
348{
349 int ret = 0;
350
351 pr_debug("%s:", __func__);
352
353 if (this_afe.apr == NULL) {
354 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
355 0xFFFFFFFF, &this_afe);
356 pr_debug("%s: Register AFE\n", __func__);
357 if (this_afe.apr == NULL) {
358 pr_err("%s: Unable to register AFE\n", __func__);
359 ret = -ENODEV;
360 }
361 }
362 return ret;
363}
364
Ben Rombergerb7603232011-11-23 17:16:27 -0800365static void afe_send_cal_block(int32_t path, u16 port_id)
366{
367 int result = 0;
368 struct acdb_cal_block cal_block;
369 struct afe_port_cmd_set_param_no_payload afe_cal;
370 pr_debug("%s: path %d\n", __func__, path);
371
372 get_afe_cal(path, &cal_block);
373 if (cal_block.cal_size <= 0) {
374 pr_debug("%s: No AFE cal to send!\n", __func__);
375 goto done;
376 }
377
Ben Romberger9e792562012-02-24 12:29:01 -0800378 if ((afe_cal_addr[path].cal_paddr != cal_block.cal_paddr) ||
379 (cal_block.cal_size > afe_cal_addr[path].cal_size)) {
380 if (afe_cal_addr[path].cal_paddr != 0)
Patrick Laibf978952012-06-29 09:20:42 -0700381 afe_cmd_memory_unmap(
Ben Romberger9e792562012-02-24 12:29:01 -0800382 afe_cal_addr[path].cal_paddr);
383
Patrick Laibf978952012-06-29 09:20:42 -0700384 afe_cmd_memory_map(cal_block.cal_paddr, cal_block.cal_size);
Ben Romberger9e792562012-02-24 12:29:01 -0800385 afe_cal_addr[path].cal_paddr = cal_block.cal_paddr;
386 afe_cal_addr[path].cal_size = cal_block.cal_size;
Ben Rombergerb7603232011-11-23 17:16:27 -0800387 }
388
389 afe_cal.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
390 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
391 afe_cal.hdr.pkt_size = sizeof(afe_cal);
392 afe_cal.hdr.src_port = 0;
393 afe_cal.hdr.dest_port = 0;
394 afe_cal.hdr.token = 0;
395 afe_cal.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
396 afe_cal.port_id = port_id;
397 afe_cal.payload_size = cal_block.cal_size;
398 afe_cal.payload_address = cal_block.cal_paddr;
399
400 pr_debug("%s: AFE cal sent for device port = %d, path = %d, "
401 "cal size = %d, cal addr = 0x%x\n", __func__,
402 port_id, path, cal_block.cal_size, cal_block.cal_paddr);
403
Patrick Laibf978952012-06-29 09:20:42 -0700404 atomic_set(&this_afe.state, 1);
Ben Rombergerb7603232011-11-23 17:16:27 -0800405 result = apr_send_pkt(this_afe.apr, (uint32_t *) &afe_cal);
406 if (result < 0) {
407 pr_err("%s: AFE cal for port %d failed\n",
408 __func__, port_id);
409 }
410
Patrick Laibf978952012-06-29 09:20:42 -0700411 result = wait_event_timeout(this_afe.wait,
412 (atomic_read(&this_afe.state) == 0),
413 msecs_to_jiffies(TIMEOUT_MS));
414 if (!result) {
415 pr_err("%s: wait_event timeout SET AFE CAL\n", __func__);
416 goto done;
417 }
418
Ben Rombergerb7603232011-11-23 17:16:27 -0800419 pr_debug("%s: AFE cal sent for path %d device!\n", __func__, path);
420done:
421 return;
422}
423
424void afe_send_cal(u16 port_id)
425{
426 pr_debug("%s\n", __func__);
427
428 if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX)
429 afe_send_cal_block(TX_CAL, port_id);
430 else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX)
431 afe_send_cal_block(RX_CAL, port_id);
432}
433
Patrick Laibf978952012-06-29 09:20:42 -0700434/* This function sends multi-channel HDMI configuration command and AFE
435 * calibration which is only supported by QDSP6 on 8960 and onward.
436 */
437int afe_port_start(u16 port_id, union afe_port_config *afe_config,
438 u32 rate)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700439{
440 struct afe_port_start_command start;
441 struct afe_audioif_config_command config;
442 int ret;
443
444 if (!afe_config) {
445 pr_err("%s: Error, no configuration data\n", __func__);
446 ret = -EINVAL;
447 return ret;
448 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -0800449 pr_debug("%s: %d %d\n", __func__, port_id, rate);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700450
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530451 if ((port_id == RT_PROXY_DAI_001_RX) ||
Satya Krishna Pindiprolie8b84552013-01-24 09:46:10 +0530452 (port_id == RT_PROXY_DAI_002_TX)) {
453 pr_debug("%s: before incrementing pcm_afe_instance %d"\
454 "port_id %d\n", __func__,
455 pcm_afe_instance[port_id & 0x1], port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530456 port_id = VIRTUAL_ID_TO_PORTID(port_id);
Satya Krishna Pindiprolie8b84552013-01-24 09:46:10 +0530457 pcm_afe_instance[port_id & 0x1]++;
458 return 0;
459 }
460 if ((port_id == RT_PROXY_DAI_002_RX) ||
461 (port_id == RT_PROXY_DAI_001_TX)) {
462 pr_debug("%s: before incrementing proxy_afe_instance %d"\
463 "port_id %d\n", __func__,
464 proxy_afe_instance[port_id & 0x1], port_id);
465 port_id = VIRTUAL_ID_TO_PORTID(port_id);
466 proxy_afe_instance[port_id & 0x1]++;
467 }
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530468
Patrick Laibf978952012-06-29 09:20:42 -0700469 ret = afe_q6_interface_prepare();
470 if (IS_ERR_VALUE(ret))
Jay Wang6a305432011-08-05 16:01:54 -0700471 return ret;
Kiran Kandi5e809b02012-01-31 00:24:33 -0800472
473 if (port_id == HDMI_RX) {
474 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700475 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
Kiran Kandi5e809b02012-01-31 00:24:33 -0800476 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
477 config.hdr.src_port = 0;
478 config.hdr.dest_port = 0;
479 config.hdr.token = 0;
480 config.hdr.opcode = AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG;
481 } else {
482
483 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
484 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
485 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
486 config.hdr.src_port = 0;
487 config.hdr.dest_port = 0;
488 config.hdr.token = 0;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800489 switch (port_id) {
490 case SLIMBUS_0_RX:
491 case SLIMBUS_0_TX:
492 case SLIMBUS_1_RX:
493 case SLIMBUS_1_TX:
494 case SLIMBUS_2_RX:
495 case SLIMBUS_2_TX:
496 case SLIMBUS_3_RX:
497 case SLIMBUS_3_TX:
498 case SLIMBUS_4_RX:
499 case SLIMBUS_4_TX:
500 config.hdr.opcode = AFE_PORT_AUDIO_SLIM_SCH_CONFIG;
501 break;
Kuirong Wanga36f2882012-04-02 19:45:26 -0700502 case MI2S_TX:
503 case MI2S_RX:
504 case SECONDARY_I2S_RX:
505 case SECONDARY_I2S_TX:
506 case PRIMARY_I2S_RX:
507 case PRIMARY_I2S_TX:
508 /* AFE_PORT_CMD_I2S_CONFIG command is not supported
509 * in the LPASS EL 1.0. So we have to distiguish
510 * which AFE command, AFE_PORT_CMD_I2S_CONFIG or
511 * AFE_PORT_AUDIO_IF_CONFIG to use. If the format
512 * is L-PCM, the AFE_PORT_AUDIO_IF_CONFIG is used
513 * to make the backward compatible.
514 */
515 pr_debug("%s: afe_config->mi2s.format = %d\n", __func__,
516 afe_config->mi2s.format);
517 if (afe_config->mi2s.format == MSM_AFE_I2S_FORMAT_LPCM)
518 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
519 else
520 config.hdr.opcode = AFE_PORT_CMD_I2S_CONFIG;
521 break;
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800522 default:
523 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
524 break;
525 }
Kiran Kandi5e809b02012-01-31 00:24:33 -0800526 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700527
528 if (afe_validate_port(port_id) < 0) {
529
530 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
531 port_id);
532 ret = -EINVAL;
533 goto fail_cmd;
534 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700535 config.port_id = port_id;
536 config.port = *afe_config;
537
Patrick Laibf978952012-06-29 09:20:42 -0700538 atomic_set(&this_afe.state, 1);
539 atomic_set(&this_afe.status, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700540 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
541 if (ret < 0) {
542 pr_err("%s: AFE enable for port %d failed\n", __func__,
543 port_id);
544 ret = -EINVAL;
545 goto fail_cmd;
546 }
Ben Rombergerb7603232011-11-23 17:16:27 -0800547
Patrick Laibf978952012-06-29 09:20:42 -0700548 ret = wait_event_timeout(this_afe.wait,
549 (atomic_read(&this_afe.state) == 0),
550 msecs_to_jiffies(TIMEOUT_MS));
551
552 if (!ret) {
553 pr_err("%s: wait_event timeout IF CONFIG\n", __func__);
554 ret = -EINVAL;
555 goto fail_cmd;
556 }
557 if (atomic_read(&this_afe.status) != 0) {
558 pr_err("%s: config cmd failed\n", __func__);
559 ret = -EINVAL;
560 goto fail_cmd;
561 }
562
Ben Rombergerb7603232011-11-23 17:16:27 -0800563 /* send AFE cal */
564 afe_send_cal(port_id);
565
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700566 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
567 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
568 start.hdr.pkt_size = sizeof(start);
569 start.hdr.src_port = 0;
570 start.hdr.dest_port = 0;
571 start.hdr.token = 0;
572 start.hdr.opcode = AFE_PORT_CMD_START;
573 start.port_id = port_id;
574 start.gain = 0x2000;
575 start.sample_rate = rate;
576
Patrick Laibf978952012-06-29 09:20:42 -0700577 atomic_set(&this_afe.state, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700578 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
579
580 if (IS_ERR_VALUE(ret)) {
581 pr_err("%s: AFE enable for port %d failed\n", __func__,
582 port_id);
583 ret = -EINVAL;
584 goto fail_cmd;
585 }
586
Patrick Laibf978952012-06-29 09:20:42 -0700587 ret = wait_event_timeout(this_afe.wait,
588 (atomic_read(&this_afe.state) == 0),
589 msecs_to_jiffies(TIMEOUT_MS));
590 if (!ret) {
591 pr_err("%s: wait_event timeout PORT START\n", __func__);
592 ret = -EINVAL;
593 goto fail_cmd;
594 }
595
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700596 if (this_afe.task != current)
597 this_afe.task = current;
598
599 pr_debug("task_name = %s pid = %d\n",
600 this_afe.task->comm, this_afe.task->pid);
601 return 0;
602
603fail_cmd:
604 return ret;
605}
606
Patrick Laibf978952012-06-29 09:20:42 -0700607/* This function should be used by 8660 exclusively */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700608int afe_open(u16 port_id, union afe_port_config *afe_config, int rate)
609{
610 struct afe_port_start_command start;
611 struct afe_audioif_config_command config;
612 int ret = 0;
613
614 if (!afe_config) {
615 pr_err("%s: Error, no configuration data\n", __func__);
616 ret = -EINVAL;
617 return ret;
618 }
619
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -0800620 pr_debug("%s: %d %d\n", __func__, port_id, rate);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700621
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530622 if ((port_id == RT_PROXY_DAI_001_RX) ||
623 (port_id == RT_PROXY_DAI_002_TX))
Asish Bhattacharyad482c992012-07-31 20:58:18 +0530624 return 0;
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530625 if ((port_id == RT_PROXY_DAI_002_RX) ||
626 (port_id == RT_PROXY_DAI_001_TX))
627 port_id = VIRTUAL_ID_TO_PORTID(port_id);
628
Jay Wang6a305432011-08-05 16:01:54 -0700629 ret = afe_q6_interface_prepare();
630 if (ret != 0)
631 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700632
633 config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
634 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
635 config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
636 config.hdr.src_port = 0;
637 config.hdr.dest_port = 0;
638 config.hdr.token = 0;
Kuirong Wanga36f2882012-04-02 19:45:26 -0700639 switch (port_id) {
640 case SLIMBUS_0_RX:
641 case SLIMBUS_0_TX:
642 case SLIMBUS_1_RX:
643 case SLIMBUS_1_TX:
644 case SLIMBUS_2_RX:
645 case SLIMBUS_2_TX:
646 case SLIMBUS_3_RX:
647 case SLIMBUS_3_TX:
648 case SLIMBUS_4_RX:
649 case SLIMBUS_4_TX:
650 config.hdr.opcode = AFE_PORT_AUDIO_SLIM_SCH_CONFIG;
651 break;
652 case MI2S_TX:
653 case MI2S_RX:
654 case SECONDARY_I2S_RX:
655 case SECONDARY_I2S_TX:
656 case PRIMARY_I2S_RX:
657 case PRIMARY_I2S_TX:
658 /* AFE_PORT_CMD_I2S_CONFIG command is not supported
659 * in the LPASS EL 1.0. So we have to distiguish
660 * which AFE command, AFE_PORT_CMD_I2S_CONFIG or
661 * AFE_PORT_AUDIO_IF_CONFIG to use. If the format
662 * is L-PCM, the AFE_PORT_AUDIO_IF_CONFIG is used
663 * to make the backward compatible.
664 */
665 pr_debug("%s: afe_config->mi2s.format = %d\n", __func__,
666 afe_config->mi2s.format);
667 if (afe_config->mi2s.format == MSM_AFE_I2S_FORMAT_LPCM)
668 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
669 else
670 config.hdr.opcode = AFE_PORT_CMD_I2S_CONFIG;
671 break;
672 default:
673 config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
674 break;
675 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700676
677 if (afe_validate_port(port_id) < 0) {
678
679 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
680 port_id);
681 ret = -EINVAL;
682 goto fail_cmd;
683 }
684
685 config.port_id = port_id;
686 config.port = *afe_config;
687
688 atomic_set(&this_afe.state, 1);
689 atomic_set(&this_afe.status, 0);
690 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &config);
691 if (ret < 0) {
692 pr_err("%s: AFE enable for port %d failed\n", __func__,
693 port_id);
694 ret = -EINVAL;
695 goto fail_cmd;
696 }
697
698 ret = wait_event_timeout(this_afe.wait,
699 (atomic_read(&this_afe.state) == 0),
700 msecs_to_jiffies(TIMEOUT_MS));
701 if (!ret) {
702 pr_err("%s: wait_event timeout\n", __func__);
703 ret = -EINVAL;
704 goto fail_cmd;
705 }
706 if (atomic_read(&this_afe.status) != 0) {
707 pr_err("%s: config cmd failed\n", __func__);
708 ret = -EINVAL;
709 goto fail_cmd;
710 }
711 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
712 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
713 start.hdr.pkt_size = sizeof(start);
714 start.hdr.src_port = 0;
715 start.hdr.dest_port = 0;
716 start.hdr.token = 0;
717 start.hdr.opcode = AFE_PORT_CMD_START;
718 start.port_id = port_id;
719 start.gain = 0x2000;
720 start.sample_rate = rate;
721
722 atomic_set(&this_afe.state, 1);
723 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
724 if (ret < 0) {
725 pr_err("%s: AFE enable for port %d failed\n", __func__,
726 port_id);
727 ret = -EINVAL;
728 goto fail_cmd;
729 }
730 ret = wait_event_timeout(this_afe.wait,
731 (atomic_read(&this_afe.state) == 0),
732 msecs_to_jiffies(TIMEOUT_MS));
733 if (!ret) {
734 pr_err("%s: wait_event timeout\n", __func__);
735 ret = -EINVAL;
736 goto fail_cmd;
737 }
738
739 if (this_afe.task != current)
740 this_afe.task = current;
741
742 pr_debug("task_name = %s pid = %d\n",
743 this_afe.task->comm, this_afe.task->pid);
744 return 0;
745fail_cmd:
746 return ret;
747}
748
Neema Shetty74131ac2012-05-09 13:35:26 -0700749int afe_loopback(u16 enable, u16 dst_port, u16 src_port)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700750{
751 struct afe_loopback_command lb_cmd;
752 int ret = 0;
Jay Wang6a305432011-08-05 16:01:54 -0700753
754 ret = afe_q6_interface_prepare();
755 if (ret != 0)
756 return ret;
757
Neema Shetty74131ac2012-05-09 13:35:26 -0700758 if ((afe_get_port_type(dst_port) == MSM_AFE_PORT_TYPE_RX) &&
759 (afe_get_port_type(src_port) == MSM_AFE_PORT_TYPE_RX))
760 return afe_loopback_cfg(enable, dst_port, src_port,
761 LB_MODE_EC_REF_VOICE_AUDIO);
762
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700763 lb_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
764 APR_HDR_LEN(20), APR_PKT_VER);
765 lb_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
766 sizeof(lb_cmd) - APR_HDR_SIZE);
767 lb_cmd.hdr.src_port = 0;
768 lb_cmd.hdr.dest_port = 0;
769 lb_cmd.hdr.token = 0;
770 lb_cmd.hdr.opcode = AFE_PORT_CMD_LOOPBACK;
Neema Shetty74131ac2012-05-09 13:35:26 -0700771 lb_cmd.tx_port_id = src_port;
772 lb_cmd.rx_port_id = dst_port;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700773 lb_cmd.mode = 0xFFFF;
774 lb_cmd.enable = (enable ? 1 : 0);
775 atomic_set(&this_afe.state, 1);
776
777 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &lb_cmd);
778 if (ret < 0) {
779 pr_err("%s: AFE loopback failed\n", __func__);
780 ret = -EINVAL;
781 goto done;
782 }
783 ret = wait_event_timeout(this_afe.wait,
784 (atomic_read(&this_afe.state) == 0),
785 msecs_to_jiffies(TIMEOUT_MS));
786 if (!ret) {
787 pr_err("%s: wait_event timeout\n", __func__);
788 ret = -EINVAL;
789 }
790done:
791 return ret;
792}
793
Neema Shetty74131ac2012-05-09 13:35:26 -0700794int afe_loopback_cfg(u16 enable, u16 dst_port, u16 src_port, u16 mode)
795{
796 struct afe_port_cmd_set_param lp_cfg;
797 int ret = 0;
798
799 ret = afe_q6_interface_prepare();
800 if (ret != 0)
801 return ret;
802
803 pr_debug("%s: src_port %d, dst_port %d\n",
804 __func__, src_port, dst_port);
805
806 lp_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
807 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
808 lp_cfg.hdr.pkt_size = sizeof(lp_cfg);
809 lp_cfg.hdr.src_port = 0;
810 lp_cfg.hdr.dest_port = 0;
811 lp_cfg.hdr.token = 0;
812 lp_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
813
814 lp_cfg.port_id = src_port;
Patrick Lai48da1492012-07-04 20:48:24 -0700815 lp_cfg.payload_size = sizeof(struct afe_param_payload_base) +
816 sizeof(struct afe_param_loopback_cfg);
Neema Shetty74131ac2012-05-09 13:35:26 -0700817 lp_cfg.payload_address = 0;
818
Patrick Lai48da1492012-07-04 20:48:24 -0700819 lp_cfg.payload.base.module_id = AFE_MODULE_LOOPBACK;
820 lp_cfg.payload.base.param_id = AFE_PARAM_ID_LOOPBACK_CONFIG;
821 lp_cfg.payload.base.param_size = sizeof(struct afe_param_loopback_cfg);
822 lp_cfg.payload.base.reserved = 0;
Neema Shetty74131ac2012-05-09 13:35:26 -0700823
824 lp_cfg.payload.param.loopback_cfg.loopback_cfg_minor_version =
825 AFE_API_VERSION_LOOPBACK_CONFIG;
826 lp_cfg.payload.param.loopback_cfg.dst_port_id = dst_port;
827 lp_cfg.payload.param.loopback_cfg.routing_mode = mode;
828 lp_cfg.payload.param.loopback_cfg.enable = enable;
829 lp_cfg.payload.param.loopback_cfg.reserved = 0;
830
831 atomic_set(&this_afe.state, 1);
832 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &lp_cfg);
833 if (ret < 0) {
834 pr_err("%s: AFE loopback config failed for src_port %d, dst_port %d\n",
835 __func__, src_port, dst_port);
836 ret = -EINVAL;
837 goto fail_cmd;
838 }
839
840 ret = wait_event_timeout(this_afe.wait,
841 (atomic_read(&this_afe.state) == 0),
842 msecs_to_jiffies(TIMEOUT_MS));
843 if (ret < 0) {
844 pr_err("%s: wait_event timeout\n", __func__);
845 ret = -EINVAL;
846 goto fail_cmd;
847 }
848 return 0;
849fail_cmd:
850 return ret;
851}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700852
853int afe_loopback_gain(u16 port_id, u16 volume)
854{
855 struct afe_port_cmd_set_param set_param;
856 int ret = 0;
857
858 if (this_afe.apr == NULL) {
Jayasena Sangaraboina82435032011-07-26 15:23:00 -0700859 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
860 0xFFFFFFFF, &this_afe);
861 pr_debug("%s: Register AFE\n", __func__);
862 if (this_afe.apr == NULL) {
863 pr_err("%s: Unable to register AFE\n", __func__);
864 ret = -ENODEV;
865 return ret;
866 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700867 }
868
869 if (afe_validate_port(port_id) < 0) {
870
871 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
872 port_id);
873 ret = -EINVAL;
874 goto fail_cmd;
875 }
876
877 /* RX ports numbers are even .TX ports numbers are odd. */
878 if (port_id % 2 == 0) {
879 pr_err("%s: Failed : afe loopback gain only for TX ports."
880 " port_id %d\n", __func__, port_id);
881 ret = -EINVAL;
882 goto fail_cmd;
883 }
884
885 pr_debug("%s: %d %hX\n", __func__, port_id, volume);
886
887 set_param.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
888 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
889 set_param.hdr.pkt_size = sizeof(set_param);
890 set_param.hdr.src_port = 0;
891 set_param.hdr.dest_port = 0;
892 set_param.hdr.token = 0;
893 set_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
894
895 set_param.port_id = port_id;
Patrick Lai48da1492012-07-04 20:48:24 -0700896 set_param.payload_size = sizeof(struct afe_param_payload_base) +
897 sizeof(struct afe_param_loopback_gain);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700898 set_param.payload_address = 0;
899
Patrick Lai48da1492012-07-04 20:48:24 -0700900 set_param.payload.base.module_id = AFE_MODULE_ID_PORT_INFO;
901 set_param.payload.base.param_id = AFE_PARAM_ID_LOOPBACK_GAIN;
902 set_param.payload.base.param_size =
903 sizeof(struct afe_param_loopback_gain);
904 set_param.payload.base.reserved = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700905
906 set_param.payload.param.loopback_gain.gain = volume;
907 set_param.payload.param.loopback_gain.reserved = 0;
908
909 atomic_set(&this_afe.state, 1);
910 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_param);
911 if (ret < 0) {
912 pr_err("%s: AFE param set failed for port %d\n",
913 __func__, port_id);
914 ret = -EINVAL;
915 goto fail_cmd;
916 }
917
918 ret = wait_event_timeout(this_afe.wait,
919 (atomic_read(&this_afe.state) == 0),
920 msecs_to_jiffies(TIMEOUT_MS));
921 if (ret < 0) {
922 pr_err("%s: wait_event timeout\n", __func__);
923 ret = -EINVAL;
924 goto fail_cmd;
925 }
926 return 0;
927fail_cmd:
928 return ret;
929}
930
Laxminath Kasam885f5102011-07-14 10:20:21 +0530931int afe_apply_gain(u16 port_id, u16 gain)
932{
933 struct afe_port_gain_command set_gain;
934 int ret = 0;
935
936 if (this_afe.apr == NULL) {
937 pr_err("%s: AFE is not opened\n", __func__);
938 ret = -EPERM;
939 goto fail_cmd;
940 }
941
942 if (afe_validate_port(port_id) < 0) {
943 pr_err("%s: Failed : Invalid Port id = %d\n", __func__,
944 port_id);
945 ret = -EINVAL;
946 goto fail_cmd;
947 }
948
949 /* RX ports numbers are even .TX ports numbers are odd. */
950 if (port_id % 2 == 0) {
951 pr_err("%s: Failed : afe apply gain only for TX ports."
952 " port_id %d\n", __func__, port_id);
953 ret = -EINVAL;
954 goto fail_cmd;
955 }
956
957 pr_debug("%s: %d %hX\n", __func__, port_id, gain);
958
959 set_gain.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
960 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
961 set_gain.hdr.pkt_size = sizeof(set_gain);
962 set_gain.hdr.src_port = 0;
963 set_gain.hdr.dest_port = 0;
964 set_gain.hdr.token = 0;
965 set_gain.hdr.opcode = AFE_PORT_CMD_APPLY_GAIN;
966
967 set_gain.port_id = port_id;
968 set_gain.gain = gain;
969
970 atomic_set(&this_afe.state, 1);
971 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &set_gain);
972 if (ret < 0) {
973 pr_err("%s: AFE Gain set failed for port %d\n",
974 __func__, port_id);
975 ret = -EINVAL;
976 goto fail_cmd;
977 }
978
979 ret = wait_event_timeout(this_afe.wait,
980 (atomic_read(&this_afe.state) == 0),
981 msecs_to_jiffies(TIMEOUT_MS));
982 if (ret < 0) {
983 pr_err("%s: wait_event timeout\n", __func__);
984 ret = -EINVAL;
985 goto fail_cmd;
986 }
987 return 0;
988fail_cmd:
989 return ret;
990}
Helen Zeng0705a5f2011-10-14 15:29:52 -0700991
992int afe_pseudo_port_start_nowait(u16 port_id)
993{
994 int ret = 0;
995 struct afe_pseudoport_start_command start;
996
997 pr_debug("%s: port_id=%d\n", __func__, port_id);
998 if (this_afe.apr == NULL) {
999 pr_err("%s: AFE APR is not registered\n", __func__);
1000 return -ENODEV;
1001 }
1002
1003
1004 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1005 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1006 start.hdr.pkt_size = sizeof(start);
1007 start.hdr.src_port = 0;
1008 start.hdr.dest_port = 0;
1009 start.hdr.token = 0;
1010 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
1011 start.port_id = port_id;
1012 start.timing = 1;
1013
1014 atomic_set(&this_afe.state, 1);
1015 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
1016 if (ret < 0) {
1017 pr_err("%s: AFE enable for port %d failed %d\n",
1018 __func__, port_id, ret);
1019 return -EINVAL;
1020 }
1021 return 0;
1022}
1023
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001024int afe_start_pseudo_port(u16 port_id)
1025{
1026 int ret = 0;
1027 struct afe_pseudoport_start_command start;
1028
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001029 pr_debug("%s: port_id=%d\n", __func__, port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001030
Jay Wang6a305432011-08-05 16:01:54 -07001031 ret = afe_q6_interface_prepare();
1032 if (ret != 0)
1033 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001034
1035 start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1036 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1037 start.hdr.pkt_size = sizeof(start);
1038 start.hdr.src_port = 0;
1039 start.hdr.dest_port = 0;
1040 start.hdr.token = 0;
1041 start.hdr.opcode = AFE_PSEUDOPORT_CMD_START;
1042 start.port_id = port_id;
1043 start.timing = 1;
1044
1045 atomic_set(&this_afe.state, 1);
1046 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
1047 if (ret < 0) {
1048 pr_err("%s: AFE enable for port %d failed %d\n",
1049 __func__, port_id, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001050 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001051 }
1052
1053 ret = wait_event_timeout(this_afe.wait,
1054 (atomic_read(&this_afe.state) == 0),
1055 msecs_to_jiffies(TIMEOUT_MS));
1056 if (!ret) {
1057 pr_err("%s: wait_event timeout\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001058 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001059 }
1060
1061 return 0;
1062}
1063
Helen Zeng0705a5f2011-10-14 15:29:52 -07001064int afe_pseudo_port_stop_nowait(u16 port_id)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001065{
1066 int ret = 0;
1067 struct afe_pseudoport_stop_command stop;
1068
Helen Zeng0705a5f2011-10-14 15:29:52 -07001069 pr_debug("%s: port_id=%d\n", __func__, port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001070
1071 if (this_afe.apr == NULL) {
1072 pr_err("%s: AFE is already closed\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001073 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001074 }
1075
1076 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1077 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1078 stop.hdr.pkt_size = sizeof(stop);
1079 stop.hdr.src_port = 0;
1080 stop.hdr.dest_port = 0;
1081 stop.hdr.token = 0;
1082 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
1083 stop.port_id = port_id;
1084 stop.reserved = 0;
1085
1086 atomic_set(&this_afe.state, 1);
1087 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1088 if (ret < 0) {
1089 pr_err("%s: AFE close failed %d\n", __func__, ret);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001090 return -EINVAL;
1091 }
1092
1093 return 0;
1094
1095}
1096
1097int afe_stop_pseudo_port(u16 port_id)
1098{
1099 int ret = 0;
1100 struct afe_pseudoport_stop_command stop;
1101
Bharath Ramachandramurthy9c79f132011-11-28 11:18:57 -08001102 pr_debug("%s: port_id=%d\n", __func__, port_id);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001103
1104 if (this_afe.apr == NULL) {
1105 pr_err("%s: AFE is already closed\n", __func__);
1106 return -EINVAL;
1107 }
1108
1109 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1110 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1111 stop.hdr.pkt_size = sizeof(stop);
1112 stop.hdr.src_port = 0;
1113 stop.hdr.dest_port = 0;
1114 stop.hdr.token = 0;
1115 stop.hdr.opcode = AFE_PSEUDOPORT_CMD_STOP;
1116 stop.port_id = port_id;
1117 stop.reserved = 0;
1118
1119 atomic_set(&this_afe.state, 1);
1120 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1121 if (ret < 0) {
1122 pr_err("%s: AFE close failed %d\n", __func__, ret);
1123 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001124 }
1125
1126 ret = wait_event_timeout(this_afe.wait,
1127 (atomic_read(&this_afe.state) == 0),
1128 msecs_to_jiffies(TIMEOUT_MS));
1129 if (!ret) {
1130 pr_err("%s: wait_event timeout\n", __func__);
Helen Zeng0705a5f2011-10-14 15:29:52 -07001131 return -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001132 }
1133
1134 return 0;
1135}
1136
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301137int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz)
1138{
1139 int ret = 0;
1140 struct afe_cmd_memory_map mregion;
1141
1142 pr_debug("%s:\n", __func__);
1143
1144 if (this_afe.apr == NULL) {
1145 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1146 0xFFFFFFFF, &this_afe);
1147 pr_debug("%s: Register AFE\n", __func__);
1148 if (this_afe.apr == NULL) {
1149 pr_err("%s: Unable to register AFE\n", __func__);
1150 ret = -ENODEV;
1151 return ret;
1152 }
1153 }
1154
1155 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1156 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1157 mregion.hdr.pkt_size = sizeof(mregion);
1158 mregion.hdr.src_port = 0;
1159 mregion.hdr.dest_port = 0;
1160 mregion.hdr.token = 0;
1161 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
1162 mregion.phy_addr = dma_addr_p;
1163 mregion.mem_sz = dma_buf_sz;
1164 mregion.mem_id = 0;
1165 mregion.rsvd = 0;
1166
1167 atomic_set(&this_afe.state, 1);
1168 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1169 if (ret < 0) {
1170 pr_err("%s: AFE memory map cmd failed %d\n",
1171 __func__, ret);
1172 ret = -EINVAL;
1173 return ret;
1174 }
1175
1176 ret = wait_event_timeout(this_afe.wait,
1177 (atomic_read(&this_afe.state) == 0),
1178 msecs_to_jiffies(TIMEOUT_MS));
1179 if (!ret) {
1180 pr_err("%s: wait_event timeout\n", __func__);
1181 ret = -EINVAL;
1182 return ret;
1183 }
1184
1185 return 0;
1186}
1187
Ben Rombergerb7603232011-11-23 17:16:27 -08001188int afe_cmd_memory_map_nowait(u32 dma_addr_p, u32 dma_buf_sz)
1189{
1190 int ret = 0;
1191 struct afe_cmd_memory_map mregion;
1192
1193 pr_debug("%s:\n", __func__);
1194
1195 if (this_afe.apr == NULL) {
1196 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1197 0xFFFFFFFF, &this_afe);
1198 pr_debug("%s: Register AFE\n", __func__);
1199 if (this_afe.apr == NULL) {
1200 pr_err("%s: Unable to register AFE\n", __func__);
1201 ret = -ENODEV;
1202 return ret;
1203 }
1204 }
1205
1206 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1207 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1208 mregion.hdr.pkt_size = sizeof(mregion);
1209 mregion.hdr.src_port = 0;
1210 mregion.hdr.dest_port = 0;
1211 mregion.hdr.token = 0;
1212 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
1213 mregion.phy_addr = dma_addr_p;
1214 mregion.mem_sz = dma_buf_sz;
1215 mregion.mem_id = 0;
1216 mregion.rsvd = 0;
1217
1218 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1219 if (ret < 0) {
1220 pr_err("%s: AFE memory map cmd failed %d\n",
1221 __func__, ret);
1222 ret = -EINVAL;
1223 }
1224 return 0;
1225}
1226
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301227int afe_cmd_memory_unmap(u32 dma_addr_p)
1228{
1229 int ret = 0;
1230 struct afe_cmd_memory_unmap mregion;
1231
1232 pr_debug("%s:\n", __func__);
1233
1234 if (this_afe.apr == NULL) {
1235 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1236 0xFFFFFFFF, &this_afe);
1237 pr_debug("%s: Register AFE\n", __func__);
1238 if (this_afe.apr == NULL) {
1239 pr_err("%s: Unable to register AFE\n", __func__);
1240 ret = -ENODEV;
1241 return ret;
1242 }
1243 }
1244
1245 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1246 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1247 mregion.hdr.pkt_size = sizeof(mregion);
1248 mregion.hdr.src_port = 0;
1249 mregion.hdr.dest_port = 0;
1250 mregion.hdr.token = 0;
1251 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
1252 mregion.phy_addr = dma_addr_p;
1253
1254 atomic_set(&this_afe.state, 1);
1255 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1256 if (ret < 0) {
Ben Rombergerb7603232011-11-23 17:16:27 -08001257 pr_err("%s: AFE memory unmap cmd failed %d\n",
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301258 __func__, ret);
1259 ret = -EINVAL;
1260 return ret;
1261 }
1262
1263 ret = wait_event_timeout(this_afe.wait,
1264 (atomic_read(&this_afe.state) == 0),
1265 msecs_to_jiffies(TIMEOUT_MS));
1266 if (!ret) {
1267 pr_err("%s: wait_event timeout\n", __func__);
1268 ret = -EINVAL;
1269 return ret;
1270 }
Ben Rombergerb7603232011-11-23 17:16:27 -08001271 return 0;
1272}
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301273
Ben Rombergerb7603232011-11-23 17:16:27 -08001274int afe_cmd_memory_unmap_nowait(u32 dma_addr_p)
1275{
1276 int ret = 0;
1277 struct afe_cmd_memory_unmap mregion;
1278
1279 pr_debug("%s:\n", __func__);
1280
1281 if (this_afe.apr == NULL) {
1282 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1283 0xFFFFFFFF, &this_afe);
1284 pr_debug("%s: Register AFE\n", __func__);
1285 if (this_afe.apr == NULL) {
1286 pr_err("%s: Unable to register AFE\n", __func__);
1287 ret = -ENODEV;
1288 return ret;
1289 }
1290 }
1291
1292 mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1293 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1294 mregion.hdr.pkt_size = sizeof(mregion);
1295 mregion.hdr.src_port = 0;
1296 mregion.hdr.dest_port = 0;
1297 mregion.hdr.token = 0;
1298 mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
1299 mregion.phy_addr = dma_addr_p;
1300
1301 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
1302 if (ret < 0) {
1303 pr_err("%s: AFE memory unmap cmd failed %d\n",
1304 __func__, ret);
1305 ret = -EINVAL;
1306 }
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301307 return 0;
1308}
1309
1310int afe_register_get_events(u16 port_id,
1311 void (*cb) (uint32_t opcode,
1312 uint32_t token, uint32_t *payload, void *priv),
1313 void *private_data)
1314{
1315 int ret = 0;
1316 struct afe_cmd_reg_rtport rtproxy;
1317
1318 pr_debug("%s:\n", __func__);
1319
1320 if (this_afe.apr == NULL) {
1321 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1322 0xFFFFFFFF, &this_afe);
1323 pr_debug("%s: Register AFE\n", __func__);
1324 if (this_afe.apr == NULL) {
1325 pr_err("%s: Unable to register AFE\n", __func__);
1326 ret = -ENODEV;
1327 return ret;
1328 }
1329 }
1330 if ((port_id == RT_PROXY_DAI_002_RX) ||
1331 (port_id == RT_PROXY_DAI_001_TX))
1332 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1333 else
1334 return -EINVAL;
1335
1336 if (port_id == RT_PROXY_PORT_001_TX) {
1337 this_afe.tx_cb = cb;
1338 this_afe.tx_private_data = private_data;
1339 } else if (port_id == RT_PROXY_PORT_001_RX) {
1340 this_afe.rx_cb = cb;
1341 this_afe.rx_private_data = private_data;
1342 }
1343
1344 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1345 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1346 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1347 rtproxy.hdr.src_port = 1;
1348 rtproxy.hdr.dest_port = 1;
1349 rtproxy.hdr.token = 0;
1350 rtproxy.hdr.opcode = AFE_SERVICE_CMD_REG_RTPORT;
1351 rtproxy.port_id = port_id;
1352 rtproxy.rsvd = 0;
1353
1354 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1355 if (ret < 0) {
1356 pr_err("%s: AFE reg. rtproxy_event failed %d\n",
1357 __func__, ret);
1358 ret = -EINVAL;
1359 return ret;
1360 }
1361 return 0;
1362}
1363
1364int afe_unregister_get_events(u16 port_id)
1365{
1366 int ret = 0;
1367 struct afe_cmd_unreg_rtport rtproxy;
1368
1369 pr_debug("%s:\n", __func__);
1370
1371 if (this_afe.apr == NULL) {
1372 this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
1373 0xFFFFFFFF, &this_afe);
1374 pr_debug("%s: Register AFE\n", __func__);
1375 if (this_afe.apr == NULL) {
1376 pr_err("%s: Unable to register AFE\n", __func__);
1377 ret = -ENODEV;
1378 return ret;
1379 }
1380 }
1381 if ((port_id == RT_PROXY_DAI_002_RX) ||
1382 (port_id == RT_PROXY_DAI_001_TX))
1383 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1384 else
1385 return -EINVAL;
1386
1387 rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1388 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1389 rtproxy.hdr.pkt_size = sizeof(rtproxy);
1390 rtproxy.hdr.src_port = 0;
1391 rtproxy.hdr.dest_port = 0;
1392 rtproxy.hdr.token = 0;
1393 rtproxy.hdr.opcode = AFE_SERVICE_CMD_UNREG_RTPORT;
1394 rtproxy.port_id = port_id;
1395 rtproxy.rsvd = 0;
1396
1397 if (port_id == RT_PROXY_PORT_001_TX) {
1398 this_afe.tx_cb = NULL;
1399 this_afe.tx_private_data = NULL;
1400 } else if (port_id == RT_PROXY_PORT_001_RX) {
1401 this_afe.rx_cb = NULL;
1402 this_afe.rx_private_data = NULL;
1403 }
1404
1405 atomic_set(&this_afe.state, 1);
1406 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &rtproxy);
1407 if (ret < 0) {
1408 pr_err("%s: AFE enable Unreg. rtproxy_event failed %d\n",
1409 __func__, ret);
1410 ret = -EINVAL;
1411 return ret;
1412 }
1413
1414 ret = wait_event_timeout(this_afe.wait,
1415 (atomic_read(&this_afe.state) == 0),
1416 msecs_to_jiffies(TIMEOUT_MS));
1417 if (!ret) {
1418 pr_err("%s: wait_event timeout\n", __func__);
1419 ret = -EINVAL;
1420 return ret;
1421 }
1422 return 0;
1423}
1424
1425int afe_rt_proxy_port_write(u32 buf_addr_p, int bytes)
1426{
1427 int ret = 0;
1428 struct afe_cmd_rtport_wr afecmd_wr;
1429
1430 if (this_afe.apr == NULL) {
1431 pr_err("%s:register to AFE is not done\n", __func__);
1432 ret = -ENODEV;
1433 return ret;
1434 }
1435 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1436 buf_addr_p, bytes);
1437
1438 afecmd_wr.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1439 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1440 afecmd_wr.hdr.pkt_size = sizeof(afecmd_wr);
1441 afecmd_wr.hdr.src_port = 0;
1442 afecmd_wr.hdr.dest_port = 0;
1443 afecmd_wr.hdr.token = 0;
1444 afecmd_wr.hdr.opcode = AFE_SERVICE_CMD_RTPORT_WR;
1445 afecmd_wr.buf_addr = (uint32_t)buf_addr_p;
1446 afecmd_wr.port_id = RT_PROXY_PORT_001_TX;
1447 afecmd_wr.bytes_avail = bytes;
1448 afecmd_wr.rsvd = 0;
1449
1450 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_wr);
1451 if (ret < 0) {
1452 pr_err("%s: AFE rtproxy write to port 0x%x failed %d\n",
1453 __func__, afecmd_wr.port_id, ret);
1454 ret = -EINVAL;
1455 return ret;
1456 }
1457 return 0;
1458
1459}
1460
1461int afe_rt_proxy_port_read(u32 buf_addr_p, int bytes)
1462{
1463 int ret = 0;
1464 struct afe_cmd_rtport_rd afecmd_rd;
1465
1466 if (this_afe.apr == NULL) {
1467 pr_err("%s: register to AFE is not done\n", __func__);
1468 ret = -ENODEV;
1469 return ret;
1470 }
1471 pr_debug("%s: buf_addr_p = 0x%08x bytes = %d\n", __func__,
1472 buf_addr_p, bytes);
1473
1474 afecmd_rd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1475 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1476 afecmd_rd.hdr.pkt_size = sizeof(afecmd_rd);
1477 afecmd_rd.hdr.src_port = 0;
1478 afecmd_rd.hdr.dest_port = 0;
1479 afecmd_rd.hdr.token = 0;
1480 afecmd_rd.hdr.opcode = AFE_SERVICE_CMD_RTPORT_RD;
1481 afecmd_rd.buf_addr = (uint32_t)buf_addr_p;
1482 afecmd_rd.port_id = RT_PROXY_PORT_001_RX;
1483 afecmd_rd.bytes_avail = bytes;
1484 afecmd_rd.rsvd = 0;
1485
1486 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_rd);
1487 if (ret < 0) {
1488 pr_err("%s: AFE rtproxy read cmd to port 0x%x failed %d\n",
1489 __func__, afecmd_rd.port_id, ret);
1490 ret = -EINVAL;
1491 return ret;
1492 }
1493 return 0;
1494}
1495
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001496#ifdef CONFIG_DEBUG_FS
1497static struct dentry *debugfs_afelb;
1498static struct dentry *debugfs_afelb_gain;
1499
1500static int afe_debug_open(struct inode *inode, struct file *file)
1501{
1502 file->private_data = inode->i_private;
1503 pr_info("debug intf %s\n", (char *) file->private_data);
1504 return 0;
1505}
1506
1507static int afe_get_parameters(char *buf, long int *param1, int num_of_par)
1508{
1509 char *token;
1510 int base, cnt;
1511
1512 token = strsep(&buf, " ");
1513
1514 for (cnt = 0; cnt < num_of_par; cnt++) {
1515 if (token != NULL) {
1516 if ((token[1] == 'x') || (token[1] == 'X'))
1517 base = 16;
1518 else
1519 base = 10;
1520
1521 if (strict_strtoul(token, base, &param1[cnt]) != 0)
1522 return -EINVAL;
1523
1524 token = strsep(&buf, " ");
1525 } else
1526 return -EINVAL;
1527 }
1528 return 0;
1529}
1530#define AFE_LOOPBACK_ON (1)
1531#define AFE_LOOPBACK_OFF (0)
1532static ssize_t afe_debug_write(struct file *filp,
1533 const char __user *ubuf, size_t cnt, loff_t *ppos)
1534{
1535 char *lb_str = filp->private_data;
1536 char lbuf[32];
1537 int rc;
1538 unsigned long param[5];
1539
1540 if (cnt > sizeof(lbuf) - 1)
1541 return -EINVAL;
1542
1543 rc = copy_from_user(lbuf, ubuf, cnt);
1544 if (rc)
1545 return -EFAULT;
1546
1547 lbuf[cnt] = '\0';
1548
1549 if (!strcmp(lb_str, "afe_loopback")) {
1550 rc = afe_get_parameters(lbuf, param, 3);
1551 if (!rc) {
1552 pr_info("%s %lu %lu %lu\n", lb_str, param[0], param[1],
1553 param[2]);
1554
1555 if ((param[0] != AFE_LOOPBACK_ON) && (param[0] !=
1556 AFE_LOOPBACK_OFF)) {
1557 pr_err("%s: Error, parameter 0 incorrect\n",
1558 __func__);
1559 rc = -EINVAL;
1560 goto afe_error;
1561 }
1562 if ((afe_validate_port(param[1]) < 0) ||
1563 (afe_validate_port(param[2])) < 0) {
1564 pr_err("%s: Error, invalid afe port\n",
1565 __func__);
1566 }
1567 if (this_afe.apr == NULL) {
1568 pr_err("%s: Error, AFE not opened\n", __func__);
1569 rc = -EINVAL;
1570 } else {
1571 rc = afe_loopback(param[0], param[1], param[2]);
1572 }
1573 } else {
1574 pr_err("%s: Error, invalid parameters\n", __func__);
1575 rc = -EINVAL;
1576 }
1577
1578 } else if (!strcmp(lb_str, "afe_loopback_gain")) {
1579 rc = afe_get_parameters(lbuf, param, 2);
1580 if (!rc) {
1581 pr_info("%s %lu %lu\n", lb_str, param[0], param[1]);
1582
1583 if (afe_validate_port(param[0]) < 0) {
1584 pr_err("%s: Error, invalid afe port\n",
1585 __func__);
1586 rc = -EINVAL;
1587 goto afe_error;
1588 }
1589
1590 if (param[1] < 0 || param[1] > 100) {
1591 pr_err("%s: Error, volume shoud be 0 to 100"
1592 " percentage param = %lu\n",
1593 __func__, param[1]);
1594 rc = -EINVAL;
1595 goto afe_error;
1596 }
1597
1598 param[1] = (Q6AFE_MAX_VOLUME * param[1]) / 100;
1599
1600 if (this_afe.apr == NULL) {
1601 pr_err("%s: Error, AFE not opened\n", __func__);
1602 rc = -EINVAL;
1603 } else {
1604 rc = afe_loopback_gain(param[0], param[1]);
1605 }
1606 } else {
1607 pr_err("%s: Error, invalid parameters\n", __func__);
1608 rc = -EINVAL;
1609 }
1610 }
1611
1612afe_error:
1613 if (rc == 0)
1614 rc = cnt;
1615 else
1616 pr_err("%s: rc = %d\n", __func__, rc);
1617
1618 return rc;
1619}
1620
1621static const struct file_operations afe_debug_fops = {
1622 .open = afe_debug_open,
1623 .write = afe_debug_write
1624};
1625#endif
1626int afe_sidetone(u16 tx_port_id, u16 rx_port_id, u16 enable, uint16_t gain)
1627{
1628 struct afe_port_sidetone_command cmd_sidetone;
1629 int ret = 0;
1630
1631 pr_info("%s: tx_port_id:%d rx_port_id:%d enable:%d gain:%d\n", __func__,
1632 tx_port_id, rx_port_id, enable, gain);
1633 cmd_sidetone.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1634 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1635 cmd_sidetone.hdr.pkt_size = sizeof(cmd_sidetone);
1636 cmd_sidetone.hdr.src_port = 0;
1637 cmd_sidetone.hdr.dest_port = 0;
1638 cmd_sidetone.hdr.token = 0;
1639 cmd_sidetone.hdr.opcode = AFE_PORT_CMD_SIDETONE_CTL;
1640 cmd_sidetone.tx_port_id = tx_port_id;
1641 cmd_sidetone.rx_port_id = rx_port_id;
1642 cmd_sidetone.gain = gain;
1643 cmd_sidetone.enable = enable;
1644
1645 atomic_set(&this_afe.state, 1);
1646 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &cmd_sidetone);
1647 if (ret < 0) {
1648 pr_err("%s: AFE sidetone failed for tx_port:%d rx_port:%d\n",
1649 __func__, tx_port_id, rx_port_id);
1650 ret = -EINVAL;
1651 goto fail_cmd;
1652 }
1653
1654 ret = wait_event_timeout(this_afe.wait,
1655 (atomic_read(&this_afe.state) == 0),
1656 msecs_to_jiffies(TIMEOUT_MS));
1657 if (ret < 0) {
1658 pr_err("%s: wait_event timeout\n", __func__);
1659 ret = -EINVAL;
1660 goto fail_cmd;
1661 }
1662 return 0;
1663fail_cmd:
1664 return ret;
1665}
1666
1667int afe_port_stop_nowait(int port_id)
1668{
1669 struct afe_port_stop_command stop;
1670 int ret = 0;
1671
1672 if (this_afe.apr == NULL) {
1673 pr_err("AFE is already closed\n");
1674 ret = -EINVAL;
1675 goto fail_cmd;
1676 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001677 pr_debug("%s: port_id=%d\n", __func__, port_id);
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301678 port_id = afe_convert_virtual_to_portid(port_id);
1679
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001680 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1681 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1682 stop.hdr.pkt_size = sizeof(stop);
1683 stop.hdr.src_port = 0;
1684 stop.hdr.dest_port = 0;
1685 stop.hdr.token = 0;
1686 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1687 stop.port_id = port_id;
1688 stop.reserved = 0;
1689
1690 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1691
1692 if (ret == -ENETRESET) {
1693 pr_info("%s: Need to reset, calling APR deregister", __func__);
1694 return apr_deregister(this_afe.apr);
1695 } else if (IS_ERR_VALUE(ret)) {
1696 pr_err("%s: AFE close failed\n", __func__);
1697 ret = -EINVAL;
1698 }
1699
1700fail_cmd:
1701 return ret;
1702
1703}
1704
1705int afe_close(int port_id)
1706{
1707 struct afe_port_stop_command stop;
1708 int ret = 0;
1709
1710 if (this_afe.apr == NULL) {
1711 pr_err("AFE is already closed\n");
1712 ret = -EINVAL;
1713 goto fail_cmd;
1714 }
Jeff Ohlstein293b91f2011-12-16 13:22:46 -08001715 pr_debug("%s: port_id=%d\n", __func__, port_id);
Satya Krishna Pindiprolie8b84552013-01-24 09:46:10 +05301716
1717 if ((port_id == RT_PROXY_DAI_001_RX) ||
1718 (port_id == RT_PROXY_DAI_002_TX)) {
1719 pr_debug("%s: before decrementing pcm_afe_instance %d\n",
1720 __func__, pcm_afe_instance[port_id & 0x1]);
1721 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1722 pcm_afe_instance[port_id & 0x1]--;
1723 if (!(pcm_afe_instance[port_id & 0x1] == 0 &&
1724 proxy_afe_instance[port_id & 0x1] == 0))
1725 return 0;
1726 }
1727
1728 if ((port_id == RT_PROXY_DAI_002_RX) ||
1729 (port_id == RT_PROXY_DAI_001_TX)) {
1730 pr_debug("%s: before decrementing proxy_afe_instance %d\n",
1731 __func__, proxy_afe_instance[port_id & 0x1]);
1732 port_id = VIRTUAL_ID_TO_PORTID(port_id);
1733 proxy_afe_instance[port_id & 0x1]--;
1734 if (!(pcm_afe_instance[port_id & 0x1] == 0 &&
1735 proxy_afe_instance[port_id & 0x1] == 0))
1736 return 0;
1737 }
1738
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301739 port_id = afe_convert_virtual_to_portid(port_id);
1740
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001741 stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1742 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1743 stop.hdr.pkt_size = sizeof(stop);
1744 stop.hdr.src_port = 0;
1745 stop.hdr.dest_port = 0;
1746 stop.hdr.token = 0;
1747 stop.hdr.opcode = AFE_PORT_CMD_STOP;
1748 stop.port_id = port_id;
1749 stop.reserved = 0;
1750
1751 atomic_set(&this_afe.state, 1);
1752 ret = apr_send_pkt(this_afe.apr, (uint32_t *) &stop);
1753
1754 if (ret == -ENETRESET) {
1755 pr_info("%s: Need to reset, calling APR deregister", __func__);
1756 return apr_deregister(this_afe.apr);
1757 }
1758
1759 if (ret < 0) {
1760 pr_err("%s: AFE close failed\n", __func__);
1761 ret = -EINVAL;
1762 goto fail_cmd;
1763 }
1764
1765 ret = wait_event_timeout(this_afe.wait,
1766 (atomic_read(&this_afe.state) == 0),
1767 msecs_to_jiffies(TIMEOUT_MS));
1768 if (!ret) {
1769 pr_err("%s: wait_event timeout\n", __func__);
1770 ret = -EINVAL;
1771 goto fail_cmd;
1772 }
1773fail_cmd:
1774 return ret;
1775}
1776
1777static int __init afe_init(void)
1778{
1779 init_waitqueue_head(&this_afe.wait);
1780 atomic_set(&this_afe.state, 0);
1781 atomic_set(&this_afe.status, 0);
1782 this_afe.apr = NULL;
1783#ifdef CONFIG_DEBUG_FS
1784 debugfs_afelb = debugfs_create_file("afe_loopback",
Glenn Kasten5dfda802012-10-04 16:40:27 -07001785 0220, NULL, (void *) "afe_loopback",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001786 &afe_debug_fops);
1787
1788 debugfs_afelb_gain = debugfs_create_file("afe_loopback_gain",
Glenn Kasten5dfda802012-10-04 16:40:27 -07001789 0220, NULL, (void *) "afe_loopback_gain",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001790 &afe_debug_fops);
1791
1792
1793#endif
1794 return 0;
1795}
1796
1797static void __exit afe_exit(void)
1798{
Ben Rombergerb7603232011-11-23 17:16:27 -08001799 int i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001800#ifdef CONFIG_DEBUG_FS
1801 if (debugfs_afelb)
1802 debugfs_remove(debugfs_afelb);
1803 if (debugfs_afelb_gain)
1804 debugfs_remove(debugfs_afelb_gain);
1805#endif
Ben Rombergerb7603232011-11-23 17:16:27 -08001806 for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
Ben Romberger9e792562012-02-24 12:29:01 -08001807 if (afe_cal_addr[i].cal_paddr != 0)
1808 afe_cmd_memory_unmap_nowait(
1809 afe_cal_addr[i].cal_paddr);
Ben Rombergerb7603232011-11-23 17:16:27 -08001810 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001811}
1812
1813device_initcall(afe_init);
1814__exitcall(afe_exit);