OMAP2/3 显示子系统¶
这是对 drivers/video/omap 中的 OMAP FB 驱动程序的几乎完全的重写(我们称之为 DSS1)。 DSS1 和 DSS2 之间的主要区别在于 DSI、TV-out 和多显示器支持,但也有许多小的改进。
DSS2 驱动程序 (omapdss 模块) 位于 arch/arm/plat-omap/dss/ 中,FB、面板和控制器驱动程序位于 drivers/video/omap2/ 中。 DSS1 和 DSS2 目前并存,您可以选择使用哪一个。
特性¶
已工作并测试过的特性包括
MIPI DPI(并行)输出
MIPI DSI 输出(命令模式)
MIPI DBI (RFBI) 输出
SDI 输出
TV 输出
所有部分都可以编译为模块或在内核中
使用 DISPC 更新任何输出
使用 CPU 更新 RFBI 或 DSI 输出
OMAP DISPC 平面
RGB16、RGB24 打包、RGB24 解包
YUV2, UYVY
缩放
调整 DSS FCK 以找到一个好的像素时钟
使用 DSI DPLL 创建 DSS FCK
测试过的板子包括:- OMAP3 SDP 板 - Beagle 板 - N810
omapdss 驱动程序¶
DSS 驱动程序本身不支持 Linux framebuffer、V4L 或类似当前的驱动程序,但它有一个内部内核 API,上层驱动程序可以使用它。
DSS 驱动程序以一种灵活的方式建模 OMAP 的覆盖层、覆盖管理器和显示器,以支持非通用的多显示器配置。 除了对硬件覆盖层进行建模外,omapdss 还支持虚拟覆盖层和覆盖管理器。 当使用 CPU 或系统 DMA 更新显示器时,可以使用它们。
omapdss 驱动程序对音频的支持¶
存在多种支持音频的显示技术和标准。 因此,更新 DSS 设备驱动程序以提供可供音频驱动程序或任何其他对该功能感兴趣的驱动程序使用的音频接口是相关的。
audio_enable 函数旨在准备相关的 IP 进行播放(例如,启用音频 FIFO,进出复位某些 IP,启用配套芯片等)。 它旨在 audio_start 之前调用。 audio_disable 函数执行相反的操作,旨在 audio_stop 之后调用。
虽然给定的 DSS 设备驱动程序可能支持音频,但对于某些配置,可能不支持音频(例如,使用 VESA 视频时序的 HDMI 显示器)。 audio_supported 函数旨在查询显示器的当前配置是否支持音频。
audio_config 函数旨在配置显示器的所有相关音频参数。 为了使该函数独立于任何特定的 DSS 设备驱动程序,定义了一个 struct omap_dss_audio。 它的目的是包含音频配置所需的所有参数。 目前,该结构包含指向 IEC-60958 通道状态字和 CEA-861 音频信息帧结构的指针。 这应该足以支持 HDMI 和 DisplayPort,因为两者都基于 CEA-861 和 IEC-60958。
audio_enable/disable、audio_config 和 audio_supported 函数可以实现为可能休眠的函数。 因此,在持有自旋锁或读锁时,不应调用它们。
audio_start/audio_stop 函数旨在在配置完成后有效地启动/停止音频播放。 这些函数旨在在原子上下文中使用。 因此,audio_start 应该快速返回,并且只有在启动数据传输所需的音频播放的所有必要资源(音频 FIFO、DMA 通道、配套芯片等)都已启用后才能调用。 audio_stop 旨在仅停止音频传输。 用于播放的资源使用 audio_disable 释放。
enum omap_dss_audio_state 可用于帮助接口的实现跟踪音频状态。 初始状态为 _DISABLED; 然后,状态转换为 _CONFIGURED,然后,当它准备好播放音频时,转换为 _ENABLED。 状态 _PLAYING 在渲染音频时使用。
面板和控制器驱动程序¶
这些驱动程序实现了面板或控制器特定的功能,通常除了通过 omapfb 驱动程序之外,用户不可见。 它们将自己注册到 DSS 驱动程序。
omapfb 驱动程序¶
omapfb 驱动程序实现了任意数量的标准 linux framebuffer。 这些 framebuffer 可以灵活地路由到任何覆盖层,从而允许非常动态的显示架构。
该驱动程序导出一些 omapfb 特定的 ioctl,这些 ioctl 与旧驱动程序中的 ioctl 兼容。
其余的非标准特性通过 sysfs 导出。 最终实现是使用 sysfs 还是 ioctl 仍未确定。
V4L2 驱动程序¶
V4L2 正在 TI 中实现。
从 omapdss 的角度来看,V4L2 驱动程序应该类似于 framebuffer 驱动程序。
架构¶
一些澄清不同组件的功能
Framebuffer 是 OMAP 的 SRAM/SDRAM 中的一个内存区域,其中包含图像的像素数据。 Framebuffer 具有宽度、高度和颜色深度。
覆盖层定义了从哪里读取像素以及它们在屏幕上的显示位置。 覆盖层可能小于 framebuffer,因此只显示 framebuffer 的一部分。 如果覆盖层小于显示器,则可以更改覆盖层的位置。
覆盖管理器将覆盖层组合成一个图像并将其馈送到显示器。
显示器是实际的物理显示设备。
一个 framebuffer 可以连接到多个覆盖层,以在所有覆盖层上显示相同的像素数据。 请注意,在这种情况下,覆盖层输入大小必须相同,但是,对于视频覆盖层,输出大小可以不同。 任何 framebuffer 都可以连接到任何覆盖层。
一个覆盖层可以连接到一个覆盖管理器。 此外,DISPC 覆盖层只能连接到 DISPC 覆盖管理器,虚拟覆盖层只能连接到虚拟覆盖层。
一个覆盖管理器可以连接到一个显示器。 某些覆盖管理器可以连接到哪些类型的显示器存在一些限制
DISPC TV 覆盖管理器只能连接到 TV 显示器。
虚拟覆盖管理器只能连接到 DBI 或 DSI 显示器。
DISPC LCD 覆盖管理器可以连接到所有显示器,除了 TV 显示器。
Sysfs¶
sysfs 接口主要用于测试。 我认为 sysfs 接口不是最终版本中的最佳选择,但我不太清楚这些事情的最佳接口是什么。
sysfs 接口分为两个部分:DSS 和 FB。
/sys/class/graphics/fb? 目录:mirror 0=off, 1=on rotate 旋转 0-3 表示 0、90、180、270 度 rotate_type 0 = DMA 旋转,1 = VRFB 旋转 overlays Framebuffer 像素转到的覆盖层编号列表 phys_addr Framebuffer 的物理地址 virt_addr Framebuffer 的虚拟地址 size Framebuffer 的大小
/sys/devices/platform/omapdss/overlay? 目录:enabled 0=off, 1=on input_size 宽度,高度 (即 framebuffer 大小) manager 目标覆盖管理器名称 name output_size 宽度,高度 position x,y screen_width 宽度 global_alpha 全局 alpha 0-255 0=透明 255=不透明
/sys/devices/platform/omapdss/manager? 目录:display 目标显示器名称 alpha_blending_enabled 0=off, 1=on trans_key_enabled 0=off, 1=on trans_key_type gfx-destination, video-source trans_key_value 透明颜色键 (RGB24) default_color 默认背景颜色 (RGB24)
/sys/devices/platform/omapdss/display? 目录
ctrl_name |
控制器名称 |
mirror |
0=off, 1=on |
update_mode |
0=off, 1=自动, 2=手动 |
enabled |
0=off, 1=on |
name |
|
rotate |
旋转 0-3 表示 0、90、180、270 度 |
timings |
显示时序 (像素时钟,xres/hfp/hbp/hsw,yres/vfp/vbp/vsw) 写入时,接受两个特殊的时序用于 tv-out:“pal” 和 “ntsc” |
panel_name |
|
tear_elim |
撕裂消除 0=off, 1=on |
output_type |
输出类型(仅限视频编码器):“composite” 或 “svideo” |
在 <debugfs>/omapdss/ 中也有一些 debugfs 文件,显示有关时钟和寄存器的信息。
示例¶
已为以下示例进行以下定义
ovl0=/sys/devices/platform/omapdss/overlay0
ovl1=/sys/devices/platform/omapdss/overlay1
ovl2=/sys/devices/platform/omapdss/overlay2
mgr0=/sys/devices/platform/omapdss/manager0
mgr1=/sys/devices/platform/omapdss/manager1
lcd=/sys/devices/platform/omapdss/display0
dvi=/sys/devices/platform/omapdss/display1
tv=/sys/devices/platform/omapdss/display2
fb0=/sys/class/graphics/fb0
fb1=/sys/class/graphics/fb1
fb2=/sys/class/graphics/fb2
OMAP3 SDP 上的默认设置¶
这是 OMAP3 SDP 板上的默认设置。 所有平面都转到 LCD。 DVI 和 TV-out 未在使用中。 从左到右的列是:framebuffer、覆盖层、覆盖管理器、显示器。 Framebuffer 由 omapfb 处理,其余由 DSS 处理
FB0 --- GFX -\ DVI
FB1 --- VID1 --+- LCD ---- LCD
FB2 --- VID2 -/ TV ----- TV
示例:从 LCD 切换到 DVI¶
w=`cat $dvi/timings | cut -d "," -f 2 | cut -d "/" -f 1`
h=`cat $dvi/timings | cut -d "," -f 3 | cut -d "/" -f 1`
echo "0" > $lcd/enabled
echo "" > $mgr0/display
fbset -fb /dev/fb0 -xres $w -yres $h -vxres $w -vyres $h
# at this point you have to switch the dvi/lcd dip-switch from the omap board
echo "dvi" > $mgr0/display
echo "1" > $dvi/enabled
之后,配置如下所示:
FB0 --- GFX -\ -- DVI
FB1 --- VID1 --+- LCD -/ LCD
FB2 --- VID2 -/ TV ----- TV
示例:将 GFX 覆盖克隆到 LCD 和 TV¶
w=`cat $tv/timings | cut -d "," -f 2 | cut -d "/" -f 1`
h=`cat $tv/timings | cut -d "," -f 3 | cut -d "/" -f 1`
echo "0" > $ovl0/enabled
echo "0" > $ovl1/enabled
echo "" > $fb1/overlays
echo "0,1" > $fb0/overlays
echo "$w,$h" > $ovl1/output_size
echo "tv" > $ovl1/manager
echo "1" > $ovl0/enabled
echo "1" > $ovl1/enabled
echo "1" > $tv/enabled
之后,配置如下所示(仅显示相关部分)
FB0 +-- GFX ---- LCD ---- LCD
\- VID1 ---- TV ---- TV
其他说明¶
OMAP FB 使用标准 dma 分配器分配 framebuffer 内存。 您可以启用 Contiguous Memory Allocator (CONFIG_CMA) 来改进 dma 分配器,如果启用了 CMA,您可以使用 “cma=” 内核参数来增加 CMA 的全局内存区域。
使用 DSI DPLL 生成像素时钟可以产生 86.5MHz 的像素时钟(最大可能值),通过它可以从 DVI 获得 1280x1024@57 输出。
旋转和镜像当前仅支持 RGB565 和 RGB8888 模式。 VRFB 不支持镜像。
VRFB 旋转比非旋转 framebuffer 需要更多的内存,因此您可能需要在使用 VRFB 旋转之前增加 vram 设置。 此外,如果许多应用程序不注意所有 framebuffer 参数,则可能无法使用 VRFB。
内核启动参数¶
- omapfb.mode=<显示器>:<模式>[,...]
指定显示器的默认视频模式。 例如,“dvi:800x400MR-24@60”。 请参阅 drivers/video/modedb.c。 还有两种特殊模式:“pal” 和 “ntsc”,可用于 tv out。
- omapfb.vram=<fbnum>:<size>[@<physaddr>][,...]
为 framebuffer 分配的 VRAM。 通常 omapfb 根据显示大小分配 vram。 使用此方法,您可以手动分配更多内存或定义每个 framebuffer 的物理地址。 例如,“1:4M” 为 fb1 分配 4M。
- omapfb.debug=<y|n>
启用调试打印。 您必须在内核配置中启用 OMAPFB 调试支持。
- omapfb.test=<y|n>
每当 framebuffer 设置更改时,将测试图案绘制到 framebuffer。 您需要在内核配置中启用 OMAPFB 调试支持。
- omapfb.vrfb=<y|n>
对所有 framebuffer 使用 VRFB 旋转。
- omapfb.rotate=<角度>
应用于所有 framebuffer 的默认旋转。 0 - 0 度旋转 1 - 90 度旋转 2 - 180 度旋转 3 - 270 度旋转
- omapfb.mirror=<y|n>
所有 framebuffer 的默认镜像。 仅适用于 DMA 旋转。
- omapdss.def_disp=<显示器>
所有覆盖层将连接到的默认显示器的名称。 常见的例子是 “lcd” 或 “tv”。
- omapdss.debug=<y|n>
启用调试打印。 您必须在内核配置中启用 DSS 调试支持。
TODO¶
DSS 锁定
错误检查
缺少许多检查,或者只是作为 BUG() 实现
DSI 的系统 DMA 更新
可用于 RGB16 和 RGB24P 模式。 可能不适用于 RGB24U(如何跳过空字节?)
OMAP1 支持
不确定是否需要