Ravi kumar has uploaded this change for review.

View Change

sc7180: Add display hardware pipe line initialization [patch 3 of 3]

Add sc7180 display hardware pipeline programming support
and invoke the display initialization from soc_init

Change-Id: I7d5e3f1781c48759553243abeb3d694f76cd008e
Signed-off-by: Vinod Polimera <vpolimer@codeaurora.org>
---
M src/soc/qualcomm/sc7180/Kconfig
M src/soc/qualcomm/sc7180/Makefile.inc
A src/soc/qualcomm/sc7180/display.c
A src/soc/qualcomm/sc7180/display/mdss.c
A src/soc/qualcomm/sc7180/display/oem_panel.c
A src/soc/qualcomm/sc7180/include/soc/display.h
A src/soc/qualcomm/sc7180/include/soc/display/panel_sn65dsix6_auo_bll6xak01_dsi_video.h
M src/soc/qualcomm/sc7180/soc.c
8 files changed, 1,448 insertions(+), 1 deletion(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/15/39615/1
diff --git a/src/soc/qualcomm/sc7180/Kconfig b/src/soc/qualcomm/sc7180/Kconfig
index 5ef5360..b07f518 100644
--- a/src/soc/qualcomm/sc7180/Kconfig
+++ b/src/soc/qualcomm/sc7180/Kconfig
@@ -14,6 +14,9 @@
select SOC_QUALCOMM_COMMON
select HAVE_UART_SPECIAL
select BOOTBLOCK_CONSOLE
+ select MAINBOARD_HAS_NATIVE_VGA_INIT
+ select MAINBOARD_FORCE_NATIVE_VGA_INIT
+ select HAVE_LINEAR_FRAMEBUFFER

if SOC_QUALCOMM_SC7180

diff --git a/src/soc/qualcomm/sc7180/Makefile.inc b/src/soc/qualcomm/sc7180/Makefile.inc
index 7df4f6e..8bdd329 100644
--- a/src/soc/qualcomm/sc7180/Makefile.inc
+++ b/src/soc/qualcomm/sc7180/Makefile.inc
@@ -59,6 +59,14 @@
ramstage-y += qupv3_config.c
ramstage-y += qcom_qup_se.c
ramstage-$(CONFIG_DRIVERS_UART) += qupv3_uart.c
+ramstage-$(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) += display/oem_panel.c
+ramstage-$(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) += display/mdss.c
+ramstage-$(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) += display/target_sc7180.c
+ramstage-$(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) += display/dsi_panel_display.c
+ramstage-$(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) += display/dsi_phy_pll.c
+ramstage-$(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) += display/dsi_phy.c
+ramstage-$(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) += display/dsi.c
+ramstage-$(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT) += display.c

################################################################################

diff --git a/src/soc/qualcomm/sc7180/display.c b/src/soc/qualcomm/sc7180/display.c
new file mode 100644
index 0000000..1759179
--- /dev/null
+++ b/src/soc/qualcomm/sc7180/display.c
@@ -0,0 +1,275 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2020 Qualcomm Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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 <stdlib.h>
+#include <console/console.h>
+#include <delay.h>
+#include <device/device.h>
+#include <soc/mdss_6_2_0.h>
+#include <soc/display/panel.h>
+#include <soc/display/mipi_dsi.h>
+#include <soc/display/panel_display.h>
+#include <soc/display/target_sc7180.h>
+#include <soc/display.h>
+
+static struct msm_fb_panel_data panel;
+struct panel_struct panelstruct;
+static uint8_t display_enable;
+static struct mdss_dsi_phy_ctrl dsi_video_mode_phy_db;
+extern int msm_display_init(struct msm_fb_panel_data *pdata);
+int msm_display_config(void);
+
+static int update_dsi_display_config(void)
+{
+ /* Place holder to handle dual dsi cases in future */
+ int ret = NO_ERROR;
+ return ret;
+}
+
+static uint32_t mdss_dsi_panel_clock(uint8_t enable,
+ struct msm_panel_info *pinfo)
+{
+ /* MDSS Clocks are set in QCLib. DSI clocks are set after programming
+ * DSI Phy and Pll. This will be place holder if we want to enable
+ * MDSS Clocks in coreboot later.
+ */
+ return NO_ERROR;
+}
+
+static uint32_t mdss_dsi_panel_reset(uint8_t enable)
+{
+ uint32_t ret = NO_ERROR;
+// if (panelstruct.panelresetseq) //TODO: check if bridge reset seq?
+ ret = target_panel_reset(enable, panelstruct.panelresetseq,
+ &panel.panel_info);
+ return ret;
+}
+
+static int mdss_dsi_panel_power(uint8_t enable,
+ struct msm_panel_info *pinfo)
+{
+ int ret = NO_ERROR;
+ if (enable) {
+ ret = mdss_dsi_panel_reset(enable);
+ if (ret) {
+ printk(BIOS_ERR, "panel reset failed\n");
+ return ret;
+ }
+ } else {
+ ret = mdss_dsi_panel_reset(enable);
+ if (ret) {
+ printk(BIOS_ERR, "panel reset disable failed\n");
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static int mdss_dsi_panel_pre_init(void)
+{
+ int ret = NO_ERROR;
+ if (panelstruct.paneldata->panel_lp11_init) {
+ ret = mdss_dsi_panel_reset(1);
+ if (ret) {
+ printk(BIOS_ERR, "panel reset failed\n");
+ return ret;
+ }
+ }
+ if (panelstruct.paneldata->panel_init_delay)
+ udelay(panelstruct.paneldata->panel_init_delay);
+
+ printk(BIOS_INFO, "Panel pre init done\n");
+ return ret;
+}
+
+static int mdss_dsi_bl_enable(uint8_t enable)
+{
+ int ret = NO_ERROR;
+
+ ret = target_backlight_ctrl(enable);
+ if (ret)
+ printk(BIOS_ERR, "Backlight %s failed\n", enable ? "enable" :
+ "disable");
+ return ret;
+}
+
+int msm_display_config(void)
+{
+ int ret = NO_ERROR;
+ struct msm_panel_info *pinfo;
+ pinfo = &(panel.panel_info);
+
+ mdp_set_revision(panel.mdp_rev);
+
+ switch (pinfo->type) {
+ case MIPI_VIDEO_PANEL:
+ printk(BIOS_INFO, "Config MIPI_VIDEO_PANEL.\n");
+ ret = mdss_dsi_config(&panel);
+ if (ret)
+ goto msm_display_config_out;
+
+ if (pinfo->early_config)
+ ret = pinfo->early_config((void *)pinfo);
+
+ ret = mdp_dsi_video_config(pinfo, &(panel.fb));
+
+ if (ret)
+ goto msm_display_config_out;
+
+ break;
+ default:
+ return ERROR;
+ }
+ if (pinfo->config)
+ ret = pinfo->config((void *)pinfo);
+
+msm_display_config_out:
+ return ret;
+}
+
+int msm_display_init(struct msm_fb_panel_data *pdata)
+{
+ int ret = NO_ERROR;
+
+ printk(BIOS_INFO, "%s: Display Initialization start\n", __func__);
+ if (!pdata) {
+ ret = ERROR;
+ goto msm_display_init_out;
+ }
+ /* Turn on panel */
+ if (pdata->power_func)
+ ret = pdata->power_func(1, &(pdata->panel_info));
+
+ if (ret)
+ goto msm_display_init_out;
+
+ /* Enable clock */
+ if (pdata->clk_func)
+ ret = pdata->clk_func(1, &(pdata->panel_info));
+ if (ret)
+ goto msm_display_init_out;
+
+ if (pdata->update_panel_info)
+ ret = pdata->update_panel_info();
+
+ if (ret)
+ goto msm_display_init_out;
+
+ if (pdata->pll_clk_func)
+ ret = pdata->pll_clk_func(1, &(pdata->panel_info));
+ if (ret)
+ goto msm_display_init_out;
+
+ /* pinfo prepare */
+ if (pdata->panel_info.prepare) {
+ /* this is for edp which pinfo derived from edid */
+ ret = pdata->panel_info.prepare();
+ pdata->fb.width = pdata->panel_info.xres;
+ pdata->fb.height = pdata->panel_info.yres;
+ pdata->fb.stride = pdata->panel_info.xres;
+ pdata->fb.bpp = pdata->panel_info.bpp;
+ }
+
+ if (ret)
+ goto msm_display_init_out;
+
+ ret = msm_display_config();
+
+ if (ret)
+ goto msm_display_init_out;
+
+ ret = mdp_dsi_video_on(&(pdata->panel_info));
+
+ if (ret)
+ goto msm_display_init_out;
+
+ if (pdata->post_power_func)
+ ret = pdata->post_power_func(1);
+
+ if (ret)
+ goto msm_display_init_out;
+
+ /* Turn on backlight */
+ if (pdata->bl_func)
+ ret = pdata->bl_func(1);
+ if (ret)
+ goto msm_display_init_out;
+
+msm_display_init_out:
+ return ret;
+}
+
+/* This has to be called from soc init, with right MDP rev */
+int display_init(const char *panel_name, uint32_t rev, struct edid *ed)
+{
+ int ret = NO_ERROR;
+ int pan_type;
+ dsi_video_mode_phy_db.pll_type = DSI_PLL_TYPE_10NM;
+ printk(BIOS_INFO, " display init!\n");
+ pan_type = oem_panel_select(panel_name, &panelstruct,
+ &(panel.panel_info),
+ &dsi_video_mode_phy_db);
+ if (pan_type == PANEL_TYPE_DSI) {
+ if (update_dsi_display_config())
+ goto error_display_init;
+ target_dsi_phy_config(&dsi_video_mode_phy_db);
+ if (dsi_panel_init(&(panel.panel_info), &panelstruct)) {
+ printk(BIOS_ERR, "DSI panel init failed!\n");
+ ret = ERROR;
+ goto error_display_init;
+ }
+ panel.panel_info.mipi.mdss_dsi_phy_db = &dsi_video_mode_phy_db;
+ panel.pll_clk_func = mdss_dsi_panel_clock;
+ panel.power_func = mdss_dsi_panel_power;
+ panel.pre_init_func = mdss_dsi_panel_pre_init;
+ panel.bl_func = mdss_dsi_bl_enable;
+
+ panel.fb.base = NULL; /* Filled in DC */
+ panel.fb.width = panel.panel_info.xres;
+ panel.fb.height = panel.panel_info.yres;
+ panel.fb.stride = panel.panel_info.xres;
+ panel.fb.bpp = panel.panel_info.bpp;
+ panel.fb.format = panel.panel_info.mipi.dst_format;
+ panel.fb.sbpp = FRAMEBUFFER_SRC_BPP;
+ if (ed != NULL) {
+ ed->mode.ha = panel.panel_info.xres;
+ ed->mode.va = panel.panel_info.yres;
+ ed->framebuffer_bits_per_pixel = FRAMEBUFFER_SRC_BPP;
+ }
+ } else {
+ printk(BIOS_ERR, "Target panel init not found!\n");
+ ret = ERROR;
+ goto error_display_init;
+ }
+ panel.mdp_rev = rev;
+ ret = msm_display_init(&panel);
+
+error_display_init:
+ display_enable = ret ? 0 : 1;
+ return ret;
+}
+
+void sc7180_display_init(struct device *dev)
+{
+ /* Restricting display hw initialization to cheza boards only */
+ static struct edid ed;
+ printk(BIOS_INFO, "sc7180 display init!\n");
+ display_init(NULL, MDSS_MDP_HW_REV_620, &ed);
+ edid_set_framebuffer_bits_per_pixel(&ed, ed.framebuffer_bits_per_pixel,
+ 0);
+ set_vbe_mode_info_valid(&ed, (uintptr_t)0);
+}
diff --git a/src/soc/qualcomm/sc7180/display/mdss.c b/src/soc/qualcomm/sc7180/display/mdss.c
new file mode 100644
index 0000000..f949729
--- /dev/null
+++ b/src/soc/qualcomm/sc7180/display/mdss.c
@@ -0,0 +1,679 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2020 Qualcomm Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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 <arch/mmio.h>
+#include <stdlib.h>
+#include <console/console.h>
+#include <delay.h>
+#include <soc/mdss_6_2_0.h>
+#include <soc/display/target_sc7180.h>
+#include <soc/display/msm_panel.h>
+#include <soc/display/mipi_dsi.h>
+
+#define MDSS_MDP_MAX_PREFILL_FETCH 25
+
+uint32_t mdss_mdp_intf_offset(void);
+
+void mdss_layer_mixer_setup(struct fbcon_config *fb, struct msm_panel_info
+ *pinfo);
+
+void mdss_vbif_qos_remapper_setup(struct msm_panel_info *pinfo);
+
+int mdp_dsi_video_off(struct msm_panel_info *pinfo);
+
+int mdp_dsi_cmd_off(void);
+
+static int mdp_rev;
+
+void mdp_set_revision(int rev)
+{
+ mdp_rev = rev;
+}
+
+int mdp_get_revision(void)
+{
+ return mdp_rev;
+}
+
+uint32_t mdss_mdp_intf_offset(void)
+{
+ return 0;
+}
+
+static uint32_t mdss_mdp_get_ppb_offset(void)
+{
+ uint32_t mdss_mdp_ppb_off = 0;
+ uint32_t mdss_mdp_rev = readl(MDP_HW_REV);
+
+ /* return MMSS_MDP_PPB0_CONFIG offset from MDSS base */
+ if (mdss_mdp_rev == MDSS_MDP_HW_REV_620)
+ mdss_mdp_ppb_off = 0x1420; //TODO: check if it is required atall
+ else
+ printk(BIOS_ERR, "Invalid PPB0_CONFIG offset\n");
+
+ return mdss_mdp_ppb_off;
+}
+
+static void mdp_select_pipe_type(struct msm_panel_info *pinfo,
+ uint32_t *left_pipe, uint32_t *right_pipe)
+{
+ switch (pinfo->pipe_type) {
+
+ case MDSS_MDP_PIPE_TYPE_DMA:
+ *left_pipe = MDP_VP_0_DMA_0_BASE;
+ *right_pipe = MDP_VP_0_DMA_1_BASE;
+ break;
+
+ case MDSS_MDP_PIPE_TYPE_VIG:
+ default:
+ *left_pipe = MDP_VP_0_VIG_0_BASE;
+ *right_pipe = MDP_VP_0_VIG_1_BASE;
+ break;
+ }
+}
+
+static void mdss_mdp_set_flush(struct msm_panel_info *pinfo,
+ uint32_t *ctl0_reg_val, uint32_t *ctl1_reg_val)
+{
+ bool dual_pipe_single_ctl = pinfo->lcdc.dual_pipe &&
+ !pinfo->mipi.dual_dsi &&
+ !pinfo->lcdc.split_display;
+
+ *ctl0_reg_val = BIT(17); /*attach ctl path */
+ *ctl1_reg_val = BIT(17);
+
+ switch (pinfo->pipe_type) {
+
+ case MDSS_MDP_PIPE_TYPE_DMA:
+ if (dual_pipe_single_ctl)
+ *ctl0_reg_val |= BIT(12)| BIT(11) | BIT(6) | BIT(7);
+ else
+ *ctl0_reg_val |= BIT(12) | BIT(11) | BIT(6);
+
+ *ctl1_reg_val |= BIT(12)| BIT(7);
+
+ if (pinfo->lcdc.dst_split)
+ *ctl0_reg_val |= BIT(12);
+ break;
+
+ case MDSS_MDP_PIPE_TYPE_VIG:
+ default:
+ if (dual_pipe_single_ctl)
+ *ctl0_reg_val |= BIT(0)| BIT(1) |BIT(6) | BIT(7);
+ else
+ *ctl0_reg_val |= BIT(0)| BIT(6);
+
+ *ctl1_reg_val |= BIT(7)|BIT(1);
+
+ if (pinfo->lcdc.dst_split)
+ *ctl0_reg_val |= BIT(1);
+
+ break;
+ }
+
+ *ctl0_reg_val |= BIT(31); /*Interface flush */
+ *ctl1_reg_val |= BIT(31);
+}
+
+static void mdss_source_pipe_config(struct fbcon_config *fb,
+ struct msm_panel_info *pinfo,
+ uint32_t pipe_base)
+{
+ uint32_t img_size, out_size, stride;
+ uint32_t fb_off = 0;
+ uint32_t flip_bits = 0;
+ uint32_t src_xy = 0;
+ uint32_t dst_xy = 0;
+ uint32_t height, width;
+
+ height = fb->height - pinfo->border_top - pinfo->border_bottom;
+ width = fb->width - pinfo->border_left - pinfo->border_right;
+
+ /* write active region size*/
+ img_size = (height << 16) | width;
+ out_size = img_size;
+
+ if (pinfo->lcdc.dual_pipe) {
+
+ if ((pipe_base == MDP_VP_0_DMA_1_BASE) ||
+ (pipe_base == MDP_VP_0_VIG_1_BASE)) {
+ fb_off = (pinfo->xres / 2);
+ out_size = (height << 16) + (pinfo->lm_split[1]);
+ }
+ else {
+ out_size = (height << 16) + (pinfo->lm_split[0]);
+ }
+ }
+
+ stride = (fb->stride * fb->sbpp/8);
+
+ if (fb_off == 0) { /* left */
+ dst_xy = (pinfo->border_top << 16) | pinfo->border_left;
+ src_xy = dst_xy;
+ } else { /* right */
+ dst_xy = (pinfo->border_top << 16);
+ src_xy = (pinfo->border_top << 16) | fb_off;
+ }
+
+ printk(BIOS_INFO, "%s: src=%x fb_off=%x src_xy=%x dst_xy=%x\n",
+ __func__, out_size, fb_off, src_xy, dst_xy);
+
+ writel(stride, pipe_base + PIPE_SSPP_SRC_YSTRIDE);
+
+ writel(out_size, pipe_base + PIPE_SSPP_SRC_SIZE);
+ writel(out_size, pipe_base + PIPE_SSPP_SRC_OUT_SIZE);
+ writel(src_xy, pipe_base + PIPE_SSPP_SRC_XY);
+ writel(dst_xy, pipe_base + PIPE_SSPP_OUT_XY);
+
+ /* Tight Packing 4bpp Alpha 8-bit A R B G */
+ writel(0x000236ff, pipe_base + PIPE_SSPP_SRC_FORMAT);
+ writel(0x03020001, pipe_base + PIPE_SSPP_SRC_UNPACK_PATTERN);
+
+ /* bit(0) is set if hflip is required.
+ * bit(1) is set if vflip is required.
+ */
+ if (pinfo->orientation & 0x1)
+ flip_bits |= MDSS_MDP_OP_MODE_FLIP_LR;
+ if (pinfo->orientation & 0x2)
+ flip_bits |= MDSS_MDP_OP_MODE_FLIP_UD;
+
+ flip_bits |= BIT(31);
+ writel(out_size, pipe_base + PIPE_SW_PIXEL_EXT_C0_REQ);
+ writel(out_size, pipe_base + PIPE_SW_PIXEL_EXT_C1C2_REQ);
+ writel(out_size, pipe_base + PIPE_SW_PIXEL_EXT_C3_REQ);
+ writel(flip_bits, pipe_base + PIPE_SSPP_SRC_OP_MODE);
+
+}
+
+static void mdss_vbif_setup(void)
+{
+ writel(0x33333333, VBIF_VBIF_DDR_AXI_AMEMTYPE_CONF0);
+ writel(0x00333333, VBIF_VBIF_DDR_AXI_AMEMTYPE_CONF1);
+}
+
+static void mdss_intf_tg_setup(struct msm_panel_info *pinfo, uint32_t intf_base)
+{
+ uint32_t hsync_period, vsync_period;
+ uint32_t hsync_start_x, hsync_end_x;
+ uint32_t display_hctl, hsync_ctl, display_vstart, display_vend;
+ uint32_t adjust_xres = 0;
+ uint32_t upper = 0, lower = 0;
+
+ struct lcdc_panel_info *lcdc = NULL;
+ struct intf_timing_params itp = {0};
+
+ if (pinfo == NULL)
+ return;
+
+ lcdc = &(pinfo->lcdc);
+ if (lcdc == NULL)
+ return;
+
+ adjust_xres = pinfo->xres;
+ if (pinfo->lcdc.split_display) {
+ if (pinfo->lcdc.dst_split) {
+ adjust_xres /= 2;
+ } else if (pinfo->lcdc.dual_pipe) {
+ if (intf_base ==
+ (MDP_INTF_1_BASE + mdss_mdp_intf_offset()))
+ adjust_xres = pinfo->lm_split[0];
+ else
+ adjust_xres = pinfo->lm_split[1];
+ }
+
+ if (intf_base == (MDP_INTF_1_BASE + mdss_mdp_intf_offset())) {
+ if (pinfo->lcdc.pipe_swap) {
+ lower |= BIT(4);
+ upper |= BIT(8);
+ } else {
+ lower |= BIT(8);
+ upper |= BIT(4);
+ }
+ writel(lower, MDP_REG_SPLIT_DISPLAY_LOWER_PIPE_CTL);
+ writel(upper, MDP_REG_SPLIT_DISPLAY_UPPER_PIPE_CTL);
+ writel(0x1, MDP_REG_SPLIT_DISPLAY_EN);
+ }
+ }
+
+ if (pinfo->lcdc.dst_split &&
+ (intf_base == (MDP_INTF_1_BASE + mdss_mdp_intf_offset()))) {
+ uint32_t ppb_offset = mdss_mdp_get_ppb_offset();
+
+ writel(BIT(5), REG_MDP(ppb_offset)); /* MMSS_MDP_PPB0_CNTL */
+ writel(BIT(16) | (0x3 << 20), REG_MDP(ppb_offset + 0x4));
+ }
+
+ itp.xres = adjust_xres;
+ itp.yres = pinfo->yres;
+ itp.width = (adjust_xres + pinfo->lcdc.xres_pad);
+
+ if (pinfo->compression_mode == COMPRESSION_DSC) {
+ itp.xres = pinfo->dsc.pclk_per_line;
+ itp.width = pinfo->dsc.pclk_per_line;
+ }
+
+ itp.height = pinfo->yres + pinfo->lcdc.yres_pad;
+ itp.h_back_porch = pinfo->lcdc.h_back_porch;
+ itp.h_front_porch = pinfo->lcdc.h_front_porch;
+ itp.v_back_porch = pinfo->lcdc.v_back_porch;
+ itp.v_front_porch = pinfo->lcdc.v_front_porch;
+ itp.hsync_pulse_width = pinfo->lcdc.h_pulse_width;
+ itp.vsync_pulse_width = pinfo->lcdc.v_pulse_width;
+
+ itp.border_clr = pinfo->lcdc.border_clr;
+ itp.underflow_clr = pinfo->lcdc.underflow_clr;
+ itp.hsync_skew = pinfo->lcdc.hsync_skew;
+
+ hsync_period = itp.hsync_pulse_width + itp.h_back_porch +
+ itp.width + itp.h_front_porch;
+
+ vsync_period = itp.vsync_pulse_width + itp.v_back_porch +
+ itp.height + itp.v_front_porch;
+
+ hsync_start_x = itp.hsync_pulse_width +
+ itp.h_back_porch;
+ hsync_end_x = hsync_period - itp.h_front_porch - 1;
+
+ display_vstart = (itp.vsync_pulse_width +
+ itp.v_back_porch) *
+ hsync_period + itp.hsync_skew;
+
+ display_vend = ((vsync_period - itp.v_front_porch) * hsync_period)
+ + itp.hsync_skew - 1;
+
+ if (intf_base == (MDP_INTF_0_BASE + mdss_mdp_intf_offset())) { /* eDP */
+ display_vstart += itp.hsync_pulse_width + itp.h_back_porch;
+ display_vend -= itp.h_front_porch;
+ }
+
+ hsync_ctl = (hsync_period << 16) | itp.hsync_pulse_width;
+ display_hctl = (hsync_end_x << 16) | hsync_start_x;
+
+ writel(hsync_ctl, MDP_HSYNC_CTL + intf_base);
+ writel(vsync_period*hsync_period, MDP_VSYNC_PERIOD_F0 +
+ intf_base);
+ writel(itp.vsync_pulse_width*hsync_period,
+ MDP_VSYNC_PULSE_WIDTH_F0 +
+ intf_base);
+ writel(display_hctl, MDP_DISPLAY_HCTL + intf_base);
+ writel(display_vstart, MDP_DISPLAY_V_START_F0 +
+ intf_base);
+ writel(display_vend, MDP_DISPLAY_V_END_F0 +
+ intf_base);
+ writel(itp.underflow_clr, MDP_UNDERFFLOW_COLOR + intf_base);
+ writel(0x2100, MDP_PANEL_FORMAT + intf_base);
+}
+
+static void mdss_intf_fetch_start_config(struct msm_panel_info *pinfo,
+ uint32_t intf_base)
+{
+ uint32_t v_total, h_total, fetch_start, vfp_start;
+ uint32_t prefetch_avail, prefetch_needed;
+ uint32_t adjust_xres = 0;
+ uint32_t fetch_enable = BIT(31);
+
+ struct lcdc_panel_info *lcdc = NULL;
+
+ if (pinfo == NULL)
+ return;
+
+ lcdc = &(pinfo->lcdc);
+ if (lcdc == NULL)
+ return;
+
+ /*
+ * MDP programmable fetch is for MDP with rev >= 1.05.
+ * Programmable fetch is not needed if vertical back porch
+ * plus vertical puls width is >= 25.
+ */
+ if ((lcdc->v_back_porch + lcdc->v_pulse_width) >= MDSS_MDP_MAX_PREFILL_FETCH)
+ return;
+
+ adjust_xres = pinfo->xres;
+ if (pinfo->lcdc.split_display) {
+ if (pinfo->lcdc.dst_split) {
+ adjust_xres /= 2;
+ } else if (pinfo->lcdc.dual_pipe) {
+ if (intf_base == (MDP_INTF_1_BASE + mdss_mdp_intf_offset()))
+ adjust_xres = pinfo->lm_split[0];
+ else
+ adjust_xres = pinfo->lm_split[1];
+ }
+ }
+
+ if (pinfo->compression_mode == COMPRESSION_DSC)
+ adjust_xres = pinfo->dsc.pclk_per_line;
+
+ /*
+ * Fetch should always be outside the active lines. If the fetching
+ * is programmed within active region, hardware behavior is unknown.
+ */
+ v_total = lcdc->v_pulse_width + lcdc->v_back_porch + pinfo->yres +
+ lcdc->v_front_porch;
+ h_total = lcdc->h_pulse_width + lcdc->h_back_porch + adjust_xres +
+ lcdc->h_front_porch;
+ vfp_start = lcdc->v_pulse_width + lcdc->v_back_porch + pinfo->yres;
+
+ prefetch_avail = v_total - vfp_start;
+ prefetch_needed = MDSS_MDP_MAX_PREFILL_FETCH - lcdc->v_back_porch -
+ lcdc->v_pulse_width;
+
+ /*
+ * In some cases, vertical front porch is too high. In such cases limit
+ * the mdp fetch lines as the last (25 - vbp - vpw) lines of
+ * vertical front porch.
+ */
+ if (prefetch_avail > prefetch_needed)
+ prefetch_avail = prefetch_needed;
+
+ fetch_start = (v_total - prefetch_avail) * h_total+ h_total + 1;
+
+ if (pinfo->dfps.panel_dfps.enabled)
+ fetch_enable |= BIT(23); //TODO: this shoudld not be enabled ?
+
+ writel(fetch_start, MDP_PROG_FETCH_START + intf_base);
+
+ writel(fetch_enable, MDP_INTF_CONFIG + intf_base);
+
+}
+
+void mdss_layer_mixer_setup(struct fbcon_config *fb, struct msm_panel_info
+ *pinfo)
+{
+ uint32_t mdp_rgb_size, height, width;
+ uint32_t left_staging_level, right_staging_level;
+
+ height = fb->height;
+ width = fb->width;
+
+ if (pinfo->lcdc.dual_pipe && !pinfo->lcdc.dst_split)
+ width = pinfo->lm_split[0];
+
+ /* write active region size*/
+ mdp_rgb_size = (height << 16) | width;
+
+ writel(mdp_rgb_size, MDP_VP_0_MIXER_0_BASE + LAYER_0_OUT_SIZE);
+ writel(0x00, MDP_VP_0_MIXER_0_BASE + LAYER_0_OP_MODE);
+
+ for (int i = 0; i < 6; i++) {
+ writel(0x100, MDP_VP_0_MIXER_0_BASE + LAYER_0_BLEND_OP(i));
+ writel(0x00ff0000, MDP_VP_0_MIXER_0_BASE + LAYER_0_BLEND0_CONST_ALPHA(i));
+ }
+
+ left_staging_level =BIT(24); //attach border
+ right_staging_level=BIT(24);
+
+ switch (pinfo->pipe_type) {
+ case MDSS_MDP_PIPE_TYPE_DMA:
+ left_staging_level |= BIT(18);
+ right_staging_level |= BIT(21);
+ break;
+ case MDSS_MDP_PIPE_TYPE_VIG:
+ default:
+ left_staging_level |= BIT(1);
+ right_staging_level |= BIT(3);
+ break;
+ }
+
+ /*
+ * When ping-pong split is enabled and two pipes are used,
+ * both the pipes need to be staged on the same layer mixer.
+ */
+ if (pinfo->lcdc.dual_pipe && pinfo->lcdc.dst_split)
+ left_staging_level |= right_staging_level;
+
+ /* Base layer for layer mixer 0 */
+ writel(left_staging_level, MDP_CTL_0_BASE + CTL_LAYER_0);
+
+ if (pinfo->lcdc.dual_pipe && !pinfo->lcdc.dst_split) {
+ /* write active region size*/
+ mdp_rgb_size = (height << 16) | pinfo->lm_split[1];
+
+ writel(mdp_rgb_size, MDP_VP_0_MIXER_1_BASE + LAYER_0_OUT_SIZE);
+ writel(0x00, MDP_VP_0_MIXER_1_BASE + LAYER_0_OP_MODE);
+
+ for (int i = 0; i < 6; i++) {
+ writel(0x100, MDP_VP_0_MIXER_1_BASE + LAYER_0_BLEND_OP(i));
+ writel(0x00ff0000, MDP_VP_0_MIXER_1_BASE + LAYER_0_BLEND0_CONST_ALPHA(i));
+ }
+
+ /* Base layer for layer mixer 1 */
+ if (pinfo->lcdc.split_display)
+ writel(right_staging_level, MDP_CTL_1_BASE + CTL_LAYER_1);
+ else
+ writel(right_staging_level, MDP_CTL_0_BASE + CTL_LAYER_1);
+ }
+}
+
+void mdss_vbif_qos_remapper_setup(struct msm_panel_info *pinfo)
+{
+ writel(0x00000003, MDSS_VBIF_RT_BASE + 0x550);
+ writel(0x11111113, MDSS_VBIF_RT_BASE + 0x558);
+ writel(0x22222224, MDSS_VBIF_RT_BASE + 0x560);
+ writel(0x33333334, MDSS_VBIF_RT_BASE + 0x568);
+ writel(0x44444445, MDSS_VBIF_RT_BASE + 0x570);
+ writel(0x77777776, MDSS_VBIF_RT_BASE + 0x588);
+ writel(0x00000003, MDSS_VBIF_RT_BASE + 0x590);
+ writel(0x11111113, MDSS_VBIF_RT_BASE + 0x598);
+ writel(0x22222224, MDSS_VBIF_RT_BASE + 0x5a0);
+ writel(0x33333334, MDSS_VBIF_RT_BASE + 0x5a8);
+ writel(0x44444445, MDSS_VBIF_RT_BASE + 0x5b0);
+ writel(0x77777776, MDSS_VBIF_RT_BASE + 0x5c8);
+
+}
+
+static uint32_t mdss_mdp_ctl_out_sel(struct msm_panel_info *pinfo,
+ int is_main_ctl)
+{
+ uint32_t mctl_intf_sel;
+ uint32_t sctl_intf_sel;
+
+ if ((pinfo->dest == DISPLAY_2) ||
+ ((pinfo->dest == DISPLAY_1) && (pinfo->lcdc.pipe_swap))) {
+ mctl_intf_sel = BIT(4) | BIT(5); /* Interface 2 */
+ sctl_intf_sel = BIT(5); /* Interface 1 */
+ } else {
+ mctl_intf_sel = BIT(5); /* Interface 1 */
+ sctl_intf_sel = BIT(4) | BIT(5); /* Interface 2 */
+ }
+ printk(BIOS_INFO, "%s: main ctl dest=%s sec ctl dest=%s\n", __func__,
+ (mctl_intf_sel & BIT(4)) ? "Intf2" : "Intf1",
+ (sctl_intf_sel & BIT(4)) ? "Intf2" : "Intf1");
+ return is_main_ctl ? mctl_intf_sel : sctl_intf_sel;
+}
+
+static void mdp_set_intf_base(struct msm_panel_info *pinfo,
+ uint32_t *intf_base, uint32_t *sintf_base)
+{
+ if (pinfo->dest == DISPLAY_2) {
+ *intf_base = MDP_INTF_2_BASE;
+ *sintf_base = MDP_INTF_1_BASE;
+ } else {
+ *intf_base = MDP_INTF_1_BASE;
+ *sintf_base = MDP_INTF_2_BASE;
+ }
+}
+
+int mdp_dsi_video_config(struct msm_panel_info *pinfo,
+ struct fbcon_config *fb)
+{
+ uint32_t intf_sel, sintf_sel;
+ uint32_t intf_base, sintf_base;
+ uint32_t left_pipe, right_pipe;
+ uint32_t reg;
+
+ mdp_set_intf_base(pinfo, &intf_base, &sintf_base);
+
+ mdss_intf_tg_setup(pinfo, intf_base);
+ mdss_intf_fetch_start_config(pinfo, intf_base);
+
+ if (pinfo->mipi.dual_dsi) {
+ mdss_intf_tg_setup(pinfo, sintf_base);
+ mdss_intf_fetch_start_config(pinfo, sintf_base);
+ }
+
+ mdp_select_pipe_type(pinfo, &left_pipe, &right_pipe);
+ mdss_vbif_setup();
+ mdss_vbif_qos_remapper_setup(pinfo);
+
+ mdss_source_pipe_config(fb, pinfo, left_pipe);
+
+ if (pinfo->lcdc.dual_pipe)
+ mdss_source_pipe_config(fb, pinfo, right_pipe);
+
+ mdss_layer_mixer_setup(fb, pinfo);
+ reg = mdss_mdp_ctl_out_sel(pinfo, 1); /*Selecting interface 1 */
+
+ /* enable 3D mux for dual_pipe but single interface config */
+ if (pinfo->lcdc.dual_pipe && !pinfo->mipi.dual_dsi &&
+ !pinfo->lcdc.split_display) {
+
+ if (pinfo->num_dsc_enc != 2)
+ reg |= BIT(19) | BIT(20);
+ }
+
+ writel(0x0F0000, MDP_INTF_1_BASE + INTF_MUX);
+ writel(0x0, MDP_CTL_0_BASE + CTL_TOP);
+ writel(BIT(1), MDP_CTL_0_BASE + CTL_INTF_ACTIVE); /*Selecting interface 1 */
+
+ if ((pinfo->compression_mode == COMPRESSION_DSC) &&
+ pinfo->dsc.mdp_dsc_config) {
+ struct dsc_desc *dsc = &pinfo->dsc;
+
+ if (pinfo->lcdc.dual_pipe && !pinfo->mipi.dual_dsi &&
+ !pinfo->lcdc.split_display && (pinfo->num_dsc_enc == 2)) {
+ dsc->mdp_dsc_config(pinfo, MDP_PP_0_BASE,
+ MDP_DSC_0_BASE, true, true);
+
+ dsc->mdp_dsc_config(pinfo, MDP_PP_1_BASE,
+ MDP_DSC_1_BASE, true, true);
+
+ } else if (pinfo->lcdc.dual_pipe && pinfo->mipi.dual_dsi &&
+ pinfo->lcdc.split_display && (pinfo->num_dsc_enc == 1)) {
+ dsc->mdp_dsc_config(pinfo, MDP_PP_0_BASE,
+ MDP_DSC_0_BASE, false, false);
+ dsc->mdp_dsc_config(pinfo, MDP_PP_1_BASE,
+ MDP_DSC_1_BASE, false, false);
+
+ } else {
+ dsc->mdp_dsc_config(pinfo, MDP_PP_0_BASE,
+ MDP_DSC_0_BASE, false, false);
+ }
+ }
+
+ /*
+ * if dst_split is enabled, intf 1 & 2 needs to be enabled but
+ * CTL_1 path should not be set since CTL_0 itself is going
+ * to split after DSPP block and drive both intf.
+ */
+ if (pinfo->mipi.dual_dsi) {
+ if (!pinfo->lcdc.dst_split) {
+ reg = 0x1f00 | mdss_mdp_ctl_out_sel(pinfo, 0);
+ writel(reg, MDP_CTL_1_BASE + CTL_TOP);
+ }
+
+ intf_sel |= sintf_sel; /* INTF 2 enable */
+ }
+
+ return 0;
+}
+
+int mdp_dsi_cmd_config(struct msm_panel_info *pinfo,
+ struct fbcon_config *fb)
+{
+ int ret = NO_ERROR;
+ return ret;
+}
+
+int mdp_dsi_video_on(struct msm_panel_info *pinfo)
+{
+ uint32_t ctl0_reg_val, ctl1_reg_val;
+
+ writel(0x2, MDP_CTL_0_BASE + CTL_INTF_FLUSH);
+ mdss_mdp_set_flush(pinfo, &ctl0_reg_val, &ctl1_reg_val);
+ writel(ctl0_reg_val, MDP_CTL_0_BASE + CTL_FLUSH);
+
+ if (pinfo->lcdc.dual_pipe && !pinfo->lcdc.dst_split){
+ writel(0x4, MDP_CTL_1_BASE + CTL_INTF_FLUSH);
+ writel(ctl1_reg_val, MDP_CTL_1_BASE + CTL_FLUSH);
+ }
+
+ return NO_ERROR;
+}
+
+static void mdp_set_cmd_autorefresh_mode(struct msm_panel_info *pinfo)
+{
+ uint32_t total_lines = 0, vclks_line = 0, cfg = 0;
+
+ if (!pinfo || (pinfo->type != MIPI_CMD_PANEL) || !pinfo->autorefresh_enable)
+ return;
+
+ total_lines = pinfo->lcdc.v_front_porch +
+ pinfo->lcdc.v_back_porch +
+ pinfo->lcdc.v_pulse_width +
+ pinfo->border_top + pinfo->border_bottom +
+ pinfo->yres;
+
+ total_lines *= pinfo->mipi.frame_rate;
+
+ vclks_line = (total_lines) ? 19200000 / total_lines : 0;
+ vclks_line = vclks_line * pinfo->mipi.frame_rate * 100 / 6000;
+
+ cfg = BIT(19) | vclks_line;
+
+ /* Configure tearcheck VSYNC param */
+ writel(cfg, MDP_REG_PP_0_SYNC_CONFIG_VSYNC);
+
+ if (pinfo->lcdc.dst_split)
+ writel(cfg, MDP_REG_PP_SLAVE_SYNC_CONFIG_VSYNC);
+
+ if (pinfo->lcdc.dual_pipe)
+ writel(cfg, MDP_REG_PP_1_SYNC_CONFIG_VSYNC);
+ dsb();
+
+ /* Enable autorefresh mode */
+ writel((BIT(31) | pinfo->autorefresh_framenum),
+ MDP_REG_PP_0_AUTOREFRESH_CONFIG);
+
+ if (pinfo->lcdc.dst_split)
+ writel((BIT(31) | pinfo->autorefresh_framenum),
+ MDP_REG_PP_SLAVE_AUTOREFRESH_CONFIG);
+
+ if (pinfo->lcdc.dual_pipe)
+ writel((BIT(31) | pinfo->autorefresh_framenum),
+ MDP_REG_PP_1_AUTOREFRESH_CONFIG);
+
+ dsb();
+}
+
+int mdp_dma_on(struct msm_panel_info *pinfo)
+{
+ uint32_t ctl0_reg_val, ctl1_reg_val;
+
+ mdss_mdp_set_flush(pinfo, &ctl0_reg_val, &ctl1_reg_val);
+
+ writel(ctl0_reg_val, MDP_CTL_0_BASE + CTL_FLUSH);
+
+ if (pinfo->lcdc.dual_pipe && !pinfo->lcdc.dst_split)
+ writel(ctl1_reg_val, MDP_CTL_1_BASE + CTL_FLUSH);
+
+ if (pinfo->autorefresh_enable)
+ mdp_set_cmd_autorefresh_mode(pinfo);
+
+ writel(0x01, MDP_CTL_0_BASE + CTL_START);
+
+ return NO_ERROR;
+}
+
diff --git a/src/soc/qualcomm/sc7180/display/oem_panel.c b/src/soc/qualcomm/sc7180/display/oem_panel.c
new file mode 100644
index 0000000..da90398
--- /dev/null
+++ b/src/soc/qualcomm/sc7180/display/oem_panel.c
@@ -0,0 +1,172 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2020 Qualcomm Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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 <string.h>
+#include <arch/mmio.h>
+#include <lib.h>
+#include <stdlib.h>
+#include <console/console.h>
+#include <delay.h>
+#include <soc/display/msm_panel.h>
+#include <soc/display/mipi_dsi.h>
+#include <soc/display/target_sc7180.h>
+#include <soc/display/panel_display.h>
+#include <soc/mdss_6_2_0.h>
+#include <soc/display/panel_sn65dsix6_auo_bll6xak01_dsi_video.h>
+
+enum {
+ HW_PLATFORM_MTP,
+ HW_PLATFORM_PROTO,
+};
+
+enum {
+ SN65DSIX6_AUO_B116XAK01_DSI_VIDEO_PANEL,
+ UNKNOWN_PANEL
+};
+
+/*
+ * The list of panels that are supported on this target.
+ */
+static struct panel_list supp_panels[] = {
+ {"sn65dsix6_auo_b116xak01_dsi_video",
+ SN65DSIX6_AUO_B116XAK01_DSI_VIDEO_PANEL},
+};
+
+static uint32_t panel_id;
+#define SN65DSIX6_AUO_B116XAK01_DSI_VIDEO_PANEL_DELAY 40
+
+int oem_panel_bridge_chip_init(struct msm_panel_info *pinfo);
+
+int oem_panel_rotation(void)
+{
+ return NO_ERROR;
+}
+
+int oem_panel_on(void)
+{
+ if (panel_id == SN65DSIX6_AUO_B116XAK01_DSI_VIDEO_PANEL) {
+ /* needs extra delay to avoid unexpected artifacts */
+ mdelay(SN65DSIX6_AUO_B116XAK01_DSI_VIDEO_PANEL_DELAY);
+ }
+
+ return NO_ERROR;
+}
+
+int oem_panel_off(void)
+{
+ return NO_ERROR;
+}
+
+static int init_panel_data(struct panel_struct *panelstruct,
+ struct msm_panel_info *pinfo,
+ struct mdss_dsi_phy_ctrl *phy_db)
+{
+ int pan_type = PANEL_TYPE_DSI;
+
+ switch (panel_id) {
+ case SN65DSIX6_AUO_B116XAK01_DSI_VIDEO_PANEL:
+ pan_type = PANEL_TYPE_DSI;
+ panelstruct->paneldata
+ = &sn65dsix6_auo_b116xak01_dsi_video_panel_data;
+ panelstruct->paneldata->panel_with_enable_gpio = 0;
+ panelstruct->panelres
+ = &sn65dsix6_auo_b116xak01_dsi_video_panel_res;
+ panelstruct->color
+ = &sn65dsix6_auo_b116xak01_dsi_video_color;
+ panelstruct->videopanel
+ = &sn65dsix6_auo_b116xak01_dsi_video_panel;
+ panelstruct->commandpanel
+ = &sn65dsix6_auo_b116xak01_dsi_video_command_panel;
+ panelstruct->state
+ = &sn65dsix6_auo_b116xak01_dsi_video_state;
+ panelstruct->laneconfig
+ = &sn65dsix6_auo_b116xak01_dsi_video_lane_config;
+ panelstruct->paneltiminginfo
+ = &sn65dsix6_auo_b116xak01_dsi_video_timing_info;
+ panelstruct->panelresetseq
+ = &sn65dsix6_auo_b116xak01_dsi_video_panel_reset_seq;
+ pinfo->mipi.panel_on_cmds
+ = sn65dsix6_auo_b116xak01_dsi_video_on_command;
+ pinfo->mipi.num_of_panel_on_cmds
+ = SN65DSIX6_AUO_B116XAK01_DSI_VIDEO_ON_COMMAND;
+ pinfo->mipi.panel_off_cmds
+ = sn65dsix6_auo_b116xak01_dsi_video_off_command;
+ pinfo->mipi.num_of_panel_off_cmds
+ = SN65DSIX6_AUO_B116XAK01_DSI_VIDEO_OFF_COMMAND;
+ memcpy(phy_db->timing,
+ sn65dsix6_auo_b116xak01_dsi_video_timings,
+ MAX_TIMING_CONFIG * sizeof(uint32_t));
+ break;
+ default:
+ case UNKNOWN_PANEL:
+ pan_type = PANEL_TYPE_UNKNOWN;
+ break;
+ }
+
+ return pan_type;
+}
+
+int oem_panel_bridge_chip_init(struct msm_panel_info *pinfo)
+{
+ return target_set_switch_gpio(1);
+}
+
+int oem_panel_select(const char *panel_name, struct panel_struct *panelstruct,
+ struct msm_panel_info *pinfo,
+ struct mdss_dsi_phy_ctrl *phy_db)
+{
+ uint32_t hw_id = HW_PLATFORM_PROTO;
+ int32_t panel_override_id;
+ uint32_t ret = 0;
+
+ phy_db->pll_type = DSI_PLL_TYPE_10NM;
+
+ if (panel_name) {
+ panel_override_id = panel_name_to_id(supp_panels,
+ ARRAY_SIZE(supp_panels), panel_name);
+
+ if (panel_override_id < 0) {
+ printk(BIOS_ERR, "Not able to search the panel:%s\n",
+ panel_name);
+ } else if (panel_override_id < UNKNOWN_PANEL) {
+ panel_id = panel_override_id;
+ printk(BIOS_INFO, "OEM panel override:%s\n",
+ panel_name);
+ goto panel_init;
+ }
+ }
+
+ switch (hw_id) {
+ case HW_PLATFORM_PROTO:
+ panel_id = SN65DSIX6_AUO_B116XAK01_DSI_VIDEO_PANEL;
+ pinfo->has_bridge_chip = true;
+ break;
+ case HW_PLATFORM_MTP:
+ default:
+ printk(BIOS_ERR, "Display not enabled for %d HW type\n"
+ , hw_id);
+ return PANEL_TYPE_UNKNOWN;
+ }
+
+panel_init:
+ if (pinfo->has_bridge_chip) {
+ ret = oem_panel_bridge_chip_init(pinfo);
+ if (ret) {
+ printk(BIOS_ERR, "Error initializing bridge chip\n");
+ return ret;
+ }
+ }
+ return init_panel_data(panelstruct, pinfo, phy_db);
+}
diff --git a/src/soc/qualcomm/sc7180/include/soc/display.h b/src/soc/qualcomm/sc7180/include/soc/display.h
new file mode 100644
index 0000000..20cd748
--- /dev/null
+++ b/src/soc/qualcomm/sc7180/include/soc/display.h
@@ -0,0 +1,25 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (c) 2018 Qualcomm Technologies
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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 __SOC_QCOM_SC7180_DISPLAY_H__
+#define __SOC_QCOM_SC7180_DISPLAY_H__
+
+#include <edid.h>
+
+void sc7180_display_init(struct device *dev);
+int display_init(const char *panel_name, uint32_t rev, struct edid *ed);
+
+#endif
+
diff --git a/src/soc/qualcomm/sc7180/include/soc/display/panel_sn65dsix6_auo_bll6xak01_dsi_video.h b/src/soc/qualcomm/sc7180/include/soc/display/panel_sn65dsix6_auo_bll6xak01_dsi_video.h
new file mode 100644
index 0000000..a783e03
--- /dev/null
+++ b/src/soc/qualcomm/sc7180/include/soc/display/panel_sn65dsix6_auo_bll6xak01_dsi_video.h
@@ -0,0 +1,281 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (c) 2020 Qualcomm Technologies
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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 _PANEL_SN65DSIX6_AUO_BLL6XAK01_DSI_VIDEO_H_
+#define _PANEL_SN65DSIX6_AUO_BLL6XAK01_DSI_VIDEO_H_
+
+#include "panel.h"
+
+static char panel_node_id[256] = "qcom,dsi_sn65dsix6_auo_b116xak01_video";
+static char panel_controller[256] = "dsi:0:"; /* panel_controller */
+static char panel_compatible[256] = "qcom,mdss-dsi-panel";
+static char panel_destination[256] = "DISPLAY_1";
+static char slave_panel_node_id[256] = "qcom,dsi_sn65dsix6_auo_b116xak01_video";
+
+static struct panel_config sn65dsix6_auo_b116xak01_dsi_video_panel_data = {
+ panel_node_id,
+ panel_controller,
+ panel_compatible,
+ 10, /* panel_interface */
+ 0, /* panel_type */
+ panel_destination,
+ 0, /* panel_orientation */
+ 0, /* panel_clockrate */
+ 60, /* panel_framerate */
+ 0, /* panel_channelid */
+ 0, /* dsi_virtualchannel_id */
+ 0, /* panel_broadcast_mode */
+ 0, /* panel_lp11_init */
+ 0, /* panel_init_delay */
+ 0, /* dsi_stream */
+ 0, /* interleave_mode */
+ 0, /* panel_bitclock_freq */
+ 0, /* panel_operating_mode */
+ 0, /* panel_with_enable_gpio */
+ 0, /* mode_gpio_state */
+ slave_panel_node_id,
+};
+
+static struct panel_resolution sn65dsix6_auo_b116xak01_dsi_video_panel_res = {
+ 1366, /* panel_width .*/
+ 768, /* panel_height .*/
+ 48, /* hfront_porch .*/
+ 10, /* hback_porch .*/
+ 32, /* hpulse_width .*/
+ 0, /* hsync_skew .*/
+ 4, /* vfront_porch .*/
+ 15, /* vback_porch .*/
+ 6, /* vpulse_width .*/
+ 0, /* hleft_border .*/
+ 0, /* hright_border .*/
+ 0, /* vtop_border .*/
+ 0, /* vbottom_border .*/
+ 0, /* hactive_res */
+ 0, /* uint16_t vactive_res */
+ 0, /* invert_data_polarity */
+ 0, /* invert_vsync_polarity */
+ 0, /* invert_hsync_polarity */
+};
+
+static struct color_info sn65dsix6_auo_b116xak01_dsi_video_color = {
+ 24, /* color_format */
+ 0, /* color_order */
+ 0, /* underflow_color */
+ 0, /* border_color */
+ 0, /* pixel_packing */
+ 0, /* pixel_alignment */
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd1[] = {
+ 0x5c, 0x01, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd2[] = {
+ 0x0a, 0x02, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd3[] = {
+ 0x10, 0x20, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd4[] = {
+ 0x12, 0x29, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd5[] = {
+ 0x5a, 0x05, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd6[] = {
+ 0x93, 0x10, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd7[] = {
+ 0x94, 0x81, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd8[] = {
+ 0x0d, 0x01, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd9[] = {
+ 0x64, 0x01, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd10[] = {
+ 0x74, 0x00, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd11[] = {
+ 0x75, 0x01, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd12[] = {
+ 0x76, 0x0a, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd13[] = {
+ 0x77, 0x01, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd14[] = {
+ 0x78, 0x81, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd15[] = {
+ 0x96, 0x0a, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd16[] = {
+ 0x20, 0x56, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd17[] = {
+ 0x21, 0x05, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd18[] = {
+ 0x24, 0x00, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd19[] = {
+ 0x25, 0x03, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd20[] = {
+ 0x2c, 0x20, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd21[] = {
+ 0x2d, 0x00, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd22[] = {
+ 0x30, 0x06, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd23[] = {
+ 0x31, 0x00, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd24[] = {
+ 0x34, 0x0a, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd25[] = {
+ 0x36, 0x0f, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd26[] = {
+ 0x38, 0x30, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd27[] = {
+ 0x3a, 0x04, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd28[] = {
+ 0x5b, 0x01, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd29[] = {
+ 0x3c, 0x00, 0x23, 0x80
+};
+
+static char sn65dsix6_auo_b116xak01_dsi_video_on_cmd30[] = {
+ 0x5a, 0x0d, 0x23, 0x80
+};
+
+static struct mipi_dsi_cmd sn65dsix6_auo_b116xak01_dsi_video_on_command[] = {
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd1, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd2, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd3, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd4, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd5, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd6, 0xff},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd7, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd8, 0xff},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd9, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd10, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd11, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd12, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd13, 0xff},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd14, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd15, 0xff},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd16, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd17, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd18, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd19, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd20, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd21, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd22, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd23, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd24, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd25, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd26, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd27, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd28, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd29, 0x10},
+ {0x4, sn65dsix6_auo_b116xak01_dsi_video_on_cmd30, 0x10},
+};
+
+#define SN65DSIX6_AUO_B116XAK01_DSI_VIDEO_ON_COMMAND 30
+
+static struct mipi_dsi_cmd sn65dsix6_auo_b116xak01_dsi_video_off_command[] = {
+};
+
+#define SN65DSIX6_AUO_B116XAK01_DSI_VIDEO_OFF_COMMAND 0
+
+static struct command_state sn65dsix6_auo_b116xak01_dsi_video_state = {
+ 0, 1
+};
+
+static struct commandpanel_info sn65dsix6_auo_b116xak01_dsi_video_command_panel = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static struct videopanel_info sn65dsix6_auo_b116xak01_dsi_video_panel = {
+ 0, /* hsync_pulse */
+ 0, /* hfp_power_mode */
+ 0, /* hbp_power_mode */
+ 0, /* hsa_power_mode */
+ 1, /* bllp_eof_power_mode */
+ 1, /* bllp_power_mode */
+ 0, /* traffic_mode */
+ 0, /* dma_delayafter_vsync */
+ 0x9, /* bllp_eof_power */
+};
+
+static struct lane_configuration sn65dsix6_auo_b116xak01_dsi_video_lane_config = {
+/* For Proto0, due to the incorrect schematic we have to set
+ force_clk_lane_hs because we are supporting only 384Mhz continuous clock
+*/
+ 4, 0, 1, 1, 1, 1, 1
+};
+
+static const uint32_t sn65dsix6_auo_b116xak01_dsi_video_timings[] = {
+ 0x0, 0x11, 0x3, 0x5, 0x1E, 0x1E, 0x4, 0x4, 0x2, 0x3, 0x4
+};
+
+static struct panel_timing sn65dsix6_auo_b116xak01_dsi_video_timing_info = {
+ 0x0, 0x04, 0x0c, 0x2d
+};
+
+static struct panel_reset_sequence
+ sn65dsix6_auo_b116xak01_dsi_video_panel_reset_seq = {
+ {1, 0, 1, }, {20, 20, 50, }, 2
+};
+
+#endif
diff --git a/src/soc/qualcomm/sc7180/soc.c b/src/soc/qualcomm/sc7180/soc.c
index fbcfc6e..c0b11ae 100644
--- a/src/soc/qualcomm/sc7180/soc.c
+++ b/src/soc/qualcomm/sc7180/soc.c
@@ -1,7 +1,7 @@
/*
* This file is part of the coreboot project.
*
- * Copyright (C) 2018-2019, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2018-2020, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,7 @@
#include <soc/mmu_common.h>
#include <soc/symbols.h>
#include <soc/aop.h>
+#include <soc/display.h>

static void soc_read_resources(struct device *dev)
{
@@ -33,6 +34,9 @@
static void soc_init(struct device *dev)
{
aop_fw_load_reset();
+#if CONFIG(MAINBOARD_DO_NATIVE_VGA_INIT)
+ sc7180_display_init(dev);
+#endif
}

static struct device_operations soc_ops = {

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

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I7d5e3f1781c48759553243abeb3d694f76cd008e
Gerrit-Change-Number: 39615
Gerrit-PatchSet: 1
Gerrit-Owner: Ravi kumar <rbokka@codeaurora.org>
Gerrit-Reviewer: Martin Roth <martinroth@google.com>
Gerrit-Reviewer: Patrick Georgi <pgeorgi@google.com>
Gerrit-MessageType: newchange