14765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev/*
24765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * Copyright (C) 2011 The Android Open Source Project
34765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
44765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *
54765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * Licensed under the Apache License, Version 2.0 (the "License");
64765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * you may not use this file except in compliance with the License.
74765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * You may obtain a copy of the License at
84765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *
94765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *      http://www.apache.org/licenses/LICENSE-2.0
104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev *
114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * Unless required by applicable law or agreed to in writing, software
124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * distributed under the License is distributed on an "AS IS" BASIS,
134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * See the License for the specific language governing permissions and
154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev * limitations under the License.
164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev */
174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
189746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#define LOG_TAG "qcom_audio_hw_hal"
194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev//#define LOG_NDEBUG 0
204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <stdint.h>
224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <hardware/hardware.h>
244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <system/audio.h>
254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <hardware/audio.h>
264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <hardware_legacy/AudioHardwareInterface.h>
284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#include <hardware_legacy/AudioSystemLegacy.h>
294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevnamespace android_audio_legacy {
314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevextern "C" {
334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstruct qcom_audio_module {
354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct audio_module module;
364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev};
374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstruct qcom_audio_device {
394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct audio_hw_device device;
404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct AudioHardwareInterface *hwif;
424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev};
434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstruct qcom_stream_out {
454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct audio_stream_out stream;
464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    AudioStreamOut *qcom_out;
484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev};
494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstruct qcom_stream_in {
514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct audio_stream_in stream;
524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    AudioStreamIn *qcom_in;
544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev};
554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
567801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent
577801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurentenum {
587801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    HAL_API_REV_1_0,
597801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    HAL_API_REV_2_0,
607801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    HAL_API_REV_NUM
617801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent} hal_api_rev;
627801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent
637801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurentstatic uint32_t audio_device_conv_table[][HAL_API_REV_NUM] =
647801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent{
657801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        /* output devices */
667801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_OUT_EARPIECE, AUDIO_DEVICE_OUT_EARPIECE },
677801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_OUT_SPEAKER, AUDIO_DEVICE_OUT_SPEAKER },
687801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_OUT_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADSET },
697801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_WIRED_HEADPHONE },
707801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_OUT_BLUETOOTH_SCO, AUDIO_DEVICE_OUT_BLUETOOTH_SCO },
717801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET },
727801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT },
737801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP },
747801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES },
757801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER },
767801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_OUT_AUX_DIGITAL, AUDIO_DEVICE_OUT_AUX_DIGITAL },
777801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET },
787801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET },
797801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_OUT_DEFAULT, AUDIO_DEVICE_OUT_DEFAULT },
807801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent#ifdef QCOM_ANC_HEADSET_ENABLED
817801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_OUT_ANC_HEADSET, AUDIO_DEVICE_OUT_ANC_HEADSET },
827801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_OUT_ANC_HEADPHONE, AUDIO_DEVICE_OUT_ANC_HEADPHONE },
837801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent#endif
847801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent#ifdef QCOM_FM_ENABLED
857801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_OUT_FM, AUDIO_DEVICE_OUT_FM },
867801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent#endif
877801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent#ifdef QCOM_FM_TX_ENABLED
887801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_OUT_FM_TX, AUDIO_DEVICE_OUT_FM_TX },
897801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent#endif
907801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent#ifdef QCOM_VOIP_ENABLED
917801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_OUT_DIRECTOUTPUT, AUDIO_DEVICE_OUT_DIRECTOUTPUT },
927801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent#endif
937801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent#ifdef QCOM_PROXY_DEVICE_ENABLED
947801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_OUT_PROXY, AUDIO_DEVICE_OUT_PROXY },
957801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent#endif
967801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    /* input devices */
977801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_IN_COMMUNICATION, AUDIO_DEVICE_IN_COMMUNICATION },
987801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_IN_AMBIENT, AUDIO_DEVICE_IN_AMBIENT },
997801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_IN_BUILTIN_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC },
1007801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET },
1017801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_WIRED_HEADSET },
1027801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_IN_AUX_DIGITAL, AUDIO_DEVICE_IN_AUX_DIGITAL },
1037801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_IN_VOICE_CALL, AUDIO_DEVICE_IN_VOICE_CALL },
1047801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BACK_MIC },
1057801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_IN_DEFAULT, AUDIO_DEVICE_IN_DEFAULT },
1067801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent#ifdef QCOM_ANC_HEADSET_ENABLED
1077801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_IN_ANC_HEADSET, AUDIO_DEVICE_IN_ANC_HEADSET },
1087801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent#endif
1097801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent#ifdef QCOM_FM_ENABLED
1107801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_IN_FM_RX, AUDIO_DEVICE_IN_FM_RX },
1117801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    { AudioSystem::DEVICE_IN_FM_RX_A2DP, AUDIO_DEVICE_IN_FM_RX_A2DP },
1127801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent#endif
1137801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent};
1147801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent
1157801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurentstatic uint32_t convert_audio_device(uint32_t from_device, int from_rev, int to_rev)
1167801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent{
1177801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    const uint32_t k_num_devices = sizeof(audio_device_conv_table)/sizeof(uint32_t)/HAL_API_REV_NUM;
1187801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    uint32_t to_device =  AUDIO_DEVICE_NONE;
1197801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    uint32_t in_bit = 0;
1207801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent
1217801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    if (from_rev != HAL_API_REV_1_0) {
1227801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        in_bit = from_device & AUDIO_DEVICE_BIT_IN;
1237801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        from_device &= ~AUDIO_DEVICE_BIT_IN;
1247801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    }
1257801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent
1267801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    while (from_device) {
1277801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        uint32_t i = 31 - __builtin_clz(from_device);
1287801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        uint32_t cur_device = (1 << i) | in_bit;
1297801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent
1307801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        for (i = 0; i < k_num_devices; i++) {
1317801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent            if (audio_device_conv_table[i][from_rev] == cur_device) {
1327801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent                to_device |= audio_device_conv_table[i][to_rev];
1337801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent                break;
1347801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent            }
1357801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        }
1367801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        from_device &= ~cur_device;
1377801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    }
1387801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    return to_device;
1397801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent}
1407801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent
1414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev/** audio_stream_out implementation **/
1424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic uint32_t out_get_sample_rate(const struct audio_stream *stream)
1434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
1444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    const struct qcom_stream_out *out =
1454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<const struct qcom_stream_out *>(stream);
1464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return out->qcom_out->sampleRate();
1474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
1484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
1494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
1504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
1514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_stream_out *out =
1524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<struct qcom_stream_out *>(stream);
1534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
1544113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
1554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    /* TODO: implement this */
1564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return 0;
1574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
1584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
1594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic size_t out_get_buffer_size(const struct audio_stream *stream)
1604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
1614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    const struct qcom_stream_out *out =
1624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<const struct qcom_stream_out *>(stream);
1634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return out->qcom_out->bufferSize();
1644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
1654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
1664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
1674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
1684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    const struct qcom_stream_out *out =
1694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<const struct qcom_stream_out *>(stream);
1704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return out->qcom_out->channels();
1714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
1724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
1734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic audio_format_t out_get_format(const struct audio_stream *stream)
1744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
1754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    const struct qcom_stream_out *out =
1764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<const struct qcom_stream_out *>(stream);
1774113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    return (audio_format_t)out->qcom_out->format();
1784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
1794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
1804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int out_set_format(struct audio_stream *stream, audio_format_t format)
1814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
1824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_stream_out *out =
1834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<struct qcom_stream_out *>(stream);
1844113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
1854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    /* TODO: implement me */
1864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return 0;
1874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
1884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
1894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int out_standby(struct audio_stream *stream)
1904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
1914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_stream_out *out =
1924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<struct qcom_stream_out *>(stream);
1934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return out->qcom_out->standby();
1944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
1954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
1964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int out_dump(const struct audio_stream *stream, int fd)
1974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
1984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    const struct qcom_stream_out *out =
1994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<const struct qcom_stream_out *>(stream);
2004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    Vector<String16> args;
2014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return out->qcom_out->dump(fd, args);
2024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
2034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
2064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_stream_out *out =
2074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<struct qcom_stream_out *>(stream);
2087801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    int val;
2097801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    String8 s8 = String8(kvpairs);
2107801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    AudioParameter parms = AudioParameter(String8(kvpairs));
2117801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent
2127801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) {
2137801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        val = convert_audio_device(val, HAL_API_REV_2_0, HAL_API_REV_1_0);
2147801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING));
2157801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val);
2167801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        s8 = parms.toString();
2177801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    }
2187801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent
2197801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    return out->qcom_out->setParameters(s8);
2204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
2214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic char * out_get_parameters(const struct audio_stream *stream, const char *keys)
2234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
2244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    const struct qcom_stream_out *out =
2254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<const struct qcom_stream_out *>(stream);
2264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    String8 s8;
2277801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    int val;
2287801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent
2294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    s8 = out->qcom_out->getParameters(String8(keys));
2307801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent
2317801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    AudioParameter parms = AudioParameter(s8);
2327801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) {
2337801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        val = convert_audio_device(val, HAL_API_REV_1_0, HAL_API_REV_2_0);
2347801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING));
2357801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val);
2367801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        s8 = parms.toString();
2377801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    }
2387801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent
2394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return strdup(s8.string());
2404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
2414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic uint32_t out_get_latency(const struct audio_stream_out *stream)
2434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
2444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    const struct qcom_stream_out *out =
2454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<const struct qcom_stream_out *>(stream);
2464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return out->qcom_out->latency();
2474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
2484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int out_set_volume(struct audio_stream_out *stream, float left,
2504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                          float right)
2514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
2524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_stream_out *out =
2534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<struct qcom_stream_out *>(stream);
2544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return out->qcom_out->setVolume(left, right);
2554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
2564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
2584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                         size_t bytes)
2594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
2604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_stream_out *out =
2614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<struct qcom_stream_out *>(stream);
2624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return out->qcom_out->write(buffer, bytes);
2634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
2644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int out_get_render_position(const struct audio_stream_out *stream,
2664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                   uint32_t *dsp_frames)
2674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
2684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    const struct qcom_stream_out *out =
2694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<const struct qcom_stream_out *>(stream);
2704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return out->qcom_out->getRenderPosition(dsp_frames);
2714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
2724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
2744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
2754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return 0;
2764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
2774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
2794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
2804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return 0;
2814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
2824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int out_get_next_write_timestamp(const struct audio_stream_out *stream,
2844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                        int64_t *timestamp)
2854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
2869746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani    const struct qcom_stream_out *out =
2879746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani        reinterpret_cast<const struct qcom_stream_out *>(stream);
2889746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani    return out->qcom_out->getNextWriteTimestamp(timestamp);
2894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
2904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev/** audio_stream_in implementation **/
2924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic uint32_t in_get_sample_rate(const struct audio_stream *stream)
2934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
2944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    const struct qcom_stream_in *in =
2954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<const struct qcom_stream_in *>(stream);
2964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return in->qcom_in->sampleRate();
2974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
2984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
2994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
3004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
3014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_stream_in *in =
3024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<struct qcom_stream_in *>(stream);
3034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3044113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
3054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    /* TODO: implement this */
3064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return 0;
3074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
3084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic size_t in_get_buffer_size(const struct audio_stream *stream)
3104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
3114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    const struct qcom_stream_in *in =
3124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<const struct qcom_stream_in *>(stream);
3134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return in->qcom_in->bufferSize();
3144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
3154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
3174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
3184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    const struct qcom_stream_in *in =
3194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<const struct qcom_stream_in *>(stream);
3204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return in->qcom_in->channels();
3214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
3224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic audio_format_t in_get_format(const struct audio_stream *stream)
3244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
3254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    const struct qcom_stream_in *in =
3264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<const struct qcom_stream_in *>(stream);
3274113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    return (audio_format_t)in->qcom_in->format();
3284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
3294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int in_set_format(struct audio_stream *stream, audio_format_t format)
3314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
3324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_stream_in *in =
3334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<struct qcom_stream_in *>(stream);
3344113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
3354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    /* TODO: implement me */
3364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return 0;
3374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
3384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int in_standby(struct audio_stream *stream)
3404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
3414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_stream_in *in = reinterpret_cast<struct qcom_stream_in *>(stream);
3424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return in->qcom_in->standby();
3434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
3444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int in_dump(const struct audio_stream *stream, int fd)
3464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
3474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    const struct qcom_stream_in *in =
3484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<const struct qcom_stream_in *>(stream);
3494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    Vector<String16> args;
3504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return in->qcom_in->dump(fd, args);
3514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
3524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
3554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_stream_in *in =
3564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<struct qcom_stream_in *>(stream);
3577801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    int val;
3587801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    AudioParameter parms = AudioParameter(String8(kvpairs));
3597801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    String8 s8 = String8(kvpairs);
3607801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent
3617801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) {
3627801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        val = convert_audio_device(val, HAL_API_REV_2_0, HAL_API_REV_1_0);
3637801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING));
3647801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val);
3657801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        s8 = parms.toString();
3667801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    }
3677801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent
3687801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    return in->qcom_in->setParameters(s8);
3694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
3704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic char * in_get_parameters(const struct audio_stream *stream,
3724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                const char *keys)
3734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
3744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    const struct qcom_stream_in *in =
3754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<const struct qcom_stream_in *>(stream);
3764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    String8 s8;
3777801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    int val;
3787801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent
3794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    s8 = in->qcom_in->getParameters(String8(keys));
3807801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent
3817801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    AudioParameter parms = AudioParameter(s8);
3827801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) {
3837801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        val = convert_audio_device(val, HAL_API_REV_1_0, HAL_API_REV_2_0);
3847801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING));
3857801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val);
3867801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent        s8 = parms.toString();
3877801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    }
3887801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent
3894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return strdup(s8.string());
3904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
3914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int in_set_gain(struct audio_stream_in *stream, float gain)
3934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
3944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_stream_in *in =
3954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<struct qcom_stream_in *>(stream);
3964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return in->qcom_in->setGain(gain);
3974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
3984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
3994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic ssize_t in_read(struct audio_stream_in *stream, void* buffer,
4004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                       size_t bytes)
4014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
4024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_stream_in *in =
4034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<struct qcom_stream_in *>(stream);
4044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return in->qcom_in->read(buffer, bytes);
4054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
4064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
4084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
4094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_stream_in *in =
4104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<struct qcom_stream_in *>(stream);
4114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return in->qcom_in->getInputFramesLost();
4124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
4134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
4154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
4164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    const struct qcom_stream_in *in =
4174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<const struct qcom_stream_in *>(stream);
4184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return in->qcom_in->addAudioEffect(effect);
4194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
4204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
4224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
4234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    const struct qcom_stream_in *in =
4244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<const struct qcom_stream_in *>(stream);
4254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return in->qcom_in->removeAudioEffect(effect);
4264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
4274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev/** audio_hw_device implementation **/
4294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic inline struct qcom_audio_device * to_ladev(struct audio_hw_device *dev)
4304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
4314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return reinterpret_cast<struct qcom_audio_device *>(dev);
4324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
4334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic inline const struct qcom_audio_device * to_cladev(const struct audio_hw_device *dev)
4354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
4364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return reinterpret_cast<const struct qcom_audio_device *>(dev);
4374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
4384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int adev_init_check(const struct audio_hw_device *dev)
4404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
4414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    const struct qcom_audio_device *qadev = to_cladev(dev);
4424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return qadev->hwif->initCheck();
4444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
4454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
4484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_audio_device *qadev = to_ladev(dev);
4494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return qadev->hwif->setVoiceVolume(volume);
4504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
4514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int adev_set_master_volume(struct audio_hw_device *dev, float volume)
4534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
4544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_audio_device *qadev = to_ladev(dev);
4554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return qadev->hwif->setMasterVolume(volume);
4564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
4574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int adev_get_master_volume(struct audio_hw_device *dev, float *volume) {
4594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4604113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    struct qcom_audio_device *qadev = to_ladev(dev);
4614113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    return qadev->hwif->getMasterVolume(volume);
4624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
4639746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani
4649746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED
4654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int adev_set_fm_volume(struct audio_hw_device *dev, float volume)
4664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
4674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_audio_device *qadev = to_ladev(dev);
4684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return qadev->hwif->setFmVolume(volume);
4694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
4704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif
4714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
4744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_audio_device *qadev = to_ladev(dev);
4754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return qadev->hwif->setMode(mode);
4764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
4774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
4804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_audio_device *qadev = to_ladev(dev);
4814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return qadev->hwif->setMicMute(state);
4824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
4834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
4864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    const struct qcom_audio_device *qadev = to_cladev(dev);
4874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return qadev->hwif->getMicMute(state);
4884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
4894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
4924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_audio_device *qadev = to_ladev(dev);
4934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return qadev->hwif->setParameters(String8(kvpairs));
4944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
4954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
4964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic char * adev_get_parameters(const struct audio_hw_device *dev,
4974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                  const char *keys)
4984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
4994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    const struct qcom_audio_device *qadev = to_cladev(dev);
5004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    String8 s8;
5014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    s8 = qadev->hwif->getParameters(String8(keys));
5034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return strdup(s8.string());
5044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
5054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
5074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                         const struct audio_config *config)
5084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
5094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    const struct qcom_audio_device *qadev = to_cladev(dev);
510ed3c0fdecb72890240d52a8ba3b5ecd05331736aSathishKumar Mani    uint8_t channelCount = popcount(config->channel_mask);
511ed3c0fdecb72890240d52a8ba3b5ecd05331736aSathishKumar Mani    return qadev->hwif->getInputBufferSize(config->sample_rate, config->format, channelCount);
5124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
5134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5149746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_TUNNEL_LPA_ENABLED
5154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int adev_open_output_session(struct audio_hw_device *dev,
5164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                   uint32_t devices,
5174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                   int *format,
5184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                   int sessionId,
5194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                   uint32_t samplingRate,
5204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                   uint32_t channels,
5214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                   struct audio_stream_out **stream_out)
5224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
5234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_audio_device *qadev = to_ladev(dev);
5244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    status_t status;
5254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_stream_out *out;
5264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    int ret;
5274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out = (struct qcom_stream_out *)calloc(1, sizeof(*out));
5294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (!out)
5304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        return -ENOMEM;
5314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out->qcom_out = qadev->hwif->openOutputSession(devices, format,&status,sessionId,samplingRate,channels);
5334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (!out->qcom_out) {
5344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        ret = status;
5354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        goto err_open;
5364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
5374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5384765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out->stream.common.standby = out_standby;
5394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out->stream.common.set_parameters = out_set_parameters;
5404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out->stream.set_volume = out_set_volume;
5414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    *stream_out = &out->stream;
5434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return 0;
5444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malcheverr_open:
5464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    free(out);
5474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    *stream_out = NULL;
5484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return ret;
5494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
5504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif
5514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int adev_open_output_stream(struct audio_hw_device *dev,
5534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                   audio_io_handle_t handle,
5544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                   audio_devices_t devices,
5554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                   audio_output_flags_t flags,
5564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                   struct audio_config *config,
5574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                   struct audio_stream_out **stream_out)
5584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
5594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_audio_device *qadev = to_ladev(dev);
5604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    status_t status;
5614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_stream_out *out;
5624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    int ret;
5634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out = (struct qcom_stream_out *)calloc(1, sizeof(*out));
5654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (!out)
5664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        return -ENOMEM;
5674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5687801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    devices = convert_audio_device(devices, HAL_API_REV_2_0, HAL_API_REV_1_0);
5698861338c2a520669a870ee5f3e0c740e438c99bcSathishKumar Mani    status = static_cast<audio_output_flags_t> (flags);
5707801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent
5714113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    out->qcom_out = qadev->hwif->openOutputStream(devices,
5724113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                                                    (int *)&config->format,
5734113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                                                    &config->channel_mask,
5744113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                                                    &config->sample_rate,
5754113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                                                    &status);
5764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (!out->qcom_out) {
5774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        ret = status;
5784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        goto err_open;
5794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
5804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out->stream.common.get_sample_rate = out_get_sample_rate;
5824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out->stream.common.set_sample_rate = out_set_sample_rate;
5834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out->stream.common.get_buffer_size = out_get_buffer_size;
5844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out->stream.common.get_channels = out_get_channels;
5854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out->stream.common.get_format = out_get_format;
5864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out->stream.common.set_format = out_set_format;
5874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out->stream.common.standby = out_standby;
5884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out->stream.common.dump = out_dump;
5894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out->stream.common.set_parameters = out_set_parameters;
5904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out->stream.common.get_parameters = out_get_parameters;
5914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out->stream.common.add_audio_effect = out_add_audio_effect;
5924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out->stream.common.remove_audio_effect = out_remove_audio_effect;
5934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out->stream.get_latency = out_get_latency;
5944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out->stream.set_volume = out_set_volume;
5954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out->stream.write = out_write;
5964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out->stream.get_render_position = out_get_render_position;
5974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
5984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
5994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    *stream_out = &out->stream;
6004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return 0;
6014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
6024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malcheverr_open:
6034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    free(out);
6044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    *stream_out = NULL;
6054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return ret;
6064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
6074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
6084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic void adev_close_output_stream(struct audio_hw_device *dev,
6094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                     struct audio_stream_out* stream)
6104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
6114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_audio_device *qadev = to_ladev(dev);
6124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_stream_out *out = reinterpret_cast<struct qcom_stream_out *>(stream);
6134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
6144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->hwif->closeOutputStream(out->qcom_out);
6154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    free(out);
6164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
6174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
6184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev/** This method creates and opens the audio hardware input stream */
6194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int adev_open_input_stream(struct audio_hw_device *dev,
6204765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                  audio_io_handle_t handle,
6214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                  audio_devices_t devices,
6224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                  audio_config *config,
6234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                                  audio_stream_in **stream_in)
6244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
6254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_audio_device *qadev = to_ladev(dev);
6264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    status_t status;
6274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_stream_in *in;
6284765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    int ret;
6294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
6304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    in = (struct qcom_stream_in *)calloc(1, sizeof(*in));
6314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (!in)
6324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        return -ENOMEM;
6334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
6347801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    devices = convert_audio_device(devices, HAL_API_REV_2_0, HAL_API_REV_1_0);
6357801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent
6364113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev    in->qcom_in = qadev->hwif->openInputStream(devices, (int *)&config->format,
6374113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                                    &config->channel_mask,
6384113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                                    &config->sample_rate,
6394113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                                    &status,
6404113f34dfbaa8d82a5e1ef0265e916317161984dIliyan Malchev                                    (AudioSystem::audio_in_acoustics)0);
6414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (!in->qcom_in) {
6424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        ret = status;
6434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        goto err_open;
6444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
6454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
6464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    in->stream.common.get_sample_rate = in_get_sample_rate;
6474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    in->stream.common.set_sample_rate = in_set_sample_rate;
6484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    in->stream.common.get_buffer_size = in_get_buffer_size;
6494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    in->stream.common.get_channels = in_get_channels;
6504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    in->stream.common.get_format = in_get_format;
6514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    in->stream.common.set_format = in_set_format;
6524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    in->stream.common.standby = in_standby;
6534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    in->stream.common.dump = in_dump;
6544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    in->stream.common.set_parameters = in_set_parameters;
6554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    in->stream.common.get_parameters = in_get_parameters;
6564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    in->stream.common.add_audio_effect = in_add_audio_effect;
6574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    in->stream.common.remove_audio_effect = in_remove_audio_effect;
6584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    in->stream.set_gain = in_set_gain;
6594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    in->stream.read = in_read;
6604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    in->stream.get_input_frames_lost = in_get_input_frames_lost;
6614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
6624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    *stream_in = &in->stream;
6634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return 0;
6644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
6654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malcheverr_open:
6664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    free(in);
6674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    *stream_in = NULL;
6684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return ret;
6694765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
6704765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
6714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic void adev_close_input_stream(struct audio_hw_device *dev,
6724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                               struct audio_stream_in *stream)
6734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
6744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_audio_device *qadev = to_ladev(dev);
6754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_stream_in *in =
6764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        reinterpret_cast<struct qcom_stream_in *>(stream);
6774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
6784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->hwif->closeInputStream(in->qcom_in);
6794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    free(in);
6804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
6814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
6824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int adev_dump(const struct audio_hw_device *dev, int fd)
6834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
6844765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    const struct qcom_audio_device *qadev = to_cladev(dev);
6854765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    Vector<String16> args;
6864765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
6874765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return qadev->hwif->dumpState(fd, args);
6884765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
6894765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
6904765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int qcom_adev_close(hw_device_t* device)
6914765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
6924765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct audio_hw_device *hwdev =
6934765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                        reinterpret_cast<struct audio_hw_device *>(device);
6944765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_audio_device *qadev = to_ladev(hwdev);
6954765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
6964765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (!qadev)
6974765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        return 0;
6984765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
6994765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (qadev->hwif)
7004765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        delete qadev->hwif;
7014765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
7024765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    free(qadev);
7034765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return 0;
7044765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
7054765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
7064765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic int qcom_adev_open(const hw_module_t* module, const char* name,
7074765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev                            hw_device_t** device)
7084765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev{
7094765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    struct qcom_audio_device *qadev;
7104765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    int ret;
7114765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
7124765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
7134765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        return -EINVAL;
7144765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
7154765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev = (struct qcom_audio_device *)calloc(1, sizeof(*qadev));
7164765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (!qadev)
7174765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        return -ENOMEM;
7184765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
7194765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->device.common.tag = HARDWARE_DEVICE_TAG;
7207801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent    qadev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
7214765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->device.common.module = const_cast<hw_module_t*>(module);
7224765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->device.common.close = qcom_adev_close;
7234765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
7244765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->device.init_check = adev_init_check;
7254765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->device.set_voice_volume = adev_set_voice_volume;
7264765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->device.set_master_volume = adev_set_master_volume;
7274765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->device.get_master_volume = adev_get_master_volume;
7289746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_FM_ENABLED
7294765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->device.set_fm_volume = adev_set_fm_volume;
7304765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif
7314765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->device.set_mode = adev_set_mode;
7324765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->device.set_mic_mute = adev_set_mic_mute;
7334765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->device.get_mic_mute = adev_get_mic_mute;
7344765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->device.set_parameters = adev_set_parameters;
7354765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->device.get_parameters = adev_get_parameters;
7364765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->device.get_input_buffer_size = adev_get_input_buffer_size;
7374765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->device.open_output_stream = adev_open_output_stream;
7389746c4758b161e26eec92b1ef1ff1bf0ba0bd268Ajay Dudani#ifdef QCOM_TUNNEL_LPA_ENABLED
7394765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->device.open_output_session = adev_open_output_session;
7404765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev#endif
7414765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->device.close_output_stream = adev_close_output_stream;
7424765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->device.open_input_stream = adev_open_input_stream;
7434765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->device.close_input_stream = adev_close_input_stream;
7444765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->device.dump = adev_dump;
7454765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
7464765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    qadev->hwif = createAudioHardware();
7474765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    if (!qadev->hwif) {
7484765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        ret = -EIO;
7494765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        goto err_create_audio_hw;
7504765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    }
7514765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
7524765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    *device = &qadev->device.common;
7534765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
7544765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return 0;
7554765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
7564765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malcheverr_create_audio_hw:
7574765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    free(qadev);
7584765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    return ret;
7594765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}
7604765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
7614765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstatic struct hw_module_methods_t qcom_audio_module_methods = {
7624765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        open: qcom_adev_open
7634765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev};
7644765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
7654765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchevstruct qcom_audio_module HAL_MODULE_INFO_SYM = {
7664765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    module: {
7674765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        common: {
7684765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            tag: HARDWARE_MODULE_TAG,
7697801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent            module_api_version: AUDIO_MODULE_API_VERSION_0_1,
7707801df9b35653562139ddaaa5c29c61f0eddc92fEric Laurent            hal_api_version: HARDWARE_HAL_API_VERSION,
7714765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            id: AUDIO_HARDWARE_MODULE_ID,
7724765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            name: "QCOM Audio HW HAL",
7734765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            author: "Code Aurora Forum",
7744765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            methods: &qcom_audio_module_methods,
7754765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            dso : NULL,
7764765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev            reserved : {0},
7774765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev        },
7784765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev    },
7794765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev};
7804765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
7814765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}; // extern "C"
7824765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev
7834765c439491ddda3de658e62cc4a64d10e726b34Iliyan Malchev}; // namespace android_audio_legacy
784