1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "audio_host.h"
10 #include "audio_codec_if.h"
11 #include "audio_core.h"
12 #include "audio_sapm.h"
13 #include "audio_driver_log.h"
14 #include "audio_parse.h"
15
16 #define HDF_LOG_TAG HDF_AUDIO_KADM
17
18 AUDIO_LIST_HEAD(cardManager);
19
20 /* Get a sound card instance */
GetCardInstance(const char * serviceName)21 struct AudioCard *GetCardInstance(const char *serviceName)
22 {
23 struct AudioCard *audioCard = NULL;
24
25 if (serviceName == NULL) {
26 ADM_LOG_ERR("serviceName is NULL.");
27 return NULL;
28 }
29
30 if (DListIsEmpty(&cardManager)) {
31 ADM_LOG_ERR("cardManager is empty.");
32 return NULL;
33 }
34
35 DLIST_FOR_EACH_ENTRY(audioCard, &cardManager, struct AudioCard, list) {
36 if (audioCard->configData.cardServiceName == NULL) {
37 ADM_LOG_ERR("cardServiceName is NULL.");
38 return NULL;
39 }
40
41 if (strcmp(audioCard->configData.cardServiceName, serviceName) == 0) {
42 return audioCard;
43 }
44 }
45 ADM_LOG_ERR("serviceName is %s.", serviceName);
46 return NULL;
47 }
48
AudioCodecDevInit(struct AudioCard * audioCard)49 static int32_t AudioCodecDevInit(struct AudioCard *audioCard)
50 {
51 struct AudioRuntimeDeivces *rtd = NULL;
52 struct CodecDevice *codec = NULL;
53 ADM_LOG_DEBUG("entry.");
54
55 if (audioCard == NULL) {
56 ADM_LOG_ERR("audioCard is NULL.");
57 return HDF_ERR_IO;
58 }
59 rtd = audioCard->rtd;
60 if (rtd == NULL) {
61 ADM_LOG_ERR("rtd is NULL.");
62 return HDF_ERR_IO;
63 }
64 codec = rtd->codec;
65 if (codec != NULL && codec->devData != NULL && codec->devData->Init != NULL) {
66 /* codec initialization */
67 int32_t ret = codec->devData->Init(audioCard, codec);
68 if (ret != HDF_SUCCESS) {
69 ADM_LOG_ERR("codec initialization fail ret=%d", ret);
70 return HDF_ERR_IO;
71 }
72 }
73
74 ADM_LOG_INFO("success.");
75 return HDF_SUCCESS;
76 }
77
AudioPlatformDevInit(const struct AudioCard * audioCard)78 static int32_t AudioPlatformDevInit(const struct AudioCard *audioCard)
79 {
80 struct AudioRuntimeDeivces *rtd = NULL;
81 struct PlatformDevice *platform = NULL;
82
83 if (audioCard == NULL) {
84 ADM_LOG_ERR("input param is NULL.");
85 return HDF_ERR_IO;
86 }
87 ADM_LOG_DEBUG("entry.");
88
89 rtd = audioCard->rtd;
90 if (rtd == NULL) {
91 ADM_LOG_ERR("Platform rtd is NULL.");
92 return HDF_ERR_IO;
93 }
94 platform = rtd->platform;
95 if (platform != NULL && platform->devData != NULL && platform->devData->PlatformInit != NULL) {
96 /* platform initialization */
97 int32_t ret = platform->devData->PlatformInit(audioCard, platform);
98 if (ret != HDF_SUCCESS) {
99 ADM_LOG_ERR("platform initialization fail ret=%d", ret);
100 return HDF_ERR_IO;
101 }
102 }
103
104 ADM_LOG_INFO("success.");
105 return HDF_SUCCESS;
106 }
107
AudioDspDevInit(const struct AudioCard * audioCard)108 static int32_t AudioDspDevInit(const struct AudioCard *audioCard)
109 {
110 struct AudioRuntimeDeivces *rtd = NULL;
111 struct DspDevice *dsp = NULL;
112
113 if (audioCard == NULL) {
114 ADM_LOG_ERR("audioCard is NULL.");
115 return HDF_ERR_IO;
116 }
117 ADM_LOG_DEBUG("entry.");
118
119 rtd = audioCard->rtd;
120 if (rtd == NULL) {
121 ADM_LOG_ERR("audioCard rtd object is NULL.");
122 return HDF_ERR_IO;
123 }
124
125 dsp = rtd->dsp;
126 if (dsp != NULL && dsp->devData != NULL && dsp->devData->DspInit != NULL) {
127 /* dsp initialization */
128 int32_t ret = dsp->devData->DspInit(dsp);
129 if (ret != HDF_SUCCESS) {
130 ADM_LOG_ERR("dsp initialization fail ret=%d", ret);
131 return HDF_ERR_IO;
132 }
133 }
134
135 ADM_LOG_INFO("success.");
136 return HDF_SUCCESS;
137 }
138
AudioCodecDaiDevInit(struct AudioCard * audioCard)139 static int32_t AudioCodecDaiDevInit(struct AudioCard *audioCard)
140 {
141 struct AudioRuntimeDeivces *rtd = NULL;
142 struct DaiDevice *codecDai = NULL;
143
144 if (audioCard == NULL) {
145 ADM_LOG_ERR("audioCard is NULL.");
146 return HDF_ERR_IO;
147 }
148 ADM_LOG_DEBUG("entry.");
149
150 rtd = audioCard->rtd;
151 if (rtd == NULL) {
152 ADM_LOG_ERR("CodecDai rtd is NULL.");
153 return HDF_ERR_IO;
154 }
155 codecDai = rtd->codecDai;
156 if (codecDai != NULL && codecDai->devData != NULL && codecDai->devData->DaiInit != NULL) {
157 /* codec dai initialization */
158 int32_t ret = codecDai->devData->DaiInit(audioCard, codecDai);
159 if (ret != HDF_SUCCESS) {
160 ADM_LOG_ERR("codec dai initialization fail ret=%d", ret);
161 return HDF_ERR_IO;
162 }
163 }
164
165 ADM_LOG_INFO("success.");
166 return HDF_SUCCESS;
167 }
168
AudioCpuDaiDevInit(struct AudioCard * audioCard)169 static int32_t AudioCpuDaiDevInit(struct AudioCard *audioCard)
170 {
171 struct AudioRuntimeDeivces *rtd = NULL;
172 struct DaiDevice *cpuDai = NULL;
173
174 if (audioCard == NULL) {
175 ADM_LOG_ERR("audioCard is NULL.");
176 return HDF_ERR_IO;
177 }
178 ADM_LOG_DEBUG("entry.");
179
180 rtd = audioCard->rtd;
181 if (rtd == NULL) {
182 ADM_LOG_ERR("cpuDai rtd is NULL.");
183 return HDF_ERR_IO;
184 }
185 cpuDai = rtd->cpuDai;
186 if (cpuDai != NULL && cpuDai->devData != NULL && cpuDai->devData->DaiInit != NULL) {
187 /* cpu dai initialization */
188 int32_t ret = cpuDai->devData->DaiInit(audioCard, cpuDai);
189 if (ret != HDF_SUCCESS) {
190 ADM_LOG_ERR("cpu dai initialization fail ret=%d", ret);
191 return HDF_ERR_IO;
192 }
193 }
194
195 ADM_LOG_INFO("success.");
196 return HDF_SUCCESS;
197 }
198
AudioDspDaiDevInit(struct AudioCard * audioCard)199 static int32_t AudioDspDaiDevInit(struct AudioCard *audioCard)
200 {
201 struct AudioRuntimeDeivces *rtd = NULL;
202 struct DaiDevice *dspDai = NULL;
203 int32_t ret;
204
205 if (audioCard == NULL) {
206 ADM_LOG_ERR("audioCard is NULL.");
207 return HDF_ERR_IO;
208 }
209 ADM_LOG_DEBUG("dsp init entry.");
210
211 rtd = audioCard->rtd;
212 if (rtd == NULL) {
213 ADM_LOG_ERR("dspDai rtd is NULL.");
214 return HDF_ERR_IO;
215 }
216
217 dspDai = rtd->dspDai;
218 if (dspDai != NULL && dspDai->devData != NULL && dspDai->devData->DaiInit != NULL) {
219 ret = dspDai->devData->DaiInit(audioCard, dspDai);
220 if (ret != HDF_SUCCESS) {
221 ADM_LOG_ERR("dsp dai initialization fail ret=%d", ret);
222 return HDF_ERR_IO;
223 }
224 }
225
226 ADM_LOG_INFO("success.");
227 return HDF_SUCCESS;
228 }
229
AudioInitDaiLink(struct AudioCard * audioCard)230 static int32_t AudioInitDaiLink(struct AudioCard *audioCard)
231 {
232 if (audioCard == NULL) {
233 ADM_LOG_ERR("audioCard is NULL.");
234 return HDF_ERR_IO;
235 }
236 ADM_LOG_DEBUG("entry.");
237
238 if (AudioPlatformDevInit(audioCard) || AudioCpuDaiDevInit(audioCard)) {
239 ADM_LOG_ERR("Platform and CpuDai init fail.");
240 return HDF_FAILURE;
241 }
242
243 if ((AudioCodecDevInit(audioCard) || AudioCodecDaiDevInit(audioCard))) {
244 ADM_LOG_ERR("codec Device init fail.");
245 return HDF_FAILURE;
246 }
247
248 if (AudioDspDevInit(audioCard) || AudioDspDaiDevInit(audioCard)) {
249 ADM_LOG_ERR("Dsp Device init fail.");
250 return HDF_FAILURE;
251 }
252
253 ADM_LOG_DEBUG("success.");
254 return HDF_SUCCESS;
255 }
256
AudioHostCreateAndBind(struct HdfDeviceObject * device)257 struct AudioHost *AudioHostCreateAndBind(struct HdfDeviceObject *device)
258 {
259 struct AudioHost *audioHost = NULL;
260
261 if (device == NULL) {
262 ADM_LOG_ERR("device is NULL!");
263 return NULL;
264 }
265
266 audioHost = (struct AudioHost *)OsalMemCalloc(sizeof(*audioHost));
267 if (audioHost == NULL) {
268 ADM_LOG_ERR("Malloc audio host fail!");
269 return NULL;
270 }
271 audioHost->device = device;
272 device->service = &audioHost->service;
273 return audioHost;
274 }
275
276 /* HdfDriverEntry implementations */
AudioDriverBind(struct HdfDeviceObject * device)277 static int32_t AudioDriverBind(struct HdfDeviceObject *device)
278 {
279 struct AudioHost *audioHost = NULL;
280
281 ADM_LOG_DEBUG("entry.");
282 if (device == NULL) {
283 ADM_LOG_ERR("device is NULL.");
284 return HDF_ERR_INVALID_OBJECT;
285 }
286
287 audioHost = AudioHostCreateAndBind(device);
288 if (audioHost == NULL) {
289 ADM_LOG_ERR("audioHost create failed!");
290 return HDF_FAILURE;
291 }
292
293 ADM_LOG_INFO("success.");
294 return HDF_SUCCESS;
295 }
296
AudioCardInit(struct HdfDeviceObject * device,struct AudioHost * audioHost)297 static int32_t AudioCardInit(struct HdfDeviceObject *device, struct AudioHost *audioHost)
298 {
299 int32_t ret;
300 struct AudioCard *audioCard = NULL;
301 if (device == NULL || audioHost == NULL) {
302 ADM_LOG_ERR("device or audioHost is NULL.");
303 return HDF_FAILURE;
304 }
305
306 audioCard = (struct AudioCard *)OsalMemCalloc(sizeof(*audioCard));
307 if (audioCard == NULL) {
308 ADM_LOG_ERR("Malloc audioCard fail!");
309 return HDF_FAILURE;
310 }
311 audioHost->priv = audioCard;
312 /* Get node information through HCS file */
313 ret = AudioFillConfigData(device, &(audioCard->configData));
314 if (ret != HDF_SUCCESS) {
315 ADM_LOG_ERR("AudioFillConfigData fail ret=%d", ret);
316 return HDF_ERR_IO;
317 }
318
319 audioCard->device = device;
320 audioCard->standbyMode = AUDIO_SAPM_TURN_STANDBY_LATER;
321
322 /* Bind specific codec、platform and dai device */
323 ret = AudioBindDaiLink(audioCard, &(audioCard->configData));
324 if (ret != HDF_SUCCESS) {
325 ADM_LOG_ERR("AudioBindDaiLink fail ret=%d", ret);
326 return HDF_FAILURE;
327 }
328 if (audioCard->rtd == NULL || (!audioCard->rtd->complete)) {
329 ADM_LOG_ERR("AudioBindDaiLink fail!");
330 return HDF_ERR_IO;
331 }
332
333 /* Initialize controls list */
334 DListHeadInit(&audioCard->controls);
335 DListHeadInit(&audioCard->components);
336 DListHeadInit(&audioCard->paths);
337 DListHeadInit(&audioCard->sapmDirty);
338 /* Initialize hardware device */
339 ret = AudioInitDaiLink(audioCard);
340 if (ret != HDF_SUCCESS) {
341 ADM_LOG_ERR("AudioInitDaiLink fail ret=%d", ret);
342 return HDF_ERR_IO;
343 }
344
345 /* sound card added to list */
346 DListInsertHead(&audioCard->list, &cardManager);
347
348 return HDF_SUCCESS;
349 }
350
AudioDriverInit(struct HdfDeviceObject * device)351 static int32_t AudioDriverInit(struct HdfDeviceObject *device)
352 {
353 struct AudioHost *audioHost = NULL;
354
355 ADM_LOG_DEBUG("entry.");
356 if (device == NULL) {
357 ADM_LOG_ERR("device is NULL.");
358 return HDF_ERR_INVALID_OBJECT;
359 }
360 if (!HdfDeviceSetClass(device, DEVICE_CLASS_AUDIO)) {
361 ADM_LOG_ERR("set audio class failed.");
362 return HDF_FAILURE;
363 }
364 audioHost = (struct AudioHost *)device->service;
365 if (AudioCardInit(device, audioHost) != HDF_SUCCESS) {
366 ADM_LOG_ERR("set audio class failed.");
367 return HDF_FAILURE;
368 }
369 ADM_LOG_INFO("success.");
370 return HDF_SUCCESS;
371 }
372
AudioDriverRelease(struct HdfDeviceObject * device)373 static void AudioDriverRelease(struct HdfDeviceObject *device)
374 {
375 struct AudioHost *audioHost = NULL;
376 struct AudioCard *audioCard = NULL;
377 struct DListHead *componentHead = NULL;
378 struct DListHead *controlHead = NULL;
379 struct AudioSapmComponent *componentReq = NULL;
380 struct AudioSapmComponent *componentTmp = NULL;
381 struct AudioKcontrol *ctrlReq = NULL;
382 struct AudioKcontrol *ctrlTmp = NULL;
383
384 ADM_LOG_DEBUG("entry.");
385 if (device == NULL) {
386 ADM_LOG_ERR("device is NULL.");
387 return;
388 }
389 audioHost = (struct AudioHost *)device->service;
390 if (audioHost == NULL) {
391 ADM_LOG_ERR("audioHost is NULL.");
392 return;
393 }
394
395 if (audioHost->priv != NULL) {
396 audioCard = (struct AudioCard *)audioHost->priv;
397
398 componentHead = &audioCard->components;
399 DLIST_FOR_EACH_ENTRY_SAFE(componentReq, componentTmp, componentHead, struct AudioSapmComponent, list) {
400 DListRemove(&componentReq->list);
401 if (componentReq->componentName != NULL) {
402 OsalMemFree(componentReq->componentName);
403 }
404 OsalMemFree(componentReq);
405 }
406
407 controlHead = &audioCard->controls;
408 DLIST_FOR_EACH_ENTRY_SAFE(ctrlReq, ctrlTmp, controlHead, struct AudioKcontrol, list) {
409 DListRemove(&ctrlReq->list);
410 if (ctrlReq->privateData != NULL) {
411 OsalMemFree(ctrlReq->privateData);
412 }
413 OsalMemFree(ctrlReq);
414 }
415
416 if (audioCard->rtd != NULL) {
417 OsalMemFree(audioCard->rtd);
418 }
419
420 if (audioHost->priv != NULL) {
421 OsalMemFree(audioHost->priv);
422 }
423 }
424
425 OsalMemFree(audioHost);
426 ADM_LOG_INFO("success.");
427 }
428
429 /* HdfDriverEntry definitions */
430 struct HdfDriverEntry g_audioDriverEntry = {
431 .moduleVersion = 1,
432 .moduleName = "HDF_AUDIO",
433 .Bind = AudioDriverBind,
434 .Init = AudioDriverInit,
435 .Release = AudioDriverRelease,
436 };
437 HDF_INIT(g_audioDriverEntry);
438