jitao shi has uploaded this change for review.

View Change

WIP: temp for dispaly conflick

Temp
squlash patches
google/krane: Add Panel TV101WUM-NL6 support.
google/kukui: Elaborate panel support for Kukui family boards.
google/kukui: Enable config for coreboot display
mediatek/mt8183: add dsi driver for mt8183
google/kukui: Enable display on internal panel
mediatek/mt8183: Add display driver

Change-Id: I09d127ab491bca98f3a9c9b7d4ad4b09674c963d
---
D 3rdparty/blobs
M src/mainboard/google/kukui/Kconfig
M src/mainboard/google/kukui/Makefile.inc
A src/mainboard/google/kukui/display.c
A src/mainboard/google/kukui/display.h
M src/mainboard/google/kukui/mainboard.c
A src/mainboard/google/kukui/panel_krane.c
A src/mainboard/google/kukui/panel_kukui.c
M src/soc/mediatek/mt8183/Makefile.inc
A src/soc/mediatek/mt8183/ddp.c
A src/soc/mediatek/mt8183/dsi.c
M src/soc/mediatek/mt8183/include/soc/addressmap.h
A src/soc/mediatek/mt8183/include/soc/ddp.h
A src/soc/mediatek/mt8183/include/soc/dsi.h
14 files changed, 2,372 insertions(+), 1 deletion(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/06/33106/1
diff --git a/3rdparty/blobs b/3rdparty/blobs
deleted file mode 160000
index ca6cfcd..0000000
--- a/3rdparty/blobs
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit ca6cfcdbe1cdeb38c2622ee2e5236cc4657e3377
diff --git a/src/mainboard/google/kukui/Kconfig b/src/mainboard/google/kukui/Kconfig
index 6831d1e..5893722 100644
--- a/src/mainboard/google/kukui/Kconfig
+++ b/src/mainboard/google/kukui/Kconfig
@@ -37,6 +37,9 @@
select EC_GOOGLE_CHROMEEC_SPI
select MAINBOARD_HAS_SPI_TPM_CR50 if VBOOT
select MAINBOARD_HAS_TPM2 if VBOOT
+ select MAINBOARD_HAS_NATIVE_VGA_INIT
+ select MAINBOARD_FORCE_NATIVE_VGA_INIT
+ select HAVE_LINEAR_FRAMEBUFFER

config MAINBOARD_DIR
string
diff --git a/src/mainboard/google/kukui/Makefile.inc b/src/mainboard/google/kukui/Makefile.inc
index a0556c1..8a023a5 100644
--- a/src/mainboard/google/kukui/Makefile.inc
+++ b/src/mainboard/google/kukui/Makefile.inc
@@ -22,6 +22,9 @@

ramstage-y += boardid.c
ramstage-y += chromeos.c
+ramstage-y += display.c
+ramstage-$(CONFIG_BOARD_GOOGLE_KUKUI) += panel_kukui.c
+ramstage-$(CONFIG_BOARD_GOOGLE_KRANE) += panel_krane.c
ramstage-y += mainboard.c
ramstage-y += memlayout.ld
ramstage-y += reset.c
diff --git a/src/mainboard/google/kukui/display.c b/src/mainboard/google/kukui/display.c
new file mode 100644
index 0000000..c7f7f91
--- /dev/null
+++ b/src/mainboard/google/kukui/display.c
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+#include <console/console.h>
+#include <delay.h>
+#include <device/device.h>
+#include <edid.h>
+#include <gpio.h>
+#include <soc/auxadc.h>
+#include <soc/ddp.h>
+#include <soc/dsi.h>
+#include <soc/gpio.h>
+#include <boardid.h>
+
+#include "display.h"
+#include "gpio.h"
+
+static void _display_startup(struct edid *edid,
+ struct lcm_init_table *init_table,
+ u32 init_table_size)
+{
+ int ret = 0;
+ u32 mipi_dsi_flags;
+
+ if ((edid == NULL) || (init_table == NULL)) {
+ printk(BIOS_ERR, "%s: wrong parameters\n", __func__);
+ return;
+ }
+
+ mipi_dsi_flags = MIPI_DSI_MODE_VIDEO |
+ MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_LPM;
+
+ edid_set_framebuffer_bits_per_pixel(edid, 32, 0);
+
+ mtk_ddp_init();
+ ret = mtk_dsi_init(mipi_dsi_flags, MIPI_DSI_FMT_RGB888, 4,
+ false, edid, init_table, init_table_size);
+
+ if (ret < 0) {
+ printk(BIOS_ERR, "dsi init fail\n");
+ return;
+ }
+
+ mtk_ddp_mode_set(edid);
+
+ set_vbe_mode_info_valid(edid, (uintptr_t)0);
+}
+
+static struct edid *get_edid(struct board_display_intf *intf)
+{
+ struct panel_info *info = intf->cur_panel_info;
+
+ if (info)
+ return info->edid;
+ return NULL;
+}
+
+static struct lcm_init_table *get_panel_init_table(struct board_display_intf
+ *intf, u32 *table_size)
+{
+ struct panel_info *info = intf->cur_panel_info;
+
+ if (info) {
+ *table_size = info->table_size;
+ return info->init_table;
+ }
+
+ *table_size = 0;
+ return NULL;
+}
+
+static const char *get_panel_name(struct board_display_intf *intf)
+{
+ struct panel_info *info = intf->cur_panel_info;
+
+ if (info)
+ return info->panel_name;
+ return NULL;
+}
+
+/* Exported Functions */
+
+struct board_display_intf *get_current_display_intf(void)
+{
+ return &panel_display_intf;
+}
+
+int update_panel_info(struct board_display_intf *intf)
+{
+ int i;
+ union panel_id id = intf->get_panel_id(intf);
+
+ if (intf->is_panel_id_valid(id)) {
+ for (i = 0; i < intf->all_panel_info_size; ++i) {
+ if (id.value == intf->all_panel_info[i].disp_id.value) {
+ intf->cur_panel_info = &intf->all_panel_info[i];
+ return 0;
+ }
+ }
+ }
+ return -1;
+}
+
+void display_startup(struct board_display_intf *intf)
+{
+ struct edid *edid;
+ u32 init_table_size;
+ struct lcm_init_table *init_table;
+
+ edid = get_edid(intf);
+ init_table = get_panel_init_table(intf, &init_table_size);
+ printk(BIOS_INFO, "%s: name:%s init_table_size:%d\n",
+ __func__, get_panel_name(intf), init_table_size);
+ _display_startup(edid, init_table, init_table_size);
+}
diff --git a/src/mainboard/google/kukui/display.h b/src/mainboard/google/kukui/display.h
new file mode 100644
index 0000000..d7b8bd9
--- /dev/null
+++ b/src/mainboard/google/kukui/display.h
@@ -0,0 +1,99 @@
+/*
+ * 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_DISPLAY_H__
+#define __MAINBOARD_GOOGLE_DISPLAY_H__
+
+#include <soc/dsi.h>
+#include <soc/gpio.h>
+
+#define MAKE_AS_A_STRING(arg) #arg
+
+enum kukui_panel_id {
+ PANEL_KUKUI_FIRST = 0,
+ PANEL_KUKUI_INNOLUX = 0,
+ PANEL_KUKUI_P097PFG_SSD2858,
+ PANEL_KUKUI_UNKNOWN,
+ PANEL_KUKUI_COUNT,
+ PANEL_KUKUI_UNINITIALIZED
+};
+
+enum krane_panel_id {
+ PANEL_KRANE_FIRST = 0,
+ PANEL_KRANE_BOE_TV101WUM_NL6,
+ PANEL_KRANE_UNKNOWN,
+ PANEL_KRANE_COUNT,
+ PANEL_KRANE_UNINITIALIZED
+};
+
+
+union panel_id {
+ enum kukui_panel_id kukui_panel;
+ enum krane_panel_id krane_panel;
+ int value;
+};
+
+struct panel_info {
+ union panel_id disp_id; /* the ID for panel */
+ const char *panel_name; /* display panel name */
+ int voltage; /* voltage of LCM_ID */
+ struct edid *edid; /* edid info of this panel */
+ struct lcm_init_table *init_table; /* init command table */
+ u32 table_size; /* init command table size */
+};
+
+#define PANEL(_panel_id, _voltage, _edid, _init_table) \
+ { \
+ .disp_id = {_panel_id},\
+ .panel_name = MAKE_AS_A_STRING(_panel_id),\
+ .voltage = _voltage,\
+ .edid = &_edid,\
+ .init_table = _init_table,\
+ .table_size = ARRAY_SIZE(_init_table)} \
+
+
+struct board_display_intf {
+ const char *board; /* board name */
+ struct panel_info *all_panel_info; /* all supported panel info */
+ u32 all_panel_info_size; /* num of supported panel */
+ /*
+ * Runtime member
+ */
+ struct panel_info *cur_panel_info; /* detected panel info */
+ /*
+ * board related functions
+ */
+
+ union panel_id (*get_panel_id)(struct board_display_intf *intf);
+ bool (*is_panel_id_valid)(union panel_id id);
+ int (*backlight)(struct board_display_intf *intf);
+ int (*power)(struct board_display_intf *intf);
+};
+
+/*
+ * Exported functions
+ */
+
+struct board_display_intf *get_current_display_intf(void);
+int update_panel_info(struct board_display_intf *intf);
+void display_startup(struct board_display_intf *intf);
+
+
+/*
+ * Panel Interface for boards
+ */
+extern struct board_display_intf panel_display_intf;
+
+#endif
diff --git a/src/mainboard/google/kukui/mainboard.c b/src/mainboard/google/kukui/mainboard.c
index 7a31909..4e7c20b 100644
--- a/src/mainboard/google/kukui/mainboard.c
+++ b/src/mainboard/google/kukui/mainboard.c
@@ -13,8 +13,17 @@
* 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 <soc/bl31_plat_params.h>
+#include "display.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>
@@ -70,6 +79,28 @@

