diff options
Diffstat (limited to 'src/soc/mediatek/common')
-rw-r--r-- | src/soc/mediatek/common/display.c | 116 | ||||
-rw-r--r-- | src/soc/mediatek/common/include/soc/display.h | 32 |
2 files changed, 148 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; +} 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 |