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{
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
568    devices = convert_audio_device(devices, HAL_API_REV_2_0, HAL_API_REV_1_0);
569    status = static_cast<audio_output_flags_t> (flags);
570
571    out->qcom_out = qadev->hwif->openOutputStream(devices,
572                                                    (int *)&config->format,
573                                                    &config->channel_mask,
574                                                    &config->sample_rate,
575                                                    &status);
576    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
634    devices = convert_audio_device(devices, HAL_API_REV_2_0, HAL_API_REV_1_0);
635
636    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);
641    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;
720    qadev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
721    qadev->device.common.module = const_cast<hw_module_t*>(module);
722    qadev->device.common.close = qcom_adev_close;
723
724    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;
728#ifdef QCOM_FM_ENABLED
729    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;
738#ifdef QCOM_TUNNEL_LPA_ENABLED
739    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,
769            module_api_version: AUDIO_MODULE_API_VERSION_0_1,
770            hal_api_version: HARDWARE_HAL_API_VERSION,
771            id: AUDIO_HARDWARE_MODULE_ID,
772            name: "QCOM Audio HW HAL",
773            author: "Code Aurora Forum",
774            methods: &qcom_audio_module_methods,
775            dso : NULL,
776            reserved : {0},
777        },
778    },
779};
780
781}; // extern "C"
782
783}; // namespace android_audio_legacy
784