Ravi kumar has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/39615 )
Change subject: sc7180: Add display hardware pipe line initialization [patch 3 of 3] ......................................................................
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 = {