1. Camera驱动概述:Camera硬件接口介绍(MIPI、DVP、USB)、Linux V4L2框架简介、驱动在系统中的位置

各位同学,咱们今天正式开始聊Camera驱动。说实话,每次讲这个章节我都挺感慨的——当年我刚入行时,第一次接触Camera驱动,对着数据手册看了三天,愣是没搞明白MIPI和DVP到底有啥区别。后来踩了不少坑,才慢慢摸清门道。今天我就把这些经验掰开了揉碎了讲给你们听。

1.1 Camera硬件接口:MIPI、DVP、USB

先说说硬件接口。Camera传感器和主控芯片之间怎么传数据?说白了就三种主流方式:MIPI、DVP、USB。嗯,这里要注意,不是所有接口都适合所有场景。

MIPI(Mobile Industry Processor Interface)

MIPI是目前最主流的接口,尤其在手机、平板、车载摄像头领域。它采用差分信号传输,说白了就是一对线传一个信号,抗干扰能力强。MIPI CSI(Camera Serial Interface)通常用1-4个数据通道(Lane),每个通道速率能到1Gbps以上。

关键点:MIPI是串行接口,线少、速率高、功耗低。我做过一个项目,用4 Lane MIPI传1080P 60fps的视频流,稳得很。

MIPI的物理层叫D-PHY,分LP(低功耗)和HS(高速)两种模式。LP模式用来传控制信号,HS模式才真正传图像数据。我曾经遇到过一个坑:某个模组的LP时序不达标,导致初始化时老是失败。后来用示波器一抓,发现LP-11状态维持时间不够——嗯,这种问题查起来特别费劲。

DVP(Digital Video Port)

DVP是并行接口,说白了就是一根根数据线同时传数据。通常有8位、10位、12位等。DVP接口简单,但缺点也很明显:线多、速率上不去、抗干扰差。

对比项 MIPI DVP
信号线数量 4-10根(含时钟) 20-30根(含时钟、同步信号)
最高速率 数Gbps 几百Mbps
抗干扰 强(差分信号) 弱(单端信号)
适用场景 手机、车载、高清 低端、低速、老平台

我个人习惯,如果项目对成本敏感、分辨率不高(比如VGA级别),DVP还能用用。但但凡要上720P以上,我建议直接上MIPI。别问我为什么——我在一个项目里用DVP跑1080P,结果EMI测试死活过不了,最后改版加屏蔽罩,成本反而更高了。

USB Camera

USB接口的Camera,说白了就是UVC(USB Video Class)设备。这种接口最大的好处是即插即用,Windows、Linux、macOS都原生支持。但缺点也很明显:延迟高、带宽共享、不适合实时性要求高的场景。

你想想看,USB是主机轮询的,不像MIPI那样有专用时钟和同步信号。所以做工业相机、车载环视这种对实时性要求高的项目,基本不会用USB。但做消费级产品,比如USB摄像头、内窥镜,那就很合适了。

1.2 Linux V4L2框架简介

V4L2,全称Video for Linux 2,是Linux内核里处理视频设备的框架。说白了,它就是一套标准接口,让应用程序不用关心底层硬件是MIPI还是USB,统一通过/dev/videoX操作。

V4L2框架的核心概念有几个:

  • Video Device:对应/dev/videoX节点,用户空间通过它来操作
  • Buffer:存放图像数据的内存区域,有单缓冲区、多缓冲区、DMABUF等模式
  • Format:图像格式,比如YUYV、MJPEG、NV12等
  • Control:控制参数,比如亮度、对比度、曝光时间

我记得刚学V4L2时,最头疼的就是它的ioctl命令。太多了!VIDIOC_QUERYCAPVIDIOC_ENUM_FMTVIDIOC_S_FMTVIDIOC_REQBUFSVIDIOC_QBUFVIDIOC_DQBUF……光记名字就够呛。

但后来我总结了一个规律:V4L2的流程其实就三步——

  1. 打开设备,查询能力,设置格式
  2. 申请缓冲区,把缓冲区映射到用户空间
  3. 启动流,循环入队出队

说白了就是:打开、设置、循环。你把这个流程记住,V4L2就入门了。

小技巧:调试V4L2驱动时,可以用v4l2-ctl工具。比如v4l2-ctl --list-formats查看支持的格式,v4l2-ctl --set-fmt-video=width=1920,height=1080,pixelformat=YUYV设置格式。这比写测试程序快多了。

1.3 驱动在系统中的位置

Camera驱动在Linux内核里到底待在哪?我画个简单的层次图给你看:

用户空间 (应用程序)
    ↓ 系统调用 (open/ioctl/mmap)
V4L2核心层 (videodev.ko)
    ↓
Camera子设备驱动 (sensor驱动、CSI控制器驱动)
    ↓
硬件抽象层 (I2C、GPIO、DMA、Clock)
    ↓
物理硬件 (Camera模组、SoC接口)

嗯,这里要注意,Camera驱动不是孤零零一个文件。它通常分两部分:

  • Sensor驱动:负责初始化传感器、配置寄存器、控制曝光/增益等。一般通过I2C通信。
  • 接口控制器驱动:负责MIPI/DVP的时序控制、数据接收、DMA传输。这部分通常集成在SoC里。

我曾经犯过一个低级错误:写Sensor驱动时,忘了把MIPI的时钟使能。结果Sensor初始化成功了,但就是没数据。查了两天,最后发现是SoC的CSI控制器没开时钟——这种问题,说白了就是驱动之间的依赖关系没理清。

V4L2框架里,Sensor驱动通常注册为v4l2_subdev,接口控制器驱动注册为video_device。两者通过media_entity连接起来。你想想看,这就像搭积木:Sensor负责采集,控制器负责传输,V4L2负责统一管理。

避坑指南:我曾经在一个项目里,Sensor驱动和控制器驱动是两个人写的。结果Sensor输出的格式是RAW10,控制器却配置成了RAW8。图像出来全是花的。所以,驱动开发时一定要对齐格式、分辨率、帧率这些参数。最好写个文档,把双方的接口约定写清楚。

最后说一句,Camera驱动在系统中的位置,说白了就是「承上启下」。对上,它通过V4L2接口给应用程序提供服务;对下,它通过I2C、GPIO、DMA等子系统操作硬件。搞懂这个位置关系,你写驱动时就知道该调用哪些内核API了。

好了,这一章就到这里。下一章我们开始深入MIPI的物理层和协议层,到时候我会带你们看一个实际项目的MIPI调试过程——嗯,那才叫真正的「踩坑实录」。