Platform: RK3399
OS: Android 8.1
现象:
上篇介绍了如何修改LT9611驱动,调试可以正常输出HDMI,接双屏(HDMI+9611HDMI)后,热插拔9611HDMI系统会崩溃。
问题1
通过查看LOG,猜测崩溃原因是主副屏切换造成的系统崩溃,猜测MIPI接口热插拔会导致系统崩溃,
由于最终我们的目标是三屏异显(mipi转HDMI,mipi转EDP,HDMI)。所以两个mipi输出分辨率固定为EDP屏的分辨率1080P 60
所以修改方案为:
将LT9611看成一个显示屏,RK3399mipi开机后对外输出1080P图像,LT9611检测HPD状态,如果有设备插入,输出1080P图像,如果设备拔出,LT9611失能
解决方法:
1.修改DTS文件,使LT9611不再直接挂在DRM上,DSI直接输出1080P图像
&dsi {
status = "okay";
rockchip,lane-rate = <1200>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@1 {
reg = <1>;
dsi_out_hdmi: endpoint {
remote-endpoint = <&hdmi_in_dsi>;
};
};
};
panel {
compatible ="simple-panel-dsi";
status = "okay";
reg = <0>;
// power-supply = <&vcc3v3_sys>;
backlight = <&backlight>;
// enable-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
// reset-gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;
dsi,flags = <(MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
MIPI_DSI_MODE_VIDEO_SYNC_PULSE)>;
dsi,format = <MIPI_DSI_FMT_RGB888>;
// bus-format = <MEDIA_BUS_FMT_RGB666_1X24>;
dsi,lanes = <4>;
// reset-delay-ms = <20>;
// init-delay-ms = <20>;
// enable-delay-ms = <120>;
prepare-delay-ms = <120>;
display-timings {
native-mode = <&timing0>;
timing0: timing0 {
clock-frequency = <148500000>;//15
hactive = <1920>;
vactive = <1200>;
hback-porch = <60>;
hfront-porch = <16>;
vback-porch = <23>;
vfront-porch = <12>;
hsync-len = <20>;
vsync-len = <3>;
de-active = <0>;
hsync-active = <0>;
vsync-active = <0>;
pixelclk-active = <1>;
};
timing1: timing1{
clock-frequency = <140000000>;
hactive = <1920>;
vactive = <1200>;
hback-porch = <60>;
hfront-porch = <16>;
vback-porch = <23>;
vfront-porch = <12>;
hsync-len = <20>;
vsync-len = <3>;
de-active = <0>;
hsync-active = <0>;
vsync-active = <0>;
pixelclk-active = <0>;
};
};
};
};
2.修改LT9611驱动文件, 不再通过判断MIPI信号以及bridge状态来进行HDMI输出,修改为通过判断HPD状态来进行HDMI输出
if (lt->rxsense){
ret = lt9611_poweron(lt);
}else{
ret = lt9611_poweroff(lt);
}
return ret;
3.因为lt9611获取不到DRM输出的分辨率,所以将LT9611获取到的MIPI模式固定为1080P60
static int lt9611_display_mode_to_timing(struct lt9611 *lt, struct drm_display_mode *mode)
{
u16 h_act,h_tal,v_act,v_tal,htotal_sysclk; //hfp,hs_width,hbp,vfp,vs_width,vbp,
int ret = 0;
h_act = video_1920x1080_60Hz.hact;
v_act = video_1920x1080_60Hz.vact;
h_tal = video_1920x1080_60Hz.htotal;
v_tal = video_1920x1080_60Hz.vtotal;
htotal_sysclk = lt9611_htotal_sysclk(lt);;
/*
lt->vd_timing.vact = mode->vdisplay;
lt->vd_timing.vbp = mode->vtotal - mode->vsync_end; //mode->vback_porch;
lt->vd_timing.vfp = mode->vsync_start - mode->vdisplay; //mode->vfront_porch;
lt->vd_timing.vs = mode->vsync_end - mode->vsync_start; //mode->vsync_len;
lt->vd_timing.vtotal = mode->vtotal; //mode->vsync_len + mode->vfront_porch + mode->vback_porch + mode->vactive;
lt->vd_timing.hact = mode->hdisplay; //mode->hactive;
lt->vd_timing.hbp = mode->htotal - mode->hsync_end; //mode->hback_porch;
lt->vd_timing.hfp = mode->hsync_start - mode->hdisplay; //mode->hfront_porch;
lt->vd_timing.hs = mode->hsync_end - mode->hsync_start; //mode->hsync_len;
lt->vd_timing.htotal = mode->htotal; //mode->hactive + mode->hback_porch + mode->hfront_porch + mode->hsync_len;
lt->vd_timing.pclk_khz = mode->clock;
*/
lt->vd_timing.vact = video_1920x1080_60Hz.vact;
lt->vd_timing.vbp = video_1920x1080_60Hz.vbp;
lt->vd_timing.vfp = video_1920x1080_60Hz.vfp;
lt->vd_timing.vs = video_1920x1080_60Hz.vs;
lt->vd_timing.vtotal = video_1920x1080_60Hz.vtotal;
lt->vd_timing.hact = video_1920x1080_60Hz.hact;
lt->vd_timing.hbp = video_1920x1080_60Hz.hbp;
lt->vd_timing.hfp = video_1920x1080_60Hz.hfp;
lt->vd_timing.hs = video_1920x1080_60Hz.hs;
lt->vd_timing.htotal = video_1920x1080_60Hz.htotal;
lt->vd_timing.pclk_khz = video_1920x1080_60Hz.pclk_khz;
if ((h_act == video_640x480_60Hz.hact) && (v_act == video_640x480_60Hz.vact) && (v_tal == video_640x480_60Hz.vtotal)) {
DRM_ERROR("video_format = video_640x480_60Hz(h_act: %d, v_act: %d, v_tal: %d, h_tal: %d, htotal_sysclk: %d)\n", h_act, v_act, v_tal, h_tal,htotal_sysclk);
lt->video_format = video_640x480_60Hz_vic1;
lt->hdmi_vic = 1;
lt->hdmi_sync_pol = 3;
} else if ((h_act == video_720x480_60Hz.hact) && (v_act == video_720x480_60Hz.vact) && (v_tal == video_720x480_60Hz.vtotal)) {
DRM_ERROR("video_format = video_720x480_60Hz(h_act: %d, v_act: %d, v_tal: %d, h_tal: %d, htotal_sysclk: %d)\n", h_act, v_act, v_tal, h_tal,htotal_sysclk);
lt->video_format = video_720x480_60Hz_vic3;
lt->hdmi_vic = 3;
lt->hdmi_sync_pol = 3;
} else if ((h_act == video_720x576_50Hz.hact) && (v_act == video_720x576_50Hz.vact) && (v_tal==video_720x576_50Hz.vtotal)) {
DRM_ERROR("video_format = video_720x576_50Hz(h_act: %d, v_act: %d, v_tal: %d, h_tal: %d, htotal_sysclk: %d)\n", h_act, v_act, v_tal, h_tal,htotal_sysclk);
lt->video_format = video_720x576_50Hz_vic17;
lt->hdmi_vic = 17;
lt->hdmi_sync_pol = 3;
} else if ((h_act == video_1280x720_60Hz.hact) && (v_act == video_1280x720_60Hz.vact) && (v_tal==video_1280x720_60Hz.vtotal)) {
if (htotal_sysclk > 1700) {
DRM_ERROR("video_format = video_1280x720_50Hz(h_act: %d, v_act: %d, v_tal: %d, h_tal: %d, htotal_sysclk: %d)\n", h_act, v_act, v_tal, h_tal, htotal_sysclk);
lt->video_format = video_1280x720_50Hz_vic19;
lt->hdmi_vic = 19;
lt->hdmi_sync_pol = 0;
} else {
DRM_ERROR("video_format = video_1280x720_60Hz(h_act: %d, v_act: %d, v_tal: %d, h_tal: %d, htotal_sysclk: %d)\n", h_act, v_act, v_tal, h_tal, htotal_sysclk);
lt->video_format = video_1280x720_60Hz_vic4;
lt->hdmi_vic = 4;
lt->hdmi_sync_pol = 0;
}
} else if ((h_act == video_1920x1080_60Hz.hact) && (v_act == video_1920x1080_60Hz.vact)) {
if (htotal_sysclk > 500) {
DRM_ERROR("video_format = video_1920x1080_30Hz(h_act: %d, v_act: %d, v_tal: %d, h_tal: %d, htotal_sysclk: %d)\n", h_act, v_act, v_tal, h_tal, htotal_sysclk);
lt->video_format = video_1920x1080_30Hz_vic;
lt->hdmi_vic = 34;
lt->hdmi_sync_pol = 0;
} else if (htotal_sysclk > 420) {
DRM_ERROR("video_format = video_1920x1080_50Hz(h_act: %d, v_act: %d, v_tal: %d, h_tal: %d, htotal_sysclk: %d)\n", h_act, v_act, v_tal, h_tal, htotal_sysclk);
lt->video_format = video_1920x1080_50Hz_vic31;
lt->hdmi_vic = 31;
lt->hdmi_sync_pol = 0;
} else {
DRM_ERROR("video_format = video_1920x1080_60Hz(h_act: %d, v_act: %d, v_tal: %d, h_tal: %d, htotal_sysclk: %d)\n", h_act, v_act, v_tal, h_tal, htotal_sysclk);
lt->video_format =video_1920x1080_60Hz_vic16;
lt->hdmi_vic = 16;
lt->hdmi_sync_pol=0;
}
} else if ((h_act == video_3840x2160_30Hz.hact) && (v_act == video_3840x2160_30Hz.vact)) {
DRM_ERROR("video_format = video_3840x2160_30Hz(h_act: %d, v_act: %d, v_tal: %d, h_tal: %d, htotal_sysclk: %d)\n", h_act, v_act, v_tal, h_tal, htotal_sysclk);
lt->video_format = video_3840x2160_30Hz_vic;
lt->hdmi_vic = 95;
lt->hdmi_sync_pol = 0;
} else if ((h_act == video_3840x1080_60Hz.hact) && (v_act == video_3840x1080_60Hz.vact)) {
DRM_ERROR("video_format = video_3840x2160_30Hz(h_act: %d, v_act: %d, v_tal: %d, h_tal: %d, htotal_sysclk: %d)\n", h_act, v_act, v_tal, h_tal, htotal_sysclk);
lt->video_format = video_3840x1080_60Hz_vic;
lt->hdmi_vic = 0;
lt->hdmi_sync_pol = 0;
} else if ((h_act == video_1024x768_70Hz.hact) && (v_act == video_1024x768_70Hz.vact)) {
DRM_ERROR("video_format = video_1024x768_70Hz(h_act: %d, v_act: %d, v_tal: %d, h_tal: %d, htotal_sysclk: %d)\n", h_act, v_act, v_tal, h_tal, htotal_sysclk);
lt->video_format = video_1024x768_70Hz_vic;
lt->hdmi_vic = 0;
lt->hdmi_sync_pol = 3;
} else if ((h_act == video_1280x1024_60Hz.hact) && (v_act == video_1280x1024_60Hz.vact)) {
DRM_ERROR("video_format = video_1280x1024_60Hz(h_act: %d, v_act: %d, v_tal: %d, h_tal: %d, htotal_sysclk: %d)\n", h_act, v_act, v_tal, h_tal, htotal_sysclk);
lt->video_format = video_1280x1024_60Hz_vic;
lt->hdmi_vic = 0;
lt->hdmi_sync_pol = 0;
} else if ((h_act == video_1366x768_60Hz.hact) && (v_act == video_1366x768_60Hz.vact)) {
DRM_ERROR("video_format = video_1366x768_60Hz(h_act: %d, v_act: %d, v_tal: %d, h_tal: %d, htotal_sysclk: %d)\n", h_act, v_act, v_tal, h_tal, htotal_sysclk);
lt->video_format = video_1366x768_60Hz_vic;
lt->hdmi_vic = 0;
lt->hdmi_sync_pol = 0;
} else if ((h_act == video_1440x900_60Hz.hact) &&(v_act == video_1440x900_60Hz.vact)) {
DRM_ERROR("video_format = video_1440x900_60Hz(h_act: %d, v_act: %d, v_tal: %d, h_tal: %d, htotal_sysclk: %d)\n", h_act, v_act, v_tal, h_tal, htotal_sysclk);
lt->video_format = video_1440x900_60Hz_vic;
lt->hdmi_vic = 14;
} else if ((h_act == video_1600x900_60Hz.hact) && (v_act == video_1600x900_60Hz.vact)) {
DRM_ERROR("video_format = video_1600x900_60Hz(h_act: %d, v_act: %d, v_tal: %d, h_tal: %d, htotal_sysclk: %d)\n", h_act, v_act, v_tal, h_tal, htotal_sysclk);
lt->video_format = video_1600x900_60Hz_vic;
lt->hdmi_vic = 0;
lt->hdmi_sync_pol = 0;
} else if ((h_act == video_1680x1050_60Hz.hact) && (v_act == video_1680x1050_60Hz.vact)) {
DRM_ERROR("video_format = video_1680x1050_60Hz(h_act: %d, v_act: %d, v_tal: %d, h_tal: %d, htotal_sysclk: %d)\n", h_act, v_act, v_tal, h_tal, htotal_sysclk);
lt->video_format = video_1680x1050_60Hz_vic;
lt->hdmi_vic = 0;
lt->hdmi_sync_pol = 0;
} else {
DRM_ERROR("video_format = unknown video format: h_act: %d, v_act: %d, v_tal: %d, h_tal: %d, htotal_sysclk: %d\n", h_act, v_act, v_tal, h_tal, htotal_sysclk);
lt->video_format = video_1920x1080_60Hz_vic16;
lt->hdmi_vic = 16;
lt->hdmi_sync_pol = 0;
}
return ret;
}
4.修改中断部分逻辑,这里不贴出了
扫描二维码关注公众号,回复:
8680272 查看本文章
问题2
编译后LT9611HDMI接显示屏,插拔HDMI后屏幕有识别到信号源的动作,但是没有图像输出
解决方法:
1.修改DTS中mipi输出timing为标准时钟输出,输出正常。
timing1: timing1 {
clock-frequency = <148500000>;
hactive = <1920>;
vactive = <1080>;
hfront-porch = <88>;
hsync-len = <44>;
hback-porch = <148>;
vfront-porch = <4>;
vsync-len = <5>;
vback-porch = <36>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
总结
修改后mipi作为主屏,HDMI作为副屏,可以实现双屏同显功能,并且支持热插拔。后续会继续更新三屏异显