“0fc3bfe573083655efcae2de19a49f32aa6f9cda”上不存在“src/git@gitcode.net:openanolis/dragonwell8_hotspot.git”
未验证 提交 27ca263a 编写于 作者: O openharmony_ci 提交者: Gitee

!20638 [翻译完成】#I7C851

Merge pull request !20638 from Annie_wang/PR19194A
...@@ -5,24 +5,24 @@ ...@@ -5,24 +5,24 @@
A 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. A 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.
This document describes the audio driver architecture and functional modules and how to develop audio drivers based on the Hardware Driver Foundation (HDF). Chip vendors can develop their own drivers and invocation of Hardware Abstraction Layer (HAL) APIs based on the driver architecture. This 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.
## Audio Driver Architecture ## Audio Driver Architecture
The audio driver architecture is implemented based on the [HDF](driver-hdf-overview.md). The audio driver architecture is as follows: The audio driver framework is implemented based on the [HDF](driver-overview-foundation.md). The following figure illustrates the audio driver architecture.
![](figures/Audio_architecture.png) ![](figures/Audio_architecture.png)
The driver architecture consists of the following: The driver architecture consists of the following:
- Hardware Device Interface (HDI) adapter: implements the audio HAL driver (HDI adaptation) and provides hardware driver capability interfaces for the audio service (frameworks). The HDI adapter provides interface objects such as Audio Manager, Audio Adapter, Audio Control, Audio Capture, and Audio Render. - 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**.
- 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. - 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.
- 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 unified interfaces provided by the ADM and implement quick development and easy adaptation to the OpenHarmony system. - 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.
- Audio Control Dispatch: dispatches the control instructions from the Audio Interface Lib to the driver layer. - Audio Control Dispatch: dispatches the control instructions from the Audio Interface Lib to the driver layer.
- Audio Stream Dispatch: dispatches the data from the Audio Interface Lib to the driver layer. - Audio Stream Dispatch: dispatches the data from the Audio Interface Lib to the driver layer.
- Card Manager: manages multiple audio adapters. Each audio adapter consists of the digital audio interface (DAI), platform, codec, accessory, DSP, and Smart Audio Power Manager (SAPM) modules. - 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.
- Platform Drivers: driver adaptation layer. - Platform Drivers: driver adaptation layer.
- SAPM: optimizes the power consumption policy of the ADM. - SAPM: optimizes the power consumption policy of the ADM.
...@@ -31,36 +31,39 @@ The driver architecture consists of the following: ...@@ -31,36 +31,39 @@ The driver architecture consists of the following:
The following uses the Hi3516D V300 as an example to describe how to develop drivers based on the audio driver architecture. The following uses the Hi3516D V300 as an example to describe how to develop drivers based on the audio driver architecture.
### Audio ADM Architecture ### Audio ADM Architecture
The 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: The 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:
```c ```shell
# ls -l hdf_audio* # ls -l hdf_audio*
crw-rw---- 1 system system 248, 6 1970-01-01 00:00 hdf_audio_capture // Voice recording service. crw-rw---- 1 system system 247, 6 1970-01-01 00:00 hdf_audio_capture // Voice recording service.
crw-rw---- 1 system system 248, 4 1970-01-01 00:00 hdf_audio_codec_dev0 // Name of audio adapter 0. crw-rw---- 1 root root 247, 4 1970-01-01 00:00 hdf_audio_codec_primary_dev0 // Audio adapter device 0.
crw-rw---- 1 system system 248, 4 1970-01-01 00:00 hdf_audio_codec_dev1 // Name of audio adapter 1. crw-rw---- 1 root root 247, 4 1970-01-01 00:00 hdf_audio_codec_primary_dev11 // Audio adapter device 1.
crw-rw---- 1 system system 248, 5 1970-01-01 00:00 hdf_audio_control // Audio control service. crw-rw---- 1 system system 247, 5 1970-01-01 00:00 hdf_audio_control // Audio control service.
crw-rw---- 1 system system 248, 7 1970-01-01 00:00 hdf_audio_render // Audio playback service. crw-rw---- 1 system system 247, 7 1970-01-01 00:00 hdf_audio_render // Audio playback service.
``` ```
The audio adapters have the following driver services: The audio adapters have the following driver services:
hdf\_audio\_codec\_dev0 hdf_audio_codec_primary_dev0
- **dma\_service\_0**: direct memory access (DMA) service
- **dai_service**: CPU DAI service
- **codec\_service\_0**: codec service (built-in codec)
- **dsp\_service\_0**: DSP service (optional)
hdf\_audio\_codec\_dev1 - **dma_service_0**: DMA service
- **dma\_service\_0**: DMA service
- **dai_service**: CPU DAI service - **dai_service**: CPU DAI service
- **codec\_service\_1**: accessory service (SmartPA) - **codec_service_0**: codec service (which can be smartPA)
- **dsp\_service\_0**: DSP service (optional) - **dsp_service_0**: DSP service (optional)
hdf_audio_codec_primary_dev11
- **dma_service_0**: DMA service
- **dai_service**: CPU DAI service
- **codec_service_1**: codec service (which can be smartPA)
- **dsp_service_0**: DSP service (optional)
#### Startup Process #### Startup Process
![](figures/ADM_startup_flowchart.png) ![](figures/ADM_startup_flowchart.png)
1. When the system starts, the platform, codec, accessory, 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 structures. 1. 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.
2. Each driver module calls the ADM registration interface to add itself to the linked list of the driver module. 2. Each driver module calls the ADM registration interface to add itself to the linked list of the driver module.
...@@ -72,7 +75,7 @@ hdf\_audio\_codec\_dev1 ...@@ -72,7 +75,7 @@ hdf\_audio\_codec\_dev1
#### Playback Process #### Playback Process
![=](figures/ADM_playback_flowchart.png) ![](figures/ADM_playback_flowchart.png)
1. 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. 1. 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.
...@@ -95,13 +98,37 @@ hdf\_audio\_codec\_dev1 ...@@ -95,13 +98,37 @@ hdf\_audio\_codec\_dev1
1. 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. 1. 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.
2. 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. 2. 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.
### Common Audio Driver Functions
| Function | Description |
| ------------------------------ | ------------------------------------------- |
| CodecDeviceReadReg | Reads data from a codec register. |
| CodecDeviceWriteReg | Writes data to a codec register. |
| CodecDaiRegI2cRead | Reads data from a codec register over an I2C interface to a codec DAI. |
| CodecDaiRegI2cWrite | Writes data to a codec register over an I2C interface from a codec DAI. |
| CodecDeviceRegI2cRead | Reads data from a codec register over an I2C interface to a codec device. |
| CodecDeviceRegI2cWrite | Write data to a codec register over an I2C interface from a codec device. |
| CodecDeviceInitRegConfig | Initializes codec. |
| CodecDaiDeviceStartupRegConfig | Starts a codec device. |
| CodecSetCtlFunc | Sets the **set()** and **get()** functions. |
| CodecSetConfigInfoOfControls | Sets the codec control function and register information.|
| CodecGetConfigInfo | Obtains the code HDF configuration source (HCS). |
| CodecGetDaiName | Obtains the DAI name in the HCS. |
| CodecGetServiceName | Obtains the service name in the HCS. |
| DaiDeviceReadReg | Reads data from a DAI register. |
| DaiDeviceWriteReg | Writes data to a DAI register. |
| DaiSetConfigInfoOfControls | Sets the DAI control function and register information. |
| DaiGetConfigInfo | Obtains the DAI HCS. |
### Audio Driver Development Procedure ### Audio Driver Development Procedure
#### Development on an Adapted Platform #### Development on an Adapted Platform
The following figure shows the process for developing the codec or accessory (SmartPA) driver on a chip platform (Hi3516D V300) to which the ADM has adapted. The following figure shows the process for developing the codec or SmartPA driver on a chip platform (Hi3516D V300) to which the ADM has adapted.
![](figures/audio_development_flowchart_1.png) ![](figures/audio_development_flowchart_1.png)
- Add register information to the private HDF configuration source (HCS) of the codec or SmartPA based on the chip description. - Add register information to the private HDF configuration source (HCS) of the codec or SmartPA based on the chip description.
...@@ -125,26 +152,26 @@ The codec (optional), DAI, DMA, DSP (optional), and SmartPA (optional) modules o ...@@ -125,26 +152,26 @@ The codec (optional), DAI, DMA, DSP (optional), and SmartPA (optional) modules o
- Perform build, debugging, and testing. - Perform build, debugging, and testing.
## Audio Driver Development Examples ## Audio Driver Development Examples
Code path: **drivers/peripheral/audio** Code path: **device/board/hisilicon/hispark_taurus/audio_drivers**
The following uses Hi3516D V300 as an example to describe how to develop the audio codec driver, accessory driver, DAI driver, and platform driver. The following uses Hi3516D V300 as an example to describe how to develop the codec driver, DAI driver, and Platform driver.
### Codec Driver Development Example ### Codec Driver Development Example
Code path: **drivers/peripheral/audio/chipsets/hi3516dv300/codec**
Code path: **device/board/hisilicon/hispark_taurus/audio_drivers/codec/hi3516**
The major steps for developing the codec driver are as follows: The major steps for developing the codec driver are as follows:
1. Define and fill in a codec instance. 1. Define and fill in a codec instance.
2. Implement callbacks for the codec instance. 2. Implement callbacks for the codec instance.
3. Register and bind the codec instance to the HDF. 3. Register and bind the codec instance to the HDF.
4. Configure the HCS and makefile. 4. Configure the HCS and makefile.
#### Filling in Codec Data Structures #### Filling in Codec Data Structs
Fill in the following data structures for the codec module: Fill in the following data structs for the codec module:
- **g_codecData**: operation function set and private data set of the codec device. - **g_codecData**: operation function set and private data set of the codec device.
...@@ -154,9 +181,9 @@ Fill in the following data structures for the codec module: ...@@ -154,9 +181,9 @@ Fill in the following data structures for the codec module:
```c ```c
struct CodecData g_codecData = { struct CodecData g_codecData = {
.Init = CodecDeviceInit, // Initialize the codec device (need to be implemented for a new platform). .Init = CodecDeviceInit, // Initialize the codec device (need to be implemented for a new platform).
.Read = AudioDeviceReadReg, // Read the register (already implemented in the existing framework and no adaptation needed). .Read = AudioDeviceReadReg, // Read the register (available in the existing framework).
.Write = AudioDeviceWriteReg, // Write the register (already implemented in the existing framework and no adaptation needed). .Write = AudioDeviceWriteReg, // Write the register (available in the existing framework).
}; };
struct AudioDaiOps g_codecDaiDeviceOps = { struct AudioDaiOps g_codecDaiDeviceOps = {
...@@ -166,42 +193,42 @@ struct AudioDaiOps g_codecDaiDeviceOps = { ...@@ -166,42 +193,42 @@ struct AudioDaiOps g_codecDaiDeviceOps = {
struct DaiData g_codecDaiData = { struct DaiData g_codecDaiData = {
.DaiInit = CodecDaiDeviceInit, // Initialize the codec DAI device (need to be implemented for a new platform). .DaiInit = CodecDaiDeviceInit, // Initialize the codec DAI device (need to be implemented for a new platform).
.ops = &g_codecDaiDeviceOps, // codec DAI device operation function set. .ops = &g_codecDaiDeviceOps, // Codec DAI device operation function set.
}; };
``` ```
#### Initializing codecDevice and codecDai #### Initializing codecDevice and codecDai
**CODECDeviceInit** sets audio input/audio output (AIAO), initializes registers, inserts **g_audioControls** into the control linked list, initializes the power management, and selects a path. **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.
```c ```c
int32_t CodecDeviceInit(struct AudioCard *audioCard, struct CodecDevice *codec) int32_t CodecDeviceInit(struct AudioCard *audioCard, struct CodecDevice *codec)
{ {
... ...
/* Register set() and get() of the AIAO module on the Hi3516 platform. */ /* Register set() and get() of the AIAO module on the Hi3516. */
CodecSetCtlFunc(codec->devData, AudioCodecAiaoGetCtrlOps, AudioCodecAiaoSetCtrlOps) CodecSetCtlFunc(codec->devData, AudioCodecAiaoGetCtrlOps, AudioCodecAiaoSetCtrlOps)
... ...
/* Hi3516 codec register IoRemap */ /* Hi3516 codec register IoRemap. */
CodecHalSysInit(); CodecHalSysInit();
... ...
/* Initialize the codec registers of the Hi3516 platform. */ /* Initialize the codec registers of the Hi3516. */
CodecRegDefaultInit(codec->devData->regCfgGroup); CodecRegDefaultInit(codec->devData->regCfgGroup);
... ...
/* Insert g_audioControls of the Hi3516 platform to the controller linked list.*/ /* Add g_audioControls of the Hi3516 to the controller linked list.*/
AudioAddControls(audioCard, codec->devData->controls, codec->devData->numControls); AudioAddControls(audioCard, codec->devData->controls, codec->devData->numControls);
... ...
/* Load the codec of the Hi3516 platform to the SAPM. */ /* Load the codec of the Hi3516 to the SAPM. */
AudioSapmNewComponents(audioCard, codec->devData->sapmComponents, codec->devData->numSapmComponent); AudioSapmNewComponents(audioCard, codec->devData->sapmComponents, codec->devData->numSapmComponent);
... ...
/* Insert the codec of the Hi3516 platform to the audioRoutes linked list. */ /* Add the codec of the Hi3516 to the audioRoutes linked list. */
AudioSapmAddRoutes(audioCard, g_audioRoutes, HDF_ARRAY_SIZE(g_audioRoutes); AudioSapmAddRoutes(audioCard, g_audioRoutes, HDF_ARRAY_SIZE(g_audioRoutes);
... ...
AudioSapmNewControls(audioCard); AudioSapmNewControls(audioCard);
... ...
/* Hi3516 codec power management */ /* Hi3516 codec power management. */
AudioSapmSleep(audioCard); AudioSapmSleep(audioCard);
... ...
return HDF_SUCCESS; return HDF_SUCCESS;
} }
``` ```
...@@ -211,10 +238,10 @@ int32_t CodecDeviceInit(struct AudioCard *audioCard, struct CodecDevice *codec) ...@@ -211,10 +238,10 @@ int32_t CodecDeviceInit(struct AudioCard *audioCard, struct CodecDevice *codec)
int32_t CodecDaiDeviceInit(struct AudioCard *card, const struct DaiDevice *device) int32_t CodecDaiDeviceInit(struct AudioCard *card, const struct DaiDevice *device)
{ {
... ...
AUDIO_DRIVER_LOG_DEBUG("codec dai device name: %s\n", device->devDaiName); AUDIO_DRIVER_LOG_DEBUG("codec dai device name: %s\n", device->devDaiName);
(void)card; (void)card;
return HDF_SUCCESS; return HDF_SUCCESS;
} }
``` ```
...@@ -273,11 +300,11 @@ int32_t CodecDaiHwParams(const struct AudioCard *card, const struct AudioPcmHwPa ...@@ -273,11 +300,11 @@ int32_t CodecDaiHwParams(const struct AudioCard *card, const struct AudioPcmHwPa
#### Registering and Binding Codec to HDF #### Registering and Binding Codec to HDF
This process depends on the driver implementation mode of the HDF. For details, see [HDF](driver-hdf-overview.md). The following implementation depends on the driver implementation mode of the HDF. For details, see [HDF](driver-overview-foundation.md).
Fill in the **g_codecDriverEntry** structure. 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. Fill 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.
drivers/peripheral/audio/chipsets/hi3516dv300/codec/src/hi3516_codec_adapter.c device/board/hisilicon/hispark_taurus/audio_drivers/codec/hi3516/src/hi3516_codec_adapter.c
```c ```c
struct HdfDriverEntry g_codecDriverEntry = { struct HdfDriverEntry g_codecDriverEntry = {
...@@ -329,9 +356,9 @@ static void CodecDriverRelease(struct HdfDeviceObject *device) ...@@ -329,9 +356,9 @@ static void CodecDriverRelease(struct HdfDeviceObject *device)
} }
``` ```
#### Configuring HCS<a name="section4115"></a> #### Configuring HCS
Configure the driver node, loading sequence, and service name in the .hcs file. For details about the HCS syntax, see [Driver Configuration Management](driver-hdf-manage.md) in the HDF. Configure 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.
Path of the standard-system configuration file: Path of the standard-system configuration file:
...@@ -343,7 +370,7 @@ Path of the small-system configuration file: ...@@ -343,7 +370,7 @@ Path of the small-system configuration file:
**Configuring Codec Device Information in device_info.hcs** **Configuring Codec Device Information in device_info.hcs**
Add codec node configuration. Modify **moduleName** in the configuration file. The value must be the same as **moduleName** in the **HdfDriverEntry** structure. Generally, the value should present the hardware platform. For example, moduleName = "CODEC_HI3516". Add 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".
The code snippet is as follows: The code snippet is as follows:
...@@ -351,20 +378,20 @@ The code snippet is as follows: ...@@ -351,20 +378,20 @@ The code snippet is as follows:
audio :: host { audio :: host {
device_codec :: device { device_codec :: device {
device0 :: deviceNode { device0 :: deviceNode {
policy = 1; // The codec module provides services only for the kernel. policy = 1; // The codec module provides services only for the kernel.
priority = 50; // The codec module must be loaded before the load of the HDF_AUDIO module. priority = 50; // The codec module must be loaded before the load of the HDF_AUDIO module.
preload = 0; preload = 0;
permission = 0666; permission = 0666;
moduleName = "CODEC_HI3516"; // The value must be the same as moduleName in HdfDriverEntry. moduleName = "CODEC_HI3516"; // The value must be the same as moduleName in HdfDriverEntry.
serviceName = "codec_service_0"; // Name of the service provided externally. serviceName = "codec_service_0"; // Name of the service provided externally.
deviceMatchAttr = "hdf_codec_driver"; // Name of the private attribute, which is used to match the corresponding private data (including the register configuration). deviceMatchAttr = "hdf_codec_driver"; // Name of the private attribute, which is used to match the corresponding private data (including the register configuration).
} }
} }
``` ```
**Configuring Dependencies in audio_config.hcs** **Configuring Dependencies in audio_config.hcs**
Configure dependencies between the codec, platform, DAI, DSP, and accessory for the audio adapters. Configure the dependency between the codec, platform, DAI, and DSP on which the audio_card device depends.
The code snippet is as follows: The code snippet is as follows:
...@@ -373,15 +400,15 @@ root { ...@@ -373,15 +400,15 @@ root {
platform { platform {
... ...
controller_0x120c1001 :: card_controller { controller_0x120c1001 :: card_controller {
// Set the private data attribute name, which must be the same as deviceMatchAttr in device_info.hcs. // Set the private data attribute name, which must be the same as the deviceMatchAttr in device_info.hcs.
match_attr = "hdf_audio_driver_1"; match_attr = "hdf_audio_driver_1";
serviceName = "hdf_audio_smartpa_dev0"; // Name of the service provided externally. serviceName = "hdf_audio_codec_primary_dev11"; // Name of the service provided externally.
accessoryName = "codec_service_1"; // External codec service name. codecName = "codec_service_1"; // Codec service name.
platformName = "dma_service_0"; // DMA service. platformName = "dma_service_0"; // DMA service.
cpuDaiName = "dai_service"; // CPU DAI service. cpuDaiName = "dai_service"; // CPU DAI service.
accessoryDaiName = "accessory_dai"; // External DAI. codecDaiName = "tfa9879_codec_dai"; // Codec DAI service.
dspName = "dsp_service_0"; // DSP service name. dspName = "dsp_service_0"; // DSP service name.
dspDaiName = "dsp_dai"; // DSP DAI. dspDaiName = "dsp_dai"; // DSP DAI.
} }
} }
} }
...@@ -391,45 +418,37 @@ root { ...@@ -391,45 +418,37 @@ root {
The configuration matches **deviceMatchAttr** of the codec configured in **device_info.hcs**. It includes the register configuration. The configuration matches **deviceMatchAttr** of the codec configured in **device_info.hcs**. It includes the register configuration.
Binding the control functionality configuration is to configure the control functionalities and their register parameters in the .hcs file according to unified structure specifications. The configuration can be obtained and parsed, and added to the controller linked list. Binding 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.
- **regConfig**: register and control functionality configuration - **regConfig**: register and control functionality configuration.
- **ctrlParamsSeqConfig**: control functionality register configuration - **ctrlParamsSeqConfig**: register configuration for a function. The items in **ctrlParamsSeqConfig** must be in the same sequence as the items in **controlsConfig**.
- **daiStartupSeqConfig**: DAI startup configuration - **daiStartupSeqConfig**: DAI startup configuration.
- **daiParamsSeqConfig**: playback parameter configuration - **daiParamsSeqConfig**: playback parameter configuration.
- **resetSeqConfig**: reset process register configuration - **resetSeqConfig**: reset process register configuration.
- **initSeqConfig**: initialization process register configuration - **initSeqConfig**: initialization process register configuration.
- **controlsConfig**: control functionality configuration. The **array index** (specific service scenario) and **iface** (same as the HAL) are of fixed values. - **controlsConfig**: control function configuration. The **array index** (specific service scenario) and **iface** (same as that in the HAL) have fixed values.
``` - **sapmConfig**: power management and control function configuration. The values of **array index** (specific service scenario) and **iface** (consistent with the HAL) have fixed values.
array index
0: Main Playback Volume - **ctrlSapmParamsSeqConfig**: register configuration of the power management and control function.
1: Main Capture Volume
2: Playback Mute - **sapmComponent**: power management component configuration.
3: Capture Mute
4: Mic Left Gain - **array index**:
5: Mic Right Gain
6: External Codec Enable The **array index** in **controlsConfig** is the element ID in the **g_audioCodecControlsList** array in the **audio_codec_base.c** file.
7: Internally Codec Enable
8: Render Channel Mode The **array index** in **sapmConfig** is the element ID in the **g_audioSapmCfgNameList** array in the **audio_codec_base.c** file.
9: Capture Channel Mode
iface The **compNameIndex** in **sapmComponent** is the element ID in the **g_audioSapmCompNameList** array in the **audio_codec_base.c** file.
0: virtual dac device
1: virtual adc device
2: virtual adc device
3: virtual mixer device
4: Codec device
5: PGA device
6: AIAO device
```
**ctrlParamsSeqConfig**: control function register configuration. The **item** sequence corresponds to the **item** sequence in **controlsConfig**, indicating the register configuration corresponding to a function. - **iface**: **2** for the virtual mixer device.
```c ```c
root { root {
...@@ -444,16 +463,16 @@ iface ...@@ -444,16 +463,16 @@ iface
serviceName = "codec_service_0"; serviceName = "codec_service_0";
codecDaiName = "codec_dai"; codecDaiName = "codec_dai";
/* Base address of the Hi3516 register*/ /* Base address of Hi3516 registers. */
idInfo { idInfo {
chipName = "hi3516"; // Codec name chipName = "hi3516"; // Codec name.
chipIdRegister = 0x113c0000; // Codec base address chipIdRegister = 0x113c0000; // Codec base address.
chipIdSize = 0x1000; // Codec address offset chipIdSize = 0x1000; // Codec address offset.
} }
/* Register configuration, including configuration of registers */ /* Register configuration, including configuration of registers. */
regConfig { regConfig {
/* reg: register address /* reg: register address
rreg: register address rreg: register address
shift: shift bits shift: shift bits
rshift: rshift bits rshift: rshift bits
...@@ -479,34 +498,33 @@ iface ...@@ -479,34 +498,33 @@ iface
0x14, 0x04000002 0x14, 0x04000002
]; ];
/* Control functionality configuration /* Control functionality configuration.
array index, iface, enable*/ array index, iface, mixer/mux, enable, */
controlsConfig = [ 0, 2, 0, 0,
0, 0, 0, 1, 2, 0, 1,
1, 1, 1, 2, 2, 0, 1,
2, 0, 1, 3, 2, 0, 1,
3, 1, 1, 4, 2, 0, 1,
4, 2, 1, 5, 2, 0, 1,
5, 2, 1, 8, 2, 0, 0,
8, 6, 0, 9, 2, 0, 0,
9, 6, 0,
]; ];
/* Control functionality register configuration /* Control functionality register configuration
reg, rreg, shift, rshift, min, max, mask, invert, value */ reg, rreg, shift, rshift, min, max, mask, invert, value */
ctrlParamsSeqConfig = [ ctrlParamsSeqConfig = [
0x3c, 0x3c, 24, 24, 0x0, 0x57, 0x7F, 1, 0, //"Main Capture Volume" 0x3c, 0x3c, 24, 24, 0x0, 0x57, 0x7F, 1, 0, // "Main Capture Volume"
0x38, 0x38, 31, 31, 0x0, 0x1, 0x1, 0, 0, //"Playback Mute" 0x38, 0x38, 31, 31, 0x0, 0x1, 0x1, 0, 0, // "Playback Mute"
0x3c, 0x3c, 31, 31, 0x0, 0x1, 0x1, 0, 0, //"Capture Mute" 0x3c, 0x3c, 31, 31, 0x0, 0x1, 0x1, 0, 0, // "Capture Mute"
0x20, 0x20, 16, 16, 0x0, 0xF, 0x1F, 0, 0, //"Mic Left Gain" 0x20, 0x20, 16, 16, 0x0, 0xF, 0x1F, 0, 0, // "Mic Left Gain"
0x20, 0x20, 24, 24, 0x0, 0xF, 0x1F, 0, 0, // "Mic Right Gain" 0x20, 0x20, 24, 24, 0x0, 0xF, 0x1F, 0, 0, // "Mic Right Gain"
0x2000, 0x2000, 16, 16, 0x0, 0x7, 0x7, 0, 0, // "Render Channel Mode" 0x2000, 0x2000, 16, 16, 0x0, 0x7, 0x7, 0, 0, // "Render Channel Mode"
0x1000, 0x1000, 16, 16, 0x0, 0x7, 0x7, 0, 0 //"Capture Channel Mode" 0x1000, 0x1000, 16, 16, 0x0, 0x7, 0x7, 0, 0 // "Capture Channel Mode"
]; ];
/* After the upper layer delivers parameters, write audio-related data to registers. /* After the upper layer delivers parameters, write audio-related data to registers.
reg, rreg, shift, rshift, min, max, mask, invert, value */ reg, rreg, shift, rshift, min, max, mask, invert, value */
daiParamsSeqConfig = [ daiParamsSeqConfig = [
0x30, 0x30, 13, 13, 0x0, 0x1F, 0x1F, 0, 0x0, // i2s_frequency 0x30, 0x30, 13, 13, 0x0, 0x1F, 0x1F, 0, 0x0, // i2s_frequency
0x1C, 0x1C, 6, 6, 0x0, 0x3, 0x3, 0, 0x0, // adc_mode_sel 0x1C, 0x1C, 6, 6, 0x0, 0x3, 0x3, 0, 0x0, // adc_mode_sel
0x30, 0x30, 22, 22, 0x0, 0x3, 0x3, 0, 0x0, // i2s_datawith 0x30, 0x30, 22, 22, 0x0, 0x3, 0x3, 0, 0x0, // i2s_datawith
]; ];
...@@ -514,37 +532,40 @@ iface ...@@ -514,37 +532,40 @@ iface
/* Configuration of the power management function register. /* Configuration of the power management function register.
reg, rreg, shift, rshift, min, max, mask, invert, value */ reg, rreg, shift, rshift, min, max, mask, invert, value */
ctrlSapmParamsSeqConfig = [ ctrlSapmParamsSeqConfig = [
0x20, 0x20, 23, 23, 0x0, 0x1, 0x1, 0, 0, //LPGA MIC 0 -- connect MIC 0x20, 0x20, 23, 23, 0x0, 0x1, 0x1, 0, 0, // LPGA MIC 0 -- connect MIC
0x20, 0x20, 31, 31, 0x0, 0x1, 0x1, 0, 0, //RPGA MIC 0 -- connect MIC 0x20, 0x20, 31, 31, 0x0, 0x1, 0x1, 0, 0, // RPGA MIC 0 -- connect MIC
0x30, 0x30, 27, 27, 0x0, 0x1, 0x1, 0, 0, //dacl to dacr mixer 0x30, 0x30, 27, 27, 0x0, 0x1, 0x1, 0, 0, // dacl to dacr mixer
0x30, 0x30, 26, 26, 0x0, 0x1, 0x1, 0, 0 //dacr to dacl mixer 0x30, 0x30, 26, 26, 0x0, 0x1, 0x1, 0, 0 // dacr to dacl mixer
]; ];
/* /*
Power management component configuration Power management component configuration.
componentName: function name, {"ADCL", "ADCR", "DACL", "DACR", "LPGA", "RPGA", "SPKL", "SPKR", "MIC"} array index. sapmType, compNameIndex, reg, mask, shift, invert, kcontrolNews, kcontrolsNum
sapmType,compNameIndex,reg, mask,shift,invert, kcontrolNews,kcontrolsNum reg = 0xFFFF: component has no sapm register bit
*/ */
sapmComponent = [ sapmComponent = [
10, 0, 0x20, 0x1, 15, 1, 0, 0, //ADCL 10, 0, 0x20, 0x1, 15, 1, 0, 0, // ADCL
10, 1, 0x20, 0x1, 14, 1, 0, 0, //ADCR 10, 1, 0x20, 0x1, 14, 1, 0, 0, // ADCR
11, 2, 0x14, 0x1, 11, 1, 0, 0, //DACL 11, 2, 0x14, 0x1, 11, 1, 0, 0, // DACL
11, 3, 0x14, 0x1, 12, 1, 0, 0, //DACR 11, 3, 0x14, 0x1, 12, 1, 0, 0, // DACR
8, 4, 0x20, 0x1, 13, 1, 1, 1, //LPGA 17, 4, 0x20, 0x1, 13, 1, 1, 1, // LPGA
8, 5, 0x20, 0x1, 12, 1, 2, 1, //RPGA 17, 5, 0x20, 0x1, 12, 1, 2, 1, // RPGA
15, 6, 0, 0x1, 0, 0, 3, 1, //SPKL 15, 6, 0xFFFF, 0xFFFF, 0, 0, 0, 0, // SPKL
15, 7, 0, 0x1, 0, 0, 4, 1, //SPKR 15, 7, 0xFFFF, 0xFFFF, 0, 0, 0, 0, // SPKR
0, 8, 0, 0x1, 0, 0, 0, 0 //MIC 17, 52, 0xFFFF, 0xFFFF, 0, 0, 3, 1, // SPKL PGA
17, 53, 0xFFFF, 0xFFFF, 0, 0, 4, 1, // SPKR PGA
13, 40, 0xFFFF, 0xFFFF, 0, 0, 0, 0, // MIC1
13, 41, 0xFFFF, 0xFFFF, 0, 0, 0, 0 // MIC2
]; ];
/* Power management function configuration /* Power management function configuration.
array index, iface, enable array index, iface, mixer/mux, enable
*/ */
sapmConfig = [ sapmConfig = [
0, 5, 1, 0, 2, 0, 1,
1, 5, 1, 1, 2, 0, 1,
2, 0, 1, 2, 2, 0, 1,
3, 0, 1 3, 2, 0, 1
]; ];
} }
} }
...@@ -609,32 +630,32 @@ int32_t CodecDeviceInit(struct AudioCard *audioCard, struct CodecDevice *codec) ...@@ -609,32 +630,32 @@ int32_t CodecDeviceInit(struct AudioCard *audioCard, struct CodecDevice *codec)
} }
``` ```
### SmartPA Driver Development Example
Code path: **device/board/hisilicon/hispark_taurus/audio_drivers/codec/tfa9879**
### Accessory Driver Development Example The SmartPA is a type of codec driver. The development process is as follows:
Code path: **drivers/peripheral/audio/chipsets/tfa9879/accessory**
SmartPA is a type of accessory driver. The SmartPA development procedure is similar to the codec development procedure. 1. Define and fill in a codec instance.
1. Define and fill in an accessory instance. 2. Implement callbacks for the codec instance.
2. Implement callbacks for the accessory instance. 3. Register and bind the codec instance to the HDF.
3. Register and bind the accessory instance to the HDF.
4. Configure the HCS and makefile. 4. Configure the HCS and makefile.
#### Filling in Accessory Data Structures #### Filling in the Codec Data Structs
Fill in the following data structures for the accessory module: Fill in the following data structs for the codec module:
- **g_tfa9879Data**: operation function set of the accessory device. It contains the configuration in the .hcs file, and defines and maps the functions for initializing the accessory device and reading and writing registers. - **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.
- **g_tfa9879DaiDeviceOps**: data set of the DAI of the accessory device. It defines and maps the operation set of the accessory device DAI. - **g_tfa9879DaiDeviceOps**: DAI data set that defines and maps the operations of the codec device DAI.
- **g_tfa9879DaiData**: data set of the DAI of the accessory device. It defines and maps the driver name, initialization, and operation set of the data access interface of the accessory device. - **g_tfa9879DaiData**: DAI data set that defines and maps the driver name, initialization, and operations of the data access interfaces of the codec device.
```c ```c
struct AccessoryData g_tfa9879Data = { struct CodecData g_tfa9879Data = {
.Init = Tfa9879DeviceInit, .Init = Tfa9879DeviceInit,
.Read = AccessoryDeviceRegRead, .Read = CodecDeviceRegI2cRead,
.Write = AccessoryDeviceRegWrite, .Write = CodecDeviceRegI2cWrite,
}; };
struct AudioDaiOps g_tfa9879DaiDeviceOps = { struct AudioDaiOps g_tfa9879DaiDeviceOps = {
...@@ -643,99 +664,98 @@ struct AudioDaiOps g_tfa9879DaiDeviceOps = { ...@@ -643,99 +664,98 @@ struct AudioDaiOps g_tfa9879DaiDeviceOps = {
}; };
struct DaiData g_tfa9879DaiData = { struct DaiData g_tfa9879DaiData = {
.drvDaiName = "accessory_dai", .drvDaiName = "tfa9879_codec_dai",
.DaiInit = Tfa9879DaiDeviceInit, .DaiInit = Tfa9879DaiDeviceInit,
.ops = &g_tfa9879DaiDeviceOps, .ops = &g_tfa9879DaiDeviceOps,
.Read = CodecDaiRegI2cRead,
.Write = CodecDaiRegI2cWrite,
}; };
``` ```
#### Initializing accessoryDevice and accessoryDai #### Initializing codecDevice and codecDai
As 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. As 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.
```c ```c
int32_t Tfa9879DeviceInit(struct AudioCard *audioCard, const struct AccessoryDevice *device) int32_t Tfa9879DeviceInit(struct AudioCard *audioCard, const struct CodecDevice *device)
{ {
int32_t ret; int32_t ret;
... ...
g_accessoryTransferData.i2cDevAddr = TFA9879_I2C_DEV_ADDR; // 0x6D
// Obtain configuration data.
ret = AccessoryDeviceCfgGet(device->devData, &g_accessoryTransferData);
...
// Initialize GPIO pins. // Initialize GPIO pins.
ret = Hi35xxGpioPinInit(); ret = Hi35xxGpioPinInit();
... ...
// Set I2C parameters.
g_transferParam.i2cBusNumber = TFA9879_I2C_BUS_NUMBER;
g_transferParam.i2cDevAddr = TFA9879_I2C_DEV_ADDR;
g_transferParam.i2cRegDataLen = TFA9879_I2C_REG_DATA_LEN;
device->devData->privateParam = &g_transferParam;
...
// Initialize device registers. // Initialize device registers.
ret = AccessoryDeviceCtrlRegInit(); ret = CodecDeviceInitRegConfig(device);
... ...
// Bind the control functionality configuration. // Bind the control functionality configuration.
ret = AudioAddControls(audioCard, g_accessoryTransferData.accessoryControls, if (AudioAddControls(audioCard, device->devData->controls, device->devData->numControls) !=
g_accessoryTransferData.accessoryCfgCtrlCount); HDF_SUCCESS) {
AUDIO_DRIVER_LOG_ERR("add controls failed.");
return HDF_FAILURE;
}
... ...
} }
``` ```
**AccessoryI2cReadWrite** reads and writes I2C registers. Common functions of the I2C read/write registers:
```c ```c
int32_t AccessoryI2cReadWrite(struct AudioAddrConfig *regAttr, uint16_t rwFlag) int32_t CodecDeviceRegI2cRead(const struct CodecDevice *codec, uint32_t reg, uint32_t *val)
{ {
int32_t ret; int32_t ret;
DevHandle i2cHandle; struct AudioAddrConfig regAttr;
int16_t transferMsgCount = 1; struct I2cTransferParam *i2cTransferParam = NULL;
uint8_t regs[I2C_REG_LEN];
struct I2cMsg msgs[I2C_MSG_NUM];
... ...
i2cHandle = I2cOpen(I2C_BUS_NUM); i2cTransferParam = (struct I2cTransferParam *)codec->devData->privateParam;
... ...
if (rwFlag == I2C_FLAG_READ) { regAttr.addr = (uint8_t)reg;
transferMsgCount = I2C_MSG_NUM; regAttr.value = 0;
} ret = CodecI2cTransfer(i2cTransferParam, &regAttr, I2C_FLAG_READ);
ret = AccessoryI2cMsgFill(regAttr, rwFlag, regs, msgs);
...
ret = I2cTransfer(i2cHandle, msgs, transferMsgCount);
... ...
AccessoryI2cRelease(msgs, transferMsgCount, i2cHandle); *val = regAttr.value;
return HDF_SUCCESS; return HDF_SUCCESS;
} }
```
#### Implementing the Accessory Operation Function Set
The callbacks **AccessoryDeviceRegRead** and **AccessoryDeviceRegWrite** invoke **AccessoryI2cReadWrite** to read and write the control register values. int32_t CodecDeviceRegI2cWrite(const struct CodecDevice *codec, uint32_t reg, uint32_t value)
```c
int32_t AccessoryDeviceRegRead(const struct AccessoryDevice *codec, uint32_t reg, uint32_t *val)
{ {
int32_t ret; int32_t ret;
struct AudioAddrConfig regAttr; struct AudioAddrConfig regAttr;
struct I2cTransferParam *i2cTransferParam = NULL;
...
i2cTransferParam = (struct I2cTransferParam *)codec->devData->privateParam;
... ...
(void)codec;
regAttr.addr = (uint8_t)reg; regAttr.addr = (uint8_t)reg;
regAttr.value = 0; regAttr.value = (uint16_t)value;
ret = AccessoryI2cReadWrite(&regAttr, I2C_FLAG_READ); ret = CodecI2cTransfer(i2cTransferParam, &regAttr, 0);
if (ret != HDF_SUCCESS) {
AUDIO_DRIVER_LOG_ERR("failed.");
return HDF_FAILURE;
}
*val = regAttr.value;
... ...
return HDF_SUCCESS; return HDF_SUCCESS;
} }
int32_t AccessoryDeviceRegWrite(const struct AccessoryDevice *codec, uint32_t reg, uint32_t value) int32_t CodecDaiRegI2cRead(const struct DaiDevice *dai, uint32_t reg, uint32_t *value)
{ {
int32_t ret; ...
struct AudioAddrConfig regAttr; ret = CodecI2cTransfer(i2cTransferParam, &regAttr, I2C_FLAG_READ);
(void)codec; ...
regAttr.addr = (uint8_t)reg; return HDF_SUCCESS;
regAttr.value = (uint16_t)value; }
ret = AccessoryI2cReadWrite(&regAttr, 0);
int32_t CodecDaiRegI2cWrite(const struct DaiDevice *dai, uint32_t reg, uint32_t value)
{
...
ret = CodecI2cTransfer(i2cTransferParam, &regAttr, 0);
... ...
return HDF_SUCCESS; return HDF_SUCCESS;
} }
``` ```
#### Implementing the Codec Operation Function Set
**Tfa9879DaiStartup** performs startup settings. The code snippet is as follows: **Tfa9879DaiStartup** performs startup settings. The code snippet is as follows:
```c ```c
...@@ -743,9 +763,9 @@ int32_t Tfa9879DaiStartup(const struct AudioCard *card, const struct DaiDevice * ...@@ -743,9 +763,9 @@ int32_t Tfa9879DaiStartup(const struct AudioCard *card, const struct DaiDevice *
{ {
int ret; int ret;
(void)card; (void)card;
(void)device; (void)device;
// Set the working status of SmartPA. // Set the register for starting the SmartPA.
ret = Tfa9879WorkStatusEnable(); ret = CodecDaiDeviceStartupRegConfig(device);
... ...
return HDF_SUCCESS; return HDF_SUCCESS;
} }
...@@ -761,29 +781,29 @@ int32_t Tfa9879DaiHwParams(const struct AudioCard *card, const struct AudioPcmHw ...@@ -761,29 +781,29 @@ int32_t Tfa9879DaiHwParams(const struct AudioCard *card, const struct AudioPcmHw
uint16_t frequency, bitWidth; uint16_t frequency, bitWidth;
struct DaiParamsVal daiParamsVal; struct DaiParamsVal daiParamsVal;
(void)card; (void)card;
... ...
// Set the sampling rate. // Set the sampling rate.
ret = AccessoryDeviceFrequencyParse(param->rate, &frequency); ret = Tfa9879FrequencyParse(param->rate, &frequency);
... ...
// Set the bit width. // Set the bit width.
ret = Tfa9879FormatParse(param->format, &bitWidth); ret = Tfa9879FormatParse(param->format, &bitWidth);
... ...
daiParamsVal.frequencyVal = frequency; daiParamsVal.frequencyVal = frequency;
daiParamsVal.formatVal = bitWidth; daiParamsVal.formatVal = bitWidth;
daiParamsVal.channelVal = param->channels; // Set the audio channel. daiParamsVal.channelVal = param->channels; // Set the audio channel.
ret = AccessoryDaiParamsUpdate(daiParamsVal); ret = Tfa9879DaiParamsUpdate(card->rtd->codecDai, daiParamsVal);
... ...
return HDF_SUCCESS; return HDF_SUCCESS;
} }
``` ```
#### Registering and Binding Accessory to HDF #### Registering and Binding Codec to HDF
This process depends on the driver implementation mode of the HDF. For details, see [HDF](driver-hdf-overview.md). The following implementation depends on the driver implementation mode of the HDF. For details, see [HDF](driver-overview-foundation.md).
Fill in the **g_tfa9879DriverEntry** structure. 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. Fill 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.
drivers/peripheral/audio/chipsets/tfa9879/accessory/src/tfa9879_accessory_adapter.c device/board/hisilicon/hispark_taurus/audio_drivers/codec/tfa9879/src/tfa9879_accessory_adapter.c
```c ```c
static int32_t Tfa9879DriverBind(struct HdfDeviceObject *device) static int32_t Tfa9879DriverBind(struct HdfDeviceObject *device)
...@@ -798,11 +818,17 @@ static int32_t Tfa9879DriverInit(struct HdfDeviceObject *device) ...@@ -798,11 +818,17 @@ static int32_t Tfa9879DriverInit(struct HdfDeviceObject *device)
int32_t ret; int32_t ret;
... ...
// Obtain configuration data from .hcs files. // Obtain configuration data from .hcs files.
ret = AccessoryGetConfigInfo(device, &g_tfa9879Data); ret = CodecGetConfigInfo(device, &g_tfa9879Data);
...
// Set the interface functions and register information related to codec control.
ret = CodecSetConfigInfoOfControls(&g_tfa9879Data, &g_tfa9879DaiData);
...
ret = CodecGetServiceName(device, &g_tfa9879Data.drvCodecName);
... ...
ret = ret = GetServiceName(device); ret = CodecGetDaiName(device, &g_tfa9879DaiData.drvDaiName);
... ...
ret = AudioRegisterAccessory(device, &g_tfa9879Data, &g_tfa9879DaiData); // Register the codec with the audio adapter.
ret = AudioRegisterCodec(device, &g_tfa9879Data, &g_tfa9879DaiData);
.... ....
return HDF_SUCCESS; return HDF_SUCCESS;
} }
...@@ -820,22 +846,22 @@ HDF_INIT(g_tfa9879DriverEntry); ...@@ -820,22 +846,22 @@ HDF_INIT(g_tfa9879DriverEntry);
#### Configuring HCS #### Configuring HCS
For details about the configuration process, see [Configuring HCS](#section4115) in **Codec Driver Development Example**. For details about the configuration process, see [Configuring HCS](#configuring-hcs) in **Codec Driver Development Example**.
### Platform Driver Development Example ### Platform Driver Development Example
Code path: **drivers/peripheral/audio/chipsets/hi3516dv300/soc**
Code path: **device/board/hisilicon/hispark_taurus/audio_drivers/soc**
In 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: In 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:
1. Define and fill in a platform instance. 1. Define and fill in a platform instance.
2. Implement callbacks for the platform instance. 2. Implement callbacks for the platform instance.
3. Register and bind the platform instance to the HDF. 3. Register and bind the codec instance to the HDF.
4. Configure the HCS and makefile. 4. Configure the HCS and makefile.
#### Filling in Platform Data Structures #### Filling in Platform Data Structures
Fill in the following structures for the platform module: Fill in the following structs for the platform module:
- **g_platformData**: private configuration of the platform device, including the initialization and operation functions of the platform device. - **g_platformData**: private configuration of the platform device, including the initialization and operation functions of the platform device.
...@@ -850,8 +876,8 @@ struct AudioDmaOps g_dmaDeviceOps = { ...@@ -850,8 +876,8 @@ struct AudioDmaOps g_dmaDeviceOps = {
.DmaPrep = Hi3516DmaPrep, // Prepare for DMA. .DmaPrep = Hi3516DmaPrep, // Prepare for DMA.
.DmaSubmit = Hi3516DmaSubmit, // Submit a DMA request. .DmaSubmit = Hi3516DmaSubmit, // Submit a DMA request.
.DmaPending = Hi3516DmaPending, // Pend DMA. .DmaPending = Hi3516DmaPending, // Pend DMA.
.DmaPause = Hi3516DmaPause, // Pause or stop DMA. .DmaPause = Hi3516DmaPause, // Pause or stop the DMA service.
.DmaResume = Hi3516DmaResume, // Resume DMA. .DmaResume = Hi3516DmaResume, // Resume the DMA service.
.DmaPointer = Hi3516DmaPointer, // Obtain the current playing or recording position. .DmaPointer = Hi3516DmaPointer, // Obtain the current playing or recording position.
}; };
...@@ -886,27 +912,28 @@ int32_t AudioDmaDeviceInit(const struct AudioCard *card, const struct PlatformDe ...@@ -886,27 +912,28 @@ int32_t AudioDmaDeviceInit(const struct AudioCard *card, const struct PlatformDe
The 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. The 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.
```c ```c
int32_t AudioDmaDeviceInit(const struct AudioCard *card, const struct PlatformDevice *platform);
int32_t Hi3516DmaBufAlloc(struct PlatformData *data, const enum AudioStreamType streamType); int32_t Hi3516DmaBufAlloc(struct PlatformData *data, const enum AudioStreamType streamType);
int32_t Hi3516DmaBufFree(struct PlatformData *data, const enum AudioStreamType streamType); int32_t Hi3516DmaBufFree(struct PlatformData *data, const enum AudioStreamType streamType);
int32_t Hi3516DmaRequestChannel(const struct PlatformData *data); int32_t Hi3516DmaRequestChannel(const struct PlatformData *data, const enum AudioStreamType streamType);
int32_t Hi3516DmaConfigChannel(const struct PlatformData *data); int32_t Hi3516DmaConfigChannel(const struct PlatformData *data, const enum AudioStreamType streamType);
int32_t Hi3516DmaPrep(const struct PlatformData *data); int32_t Hi3516DmaPrep(const struct PlatformData *data, const enum AudioStreamType streamType);
int32_t Hi3516DmaSubmit(const struct PlatformData *data); int32_t Hi3516DmaSubmit(const struct PlatformData *data, const enum AudioStreamType streamType);
int32_t Hi3516DmaPending(struct PlatformData *data); int32_t Hi3516DmaPending(struct PlatformData *data, const enum AudioStreamType streamType);
int32_t Hi3516DmaPause(struct PlatformData *data); int32_t Hi3516DmaPause(struct PlatformData *data, const enum AudioStreamType streamType);
int32_t Hi3516DmaResume(const struct PlatformData *data); int32_t Hi3516DmaResume(const struct PlatformData *data, const enum AudioStreamType streamType);
int32_t Hi3516DmaPointer(struct PlatformData *data, uint32_t *pointer); int32_t Hi3516DmaPointer(struct PlatformData *data, const enum AudioStreamType streamType, uint32_t *pointer);
``` ```
#### Registering and Binding Platform to HDF #### Registering and Binding Platform to HDF
This process depends on the driver implementation mode of the HDF. For details, see [HDF](driver-hdf-overview.md). The following implementation depends on the driver implementation mode of the HDF. For details, see [HDF](driver-overview-foundation.md).
- Fill in the **g_platformDriverEntry** structure. - Fill in the **g_platformDriverEntry** struct.
- Ensure that the value of **moduleName** is the same as that in **device_info.hcs**. - 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. - Implement the pointers to the **Bind**, **Init**, and **Release** functions.
drivers/peripheral/audio/chipsets/hi3516dv300/soc/src/hi3516_dma_adapter.c **device/board/hisilicon/hispark_taurus/audio_drivers/soc/src/hi3516_dma_adapter.c**
```c ```c
static int32_t Hi3516DmaDriverInit(struct HdfDeviceObject *device) static int32_t Hi3516DmaDriverInit(struct HdfDeviceObject *device)
...@@ -944,22 +971,22 @@ HDF_INIT(g_platformDriverEntry); ...@@ -944,22 +971,22 @@ HDF_INIT(g_platformDriverEntry);
#### Configuring HCS #### Configuring HCS
For details about the configuration process, see [Configuring HCS](#section4115) in **Codec Driver Development Example**. For details about the configuration process, see [Configuring HCS](#configuring-hcs) in **Codec Driver Development Example**.
### DAI Driver Development Example ### DAI Driver Development Example
Code path: **drivers/peripheral/audio/chipsets/hi3516dv300/soc**
Code path: **device/board/hisilicon/hispark_taurus/audio_drivers/soc**
The major steps for developing the DAI driver are as follows: The major steps for developing the DAI driver are as follows:
1. Define and fill in a DAI instance. 1. Define and fill in a DAI instance.
2. Implement callbacks for the DAI instance. 2. Implement callbacks for the DAI instance.
3. Register and bind the DAI instance to the HDF. 3. Register and bind the codec instance to the HDF.
4. Configure the HCS and makefile. 4. Configure the HCS and makefile.
#### Filling in DAI Data Structures #### Filling in DAI Data Structures
Fill in the following structures for the DAI module: Fill in the following structs for the DAI module:
- **g_daiData**: private configuration of the DAI device, including the initialization of the DAI device, read/write of registers, and operation functions. - **g_daiData**: private configuration of the DAI device, including the initialization of the DAI device, read/write of registers, and operation functions.
...@@ -996,7 +1023,7 @@ int32_t DaiDeviceInit(struct AudioCard *audioCard, const struct DaiDevice *dai) ...@@ -996,7 +1023,7 @@ int32_t DaiDeviceInit(struct AudioCard *audioCard, const struct DaiDevice *dai)
data->regVirtualAddr = (uintptr_t)g_regCodecBase; data->regVirtualAddr = (uintptr_t)g_regCodecBase;
DaiSetConfigInfo(data); DaiSetConfigInfo(data);
AudioAddControls(audioCard, data->controls, data->numControls); AudioAddControls(audioCard, data->controls, data->numControls);
I2c6PinInit(); I2c6PinInit();
... ...
data->daiInitFlag = true; data->daiInitFlag = true;
return HDF_SUCCESS; return HDF_SUCCESS;
...@@ -1026,7 +1053,7 @@ int32_t DaiHwParams(const struct AudioCard *card, const struct AudioPcmHwParams ...@@ -1026,7 +1053,7 @@ int32_t DaiHwParams(const struct AudioCard *card, const struct AudioPcmHwParams
data->pcmInfo.streamType = param->streamType; data->pcmInfo.streamType = param->streamType;
data->regVirtualAddr = (uintptr_t)g_regDaiBase; data->regVirtualAddr = (uintptr_t)g_regDaiBase;
... ...
DaiParamsUpdate(device); DaiParamsUpdate(device);
data->regVirtualAddr = (uintptr_t)g_regCodecBase; data->regVirtualAddr = (uintptr_t)g_regCodecBase;
return HDF_SUCCESS; return HDF_SUCCESS;
} }
...@@ -1064,13 +1091,13 @@ int32_t DaiStartup(const struct AudioCard *card, const struct DaiDevice *device) ...@@ -1064,13 +1091,13 @@ int32_t DaiStartup(const struct AudioCard *card, const struct DaiDevice *device)
#### Registering and Binding DAI to HDF #### Registering and Binding DAI to HDF
This process depends on the driver implementation mode of the HDF. For details, see [HDF](driver-hdf-overview.md). The following implementation depends on the driver implementation mode of the HDF. For details, see [HDF](driver-overview-foundation.md).
- Fill in the **g_daiDriverEntry** structure. - Fill in the **g_daiDriverEntry** struct.
- Ensure that the value of **moduleName** is the same as that in **device_info.hcs**. - 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. - Implement the pointers to the **Bind**, **Init**, and **Release** functions.
drivers/peripheral/audio/chipsets/hi3516dv300/soc/src/hi3516_dai_adapter.c **device/board/hisilicon/hispark_taurus/audio_drivers/soc/src/hi3516_dai_adapter.c**
```c ```c
static int32_t DaiDriverBind(struct HdfDeviceObject *device) static int32_t DaiDriverBind(struct HdfDeviceObject *device)
...@@ -1120,112 +1147,107 @@ HDF_INIT(g_daiDriverEntry); ...@@ -1120,112 +1147,107 @@ HDF_INIT(g_daiDriverEntry);
#### Configuring HCS #### Configuring HCS
For details about the configuration process, see [Configuring HCS](#section4115) in **Codec Driver Development Example**. For details about the configuration process, see [Configuring HCS](#configuring-hcs) in **Codec Driver Development Example**.
### Adding Compilation Configuration to Makefile ### Adding Compilation Configuration to Makefile
Add the newly added files to the **Makefile** file to link them to the kernel image. Add the newly added files to the **Makefile** file to link them to the kernel image.
Standard system (Linux): **drivers/adapter/khdf/linux/model/audio/Makefile** Standard system (Linux): **device/board/hisilicon/hispark_taurus/audio_drivers/Makefile**
```makefile ```makefile
obj-$(CONFIG_DRIVERS_HDF_AUDIO_CODEC) += \ obj-$(CONFIG_DRIVERS_HDF_AUDIO_HI3516CODEC) += \
$(KHDF_AUDIO_HI3516DV300_DIR)/../tfa9879/accessory/src/tfa9879_accessory_adapter.o \ codec/tfa9879/src/tfa9879_codec_adapter.o \
$(KHDF_AUDIO_HI3516DV300_DIR)/../tfa9879/accessory/src/tfa9879_accessory_impl.o \ codec/tfa9879/src/tfa9879_codec_ops.o \
$(KHDF_AUDIO_HI3516DV300_DIR)/codec/src/hi3516_codec_adapter.o \ codec/hi3516/src/hi3516_codec_adapter.o \
$(KHDF_AUDIO_HI3516DV300_DIR)/codec/src/hi3516_codec_impl.o \ codec/hi3516/src/hi3516_codec_impl.o \
$(KHDF_AUDIO_HI3516DV300_DIR)/codec/src/hi3516_codec_ops.o \ codec/hi3516/src/hi3516_codec_ops.o \
$(KHDF_AUDIO_HI3516DV300_DIR)/dsp/src/dsp_adapter.o \ dsp/src/dsp_adapter.o \
$(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dai_adapter.o \ dsp/src/dsp_ops.o \
$(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dai_ops.o \ soc/src/hi3516_dai_adapter.o \
$(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_aiao_impl.o \ soc/src/hi3516_dai_ops.o \
$(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dma_ops.o \ soc/src/hi3516_aiao_impl.o \
$(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dma_adapter.o \ soc/src/hi3516_dma_ops.o \
$(KHDF_AUDIO_HI3516DV300_DIR)/codec/src/hi3516_codec_adapter.o soc/src/hi3516_dma_adapter.o
``` ```
Small system (LiteOS): **drivers/adapter/khdf/liteos/model/audio/Makefile** Small system (LiteOS): **drivers/adapter/khdf/liteos/model/audio/Makefile**
```makefile ```makefile
LOCAL_SRCS += \ LOCAL_SRCS += \
$(KHDF_AUDIO_HI3516DV300_DIR)/../tfa9879/accessory/src/tfa9879_accessory_adapter.c \ $(KHDF_AUDIO_HI3516DV300_DIR)/codec/tfa9879/src/tfa9879_codec_adapter.c \
$(KHDF_AUDIO_HI3516DV300_DIR)/../tfa9879/accessory/src/tfa9879_accessory_impl.c \ $(KHDF_AUDIO_HI3516DV300_DIR)/codec/tfa9879/src/tfa9879_codec_ops.c \
$(KHDF_AUDIO_HI3516DV300_DIR)/codec/src/hi3516_codec_adapter.c \ $(KHDF_AUDIO_HI3516DV300_DIR)/codec/hi3516/src/hi3516_codec_adapter.c \
$(KHDF_AUDIO_HI3516DV300_DIR)/codec/src/hi3516_codec_impl.c \ $(KHDF_AUDIO_HI3516DV300_DIR)/codec/hi3516/src/hi3516_codec_impl.c \
$(KHDF_AUDIO_HI3516DV300_DIR)/codec/src/hi3516_codec_ops.c \ $(KHDF_AUDIO_HI3516DV300_DIR)/codec/hi3516/src/hi3516_codec_ops.c \
$(KHDF_AUDIO_HI3516DV300_DIR)/dsp/src/dsp_adapter.c \ $(KHDF_AUDIO_HI3516DV300_DIR)/dsp/src/dsp_adapter.c \
$(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dai_adapter.c \ $(KHDF_AUDIO_HI3516DV300_DIR)/dsp/src/dsp_ops.c \
$(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dai_ops.c \ $(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dai_adapter.c \
$(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_aiao_impl.c \ $(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dai_ops.c \
$(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dma_ops.c \ $(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_aiao_impl.c \
$(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dma_adapter.c $(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dma_ops.c \
$(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dma_adapter.c
``` ```
### Source Code Structure and Directory ### Source Code Structure and Directory
The development example implements the functions in the header file of the driver interface. The following uses Hi3516 as an example to describe the directory structure. The 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.
Path of the driver implementation sample code: **drivers\peripheral\audio\chipsets\** Path of the driver implementation sample code: **device/board/hisilicon/hispark_taurus/audio_drivers/**
``` ```shell
├── hi3516dv300 .
│   ├── codec ├── codec
│   │   ├── include │ ├── hi3516
│   │   │   ├── hi3516_codec_impl.h │ │ ├── include
│   │   │   └── hi3516_codec_ops.h │ │ │ ├── hi3516_codec_impl.h
│   │   ├── src │ │ │ └── hi3516_codec_ops.h
│ │ └── src
│ │ │ ├── hi3516_codec_adapter.c // Codec driver entry │ │ │ ├── hi3516_codec_adapter.c // Codec driver entry
│ │ │ ├── hi3516_codec_impl.c // Implement codec hardware operations. │ │ │ ├── hi3516_codec_impl.c // Implementation of codec hardware operations
│ │ │ └── hi3516_codec_ops.c // Implement codec driver APIs. │ │ │ └── hi3516_codec_ops.c // Implementation of codec driver APIs
│   │   └── test │ └── tfa9879
│   │   └── unittest │ ├── include
│   ├── dsp │ │ └── tfa9879_codec_ops.h
│   │   └── include │ └── src
│   │   └── dsp_ops.h │ ├── tfa9879_codec_adapter.c
│   │   └── src │ └── tfa9879_codec_ops.c
│ │ └── dsp_adapter.c // DSP driver entry ├── dsp
│   │   └── dsp_ops.c │ ├── include
│   └── soc │ │ └── dsp_ops.h
│   ├── include │ └── src
│   │   ├── hi3516_aiao_impl.h │ ├── dsp_adapter.c // DSP driver entry
│   │   ├── hi3516_dai_ops.h │ └── dsp_ops.c
│   │   └── hi3516_dma_ops.h ├── LICENSE
│   ├── src ├── Makefile
│   │   ├── hi3516_aiao_impl.c └── soc
│ │ ├── hi3516_dai_adapter.c // DAI driver entry ├── include
│   │   ├── hi3516_dai_ops.c │ ├── hi3516_aiao_impl.h
│ │ ├── hi3516_dma_adapter.c // DMA driver entry │ ├── hi3516_dai_ops.h
│   │   └── hi3516_dma_ops.c │ └── hi3516_dma_ops.h
│   └── test └── src
│   └── unittest ├── hi3516_aiao_impl.c
└── tfa9879 ├── hi3516_dai_adapter.c // DAI driver entry
   └── accessory ├── hi3516_dai_ops.c
   ├── include ├── hi3516_dma_adapter.c // DMA driver entry
   │   └── tfa9879_accessory_impl.h └── hi3516_dma_ops.c
   └── src
├── tfa9879_accessory_adapter.c // Accessory driver entry
   └── tfa9879_accessory_impl.c
``` ```
HCS Files and Directory HCS Files and Directory
``` ```shell
Standard system: Standard system:
vendor/hisilicon/hispark_taurus_standard/ vendor/hisilicon/hispark_taurus_standard/
└── hdf_config └── hdf_config
└── khdf └── khdf
├── audio ├── audio
   ├── audio_config.hcs ├── audio_config.hcs
   ├── codec_config.hcs ├── codec_config.hcs
   ├── dai_config.hcs ├── dai_config.hcs
   ├── dma_config.hcs ├── dma_config.hcs
   └── dsp_config.hcs └── dsp_config.hcs
├── device_info ├── device_info
   └── device_info.hcs └── device_info.hcs
└── hdf.hcs └── hdf.hcs
Small system: Small system:
...@@ -1233,72 +1255,75 @@ vendor/hisilicon/hispark_taurus/ ...@@ -1233,72 +1255,75 @@ vendor/hisilicon/hispark_taurus/
├── config.json ├── config.json
└── hdf_config └── hdf_config
├── audio ├── audio
   ├── audio_config.hcs ├── audio_config.hcs
   ├── codec_config.hcs ├── codec_config.hcs
   ├── dai_config.hcs ├── dai_config.hcs
   ├── dma_config.hcs ├── dma_config.hcs
   └── dsp_config.hcs └── dsp_config.hcs
├── device_info ├── device_info
   └── device_info.hcs └── device_info.hcs
└── hdf.hcs └── hdf.hcs
``` ```
## HAL-based Development Procedure and Example ## HAL-based Development Procedure and Example
The Hardware Abstraction Layer (HAL) provides the following functions:
1. Provides audio HDIs for audio services to implement basic audio features on applications. The Hardware Abstraction Layer (HAL) provides the following function:
2. Provides standard interfaces for device developers to comply with the HDI adapter standards. This promises a healthy evolution of the ecosystem.
- Provides audio HDIs for audio services to implement basic audio features on applications.
- Provides standard interfaces for device developers to comply with the HDI adapter standards. This promises a healthy evolution of the ecosystem.
Code path: **drivers/peripheral/audio/hal** Code path: **drivers_interface/audio/v1_0**
### Development procedure ### Development procedure
![](figures/HAL_flowchart.png) ![](figures/HAL_flowchart.png)
1. Call **GetAudioManagerFuncs()** to obtain functions. 1. Call **GetAudioManagerFuncs()** to obtain methods.
2. Call **GetAllAdapters()** to obtain information about the supported audio adapters and call **LoadAdapter()** to load the corresponding audio adapter.
3. Create an audio player class by calling **CreateRender()** or create a recorder class and deliver audio attributes.
4. Call the methods mounted to the created audio player class to call **render->control.Start()** and **render->RenderFrame()** to dispatch the start instruction and deliver audio data cyclically. 2. Use **GetAllAdapters()** to obtain information about the supported audio adapter, and call **LoadAdapter()** to load the audio adapter.
5. During the playback, call **render->control.Pause()**, **render->control.Resume()**, or **render->volume.SetVolume()** to control the audio player service, for example, pausing the playback, resuming the playback, and adjusting the volume. 3. Create a **Render** class by calling **CreateRender()** or create a recorder class and deliver audio attributes.
6. After the audio player service is complete, stop the playback, destroy the audio player class, and unload the audio adapter. 4. 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.
1. render->control.Stop(); 5. 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.
2. adapter->DestroyRender(); 6. 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.
3. manager->UnloadAdapter(); ### HAL Usage Example
### Development Example
```c ```c
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include "audio_types.h"
#include <pthread.h> #include <pthread.h>
#include "audio_manager.h" #include "v1_0/audio_types.h"
#include "v1_0/iaudio_manager.h"
/* Open the dynamic link to the so library. */
char *soPathHdi = "/system/lib/libhdi_audio.z.so"; struct IAudioRender *g_render = NULL;
void *g_handle = dlopen(soPathHdi , 1); struct IAudioAdapter *g_adapter = NULL;
struct AudioDeviceDescriptor g_devDesc;
int32_t FrameStart(void *param) struct AudioSampleAttributes g_attrs;
struct AudioHeadInfo g_wavHeadInfo;
bool g_isDirect = false; //IPC Loading
uint32_t g_renderId = 0;
static int32_t FrameStart(const struct StrPara *param)
{ {
... ...
/* Initialize parameters. */
char *frame = param->frame;
int32_t bufferSize = param->bufferSize;
size_t remainingDataSize = g_wavHeadInfo.riffSize;
/* Send audio data cyclically. */ /* Send audio data cyclically. */
do { do {
readSize = (remainingDataSize > bufferSize) ? bufferSize : remainingDataSize; uint64_t replyBytes = 0;
size_t readSize = (remainingDataSize > bufferSize) ? (size_t)bufferSize : remainingDataSize;
numRead = fread(frame, 1, readSize, g_file); numRead = fread(frame, 1, readSize, g_file);
if (numRead > 0) { if (numRead > 0) {
ret = render->RenderFrame(render, frame, numRead, &replyBytes); int32_t ret = render->RenderFrame(render, (int8_t *)frame, numRead, &replyBytes);
if (ret == HDF_ERR_INVALID_OBJECT) { if (ret == HDF_ERR_INVALID_OBJECT) {
LOG_FUN_ERR("Render already stop!"); AUDIO_FUNC_LOGE("Render already stop!");
break; break;
} }
remainingDataSize -= numRead; remainingDataSize -= numRead;
...@@ -1315,54 +1340,57 @@ int32_t FrameStart(void *param) ...@@ -1315,54 +1340,57 @@ int32_t FrameStart(void *param)
static void *hal_main() static void *hal_main()
{ {
/* Map and call the entry function. */ int32_t adapterIndex = 0;
struct AudioManager *(*getAudioManager)() = struct AudioPort *renderPort;
(struct AudioManager *(*)())(dlsym(g_handle, "GetAudioManagerFuncs"));
struct AudioManager *manager = getAudioManager(); /* Call IAudioManagerGet() to obtain the entry function. */
struct IAudioManager *audioManagerIns = IAudioManagerGet(g_isDirect);
if (audioManagerIns == NULL) {
AUDIO_FUNC_LOGE("Get Audio Manager Fail");
return HDF_FAILURE;
}
/* Obtain the audio adapter list. */ /* Obtain the audio adapter list. */
struct AudioAdapterDescriptor *descs = NULL; struct AudioAdapterDescriptor *descs = (struct AudioAdapterDescriptor *)OsalMemCalloc(
int32_t size = 0; sizeof(struct AudioAdapterDescriptor) * (MAX_AUDIO_ADAPTER_DESC));
int32_t ret = manager->GetAllAdapters(manager, &descs, &size); uint32_t adapterNum = MAX_AUDIO_ADAPTER_DESC;
int32_t ret = audioManagerIns->GetAllAdapters(audioManagerIns, descs, &adapterNum);
/* Locate the audio adapter and port based on the specified audio adapter name and port description. */ /* Locate the audio adapter and port based on the specified audio adapter name and port description. */
enum AudioPortDirection port = PORT_OUT; // The port type OUT means to play the audio. SelectAudioCard(descs, adapterNum, &adapterIndex);
struct AudioPort renderPort; strcpy_s(g_adapterName, PATH_LEN, descs[adapterIndex - 1].adapterName);
char * adapterNameCase = "usb"; SwitchAudioPort(&descs[adapterIndex - 1], PORT_OUT, renderPort); // The port type is OUT, which means playback.
int32_t index = SwitchAdapter(descs, adapterNameCase, port, &renderPort, size);
/* Load the audio adapter based on the matched audio adapter information. */ /* Load the audio adapter based on the matched audio adapter information. */
struct AudioAdapter *adapter = NULL; audioManagerIns->LoadAdapter(audioManagerIns, &descs[adapterIndex - 1], &g_adapter); // Load the audio adapter and obtain the related instances.
struct AudioAdapterDescriptor *desc = &descs[index]; // Obtain the device based on the matched audio adapter information.
manager->LoadAdapter(manager, desc, &adapter); // Load the audio adapter and obtain the audio adapter instance. /* Create a Render class. */
uint32_t portId = renderPort->portId;
/* Create an audio player class. */ InitDevDesc(&g_devDesc, portId); // Initialize the parameters for setting the device.
struct AudioRender *render; InitAttrs(&g_attrs); // Initialize audio attribute parameters.
struct AudioDeviceDescriptor devDesc; CheckWavFileHeader(g_file, &g_wavHeadInfo, &g_attrs); // Parse the audio file and set attributes.
struct AudioSampleAttributes attrs; g_adapter->CreateRender(g_adapter, &g_devDesc, &g_attrs, &g_render, &g_renderId);
InitDevDesc(&devDesc, renderPort.portId); // Initialize device parameters.
WavHeadAnalysis(g_file, &attrs); // Parse the audio file to set attributes. /* Deliver the number of the audio to be played. */
adapter->CreateRender(adapter, &devDesc, &attrs, &render); g_render->Start((void *)g_render); // Send the start command to start the playback.
pthread_create(&g_tids, &tidsAttr, (void *)(&FrameStart), &g_str); // Start the thread to play the music.
/* Deliver the audio data to play. */
render->control.Start((AudioHandle)render); // Dispatch the start instruction and prepare for the action. /* Send the control instructions. */
pthread_create(&g_tids, NULL, (void *)(&FrameStart), &g_str); // Start the thread to play the audio clip. g_render->Pause((void *)g_render); // Pause the playback.
g_render->Resume((void *)g_render); // Resume the playback.
/* Control instructions */ g_render->SetVolume((void *)g_render, 0.5); // Set the volume.
render->control.Pause((AudioHandle)render); // Pause the playback.
render->control.Resume((AudioHandle)render); // Resume the playback. /* Stop playback and destroy the Render class. */
render->volume.SetVolume((AudioHandle)render, 0.5); // Set the volume. g_render->Stop((void *)g_render);
g_adapter->DestroyRender(g_adapter, g_renderId);
/* Stop playback and destroy the audio player class. */
render->control.Stop((AudioHandle)render);
adapter->DestroyRender(adapter, render);
/* Unload the audio adapter. */ /* Unload the audio adapter. */
manager->UnloadAdapter(manager, adapter); audioManagerIns->UnloadAdapter(audioManagerIns, g_adapterName);
} }
``` ```
## Summary ## Summary
This 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 framework. This 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.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册