1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "alsa_snd_render.h"
17#include "common.h"
18
19#define HDF_LOG_TAG HDF_AUDIO_HAL_RENDER
20
21typedef struct _RENDER_DATA_ {
22    struct AlsaMixerCtlElement ctrlLeftVolume;
23    struct AlsaMixerCtlElement ctrlRightVolume;
24    long tempVolume;
25}RenderData;
26
27static int32_t RenderInitImpl(struct AlsaRender *renderIns)
28{
29    if (renderIns->priData != NULL) {
30        return HDF_SUCCESS;
31    }
32    CHECK_NULL_PTR_RETURN_DEFAULT(renderIns);
33
34    RenderData *priData = (RenderData *)OsalMemCalloc(sizeof(RenderData));
35    if (priData == NULL) {
36        AUDIO_FUNC_LOGE("Failed to allocate memory!");
37        return HDF_FAILURE;
38    }
39
40    SndElementItemInit(&priData->ctrlLeftVolume);
41    SndElementItemInit(&priData->ctrlRightVolume);
42    priData->ctrlLeftVolume.numid = SND_NUMID_DACL_PLAYBACK_VOL;
43    priData->ctrlLeftVolume.name = SND_ELEM_DACL_PLAYBACK_VOL;
44    priData->ctrlRightVolume.numid = SND_NUMID_DACR_PLAYBACK_VOL;
45    priData->ctrlRightVolume.name = SND_ELEM_DACR_PLAYBACK_VOL;
46    RenderSetPriData(renderIns, (RenderPriData)priData);
47
48    return HDF_SUCCESS;
49}
50
51static int32_t RenderSelectSceneImpl(struct AlsaRender *renderIns, enum AudioPortPin descPins,
52    const struct PathDeviceInfo *deviceInfo)
53{
54    renderIns->descPins = descPins;
55    return HDF_SUCCESS;
56}
57
58static int32_t RenderGetVolThresholdImpl(struct AlsaRender *renderIns, long *volMin, long *volMax)
59{
60    int32_t ret;
61    long _volMin = 0;
62    long _volMax = 0;
63    struct AlsaSoundCard *cardIns = (struct AlsaSoundCard *)renderIns;
64    RenderData *priData = RenderGetPriData(renderIns);
65    CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
66    CHECK_NULL_PTR_RETURN_DEFAULT(priData);
67
68    ret = SndElementReadRange(cardIns, &priData->ctrlLeftVolume, &_volMin, &_volMax);
69    if (ret != HDF_SUCCESS) {
70        AUDIO_FUNC_LOGE("SndElementReadRange fail!");
71        return HDF_FAILURE;
72    }
73    *volMin = _volMin;
74    *volMax = _volMax;
75
76    return HDF_SUCCESS;
77}
78
79static int32_t RenderGetVolumeImpl(struct AlsaRender *renderIns, long *volume)
80{
81    int32_t ret;
82    long volLeft = 0;
83    long volRight = 0;
84    struct AlsaSoundCard *cardIns = (struct AlsaSoundCard *)renderIns;
85    RenderData *priData = RenderGetPriData(renderIns);
86    CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
87    CHECK_NULL_PTR_RETURN_DEFAULT(priData);
88
89    ret = SndElementReadInt(cardIns, &priData->ctrlLeftVolume, &volLeft);
90    if (ret != HDF_SUCCESS) {
91        AUDIO_FUNC_LOGE("Read left volume fail!");
92        return HDF_FAILURE;
93    }
94    ret = SndElementReadInt(cardIns, &priData->ctrlRightVolume, &volRight);
95    if (ret != HDF_SUCCESS) {
96        AUDIO_FUNC_LOGE("Read right volume fail!");
97        return HDF_FAILURE;
98    }
99    *volume = (volLeft + volRight) >> 1;
100
101    return HDF_SUCCESS;
102}
103
104static int32_t RenderSetVolumeImpl(struct AlsaRender *renderIns, long volume)
105{
106    int32_t ret;
107    struct AlsaSoundCard *cardIns = (struct AlsaSoundCard *)renderIns;
108    RenderData *priData = RenderGetPriData(renderIns);
109    CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
110    CHECK_NULL_PTR_RETURN_DEFAULT(priData);
111
112    ret = SndElementWriteInt(cardIns, &priData->ctrlLeftVolume, volume);
113    if (ret != HDF_SUCCESS) {
114        AUDIO_FUNC_LOGE("Write left volume fail!");
115        return HDF_FAILURE;
116    }
117    ret = SndElementWriteInt(cardIns, &priData->ctrlRightVolume, volume);
118    if (ret != HDF_SUCCESS) {
119        AUDIO_FUNC_LOGE("Write right volume fail!");
120        return HDF_FAILURE;
121    }
122
123    return HDF_SUCCESS;
124}
125
126static bool RenderGetMuteImpl(struct AlsaRender *renderIns)
127{
128    return renderIns->muteState;
129}
130
131static int32_t RenderSetMuteImpl(struct AlsaRender *renderIns, bool muteFlag)
132{
133    int32_t ret;
134    long vol, setVol;
135    RenderData *priData = RenderGetPriData(renderIns);
136    CHECK_NULL_PTR_RETURN_DEFAULT(renderIns);
137    CHECK_NULL_PTR_RETURN_DEFAULT(priData);
138
139    ret = renderIns->GetVolume(renderIns, &vol);
140    if (ret != HDF_SUCCESS) {
141        AUDIO_FUNC_LOGE("GetVolume failed!");
142        return HDF_FAILURE;
143    }
144
145    if (muteFlag) {
146        priData->tempVolume = vol;
147        setVol = 0;
148    } else {
149        setVol = priData->tempVolume;
150    }
151
152    renderIns->SetVolume(renderIns, setVol);
153    if (ret != HDF_SUCCESS) {
154        AUDIO_FUNC_LOGE("SetVolume failed!");
155        return HDF_FAILURE;
156    }
157    renderIns->muteState = muteFlag;
158
159    return HDF_SUCCESS;
160}
161
162static int32_t RenderStartImpl(struct AlsaRender *renderIns)
163{
164    int32_t ret;
165    struct AlsaMixerCtlElement elem;
166    struct AlsaSoundCard *cardIns = (struct AlsaSoundCard *)renderIns;
167
168    SndElementItemInit(&elem);
169    elem.numid = SND_NUMID_PLAYBACK_PATH;
170    elem.name = SND_ELEM_PLAYBACK_PATH;
171    switch (renderIns->descPins) {
172        case PIN_OUT_SPEAKER:
173            elem.value = SND_OUT_CARD_SPK_HP;
174            break;
175        case PIN_OUT_HEADSET:
176            elem.value = SND_OUT_CARD_HP;
177            break;
178        default:
179            elem.value = SND_OUT_CARD_SPK_HP;
180    }
181
182    ret = SndElementWrite(cardIns, &elem);
183    if (ret != HDF_SUCCESS) {
184        AUDIO_FUNC_LOGE("write render fail!");
185        return HDF_FAILURE;
186    }
187
188    return HDF_SUCCESS;
189}
190
191static int32_t RenderStopImpl(struct AlsaRender *renderIns)
192{
193    CHECK_NULL_PTR_RETURN_DEFAULT(renderIns);
194    int32_t ret;
195    struct AlsaMixerCtlElement elem;
196    struct AlsaSoundCard *cardIns = (struct AlsaSoundCard *)renderIns;
197    CHECK_NULL_PTR_RETURN_DEFAULT(cardIns);
198    CHECK_NULL_PTR_RETURN_DEFAULT(&renderIns->soundCard);
199
200    SndElementItemInit(&elem);
201    elem.numid = SND_NUMID_PLAYBACK_PATH;
202    elem.name = SND_ELEM_PLAYBACK_PATH;
203    elem.value = SND_OUT_CARD_OFF;
204    ret = SndElementWrite(cardIns, &elem);
205    if (ret != HDF_SUCCESS) {
206        AUDIO_FUNC_LOGE("write render fail!");
207        return HDF_FAILURE;
208    }
209
210    CHECK_NULL_PTR_RETURN_DEFAULT(renderIns->soundCard.pcmHandle);
211
212    snd_pcm_drain(renderIns->soundCard.pcmHandle);
213    return HDF_SUCCESS;
214}
215
216static int32_t RenderGetGainThresholdImpl(struct AlsaRender *renderIns, float *gainMin, float *gainMax)
217{
218    AUDIO_FUNC_LOGI("Not support gain operation");
219    return HDF_SUCCESS;
220}
221
222static int32_t RenderGetGainImpl(struct AlsaRender *renderIns, float *volume)
223{
224    AUDIO_FUNC_LOGI("Not support gain operation");
225    return HDF_SUCCESS;
226}
227
228static int32_t RenderSetGainImpl(struct AlsaRender *renderIns, float volume)
229{
230    AUDIO_FUNC_LOGI("Not support gain operation");
231    return HDF_SUCCESS;
232}
233
234static int32_t RenderGetChannelModeImpl(struct AlsaRender *renderIns, enum AudioChannelMode *mode)
235{
236    return HDF_SUCCESS;
237}
238
239static int32_t RenderSetChannelModeImpl(struct AlsaRender *renderIns, enum AudioChannelMode mode)
240{
241    return HDF_SUCCESS;
242}
243
244int32_t RenderOverrideFunc(struct AlsaRender *renderIns)
245{
246    struct AlsaSoundCard *cardIns = (struct AlsaSoundCard *)renderIns;
247
248    if (cardIns->cardType == SND_CARD_PRIMARY) {
249        renderIns->Init = RenderInitImpl;
250        renderIns->SelectScene = RenderSelectSceneImpl;
251        renderIns->Start = RenderStartImpl;
252        renderIns->Stop = RenderStopImpl;
253        renderIns->GetVolThreshold = RenderGetVolThresholdImpl;
254        renderIns->GetVolume = RenderGetVolumeImpl;
255        renderIns->SetVolume = RenderSetVolumeImpl;
256        renderIns->GetGainThreshold = RenderGetGainThresholdImpl;
257        renderIns->GetGain = RenderGetGainImpl;
258        renderIns->SetGain = RenderSetGainImpl;
259        renderIns->GetMute = RenderGetMuteImpl;
260        renderIns->SetMute = RenderSetMuteImpl;
261        renderIns->GetChannelMode = RenderGetChannelModeImpl;
262        renderIns->SetChannelMode = RenderSetChannelModeImpl;
263    }
264
265    return HDF_SUCCESS;
266}
267