1. 理解ISP V4L2驱动中的格式支持机制
在图像信号处理(ISP)驱动开发中,V4L2(Video4Linux2)作为Linux内核的视频设备框架,负责处理不同像素格式的输入输出。Mali-C71AE和Mali-C78AE这类ISP硬件虽然原生支持多种格式,但驱动层需要明确映射这些格式才能被上层应用调用。
当前驱动默认支持的格式包括:
- V4L2_PIX_FMT_SBGGR12/14/16(Bayer原始数据)
- V4L2_PIX_FMT_ABGR32(带Alpha通道的ABGR)
- V4L2_PIX_FMT_BGR24(标准BGR格式)
- V4L2_PIX_FMT_NV12(YUV420半平面格式)
这些格式通过AXI总线与ISP硬件通信时,需要特定的数据打包方式。例如,NV12格式在AXI总线上会被转换为OF_AXI_MODE_Y8UV88_2X2这种硬件识别的内部表示。
关键提示:在修改驱动前,必须查阅Hardware TRM中的Figure 3-43和Figure 3-44,确认目标格式的AXI打包方式与硬件规格完全匹配。
2. 格式添加的完整技术流程
2.1 格式映射表建立
首先需要明确V4L2像素格式与ISP硬件格式的对应关系。以下是典型格式的映射示例:
| V4L2格式定义 | V4L2 FourCC码 | ISP AXI输出格式 |
|---|---|---|
| V4L2_PIX_FMT_RGBA32 | v4l2_fourcc('A','B','2','4') | OF_AXI_MODE_RGBA32 |
| V4L2_PIX_FMT_YUYV | v4l2_fourcc('Y','U','Y','V') | OF_AXI_MODE_YUV_YUYV_8 |
| V4L2_PIX_FMT_NV16 | v4l2_fourcc('N','V','1','6') | OF_AXI_MODE_Y8UV88_2X1 |
FourCC码是四字符编码,用于唯一标识视频格式。例如'YUYV'表示YUV422交错格式,每个宏像素包含两个Y分量和共享的U、V分量。
2.2 驱动代码修改步骤
以添加RGBA32和YUYV格式为例:
启用V4L2编译选项
在acamera_configuration.h中确保开启编译开关:#define V4L2_INTERFACE_BUILD 1更新fw-interface.c
在fw_intf_stream_set_output_mode()函数中添加格式转换逻辑:case V4L2_PIX_FMT_RGBA32: value = OF_AXI_MODE_RGBA32; string_value = "OF_AXI_MODE_RGBA32"; break; case V4L2_PIX_FMT_YUYV: value = OF_AXI_MODE_YUV_YUYV_8; string_value = "OF_AXI_MODE_YUV_YUYV_8"; break;声明FourCC码
在isp-v4l2-common.h中添加新格式的宏定义:#define V4L2_PIX_FMT_RGBA32 v4l2_fourcc('A','B','2','4') #define V4L2_PIX_FMT_YUYV v4l2_fourcc('Y','U','Y','V')扩展输出格式结构体
修改isp-v4l2-stream.c中的V4L2_STREAM_TYPE_OUT结构:{ .description = "RGBA32", .pixelformat = V4L2_PIX_FMT_RGBA32, .data_width = 32, .num_planes = 1, .is_yuv = 0, }, { .description = "YUYV", .pixelformat = V4L2_PIX_FMT_YUYV, .data_width = 16, .num_planes = 1, .is_yuv = 1, }同时更新格式计数器:
.num_formats = 3 + 2 // 原3个格式+新增2个
2.3 应用层适配
如果使用Arm提供的V4L2测试工具,需要同步更新:
- 在
common.h中添加相同的FourCC定义 - 在
v4l2_test.h中扩展输出模式枚举:enum { OUTPUT_MODE_RGB_BGRA8888, OUTPUT_MODE_RGB_RGBA8888, // 新增 OUTPUT_MODE_YUV_YUYV, // 新增 OUTPUT_MODE_YUV_NV12, OUTPUT_MODE_MAX, }; - 在
v4l2_test.c中实现格式选择逻辑:case OUTPUT_MODE_RGB_RGBA8888: pixel_format = V4L2_PIX_FMT_RGBA32; break; case OUTPUT_MODE_YUV_YUYV: pixel_format = V4L2_PIX_FMT_YUYV; break;
3. 验证与调试技巧
3.1 硬件寄存器检查
使用Arm Control Tool(ACT)验证配置是否生效:
- 连接目标设备并启动ACT
- 导航至API > TIMAGE > OUTPUT_AXI_MODE_ID
- 检查寄存器值是否与预期格式代码匹配
常见问题排查表:
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 应用无法识别新格式 | FourCC码定义不一致 | 检查所有头文件的宏定义一致性 |
| 图像色彩异常 | AXI打包模式配置错误 | 对照TRM确认数据排列顺序 |
| 驱动加载失败 | num_formats计数错误 | 检查结构体初始化代码 |
| ACT显示未知格式 | 寄存器写入未生效 | 跟踪fw_intf_stream_set_output_mode调用链 |
3.2 性能优化建议
- 内存对齐:RGBA32等32位格式应确保缓冲区地址64字节对齐,避免DMA性能下降
- 缓存控制:对于YUV格式,建议设置
V4L2_BUF_FLAG_NO_CACHE_INVALIDATE标志 - 中断合并:高分辨率图像处理时,适当调整ISP的VSYNC中断间隔
4. 高级扩展:动态格式支持
对于需要频繁变更格式的场景,可以进一步改进驱动架构:
- 实现ioctl扩展:
static long isp_v4l2_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { case ISP_IOC_ADD_FORMAT: { struct isp_format_desc desc; copy_from_user(&desc, (void __user *)arg, sizeof(desc)); // 动态添加到格式表 break; } } - 维护格式哈希表:使用内核的hlist管理动态添加的格式
- 热加载支持:通过sysfs接口实现格式模块的运行时加载
经验之谈:在Mali-C78AE r1p0 eac01版本中,曾发现AXI模式寄存器需要至少2个时钟周期的稳定时间。建议在设置OUTPUT_AXI_MODE_ID后添加微小延迟。