我的堆栈是:raspberrypi、uboot、buildroot 和 weston。我有两个显示设备连接到主板。第一个是用户界面的触摸屏(HDMI-A-1
),第二个是投影仪的触摸屏(HDMI-A-2
)。我使用自定义内核启动徽标。是否可以仅在上显示启动启动画面HDMI-A-1
?我设法通过在 bootargs 中禁用来做到这一点HDMI-A-2
,如下所示:
bootargs=console=ttyAMA0,115200 earlycon=ttyAMA0,115200 splash video=HDMI-A-1:1024x600-32 video=HDMI-A-2:d vt.global_cursor_default=0
但后来我无法HDMI-A-2
在运行时打开:
connector[89]: HDMI-A-1
crtc=crtc-0
self_refresh_aware=0
connector[153]: HDMI-A-2
crtc=(null)
self_refresh_aware=0
有什么解决办法吗?
编辑:
我发现通过将帧缓冲区映射到控制台可以部分实现这一点:
fbcon=map:1
它仅在两个显示器都有单独的帧缓冲区的情况下才有效。不幸的是,vc4 为两个显示器发布了一个共享的帧缓冲区,所以这对我来说不是一个解决方案。
编辑2:
不幸的是,据我所知,如果不修补内核,这是不可能的。有 raspberrypi 固件可以做到这一点,但它只能在 32 位系统上编译。RaspberryPi 固件开发人员强烈声称没有 64 位端口,他们未来也没有这样做的计划。
答案1
正如我在评论中提到的,可以使用 DRM 创建虚拟帧缓冲区。
在 *.h 文件中准备适当分辨率的徽标。这可能会有所帮助:https://lvgl.io/tools/imageconverter
我们需要编写简单的 C 程序:
a)包括第一步中的徽标:
#include "logo.h"
b)我们需要它通过 ioctl 调用 drm:
#include <sys/ioctl.h>
#include <drm/drm.h>
#include <drm/drm_mode.h>
c) 打开适当的设备:
int dri_fd0 = open("/dev/dri/card0",O_RDWR | O_CLOEXEC);
d)从 drm 检索信息:
struct drm_mode_modeinfo conn_mode_buf[20]={0};
uint64_t conn_prop_buf[20]={0},
conn_propval_buf[20]={0},
conn_enc_buf[20]={0};
struct drm_mode_get_connector conn={0};
conn.connector_id=res_conn_buf[i];
ioctl(dri_fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn);
conn.modes_ptr=(uint64_t)conn_mode_buf;
conn.props_ptr=(uint64_t)conn_prop_buf;
conn.prop_values_ptr=(uint64_t)conn_propval_buf;
conn.encoders_ptr=(uint64_t)conn_enc_buf;
ioctl(dri_fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn);
e) 初始化虚拟缓冲区:struct drm_mode_create_dumb create_dumb={0}; struct drm_mode_map_dumb map_dumb={0}; struct drm_mode_fb_cmd cmd_dumb={0};
create_dumb.width = width;
create_dumb.height = height;
create_dumb.bpp = 32;
create_dumb.flags = 0;
create_dumb.pitch = 0;
create_dumb.size = 0;
create_dumb.handle = 0;
ioctl(dri_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
cmd_dumb.width=create_dumb.width;
cmd_dumb.height=create_dumb.height;
cmd_dumb.bpp=create_dumb.bpp;
cmd_dumb.pitch=create_dumb.pitch;
cmd_dumb.depth=24;
cmd_dumb.handle=create_dumb.handle;
ioctl(dri_fd,DRM_IOCTL_MODE_ADDFB,&cmd_dumb);
map_dumb.handle=create_dumb.handle;
ioctl(dri_fd,DRM_IOCTL_MODE_MAP_DUMB,&map_dumb);
fb_base[i] = mmap(0, create_dumb.size, PROT_READ | PROT_WRITE, MAP_SHARED, dri_fd, map_dumb.offset);
struct drm_mode_get_encoder enc={0};
enc.encoder_id=conn.encoder_id;
ioctl(dri_fd, DRM_IOCTL_MODE_GETENCODER, &enc); //get encoder
struct drm_mode_crtc crtc={0};
crtc.crtc_id=enc.crtc_id;
ioctl(dri_fd, DRM_IOCTL_MODE_GETCRTC, &crtc);
crtc.fb_id=cmd_dumb.fb_id;
crtc.set_connectors_ptr=(uint64_t)&res_conn_buf[i];
crtc.count_connectors=1;
crtc.mode=conn_mode_buf[0];
crtc.mode_valid=1;
ioctl(dri_fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
f)将带有您的徽标的数据从 c 数组复制到视频卡共享缓冲区:
memcpy(fb_base[0], uint32_data, sizeof(uint32_t) * logo_width * logo_height);
我们需要循环执行此操作,因为缓冲区会定期自动清除。
为专用平台构建应用程序并复制到
/usr/bin/
。添加触发器
udev
:a)在 /usr/lib/udev/rules.d/11-framebuffer.rules 中创建新文件
KERNEL=="card0", RUN+="/usr/bin/splash-launch"
b)在文件内部添加触发器,当视频卡准备就绪时调用启动画面: