1# HDMI 2 3 4## 概述 5 6### 功能简介 7 8HDMI(High Definition Multimedia Interface),即高清多媒体接口,是Hitachi、Panasonic、Philips、Silicon Image、Sony、Thomson、Toshiba共同发布的一款音视频传输协议,主要用于DVD、机顶盒等音视频Source设备到TV、显示器等Sink设备的传输。HDMI传输过程遵循TMDS(Transition Minimized Differential Signaling)协议。 9 10### 基本概念 11 12- TMDS(Transition Minimized Differential signal):过渡调制差分信号,也被称为最小化传输差分信号,用于发送音频、视频及各种辅助数据。 13 14- DDC(Display Data Channel):显示数据通道,发送端与接收端可利用DDC通道得知彼此的发送与接收能力,但HDMI仅需单向获知接收端(显示器)的能力。 15 16- CEC(Consumer Electronics Control):消费电子控制,该功能应该能够在连接HDMI的发送设备与接收设备之间实现交互操作。 17 18- FRL(Fixed Rate Link):TMDS的架构进行讯号传输时,最高带宽可达18Gbps,而FRL模式的带宽则提升到48Gbps。 19 20- HDCP(High-bandwidth Digital Content Protection):即高带宽数字内容保护技术,当用户对高清晰信号进行非法复制时,该技术会进行干扰,降低复制出来的影像的质量,从而对内容进行保护。 21 22 23### 运作机制 24 25在HDF框架中,HDMI的接口适配模式采用独立服务模式(如图1)。在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用率。 26 27 **图 1** HDMI独立服务模式 28 29![image1](figures/独立服务模式结构图.png) 30 31### 约束与限制 32 33HDMI模块当前仅支持轻量和小型系统内核(LiteOS) 。 34 35## 开发指导 36 37### 场景介绍 38 39HDMI具有体积小、传输速率高、传输带宽宽、兼容性好、能同时传输无压缩音视频信号等优点。与传统的全模拟接口相比,HDMI不但增加了设备间接线的便捷性,还提供了一些HDMI特有的智能化功能,可用于小体积设备进行高质量音视频传输的场景。 40 41### 接口说明 42 43HdmiCntlrOps定义: 44```c 45struct HdmiCntlrOps { 46 void (*hardWareInit)(struct HdmiCntlr *cntlr); 47 void (*hardWareStatusGet)(struct HdmiCntlr *cntlr, struct HdmiHardwareStatus *status); 48 void (*controllerReset)(struct HdmiCntlr *cntlr); 49 bool (*hotPlugStateGet)(struct HdmiCntlr *cntlr); 50 bool (*hotPlugInterruptStateGet)(struct HdmiCntlr *cntlr); 51 void (*lowPowerSet)(struct HdmiCntlr *cntlr, bool enable); 52 void (*tmdsModeSet)(struct HdmiCntlr *cntlr, enum HdmiTmdsModeType mode); 53 int32_t (*tmdsConfigSet)(struct HdmiCntlr *cntlr, struct HdmiTmdsConfig mode); 54 void (*infoFrameEnable)(struct HdmiCntlr *cntlr, enum HdmiPacketType infoFrameType, bool enable); 55 int32_t (*infoFrameSend)(struct HdmiCntlr *cntlr, enum HdmiPacketType infoFrameType, uint8_t *data, uint32_t len); 56 int32_t (*infoFrameDataSet)(struct HdmiCntlr *cntlr, uint32_t type, uint8_t *data, uint32_t len); 57 int32_t (*cecMsgSend)(struct HdmiCntlr *cntlr, struct HdmiCecMsg *msg); 58 void (*audioPathEnable)(struct HdmiCntlr *cntlr, bool enable); 59 void (*audioPathSet)(struct HdmiCntlr *cntlr, struct HdmiAudioConfigInfo *config); 60 void (*phyOutputEnable)(struct HdmiCntlr *cntlr, bool enable); 61 void (*phyOutputSet)(struct HdmiCntlr *cntlr, struct HdmiPhyCfg *cfg); 62 void (*blackDataSet)(struct HdmiCntlr *cntlr, bool enable); 63 void (*videoMuteEnable)(struct HdmiCntlr *cntlr, bool enable); 64 void (*videoPathSet)(struct HdmiCntlr *cntlr, struct HdmiVideoAttr *attr); 65 void (*audioMuteEnable)(struct HdmiCntlr *cntlr, bool enable); 66 void (*avmuteSet)(struct HdmiCntlr *cntlr, bool enable); 67 int32_t (*ddcTransfer)(struct HdmiCntlr *cntlr, struct HdmiDdcCfg *ddcCfg); 68 bool (*scdcSourceScrambleGet)(struct HdmiCntlr *cntlr); 69 int32_t (*scdcSourceScrambleSet)(struct HdmiCntlr *cntlr, bool enable); 70 void (*frlSet)(struct HdmiCntlr *cntlr); 71 int32_t (*frlEnable)(struct HdmiCntlr *cntlr, bool enable); 72 int32_t (*audioNctsSet)(struct HdmiCntlr *cntlr, struct HdmiFrlAudioNctsConfig *cfg); 73 void (*frlTrainingConfigSet)(struct HdmiCntlr *cntlr, struct HdmiFrlTrainConfig *cfg); 74 void (*frlTrainingStart)(struct HdmiCntlr *cntlr); 75 void (*frlGetTriningRslt)(struct HdmiCntlr *cntlr, struct HdmiFrlTrainRslt *rslt); 76 void (*hdcpRegInit)(struct HdmiCntlr *cntlr); 77 int32_t (*hdcpGenerateAksvAndAn)(struct HdmiCntlr *cntlr); 78 int32_t (*hdcpOptReg)(struct HdmiCntlr *cntlr, enum HdmiHdcpRegOptType type, uint8_t *data, uint32_t len); 79 void (*hdrTimerSet)(struct HdmiCntlr *cntlr, struct HdmiHdrTimerConfig *config); 80}; 81``` 82 83**表1** HdmiCntlrOps结构体成员的回调函数功能说明 84 85| 函数成员 | 入参 | 出参 | 返回值 | 功能 | 86| ------------------------ | ------------------------------------------------------------ | -------------------------------------- | ------------------ | -------------------------------------------------- | 87| hardWareInit | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | 无 | 初始化HDMI硬件 | 88| hardWareStatusGet | **cntlr**:结构体指针,核心层HDMI控制器<br /> | **status**:HDMI硬件状态 ; | 无 | 获取HDMI当前硬件状态 | 89| controllerReset | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | 无 | 复位HDMI控制器 | 90| hotPlugStateGet | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | bool:HDMI热插拔状态 | 获取HDMI热插拔状态 | 91| hotPlugInterruptStateGet | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | bool:HDMI热插拔中断状态 | 获取HDMI热插拔中断状态 | 92| lowPowerSet | **cntlr**:结构体指针,核心层HDMI控制器<br />**enable**:bool,使能/去使能 | 无 | 无 | 使能/去使能低功耗 | 93| tmdsModeSet | **cntlr**:结构体指针,核心层HDMI控制器<br />**mode**:TMDS模式 | 无 | 无 | 设置TMDS模式 | 94| tmdsConfigSet | **cntlr**:结构体指针,核心层HDMI控制器<br />**mode**:TMDS参数 | 无 | HDF_STATUS相关状态 | 配置TMDS参数 | 95| infoFrameEnable | **cntlr**:结构体指针,核心层HDMI控制器<br />**infoFrameType**:packet类型<br />**enable**:bool,使能/去使能 | 无 | 无 | 使能/去使能infoFrame | 96| infoFrameSend | **cntlr**:结构体指针,核心层HDMI控制器<br />**infoFrameType**:packet类型<br />**data**:infoFrame数据<br />**len**:数据长度 | 无 | HDF_STATUS相关状态 | 发送infoFrame | 97| cecMsgSend | **cntlr**:结构体指针,核心层HDMI控制器<br />**msg**:CEC消息 | 无 | HDF_STATUS相关状态 | 发送CEC消息 | 98| audioPathEnable | **cntlr**:结构体指针,核心层HDMI控制器<br />**enable**:bool,使能/去使能| 无 | 无 | 使能/去使能audio通路 | 99| audioPathSet | **cntlr**:结构体指针,核心层HDMI控制器<br />**config**:配置信息 | 无 | 无 | 设置audio通路配置信息 | 100| phyOutputEnable | **cntlr**:结构体指针,核心层HDMI控制器<br />**enable**:bool,使能/去使能 | 无 | 无 | 使能/去使能物理层输出状态 | 101| phyOutputSet | **cntlr**:结构体指针,核心层HDMI控制器<br />**cfg**:配置信息 | 无 | 无 | 设置物理层配置信息 | 102| blackDataSet | **cntlr**:结构体指针,核心层HDMI控制器<br />**enable**:bool,使能/去使能 | 无 | 无 | 设置黑屏 | 103| videoMuteEnable | **cntlr**:结构体指针,核心层HDMI控制器<br />**enable**:bool,使能/去使能 | 无 | 无 | 使能/去使能video静音 | 104| videoPathSet | **cntlr**:结构体指针,核心层HDMI控制器<br />**attr**:配置信息| 无 | 无 | 设置video通路配置信息 | 105|audioMuteEnable | **cntlr**:结构体指针,核心层HDMI控制器<br />**enable**:bool,使能/去使能 | 无 | 无 | 使能/去使能audio静音 | 106| avmuteSet | **cntlr**:结构体指针,核心层HDMI控制器<br />**enable**:bool,使能/去使能| 无 | 无 | 使能/去使能声音图像消隐 | 107| ddcTransfer | **cntlr**:结构体指针,核心层HDMI控制器<br />**ddcCfg**:DDC配置参数 |**ddcCfg**:DDC配置参数 |HDF_STATUS相关状态 | 读写DDC数据 | 108| scdcSourceScrambleGet | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | bool,加扰状态 | 获取source端的加扰状态 | 109| scdcSourceScrambleSet | **cntlr**:结构体指针,核心层HDMI控制器<br />**enable**:bool,使能/去使能 | 无 | HDF_STATUS相关状态 | 使能/去使能source端的加扰 | 110| frlEnable | **cntlr**:结构体指针,核心层HDMI控制器<br />**enable**:bool,使能/去使能 | 无 | HDF_STATUS相关状态 | 使能/去使能FRL | 111| audioNctsSet | **cntlr**:结构体指针,核心层HDMI控制器<br />**cfg**:N/CTS配置参数 | 无 | HDF_STATUS相关状态 | 设置audio的N/CTS信息 | 112| frlTrainingConfigSet | **cntlr**:结构体指针,核心层HDMI控制器<br />**cfg**:FRL Training配置参数 | 无 | 无| 设置FRL Training配置信息 | 113| frlTrainingStart | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | 无 | 开始FRL Training流程 | 114| frlGetTriningRslt | **cntlr**:结构体指针,核心层HDMI控制器 | **rslt**:FRL Training结果 | 无 | 获取FRL Training结果 | 115| hdcpRegInit | **cntlr**:结构体指针,核心层HDMI控制器 | 无 | 无 | 初始化HDCP流程相关的寄存器 | 116|hdcpGenerateAksvAndAn |**cntlr**:结构体指针,核心层HDMI控制器 | 无 | HDF_STATUS相关状态 | HDCP流程中生成aksv和an | 117| hdcpOptReg | **cntlr**:结构体指针,核心层HDMI控制器<br />**type**:操作类型<br />**data**:寄存器数据<br />**len**:数据长度 | **data**:寄存器数据 | HDF_STATUS相关状态 | HDCP流程中读写相关寄存器 | 118| hdrTimerSet | **cntlr**:结构体指针,核心层HDMI控制器<br />**config**:timer配置信息 | 无 | 无 | 设置HDR相关的timer配置信息 | 119 120 121### 开发步骤 122 123HDMI模块适配的三个环节是实例化驱动入口、配置属性文件以及实例化HDMI控制器对象。 124 125- 实例化驱动入口: 126 - 实例化HdfDriverEntry结构体成员。 127 - 调用HDF_INIT将HdfDriverEntry实例化对象注册到HDF框架中。 128 129- 配置属性文件: 130 - 在device_info.hcs文件中添加deviceNode描述。 131 - 【可选】添加hdmi_config.hcs器件属性文件。 132 133- 实例化HDMI控制器对象: 134 - 初始化HdmiCntlr成员。 135 - 实例化HdmiCntlr成员HdmiCntlrOps方法集合。 136 1371. 实例化驱动入口 138 139 驱动入口必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。 140 141 一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 142 143 HDMI驱动入口参考: 144 145 ```c 146 struct HdfDriverEntry g_hdmiDriverEntry = { 147 .moduleVersion = 1, 148 .Bind = HdmiAdapterBind, 149 .Init = HdmiAdapterInit, 150 .Release = HdmiAdapterRelease, 151 .moduleName = "adapter_hdmi_driver",//【必要】与HCS里面的名字匹配 152 }; 153 HDF_INIT(g_hdmiDriverEntry); // 调用HDF_INIT将驱动入口注册到HDF框架中 154 ``` 155 1562. 配置属性文件 157 158 完成驱动入口注册之后,下一步请在device_info.hcs文件中添加deviceNode信息,并在hdmi_config.hcs中配置器件属性。deviceNode信息与驱动入口注册相关,器件属性值对于厂商驱动的实现以及核心层HdmiCntlr相关成员的默认值或限制范围有密切关系。 159 160 从第一个节点开始配置具体HDMI控制器信息,此节点并不表示某一路HDMI控制器,而是代表一个资源性质设备,用于描述一类HDMI控制器的信息。本例只有一个HDMI控制器,如有多个控制器,则需要在device_info文件增加deviceNode信息,以及在hdmi_config文件中增加对应的器件属性。 161 162 - device_info.hcs配置参考 163 164 ```c 165 root { 166 platform :: host { 167 device_hdmi :: device { 168 device0 :: deviceNode { 169 policy = 2; // 等于2,需要发布服务。 170 priority = 20; // 驱动启动优先级。 171 permission = 0644; // 驱动创建设备节点权限。 172 serviceName = "HDF_PLATFORM_HDMI_0"; //【必要】驱动对外发布服务的名称,必须唯一。 173 moduleName = "hdmi_driver"; //【必要】用于指定驱动名称,需要与期望的驱动Entry中的moduleName一致。 174 deviceMatchAttr = "adapter_hdmi_driver"; //【必要】用于配置控制器私有数据,要与hdmi_config.hcs中对应控制器保持一致。 175 } // 具体的控制器信息在hdmi_config.hcs中。 176 } 177 } 178 } 179 ``` 180 181 - hdmi_config.hcs 配置参考 182 183 ```c 184 root { 185 platform { 186 hdmi_config { 187 template hdmi_controller { // 模板公共参数,继承该模板的节点如果使用模板中的默认值,则节点字段可以缺省。 188 match_attr = ""; //【必要】需要和device_info.hcs中的deviceMatchAttr值一致。 189 index = 0; //【必要】hdmi控制器编号 190 regBasePhy = 0x10100000; //【必要】寄存器物理基地址 191 regSize = 0xd1; //【必要】寄存器位宽 192 irqNum = 100; //【必要】中断号 193 maxTmdsClock = 300; 194 videoTiming = 10; 195 quantization = 1; 196 colorSpace = 0; 197 colorimetry = 0; 198 audioIfType = 0; 199 audioBitDepth = 1; 200 audioSampleRate = 2; 201 audioChannels = 1; 202 hdrColorimetry = 4; 203 hdrUserMode = 1; 204 cap = 0xd001e045; 205 } 206 controller_0x10100000 :: hdmi_controller { 207 match_attr = "adapter_hdmi_driver"; 208 index = 0; 209 regBasePhy = 0x10100000; 210 irqNum = 100; 211 maxTmdsClock = 400; 212 defTmdsClock = 300; 213 maxFrlRate = 600; 214 videoTiming = 10; 215 quantization = 1; 216 colorSpace = 0; 217 colorimetry = 0; 218 audioIfType = 0; 219 audioSampleRate = 2; 220 audioChannels = 1; 221 hdrColorimetry = 4; 222 hdrUserMode = 1; 223 cap = 0xd001e045; 224 } 225 } 226 } 227 } 228 ``` 229 2303. 实例化控制器对象 231 232 最后一步,完成驱动入口注册之后,要以核心层HdmiCntlr对象的初始化为核心,包括厂商自定义结构体(传递参数和数据),实例化HdmiCntlr成员HdmiCntlrOps(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。 233 234 - 自定义结构体参考 235 236 > ![](../public_sys-resources/icon-note.gif) **说明:**<br> 237 > 从驱动角度看,自定义结构体是参数和数据的载体。HDF会读取hdmi_config.hcs文件中的数值并通过DeviceResourceIface来初始化结构体成员,且其中一些重要数值(例如设备号、总线号等)也会被传递给核心层HdmiCntlr对象。 238 239 ```c 240 struct HdmiAdapterHost { 241 struct HdmiCntlr *cntlr; //【必要】是核心层控制对象,具体描述如下。 242 volatile unsigned char *regBase;//【必要】寄存器基地址 243 uint32_t regBasePhy; //【必要】寄存器物理基地址 244 uint32_t regSize; //【必要】寄存器位宽 245 uint32_t irqNum; //【必要】中断号 246 }; 247 248 /* HdmiCntlr是核心层控制器结构体,其中的成员在Init函数中被赋值。 */ 249 struct HdmiCntlr { 250 struct IDeviceIoService service; 251 struct HdfDeviceObject *hdfDevObj; 252 struct PlatformDevice device; 253 struct OsalMutex mutex; 254 struct PlatformQueue *msgQueue; 255 struct HdmiCntlrCap cap; 256 struct HdmiAttr attr; 257 struct HdmiCntlrOps *ops; 258 uint32_t deviceIndex; 259 uint32_t state; // 控制器状态 260 enum HdmiTmdsModeType tmdsMode; 261 struct HdmiDevice *hdmi; 262 struct HdmiInfoframe infoframe; 263 struct HdmiScdc *scdc; 264 struct HdmiDdc ddc; 265 struct HdmiFrl *frl; 266 struct HdmiHdcp *hdcp; 267 struct HdmiCec *cec; 268 struct HdmiEvent event; 269 struct HdmiHdr *hdr; 270 void *priv; 271 }; 272 ``` 273 274 - HdmiCntlr成员回调函数结构体HdmiCntlrOps的实例化 275 276 ```c 277 static struct HdmiCntlrOps g_hdmiAdapterHostOps = { 278 .hardWareInit = HdmiAdapterHardWareInit, 279 .hardWareStatusGet = HdmiAdapterHardWareStatusGet, 280 .controllerReset = HdmiAdapterControllerReset, 281 .hotPlugStateGet = HdmiAdapterHotPlugStateGet, 282 .hotPlugInterruptStateGet = HdmiAdapterHotPlugInterruptStateGet, 283 .lowPowerSet = HdmiAdapterLowPowerSet, 284 .tmdsModeSet = HdmiAdapterTmdsModeSet, 285 .tmdsConfigSet = HdmiAdapterTmdsConfigSet, 286 .infoframeEnable = HdmiAdapterInfoframeEnable, 287 .infoframeSend = HdmiAdapterInfoframeSend, 288 .infoframeDataSet = HdmiAdapterInfoframeDataSet, 289 .cecMsgSend = HdmiAdapterCecMsgSend, 290 .audioPathEnable = HdmiAdapterAudioPathEnable, 291 .audioPathSet = HdmiAdapterAudioPathSet, 292 .phyOutputEnable = HdmiAdapterPhyOutputEnable, 293 .phyOutputSet = HdmiAdapterPhyOutputSet, 294 .blackDataSet = HdmiAdapterBlackDataSet, 295 .videoMuteEnable = HdmiAdapterVideoMuteEnable, 296 .videoPathSet = HdmiAdapterVideoPathSet, 297 .audioMuteEnable = HdmiAdapterAudioMuteEnable, 298 .avmuteSet = HdmiAdapterAvmuteSet, 299 .ddcTransfer = HdmiAdapterDdcTransfer, 300 .scdcSourceScrambleGet = HdmiAdapterScdcSourceScrambleGet, 301 .scdcSourceScrambleSet = HdmiAdapterScdcSourceScrambleSet, 302 .frlSet = HdmiAdapterFrlSet, 303 .frlEnable = HdmiAdapterFrlEnable, 304 .audioNctsSet = HdmiAdapterAudioNctsSet, 305 .frlTrainingConfigSet = HdmiAdapterFrlTrainingConfigSet, 306 .frlTrainingStart = HdmiAdapterFrlTrainingStart, 307 .frlGetTriningRslt = HdmiAdapterFrlGetTriningRslt, 308 .hdcpRegInit = HdmiAdapterHdcpRegInit, 309 .hdcpGenerateAksvAndAn = HdmiAdapterHdcpGenerateAksvAndAn, 310 .hdcpOptReg = HdmiAdapterHdcpOptReg, 311 .hdrTimerSet = HdmiAdapterHdrTimerSet, 312 }; 313 ``` 314 315 - Bind函数参考 316 317 **入参:** 318 319 HdfDeviceObject是整个驱动对外呈现的接口参数,具备HCS配置文件的信息。 320 321 **返回值:** 322 323 HDF_STATUS相关状态(下表为部分展示,如需使用其他状态,可见//drivers/framework/include/utils/hdf_base.h中HDF_STATUS 定义) 324 325 |状态(值)|状态描述| 326 |:-|:-| 327 |HDF_ERR_INVALID_OBJECT|控制器对象非法| 328 |HDF_ERR_INVALID_PARAM |参数非法| 329 |HDF_ERR_MALLOC_FAIL |内存分配失败| 330 |HDF_ERR_IO |I/O错误| 331 |HDF_SUCCESS |传输成功| 332 |HDF_FAILURE |传输失败| 333 334 **函数说明:** 335 336 初始化自定义结构体对象HdmiAdapterHost,初始化HdmiCntlr成员,调用核心层HdmiCntlrAdd函数。 337 338 HdmiCntlr,HdmiAdapterHost,HdfDeviceObject之间互相赋值,方便其他函数可以相互转化。 339 340 ```c 341 static int32_t HdmiAdapterBind(struct HdfDeviceObject *obj) 342 { 343 struct HdmiCntlr *cntlr = NULL; 344 struct HimciAdapterHost *host = NULL; 345 int32_t ret; 346 cntlr = (struct HdmiCntlr *)OsalMemCalloc(sizeof(struct HdmiCntlr)); 347 if (cntlr == NULL) { 348 HDF_LOGE("%s: malloc cntlr failed!", __func__); 349 return HDF_ERR_MALLOC_FAIL; 350 } 351 host = (struct HimciAdapterHost *)OsalMemCalloc(sizeof(struct HimciAdapterHost)); 352 if (host == NULL) { 353 HDF_LOGE("%s: malloc host failed!", __func__); 354 return HDF_ERR_MALLOC_FAIL; 355 } 356 cntlr->priv = (void *)host; //【必要】将host存放至cntlr的私有数据 357 cntlr->ops = &g_hdmiHostOps; //【必要】HdmiCntlrOps的实例化对象的挂载 358 cntlr->hdfDevObj = obj; //【必要】使HdfDeviceObject与HdmiCntlr可以相互转化的前提 359 obj->service = &cntlr->service; //【必要】使HdfDeviceObject与HdmiCntlr可以相互转化的前提 360 ret = HdmiAdapterCntlrParse(cntlr, obj); //【必要】初始化cntlr,失败则goto __ERR。 361 ... 362 ret = HdmiAdapterHostParse(host, obj); //【必要】初始化host对象的相关属性,失败则goto __ERR。 363 ... 364 ret = HdmiAdapterHostInit(host, cntlr); // 厂商自定义的初始化,失败则goto __ERR。 365 ... 366 ret = HdmiCntlrAdd(cntlr); // 调用核心层函数,失败则goto __ERR。 367 ... 368 HDF_LOGD("HdmiAdapterBind: success."); 369 return HDF_SUCCESS; 370 __ERR: 371 HdmiAdapterDeleteHost(host); 372 HDF_LOGD("HdmiAdapterBind: fail, err = %d.", ret); 373 return ret; 374 } 375 ``` 376 377 - Init函数参考 378 379 **入参:** 380 381 HdfDeviceObject是整个驱动对外暴露的接口参数,具备HCS配置文件的信息。 382 383 **返回值:** 384 385 HDF_STATUS相关状态。 386 387 **函数说明**: 388 389 实现HdmiAdapterInit函数。 390 391 ```c 392 static int32_t HdmiAdapterInit(struct HdfDeviceObject *obj) 393 { 394 return HDF_SUCCESS; 395 } 396 ``` 397 398 - Release函数参考 399 400 **入参:** 401 402 HdfDeviceObject是整个驱动对外暴露的接口参数,具备HCS配置文件的信息。 403 404 **返回值:** 405 406 无 407 408 **函数说明:** 409 410 释放内存和删除控制器,该函数需要在驱动入口结构体中赋值给Release接口,当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源。 411 412 > ![](../public_sys-resources/icon-note.gif) **说明:**<br> 413 > 所有强制转换获取相应对象的操作前提是在Init函数中具备对应赋值的操作。 414 415 ```c 416 static void HdmiAdapterRelease(struct HdfDeviceObject *obj) 417 { 418 struct HdmiCntlr *cntlr = NULL; 419 ... 420 cntlr = (struct HdmiCntlr *)obj->service; // 这里有HdfDeviceObject到HdmiCntlr的强制转化,通过service成员,赋值见Bind函数。 421 ... 422 HimciDeleteHost((struct HimciAdapterHost *)cntlr->priv);// 厂商自定义的内存释放函数,这里有HdmiCntlr到HimciAdapterHost的强制转化。 423 } 424 ``` 425 426 427