1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
4 *
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
18#define LOG_TAG "qcom_audio_hw_hal"
19//#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
56
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
141/** 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
154    ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
155    /* 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);
177    return (audio_format_t)out->qcom_out->format();
178}
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);
184    ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
185    /* 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);
208    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);
220}
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;
227    int val;
228
229    s8 = out->qcom_out->getParameters(String8(keys));
230
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
239    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{
286    const struct qcom_stream_out *out =
287        reinterpret_cast<const struct qcom_stream_out *>(stream);
288    return out->qcom_out->getNextWriteTimestamp(timestamp);
289}
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
304    ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
305    /* 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);
327    return (audio_format_t)in->qcom_in->format();
328}
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);
334    ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
335    /* 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);
357    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);
369}
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;
377    int val;
378
379    s8 = in->qcom_in->getParameters(String8(keys));
380
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
389    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
439static 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
460    struct qcom_audio_device *qadev = to_ladev(dev);
461    return qadev->hwif->getMasterVolume(volume);
462}
463
464#ifdef QCOM_FM_ENABLED
465static 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);
510    uint8_t channelCount = popcount(config->channel_mask);
511    return qadev->hwif->getInputBufferSize(config->sample_rate, config->format, channelCount);
512}
513
514#ifdef QCOM_TUNNEL_LPA_ENABLED
515static 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                                   const char *address __unused)
559{
560    struct qcom_audio_device *qadev = to_ladev(dev);
561    status_t status;
562    struct qcom_stream_out *out;
563    int ret;
564
565    out = (struct qcom_stream_out *)calloc(1, sizeof(*out));
566    if (!out)
567        return -ENOMEM;
568
569    devices = convert_audio_device(devices, HAL_API_REV_2_0, HAL_API_REV_1_0);
570    status = static_cast<audio_output_flags_t> (flags);
571
572    out->qcom_out = qadev->hwif->openOutputStream(devices,
573                                                    (int *)&config->format,
574                                                    &config->channel_mask,
575                                                    &config->sample_rate,
576                                                    &status);
577    if (!out->qcom_out) {
578        ret = status;
579        goto err_open;
580    }
581
582    out->stream.common.get_sample_rate = out_get_sample_rate;
583    out->stream.common.set_sample_rate = out_set_sample_rate;
584    out->stream.common.get_buffer_size = out_get_buffer_size;
585    out->stream.common.get_channels = out_get_channels;
586    out->stream.common.get_format = out_get_format;
587    out->stream.common.set_format = out_set_format;
588    out->stream.common.standby = out_standby;
589    out->stream.common.dump = out_dump;
590    out->stream.common.set_parameters = out_set_parameters;
591    out->stream.common.get_parameters = out_get_parameters;
592    out->stream.common.add_audio_effect = out_add_audio_effect;
593    out->stream.common.remove_audio_effect = out_remove_audio_effect;
594    out->stream.get_latency = out_get_latency;
595    out->stream.set_volume = out_set_volume;
596    out->stream.write = out_write;
597    out->stream.get_render_position = out_get_render_position;
598    out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
599
600    *stream_out = &out->stream;
601    return 0;
602
603err_open:
604    free(out);
605    *stream_out = NULL;
606    return ret;
607}
608
609static void adev_close_output_stream(struct audio_hw_device *dev,
610                                     struct audio_stream_out* stream)
611{
612    struct qcom_audio_device *qadev = to_ladev(dev);
613    struct qcom_stream_out *out = reinterpret_cast<struct qcom_stream_out *>(stream);
614
615    qadev->hwif->closeOutputStream(out->qcom_out);
616    free(out);
617}
618
619/** This method creates and opens the audio hardware input stream */
620static int adev_open_input_stream(struct audio_hw_device *dev,
621                                  audio_io_handle_t handle,
622                                  audio_devices_t devices,
623                                  audio_config *config,
624                                  audio_stream_in **stream_in,
625                                  audio_input_flags_t flags __unused,
626                                  const char *address __unused,
627                                  audio_source_t source __unused)
628{
629    struct qcom_audio_device *qadev = to_ladev(dev);
630    status_t status;
631    struct qcom_stream_in *in;
632    int ret;
633
634    in = (struct qcom_stream_in *)calloc(1, sizeof(*in));
635    if (!in)
636        return -ENOMEM;
637
638    devices = convert_audio_device(devices, HAL_API_REV_2_0, HAL_API_REV_1_0);
639
640    in->qcom_in = qadev->hwif->openInputStream(devices, (int *)&config->format,
641                                    &config->channel_mask,
642                                    &config->sample_rate,
643                                    &status,
644                                    (AudioSystem::audio_in_acoustics)0);
645    if (!in->qcom_in) {
646        ret = status;
647        goto err_open;
648    }
649
650    in->stream.common.get_sample_rate = in_get_sample_rate;
651    in->stream.common.set_sample_rate = in_set_sample_rate;
652    in->stream.common.get_buffer_size = in_get_buffer_size;
653    in->stream.common.get_channels = in_get_channels;
654    in->stream.common.get_format = in_get_format;
655    in->stream.common.set_format = in_set_format;
656    in->stream.common.standby = in_standby;
657    in->stream.common.dump = in_dump;
658    in->stream.common.set_parameters = in_set_parameters;
659    in->stream.common.get_parameters = in_get_parameters;
660    in->stream.common.add_audio_effect = in_add_audio_effect;
661    in->stream.common.remove_audio_effect = in_remove_audio_effect;
662    in->stream.set_gain = in_set_gain;
663    in->stream.read = in_read;
664    in->stream.get_input_frames_lost = in_get_input_frames_lost;
665
666    *stream_in = &in->stream;
667    return 0;
668
669err_open:
670    free(in);
671    *stream_in = NULL;
672    return ret;
673}
674
675static void adev_close_input_stream(struct audio_hw_device *dev,
676                               struct audio_stream_in *stream)
677{
678    struct qcom_audio_device *qadev = to_ladev(dev);
679    struct qcom_stream_in *in =
680        reinterpret_cast<struct qcom_stream_in *>(stream);
681
682    qadev->hwif->closeInputStream(in->qcom_in);
683    free(in);
684}
685
686static int adev_dump(const struct audio_hw_device *dev, int fd)
687{
688    const struct qcom_audio_device *qadev = to_cladev(dev);
689    Vector<String16> args;
690
691    return qadev->hwif->dumpState(fd, args);
692}
693
694static int qcom_adev_close(hw_device_t* device)
695{
696    struct audio_hw_device *hwdev =
697                        reinterpret_cast<struct audio_hw_device *>(device);
698    struct qcom_audio_device *qadev = to_ladev(hwdev);
699
700    if (!qadev)
701        return 0;
702
703    if (qadev->hwif)
704        delete qadev->hwif;
705
706    free(qadev);
707    return 0;
708}
709
710static int qcom_adev_open(const hw_module_t* module, const char* name,
711                            hw_device_t** device)
712{
713    struct qcom_audio_device *qadev;
714    int ret;
715
716    if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
717        return -EINVAL;
718
719    qadev = (struct qcom_audio_device *)calloc(1, sizeof(*qadev));
720    if (!qadev)
721        return -ENOMEM;
722
723    qadev->device.common.tag = HARDWARE_DEVICE_TAG;
724    qadev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
725    qadev->device.common.module = const_cast<hw_module_t*>(module);
726    qadev->device.common.close = qcom_adev_close;
727
728    qadev->device.init_check = adev_init_check;
729    qadev->device.set_voice_volume = adev_set_voice_volume;
730    qadev->device.set_master_volume = adev_set_master_volume;
731    qadev->device.get_master_volume = adev_get_master_volume;
732#ifdef QCOM_FM_ENABLED
733    qadev->device.set_fm_volume = adev_set_fm_volume;
734#endif
735    qadev->device.set_mode = adev_set_mode;
736    qadev->device.set_mic_mute = adev_set_mic_mute;
737    qadev->device.get_mic_mute = adev_get_mic_mute;
738    qadev->device.set_parameters = adev_set_parameters;
739    qadev->device.get_parameters = adev_get_parameters;
740    qadev->device.get_input_buffer_size = adev_get_input_buffer_size;
741    qadev->device.open_output_stream = adev_open_output_stream;
742#ifdef QCOM_TUNNEL_LPA_ENABLED
743    qadev->device.open_output_session = adev_open_output_session;
744#endif
745    qadev->device.close_output_stream = adev_close_output_stream;
746    qadev->device.open_input_stream = adev_open_input_stream;
747    qadev->device.close_input_stream = adev_close_input_stream;
748    qadev->device.dump = adev_dump;
749
750    qadev->hwif = createAudioHardware();
751    if (!qadev->hwif) {
752        ret = -EIO;
753        goto err_create_audio_hw;
754    }
755
756    *device = &qadev->device.common;
757
758    return 0;
759
760err_create_audio_hw:
761    free(qadev);
762    return ret;
763}
764
765static struct hw_module_methods_t qcom_audio_module_methods = {
766        open: qcom_adev_open
767};
768
769struct qcom_audio_module HAL_MODULE_INFO_SYM = {
770    module: {
771        common: {
772            tag: HARDWARE_MODULE_TAG,
773            module_api_version: AUDIO_MODULE_API_VERSION_0_1,
774            hal_api_version: HARDWARE_HAL_API_VERSION,
775            id: AUDIO_HARDWARE_MODULE_ID,
776            name: "QCOM Audio HW HAL",
777            author: "Code Aurora Forum",
778            methods: &qcom_audio_module_methods,
779            dso : NULL,
780            reserved : {0},
781        },
782    },
783};
784
785}; // extern "C"
786
787}; // namespace android_audio_legacy
788