diff options
Diffstat (limited to 'src/soc')
-rw-r--r-- | src/soc/mediatek/common/display.c | 116 | ||||
-rw-r--r-- | src/soc/mediatek/common/include/soc/display.h | 32 | ||||
-rw-r--r-- | src/soc/mediatek/mt8188/Makefile.inc | 1 | ||||
-rw-r--r-- | src/soc/mediatek/mt8188/include/soc/ddp.h | 10 |
4 files changed, 150 insertions, 9 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; +} diff --git a/src/soc/mediatek/common/include/soc/display.h b/src/soc/mediatek/common/include/soc/display.h new file mode 100644 index 0000000000..61bc21fc98 --- /dev/null +++ b/src/soc/mediatek/common/include/soc/display.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __SOC_MEDIATEK_COMMON_DISPLAY_H__ +#define __SOC_MEDIATEK_COMMON_DISPLAY_H__ + +#include <commonlib/coreboot_tables.h> +#include <mipi/panel.h> + +enum disp_path_sel { + DISP_PATH_NONE = 0, + DISP_PATH_EDP, + DISP_PATH_MIPI, +}; + +struct panel_description { + const char *name; + void (*configure_backlight)(void); + void (*power_on)(void); + int (*get_edid)(struct edid *edid); + int (*post_power_on)(const struct edid *edid); + enum lb_fb_orientation orientation; + enum disp_path_sel disp_path; + bool pwm_ctrl_gpio; +}; + +int mtk_display_init(void); +struct panel_description *get_active_panel(void); + +void mtk_ddp_init(void); +void mtk_ddp_mode_set(const struct edid *edid, enum disp_path_sel path); + +#endif diff --git a/src/soc/mediatek/mt8188/Makefile.inc b/src/soc/mediatek/mt8188/Makefile.inc index 6a643b0057..4731fab14c 100644 --- a/src/soc/mediatek/mt8188/Makefile.inc +++ b/src/soc/mediatek/mt8188/Makefile.inc @@ -37,6 +37,7 @@ ramstage-y += cpu_input_gating.c ramstage-y += ../common/ddp.c ddp.c ramstage-y += ../common/devapc.c devapc.c ramstage-y += ../common/dfd.c +ramstage-y += ../common/display.c ramstage-y += ../common/dp/dp_intf.c ../common/dp/dptx.c ../common/dp/dptx_hal.c dp_intf.c ramstage-y += ../common/dpm.c ramstage-$(CONFIG_DPM_FOUR_CHANNEL) += ../common/dpm_4ch.c diff --git a/src/soc/mediatek/mt8188/include/soc/ddp.h b/src/soc/mediatek/mt8188/include/soc/ddp.h index da14a2c4e7..94fdb810a7 100644 --- a/src/soc/mediatek/mt8188/include/soc/ddp.h +++ b/src/soc/mediatek/mt8188/include/soc/ddp.h @@ -5,6 +5,7 @@ #include <soc/addressmap.h> #include <soc/ddp_common.h> +#include <soc/display.h> #include <types.h> #define MAIN_PATH_OVL_NR 1 @@ -282,13 +283,4 @@ enum { SMI_LARB_PORT_L0_OVL_RDMA0 = 0xF88, }; -enum disp_path_sel { - DISP_PATH_NONE = 0, - DISP_PATH_EDP, - DISP_PATH_MIPI, -}; - -void mtk_ddp_init(void); -void mtk_ddp_mode_set(const struct edid *edid, enum disp_path_sel); - #endif |