diff options
author | Yidi Lin <yidilin@chromium.org> | 2024-01-03 16:07:24 +0800 |
---|---|---|
committer | Felix Held <felix-coreboot@felixheld.de> | 2024-01-10 14:20:25 +0000 |
commit | ba604b558e3a4e9e53c948391bc86a7bc775e6b3 (patch) | |
tree | 9a179c8219bb842507b0c2f2ba3d1e2852d680e9 /src/soc/mediatek/common/display.c | |
parent | 7224999497634dbd4c15fc8b1cdd4d2d2b39fec2 (diff) |
soc/mediatek: Add common implementation to configure display
The sequences of configure_display() are similar on MediaTek platforms.
The sequences usually involve following steps:
1. Setup mtcmos for display hardware block.
- mtcmos_display_power_on()
- mtcmos_protect_display_bus()
2. Configure backlight pins
3. Power on the panel
- It also powers on the bridge in MIPI DSI to eDP case.
4. General initialization for DDP(display data path)
5. Initialize eDP/MIPI DSI accordingly,
- For eDP path, it calls mtk_edp_init() to get edid from the panel
and initializes eDP driver.
- For MIPI DSI path, the edid is retrieved either from the bridge or
from CBFS (the serializable data), and then initializes DSI driver.
6. Set framebuffer bits per pixel
7. Setup DDP mode
8. Setup panel orientation
This patch extracts geralt/display.c to mediatek/common/display.c and
refactors `struct panel_description` to generalize the display init
sequences. configure_display() is also renamed to mtk_display_init().
TEST=check FW screen on geralt.
Change-Id: I403bba8a826de5f3fb2ea96a5403725ff194164f
Signed-off-by: Yidi Lin <yidilin@chromium.org>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/79776
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/soc/mediatek/common/display.c')
-rw-r--r-- | src/soc/mediatek/common/display.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/src/soc/mediatek/common/display.c b/src/soc/mediatek/common/display.c new file mode 100644 index 0000000000..72b7fe04bd --- /dev/null +++ b/src/soc/mediatek/common/display.c @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <cbfs.h> +#include <console/console.h> +#include <delay.h> +#include <edid.h> +#include <framebuffer_info.h> +#include <soc/ddp.h> +#include <soc/display.h> +#include <soc/dptx.h> +#include <soc/dsi.h> +#include <soc/mtcmos.h> +#include <string.h> + +static struct panel_serializable_data *get_mipi_cmd_from_cbfs(struct panel_description *desc) +{ + /* + * The CBFS file name is panel-{MANUFACTURER}-${PANEL_NAME}, where MANUFACTURER is 3 + * characters and PANEL_NAME is usually 13 characters. + */ + char cbfs_name[64]; + static union { + u8 raw[4 * 1024]; /* Most panels only need < 2K. */ + struct panel_serializable_data s; + } buffer; + + if (!desc->name) { + printk(BIOS_ERR, "Missing panel CBFS file name.\n"); + return NULL; + } + + snprintf(cbfs_name, sizeof(cbfs_name), "panel-%s", desc->name); + if (cbfs_load(cbfs_name, buffer.raw, sizeof(buffer))) + return &buffer.s; + + printk(BIOS_ERR, "Missing %s in CBFS.\n", cbfs_name); + return NULL; +} + +int mtk_display_init(void) +{ + struct edid edid; + struct fb_info *info; + const char *name; + struct panel_description *panel = get_active_panel(); + + if (!panel || panel->disp_path == DISP_PATH_NONE) { + printk(BIOS_ERR, "%s: Failed to get the active panel\n", __func__); + return -1; + } + + printk(BIOS_INFO, "%s: Starting display initialization\n", __func__); + + mtcmos_display_power_on(); + mtcmos_protect_display_bus(); + + if (panel->configure_backlight) + panel->configure_backlight(); + if (panel->power_on) + panel->power_on(); + + mtk_ddp_init(); + + if (panel->disp_path == DISP_PATH_EDP) { + mdelay(200); + if (mtk_edp_init(&edid) < 0) { + printk(BIOS_ERR, "%s: Failed to initialize eDP\n", __func__); + return -1; + } + } else { + + struct panel_serializable_data *mipi_data = NULL; + + if (panel->get_edid) { + if (panel->get_edid(&edid) < 0) + return -1; + } else { + mipi_data = get_mipi_cmd_from_cbfs(panel); + if (!mipi_data) + return -1; + edid = mipi_data->edid; + } + + u32 mipi_dsi_flags = (MIPI_DSI_MODE_VIDEO | + MIPI_DSI_MODE_VIDEO_SYNC_PULSE | + MIPI_DSI_MODE_LPM | + MIPI_DSI_MODE_EOT_PACKET); + + if (mtk_dsi_init(mipi_dsi_flags, MIPI_DSI_FMT_RGB888, 4, &edid, + mipi_data ? mipi_data->init : NULL) < 0) { + printk(BIOS_ERR, "%s: Failed in DSI init\n", __func__); + return -1; + } + + if (panel->post_power_on && panel->post_power_on(&edid) < 0) { + printk(BIOS_ERR, "%s: Failed to post power on bridge\n", __func__); + return -1; + } + } + + name = edid.ascii_string; + if (name[0] == '\0') + name = "unknown name"; + printk(BIOS_INFO, "%s: '%s %s' %dx%d@%dHz\n", __func__, + edid.manufacturer_name, name, edid.mode.ha, edid.mode.va, + edid.mode.refresh); + + edid_set_framebuffer_bits_per_pixel(&edid, 32, 0); + + mtk_ddp_mode_set(&edid, panel->disp_path); + info = fb_new_framebuffer_info_from_edid(&edid, (uintptr_t)0); + if (info) + fb_set_orientation(info, panel->orientation); + + return 0; +} |