设计说明
源码说明
源代码位于 bsp/artinchip/
:
- bsp/artinchip/drv/dvp/drv_dvp.c,DVP Driver 层实现
- bsp/artinchip/hal/dvp/hal_dvp.c,DVP HAL 层实现
- bsp/artinchip/include/hal/hal_dvp.h,DVP HAL 层接口头文件
模块架构
整个软件系统的架构图如下:
- DVP 驱动需要和我司的 MPP 中间件配合一起使用,DVP Driver 层采用普通的 API 方式向上提供接口。 - 同时,DVP 还需要和 Camera 外设的驱动配合一起完成图像数据的采集。 - MPP VIN 模块对 APP 提供类似 ioctl 的接口封装,这样设计是为了和 Linux 中 MPP VIN 保持一致。 - DVP 暂不支持在裸机环境中运行。关键流程设计
初始化流程
DVP 驱动的初始化过程分为两大段:
- 由 probe() 接口完成,完成中断申请、管理状态初始化等。
- 由 open() 接口完成 (需要等 Sensor 执行完初始化后才能执行),完成的操作有:使能时钟、使能 DVP 控制器、初始化 Buf 链表信息等。
Buf 管理
详见 MPP VIN 模块中的 Buf 队列管理。
中断处理流程
DVP 的中断处理函数中主要处理 Buf 的队列切换操作。DVP 硬件提供的中断可以反映出多个状态 (包括出错状态),其中有两个关键状态:
1.HNUM Interrupt:
表示当前图像帧已经完成 1/4 帧数据的刷新,意味着此时的 Buf 相关 Register (影子寄存器) 可以被修改,软件可以传入下一个 Buf 的参数了。
2.Frame done:
表示当前帧的数据传输完成。
可见,HNUM Interrupt 会先于 Frame done 发生,驱动中用 HNUM Interrupt 判断当前 Register 是否可以修改,用 Frame done 判断当前 buf 是否完成(done 状态),该 buf 就可以从 QBuf list 切换到 DQbuf list 了。
按照 DVP 硬件设计的逻辑,HNUM Interrupt 和 Frame done 会间隔着产生:
bash
HNUM Interrupt -> Frame done -> HNUM Interrupt -> Frame done -> HNUM Interrupt -> Frame done ...
1
“处理 HNUM Interrupt 事件” 的子流程如下:
数据结构设计
struct aic_dvp
属于 Driver 层接口,定义了 DVP 控制器的设备管理信息:
bash
- struct aic_dvp {
- struct aic_dvp_config cfg; /* The configuration of DVP HW */
- struct dvp_out_fmt fmt; /* The format of output data */
- /* Videobuf */
- struct vb_queue queue;
- struct list_head active_list;
- unsigned int sequence;
- unsigned int streaming;
};
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
struct aic_dvp_config
属于 HAL 层接口,定义了媒体数据的配置信息:
bash
- struct aic_dvp_config {
- enum dvp_input input;
- enum dvp_input_yuv_seq input_seq;
- u32 flags;
- /* Output format */
- enum dvp_output output;
- u32 width;
- u32 height;
- u32 stride[DVP_PLANE_NUM];
- u32 sizeimage[DVP_PLANE_NUM];
};
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
输入输出的数据格式
enum dvp_input
属于 HAL 层接口,定义了 DVP 输入数据的格式:
bash
enum dvp_input {
DVP_IN_RAW = 0,
DVP_IN_YUV422 = 1,
DVP_IN_BT656 = 2,
};
1
2
3
4
5
2
3
4
5
enum dvp_input_yuv_seq
属于 HAL 层接口,定义了 DVP 输入数据的 YUV 格式:
bash
enum dvp_input_yuv_seq {
DVP_YUV_DATA_SEQ_YUYV = 0,
DVP_YUV_DATA_SEQ_YVYU = 1,
DVP_YUV_DATA_SEQ_UYVY = 2,
DVP_YUV_DATA_SEQ_VYUY = 3,
};
1
2
3
4
5
6
2
3
4
5
6
enum dvp_output
属于 HAL 层接口,定义了 DVP 输出数据的格式:
bash
enum dvp_output {
DVP_OUT_RAW_PASSTHROUGH = 0,
DVP_OUT_YUV422_COMBINED_NV16 = 1,
DVP_OUT_YUV420_COMBINED_NV12 = 2,
};
1
2
3
4
5
2
3
4
5
Driver 层接口设计
aic_dvp_probe
函数原型 | int aic_dvp_probe(void) |
---|---|
功能说明 | 完成中断申请、管理状态初始化等 |
参数定义 | 无 |
返回值 | 0,成功;< 0,失败 |
注意事项 | 无 |
aic_dvp_open
函数原型 | int aic_dvp_open(void) |
---|---|
功能说明 | 使能时钟、使能 DVP 控制器、初始化 Buf 链表信息等 |
参数定义 | 无 |
返回值 | 0,成功;< 0,失败 |
注意事项 | 无 |
aic_dvp_close
函数原型 | int aic_dvp_close(void) |
---|---|
功能说明 | 关闭时钟、关闭 DVP 控制器 |
参数定义 | 无 |
返回值 | 0,成功;< 0,失败 |
注意事项 | 无 |
aic_dvp_set_in_fmt
函数原型 | int aic_dvp_set_in_fmt(struct mpp_video_fmt *fmt) |
---|---|
功能说明 | 设置 DVP 的输入视频格式 |
参数定义 | fmt - 指向 struct mpp_video_fmt 类型的指针 |
返回值 | 0,成功;< 0,失败 |
注意事项 | fmt 一般是从 Camera 设备中读取到的格式信息 |
aic_dvp_set_out_fmt
函数原型 | int aic_dvp_set_out_fmt(struct dvp_out_fmt *fmt) |
---|---|
功能说明 | 设置 DVP 的输出图像格式 |
参数定义 | fmt - 指向 struct dvp_out_fmt 类型的指针 |
返回值 | 0,成功 |
注意事项 | 无 |
aic_dvp_stream_on
函数原型 | int aic_dvp_stream_on(void) |
---|---|
功能说明 | 启动视频流 |
参数定义 | 无 |
返回值 | 0,成功;<0,失败 |
注意事项 | 无 |
aic_dvp_stream_off
函数原型 | int aic_dvp_stream_off(void) |
---|---|
功能说明 | 关闭视频流 |
参数定义 | 无 |
返回值 | 0,成功;<0,失败 |
注意事项 | 无 |
aic_dvp_req_buf
函数原型 | int aic_dvp_req_buf(char *buf, u32 size, struct vin_video_buf *vbuf) |
---|---|
功能说明 | 按照给定的 Video Buf 配置信息从内存池中申请 Buf |
参数定义 | buf - 指向内存池的指针 size - 内存池的总大小 vbuf - Video Buf 的配置信息 |
返回值 | 0,成功;<0,失败 |
注意事项 | 无 |
aic_dvp_q_buf
函数原型 | int aic_dvp_q_buf(u32 index) |
---|---|
功能说明 | 释放指定 index 的 Buf 进入空闲队列(queued_list) |
参数定义 | index - Buf 的索引号 |
返回值 | 0,成功;<0,失败 |
注意事项 | 无 |
aic_dvp_dq_buf
函数原型 | int aic_dvp_dq_buf(u32 *pindex) |
---|---|
功能说明 | 从 DVP 处理完成后的队列(done_list)中获取一个 Buf |
参数定义 | pindex - 用于保存获取到的 Buf 索引号 |
返回值 | 0,成功;<0,失败 |
注意事项 | 无 |
APP Demo
详见 MPP VIN 模块中的 参考Demo