platform: mtk8937
以下为开机后调用关系:
根据不同的平台,这个函数所在的文件不同; 我们项目属于msm8952系列;
void target_display_init(const char *panel_name)
{
struct oem_panel_data oem;
int32_t ret = 0;
uint32_t panel_loop = 0;
set_panel_cmd_string(panel_name);
oem = mdss_dsi_get_oem_data();
if (!strcmp(oem.panel, NO_PANEL_CONFIG)
|| !strcmp(oem.panel, SIM_VIDEO_PANEL)
|| !strcmp(oem.panel, SIM_CMD_PANEL)
|| oem.skip) {
dprintf(INFO, "Selected panel: %s\nSkip panel configuration\n",
oem.panel);
return;
}
do {
target_force_cont_splash_disable(false);
ret = gcdb_display_init(oem.panel, MDP_REV_50, (void *)MIPI_FB_ADDR);
if (!ret || ret == ERR_NOT_SUPPORTED) {
break;
} else {
target_force_cont_splash_disable(true);
msm_display_off();
}
} while (++panel_loop <= oem_panel_max_auto_detect_panels());
if (!oem.cont_splash) {
dprintf(INFO, "Forcing continuous splash disable\n");
target_force_cont_splash_disable(true);
}
}
再调用以下函数:
int gcdb_display_init(const char *panel_name, uint32_t rev, void *base)
{
int ret = NO_ERROR;
int pan_type;
dsi_video_mode_phy_db.pll_type = DSI_PLL_TYPE_28NM;
pan_type = oem_panel_select(panel_name, &panelstruct, &(panel.panel_info),
&dsi_video_mode_phy_db);
if (pan_type == PANEL_TYPE_DSI) {
if (update_dsi_display_config())
goto error_gcdb_display_init;
target_dsi_phy_config(&dsi_video_mode_phy_db);
mdss_dsi_check_swap_status();
mdss_dsi_set_pll_src();
if (dsi_panel_init(&(panel.panel_info), &panelstruct)) {
dprintf(CRITICAL, "DSI panel init failed!\n");
ret = ERROR;
goto error_gcdb_display_init;
}
panel.panel_info.mipi.mdss_dsi_phy_db = &dsi_video_mode_phy_db;
panel.pll_clk_func = mdss_dsi_panel_clock;
panel.dfps_func = mdss_dsi_mipi_dfps_config;
panel.power_func = mdss_dsi_panel_power;
panel.pre_init_func = mdss_dsi_panel_pre_init;
panel.bl_func = mdss_dsi_bl_enable;
panel.dsi2HDMI_config = mdss_dsi2HDMI_config;
/*
* Reserve fb memory to store pll codes and pass
* pll codes values to kernel.
*/
panel.panel_info.dfps.dfps_fb_base = base;
base += DFPS_PLL_CODES_SIZE;
panel.fb.base = base;
dprintf(SPEW, "dfps base=0x%p,d, fb_base=0x%p!\n",
panel.panel_info.dfps.dfps_fb_base, base);
panel.fb.width = panel.panel_info.xres;
panel.fb.height = panel.panel_info.yres;
panel.fb.stride = panel.panel_info.xres;
panel.fb.bpp = panel.panel_info.bpp;
panel.fb.format = panel.panel_info.mipi.dst_format;
} else if (pan_type == PANEL_TYPE_EDP) {
mdss_edp_panel_init(&(panel.panel_info));
/* prepare func is set up at edp_panel_init */
panel.clk_func = mdss_edp_panel_clock;
panel.power_func = mdss_edp_panel_power;
panel.bl_func = mdss_edp_bl_enable;
panel.fb.format = FB_FORMAT_RGB888;
} else {
dprintf(CRITICAL, "Target panel init not found!\n");
ret = ERR_NOT_SUPPORTED;
goto error_gcdb_display_init;
}
panel.fb.base = base;
panel.mdp_rev = rev;
ret = msm_display_init(&panel);
error_gcdb_display_init:
display_enable = ret ? 0 : 1;
return ret;
}
再调用下面函数: // 配置lcd.
int msm_display_init(struct msm_fb_panel_data *pdata)
{
int ret = NO_ERROR;
panel = pdata;
if (!panel) {
ret = ERR_INVALID_ARGS;
goto msm_display_init_out;
}
/* Turn on panel */
if (pdata->power_func)
ret = pdata->power_func(1, &(panel->panel_info));
if (ret)
goto msm_display_init_out;
if (pdata->dfps_func)
ret = pdata->dfps_func(&(panel->panel_info));
/* Enable clock */
if (pdata->clk_func)
ret = pdata->clk_func(1, &(panel->panel_info));
if (ret)
goto msm_display_init_out;
/* Read specifications from panel if available.
* If further clocks should be enabled, they can be enabled
* using pll_clk_func
*/
if (pdata->update_panel_info)
ret = pdata->update_panel_info();
if (ret)
goto msm_display_init_out;
/* Enabled for auto PLL calculation or to enable
* additional clocks
*/
if (pdata->pll_clk_func)
ret = pdata->pll_clk_func(1, &(panel->panel_info));
if (ret)
goto msm_display_init_out;
/* pinfo prepare */
if (pdata->panel_info.prepare) {
/* this is for edp which pinfo derived from edid */
ret = pdata->panel_info.prepare();
panel->fb.width = panel->panel_info.xres;
panel->fb.height = panel->panel_info.yres;
panel->fb.stride = panel->panel_info.xres;
panel->fb.bpp = panel->panel_info.bpp;
}
if (ret)
goto msm_display_init_out;
ret = msm_fb_alloc(&(panel->fb));
if (ret)
goto msm_display_init_out;
fbcon_setup(&(panel->fb));
display_image_on_screen();
if ((panel->dsi2HDMI_config) && (panel->panel_info.has_bridge_chip))
ret = panel->dsi2HDMI_config(&(panel->panel_info));
if (ret)
goto msm_display_init_out;
ret = msm_display_config();
if (ret)
goto msm_display_init_out;
ret = msm_display_on();
if (ret)
goto msm_display_init_out;
if (pdata->post_power_func)
ret = pdata->post_power_func(1);
if (ret)
goto msm_display_init_out;
/* Turn on backlight */
if (pdata->bl_func)
ret = pdata->bl_func(1);
if (ret)
goto msm_display_init_out;
msm_display_init_out:
return ret;
}
再调用,下面函数;
void display_image_on_screen(void)
{
#if DISPLAY_TYPE_MIPI
int fetch_image_from_partition();
dprintf(INFO, "display_image_on_screen-1\n");
if (fetch_image_from_partition() < 0) {
display_default_image_on_screen();
} else {
/* data has been put into the right place */
fbcon_flush();
}
#else
display_default_image_on_screen();
#endif
}
再调用显示logo函数:
void display_default_image_on_screen(void)
{
unsigned i = 0;
unsigned total_x;
unsigned total_y;
unsigned bytes_per_bpp;
unsigned image_base;
#if DISPLAY_TYPE_MIPI
char *image = NULL;
#endif
if (!config) {
dprintf(CRITICAL,"NULL configuration, image cannot be displayed\n");
return;
}
fbcon_clear(); // clear screen with Black color
total_x = config->width;
total_y = config->height;
bytes_per_bpp = ((config->bpp) / 8);
image_base = ((((total_y/2) - (SPLASH_IMAGE_HEIGHT / 2) - 1) *
(config->width)) + (total_x/2 - (SPLASH_IMAGE_WIDTH / 2)));
#if DISPLAY_TYPE_MIPI
#if ENABLE_WBC
image = (pm_appsbl_charging_in_progress() ? image_batt888 : imageBuffer_rgb888);
#else
image = imageBuffer_rgb888;
#endif
if (bytes_per_bpp == 3) {
for (i = 0; i < SPLASH_IMAGE_HEIGHT; i++) {
memcpy (config->base + ((image_base + (i * (config->width))) * bytes_per_bpp),
image + (i * SPLASH_IMAGE_WIDTH * bytes_per_bpp),
SPLASH_IMAGE_WIDTH * bytes_per_bpp);
}
}
fbcon_flush();
#if DISPLAY_MIPI_PANEL_NOVATEK_BLUE
if(is_cmd_mode_enabled())
mipi_dsi_cmd_mode_trigger();
#endif
#else
if (bytes_per_bpp == 2) {
for (i = 0; i < SPLASH_IMAGE_HEIGHT; i++) {
memcpy (config->base + ((image_base + (i * (config->width))) * bytes_per_bpp),
imageBuffer + (i * SPLASH_IMAGE_WIDTH * bytes_per_bpp),
SPLASH_IMAGE_WIDTH * bytes_per_bpp);
}
}
fbcon_flush();
#endif
}
在以上函数中,fbcon_clear() 是清屏。
fbcon_clear(); // clear screen with Black color
config->width; // screen total width
config->height // screen total high
image_base // 显示的screen的中心基准。
改变这个image_base 的中心基准值,可以改变图片的显示位置。