1 /*
2 * Copyright (c) 2022 Unionman Technology 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 <linux/soundcard.h>
17 #include "sound/asound.h"
18
19 #include "hdf_log.h"
20 #include "tinyalsa/asoundlib.h"
21
22 #include "audio_interface_lib_render.h"
23
24 #define HDF_LOG_TAG HDI_AUDIO_R_ALSA
25
26 // treat hats.
27 #define PLEASURE_HATS
28
29 #define SOUND_CARD_ID (0)
30 #define SOUND_DEV_ID (1)
31
32 #define VOLUME_DEFAULT (50)
33
34 struct AlsaCtx {
35 struct pcm *pcmHandler;
36 struct pcm_config config;
37 struct mixer *mixerHandler;
38
39 int initFlag;
40 int renderRefCount;
41 int ctlRefCount;
42 int volume; // volume in db [ (volMax - volMin) / 2 * log10(Vol) + volMin]
43 int volMin;
44 int volMax;
45
46 float gain;
47 float gainMin;
48 float gainMax;
49
50 bool mute;
51 };
52
53 static struct AlsaCtx s_alsaCtx = {.initFlag = 0};
54
55 struct AlsaDevObject {
56 char serviceName[64];
57 struct AlsaCtx *pAlsaCtx;
58 };
59
ConvertFormatToAlsa(enum AudioFormat format)60 static enum pcm_format ConvertFormatToAlsa(enum AudioFormat format)
61 {
62 switch (format) {
63 case AUDIO_FORMAT_TYPE_PCM_8_BIT:
64 return PCM_FORMAT_S8;
65 case AUDIO_FORMAT_TYPE_PCM_16_BIT:
66 return PCM_FORMAT_S16_LE;
67 case AUDIO_FORMAT_TYPE_PCM_24_BIT:
68 return PCM_FORMAT_S24_LE;
69 case AUDIO_FORMAT_TYPE_PCM_32_BIT:
70 return PCM_FORMAT_S32_LE;
71 case AUDIO_FORMAT_TYPE_AAC_MAIN:
72 case AUDIO_FORMAT_TYPE_AAC_LC:
73 case AUDIO_FORMAT_TYPE_AAC_LD:
74 case AUDIO_FORMAT_TYPE_AAC_ELD:
75 case AUDIO_FORMAT_TYPE_AAC_HE_V1:
76 case AUDIO_FORMAT_TYPE_AAC_HE_V2:
77 case AUDIO_FORMAT_TYPE_G711A:
78 case AUDIO_FORMAT_TYPE_G711U:
79 case AUDIO_FORMAT_TYPE_G726:
80 default:
81 return PCM_FORMAT_INVALID;
82 }
83 }
84
MixerInit(struct mixer * mixer)85 static int32_t MixerInit(struct mixer *mixer)
86 {
87 int32_t ret = 0;
88
89 if (!mixer) {
90 HDF_LOGE("Error: mixer is NULL.");
91 return -1;
92 }
93
94 // config audio path
95 ret |= mixer_ctl_set_value(
96 mixer_get_ctl_by_name(mixer, "FRDDR_B SRC 1 EN Switch"), 0, 1);
97 ret |= mixer_ctl_set_enum_by_string(
98 mixer_get_ctl_by_name(mixer, "FRDDR_B SINK 1 SEL"), "OUT 1");
99 ret |= mixer_ctl_set_enum_by_string(
100 mixer_get_ctl_by_name(mixer, "TDMOUT_B SRC SEL"), "IN 1");
101
102 ret |= mixer_ctl_set_value(mixer_get_ctl_by_name(mixer, "TOHDMITX Switch"),
103 0, 1);
104 ret |= mixer_ctl_set_enum_by_string(
105 mixer_get_ctl_by_name(mixer, "TOHDMITX I2S SRC"), "I2S B");
106
107 ret |= mixer_ctl_set_value(
108 mixer_get_ctl_by_name(mixer, "TOACODEC OUT EN Switch"), 0, 1);
109 ret |= mixer_ctl_set_enum_by_string(
110 mixer_get_ctl_by_name(mixer, "TOACODEC SRC"), "I2S B");
111
112 // config volume
113 ret |= mixer_ctl_set_value(
114 mixer_get_ctl_by_name(mixer, "ACODEC Playback Volume"), 0, 255U);
115 ret |= mixer_ctl_set_value(
116 mixer_get_ctl_by_name(mixer, "ACODEC Playback Volume"), 1, 255U);
117 ret |= mixer_ctl_set_value(
118 mixer_get_ctl_by_name(mixer, "ACODEC Mute Ramp Switch"), 0, 1);
119 ret |= mixer_ctl_set_value(
120 mixer_get_ctl_by_name(mixer, "ACODEC Unmute Ramp Switch"), 0, 1);
121
122 ret |= mixer_ctl_set_value(
123 mixer_get_ctl_by_name(mixer, "TDMOUT_B Gain Enable Switch"), 0, 1);
124
125 return ret;
126 }
127
AlsaVolumeUpdate(struct AlsaCtx * aCtx)128 static int32_t AlsaVolumeUpdate(struct AlsaCtx *aCtx)
129 {
130 int32_t ret = 0;
131 int volumeSet = 0;
132
133 if (!aCtx->mixerHandler) {
134 return -1;
135 }
136
137 if (aCtx->mute) {
138 volumeSet = 0;
139 } else {
140 volumeSet = aCtx->volume * 255U /
141 (aCtx->volMax - aCtx->volMin); // need adjustment
142 }
143
144 ret |= mixer_ctl_set_value(
145 mixer_get_ctl_by_name(aCtx->mixerHandler, "TDMOUT_B Lane 0 Volume"), 0,
146 volumeSet);
147 ret |= mixer_ctl_set_value(
148 mixer_get_ctl_by_name(aCtx->mixerHandler, "TDMOUT_B Lane 0 Volume"), 1,
149 volumeSet);
150
151 HDF_LOGV("Set Volume: volume=%{public}d, mute=%{public}d, "
152 "volumeSet=%{public}d, ret=%{public}d",
153 aCtx->volume, aCtx->mute, volumeSet, ret);
154
155 return ret;
156 }
157
AlsaCtxInstanceGet(void)158 static struct AlsaCtx *AlsaCtxInstanceGet(void)
159 {
160 if (!s_alsaCtx.initFlag) {
161 memset_s(&s_alsaCtx, sizeof(s_alsaCtx), 0, sizeof(s_alsaCtx));
162 s_alsaCtx.renderRefCount = 0;
163 s_alsaCtx.pcmHandler = NULL;
164 s_alsaCtx.volMax = 100U;
165 s_alsaCtx.volMin = 0;
166 s_alsaCtx.volume = VOLUME_DEFAULT;
167 s_alsaCtx.gainMin = 0.0;
168 s_alsaCtx.gainMax = 15.0f;
169 s_alsaCtx.gain = s_alsaCtx.gainMax;
170 s_alsaCtx.mute = false;
171 s_alsaCtx.mixerHandler = mixer_open(SOUND_CARD_ID);
172 MixerInit(s_alsaCtx.mixerHandler);
173 s_alsaCtx.initFlag = 1;
174
175 AlsaVolumeUpdate(&s_alsaCtx);
176 }
177
178 return &s_alsaCtx;
179 }
180
AlsaOpen(struct AlsaCtx * aCtx)181 static int AlsaOpen(struct AlsaCtx *aCtx)
182 {
183 int sound_card_id = SOUND_CARD_ID;
184 int sound_dev_id = SOUND_DEV_ID;
185
186 HDF_LOGI(
187 "%{public}s() rate=%{public}d, channels=%{public}d, format=%{public}d",
188 __func__, aCtx->config.rate, aCtx->config.channels,
189 aCtx->config.format);
190
191 if (aCtx->pcmHandler) {
192 HDF_LOGW("Alsa is opened already.");
193 return 0;
194 }
195
196 struct pcm_config config;
197 (void)memcpy_s(&config, sizeof(config), &aCtx->config, sizeof(config));
198 struct pcm *pcm = pcm_open(sound_card_id, sound_dev_id, PCM_OUT, &config);
199 if (!pcm_is_ready(pcm)) {
200 HDF_LOGE("Error: %{public}s() Cannot open pcm_out(card %{public}d, "
201 "device %{public}d): %{public}s",
202 __func__, sound_card_id, sound_dev_id, pcm_get_error(pcm));
203 pcm_close(pcm);
204
205 return -1;
206 }
207
208 aCtx->pcmHandler = pcm;
209
210 HDF_LOGI("Open Alsa Success.");
211
212 return 0;
213 }
214
AlsaClose(struct AlsaCtx * aCtx)215 static int AlsaClose(struct AlsaCtx *aCtx)
216 {
217 if (aCtx->pcmHandler) {
218 pcm_close(aCtx->pcmHandler);
219 aCtx->pcmHandler = NULL;
220 }
221
222 HDF_LOGI("Close Alsa Success.");
223
224 return 0;
225 }
226
CheckHwParam(struct AudioHwRenderParam * handleData)227 static int CheckHwParam(struct AudioHwRenderParam *handleData)
228 {
229 if (handleData == NULL) {
230 HDF_LOGE("Error: handleData is NULL!");
231 return -1;
232 }
233
234 if (handleData->frameRenderMode.attrs.channelCount != 1U &&
235 handleData->frameRenderMode.attrs.channelCount != 2U) {
236 HDF_LOGE("Error: Unsupported channel count: %{public}d",
237 handleData->frameRenderMode.attrs.channelCount);
238 return -1;
239 }
240
241 if (handleData->frameRenderMode.attrs.format == AUDIO_FORMAT_TYPE_PCM_8_BIT &&
242 handleData->frameRenderMode.attrs.sampleRate == 8000U)
243 return -1;
244
245 if (handleData->frameRenderMode.attrs.format == AUDIO_FORMAT_TYPE_PCM_32_BIT &&
246 handleData->frameRenderMode.attrs.sampleRate == 11025U)
247 return -1;
248
249 return 0;
250 }
251
AlsaConfig(struct AlsaCtx * aCtx,struct AudioHwRenderParam * handleData)252 static int AlsaConfig(struct AlsaCtx *aCtx, struct AudioHwRenderParam *handleData)
253 {
254 struct pcm_config config;
255 enum pcm_format format;
256
257 if (CheckHwParam(handleData)) {
258 return -1;
259 }
260
261 format = ConvertFormatToAlsa(handleData->frameRenderMode.attrs.format);
262 if (PCM_FORMAT_INVALID == format) {
263 HDF_LOGE("Error: Unsupported format: %{public}d", handleData->frameRenderMode.attrs.format);
264 return -1;
265 }
266
267 memset_s(&config, sizeof(config), 0, sizeof(config));
268
269 config.channels = handleData->frameRenderMode.attrs.channelCount;
270 config.rate = handleData->frameRenderMode.attrs.sampleRate;
271 config.format = format;
272 config.period_count = handleData->frameRenderMode.periodCount; // 6
273 config.period_size = handleData->frameRenderMode.periodSize; // 512
274 config.start_threshold = handleData->frameRenderMode.attrs.startThreshold;
275 config.stop_threshold = handleData->frameRenderMode.attrs.stopThreshold;
276 config.silence_threshold = handleData->frameRenderMode.attrs.silenceThreshold;
277
278 #ifdef PLEASURE_HATS
279 if (config.rate == 12000) {
280 config.rate = 8000;
281 } else if (config.rate == 24000) {
282 config.rate = 22050;
283 }
284 #endif
285
286 HDF_LOGV("DUMP Alsa Config 1#: channels=%{public}d, rate=%{public}d, "
287 "format=%{public}d, period_count=%{public}d, period_size=%{public}d",
288 config.channels, config.rate, config.format, config.period_count, config.period_size);
289
290 HDF_LOGV("DUMP Alsa OldConfig 1#: channels=%{public}d, rate=%{public}d, "
291 "format=%{public}d, period_count=%{public}d, period_size=%{public}d",
292 aCtx->config.channels, aCtx->config.rate, aCtx->config.format,
293 aCtx->config.period_count, aCtx->config.period_size);
294
295 if (aCtx->pcmHandler && !memcmp(&config, &aCtx->config, sizeof(config))) {
296 HDF_LOGW("Warn: Same Audio Hw config. No need to change.");
297 return 0;
298 }
299
300 (void)memcpy_s(&aCtx->config, sizeof(aCtx->config), &config, sizeof(config));
301
302 AlsaClose(aCtx);
303 if (AlsaOpen(aCtx) < 0) {
304 HDF_LOGE("Error: in %{public}s, AlsaOpen() failed.", __func__);
305 return -1;
306 }
307
308 HDF_LOGV("Config Alsa SUCCESS.");
309
310 return 0;
311 }
312
DoCtlRenderSetVolume(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)313 static int32_t DoCtlRenderSetVolume(const struct DevHandle *handle, int cmdId,
314 struct AudioHwRenderParam *handleData)
315 {
316 struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
317
318 HDF_LOGV("INFO: enter %{public}s(). volume=%{public}f", __func__,
319 handleData->renderMode.ctlParam.volume);
320
321 int volume = (int)handleData->renderMode.ctlParam.volume;
322
323 if (volume < aCtx->volMin || volume > aCtx->volMax) {
324 HDF_LOGE("Error: Invalid volume: %{public}d", volume);
325 return HDF_FAILURE;
326 }
327
328 aCtx->volume = volume;
329
330 return AlsaVolumeUpdate(aCtx);
331 }
332
DoCtlRenderGetVolume(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)333 static int32_t DoCtlRenderGetVolume(const struct DevHandle *handle, int cmdId,
334 struct AudioHwRenderParam *handleData)
335 {
336 struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
337
338 handleData->renderMode.ctlParam.volume = aCtx->volume;
339
340 return HDF_SUCCESS;
341 }
342
DoCtlRenderSetPauseStu(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)343 static int32_t DoCtlRenderSetPauseStu(const struct DevHandle *handle, int cmdId,
344 struct AudioHwRenderParam *handleData)
345 {
346 struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
347
348 if (!((struct AlsaCtx *)aCtx)->pcmHandler) {
349 HDF_LOGE("Error: in %{public}s, Pcm is not opened!", __func__);
350 return HDF_FAILURE;
351 }
352
353 if (pcm_ioctl(aCtx->pcmHandler, SNDRV_PCM_IOCTL_PAUSE,
354 handleData->renderMode.ctlParam.pause ? 1 : 0) < 0) {
355 HDF_LOGE("Error: pcm_ioctl(SNDRV_PCM_IOCTL_PAUSE) failed: %{public}s\n",
356 pcm_get_error(aCtx->pcmHandler));
357 return HDF_FAILURE;
358 }
359
360 return HDF_SUCCESS;
361 }
362
DoCtlRenderSetMuteStu(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)363 static int32_t DoCtlRenderSetMuteStu(const struct DevHandle *handle, int cmdId,
364 struct AudioHwRenderParam *handleData)
365 {
366 struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
367
368 aCtx->mute = handleData->renderMode.ctlParam.mute;
369
370 return AlsaVolumeUpdate(aCtx);
371 }
372
DoCtlRenderGetMuteStu(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)373 static int32_t DoCtlRenderGetMuteStu(const struct DevHandle *handle, int cmdId,
374 struct AudioHwRenderParam *handleData)
375 {
376 struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
377
378 handleData->renderMode.ctlParam.mute = aCtx->mute;
379
380 return HDF_SUCCESS;
381 }
382
DoCtlRenderSetGainStu(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)383 static int32_t DoCtlRenderSetGainStu(const struct DevHandle *handle, int cmdId,
384 struct AudioHwRenderParam *handleData)
385 {
386 struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
387
388 float gain = handleData->renderMode.ctlParam.audioGain.gain;
389
390 if (gain < aCtx->gainMin || gain > aCtx->gainMax) {
391 HDF_LOGE("Error: Invalid gain: %{public}f", gain);
392 return HDF_FAILURE;
393 }
394
395 aCtx->gain = gain;
396
397 return HDF_SUCCESS;
398 }
399
DoCtlRenderGetGainStu(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)400 static int32_t DoCtlRenderGetGainStu(const struct DevHandle *handle, int cmdId,
401 struct AudioHwRenderParam *handleData)
402 {
403 struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
404
405 handleData->renderMode.ctlParam.audioGain.gain = aCtx->gain;
406
407 return HDF_SUCCESS;
408 }
409
DoCtlRenderSceneSelect(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)410 static int32_t DoCtlRenderSceneSelect(const struct DevHandle *handle, int cmdId,
411 struct AudioHwRenderParam *handleData)
412 {
413 HDF_LOGV("INFO: enter %{public}s(). portId=%{public}d", __func__,
414 handleData->renderMode.hwInfo.deviceDescript.portId);
415
416 HDF_LOGV("DUMP AudioHwRenderParam: %{public}d, %{public}d, %{public}d, "
417 "%{public}d, %{public}d, %{public}d, "
418 "%{public}d, %{public}d",
419 handleData->frameRenderMode.attrs.channelCount,
420 handleData->frameRenderMode.attrs.sampleRate,
421 handleData->frameRenderMode.attrs.format,
422 handleData->frameRenderMode.periodCount,
423 handleData->frameRenderMode.periodSize,
424 handleData->frameRenderMode.attrs.startThreshold,
425 handleData->frameRenderMode.attrs.stopThreshold,
426 handleData->frameRenderMode.attrs.silenceThreshold);
427
428 return HDF_SUCCESS;
429 }
430
DoCtlRenderSceneGetGainThreshold(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)431 static int32_t DoCtlRenderSceneGetGainThreshold(const struct DevHandle *handle, int cmdId,
432 struct AudioHwRenderParam *handleData)
433 {
434 struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
435
436 handleData->renderMode.ctlParam.audioGain.gainMax = aCtx->gainMax;
437 handleData->renderMode.ctlParam.audioGain.gainMin = aCtx->gainMin;
438
439 return HDF_SUCCESS;
440 }
441
DoCtlRenderGetVolThreshold(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)442 static int32_t DoCtlRenderGetVolThreshold(const struct DevHandle *handle,
443 int cmdId,
444 struct AudioHwRenderParam *handleData)
445 {
446 struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
447
448 handleData->renderMode.ctlParam.volThreshold.volMax = aCtx->volMax;
449 handleData->renderMode.ctlParam.volThreshold.volMin = aCtx->volMin;
450
451 return HDF_SUCCESS;
452 }
453
DoCtlRenderSetChannelMode(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)454 static int32_t DoCtlRenderSetChannelMode(const struct DevHandle *handle,
455 int cmdId,
456 struct AudioHwRenderParam *handleData)
457 {
458 return HDF_SUCCESS;
459 }
460
DoCtlRenderGetChannelMode(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)461 static int32_t DoCtlRenderGetChannelMode(const struct DevHandle *handle,
462 int cmdId,
463 struct AudioHwRenderParam *handleData)
464 {
465 handleData->frameRenderMode.mode = AUDIO_CHANNEL_NORMAL;
466 return HDF_SUCCESS;
467 }
468
DoCtlRenderSetAcodecMode(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)469 static int32_t DoCtlRenderSetAcodecMode(const struct DevHandle *handle,
470 int cmdId,
471 struct AudioHwRenderParam *handleData)
472 {
473 return HDF_SUCCESS;
474 }
475
HandleCtlRenderCmd(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)476 static int32_t HandleCtlRenderCmd(const struct DevHandle *handle, int cmdId,
477 struct AudioHwRenderParam *handleData)
478 {
479 switch (cmdId) {
480 case AUDIODRV_CTL_IOCTL_ELEM_READ:
481 return DoCtlRenderGetVolume(handle, cmdId, handleData);
482 case AUDIODRV_CTL_IOCTL_ELEM_WRITE:
483 return DoCtlRenderSetVolume(handle, cmdId, handleData);
484 case AUDIODRV_CTL_IOCTL_MUTE_READ:
485 return DoCtlRenderGetMuteStu(handle, cmdId, handleData);
486 case AUDIODRV_CTL_IOCTL_MUTE_WRITE:
487 return DoCtlRenderSetMuteStu(handle, cmdId, handleData);
488 case AUDIODRV_CTL_IOCTL_CHANNEL_MODE_READ:
489 return DoCtlRenderGetChannelMode(handle, cmdId, handleData);
490 case AUDIODRV_CTL_IOCTL_CHANNEL_MODE_WRITE:
491 return DoCtlRenderSetChannelMode(handle, cmdId, handleData);
492 case AUDIODRV_CTL_IOCTL_GAIN_WRITE:
493 return DoCtlRenderSetGainStu(handle, cmdId, handleData);
494 case AUDIODRV_CTL_IOCTL_GAIN_READ:
495 return DoCtlRenderGetGainStu(handle, cmdId, handleData);
496 case AUDIODRV_CTL_IOCTL_SCENESELECT_WRITE:
497 return DoCtlRenderSceneSelect(handle, cmdId, handleData);
498 case AUDIODRV_CTL_IOCTL_GAINTHRESHOLD_READ:
499 return DoCtlRenderSceneGetGainThreshold(handle, cmdId, handleData);
500 case AUDIODRV_CTL_IOCTL_ACODEC_CHANGE_IN:
501 case AUDIODRV_CTL_IOCTL_ACODEC_CHANGE_OUT:
502 return DoCtlRenderSetAcodecMode(handle, cmdId, handleData);
503 case AUDIODRV_CTL_IOCTL_VOL_THRESHOLD_READ:
504 return DoCtlRenderGetVolThreshold(handle, cmdId, handleData);
505 default:
506 HDF_LOGE("Error: Output Mode not support!");
507 break;
508 }
509
510 return HDF_FAILURE;
511 }
512
DoOutputRenderHwParams(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)513 static int32_t DoOutputRenderHwParams(const struct DevHandle *handle, int cmdId,
514 struct AudioHwRenderParam *handleData)
515 {
516 struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
517
518 HDF_LOGV("INFO: enter %{public}s()", __func__);
519
520 if (AlsaConfig(aCtx, handleData) < 0) {
521 HDF_LOGE("Error: in %{public}s, AlsaConfig() failed.", __func__);
522 return HDF_FAILURE;
523 }
524
525 return HDF_SUCCESS;
526 }
527
DoOutputRenderWrite(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)528 static int32_t DoOutputRenderWrite(const struct DevHandle *handle, int cmdId,
529 struct AudioHwRenderParam *handleData)
530 {
531 struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
532
533 if (!((struct AlsaCtx *)aCtx)->pcmHandler) {
534 HDF_LOGE("Error: in %{public}s, Pcm is not opened!", __func__);
535 return HDF_FAILURE;
536 }
537
538 if (!handleData->frameRenderMode.buffer ||
539 handleData->frameRenderMode.bufferSize == 0) {
540 HDF_LOGE("Error: %{public}s, empty buf", __func__);
541 return HDF_FAILURE;
542 }
543
544 if (pcm_write(aCtx->pcmHandler, handleData->frameRenderMode.buffer,
545 handleData->frameRenderMode.bufferSize) < 0) {
546 HDF_LOGE("Error: pcm_write() failed: %{public}s\n",
547 pcm_get_error(aCtx->pcmHandler));
548 return HDF_FAILURE;
549 }
550
551 return HDF_SUCCESS;
552 }
553
DoOutputRenderStartPrepare(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)554 static int32_t DoOutputRenderStartPrepare(const struct DevHandle *handle,
555 int cmdId,
556 struct AudioHwRenderParam *handleData)
557 {
558 struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
559
560 HDF_LOGV("INFO: enter %{public}s()", __func__);
561
562 AlsaOpen(aCtx);
563
564 if (!((struct AlsaCtx *)aCtx)->pcmHandler) {
565 HDF_LOGE("Error: in %{public}s, Pcm is not opened!", __func__);
566 return HDF_FAILURE;
567 }
568
569 // NOTE: depop here
570 int bufsize = aCtx->config.period_count * aCtx->config.period_size;
571 char *buf = calloc(1, bufsize);
572 if (buf) {
573 pcm_write(aCtx->pcmHandler, buf, bufsize);
574 free(buf);
575 }
576
577 usleep(10000);
578
579 return HDF_SUCCESS;
580 }
581
DoOutputRenderStop(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)582 static int32_t DoOutputRenderStop(const struct DevHandle *handle, int cmdId,
583 struct AudioHwRenderParam *handleData)
584 {
585 struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
586
587 HDF_LOGV("INFO: enter %{public}s()", __func__);
588
589 if (!((struct AlsaCtx *)aCtx)->pcmHandler) {
590 HDF_LOGE("Error: in %{public}s, Pcm is not opened!", __func__);
591 return HDF_FAILURE;
592 }
593
594 AlsaClose(aCtx);
595
596 return HDF_SUCCESS;
597 }
598
DoOutputRenderReqMmapBuffer(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)599 static int32_t DoOutputRenderReqMmapBuffer(const struct DevHandle *handle, int cmdId,
600 struct AudioHwRenderParam *handleData)
601 {
602 return HDF_SUCCESS;
603 }
604
DoOutputRenderGetMmapPosition(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)605 static int32_t DoOutputRenderGetMmapPosition(const struct DevHandle *handle, int cmdId,
606 struct AudioHwRenderParam *handleData)
607 {
608 return HDF_SUCCESS;
609 }
610
DoOutputRenderOpen(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)611 static int32_t DoOutputRenderOpen(const struct DevHandle *handle, int cmdId,
612 struct AudioHwRenderParam *handleData)
613 {
614 return HDF_SUCCESS;
615 }
616
DoOutputRenderClose(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)617 static int32_t DoOutputRenderClose(const struct DevHandle *handle, int cmdId,
618 struct AudioHwRenderParam *handleData)
619 {
620 struct AlsaCtx *aCtx = ((struct AlsaDevObject *)handle->object)->pAlsaCtx;
621
622 HDF_LOGV("INFO: enter %{public}s()", __func__);
623
624 AlsaClose(aCtx);
625
626 return HDF_SUCCESS;
627 }
628
HandleOutputRenderCmd(const struct DevHandle * handle,int cmdId,struct AudioHwRenderParam * handleData)629 static int32_t HandleOutputRenderCmd(const struct DevHandle *handle, int cmdId,
630 struct AudioHwRenderParam *handleData)
631 {
632 int32_t ret;
633 switch (cmdId) {
634 case AUDIO_DRV_PCM_IOCTL_HW_PARAMS:
635 ret = DoOutputRenderHwParams(handle, cmdId, handleData);
636 break;
637 case AUDIO_DRV_PCM_IOCTL_WRITE:
638 ret = DoOutputRenderWrite(handle, cmdId, handleData);
639 break;
640 case AUDIO_DRV_PCM_IOCTRL_STOP:
641 ret = DoOutputRenderStop(handle, cmdId, handleData);
642 break;
643 case AUDIO_DRV_PCM_IOCTRL_START:
644 case AUDIO_DRV_PCM_IOCTL_PREPARE:
645 ret = DoOutputRenderStartPrepare(handle, cmdId, handleData);
646 break;
647 case AUDIODRV_CTL_IOCTL_PAUSE_WRITE:
648 ret = DoCtlRenderSetPauseStu(handle, cmdId, handleData);
649 break;
650 case AUDIO_DRV_PCM_IOCTL_MMAP_BUFFER:
651 ret = DoOutputRenderReqMmapBuffer(handle, cmdId, handleData);
652 break;
653 case AUDIO_DRV_PCM_IOCTL_MMAP_POSITION:
654 ret = DoOutputRenderGetMmapPosition(handle, cmdId, handleData);
655 break;
656 case AUDIO_DRV_PCM_IOCTRL_RENDER_OPEN:
657 ret = DoOutputRenderOpen(handle, cmdId, handleData);
658 break;
659 case AUDIO_DRV_PCM_IOCTRL_RENDER_CLOSE:
660 ret = DoOutputRenderClose(handle, cmdId, handleData);
661 break;
662 default:
663 HDF_LOGE("Error: Output Mode not support!");
664 ret = HDF_FAILURE;
665 break;
666 }
667 return ret;
668 }
669
670 /************************************************************************************
671 Exported Interface
672 *************************************************************************************/
673
674 /* CreatRender for Bind handle */
AudioBindServiceRender(const char * name)675 struct DevHandle *AudioBindServiceRender(const char *name)
676 {
677 struct DevHandle *handle = NULL;
678 if (!name) {
679 HDF_LOGE("Error: service name NULL!");
680 return NULL;
681 }
682
683 HDF_LOGD("AudioBindServiceRender() name=%{public}s", name);
684
685 if (!strcmp(name, "render")) {
686 if (AlsaCtxInstanceGet()->renderRefCount > 0) {
687 HDF_LOGE("Error: Audio Render can only be bound to 1 handle.");
688 return NULL;
689 }
690 } else if (!strcmp(name, "control")) {
691 if (AlsaCtxInstanceGet()->ctlRefCount > 0) {
692 HDF_LOGE("Error: Audio Controler can only be bound to 1 handle.");
693 return NULL;
694 }
695 } else {
696 HDF_LOGE("Error: invalid service name.");
697 return NULL;
698 }
699
700 handle = (struct DevHandle *)calloc(1, sizeof(struct DevHandle));
701 if (!handle) {
702 HDF_LOGE("Error: Failed to OsalMemCalloc handle");
703 return NULL;
704 }
705
706 struct AlsaDevObject *devObject = calloc(1, sizeof(struct AlsaDevObject));
707 if (!devObject) {
708 HDF_LOGE("Error: alloc AlsaDevObject failed.");
709 free(handle);
710 return NULL;
711 }
712
713 (void)sprintf_s(devObject->serviceName, sizeof(devObject->serviceName),
714 "%s", name);
715 devObject->pAlsaCtx = AlsaCtxInstanceGet();
716 if (!strcmp(devObject->serviceName, "render")) {
717 devObject->pAlsaCtx->renderRefCount++;
718 } else {
719 devObject->pAlsaCtx->ctlRefCount++;
720 }
721
722 handle->object = devObject;
723
724 HDF_LOGI("BIND SERVICE SUCCESS!");
725
726 return handle;
727 }
728
AudioCloseServiceRender(const struct DevHandle * handle)729 void AudioCloseServiceRender(const struct DevHandle *handle)
730 {
731 if (!handle || !handle->object) {
732 HDF_LOGE("Error: Render handle or handle->object is NULL");
733 return;
734 }
735
736 struct AlsaDevObject *devObject = (struct AlsaDevObject *)handle->object;
737 if (!strcmp(devObject->serviceName, "render")) {
738 if (--devObject->pAlsaCtx->renderRefCount <= 0) {
739 // Do somthing here.
740 devObject->pAlsaCtx->renderRefCount = 0;
741 }
742 } else {
743 if (--devObject->pAlsaCtx->ctlRefCount <= 0) {
744 // Do somthing here.
745 devObject->pAlsaCtx->ctlRefCount = 0;
746 }
747 }
748
749 HDF_LOGD("AudioCloseServiceRender(), name=%{public}s",
750 devObject->serviceName);
751
752 free((void *)handle->object);
753 free((void *)handle);
754
755 HDF_LOGD("CLOSE SERVICE SUCCESS!");
756
757 return;
758 }
759
AudioInterfaceLibModeRender(const struct DevHandle * handle,struct AudioHwRenderParam * handleData,int cmdId)760 int32_t AudioInterfaceLibModeRender(const struct DevHandle *handle,
761 struct AudioHwRenderParam *handleData,
762 int cmdId)
763 {
764 if (!handle || !handle->object || !handleData) {
765 HDF_LOGE("Error: paras is NULL!");
766 return HDF_FAILURE;
767 }
768
769 if (AUDIO_DRV_PCM_IOCTL_WRITE != cmdId) {
770 HDF_LOGE("AudioInterfaceLibModeRender(cmdid=%{public}d)", cmdId);
771 }
772
773 switch (cmdId) {
774 case AUDIO_DRV_PCM_IOCTL_HW_PARAMS:
775 case AUDIO_DRV_PCM_IOCTL_WRITE:
776 case AUDIO_DRV_PCM_IOCTRL_STOP:
777 case AUDIO_DRV_PCM_IOCTRL_START:
778 case AUDIO_DRV_PCM_IOCTL_PREPARE:
779 case AUDIODRV_CTL_IOCTL_PAUSE_WRITE:
780 case AUDIO_DRV_PCM_IOCTL_MMAP_BUFFER:
781 case AUDIO_DRV_PCM_IOCTL_MMAP_POSITION:
782 case AUDIO_DRV_PCM_IOCTRL_RENDER_OPEN:
783 case AUDIO_DRV_PCM_IOCTRL_RENDER_CLOSE:
784 return HandleOutputRenderCmd(handle, cmdId, handleData);
785 case AUDIODRV_CTL_IOCTL_ELEM_WRITE:
786 case AUDIODRV_CTL_IOCTL_ELEM_READ:
787 case AUDIODRV_CTL_IOCTL_MUTE_WRITE:
788 case AUDIODRV_CTL_IOCTL_MUTE_READ:
789 case AUDIODRV_CTL_IOCTL_GAIN_WRITE:
790 case AUDIODRV_CTL_IOCTL_GAIN_READ:
791 case AUDIODRV_CTL_IOCTL_CHANNEL_MODE_WRITE:
792 case AUDIODRV_CTL_IOCTL_CHANNEL_MODE_READ:
793 case AUDIODRV_CTL_IOCTL_SCENESELECT_WRITE:
794 case AUDIODRV_CTL_IOCTL_GAINTHRESHOLD_READ:
795 case AUDIODRV_CTL_IOCTL_ACODEC_CHANGE_IN:
796 case AUDIODRV_CTL_IOCTL_ACODEC_CHANGE_OUT:
797 case AUDIODRV_CTL_IOCTL_VOL_THRESHOLD_READ:
798 return HandleCtlRenderCmd(handle, cmdId, handleData);
799 default:
800 HDF_LOGE("Error: Mode Error!");
801 break;
802 }
803
804 return HDF_ERR_NOT_SUPPORT;
805 }
806