• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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![](figures/CSI发送-接收接口.png)
15
16MIPI CSI标准分为应用层、协议层与物理层,协议层又细分为像素字节转换层、低级协议层、Lane管理层。
17
18- 物理层(PHY Layer)
19
20  PHY层指定了传输媒介,在电气层面从串行bit流中捕捉“0”与“1”,同时生成SoT与EoT等信号。
21
22- 协议层(Protocol Layer)
23
24  协议层由三个子层组成,每个子层有不同的职责。CSI-2协议能够在host侧处理器上用一个单独的接口处理多条数据流。协议层规定了多条数据流该如何标记和交织起来,以便每条数据流能够被正确地恢复出来。
25
26  - 像素字节转换层(Pixel/Byte Packing/Unpacking Layer)
27
28    CSI-2规范支持多种不同像素格式的图像应用。在发送方中,本层在发送数据到Low Level Protocol层之前,将来自应用层的像素封包为字节数据。在接收方中,本层在发送数据到应用层之前,将来自Low Level Protocol层的字节数据解包为像素。8位的像素数据在本层中传输时保持不变。
29
30  - 低级协议层(Low Level Protocol)
31
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![](../public_sys-resources/icon-note.gif) **说明:**<br>核心层可以调用接口层的函数,核心层通过钩子函数调用适配层函数,从而适配层可以间接的调用接口层函数,但是不可逆转接口层调用适配层函数。
49
50**图2**CSI无服务模式结构图
51
52![image](figures/无服务模式结构图.png "CSI无服务模式结构图")
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.h67
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&nbsp;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&nbsp;RX。不同的s32WorkingViNum有不同的enSnsType |
107| int32_t MipiCsiUnresetRx(DevHandle handle, uint8_t comboDev) | 撤销复位MIPI&nbsp;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
118使用MIPI CSI的一般流程如图3所示。
119
120**图3**  MIPI CSI使用流程图
121
122
123![](figures/MIPI-CSI使用流程图.png)
124
125#### 获取MIPI CSI控制器操作句柄
126
127在进行MIPI CSI进行通信前,首先要调用MipiCsiOpen获取控制器操作句柄,该函数会返回指定通道ID的控制器操作句柄。
128
129```c
130DevHandle MipiCsiOpen(uint8_t id);
131```
132
133**表4**  MipiCsiOpen的参数和返回值描述
134
135| 参数       | 参数描述                                        |
136| ---------- | ----------------------------------------------- |
137| id         | MIPI CSI通道ID                                  |
138| **返回值** | **返回值描述**                                  |
139| NULL       | 获取失败                                        |
140| 设备句柄   | 获取到指令通道的控制器操作句柄,类型为DevHandle |
141
142假设系统中的MIPI CSI通道为0,获取该通道控制器操作句柄的示例如下:
143
144```c
145DevHandle MipiCsiHandle = NULL;  /* 设备句柄 */
146id = 0;      /* MIPI CSI通道ID */
147
148/* 获取控制器操作句柄 */
149MipiCsiHandle = MipiCsiOpen(id);
150if (MipiCsiHandle == NULL) {
151    HDF_LOGE("MipiCsiOpen: failed\n");
152    return;
153}
154```
155
156#### 进行MIPI CSI相应配置
157
158-   写入MIPI CSI配置
159
160    ```c
161    int32_t MipiCsiSetComboDevAttr(DevHandle handle, ComboDevAttr *pAttr);
162    ```
163
164    **表5**  MipiCsiSetComboDevAttr的参数和返回值描述
165
166    <a name="table5_MIPI_CSIDes"></a>
167
168    | 参数       | 参数描述                   |
169    | ---------- | -------------------------- |
170    | handle     | 控制器操作句柄             |
171    | pAttr      | MIPI CSI相应配置结构体指针 |
172    | **返回值** | **返回值描述**             |
173    | 0          | 设置成功                   |
174    | 负数       | 设置失败                   |
175
176    ```c
177    int32_t ret;
178    struct ComboDevAttr attr;
179
180    /* 当前配置如下 */
181    (void)memset_s(&attr, sizeof(ComboDevAttr), 0, sizeof(ComboDevAttr));
182    attr.devno = 0; /* 设备0 */
183    attr.inputMode = INPUT_MODE_MIPI; /* 输入模式为MIPI */
184    attr.dataRate = MIPI_DATA_RATE_X1; /* 每时钟输出1像素 */
185    attr.imgRect.x = 0; /* 0: 图像传感器左上位置 */
186    attr.imgRect.y = 0; /* 0: 图像传感器右上位置 */
187    attr.imgRect.width = 2592; /* 2592: 图像传感器宽度大小 */
188    attr.imgRect.height = 1944; /* 1944: 图像传感器高度尺寸 */
189    /* 写入配置数据 */
190    ret = MipiCsiSetComboDevAttr(MipiCsiHandle, &attr);
191    if (ret != 0) {
192        HDF_LOGE("%s: MipiCsiSetComboDevAttr fail! ret=%d\n", __func__, ret);
193        return -1;
194    }
195    ```
196
197-   设置YUV和RAW数据格式和位深
198
199    ```c
200    int32_t MipiCsiSetExtDataType(DevHandle handle, ExtDataType* dataType);
201    ```
202
203    **表6**  MipiCsiSetExtDataType的参数和返回值描述
204
205    <a name="table6_MIPI_CSIDes"></a>
206
207    | 参数       | 参数描述                        |
208    | ---------- | ------------------------------- |
209    | handle     | 控制器操作句柄                  |
210    | dataType   | 定义YUV和原始数据格式以及位深度 |
211    | **返回值** | **返回值描述**                  |
212    | 0          | 设置成功                        |
213    | 负数       | 设置失败                        |
214
215    ```c
216    int32_t ret;
217    struct ExtDataType dataType;
218
219    /* 配置YUV和RAW数据格式和位深参数 */
220    dataType.devno = 0; /* 设备0 */
221    dataType.num = 0;   /* Sensor 0 */
222    dataType.extDataBitWidth[0] = 12; /* 位深数组元素0 */
223    dataType.extDataBitWidth[1] = 12; /* 位深数组元素1 */
224    dataType.extDataBitWidth[2] = 12; /* 位深数组元素2 */
225
226    dataType.extDataType[0] = 0x39; /* 定义YUV和原始数据格式以及位深度元素0 */
227    dataType.extDataType[1] = 0x39; /* 定义YUV和原始数据格式以及位深度元素1 */
228    dataType.extDataType[2] = 0x39; /* 定义YUV和原始数据格式以及位深度元素2 */
229    /* 设置YUV和RAW数据格式和位深 */
230    ret = MipiCsiSetExtDataType(MipiCsiHandle, &dataType);
231    if (ret != 0) {
232        HDF_LOGE("%s: MipiCsiSetExtDataType fail! ret=%d\n", __func__, ret);
233        return -1;
234    }
235    ```
236
237-   设置MIPI RX的Lane分布
238
239    ```c
240    int32_t MipiCsiSetHsMode(DevHandle handle, LaneDivideMode laneDivideMode);
241    ```
242
243    **表7**  MipiCsiSetHsMode的参数和返回值描述
244
245    | 参数           | 参数描述       |
246    | -------------- | -------------- |
247    | handle         | 控制器操作句柄 |
248    | laneDivideMode | Lane模式参数   |
249    | **返回值**     | **返回值描述** |
250    | 0              | 设置成功       |
251    | 负数           | 设置失败       |
252
253    ```c
254    int32_t ret;
255    enum LaneDivideMode mode;
256
257    /* Lane模式参数为0 */
258    mode = LANE_DIVIDE_MODE_0;
259    /* 设置MIPI RX的 Lane分布 */
260    ret = MipiCsiSetHsMode(MipiCsiHandle, mode);
261    if (ret != 0) {
262        HDF_LOGE("%s: MipiCsiSetHsMode fail! ret=%d\n", __func__, ret);
263        return -1;
264    }
265    ```
266
267-   设置共模电压模式
268
269    ```c
270    int32_t MipiCsiSetPhyCmvmode(DevHandle handle, uint8_t devno, PhyCmvMode cmvMode);
271    ```
272
273    **表8**  MipiCsiSetPhyCmvmode的参数和返回值描述
274
275    | 参数       | 参数描述         |
276    | ---------- | ---------------- |
277    | handle     | 控制器操作句柄   |
278    | cmvMode    | 共模电压模式参数 |
279    | devno      | 设备编号         |
280    | **返回值** | **返回值描述**   |
281    | 0          | 设置成功         |
282    | 负数       | 设置失败         |
283
284    ```c
285    int32_t ret;
286    enum PhyCmvMode mode;
287    uint8_t devno;
288
289    /* 共模电压模式参数为0 */
290    mode = PHY_CMV_GE1200MV;
291    /* 设备编号为0 */
292    devno = 0;
293    /* 设置共模电压模式 */
294    ret = MipiCsiSetPhyCmvmode(MipiCsiHandle, devno, mode);
295    if (ret != 0) {
296        HDF_LOGE("%s: MipiCsiSetPhyCmvmode fail! ret=%d\n", __func__, ret);
297        return -1;
298    }
299    ```
300
301#### 复位/撤销复位Sensor
302
303-   复位Sensor
304
305    ```c
306    int32_t MipiCsiResetSensor(DevHandle handle, uint8_t snsResetSource);
307    ```
308
309    **表9**  MipiCsiResetSensor的参数和返回值描述
310
311    | 参数           | 参数描述                                         |
312    | -------------- | ------------------------------------------------ |
313    | handle         | 控制器操作句柄                                   |
314    | snsResetSource | 传感器的复位信号线号,在软件中称为传感器的复位源 |
315    | **返回值**     | **返回值描述**                                   |
316    | 0              | 复位成功                                         |
317    | 负数           | 复位失败                                         |
318
319    ```c
320    int32_t ret;
321    uint8_t snsResetSource;
322
323    /* 传感器复位信号线号为0 */
324    snsResetSource = 0;
325    /* 复位Sensor */
326    ret = MipiCsiResetSensor(MipiCsiHandle, snsResetSource);
327    if (ret != 0) {
328        HDF_LOGE("%s: MipiCsiResetSensor fail! ret=%d\n", __func__, ret);
329        return -1;
330    }
331    ```
332
333-   撤销复位Sensor
334
335    ```c
336    int32_t MipiCsiUnresetSensor(DevHandle handle, uint8_t snsResetSource);
337    ```
338
339    **表10**  MipiCsiUnresetSensor的参数和返回值描述
340
341    | 参数           | 参数描述                                         |
342    | -------------- | ------------------------------------------------ |
343    | handle         | 控制器操作句柄                                   |
344    | snsResetSource | 传感器的复位信号线号,在软件中称为传感器的复位源 |
345    | **返回值**     | **返回值描述**                                   |
346    | 0              | 撤销复位成功                                     |
347    | 负数           | 撤销复位失败                                     |
348
349    ```c
350    int32_t ret;
351    uint8_t snsResetSource;
352
353    /* 传感器撤销复位信号线号为0 */
354    snsResetSource = 0;
355    /* 撤销复位Sensor */
356    ret = MipiCsiUnresetSensor(MipiCsiHandle, snsResetSource);
357    if (ret != 0) {
358        HDF_LOGE("%s: MipiCsiUnresetSensor fail! ret=%d\n", __func__, ret);
359        return -1;
360    }
361    ```
362
363#### 复位/撤销复位MIPI RX
364
365-   复位MIPI RX
366
367    ```c
368    int32_t MipiCsiResetRx(DevHandle handle, uint8_t comboDev);
369    ```
370
371    **表11**  MipiCsiResetRx的参数和返回值描述
372
373    | 参数       | 参数描述              |
374    | ---------- | --------------------- |
375    | handle     | 控制器操作句柄        |
376    | comboDev   | MIPI RX或LVDS通路序号 |
377    | **返回值** | **返回值描述**        |
378    | 0          | 复位成功              |
379    | 负数       | 复位失败              |
380
381    ```c
382    int32_t ret;
383    uint8_t comboDev;
384
385    /* 通路序号为0 */
386    comboDev = 0;
387    /* 复位MIPI RX */
388    ret = MipiCsiResetRx(MipiCsiHandle, comboDev);
389    if (ret != 0) {
390        HDF_LOGE("%s: MipiCsiResetRx fail! ret=%d\n", __func__, ret);
391        return -1;
392    }
393    ```
394
395-   撤销复位MIPI RX
396
397    ```c
398    int32_t MipiCsiUnresetRx(DevHandle handle, uint8_t comboDev);
399    ```
400
401    **表12**  MipiCsiUnresetRx的参数和返回值描述
402
403    | 参数       | 参数描述              |
404    | ---------- | --------------------- |
405    | handle     | 控制器操作句柄        |
406    | comboDev   | MIPI RX或LVDS通路序号 |
407    | **返回值** | **返回值描述**        |
408    | 0          | 撤销复位成功          |
409    | 负数       | 撤销复位失败          |
410
411    ```c
412    int32_t ret;
413    uint8_t comboDev;
414
415    /* 通路序号为0 */
416    comboDev = 0;
417    /* 撤销复位MIPI RX */
418    ret = MipiCsiUnresetRx(MipiCsiHandle, comboDev);
419    if (ret != 0) {
420        HDF_LOGE("%s: MipiCsiUnresetRx fail! ret=%d\n", __func__, ret);
421        return -1;
422    }
423    ```
424
425#### 使能/关闭MIPI的时钟
426
427-   使能MIPI的时钟
428
429    ```c
430    int32_t MipiCsiEnableClock(DevHandle handle, uint8_t comboDev);
431    ```
432
433    **表13**  MipiCsiEnableClock的参数和返回值描述
434
435    <a name="table13_MIPI_CSIDes"></a>
436
437    | 参数       | 参数描述       |
438    | ---------- | -------------- |
439    | handle     | 控制器操作句柄 |
440    | comboDev   | 通路序号       |
441    | **返回值** | **返回值描述** |
442    | 0          | 使能成功       |
443    | 负数       | 使能失败       |
444
445    ```c
446    int32_t ret;
447    uint8_t comboDev;
448
449    /* 通路序号为0 */
450    comboDev = 0;
451    /* 使能MIPI的时钟 */
452    ret = MipiCsiEnableClock(MipiCsiHandle, comboDev);
453    if (ret != 0) {
454        HDF_LOGE("%s: MipiCsiEnableClock fail! ret=%d\n", __func__, ret);
455        return -1;
456    }
457    ```
458
459-   关闭MIPI的时钟
460
461    ```c
462    int32_t MipiCsiDisableClock(DevHandle handle, uint8_t comboDev);
463    ```
464
465    **表14**  MipiCsiDisableClock的参数和返回值描述
466
467    <a name="table14_MIPI_CSIDes"></a>
468
469    | 参数       | 参数描述       |
470    | ---------- | -------------- |
471    | handle     | 控制器操作句柄 |
472    | comboDev   | 通路序号       |
473    | **返回值** | **返回值描述** |
474    | 0          | 关闭成功       |
475    | 负数       | 关闭失败       |
476
477    ```c
478    int32_t ret;
479    uint8_t comboDev;
480
481    /* 通路序号为0 */
482    comboDev = 0;
483    /* 关闭MIPI的时钟 */
484    ret = MipiCsiDisableClock(MipiCsiHandle, comboDev);
485    if (ret != 0) {
486        HDF_LOGE("%s: MipiCsiDisableClock fail! ret=%d\n", __func__, ret);
487        return -1;
488    }
489    ```
490
491#### 使能/关闭MIPI上的Sensor时钟<a name="section2.7_MIPI_CSIDes"></a>
492
493-   使能MIPI上的Sensor时钟
494
495    ```c
496    int32_t MipiCsiEnableSensorClock(DevHandle handle, uint8_t snsClkSource);
497    ```
498
499    **表15**  MipiCsiEnableSensorClock的参数和返回值描述
500
501    <a name="table15_MIPI_CSIDes"></a>
502
503    | 参数         | 参数描述                                         |
504    | ------------ | ------------------------------------------------ |
505    | handle       | 控制器操作句柄                                   |
506    | snsClkSource | 传感器的时钟信号线号,在软件中称为传感器的时钟源 |
507    | **返回值**   | **返回值描述**                                   |
508    | 0            | 使能成功                                         |
509    | 负数         | 使能失败                                         |
510
511    ```c
512    int32_t ret;
513    uint8_t snsClkSource;
514
515    /* 传感器的时钟信号线号为0 */
516    snsClkSource = 0;
517    /* 使能MIPI上的Sensor时钟 */
518    ret = MipiCsiEnableSensorClock(MipiCsiHandle, snsClkSource);
519    if (ret != 0) {
520        HDF_LOGE("%s: MipiCsiEnableSensorClock fail! ret=%d\n", __func__, ret);
521        return -1;
522    }
523    ```
524
525-   关闭MIPI上的Sensor时钟
526
527    ```c
528    int32_t MipiCsiDisableSensorClock(DevHandle handle, uint8_t snsClkSource);
529    ```
530
531    **表16**  MipiCsiDisableSensorClock的参数和返回值描述
532
533    <a name="table16_MIPI_CSIDes"></a>
534
535    | 参数         | 参数描述                                         |
536    | ------------ | ------------------------------------------------ |
537    | handle       | 控制器操作句柄                                   |
538    | snsClkSource | 传感器的时钟信号线号,在软件中称为传感器的时钟源 |
539    | **返回值**   | **返回值描述**                                   |
540    | 0            | 关闭成功                                         |
541    | 负数         | 关闭失败                                         |
542
543    ```c
544    int32_t ret;
545    uint8_t snsClkSource;
546
547    /* 传感器的时钟信号线号为0 */
548    snsClkSource = 0;
549    /* 关闭MIPI上的Sensor时钟 */
550    ret = MipiCsiDisableSensorClock(MipiCsiHandle, snsClkSource);
551    if (ret != 0) {
552        HDF_LOGE("%s: MipiCsiDisableSensorClock fail! ret=%d\n", __func__, ret);
553        return -1;
554    }
555    ```
556
557#### 释放MIPI CSI控制器操作句柄<a name="section2.8_MIPI_CSIDes"></a>
558
559MIPI CSI使用完成之后,需要释放控制器操作句柄,释放句柄的函数如下所示:
560
561```c
562void MipiCsiClose(DevHandle handle);
563```
564
565该函数会释放掉由MipiCsiOpen申请的资源。
566
567**表17**  MipiCsiClose的参数和返回值描述
568
569<a name="table17_MIPI_CSIDes"></a>
570
571| 参数         | 参数描述                                         |
572| ------------ | ------------------------------------------------ |
573| handle       | MIPI CSI控制器操作句柄                                  |
574
575```c
576MipiCsiClose(MIPIHandle); /* 释放掉MIPI CSI控制器操作句柄 */
577```
578
579## 使用实例<a name="section3_MIPI_CSIDes"></a>
580
581本例拟对Hi3516DV300开发板上MIPI CSI设备进行操作。
582
583MIPI CSI完整的使用示例如下所示:
584
585```c
586#include "hdf.h"
587#include "MIPI_csi_if.h"
588
589void PalMipiCsiTestSample(void)
590{
591    uint8_t id;
592    int32_t ret;
593    uint8_t comboDev;
594    uint8_t snsClkSource;
595    uint8_t devno;
596    enum LaneDivideMode mode;
597    enum PhyCmvMode mode;
598    struct ComboDevAttr attr;
599    struct ExtDataType dataType;
600    DevHandle MipiCsiHandle = NULL;
601
602    /* 控制器ID号 */
603    id = 0;
604    /* 获取控制器操作句柄 */
605    MipiCsiHandle = MipiCsiOpen(id);
606    if (MipiCsiHandle == NULL) {
607        HDF_LOGE("MipiCsiOpen: failed!\n");
608        return;
609    }
610
611    /* Lane模式参数为0 */
612    mode = LANE_DIVIDE_MODE_0;
613    /* 设置MIPI RX的Lane分布 */
614    ret = MipiCsiSetHsMode(MipiCsiHandle, mode);
615    if (ret != 0) {
616        HDF_LOGE("%s: MipiCsiSetHsMode fail! ret=%d\n", __func__, ret);
617        return;
618    }
619
620    /* 通路序号为0 */
621    comboDev = 0;
622    /* 使能MIPI的时钟 */
623    ret = MipiCsiEnableClock(MipiCsiHandle, comboDev);
624    if (ret != 0) {
625        HDF_LOGE("%s: MipiCsiEnableClock fail! ret=%d\n", __func__, ret);
626        return;
627    }
628
629    /* 复位MIPI RX */
630    ret = MipiCsiResetRx(MipiCsiHandle, comboDev);
631    if (ret != 0) {
632        HDF_LOGE("%s: MipiCsiResetRx fail! ret=%d\n", __func__, ret);
633        return;
634    }
635
636    /* 传感器的时钟信号线号为0 */
637    snsClkSource = 0;
638    /* 使能MIPI上的Sensor时钟 */
639    ret = MipiCsiEnableSensorClock(MipiCsiHandle, snsClkSource);
640    if (ret != 0) {
641        HDF_LOGE("%s: MipiCsiEnableSensorClock fail! ret=%d\n", __func__, ret);
642        return;
643    }
644
645    /* 复位Sensor */
646    ret = MipiCsiResetSensor(MipiCsiHandle, snsResetSource);
647    if (ret != 0) {
648        HDF_LOGE("%s: MipiCsiResetSensor fail! ret=%d\n", __func__, ret);
649        return;
650    }
651
652    /* MIPI参数配置如下 */
653    (void)memset_s(&attr, sizeof(ComboDevAttr), 0, sizeof(ComboDevAttr));
654    attr.devno = 0; /* 设备0 */
655    attr.inputMode = INPUT_MODE_MIPI; /* 输入模式为MIPI */
656    attr.dataRate = MIPI_DATA_RATE_X1; /* 每时钟输出1像素 */
657    attr.imgRect.x = 0; /* 0: 图像传感器左上位置 */
658    attr.imgRect.y = 0; /* 0: 图像传感器右上位置 */
659    attr.imgRect.width = 2592; /* 2592: 图像传感器宽度大小 */
660    attr.imgRect.height = 1944; /* 1944: 图像传感器高度尺寸 */
661    /* 写入配置数据 */
662    ret = MipiCsiSetComboDevAttr(MipiCsiHandle, &attr);
663    if (ret != 0) {
664        HDF_LOGE("%s: MipiCsiSetComboDevAttr fail! ret=%d\n", __func__, ret);
665        return;
666    }
667
668    /* 共模电压模式参数为0 */
669    mode = PHY_CMV_GE1200MV;
670    /* 设备编号为0 */
671    devno = 0;
672    /* 设置共模电压模式 */
673    ret = MipiCsiSetPhyCmvmode(MipiCsiHandle, devno, mode);
674    if (ret != 0) {
675        HDF_LOGE("%s: MipiCsiSetPhyCmvmode fail! ret=%d\n", __func__, ret);
676        return;
677    }
678
679    /* 通路序号为0 */
680    comboDev = 0;
681    /* 撤销复位MIPI RX */
682    ret = MipiCsiUnresetRx(MipiCsiHandle, comboDev);
683    if (ret != 0) {
684        HDF_LOGE("%s: MipiCsiUnresetRx fail! ret=%d\n", __func__, ret);
685        return;
686    }
687
688    /* 关闭MIPI的时钟 */
689    ret = MipiCsiDisableClock(MipiCsiHandle, comboDev);
690    if (ret != 0) {
691        HDF_LOGE("%s: MipiCsiDisableClock fail! ret=%d\n", __func__, ret);
692        return;
693    }
694
695    /* 传感器撤销复位信号线号为0 */
696    snsResetSource = 0;
697    /* 撤销复位Sensor */
698    ret = MipiCsiUnresetSensor(MipiCsiHandle, snsResetSource);
699    if (ret != 0) {
700        HDF_LOGE("%s: MipiCsiUnresetSensor fail! ret=%d\n", __func__, ret);
701        return;
702    }
703
704    /* 关闭MIPI上的Sensor时钟 */
705    ret = MipiCsiDisableSensorClock(MipiCsiHandle, snsClkSource);
706    if (ret != 0) {
707        HDF_LOGE("%s: MipiCsiDisableSensorClock fail! ret=%d\n", __func__, ret);
708        return;
709    }
710
711    /* 释放MIPI DSI设备句柄 */
712    MipiCsiClose(MipiCsiHandle);
713}
714```
715
716