coreboot-kgpe-d16/src/mainboard/google/kukui/mainboard.c
Julius Werner 1f84b2c025 drivers/mipi: Make orientation a property of the mainboard, not panel
It doesn't make sense to store the orientation field directly in the
panel information structure, which is supposed to be reuseable between
different boards. The thing that determines orientation is how that
panel is built into the board in question, which only the board itself
can know. The same portrait panel could be rotated left to be used as
landscape in one board and rotated right to be used as landscape in
another. This patch moves the orientation field out of the panel
structure back into the mainboards to reflect this.

Signed-off-by: Julius Werner <jwerner@chromium.org>
Change-Id: If2b716aa4dae036515730c12961fdd8a9ac34753
Reviewed-on: https://review.coreboot.org/c/coreboot/+/57324
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
2021-09-02 21:43:11 +00:00

224 lines
5.6 KiB
C

/* SPDX-License-Identifier: GPL-2.0-only */
#include <assert.h>
#include <bl31.h>
#include <boardid.h>
#include <bootmode.h>
#include <cbfs.h>
#include <console/console.h>
#include <delay.h>
#include <device/device.h>
#include <ec/google/chromeec/ec.h>
#include <edid.h>
#include <framebuffer_info.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/spm.h>
#include <soc/usb.h>
#include <string.h>
#include "gpio.h"
#include "panel.h"
#include <arm-trusted-firmware/include/export/plat/mediatek/common/plat_params_exp.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);
}
static void configure_ec(void)
{
/* EC may need SKU ID to identify if it is clamshell or convertible. */
if (CONFIG(BOARD_GOOGLE_JACUZZI_COMMON))
google_chromeec_set_sku_id(sku_id());
}
/* 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(15);
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_load(cbfs_name, buffer.raw, sizeof(buffer)))
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 & 0x0F;
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 (CONFIG(DRIVER_ANALOGIX_ANX7625))
mipi_dsi_flags |= MIPI_DSI_MODE_EOT_PACKET |
MIPI_DSI_MODE_LINE_END;
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;
}
if (panel->post_power_on)
panel->post_power_on();
mtk_ddp_mode_set(edid);
struct fb_info *info = fb_new_framebuffer_info_from_edid(edid, 0);
if (info)
fb_set_orientation(info, panel->orientation);
return true;
}
static void register_reset_to_bl31(void)
{
static struct bl_aux_param_gpio param_reset = {
.h = { .type = BL_AUX_PARAM_MTK_RESET_GPIO },
.gpio = { .polarity = ARM_TF_GPIO_LEVEL_HIGH },
};
param_reset.gpio.index = GPIO_RESET.id;
register_bl31_aux_param(&param_reset.h);
}
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();
configure_ec();
if (spm_init())
printk(BIOS_ERR,
"SPM initialization failed, suspend/resume may fail.\n");
register_reset_to_bl31();
}
static void mainboard_enable(struct device *dev)
{
dev->ops->init = &mainboard_init;
}
struct chip_operations mainboard_ops = {
.enable_dev = mainboard_enable,
};