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 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 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 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 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 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 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, ®Attr, 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, ®Attr, 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, ®Attr, 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, ®Attr, 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, ®CfgItem[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 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