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 <hungte@chromium.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/32511 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Julius Werner <jwerner@chromium.org>
This commit is contained in:
parent
32ddc0d9f7
commit
2c307a0bed
|
@ -13,12 +13,22 @@
|
|||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <boardid.h>
|
||||
#include <bootmode.h>
|
||||
#include <console/console.h>
|
||||
#include <delay.h>
|
||||
#include <device/device.h>
|
||||
#include <edid.h>
|
||||
#include <gpio.h>
|
||||
#include <soc/ddp.h>
|
||||
#include <soc/dsi.h>
|
||||
#include <soc/gpio.h>
|
||||
#include <soc/mmu_operations.h>
|
||||
#include <soc/mtcmos.h>
|
||||
#include <soc/usb.h>
|
||||
|
||||
#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();
|
||||
|
|
|
@ -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 <edid.h>
|
||||
#include <soc/dsi.h>
|
||||
|
||||
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__ */
|
Loading…
Reference in New Issue