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