blob: fd95db0b948107a101ff2631ef398f7ad66f9a88 [file] [log] [blame]
Subhash Chandra Bose Naripeddye40a7cd2014-06-03 19:42:41 -07001/*
2 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 *
18 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
28 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#define LOG_TAG "hw_accelerator_effect"
32/*#define LOG_NDEBUG 0*/
33
34#include <cutils/list.h>
35#include <cutils/log.h>
36#include <fcntl.h>
37#include <tinyalsa/asoundlib.h>
38#include <sound/audio_effects.h>
39#include <audio_effects/effect_hwaccelerator.h>
40
41#include "effect_api.h"
42#include "hw_accelerator.h"
43
44
45/* hw_accelerator UUID: 7d1580bd-297f-4683-9239-e475b6d1d69f */
46const effect_descriptor_t hw_accelerator_descriptor = {
47 EFFECT_UIID_HWACCELERATOR__,
48 {0x7d1580bd, 0x297f, 0x4683, 0x9239, {0xe4, 0x75, 0xb6, 0xd1, 0xd6, 0x9f}}, // uuid
49 EFFECT_CONTROL_API_VERSION,
50 (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_DEVICE_IND),
51 0, /* TODO */
52 1,
53 "HwAccelerated Library",
54 "QTI",
55};
56
57int hw_accelerator_get_parameter(effect_context_t *context,
58 effect_param_t *p, uint32_t *size)
59{
60 hw_accelerator_context_t *hw_acc_ctxt = (hw_accelerator_context_t *)context;
61 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
62 int32_t *param_tmp = (int32_t *)p->data;
63 int32_t param = *param_tmp++;
64 void *value = p->data + voffset;
65 int i;
66
67 ALOGV("%s: ctxt %p, param %d", __func__, hw_acc_ctxt, param);
68
69 p->status = 0;
70
71 switch (param) {
72 case HW_ACCELERATOR_FD:
73 if (p->vsize < sizeof(int32_t))
74 p->status = -EINVAL;
75 p->vsize = sizeof(int32_t);
76 break;
77 default:
78 p->status = -EINVAL;
79 }
80
81 *size = sizeof(effect_param_t) + voffset + p->vsize;
82
83 if (p->status != 0)
84 return 0;
85
86 switch (param) {
87 case HW_ACCELERATOR_FD:
88 ALOGV("%s: HW_ACCELERATOR_FD", __func__);
89 *(int32_t *)value = hw_acc_ctxt->fd;
90 break;
91
92 default:
93 p->status = -EINVAL;
94 break;
95 }
96
97 return 0;
98}
99
100int hw_accelerator_set_parameter(effect_context_t *context, effect_param_t *p,
101 uint32_t size)
102{
103 hw_accelerator_context_t *hw_acc_ctxt = (hw_accelerator_context_t *)context;
104 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
105 void *value = p->data + voffset;
106 int32_t *param_tmp = (int32_t *)p->data;
107 int32_t param = *param_tmp++;
108
109 ALOGV("%s: ctxt %p, param %d", __func__, hw_acc_ctxt, param);
110
111 p->status = 0;
112
113 switch (param) {
Alexy Josephd464f3b2014-11-18 16:14:41 -0800114 case HW_ACCELERATOR_HPX_STATE: {
115 int hpxState = (uint32_t)(*(int32_t *)value);
116 if (hpxState)
117 hw_acc_hpx_send_params(hw_acc_ctxt->fd, OFFLOAD_SEND_HPX_STATE_ON);
118 else
119 hw_acc_hpx_send_params(hw_acc_ctxt->fd, OFFLOAD_SEND_HPX_STATE_OFF);
120 break;
121 }
Subhash Chandra Bose Naripeddye40a7cd2014-06-03 19:42:41 -0700122 default:
123 p->status = -EINVAL;
124 break;
125 }
126
127 return 0;
128}
129
130int hw_accelerator_set_device(effect_context_t *context, uint32_t device)
131{
132 hw_accelerator_context_t *hw_acc_ctxt = (hw_accelerator_context_t *)context;
133
134 ALOGV("%s: ctxt %p", __func__, hw_acc_ctxt);
135 hw_acc_ctxt->device = device;
136 return 0;
137}
138
139int hw_accelerator_init(effect_context_t *context)
140{
141 hw_accelerator_context_t *hw_acc_ctxt = (hw_accelerator_context_t *)context;
142
143 ALOGV("%s: ctxt %p", __func__, hw_acc_ctxt);
144 context->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
145 context->config.inputCfg.channels = AUDIO_CHANNEL_OUT_7POINT1;
146 context->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
147 context->config.inputCfg.samplingRate = 44100;
148 context->config.inputCfg.bufferProvider.getBuffer = NULL;
149 context->config.inputCfg.bufferProvider.releaseBuffer = NULL;
150 context->config.inputCfg.bufferProvider.cookie = NULL;
151 context->config.inputCfg.mask = EFFECT_CONFIG_ALL;
152
153 context->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
154 context->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
155 context->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
156 context->config.outputCfg.samplingRate = 44100;
157 context->config.outputCfg.bufferProvider.getBuffer = NULL;
158 context->config.outputCfg.bufferProvider.releaseBuffer = NULL;
159 context->config.outputCfg.bufferProvider.cookie = NULL;
160 context->config.outputCfg.mask = EFFECT_CONFIG_ALL;
161
162 set_config(context, &context->config);
163
164 hw_acc_ctxt->fd = -1;
165 memset(&(hw_acc_ctxt->cfg), 0, sizeof(struct msm_hwacc_effects_config));
166
167 return 0;
168}
169
170int hw_accelerator_reset(effect_context_t *context)
171{
172 ALOGV("%s", __func__);
173 return 0;
174}
175
176int hw_accelerator_set_mode(effect_context_t *context, int32_t frame_count)
177{
178 hw_accelerator_context_t *hw_acc_ctxt = (hw_accelerator_context_t *)context;
179
180 ALOGV("%s: ctxt %p", __func__, hw_acc_ctxt);
181 hw_acc_ctxt->cfg.output.sample_rate = context->config.inputCfg.samplingRate;
182 hw_acc_ctxt->cfg.input.sample_rate = context->config.outputCfg.samplingRate;
183
184 hw_acc_ctxt->cfg.output.num_channels = popcount(context->config.inputCfg.channels);
185 hw_acc_ctxt->cfg.input.num_channels = popcount(context->config.outputCfg.channels);
186
187 hw_acc_ctxt->cfg.output.bits_per_sample = 8 *
188 audio_bytes_per_sample(context->config.inputCfg.format);
189 hw_acc_ctxt->cfg.input.bits_per_sample = 8 *
190 audio_bytes_per_sample(context->config.outputCfg.format);
191
192 ALOGV("write: sample_rate: %d, channel: %d, bit_width: %d",
193 hw_acc_ctxt->cfg.output.sample_rate, hw_acc_ctxt->cfg.output.num_channels,
194 hw_acc_ctxt->cfg.output.bits_per_sample);
195 ALOGV("read: sample_rate: %d, channel: %d, bit_width: %d",
196 hw_acc_ctxt->cfg.input.sample_rate, hw_acc_ctxt->cfg.input.num_channels,
197 hw_acc_ctxt->cfg.input.bits_per_sample);
198
199 hw_acc_ctxt->cfg.output.num_buf = 4;
200 hw_acc_ctxt->cfg.input.num_buf = 2;
201
202 hw_acc_ctxt->cfg.output.buf_size = frame_count *
203 hw_acc_ctxt->cfg.output.num_channels *
204 audio_bytes_per_sample(context->config.inputCfg.format) *
205 ((hw_acc_ctxt->cfg.output.sample_rate/hw_acc_ctxt->cfg.input.sample_rate) +
206 (hw_acc_ctxt->cfg.output.sample_rate%hw_acc_ctxt->cfg.input.sample_rate ? 1 : 0));
207 hw_acc_ctxt->cfg.input.buf_size = frame_count *
208 hw_acc_ctxt->cfg.input.num_channels *
209 audio_bytes_per_sample(context->config.outputCfg.format);
210
211 hw_acc_ctxt->cfg.meta_mode_enabled = 0;
212 /* TODO: overwrite this for effects using custom topology*/
213 hw_acc_ctxt->cfg.overwrite_topology = 0;
214 hw_acc_ctxt->cfg.topology = 0;
215
216 return 0;
217}
218
219int hw_accelerator_enable(effect_context_t *context)
220{
221 hw_accelerator_context_t *hw_acc_ctxt = (hw_accelerator_context_t *)context;
222
223 ALOGV("%s: ctxt %p", __func__, hw_acc_ctxt);
224 hw_acc_ctxt->fd = open("/dev/msm_hweffects", O_RDWR | O_NONBLOCK);
225 /* open driver */
226 if (hw_acc_ctxt->fd < 0) {
227 ALOGE("Audio Effects driver open failed");
228 return -EFAULT;
229 }
230 /* set config */
231 if (ioctl(hw_acc_ctxt->fd, AUDIO_SET_EFFECTS_CONFIG, &hw_acc_ctxt->cfg) < 0) {
232 ALOGE("setting audio effects drivers config failed");
233 if (close(hw_acc_ctxt->fd) < 0)
234 ALOGE("releasing hardware accelerated effects driver failed");
235 hw_acc_ctxt->fd = -1;
236 return -EFAULT;
237 }
238 /* start */
239 if (ioctl(hw_acc_ctxt->fd, AUDIO_START, 0) < 0) {
240 ALOGE("audio effects drivers prepare failed");
241 if (close(hw_acc_ctxt->fd) < 0)
242 ALOGE("releasing hardware accelerated effects driver failed");
243 hw_acc_ctxt->fd = -1;
244 return -EFAULT;
245 }
246 return 0;
247}
248
249int hw_accelerator_disable(effect_context_t *context)
250{
251 hw_accelerator_context_t *hw_acc_ctxt = (hw_accelerator_context_t *)context;
252
253 ALOGV("%s: ctxt %p", __func__, hw_acc_ctxt);
254 if (hw_acc_ctxt->fd > 0)
255 if (close(hw_acc_ctxt->fd) < 0)
256 ALOGE("releasing hardware accelerated effects driver failed");
257 hw_acc_ctxt->fd = -1;
258 return 0;
259}
260
261int hw_accelerator_release(effect_context_t *context)
262{
263 hw_accelerator_context_t *hw_acc_ctxt = (hw_accelerator_context_t *)context;
264
265 ALOGV("%s: ctxt %p", __func__, hw_acc_ctxt);
266 if (hw_acc_ctxt->fd > 0)
267 if (close(hw_acc_ctxt->fd) < 0)
268 ALOGE("releasing hardware accelerated effects driver failed");
269 hw_acc_ctxt->fd = -1;
270 return 0;
271}
272
273int hw_accelerator_process(effect_context_t *context, audio_buffer_t *in_buf,
274 audio_buffer_t *out_buf)
275{
276 hw_accelerator_context_t *hw_acc_ctxt = (hw_accelerator_context_t *)context;
277 struct msm_hwacc_buf_cfg buf_cfg;
278 struct msm_hwacc_buf_avail buf_avail;
279 int ret = 0;
280
281 ALOGV("%s: ctxt %p", __func__, hw_acc_ctxt);
282 if (in_buf == NULL || in_buf->raw == NULL ||
283 out_buf == NULL || out_buf->raw == NULL)
284 return -EINVAL;
285
286 buf_cfg.output_len = in_buf->frameCount *
287 audio_bytes_per_sample(context->config.inputCfg.format) *
288 hw_acc_ctxt->cfg.output.num_channels;
289 buf_cfg.input_len = out_buf->frameCount *
290 audio_bytes_per_sample(context->config.outputCfg.format) *
291 hw_acc_ctxt->cfg.input.num_channels;
292
293 if (ioctl(hw_acc_ctxt->fd, AUDIO_EFFECTS_GET_BUF_AVAIL, &buf_avail) < 0) {
294 ALOGE("AUDIO_EFFECTS_GET_BUF_AVAIL failed");
295 return -ENOMEM;
296 }
297
298 if (!hw_acc_ctxt->intial_buffer_done) {
299 if (ioctl(hw_acc_ctxt->fd, AUDIO_EFFECTS_SET_BUF_LEN, &buf_cfg) < 0) {
300 ALOGE("AUDIO_EFFECTS_BUF_CFG failed");
301 return -EFAULT;
302 }
303 if (ioctl(hw_acc_ctxt->fd, AUDIO_EFFECTS_WRITE, (char *)in_buf->raw) < 0) {
304 ALOGE("AUDIO_EFFECTS_WRITE failed");
305 return -EFAULT;
306 }
307 ALOGV("Request for more data");
308 hw_acc_ctxt->intial_buffer_done = true;
309 return -ENODATA;
310 }
311 if (buf_avail.output_num_avail > 1) {
312 if (ioctl(hw_acc_ctxt->fd, AUDIO_EFFECTS_SET_BUF_LEN, &buf_cfg) < 0) {
313 ALOGE("AUDIO_EFFECTS_BUF_CFG failed");
314 return -EFAULT;
315 }
316 if (ioctl(hw_acc_ctxt->fd, AUDIO_EFFECTS_WRITE, (char *)in_buf->raw) < 0) {
317 ALOGE("AUDIO_EFFECTS_WRITE failed");
318 return -EFAULT;
319 }
320 ret = in_buf->frameCount;
321 }
322 if (ioctl(hw_acc_ctxt->fd, AUDIO_EFFECTS_READ, (char *)out_buf->raw) < 0) {
323 ALOGE("AUDIO_EFFECTS_READ failed");
324 return -EFAULT;
325 }
326
327 return ret;
328}