1e41f4b71Sopenharmony_ci# Audio
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci
4e41f4b71Sopenharmony_ci## Audio Driver Overview
5e41f4b71Sopenharmony_ci
6e41f4b71Sopenharmony_ciA multimedia system is an indispensable part in Internet of Things (IoT) devices. Audio is an important module of the multimedia system, and building an audio driver model is particularly important in device development.
7e41f4b71Sopenharmony_ci
8e41f4b71Sopenharmony_ciThis document describes the audio driver architecture and functional modules and how to develop audio drivers based on the Hardware Driver Foundation (HDF). You can develop your own drivers and call Hardware Abstraction Layer (HAL) APIs based on this driver architecture.
9e41f4b71Sopenharmony_ci
10e41f4b71Sopenharmony_ci
11e41f4b71Sopenharmony_ci
12e41f4b71Sopenharmony_ci## Audio Driver Architecture
13e41f4b71Sopenharmony_ci
14e41f4b71Sopenharmony_ciThe audio driver framework is implemented based on the [HDF](driver-overview-foundation.md). The following figure illustrates the audio driver architecture.
15e41f4b71Sopenharmony_ci
16e41f4b71Sopenharmony_ci![](figures/Audio_architecture.png)
17e41f4b71Sopenharmony_ci
18e41f4b71Sopenharmony_ciThe driver architecture consists of the following:
19e41f4b71Sopenharmony_ci- Hardware Device Interface (HDI) adapter: implements the audio HAL driver (for HDI adaptation) and provides hardware driver APIs for audio services (frameworks). The HDI adapter provides API objects such as **AudioManager**, **AudioAdapter**, **AudioControl**, **AudioCapture**, and **AudioRender**.
20e41f4b71Sopenharmony_ci- Audio Interface Lib: works with the Audio Driver Model (ADM) in the kernel to control audio hardware, read recording data, and write playback data. The **Stream_ctrl_common** in the Audio Interface Lib interacts with the Audio HDI Adapter layer.
21e41f4b71Sopenharmony_ci- ADM: helps system developers to develop scenario-specific applications for the multimedia audio subsystem. With the ADM, codec and DSP device vendors can adapt their driver code based on the APIs provided by the ADM and implement quick development and easy adaptation to the OpenHarmony system.
22e41f4b71Sopenharmony_ci- Audio Control Dispatch: dispatches the control instructions from the Audio Interface Lib to the driver layer.
23e41f4b71Sopenharmony_ci- Audio Stream Dispatch: dispatches the data from the Audio Interface Lib to the driver layer.
24e41f4b71Sopenharmony_ci
25e41f4b71Sopenharmony_ci- Card Manager: manages multiple audio adapters. Each audio adapter consists of the digital audio interface (DAI), platform, codec, DSP, and Smart Audio Power Manager (SAPM) modules.
26e41f4b71Sopenharmony_ci- Platform Drivers: driver adaptation layer.
27e41f4b71Sopenharmony_ci- SAPM: optimizes the power consumption policy of the ADM.
28e41f4b71Sopenharmony_ci
29e41f4b71Sopenharmony_ci## Audio Driver Development
30e41f4b71Sopenharmony_ci
31e41f4b71Sopenharmony_ciThe following uses the Hi3516D V300 as an example to describe how to develop drivers based on the audio driver architecture.
32e41f4b71Sopenharmony_ci
33e41f4b71Sopenharmony_ci### Audio ADM Architecture
34e41f4b71Sopenharmony_ci
35e41f4b71Sopenharmony_ciThe audio driver provides the **hdf_audio_render**, **hdf_audio_capture**, and **hdf_audio_control** services for the HDI layer. The driver service nodes in the **dev** directory of the development board are as follows:
36e41f4b71Sopenharmony_ci
37e41f4b71Sopenharmony_ci```shell
38e41f4b71Sopenharmony_ci# ls -l hdf_audio*
39e41f4b71Sopenharmony_cicrw-rw---- 1 system system 247,   6 1970-01-01 00:00 hdf_audio_capture             // Voice recording service.
40e41f4b71Sopenharmony_cicrw-rw---- 1 root   root   247,   4 1970-01-01 00:00 hdf_audio_codec_primary_dev0  // Audio adapter device 0.
41e41f4b71Sopenharmony_cicrw-rw---- 1 root   root   247,   4 1970-01-01 00:00 hdf_audio_codec_primary_dev11 // Audio adapter device 1.
42e41f4b71Sopenharmony_cicrw-rw---- 1 system system 247,   5 1970-01-01 00:00 hdf_audio_control             // Audio control service.
43e41f4b71Sopenharmony_cicrw-rw---- 1 system system 247,   7 1970-01-01 00:00 hdf_audio_render              // Audio playback service.
44e41f4b71Sopenharmony_ci```
45e41f4b71Sopenharmony_ci
46e41f4b71Sopenharmony_ciThe audio adapters have the following driver services:
47e41f4b71Sopenharmony_ci
48e41f4b71Sopenharmony_cihdf_audio_codec_primary_dev0
49e41f4b71Sopenharmony_ci
50e41f4b71Sopenharmony_ci- **dma_service_0**: DMA service
51e41f4b71Sopenharmony_ci- **dai_service**: CPU DAI service
52e41f4b71Sopenharmony_ci- **codec_service_0**: codec service (which can be smartPA)
53e41f4b71Sopenharmony_ci- **dsp_service_0**: DSP service (optional)
54e41f4b71Sopenharmony_ci
55e41f4b71Sopenharmony_cihdf_audio_codec_primary_dev11
56e41f4b71Sopenharmony_ci
57e41f4b71Sopenharmony_ci- **dma_service_0**: DMA service
58e41f4b71Sopenharmony_ci- **dai_service**: CPU DAI service
59e41f4b71Sopenharmony_ci- **codec_service_1**: codec service (which can be smartPA)
60e41f4b71Sopenharmony_ci- **dsp_service_0**: DSP service (optional)
61e41f4b71Sopenharmony_ci
62e41f4b71Sopenharmony_ci#### Startup Process
63e41f4b71Sopenharmony_ci
64e41f4b71Sopenharmony_ci![](figures/ADM_startup_flowchart.png)
65e41f4b71Sopenharmony_ci
66e41f4b71Sopenharmony_ci1. When the system starts, the platform, codec, DSP, and DAI drivers of the audio module are loaded first. Each driver obtains the configuration information from its configuration file and saves the obtained information to the data structs.
67e41f4b71Sopenharmony_ci
68e41f4b71Sopenharmony_ci2. Each driver module calls the ADM registration interface to add itself to the linked list of the driver module.
69e41f4b71Sopenharmony_ci
70e41f4b71Sopenharmony_ci3. The ADM obtains the hdf_audio_driver_0 and hdf_audio_driver_1 configuration and loads the devices of each module.
71e41f4b71Sopenharmony_ci
72e41f4b71Sopenharmony_ci4. The ADM module initializes each module device by calling the initialization API of the respective module.
73e41f4b71Sopenharmony_ci
74e41f4b71Sopenharmony_ci5. The initialized audio devices are added to the cardManager linked list.
75e41f4b71Sopenharmony_ci
76e41f4b71Sopenharmony_ci#### Playback Process
77e41f4b71Sopenharmony_ci
78e41f4b71Sopenharmony_ci![](figures/ADM_playback_flowchart.png)
79e41f4b71Sopenharmony_ci
80e41f4b71Sopenharmony_ci1. The Audio Interface Lib sends the **Render Open** instruction to the Audio Stream Dispatch service. The Audio Stream Dispatch service calls the API of each module to deliver the instruction.
81e41f4b71Sopenharmony_ci
82e41f4b71Sopenharmony_ci2. The Audio Interface Lib sends a path select instruction to the Control Dispatch service. The Control Dispatch service calls the DAI API to set the path.
83e41f4b71Sopenharmony_ci
84e41f4b71Sopenharmony_ci3. The Audio Interface Lib sends hardware parameters to the Audio Stream Dispatch service. The Audio Stream Dispatch service calls the API of each module to set the hardware parameters.
85e41f4b71Sopenharmony_ci
86e41f4b71Sopenharmony_ci4. The Audio Interface Lib sends the start playing instruction to the Audio Stream Dispatch service. The Audio Stream Dispatch service calls the API of each module to perform related settings for each module.
87e41f4b71Sopenharmony_ci
88e41f4b71Sopenharmony_ci5. The Audio Interface Lib sends audio data to the Audio Stream Dispatch service. The Audio Stream Dispatch service calls the **Platform AudioPcmWrite** API to send the audio data to DMA.
89e41f4b71Sopenharmony_ci
90e41f4b71Sopenharmony_ci6. The Audio Interface Lib sends the stop playing instruction to the Audio Stream Dispatch service. The Audio Stream Dispatch service calls the stop API of each module to perform related stop settings for each module.
91e41f4b71Sopenharmony_ci
92e41f4b71Sopenharmony_ci7. The Audio Interface Lib sends the **Render Close** instruction to the Audio Stream Dispatch service. The Audio Stream Dispatch service calls the **Platform AudioRenderClose** API to release resources.
93e41f4b71Sopenharmony_ci
94e41f4b71Sopenharmony_ci#### Control Process
95e41f4b71Sopenharmony_ci
96e41f4b71Sopenharmony_ci![](figures/ADM_control_flowchart.png)
97e41f4b71Sopenharmony_ci
98e41f4b71Sopenharmony_ci1. When the volume needs to be adjusted, the Audio Interface Lib sends an instruction for obtaining the volume range to the Control Dispatch service. The Control Dispatch service parses the instruction and calls **get()** of the codec module to obtain the volume range.
99e41f4b71Sopenharmony_ci2. The Audio Interface Lib sends an instruction for setting the volume to the Control Dispatch service. The Control Dispatch service parses the instruction and calls **Set()** of the codec module to set the volume.
100e41f4b71Sopenharmony_ci
101e41f4b71Sopenharmony_ci### Common Audio Driver Functions
102e41f4b71Sopenharmony_ci
103e41f4b71Sopenharmony_ci| Function                        | Description                                       |
104e41f4b71Sopenharmony_ci| ------------------------------ | ------------------------------------------- |
105e41f4b71Sopenharmony_ci| CodecDeviceReadReg             | Reads data from a codec register.                          |
106e41f4b71Sopenharmony_ci| CodecDeviceWriteReg            | Writes data to a codec register.                          |
107e41f4b71Sopenharmony_ci| CodecDaiRegI2cRead             | Reads data from a codec register over an I2C interface to a codec DAI.           |
108e41f4b71Sopenharmony_ci| CodecDaiRegI2cWrite            | Writes data to a codec register over an I2C interface from a codec DAI.           |
109e41f4b71Sopenharmony_ci| CodecDeviceRegI2cRead          | Reads data from a codec register over an I2C interface to a codec device.               |
110e41f4b71Sopenharmony_ci| CodecDeviceRegI2cWrite         | Write data to a codec register over an I2C interface from a codec device.               |
111e41f4b71Sopenharmony_ci| CodecDeviceInitRegConfig       | Initializes codec.                            |
112e41f4b71Sopenharmony_ci| CodecDaiDeviceStartupRegConfig | Starts a codec device.                              |
113e41f4b71Sopenharmony_ci| CodecSetCtlFunc                | Sets the **set()** and **get()** functions.   |
114e41f4b71Sopenharmony_ci| CodecSetConfigInfoOfControls   | Sets the codec control function and register information.|
115e41f4b71Sopenharmony_ci| CodecGetConfigInfo             | Obtains the code HDF configuration source (HCS).                   |
116e41f4b71Sopenharmony_ci| CodecGetDaiName                | Obtains the DAI name in the HCS.                |
117e41f4b71Sopenharmony_ci| CodecGetServiceName            | Obtains the service name in the HCS.               |
118e41f4b71Sopenharmony_ci| DaiDeviceReadReg               | Reads data from a DAI register.                            |
119e41f4b71Sopenharmony_ci| DaiDeviceWriteReg              | Writes data to a DAI register.                            |
120e41f4b71Sopenharmony_ci| DaiSetConfigInfoOfControls     | Sets the DAI control function and register information.  |
121e41f4b71Sopenharmony_ci| DaiGetConfigInfo               | Obtains the DAI HCS.                     |
122e41f4b71Sopenharmony_ci
123e41f4b71Sopenharmony_ci
124e41f4b71Sopenharmony_ci
125e41f4b71Sopenharmony_ci### Audio Driver Development Procedure
126e41f4b71Sopenharmony_ci
127e41f4b71Sopenharmony_ci#### Development on an Adapted Platform
128e41f4b71Sopenharmony_ci
129e41f4b71Sopenharmony_ciThe following figure shows the process for developing the codec or SmartPA driver on a chip platform (Hi3516D V300) to which the ADM has adapted.
130e41f4b71Sopenharmony_ci
131e41f4b71Sopenharmony_ci![](figures/audio_development_flowchart_1.png)  
132e41f4b71Sopenharmony_ci
133e41f4b71Sopenharmony_ci- Add register information to the private HDF configuration source (HCS) of the codec or SmartPA based on the chip description.
134e41f4b71Sopenharmony_ci
135e41f4b71Sopenharmony_ci- If the workflow of the newly added codec or SmartPA is the same as that of the existing codec or SmartPA, you do not need to implement the operation function set or configure the compilation file for the newly added codec or SmartPA.
136e41f4b71Sopenharmony_ci
137e41f4b71Sopenharmony_ci- Perform build, debugging, and testing.
138e41f4b71Sopenharmony_ci
139e41f4b71Sopenharmony_ci#### Development on a New Platform
140e41f4b71Sopenharmony_ci
141e41f4b71Sopenharmony_ciThe following figure shows the driver development process if the ADM has not adapted to the platform.
142e41f4b71Sopenharmony_ci
143e41f4b71Sopenharmony_ci![](figures/audio_development_flowchart_2.png)
144e41f4b71Sopenharmony_ci
145e41f4b71Sopenharmony_ciThe codec (optional), DAI, DMA, DSP (optional), and SmartPA (optional) modules of the audio adapter need to be adapted to the new platform.
146e41f4b71Sopenharmony_ci
147e41f4b71Sopenharmony_ci- Add register information of each module driver to the private configuration file of the respective module according to the chip description.
148e41f4b71Sopenharmony_ci
149e41f4b71Sopenharmony_ci- Implement the operation function set of each module.
150e41f4b71Sopenharmony_ci
151e41f4b71Sopenharmony_ci- Modify the compilation file of the audio module.
152e41f4b71Sopenharmony_ci
153e41f4b71Sopenharmony_ci- Perform build, debugging, and testing.
154e41f4b71Sopenharmony_ci
155e41f4b71Sopenharmony_ci## Audio Driver Development Examples
156e41f4b71Sopenharmony_ci
157e41f4b71Sopenharmony_ciCode path: **device/board/hisilicon/hispark_taurus/audio_drivers**
158e41f4b71Sopenharmony_ci
159e41f4b71Sopenharmony_ciThe following uses Hi3516D V300 as an example to describe how to develop the codec driver, DAI driver, and Platform driver.
160e41f4b71Sopenharmony_ci
161e41f4b71Sopenharmony_ci### Codec Driver Development Example
162e41f4b71Sopenharmony_ci
163e41f4b71Sopenharmony_ciCode path: **device/board/hisilicon/hispark_taurus/audio_drivers/codec/hi3516**
164e41f4b71Sopenharmony_ci
165e41f4b71Sopenharmony_ciThe major steps for developing the codec driver are as follows:
166e41f4b71Sopenharmony_ci
167e41f4b71Sopenharmony_ci1. Define and fill in a codec instance.
168e41f4b71Sopenharmony_ci2. Implement callbacks for the codec instance.
169e41f4b71Sopenharmony_ci3. Register and bind the codec instance to the HDF.
170e41f4b71Sopenharmony_ci4. Configure the HCS and makefile.
171e41f4b71Sopenharmony_ci
172e41f4b71Sopenharmony_ci#### Filling in Codec Data Structs
173e41f4b71Sopenharmony_ci
174e41f4b71Sopenharmony_ciFill in the following data structs for the codec module:
175e41f4b71Sopenharmony_ci
176e41f4b71Sopenharmony_ci- **g_codecData**: operation function set and private data set of the codec device.
177e41f4b71Sopenharmony_ci
178e41f4b71Sopenharmony_ci- **g_codecDaiDeviceOps**: codec DAI device operation function set, including APIs for starting transmission and setting parameters.
179e41f4b71Sopenharmony_ci
180e41f4b71Sopenharmony_ci- **g_codecDaiData**: operation function set and private data set of the digital audio interface of the codec.
181e41f4b71Sopenharmony_ci
182e41f4b71Sopenharmony_ci```c
183e41f4b71Sopenharmony_cistruct CodecData g_codecData = {
184e41f4b71Sopenharmony_ci  .Init = CodecDeviceInit,      // Initialize the codec device (need to be implemented for a new platform).
185e41f4b71Sopenharmony_ci  .Read = AudioDeviceReadReg,   // Read the register (available in the existing framework).
186e41f4b71Sopenharmony_ci  .Write = AudioDeviceWriteReg, // Write the register (available in the existing framework).
187e41f4b71Sopenharmony_ci};
188e41f4b71Sopenharmony_ci
189e41f4b71Sopenharmony_cistruct AudioDaiOps g_codecDaiDeviceOps = {
190e41f4b71Sopenharmony_ci  .Startup = CodecDaiStartup,   // Start transmission (need to be implemented for a new platform).
191e41f4b71Sopenharmony_ci  .HwParams = CodecDaiHwParams, // Set parameters (need to be implemented for a new platform).
192e41f4b71Sopenharmony_ci};
193e41f4b71Sopenharmony_ci
194e41f4b71Sopenharmony_cistruct DaiData g_codecDaiData = {
195e41f4b71Sopenharmony_ci  .DaiInit = CodecDaiDeviceInit,// Initialize the codec DAI device (need to be implemented for a new platform).
196e41f4b71Sopenharmony_ci  .ops = &g_codecDaiDeviceOps,  // Codec DAI device operation function set.
197e41f4b71Sopenharmony_ci};
198e41f4b71Sopenharmony_ci```
199e41f4b71Sopenharmony_ci
200e41f4b71Sopenharmony_ci#### Initializing codecDevice and codecDai
201e41f4b71Sopenharmony_ci
202e41f4b71Sopenharmony_ci**CODECDeviceInit** sets audio input/audio output (AIAO), initializes registers, inserts **g_audioControls** into the controller linked list, initializes the power management, and selects a path.
203e41f4b71Sopenharmony_ci
204e41f4b71Sopenharmony_ci```c
205e41f4b71Sopenharmony_ciint32_t CodecDeviceInit(struct AudioCard *audioCard, struct CodecDevice *codec)
206e41f4b71Sopenharmony_ci{
207e41f4b71Sopenharmony_ci    ...
208e41f4b71Sopenharmony_ci    /* Register set() and get() of the AIAO module on the Hi3516. */
209e41f4b71Sopenharmony_ci    CodecSetCtlFunc(codec->devData, AudioCodecAiaoGetCtrlOps, AudioCodecAiaoSetCtrlOps)
210e41f4b71Sopenharmony_ci    ...
211e41f4b71Sopenharmony_ci    /* Hi3516 codec register IoRemap. */
212e41f4b71Sopenharmony_ci    CodecHalSysInit();
213e41f4b71Sopenharmony_ci    ...
214e41f4b71Sopenharmony_ci    /* Initialize the codec registers of the Hi3516. */
215e41f4b71Sopenharmony_ci    CodecRegDefaultInit(codec->devData->regCfgGroup);
216e41f4b71Sopenharmony_ci    ...
217e41f4b71Sopenharmony_ci    /* Add g_audioControls of the Hi3516 to the controller linked list.*/
218e41f4b71Sopenharmony_ci    AudioAddControls(audioCard, codec->devData->controls, codec->devData->numControls);
219e41f4b71Sopenharmony_ci    ...
220e41f4b71Sopenharmony_ci    /* Load the codec of the Hi3516 to the SAPM. */
221e41f4b71Sopenharmony_ci    AudioSapmNewComponents(audioCard, codec->devData->sapmComponents, codec->devData->numSapmComponent);
222e41f4b71Sopenharmony_ci    ...
223e41f4b71Sopenharmony_ci    /* Add the codec of the Hi3516 to the audioRoutes linked list. */
224e41f4b71Sopenharmony_ci    AudioSapmAddRoutes(audioCard, g_audioRoutes, HDF_ARRAY_SIZE(g_audioRoutes);
225e41f4b71Sopenharmony_ci    ...
226e41f4b71Sopenharmony_ci    AudioSapmNewControls(audioCard);
227e41f4b71Sopenharmony_ci    ...
228e41f4b71Sopenharmony_ci    /* Hi3516 codec power management. */
229e41f4b71Sopenharmony_ci    AudioSapmSleep(audioCard);
230e41f4b71Sopenharmony_ci    ...
231e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
232e41f4b71Sopenharmony_ci}
233e41f4b71Sopenharmony_ci```
234e41f4b71Sopenharmony_ci
235e41f4b71Sopenharmony_ci**CodecDaiDeviceInit** initializes the codec DAI device. This API is not used on the Hi3516 and is reserved.
236e41f4b71Sopenharmony_ci
237e41f4b71Sopenharmony_ci```c
238e41f4b71Sopenharmony_ciint32_t CodecDaiDeviceInit(struct AudioCard *card, const struct DaiDevice *device)
239e41f4b71Sopenharmony_ci
240e41f4b71Sopenharmony_ci{
241e41f4b71Sopenharmony_ci    ...
242e41f4b71Sopenharmony_ci    AUDIO_DRIVER_LOG_DEBUG("codec dai device name: %s\n", device->devDaiName);
243e41f4b71Sopenharmony_ci    (void)card;
244e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
245e41f4b71Sopenharmony_ci}
246e41f4b71Sopenharmony_ci```
247e41f4b71Sopenharmony_ci
248e41f4b71Sopenharmony_ci#### Implementing the Codec Operation Function Set
249e41f4b71Sopenharmony_ci
250e41f4b71Sopenharmony_ciThe codec module is encapsulated with the **read()** and **write()** functions of the read and write registers at the operating system abstraction layer (OSAL).
251e41f4b71Sopenharmony_ci
252e41f4b71Sopenharmony_ciIf the new platform cannot use the OSAL **read()** and **write()** functions to operate registers, you should implement them.
253e41f4b71Sopenharmony_ci
254e41f4b71Sopenharmony_ci```c
255e41f4b71Sopenharmony_ciint32_t AudioDeviceReadReg(unsigned long virtualAddress, uint32_t reg, uint32_t *val)
256e41f4b71Sopenharmony_ci{
257e41f4b71Sopenharmony_ci  ...
258e41f4b71Sopenharmony_ci  *val = OSAL_READL((void *)((uintptr_t)(virtualAddress + reg)));
259e41f4b71Sopenharmony_ci  return HDF_SUCCESS;
260e41f4b71Sopenharmony_ci}
261e41f4b71Sopenharmony_ci
262e41f4b71Sopenharmony_ciint32_t AudioDeviceWriteReg(unsigned long virtualAddress, uint32_t reg, uint32_t value)
263e41f4b71Sopenharmony_ci{
264e41f4b71Sopenharmony_ci  OSAL_WRITEL(value, (void *)((uintptr_t)(virtualAddress + reg)));
265e41f4b71Sopenharmony_ci  return HDF_SUCCESS;
266e41f4b71Sopenharmony_ci}
267e41f4b71Sopenharmony_ci```
268e41f4b71Sopenharmony_ci
269e41f4b71Sopenharmony_ci**CodecDaiStartup** completes startup settings.
270e41f4b71Sopenharmony_ci
271e41f4b71Sopenharmony_ci```c
272e41f4b71Sopenharmony_ciint32_t CodecDaiStartup(const struct AudioCard *card, const struct DaiDevice *device)
273e41f4b71Sopenharmony_ci{
274e41f4b71Sopenharmony_ci  int32_t ret;
275e41f4b71Sopenharmony_ci  ...
276e41f4b71Sopenharmony_ci  (void)card;
277e41f4b71Sopenharmony_ci  ret = CodecSetAdcTuneEnable(device->devData->regCfgGroup);
278e41f4b71Sopenharmony_ci  ...
279e41f4b71Sopenharmony_ci  return HDF_SUCCESS;
280e41f4b71Sopenharmony_ci}
281e41f4b71Sopenharmony_ci```
282e41f4b71Sopenharmony_ci
283e41f4b71Sopenharmony_ci**CodecDaiHwParams** sets parameters, including the sampling rate and bit width.
284e41f4b71Sopenharmony_ci
285e41f4b71Sopenharmony_ci```c
286e41f4b71Sopenharmony_ciint32_t CodecDaiHwParams(const struct AudioCard *card, const struct AudioPcmHwParams *param)
287e41f4b71Sopenharmony_ci{
288e41f4b71Sopenharmony_ci  unsigned int bitWidth;
289e41f4b71Sopenharmony_ci  struct CodecDaiParamsVal codecDaiParamsVal;
290e41f4b71Sopenharmony_ci  ...
291e41f4b71Sopenharmony_ci  int ret = AudioFormatToBitWidth(param->format, &bitWidth);
292e41f4b71Sopenharmony_ci  ...
293e41f4b71Sopenharmony_ci  codecDaiParamsVal.frequencyVal = param->rate;
294e41f4b71Sopenharmony_ci  codecDaiParamsVal.formatVal = bitWidth;
295e41f4b71Sopenharmony_ci  ret = CodecDaiParamsUpdate(card->rtd->codecDai->devData->regCfgGroup, codecDaiParamsVal);
296e41f4b71Sopenharmony_ci  ...
297e41f4b71Sopenharmony_ci  return HDF_SUCCESS;
298e41f4b71Sopenharmony_ci}
299e41f4b71Sopenharmony_ci```
300e41f4b71Sopenharmony_ci
301e41f4b71Sopenharmony_ci#### Registering and Binding Codec to HDF
302e41f4b71Sopenharmony_ci
303e41f4b71Sopenharmony_ciThe following implementation depends on the driver implementation mode of the HDF. For details, see [HDF](driver-overview-foundation.md).
304e41f4b71Sopenharmony_ci
305e41f4b71Sopenharmony_ciFill in the **g_codecDriverEntry** struct. Ensure that the value of **moduleName** is the same as that in **device_info.hcs**. Implement the pointers to the **Bind**, **Init**, and **Release** functions.
306e41f4b71Sopenharmony_ci
307e41f4b71Sopenharmony_cidevice/board/hisilicon/hispark_taurus/audio_drivers/codec/hi3516/src/hi3516_codec_adapter.c
308e41f4b71Sopenharmony_ci
309e41f4b71Sopenharmony_ci```c
310e41f4b71Sopenharmony_cistruct HdfDriverEntry g_codecDriverEntry = {
311e41f4b71Sopenharmony_ci   .moduleVersion = 1,
312e41f4b71Sopenharmony_ci   .moduleName = "CODEC_HI3516",
313e41f4b71Sopenharmony_ci   .Bind = CodecDriverBind,
314e41f4b71Sopenharmony_ci   .Init = CodecDriverInit,
315e41f4b71Sopenharmony_ci   .Release = CodecDriverRelease,
316e41f4b71Sopenharmony_ci};
317e41f4b71Sopenharmony_ciHDF_INIT(g_codecDriverEntry);
318e41f4b71Sopenharmony_ci```
319e41f4b71Sopenharmony_ci
320e41f4b71Sopenharmony_ci**CodecDriverBind** binds the device in the HDF to the codec and registers the codec service with the HDF.
321e41f4b71Sopenharmony_ci
322e41f4b71Sopenharmony_ci```c
323e41f4b71Sopenharmony_cistatic int32_t CodecDriverBind(struct HdfDeviceObject *device)
324e41f4b71Sopenharmony_ci{
325e41f4b71Sopenharmony_ci  struct CodecHost *codecHost = (struct CodecHost *)OsalMemCalloc(sizeof(*codecHost));
326e41f4b71Sopenharmony_ci  ...
327e41f4b71Sopenharmony_ci  codecHost->device = device;
328e41f4b71Sopenharmony_ci  device->service = &codecHost->service;
329e41f4b71Sopenharmony_ci  return HDF_SUCCESS;
330e41f4b71Sopenharmony_ci}
331e41f4b71Sopenharmony_ci```
332e41f4b71Sopenharmony_ci
333e41f4b71Sopenharmony_ci**CodecDriverInit** obtains the **codecService** name and private register configuration, and inserts them into the linked list by using **AudioRegisterCodec**.
334e41f4b71Sopenharmony_ci
335e41f4b71Sopenharmony_ci```c
336e41f4b71Sopenharmony_cistatic int32_t CodecDriverInit(struct HdfDeviceObject *device)
337e41f4b71Sopenharmony_ci{
338e41f4b71Sopenharmony_ci  ...
339e41f4b71Sopenharmony_ci  CodecGetConfigInfo(device, &g_codecData);
340e41f4b71Sopenharmony_ci  CodecSetConfigInfo(&g_codecData, &g_codecDaiData);
341e41f4b71Sopenharmony_ci  CodecGetServiceName(device, &g_codecData.drvCodecName);
342e41f4b71Sopenharmony_ci  CodecGetDaiName(device, &g_codecDaiData.drvDaiName);
343e41f4b71Sopenharmony_ci  AudioRegisterCodec(device, &g_codecData, &g_codecDaiData);
344e41f4b71Sopenharmony_ci  ...
345e41f4b71Sopenharmony_ci  return HDF_SUCCESS;
346e41f4b71Sopenharmony_ci}
347e41f4b71Sopenharmony_ci```
348e41f4b71Sopenharmony_ci
349e41f4b71Sopenharmony_ci**CodecDriverRelease** releases driver resources.
350e41f4b71Sopenharmony_ci
351e41f4b71Sopenharmony_ci```c
352e41f4b71Sopenharmony_cistatic void CodecDriverRelease(struct HdfDeviceObject *device)
353e41f4b71Sopenharmony_ci{
354e41f4b71Sopenharmony_ci   codecHost = (struct CodecHost *)device->service;
355e41f4b71Sopenharmony_ci   OsalMemFree(codecHost);
356e41f4b71Sopenharmony_ci}
357e41f4b71Sopenharmony_ci```
358e41f4b71Sopenharmony_ci
359e41f4b71Sopenharmony_ci#### Configuring HCS
360e41f4b71Sopenharmony_ci
361e41f4b71Sopenharmony_ciConfigure the driver node, loading sequence, and service name in the .hcs file. For details about the HCS syntax, see [Configuration Management](driver-hdf-manage.md) of the HDF.
362e41f4b71Sopenharmony_ci
363e41f4b71Sopenharmony_ciPath of the standard-system configuration file:
364e41f4b71Sopenharmony_ci
365e41f4b71Sopenharmony_ci**vendor/hisilicon/hispark_taurus_standard/hdf_config/khdf/**
366e41f4b71Sopenharmony_ci
367e41f4b71Sopenharmony_ciPath of the small-system configuration file:
368e41f4b71Sopenharmony_ci
369e41f4b71Sopenharmony_ci**vendor/hisilicon/hispark_taurus/hdf_config/**
370e41f4b71Sopenharmony_ci
371e41f4b71Sopenharmony_ci**Configuring Codec Device Information in device_info.hcs**
372e41f4b71Sopenharmony_ci
373e41f4b71Sopenharmony_ciAdd codec node configuration. Modify **moduleName** in the configuration file. The value must be the same as **moduleName** in the **HdfDriverEntry** struct. Generally, the value should present the hardware platform. For example, moduleName = "CODEC_HI3516".
374e41f4b71Sopenharmony_ci
375e41f4b71Sopenharmony_ciThe code snippet is as follows:
376e41f4b71Sopenharmony_ci
377e41f4b71Sopenharmony_ci```c
378e41f4b71Sopenharmony_ci     audio :: host {
379e41f4b71Sopenharmony_ci      device_codec :: device {
380e41f4b71Sopenharmony_ci         device0 :: deviceNode {
381e41f4b71Sopenharmony_ci           policy = 1;     // The codec module provides services only for the kernel.
382e41f4b71Sopenharmony_ci           priority = 50;  // The codec module must be loaded before the load of the HDF_AUDIO module.
383e41f4b71Sopenharmony_ci           preload = 0;
384e41f4b71Sopenharmony_ci           permission = 0666;
385e41f4b71Sopenharmony_ci           moduleName = "CODEC_HI3516";          // The value must be the same as moduleName in HdfDriverEntry.
386e41f4b71Sopenharmony_ci           serviceName = "codec_service_0";      // Name of the service provided externally.
387e41f4b71Sopenharmony_ci           deviceMatchAttr = "hdf_codec_driver"; // Name of the private attribute, which is used to match the corresponding private data (including the register configuration).
388e41f4b71Sopenharmony_ci         }
389e41f4b71Sopenharmony_ci       }
390e41f4b71Sopenharmony_ci```
391e41f4b71Sopenharmony_ci
392e41f4b71Sopenharmony_ci**Configuring Dependencies in audio_config.hcs**
393e41f4b71Sopenharmony_ci
394e41f4b71Sopenharmony_ciConfigure the dependency between the codec, platform, DAI, and DSP on which the audio_card device depends.
395e41f4b71Sopenharmony_ci
396e41f4b71Sopenharmony_ciThe code snippet is as follows:
397e41f4b71Sopenharmony_ci
398e41f4b71Sopenharmony_ci```c
399e41f4b71Sopenharmony_ciroot {
400e41f4b71Sopenharmony_ci    platform {
401e41f4b71Sopenharmony_ci        ...
402e41f4b71Sopenharmony_ci        controller_0x120c1001 :: card_controller {
403e41f4b71Sopenharmony_ci            // Set the private data attribute name, which must be the same as the deviceMatchAttr in device_info.hcs.
404e41f4b71Sopenharmony_ci            match_attr = "hdf_audio_driver_1"; 
405e41f4b71Sopenharmony_ci            serviceName = "hdf_audio_codec_primary_dev11"; // Name of the service provided externally.
406e41f4b71Sopenharmony_ci            codecName = "codec_service_1";       // Codec service name.
407e41f4b71Sopenharmony_ci            platformName = "dma_service_0";      // DMA service.
408e41f4b71Sopenharmony_ci            cpuDaiName = "dai_service";          // CPU DAI service.
409e41f4b71Sopenharmony_ci            codecDaiName = "tfa9879_codec_dai";  // Codec DAI service.
410e41f4b71Sopenharmony_ci            dspName = "dsp_service_0";           // DSP service name.
411e41f4b71Sopenharmony_ci            dspDaiName = "dsp_dai";              // DSP DAI.
412e41f4b71Sopenharmony_ci        }
413e41f4b71Sopenharmony_ci    }
414e41f4b71Sopenharmony_ci}
415e41f4b71Sopenharmony_ci```
416e41f4b71Sopenharmony_ci
417e41f4b71Sopenharmony_ci**Configuring Private Registers in codec_config.hcs**
418e41f4b71Sopenharmony_ci
419e41f4b71Sopenharmony_ciThe configuration matches **deviceMatchAttr** of the codec configured in **device_info.hcs**. It includes the register configuration.
420e41f4b71Sopenharmony_ci
421e41f4b71Sopenharmony_ciBinding the control functionality configuration is to configure the control functionalities and their register parameters in the .hcs file according to unified struct specifications. The configuration can be obtained and parsed, and added to the controller linked list.
422e41f4b71Sopenharmony_ci
423e41f4b71Sopenharmony_ci- **regConfig**: register and control functionality configuration.
424e41f4b71Sopenharmony_ci
425e41f4b71Sopenharmony_ci- **ctrlParamsSeqConfig**: register configuration for a function. The items in **ctrlParamsSeqConfig** must be in the same sequence as the items in **controlsConfig**.
426e41f4b71Sopenharmony_ci
427e41f4b71Sopenharmony_ci- **daiStartupSeqConfig**: DAI startup configuration.
428e41f4b71Sopenharmony_ci
429e41f4b71Sopenharmony_ci- **daiParamsSeqConfig**: playback parameter configuration.
430e41f4b71Sopenharmony_ci
431e41f4b71Sopenharmony_ci- **resetSeqConfig**: reset process register configuration.
432e41f4b71Sopenharmony_ci
433e41f4b71Sopenharmony_ci- **initSeqConfig**: initialization process register configuration.
434e41f4b71Sopenharmony_ci
435e41f4b71Sopenharmony_ci- **controlsConfig**: control function configuration. The **array index** (specific service scenario) and **iface** (same as that in the HAL) have fixed values.
436e41f4b71Sopenharmony_ci
437e41f4b71Sopenharmony_ci- **sapmConfig**: power management and control function configuration. The values of **array index** (specific service scenario) and **iface** (consistent with the HAL) have fixed values.
438e41f4b71Sopenharmony_ci
439e41f4b71Sopenharmony_ci- **ctrlSapmParamsSeqConfig**: register configuration of the power management and control function.
440e41f4b71Sopenharmony_ci
441e41f4b71Sopenharmony_ci- **sapmComponent**: power management component configuration.
442e41f4b71Sopenharmony_ci
443e41f4b71Sopenharmony_ci- **array index**:
444e41f4b71Sopenharmony_ci
445e41f4b71Sopenharmony_ci  The **array index** in **controlsConfig** is the element ID in the **g_audioCodecControlsList** array in the **audio_codec_base.c** file.
446e41f4b71Sopenharmony_ci
447e41f4b71Sopenharmony_ci  The **array index** in **sapmConfig** is the element ID in the **g_audioSapmCfgNameList** array in the **audio_codec_base.c** file.
448e41f4b71Sopenharmony_ci
449e41f4b71Sopenharmony_ci  The **compNameIndex** in **sapmComponent** is the element ID in the **g_audioSapmCompNameList** array in the **audio_codec_base.c** file.
450e41f4b71Sopenharmony_ci
451e41f4b71Sopenharmony_ci- **iface**: **2** for the virtual mixer device.
452e41f4b71Sopenharmony_ci
453e41f4b71Sopenharmony_ci```c
454e41f4b71Sopenharmony_ci root {
455e41f4b71Sopenharmony_ci    platform {
456e41f4b71Sopenharmony_ci        template codec_controller {
457e41f4b71Sopenharmony_ci            match_attr = "";
458e41f4b71Sopenharmony_ci            serviceName = "";
459e41f4b71Sopenharmony_ci            codecDaiName = "";
460e41f4b71Sopenharmony_ci        }
461e41f4b71Sopenharmony_ci        controller_0x120c1030 :: codec_controller {
462e41f4b71Sopenharmony_ci            match_attr = "hdf_codec_driver";
463e41f4b71Sopenharmony_ci            serviceName = "codec_service_0";
464e41f4b71Sopenharmony_ci            codecDaiName = "codec_dai";
465e41f4b71Sopenharmony_ci            
466e41f4b71Sopenharmony_ci            /* Base address of Hi3516 registers. */
467e41f4b71Sopenharmony_ci            idInfo {
468e41f4b71Sopenharmony_ci                chipName = "hi3516";          // Codec name.
469e41f4b71Sopenharmony_ci                chipIdRegister = 0x113c0000;  // Codec base address.
470e41f4b71Sopenharmony_ci                chipIdSize = 0x1000;          // Codec address offset.
471e41f4b71Sopenharmony_ci            }
472e41f4b71Sopenharmony_ci            
473e41f4b71Sopenharmony_ci           /* Register configuration, including configuration of registers. */
474e41f4b71Sopenharmony_ci            regConfig {                
475e41f4b71Sopenharmony_ci               /*   reg: register address
476e41f4b71Sopenharmony_ci                    rreg: register address
477e41f4b71Sopenharmony_ci                    shift: shift bits
478e41f4b71Sopenharmony_ci                    rshift: rshift bits
479e41f4b71Sopenharmony_ci                    min: min value
480e41f4b71Sopenharmony_ci                    max: max value
481e41f4b71Sopenharmony_ci                    mask: mask of value
482e41f4b71Sopenharmony_ci                    invert: enum InvertVal 0-uninvert 1-invert
483e41f4b71Sopenharmony_ci                    value: value
484e41f4b71Sopenharmony_ci                */
485e41f4b71Sopenharmony_ci
486e41f4b71Sopenharmony_ci                /* reg, value */
487e41f4b71Sopenharmony_ci                initSeqConfig = [
488e41f4b71Sopenharmony_ci                    0x14,    0x04000002,
489e41f4b71Sopenharmony_ci                    0x18,    0xFD200004,
490e41f4b71Sopenharmony_ci                    0x1C,    0x00180018,
491e41f4b71Sopenharmony_ci                    0x20,    0x83830028,
492e41f4b71Sopenharmony_ci                    0x24,    0x00005C5C,
493e41f4b71Sopenharmony_ci                    0x28,    0x00130000,
494e41f4b71Sopenharmony_ci                    0x30,    0xFF035A00,
495e41f4b71Sopenharmony_ci                    0x34,    0x08000001,
496e41f4b71Sopenharmony_ci                    0x38,    0x06062424,
497e41f4b71Sopenharmony_ci                    0x3C,    0x1E1EC001,
498e41f4b71Sopenharmony_ci                    0x14,    0x04000002
499e41f4b71Sopenharmony_ci                ];            
500e41f4b71Sopenharmony_ci                
501e41f4b71Sopenharmony_ci                /* Control functionality configuration.
502e41f4b71Sopenharmony_ci                    array index, iface, mixer/mux, enable, */
503e41f4b71Sopenharmony_ci                    0,  2,  0,  0,
504e41f4b71Sopenharmony_ci                    1,  2,  0,  1,
505e41f4b71Sopenharmony_ci                    2,  2,  0,  1,
506e41f4b71Sopenharmony_ci                    3,  2,  0,  1,
507e41f4b71Sopenharmony_ci                    4,  2,  0,  1,
508e41f4b71Sopenharmony_ci                    5,  2,  0,  1,
509e41f4b71Sopenharmony_ci                    8,  2,  0,  0,
510e41f4b71Sopenharmony_ci                    9,  2,  0,  0,
511e41f4b71Sopenharmony_ci                ];                
512e41f4b71Sopenharmony_ci                /* Control functionality register configuration 
513e41f4b71Sopenharmony_ci                   reg, rreg, shift, rshift, min, max, mask, invert, value */
514e41f4b71Sopenharmony_ci                ctrlParamsSeqConfig = [
515e41f4b71Sopenharmony_ci                    0x3c, 0x3c, 24, 24, 0x0, 0x57, 0x7F, 1, 0,   // "Main Capture Volume"
516e41f4b71Sopenharmony_ci                    0x38, 0x38, 31, 31, 0x0, 0x1, 0x1, 0, 0,     // "Playback Mute"
517e41f4b71Sopenharmony_ci                    0x3c, 0x3c, 31, 31, 0x0, 0x1, 0x1, 0, 0,     // "Capture Mute"
518e41f4b71Sopenharmony_ci                    0x20, 0x20, 16, 16, 0x0, 0xF, 0x1F, 0, 0,    // "Mic Left Gain"
519e41f4b71Sopenharmony_ci                    0x20, 0x20, 24, 24, 0x0, 0xF, 0x1F, 0, 0,    // "Mic Right Gain"
520e41f4b71Sopenharmony_ci                    0x2000, 0x2000, 16, 16, 0x0, 0x7, 0x7, 0, 0, // "Render Channel Mode"
521e41f4b71Sopenharmony_ci                    0x1000, 0x1000, 16, 16, 0x0, 0x7, 0x7, 0, 0  // "Capture Channel Mode"
522e41f4b71Sopenharmony_ci                ];
523e41f4b71Sopenharmony_ci
524e41f4b71Sopenharmony_ci                /* After the upper layer delivers parameters, write audio-related data to registers.
525e41f4b71Sopenharmony_ci                   reg, rreg, shift, rshift, min, max, mask, invert, value */
526e41f4b71Sopenharmony_ci                daiParamsSeqConfig = [  
527e41f4b71Sopenharmony_ci                    0x30, 0x30, 13, 13, 0x0, 0x1F, 0x1F, 0, 0x0,   // i2s_frequency
528e41f4b71Sopenharmony_ci                    0x1C, 0x1C, 6, 6, 0x0, 0x3, 0x3, 0, 0x0,       // adc_mode_sel
529e41f4b71Sopenharmony_ci                    0x30, 0x30, 22, 22, 0x0, 0x3, 0x3, 0, 0x0,     // i2s_datawith
530e41f4b71Sopenharmony_ci                ];
531e41f4b71Sopenharmony_ci
532e41f4b71Sopenharmony_ci                /* Configuration of the power management function register.
533e41f4b71Sopenharmony_ci                   reg, rreg, shift, rshift, min, max, mask, invert, value */
534e41f4b71Sopenharmony_ci                ctrlSapmParamsSeqConfig = [  
535e41f4b71Sopenharmony_ci                    0x20, 0x20, 23, 23, 0x0, 0x1, 0x1, 0, 0,  // LPGA MIC 0 -- connect MIC
536e41f4b71Sopenharmony_ci                    0x20, 0x20, 31, 31, 0x0, 0x1, 0x1, 0, 0,  // RPGA MIC 0 -- connect MIC
537e41f4b71Sopenharmony_ci                    0x30, 0x30, 27, 27, 0x0, 0x1, 0x1, 0, 0,  // dacl to dacr mixer
538e41f4b71Sopenharmony_ci                    0x30, 0x30, 26, 26, 0x0, 0x1, 0x1, 0, 0   // dacr to dacl mixer
539e41f4b71Sopenharmony_ci                ];
540e41f4b71Sopenharmony_ci
541e41f4b71Sopenharmony_ci                /*
542e41f4b71Sopenharmony_ci                 Power management component configuration.
543e41f4b71Sopenharmony_ci                 sapmType, compNameIndex, reg, mask, shift, invert, kcontrolNews, kcontrolsNum
544e41f4b71Sopenharmony_ci                 reg = 0xFFFF: component has no sapm register bit
545e41f4b71Sopenharmony_ci                */
546e41f4b71Sopenharmony_ci                sapmComponent = [ 
547e41f4b71Sopenharmony_ci                    10, 0,    0x20,    0x1, 15,  1, 0, 0, // ADCL
548e41f4b71Sopenharmony_ci                    10, 1,    0x20,    0x1, 14,  1, 0, 0, // ADCR
549e41f4b71Sopenharmony_ci                    11, 2,    0x14,    0x1, 11,  1, 0, 0, // DACL
550e41f4b71Sopenharmony_ci                    11, 3,    0x14,    0x1, 12,  1, 0, 0, // DACR
551e41f4b71Sopenharmony_ci                    17, 4,    0x20,    0x1, 13,  1, 1, 1, // LPGA
552e41f4b71Sopenharmony_ci                    17, 5,    0x20,    0x1, 12,  1, 2, 1, // RPGA
553e41f4b71Sopenharmony_ci                    15, 6,  0xFFFF, 0xFFFF,  0,  0, 0, 0, // SPKL
554e41f4b71Sopenharmony_ci                    15, 7,  0xFFFF, 0xFFFF,  0,  0, 0, 0, // SPKR
555e41f4b71Sopenharmony_ci                    17, 52, 0xFFFF, 0xFFFF,  0,  0, 3, 1, // SPKL PGA
556e41f4b71Sopenharmony_ci                    17, 53, 0xFFFF, 0xFFFF,  0,  0, 4, 1, // SPKR PGA
557e41f4b71Sopenharmony_ci                    13, 40, 0xFFFF, 0xFFFF,  0,  0, 0, 0, // MIC1
558e41f4b71Sopenharmony_ci                    13, 41, 0xFFFF, 0xFFFF,  0,  0, 0, 0  // MIC2
559e41f4b71Sopenharmony_ci                ];
560e41f4b71Sopenharmony_ci                
561e41f4b71Sopenharmony_ci              /* Power management function configuration.
562e41f4b71Sopenharmony_ci                   array index, iface, mixer/mux, enable
563e41f4b71Sopenharmony_ci              */ 
564e41f4b71Sopenharmony_ci                sapmConfig = [
565e41f4b71Sopenharmony_ci                    0,    2,    0,    1,
566e41f4b71Sopenharmony_ci                    1,    2,    0,    1,
567e41f4b71Sopenharmony_ci                    2,    2,    0,    1,
568e41f4b71Sopenharmony_ci                    3,    2,    0,    1
569e41f4b71Sopenharmony_ci                ];
570e41f4b71Sopenharmony_ci            }
571e41f4b71Sopenharmony_ci        }
572e41f4b71Sopenharmony_ci    }
573e41f4b71Sopenharmony_ci}
574e41f4b71Sopenharmony_ci```
575e41f4b71Sopenharmony_ci
576e41f4b71Sopenharmony_ciRead the .hcs files in the C code to obtain register configuration.
577e41f4b71Sopenharmony_ci
578e41f4b71Sopenharmony_ci```c
579e41f4b71Sopenharmony_cistatic int32_t CodecDriverInit(struct HdfDeviceObject *device)
580e41f4b71Sopenharmony_ci{
581e41f4b71Sopenharmony_ci  ...
582e41f4b71Sopenharmony_ci  CodecGetConfigInfo(device, &g_codecData) ;
583e41f4b71Sopenharmony_ci  CodecSetConfigInfo(&g_codecData, &g_codecDaiData);
584e41f4b71Sopenharmony_ci  ...
585e41f4b71Sopenharmony_ci  return HDF_SUCCESS;
586e41f4b71Sopenharmony_ci} 
587e41f4b71Sopenharmony_ci```
588e41f4b71Sopenharmony_ci
589e41f4b71Sopenharmony_ciWhen the codec is registered, the input parameter **device** contains controller_0x120c1030 node information. You only need to parse the node to obtain the configuration information.
590e41f4b71Sopenharmony_ci
591e41f4b71Sopenharmony_ci```c
592e41f4b71Sopenharmony_ciint32_t CodecGetConfigInfo(const struct HdfDeviceObject *device, struct CodecData *codecData)
593e41f4b71Sopenharmony_ci{
594e41f4b71Sopenharmony_ci  codecData->regConfig = (struct AudioRegCfgData *)OsalMemCalloc(sizeof(*(codecData->regConfig)));
595e41f4b71Sopenharmony_ci  CodecGetRegConfig(device, codecData->regConfig);
596e41f4b71Sopenharmony_ci  return HDF_SUCCESS;
597e41f4b71Sopenharmony_ci}
598e41f4b71Sopenharmony_ci```
599e41f4b71Sopenharmony_ci
600e41f4b71Sopenharmony_ciObtain the node configuration to configure the node.
601e41f4b71Sopenharmony_ci
602e41f4b71Sopenharmony_ci```c
603e41f4b71Sopenharmony_ciint32_t CodecGetRegConfig(const struct HdfDeviceObject *device, struct AudioRegCfgData *configData)
604e41f4b71Sopenharmony_ci{
605e41f4b71Sopenharmony_ci    ...
606e41f4b71Sopenharmony_ci    drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
607e41f4b71Sopenharmony_ci    ...
608e41f4b71Sopenharmony_ci    idNode = drsOps->GetChildNode(root, "idInfo");
609e41f4b71Sopenharmony_ci    ParseAudioAttr(drsOps, idNode, &configData->audioIdInfo);
610e41f4b71Sopenharmony_ci    regCfgNode = drsOps->GetChildNode(root, "regConfig");
611e41f4b71Sopenharmony_ci    ...
612e41f4b71Sopenharmony_ci    DEV_RES_NODE_FOR_EACH_ATTR(regCfgNode, regAttr) {
613e41f4b71Sopenharmony_ci    ...
614e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
615e41f4b71Sopenharmony_ci}
616e41f4b71Sopenharmony_ci```
617e41f4b71Sopenharmony_ci
618e41f4b71Sopenharmony_ciObtain and use the configuration of the **regConfig** node. After the configuration files are parsed, the register information in the code can be directly updated.
619e41f4b71Sopenharmony_ci
620e41f4b71Sopenharmony_ci```c
621e41f4b71Sopenharmony_ciint32_t CodecDeviceInit(struct AudioCard *audioCard, struct CodecDevice *codec)
622e41f4b71Sopenharmony_ci{
623e41f4b71Sopenharmony_ci...
624e41f4b71Sopenharmony_ci    if (CodecRegDefaultInit(codec->devData->regCfgGroup) != HDF_SUCCESS) {
625e41f4b71Sopenharmony_ci        AUDIO_DRIVER_LOG_ERR("CodecRegDefaultInit failed.");
626e41f4b71Sopenharmony_ci        return HDF_FAILURE;
627e41f4b71Sopenharmony_ci    }
628e41f4b71Sopenharmony_ci...
629e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
630e41f4b71Sopenharmony_ci}
631e41f4b71Sopenharmony_ci```
632e41f4b71Sopenharmony_ci
633e41f4b71Sopenharmony_ci### SmartPA Driver Development Example
634e41f4b71Sopenharmony_ci
635e41f4b71Sopenharmony_ciCode path: **device/board/hisilicon/hispark_taurus/audio_drivers/codec/tfa9879**
636e41f4b71Sopenharmony_ci
637e41f4b71Sopenharmony_ciThe SmartPA is a type of codec driver. The development process is as follows:
638e41f4b71Sopenharmony_ci
639e41f4b71Sopenharmony_ci1. Define and fill in a codec instance.
640e41f4b71Sopenharmony_ci2. Implement callbacks for the codec instance.
641e41f4b71Sopenharmony_ci3. Register and bind the codec instance to the HDF.
642e41f4b71Sopenharmony_ci4. Configure the HCS and makefile.
643e41f4b71Sopenharmony_ci
644e41f4b71Sopenharmony_ci#### Filling in the Codec Data Structs
645e41f4b71Sopenharmony_ci
646e41f4b71Sopenharmony_ciFill in the following data structs for the codec module:
647e41f4b71Sopenharmony_ci
648e41f4b71Sopenharmony_ci- **g_tfa9879Data**: operation function set of the codec device. It contains the configuration in the .hcs file, and defines and maps the functions for initializing the codec device and reading and writing registers.
649e41f4b71Sopenharmony_ci
650e41f4b71Sopenharmony_ci- **g_tfa9879DaiDeviceOps**: DAI data set that defines and maps the operations of the codec device DAI.
651e41f4b71Sopenharmony_ci
652e41f4b71Sopenharmony_ci- **g_tfa9879DaiData**: DAI data set that defines and maps the driver name, initialization, and operations of the data access interfaces of the codec device.
653e41f4b71Sopenharmony_ci
654e41f4b71Sopenharmony_ci```c
655e41f4b71Sopenharmony_cistruct CodecData g_tfa9879Data = {
656e41f4b71Sopenharmony_ci    .Init = Tfa9879DeviceInit,
657e41f4b71Sopenharmony_ci    .Read = CodecDeviceRegI2cRead,
658e41f4b71Sopenharmony_ci    .Write = CodecDeviceRegI2cWrite,
659e41f4b71Sopenharmony_ci};
660e41f4b71Sopenharmony_ci
661e41f4b71Sopenharmony_cistruct AudioDaiOps g_tfa9879DaiDeviceOps = {
662e41f4b71Sopenharmony_ci    .Startup = Tfa9879DaiStartup,
663e41f4b71Sopenharmony_ci    .HwParams = Tfa9879DaiHwParams,
664e41f4b71Sopenharmony_ci};
665e41f4b71Sopenharmony_ci
666e41f4b71Sopenharmony_cistruct DaiData g_tfa9879DaiData = {
667e41f4b71Sopenharmony_ci    .drvDaiName = "tfa9879_codec_dai",
668e41f4b71Sopenharmony_ci    .DaiInit = Tfa9879DaiDeviceInit,
669e41f4b71Sopenharmony_ci    .ops = &g_tfa9879DaiDeviceOps,
670e41f4b71Sopenharmony_ci    .Read = CodecDaiRegI2cRead,
671e41f4b71Sopenharmony_ci    .Write = CodecDaiRegI2cWrite,
672e41f4b71Sopenharmony_ci};
673e41f4b71Sopenharmony_ci```
674e41f4b71Sopenharmony_ci
675e41f4b71Sopenharmony_ci#### Initializing codecDevice and codecDai
676e41f4b71Sopenharmony_ci
677e41f4b71Sopenharmony_ciAs the entry function for device initialization, **Tfa9879DeviceInit** sets the address of the SmartPA I2C device, obtains configuration data, initializes (including resets) the device registers, and adds the control functionality to the controller linked list. The current demo also includes the initialization of the registers related to the Hi3516D V300 device, such as initialization of GPIO pins.
678e41f4b71Sopenharmony_ci
679e41f4b71Sopenharmony_ci```c
680e41f4b71Sopenharmony_ciint32_t Tfa9879DeviceInit(struct AudioCard *audioCard, const struct CodecDevice *device)
681e41f4b71Sopenharmony_ci{
682e41f4b71Sopenharmony_ci    int32_t ret;
683e41f4b71Sopenharmony_ci    ...
684e41f4b71Sopenharmony_ci    // Initialize GPIO pins.
685e41f4b71Sopenharmony_ci    ret = Hi35xxGpioPinInit();
686e41f4b71Sopenharmony_ci    ...
687e41f4b71Sopenharmony_ci    // Set I2C parameters.
688e41f4b71Sopenharmony_ci    g_transferParam.i2cBusNumber = TFA9879_I2C_BUS_NUMBER;
689e41f4b71Sopenharmony_ci    g_transferParam.i2cDevAddr = TFA9879_I2C_DEV_ADDR;
690e41f4b71Sopenharmony_ci    g_transferParam.i2cRegDataLen = TFA9879_I2C_REG_DATA_LEN;
691e41f4b71Sopenharmony_ci    device->devData->privateParam = &g_transferParam;
692e41f4b71Sopenharmony_ci    ...
693e41f4b71Sopenharmony_ci    // Initialize device registers.
694e41f4b71Sopenharmony_ci    ret = CodecDeviceInitRegConfig(device);
695e41f4b71Sopenharmony_ci    ...
696e41f4b71Sopenharmony_ci    // Bind the control functionality configuration.
697e41f4b71Sopenharmony_ci    if (AudioAddControls(audioCard, device->devData->controls, device->devData->numControls) !=
698e41f4b71Sopenharmony_ci        HDF_SUCCESS) {
699e41f4b71Sopenharmony_ci        AUDIO_DRIVER_LOG_ERR("add controls failed.");
700e41f4b71Sopenharmony_ci        return HDF_FAILURE;
701e41f4b71Sopenharmony_ci    }
702e41f4b71Sopenharmony_ci    ...
703e41f4b71Sopenharmony_ci}
704e41f4b71Sopenharmony_ci```
705e41f4b71Sopenharmony_ci
706e41f4b71Sopenharmony_ciCommon functions of the I2C read/write registers:
707e41f4b71Sopenharmony_ci
708e41f4b71Sopenharmony_ci```c
709e41f4b71Sopenharmony_ciint32_t CodecDeviceRegI2cRead(const struct CodecDevice *codec, uint32_t reg, uint32_t *val)
710e41f4b71Sopenharmony_ci{
711e41f4b71Sopenharmony_ci    int32_t ret;
712e41f4b71Sopenharmony_ci    struct AudioAddrConfig regAttr;
713e41f4b71Sopenharmony_ci    struct I2cTransferParam *i2cTransferParam = NULL;
714e41f4b71Sopenharmony_ci    ...
715e41f4b71Sopenharmony_ci    i2cTransferParam = (struct I2cTransferParam *)codec->devData->privateParam;
716e41f4b71Sopenharmony_ci    ...
717e41f4b71Sopenharmony_ci    regAttr.addr = (uint8_t)reg;
718e41f4b71Sopenharmony_ci    regAttr.value = 0;
719e41f4b71Sopenharmony_ci    ret = CodecI2cTransfer(i2cTransferParam, &regAttr, I2C_FLAG_READ);
720e41f4b71Sopenharmony_ci    ...
721e41f4b71Sopenharmony_ci    *val = regAttr.value;
722e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
723e41f4b71Sopenharmony_ci}
724e41f4b71Sopenharmony_ci
725e41f4b71Sopenharmony_ciint32_t CodecDeviceRegI2cWrite(const struct CodecDevice *codec, uint32_t reg, uint32_t value)
726e41f4b71Sopenharmony_ci{
727e41f4b71Sopenharmony_ci    int32_t ret;
728e41f4b71Sopenharmony_ci    struct AudioAddrConfig regAttr;
729e41f4b71Sopenharmony_ci    struct I2cTransferParam *i2cTransferParam = NULL;
730e41f4b71Sopenharmony_ci    ...
731e41f4b71Sopenharmony_ci    i2cTransferParam = (struct I2cTransferParam *)codec->devData->privateParam;
732e41f4b71Sopenharmony_ci    ...
733e41f4b71Sopenharmony_ci    regAttr.addr = (uint8_t)reg;
734e41f4b71Sopenharmony_ci    regAttr.value = (uint16_t)value;
735e41f4b71Sopenharmony_ci    ret = CodecI2cTransfer(i2cTransferParam, &regAttr, 0);
736e41f4b71Sopenharmony_ci    ...
737e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
738e41f4b71Sopenharmony_ci}
739e41f4b71Sopenharmony_ci
740e41f4b71Sopenharmony_ciint32_t CodecDaiRegI2cRead(const struct DaiDevice *dai, uint32_t reg, uint32_t *value)
741e41f4b71Sopenharmony_ci{
742e41f4b71Sopenharmony_ci    ...
743e41f4b71Sopenharmony_ci    ret = CodecI2cTransfer(i2cTransferParam, &regAttr, I2C_FLAG_READ);
744e41f4b71Sopenharmony_ci    ...
745e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
746e41f4b71Sopenharmony_ci}
747e41f4b71Sopenharmony_ci
748e41f4b71Sopenharmony_ciint32_t CodecDaiRegI2cWrite(const struct DaiDevice *dai, uint32_t reg, uint32_t value)
749e41f4b71Sopenharmony_ci{
750e41f4b71Sopenharmony_ci    ...
751e41f4b71Sopenharmony_ci    ret = CodecI2cTransfer(i2cTransferParam, &regAttr, 0);
752e41f4b71Sopenharmony_ci    ...
753e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
754e41f4b71Sopenharmony_ci}
755e41f4b71Sopenharmony_ci```
756e41f4b71Sopenharmony_ci
757e41f4b71Sopenharmony_ci#### Implementing the Codec Operation Function Set
758e41f4b71Sopenharmony_ci
759e41f4b71Sopenharmony_ci**Tfa9879DaiStartup** performs startup settings. The code snippet is as follows:
760e41f4b71Sopenharmony_ci
761e41f4b71Sopenharmony_ci```c
762e41f4b71Sopenharmony_ciint32_t Tfa9879DaiStartup(const struct AudioCard *card, const struct DaiDevice *device)
763e41f4b71Sopenharmony_ci{
764e41f4b71Sopenharmony_ci    int ret;
765e41f4b71Sopenharmony_ci    (void)card;
766e41f4b71Sopenharmony_ci    (void)device;
767e41f4b71Sopenharmony_ci    // Set the register for starting the SmartPA.
768e41f4b71Sopenharmony_ci    ret = CodecDaiDeviceStartupRegConfig(device);
769e41f4b71Sopenharmony_ci    ...
770e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
771e41f4b71Sopenharmony_ci}
772e41f4b71Sopenharmony_ci
773e41f4b71Sopenharmony_ci```
774e41f4b71Sopenharmony_ci
775e41f4b71Sopenharmony_ci**Tfa9879DaiHwParams** delivers playback parameters. The code snippet is as follows:
776e41f4b71Sopenharmony_ci
777e41f4b71Sopenharmony_ci```c
778e41f4b71Sopenharmony_ciint32_t Tfa9879DaiHwParams(const struct AudioCard *card, const struct AudioPcmHwParams *param)
779e41f4b71Sopenharmony_ci{
780e41f4b71Sopenharmony_ci    int32_t ret;
781e41f4b71Sopenharmony_ci    uint16_t frequency, bitWidth;
782e41f4b71Sopenharmony_ci    struct DaiParamsVal daiParamsVal;
783e41f4b71Sopenharmony_ci    (void)card;
784e41f4b71Sopenharmony_ci    ...
785e41f4b71Sopenharmony_ci    // Set the sampling rate.
786e41f4b71Sopenharmony_ci    ret = Tfa9879FrequencyParse(param->rate, &frequency);
787e41f4b71Sopenharmony_ci    ...
788e41f4b71Sopenharmony_ci    // Set the bit width.
789e41f4b71Sopenharmony_ci    ret = Tfa9879FormatParse(param->format, &bitWidth);
790e41f4b71Sopenharmony_ci    ...
791e41f4b71Sopenharmony_ci    daiParamsVal.frequencyVal = frequency;
792e41f4b71Sopenharmony_ci    daiParamsVal.formatVal = bitWidth;
793e41f4b71Sopenharmony_ci    daiParamsVal.channelVal = param->channels; // Set the audio channel.
794e41f4b71Sopenharmony_ci    ret = Tfa9879DaiParamsUpdate(card->rtd->codecDai, daiParamsVal);
795e41f4b71Sopenharmony_ci    ...
796e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
797e41f4b71Sopenharmony_ci}
798e41f4b71Sopenharmony_ci```
799e41f4b71Sopenharmony_ci
800e41f4b71Sopenharmony_ci#### Registering and Binding Codec to HDF
801e41f4b71Sopenharmony_ci
802e41f4b71Sopenharmony_ciThe following implementation depends on the driver implementation mode of the HDF. For details, see [HDF](driver-overview-foundation.md).
803e41f4b71Sopenharmony_ci
804e41f4b71Sopenharmony_ciFill in the **g_tfa9879DriverEntry** struct. Ensure that the value of **moduleName** is the same as that in **device_info.hcs**. Implement the pointers to the **Bind**, **Init**, and **Release** functions.
805e41f4b71Sopenharmony_ci
806e41f4b71Sopenharmony_cidevice/board/hisilicon/hispark_taurus/audio_drivers/codec/tfa9879/src/tfa9879_accessory_adapter.c
807e41f4b71Sopenharmony_ci
808e41f4b71Sopenharmony_ci```c
809e41f4b71Sopenharmony_cistatic int32_t Tfa9879DriverBind(struct HdfDeviceObject *device)
810e41f4b71Sopenharmony_ci{
811e41f4b71Sopenharmony_ci    (void)device;
812e41f4b71Sopenharmony_ci    AUDIO_DRIVER_LOG_INFO("success!");
813e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
814e41f4b71Sopenharmony_ci}
815e41f4b71Sopenharmony_ci
816e41f4b71Sopenharmony_cistatic int32_t Tfa9879DriverInit(struct HdfDeviceObject *device)
817e41f4b71Sopenharmony_ci{
818e41f4b71Sopenharmony_ci    int32_t ret;
819e41f4b71Sopenharmony_ci    ...
820e41f4b71Sopenharmony_ci    // Obtain configuration data from .hcs files.
821e41f4b71Sopenharmony_ci    ret = CodecGetConfigInfo(device, &g_tfa9879Data);
822e41f4b71Sopenharmony_ci    ...
823e41f4b71Sopenharmony_ci    // Set the interface functions and register information related to codec control.
824e41f4b71Sopenharmony_ci    ret = CodecSetConfigInfoOfControls(&g_tfa9879Data, &g_tfa9879DaiData);
825e41f4b71Sopenharmony_ci    ...
826e41f4b71Sopenharmony_ci    ret = CodecGetServiceName(device, &g_tfa9879Data.drvCodecName);
827e41f4b71Sopenharmony_ci    ...
828e41f4b71Sopenharmony_ci    ret = CodecGetDaiName(device, &g_tfa9879DaiData.drvDaiName);
829e41f4b71Sopenharmony_ci    ...
830e41f4b71Sopenharmony_ci    // Register the codec with the audio adapter.
831e41f4b71Sopenharmony_ci    ret = AudioRegisterCodec(device, &g_tfa9879Data, &g_tfa9879DaiData);
832e41f4b71Sopenharmony_ci    ....
833e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
834e41f4b71Sopenharmony_ci}
835e41f4b71Sopenharmony_ci
836e41f4b71Sopenharmony_ci/* HdfDriverEntry definitions */
837e41f4b71Sopenharmony_cistruct HdfDriverEntry g_tfa9879DriverEntry = {
838e41f4b71Sopenharmony_ci    .moduleVersion = 1,
839e41f4b71Sopenharmony_ci    .moduleName = "CODEC_TFA9879",
840e41f4b71Sopenharmony_ci    .Bind = Tfa9879DriverBind,
841e41f4b71Sopenharmony_ci    .Init = Tfa9879DriverInit,
842e41f4b71Sopenharmony_ci    .Release = NULL,
843e41f4b71Sopenharmony_ci};
844e41f4b71Sopenharmony_ciHDF_INIT(g_tfa9879DriverEntry);
845e41f4b71Sopenharmony_ci```
846e41f4b71Sopenharmony_ci
847e41f4b71Sopenharmony_ci#### Configuring HCS
848e41f4b71Sopenharmony_ci
849e41f4b71Sopenharmony_ciFor details about the configuration process, see [Configuring HCS](#configuring-hcs) in **Codec Driver Development Example**.
850e41f4b71Sopenharmony_ci
851e41f4b71Sopenharmony_ci### Platform Driver Development Example
852e41f4b71Sopenharmony_ci
853e41f4b71Sopenharmony_ciCode path: **device/board/hisilicon/hispark_taurus/audio_drivers/soc**
854e41f4b71Sopenharmony_ci
855e41f4b71Sopenharmony_ciIn audio driver development, the Platform module is configured to adapt to the DMA driver. The major steps for developing the platform driver are as follows:
856e41f4b71Sopenharmony_ci
857e41f4b71Sopenharmony_ci1. Define and fill in a platform instance.
858e41f4b71Sopenharmony_ci2. Implement callbacks for the platform instance.
859e41f4b71Sopenharmony_ci3. Register and bind the codec instance to the HDF.
860e41f4b71Sopenharmony_ci4. Configure the HCS and makefile.
861e41f4b71Sopenharmony_ci
862e41f4b71Sopenharmony_ci#### Filling in Platform Data Structures
863e41f4b71Sopenharmony_ci
864e41f4b71Sopenharmony_ciFill in the following structs for the platform module:
865e41f4b71Sopenharmony_ci
866e41f4b71Sopenharmony_ci- **g_platformData**: private configuration of the platform device, including the initialization and operation functions of the platform device.
867e41f4b71Sopenharmony_ci
868e41f4b71Sopenharmony_ci- **g_dmaDeviceOps**: DMA device operation function set, including the encapsulation of some common DMA APIs.
869e41f4b71Sopenharmony_ci
870e41f4b71Sopenharmony_ci```c
871e41f4b71Sopenharmony_cistruct AudioDmaOps g_dmaDeviceOps = {
872e41f4b71Sopenharmony_ci    .DmaBufAlloc = Hi3516DmaBufAlloc,             // Apply for memory for the DMA device.
873e41f4b71Sopenharmony_ci    .DmaBufFree = Hi3516DmaBufFree,               // Release the memory of the DMA device.
874e41f4b71Sopenharmony_ci    .DmaRequestChannel = Hi3516DmaRequestChannel, // Request a DMA channel.
875e41f4b71Sopenharmony_ci    .DmaConfigChannel = Hi3516DmaConfigChannel,   // Configure the DMA channel.
876e41f4b71Sopenharmony_ci    .DmaPrep = Hi3516DmaPrep,                     // Prepare for DMA.
877e41f4b71Sopenharmony_ci    .DmaSubmit = Hi3516DmaSubmit,                 // Submit a DMA request. 
878e41f4b71Sopenharmony_ci    .DmaPending = Hi3516DmaPending,               // Pend DMA.
879e41f4b71Sopenharmony_ci    .DmaPause = Hi3516DmaPause,                   // Pause or stop the DMA service.
880e41f4b71Sopenharmony_ci    .DmaResume = Hi3516DmaResume,                 // Resume the DMA service.
881e41f4b71Sopenharmony_ci    .DmaPointer = Hi3516DmaPointer,               // Obtain the current playing or recording position.
882e41f4b71Sopenharmony_ci};
883e41f4b71Sopenharmony_ci
884e41f4b71Sopenharmony_cistruct PlatformData g_platformData = {
885e41f4b71Sopenharmony_ci    .PlatformInit = AudioDmaDeviceInit, // Initialize the DMA device.
886e41f4b71Sopenharmony_ci    .ops = &g_dmaDeviceOps,
887e41f4b71Sopenharmony_ci};
888e41f4b71Sopenharmony_ci```
889e41f4b71Sopenharmony_ci
890e41f4b71Sopenharmony_ci#### Initializing dmaDevice
891e41f4b71Sopenharmony_ci
892e41f4b71Sopenharmony_ci**AudioDmaDeviceInit** initializes the DMA device, including setting the Hi3516 AIAO module.
893e41f4b71Sopenharmony_ci
894e41f4b71Sopenharmony_ci```c
895e41f4b71Sopenharmony_ciint32_t AudioDmaDeviceInit(const struct AudioCard *card, const struct PlatformDevice *platformDevice)
896e41f4b71Sopenharmony_ci{
897e41f4b71Sopenharmony_ci... 
898e41f4b71Sopenharmony_ci    AiaoHalSysInit();
899e41f4b71Sopenharmony_ci    /* PIN MUX */
900e41f4b71Sopenharmony_ci    AiaoSysPinMux();
901e41f4b71Sopenharmony_ci    /* CLK reset */
902e41f4b71Sopenharmony_ci    AiaoClockReset();
903e41f4b71Sopenharmony_ci    /* AIAO initialization */
904e41f4b71Sopenharmony_ci    AiaoDeviceInit(chnId);
905e41f4b71Sopenharmony_ci...
906e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
907e41f4b71Sopenharmony_ci}
908e41f4b71Sopenharmony_ci```
909e41f4b71Sopenharmony_ci
910e41f4b71Sopenharmony_ci#### Implementing the DMA Operation Function Set
911e41f4b71Sopenharmony_ci
912e41f4b71Sopenharmony_ciThe DMA device operation function set includes the encapsulation of DMA common APIs. If the common APIs cannot meet development requirements, you can implement new DMA callbacks.
913e41f4b71Sopenharmony_ci
914e41f4b71Sopenharmony_ci```c
915e41f4b71Sopenharmony_ciint32_t AudioDmaDeviceInit(const struct AudioCard *card, const struct PlatformDevice *platform);
916e41f4b71Sopenharmony_ciint32_t Hi3516DmaBufAlloc(struct PlatformData *data, const enum AudioStreamType streamType);
917e41f4b71Sopenharmony_ciint32_t Hi3516DmaBufFree(struct PlatformData *data, const enum AudioStreamType streamType);
918e41f4b71Sopenharmony_ciint32_t Hi3516DmaRequestChannel(const struct PlatformData *data, const enum AudioStreamType streamType);
919e41f4b71Sopenharmony_ciint32_t Hi3516DmaConfigChannel(const struct PlatformData *data, const enum AudioStreamType streamType);
920e41f4b71Sopenharmony_ciint32_t Hi3516DmaPrep(const struct PlatformData *data, const enum AudioStreamType streamType);
921e41f4b71Sopenharmony_ciint32_t Hi3516DmaSubmit(const struct PlatformData *data, const enum AudioStreamType streamType);
922e41f4b71Sopenharmony_ciint32_t Hi3516DmaPending(struct PlatformData *data, const enum AudioStreamType streamType);
923e41f4b71Sopenharmony_ciint32_t Hi3516DmaPause(struct PlatformData *data, const enum AudioStreamType streamType);
924e41f4b71Sopenharmony_ciint32_t Hi3516DmaResume(const struct PlatformData *data, const enum AudioStreamType streamType);
925e41f4b71Sopenharmony_ciint32_t Hi3516DmaPointer(struct PlatformData *data, const enum AudioStreamType streamType, uint32_t *pointer);
926e41f4b71Sopenharmony_ci```
927e41f4b71Sopenharmony_ci
928e41f4b71Sopenharmony_ci#### Registering and Binding Platform to HDF
929e41f4b71Sopenharmony_ci
930e41f4b71Sopenharmony_ciThe following implementation depends on the driver implementation mode of the HDF. For details, see [HDF](driver-overview-foundation.md).
931e41f4b71Sopenharmony_ci
932e41f4b71Sopenharmony_ci- Fill in the **g_platformDriverEntry** struct.
933e41f4b71Sopenharmony_ci- Ensure that the value of **moduleName** is the same as that in **device_info.hcs**.
934e41f4b71Sopenharmony_ci- Implement the pointers to the **Bind**, **Init**, and **Release** functions.
935e41f4b71Sopenharmony_ci
936e41f4b71Sopenharmony_ci**device/board/hisilicon/hispark_taurus/audio_drivers/soc/src/hi3516_dma_adapter.c**
937e41f4b71Sopenharmony_ci
938e41f4b71Sopenharmony_ci```c
939e41f4b71Sopenharmony_cistatic int32_t Hi3516DmaDriverInit(struct HdfDeviceObject *device)
940e41f4b71Sopenharmony_ci{
941e41f4b71Sopenharmony_ci...
942e41f4b71Sopenharmony_ci    OsalMutexInit(&g_platformData.renderBufInfo.buffMutex);
943e41f4b71Sopenharmony_ci    OsalMutexInit(&g_platformData.captureBufInfo.buffMutex);
944e41f4b71Sopenharmony_ci    g_platformData.platformInitFlag = false;
945e41f4b71Sopenharmony_ci    ret = AudioSocRegisterPlatform(device, &g_platformData);
946e41f4b71Sopenharmony_ci...
947e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
948e41f4b71Sopenharmony_ci}
949e41f4b71Sopenharmony_ci
950e41f4b71Sopenharmony_cistatic void Hi3516DmaDriverRelease(struct HdfDeviceObject *device)
951e41f4b71Sopenharmony_ci{
952e41f4b71Sopenharmony_ci    struct PlatformHost *platformHost = NULL;
953e41f4b71Sopenharmony_ci...
954e41f4b71Sopenharmony_ci    platformHost = (struct PlatformHost *)device->service;
955e41f4b71Sopenharmony_ci...
956e41f4b71Sopenharmony_ci    OsalMutexDestroy(&g_platformData.renderBufInfo.buffMutex);
957e41f4b71Sopenharmony_ci    OsalMutexDestroy(&g_platformData.captureBufInfo.buffMutex);
958e41f4b71Sopenharmony_ci    OsalMemFree(platformHost);
959e41f4b71Sopenharmony_ci}
960e41f4b71Sopenharmony_ci
961e41f4b71Sopenharmony_ci/* HdfDriverEntry definitions */
962e41f4b71Sopenharmony_cistruct HdfDriverEntry g_platformDriverEntry = {
963e41f4b71Sopenharmony_ci    .moduleVersion = 1,
964e41f4b71Sopenharmony_ci    .moduleName = "DMA_HI3516",
965e41f4b71Sopenharmony_ci    .Bind = Hi3516DmaDriverBind,
966e41f4b71Sopenharmony_ci    .Init = Hi3516DmaDriverInit,
967e41f4b71Sopenharmony_ci    .Release = Hi3516DmaDriverRelease,
968e41f4b71Sopenharmony_ci};
969e41f4b71Sopenharmony_ciHDF_INIT(g_platformDriverEntry);
970e41f4b71Sopenharmony_ci```
971e41f4b71Sopenharmony_ci
972e41f4b71Sopenharmony_ci#### Configuring HCS
973e41f4b71Sopenharmony_ci
974e41f4b71Sopenharmony_ciFor details about the configuration process, see [Configuring HCS](#configuring-hcs) in **Codec Driver Development Example**.
975e41f4b71Sopenharmony_ci
976e41f4b71Sopenharmony_ci### DAI Driver Development Example
977e41f4b71Sopenharmony_ci
978e41f4b71Sopenharmony_ciCode path: **device/board/hisilicon/hispark_taurus/audio_drivers/soc**
979e41f4b71Sopenharmony_ci
980e41f4b71Sopenharmony_ciThe major steps for developing the DAI driver are as follows:
981e41f4b71Sopenharmony_ci
982e41f4b71Sopenharmony_ci1. Define and fill in a DAI instance.
983e41f4b71Sopenharmony_ci2. Implement callbacks for the DAI instance.
984e41f4b71Sopenharmony_ci3. Register and bind the codec instance to the HDF.
985e41f4b71Sopenharmony_ci4. Configure the HCS and makefile.
986e41f4b71Sopenharmony_ci
987e41f4b71Sopenharmony_ci#### Filling in DAI Data Structures
988e41f4b71Sopenharmony_ci
989e41f4b71Sopenharmony_ciFill in the following structs for the DAI module:
990e41f4b71Sopenharmony_ci
991e41f4b71Sopenharmony_ci- **g_daiData**: private configuration of the DAI device, including the initialization of the DAI device, read/write of registers, and operation functions.
992e41f4b71Sopenharmony_ci
993e41f4b71Sopenharmony_ci- **g_daiDeviceOps**: DAI device operation function set, including setting DAI parameters and triggering and starting the DAI device.
994e41f4b71Sopenharmony_ci
995e41f4b71Sopenharmony_ci```c
996e41f4b71Sopenharmony_cistruct AudioDaiOps g_daiDeviceOps = {
997e41f4b71Sopenharmony_ci    .HwParams = DaiHwParams,
998e41f4b71Sopenharmony_ci    .Trigger = DaiTrigger,
999e41f4b71Sopenharmony_ci    .Startup = DaiStartup,
1000e41f4b71Sopenharmony_ci};
1001e41f4b71Sopenharmony_ci
1002e41f4b71Sopenharmony_cistruct DaiData g_daiData = {
1003e41f4b71Sopenharmony_ci    .DaiInit = DaiDeviceInit,
1004e41f4b71Sopenharmony_ci    .Read = AudioDeviceReadReg,
1005e41f4b71Sopenharmony_ci    .Write = AudioDeviceWriteReg,
1006e41f4b71Sopenharmony_ci    .ops = &g_daiDeviceOps,
1007e41f4b71Sopenharmony_ci};
1008e41f4b71Sopenharmony_ci```
1009e41f4b71Sopenharmony_ci
1010e41f4b71Sopenharmony_ci#### Initializing daiDevice
1011e41f4b71Sopenharmony_ci
1012e41f4b71Sopenharmony_ci**DaiDeviceInit** initializes DAI configuration and adds the information to the controller linked list.
1013e41f4b71Sopenharmony_ci
1014e41f4b71Sopenharmony_ci```c
1015e41f4b71Sopenharmony_ciint32_t DaiDeviceInit(struct AudioCard *audioCard, const struct DaiDevice *dai)
1016e41f4b71Sopenharmony_ci{
1017e41f4b71Sopenharmony_ci...
1018e41f4b71Sopenharmony_ci    struct DaiData *data = dai->devData;
1019e41f4b71Sopenharmony_ci    struct AudioRegCfgData *regConfig = dai->devData->regConfig;
1020e41f4b71Sopenharmony_ci...
1021e41f4b71Sopenharmony_ci    g_regCodecBase = OsalIoRemap(CODEC_REG_BASE, CODEC_MAX_REG_SIZE);
1022e41f4b71Sopenharmony_ci...
1023e41f4b71Sopenharmony_ci    data->regVirtualAddr = (uintptr_t)g_regCodecBase;
1024e41f4b71Sopenharmony_ci    DaiSetConfigInfo(data);
1025e41f4b71Sopenharmony_ci    AudioAddControls(audioCard, data->controls, data->numControls);
1026e41f4b71Sopenharmony_ci    I2c6PinInit();
1027e41f4b71Sopenharmony_ci...
1028e41f4b71Sopenharmony_ci    data->daiInitFlag = true;
1029e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
1030e41f4b71Sopenharmony_ci}
1031e41f4b71Sopenharmony_ci```
1032e41f4b71Sopenharmony_ci
1033e41f4b71Sopenharmony_ci#### Implementing the DAI Operation Function Set
1034e41f4b71Sopenharmony_ci
1035e41f4b71Sopenharmony_ci**AudioDeviceReadReg** and **AudioDeviceWriteReg** are not used on the Hi3516 and are reserved.
1036e41f4b71Sopenharmony_ci
1037e41f4b71Sopenharmony_ci**DaiHwParams** sets PCM stream information.
1038e41f4b71Sopenharmony_ci
1039e41f4b71Sopenharmony_ci```c
1040e41f4b71Sopenharmony_ciint32_t DaiHwParams(const struct AudioCard *card, const struct AudioPcmHwParams *param)
1041e41f4b71Sopenharmony_ci{
1042e41f4b71Sopenharmony_ci    uint32_t bitWidth;
1043e41f4b71Sopenharmony_ci    struct DaiDevice *device = card->rtd->cpuDai;
1044e41f4b71Sopenharmony_ci...
1045e41f4b71Sopenharmony_ci    DaiCheckSampleRate(param->rate);
1046e41f4b71Sopenharmony_ci    struct DaiData *data = DaiDataFromCard(card);
1047e41f4b71Sopenharmony_ci    data->pcmInfo.channels = param->channels;
1048e41f4b71Sopenharmony_ci...
1049e41f4b71Sopenharmony_ci    AudioFormatToBitWidth(param->format, &bitWidth);
1050e41f4b71Sopenharmony_ci...
1051e41f4b71Sopenharmony_ci    data->pcmInfo.bitWidth = bitWidth;
1052e41f4b71Sopenharmony_ci    data->pcmInfo.rate = param->rate;
1053e41f4b71Sopenharmony_ci    data->pcmInfo.streamType = param->streamType;
1054e41f4b71Sopenharmony_ci    data->regVirtualAddr = (uintptr_t)g_regDaiBase;
1055e41f4b71Sopenharmony_ci...
1056e41f4b71Sopenharmony_ci    DaiParamsUpdate(device);
1057e41f4b71Sopenharmony_ci    data->regVirtualAddr = (uintptr_t)g_regCodecBase;
1058e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
1059e41f4b71Sopenharmony_ci}
1060e41f4b71Sopenharmony_ci```
1061e41f4b71Sopenharmony_ci
1062e41f4b71Sopenharmony_ci**DaiTrigger** is not used on the Hi3516 and is reserved.
1063e41f4b71Sopenharmony_ci
1064e41f4b71Sopenharmony_ci**DaiStartup** updates the register configuration and configures the I2S.
1065e41f4b71Sopenharmony_ci
1066e41f4b71Sopenharmony_ci```c
1067e41f4b71Sopenharmony_ciint32_t DaiStartup(const struct AudioCard *card, const struct DaiDevice *device)
1068e41f4b71Sopenharmony_ci{
1069e41f4b71Sopenharmony_ci    struct AudioMixerControl *regCfgItem = NULL;
1070e41f4b71Sopenharmony_ci...
1071e41f4b71Sopenharmony_ci    regCfgItem = device->devData->regConfig->audioRegParams[AUDIO_DAI_STARTUP_PATAM_GROUP]->regCfgItem;
1072e41f4b71Sopenharmony_ci    itemNum = device->devData->regConfig->audioRegParams[AUDIO_DAI_STARTUP_PATAM_GROUP]->itemNum;
1073e41f4b71Sopenharmony_ci
1074e41f4b71Sopenharmony_ci    device->devData->regVirtualAddr = (uintptr_t)g_regDaiBase;
1075e41f4b71Sopenharmony_ci    for (int i = 0; i < itemNum; i++) {
1076e41f4b71Sopenharmony_ci        int ret = AudioUpdateDaiRegBits(device, &regCfgItem[i], regCfgItem[i].value);
1077e41f4b71Sopenharmony_ci        if (ret != HDF_SUCCESS) {
1078e41f4b71Sopenharmony_ci            AUDIO_DRIVER_LOG_ERR("set frequency fail.");
1079e41f4b71Sopenharmony_ci            return HDF_FAILURE;
1080e41f4b71Sopenharmony_ci        }
1081e41f4b71Sopenharmony_ci    }
1082e41f4b71Sopenharmony_ci    device->devData->regVirtualAddr = (uintptr_t)g_regCodecBase;
1083e41f4b71Sopenharmony_ci
1084e41f4b71Sopenharmony_ci    if (I2sPinInit() != HDF_SUCCESS) {
1085e41f4b71Sopenharmony_ci        AUDIO_DRIVER_LOG_ERR("I2sPinInit fail.");
1086e41f4b71Sopenharmony_ci    }
1087e41f4b71Sopenharmony_ci
1088e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
1089e41f4b71Sopenharmony_ci}
1090e41f4b71Sopenharmony_ci```
1091e41f4b71Sopenharmony_ci
1092e41f4b71Sopenharmony_ci#### Registering and Binding DAI to HDF
1093e41f4b71Sopenharmony_ci
1094e41f4b71Sopenharmony_ciThe following implementation depends on the driver implementation mode of the HDF. For details, see [HDF](driver-overview-foundation.md).
1095e41f4b71Sopenharmony_ci
1096e41f4b71Sopenharmony_ci- Fill in the **g_daiDriverEntry** struct.
1097e41f4b71Sopenharmony_ci- Ensure that the value of **moduleName** is the same as that in **device_info.hcs**.
1098e41f4b71Sopenharmony_ci- Implement the pointers to the **Bind**, **Init**, and **Release** functions.
1099e41f4b71Sopenharmony_ci
1100e41f4b71Sopenharmony_ci**device/board/hisilicon/hispark_taurus/audio_drivers/soc/src/hi3516_dai_adapter.c**
1101e41f4b71Sopenharmony_ci
1102e41f4b71Sopenharmony_ci```c
1103e41f4b71Sopenharmony_cistatic int32_t DaiDriverBind(struct HdfDeviceObject *device)
1104e41f4b71Sopenharmony_ci{
1105e41f4b71Sopenharmony_ci...
1106e41f4b71Sopenharmony_ci    struct DaiHost *daiHost = (struct DaiHost *)OsalMemCalloc(sizeof(*daiHost));
1107e41f4b71Sopenharmony_ci...
1108e41f4b71Sopenharmony_ci    daiHost->device = device;
1109e41f4b71Sopenharmony_ci    device->service = &daiHost->service;
1110e41f4b71Sopenharmony_ci    g_daiData.daiInitFlag = false;
1111e41f4b71Sopenharmony_ci...
1112e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
1113e41f4b71Sopenharmony_ci}
1114e41f4b71Sopenharmony_ci
1115e41f4b71Sopenharmony_cistatic int32_t DaiDriverInit(struct HdfDeviceObject *device)
1116e41f4b71Sopenharmony_ci{
1117e41f4b71Sopenharmony_ci...
1118e41f4b71Sopenharmony_ci    DaiGetConfigInfo(device, &g_daiData);
1119e41f4b71Sopenharmony_ci    DaiGetServiceName(device);
1120e41f4b71Sopenharmony_ci...
1121e41f4b71Sopenharmony_ci    OsalMutexInit(&g_daiData.mutex);
1122e41f4b71Sopenharmony_ci    AudioSocRegisterDai(device, &g_daiData);
1123e41f4b71Sopenharmony_ci...
1124e41f4b71Sopenharmony_ci    return HDF_SUCCESS;
1125e41f4b71Sopenharmony_ci}
1126e41f4b71Sopenharmony_ci
1127e41f4b71Sopenharmony_cistatic void DaiDriverRelease(struct HdfDeviceObject *device)
1128e41f4b71Sopenharmony_ci{
1129e41f4b71Sopenharmony_ci...
1130e41f4b71Sopenharmony_ci    OsalMutexDestroy(&g_daiData.mutex);
1131e41f4b71Sopenharmony_ci...
1132e41f4b71Sopenharmony_ci    struct DaiHost *daiHost = (struct DaiHost *)device->service;
1133e41f4b71Sopenharmony_ci...
1134e41f4b71Sopenharmony_ci    OsalMemFree(daiHost);
1135e41f4b71Sopenharmony_ci}
1136e41f4b71Sopenharmony_ci
1137e41f4b71Sopenharmony_ci/* HdfDriverEntry definitions */
1138e41f4b71Sopenharmony_cistruct HdfDriverEntry g_daiDriverEntry = {
1139e41f4b71Sopenharmony_ci    .moduleVersion = 1,
1140e41f4b71Sopenharmony_ci    .moduleName = "DAI_HI3516",
1141e41f4b71Sopenharmony_ci    .Bind = DaiDriverBind,
1142e41f4b71Sopenharmony_ci    .Init = DaiDriverInit,
1143e41f4b71Sopenharmony_ci    .Release = DaiDriverRelease,
1144e41f4b71Sopenharmony_ci};
1145e41f4b71Sopenharmony_ciHDF_INIT(g_daiDriverEntry);
1146e41f4b71Sopenharmony_ci```
1147e41f4b71Sopenharmony_ci
1148e41f4b71Sopenharmony_ci#### Configuring HCS
1149e41f4b71Sopenharmony_ci
1150e41f4b71Sopenharmony_ciFor details about the configuration process, see [Configuring HCS](#configuring-hcs) in **Codec Driver Development Example**.
1151e41f4b71Sopenharmony_ci
1152e41f4b71Sopenharmony_ci### Adding Compilation Configuration to Makefile
1153e41f4b71Sopenharmony_ci
1154e41f4b71Sopenharmony_ciAdd the newly added files to the **Makefile** file to link them to the kernel image.
1155e41f4b71Sopenharmony_ci
1156e41f4b71Sopenharmony_ciStandard system (Linux): **device/board/hisilicon/hispark_taurus/audio_drivers/Makefile**
1157e41f4b71Sopenharmony_ci
1158e41f4b71Sopenharmony_ci```makefile
1159e41f4b71Sopenharmony_ciobj-$(CONFIG_DRIVERS_HDF_AUDIO_HI3516CODEC) += \
1160e41f4b71Sopenharmony_ci        codec/tfa9879/src/tfa9879_codec_adapter.o \
1161e41f4b71Sopenharmony_ci        codec/tfa9879/src/tfa9879_codec_ops.o \
1162e41f4b71Sopenharmony_ci        codec/hi3516/src/hi3516_codec_adapter.o \
1163e41f4b71Sopenharmony_ci        codec/hi3516/src/hi3516_codec_impl.o \
1164e41f4b71Sopenharmony_ci        codec/hi3516/src/hi3516_codec_ops.o \
1165e41f4b71Sopenharmony_ci        dsp/src/dsp_adapter.o \
1166e41f4b71Sopenharmony_ci        dsp/src/dsp_ops.o \
1167e41f4b71Sopenharmony_ci        soc/src/hi3516_dai_adapter.o \
1168e41f4b71Sopenharmony_ci        soc/src/hi3516_dai_ops.o \
1169e41f4b71Sopenharmony_ci        soc/src/hi3516_aiao_impl.o \
1170e41f4b71Sopenharmony_ci        soc/src/hi3516_dma_ops.o \
1171e41f4b71Sopenharmony_ci        soc/src/hi3516_dma_adapter.o
1172e41f4b71Sopenharmony_ci```
1173e41f4b71Sopenharmony_ci
1174e41f4b71Sopenharmony_ciSmall system (LiteOS): **drivers/adapter/khdf/liteos/model/audio/Makefile**
1175e41f4b71Sopenharmony_ci
1176e41f4b71Sopenharmony_ci```makefile
1177e41f4b71Sopenharmony_ciLOCAL_SRCS += \
1178e41f4b71Sopenharmony_ci    $(KHDF_AUDIO_HI3516DV300_DIR)/codec/tfa9879/src/tfa9879_codec_adapter.c \
1179e41f4b71Sopenharmony_ci    $(KHDF_AUDIO_HI3516DV300_DIR)/codec/tfa9879/src/tfa9879_codec_ops.c \
1180e41f4b71Sopenharmony_ci    $(KHDF_AUDIO_HI3516DV300_DIR)/codec/hi3516/src/hi3516_codec_adapter.c \
1181e41f4b71Sopenharmony_ci    $(KHDF_AUDIO_HI3516DV300_DIR)/codec/hi3516/src/hi3516_codec_impl.c \
1182e41f4b71Sopenharmony_ci    $(KHDF_AUDIO_HI3516DV300_DIR)/codec/hi3516/src/hi3516_codec_ops.c \
1183e41f4b71Sopenharmony_ci    $(KHDF_AUDIO_HI3516DV300_DIR)/dsp/src/dsp_adapter.c \
1184e41f4b71Sopenharmony_ci    $(KHDF_AUDIO_HI3516DV300_DIR)/dsp/src/dsp_ops.c \
1185e41f4b71Sopenharmony_ci    $(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dai_adapter.c \
1186e41f4b71Sopenharmony_ci    $(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dai_ops.c \
1187e41f4b71Sopenharmony_ci    $(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_aiao_impl.c \
1188e41f4b71Sopenharmony_ci    $(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dma_ops.c \
1189e41f4b71Sopenharmony_ci    $(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dma_adapter.c
1190e41f4b71Sopenharmony_ci```
1191e41f4b71Sopenharmony_ci
1192e41f4b71Sopenharmony_ci### Source Code Structure and Directory
1193e41f4b71Sopenharmony_ci
1194e41f4b71Sopenharmony_ciThe development example implements the functions in the header file of the driver interface. The following uses Hi3516 as an example to describe the directory struct. 
1195e41f4b71Sopenharmony_ci
1196e41f4b71Sopenharmony_ciPath of the driver implementation sample code: **device/board/hisilicon/hispark_taurus/audio_drivers/**
1197e41f4b71Sopenharmony_ci
1198e41f4b71Sopenharmony_ci```shell
1199e41f4b71Sopenharmony_ci.
1200e41f4b71Sopenharmony_ci├── codec
1201e41f4b71Sopenharmony_ci│   ├── hi3516
1202e41f4b71Sopenharmony_ci│   │   ├── include
1203e41f4b71Sopenharmony_ci│   │   │   ├── hi3516_codec_impl.h
1204e41f4b71Sopenharmony_ci│   │   │   └── hi3516_codec_ops.h
1205e41f4b71Sopenharmony_ci│   │   └── src
1206e41f4b71Sopenharmony_ci│   │   │   ├── hi3516_codec_adapter.c  // Codec driver entry
1207e41f4b71Sopenharmony_ci│   │   │   ├── hi3516_codec_impl.c     // Implementation of codec hardware operations
1208e41f4b71Sopenharmony_ci│   │   │   └── hi3516_codec_ops.c      // Implementation of codec driver APIs
1209e41f4b71Sopenharmony_ci│   └── tfa9879
1210e41f4b71Sopenharmony_ci│       ├── include
1211e41f4b71Sopenharmony_ci│       │   └── tfa9879_codec_ops.h
1212e41f4b71Sopenharmony_ci│       └── src
1213e41f4b71Sopenharmony_ci│           ├── tfa9879_codec_adapter.c
1214e41f4b71Sopenharmony_ci│           └── tfa9879_codec_ops.c
1215e41f4b71Sopenharmony_ci├── dsp
1216e41f4b71Sopenharmony_ci│   ├── include
1217e41f4b71Sopenharmony_ci│   │   └── dsp_ops.h
1218e41f4b71Sopenharmony_ci│   └── src
1219e41f4b71Sopenharmony_ci│       ├── dsp_adapter.c                 // DSP driver entry
1220e41f4b71Sopenharmony_ci│       └── dsp_ops.c
1221e41f4b71Sopenharmony_ci├── LICENSE
1222e41f4b71Sopenharmony_ci├── Makefile
1223e41f4b71Sopenharmony_ci└── soc
1224e41f4b71Sopenharmony_ci    ├── include
1225e41f4b71Sopenharmony_ci    │   ├── hi3516_aiao_impl.h
1226e41f4b71Sopenharmony_ci    │   ├── hi3516_dai_ops.h
1227e41f4b71Sopenharmony_ci    │   └── hi3516_dma_ops.h
1228e41f4b71Sopenharmony_ci    └── src
1229e41f4b71Sopenharmony_ci        ├── hi3516_aiao_impl.c
1230e41f4b71Sopenharmony_ci        ├── hi3516_dai_adapter.c          // DAI driver entry
1231e41f4b71Sopenharmony_ci        ├── hi3516_dai_ops.c
1232e41f4b71Sopenharmony_ci        ├── hi3516_dma_adapter.c          // DMA driver entry
1233e41f4b71Sopenharmony_ci        └── hi3516_dma_ops.c
1234e41f4b71Sopenharmony_ci```
1235e41f4b71Sopenharmony_ci
1236e41f4b71Sopenharmony_ciHCS Files and Directory
1237e41f4b71Sopenharmony_ci
1238e41f4b71Sopenharmony_ci```shell
1239e41f4b71Sopenharmony_ciStandard system:
1240e41f4b71Sopenharmony_civendor/hisilicon/hispark_taurus_standard/
1241e41f4b71Sopenharmony_ci└── hdf_config
1242e41f4b71Sopenharmony_ci    └── khdf
1243e41f4b71Sopenharmony_ci        ├── audio
1244e41f4b71Sopenharmony_ci        │   ├── audio_config.hcs
1245e41f4b71Sopenharmony_ci        │   ├── codec_config.hcs
1246e41f4b71Sopenharmony_ci        │   ├── dai_config.hcs
1247e41f4b71Sopenharmony_ci        │   ├── dma_config.hcs
1248e41f4b71Sopenharmony_ci        │   └── dsp_config.hcs
1249e41f4b71Sopenharmony_ci        ├── device_info
1250e41f4b71Sopenharmony_ci        │   └── device_info.hcs
1251e41f4b71Sopenharmony_ci        └── hdf.hcs
1252e41f4b71Sopenharmony_ci
1253e41f4b71Sopenharmony_ciSmall system:
1254e41f4b71Sopenharmony_civendor/hisilicon/hispark_taurus/
1255e41f4b71Sopenharmony_ci├── config.json
1256e41f4b71Sopenharmony_ci└── hdf_config
1257e41f4b71Sopenharmony_ci    ├── audio
1258e41f4b71Sopenharmony_ci    │   ├── audio_config.hcs
1259e41f4b71Sopenharmony_ci    │   ├── codec_config.hcs
1260e41f4b71Sopenharmony_ci    │   ├── dai_config.hcs
1261e41f4b71Sopenharmony_ci    │   ├── dma_config.hcs
1262e41f4b71Sopenharmony_ci    │   └── dsp_config.hcs
1263e41f4b71Sopenharmony_ci    ├── device_info
1264e41f4b71Sopenharmony_ci    │   └── device_info.hcs
1265e41f4b71Sopenharmony_ci    └── hdf.hcs
1266e41f4b71Sopenharmony_ci```
1267e41f4b71Sopenharmony_ci
1268e41f4b71Sopenharmony_ci## HAL-based Development Procedure and Example
1269e41f4b71Sopenharmony_ci
1270e41f4b71Sopenharmony_ciThe Hardware Abstraction Layer (HAL) provides the following function:
1271e41f4b71Sopenharmony_ci
1272e41f4b71Sopenharmony_ci- Provides audio HDIs for audio services to implement basic audio features on applications.
1273e41f4b71Sopenharmony_ci- Provides standard interfaces for device developers to comply with the HDI adapter standards. This promises a healthy evolution of the ecosystem.
1274e41f4b71Sopenharmony_ci
1275e41f4b71Sopenharmony_ciCode path: **drivers_interface/audio/v1_0**
1276e41f4b71Sopenharmony_ci
1277e41f4b71Sopenharmony_ci### Development procedure
1278e41f4b71Sopenharmony_ci
1279e41f4b71Sopenharmony_ci![](figures/HAL_flowchart.png)
1280e41f4b71Sopenharmony_ci
1281e41f4b71Sopenharmony_ci1. Call **GetAudioManagerFuncs()** to obtain methods.
1282e41f4b71Sopenharmony_ci
1283e41f4b71Sopenharmony_ci2. Use **GetAllAdapters()** to obtain information about the supported audio adapter, and call **LoadAdapter()** to load the audio adapter.
1284e41f4b71Sopenharmony_ci
1285e41f4b71Sopenharmony_ci3. Create a **Render** class by calling **CreateRender()** or create a recorder class and deliver audio attributes.
1286e41f4b71Sopenharmony_ci
1287e41f4b71Sopenharmony_ci4. Call the methods hooked in the **Render** class created. For example, call **render->Start()** to start the playback, and call **render->RenderFrame()** to deliver audio data cyclically.
1288e41f4b71Sopenharmony_ci
1289e41f4b71Sopenharmony_ci5. During the playback, call control commands to control the playback service, for example, call **render->SetVolume()** to adjust the volume, call **render->Pause()** to pause the playback, and call **render->Resume()** to resume the playback.
1290e41f4b71Sopenharmony_ci
1291e41f4b71Sopenharmony_ci6. After the playback is complete, call **render->Stop()** to stop the playback, call **adapter->DestroyRender()** to destroy the playback instance, and call **audioManagerIns->UnloadAdapter()** to unload the audio adapter.
1292e41f4b71Sopenharmony_ci
1293e41f4b71Sopenharmony_ci### HAL Usage Example
1294e41f4b71Sopenharmony_ci
1295e41f4b71Sopenharmony_ci```c
1296e41f4b71Sopenharmony_ci#include <string.h>
1297e41f4b71Sopenharmony_ci#include <stdio.h>
1298e41f4b71Sopenharmony_ci#include <pthread.h>
1299e41f4b71Sopenharmony_ci#include "v1_0/audio_types.h"
1300e41f4b71Sopenharmony_ci#include "v1_0/iaudio_manager.h"
1301e41f4b71Sopenharmony_ci
1302e41f4b71Sopenharmony_cistruct IAudioRender *g_render = NULL;
1303e41f4b71Sopenharmony_cistruct IAudioAdapter *g_adapter = NULL;
1304e41f4b71Sopenharmony_cistruct AudioDeviceDescriptor g_devDesc;
1305e41f4b71Sopenharmony_cistruct AudioSampleAttributes g_attrs;
1306e41f4b71Sopenharmony_cistruct AudioHeadInfo g_wavHeadInfo;
1307e41f4b71Sopenharmony_cibool g_isDirect = false;  //IPC Loading
1308e41f4b71Sopenharmony_ciuint32_t g_renderId = 0;
1309e41f4b71Sopenharmony_ci
1310e41f4b71Sopenharmony_cistatic int32_t FrameStart(const struct StrPara *param)
1311e41f4b71Sopenharmony_ci{
1312e41f4b71Sopenharmony_ci...
1313e41f4b71Sopenharmony_ci    /* Initialize parameters. */
1314e41f4b71Sopenharmony_ci    char *frame = param->frame;
1315e41f4b71Sopenharmony_ci    int32_t bufferSize = param->bufferSize;
1316e41f4b71Sopenharmony_ci    size_t remainingDataSize = g_wavHeadInfo.riffSize;
1317e41f4b71Sopenharmony_ci
1318e41f4b71Sopenharmony_ci    /* Send audio data cyclically. */
1319e41f4b71Sopenharmony_ci    do {
1320e41f4b71Sopenharmony_ci        uint64_t replyBytes = 0;
1321e41f4b71Sopenharmony_ci        size_t readSize = (remainingDataSize > bufferSize) ? (size_t)bufferSize : remainingDataSize;
1322e41f4b71Sopenharmony_ci        numRead = fread(frame, 1, readSize, g_file);
1323e41f4b71Sopenharmony_ci        if (numRead > 0) {
1324e41f4b71Sopenharmony_ci            int32_t ret = render->RenderFrame(render, (int8_t *)frame, numRead, &replyBytes);
1325e41f4b71Sopenharmony_ci            if (ret == HDF_ERR_INVALID_OBJECT) {
1326e41f4b71Sopenharmony_ci                AUDIO_FUNC_LOGE("Render already stop!");
1327e41f4b71Sopenharmony_ci                break;
1328e41f4b71Sopenharmony_ci            }
1329e41f4b71Sopenharmony_ci            remainingDataSize -= numRead;
1330e41f4b71Sopenharmony_ci        }
1331e41f4b71Sopenharmony_ci        /* Pause the playback and wait. */
1332e41f4b71Sopenharmony_ci        while (g_waitSleep) {
1333e41f4b71Sopenharmony_ci            printf("music pause now.\n");
1334e41f4b71Sopenharmony_ci            pthread_cond_wait(&g_functionCond, &g_mutex);
1335e41f4b71Sopenharmony_ci            printf("music resume now.\n");
1336e41f4b71Sopenharmony_ci        }
1337e41f4b71Sopenharmony_ci    } while (!g_closeEnd && numRead > 0 && remainingDataSize > 0);
1338e41f4b71Sopenharmony_ci...
1339e41f4b71Sopenharmony_ci}
1340e41f4b71Sopenharmony_ci
1341e41f4b71Sopenharmony_cistatic void *hal_main()
1342e41f4b71Sopenharmony_ci{
1343e41f4b71Sopenharmony_ci    int32_t adapterIndex = 0;
1344e41f4b71Sopenharmony_ci    struct AudioPort *renderPort;
1345e41f4b71Sopenharmony_ci
1346e41f4b71Sopenharmony_ci    /* Call IAudioManagerGet() to obtain the entry function. */
1347e41f4b71Sopenharmony_ci    struct IAudioManager *audioManagerIns = IAudioManagerGet(g_isDirect);
1348e41f4b71Sopenharmony_ci    if (audioManagerIns == NULL) {
1349e41f4b71Sopenharmony_ci        AUDIO_FUNC_LOGE("Get Audio Manager Fail");
1350e41f4b71Sopenharmony_ci        return HDF_FAILURE;
1351e41f4b71Sopenharmony_ci    }
1352e41f4b71Sopenharmony_ci    
1353e41f4b71Sopenharmony_ci    /* Obtain the audio adapter list. */
1354e41f4b71Sopenharmony_ci    struct AudioAdapterDescriptor *descs = (struct AudioAdapterDescriptor *)OsalMemCalloc(
1355e41f4b71Sopenharmony_ci        sizeof(struct AudioAdapterDescriptor) * (MAX_AUDIO_ADAPTER_DESC));
1356e41f4b71Sopenharmony_ci    uint32_t adapterNum = MAX_AUDIO_ADAPTER_DESC;
1357e41f4b71Sopenharmony_ci
1358e41f4b71Sopenharmony_ci    int32_t ret = audioManagerIns->GetAllAdapters(audioManagerIns, descs, &adapterNum);
1359e41f4b71Sopenharmony_ci
1360e41f4b71Sopenharmony_ci    /* Locate the audio adapter and port based on the specified audio adapter name and port description. */
1361e41f4b71Sopenharmony_ci    SelectAudioCard(descs, adapterNum, &adapterIndex);
1362e41f4b71Sopenharmony_ci    strcpy_s(g_adapterName, PATH_LEN, descs[adapterIndex - 1].adapterName);
1363e41f4b71Sopenharmony_ci    SwitchAudioPort(&descs[adapterIndex - 1], PORT_OUT, renderPort);  // The port type is OUT, which means playback.
1364e41f4b71Sopenharmony_ci
1365e41f4b71Sopenharmony_ci    /* Load the audio adapter based on the matched audio adapter information. */
1366e41f4b71Sopenharmony_ci    audioManagerIns->LoadAdapter(audioManagerIns, &descs[adapterIndex - 1], &g_adapter);                                               // Load the audio adapter and obtain the related instances.
1367e41f4b71Sopenharmony_ci
1368e41f4b71Sopenharmony_ci    /* Create a Render class. */
1369e41f4b71Sopenharmony_ci    uint32_t portId = renderPort->portId;
1370e41f4b71Sopenharmony_ci    InitDevDesc(&g_devDesc, portId);                       // Initialize the parameters for setting the device.
1371e41f4b71Sopenharmony_ci    InitAttrs(&g_attrs);                                   // Initialize audio attribute parameters.
1372e41f4b71Sopenharmony_ci    CheckWavFileHeader(g_file, &g_wavHeadInfo, &g_attrs);  // Parse the audio file and set attributes.
1373e41f4b71Sopenharmony_ci    g_adapter->CreateRender(g_adapter, &g_devDesc, &g_attrs, &g_render, &g_renderId);
1374e41f4b71Sopenharmony_ci
1375e41f4b71Sopenharmony_ci    /* Deliver the number of the audio to be played. */
1376e41f4b71Sopenharmony_ci    g_render->Start((void *)g_render);                                  // Send the start command to start the playback.
1377e41f4b71Sopenharmony_ci    pthread_create(&g_tids, &tidsAttr, (void *)(&FrameStart), &g_str);  // Start the thread to play the music.
1378e41f4b71Sopenharmony_ci
1379e41f4b71Sopenharmony_ci    /* Send the control instructions. */
1380e41f4b71Sopenharmony_ci    g_render->Pause((void *)g_render);           // Pause the playback.
1381e41f4b71Sopenharmony_ci    g_render->Resume((void *)g_render);          // Resume the playback.
1382e41f4b71Sopenharmony_ci    g_render->SetVolume((void *)g_render, 0.5);  // Set the volume.
1383e41f4b71Sopenharmony_ci
1384e41f4b71Sopenharmony_ci     /* Stop playback and destroy the Render class. */
1385e41f4b71Sopenharmony_ci    g_render->Stop((void *)g_render);
1386e41f4b71Sopenharmony_ci    g_adapter->DestroyRender(g_adapter, g_renderId);
1387e41f4b71Sopenharmony_ci     /* Unload the audio adapter. */
1388e41f4b71Sopenharmony_ci    audioManagerIns->UnloadAdapter(audioManagerIns, g_adapterName);
1389e41f4b71Sopenharmony_ci}
1390e41f4b71Sopenharmony_ci```
1391e41f4b71Sopenharmony_ci
1392e41f4b71Sopenharmony_ci
1393e41f4b71Sopenharmony_ci
1394e41f4b71Sopenharmony_ci## Summary
1395e41f4b71Sopenharmony_ci
1396e41f4b71Sopenharmony_ciThis document provides all the key adaptations involved in the audio driver development. It elaborates how to adapt the audio driver and use HDI APIs. You can conduct development based on the chip you use. After reading this document, you will be able to master the audio driver development based on the HDF.
1397