static void mainboard_init(struct device *dev)
{
+ struct board_display_intf *cur_disp_intf = NULL;
+
+ if (display_init_required()) {
+ printk(BIOS_INFO, "Starting display init.\n");
+
+ cur_disp_intf = get_current_display_intf();
+ if (cur_disp_intf && !update_panel_info(cur_disp_intf)) {
+ mtcmos_display_power_on();
+ mtcmos_protect_display_bus();
+
+ cur_disp_intf->backlight(cur_disp_intf);
+ cur_disp_intf->power(cur_disp_intf);
+ display_startup(cur_disp_intf);
+ } else {
+ printk(BIOS_ERR,
+ "%s: Can't find correct display interface\n",
+ __func__);
+ }
+
+ } else
+ printk(BIOS_ERR, "Skipping display init.\n");
+
configure_emmc();
configure_usb();
configure_audio();
diff --git a/src/mainboard/google/kukui/panel_krane.c b/src/mainboard/google/kukui/panel_krane.c
new file mode 100644
index 0000000..b6fa9a5
--- /dev/null
+++ b/src/mainboard/google/kukui/panel_krane.c
@@ -0,0 +1,409 @@
+/*
+ * 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.
+ */
+
+#include <console/console.h>
+#include <delay.h>
+#include <device/device.h>
+#include <edid.h>
+#include <gpio.h>
+#include <soc/auxadc.h>
+#include <soc/ddp.h>
+#include <soc/dsi.h>
+#include <soc/gpio.h>
+#include <boardid.h>
+
+#include "display.h"
+#include "gpio.h"
+
+static struct edid krane_boe_tv101wum_nl6_edid = {
+ .panel_bits_per_color = 8,
+ .panel_bits_per_pixel = 24,
+ .mode = {
+ .name = "1200x1920@60Hz",
+ .pixel_clock = 159425,
+ .lvds_dual_channel = 0,
+ .refresh = 60,
+ .ha = 1200, .hbl = 164, .hso = 100, .hspw = 24, .hborder = 0,
+ .va = 1920, .vbl = 28, .vso = 10, .vspw = 4, .vborder = 0,
+ .phsync = '-', .pvsync = '-',
+ .x_mm = 135, .y_mm = 216,
+ },
+};
+
+struct lcm_init_table boe_tv101wum_nl6_init_cmd[] = {
+ {INIT_DCS_CMD, 1, { 0x10 } },
+ {DELAY_CMD, 34, {} },
+ {INIT_DCS_CMD, 2, { 0xB0, 0x05 } },
+ {INIT_DCS_CMD, 2, { 0xB1, 0xE5 } },
+ {INIT_DCS_CMD, 2, { 0xB3, 0x52 } },
+ {INIT_DCS_CMD, 2, { 0xB0, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xB3, 0x88 } },
+ {INIT_DCS_CMD, 2, { 0xB0, 0x04 } },
+ {INIT_DCS_CMD, 2, { 0xB8, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xB0, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xB6, 0x03 } },
+ {INIT_DCS_CMD, 2, { 0xBA, 0x8B } },
+ {INIT_DCS_CMD, 2, { 0xBF, 0x1A } },
+ {INIT_DCS_CMD, 2, { 0xC0, 0x0F } },
+ {INIT_DCS_CMD, 2, { 0xC2, 0x0C } },
+ {INIT_DCS_CMD, 2, { 0xC3, 0x02 } },
+ {INIT_DCS_CMD, 2, { 0xC4, 0x0C } },
+ {INIT_DCS_CMD, 2, { 0xC5, 0x02 } },
+ {INIT_DCS_CMD, 2, { 0xB0, 0x01 } },
+ {INIT_DCS_CMD, 2, { 0xE0, 0x26 } },
+ {INIT_DCS_CMD, 2, { 0xE1, 0x26 } },
+ {INIT_DCS_CMD, 2, { 0xDC, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xDD, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xCC, 0x26 } },
+ {INIT_DCS_CMD, 2, { 0xCD, 0x26 } },
+ {INIT_DCS_CMD, 2, { 0xC8, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xC9, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xD2, 0x03 } },
+ {INIT_DCS_CMD, 2, { 0xD3, 0x03 } },
+ {INIT_DCS_CMD, 2, { 0xE6, 0x04 } },
+ {INIT_DCS_CMD, 2, { 0xE7, 0x04 } },
+ {INIT_DCS_CMD, 2, { 0xC4, 0x09 } },
+ {INIT_DCS_CMD, 2, { 0xC5, 0x09 } },
+ {INIT_DCS_CMD, 2, { 0xD8, 0x0A } },
+ {INIT_DCS_CMD, 2, { 0xD9, 0x0A } },
+ {INIT_DCS_CMD, 2, { 0xC2, 0x0B } },
+ {INIT_DCS_CMD, 2, { 0xC3, 0x0B } },
+ {INIT_DCS_CMD, 2, { 0xD6, 0x0C } },
+ {INIT_DCS_CMD, 2, { 0xD7, 0x0C } },
+ {INIT_DCS_CMD, 2, { 0xC0, 0x05 } },
+ {INIT_DCS_CMD, 2, { 0xC1, 0x05 } },
+ {INIT_DCS_CMD, 2, { 0xD4, 0x06 } },
+ {INIT_DCS_CMD, 2, { 0xD5, 0x06 } },
+ {INIT_DCS_CMD, 2, { 0xCA, 0x07 } },
+ {INIT_DCS_CMD, 2, { 0xCB, 0x07 } },
+ {INIT_DCS_CMD, 2, { 0xDE, 0x08 } },
+ {INIT_DCS_CMD, 2, { 0xDF, 0x08 } },
+ {INIT_DCS_CMD, 2, { 0xB0, 0x02 } },
+ {INIT_DCS_CMD, 2, { 0xC0, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xC1, 0x0D } },
+ {INIT_DCS_CMD, 2, { 0xC2, 0x17 } },
+ {INIT_DCS_CMD, 2, { 0xC3, 0x26 } },
+ {INIT_DCS_CMD, 2, { 0xC4, 0x31 } },
+ {INIT_DCS_CMD, 2, { 0xC5, 0x1C } },
+ {INIT_DCS_CMD, 2, { 0xC6, 0x2C } },
+ {INIT_DCS_CMD, 2, { 0xC7, 0x33 } },
+ {INIT_DCS_CMD, 2, { 0xC8, 0x31 } },
+ {INIT_DCS_CMD, 2, { 0xC9, 0x37 } },
+ {INIT_DCS_CMD, 2, { 0xCA, 0x37 } },
+ {INIT_DCS_CMD, 2, { 0xCB, 0x37 } },
+ {INIT_DCS_CMD, 2, { 0xCC, 0x39 } },
+ {INIT_DCS_CMD, 2, { 0xCD, 0x2E } },
+ {INIT_DCS_CMD, 2, { 0xCE, 0x2F } },
+ {INIT_DCS_CMD, 2, { 0xCF, 0x2F } },
+ {INIT_DCS_CMD, 2, { 0xD0, 0x07 } },
+ {INIT_DCS_CMD, 2, { 0xD2, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xD3, 0x0D } },
+ {INIT_DCS_CMD, 2, { 0xD4, 0x17 } },
+ {INIT_DCS_CMD, 2, { 0xD5, 0x26 } },
+ {INIT_DCS_CMD, 2, { 0xD6, 0x31 } },
+ {INIT_DCS_CMD, 2, { 0xD7, 0x3F } },
+ {INIT_DCS_CMD, 2, { 0xD8, 0x3F } },
+ {INIT_DCS_CMD, 2, { 0xD9, 0x3F } },
+ {INIT_DCS_CMD, 2, { 0xDA, 0x3F } },
+ {INIT_DCS_CMD, 2, { 0xDB, 0x37 } },
+ {INIT_DCS_CMD, 2, { 0xDC, 0x37 } },
+ {INIT_DCS_CMD, 2, { 0xDD, 0x37 } },
+ {INIT_DCS_CMD, 2, { 0xDE, 0x39 } },
+ {INIT_DCS_CMD, 2, { 0xDF, 0x2E } },
+ {INIT_DCS_CMD, 2, { 0xE0, 0x2F } },
+ {INIT_DCS_CMD, 2, { 0xE1, 0x2F } },
+ {INIT_DCS_CMD, 2, { 0xE2, 0x07 } },
+ {INIT_DCS_CMD, 2, { 0xB0, 0x03 } },
+ {INIT_DCS_CMD, 2, { 0xC8, 0x0B } },
+ {INIT_DCS_CMD, 2, { 0xC9, 0x07 } },
+ {INIT_DCS_CMD, 2, { 0xC3, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xE7, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xC5, 0x2A } },
+ {INIT_DCS_CMD, 2, { 0xDE, 0x2A } },
+ {INIT_DCS_CMD, 2, { 0xCA, 0x43 } },
+ {INIT_DCS_CMD, 2, { 0xC9, 0x07 } },
+ {INIT_DCS_CMD, 2, { 0xE4, 0xC0 } },
+ {INIT_DCS_CMD, 2, { 0xE5, 0x0D } },
+ {INIT_DCS_CMD, 2, { 0xCB, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xB0, 0x06 } },
+ {INIT_DCS_CMD, 2, { 0xB8, 0xA5 } },
+ {INIT_DCS_CMD, 2, { 0xC0, 0xA5 } },
+ {INIT_DCS_CMD, 2, { 0xC7, 0x0F } },
+ {INIT_DCS_CMD, 2, { 0xD5, 0x32 } },
+ {INIT_DCS_CMD, 2, { 0xB8, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xC0, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xBC, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xB0, 0x07 } },
+ {INIT_DCS_CMD, 2, { 0xB1, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xB2, 0x02 } },
+ {INIT_DCS_CMD, 2, { 0xB3, 0x0F } },
+ {INIT_DCS_CMD, 2, { 0xB4, 0x25 } },
+ {INIT_DCS_CMD, 2, { 0xB5, 0x39 } },
+ {INIT_DCS_CMD, 2, { 0xB6, 0x4E } },
+ {INIT_DCS_CMD, 2, { 0xB7, 0x72 } },
+ {INIT_DCS_CMD, 2, { 0xB8, 0x97 } },
+ {INIT_DCS_CMD, 2, { 0xB9, 0xDC } },
+ {INIT_DCS_CMD, 2, { 0xBA, 0x22 } },
+ {INIT_DCS_CMD, 2, { 0xBB, 0xA4 } },
+ {INIT_DCS_CMD, 2, { 0xBC, 0x2B } },
+ {INIT_DCS_CMD, 2, { 0xBD, 0x2F } },
+ {INIT_DCS_CMD, 2, { 0xBE, 0xA9 } },
+ {INIT_DCS_CMD, 2, { 0xBF, 0x25 } },
+ {INIT_DCS_CMD, 2, { 0xC0, 0x61 } },
+ {INIT_DCS_CMD, 2, { 0xC1, 0x97 } },
+ {INIT_DCS_CMD, 2, { 0xC2, 0xB2 } },
+ {INIT_DCS_CMD, 2, { 0xC3, 0xCD } },
+ {INIT_DCS_CMD, 2, { 0xC4, 0xD9 } },
+ {INIT_DCS_CMD, 2, { 0xC5, 0xE7 } },
+ {INIT_DCS_CMD, 2, { 0xC6, 0xF4 } },
+ {INIT_DCS_CMD, 2, { 0xC7, 0xFA } },
+ {INIT_DCS_CMD, 2, { 0xC8, 0xFC } },
+ {INIT_DCS_CMD, 2, { 0xC9, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xCA, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xCB, 0x16 } },
+ {INIT_DCS_CMD, 2, { 0xCC, 0xAF } },
+ {INIT_DCS_CMD, 2, { 0xCD, 0xFF } },
+ {INIT_DCS_CMD, 2, { 0xCE, 0xFF } },
+ {INIT_DCS_CMD, 2, { 0xB0, 0x08 } },
+ {INIT_DCS_CMD, 2, { 0xB1, 0x04 } },
+ {INIT_DCS_CMD, 2, { 0xB2, 0x05 } },
+ {INIT_DCS_CMD, 2, { 0xB3, 0x11 } },
+ {INIT_DCS_CMD, 2, { 0xB4, 0x24 } },
+ {INIT_DCS_CMD, 2, { 0xB5, 0x39 } },
+ {INIT_DCS_CMD, 2, { 0xB6, 0x4F } },
+ {INIT_DCS_CMD, 2, { 0xB7, 0x72 } },
+ {INIT_DCS_CMD, 2, { 0xB8, 0x98 } },
+ {INIT_DCS_CMD, 2, { 0xB9, 0xDC } },
+ {INIT_DCS_CMD, 2, { 0xBA, 0x23 } },
+ {INIT_DCS_CMD, 2, { 0xBB, 0xA6 } },
+ {INIT_DCS_CMD, 2, { 0xBC, 0x2C } },
+ {INIT_DCS_CMD, 2, { 0xBD, 0x30 } },
+ {INIT_DCS_CMD, 2, { 0xBE, 0xAA } },
+ {INIT_DCS_CMD, 2, { 0xBF, 0x26 } },
+ {INIT_DCS_CMD, 2, { 0xC0, 0x62 } },
+ {INIT_DCS_CMD, 2, { 0xC1, 0x9B } },
+ {INIT_DCS_CMD, 2, { 0xC2, 0xB5 } },
+ {INIT_DCS_CMD, 2, { 0xC3, 0xCF } },
+ {INIT_DCS_CMD, 2, { 0xC4, 0xDB } },
+ {INIT_DCS_CMD, 2, { 0xC5, 0xE8 } },
+ {INIT_DCS_CMD, 2, { 0xC6, 0xF5 } },
+ {INIT_DCS_CMD, 2, { 0xC7, 0xFA } },
+ {INIT_DCS_CMD, 2, { 0xC8, 0xFC } },
+ {INIT_DCS_CMD, 2, { 0xC9, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xCA, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xCB, 0x16 } },
+ {INIT_DCS_CMD, 2, { 0xCC, 0xAF } },
+ {INIT_DCS_CMD, 2, { 0xCD, 0xFF } },
+ {INIT_DCS_CMD, 2, { 0xCE, 0xFF } },
+ {INIT_DCS_CMD, 2, { 0xB0, 0x09 } },
+ {INIT_DCS_CMD, 2, { 0xB1, 0x04 } },
+ {INIT_DCS_CMD, 2, { 0xB2, 0x02 } },
+ {INIT_DCS_CMD, 2, { 0xB3, 0x16 } },
+ {INIT_DCS_CMD, 2, { 0xB4, 0x24 } },
+ {INIT_DCS_CMD, 2, { 0xB5, 0x3B } },
+ {INIT_DCS_CMD, 2, { 0xB6, 0x4F } },
+ {INIT_DCS_CMD, 2, { 0xB7, 0x73 } },
+ {INIT_DCS_CMD, 2, { 0xB8, 0x99 } },
+ {INIT_DCS_CMD, 2, { 0xB9, 0xE0 } },
+ {INIT_DCS_CMD, 2, { 0xBA, 0x26 } },
+ {INIT_DCS_CMD, 2, { 0xBB, 0xAD } },
+ {INIT_DCS_CMD, 2, { 0xBC, 0x36 } },
+ {INIT_DCS_CMD, 2, { 0xBD, 0x3A } },
+ {INIT_DCS_CMD, 2, { 0xBE, 0xAE } },
+ {INIT_DCS_CMD, 2, { 0xBF, 0x2A } },
+ {INIT_DCS_CMD, 2, { 0xC0, 0x66 } },
+ {INIT_DCS_CMD, 2, { 0xC1, 0x9E } },
+ {INIT_DCS_CMD, 2, { 0xC2, 0xB8 } },
+ {INIT_DCS_CMD, 2, { 0xC3, 0xD1 } },
+ {INIT_DCS_CMD, 2, { 0xC4, 0xDD } },
+ {INIT_DCS_CMD, 2, { 0xC5, 0xE9 } },
+ {INIT_DCS_CMD, 2, { 0xC6, 0xF6 } },
+ {INIT_DCS_CMD, 2, { 0xC7, 0xFA } },
+ {INIT_DCS_CMD, 2, { 0xC8, 0xFC } },
+ {INIT_DCS_CMD, 2, { 0xC9, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xCA, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xCB, 0x16 } },
+ {INIT_DCS_CMD, 2, { 0xCC, 0xAF } },
+ {INIT_DCS_CMD, 2, { 0xCD, 0xFF } },
+ {INIT_DCS_CMD, 2, { 0xCE, 0xFF } },
+ {INIT_DCS_CMD, 2, { 0xB0, 0x0A } },
+ {INIT_DCS_CMD, 2, { 0xB1, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xB2, 0x02 } },
+ {INIT_DCS_CMD, 2, { 0xB3, 0x0F } },
+ {INIT_DCS_CMD, 2, { 0xB4, 0x25 } },
+ {INIT_DCS_CMD, 2, { 0xB5, 0x39 } },
+ {INIT_DCS_CMD, 2, { 0xB6, 0x4E } },
+ {INIT_DCS_CMD, 2, { 0xB7, 0x72 } },
+ {INIT_DCS_CMD, 2, { 0xB8, 0x97 } },
+ {INIT_DCS_CMD, 2, { 0xB9, 0xDC } },
+ {INIT_DCS_CMD, 2, { 0xBA, 0x22 } },
+ {INIT_DCS_CMD, 2, { 0xBB, 0xA4 } },
+ {INIT_DCS_CMD, 2, { 0xBC, 0x2B } },
+ {INIT_DCS_CMD, 2, { 0xBD, 0x2F } },
+ {INIT_DCS_CMD, 2, { 0xBE, 0xA9 } },
+ {INIT_DCS_CMD, 2, { 0xBF, 0x25 } },
+ {INIT_DCS_CMD, 2, { 0xC0, 0x61 } },
+ {INIT_DCS_CMD, 2, { 0xC1, 0x97 } },
+ {INIT_DCS_CMD, 2, { 0xC2, 0xB2 } },
+ {INIT_DCS_CMD, 2, { 0xC3, 0xCD } },
+ {INIT_DCS_CMD, 2, { 0xC4, 0xD9 } },
+ {INIT_DCS_CMD, 2, { 0xC5, 0xE7 } },
+ {INIT_DCS_CMD, 2, { 0xC6, 0xF4 } },
+ {INIT_DCS_CMD, 2, { 0xC7, 0xFA } },
+ {INIT_DCS_CMD, 2, { 0xC8, 0xFC } },
+ {INIT_DCS_CMD, 2, { 0xC9, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xCA, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xCB, 0x16 } },
+ {INIT_DCS_CMD, 2, { 0xCC, 0xAF } },
+ {INIT_DCS_CMD, 2, { 0xCD, 0xFF } },
+ {INIT_DCS_CMD, 2, { 0xCE, 0xFF } },
+ {INIT_DCS_CMD, 2, { 0xB0, 0x0B } },
+ {INIT_DCS_CMD, 2, { 0xB1, 0x04 } },
+ {INIT_DCS_CMD, 2, { 0xB2, 0x05 } },
+ {INIT_DCS_CMD, 2, { 0xB3, 0x11 } },
+ {INIT_DCS_CMD, 2, { 0xB4, 0x24 } },
+ {INIT_DCS_CMD, 2, { 0xB5, 0x39 } },
+ {INIT_DCS_CMD, 2, { 0xB6, 0x4F } },
+ {INIT_DCS_CMD, 2, { 0xB7, 0x72 } },
+ {INIT_DCS_CMD, 2, { 0xB8, 0x98 } },
+ {INIT_DCS_CMD, 2, { 0xB9, 0xDC } },
+ {INIT_DCS_CMD, 2, { 0xBA, 0x23 } },
+ {INIT_DCS_CMD, 2, { 0xBB, 0xA6 } },
+ {INIT_DCS_CMD, 2, { 0xBC, 0x2C } },
+ {INIT_DCS_CMD, 2, { 0xBD, 0x30 } },
+ {INIT_DCS_CMD, 2, { 0xBE, 0xAA } },
+ {INIT_DCS_CMD, 2, { 0xBF, 0x26 } },
+ {INIT_DCS_CMD, 2, { 0xC0, 0x62 } },
+ {INIT_DCS_CMD, 2, { 0xC1, 0x9B } },
+ {INIT_DCS_CMD, 2, { 0xC2, 0xB5 } },
+ {INIT_DCS_CMD, 2, { 0xC3, 0xCF } },
+ {INIT_DCS_CMD, 2, { 0xC4, 0xDB } },
+ {INIT_DCS_CMD, 2, { 0xC5, 0xE8 } },
+ {INIT_DCS_CMD, 2, { 0xC6, 0xF5 } },
+ {INIT_DCS_CMD, 2, { 0xC7, 0xFA } },
+ {INIT_DCS_CMD, 2, { 0xC8, 0xFC } },
+ {INIT_DCS_CMD, 2, { 0xC9, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xCA, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xCB, 0x16 } },
+ {INIT_DCS_CMD, 2, { 0xCC, 0xAF } },
+ {INIT_DCS_CMD, 2, { 0xCD, 0xFF } },
+ {INIT_DCS_CMD, 2, { 0xCE, 0xFF } },
+ {INIT_DCS_CMD, 2, { 0xB0, 0x0C } },
+ {INIT_DCS_CMD, 2, { 0xB1, 0x04 } },
+ {INIT_DCS_CMD, 2, { 0xB2, 0x02 } },
+ {INIT_DCS_CMD, 2, { 0xB3, 0x16 } },
+ {INIT_DCS_CMD, 2, { 0xB4, 0x24 } },
+ {INIT_DCS_CMD, 2, { 0xB5, 0x3B } },
+ {INIT_DCS_CMD, 2, { 0xB6, 0x4F } },
+ {INIT_DCS_CMD, 2, { 0xB7, 0x73 } },
+ {INIT_DCS_CMD, 2, { 0xB8, 0x99 } },
+ {INIT_DCS_CMD, 2, { 0xB9, 0xE0 } },
+ {INIT_DCS_CMD, 2, { 0xBA, 0x26 } },
+ {INIT_DCS_CMD, 2, { 0xBB, 0xAD } },
+ {INIT_DCS_CMD, 2, { 0xBC, 0x36 } },
+ {INIT_DCS_CMD, 2, { 0xBD, 0x3A } },
+ {INIT_DCS_CMD, 2, { 0xBE, 0xAE } },
+ {INIT_DCS_CMD, 2, { 0xBF, 0x2A } },
+ {INIT_DCS_CMD, 2, { 0xC0, 0x66 } },
+ {INIT_DCS_CMD, 2, { 0xC1, 0x9E } },
+ {INIT_DCS_CMD, 2, { 0xC2, 0xB8 } },
+ {INIT_DCS_CMD, 2, { 0xC3, 0xD1 } },
+ {INIT_DCS_CMD, 2, { 0xC4, 0xDD } },
+ {INIT_DCS_CMD, 2, { 0xC5, 0xE9 } },
+ {INIT_DCS_CMD, 2, { 0xC6, 0xF6 } },
+ {INIT_DCS_CMD, 2, { 0xC7, 0xFA } },
+ {INIT_DCS_CMD, 2, { 0xC8, 0xFC } },
+ {INIT_DCS_CMD, 2, { 0xC9, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xCA, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xCB, 0x16 } },
+ {INIT_DCS_CMD, 2, { 0xCC, 0xAF } },
+ {INIT_DCS_CMD, 2, { 0xCD, 0xFF } },
+ {INIT_DCS_CMD, 2, { 0xCE, 0xFF } },
+ {INIT_DCS_CMD, 2, { 0xB0, 0x00 } },
+ {INIT_DCS_CMD, 2, { 0xB3, 0x08 } },
+ {INIT_DCS_CMD, 2, { 0xB0, 0x04 } },
+ {INIT_DCS_CMD, 2, { 0xB8, 0x68 } },
+ {DELAY_CMD, 10, {} },
+ {INIT_DCS_CMD, 1, { 0x11 } },
+ {DELAY_CMD, 120, {} },
+ {INIT_DCS_CMD, 1, { 0x29 } },
+ {DELAY_CMD, 20, {} },
+
+};
+
+struct panel_info krane_panel_info[] = {
+ PANEL(PANEL_KRANE_BOE_TV101WUM_NL6,
+ 74000,
+ krane_boe_tv101wum_nl6_edid,
+ boe_tv101wum_nl6_init_cmd),
+ {{PANEL_KRANE_UNKNOWN}, "PANEL_KRANE_UNKNOWN",
+ 0, NULL, NULL, 0},
+};
+
+static union panel_id krane_get_panel_id(struct board_display_intf *intf)
+{
+ return (union panel_id)PANEL_KRANE_BOE_TV101WUM_NL6;
+};
+
+static bool krane_is_panel_id_valid(union panel_id id)
+{
+ if (id.value < PANEL_KRANE_UNKNOWN)
+ return true;
+ return false;
+};
+
+static int krane_backlight(struct board_display_intf *intf)
+{
+ gpio_output(GPIO(PERIPHERAL_EN13), 1);
+ gpio_output(GPIO(DISP_PWM), 1); /* DISP_PWM0 */
+
+ return 0;
+};
+
+static int krane_power(struct board_display_intf *intf)
+{
+ if (board_id() < 2) {
+ /* board from p1 */
+ gpio_output(GPIO(LCM_RST), 0);
+ udelay(100);
+ gpio_output(GPIO(LCM_RST), 1);
+ mdelay(20);
+ } else {
+ /* board from p2 */
+ gpio_output(GPIO(LCM_RST), 0);
+ udelay(1500);
+ gpio_output(GPIO(SIM2_SRST), 1);
+ mdelay(5);
+ gpio_output(GPIO(PERIPHERAL_EN9), 1);
+ gpio_output(GPIO(MISC_BSI_CK_3), 1);
+ mdelay(100);
+ gpio_output(GPIO(LCM_RST), 1);
+ mdelay(10);
+ }
+
+ return 0;
+
+};
+
+struct board_display_intf panel_display_intf = {
+ .board = "krane",
+ .all_panel_info = krane_panel_info,
+ .all_panel_info_size = ARRAY_SIZE(krane_panel_info),
+ .cur_panel_info = NULL,
+ .get_panel_id = &krane_get_panel_id,
+ .is_panel_id_valid = &krane_is_panel_id_valid,
+ .backlight = &krane_backlight,
+ .power = &krane_power,
+};
diff --git a/src/mainboard/google/kukui/panel_kukui.c b/src/mainboard/google/kukui/panel_kukui.c
new file mode 100644
index 0000000..be76aa4
--- /dev/null
+++ b/src/mainboard/google/kukui/panel_kukui.c
@@ -0,0 +1,194 @@
+/*
+ * 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.
+ */
+
+#include <console/console.h>
+#include <delay.h>
+#include <device/device.h>
+#include <edid.h>
+#include <gpio.h>
+#include <soc/auxadc.h>
+#include <soc/ddp.h>
+#include <soc/dsi.h>
+#include <soc/gpio.h>
+#include <boardid.h>
+
+#include "display.h"
+#include "gpio.h"
+
+static struct edid kukui_innolux_edid = {
+ .panel_bits_per_color = 8,
+ .panel_bits_per_pixel = 24,
+ .mode = {
+ .name = "768x1024@60Hz",
+ .pixel_clock = 56900,
+ .lvds_dual_channel = 0,
+ .refresh = 60,
+ .ha = 768, .hbl = 120, .hso = 40, .hspw = 40, .hborder = 0,
+ .va = 1024, .vbl = 44, .vso = 20, .vspw = 4, .vborder = 0,
+ .phsync = '-', .pvsync = '-',
+ .x_mm = 120, .y_mm = 160,
+ },
+};
+
+static struct lcm_init_table lcm_init_cmd[] = {
+ {INIT_DCS_CMD, 1, {MIPI_DCS_EXIT_SLEEP_MODE} },
+ {DELAY_CMD, 120, {} },
+ {INIT_DCS_CMD, 1, {MIPI_DCS_SET_DISPLAY_ON} },
+ {DELAY_CMD, 120, {} },
+};
+
+static struct edid kukui_p097pfg_ssd2858_edid = {
+ .panel_bits_per_color = 8,
+ .panel_bits_per_pixel = 24,
+ .mode = {
+ .name = "1536x2048@60Hz",
+ .pixel_clock = 211660,
+ .lvds_dual_channel = 0,
+ .refresh = 60,
+ .ha = 1536, .hbl = 160, .hso = 140, .hspw = 10, .hborder = 0,
+ .va = 2048, .vbl = 32, .vso = 20, .vspw = 2, .vborder = 0,
+ .phsync = '-', .pvsync = '-',
+ .x_mm = 147, .y_mm = 196,
+ },
+};
+
+struct lcm_init_table lcm_p097pfg_ssd2858_init_cmd[] = {
+ /* SSD2858 config */
+ {INIT_GENENIC_CMD, 2, {0xff, 0x00} },
+ /* LOCKCNT=0x1f4, MRX=0, POSTDIV=1 (/2} }, MULT=0x49
+ * 27 Mhz => 985.5 Mhz
+ */
+ {INIT_GENENIC_CMD, 6, {0x00, 0x08, 0x01, 0xf4, 0x01, 0x49} },
+ /* MTXDIV=1, SYSDIV=3 (=> 4) */
+ {INIT_GENENIC_CMD, 6, {0x00, 0x0c, 0x00, 0x00, 0x00, 0x03} },
+ /* MTXVPF=24bpp, MRXLS=4 lanes, MRXVB=bypass, MRXECC=1, MRXEOT=1
+ * MRXEE=1
+ */
+ {INIT_GENENIC_CMD, 6, {0x00, 0x14, 0x0c, 0x3d, 0x80, 0x0f} },
+ {INIT_GENENIC_CMD, 6, {0x00, 0x20, 0x15, 0x92, 0x56, 0x7d} },
+ {INIT_GENENIC_CMD, 6, {0x00, 0x24, 0x00, 0x00, 0x30, 0x00} },
+
+ {INIT_GENENIC_CMD, 6, {0x10, 0x08, 0x01, 0x20, 0x08, 0x45} },
+ {INIT_GENENIC_CMD, 6, {0x10, 0x1c, 0x00, 0x00, 0x00, 0x00} },
+ {INIT_GENENIC_CMD, 6, {0x20, 0x0c, 0x00, 0x00, 0x00, 0x04} },
+ /* Pixel clock 985.5 Mhz * 0x49/0x4b = 959 Mhz */
+ {INIT_GENENIC_CMD, 6, {0x20, 0x10, 0x00, 0x4b, 0x00, 0x49} },
+ {INIT_GENENIC_CMD, 6, {0x20, 0xa0, 0x00, 0x00, 0x00, 0x00} },
+ /* EOT=1, LPE = 0, LSOUT=4 lanes, LPD=25 */
+ {INIT_GENENIC_CMD, 6, {0x60, 0x08, 0x00, 0xd9, 0x00, 0x08} },
+ {INIT_GENENIC_CMD, 6, {0x60, 0x14, 0x01, 0x00, 0x01, 0x06} },
+ /* DSI0 enable (default: probably not needed) */
+ {INIT_GENENIC_CMD, 6, {0x60, 0x80, 0x00, 0x00, 0x00, 0x0f} },
+ /* DSI1 enable */
+ {INIT_GENENIC_CMD, 6, {0x60, 0xa0, 0x00, 0x00, 0x00, 0x0f} },
+
+ /* HSA=0x18, VSA=0x02, HBP=0x50, VBP=0x0c */
+ {INIT_GENENIC_CMD, 6, {0x60, 0x0c, 0x0c, 0x50, 0x02, 0x18} },
+ /* VACT= 0x800 (2048} }, VFP= 0x14, HFP=0x50 */
+ {INIT_GENENIC_CMD, 6, {0x60, 0x10, 0x08, 0x00, 0x14, 0x50} },
+ /* HACT=0x300 (768) */
+ {INIT_GENENIC_CMD, 6, {0x60, 0x84, 0x00, 0x00, 0x03, 0x00} },
+ {INIT_GENENIC_CMD, 6, {0x60, 0xa4, 0x00, 0x00, 0x03, 0x00} },
+
+ /* Take panel out of sleep. */
+ {INIT_GENENIC_CMD, 2, {0xff, 0x01} },
+ {INIT_DCS_CMD, 1, {0x11} },
+ {DELAY_CMD, 120, {} },
+ {INIT_DCS_CMD, 1, {0x29} },
+ {DELAY_CMD, 20, {} },
+ {INIT_GENENIC_CMD, 2, {0xff, 0x00} },
+
+ {DELAY_CMD, 120, {} },
+ {INIT_DCS_CMD, 1, {0x11} },
+ {DELAY_CMD, 120, {} },
+ {INIT_DCS_CMD, 1, {0x29} },
+ {DELAY_CMD, 20, {} },
+};
+
+struct panel_info kukui_panel_info[] = {
+ PANEL(PANEL_KUKUI_INNOLUX,
+ 74000,
+ kukui_innolux_edid,
+ lcm_init_cmd),
+ PANEL(PANEL_KUKUI_P097PFG_SSD2858,
+ 212000,
+ kukui_p097pfg_ssd2858_edid,
+ lcm_p097pfg_ssd2858_init_cmd),
+ {{PANEL_KUKUI_UNKNOWN}, "PANEL_KUKUI_UNKNOWN",
+ 0, NULL, NULL, 0},
+};
+
+static union panel_id kukui_get_panel_id(struct board_display_intf *intf)
+{
+ if (board_id() < 2)
+ return (union panel_id)PANEL_KUKUI_INNOLUX;
+ else
+ return (union panel_id)PANEL_KUKUI_P097PFG_SSD2858;
+};
+
+static bool kukui_is_panel_id_valid(union panel_id id)
+{
+ if (id.value < PANEL_KUKUI_UNKNOWN)
+ return true;
+ return false;
+};
+
+static int kukui_backlight(struct board_display_intf *intf)
+{
+ gpio_output(GPIO(PERIPHERAL_EN13), 1);
+ gpio_output(GPIO(DISP_PWM), 1); /* DISP_PWM0 */
+
+ return 0;
+};
+
+static int kukui_power(struct board_display_intf *intf)
+{
+ if (board_id() < 2) {
+ /* board from p1 */
+ gpio_output(GPIO(LCM_RST), 0);
+ udelay(100);
+ gpio_output(GPIO(LCM_RST), 1);
+ mdelay(20);
+ } else {
+ /* board from p2 */
+ gpio_output(GPIO(LCM_RST), 0);
+ gpio_output(GPIO(BPI_BUS3), 0);
+ gpio_output(GPIO(MISC_BSI_CK_3), 1);
+ gpio_output(GPIO(PERIPHERAL_EN9), 1);
+ gpio_output(GPIO(SIM2_SRST), 1);
+ gpio_output(GPIO(SIM2_SIO), 1);
+ gpio_output(GPIO(BPI_OLAT1), 1);
+ gpio_output(GPIO(SIM2_SCLK), 1);
+ mdelay(20);
+ gpio_output(GPIO(LCM_RST), 1);
+ mdelay(20);
+ gpio_output(GPIO(BPI_BUS3), 1);
+ mdelay(20);
+ }
+
+ return 0;
+
+};
+
+struct board_display_intf panel_display_intf = {
+ .board = "kukui",
+ .all_panel_info = kukui_panel_info,
+ .all_panel_info_size = ARRAY_SIZE(kukui_panel_info),
+ .cur_panel_info = NULL,
+ .get_panel_id = &kukui_get_panel_id,
+ .is_panel_id_valid = &kukui_is_panel_id_valid,
+ .backlight = &kukui_backlight,
+ .power = &kukui_power,
+};
diff --git a/src/soc/mediatek/mt8183/Makefile.inc b/src/soc/mediatek/mt8183/Makefile.inc
index ce498c1..0afa335 100644
--- a/src/soc/mediatek/mt8183/Makefile.inc
+++ b/src/soc/mediatek/mt8183/Makefile.inc
@@ -42,6 +42,8 @@

ramstage-y += auxadc.c
ramstage-y += ../common/cbmem.c emi.c
+ramstage-y += ddp.c
+ramstage-y += dsi.c
ramstage-y += ../common/gpio.c gpio.c
ramstage-y += ../common/mmu_operations.c mmu_operations.c
ramstage-y += ../common/mtcmos.c mtcmos.c
diff --git a/src/soc/mediatek/mt8183/ddp.c b/src/soc/mediatek/mt8183/ddp.c
new file mode 100644
index 0000000..d845981
--- /dev/null
+++ b/src/soc/mediatek/mt8183/ddp.c
@@ -0,0 +1,202 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2019 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 <console/console.h>
+#include <delay.h>
+#include <device/mmio.h>
+#include <edid.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stddef.h>
+#include <soc/addressmap.h>
+#include <soc/ddp.h>
+
+#define RDMA_FIFO_PSEUDO_SIZE(bytes) (((bytes) / 16) << 16)
+#define RDMA_OUTPUT_VALID_FIFO_THRESHOLD(bytes) ((bytes) / 16)
+
+static void disp_config_main_path_connection(void)
+{
+ write32(&mmsys_cfg->disp_ovl0_mout_en, OVL0_MOUT_EN_OVL0_2L);
+ write32(&mmsys_cfg->disp_ovl0_2l_mout_en, OVL0_2L_MOUT_EN_DISP_PATH0);
+ write32(&mmsys_cfg->disp_path0_sel_in, DISP_PATH0_SEL_IN_OVL0_2L);
+ write32(&mmsys_cfg->disp_rdma0_sout_sel_in, RDMA0_SOUT_SEL_IN_COLOR);
+ write32(&mmsys_cfg->disp_dither0_mout_en, DITHER0_MOUT_EN_DISP_DSI0);
+ write32(&mmsys_cfg->dsi0_sel_in, DSI0_SEL_IN_DITHER0_MOUT);
+}
+
+static void disp_config_main_path_mutex(void)
+{
+ write32(&disp_mutex->mutex[0].mod, MUTEX_MOD_MAIN_PATH);
+
+ /* Clock source from DSI0 */
+ write32(&disp_mutex->mutex[0].ctl,
+ MUTEX_SOF_DSI0 | (MUTEX_SOF_DSI0 << 6));
+ write32(&disp_mutex->mutex[0].en, BIT(0));
+}
+
+static void ovl_set_roi(u32 idx, u32 width, u32 height, u32 color)
+{
+ write32(&disp_ovl[idx]->roi_size, height << 16 | width);
+ write32(&disp_ovl[idx]->roi_bgclr, color);
+}
+
+static void ovl_layer_enable(u32 idx)
+{
+ write32(&disp_ovl[idx]->rdma[0].ctrl, BIT(0));
+ write32(&disp_ovl[idx]->rdma[0].mem_gmc_setting, RDMA_MEM_GMC);
+
+ setbits_le32(&disp_ovl[idx]->src_con, BIT(0));
+}
+
+static void ovl_bgclr_in_sel(u32 idx)
+{
+ setbits_le32(&disp_ovl[idx]->datapath_con, BIT(2));
+}
+
+static void rdma_start(u32 idx)
+{
+ setbits_le32(&disp_rdma[idx]->global_con, RDMA_ENGINE_EN);
+}
+
+static void rdma_config(u32 idx, u32 width, u32 height, u32 vrefresh)
+{
+ u32 threshold;
+ u32 reg;
+ u32 fifo_size;
+
+ clrsetbits_le32(&disp_rdma[idx]->size_con_0, 0x1FFF, width);
+ clrsetbits_le32(&disp_rdma[idx]->size_con_1, 0xFFFFF, height);
+
+ /*
+ * Enable FIFO underflow since DSI and DPI can't be blocked. Keep the
+ * FIFO pseudo size reset default of 8 KiB. Set the output threshold to
+ * 6 microseconds with 7/6 overhead to account for blanking, and with a
+ * pixel depth of 4 bytes:
+ */
+ fifo_size = RDMA_FIFO_SIZE_0 * KiB;
+
+ threshold = width * height * vrefresh * 4 * 7 / 1000000;
+
+ if (threshold > fifo_size)
+ threshold = fifo_size;
+
+ reg = RDMA_FIFO_UNDERFLOW_EN |
+ RDMA_FIFO_PSEUDO_SIZE(fifo_size) |
+ RDMA_OUTPUT_VALID_FIFO_THRESHOLD(threshold);
+
+ write32(&disp_rdma[idx]->fifo_con, reg);
+}
+
+static void color_start(u32 width, u32 height)
+{
+ write32(&disp_color->width, width);
+ write32(&disp_color->height, height);
+ write32(&disp_color->cfg_main, COLOR_BYPASS_ALL | COLOR_SEQ_SEL);
+ write32(&disp_color->start, BIT(0));
+}
+
+static void aal_start(u32 width, u32 height)
+{
+ write32(&disp_aal->size, height << 16 | width);
+ write32(&disp_aal->en, PQ_EN);
+}
+
+static void ccorr_start(u32 width, u32 height)
+{
+ write32(&disp_ccorr->size, height << 16 | width);
+ write32(&disp_ccorr->cfg, PQ_RELAY_MODE);
+ write32(&disp_ccorr->en, PQ_EN);
+}
+
+static void dither_start(u32 width, u32 height)
+{
+ write32(&disp_dither->size, height << 16 | width);
+ write32(&disp_dither->cfg, PQ_RELAY_MODE);
+ write32(&disp_dither->en, PQ_EN);
+}
+
+static void gamma_start(u32 width, u32 height)
+{
+ write32(&disp_gamma->size, height << 16 | width);
+ write32(&disp_gamma->en, PQ_EN);
+}
+
+static void ovl_layer_config(u32 idx, u32 fmt, u32 bpp, u32 width, u32 height)
+{
+ write32(&disp_ovl[idx]->layer[0].con, fmt << 12);
+ write32(&disp_ovl[idx]->layer[0].src_size, height << 16 | width);
+ write32(&disp_ovl[idx]->layer[0].pitch, (width * bpp) & 0xFFFF);
+
+ ovl_layer_enable(idx);
+}
+
+static void main_disp_path_setup(u32 width, u32 height, u32 vrefresh)
+{
+ u32 idx = 0;
+
+ /* Setup OVL */
+ for (idx = 0; idx < MAIN_PATH_OVL_NR; idx++) {
+ u32 color = 0;
+
+ if (idx == 0)
+ color = 0xFF0000FF;
+
+ ovl_set_roi(idx, width, height, color);
+ }
+
+ idx = 0;
+ rdma_config(idx, width, height, vrefresh);
+ color_start(width, height);
+ ccorr_start(width, height);
+ aal_start(width, height);
+ gamma_start(width, height);
+ dither_start(width, height);
+ disp_config_main_path_connection();
+ disp_config_main_path_mutex();
+}
+
+static void disp_clock_on(void)
+{
+ clrbits_le32(&mmsys_cfg->mmsys_cg_con0, CG_CON0_DISP_ALL);
+
+ clrbits_le32(&mmsys_cfg->mmsys_cg_con1, CG_CON1_DISP_DSI0 |
+ CG_CON1_DISP_DSI0_INTERFACE);
+}
+
+static void disp_m4u_port_off(void)
+{
+ write32((void *)(SMI_LARB0 + SMI_LARB_NON_SEC_CON), 0);
+}
+
+void mtk_ddp_init(void)
+{
+ disp_clock_on();
+ disp_m4u_port_off();
+}
+
+void mtk_ddp_mode_set(const struct edid *edid)
+{
+ u32 fmt = OVL_INFMT_RGBA8888;
+ u32 bpp = edid->framebuffer_bits_per_pixel / 8;
+ u32 idx = 0;
+ u32 width = edid->mode.ha;
+ u32 height = edid->mode.va;
+ u32 vrefresh = edid->mode.refresh;
+
+ main_disp_path_setup(width, height, vrefresh);
+ rdma_start(idx);
+ ovl_layer_config(idx, fmt, bpp, width, height);
+ ovl_bgclr_in_sel(idx+1);
+}
diff --git a/src/soc/mediatek/mt8183/dsi.c b/src/soc/mediatek/mt8183/dsi.c
new file mode 100644
index 0000000..3bfada7
--- /dev/null
+++ b/src/soc/mediatek/mt8183/dsi.c
@@ -0,0 +1,485 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 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 <device/mmio.h>
+#include <console/console.h>
+#include <delay.h>
+#include <soc/addressmap.h>
+#include <soc/dsi.h>
+#include <timer.h>
+
+static void dsi_write32(void *a, uint32_t v)
+{
+ write32(a, v);
+}
+
+static void dsi_clrsetbits_le32(void *a, uint32_t m, uint32_t v)
+{
+ clrsetbits_le32(a, m, v);
+}
+
+static void dsi_clrbits_le32(void *a, uint32_t m)
+{
+ clrbits_le32(a, m);
+}
+
+static void dsi_setbits_le32(void *a, uint32_t m)
+{
+ setbits_le32(a, m);
+}
+
+static int mtk_dsi_phy_clk_setting(u32 format, u32 lanes,
+ const struct edid *edid)
+{
+ unsigned int txdiv, txdiv0, txdiv1;
+ u64 pcw;
+ int data_rate;
+ u32 bpp;
+
+ switch (format) {
+ case MIPI_DSI_FMT_RGB565:
+ bpp = 16;
+ break;
+ case MIPI_DSI_FMT_RGB666:
+ case MIPI_DSI_FMT_RGB666_PACKED:
+ bpp = 18;
+ break;
+ case MIPI_DSI_FMT_RGB888:
+ default:
+ bpp = 24;
+ break;
+ }
+
+ data_rate = (u64)(edid->mode.pixel_clock * 1000 * bpp) / lanes;
+
+ printk(BIOS_INFO, "data_rate: %u bps\n", data_rate);
+
+ if (data_rate >= 2000000000) {
+ txdiv = 1;
+ txdiv0 = 0;
+ txdiv1 = 0;
+ } else if (data_rate >= 1000000000) {
+ txdiv = 2;
+ txdiv0 = 1;
+ txdiv1 = 0;
+ } else if (data_rate >= 500000000) {
+ txdiv = 4;
+ txdiv0 = 2;
+ txdiv1 = 0;
+ } else if (data_rate > 250000000) {
+ txdiv = 8;
+ txdiv0 = 3;
+ txdiv1 = 0;
+ } else if (data_rate >= 125000000) {
+ txdiv = 16;
+ txdiv0 = 4;
+ txdiv1 = 0;
+ } else {
+ printk(BIOS_ERR, "data rate (%u) must be >=50. Please check "
+ "pixel clock (%u), bpp (%u), number of lanes (%u)\n",
+ data_rate, edid->mode.pixel_clock, bpp,
+ lanes);
+ return -1;
+ }
+
+ dsi_clrbits_le32(mipi_tx + MIPITX_PLL_CON4, BIT(11) | BIT(10));
+
+ dsi_setbits_le32(mipi_tx + MIPITX_PLL_PWR, AD_DSI_PLL_SDM_PWR_ON);
+ udelay(30);
+ dsi_clrbits_le32(mipi_tx + MIPITX_PLL_PWR, AD_DSI_PLL_SDM_ISO_EN);
+
+ pcw = (u64)((data_rate / 1000000) * (1 << txdiv0) * (1 << txdiv1));
+ pcw <<= 24;
+ pcw /= 26;
+
+ dsi_write32(mipi_tx + MIPITX_PLL_CON0, pcw);
+ dsi_clrsetbits_le32(mipi_tx + MIPITX_PLL_CON1, RG_DSI_PLL_POSDIV,
+ txdiv0 << 8);
+ udelay(30);
+ dsi_setbits_le32(mipi_tx + MIPITX_PLL_CON1, RG_DSI_PLL_EN);
+
+ /* BG_LPF_EN / BG_CORE_EN */
+ dsi_write32(mipi_tx + MIPITX_LANE_CON, 0x3FFF0180);
+ udelay(40);
+ dsi_write32(mipi_tx + MIPITX_LANE_CON, 0x3FFF00c0);
+
+ /* Switch OFF each Lane */
+ dsi_clrbits_le32(mipi_tx + MIPITX_D0_SW_CTL_EN, DSI_SW_CTL_EN);
+ dsi_clrbits_le32(mipi_tx + MIPITX_D1_SW_CTL_EN, DSI_SW_CTL_EN);
+ dsi_clrbits_le32(mipi_tx + MIPITX_D2_SW_CTL_EN, DSI_SW_CTL_EN);
+ dsi_clrbits_le32(mipi_tx + MIPITX_D3_SW_CTL_EN, DSI_SW_CTL_EN);
+ dsi_clrbits_le32(mipi_tx + MIPITX_CK_SW_CTL_EN, DSI_SW_CTL_EN);
+
+ dsi_setbits_le32(mipi_tx + MIPITX_CK_CKMODE_EN, DSI_CK_CKMODE_EN);
+
+ return data_rate;
+}
+
+static void mtk_dsi_phy_timconfig(u32 data_rate,
+ struct mtk_phy_timing *phy_timing)
+{
+ u32 timcon0, timcon1, timcon2, timcon3;
+
+ timcon0 = phy_timing->lpx | phy_timing->da_hs_prepare << 8 |
+ phy_timing->da_hs_zero << 16 | phy_timing->da_hs_trail << 24;
+ timcon1 = phy_timing->ta_go | phy_timing->ta_sure << 8 |
+ phy_timing->ta_get << 16 | phy_timing->da_hs_exit << 24;
+ timcon2 = 1 << 8 | phy_timing->clk_hs_zero << 16 |
+ phy_timing->clk_hs_trail << 24;
+ timcon3 = phy_timing->clk_hs_prepare | phy_timing->clk_hs_post << 8 |
+ phy_timing->clk_hs_exit << 16;
+
+ dsi_write32(&dsi->dsi_phy_timecon0, timcon0);
+ dsi_write32(&dsi->dsi_phy_timecon1, timcon1);
+ dsi_write32(&dsi->dsi_phy_timecon2, timcon2);
+ dsi_write32(&dsi->dsi_phy_timecon3, timcon3);
+}
+
+static void mtk_dsi_reset(void)
+{
+ dsi_write32(&dsi->dsi_con_ctrl, 1);
+ dsi_write32(&dsi->dsi_con_ctrl, 0);
+}
+
+static void mtk_dsi_clk_hs_mode_enable(void)
+{
+ dsi_setbits_le32(&dsi->dsi_phy_lccon, 1);
+}
+
+static void mtk_dsi_set_mode(u32 mode_flags)
+{
+ u32 tmp_reg1 = 0;
+
+ if (mode_flags & MIPI_DSI_MODE_VIDEO) {
+ tmp_reg1 = SYNC_PULSE_MODE;
+
+ if (mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+ tmp_reg1 = BURST_MODE;
+
+ if (mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
+ tmp_reg1 = SYNC_PULSE_MODE;
+ }
+
+ dsi_write32(&dsi->dsi_mode_ctrl, tmp_reg1);
+}
+
+static void mtk_dsi_phy_timing_calc(u32 format, u32 lanes,
+ const struct edid *edid,
+ struct mtk_phy_timing *phy_timing)
+{
+ u32 ui, cycle_time, data_rate;
+ u32 bit_per_pixel;
+
+ switch (format) {
+ case MIPI_DSI_FMT_RGB565:
+ bit_per_pixel = 16;
+ break;
+ case MIPI_DSI_FMT_RGB666:
+ case MIPI_DSI_FMT_RGB666_PACKED:
+ bit_per_pixel = 18;
+ break;
+ case MIPI_DSI_FMT_RGB888:
+ default:
+ bit_per_pixel = 24;
+ break;
+ }
+
+ data_rate = edid->mode.pixel_clock * bit_per_pixel / lanes;
+
+ ui = 1000 / (data_rate / 1000) + 1U;
+ cycle_time = 8000 / (data_rate / 1000) + 1U;
+
+ phy_timing->lpx = DIV_ROUND_UP(60, cycle_time);
+ phy_timing->da_hs_prepare = DIV_ROUND_UP((40 + 5 * ui), cycle_time);
+ phy_timing->da_hs_zero = DIV_ROUND_UP((180 + 6 * ui), cycle_time);
+ phy_timing->da_hs_trail = DIV_ROUND_UP(((4 * ui) + 80), cycle_time);
+
+ if (phy_timing->da_hs_zero > phy_timing->da_hs_prepare)
+ phy_timing->da_hs_zero -= phy_timing->da_hs_prepare;
+
+ phy_timing->ta_go = 4U * phy_timing->lpx;
+ phy_timing->ta_sure = 3U * phy_timing->lpx / 2U;
+ phy_timing->ta_get = 5U * phy_timing->lpx;
+ phy_timing->da_hs_exit = 2U * phy_timing->lpx;
+
+ phy_timing->clk_hs_zero = DIV_ROUND_UP(0x150U, cycle_time);
+ phy_timing->clk_hs_trail = DIV_ROUND_UP(0x64U, cycle_time) + 0xaU;
+
+ phy_timing->clk_hs_prepare = DIV_ROUND_UP(0x40U, cycle_time);
+ phy_timing->clk_hs_post = DIV_ROUND_UP(80U + 52U * ui, cycle_time);
+ phy_timing->clk_hs_exit = 2U * phy_timing->lpx;
+}
+
+static void mtk_dsi_rxtx_control(u32 mode_flags, u32 lanes)
+{
+ u32 tmp_reg = 0;
+
+ switch (lanes) {
+ case 1:
+ tmp_reg = 1 << 2;
+ break;
+ case 2:
+ tmp_reg = 3 << 2;
+ break;
+ case 3:
+ tmp_reg = 7 << 2;
+ break;
+ case 4:
+ default:
+ tmp_reg = 0xf << 2;
+ break;
+ }
+
+ tmp_reg |= (mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) << 6;
+ tmp_reg |= (mode_flags & MIPI_DSI_MODE_EOT_PACKET) >> 3;
+
+ dsi_write32(&dsi->dsi_txrx_ctrl, tmp_reg);
+}
+
+static void mtk_dsi_config_vdo_timing(u32 mode_flags, u32 format,
+ const struct edid *edid,
+ struct mtk_phy_timing *phy_timing,
+ u32 lanes)
+{
+ u32 hsync_active_byte;
+ u32 hbp_byte;
+ u32 hfp_byte, tmp_hfp_byte;
+ u32 vbp_byte;
+ u32 vfp_byte;
+ u32 bpp;
+ u32 packet_fmt;
+ u32 hactive;
+ u32 data_phy_cycles;
+
+ if (format == MIPI_DSI_FMT_RGB565)
+ bpp = 2;
+ else
+ bpp = 3;
+
+ vbp_byte = edid->mode.vbl - edid->mode.vso - edid->mode.vspw -
+ edid->mode.vborder;
+ vfp_byte = edid->mode.vso - edid->mode.vborder;
+
+ dsi_write32(&dsi->dsi_vsa_nl, edid->mode.vspw);
+ dsi_write32(&dsi->dsi_vbp_nl, vbp_byte);
+ dsi_write32(&dsi->dsi_vfp_nl, vfp_byte);
+ dsi_write32(&dsi->dsi_vact_nl, edid->mode.va);
+
+ if (mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
+ hbp_byte = (edid->mode.hbl - edid->mode.hso - edid->mode.hspw -
+ edid->mode.hborder) * bpp - 10;
+ else
+ hbp_byte = (edid->mode.hbl - edid->mode.hso -
+ edid->mode.hborder) * bpp - 10;
+
+ hsync_active_byte = edid->mode.hspw * bpp - 10;
+
+ data_phy_cycles = phy_timing->lpx + phy_timing->da_hs_prepare +
+ phy_timing->da_hs_zero + phy_timing->da_hs_exit + 2;
+
+ tmp_hfp_byte = (edid->mode.hso - edid->mode.hborder) * bpp;
+
+ if (mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
+ if (tmp_hfp_byte > data_phy_cycles * lanes + 18) {
+ hfp_byte = tmp_hfp_byte - data_phy_cycles * lanes - 18;
+ } else {
+ printk(BIOS_ERR, "HFP less than d-phy, FPS will under 60Hz\n");
+ hfp_byte = tmp_hfp_byte;
+ }
+ } else {
+ if (tmp_hfp_byte > data_phy_cycles * lanes + 12) {
+ hfp_byte = tmp_hfp_byte - data_phy_cycles * lanes - 12;
+ } else {
+ printk(BIOS_ERR, "HFP less than d-phy, FPS will under 60Hz\n");
+ hfp_byte = tmp_hfp_byte;
+ }
+ }
+
+ dsi_write32(&dsi->dsi_hsa_wc, hsync_active_byte);
+ dsi_write32(&dsi->dsi_hbp_wc, hbp_byte);
+ dsi_write32(&dsi->dsi_hfp_wc, hfp_byte);
+
+ switch (format) {
+ case MIPI_DSI_FMT_RGB888:
+ packet_fmt = PACKED_PS_24BIT_RGB888;
+ break;
+ case MIPI_DSI_FMT_RGB666:
+ packet_fmt = LOOSELY_PS_18BIT_RGB666;
+ break;
+ case MIPI_DSI_FMT_RGB666_PACKED:
+ packet_fmt = PACKED_PS_18BIT_RGB666;
+ break;
+ case MIPI_DSI_FMT_RGB565:
+ packet_fmt = PACKED_PS_16BIT_RGB565;
+ break;
+ default:
+ packet_fmt = PACKED_PS_24BIT_RGB888;
+ break;
+ }
+
+ hactive = edid->mode.ha;
+ packet_fmt |= (hactive * bpp) & DSI_PS_WC;
+
+ dsi_write32(&dsi->dsi_psctrl, 0x2c << 24 | packet_fmt);
+ dsi_write32(&dsi->dsi_size_con, edid->mode.va << 16 | hactive);
+}
+
+static void mtk_dsi_start(void)
+{
+ dsi_clrbits_le32(&dsi->dsi_start, 1);
+ dsi_setbits_le32(&dsi->dsi_start, 1);
+}
+
+static void mtk_dsi_cmdq(u8 *data, u8 len, u32 type)
+{
+ struct stopwatch sw;
+ u8 *tx_buf = data;
+ u8 cmdq_size;
+ u32 reg_val, cmdq_mask, i, config, cmdq_off, intsta_0;
+
+ while (read32(&dsi->dsi_intsta) & (1 << 31)) {
+ printk(BIOS_ERR, "%s wait dsi no busy\n", __func__);
+ mdelay(20);
+ }
+
+ dsi_write32(&dsi->dsi_intsta, 0);
+
+ if (MTK_DSI_HOST_IS_READ(type))
+ config = BTA;
+ else
+ config = (len > 2) ? LONG_PACKET : SHORT_PACKET;
+
+ if (len > 2) {
+ cmdq_size = 1 + (len + 3) / 4;
+ cmdq_off = 4;
+ cmdq_mask = CONFIG | DATA_ID | DATA_0 | DATA_1;
+ reg_val = (len << 16) | (type << 8) | config;
+ } else {
+ cmdq_size = 1;
+ cmdq_off = 2;
+ cmdq_mask = CONFIG | DATA_ID;
+ reg_val = (type << 8) | config;
+ }
+
+ for (i = 0; i < 0x20; i = i + 4)
+ dsi_write32((void *)DSI_BASE + 0x200 + i, 0);
+
+ for (i = 0; i < len; i++) {
+ dsi_clrsetbits_le32((void *)DSI_BASE + 0x200 +
+ ((cmdq_off + i) & (0xfffffffc)),
+ (0xff << (((i + cmdq_off) & 3) * 8)),
+ tx_buf[i] << (((i + cmdq_off) & 3) * 8));
+ }
+
+ dsi_clrsetbits_le32(&dsi->dsi_cmdq0, cmdq_mask, reg_val);
+ dsi_clrsetbits_le32(&dsi->dsi_cmdq_size, CMDQ_SIZE, cmdq_size);
+ mtk_dsi_start();
+
+ stopwatch_init_usecs_expire(&sw, 400);
+ do {
+ intsta_0 = read32(&dsi->dsi_intsta);
+ if (intsta_0 & CMD_DONE_INT_FLAG)
+ break;
+ udelay(4);
+ } while (!stopwatch_expired(&sw));
+
+ if (!(intsta_0 & CMD_DONE_INT_FLAG))
+ printk(BIOS_ERR, "dsi send cmd time-out(400uS)\n");
+}
+
+static void push_table(struct lcm_init_table *init_cmd, u32 count)
+{
+ u32 cmd, i;
+ u32 type;
+
+ for (i = 0; i < count; i++) {
+ cmd = init_cmd[i].cmd;
+
+ switch (cmd) {
+ case DELAY_CMD:
+ mdelay(init_cmd[i].len);
+ break;
+
+ case END_OF_TABLE:
+ break;
+
+ case INIT_DCS_CMD:
+ switch (init_cmd[i].len) {
+ case 0:
+ return;
+
+ case 1:
+ type = MIPI_DSI_DCS_SHORT_WRITE;
+ break;
+
+ case 2:
+ type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
+ break;
+
+ default:
+ type = MIPI_DSI_DCS_LONG_WRITE;
+ break;
+ }
+ mtk_dsi_cmdq(init_cmd[i].data, init_cmd[i].len, type);
+ break;
+
+ case INIT_GENENIC_CMD:
+ default:
+ switch (init_cmd[i].len) {
+ case 0:
+ type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM;
+ break;
+ case 1:
+ type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM;
+ break;
+ case 2:
+ type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM;
+ break;
+ default:
+ type = MIPI_DSI_GENERIC_LONG_WRITE;
+ break;
+ }
+ mtk_dsi_cmdq(init_cmd[i].data, init_cmd[i].len, type);
+ break;
+ }
+ }
+}
+
+int mtk_dsi_init(u32 mode_flags, u32 format, u32 lanes, bool dual,
+ const struct edid *edid, struct lcm_init_table *init_cmd,
+ u32 count)
+{
+ int data_rate;
+ struct mtk_phy_timing phy_timing;
+
+ mtk_dsi_phy_timing_calc(format, lanes, edid, &phy_timing);
+
+ data_rate = mtk_dsi_phy_clk_setting(format, lanes, edid);
+
+ if (data_rate < 0)
+ return -1;
+
+ dsi_write32(&dsi->dsi_force_commit, 3);
+ mtk_dsi_reset();
+ mtk_dsi_phy_timconfig(data_rate, &phy_timing);
+ mtk_dsi_rxtx_control(mode_flags, lanes);
+ mtk_dsi_config_vdo_timing(mode_flags, format, edid, &phy_timing, lanes);
+ mtk_dsi_clk_hs_mode_enable();
+ push_table(init_cmd, count);
+ mtk_dsi_set_mode(mode_flags);
+ mtk_dsi_start();
+
+ return 0;
+}
diff --git a/src/soc/mediatek/mt8183/include/soc/addressmap.h b/src/soc/mediatek/mt8183/include/soc/addressmap.h
index d41b2b9..75202dd 100644
--- a/src/soc/mediatek/mt8183/include/soc/addressmap.h
+++ b/src/soc/mediatek/mt8183/include/soc/addressmap.h
@@ -47,12 +47,27 @@
IOCFG_RT_BASE = IO_PHYS + 0x01C50000,
IOCFG_RM_BASE = IO_PHYS + 0x01D20000,
IOCFG_RB_BASE = IO_PHYS + 0x01D30000,
+ MIPITX_BASE = IO_PHYS + 0x01E50000,
IOCFG_LB_BASE = IO_PHYS + 0x01E70000,
IOCFG_LM_BASE = IO_PHYS + 0x01E80000,
IOCFG_BL_BASE = IO_PHYS + 0x01E90000,
IOCFG_LT_BASE = IO_PHYS + 0x01F20000,
IOCFG_TL_BASE = IO_PHYS + 0x01F30000,
SSUSB_SIF_BASE = IO_PHYS + 0x01F40300,
+ MMSYS_BASE = IO_PHYS + 0x04000000,
+ DISP_OVL0_BASE = IO_PHYS + 0x04008000,
+ DISP_OVL0_2L_BASE = IO_PHYS + 0x04009000,
+ DISP_OVL1_2L_BASE = IO_PHYS + 0x0400A000,
+ DISP_RDMA0_BASE = IO_PHYS + 0x0400B000,
+ DISP_RDMA1_BASE = IO_PHYS + 0x0400C000,
+ DISP_COLOR0_BASE = IO_PHYS + 0x0400E000,
+ DISP_CCORR0_BASE = IO_PHYS + 0x0400F000,
+ DISP_AAL0_BASE = IO_PHYS + 0x04010000,
+ DISP_GAMMA0_BASE = IO_PHYS + 0x04011000,
+ DISP_DITHER0_BASE = IO_PHYS + 0x04012000,
+ DSI_BASE = IO_PHYS + 0x04014000,
+ DISP_MUTEX_BASE = IO_PHYS + 0x04016000,
+ SMI_LARB0 = IO_PHYS + 0x04017000,
SMI_BASE = IO_PHYS + 0x04019000,
};

diff --git a/src/soc/mediatek/mt8183/include/soc/ddp.h b/src/soc/mediatek/mt8183/include/soc/ddp.h
new file mode 100644
index 0000000..1914868
--- /dev/null
+++ b/src/soc/mediatek/mt8183/include/soc/ddp.h
@@ -0,0 +1,315 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 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.
+ */
+
+#ifndef _DDP_REG_H_
+#define _DDP_REG_H_
+
+#include <soc/addressmap.h>
+#include <types.h>
+
+#define MAIN_PATH_OVL_NR 2
+
+struct mmsys_cfg_regs {
+ u32 reserved_0x000[64]; /* 0x000 */
+ u32 mmsys_cg_con0; /* 0x100 */
+ u32 mmsys_cg_set0; /* 0x104 */
+ u32 mmsys_cg_clr0; /* 0x108 */
+ u32 reserved_0x10C; /* 0x10C */
+ u32 mmsys_cg_con1; /* 0x110 */
+ u32 mmsys_cg_set1; /* 0x114 */
+ u32 mmsys_cg_clr1; /* 0x118 */
+ u32 reserved_0x11C[889]; /* 0x11C */
+ u32 disp_ovl0_mout_en; /* 0xF00 */
+ u32 disp_ovl0_2l_mout_en; /* 0xF04 */
+ u32 disp_ovl1_2l_mout_en; /* 0xF08 */
+ u32 disp_dither0_mout_en; /* 0xF0C */
+ u32 reserved_0xF10[5]; /* 0xF10 - 0xF20 */
+ u32 disp_path0_sel_in; /* 0xF24 */
+ u32 reserved_0xF28; /* 0xF28 */
+ u32 dsi0_sel_in; /* 0xF2C */
+ u32 dpi0_sel_in; /* 0xF30 */
+ u32 reserved_0xF34; /* 0xF34 */
+ u32 disp_ovl0_2l_sel_in; /* 0xF38 */
+ u32 reserved_0xF3C[5]; /* 0xF3C - 0xF4C */
+ u32 disp_rdma0_sout_sel_in; /* 0xF50 */
+ u32 disp_rdma1_sout_sel_in; /* 0xF54 */
+ u32 reserved_0xF58[3]; /* 0xF58 - 0xF60 */
+ u32 dpi0_sel_sout_sel_in; /* 0xF64 */
+};
+
+check_member(mmsys_cfg_regs, mmsys_cg_con0, 0x100);
+check_member(mmsys_cfg_regs, dpi0_sel_sout_sel_in, 0xF64);
+static struct mmsys_cfg_regs *const mmsys_cfg =
+ (void *)MMSYS_BASE;
+
+
+/* DISP_REG_CONFIG_MMSYS_CG_CON0
+ Configures free-run clock gating 0
+ 0: Enable clock
+ 1: Clock gating */
+enum {
+ CG_CON0_SMI_COMMON = BIT(0),
+ CG_CON0_SMI_LARB0 = BIT(1),
+ CG_CON0_GALS_COMMON0 = BIT(3),
+ CG_CON0_GALS_COMMON1 = BIT(4),
+ CG_CON0_DISP_OVL0 = BIT(20),
+ CG_CON0_DISP_OVL0_2L = BIT(21),
+ CG_CON0_DISP_OVL1_2L = BIT(22),
+ CG_CON0_DISP_RDMA0 = BIT(23),
+ CG_CON0_DISP_RDMA1 = BIT(24),
+ CG_CON0_DISP_WDMA0 = BIT(25),
+ CG_CON0_DISP_COLOR0 = BIT(26),
+ CG_CON0_DISP_CCORR0 = BIT(27),
+ CG_CON0_DISP_AAL0 = BIT(28),
+ CG_CON0_DISP_GAMMA0 = BIT(29),
+ CG_CON0_DISP_DITHER0 = BIT(30),
+ CG_CON0_DISP_ALL = CG_CON0_SMI_COMMON |
+ CG_CON0_SMI_LARB0 |
+ CG_CON0_GALS_COMMON0 |
+ CG_CON0_GALS_COMMON1 |
+ CG_CON0_DISP_OVL0 |
+ CG_CON0_DISP_OVL0_2L |
+ CG_CON0_DISP_RDMA0 |
+ CG_CON0_DISP_COLOR0 |
+ CG_CON0_DISP_CCORR0 |
+ CG_CON0_DISP_AAL0 |
+ CG_CON0_DISP_DITHER0 |
+ CG_CON0_DISP_GAMMA0,
+ CG_CON0_ALL = 0xffffffff
+};
+
+/* DISP_REG_CONFIG_MMSYS_CG_CON1
+ Configures free-run clock gating 1
+ 0: Enable clock
+ 1: Clock gating */
+enum {
+ CG_CON1_DISP_DSI0 = BIT(0),
+ CG_CON1_DISP_DSI0_INTERFACE = BIT(1),
+ CG_CON1_DISP_26M = BIT(7),
+
+ CG_CON1_ALL = 0xffffffff
+};
+
+enum {
+ OVL0_MOUT_EN_RDMA0 = BIT(0),
+ OVL0_MOUT_EN_OVL0_2L = BIT(4),
+ OVL0_2L_MOUT_EN_DISP_PATH0 = BIT(0),
+ OVL1_2L_MOUT_EN_DISP_RDMA1 = BIT(4),
+ DITHER0_MOUT_EN_DISP_DSI0 = BIT(0),
+};
+
+enum {
+ DISP_PATH0_SEL_IN_OVL0 = 0,
+ DISP_PATH0_SEL_IN_OVL0_2L = 1,
+ DSI0_SEL_IN_DITHER0_MOUT = 0,
+ DSI0_SEL_IN_RDMA0 = 1,
+ RDMA0_SOUT_SEL_IN_DSI0 = 0,
+ RDMA0_SOUT_SEL_IN_COLOR = 1,
+};
+
+struct disp_mutex_regs {
+ u32 inten;
+ u32 intsta;
+ u32 reserved0[6];
+ struct {
+ u32 en;
+ u32 dummy;
+ u32 rst;
+ u32 ctl;
+ u32 mod;
+ u32 reserved[3];
+ } mutex[12];
+};
+
+static struct disp_mutex_regs *const disp_mutex = (void *)DISP_MUTEX_BASE;
+
+enum {
+ MUTEX_MOD_DISP_RDMA0 = BIT(0),
+ MUTEX_MOD_DISP_RDMA1 = BIT(1),
+ MUTEX_MOD_DISP_OVL0 = BIT(9),
+ MUTEX_MOD_DISP_OVL0_2L = BIT(10),
+ MUTEX_MOD_DISP_OVL1_2L = BIT(11),
+ MUTEX_MOD_DISP_WDMA0 = BIT(12),
+ MUTEX_MOD_DISP_COLOR0 = BIT(13),
+ MUTEX_MOD_DISP_CCORR0 = BIT(14),
+ MUTEX_MOD_DISP_AAL0 = BIT(15),
+ MUTEX_MOD_DISP_GAMMA0 = BIT(16),
+ MUTEX_MOD_DISP_DITHER0 = BIT(17),
+ MUTEX_MOD_DISP_PWM0 = BIT(28),
+ MUTEX_MOD_MAIN_PATH = MUTEX_MOD_DISP_OVL0 | MUTEX_MOD_DISP_OVL0_2L |
+ MUTEX_MOD_DISP_RDMA0 | MUTEX_MOD_DISP_COLOR0 |
+ MUTEX_MOD_DISP_CCORR0 | MUTEX_MOD_DISP_AAL0 |
+ MUTEX_MOD_DISP_GAMMA0 |
+ MUTEX_MOD_DISP_DITHER0,
+};
+
+enum {
+ MUTEX_SOF_SINGLE_MODE = 0,
+ MUTEX_SOF_DSI0 = 1,
+ MUTEX_SOF_DPI0 = 2,
+};
+
+struct disp_ovl_regs {
+ u32 sta;
+ u32 inten;
+ u32 intsta;
+ u32 en;
+ u32 trig;
+ u32 rst;
+ u32 reserved_0x018[2];
+ u32 roi_size;
+ u32 datapath_con;
+ u32 roi_bgclr;
+ u32 src_con;
+ struct {
+ u32 con;
+ u32 srckey;
+ u32 src_size;
+ u32 offset;
+ u32 reserved0;
+ u32 pitch;
+ u32 reserved1[2];
+ } layer[4];
+ u32 reserved_0x0B0[4];
+ struct {
+ u32 ctrl;
+ u32 reserved0;
+ u32 mem_gmc_setting;
+ u32 mem_slow_con;
+ u32 fifo_ctrl;
+ u32 reserved1[3];
+ } rdma[4];
+ u32 reserved_0x140[880];
+ u32 reserved_0xF00[16];
+ u32 l0_addr;
+ u32 reserved_0xF44[7];
+ u32 l1_addr;
+ u32 reserved_0xF64[7];
+ u32 l2_addr;
+ u32 reserved_0xF84[7];
+ u32 l3_addr;
+};
+
+check_member(disp_ovl_regs, l3_addr, 0xFA0);
+static struct disp_ovl_regs *const disp_ovl[2] = {
+ (void *)DISP_OVL0_BASE, (void *)DISP_OVL0_2L_BASE
+};
+
+struct disp_rdma_regs {
+ u32 int_enable;
+ u32 int_status;
+ u32 reserved0[2];
+ u32 global_con;
+ u32 size_con_0;
+ u32 size_con_1;
+ u32 target_line;
+ u32 reserved1;
+ u32 mem_con;
+ u32 reserved2;
+ u32 mem_src_pitch;
+ u32 mem_gmc_setting_0;
+ u32 mem_gmc_setting_1;
+ u32 mem_slow_con;
+ u32 mem_gmc_setting_2;
+ u32 fifo_con;
+ u32 reserved3[4];
+ u32 cf[3][3];
+ u32 cf_pre_add[3];
+ u32 cf_post_add[3];
+ u32 dummy;
+ u32 debug_out_sel;
+};
+
+enum {
+ RDMA_ENGINE_EN = BIT(0),
+ RDMA_FIFO_UNDERFLOW_EN = BIT(31),
+ RDMA_FIFO_SIZE_0 = 5, /* 5K */
+ RDMA_VREFRESH = 60, /* vrefresh 60HZ */
+ RDMA_MEM_GMC = 0x40402020,
+};
+
+check_member(disp_rdma_regs, debug_out_sel, 0x94);
+static struct disp_rdma_regs *const disp_rdma[2] = {
+ (void *)DISP_RDMA0_BASE,
+ (void *)DISP_RDMA1_BASE,
+};
+
+struct disp_color_regs {
+ u8 reserved0[1024];
+ u32 cfg_main;
+ u8 reserved1[2044];
+ u32 start;
+ u8 reserved2[76];
+ u32 width;
+ u32 height;
+};
+
+check_member(disp_color_regs, height, 0xC54);
+static struct disp_color_regs *const disp_color = (void *)DISP_COLOR0_BASE;
+
+enum {
+ COLOR_BYPASS_ALL = BIT(7),
+ COLOR_SEQ_SEL = BIT(13),
+};
+
+struct disp_pq_regs {
+ u32 en;
+ u32 reset;
+ u32 inten;
+ u32 intsta;
+ u32 status;
+ u32 reserved0[3];
+ u32 cfg;
+ u32 reserved1[3];
+ u32 size;
+};
+
+enum {
+ PQ_EN = BIT(0),
+ PQ_RELAY_MODE = BIT(0),
+};
+
+static struct disp_pq_regs *const disp_ccorr = (void *)DISP_CCORR0_BASE;
+
+static struct disp_pq_regs *const disp_aal = (void *)DISP_AAL0_BASE;
+
+static struct disp_pq_regs *const disp_gamma = (void *)DISP_GAMMA0_BASE;
+
+static struct disp_pq_regs *const disp_dither = (void *)DISP_DITHER0_BASE;
+
+enum {
+ SMI_LARB_NON_SEC_CON = 0x380,
+};
+
+enum OVL_INPUT_FORMAT {
+ OVL_INFMT_RGB565 = 0,
+ OVL_INFMT_RGB888 = 1,
+ OVL_INFMT_RGBA8888 = 2,
+ OVL_INFMT_ARGB8888 = 3,
+ OVL_INFMT_UYVY = 4,
+ OVL_INFMT_YUYV = 5,
+ OVL_INFMT_UNKNOWN = 16,
+
+ OVL_COLOR_BASE = 30,
+ OVL_INFMT_BGR565 = OVL_INFMT_RGB565 + OVL_COLOR_BASE,
+ OVL_INFMT_BGR888 = OVL_INFMT_RGB888 + OVL_COLOR_BASE,
+ OVL_INFMT_BGRA8888 = OVL_INFMT_RGBA8888 + OVL_COLOR_BASE,
+ OVL_INFMT_ABGR8888 = OVL_INFMT_ARGB8888 + OVL_COLOR_BASE,
+};
+
+void mtk_ddp_init(void);
+void mtk_ddp_mode_set(const struct edid *edid);
+
+#endif
diff --git a/src/soc/mediatek/mt8183/include/soc/dsi.h b/src/soc/mediatek/mt8183/include/soc/dsi.h
new file mode 100644
index 0000000..dc89668
--- /dev/null
+++ b/src/soc/mediatek/mt8183/include/soc/dsi.h
@@ -0,0 +1,487 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 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.
+ */
+
+#ifndef _DSI_REG_H_
+#define _DSI_REG_H_
+
+#include <edid.h>
+#include <soc/addressmap.h>
+#include <types.h>
+
+enum mipi_dsi_pixel_format {
+ MIPI_DSI_FMT_RGB888,
+ MIPI_DSI_FMT_RGB666,
+ MIPI_DSI_FMT_RGB666_PACKED,
+ MIPI_DSI_FMT_RGB565
+};
+
+/* video mode */
+enum {
+ MIPI_DSI_MODE_VIDEO = BIT(0),
+ /* video burst mode */
+ MIPI_DSI_MODE_VIDEO_BURST = BIT(1),
+ /* video pulse mode */
+ MIPI_DSI_MODE_VIDEO_SYNC_PULSE = BIT(2),
+ /* enable auto vertical count mode */
+ MIPI_DSI_MODE_VIDEO_AUTO_VERT = BIT(3),
+ /* enable hsync-end packets in vsync-pulse and v-porch area */
+ MIPI_DSI_MODE_VIDEO_HSE = BIT(4),
+ /* disable hfront-porch area */
+ MIPI_DSI_MODE_VIDEO_HFP = BIT(5),
+ /* disable hback-porch area */
+ MIPI_DSI_MODE_VIDEO_HBP = BIT(6),
+ /* disable hsync-active area */
+ MIPI_DSI_MODE_VIDEO_HSA = BIT(7),
+ /* flush display FIFO on vsync pulse */
+ MIPI_DSI_MODE_VSYNC_FLUSH = BIT(8),
+ /* disable EoT packets in HS mode */
+ MIPI_DSI_MODE_EOT_PACKET = BIT(9),
+ /* device supports non-continuous clock behavior (DSI spec 5.6.1) */
+ MIPI_DSI_CLOCK_NON_CONTINUOUS = BIT(10),
+ /* transmit data in low power */
+ MIPI_DSI_MODE_LPM = BIT(11)
+};
+
+struct dsi_regs {
+ u32 dsi_start;
+ u8 reserved0[4];
+ u32 dsi_inten;
+ u32 dsi_intsta;
+ u32 dsi_con_ctrl;
+ u32 dsi_mode_ctrl;
+ u32 dsi_txrx_ctrl;
+ u32 dsi_psctrl;
+ u32 dsi_vsa_nl;
+ u32 dsi_vbp_nl;
+ u32 dsi_vfp_nl;
+ u32 dsi_vact_nl;
+ u32 dsi_lfr_con;
+ u32 dsi_lfr_sta;
+ u32 dsi_size_con;
+ u32 dsi_vfp_early_stop;
+ u32 reserved1[4];
+ u32 dsi_hsa_wc;
+ u32 dsi_hbp_wc;
+ u32 dsi_hfp_wc;
+ u32 dsi_bllp_wc;
+ u32 dsi_cmdq_size;
+ u32 dsi_hstx_cklp_wc;
+ u8 reserved2[156];
+ u32 dsi_phy_lccon;
+ u32 dsi_phy_ld0con;
+ u8 reserved3[4];
+ u32 dsi_phy_timecon0;
+ u32 dsi_phy_timecon1;
+ u32 dsi_phy_timecon2;
+ u32 dsi_phy_timecon3;
+ u8 reserved4[16];
+ u32 dsi_vm_cmd_con;
+ u8 reserved5[92];
+ u32 dsi_force_commit;
+ u8 reserved6[108];
+ u32 dsi_cmdq0;
+};
+
+check_member(dsi_regs, dsi_phy_lccon, 0x104);
+check_member(dsi_regs, dsi_phy_timecon3, 0x11c);
+check_member(dsi_regs, dsi_vm_cmd_con, 0x130);
+check_member(dsi_regs, dsi_force_commit, 0x190);
+check_member(dsi_regs, dsi_cmdq0, 0x200);
+static struct dsi_regs *const dsi = (void *)DSI_BASE;
+
+#define DELAY_CMD 0
+#define END_OF_TABLE 1
+#define INIT_GENENIC_CMD 2
+#define INIT_DCS_CMD 3
+
+struct lcm_init_table {
+ u32 cmd;
+ u32 len;
+ u8 data[64];
+};
+
+struct mtk_phy_timing {
+ u8 lpx;
+ u8 da_hs_prepare;
+ u8 da_hs_zero;
+ u8 da_hs_trail;
+
+ u8 ta_go;
+ u8 ta_sure;
+ u8 ta_get;
+ u8 da_hs_exit;
+
+ u8 clk_hs_zero;
+ u8 clk_hs_trail;
+
+ u8 clk_hs_prepare;
+ u8 clk_hs_post;
+ u8 clk_hs_exit;
+};
+
+/* DSI_INTSTA */
+enum {
+ LPRX_RD_RDY_INT_FLAG = BIT(0),
+ CMD_DONE_INT_FLAG = BIT(1),
+ TE_RDY_INT_FLAG = BIT(2),
+ VM_DONE_INT_FLAG = BIT(3),
+ EXT_TE_RDY_INT_FLAG = BIT(4),
+ DSI_BUSY = BIT(31),
+};
+
+/* DSI_CON_CTRL */
+enum {
+ DSI_RESET = BIT(0),
+ DSI_EN = BIT(1),
+ DSI_DUAL = BIT(4),
+};
+
+/* DSI_MODE_CTRL */
+enum {
+ MODE = 3,
+ CMD_MODE = 0,
+ SYNC_PULSE_MODE = 1,
+ SYNC_EVENT_MODE = 2,
+ BURST_MODE = 3,
+ FRM_MODE = BIT(16),
+ MIX_MODE = BIT(17)
+};
+
+/* DSI_PSCTRL */
+enum {
+ DSI_PS_WC = 0x3fff,
+ DSI_PS_SEL = (3 << 16),
+ PACKED_PS_16BIT_RGB565 = (0 << 16),
+ LOOSELY_PS_18BIT_RGB666 = (1 << 16),
+ PACKED_PS_18BIT_RGB666 = (2 << 16),
+ PACKED_PS_24BIT_RGB888 = (3 << 16)
+};
+
+/* DSI_CMDQ_SIZE */
+enum {
+ CMDQ_SIZE = 0x3f,
+};
+
+/* DSI_PHY_LCCON */
+enum {
+ LC_HS_TX_EN = BIT(0),
+ LC_ULPM_EN = BIT(1),
+ LC_WAKEUP_EN = BIT(2)
+};
+
+/*DSI_PHY_LD0CON */
+enum {
+ LD0_RM_TRIG_EN = BIT(0),
+ LD0_ULPM_EN = BIT(1),
+ LD0_WAKEUP_EN = BIT(2)
+};
+
+enum {
+ LPX = (0xff << 0),
+ HS_PRPR = (0xff << 8),
+ HS_ZERO = (0xff << 16),
+ HS_TRAIL = (0xff << 24)
+};
+
+enum {
+ TA_GO = (0xff << 0),
+ TA_SURE = (0xff << 8),
+ TA_GET = (0xff << 16),
+ DA_HS_EXIT = (0xff << 24)
+};
+
+enum {
+ CONT_DET = (0xff << 0),
+ CLK_ZERO = (0xf << 16),
+ CLK_TRAIL = (0xff << 24)
+};
+
+enum {
+ CLK_HS_PRPR = (0xff << 0),
+ CLK_HS_POST = (0xff << 8),
+ CLK_HS_EXIT = (0xf << 16)
+};
+
+/* DSI_VM_CMD_CON */
+enum {
+ VM_CMD_EN = BIT(0),
+ TS_VFP_EN = BIT(5),
+};
+
+/* DSI_CMDQ0 */
+enum {
+ CONFIG = (0xff << 0),
+ SHORT_PACKET = 0,
+ LONG_PACKET = 2,
+ BTA = BIT(2),
+ DATA_ID = (0xff << 8),
+ DATA_0 = (0xff << 16),
+ DATA_1 = (0xff << 24),
+};
+
+#define MIPITX_LANE_CON 0x000c
+#define MIPITX_PLL_PWR 0x0028
+#define MIPITX_PLL_CON0 0x002c
+#define MIPITX_PLL_CON1 0x0030
+#define MIPITX_PLL_CON2 0x0034
+#define MIPITX_PLL_CON3 0x0038
+#define MIPITX_PLL_CON4 0x003c
+#define MIPITX_D2_SW_CTL_EN 0x0144
+#define MIPITX_D0_SW_CTL_EN 0x0244
+#define MIPITX_CK_CKMODE_EN 0x0328
+#define DSI_CK_CKMODE_EN BIT(0)
+#define MIPITX_CK_SW_CTL_EN 0x0344
+#define MIPITX_D1_SW_CTL_EN 0x0444
+#define MIPITX_D3_SW_CTL_EN 0x0544
+#define DSI_SW_CTL_EN BIT(0)
+#define AD_DSI_PLL_SDM_PWR_ON BIT(0)
+#define AD_DSI_PLL_SDM_ISO_EN BIT(1)
+
+#define RG_DSI_PLL_EN BIT(4)
+#define RG_DSI_PLL_POSDIV (0x7 << 8)
+
+/* MIPITX_REG */
+struct mipi_tx_regs {
+ u32 dsi_con;
+ u32 dsi_clock_lane;
+ u32 dsi_data_lane[4];
+ u8 reserved0[40];
+ u32 dsi_top_con;
+ u32 dsi_bg_con;
+ u8 reserved1[8];
+ u32 dsi_pll_con0;
+ u32 dsi_pll_con1;
+ u32 dsi_pll_con2;
+ u32 dsi_pll_con3;
+ u32 dsi_pll_chg;
+ u32 dsi_pll_top;
+ u32 dsi_pll_pwr;
+ u8 reserved2[4];
+ u32 dsi_rgs;
+ u32 dsi_gpi_en;
+ u32 dsi_gpi_pull;
+ u32 dsi_phy_sel;
+ u32 dsi_sw_ctrl_en;
+ u32 dsi_sw_ctrl_con0;
+ u32 dsi_sw_ctrl_con1;
+ u32 dsi_sw_ctrl_con2;
+ u32 dsi_dbg_con;
+ u32 dsi_dbg_out;
+ u32 dsi_apb_async_sta;
+};
+
+check_member(mipi_tx_regs, dsi_top_con, 0x40);
+check_member(mipi_tx_regs, dsi_pll_pwr, 0x68);
+
+static void *const mipi_tx = (void *)MIPITX_BASE;
+
+/* MIPITX_DSI_CON */
+enum {
+ RG_DSI_LDOCORE_EN = BIT(0),
+ RG_DSI_CKG_LDOOUT_EN = BIT(1),
+ RG_DSI_BCLK_SEL = (3 << 2),
+ RG_DSI_LD_IDX_SEL = (7 << 4),
+ RG_DSI_PHYCLK_SEL = (2 << 8),
+ RG_DSI_DSICLK_FREQ_SEL = BIT(10),
+ RG_DSI_LPTX_CLMP_EN = BIT(11)
+};
+
+/* MIPITX_DSI_CLOCK_LANE */
+enum {
+ LDOOUT_EN = BIT(0),
+ CKLANE_EN = BIT(1),
+ IPLUS1 = BIT(2),
+ LPTX_IPLUS2 = BIT(3),
+ LPTX_IMINUS = BIT(4),
+ LPCD_IPLUS = BIT(5),
+ LPCD_IMLUS = BIT(6),
+ RT_CODE = (0xf << 8)
+};
+
+/* MIPITX_DSI_TOP_CON */
+enum {
+ RG_DSI_LNT_INTR_EN = BIT(0),
+ RG_DSI_LNT_HS_BIAS_EN = BIT(1),
+ RG_DSI_LNT_IMP_CAL_EN = BIT(2),
+ RG_DSI_LNT_TESTMODE_EN = BIT(3),
+ RG_DSI_LNT_IMP_CAL_CODE = (0xf << 4),
+ RG_DSI_LNT_AIO_SEL = (7 << 8),
+ RG_DSI_PAD_TIE_LOW_EN = BIT(11),
+ RG_DSI_DEBUG_INPUT_EN = BIT(12),
+ RG_DSI_PRESERVE = (7 << 13)
+};
+
+/* MIPITX_DSI_BG_CON */
+enum {
+ RG_DSI_BG_CORE_EN = BIT(0),
+ RG_DSI_BG_CKEN = BIT(1),
+ RG_DSI_BG_DIV = (0x3 << 2),
+ RG_DSI_BG_FAST_CHARGE = BIT(4),
+ RG_DSI_V12_SEL = (7 << 5),
+ RG_DSI_V10_SEL = (7 << 8),
+ RG_DSI_V072_SEL = (7 << 11),
+ RG_DSI_V04_SEL = (7 << 14),
+ RG_DSI_V032_SEL = (7 << 17),
+ RG_DSI_V02_SEL = (7 << 20),
+ rsv_23 = BIT(23),
+ RG_DSI_BG_R1_TRIM = (0xf << 24),
+ RG_DSI_BG_R2_TRIM = (0xf << 28)
+};
+
+/* MIPITX_DSI_PLL_CON0 */
+enum {
+ RG_DSI_MPPLL_PLL_EN = BIT(0),
+ RG_DSI_MPPLL_PREDIV = (3 << 1),
+ RG_DSI_MPPLL_TXDIV0 = (3 << 3),
+ RG_DSI_MPPLL_TXDIV1 = (3 << 5),
+ RG_DSI_MPPLL_POSDIV = (7 << 7),
+ RG_DSI_MPPLL_MONVC_EN = BIT(10),
+ RG_DSI_MPPLL_MONREF_EN = BIT(11),
+ RG_DSI_MPPLL_VOD_EN = BIT(12)
+};
+
+/* MIPITX_DSI_PLL_CON1 */
+enum {
+ RG_DSI_MPPLL_SDM_FRA_EN = BIT(0),
+ RG_DSI_MPPLL_SDM_SSC_PH_INIT = BIT(1),
+ RG_DSI_MPPLL_SDM_SSC_EN = BIT(2),
+ RG_DSI_MPPLL_SDM_SSC_PRD = (0xffff << 16)
+};
+
+/* MIPITX_DSI_PLL_PWR */
+enum {
+ RG_DSI_MPPLL_SDM_PWR_ON = BIT(0),
+ RG_DSI_MPPLL_SDM_ISO_EN = BIT(1),
+ RG_DSI_MPPLL_SDM_PWR_ACK = BIT(8)
+};
+
+/* MIPI DSI Processor-to-Peripheral transaction types */
+enum {
+ MIPI_DSI_V_SYNC_START = 0x01,
+ MIPI_DSI_V_SYNC_END = 0x11,
+ MIPI_DSI_H_SYNC_START = 0x21,
+ MIPI_DSI_H_SYNC_END = 0x31,
+
+ MIPI_DSI_COLOR_MODE_OFF = 0x02,
+ MIPI_DSI_COLOR_MODE_ON = 0x12,
+ MIPI_DSI_SHUTDOWN_PERIPHERAL = 0x22,
+ MIPI_DSI_TURN_ON_PERIPHERAL = 0x32,
+
+ MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM = 0x03,
+ MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM = 0x13,
+ MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM = 0x23,
+
+ MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM = 0x04,
+ MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM = 0x14,
+ MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM = 0x24,
+
+ MIPI_DSI_DCS_SHORT_WRITE = 0x05,
+ MIPI_DSI_DCS_SHORT_WRITE_PARAM = 0x15,
+
+ MIPI_DSI_DCS_READ = 0x06,
+
+ MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE = 0x37,
+
+ MIPI_DSI_END_OF_TRANSMISSION = 0x08,
+
+ MIPI_DSI_NULL_PACKET = 0x09,
+ MIPI_DSI_BLANKING_PACKET = 0x19,
+ MIPI_DSI_GENERIC_LONG_WRITE = 0x29,
+ MIPI_DSI_DCS_LONG_WRITE = 0x39,
+
+ MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20 = 0x0c,
+ MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24 = 0x1c,
+ MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16 = 0x2c,
+
+ MIPI_DSI_PACKED_PIXEL_STREAM_30 = 0x0d,
+ MIPI_DSI_PACKED_PIXEL_STREAM_36 = 0x1d,
+ MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12 = 0x3d,
+
+ MIPI_DSI_PACKED_PIXEL_STREAM_16 = 0x0e,
+ MIPI_DSI_PACKED_PIXEL_STREAM_18 = 0x1e,
+ MIPI_DSI_PIXEL_STREAM_3BYTE_18 = 0x2e,
+ MIPI_DSI_PACKED_PIXEL_STREAM_24 = 0x3e,
+};
+
+/* MIPI DSI Peripheral-to-Processor transaction types */
+enum {
+ MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT = 0x02,
+ MIPI_DSI_RX_END_OF_TRANSMISSION = 0x08,
+ MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE = 0x11,
+ MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE = 0x12,
+ MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE = 0x1a,
+ MIPI_DSI_RX_DCS_LONG_READ_RESPONSE = 0x1c,
+ MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE = 0x21,
+ MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE = 0x22,
+};
+
+/* MIPI DCS commands */
+enum {
+ MIPI_DCS_NOP = 0x00,
+ MIPI_DCS_SOFT_RESET = 0x01,
+ MIPI_DCS_GET_DISPLAY_ID = 0x04,
+ MIPI_DCS_GET_RED_CHANNEL = 0x06,
+ MIPI_DCS_GET_GREEN_CHANNEL = 0x07,
+ MIPI_DCS_GET_BLUE_CHANNEL = 0x08,
+ MIPI_DCS_GET_DISPLAY_STATUS = 0x09,
+ MIPI_DCS_GET_POWER_MODE = 0x0A,
+ MIPI_DCS_GET_ADDRESS_MODE = 0x0B,
+ MIPI_DCS_GET_PIXEL_FORMAT = 0x0C,
+ MIPI_DCS_GET_DISPLAY_MODE = 0x0D,
+ MIPI_DCS_GET_SIGNAL_MODE = 0x0E,
+ MIPI_DCS_GET_DIAGNOSTIC_RESULT = 0x0F,
+ MIPI_DCS_ENTER_SLEEP_MODE = 0x10,
+ MIPI_DCS_EXIT_SLEEP_MODE = 0x11,
+ MIPI_DCS_ENTER_PARTIAL_MODE = 0x12,
+ MIPI_DCS_ENTER_NORMAL_MODE = 0x13,
+ MIPI_DCS_EXIT_INVERT_MODE = 0x20,
+ MIPI_DCS_ENTER_INVERT_MODE = 0x21,
+ MIPI_DCS_SET_GAMMA_CURVE = 0x26,
+ MIPI_DCS_SET_DISPLAY_OFF = 0x28,
+ MIPI_DCS_SET_DISPLAY_ON = 0x29,
+ MIPI_DCS_SET_COLUMN_ADDRESS = 0x2A,
+ MIPI_DCS_SET_PAGE_ADDRESS = 0x2B,
+ MIPI_DCS_WRITE_MEMORY_START = 0x2C,
+ MIPI_DCS_WRITE_LUT = 0x2D,
+ MIPI_DCS_READ_MEMORY_START = 0x2E,
+ MIPI_DCS_SET_PARTIAL_AREA = 0x30,
+ MIPI_DCS_SET_SCROLL_AREA = 0x33,
+ MIPI_DCS_SET_TEAR_OFF = 0x34,
+ MIPI_DCS_SET_TEAR_ON = 0x35,
+ MIPI_DCS_SET_ADDRESS_MODE = 0x36,
+ MIPI_DCS_SET_SCROLL_START = 0x37,
+ MIPI_DCS_EXIT_IDLE_MODE = 0x38,
+ MIPI_DCS_ENTER_IDLE_MODE = 0x39,
+ MIPI_DCS_SET_PIXEL_FORMAT = 0x3A,
+ MIPI_DCS_WRITE_MEMORY_CONTINUE = 0x3C,
+ MIPI_DCS_READ_MEMORY_CONTINUE = 0x3E,
+ MIPI_DCS_SET_TEAR_SCANLINE = 0x44,
+ MIPI_DCS_GET_SCANLINE = 0x45,
+ MIPI_DCS_READ_DDB_START = 0xA1,
+ MIPI_DCS_READ_DDB_CONTINUE = 0xA8,
+};
+
+#define MTK_DSI_HOST_IS_READ(type) \
+ ((type == MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM) || \
+ (type == MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM) || \
+ (type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM) || \
+ (type == MIPI_DSI_DCS_READ))
+
+extern int mtk_dsi_init(u32 mode_flags, u32 format, u32 lanes, bool dual,
+ const struct edid *edid,
+ struct lcm_init_table *init_cmd,
+ u32 count);
+
+#endif

To view, visit change 33106. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I09d127ab491bca98f3a9c9b7d4ad4b09674c963d
Gerrit-Change-Number: 33106
Gerrit-PatchSet: 1
Gerrit-Owner: jitao shi <jitao.shi@mediatek.com>
Gerrit-MessageType: newchange