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 
21 typedef struct _RENDER_DATA_ {
22     struct AlsaMixerCtlElement ctrlLeftVolume;
23     struct AlsaMixerCtlElement ctrlRightVolume;
24     long tempVolume;
25 }RenderData;
26 
RenderInitImpl(struct AlsaRender *renderIns)27 static 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 
RenderSelectSceneImpl(struct AlsaRender *renderIns, enum AudioPortPin descPins, const struct PathDeviceInfo *deviceInfo)51 static 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 
RenderGetVolThresholdImpl(struct AlsaRender *renderIns, long *volMin, long *volMax)58 static 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 
RenderGetVolumeImpl(struct AlsaRender *renderIns, long *volume)79 static 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 
RenderSetVolumeImpl(struct AlsaRender *renderIns, long volume)104 static 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 
RenderGetMuteImpl(struct AlsaRender *renderIns)126 static bool RenderGetMuteImpl(struct AlsaRender *renderIns)
127 {
128     return renderIns->muteState;
129 }
130 
RenderSetMuteImpl(struct AlsaRender *renderIns, bool muteFlag)131 static 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 
RenderStartImpl(struct AlsaRender *renderIns)162 static 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 
RenderStopImpl(struct AlsaRender *renderIns)191 static 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 
RenderGetGainThresholdImpl(struct AlsaRender *renderIns, float *gainMin, float *gainMax)216 static 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 
RenderGetGainImpl(struct AlsaRender *renderIns, float *volume)222 static int32_t RenderGetGainImpl(struct AlsaRender *renderIns, float *volume)
223 {
224     AUDIO_FUNC_LOGI("Not support gain operation");
225     return HDF_SUCCESS;
226 }
227 
RenderSetGainImpl(struct AlsaRender *renderIns, float volume)228 static int32_t RenderSetGainImpl(struct AlsaRender *renderIns, float volume)
229 {
230     AUDIO_FUNC_LOGI("Not support gain operation");
231     return HDF_SUCCESS;
232 }
233 
RenderGetChannelModeImpl(struct AlsaRender *renderIns, enum AudioChannelMode *mode)234 static int32_t RenderGetChannelModeImpl(struct AlsaRender *renderIns, enum AudioChannelMode *mode)
235 {
236     return HDF_SUCCESS;
237 }
238 
RenderSetChannelModeImpl(struct AlsaRender *renderIns, enum AudioChannelMode mode)239 static int32_t RenderSetChannelModeImpl(struct AlsaRender *renderIns, enum AudioChannelMode mode)
240 {
241     return HDF_SUCCESS;
242 }
243 
RenderOverrideFunc(struct AlsaRender *renderIns)244 int32_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