1# MIPI CSI 2 3## 概述 4 5### 功能简介 6 7CSI(Camera Serial Interface)是由MIPI联盟下Camera工作组指定的接口标准。CSI-2是MIPI CSI第二版,主要由应用层、协议层、物理层组成,最大支持4通道数据传输、单线传输速度高达1Gb/s。 8 9物理层支持HS(High Speed)和LP(Low Speed)两种工作模式。HS模式下采用低压差分信号,功耗较大,但数据传输速率可以很高(数据速率为80M~1Gbps);LP模式下采用单端信号,数据速率很低(<10Mbps),但是相应的功耗也很低。两种模式的结合保证了MIPI总线在需要传输大量数据(如图像)时可以高速传输,而在不需要传输大数据量时又能够减少功耗。 10 11图1显示了简化的CSI接口。D-PHY采用1对源同步的差分时钟和1~4对差分数据线来进行数据传输。数据传输采用DDR方式,即在时钟的上下边沿都有数据传输。 12 13**图 1** CSI发送、接收接口<a name="fig1_MIPI_CSIDes"></a> 14 15 16 17MIPI CSI标准分为应用层、协议层与物理层,协议层又细分为像素字节转换层、低级协议层、Lane管理层。 18 19- 物理层(PHY Layer) 20 21 PHY层指定了传输媒介,在电气层面从串行bit流中捕捉“0”与“1”,同时生成SoT与EoT等信号。 22 23- 协议层(Protocol Layer) 24 25 协议层由三个子层组成,每个子层有不同的职责。CSI-2协议能够在host侧处理器上用一个单独的接口处理多条数据流。协议层规定了多条数据流该如何标记和交织起来,以便每条数据流能够被正确地恢复出来。 26 27 - 像素字节转换层(Pixel/Byte Packing/Unpacking Layer) 28 29 CSI-2规范支持多种不同像素格式的图像应用。在发送方中,本层在发送数据到Low Level Protocol层之前,将来自应用层的像素封包为字节数据。在接收方中,本层在发送数据到应用层之前,将来自Low Level Protocol层的字节数据解包为像素。8位的像素数据在本层中传输时保持不变。 30 31 - 低级协议层(Low Level Protocol) 32 LLP主要包含了在SoT和EoT事件之间的bit和byte级别的同步方法,以及和下一层传递数据的方法。LLP最小数据粒度是1个字节。LLP也包含了一个字节内的bit值解析,即Endian(大小端里的Endian的意思)的处理。 33 34 - Lane管理层(Lane Management) 35 36 CSI-2的Lane是可扩展的。具体的数据Lane的数量规范并没有给出限制,具体根据应用的带宽需求而定。发送侧分发(distributor功能)来自出口方向数据流的字节到1条或多条Lane上。接收侧则从一条或多条Lane中收集字节并合并(merge功能)到一个数据流上,复原出原始流的字节顺序。对于C-PHY物理层来说,本层专门分发字节对(16 bits)到数据Lane或从数据Lane中收集字节对。基于每Lane的扰码功能是可选特性。 37 38 协议层的数据组织形式是包(packet)。接口的发送侧会增加包头(header)和错误校验(error-checking)信息到即将被LLP发送的数据上。接收侧在LLP将包头剥掉,包头会被接收器中对应的逻辑所解析。错误校验信息可以用来做入口数据的完整性检查。 39 40- 应用层(Application Layer) 41 42 本层描述了更高层级的应用对于数据中的数据的处理,规范并不涵盖应用层。CSI-2规范只给出了像素值和字节的映射关系。 43 44### 运作机制 45 46MIPI CSI模块各分层的作用为:接口层提供打开设备、写入数据和关闭设备的接口。核心层主要提供绑定设备、初始化设备以及释放设备的能力。适配层实现其它具体的功能。 47 48 **说明:**<br>核心层可以调用接口层的函数,核心层通过钩子函数调用适配层函数,从而适配层可以间接的调用接口层函数,但是不可逆转接口层调用适配层函数。 49 50**图 2** CSI无服务模式结构图 51 52 53 54### 约束与限制 55 56由于使用无服务模式,MIPI_CSI接口暂不支持用户态使用。 57 58## 使用指导 59 60### 场景介绍 61 62MIPI CSI主要用于连接摄像头组件。 63 64### 接口说明 65 66MIPI CSI模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/framework/include/platform/mipi_csi_if.h。 67 68**表 1** ComboDevAttr结构体介绍 69 70<a name="table1_MIPI_CSIDes"></a> 71 72| 名称 | 描述 | 73| --------- | ----------------------------------------------------- | 74| devno | 设备号 | 75| inputMode | 输入模式:MIPI/LVDS/SUBSLVDS/HISPI/DC | 76| dataRate | Mipi Rx,SLVS输入速率 | 77| imgRect | MIPI Rx设备裁剪区域(与原始传感器输入图像大小相对应) | 78| MIPIAttr | Mipi设备属性 | 79| lvdsAttr | LVDS/SubLVDS/HiSPi设备属性 | 80 81**表 2** ExtDataType结构体介绍 82 83<a name="table2_MIPI_CSIDes"></a> 84 85| 名称 | 描述 | 86| --------------- | ------------------------------- | 87| devno | 设备号 | 88| num | Sensor号 | 89| extDataBitWidth | 图片的位深 | 90| extDataType | 定义YUV和原始数据格式以及位深度 | 91 92**表 3** MIPI CSI API接口功能介绍 93 94<a name="table3_MIPI_CSIDes"></a> 95 96| 接口名 | 接口描述 | 97| -------- | -------- | 98| DevHandle MipiCsiOpen(uint8_t id) | 获取MIPI_CSI控制器操作句柄 | 99| void MipiCsiClose(DevHandle handle) | 释放MIPI_CSI控制器操作句柄 | 100| int32_t MipiCsiSetComboDevAttr(DevHandle handle, ComboDevAttr \*pAttr) | 设置MIPI,CMOS或者LVDS相机的参数给控制器,参数包括工作模式,图像区域,图像深度,数据速率和物理通道等 | 101| int32_t MipiCsiSetExtDataType(DevHandle handle, ExtDataType \*dataType) | 设置YUV和RAW数据格式和位深(可选) | 102| int32_t MipiCsiSetHsMode(DevHandle handle, LaneDivideMode laneDivideMode) | 设置MIPI RX的Lane分布。根据硬件连接的形式选择具体的mode | 103| int32_t MipiCsiSetPhyCmvmode(DevHandle handle, uint8_t devno, PhyCmvMode cmvMode) | 设置共模电压模式 | 104| int32_t MipiCsiResetSensor(DevHandle handle, uint8_t snsResetSource) | 复位Sensor | 105| int32_t MipiCsiUnresetSensor(DevHandle handle, uint8_t snsResetSource) | 撤销复位Sensor | 106| int32_t MipiCsiResetRx(DevHandle handle, uint8_t comboDev) | 复位MIPI RX。不同的s32WorkingViNum有不同的enSnsType | 107| int32_t MipiCsiUnresetRx(DevHandle handle, uint8_t comboDev) | 撤销复位MIPI RX | 108| int32_t MipiCsiEnableClock(DevHandle handle, uint8_t comboDev) | 使能MIPI的时钟。根据上层函数电泳传递的enSnsType参数决定是用MIPI还是LVDS | 109| int32_t MipiCsiDisableClock(DevHandle handle, uint8_t comboDev) | 关闭MIPI设备的时钟 | 110| int32_t MipiCsiEnableSensorClock(DevHandle handle, uint8_t snsClkSource) | 使能MIPI上的Sensor时钟 | 111| int32_t MipiCsiDisableSensorClock(DevHandle handle, uint8_t snsClkSource) | 关闭Sensor的时钟 | 112 113## 开发步骤 114 115#### 使用流程 116 117使用MIPI CSI的一般流程如图3所示。 118 119**图 3** MIPI CSI使用流程图 120 121 122 123#### 获取MIPI CSI控制器操作句柄 124 125在进行MIPI CSI进行通信前,首先要调用MipiCsiOpen获取控制器操作句柄,该函数会返回指定通道ID的控制器操作句柄。 126 127```c 128DevHandle MipiCsiOpen(uint8_t id); 129``` 130 131**表 4** MipiCsiOpen的参数和返回值描述 132 133| 参数 | 参数描述 | 134| ---------- | ----------------------------------------------- | 135| id | uint8_t类型,MIPI CSI通道ID | 136| **返回值** | **返回值描述** | 137| NULL | 获取失败 | 138| 设备句柄 | 获取到指令通道的控制器操作句柄,类型为DevHandle | 139 140假设系统中的MIPI CSI通道为0,获取该通道控制器操作句柄的示例如下: 141 142```c 143DevHandle MipiCsiHandle = NULL; // 设备句柄 144id = 0; // MIPI CSI通道ID 145 146// 获取控制器操作句柄 147MipiCsiHandle = MipiCsiOpen(id); 148if (MipiCsiHandle == NULL) { 149 HDF_LOGE("MipiCsiOpen: mipi csi open fail.\n"); 150 return NULL; 151} 152``` 153 154#### 进行MIPI CSI相应配置 155 156- 写入MIPI CSI配置 157 158 ```c 159 int32_t MipiCsiSetComboDevAttr(DevHandle handle, ComboDevAttr *pAttr); 160 ``` 161 162 **表 5** MipiCsiSetComboDevAttr的参数和返回值描述 163 164 <a name="table5_MIPI_CSIDes"></a> 165 166 | 参数 | 参数描述 | 167 | ---------- | -------------------------- | 168 | handle | DevHandle类型,控制器操作句柄 | 169 | pAttr | 结构体指针,MIPI CSI相应配置 | 170 | **返回值** | **返回值描述** | 171 | HDF_SUCCESS | 设置成功 | 172 | 负数 | 设置失败 | 173 174 ```c 175 int32_t ret; 176 struct ComboDevAttr attr; 177 178 // 当前配置如下 179 (void)memset_s(&attr, sizeof(ComboDevAttr), 0, sizeof(ComboDevAttr)); 180 attr.devno = 0; // 设备0 181 attr.inputMode = INPUT_MODE_MIPI; // 输入模式为MIPI 182 attr.dataRate = MIPI_DATA_RATE_X1; // 每时钟输出1像素 183 attr.imgRect.x = 0; // 0: 图像传感器左上位置 184 attr.imgRect.y = 0; // 0: 图像传感器右上位置 185 attr.imgRect.width = 2592; // 2592: 图像传感器宽度大小 186 attr.imgRect.height = 1944; // 1944: 图像传感器高度尺寸 187 // 写入配置数据 188 ret = MipiCsiSetComboDevAttr(MipiCsiHandle, &attr); 189 if (ret != HDF_SUCCESS) { 190 HDF_LOGE("MipiCsiSetComboDevAttr: mipi csi set combo dev attr fail, ret=%d\n", ret); 191 return ret; 192 } 193 ``` 194 195- 设置YUV和RAW数据格式和位深 196 197 ```c 198 int32_t MipiCsiSetExtDataType(DevHandle handle, ExtDataType* dataType); 199 ``` 200 201 **表 6** MipiCsiSetExtDataType的参数和返回值描述 202 203 <a name="table6_MIPI_CSIDes"></a> 204 205 | 参数 | 参数描述 | 206 | ---------- | ------------------------------- | 207 | handle | DevHandle类型,控制器操作句柄 | 208 | dataType | 结构体指针,定义YUV和原始数据格式以及位深度 | 209 | **返回值** | **返回值描述** | 210 | HDF_SUCCESS | 设置成功 | 211 | 负数 | 设置失败 | 212 213 ```c 214 int32_t ret; 215 struct ExtDataType dataType; 216 217 // 配置YUV和RAW数据格式和位深参数 218 dataType.devno = 0; // 设备0 219 dataType.num = 0; // Sensor 0 220 dataType.extDataBitWidth[0] = 12; // 位深数组元素0 221 dataType.extDataBitWidth[1] = 12; // 位深数组元素1 222 dataType.extDataBitWidth[2] = 12; // 位深数组元素2 223 224 dataType.extDataType[0] = 0x39; // 定义YUV和原始数据格式以及位深度元素0 225 dataType.extDataType[1] = 0x39; // 定义YUV和原始数据格式以及位深度元素1 226 dataType.extDataType[2] = 0x39; // 定义YUV和原始数据格式以及位深度元素2 227 // 设置YUV和RAW数据格式和位深 228 ret = MipiCsiSetExtDataType(MipiCsiHandle, &dataType); 229 if (ret != HDF_SUCCESS) { 230 HDF_LOGE("MipiCsiSetExtDataType: mipi csi set ext data type fail, ret=%d\n", ret); 231 return ret; 232 } 233 ``` 234 235- 设置MIPI RX的Lane分布 236 237 ```c 238 int32_t MipiCsiSetHsMode(DevHandle handle, LaneDivideMode laneDivideMode); 239 ``` 240 241 **表 7** MipiCsiSetHsMode的参数和返回值描述 242 243 | 参数 | 参数描述 | 244 | -------------- | -------------- | 245 | handle | DevHandle类型,控制器操作句柄 | 246 | laneDivideMode | 结构体类型,Lane模式参数 | 247 | **返回值** | **返回值描述** | 248 | HDF_SUCCESS | 设置成功 | 249 | 负数 | 设置失败 | 250 251 ```c 252 int32_t ret; 253 enum LaneDivideMode mode; 254 255 // Lane模式参数为0 256 mode = LANE_DIVIDE_MODE_0; 257 // 设置MIPI RX的 Lane分布 258 ret = MipiCsiSetHsMode(MipiCsiHandle, mode); 259 if (ret != HDF_SUCCESS) { 260 HDF_LOGE("MipiCsiSetHsMode: mipi csi set hs mode fail, ret=%d\n", ret); 261 return ret; 262 } 263 ``` 264 265- 设置共模电压模式 266 267 ```c 268 int32_t MipiCsiSetPhyCmvmode(DevHandle handle, uint8_t devno, PhyCmvMode cmvMode); 269 ``` 270 271 **表 8** MipiCsiSetPhyCmvmode的参数和返回值描述 272 273 | 参数 | 参数描述 | 274 | ---------- | ---------------- | 275 | handle | DevHandle类型,控制器操作句柄 | 276 | cmvMode | 结构体类型,共模电压模式参数 | 277 | devno | uint8_t类型,设备编号 | 278 | **返回值** | **返回值描述** | 279 | HDF_SUCCESS | 设置成功 | 280 | 负数 | 设置失败 | 281 282 ```c 283 int32_t ret; 284 enum PhyCmvMode mode; 285 uint8_t devno; 286 287 // 共模电压模式参数为0 288 mode = PHY_CMV_GE1200MV; 289 // 设备编号为0 290 devno = 0; 291 // 设置共模电压模式 292 ret = MipiCsiSetPhyCmvmode(MipiCsiHandle, devno, mode); 293 if (ret != HDF_SUCCESS) { 294 HDF_LOGE("MipiCsiSetPhyCmvmode: mipi csi set phy cmv mode fail, ret=%d\n", ret); 295 return ret; 296 } 297 ``` 298 299#### 复位/撤销复位Sensor 300 301- 复位Sensor 302 303 ```c 304 int32_t MipiCsiResetSensor(DevHandle handle, uint8_t snsResetSource); 305 ``` 306 307 **表 9** MipiCsiResetSensor的参数和返回值描述 308 309 | 参数 | 参数描述 | 310 | -------------- | ------------------------------------------------ | 311 | handle | DevHandle类型,控制器操作句柄 | 312 | snsResetSource | uint8_t类型,传感器的复位信号线号,在软件中称为传感器的复位源 | 313 | **返回值** | **返回值描述** | 314 | HDF_SUCCESS | 复位成功 | 315 | 负数 | 复位失败 | 316 317 ```c 318 int32_t ret; 319 uint8_t snsResetSource; 320 321 // 传感器复位信号线号为0 322 snsResetSource = 0; 323 // 复位Sensor 324 ret = MipiCsiResetSensor(MipiCsiHandle, snsResetSource); 325 if (ret != HDF_SUCCESS) { 326 HDF_LOGE("MipiCsiResetSensor: mipi csi reset sensor fail, ret=%d\n", ret); 327 return ret; 328 } 329 ``` 330 331- 撤销复位Sensor 332 333 ```c 334 int32_t MipiCsiUnresetSensor(DevHandle handle, uint8_t snsResetSource); 335 ``` 336 337 **表 10** MipiCsiUnresetSensor的参数和返回值描述 338 339 | 参数 | 参数描述 | 340 | -------------- | ------------------------------------------------ | 341 | handle | DevHandle类型,控制器操作句柄 | 342 | snsResetSource | uint8_t类型,传感器的复位信号线号,在软件中称为传感器的复位源 | 343 | **返回值** | **返回值描述** | 344 | HDF_SUCCESS | 撤销复位成功 | 345 | 负数 | 撤销复位失败 | 346 347 ```c 348 int32_t ret; 349 uint8_t snsResetSource; 350 351 // 传感器撤销复位信号线号为0 352 snsResetSource = 0; 353 // 撤销复位Sensor 354 ret = MipiCsiUnresetSensor(MipiCsiHandle, snsResetSource); 355 if (ret != HDF_SUCCESS) { 356 HDF_LOGE("MipiCsiUnresetSensor: mipi csi unreset sensor fail, ret=%d\n", ret); 357 return ret; 358 } 359 ``` 360 361#### 复位/撤销复位MIPI RX 362 363- 复位MIPI RX 364 365 ```c 366 int32_t MipiCsiResetRx(DevHandle handle, uint8_t comboDev); 367 ``` 368 369 **表 11** MipiCsiResetRx的参数和返回值描述 370 371 | 参数 | 参数描述 | 372 | ---------- | --------------------- | 373 | handle | DevHandle类型,控制器操作句柄 | 374 | comboDev | uint8_t类型,MIPI RX或LVDS通路序号 | 375 | **返回值** | **返回值描述** | 376 | HDF_SUCCESS | 复位成功 | 377 | 负数 | 复位失败 | 378 379 ```c 380 int32_t ret; 381 uint8_t comboDev; 382 383 // 通路序号为0 384 comboDev = 0; 385 // 复位MIPI RX 386 ret = MipiCsiResetRx(MipiCsiHandle, comboDev); 387 if (ret != HDF_SUCCESS) { 388 HDF_LOGE("MipiCsiResetRx: mipi csi reset rx fail, ret=%d\n", ret); 389 return ret; 390 } 391 ``` 392 393- 撤销复位MIPI RX 394 395 ```c 396 int32_t MipiCsiUnresetRx(DevHandle handle, uint8_t comboDev); 397 ``` 398 399 **表 12** MipiCsiUnresetRx的参数和返回值描述 400 401 | 参数 | 参数描述 | 402 | ---------- | --------------------- | 403 | handle | DevHandle类型,控制器操作句柄 | 404 | comboDev | uint8_t类型,MIPI RX或LVDS通路序号 | 405 | **返回值** | **返回值描述** | 406 | HDF_SUCCESS | 撤销复位成功 | 407 | 负数 | 撤销复位失败 | 408 409 ```c 410 int32_t ret; 411 uint8_t comboDev; 412 413 // 通路序号为0 414 comboDev = 0; 415 // 撤销复位MIPI RX 416 ret = MipiCsiUnresetRx(MipiCsiHandle, comboDev); 417 if (ret != HDF_SUCCESS) { 418 HDF_LOGE("MipiCsiUnresetRx: mipi csi unreset rx fail, ret=%d\n", ret); 419 return ret; 420 } 421 ``` 422 423#### 使能/关闭MIPI的时钟 424 425- 使能MIPI的时钟 426 427 ```c 428 int32_t MipiCsiEnableClock(DevHandle handle, uint8_t comboDev); 429 ``` 430 431 **表 13** MipiCsiEnableClock的参数和返回值描述 432 433 <a name="table13_MIPI_CSIDes"></a> 434 435 | 参数 | 参数描述 | 436 | ---------- | -------------- | 437 | handle | DevHandle类型,控制器操作句柄 | 438 | comboDev | uint8_t类型,通路序号 | 439 | **返回值** | **返回值描述** | 440 | HDF_SUCCESS | 使能成功 | 441 | 负数 | 使能失败 | 442 443 ```c 444 int32_t ret; 445 uint8_t comboDev; 446 447 // 通路序号为0 448 comboDev = 0; 449 // 使能MIPI的时钟 450 ret = MipiCsiEnableClock(MipiCsiHandle, comboDev); 451 if (ret != HDF_SUCCESS) { 452 HDF_LOGE("MipiCsiEnableClock: mipi csi enable clock fail, ret=%d\n", ret); 453 return ret; 454 } 455 ``` 456 457- 关闭MIPI的时钟 458 459 ```c 460 int32_t MipiCsiDisableClock(DevHandle handle, uint8_t comboDev); 461 ``` 462 463 **表 14** MipiCsiDisableClock的参数和返回值描述 464 465 <a name="table14_MIPI_CSIDes"></a> 466 467 | 参数 | 参数描述 | 468 | ---------- | -------------- | 469 | handle | DevHandle类型,控制器操作句柄 | 470 | comboDev | uint8_t类型,通路序号 | 471 | **返回值** | **返回值描述** | 472 | HDF_SUCCESS | 关闭成功 | 473 | 负数 | 关闭失败 | 474 475 ```c 476 int32_t ret; 477 uint8_t comboDev; 478 479 // 通路序号为0 480 comboDev = 0; 481 // 关闭MIPI的时钟 482 ret = MipiCsiDisableClock(MipiCsiHandle, comboDev); 483 if (ret != HDF_SUCCESS) { 484 HDF_LOGE("MipiCsiDisableClock: mipi csi disable clock fail, ret=%d\n", ret); 485 return ret; 486 } 487 ``` 488 489#### 使能/关闭MIPI上的Sensor时钟<a name="section2.7_MIPI_CSIDes"></a> 490 491- 使能MIPI上的Sensor时钟 492 493 ```c 494 int32_t MipiCsiEnableSensorClock(DevHandle handle, uint8_t snsClkSource); 495 ``` 496 497 **表 15** MipiCsiEnableSensorClock的参数和返回值描述 498 499 <a name="table15_MIPI_CSIDes"></a> 500 501 | 参数 | 参数描述 | 502 | ------------ | ------------------------------------------------ | 503 | handle | DevHandle类型,控制器操作句柄 | 504 | snsClkSource | uint8_t类型,传感器的时钟信号线号,在软件中称为传感器的时钟源 | 505 | **返回值** | **返回值描述** | 506 | HDF_SUCCESS | 使能成功 | 507 | 负数 | 使能失败 | 508 509 ```c 510 int32_t ret; 511 uint8_t snsClkSource; 512 513 // 传感器的时钟信号线号为0 514 snsClkSource = 0; 515 // 使能MIPI上的Sensor时钟 516 ret = MipiCsiEnableSensorClock(MipiCsiHandle, snsClkSource); 517 if (ret != HDF_SUCCESS) { 518 HDF_LOGE("MipiCsiEnableSensorClock: mipi csi enable sensor clock fail, ret=%d\n", ret); 519 return ret; 520 } 521 ``` 522 523- 关闭MIPI上的Sensor时钟 524 525 ```c 526 int32_t MipiCsiDisableSensorClock(DevHandle handle, uint8_t snsClkSource); 527 ``` 528 529 **表 16** MipiCsiDisableSensorClock的参数和返回值描述 530 531 <a name="table16_MIPI_CSIDes"></a> 532 533 | 参数 | 参数描述 | 534 | ------------ | ------------------------------------------------ | 535 | handle | DevHandle类型,控制器操作句柄 | 536 | snsClkSource | uint8_t类型,传感器的时钟信号线号,在软件中称为传感器的时钟源 | 537 | **返回值** | **返回值描述** | 538 | HDF_SUCCESS | 关闭成功 | 539 | 负数 | 关闭失败 | 540 541 ```c 542 int32_t ret; 543 uint8_t snsClkSource; 544 545 // 传感器的时钟信号线号为0 546 snsClkSource = 0; 547 // 关闭MIPI上的Sensor时钟 548 ret = MipiCsiDisableSensorClock(MipiCsiHandle, snsClkSource); 549 if (ret != HDF_SUCCESS) { 550 HDF_LOGE("MipiCsiDisableSensorClock: mipi csi disable sensor clock fail, ret=%d\n", ret); 551 return ret; 552 } 553 ``` 554 555#### 释放MIPI CSI控制器操作句柄<a name="section2.8_MIPI_CSIDes"></a> 556 557MIPI CSI使用完成之后,需要释放控制器操作句柄,释放句柄的函数如下所示: 558 559```c 560void MipiCsiClose(DevHandle handle); 561``` 562 563该函数会释放掉由MipiCsiOpen申请的资源。 564 565**表 17** MipiCsiClose的参数和返回值描述 566 567<a name="table17_MIPI_CSIDes"></a> 568 569| 参数 | 参数描述 | 570| ------------ | ------------------------------------------------ | 571| handle | DevHandle类型,MIPI CSI控制器操作句柄 | 572 573```c 574MipiCsiClose(MIPIHandle); // 释放掉MIPI CSI控制器操作句柄 575``` 576 577## 使用实例<a name="section3_MIPI_CSIDes"></a> 578 579本例拟对Hi3516DV300开发板上MIPI CSI设备进行操作。 580 581MIPI CSI完整的使用示例如下所示: 582 583```c 584#include "hdf_log.h" 585#include "mipi_csi_if.h" 586#include "securec.h" 587 588enum InterfaceType { 589 INTERFACE_MIPI = 0, 590 INTERFACE_LVDS, 591 INTERFACE_CMOS, 592 INTERFACE_BUTT 593}; 594 595static void InitMipiDevAttr(MipiDevAttr *mipiAttr) 596{ 597 MipiDevAttr attr; 598 if (mipiAttr == NULL) { 599 return; 600 } 601 602 HDF_LOGI("InitMipiDevAttr: enter."); 603 (void)memset_s(&attr, sizeof(MipiDevAttr), 0, sizeof(MipiDevAttr)); 604 attr.inputDataType = DATA_TYPE_RAW_12BIT; 605 attr.wdrMode = HI_MIPI_WDR_MODE_NONE; 606 // laneId: -1 - disable 607 attr.laneId[0] = 0; // 0 -- laneId 0 608 attr.laneId[1] = 1; // 1 -- laneId 1 609 attr.laneId[2] = 2; // 2 -- laneId 2 610 attr.laneId[3] = 3; // 3 -- laneId 3 611 612 // Used by the HI_MIPI_WDR_MODE_DT, This is not fully tested! 613 if (attr.wdrMode == HI_MIPI_WDR_MODE_DT) { 614 attr.dataType[0] = 0x39; // 0x39 -- data type reserved 615 attr.dataType[1] = 0x39; // 0x39 -- data type reserved 616 attr.dataType[2] = 0x39; // 0x39 -- data type reserved 617 attr.dataType[3] = 0x39; // 0x39 -- data type reserved 618 } 619 620 *mipiAttr = attr; 621} 622 623static int MipiGetIntputModeType(InputMode inputMode) 624{ 625 switch (inputMode) { 626 case INPUT_MODE_SUBLVDS: 627 case INPUT_MODE_LVDS: 628 case INPUT_MODE_HISPI: 629 return INTERFACE_LVDS; 630 case INPUT_MODE_MIPI: 631 return INTERFACE_MIPI; 632 case INPUT_MODE_CMOS: 633 case INPUT_MODE_BT1120: 634 case INPUT_MODE_BT656: 635 case INPUT_MODE_BYPASS: 636 return INTERFACE_CMOS; 637 default: 638 break; 639 } 640 641 return INTERFACE_BUTT; 642} 643 644static void InitLvdsDevAttr(LvdsDevAttr *lvdsAttr) 645{ 646 int i; 647 int j; 648 int k; 649 LvdsDevAttr attr; 650 651 if (lvdsAttr == NULL) { 652 return; 653 } 654 655 (void)memset_s(&attr, sizeof(LvdsDevAttr), 0, sizeof(LvdsDevAttr)); 656 attr.inputDataType = DATA_TYPE_RAW_12BIT; 657 attr.wdrMode = HI_WDR_MODE_NONE; 658 // LVDS synchronization mode. LVDS_SYNC_MODE_SOF, LVDS_SYNC_MODE_SAV 659 attr.syncMode = LVDS_SYNC_MODE_SOF; 660 // LVDS Vsync type. LVDS_VSYNC_NORMAL, LVDS_VSYNC_SHARE, LVDS_VSYNC_HCONNECT 661 attr.vsyncAttr.syncType = LVDS_VSYNC_NORMAL; 662 // hconnect vsync blanking len, valid when the syncType is LVDS_VSYNC_HCONNECT 663 // This is not fully tested! 664 if (attr.vsyncAttr.syncType == LVDS_VSYNC_HCONNECT) { 665 attr.vsyncAttr.hblank1 = 0; 666 attr.vsyncAttr.hblank2 = 0; 667 } 668 // frame identification code: LVDS_FID_NONE, LVDS_FID_IN_SAV, LVDS_FID_IN_DATA 669 attr.fidAttr.fidType = LVDS_FID_NONE; 670 // Sony DOL has the Frame Information Line, in DOL H-Connection mode, should 671 // configure this flag as false to disable output the Frame Information Line. 672 // This is not fully tested! 673 attr.fidAttr.outputFil = 'm'; 674 // LVDS bit size end mode: LVDS_ENDIAN_LITTLE, LVDS_ENDIAN_BIG 675 attr.dataEndian = LVDS_ENDIAN_LITTLE; 676 // sync code endian: little/big, LVDS_ENDIAN_LITTLE, LVDS_ENDIAN_BIG 677 attr.syncCodeEndian = LVDS_ENDIAN_LITTLE; 678 // laneId: -1 - disable 679 attr.laneId[0] = 0; // 0 -- laneId 0 680 attr.laneId[1] = 1; // 1 -- laneId 1 681 attr.laneId[2] = 2; // 2 -- laneId 2 682 attr.laneId[3] = 3; // 3 -- laneId 3 683 684 /* each vc has 4 params, syncCode[i]: 685 syncMode is SYNC_MODE_SOF: SOF, EOF, SOL, EOL 686 syncMode is SYNC_MODE_SAV: invalid sav, invalid eav, valid sav, valid eav 687 This is not fully tested! */ 688 for (i = 0; i < LVDS_LANE_NUM; i++) { 689 for (j = 0; j < WDR_VC_NUM; j++) { 690 for (k = 0; k < SYNC_CODE_NUM; k++) { 691 attr.syncCode[i][j][k] = 0; // 0 -- frame0 sof 692 } 693 } 694 } 695 696 *lvdsAttr = attr; 697} 698 699static int32_t PalMipiCsiTestSample(void) 700{ 701 uint8_t id; 702 int32_t ret; 703 uint8_t comboDev; 704 uint8_t snsClkSource; 705 uint8_t snsResetSource; 706 uint8_t devno; 707 LaneDivideMode laneMode; 708 PhyCmvMode CmvMode; 709 ComboDevAttr attr; 710 DevHandle MipiCsiHandle = NULL; 711 enum InterfaceType interType; 712 713 // 控制器ID号 714 id = 0; 715 // 获取控制器操作句柄 716 MipiCsiHandle = MipiCsiOpen(id); 717 if (MipiCsiHandle == NULL) { 718 HDF_LOGE("PalMipiCsiTestSample: mipi csi open fail!\n"); 719 return HDF_FAILURE; 720 } 721 722 // Lane模式参数为0 723 laneMode = LANE_DIVIDE_MODE_0; 724 // 设置MIPI RX的Lane分布 725 ret = MipiCsiSetHsMode(MipiCsiHandle, laneMode); 726 if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) { 727 HDF_LOGE("PalMipiCsiTestSample: mipi csi set hs mode fail, ret=%d\n", ret); 728 return ret; 729 } 730 731 // 通路序号为0 732 comboDev = 0; 733 // 使能MIPI的时钟 734 ret = MipiCsiEnableClock(MipiCsiHandle, comboDev); 735 if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) { 736 HDF_LOGE("PalMipiCsiTestSample: mipi csi enable clock fail, ret=%d\n", ret); 737 return ret; 738 } 739 740 // 复位MIPI RX 741 ret = MipiCsiResetRx(MipiCsiHandle, comboDev); 742 if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) { 743 HDF_LOGE("PalMipiCsiTestSample: mipi csi reset rx fail, ret=%d\n", ret); 744 return ret; 745 } 746 747 // 传感器的时钟信号线号为0 748 snsClkSource = 0; 749 // 使能MIPI上的Sensor时钟 750 ret = MipiCsiEnableSensorClock(MipiCsiHandle, snsClkSource); 751 if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) { 752 HDF_LOGE("PalMipiCsiTestSample: mipi csi enable sensor clock fail, ret=%d\n", ret); 753 return ret; 754 } 755 snsResetSource = 0; 756 // 复位Sensor 757 ret = MipiCsiResetSensor(MipiCsiHandle, snsResetSource); 758 if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) { 759 HDF_LOGE("PalMipiCsiTestSample: mipi csi reset sensor fail, ret=%d\n", ret); 760 return ret; 761 } 762 763 // MIPI参数配置如下 764 (void)memset_s(&attr, sizeof(ComboDevAttr), 0, sizeof(ComboDevAttr)); 765 attr.devno = 0; // 设备0 766 attr.inputMode = INPUT_MODE_MIPI; // 输入模式为MIPI 767 attr.dataRate = MIPI_DATA_RATE_X1; // 每时钟输出1像素 768 attr.imgRect.x = 0; // 0: 图像传感器左上位置 769 attr.imgRect.y = 0; // 0: 图像传感器右上位置 770 attr.imgRect.width = 2592; // 2592: 图像传感器宽度大小 771 attr.imgRect.height = 1944; // 1944: 图像传感器高度尺寸 772 interType = MipiGetIntputModeType(attr.inputMode); 773 if (interType == INTERFACE_MIPI) { 774 HDF_LOGI("PalMipiCsiTestSample: call[InitMipiDevAttr]."); 775 InitMipiDevAttr(&attr.mipiAttr); 776 } else if (interType == INTERFACE_LVDS) { 777 HDF_LOGI("PalMipiCsiTestSample: call[InitLvdsDevAttr]."); 778 InitLvdsDevAttr(&attr.lvdsAttr); 779 } else { 780 HDF_LOGE("PalMipiCsiTestSample: interType = %d is error!", attr.inputMode); 781 } 782 // 写入配置数据 783 ret = MipiCsiSetComboDevAttr(MipiCsiHandle, &attr); 784 if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) { 785 HDF_LOGE("PalMipiCsiTestSample: mipi csi set combo devAttr fail, ret=%d\n", ret); 786 return ret; 787 } 788 789 // 共模电压模式参数为0 790 CmvMode = PHY_CMV_GE1200MV; 791 // 设备编号为0 792 devno = 0; 793 // 设置共模电压模式 794 ret = MipiCsiSetPhyCmvmode(MipiCsiHandle, devno, CmvMode); 795 if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) { 796 HDF_LOGE("PalMipiCsiTestSample: mipi csi set phy cmv mode fail, ret=%d\n", ret); 797 return ret; 798 } 799 800 // 通路序号为0 801 comboDev = 0; 802 // 撤销复位MIPI RX 803 ret = MipiCsiUnresetRx(MipiCsiHandle, comboDev); 804 if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) { 805 HDF_LOGE("PalMipiCsiTestSample: mipi csi unreset rx fail, ret=%d\n", ret); 806 return ret; 807 } 808 809 // 关闭MIPI的时钟 810 ret = MipiCsiDisableClock(MipiCsiHandle, comboDev); 811 if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) { 812 HDF_LOGE("PalMipiCsiTestSample: mipi csi disable clock fail, ret=%d\n", ret); 813 return ret; 814 } 815 816 // 传感器撤销复位信号线号为0 817 snsResetSource = 0; 818 // 撤销复位Sensor 819 ret = MipiCsiUnresetSensor(MipiCsiHandle, snsResetSource); 820 if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) { 821 HDF_LOGE("PalMipiCsiTestSample: mipi csi unreset sensor fail, ret=%d\n", ret); 822 return ret; 823 } 824 825 // 关闭MIPI上的Sensor时钟 826 ret = MipiCsiDisableSensorClock(MipiCsiHandle, snsClkSource); 827 if (ret != HDF_SUCCESS && ret != HDF_ERR_NOT_SUPPORT) { 828 HDF_LOGE("PalMipiCsiTestSample: mipi csi disable sensor clock fail, ret=%d\n", ret); 829 return ret; 830 } 831 HDF_LOGI("PalMipiCsiTestSample: function tests end."); 832 // 释放MIPI DSI设备句柄 833 MipiCsiClose(MipiCsiHandle); 834 return ret; 835} 836``` 837 838