blob: 6b3409014ad15485cab2c63c3dc888eec8032df9 [file] [log] [blame]
Iliyan Malchev4765c432012-06-11 14:36:16 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
Mingming Yinfddaa942012-12-27 17:42:46 -08003 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Iliyan Malchev4765c432012-06-11 14:36:16 -07004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
Ajay Dudani9746c472012-06-18 16:01:16 -070018#define LOG_TAG "qcom_audio_hw_hal"
Iliyan Malchev4765c432012-06-11 14:36:16 -070019//#define LOG_NDEBUG 0
20
21#include <stdint.h>
22
23#include <hardware/hardware.h>
24#include <system/audio.h>
25#include <hardware/audio.h>
26
Daniel Hillenbrandc757e342013-05-23 06:40:42 +020027#ifdef USES_AUDIO_AMPLIFIER
28#include <audio_amplifier.h>
29#endif
30
Iliyan Malchev4765c432012-06-11 14:36:16 -070031#include <hardware_legacy/AudioHardwareInterface.h>
32#include <hardware_legacy/AudioSystemLegacy.h>
33
34namespace android_audio_legacy {
35
36extern "C" {
37
38struct qcom_audio_module {
39 struct audio_module module;
40};
41
42struct qcom_audio_device {
43 struct audio_hw_device device;
44
45 struct AudioHardwareInterface *hwif;
46};
47
48struct qcom_stream_out {
49 struct audio_stream_out stream;
50
51 AudioStreamOut *qcom_out;
52};
53
54struct qcom_stream_in {
55 struct audio_stream_in stream;
56
57 AudioStreamIn *qcom_in;
58};
59
Eric Laurent7801df92012-08-28 14:33:09 -070060
61enum {
62 HAL_API_REV_1_0,
63 HAL_API_REV_2_0,
64 HAL_API_REV_NUM
65} hal_api_rev;
66
67static uint32_t audio_device_conv_table[][HAL_API_REV_NUM] =
68{
69 /* output devices */
70 { AudioSystem::DEVICE_OUT_EARPIECE, AUDIO_DEVICE_OUT_EARPIECE },
71 { AudioSystem::DEVICE_OUT_SPEAKER, AUDIO_DEVICE_OUT_SPEAKER },
72 { AudioSystem::DEVICE_OUT_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADSET },
73 { AudioSystem::DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_WIRED_HEADPHONE },
74 { AudioSystem::DEVICE_OUT_BLUETOOTH_SCO, AUDIO_DEVICE_OUT_BLUETOOTH_SCO },
75 { AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET },
76 { AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT },
77 { AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP },
78 { AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES },
79 { AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER },
80 { AudioSystem::DEVICE_OUT_AUX_DIGITAL, AUDIO_DEVICE_OUT_AUX_DIGITAL },
81 { AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET },
82 { AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET },
Mingming Yinfddaa942012-12-27 17:42:46 -080083 { AudioSystem::DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_ACCESSORY },
84 { AudioSystem::DEVICE_OUT_USB_DEVICE, AUDIO_DEVICE_OUT_USB_DEVICE },
Eric Laurent7801df92012-08-28 14:33:09 -070085#ifdef QCOM_ANC_HEADSET_ENABLED
86 { AudioSystem::DEVICE_OUT_ANC_HEADSET, AUDIO_DEVICE_OUT_ANC_HEADSET },
87 { AudioSystem::DEVICE_OUT_ANC_HEADPHONE, AUDIO_DEVICE_OUT_ANC_HEADPHONE },
88#endif
Eric Laurent7801df92012-08-28 14:33:09 -070089#ifdef QCOM_PROXY_DEVICE_ENABLED
90 { AudioSystem::DEVICE_OUT_PROXY, AUDIO_DEVICE_OUT_PROXY },
91#endif
Giulio Cervera99dfda52013-02-14 12:26:00 +010092#if defined(QCOM_FM_ENABLED) || defined(STE_FM)
Mingming Yinfddaa942012-12-27 17:42:46 -080093 { AudioSystem::DEVICE_OUT_FM, AUDIO_DEVICE_OUT_FM },
94 { AudioSystem::DEVICE_OUT_FM_TX, AUDIO_DEVICE_OUT_FM_TX },
95#endif
Mingming Yinbbd94ad2012-11-29 20:04:36 -080096 { AudioSystem::DEVICE_OUT_DEFAULT, AUDIO_DEVICE_OUT_DEFAULT },
Eric Laurent7801df92012-08-28 14:33:09 -070097 /* input devices */
98 { AudioSystem::DEVICE_IN_COMMUNICATION, AUDIO_DEVICE_IN_COMMUNICATION },
99 { AudioSystem::DEVICE_IN_AMBIENT, AUDIO_DEVICE_IN_AMBIENT },
100 { AudioSystem::DEVICE_IN_BUILTIN_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC },
101 { AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET },
102 { AudioSystem::DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_WIRED_HEADSET },
103 { AudioSystem::DEVICE_IN_AUX_DIGITAL, AUDIO_DEVICE_IN_AUX_DIGITAL },
104 { AudioSystem::DEVICE_IN_VOICE_CALL, AUDIO_DEVICE_IN_VOICE_CALL },
105 { AudioSystem::DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BACK_MIC },
Mingming Yinfddaa942012-12-27 17:42:46 -0800106 { AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET, AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET },
Eric Laurent7801df92012-08-28 14:33:09 -0700107#ifdef QCOM_ANC_HEADSET_ENABLED
108 { AudioSystem::DEVICE_IN_ANC_HEADSET, AUDIO_DEVICE_IN_ANC_HEADSET },
109#endif
Mingming Yinbbd94ad2012-11-29 20:04:36 -0800110#ifdef QCOM_PROXY_DEVICE_ENABLED
111 { AudioSystem::DEVICE_IN_PROXY, AUDIO_DEVICE_IN_PROXY },
Eric Laurent7801df92012-08-28 14:33:09 -0700112#endif
Giulio Cervera99dfda52013-02-14 12:26:00 +0100113#if defined(QCOM_FM_ENABLED) || defined(STE_FM)
Mingming Yinfddaa942012-12-27 17:42:46 -0800114 { AudioSystem::DEVICE_IN_FM_RX, AUDIO_DEVICE_IN_FM_RX },
115 { AudioSystem::DEVICE_IN_FM_RX_A2DP, AUDIO_DEVICE_IN_FM_RX_A2DP },
116#endif
Mingming Yinbbd94ad2012-11-29 20:04:36 -0800117 { AudioSystem::DEVICE_IN_DEFAULT, AUDIO_DEVICE_IN_DEFAULT },
Eric Laurent7801df92012-08-28 14:33:09 -0700118};
119
Mingming Yinbbd94ad2012-11-29 20:04:36 -0800120// the "audio_devices" enumeration defined in hardware/libhardware_legacy is obsolete,
121// use type "audio_devices_t" and audio device enumeration from system/audio.h instead.
122// Do not use convert_audio_device if audio hal uses device definition from system/core
123// There's no need to conver audio device if HAL uses AUDIO_DEVICE_XXX defintions instead
124// of AudioSystem::Device_XXX.
Eric Laurent7801df92012-08-28 14:33:09 -0700125static uint32_t convert_audio_device(uint32_t from_device, int from_rev, int to_rev)
126{
127 const uint32_t k_num_devices = sizeof(audio_device_conv_table)/sizeof(uint32_t)/HAL_API_REV_NUM;
128 uint32_t to_device = AUDIO_DEVICE_NONE;
129 uint32_t in_bit = 0;
130
131 if (from_rev != HAL_API_REV_1_0) {
132 in_bit = from_device & AUDIO_DEVICE_BIT_IN;
133 from_device &= ~AUDIO_DEVICE_BIT_IN;
134 }
135
136 while (from_device) {
137 uint32_t i = 31 - __builtin_clz(from_device);
138 uint32_t cur_device = (1 << i) | in_bit;
139
140 for (i = 0; i < k_num_devices; i++) {
141 if (audio_device_conv_table[i][from_rev] == cur_device) {
142 to_device |= audio_device_conv_table[i][to_rev];
143 break;
144 }
145 }
146 from_device &= ~cur_device;
147 }
148 return to_device;
149}
150
Iliyan Malchev4765c432012-06-11 14:36:16 -0700151/** audio_stream_out implementation **/
152static uint32_t out_get_sample_rate(const struct audio_stream *stream)
153{
154 const struct qcom_stream_out *out =
155 reinterpret_cast<const struct qcom_stream_out *>(stream);
156 return out->qcom_out->sampleRate();
157}
158
159static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
160{
161 struct qcom_stream_out *out =
162 reinterpret_cast<struct qcom_stream_out *>(stream);
163
Mingming Yinbbd94ad2012-11-29 20:04:36 -0800164 ALOGV("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700165 /* TODO: implement this */
166 return 0;
167}
168
169static size_t out_get_buffer_size(const struct audio_stream *stream)
170{
171 const struct qcom_stream_out *out =
172 reinterpret_cast<const struct qcom_stream_out *>(stream);
173 return out->qcom_out->bufferSize();
174}
175
176static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
177{
178 const struct qcom_stream_out *out =
179 reinterpret_cast<const struct qcom_stream_out *>(stream);
180 return out->qcom_out->channels();
181}
182
183static audio_format_t out_get_format(const struct audio_stream *stream)
184{
185 const struct qcom_stream_out *out =
186 reinterpret_cast<const struct qcom_stream_out *>(stream);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700187 return (audio_format_t)out->qcom_out->format();
Iliyan Malchev4765c432012-06-11 14:36:16 -0700188}
189
190static int out_set_format(struct audio_stream *stream, audio_format_t format)
191{
192 struct qcom_stream_out *out =
193 reinterpret_cast<struct qcom_stream_out *>(stream);
Mingming Yinbbd94ad2012-11-29 20:04:36 -0800194 ALOGV("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700195 /* TODO: implement me */
196 return 0;
197}
198
199static int out_standby(struct audio_stream *stream)
200{
201 struct qcom_stream_out *out =
202 reinterpret_cast<struct qcom_stream_out *>(stream);
203 return out->qcom_out->standby();
204}
205
206static int out_dump(const struct audio_stream *stream, int fd)
207{
208 const struct qcom_stream_out *out =
209 reinterpret_cast<const struct qcom_stream_out *>(stream);
210 Vector<String16> args;
211 return out->qcom_out->dump(fd, args);
212}
213
214static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
215{
216 struct qcom_stream_out *out =
217 reinterpret_cast<struct qcom_stream_out *>(stream);
Eric Laurent7801df92012-08-28 14:33:09 -0700218 int val;
219 String8 s8 = String8(kvpairs);
220 AudioParameter parms = AudioParameter(String8(kvpairs));
221
222 if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) {
223 val = convert_audio_device(val, HAL_API_REV_2_0, HAL_API_REV_1_0);
224 parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING));
225 parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val);
226 s8 = parms.toString();
227 }
228
229 return out->qcom_out->setParameters(s8);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700230}
231
232static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
233{
234 const struct qcom_stream_out *out =
235 reinterpret_cast<const struct qcom_stream_out *>(stream);
236 String8 s8;
Eric Laurent7801df92012-08-28 14:33:09 -0700237 int val;
238
Iliyan Malchev4765c432012-06-11 14:36:16 -0700239 s8 = out->qcom_out->getParameters(String8(keys));
Eric Laurent7801df92012-08-28 14:33:09 -0700240
241 AudioParameter parms = AudioParameter(s8);
242 if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) {
243 val = convert_audio_device(val, HAL_API_REV_1_0, HAL_API_REV_2_0);
244 parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING));
245 parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val);
246 s8 = parms.toString();
247 }
248
Iliyan Malchev4765c432012-06-11 14:36:16 -0700249 return strdup(s8.string());
250}
251
252static uint32_t out_get_latency(const struct audio_stream_out *stream)
253{
254 const struct qcom_stream_out *out =
255 reinterpret_cast<const struct qcom_stream_out *>(stream);
256 return out->qcom_out->latency();
257}
258
259static int out_set_volume(struct audio_stream_out *stream, float left,
260 float right)
261{
262 struct qcom_stream_out *out =
263 reinterpret_cast<struct qcom_stream_out *>(stream);
264 return out->qcom_out->setVolume(left, right);
265}
266
267static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
268 size_t bytes)
269{
270 struct qcom_stream_out *out =
271 reinterpret_cast<struct qcom_stream_out *>(stream);
272 return out->qcom_out->write(buffer, bytes);
273}
274
275static int out_get_render_position(const struct audio_stream_out *stream,
276 uint32_t *dsp_frames)
277{
278 const struct qcom_stream_out *out =
279 reinterpret_cast<const struct qcom_stream_out *>(stream);
280 return out->qcom_out->getRenderPosition(dsp_frames);
281}
282
Subhash Chandra Bose Naripeddy22d0d6f2012-12-01 23:03:41 -0800283static int out_set_observer(const struct audio_stream_out *stream,
284 void *observer)
285{
286 const struct qcom_stream_out *out =
287 reinterpret_cast<const struct qcom_stream_out *>(stream);
288 return out->qcom_out->setObserver(observer);
289}
290
Subhash Chandra Bose Naripeddy908253a2012-12-07 11:57:25 -0800291static int out_get_buffer_info(const struct audio_stream_out *stream,
292 buf_info ** buf)
293{
294 const struct qcom_stream_out *out =
295 reinterpret_cast<const struct qcom_stream_out *>(stream);
296 return out->qcom_out->getBufferInfo(buf);
297}
298
Subhash Chandra Bose Naripeddy22d0d6f2012-12-01 23:03:41 -0800299static int out_is_buffer_available(const struct audio_stream_out *stream,
300 int *isAvail)
301{
302 const struct qcom_stream_out *out =
303 reinterpret_cast<const struct qcom_stream_out *>(stream);
304 return out->qcom_out->isBufferAvailable(isAvail);
305}
306
307static status_t out_start(struct audio_stream_out *stream)
308{
309 struct qcom_stream_out *out =
310 reinterpret_cast<struct qcom_stream_out *>(stream);
311 return out->qcom_out->start();
312}
313
314static status_t out_pause(struct audio_stream_out *stream)
315{
316 struct qcom_stream_out *out =
317 reinterpret_cast<struct qcom_stream_out *>(stream);
318 return out->qcom_out->pause();
319}
320
321static status_t out_flush(struct audio_stream_out *stream)
322{
323 struct qcom_stream_out *out =
324 reinterpret_cast<struct qcom_stream_out *>(stream);
325 return out->qcom_out->flush();
326}
327
328static status_t out_stop(struct audio_stream_out *stream)
329{
330 struct qcom_stream_out *out =
331 reinterpret_cast<struct qcom_stream_out *>(stream);
332 return out->qcom_out->stop();
333}
Iliyan Malchev4765c432012-06-11 14:36:16 -0700334static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
335{
336 return 0;
337}
338
339static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
340{
341 return 0;
342}
343
344static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
345 int64_t *timestamp)
346{
Ajay Dudani9746c472012-06-18 16:01:16 -0700347 const struct qcom_stream_out *out =
348 reinterpret_cast<const struct qcom_stream_out *>(stream);
349 return out->qcom_out->getNextWriteTimestamp(timestamp);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700350}
351
352/** audio_stream_in implementation **/
353static uint32_t in_get_sample_rate(const struct audio_stream *stream)
354{
355 const struct qcom_stream_in *in =
356 reinterpret_cast<const struct qcom_stream_in *>(stream);
357 return in->qcom_in->sampleRate();
358}
359
360static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
361{
362 struct qcom_stream_in *in =
363 reinterpret_cast<struct qcom_stream_in *>(stream);
364
Mingming Yinbbd94ad2012-11-29 20:04:36 -0800365 ALOGV("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700366 /* TODO: implement this */
367 return 0;
368}
369
370static size_t in_get_buffer_size(const struct audio_stream *stream)
371{
372 const struct qcom_stream_in *in =
373 reinterpret_cast<const struct qcom_stream_in *>(stream);
374 return in->qcom_in->bufferSize();
375}
376
377static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
378{
379 const struct qcom_stream_in *in =
380 reinterpret_cast<const struct qcom_stream_in *>(stream);
381 return in->qcom_in->channels();
382}
383
384static audio_format_t in_get_format(const struct audio_stream *stream)
385{
386 const struct qcom_stream_in *in =
387 reinterpret_cast<const struct qcom_stream_in *>(stream);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700388 return (audio_format_t)in->qcom_in->format();
Iliyan Malchev4765c432012-06-11 14:36:16 -0700389}
390
391static int in_set_format(struct audio_stream *stream, audio_format_t format)
392{
393 struct qcom_stream_in *in =
394 reinterpret_cast<struct qcom_stream_in *>(stream);
Mingming Yinbbd94ad2012-11-29 20:04:36 -0800395 ALOGV("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700396 /* TODO: implement me */
397 return 0;
398}
399
400static int in_standby(struct audio_stream *stream)
401{
402 struct qcom_stream_in *in = reinterpret_cast<struct qcom_stream_in *>(stream);
403 return in->qcom_in->standby();
404}
405
406static int in_dump(const struct audio_stream *stream, int fd)
407{
408 const struct qcom_stream_in *in =
409 reinterpret_cast<const struct qcom_stream_in *>(stream);
410 Vector<String16> args;
411 return in->qcom_in->dump(fd, args);
412}
413
414static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
415{
416 struct qcom_stream_in *in =
417 reinterpret_cast<struct qcom_stream_in *>(stream);
Eric Laurent7801df92012-08-28 14:33:09 -0700418 int val;
419 AudioParameter parms = AudioParameter(String8(kvpairs));
420 String8 s8 = String8(kvpairs);
421
422 if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) {
423 val = convert_audio_device(val, HAL_API_REV_2_0, HAL_API_REV_1_0);
424 parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING));
425 parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val);
426 s8 = parms.toString();
427 }
428
429 return in->qcom_in->setParameters(s8);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700430}
431
432static char * in_get_parameters(const struct audio_stream *stream,
433 const char *keys)
434{
435 const struct qcom_stream_in *in =
436 reinterpret_cast<const struct qcom_stream_in *>(stream);
437 String8 s8;
Eric Laurent7801df92012-08-28 14:33:09 -0700438 int val;
439
Iliyan Malchev4765c432012-06-11 14:36:16 -0700440 s8 = in->qcom_in->getParameters(String8(keys));
Eric Laurent7801df92012-08-28 14:33:09 -0700441
442 AudioParameter parms = AudioParameter(s8);
443 if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) {
444 val = convert_audio_device(val, HAL_API_REV_1_0, HAL_API_REV_2_0);
445 parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING));
446 parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val);
447 s8 = parms.toString();
448 }
449
Iliyan Malchev4765c432012-06-11 14:36:16 -0700450 return strdup(s8.string());
451}
452
453static int in_set_gain(struct audio_stream_in *stream, float gain)
454{
455 struct qcom_stream_in *in =
456 reinterpret_cast<struct qcom_stream_in *>(stream);
457 return in->qcom_in->setGain(gain);
458}
459
460static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
461 size_t bytes)
462{
463 struct qcom_stream_in *in =
464 reinterpret_cast<struct qcom_stream_in *>(stream);
465 return in->qcom_in->read(buffer, bytes);
466}
467
468static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
469{
470 struct qcom_stream_in *in =
471 reinterpret_cast<struct qcom_stream_in *>(stream);
472 return in->qcom_in->getInputFramesLost();
473}
474
475static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
476{
477 const struct qcom_stream_in *in =
478 reinterpret_cast<const struct qcom_stream_in *>(stream);
479 return in->qcom_in->addAudioEffect(effect);
480}
481
482static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
483{
484 const struct qcom_stream_in *in =
485 reinterpret_cast<const struct qcom_stream_in *>(stream);
486 return in->qcom_in->removeAudioEffect(effect);
487}
488
489/** audio_hw_device implementation **/
490static inline struct qcom_audio_device * to_ladev(struct audio_hw_device *dev)
491{
492 return reinterpret_cast<struct qcom_audio_device *>(dev);
493}
494
495static inline const struct qcom_audio_device * to_cladev(const struct audio_hw_device *dev)
496{
497 return reinterpret_cast<const struct qcom_audio_device *>(dev);
498}
499
Mingming Yinbbd94ad2012-11-29 20:04:36 -0800500static uint32_t adev_get_supported_devices(const struct audio_hw_device *dev)
501{
502 /* XXX: The old AudioHardwareInterface interface is not smart enough to
503 * tell us this, so we'll lie and basically tell AF that we support the
504 * below input/output devices and cross our fingers. To do things properly,
505 * audio hardware interfaces that need advanced features (like this) should
506 * convert to the new HAL interface and not use this wrapper. */
507 return (/* OUT */
508 AUDIO_DEVICE_OUT_EARPIECE |
509 AUDIO_DEVICE_OUT_SPEAKER |
510 AUDIO_DEVICE_OUT_WIRED_HEADSET |
511 AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
512 AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
513 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
514 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT |
515 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
516 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
517 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER |
518 AUDIO_DEVICE_OUT_AUX_DIGITAL |
519 AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
520 AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET |
521 AUDIO_DEVICE_OUT_USB_ACCESSORY |
522 AUDIO_DEVICE_OUT_USB_DEVICE |
523 AUDIO_DEVICE_OUT_REMOTE_SUBMIX |
524#ifdef QCOM_ANC_HEADSET_ENABLED
525 AUDIO_DEVICE_OUT_ANC_HEADSET |
526 AUDIO_DEVICE_OUT_ANC_HEADPHONE |
527#endif
528#ifdef QCOM_PROXY_DEVICE_ENABLED
529 AUDIO_DEVICE_OUT_PROXY |
530#endif
Giulio Cervera99dfda52013-02-14 12:26:00 +0100531#if defined(QCOM_FM_ENABLED) || defined(STE_FM)
Mingming Yinbbd94ad2012-11-29 20:04:36 -0800532 AUDIO_DEVICE_OUT_FM |
533 AUDIO_DEVICE_OUT_FM_TX |
534#endif
535 AUDIO_DEVICE_OUT_DEFAULT |
536 /* IN */
537 AUDIO_DEVICE_IN_COMMUNICATION |
538 AUDIO_DEVICE_IN_AMBIENT |
539 AUDIO_DEVICE_IN_BUILTIN_MIC |
540 AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET |
541 AUDIO_DEVICE_IN_WIRED_HEADSET |
542 AUDIO_DEVICE_IN_AUX_DIGITAL |
543 AUDIO_DEVICE_IN_VOICE_CALL |
544 AUDIO_DEVICE_IN_BACK_MIC |
545 AUDIO_DEVICE_IN_REMOTE_SUBMIX |
546 AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET |
547 AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET |
548 AUDIO_DEVICE_IN_USB_ACCESSORY |
549 AUDIO_DEVICE_IN_USB_DEVICE |
550#ifdef QCOM_ANC_HEADSET_ENABLED
551 AUDIO_DEVICE_IN_ANC_HEADSET |
552#endif
553#ifdef QCOM_PROXY_DEVICE_ENABLED
554 AUDIO_DEVICE_IN_PROXY |
555#endif
Giulio Cervera99dfda52013-02-14 12:26:00 +0100556#if defined(QCOM_FM_ENABLED) || defined(STE_FM)
Mingming Yinbbd94ad2012-11-29 20:04:36 -0800557 AUDIO_DEVICE_IN_FM_RX |
558 AUDIO_DEVICE_IN_FM_RX_A2DP |
559#endif
560 AUDIO_DEVICE_IN_DEFAULT);
561}
562
Iliyan Malchev4765c432012-06-11 14:36:16 -0700563static int adev_init_check(const struct audio_hw_device *dev)
564{
565 const struct qcom_audio_device *qadev = to_cladev(dev);
566
567 return qadev->hwif->initCheck();
568}
569
570static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
571{
572 struct qcom_audio_device *qadev = to_ladev(dev);
573 return qadev->hwif->setVoiceVolume(volume);
574}
575
576static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
577{
578 struct qcom_audio_device *qadev = to_ladev(dev);
579 return qadev->hwif->setMasterVolume(volume);
580}
581
582static int adev_get_master_volume(struct audio_hw_device *dev, float *volume) {
583
Iliyan Malchev4113f342012-06-11 14:39:47 -0700584 struct qcom_audio_device *qadev = to_ladev(dev);
585 return qadev->hwif->getMasterVolume(volume);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700586}
Ajay Dudani9746c472012-06-18 16:01:16 -0700587
588#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700589static int adev_set_fm_volume(struct audio_hw_device *dev, float volume)
590{
591 struct qcom_audio_device *qadev = to_ladev(dev);
592 return qadev->hwif->setFmVolume(volume);
593}
594#endif
595
596static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
597{
598 struct qcom_audio_device *qadev = to_ladev(dev);
Daniel Hillenbrandc757e342013-05-23 06:40:42 +0200599
600#ifdef USES_AUDIO_AMPLIFIER
601 if (amplifier_set_mode(mode) != 0)
602 ALOGE("Failed setting amplifier mode");
603#endif
604
Iliyan Malchev4765c432012-06-11 14:36:16 -0700605 return qadev->hwif->setMode(mode);
606}
607
608static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
609{
610 struct qcom_audio_device *qadev = to_ladev(dev);
611 return qadev->hwif->setMicMute(state);
612}
613
614static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
615{
616 const struct qcom_audio_device *qadev = to_cladev(dev);
617 return qadev->hwif->getMicMute(state);
618}
619
620static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
621{
622 struct qcom_audio_device *qadev = to_ladev(dev);
623 return qadev->hwif->setParameters(String8(kvpairs));
624}
625
626static char * adev_get_parameters(const struct audio_hw_device *dev,
627 const char *keys)
628{
629 const struct qcom_audio_device *qadev = to_cladev(dev);
630 String8 s8;
631
632 s8 = qadev->hwif->getParameters(String8(keys));
633 return strdup(s8.string());
634}
635
636static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
637 const struct audio_config *config)
638{
639 const struct qcom_audio_device *qadev = to_cladev(dev);
SathishKumar Manied3c0fd2012-09-21 10:31:40 -0700640 uint8_t channelCount = popcount(config->channel_mask);
641 return qadev->hwif->getInputBufferSize(config->sample_rate, config->format, channelCount);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700642}
643
Iliyan Malchev4765c432012-06-11 14:36:16 -0700644static int adev_open_output_stream(struct audio_hw_device *dev,
645 audio_io_handle_t handle,
646 audio_devices_t devices,
647 audio_output_flags_t flags,
648 struct audio_config *config,
649 struct audio_stream_out **stream_out)
650{
651 struct qcom_audio_device *qadev = to_ladev(dev);
652 status_t status;
653 struct qcom_stream_out *out;
654 int ret;
655
656 out = (struct qcom_stream_out *)calloc(1, sizeof(*out));
657 if (!out)
658 return -ENOMEM;
659
Eric Laurent7801df92012-08-28 14:33:09 -0700660 devices = convert_audio_device(devices, HAL_API_REV_2_0, HAL_API_REV_1_0);
SathishKumar Mani88613382012-08-13 18:40:18 -0700661 status = static_cast<audio_output_flags_t> (flags);
Eric Laurent7801df92012-08-28 14:33:09 -0700662
Iliyan Malchev4113f342012-06-11 14:39:47 -0700663 out->qcom_out = qadev->hwif->openOutputStream(devices,
664 (int *)&config->format,
665 &config->channel_mask,
666 &config->sample_rate,
667 &status);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700668 if (!out->qcom_out) {
669 ret = status;
670 goto err_open;
671 }
672
673 out->stream.common.get_sample_rate = out_get_sample_rate;
674 out->stream.common.set_sample_rate = out_set_sample_rate;
675 out->stream.common.get_buffer_size = out_get_buffer_size;
676 out->stream.common.get_channels = out_get_channels;
677 out->stream.common.get_format = out_get_format;
678 out->stream.common.set_format = out_set_format;
679 out->stream.common.standby = out_standby;
680 out->stream.common.dump = out_dump;
681 out->stream.common.set_parameters = out_set_parameters;
682 out->stream.common.get_parameters = out_get_parameters;
683 out->stream.common.add_audio_effect = out_add_audio_effect;
684 out->stream.common.remove_audio_effect = out_remove_audio_effect;
685 out->stream.get_latency = out_get_latency;
686 out->stream.set_volume = out_set_volume;
687 out->stream.write = out_write;
688 out->stream.get_render_position = out_get_render_position;
689 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Subhash Chandra Bose Naripeddy22d0d6f2012-12-01 23:03:41 -0800690 out->stream.start = out_start;
691 out->stream.pause = out_pause;
692 out->stream.flush = out_flush;
693 out->stream.stop = out_stop;
694 out->stream.set_observer = out_set_observer;
Subhash Chandra Bose Naripeddy908253a2012-12-07 11:57:25 -0800695 out->stream.get_buffer_info = out_get_buffer_info;
Subhash Chandra Bose Naripeddy22d0d6f2012-12-01 23:03:41 -0800696 out->stream.is_buffer_available = out_is_buffer_available;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700697
698 *stream_out = &out->stream;
699 return 0;
700
701err_open:
702 free(out);
703 *stream_out = NULL;
704 return ret;
705}
706
707static void adev_close_output_stream(struct audio_hw_device *dev,
708 struct audio_stream_out* stream)
709{
710 struct qcom_audio_device *qadev = to_ladev(dev);
711 struct qcom_stream_out *out = reinterpret_cast<struct qcom_stream_out *>(stream);
712
713 qadev->hwif->closeOutputStream(out->qcom_out);
714 free(out);
715}
716
717/** This method creates and opens the audio hardware input stream */
718static int adev_open_input_stream(struct audio_hw_device *dev,
719 audio_io_handle_t handle,
720 audio_devices_t devices,
721 audio_config *config,
722 audio_stream_in **stream_in)
723{
724 struct qcom_audio_device *qadev = to_ladev(dev);
725 status_t status;
726 struct qcom_stream_in *in;
727 int ret;
728
729 in = (struct qcom_stream_in *)calloc(1, sizeof(*in));
730 if (!in)
731 return -ENOMEM;
732
Eric Laurent7801df92012-08-28 14:33:09 -0700733 devices = convert_audio_device(devices, HAL_API_REV_2_0, HAL_API_REV_1_0);
734
Iliyan Malchev4113f342012-06-11 14:39:47 -0700735 in->qcom_in = qadev->hwif->openInputStream(devices, (int *)&config->format,
736 &config->channel_mask,
737 &config->sample_rate,
738 &status,
739 (AudioSystem::audio_in_acoustics)0);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700740 if (!in->qcom_in) {
741 ret = status;
742 goto err_open;
743 }
744
745 in->stream.common.get_sample_rate = in_get_sample_rate;
746 in->stream.common.set_sample_rate = in_set_sample_rate;
747 in->stream.common.get_buffer_size = in_get_buffer_size;
748 in->stream.common.get_channels = in_get_channels;
749 in->stream.common.get_format = in_get_format;
750 in->stream.common.set_format = in_set_format;
751 in->stream.common.standby = in_standby;
752 in->stream.common.dump = in_dump;
753 in->stream.common.set_parameters = in_set_parameters;
754 in->stream.common.get_parameters = in_get_parameters;
755 in->stream.common.add_audio_effect = in_add_audio_effect;
756 in->stream.common.remove_audio_effect = in_remove_audio_effect;
757 in->stream.set_gain = in_set_gain;
758 in->stream.read = in_read;
759 in->stream.get_input_frames_lost = in_get_input_frames_lost;
760
761 *stream_in = &in->stream;
762 return 0;
763
764err_open:
765 free(in);
766 *stream_in = NULL;
767 return ret;
768}
769
770static void adev_close_input_stream(struct audio_hw_device *dev,
771 struct audio_stream_in *stream)
772{
773 struct qcom_audio_device *qadev = to_ladev(dev);
774 struct qcom_stream_in *in =
775 reinterpret_cast<struct qcom_stream_in *>(stream);
776
777 qadev->hwif->closeInputStream(in->qcom_in);
778 free(in);
779}
780
781static int adev_dump(const struct audio_hw_device *dev, int fd)
782{
783 const struct qcom_audio_device *qadev = to_cladev(dev);
784 Vector<String16> args;
785
786 return qadev->hwif->dumpState(fd, args);
787}
788
789static int qcom_adev_close(hw_device_t* device)
790{
791 struct audio_hw_device *hwdev =
792 reinterpret_cast<struct audio_hw_device *>(device);
793 struct qcom_audio_device *qadev = to_ladev(hwdev);
794
Daniel Hillenbrand5507a6b2013-09-06 20:04:58 +0200795#ifdef USES_AUDIO_AMPLIFIER
796 if (amplifier_close() != 0)
797 ALOGE("Amplifier close failed");
798#endif
799
Iliyan Malchev4765c432012-06-11 14:36:16 -0700800 if (!qadev)
801 return 0;
802
803 if (qadev->hwif)
804 delete qadev->hwif;
805
806 free(qadev);
807 return 0;
808}
809
810static int qcom_adev_open(const hw_module_t* module, const char* name,
811 hw_device_t** device)
812{
813 struct qcom_audio_device *qadev;
814 int ret;
815
816 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
817 return -EINVAL;
818
819 qadev = (struct qcom_audio_device *)calloc(1, sizeof(*qadev));
820 if (!qadev)
821 return -ENOMEM;
822
823 qadev->device.common.tag = HARDWARE_DEVICE_TAG;
Eric Laurent7801df92012-08-28 14:33:09 -0700824 qadev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700825 qadev->device.common.module = const_cast<hw_module_t*>(module);
826 qadev->device.common.close = qcom_adev_close;
827
Mingming Yinbbd94ad2012-11-29 20:04:36 -0800828 qadev->device.get_supported_devices = adev_get_supported_devices;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700829 qadev->device.init_check = adev_init_check;
830 qadev->device.set_voice_volume = adev_set_voice_volume;
831 qadev->device.set_master_volume = adev_set_master_volume;
832 qadev->device.get_master_volume = adev_get_master_volume;
Ajay Dudani9746c472012-06-18 16:01:16 -0700833#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700834 qadev->device.set_fm_volume = adev_set_fm_volume;
835#endif
836 qadev->device.set_mode = adev_set_mode;
837 qadev->device.set_mic_mute = adev_set_mic_mute;
838 qadev->device.get_mic_mute = adev_get_mic_mute;
839 qadev->device.set_parameters = adev_set_parameters;
840 qadev->device.get_parameters = adev_get_parameters;
841 qadev->device.get_input_buffer_size = adev_get_input_buffer_size;
842 qadev->device.open_output_stream = adev_open_output_stream;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700843 qadev->device.close_output_stream = adev_close_output_stream;
844 qadev->device.open_input_stream = adev_open_input_stream;
845 qadev->device.close_input_stream = adev_close_input_stream;
846 qadev->device.dump = adev_dump;
847
848 qadev->hwif = createAudioHardware();
849 if (!qadev->hwif) {
850 ret = -EIO;
851 goto err_create_audio_hw;
852 }
853
854 *device = &qadev->device.common;
855
Daniel Hillenbrand5507a6b2013-09-06 20:04:58 +0200856#ifdef USES_AUDIO_AMPLIFIER
857 if (amplifier_open() != 0)
858 ALOGE("Amplifier initialization failed");
859#endif
860
Iliyan Malchev4765c432012-06-11 14:36:16 -0700861 return 0;
862
863err_create_audio_hw:
864 free(qadev);
865 return ret;
866}
867
868static struct hw_module_methods_t qcom_audio_module_methods = {
869 open: qcom_adev_open
870};
871
872struct qcom_audio_module HAL_MODULE_INFO_SYM = {
873 module: {
874 common: {
875 tag: HARDWARE_MODULE_TAG,
Eric Laurent7801df92012-08-28 14:33:09 -0700876 module_api_version: AUDIO_MODULE_API_VERSION_0_1,
877 hal_api_version: HARDWARE_HAL_API_VERSION,
Iliyan Malchev4765c432012-06-11 14:36:16 -0700878 id: AUDIO_HARDWARE_MODULE_ID,
879 name: "QCOM Audio HW HAL",
Duy Truongeb337332013-01-17 10:33:22 -0800880 author: "The Linux Foundation",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700881 methods: &qcom_audio_module_methods,
882 dso : NULL,
883 reserved : {0},
884 },
885 },
886};
887
888}; // extern "C"
889
890}; // namespace android_audio_legacy