coreboot-kgpe-d16/src/mainboard/google/kukui/mainboard.c
Hung-Te Lin 9ede2ffee8 mb/google/kukui: Move panel description to CBFS files
The panel description may be pretty large (for example, 1.3k for BOE
TV101) due to init commands and we should only load the right config
when display is needed.

BUG=None
TEST=make -j; boots and see display on Krane.

Change-Id: I2560a11ecf7badfd0605ab189d57ec9456850f75
Signed-off-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/34877
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
2019-08-21 22:58:45 +00:00

199 lines
5.2 KiB
C

/*
* This file is part of the coreboot project.
*
* Copyright 2018 MediaTek 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.
*/
#include <assert.h>
#include <boardid.h>
#include <bootmode.h>
#include <cbfs.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 <string.h>
#include "panel.h"
static void configure_emmc(void)
{
const gpio_t emmc_pin[] = {
GPIO(MSDC0_DAT0), GPIO(MSDC0_DAT1),
GPIO(MSDC0_DAT2), GPIO(MSDC0_DAT3),
GPIO(MSDC0_DAT4), GPIO(MSDC0_DAT5),
GPIO(MSDC0_DAT6), GPIO(MSDC0_DAT7),
GPIO(MSDC0_CMD), GPIO(MSDC0_RSTB),
};
for (size_t i = 0; i < ARRAY_SIZE(emmc_pin); i++)
gpio_set_pull(emmc_pin[i], GPIO_PULL_ENABLE, GPIO_PULL_UP);
}
static void configure_usb(void)
{
setup_usb_host();
}
static void configure_audio(void)
{
/* Audio PWR*/
mtcmos_audio_power_on();
/* SoC I2S */
gpio_set_mode(GPIO(CAM_RST0), PAD_CAM_RST0_FUNC_I2S2_LRCK);
gpio_set_mode(GPIO(CAM_PDN1), PAD_CAM_PDN1_FUNC_I2S2_BCK);
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);
}
struct panel_description *get_panel_from_cbfs(struct panel_description *desc)
{
/* The CBFS name will be 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)
return NULL;
snprintf(cbfs_name, sizeof(cbfs_name), "panel-%s", desc->name);
if (cbfs_boot_load_file(cbfs_name, buffer.raw, sizeof(buffer),
CBFS_TYPE_STRUCT))
desc->s = &buffer.s;
else
printk(BIOS_ERR, "Missing %s in CBFS.\n", cbfs_name);
return desc->s ? desc : NULL;
}
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;
}
assert(panel->s);
const struct edid *edid = &panel->s->edid;
const char *name = edid->ascii_string;
if (name[0] == '\0')
name = "unknown name";
printk(BIOS_INFO, "%s: Found ID %d: '%s %s' %dx%d@%dHz\n", __func__,
panel_id, edid->manufacturer_name, name, edid->mode.ha,
edid->mode.va, edid->mode.refresh);
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->s->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->s->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->s->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();
}
static void mainboard_enable(struct device *dev)
{
dev->ops->init = &mainboard_init;
}
struct chip_operations mainboard_ops = {
.name = CONFIG_MAINBOARD_PART_NUMBER,
.enable_dev = mainboard_enable,
};