From 2c307a0bedfeecd932531387efcc4f66381f6d56 Mon Sep 17 00:00:00 2001 From: Hung-Te Lin Date: Wed, 20 Feb 2019 14:31:23 +0800 Subject: mb/google/kukui: Initialize display Many devices in Kukui family will be using MIPI panels, which needs hard-coded EDID and initialization commands. And because each device may have its own layout and ID, there should be very few devices sharing same panel configuration. As a result, we want to put panel data (EDID and init commands) into board-specific modules, provided by `get_panel_description` function. The panel numeric ID is identified by ADC 2, and is currently available as higher 4 bits of sku_id(). After ID is retrieved, the get_panel_description should return a reference to the EDID and table of init commands. The default implementation is to simply return NULL, and the data for real devices should be provided by panel_*.c in further commits. BUG=b:80501386,b:117254947 BRANCH=none TEST=boot correctly on Kukui Change-Id: I19213aee1ac0f69f42e73be9e5ab72394f412a01 Signed-off-by: Hung-Te Lin Reviewed-on: https://review.coreboot.org/c/coreboot/+/32511 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- src/mainboard/google/kukui/mainboard.c | 101 +++++++++++++++++++++++++++++++++ src/mainboard/google/kukui/panel.h | 59 +++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 src/mainboard/google/kukui/panel.h (limited to 'src') diff --git a/src/mainboard/google/kukui/mainboard.c b/src/mainboard/google/kukui/mainboard.c index 40b8a49c61..7bf2580751 100644 --- a/src/mainboard/google/kukui/mainboard.c +++ b/src/mainboard/google/kukui/mainboard.c @@ -13,12 +13,22 @@ * GNU General Public License for more details. */ +#include +#include +#include +#include #include +#include +#include +#include +#include #include #include #include #include +#include "panel.h" + static void configure_emmc(void) { const gpio_t emmc_pin[] = { @@ -49,8 +59,99 @@ static void configure_audio(void) gpio_set_mode(GPIO(CAM_PDN0), PAD_CAM_PDN0_FUNC_I2S2_MCK); gpio_set_mode(GPIO(EINT3), PAD_EINT3_FUNC_I2S3_DO); } + +/* Default implementation for boards without panels defined yet. */ +struct panel_description __weak *get_panel_description(int panel_id) +{ + printk(BIOS_ERR, "%s: ERROR: No panels defined for board: %s.\n", + __func__, CONFIG_MAINBOARD_PART_NUMBER); + return NULL; +} + +/* Set up backlight control pins as output pin and power-off by default */ +static void configure_panel_backlight(void) +{ + gpio_output(GPIO(PERIPHERAL_EN13), 0); + gpio_output(GPIO(DISP_PWM), 0); +} + +static void power_on_panel(struct panel_description *panel) +{ + if (panel->power_on) { + panel->power_on(); + return; + } + + /* Default power sequence for most panels. */ + gpio_output(GPIO_LCM_RST_1V8, 0); + gpio_output(GPIO_PPVARP_LCD_EN, 1); + gpio_output(GPIO_PPVARN_LCD_EN, 1); + gpio_output(GPIO_PP1800_LCM_EN, 1); + gpio_output(GPIO_PP3300_LCM_EN, 1); + mdelay(6); + gpio_output(GPIO_LCM_RST_1V8, 1); + mdelay(6); +} + +static struct panel_description *get_active_panel(void) +{ + /* TODO(hungte) Create a dedicated panel_id() in board_id.c */ + int panel_id = sku_id() >> 4; + + struct panel_description *panel = get_panel_description(panel_id); + if (!panel) { + printk(BIOS_ERR, "%s: Panel %d is not supported.\n", + __func__, panel_id); + return NULL; + } + const char *mode_name = panel->edid.mode.name; + const char *name = panel->edid.ascii_string; + if (name[0] == '\0') + name = "unknown name"; + printk(BIOS_INFO, "%s: Found ID %d: '%s' %s\n", __func__, + panel_id, name, mode_name ? mode_name : "(unknown mode)"); + return panel; +} + +static bool configure_display(void) +{ + struct panel_description *panel = get_active_panel(); + if (!panel) + return false; + + mtcmos_display_power_on(); + mtcmos_protect_display_bus(); + configure_panel_backlight(); + power_on_panel(panel); + + struct edid *edid = &panel->edid; + edid_set_framebuffer_bits_per_pixel(edid, 32, 0); + mtk_ddp_init(); + u32 mipi_dsi_flags = (MIPI_DSI_MODE_VIDEO | + MIPI_DSI_MODE_VIDEO_SYNC_PULSE | + MIPI_DSI_MODE_LPM); + if (mtk_dsi_init(mipi_dsi_flags, MIPI_DSI_FMT_RGB888, 4, edid, + panel->init) < 0) { + printk(BIOS_ERR, "%s: Failed in DSI init.\n", __func__); + return false; + } + mtk_ddp_mode_set(edid); + set_vbe_mode_info_valid(edid, 0); + set_vbe_framebuffer_orientation(panel->orientation); + return true; +} + static void mainboard_init(struct device *dev) { + if (display_init_required()) { + printk(BIOS_INFO, "%s: Starting display init.\n", __func__); + if (!configure_display()) + printk(BIOS_ERR, "%s: Failed to init display.\n", + __func__); + } else { + printk(BIOS_INFO, "%s: Skipped display init.\n", __func__); + } + configure_emmc(); configure_usb(); configure_audio(); diff --git a/src/mainboard/google/kukui/panel.h b/src/mainboard/google/kukui/panel.h new file mode 100644 index 0000000000..e68567ddd4 --- /dev/null +++ b/src/mainboard/google/kukui/panel.h @@ -0,0 +1,59 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2019 Huaqin Telecom Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __MAINBOARD_GOOGLE_KUKUI_PANEL_H__ +#define __MAINBOARD_GOOGLE_KUKUI_PANEL_H__ + +#include +#include + +struct panel_description { + struct edid edid; /* edid info of this panel */ + enum lb_fb_orientation orientation; /* panel orientation */ + void (*power_on)(void); /* Callback to turn on panel */ + struct lcm_init_command init[]; /* table of init commands */ +}; + +/* Returns the panel description from given ID. */ +extern struct panel_description *get_panel_description(int panel_id); + +#define INIT_DCS_CMD(...) { \ + .cmd = LCM_DCS_CMD, \ + .len = sizeof((u8[]){__VA_ARGS__}), \ + .data = {__VA_ARGS__} } + +#define INIT_GENERIC_CMD(...) { \ + .cmd = LCM_GENERIC_CMD, \ + .len = sizeof((u8[]){__VA_ARGS__}), \ + .data = {__VA_ARGS__} } + +#define INIT_DELAY_CMD(delay) { \ + .cmd = LCM_DELAY_CMD,\ + .len = delay, } + +#define INIT_END_CMD { .cmd = LCM_END_CMD, } + +/* GPIO names */ +#define GPIO_LCM_RST_1V8 GPIO(LCM_RST) /* 45 */ +#define GPIO_MIPIBRDG_PWRDN_L_1V8 GPIO(LCM_RST) /* 45 */ +#define GPIO_MIPIBRDG_RST_L_1V8 GPIO(BPI_BUS3) /* 73 */ +#define GPIO_PP1200_MIPIBRDG_EN GPIO(BPI_OLAT1) /* 54 */ +#define GPIO_PP1800_LCM_EN GPIO(SIM2_SRST) /* 36 */ +#define GPIO_PP3300_LCM_EN GPIO(SIM2_SIO) /* 35 */ +#define GPIO_PPVARN_LCD_EN GPIO(PERIPHERAL_EN9) /* 166 */ +#define GPIO_PPVARP_LCD_EN GPIO(MISC_BSI_CK_3) /* 66 */ +#define GPIO_VDDIO_MIPIBRDG_EN GPIO(SIM2_SCLK) /* 37 */ + +#endif /* __MAINBOARD_GOOGLE_KUKUI_PANEL_H__ */ -- cgit v1.2.3