- The High-Definition Multimedia Interface (HDMI) is an audio/video transmission protocol released by Hitachi, Panasonic, Philips, Silicon Image, Sony, Thomson, Toshiba.
- The HDMI works in master/slave mode and usually has a source and a sink.
- The HDMI APIs provide a set of common functions for HDMI transmission, including:
High-Definition Multimedia Interface (HDMI) is an audio/video transmission protocol released by Hitachi, Panasonic, Philips, Silicon Image, Sony, Thomson, and Toshiba.
- Opening and closing an HDMI controller.
- Starting and stopping HDMI transmission.
- Setting audio, video, and High Dynamic Range (HDR) attributes, color depth, and AV mute.
- Reading the raw Extended Display Identification Data (EDID) from a sink.
- Registering and unregistering a callback for HDMI hot plug detect.
-[Figure 1](#fig1) shows the HDMI physical connection.
HDMI works in master/slave mode and usually has a source and a sink.
<tdclass="cellrowborder"valign="top"width="53.339999999999996%">Reads the raw EDID from a sink.</p>
</td>
</tr>
<tr><tdclass="cellrowborder"bgcolor="#ffffff"rowspan="2"valign="top"width="18.63%"><p>Registering or unregistering a callback for HDMI hot plug detect</p>
<tr><tdclass="cellrowborder"bgcolor="#ffffff"rowspan="2"valign="top"width="18.63%"><p>Registering or unregistering a callback for HDMI HPD</p>
The Improved Inter-Integrated Circuit (I3C) is a simple and cost-efficient bidirectional 2-wire synchronous serial bus protocol developed by the Mobile Industry Processor Interface (MIPI) Alliance.
I3C is backward compatible with legacy Inter-Integrated Circuit (I2C) devices. Moreover, it provides the in-band interrupt (IBI) function and supports hot-join of I3C devices. This eliminates the need for adding an extra interrupt line to implement interrupts in I2C.
I3C is backward compatible with legacy Inter-Integrated Circuit (I2C). Moreover, it provides the in-band interrupt (IBI) function and supports hot-join of I3C devices. This eliminates the need for adding an extra interrupt line to implement interrupts in I2C.
The I2C device, I3C slave device, and I3C secondary master device can coexist on the I3C bus.
The I3C APIs provide a set of common functions for I3C transfer, including:
-Opening and closing an I3C controller.
-Obtaining and setting I3C controller parameters.
-Performing customized I3C message transfer by using a message array.
-Requesting and releasing an IBI.
- Opening and closing an I3C controller
- Obtaining and setting I3C controller parameters
- Performing custom I3C message transfer by using a message array
- Requesting and releasing an IBI
[Figure 1](#fig1) shows the I3C physical connection.
<tdclass="cellrowborder"valign="top"width="50%"><p>Transmission mode, where the value 0 indicates the I2C mode, 1 indicates the I3C mode, and 2 indicates transmission of the Common Command Code (CCC).
<tdclass="cellrowborder"valign="top"width="50%"><p>Transmission mode, where the value <b>0</b> indicates the I2C mode, <b>1</b> indicates the I3C mode, and <b>2</b> indicates transmission of the Common Command Code (CCC).
>- The device address in the **I3cMsg** structure does not contain the read/write flag bit. The read/write information is passed by the read/write control bit in the member variable **flags**.
>- The **I3cTransfer()** function does not limit the number of message structures or the length of data in each message structure. The I3C controller determines these two parameters.
>- The **I3cTransfer()** function does not limit the number of message structures or the length of data in each message structure. The I3C controller determines these two limits.
>- Using **I3cTransfer()** may cause the system to sleep. Do not call it in the interrupt context.
### Obtaining the I3C Controller Configuration<a name="section7"></a>
The pin module controls the states and functionalities of system pins. In the Hardware Driver Foundation (HDF), the pin module uses the service-free mode for API adaptation. The service-free mode applies to devices that do not provide user-mode APIs or the OS system that does not distinguish the user mode and the kernel mode. In the service-free mode, DevHandle (a void pointer) directly points to the kernel-mode address of the device object.
| SetPinPull | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**pullType**: pull type of the pin. It is an enum constant.|HDF_STATUS|Sets the pull type of a pin.|
| GetPinPull | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**pullType**: pointer to the pull type of the pin.| HDF_STATUS| Obtains the pull type of a pin.|
| SetPinStrength | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**strength**: pull strength of the pin. It is a uint32_t variable.| HDF_STATUS| Sets the pull strength of a pin.|
| GetPinStrength | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**strength**: pointer to the pull strength of the pin.| HDF_STATUS| Obtains the pull strength of a pin.|
| SetPinFunc | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**funcName**: char pointer to the pin functionality.| HDF_STATUS| Sets the pin functionality.|
| GetPinFunc | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**funcName**: char double pointer to the pin functionality.| HDF_STATUS| Obtains the pin functionalities.|
## How to Develop<a name="section3_PinDevelop"></a>
The pin module adaptation involves the following steps:
1. Instantiate the driver entry.
- Instantiate the **HdfDriverEntry** structure.
- Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF.
2. Configure attribute files.
- Add the **deviceNode** information to the **device_info.hcs** file.
- (Optional) Add the **pin_config.hcs** file.
3. Instantiate the pin controller object.
- Initialize the **PinCntlr** object.
- Instantiate **PinCntlrMethod** in the **PinCntlr** object.
>For details, see [Available APIs](#section2_PINDevelop).
4. Debug the driver.
- (Optional) Verify basic functionalities of new drivers. For example, verify the information returned when the driver is loaded and whether data is successfully transmitted.
## Development Example<a name="section4_PinDevelop"></a>
The following uses **pin_hi35xx.c** as an example to present the content to be provided by the vendor to implement device functionalities.
1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type (defined in **hdf\_device\_desc.h**), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers are collected to form a segment address space similar to an array for the upper layer to invoke.
Generally, the HDF calls the **Bind** function and then the **Init** function to load the driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
.moduleName="hi35xx_pin_driver",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
};
// Call HDF_INIT to register the driver entry with the HDF.
HDF_INIT(g_hi35xxPinDriverEntry);
```
2. Add **deviceNode** to the **device\_info.hcs** file, and set the device attributes in the **pin\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **PinCntlr** members at the core layer.
>If there are multiple devices, add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **pin\_config** file.
-**device\_info.hcs** reference:
```c
root {
device_info {
platform :: host {
hostName = "platform_host";
priority = 50;
device_pin :: device {
device0:: deviceNode { // Set an HDF device node for each pin controller.
policy = 0; // 2: visible in user mode; 1: visible in kernel mode; 0: no service required.
priority = 10; // Driver startup priority.
permission = 0644; // Permission to create device nodes for the driver.
/* (Mandatory) Driver name, which must be the same as the moduleName in the driver entry. */
moduleName = "hi35xx_Pin_driver";
/* (Mandatory) Set the controller private data, which must be same as that in Pin_config.hcs. */
deviceMatchAttr = "hisilicon_hi35xx_Pin_0";
}
device1 :: deviceNode {
policy = 0;
priority = 10;
permission = 0644;
moduleName = "hi35xx_Pin_driver";
deviceMatchAttr = "hisilicon_hi35xx_Pin_1";
}
...
}
}
}
}
```
-**Pin\_config.hcs** reference:
```c
root {
platform {
Pin_config_hi35xx {
template Pin_controller { // (Mandatory) Template configuration. In the template, you can configure the common parameters shared by device nodes.
number = 0; // (Mandatory) Controller ID.
regStartBasePhy = 0; // (Mandatory) Start physical base address of the register.
regSize = 0; // (Mandatory) Register bit width.
PinCount = 0; // (Mandatory) Number of pins.
match_attr = "";
template Pin_desc {
PinName = ""; // (Mandatory) Pin name.
init = 0; // (Mandatory) Default value of the register.
F0 = ""; // (Mandatory) Functionality 0.
F1 = ""; // Functionality 1.
F2 = ""; // Functionality 2.
F3 = ""; // Functionality 3.
F4 = ""; // Functionality 4.
F5 = ""; // Functionality 5.
}
}
controller_0 :: Pin_controller {
number = 0;
regStartBasePhy = 0x10FF0000;
regSize = 0x48;
PinCount = 18;
match_attr = "hisilicon_hi35xx_Pin_0";
T1 :: Pin_desc {
PinName = "T1";
init = 0x0600;
F0 = "EMMC_CLK";
F1 = "SFC_CLK";
F2 = "SFC_BOOT_MODE";
}
...
}
...// Each pin controller corresponds to a controller node. If there are multiple pin controllers, add the corresponding controller nodes one by one.
}
}
}
```
3. Initialize the **PinCntlr** object at the core layer, including initializing the vendor custom structure (passing parameters and data), instantiating **PinCntlrMethod** (used to call underlying functions of the driver) in **PinCntlr**, and implementing the **HdfDriverEntry** member functions (**Bind**, **Init**, and **Release**).
- Initializing the vendor custom structure
The **PinCntlr** structure holds parameters and data for the driver. The HDF obtains the values in **pin\_config.hcs** using **DeviceResourceIface**.
```c
// PinCntlr is the controller structure at the core layer. Its members are assigned with values by using the Init function.
struct PinCntlr {
struct IDeviceIoService service;
struct HdfDeviceObject *device;
struct PinCntlrMethod *method;
struct DListHead node;
OsalSPinlock sPin;
uint16_t number;
uint16_t PinCount;
struct PinDesc *Pins;
void *priv;
};
struct PinDesc {
const char *PinName; // Pointer to the pin name.
void *priv;
};
```
- Instantiating **PinCntlrMethod** (other members are initialized by **Init**)
```c
// Example of Pin_hi35xx.c: Instantiate the hook.
staticstructPinCntlrMethodg_method={
.SetPinPull=Hi35xxPinSetPull,
.GetPinPull=Hi35xxPinGetPull,
.SetPinStrength=Hi35xxPinSetStrength,
.GetPinStrength=Hi35xxPinGetStrength,
.SetPinFunc=Hi35xxPinSetFunc,
.GetPinFunc=Hi35xxPinGetFunc,
};
```
-**Init** function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration.
Return value:
**HDF\_STATUS** (The following table lists some states. For more details, see **HDF\_STATUS** in **/drivers/framework/include/utils/hdf\_base.h**.)
<tdclass="cellrowborder"valign="top"width="50%"headers="mcps1.1.3.1.2 "><pid="entry361497788164144p0"><aname="entry361497788164144p0"></a><aname="entry361497788164144p0"></a>Failed to allocate memory</p>
Initializes the custom structure and **PinCntlr** members, and connects to the pin controller by calling the **PinCntlrAdd** function at the core layer.
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration.
Return value:
–
Function description:
Releases memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. If the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources.
The regulator module controls the voltage and current supplies of some devices in the system. In an embedded system (especially a mobile phone), it is important to control the power consumption, which directly affects the battery endurance. You can use a regulator to shut down the power supply to an idle module in the system or reduce the voltage and current for the module.
- The regulator APIs provide a set of functions for managing a regulator, including those for:
- Opening or closing a regulator device handle
- Setting the output voltage and current for a regulator
- Enabling or disabling a regulator
- Obtaining the voltage, current, and status of a regulator
## Available APIs<a name="section2_REGULATOR_des"></a>
### How to Use<a name="section3.1_REGULATOR_des"></a>
During the OS startup process, the driver management module loads the regulator driver based on the configuration file. Then, the regulator driver detects the regulator devices and initializes the driver.
The figure below shows the process of using a regulator.
**Figure 1** Process of using a regulator<aname="fig1_regulator_des"></a>
![](figures/process-of-using-regulator.png)
### Opening a Regulator Device Handle<a name="section3.2_REGULATOR_des"></a>
Before operating a regulator, call **RegulatorOpen** to open the device handle of the regulator. This function returns the device handle of the regulator.
```c
DevHandleRegulatorOpen(constchar*name);
```
**Table 2** Description of RegulatorOpen
<aname="table2_REGULATOR_des"></a>
| **Parameter** | **Description** |
| ---------- | ----------------------------- |
| name | Name of the target regulator. |
| **Return Value**| **Description** |
| handle | The regulator device handle is returned if the operation is successful.|
| NULL | The operation fails. |
```c
/* Regulator name. */
constchar*name="regulator_virtual_1";
DevHandlehandle=NULL;
/* Open the regulator device handle. */
handle=RegulatorOpen(name);
if(handle==NULL){
/* Error handling. */
}
```
### Closing a Regulator Device Handle<a name="section3.3_REGULATOR_des"></a>
Call **RegulatorClose** to close the regulator device handle to release resources.
```c
voidRegulatorClose(DevHandlehandle);
```
**Table 3** Description of RegulatorClose
<aname="table3_REGULATOR_des"></a>
| **Parameter** | **Description** |
| ------ | ----------------- |
| handle | Regulator device handle to close.|
```c
/* Close the regulator device handle. */
RegulatorClose(handle);
```
### Enabling a Regulator<a name="section3.4_REGULATOR_des"></a>
Call **RegulatorEnable** to enable a regulator.
```c
int32_tRegulatorEnable(DevHandlehandle);
```
**Table 4** Description of RegulatorEnable
<aname="table4_REGULATOR_des"></a>
| **Parameter** | **Description** |
| ---------- | ----------------- |
| handle | Device handle of the regulator to enable.|
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
```c
int32_tret;
/* Enable the regulator. */
ret=RegulatorEnable(handle);
if(ret!=0){
/* Error handling. */
}
```
### Disabling a Regulator<a name="section3.5_REGULATOR_des"></a>
Call **RegulatorDisable** to disable a regulator. The operation will fail if the regulator status is set to always on or if a child node of the regulator is not disabled.
```c
int32_tRegulatorDisable(DevHandlehandle);
```
**Table 5** Description of RegulatorDisable
<aname="table5_REGULATOR_des"></a>
| **Parameter** | **Description** |
| ---------- | ----------------- |
| handle | Device handle of the regulator to disable.|
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
```c
int32_tret;
/* Disable the regulator. */
ret=RegulatorDisable(handle);
if(ret!=0){
/* Error handling. */
}
```
### Forcibly Disabling a Regulator<a name="section3.6_REGULATOR_des"></a>
Call **RegulatorForceDisable** to forcibly disable a regulator. The regulator will be disabled event if its status is set to always on or its child node is still enabled.
```c
int32_tRegulatorForceDisable(DevHandlehandle);
```
**Table 6** Description of RegulatorForceDisable
<aname="table6_REGULATOR_des"></a>
| **Parameter** | **Description** |
| ---------- | ----------------- |
| handle | Device handle of the target regulator.|
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
```c
int32_tret;
/* Forcibly disable the regulator. */
ret=RegulatorForceDisable(handle);
if(ret!=0){
/* Error handling. */
}
```
### Setting the Output Voltage Range for a Regulator<a name="section3.7_REGULATOR_des"></a>
Call **RegulatorSetVoltage** to set the output voltage range for a regulator.
The regulator module controls the voltage and current supplies of some devices in the system. In the Hardware Driver Foundation (HDF), the regulator module uses the unified service mode for API adaptation. In this mode, a device service is used as the regulator manager to handle external access requests in a unified manner, which is reflected in the configuration file. The unified service mode applies to the scenario where there are many device objects of the same type, for example, when the regulator has more than 10 controllers. If the independent service mode is used, more device nodes need to be configured and more memory resources will be consumed by services.
**Figure 1** Unified service mode
![image1](figures/unified-service-mode.png)
## Available APIs<a name="section2_REGULATORDevelop"></a>
| open | **node**: structure pointer to the regulator node at the core layer.|HDF_STATUS|Opens a device.|
| close | **node**: structure pointer to the regulator node at the core layer.| HDF_STATUS| Closes a device.|
| release | **node**: structure pointer to the regulator node at the core layer.| HDF_STATUS| Releases a device handle.|
| enable | **node**: structure pointer to the regulator node at the core layer.| HDF_STATUS| Enables a device.|
| disable | **node**: structure pointer to the regulator node at the core layer.| HDF_STATUS| Disables a device.|
| forceDisable | **node**: structure pointer to the regulator node at the core layer.| HDF_STATUS| Forcibly disables a device.|
| setVoltage | **node**: structure pointer to the regulator node at the core layer.<br>**minUv**: minimum voltage to set. It is a uint32_t variable.<br>**maxUv**: maximum voltage to set. It is a uint32_t variable.| HDF_STATUS| Sets the output voltage range.|
| getVoltage | **node**: structure pointer to the regulator node at the core layer.<br>**voltage**: pointer to the output voltage value.| HDF_STATUS| Obtains the voltage.|
| setCurrent | **node**: structure pointer to the regulator node at the core layer.<br>**minUa**: minimum current to set. It is a uint32_t variable.<br>**maxUa**: maximum current to set. It is a uint32_t variable.| HDF_STATUS| Sets the output current range.|
| getCurrent | **node**: structure pointer to the regulator node at the core layer.<br>**regCurrent**: pointer to the output current, which is of the uint32_t type.| HDF_STATUS| Obtains the current.|
| getStatus | **node**: structure pointer to the regulator node at the core layer.<br>**status**: pointer to the output status, which is of the uint32_t type.| HDF_STATUS| Obtains the device status.|
## How to Develop<a name="section3_REGULATORDevelop"></a>
The regulator module adaptation involves the following steps:
1. Instantiate the driver entry.
- Instantiate the **HdfDriverEntry** structure.
- Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF.
2. Configure attribute files.
- Add the **deviceNode** information to the **device_info.hcs** file.
- (Optional) Add the **regulator_config.hcs** file.
>For details, see [Available APIs](#section2_REGULATORDevelop).
4. Debug the driver.
- (Optional) Verify basic functionalities of new drivers. For example, verify the information returned when the driver is loaded and whether data is successfully transmitted.
## Development Example<a name="section4_REGULATORDevelop"></a>
The following uses **regulator_virtual.c** as an example to present the content to be provided by the vendor to implement device functionalities.
1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type (defined in **hdf\_device\_desc.h**), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers are collected to form a segment address space similar to an array for the upper layer to invoke.
Generally, the HDF calls the **Bind** function and then the **Init** function to load the driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
Regulator driver entry reference:
```c
structHdfDriverEntryg_regulatorDriverEntry={
.moduleVersion=1,
.moduleName="virtual_regulator_driver",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
.Init=VirtualRegulatorInit,
.Release=VirtualRegulatorRelease,
};
// Call HDF_INIT to register the driver entry with the HDF framework.
HDF_INIT(g_regulatorDriverEntry);
```
2. Add **deviceNode** to the **device\_info.hcs** file, and set the device attributes in the **regulator\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **RegulatorNode** members at the core layer.
>If there are multiple devices, add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **regulator\_config** file.
-**device\_info.hcs** reference:
```c
root {
device_info {
platform :: host {
hostName = "platform_host";
priority = 50;
device_regulator :: device {
device0 :: deviceNode { // Configure an HDF device node for each regulator controller.
policy = 1; // 2: visible in user mode; 1: visible in kernel mode; 0: no service required.
priority = 50; // Driver startup priority.
permission = 0644; // Permission to create device nodes of the driver.
/* (Mandatory) Driver name, which must be the same as the moduleName in the driver entry. */
moduleName = "HDF_PLATFORM_REGULATOR_MANAGER";
serviceName = "HDF_PLATFORM_REGULATOR_MANAGER"; // (Mandatory) Unique name of the service published by the driver.
/* (Mandatory) Set the controller private data, which must be same as that in regulator_config.hcs. */
template regulator_controller { // (Mandatory) Template configuration. In the template, you can configure the common parameters shared by device nodes.
device_num = 1;
name = "";
devName = "regulator_adapter_consumer01";
supplyName = "";
mode = 1;
minUv = 0;
maxUv = 20000;
minUa = 0;
maxUa = 0;
}
controller_0x130d0000 :: regulator_controller {
device_num = 1;
name = "regulator_adapter_1";
devName = "regulator_adapter_consumer01";
supplyName = "virtual-regulator-hdf-adapter";
mode = 1;
minUv = 1000;
maxUv = 50000;
minUa = 0;
maxUa = 0;
}
/* Each regulator controller corresponds to a controller node. If there are multiple regulator controllers, add the corresponding controller nodes one by one.*/
controller_0x130d0001 :: regulator_controller {
device_num = 1;
name = "regulator_adapter_2";
devName = "regulator_adapter_consumer01";
supplyName = "virtual2-regulator-hdf-adapter";
mode = 2;
minUv = 0;
maxUv = 0;
minUa = 1000;
maxUa = 50000;
}
}
}
}
```
3. Initialize the **RegulatorNode** object at the core layer, including initializing the vendor custom structure (passing parameters and data), instantiating **RegulatorMethod** (used to call underlying functions of the driver) in **PinCntlr**, and implementing the **HdfDriverEntry** member functions (**Bind**, **Init**, and **Release**).
- Initializing the vendor custom structure
The **RegulatorNode** structure holds parameters and data for the driver. The HDF obtains the values in **regulator\_config.hcs** using **DeviceResourceIface**.
```c
// RegulatorNode is the controller structure at the core layer. Its members are assigned with values by using the Init function.
<tdclass="cellrowborder"valign="top"width="50%"headers="mcps1.1.3.1.2 "><pid="entry361497788164144p0"><aname="entry361497788164144p0"></a><aname="entry361497788164144p0"></a>Failed to allocate memory.</p>
Initializes the custom structure and **RegulatorNode** members, and adds the regulator controller by calling the **RegulatorNodeAdd** function at the core layer.