Ravi kumar has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/39613 )
Change subject: sc7180: Add display 10nm phy & pll programming support [Patch 1 of 3] ......................................................................
sc7180: Add display 10nm phy & pll programming support [Patch 1 of 3]
Adds basic headers as well as source required for display dsi 10nm phy & pll programming.
Change-Id: I8ff400922ae594f558cf73a5aaa433a3a93347c2 Signed-off-by: Vinod Polimera vpolimer@codeaurora.org --- A src/soc/qualcomm/sc7180/display/dsi_phy.c A src/soc/qualcomm/sc7180/display/dsi_phy_pll.c A src/soc/qualcomm/sc7180/include/soc/display/display_resources.h A src/soc/qualcomm/sc7180/include/soc/display/dsi_phy.h A src/soc/qualcomm/sc7180/include/soc/display/dsi_phy_pll.h A src/soc/qualcomm/sc7180/include/soc/display/msm_panel.h A src/soc/qualcomm/sc7180/include/soc/display/panel.h A src/soc/qualcomm/sc7180/include/soc/mdss_6_2_0.h 8 files changed, 3,159 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/13/39613/1
diff --git a/src/soc/qualcomm/sc7180/display/dsi_phy.c b/src/soc/qualcomm/sc7180/display/dsi_phy.c new file mode 100644 index 0000000..5e12235 --- /dev/null +++ b/src/soc/qualcomm/sc7180/display/dsi_phy.c @@ -0,0 +1,1146 @@ +/* + * 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 <lib.h> +#include <stdlib.h> +#include <console/console.h> +#include <delay.h> +#include <string.h> +#include <stdint.h> +#include <sys/types.h> +#include <soc/clock.h> +#include <soc/mdss_6_2_0.h> +#include <soc/display/dsi_phy.h> +#include <soc/display/display_resources.h> + +#define HAL_DSI_PHY_PLL_READY_TIMEOUT 150 /* ~15 ms */ +#define HAL_DSI_PHY_REFGEN_TIMEOUT 150 /* ~15 ms */ + +#define DSI_MAX_REFRESH_RATE 95 +#define DSI_MIN_REFRESH_RATE 15 + +#define HAL_DSI_PLL_VCO_MIN_MHZ_2_2_0 1000 + +typedef int32_t SIM_FLOAT; +typedef int32_t SIM_DOUBLE; + +typedef struct _dsi_phy_dividerlutentrytype_ { + uint16_t pll_post_div; + uint16_t phy_post_div; +} dsi_phy_dividerlutentrytype; + +/* PLL divider LUTs */ +static dsi_phy_dividerlutentrytype pll_dividerlut_dphy[] = { + { 2, 11}, + { 4, 5 }, + { 2, 9 }, + { 8, 2 }, + { 1, 15}, + { 2, 7 }, + { 1, 13}, + { 4, 3 }, + { 1, 11}, + { 2, 5 }, + { 1, 9 }, + { 8, 1 }, + { 1, 7 }, + { 2, 3 }, + { 1, 5 }, + { 4, 1 }, + { 1, 3 }, + { 2, 1 }, + { 1, 1 } +}; + +typedef enum { + DSI_DeviceID_0 = 0, + DSI_DeviceID_1, + DSI_DeviceID_MAX, + DSI_DeviceID_FORCE_32BIT = 0x7FFFFFFF +} dsi_devid_type; + +typedef struct _dsi_phy_laneconfig_type { + uint32_t data_strength_lp_P; + uint32_t data_strength_lp_N; + uint32_t data_strength_hs; + uint32_t clk_strength_hs; + uint32_t pemph_bottom; /* Determines how many pre-emphasis branches for bottom termination */ + uint32_t pemph_top; /* Determines how many pre-emphasis branches for top termination */ + bool pemph_enable; /* Enable driver pre-emphasis */ + bool strength_override; /* Strength override to use DSIPHY_LNn_TEST_STR */ +} dsi_phy_laneconfig_type; + +typedef enum { + DSI_LaneID_0 = 0, + DSI_LaneID_1, + DSI_LaneID_2, + DSI_LaneID_3, + DSI_LaneID_CLK, + DSI_LaneID_Max, + DSI_LaneID_FORCE_32BIT = 0x7FFFFFFF +} dsi_laneid_type; + + +typedef enum _dsi_pllconfig_sourcetype { + DSI_PLL_CONFIG_INDEPENDENT_SOURCE, /* PLL0 and PLL1 run independently */ + DSI_PLL_CONFIG_SPLIT_SOURCE, /* PLL0 is used to drive DSI0 and DSI1 */ + DSI_PLL_CONFIG_EXTERNAL_SOURCE, /* PLLs are used to drive external device */ +} dsi_pllconfig_sourcetype; + +typedef struct _dsi_phy_pllconfigtype { + uint32_t decdiv_start; /* Freq divider Decimal value */ + uint32_t fracdiv_low; /* Freq divider Fractional part bits 7:0 */ + uint32_t fracdiv_mid; /* Freq divider Fractional part bits 15:8 */ + uint32_t fracdiv_high; /* Freq divider Fractional part bits 17:16 */ + uint32_t pll_post_div; /* PLL Post divider ratio */ + uint32_t propgain_rate; + uint32_t lockdet_rate; + uint32_t freqdet_thresh; + uint32_t freqdet_refclk; + uint32_t freqdet_pllclk; + uint32_t sscper; + uint32_t ssc_adjper; + uint32_t ssc_stepsize; + uint32_t lock_delay; + uint32_t clock_inverters; + SIM_FLOAT pll_error_ppm; +} dsi_phy_pllconfigtype; + +typedef struct _dsi_phy_config_type { + dsi_devid_type dev_id; /* DSI Core ID */ + uint32_t desired_bitclk_freq; /* desired bit clock frequency in Hz */ + uint32_t bits_per_pixel; /* number of bits per pixel */ + uint32_t num_data_lanes; /* number of DSI data lanes */ + uint32_t cfg_flags; + /* PLL config options */ + bool dcdc_mode; /* Regulator mode, TRUE=DCDC ,FALSE=LDO */ + uint32_t clk_strength_hs; /* Clock lane strength in HS */ + uint32_t data_strength_hs; /* Data lane strength in HS */ + uint32_t data_strength_lp; /* Data lane strength in LP */ + dsi_pllconfig_sourcetype pll_config_source; /* PLL Source */ + uint32_t escape_freq; /* Escape clk freq in Hz */ + bool cphy_mode; /* C-Phy */ + uint32_t dsi_clksel; /* pixel clk source select */ + uint32_t phy_post_div; + uint32_t pll_post_div; +} dsi_phy_configtype; + +typedef struct _dsi_phy_configtype_info { + uint32_t pll_vco_output_freq; /* PLL VCO output frequency in Hz */ + uint32_t bitclk_freq; /* bit clock frequency in Hz */ + uint32_t byteclk_freq; /* byte clock frequency in Hz */ + uint32_t dsiclk_freq; /* DSI pclk clock frequency Hz */ + uint32_t pclk_freq; /* PClk frequency in Hz */ + uint32_t pclk_divnumerator; /* numerator of PClk divider ratio */ + uint32_t pclk_divdenominator; /* denominator of PClk divider ratio */ +} dsi_phy_configinfo_type; + +void mdss_dsi_phy_reset(uint32_t base); + +void mdss_dsi_phy_commit_pll(uint32_t dev_id, + dsi_pllconfig_sourcetype pll_cfg_source, + dsi_phy_pllconfigtype *pll_cfg); + +int32_t mdss_dsi_phy_timings(uint32_t dev_id, struct mipi_panel_info *mipi); + +uint32_t dsi_getregbase_offset(uint32_t dev_id); + +uint32_t dsi_phy_dsiclk_divider(dsi_phy_configtype *phy_cfg, + dsi_phy_configinfo_type *phy_cfg_info); + +void dsi_phy_mnd_divider(dsi_phy_configtype *phy_cfg, + dsi_phy_configinfo_type *phy_cfg_info); + +void dsi_phy_dsiclk_sel(dsi_phy_configtype *phy_cfg, + dsi_phy_configinfo_type *phy_cfg_info); + +static void dsi_phy_pll_set_source(dsi_phy_configtype *phy_cfg); + +int32_t mdss_dsi_phy_commit(uint32_t dev_id, dsi_phy_laneconfig_type lane_cfg, + struct mipi_panel_info *mipi); + +int dsi_phy_pll_calcandcommit(dsi_phy_configtype *phy_cfg, + dsi_phy_configinfo_type *phy_cfg_info); + +unsigned long dsi_phy_calc_clk_divider(dsi_phy_configtype *phy_cfg, + dsi_phy_pllconfigtype *pll_cfg, + dsi_phy_configinfo_type *phy_cfg_info); + +int mdss_dsi_phy_setup(struct mipi_panel_info *mipi); + +int32_t mdss_dsi_phy_setup_lanephy(uint32_t dev_id, dsi_laneid_type lane, + dsi_phy_laneconfig_type lane_cfg, + struct mipi_panel_info *mipi); + +uint32_t dsi_phy_getlane_offset(dsi_laneid_type laneId); + +int32_t mdss_dsi_power_down(uint32_t dev_id, struct mipi_panel_info *mipi); + +int mdss_dsi_phy_pll_setup(struct msm_panel_info *pinfo); + +uint32_t dsi_calc_desired_bitclk(struct msm_panel_info *pinfo); + +void dsi_phy_pll_outputdiv_rate(uint32_t id, dsi_phy_pllconfigtype *pll_cfg); + +int enable_dsi_clk(void); + +static uint32_t dsi_phy_rounddown(SIM_DOUBLE SIM_FLOAT_value) +{ + uint32_t roundupValue; + + if (SIM_FLOAT_value > 0) + roundupValue = (uint32_t)SIM_FLOAT_value; + else + roundupValue = 0; + + return roundupValue; +} + +void mdss_dsi_phy_commit_pll(uint32_t dev_id, + dsi_pllconfig_sourcetype pll_cfg_source, + dsi_phy_pllconfigtype *pll_cfg) +{ + uint32_t offset = dsi_getregbase_offset(dev_id); + uint32_t reg_val = 0; + uint32_t pll_post_div = 0; + uint32_t i = 0; + + /* PLL core input override */ + writel(offset + DSI_0_PHY_PLL_CORE_INPUT_OVERRIDE_ADDR, 0x12); + writel(0x12, offset + DSI_0_PHY_PLL_CORE_INPUT_OVERRIDE_ADDR); + + /* Dec div start */ + writel(pll_cfg->decdiv_start, + offset + DSI_0_PHY_PLL_DECIMAL_DIV_START_1_ADDR); + + /* Frac div low part */ + writel(pll_cfg->fracdiv_low, + offset + DSI_0_PHY_PLL_FRAC_DIV_START_LOW_1_ADDR); + + /* Frac div mid part */ + writel(pll_cfg->fracdiv_mid, + offset + DSI_0_PHY_PLL_FRAC_DIV_START_MID_1_ADDR); + + /* Frac div high part */ + writel(pll_cfg->fracdiv_high, + offset + DSI_0_PHY_PLL_FRAC_DIV_START_HIGH_1_ADDR); + + writel(pll_cfg->propgain_rate, + offset + DSI_0_PHY_PLL_PROP_GAIN_RATE_1_ADDR); + + /* Set BIAS_EN_MUX, BIAS_EN */ + reg_val = (1 << 6) | (1 << 7); + /* pll system muxes */ + writel(reg_val, offset + DSI_0_PHY_PLL_SYSTEM_MUXES_ADDR); + + /* lockdet */ + writel(pll_cfg->lockdet_rate, offset + DSI_0_PHY_PLL_LOCKDET_RATE_1_ADDR); + + /* Output divider */ + pll_post_div = 0; + + for (i = 0; i < 4; i++) { + if (pll_cfg->pll_post_div & (1 << i)) { + pll_post_div = i; + break; + } + } + reg_val = 0; + reg_val = pll_post_div & 0x3; + writel(reg_val, offset + DSI_0_PHY_PLL_OUTDIV_RATE_ADDR); + + /* Pll lock delay */ + writel(pll_cfg->lock_delay, offset + DSI_0_PHY_PLL_LOCK_DELAY_ADDR); + + /* clock inverters */ + writel(pll_cfg->clock_inverters, offset + DSI_0_PHY_PLL_CLOCK_INVERTERS_ADDR); + + //Step 3B + writel(0x00000010, offset + DSI_0_PHY_PLL_CMODE_ADDR); + + /* Frequency independent registers */ + writel(0x00000080, offset + DSI_0_PHY_PLL_ANALOG_CONTROLS_ONE_ADDR); + writel(0x00000003, offset + DSI_0_PHY_PLL_ANALOG_CONTROLS_TWO_ADDR); + writel(0x00000000, offset + DSI_0_PHY_PLL_ANALOG_CONTROLS_THREE_ADDR); + writel(0x00000000, offset + DSI_0_PHY_PLL_DSM_DIVIDER_ADDR); + writel(0x0000004E, offset + DSI_0_PHY_PLL_FEEDBACK_DIVIDER_ADDR); + writel(0x00000040, offset + DSI_0_PHY_PLL_CALIBRATION_SETTINGS_ADDR); + writel(0x000000BA, offset + DSI_0_PHY_PLL_BAND_SEL_CAL_SETTINGS_THREE_ADDR); + writel(0x0000000C, offset + DSI_0_PHY_PLL_FREQ_DETECT_SETTINGS_ONE_ADDR); + writel(0x00000000, offset + DSI_0_PHY_PLL_OUTDIV_ADDR); + writel(0x00000000, offset + DSI_0_PHY_PLL_CORE_OVERRIDE_ADDR); + writel(0x00000008, offset + DSI_1_PHY_PLL_DIGITAL_TIMERS_TWO_ADDR); + writel(0x000000C0, offset + DSI_0_PHY_PLL_BAND_SEL_RATE_1_ADDR); + writel(0x000000FA, offset + DSI_0_PHY_PLL_INT_GAIN_IFILT_BAND_1_ADDR); + writel(0x0000004C, offset + DSI_0_PHY_PLL_FL_INT_GAIN_PFILT_BAND_1_ADDR); + writel(0x00000080, offset + DSI_0_PHY_PLL_LOCK_OVERRIDE_ADDR); + writel(0x00000029, offset + DSI_0_PHY_PLL_PFILT_ADDR); + writel(0x0000003F, offset + DSI_0_PHY_PLL_IFILT_ADDR); + +} + +void mdss_dsi_phy_reset(uint32_t base) +{ + writel(0x40, (base + DSI_PHY_DSIPHY_CMN_CTRL_1_OFFSET)); + udelay(100); /*delay ~100us*/ + writel(0x0, (base + DSI_PHY_DSIPHY_CMN_CTRL_1_OFFSET)); +} + +uint32_t dsi_phy_getlane_offset(dsi_laneid_type laneId) +{ + uint32_t offset = 0; + + if (laneId == DSI_LaneID_0) + offset = 0; + else if (laneId == DSI_LaneID_1) + offset = DSI_0_PHY_DLN1_CFG0_ADDR - DSI_0_PHY_DLN0_CFG0_ADDR; + else if (laneId == DSI_LaneID_2) + offset = DSI_0_PHY_DLN2_CFG0_ADDR - DSI_0_PHY_DLN0_CFG0_ADDR; + else if (laneId == DSI_LaneID_3) + offset = DSI_0_PHY_DLN3_CFG0_ADDR - DSI_0_PHY_DLN0_CFG0_ADDR; + else if (laneId == DSI_LaneID_CLK) + offset = DSI_0_PHY_CKLN_CFG0_ADDR - DSI_0_PHY_DLN0_CFG0_ADDR; + else + offset = 0; + + return offset; +} + +uint32_t dsi_getregbase_offset(uint32_t dev_id) +{ + if (dev_id == 0) + return 0; + else if (dev_id == 1) + return (MIPI_DSI1_BASE - MIPI_DSI0_BASE); + else + return 0; //err +} + +int32_t mdss_dsi_power_down(uint32_t dev_id, struct mipi_panel_info *mipi) +{ + uint32_t offset = dsi_getregbase_offset(dev_id); + + /* power up DIGTOP & PLL */ + writel(0x00000060, offset + DSI_0_PHY_CMN_CTRL_0_ADDR); + + /* Disable PLL */ + writel(0x0, offset + DSI_0_PHY_CMN_PLL_CNTRL_ADDR); + + /* Resync re-time FIFO OFF*/ + writel(0x0, offset + DSI_0_PHY_CMN_RBUF_CTRL_ADDR); + + return NO_ERROR; +} + +int32_t mdss_dsi_phy_setup_lanephy(uint32_t dev_id, + dsi_laneid_type lane, + dsi_phy_laneconfig_type lane_cfg, + struct mipi_panel_info *mipi) +{ + int32_t ret = 0; + uint32_t reg_val = 0; + uint32_t offset = dsi_getregbase_offset(dev_id) + + dsi_phy_getlane_offset(lane); + uint32_t lprx_ctrl = 0; + uint32_t hstx_strength = 0; + uint32_t clk_lane = 0; + + if (DSI_LaneID_CLK == lane) { + clk_lane = 1; + hstx_strength = lane_cfg.clk_strength_hs; + } else { + clk_lane = 0; + hstx_strength = lane_cfg.data_strength_hs; + } + + if (DSI_LaneID_0 == lane) + lprx_ctrl = 3; + + // DSIPHY_STR_LP_N + // DSIPHY_STR_LP_P + reg_val = ((lane_cfg.data_strength_lp_N << 0x4) & 0xf0) | + (lane_cfg.data_strength_lp_P & 0x0f); + + writel(reg_val, offset + DSI_0_PHY_DLN0_LPTX_STR_CTRL_ADDR); + + /* DSIPHY_LPRX_EN */ + /* DSIPHY_CDRX_EN */ + /* Transition from 0 to 1 for DLN0-3 CLKLN stays 0 */ + writel(0x00000000, offset + DSI_0_PHY_DLN0_LPRX_CTRL_ADDR); + writel(lprx_ctrl, offset + DSI_0_PHY_DLN0_LPRX_CTRL_ADDR); + + /* Pin Swap */ + writel(0x00000000, offset + DSI_0_PHY_DLN0_PIN_SWAP_ADDR); + + /* DSIPHY_HSTX_STR_HSTOP */ + /* DSIPHY_HSTX_STR_HSBOT */ + writel(hstx_strength, offset + DSI_0_PHY_DLN0_HSTX_STR_CTRL_ADDR); + + /* PGM Delay */ + writel(0x00000000, offset + DSI_0_PHY_DLN0_CFG0_ADDR); + + /* DLN0_CFG1 */ + reg_val = lane_cfg.strength_override ? 1 : 0; + reg_val = (reg_val << 0x5) & 0x20; + writel(reg_val, offset + DSI_0_PHY_DLN0_CFG1_ADDR); + + /* DLN0_CFG2 */ + reg_val = ((lane_cfg.pemph_bottom << 0x04) & 0xf0) | + (lane_cfg.pemph_top & 0x0f); + + writel(reg_val, offset + DSI_0_PHY_DLN0_CFG2_ADDR); + + writel(0x00000000, offset + DSI_0_PHY_DLN0_OFFSET_TOP_CTRL_ADDR); + writel(0x00000000, offset + DSI_0_PHY_DLN0_OFFSET_BOT_CTRL_ADDR); + + /* DSIPHY_LPRX_DLY */ + /* IS_CKLANE */ + reg_val = (clk_lane << 0x07) & 0x80; + writel(reg_val, offset + DSI_0_PHY_DLN0_CFG3_ADDR); + + reg_val = 0; + + if (DSI_LaneID_CLK == lane) + reg_val = 1; + + if ((DSI_LaneID_3 == lane) && mipi->dual_dsi) + reg_val |= 0x04; + + writel(reg_val, offset + DSI_0_PHY_DLN0_TX_DCTRL_ADDR); + + return ret; +} + +int32_t mdss_dsi_phy_timings(uint32_t dev_id, struct mipi_panel_info *mipi) +{ + uint32_t reg_val = 0; + uint32_t offset = dsi_getregbase_offset(dev_id); + uint32_t *timing = mipi->mdss_dsi_phy_db->timing; + + if (mipi == NULL) { + printk(BIOS_ERR, "%s : mipi NULL, error\n", __func__); + return ERROR; + } + + // Step 4 Common block including GlobalTiming Parameters + /* BYTECLK_SEL */ + reg_val = (0x02 << 3) & 0x18; + + writel(reg_val, offset + DSI_0_PHY_CMN_GLBL_CTRL_ADDR); + + /* VREG_CTRL */ + writel(0x00000059, offset + DSI_0_PHY_CMN_VREG_CTRL_ADDR); + + /*HALFBYTECLK_EN*/ + writel(timing[0], offset + DSI_0_PHY_CMN_TIMING_CTRL_0_ADDR); + + /* T_CLK_ZERO */ + writel((uint32_t)mipi->mdss_dsi_phy_db->timing[1], offset + DSI_0_PHY_CMN_TIMING_CTRL_1_ADDR); + + /* T_CLK_PREPARE */ + writel((uint32_t)mipi->mdss_dsi_phy_db->timing[2], offset + DSI_0_PHY_CMN_TIMING_CTRL_2_ADDR); + + /* T_CLK_TRAIL */ + writel((uint32_t)mipi->mdss_dsi_phy_db->timing[3], offset + DSI_0_PHY_CMN_TIMING_CTRL_3_ADDR); + + /* T_HS_EXIT */ + writel((uint32_t)mipi->mdss_dsi_phy_db->timing[4], offset + DSI_0_PHY_CMN_TIMING_CTRL_4_ADDR); + + /* T_HS_ZERO */ + writel((uint32_t)mipi->mdss_dsi_phy_db->timing[5], offset + DSI_0_PHY_CMN_TIMING_CTRL_5_ADDR); + + /* T_HS_PREPARE */ + writel((uint32_t)mipi->mdss_dsi_phy_db->timing[6], offset + DSI_0_PHY_CMN_TIMING_CTRL_6_ADDR); + + /* T_HS_TRAIL */ + writel((uint32_t)mipi->mdss_dsi_phy_db->timing[7], offset + DSI_0_PHY_CMN_TIMING_CTRL_7_ADDR); + + /* T_HS_RQST */ + writel((uint32_t)mipi->mdss_dsi_phy_db->timing[8], offset + DSI_0_PHY_CMN_TIMING_CTRL_8_ADDR); + + /* T_TA_GO & T_TA_SURE */ + writel((uint32_t)mipi->mdss_dsi_phy_db->timing[9], offset + DSI_0_PHY_CMN_TIMING_CTRL_9_ADDR); + + /* T_TA_GET */ + writel((uint32_t)mipi->mdss_dsi_phy_db->timing[10], offset + DSI_0_PHY_CMN_TIMING_CTRL_10_ADDR); + + /*DSIPHY_TRIG3_CMD*/ + writel(0x00000000, offset + DSI_0_PHY_CMN_TIMING_CTRL_11_ADDR); + + /* DSI clock out timing ctrl T_CLK_PRE & T_CLK_POST*/ + reg_val = ((mipi->t_clk_post << 8) | mipi->t_clk_pre); + + writel(reg_val, offset + HWIO_DSI_0_CLKOUT_TIMING_CTRL_ADDR); + + /* DCTRL */ + writel(0x00000040, offset + DSI_0_PHY_CMN_CTRL_2_ADDR); + + return NO_ERROR; +} + +static int dsi_phy_waitforrefgen(dsi_devid_type dev_id) +{ + + uint32_t offset = dsi_getregbase_offset(dev_id); + uint32_t timeout = HAL_DSI_PHY_REFGEN_TIMEOUT; + uint32_t refgen = 0; + int ret = 0; + + while (refgen == 0) { + refgen = (readl(offset + DSI_0_PHY_CMN_PHY_STATUS_ADDR) & 0x1); + + if (refgen == 0) { + udelay(100); /*delay ~100us*/ + timeout--; + + if (timeout == 0) { + /* timeout while polling the lock status */ + ret = -1; + break; + } + } + } + + return ret; +} + +int32_t mdss_dsi_phy_commit(uint32_t dev_id, dsi_phy_laneconfig_type lane_cfg, + struct mipi_panel_info *mipi) +{ + uint32_t offset = dsi_getregbase_offset(dev_id); + int32_t ret = NO_ERROR; + + if (mipi == NULL) { + printk(BIOS_ERR, "%s: mipi NULL, error\n", __func__); + return ERROR; + } + + ret = dsi_phy_waitforrefgen(dev_id); + + if (ret != 0) { + printk(BIOS_ERR, "%s: waitforrefgen error\n", __func__); + return ret; + } + + mdss_dsi_power_down(dev_id, mipi); + + /* Remove PLL, DIG and all lanes from pwrdn */ + writel(0x0000007F, offset + DSI_0_PHY_CMN_CTRL_0_ADDR); + + /* Lane enable */ + writel(0x0000001F, offset + DSI_0_PHY_CMN_DSI_LANE_CTRL0_ADDR); + + mdss_dsi_phy_setup_lanephy(dev_id, DSI_LaneID_0, lane_cfg, mipi); + mdss_dsi_phy_setup_lanephy(dev_id, DSI_LaneID_1, lane_cfg, mipi); + mdss_dsi_phy_setup_lanephy(dev_id, DSI_LaneID_2, lane_cfg, mipi); + mdss_dsi_phy_setup_lanephy(dev_id, DSI_LaneID_3, lane_cfg, mipi); + mdss_dsi_phy_setup_lanephy(dev_id, DSI_LaneID_CLK, lane_cfg, mipi); + + return ret; +} + +int mdss_dsi_phy_setup(struct mipi_panel_info *mipi) +{ + dsi_phy_laneconfig_type lane_cfg; + + if (mipi == NULL) { + printk(BIOS_ERR, "%s: mipi is NULL, error\n", __func__); + return ERROR; + } + + /* Lane Settings */ + lane_cfg.data_strength_lp_N = 0x5; + lane_cfg.data_strength_lp_P = 0x5; + lane_cfg.data_strength_hs = 0x88; + lane_cfg.clk_strength_hs = 0x88; + lane_cfg.pemph_bottom = 0; + lane_cfg.pemph_top = 0; + lane_cfg.pemph_enable = false; + lane_cfg.strength_override = 0; + + //First reset phy + mdss_dsi_phy_reset(mipi->phy_base); + + if (mipi->dual_dsi) + mdss_dsi_phy_reset(mipi->sphy_base); + + //commit phy settings + mdss_dsi_phy_commit(0, lane_cfg, mipi); + + if (mipi->dual_dsi) + mdss_dsi_phy_commit(1, lane_cfg, mipi); + + return NO_ERROR; +} + +static void dsi_phy_resync_fifo(dsi_devid_type dev_id) +{ + uint32_t offset = dsi_getregbase_offset(dev_id); + + /* Resync FIFO*/ + writel(0x00000001, offset + DSI_0_PHY_CMN_RBUF_CTRL_ADDR); +} + +static void dsi_phy_pll_global_clk_enable(dsi_devid_type dev_id, bool enable) +{ + uint32_t offset = dsi_getregbase_offset(dev_id); + uint32_t clk_cfg = readl(offset + DSI_0_PHY_CMN_CLK_CFG1_ADDR); + uint32_t clk_enable = 0; + + /* Set CLK_EN */ + if (enable) + clk_enable = 1; + + clk_cfg &= ~0x20; + clk_cfg |= ((clk_enable << 0x5) & 0x20); + + /* clk cfg1 */ + writel(clk_cfg, offset + DSI_0_PHY_CMN_CLK_CFG1_ADDR); +} + +static int dsi_phy_pll_lock_detect(dsi_devid_type dev_id) +{ + int ret = 0; + uint32_t offset = dsi_getregbase_offset(dev_id); + uint32_t time_out = HAL_DSI_PHY_PLL_READY_TIMEOUT; + uint32_t pll_status; + + wmb(); /* ensure dsiclk_sel is always programmed before pll start */ + + /* Enable PLL */ + writel(0x1, offset + DSI_0_PHY_CMN_PLL_CNTRL_ADDR); + + /* + * ensure all PLL configurations are written prior to checking + * for PLL lock. + */ + wmb(); + + /* Wait for Lock */ + pll_status = readl(offset + DSI_0_PHY_PLL_COMMON_STATUS_ONE_ADDR) & 0x1; + + while ((pll_status == 0) && (time_out)) { + udelay(100); /*delay ~100us*/ + pll_status = readl(offset + DSI_0_PHY_PLL_COMMON_STATUS_ONE_ADDR)& 0x1; + time_out--; + } + + if ((pll_status & 0x1) == 0) { + /* timeout while polling the lock status */ + ret = -1; + printk(BIOS_ERR, "dsi pll lock detect timedout, error.\n"); + } + return ret; +} + +static void dsi_phy_toggle_dln3_tx_dctrl(dsi_devid_type dev_id) +{ + uint32_t offset = dsi_getregbase_offset(dev_id) + dsi_phy_getlane_offset(DSI_LaneID_3); + uint32_t reg_val = 0; + + reg_val = readl(offset + DSI_0_PHY_DLN0_TX_DCTRL_ADDR); + + /* clear bit 0 and keep all other bits including bit 2 */ + reg_val &= ~0x01; + + /* toggle bit 0 */ + writel((0x01 | reg_val), offset + DSI_0_PHY_DLN0_TX_DCTRL_ADDR); + writel(0x4, offset + DSI_0_PHY_DLN0_TX_DCTRL_ADDR); +} + +static void dsi_phy_pll_set_source(dsi_phy_configtype *phy_cfg) +{ + uint32_t offset = dsi_getregbase_offset(phy_cfg->dev_id); + uint32_t clk_cfg = readl(offset + DSI_0_PHY_CMN_CLK_CFG1_ADDR); + + if ((phy_cfg->pll_config_source == DSI_PLL_CONFIG_SPLIT_SOURCE) && + (phy_cfg->dev_id == DSI_DeviceID_1)) { + clk_cfg &= ~0x0c; + clk_cfg |= (((0x01) << 0x02) & 0x0c); + } else { + clk_cfg &= ~0x03; + clk_cfg |= ((phy_cfg->dsi_clksel) & 0x3); + } + + /* clk cfg1 */ + writel(clk_cfg, offset + DSI_0_PHY_CMN_CLK_CFG1_ADDR); +} + +static void dsi_phy_pll_bias_enable(dsi_devid_type dev_id, bool enable) +{ + uint32_t offset = dsi_getregbase_offset(dev_id); + uint32_t reg_val = 0; + + /* Set BIAS_EN_MUX, BIAS_EN */ + if (enable) + reg_val = (0x01 << 6) | (0x01 << 7); + + /* pll system muxes */ + writel(reg_val, offset + DSI_0_PHY_PLL_SYSTEM_MUXES_ADDR); + +} + +void dsi_phy_dsiclk_sel(dsi_phy_configtype *phy_cfg, + dsi_phy_configinfo_type *phy_cfg_info) +{ + uint32_t dsi_clk_sel = 0; + + /* C-phy */ + if (phy_cfg->cphy_mode) + printk(BIOS_ERR, "C Phy not supported, error\n"); + else /* D-Phy */ + dsi_clk_sel = 1; + + phy_cfg->dsi_clksel = dsi_clk_sel; +} + +void dsi_phy_mnd_divider(dsi_phy_configtype *phy_cfg, + dsi_phy_configinfo_type *phy_cfg_info) +{ + uint32_t m_val = 1; + uint32_t n_val = 1; + + if (phy_cfg->cphy_mode) { /* C-phy */ + printk(BIOS_ERR, "C Phy not supported, error\n"); + } else { /* D-Phy */ + if (phy_cfg->bits_per_pixel == 18) { + switch (phy_cfg->num_data_lanes) { + case 1: + case 2: + m_val = 2; + n_val = 9; + break; + case 4: + m_val = 4; + n_val = 9; + break; + default: + break; + } + } else if ((phy_cfg->bits_per_pixel == 16) && + (phy_cfg->num_data_lanes == 3)) { + m_val = 3; + n_val = 8; + } else if ((phy_cfg->bits_per_pixel == 30) && + (phy_cfg->num_data_lanes == 4)) { + m_val = 2; + n_val = 3; + } + } + + /*Save M/N info */ + phy_cfg_info->pclk_divnumerator = m_val; + phy_cfg_info->pclk_divdenominator = n_val; + +} + +uint32_t dsi_phy_dsiclk_divider(dsi_phy_configtype *phy_cfg, + dsi_phy_configinfo_type *phy_cfg_info) +{ + uint32_t m_val = phy_cfg_info->pclk_divnumerator; + uint32_t n_val = phy_cfg_info->pclk_divdenominator; + uint32_t div_ctrl = 0; + uint32_t fval; + + if (phy_cfg->cphy_mode) { /* C-phy */ + printk(BIOS_ERR, "C Phy unsupported, error\n"); + } else { + fval = (m_val * phy_cfg->bits_per_pixel) / + (n_val * phy_cfg->num_data_lanes * 2); + + if (phy_cfg->bits_per_pixel >= 16) + div_ctrl = (uint32_t)fval; + else + div_ctrl = dsi_phy_rounddown(fval); + + } + + return div_ctrl; +} + + +unsigned long dsi_phy_calc_clk_divider(dsi_phy_configtype *phy_cfg, + dsi_phy_pllconfigtype *pll_cfg, + dsi_phy_configinfo_type *phy_cfg_info) +{ + bool div_found = false; + uint32_t offset = dsi_getregbase_offset(phy_cfg->dev_id); + uint32_t m_val = 1; + uint32_t n_val = 1; + uint32_t div_ctrl = 0; + uint32_t reg_val = 0; + uint32_t pll_post_div = 0; + uint32_t phy_post_div = 0; + uint64_t vco_freq_hz = 0; + uint64_t fval = 0; + uint64_t pll_output_freq_hz; + uint64_t desired_bitclk_hz; + uint64_t min_vco_freq_hz = 0; //0.0f; + uint32_t lut_max; + int i; + dsi_phy_dividerlutentrytype *lut; + + /* Napali, use 1000Mhz */ + min_vco_freq_hz = (HAL_DSI_PLL_VCO_MIN_MHZ_2_2_0 * 1000000); + + dsi_phy_mnd_divider(phy_cfg, phy_cfg_info); + + m_val = phy_cfg_info->pclk_divnumerator; + n_val = phy_cfg_info->pclk_divdenominator; + + /* Desired clock in MHz */ + desired_bitclk_hz = (uint64_t)phy_cfg->desired_bitclk_freq; + + if (phy_cfg->cphy_mode) { + printk(BIOS_ERR, "cphy_mode is not supported, error.\n"); + goto out; + } else { + /* D Phy */ + lut = pll_dividerlut_dphy; + lut_max = sizeof(pll_dividerlut_dphy) / sizeof(*lut); + lut += (lut_max - 1); + } + + /* + * PLL Post Div - from LUT + * Check the LUT in reverse order + */ + for (i = lut_max - 1; i >= 0; i--, lut--) { + fval = (uint64_t)lut->phy_post_div * + (uint64_t)lut->pll_post_div; + + if (fval) { + if ((desired_bitclk_hz * fval) > min_vco_freq_hz) { + /* Range found */ + pll_post_div = lut->pll_post_div; + phy_post_div = lut->phy_post_div; + div_found = true; + break; + } + } + } + + if (div_found) { + pll_cfg->pll_post_div = pll_post_div; + phy_cfg->pll_post_div = pll_post_div; + phy_cfg->phy_post_div = phy_post_div; + + /* Div Ctrl*/ + dsi_phy_dsiclk_sel(phy_cfg, phy_cfg_info); + + /*div_ctrl_7_4 */ + div_ctrl = dsi_phy_dsiclk_divider(phy_cfg, phy_cfg_info); + + /* DIV_CTRL_7_4 DIV_CTRL_3_0 + (DIV_CTRL_3_0 = PHY post divider ratio) */ + reg_val = (div_ctrl << 0x04) & 0xf0; + + if ((phy_cfg->pll_config_source == DSI_PLL_CONFIG_SPLIT_SOURCE) + && (phy_cfg->dev_id == DSI_DeviceID_1)) { + /* For slave node PHY post div is forced to 1 */ + reg_val |= 0x01; + } else { + reg_val |= (phy_post_div & 0x0f); + } + + writel(reg_val, offset + DSI_0_PHY_CMN_CLK_CFG0_ADDR); + + /* PLL output frequency = desired_bitclk_hz * phy_post_div */ + pll_output_freq_hz = desired_bitclk_hz * phy_post_div; + + /* VCO output freq*/ + vco_freq_hz = pll_output_freq_hz * pll_post_div; + + } else { + printk(BIOS_ERR, "div not found, error\n"); + } +out: + return (unsigned long)vco_freq_hz; +} + +void dsi_phy_pll_outputdiv_rate(uint32_t dev_id, dsi_phy_pllconfigtype *pll_cfg) +{ + /* Output divider */ + uint32_t pll_post_div = 0; + uint32_t i = 0; + uint32_t reg_val = 0; + uint32_t offset = dsi_getregbase_offset(dev_id); + + for (i = 0; i < 4; i++) { + if (pll_cfg->pll_post_div & (1 << i)) { + pll_post_div = i; + break; + } + } + + reg_val = 0; + reg_val = pll_post_div & 0x3; + writel(reg_val, offset + DSI_0_PHY_PLL_OUTDIV_RATE_ADDR); +} + +int dsi_phy_pll_calcandcommit(dsi_phy_configtype *phy_cfg, + dsi_phy_configinfo_type *phy_cfg_info) +{ + + unsigned long vco_freq_hz; + dsi_phy_pllconfigtype pll_cfg; + dsi_devid_type dev_id = phy_cfg->dev_id; + int ret = 0; + + /* validate input parameters */ + if ((phy_cfg == NULL) || + (phy_cfg_info == NULL)) { + ret = -1; + goto out; + } + else if ((phy_cfg->dev_id != DSI_DeviceID_0) && + (phy_cfg->dev_id != DSI_DeviceID_1)) { + ret = -1; + goto out; + } + else if ((phy_cfg->bits_per_pixel != 16) && + (phy_cfg->bits_per_pixel != 18) && + (phy_cfg->bits_per_pixel != 24)) { + + /* Unsupported pixel bit depth */ + ret = -1; + goto out; + } + else if ((phy_cfg->num_data_lanes == 0) || + (phy_cfg->num_data_lanes > 4)) { + + /* Illegal number of DSI data lanes */ + ret = -1; + goto out; + } + + memset((void *)&pll_cfg, 0, sizeof(dsi_phy_pllconfigtype)); + + /* Save Clock info */ + phy_cfg_info->bitclk_freq = phy_cfg->desired_bitclk_freq; + printk(BIOS_INFO, "calc vco rate with desired_bitclk_freq: %u\n",phy_cfg_info->bitclk_freq); + + vco_freq_hz = dsi_phy_calc_clk_divider(phy_cfg, &pll_cfg, phy_cfg_info); + + if (vco_freq_hz == 0) { + /* bitclock too low - unsupported */ + printk(BIOS_ERR, "vco_freq_hz is 0, unsupported\n"); + ret = -1; + goto out; + } + + /* Enable PLL bias */ + dsi_phy_pll_bias_enable(phy_cfg->dev_id, true); + + /* Set byte clk source */ + dsi_phy_pll_set_source(phy_cfg); + + if ((phy_cfg->pll_config_source == DSI_PLL_CONFIG_SPLIT_SOURCE) && + (phy_cfg->dev_id == DSI_DeviceID_1)) { + /* Global clock enable */ + dsi_phy_pll_global_clk_enable(phy_cfg->dev_id, true); + + /* Resync FIFOs */ + dsi_phy_resync_fifo(dev_id); + } else { + dsi_phy_pll_outputdiv_rate(phy_cfg->dev_id, &pll_cfg); + dsi_phy_pll_vco_10nm_set_rate(phy_cfg->dev_id, vco_freq_hz); + + dsi_phy_toggle_dln3_tx_dctrl(dev_id); + + /* Steps 6,7 Start PLL & Lock */ + if (ret == 0) + ret = dsi_phy_pll_lock_detect(dev_id); + + /* Step 8 - Resync Data Paths */ + if (ret == 0) { + /* Global clock enable */ + dsi_phy_pll_global_clk_enable(phy_cfg->dev_id, true); + + /* Resync FIFOs */ + dsi_phy_resync_fifo(dev_id); + } + } + return 0; +out: + return ret; +} + +uint32_t dsi_calc_desired_bitclk(struct msm_panel_info *pinfo) +{ + uint64_t desired_bclk = 0; + uint32_t num_lines = pinfo->mipi.num_of_lanes; + uint32_t bpp = pinfo->bpp; + uint32_t width = pinfo->xres + pinfo->lcdc.h_back_porch + + pinfo->lcdc.h_front_porch + pinfo->lcdc.h_pulse_width; + uint32_t height = pinfo->yres + pinfo->lcdc.v_back_porch + + pinfo->lcdc.v_front_porch + pinfo->lcdc.v_pulse_width; + + /* If the upper layer has requested a specific bitclock frequency + * override the calculated bitclock frequency. + */ + if (pinfo->mipi.bitclock > 0) { + // Use the bitclock from the upper layer (in Hz) + desired_bclk = (uint64_t)(pinfo->mipi.bitclock); + printk(BIOS_INFO, "Override bitclock:%llu\n", desired_bclk); + } + else { + // refresh_rate is in Q16.16 format + uint32_t refresh_rate = pinfo->mipi.frame_rate; + + // Perform some sanity checking, clamp the refresh rate + // MAX/MIN refresh rate also defined as Q16.16 format + if (refresh_rate > DSI_MAX_REFRESH_RATE) + refresh_rate = DSI_MAX_REFRESH_RATE; + else if (refresh_rate < DSI_MIN_REFRESH_RATE) + refresh_rate = DSI_MIN_REFRESH_RATE; + + if (num_lines) { + desired_bclk = (uint64_t)(height)*(uint64_t)(width); + desired_bclk = desired_bclk * (uint64_t)refresh_rate; + desired_bclk = desired_bclk * (uint64_t)bpp; + desired_bclk = desired_bclk/(uint64_t)(num_lines); + } + + } + + printk(BIOS_INFO, "Desired bitclock:%u\n", (uint32_t)desired_bclk); + return (uint32_t)desired_bclk; +} + +int mdss_dsi_phy_pll_setup(struct msm_panel_info *pinfo) +{ + dsi_phy_configtype phy_cfg; + dsi_phy_configinfo_type phy_cfgtype; + int ret = NO_ERROR; + + /* Setup the PhyStructure */ + memset(&phy_cfg, 0, sizeof(dsi_phy_configtype)); + memset(&phy_cfgtype, 0, sizeof(dsi_phy_configinfo_type)); + + phy_cfg.dev_id = DSI_DeviceID_0; + phy_cfg.bits_per_pixel = pinfo->bpp; //bits_per_pixel; + phy_cfg.num_data_lanes = pinfo->mipi.num_of_lanes; //uNumLanes; + phy_cfg.cfg_flags = 0; + + /* desired DSI PLL bit clk freq in Hz */ + phy_cfg.desired_bitclk_freq = dsi_calc_desired_bitclk(pinfo); + phy_cfg.escape_freq = 19; + phy_cfg.cphy_mode = false; + + if (pinfo->mipi.dual_dsi) + phy_cfg.pll_config_source = DSI_PLL_CONFIG_SPLIT_SOURCE; + else + phy_cfg.pll_config_source = DSI_PLL_CONFIG_INDEPENDENT_SOURCE; + + ret = dsi_phy_pll_calcandcommit(&phy_cfg, &phy_cfgtype); + + if (ret) + goto out; + + ret = mdss_dsi_phy_timings(DSI_DeviceID_0, &(pinfo->mipi)); + if (ret) + goto out; + + if (pinfo->mipi.dual_dsi) { + phy_cfg.dev_id = DSI_DeviceID_1; + ret = dsi_phy_pll_calcandcommit(&phy_cfg, &phy_cfgtype); + + if (ret) + goto out; + + ret = mdss_dsi_phy_timings(DSI_DeviceID_1, &(pinfo->mipi)); + + if (ret) + goto out; + } +out: + return ret; +} + +int enable_dsi_clk(void) +{ + int ret = 0; + uint32_t clk_enable = 1; + MDPExternalClockEntry *clk_list = sDSI0ExtClocks_6xx; + + if(clk_list != NULL){ + uint32_t i = 0; + + while (clk_list[i].szName[0] != '\0') { + //Set Ext Source + ret = mdss_clock_configure(clk_list[i].szName, + clk_list[i].uClkSource, + clk_list[i].nClkDiv, + clk_list[i].uClkPLL_M, + clk_list[i].uClkPLL_N, + clk_list[i].uClkPLL_2D); + + if (ret != 0) { + printk(BIOS_ERR,"mdss_clock_configure fialed for %s\n",clk_list[i].szName); + goto out; + } + + ret = mdss_clock_enable(clk_list[i].szName, clk_enable); + + if (ret != 0) { + printk(BIOS_ERR,"mdss_clock_enable fialed for %s\n",clk_list[i].szName); + goto out; + } + + i++; + } + } +out: + return ret; +} + +int mdss_dsi_phy_10nm_init(struct msm_panel_info *pinfo) +{ + int ret = NO_ERROR; + + if (pinfo == NULL) { + printk(BIOS_ERR, "%s: pinfo NULL, error\n", __func__); + goto out; + } + + //Phy set up + ret = mdss_dsi_phy_setup(&(pinfo->mipi)); + + if (ret) + goto out; + + ret = mdss_dsi_phy_pll_setup(pinfo); + + enable_dsi_clk(); + +out: + return ret; +} + +int mdss_dsi_phy_intf_setup(uint32_t phy_pll_type, mdss_dsi_phy_ftable *intf) +{ + int32_t ret = -1; + + if (intf != NULL && phy_pll_type == DSI_PLL_TYPE_10NM) { + memset(intf, 0, sizeof(intf)); + intf->dsi_phy_init = mdss_dsi_phy_10nm_init; + return 0; + } + + return ret; +} + diff --git a/src/soc/qualcomm/sc7180/display/dsi_phy_pll.c b/src/soc/qualcomm/sc7180/display/dsi_phy_pll.c new file mode 100644 index 0000000..c54668f --- /dev/null +++ b/src/soc/qualcomm/sc7180/display/dsi_phy_pll.c @@ -0,0 +1,475 @@ +/* + * 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 <lib.h> +#include <stdlib.h> +#include <console/console.h> +#include <delay.h> +#include <device/device.h> +#include <edid.h> +#include <types.h> +#include <string.h> + +#include <soc/mdss_6_2_0.h> +#include <soc/display/dsi_phy_pll.h> + +#define DSI_0_PHY_PLL_QLINK_COM_REG_BASE (MDSSHW_BASE + 0x00094a00) +#define VCO_DELAY_USEC 1 + +#define MHZ_250 250000000UL +#define MHZ_500 500000000UL +#define MHZ_1000 1000000000UL +#define MHZ_1100 1100000000UL +#define MHZ_1900 1900000000UL +#define MHZ_3000 3000000000UL + +/* Register Offsets from PLL base address */ +#define PLL_ANALOG_CONTROLS_ONE 0x000 +#define PLL_ANALOG_CONTROLS_TWO 0x004 +#define PLL_INT_LOOP_SETTINGS 0x008 +#define PLL_INT_LOOP_SETTINGS_TWO 0x00c +#define PLL_ANALOG_CONTROLS_THREE 0x010 +#define PLL_ANALOG_CONTROLS_FOUR 0x014 +#define PLL_INT_LOOP_CONTROLS 0x018 +#define PLL_DSM_DIVIDER 0x01c +#define PLL_FEEDBACK_DIVIDER 0x020 +#define PLL_SYSTEM_MUXER 0x024 +#define PLL_FREQ_UPDATE_CONTROL_OVERRIDES 0x028 +#define PLL_CMODE 0x02c +#define PLL_CALIBRATION_SETTINGS 0x030 +#define PLL_BAND_SEL_CAL_TIMER_LOW 0x034 +#define PLL_BAND_SEL_CAL_TIMER_HIGH 0x038 +#define PLL_BAND_SEL_CAL_SETTINGS 0x03c +#define PLL_BAND_SEL_MIN 0x040 +#define PLL_BAND_SEL_MAX 0x044 +#define PLL_BAND_SEL_PFILT 0x048 +#define PLL_BAND_SEL_IFILT 0x04c +#define PLL_BAND_SEL_CAL_SETTINGS_TWO 0x050 +#define PLL_BAND_SEL_CAL_SETTINGS_THREE 0x054 +#define PLL_BAND_SEL_CAL_SETTINGS_FOUR 0x058 +#define PLL_BAND_SEL_ICODE_HIGH 0x05c +#define PLL_BAND_SEL_ICODE_LOW 0x060 +#define PLL_FREQ_DETECT_SETTINGS_ONE 0x064 +#define PLL_PFILT 0x07c +#define PLL_IFILT 0x080 +#define PLL_GAIN 0x084 +#define PLL_ICODE_LOW 0x088 +#define PLL_ICODE_HIGH 0x08c +#define PLL_LOCKDET 0x090 +#define PLL_OUTDIV 0x094 +#define PLL_FASTLOCK_CONTROL 0x098 +#define PLL_PASS_OUT_OVERRIDE_ONE 0x09c +#define PLL_PASS_OUT_OVERRIDE_TWO 0x0a0 +#define PLL_CORE_OVERRIDE 0x0a4 +#define PLL_CORE_INPUT_OVERRIDE 0x0a8 +#define PLL_RATE_CHANGE 0x0ac +#define PLL_PLL_DIGITAL_TIMERS 0x0b0 +#define PLL_PLL_DIGITAL_TIMERS_TWO 0x0b4 +#define PLL_DEC_FRAC_MUXES 0x0c8 +#define PLL_DECIMAL_DIV_START_1 0x0cc +#define PLL_FRAC_DIV_START_LOW_1 0x0d0 +#define PLL_FRAC_DIV_START_MID_1 0x0d4 +#define PLL_FRAC_DIV_START_HIGH_1 0x0d8 +#define PLL_MASH_CONTROL 0x0ec +#define PLL_SSC_MUX_CONTROL 0x108 +#define PLL_SSC_STEPSIZE_LOW_1 0x10c +#define PLL_SSC_STEPSIZE_HIGH_1 0x110 +#define PLL_SSC_DIV_PER_LOW_1 0x114 +#define PLL_SSC_DIV_PER_HIGH_1 0x118 +#define PLL_SSC_DIV_ADJPER_LOW_1 0x11c +#define PLL_SSC_DIV_ADJPER_HIGH_1 0x120 +#define PLL_SSC_CONTROL 0x13c +#define PLL_PLL_OUTDIV_RATE 0x140 +#define PLL_PLL_LOCKDET_RATE_1 0x144 +#define PLL_PLL_PROP_GAIN_RATE_1 0x14c +#define PLL_PLL_BAND_SET_RATE_1 0x154 +#define PLL_PLL_INT_GAIN_IFILT_BAND_1 0x15c +#define PLL_PLL_FL_INT_GAIN_PFILT_BAND_1 0x164 +#define PLL_FASTLOCK_EN_BAND 0x16c +#define PLL_FREQ_TUNE_ACCUM_INIT_MUX 0x17c +#define PLL_PLL_LOCK_OVERRIDE 0x180 +#define PLL_PLL_LOCK_DELAY 0x184 +#define PLL_PLL_LOCK_MIN_DELAY 0x188 +#define PLL_CLOCK_INVERTERS 0x18c +#define PLL_SPARE_AND_JPC_OVERRIDES 0x190 +#define PLL_BIAS_CONTROL_1 0x194 +#define PLL_BIAS_CONTROL_2 0x198 +#define PLL_ALOG_OBSV_BUS_CTRL_1 0x19c +#define PLL_COMMON_STATUS_ONE 0x1a0 + +/* Register Offsets from PHY base address */ +#define PHY_CMN_CLK_CFG0 0x010 +#define PHY_CMN_CLK_CFG1 0x014 +#define PHY_CMN_RBUF_CTRL 0x01c +#define PHY_CMN_PLL_CNTRL 0x038 +#define PHY_CMN_CTRL_0 0x024 + +# define do_div(n, base) ( \ +{ \ + uint32_t __base = (base); \ + uint32_t __rem; \ + __rem = ((uint64_t)(n)) % __base; \ + (n) = ((uint64_t)(n)) / __base; \ + __rem; \ +} \ +) \ + +#define DIV_ROUND_CLOSEST_ULL(x, divisor)( \ +{ \ + typeof(divisor) __d = divisor; \ + unsigned long long _tmp = (x) + (__d) / 2; \ + do_div(_tmp, __d); \ + _tmp; \ +} \ +) + +/* Bit definition of SSC control registers */ +#define SSC_CENTER BIT(0) +#define SSC_EN BIT(1) +#define SSC_FREQ_UPDATE BIT(2) +#define SSC_FREQ_UPDATE_MUX BIT(3) +#define SSC_UPDATE_SSC BIT(4) +#define SSC_UPDATE_SSC_MUX BIT(5) +#define SSC_START BIT(6) +#define SSC_START_MUX BIT(7) + +enum { + DSI_PLL_0, + DSI_PLL_1, + DSI_PLL_MAX +}; + +struct dsi_pll_regs { + u32 pll_prop_gain_rate; + u32 pll_lockdet_rate; + u32 decimal_div_start; + u32 frac_div_start_low; + u32 frac_div_start_mid; + u32 frac_div_start_high; + u32 pll_clock_inverters; + u32 ssc_stepsize_low; + u32 ssc_stepsize_high; + u32 ssc_div_per_low; + u32 ssc_div_per_high; + u32 ssc_adjper_low; + u32 ssc_adjper_high; + u32 ssc_control; +}; + +struct dsi_pll_config { + u32 ref_freq; + bool div_override; + u32 output_div; + bool ignore_frac; + bool disable_prescaler; + bool enable_ssc; + bool ssc_center; + u32 dec_bits; + u32 frac_bits; + u32 lock_timer; + u32 ssc_freq; + u32 ssc_offset; + u32 ssc_adj_per; + u32 thresh_cycles; + u32 refclk_cycles; +}; + +struct dsi_pll_10nm { + struct mdss_pll_resources *rsc; + struct dsi_pll_config pll_configuration; + struct dsi_pll_regs reg_setup; +}; + +static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder) +{ + *remainder = dividend % divisor; + return dividend / divisor; +} + +static inline u64 div_u64(u64 dividend, u32 divisor) +{ + u32 remainder; + return div_u64_rem(dividend, divisor, &remainder); +} + +static struct dsi_pll_10nm plls[DSI_PLL_MAX]; + +static void dsi_pll_setup_config(struct dsi_pll_10nm *pll, + struct mdss_pll_resources *rsc) +{ + struct dsi_pll_config *config = &pll->pll_configuration; + config->ref_freq = 19200000; + config->output_div = 1; + config->dec_bits = 8; + config->frac_bits = 18; + config->lock_timer = 64; + config->ssc_freq = 31500; + config->ssc_offset = 5000; + config->ssc_adj_per = 2; + config->thresh_cycles = 32; + config->refclk_cycles = 256; + + config->div_override = false; + config->ignore_frac = false; + config->disable_prescaler = false; + config->enable_ssc = rsc->ssc_en; + config->ssc_center = rsc->ssc_center; + + if (config->enable_ssc) { + + if (rsc->ssc_freq) + config->ssc_freq = rsc->ssc_freq; + + if (rsc->ssc_ppm) + config->ssc_offset = rsc->ssc_ppm; + } +} + +static void dsi_pll_init_val(struct mdss_pll_resources *rsc) +{ + void *pll_base = rsc->pll_base; + + MDSS_PLL_REG_W(pll_base, PLL_CORE_INPUT_OVERRIDE, 0x10); + MDSS_PLL_REG_W(pll_base, PLL_INT_LOOP_SETTINGS, 0x3f); + MDSS_PLL_REG_W(pll_base, PLL_INT_LOOP_SETTINGS_TWO, 0x0); + MDSS_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_FOUR, 0x0); + MDSS_PLL_REG_W(pll_base, PLL_INT_LOOP_CONTROLS, 0x80); + MDSS_PLL_REG_W(pll_base, PLL_FREQ_UPDATE_CONTROL_OVERRIDES, 0x0); + MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_TIMER_LOW, 0x0); + MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_TIMER_HIGH, 0x02); + MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS, 0x82); + MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_MIN, 0x00); + MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_MAX, 0xff); + MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_PFILT, 0x00); + MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_IFILT, 0x00); + MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS_TWO, 0x25); + MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS_FOUR, 0x4f); + MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_ICODE_HIGH, 0x0a); + MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_ICODE_LOW, 0x0); + MDSS_PLL_REG_W(pll_base, PLL_GAIN, 0x42); + MDSS_PLL_REG_W(pll_base, PLL_ICODE_LOW, 0x00); + MDSS_PLL_REG_W(pll_base, PLL_ICODE_HIGH, 0x00); + MDSS_PLL_REG_W(pll_base, PLL_LOCKDET, 0x30); + MDSS_PLL_REG_W(pll_base, PLL_FASTLOCK_CONTROL, 0x04); + MDSS_PLL_REG_W(pll_base, PLL_PASS_OUT_OVERRIDE_ONE, 0x00); + MDSS_PLL_REG_W(pll_base, PLL_PASS_OUT_OVERRIDE_TWO, 0x00); + MDSS_PLL_REG_W(pll_base, PLL_RATE_CHANGE, 0x01); + MDSS_PLL_REG_W(pll_base, PLL_PLL_DIGITAL_TIMERS, 0x08); + MDSS_PLL_REG_W(pll_base, PLL_DEC_FRAC_MUXES, 0x00); + MDSS_PLL_REG_W(pll_base, PLL_MASH_CONTROL, 0x03); + MDSS_PLL_REG_W(pll_base, PLL_SSC_MUX_CONTROL, 0x0); + MDSS_PLL_REG_W(pll_base, PLL_SSC_CONTROL, 0x0); + MDSS_PLL_REG_W(pll_base, PLL_FASTLOCK_EN_BAND, 0x03); + MDSS_PLL_REG_W(pll_base, PLL_FREQ_TUNE_ACCUM_INIT_MUX, 0x0); + MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCK_MIN_DELAY, 0x19); + MDSS_PLL_REG_W(pll_base, PLL_SPARE_AND_JPC_OVERRIDES, 0x0); + MDSS_PLL_REG_W(pll_base, PLL_BIAS_CONTROL_1, 0x40); + MDSS_PLL_REG_W(pll_base, PLL_BIAS_CONTROL_2, 0x20); + MDSS_PLL_REG_W(pll_base, PLL_ALOG_OBSV_BUS_CTRL_1, 0x0); +} + +static void dsi_pll_calc_dec_frac(struct dsi_pll_10nm *pll, + struct mdss_pll_resources *rsc) +{ + struct dsi_pll_config *config = &pll->pll_configuration; + struct dsi_pll_regs *regs = &pll->reg_setup; + u64 fref = rsc->vco_ref_clk_rate; + u64 pll_freq; + u64 divider; + u64 dec, dec_multiple; + u32 frac; + u64 multiplier; + + pll_freq = rsc->vco_current_rate; + + if (config->disable_prescaler) + divider = fref; + else + divider = fref * 2; + + multiplier = 1 << config->frac_bits; + dec_multiple = div_u64(pll_freq * multiplier, divider); + div_u64_rem(dec_multiple, multiplier, &frac); + + dec = div_u64(dec_multiple, multiplier); + + if (pll_freq <= MHZ_1900) + regs->pll_prop_gain_rate = 8; + else if (pll_freq <= MHZ_3000) + regs->pll_prop_gain_rate = 10; + else + regs->pll_prop_gain_rate = 12; + + if (pll_freq < MHZ_1100) + regs->pll_clock_inverters = 8; + else + regs->pll_clock_inverters = 0; + + regs->pll_lockdet_rate = config->lock_timer; + regs->decimal_div_start = dec; + regs->frac_div_start_low = (frac & 0xff); + regs->frac_div_start_mid = (frac & 0xff00) >> 8; + regs->frac_div_start_high = (frac & 0x30000) >> 16; +} + +static void dsi_pll_calc_ssc(struct dsi_pll_10nm *pll, + struct mdss_pll_resources *rsc) +{ + struct dsi_pll_config *config = &pll->pll_configuration; + struct dsi_pll_regs *regs = &pll->reg_setup; + u32 ssc_per; + u32 ssc_mod; + u64 ssc_step_size; + u64 frac; + + if (!config->enable_ssc) { + printk(BIOS_INFO, "SSC not enabled\n"); + return; + } + + ssc_per = DIV_ROUND_CLOSEST(config->ref_freq, config->ssc_freq) / 2 - 1; + ssc_mod = (ssc_per + 1) % (config->ssc_adj_per + 1); + ssc_per -= ssc_mod; + + frac = regs->frac_div_start_low | + (regs->frac_div_start_mid << 8) | + (regs->frac_div_start_high << 16); + + ssc_step_size = regs->decimal_div_start; + ssc_step_size *= (1 << config->frac_bits); + ssc_step_size += frac; + ssc_step_size *= config->ssc_offset; + ssc_step_size *= (config->ssc_adj_per + 1); + ssc_step_size = div_u64(ssc_step_size, (ssc_per + 1)); + ssc_step_size = DIV_ROUND_CLOSEST_ULL(ssc_step_size, 1000000); + + regs->ssc_div_per_low = ssc_per & 0xFF; + regs->ssc_div_per_high = (ssc_per & 0xFF00) >> 8; + regs->ssc_stepsize_low = (u32)(ssc_step_size & 0xFF); + regs->ssc_stepsize_high = (u32)((ssc_step_size & 0xFF00) >> 8); + regs->ssc_adjper_low = config->ssc_adj_per & 0xFF; + regs->ssc_adjper_high = (config->ssc_adj_per & 0xFF00) >> 8; + + regs->ssc_control = config->ssc_center ? SSC_CENTER : 0; + + printk(BIOS_INFO, "SCC: Dec:%d, frac:%llu, frac_bits:%d\n", + regs->decimal_div_start, frac, config->frac_bits); + + printk(BIOS_INFO, "SSC: div_per:0x%X, stepsize:0x%X, adjper:0x%X\n", + ssc_per, (u32)ssc_step_size, config->ssc_adj_per); +} + +static void dsi_pll_commit(struct dsi_pll_10nm *pll, + struct mdss_pll_resources *rsc) +{ + void *pll_base = rsc->pll_base; + struct dsi_pll_regs *reg = &pll->reg_setup; + + MDSS_PLL_REG_W(pll_base, PLL_CORE_INPUT_OVERRIDE, 0x12); + MDSS_PLL_REG_W(pll_base, PLL_DECIMAL_DIV_START_1,reg->decimal_div_start); + MDSS_PLL_REG_W(pll_base, PLL_FRAC_DIV_START_LOW_1,reg->frac_div_start_low); + MDSS_PLL_REG_W(pll_base, PLL_FRAC_DIV_START_MID_1,reg->frac_div_start_mid); + MDSS_PLL_REG_W(pll_base, PLL_FRAC_DIV_START_HIGH_1,reg->frac_div_start_high); + MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCKDET_RATE_1, 0x40); + MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCK_DELAY, 0x06); + MDSS_PLL_REG_W(pll_base, PLL_CMODE, 0x10); + MDSS_PLL_REG_W(pll_base, PLL_CLOCK_INVERTERS, reg->pll_clock_inverters); +} + +static void dsi_pll_config_hzindep_reg(struct dsi_pll_10nm *pll, + struct mdss_pll_resources *rsc) +{ + void *pll_base = rsc->pll_base; + + MDSS_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_ONE, 0x80); + MDSS_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_TWO, 0x03); + MDSS_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_THREE, 0x00); + MDSS_PLL_REG_W(pll_base, PLL_DSM_DIVIDER, 0x00); + MDSS_PLL_REG_W(pll_base, PLL_FEEDBACK_DIVIDER, 0x4e); + MDSS_PLL_REG_W(pll_base, PLL_CALIBRATION_SETTINGS, 0x40); + MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS_THREE, 0xba); + MDSS_PLL_REG_W(pll_base, PLL_FREQ_DETECT_SETTINGS_ONE, 0x0c); + MDSS_PLL_REG_W(pll_base, PLL_OUTDIV, 0x00); + MDSS_PLL_REG_W(pll_base, PLL_CORE_OVERRIDE, 0x00); + MDSS_PLL_REG_W(pll_base, PLL_PLL_DIGITAL_TIMERS_TWO, 0x08); + MDSS_PLL_REG_W(pll_base, PLL_PLL_PROP_GAIN_RATE_1, 0x08); + MDSS_PLL_REG_W(pll_base, PLL_PLL_BAND_SET_RATE_1, 0xc0); + MDSS_PLL_REG_W(pll_base, PLL_PLL_INT_GAIN_IFILT_BAND_1, 0xfa); + MDSS_PLL_REG_W(pll_base, PLL_PLL_FL_INT_GAIN_PFILT_BAND_1, 0x4c); + MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCK_OVERRIDE, 0x80); + MDSS_PLL_REG_W(pll_base, PLL_PFILT, 0x29); + MDSS_PLL_REG_W(pll_base, PLL_IFILT, 0x3f); +} + +static void dsi_pll_ssc_commit(struct dsi_pll_10nm *pll, + struct mdss_pll_resources *rsc) +{ + void *pll_base = rsc->pll_base; + struct dsi_pll_regs *regs = &pll->reg_setup; + + if (pll->pll_configuration.enable_ssc) { + printk(BIOS_INFO, "SSC is enabled\n"); + + MDSS_PLL_REG_W(pll_base, PLL_SSC_STEPSIZE_LOW_1,regs->ssc_stepsize_low); + MDSS_PLL_REG_W(pll_base, PLL_SSC_STEPSIZE_HIGH_1,regs->ssc_stepsize_high); + MDSS_PLL_REG_W(pll_base, PLL_SSC_DIV_PER_LOW_1,regs->ssc_div_per_low); + MDSS_PLL_REG_W(pll_base, PLL_SSC_DIV_PER_HIGH_1,regs->ssc_div_per_high); + MDSS_PLL_REG_W(pll_base, PLL_SSC_DIV_ADJPER_LOW_1,regs->ssc_adjper_low); + MDSS_PLL_REG_W(pll_base, PLL_SSC_DIV_ADJPER_HIGH_1,regs->ssc_adjper_high); + MDSS_PLL_REG_W(pll_base, PLL_SSC_CONTROL,SSC_EN | regs->ssc_control); + } +} + +/* +static int vco_10nm_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +*/ +int dsi_phy_pll_vco_10nm_set_rate(int idx, unsigned long rate) +{ + int rc = NO_ERROR; + struct mdss_pll_resources rsc; + struct dsi_pll_10nm *pll; + + memset((void *)&rsc, 0, sizeof(struct mdss_pll_resources)); + rsc.pll_base = (void *)DSI_0_PHY_PLL_QLINK_COM_REG_BASE; + rsc.ssc_en = false; + + rsc.priv = &plls[idx]; + pll = (struct dsi_pll_10nm *)rsc.priv; + + rsc.vco_current_rate = rate; + rsc.vco_ref_clk_rate = 19200000UL; + + dsi_pll_init_val(&rsc); + + dsi_pll_setup_config(pll, &rsc); + + dsi_pll_calc_dec_frac(pll, &rsc); + + dsi_pll_calc_ssc(pll, &rsc); + + dsi_pll_commit(pll, &rsc); + + dsi_pll_config_hzindep_reg(pll, &rsc); + + dsi_pll_ssc_commit(pll, &rsc); + + /* flush, ensure all register writes are done*/ + wmb(); + + return rc; +} + diff --git a/src/soc/qualcomm/sc7180/include/soc/display/display_resources.h b/src/soc/qualcomm/sc7180/include/soc/display/display_resources.h new file mode 100644 index 0000000..4e71297 --- /dev/null +++ b/src/soc/qualcomm/sc7180/include/soc/display/display_resources.h @@ -0,0 +1,49 @@ +/* + * 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 _PLATFORM_DISPLAY_RESOURCES_H_ +#define _PLATFORM_DISPLAY_RESOURCES_H_ + +#define MDP_MAX_CLOCK_NAME 30 + +static char esc0_clk_name[MDP_MAX_CLOCK_NAME] = "disp_cc_mdss_esc0_clk"; +static char pclk0_clk_name[MDP_MAX_CLOCK_NAME] = "disp_cc_mdss_pclk0_clk"; +static char byte0_clk_name[MDP_MAX_CLOCK_NAME] = "disp_cc_mdss_byte0_clk"; +static char byte0_intf_clk_name[MDP_MAX_CLOCK_NAME] = "disp_cc_mdss_byte0_intf_clk"; +static char clk_null[MDP_MAX_CLOCK_NAME] = "\0"; + +/* MDP External Clocks Entry + */ +typedef struct { + char *szName; /* Clock name */ + uint32_t uClkSource; /* Primary Clock Source */ + uint32_t uClkSecondarySource; /* Secondary Clock source */ + uint32_t nClkDiv; /* Clock pre-divider */ + uint32_t uClkPLL_M; /* Clock M value */ + uint32_t uClkPLL_N; /* Clock N value */ + uint32_t uClkPLL_2D; /* Clock 2D value */ + uint32_t nSourceDiv; /* Clock may need source divider */ +} MDPExternalClockEntry; + +MDPExternalClockEntry sDSI0ExtClocks_6xx[] = { + {esc0_clk_name, 0, 1, 0, 0, 0, 0}, + {pclk0_clk_name, 1, 0, 0, 0, 0, 0}, + {byte0_clk_name, 1, 0, 0, 0, 0, 0}, + {byte0_intf_clk_name,1, 0, 2, 0, 0, 0, 2}, + {clk_null, 0, 0, 0, 0, 0, 0}, +}; + +#endif + diff --git a/src/soc/qualcomm/sc7180/include/soc/display/dsi_phy.h b/src/soc/qualcomm/sc7180/include/soc/display/dsi_phy.h new file mode 100644 index 0000000..2449023 --- /dev/null +++ b/src/soc/qualcomm/sc7180/include/soc/display/dsi_phy.h @@ -0,0 +1,67 @@ +/* + * 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 _DSI_PHY_H +#define _DSI_PHY_H + +#include <soc/display/dsi_phy_pll.h> + +#define MAX_REGULATOR_CONFIG 7 +#define MAX_BIST_CONFIG 6 +#define MAX_TIMING_CONFIG 40 +#define MAX_LANE_CONFIG 45 +#define MAX_STRENGTH_CONFIG 10 +#define MAX_CTRL_CONFIG 4 +#define DMA_TPG_FIFO_LEN 64 + +struct msm_panel_info; +struct mipi_dsi_phy_ctrl { + uint32_t regulator[5]; + uint32_t timing[12]; + uint32_t ctrl[4]; + uint32_t strength[4]; + uint32_t pll[21]; +}; + +enum dsi_reg_mode { + DSI_PHY_REGULATOR_DCDC_MODE, + DSI_PHY_REGULATOR_LDO_MODE, +}; + +enum { + DSI_PLL_TYPE_10NM, + DSI_PLL_TYPE_MAX, +}; + +struct mdss_dsi_phy_ctrl { + uint32_t regulator[MAX_REGULATOR_CONFIG]; + uint32_t timing[MAX_TIMING_CONFIG]; + uint32_t ctrl[MAX_CTRL_CONFIG]; + uint32_t strength[MAX_STRENGTH_CONFIG]; + char bistCtrl[MAX_BIST_CONFIG]; + char laneCfg[MAX_LANE_CONFIG]; + enum dsi_reg_mode regulator_mode; + int pll_type; +}; + +typedef struct _mdss_dsi_phy_ftable { + int (*dsi_phy_init)(struct msm_panel_info *pinfo); +} mdss_dsi_phy_ftable; + +int mdss_dsi_phy_intf_setup(uint32_t phy_pll_type, mdss_dsi_phy_ftable *ftable); +int mdss_dsi_phy_10nm_init(struct msm_panel_info *pinfo); + +#endif + diff --git a/src/soc/qualcomm/sc7180/include/soc/display/dsi_phy_pll.h b/src/soc/qualcomm/sc7180/include/soc/display/dsi_phy_pll.h new file mode 100644 index 0000000..be2d06c --- /dev/null +++ b/src/soc/qualcomm/sc7180/include/soc/display/dsi_phy_pll.h @@ -0,0 +1,169 @@ +/* + * 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 __DSI_PHY_PLL_H +#define __DSI_PHY_PLL_H + +#define MDSS_PLL_REG_W(base, offset, data) \ + write32(((base) + (offset)), (data)) +#define MDSS_PLL_REG_R(base, offset) read32((base) + (offset)) + +#define PLL_CALC_DATA(addr0, addr1, data0, data1) \ + (((data1) << 24) | ((((addr1) / 4) & 0xFF) << 16) | \ + ((data0) << 8) | (((addr0) / 4) & 0xFF)) + +#define MDSS_DYN_PLL_REG_W(base, offset, addr0, addr1, data0, data1) \ + writel_relaxed(((base) + (offset)), \ + PLL_CALC_DATA(addr0, addr1, data0, data1)) + +enum { + MDSS_DSI_PLL_10NM, + MDSS_DP_PLL_10NM, + MDSS_UNKNOWN_PLL, +}; + +enum { + MDSS_PLL_TARGET_8996, +}; + +struct mdss_pll_resources { + + /* Pll specific resources like GPIO, power supply, clocks, etc*/ + + /* + * dsi/edp/hmdi plls' base register, phy, gdsc and dynamic refresh + * register mapping + */ + void *pll_base; + void *phy_base; + void *ln_tx0_base; + void *ln_tx1_base; + void *gdsc_base; + void *dyn_pll_base; + + bool is_init_locked; + s64 vco_current_rate; + s64 vco_locking_rate; + s64 vco_ref_clk_rate; + + /* + * Certain pll's needs to update the same vco rate after resume in + * suspend/resume scenario. Cached the vco rate for such plls. + */ + unsigned long vco_cached_rate; + u32 cached_cfg0; + u32 cached_cfg1; + u32 cached_outdiv; + + /* dsi/edp/hmdi pll interface type */ + u32 pll_interface_type; + + /* + * Target ID. Used in pll_register API for valid target check before + * registering the PLL clocks. + */ + u32 target_id; + + /* HW recommended delay during configuration of vco clock rate */ + u32 vco_delay; + + /* Ref-count of the PLL resources */ + u32 resource_ref_cnt; + + /* + * Keep track to resource status to avoid updating same status for the + * pll from different paths + */ + bool resource_enable; + + /* + * Certain plls' do not allow vco rate update if it is on. Keep track of + * status for them to turn on/off after set rate success. + */ + bool pll_on; + + /* + * handoff_status is true of pll is already enabled by bootloader with + * continuous splash enable case. Clock API will call the handoff API + * to enable the status. It is disabled if continuous splash + * feature is disabled. + */ + bool handoff_resources; + + /* + * caching the pll trim codes in the case of dynamic refresh + */ + int cache_pll_trim_codes[2]; + + /* + * for maintaining the status of saving trim codes + */ + bool reg_upd; + + /* + * PLL index if multiple index are available. Eg. in case of + * DSI we have 2 plls. + */ + uint32_t index; + + bool ssc_en; /* share pll with master */ + bool ssc_center; /* default is down spread */ + u32 ssc_freq; + u32 ssc_ppm; + + struct mdss_pll_resources *slave; + + /* + * target pll revision information + */ + int revision; + + void *priv; + + /* + * dynamic refresh pll codes stored in this structure + */ + struct dfps_info *dfps; + +}; + +struct mdss_pll_vco_calc { + s32 div_frac_start1; + s32 div_frac_start2; + s32 div_frac_start3; + s64 dec_start1; + s64 dec_start2; + s64 pll_plllock_cmp1; + s64 pll_plllock_cmp2; + s64 pll_plllock_cmp3; +}; + +static inline int mdss_set_mux_sel(void *context, unsigned int reg, + unsigned int val) +{ + return 0; +} + +static inline int mdss_get_mux_sel(void *context, unsigned int reg, + unsigned int *val) +{ + *val = 0; + return 0; +} + +int dsi_phy_pll_vco_10nm_set_rate(int dev_id, unsigned long rate); + +#endif + diff --git a/src/soc/qualcomm/sc7180/include/soc/display/msm_panel.h b/src/soc/qualcomm/sc7180/include/soc/display/msm_panel.h new file mode 100644 index 0000000..37758d4 --- /dev/null +++ b/src/soc/qualcomm/sc7180/include/soc/display/msm_panel.h @@ -0,0 +1,324 @@ +/* + * 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 _PLATFORM_MSM_PANEL_H_ +#define _PLATFORM_MSM_PANEL_H_ + +#include <sys/types.h> +#include <stdint.h> +#include <sys/types.h> +#include <soc/display/dsi_phy.h> + +#define DFPS_MAX_FRAME_RATE 20 +#define DFPS_PLL_CODES_SIZE 0x1000 /* One page */ +#define NO_ERROR 0 +#define ERROR -1 + +#define NO_PANEL 0xffff +#define MIPI_VIDEO_PANEL 8 +#define MIPI_CMD_PANEL 9 +#define DISPLAY_UNKNOWN 0 +#define DISPLAY_1 1 +#define DISPLAY_2 2 + +struct fbcon_config { + void *base; + unsigned int width; + unsigned int height; + unsigned int stride; + unsigned int bpp; + unsigned int sbpp; + unsigned int format; +}; + +enum mdss_mdp_pipe_type { + MDSS_MDP_PIPE_TYPE_VIG, + MDSS_MDP_PIPE_TYPE_RGB, + MDSS_MDP_PIPE_TYPE_DMA, +}; + +struct lcdc_panel_info { + uint32_t h_back_porch; + uint32_t h_front_porch; + uint32_t h_pulse_width; + uint32_t v_back_porch; + uint32_t v_front_porch; + uint32_t v_pulse_width; + uint32_t border_clr; + uint32_t underflow_clr; + uint32_t hsync_skew; + uint32_t xres_pad; + uint32_t yres_pad; + uint8_t dual_pipe; + uint8_t split_display; + uint8_t pipe_swap; + uint8_t dst_split; +}; + +enum { + COMPRESSION_NONE, + COMPRESSION_DSC, + COMPRESSION_FBC +}; + +#define DCS_HDR_LEN 4 +#define DSC_PPS_LEN 128 + +struct msm_panel_info; + +struct dsc_desc { + int initial_lines; + int slice_last_group_size; + int bpp; /* target bit per pixel */ + int bpc; /* bit per component */ + int line_buf_depth; + int config_by_manufacture_cmd; + int block_pred_enable; + int vbr_enable; + int enable_422; + int convert_rgb; + int input_10_bits; + int slice_per_pkt; + + int major; + int minor; + int scr_rev; + int pps_id; + + int pic_height; + int pic_width; + int slice_height; + int slice_width; + int chunk_size; + + int pkt_per_line; + int bytes_in_slice; + int bytes_per_pkt; + int eol_byte_num; + int pclk_per_line; /* width */ + + int initial_dec_delay; + int initial_xmit_delay; + + int initial_scale_value; + int scale_decrement_interval; + int scale_increment_interval; + + int first_line_bpg_offset; + int nfl_bpg_offset; + int slice_bpg_offset; + + int initial_offset; + int final_offset; + + int rc_model_size; /* rate_buffer_size */ + + int det_thresh_flatness; + int max_qp_flatness; + int min_qp_flatness; + int edge_factor; + int quant_incr_limit0; + int quant_incr_limit1; + int tgt_offset_hi; + int tgt_offset_lo; + char *buf_thresh; + char *range_min_qp; + char *range_max_qp; + char *range_bpg_offset; + char pps_buf[DCS_HDR_LEN + DSC_PPS_LEN]; + + void (*parameter_calc)(struct msm_panel_info *pinfo); + int (*dsc2buf)(struct msm_panel_info *pinfo); + void (*dsi_dsc_config)(uint32_t base, int mode, struct dsc_desc *dsc); + void (*mdp_dsc_config)(struct msm_panel_info *pinfo, + unsigned int pp_base, unsigned int dsc_base, + bool mux, bool split_mode); +}; + +struct dfps_panel_info { + uint32_t enabled; + uint32_t frame_rate_cnt; + uint32_t frame_rate[DFPS_MAX_FRAME_RATE]; +}; + +struct dfps_pll_codes { + uint32_t codes[2]; +}; + +struct dfps_codes_info { + uint32_t is_valid; + uint32_t frame_rate; + uint32_t clk_rate; + struct dfps_pll_codes pll_codes; +}; + +struct dfps_info { + struct dfps_panel_info panel_dfps; + struct dfps_codes_info codes_dfps[DFPS_MAX_FRAME_RATE]; + void *dfps_fb_base; + uint32_t chip_serial; +}; + +/* intf timing settings */ +struct intf_timing_params { + uint32_t width; + uint32_t height; + uint32_t xres; + uint32_t yres; + + uint32_t h_back_porch; + uint32_t h_front_porch; + uint32_t v_back_porch; + uint32_t v_front_porch; + uint32_t hsync_pulse_width; + uint32_t vsync_pulse_width; + + uint32_t border_clr; + uint32_t underflow_clr; + uint32_t hsync_skew; +}; + +struct mipi_panel_info { + char cmds_post_tg; /* send on commands after tg on */ + char mode; /* video/cmd */ + char interleave_mode; + int eof_bllp_power; + uint32_t bitclock; + char crc_check; + char ecc_check; + char dst_format; /* shared by video and command */ + char num_of_lanes; + char data_lane0; + char data_lane1; + char data_lane2; + char data_lane3; + char dlane_swap; /* data lane swap */ + char rgb_swap; + char b_sel; + char g_sel; + char r_sel; + char rx_eot_ignore; + char tx_eot_append; + char t_clk_post; /* 0xc0, DSI_CLKOUT_TIMING_CTRL */ + char t_clk_pre; /* 0xc0, DSI_CLKOUT_TIMING_CTRL */ + char vc; /* virtual channel */ + struct mipi_dsi_phy_ctrl *dsi_phy_db; + struct mdss_dsi_phy_ctrl *mdss_dsi_phy_db; + struct mipi_dsi_cmd *panel_on_cmds; + int num_of_panel_on_cmds; + struct mipi_dsi_cmd *panel_off_cmds; + int num_of_panel_off_cmds; + /* video mode */ + char pulse_mode_hsa_he; + char hfp_power_stop; + char hbp_power_stop; + char hsa_power_stop; + char eof_bllp_power_stop; + char bllp_power_stop; + char traffic_mode; + char frame_rate; + /* command mode */ + char interleave_max; + char insert_dcs_cmd; + char wr_mem_continue; + char wr_mem_start; + char te_sel; + char stream; /* 0 or 1 */ + char mdp_trigger; + char dma_trigger; + uint32_t dsi_pclk_rate; + /* The packet-size should not bet changed */ + char no_max_pkt_size; + /* Clock required during LP commands */ + char force_clk_lane_hs; + char lane_swap; + uint8_t dual_dsi; + uint8_t use_dsi1_pll; + uint8_t broadcast; + uint8_t mode_gpio_state; + uint32_t signature; + uint32_t use_enable_gpio; + uint32_t ctl_base; + uint32_t phy_base; + uint32_t sctl_base; + uint32_t sphy_base; + uint32_t reg_base; + uint32_t sreg_base; + uint32_t pll_base; + uint32_t spll_base; + + struct dfps_pll_codes pll_codes; +}; + +struct msm_panel_info { + uint32_t xres; + uint32_t yres; + uint32_t bpp; + uint32_t type; + uint32_t wait_cycle; + uint32_t clk_rate; + uint32_t orientation; + uint32_t dest; + uint32_t compression_mode; + /* Select pipe type for handoff */ + uint32_t pipe_type; + char lowpowerstop; + char lcd_reg_en; + uint32_t border_top; + uint32_t border_bottom; + uint32_t border_left; + uint32_t border_right; + + int lm_split[2]; + int num_dsc_enc; + + struct lcdc_panel_info lcdc; + struct dsc_desc dsc; + struct mipi_panel_info mipi; + bool has_bridge_chip; + struct dfps_info dfps; + + int (*on)(void); + int (*off)(void); + int (*pre_on)(void); + int (*pre_off)(void); + int (*prepare)(void); + int (*early_config)(void *pdata); + int (*config)(void *pdata); + int (*rotate)(void); + + char autorefresh_enable; + uint32_t autorefresh_framenum; +}; + +struct msm_fb_panel_data { + struct msm_panel_info panel_info; + struct fbcon_config fb; + int mdp_rev; + int rotate; + + /* function entry chain */ + int (*power_func)(uint8_t enable, struct msm_panel_info *pinfo); + uint32_t (*clk_func)(uint8_t enable, struct msm_panel_info *pinfo); + int (*bl_func)(uint8_t enable); + uint32_t (*pll_clk_func)(uint8_t enable, struct msm_panel_info *pinfo); + int (*dfps_func)(struct msm_panel_info *pinfo); + int (*post_power_func)(int enable); + int (*pre_init_func)(void); + int (*update_panel_info)(void); +}; + +#endif + diff --git a/src/soc/qualcomm/sc7180/include/soc/display/panel.h b/src/soc/qualcomm/sc7180/include/soc/display/panel.h new file mode 100644 index 0000000..afd701f --- /dev/null +++ b/src/soc/qualcomm/sc7180/include/soc/display/panel.h @@ -0,0 +1,189 @@ +/* + * 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_H_ +#define _PANEL_H_ + +/*---------------------------------------------------------------------------*/ +/* HEADER files */ +/*---------------------------------------------------------------------------*/ +#include <types.h> + +#define TOTAL_RESET_GPIO_CTRL 5 + +/*---------------------------------------------------------------------------*/ +/* panel type */ +/*---------------------------------------------------------------------------*/ +enum { + PANEL_TYPE_UNKNOWN, + PANEL_TYPE_DSI, +}; + +/*---------------------------------------------------------------------------*/ +/* Structure definition */ +/*---------------------------------------------------------------------------*/ + +/*Panel Configuration */ +struct panel_config { + char *panel_node_id; + char *panel_controller; + char *panel_compatible; + uint16_t panel_interface; + uint16_t panel_type; + char *panel_destination; + uint32_t panel_orientation; + uint32_t panel_clockrate; /* panel_clockrate is deprecated in favor of panel_bitclock_freq */ + uint16_t panel_framerate; + uint16_t panel_channelid; + uint16_t dsi_virtualchannel_id; + uint16_t panel_broadcast_mode; + uint16_t panel_lp11_init; + uint16_t panel_init_delay; + uint16_t dsi_stream; + uint8_t interleave_mode; + uint32_t panel_bitclock_freq; + uint32_t panel_operating_mode; + uint32_t panel_with_enable_gpio; + uint8_t mode_gpio_state; + char *slave_panel_node_id; +}; + +struct panel_resolution { + uint16_t panel_width; + uint16_t panel_height; + uint16_t hfront_porch; + uint16_t hback_porch; + uint16_t hpulse_width; + uint16_t hsync_skew; + uint16_t vfront_porch; + uint16_t vback_porch; + uint16_t vpulse_width; + uint16_t hleft_border; + uint16_t hright_border; + uint16_t vtop_border; + uint16_t vbottom_border; + uint16_t hactive_res; + uint16_t vactive_res; + uint16_t invert_data_polarity; + uint16_t invert_vsync_polarity; + uint16_t invert_hsync_polarity; +}; + +struct color_info { + uint8_t color_format; + uint8_t color_order; + uint8_t underflow_color; + uint8_t border_color; + uint8_t pixel_packing; + uint8_t pixel_alignment; +}; + +struct command_state { + uint8_t oncommand_state; + uint8_t offcommand_state; +}; + +struct videopanel_info { + uint8_t hsync_pulse; + uint8_t hfp_power_mode; + uint8_t hbp_power_mode; + uint8_t hsa_power_mode; + uint8_t bllp_eof_power_mode; + uint8_t bllp_power_mode; + uint8_t traffic_mode; + uint8_t dma_delayafter_vsync; + uint32_t bllp_eof_power; +}; + +struct commandpanel_info { + uint8_t techeck_enable; + uint8_t tepin_select; + uint8_t teusing_tepin; + uint8_t autorefresh_enable; + uint32_t autorefresh_framenumdiv; + uint32_t tevsync_rdptr_irqline; + uint32_t tevsync_continue_lines; + uint32_t tevsync_startline_divisor; + uint32_t tepercent_variance; + uint8_t tedcs_command; + uint8_t disable_eotafter_hsxfer; + uint32_t cmdmode_idletime; +}; + +struct lane_configuration { + uint8_t dsi_lanes; + uint8_t dsi_lanemap; + uint8_t lane0_state; + uint8_t lane1_state; + uint8_t lane2_state; + uint8_t lane3_state; + uint8_t force_clk_lane_hs; +}; + +struct panel_timing { + uint8_t dsi_mdp_trigger; + uint8_t dsi_dma_trigger; + uint8_t tclk_post; + uint8_t tclk_pre; +}; + +enum { + BL_PWM = 0, + BL_WLED, + BL_DCS, +}; + +struct panel_reset_sequence { + uint8_t pin_state[TOTAL_RESET_GPIO_CTRL]; + uint32_t sleep[TOTAL_RESET_GPIO_CTRL]; + uint8_t pin_direction; +}; + +struct backlight { + uint16_t bl_interface_type; + uint16_t bl_min_level; + uint16_t bl_max_level; + uint16_t bl_step; + uint16_t bl_pmic_controltype; + char *bl_pmic_model; +}; + +struct dsc_parameters { + uint32_t major; + uint32_t minor; + uint32_t pps_id; + uint32_t slice_height; + uint32_t slice_width; + uint32_t bpp; /* target bpp */ + uint32_t bpc; /* target bpc, byte per component */ + uint32_t slice_per_pkt; + uint32_t block_prediction; + uint32_t scr_rev; +}; + +struct topology_config { + char *config_name; /* matches with kernel cmdline */ + /* + * lm_split: -ve value means that lm_split is not used. + * If lm_split is used then DUAL_PIPE flag will be added. + */ + int lm_split[2]; + int num_dsc_enc; /* how many encoder to use */ + struct dsc_parameters *dsc; + int use_pingpong_split; +}; + +#endif /*_PANEL_H_ */ + diff --git a/src/soc/qualcomm/sc7180/include/soc/mdss_6_2_0.h b/src/soc/qualcomm/sc7180/include/soc/mdss_6_2_0.h new file mode 100644 index 0000000..ce7df01 --- /dev/null +++ b/src/soc/qualcomm/sc7180/include/soc/mdss_6_2_0.h @@ -0,0 +1,740 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 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 + * 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 _MDSS_6_2_0_H_ +#define _MDSS_6_2_0_H_ + +#include <types.h> +#include <soc/display/msm_panel.h> + +#define writel(v, a) write32((void *)(size_t)(a), (v)) +#define readl(a) read32((void *)(size_t)(a)) + +/* + HWIO_OUT_FLD: macro to update a given field in a 32 bit value + regVal = current value of a register + io = name of register + field = field inside register + fldVal = value to insert in the given field + eg regVal = HWIO_OUT_FLD(regVal, HWIO_MDP_VP_0_VIG_0_SSPP_OUT_SIZE, DST_H,720); +*/ +#define HWIO_OUT_FLD(regVal, io, field, fldVal) (uint32_t)((((uint32_t)(fldVal) << HWIO_##io##_##field##_SHFT) & HWIO_##io##_##field##_BMSK) | ((uint32_t)(regVal) & ~ HWIO_##io##_##field##_BMSK)) + +#define FRAMEBUFFER_SRC_BPP 32 +#define MDSSHW_BASE (0x0AE00000) +#define MIPI_DSI_BASE (MDSSHW_BASE + 0x94000) +#define MIPI_DSI0_BASE (MIPI_DSI_BASE) +#define MIPI_DSI1_BASE (MDSSHW_BASE + 0x96000) +#define DSI0_PHY_BASE (MDSSHW_BASE + 0x94400) +#define DSI1_PHY_BASE (MDSSHW_BASE + 0x96400) +#define MDSS_VBIF_RT_BASE (MDSSHW_BASE + 0xB0000) +#define MMSS_DSI_PHY_PLL_CORE_VCO_TUNE 0x0D0 +#define MMSS_DSI_PHY_PLL_CORE_KVCO_CODE 0x0D4 + +#define REG_MDP(off) (MDSSHW_BASE + (off)) + +#ifdef MDP_PP_0_BASE +#undef MDP_PP_0_BASE +#endif +#define MDP_PP_0_BASE REG_MDP(0x71000) + +#ifdef MDP_PP_1_BASE +#undef MDP_PP_1_BASE +#endif +#define MDP_PP_1_BASE REG_MDP(0x71800) + +#ifdef MDP_DSC_0_BASE +#undef MDP_DSC_0_BASE +#endif +#define MDP_DSC_0_BASE REG_MDP(0x81000) + +#ifdef MDP_DSC_1_BASE +#undef MDP_DSC_1_BASE +#endif +#define MDP_DSC_1_BASE REG_MDP(0x81400) + +#ifdef MDP_HW_REV +#undef MDP_HW_REV +#endif +#define MDP_HW_REV REG_MDP(0x1000) + +#ifdef MDP_INTR_EN +#undef MDP_INTR_EN +#endif +#define MDP_INTR_EN REG_MDP(0x1010) + +#ifdef MDP_INTR_CLEAR +#undef MDP_INTR_CLEAR +#endif +#define MDP_INTR_CLEAR REG_MDP(0x1018) + +#ifdef MDP_HIST_INTR_EN +#undef MDP_HIST_INTR_EN +#endif +#define MDP_HIST_INTR_EN REG_MDP(0x101C) + +#ifdef MDP_VIDEO_INTF_UNDERFLOW_CTL +#undef MDP_VIDEO_INTF_UNDERFLOW_CTL +#endif +#define MDP_VIDEO_INTF_UNDERFLOW_CTL REG_MDP(0x12E0) + +#ifdef MDP_UPPER_NEW_ROI_PRIOR_RO_START +#undef MDP_UPPER_NEW_ROI_PRIOR_RO_START +#endif +#define MDP_UPPER_NEW_ROI_PRIOR_RO_START REG_MDP(0x11EC) + +#ifdef MDP_LOWER_NEW_ROI_PRIOR_TO_START +#undef MDP_LOWER_NEW_ROI_PRIOR_TO_START +#endif +#define MDP_LOWER_NEW_ROI_PRIOR_TO_START REG_MDP(0x13F8) + +#ifdef MDP_INTF_0_TIMING_ENGINE_EN +#undef MDP_INTF_0_TIMING_ENGINE_EN +#endif +#define MDP_INTF_0_TIMING_ENGINE_EN REG_MDP(0x6b000) + +#ifdef MDP_INTF_1_TIMING_ENGINE_EN +#undef MDP_INTF_1_TIMING_ENGINE_EN +#endif +#define MDP_INTF_1_TIMING_ENGINE_EN REG_MDP(0x6b800) + +#ifdef MDP_INTF_2_TIMING_ENGINE_EN +#undef MDP_INTF_2_TIMING_ENGINE_EN +#endif +#define MDP_INTF_2_TIMING_ENGINE_EN REG_MDP(0x6C000) + +#ifdef MDP_INTF_3_TIMING_ENGINE_EN +#undef MDP_INTF_3_TIMING_ENGINE_EN +#endif +#define MDP_INTF_3_TIMING_ENGINE_EN REG_MDP(0x6C800) + +#ifdef MDP_CTL_0_BASE +#undef MDP_CTL_0_BASE +#endif +#define MDP_CTL_0_BASE REG_MDP(0x2000) + +#ifdef MDP_CTL_1_BASE +#undef MDP_CTL_1_BASE +#endif +#define MDP_CTL_1_BASE REG_MDP(0x2200) + +#ifdef MDP_REG_SPLIT_DISPLAY_EN +#undef MDP_REG_SPLIT_DISPLAY_EN +#endif +#define MDP_REG_SPLIT_DISPLAY_EN REG_MDP(0x12F4) + +#ifdef MDP_REG_SPLIT_DISPLAY_UPPER_PIPE_CTL +#undef MDP_REG_SPLIT_DISPLAY_UPPER_PIPE_CTL +#endif +#define MDP_REG_SPLIT_DISPLAY_UPPER_PIPE_CTL REG_MDP(0x12F8) + +#ifdef MDP_REG_SPLIT_DISPLAY_LOWER_PIPE_CTL +#undef MDP_REG_SPLIT_DISPLAY_LOWER_PIPE_CTL +#endif +#define MDP_REG_SPLIT_DISPLAY_LOWER_PIPE_CTL REG_MDP(0x13F0) + +#ifdef MDP_INTF_0_BASE +#undef MDP_INTF_0_BASE +#endif +#define MDP_INTF_0_BASE REG_MDP(0x6b000) + +#ifdef MDP_INTF_1_BASE +#undef MDP_INTF_1_BASE +#endif +#define MDP_INTF_1_BASE REG_MDP(0x6b800) + +#ifdef MDP_INTF_2_BASE +#undef MDP_INTF_2_BASE +#endif +#define MDP_INTF_2_BASE REG_MDP(0x6c000) + +#ifdef MDP_INTF_3_BASE +#undef MDP_INTF_3_BASE +#endif +#define MDP_INTF_3_BASE REG_MDP(0x6c800) + +#ifdef MDP_CLK_CTRL0 +#undef MDP_CLK_CTRL0 +#endif +#define MDP_CLK_CTRL0 REG_MDP(0x12AC) + +#ifdef MDP_CLK_CTRL1 +#undef MDP_CLK_CTRL1 +#endif +#define MDP_CLK_CTRL1 REG_MDP(0x12B4) + +#ifdef MDP_CLK_CTRL2 +#undef MDP_CLK_CTRL2 +#endif +#define MDP_CLK_CTRL2 REG_MDP(0x12BC) + +#ifdef MDP_CLK_CTRL3 +#undef MDP_CLK_CTRL3 +#endif +#define MDP_CLK_CTRL3 REG_MDP(0x13A8) + +#ifdef MDP_CLK_CTRL4 +#undef MDP_CLK_CTRL4 +#endif +#define MDP_CLK_CTRL4 REG_MDP(0x13B0) + +#ifdef MDP_CLK_CTRL5 +#undef MDP_CLK_CTRL5 +#endif +#define MDP_CLK_CTRL5 REG_MDP(0x13B8) + +#ifdef MDP_CLK_CTRL6 +#undef MDP_CLK_CTRL6 +#endif +#define MDP_CLK_CTRL6 REG_MDP(0x12C4) + +#ifdef MDP_CLK_CTRL7 +#undef MDP_CLK_CTRL7 +#endif +#define MDP_CLK_CTRL7 REG_MDP(0x13D0) + +#ifdef VBIF_VBIF_DDR_FORCE_CLK_ON +#undef VBIF_VBIF_DDR_FORCE_CLK_ON +#endif +#define VBIF_VBIF_DDR_FORCE_CLK_ON REG_MDP(0xb0004) + +#ifdef VBIF_VBIF_DDR_OUT_MAX_BURST +#undef VBIF_VBIF_DDR_OUT_MAX_BURST +#endif +#define VBIF_VBIF_DDR_OUT_MAX_BURST REG_MDP(0xb00D8) + +#ifdef VBIF_VBIF_DDR_ARB_CTRL +#undef VBIF_VBIF_DDR_ARB_CTRL +#endif +#define VBIF_VBIF_DDR_ARB_CTRL REG_MDP(0xb00F0) + +#ifdef VBIF_VBIF_DDR_RND_RBN_QOS_ARB +#undef VBIF_VBIF_DDR_RND_RBN_QOS_ARB +#endif +#define VBIF_VBIF_DDR_RND_RBN_QOS_ARB REG_MDP(0xb0124) + +#ifdef VBIF_VBIF_DDR_AXI_AMEMTYPE_CONF0 +#undef VBIF_VBIF_DDR_AXI_AMEMTYPE_CONF0 +#endif +#define VBIF_VBIF_DDR_AXI_AMEMTYPE_CONF0 REG_MDP(0xb0160) + +#ifdef VBIF_VBIF_DDR_AXI_AMEMTYPE_CONF1 +#undef VBIF_VBIF_DDR_AXI_AMEMTYPE_CONF1 +#endif +#define VBIF_VBIF_DDR_AXI_AMEMTYPE_CONF1 REG_MDP(0xb0164) + +#ifdef VBIF_VBIF_DDR_OUT_AOOO_AXI_EN +#undef VBIF_VBIF_DDR_OUT_AOOO_AXI_EN +#endif +#define VBIF_VBIF_DDR_OUT_AOOO_AXI_EN REG_MDP(0xb0178) + +#ifdef VBIF_VBIF_DDR_OUT_AX_AOOO +#undef VBIF_VBIF_DDR_OUT_AX_AOOO +#endif +#define VBIF_VBIF_DDR_OUT_AX_AOOO REG_MDP(0xb017C) + +#ifdef VBIF_VBIF_IN_RD_LIM_CONF0 +#undef VBIF_VBIF_IN_RD_LIM_CONF0 +#endif +#define VBIF_VBIF_IN_RD_LIM_CONF0 REG_MDP(0xb00B0) + +#ifdef VBIF_VBIF_IN_RD_LIM_CONF1 +#undef VBIF_VBIF_IN_RD_LIM_CONF1 +#endif +#define VBIF_VBIF_IN_RD_LIM_CONF1 REG_MDP(0xb00B4) + +#ifdef VBIF_VBIF_IN_RD_LIM_CONF2 +#undef VBIF_VBIF_IN_RD_LIM_CONF2 +#endif +#define VBIF_VBIF_IN_RD_LIM_CONF2 REG_MDP(0xb00B8) + +#ifdef VBIF_VBIF_IN_RD_LIM_CONF3 +#undef VBIF_VBIF_IN_RD_LIM_CONF3 +#endif +#define VBIF_VBIF_IN_RD_LIM_CONF3 REG_MDP(0xb00BC) + +#ifdef VBIF_VBIF_IN_WR_LIM_CONF0 +#undef VBIF_VBIF_IN_WR_LIM_CONF0 +#endif +#define VBIF_VBIF_IN_WR_LIM_CONF0 REG_MDP(0xb00C0) + +#ifdef VBIF_VBIF_IN_WR_LIM_CONF1 +#undef VBIF_VBIF_IN_WR_LIM_CONF1 +#endif +#define VBIF_VBIF_IN_WR_LIM_CONF1 REG_MDP(0xb00C4) + +#ifdef VBIF_VBIF_IN_WR_LIM_CONF2 +#undef VBIF_VBIF_IN_WR_LIM_CONF2 +#endif +#define VBIF_VBIF_IN_WR_LIM_CONF2 REG_MDP(0xb00C8) + +#ifdef VBIF_VBIF_IN_WR_LIM_CONF3 +#undef VBIF_VBIF_IN_WR_LIM_CONF3 +#endif +#define VBIF_VBIF_IN_WR_LIM_CONF3 REG_MDP(0xb00CC) + +#ifdef VBIF_VBIF_ABIT_SHORT +#undef VBIF_VBIF_ABIT_SHORT +#endif +#define VBIF_VBIF_ABIT_SHORT REG_MDP(0xb0070) + +#ifdef VBIF_VBIF_ABIT_SHORT_CONF +#undef VBIF_VBIF_ABIT_SHORT_CONF +#endif +#define VBIF_VBIF_ABIT_SHORT_CONF REG_MDP(0xb0074) + +#ifdef VBIF_VBIF_GATE_OFF_WRREQ_EN +#undef VBIF_VBIF_GATE_OFF_WRREQ_EN +#endif +#define VBIF_VBIF_GATE_OFF_WRREQ_EN REG_MDP(0xb00A8) + +#define MDP_VP_0_VIG_0_BASE REG_MDP(0x5000) +#define MDP_VP_0_VIG_1_BASE REG_MDP(0x7000) +#define MDP_VP_0_VIG_2_BASE REG_MDP(0x9000) +#define MDP_VP_0_VIG_3_BASE REG_MDP(0xB000) +#define MDP_VP_0_DMA_0_BASE REG_MDP(0x25000) +#define MDP_VP_0_DMA_1_BASE REG_MDP(0x27000) +#define MDP_VP_0_DMA_2_BASE REG_MDP(0x29000) +#define MDP_VP_0_DMA_3_BASE REG_MDP(0x2B000) +#define MDP_VP_0_MIXER_0_BASE REG_MDP(0x45000) +#define MDP_VP_0_MIXER_1_BASE REG_MDP(0x46000) +#define MDP_VP_0_MIXER_2_BASE REG_MDP(0x47000) +#define MDP_VP_0_MIXER_5_BASE REG_MDP(0x4A000) + +#define DMA_CMD_OFFSET 0x048 +#define DMA_CMD_LENGTH 0x04C + +#define INT_CTRL 0x110 +#define CMD_MODE_DMA_SW_TRIGGER 0x090 + +#define EOT_PACKET_CTRL 0x0CC +#define MISR_CMD_CTRL 0x0A0 +#define MISR_VIDEO_CTRL 0x0A4 +#define VIDEO_MODE_CTRL 0x010 +#define HS_TIMER_CTRL 0x0BC + +#define SOFT_RESET 0x118 +#define TPG_DMA_FIFO_RESET 0x1EC +#define CLK_CTRL 0x11C +#define COMMAND_MODE_MDP_CTRL2 0x1B8 +#define TEST_PATTERN_GEN_CTRL 0x15C +#define TEST_PATTERN_GEN_CMD_DMA_INIT_VAL 0x17C +#define TRIG_CTRL 0x084 +#define CTRL 0x004 +#define COMMAND_MODE_DMA_CTRL 0x03C +#define COMMAND_MODE_MDP_CTRL 0x040 +#define COMMAND_MODE_MDP_DCS_CMD_CTRL 0x044 +#define COMMAND_MODE_MDP_STREAM0_CTRL 0x058 +#define COMMAND_MODE_MDP_STREAM0_TOTAL 0x05C +#define COMMAND_MODE_MDP_STREAM1_CTRL 0x060 +#define COMMAND_MODE_MDP_STREAM1_TOTAL 0x064 +#define ERR_INT_MASK0 0x10C + +#define LANE_CTL 0x0AC +#define TIMING_CTL 0x0C4 + +#define VIDEO_MODE_ACTIVE_H 0x024 +#define VIDEO_MODE_ACTIVE_V 0x028 +#define VIDEO_MODE_TOTAL 0x02C +#define VIDEO_MODE_HSYNC 0x030 +#define VIDEO_MODE_VSYNC 0x034 +#define VIDEO_MODE_VSYNC_VPOS 0x038 + +#define VIDEO_COMPRESSION_MODE_CTRL 0x2A0 +#define VIDEO_COMPRESSION_MODE_CTRL_2 0x2A4 +#define CMD_COMPRESSION_MODE_CTRL 0x2A8 +#define CMD_COMPRESSION_MODE_CTRL_2 0x2Ac +#define CMD_COMPRESSION_MODE_CTRL_3 0x2B0 + +#define PIPE_SSPP_SRC0_ADDR 0x14 +#define PIPE_SSPP_SRC_YSTRIDE 0x24 +#define PIPE_SSPP_SRC_SIZE 0x00 +#define PIPE_SSPP_SRC_OUT_SIZE 0x0C +#define PIPE_SSPP_SRC_XY 0x08 +#define PIPE_SSPP_OUT_XY 0x10 +#define PIPE_SSPP_SRC_FORMAT 0x30 +#define PIPE_SSPP_SRC_UNPACK_PATTERN 0x34 +#define PIPE_SSPP_SRC_OP_MODE 0x38 +#define PIPE_SW_PIXEL_EXT_C0_REQ 0x108 +#define PIPE_SW_PIXEL_EXT_C1C2_REQ 0x118 +#define PIPE_SW_PIXEL_EXT_C3_REQ 0x128 + +#define LAYER_0_OUT_SIZE 0x04 +#define LAYER_0_OP_MODE 0x00 +#define LAYER_0_BORDER_COLOR_0 0x08 +#define LAYER_0_BLEND_OP(n) (0x20 + n*0x18) +#define LAYER_0_BLEND0_CONST_ALPHA(n) (0x24 + n*0x18) + +/* HW Revisions for different MDSS targets */ +#define MDSS_GET_MAJOR(rev) ((rev) >> 28) +#define MDSS_GET_MINOR(rev) (((rev) >> 16) & 0xFFF) +#define MDSS_GET_STEP(rev) ((rev) & 0xFFFF) +#define MDSS_GET_MAJOR_MINOR(rev) ((rev) >> 16) + +#define MDSS_IS_MAJOR_MINOR_MATCHING(a, b) \ + (MDSS_GET_MAJOR_MINOR((a)) == MDSS_GET_MAJOR_MINOR((b))) + +#define MDSS_MDP_REV(major, minor, step) \ + ((((major) & 0x000F) << 28) | \ + (((minor) & 0x0FFF) << 16) | \ + ((step) & 0xFFFF)) + +#define MDSS_MDP_HW_REV_620 MDSS_MDP_REV(6, 2, 0) /* Rennell v1.0 */ + +#define MDSS_MAX_LINE_BUF_WIDTH 2048 + +#define CTL_LAYER_0 0x00 +#define CTL_LAYER_1 0x04 +#define CTL_TOP 0x14 +#define CTL_FLUSH 0x18 +#define CTL_START 0x1C +#define CTL_INTF_ACTIVE 0xF4 +#define CTL_INTF_FLUSH 0x110 + +#define MDP_INTF_CONFIG 0x04 +#define MDP_HSYNC_CTL 0x08 +#define MDP_VSYNC_PERIOD_F0 0x0C +#define MDP_VSYNC_PULSE_WIDTH_F0 0x14 +#define MDP_DISPLAY_HCTL 0x3C +#define MDP_DISPLAY_V_START_F0 0x1C +#define MDP_DISPLAY_V_END_F0 0x24 +#define MDP_ACTIVE_HCTL 0x40 +#define MDP_ACTIVE_V_START_F0 0x2C +#define MDP_ACTIVE_V_END_F0 0x34 +#define MDP_UNDERFFLOW_COLOR 0x48 +#define MDP_PANEL_FORMAT 0x90 +#define MDP_PROG_FETCH_START 0x170 +#define INTF_MUX 0x25C + +/* source pipe opmode bits for flip */ +#define MDSS_MDP_OP_MODE_FLIP_UD BIT(14) +#define MDSS_MDP_OP_MODE_FLIP_LR BIT(13) + +#define MDSS_MDP_REG_DCE_SEL REG_MDP(0x1450) + +#define MDSS_MDP_PP_DSC_MODE 0x0A0 +#define MDSS_MDP_PP_DCE_DATA_OUT_SWAP 0x0C8 + +#define MDSS_MDP_DSC_COMMON_MODE 0x00 +#define MDSS_MDP_DSC_ENC 0x04 +#define MDSS_MDP_DSC_PICTURE 0x08 +#define MDSS_MDP_DSC_SLICE 0x0c +#define MDSS_MDP_DSC_CHUNK_SIZE 0x10 +#define MDSS_MDP_DSC_DELAY 0x14 +#define MDSS_MDP_DSC_SCALE_INITIAL 0x18 +#define MDSS_MDP_DSC_SCALE_DEC_INTERVAL 0x1c +#define MDSS_MDP_DSC_SCALE_INC_INTERVAL 0x20 +#define MDSS_MDP_DSC_FIRST_LINE_BPG_OFFSET 0x24 +#define MDSS_MDP_DSC_BPG_OFFSET 0x28 +#define MDSS_MDP_DSC_DSC_OFFSET 0x2c +#define MDSS_MDP_DSC_FLATNESS 0x30 +#define MDSS_MDP_DSC_RC_MODEL_SIZE 0x34 +#define MDSS_MDP_DSC_RC 0x38 +#define MDSS_MDP_DSC_RC_BUF_THRESH 0x3c /* 14 bytes */ +#define MDSS_MDP_DSC_RANGE_MIN_QP 0x74 /* 15 bytes */ +#define MDSS_MDP_DSC_RANGE_MAX_QP 0xB0 /* 15 bytes */ +#define MDSS_MDP_DSC_RANGE_BPG_OFFSET 0xEc /* 15 bytes */ + +/* Autorefresh related registers */ +#define MDP_REG_PP_0_SYNC_CONFIG_VSYNC REG_MDP(0x71004) +#define MDP_REG_PP_1_SYNC_CONFIG_VSYNC REG_MDP(0x71804) +#define MDP_REG_PP_SLAVE_SYNC_CONFIG_VSYNC REG_MDP(0x73004) +#define MDP_REG_PP_0_AUTOREFRESH_CONFIG REG_MDP(0x71030) +#define MDP_REG_PP_1_AUTOREFRESH_CONFIG REG_MDP(0x71830) +#define MDP_REG_PP_SLAVE_AUTOREFRESH_CONFIG REG_MDP(0x73030) + +/* Registers for programming the CDM hardware in bypass mode. */ +#define CDM_HDMI_PACK_OP_MODE REG_MDP (0x7A400) +#define MDP_OUT_CTL_0 REG_MDP (0x01410) +#define MDP_INTF_3_INTF_CONFIG REG_MDP (0x6C804) +#define CDM_CDWN2_OUT_SIZE REG_MDP (0x7A330) +#define CDM_CDWN2_OP_MODE REG_MDP (0x7A300) +#define CDM_CDWN2_CLAMP_OUT REG_MDP (0x7A304) +#define CDM_CSC_10_OP_MODE REG_MDP (0x7A200) + +#define HWIO_INT_CTRL_DSI_DESKEW_DONE_MASK_BMSK 0x80000000 +#define HWIO_INT_CTRL_DSI_DESKEW_DONE_MASK_SHFT 0x1f +#define HWIO_INT_CTRL_DSI_DESKEW_DONE_AK_BMSK 0x40000000 +#define HWIO_INT_CTRL_DSI_DESKEW_DONE_AK_SHFT 0x1e +#define HWIO_INT_CTRL_DSI_DESKEW_DONE_STAT_BMSK 0x40000000 +#define HWIO_INT_CTRL_DSI_DESKEW_DONE_STAT_SHFT 0x1e +#define HWIO_INT_CTRL_DSI_DYNAMIC_REFRESH_DONE_MASK_BMSK 0x20000000 +#define HWIO_INT_CTRL_DSI_DYNAMIC_REFRESH_DONE_MASK_SHFT 0x1d +#define HWIO_INT_CTRL_DSI_DYNAMIC_REFRESH_DONE_AK_BMSK 0x10000000 +#define HWIO_INT_CTRL_DSI_DYNAMIC_REFRESH_DONE_AK_SHFT 0x1c +#define HWIO_INT_CTRL_DSI_DYNAMIC_REFRESH_DONE_STAT_BMSK 0x10000000 +#define HWIO_INT_CTRL_DSI_DYNAMIC_REFRESH_DONE_STAT_SHFT 0x1c +#define HWIO_INT_CTRL_DSI_DYNAMIC_BLANKING_DMA_DONE_MASK_BMSK 0x8000000 +#define HWIO_INT_CTRL_DSI_DYNAMIC_BLANKING_DMA_DONE_MASK_SHFT 0x1b +#define HWIO_INT_CTRL_DSI_DYNAMIC_BLANKING_DMA_DONE_AK_BMSK 0x4000000 +#define HWIO_INT_CTRL_DSI_DYNAMIC_BLANKING_DMA_DONE_AK_SHFT 0x1a +#define HWIO_INT_CTRL_DSI_DYNAMIC_BLANKING_DMA_DONE_STAT_BMSK 0x4000000 +#define HWIO_INT_CTRL_DSI_DYNAMIC_BLANKING_DMA_DONE_STAT_SHFT 0x1a +#define HWIO_INT_CTRL_DSI_ERROR_MASK_BMSK 0x2000000 +#define HWIO_INT_CTRL_DSI_ERROR_MASK_SHFT 0x19 +#define HWIO_INT_CTRL_DSI_ERROR_AK_BMSK 0x1000000 +#define HWIO_INT_CTRL_DSI_ERROR_AK_SHFT 0x18 +#define HWIO_INT_CTRL_DSI_ERROR_STAT_BMSK 0x1000000 +#define HWIO_INT_CTRL_DSI_ERROR_STAT_SHFT 0x18 +#define HWIO_INT_CTRL_DSI_BTA_DONE_MASK_BMSK 0x200000 +#define HWIO_INT_CTRL_DSI_BTA_DONE_MASK_SHFT 0x15 +#define HWIO_INT_CTRL_DSI_BTA_DONE_AK_BMSK 0x100000 +#define HWIO_INT_CTRL_DSI_BTA_DONE_AK_SHFT 0x14 +#define HWIO_INT_CTRL_DSI_BTA_DONE_STAT_BMSK 0x100000 +#define HWIO_INT_CTRL_DSI_BTA_DONE_STAT_SHFT 0x14 +#define HWIO_INT_CTRL_DSI_VIDEO_MODE_DONE_MASK_BMSK 0x20000 +#define HWIO_INT_CTRL_DSI_VIDEO_MODE_DONE_MASK_SHFT 0x11 +#define HWIO_INT_CTRL_DSI_VIDEO_MODE_DONE_AK_BMSK 0x10000 +#define HWIO_INT_CTRL_DSI_VIDEO_MODE_DONE_AK_SHFT 0x10 +#define HWIO_INT_CTRL_DSI_VIDEO_MODE_DONE_STAT_BMSK 0x10000 +#define HWIO_INT_CTRL_DSI_VIDEO_MODE_DONE_STAT_SHFT 0x10 +#define HWIO_INT_CTRL_DSI_CMD_MDP_STREAM0_DONE_MASK_BMSK 0x800 +#define HWIO_INT_CTRL_DSI_CMD_MDP_STREAM0_DONE_MASK_SHFT 0xb +#define HWIO_INT_CTRL_DSI_CMD_MDP_STREAM0_DONE_AK_BMSK 0x400 +#define HWIO_INT_CTRL_DSI_CMD_MDP_STREAM0_DONE_AK_SHFT 0xa +#define HWIO_INT_CTRL_DSI_CMD_MDP_STREAM0_DONE_STAT_BMSK 0x400 +#define HWIO_INT_CTRL_DSI_CMD_MDP_STREAM0_DONE_STAT_SHFT 0xa +#define HWIO_INT_CTRL_DSI_CMD_MODE_MDP_DONE_MASK_BMSK 0x200 +#define HWIO_INT_CTRL_DSI_CMD_MODE_MDP_DONE_MASK_SHFT 0x9 +#define HWIO_INT_CTRL_DSI_CMD_MODE_MDP_DONE_AK_BMSK 0x100 +#define HWIO_INT_CTRL_DSI_CMD_MODE_MDP_DONE_AK_SHFT 0x8 +#define HWIO_INT_CTRL_DSI_CMD_MODE_MDP_DONE_STAT_BMSK 0x100 +#define HWIO_INT_CTRL_DSI_CMD_MODE_MDP_DONE_STAT_SHFT 0x8 +#define HWIO_INT_CTRL_DSI_CMD_MODE_DMA_DONE_MASK_BMSK 0x2 +#define HWIO_INT_CTRL_DSI_CMD_MODE_DMA_DONE_MASK_SHFT 0x1 +#define HWIO_INT_CTRL_DSI_CMD_MODE_DMA_DONE_AK_BMSK 0x1 +#define HWIO_INT_CTRL_DSI_CMD_MODE_DMA_DONE_AK_SHFT 0x0 +#define HWIO_INT_CTRL_DSI_CMD_MODE_DMA_DONE_STAT_BMSK 0x1 +#define HWIO_INT_CTRL_DSI_CMD_MODE_DMA_DONE_STAT_SHFT 0x0 +#define HWIO_CLK_STATUS_DSI_DYN_BYTE_INTF_CLK_ACTIVE_BMSK 0x800000 +#define HWIO_CLK_STATUS_DSI_DYN_BYTE_INTF_CLK_ACTIVE_SHFT 0x17 +#define HWIO_CLK_STATUS_DSI_HW_EVENT_CLK_ACTIVE_BMSK 0x400000 +#define HWIO_CLK_STATUS_DSI_HW_EVENT_CLK_ACTIVE_SHFT 0x16 +#define HWIO_CLK_STATUS_DSI_QDSS_CLK_ACTIVE_BMSK 0x200000 +#define HWIO_CLK_STATUS_DSI_QDSS_CLK_ACTIVE_SHFT 0x15 +#define HWIO_CLK_STATUS_DSI_LANE_LAYER_TG_BYTECLK_ACTIVE_BMSK 0x100000 +#define HWIO_CLK_STATUS_DSI_LANE_LAYER_TG_BYTECLK_ACTIVE_SHFT 0x14 +#define HWIO_CLK_STATUS_DSIPLL_UNLOCKED_CLR_BMSK 0x10000 +#define HWIO_CLK_STATUS_DSIPLL_UNLOCKED_CLR_SHFT 0x10 +#define HWIO_CLK_STATUS_DSIPLL_UNLOCKED_BMSK 0x10000 +#define HWIO_CLK_STATUS_DSIPLL_UNLOCKED_SHFT 0x10 +#define HWIO_CLK_STATUS_DSI_CAM_BIST_PCLK_ACTIVE_BMSK 0x8000 +#define HWIO_CLK_STATUS_DSI_CAM_BIST_PCLK_ACTIVE_SHFT 0xf +#define HWIO_CLK_STATUS_DSI_VID_PCLK_ACTIVE_BMSK 0x4000 +#define HWIO_CLK_STATUS_DSI_VID_PCLK_ACTIVE_SHFT 0xe +#define HWIO_CLK_STATUS_DSI_CMD_PCLK_ACTIVE_BMSK 0x2000 +#define HWIO_CLK_STATUS_DSI_CMD_PCLK_ACTIVE_SHFT 0xd +#define HWIO_CLK_STATUS_DSI_DYN_CMD_PCLK_ACTIVE_BMSK 0x1000 +#define HWIO_CLK_STATUS_DSI_DYN_CMD_PCLK_ACTIVE_SHFT 0xc +#define HWIO_CLK_STATUS_DSI_DYN_PCLK_ACTIVE_BMSK 0x400 +#define HWIO_CLK_STATUS_DSI_DYN_PCLK_ACTIVE_SHFT 0xa +#define HWIO_CLK_STATUS_DSI_AON_PCLK_ACTIVE_BMSK 0x200 +#define HWIO_CLK_STATUS_DSI_AON_PCLK_ACTIVE_SHFT 0x9 +#define HWIO_CLK_STATUS_DSI_AON_ESCCLK_ACTIVE_BMSK 0x100 +#define HWIO_CLK_STATUS_DSI_AON_ESCCLK_ACTIVE_SHFT 0x8 +#define HWIO_CLK_STATUS_DSI_DYN_BYTECLK_ACTIVE_BMSK 0x80 +#define HWIO_CLK_STATUS_DSI_DYN_BYTECLK_ACTIVE_SHFT 0x7 +#define HWIO_CLK_STATUS_DSI_AON_BYTECLK_ACTIVE_BMSK 0x40 +#define HWIO_CLK_STATUS_DSI_AON_BYTECLK_ACTIVE_SHFT 0x6 +#define HWIO_CLK_STATUS_DSI_DYN_DSICLK_ACTIVE_BMSK 0x20 +#define HWIO_CLK_STATUS_DSI_DYN_DSICLK_ACTIVE_SHFT 0x5 +#define HWIO_CLK_STATUS_DSI_AON_DSICLK_ACTIVE_BMSK 0x10 +#define HWIO_CLK_STATUS_DSI_AON_DSICLK_ACTIVE_SHFT 0x4 +#define HWIO_CLK_STATUS_DSI_DYN_AHBS_HCLK_ACTIVE_BMSK 0x8 +#define HWIO_CLK_STATUS_DSI_DYN_AHBS_HCLK_ACTIVE_SHFT 0x3 +#define HWIO_CLK_STATUS_DSI_AON_AHBS_HCLK_ACTIVE_BMSK 0x4 +#define HWIO_CLK_STATUS_DSI_AON_AHBS_HCLK_ACTIVE_SHFT 0x2 +#define HWIO_CLK_STATUS_DSI_DYN_AHBM_HCLK_ACTIVE_BMSK 0x2 +#define HWIO_CLK_STATUS_DSI_DYN_AHBM_HCLK_ACTIVE_SHFT 0x1 +#define HWIO_CLK_STATUS_DSI_AON_AHBM_HCLK_ACTIVE_BMSK 0x1 +#define HWIO_CLK_STATUS_DSI_AON_AHBM_HCLK_ACTIVE_SHFT 0x0 +#define HWIO_COMMAND_MODE_MDP_DCS_CMD_CTRL_INSERT_DCS_COMMAND_BMSK 0x10000 +#define HWIO_COMMAND_MODE_MDP_DCS_CMD_CTRL_INSERT_DCS_COMMAND_SHFT 0x10 +#define HWIO_COMMAND_MODE_DMA_CTRL_EMBEDDED_MODE_BMSK 0x10000000 +#define HWIO_COMMAND_MODE_DMA_CTRL_EMBEDDED_MODE_SHFT 0x1c +#define HWIO_COMMAND_MODE_DMA_CTRL_POWER_MODE_BMSK 0x4000000 +#define HWIO_COMMAND_MODE_DMA_CTRL_POWER_MODE_SHFT 0x1a +#define HWIO_CLK_CTRL_DSI_DMA_CLK_STOP_BMSK 0x400000 +#define HWIO_CLK_CTRL_DSI_DMA_CLK_STOP_SHFT 0x16 +#define HWIO_CLK_CTRL_DSI_FORCE_ON_LANE_LAYER_TG_BYTECLK_BMSK 0x200000 +#define HWIO_CLK_CTRL_DSI_FORCE_ON_LANE_LAYER_TG_BYTECLK_SHFT 0x15 +#define HWIO_CLK_CTRL_DSI_FORCE_ON_DYN_PCLK_BMSK 0x100000 +#define HWIO_CLK_CTRL_DSI_FORCE_ON_DYN_PCLK_SHFT 0x14 +#define HWIO_CLK_CTRL_DSI_DSICLK_HYSTERISIS1_CTRL_BMSK 0x30000 +#define HWIO_CLK_CTRL_DSI_DSICLK_HYSTERISIS1_CTRL_SHFT 0x10 +#define HWIO_CLK_CTRL_DSI_AHBM_HCLK_HYSTERISIS1_CTRL_BMSK 0xc000 +#define HWIO_CLK_CTRL_DSI_AHBM_HCLK_HYSTERISIS1_CTRL_SHFT 0xe +#define HWIO_CLK_CTRL_DSI_AHBS_HCLK_HYSTERISIS1_CTRL_BMSK 0x3000 +#define HWIO_CLK_CTRL_DSI_AHBS_HCLK_HYSTERISIS1_CTRL_SHFT 0xc +#define HWIO_CLK_CTRL_DSI_FORCE_ON_DYN_BYTECLK_BMSK 0x800 +#define HWIO_CLK_CTRL_DSI_FORCE_ON_DYN_BYTECLK_SHFT 0xb +#define HWIO_CLK_CTRL_DSI_FORCE_ON_DYN_DSICLK_BMSK 0x400 +#define HWIO_CLK_CTRL_DSI_FORCE_ON_DYN_DSICLK_SHFT 0xa +#define HWIO_CLK_CTRL_DSI_FORCE_ON_DYN_AHBM_HCLK_BMSK 0x200 +#define HWIO_CLK_CTRL_DSI_FORCE_ON_DYN_AHBM_HCLK_SHFT 0x9 +#define HWIO_CLK_CTRL_DSI_FORCE_ON_DYN_AHBS_HCLK_BMSK 0x100 +#define HWIO_CLK_CTRL_DSI_FORCE_ON_DYN_AHBS_HCLK_SHFT 0x8 +#define HWIO_CLK_CTRL_DSI_ESCCLK_ON_BMSK 0x20 +#define HWIO_CLK_CTRL_DSI_ESCCLK_ON_SHFT 0x5 +#define HWIO_CLK_CTRL_DSI_BYTECLK_ON_BMSK 0x10 +#define HWIO_CLK_CTRL_DSI_BYTECLK_ON_SHFT 0x4 +#define HWIO_CLK_CTRL_DSI_DSICLK_ON_BMSK 0x8 +#define HWIO_CLK_CTRL_DSI_DSICLK_ON_SHFT 0x3 +#define HWIO_CLK_CTRL_DSI_PCLK_ON_BMSK 0x4 +#define HWIO_CLK_CTRL_DSI_PCLK_ON_SHFT 0x2 +#define HWIO_CLK_CTRL_DSI_AHBM_SCLK_ON_BMSK 0x2 +#define HWIO_CLK_CTRL_DSI_AHBM_SCLK_ON_SHFT 0x1 +#define HWIO_CLK_CTRL_DSI_AHBS_HCLK_ON_BMSK 0x1 +#define HWIO_CLK_CTRL_DSI_AHBS_HCLK_ON_SHFT 0x0 + + +/* DSI Phy Related Registers */ +#define HWIO_DSI_0_CLKOUT_TIMING_CTRL_ADDR (MIPI_DSI0_BASE + 0x000000c4) +#define DSI_PHY_DSIPHY_CMN_CTRL_1_OFFSET (0x28) +#define DSI_0_PHY_CMN_REG_BASE DSI0_PHY_BASE + +#define DSI_0_PHY_CMN_REVISION_ID0_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x00000000) +#define DSI_0_PHY_CMN_DSI_LANE_CTRL0_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x00000098) +#define DSI_0_PHY_CMN_CTRL_0_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x00000024) +#define DSI_0_PHY_CMN_PLL_CNTRL_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x00000038) +#define DSI_0_PHY_CMN_RBUF_CTRL_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x0000001c) + +#define DSI_0_PHY_DLN0_DATALN_REG_BASE (MDSSHW_BASE + 0x00094600) +#define DSI_0_PHY_DLN0_CFG0_ADDR (DSI_0_PHY_DLN0_DATALN_REG_BASE + 0x00000000) + +#define DSI_0_PHY_DLN1_DATALN_REG_BASE (MDSSHW_BASE + 0x00094680) +#define DSI_0_PHY_DLN1_CFG0_ADDR (DSI_0_PHY_DLN1_DATALN_REG_BASE + 0x00000000) + +#define DSI_0_PHY_DLN2_DATALN_REG_BASE (MDSSHW_BASE + 0x00094700) +#define DSI_0_PHY_DLN2_CFG0_ADDR (DSI_0_PHY_DLN2_DATALN_REG_BASE + 0x00000000) + +#define DSI_0_PHY_DLN3_DATALN_REG_BASE (MDSSHW_BASE + 0x00094780) +#define DSI_0_PHY_DLN3_CFG0_ADDR (DSI_0_PHY_DLN3_DATALN_REG_BASE + 0x00000000) + +#define DSI_0_PHY_CKLN_DATALN_REG_BASE (MDSSHW_BASE + 0x00094800) +#define DSI_0_PHY_CKLN_CFG0_ADDR (DSI_0_PHY_CKLN_DATALN_REG_BASE + 0x00000000) + +#define DSI_0_PHY_DLN0_LPTX_STR_CTRL_ADDR \ + (DSI_0_PHY_DLN0_DATALN_REG_BASE + 0x00000024) +#define DSI_0_PHY_DLN0_LPRX_CTRL_ADDR \ + (DSI_0_PHY_DLN0_DATALN_REG_BASE + 0x00000028) +#define DSI_0_PHY_DLN0_PIN_SWAP_ADDR \ + (DSI_0_PHY_DLN0_DATALN_REG_BASE + 0x00000014) +#define DSI_0_PHY_DLN0_HSTX_STR_CTRL_ADDR \ + (DSI_0_PHY_DLN0_DATALN_REG_BASE + 0x00000018) +#define DSI_0_PHY_DLN0_CFG0_ADDR (DSI_0_PHY_DLN0_DATALN_REG_BASE + 0x00000000) +#define DSI_0_PHY_DLN0_CFG1_ADDR (DSI_0_PHY_DLN0_DATALN_REG_BASE + 0x00000004) +#define DSI_0_PHY_DLN0_CFG2_ADDR (DSI_0_PHY_DLN0_DATALN_REG_BASE + 0x00000008) +#define DSI_0_PHY_DLN0_CFG3_ADDR (DSI_0_PHY_DLN0_DATALN_REG_BASE + 0x0000000c) + +#define DSI_0_PHY_DLN0_OFFSET_TOP_CTRL_ADDR \ + (DSI_0_PHY_DLN0_DATALN_REG_BASE + 0x0000001c) +#define DSI_0_PHY_DLN0_OFFSET_BOT_CTRL_ADDR \ + (DSI_0_PHY_DLN0_DATALN_REG_BASE + 0x00000020) +#define DSI_0_PHY_DLN0_TX_DCTRL_ADDR \ + (DSI_0_PHY_DLN0_DATALN_REG_BASE + 0x0000002c) + +#define DSI_0_PHY_CMN_VREG_CTRL_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x00000020) +#define DSI_0_PHY_CMN_GLBL_CTRL_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x00000018) +#define DSI_0_PHY_CMN_TIMING_CTRL_0_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x000000ac) +#define DSI_0_PHY_CMN_TIMING_CTRL_1_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x000000b0) +#define DSI_0_PHY_CMN_TIMING_CTRL_2_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x000000b4) +#define DSI_0_PHY_CMN_TIMING_CTRL_3_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x000000b8) +#define DSI_0_PHY_CMN_TIMING_CTRL_4_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x000000bc) +#define DSI_0_PHY_CMN_TIMING_CTRL_5_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x000000c0) +#define DSI_0_PHY_CMN_TIMING_CTRL_6_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x000000c4) +#define DSI_0_PHY_CMN_TIMING_CTRL_7_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x000000c8) +#define DSI_0_PHY_CMN_TIMING_CTRL_8_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x000000cc) +#define DSI_0_PHY_CMN_TIMING_CTRL_9_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x000000d0) +#define DSI_0_PHY_CMN_TIMING_CTRL_10_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x000000d4) +#define DSI_0_PHY_CMN_TIMING_CTRL_11_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x000000d8) +#define DSI_0_PHY_CMN_CLK_CFG1_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x00000014) + +#define DSI_0_PHY_CMN_CTRL_2_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x0000002c) +#define DSI_0_PHY_CMN_CLK_CFG0_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x00000010) +#define DSI_0_PHY_CMN_PHY_STATUS_ADDR (DSI_0_PHY_CMN_REG_BASE + 0x000000ec) + +#define DSI_0_PHY_PLL_QLINK_COM_REG_BASE (MDSSHW_BASE + 0x00094a00) +#define DSI_1_PHY_PLL_QLINK_COM_REG_BASE (MDSSHW_BASE + 0x00096a00) +#define DSI_0_PHY_PLL_CORE_INPUT_OVERRIDE_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x000000a8) +#define DSI_0_PHY_PLL_DECIMAL_DIV_START_1_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x000000cc) +#define DSI_0_PHY_PLL_FRAC_DIV_START_LOW_1_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x000000d0) +#define DSI_0_PHY_PLL_FRAC_DIV_START_MID_1_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x000000d4) +#define DSI_0_PHY_PLL_FRAC_DIV_START_HIGH_1_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x000000d8) +#define DSI_0_PHY_PLL_PROP_GAIN_RATE_1_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x0000014c) +#define DSI_0_PHY_PLL_SYSTEM_MUXES_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x00000024) +#define DSI_0_PHY_PLL_LOCKDET_RATE_1_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x00000144) +#define DSI_0_PHY_PLL_OUTDIV_RATE_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x00000140) +#define DSI_0_PHY_PLL_LOCK_DELAY_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x00000184) +#define DSI_0_PHY_PLL_CLOCK_INVERTERS_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x0000018c) +#define DSI_0_PHY_PLL_CMODE_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x0000002c) +#define DSI_0_PHY_PLL_ANALOG_CONTROLS_ONE_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x00000000) +#define DSI_0_PHY_PLL_ANALOG_CONTROLS_TWO_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x00000004) +#define DSI_0_PHY_PLL_ANALOG_CONTROLS_THREE_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x00000010) +#define DSI_0_PHY_PLL_DSM_DIVIDER_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x0000001c) +#define DSI_0_PHY_PLL_FEEDBACK_DIVIDER_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x00000020) +#define DSI_0_PHY_PLL_CALIBRATION_SETTINGS_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x00000030) +#define DSI_0_PHY_PLL_BAND_SEL_CAL_SETTINGS_THREE_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x00000054) +#define DSI_0_PHY_PLL_FREQ_DETECT_SETTINGS_ONE_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x00000064) +#define DSI_0_PHY_PLL_OUTDIV_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x00000094) +#define DSI_0_PHY_PLL_CORE_OVERRIDE_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x000000a4) +#define DSI_1_PHY_PLL_DIGITAL_TIMERS_TWO_ADDR \ + (DSI_1_PHY_PLL_QLINK_COM_REG_BASE + 0x000000b4) +#define DSI_0_PHY_PLL_BAND_SEL_RATE_1_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x00000154) +#define DSI_0_PHY_PLL_INT_GAIN_IFILT_BAND_1_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x0000015c) + +#define DSI_0_PHY_PLL_FL_INT_GAIN_PFILT_BAND_1_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x00000164) +#define DSI_0_PHY_PLL_LOCK_OVERRIDE_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x00000180) +#define DSI_0_PHY_PLL_PFILT_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x0000007c) +#define DSI_0_PHY_PLL_IFILT_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x00000080) +#define DSI_0_PHY_PLL_COMMON_STATUS_ONE_ADDR \ + (DSI_0_PHY_PLL_QLINK_COM_REG_BASE + 0x000001a0) + +void mdp_set_revision(int rev); +int mdp_get_revision(void); +int mdp_dsi_video_config(struct msm_panel_info *pinfo, struct fbcon_config *fb); +int mdp_dsi_cmd_config(struct msm_panel_info *pinfo, struct fbcon_config *fb); +int mdp_dsi_video_on(struct msm_panel_info *pinfo); +int mdp_dma_on(struct msm_panel_info *pinfo); + +#endif