位于u-boot\drivers\video\drm\rockchip_display.c 函數 display_logo:
static int display_logo(struct display_state *state)
{
struct crtc_state *crtc_state = &state->crtc_state;
struct connector_state *conn_state = &state->conn_state;
struct logo_info *logo = &state->logo;
int hdisplay, vdisplay;
display_init(state);
if (!state->is_init)
return -ENODEV;
switch (logo->bpp) {
case 16:
crtc_state->format = ROCKCHIP_FMT_RGB565;
break;
case 24:
crtc_state->format = ROCKCHIP_FMT_RGB888;
break;
case 32:
crtc_state->format = ROCKCHIP_FMT_ARGB8888;
break;
default:
printf("can't support bmp bits[%d]\n", logo->bpp);
return -EINVAL;
}
crtc_state->rb_swap = logo->bpp != 32;
hdisplay = conn_state->mode.hdisplay;
vdisplay = conn_state->mode.vdisplay;
crtc_state->src_w = logo->width;
crtc_state->src_h = logo->height;
crtc_state->src_x = 0;
crtc_state->src_y = 0;
crtc_state->ymirror = logo->ymirror;
crtc_state->dma_addr = (u32)(unsigned long)logo->mem + logo->offset;
crtc_state->xvir = ALIGN(crtc_state->src_w * logo->bpp, 32) >> 5;
if (logo->mode == ROCKCHIP_DISPLAY_FULLSCREEN) {
crtc_state->crtc_x = 0;
crtc_state->crtc_y = 0;
crtc_state->crtc_w = hdisplay;
crtc_state->crtc_h = vdisplay;
} else {
if (crtc_state->src_w >= hdisplay) {
crtc_state->crtc_x = 0;
crtc_state->crtc_w = hdisplay;
} else {
crtc_state->crtc_x = (hdisplay - crtc_state->src_w) / 2;
crtc_state->crtc_w = crtc_state->src_w;
}
if (crtc_state->src_h >= vdisplay) {
crtc_state->crtc_y = 0;
crtc_state->crtc_h = vdisplay;
} else {
crtc_state->crtc_y = (vdisplay - crtc_state->src_h) / 2;
crtc_state->crtc_h = crtc_state->src_h;
}
}
display_set_plane(state);
display_enable(state);
return 0;
}
1. display_init: 初始化panel,注冊相關函數;初始化connector,注冊相關函數,檢測連接配接器插入裝置;擷取顯示控制時序或讀取edid,設定掃描模式。
static int display_init(struct display_state *state)
{
struct connector_state *conn_state = &state->conn_state;
struct panel_state *panel_state = &state->panel_state;
const struct rockchip_connector *conn = conn_state->connector;
const struct rockchip_connector_funcs *conn_funcs = conn->funcs;
struct crtc_state *crtc_state = &state->crtc_state;
struct rockchip_crtc *crtc = crtc_state->crtc;
const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
struct drm_display_mode *mode = &conn_state->mode;
int bpc;
int ret = 0;
static bool __print_once = false;
if (!__print_once) {
__print_once = true;
printf("Rockchip UBOOT DRM driver version: %s\n", DRIVER_VERSION);
}
if (state->is_init)
return 0;
if (!conn_funcs || !crtc_funcs) {
printf("failed to find connector or crtc functions\n");
return -ENXIO;
}
if (panel_state->panel)
rockchip_panel_init(panel_state->panel);
if (conn_funcs->init) {
ret = conn_funcs->init(state);
if (ret)
goto deinit;
}
if (conn_state->phy)
rockchip_phy_init(conn_state->phy);
/*
* support hotplug, but not connect;
*/
#ifdef CONFIG_ROCKCHIP_DRM_TVE
if (crtc->hdmi_hpd && conn_state->type == DRM_MODE_CONNECTOR_TV) {
printf("hdmi plugin ,skip tve\n");
goto deinit;
}
#elif defined(CONFIG_DRM_ROCKCHIP_RK1000)
if (crtc->hdmi_hpd && conn_state->type == DRM_MODE_CONNECTOR_LVDS) {
printf("hdmi plugin ,skip tve\n");
goto deinit;
}
#endif
if (conn_funcs->detect) {
ret = conn_funcs->detect(state);
#if defined(CONFIG_ROCKCHIP_DRM_TVE) || defined(CONFIG_DRM_ROCKCHIP_RK1000)
if (conn_state->type == DRM_MODE_CONNECTOR_HDMIA)
crtc->hdmi_hpd = ret;
#endif
if (!ret)
goto deinit;
}
if (panel_state->panel) {
ret = display_get_timing(state);
} else if (conn_state->bridge) {
ret = video_bridge_read_edid(conn_state->bridge->dev,
conn_state->edid, EDID_SIZE);
if (ret > 0) {
ret = edid_get_drm_mode(conn_state->edid, ret, mode,
&bpc);
if (!ret)
edid_print_info((void *)&conn_state->edid);
} else {
ret = video_bridge_get_timing(conn_state->bridge->dev);
}
} else if (conn_funcs->get_timing) {
ret = conn_funcs->get_timing(state);
} else if (conn_funcs->get_edid) {
ret = conn_funcs->get_edid(state);
if (!ret) {
ret = edid_get_drm_mode((void *)&conn_state->edid,
sizeof(conn_state->edid), mode,
&bpc);
if (!ret)
edid_print_info((void *)&conn_state->edid);
}
}
if (ret)
goto deinit;
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
if (crtc_funcs->init) {
ret = crtc_funcs->init(state);
if (ret)
goto deinit;
}
state->is_init = 1;
return 0;
deinit:
if (conn_funcs->deinit)
conn_funcs->deinit(state);
return ret;
}
2.設定幀緩沖屬性,如格式RGB565,RGB888或ARGB8888,設定分辨率大小及幀起始位址。将幀緩沖注冊到plane,使能顯示面闆,開始顯示。
3.display_set_plane:注冊顯示緩沖到面闆
static int display_set_plane(struct display_state *state)
{
struct crtc_state *crtc_state = &state->crtc_state;
const struct rockchip_crtc *crtc = crtc_state->crtc;
const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
int ret;
if (!state->is_init)
return -EINVAL;
if (crtc_funcs->set_plane) {
ret = crtc_funcs->set_plane(state);
if (ret)
return ret;
}
return 0;
}
4.display_enable: 使能顯示
static int display_enable(struct display_state *state)
{
struct connector_state *conn_state = &state->conn_state;
const struct rockchip_connector *conn = conn_state->connector;
const struct rockchip_connector_funcs *conn_funcs = conn->funcs;
struct crtc_state *crtc_state = &state->crtc_state;
const struct rockchip_crtc *crtc = crtc_state->crtc;
const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
struct panel_state *panel_state = &state->panel_state;
display_init(state);
if (!state->is_init)
return -EINVAL;
if (state->is_enable)
return 0;
if (crtc_funcs->prepare)
crtc_funcs->prepare(state);
if (conn_funcs->prepare)
conn_funcs->prepare(state);
if (conn_state->bridge)
rockchip_bridge_pre_enable(conn_state->bridge);
if (panel_state->panel)
rockchip_panel_prepare(panel_state->panel);
if (crtc_funcs->enable)
crtc_funcs->enable(state);
if (conn_funcs->enable)
conn_funcs->enable(state);
if (conn_state->bridge)
rockchip_bridge_enable(conn_state->bridge);
if (panel_state->panel)
rockchip_panel_enable(panel_state->panel);
state->is_enable = true;
return 0;
}