TMS320DM6446的VPBE(Video Processing Back End)是视频输出的核心模块,由OSD(On-Screen Display)和VENC(Video ENCoder)两部分组成。VPBE的工作流程可以概括为:
在RGB666模式下,每个像素使用18位表示(R/G/B各6位),这种非交错(non-interlaced)色彩格式需要特别注意VENC寄存器的配置。典型的寄存器配置序列如下:
c复制// 设置RGB输出模式
dispc_reg_out(VENC_VMOD, VMOD_RGB666);
// 配置色彩空间转换参数
dispc_reg_out(VENC_CVBS, 0x0);
// 启用LCD输出
dispc_reg_out(VENC_LCDOUT, 0x1);
Linux FBDev(Frame Buffer Device)为视频驱动提供了统一的用户接口,主要包含以下关键组件:
/dev/fbX设备节点:提供mmap映射和ioctl控制fb_info结构体:维护显示设备的当前状态fb_ops操作集:实现驱动核心功能在DaVinci平台上,我们通过扩展标准的FBDev驱动来支持高级功能。例如添加专有的IOCTL命令:
c复制#define FBIO_SET_VIDEODAC _IOW('F', 0x22, int)
这个自定义IOCTL允许应用程序动态切换连接的DAC芯片,其处理流程包括:
动态分辨率切换的核心是通过FBIOPUT_VSCREENINFO ioctl更新显示参数。驱动收到请求后:
fb_set_par回调中解析新分辨率参数fb_var_screeninfodavinci_set_par执行实际硬件配置关键代码路径:
c复制static int davinci_fb_set_par(struct fb_info *info)
{
struct davinci_fb_par *par = info->par;
// 计算时钟分频参数
calc_clk_divider(par);
// 配置VPBE时序发生器
setup_venc_timing(par);
// 更新OSD窗口设置
config_osd_windows(par);
// 同步DAC配置
configureVideoDAC(par->video_format);
return 0;
}
为支持720p/1080i/VGA等多种分辨率,驱动需要维护一个分辨率描述表:
c复制static struct vmode_config {
const char *name;
u32 width;
u32 height;
u32 hsync_len;
u32 vsync_len;
u32 left_margin;
u32 upper_margin;
enum davinci_video_format format;
} supported_modes[] = {
{"720p", 1280, 720, 40, 5, 300, 26, VIDFMT_720P},
{"1080i", 1920, 540, 44, 5, 200, 18, VIDFMT_1080I},
{"vga", 640, 480, 96, 2, 48, 33, VIDFMT_VGA},
};
当应用程序请求分辨率切换时,驱动会:
davinci_set_par中匹配请求的分辨率configureVideoDAC同步外部DAC设置驱动初始化时通过DAC检测列表实现自动识别:
c复制static struct dac_desc {
enum davinci_dac_type type;
int (*detect)(void);
const char *name;
} dac_list[] = {
{DAC_THS8200, ths8200_probe, "THS8200"},
// 可扩展其他DAC型号
};
检测流程:
dac_list中的每个条目detect()函数检查硬件是否存在以720p模式为例,THS8200需要配置的关键寄存器包括:
输入输出模式设置:
c复制// 设置YPbPr输出模式
buf[0] = 0x82;
buf[1] = 0x1b;
i2c_write(i2cfd, buf, 2);
时序发生器配置:
c复制// 启用DTG并选择720p模式
buf[0] = 0x38;
buf[1] = 0x82;
i2c_write(i2cfd, buf, 2);
水平时序参数:
c复制// 同步脉冲宽度
buf[0] = 0x25;
buf[1] = 0x28; // 40像素
i2c_write(i2cfd, buf, 2);
// 有效视频起始位置
buf[0] = 0x2a;
buf[1] = 0x2c; // 300像素
i2c_write(i2cfd, buf, 2);
这些参数必须与DM6446 VENC的配置严格匹配,否则会导致显示异常。
实现720p输出需要协调三个子系统的配置:
DM6446 OSD窗口设置:
c复制#define BASEX720P 0x50
#define BASEY720P 0x5
dispc_reg_out(OSD_BASEPX, BASEX720P);
dispc_reg_out(OSD_BASEPY, BASEY720P);
dispc_reg_out(OSD_VIDWIN0XL, 1280);
dispc_reg_out(OSD_VIDWIN0YL, 720);
VENC时序发生器配置:
c复制dispc_reg_out(VENC_HINT, 1649); // 总行周期1650
dispc_reg_out(VENC_HSTART, 300); // 水平起始
dispc_reg_out(VENC_VINT, 749); // 总场周期750
dispc_reg_out(VENC_VSTART, 26); // 垂直起始
时钟系统配置:
c复制// 启用外部74.25MHz时钟
dispc_reg_out(VPSS_CLKCTL, 0x0a);
// 配置DCLK分频器
dispc_reg_out(VENC_DCLKCTL, VENC_DCKCTL_DCKEC);
1080i隔行扫描模式需要特别注意:
启用场同步信号:
c复制dispc_reg_merge(PINMUX0, PINMUX0_LFLDEN, PINMUX0_LFLDEN);
窗口高度设置为总高度的一半:
c复制dispc_reg_out(OSD_VIDWIN0YL, 540); // 1080/2
配置场时序参数:
c复制dispc_reg_out(VENC_VSTARTA, 13); // 第二场起始行
无图像输出:
图像撕裂或错位:
色彩异常:
寄存器调试:
bash复制# 通过/sys/kernel/debug访问寄存器
cat /sys/kernel/debug/venc/registers
信号测量:
性能优化:
在实际项目中,建议先使用默认参数确保基本功能正常,再逐步调整高级参数。特别注意不同分辨率切换时需要重新计算所有时序参数,任何微小的不匹配都可能导致显示异常。