blob: 24e50d325adc561a6df7077db47810b881a2218d [file] [log] [blame]
Iliyan Malchev4765c432012-06-11 14:36:16 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
Duy Truongfae19622013-11-24 02:17:54 -08003 * Copyright (c) 2011-2012, 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
27#include <hardware_legacy/AudioHardwareInterface.h>
28#include <hardware_legacy/AudioSystemLegacy.h>
29
30namespace android_audio_legacy {
31
32extern "C" {
33
34struct qcom_audio_module {
35 struct audio_module module;
36};
37
38struct qcom_audio_device {
39 struct audio_hw_device device;
40
41 struct AudioHardwareInterface *hwif;
42};
43
44struct qcom_stream_out {
45 struct audio_stream_out stream;
46
47 AudioStreamOut *qcom_out;
48};
49
50struct qcom_stream_in {
51 struct audio_stream_in stream;
52
53 AudioStreamIn *qcom_in;
54};
55
Eric Laurent7801df92012-08-28 14:33:09 -070056
57enum {
58 HAL_API_REV_1_0,
59 HAL_API_REV_2_0,
60 HAL_API_REV_NUM
61} hal_api_rev;
62
63static uint32_t audio_device_conv_table[][HAL_API_REV_NUM] =
64{
65 /* output devices */
66 { AudioSystem::DEVICE_OUT_EARPIECE, AUDIO_DEVICE_OUT_EARPIECE },
67 { AudioSystem::DEVICE_OUT_SPEAKER, AUDIO_DEVICE_OUT_SPEAKER },
68 { AudioSystem::DEVICE_OUT_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADSET },
69 { AudioSystem::DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_WIRED_HEADPHONE },
70 { AudioSystem::DEVICE_OUT_BLUETOOTH_SCO, AUDIO_DEVICE_OUT_BLUETOOTH_SCO },
71 { AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET },
72 { AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT },
73 { AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP },
74 { AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES },
75 { AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER },
76 { AudioSystem::DEVICE_OUT_AUX_DIGITAL, AUDIO_DEVICE_OUT_AUX_DIGITAL },
77 { AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET },
78 { AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET },
79 { AudioSystem::DEVICE_OUT_DEFAULT, AUDIO_DEVICE_OUT_DEFAULT },
80#ifdef QCOM_ANC_HEADSET_ENABLED
81 { AudioSystem::DEVICE_OUT_ANC_HEADSET, AUDIO_DEVICE_OUT_ANC_HEADSET },
82 { AudioSystem::DEVICE_OUT_ANC_HEADPHONE, AUDIO_DEVICE_OUT_ANC_HEADPHONE },
83#endif
84#ifdef QCOM_FM_ENABLED
85 { AudioSystem::DEVICE_OUT_FM, AUDIO_DEVICE_OUT_FM },
86#endif
87#ifdef QCOM_FM_TX_ENABLED
88 { AudioSystem::DEVICE_OUT_FM_TX, AUDIO_DEVICE_OUT_FM_TX },
89#endif
90#ifdef QCOM_VOIP_ENABLED
91 { AudioSystem::DEVICE_OUT_DIRECTOUTPUT, AUDIO_DEVICE_OUT_DIRECTOUTPUT },
92#endif
93#ifdef QCOM_PROXY_DEVICE_ENABLED
94 { AudioSystem::DEVICE_OUT_PROXY, AUDIO_DEVICE_OUT_PROXY },
95#endif
96 /* input devices */
97 { AudioSystem::DEVICE_IN_COMMUNICATION, AUDIO_DEVICE_IN_COMMUNICATION },
98 { AudioSystem::DEVICE_IN_AMBIENT, AUDIO_DEVICE_IN_AMBIENT },
99 { AudioSystem::DEVICE_IN_BUILTIN_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC },
100 { AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET },
101 { AudioSystem::DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_WIRED_HEADSET },
102 { AudioSystem::DEVICE_IN_AUX_DIGITAL, AUDIO_DEVICE_IN_AUX_DIGITAL },
103 { AudioSystem::DEVICE_IN_VOICE_CALL, AUDIO_DEVICE_IN_VOICE_CALL },
104 { AudioSystem::DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BACK_MIC },
105 { AudioSystem::DEVICE_IN_DEFAULT, AUDIO_DEVICE_IN_DEFAULT },
106#ifdef QCOM_ANC_HEADSET_ENABLED
107 { AudioSystem::DEVICE_IN_ANC_HEADSET, AUDIO_DEVICE_IN_ANC_HEADSET },
108#endif
109#ifdef QCOM_FM_ENABLED
110 { AudioSystem::DEVICE_IN_FM_RX, AUDIO_DEVICE_IN_FM_RX },
111 { AudioSystem::DEVICE_IN_FM_RX_A2DP, AUDIO_DEVICE_IN_FM_RX_A2DP },
112#endif
113};
114
115static uint32_t convert_audio_device(uint32_t from_device, int from_rev, int to_rev)
116{
117 const uint32_t k_num_devices = sizeof(audio_device_conv_table)/sizeof(uint32_t)/HAL_API_REV_NUM;
118 uint32_t to_device = AUDIO_DEVICE_NONE;
119 uint32_t in_bit = 0;
120
121 if (from_rev != HAL_API_REV_1_0) {
122 in_bit = from_device & AUDIO_DEVICE_BIT_IN;
123 from_device &= ~AUDIO_DEVICE_BIT_IN;
124 }
125
126 while (from_device) {
127 uint32_t i = 31 - __builtin_clz(from_device);
128 uint32_t cur_device = (1 << i) | in_bit;
129
130 for (i = 0; i < k_num_devices; i++) {
131 if (audio_device_conv_table[i][from_rev] == cur_device) {
132 to_device |= audio_device_conv_table[i][to_rev];
133 break;
134 }
135 }
136 from_device &= ~cur_device;
137 }
138 return to_device;
139}
140
Iliyan Malchev4765c432012-06-11 14:36:16 -0700141/** audio_stream_out implementation **/
142static uint32_t out_get_sample_rate(const struct audio_stream *stream)
143{
144 const struct qcom_stream_out *out =
145 reinterpret_cast<const struct qcom_stream_out *>(stream);
146 return out->qcom_out->sampleRate();
147}
148
149static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
150{
151 struct qcom_stream_out *out =
152 reinterpret_cast<struct qcom_stream_out *>(stream);
153
Iliyan Malchev4113f342012-06-11 14:39:47 -0700154 ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700155 /* TODO: implement this */
156 return 0;
157}
158
159static size_t out_get_buffer_size(const struct audio_stream *stream)
160{
161 const struct qcom_stream_out *out =
162 reinterpret_cast<const struct qcom_stream_out *>(stream);
163 return out->qcom_out->bufferSize();
164}
165
166static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
167{
168 const struct qcom_stream_out *out =
169 reinterpret_cast<const struct qcom_stream_out *>(stream);
170 return out->qcom_out->channels();
171}
172
173static audio_format_t out_get_format(const struct audio_stream *stream)
174{
175 const struct qcom_stream_out *out =
176 reinterpret_cast<const struct qcom_stream_out *>(stream);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700177 return (audio_format_t)out->qcom_out->format();
Iliyan Malchev4765c432012-06-11 14:36:16 -0700178}
179
180static int out_set_format(struct audio_stream *stream, audio_format_t format)
181{
182 struct qcom_stream_out *out =
183 reinterpret_cast<struct qcom_stream_out *>(stream);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700184 ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700185 /* TODO: implement me */
186 return 0;
187}
188
189static int out_standby(struct audio_stream *stream)
190{
191 struct qcom_stream_out *out =
192 reinterpret_cast<struct qcom_stream_out *>(stream);
193 return out->qcom_out->standby();
194}
195
196static int out_dump(const struct audio_stream *stream, int fd)
197{
198 const struct qcom_stream_out *out =
199 reinterpret_cast<const struct qcom_stream_out *>(stream);
200 Vector<String16> args;
201 return out->qcom_out->dump(fd, args);
202}
203
204static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
205{
206 struct qcom_stream_out *out =
207 reinterpret_cast<struct qcom_stream_out *>(stream);
Eric Laurent7801df92012-08-28 14:33:09 -0700208 int val;
209 String8 s8 = String8(kvpairs);
210 AudioParameter parms = AudioParameter(String8(kvpairs));
211
212 if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) {
213 val = convert_audio_device(val, HAL_API_REV_2_0, HAL_API_REV_1_0);
214 parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING));
215 parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val);
216 s8 = parms.toString();
217 }
218
219 return out->qcom_out->setParameters(s8);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700220}
221
222static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
223{
224 const struct qcom_stream_out *out =
225 reinterpret_cast<const struct qcom_stream_out *>(stream);
226 String8 s8;
Eric Laurent7801df92012-08-28 14:33:09 -0700227 int val;
228
Iliyan Malchev4765c432012-06-11 14:36:16 -0700229 s8 = out->qcom_out->getParameters(String8(keys));
Eric Laurent7801df92012-08-28 14:33:09 -0700230
231 AudioParameter parms = AudioParameter(s8);
232 if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) {
233 val = convert_audio_device(val, HAL_API_REV_1_0, HAL_API_REV_2_0);
234 parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING));
235 parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val);
236 s8 = parms.toString();
237 }
238
Iliyan Malchev4765c432012-06-11 14:36:16 -0700239 return strdup(s8.string());
240}
241
242static uint32_t out_get_latency(const struct audio_stream_out *stream)
243{
244 const struct qcom_stream_out *out =
245 reinterpret_cast<const struct qcom_stream_out *>(stream);
246 return out->qcom_out->latency();
247}
248
249static int out_set_volume(struct audio_stream_out *stream, float left,
250 float right)
251{
252 struct qcom_stream_out *out =
253 reinterpret_cast<struct qcom_stream_out *>(stream);
254 return out->qcom_out->setVolume(left, right);
255}
256
257static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
258 size_t bytes)
259{
260 struct qcom_stream_out *out =
261 reinterpret_cast<struct qcom_stream_out *>(stream);
262 return out->qcom_out->write(buffer, bytes);
263}
264
265static int out_get_render_position(const struct audio_stream_out *stream,
266 uint32_t *dsp_frames)
267{
268 const struct qcom_stream_out *out =
269 reinterpret_cast<const struct qcom_stream_out *>(stream);
270 return out->qcom_out->getRenderPosition(dsp_frames);
271}
272
273static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
274{
275 return 0;
276}
277
278static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
279{
280 return 0;
281}
282
283static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
284 int64_t *timestamp)
285{
Ajay Dudani9746c472012-06-18 16:01:16 -0700286 const struct qcom_stream_out *out =
287 reinterpret_cast<const struct qcom_stream_out *>(stream);
288 return out->qcom_out->getNextWriteTimestamp(timestamp);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700289}
290
291/** audio_stream_in implementation **/
292static uint32_t in_get_sample_rate(const struct audio_stream *stream)
293{
294 const struct qcom_stream_in *in =
295 reinterpret_cast<const struct qcom_stream_in *>(stream);
296 return in->qcom_in->sampleRate();
297}
298
299static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
300{
301 struct qcom_stream_in *in =
302 reinterpret_cast<struct qcom_stream_in *>(stream);
303
Iliyan Malchev4113f342012-06-11 14:39:47 -0700304 ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700305 /* TODO: implement this */
306 return 0;
307}
308
309static size_t in_get_buffer_size(const struct audio_stream *stream)
310{
311 const struct qcom_stream_in *in =
312 reinterpret_cast<const struct qcom_stream_in *>(stream);
313 return in->qcom_in->bufferSize();
314}
315
316static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
317{
318 const struct qcom_stream_in *in =
319 reinterpret_cast<const struct qcom_stream_in *>(stream);
320 return in->qcom_in->channels();
321}
322
323static audio_format_t in_get_format(const struct audio_stream *stream)
324{
325 const struct qcom_stream_in *in =
326 reinterpret_cast<const struct qcom_stream_in *>(stream);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700327 return (audio_format_t)in->qcom_in->format();
Iliyan Malchev4765c432012-06-11 14:36:16 -0700328}
329
330static int in_set_format(struct audio_stream *stream, audio_format_t format)
331{
332 struct qcom_stream_in *in =
333 reinterpret_cast<struct qcom_stream_in *>(stream);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700334 ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700335 /* TODO: implement me */
336 return 0;
337}
338
339static int in_standby(struct audio_stream *stream)
340{
341 struct qcom_stream_in *in = reinterpret_cast<struct qcom_stream_in *>(stream);
342 return in->qcom_in->standby();
343}
344
345static int in_dump(const struct audio_stream *stream, int fd)
346{
347 const struct qcom_stream_in *in =
348 reinterpret_cast<const struct qcom_stream_in *>(stream);
349 Vector<String16> args;
350 return in->qcom_in->dump(fd, args);
351}
352
353static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
354{
355 struct qcom_stream_in *in =
356 reinterpret_cast<struct qcom_stream_in *>(stream);
Eric Laurent7801df92012-08-28 14:33:09 -0700357 int val;
358 AudioParameter parms = AudioParameter(String8(kvpairs));
359 String8 s8 = String8(kvpairs);
360
361 if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) {
362 val = convert_audio_device(val, HAL_API_REV_2_0, HAL_API_REV_1_0);
363 parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING));
364 parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val);
365 s8 = parms.toString();
366 }
367
368 return in->qcom_in->setParameters(s8);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700369}
370
371static char * in_get_parameters(const struct audio_stream *stream,
372 const char *keys)
373{
374 const struct qcom_stream_in *in =
375 reinterpret_cast<const struct qcom_stream_in *>(stream);
376 String8 s8;
Eric Laurent7801df92012-08-28 14:33:09 -0700377 int val;
378
Iliyan Malchev4765c432012-06-11 14:36:16 -0700379 s8 = in->qcom_in->getParameters(String8(keys));
Eric Laurent7801df92012-08-28 14:33:09 -0700380
381 AudioParameter parms = AudioParameter(s8);
382 if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) {
383 val = convert_audio_device(val, HAL_API_REV_1_0, HAL_API_REV_2_0);
384 parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING));
385 parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val);
386 s8 = parms.toString();
387 }
388
Iliyan Malchev4765c432012-06-11 14:36:16 -0700389 return strdup(s8.string());
390}
391
392static int in_set_gain(struct audio_stream_in *stream, float gain)
393{
394 struct qcom_stream_in *in =
395 reinterpret_cast<struct qcom_stream_in *>(stream);
396 return in->qcom_in->setGain(gain);
397}
398
399static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
400 size_t bytes)
401{
402 struct qcom_stream_in *in =
403 reinterpret_cast<struct qcom_stream_in *>(stream);
404 return in->qcom_in->read(buffer, bytes);
405}
406
407static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
408{
409 struct qcom_stream_in *in =
410 reinterpret_cast<struct qcom_stream_in *>(stream);
411 return in->qcom_in->getInputFramesLost();
412}
413
414static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
415{
416 const struct qcom_stream_in *in =
417 reinterpret_cast<const struct qcom_stream_in *>(stream);
418 return in->qcom_in->addAudioEffect(effect);
419}
420
421static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
422{
423 const struct qcom_stream_in *in =
424 reinterpret_cast<const struct qcom_stream_in *>(stream);
425 return in->qcom_in->removeAudioEffect(effect);
426}
427
428/** audio_hw_device implementation **/
429static inline struct qcom_audio_device * to_ladev(struct audio_hw_device *dev)
430{
431 return reinterpret_cast<struct qcom_audio_device *>(dev);
432}
433
434static inline const struct qcom_audio_device * to_cladev(const struct audio_hw_device *dev)
435{
436 return reinterpret_cast<const struct qcom_audio_device *>(dev);
437}
438
Iliyan Malchev4765c432012-06-11 14:36:16 -0700439static int adev_init_check(const struct audio_hw_device *dev)
440{
441 const struct qcom_audio_device *qadev = to_cladev(dev);
442
443 return qadev->hwif->initCheck();
444}
445
446static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
447{
448 struct qcom_audio_device *qadev = to_ladev(dev);
449 return qadev->hwif->setVoiceVolume(volume);
450}
451
452static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
453{
454 struct qcom_audio_device *qadev = to_ladev(dev);
455 return qadev->hwif->setMasterVolume(volume);
456}
457
458static int adev_get_master_volume(struct audio_hw_device *dev, float *volume) {
459
Iliyan Malchev4113f342012-06-11 14:39:47 -0700460 struct qcom_audio_device *qadev = to_ladev(dev);
461 return qadev->hwif->getMasterVolume(volume);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700462}
Ajay Dudani9746c472012-06-18 16:01:16 -0700463
464#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700465static int adev_set_fm_volume(struct audio_hw_device *dev, float volume)
466{
467 struct qcom_audio_device *qadev = to_ladev(dev);
468 return qadev->hwif->setFmVolume(volume);
469}
470#endif
471
472static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
473{
474 struct qcom_audio_device *qadev = to_ladev(dev);
475 return qadev->hwif->setMode(mode);
476}
477
478static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
479{
480 struct qcom_audio_device *qadev = to_ladev(dev);
481 return qadev->hwif->setMicMute(state);
482}
483
484static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
485{
486 const struct qcom_audio_device *qadev = to_cladev(dev);
487 return qadev->hwif->getMicMute(state);
488}
489
490static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
491{
492 struct qcom_audio_device *qadev = to_ladev(dev);
493 return qadev->hwif->setParameters(String8(kvpairs));
494}
495
496static char * adev_get_parameters(const struct audio_hw_device *dev,
497 const char *keys)
498{
499 const struct qcom_audio_device *qadev = to_cladev(dev);
500 String8 s8;
501
502 s8 = qadev->hwif->getParameters(String8(keys));
503 return strdup(s8.string());
504}
505
506static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
507 const struct audio_config *config)
508{
509 const struct qcom_audio_device *qadev = to_cladev(dev);
SathishKumar Manied3c0fd2012-09-21 10:31:40 -0700510 uint8_t channelCount = popcount(config->channel_mask);
511 return qadev->hwif->getInputBufferSize(config->sample_rate, config->format, channelCount);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700512}
513
Ajay Dudani9746c472012-06-18 16:01:16 -0700514#ifdef QCOM_TUNNEL_LPA_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700515static int adev_open_output_session(struct audio_hw_device *dev,
516 uint32_t devices,
517 int *format,
518 int sessionId,
519 uint32_t samplingRate,
520 uint32_t channels,
521 struct audio_stream_out **stream_out)
522{
523 struct qcom_audio_device *qadev = to_ladev(dev);
524 status_t status;
525 struct qcom_stream_out *out;
526 int ret;
527
528 out = (struct qcom_stream_out *)calloc(1, sizeof(*out));
529 if (!out)
530 return -ENOMEM;
531
532 out->qcom_out = qadev->hwif->openOutputSession(devices, format,&status,sessionId,samplingRate,channels);
533 if (!out->qcom_out) {
534 ret = status;
535 goto err_open;
536 }
537
538 out->stream.common.standby = out_standby;
539 out->stream.common.set_parameters = out_set_parameters;
540 out->stream.set_volume = out_set_volume;
541
542 *stream_out = &out->stream;
543 return 0;
544
545err_open:
546 free(out);
547 *stream_out = NULL;
548 return ret;
549}
550#endif
551
552static int adev_open_output_stream(struct audio_hw_device *dev,
553 audio_io_handle_t handle,
554 audio_devices_t devices,
555 audio_output_flags_t flags,
556 struct audio_config *config,
557 struct audio_stream_out **stream_out)
558{
559 struct qcom_audio_device *qadev = to_ladev(dev);
560 status_t status;
561 struct qcom_stream_out *out;
562 int ret;
563
564 out = (struct qcom_stream_out *)calloc(1, sizeof(*out));
565 if (!out)
566 return -ENOMEM;
567
Eric Laurent7801df92012-08-28 14:33:09 -0700568 devices = convert_audio_device(devices, HAL_API_REV_2_0, HAL_API_REV_1_0);
SathishKumar Mani88613382012-08-13 18:40:18 -0700569 status = static_cast<audio_output_flags_t> (flags);
Eric Laurent7801df92012-08-28 14:33:09 -0700570
Iliyan Malchev4113f342012-06-11 14:39:47 -0700571 out->qcom_out = qadev->hwif->openOutputStream(devices,
572 (int *)&config->format,
573 &config->channel_mask,
574 &config->sample_rate,
575 &status);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700576 if (!out->qcom_out) {
577 ret = status;
578 goto err_open;
579 }
580
581 out->stream.common.get_sample_rate = out_get_sample_rate;
582 out->stream.common.set_sample_rate = out_set_sample_rate;
583 out->stream.common.get_buffer_size = out_get_buffer_size;
584 out->stream.common.get_channels = out_get_channels;
585 out->stream.common.get_format = out_get_format;
586 out->stream.common.set_format = out_set_format;
587 out->stream.common.standby = out_standby;
588 out->stream.common.dump = out_dump;
589 out->stream.common.set_parameters = out_set_parameters;
590 out->stream.common.get_parameters = out_get_parameters;
591 out->stream.common.add_audio_effect = out_add_audio_effect;
592 out->stream.common.remove_audio_effect = out_remove_audio_effect;
593 out->stream.get_latency = out_get_latency;
594 out->stream.set_volume = out_set_volume;
595 out->stream.write = out_write;
596 out->stream.get_render_position = out_get_render_position;
597 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
598
599 *stream_out = &out->stream;
600 return 0;
601
602err_open:
603 free(out);
604 *stream_out = NULL;
605 return ret;
606}
607
608static void adev_close_output_stream(struct audio_hw_device *dev,
609 struct audio_stream_out* stream)
610{
611 struct qcom_audio_device *qadev = to_ladev(dev);
612 struct qcom_stream_out *out = reinterpret_cast<struct qcom_stream_out *>(stream);
613
614 qadev->hwif->closeOutputStream(out->qcom_out);
615 free(out);
616}
617
618/** This method creates and opens the audio hardware input stream */
619static int adev_open_input_stream(struct audio_hw_device *dev,
620 audio_io_handle_t handle,
621 audio_devices_t devices,
622 audio_config *config,
623 audio_stream_in **stream_in)
624{
625 struct qcom_audio_device *qadev = to_ladev(dev);
626 status_t status;
627 struct qcom_stream_in *in;
628 int ret;
629
630 in = (struct qcom_stream_in *)calloc(1, sizeof(*in));
631 if (!in)
632 return -ENOMEM;
633
Eric Laurent7801df92012-08-28 14:33:09 -0700634 devices = convert_audio_device(devices, HAL_API_REV_2_0, HAL_API_REV_1_0);
635
Iliyan Malchev4113f342012-06-11 14:39:47 -0700636 in->qcom_in = qadev->hwif->openInputStream(devices, (int *)&config->format,
637 &config->channel_mask,
638 &config->sample_rate,
639 &status,
640 (AudioSystem::audio_in_acoustics)0);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700641 if (!in->qcom_in) {
642 ret = status;
643 goto err_open;
644 }
645
646 in->stream.common.get_sample_rate = in_get_sample_rate;
647 in->stream.common.set_sample_rate = in_set_sample_rate;
648 in->stream.common.get_buffer_size = in_get_buffer_size;
649 in->stream.common.get_channels = in_get_channels;
650 in->stream.common.get_format = in_get_format;
651 in->stream.common.set_format = in_set_format;
652 in->stream.common.standby = in_standby;
653 in->stream.common.dump = in_dump;
654 in->stream.common.set_parameters = in_set_parameters;
655 in->stream.common.get_parameters = in_get_parameters;
656 in->stream.common.add_audio_effect = in_add_audio_effect;
657 in->stream.common.remove_audio_effect = in_remove_audio_effect;
658 in->stream.set_gain = in_set_gain;
659 in->stream.read = in_read;
660 in->stream.get_input_frames_lost = in_get_input_frames_lost;
661
662 *stream_in = &in->stream;
663 return 0;
664
665err_open:
666 free(in);
667 *stream_in = NULL;
668 return ret;
669}
670
671static void adev_close_input_stream(struct audio_hw_device *dev,
672 struct audio_stream_in *stream)
673{
674 struct qcom_audio_device *qadev = to_ladev(dev);
675 struct qcom_stream_in *in =
676 reinterpret_cast<struct qcom_stream_in *>(stream);
677
678 qadev->hwif->closeInputStream(in->qcom_in);
679 free(in);
680}
681
682static int adev_dump(const struct audio_hw_device *dev, int fd)
683{
684 const struct qcom_audio_device *qadev = to_cladev(dev);
685 Vector<String16> args;
686
687 return qadev->hwif->dumpState(fd, args);
688}
689
690static int qcom_adev_close(hw_device_t* device)
691{
692 struct audio_hw_device *hwdev =
693 reinterpret_cast<struct audio_hw_device *>(device);
694 struct qcom_audio_device *qadev = to_ladev(hwdev);
695
696 if (!qadev)
697 return 0;
698
699 if (qadev->hwif)
700 delete qadev->hwif;
701
702 free(qadev);
703 return 0;
704}
705
706static int qcom_adev_open(const hw_module_t* module, const char* name,
707 hw_device_t** device)
708{
709 struct qcom_audio_device *qadev;
710 int ret;
711
712 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
713 return -EINVAL;
714
715 qadev = (struct qcom_audio_device *)calloc(1, sizeof(*qadev));
716 if (!qadev)
717 return -ENOMEM;
718
719 qadev->device.common.tag = HARDWARE_DEVICE_TAG;
Eric Laurent7801df92012-08-28 14:33:09 -0700720 qadev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700721 qadev->device.common.module = const_cast<hw_module_t*>(module);
722 qadev->device.common.close = qcom_adev_close;
723
Iliyan Malchev4765c432012-06-11 14:36:16 -0700724 qadev->device.init_check = adev_init_check;
725 qadev->device.set_voice_volume = adev_set_voice_volume;
726 qadev->device.set_master_volume = adev_set_master_volume;
727 qadev->device.get_master_volume = adev_get_master_volume;
Ajay Dudani9746c472012-06-18 16:01:16 -0700728#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700729 qadev->device.set_fm_volume = adev_set_fm_volume;
730#endif
731 qadev->device.set_mode = adev_set_mode;
732 qadev->device.set_mic_mute = adev_set_mic_mute;
733 qadev->device.get_mic_mute = adev_get_mic_mute;
734 qadev->device.set_parameters = adev_set_parameters;
735 qadev->device.get_parameters = adev_get_parameters;
736 qadev->device.get_input_buffer_size = adev_get_input_buffer_size;
737 qadev->device.open_output_stream = adev_open_output_stream;
Ajay Dudani9746c472012-06-18 16:01:16 -0700738#ifdef QCOM_TUNNEL_LPA_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700739 qadev->device.open_output_session = adev_open_output_session;
740#endif
741 qadev->device.close_output_stream = adev_close_output_stream;
742 qadev->device.open_input_stream = adev_open_input_stream;
743 qadev->device.close_input_stream = adev_close_input_stream;
744 qadev->device.dump = adev_dump;
745
746 qadev->hwif = createAudioHardware();
747 if (!qadev->hwif) {
748 ret = -EIO;
749 goto err_create_audio_hw;
750 }
751
752 *device = &qadev->device.common;
753
754 return 0;
755
756err_create_audio_hw:
757 free(qadev);
758 return ret;
759}
760
761static struct hw_module_methods_t qcom_audio_module_methods = {
762 open: qcom_adev_open
763};
764
765struct qcom_audio_module HAL_MODULE_INFO_SYM = {
766 module: {
767 common: {
768 tag: HARDWARE_MODULE_TAG,
Eric Laurent7801df92012-08-28 14:33:09 -0700769 module_api_version: AUDIO_MODULE_API_VERSION_0_1,
770 hal_api_version: HARDWARE_HAL_API_VERSION,
Iliyan Malchev4765c432012-06-11 14:36:16 -0700771 id: AUDIO_HARDWARE_MODULE_ID,
772 name: "QCOM Audio HW HAL",
Duy Truongfae19622013-11-24 02:17:54 -0800773 author: "The Linux Foundation",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700774 methods: &qcom_audio_module_methods,
775 dso : NULL,
776 reserved : {0},
777 },
778 },
779};
780
781}; // extern "C"
782
783}; // namespace android_audio_legacy