diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 46498ee43bcf978fd8041feb2dce98f48766671b..a72c058b29fa536eafa80d0ba2fb31ca4e6affce 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -1,5 +1,3 @@ -source "drivers/clk/qcom/mdss/Kconfig" - config QCOM_GDSC bool select PM_GENERIC_DOMAINS if PM diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index f64d82d989dc15434478a225fd0bfad4391dd7ee..40dca851b95a4b168f2efd17ecd870c8353d9fa1 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -60,5 +60,3 @@ obj-$(CONFIG_SM_NPUCC_LITO) += npucc-lito.o obj-$(CONFIG_SM_VIDEOCC_LITO) += videocc-lito.o obj-$(CONFIG_SM_GPUCC_LITO) += gpucc-lito.o obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o - -obj-y += mdss/ diff --git a/drivers/clk/qcom/mdss/Kconfig b/drivers/clk/qcom/mdss/Kconfig deleted file mode 100644 index 3b5b835a6566875e528fdef9200d8bd1f6115096..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/Kconfig +++ /dev/null @@ -1,17 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -config QCOM_MDSS_PLL - bool "MDSS pll programming" - depends on COMMON_CLK_QCOM - help - It provides support for DSI, eDP and HDMI interface pll programming on MDSS - hardware. It also handles the pll specific resources and turn them on/off when - mdss pll client tries to enable/disable pll clocks. - -config QCOM_MDSS_DP_PLL - bool "MDSS DisplayPort PLL programming" - depends on QCOM_MDSS_PLL - default n - help - This flag enables the modules for DisplayPort (DP) PLL programming and is - required for all targets that support DP. diff --git a/drivers/clk/qcom/mdss/Makefile b/drivers/clk/qcom/mdss/Makefile deleted file mode 100644 index a6d69af4ac4d1b2cb9c29b038274833bb138311f..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-pll-util.o -obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-pll.o -obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dsi-pll-10nm.o -obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dsi-pll-7nm.o -obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dsi-pll-28lpm.o -obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dsi-pll-28nm-util.o -obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dsi-pll-14nm.o -obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-dsi-pll-14nm-util.o -obj-$(CONFIG_QCOM_MDSS_PLL) += mdss-hdmi-pll-28lpm.o -obj-$(CONFIG_QCOM_MDSS_DP_PLL) += mdss-dp-pll-7nm.o \ - mdss-dp-pll-7nm-util.o \ - mdss-dp-pll-10nm.o \ - mdss-dp-pll-10nm-util.o \ - mdss-dp-pll-14nm.o \ diff --git a/drivers/clk/qcom/mdss/mdss-dp-pll-10nm-util.c b/drivers/clk/qcom/mdss/mdss-dp-pll-10nm-util.c deleted file mode 100644 index e0c6600b3c1b3b69929afe2239a5d69ab43d08bc..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dp-pll-10nm-util.c +++ /dev/null @@ -1,757 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include - -#include "mdss-pll.h" -#include "mdss-dp-pll.h" -#include "mdss-dp-pll-10nm.h" - -#define DP_PHY_REVISION_ID0 0x0000 -#define DP_PHY_REVISION_ID1 0x0004 -#define DP_PHY_REVISION_ID2 0x0008 -#define DP_PHY_REVISION_ID3 0x000C - -#define DP_PHY_CFG 0x0010 -#define DP_PHY_PD_CTL 0x0018 -#define DP_PHY_MODE 0x001C - -#define DP_PHY_AUX_CFG0 0x0020 -#define DP_PHY_AUX_CFG1 0x0024 -#define DP_PHY_AUX_CFG2 0x0028 -#define DP_PHY_AUX_CFG3 0x002C -#define DP_PHY_AUX_CFG4 0x0030 -#define DP_PHY_AUX_CFG5 0x0034 -#define DP_PHY_AUX_CFG6 0x0038 -#define DP_PHY_AUX_CFG7 0x003C -#define DP_PHY_AUX_CFG8 0x0040 -#define DP_PHY_AUX_CFG9 0x0044 -#define DP_PHY_AUX_INTERRUPT_MASK 0x0048 -#define DP_PHY_AUX_INTERRUPT_CLEAR 0x004C -#define DP_PHY_AUX_BIST_CFG 0x0050 - -#define DP_PHY_VCO_DIV 0x0064 -#define DP_PHY_TX0_TX1_LANE_CTL 0x006C -#define DP_PHY_TX2_TX3_LANE_CTL 0x0088 - -#define DP_PHY_SPARE0 0x00AC -#define DP_PHY_STATUS 0x00C0 - -/* Tx registers */ -#define TXn_BIST_MODE_LANENO 0x0000 -#define TXn_CLKBUF_ENABLE 0x0008 -#define TXn_TX_EMP_POST1_LVL 0x000C - -#define TXn_TX_DRV_LVL 0x001C - -#define TXn_RESET_TSYNC_EN 0x0024 -#define TXn_PRE_STALL_LDO_BOOST_EN 0x0028 -#define TXn_TX_BAND 0x002C -#define TXn_SLEW_CNTL 0x0030 -#define TXn_INTERFACE_SELECT 0x0034 - -#define TXn_RES_CODE_LANE_TX 0x003C -#define TXn_RES_CODE_LANE_RX 0x0040 -#define TXn_RES_CODE_LANE_OFFSET_TX 0x0044 -#define TXn_RES_CODE_LANE_OFFSET_RX 0x0048 - -#define TXn_DEBUG_BUS_SEL 0x0058 -#define TXn_TRANSCEIVER_BIAS_EN 0x005C -#define TXn_HIGHZ_DRVR_EN 0x0060 -#define TXn_TX_POL_INV 0x0064 -#define TXn_PARRATE_REC_DETECT_IDLE_EN 0x0068 - -#define TXn_LANE_MODE_1 0x008C - -#define TXn_TRAN_DRVR_EMP_EN 0x00C0 -#define TXn_TX_INTERFACE_MODE 0x00C4 - -#define TXn_VMODE_CTRL1 0x00F0 - -/* PLL register offset */ -#define QSERDES_COM_ATB_SEL1 0x0000 -#define QSERDES_COM_ATB_SEL2 0x0004 -#define QSERDES_COM_FREQ_UPDATE 0x0008 -#define QSERDES_COM_BG_TIMER 0x000C -#define QSERDES_COM_SSC_EN_CENTER 0x0010 -#define QSERDES_COM_SSC_ADJ_PER1 0x0014 -#define QSERDES_COM_SSC_ADJ_PER2 0x0018 -#define QSERDES_COM_SSC_PER1 0x001C -#define QSERDES_COM_SSC_PER2 0x0020 -#define QSERDES_COM_SSC_STEP_SIZE1 0x0024 -#define QSERDES_COM_SSC_STEP_SIZE2 0x0028 -#define QSERDES_COM_POST_DIV 0x002C -#define QSERDES_COM_POST_DIV_MUX 0x0030 -#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN 0x0034 -#define QSERDES_COM_CLK_ENABLE1 0x0038 -#define QSERDES_COM_SYS_CLK_CTRL 0x003C -#define QSERDES_COM_SYSCLK_BUF_ENABLE 0x0040 -#define QSERDES_COM_PLL_EN 0x0044 -#define QSERDES_COM_PLL_IVCO 0x0048 -#define QSERDES_COM_CMN_IETRIM 0x004C -#define QSERDES_COM_CMN_IPTRIM 0x0050 - -#define QSERDES_COM_CP_CTRL_MODE0 0x0060 -#define QSERDES_COM_CP_CTRL_MODE1 0x0064 -#define QSERDES_COM_PLL_RCTRL_MODE0 0x0068 -#define QSERDES_COM_PLL_RCTRL_MODE1 0x006C -#define QSERDES_COM_PLL_CCTRL_MODE0 0x0070 -#define QSERDES_COM_PLL_CCTRL_MODE1 0x0074 -#define QSERDES_COM_PLL_CNTRL 0x0078 -#define QSERDES_COM_BIAS_EN_CTRL_BY_PSM 0x007C -#define QSERDES_COM_SYSCLK_EN_SEL 0x0080 -#define QSERDES_COM_CML_SYSCLK_SEL 0x0084 -#define QSERDES_COM_RESETSM_CNTRL 0x0088 -#define QSERDES_COM_RESETSM_CNTRL2 0x008C -#define QSERDES_COM_LOCK_CMP_EN 0x0090 -#define QSERDES_COM_LOCK_CMP_CFG 0x0094 -#define QSERDES_COM_LOCK_CMP1_MODE0 0x0098 -#define QSERDES_COM_LOCK_CMP2_MODE0 0x009C -#define QSERDES_COM_LOCK_CMP3_MODE0 0x00A0 - -#define QSERDES_COM_DEC_START_MODE0 0x00B0 -#define QSERDES_COM_DEC_START_MODE1 0x00B4 -#define QSERDES_COM_DIV_FRAC_START1_MODE0 0x00B8 -#define QSERDES_COM_DIV_FRAC_START2_MODE0 0x00BC -#define QSERDES_COM_DIV_FRAC_START3_MODE0 0x00C0 -#define QSERDES_COM_DIV_FRAC_START1_MODE1 0x00C4 -#define QSERDES_COM_DIV_FRAC_START2_MODE1 0x00C8 -#define QSERDES_COM_DIV_FRAC_START3_MODE1 0x00CC -#define QSERDES_COM_INTEGLOOP_INITVAL 0x00D0 -#define QSERDES_COM_INTEGLOOP_EN 0x00D4 -#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0 0x00D8 -#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0 0x00DC -#define QSERDES_COM_INTEGLOOP_GAIN0_MODE1 0x00E0 -#define QSERDES_COM_INTEGLOOP_GAIN1_MODE1 0x00E4 -#define QSERDES_COM_VCOCAL_DEADMAN_CTRL 0x00E8 -#define QSERDES_COM_VCO_TUNE_CTRL 0x00EC -#define QSERDES_COM_VCO_TUNE_MAP 0x00F0 - -#define QSERDES_COM_CMN_STATUS 0x0124 -#define QSERDES_COM_RESET_SM_STATUS 0x0128 - -#define QSERDES_COM_CLK_SEL 0x0138 -#define QSERDES_COM_HSCLK_SEL 0x013C - -#define QSERDES_COM_CORECLK_DIV_MODE0 0x0148 - -#define QSERDES_COM_SW_RESET 0x0150 -#define QSERDES_COM_CORE_CLK_EN 0x0154 -#define QSERDES_COM_C_READY_STATUS 0x0158 -#define QSERDES_COM_CMN_CONFIG 0x015C - -#define QSERDES_COM_SVS_MODE_CLK_SEL 0x0164 - -#define DP_PHY_PLL_POLL_SLEEP_US 500 -#define DP_PHY_PLL_POLL_TIMEOUT_US 10000 - -#define DP_VCO_RATE_8100MHZDIV1000 8100000UL -#define DP_VCO_RATE_9720MHZDIV1000 9720000UL -#define DP_VCO_RATE_10800MHZDIV1000 10800000UL - -int dp_mux_set_parent_10nm(void *context, unsigned int reg, unsigned int val) -{ - struct mdss_pll_resources *dp_res = context; - int rc; - u32 auxclk_div; - - rc = mdss_pll_resource_enable(dp_res, true); - if (rc) { - pr_err("Failed to enable mdss DP PLL resources\n"); - return rc; - } - - auxclk_div = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_VCO_DIV); - auxclk_div &= ~0x03; /* bits 0 to 1 */ - - if (val == 0) /* mux parent index = 0 */ - auxclk_div |= 1; - else if (val == 1) /* mux parent index = 1 */ - auxclk_div |= 2; - else if (val == 2) /* mux parent index = 2 */ - auxclk_div |= 0; - - MDSS_PLL_REG_W(dp_res->phy_base, - DP_PHY_VCO_DIV, auxclk_div); - /* Make sure the PHY registers writes are done */ - wmb(); - pr_debug("%s: mux=%d auxclk_div=%x\n", __func__, val, auxclk_div); - - mdss_pll_resource_enable(dp_res, false); - - return 0; -} - -int dp_mux_get_parent_10nm(void *context, unsigned int reg, unsigned int *val) -{ - int rc; - u32 auxclk_div = 0; - struct mdss_pll_resources *dp_res = context; - - rc = mdss_pll_resource_enable(dp_res, true); - if (rc) { - pr_err("Failed to enable dp_res resources\n"); - return rc; - } - - auxclk_div = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_VCO_DIV); - auxclk_div &= 0x03; - - if (auxclk_div == 1) /* Default divider */ - *val = 0; - else if (auxclk_div == 2) - *val = 1; - else if (auxclk_div == 0) - *val = 2; - - mdss_pll_resource_enable(dp_res, false); - - pr_debug("%s: auxclk_div=%d, val=%d\n", __func__, auxclk_div, *val); - - return 0; -} - -static int dp_vco_pll_init_db_10nm(struct dp_pll_db *pdb, - unsigned long rate) -{ - struct mdss_pll_resources *dp_res = pdb->pll; - u32 spare_value = 0; - - spare_value = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_SPARE0); - pdb->lane_cnt = spare_value & 0x0F; - pdb->orientation = (spare_value & 0xF0) >> 4; - - pr_debug("%s: spare_value=0x%x, ln_cnt=0x%x, orientation=0x%x\n", - __func__, spare_value, pdb->lane_cnt, pdb->orientation); - - switch (rate) { - case DP_VCO_HSCLK_RATE_1620MHZDIV1000: - pr_debug("%s: VCO rate: %ld\n", __func__, - DP_VCO_RATE_9720MHZDIV1000); - pdb->hsclk_sel = 0x0c; - pdb->dec_start_mode0 = 0x69; - pdb->div_frac_start1_mode0 = 0x00; - pdb->div_frac_start2_mode0 = 0x80; - pdb->div_frac_start3_mode0 = 0x07; - pdb->integloop_gain0_mode0 = 0x3f; - pdb->integloop_gain1_mode0 = 0x00; - pdb->vco_tune_map = 0x00; - pdb->lock_cmp1_mode0 = 0x6f; - pdb->lock_cmp2_mode0 = 0x08; - pdb->lock_cmp3_mode0 = 0x00; - pdb->phy_vco_div = 0x1; - pdb->lock_cmp_en = 0x00; - break; - case DP_VCO_HSCLK_RATE_2700MHZDIV1000: - pr_debug("%s: VCO rate: %ld\n", __func__, - DP_VCO_RATE_10800MHZDIV1000); - pdb->hsclk_sel = 0x04; - pdb->dec_start_mode0 = 0x69; - pdb->div_frac_start1_mode0 = 0x00; - pdb->div_frac_start2_mode0 = 0x80; - pdb->div_frac_start3_mode0 = 0x07; - pdb->integloop_gain0_mode0 = 0x3f; - pdb->integloop_gain1_mode0 = 0x00; - pdb->vco_tune_map = 0x00; - pdb->lock_cmp1_mode0 = 0x0f; - pdb->lock_cmp2_mode0 = 0x0e; - pdb->lock_cmp3_mode0 = 0x00; - pdb->phy_vco_div = 0x1; - pdb->lock_cmp_en = 0x00; - break; - case DP_VCO_HSCLK_RATE_5400MHZDIV1000: - pr_debug("%s: VCO rate: %ld\n", __func__, - DP_VCO_RATE_10800MHZDIV1000); - pdb->hsclk_sel = 0x00; - pdb->dec_start_mode0 = 0x8c; - pdb->div_frac_start1_mode0 = 0x00; - pdb->div_frac_start2_mode0 = 0x00; - pdb->div_frac_start3_mode0 = 0x0a; - pdb->integloop_gain0_mode0 = 0x3f; - pdb->integloop_gain1_mode0 = 0x00; - pdb->vco_tune_map = 0x00; - pdb->lock_cmp1_mode0 = 0x1f; - pdb->lock_cmp2_mode0 = 0x1c; - pdb->lock_cmp3_mode0 = 0x00; - pdb->phy_vco_div = 0x2; - pdb->lock_cmp_en = 0x00; - break; - case DP_VCO_HSCLK_RATE_8100MHZDIV1000: - pr_debug("%s: VCO rate: %ld\n", __func__, - DP_VCO_RATE_8100MHZDIV1000); - pdb->hsclk_sel = 0x03; - pdb->dec_start_mode0 = 0x69; - pdb->div_frac_start1_mode0 = 0x00; - pdb->div_frac_start2_mode0 = 0x80; - pdb->div_frac_start3_mode0 = 0x07; - pdb->integloop_gain0_mode0 = 0x3f; - pdb->integloop_gain1_mode0 = 0x00; - pdb->vco_tune_map = 0x00; - pdb->lock_cmp1_mode0 = 0x2f; - pdb->lock_cmp2_mode0 = 0x2a; - pdb->lock_cmp3_mode0 = 0x00; - pdb->phy_vco_div = 0x0; - pdb->lock_cmp_en = 0x08; - break; - default: - return -EINVAL; - } - return 0; -} - -static int dp_config_vco_rate_10nm(struct dp_pll_vco_clk *vco, - unsigned long rate) -{ - u32 res = 0; - struct mdss_pll_resources *dp_res = vco->priv; - struct dp_pll_db *pdb = (struct dp_pll_db *)dp_res->priv; - - res = dp_vco_pll_init_db_10nm(pdb, rate); - if (res) { - pr_err("VCO Init DB failed\n"); - return res; - } - - if (pdb->lane_cnt != 4) { - if (pdb->orientation == ORIENTATION_CC2) - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_PD_CTL, 0x6d); - else - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_PD_CTL, 0x75); - } else { - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_PD_CTL, 0x7d); - } - - /* Make sure the PHY register writes are done */ - wmb(); - - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_SVS_MODE_CLK_SEL, 0x01); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_SYSCLK_EN_SEL, 0x37); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_SYS_CLK_CTRL, 0x02); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CLK_ENABLE1, 0x0e); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_SYSCLK_BUF_ENABLE, 0x06); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CLK_SEL, 0x30); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CMN_CONFIG, 0x02); - - /* Different for each clock rates */ - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_HSCLK_SEL, pdb->hsclk_sel); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_DEC_START_MODE0, pdb->dec_start_mode0); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_DIV_FRAC_START1_MODE0, pdb->div_frac_start1_mode0); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_DIV_FRAC_START2_MODE0, pdb->div_frac_start2_mode0); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_DIV_FRAC_START3_MODE0, pdb->div_frac_start3_mode0); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_INTEGLOOP_GAIN0_MODE0, pdb->integloop_gain0_mode0); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_INTEGLOOP_GAIN1_MODE0, pdb->integloop_gain1_mode0); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_VCO_TUNE_MAP, pdb->vco_tune_map); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_LOCK_CMP1_MODE0, pdb->lock_cmp1_mode0); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_LOCK_CMP2_MODE0, pdb->lock_cmp2_mode0); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_LOCK_CMP3_MODE0, pdb->lock_cmp3_mode0); - /* Make sure the PLL register writes are done */ - wmb(); - - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_BG_TIMER, 0x0a); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CORECLK_DIV_MODE0, 0x0a); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_VCO_TUNE_CTRL, 0x00); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x3f); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CORE_CLK_EN, 0x1f); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_PLL_IVCO, 0x07); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_LOCK_CMP_EN, pdb->lock_cmp_en); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_PLL_CCTRL_MODE0, 0x36); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_PLL_RCTRL_MODE0, 0x16); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CP_CTRL_MODE0, 0x06); - /* Make sure the PHY register writes are done */ - wmb(); - - if (pdb->orientation == ORIENTATION_CC2) - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_MODE, 0x4c); - else - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_MODE, 0x5c); - /* Make sure the PLL register writes are done */ - wmb(); - - /* TX Lane configuration */ - MDSS_PLL_REG_W(dp_res->phy_base, - DP_PHY_TX0_TX1_LANE_CTL, 0x05); - MDSS_PLL_REG_W(dp_res->phy_base, - DP_PHY_TX2_TX3_LANE_CTL, 0x05); - - /* TX-0 register configuration */ - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_TRANSCEIVER_BIAS_EN, 0x1a); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_VMODE_CTRL1, 0x40); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_PRE_STALL_LDO_BOOST_EN, 0x30); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_INTERFACE_SELECT, 0x3d); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_CLKBUF_ENABLE, 0x0f); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_RESET_TSYNC_EN, 0x03); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_TRAN_DRVR_EMP_EN, 0x03); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, - TXn_PARRATE_REC_DETECT_IDLE_EN, 0x00); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_TX_INTERFACE_MODE, 0x00); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_TX_BAND, 0x4); - - /* TX-1 register configuration */ - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_TRANSCEIVER_BIAS_EN, 0x1a); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_VMODE_CTRL1, 0x40); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_PRE_STALL_LDO_BOOST_EN, 0x30); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_INTERFACE_SELECT, 0x3d); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_CLKBUF_ENABLE, 0x0f); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_RESET_TSYNC_EN, 0x03); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_TRAN_DRVR_EMP_EN, 0x03); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, - TXn_PARRATE_REC_DETECT_IDLE_EN, 0x00); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_TX_INTERFACE_MODE, 0x00); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_TX_BAND, 0x4); - /* Make sure the PHY register writes are done */ - wmb(); - - /* dependent on the vco frequency */ - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_VCO_DIV, pdb->phy_vco_div); - - return res; -} - -static bool dp_10nm_pll_lock_status(struct mdss_pll_resources *dp_res) -{ - u32 status; - bool pll_locked; - - /* poll for PLL lock status */ - if (readl_poll_timeout_atomic((dp_res->pll_base + - QSERDES_COM_C_READY_STATUS), - status, - ((status & BIT(0)) > 0), - DP_PHY_PLL_POLL_SLEEP_US, - DP_PHY_PLL_POLL_TIMEOUT_US)) { - pr_err("%s: C_READY status is not high. Status=%x\n", - __func__, status); - pll_locked = false; - } else { - pll_locked = true; - } - - return pll_locked; -} - -static bool dp_10nm_phy_rdy_status(struct mdss_pll_resources *dp_res) -{ - u32 status; - bool phy_ready = true; - - /* poll for PHY ready status */ - if (readl_poll_timeout_atomic((dp_res->phy_base + - DP_PHY_STATUS), - status, - ((status & (BIT(1))) > 0), - DP_PHY_PLL_POLL_SLEEP_US, - DP_PHY_PLL_POLL_TIMEOUT_US)) { - pr_err("%s: Phy_ready is not high. Status=%x\n", - __func__, status); - phy_ready = false; - } - - return phy_ready; -} - -static int dp_pll_enable_10nm(struct clk_hw *hw) -{ - int rc = 0; - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - struct mdss_pll_resources *dp_res = vco->priv; - struct dp_pll_db *pdb = (struct dp_pll_db *)dp_res->priv; - u32 bias_en, drvr_en; - - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_AUX_CFG2, 0x04); - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x01); - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x05); - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x01); - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x09); - wmb(); /* Make sure the PHY register writes are done */ - - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_RESETSM_CNTRL, 0x20); - wmb(); /* Make sure the PLL register writes are done */ - - if (!dp_10nm_pll_lock_status(dp_res)) { - rc = -EINVAL; - goto lock_err; - } - - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x19); - /* Make sure the PHY register writes are done */ - wmb(); - /* poll for PHY ready status */ - if (!dp_10nm_phy_rdy_status(dp_res)) { - rc = -EINVAL; - goto lock_err; - } - - pr_debug("%s: PLL is locked\n", __func__); - - if (pdb->lane_cnt == 1) { - bias_en = 0x3e; - drvr_en = 0x13; - } else { - bias_en = 0x3f; - drvr_en = 0x10; - } - - if (pdb->lane_cnt != 4) { - if (pdb->orientation == ORIENTATION_CC1) { - MDSS_PLL_REG_W(dp_res->ln_tx1_base, - TXn_HIGHZ_DRVR_EN, drvr_en); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, - TXn_TRANSCEIVER_BIAS_EN, bias_en); - } else { - MDSS_PLL_REG_W(dp_res->ln_tx0_base, - TXn_HIGHZ_DRVR_EN, drvr_en); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, - TXn_TRANSCEIVER_BIAS_EN, bias_en); - } - } else { - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_HIGHZ_DRVR_EN, drvr_en); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, - TXn_TRANSCEIVER_BIAS_EN, bias_en); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_HIGHZ_DRVR_EN, drvr_en); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, - TXn_TRANSCEIVER_BIAS_EN, bias_en); - } - - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_TX_POL_INV, 0x0a); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_TX_POL_INV, 0x0a); - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x18); - udelay(2000); - - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x19); - - /* - * Make sure all the register writes are completed before - * doing any other operation - */ - wmb(); - - /* poll for PHY ready status */ - if (!dp_10nm_phy_rdy_status(dp_res)) { - rc = -EINVAL; - goto lock_err; - } - - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_TX_DRV_LVL, 0x38); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_TX_DRV_LVL, 0x38); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_TX_EMP_POST1_LVL, 0x20); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_TX_EMP_POST1_LVL, 0x20); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_RES_CODE_LANE_OFFSET_TX, 0x06); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_RES_CODE_LANE_OFFSET_TX, 0x06); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_RES_CODE_LANE_OFFSET_RX, 0x07); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_RES_CODE_LANE_OFFSET_RX, 0x07); - /* Make sure the PHY register writes are done */ - wmb(); - -lock_err: - return rc; -} - -static int dp_pll_disable_10nm(struct clk_hw *hw) -{ - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - struct mdss_pll_resources *dp_res = vco->priv; - - /* Assert DP PHY power down */ - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_PD_CTL, 0x2); - /* - * Make sure all the register writes to disable PLL are - * completed before doing any other operation - */ - wmb(); - - return 0; -} - - -int dp_vco_prepare_10nm(struct clk_hw *hw) -{ - int rc = 0; - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - struct mdss_pll_resources *dp_res = vco->priv; - - pr_debug("rate=%ld\n", vco->rate); - rc = mdss_pll_resource_enable(dp_res, true); - if (rc) { - pr_err("Failed to enable mdss DP pll resources\n"); - goto error; - } - - if ((dp_res->vco_cached_rate != 0) - && (dp_res->vco_cached_rate == vco->rate)) { - rc = vco->hw.init->ops->set_rate(hw, - dp_res->vco_cached_rate, dp_res->vco_cached_rate); - if (rc) { - pr_err("index=%d vco_set_rate failed. rc=%d\n", - rc, dp_res->index); - mdss_pll_resource_enable(dp_res, false); - goto error; - } - } - - rc = dp_pll_enable_10nm(hw); - if (rc) { - mdss_pll_resource_enable(dp_res, false); - pr_err("ndx=%d failed to enable dp pll\n", - dp_res->index); - goto error; - } - - mdss_pll_resource_enable(dp_res, false); -error: - return rc; -} - -void dp_vco_unprepare_10nm(struct clk_hw *hw) -{ - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - struct mdss_pll_resources *dp_res = vco->priv; - - if (!dp_res) { - pr_err("Invalid input parameter\n"); - return; - } - - if (!dp_res->pll_on && - mdss_pll_resource_enable(dp_res, true)) { - pr_err("pll resource can't be enabled\n"); - return; - } - dp_res->vco_cached_rate = vco->rate; - dp_pll_disable_10nm(hw); - - dp_res->handoff_resources = false; - mdss_pll_resource_enable(dp_res, false); - dp_res->pll_on = false; -} - -int dp_vco_set_rate_10nm(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - struct mdss_pll_resources *dp_res = vco->priv; - int rc; - - rc = mdss_pll_resource_enable(dp_res, true); - if (rc) { - pr_err("pll resource can't be enabled\n"); - return rc; - } - - pr_debug("DP lane CLK rate=%ld\n", rate); - - rc = dp_config_vco_rate_10nm(vco, rate); - if (rc) - pr_err("%s: Failed to set clk rate\n", __func__); - - mdss_pll_resource_enable(dp_res, false); - - vco->rate = rate; - - return 0; -} - -unsigned long dp_vco_recalc_rate_10nm(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - int rc; - u32 div, hsclk_div, link_clk_div = 0; - u64 vco_rate; - struct mdss_pll_resources *dp_res = vco->priv; - - rc = mdss_pll_resource_enable(dp_res, true); - if (rc) { - pr_err("Failed to enable mdss DP pll=%d\n", dp_res->index); - return rc; - } - - div = MDSS_PLL_REG_R(dp_res->pll_base, QSERDES_COM_HSCLK_SEL); - div &= 0x0f; - - if (div == 12) - hsclk_div = 6; /* Default */ - else if (div == 4) - hsclk_div = 4; - else if (div == 0) - hsclk_div = 2; - else if (div == 3) - hsclk_div = 1; - else { - pr_debug("unknown divider. forcing to default\n"); - hsclk_div = 5; - } - - div = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_AUX_CFG2); - div >>= 2; - - if ((div & 0x3) == 0) - link_clk_div = 5; - else if ((div & 0x3) == 1) - link_clk_div = 10; - else if ((div & 0x3) == 2) - link_clk_div = 20; - else - pr_err("%s: unsupported div. Phy_mode: %d\n", __func__, div); - - if (link_clk_div == 20) { - vco_rate = DP_VCO_HSCLK_RATE_2700MHZDIV1000; - } else { - if (hsclk_div == 6) - vco_rate = DP_VCO_HSCLK_RATE_1620MHZDIV1000; - else if (hsclk_div == 4) - vco_rate = DP_VCO_HSCLK_RATE_2700MHZDIV1000; - else if (hsclk_div == 2) - vco_rate = DP_VCO_HSCLK_RATE_5400MHZDIV1000; - else - vco_rate = DP_VCO_HSCLK_RATE_8100MHZDIV1000; - } - - pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate); - - mdss_pll_resource_enable(dp_res, false); - - dp_res->vco_cached_rate = vco->rate = vco_rate; - return (unsigned long)vco_rate; -} - -long dp_vco_round_rate_10nm(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - unsigned long rrate = rate; - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - - if (rate <= vco->min_rate) - rrate = vco->min_rate; - else if (rate <= DP_VCO_HSCLK_RATE_2700MHZDIV1000) - rrate = DP_VCO_HSCLK_RATE_2700MHZDIV1000; - else if (rate <= DP_VCO_HSCLK_RATE_5400MHZDIV1000) - rrate = DP_VCO_HSCLK_RATE_5400MHZDIV1000; - else - rrate = vco->max_rate; - - pr_debug("%s: rrate=%ld\n", __func__, rrate); - - *parent_rate = rrate; - return rrate; -} - diff --git a/drivers/clk/qcom/mdss/mdss-dp-pll-10nm.c b/drivers/clk/qcom/mdss/mdss-dp-pll-10nm.c deleted file mode 100644 index b3cfcbad00155f5b9dfedaefd18343fa4b10bb19..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dp-pll-10nm.c +++ /dev/null @@ -1,287 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. - */ - -/* - * Display Port PLL driver block diagram for branch clocks - * - * +------------------------------+ - * | DP_VCO_CLK | - * | | - * | +-------------------+ | - * | | (DP PLL/VCO) | | - * | +---------+---------+ | - * | v | - * | +----------+-----------+ | - * | | hsclk_divsel_clk_src | | - * | +----------+-----------+ | - * +------------------------------+ - * | - * +------------<---------v------------>----------+ - * | | - * +-----v------------+ | - * | dp_link_clk_src | | - * | divsel_ten | | - * +---------+--------+ | - * | | - * | | - * v v - * Input to DISPCC block | - * for link clk, crypto clk | - * and interface clock | - * | - * | - * +--------<------------+-----------------+---<---+ - * | | | - * +-------v------+ +--------v-----+ +--------v------+ - * | vco_divided | | vco_divided | | vco_divided | - * | _clk_src | | _clk_src | | _clk_src | - * | | | | | | - * |divsel_six | | divsel_two | | divsel_four | - * +-------+------+ +-----+--------+ +--------+------+ - * | | | - * v------->----------v-------------<------v - * | - * +----------+---------+ - * | vco_divided_clk | - * | _src_mux | - * +---------+----------+ - * | - * v - * Input to DISPCC block - * for DP pixel clock - * - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include - -#include "mdss-pll.h" -#include "mdss-dp-pll.h" -#include "mdss-dp-pll-10nm.h" - -static struct dp_pll_db dp_pdb; -static struct clk_ops mux_clk_ops; - -static struct regmap_config dp_pll_10nm_cfg = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x910, -}; - -static struct regmap_bus dp_pixel_mux_regmap_ops = { - .reg_write = dp_mux_set_parent_10nm, - .reg_read = dp_mux_get_parent_10nm, -}; - -/* Op structures */ -static const struct clk_ops dp_10nm_vco_clk_ops = { - .recalc_rate = dp_vco_recalc_rate_10nm, - .set_rate = dp_vco_set_rate_10nm, - .round_rate = dp_vco_round_rate_10nm, - .prepare = dp_vco_prepare_10nm, - .unprepare = dp_vco_unprepare_10nm, -}; - -static struct dp_pll_vco_clk dp_vco_clk = { - .min_rate = DP_VCO_HSCLK_RATE_1620MHZDIV1000, - .max_rate = DP_VCO_HSCLK_RATE_8100MHZDIV1000, - .hw.init = &(struct clk_init_data){ - .name = "dp_vco_clk", - .parent_names = (const char *[]){ "xo_board" }, - .num_parents = 1, - .ops = &dp_10nm_vco_clk_ops, - }, -}; - -static struct clk_fixed_factor dp_link_clk_divsel_ten = { - .div = 10, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "dp_link_clk_divsel_ten", - .parent_names = - (const char *[]){ "dp_vco_clk" }, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dp_vco_divsel_two_clk_src = { - .div = 2, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "dp_vco_divsel_two_clk_src", - .parent_names = - (const char *[]){ "dp_vco_clk" }, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dp_vco_divsel_four_clk_src = { - .div = 4, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "dp_vco_divsel_four_clk_src", - .parent_names = - (const char *[]){ "dp_vco_clk" }, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dp_vco_divsel_six_clk_src = { - .div = 6, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "dp_vco_divsel_six_clk_src", - .parent_names = - (const char *[]){ "dp_vco_clk" }, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE), - .ops = &clk_fixed_factor_ops, - }, -}; - - -static int clk_mux_determine_rate(struct clk_hw *hw, - struct clk_rate_request *req) -{ - int ret = 0; - - ret = __clk_mux_determine_rate_closest(hw, req); - if (ret) - return ret; - - /* Set the new parent of mux if there is a new valid parent */ - if (hw->clk && req->best_parent_hw->clk) - clk_set_parent(hw->clk, req->best_parent_hw->clk); - - return 0; -} - -static unsigned long mux_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk *div_clk = NULL, *vco_clk = NULL; - struct dp_pll_vco_clk *vco = NULL; - - div_clk = clk_get_parent(hw->clk); - if (!div_clk) - return 0; - - vco_clk = clk_get_parent(div_clk); - if (!vco_clk) - return 0; - - vco = to_dp_vco_hw(__clk_get_hw(vco_clk)); - if (!vco) - return 0; - - if (vco->rate == DP_VCO_HSCLK_RATE_8100MHZDIV1000) - return (vco->rate / 6); - else if (vco->rate == DP_VCO_HSCLK_RATE_5400MHZDIV1000) - return (vco->rate / 4); - else - return (vco->rate / 2); -} - -static struct clk_regmap_mux dp_vco_divided_clk_src_mux = { - .reg = 0x64, - .shift = 0, - .width = 2, - - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dp_vco_divided_clk_src_mux", - .parent_names = - (const char *[]){"dp_vco_divsel_two_clk_src", - "dp_vco_divsel_four_clk_src", - "dp_vco_divsel_six_clk_src"}, - .num_parents = 3, - .ops = &mux_clk_ops, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - }, - }, -}; - -static struct clk_hw *mdss_dp_pllcc_10nm[] = { - [DP_VCO_CLK] = &dp_vco_clk.hw, - [DP_LINK_CLK_DIVSEL_TEN] = &dp_link_clk_divsel_ten.hw, - [DP_VCO_DIVIDED_TWO_CLK_SRC] = &dp_vco_divsel_two_clk_src.hw, - [DP_VCO_DIVIDED_FOUR_CLK_SRC] = &dp_vco_divsel_four_clk_src.hw, - [DP_VCO_DIVIDED_SIX_CLK_SRC] = &dp_vco_divsel_six_clk_src.hw, - [DP_VCO_DIVIDED_CLK_SRC_MUX] = &dp_vco_divided_clk_src_mux.clkr.hw, -}; - -int dp_pll_clock_register_10nm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int rc = -ENOTSUPP, i = 0; - struct clk_onecell_data *clk_data; - struct clk *clk; - struct regmap *regmap; - int num_clks = ARRAY_SIZE(mdss_dp_pllcc_10nm); - - clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL); - if (!clk_data) - return -ENOMEM; - - clk_data->clks = devm_kcalloc(&pdev->dev, num_clks, - sizeof(struct clk *), GFP_KERNEL); - if (!clk_data->clks) - return -ENOMEM; - - clk_data->clk_num = num_clks; - - pll_res->priv = &dp_pdb; - dp_pdb.pll = pll_res; - - /* Set client data for vco, mux and div clocks */ - regmap = devm_regmap_init(&pdev->dev, &dp_pixel_mux_regmap_ops, - pll_res, &dp_pll_10nm_cfg); - dp_vco_divided_clk_src_mux.clkr.regmap = regmap; - mux_clk_ops = clk_regmap_mux_closest_ops; - mux_clk_ops.determine_rate = clk_mux_determine_rate; - mux_clk_ops.recalc_rate = mux_recalc_rate; - - dp_vco_clk.priv = pll_res; - - for (i = DP_VCO_CLK; i <= DP_VCO_DIVIDED_CLK_SRC_MUX; i++) { - pr_debug("reg clk: %d index: %d\n", i, pll_res->index); - clk = devm_clk_register(&pdev->dev, - mdss_dp_pllcc_10nm[i]); - if (IS_ERR(clk)) { - pr_err("clk registration failed for DP: %d\n", - pll_res->index); - rc = -EINVAL; - goto clk_reg_fail; - } - clk_data->clks[i] = clk; - } - - rc = of_clk_add_provider(pdev->dev.of_node, - of_clk_src_onecell_get, clk_data); - if (rc) { - pr_err("%s: Clock register failed rc=%d\n", __func__, rc); - rc = -EPROBE_DEFER; - } else { - pr_debug("%s SUCCESS\n", __func__); - } - return 0; -clk_reg_fail: - return rc; -} diff --git a/drivers/clk/qcom/mdss/mdss-dp-pll-10nm.h b/drivers/clk/qcom/mdss/mdss-dp-pll-10nm.h deleted file mode 100644 index 5135c87e064091f998c5ad24939199189c2fd298..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dp-pll-10nm.h +++ /dev/null @@ -1,51 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - */ - -#ifndef __MDSS_DP_PLL_10NM_H -#define __MDSS_DP_PLL_10NM_H - -#define DP_VCO_HSCLK_RATE_1620MHZDIV1000 1620000UL -#define DP_VCO_HSCLK_RATE_2700MHZDIV1000 2700000UL -#define DP_VCO_HSCLK_RATE_5400MHZDIV1000 5400000UL -#define DP_VCO_HSCLK_RATE_8100MHZDIV1000 8100000UL - -struct dp_pll_db { - struct mdss_pll_resources *pll; - - /* lane and orientation settings */ - u8 lane_cnt; - u8 orientation; - - /* COM PHY settings */ - u32 hsclk_sel; - u32 dec_start_mode0; - u32 div_frac_start1_mode0; - u32 div_frac_start2_mode0; - u32 div_frac_start3_mode0; - u32 integloop_gain0_mode0; - u32 integloop_gain1_mode0; - u32 vco_tune_map; - u32 lock_cmp1_mode0; - u32 lock_cmp2_mode0; - u32 lock_cmp3_mode0; - u32 lock_cmp_en; - - /* PHY vco divider */ - u32 phy_vco_div; -}; - -int dp_vco_set_rate_10nm(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate); -unsigned long dp_vco_recalc_rate_10nm(struct clk_hw *hw, - unsigned long parent_rate); -long dp_vco_round_rate_10nm(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate); -int dp_vco_prepare_10nm(struct clk_hw *hw); -void dp_vco_unprepare_10nm(struct clk_hw *hw); -int dp_mux_set_parent_10nm(void *context, - unsigned int reg, unsigned int val); -int dp_mux_get_parent_10nm(void *context, - unsigned int reg, unsigned int *val); -#endif /* __MDSS_DP_PLL_10NM_H */ diff --git a/drivers/clk/qcom/mdss/mdss-dp-pll-14nm.c b/drivers/clk/qcom/mdss/mdss-dp-pll-14nm.c deleted file mode 100644 index f1c745d7580bb021f8b4567671515c8d72398105..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dp-pll-14nm.c +++ /dev/null @@ -1,820 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. - */ - -/* - *************************************************************************** - ******** Display Port PLL driver block diagram for branch clocks ********** - *************************************************************************** - - +--------------------------+ - | DP_VCO_CLK | - | | - | +-------------------+ | - | | (DP PLL/VCO) | | - | +---------+---------+ | - | v | - | +----------+-----------+ | - | | hsclk_divsel_clk_src | | - | +----------+-----------+ | - +--------------------------+ - | - v - +------------<------------|------------>-------------+ - | | | -+----------v----------+ +----------v----------+ +----------v----------+ -| dp_link_2x_clk | | vco_divided_clk_src | | vco_divided_clk_src | -| divsel_five | | | | | -v----------+----------v | divsel_two | | divsel_four | - | +----------+----------+ +----------+----------+ - | | | - v v v - | +---------------------+ | - Input to MMSSCC block | | (aux_clk_ops) | | - for link clk, crypto clk +--> vco_divided_clk <-+ - and interface clock | _src_mux | - +----------+----------+ - | - v - Input to MMSSCC block - for DP pixel clock - - ****************************************************************************** - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include - -#include - -#include "mdss-pll.h" -#include "mdss-dp-pll.h" -#include "mdss-dp-pll-14nm.h" - -static struct dp_pll_db dp_pdb; -static struct clk_ops mux_clk_ops; - -static struct regmap_config dp_pll_14nm_cfg = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x910, -}; - -static struct regmap_bus dp_pixel_mux_regmap_ops = { - .reg_write = dp_mux_set_parent_14nm, - .reg_read = dp_mux_get_parent_14nm, -}; - -/* Op structures */ -static const struct clk_ops dp_14nm_vco_clk_ops = { - .recalc_rate = dp_vco_recalc_rate_14nm, - .set_rate = dp_vco_set_rate_14nm, - .round_rate = dp_vco_round_rate_14nm, - .prepare = dp_vco_prepare_14nm, - .unprepare = dp_vco_unprepare_14nm, -}; - -static struct dp_pll_vco_clk dp_vco_clk = { - .min_rate = DP_VCO_HSCLK_RATE_1620MHZDIV1000, - .max_rate = DP_VCO_HSCLK_RATE_5400MHZDIV1000, - .hw.init = &(struct clk_init_data){ - .name = "dp_vco_clk", - .parent_names = (const char *[]){ "xo_board" }, - .num_parents = 1, - .ops = &dp_14nm_vco_clk_ops, - }, -}; - -static struct clk_fixed_factor dp_phy_pll_link_clk = { - .div = 10, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "dp_phy_pll_link_clk", - .parent_names = - (const char *[]){ "dp_vco_clk" }, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dp_vco_divsel_two_clk_src = { - .div = 2, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "dp_vco_divsel_two_clk_src", - .parent_names = - (const char *[]){ "dp_vco_clk" }, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dp_vco_divsel_four_clk_src = { - .div = 4, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "dp_vco_divsel_four_clk_src", - .parent_names = - (const char *[]){ "dp_vco_clk" }, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE), - .ops = &clk_fixed_factor_ops, - }, -}; - -static int clk_mux_determine_rate(struct clk_hw *hw, - struct clk_rate_request *req) -{ - int ret = 0; - - ret = __clk_mux_determine_rate_closest(hw, req); - if (ret) - return ret; - - /* Set the new parent of mux if there is a new valid parent */ - if (hw->clk && req->best_parent_hw->clk) - clk_set_parent(hw->clk, req->best_parent_hw->clk); - - return 0; -} - - -static unsigned long mux_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk *div_clk = NULL, *vco_clk = NULL; - struct dp_pll_vco_clk *vco = NULL; - - div_clk = clk_get_parent(hw->clk); - if (!div_clk) - return 0; - - vco_clk = clk_get_parent(div_clk); - if (!vco_clk) - return 0; - - vco = to_dp_vco_hw(__clk_get_hw(vco_clk)); - if (!vco) - return 0; - - if (vco->rate == DP_VCO_HSCLK_RATE_5400MHZDIV1000) - return (vco->rate / 4); - else - return (vco->rate / 2); -} - -static struct clk_regmap_mux dp_phy_pll_vco_div_clk = { - .reg = 0x64, - .shift = 0, - .width = 1, - - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dp_phy_pll_vco_div_clk", - .parent_names = - (const char *[]){"dp_vco_divsel_two_clk_src", - "dp_vco_divsel_four_clk_src"}, - .num_parents = 2, - .ops = &mux_clk_ops, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - }, - }, -}; - -static struct clk_hw *mdss_dp_pllcc_14nm[] = { - [DP_VCO_CLK] = &dp_vco_clk.hw, - [DP_PHY_PLL_LINK_CLK] = &dp_phy_pll_link_clk.hw, - [DP_VCO_DIVSEL_FOUR_CLK_SRC] = &dp_vco_divsel_four_clk_src.hw, - [DP_VCO_DIVSEL_TWO_CLK_SRC] = &dp_vco_divsel_two_clk_src.hw, - [DP_PHY_PLL_VCO_DIV_CLK] = &dp_phy_pll_vco_div_clk.clkr.hw, -}; - - -int dp_mux_set_parent_14nm(void *context, unsigned int reg, unsigned int val) -{ - struct mdss_pll_resources *dp_res = context; - int rc; - u32 auxclk_div; - - rc = mdss_pll_resource_enable(dp_res, true); - if (rc) { - pr_err("Failed to enable mdss DP PLL resources\n"); - return rc; - } - - auxclk_div = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_VCO_DIV); - auxclk_div &= ~0x03; /* bits 0 to 1 */ - - if (val == 0) /* mux parent index = 0 */ - auxclk_div |= 1; - else if (val == 1) /* mux parent index = 1 */ - auxclk_div |= 2; - - MDSS_PLL_REG_W(dp_res->phy_base, - DP_PHY_VCO_DIV, auxclk_div); - /* Make sure the PHY registers writes are done */ - wmb(); - pr_debug("mux=%d auxclk_div=%x\n", val, auxclk_div); - - mdss_pll_resource_enable(dp_res, false); - - return 0; -} - -int dp_mux_get_parent_14nm(void *context, unsigned int reg, unsigned int *val) -{ - int rc; - u32 auxclk_div = 0; - struct mdss_pll_resources *dp_res = context; - - rc = mdss_pll_resource_enable(dp_res, true); - if (rc) { - pr_err("Failed to enable dp_res resources\n"); - return rc; - } - - auxclk_div = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_VCO_DIV); - auxclk_div &= 0x03; - - if (auxclk_div == 1) /* Default divider */ - *val = 0; - else if (auxclk_div == 2) - *val = 1; - - mdss_pll_resource_enable(dp_res, false); - - pr_debug("auxclk_div=%d, val=%d\n", auxclk_div, *val); - - return 0; -} - -static int dp_vco_pll_init_db_14nm(struct dp_pll_db *pdb, - unsigned long rate) -{ - struct mdss_pll_resources *dp_res = pdb->pll; - u32 spare_value = 0; - - spare_value = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_SPARE0); - pdb->lane_cnt = spare_value & 0x0F; - pdb->orientation = (spare_value & 0xF0) >> 4; - - pr_debug("spare_value=0x%x, ln_cnt=0x%x, orientation=0x%x\n", - spare_value, pdb->lane_cnt, pdb->orientation); - - switch (rate) { - case DP_VCO_HSCLK_RATE_1620MHZDIV1000: - pdb->hsclk_sel = 0x2c; - pdb->dec_start_mode0 = 0x69; - pdb->div_frac_start1_mode0 = 0x00; - pdb->div_frac_start2_mode0 = 0x80; - pdb->div_frac_start3_mode0 = 0x07; - pdb->lock_cmp1_mode0 = 0xbf; - pdb->lock_cmp2_mode0 = 0x21; - pdb->lock_cmp3_mode0 = 0x00; - pdb->phy_vco_div = 0x1; - pdb->lane_mode_1 = 0xc6; - break; - case DP_VCO_HSCLK_RATE_2700MHZDIV1000: - pdb->hsclk_sel = 0x24; - pdb->dec_start_mode0 = 0x69; - pdb->div_frac_start1_mode0 = 0x00; - pdb->div_frac_start2_mode0 = 0x80; - pdb->div_frac_start3_mode0 = 0x07; - pdb->lock_cmp1_mode0 = 0x3f; - pdb->lock_cmp2_mode0 = 0x38; - pdb->lock_cmp3_mode0 = 0x00; - pdb->phy_vco_div = 0x1; - pdb->lane_mode_1 = 0xc4; - break; - case DP_VCO_HSCLK_RATE_5400MHZDIV1000: - pdb->hsclk_sel = 0x20; - pdb->dec_start_mode0 = 0x8c; - pdb->div_frac_start1_mode0 = 0x00; - pdb->div_frac_start2_mode0 = 0x00; - pdb->div_frac_start3_mode0 = 0x0a; - pdb->lock_cmp1_mode0 = 0x7f; - pdb->lock_cmp2_mode0 = 0x70; - pdb->lock_cmp3_mode0 = 0x00; - pdb->phy_vco_div = 0x2; - pdb->lane_mode_1 = 0xc4; - break; - default: - return -EINVAL; - } - return 0; -} - -int dp_config_vco_rate_14nm(struct dp_pll_vco_clk *vco, - unsigned long rate) -{ - u32 res = 0; - struct mdss_pll_resources *dp_res = vco->priv; - struct dp_pll_db *pdb = (struct dp_pll_db *)dp_res->priv; - - res = dp_vco_pll_init_db_14nm(pdb, rate); - if (res) { - pr_err("VCO Init DB failed\n"); - return res; - } - - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_PD_CTL, 0x3d); - - /* Make sure the PHY register writes are done */ - wmb(); - - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_SVS_MODE_CLK_SEL, 0x01); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_SYSCLK_EN_SEL, 0x37); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_CLK_SELECT, 0x00); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_SYS_CLK_CTRL, 0x06); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x3f); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_CLK_ENABLE1, 0x0e); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_BG_CTRL, 0x0f); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_SYSCLK_BUF_ENABLE, 0x06); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_CLK_SELECT, 0x30); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_PLL_IVCO, 0x0f); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_PLL_CCTRL_MODE0, 0x28); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_PLL_RCTRL_MODE0, 0x16); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_CP_CTRL_MODE0, 0x0b); - - /* Parameters dependent on vco clock frequency */ - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_HSCLK_SEL, pdb->hsclk_sel); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_DEC_START_MODE0, pdb->dec_start_mode0); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_DIV_FRAC_START1_MODE0, pdb->div_frac_start1_mode0); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_DIV_FRAC_START2_MODE0, pdb->div_frac_start2_mode0); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_DIV_FRAC_START3_MODE0, pdb->div_frac_start3_mode0); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_LOCK_CMP1_MODE0, pdb->lock_cmp1_mode0); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_LOCK_CMP2_MODE0, pdb->lock_cmp2_mode0); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_LOCK_CMP3_MODE0, pdb->lock_cmp3_mode0); - - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x40); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_VCO_TUNE_MAP, 0x00); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_BG_TIMER, 0x08); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_CORECLK_DIV, 0x05); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_VCO_TUNE_CTRL, 0x00); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_VCO_TUNE1_MODE0, 0x00); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_VCO_TUNE2_MODE0, 0x00); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_VCO_TUNE_CTRL, 0x00); - wmb(); /* make sure write happens */ - - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_CORE_CLK_EN, 0x0f); - wmb(); /* make sure write happens */ - - if (pdb->orientation == ORIENTATION_CC2) - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_MODE, 0xc9); - else - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_MODE, 0xd9); - wmb(); /* make sure write happens */ - - /* TX Lane configuration */ - MDSS_PLL_REG_W(dp_res->phy_base, - DP_PHY_TX0_TX1_LANE_CTL, 0x05); - MDSS_PLL_REG_W(dp_res->phy_base, - DP_PHY_TX2_TX3_LANE_CTL, 0x05); - - /* TX-0 register configuration */ - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x1a); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_VMODE_CTRL1, 0x40); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_PRE_STALL_LDO_BOOST_EN, 0x30); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_INTERFACE_SELECT, 0x3d); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_CLKBUF_ENABLE, 0x0f); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_RESET_TSYNC_EN, 0x03); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_TRAN_DRVR_EMP_EN, 0x03); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_PARRATE_REC_DETECT_IDLE_EN, 0x00); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_TX_INTERFACE_MODE, 0x00); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_TX_EMP_POST1_LVL, 0x2b); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_TX_DRV_LVL, 0x2f); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_TX_BAND, 0x4); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_RES_CODE_LANE_OFFSET_TX, 0x12); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_RES_CODE_LANE_OFFSET_RX, 0x12); - - /* TX-1 register configuration */ - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x1a); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX1_OFFSET + TXn_VMODE_CTRL1, 0x40); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX1_OFFSET + TXn_PRE_STALL_LDO_BOOST_EN, 0x30); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX1_OFFSET + TXn_INTERFACE_SELECT, 0x3d); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX1_OFFSET + TXn_CLKBUF_ENABLE, 0x0f); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX1_OFFSET + TXn_RESET_TSYNC_EN, 0x03); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX1_OFFSET + TXn_TRAN_DRVR_EMP_EN, 0x03); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX1_OFFSET + TXn_PARRATE_REC_DETECT_IDLE_EN, 0x00); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX1_OFFSET + TXn_TX_INTERFACE_MODE, 0x00); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX1_OFFSET + TXn_TX_EMP_POST1_LVL, 0x2b); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX1_OFFSET + TXn_TX_DRV_LVL, 0x2f); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX1_OFFSET + TXn_TX_BAND, 0x4); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX1_OFFSET + TXn_RES_CODE_LANE_OFFSET_TX, 0x12); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX1_OFFSET + TXn_RES_CODE_LANE_OFFSET_RX, 0x12); - wmb(); /* make sure write happens */ - - /* PHY VCO divider programming */ - MDSS_PLL_REG_W(dp_res->phy_base, - DP_PHY_VCO_DIV, pdb->phy_vco_div); - wmb(); /* make sure write happens */ - - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_CMN_CONFIG, 0x02); - wmb(); /* make sure write happens */ - - return res; -} - -static bool dp_14nm_pll_lock_status(struct mdss_pll_resources *dp_res) -{ - u32 status; - bool pll_locked; - - /* poll for PLL lock status */ - if (readl_poll_timeout_atomic((dp_res->pll_base + - QSERDES_COM_C_READY_STATUS), - status, - ((status & BIT(0)) > 0), - DP_PLL_POLL_SLEEP_US, - DP_PLL_POLL_TIMEOUT_US)) { - pr_err("C_READY status is not high. Status=%x\n", status); - pll_locked = false; - } else { - pll_locked = true; - } - - return pll_locked; -} - -static bool dp_14nm_phy_rdy_status(struct mdss_pll_resources *dp_res) -{ - u32 status; - bool phy_ready = true; - - /* poll for PHY ready status */ - if (readl_poll_timeout_atomic((dp_res->phy_base + - DP_PHY_STATUS), - status, - ((status & (BIT(1) | BIT(0))) > 0), - DP_PHY_POLL_SLEEP_US, - DP_PHY_POLL_TIMEOUT_US)) { - pr_err("Phy_ready is not high. Status=%x\n", status); - phy_ready = false; - } - - return phy_ready; -} - -static int dp_pll_enable_14nm(struct clk_hw *hw) -{ - int rc = 0; - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - struct mdss_pll_resources *dp_res = vco->priv; - - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x01); - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x05); - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x01); - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x09); - wmb(); /* Make sure the PHY register writes are done */ - - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_RESETSM_CNTRL, 0x20); - wmb(); /* Make sure the PLL register writes are done */ - - udelay(900); /* hw recommended delay for full PU */ - - if (!dp_14nm_pll_lock_status(dp_res)) { - rc = -EINVAL; - goto lock_err; - } - - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x19); - wmb(); /* Make sure the PHY register writes are done */ - - udelay(10); /* hw recommended delay */ - - if (!dp_14nm_phy_rdy_status(dp_res)) { - rc = -EINVAL; - goto lock_err; - } - - pr_debug("PLL is locked\n"); - - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x3f); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_HIGHZ_DRVR_EN, 0x10); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x3f); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX1_OFFSET + TXn_HIGHZ_DRVR_EN, 0x10); - - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX0_OFFSET + TXn_TX_POL_INV, 0x0a); - MDSS_PLL_REG_W(dp_res->phy_base, - QSERDES_TX1_OFFSET + TXn_TX_POL_INV, 0x0a); - - /* - * Switch DP Mainlink clock (cc_dpphy_link_clk) from DP - * controller side with final frequency - */ - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x18); - wmb(); /* Make sure the PHY register writes are done */ - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x19); - wmb(); /* Make sure the PHY register writes are done */ - -lock_err: - return rc; -} - -static int dp_pll_disable_14nm(struct clk_hw *hw) -{ - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - struct mdss_pll_resources *dp_res = vco->priv; - - /* Assert DP PHY power down */ - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_PD_CTL, 0x2); - /* - * Make sure all the register writes to disable PLL are - * completed before doing any other operation - */ - wmb(); - - return 0; -} - - -int dp_vco_prepare_14nm(struct clk_hw *hw) -{ - int rc = 0; - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - struct mdss_pll_resources *dp_res = vco->priv; - - pr_debug("rate=%ld\n", vco->rate); - rc = mdss_pll_resource_enable(dp_res, true); - if (rc) { - pr_err("Failed to enable mdss DP pll resources\n"); - goto error; - } - - if ((dp_res->vco_cached_rate != 0) - && (dp_res->vco_cached_rate == vco->rate)) { - rc = vco->hw.init->ops->set_rate(hw, - dp_res->vco_cached_rate, dp_res->vco_cached_rate); - if (rc) { - pr_err("index=%d vco_set_rate failed. rc=%d\n", - rc, dp_res->index); - mdss_pll_resource_enable(dp_res, false); - goto error; - } - } - - rc = dp_pll_enable_14nm(hw); - if (rc) { - mdss_pll_resource_enable(dp_res, false); - pr_err("ndx=%d failed to enable dp pll\n", - dp_res->index); - goto error; - } - - mdss_pll_resource_enable(dp_res, false); -error: - return rc; -} - -void dp_vco_unprepare_14nm(struct clk_hw *hw) -{ - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - struct mdss_pll_resources *dp_res = vco->priv; - - if (!dp_res) { - pr_err("Invalid input parameter\n"); - return; - } - - if (!dp_res->pll_on && - mdss_pll_resource_enable(dp_res, true)) { - pr_err("pll resource can't be enabled\n"); - return; - } - dp_res->vco_cached_rate = vco->rate; - dp_pll_disable_14nm(hw); - - dp_res->handoff_resources = false; - mdss_pll_resource_enable(dp_res, false); - dp_res->pll_on = false; -} - -int dp_vco_set_rate_14nm(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - struct mdss_pll_resources *dp_res = vco->priv; - int rc; - - rc = mdss_pll_resource_enable(dp_res, true); - if (rc) { - pr_err("pll resource can't be enabled\n"); - return rc; - } - - pr_debug("DP lane CLK rate=%ld\n", rate); - - rc = dp_config_vco_rate_14nm(vco, rate); - if (rc) - pr_err("Failed to set clk rate\n"); - - mdss_pll_resource_enable(dp_res, false); - - vco->rate = rate; - - return 0; -} - -unsigned long dp_vco_recalc_rate_14nm(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - int rc; - u32 div, hsclk_div; - u64 vco_rate; - struct mdss_pll_resources *dp_res = vco->priv; - - if (is_gdsc_disabled(dp_res)) - return 0; - - rc = mdss_pll_resource_enable(dp_res, true); - if (rc) { - pr_err("Failed to enable mdss DP pll=%d\n", dp_res->index); - return rc; - } - - div = MDSS_PLL_REG_R(dp_res->pll_base, QSERDES_COM_HSCLK_SEL); - div &= 0x0f; - - if (div == 12) - hsclk_div = 5; /* Default */ - else if (div == 4) - hsclk_div = 3; - else if (div == 0) - hsclk_div = 2; - else { - pr_debug("unknown divider. forcing to default\n"); - hsclk_div = 5; - } - - if (hsclk_div == 5) - vco_rate = DP_VCO_HSCLK_RATE_1620MHZDIV1000; - else if (hsclk_div == 3) - vco_rate = DP_VCO_HSCLK_RATE_2700MHZDIV1000; - else - vco_rate = DP_VCO_HSCLK_RATE_5400MHZDIV1000; - - pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate); - - mdss_pll_resource_enable(dp_res, false); - - dp_res->vco_cached_rate = vco->rate = vco_rate; - return (unsigned long)vco_rate; -} - -long dp_vco_round_rate_14nm(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - unsigned long rrate = rate; - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - - if (rate <= vco->min_rate) - rrate = vco->min_rate; - else if (rate <= DP_VCO_HSCLK_RATE_2700MHZDIV1000) - rrate = DP_VCO_HSCLK_RATE_2700MHZDIV1000; - else - rrate = vco->max_rate; - - pr_debug("rrate=%ld\n", rrate); - - *parent_rate = rrate; - return rrate; -} - -int dp_pll_clock_register_14nm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int rc = -ENOTSUPP, i = 0; - struct clk_onecell_data *clk_data; - struct clk *clk; - struct regmap *regmap; - int num_clks = ARRAY_SIZE(mdss_dp_pllcc_14nm); - - clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL); - if (!clk_data) - return -ENOMEM; - - clk_data->clks = devm_kcalloc(&pdev->dev, num_clks, - sizeof(struct clk *), GFP_KERNEL); - if (!clk_data->clks) - return -ENOMEM; - - clk_data->clk_num = num_clks; - - pll_res->priv = &dp_pdb; - dp_pdb.pll = pll_res; - - /* Set client data for vco, mux and div clocks */ - regmap = devm_regmap_init(&pdev->dev, &dp_pixel_mux_regmap_ops, - pll_res, &dp_pll_14nm_cfg); - dp_phy_pll_vco_div_clk.clkr.regmap = regmap; - mux_clk_ops = clk_regmap_mux_closest_ops; - mux_clk_ops.determine_rate = clk_mux_determine_rate; - mux_clk_ops.recalc_rate = mux_recalc_rate; - - dp_vco_clk.priv = pll_res; - - for (i = DP_VCO_CLK; i <= DP_PHY_PLL_VCO_DIV_CLK; i++) { - pr_debug("reg clk: %d index: %d\n", i, pll_res->index); - clk = devm_clk_register(&pdev->dev, - mdss_dp_pllcc_14nm[i]); - if (IS_ERR(clk)) { - pr_err("clk registration failed for DP: %d\n", - pll_res->index); - rc = -EINVAL; - goto clk_reg_fail; - } - clk_data->clks[i] = clk; - } - - rc = of_clk_add_provider(pdev->dev.of_node, - of_clk_src_onecell_get, clk_data); - if (rc) { - pr_err("Clock register failed rc=%d\n", rc); - rc = -EPROBE_DEFER; - } else { - pr_debug("SUCCESS\n"); - } - return 0; -clk_reg_fail: - return rc; -} diff --git a/drivers/clk/qcom/mdss/mdss-dp-pll-14nm.h b/drivers/clk/qcom/mdss/mdss-dp-pll-14nm.h deleted file mode 100644 index f8c9c3043bdf7311a78f8c0e9d799250a1011bdb..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dp-pll-14nm.h +++ /dev/null @@ -1,188 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. - */ - -#ifndef __MDSS_DP_PLL_14NM_H -#define __MDSS_DP_PLL_14NM_H - -#define DP_PHY_REVISION_ID0 0x0000 -#define DP_PHY_REVISION_ID1 0x0004 -#define DP_PHY_REVISION_ID2 0x0008 -#define DP_PHY_REVISION_ID3 0x000C - -#define DP_PHY_CFG 0x0010 -#define DP_PHY_CFG_1 0x0014 -#define DP_PHY_PD_CTL 0x0018 -#define DP_PHY_MODE 0x001C - -#define DP_PHY_AUX_CFG0 0x0020 -#define DP_PHY_AUX_CFG1 0x0024 -#define DP_PHY_AUX_CFG2 0x0028 -#define DP_PHY_AUX_CFG3 0x002C -#define DP_PHY_AUX_CFG4 0x0030 -#define DP_PHY_AUX_CFG5 0x0034 -#define DP_PHY_AUX_CFG6 0x0038 -#define DP_PHY_AUX_CFG7 0x003C -#define DP_PHY_AUX_CFG8 0x0040 -#define DP_PHY_AUX_CFG9 0x0044 -#define DP_PHY_AUX_INTERRUPT_MASK 0x0048 -#define DP_PHY_AUX_INTERRUPT_CLEAR 0x004C -#define DP_PHY_AUX_BIST_CFG 0x0050 - -#define DP_PHY_VCO_DIV 0x0068 -#define DP_PHY_TX0_TX1_LANE_CTL 0x006C - -#define DP_PHY_TX2_TX3_LANE_CTL 0x0088 -#define DP_PHY_SPARE0 0x00AC -#define DP_PHY_STATUS 0x00C0 - -/* Tx registers */ -#define QSERDES_TX0_OFFSET 0x0400 -#define QSERDES_TX1_OFFSET 0x0800 - -#define TXn_BIST_MODE_LANENO 0x0000 -#define TXn_CLKBUF_ENABLE 0x0008 -#define TXn_TX_EMP_POST1_LVL 0x000C - -#define TXn_TX_DRV_LVL 0x001C - -#define TXn_RESET_TSYNC_EN 0x0024 -#define TXn_PRE_STALL_LDO_BOOST_EN 0x0028 -#define TXn_TX_BAND 0x002C -#define TXn_SLEW_CNTL 0x0030 -#define TXn_INTERFACE_SELECT 0x0034 - -#define TXn_RES_CODE_LANE_TX 0x003C -#define TXn_RES_CODE_LANE_RX 0x0040 -#define TXn_RES_CODE_LANE_OFFSET_TX 0x0044 -#define TXn_RES_CODE_LANE_OFFSET_RX 0x0048 - -#define TXn_DEBUG_BUS_SEL 0x0058 -#define TXn_TRANSCEIVER_BIAS_EN 0x005C -#define TXn_HIGHZ_DRVR_EN 0x0060 -#define TXn_TX_POL_INV 0x0064 -#define TXn_PARRATE_REC_DETECT_IDLE_EN 0x0068 - -#define TXn_LANE_MODE_1 0x008C - -#define TXn_TRAN_DRVR_EMP_EN 0x00C0 -#define TXn_TX_INTERFACE_MODE 0x00C4 - -#define TXn_VMODE_CTRL1 0x00F0 - - -/* PLL register offset */ -#define QSERDES_COM_ATB_SEL1 0x0000 -#define QSERDES_COM_ATB_SEL2 0x0004 -#define QSERDES_COM_FREQ_UPDATE 0x0008 -#define QSERDES_COM_BG_TIMER 0x000C -#define QSERDES_COM_SSC_EN_CENTER 0x0010 -#define QSERDES_COM_SSC_ADJ_PER1 0x0014 -#define QSERDES_COM_SSC_ADJ_PER2 0x0018 -#define QSERDES_COM_SSC_PER1 0x001C -#define QSERDES_COM_SSC_PER2 0x0020 -#define QSERDES_COM_SSC_STEP_SIZE1 0x0024 -#define QSERDES_COM_SSC_STEP_SIZE2 0x0028 -#define QSERDES_COM_POST_DIV 0x002C -#define QSERDES_COM_POST_DIV_MUX 0x0030 -#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN 0x0034 -#define QSERDES_COM_CLK_ENABLE1 0x0038 -#define QSERDES_COM_SYS_CLK_CTRL 0x003C -#define QSERDES_COM_SYSCLK_BUF_ENABLE 0x0040 -#define QSERDES_COM_PLL_EN 0x0044 -#define QSERDES_COM_PLL_IVCO 0x0048 -#define QSERDES_COM_LOCK_CMP1_MODE0 0x004C -#define QSERDES_COM_LOCK_CMP2_MODE0 0x0050 -#define QSERDES_COM_LOCK_CMP3_MODE0 0x0054 - -#define QSERDES_COM_CP_CTRL_MODE0 0x0078 -#define QSERDES_COM_CP_CTRL_MODE1 0x007C -#define QSERDES_COM_PLL_RCTRL_MODE0 0x0084 -#define QSERDES_COM_PLL_CCTRL_MODE0 0x0090 -#define QSERDES_COM_PLL_CNTRL 0x009C - -#define QSERDES_COM_SYSCLK_EN_SEL 0x00AC -#define QSERDES_COM_CML_SYSCLK_SEL 0x00B0 -#define QSERDES_COM_RESETSM_CNTRL 0x00B4 -#define QSERDES_COM_RESETSM_CNTRL2 0x00B8 -#define QSERDES_COM_LOCK_CMP_EN 0x00C8 -#define QSERDES_COM_LOCK_CMP_CFG 0x00CC - - -#define QSERDES_COM_DEC_START_MODE0 0x00D0 -#define QSERDES_COM_DEC_START_MODE1 0x00D4 -#define QSERDES_COM_DIV_FRAC_START1_MODE0 0x00DC -#define QSERDES_COM_DIV_FRAC_START2_MODE0 0x00E0 -#define QSERDES_COM_DIV_FRAC_START3_MODE0 0x00E4 - -#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0 0x0108 -#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0 0x010C -#define QSERDES_COM_VCO_TUNE_CTRL 0x0124 -#define QSERDES_COM_VCO_TUNE_MAP 0x0128 -#define QSERDES_COM_VCO_TUNE1_MODE0 0x012C -#define QSERDES_COM_VCO_TUNE2_MODE0 0x0130 - -#define QSERDES_COM_CMN_STATUS 0x015C -#define QSERDES_COM_RESET_SM_STATUS 0x0160 - -#define QSERDES_COM_BG_CTRL 0x0170 -#define QSERDES_COM_CLK_SELECT 0x0174 -#define QSERDES_COM_HSCLK_SEL 0x0178 -#define QSERDES_COM_CORECLK_DIV 0x0184 -#define QSERDES_COM_SW_RESET 0x0188 -#define QSERDES_COM_CORE_CLK_EN 0x018C -#define QSERDES_COM_C_READY_STATUS 0x0190 -#define QSERDES_COM_CMN_CONFIG 0x0194 -#define QSERDES_COM_SVS_MODE_CLK_SEL 0x019C - -#define DP_PLL_POLL_SLEEP_US 500 -#define DP_PLL_POLL_TIMEOUT_US 10000 - -#define DP_PHY_POLL_SLEEP_US 500 -#define DP_PHY_POLL_TIMEOUT_US 10000 - -#define DP_VCO_RATE_8100MHZDIV1000 8100000UL -#define DP_VCO_RATE_10800MHZDIV1000 10800000UL - -#define DP_VCO_HSCLK_RATE_1620MHZDIV1000 1620000UL -#define DP_VCO_HSCLK_RATE_2700MHZDIV1000 2700000UL -#define DP_VCO_HSCLK_RATE_5400MHZDIV1000 5400000UL - -struct dp_pll_db { - struct mdss_pll_resources *pll; - - /* lane and orientation settings */ - u8 lane_cnt; - u8 orientation; - - /* COM PHY settings */ - u32 hsclk_sel; - u32 dec_start_mode0; - u32 div_frac_start1_mode0; - u32 div_frac_start2_mode0; - u32 div_frac_start3_mode0; - u32 lock_cmp1_mode0; - u32 lock_cmp2_mode0; - u32 lock_cmp3_mode0; - - /* PHY vco divider */ - u32 phy_vco_div; - - /* TX settings */ - u32 lane_mode_1; -}; - -int dp_vco_set_rate_14nm(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate); -unsigned long dp_vco_recalc_rate_14nm(struct clk_hw *hw, - unsigned long parent_rate); -long dp_vco_round_rate_14nm(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate); -int dp_vco_prepare_14nm(struct clk_hw *hw); -void dp_vco_unprepare_14nm(struct clk_hw *hw); -int dp_mux_set_parent_14nm(void *context, - unsigned int reg, unsigned int val); -int dp_mux_get_parent_14nm(void *context, - unsigned int reg, unsigned int *val); -#endif /* __MDSS_DP_PLL_14NM_H */ diff --git a/drivers/clk/qcom/mdss/mdss-dp-pll-7nm-util.c b/drivers/clk/qcom/mdss/mdss-dp-pll-7nm-util.c deleted file mode 100644 index a91e0eb995c680552188097afe9b41e3e8fdc93b..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dp-pll-7nm-util.c +++ /dev/null @@ -1,733 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[dp-pll] %s: " fmt, __func__ - -#include -#include -#include -#include -#include - -#include "mdss-pll.h" -#include "mdss-dp-pll.h" -#include "mdss-dp-pll-7nm.h" - -#define DP_PHY_CFG 0x0010 -#define DP_PHY_PD_CTL 0x0018 -#define DP_PHY_MODE 0x001C - -#define DP_PHY_AUX_CFG1 0x0024 -#define DP_PHY_AUX_CFG2 0x0028 - -#define DP_PHY_VCO_DIV 0x0070 -#define DP_PHY_TX0_TX1_LANE_CTL 0x0078 -#define DP_PHY_TX2_TX3_LANE_CTL 0x009C - -#define DP_PHY_SPARE0 0x00C8 -#define DP_PHY_STATUS 0x00DC - -/* Tx registers */ -#define TXn_CLKBUF_ENABLE 0x0008 -#define TXn_TX_EMP_POST1_LVL 0x000C - -#define TXn_TX_DRV_LVL 0x0014 - -#define TXn_RESET_TSYNC_EN 0x001C -#define TXn_PRE_STALL_LDO_BOOST_EN 0x0020 -#define TXn_TX_BAND 0x0024 -#define TXn_INTERFACE_SELECT 0x002C - -#define TXn_RES_CODE_LANE_OFFSET_TX 0x003C -#define TXn_RES_CODE_LANE_OFFSET_RX 0x0040 - -#define TXn_TRANSCEIVER_BIAS_EN 0x0054 -#define TXn_HIGHZ_DRVR_EN 0x0058 -#define TXn_TX_POL_INV 0x005C -#define TXn_PARRATE_REC_DETECT_IDLE_EN 0x0060 - -#define TXn_TRAN_DRVR_EMP_EN 0x00B8 -#define TXn_TX_INTERFACE_MODE 0x00BC - -#define TXn_VMODE_CTRL1 0x00E8 - -/* PLL register offset */ -#define QSERDES_COM_BG_TIMER 0x000C -#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN 0x0044 -#define QSERDES_COM_CLK_ENABLE1 0x0048 -#define QSERDES_COM_SYS_CLK_CTRL 0x004C -#define QSERDES_COM_SYSCLK_BUF_ENABLE 0x0050 -#define QSERDES_COM_PLL_IVCO 0x0058 - -#define QSERDES_COM_CP_CTRL_MODE0 0x0074 -#define QSERDES_COM_PLL_RCTRL_MODE0 0x007C -#define QSERDES_COM_PLL_CCTRL_MODE0 0x0084 -#define QSERDES_COM_SYSCLK_EN_SEL 0x0094 -#define QSERDES_COM_RESETSM_CNTRL 0x009C -#define QSERDES_COM_LOCK_CMP_EN 0x00A4 -#define QSERDES_COM_LOCK_CMP1_MODE0 0x00AC -#define QSERDES_COM_LOCK_CMP2_MODE0 0x00B0 - -#define QSERDES_COM_DEC_START_MODE0 0x00BC -#define QSERDES_COM_DIV_FRAC_START1_MODE0 0x00CC -#define QSERDES_COM_DIV_FRAC_START2_MODE0 0x00D0 -#define QSERDES_COM_DIV_FRAC_START3_MODE0 0x00D4 -#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0 0x00EC -#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0 0x00F0 -#define QSERDES_COM_VCO_TUNE_CTRL 0x0108 -#define QSERDES_COM_VCO_TUNE_MAP 0x010C - -#define QSERDES_COM_CLK_SEL 0x0154 -#define QSERDES_COM_HSCLK_SEL 0x0158 - -#define QSERDES_COM_CORECLK_DIV_MODE0 0x0168 - -#define QSERDES_COM_CORE_CLK_EN 0x0174 -#define QSERDES_COM_C_READY_STATUS 0x0178 -#define QSERDES_COM_CMN_CONFIG 0x017C - -#define QSERDES_COM_SVS_MODE_CLK_SEL 0x0184 - -#define DP_PHY_PLL_POLL_SLEEP_US 500 -#define DP_PHY_PLL_POLL_TIMEOUT_US 10000 - -#define DP_VCO_RATE_8100MHZDIV1000 8100000UL -#define DP_VCO_RATE_9720MHZDIV1000 9720000UL -#define DP_VCO_RATE_10800MHZDIV1000 10800000UL - -int dp_mux_set_parent_7nm(void *context, unsigned int reg, unsigned int val) -{ - struct mdss_pll_resources *dp_res = context; - int rc; - u32 auxclk_div; - - if (!context) { - pr_err("invalid input parameters\n"); - return -EINVAL; - } - - rc = mdss_pll_resource_enable(dp_res, true); - if (rc) { - pr_err("Failed to enable mdss DP PLL resources\n"); - return rc; - } - - auxclk_div = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_VCO_DIV); - auxclk_div &= ~0x03; - - if (val == 0) - auxclk_div |= 1; - else if (val == 1) - auxclk_div |= 2; - else if (val == 2) - auxclk_div |= 0; - - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_VCO_DIV, auxclk_div); - /* Make sure the PHY registers writes are done */ - wmb(); - pr_debug("mux=%d auxclk_div=%x\n", val, auxclk_div); - - mdss_pll_resource_enable(dp_res, false); - - return 0; -} - -int dp_mux_get_parent_7nm(void *context, unsigned int reg, unsigned int *val) -{ - int rc; - u32 auxclk_div = 0; - struct mdss_pll_resources *dp_res = context; - - if (!context || !val) { - pr_err("invalid input parameters\n"); - return -EINVAL; - } - - if (is_gdsc_disabled(dp_res)) - return 0; - - rc = mdss_pll_resource_enable(dp_res, true); - if (rc) { - pr_err("Failed to enable dp_res resources\n"); - return rc; - } - - auxclk_div = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_VCO_DIV); - auxclk_div &= 0x03; - - if (auxclk_div == 1) /* Default divider */ - *val = 0; - else if (auxclk_div == 2) - *val = 1; - else if (auxclk_div == 0) - *val = 2; - - mdss_pll_resource_enable(dp_res, false); - - pr_debug("auxclk_div=%d, val=%d\n", auxclk_div, *val); - - return 0; -} - -static int dp_vco_pll_init_db_7nm(struct dp_pll_db_7nm *pdb, - unsigned long rate) -{ - struct mdss_pll_resources *dp_res = pdb->pll; - u32 spare_value = 0; - - spare_value = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_SPARE0); - pdb->lane_cnt = spare_value & 0x0F; - pdb->orientation = (spare_value & 0xF0) >> 4; - - pr_debug("spare_value=0x%x, ln_cnt=0x%x, orientation=0x%x\n", - spare_value, pdb->lane_cnt, pdb->orientation); - - pdb->div_frac_start1_mode0 = 0x00; - pdb->integloop_gain0_mode0 = 0x3f; - pdb->integloop_gain1_mode0 = 0x00; - pdb->vco_tune_map = 0x00; - pdb->cmn_config = 0x02; - pdb->txn_tran_drv_emp_en = 0xf; - - switch (rate) { - case DP_VCO_HSCLK_RATE_1620MHZDIV1000: - pr_debug("VCO rate: %ld\n", DP_VCO_RATE_9720MHZDIV1000); - pdb->hsclk_sel = 0x05; - pdb->dec_start_mode0 = 0x69; - pdb->div_frac_start2_mode0 = 0x80; - pdb->div_frac_start3_mode0 = 0x07; - pdb->lock_cmp1_mode0 = 0x6f; - pdb->lock_cmp2_mode0 = 0x08; - pdb->phy_vco_div = 0x1; - pdb->lock_cmp_en = 0x04; - break; - case DP_VCO_HSCLK_RATE_2700MHZDIV1000: - pr_debug("VCO rate: %ld\n", DP_VCO_RATE_10800MHZDIV1000); - pdb->hsclk_sel = 0x03; - pdb->dec_start_mode0 = 0x69; - pdb->div_frac_start2_mode0 = 0x80; - pdb->div_frac_start3_mode0 = 0x07; - pdb->lock_cmp1_mode0 = 0x0f; - pdb->lock_cmp2_mode0 = 0x0e; - pdb->phy_vco_div = 0x1; - pdb->lock_cmp_en = 0x08; - break; - case DP_VCO_HSCLK_RATE_5400MHZDIV1000: - pr_debug("VCO rate: %ld\n", DP_VCO_RATE_10800MHZDIV1000); - pdb->hsclk_sel = 0x01; - pdb->dec_start_mode0 = 0x8c; - pdb->div_frac_start2_mode0 = 0x00; - pdb->div_frac_start3_mode0 = 0x0a; - pdb->lock_cmp1_mode0 = 0x1f; - pdb->lock_cmp2_mode0 = 0x1c; - pdb->phy_vco_div = 0x2; - pdb->lock_cmp_en = 0x08; - break; - case DP_VCO_HSCLK_RATE_8100MHZDIV1000: - pr_debug("VCO rate: %ld\n", DP_VCO_RATE_8100MHZDIV1000); - pdb->hsclk_sel = 0x00; - pdb->dec_start_mode0 = 0x69; - pdb->div_frac_start2_mode0 = 0x80; - pdb->div_frac_start3_mode0 = 0x07; - pdb->lock_cmp1_mode0 = 0x2f; - pdb->lock_cmp2_mode0 = 0x2a; - pdb->phy_vco_div = 0x0; - pdb->lock_cmp_en = 0x08; - break; - default: - pr_err("unsupported rate %ld\n", rate); - return -EINVAL; - } - return 0; -} - -static int dp_config_vco_rate_7nm(struct dp_pll_vco_clk *vco, - unsigned long rate) -{ - u32 res = 0; - struct mdss_pll_resources *dp_res = vco->priv; - struct dp_pll_db_7nm *pdb = (struct dp_pll_db_7nm *)dp_res->priv; - - res = dp_vco_pll_init_db_7nm(pdb, rate); - if (res) { - pr_err("VCO Init DB failed\n"); - return res; - } - - if (pdb->lane_cnt != 4) { - if (pdb->orientation == ORIENTATION_CC2) - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_PD_CTL, 0x6d); - else - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_PD_CTL, 0x75); - } else { - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_PD_CTL, 0x7d); - } - - /* Make sure the PHY register writes are done */ - wmb(); - - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_SVS_MODE_CLK_SEL, 0x05); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_SYSCLK_EN_SEL, 0x3b); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_SYS_CLK_CTRL, 0x02); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CLK_ENABLE1, 0x0c); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_SYSCLK_BUF_ENABLE, 0x06); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CLK_SEL, 0x30); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_HSCLK_SEL, pdb->hsclk_sel); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_PLL_IVCO, 0x0f); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_LOCK_CMP_EN, pdb->lock_cmp_en); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_PLL_CCTRL_MODE0, 0x36); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_PLL_RCTRL_MODE0, 0x16); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CP_CTRL_MODE0, 0x06); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_DEC_START_MODE0, pdb->dec_start_mode0); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_DIV_FRAC_START1_MODE0, pdb->div_frac_start1_mode0); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_DIV_FRAC_START2_MODE0, pdb->div_frac_start2_mode0); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_DIV_FRAC_START3_MODE0, pdb->div_frac_start3_mode0); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_CMN_CONFIG, pdb->cmn_config); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_INTEGLOOP_GAIN0_MODE0, pdb->integloop_gain0_mode0); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_INTEGLOOP_GAIN1_MODE0, pdb->integloop_gain1_mode0); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_VCO_TUNE_MAP, pdb->vco_tune_map); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_LOCK_CMP1_MODE0, pdb->lock_cmp1_mode0); - MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_LOCK_CMP2_MODE0, pdb->lock_cmp2_mode0); - /* Make sure the PLL register writes are done */ - wmb(); - - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_BG_TIMER, 0x0a); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CORECLK_DIV_MODE0, 0x0a); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_VCO_TUNE_CTRL, 0x00); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x17); - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CORE_CLK_EN, 0x1f); - /* Make sure the PHY register writes are done */ - wmb(); - - if (pdb->orientation == ORIENTATION_CC2) - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_MODE, 0x4c); - else - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_MODE, 0x5c); - /* Make sure the PLL register writes are done */ - wmb(); - - /* TX Lane configuration */ - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_TX0_TX1_LANE_CTL, 0x05); - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_TX2_TX3_LANE_CTL, 0x05); - - /* TX-0 register configuration */ - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_TRANSCEIVER_BIAS_EN, 0x1a); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_VMODE_CTRL1, 0x40); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_PRE_STALL_LDO_BOOST_EN, 0x30); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_INTERFACE_SELECT, 0x3b); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_CLKBUF_ENABLE, 0x0f); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_RESET_TSYNC_EN, 0x03); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_TRAN_DRVR_EMP_EN, - pdb->txn_tran_drv_emp_en); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, - TXn_PARRATE_REC_DETECT_IDLE_EN, 0x00); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_TX_INTERFACE_MODE, 0x00); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_TX_BAND, 0x4); - - /* TX-1 register configuration */ - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_TRANSCEIVER_BIAS_EN, 0x1a); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_VMODE_CTRL1, 0x40); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_PRE_STALL_LDO_BOOST_EN, 0x30); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_INTERFACE_SELECT, 0x3b); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_CLKBUF_ENABLE, 0x0f); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_RESET_TSYNC_EN, 0x03); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_TRAN_DRVR_EMP_EN, - pdb->txn_tran_drv_emp_en); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, - TXn_PARRATE_REC_DETECT_IDLE_EN, 0x00); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_TX_INTERFACE_MODE, 0x00); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_TX_BAND, 0x4); - /* Make sure the PHY register writes are done */ - wmb(); - - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_VCO_DIV, pdb->phy_vco_div); - - return res; -} - -static bool dp_7nm_pll_lock_status(struct mdss_pll_resources *dp_res) -{ - u32 status; - bool pll_locked; - - if (readl_poll_timeout_atomic((dp_res->pll_base + - QSERDES_COM_C_READY_STATUS), - status, - ((status & BIT(0)) > 0), - DP_PHY_PLL_POLL_SLEEP_US, - DP_PHY_PLL_POLL_TIMEOUT_US)) { - pr_err("C_READY status is not high. Status=%x\n", status); - pll_locked = false; - } else { - pll_locked = true; - } - - return pll_locked; -} - -static bool dp_7nm_phy_rdy_status(struct mdss_pll_resources *dp_res) -{ - u32 status; - bool phy_ready = true; - - /* poll for PHY ready status */ - if (readl_poll_timeout_atomic((dp_res->phy_base + - DP_PHY_STATUS), - status, - ((status & (BIT(1))) > 0), - DP_PHY_PLL_POLL_SLEEP_US, - DP_PHY_PLL_POLL_TIMEOUT_US)) { - pr_err("Phy_ready is not high. Status=%x\n", status); - phy_ready = false; - } - - return phy_ready; -} - -static int dp_pll_enable_7nm(struct clk_hw *hw) -{ - int rc = 0; - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - struct mdss_pll_resources *dp_res = vco->priv; - struct dp_pll_db_7nm *pdb = (struct dp_pll_db_7nm *)dp_res->priv; - u32 bias_en, drvr_en; - - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_AUX_CFG1, 0x13); - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_AUX_CFG2, 0xA4); - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x01); - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x05); - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x01); - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x09); - wmb(); /* Make sure the PHY register writes are done */ - - MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_RESETSM_CNTRL, 0x20); - wmb(); /* Make sure the PLL register writes are done */ - - if (!dp_7nm_pll_lock_status(dp_res)) { - rc = -EINVAL; - goto lock_err; - } - - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x19); - /* Make sure the PHY register writes are done */ - wmb(); - /* poll for PHY ready status */ - if (!dp_7nm_phy_rdy_status(dp_res)) { - rc = -EINVAL; - goto lock_err; - } - - pr_debug("PLL is locked\n"); - - if (pdb->lane_cnt == 1) { - bias_en = 0x3e; - drvr_en = 0x13; - } else { - bias_en = 0x3f; - drvr_en = 0x10; - } - - if (pdb->lane_cnt != 4) { - if (pdb->orientation == ORIENTATION_CC1) { - MDSS_PLL_REG_W(dp_res->ln_tx1_base, - TXn_HIGHZ_DRVR_EN, drvr_en); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, - TXn_TRANSCEIVER_BIAS_EN, bias_en); - } else { - MDSS_PLL_REG_W(dp_res->ln_tx0_base, - TXn_HIGHZ_DRVR_EN, drvr_en); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, - TXn_TRANSCEIVER_BIAS_EN, bias_en); - } - } else { - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_HIGHZ_DRVR_EN, drvr_en); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, - TXn_TRANSCEIVER_BIAS_EN, bias_en); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_HIGHZ_DRVR_EN, drvr_en); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, - TXn_TRANSCEIVER_BIAS_EN, bias_en); - } - - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_TX_POL_INV, 0x0a); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_TX_POL_INV, 0x0a); - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x18); - udelay(2000); - - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x19); - - /* - * Make sure all the register writes are completed before - * doing any other operation - */ - wmb(); - - /* poll for PHY ready status */ - if (!dp_7nm_phy_rdy_status(dp_res)) { - rc = -EINVAL; - goto lock_err; - } - - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_TX_DRV_LVL, 0x3f); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_TX_DRV_LVL, 0x3f); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_TX_EMP_POST1_LVL, 0x23); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_TX_EMP_POST1_LVL, 0x23); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_RES_CODE_LANE_OFFSET_TX, 0x11); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_RES_CODE_LANE_OFFSET_TX, 0x11); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_RES_CODE_LANE_OFFSET_RX, 0x11); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_RES_CODE_LANE_OFFSET_RX, 0x11); - MDSS_PLL_REG_W(dp_res->ln_tx0_base, TXn_INTERFACE_SELECT, 0x3b); - MDSS_PLL_REG_W(dp_res->ln_tx1_base, TXn_INTERFACE_SELECT, 0x3b); - /* Make sure the PHY register writes are done */ - wmb(); - -lock_err: - return rc; -} - -static int dp_pll_disable_7nm(struct clk_hw *hw) -{ - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - struct mdss_pll_resources *dp_res = vco->priv; - - /* Assert DP PHY power down */ - MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_PD_CTL, 0x2); - /* - * Make sure all the register writes to disable PLL are - * completed before doing any other operation - */ - wmb(); - - return 0; -} - -int dp_vco_prepare_7nm(struct clk_hw *hw) -{ - int rc = 0; - struct dp_pll_vco_clk *vco; - struct mdss_pll_resources *dp_res; - - if (!hw) { - pr_err("invalid input parameters\n"); - return -EINVAL; - } - - vco = to_dp_vco_hw(hw); - dp_res = vco->priv; - - pr_debug("rate=%ld\n", vco->rate); - rc = mdss_pll_resource_enable(dp_res, true); - if (rc) { - pr_err("Failed to enable mdss DP pll resources\n"); - goto error; - } - - if ((dp_res->vco_cached_rate != 0) - && (dp_res->vco_cached_rate == vco->rate)) { - rc = vco->hw.init->ops->set_rate(hw, - dp_res->vco_cached_rate, dp_res->vco_cached_rate); - if (rc) { - pr_err("index=%d vco_set_rate failed. rc=%d\n", - rc, dp_res->index); - mdss_pll_resource_enable(dp_res, false); - goto error; - } - } - - rc = dp_pll_enable_7nm(hw); - if (rc) { - mdss_pll_resource_enable(dp_res, false); - pr_err("ndx=%d failed to enable dp pll\n", dp_res->index); - goto error; - } - - mdss_pll_resource_enable(dp_res, false); -error: - return rc; -} - -void dp_vco_unprepare_7nm(struct clk_hw *hw) -{ - struct dp_pll_vco_clk *vco; - struct mdss_pll_resources *dp_res; - - if (!hw) { - pr_err("invalid input parameters\n"); - return; - } - - vco = to_dp_vco_hw(hw); - dp_res = vco->priv; - - if (!dp_res) { - pr_err("invalid input parameter\n"); - return; - } - - if (!dp_res->pll_on && - mdss_pll_resource_enable(dp_res, true)) { - pr_err("pll resource can't be enabled\n"); - return; - } - dp_res->vco_cached_rate = vco->rate; - dp_pll_disable_7nm(hw); - - dp_res->handoff_resources = false; - mdss_pll_resource_enable(dp_res, false); - dp_res->pll_on = false; -} - -int dp_vco_set_rate_7nm(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct dp_pll_vco_clk *vco; - struct mdss_pll_resources *dp_res; - int rc; - - if (!hw) { - pr_err("invalid input parameters\n"); - return -EINVAL; - } - - vco = to_dp_vco_hw(hw); - dp_res = vco->priv; - - rc = mdss_pll_resource_enable(dp_res, true); - if (rc) { - pr_err("pll resource can't be enabled\n"); - return rc; - } - - pr_debug("DP lane CLK rate=%ld\n", rate); - - rc = dp_config_vco_rate_7nm(vco, rate); - if (rc) - pr_err("Failed to set clk rate\n"); - - mdss_pll_resource_enable(dp_res, false); - - vco->rate = rate; - - return 0; -} - -unsigned long dp_vco_recalc_rate_7nm(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct dp_pll_vco_clk *vco; - int rc; - u32 hsclk_sel, link_clk_divsel, hsclk_div, link_clk_div = 0; - unsigned long vco_rate; - struct mdss_pll_resources *dp_res; - - if (!hw) { - pr_err("invalid input parameters\n"); - return 0; - } - - vco = to_dp_vco_hw(hw); - dp_res = vco->priv; - - if (is_gdsc_disabled(dp_res)) - return 0; - - rc = mdss_pll_resource_enable(dp_res, true); - if (rc) { - pr_err("Failed to enable mdss DP pll=%d\n", dp_res->index); - return 0; - } - - pr_debug("input rates: parent=%lu, vco=%lu\n", parent_rate, vco->rate); - - hsclk_sel = MDSS_PLL_REG_R(dp_res->pll_base, QSERDES_COM_HSCLK_SEL); - hsclk_sel &= 0x0f; - - if (hsclk_sel == 5) - hsclk_div = 5; - else if (hsclk_sel == 3) - hsclk_div = 3; - else if (hsclk_sel == 1) - hsclk_div = 2; - else if (hsclk_sel == 0) - hsclk_div = 1; - else { - pr_debug("unknown divider. forcing to default\n"); - hsclk_div = 5; - } - - link_clk_divsel = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_AUX_CFG2); - link_clk_divsel >>= 2; - link_clk_divsel &= 0x3; - - if (link_clk_divsel == 0) - link_clk_div = 5; - else if (link_clk_divsel == 1) - link_clk_div = 10; - else if (link_clk_divsel == 2) - link_clk_div = 20; - else - pr_err("unsupported div. Phy_mode: %d\n", link_clk_divsel); - - if (link_clk_div == 20) { - vco_rate = DP_VCO_HSCLK_RATE_2700MHZDIV1000; - } else { - if (hsclk_div == 5) - vco_rate = DP_VCO_HSCLK_RATE_1620MHZDIV1000; - else if (hsclk_div == 3) - vco_rate = DP_VCO_HSCLK_RATE_2700MHZDIV1000; - else if (hsclk_div == 2) - vco_rate = DP_VCO_HSCLK_RATE_5400MHZDIV1000; - else - vco_rate = DP_VCO_HSCLK_RATE_8100MHZDIV1000; - } - - pr_debug("hsclk: sel=0x%x, div=0x%x; lclk: sel=%u, div=%u, rate=%lu\n", - hsclk_sel, hsclk_div, link_clk_divsel, link_clk_div, vco_rate); - - mdss_pll_resource_enable(dp_res, false); - - dp_res->vco_cached_rate = vco->rate = vco_rate; - return vco_rate; -} - -long dp_vco_round_rate_7nm(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - unsigned long rrate = rate; - struct dp_pll_vco_clk *vco; - - if (!hw) { - pr_err("invalid input parameters\n"); - return 0; - } - - vco = to_dp_vco_hw(hw); - if (rate <= vco->min_rate) - rrate = vco->min_rate; - else if (rate <= DP_VCO_HSCLK_RATE_2700MHZDIV1000) - rrate = DP_VCO_HSCLK_RATE_2700MHZDIV1000; - else if (rate <= DP_VCO_HSCLK_RATE_5400MHZDIV1000) - rrate = DP_VCO_HSCLK_RATE_5400MHZDIV1000; - else - rrate = vco->max_rate; - - pr_debug("rrate=%ld\n", rrate); - - if (parent_rate) - *parent_rate = rrate; - return rrate; -} - diff --git a/drivers/clk/qcom/mdss/mdss-dp-pll-7nm.c b/drivers/clk/qcom/mdss/mdss-dp-pll-7nm.c deleted file mode 100644 index 29fcdf978b8a70a1bb465f383e4558a71f3a4382..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dp-pll-7nm.c +++ /dev/null @@ -1,297 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. - */ - -/* - * Display Port PLL driver block diagram for branch clocks - * - * +------------------------------+ - * | DP_VCO_CLK | - * | | - * | +-------------------+ | - * | | (DP PLL/VCO) | | - * | +---------+---------+ | - * | v | - * | +----------+-----------+ | - * | | hsclk_divsel_clk_src | | - * | +----------+-----------+ | - * +------------------------------+ - * | - * +------------<---------v------------>----------+ - * | | - * +-----v------------+ | - * | dp_link_clk_src | | - * | divsel_ten | | - * +---------+--------+ | - * | | - * | | - * v v - * Input to DISPCC block | - * for link clk, crypto clk | - * and interface clock | - * | - * | - * +--------<------------+-----------------+---<---+ - * | | | - * +-------v------+ +--------v-----+ +--------v------+ - * | vco_divided | | vco_divided | | vco_divided | - * | _clk_src | | _clk_src | | _clk_src | - * | | | | | | - * |divsel_six | | divsel_two | | divsel_four | - * +-------+------+ +-----+--------+ +--------+------+ - * | | | - * v------->----------v-------------<------v - * | - * +----------+---------+ - * | vco_divided_clk | - * | _src_mux | - * +---------+----------+ - * | - * v - * Input to DISPCC block - * for DP pixel clock - * - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include - -#include "mdss-pll.h" -#include "mdss-dp-pll.h" -#include "mdss-dp-pll-7nm.h" - -static struct dp_pll_db_7nm dp_pdb_7nm; -static struct clk_ops mux_clk_ops; - -static struct regmap_config dp_pll_7nm_cfg = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x910, -}; - -static struct regmap_bus dp_pixel_mux_regmap_ops = { - .reg_write = dp_mux_set_parent_7nm, - .reg_read = dp_mux_get_parent_7nm, -}; - -/* Op structures */ -static const struct clk_ops dp_7nm_vco_clk_ops = { - .recalc_rate = dp_vco_recalc_rate_7nm, - .set_rate = dp_vco_set_rate_7nm, - .round_rate = dp_vco_round_rate_7nm, - .prepare = dp_vco_prepare_7nm, - .unprepare = dp_vco_unprepare_7nm, -}; - -static struct dp_pll_vco_clk dp_vco_clk = { - .min_rate = DP_VCO_HSCLK_RATE_1620MHZDIV1000, - .max_rate = DP_VCO_HSCLK_RATE_8100MHZDIV1000, - .hw.init = &(struct clk_init_data){ - .name = "dp_vco_clk", - .parent_names = (const char *[]){ "xo_board" }, - .num_parents = 1, - .ops = &dp_7nm_vco_clk_ops, - }, -}; - -static struct clk_fixed_factor dp_link_clk_divsel_ten = { - .div = 10, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "dp_link_clk_divsel_ten", - .parent_names = - (const char *[]){ "dp_vco_clk" }, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dp_vco_divsel_two_clk_src = { - .div = 2, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "dp_vco_divsel_two_clk_src", - .parent_names = - (const char *[]){ "dp_vco_clk" }, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dp_vco_divsel_four_clk_src = { - .div = 4, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "dp_vco_divsel_four_clk_src", - .parent_names = - (const char *[]){ "dp_vco_clk" }, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dp_vco_divsel_six_clk_src = { - .div = 6, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "dp_vco_divsel_six_clk_src", - .parent_names = - (const char *[]){ "dp_vco_clk" }, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE), - .ops = &clk_fixed_factor_ops, - }, -}; - - -static int clk_mux_determine_rate(struct clk_hw *hw, - struct clk_rate_request *req) -{ - int ret = 0; - - if (!hw || !req) { - pr_err("Invalid input parameters\n"); - return -EINVAL; - } - - ret = __clk_mux_determine_rate_closest(hw, req); - if (ret) - return ret; - - /* Set the new parent of mux if there is a new valid parent */ - if (hw->clk && req->best_parent_hw->clk) - clk_set_parent(hw->clk, req->best_parent_hw->clk); - - return 0; -} - -static unsigned long mux_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk *div_clk = NULL, *vco_clk = NULL; - struct dp_pll_vco_clk *vco = NULL; - - if (!hw) { - pr_err("Invalid input parameter\n"); - return 0; - } - - div_clk = clk_get_parent(hw->clk); - if (!div_clk) - return 0; - - vco_clk = clk_get_parent(div_clk); - if (!vco_clk) - return 0; - - vco = to_dp_vco_hw(__clk_get_hw(vco_clk)); - if (!vco) - return 0; - - if (vco->rate == DP_VCO_HSCLK_RATE_8100MHZDIV1000) - return (vco->rate / 6); - else if (vco->rate == DP_VCO_HSCLK_RATE_5400MHZDIV1000) - return (vco->rate / 4); - else - return (vco->rate / 2); -} - -static struct clk_regmap_mux dp_vco_divided_clk_src_mux = { - .reg = 0x64, - .shift = 0, - .width = 2, - - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dp_vco_divided_clk_src_mux", - .parent_names = - (const char *[]){"dp_vco_divsel_two_clk_src", - "dp_vco_divsel_four_clk_src", - "dp_vco_divsel_six_clk_src"}, - .num_parents = 3, - .ops = &mux_clk_ops, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - }, - }, -}; - -static struct clk_hw *mdss_dp_pllcc_7nm[] = { - [DP_VCO_CLK] = &dp_vco_clk.hw, - [DP_LINK_CLK_DIVSEL_TEN] = &dp_link_clk_divsel_ten.hw, - [DP_VCO_DIVIDED_TWO_CLK_SRC] = &dp_vco_divsel_two_clk_src.hw, - [DP_VCO_DIVIDED_FOUR_CLK_SRC] = &dp_vco_divsel_four_clk_src.hw, - [DP_VCO_DIVIDED_SIX_CLK_SRC] = &dp_vco_divsel_six_clk_src.hw, - [DP_VCO_DIVIDED_CLK_SRC_MUX] = &dp_vco_divided_clk_src_mux.clkr.hw, -}; - -int dp_pll_clock_register_7nm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int rc = -ENOTSUPP, i = 0; - struct clk_onecell_data *clk_data; - struct clk *clk; - struct regmap *regmap; - int num_clks = ARRAY_SIZE(mdss_dp_pllcc_7nm); - - clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL); - if (!clk_data) - return -ENOMEM; - - clk_data->clks = devm_kcalloc(&pdev->dev, num_clks, - sizeof(struct clk *), GFP_KERNEL); - if (!clk_data->clks) - return -ENOMEM; - - clk_data->clk_num = num_clks; - - pll_res->priv = &dp_pdb_7nm; - dp_pdb_7nm.pll = pll_res; - - /* Set client data for vco, mux and div clocks */ - regmap = devm_regmap_init(&pdev->dev, &dp_pixel_mux_regmap_ops, - pll_res, &dp_pll_7nm_cfg); - dp_vco_divided_clk_src_mux.clkr.regmap = regmap; - mux_clk_ops = clk_regmap_mux_closest_ops; - mux_clk_ops.determine_rate = clk_mux_determine_rate; - mux_clk_ops.recalc_rate = mux_recalc_rate; - - dp_vco_clk.priv = pll_res; - - for (i = DP_VCO_CLK; i <= DP_VCO_DIVIDED_CLK_SRC_MUX; i++) { - pr_debug("reg clk: %d index: %d\n", i, pll_res->index); - clk = devm_clk_register(&pdev->dev, mdss_dp_pllcc_7nm[i]); - if (IS_ERR(clk)) { - pr_err("clk registration failed for DP: %d\n", - pll_res->index); - rc = -EINVAL; - goto clk_reg_fail; - } - clk_data->clks[i] = clk; - } - - rc = of_clk_add_provider(pdev->dev.of_node, - of_clk_src_onecell_get, clk_data); - if (rc) { - pr_err("Clock register failed rc=%d\n", rc); - rc = -EPROBE_DEFER; - goto clk_reg_fail; - } else { - pr_debug("SUCCESS\n"); - } - return rc; -clk_reg_fail: - return rc; -} diff --git a/drivers/clk/qcom/mdss/mdss-dp-pll-7nm.h b/drivers/clk/qcom/mdss/mdss-dp-pll-7nm.h deleted file mode 100644 index 336eb1f9cf385e8b66f1786033edb960770e26d1..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dp-pll-7nm.h +++ /dev/null @@ -1,52 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - */ - -#ifndef __MDSS_DP_PLL_7NM_H -#define __MDSS_DP_PLL_7NM_H - -#define DP_VCO_HSCLK_RATE_1620MHZDIV1000 1620000UL -#define DP_VCO_HSCLK_RATE_2700MHZDIV1000 2700000UL -#define DP_VCO_HSCLK_RATE_5400MHZDIV1000 5400000UL -#define DP_VCO_HSCLK_RATE_8100MHZDIV1000 8100000UL - -struct dp_pll_db_7nm { - struct mdss_pll_resources *pll; - - /* lane and orientation settings */ - u8 lane_cnt; - u8 orientation; - - /* COM PHY settings */ - u32 hsclk_sel; - u32 dec_start_mode0; - u32 div_frac_start1_mode0; - u32 div_frac_start2_mode0; - u32 div_frac_start3_mode0; - u32 integloop_gain0_mode0; - u32 integloop_gain1_mode0; - u32 vco_tune_map; - u32 lock_cmp1_mode0; - u32 lock_cmp2_mode0; - u32 lock_cmp_en; - u32 cmn_config; - u32 txn_tran_drv_emp_en; - - /* PHY vco divider */ - u32 phy_vco_div; -}; - -int dp_vco_set_rate_7nm(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate); -unsigned long dp_vco_recalc_rate_7nm(struct clk_hw *hw, - unsigned long parent_rate); -long dp_vco_round_rate_7nm(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate); -int dp_vco_prepare_7nm(struct clk_hw *hw); -void dp_vco_unprepare_7nm(struct clk_hw *hw); -int dp_mux_set_parent_7nm(void *context, - unsigned int reg, unsigned int val); -int dp_mux_get_parent_7nm(void *context, - unsigned int reg, unsigned int *val); -#endif /* __MDSS_DP_PLL_7NM_H */ diff --git a/drivers/clk/qcom/mdss/mdss-dp-pll.h b/drivers/clk/qcom/mdss/mdss-dp-pll.h deleted file mode 100644 index 2ef735833002b76db6a320217f5e924ac661f009..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dp-pll.h +++ /dev/null @@ -1,50 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. - */ - -#ifndef __MDSS_DP_PLL_H -#define __MDSS_DP_PLL_H - -struct dp_pll_vco_clk { - struct clk_hw hw; - unsigned long rate; /* current vco rate */ - u64 min_rate; /* min vco rate */ - u64 max_rate; /* max vco rate */ - void *priv; -}; - -static inline struct dp_pll_vco_clk *to_dp_vco_hw(struct clk_hw *hw) -{ - return container_of(hw, struct dp_pll_vco_clk, hw); -} - -#ifdef CONFIG_QCOM_MDSS_DP_PLL -int dp_pll_clock_register_14nm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res); - -int dp_pll_clock_register_10nm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res); - -int dp_pll_clock_register_7nm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res); -#else -static inline int dp_pll_clock_register_14nm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - return 0; -} - -static inline int dp_pll_clock_register_10nm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - return 0; -} - -static inline int dp_pll_clock_register_7nm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - return 0; -} -#endif -#endif /* __MDSS_DP_PLL_H */ diff --git a/drivers/clk/qcom/mdss/mdss-dsi-20nm-pll-util.c b/drivers/clk/qcom/mdss/mdss-dsi-20nm-pll-util.c deleted file mode 100644 index f715e8a768ad755d6cd8d42832df819257f97546..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dsi-20nm-pll-util.c +++ /dev/null @@ -1,1004 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include - -#include "mdss-pll.h" -#include "mdss-dsi-pll.h" - -#define MMSS_DSI_PHY_PLL_SYS_CLK_CTRL 0x0000 -#define MMSS_DSI_PHY_PLL_PLL_VCOTAIL_EN 0x0004 -#define MMSS_DSI_PHY_PLL_CMN_MODE 0x0008 -#define MMSS_DSI_PHY_PLL_IE_TRIM 0x000C -#define MMSS_DSI_PHY_PLL_IP_TRIM 0x0010 - -#define MMSS_DSI_PHY_PLL_PLL_PHSEL_CONTROL 0x0018 -#define MMSS_DSI_PHY_PLL_IPTAT_TRIM_VCCA_TX_SEL 0x001C -#define MMSS_DSI_PHY_PLL_PLL_PHSEL_DC 0x0020 -#define MMSS_DSI_PHY_PLL_PLL_IP_SETI 0x0024 -#define MMSS_DSI_PHY_PLL_CORE_CLK_IN_SYNC_SEL 0x0028 - -#define MMSS_DSI_PHY_PLL_BIAS_EN_CLKBUFLR_EN 0x0030 -#define MMSS_DSI_PHY_PLL_PLL_CP_SETI 0x0034 -#define MMSS_DSI_PHY_PLL_PLL_IP_SETP 0x0038 -#define MMSS_DSI_PHY_PLL_PLL_CP_SETP 0x003C -#define MMSS_DSI_PHY_PLL_ATB_SEL1 0x0040 -#define MMSS_DSI_PHY_PLL_ATB_SEL2 0x0044 -#define MMSS_DSI_PHY_PLL_SYSCLK_EN_SEL_TXBAND 0x0048 -#define MMSS_DSI_PHY_PLL_RESETSM_CNTRL 0x004C -#define MMSS_DSI_PHY_PLL_RESETSM_CNTRL2 0x0050 -#define MMSS_DSI_PHY_PLL_RESETSM_CNTRL3 0x0054 -#define MMSS_DSI_PHY_PLL_RESETSM_PLL_CAL_COUNT1 0x0058 -#define MMSS_DSI_PHY_PLL_RESETSM_PLL_CAL_COUNT2 0x005C -#define MMSS_DSI_PHY_PLL_DIV_REF1 0x0060 -#define MMSS_DSI_PHY_PLL_DIV_REF2 0x0064 -#define MMSS_DSI_PHY_PLL_KVCO_COUNT1 0x0068 -#define MMSS_DSI_PHY_PLL_KVCO_COUNT2 0x006C -#define MMSS_DSI_PHY_PLL_KVCO_CAL_CNTRL 0x0070 -#define MMSS_DSI_PHY_PLL_KVCO_CODE 0x0074 -#define MMSS_DSI_PHY_PLL_VREF_CFG1 0x0078 -#define MMSS_DSI_PHY_PLL_VREF_CFG2 0x007C -#define MMSS_DSI_PHY_PLL_VREF_CFG3 0x0080 -#define MMSS_DSI_PHY_PLL_VREF_CFG4 0x0084 -#define MMSS_DSI_PHY_PLL_VREF_CFG5 0x0088 -#define MMSS_DSI_PHY_PLL_VREF_CFG6 0x008C -#define MMSS_DSI_PHY_PLL_PLLLOCK_CMP1 0x0090 -#define MMSS_DSI_PHY_PLL_PLLLOCK_CMP2 0x0094 -#define MMSS_DSI_PHY_PLL_PLLLOCK_CMP3 0x0098 - -#define MMSS_DSI_PHY_PLL_BGTC 0x00A0 -#define MMSS_DSI_PHY_PLL_PLL_TEST_UPDN 0x00A4 -#define MMSS_DSI_PHY_PLL_PLL_VCO_TUNE 0x00A8 -#define MMSS_DSI_PHY_PLL_DEC_START1 0x00AC -#define MMSS_DSI_PHY_PLL_PLL_AMP_OS 0x00B0 -#define MMSS_DSI_PHY_PLL_SSC_EN_CENTER 0x00B4 -#define MMSS_DSI_PHY_PLL_SSC_ADJ_PER1 0x00B8 -#define MMSS_DSI_PHY_PLL_SSC_ADJ_PER2 0x00BC -#define MMSS_DSI_PHY_PLL_SSC_PER1 0x00C0 -#define MMSS_DSI_PHY_PLL_SSC_PER2 0x00C4 -#define MMSS_DSI_PHY_PLL_SSC_STEP_SIZE1 0x00C8 -#define MMSS_DSI_PHY_PLL_SSC_STEP_SIZE2 0x00CC -#define MMSS_DSI_PHY_PLL_RES_CODE_UP 0x00D0 -#define MMSS_DSI_PHY_PLL_RES_CODE_DN 0x00D4 -#define MMSS_DSI_PHY_PLL_RES_CODE_UP_OFFSET 0x00D8 -#define MMSS_DSI_PHY_PLL_RES_CODE_DN_OFFSET 0x00DC -#define MMSS_DSI_PHY_PLL_RES_CODE_START_SEG1 0x00E0 -#define MMSS_DSI_PHY_PLL_RES_CODE_START_SEG2 0x00E4 -#define MMSS_DSI_PHY_PLL_RES_CODE_CAL_CSR 0x00E8 -#define MMSS_DSI_PHY_PLL_RES_CODE 0x00EC -#define MMSS_DSI_PHY_PLL_RES_TRIM_CONTROL 0x00F0 -#define MMSS_DSI_PHY_PLL_RES_TRIM_CONTROL2 0x00F4 -#define MMSS_DSI_PHY_PLL_RES_TRIM_EN_VCOCALDONE 0x00F8 -#define MMSS_DSI_PHY_PLL_FAUX_EN 0x00FC - -#define MMSS_DSI_PHY_PLL_DIV_FRAC_START1 0x0100 -#define MMSS_DSI_PHY_PLL_DIV_FRAC_START2 0x0104 -#define MMSS_DSI_PHY_PLL_DIV_FRAC_START3 0x0108 -#define MMSS_DSI_PHY_PLL_DEC_START2 0x010C -#define MMSS_DSI_PHY_PLL_PLL_RXTXEPCLK_EN 0x0110 -#define MMSS_DSI_PHY_PLL_PLL_CRCTRL 0x0114 -#define MMSS_DSI_PHY_PLL_LOW_POWER_RO_CONTROL 0x013C -#define MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL 0x0140 -#define MMSS_DSI_PHY_PLL_HR_OCLK2_DIVIDER 0x0144 -#define MMSS_DSI_PHY_PLL_HR_OCLK3_DIVIDER 0x0148 -#define MMSS_DSI_PHY_PLL_PLL_VCO_HIGH 0x014C -#define MMSS_DSI_PHY_PLL_RESET_SM 0x0150 -#define MMSS_DSI_PHY_PLL_MUXVAL 0x0154 -#define MMSS_DSI_PHY_PLL_CORE_RES_CODE_DN 0x0158 -#define MMSS_DSI_PHY_PLL_CORE_RES_CODE_UP 0x015C -#define MMSS_DSI_PHY_PLL_CORE_VCO_TUNE 0x0160 -#define MMSS_DSI_PHY_PLL_CORE_VCO_TAIL 0x0164 -#define MMSS_DSI_PHY_PLL_CORE_KVCO_CODE 0x0168 - -#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL0 0x014 -#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL1 0x018 -#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL2 0x01C -#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL3 0x020 -#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL4 0x024 -#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL5 0x028 -#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL6 0x02C -#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL7 0x030 -#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL8 0x034 -#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL9 0x038 -#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL10 0x03C -#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL11 0x040 -#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL12 0x044 -#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL13 0x048 -#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL14 0x04C -#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL15 0x050 -#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL16 0x054 -#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL17 0x058 - -#define DSI_PLL_POLL_DELAY_US 1000 -#define DSI_PLL_POLL_TIMEOUT_US 15000 - -int set_mdss_byte_mux_sel(struct mux_clk *clk, int sel) -{ - return 0; -} - -int get_mdss_byte_mux_sel(struct mux_clk *clk) -{ - return 0; -} - -int set_mdss_pixel_mux_sel(struct mux_clk *clk, int sel) -{ - return 0; -} - -int get_mdss_pixel_mux_sel(struct mux_clk *clk) -{ - return 0; -} - -static void pll_20nm_cache_trim_codes(struct mdss_pll_resources *dsi_pll_res) -{ - int rc; - - if (dsi_pll_res->reg_upd) - return; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return; - } - - dsi_pll_res->cache_pll_trim_codes[0] = - MDSS_PLL_REG_R(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_CORE_KVCO_CODE); - dsi_pll_res->cache_pll_trim_codes[1] = - MDSS_PLL_REG_R(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_CORE_VCO_TUNE); - - pr_debug("core_kvco_code=0x%x core_vco_turn=0x%x\n", - dsi_pll_res->cache_pll_trim_codes[0], - dsi_pll_res->cache_pll_trim_codes[1]); - - mdss_pll_resource_enable(dsi_pll_res, false); - - dsi_pll_res->reg_upd = true; -} - -static void pll_20nm_override_trim_codes(struct mdss_pll_resources *dsi_pll_res) -{ - u32 reg_data; - void __iomem *pll_base = dsi_pll_res->pll_base; - - /* - * Override mux config for all cached trim codes from - * saved config except for VCO Tune - */ - reg_data = (dsi_pll_res->cache_pll_trim_codes[0] & 0x3f) | BIT(5); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_KVCO_CODE, reg_data); - - reg_data = (dsi_pll_res->cache_pll_trim_codes[1] & 0x7f) | BIT(7); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_PLL_VCO_TUNE, reg_data); -} - - -int set_bypass_lp_div_mux_sel(struct mux_clk *clk, int sel) -{ - struct mdss_pll_resources *dsi_pll_res = clk->priv; - int reg_data; - - pr_debug("bypass_lp_div mux set to %s mode\n", - sel ? "indirect" : "direct"); - - pr_debug("POST_DIVIDER_CONTROL = 0x%x\n", - MDSS_PLL_REG_R(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL)); - - reg_data = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL); - reg_data |= BIT(7); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL, - reg_data | (sel << 5)); - pr_debug("POST_DIVIDER_CONTROL = 0x%x\n", - MDSS_PLL_REG_R(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL)); - - return 0; -} - -int set_shadow_bypass_lp_div_mux_sel(struct mux_clk *clk, int sel) -{ - struct mdss_pll_resources *dsi_pll_res = clk->priv; - int reg_data, rem; - - if (!dsi_pll_res->resource_enable) { - pr_err("PLL resources disabled. Dynamic fps invalid\n"); - return -EINVAL; - } - - reg_data = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL); - reg_data |= BIT(7); - - pr_debug("%d: reg_data = %x\n", __LINE__, reg_data); - - /* Repeat POST DIVIDER 2 times (4 writes)*/ - for (rem = 0; rem < 2; rem++) - MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base, - MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL16 + (4 * rem), - MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL, - MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL, - (reg_data | (sel << 5)), (reg_data | (sel << 5))); - - return 0; -} - -int get_bypass_lp_div_mux_sel(struct mux_clk *clk) -{ - int mux_mode, rc; - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - if (is_gdsc_disabled(dsi_pll_res)) - return 0; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - mux_mode = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL) & BIT(5); - - pr_debug("bypass_lp_div mux mode = %s\n", - mux_mode ? "indirect" : "direct"); - mdss_pll_resource_enable(dsi_pll_res, false); - - return !!mux_mode; -} - -int ndiv_set_div(struct div_clk *clk, int div) -{ - int rc, reg_data; - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - reg_data = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL, - reg_data | div); - - pr_debug("POST_DIVIDER_CONTROL = 0x%x\n", - MDSS_PLL_REG_R(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL)); - - mdss_pll_resource_enable(dsi_pll_res, false); - return rc; -} - -int shadow_ndiv_set_div(struct div_clk *clk, int div) -{ - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - if (!dsi_pll_res->resource_enable) { - pr_err("PLL resources disabled. Dynamic fps invalid\n"); - return -EINVAL; - } - - pr_debug("%d div=%i\n", __LINE__, div); - - MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base, - MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL14, - MMSS_DSI_PHY_PLL_RESETSM_CNTRL3, - MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL, - 0x07, (0xB | div)); - - return 0; -} - -int ndiv_get_div(struct div_clk *clk) -{ - int div = 0, rc; - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - if (is_gdsc_disabled(dsi_pll_res)) - return 0; - - rc = mdss_pll_resource_enable(clk->priv, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - div = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL) & 0x0F; - - mdss_pll_resource_enable(dsi_pll_res, false); - - return div; -} - -int fixed_hr_oclk2_set_div(struct div_clk *clk, int div) -{ - int rc; - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_HR_OCLK2_DIVIDER, - (div - 1)); - - mdss_pll_resource_enable(dsi_pll_res, false); - return rc; -} - -int shadow_fixed_hr_oclk2_set_div(struct div_clk *clk, int div) -{ - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - if (!dsi_pll_res->resource_enable) { - pr_err("PLL resources disabled. Dynamic fps invalid\n"); - return -EINVAL; - } - pr_debug("%d div = %d\n", __LINE__, div); - - MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base, - MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL5, - MMSS_DSI_PHY_PLL_HR_OCLK2_DIVIDER, - MMSS_DSI_PHY_PLL_HR_OCLK2_DIVIDER, - (div - 1), (div - 1)); - - return 0; -} - -int fixed_hr_oclk2_get_div(struct div_clk *clk) -{ - int div = 0, rc; - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - if (is_gdsc_disabled(dsi_pll_res)) - return 0; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - div = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_HR_OCLK2_DIVIDER); - - mdss_pll_resource_enable(dsi_pll_res, false); - return div + 1; -} - -int hr_oclk3_set_div(struct div_clk *clk, int div) -{ - int rc; - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - pr_debug("%d div = %d\n", __LINE__, div); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_HR_OCLK3_DIVIDER, - (div - 1)); - pr_debug("%s: HR_OCLK3_DIVIDER = 0x%x\n", __func__, - MDSS_PLL_REG_R(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_HR_OCLK3_DIVIDER)); - - mdss_pll_resource_enable(dsi_pll_res, false); - return rc; -} - -int shadow_hr_oclk3_set_div(struct div_clk *clk, int div) -{ - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - if (!dsi_pll_res->resource_enable) { - pr_err("PLL resources disabled. Dynamic fps invalid\n"); - return -EINVAL; - } - - pr_debug("%d div = %d\n", __LINE__, div); - - MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base, - MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL6, - MMSS_DSI_PHY_PLL_HR_OCLK3_DIVIDER, - MMSS_DSI_PHY_PLL_HR_OCLK3_DIVIDER, - (div - 1), (div - 1)); - - return 0; -} - -int hr_oclk3_get_div(struct div_clk *clk) -{ - int div = 0, rc; - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - if (is_gdsc_disabled(dsi_pll_res)) - return 0; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - div = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_HR_OCLK3_DIVIDER); - - mdss_pll_resource_enable(dsi_pll_res, false); - return div + 1; -} - -static bool pll_20nm_is_pll_locked(struct mdss_pll_resources *dsi_pll_res) -{ - u32 status; - bool pll_locked; - - /* poll for PLL ready status */ - if (readl_poll_timeout_atomic((dsi_pll_res->pll_base + - MMSS_DSI_PHY_PLL_RESET_SM), - status, - ((status & BIT(5)) > 0), - DSI_PLL_POLL_DELAY_US, - DSI_PLL_POLL_TIMEOUT_US)) { - pr_debug("DSI PLL status=%x failed to Lock\n", status); - pll_locked = false; - } else if (readl_poll_timeout_atomic((dsi_pll_res->pll_base + - MMSS_DSI_PHY_PLL_RESET_SM), - status, - ((status & BIT(6)) > 0), - DSI_PLL_POLL_DELAY_US, - DSI_PLL_POLL_TIMEOUT_US)) { - pr_debug("DSI PLL status=%x PLl not ready\n", status); - pll_locked = false; - } else { - pll_locked = true; - } - - return pll_locked; -} - -void __dsi_pll_disable(void __iomem *pll_base) -{ - if (!pll_base) { - pr_err("Invalid pll base\n"); - return; - } - pr_debug("Disabling PHY PLL for PLL_BASE=%p\n", pll_base); - - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_PLL_VCOTAIL_EN, 0x02); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_RESETSM_CNTRL3, 0x06); -} - -static void pll_20nm_config_powerdown(void __iomem *pll_base) -{ - if (!pll_base) { - pr_err("Invalid pll base.\n"); - return; - } - - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_SYS_CLK_CTRL, 0x00); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_CMN_MODE, 0x01); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_PLL_VCOTAIL_EN, 0x82); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_BIAS_EN_CLKBUFLR_EN, 0x02); -} - -static int dsi_pll_enable(struct clk *c) -{ - int i, rc; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - /* Try all enable sequences until one succeeds */ - for (i = 0; i < vco->pll_en_seq_cnt; i++) { - rc = vco->pll_enable_seqs[i](dsi_pll_res); - pr_debug("DSI PLL %s after sequence #%d\n", - rc ? "unlocked" : "locked", i + 1); - if (!rc) - break; - } - /* Disable PLL1 to avoid current leakage while toggling MDSS GDSC */ - if (dsi_pll_res->pll_1_base) - pll_20nm_config_powerdown(dsi_pll_res->pll_1_base); - - if (rc) { - mdss_pll_resource_enable(dsi_pll_res, false); - pr_err("DSI PLL failed to lock\n"); - } - dsi_pll_res->pll_on = true; - - return rc; -} - -static void dsi_pll_disable(struct clk *c) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - if (!dsi_pll_res->pll_on && - mdss_pll_resource_enable(dsi_pll_res, true)) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return; - } - - dsi_pll_res->handoff_resources = false; - - __dsi_pll_disable(dsi_pll_res->pll_base); - - /* Disable PLL1 to avoid current leakage while toggling MDSS GDSC */ - if (dsi_pll_res->pll_1_base) - pll_20nm_config_powerdown(dsi_pll_res->pll_1_base); - - pll_20nm_config_powerdown(dsi_pll_res->pll_base); - - mdss_pll_resource_enable(dsi_pll_res, false); - - dsi_pll_res->pll_on = false; - - pr_debug("DSI PLL Disabled\n"); -} - -static void pll_20nm_config_common_block_1(void __iomem *pll_base) -{ - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_PLL_VCOTAIL_EN, 0x82); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_BIAS_EN_CLKBUFLR_EN, 0x2a); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_BIAS_EN_CLKBUFLR_EN, 0x2b); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_RESETSM_CNTRL3, 0x02); -} - -static void pll_20nm_config_common_block_2(void __iomem *pll_base) -{ - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_SYS_CLK_CTRL, 0x40); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_IE_TRIM, 0x0F); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_IP_TRIM, 0x0F); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_PLL_PHSEL_CONTROL, 0x08); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_IPTAT_TRIM_VCCA_TX_SEL, 0x0E); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_PLL_BKG_KVCO_CAL_EN, 0x08); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_SYSCLK_EN_SEL_TXBAND, 0x4A); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_DIV_REF1, 0x00); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_DIV_REF2, 0x01); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_PLL_CNTRL, 0x07); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_KVCO_CAL_CNTRL, 0x1f); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_KVCO_COUNT1, 0x8A); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_VREF_CFG3, 0x10); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_SSC_EN_CENTER, 0x00); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_FAUX_EN, 0x0C); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_PLL_RXTXEPCLK_EN, 0x0a); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_LOW_POWER_RO_CONTROL, 0x0f); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_CMN_MODE, 0x00); -} - -static void pll_20nm_config_loop_bw(void __iomem *pll_base) -{ - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_PLL_IP_SETI, 0x03); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_PLL_CP_SETI, 0x3F); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_PLL_IP_SETP, 0x03); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_PLL_CP_SETP, 0x1F); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_PLL_CRCTRL, 0x77); -} - -static void pll_20nm_vco_rate_calc(struct mdss_pll_vco_calc *vco_calc, - s64 vco_clk_rate, s64 ref_clk_rate) -{ - s64 multiplier = (1 << 20); - s64 duration = 1024, pll_comp_val; - s64 dec_start_multiple, dec_start; - s32 div_frac_start; - s64 dec_start1, dec_start2; - s32 div_frac_start1, div_frac_start2, div_frac_start3; - s64 pll_plllock_cmp1, pll_plllock_cmp2, pll_plllock_cmp3; - - memset(vco_calc, 0, sizeof(*vco_calc)); - pr_debug("vco_clk_rate=%lld ref_clk_rate=%lld\n", vco_clk_rate, - ref_clk_rate); - - dec_start_multiple = div_s64(vco_clk_rate * multiplier, - 2 * ref_clk_rate); - div_s64_rem(dec_start_multiple, - multiplier, &div_frac_start); - - dec_start = div_s64(dec_start_multiple, multiplier); - dec_start1 = (dec_start & 0x7f) | BIT(7); - dec_start2 = ((dec_start & 0x80) >> 7) | BIT(1); - div_frac_start1 = (div_frac_start & 0x7f) | BIT(7); - div_frac_start2 = ((div_frac_start >> 7) & 0x7f) | BIT(7); - div_frac_start3 = ((div_frac_start >> 14) & 0x3f) | BIT(6); - pll_comp_val = (div_s64(dec_start_multiple * 2 * duration, - 10 * multiplier)) - 1; - pll_plllock_cmp1 = pll_comp_val & 0xff; - pll_plllock_cmp2 = (pll_comp_val >> 8) & 0xff; - pll_plllock_cmp3 = (pll_comp_val >> 16) & 0xff; - - pr_debug("dec_start_multiple = 0x%llx\n", dec_start_multiple); - pr_debug("dec_start = 0x%llx, div_frac_start = 0x%x\n", - dec_start, div_frac_start); - pr_debug("dec_start1 = 0x%llx, dec_start2 = 0x%llx\n", - dec_start1, dec_start2); - pr_debug("div_frac_start1 = 0x%x, div_frac_start2 = 0x%x\n", - div_frac_start1, div_frac_start2); - pr_debug("div_frac_start3 = 0x%x\n", div_frac_start3); - pr_debug("pll_comp_val = 0x%llx\n", pll_comp_val); - pr_debug("pll_plllock_cmp1 = 0x%llx, pll_plllock_cmp2 =%llx\n", - pll_plllock_cmp1, pll_plllock_cmp2); - pr_debug("pll_plllock_cmp3 = 0x%llx\n", pll_plllock_cmp3); - - /* Assign to vco struct */ - vco_calc->div_frac_start1 = div_frac_start1; - vco_calc->div_frac_start2 = div_frac_start2; - vco_calc->div_frac_start3 = div_frac_start3; - vco_calc->dec_start1 = dec_start1; - vco_calc->dec_start2 = dec_start2; - vco_calc->pll_plllock_cmp1 = pll_plllock_cmp1; - vco_calc->pll_plllock_cmp2 = pll_plllock_cmp2; - vco_calc->pll_plllock_cmp3 = pll_plllock_cmp3; -} - -static void pll_20nm_config_vco_rate(void __iomem *pll_base, - struct mdss_pll_vco_calc *vco_calc) -{ - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_DIV_FRAC_START1, - vco_calc->div_frac_start1); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_DIV_FRAC_START2, - vco_calc->div_frac_start2); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_DIV_FRAC_START3, - vco_calc->div_frac_start3); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_DEC_START1, - vco_calc->dec_start1); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_DEC_START2, - vco_calc->dec_start2); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_PLLLOCK_CMP1, - vco_calc->pll_plllock_cmp1); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_PLLLOCK_CMP2, - vco_calc->pll_plllock_cmp2); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_PLLLOCK_CMP3, - vco_calc->pll_plllock_cmp3); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_PLLLOCK_CMP_EN, 0x01); -} - -int pll_20nm_vco_set_rate(struct dsi_pll_vco_clk *vco, unsigned long rate) -{ - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - dsi_pll_res->vco_current_rate = rate; - dsi_pll_res->vco_ref_clk_rate = vco->ref_clk_rate; - - return 0; -} - -int shadow_pll_20nm_vco_set_rate(struct dsi_pll_vco_clk *vco, - unsigned long rate) -{ - struct mdss_pll_resources *dsi_pll_res = vco->priv; - struct mdss_pll_vco_calc vco_calc; - s64 vco_clk_rate = rate; - u32 rem; - - if (!dsi_pll_res->resource_enable) { - pr_err("PLL resources disabled. Dynamic fps invalid\n"); - return -EINVAL; - } - - pr_debug("req vco set rate: %lld\n", vco_clk_rate); - - pll_20nm_override_trim_codes(dsi_pll_res); - - /* div fraction, start and comp calculations */ - pll_20nm_vco_rate_calc(&vco_calc, vco_clk_rate, - dsi_pll_res->vco_ref_clk_rate); - - MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base, - MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL0, - MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL, - MMSS_DSI_PHY_PLL_PLLLOCK_CMP_EN, - 0xB1, 0); - MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base, - MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL1, - MMSS_DSI_PHY_PLL_PLLLOCK_CMP1, - MMSS_DSI_PHY_PLL_PLLLOCK_CMP2, - vco_calc.pll_plllock_cmp1, vco_calc.pll_plllock_cmp2); - MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base, - MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL2, - MMSS_DSI_PHY_PLL_PLLLOCK_CMP3, - MMSS_DSI_PHY_PLL_DEC_START1, - vco_calc.pll_plllock_cmp3, vco_calc.dec_start1); - MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base, - MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL3, - MMSS_DSI_PHY_PLL_DEC_START2, - MMSS_DSI_PHY_PLL_DIV_FRAC_START1, - vco_calc.dec_start2, vco_calc.div_frac_start1); - MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base, - MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL4, - MMSS_DSI_PHY_PLL_DIV_FRAC_START2, - MMSS_DSI_PHY_PLL_DIV_FRAC_START3, - vco_calc.div_frac_start2, vco_calc.div_frac_start3); - /* Method 2 - Auto PLL calibration */ - MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base, - MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL7, - MMSS_DSI_PHY_PLL_PLL_VCO_TUNE, - MMSS_DSI_PHY_PLL_PLLLOCK_CMP_EN, - 0, 0x0D); - MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base, - MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL8, - MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL, - MMSS_DSI_PHY_PLL_RESETSM_CNTRL3, - 0xF0, 0x07); - - /* - * RESETSM_CTRL3 has to be set for 12 times (6 reg writes), - * Each register setting write 2 times, running in loop for 5 - * times (5 reg writes) and other two iterations are taken - * care (one above and other in shadow_bypass - */ - for (rem = 0; rem < 5; rem++) { - MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base, - MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL9 + (4 * rem), - MMSS_DSI_PHY_PLL_RESETSM_CNTRL3, - MMSS_DSI_PHY_PLL_RESETSM_CNTRL3, - 0x07, 0x07); - } - - MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base, - MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL15, - MMSS_DSI_PHY_PLL_RESETSM_CNTRL3, - MMSS_DSI_PHY_PLL_RESETSM_CNTRL3, - 0x03, 0x03); - - /* memory barrier */ - wmb(); - return 0; -} - -unsigned long pll_20nm_vco_get_rate(struct clk *c) -{ - u64 vco_rate, multiplier = (1 << 20); - s32 div_frac_start; - u32 dec_start; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - u64 ref_clk = vco->ref_clk_rate; - int rc; - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - if (is_gdsc_disabled(dsi_pll_res)) - return 0; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - dec_start = (MDSS_PLL_REG_R(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_DEC_START2) & BIT(0)) << 7; - dec_start |= (MDSS_PLL_REG_R(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_DEC_START1) & 0x7f); - pr_debug("dec_start = 0x%x\n", dec_start); - - div_frac_start = (MDSS_PLL_REG_R(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_DIV_FRAC_START3) & 0x3f) << 14; - div_frac_start |= (MDSS_PLL_REG_R(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_DIV_FRAC_START2) & 0x7f) << 7; - div_frac_start |= MDSS_PLL_REG_R(dsi_pll_res->pll_base, - MMSS_DSI_PHY_PLL_DIV_FRAC_START1) & 0x7f; - pr_debug("div_frac_start = 0x%x\n", div_frac_start); - - vco_rate = ref_clk * 2 * dec_start; - vco_rate += ((ref_clk * 2 * div_frac_start) / multiplier); - pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate); - - mdss_pll_resource_enable(dsi_pll_res, false); - - return (unsigned long)vco_rate; -} -long pll_20nm_vco_round_rate(struct clk *c, unsigned long rate) -{ - unsigned long rrate = rate; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - - if (rate < vco->min_rate) - rrate = vco->min_rate; - if (rate > vco->max_rate) - rrate = vco->max_rate; - - return rrate; -} - -enum handoff pll_20nm_vco_handoff(struct clk *c) -{ - int rc; - enum handoff ret = HANDOFF_DISABLED_CLK; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - if (is_gdsc_disabled(dsi_pll_res)) - return HANDOFF_DISABLED_CLK; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return ret; - } - - if (pll_20nm_is_pll_locked(dsi_pll_res)) { - dsi_pll_res->handoff_resources = true; - dsi_pll_res->pll_on = true; - c->rate = pll_20nm_vco_get_rate(c); - ret = HANDOFF_ENABLED_CLK; - dsi_pll_res->vco_locking_rate = c->rate; - dsi_pll_res->is_init_locked = true; - pll_20nm_cache_trim_codes(dsi_pll_res); - pr_debug("handoff vco_locking_rate=%llu\n", - dsi_pll_res->vco_locking_rate); - } else { - mdss_pll_resource_enable(dsi_pll_res, false); - dsi_pll_res->vco_locking_rate = 0; - dsi_pll_res->is_init_locked = false; - } - - return ret; -} - -int pll_20nm_vco_prepare(struct clk *c) -{ - int rc = 0; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - if (!dsi_pll_res) { - pr_err("Dsi pll resources are not available\n"); - return -EINVAL; - } - - if ((dsi_pll_res->vco_cached_rate != 0) - && (dsi_pll_res->vco_cached_rate == c->rate)) { - rc = c->ops->set_rate(c, dsi_pll_res->vco_cached_rate); - if (rc) { - pr_err("vco_set_rate failed. rc=%d\n", rc); - goto error; - } - } - - rc = dsi_pll_enable(c); - -error: - return rc; -} - -void pll_20nm_vco_unprepare(struct clk *c) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - if (!dsi_pll_res) { - pr_err("Dsi pll resources are not available\n"); - return; - } - - dsi_pll_res->vco_cached_rate = c->rate; - dsi_pll_disable(c); -} - -static void pll_20nm_config_resetsm(void __iomem *pll_base) -{ - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_RESETSM_CNTRL, 0x24); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_RESETSM_CNTRL2, 0x07); -} - -static void pll_20nm_config_vco_start(void __iomem *pll_base) -{ - - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_PLL_VCOTAIL_EN, 0x03); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_RESETSM_CNTRL3, 0x02); - udelay(10); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_RESETSM_CNTRL3, 0x03); -} - -static void pll_20nm_config_bypass_cal(void __iomem *pll_base) -{ - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_RESETSM_CNTRL, 0xac); - MDSS_PLL_REG_W(pll_base, MMSS_DSI_PHY_PLL_PLL_BKG_KVCO_CAL_EN, 0x28); -} - -static int pll_20nm_vco_relock(struct mdss_pll_resources *dsi_pll_res) -{ - int rc = 0; - - pll_20nm_override_trim_codes(dsi_pll_res); - pll_20nm_config_bypass_cal(dsi_pll_res->pll_base); - pll_20nm_config_vco_start(dsi_pll_res->pll_base); - - if (!pll_20nm_is_pll_locked(dsi_pll_res)) { - pr_err("DSI PLL re-lock failed\n"); - rc = -EINVAL; - } - - return rc; -} - -static int pll_20nm_vco_init_lock(struct mdss_pll_resources *dsi_pll_res) -{ - int rc = 0; - - pll_20nm_config_resetsm(dsi_pll_res->pll_base); - pll_20nm_config_vco_start(dsi_pll_res->pll_base); - - if (!pll_20nm_is_pll_locked(dsi_pll_res)) { - pr_err("DSI PLL init lock failed\n"); - rc = -EINVAL; - goto init_lock_err; - } - - pll_20nm_cache_trim_codes(dsi_pll_res); - -init_lock_err: - return rc; -} - -int pll_20nm_vco_enable_seq(struct mdss_pll_resources *dsi_pll_res) -{ - int rc = 0; - struct mdss_pll_vco_calc vco_calc; - - if (!dsi_pll_res) { - pr_err("Invalid PLL resources\n"); - return -EINVAL; - } - - pll_20nm_config_common_block_1(dsi_pll_res->pll_1_base); - pll_20nm_config_common_block_1(dsi_pll_res->pll_base); - pll_20nm_config_common_block_2(dsi_pll_res->pll_base); - pll_20nm_config_loop_bw(dsi_pll_res->pll_base); - - pll_20nm_vco_rate_calc(&vco_calc, dsi_pll_res->vco_current_rate, - dsi_pll_res->vco_ref_clk_rate); - pll_20nm_config_vco_rate(dsi_pll_res->pll_base, &vco_calc); - - pr_debug("init lock=%d prev vco_rate=%llu, new vco_rate=%llu\n", - dsi_pll_res->is_init_locked, dsi_pll_res->vco_locking_rate, - dsi_pll_res->vco_current_rate); - /* - * Run auto-lock sequence if it is either bootup initial - * locking or when the vco rate is changed. Otherwise, just - * use stored codes and bypass caliberation. - */ - if (!dsi_pll_res->is_init_locked || (dsi_pll_res->vco_locking_rate != - dsi_pll_res->vco_current_rate)) { - rc = pll_20nm_vco_init_lock(dsi_pll_res); - dsi_pll_res->is_init_locked = (rc) ? false : true; - } else { - rc = pll_20nm_vco_relock(dsi_pll_res); - } - - dsi_pll_res->vco_locking_rate = (rc) ? 0 : - dsi_pll_res->vco_current_rate; - - return rc; -} diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c deleted file mode 100644 index 1eb4f6f193011ba66a1fa3022717c09c9c7aa393..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c +++ /dev/null @@ -1,1643 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include "mdss-dsi-pll.h" -#include "mdss-pll.h" -#include -#define CREATE_TRACE_POINTS -#include "mdss_pll_trace.h" - -#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_MUXES 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 - -/* 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 int pll_reg_read(void *context, unsigned int reg, - unsigned int *val) -{ - int rc = 0; - struct mdss_pll_resources *rsc = context; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - *val = MDSS_PLL_REG_R(rsc->pll_base, reg); - (void)mdss_pll_resource_enable(rsc, false); - - return rc; -} - -static inline int pll_reg_write(void *context, unsigned int reg, - unsigned int val) -{ - int rc = 0; - struct mdss_pll_resources *rsc = context; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - MDSS_PLL_REG_W(rsc->pll_base, reg, val); - (void)mdss_pll_resource_enable(rsc, false); - - return rc; -} - -static inline int phy_reg_read(void *context, unsigned int reg, - unsigned int *val) -{ - int rc = 0; - struct mdss_pll_resources *rsc = context; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - *val = MDSS_PLL_REG_R(rsc->phy_base, reg); - (void)mdss_pll_resource_enable(rsc, false); - - return rc; -} - -static inline int phy_reg_write(void *context, unsigned int reg, - unsigned int val) -{ - int rc = 0; - struct mdss_pll_resources *rsc = context; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - MDSS_PLL_REG_W(rsc->phy_base, reg, val); - (void)mdss_pll_resource_enable(rsc, false); - - return rc; -} - -static inline int phy_reg_update_bits_sub(struct mdss_pll_resources *rsc, - unsigned int reg, unsigned int mask, unsigned int val) -{ - u32 reg_val; - - reg_val = MDSS_PLL_REG_R(rsc->phy_base, reg); - reg_val &= ~mask; - reg_val |= (val & mask); - MDSS_PLL_REG_W(rsc->phy_base, reg, reg_val); - - return 0; -} - -static inline int phy_reg_update_bits(void *context, unsigned int reg, - unsigned int mask, unsigned int val) -{ - int rc = 0; - struct mdss_pll_resources *rsc = context; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - rc = phy_reg_update_bits_sub(rsc, reg, mask, val); - if (!rc && rsc->slave) - rc = phy_reg_update_bits_sub(rsc->slave, reg, mask, val); - (void)mdss_pll_resource_enable(rsc, false); - - return rc; -} - -static inline int pclk_mux_read_sel(void *context, unsigned int reg, - unsigned int *val) -{ - int rc = 0; - struct mdss_pll_resources *rsc = context; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - else - *val = (MDSS_PLL_REG_R(rsc->phy_base, reg) & 0x3); - - (void)mdss_pll_resource_enable(rsc, false); - return rc; -} - - -static inline int pclk_mux_write_sel_sub(struct mdss_pll_resources *rsc, - unsigned int reg, unsigned int val) -{ - u32 reg_val; - - reg_val = MDSS_PLL_REG_R(rsc->phy_base, reg); - reg_val &= ~0x03; - reg_val |= val; - - MDSS_PLL_REG_W(rsc->phy_base, reg, reg_val); - - return 0; -} - -static inline int pclk_mux_write_sel(void *context, unsigned int reg, - unsigned int val) -{ - int rc = 0; - struct mdss_pll_resources *rsc = context; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - rc = pclk_mux_write_sel_sub(rsc, reg, val); - if (!rc && rsc->slave) - rc = pclk_mux_write_sel_sub(rsc->slave, reg, val); - - (void)mdss_pll_resource_enable(rsc, false); - - /* - * cache the current parent index for cases where parent - * is not changing but rate is changing. In that case - * clock framework won't call parent_set and hence dsiclk_sel - * bit won't be programmed. e.g. dfps update use case. - */ - rsc->cached_cfg1 = val; - - return rc; -} - -static struct mdss_pll_resources *pll_rsc_db[DSI_PLL_MAX]; -static struct dsi_pll_10nm plls[DSI_PLL_MAX]; - -static void dsi_pll_config_slave(struct mdss_pll_resources *rsc) -{ - u32 reg; - struct mdss_pll_resources *orsc = pll_rsc_db[DSI_PLL_1]; - - if (!rsc) - return; - - /* Only DSI PLL0 can act as a master */ - if (rsc->index != DSI_PLL_0) - return; - - /* default configuration: source is either internal or ref clock */ - rsc->slave = NULL; - - if (!orsc) { - pr_warn("slave PLL unavilable, assuming standalone config\n"); - return; - } - - /* check to see if the source of DSI1 PLL bitclk is set to external */ - reg = MDSS_PLL_REG_R(orsc->phy_base, PHY_CMN_CLK_CFG1); - reg &= (BIT(2) | BIT(3)); - if (reg == 0x04) - rsc->slave = pll_rsc_db[DSI_PLL_1]; /* external source */ - - pr_debug("Slave PLL %s\n", rsc->slave ? "configured" : "absent"); -} - -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; - } - - dsi_pll_config_slave(rsc); -} - -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) { - pr_debug("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; - - pr_debug("SCC: Dec:%d, frac:%llu, frac_bits:%d\n", - regs->decimal_div_start, frac, config->frac_bits); - pr_debug("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_ssc_commit(struct dsi_pll_10nm *pll, - struct mdss_pll_resources *rsc) -{ - void __iomem *pll_base = rsc->pll_base; - struct dsi_pll_regs *regs = &pll->reg_setup; - - if (pll->pll_configuration.enable_ssc) { - pr_debug("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 void dsi_pll_config_hzindep_reg(struct dsi_pll_10nm *pll, - struct mdss_pll_resources *rsc) -{ - void __iomem *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_init_val(struct mdss_pll_resources *rsc) -{ - void __iomem *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_commit(struct dsi_pll_10nm *pll, - struct mdss_pll_resources *rsc) -{ - void __iomem *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 int vco_10nm_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - int rc; - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct mdss_pll_resources *rsc = vco->priv; - struct dsi_pll_10nm *pll; - - if (!rsc) { - pr_err("pll resource not found\n"); - return -EINVAL; - } - - if (rsc->pll_on) - return 0; - - pll = rsc->priv; - if (!pll) { - pr_err("pll configuration not found\n"); - return -EINVAL; - } - - pr_debug("ndx=%d, rate=%lu\n", rsc->index, rate); - - rsc->vco_current_rate = rate; - rsc->vco_ref_clk_rate = vco->ref_clk_rate; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("failed to enable mdss dsi pll(%d), rc=%d\n", - rsc->index, rc); - return rc; - } - - 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(); - - mdss_pll_resource_enable(rsc, false); - - return 0; -} - -static int dsi_pll_10nm_lock_status(struct mdss_pll_resources *pll) -{ - int rc; - u32 status; - u32 const delay_us = 100; - u32 const timeout_us = 5000; - - rc = readl_poll_timeout_atomic(pll->pll_base + PLL_COMMON_STATUS_ONE, - status, - ((status & BIT(0)) > 0), - delay_us, - timeout_us); - if (rc) - pr_err("DSI PLL(%d) lock failed, status=0x%08x\n", - pll->index, status); - - return rc; -} - -static void dsi_pll_disable_pll_bias(struct mdss_pll_resources *rsc) -{ - u32 data = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CTRL_0); - - MDSS_PLL_REG_W(rsc->pll_base, PLL_SYSTEM_MUXES, 0); - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data & ~BIT(5)); - ndelay(250); -} - -static void dsi_pll_enable_pll_bias(struct mdss_pll_resources *rsc) -{ - u32 data = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CTRL_0); - - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data | BIT(5)); - MDSS_PLL_REG_W(rsc->pll_base, PLL_SYSTEM_MUXES, 0xc0); - ndelay(250); -} - -static void dsi_pll_disable_global_clk(struct mdss_pll_resources *rsc) -{ - u32 data; - - data = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG1); - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CLK_CFG1, (data & ~BIT(5))); -} - -static void dsi_pll_enable_global_clk(struct mdss_pll_resources *rsc) -{ - u32 data; - - data = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG1); - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CLK_CFG1, (data | BIT(5))); -} - -static int dsi_pll_enable(struct dsi_pll_vco_clk *vco) -{ - int rc; - struct mdss_pll_resources *rsc = vco->priv; - - dsi_pll_enable_pll_bias(rsc); - if (rsc->slave) - dsi_pll_enable_pll_bias(rsc->slave); - - phy_reg_update_bits_sub(rsc, PHY_CMN_CLK_CFG1, 0x03, rsc->cached_cfg1); - if (rsc->slave) - phy_reg_update_bits_sub(rsc->slave, PHY_CMN_CLK_CFG1, - 0x03, rsc->cached_cfg1); - wmb(); /* ensure dsiclk_sel is always programmed before pll start */ - - /* Start PLL */ - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_PLL_CNTRL, 0x01); - - /* - * ensure all PLL configurations are written prior to checking - * for PLL lock. - */ - wmb(); - - /* Check for PLL lock */ - rc = dsi_pll_10nm_lock_status(rsc); - if (rc) { - pr_err("PLL(%d) lock failed\n", rsc->index); - goto error; - } - - rsc->pll_on = true; - - dsi_pll_enable_global_clk(rsc); - if (rsc->slave) - dsi_pll_enable_global_clk(rsc->slave); - - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_RBUF_CTRL, 0x01); - if (rsc->slave) - MDSS_PLL_REG_W(rsc->slave->phy_base, PHY_CMN_RBUF_CTRL, 0x01); - -error: - return rc; -} - -static void dsi_pll_disable_sub(struct mdss_pll_resources *rsc) -{ - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_RBUF_CTRL, 0); - dsi_pll_disable_pll_bias(rsc); -} - -static void dsi_pll_disable(struct dsi_pll_vco_clk *vco) -{ - struct mdss_pll_resources *rsc = vco->priv; - - if (!rsc->pll_on && - mdss_pll_resource_enable(rsc, true)) { - pr_err("failed to enable pll (%d) resources\n", rsc->index); - return; - } - - rsc->handoff_resources = false; - - pr_debug("stop PLL (%d)\n", rsc->index); - - /* - * To avoid any stray glitches while - * abruptly powering down the PLL - * make sure to gate the clock using - * the clock enable bit before powering - * down the PLL - */ - dsi_pll_disable_global_clk(rsc); - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_PLL_CNTRL, 0); - dsi_pll_disable_sub(rsc); - if (rsc->slave) { - dsi_pll_disable_global_clk(rsc->slave); - dsi_pll_disable_sub(rsc->slave); - } - /* flush, ensure all register writes are done*/ - wmb(); - rsc->pll_on = false; -} - -long vco_10nm_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - unsigned long rrate = rate; - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - - if (rate < vco->min_rate) - rrate = vco->min_rate; - if (rate > vco->max_rate) - rrate = vco->max_rate; - - *parent_rate = rrate; - - return rrate; -} - -static void vco_10nm_unprepare(struct clk_hw *hw) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct mdss_pll_resources *pll = vco->priv; - - if (!pll) { - pr_err("dsi pll resources not available\n"); - return; - } - - /* - * During unprepare in continuous splash use case we want driver - * to pick all dividers instead of retaining bootloader configurations. - */ - if (!pll->handoff_resources) { - pll->cached_cfg0 = MDSS_PLL_REG_R(pll->phy_base, - PHY_CMN_CLK_CFG0); - pll->cached_outdiv = MDSS_PLL_REG_R(pll->pll_base, - PLL_PLL_OUTDIV_RATE); - pr_debug("cfg0=%d,cfg1=%d, outdiv=%d\n", pll->cached_cfg0, - pll->cached_cfg1, pll->cached_outdiv); - - pll->vco_cached_rate = clk_hw_get_rate(hw); - } - - /* - * When continuous splash screen feature is enabled, we need to cache - * the mux configuration for the pixel_clk_src mux clock. The clock - * framework does not call back to re-configure the mux value if it is - * does not change.For such usecases, we need to ensure that the cached - * value is programmed prior to PLL being locked - */ - if (pll->handoff_resources) - pll->cached_cfg1 = MDSS_PLL_REG_R(pll->phy_base, - PHY_CMN_CLK_CFG1); - dsi_pll_disable(vco); - mdss_pll_resource_enable(pll, false); -} - -static int vco_10nm_prepare(struct clk_hw *hw) -{ - int rc = 0; - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct mdss_pll_resources *pll = vco->priv; - - if (!pll) { - pr_err("dsi pll resources are not available\n"); - return -EINVAL; - } - - /* Skip vco recalculation for continuous splash use case */ - if (pll->handoff_resources) - return 0; - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("failed to enable pll (%d) resource, rc=%d\n", - pll->index, rc); - return rc; - } - - if ((pll->vco_cached_rate != 0) && - (pll->vco_cached_rate == clk_hw_get_rate(hw))) { - rc = hw->init->ops->set_rate(hw, pll->vco_cached_rate, - pll->vco_cached_rate); - if (rc) { - pr_err("pll(%d) set_rate failed, rc=%d\n", - pll->index, rc); - mdss_pll_resource_enable(pll, false); - return rc; - } - pr_debug("cfg0=%d, cfg1=%d\n", pll->cached_cfg0, - pll->cached_cfg1); - MDSS_PLL_REG_W(pll->phy_base, PHY_CMN_CLK_CFG0, - pll->cached_cfg0); - MDSS_PLL_REG_W(pll->pll_base, PLL_PLL_OUTDIV_RATE, - pll->cached_outdiv); - } - MDSS_PLL_ATRACE_BEGIN("pll_lock"); - trace_mdss_pll_lock_start((u64)pll->vco_cached_rate, - pll->vco_current_rate, - pll->cached_cfg0, pll->cached_cfg1, - pll->cached_outdiv, pll->resource_ref_cnt); - rc = dsi_pll_enable(vco); - MDSS_PLL_ATRACE_END("pll_lock"); - if (rc) { - mdss_pll_resource_enable(pll, false); - pr_err("pll(%d) enable failed, rc=%d\n", pll->index, rc); - return rc; - } - - return rc; -} - -static unsigned long vco_10nm_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct mdss_pll_resources *pll = vco->priv; - int rc; - u64 ref_clk = vco->ref_clk_rate; - u64 vco_rate; - u64 multiplier; - u32 frac; - u32 dec; - u32 outdiv; - u64 pll_freq, tmp64; - - if (!vco->priv) - pr_err("vco priv is null\n"); - - if (!pll) { - pr_err("pll is null\n"); - return 0; - } - - /* - * Calculate the vco rate from HW registers only for handoff cases. - * For other cases where a vco_10nm_set_rate() has already been - * called, just return the rate that was set earlier. This is due - * to the fact that recalculating VCO rate requires us to read the - * correct value of the pll_out_div divider clock, which is only set - * afterwards. - */ - if (pll->vco_current_rate != 0) { - pr_debug("returning vco rate = %lld\n", pll->vco_current_rate); - return pll->vco_current_rate; - } - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("failed to enable pll(%d) resource, rc=%d\n", - pll->index, rc); - return 0; - } - - if (!dsi_pll_10nm_lock_status(pll)) - pll->handoff_resources = true; - - dec = MDSS_PLL_REG_R(pll->pll_base, PLL_DECIMAL_DIV_START_1); - dec &= 0xFF; - - frac = MDSS_PLL_REG_R(pll->pll_base, PLL_FRAC_DIV_START_LOW_1); - frac |= ((MDSS_PLL_REG_R(pll->pll_base, PLL_FRAC_DIV_START_MID_1) & - 0xFF) << - 8); - frac |= ((MDSS_PLL_REG_R(pll->pll_base, PLL_FRAC_DIV_START_HIGH_1) & - 0x3) << - 16); - - /* OUTDIV_1:0 field is (log(outdiv, 2)) */ - outdiv = MDSS_PLL_REG_R(pll->pll_base, PLL_PLL_OUTDIV_RATE); - outdiv &= 0x3; - outdiv = 1 << outdiv; - - /* - * TODO: - * 1. Assumes prescaler is disabled - * 2. Multiplier is 2^18. it should be 2^(num_of_frac_bits) - **/ - multiplier = 1 << 18; - pll_freq = dec * (ref_clk * 2); - tmp64 = (ref_clk * 2 * frac); - pll_freq += div_u64(tmp64, multiplier); - - vco_rate = div_u64(pll_freq, outdiv); - - pr_debug("dec=0x%x, frac=0x%x, outdiv=%d, vco=%llu\n", - dec, frac, outdiv, vco_rate); - - (void)mdss_pll_resource_enable(pll, false); - - return (unsigned long)vco_rate; -} - -static int pixel_clk_get_div(void *context, unsigned int reg, unsigned int *div) -{ - int rc; - struct mdss_pll_resources *pll = context; - u32 reg_val; - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - reg_val = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0); - *div = (reg_val & 0xF0) >> 4; - - /** - * Common clock framework the divider value is interpreted as one less - * hence we return one less for all dividers except when zero - */ - if (*div != 0) - *div -= 1; - - (void)mdss_pll_resource_enable(pll, false); - - return rc; -} - -static void pixel_clk_set_div_sub(struct mdss_pll_resources *pll, int div) -{ - u32 reg_val; - - reg_val = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0); - reg_val &= ~0xF0; - reg_val |= (div << 4); - MDSS_PLL_REG_W(pll->phy_base, PHY_CMN_CLK_CFG0, reg_val); -} - -static int pixel_clk_set_div(void *context, unsigned int reg, unsigned int div) -{ - int rc; - struct mdss_pll_resources *pll = context; - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - /** - * In common clock framework the divider value provided is one less and - * and hence adjusting the divider value by one prior to writing it to - * hardware - */ - div++; - pixel_clk_set_div_sub(pll, div); - if (pll->slave) - pixel_clk_set_div_sub(pll->slave, div); - (void)mdss_pll_resource_enable(pll, false); - - return 0; -} - -static int bit_clk_get_div(void *context, unsigned int reg, unsigned int *div) -{ - int rc; - struct mdss_pll_resources *pll = context; - u32 reg_val; - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - reg_val = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0); - *div = (reg_val & 0x0F); - - /** - *Common clock framework the divider value is interpreted as one less - * hence we return one less for all dividers except when zero - */ - if (*div != 0) - *div -= 1; - (void)mdss_pll_resource_enable(pll, false); - - return rc; -} - -static void bit_clk_set_div_sub(struct mdss_pll_resources *rsc, int div) -{ - u32 reg_val; - - reg_val = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG0); - reg_val &= ~0x0F; - reg_val |= div; - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CLK_CFG0, reg_val); -} - -static int bit_clk_set_div(void *context, unsigned int reg, unsigned int div) -{ - int rc; - struct mdss_pll_resources *rsc = context; - struct dsi_pll_8998 *pll; - - if (!rsc) { - pr_err("pll resource not found\n"); - return -EINVAL; - } - - pll = rsc->priv; - if (!pll) { - pr_err("pll configuration not found\n"); - return -EINVAL; - } - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - /** - * In common clock framework the divider value provided is one less and - * and hence adjusting the divider value by one prior to writing it to - * hardware - */ - div++; - - bit_clk_set_div_sub(rsc, div); - /* For slave PLL, this divider always should be set to 1 */ - if (rsc->slave) - bit_clk_set_div_sub(rsc->slave, 1); - - (void)mdss_pll_resource_enable(rsc, false); - - return rc; -} - -static struct regmap_config dsi_pll_10nm_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x7c0, -}; - -static struct regmap_bus pll_regmap_bus = { - .reg_write = pll_reg_write, - .reg_read = pll_reg_read, -}; - -static struct regmap_bus pclk_src_mux_regmap_bus = { - .reg_read = pclk_mux_read_sel, - .reg_write = pclk_mux_write_sel, -}; - -static struct regmap_bus pclk_src_regmap_bus = { - .reg_write = pixel_clk_set_div, - .reg_read = pixel_clk_get_div, -}; - -static struct regmap_bus bitclk_src_regmap_bus = { - .reg_write = bit_clk_set_div, - .reg_read = bit_clk_get_div, -}; - -static const struct clk_ops clk_ops_vco_10nm = { - .recalc_rate = vco_10nm_recalc_rate, - .set_rate = vco_10nm_set_rate, - .round_rate = vco_10nm_round_rate, - .prepare = vco_10nm_prepare, - .unprepare = vco_10nm_unprepare, -}; - -static struct regmap_bus mdss_mux_regmap_bus = { - .reg_write = mdss_set_mux_sel, - .reg_read = mdss_get_mux_sel, -}; - -/* - * Clock tree for generating DSI byte and pixel clocks. - * - * - * +---------------+ - * | vco_clk | - * +-------+-------+ - * | - * | - * +---------------+ - * | pll_out_div | - * | DIV(1,2,4,8) | - * +-------+-------+ - * | - * +-----------------------------+--------+ - * | | | - * +-------v-------+ | | - * | bitclk_src | | | - * | DIV(1..15) | | | - * +-------+-------+ | | - * | | | - * +----------+---------+ | | - * Shadow Path | | | | | - * + +-------v-------+ | +------v------+ | +------v-------+ - * | | byteclk_src | | |post_bit_div | | |post_vco_div | - * | | DIV(8) | | |DIV (2) | | |DIV(4) | - * | +-------+-------+ | +------+------+ | +------+-------+ - * | | | | | | | - * | | | +------+ | | - * | | +-------------+ | | +----+ - * | +--------+ | | | | - * | | +-v--v-v---v------+ - * +-v---------v----+ \ pclk_src_mux / - * \ byteclk_mux / \ / - * \ / +-----+-----+ - * +----+-----+ | Shadow Path - * | | + - * v +-----v------+ | - * dsi_byte_clk | pclk_src | | - * | DIV(1..15) | | - * +-----+------+ | - * | | - * | | - * +--------+ | - * | | - * +---v----v----+ - * \ pclk_mux / - * \ / - * +---+---+ - * | - * | - * v - * dsi_pclk - * - */ - -static struct dsi_pll_vco_clk dsi0pll_vco_clk = { - .ref_clk_rate = 19200000UL, - .min_rate = 1000000000UL, - .max_rate = 3500000000UL, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_vco_clk", - .parent_names = (const char *[]){"bi_tcxo"}, - .num_parents = 1, - .ops = &clk_ops_vco_10nm, - .flags = CLK_GET_RATE_NOCACHE, - }, -}; - -static struct dsi_pll_vco_clk dsi1pll_vco_clk = { - .ref_clk_rate = 19200000UL, - .min_rate = 1000000000UL, - .max_rate = 3500000000UL, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_vco_clk", - .parent_names = (const char *[]){"bi_tcxo"}, - .num_parents = 1, - .ops = &clk_ops_vco_10nm, - .flags = CLK_GET_RATE_NOCACHE, - }, -}; - -static struct clk_regmap_div dsi0pll_pll_out_div = { - .reg = PLL_PLL_OUTDIV_RATE, - .shift = 0, - .width = 2, - .flags = CLK_DIVIDER_POWER_OF_TWO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_pll_out_div", - .parent_names = (const char *[]){"dsi0pll_vco_clk"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_pll_out_div = { - .reg = PLL_PLL_OUTDIV_RATE, - .shift = 0, - .width = 2, - .flags = CLK_DIVIDER_POWER_OF_TWO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_pll_out_div", - .parent_names = (const char *[]){"dsi1pll_vco_clk"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi0pll_bitclk_src = { - .shift = 0, - .width = 4, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_bitclk_src", - .parent_names = (const char *[]){"dsi0pll_pll_out_div"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_bitclk_src = { - .shift = 0, - .width = 4, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_bitclk_src", - .parent_names = (const char *[]){"dsi1pll_pll_out_div"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_fixed_factor dsi0pll_post_vco_div = { - .div = 4, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_post_vco_div", - .parent_names = (const char *[]){"dsi0pll_pll_out_div"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_post_vco_div = { - .div = 4, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_post_vco_div", - .parent_names = (const char *[]){"dsi1pll_pll_out_div"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi0pll_byteclk_src = { - .div = 8, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_byteclk_src", - .parent_names = (const char *[]){"dsi0pll_bitclk_src"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_byteclk_src = { - .div = 8, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_byteclk_src", - .parent_names = (const char *[]){"dsi1pll_bitclk_src"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi0pll_post_bit_div = { - .div = 2, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_post_bit_div", - .parent_names = (const char *[]){"dsi0pll_bitclk_src"}, - .num_parents = 1, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_post_bit_div = { - .div = 2, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_post_bit_div", - .parent_names = (const char *[]){"dsi1pll_bitclk_src"}, - .num_parents = 1, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_regmap_mux dsi0pll_byteclk_mux = { - .shift = 0, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0_phy_pll_out_byteclk", - .parent_names = (const char *[]){"dsi0pll_byteclk_src"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi1pll_byteclk_mux = { - .shift = 0, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1_phy_pll_out_byteclk", - .parent_names = (const char *[]){"dsi1pll_byteclk_src"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi0pll_pclk_src_mux = { - .reg = PHY_CMN_CLK_CFG1, - .shift = 0, - .width = 2, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_pclk_src_mux", - .parent_names = (const char *[]){"dsi0pll_bitclk_src", - "dsi0pll_post_bit_div", - "dsi0pll_pll_out_div", - "dsi0pll_post_vco_div"}, - .num_parents = 4, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi1pll_pclk_src_mux = { - .reg = PHY_CMN_CLK_CFG1, - .shift = 0, - .width = 2, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_pclk_src_mux", - .parent_names = (const char *[]){"dsi1pll_bitclk_src", - "dsi1pll_post_bit_div", - "dsi1pll_pll_out_div", - "dsi1pll_post_vco_div"}, - .num_parents = 4, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_div dsi0pll_pclk_src = { - .shift = 0, - .width = 4, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_pclk_src", - .parent_names = (const char *[]){ - "dsi0pll_pclk_src_mux"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_pclk_src = { - .shift = 0, - .width = 4, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_pclk_src", - .parent_names = (const char *[]){ - "dsi1pll_pclk_src_mux"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi0pll_pclk_mux = { - .shift = 0, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0_phy_pll_out_dsiclk", - .parent_names = (const char *[]){"dsi0pll_pclk_src"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi1pll_pclk_mux = { - .shift = 0, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1_phy_pll_out_dsiclk", - .parent_names = (const char *[]){"dsi1pll_pclk_src"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_hw *mdss_dsi_pllcc_10nm[] = { - [VCO_CLK_0] = &dsi0pll_vco_clk.hw, - [PLL_OUT_DIV_0_CLK] = &dsi0pll_pll_out_div.clkr.hw, - [BITCLK_SRC_0_CLK] = &dsi0pll_bitclk_src.clkr.hw, - [BYTECLK_SRC_0_CLK] = &dsi0pll_byteclk_src.hw, - [POST_BIT_DIV_0_CLK] = &dsi0pll_post_bit_div.hw, - [POST_VCO_DIV_0_CLK] = &dsi0pll_post_vco_div.hw, - [BYTECLK_MUX_0_CLK] = &dsi0pll_byteclk_mux.clkr.hw, - [PCLK_SRC_MUX_0_CLK] = &dsi0pll_pclk_src_mux.clkr.hw, - [PCLK_SRC_0_CLK] = &dsi0pll_pclk_src.clkr.hw, - [PCLK_MUX_0_CLK] = &dsi0pll_pclk_mux.clkr.hw, - [VCO_CLK_1] = &dsi1pll_vco_clk.hw, - [PLL_OUT_DIV_1_CLK] = &dsi1pll_pll_out_div.clkr.hw, - [BITCLK_SRC_1_CLK] = &dsi1pll_bitclk_src.clkr.hw, - [BYTECLK_SRC_1_CLK] = &dsi1pll_byteclk_src.hw, - [POST_BIT_DIV_1_CLK] = &dsi1pll_post_bit_div.hw, - [POST_VCO_DIV_1_CLK] = &dsi1pll_post_vco_div.hw, - [BYTECLK_MUX_1_CLK] = &dsi1pll_byteclk_mux.clkr.hw, - [PCLK_SRC_MUX_1_CLK] = &dsi1pll_pclk_src_mux.clkr.hw, - [PCLK_SRC_1_CLK] = &dsi1pll_pclk_src.clkr.hw, - [PCLK_MUX_1_CLK] = &dsi1pll_pclk_mux.clkr.hw, -}; - -int dsi_pll_clock_register_10nm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int rc = 0, ndx, i; - struct clk *clk; - struct clk_onecell_data *clk_data; - int num_clks = ARRAY_SIZE(mdss_dsi_pllcc_10nm); - struct regmap *rmap; - - ndx = pll_res->index; - - if (ndx >= DSI_PLL_MAX) { - pr_err("pll index(%d) NOT supported\n", ndx); - return -EINVAL; - } - - pll_rsc_db[ndx] = pll_res; - plls[ndx].rsc = pll_res; - pll_res->priv = &plls[ndx]; - pll_res->vco_delay = VCO_DELAY_USEC; - - clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL); - if (!clk_data) - return -ENOMEM; - - clk_data->clks = devm_kcalloc(&pdev->dev, num_clks, - sizeof(struct clk *), GFP_KERNEL); - if (!clk_data->clks) - return -ENOMEM; - - clk_data->clk_num = num_clks; - - /* Establish client data */ - if (ndx == 0) { - - rmap = devm_regmap_init(&pdev->dev, &pll_regmap_bus, - pll_res, &dsi_pll_10nm_config); - dsi0pll_pll_out_div.clkr.regmap = rmap; - - rmap = devm_regmap_init(&pdev->dev, &bitclk_src_regmap_bus, - pll_res, &dsi_pll_10nm_config); - dsi0pll_bitclk_src.clkr.regmap = rmap; - - rmap = devm_regmap_init(&pdev->dev, &pclk_src_regmap_bus, - pll_res, &dsi_pll_10nm_config); - dsi0pll_pclk_src.clkr.regmap = rmap; - - rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus, - pll_res, &dsi_pll_10nm_config); - dsi0pll_pclk_mux.clkr.regmap = rmap; - - rmap = devm_regmap_init(&pdev->dev, &pclk_src_mux_regmap_bus, - pll_res, &dsi_pll_10nm_config); - dsi0pll_pclk_src_mux.clkr.regmap = rmap; - rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus, - pll_res, &dsi_pll_10nm_config); - dsi0pll_byteclk_mux.clkr.regmap = rmap; - - dsi0pll_vco_clk.priv = pll_res; - for (i = VCO_CLK_0; i <= PCLK_MUX_0_CLK; i++) { - clk = devm_clk_register(&pdev->dev, - mdss_dsi_pllcc_10nm[i]); - if (IS_ERR(clk)) { - pr_err("clk registration failed for DSI clock:%d\n", - pll_res->index); - rc = -EINVAL; - goto clk_register_fail; - } - clk_data->clks[i] = clk; - - } - - rc = of_clk_add_provider(pdev->dev.of_node, - of_clk_src_onecell_get, clk_data); - - - } else { - rmap = devm_regmap_init(&pdev->dev, &pll_regmap_bus, - pll_res, &dsi_pll_10nm_config); - dsi1pll_pll_out_div.clkr.regmap = rmap; - - rmap = devm_regmap_init(&pdev->dev, &bitclk_src_regmap_bus, - pll_res, &dsi_pll_10nm_config); - dsi1pll_bitclk_src.clkr.regmap = rmap; - - rmap = devm_regmap_init(&pdev->dev, &pclk_src_regmap_bus, - pll_res, &dsi_pll_10nm_config); - dsi1pll_pclk_src.clkr.regmap = rmap; - - rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus, - pll_res, &dsi_pll_10nm_config); - dsi1pll_pclk_mux.clkr.regmap = rmap; - - rmap = devm_regmap_init(&pdev->dev, &pclk_src_mux_regmap_bus, - pll_res, &dsi_pll_10nm_config); - dsi1pll_pclk_src_mux.clkr.regmap = rmap; - rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus, - pll_res, &dsi_pll_10nm_config); - dsi1pll_byteclk_mux.clkr.regmap = rmap; - dsi1pll_vco_clk.priv = pll_res; - - for (i = VCO_CLK_1; i <= PCLK_MUX_1_CLK; i++) { - clk = devm_clk_register(&pdev->dev, - mdss_dsi_pllcc_10nm[i]); - if (IS_ERR(clk)) { - pr_err("clk registration failed for DSI clock:%d\n", - pll_res->index); - rc = -EINVAL; - goto clk_register_fail; - } - clk_data->clks[i] = clk; - - } - - rc = of_clk_add_provider(pdev->dev.of_node, - of_clk_src_onecell_get, clk_data); - } - if (!rc) { - pr_info("Registered DSI PLL ndx=%d, clocks successfully\n", - ndx); - - return rc; - } -clk_register_fail: - return rc; -} diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm-util.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm-util.c deleted file mode 100644 index 455d2c0ea24b21c0b4b24776b2d83bf8719067d8..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm-util.c +++ /dev/null @@ -1,1148 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include - -#include "mdss-pll.h" -#include "mdss-dsi-pll.h" -#include "mdss-dsi-pll-14nm.h" - -#define DSI_PLL_POLL_MAX_READS 15 -#define DSI_PLL_POLL_TIMEOUT_US 1000 -#define MSM8996_DSI_PLL_REVISION_2 2 - -#define VCO_REF_CLK_RATE 19200000 - -#define CEIL(x, y) (((x) + ((y)-1)) / (y)) - -static int mdss_pll_read_stored_trim_codes( - struct mdss_pll_resources *dsi_pll_res, s64 vco_clk_rate) -{ - int i; - int rc = 0; - bool found = false; - - if (!dsi_pll_res->dfps) { - rc = -EINVAL; - goto end_read; - } - - for (i = 0; i < dsi_pll_res->dfps->panel_dfps.frame_rate_cnt; i++) { - struct dfps_codes_info *codes_info = - &dsi_pll_res->dfps->codes_dfps[i]; - - pr_debug("valid=%d frame_rate=%d, vco_rate=%d, code %d %d\n", - codes_info->is_valid, codes_info->frame_rate, - codes_info->clk_rate, codes_info->pll_codes.pll_codes_1, - codes_info->pll_codes.pll_codes_2); - - if (vco_clk_rate != codes_info->clk_rate && - codes_info->is_valid) - continue; - - dsi_pll_res->cache_pll_trim_codes[0] = - codes_info->pll_codes.pll_codes_1; - dsi_pll_res->cache_pll_trim_codes[1] = - codes_info->pll_codes.pll_codes_2; - found = true; - break; - } - - if (!found) { - rc = -EINVAL; - goto end_read; - } - - pr_debug("core_kvco_code=0x%x core_vco_tune=0x%x\n", - dsi_pll_res->cache_pll_trim_codes[0], - dsi_pll_res->cache_pll_trim_codes[1]); - -end_read: - return rc; -} - -int post_n1_div_set_div(void *context, unsigned int reg, unsigned int div) -{ - struct mdss_pll_resources *pll = context; - struct dsi_pll_db *pdb; - struct dsi_pll_output *pout; - int rc; - u32 n1div = 0; - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - /* in common clock framework the divider value provided is one less */ - div++; - - pdb = (struct dsi_pll_db *)pll->priv; - pout = &pdb->out; - - /* - * vco rate = bit_clk * postdiv * n1div - * vco range from 1300 to 2600 Mhz - * postdiv = 1 - * n1div = 1 to 15 - * n1div = roundup(1300Mhz / bit_clk) - * support bit_clk above 86.67Mhz - */ - - pout->pll_n1div = div; - - n1div = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_CMN_CLK_CFG0); - n1div &= ~0xf; - n1div |= (div & 0xf); - MDSS_PLL_REG_W(pll->pll_base, DSIPHY_CMN_CLK_CFG0, n1div); - /* ensure n1 divider is programed */ - wmb(); - pr_debug("ndx=%d div=%d postdiv=%x n1div=%x\n", - pll->index, div, pout->pll_postdiv, pout->pll_n1div); - - mdss_pll_resource_enable(pll, false); - - return 0; -} - -int post_n1_div_get_div(void *context, unsigned int reg, unsigned int *div) -{ - int rc; - struct mdss_pll_resources *pll = context; - struct dsi_pll_db *pdb; - struct dsi_pll_output *pout; - - pdb = (struct dsi_pll_db *)pll->priv; - pout = &pdb->out; - - if (is_gdsc_disabled(pll)) - return 0; - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - /* - * postdiv = 1/2/4/8 - * n1div = 1 - 15 - * fot the time being, assume postdiv = 1 - */ - - *div = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_CMN_CLK_CFG0); - *div &= 0xF; - - /* - * initialize n1div here, it will get updated when - * corresponding set_div is called. - */ - pout->pll_n1div = *div; - - /* common clock framework will add one to the divider value sent */ - if (*div == 0) - *div = 1; /* value of zero means div is 2 as per SWI */ - else - *div -= 1; - - pr_debug("post n1 get div = %d\n", *div); - - mdss_pll_resource_enable(pll, false); - - return rc; -} - -int n2_div_set_div(void *context, unsigned int reg, unsigned int div) -{ - int rc; - u32 n2div; - struct mdss_pll_resources *pll = context; - struct dsi_pll_db *pdb; - struct dsi_pll_output *pout; - struct mdss_pll_resources *slave; - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - /* - * in common clock framework the actual divider value - * provided is one less. - */ - div++; - - pdb = (struct dsi_pll_db *)pll->priv; - pout = &pdb->out; - - /* this is for pixel clock */ - n2div = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_CMN_CLK_CFG0); - n2div &= ~0xf0; /* bits 4 to 7 */ - n2div |= (div << 4); - MDSS_PLL_REG_W(pll->pll_base, DSIPHY_CMN_CLK_CFG0, n2div); - - /* commit slave if split display is enabled */ - slave = pll->slave; - if (slave) - MDSS_PLL_REG_W(slave->pll_base, DSIPHY_CMN_CLK_CFG0, n2div); - - pout->pll_n2div = div; - - /* set dsiclk_sel=1 so that n2div *= 2 */ - MDSS_PLL_REG_W(pll->pll_base, DSIPHY_CMN_CLK_CFG1, 1); - pr_debug("ndx=%d div=%d n2div=%x\n", pll->index, div, n2div); - - mdss_pll_resource_enable(pll, false); - - return rc; -} - -int shadow_n2_div_set_div(void *context, unsigned int reg, unsigned int div) -{ - struct mdss_pll_resources *pll = context; - struct dsi_pll_db *pdb; - struct dsi_pll_output *pout; - u32 data; - - pdb = pll->priv; - pout = &pdb->out; - - /* - * in common clock framework the actual divider value - * provided is one less. - */ - div++; - - pout->pll_n2div = div; - - data = (pout->pll_n1div | (pout->pll_n2div << 4)); - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL19, - DSIPHY_CMN_CLK_CFG0, DSIPHY_CMN_CLK_CFG1, - data, 1); - return 0; -} - -int n2_div_get_div(void *context, unsigned int reg, unsigned int *div) -{ - int rc; - u32 n2div; - struct mdss_pll_resources *pll = context; - struct dsi_pll_db *pdb; - struct dsi_pll_output *pout; - - if (is_gdsc_disabled(pll)) - return 0; - - pdb = (struct dsi_pll_db *)pll->priv; - pout = &pdb->out; - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll=%d resources\n", - pll->index); - return rc; - } - - n2div = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_CMN_CLK_CFG0); - n2div >>= 4; - n2div &= 0x0f; - /* - * initialize n2div here, it will get updated when - * corresponding set_div is called. - */ - pout->pll_n2div = n2div; - mdss_pll_resource_enable(pll, false); - - *div = n2div; - - /* common clock framework will add one to the divider value sent */ - if (*div == 0) - *div = 1; /* value of zero means div is 2 as per SWI */ - else - *div -= 1; - - pr_debug("ndx=%d div=%d\n", pll->index, *div); - - return rc; -} - -static bool pll_is_pll_locked_14nm(struct mdss_pll_resources *pll) -{ - u32 status; - bool pll_locked; - - /* poll for PLL ready status */ - if (readl_poll_timeout_atomic((pll->pll_base + - DSIPHY_PLL_RESET_SM_READY_STATUS), - status, - ((status & BIT(5)) > 0), - DSI_PLL_POLL_MAX_READS, - DSI_PLL_POLL_TIMEOUT_US)) { - pr_err("DSI PLL ndx=%d status=%x failed to Lock\n", - pll->index, status); - pll_locked = false; - } else if (readl_poll_timeout_atomic((pll->pll_base + - DSIPHY_PLL_RESET_SM_READY_STATUS), - status, - ((status & BIT(0)) > 0), - DSI_PLL_POLL_MAX_READS, - DSI_PLL_POLL_TIMEOUT_US)) { - pr_err("DSI PLL ndx=%d status=%x PLl not ready\n", - pll->index, status); - pll_locked = false; - } else { - pll_locked = true; - } - - return pll_locked; -} - -static void dsi_pll_start_14nm(void __iomem *pll_base) -{ - pr_debug("start PLL at base=%pK\n", pll_base); - - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_VREF_CFG1, 0x10); - MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_PLL_CNTRL, 1); -} - -static void dsi_pll_stop_14nm(void __iomem *pll_base) -{ - pr_debug("stop PLL at base=%pK\n", pll_base); - - MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_PLL_CNTRL, 0); -} - -int dsi_pll_enable_seq_14nm(struct mdss_pll_resources *pll) -{ - int rc = 0; - - if (!pll) { - pr_err("Invalid PLL resources\n"); - return -EINVAL; - } - - dsi_pll_start_14nm(pll->pll_base); - - /* - * both DSIPHY_PLL_CLKBUFLR_EN and DSIPHY_CMN_GLBL_TEST_CTRL - * enabled at mdss_dsi_14nm_phy_config() - */ - - if (!pll_is_pll_locked_14nm(pll)) { - pr_err("DSI PLL ndx=%d lock failed\n", pll->index); - rc = -EINVAL; - goto init_lock_err; - } - - pr_debug("DSI PLL ndx=%d Lock success\n", pll->index); - -init_lock_err: - return rc; -} - -static int dsi_pll_enable(struct clk_hw *hw) -{ - int i, rc = 0; - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct mdss_pll_resources *pll = vco->priv; - - /* Try all enable sequences until one succeeds */ - for (i = 0; i < vco->pll_en_seq_cnt; i++) { - rc = vco->pll_enable_seqs[i](pll); - pr_debug("DSI PLL %s after sequence #%d\n", - rc ? "unlocked" : "locked", i + 1); - if (!rc) - break; - } - - if (rc) - pr_err("ndx=%d DSI PLL failed to lock\n", pll->index); - else - pll->pll_on = true; - - return rc; -} - -static void dsi_pll_disable(struct clk_hw *hw) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct mdss_pll_resources *pll = vco->priv; - struct mdss_pll_resources *slave; - - if (!pll->pll_on && - mdss_pll_resource_enable(pll, true)) { - pr_err("Failed to enable mdss dsi pll=%d\n", pll->index); - return; - } - - pll->handoff_resources = false; - slave = pll->slave; - - dsi_pll_stop_14nm(pll->pll_base); - - mdss_pll_resource_enable(pll, false); - - pll->pll_on = false; - - pr_debug("DSI PLL ndx=%d Disabled\n", pll->index); -} - -static void mdss_dsi_pll_14nm_input_init(struct mdss_pll_resources *pll, - struct dsi_pll_db *pdb) -{ - pdb->in.fref = 19200000; /* 19.2 Mhz*/ - pdb->in.fdata = 0; /* bit clock rate */ - pdb->in.dsiclk_sel = 1; /* 1, reg: 0x0014 */ - pdb->in.ssc_en = pll->ssc_en; /* 1, reg: 0x0494, bit 0 */ - pdb->in.ldo_en = 0; /* 0, reg: 0x004c, bit 0 */ - - /* fixed input */ - pdb->in.refclk_dbler_en = 0; /* 0, reg: 0x04c0, bit 1 */ - pdb->in.vco_measure_time = 5; /* 5, unknown */ - pdb->in.kvco_measure_time = 5; /* 5, unknown */ - pdb->in.bandgap_timer = 4; /* 4, reg: 0x0430, bit 3 - 5 */ - pdb->in.pll_wakeup_timer = 5; /* 5, reg: 0x043c, bit 0 - 2 */ - pdb->in.plllock_cnt = 1; /* 1, reg: 0x0488, bit 1 - 2 */ - pdb->in.plllock_rng = 0; /* 0, reg: 0x0488, bit 3 - 4 */ - pdb->in.ssc_center = pll->ssc_center;/* 0, reg: 0x0494, bit 1 */ - pdb->in.ssc_adj_period = 37; /* 37, reg: 0x498, bit 0 - 9 */ - pdb->in.ssc_spread = pll->ssc_ppm / 1000; - pdb->in.ssc_freq = pll->ssc_freq; - - pdb->in.pll_ie_trim = 4; /* 4, reg: 0x0400 */ - pdb->in.pll_ip_trim = 4; /* 4, reg: 0x0404 */ - pdb->in.pll_cpcset_cur = 1; /* 1, reg: 0x04f0, bit 0 - 2 */ - pdb->in.pll_cpmset_cur = 1; /* 1, reg: 0x04f0, bit 3 - 5 */ - pdb->in.pll_icpmset = 4; /* 4, reg: 0x04fc, bit 3 - 5 */ - pdb->in.pll_icpcset = 4; /* 4, reg: 0x04fc, bit 0 - 2 */ - pdb->in.pll_icpmset_p = 0; /* 0, reg: 0x04f4, bit 0 - 2 */ - pdb->in.pll_icpmset_m = 0; /* 0, reg: 0x04f4, bit 3 - 5 */ - pdb->in.pll_icpcset_p = 0; /* 0, reg: 0x04f8, bit 0 - 2 */ - pdb->in.pll_icpcset_m = 0; /* 0, reg: 0x04f8, bit 3 - 5 */ - pdb->in.pll_lpf_res1 = 3; /* 3, reg: 0x0504, bit 0 - 3 */ - pdb->in.pll_lpf_cap1 = 11; /* 11, reg: 0x0500, bit 0 - 3 */ - pdb->in.pll_lpf_cap2 = 1; /* 1, reg: 0x0500, bit 4 - 7 */ - pdb->in.pll_iptat_trim = 7; - pdb->in.pll_c3ctrl = 2; /* 2 */ - pdb->in.pll_r3ctrl = 1; /* 1 */ - pdb->out.pll_postdiv = 1; -} - -static void pll_14nm_ssc_calc(struct mdss_pll_resources *pll, - struct dsi_pll_db *pdb) -{ - u32 period, ssc_period; - u32 ref, rem; - s64 step_size; - - pr_debug("%s: vco=%lld ref=%lld\n", __func__, - pll->vco_current_rate, pll->vco_ref_clk_rate); - - ssc_period = pdb->in.ssc_freq / 500; - period = (unsigned long)pll->vco_ref_clk_rate / 1000; - ssc_period = CEIL(period, ssc_period); - ssc_period -= 1; - pdb->out.ssc_period = ssc_period; - - pr_debug("%s: ssc, freq=%d spread=%d period=%d\n", __func__, - pdb->in.ssc_freq, pdb->in.ssc_spread, pdb->out.ssc_period); - - step_size = (u32)pll->vco_current_rate; - ref = pll->vco_ref_clk_rate; - ref /= 1000; - step_size = div_s64(step_size, ref); - step_size <<= 20; - step_size = div_s64(step_size, 1000); - step_size *= pdb->in.ssc_spread; - step_size = div_s64(step_size, 1000); - step_size *= (pdb->in.ssc_adj_period + 1); - - rem = 0; - step_size = div_s64_rem(step_size, ssc_period + 1, &rem); - if (rem) - step_size++; - - pr_debug("%s: step_size=%lld\n", __func__, step_size); - - step_size &= 0x0ffff; /* take lower 16 bits */ - - pdb->out.ssc_step_size = step_size; -} - -static void pll_14nm_dec_frac_calc(struct mdss_pll_resources *pll, - struct dsi_pll_db *pdb) -{ - struct dsi_pll_input *pin = &pdb->in; - struct dsi_pll_output *pout = &pdb->out; - u64 multiplier = BIT(20); - u64 dec_start_multiple, dec_start, pll_comp_val; - s32 duration, div_frac_start; - s64 vco_clk_rate = pll->vco_current_rate; - s64 fref = pll->vco_ref_clk_rate; - - pr_debug("vco_clk_rate=%lld ref_clk_rate=%lld\n", - vco_clk_rate, fref); - - dec_start_multiple = div_s64(vco_clk_rate * multiplier, fref); - div_s64_rem(dec_start_multiple, multiplier, &div_frac_start); - - dec_start = div_s64(dec_start_multiple, multiplier); - - pout->dec_start = (u32)dec_start; - pout->div_frac_start = div_frac_start; - - if (pin->plllock_cnt == 0) - duration = 1024; - else if (pin->plllock_cnt == 1) - duration = 256; - else if (pin->plllock_cnt == 2) - duration = 128; - else - duration = 32; - - pll_comp_val = duration * dec_start_multiple; - pll_comp_val = div_u64(pll_comp_val, multiplier); - do_div(pll_comp_val, 10); - - pout->plllock_cmp = (u32)pll_comp_val; - - pout->pll_txclk_en = 1; - if (pll->revision == MSM8996_DSI_PLL_REVISION_2) - pout->cmn_ldo_cntrl = 0x3c; - else - pout->cmn_ldo_cntrl = 0x1c; -} - -static u32 pll_14nm_kvco_slop(u32 vrate) -{ - u32 slop = 0; - - if (vrate > 1300000000UL && vrate <= 1800000000UL) - slop = 600; - else if (vrate > 1800000000UL && vrate < 2300000000UL) - slop = 400; - else if (vrate > 2300000000UL && vrate < 2600000000UL) - slop = 280; - - return slop; -} - -static void pll_14nm_calc_vco_count(struct dsi_pll_db *pdb, - s64 vco_clk_rate, s64 fref) -{ - struct dsi_pll_input *pin = &pdb->in; - struct dsi_pll_output *pout = &pdb->out; - u64 data; - u32 cnt; - - data = fref * pin->vco_measure_time; - do_div(data, 1000000); - data &= 0x03ff; /* 10 bits */ - data -= 2; - pout->pll_vco_div_ref = data; - - data = (unsigned long)vco_clk_rate / 1000000; /* unit is Mhz */ - data *= pin->vco_measure_time; - do_div(data, 10); - pout->pll_vco_count = data; /* reg: 0x0474, 0x0478 */ - - data = fref * pin->kvco_measure_time; - do_div(data, 1000000); - data &= 0x03ff; /* 10 bits */ - data -= 1; - pout->pll_kvco_div_ref = data; - - cnt = pll_14nm_kvco_slop(vco_clk_rate); - cnt *= 2; - cnt /= 100; - cnt *= pin->kvco_measure_time; - pout->pll_kvco_count = cnt; - - pout->pll_misc1 = 16; - pout->pll_resetsm_cntrl = 48; - pout->pll_resetsm_cntrl2 = pin->bandgap_timer << 3; - pout->pll_resetsm_cntrl5 = pin->pll_wakeup_timer; - pout->pll_kvco_code = 0; -} - -static void pll_db_commit_ssc(struct mdss_pll_resources *pll, - struct dsi_pll_db *pdb) -{ - void __iomem *pll_base = pll->pll_base; - struct dsi_pll_input *pin = &pdb->in; - struct dsi_pll_output *pout = &pdb->out; - char data; - - data = pin->ssc_adj_period; - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_ADJ_PER1, data); - data = (pin->ssc_adj_period >> 8); - data &= 0x03; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_ADJ_PER2, data); - - data = pout->ssc_period; - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_PER1, data); - data = (pout->ssc_period >> 8); - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_PER2, data); - - data = pout->ssc_step_size; - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_STEP_SIZE1, data); - data = (pout->ssc_step_size >> 8); - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_STEP_SIZE2, data); - - data = (pin->ssc_center & 0x01); - data <<= 1; - data |= 0x01; /* enable */ - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_EN_CENTER, data); - - wmb(); /* make sure register committed */ -} - -static void pll_db_commit_common(struct mdss_pll_resources *pll, - struct dsi_pll_db *pdb) -{ - void __iomem *pll_base = pll->pll_base; - struct dsi_pll_input *pin = &pdb->in; - struct dsi_pll_output *pout = &pdb->out; - char data; - - /* confgiure the non frequency dependent pll registers */ - data = 0; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SYSCLK_EN_RESET, data); - - /* DSIPHY_PLL_CLKBUFLR_EN updated at dsi phy */ - - data = pout->pll_txclk_en; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_TXCLK_EN, data); - - data = pout->pll_resetsm_cntrl; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_RESETSM_CNTRL, data); - data = pout->pll_resetsm_cntrl2; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_RESETSM_CNTRL2, data); - data = pout->pll_resetsm_cntrl5; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_RESETSM_CNTRL5, data); - - data = pout->pll_vco_div_ref; - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_VCO_DIV_REF1, data); - data = (pout->pll_vco_div_ref >> 8); - data &= 0x03; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_VCO_DIV_REF2, data); - - data = pout->pll_kvco_div_ref; - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_KVCO_DIV_REF1, data); - data = (pout->pll_kvco_div_ref >> 8); - data &= 0x03; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_KVCO_DIV_REF2, data); - - data = pout->pll_misc1; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLL_MISC1, data); - - data = pin->pll_ie_trim; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_IE_TRIM, data); - - data = pin->pll_ip_trim; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_IP_TRIM, data); - - data = ((pin->pll_cpmset_cur << 3) | pin->pll_cpcset_cur); - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_CP_SET_CUR, data); - - data = ((pin->pll_icpcset_p << 3) | pin->pll_icpcset_m); - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLL_ICPCSET, data); - - data = ((pin->pll_icpmset_p << 3) | pin->pll_icpcset_m); - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLL_ICPMSET, data); - - data = ((pin->pll_icpmset << 3) | pin->pll_icpcset); - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLL_ICP_SET, data); - - data = ((pdb->in.pll_lpf_cap2 << 4) | pdb->in.pll_lpf_cap1); - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLL_LPF1, data); - - data = pin->pll_iptat_trim; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_IPTAT_TRIM, data); - - data = (pdb->in.pll_c3ctrl | (pdb->in.pll_r3ctrl << 4)); - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLL_CRCTRL, data); -} - -static void pll_db_commit_14nm(struct mdss_pll_resources *pll, - struct dsi_pll_db *pdb) -{ - void __iomem *pll_base = pll->pll_base; - struct dsi_pll_input *pin = &pdb->in; - struct dsi_pll_output *pout = &pdb->out; - char data; - - data = pout->cmn_ldo_cntrl; - MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_LDO_CNTRL, data); - - pll_db_commit_common(pll, pdb); - - /* de assert pll start and apply pll sw reset */ - /* stop pll */ - MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_PLL_CNTRL, 0); - - /* pll sw reset */ - MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_CTRL_1, 0x20); - wmb(); /* make sure register committed */ - udelay(10); - - MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_CTRL_1, 0); - wmb(); /* make sure register committed */ - - data = pdb->in.dsiclk_sel; /* set dsiclk_sel = 1 */ - MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_CLK_CFG1, data); - - data = 0xff; /* data, clk, pll normal operation */ - MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_CTRL_0, data); - - /* confgiure the frequency dependent pll registers */ - data = pout->dec_start; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_DEC_START, data); - - data = pout->div_frac_start; - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_DIV_FRAC_START1, data); - data = (pout->div_frac_start >> 8); - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_DIV_FRAC_START2, data); - data = (pout->div_frac_start >> 16); - data &= 0x0f; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_DIV_FRAC_START3, data); - - data = pout->plllock_cmp; - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLLLOCK_CMP1, data); - data = (pout->plllock_cmp >> 8); - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLLLOCK_CMP2, data); - data = (pout->plllock_cmp >> 16); - data &= 0x03; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLLLOCK_CMP3, data); - - data = ((pin->plllock_cnt << 1) | (pin->plllock_rng << 3)); - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLLLOCK_CMP_EN, data); - - data = pout->pll_vco_count; - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_VCO_COUNT1, data); - data = (pout->pll_vco_count >> 8); - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_VCO_COUNT2, data); - - data = pout->pll_kvco_count; - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_KVCO_COUNT1, data); - data = (pout->pll_kvco_count >> 8); - data &= 0x03; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_KVCO_COUNT2, data); - - /* - * tx_band = pll_postdiv - * 0: divided by 1 <== for now - * 1: divided by 2 - * 2: divided by 4 - * 3: divided by 8 - */ - data = (((pout->pll_postdiv - 1) << 4) | pdb->in.pll_lpf_res1); - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLL_LPF2_POSTDIV, data); - - data = (pout->pll_n1div | (pout->pll_n2div << 4)); - MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_CLK_CFG0, data); - - if (pll->ssc_en) - pll_db_commit_ssc(pll, pdb); - - wmb(); /* make sure register committed */ -} - -/* - * pll_source_finding: - * Both GLBL_TEST_CTRL and CLKBUFLR_EN are configured - * at mdss_dsi_14nm_phy_config() - */ -static int pll_source_finding(struct mdss_pll_resources *pll) -{ - u32 clk_buf_en; - u32 glbl_test_ctrl; - - glbl_test_ctrl = MDSS_PLL_REG_R(pll->pll_base, - DSIPHY_CMN_GLBL_TEST_CTRL); - clk_buf_en = MDSS_PLL_REG_R(pll->pll_base, - DSIPHY_PLL_CLKBUFLR_EN); - - glbl_test_ctrl &= BIT(2); - glbl_test_ctrl >>= 2; - - pr_debug("%s: pll=%d clk_buf_en=%x glbl_test_ctrl=%x\n", - __func__, pll->index, clk_buf_en, glbl_test_ctrl); - - clk_buf_en &= (PLL_OUTPUT_RIGHT | PLL_OUTPUT_LEFT); - - if ((glbl_test_ctrl == PLL_SOURCE_FROM_LEFT) && - (clk_buf_en == PLL_OUTPUT_BOTH)) - return PLL_MASTER; - - if ((glbl_test_ctrl == PLL_SOURCE_FROM_RIGHT) && - (clk_buf_en == PLL_OUTPUT_NONE)) - return PLL_SLAVE; - - if ((glbl_test_ctrl == PLL_SOURCE_FROM_LEFT) && - (clk_buf_en == PLL_OUTPUT_RIGHT)) - return PLL_STANDALONE; - - pr_debug("%s: Error pll setup, clk_buf_en=%x glbl_test_ctrl=%x\n", - __func__, clk_buf_en, glbl_test_ctrl); - - return PLL_UNKNOWN; -} - -static void pll_source_setup(struct mdss_pll_resources *pll) -{ - int status; - struct dsi_pll_db *pdb = (struct dsi_pll_db *)pll->priv; - struct mdss_pll_resources *other; - - if (pdb->source_setup_done) - return; - - pdb->source_setup_done++; - - status = pll_source_finding(pll); - - if (status == PLL_STANDALONE || status == PLL_UNKNOWN) - return; - - other = pdb->next->pll; - if (!other) - return; - - pr_debug("%s: status=%d pll=%d other=%d\n", __func__, - status, pll->index, other->index); - - if (status == PLL_MASTER) - pll->slave = other; - else - other->slave = pll; -} - -unsigned long pll_vco_recalc_rate_14nm(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct mdss_pll_resources *pll = vco->priv; - u64 vco_rate, multiplier = BIT(20); - s32 div_frac_start; - u32 dec_start; - u64 ref_clk = vco->ref_clk_rate; - int rc; - - if (pll->vco_current_rate) - return (unsigned long)pll->vco_current_rate; - - if (is_gdsc_disabled(pll)) - return 0; - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll=%d\n", pll->index); - return rc; - } - - dec_start = MDSS_PLL_REG_R(pll->pll_base, - DSIPHY_PLL_DEC_START); - dec_start &= 0x0ff; - pr_debug("dec_start = 0x%x\n", dec_start); - - div_frac_start = (MDSS_PLL_REG_R(pll->pll_base, - DSIPHY_PLL_DIV_FRAC_START3) & 0x0f) << 16; - div_frac_start |= (MDSS_PLL_REG_R(pll->pll_base, - DSIPHY_PLL_DIV_FRAC_START2) & 0x0ff) << 8; - div_frac_start |= MDSS_PLL_REG_R(pll->pll_base, - DSIPHY_PLL_DIV_FRAC_START1) & 0x0ff; - pr_debug("div_frac_start = 0x%x\n", div_frac_start); - - vco_rate = ref_clk * dec_start; - vco_rate += ((ref_clk * div_frac_start) / multiplier); - - pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate); - - mdss_pll_resource_enable(pll, false); - - pr_debug("%s: returning vco rate as %lu\n", - __func__, (unsigned long)vco_rate); - return (unsigned long)vco_rate; -} - -int pll_vco_set_rate_14nm(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - int rc; - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct mdss_pll_resources *pll = vco->priv; - struct mdss_pll_resources *slave; - struct dsi_pll_db *pdb; - - pdb = (struct dsi_pll_db *)pll->priv; - if (!pdb) { - pr_err("No prov found\n"); - return -EINVAL; - } - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable mdss dsi plla=%d\n", pll->index); - return rc; - } - - pll_source_setup(pll); - - pr_debug("%s: ndx=%d base=%pK rate=%lu slave=%pK\n", __func__, - pll->index, pll->pll_base, rate, pll->slave); - - pll->vco_current_rate = rate; - pll->vco_ref_clk_rate = vco->ref_clk_rate; - - mdss_dsi_pll_14nm_input_init(pll, pdb); - - pll_14nm_dec_frac_calc(pll, pdb); - - if (pll->ssc_en) - pll_14nm_ssc_calc(pll, pdb); - - pll_14nm_calc_vco_count(pdb, pll->vco_current_rate, - pll->vco_ref_clk_rate); - - /* commit slave if split display is enabled */ - slave = pll->slave; - if (slave) - pll_db_commit_14nm(slave, pdb); - - /* commit master itself */ - pll_db_commit_14nm(pll, pdb); - - mdss_pll_resource_enable(pll, false); - - return rc; -} - -static void shadow_pll_dynamic_refresh_14nm(struct mdss_pll_resources *pll, - struct dsi_pll_db *pdb) -{ - struct dsi_pll_output *pout = &pdb->out; - - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL20, - DSIPHY_CMN_CTRL_0, DSIPHY_PLL_SYSCLK_EN_RESET, - 0xFF, 0x0); - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL21, - DSIPHY_PLL_DEC_START, DSIPHY_PLL_DIV_FRAC_START1, - pout->dec_start, (pout->div_frac_start & 0x0FF)); - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL22, - DSIPHY_PLL_DIV_FRAC_START2, DSIPHY_PLL_DIV_FRAC_START3, - ((pout->div_frac_start >> 8) & 0x0FF), - ((pout->div_frac_start >> 16) & 0x0F)); - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL23, - DSIPHY_PLL_PLLLOCK_CMP1, DSIPHY_PLL_PLLLOCK_CMP2, - (pout->plllock_cmp & 0x0FF), - ((pout->plllock_cmp >> 8) & 0x0FF)); - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL24, - DSIPHY_PLL_PLLLOCK_CMP3, DSIPHY_PLL_PLL_VCO_TUNE, - ((pout->plllock_cmp >> 16) & 0x03), - (pll->cache_pll_trim_codes[1] | BIT(7))); /* VCO tune*/ - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL25, - DSIPHY_PLL_KVCO_CODE, DSIPHY_PLL_RESETSM_CNTRL, - (pll->cache_pll_trim_codes[0] | BIT(5)), 0x38); - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL26, - DSIPHY_PLL_PLL_LPF2_POSTDIV, DSIPHY_CMN_PLL_CNTRL, - (((pout->pll_postdiv - 1) << 4) | pdb->in.pll_lpf_res1), 0x01); - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL27, - DSIPHY_CMN_PLL_CNTRL, DSIPHY_CMN_PLL_CNTRL, - 0x01, 0x01); - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL28, - DSIPHY_CMN_PLL_CNTRL, DSIPHY_CMN_PLL_CNTRL, - 0x01, 0x01); - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL29, - DSIPHY_CMN_PLL_CNTRL, DSIPHY_CMN_PLL_CNTRL, - 0x01, 0x01); - MDSS_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR, 0x0000001E); - MDSS_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR2, 0x001FFE00); - - /* - * Ensure all the dynamic refresh registers are written before - * dynamic refresh to change the fps is triggered - */ - wmb(); -} - -int shadow_pll_vco_set_rate_14nm(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - int rc; - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct mdss_pll_resources *pll = vco->priv; - struct dsi_pll_db *pdb; - s64 vco_clk_rate = (s64)rate; - - if (!pll) { - pr_err("PLL data not found\n"); - return -EINVAL; - } - - pdb = pll->priv; - if (!pdb) { - pr_err("No priv data found\n"); - return -EINVAL; - } - - rc = mdss_pll_read_stored_trim_codes(pll, vco_clk_rate); - if (rc) { - pr_err("cannot find pll codes rate=%lld\n", vco_clk_rate); - return -EINVAL; - } - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable mdss dsi plla=%d\n", pll->index); - return rc; - } - - pr_debug("%s: ndx=%d base=%pK rate=%lu\n", __func__, - pll->index, pll->pll_base, rate); - - pll->vco_current_rate = rate; - pll->vco_ref_clk_rate = vco->ref_clk_rate; - - mdss_dsi_pll_14nm_input_init(pll, pdb); - - pll_14nm_dec_frac_calc(pll, pdb); - - pll_14nm_calc_vco_count(pdb, pll->vco_current_rate, - pll->vco_ref_clk_rate); - - shadow_pll_dynamic_refresh_14nm(pll, pdb); - - rc = mdss_pll_resource_enable(pll, false); - if (rc) { - pr_err("Failed to enable mdss dsi plla=%d\n", pll->index); - return rc; - } - - return rc; -} - -long pll_vco_round_rate_14nm(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - unsigned long rrate = rate; - u32 div; - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - - div = vco->min_rate / rate; - if (div > 15) { - /* rate < 86.67 Mhz */ - pr_err("rate=%lu NOT supportted\n", rate); - return -EINVAL; - } - - if (rate < vco->min_rate) - rrate = vco->min_rate; - if (rate > vco->max_rate) - rrate = vco->max_rate; - - *parent_rate = rrate; - return rrate; -} - -int pll_vco_prepare_14nm(struct clk_hw *hw) -{ - int rc = 0; - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct mdss_pll_resources *pll = vco->priv; - - if (!pll) { - pr_err("Dsi pll resources are not available\n"); - return -EINVAL; - } - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("ndx=%d Failed to enable mdss dsi pll resources\n", - pll->index); - return rc; - } - - if ((pll->vco_cached_rate != 0) - && (pll->vco_cached_rate == clk_hw_get_rate(hw))) { - rc = hw->init->ops->set_rate(hw, pll->vco_cached_rate, - pll->vco_cached_rate); - if (rc) { - pr_err("index=%d vco_set_rate failed. rc=%d\n", - rc, pll->index); - mdss_pll_resource_enable(pll, false); - goto error; - } - } - - rc = dsi_pll_enable(hw); - - if (rc) { - mdss_pll_resource_enable(pll, false); - pr_err("ndx=%d failed to enable dsi pll\n", pll->index); - } - -error: - return rc; -} - -void pll_vco_unprepare_14nm(struct clk_hw *hw) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct mdss_pll_resources *pll = vco->priv; - - if (!pll) { - pr_err("Dsi pll resources are not available\n"); - return; - } - - pll->vco_cached_rate = clk_hw_get_rate(hw); - dsi_pll_disable(hw); -} - -int dsi_mux_set_parent_14nm(void *context, unsigned int reg, unsigned int val) -{ - return 0; -} - -int dsi_mux_get_parent_14nm(void *context, unsigned int reg, unsigned int *val) -{ - *val = 0; - return 0; -} diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.c deleted file mode 100644 index b23d11714e58ed4ba3bf554ba821b9abf8b0d7b7..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.c +++ /dev/null @@ -1,592 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include - -#include "mdss-pll.h" -#include "mdss-dsi-pll.h" -#include "mdss-dsi-pll-14nm.h" -#include - -#define VCO_DELAY_USEC 1 - -static struct dsi_pll_db pll_db[DSI_PLL_NUM]; - -static struct regmap_config dsi_pll_14nm_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x588, -}; - -static struct regmap_bus post_n1_div_regmap_bus = { - .reg_write = post_n1_div_set_div, - .reg_read = post_n1_div_get_div, -}; - -static struct regmap_bus n2_div_regmap_bus = { - .reg_write = n2_div_set_div, - .reg_read = n2_div_get_div, -}; - -static struct regmap_bus shadow_n2_div_regmap_bus = { - .reg_write = shadow_n2_div_set_div, - .reg_read = n2_div_get_div, -}; - -static struct regmap_bus dsi_mux_regmap_bus = { - .reg_write = dsi_mux_set_parent_14nm, - .reg_read = dsi_mux_get_parent_14nm, -}; - -/* Op structures */ -static const struct clk_ops clk_ops_dsi_vco = { - .recalc_rate = pll_vco_recalc_rate_14nm, - .set_rate = pll_vco_set_rate_14nm, - .round_rate = pll_vco_round_rate_14nm, - .prepare = pll_vco_prepare_14nm, - .unprepare = pll_vco_unprepare_14nm, -}; - -/* Shadow ops for dynamic refresh */ -static const struct clk_ops clk_ops_shadow_dsi_vco = { - .recalc_rate = pll_vco_recalc_rate_14nm, - .set_rate = shadow_pll_vco_set_rate_14nm, - .round_rate = pll_vco_round_rate_14nm, -}; - -static struct dsi_pll_vco_clk dsi0pll_vco_clk = { - .ref_clk_rate = 19200000UL, - .min_rate = 1300000000UL, - .max_rate = 2600000000UL, - .pll_en_seq_cnt = 1, - .pll_enable_seqs[0] = dsi_pll_enable_seq_14nm, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_vco_clk_14nm", - .parent_names = (const char *[]){ "bi_tcxo" }, - .num_parents = 1, - .ops = &clk_ops_dsi_vco, - }, -}; - -static struct dsi_pll_vco_clk dsi0pll_shadow_vco_clk = { - .ref_clk_rate = 19200000u, - .min_rate = 1300000000u, - .max_rate = 2600000000u, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_vco_clk_14nm", - .parent_names = (const char *[]){ "bi_tcxo" }, - .num_parents = 1, - .ops = &clk_ops_shadow_dsi_vco, - }, -}; - -static struct dsi_pll_vco_clk dsi1pll_vco_clk = { - .ref_clk_rate = 19200000UL, - .min_rate = 1300000000UL, - .max_rate = 2600000000UL, - .pll_en_seq_cnt = 1, - .pll_enable_seqs[0] = dsi_pll_enable_seq_14nm, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_vco_clk_14nm", - .parent_names = (const char *[]){ "bi_tcxo" }, - .num_parents = 1, - .ops = &clk_ops_dsi_vco, - }, -}; - -static struct dsi_pll_vco_clk dsi1pll_shadow_vco_clk = { - .ref_clk_rate = 19200000u, - .min_rate = 1300000000u, - .max_rate = 2600000000u, - .pll_en_seq_cnt = 1, - .pll_enable_seqs[0] = dsi_pll_enable_seq_14nm, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_vco_clk_14nm", - .parent_names = (const char *[]){ "bi_tcxo" }, - .num_parents = 1, - .ops = &clk_ops_shadow_dsi_vco, - }, -}; - -static struct clk_regmap_div dsi0pll_post_n1_div_clk = { - .reg = 0x48, - .shift = 0, - .width = 4, - - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_post_n1_div_clk", - .parent_names = - (const char *[]){ "dsi0pll_vco_clk_14nm" }, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi0pll_shadow_post_n1_div_clk = { - .reg = 0x48, - .shift = 0, - .width = 4, - - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_post_n1_div_clk", - .parent_names = - (const char *[]){"dsi0pll_shadow_vco_clk_14nm"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_post_n1_div_clk = { - .reg = 0x48, - .shift = 0, - .width = 4, - - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_post_n1_div_clk", - .parent_names = - (const char *[]){ "dsi1pll_vco_clk_14nm" }, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_shadow_post_n1_div_clk = { - .reg = 0x48, - .shift = 0, - .width = 4, - - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_post_n1_div_clk", - .parent_names = - (const char *[]){"dsi1pll_shadow_vco_clk_14nm"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi0pll_n2_div_clk = { - .reg = 0x48, - .shift = 0, - .width = 4, - - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_n2_div_clk", - .parent_names = - (const char *[]){ "dsi0pll_post_n1_div_clk" }, - .num_parents = 1, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi0pll_shadow_n2_div_clk = { - .reg = 0x48, - .shift = 0, - .width = 4, - - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_n2_div_clk", - .parent_names = - (const char *[]){ "dsi0pll_shadow_post_n1_div_clk" }, - .num_parents = 1, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_n2_div_clk = { - .reg = 0x48, - .shift = 0, - .width = 4, - - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_n2_div_clk", - .parent_names = - (const char *[]){ "dsi1pll_post_n1_div_clk" }, - .num_parents = 1, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_shadow_n2_div_clk = { - .reg = 0x48, - .shift = 0, - .width = 4, - - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_n2_div_clk", - .parent_names = - (const char *[]){ "dsi1pll_shadow_post_n1_div_clk" }, - .num_parents = 1, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_fixed_factor dsi0pll_pixel_clk_src = { - .div = 2, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_pixel_clk_src", - .parent_names = (const char *[]){ "dsi0pll_n2_div_clk" }, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi0pll_shadow_pixel_clk_src = { - .div = 2, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_pixel_clk_src", - .parent_names = (const char *[]){ "dsi0pll_shadow_n2_div_clk" }, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_pixel_clk_src = { - .div = 2, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_pixel_clk_src", - .parent_names = (const char *[]){ "dsi1pll_n2_div_clk" }, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_shadow_pixel_clk_src = { - .div = 2, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_pixel_clk_src", - .parent_names = (const char *[]){ "dsi1pll_shadow_n2_div_clk" }, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_regmap_mux dsi0pll_pixel_clk_mux = { - .reg = 0x48, - .shift = 0, - .width = 1, - - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0_phy_pll_out_dsiclk", - .parent_names = - (const char *[]){ "dsi0pll_pixel_clk_src", - "dsi0pll_shadow_pixel_clk_src"}, - .num_parents = 2, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi1pll_pixel_clk_mux = { - .reg = 0x48, - .shift = 0, - .width = 1, - - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_pixel_clk_mux", - .parent_names = - (const char *[]){ "dsi1pll_pixel_clk_src", - "dsi1pll_shadow_pixel_clk_src"}, - .num_parents = 2, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_fixed_factor dsi0pll_byte_clk_src = { - .div = 8, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_byte_clk_src", - .parent_names = (const char *[]){ "dsi0pll_post_n1_div_clk" }, - .num_parents = 1, - .flags = (CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi0pll_shadow_byte_clk_src = { - .div = 8, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_shadow_byte_clk_src", - .parent_names = - (const char *[]){ "dsi0pll_shadow_post_n1_div_clk" }, - .num_parents = 1, - .flags = (CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_byte_clk_src = { - .div = 8, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_byte_clk_src", - .parent_names = (const char *[]){ "dsi1pll_post_n1_div_clk" }, - .num_parents = 1, - .flags = (CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_shadow_byte_clk_src = { - .div = 8, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_shadow_byte_clk_src", - .parent_names = - (const char *[]){ "dsi1pll_shadow_post_n1_div_clk" }, - .num_parents = 1, - .flags = (CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_regmap_mux dsi0pll_byte_clk_mux = { - .reg = 0x48, - .shift = 0, - .width = 1, - - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0_phy_pll_out_byteclk", - .parent_names = - (const char *[]){"dsi0pll_byte_clk_src", - "dsi0pll_shadow_byte_clk_src"}, - .num_parents = 2, - .ops = &clk_regmap_mux_closest_ops, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - }, - }, -}; - -static struct clk_regmap_mux dsi1pll_byte_clk_mux = { - .reg = 0x48, - .shift = 0, - .width = 1, - - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_byte_clk_mux", - .parent_names = - (const char *[]){"dsi1pll_byte_clk_src", - "dsi1pll_shadow_byte_clk_src"}, - .num_parents = 2, - .ops = &clk_regmap_mux_closest_ops, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - }, - }, -}; - -static struct clk_hw *mdss_dsi_pllcc_14nm[] = { - [BYTE0_MUX_CLK] = &dsi0pll_byte_clk_mux.clkr.hw, - [BYTE0_SRC_CLK] = &dsi0pll_byte_clk_src.hw, - [PIX0_MUX_CLK] = &dsi0pll_pixel_clk_mux.clkr.hw, - [PIX0_SRC_CLK] = &dsi0pll_pixel_clk_src.hw, - [N2_DIV_0_CLK] = &dsi0pll_n2_div_clk.clkr.hw, - [POST_N1_DIV_0_CLK] = &dsi0pll_post_n1_div_clk.clkr.hw, - [VCO_CLK_0_CLK] = &dsi0pll_vco_clk.hw, - [SHADOW_BYTE0_SRC_CLK] = &dsi0pll_shadow_byte_clk_src.hw, - [SHADOW_PIX0_SRC_CLK] = &dsi0pll_shadow_pixel_clk_src.hw, - [SHADOW_N2_DIV_0_CLK] = &dsi0pll_shadow_n2_div_clk.clkr.hw, - [SHADOW_POST_N1_DIV_0_CLK] = &dsi0pll_shadow_post_n1_div_clk.clkr.hw, - [SHADOW_VCO_CLK_0_CLK] = &dsi0pll_shadow_vco_clk.hw, - [BYTE1_MUX_CLK] = &dsi1pll_byte_clk_mux.clkr.hw, - [BYTE1_SRC_CLK] = &dsi1pll_byte_clk_src.hw, - [PIX1_MUX_CLK] = &dsi1pll_pixel_clk_mux.clkr.hw, - [PIX1_SRC_CLK] = &dsi1pll_pixel_clk_src.hw, - [N2_DIV_1_CLK] = &dsi1pll_n2_div_clk.clkr.hw, - [POST_N1_DIV_1_CLK] = &dsi1pll_post_n1_div_clk.clkr.hw, - [VCO_CLK_1_CLK] = &dsi1pll_vco_clk.hw, - [SHADOW_BYTE1_SRC_CLK] = &dsi1pll_shadow_byte_clk_src.hw, - [SHADOW_PIX1_SRC_CLK] = &dsi1pll_shadow_pixel_clk_src.hw, - [SHADOW_N2_DIV_1_CLK] = &dsi1pll_shadow_n2_div_clk.clkr.hw, - [SHADOW_POST_N1_DIV_1_CLK] = &dsi1pll_shadow_post_n1_div_clk.clkr.hw, - [SHADOW_VCO_CLK_1_CLK] = &dsi1pll_shadow_vco_clk.hw, -}; - -int dsi_pll_clock_register_14nm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int rc = 0, ndx, i; - int const ssc_freq_default = 31500; /* default h/w recommended value */ - int const ssc_ppm_default = 5000; /* default h/w recommended value */ - struct dsi_pll_db *pdb; - struct clk_onecell_data *clk_data; - struct clk *clk; - struct regmap *regmap; - int num_clks = ARRAY_SIZE(mdss_dsi_pllcc_14nm); - - if (pll_res->index >= DSI_PLL_NUM) { - pr_err("pll ndx=%d is NOT supported\n", pll_res->index); - return -EINVAL; - } - - ndx = pll_res->index; - pdb = &pll_db[ndx]; - pll_res->priv = pdb; - pdb->pll = pll_res; - ndx++; - ndx %= DSI_PLL_NUM; - pdb->next = &pll_db[ndx]; - - if (pll_res->ssc_en) { - if (!pll_res->ssc_freq) - pll_res->ssc_freq = ssc_freq_default; - if (!pll_res->ssc_ppm) - pll_res->ssc_ppm = ssc_ppm_default; - } - - clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL); - if (!clk_data) - return -ENOMEM; - - clk_data->clks = devm_kcalloc(&pdev->dev, num_clks, - sizeof(struct clk *), GFP_KERNEL); - if (!clk_data->clks) - return -ENOMEM; - - clk_data->clk_num = num_clks; - - /* Set client data to mux, div and vco clocks. */ - if (pll_res->index == DSI_PLL_1) { - regmap = devm_regmap_init(&pdev->dev, &post_n1_div_regmap_bus, - pll_res, &dsi_pll_14nm_config); - dsi1pll_post_n1_div_clk.clkr.regmap = regmap; - dsi1pll_shadow_post_n1_div_clk.clkr.regmap = regmap; - - regmap = devm_regmap_init(&pdev->dev, &n2_div_regmap_bus, - pll_res, &dsi_pll_14nm_config); - dsi1pll_n2_div_clk.clkr.regmap = regmap; - - regmap = devm_regmap_init(&pdev->dev, &shadow_n2_div_regmap_bus, - pll_res, &dsi_pll_14nm_config); - dsi1pll_shadow_n2_div_clk.clkr.regmap = regmap; - - regmap = devm_regmap_init(&pdev->dev, &dsi_mux_regmap_bus, - pll_res, &dsi_pll_14nm_config); - dsi1pll_byte_clk_mux.clkr.regmap = regmap; - dsi1pll_pixel_clk_mux.clkr.regmap = regmap; - - dsi1pll_vco_clk.priv = pll_res; - dsi1pll_shadow_vco_clk.priv = pll_res; - - pll_res->vco_delay = VCO_DELAY_USEC; - - for (i = BYTE1_MUX_CLK; i <= SHADOW_VCO_CLK_1_CLK; i++) { - pr_debug("register clk: %d index: %d\n", - i, pll_res->index); - clk = devm_clk_register(&pdev->dev, - mdss_dsi_pllcc_14nm[i]); - if (IS_ERR(clk)) { - pr_err("clk registration failed for DSI: %d\n", - pll_res->index); - rc = -EINVAL; - goto clk_reg_fail; - } - clk_data->clks[i] = clk; - } - - rc = of_clk_add_provider(pdev->dev.of_node, - of_clk_src_onecell_get, clk_data); - } else { - regmap = devm_regmap_init(&pdev->dev, &post_n1_div_regmap_bus, - pll_res, &dsi_pll_14nm_config); - dsi0pll_post_n1_div_clk.clkr.regmap = regmap; - dsi0pll_shadow_post_n1_div_clk.clkr.regmap = regmap; - - regmap = devm_regmap_init(&pdev->dev, &n2_div_regmap_bus, - pll_res, &dsi_pll_14nm_config); - dsi0pll_n2_div_clk.clkr.regmap = regmap; - - regmap = devm_regmap_init(&pdev->dev, &shadow_n2_div_regmap_bus, - pll_res, &dsi_pll_14nm_config); - dsi0pll_shadow_n2_div_clk.clkr.regmap = regmap; - - regmap = devm_regmap_init(&pdev->dev, &dsi_mux_regmap_bus, - pll_res, &dsi_pll_14nm_config); - dsi0pll_byte_clk_mux.clkr.regmap = regmap; - dsi0pll_pixel_clk_mux.clkr.regmap = regmap; - - dsi0pll_vco_clk.priv = pll_res; - dsi0pll_shadow_vco_clk.priv = pll_res; - pll_res->vco_delay = VCO_DELAY_USEC; - - for (i = BYTE0_MUX_CLK; i <= SHADOW_VCO_CLK_0_CLK; i++) { - pr_debug("reg clk: %d index: %d\n", i, pll_res->index); - clk = devm_clk_register(&pdev->dev, - mdss_dsi_pllcc_14nm[i]); - if (IS_ERR(clk)) { - pr_err("clk registration failed for DSI: %d\n", - pll_res->index); - rc = -EINVAL; - goto clk_reg_fail; - } - clk_data->clks[i] = clk; - } - - rc = of_clk_add_provider(pdev->dev.of_node, - of_clk_src_onecell_get, clk_data); - } - - if (!rc) { - pr_info("Registered DSI PLL ndx=%d clocks successfully\n", - pll_res->index); - return rc; - } - -clk_reg_fail: - return rc; -} diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.h b/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.h deleted file mode 100644 index 25587de066b75e12ea260cd311b1652aff36062e..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm.h +++ /dev/null @@ -1,220 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - */ - -#ifndef MDSS_DSI_PLL_14NM_H -#define MDSS_DSI_PLL_14NM_H - -#define DSIPHY_CMN_CLK_CFG0 0x0010 -#define DSIPHY_CMN_CLK_CFG1 0x0014 -#define DSIPHY_CMN_GLBL_TEST_CTRL 0x0018 - -#define DSIPHY_CMN_PLL_CNTRL 0x0048 -#define DSIPHY_CMN_CTRL_0 0x001c -#define DSIPHY_CMN_CTRL_1 0x0020 - -#define DSIPHY_CMN_LDO_CNTRL 0x004c - -#define DSIPHY_PLL_IE_TRIM 0x0400 -#define DSIPHY_PLL_IP_TRIM 0x0404 - -#define DSIPHY_PLL_IPTAT_TRIM 0x0410 - -#define DSIPHY_PLL_CLKBUFLR_EN 0x041c - -#define DSIPHY_PLL_SYSCLK_EN_RESET 0x0428 -#define DSIPHY_PLL_RESETSM_CNTRL 0x042c -#define DSIPHY_PLL_RESETSM_CNTRL2 0x0430 -#define DSIPHY_PLL_RESETSM_CNTRL3 0x0434 -#define DSIPHY_PLL_RESETSM_CNTRL4 0x0438 -#define DSIPHY_PLL_RESETSM_CNTRL5 0x043c -#define DSIPHY_PLL_KVCO_DIV_REF1 0x0440 -#define DSIPHY_PLL_KVCO_DIV_REF2 0x0444 -#define DSIPHY_PLL_KVCO_COUNT1 0x0448 -#define DSIPHY_PLL_KVCO_COUNT2 0x044c -#define DSIPHY_PLL_VREF_CFG1 0x045c - -#define DSIPHY_PLL_KVCO_CODE 0x0458 - -#define DSIPHY_PLL_VCO_DIV_REF1 0x046c -#define DSIPHY_PLL_VCO_DIV_REF2 0x0470 -#define DSIPHY_PLL_VCO_COUNT1 0x0474 -#define DSIPHY_PLL_VCO_COUNT2 0x0478 -#define DSIPHY_PLL_PLLLOCK_CMP1 0x047c -#define DSIPHY_PLL_PLLLOCK_CMP2 0x0480 -#define DSIPHY_PLL_PLLLOCK_CMP3 0x0484 -#define DSIPHY_PLL_PLLLOCK_CMP_EN 0x0488 -#define DSIPHY_PLL_PLL_VCO_TUNE 0x048C -#define DSIPHY_PLL_DEC_START 0x0490 -#define DSIPHY_PLL_SSC_EN_CENTER 0x0494 -#define DSIPHY_PLL_SSC_ADJ_PER1 0x0498 -#define DSIPHY_PLL_SSC_ADJ_PER2 0x049c -#define DSIPHY_PLL_SSC_PER1 0x04a0 -#define DSIPHY_PLL_SSC_PER2 0x04a4 -#define DSIPHY_PLL_SSC_STEP_SIZE1 0x04a8 -#define DSIPHY_PLL_SSC_STEP_SIZE2 0x04ac -#define DSIPHY_PLL_DIV_FRAC_START1 0x04b4 -#define DSIPHY_PLL_DIV_FRAC_START2 0x04b8 -#define DSIPHY_PLL_DIV_FRAC_START3 0x04bc -#define DSIPHY_PLL_TXCLK_EN 0x04c0 -#define DSIPHY_PLL_PLL_CRCTRL 0x04c4 - -#define DSIPHY_PLL_RESET_SM_READY_STATUS 0x04cc - -#define DSIPHY_PLL_PLL_MISC1 0x04e8 - -#define DSIPHY_PLL_CP_SET_CUR 0x04f0 -#define DSIPHY_PLL_PLL_ICPMSET 0x04f4 -#define DSIPHY_PLL_PLL_ICPCSET 0x04f8 -#define DSIPHY_PLL_PLL_ICP_SET 0x04fc -#define DSIPHY_PLL_PLL_LPF1 0x0500 -#define DSIPHY_PLL_PLL_LPF2_POSTDIV 0x0504 -#define DSIPHY_PLL_PLL_BANDGAP 0x0508 - -#define DSI_DYNAMIC_REFRESH_PLL_CTRL15 0x050 -#define DSI_DYNAMIC_REFRESH_PLL_CTRL19 0x060 -#define DSI_DYNAMIC_REFRESH_PLL_CTRL20 0x064 -#define DSI_DYNAMIC_REFRESH_PLL_CTRL21 0x068 -#define DSI_DYNAMIC_REFRESH_PLL_CTRL22 0x06C -#define DSI_DYNAMIC_REFRESH_PLL_CTRL23 0x070 -#define DSI_DYNAMIC_REFRESH_PLL_CTRL24 0x074 -#define DSI_DYNAMIC_REFRESH_PLL_CTRL25 0x078 -#define DSI_DYNAMIC_REFRESH_PLL_CTRL26 0x07C -#define DSI_DYNAMIC_REFRESH_PLL_CTRL27 0x080 -#define DSI_DYNAMIC_REFRESH_PLL_CTRL28 0x084 -#define DSI_DYNAMIC_REFRESH_PLL_CTRL29 0x088 -#define DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR 0x094 -#define DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR2 0x098 - -struct dsi_pll_input { - u32 fref; /* 19.2 Mhz, reference clk */ - u32 fdata; /* bit clock rate */ - u32 dsiclk_sel; /* 1, reg: 0x0014 */ - u32 n2div; /* 1, reg: 0x0010, bit 4-7 */ - u32 ssc_en; /* 1, reg: 0x0494, bit 0 */ - u32 ldo_en; /* 0, reg: 0x004c, bit 0 */ - - /* fixed */ - u32 refclk_dbler_en; /* 0, reg: 0x04c0, bit 1 */ - u32 vco_measure_time; /* 5, unknown */ - u32 kvco_measure_time; /* 5, unknown */ - u32 bandgap_timer; /* 4, reg: 0x0430, bit 3 - 5 */ - u32 pll_wakeup_timer; /* 5, reg: 0x043c, bit 0 - 2 */ - u32 plllock_cnt; /* 1, reg: 0x0488, bit 1 - 2 */ - u32 plllock_rng; /* 1, reg: 0x0488, bit 3 - 4 */ - u32 ssc_center; /* 0, reg: 0x0494, bit 1 */ - u32 ssc_adj_period; /* 37, reg: 0x498, bit 0 - 9 */ - u32 ssc_spread; /* 0.005 */ - u32 ssc_freq; /* unknown */ - u32 pll_ie_trim; /* 4, reg: 0x0400 */ - u32 pll_ip_trim; /* 4, reg: 0x0404 */ - u32 pll_iptat_trim; /* reg: 0x0410 */ - u32 pll_cpcset_cur; /* 1, reg: 0x04f0, bit 0 - 2 */ - u32 pll_cpmset_cur; /* 1, reg: 0x04f0, bit 3 - 5 */ - - u32 pll_icpmset; /* 4, reg: 0x04fc, bit 3 - 5 */ - u32 pll_icpcset; /* 4, reg: 0x04fc, bit 0 - 2 */ - - u32 pll_icpmset_p; /* 0, reg: 0x04f4, bit 0 - 2 */ - u32 pll_icpmset_m; /* 0, reg: 0x04f4, bit 3 - 5 */ - - u32 pll_icpcset_p; /* 0, reg: 0x04f8, bit 0 - 2 */ - u32 pll_icpcset_m; /* 0, reg: 0x04f8, bit 3 - 5 */ - - u32 pll_lpf_res1; /* 3, reg: 0x0504, bit 0 - 3 */ - u32 pll_lpf_cap1; /* 11, reg: 0x0500, bit 0 - 3 */ - u32 pll_lpf_cap2; /* 1, reg: 0x0500, bit 4 - 7 */ - u32 pll_c3ctrl; /* 2, reg: 0x04c4 */ - u32 pll_r3ctrl; /* 1, reg: 0x04c4 */ -}; - -struct dsi_pll_output { - u32 pll_txclk_en; /* reg: 0x04c0 */ - u32 dec_start; /* reg: 0x0490 */ - u32 div_frac_start; /* reg: 0x04b4, 0x4b8, 0x04bc */ - u32 ssc_period; /* reg: 0x04a0, 0x04a4 */ - u32 ssc_step_size; /* reg: 0x04a8, 0x04ac */ - u32 plllock_cmp; /* reg: 0x047c, 0x0480, 0x0484 */ - u32 pll_vco_div_ref; /* reg: 0x046c, 0x0470 */ - u32 pll_vco_count; /* reg: 0x0474, 0x0478 */ - u32 pll_kvco_div_ref; /* reg: 0x0440, 0x0444 */ - u32 pll_kvco_count; /* reg: 0x0448, 0x044c */ - u32 pll_misc1; /* reg: 0x04e8 */ - u32 pll_lpf2_postdiv; /* reg: 0x0504 */ - u32 pll_resetsm_cntrl; /* reg: 0x042c */ - u32 pll_resetsm_cntrl2; /* reg: 0x0430 */ - u32 pll_resetsm_cntrl5; /* reg: 0x043c */ - u32 pll_kvco_code; /* reg: 0x0458 */ - - u32 cmn_clk_cfg0; /* reg: 0x0010 */ - u32 cmn_clk_cfg1; /* reg: 0x0014 */ - u32 cmn_ldo_cntrl; /* reg: 0x004c */ - - u32 pll_postdiv; /* vco */ - u32 pll_n1div; /* vco */ - u32 pll_n2div; /* hr_oclk3, pixel */ - u32 fcvo; -}; - -enum { - DSI_PLL_0, - DSI_PLL_1, - DSI_PLL_NUM -}; - -struct dsi_pll_db { - struct dsi_pll_db *next; - struct mdss_pll_resources *pll; - struct dsi_pll_input in; - struct dsi_pll_output out; - int source_setup_done; -}; - -enum { - PLL_OUTPUT_NONE, - PLL_OUTPUT_RIGHT, - PLL_OUTPUT_LEFT, - PLL_OUTPUT_BOTH -}; - -enum { - PLL_SOURCE_FROM_LEFT, - PLL_SOURCE_FROM_RIGHT -}; - -enum { - PLL_UNKNOWN, - PLL_STANDALONE, - PLL_SLAVE, - PLL_MASTER -}; - -int pll_vco_set_rate_14nm(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate); -int shadow_pll_vco_set_rate_14nm(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate); -long pll_vco_round_rate_14nm(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate); -unsigned long pll_vco_recalc_rate_14nm(struct clk_hw *hw, - unsigned long parent_rate); - -int pll_vco_prepare_14nm(struct clk_hw *hw); -void pll_vco_unprepare_14nm(struct clk_hw *hw); - -int shadow_post_n1_div_set_div(void *context, - unsigned int reg, unsigned int div); -int shadow_post_n1_div_get_div(void *context, - unsigned int reg, unsigned int *div); -int shadow_n2_div_set_div(void *context, unsigned int reg, unsigned int div); -int shadow_n2_div_get_div(void *context, unsigned int reg, unsigned int *div); - -int post_n1_div_set_div(void *context, unsigned int reg, unsigned int div); -int post_n1_div_get_div(void *context, unsigned int reg, unsigned int *div); -int n2_div_set_div(void *context, unsigned int reg, unsigned int div); -int n2_div_get_div(void *context, unsigned int reg, unsigned int *div); -int dsi_pll_enable_seq_14nm(struct mdss_pll_resources *pll); -int dsi_mux_set_parent_14nm(void *context, unsigned int reg, unsigned int val); -int dsi_mux_get_parent_14nm(void *context, unsigned int reg, unsigned int *val); - -#endif /* MDSS_DSI_PLL_14NM_H */ diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-20nm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-20nm.c deleted file mode 100644 index aebcd260dcb5c6f4071587985a3ca325c0c826a0..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-20nm.c +++ /dev/null @@ -1,590 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mdss-pll.h" -#include "mdss-dsi-pll.h" - -#define VCO_DELAY_USEC 1 - -static const struct clk_ops bypass_lp_div_mux_clk_ops; -static const struct clk_ops pixel_clk_src_ops; -static const struct clk_ops byte_clk_src_ops; -static const struct clk_ops ndiv_clk_ops; - -static const struct clk_ops shadow_pixel_clk_src_ops; -static const struct clk_ops shadow_byte_clk_src_ops; -static const struct clk_ops clk_ops_gen_mux_dsi; - -static int vco_set_rate_20nm(struct clk *c, unsigned long rate) -{ - int rc; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - pr_debug("Cancel pending pll off work\n"); - cancel_work_sync(&dsi_pll_res->pll_off); - rc = pll_20nm_vco_set_rate(vco, rate); - - mdss_pll_resource_enable(dsi_pll_res, false); - return rc; -} - -static int pll1_vco_set_rate_20nm(struct clk *c, unsigned long rate) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *pll_res = vco->priv; - - mdss_pll_resource_enable(pll_res, true); - __dsi_pll_disable(pll_res->pll_base); - mdss_pll_resource_enable(pll_res, false); - - pr_debug("Configuring PLL1 registers.\n"); - - return 0; -} - -static int shadow_vco_set_rate_20nm(struct clk *c, unsigned long rate) -{ - int rc; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - if (!dsi_pll_res->resource_enable) { - pr_err("PLL resources disabled. Dynamic fps invalid\n"); - return -EINVAL; - } - - rc = shadow_pll_20nm_vco_set_rate(vco, rate); - - return rc; -} - -/* Op structures */ - -static const struct clk_ops pll1_clk_ops_dsi_vco = { - .set_rate = pll1_vco_set_rate_20nm, -}; - -static const struct clk_ops clk_ops_dsi_vco = { - .set_rate = vco_set_rate_20nm, - .round_rate = pll_20nm_vco_round_rate, - .handoff = pll_20nm_vco_handoff, - .prepare = pll_20nm_vco_prepare, - .unprepare = pll_20nm_vco_unprepare, -}; - -static struct clk_div_ops fixed_hr_oclk2_div_ops = { - .set_div = fixed_hr_oclk2_set_div, - .get_div = fixed_hr_oclk2_get_div, -}; - -static struct clk_div_ops ndiv_ops = { - .set_div = ndiv_set_div, - .get_div = ndiv_get_div, -}; - -static struct clk_div_ops hr_oclk3_div_ops = { - .set_div = hr_oclk3_set_div, - .get_div = hr_oclk3_get_div, -}; - -static struct clk_mux_ops bypass_lp_div_mux_ops = { - .set_mux_sel = set_bypass_lp_div_mux_sel, - .get_mux_sel = get_bypass_lp_div_mux_sel, -}; - -static const struct clk_ops shadow_clk_ops_dsi_vco = { - .set_rate = shadow_vco_set_rate_20nm, - .round_rate = pll_20nm_vco_round_rate, - .handoff = pll_20nm_vco_handoff, -}; - -static struct clk_div_ops shadow_fixed_hr_oclk2_div_ops = { - .set_div = shadow_fixed_hr_oclk2_set_div, - .get_div = fixed_hr_oclk2_get_div, -}; - -static struct clk_div_ops shadow_ndiv_ops = { - .set_div = shadow_ndiv_set_div, - .get_div = ndiv_get_div, -}; - -static struct clk_div_ops shadow_hr_oclk3_div_ops = { - .set_div = shadow_hr_oclk3_set_div, - .get_div = hr_oclk3_get_div, -}; - -static struct clk_mux_ops shadow_bypass_lp_div_mux_ops = { - .set_mux_sel = set_shadow_bypass_lp_div_mux_sel, - .get_mux_sel = get_bypass_lp_div_mux_sel, -}; - -static struct clk_mux_ops mdss_byte_mux_ops = { - .set_mux_sel = set_mdss_byte_mux_sel, - .get_mux_sel = get_mdss_byte_mux_sel, -}; - -static struct clk_mux_ops mdss_pixel_mux_ops = { - .set_mux_sel = set_mdss_pixel_mux_sel, - .get_mux_sel = get_mdss_pixel_mux_sel, -}; - -static struct dsi_pll_vco_clk mdss_dsi1_vco_clk_src = { - .c = { - .dbg_name = "mdss_dsi1_vco_clk_src", - .ops = &pll1_clk_ops_dsi_vco, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(mdss_dsi1_vco_clk_src.c), - }, -}; - -static struct dsi_pll_vco_clk dsi_vco_clk_8994 = { - .ref_clk_rate = 19200000, - .min_rate = 300000000, - .max_rate = 1500000000, - .pll_en_seq_cnt = 1, - .pll_enable_seqs[0] = pll_20nm_vco_enable_seq, - .c = { - .dbg_name = "dsi_vco_clk_8994", - .ops = &clk_ops_dsi_vco, - CLK_INIT(dsi_vco_clk_8994.c), - }, -}; - -static struct dsi_pll_vco_clk shadow_dsi_vco_clk_8994 = { - .ref_clk_rate = 19200000, - .min_rate = 300000000, - .max_rate = 1500000000, - .c = { - .dbg_name = "shadow_dsi_vco_clk_8994", - .ops = &shadow_clk_ops_dsi_vco, - CLK_INIT(shadow_dsi_vco_clk_8994.c), - }, -}; - -static struct div_clk ndiv_clk_8994 = { - .data = { - .max_div = 15, - .min_div = 1, - }, - .ops = &ndiv_ops, - .c = { - .parent = &dsi_vco_clk_8994.c, - .dbg_name = "ndiv_clk_8994", - .ops = &ndiv_clk_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(ndiv_clk_8994.c), - }, -}; - -static struct div_clk shadow_ndiv_clk_8994 = { - .data = { - .max_div = 15, - .min_div = 1, - }, - .ops = &shadow_ndiv_ops, - .c = { - .parent = &shadow_dsi_vco_clk_8994.c, - .dbg_name = "shadow_ndiv_clk_8994", - .ops = &clk_ops_div, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(shadow_ndiv_clk_8994.c), - }, -}; - -static struct div_clk indirect_path_div2_clk_8994 = { - .data = { - .div = 2, - .min_div = 2, - .max_div = 2, - }, - .c = { - .parent = &ndiv_clk_8994.c, - .dbg_name = "indirect_path_div2_clk_8994", - .ops = &clk_ops_div, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(indirect_path_div2_clk_8994.c), - }, -}; - -static struct div_clk shadow_indirect_path_div2_clk_8994 = { - .data = { - .div = 2, - .min_div = 2, - .max_div = 2, - }, - .c = { - .parent = &shadow_ndiv_clk_8994.c, - .dbg_name = "shadow_indirect_path_div2_clk_8994", - .ops = &clk_ops_div, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(shadow_indirect_path_div2_clk_8994.c), - }, -}; - -static struct div_clk hr_oclk3_div_clk_8994 = { - .data = { - .max_div = 255, - .min_div = 1, - }, - .ops = &hr_oclk3_div_ops, - .c = { - .parent = &dsi_vco_clk_8994.c, - .dbg_name = "hr_oclk3_div_clk_8994", - .ops = &pixel_clk_src_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(hr_oclk3_div_clk_8994.c), - }, -}; - -static struct div_clk shadow_hr_oclk3_div_clk_8994 = { - .data = { - .max_div = 255, - .min_div = 1, - }, - .ops = &shadow_hr_oclk3_div_ops, - .c = { - .parent = &shadow_dsi_vco_clk_8994.c, - .dbg_name = "shadow_hr_oclk3_div_clk_8994", - .ops = &shadow_pixel_clk_src_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(shadow_hr_oclk3_div_clk_8994.c), - }, -}; - -static struct div_clk pixel_clk_src = { - .data = { - .div = 2, - .min_div = 2, - .max_div = 2, - }, - .c = { - .parent = &hr_oclk3_div_clk_8994.c, - .dbg_name = "pixel_clk_src", - .ops = &clk_ops_div, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(pixel_clk_src.c), - }, -}; - -static struct div_clk shadow_pixel_clk_src = { - .data = { - .div = 2, - .min_div = 2, - .max_div = 2, - }, - .c = { - .parent = &shadow_hr_oclk3_div_clk_8994.c, - .dbg_name = "shadow_pixel_clk_src", - .ops = &clk_ops_div, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(shadow_pixel_clk_src.c), - }, -}; - -static struct mux_clk bypass_lp_div_mux_8994 = { - .num_parents = 2, - .parents = (struct clk_src[]){ - {&dsi_vco_clk_8994.c, 0}, - {&indirect_path_div2_clk_8994.c, 1}, - }, - .ops = &bypass_lp_div_mux_ops, - .c = { - .parent = &dsi_vco_clk_8994.c, - .dbg_name = "bypass_lp_div_mux_8994", - .ops = &bypass_lp_div_mux_clk_ops, - CLK_INIT(bypass_lp_div_mux_8994.c), - }, -}; - -static struct mux_clk shadow_bypass_lp_div_mux_8994 = { - .num_parents = 2, - .parents = (struct clk_src[]){ - {&shadow_dsi_vco_clk_8994.c, 0}, - {&shadow_indirect_path_div2_clk_8994.c, 1}, - }, - .ops = &shadow_bypass_lp_div_mux_ops, - .c = { - .parent = &shadow_dsi_vco_clk_8994.c, - .dbg_name = "shadow_bypass_lp_div_mux_8994", - .ops = &clk_ops_gen_mux, - CLK_INIT(shadow_bypass_lp_div_mux_8994.c), - }, -}; - -static struct div_clk fixed_hr_oclk2_div_clk_8994 = { - .ops = &fixed_hr_oclk2_div_ops, - .data = { - .min_div = 4, - .max_div = 4, - }, - .c = { - .parent = &bypass_lp_div_mux_8994.c, - .dbg_name = "fixed_hr_oclk2_div_clk_8994", - .ops = &byte_clk_src_ops, - CLK_INIT(fixed_hr_oclk2_div_clk_8994.c), - }, -}; - -static struct div_clk shadow_fixed_hr_oclk2_div_clk_8994 = { - .ops = &shadow_fixed_hr_oclk2_div_ops, - .data = { - .min_div = 4, - .max_div = 4, - }, - .c = { - .parent = &shadow_bypass_lp_div_mux_8994.c, - .dbg_name = "shadow_fixed_hr_oclk2_div_clk_8994", - .ops = &shadow_byte_clk_src_ops, - CLK_INIT(shadow_fixed_hr_oclk2_div_clk_8994.c), - }, -}; - -static struct div_clk byte_clk_src = { - .data = { - .div = 2, - .min_div = 2, - .max_div = 2, - }, - .c = { - .parent = &fixed_hr_oclk2_div_clk_8994.c, - .dbg_name = "byte_clk_src", - .ops = &clk_ops_div, - CLK_INIT(byte_clk_src.c), - }, -}; - -static struct div_clk shadow_byte_clk_src = { - .data = { - .div = 2, - .min_div = 2, - .max_div = 2, - }, - .c = { - .parent = &shadow_fixed_hr_oclk2_div_clk_8994.c, - .dbg_name = "shadow_byte_clk_src", - .ops = &clk_ops_div, - CLK_INIT(shadow_byte_clk_src.c), - }, -}; - -static struct mux_clk mdss_pixel_clk_mux = { - .num_parents = 2, - .parents = (struct clk_src[]) { - {&pixel_clk_src.c, 0}, - {&shadow_pixel_clk_src.c, 1}, - }, - .ops = &mdss_pixel_mux_ops, - .c = { - .parent = &pixel_clk_src.c, - .dbg_name = "mdss_pixel_clk_mux", - .ops = &clk_ops_gen_mux, - CLK_INIT(mdss_pixel_clk_mux.c), - } -}; - -static struct mux_clk mdss_byte_clk_mux = { - .num_parents = 2, - .parents = (struct clk_src[]) { - {&byte_clk_src.c, 0}, - {&shadow_byte_clk_src.c, 1}, - }, - .ops = &mdss_byte_mux_ops, - .c = { - .parent = &byte_clk_src.c, - .dbg_name = "mdss_byte_clk_mux", - .ops = &clk_ops_gen_mux_dsi, - CLK_INIT(mdss_byte_clk_mux.c), - } -}; - -static struct clk_lookup mdss_dsi_pll_1_cc_8994[] = { - CLK_LIST(mdss_dsi1_vco_clk_src), -}; - -static struct clk_lookup mdss_dsi_pllcc_8994[] = { - CLK_LIST(mdss_pixel_clk_mux), - CLK_LIST(mdss_byte_clk_mux), - CLK_LIST(pixel_clk_src), - CLK_LIST(byte_clk_src), - CLK_LIST(fixed_hr_oclk2_div_clk_8994), - CLK_LIST(bypass_lp_div_mux_8994), - CLK_LIST(hr_oclk3_div_clk_8994), - CLK_LIST(indirect_path_div2_clk_8994), - CLK_LIST(ndiv_clk_8994), - CLK_LIST(dsi_vco_clk_8994), - CLK_LIST(shadow_pixel_clk_src), - CLK_LIST(shadow_byte_clk_src), - CLK_LIST(shadow_fixed_hr_oclk2_div_clk_8994), - CLK_LIST(shadow_bypass_lp_div_mux_8994), - CLK_LIST(shadow_hr_oclk3_div_clk_8994), - CLK_LIST(shadow_indirect_path_div2_clk_8994), - CLK_LIST(shadow_ndiv_clk_8994), - CLK_LIST(shadow_dsi_vco_clk_8994), -}; - -static void dsi_pll_off_work(struct work_struct *work) -{ - struct mdss_pll_resources *pll_res; - - if (!work) { - pr_err("pll_resource is invalid\n"); - return; - } - - pr_debug("Starting PLL off Worker%s\n", __func__); - - pll_res = container_of(work, struct - mdss_pll_resources, pll_off); - - mdss_pll_resource_enable(pll_res, true); - __dsi_pll_disable(pll_res->pll_base); - if (pll_res->pll_1_base) - __dsi_pll_disable(pll_res->pll_1_base); - mdss_pll_resource_enable(pll_res, false); -} - -static int dsi_pll_regulator_notifier_call(struct notifier_block *self, - unsigned long event, void *data) -{ - - struct mdss_pll_resources *pll_res; - - if (!self) { - pr_err("pll_resource is invalid\n"); - goto error; - } - - pll_res = container_of(self, struct - mdss_pll_resources, gdsc_cb); - - if (event & REGULATOR_EVENT_ENABLE) { - pr_debug("Regulator ON event. Scheduling pll off worker\n"); - schedule_work(&pll_res->pll_off); - } - - if (event & REGULATOR_EVENT_DISABLE) - pr_debug("Regulator OFF event.\n"); - -error: - return NOTIFY_OK; -} - -int dsi_pll_clock_register_20nm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int rc; - struct dss_vreg *pll_reg; - - /* - * Set client data to mux, div and vco clocks. - * This needs to be done only for PLL0 since, that is the one in - * use. - **/ - if (!pll_res->index) { - byte_clk_src.priv = pll_res; - pixel_clk_src.priv = pll_res; - bypass_lp_div_mux_8994.priv = pll_res; - indirect_path_div2_clk_8994.priv = pll_res; - ndiv_clk_8994.priv = pll_res; - fixed_hr_oclk2_div_clk_8994.priv = pll_res; - hr_oclk3_div_clk_8994.priv = pll_res; - dsi_vco_clk_8994.priv = pll_res; - - shadow_byte_clk_src.priv = pll_res; - shadow_pixel_clk_src.priv = pll_res; - shadow_bypass_lp_div_mux_8994.priv = pll_res; - shadow_indirect_path_div2_clk_8994.priv = pll_res; - shadow_ndiv_clk_8994.priv = pll_res; - shadow_fixed_hr_oclk2_div_clk_8994.priv = pll_res; - shadow_hr_oclk3_div_clk_8994.priv = pll_res; - shadow_dsi_vco_clk_8994.priv = pll_res; - - pll_res->vco_delay = VCO_DELAY_USEC; - - /* Set clock source operations */ - pixel_clk_src_ops = clk_ops_slave_div; - pixel_clk_src_ops.prepare = dsi_pll_div_prepare; - - ndiv_clk_ops = clk_ops_div; - ndiv_clk_ops.prepare = dsi_pll_div_prepare; - - byte_clk_src_ops = clk_ops_div; - byte_clk_src_ops.prepare = dsi_pll_div_prepare; - - bypass_lp_div_mux_clk_ops = clk_ops_gen_mux; - bypass_lp_div_mux_clk_ops.prepare = dsi_pll_mux_prepare; - - clk_ops_gen_mux_dsi = clk_ops_gen_mux; - clk_ops_gen_mux_dsi.round_rate = parent_round_rate; - clk_ops_gen_mux_dsi.set_rate = parent_set_rate; - - shadow_pixel_clk_src_ops = clk_ops_slave_div; - shadow_pixel_clk_src_ops.prepare = dsi_pll_div_prepare; - - shadow_byte_clk_src_ops = clk_ops_div; - shadow_byte_clk_src_ops.prepare = dsi_pll_div_prepare; - } else { - mdss_dsi1_vco_clk_src.priv = pll_res; - } - - if ((pll_res->target_id == MDSS_PLL_TARGET_8994) || - (pll_res->target_id == MDSS_PLL_TARGET_8992)) { - if (pll_res->index) { - rc = of_msm_clock_register(pdev->dev.of_node, - mdss_dsi_pll_1_cc_8994, - ARRAY_SIZE(mdss_dsi_pll_1_cc_8994)); - if (rc) { - pr_err("Clock register failed\n"); - rc = -EPROBE_DEFER; - } - } else { - rc = of_msm_clock_register(pdev->dev.of_node, - mdss_dsi_pllcc_8994, - ARRAY_SIZE(mdss_dsi_pllcc_8994)); - if (rc) { - pr_err("Clock register failed\n"); - rc = -EPROBE_DEFER; - } - pll_res->gdsc_cb.notifier_call = - dsi_pll_regulator_notifier_call; - INIT_WORK(&pll_res->pll_off, dsi_pll_off_work); - - pll_reg = mdss_pll_get_mp_by_reg_name(pll_res, "gdsc"); - if (pll_reg) { - pr_debug("Registering for gdsc regulator events\n"); - if (regulator_register_notifier(pll_reg->vreg, - &(pll_res->gdsc_cb))) - pr_err("Regulator notification registration failed!\n"); - } - } - - } else { - pr_err("Invalid target ID\n"); - rc = -EINVAL; - } - - if (!rc) - pr_info("Registered DSI PLL clocks successfully\n"); - - return rc; -} diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-28hpm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-28hpm.c deleted file mode 100644 index d39a6b8aec85a9c04bb567729cc581e4d4ca56c7..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-28hpm.c +++ /dev/null @@ -1,317 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include - -#include "mdss-pll.h" -#include "mdss-dsi-pll.h" - -#define VCO_DELAY_USEC 1 - -static struct clk_div_ops fixed_2div_ops; -static const struct clk_ops byte_mux_clk_ops; -static const struct clk_ops pixel_clk_src_ops; -static const struct clk_ops byte_clk_src_ops; -static const struct clk_ops analog_postdiv_clk_ops; -static struct lpfr_cfg lpfr_lut_struct[] = { - {479500000, 8}, - {480000000, 11}, - {575500000, 8}, - {576000000, 12}, - {610500000, 8}, - {659500000, 9}, - {671500000, 10}, - {672000000, 14}, - {708500000, 10}, - {750000000, 11}, -}; - -static void dsi_pll_software_reset(struct mdss_pll_resources *dsi_pll_res) -{ - /* - * Add HW recommended delays after toggling the software - * reset bit off and back on. - */ - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x01); - udelay(1); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x00); - udelay(1); -} - -static int vco_set_rate_hpm(struct clk *c, unsigned long rate) -{ - int rc; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - rc = vco_set_rate(vco, rate); - - mdss_pll_resource_enable(dsi_pll_res, false); - return rc; -} - -static int dsi_pll_enable_seq_8974(struct mdss_pll_resources *dsi_pll_res) -{ - int i, rc = 0; - int pll_locked; - - dsi_pll_software_reset(dsi_pll_res); - - /* - * PLL power up sequence. - * Add necessary delays recommeded by hardware. - */ - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01); - udelay(1); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05); - udelay(200); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x07); - udelay(500); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f); - udelay(500); - - for (i = 0; i < 2; i++) { - udelay(100); - /* DSI Uniphy lock detect setting */ - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x0c); - udelay(100); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x0d); - - pll_locked = dsi_pll_lock_status(dsi_pll_res); - if (pll_locked) - break; - - dsi_pll_software_reset(dsi_pll_res); - /* - * PLL power up sequence. - * Add necessary delays recommeded by hardware. - */ - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x1); - udelay(1); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x5); - udelay(200); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x7); - udelay(250); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x5); - udelay(200); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x7); - udelay(500); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0xf); - udelay(500); - - } - - if (!pll_locked) { - pr_err("DSI PLL lock failed\n"); - rc = -EINVAL; - } else { - pr_debug("DSI PLL Lock success\n"); - } - - return rc; -} - -/* Op structures */ - -static const struct clk_ops clk_ops_dsi_vco = { - .set_rate = vco_set_rate_hpm, - .round_rate = vco_round_rate, - .handoff = vco_handoff, - .prepare = vco_prepare, - .unprepare = vco_unprepare, -}; - - -static struct clk_div_ops fixed_4div_ops = { - .set_div = fixed_4div_set_div, - .get_div = fixed_4div_get_div, -}; - -static struct clk_div_ops analog_postdiv_ops = { - .set_div = analog_set_div, - .get_div = analog_get_div, -}; - -static struct clk_div_ops digital_postdiv_ops = { - .set_div = digital_set_div, - .get_div = digital_get_div, -}; - -static struct clk_mux_ops byte_mux_ops = { - .set_mux_sel = set_byte_mux_sel, - .get_mux_sel = get_byte_mux_sel, -}; - -static struct dsi_pll_vco_clk dsi_vco_clk_8974 = { - .ref_clk_rate = 19200000, - .min_rate = 350000000, - .max_rate = 750000000, - .pll_en_seq_cnt = 3, - .pll_enable_seqs[0] = dsi_pll_enable_seq_8974, - .pll_enable_seqs[1] = dsi_pll_enable_seq_8974, - .pll_enable_seqs[2] = dsi_pll_enable_seq_8974, - .lpfr_lut_size = 10, - .lpfr_lut = lpfr_lut_struct, - .c = { - .dbg_name = "dsi_vco_clk_8974", - .ops = &clk_ops_dsi_vco, - CLK_INIT(dsi_vco_clk_8974.c), - }, -}; - -static struct div_clk analog_postdiv_clk_8974 = { - .data = { - .max_div = 255, - .min_div = 1, - }, - .ops = &analog_postdiv_ops, - .c = { - .parent = &dsi_vco_clk_8974.c, - .dbg_name = "analog_postdiv_clk", - .ops = &analog_postdiv_clk_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(analog_postdiv_clk_8974.c), - }, -}; - -static struct div_clk indirect_path_div2_clk_8974 = { - .ops = &fixed_2div_ops, - .data = { - .div = 2, - .min_div = 2, - .max_div = 2, - }, - .c = { - .parent = &analog_postdiv_clk_8974.c, - .dbg_name = "indirect_path_div2_clk", - .ops = &clk_ops_div, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(indirect_path_div2_clk_8974.c), - }, -}; - -static struct div_clk pixel_clk_src_8974 = { - .data = { - .max_div = 255, - .min_div = 1, - }, - .ops = &digital_postdiv_ops, - .c = { - .parent = &dsi_vco_clk_8974.c, - .dbg_name = "pixel_clk_src_8974", - .ops = &pixel_clk_src_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(pixel_clk_src_8974.c), - }, -}; - -static struct mux_clk byte_mux_8974 = { - .num_parents = 2, - .parents = (struct clk_src[]){ - {&dsi_vco_clk_8974.c, 0}, - {&indirect_path_div2_clk_8974.c, 1}, - }, - .ops = &byte_mux_ops, - .c = { - .parent = &dsi_vco_clk_8974.c, - .dbg_name = "byte_mux_8974", - .ops = &byte_mux_clk_ops, - CLK_INIT(byte_mux_8974.c), - }, -}; - -static struct div_clk byte_clk_src_8974 = { - .ops = &fixed_4div_ops, - .data = { - .min_div = 4, - .max_div = 4, - }, - .c = { - .parent = &byte_mux_8974.c, - .dbg_name = "byte_clk_src_8974", - .ops = &byte_clk_src_ops, - CLK_INIT(byte_clk_src_8974.c), - }, -}; - -static struct clk_lookup mdss_dsi_pllcc_8974[] = { - CLK_LOOKUP_OF("pixel_src", pixel_clk_src_8974, - "fd8c0000.qcom,mmsscc-mdss"), - CLK_LOOKUP_OF("byte_src", byte_clk_src_8974, - "fd8c0000.qcom,mmsscc-mdss"), -}; - -int dsi_pll_clock_register_hpm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int rc; - - /* Set client data to mux, div and vco clocks */ - byte_clk_src_8974.priv = pll_res; - pixel_clk_src_8974.priv = pll_res; - byte_mux_8974.priv = pll_res; - indirect_path_div2_clk_8974.priv = pll_res; - analog_postdiv_clk_8974.priv = pll_res; - dsi_vco_clk_8974.priv = pll_res; - pll_res->vco_delay = VCO_DELAY_USEC; - - /* Set clock source operations */ - pixel_clk_src_ops = clk_ops_slave_div; - pixel_clk_src_ops.prepare = dsi_pll_div_prepare; - - analog_postdiv_clk_ops = clk_ops_div; - analog_postdiv_clk_ops.prepare = dsi_pll_div_prepare; - - byte_clk_src_ops = clk_ops_div; - byte_clk_src_ops.prepare = dsi_pll_div_prepare; - - byte_mux_clk_ops = clk_ops_gen_mux; - byte_mux_clk_ops.prepare = dsi_pll_mux_prepare; - - if (pll_res->target_id == MDSS_PLL_TARGET_8974) { - rc = of_msm_clock_register(pdev->dev.of_node, - mdss_dsi_pllcc_8974, ARRAY_SIZE(mdss_dsi_pllcc_8974)); - if (rc) { - pr_err("Clock register failed\n"); - rc = -EPROBE_DEFER; - } - } else { - pr_err("Invalid target ID\n"); - rc = -EINVAL; - } - - if (!rc) - pr_info("Registered DSI PLL clocks successfully\n"); - - return rc; -} diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-28lpm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-28lpm.c deleted file mode 100644 index 68e9edff265ca642fbcbae29ca359d167fb1193a..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-28lpm.c +++ /dev/null @@ -1,545 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include - -#include "mdss-pll.h" -#include "mdss-dsi-pll.h" -#include "mdss-dsi-pll-28nm.h" - -#define VCO_DELAY_USEC 1000 - -enum { - DSI_PLL_0, - DSI_PLL_1, - DSI_PLL_MAX -}; - -static struct lpfr_cfg lpfr_lut_struct[] = { - {479500000, 8}, - {480000000, 11}, - {575500000, 8}, - {576000000, 12}, - {610500000, 8}, - {659500000, 9}, - {671500000, 10}, - {672000000, 14}, - {708500000, 10}, - {750000000, 11}, -}; - -static void dsi_pll_sw_reset(struct mdss_pll_resources *rsc) -{ - /* - * DSI PLL software reset. Add HW recommended delays after toggling - * the software reset bit off and back on. - */ - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x01); - ndelay(500); - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x00); -} - -static void dsi_pll_toggle_lock_detect( - struct mdss_pll_resources *rsc) -{ - /* DSI PLL toggle lock detect setting */ - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x04); - ndelay(500); - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x05); - udelay(512); -} - -static int dsi_pll_check_lock_status( - struct mdss_pll_resources *rsc) -{ - int rc = 0; - - rc = dsi_pll_lock_status(rsc); - if (rc) - pr_debug("PLL Locked\n"); - else - pr_err("PLL failed to lock\n"); - - return rc; -} - - -static int dsi_pll_enable_seq_gf2(struct mdss_pll_resources *rsc) -{ - int pll_locked = 0; - - dsi_pll_sw_reset(rsc); - - /* - * GF PART 2 PLL power up sequence. - * Add necessary delays recommended by hardware. - */ - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG1, 0x04); - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01); - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05); - udelay(3); - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f); - udelay(500); - - dsi_pll_toggle_lock_detect(rsc); - - pll_locked = dsi_pll_check_lock_status(rsc); - return pll_locked ? 0 : -EINVAL; -} - -static int dsi_pll_enable_seq_gf1(struct mdss_pll_resources *rsc) -{ - int pll_locked = 0; - - dsi_pll_sw_reset(rsc); - /* - * GF PART 1 PLL power up sequence. - * Add necessary delays recommended by hardware. - */ - - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG1, 0x14); - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01); - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05); - udelay(3); - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f); - udelay(500); - - dsi_pll_toggle_lock_detect(rsc); - - pll_locked = dsi_pll_check_lock_status(rsc); - return pll_locked ? 0 : -EINVAL; -} - -static int dsi_pll_enable_seq_tsmc(struct mdss_pll_resources *rsc) -{ - int pll_locked = 0; - - dsi_pll_sw_reset(rsc); - /* - * TSMC PLL power up sequence. - * Add necessary delays recommended by hardware. - */ - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG1, 0x34); - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01); - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05); - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f); - udelay(500); - - dsi_pll_toggle_lock_detect(rsc); - - pll_locked = dsi_pll_check_lock_status(rsc); - return pll_locked ? 0 : -EINVAL; -} - -static struct regmap_config dsi_pll_28lpm_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0xF4, -}; - -static struct regmap_bus analog_postdiv_regmap_bus = { - .reg_write = analog_postdiv_reg_write, - .reg_read = analog_postdiv_reg_read, -}; - -static struct regmap_bus byteclk_src_mux_regmap_bus = { - .reg_write = byteclk_mux_write_sel, - .reg_read = byteclk_mux_read_sel, -}; - -static struct regmap_bus pclk_src_regmap_bus = { - .reg_write = pixel_clk_set_div, - .reg_read = pixel_clk_get_div, -}; - -static const struct clk_ops clk_ops_vco_28lpm = { - .recalc_rate = vco_28nm_recalc_rate, - .set_rate = vco_28nm_set_rate, - .round_rate = vco_28nm_round_rate, - .prepare = vco_28nm_prepare, - .unprepare = vco_28nm_unprepare, -}; - -static struct dsi_pll_vco_clk dsi0pll_vco_clk = { - .ref_clk_rate = 19200000UL, - .min_rate = 350000000UL, - .max_rate = 750000000UL, - .pll_en_seq_cnt = 9, - .pll_enable_seqs[0] = dsi_pll_enable_seq_tsmc, - .pll_enable_seqs[1] = dsi_pll_enable_seq_tsmc, - .pll_enable_seqs[2] = dsi_pll_enable_seq_tsmc, - .pll_enable_seqs[3] = dsi_pll_enable_seq_gf1, - .pll_enable_seqs[4] = dsi_pll_enable_seq_gf1, - .pll_enable_seqs[5] = dsi_pll_enable_seq_gf1, - .pll_enable_seqs[6] = dsi_pll_enable_seq_gf2, - .pll_enable_seqs[7] = dsi_pll_enable_seq_gf2, - .pll_enable_seqs[8] = dsi_pll_enable_seq_gf2, - .lpfr_lut_size = 10, - .lpfr_lut = lpfr_lut_struct, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_vco_clk", - .parent_names = (const char *[]){"cxo"}, - .num_parents = 1, - .ops = &clk_ops_vco_28lpm, - .flags = CLK_GET_RATE_NOCACHE, - }, -}; - -static struct dsi_pll_vco_clk dsi1pll_vco_clk = { - .ref_clk_rate = 19200000UL, - .min_rate = 350000000UL, - .max_rate = 750000000UL, - .pll_en_seq_cnt = 9, - .pll_enable_seqs[0] = dsi_pll_enable_seq_tsmc, - .pll_enable_seqs[1] = dsi_pll_enable_seq_tsmc, - .pll_enable_seqs[2] = dsi_pll_enable_seq_tsmc, - .pll_enable_seqs[3] = dsi_pll_enable_seq_gf1, - .pll_enable_seqs[4] = dsi_pll_enable_seq_gf1, - .pll_enable_seqs[5] = dsi_pll_enable_seq_gf1, - .pll_enable_seqs[6] = dsi_pll_enable_seq_gf2, - .pll_enable_seqs[7] = dsi_pll_enable_seq_gf2, - .pll_enable_seqs[8] = dsi_pll_enable_seq_gf2, - .lpfr_lut_size = 10, - .lpfr_lut = lpfr_lut_struct, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_vco_clk", - .parent_names = (const char *[]){"cxo"}, - .num_parents = 1, - .ops = &clk_ops_vco_28lpm, - .flags = CLK_GET_RATE_NOCACHE, - }, -}; - -static struct clk_regmap_div dsi0pll_analog_postdiv = { - .reg = DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG, - .shift = 0, - .width = 4, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_analog_postdiv", - .parent_names = (const char *[]){"dsi0pll_vco_clk"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_analog_postdiv = { - .reg = DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG, - .shift = 0, - .width = 4, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_analog_postdiv", - .parent_names = (const char *[]){"dsi1pll_vco_clk"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_fixed_factor dsi0pll_indirect_path_src = { - .div = 2, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_indirect_path_src", - .parent_names = (const char *[]){"dsi0pll_analog_postdiv"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_indirect_path_src = { - .div = 2, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_indirect_path_src", - .parent_names = (const char *[]){"dsi1pll_analog_postdiv"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_regmap_mux dsi0pll_byteclk_src_mux = { - .reg = DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG, - .shift = 1, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_byteclk_src_mux", - .parent_names = (const char *[]){ - "dsi0pll_vco_clk", - "dsi0pll_indirect_path_src"}, - .num_parents = 2, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi1pll_byteclk_src_mux = { - .reg = DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG, - .shift = 1, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_byteclk_src_mux", - .parent_names = (const char *[]){ - "dsi1pll_vco_clk", - "dsi1pll_indirect_path_src"}, - .num_parents = 2, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_fixed_factor dsi0pll_byteclk_src = { - .div = 4, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_byteclk_src", - .parent_names = (const char *[]){ - "dsi0pll_byteclk_src_mux"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_byteclk_src = { - .div = 4, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_byteclk_src", - .parent_names = (const char *[]){ - "dsi1pll_byteclk_src_mux"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_regmap_div dsi0pll_pclk_src = { - .reg = DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG, - .shift = 0, - .width = 8, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_pclk_src", - .parent_names = (const char *[]){"dsi0pll_vco_clk"}, - .num_parents = 1, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_pclk_src = { - .reg = DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG, - .shift = 0, - .width = 8, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_pclk_src", - .parent_names = (const char *[]){"dsi1pll_vco_clk"}, - .num_parents = 1, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_hw *mdss_dsi_pllcc_28lpm[] = { - [VCO_CLK_0] = &dsi0pll_vco_clk.hw, - [ANALOG_POSTDIV_0_CLK] = &dsi0pll_analog_postdiv.clkr.hw, - [INDIRECT_PATH_SRC_0_CLK] = &dsi0pll_indirect_path_src.hw, - [BYTECLK_SRC_MUX_0_CLK] = &dsi0pll_byteclk_src_mux.clkr.hw, - [BYTECLK_SRC_0_CLK] = &dsi0pll_byteclk_src.hw, - [PCLK_SRC_0_CLK] = &dsi0pll_pclk_src.clkr.hw, - [VCO_CLK_1] = &dsi1pll_vco_clk.hw, - [ANALOG_POSTDIV_1_CLK] = &dsi1pll_analog_postdiv.clkr.hw, - [INDIRECT_PATH_SRC_1_CLK] = &dsi1pll_indirect_path_src.hw, - [BYTECLK_SRC_MUX_1_CLK] = &dsi1pll_byteclk_src_mux.clkr.hw, - [BYTECLK_SRC_1_CLK] = &dsi1pll_byteclk_src.hw, - [PCLK_SRC_1_CLK] = &dsi1pll_pclk_src.clkr.hw, -}; - -int dsi_pll_clock_register_28lpm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int rc = 0, ndx, i; - struct clk *clk; - struct clk_onecell_data *clk_data; - int num_clks = ARRAY_SIZE(mdss_dsi_pllcc_28lpm); - struct regmap *rmap; - - int const ssc_freq_min = 30000; /* min. recommended freq. value */ - int const ssc_freq_max = 33000; /* max. recommended freq. value */ - int const ssc_ppm_max = 5000; /* max. recommended ppm */ - - ndx = pll_res->index; - - if (ndx >= DSI_PLL_MAX) { - pr_err("pll index(%d) NOT supported\n", ndx); - return -EINVAL; - } - - pll_res->vco_delay = VCO_DELAY_USEC; - - if (pll_res->ssc_en) { - if (!pll_res->ssc_freq || (pll_res->ssc_freq < ssc_freq_min) || - (pll_res->ssc_freq > ssc_freq_max)) { - pll_res->ssc_freq = ssc_freq_min; - pr_debug("SSC frequency out of recommended range. Set to default=%d\n", - pll_res->ssc_freq); - } - - if (!pll_res->ssc_ppm || (pll_res->ssc_ppm > ssc_ppm_max)) { - pll_res->ssc_ppm = ssc_ppm_max; - pr_debug("SSC PPM out of recommended range. Set to default=%d\n", - pll_res->ssc_ppm); - } - } - - clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), - GFP_KERNEL); - if (!clk_data) - return -ENOMEM; - - clk_data->clks = devm_kcalloc(&pdev->dev, num_clks, - sizeof(struct clk *), GFP_KERNEL); - if (!clk_data->clks) - return -ENOMEM; - - clk_data->clk_num = num_clks; - - /* Establish client data */ - if (ndx == 0) { - rmap = devm_regmap_init(&pdev->dev, &byteclk_src_mux_regmap_bus, - pll_res, &dsi_pll_28lpm_config); - if (IS_ERR(rmap)) { - pr_err("regmap init failed for DSI clock:%d\n", - pll_res->index); - return -EINVAL; - } - dsi0pll_byteclk_src_mux.clkr.regmap = rmap; - - rmap = devm_regmap_init(&pdev->dev, &analog_postdiv_regmap_bus, - pll_res, &dsi_pll_28lpm_config); - if (IS_ERR(rmap)) { - pr_err("regmap init failed for DSI clock:%d\n", - pll_res->index); - return -EINVAL; - } - dsi0pll_analog_postdiv.clkr.regmap = rmap; - - rmap = devm_regmap_init(&pdev->dev, &pclk_src_regmap_bus, - pll_res, &dsi_pll_28lpm_config); - if (IS_ERR(rmap)) { - pr_err("regmap init failed for DSI clock:%d\n", - pll_res->index); - return -EINVAL; - } - dsi0pll_pclk_src.clkr.regmap = rmap; - - dsi0pll_vco_clk.priv = pll_res; - for (i = VCO_CLK_0; i <= PCLK_SRC_0_CLK; i++) { - clk = devm_clk_register(&pdev->dev, - mdss_dsi_pllcc_28lpm[i]); - if (IS_ERR(clk)) { - pr_err("clk registration failed for DSI clock:%d\n", - pll_res->index); - rc = -EINVAL; - goto clk_register_fail; - } - clk_data->clks[i] = clk; - - } - - rc = of_clk_add_provider(pdev->dev.of_node, - of_clk_src_onecell_get, clk_data); - - } else { - rmap = devm_regmap_init(&pdev->dev, &byteclk_src_mux_regmap_bus, - pll_res, &dsi_pll_28lpm_config); - if (IS_ERR(rmap)) { - pr_err("regmap init failed for DSI clock:%d\n", - pll_res->index); - return -EINVAL; - } - dsi1pll_byteclk_src_mux.clkr.regmap = rmap; - - rmap = devm_regmap_init(&pdev->dev, &analog_postdiv_regmap_bus, - pll_res, &dsi_pll_28lpm_config); - if (IS_ERR(rmap)) { - pr_err("regmap init failed for DSI clock:%d\n", - pll_res->index); - return -EINVAL; - } - dsi1pll_analog_postdiv.clkr.regmap = rmap; - - rmap = devm_regmap_init(&pdev->dev, &pclk_src_regmap_bus, - pll_res, &dsi_pll_28lpm_config); - if (IS_ERR(rmap)) { - pr_err("regmap init failed for DSI clock:%d\n", - pll_res->index); - return -EINVAL; - } - dsi1pll_pclk_src.clkr.regmap = rmap; - - dsi1pll_vco_clk.priv = pll_res; - for (i = VCO_CLK_1; i <= PCLK_SRC_1_CLK; i++) { - clk = devm_clk_register(&pdev->dev, - mdss_dsi_pllcc_28lpm[i]); - if (IS_ERR(clk)) { - pr_err("clk registration failed for DSI clock:%d\n", - pll_res->index); - rc = -EINVAL; - goto clk_register_fail; - } - clk_data->clks[i] = clk; - - } - - rc = of_clk_add_provider(pdev->dev.of_node, - of_clk_src_onecell_get, clk_data); - } - if (!rc) { - pr_info("Registered DSI PLL ndx=%d, clocks successfully\n", - ndx); - - return rc; - } - -clk_register_fail: - return rc; -} diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-28nm-util.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-28nm-util.c deleted file mode 100644 index f168f637121bee0390837049b69594292f76ac7b..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-28nm-util.c +++ /dev/null @@ -1,652 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include - -#include "mdss-pll.h" -#include "mdss-dsi-pll.h" -#include "mdss-dsi-pll-28nm.h" - -#define DSI_PHY_PLL_UNIPHY_PLL_REFCLK_CFG (0x0) -#define DSI_PHY_PLL_UNIPHY_PLL_CHGPUMP_CFG (0x0008) -#define DSI_PHY_PLL_UNIPHY_PLL_VCOLPF_CFG (0x000C) -#define DSI_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG (0x0014) -#define DSI_PHY_PLL_UNIPHY_PLL_POSTDIV2_CFG (0x0024) -#define DSI_PHY_PLL_UNIPHY_PLL_LPFR_CFG (0x002C) -#define DSI_PHY_PLL_UNIPHY_PLL_LPFC1_CFG (0x0030) -#define DSI_PHY_PLL_UNIPHY_PLL_LPFC2_CFG (0x0034) -#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0 (0x0038) -#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1 (0x003C) -#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2 (0x0040) -#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3 (0x0044) -#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG4 (0x0048) -#define DSI_PHY_PLL_UNIPHY_PLL_SSC_CFG0 (0x004C) -#define DSI_PHY_PLL_UNIPHY_PLL_SSC_CFG1 (0x0050) -#define DSI_PHY_PLL_UNIPHY_PLL_SSC_CFG2 (0x0054) -#define DSI_PHY_PLL_UNIPHY_PLL_SSC_CFG3 (0x0058) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG0 (0x006C) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG2 (0x0074) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG3 (0x0078) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG4 (0x007C) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG5 (0x0080) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG6 (0x0084) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG7 (0x0088) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG8 (0x008C) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG9 (0x0090) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG10 (0x0094) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG11 (0x0098) -#define DSI_PHY_PLL_UNIPHY_PLL_EFUSE_CFG (0x009C) -#define DSI_PHY_PLL_UNIPHY_PLL_STATUS (0x00C0) - -#define DSI_PLL_POLL_DELAY_US 50 -#define DSI_PLL_POLL_TIMEOUT_US 500 - -int analog_postdiv_reg_read(void *context, unsigned int reg, - unsigned int *div) -{ - int rc = 0; - struct mdss_pll_resources *rsc = context; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - *div = MDSS_PLL_REG_R(rsc->pll_base, reg); - - pr_debug("analog_postdiv div = %d\n", *div); - - (void)mdss_pll_resource_enable(rsc, false); - return rc; -} - -int analog_postdiv_reg_write(void *context, unsigned int reg, - unsigned int div) -{ - int rc = 0; - struct mdss_pll_resources *rsc = context; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - pr_debug("analog_postdiv div = %d\n", div); - - MDSS_PLL_REG_W(rsc->pll_base, reg, div); - - (void)mdss_pll_resource_enable(rsc, false); - return rc; -} - -int byteclk_mux_read_sel(void *context, unsigned int reg, - unsigned int *val) -{ - int rc = 0; - struct mdss_pll_resources *rsc = context; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - *val = (MDSS_PLL_REG_R(rsc->pll_base, reg) & BIT(1)); - pr_debug("byteclk mux mode = %s\n", *val ? "indirect" : "direct"); - - (void)mdss_pll_resource_enable(rsc, false); - return rc; -} - -int byteclk_mux_write_sel(void *context, unsigned int reg, - unsigned int val) -{ - int rc = 0; - u32 reg_val = 0; - struct mdss_pll_resources *rsc = context; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - pr_debug("byteclk mux set to %s mode\n", val ? "indirect" : "direct"); - - reg_val = MDSS_PLL_REG_R(rsc->pll_base, reg); - reg_val &= ~0x02; - reg_val |= val; - - MDSS_PLL_REG_W(rsc->pll_base, reg, reg_val); - - (void)mdss_pll_resource_enable(rsc, false); - - return rc; -} - -int pixel_clk_get_div(void *context, unsigned int reg, - unsigned int *div) -{ - int rc = 0; - struct mdss_pll_resources *rsc = context; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - *div = MDSS_PLL_REG_R(rsc->pll_base, reg); - - pr_debug("pclk_src div = %d\n", *div); - - (void)mdss_pll_resource_enable(rsc, false); - return rc; -} - -int pixel_clk_set_div(void *context, unsigned int reg, - unsigned int div) -{ - int rc = 0; - struct mdss_pll_resources *rsc = context; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - pr_debug("pclk_src div = %d\n", div); - - MDSS_PLL_REG_W(rsc->pll_base, reg, div); - - (void)mdss_pll_resource_enable(rsc, false); - return rc; -} - -int dsi_pll_lock_status(struct mdss_pll_resources *rsc) -{ - u32 status; - int pll_locked; - - /* poll for PLL ready status */ - if (readl_poll_timeout_atomic((rsc->pll_base + - DSI_PHY_PLL_UNIPHY_PLL_STATUS), - status, - ((status & BIT(0)) == 1), - DSI_PLL_POLL_DELAY_US, - DSI_PLL_POLL_TIMEOUT_US)) { - pr_debug("DSI PLL status=%x failed to Lock\n", status); - pll_locked = 0; - } else { - pll_locked = 1; - } - - return pll_locked; -} - -static int pll_28nm_vco_rate_calc(struct dsi_pll_vco_clk *vco, - struct mdss_dsi_vco_calc *vco_calc, unsigned long vco_clk_rate) -{ - s32 rem; - s64 frac_n_mode, ref_doubler_en_b; - s64 ref_clk_to_pll, div_fb, frac_n_value; - int i; - - /* Configure the Loop filter resistance */ - for (i = 0; i < vco->lpfr_lut_size; i++) - if (vco_clk_rate <= vco->lpfr_lut[i].vco_rate) - break; - if (i == vco->lpfr_lut_size) { - pr_err("unable to get loop filter resistance. vco=%ld\n", - vco_clk_rate); - return -EINVAL; - } - vco_calc->lpfr_lut_res = vco->lpfr_lut[i].r; - - div_s64_rem(vco_clk_rate, vco->ref_clk_rate, &rem); - if (rem) { - vco_calc->refclk_cfg = 0x1; - frac_n_mode = 1; - ref_doubler_en_b = 0; - } else { - vco_calc->refclk_cfg = 0x0; - frac_n_mode = 0; - ref_doubler_en_b = 1; - } - - pr_debug("refclk_cfg = %lld\n", vco_calc->refclk_cfg); - - ref_clk_to_pll = ((vco->ref_clk_rate * 2 * (vco_calc->refclk_cfg)) - + (ref_doubler_en_b * vco->ref_clk_rate)); - - div_fb = div_s64_rem(vco_clk_rate, ref_clk_to_pll, &rem); - frac_n_value = div_s64(((s64)rem * (1 << 16)), ref_clk_to_pll); - vco_calc->gen_vco_clk = vco_clk_rate; - - pr_debug("ref_clk_to_pll = %lld\n", ref_clk_to_pll); - pr_debug("div_fb = %lld\n", div_fb); - pr_debug("frac_n_value = %lld\n", frac_n_value); - - pr_debug("Generated VCO Clock: %lld\n", vco_calc->gen_vco_clk); - rem = 0; - if (frac_n_mode) { - vco_calc->sdm_cfg0 = 0; - vco_calc->sdm_cfg1 = (div_fb & 0x3f) - 1; - vco_calc->sdm_cfg3 = div_s64_rem(frac_n_value, 256, &rem); - vco_calc->sdm_cfg2 = rem; - } else { - vco_calc->sdm_cfg0 = (0x1 << 5); - vco_calc->sdm_cfg0 |= (div_fb & 0x3f) - 1; - vco_calc->sdm_cfg1 = 0; - vco_calc->sdm_cfg2 = 0; - vco_calc->sdm_cfg3 = 0; - } - - pr_debug("sdm_cfg0=%lld\n", vco_calc->sdm_cfg0); - pr_debug("sdm_cfg1=%lld\n", vco_calc->sdm_cfg1); - pr_debug("sdm_cfg2=%lld\n", vco_calc->sdm_cfg2); - pr_debug("sdm_cfg3=%lld\n", vco_calc->sdm_cfg3); - - vco_calc->cal_cfg11 = div_s64_rem(vco_calc->gen_vco_clk, - 256 * 1000000, &rem); - vco_calc->cal_cfg10 = rem / 1000000; - pr_debug("cal_cfg10=%lld, cal_cfg11=%lld\n", - vco_calc->cal_cfg10, vco_calc->cal_cfg11); - - return 0; -} - -static void pll_28nm_ssc_param_calc(struct dsi_pll_vco_clk *vco, - struct mdss_dsi_vco_calc *vco_calc) -{ - struct mdss_pll_resources *rsc = vco->priv; - s64 ppm_freq, incr, spread_freq, div_rf, frac_n_value; - s32 rem; - - if (!rsc->ssc_en) { - pr_debug("DSI PLL SSC not enabled\n"); - return; - } - - vco_calc->ssc.kdiv = DIV_ROUND_CLOSEST(vco->ref_clk_rate, - 1000000) - 1; - vco_calc->ssc.triang_steps = DIV_ROUND_CLOSEST(vco->ref_clk_rate, - rsc->ssc_freq * (vco_calc->ssc.kdiv + 1)); - ppm_freq = div_s64(vco_calc->gen_vco_clk * rsc->ssc_ppm, - 1000000); - incr = div64_s64(ppm_freq * 65536, vco->ref_clk_rate * 2 * - vco_calc->ssc.triang_steps); - - vco_calc->ssc.triang_inc_7_0 = incr & 0xff; - vco_calc->ssc.triang_inc_9_8 = (incr >> 8) & 0x3; - - if (!rsc->ssc_center) - spread_freq = vco_calc->gen_vco_clk - ppm_freq; - else - spread_freq = vco_calc->gen_vco_clk - (ppm_freq / 2); - - div_rf = div_s64(spread_freq, 2 * vco->ref_clk_rate); - vco_calc->ssc.dc_offset = (div_rf - 1); - - div_s64_rem(spread_freq, 2 * vco->ref_clk_rate, &rem); - frac_n_value = div_s64((s64)rem * 65536, 2 * vco->ref_clk_rate); - - vco_calc->ssc.freq_seed_7_0 = frac_n_value & 0xff; - vco_calc->ssc.freq_seed_15_8 = (frac_n_value >> 8) & 0xff; -} - -static void pll_28nm_vco_config(struct dsi_pll_vco_clk *vco, - struct mdss_dsi_vco_calc *vco_calc) -{ - struct mdss_pll_resources *rsc = vco->priv; - void __iomem *pll_base = rsc->pll_base; - u32 vco_delay_us = rsc->vco_delay; - bool ssc_en = rsc->ssc_en; - - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_LPFR_CFG, - vco_calc->lpfr_lut_res); - - /* Loop filter capacitance values : c1 and c2 */ - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_LPFC1_CFG, 0x70); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_LPFC2_CFG, 0x15); - - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_CHGPUMP_CFG, 0x02); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG3, 0x2b); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG4, 0x66); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x0d); - - if (!ssc_en) { - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1, - (u32)(vco_calc->sdm_cfg1 & 0xff)); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2, - (u32)(vco_calc->sdm_cfg2 & 0xff)); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3, - (u32)(vco_calc->sdm_cfg3 & 0xff)); - } else { - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1, - (u32)vco_calc->ssc.dc_offset); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2, - (u32)vco_calc->ssc.freq_seed_7_0); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3, - (u32)vco_calc->ssc.freq_seed_15_8); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SSC_CFG0, - (u32)vco_calc->ssc.kdiv); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SSC_CFG1, - (u32)vco_calc->ssc.triang_inc_7_0); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SSC_CFG2, - (u32)vco_calc->ssc.triang_inc_9_8); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SSC_CFG3, - (u32)vco_calc->ssc.triang_steps); - } - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG4, 0x00); - - /* Add hardware recommended delay for correct PLL configuration */ - if (vco_delay_us) - udelay(vco_delay_us); - - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_REFCLK_CFG, - (u32)vco_calc->refclk_cfg); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_VCOLPF_CFG, 0x71); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0, - (u32)vco_calc->sdm_cfg0); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG0, 0x12); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG6, 0x30); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG7, 0x00); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG8, 0x60); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG9, 0x00); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG10, - (u32)(vco_calc->cal_cfg10 & 0xff)); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG11, - (u32)(vco_calc->cal_cfg11 & 0xff)); - MDSS_PLL_REG_W(pll_base, DSI_PHY_PLL_UNIPHY_PLL_EFUSE_CFG, 0x20); - MDSS_PLL_REG_W(pll_base, - DSI_PHY_PLL_UNIPHY_PLL_POSTDIV2_CFG, 0x3); /* Fixed div-4 */ -} - -static int vco_set_rate(struct dsi_pll_vco_clk *vco, unsigned long rate) -{ - struct mdss_dsi_vco_calc vco_calc = {0}; - int rc = 0; - - rc = pll_28nm_vco_rate_calc(vco, &vco_calc, rate); - if (rc) { - pr_err("vco rate calculation failed\n"); - return rc; - } - - pll_28nm_ssc_param_calc(vco, &vco_calc); - pll_28nm_vco_config(vco, &vco_calc); - - return 0; -} - -static unsigned long vco_get_rate(struct dsi_pll_vco_clk *vco) -{ - struct mdss_pll_resources *rsc = vco->priv; - int rc; - u32 sdm0, doubler, sdm_byp_div; - u64 vco_rate; - u32 sdm_dc_off, sdm_freq_seed, sdm2, sdm3; - u64 ref_clk = vco->ref_clk_rate; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - /* Check to see if the ref clk doubler is enabled */ - doubler = MDSS_PLL_REG_R(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_REFCLK_CFG) & BIT(0); - ref_clk += (doubler * vco->ref_clk_rate); - - /* see if it is integer mode or sdm mode */ - sdm0 = MDSS_PLL_REG_R(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0); - if (sdm0 & BIT(6)) { - /* integer mode */ - sdm_byp_div = (MDSS_PLL_REG_R(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0) & 0x3f) + 1; - vco_rate = ref_clk * sdm_byp_div; - } else { - /* sdm mode */ - sdm_dc_off = MDSS_PLL_REG_R(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1) & 0xFF; - pr_debug("sdm_dc_off = %d\n", sdm_dc_off); - sdm2 = MDSS_PLL_REG_R(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2) & 0xFF; - sdm3 = MDSS_PLL_REG_R(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3) & 0xFF; - sdm_freq_seed = (sdm3 << 8) | sdm2; - pr_debug("sdm_freq_seed = %d\n", sdm_freq_seed); - - vco_rate = (ref_clk * (sdm_dc_off + 1)) + - mult_frac(ref_clk, sdm_freq_seed, BIT(16)); - pr_debug("vco rate = %lld\n", vco_rate); - } - - pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate); - - mdss_pll_resource_enable(rsc, false); - - return (unsigned long)vco_rate; -} - -static int dsi_pll_enable(struct dsi_pll_vco_clk *vco) -{ - int i, rc; - struct mdss_pll_resources *rsc = vco->priv; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("failed to enable dsi pll(%d) resources\n", - rsc->index); - return rc; - } - - /* Try all enable sequences until one succeeds */ - for (i = 0; i < vco->pll_en_seq_cnt; i++) { - rc = vco->pll_enable_seqs[i](rsc); - pr_debug("DSI PLL %s after sequence #%d\n", - rc ? "unlocked" : "locked", i + 1); - if (!rc) - break; - } - - if (rc) { - mdss_pll_resource_enable(rsc, false); - pr_err("DSI PLL failed to lock\n"); - } - rsc->pll_on = true; - - return rc; -} - -static void dsi_pll_disable(struct dsi_pll_vco_clk *vco) -{ - struct mdss_pll_resources *rsc = vco->priv; - - if (!rsc->pll_on && - mdss_pll_resource_enable(rsc, true)) { - pr_err("failed to enable dsi pll(%d) resources\n", - rsc->index); - return; - } - - rsc->handoff_resources = false; - - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x00); - - mdss_pll_resource_enable(rsc, false); - rsc->pll_on = false; - - pr_debug("DSI PLL Disabled\n"); -} - -int vco_28nm_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct mdss_pll_resources *rsc = vco->priv; - int rc; - - if (!rsc) { - pr_err("pll resource not found\n"); - return -EINVAL; - } - - if (rsc->pll_on) - return 0; - - pr_debug("ndx=%d, rate=%lu\n", rsc->index, rate); - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("failed to enable mdss dsi pll(%d), rc=%d\n", - rsc->index, rc); - return rc; - } - - /* - * DSI PLL software reset. Add HW recommended delays after toggling - * the software reset bit off and back on. - */ - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x01); - udelay(1000); - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x00); - udelay(1000); - - rc = vco_set_rate(vco, rate); - rsc->vco_current_rate = rate; - - mdss_pll_resource_enable(rsc, false); - - return 0; -} - -long vco_28nm_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - unsigned long rrate = rate; - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - - if (rate < vco->min_rate) - rrate = vco->min_rate; - if (rate > vco->max_rate) - rrate = vco->max_rate; - - *parent_rate = rrate; - - return rrate; -} - -unsigned long vco_28nm_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct mdss_pll_resources *rsc = vco->priv; - int rc; - u64 vco_rate = 0; - - if (!rsc) { - pr_err("dsi pll resources not available\n"); - return 0; - } - - if (rsc->vco_current_rate) - return (unsigned long)rsc->vco_current_rate; - - if (is_gdsc_disabled(rsc)) - return 0; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("failed to enable dsi pll(%d) resources\n", - rsc->index); - return 0; - } - - if (dsi_pll_lock_status(rsc)) { - rsc->handoff_resources = true; - rsc->pll_on = true; - vco_rate = vco_get_rate(vco); - } else { - mdss_pll_resource_enable(rsc, false); - } - - return (unsigned long)vco_rate; -} - -int vco_28nm_prepare(struct clk_hw *hw) -{ - int rc = 0; - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct mdss_pll_resources *rsc = vco->priv; - - if (!rsc) { - pr_err("dsi pll resources not available\n"); - return -EINVAL; - } - - if ((rsc->vco_cached_rate != 0) - && (rsc->vco_cached_rate == clk_hw_get_rate(hw))) { - rc = hw->init->ops->set_rate(hw, rsc->vco_cached_rate, - rsc->vco_cached_rate); - if (rc) { - pr_err("pll(%d ) set_rate failed. rc=%d\n", - rsc->index, rc); - goto error; - } - - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG, - rsc->cached_postdiv1); - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG, - rsc->cached_postdiv3); - MDSS_PLL_REG_W(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG, - rsc->cached_vreg_cfg); - } - - rc = dsi_pll_enable(vco); - -error: - return rc; -} - -void vco_28nm_unprepare(struct clk_hw *hw) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct mdss_pll_resources *rsc = vco->priv; - - if (!rsc) { - pr_err("dsi pll resources not available\n"); - return; - } - - rsc->cached_postdiv1 = MDSS_PLL_REG_R(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG); - rsc->cached_postdiv3 = MDSS_PLL_REG_R(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG); - rsc->cached_vreg_cfg = MDSS_PLL_REG_R(rsc->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG); - - rsc->vco_cached_rate = clk_hw_get_rate(hw); - - dsi_pll_disable(vco); -} diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-28nm.h b/drivers/clk/qcom/mdss/mdss-dsi-pll-28nm.h deleted file mode 100644 index fc03f36a94de2eaa48814f41d6c58c5d6ce3d1e1..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-28nm.h +++ /dev/null @@ -1,64 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. - */ - -#ifndef __MDSS_DSI_PLL_28NM_H -#define __MDSS_DSI_PLL_28NM_H - -#define DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG (0x0020) -#define DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2 (0x0064) -#define DSI_PHY_PLL_UNIPHY_PLL_TEST_CFG (0x0068) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG1 (0x0070) - -#define DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG (0x0004) -#define DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG (0x0028) -#define DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG (0x0010) - -struct ssc_params { - s32 kdiv; - s64 triang_inc_7_0; - s64 triang_inc_9_8; - s64 triang_steps; - s64 dc_offset; - s64 freq_seed_7_0; - s64 freq_seed_15_8; -}; - -struct mdss_dsi_vco_calc { - s64 sdm_cfg0; - s64 sdm_cfg1; - s64 sdm_cfg2; - s64 sdm_cfg3; - s64 cal_cfg10; - s64 cal_cfg11; - s64 refclk_cfg; - s64 gen_vco_clk; - u32 lpfr_lut_res; - struct ssc_params ssc; -}; - -unsigned long vco_28nm_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate); -int vco_28nm_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate); -long vco_28nm_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate); -int vco_28nm_prepare(struct clk_hw *hw); -void vco_28nm_unprepare(struct clk_hw *hw); - -int analog_postdiv_reg_write(void *context, - unsigned int reg, unsigned int div); -int analog_postdiv_reg_read(void *context, - unsigned int reg, unsigned int *div); -int byteclk_mux_write_sel(void *context, - unsigned int reg, unsigned int val); -int byteclk_mux_read_sel(void *context, - unsigned int reg, unsigned int *val); -int pixel_clk_set_div(void *context, - unsigned int reg, unsigned int div); -int pixel_clk_get_div(void *context, - unsigned int reg, unsigned int *div); - -int dsi_pll_lock_status(struct mdss_pll_resources *rsc); -#endif /* __MDSS_DSI_PLL_28NM_H */ diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-7nm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-7nm.c deleted file mode 100644 index e1e7abcbc81192ef995bd664f9dcd91328d060c6..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-7nm.c +++ /dev/null @@ -1,1942 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include "mdss-dsi-pll.h" -#include "mdss-pll.h" -#include - -#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 0x0000 -#define PLL_ANALOG_CONTROLS_TWO 0x0004 -#define PLL_INT_LOOP_SETTINGS 0x0008 -#define PLL_INT_LOOP_SETTINGS_TWO 0x000C -#define PLL_ANALOG_CONTROLS_THREE 0x0010 -#define PLL_ANALOG_CONTROLS_FOUR 0x0014 -#define PLL_ANALOG_CONTROLS_FIVE 0x0018 -#define PLL_INT_LOOP_CONTROLS 0x001C -#define PLL_DSM_DIVIDER 0x0020 -#define PLL_FEEDBACK_DIVIDER 0x0024 -#define PLL_SYSTEM_MUXES 0x0028 -#define PLL_FREQ_UPDATE_CONTROL_OVERRIDES 0x002C -#define PLL_CMODE 0x0030 -#define PLL_PSM_CTRL 0x0034 -#define PLL_RSM_CTRL 0x0038 -#define PLL_VCO_TUNE_MAP 0x003C -#define PLL_PLL_CNTRL 0x0040 -#define PLL_CALIBRATION_SETTINGS 0x0044 -#define PLL_BAND_SEL_CAL_TIMER_LOW 0x0048 -#define PLL_BAND_SEL_CAL_TIMER_HIGH 0x004C -#define PLL_BAND_SEL_CAL_SETTINGS 0x0050 -#define PLL_BAND_SEL_MIN 0x0054 -#define PLL_BAND_SEL_MAX 0x0058 -#define PLL_BAND_SEL_PFILT 0x005C -#define PLL_BAND_SEL_IFILT 0x0060 -#define PLL_BAND_SEL_CAL_SETTINGS_TWO 0x0064 -#define PLL_BAND_SEL_CAL_SETTINGS_THREE 0x0068 -#define PLL_BAND_SEL_CAL_SETTINGS_FOUR 0x006C -#define PLL_BAND_SEL_ICODE_HIGH 0x0070 -#define PLL_BAND_SEL_ICODE_LOW 0x0074 -#define PLL_FREQ_DETECT_SETTINGS_ONE 0x0078 -#define PLL_FREQ_DETECT_THRESH 0x007C -#define PLL_FREQ_DET_REFCLK_HIGH 0x0080 -#define PLL_FREQ_DET_REFCLK_LOW 0x0084 -#define PLL_FREQ_DET_PLLCLK_HIGH 0x0088 -#define PLL_FREQ_DET_PLLCLK_LOW 0x008C -#define PLL_PFILT 0x0090 -#define PLL_IFILT 0x0094 -#define PLL_PLL_GAIN 0x0098 -#define PLL_ICODE_LOW 0x009C -#define PLL_ICODE_HIGH 0x00A0 -#define PLL_LOCKDET 0x00A4 -#define PLL_OUTDIV 0x00A8 -#define PLL_FASTLOCK_CONTROL 0x00AC -#define PLL_PASS_OUT_OVERRIDE_ONE 0x00B0 -#define PLL_PASS_OUT_OVERRIDE_TWO 0x00B4 -#define PLL_CORE_OVERRIDE 0x00B8 -#define PLL_CORE_INPUT_OVERRIDE 0x00BC -#define PLL_RATE_CHANGE 0x00C0 -#define PLL_PLL_DIGITAL_TIMERS 0x00C4 -#define PLL_PLL_DIGITAL_TIMERS_TWO 0x00C8 -#define PLL_DECIMAL_DIV_START 0x00CC -#define PLL_FRAC_DIV_START_LOW 0x00D0 -#define PLL_FRAC_DIV_START_MID 0x00D4 -#define PLL_FRAC_DIV_START_HIGH 0x00D8 -#define PLL_DEC_FRAC_MUXES 0x00DC -#define PLL_DECIMAL_DIV_START_1 0x00E0 -#define PLL_FRAC_DIV_START_LOW_1 0x00E4 -#define PLL_FRAC_DIV_START_MID_1 0x00E8 -#define PLL_FRAC_DIV_START_HIGH_1 0x00EC -#define PLL_DECIMAL_DIV_START_2 0x00F0 -#define PLL_FRAC_DIV_START_LOW_2 0x00F4 -#define PLL_FRAC_DIV_START_MID_2 0x00F8 -#define PLL_FRAC_DIV_START_HIGH_2 0x00FC -#define PLL_MASH_CONTROL 0x0100 -#define PLL_SSC_STEPSIZE_LOW 0x0104 -#define PLL_SSC_STEPSIZE_HIGH 0x0108 -#define PLL_SSC_DIV_PER_LOW 0x010C -#define PLL_SSC_DIV_PER_HIGH 0x0110 -#define PLL_SSC_ADJPER_LOW 0x0114 -#define PLL_SSC_ADJPER_HIGH 0x0118 -#define PLL_SSC_MUX_CONTROL 0x011C -#define PLL_SSC_STEPSIZE_LOW_1 0x0120 -#define PLL_SSC_STEPSIZE_HIGH_1 0x0124 -#define PLL_SSC_DIV_PER_LOW_1 0x0128 -#define PLL_SSC_DIV_PER_HIGH_1 0x012C -#define PLL_SSC_ADJPER_LOW_1 0x0130 -#define PLL_SSC_ADJPER_HIGH_1 0x0134 -#define PLL_SSC_STEPSIZE_LOW_2 0x0138 -#define PLL_SSC_STEPSIZE_HIGH_2 0x013C -#define PLL_SSC_DIV_PER_LOW_2 0x0140 -#define PLL_SSC_DIV_PER_HIGH_2 0x0144 -#define PLL_SSC_ADJPER_LOW_2 0x0148 -#define PLL_SSC_ADJPER_HIGH_2 0x014C -#define PLL_SSC_CONTROL 0x0150 -#define PLL_PLL_OUTDIV_RATE 0x0154 -#define PLL_PLL_LOCKDET_RATE_1 0x0158 -#define PLL_PLL_LOCKDET_RATE_2 0x015C -#define PLL_PLL_PROP_GAIN_RATE_1 0x0160 -#define PLL_PLL_PROP_GAIN_RATE_2 0x0164 -#define PLL_PLL_BAND_SEL_RATE_1 0x0168 -#define PLL_PLL_BAND_SEL_RATE_2 0x016C -#define PLL_PLL_INT_GAIN_IFILT_BAND_1 0x0170 -#define PLL_PLL_INT_GAIN_IFILT_BAND_2 0x0174 -#define PLL_PLL_FL_INT_GAIN_PFILT_BAND_1 0x0178 -#define PLL_PLL_FL_INT_GAIN_PFILT_BAND_2 0x017C -#define PLL_PLL_FASTLOCK_EN_BAND 0x0180 -#define PLL_FREQ_TUNE_ACCUM_INIT_MID 0x0184 -#define PLL_FREQ_TUNE_ACCUM_INIT_HIGH 0x0188 -#define PLL_FREQ_TUNE_ACCUM_INIT_MUX 0x018C -#define PLL_PLL_LOCK_OVERRIDE 0x0190 -#define PLL_PLL_LOCK_DELAY 0x0194 -#define PLL_PLL_LOCK_MIN_DELAY 0x0198 -#define PLL_CLOCK_INVERTERS 0x019C -#define PLL_SPARE_AND_JPC_OVERRIDES 0x01A0 -#define PLL_BIAS_CONTROL_1 0x01A4 -#define PLL_BIAS_CONTROL_2 0x01A8 -#define PLL_ALOG_OBSV_BUS_CTRL_1 0x01AC -#define PLL_COMMON_STATUS_ONE 0x01B0 -#define PLL_COMMON_STATUS_TWO 0x01B4 -#define PLL_BAND_SEL_CAL 0x01B8 -#define PLL_ICODE_ACCUM_STATUS_LOW 0x01BC -#define PLL_ICODE_ACCUM_STATUS_HIGH 0x01C0 -#define PLL_FD_OUT_LOW 0x01C4 -#define PLL_FD_OUT_HIGH 0x01C8 -#define PLL_ALOG_OBSV_BUS_STATUS_1 0x01CC -#define PLL_PLL_MISC_CONFIG 0x01D0 -#define PLL_FLL_CONFIG 0x01D4 -#define PLL_FLL_FREQ_ACQ_TIME 0x01D8 -#define PLL_FLL_CODE0 0x01DC -#define PLL_FLL_CODE1 0x01E0 -#define PLL_FLL_GAIN0 0x01E4 -#define PLL_FLL_GAIN1 0x01E8 -#define PLL_SW_RESET 0x01EC -#define PLL_FAST_PWRUP 0x01F0 -#define PLL_LOCKTIME0 0x01F4 -#define PLL_LOCKTIME1 0x01F8 -#define PLL_DEBUG_BUS_SEL 0x01FC -#define PLL_DEBUG_BUS0 0x0200 -#define PLL_DEBUG_BUS1 0x0204 -#define PLL_DEBUG_BUS2 0x0208 -#define PLL_DEBUG_BUS3 0x020C -#define PLL_ANALOG_FLL_CONTROL_OVERRIDES 0x0210 -#define PLL_VCO_CONFIG 0x0214 -#define PLL_VCO_CAL_CODE1_MODE0_STATUS 0x0218 -#define PLL_VCO_CAL_CODE1_MODE1_STATUS 0x021C -#define PLL_RESET_SM_STATUS 0x0220 -#define PLL_TDC_OFFSET 0x0224 -#define PLL_PS3_PWRDOWN_CONTROLS 0x0228 -#define PLL_PS4_PWRDOWN_CONTROLS 0x022C -#define PLL_PLL_RST_CONTROLS 0x0230 -#define PLL_GEAR_BAND_SELECT_CONTROLS 0x0234 -#define PLL_PSM_CLK_CONTROLS 0x0238 -#define PLL_SYSTEM_MUXES_2 0x023C -#define PLL_VCO_CONFIG_1 0x0240 -#define PLL_VCO_CONFIG_2 0x0244 -#define PLL_CLOCK_INVERTERS_1 0x0248 -#define PLL_CLOCK_INVERTERS_2 0x024C -#define PLL_CMODE_1 0x0250 -#define PLL_CMODE_2 0x0254 -#define PLL_ANALOG_CONTROLS_FIVE_1 0x0258 -#define PLL_ANALOG_CONTROLS_FIVE_2 0x025C -#define PLL_PERF_OPTIMIZE 0x0260 - -/* 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_CTRL_0 0x024 -#define PHY_CMN_CTRL_3 0x030 -#define PHY_CMN_PLL_CNTRL 0x03C -#define PHY_CMN_GLBL_DIGTOP_SPARE4 0x128 - -/* 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_7nm { - struct mdss_pll_resources *rsc; - struct dsi_pll_config pll_configuration; - struct dsi_pll_regs reg_setup; -}; - -static inline bool dsi_pll_7nm_is_hw_revision_v1( - struct mdss_pll_resources *rsc) -{ - return (rsc->pll_interface_type == MDSS_DSI_PLL_7NM) ? true : false; -} - -static inline bool dsi_pll_7nm_is_hw_revision_v2( - struct mdss_pll_resources *rsc) -{ - return (rsc->pll_interface_type == MDSS_DSI_PLL_7NM_V2) ? true : false; -} - -static inline bool dsi_pll_7nm_is_hw_revision_v4_1( - struct mdss_pll_resources *rsc) -{ - return (rsc->pll_interface_type == MDSS_DSI_PLL_7NM_V4_1) ? - true : false; -} - -static inline int pll_reg_read(void *context, unsigned int reg, - unsigned int *val) -{ - int rc = 0; - u32 data; - struct mdss_pll_resources *rsc = context; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - /* - * DSI PHY/PLL should be both powered on when reading PLL - * registers. Since PHY power has been enabled in DSI PHY - * driver, only PLL power is needed to enable here. - */ - data = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CTRL_0); - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data | BIT(5)); - ndelay(250); - - *val = MDSS_PLL_REG_R(rsc->pll_base, reg); - - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data); - - (void)mdss_pll_resource_enable(rsc, false); - - return rc; -} - -static inline int pll_reg_write(void *context, unsigned int reg, - unsigned int val) -{ - int rc = 0; - struct mdss_pll_resources *rsc = context; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - MDSS_PLL_REG_W(rsc->pll_base, reg, val); - (void)mdss_pll_resource_enable(rsc, false); - - return rc; -} - -static inline int phy_reg_read(void *context, unsigned int reg, - unsigned int *val) -{ - int rc = 0; - struct mdss_pll_resources *rsc = context; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - *val = MDSS_PLL_REG_R(rsc->phy_base, reg); - (void)mdss_pll_resource_enable(rsc, false); - - return rc; -} - -static inline int phy_reg_write(void *context, unsigned int reg, - unsigned int val) -{ - int rc = 0; - struct mdss_pll_resources *rsc = context; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - MDSS_PLL_REG_W(rsc->phy_base, reg, val); - (void)mdss_pll_resource_enable(rsc, false); - - return rc; -} - -static inline int phy_reg_update_bits_sub(struct mdss_pll_resources *rsc, - unsigned int reg, unsigned int mask, unsigned int val) -{ - u32 reg_val; - - reg_val = MDSS_PLL_REG_R(rsc->phy_base, reg); - reg_val &= ~mask; - reg_val |= (val & mask); - MDSS_PLL_REG_W(rsc->phy_base, reg, reg_val); - - return 0; -} - -static inline int phy_reg_update_bits(void *context, unsigned int reg, - unsigned int mask, unsigned int val) -{ - int rc = 0; - struct mdss_pll_resources *rsc = context; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - rc = phy_reg_update_bits_sub(rsc, reg, mask, val); - if (!rc && rsc->slave) - rc = phy_reg_update_bits_sub(rsc->slave, reg, mask, val); - (void)mdss_pll_resource_enable(rsc, false); - - return rc; -} - -static inline int pclk_mux_read_sel(void *context, unsigned int reg, - unsigned int *val) -{ - int rc = 0; - struct mdss_pll_resources *rsc = context; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - else - *val = (MDSS_PLL_REG_R(rsc->phy_base, reg) & 0x3); - - (void)mdss_pll_resource_enable(rsc, false); - return rc; -} - - -static inline int pclk_mux_write_sel_sub(struct mdss_pll_resources *rsc, - unsigned int reg, unsigned int val) -{ - u32 reg_val; - - reg_val = MDSS_PLL_REG_R(rsc->phy_base, reg); - reg_val &= ~0x03; - reg_val |= val; - - MDSS_PLL_REG_W(rsc->phy_base, reg, reg_val); - - return 0; -} - -static inline int pclk_mux_write_sel(void *context, unsigned int reg, - unsigned int val) -{ - int rc = 0; - struct mdss_pll_resources *rsc = context; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - rc = pclk_mux_write_sel_sub(rsc, reg, val); - if (!rc && rsc->slave) - rc = pclk_mux_write_sel_sub(rsc->slave, reg, val); - - (void)mdss_pll_resource_enable(rsc, false); - - /* - * cache the current parent index for cases where parent - * is not changing but rate is changing. In that case - * clock framework won't call parent_set and hence dsiclk_sel - * bit won't be programmed. e.g. dfps update use case. - */ - rsc->cached_cfg1 = val; - - return rc; -} - -static struct mdss_pll_resources *pll_rsc_db[DSI_PLL_MAX]; -static struct dsi_pll_7nm plls[DSI_PLL_MAX]; - -static void dsi_pll_config_slave(struct mdss_pll_resources *rsc) -{ - u32 reg; - struct mdss_pll_resources *orsc = pll_rsc_db[DSI_PLL_1]; - - if (!rsc) - return; - - /* Only DSI PLL0 can act as a master */ - if (rsc->index != DSI_PLL_0) - return; - - /* default configuration: source is either internal or ref clock */ - rsc->slave = NULL; - - if (!orsc) { - pr_warn("slave PLL unavilable, assuming standalone config\n"); - return; - } - - /* check to see if the source of DSI1 PLL bitclk is set to external */ - reg = MDSS_PLL_REG_R(orsc->phy_base, PHY_CMN_CLK_CFG1); - reg &= (BIT(2) | BIT(3)); - if (reg == 0x04) - rsc->slave = pll_rsc_db[DSI_PLL_1]; /* external source */ - - pr_debug("Slave PLL %s\n", rsc->slave ? "configured" : "absent"); -} - -static void dsi_pll_setup_config(struct dsi_pll_7nm *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; - } - - dsi_pll_config_slave(rsc); -} - -static void dsi_pll_calc_dec_frac(struct dsi_pll_7nm *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); - - switch (rsc->pll_interface_type) { - case MDSS_DSI_PLL_7NM: - regs->pll_clock_inverters = 0x0; - break; - case MDSS_DSI_PLL_7NM_V2: - regs->pll_clock_inverters = 0x28; - break; - case MDSS_DSI_PLL_7NM_V4_1: - default: - if (pll_freq <= 1000000000) - regs->pll_clock_inverters = 0xA0; - else if (pll_freq <= 2500000000) - regs->pll_clock_inverters = 0x20; - else if (pll_freq <= 3020000000) - regs->pll_clock_inverters = 0x00; - else - regs->pll_clock_inverters = 0x40; - break; - } - - 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_7nm *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) { - pr_debug("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; - - pr_debug("SCC: Dec:%d, frac:%llu, frac_bits:%d\n", - regs->decimal_div_start, frac, config->frac_bits); - pr_debug("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_ssc_commit(struct dsi_pll_7nm *pll, - struct mdss_pll_resources *rsc) -{ - void __iomem *pll_base = rsc->pll_base; - struct dsi_pll_regs *regs = &pll->reg_setup; - - if (pll->pll_configuration.enable_ssc) { - pr_debug("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_ADJPER_LOW_1, - regs->ssc_adjper_low); - MDSS_PLL_REG_W(pll_base, PLL_SSC_ADJPER_HIGH_1, - regs->ssc_adjper_high); - MDSS_PLL_REG_W(pll_base, PLL_SSC_CONTROL, - SSC_EN | regs->ssc_control); - } -} - -static void dsi_pll_config_hzindep_reg(struct dsi_pll_7nm *pll, - struct mdss_pll_resources *rsc) -{ - void __iomem *pll_base = rsc->pll_base; - u64 vco_rate = rsc->vco_current_rate; - - switch (rsc->pll_interface_type) { - case MDSS_DSI_PLL_7NM: - case MDSS_DSI_PLL_7NM_V2: - MDSS_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_FIVE_1, 0x01); - MDSS_PLL_REG_W(pll_base, PLL_VCO_CONFIG_1, 0x00); - break; - case MDSS_DSI_PLL_7NM_V4_1: - default: - if (vco_rate < 3100000000) - MDSS_PLL_REG_W(pll_base, - PLL_ANALOG_CONTROLS_FIVE_1, 0x01); - else - MDSS_PLL_REG_W(pll_base, - PLL_ANALOG_CONTROLS_FIVE_1, 0x03); - - if (vco_rate < 1520000000) - MDSS_PLL_REG_W(pll_base, PLL_VCO_CONFIG_1, 0x08); - else if (vco_rate < 2990000000) - MDSS_PLL_REG_W(pll_base, PLL_VCO_CONFIG_1, 0x01); - else - MDSS_PLL_REG_W(pll_base, PLL_VCO_CONFIG_1, 0x00); - - break; - } - - if (dsi_pll_7nm_is_hw_revision_v1(rsc)) - MDSS_PLL_REG_W(pll_base, PLL_GEAR_BAND_SELECT_CONTROLS, 0x21); - - MDSS_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_FIVE, 0x01); - 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, 0x0a); - MDSS_PLL_REG_W(pll_base, PLL_PLL_BAND_SEL_RATE_1, 0xc0); - MDSS_PLL_REG_W(pll_base, PLL_PLL_INT_GAIN_IFILT_BAND_1, 0x84); - MDSS_PLL_REG_W(pll_base, PLL_PLL_INT_GAIN_IFILT_BAND_1, 0x82); - 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_PFILT, 0x2f); - MDSS_PLL_REG_W(pll_base, PLL_IFILT, 0x2a); - - switch (rsc->pll_interface_type) { - case MDSS_DSI_PLL_7NM: - MDSS_PLL_REG_W(pll_base, PLL_IFILT, 0x30); - break; - case MDSS_DSI_PLL_7NM_V2: - MDSS_PLL_REG_W(pll_base, PLL_IFILT, 0x22); - break; - case MDSS_DSI_PLL_7NM_V4_1: - default: - MDSS_PLL_REG_W(pll_base, PLL_IFILT, 0x3F); - break; - } - - if (dsi_pll_7nm_is_hw_revision_v4_1(rsc)) - MDSS_PLL_REG_W(pll_base, PLL_PERF_OPTIMIZE, 0x22); -} - -static void dsi_pll_init_val(struct mdss_pll_resources *rsc) -{ - void __iomem *pll_base = rsc->pll_base; - - MDSS_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_ONE, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_INT_LOOP_SETTINGS, 0x0000003F); - MDSS_PLL_REG_W(pll_base, PLL_INT_LOOP_SETTINGS_TWO, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_FOUR, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_INT_LOOP_CONTROLS, 0x00000080); - MDSS_PLL_REG_W(pll_base, PLL_SYSTEM_MUXES, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_FREQ_UPDATE_CONTROL_OVERRIDES, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_CMODE, 0x00000010); - MDSS_PLL_REG_W(pll_base, PLL_PSM_CTRL, 0x00000020); - MDSS_PLL_REG_W(pll_base, PLL_RSM_CTRL, 0x00000010); - MDSS_PLL_REG_W(pll_base, PLL_VCO_TUNE_MAP, 0x00000002); - MDSS_PLL_REG_W(pll_base, PLL_PLL_CNTRL, 0x0000001C); - MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_TIMER_LOW, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_TIMER_HIGH, 0x00000002); - MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS, 0x00000020); - MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_MIN, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_MAX, 0x000000FF); - MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_PFILT, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_IFILT, 0x0000000A); - MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS_TWO, 0x00000025); - MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS_THREE, 0x000000BA); - MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS_FOUR, 0x0000004F); - MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_ICODE_HIGH, 0x0000000A); - MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_ICODE_LOW, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_FREQ_DETECT_SETTINGS_ONE, 0x0000000C); - MDSS_PLL_REG_W(pll_base, PLL_FREQ_DETECT_THRESH, 0x00000020); - MDSS_PLL_REG_W(pll_base, PLL_FREQ_DET_REFCLK_HIGH, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_FREQ_DET_REFCLK_LOW, 0x000000FF); - MDSS_PLL_REG_W(pll_base, PLL_FREQ_DET_PLLCLK_HIGH, 0x00000010); - MDSS_PLL_REG_W(pll_base, PLL_FREQ_DET_PLLCLK_LOW, 0x00000046); - MDSS_PLL_REG_W(pll_base, PLL_PLL_GAIN, 0x00000054); - MDSS_PLL_REG_W(pll_base, PLL_ICODE_LOW, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_ICODE_HIGH, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_LOCKDET, 0x00000040); - MDSS_PLL_REG_W(pll_base, PLL_FASTLOCK_CONTROL, 0x00000004); - MDSS_PLL_REG_W(pll_base, PLL_PASS_OUT_OVERRIDE_ONE, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_PASS_OUT_OVERRIDE_TWO, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_CORE_OVERRIDE, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_CORE_INPUT_OVERRIDE, 0x00000010); - MDSS_PLL_REG_W(pll_base, PLL_RATE_CHANGE, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_PLL_DIGITAL_TIMERS, 0x00000008); - MDSS_PLL_REG_W(pll_base, PLL_PLL_DIGITAL_TIMERS_TWO, 0x00000008); - MDSS_PLL_REG_W(pll_base, PLL_DEC_FRAC_MUXES, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_MASH_CONTROL, 0x00000003); - MDSS_PLL_REG_W(pll_base, PLL_SSC_STEPSIZE_LOW, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_SSC_STEPSIZE_HIGH, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_SSC_DIV_PER_LOW, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_SSC_DIV_PER_HIGH, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_SSC_ADJPER_LOW, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_SSC_ADJPER_HIGH, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_SSC_MUX_CONTROL, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_SSC_STEPSIZE_LOW_1, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_SSC_STEPSIZE_HIGH_1, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_SSC_DIV_PER_LOW_1, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_SSC_DIV_PER_HIGH_1, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_SSC_ADJPER_LOW_1, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_SSC_ADJPER_HIGH_1, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_SSC_STEPSIZE_LOW_2, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_SSC_STEPSIZE_HIGH_2, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_SSC_DIV_PER_LOW_2, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_SSC_DIV_PER_HIGH_2, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_SSC_ADJPER_LOW_2, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_SSC_ADJPER_HIGH_2, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_SSC_CONTROL, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_PLL_OUTDIV_RATE, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCKDET_RATE_1, 0x00000040); - MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCKDET_RATE_2, 0x00000040); - MDSS_PLL_REG_W(pll_base, PLL_PLL_PROP_GAIN_RATE_1, 0x0000000C); - MDSS_PLL_REG_W(pll_base, PLL_PLL_PROP_GAIN_RATE_2, 0x0000000A); - MDSS_PLL_REG_W(pll_base, PLL_PLL_BAND_SEL_RATE_1, 0x000000C0); - MDSS_PLL_REG_W(pll_base, PLL_PLL_BAND_SEL_RATE_2, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_PLL_INT_GAIN_IFILT_BAND_1, 0x00000054); - MDSS_PLL_REG_W(pll_base, PLL_PLL_INT_GAIN_IFILT_BAND_2, 0x00000054); - MDSS_PLL_REG_W(pll_base, PLL_PLL_FL_INT_GAIN_PFILT_BAND_1, 0x0000004C); - MDSS_PLL_REG_W(pll_base, PLL_PLL_FL_INT_GAIN_PFILT_BAND_2, 0x0000004C); - MDSS_PLL_REG_W(pll_base, PLL_PLL_FASTLOCK_EN_BAND, 0x00000003); - MDSS_PLL_REG_W(pll_base, PLL_FREQ_TUNE_ACCUM_INIT_MID, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_FREQ_TUNE_ACCUM_INIT_HIGH, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_FREQ_TUNE_ACCUM_INIT_MUX, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCK_OVERRIDE, 0x00000080); - MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCK_DELAY, 0x00000006); - MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCK_MIN_DELAY, 0x00000019); - MDSS_PLL_REG_W(pll_base, PLL_CLOCK_INVERTERS, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_SPARE_AND_JPC_OVERRIDES, 0x00000000); - - if (dsi_pll_7nm_is_hw_revision_v1(rsc)) - MDSS_PLL_REG_W(pll_base, PLL_BIAS_CONTROL_1, 0x00000066); - else - MDSS_PLL_REG_W(pll_base, PLL_BIAS_CONTROL_1, 0x00000040); - - MDSS_PLL_REG_W(pll_base, PLL_BIAS_CONTROL_2, 0x00000020); - MDSS_PLL_REG_W(pll_base, PLL_ALOG_OBSV_BUS_CTRL_1, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_COMMON_STATUS_ONE, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_COMMON_STATUS_TWO, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_ICODE_ACCUM_STATUS_LOW, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_ICODE_ACCUM_STATUS_HIGH, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_FD_OUT_LOW, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_FD_OUT_HIGH, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_ALOG_OBSV_BUS_STATUS_1, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_PLL_MISC_CONFIG, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_FLL_CONFIG, 0x00000002); - MDSS_PLL_REG_W(pll_base, PLL_FLL_FREQ_ACQ_TIME, 0x00000011); - MDSS_PLL_REG_W(pll_base, PLL_FLL_CODE0, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_FLL_CODE1, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_FLL_GAIN0, 0x00000080); - MDSS_PLL_REG_W(pll_base, PLL_FLL_GAIN1, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_SW_RESET, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_FAST_PWRUP, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_LOCKTIME0, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_LOCKTIME1, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_DEBUG_BUS_SEL, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_DEBUG_BUS0, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_DEBUG_BUS1, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_DEBUG_BUS2, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_DEBUG_BUS3, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_ANALOG_FLL_CONTROL_OVERRIDES, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_VCO_CONFIG, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_VCO_CAL_CODE1_MODE0_STATUS, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_VCO_CAL_CODE1_MODE1_STATUS, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_RESET_SM_STATUS, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_TDC_OFFSET, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_PS3_PWRDOWN_CONTROLS, 0x0000001D); - MDSS_PLL_REG_W(pll_base, PLL_PS4_PWRDOWN_CONTROLS, 0x0000001C); - MDSS_PLL_REG_W(pll_base, PLL_PLL_RST_CONTROLS, 0x000000FF); - MDSS_PLL_REG_W(pll_base, PLL_GEAR_BAND_SELECT_CONTROLS, 0x00000022); - MDSS_PLL_REG_W(pll_base, PLL_PSM_CLK_CONTROLS, 0x00000009); - MDSS_PLL_REG_W(pll_base, PLL_SYSTEM_MUXES_2, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_VCO_CONFIG_1, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_VCO_CONFIG_2, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_CLOCK_INVERTERS_1, 0x00000040); - MDSS_PLL_REG_W(pll_base, PLL_CLOCK_INVERTERS_2, 0x00000000); - MDSS_PLL_REG_W(pll_base, PLL_CMODE_1, 0x00000010); - MDSS_PLL_REG_W(pll_base, PLL_CMODE_2, 0x00000010); - MDSS_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_FIVE_2, 0x00000003); - -} - -static void dsi_pll_commit(struct dsi_pll_7nm *pll, - struct mdss_pll_resources *rsc) -{ - void __iomem *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_1, 0x10); - MDSS_PLL_REG_W(pll_base, PLL_CLOCK_INVERTERS_1, - reg->pll_clock_inverters); -} - -static int vco_7nm_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - int rc; - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct mdss_pll_resources *rsc = vco->priv; - struct dsi_pll_7nm *pll; - - if (!rsc) { - pr_err("pll resource not found\n"); - return -EINVAL; - } - - if (rsc->pll_on) - return 0; - - pll = rsc->priv; - if (!pll) { - pr_err("pll configuration not found\n"); - return -EINVAL; - } - - pr_debug("ndx=%d, rate=%lu\n", rsc->index, rate); - - rsc->vco_current_rate = rate; - rsc->vco_ref_clk_rate = vco->ref_clk_rate; - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("failed to enable mdss dsi pll(%d), rc=%d\n", - rsc->index, rc); - return rc; - } - - 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(); - - mdss_pll_resource_enable(rsc, false); - - return 0; -} - -static int dsi_pll_7nm_lock_status(struct mdss_pll_resources *pll) -{ - int rc; - u32 status; - u32 const delay_us = 100; - u32 const timeout_us = 5000; - - rc = readl_poll_timeout_atomic(pll->pll_base + PLL_COMMON_STATUS_ONE, - status, - ((status & BIT(0)) > 0), - delay_us, - timeout_us); - if (rc && !pll->handoff_resources) - pr_err("DSI PLL(%d) lock failed, status=0x%08x\n", - pll->index, status); - - return rc; -} - -static void dsi_pll_disable_pll_bias(struct mdss_pll_resources *rsc) -{ - u32 data = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CTRL_0); - - MDSS_PLL_REG_W(rsc->pll_base, PLL_SYSTEM_MUXES, 0); - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data & ~BIT(5)); - ndelay(250); -} - -static void dsi_pll_enable_pll_bias(struct mdss_pll_resources *rsc) -{ - u32 data = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CTRL_0); - - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data | BIT(5)); - MDSS_PLL_REG_W(rsc->pll_base, PLL_SYSTEM_MUXES, 0xc0); - ndelay(250); -} - -static void dsi_pll_disable_global_clk(struct mdss_pll_resources *rsc) -{ - u32 data; - - data = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG1); - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CLK_CFG1, (data & ~BIT(5))); -} - -static void dsi_pll_enable_global_clk(struct mdss_pll_resources *rsc) -{ - u32 data; - - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_3, 0x04); - - data = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG1); - - /* Turn on clk_en_sel bit prior to resync toggle fifo */ - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CLK_CFG1, (data | BIT(5) | - BIT(4))); -} - -static void dsi_pll_phy_dig_reset(struct mdss_pll_resources *rsc) -{ - /* - * Reset the PHY digital domain. This would be needed when - * coming out of a CX or analog rail power collapse while - * ensuring that the pads maintain LP00 or LP11 state - */ - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_GLBL_DIGTOP_SPARE4, BIT(0)); - wmb(); /* Ensure that the reset is asserted */ - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_GLBL_DIGTOP_SPARE4, 0x0); - wmb(); /* Ensure that the reset is deasserted */ -} - -static int dsi_pll_enable(struct dsi_pll_vco_clk *vco) -{ - int rc; - struct mdss_pll_resources *rsc = vco->priv; - - dsi_pll_enable_pll_bias(rsc); - if (rsc->slave) - dsi_pll_enable_pll_bias(rsc->slave); - - phy_reg_update_bits_sub(rsc, PHY_CMN_CLK_CFG1, 0x03, rsc->cached_cfg1); - if (rsc->slave) - phy_reg_update_bits_sub(rsc->slave, PHY_CMN_CLK_CFG1, - 0x03, rsc->cached_cfg1); - wmb(); /* ensure dsiclk_sel is always programmed before pll start */ - - /* Start PLL */ - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_PLL_CNTRL, 0x01); - - /* - * ensure all PLL configurations are written prior to checking - * for PLL lock. - */ - wmb(); - - /* Check for PLL lock */ - rc = dsi_pll_7nm_lock_status(rsc); - if (rc) { - pr_err("PLL(%d) lock failed\n", rsc->index); - goto error; - } - - rsc->pll_on = true; - - /* - * assert power on reset for PHY digital in case the PLL is - * enabled after CX of analog domain power collapse. This needs - * to be done before enabling the global clk. - */ - dsi_pll_phy_dig_reset(rsc); - if (rsc->slave) - dsi_pll_phy_dig_reset(rsc->slave); - - dsi_pll_enable_global_clk(rsc); - if (rsc->slave) - dsi_pll_enable_global_clk(rsc->slave); - -error: - return rc; -} - -static void dsi_pll_disable_sub(struct mdss_pll_resources *rsc) -{ - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_RBUF_CTRL, 0); - dsi_pll_disable_pll_bias(rsc); -} - -static void dsi_pll_disable(struct dsi_pll_vco_clk *vco) -{ - struct mdss_pll_resources *rsc = vco->priv; - - if (!rsc->pll_on && - mdss_pll_resource_enable(rsc, true)) { - pr_err("failed to enable pll (%d) resources\n", rsc->index); - return; - } - - rsc->handoff_resources = false; - - pr_debug("stop PLL (%d)\n", rsc->index); - - /* - * To avoid any stray glitches while - * abruptly powering down the PLL - * make sure to gate the clock using - * the clock enable bit before powering - * down the PLL - */ - dsi_pll_disable_global_clk(rsc); - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_PLL_CNTRL, 0); - dsi_pll_disable_sub(rsc); - if (rsc->slave) { - dsi_pll_disable_global_clk(rsc->slave); - dsi_pll_disable_sub(rsc->slave); - } - /* flush, ensure all register writes are done*/ - wmb(); - rsc->pll_on = false; -} - -long vco_7nm_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - unsigned long rrate = rate; - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - - if (rate < vco->min_rate) - rrate = vco->min_rate; - if (rate > vco->max_rate) - rrate = vco->max_rate; - - *parent_rate = rrate; - - return rrate; -} - -static void vco_7nm_unprepare(struct clk_hw *hw) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct mdss_pll_resources *pll = vco->priv; - - if (!pll) { - pr_err("dsi pll resources not available\n"); - return; - } - - /* - * During unprepare in continuous splash use case we want driver - * to pick all dividers instead of retaining bootloader configurations. - */ - if (!pll->handoff_resources) { - pll->cached_cfg0 = MDSS_PLL_REG_R(pll->phy_base, - PHY_CMN_CLK_CFG0); - pll->cached_outdiv = MDSS_PLL_REG_R(pll->pll_base, - PLL_PLL_OUTDIV_RATE); - pr_debug("cfg0=%d,cfg1=%d, outdiv=%d\n", pll->cached_cfg0, - pll->cached_cfg1, pll->cached_outdiv); - - pll->vco_cached_rate = clk_hw_get_rate(hw); - } - - /* - * When continuous splash screen feature is enabled, we need to cache - * the mux configuration for the pixel_clk_src mux clock. The clock - * framework does not call back to re-configure the mux value if it is - * does not change.For such usecases, we need to ensure that the cached - * value is programmed prior to PLL being locked - */ - if (pll->handoff_resources) - pll->cached_cfg1 = MDSS_PLL_REG_R(pll->phy_base, - PHY_CMN_CLK_CFG1); - - dsi_pll_disable(vco); - mdss_pll_resource_enable(pll, false); -} - -static int vco_7nm_prepare(struct clk_hw *hw) -{ - int rc = 0; - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct mdss_pll_resources *pll = vco->priv; - - if (!pll) { - pr_err("dsi pll resources are not available\n"); - return -EINVAL; - } - - /* Skip vco recalculation for continuous splash use case */ - if (pll->handoff_resources) - return 0; - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("failed to enable pll (%d) resource, rc=%d\n", - pll->index, rc); - return rc; - } - - if ((pll->vco_cached_rate != 0) && - (pll->vco_cached_rate == clk_hw_get_rate(hw))) { - rc = hw->init->ops->set_rate(hw, pll->vco_cached_rate, - pll->vco_cached_rate); - if (rc) { - pr_err("pll(%d) set_rate failed, rc=%d\n", - pll->index, rc); - mdss_pll_resource_enable(pll, false); - return rc; - } - pr_debug("cfg0=%d, cfg1=%d\n", pll->cached_cfg0, - pll->cached_cfg1); - MDSS_PLL_REG_W(pll->phy_base, PHY_CMN_CLK_CFG0, - pll->cached_cfg0); - MDSS_PLL_REG_W(pll->pll_base, PLL_PLL_OUTDIV_RATE, - pll->cached_outdiv); - } - - rc = dsi_pll_enable(vco); - if (rc) { - mdss_pll_resource_enable(pll, false); - pr_err("pll(%d) enable failed, rc=%d\n", pll->index, rc); - return rc; - } - - return rc; -} - -static unsigned long vco_7nm_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk_hw(hw); - struct mdss_pll_resources *pll = vco->priv; - int rc; - u64 ref_clk = vco->ref_clk_rate; - u64 vco_rate = 0; - u64 multiplier; - u32 frac; - u32 dec; - u32 outdiv; - u64 pll_freq, tmp64; - - if (!vco->priv) { - pr_err("vco priv is null\n"); - return 0; - } - - /* - * Calculate the vco rate from HW registers only for handoff cases. - * For other cases where a vco_10nm_set_rate() has already been - * called, just return the rate that was set earlier. This is due - * to the fact that recalculating VCO rate requires us to read the - * correct value of the pll_out_div divider clock, which is only set - * afterwards. - */ - if (pll->vco_current_rate != 0) { - pr_debug("returning vco rate = %lld\n", pll->vco_current_rate); - return pll->vco_current_rate; - } - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("failed to enable pll(%d) resource, rc=%d\n", - pll->index, rc); - return 0; - } - - pll->handoff_resources = true; - if (dsi_pll_7nm_lock_status(pll)) { - pr_debug("PLL not enabled\n"); - pll->handoff_resources = false; - goto end; - } - - dec = MDSS_PLL_REG_R(pll->pll_base, PLL_DECIMAL_DIV_START_1); - dec &= 0xFF; - - frac = MDSS_PLL_REG_R(pll->pll_base, PLL_FRAC_DIV_START_LOW_1); - frac |= ((MDSS_PLL_REG_R(pll->pll_base, PLL_FRAC_DIV_START_MID_1) & - 0xFF) << - 8); - frac |= ((MDSS_PLL_REG_R(pll->pll_base, PLL_FRAC_DIV_START_HIGH_1) & - 0x3) << - 16); - - /* OUTDIV_1:0 field is (log(outdiv, 2)) */ - outdiv = MDSS_PLL_REG_R(pll->pll_base, PLL_PLL_OUTDIV_RATE); - outdiv &= 0x3; - outdiv = 1 << outdiv; - - /* - * TODO: - * 1. Assumes prescaler is disabled - * 2. Multiplier is 2^18. it should be 2^(num_of_frac_bits) - **/ - multiplier = 1 << 18; - pll_freq = dec * (ref_clk * 2); - tmp64 = (ref_clk * 2 * frac); - pll_freq += div_u64(tmp64, multiplier); - - vco_rate = div_u64(pll_freq, outdiv); - - pr_debug("dec=0x%x, frac=0x%x, outdiv=%d, vco=%llu\n", - dec, frac, outdiv, vco_rate); - -end: - (void)mdss_pll_resource_enable(pll, false); - return (unsigned long)vco_rate; -} - -static int pixel_clk_get_div(void *context, unsigned int reg, unsigned int *div) -{ - int rc; - struct mdss_pll_resources *pll = context; - u32 reg_val; - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - reg_val = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0); - *div = (reg_val & 0xF0) >> 4; - - /** - * Common clock framework the divider value is interpreted as one less - * hence we return one less for all dividers except when zero - */ - if (*div != 0) - *div -= 1; - - (void)mdss_pll_resource_enable(pll, false); - - return rc; -} - -static void pixel_clk_set_div_sub(struct mdss_pll_resources *pll, int div) -{ - u32 reg_val; - - reg_val = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0); - reg_val &= ~0xF0; - reg_val |= (div << 4); - MDSS_PLL_REG_W(pll->phy_base, PHY_CMN_CLK_CFG0, reg_val); -} - -static int pixel_clk_set_div(void *context, unsigned int reg, unsigned int div) -{ - int rc; - struct mdss_pll_resources *pll = context; - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - /** - * In common clock framework the divider value provided is one less and - * and hence adjusting the divider value by one prior to writing it to - * hardware - */ - div++; - pixel_clk_set_div_sub(pll, div); - if (pll->slave) - pixel_clk_set_div_sub(pll->slave, div); - (void)mdss_pll_resource_enable(pll, false); - - return 0; -} - -static int bit_clk_get_div(void *context, unsigned int reg, unsigned int *div) -{ - int rc; - struct mdss_pll_resources *pll = context; - u32 reg_val; - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - reg_val = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0); - *div = (reg_val & 0x0F); - - /** - *Common clock framework the divider value is interpreted as one less - * hence we return one less for all dividers except when zero - */ - if (*div != 0) - *div -= 1; - (void)mdss_pll_resource_enable(pll, false); - - return rc; -} - -static void bit_clk_set_div_sub(struct mdss_pll_resources *rsc, int div) -{ - u32 reg_val; - - reg_val = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG0); - reg_val &= ~0x0F; - reg_val |= div; - MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CLK_CFG0, reg_val); -} - -static int bit_clk_set_div(void *context, unsigned int reg, unsigned int div) -{ - int rc; - struct mdss_pll_resources *rsc = context; - struct dsi_pll_8998 *pll; - - if (!rsc) { - pr_err("pll resource not found\n"); - return -EINVAL; - } - - pll = rsc->priv; - if (!pll) { - pr_err("pll configuration not found\n"); - return -EINVAL; - } - - rc = mdss_pll_resource_enable(rsc, true); - if (rc) { - pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); - return rc; - } - - /** - * In common clock framework the divider value provided is one less and - * and hence adjusting the divider value by one prior to writing it to - * hardware - */ - div++; - - bit_clk_set_div_sub(rsc, div); - /* For slave PLL, this divider always should be set to 1 */ - if (rsc->slave) - bit_clk_set_div_sub(rsc->slave, 1); - - (void)mdss_pll_resource_enable(rsc, false); - - return rc; -} - -static struct regmap_config dsi_pll_7nm_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x7c0, -}; - -static struct regmap_bus pll_regmap_bus = { - .reg_write = pll_reg_write, - .reg_read = pll_reg_read, -}; - -static struct regmap_bus pclk_src_mux_regmap_bus = { - .reg_read = pclk_mux_read_sel, - .reg_write = pclk_mux_write_sel, -}; - -static struct regmap_bus pclk_src_regmap_bus = { - .reg_write = pixel_clk_set_div, - .reg_read = pixel_clk_get_div, -}; - -static struct regmap_bus bitclk_src_regmap_bus = { - .reg_write = bit_clk_set_div, - .reg_read = bit_clk_get_div, -}; - -static const struct clk_ops clk_ops_vco_7nm = { - .recalc_rate = vco_7nm_recalc_rate, - .set_rate = vco_7nm_set_rate, - .round_rate = vco_7nm_round_rate, - .prepare = vco_7nm_prepare, - .unprepare = vco_7nm_unprepare, -}; - -static struct regmap_bus mdss_mux_regmap_bus = { - .reg_write = mdss_set_mux_sel, - .reg_read = mdss_get_mux_sel, -}; - -/* - * Clock tree for generating DSI byte and pclk. - * - * - * +---------------+ - * | vco_clk | - * +-------+-------+ - * | - * | - * +---------------+ - * | pll_out_div | - * | DIV(1,2,4,8) | - * +-------+-------+ - * | - * +-----------------------------+--------+ - * | | | - * +-------v-------+ | | - * | bitclk_src | | | - * | DIV(1..15) | | | - * +-------+-------+ | | - * | | | - * +----------+---------+ | | - * Shadow Path | | | | | - * + +-------v-------+ | +------v------+ | +------v-------+ - * | | byteclk_src | | |post_bit_div | | |post_vco_div | - * | | DIV(8) | | |DIV (2) | | |DIV(4) | - * | +-------+-------+ | +------+------+ | +------+-------+ - * | | | | | | | - * | | | +------+ | | - * | | +-------------+ | | +----+ - * | +--------+ | | | | - * | | +-v--v-v---v------+ - * +-v---------v----+ \ pclk_src_mux / - * \ byteclk_mux / \ / - * \ / +-----+-----+ - * +----+-----+ | Shadow Path - * | | + - * v +-----v------+ | - * dsi_byte_clk | pclk_src | | - * | DIV(1..15) | | - * +-----+------+ | - * | | - * | | - * +--------+ | - * | | - * +---v----v----+ - * \ pclk_mux / - * \ / - * +---+---+ - * | - * | - * v - * dsi_pclk - * - */ - -static struct dsi_pll_vco_clk dsi0pll_vco_clk = { - .ref_clk_rate = 19200000UL, - .min_rate = 1000000000UL, - .max_rate = 3500000000UL, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_vco_clk", - .parent_names = (const char *[]){"bi_tcxo"}, - .num_parents = 1, - .ops = &clk_ops_vco_7nm, - .flags = CLK_GET_RATE_NOCACHE, - }, -}; - -static struct dsi_pll_vco_clk dsi1pll_vco_clk = { - .ref_clk_rate = 19200000UL, - .min_rate = 1000000000UL, - .max_rate = 3500000000UL, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_vco_clk", - .parent_names = (const char *[]){"bi_tcxo"}, - .num_parents = 1, - .ops = &clk_ops_vco_7nm, - .flags = CLK_GET_RATE_NOCACHE, - }, -}; - -static struct clk_regmap_div dsi0pll_pll_out_div = { - .reg = PLL_PLL_OUTDIV_RATE, - .shift = 0, - .width = 2, - .flags = CLK_DIVIDER_POWER_OF_TWO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_pll_out_div", - .parent_names = (const char *[]){"dsi0pll_vco_clk"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_pll_out_div = { - .reg = PLL_PLL_OUTDIV_RATE, - .shift = 0, - .width = 2, - .flags = CLK_DIVIDER_POWER_OF_TWO, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_pll_out_div", - .parent_names = (const char *[]){"dsi1pll_vco_clk"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi0pll_bitclk_src = { - .shift = 0, - .width = 4, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_bitclk_src", - .parent_names = (const char *[]){"dsi0pll_pll_out_div"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_bitclk_src = { - .shift = 0, - .width = 4, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_bitclk_src", - .parent_names = (const char *[]){"dsi1pll_pll_out_div"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_fixed_factor dsi0pll_post_vco_div = { - .div = 4, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_post_vco_div", - .parent_names = (const char *[]){"dsi0pll_pll_out_div"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_post_vco_div = { - .div = 4, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_post_vco_div", - .parent_names = (const char *[]){"dsi1pll_pll_out_div"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi0pll_byteclk_src = { - .div = 8, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_byteclk_src", - .parent_names = (const char *[]){"dsi0pll_bitclk_src"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_byteclk_src = { - .div = 8, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_byteclk_src", - .parent_names = (const char *[]){"dsi1pll_bitclk_src"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi0pll_post_bit_div = { - .div = 2, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_post_bit_div", - .parent_names = (const char *[]){"dsi0pll_bitclk_src"}, - .num_parents = 1, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor dsi1pll_post_bit_div = { - .div = 2, - .mult = 1, - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_post_bit_div", - .parent_names = (const char *[]){"dsi1pll_bitclk_src"}, - .num_parents = 1, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_regmap_mux dsi0pll_byteclk_mux = { - .shift = 0, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0_phy_pll_out_byteclk", - .parent_names = (const char *[]){"dsi0pll_byteclk_src"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi1pll_byteclk_mux = { - .shift = 0, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1_phy_pll_out_byteclk", - .parent_names = (const char *[]){"dsi1pll_byteclk_src"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi0pll_pclk_src_mux = { - .reg = PHY_CMN_CLK_CFG1, - .shift = 0, - .width = 2, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_pclk_src_mux", - .parent_names = (const char *[]){"dsi0pll_bitclk_src", - "dsi0pll_post_bit_div", - "dsi0pll_pll_out_div", - "dsi0pll_post_vco_div"}, - .num_parents = 4, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi1pll_pclk_src_mux = { - .reg = PHY_CMN_CLK_CFG1, - .shift = 0, - .width = 2, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_pclk_src_mux", - .parent_names = (const char *[]){"dsi1pll_bitclk_src", - "dsi1pll_post_bit_div", - "dsi1pll_pll_out_div", - "dsi1pll_post_vco_div"}, - .num_parents = 4, - .flags = CLK_GET_RATE_NOCACHE, - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_div dsi0pll_pclk_src = { - .shift = 0, - .width = 4, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_pclk_src", - .parent_names = (const char *[]){ - "dsi0pll_pclk_src_mux"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_div dsi1pll_pclk_src = { - .shift = 0, - .width = 4, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_pclk_src", - .parent_names = (const char *[]){ - "dsi1pll_pclk_src_mux"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_div_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi0pll_pclk_mux = { - .shift = 0, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi0_phy_pll_out_dsiclk", - .parent_names = (const char *[]){"dsi0pll_pclk_src"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_regmap_mux dsi1pll_pclk_mux = { - .shift = 0, - .width = 1, - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "dsi1_phy_pll_out_dsiclk", - .parent_names = (const char *[]){"dsi1pll_pclk_src"}, - .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), - .ops = &clk_regmap_mux_closest_ops, - }, - }, -}; - -static struct clk_hw *mdss_dsi_pllcc_7nm[] = { - [VCO_CLK_0] = &dsi0pll_vco_clk.hw, - [PLL_OUT_DIV_0_CLK] = &dsi0pll_pll_out_div.clkr.hw, - [BITCLK_SRC_0_CLK] = &dsi0pll_bitclk_src.clkr.hw, - [BYTECLK_SRC_0_CLK] = &dsi0pll_byteclk_src.hw, - [POST_BIT_DIV_0_CLK] = &dsi0pll_post_bit_div.hw, - [POST_VCO_DIV_0_CLK] = &dsi0pll_post_vco_div.hw, - [BYTECLK_MUX_0_CLK] = &dsi0pll_byteclk_mux.clkr.hw, - [PCLK_SRC_MUX_0_CLK] = &dsi0pll_pclk_src_mux.clkr.hw, - [PCLK_SRC_0_CLK] = &dsi0pll_pclk_src.clkr.hw, - [PCLK_MUX_0_CLK] = &dsi0pll_pclk_mux.clkr.hw, - [VCO_CLK_1] = &dsi1pll_vco_clk.hw, - [PLL_OUT_DIV_1_CLK] = &dsi1pll_pll_out_div.clkr.hw, - [BITCLK_SRC_1_CLK] = &dsi1pll_bitclk_src.clkr.hw, - [BYTECLK_SRC_1_CLK] = &dsi1pll_byteclk_src.hw, - [POST_BIT_DIV_1_CLK] = &dsi1pll_post_bit_div.hw, - [POST_VCO_DIV_1_CLK] = &dsi1pll_post_vco_div.hw, - [BYTECLK_MUX_1_CLK] = &dsi1pll_byteclk_mux.clkr.hw, - [PCLK_SRC_MUX_1_CLK] = &dsi1pll_pclk_src_mux.clkr.hw, - [PCLK_SRC_1_CLK] = &dsi1pll_pclk_src.clkr.hw, - [PCLK_MUX_1_CLK] = &dsi1pll_pclk_mux.clkr.hw, -}; - -int dsi_pll_clock_register_7nm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int rc = 0, ndx, i; - struct clk *clk; - struct clk_onecell_data *clk_data; - int num_clks = ARRAY_SIZE(mdss_dsi_pllcc_7nm); - struct regmap *rmap; - - ndx = pll_res->index; - - if (ndx >= DSI_PLL_MAX) { - pr_err("pll index(%d) NOT supported\n", ndx); - return -EINVAL; - } - - pll_rsc_db[ndx] = pll_res; - plls[ndx].rsc = pll_res; - pll_res->priv = &plls[ndx]; - pll_res->vco_delay = VCO_DELAY_USEC; - - clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL); - if (!clk_data) - return -ENOMEM; - - clk_data->clks = devm_kcalloc(&pdev->dev, num_clks, - sizeof(struct clk *), GFP_KERNEL); - if (!clk_data->clks) - return -ENOMEM; - - clk_data->clk_num = num_clks; - - /* Establish client data */ - if (ndx == 0) { - - rmap = devm_regmap_init(&pdev->dev, &pll_regmap_bus, - pll_res, &dsi_pll_7nm_config); - dsi0pll_pll_out_div.clkr.regmap = rmap; - - rmap = devm_regmap_init(&pdev->dev, &bitclk_src_regmap_bus, - pll_res, &dsi_pll_7nm_config); - dsi0pll_bitclk_src.clkr.regmap = rmap; - - rmap = devm_regmap_init(&pdev->dev, &pclk_src_regmap_bus, - pll_res, &dsi_pll_7nm_config); - dsi0pll_pclk_src.clkr.regmap = rmap; - - rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus, - pll_res, &dsi_pll_7nm_config); - dsi0pll_pclk_mux.clkr.regmap = rmap; - - rmap = devm_regmap_init(&pdev->dev, &pclk_src_mux_regmap_bus, - pll_res, &dsi_pll_7nm_config); - dsi0pll_pclk_src_mux.clkr.regmap = rmap; - rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus, - pll_res, &dsi_pll_7nm_config); - dsi0pll_byteclk_mux.clkr.regmap = rmap; - - dsi0pll_vco_clk.priv = pll_res; - - if (dsi_pll_7nm_is_hw_revision_v4_1(pll_res)) { - dsi0pll_vco_clk.min_rate = 600000000; - dsi0pll_vco_clk.max_rate = 5000000000; - } - - for (i = VCO_CLK_0; i <= PCLK_MUX_0_CLK; i++) { - clk = devm_clk_register(&pdev->dev, - mdss_dsi_pllcc_7nm[i]); - if (IS_ERR(clk)) { - pr_err("clk registration failed for DSI clock:%d\n", - pll_res->index); - rc = -EINVAL; - goto clk_register_fail; - } - clk_data->clks[i] = clk; - - } - - rc = of_clk_add_provider(pdev->dev.of_node, - of_clk_src_onecell_get, clk_data); - - - } else { - rmap = devm_regmap_init(&pdev->dev, &pll_regmap_bus, - pll_res, &dsi_pll_7nm_config); - dsi1pll_pll_out_div.clkr.regmap = rmap; - - rmap = devm_regmap_init(&pdev->dev, &bitclk_src_regmap_bus, - pll_res, &dsi_pll_7nm_config); - dsi1pll_bitclk_src.clkr.regmap = rmap; - - rmap = devm_regmap_init(&pdev->dev, &pclk_src_regmap_bus, - pll_res, &dsi_pll_7nm_config); - dsi1pll_pclk_src.clkr.regmap = rmap; - - rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus, - pll_res, &dsi_pll_7nm_config); - dsi1pll_pclk_mux.clkr.regmap = rmap; - - rmap = devm_regmap_init(&pdev->dev, &pclk_src_mux_regmap_bus, - pll_res, &dsi_pll_7nm_config); - dsi1pll_pclk_src_mux.clkr.regmap = rmap; - rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus, - pll_res, &dsi_pll_7nm_config); - dsi1pll_byteclk_mux.clkr.regmap = rmap; - dsi1pll_vco_clk.priv = pll_res; - - if (dsi_pll_7nm_is_hw_revision_v4_1(pll_res)) { - dsi1pll_vco_clk.min_rate = 600000000; - dsi1pll_vco_clk.max_rate = 5000000000; - } - - for (i = VCO_CLK_1; i <= PCLK_MUX_1_CLK; i++) { - clk = devm_clk_register(&pdev->dev, - mdss_dsi_pllcc_7nm[i]); - if (IS_ERR(clk)) { - pr_err("clk registration failed for DSI clock:%d\n", - pll_res->index); - rc = -EINVAL; - goto clk_register_fail; - } - clk_data->clks[i] = clk; - - } - - rc = of_clk_add_provider(pdev->dev.of_node, - of_clk_src_onecell_get, clk_data); - } - if (!rc) { - pr_info("Registered DSI PLL ndx=%d, clocks successfully\n", - ndx); - - return rc; - } -clk_register_fail: - return rc; -} diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-8996-util.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-8996-util.c deleted file mode 100644 index c8d5f1e8b897a2e2a67a57152c530bc4f11841a5..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-8996-util.c +++ /dev/null @@ -1,1130 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include - -#include "mdss-pll.h" -#include "mdss-dsi-pll.h" -#include "mdss-dsi-pll-8996.h" - -#define DSI_PLL_POLL_MAX_READS 15 -#define DSI_PLL_POLL_TIMEOUT_US 1000 -#define MSM8996_DSI_PLL_REVISION_2 2 - -#define CEIL(x, y) (((x) + ((y)-1)) / (y)) - -int set_mdss_byte_mux_sel_8996(struct mux_clk *clk, int sel) -{ - return 0; -} - -int get_mdss_byte_mux_sel_8996(struct mux_clk *clk) -{ - return 0; -} - -int set_mdss_pixel_mux_sel_8996(struct mux_clk *clk, int sel) -{ - return 0; -} - -int get_mdss_pixel_mux_sel_8996(struct mux_clk *clk) -{ - return 0; -} - -static int mdss_pll_read_stored_trim_codes( - struct mdss_pll_resources *dsi_pll_res, s64 vco_clk_rate) -{ - int i; - int rc = 0; - bool found = false; - - if (!dsi_pll_res->dfps) { - rc = -EINVAL; - goto end_read; - } - - for (i = 0; i < dsi_pll_res->dfps->panel_dfps.frame_rate_cnt; i++) { - struct dfps_codes_info *codes_info = - &dsi_pll_res->dfps->codes_dfps[i]; - - pr_debug("valid=%d frame_rate=%d, vco_rate=%d, code %d %d\n", - codes_info->is_valid, codes_info->frame_rate, - codes_info->clk_rate, codes_info->pll_codes.pll_codes_1, - codes_info->pll_codes.pll_codes_2); - - if (vco_clk_rate != codes_info->clk_rate && - codes_info->is_valid) - continue; - - dsi_pll_res->cache_pll_trim_codes[0] = - codes_info->pll_codes.pll_codes_1; - dsi_pll_res->cache_pll_trim_codes[1] = - codes_info->pll_codes.pll_codes_2; - found = true; - break; - } - - if (!found) { - rc = -EINVAL; - goto end_read; - } - - pr_debug("core_kvco_code=0x%x core_vco_tune=0x%x\n", - dsi_pll_res->cache_pll_trim_codes[0], - dsi_pll_res->cache_pll_trim_codes[1]); - -end_read: - return rc; -} - -int post_n1_div_set_div(struct div_clk *clk, int div) -{ - struct mdss_pll_resources *pll = clk->priv; - struct dsi_pll_db *pdb; - struct dsi_pll_output *pout; - int rc; - u32 n1div = 0; - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - pdb = (struct dsi_pll_db *)pll->priv; - pout = &pdb->out; - - /* - * vco rate = bit_clk * postdiv * n1div - * vco range from 1300 to 2600 Mhz - * postdiv = 1 - * n1div = 1 to 15 - * n1div = roundup(1300Mhz / bit_clk) - * support bit_clk above 86.67Mhz - */ - - /* this is for vco/bit clock */ - pout->pll_postdiv = 1; /* fixed, divided by 1 */ - pout->pll_n1div = div; - - n1div = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_CMN_CLK_CFG0); - n1div &= ~0xf; - n1div |= (div & 0xf); - MDSS_PLL_REG_W(pll->pll_base, DSIPHY_CMN_CLK_CFG0, n1div); - /* ensure n1 divider is programed */ - wmb(); - pr_debug("ndx=%d div=%d postdiv=%x n1div=%x\n", - pll->index, div, pout->pll_postdiv, pout->pll_n1div); - - mdss_pll_resource_enable(pll, false); - - return 0; -} - -int post_n1_div_get_div(struct div_clk *clk) -{ - u32 div; - int rc; - struct mdss_pll_resources *pll = clk->priv; - - if (is_gdsc_disabled(pll)) - return 0; - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - /* - * postdiv = 1/2/4/8 - * n1div = 1 - 15 - * fot the time being, assume postdiv = 1 - */ - - div = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_CMN_CLK_CFG0); - div &= 0xF; - pr_debug("n1 div = %d\n", div); - - mdss_pll_resource_enable(pll, false); - - return div; -} - -int n2_div_set_div(struct div_clk *clk, int div) -{ - int rc; - u32 n2div; - struct mdss_pll_resources *pll = clk->priv; - struct dsi_pll_db *pdb; - struct dsi_pll_output *pout; - struct mdss_pll_resources *slave; - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - pdb = (struct dsi_pll_db *)pll->priv; - pout = &pdb->out; - - /* this is for pixel clock */ - n2div = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_CMN_CLK_CFG0); - n2div &= ~0xf0; /* bits 4 to 7 */ - n2div |= (div << 4); - MDSS_PLL_REG_W(pll->pll_base, DSIPHY_CMN_CLK_CFG0, n2div); - - /* commit slave if split display is enabled */ - slave = pll->slave; - if (slave) - MDSS_PLL_REG_W(slave->pll_base, DSIPHY_CMN_CLK_CFG0, n2div); - - pout->pll_n2div = div; - - /* set dsiclk_sel=1 so that n2div *= 2 */ - MDSS_PLL_REG_W(pll->pll_base, DSIPHY_CMN_CLK_CFG1, 1); - pr_debug("ndx=%d div=%d n2div=%x\n", pll->index, div, n2div); - - mdss_pll_resource_enable(pll, false); - - return rc; -} - -int shadow_n2_div_set_div(struct div_clk *clk, int div) -{ - struct mdss_pll_resources *pll = clk->priv; - struct dsi_pll_db *pdb; - struct dsi_pll_output *pout; - u32 data; - - pdb = pll->priv; - pout = &pdb->out; - - pout->pll_n2div = div; - - data = (pout->pll_n1div | (pout->pll_n2div << 4)); - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL19, - DSIPHY_CMN_CLK_CFG0, DSIPHY_CMN_CLK_CFG1, - data, 1); - return 0; -} - -int n2_div_get_div(struct div_clk *clk) -{ - int rc; - u32 n2div; - struct mdss_pll_resources *pll = clk->priv; - - if (is_gdsc_disabled(pll)) - return 0; - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll=%d resources\n", - pll->index); - return rc; - } - - n2div = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_CMN_CLK_CFG0); - n2div >>= 4; - n2div &= 0x0f; - - mdss_pll_resource_enable(pll, false); - - pr_debug("ndx=%d div=%d\n", pll->index, n2div); - - return n2div; -} - -static bool pll_is_pll_locked_8996(struct mdss_pll_resources *pll) -{ - u32 status; - bool pll_locked; - - /* poll for PLL ready status */ - if (readl_poll_timeout_atomic((pll->pll_base + - DSIPHY_PLL_RESET_SM_READY_STATUS), - status, - ((status & BIT(5)) > 0), - DSI_PLL_POLL_MAX_READS, - DSI_PLL_POLL_TIMEOUT_US)) { - pr_err("DSI PLL ndx=%d status=%x failed to Lock\n", - pll->index, status); - pll_locked = false; - } else if (readl_poll_timeout_atomic((pll->pll_base + - DSIPHY_PLL_RESET_SM_READY_STATUS), - status, - ((status & BIT(0)) > 0), - DSI_PLL_POLL_MAX_READS, - DSI_PLL_POLL_TIMEOUT_US)) { - pr_err("DSI PLL ndx=%d status=%x PLl not ready\n", - pll->index, status); - pll_locked = false; - } else { - pll_locked = true; - } - - return pll_locked; -} - -static void dsi_pll_start_8996(void __iomem *pll_base) -{ - pr_debug("start PLL at base=%p\n", pll_base); - - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_VREF_CFG1, 0x10); - MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_PLL_CNTRL, 1); -} - -static void dsi_pll_stop_8996(void __iomem *pll_base) -{ - pr_debug("stop PLL at base=%p\n", pll_base); - - MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_PLL_CNTRL, 0); -} - -int dsi_pll_enable_seq_8996(struct mdss_pll_resources *pll) -{ - int rc = 0; - - if (!pll) { - pr_err("Invalid PLL resources\n"); - return -EINVAL; - } - - dsi_pll_start_8996(pll->pll_base); - - /* - * both DSIPHY_PLL_CLKBUFLR_EN and DSIPHY_CMN_GLBL_TEST_CTRL - * enabled at mdss_dsi_8996_phy_config() - */ - - if (!pll_is_pll_locked_8996(pll)) { - pr_err("DSI PLL ndx=%d lock failed\n", pll->index); - rc = -EINVAL; - goto init_lock_err; - } - - pr_debug("DSI PLL ndx=%d Lock success\n", pll->index); - -init_lock_err: - return rc; -} - -static int dsi_pll_enable(struct clk *c) -{ - int i, rc = 0; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *pll = vco->priv; - - /* Try all enable sequences until one succeeds */ - for (i = 0; i < vco->pll_en_seq_cnt; i++) { - rc = vco->pll_enable_seqs[i](pll); - pr_debug("DSI PLL %s after sequence #%d\n", - rc ? "unlocked" : "locked", i + 1); - if (!rc) - break; - } - - if (rc) - pr_err("ndx=%d DSI PLL failed to lock\n", pll->index); - else - pll->pll_on = true; - - return rc; -} - -static void dsi_pll_disable(struct clk *c) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *pll = vco->priv; - struct mdss_pll_resources *slave; - - if (!pll->pll_on && - mdss_pll_resource_enable(pll, true)) { - pr_err("Failed to enable mdss dsi pll=%d\n", pll->index); - return; - } - - pll->handoff_resources = false; - slave = pll->slave; - - dsi_pll_stop_8996(pll->pll_base); - - mdss_pll_resource_enable(pll, false); - - pll->pll_on = false; - - pr_debug("DSI PLL ndx=%d Disabled\n", pll->index); -} - -static void mdss_dsi_pll_8996_input_init(struct mdss_pll_resources *pll, - struct dsi_pll_db *pdb) -{ - pdb->in.fref = 19200000; /* 19.2 Mhz*/ - pdb->in.fdata = 0; /* bit clock rate */ - pdb->in.dsiclk_sel = 1; /* 1, reg: 0x0014 */ - pdb->in.ssc_en = pll->ssc_en; /* 1, reg: 0x0494, bit 0 */ - pdb->in.ldo_en = 0; /* 0, reg: 0x004c, bit 0 */ - - /* fixed input */ - pdb->in.refclk_dbler_en = 0; /* 0, reg: 0x04c0, bit 1 */ - pdb->in.vco_measure_time = 5; /* 5, unknown */ - pdb->in.kvco_measure_time = 5; /* 5, unknown */ - pdb->in.bandgap_timer = 4; /* 4, reg: 0x0430, bit 3 - 5 */ - pdb->in.pll_wakeup_timer = 5; /* 5, reg: 0x043c, bit 0 - 2 */ - pdb->in.plllock_cnt = 1; /* 1, reg: 0x0488, bit 1 - 2 */ - pdb->in.plllock_rng = 0; /* 0, reg: 0x0488, bit 3 - 4 */ - pdb->in.ssc_center = pll->ssc_center;/* 0, reg: 0x0494, bit 1 */ - pdb->in.ssc_adj_period = 37; /* 37, reg: 0x498, bit 0 - 9 */ - pdb->in.ssc_spread = pll->ssc_ppm / 1000; - pdb->in.ssc_freq = pll->ssc_freq; - - pdb->in.pll_ie_trim = 4; /* 4, reg: 0x0400 */ - pdb->in.pll_ip_trim = 4; /* 4, reg: 0x0404 */ - pdb->in.pll_cpcset_cur = 1; /* 1, reg: 0x04f0, bit 0 - 2 */ - pdb->in.pll_cpmset_cur = 1; /* 1, reg: 0x04f0, bit 3 - 5 */ - pdb->in.pll_icpmset = 4; /* 4, reg: 0x04fc, bit 3 - 5 */ - pdb->in.pll_icpcset = 4; /* 4, reg: 0x04fc, bit 0 - 2 */ - pdb->in.pll_icpmset_p = 0; /* 0, reg: 0x04f4, bit 0 - 2 */ - pdb->in.pll_icpmset_m = 0; /* 0, reg: 0x04f4, bit 3 - 5 */ - pdb->in.pll_icpcset_p = 0; /* 0, reg: 0x04f8, bit 0 - 2 */ - pdb->in.pll_icpcset_m = 0; /* 0, reg: 0x04f8, bit 3 - 5 */ - pdb->in.pll_lpf_res1 = 3; /* 3, reg: 0x0504, bit 0 - 3 */ - pdb->in.pll_lpf_cap1 = 11; /* 11, reg: 0x0500, bit 0 - 3 */ - pdb->in.pll_lpf_cap2 = 1; /* 1, reg: 0x0500, bit 4 - 7 */ - pdb->in.pll_iptat_trim = 7; - pdb->in.pll_c3ctrl = 2; /* 2 */ - pdb->in.pll_r3ctrl = 1; /* 1 */ -} - -static void pll_8996_ssc_calc(struct mdss_pll_resources *pll, - struct dsi_pll_db *pdb) -{ - u32 period, ssc_period; - u32 ref, rem; - s64 step_size; - - pr_debug("%s: vco=%lld ref=%lld\n", __func__, - pll->vco_current_rate, pll->vco_ref_clk_rate); - - ssc_period = pdb->in.ssc_freq / 500; - period = (unsigned long)pll->vco_ref_clk_rate / 1000; - ssc_period = CEIL(period, ssc_period); - ssc_period -= 1; - pdb->out.ssc_period = ssc_period; - - pr_debug("%s: ssc, freq=%d spread=%d period=%d\n", __func__, - pdb->in.ssc_freq, pdb->in.ssc_spread, pdb->out.ssc_period); - - step_size = (u32)pll->vco_current_rate; - ref = pll->vco_ref_clk_rate; - ref /= 1000; - step_size = div_s64(step_size, ref); - step_size <<= 20; - step_size = div_s64(step_size, 1000); - step_size *= pdb->in.ssc_spread; - step_size = div_s64(step_size, 1000); - step_size *= (pdb->in.ssc_adj_period + 1); - - rem = 0; - step_size = div_s64_rem(step_size, ssc_period + 1, &rem); - if (rem) - step_size++; - - pr_debug("%s: step_size=%lld\n", __func__, step_size); - - step_size &= 0x0ffff; /* take lower 16 bits */ - - pdb->out.ssc_step_size = step_size; -} - -static void pll_8996_dec_frac_calc(struct mdss_pll_resources *pll, - struct dsi_pll_db *pdb) -{ - struct dsi_pll_input *pin = &pdb->in; - struct dsi_pll_output *pout = &pdb->out; - s64 multiplier = BIT(20); - s64 dec_start_multiple, dec_start, pll_comp_val; - s32 duration, div_frac_start; - s64 vco_clk_rate = pll->vco_current_rate; - s64 fref = pll->vco_ref_clk_rate; - - pr_debug("vco_clk_rate=%lld ref_clk_rate=%lld\n", - vco_clk_rate, fref); - - dec_start_multiple = div_s64(vco_clk_rate * multiplier, fref); - div_s64_rem(dec_start_multiple, multiplier, &div_frac_start); - - dec_start = div_s64(dec_start_multiple, multiplier); - - pout->dec_start = (u32)dec_start; - pout->div_frac_start = div_frac_start; - - if (pin->plllock_cnt == 0) - duration = 1024; - else if (pin->plllock_cnt == 1) - duration = 256; - else if (pin->plllock_cnt == 2) - duration = 128; - else - duration = 32; - - pll_comp_val = duration * dec_start_multiple; - pll_comp_val = div_s64(pll_comp_val, multiplier); - do_div(pll_comp_val, 10); - - pout->plllock_cmp = (u32)pll_comp_val; - - pout->pll_txclk_en = 1; - if (pll->revision == MSM8996_DSI_PLL_REVISION_2) - pout->cmn_ldo_cntrl = 0x3c; - else - pout->cmn_ldo_cntrl = 0x1c; -} - -static u32 pll_8996_kvco_slop(u32 vrate) -{ - u32 slop = 0; - - if (vrate > 1300000000UL && vrate <= 1800000000UL) - slop = 600; - else if (vrate > 1800000000UL && vrate < 2300000000UL) - slop = 400; - else if (vrate > 2300000000UL && vrate < 2600000000UL) - slop = 280; - - return slop; -} - -static void pll_8996_calc_vco_count(struct dsi_pll_db *pdb, - s64 vco_clk_rate, s64 fref) -{ - struct dsi_pll_input *pin = &pdb->in; - struct dsi_pll_output *pout = &pdb->out; - s64 data; - u32 cnt; - - data = fref * pin->vco_measure_time; - do_div(data, 1000000); - data &= 0x03ff; /* 10 bits */ - data -= 2; - pout->pll_vco_div_ref = data; - - data = (unsigned long)vco_clk_rate / 1000000; /* unit is Mhz */ - data *= pin->vco_measure_time; - do_div(data, 10); - pout->pll_vco_count = data; /* reg: 0x0474, 0x0478 */ - - data = fref * pin->kvco_measure_time; - do_div(data, 1000000); - data &= 0x03ff; /* 10 bits */ - data -= 1; - pout->pll_kvco_div_ref = data; - - cnt = pll_8996_kvco_slop(vco_clk_rate); - cnt *= 2; - do_div(cnt, 100); - cnt *= pin->kvco_measure_time; - pout->pll_kvco_count = cnt; - - pout->pll_misc1 = 16; - pout->pll_resetsm_cntrl = 48; - pout->pll_resetsm_cntrl2 = pin->bandgap_timer << 3; - pout->pll_resetsm_cntrl5 = pin->pll_wakeup_timer; - pout->pll_kvco_code = 0; -} - -static void pll_db_commit_ssc(struct mdss_pll_resources *pll, - struct dsi_pll_db *pdb) -{ - void __iomem *pll_base = pll->pll_base; - struct dsi_pll_input *pin = &pdb->in; - struct dsi_pll_output *pout = &pdb->out; - char data; - - data = pin->ssc_adj_period; - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_ADJ_PER1, data); - data = (pin->ssc_adj_period >> 8); - data &= 0x03; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_ADJ_PER2, data); - - data = pout->ssc_period; - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_PER1, data); - data = (pout->ssc_period >> 8); - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_PER2, data); - - data = pout->ssc_step_size; - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_STEP_SIZE1, data); - data = (pout->ssc_step_size >> 8); - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_STEP_SIZE2, data); - - data = (pin->ssc_center & 0x01); - data <<= 1; - data |= 0x01; /* enable */ - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_EN_CENTER, data); - - wmb(); /* make sure register committed */ -} - -static void pll_db_commit_common(struct mdss_pll_resources *pll, - struct dsi_pll_db *pdb) -{ - void __iomem *pll_base = pll->pll_base; - struct dsi_pll_input *pin = &pdb->in; - struct dsi_pll_output *pout = &pdb->out; - char data; - - /* confgiure the non frequency dependent pll registers */ - data = 0; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SYSCLK_EN_RESET, data); - - /* DSIPHY_PLL_CLKBUFLR_EN updated at dsi phy */ - - data = pout->pll_txclk_en; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_TXCLK_EN, data); - - data = pout->pll_resetsm_cntrl; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_RESETSM_CNTRL, data); - data = pout->pll_resetsm_cntrl2; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_RESETSM_CNTRL2, data); - data = pout->pll_resetsm_cntrl5; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_RESETSM_CNTRL5, data); - - data = pout->pll_vco_div_ref; - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_VCO_DIV_REF1, data); - data = (pout->pll_vco_div_ref >> 8); - data &= 0x03; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_VCO_DIV_REF2, data); - - data = pout->pll_kvco_div_ref; - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_KVCO_DIV_REF1, data); - data = (pout->pll_kvco_div_ref >> 8); - data &= 0x03; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_KVCO_DIV_REF2, data); - - data = pout->pll_misc1; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLL_MISC1, data); - - data = pin->pll_ie_trim; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_IE_TRIM, data); - - data = pin->pll_ip_trim; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_IP_TRIM, data); - - data = ((pin->pll_cpmset_cur << 3) | pin->pll_cpcset_cur); - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_CP_SET_CUR, data); - - data = ((pin->pll_icpcset_p << 3) | pin->pll_icpcset_m); - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLL_ICPCSET, data); - - data = ((pin->pll_icpmset_p << 3) | pin->pll_icpcset_m); - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLL_ICPMSET, data); - - data = ((pin->pll_icpmset << 3) | pin->pll_icpcset); - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLL_ICP_SET, data); - - data = ((pdb->in.pll_lpf_cap2 << 4) | pdb->in.pll_lpf_cap1); - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLL_LPF1, data); - - data = pin->pll_iptat_trim; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_IPTAT_TRIM, data); - - data = (pdb->in.pll_c3ctrl | (pdb->in.pll_r3ctrl << 4)); - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLL_CRCTRL, data); -} - -static void pll_db_commit_8996(struct mdss_pll_resources *pll, - struct dsi_pll_db *pdb) -{ - void __iomem *pll_base = pll->pll_base; - struct dsi_pll_input *pin = &pdb->in; - struct dsi_pll_output *pout = &pdb->out; - char data; - - data = pout->cmn_ldo_cntrl; - MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_LDO_CNTRL, data); - - pll_db_commit_common(pll, pdb); - - /* de assert pll start and apply pll sw reset */ - /* stop pll */ - MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_PLL_CNTRL, 0); - - /* pll sw reset */ - MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_CTRL_1, 0x20); - wmb(); /* make sure register committed */ - udelay(10); - - MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_CTRL_1, 0); - wmb(); /* make sure register committed */ - - data = pdb->in.dsiclk_sel; /* set dsiclk_sel = 1 */ - MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_CLK_CFG1, data); - - data = 0xff; /* data, clk, pll normal operation */ - MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_CTRL_0, data); - - /* confgiure the frequency dependent pll registers */ - data = pout->dec_start; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_DEC_START, data); - - data = pout->div_frac_start; - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_DIV_FRAC_START1, data); - data = (pout->div_frac_start >> 8); - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_DIV_FRAC_START2, data); - data = (pout->div_frac_start >> 16); - data &= 0x0f; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_DIV_FRAC_START3, data); - - data = pout->plllock_cmp; - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLLLOCK_CMP1, data); - data = (pout->plllock_cmp >> 8); - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLLLOCK_CMP2, data); - data = (pout->plllock_cmp >> 16); - data &= 0x03; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLLLOCK_CMP3, data); - - data = ((pin->plllock_cnt << 1) | (pin->plllock_rng << 3)); - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLLLOCK_CMP_EN, data); - - data = pout->pll_vco_count; - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_VCO_COUNT1, data); - data = (pout->pll_vco_count >> 8); - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_VCO_COUNT2, data); - - data = pout->pll_kvco_count; - data &= 0x0ff; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_KVCO_COUNT1, data); - data = (pout->pll_kvco_count >> 8); - data &= 0x03; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_KVCO_COUNT2, data); - - /* - * tx_band = pll_postdiv - * 0: divided by 1 <== for now - * 1: divided by 2 - * 2: divided by 4 - * 3: divided by 8 - */ - data = (((pout->pll_postdiv - 1) << 4) | pdb->in.pll_lpf_res1); - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLL_LPF2_POSTDIV, data); - - data = (pout->pll_n1div | (pout->pll_n2div << 4)); - MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_CLK_CFG0, data); - - if (pll->ssc_en) - pll_db_commit_ssc(pll, pdb); - - wmb(); /* make sure register committed */ -} - -/* - * pll_source_finding: - * Both GLBL_TEST_CTRL and CLKBUFLR_EN are configured - * at mdss_dsi_8996_phy_config() - */ -static int pll_source_finding(struct mdss_pll_resources *pll) -{ - u32 clk_buf_en; - u32 glbl_test_ctrl; - - glbl_test_ctrl = MDSS_PLL_REG_R(pll->pll_base, - DSIPHY_CMN_GLBL_TEST_CTRL); - clk_buf_en = MDSS_PLL_REG_R(pll->pll_base, - DSIPHY_PLL_CLKBUFLR_EN); - - glbl_test_ctrl &= BIT(2); - glbl_test_ctrl >>= 2; - - pr_debug("%s: pll=%d clk_buf_en=%x glbl_test_ctrl=%x\n", - __func__, pll->index, clk_buf_en, glbl_test_ctrl); - - clk_buf_en &= (PLL_OUTPUT_RIGHT | PLL_OUTPUT_LEFT); - - if ((glbl_test_ctrl == PLL_SOURCE_FROM_LEFT) && - (clk_buf_en == PLL_OUTPUT_BOTH)) - return PLL_MASTER; - - if ((glbl_test_ctrl == PLL_SOURCE_FROM_RIGHT) && - (clk_buf_en == PLL_OUTPUT_NONE)) - return PLL_SLAVE; - - if ((glbl_test_ctrl == PLL_SOURCE_FROM_LEFT) && - (clk_buf_en == PLL_OUTPUT_RIGHT)) - return PLL_STANDALONE; - - pr_debug("%s: Error pll setup, clk_buf_en=%x glbl_test_ctrl=%x\n", - __func__, clk_buf_en, glbl_test_ctrl); - - return PLL_UNKNOWN; -} - -static void pll_source_setup(struct mdss_pll_resources *pll) -{ - int status; - struct dsi_pll_db *pdb = (struct dsi_pll_db *)pll->priv; - struct mdss_pll_resources *other; - - if (pdb->source_setup_done) - return; - - pdb->source_setup_done++; - - status = pll_source_finding(pll); - - if (status == PLL_STANDALONE || status == PLL_UNKNOWN) - return; - - other = pdb->next->pll; - if (!other) - return; - - pr_debug("%s: status=%d pll=%d other=%d\n", __func__, - status, pll->index, other->index); - - if (status == PLL_MASTER) - pll->slave = other; - else - other->slave = pll; -} - -int pll_vco_set_rate_8996(struct clk *c, unsigned long rate) -{ - int rc; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *pll = vco->priv; - struct mdss_pll_resources *slave; - struct dsi_pll_db *pdb; - - pdb = (struct dsi_pll_db *)pll->priv; - if (!pdb) { - pr_err("No prov found\n"); - return -EINVAL; - } - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable mdss dsi plla=%d\n", pll->index); - return rc; - } - - pll_source_setup(pll); - - pr_debug("%s: ndx=%d base=%p rate=%lu slave=%p\n", __func__, - pll->index, pll->pll_base, rate, pll->slave); - - pll->vco_current_rate = rate; - pll->vco_ref_clk_rate = vco->ref_clk_rate; - - mdss_dsi_pll_8996_input_init(pll, pdb); - - pll_8996_dec_frac_calc(pll, pdb); - - if (pll->ssc_en) - pll_8996_ssc_calc(pll, pdb); - - pll_8996_calc_vco_count(pdb, pll->vco_current_rate, - pll->vco_ref_clk_rate); - - /* commit slave if split display is enabled */ - slave = pll->slave; - if (slave) - pll_db_commit_8996(slave, pdb); - - /* commit master itself */ - pll_db_commit_8996(pll, pdb); - - mdss_pll_resource_enable(pll, false); - - return rc; -} - -static void shadow_pll_dynamic_refresh_8996(struct mdss_pll_resources *pll, - struct dsi_pll_db *pdb) -{ - struct dsi_pll_output *pout = &pdb->out; - - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL20, - DSIPHY_CMN_CTRL_0, DSIPHY_PLL_SYSCLK_EN_RESET, - 0xFF, 0x0); - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL21, - DSIPHY_PLL_DEC_START, DSIPHY_PLL_DIV_FRAC_START1, - pout->dec_start, (pout->div_frac_start & 0x0FF)); - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL22, - DSIPHY_PLL_DIV_FRAC_START2, DSIPHY_PLL_DIV_FRAC_START3, - ((pout->div_frac_start >> 8) & 0x0FF), - ((pout->div_frac_start >> 16) & 0x0F)); - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL23, - DSIPHY_PLL_PLLLOCK_CMP1, DSIPHY_PLL_PLLLOCK_CMP2, - (pout->plllock_cmp & 0x0FF), - ((pout->plllock_cmp >> 8) & 0x0FF)); - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL24, - DSIPHY_PLL_PLLLOCK_CMP3, DSIPHY_PLL_PLL_VCO_TUNE, - ((pout->plllock_cmp >> 16) & 0x03), - (pll->cache_pll_trim_codes[1] | BIT(7))); /* VCO tune*/ - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL25, - DSIPHY_PLL_KVCO_CODE, DSIPHY_PLL_RESETSM_CNTRL, - (pll->cache_pll_trim_codes[0] | BIT(5)), 0x38); - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL26, - DSIPHY_PLL_PLL_LPF2_POSTDIV, DSIPHY_CMN_PLL_CNTRL, - (((pout->pll_postdiv - 1) << 4) | pdb->in.pll_lpf_res1), 0x01); - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL27, - DSIPHY_CMN_PLL_CNTRL, DSIPHY_CMN_PLL_CNTRL, - 0x01, 0x01); - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL28, - DSIPHY_CMN_PLL_CNTRL, DSIPHY_CMN_PLL_CNTRL, - 0x01, 0x01); - MDSS_DYN_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_CTRL29, - DSIPHY_CMN_PLL_CNTRL, DSIPHY_CMN_PLL_CNTRL, - 0x01, 0x01); - MDSS_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR, 0x0000001E); - MDSS_PLL_REG_W(pll->dyn_pll_base, - DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR2, 0x001FFE00); - - /* - * Ensure all the dynamic refresh registers are written before - * dynamic refresh to change the fps is triggered - */ - wmb(); -} - -int shadow_pll_vco_set_rate_8996(struct clk *c, unsigned long rate) -{ - int rc; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *pll = vco->priv; - struct dsi_pll_db *pdb; - s64 vco_clk_rate = (s64)rate; - - if (!pll) { - pr_err("PLL data not found\n"); - return -EINVAL; - } - - pdb = pll->priv; - if (!pdb) { - pr_err("No priv data found\n"); - return -EINVAL; - } - - rc = mdss_pll_read_stored_trim_codes(pll, vco_clk_rate); - if (rc) { - pr_err("cannot find pll codes rate=%lld\n", vco_clk_rate); - return -EINVAL; - } - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable mdss dsi plla=%d\n", pll->index); - return rc; - } - - pr_debug("%s: ndx=%d base=%p rate=%lu\n", __func__, - pll->index, pll->pll_base, rate); - - pll->vco_current_rate = rate; - pll->vco_ref_clk_rate = vco->ref_clk_rate; - - mdss_dsi_pll_8996_input_init(pll, pdb); - - pll_8996_dec_frac_calc(pll, pdb); - - pll_8996_calc_vco_count(pdb, pll->vco_current_rate, - pll->vco_ref_clk_rate); - - shadow_pll_dynamic_refresh_8996(pll, pdb); - - rc = mdss_pll_resource_enable(pll, false); - if (rc) { - pr_err("Failed to enable mdss dsi plla=%d\n", pll->index); - return rc; - } - - return rc; -} - -unsigned long pll_vco_get_rate_8996(struct clk *c) -{ - u64 vco_rate, multiplier = BIT(20); - s32 div_frac_start; - u32 dec_start; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - u64 ref_clk = vco->ref_clk_rate; - int rc; - struct mdss_pll_resources *pll = vco->priv; - - if (is_gdsc_disabled(pll)) - return 0; - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll=%d\n", pll->index); - return rc; - } - - dec_start = MDSS_PLL_REG_R(pll->pll_base, - DSIPHY_PLL_DEC_START); - dec_start &= 0x0ff; - pr_debug("dec_start = 0x%x\n", dec_start); - - div_frac_start = (MDSS_PLL_REG_R(pll->pll_base, - DSIPHY_PLL_DIV_FRAC_START3) & 0x0f) << 16; - div_frac_start |= (MDSS_PLL_REG_R(pll->pll_base, - DSIPHY_PLL_DIV_FRAC_START2) & 0x0ff) << 8; - div_frac_start |= MDSS_PLL_REG_R(pll->pll_base, - DSIPHY_PLL_DIV_FRAC_START1) & 0x0ff; - pr_debug("div_frac_start = 0x%x\n", div_frac_start); - - vco_rate = ref_clk * dec_start; - vco_rate += ((ref_clk * div_frac_start) / multiplier); - - pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate); - - mdss_pll_resource_enable(pll, false); - - return (unsigned long)vco_rate; -} - -long pll_vco_round_rate_8996(struct clk *c, unsigned long rate) -{ - unsigned long rrate = rate; - u32 div; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - - div = vco->min_rate / rate; - if (div > 15) { - /* rate < 86.67 Mhz */ - pr_err("rate=%lu NOT supportted\n", rate); - return -EINVAL; - } - - if (rate < vco->min_rate) - rrate = vco->min_rate; - if (rate > vco->max_rate) - rrate = vco->max_rate; - - return rrate; -} - -enum handoff pll_vco_handoff_8996(struct clk *c) -{ - int rc; - enum handoff ret = HANDOFF_DISABLED_CLK; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *pll = vco->priv; - - if (is_gdsc_disabled(pll)) - return HANDOFF_DISABLED_CLK; - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll=%d\n", pll->index); - return ret; - } - - if (pll_is_pll_locked_8996(pll)) { - pll->handoff_resources = true; - pll->pll_on = true; - c->rate = pll_vco_get_rate_8996(c); - ret = HANDOFF_ENABLED_CLK; - } else { - mdss_pll_resource_enable(pll, false); - } - - return ret; -} - -enum handoff shadow_pll_vco_handoff_8996(struct clk *c) -{ - return HANDOFF_DISABLED_CLK; -} - -int pll_vco_prepare_8996(struct clk *c) -{ - int rc = 0; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *pll = vco->priv; - - if (!pll) { - pr_err("Dsi pll resources are not available\n"); - return -EINVAL; - } - - rc = mdss_pll_resource_enable(pll, true); - if (rc) { - pr_err("ndx=%d Failed to enable mdss dsi pll resources\n", - pll->index); - return rc; - } - - if ((pll->vco_cached_rate != 0) - && (pll->vco_cached_rate == c->rate)) { - rc = c->ops->set_rate(c, pll->vco_cached_rate); - if (rc) { - pr_err("index=%d vco_set_rate failed. rc=%d\n", - rc, pll->index); - mdss_pll_resource_enable(pll, false); - goto error; - } - } - - rc = dsi_pll_enable(c); - - if (rc) { - mdss_pll_resource_enable(pll, false); - pr_err("ndx=%d failed to enable dsi pll\n", pll->index); - } - -error: - return rc; -} - -void pll_vco_unprepare_8996(struct clk *c) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *pll = vco->priv; - - if (!pll) { - pr_err("Dsi pll resources are not available\n"); - return; - } - - pll->vco_cached_rate = c->rate; - dsi_pll_disable(c); -} diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-8996.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-8996.c deleted file mode 100644 index e975fd3d407149833aed3254e960c6bea11ca81a..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-8996.c +++ /dev/null @@ -1,548 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mdss-pll.h" -#include "mdss-dsi-pll.h" -#include "mdss-dsi-pll-8996.h" - -#define VCO_DELAY_USEC 1 - -static struct dsi_pll_db pll_db[DSI_PLL_NUM]; - -static const struct clk_ops n2_clk_src_ops; -static const struct clk_ops shadow_n2_clk_src_ops; -static const struct clk_ops byte_clk_src_ops; -static const struct clk_ops post_n1_div_clk_src_ops; -static const struct clk_ops shadow_post_n1_div_clk_src_ops; - -static const struct clk_ops clk_ops_gen_mux_dsi; - -/* Op structures */ -static const struct clk_ops clk_ops_dsi_vco = { - .set_rate = pll_vco_set_rate_8996, - .round_rate = pll_vco_round_rate_8996, - .handoff = pll_vco_handoff_8996, - .prepare = pll_vco_prepare_8996, - .unprepare = pll_vco_unprepare_8996, -}; - -static struct clk_div_ops post_n1_div_ops = { - .set_div = post_n1_div_set_div, - .get_div = post_n1_div_get_div, -}; - -static struct clk_div_ops n2_div_ops = { /* hr_oclk3 */ - .set_div = n2_div_set_div, - .get_div = n2_div_get_div, -}; - -static struct clk_mux_ops mdss_byte_mux_ops = { - .set_mux_sel = set_mdss_byte_mux_sel_8996, - .get_mux_sel = get_mdss_byte_mux_sel_8996, -}; - -static struct clk_mux_ops mdss_pixel_mux_ops = { - .set_mux_sel = set_mdss_pixel_mux_sel_8996, - .get_mux_sel = get_mdss_pixel_mux_sel_8996, -}; - -/* Shadow ops for dynamic refresh */ -static const struct clk_ops clk_ops_shadow_dsi_vco = { - .set_rate = shadow_pll_vco_set_rate_8996, - .round_rate = pll_vco_round_rate_8996, - .handoff = shadow_pll_vco_handoff_8996, -}; - -static struct clk_div_ops shadow_post_n1_div_ops = { - .set_div = post_n1_div_set_div, -}; - -static struct clk_div_ops shadow_n2_div_ops = { - .set_div = shadow_n2_div_set_div, -}; - -static struct dsi_pll_vco_clk dsi0pll_vco_clk = { - .ref_clk_rate = 19200000UL, - .min_rate = 1300000000UL, - .max_rate = 2600000000UL, - .pll_en_seq_cnt = 1, - .pll_enable_seqs[0] = dsi_pll_enable_seq_8996, - .c = { - .dbg_name = "dsi0pll_vco_clk_8996", - .ops = &clk_ops_dsi_vco, - CLK_INIT(dsi0pll_vco_clk.c), - }, -}; - -static struct dsi_pll_vco_clk dsi0pll_shadow_vco_clk = { - .ref_clk_rate = 19200000u, - .min_rate = 1300000000u, - .max_rate = 2600000000u, - .c = { - .dbg_name = "dsi0pll_shadow_vco_clk", - .ops = &clk_ops_shadow_dsi_vco, - CLK_INIT(dsi0pll_shadow_vco_clk.c), - }, -}; - -static struct dsi_pll_vco_clk dsi1pll_vco_clk = { - .ref_clk_rate = 19200000UL, - .min_rate = 1300000000UL, - .max_rate = 2600000000UL, - .pll_en_seq_cnt = 1, - .pll_enable_seqs[0] = dsi_pll_enable_seq_8996, - .c = { - .dbg_name = "dsi1pll_vco_clk_8996", - .ops = &clk_ops_dsi_vco, - CLK_INIT(dsi1pll_vco_clk.c), - }, -}; - -static struct dsi_pll_vco_clk dsi1pll_shadow_vco_clk = { - .ref_clk_rate = 19200000u, - .min_rate = 1300000000u, - .max_rate = 2600000000u, - .pll_en_seq_cnt = 1, - .pll_enable_seqs[0] = dsi_pll_enable_seq_8996, - .c = { - .dbg_name = "dsi1pll_shadow_vco_clk", - .ops = &clk_ops_shadow_dsi_vco, - CLK_INIT(dsi1pll_shadow_vco_clk.c), - }, -}; - -static struct div_clk dsi0pll_post_n1_div_clk = { - .data = { - .max_div = 15, - .min_div = 1, - }, - .ops = &post_n1_div_ops, - .c = { - .parent = &dsi0pll_vco_clk.c, - .dbg_name = "dsi0pll_post_n1_div_clk", - .ops = &post_n1_div_clk_src_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi0pll_post_n1_div_clk.c), - }, -}; - -static struct div_clk dsi0pll_shadow_post_n1_div_clk = { - .data = { - .max_div = 15, - .min_div = 1, - }, - .ops = &shadow_post_n1_div_ops, - .c = { - .parent = &dsi0pll_shadow_vco_clk.c, - .dbg_name = "dsi0pll_shadow_post_n1_div_clk", - .ops = &shadow_post_n1_div_clk_src_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi0pll_shadow_post_n1_div_clk.c), - }, -}; - -static struct div_clk dsi1pll_post_n1_div_clk = { - .data = { - .max_div = 15, - .min_div = 1, - }, - .ops = &post_n1_div_ops, - .c = { - .parent = &dsi1pll_vco_clk.c, - .dbg_name = "dsi1pll_post_n1_div_clk", - .ops = &post_n1_div_clk_src_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi1pll_post_n1_div_clk.c), - }, -}; - -static struct div_clk dsi1pll_shadow_post_n1_div_clk = { - .data = { - .max_div = 15, - .min_div = 1, - }, - .ops = &shadow_post_n1_div_ops, - .c = { - .parent = &dsi1pll_shadow_vco_clk.c, - .dbg_name = "dsi1pll_shadow_post_n1_div_clk", - .ops = &shadow_post_n1_div_clk_src_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi1pll_shadow_post_n1_div_clk.c), - }, -}; - -static struct div_clk dsi0pll_n2_div_clk = { - .data = { - .max_div = 15, - .min_div = 1, - }, - .ops = &n2_div_ops, - .c = { - .parent = &dsi0pll_post_n1_div_clk.c, - .dbg_name = "dsi0pll_n2_div_clk", - .ops = &n2_clk_src_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi0pll_n2_div_clk.c), - }, -}; - -static struct div_clk dsi0pll_shadow_n2_div_clk = { - .data = { - .max_div = 15, - .min_div = 1, - }, - .ops = &shadow_n2_div_ops, - .c = { - .parent = &dsi0pll_shadow_post_n1_div_clk.c, - .dbg_name = "dsi0pll_shadow_n2_div_clk", - .ops = &shadow_n2_clk_src_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi0pll_shadow_n2_div_clk.c), - }, -}; - -static struct div_clk dsi1pll_n2_div_clk = { - .data = { - .max_div = 15, - .min_div = 1, - }, - .ops = &n2_div_ops, - .c = { - .parent = &dsi1pll_post_n1_div_clk.c, - .dbg_name = "dsi1pll_n2_div_clk", - .ops = &n2_clk_src_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi1pll_n2_div_clk.c), - }, -}; - -static struct div_clk dsi1pll_shadow_n2_div_clk = { - .data = { - .max_div = 15, - .min_div = 1, - }, - .ops = &shadow_n2_div_ops, - .c = { - .parent = &dsi1pll_shadow_post_n1_div_clk.c, - .dbg_name = "dsi1pll_shadow_n2_div_clk", - .ops = &shadow_n2_clk_src_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi1pll_shadow_n2_div_clk.c), - }, -}; - -static struct div_clk dsi0pll_pixel_clk_src = { - .data = { - .div = 2, - .min_div = 2, - .max_div = 2, - }, - .c = { - .parent = &dsi0pll_n2_div_clk.c, - .dbg_name = "dsi0pll_pixel_clk_src", - .ops = &clk_ops_div, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi0pll_pixel_clk_src.c), - }, -}; - -static struct div_clk dsi0pll_shadow_pixel_clk_src = { - .data = { - .div = 2, - .min_div = 2, - .max_div = 2, - }, - .c = { - .parent = &dsi0pll_shadow_n2_div_clk.c, - .dbg_name = "dsi0pll_shadow_pixel_clk_src", - .ops = &clk_ops_div, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi0pll_shadow_pixel_clk_src.c), - }, -}; - -static struct div_clk dsi1pll_pixel_clk_src = { - .data = { - .div = 2, - .min_div = 2, - .max_div = 2, - }, - .c = { - .parent = &dsi1pll_n2_div_clk.c, - .dbg_name = "dsi1pll_pixel_clk_src", - .ops = &clk_ops_div, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi1pll_pixel_clk_src.c), - }, -}; - -static struct div_clk dsi1pll_shadow_pixel_clk_src = { - .data = { - .div = 2, - .min_div = 2, - .max_div = 2, - }, - .c = { - .parent = &dsi1pll_shadow_n2_div_clk.c, - .dbg_name = "dsi1pll_shadow_pixel_clk_src", - .ops = &clk_ops_div, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi1pll_shadow_pixel_clk_src.c), - }, -}; - -static struct mux_clk dsi0pll_pixel_clk_mux = { - .num_parents = 2, - .parents = (struct clk_src[]) { - {&dsi0pll_pixel_clk_src.c, 0}, - {&dsi0pll_shadow_pixel_clk_src.c, 1}, - }, - .ops = &mdss_pixel_mux_ops, - .c = { - .parent = &dsi0pll_pixel_clk_src.c, - .dbg_name = "dsi0pll_pixel_clk_mux", - .ops = &clk_ops_gen_mux_dsi, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi0pll_pixel_clk_mux.c), - } -}; - -static struct mux_clk dsi1pll_pixel_clk_mux = { - .num_parents = 2, - .parents = (struct clk_src[]) { - {&dsi1pll_pixel_clk_src.c, 0}, - {&dsi1pll_shadow_pixel_clk_src.c, 1}, - }, - .ops = &mdss_pixel_mux_ops, - .c = { - .parent = &dsi1pll_pixel_clk_src.c, - .dbg_name = "dsi1pll_pixel_clk_mux", - .ops = &clk_ops_gen_mux_dsi, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi1pll_pixel_clk_mux.c), - } -}; - -static struct div_clk dsi0pll_byte_clk_src = { - .data = { - .div = 8, - .min_div = 8, - .max_div = 8, - }, - .c = { - .parent = &dsi0pll_post_n1_div_clk.c, - .dbg_name = "dsi0pll_byte_clk_src", - .ops = &clk_ops_div, - CLK_INIT(dsi0pll_byte_clk_src.c), - }, -}; - -static struct div_clk dsi0pll_shadow_byte_clk_src = { - .data = { - .div = 8, - .min_div = 8, - .max_div = 8, - }, - .c = { - .parent = &dsi0pll_shadow_post_n1_div_clk.c, - .dbg_name = "dsi0pll_shadow_byte_clk_src", - .ops = &clk_ops_div, - CLK_INIT(dsi0pll_shadow_byte_clk_src.c), - }, -}; - -static struct div_clk dsi1pll_byte_clk_src = { - .data = { - .div = 8, - .min_div = 8, - .max_div = 8, - }, - .c = { - .parent = &dsi1pll_post_n1_div_clk.c, - .dbg_name = "dsi1pll_byte_clk_src", - .ops = &clk_ops_div, - CLK_INIT(dsi1pll_byte_clk_src.c), - }, -}; - -static struct div_clk dsi1pll_shadow_byte_clk_src = { - .data = { - .div = 8, - .min_div = 8, - .max_div = 8, - }, - .c = { - .parent = &dsi1pll_shadow_post_n1_div_clk.c, - .dbg_name = "dsi1pll_shadow_byte_clk_src", - .ops = &clk_ops_div, - CLK_INIT(dsi1pll_shadow_byte_clk_src.c), - }, -}; - -static struct mux_clk dsi0pll_byte_clk_mux = { - .num_parents = 2, - .parents = (struct clk_src[]) { - {&dsi0pll_byte_clk_src.c, 0}, - {&dsi0pll_shadow_byte_clk_src.c, 1}, - }, - .ops = &mdss_byte_mux_ops, - .c = { - .parent = &dsi0pll_byte_clk_src.c, - .dbg_name = "dsi0pll_byte_clk_mux", - .ops = &clk_ops_gen_mux_dsi, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi0pll_byte_clk_mux.c), - } -}; -static struct mux_clk dsi1pll_byte_clk_mux = { - .num_parents = 2, - .parents = (struct clk_src[]) { - {&dsi1pll_byte_clk_src.c, 0}, - {&dsi1pll_shadow_byte_clk_src.c, 1}, - }, - .ops = &mdss_byte_mux_ops, - .c = { - .parent = &dsi1pll_byte_clk_src.c, - .dbg_name = "dsi1pll_byte_clk_mux", - .ops = &clk_ops_gen_mux_dsi, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(dsi1pll_byte_clk_mux.c), - } -}; - -static struct clk_lookup mdss_dsi_pllcc_8996[] = { - CLK_LIST(dsi0pll_byte_clk_mux), - CLK_LIST(dsi0pll_byte_clk_src), - CLK_LIST(dsi0pll_pixel_clk_mux), - CLK_LIST(dsi0pll_pixel_clk_src), - CLK_LIST(dsi0pll_n2_div_clk), - CLK_LIST(dsi0pll_post_n1_div_clk), - CLK_LIST(dsi0pll_vco_clk), - CLK_LIST(dsi0pll_shadow_byte_clk_src), - CLK_LIST(dsi0pll_shadow_pixel_clk_src), - CLK_LIST(dsi0pll_shadow_n2_div_clk), - CLK_LIST(dsi0pll_shadow_post_n1_div_clk), - CLK_LIST(dsi0pll_shadow_vco_clk), -}; - -static struct clk_lookup mdss_dsi_pllcc_8996_1[] = { - CLK_LIST(dsi1pll_byte_clk_mux), - CLK_LIST(dsi1pll_byte_clk_src), - CLK_LIST(dsi1pll_pixel_clk_mux), - CLK_LIST(dsi1pll_pixel_clk_src), - CLK_LIST(dsi1pll_n2_div_clk), - CLK_LIST(dsi1pll_post_n1_div_clk), - CLK_LIST(dsi1pll_vco_clk), - CLK_LIST(dsi1pll_shadow_byte_clk_src), - CLK_LIST(dsi1pll_shadow_pixel_clk_src), - CLK_LIST(dsi1pll_shadow_n2_div_clk), - CLK_LIST(dsi1pll_shadow_post_n1_div_clk), - CLK_LIST(dsi1pll_shadow_vco_clk), -}; - -int dsi_pll_clock_register_8996(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int rc = 0, ndx; - int const ssc_freq_default = 31500; /* default h/w recommended value */ - int const ssc_ppm_default = 5000; /* default h/w recommended value */ - struct dsi_pll_db *pdb; - - if (pll_res->index >= DSI_PLL_NUM) { - pr_err("pll ndx=%d is NOT supported\n", pll_res->index); - return -EINVAL; - } - - ndx = pll_res->index; - pdb = &pll_db[ndx]; - pll_res->priv = pdb; - pdb->pll = pll_res; - ndx++; - ndx %= DSI_PLL_NUM; - pdb->next = &pll_db[ndx]; - - /* Set clock source operations */ - - /* hr_oclk3, pixel */ - n2_clk_src_ops = clk_ops_slave_div; - n2_clk_src_ops.prepare = mdss_pll_div_prepare; - - shadow_n2_clk_src_ops = clk_ops_slave_div; - - /* hr_ockl2, byte, vco pll */ - post_n1_div_clk_src_ops = clk_ops_div; - post_n1_div_clk_src_ops.prepare = mdss_pll_div_prepare; - - shadow_post_n1_div_clk_src_ops = clk_ops_div; - - byte_clk_src_ops = clk_ops_div; - byte_clk_src_ops.prepare = mdss_pll_div_prepare; - - clk_ops_gen_mux_dsi = clk_ops_gen_mux; - clk_ops_gen_mux_dsi.round_rate = parent_round_rate; - clk_ops_gen_mux_dsi.set_rate = parent_set_rate; - - if (pll_res->ssc_en) { - if (!pll_res->ssc_freq) - pll_res->ssc_freq = ssc_freq_default; - if (!pll_res->ssc_ppm) - pll_res->ssc_ppm = ssc_ppm_default; - } - - /* Set client data to mux, div and vco clocks. */ - if (pll_res->index == DSI_PLL_1) { - dsi1pll_byte_clk_src.priv = pll_res; - dsi1pll_pixel_clk_src.priv = pll_res; - dsi1pll_post_n1_div_clk.priv = pll_res; - dsi1pll_n2_div_clk.priv = pll_res; - dsi1pll_vco_clk.priv = pll_res; - - dsi1pll_shadow_byte_clk_src.priv = pll_res; - dsi1pll_shadow_pixel_clk_src.priv = pll_res; - dsi1pll_shadow_post_n1_div_clk.priv = pll_res; - dsi1pll_shadow_n2_div_clk.priv = pll_res; - dsi1pll_shadow_vco_clk.priv = pll_res; - - pll_res->vco_delay = VCO_DELAY_USEC; - rc = of_msm_clock_register(pdev->dev.of_node, - mdss_dsi_pllcc_8996_1, - ARRAY_SIZE(mdss_dsi_pllcc_8996_1)); - } else { - dsi0pll_byte_clk_src.priv = pll_res; - dsi0pll_pixel_clk_src.priv = pll_res; - dsi0pll_post_n1_div_clk.priv = pll_res; - dsi0pll_n2_div_clk.priv = pll_res; - dsi0pll_vco_clk.priv = pll_res; - - dsi0pll_shadow_byte_clk_src.priv = pll_res; - dsi0pll_shadow_pixel_clk_src.priv = pll_res; - dsi0pll_shadow_post_n1_div_clk.priv = pll_res; - dsi0pll_shadow_n2_div_clk.priv = pll_res; - dsi0pll_shadow_vco_clk.priv = pll_res; - - pll_res->vco_delay = VCO_DELAY_USEC; - rc = of_msm_clock_register(pdev->dev.of_node, - mdss_dsi_pllcc_8996, - ARRAY_SIZE(mdss_dsi_pllcc_8996)); - } - - if (!rc) { - pr_info("Registered DSI PLL ndx=%d clocks successfully\n", - pll_res->index); - } - - return rc; -} diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-8996.h b/drivers/clk/qcom/mdss/mdss-dsi-pll-8996.h deleted file mode 100644 index 023a481d7c42d893ce70ef3ff133b35aab9f0690..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-8996.h +++ /dev/null @@ -1,214 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - */ - -#ifndef MDSS_DSI_PLL_8996_H -#define MDSS_DSI_PLL_8996_H - -#define DSIPHY_CMN_CLK_CFG0 0x0010 -#define DSIPHY_CMN_CLK_CFG1 0x0014 -#define DSIPHY_CMN_GLBL_TEST_CTRL 0x0018 - -#define DSIPHY_CMN_PLL_CNTRL 0x0048 -#define DSIPHY_CMN_CTRL_0 0x001c -#define DSIPHY_CMN_CTRL_1 0x0020 - -#define DSIPHY_CMN_LDO_CNTRL 0x004c - -#define DSIPHY_PLL_IE_TRIM 0x0400 -#define DSIPHY_PLL_IP_TRIM 0x0404 - -#define DSIPHY_PLL_IPTAT_TRIM 0x0410 - -#define DSIPHY_PLL_CLKBUFLR_EN 0x041c - -#define DSIPHY_PLL_SYSCLK_EN_RESET 0x0428 -#define DSIPHY_PLL_RESETSM_CNTRL 0x042c -#define DSIPHY_PLL_RESETSM_CNTRL2 0x0430 -#define DSIPHY_PLL_RESETSM_CNTRL3 0x0434 -#define DSIPHY_PLL_RESETSM_CNTRL4 0x0438 -#define DSIPHY_PLL_RESETSM_CNTRL5 0x043c -#define DSIPHY_PLL_KVCO_DIV_REF1 0x0440 -#define DSIPHY_PLL_KVCO_DIV_REF2 0x0444 -#define DSIPHY_PLL_KVCO_COUNT1 0x0448 -#define DSIPHY_PLL_KVCO_COUNT2 0x044c -#define DSIPHY_PLL_VREF_CFG1 0x045c - -#define DSIPHY_PLL_KVCO_CODE 0x0458 - -#define DSIPHY_PLL_VCO_DIV_REF1 0x046c -#define DSIPHY_PLL_VCO_DIV_REF2 0x0470 -#define DSIPHY_PLL_VCO_COUNT1 0x0474 -#define DSIPHY_PLL_VCO_COUNT2 0x0478 -#define DSIPHY_PLL_PLLLOCK_CMP1 0x047c -#define DSIPHY_PLL_PLLLOCK_CMP2 0x0480 -#define DSIPHY_PLL_PLLLOCK_CMP3 0x0484 -#define DSIPHY_PLL_PLLLOCK_CMP_EN 0x0488 -#define DSIPHY_PLL_PLL_VCO_TUNE 0x048C -#define DSIPHY_PLL_DEC_START 0x0490 -#define DSIPHY_PLL_SSC_EN_CENTER 0x0494 -#define DSIPHY_PLL_SSC_ADJ_PER1 0x0498 -#define DSIPHY_PLL_SSC_ADJ_PER2 0x049c -#define DSIPHY_PLL_SSC_PER1 0x04a0 -#define DSIPHY_PLL_SSC_PER2 0x04a4 -#define DSIPHY_PLL_SSC_STEP_SIZE1 0x04a8 -#define DSIPHY_PLL_SSC_STEP_SIZE2 0x04ac -#define DSIPHY_PLL_DIV_FRAC_START1 0x04b4 -#define DSIPHY_PLL_DIV_FRAC_START2 0x04b8 -#define DSIPHY_PLL_DIV_FRAC_START3 0x04bc -#define DSIPHY_PLL_TXCLK_EN 0x04c0 -#define DSIPHY_PLL_PLL_CRCTRL 0x04c4 - -#define DSIPHY_PLL_RESET_SM_READY_STATUS 0x04cc - -#define DSIPHY_PLL_PLL_MISC1 0x04e8 - -#define DSIPHY_PLL_CP_SET_CUR 0x04f0 -#define DSIPHY_PLL_PLL_ICPMSET 0x04f4 -#define DSIPHY_PLL_PLL_ICPCSET 0x04f8 -#define DSIPHY_PLL_PLL_ICP_SET 0x04fc -#define DSIPHY_PLL_PLL_LPF1 0x0500 -#define DSIPHY_PLL_PLL_LPF2_POSTDIV 0x0504 -#define DSIPHY_PLL_PLL_BANDGAP 0x0508 - -#define DSI_DYNAMIC_REFRESH_PLL_CTRL15 0x050 -#define DSI_DYNAMIC_REFRESH_PLL_CTRL19 0x060 -#define DSI_DYNAMIC_REFRESH_PLL_CTRL20 0x064 -#define DSI_DYNAMIC_REFRESH_PLL_CTRL21 0x068 -#define DSI_DYNAMIC_REFRESH_PLL_CTRL22 0x06C -#define DSI_DYNAMIC_REFRESH_PLL_CTRL23 0x070 -#define DSI_DYNAMIC_REFRESH_PLL_CTRL24 0x074 -#define DSI_DYNAMIC_REFRESH_PLL_CTRL25 0x078 -#define DSI_DYNAMIC_REFRESH_PLL_CTRL26 0x07C -#define DSI_DYNAMIC_REFRESH_PLL_CTRL27 0x080 -#define DSI_DYNAMIC_REFRESH_PLL_CTRL28 0x084 -#define DSI_DYNAMIC_REFRESH_PLL_CTRL29 0x088 -#define DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR 0x094 -#define DSI_DYNAMIC_REFRESH_PLL_UPPER_ADDR2 0x098 - -struct dsi_pll_input { - u32 fref; /* 19.2 Mhz, reference clk */ - u32 fdata; /* bit clock rate */ - u32 dsiclk_sel; /* 1, reg: 0x0014 */ - u32 n2div; /* 1, reg: 0x0010, bit 4-7 */ - u32 ssc_en; /* 1, reg: 0x0494, bit 0 */ - u32 ldo_en; /* 0, reg: 0x004c, bit 0 */ - - /* fixed */ - u32 refclk_dbler_en; /* 0, reg: 0x04c0, bit 1 */ - u32 vco_measure_time; /* 5, unknown */ - u32 kvco_measure_time; /* 5, unknown */ - u32 bandgap_timer; /* 4, reg: 0x0430, bit 3 - 5 */ - u32 pll_wakeup_timer; /* 5, reg: 0x043c, bit 0 - 2 */ - u32 plllock_cnt; /* 1, reg: 0x0488, bit 1 - 2 */ - u32 plllock_rng; /* 1, reg: 0x0488, bit 3 - 4 */ - u32 ssc_center; /* 0, reg: 0x0494, bit 1 */ - u32 ssc_adj_period; /* 37, reg: 0x498, bit 0 - 9 */ - u32 ssc_spread; /* 0.005 */ - u32 ssc_freq; /* unknown */ - u32 pll_ie_trim; /* 4, reg: 0x0400 */ - u32 pll_ip_trim; /* 4, reg: 0x0404 */ - u32 pll_iptat_trim; /* reg: 0x0410 */ - u32 pll_cpcset_cur; /* 1, reg: 0x04f0, bit 0 - 2 */ - u32 pll_cpmset_cur; /* 1, reg: 0x04f0, bit 3 - 5 */ - - u32 pll_icpmset; /* 4, reg: 0x04fc, bit 3 - 5 */ - u32 pll_icpcset; /* 4, reg: 0x04fc, bit 0 - 2 */ - - u32 pll_icpmset_p; /* 0, reg: 0x04f4, bit 0 - 2 */ - u32 pll_icpmset_m; /* 0, reg: 0x04f4, bit 3 - 5 */ - - u32 pll_icpcset_p; /* 0, reg: 0x04f8, bit 0 - 2 */ - u32 pll_icpcset_m; /* 0, reg: 0x04f8, bit 3 - 5 */ - - u32 pll_lpf_res1; /* 3, reg: 0x0504, bit 0 - 3 */ - u32 pll_lpf_cap1; /* 11, reg: 0x0500, bit 0 - 3 */ - u32 pll_lpf_cap2; /* 1, reg: 0x0500, bit 4 - 7 */ - u32 pll_c3ctrl; /* 2, reg: 0x04c4 */ - u32 pll_r3ctrl; /* 1, reg: 0x04c4 */ -}; - -struct dsi_pll_output { - u32 pll_txclk_en; /* reg: 0x04c0 */ - u32 dec_start; /* reg: 0x0490 */ - u32 div_frac_start; /* reg: 0x04b4, 0x4b8, 0x04bc */ - u32 ssc_period; /* reg: 0x04a0, 0x04a4 */ - u32 ssc_step_size; /* reg: 0x04a8, 0x04ac */ - u32 plllock_cmp; /* reg: 0x047c, 0x0480, 0x0484 */ - u32 pll_vco_div_ref; /* reg: 0x046c, 0x0470 */ - u32 pll_vco_count; /* reg: 0x0474, 0x0478 */ - u32 pll_kvco_div_ref; /* reg: 0x0440, 0x0444 */ - u32 pll_kvco_count; /* reg: 0x0448, 0x044c */ - u32 pll_misc1; /* reg: 0x04e8 */ - u32 pll_lpf2_postdiv; /* reg: 0x0504 */ - u32 pll_resetsm_cntrl; /* reg: 0x042c */ - u32 pll_resetsm_cntrl2; /* reg: 0x0430 */ - u32 pll_resetsm_cntrl5; /* reg: 0x043c */ - u32 pll_kvco_code; /* reg: 0x0458 */ - - u32 cmn_clk_cfg0; /* reg: 0x0010 */ - u32 cmn_clk_cfg1; /* reg: 0x0014 */ - u32 cmn_ldo_cntrl; /* reg: 0x004c */ - - u32 pll_postdiv; /* vco */ - u32 pll_n1div; /* vco */ - u32 pll_n2div; /* hr_oclk3, pixel */ - u32 fcvo; -}; - -enum { - DSI_PLL_0, - DSI_PLL_1, - DSI_PLL_NUM -}; - -struct dsi_pll_db { - struct dsi_pll_db *next; - struct mdss_pll_resources *pll; - struct dsi_pll_input in; - struct dsi_pll_output out; - int source_setup_done; -}; - -enum { - PLL_OUTPUT_NONE, - PLL_OUTPUT_RIGHT, - PLL_OUTPUT_LEFT, - PLL_OUTPUT_BOTH -}; - -enum { - PLL_SOURCE_FROM_LEFT, - PLL_SOURCE_FROM_RIGHT -}; - -enum { - PLL_UNKNOWN, - PLL_STANDALONE, - PLL_SLAVE, - PLL_MASTER -}; - -int pll_vco_set_rate_8996(struct clk *c, unsigned long rate); -long pll_vco_round_rate_8996(struct clk *c, unsigned long rate); -enum handoff pll_vco_handoff_8996(struct clk *c); -enum handoff shadow_pll_vco_handoff_8996(struct clk *c); -int shadow_post_n1_div_set_div(struct div_clk *clk, int div); -int shadow_post_n1_div_get_div(struct div_clk *clk); -int shadow_n2_div_set_div(struct div_clk *clk, int div); -int shadow_n2_div_get_div(struct div_clk *clk); -int shadow_pll_vco_set_rate_8996(struct clk *c, unsigned long rate); -int pll_vco_prepare_8996(struct clk *c); -void pll_vco_unprepare_8996(struct clk *c); -int set_mdss_byte_mux_sel_8996(struct mux_clk *clk, int sel); -int get_mdss_byte_mux_sel_8996(struct mux_clk *clk); -int set_mdss_pixel_mux_sel_8996(struct mux_clk *clk, int sel); -int get_mdss_pixel_mux_sel_8996(struct mux_clk *clk); -int post_n1_div_set_div(struct div_clk *clk, int div); -int post_n1_div_get_div(struct div_clk *clk); -int n2_div_set_div(struct div_clk *clk, int div); -int n2_div_get_div(struct div_clk *clk); -int dsi_pll_enable_seq_8996(struct mdss_pll_resources *pll); - -#endif /* MDSS_DSI_PLL_8996_H */ diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-util.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-util.c deleted file mode 100644 index f8b8337d546bce3bbd446f81ce53143ee40da711..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-util.c +++ /dev/null @@ -1,580 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include - -#include "mdss-pll.h" -#include "mdss-dsi-pll.h" - -#define DSI_PHY_PLL_UNIPHY_PLL_REFCLK_CFG (0x0) -#define DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG (0x0004) -#define DSI_PHY_PLL_UNIPHY_PLL_CHGPUMP_CFG (0x0008) -#define DSI_PHY_PLL_UNIPHY_PLL_VCOLPF_CFG (0x000C) -#define DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG (0x0010) -#define DSI_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG (0x0014) -#define DSI_PHY_PLL_UNIPHY_PLL_POSTDIV2_CFG (0x0024) -#define DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG (0x0028) -#define DSI_PHY_PLL_UNIPHY_PLL_LPFR_CFG (0x002C) -#define DSI_PHY_PLL_UNIPHY_PLL_LPFC1_CFG (0x0030) -#define DSI_PHY_PLL_UNIPHY_PLL_LPFC2_CFG (0x0034) -#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0 (0x0038) -#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1 (0x003C) -#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2 (0x0040) -#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3 (0x0044) -#define DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG4 (0x0048) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG0 (0x006C) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG2 (0x0074) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG3 (0x0078) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG4 (0x007C) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG5 (0x0080) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG6 (0x0084) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG7 (0x0088) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG8 (0x008C) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG9 (0x0090) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG10 (0x0094) -#define DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG11 (0x0098) -#define DSI_PHY_PLL_UNIPHY_PLL_EFUSE_CFG (0x009C) -#define DSI_PHY_PLL_UNIPHY_PLL_STATUS (0x00C0) - -#define DSI_PLL_POLL_DELAY_US 50 -#define DSI_PLL_POLL_TIMEOUT_US 500 - -int set_byte_mux_sel(struct mux_clk *clk, int sel) -{ - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - pr_debug("byte mux set to %s mode\n", sel ? "indirect" : "direct"); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG, (sel << 1)); - - return 0; -} - -int get_byte_mux_sel(struct mux_clk *clk) -{ - int mux_mode, rc; - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - if (is_gdsc_disabled(dsi_pll_res)) - return 0; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - mux_mode = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_VREG_CFG) & BIT(1); - - pr_debug("byte mux mode = %s\n", mux_mode ? "indirect" : "direct"); - mdss_pll_resource_enable(dsi_pll_res, false); - - return !!mux_mode; -} - -int dsi_pll_div_prepare(struct clk *c) -{ - struct div_clk *div = to_div_clk(c); - /* Restore the divider's value */ - return div->ops->set_div(div, div->data.div); -} - -int dsi_pll_mux_prepare(struct clk *c) -{ - struct mux_clk *mux = to_mux_clk(c); - int i, rc, sel = 0; - struct mdss_pll_resources *dsi_pll_res = mux->priv; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - for (i = 0; i < mux->num_parents; i++) - if (mux->parents[i].src == c->parent) { - sel = mux->parents[i].sel; - break; - } - - if (i == mux->num_parents) { - pr_err("Failed to select the parent clock\n"); - rc = -EINVAL; - goto error; - } - - /* Restore the mux source select value */ - rc = mux->ops->set_mux_sel(mux, sel); - -error: - mdss_pll_resource_enable(dsi_pll_res, false); - return rc; -} - -int fixed_4div_set_div(struct div_clk *clk, int div) -{ - int rc; - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_POSTDIV2_CFG, (div - 1)); - - mdss_pll_resource_enable(dsi_pll_res, false); - return rc; -} - -int fixed_4div_get_div(struct div_clk *clk) -{ - int div = 0, rc; - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - if (is_gdsc_disabled(dsi_pll_res)) - return 0; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - div = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_POSTDIV2_CFG); - - mdss_pll_resource_enable(dsi_pll_res, false); - return div + 1; -} - -int digital_set_div(struct div_clk *clk, int div) -{ - int rc; - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG, (div - 1)); - - mdss_pll_resource_enable(dsi_pll_res, false); - return rc; -} - -int digital_get_div(struct div_clk *clk) -{ - int div = 0, rc; - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - if (is_gdsc_disabled(dsi_pll_res)) - return 0; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - div = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG); - - mdss_pll_resource_enable(dsi_pll_res, false); - return div + 1; -} - -int analog_set_div(struct div_clk *clk, int div) -{ - int rc; - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG, div - 1); - - mdss_pll_resource_enable(dsi_pll_res, false); - return rc; -} - -int analog_get_div(struct div_clk *clk) -{ - int div = 0, rc; - struct mdss_pll_resources *dsi_pll_res = clk->priv; - - if (is_gdsc_disabled(dsi_pll_res)) - return 0; - - rc = mdss_pll_resource_enable(clk->priv, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - div = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG) + 1; - - mdss_pll_resource_enable(dsi_pll_res, false); - - return div; -} - -int dsi_pll_lock_status(struct mdss_pll_resources *dsi_pll_res) -{ - u32 status; - int pll_locked; - - /* poll for PLL ready status */ - if (readl_poll_timeout_atomic((dsi_pll_res->pll_base + - DSI_PHY_PLL_UNIPHY_PLL_STATUS), - status, - ((status & BIT(0)) == 1), - DSI_PLL_POLL_DELAY_US, - DSI_PLL_POLL_TIMEOUT_US)) { - pr_debug("DSI PLL status=%x failed to Lock\n", status); - pll_locked = 0; - } else { - pll_locked = 1; - } - - return pll_locked; -} - -int vco_set_rate(struct dsi_pll_vco_clk *vco, unsigned long rate) -{ - s64 vco_clk_rate = rate; - s32 rem; - s64 refclk_cfg, frac_n_mode, ref_doubler_en_b; - s64 ref_clk_to_pll, div_fbx1000, frac_n_value; - s64 sdm_cfg0, sdm_cfg1, sdm_cfg2, sdm_cfg3; - s64 gen_vco_clk, cal_cfg10, cal_cfg11; - u32 res; - int i; - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - /* Configure the Loop filter resistance */ - for (i = 0; i < vco->lpfr_lut_size; i++) - if (vco_clk_rate <= vco->lpfr_lut[i].vco_rate) - break; - if (i == vco->lpfr_lut_size) { - pr_err("unable to get loop filter resistance. vco=%ld\n", rate); - return -EINVAL; - } - res = vco->lpfr_lut[i].r; - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_LPFR_CFG, res); - - /* Loop filter capacitance values : c1 and c2 */ - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_LPFC1_CFG, 0x70); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_LPFC2_CFG, 0x15); - - div_s64_rem(vco_clk_rate, vco->ref_clk_rate, &rem); - if (rem) { - refclk_cfg = 0x1; - frac_n_mode = 1; - ref_doubler_en_b = 0; - } else { - refclk_cfg = 0x0; - frac_n_mode = 0; - ref_doubler_en_b = 1; - } - - pr_debug("refclk_cfg = %lld\n", refclk_cfg); - - ref_clk_to_pll = ((vco->ref_clk_rate * 2 * (refclk_cfg)) - + (ref_doubler_en_b * vco->ref_clk_rate)); - div_fbx1000 = div_s64((vco_clk_rate * 1000), ref_clk_to_pll); - - div_s64_rem(div_fbx1000, 1000, &rem); - frac_n_value = div_s64((rem * (1 << 16)), 1000); - gen_vco_clk = div_s64(div_fbx1000 * ref_clk_to_pll, 1000); - - pr_debug("ref_clk_to_pll = %lld\n", ref_clk_to_pll); - pr_debug("div_fb = %lld\n", div_fbx1000); - pr_debug("frac_n_value = %lld\n", frac_n_value); - - pr_debug("Generated VCO Clock: %lld\n", gen_vco_clk); - rem = 0; - if (frac_n_mode) { - sdm_cfg0 = (0x0 << 5); - sdm_cfg0 |= (0x0 & 0x3f); - sdm_cfg1 = (div_s64(div_fbx1000, 1000) & 0x3f) - 1; - sdm_cfg3 = div_s64_rem(frac_n_value, 256, &rem); - sdm_cfg2 = rem; - } else { - sdm_cfg0 = (0x1 << 5); - sdm_cfg0 |= (div_s64(div_fbx1000, 1000) & 0x3f) - 1; - sdm_cfg1 = (0x0 & 0x3f); - sdm_cfg2 = 0; - sdm_cfg3 = 0; - } - - pr_debug("sdm_cfg0=%lld\n", sdm_cfg0); - pr_debug("sdm_cfg1=%lld\n", sdm_cfg1); - pr_debug("sdm_cfg2=%lld\n", sdm_cfg2); - pr_debug("sdm_cfg3=%lld\n", sdm_cfg3); - - cal_cfg11 = div_s64_rem(gen_vco_clk, 256 * 1000000, &rem); - cal_cfg10 = rem / 1000000; - pr_debug("cal_cfg10=%lld, cal_cfg11=%lld\n", cal_cfg10, cal_cfg11); - - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CHGPUMP_CFG, 0x02); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG3, 0x2b); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG4, 0x66); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x0d); - - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1, (u32)(sdm_cfg1 & 0xff)); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2, (u32)(sdm_cfg2 & 0xff)); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3, (u32)(sdm_cfg3 & 0xff)); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG4, 0x00); - - /* Add hardware recommended delay for correct PLL configuration */ - if (dsi_pll_res->vco_delay) - udelay(dsi_pll_res->vco_delay); - - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_REFCLK_CFG, (u32)refclk_cfg); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_VCOLPF_CFG, 0x71); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0, (u32)sdm_cfg0); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG0, 0x12); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG6, 0x30); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG7, 0x00); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG8, 0x60); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG9, 0x00); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG10, (u32)(cal_cfg10 & 0xff)); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_CAL_CFG11, (u32)(cal_cfg11 & 0xff)); - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_EFUSE_CFG, 0x20); - - return 0; -} - -unsigned long vco_get_rate(struct clk *c) -{ - u32 sdm0, doubler, sdm_byp_div; - u64 vco_rate; - u32 sdm_dc_off, sdm_freq_seed, sdm2, sdm3; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - u64 ref_clk = vco->ref_clk_rate; - int rc; - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - if (is_gdsc_disabled(dsi_pll_res)) - return 0; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - /* Check to see if the ref clk doubler is enabled */ - doubler = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_REFCLK_CFG) & BIT(0); - ref_clk += (doubler * vco->ref_clk_rate); - - /* see if it is integer mode or sdm mode */ - sdm0 = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0); - if (sdm0 & BIT(6)) { - /* integer mode */ - sdm_byp_div = (MDSS_PLL_REG_R(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG0) & 0x3f) + 1; - vco_rate = ref_clk * sdm_byp_div; - } else { - /* sdm mode */ - sdm_dc_off = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG1) & 0xFF; - pr_debug("sdm_dc_off = %d\n", sdm_dc_off); - sdm2 = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG2) & 0xFF; - sdm3 = MDSS_PLL_REG_R(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_SDM_CFG3) & 0xFF; - sdm_freq_seed = (sdm3 << 8) | sdm2; - pr_debug("sdm_freq_seed = %d\n", sdm_freq_seed); - - vco_rate = (ref_clk * (sdm_dc_off + 1)) + - mult_frac(ref_clk, sdm_freq_seed, BIT(16)); - pr_debug("vco rate = %lld\n", vco_rate); - } - - pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate); - - mdss_pll_resource_enable(dsi_pll_res, false); - - return (unsigned long)vco_rate; -} - -static int dsi_pll_enable(struct clk *c) -{ - int i, rc; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return rc; - } - - /* Try all enable sequences until one succeeds */ - for (i = 0; i < vco->pll_en_seq_cnt; i++) { - rc = vco->pll_enable_seqs[i](dsi_pll_res); - pr_debug("DSI PLL %s after sequence #%d\n", - rc ? "unlocked" : "locked", i + 1); - if (!rc) - break; - } - - if (rc) { - mdss_pll_resource_enable(dsi_pll_res, false); - pr_err("DSI PLL failed to lock\n"); - } - dsi_pll_res->pll_on = true; - - return rc; -} - -static void dsi_pll_disable(struct clk *c) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - if (!dsi_pll_res->pll_on && - mdss_pll_resource_enable(dsi_pll_res, true)) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return; - } - - dsi_pll_res->handoff_resources = false; - - MDSS_PLL_REG_W(dsi_pll_res->pll_base, - DSI_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x00); - - mdss_pll_resource_enable(dsi_pll_res, false); - dsi_pll_res->pll_on = false; - - pr_debug("DSI PLL Disabled\n"); -} - -long vco_round_rate(struct clk *c, unsigned long rate) -{ - unsigned long rrate = rate; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - - if (rate < vco->min_rate) - rrate = vco->min_rate; - if (rate > vco->max_rate) - rrate = vco->max_rate; - - return rrate; -} - -enum handoff vco_handoff(struct clk *c) -{ - int rc; - enum handoff ret = HANDOFF_DISABLED_CLK; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - if (is_gdsc_disabled(dsi_pll_res)) - return HANDOFF_DISABLED_CLK; - - rc = mdss_pll_resource_enable(dsi_pll_res, true); - if (rc) { - pr_err("Failed to enable mdss dsi pll resources\n"); - return ret; - } - - if (dsi_pll_lock_status(dsi_pll_res)) { - dsi_pll_res->handoff_resources = true; - dsi_pll_res->pll_on = true; - c->rate = vco_get_rate(c); - ret = HANDOFF_ENABLED_CLK; - } else { - mdss_pll_resource_enable(dsi_pll_res, false); - } - - return ret; -} - -int vco_prepare(struct clk *c) -{ - int rc = 0; - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - if (!dsi_pll_res) { - pr_err("Dsi pll resources are not available\n"); - return -EINVAL; - } - - if ((dsi_pll_res->vco_cached_rate != 0) - && (dsi_pll_res->vco_cached_rate == c->rate)) { - rc = c->ops->set_rate(c, dsi_pll_res->vco_cached_rate); - if (rc) { - pr_err("vco_set_rate failed. rc=%d\n", rc); - goto error; - } - } - - rc = dsi_pll_enable(c); - -error: - return rc; -} - -void vco_unprepare(struct clk *c) -{ - struct dsi_pll_vco_clk *vco = to_vco_clk(c); - struct mdss_pll_resources *dsi_pll_res = vco->priv; - - if (!dsi_pll_res) { - pr_err("Dsi pll resources are not available\n"); - return; - } - - dsi_pll_res->vco_cached_rate = c->rate; - dsi_pll_disable(c); -} - diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll.h b/drivers/clk/qcom/mdss/mdss-dsi-pll.h deleted file mode 100644 index 398048ef8bd967e5d76c2de58a405df155039d65..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll.h +++ /dev/null @@ -1,52 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. - */ - -#ifndef __MDSS_DSI_PLL_H -#define __MDSS_DSI_PLL_H - -#include -#include "mdss-pll.h" -#define MAX_DSI_PLL_EN_SEQS 10 - -/* Register offsets for 20nm PHY PLL */ -#define MMSS_DSI_PHY_PLL_PLL_CNTRL (0x0014) -#define MMSS_DSI_PHY_PLL_PLL_BKG_KVCO_CAL_EN (0x002C) -#define MMSS_DSI_PHY_PLL_PLLLOCK_CMP_EN (0x009C) - -struct lpfr_cfg { - unsigned long vco_rate; - u32 r; -}; - -struct dsi_pll_vco_clk { - struct clk_hw hw; - unsigned long ref_clk_rate; - unsigned long min_rate; - unsigned long max_rate; - u32 pll_en_seq_cnt; - struct lpfr_cfg *lpfr_lut; - u32 lpfr_lut_size; - void *priv; - - int (*pll_enable_seqs[MAX_DSI_PLL_EN_SEQS]) - (struct mdss_pll_resources *dsi_pll_Res); -}; - -int dsi_pll_clock_register_10nm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res); - -int dsi_pll_clock_register_7nm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res); -int dsi_pll_clock_register_28lpm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res); - -static inline struct dsi_pll_vco_clk *to_vco_clk_hw(struct clk_hw *hw) -{ - return container_of(hw, struct dsi_pll_vco_clk, hw); -} - -int dsi_pll_clock_register_14nm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res); -#endif diff --git a/drivers/clk/qcom/mdss/mdss-edp-pll-28hpm.c b/drivers/clk/qcom/mdss/mdss-edp-pll-28hpm.c deleted file mode 100644 index cc148ed2e8ff286dc37c3222b41290685c81bb2e..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-edp-pll-28hpm.c +++ /dev/null @@ -1,580 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "mdss-pll.h" -#include "mdss-edp-pll.h" - -#define EDP_PHY_PLL_UNIPHY_PLL_REFCLK_CFG (0x0) -#define EDP_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG (0x0004) -#define EDP_PHY_PLL_UNIPHY_PLL_VCOLPF_CFG (0x000C) -#define EDP_PHY_PLL_UNIPHY_PLL_GLB_CFG (0x0020) -#define EDP_PHY_PLL_UNIPHY_PLL_POSTDIV2_CFG (0x0024) -#define EDP_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG (0x0028) -#define EDP_PHY_PLL_UNIPHY_PLL_SDM_CFG0 (0x0038) -#define EDP_PHY_PLL_UNIPHY_PLL_SDM_CFG1 (0x003C) -#define EDP_PHY_PLL_UNIPHY_PLL_SDM_CFG2 (0x0040) -#define EDP_PHY_PLL_UNIPHY_PLL_SDM_CFG3 (0x0044) -#define EDP_PHY_PLL_UNIPHY_PLL_SDM_CFG4 (0x0048) -#define EDP_PHY_PLL_UNIPHY_PLL_SSC_CFG0 (0x004C) -#define EDP_PHY_PLL_UNIPHY_PLL_SSC_CFG1 (0x0050) -#define EDP_PHY_PLL_UNIPHY_PLL_SSC_CFG2 (0x0054) -#define EDP_PHY_PLL_UNIPHY_PLL_SSC_CFG3 (0x0058) -#define EDP_PHY_PLL_UNIPHY_PLL_LKDET_CFG2 (0x0064) -#define EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG0 (0x006C) -#define EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG2 (0x0074) -#define EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG6 (0x0084) -#define EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG7 (0x0088) -#define EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG8 (0x008C) -#define EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG9 (0x0090) -#define EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG10 (0x0094) -#define EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG11 (0x0098) -#define EDP_PHY_PLL_UNIPHY_PLL_LKDET_CFG0 (0x005C) -#define EDP_PHY_PLL_UNIPHY_PLL_LKDET_CFG1 (0x0060) - -#define EDP_PLL_POLL_DELAY_US 50 -#define EDP_PLL_POLL_TIMEOUT_US 500 - -static const struct clk_ops edp_mainlink_clk_src_ops; -static struct clk_div_ops fixed_5div_ops; /* null ops */ -static const struct clk_ops edp_pixel_clk_ops; - -static inline struct edp_pll_vco_clk *to_edp_vco_clk(struct clk *clk) -{ - return container_of(clk, struct edp_pll_vco_clk, c); -} - -int edp_div_prepare(struct clk *c) -{ - struct div_clk *div = to_div_clk(c); - /* Restore the divider's value */ - return div->ops->set_div(div, div->data.div); -} - -static int edp_vco_set_rate(struct clk *c, unsigned long vco_rate) -{ - struct edp_pll_vco_clk *vco = to_edp_vco_clk(c); - struct mdss_pll_resources *edp_pll_res = vco->priv; - int rc; - - pr_debug("vco_rate=%d\n", (int)vco_rate); - - rc = mdss_pll_resource_enable(edp_pll_res, true); - if (rc) { - pr_err("failed to enable edp pll res rc=%d\n", rc); - rc = -EINVAL; - } - - if (vco_rate == 810000000) { - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_VCOLPF_CFG, 0x18); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x0d); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_REFCLK_CFG, 0x00); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_SDM_CFG0, 0x36); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_SDM_CFG1, 0x69); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_SDM_CFG2, 0xff); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_SDM_CFG3, 0x2f); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_SDM_CFG4, 0x00); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_SSC_CFG0, 0x80); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_SSC_CFG1, 0x00); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_SSC_CFG2, 0x00); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_SSC_CFG3, 0x00); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG0, 0x12); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG2, 0x01); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG6, 0x5a); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG7, 0x0); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG8, 0x60); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG9, 0x0); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG10, 0x2a); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG11, 0x3); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_LKDET_CFG0, 0x10); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_LKDET_CFG1, 0x1a); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG, 0x00); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG, 0x00); - } else if (vco_rate == 1350000000) { - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x0d); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_REFCLK_CFG, 0x01); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_SDM_CFG0, 0x36); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_SDM_CFG1, 0x62); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_SDM_CFG2, 0x00); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_SDM_CFG3, 0x28); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_SDM_CFG4, 0x00); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_SSC_CFG0, 0x80); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_SSC_CFG1, 0x00); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_SSC_CFG2, 0x00); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_SSC_CFG3, 0x00); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG0, 0x12); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG2, 0x01); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG6, 0x5a); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG7, 0x0); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG8, 0x60); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG9, 0x0); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG10, 0x46); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_CAL_CFG11, 0x5); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_LKDET_CFG0, 0x10); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_LKDET_CFG1, 0x1a); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_POSTDIV1_CFG, 0x00); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_POSTDIV3_CFG, 0x00); - } else { - pr_err("rate=%d is NOT supported\n", (int)vco_rate); - vco_rate = 0; - rc = -EINVAL; - } - - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01); - udelay(100); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05); - udelay(100); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x07); - udelay(100); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f); - udelay(100); - mdss_pll_resource_enable(edp_pll_res, false); - - vco->rate = vco_rate; - - return rc; -} - -static int edp_pll_ready_poll(struct mdss_pll_resources *edp_pll_res) -{ - int cnt; - u32 status; - - cnt = 100; - while (cnt--) { - udelay(100); - status = MDSS_PLL_REG_R(edp_pll_res->pll_base, 0xc0); - status &= 0x01; - if (status) - break; - } - pr_debug("cnt=%d status=%d\n", cnt, (int)status); - - if (status) - return 1; - - return 0; -} - -static int edp_vco_enable(struct clk *c) -{ - int i, ready; - int rc; - struct edp_pll_vco_clk *vco = to_edp_vco_clk(c); - struct mdss_pll_resources *edp_pll_res = vco->priv; - - rc = mdss_pll_resource_enable(edp_pll_res, true); - if (rc) { - pr_err("edp pll resources not available\n"); - return rc; - } - - for (i = 0; i < 3; i++) { - ready = edp_pll_ready_poll(edp_pll_res); - if (ready) - break; - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01); - udelay(100); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05); - udelay(100); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x07); - udelay(100); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f); - udelay(100); - } - - if (ready) { - pr_debug("EDP PLL lock success\n"); - edp_pll_res->pll_on = true; - rc = 0; - } else { - pr_err("EDP PLL failed to lock\n"); - mdss_pll_resource_enable(edp_pll_res, false); - rc = -EINVAL; - } - - return rc; -} - -static void edp_vco_disable(struct clk *c) -{ - struct edp_pll_vco_clk *vco = to_edp_vco_clk(c); - struct mdss_pll_resources *edp_pll_res = vco->priv; - - if (!edp_pll_res) { - pr_err("Invalid input parameter\n"); - return; - } - - if (!edp_pll_res->pll_on && - mdss_pll_resource_enable(edp_pll_res, true)) { - pr_err("edp pll resources not available\n"); - return; - } - - MDSS_PLL_REG_W(edp_pll_res->pll_base, 0x20, 0x00); - - edp_pll_res->handoff_resources = false; - edp_pll_res->pll_on = false; - - mdss_pll_resource_enable(edp_pll_res, false); - - pr_debug("EDP PLL Disabled\n"); -} - -static unsigned long edp_vco_get_rate(struct clk *c) -{ - struct edp_pll_vco_clk *vco = to_edp_vco_clk(c); - struct mdss_pll_resources *edp_pll_res = vco->priv; - u32 pll_status, div2; - int rc; - - if (is_gdsc_disabled(edp_pll_res)) - return 0; - - rc = mdss_pll_resource_enable(edp_pll_res, true); - if (rc) { - pr_err("edp pll resources not available\n"); - return rc; - } - - if (vco->rate == 0) { - pll_status = MDSS_PLL_REG_R(edp_pll_res->pll_base, 0xc0); - if (pll_status & 0x01) { - div2 = MDSS_PLL_REG_R(edp_pll_res->pll_base, 0x24); - if (div2 & 0x01) - vco->rate = 1350000000; - else - vco->rate = 810000000; - } - } - mdss_pll_resource_enable(edp_pll_res, false); - - pr_debug("rate=%d\n", (int)vco->rate); - - return vco->rate; -} - -static long edp_vco_round_rate(struct clk *c, unsigned long rate) -{ - struct edp_pll_vco_clk *vco = to_edp_vco_clk(c); - unsigned long rrate = -ENOENT; - unsigned long *lp; - - lp = vco->rate_list; - while (*lp) { - rrate = *lp; - if (rate <= rrate) - break; - lp++; - } - - pr_debug("rrate=%d\n", (int)rrate); - - return rrate; -} - -static int edp_vco_prepare(struct clk *c) -{ - struct edp_pll_vco_clk *vco = to_edp_vco_clk(c); - - pr_debug("rate=%d\n", (int)vco->rate); - - return edp_vco_set_rate(c, vco->rate); -} - -static void edp_vco_unprepare(struct clk *c) -{ - struct edp_pll_vco_clk *vco = to_edp_vco_clk(c); - - pr_debug("rate=%d\n", (int)vco->rate); - - edp_vco_disable(c); -} - -static int edp_pll_lock_status(struct mdss_pll_resources *edp_pll_res) -{ - u32 status; - int pll_locked = 0; - int rc; - - rc = mdss_pll_resource_enable(edp_pll_res, true); - if (rc) { - pr_err("edp pll resources not available\n"); - return rc; - } - - /* poll for PLL ready status */ - if (readl_poll_timeout_atomic((edp_pll_res->pll_base + 0xc0), - status, ((status & BIT(0)) == 1), - EDP_PLL_POLL_DELAY_US, - EDP_PLL_POLL_TIMEOUT_US)) { - pr_debug("EDP PLL status=%x failed to Lock\n", status); - pll_locked = 0; - } else { - pll_locked = 1; - } - mdss_pll_resource_enable(edp_pll_res, false); - - return pll_locked; -} - -static enum handoff edp_vco_handoff(struct clk *c) -{ - enum handoff ret = HANDOFF_DISABLED_CLK; - struct edp_pll_vco_clk *vco = to_edp_vco_clk(c); - struct mdss_pll_resources *edp_pll_res = vco->priv; - - if (is_gdsc_disabled(edp_pll_res)) - return HANDOFF_DISABLED_CLK; - - if (mdss_pll_resource_enable(edp_pll_res, true)) { - pr_err("edp pll resources not available\n"); - return ret; - } - - edp_pll_res->handoff_resources = true; - - if (edp_pll_lock_status(edp_pll_res)) { - c->rate = edp_vco_get_rate(c); - edp_pll_res->pll_on = true; - ret = HANDOFF_ENABLED_CLK; - } else { - edp_pll_res->handoff_resources = false; - mdss_pll_resource_enable(edp_pll_res, false); - } - - pr_debug("done, ret=%d\n", ret); - return ret; -} - -static unsigned long edp_vco_rate_list[] = { - 810000000, 1350000000, 0}; - -struct const clk_ops edp_vco_clk_ops = { - .enable = edp_vco_enable, - .set_rate = edp_vco_set_rate, - .get_rate = edp_vco_get_rate, - .round_rate = edp_vco_round_rate, - .prepare = edp_vco_prepare, - .unprepare = edp_vco_unprepare, - .handoff = edp_vco_handoff, -}; - -struct edp_pll_vco_clk edp_vco_clk = { - .ref_clk_rate = 19200000, - .rate = 0, - .rate_list = edp_vco_rate_list, - .c = { - .dbg_name = "edp_vco_clk", - .ops = &edp_vco_clk_ops, - CLK_INIT(edp_vco_clk.c), - }, -}; - -static unsigned long edp_mainlink_get_rate(struct clk *c) -{ - struct div_clk *mclk = to_div_clk(c); - struct clk *pclk; - unsigned long rate = 0; - - pclk = clk_get_parent(c); - - if (pclk && pclk->ops->get_rate) { - rate = pclk->ops->get_rate(pclk); - rate /= mclk->data.div; - } - - pr_debug("rate=%d div=%d\n", (int)rate, mclk->data.div); - - return rate; -} - - -struct div_clk edp_mainlink_clk_src = { - .ops = &fixed_5div_ops, - .data = { - .div = 5, - .min_div = 5, - .max_div = 5, - }, - .c = { - .parent = &edp_vco_clk.c, - .dbg_name = "edp_mainlink_clk_src", - .ops = &edp_mainlink_clk_src_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(edp_mainlink_clk_src.c), - } -}; - -/* - * this rate is from pll to clock controller - * output from pll to CC has two possibilities - * 1: if mainlink rate is 270M, then 675M - * 2: if mainlink rate is 162M, then 810M - */ -static int edp_pixel_set_div(struct div_clk *clk, int div) -{ - int rc; - struct mdss_pll_resources *edp_pll_res = clk->priv; - - rc = mdss_pll_resource_enable(edp_pll_res, true); - if (rc) { - pr_err("edp pll resources not available\n"); - return rc; - } - - pr_debug("div=%d\n", div); - MDSS_PLL_REG_W(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_POSTDIV2_CFG, (div - 1)); - mdss_pll_resource_enable(edp_pll_res, false); - - return 0; -} - -static int edp_pixel_get_div(struct div_clk *clk) -{ - int div = 0; - int rc; - struct mdss_pll_resources *edp_pll_res = clk->priv; - - if (is_gdsc_disabled(edp_pll_res)) - return 0; - - rc = mdss_pll_resource_enable(edp_pll_res, true); - if (rc) { - pr_err("edp pll resources not available\n"); - return rc; - } - - div = MDSS_PLL_REG_R(edp_pll_res->pll_base, - EDP_PHY_PLL_UNIPHY_PLL_POSTDIV2_CFG); - mdss_pll_resource_enable(edp_pll_res, false); - div &= 0x01; - pr_debug("div=%d\n", div); - return div + 1; -} - -static struct clk_div_ops edp_pixel_ops = { - .set_div = edp_pixel_set_div, - .get_div = edp_pixel_get_div, -}; - -struct div_clk edp_pixel_clk_src = { - .data = { - .max_div = 2, - .min_div = 1, - }, - .ops = &edp_pixel_ops, - .c = { - .parent = &edp_vco_clk.c, - .dbg_name = "edp_pixel_clk_src", - .ops = &edp_pixel_clk_ops, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(edp_pixel_clk_src.c), - }, -}; - -static struct clk_lookup mdss_edp_pllcc_8974[] = { - CLK_LOOKUP("edp_pixel_src", edp_pixel_clk_src.c, - "fd8c0000.qcom,mmsscc-mdss"), - CLK_LOOKUP("edp_mainlink_src", edp_mainlink_clk_src.c, - "fd8c0000.qcom,mmsscc-mdss"), -}; - -int edp_pll_clock_register(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int rc = -ENOTSUPP; - - /* Set client data to div and vco clocks */ - edp_pixel_clk_src.priv = pll_res; - edp_mainlink_clk_src.priv = pll_res; - edp_vco_clk.priv = pll_res; - - /* Set clock operation for mainlink and pixel clock */ - edp_mainlink_clk_src_ops = clk_ops_div; - edp_mainlink_clk_src_ops.get_parent = clk_get_parent; - edp_mainlink_clk_src_ops.get_rate = edp_mainlink_get_rate; - - edp_pixel_clk_ops = clk_ops_slave_div; - edp_pixel_clk_ops.prepare = edp_div_prepare; - - rc = of_msm_clock_register(pdev->dev.of_node, mdss_edp_pllcc_8974, - ARRAY_SIZE(mdss_edp_pllcc_8974)); - if (rc) { - pr_err("Clock register failed rc=%d\n", rc); - rc = -EPROBE_DEFER; - } - - return rc; -} diff --git a/drivers/clk/qcom/mdss/mdss-hdmi-pll-20nm.c b/drivers/clk/qcom/mdss/mdss-hdmi-pll-20nm.c deleted file mode 100644 index ff21be6d31dc5e33cb411168674971e2c4e24f45..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-hdmi-pll-20nm.c +++ /dev/null @@ -1,970 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mdss-pll.h" -#include "mdss-hdmi-pll.h" - -/* hdmi phy registers */ - -#define HDMI_PHY_CMD_SIZE 68 -#define HDMI_PHY_CLK_SIZE 97 - -/* Set to 1 for auto KVCO cal; set to 0 for fixed value */ -#define HDMI_PHY_AUTO_KVCO_CAL 1 - -/* PLL REGISTERS */ -#define QSERDES_COM_SYS_CLK_CTRL (0x000) -#define QSERDES_COM_PLL_VCOTAIL_EN (0x004) -#define QSERDES_COM_CMN_MODE (0x008) -#define QSERDES_COM_IE_TRIM (0x00C) -#define QSERDES_COM_IP_TRIM (0x010) -#define QSERDES_COM_PLL_CNTRL (0x014) -#define QSERDES_COM_PLL_PHSEL_CONTROL (0x018) -#define QSERDES_COM_IPTAT_TRIM_VCCA_TX_SEL (0x01C) -#define QSERDES_COM_PLL_PHSEL_DC (0x020) -#define QSERDES_COM_PLL_IP_SETI (0x024) -#define QSERDES_COM_CORE_CLK_IN_SYNC_SEL (0x028) -#define QSERDES_COM_PLL_BKG_KVCO_CAL_EN (0x02C) -#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN (0x030) -#define QSERDES_COM_PLL_CP_SETI (0x034) -#define QSERDES_COM_PLL_IP_SETP (0x038) -#define QSERDES_COM_PLL_CP_SETP (0x03C) -#define QSERDES_COM_ATB_SEL1 (0x040) -#define QSERDES_COM_ATB_SEL2 (0x044) -#define QSERDES_COM_SYSCLK_EN_SEL_TXBAND (0x048) -#define QSERDES_COM_RESETSM_CNTRL (0x04C) -#define QSERDES_COM_RESETSM_CNTRL2 (0x050) -#define QSERDES_COM_RESETSM_CNTRL3 (0x054) -#define QSERDES_COM_RESETSM_PLL_CAL_COUNT1 (0x058) -#define QSERDES_COM_RESETSM_PLL_CAL_COUNT2 (0x05C) -#define QSERDES_COM_DIV_REF1 (0x060) -#define QSERDES_COM_DIV_REF2 (0x064) -#define QSERDES_COM_KVCO_COUNT1 (0x068) -#define QSERDES_COM_KVCO_COUNT2 (0x06C) -#define QSERDES_COM_KVCO_CAL_CNTRL (0x070) -#define QSERDES_COM_KVCO_CODE (0x074) -#define QSERDES_COM_VREF_CFG1 (0x078) -#define QSERDES_COM_VREF_CFG2 (0x07C) -#define QSERDES_COM_VREF_CFG3 (0x080) -#define QSERDES_COM_VREF_CFG4 (0x084) -#define QSERDES_COM_VREF_CFG5 (0x088) -#define QSERDES_COM_VREF_CFG6 (0x08C) -#define QSERDES_COM_PLLLOCK_CMP1 (0x090) -#define QSERDES_COM_PLLLOCK_CMP2 (0x094) -#define QSERDES_COM_PLLLOCK_CMP3 (0x098) -#define QSERDES_COM_PLLLOCK_CMP_EN (0x09C) -#define QSERDES_COM_BGTC (0x0A0) -#define QSERDES_COM_PLL_TEST_UPDN (0x0A4) -#define QSERDES_COM_PLL_VCO_TUNE (0x0A8) -#define QSERDES_COM_DEC_START1 (0x0AC) -#define QSERDES_COM_PLL_AMP_OS (0x0B0) -#define QSERDES_COM_SSC_EN_CENTER (0x0B4) -#define QSERDES_COM_SSC_ADJ_PER1 (0x0B8) -#define QSERDES_COM_SSC_ADJ_PER2 (0x0BC) -#define QSERDES_COM_SSC_PER1 (0x0C0) -#define QSERDES_COM_SSC_PER2 (0x0C4) -#define QSERDES_COM_SSC_STEP_SIZE1 (0x0C8) -#define QSERDES_COM_SSC_STEP_SIZE2 (0x0CC) -#define QSERDES_COM_RES_CODE_UP (0x0D0) -#define QSERDES_COM_RES_CODE_DN (0x0D4) -#define QSERDES_COM_RES_CODE_UP_OFFSET (0x0D8) -#define QSERDES_COM_RES_CODE_DN_OFFSET (0x0DC) -#define QSERDES_COM_RES_CODE_START_SEG1 (0x0E0) -#define QSERDES_COM_RES_CODE_START_SEG2 (0x0E4) -#define QSERDES_COM_RES_CODE_CAL_CSR (0x0E8) -#define QSERDES_COM_RES_CODE (0x0EC) -#define QSERDES_COM_RES_TRIM_CONTROL (0x0F0) -#define QSERDES_COM_RES_TRIM_CONTROL2 (0x0F4) -#define QSERDES_COM_RES_TRIM_EN_VCOCALDONE (0x0F8) -#define QSERDES_COM_FAUX_EN (0x0FC) -#define QSERDES_COM_DIV_FRAC_START1 (0x100) -#define QSERDES_COM_DIV_FRAC_START2 (0x104) -#define QSERDES_COM_DIV_FRAC_START3 (0x108) -#define QSERDES_COM_DEC_START2 (0x10C) -#define QSERDES_COM_PLL_RXTXEPCLK_EN (0x110) -#define QSERDES_COM_PLL_CRCTRL (0x114) -#define QSERDES_COM_PLL_CLKEPDIV (0x118) -#define QSERDES_COM_PLL_FREQUPDATE (0x11C) -#define QSERDES_COM_PLL_BKGCAL_TRIM_UP (0x120) -#define QSERDES_COM_PLL_BKGCAL_TRIM_DN (0x124) -#define QSERDES_COM_PLL_BKGCAL_TRIM_MUX (0x128) -#define QSERDES_COM_PLL_BKGCAL_VREF_CFG (0x12C) -#define QSERDES_COM_PLL_BKGCAL_DIV_REF1 (0x130) -#define QSERDES_COM_PLL_BKGCAL_DIV_REF2 (0x134) -#define QSERDES_COM_MUXADDR (0x138) -#define QSERDES_COM_LOW_POWER_RO_CONTROL (0x13C) -#define QSERDES_COM_POST_DIVIDER_CONTROL (0x140) -#define QSERDES_COM_HR_OCLK2_DIVIDER (0x144) -#define QSERDES_COM_HR_OCLK3_DIVIDER (0x148) -#define QSERDES_COM_PLL_VCO_HIGH (0x14C) -#define QSERDES_COM_RESET_SM (0x150) -#define QSERDES_COM_MUXVAL (0x154) -#define QSERDES_COM_CORE_RES_CODE_DN (0x158) -#define QSERDES_COM_CORE_RES_CODE_UP (0x15C) -#define QSERDES_COM_CORE_VCO_TUNE (0x160) -#define QSERDES_COM_CORE_VCO_TAIL (0x164) -#define QSERDES_COM_CORE_KVCO_CODE (0x168) - -/* Tx Channel 0 REGISTERS */ -#define QSERDES_TX_L0_BIST_MODE_LANENO (0x00) -#define QSERDES_TX_L0_CLKBUF_ENABLE (0x04) -#define QSERDES_TX_L0_TX_EMP_POST1_LVL (0x08) -#define QSERDES_TX_L0_TX_DRV_LVL (0x0C) -#define QSERDES_TX_L0_RESET_TSYNC_EN (0x10) -#define QSERDES_TX_L0_LPB_EN (0x14) -#define QSERDES_TX_L0_RES_CODE_UP (0x18) -#define QSERDES_TX_L0_RES_CODE_DN (0x1C) -#define QSERDES_TX_L0_PERL_LENGTH1 (0x20) -#define QSERDES_TX_L0_PERL_LENGTH2 (0x24) -#define QSERDES_TX_L0_SERDES_BYP_EN_OUT (0x28) -#define QSERDES_TX_L0_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN (0x2C) -#define QSERDES_TX_L0_PARRATE_REC_DETECT_IDLE_EN (0x30) -#define QSERDES_TX_L0_BIST_PATTERN1 (0x34) -#define QSERDES_TX_L0_BIST_PATTERN2 (0x38) -#define QSERDES_TX_L0_BIST_PATTERN3 (0x3C) -#define QSERDES_TX_L0_BIST_PATTERN4 (0x40) -#define QSERDES_TX_L0_BIST_PATTERN5 (0x44) -#define QSERDES_TX_L0_BIST_PATTERN6 (0x48) -#define QSERDES_TX_L0_BIST_PATTERN7 (0x4C) -#define QSERDES_TX_L0_BIST_PATTERN8 (0x50) -#define QSERDES_TX_L0_LANE_MODE (0x54) -#define QSERDES_TX_L0_IDAC_CAL_LANE_MODE (0x58) -#define QSERDES_TX_L0_IDAC_CAL_LANE_MODE_CONFIGURATION (0x5C) -#define QSERDES_TX_L0_ATB_SEL1 (0x60) -#define QSERDES_TX_L0_ATB_SEL2 (0x64) -#define QSERDES_TX_L0_RCV_DETECT_LVL (0x68) -#define QSERDES_TX_L0_PRBS_SEED1 (0x6C) -#define QSERDES_TX_L0_PRBS_SEED2 (0x70) -#define QSERDES_TX_L0_PRBS_SEED3 (0x74) -#define QSERDES_TX_L0_PRBS_SEED4 (0x78) -#define QSERDES_TX_L0_RESET_GEN (0x7C) -#define QSERDES_TX_L0_TRAN_DRVR_EMP_EN (0x80) -#define QSERDES_TX_L0_TX_INTERFACE_MODE (0x84) -#define QSERDES_TX_L0_PWM_CTRL (0x88) -#define QSERDES_TX_L0_PWM_DATA (0x8C) -#define QSERDES_TX_L0_PWM_ENC_DIV_CTRL (0x90) -#define QSERDES_TX_L0_VMODE_CTRL1 (0x94) -#define QSERDES_TX_L0_VMODE_CTRL2 (0x98) -#define QSERDES_TX_L0_VMODE_CTRL3 (0x9C) -#define QSERDES_TX_L0_VMODE_CTRL4 (0xA0) -#define QSERDES_TX_L0_VMODE_CTRL5 (0xA4) -#define QSERDES_TX_L0_VMODE_CTRL6 (0xA8) -#define QSERDES_TX_L0_VMODE_CTRL7 (0xAC) -#define QSERDES_TX_L0_TX_ALOG_INTF_OBSV_CNTL (0xB0) -#define QSERDES_TX_L0_BIST_STATUS (0xB4) -#define QSERDES_TX_L0_BIST_ERROR_COUNT1 (0xB8) -#define QSERDES_TX_L0_BIST_ERROR_COUNT2 (0xBC) -#define QSERDES_TX_L0_TX_ALOG_INTF_OBSV (0xC0) -#define QSERDES_TX_L0_PWM_DEC_STATUS (0xC4) - -/* Tx Channel 1 REGISTERS */ -#define QSERDES_TX_L1_BIST_MODE_LANENO (0x00) -#define QSERDES_TX_L1_CLKBUF_ENABLE (0x04) -#define QSERDES_TX_L1_TX_EMP_POST1_LVL (0x08) -#define QSERDES_TX_L1_TX_DRV_LVL (0x0C) -#define QSERDES_TX_L1_RESET_TSYNC_EN (0x10) -#define QSERDES_TX_L1_LPB_EN (0x14) -#define QSERDES_TX_L1_RES_CODE_UP (0x18) -#define QSERDES_TX_L1_RES_CODE_DN (0x1C) -#define QSERDES_TX_L1_PERL_LENGTH1 (0x20) -#define QSERDES_TX_L1_PERL_LENGTH2 (0x24) -#define QSERDES_TX_L1_SERDES_BYP_EN_OUT (0x28) -#define QSERDES_TX_L1_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN (0x2C) -#define QSERDES_TX_L1_PARRATE_REC_DETECT_IDLE_EN (0x30) -#define QSERDES_TX_L1_BIST_PATTERN1 (0x34) -#define QSERDES_TX_L1_BIST_PATTERN2 (0x38) -#define QSERDES_TX_L1_BIST_PATTERN3 (0x3C) -#define QSERDES_TX_L1_BIST_PATTERN4 (0x40) -#define QSERDES_TX_L1_BIST_PATTERN5 (0x44) -#define QSERDES_TX_L1_BIST_PATTERN6 (0x48) -#define QSERDES_TX_L1_BIST_PATTERN7 (0x4C) -#define QSERDES_TX_L1_BIST_PATTERN8 (0x50) -#define QSERDES_TX_L1_LANE_MODE (0x54) -#define QSERDES_TX_L1_IDAC_CAL_LANE_MODE (0x58) -#define QSERDES_TX_L1_IDAC_CAL_LANE_MODE_CONFIGURATION (0x5C) -#define QSERDES_TX_L1_ATB_SEL1 (0x60) -#define QSERDES_TX_L1_ATB_SEL2 (0x64) -#define QSERDES_TX_L1_RCV_DETECT_LVL (0x68) -#define QSERDES_TX_L1_PRBS_SEED1 (0x6C) -#define QSERDES_TX_L1_PRBS_SEED2 (0x70) -#define QSERDES_TX_L1_PRBS_SEED3 (0x74) -#define QSERDES_TX_L1_PRBS_SEED4 (0x78) -#define QSERDES_TX_L1_RESET_GEN (0x7C) -#define QSERDES_TX_L1_TRAN_DRVR_EMP_EN (0x80) -#define QSERDES_TX_L1_TX_INTERFACE_MODE (0x84) -#define QSERDES_TX_L1_PWM_CTRL (0x88) -#define QSERDES_TX_L1_PWM_DATA (0x8C) -#define QSERDES_TX_L1_PWM_ENC_DIV_CTRL (0x90) -#define QSERDES_TX_L1_VMODE_CTRL1 (0x94) -#define QSERDES_TX_L1_VMODE_CTRL2 (0x98) -#define QSERDES_TX_L1_VMODE_CTRL3 (0x9C) -#define QSERDES_TX_L1_VMODE_CTRL4 (0xA0) -#define QSERDES_TX_L1_VMODE_CTRL5 (0xA4) -#define QSERDES_TX_L1_VMODE_CTRL6 (0xA8) -#define QSERDES_TX_L1_VMODE_CTRL7 (0xAC) -#define QSERDES_TX_L1_TX_ALOG_INTF_OBSV_CNTL (0xB0) -#define QSERDES_TX_L1_BIST_STATUS (0xB4) -#define QSERDES_TX_L1_BIST_ERROR_COUNT1 (0xB8) -#define QSERDES_TX_L1_BIST_ERROR_COUNT2 (0xBC) -#define QSERDES_TX_L1_TX_ALOG_INTF_OBSV (0xC0) -#define QSERDES_TX_L1_PWM_DEC_STATUS (0xC4) - -/* Tx Channel 2 REGISERS */ -#define QSERDES_TX_L2_BIST_MODE_LANENO (0x00) -#define QSERDES_TX_L2_CLKBUF_ENABLE (0x04) -#define QSERDES_TX_L2_TX_EMP_POST1_LVL (0x08) -#define QSERDES_TX_L2_TX_DRV_LVL (0x0C) -#define QSERDES_TX_L2_RESET_TSYNC_EN (0x10) -#define QSERDES_TX_L2_LPB_EN (0x14) -#define QSERDES_TX_L2_RES_CODE_UP (0x18) -#define QSERDES_TX_L2_RES_CODE_DN (0x1C) -#define QSERDES_TX_L2_PERL_LENGTH1 (0x20) -#define QSERDES_TX_L2_PERL_LENGTH2 (0x24) -#define QSERDES_TX_L2_SERDES_BYP_EN_OUT (0x28) -#define QSERDES_TX_L2_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN (0x2C) -#define QSERDES_TX_L2_PARRATE_REC_DETECT_IDLE_EN (0x30) -#define QSERDES_TX_L2_BIST_PATTERN1 (0x34) -#define QSERDES_TX_L2_BIST_PATTERN2 (0x38) -#define QSERDES_TX_L2_BIST_PATTERN3 (0x3C) -#define QSERDES_TX_L2_BIST_PATTERN4 (0x40) -#define QSERDES_TX_L2_BIST_PATTERN5 (0x44) -#define QSERDES_TX_L2_BIST_PATTERN6 (0x48) -#define QSERDES_TX_L2_BIST_PATTERN7 (0x4C) -#define QSERDES_TX_L2_BIST_PATTERN8 (0x50) -#define QSERDES_TX_L2_LANE_MODE (0x54) -#define QSERDES_TX_L2_IDAC_CAL_LANE_MODE (0x58) -#define QSERDES_TX_L2_IDAC_CAL_LANE_MODE_CONFIGURATION (0x5C) -#define QSERDES_TX_L2_ATB_SEL1 (0x60) -#define QSERDES_TX_L2_ATB_SEL2 (0x64) -#define QSERDES_TX_L2_RCV_DETECT_LVL (0x68) -#define QSERDES_TX_L2_PRBS_SEED1 (0x6C) -#define QSERDES_TX_L2_PRBS_SEED2 (0x70) -#define QSERDES_TX_L2_PRBS_SEED3 (0x74) -#define QSERDES_TX_L2_PRBS_SEED4 (0x78) -#define QSERDES_TX_L2_RESET_GEN (0x7C) -#define QSERDES_TX_L2_TRAN_DRVR_EMP_EN (0x80) -#define QSERDES_TX_L2_TX_INTERFACE_MODE (0x84) -#define QSERDES_TX_L2_PWM_CTRL (0x88) -#define QSERDES_TX_L2_PWM_DATA (0x8C) -#define QSERDES_TX_L2_PWM_ENC_DIV_CTRL (0x90) -#define QSERDES_TX_L2_VMODE_CTRL1 (0x94) -#define QSERDES_TX_L2_VMODE_CTRL2 (0x98) -#define QSERDES_TX_L2_VMODE_CTRL3 (0x9C) -#define QSERDES_TX_L2_VMODE_CTRL4 (0xA0) -#define QSERDES_TX_L2_VMODE_CTRL5 (0xA4) -#define QSERDES_TX_L2_VMODE_CTRL6 (0xA8) -#define QSERDES_TX_L2_VMODE_CTRL7 (0xAC) -#define QSERDES_TX_L2_TX_ALOG_INTF_OBSV_CNTL (0xB0) -#define QSERDES_TX_L2_BIST_STATUS (0xB4) -#define QSERDES_TX_L2_BIST_ERROR_COUNT1 (0xB8) -#define QSERDES_TX_L2_BIST_ERROR_COUNT2 (0xBC) -#define QSERDES_TX_L2_TX_ALOG_INTF_OBSV (0xC0) -#define QSERDES_TX_L2_PWM_DEC_STATUS (0xC4) - -/* Tx Channel 3 REGISERS */ -#define QSERDES_TX_L3_BIST_MODE_LANENO (0x00) -#define QSERDES_TX_L3_CLKBUF_ENABLE (0x04) -#define QSERDES_TX_L3_TX_EMP_POST1_LVL (0x08) -#define QSERDES_TX_L3_TX_DRV_LVL (0x0C) -#define QSERDES_TX_L3_RESET_TSYNC_EN (0x10) -#define QSERDES_TX_L3_LPB_EN (0x14) -#define QSERDES_TX_L3_RES_CODE_UP (0x18) -#define QSERDES_TX_L3_RES_CODE_DN (0x1C) -#define QSERDES_TX_L3_PERL_LENGTH1 (0x20) -#define QSERDES_TX_L3_PERL_LENGTH2 (0x24) -#define QSERDES_TX_L3_SERDES_BYP_EN_OUT (0x28) -#define QSERDES_TX_L3_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN (0x2C) -#define QSERDES_TX_L3_PARRATE_REC_DETECT_IDLE_EN (0x30) -#define QSERDES_TX_L3_BIST_PATTERN1 (0x34) -#define QSERDES_TX_L3_BIST_PATTERN2 (0x38) -#define QSERDES_TX_L3_BIST_PATTERN3 (0x3C) -#define QSERDES_TX_L3_BIST_PATTERN4 (0x40) -#define QSERDES_TX_L3_BIST_PATTERN5 (0x44) -#define QSERDES_TX_L3_BIST_PATTERN6 (0x48) -#define QSERDES_TX_L3_BIST_PATTERN7 (0x4C) -#define QSERDES_TX_L3_BIST_PATTERN8 (0x50) -#define QSERDES_TX_L3_LANE_MODE (0x54) -#define QSERDES_TX_L3_IDAC_CAL_LANE_MODE (0x58) -#define QSERDES_TX_L3_IDAC_CAL_LANE_MODE_CONFIGURATION (0x5C) -#define QSERDES_TX_L3_ATB_SEL1 (0x60) -#define QSERDES_TX_L3_ATB_SEL2 (0x64) -#define QSERDES_TX_L3_RCV_DETECT_LVL (0x68) -#define QSERDES_TX_L3_PRBS_SEED1 (0x6C) -#define QSERDES_TX_L3_PRBS_SEED2 (0x70) -#define QSERDES_TX_L3_PRBS_SEED3 (0x74) -#define QSERDES_TX_L3_PRBS_SEED4 (0x78) -#define QSERDES_TX_L3_RESET_GEN (0x7C) -#define QSERDES_TX_L3_TRAN_DRVR_EMP_EN (0x80) -#define QSERDES_TX_L3_TX_INTERFACE_MODE (0x84) -#define QSERDES_TX_L3_PWM_CTRL (0x88) -#define QSERDES_TX_L3_PWM_DATA (0x8C) -#define QSERDES_TX_L3_PWM_ENC_DIV_CTRL (0x90) -#define QSERDES_TX_L3_VMODE_CTRL1 (0x94) -#define QSERDES_TX_L3_VMODE_CTRL2 (0x98) -#define QSERDES_TX_L3_VMODE_CTRL3 (0x9C) -#define QSERDES_TX_L3_VMODE_CTRL4 (0xA0) -#define QSERDES_TX_L3_VMODE_CTRL5 (0xA4) -#define QSERDES_TX_L3_VMODE_CTRL6 (0xA8) -#define QSERDES_TX_L3_VMODE_CTRL7 (0xAC) -#define QSERDES_TX_L3_TX_ALOG_INTF_OBSV_CNTL (0xB0) -#define QSERDES_TX_L3_BIST_STATUS (0xB4) -#define QSERDES_TX_L3_BIST_ERROR_COUNT1 (0xB8) -#define QSERDES_TX_L3_BIST_ERROR_COUNT2 (0xBC) -#define QSERDES_TX_L3_TX_ALOG_INTF_OBSV (0xC0) -#define QSERDES_TX_L3_PWM_DEC_STATUS (0xC4) - -/* HDMI PHY REGISTERS */ -#define HDMI_PHY_CFG (0x00) -#define HDMI_PHY_PD_CTL (0x04) -#define HDMI_PHY_MODE (0x08) -#define HDMI_PHY_MISR_CLEAR (0x0C) -#define HDMI_PHY_TX0_TX1_BIST_CFG0 (0x10) -#define HDMI_PHY_TX0_TX1_BIST_CFG1 (0x14) -#define HDMI_PHY_TX0_TX1_PRBS_SEED_BYTE0 (0x18) -#define HDMI_PHY_TX0_TX1_PRBS_SEED_BYTE1 (0x1C) -#define HDMI_PHY_TX0_TX1_PRBS_SEED_BYTE2 (0x20) -#define HDMI_PHY_TX0_TX1_PRBS_SEED_BYTE3 (0x24) -#define HDMI_PHY_TX0_TX1_PRBS_POLY_BYTE0 (0x28) -#define HDMI_PHY_TX0_TX1_PRBS_POLY_BYTE1 (0x2C) -#define HDMI_PHY_TX0_TX1_PRBS_POLY_BYTE2 (0x30) -#define HDMI_PHY_TX0_TX1_PRBS_POLY_BYTE3 (0x34) -#define HDMI_PHY_TX2_TX3_BIST_CFG0 (0x38) -#define HDMI_PHY_TX2_TX3_BIST_CFG1 (0x3C) -#define HDMI_PHY_TX2_TX3_PRBS_SEED_BYTE0 (0x40) -#define HDMI_PHY_TX2_TX3_PRBS_SEED_BYTE1 (0x44) -#define HDMI_PHY_TX2_TX3_PRBS_SEED_BYTE2 (0x48) -#define HDMI_PHY_TX2_TX3_PRBS_SEED_BYTE3 (0x4C) -#define HDMI_PHY_TX2_TX3_PRBS_POLY_BYTE0 (0x50) -#define HDMI_PHY_TX2_TX3_PRBS_POLY_BYTE1 (0x54) -#define HDMI_PHY_TX2_TX3_PRBS_POLY_BYTE2 (0x58) -#define HDMI_PHY_TX2_TX3_PRBS_POLY_BYTE3 (0x5C) -#define HDMI_PHY_DEBUG_BUS_SEL (0x60) -#define HDMI_PHY_TXCAL_CFG0 (0x64) -#define HDMI_PHY_TXCAL_CFG1 (0x68) -#define HDMI_PHY_TX0_TX1_BIST_STATUS0 (0x6C) -#define HDMI_PHY_TX0_TX1_BIST_STATUS1 (0x70) -#define HDMI_PHY_TX0_TX1_BIST_STATUS2 (0x74) -#define HDMI_PHY_TX2_TX3_BIST_STATUS0 (0x78) -#define HDMI_PHY_TX2_TX3_BIST_STATUS1 (0x7C) -#define HDMI_PHY_TX2_TX3_BIST_STATUS2 (0x80) -#define HDMI_PHY_PRE_MISR_STATUS0 (0x84) -#define HDMI_PHY_PRE_MISR_STATUS1 (0x88) -#define HDMI_PHY_PRE_MISR_STATUS2 (0x8C) -#define HDMI_PHY_PRE_MISR_STATUS3 (0x90) -#define HDMI_PHY_POST_MISR_STATUS0 (0x94) -#define HDMI_PHY_POST_MISR_STATUS1 (0x98) -#define HDMI_PHY_POST_MISR_STATUS2 (0x9C) -#define HDMI_PHY_POST_MISR_STATUS3 (0xA0) -#define HDMI_PHY_STATUS (0xA4) -#define HDMI_PHY_MISC3_STATUS (0xA8) -#define HDMI_PHY_DEBUG_BUS0 (0xAC) -#define HDMI_PHY_DEBUG_BUS1 (0xB0) -#define HDMI_PHY_DEBUG_BUS2 (0xB4) -#define HDMI_PHY_DEBUG_BUS3 (0xB8) -#define HDMI_PHY_REVISION_ID0 (0xBC) -#define HDMI_PHY_REVISION_ID1 (0xC0) -#define HDMI_PHY_REVISION_ID2 (0xC4) -#define HDMI_PHY_REVISION_ID3 (0xC8) - -#define HDMI_PLL_POLL_DELAY_US 50 -#define HDMI_PLL_POLL_TIMEOUT_US 125000 -#define HDMI_PLL_REF_CLK_RATE 192ULL -#define HDMI_PLL_DIVISOR 10000000000ULL -#define HDMI_PLL_DIVISOR_32 100000U -#define HDMI_PLL_MIN_VCO_CLK 160000000ULL -#define HDMI_PLL_TMDS_MAX 800000000U - - -static int hdmi_20nm_pll_lock_status(struct mdss_pll_resources *io) -{ - u32 status; - int pll_locked = 0; - int phy_ready = 0; - int rc; - - rc = mdss_pll_resource_enable(io, true); - if (rc) { - pr_err("pll resource can't be enabled\n"); - return rc; - } - - /* Poll for C_READY and PHY READY */ - pr_debug("%s: Waiting for PHY Ready\n", __func__); - - /* poll for PLL ready status */ - if (!readl_poll_timeout_atomic( - (io->pll_base + QSERDES_COM_RESET_SM), - status, ((status & BIT(6)) == 1), - HDMI_PLL_POLL_DELAY_US, - HDMI_PLL_POLL_TIMEOUT_US)) { - pr_debug("%s: C READY\n", __func__); - pll_locked = 1; - } else { - pr_debug("%s: C READY TIMEOUT\n", __func__); - pll_locked = 0; - } - - /* poll for PHY ready status */ - if (pll_locked && !readl_poll_timeout_atomic( - (io->phy_base + HDMI_PHY_STATUS), - status, ((status & BIT(0)) == 1), - HDMI_PLL_POLL_DELAY_US, - HDMI_PLL_POLL_TIMEOUT_US)) { - pr_debug("%s: PHY READY\n", __func__); - phy_ready = 1; - } else { - pr_debug("%s: PHY READY TIMEOUT\n", __func__); - phy_ready = 0; - } - mdss_pll_resource_enable(io, false); - - return phy_ready; -} - -static inline struct hdmi_pll_vco_clk *to_hdmi_20nm_vco_clk(struct clk *clk) -{ - return container_of(clk, struct hdmi_pll_vco_clk, c); -} - -static inline u32 hdmi_20nm_phy_pll_vco_reg_val(struct hdmi_pll_cfg *pll_cfg, - u32 tmds_clk) -{ - u32 index = 0; - - while (pll_cfg[index].vco_rate < HDMI_PLL_TMDS_MAX && - pll_cfg[index].vco_rate < tmds_clk) - index++; - return pll_cfg[index].reg; -} - -static void hdmi_20nm_phy_pll_calc_settings(struct mdss_pll_resources *io, - struct hdmi_pll_vco_clk *vco, u32 vco_clk, u32 tmds_clk) -{ - u32 val = 0; - u64 dec_start_val, frac_start_val, pll_lock_cmp; - - /* Calculate decimal and fractional values */ - dec_start_val = 1000000UL * vco_clk; - do_div(dec_start_val, HDMI_PLL_REF_CLK_RATE); - do_div(dec_start_val, 2U); - frac_start_val = dec_start_val; - do_div(frac_start_val, HDMI_PLL_DIVISOR_32); - do_div(frac_start_val, HDMI_PLL_DIVISOR_32); - frac_start_val *= HDMI_PLL_DIVISOR; - frac_start_val = dec_start_val - frac_start_val; - frac_start_val *= (u64)(2 << 19); - do_div(frac_start_val, HDMI_PLL_DIVISOR_32); - do_div(frac_start_val, HDMI_PLL_DIVISOR_32); - pll_lock_cmp = dec_start_val; - do_div(pll_lock_cmp, 10U); - pll_lock_cmp *= 0x800; - do_div(pll_lock_cmp, HDMI_PLL_DIVISOR_32); - do_div(pll_lock_cmp, HDMI_PLL_DIVISOR_32); - pll_lock_cmp -= 1U; - do_div(dec_start_val, HDMI_PLL_DIVISOR_32); - do_div(dec_start_val, HDMI_PLL_DIVISOR_32); - - /* PLL loop bandwidth */ - val = hdmi_20nm_phy_pll_vco_reg_val(vco->ip_seti, tmds_clk); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_IP_SETI, val); - val = hdmi_20nm_phy_pll_vco_reg_val(vco->cp_seti, tmds_clk); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_CP_SETI, val); - val = hdmi_20nm_phy_pll_vco_reg_val(vco->cp_setp, tmds_clk); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_CP_SETP, val); - val = hdmi_20nm_phy_pll_vco_reg_val(vco->ip_setp, tmds_clk); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_IP_SETP, val); - val = hdmi_20nm_phy_pll_vco_reg_val(vco->crctrl, tmds_clk); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_CRCTRL, val); - - /* PLL calibration */ - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DIV_FRAC_START1, - 0x80 | (frac_start_val & 0x7F)); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DIV_FRAC_START2, - 0x80 | ((frac_start_val >> 7) & 0x7F)); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DIV_FRAC_START3, - 0x40 | ((frac_start_val >> 14) & 0x3F)); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DEC_START1, - 0x80 | (dec_start_val & 0x7F)); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DEC_START2, - 0x02 | (0x01 & (dec_start_val >> 7))); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLLLOCK_CMP1, - pll_lock_cmp & 0xFF); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLLLOCK_CMP2, - (pll_lock_cmp >> 8) & 0xFF); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLLLOCK_CMP3, - (pll_lock_cmp >> 16) & 0xFF); -} - -static u32 hdmi_20nm_phy_pll_set_clk_rate(struct clk *c, u32 tmds_clk) -{ - u32 tx_band = 0; - - struct hdmi_pll_vco_clk *vco = to_hdmi_20nm_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - u64 vco_clk = tmds_clk; - - while (vco_clk > 0 && vco_clk < HDMI_PLL_MIN_VCO_CLK) { - tx_band++; - vco_clk *= 2; - } - - /* Initially shut down PHY */ - pr_debug("%s: Disabling PHY\n", __func__); - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_PD_CTL, 0x0); - udelay(1000); - /* memory barrier */ - mb(); - - /* power-up and recommended common block settings */ - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_PD_CTL, 0x1F); - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x01); - udelay(1000); - /* memory barrier */ - mb(); - - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x07); - udelay(1000); - /* memory barrier */ - mb(); - - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x05); - udelay(1000); - /* memory barrier */ - mb(); - - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SYS_CLK_CTRL, 0x42); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_VCOTAIL_EN, 0x03); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_CMN_MODE, 0x00); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_IE_TRIM, 0x00); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_IP_TRIM, 0x00); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_CNTRL, 0x07); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_PHSEL_CONTROL, 0x04); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_IPTAT_TRIM_VCCA_TX_SEL, 0xA0); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_PHSEL_DC, 0x00); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_CORE_CLK_IN_SYNC_SEL, 0x00); - - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_BKG_KVCO_CAL_EN, 0x00); - - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x0F); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_ATB_SEL1, 0x01); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_ATB_SEL2, 0x01); - - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SYSCLK_EN_SEL_TXBAND, - 0x4A + (0x10 * tx_band)); - - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_VREF_CFG1, 0x00); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_VREF_CFG2, 0x00); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_BGTC, 0xFF); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_TEST_UPDN, 0x00); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_VCO_TUNE, 0x00); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_AMP_OS, 0x00); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SSC_EN_CENTER, 0x00); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RES_CODE_UP, 0x00); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RES_CODE_DN, 0x00); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_KVCO_CODE, - tmds_clk > 300000000 ? 0x3F : 0x00); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_KVCO_COUNT1, - tmds_clk > 300000000 ? 0x00 : 0x8A); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DIV_REF1, 0x00); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DIV_REF2, - tmds_clk > 300000000 ? 0x00 : 0x01); - - - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_KVCO_CAL_CNTRL, - tmds_clk > 300000000 ? 0x00 : 0x1F); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_VREF_CFG3, - tmds_clk > 300000000 ? 0x00 : 0x40); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_VREF_CFG4, 0x00); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_VREF_CFG5, 0x10); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RESETSM_CNTRL, - tmds_clk > 300000000 ? 0x80 : 0x00); - - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RES_CODE_CAL_CSR, 0x77); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RES_TRIM_EN_VCOCALDONE, 0x00); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_RXTXEPCLK_EN, 0x0C); - - hdmi_20nm_phy_pll_calc_settings(io, vco, vco_clk, tmds_clk); - - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLLLOCK_CMP_EN, 0x11); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_CNTRL, 0x07); - - /* Resistor calibration linear search */ - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RES_CODE_START_SEG1, 0x60); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RES_CODE_START_SEG2, 0x60); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RES_TRIM_CONTROL, 0x01); - - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RESETSM_CNTRL2, 0x07); - - udelay(1000); - /* memory barrier */ - mb(); - - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_MODE, tx_band); - - /* TX lanes (transceivers) power-up sequence */ - MDSS_PLL_REG_W(io->pll_base + 0x400, QSERDES_TX_L0_CLKBUF_ENABLE, 0x03); - MDSS_PLL_REG_W(io->pll_base + 0x600, QSERDES_TX_L1_CLKBUF_ENABLE, 0x03); - MDSS_PLL_REG_W(io->pll_base + 0x800, QSERDES_TX_L2_CLKBUF_ENABLE, 0x03); - MDSS_PLL_REG_W(io->pll_base + 0xA00, QSERDES_TX_L3_CLKBUF_ENABLE, 0x03); - - MDSS_PLL_REG_W(io->pll_base + 0x400, - QSERDES_TX_L0_TRAN_DRVR_EMP_EN, 0x03); - MDSS_PLL_REG_W(io->pll_base + 0x600, - QSERDES_TX_L1_TRAN_DRVR_EMP_EN, 0x03); - MDSS_PLL_REG_W(io->pll_base + 0x800, - QSERDES_TX_L2_TRAN_DRVR_EMP_EN, 0x03); - MDSS_PLL_REG_W(io->pll_base + 0xA00, - QSERDES_TX_L3_TRAN_DRVR_EMP_EN, 0x03); - - MDSS_PLL_REG_W(io->pll_base + 0x400, - QSERDES_TX_L0_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x6F); - MDSS_PLL_REG_W(io->pll_base + 0x600, - QSERDES_TX_L1_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x6F); - MDSS_PLL_REG_W(io->pll_base + 0x800, - QSERDES_TX_L2_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x6F); - MDSS_PLL_REG_W(io->pll_base + 0xA00, - QSERDES_TX_L3_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x6F); - - MDSS_PLL_REG_W(io->pll_base + 0x400, - QSERDES_TX_L0_TX_EMP_POST1_LVL, 0x0000002F); - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_TXCAL_CFG0, 0x000000AF); - - MDSS_PLL_REG_W(io->pll_base + 0x400, QSERDES_TX_L0_VMODE_CTRL1, 0x08); - MDSS_PLL_REG_W(io->pll_base + 0x800, QSERDES_TX_L2_VMODE_CTRL1, 0x09); - MDSS_PLL_REG_W(io->pll_base + 0x400, QSERDES_TX_L0_VMODE_CTRL5, 0xA0); - MDSS_PLL_REG_W(io->pll_base + 0x400, QSERDES_TX_L0_VMODE_CTRL6, 0x01); - MDSS_PLL_REG_W(io->pll_base + 0x800, QSERDES_TX_L2_VMODE_CTRL5, 0xA0); - MDSS_PLL_REG_W(io->pll_base + 0x800, QSERDES_TX_L2_VMODE_CTRL6, 0x01); - - MDSS_PLL_REG_W(io->pll_base + 0x400, - QSERDES_TX_L0_PARRATE_REC_DETECT_IDLE_EN, 0x40); - MDSS_PLL_REG_W(io->pll_base + 0x400, - QSERDES_TX_L0_TX_INTERFACE_MODE, 0x00); - MDSS_PLL_REG_W(io->pll_base + 0x600, - QSERDES_TX_L1_PARRATE_REC_DETECT_IDLE_EN, 0x40); - MDSS_PLL_REG_W(io->pll_base + 0x600, - QSERDES_TX_L1_TX_INTERFACE_MODE, 0x00); - MDSS_PLL_REG_W(io->pll_base + 0x800, - QSERDES_TX_L2_PARRATE_REC_DETECT_IDLE_EN, 0x40); - MDSS_PLL_REG_W(io->pll_base + 0x800, - QSERDES_TX_L2_TX_INTERFACE_MODE, 0x00); - MDSS_PLL_REG_W(io->pll_base + 0xA00, - QSERDES_TX_L3_PARRATE_REC_DETECT_IDLE_EN, 0x40); - MDSS_PLL_REG_W(io->pll_base + 0xA00, - QSERDES_TX_L3_TX_INTERFACE_MODE, 0x00); - - return 0; -} - -static int hdmi_20nm_vco_enable(struct clk *c) -{ - u32 ready_poll; - u32 time_out_loop; - /* Hardware recommended timeout iterator */ - u32 time_out_max = 50000; - - struct hdmi_pll_vco_clk *vco = to_hdmi_20nm_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x00000000); - udelay(100); - /* memory barrier */ - mb(); - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x00000003); - udelay(100); - /* memory barrier */ - mb(); - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x00000009); - udelay(100); - /* memory barrier */ - mb(); - - /* Poll for C_READY and PHY READY */ - pr_debug("%s: Waiting for PHY Ready\n", __func__); - time_out_loop = 0; - do { - ready_poll = MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_RESET_SM); - time_out_loop++; - udelay(10); - } while (((ready_poll & (1 << 6)) == 0) && - (time_out_loop < time_out_max)); - if (time_out_loop >= time_out_max) - pr_err("%s: ERROR: TIMED OUT BEFORE C READY\n", __func__); - else - pr_debug("%s: C READY\n", __func__); - - /* Poll for PHY READY */ - pr_debug("%s: Waiting for PHY Ready\n", __func__); - time_out_loop = 0; - do { - ready_poll = MDSS_PLL_REG_R(io->phy_base, HDMI_PHY_STATUS); - time_out_loop++; - udelay(1); - } while (((ready_poll & 0x1) == 0) && (time_out_loop < time_out_max)); - - if (time_out_loop >= time_out_max) - pr_err("%s: TIMED OUT BEFORE PHY READY\n", __func__); - else - pr_debug("%s: HDMI PHY READY\n", __func__); - - io->pll_on = true; - - return 0; -} - - -static int hdmi_20nm_vco_set_rate(struct clk *c, unsigned long rate) -{ - struct hdmi_pll_vco_clk *vco = to_hdmi_20nm_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - void __iomem *pll_base; - void __iomem *phy_base; - unsigned int set_power_dwn = 0; - int rc; - - rc = mdss_pll_resource_enable(io, true); - if (rc) { - pr_err("pll resource can't be enabled\n"); - return rc; - } - - if (io->pll_on) - set_power_dwn = 1; - - pll_base = io->pll_base; - phy_base = io->phy_base; - - pr_debug("rate=%ld\n", rate); - - hdmi_20nm_phy_pll_set_clk_rate(c, rate); - - mdss_pll_resource_enable(io, false); - - if (set_power_dwn) - hdmi_20nm_vco_enable(c); - - vco->rate = rate; - vco->rate_set = true; - - return 0; -} - -static unsigned long hdmi_20nm_vco_get_rate(struct clk *c) -{ - unsigned long freq = 0; - int rc; - struct hdmi_pll_vco_clk *vco = to_hdmi_20nm_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - - if (is_gdsc_disabled(io)) - return 0; - - rc = mdss_pll_resource_enable(io, true); - if (rc) { - pr_err("pll resource can't be enabled\n"); - return rc; - } - - mdss_pll_resource_enable(io, false); - - return freq; -} - -static long hdmi_20nm_vco_round_rate(struct clk *c, unsigned long rate) -{ - unsigned long rrate = rate; - - pr_debug("rrate=%ld\n", rrate); - - return rrate; -} - -static int hdmi_20nm_vco_prepare(struct clk *c) -{ - struct hdmi_pll_vco_clk *vco = to_hdmi_20nm_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - int ret = 0; - - pr_debug("rate=%ld\n", vco->rate); - - if (!vco->rate_set && vco->rate) - ret = hdmi_20nm_vco_set_rate(c, vco->rate); - - if (!ret) { - ret = mdss_pll_resource_enable(io, true); - if (ret) - pr_err("pll resource can't be enabled\n"); - } - - return ret; -} - -static void hdmi_20nm_vco_unprepare(struct clk *c) -{ - struct hdmi_pll_vco_clk *vco = to_hdmi_20nm_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - - vco->rate_set = false; - - if (!io) { - pr_err("Invalid input parameter\n"); - return; - } - - if (!io->pll_on && - mdss_pll_resource_enable(io, true)) { - pr_err("pll resource can't be enabled\n"); - return; - } - - io->handoff_resources = false; - mdss_pll_resource_enable(io, false); - io->pll_on = false; -} - -static enum handoff hdmi_20nm_vco_handoff(struct clk *c) -{ - enum handoff ret = HANDOFF_DISABLED_CLK; - struct hdmi_pll_vco_clk *vco = to_hdmi_20nm_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - - if (is_gdsc_disabled(io)) - return HANDOFF_DISABLED_CLK; - - if (mdss_pll_resource_enable(io, true)) { - pr_err("pll resource can't be enabled\n"); - return ret; - } - - io->handoff_resources = true; - - if (hdmi_20nm_pll_lock_status(io)) { - io->pll_on = true; - c->rate = hdmi_20nm_vco_get_rate(c); - ret = HANDOFF_ENABLED_CLK; - } else { - io->handoff_resources = false; - mdss_pll_resource_enable(io, false); - } - - pr_debug("done, ret=%d\n", ret); - return ret; -} - -static const struct clk_ops hdmi_20nm_vco_clk_ops = { - .enable = hdmi_20nm_vco_enable, - .set_rate = hdmi_20nm_vco_set_rate, - .get_rate = hdmi_20nm_vco_get_rate, - .round_rate = hdmi_20nm_vco_round_rate, - .prepare = hdmi_20nm_vco_prepare, - .unprepare = hdmi_20nm_vco_unprepare, - .handoff = hdmi_20nm_vco_handoff, -}; - -static struct hdmi_pll_vco_clk hdmi_20nm_vco_clk = { - .ip_seti = (struct hdmi_pll_cfg[]){ - {550890000, 0x03}, - {589240000, 0x07}, - {689290000, 0x03}, - {727600000, 0x07}, - {HDMI_PLL_TMDS_MAX, 0x03}, - }, - .cp_seti = (struct hdmi_pll_cfg[]){ - {34440000, 0x3F}, - {36830000, 0x2F}, - {68870000, 0x3F}, - {73660000, 0x2F}, - {137730000, 0x3F}, - {147310000, 0x2F}, - {275450000, 0x3F}, - {294620000, 0x2F}, - {344650000, 0x3F}, - {363800000, 0x2F}, - {477960000, 0x3F}, - {512530000, 0x2F}, - {550890000, 0x1F}, - {589240000, 0x2F}, - {630900000, 0x3F}, - {650590000, 0x2F}, - {689290000, 0x1F}, - {727600000, 0x2F}, - {HDMI_PLL_TMDS_MAX, 0x3F}, - }, - .ip_setp = (struct hdmi_pll_cfg[]){ - {497340000, 0x03}, - {512530000, 0x07}, - {535680000, 0x03}, - {550890000, 0x07}, - {574060000, 0x03}, - {727600000, 0x07}, - {HDMI_PLL_TMDS_MAX, 0x03}, - }, - .cp_setp = (struct hdmi_pll_cfg[]){ - {36830000, 0x1F}, - {40010000, 0x17}, - {73660000, 0x1F}, - {80000000, 0x17}, - {147310000, 0x1F}, - {160010000, 0x17}, - {294620000, 0x1F}, - {363800000, 0x17}, - {497340000, 0x0F}, - {512530000, 0x1F}, - {535680000, 0x0F}, - {550890000, 0x1F}, - {574060000, 0x0F}, - {589240000, 0x1F}, - {727600000, 0x17}, - {HDMI_PLL_TMDS_MAX, 0x07}, - }, - .crctrl = (struct hdmi_pll_cfg[]){ - {40010000, 0xBB}, - {40030000, 0x77}, - {80000000, 0xBB}, - {80060000, 0x77}, - {160010000, 0xBB}, - {160120000, 0x77}, - {772930000, 0xBB}, - {HDMI_PLL_TMDS_MAX, 0xFF}, - }, - .c = { - .dbg_name = "hdmi_20nm_vco_clk", - .ops = &hdmi_20nm_vco_clk_ops, - CLK_INIT(hdmi_20nm_vco_clk.c), - }, -}; - -static struct clk_lookup hdmipllcc_8994[] = { - CLK_LIST(hdmi_20nm_vco_clk), -}; - -int hdmi_20nm_pll_clock_register(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int rc = -ENOTSUPP; - - /* Set client data for vco, mux and div clocks */ - hdmi_20nm_vco_clk.priv = pll_res; - - rc = of_msm_clock_register(pdev->dev.of_node, hdmipllcc_8994, - ARRAY_SIZE(hdmipllcc_8994)); - if (rc) { - pr_err("Clock register failed rc=%d\n", rc); - rc = -EPROBE_DEFER; - } else { - pr_debug("%s: SUCCESS\n", __func__); - } - - return rc; -} diff --git a/drivers/clk/qcom/mdss/mdss-hdmi-pll-28hpm.c b/drivers/clk/qcom/mdss/mdss-hdmi-pll-28hpm.c deleted file mode 100644 index 5d5cd54719e5a35f87a624b67235c88a34136e07..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-hdmi-pll-28hpm.c +++ /dev/null @@ -1,1091 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include - -#include "mdss-pll.h" -#include "mdss-hdmi-pll.h" - -/* hdmi phy registers */ -#define HDMI_PHY_ANA_CFG0 (0x0000) -#define HDMI_PHY_ANA_CFG1 (0x0004) -#define HDMI_PHY_ANA_CFG2 (0x0008) -#define HDMI_PHY_ANA_CFG3 (0x000C) -#define HDMI_PHY_PD_CTRL0 (0x0010) -#define HDMI_PHY_PD_CTRL1 (0x0014) -#define HDMI_PHY_GLB_CFG (0x0018) -#define HDMI_PHY_DCC_CFG0 (0x001C) -#define HDMI_PHY_DCC_CFG1 (0x0020) -#define HDMI_PHY_TXCAL_CFG0 (0x0024) -#define HDMI_PHY_TXCAL_CFG1 (0x0028) -#define HDMI_PHY_TXCAL_CFG2 (0x002C) -#define HDMI_PHY_TXCAL_CFG3 (0x0030) -#define HDMI_PHY_BIST_CFG0 (0x0034) -#define HDMI_PHY_BIST_CFG1 (0x0038) -#define HDMI_PHY_BIST_PATN0 (0x003C) -#define HDMI_PHY_BIST_PATN1 (0x0040) -#define HDMI_PHY_BIST_PATN2 (0x0044) -#define HDMI_PHY_BIST_PATN3 (0x0048) -#define HDMI_PHY_STATUS (0x005C) - -/* hdmi phy unified pll registers */ -#define HDMI_UNI_PLL_REFCLK_CFG (0x0000) -#define HDMI_UNI_PLL_POSTDIV1_CFG (0x0004) -#define HDMI_UNI_PLL_CHFPUMP_CFG (0x0008) -#define HDMI_UNI_PLL_VCOLPF_CFG (0x000C) -#define HDMI_UNI_PLL_VREG_CFG (0x0010) -#define HDMI_UNI_PLL_PWRGEN_CFG (0x0014) -#define HDMI_UNI_PLL_GLB_CFG (0x0020) -#define HDMI_UNI_PLL_POSTDIV2_CFG (0x0024) -#define HDMI_UNI_PLL_POSTDIV3_CFG (0x0028) -#define HDMI_UNI_PLL_LPFR_CFG (0x002C) -#define HDMI_UNI_PLL_LPFC1_CFG (0x0030) -#define HDMI_UNI_PLL_LPFC2_CFG (0x0034) -#define HDMI_UNI_PLL_SDM_CFG0 (0x0038) -#define HDMI_UNI_PLL_SDM_CFG1 (0x003C) -#define HDMI_UNI_PLL_SDM_CFG2 (0x0040) -#define HDMI_UNI_PLL_SDM_CFG3 (0x0044) -#define HDMI_UNI_PLL_SDM_CFG4 (0x0048) -#define HDMI_UNI_PLL_SSC_CFG0 (0x004C) -#define HDMI_UNI_PLL_SSC_CFG1 (0x0050) -#define HDMI_UNI_PLL_SSC_CFG2 (0x0054) -#define HDMI_UNI_PLL_SSC_CFG3 (0x0058) -#define HDMI_UNI_PLL_LKDET_CFG0 (0x005C) -#define HDMI_UNI_PLL_LKDET_CFG1 (0x0060) -#define HDMI_UNI_PLL_LKDET_CFG2 (0x0064) -#define HDMI_UNI_PLL_CAL_CFG0 (0x006C) -#define HDMI_UNI_PLL_CAL_CFG1 (0x0070) -#define HDMI_UNI_PLL_CAL_CFG2 (0x0074) -#define HDMI_UNI_PLL_CAL_CFG3 (0x0078) -#define HDMI_UNI_PLL_CAL_CFG4 (0x007C) -#define HDMI_UNI_PLL_CAL_CFG5 (0x0080) -#define HDMI_UNI_PLL_CAL_CFG6 (0x0084) -#define HDMI_UNI_PLL_CAL_CFG7 (0x0088) -#define HDMI_UNI_PLL_CAL_CFG8 (0x008C) -#define HDMI_UNI_PLL_CAL_CFG9 (0x0090) -#define HDMI_UNI_PLL_CAL_CFG10 (0x0094) -#define HDMI_UNI_PLL_CAL_CFG11 (0x0098) -#define HDMI_UNI_PLL_STATUS (0x00C0) - -#define HDMI_PLL_POLL_DELAY_US 50 -#define HDMI_PLL_POLL_TIMEOUT_US 500 - -static inline struct hdmi_pll_vco_clk *to_hdmi_vco_clk(struct clk *clk) -{ - return container_of(clk, struct hdmi_pll_vco_clk, c); -} - -static void hdmi_vco_disable(struct clk *c) -{ - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c); - struct mdss_pll_resources *hdmi_pll_res = vco->priv; - - if (!hdmi_pll_res) { - pr_err("Invalid input parameter\n"); - return; - } - - if (!hdmi_pll_res->pll_on && - mdss_pll_resource_enable(hdmi_pll_res, true)) { - pr_err("pll resource can't be enabled\n"); - return; - } - - MDSS_PLL_REG_W(hdmi_pll_res->pll_base, HDMI_UNI_PLL_GLB_CFG, 0x0); - udelay(5); - MDSS_PLL_REG_W(hdmi_pll_res->phy_base, HDMI_PHY_GLB_CFG, 0x0); - - hdmi_pll_res->handoff_resources = false; - mdss_pll_resource_enable(hdmi_pll_res, false); - hdmi_pll_res->pll_on = false; -} /* hdmi_vco_disable */ - -static int hdmi_vco_enable(struct clk *c) -{ - u32 status; - u32 delay_us, timeout_us; - int rc; - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c); - struct mdss_pll_resources *hdmi_pll_res = vco->priv; - - rc = mdss_pll_resource_enable(hdmi_pll_res, true); - if (rc) { - pr_err("pll resource can't be enabled\n"); - return rc; - } - - /* Global Enable */ - MDSS_PLL_REG_W(hdmi_pll_res->phy_base, HDMI_PHY_GLB_CFG, 0x81); - /* Power up power gen */ - MDSS_PLL_REG_W(hdmi_pll_res->phy_base, HDMI_PHY_PD_CTRL0, 0x00); - udelay(350); - - /* PLL Power-Up */ - MDSS_PLL_REG_W(hdmi_pll_res->pll_base, HDMI_UNI_PLL_GLB_CFG, 0x01); - udelay(5); - /* Power up PLL LDO */ - MDSS_PLL_REG_W(hdmi_pll_res->pll_base, HDMI_UNI_PLL_GLB_CFG, 0x03); - udelay(350); - - /* PLL Power-Up */ - MDSS_PLL_REG_W(hdmi_pll_res->pll_base, HDMI_UNI_PLL_GLB_CFG, 0x0F); - udelay(350); - - /* poll for PLL ready status */ - delay_us = 100; - timeout_us = 2000; - if (readl_poll_timeout_atomic( - (hdmi_pll_res->pll_base + HDMI_UNI_PLL_STATUS), - status, ((status & BIT(0)) == 1), delay_us, timeout_us)) { - pr_err("hdmi phy pll status=%x failed to Lock\n", status); - hdmi_vco_disable(c); - mdss_pll_resource_enable(hdmi_pll_res, false); - return -EINVAL; - } - pr_debug("hdmi phy pll is locked\n"); - - udelay(350); - /* poll for PHY ready status */ - delay_us = 100; - timeout_us = 2000; - if (readl_poll_timeout_atomic( - (hdmi_pll_res->phy_base + HDMI_PHY_STATUS), - status, ((status & BIT(0)) == 1), delay_us, timeout_us)) { - pr_err("hdmi phy status=%x failed to Lock\n", status); - hdmi_vco_disable(c); - mdss_pll_resource_enable(hdmi_pll_res, false); - return -EINVAL; - } - hdmi_pll_res->pll_on = true; - pr_debug("hdmi phy is locked\n"); - - return 0; -} /* hdmi_vco_enable */ - - -static void hdmi_phy_pll_calculator(u32 vco_freq, - struct mdss_pll_resources *hdmi_pll_res) -{ - u32 ref_clk = 19200000; - u32 sdm_mode = 1; - u32 ref_clk_multiplier = sdm_mode == 1 ? 2 : 1; - u32 int_ref_clk_freq = ref_clk * ref_clk_multiplier; - u32 fbclk_pre_div = 1; - u32 ssc_mode = 0; - u32 kvco = 270; - u32 vdd = 95; - u32 ten_power_six = 1000000; - u32 ssc_ds_ppm = ssc_mode ? 5000 : 0; - u32 sdm_res = 16; - u32 ssc_tri_step = 32; - u32 ssc_freq = 2; - u64 ssc_ds = vco_freq * ssc_ds_ppm; - u32 div_in_freq = vco_freq / fbclk_pre_div; - u64 dc_offset = (div_in_freq / int_ref_clk_freq - 1) * - ten_power_six * 10; - u32 ssc_kdiv = (int_ref_clk_freq / ssc_freq) - - ten_power_six; - u64 sdm_freq_seed; - u32 ssc_tri_inc; - u64 fb_div_n; - void __iomem *pll_base = hdmi_pll_res->pll_base; - u32 val; - - pr_debug("vco_freq = %u\n", vco_freq); - - do_div(ssc_ds, (u64)ten_power_six); - - fb_div_n = (u64)div_in_freq * (u64)ten_power_six * 10; - do_div(fb_div_n, int_ref_clk_freq); - - sdm_freq_seed = ((fb_div_n - dc_offset - ten_power_six * 10) * - (1 << sdm_res) * 10) + 5; - do_div(sdm_freq_seed, ((u64)ten_power_six * 100)); - - ssc_tri_inc = (u32)ssc_ds; - ssc_tri_inc = (ssc_tri_inc / int_ref_clk_freq) * (1 << 16) / - ssc_tri_step; - - val = (ref_clk_multiplier == 2 ? 1 : 0) + - ((fbclk_pre_div == 2 ? 1 : 0) * 16); - pr_debug("HDMI_UNI_PLL_REFCLK_CFG = 0x%x\n", val); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_REFCLK_CFG, val); - - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CHFPUMP_CFG, 0x02); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_VCOLPF_CFG, 0x19); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_VREG_CFG, 0x04); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_PWRGEN_CFG, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_POSTDIV2_CFG, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_POSTDIV3_CFG, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFR_CFG, 0x0E); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFC1_CFG, 0x20); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFC2_CFG, 0x0D); - - do_div(dc_offset, (u64)ten_power_six * 10); - val = sdm_mode == 0 ? 64 + dc_offset : 0; - pr_debug("HDMI_UNI_PLL_SDM_CFG0 = 0x%x\n", val); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG0, val); - - val = 64 + dc_offset; - pr_debug("HDMI_UNI_PLL_SDM_CFG1 = 0x%x\n", val); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG1, val); - - val = sdm_freq_seed & 0xFF; - pr_debug("HDMI_UNI_PLL_SDM_CFG2 = 0x%x\n", val); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG2, val); - - val = (sdm_freq_seed >> 8) & 0xFF; - pr_debug("HDMI_UNI_PLL_SDM_CFG3 = 0x%x\n", val); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG3, val); - - val = (sdm_freq_seed >> 16) & 0xFF; - pr_debug("HDMI_UNI_PLL_SDM_CFG4 = 0x%x\n", val); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG4, val); - - val = (ssc_mode == 0 ? 128 : 0) + (ssc_kdiv / ten_power_six); - pr_debug("HDMI_UNI_PLL_SSC_CFG0 = 0x%x\n", val); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SSC_CFG0, val); - - val = ssc_tri_inc & 0xFF; - pr_debug("HDMI_UNI_PLL_SSC_CFG1 = 0x%x\n", val); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SSC_CFG1, val); - - val = (ssc_tri_inc >> 8) & 0xFF; - pr_debug("HDMI_UNI_PLL_SSC_CFG2 = 0x%x\n", val); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SSC_CFG2, val); - - pr_debug("HDMI_UNI_PLL_SSC_CFG3 = 0x%x\n", ssc_tri_step); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SSC_CFG3, ssc_tri_step); - - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG0, 0x10); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG1, 0x1A); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG2, 0x05); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG0, 0x0A); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG1, 0x04); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG2, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG3, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG4, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG5, 0x00); - - val = (kvco * vdd * 10000) / 6; - val += 500000; - val /= ten_power_six; - pr_debug("HDMI_UNI_PLL_CAL_CFG6 = 0x%x\n", val); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG6, val & 0xFF); - - val = (kvco * vdd * 10000) / 6; - val -= ten_power_six; - val /= ten_power_six; - val = (val >> 8) & 0xFF; - pr_debug("HDMI_UNI_PLL_CAL_CFG7 = 0x%x\n", val); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG7, val); - - val = (ref_clk * 5) / ten_power_six; - pr_debug("HDMI_UNI_PLL_CAL_CFG8 = 0x%x\n", val); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG8, val); - - val = ((ref_clk * 5) / ten_power_six) >> 8; - pr_debug("HDMI_UNI_PLL_CAL_CFG9 = 0x%x\n", val); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG9, val); - - vco_freq /= ten_power_six; - val = vco_freq & 0xFF; - pr_debug("HDMI_UNI_PLL_CAL_CFG10 = 0x%x\n", val); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG10, val); - - val = vco_freq >> 8; - pr_debug("HDMI_UNI_PLL_CAL_CFG11 = 0x%x\n", val); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG11, val); -} /* hdmi_phy_pll_calculator */ - -static int hdmi_vco_set_rate(struct clk *c, unsigned long rate) -{ - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c); - struct mdss_pll_resources *hdmi_pll_res = vco->priv; - void __iomem *pll_base; - void __iomem *phy_base; - unsigned int set_power_dwn = 0; - int rc; - - rc = mdss_pll_resource_enable(hdmi_pll_res, true); - if (rc) { - pr_err("pll resource can't be enabled\n"); - return rc; - } - - if (hdmi_pll_res->pll_on) { - hdmi_vco_disable(c); - set_power_dwn = 1; - } - - pll_base = hdmi_pll_res->pll_base; - phy_base = hdmi_pll_res->phy_base; - - pr_debug("rate=%ld\n", rate); - - switch (rate) { - case 0: - break; - - case 756000000: - /* 640x480p60 */ - MDSS_PLL_REG_W(phy_base, HDMI_PHY_GLB_CFG, 0x81); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_GLB_CFG, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_REFCLK_CFG, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_VCOLPF_CFG, 0x19); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFR_CFG, 0x0E); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFC1_CFG, 0x20); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFC2_CFG, 0x0D); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG0, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG1, 0x52); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG2, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG3, 0xB0); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG4, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG0, 0x10); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG1, 0x1A); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG2, 0x05); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_POSTDIV2_CFG, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_POSTDIV3_CFG, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG2, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG8, 0x60); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG9, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG10, 0xF4); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG11, 0x02); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_PD_CTRL0, 0x1F); - udelay(50); - - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_GLB_CFG, 0x0F); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_PD_CTRL1, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG2, 0x10); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG0, 0xDB); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG1, 0x43); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG2, 0x02); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG3, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_VREG_CFG, 0x04); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_DCC_CFG0, 0xD0); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_DCC_CFG1, 0x1A); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG0, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG1, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG2, 0x02); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG3, 0x05); - udelay(200); - break; - - case 810000000: - /* 576p50/576i50 case */ - MDSS_PLL_REG_W(phy_base, HDMI_PHY_GLB_CFG, 0x81); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_GLB_CFG, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_REFCLK_CFG, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_VCOLPF_CFG, 0x19); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFR_CFG, 0x0E); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFC1_CFG, 0x20); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFC2_CFG, 0x0D); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG0, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG1, 0x54); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG2, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG3, 0x18); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG4, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG0, 0x10); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG1, 0x1A); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG2, 0x05); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_POSTDIV2_CFG, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_POSTDIV3_CFG, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG2, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG8, 0x60); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG9, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG10, 0x2A); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG11, 0x03); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_PD_CTRL0, 0x1F); - udelay(50); - - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_GLB_CFG, 0x0F); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_PD_CTRL1, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG2, 0x10); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG0, 0xDB); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG1, 0x43); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG2, 0x02); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG3, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_VREG_CFG, 0x04); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_DCC_CFG0, 0xD0); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_DCC_CFG1, 0x1A); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG0, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG1, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG2, 0x02); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG3, 0x05); - udelay(200); - break; - - case 810900000: - /* 480p60/480i60 case */ - MDSS_PLL_REG_W(phy_base, HDMI_PHY_GLB_CFG, 0x81); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_GLB_CFG, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_REFCLK_CFG, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_VCOLPF_CFG, 0x19); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFR_CFG, 0x0E); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFC1_CFG, 0x20); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFC2_CFG, 0x0D); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG0, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG1, 0x54); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG2, 0x66); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG3, 0x1D); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG4, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG0, 0x10); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG1, 0x1A); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG2, 0x05); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_POSTDIV2_CFG, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_POSTDIV3_CFG, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG2, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG8, 0x60); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG9, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG10, 0x2A); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG11, 0x03); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_PD_CTRL0, 0x1F); - udelay(50); - - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_GLB_CFG, 0x0F); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_PD_CTRL1, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG2, 0x10); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG0, 0xDB); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG1, 0x43); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG2, 0x02); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG3, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_VREG_CFG, 0x04); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_DCC_CFG0, 0xD0); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_DCC_CFG1, 0x1A); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG0, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG1, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG2, 0x02); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG3, 0x05); - udelay(200); - break; - - case 650000000: - MDSS_PLL_REG_W(phy_base, HDMI_PHY_GLB_CFG, 0x81); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_GLB_CFG, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_REFCLK_CFG, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_VCOLPF_CFG, 0x19); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFR_CFG, 0x0E); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFC1_CFG, 0x20); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFC2_CFG, 0x0D); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG0, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG1, 0x4F); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG2, 0x55); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG3, 0xED); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG4, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG0, 0x10); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG1, 0x1A); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG2, 0x05); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_POSTDIV2_CFG, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_POSTDIV3_CFG, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG2, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG8, 0x60); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG9, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG10, 0x8A); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG11, 0x02); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_PD_CTRL0, 0x1F); - udelay(50); - - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_GLB_CFG, 0x0F); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_PD_CTRL1, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG2, 0x10); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG0, 0xDB); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG1, 0x43); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG2, 0x02); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG3, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_VREG_CFG, 0x04); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_DCC_CFG0, 0xD0); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_DCC_CFG1, 0x1A); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG0, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG1, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG2, 0x02); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG3, 0x05); - udelay(200); - break; - - case 742500000: - /* - * 720p60/720p50/1080i60/1080i50 - * 1080p24/1080p30/1080p25 case - */ - MDSS_PLL_REG_W(phy_base, HDMI_PHY_GLB_CFG, 0x81); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_GLB_CFG, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_REFCLK_CFG, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_VCOLPF_CFG, 0x19); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFR_CFG, 0x0E); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFC1_CFG, 0x20); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFC2_CFG, 0x0D); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG0, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG1, 0x52); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG2, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG3, 0x56); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG4, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG0, 0x10); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG1, 0x1A); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG2, 0x05); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_POSTDIV2_CFG, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_POSTDIV3_CFG, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG2, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG8, 0x60); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG9, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG10, 0xE6); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG11, 0x02); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_PD_CTRL0, 0x1F); - udelay(50); - - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_GLB_CFG, 0x0F); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_PD_CTRL1, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG2, 0x10); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG0, 0xDB); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG1, 0x43); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG2, 0x02); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG3, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_VREG_CFG, 0x04); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_DCC_CFG0, 0xD0); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_DCC_CFG1, 0x1A); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG0, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG1, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG2, 0x02); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG3, 0x05); - udelay(200); - break; - - case 1080000000: - MDSS_PLL_REG_W(phy_base, HDMI_PHY_GLB_CFG, 0x81); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_GLB_CFG, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_REFCLK_CFG, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_VCOLPF_CFG, 0x19); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFR_CFG, 0x0E); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFC1_CFG, 0x20); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFC2_CFG, 0x0D); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG0, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG1, 0x5B); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG2, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG3, 0x20); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG4, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG0, 0x10); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG1, 0x1A); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG2, 0x05); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_POSTDIV2_CFG, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_POSTDIV3_CFG, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG2, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG8, 0x60); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG9, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG10, 0x38); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG11, 0x04); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_PD_CTRL0, 0x1F); - udelay(50); - - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_GLB_CFG, 0x0F); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_PD_CTRL1, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG2, 0x10); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG0, 0xDB); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG1, 0x43); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG2, 0x02); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG3, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_VREG_CFG, 0x04); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_DCC_CFG0, 0xD0); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_DCC_CFG1, 0x1A); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG0, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG1, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG2, 0x02); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG3, 0x05); - udelay(200); - break; - - case 1342500000: - MDSS_PLL_REG_W(phy_base, HDMI_PHY_GLB_CFG, 0x81); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_GLB_CFG, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_REFCLK_CFG, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_VCOLPF_CFG, 0x19); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFR_CFG, 0x0E); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFC1_CFG, 0x20); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFC2_CFG, 0x0D); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG0, 0x36); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG1, 0x61); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG2, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG3, 0xF6); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG4, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG0, 0x10); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG1, 0x1A); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG2, 0x05); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_POSTDIV2_CFG, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_POSTDIV3_CFG, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG2, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG8, 0x60); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG9, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG10, 0x3E); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG11, 0x05); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_PD_CTRL0, 0x1F); - udelay(50); - - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_GLB_CFG, 0x0F); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_PD_CTRL1, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG2, 0x10); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG0, 0xDB); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG1, 0x43); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG2, 0x05); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG3, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_VREG_CFG, 0x04); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_DCC_CFG0, 0xD0); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_DCC_CFG1, 0x1A); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG0, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG1, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG2, 0x11); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG3, 0x05); - udelay(200); - break; - - case 1485000000: - MDSS_PLL_REG_W(phy_base, HDMI_PHY_GLB_CFG, 0x81); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_GLB_CFG, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_REFCLK_CFG, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_VCOLPF_CFG, 0x19); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFR_CFG, 0x0E); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFC1_CFG, 0x20); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LPFC2_CFG, 0x0D); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG0, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG1, 0x65); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG2, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG3, 0xAC); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_SDM_CFG4, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG0, 0x10); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG1, 0x1A); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_LKDET_CFG2, 0x05); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_POSTDIV2_CFG, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_POSTDIV3_CFG, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG2, 0x01); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG8, 0x60); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG9, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG10, 0xCD); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_CAL_CFG11, 0x05); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_PD_CTRL0, 0x1F); - udelay(50); - - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_GLB_CFG, 0x0F); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_PD_CTRL1, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG2, 0x10); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG0, 0xDB); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG1, 0x43); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG2, 0x06); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG3, 0x03); - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_VREG_CFG, 0x04); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_DCC_CFG0, 0xD0); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_DCC_CFG1, 0x1A); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG0, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG1, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG2, 0x02); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG3, 0x05); - udelay(200); - break; - - default: - pr_debug("Use pll settings calculator for rate=%ld\n", rate); - - MDSS_PLL_REG_W(phy_base, HDMI_PHY_GLB_CFG, 0x81); - hdmi_phy_pll_calculator(rate, hdmi_pll_res); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_PD_CTRL0, 0x1F); - udelay(50); - - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_GLB_CFG, 0x0F); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_PD_CTRL1, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG2, 0x10); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG0, 0xDB); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG1, 0x43); - - if (rate < 825000000) { - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG2, 0x01); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG3, 0x00); - } else if (rate >= 825000000 && rate < 1342500000) { - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG2, 0x05); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG3, 0x03); - } else { - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG2, 0x06); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_ANA_CFG3, 0x03); - } - - MDSS_PLL_REG_W(pll_base, HDMI_UNI_PLL_VREG_CFG, 0x04); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_DCC_CFG0, 0xD0); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_DCC_CFG1, 0x1A); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG0, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG1, 0x00); - - if (rate < 825000000) - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG2, 0x01); - else - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG2, 0x00); - - MDSS_PLL_REG_W(phy_base, HDMI_PHY_TXCAL_CFG3, 0x05); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_BIST_PATN0, 0x62); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_BIST_PATN1, 0x03); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_BIST_PATN2, 0x69); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_BIST_PATN3, 0x02); - - udelay(200); - - MDSS_PLL_REG_W(phy_base, HDMI_PHY_BIST_CFG1, 0x00); - MDSS_PLL_REG_W(phy_base, HDMI_PHY_BIST_CFG0, 0x00); - } - - /* Make sure writes complete before disabling iface clock */ - mb(); - - mdss_pll_resource_enable(hdmi_pll_res, false); - - if (set_power_dwn) - hdmi_vco_enable(c); - - vco->rate = rate; - vco->rate_set = true; - - return 0; -} /* hdmi_pll_set_rate */ - -/* HDMI PLL DIV CLK */ - -static unsigned long hdmi_vco_get_rate(struct clk *c) -{ - unsigned long freq = 0; - int rc; - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c); - struct mdss_pll_resources *hdmi_pll_res = vco->priv; - - if (is_gdsc_disabled(hdmi_pll_res)) - return 0; - - rc = mdss_pll_resource_enable(hdmi_pll_res, true); - if (rc) { - pr_err("pll resource can't be enabled\n"); - return rc; - } - - freq = MDSS_PLL_REG_R(hdmi_pll_res->pll_base, - HDMI_UNI_PLL_CAL_CFG11) << 8 | - MDSS_PLL_REG_R(hdmi_pll_res->pll_base, HDMI_UNI_PLL_CAL_CFG10); - - switch (freq) { - case 742: - freq = 742500000; - break; - case 810: - if (MDSS_PLL_REG_R(hdmi_pll_res->pll_base, - HDMI_UNI_PLL_SDM_CFG3) == 0x18) - freq = 810000000; - else - freq = 810900000; - break; - case 1342: - freq = 1342500000; - break; - default: - freq *= 1000000; - } - mdss_pll_resource_enable(hdmi_pll_res, false); - - return freq; -} - -static long hdmi_vco_round_rate(struct clk *c, unsigned long rate) -{ - unsigned long rrate = rate; - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c); - - if (rate < vco->min_rate) - rrate = vco->min_rate; - if (rate > vco->max_rate) - rrate = vco->max_rate; - - pr_debug("rrate=%ld\n", rrate); - - return rrate; -} - -static int hdmi_vco_prepare(struct clk *c) -{ - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c); - int ret = 0; - - pr_debug("rate=%ld\n", vco->rate); - - if (!vco->rate_set && vco->rate) - ret = hdmi_vco_set_rate(c, vco->rate); - - return ret; -} - -static void hdmi_vco_unprepare(struct clk *c) -{ - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c); - - vco->rate_set = false; -} - -static int hdmi_pll_lock_status(struct mdss_pll_resources *hdmi_pll_res) -{ - u32 status; - int pll_locked = 0; - int rc; - - rc = mdss_pll_resource_enable(hdmi_pll_res, true); - if (rc) { - pr_err("pll resource can't be enabled\n"); - return rc; - } - - /* poll for PLL ready status */ - if (readl_poll_timeout_atomic( - (hdmi_pll_res->phy_base + HDMI_PHY_STATUS), - status, ((status & BIT(0)) == 1), - HDMI_PLL_POLL_DELAY_US, - HDMI_PLL_POLL_TIMEOUT_US)) { - pr_debug("HDMI PLL status=%x failed to Lock\n", status); - pll_locked = 0; - } else { - pll_locked = 1; - } - mdss_pll_resource_enable(hdmi_pll_res, false); - - return pll_locked; -} - -static enum handoff hdmi_vco_handoff(struct clk *c) -{ - enum handoff ret = HANDOFF_DISABLED_CLK; - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c); - struct mdss_pll_resources *hdmi_pll_res = vco->priv; - - if (is_gdsc_disabled(hdmi_pll_res)) - return HANDOFF_DISABLED_CLK; - - if (mdss_pll_resource_enable(hdmi_pll_res, true)) { - pr_err("pll resource can't be enabled\n"); - return ret; - } - - hdmi_pll_res->handoff_resources = true; - - if (hdmi_pll_lock_status(hdmi_pll_res)) { - hdmi_pll_res->pll_on = true; - c->rate = hdmi_vco_get_rate(c); - ret = HANDOFF_ENABLED_CLK; - } else { - hdmi_pll_res->handoff_resources = false; - mdss_pll_resource_enable(hdmi_pll_res, false); - } - - pr_debug("done, ret=%d\n", ret); - return ret; -} - -static const struct clk_ops hdmi_vco_clk_ops = { - .enable = hdmi_vco_enable, - .set_rate = hdmi_vco_set_rate, - .get_rate = hdmi_vco_get_rate, - .round_rate = hdmi_vco_round_rate, - .prepare = hdmi_vco_prepare, - .unprepare = hdmi_vco_unprepare, - .disable = hdmi_vco_disable, - .handoff = hdmi_vco_handoff, -}; - -static struct hdmi_pll_vco_clk hdmi_vco_clk = { - .min_rate = 600000000, - .max_rate = 1800000000, - .c = { - .dbg_name = "hdmi_vco_clk", - .ops = &hdmi_vco_clk_ops, - CLK_INIT(hdmi_vco_clk.c), - }, -}; - -struct div_clk hdmipll_div1_clk = { - .data = { - .div = 1, - .min_div = 1, - .max_div = 1, - }, - .c = { - .parent = &hdmi_vco_clk.c, - .dbg_name = "hdmipll_div1_clk", - .ops = &clk_ops_div, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(hdmipll_div1_clk.c), - }, -}; - -struct div_clk hdmipll_div2_clk = { - .data = { - .div = 2, - .min_div = 2, - .max_div = 2, - }, - .c = { - .parent = &hdmi_vco_clk.c, - .dbg_name = "hdmipll_div2_clk", - .ops = &clk_ops_div, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(hdmipll_div2_clk.c), - }, -}; - -struct div_clk hdmipll_div4_clk = { - .data = { - .div = 4, - .min_div = 4, - .max_div = 4, - }, - .c = { - .parent = &hdmi_vco_clk.c, - .dbg_name = "hdmipll_div4_clk", - .ops = &clk_ops_div, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(hdmipll_div4_clk.c), - }, -}; - -struct div_clk hdmipll_div6_clk = { - .data = { - .div = 6, - .min_div = 6, - .max_div = 6, - }, - .c = { - .parent = &hdmi_vco_clk.c, - .dbg_name = "hdmipll_div6_clk", - .ops = &clk_ops_div, - .flags = CLKFLAG_NO_RATE_CACHE, - CLK_INIT(hdmipll_div6_clk.c), - }, -}; - -static int hdmipll_set_mux_sel(struct mux_clk *clk, int mux_sel) -{ - struct mdss_pll_resources *hdmi_pll_res = clk->priv; - int rc; - - rc = mdss_pll_resource_enable(hdmi_pll_res, true); - if (rc) { - pr_err("pll resource can't be enabled\n"); - return rc; - } - - pr_debug("mux_sel=%d\n", mux_sel); - MDSS_PLL_REG_W(hdmi_pll_res->pll_base, - HDMI_UNI_PLL_POSTDIV1_CFG, mux_sel); - mdss_pll_resource_enable(hdmi_pll_res, false); - - return 0; -} - -static int hdmipll_get_mux_sel(struct mux_clk *clk) -{ - int rc; - int mux_sel = 0; - struct mdss_pll_resources *hdmi_pll_res = clk->priv; - - if (is_gdsc_disabled(hdmi_pll_res)) - return 0; - - rc = mdss_pll_resource_enable(hdmi_pll_res, true); - if (rc) { - pr_err("pll resource can't be enabled\n"); - return rc; - } - - mux_sel = MDSS_PLL_REG_R(hdmi_pll_res->pll_base, - HDMI_UNI_PLL_POSTDIV1_CFG); - mdss_pll_resource_enable(hdmi_pll_res, false); - mux_sel &= 0x03; - pr_debug("mux_sel=%d\n", mux_sel); - - return mux_sel; -} - -static struct clk_mux_ops hdmipll_mux_ops = { - .set_mux_sel = hdmipll_set_mux_sel, - .get_mux_sel = hdmipll_get_mux_sel, -}; - -static const struct clk_ops hdmi_mux_ops; - -static int hdmi_mux_prepare(struct clk *c) -{ - int ret = 0; - - if (c && c->ops && c->ops->set_rate) - ret = c->ops->set_rate(c, c->rate); - - return ret; -} - -struct mux_clk hdmipll_mux_clk = { - MUX_SRC_LIST( - { &hdmipll_div1_clk.c, 0 }, - { &hdmipll_div2_clk.c, 1 }, - { &hdmipll_div4_clk.c, 2 }, - { &hdmipll_div6_clk.c, 3 }, - ), - .ops = &hdmipll_mux_ops, - .c = { - .parent = &hdmipll_div1_clk.c, - .dbg_name = "hdmipll_mux_clk", - .ops = &hdmi_mux_ops, - CLK_INIT(hdmipll_mux_clk.c), - }, -}; - -struct div_clk hdmipll_clk_src = { - .data = { - .div = 5, - .min_div = 5, - .max_div = 5, - }, - .c = { - .parent = &hdmipll_mux_clk.c, - .dbg_name = "hdmipll_clk_src", - .ops = &clk_ops_div, - CLK_INIT(hdmipll_clk_src.c), - }, -}; - -static struct clk_lookup hdmipllcc_8974[] = { - CLK_LOOKUP("extp_clk_src", hdmipll_clk_src.c, - "fd8c0000.qcom,mmsscc-mdss"), -}; - -int hdmi_pll_clock_register(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int rc = -ENOTSUPP; - - /* Set client data for vco, mux and div clocks */ - hdmipll_clk_src.priv = pll_res; - hdmipll_mux_clk.priv = pll_res; - hdmipll_div1_clk.priv = pll_res; - hdmipll_div2_clk.priv = pll_res; - hdmipll_div4_clk.priv = pll_res; - hdmipll_div6_clk.priv = pll_res; - hdmi_vco_clk.priv = pll_res; - - /* Set hdmi mux clock operation */ - hdmi_mux_ops = clk_ops_gen_mux; - hdmi_mux_ops.prepare = hdmi_mux_prepare; - - rc = of_msm_clock_register(pdev->dev.of_node, hdmipllcc_8974, - ARRAY_SIZE(hdmipllcc_8974)); - if (rc) { - pr_err("Clock register failed rc=%d\n", rc); - rc = -EPROBE_DEFER; - } - - return rc; -} diff --git a/drivers/clk/qcom/mdss/mdss-hdmi-pll-28lpm.c b/drivers/clk/qcom/mdss/mdss-hdmi-pll-28lpm.c deleted file mode 100644 index 530ad83c8b73d7a75e99fff3cf621624c7d2d069..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-hdmi-pll-28lpm.c +++ /dev/null @@ -1,790 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. - */ - - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include "mdss-pll.h" -#include "mdss-hdmi-pll.h" - -/* HDMI PLL macros */ -#define HDMI_PHY_PLL_REFCLK_CFG (0x0400) -#define HDMI_PHY_PLL_CHRG_PUMP_CFG (0x0404) -#define HDMI_PHY_PLL_LOOP_FLT_CFG0 (0x0408) -#define HDMI_PHY_PLL_LOOP_FLT_CFG1 (0x040c) -#define HDMI_PHY_PLL_IDAC_ADJ_CFG (0x0410) -#define HDMI_PHY_PLL_I_VI_KVCO_CFG (0x0414) -#define HDMI_PHY_PLL_PWRDN_B (0x0418) -#define HDMI_PHY_PLL_SDM_CFG0 (0x041c) -#define HDMI_PHY_PLL_SDM_CFG1 (0x0420) -#define HDMI_PHY_PLL_SDM_CFG2 (0x0424) -#define HDMI_PHY_PLL_SDM_CFG3 (0x0428) -#define HDMI_PHY_PLL_SDM_CFG4 (0x042c) -#define HDMI_PHY_PLL_SSC_CFG0 (0x0430) -#define HDMI_PHY_PLL_SSC_CFG1 (0x0434) -#define HDMI_PHY_PLL_SSC_CFG2 (0x0438) -#define HDMI_PHY_PLL_SSC_CFG3 (0x043c) -#define HDMI_PHY_PLL_LOCKDET_CFG0 (0x0440) -#define HDMI_PHY_PLL_LOCKDET_CFG1 (0x0444) -#define HDMI_PHY_PLL_LOCKDET_CFG2 (0x0448) -#define HDMI_PHY_PLL_VCOCAL_CFG0 (0x044c) -#define HDMI_PHY_PLL_VCOCAL_CFG1 (0x0450) -#define HDMI_PHY_PLL_VCOCAL_CFG2 (0x0454) -#define HDMI_PHY_PLL_VCOCAL_CFG3 (0x0458) -#define HDMI_PHY_PLL_VCOCAL_CFG4 (0x045c) -#define HDMI_PHY_PLL_VCOCAL_CFG5 (0x0460) -#define HDMI_PHY_PLL_VCOCAL_CFG6 (0x0464) -#define HDMI_PHY_PLL_VCOCAL_CFG7 (0x0468) -#define HDMI_PHY_PLL_DEBUG_SEL (0x046c) -#define HDMI_PHY_PLL_MISC0 (0x0470) -#define HDMI_PHY_PLL_MISC1 (0x0474) -#define HDMI_PHY_PLL_MISC2 (0x0478) -#define HDMI_PHY_PLL_MISC3 (0x047c) -#define HDMI_PHY_PLL_MISC4 (0x0480) -#define HDMI_PHY_PLL_MISC5 (0x0484) -#define HDMI_PHY_PLL_MISC6 (0x0488) -#define HDMI_PHY_PLL_DEBUG_BUS0 (0x048c) -#define HDMI_PHY_PLL_DEBUG_BUS1 (0x0490) -#define HDMI_PHY_PLL_DEBUG_BUS2 (0x0494) -#define HDMI_PHY_PLL_STATUS0 (0x0498) -#define HDMI_PHY_PLL_STATUS1 (0x049c) - -#define HDMI_PHY_REG_0 (0x0000) -#define HDMI_PHY_REG_1 (0x0004) -#define HDMI_PHY_REG_2 (0x0008) -#define HDMI_PHY_REG_3 (0x000c) -#define HDMI_PHY_REG_4 (0x0010) -#define HDMI_PHY_REG_5 (0x0014) -#define HDMI_PHY_REG_6 (0x0018) -#define HDMI_PHY_REG_7 (0x001c) -#define HDMI_PHY_REG_8 (0x0020) -#define HDMI_PHY_REG_9 (0x0024) -#define HDMI_PHY_REG_10 (0x0028) -#define HDMI_PHY_REG_11 (0x002c) -#define HDMI_PHY_REG_12 (0x0030) -#define HDMI_PHY_REG_BIST_CFG (0x0034) -#define HDMI_PHY_DEBUG_BUS_SEL (0x0038) -#define HDMI_PHY_REG_MISC0 (0x003c) -#define HDMI_PHY_REG_13 (0x0040) -#define HDMI_PHY_REG_14 (0x0044) -#define HDMI_PHY_REG_15 (0x0048) - -/* HDMI PHY/PLL bit field macros */ -#define SW_RESET BIT(2) -#define SW_RESET_PLL BIT(0) -#define PWRDN_B BIT(7) - -#define PLL_PWRDN_B BIT(3) -#define REG_VTEST_EN BIT(2) -#define PD_PLL BIT(1) -#define PD_PLL_REG BIT(0) - - -#define HDMI_PLL_POLL_DELAY_US 50 -#define HDMI_PLL_POLL_TIMEOUT_US 500 - -static int hdmi_pll_lock_status(struct mdss_pll_resources *hdmi_pll_res) -{ - u32 status; - int pll_locked = 0; - int rc; - - rc = mdss_pll_resource_enable(hdmi_pll_res, true); - if (rc) { - pr_err("pll resource can't be enabled\n"); - return rc; - } - - /* poll for PLL ready status */ - if (readl_poll_timeout_atomic( - (hdmi_pll_res->pll_base + HDMI_PHY_PLL_STATUS0), - status, ((status & BIT(0)) == 1), - HDMI_PLL_POLL_DELAY_US, - HDMI_PLL_POLL_TIMEOUT_US)) { - pr_debug("HDMI PLL status=%x failed to Lock\n", status); - pll_locked = 0; - } else { - pr_debug("HDMI PLL locked\n"); - pll_locked = 1; - } - mdss_pll_resource_enable(hdmi_pll_res, false); - - return pll_locked; -} - -static void hdmi_pll_disable_28lpm(struct clk_hw *hw) -{ - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk_hw(hw); - struct mdss_pll_resources *hdmi_pll_res = vco->priv; - u32 val; - - if (!hdmi_pll_res) { - pr_err("Invalid input parameter\n"); - return; - } - - val = MDSS_PLL_REG_R(hdmi_pll_res->pll_base, HDMI_PHY_REG_12); - val &= (~PWRDN_B); - MDSS_PLL_REG_W(hdmi_pll_res->pll_base, HDMI_PHY_REG_12, val); - - val = MDSS_PLL_REG_R(hdmi_pll_res->pll_base, HDMI_PHY_PLL_PWRDN_B); - val |= PD_PLL; - val &= (~PLL_PWRDN_B); - MDSS_PLL_REG_W(hdmi_pll_res->pll_base, HDMI_PHY_PLL_PWRDN_B, val); - - /* Make sure HDMI PHY/PLL are powered down */ - wmb(); - -} /* hdmi_pll_disable_28lpm */ - -static int hdmi_pll_enable_28lpm(struct clk_hw *hw) -{ - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk_hw(hw); - struct mdss_pll_resources *hdmi_pll_res = vco->priv; - void __iomem *pll_base; - u32 val; - int pll_lock_retry = 10; - - pll_base = hdmi_pll_res->pll_base; - - /* Assert PLL S/W reset */ - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_LOCKDET_CFG2, 0x8d); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_LOCKDET_CFG0, 0x10); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_LOCKDET_CFG1, 0x1a); - udelay(10); - /* De-assert PLL S/W reset */ - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_LOCKDET_CFG2, 0x0d); - - MDSS_PLL_REG_W(pll_base, HDMI_PHY_REG_1, 0xf2); - - udelay(10); - - MDSS_PLL_REG_W(pll_base, HDMI_PHY_REG_2, 0x1f); - - val = MDSS_PLL_REG_R(pll_base, HDMI_PHY_REG_12); - val |= BIT(5); - /* Assert PHY S/W reset */ - MDSS_PLL_REG_W(pll_base, HDMI_PHY_REG_12, val); - val &= ~BIT(5); - udelay(10); - /* De-assert PHY S/W reset */ - MDSS_PLL_REG_W(pll_base, HDMI_PHY_REG_12, val); - - val = MDSS_PLL_REG_R(pll_base, HDMI_PHY_REG_12); - val |= PWRDN_B; - MDSS_PLL_REG_W(pll_base, HDMI_PHY_REG_12, val); - - /* Wait 10 us for enabling global power for PHY */ - wmb(); - udelay(10); - - MDSS_PLL_REG_W(pll_base, HDMI_PHY_REG_3, 0x20); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_REG_4, 0x10); - - val = MDSS_PLL_REG_R(pll_base, HDMI_PHY_PLL_PWRDN_B); - val |= PLL_PWRDN_B; - val |= REG_VTEST_EN; - val &= ~PD_PLL; - val |= PD_PLL_REG; - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_PWRDN_B, val); - - MDSS_PLL_REG_W(pll_base, HDMI_PHY_REG_2, 0x81); - - do { - if (!hdmi_pll_lock_status(hdmi_pll_res)) { - /* PLL has still not locked. - * Do a software reset and try again - * Assert PLL S/W reset first - */ - MDSS_PLL_REG_W(pll_base, - HDMI_PHY_PLL_LOCKDET_CFG2, 0x8d); - - /* Wait for a short time before de-asserting - * to allow the hardware to complete its job. - * This much of delay should be fine for hardware - * to assert and de-assert. - */ - udelay(10); - MDSS_PLL_REG_W(pll_base, - HDMI_PHY_PLL_LOCKDET_CFG2, 0xd); - - /* Wait for a short duration for the PLL calibration - * before checking if the PLL gets locked - */ - udelay(350); - } else { - pr_debug("HDMI PLL locked\n"); - break; - } - - } while (--pll_lock_retry); - - if (!pll_lock_retry) { - pr_err("HDMI PLL not locked\n"); - hdmi_pll_disable_28lpm(hw); - return -EAGAIN; - } - - return 0; -} /* hdmi_pll_enable_28lpm */ - -static void hdmi_phy_pll_calculator_28lpm(unsigned long vco_rate, - struct mdss_pll_resources *hdmi_pll_res) -{ - u32 ref_clk = 19200000; - u32 integer_mode = 0; - u32 ref_clk_multiplier = integer_mode == 0 ? 2 : 1; - u32 int_ref_clk_freq = ref_clk * ref_clk_multiplier; - u32 refclk_cfg = 0; - u32 ten_power_six = 1000000; - u64 multiplier_q = 0; - u64 multiplier_r = 0; - u32 lf_cfg0 = 0; - u32 lf_cfg1 = 0; - u64 vco_cfg0 = 0; - u64 vco_cfg4 = 0; - u64 sdm_cfg0 = 0; - u64 sdm_cfg1 = 0; - u64 sdm_cfg2 = 0; - u32 val1 = 0; - u32 val2 = 0; - u32 val3 = 0; - void __iomem *pll_base = hdmi_pll_res->pll_base; - - multiplier_q = vco_rate; - multiplier_r = do_div(multiplier_q, int_ref_clk_freq); - - lf_cfg0 = multiplier_q > 30 ? 0 : (multiplier_q > 16 ? 16 : 32); - lf_cfg0 += integer_mode; - - lf_cfg1 = multiplier_q > 30 ? 0xc3 : (multiplier_q > 16 ? 0xbb : 0xf9); - - vco_cfg0 = vco_rate / ten_power_six; - vco_cfg4 = ((ref_clk * 5) / ten_power_six) - 1; - - sdm_cfg0 = (integer_mode * 64) + multiplier_q - 1; - sdm_cfg1 = 64 + multiplier_q - 1; - - sdm_cfg2 = (multiplier_r) * 65536; - do_div(sdm_cfg2, int_ref_clk_freq); - - pr_debug("lf_cfg0 = 0x%x lf_cfg1 = 0x%x\n", lf_cfg0, lf_cfg1); - pr_debug("vco_cfg0 = 0x%llx vco_cfg4 = 0x%llx\n", vco_cfg0, vco_cfg4); - pr_debug("sdm_cfg0 = 0x%llx sdm_cfg1 = 0x%llx sdm_cfg2 = 0x%llx\n", - sdm_cfg0, sdm_cfg1, sdm_cfg2); - - refclk_cfg = MDSS_PLL_REG_R(pll_base, HDMI_PHY_PLL_REFCLK_CFG); - refclk_cfg &= ~0xf; - refclk_cfg |= (ref_clk_multiplier == 2) ? 0x8 - : (ref_clk_multiplier == 1) ? 0 : 0x2; - - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_REFCLK_CFG, refclk_cfg); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_CHRG_PUMP_CFG, 0x02); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_LOOP_FLT_CFG0, lf_cfg0); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_LOOP_FLT_CFG1, lf_cfg1); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_IDAC_ADJ_CFG, 0x2c); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_I_VI_KVCO_CFG, 0x06); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_PWRDN_B, 0x0a); - - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_SDM_CFG0, sdm_cfg0); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_SDM_CFG1, sdm_cfg1); - - val1 = sdm_cfg2 & 0xff; - val2 = (sdm_cfg2 >> 8) & 0xff; - val3 = (sdm_cfg2 >> 16) & 0xff; - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_SDM_CFG2, val1); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_SDM_CFG3, val2); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_SDM_CFG4, val3); - - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_SSC_CFG0, 0x9a); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_SSC_CFG1, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_SSC_CFG2, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_SSC_CFG3, 0x00); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_LOCKDET_CFG0, 0x10); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_LOCKDET_CFG1, 0x1a); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_LOCKDET_CFG2, 0x0d); - - val1 = vco_cfg0 & 0xff; - val2 = (vco_cfg0 >> 8) & 0xff; - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_VCOCAL_CFG0, val1); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_VCOCAL_CFG1, val2); - - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_VCOCAL_CFG2, 0x3b); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_VCOCAL_CFG3, 0x00); - - val1 = vco_cfg4 & 0xff; - val2 = (vco_cfg4 >> 8) & 0xff; - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_VCOCAL_CFG4, val1); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_VCOCAL_CFG5, val2); - - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_VCOCAL_CFG6, 0x33); - MDSS_PLL_REG_W(pll_base, HDMI_PHY_PLL_VCOCAL_CFG7, 0x03); - -} - -int hdmi_vco_set_rate_28lpm(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk_hw(hw); - struct mdss_pll_resources *hdmi_pll_res = vco->priv; - void __iomem *pll_base; - int rc; - - rc = mdss_pll_resource_enable(hdmi_pll_res, true); - if (rc) { - pr_err("pll resource can't be enabled\n"); - return rc; - } - - if (hdmi_pll_res->pll_on) - return 0; - - pll_base = hdmi_pll_res->pll_base; - - pr_debug("rate=%ld\n", rate); - - hdmi_phy_pll_calculator_28lpm(rate, hdmi_pll_res); - - /* Make sure writes complete before disabling iface clock */ - wmb(); - - vco->rate = rate; - hdmi_pll_res->vco_current_rate = rate; - - mdss_pll_resource_enable(hdmi_pll_res, false); - - - return 0; -} /* hdmi_pll_set_rate */ - -static unsigned long hdmi_vco_get_rate(struct hdmi_pll_vco_clk *vco) -{ - unsigned long freq = 0; - int rc = 0; - struct mdss_pll_resources *hdmi_pll_res = vco->priv; - - rc = mdss_pll_resource_enable(hdmi_pll_res, true); - if (rc) { - pr_err("Failed to enable hdmi pll resources\n"); - return 0; - } - - freq = MDSS_PLL_REG_R(hdmi_pll_res->pll_base, - HDMI_PHY_PLL_VCOCAL_CFG1) << 8 | - MDSS_PLL_REG_R(hdmi_pll_res->pll_base, - HDMI_PHY_PLL_VCOCAL_CFG0); - - switch (freq) { - case 742: - freq = 742500000; - break; - case 810: - if (MDSS_PLL_REG_R(hdmi_pll_res->pll_base, - HDMI_PHY_PLL_SDM_CFG3) == 0x18) - freq = 810000000; - else - freq = 810900000; - break; - case 1342: - freq = 1342500000; - break; - default: - freq *= 1000000; - } - mdss_pll_resource_enable(hdmi_pll_res, false); - - return freq; -} - -long hdmi_vco_round_rate_28lpm(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - unsigned long rrate = rate; - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk_hw(hw); - - if (rate < vco->min_rate) - rrate = vco->min_rate; - if (rate > vco->max_rate) - rrate = vco->max_rate; - - *parent_rate = rrate; - pr_debug("rrate=%ld\n", rrate); - - return rrate; -} - -int hdmi_vco_prepare_28lpm(struct clk_hw *hw) -{ - int rc = 0; - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk_hw(hw); - struct mdss_pll_resources *hdmi_res = vco->priv; - - pr_debug("rate=%ld\n", clk_hw_get_rate(hw)); - rc = mdss_pll_resource_enable(hdmi_res, true); - if (rc) { - pr_err("Failed to enable mdss HDMI pll resources\n"); - goto error; - } - - if ((hdmi_res->vco_cached_rate != 0) - && (hdmi_res->vco_cached_rate == clk_hw_get_rate(hw))) { - rc = vco->hw.init->ops->set_rate(hw, - hdmi_res->vco_cached_rate, hdmi_res->vco_cached_rate); - if (rc) { - pr_err("index=%d vco_set_rate failed. rc=%d\n", - rc, hdmi_res->index); - mdss_pll_resource_enable(hdmi_res, false); - goto error; - } - } - - rc = hdmi_pll_enable_28lpm(hw); - if (rc) { - mdss_pll_resource_enable(hdmi_res, false); - pr_err("ndx=%d failed to enable hdmi pll\n", - hdmi_res->index); - goto error; - } - - mdss_pll_resource_enable(hdmi_res, false); - pr_debug("HDMI PLL enabled\n"); -error: - return rc; -} - -void hdmi_vco_unprepare_28lpm(struct clk_hw *hw) -{ - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk_hw(hw); - struct mdss_pll_resources *hdmi_res = vco->priv; - - if (!hdmi_res) { - pr_err("Invalid input parameter\n"); - return; - } - - if (!hdmi_res->pll_on && - mdss_pll_resource_enable(hdmi_res, true)) { - pr_err("pll resource can't be enabled\n"); - return; - } - - hdmi_res->vco_cached_rate = clk_hw_get_rate(hw); - hdmi_pll_disable_28lpm(hw); - - hdmi_res->handoff_resources = false; - mdss_pll_resource_enable(hdmi_res, false); - hdmi_res->pll_on = false; - - pr_debug("HDMI PLL disabled\n"); -} - - -unsigned long hdmi_vco_recalc_rate_28lpm(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk_hw(hw); - struct mdss_pll_resources *hdmi_pll_res = vco->priv; - u64 vco_rate = 0; - - if (!hdmi_pll_res) { - pr_err("dsi pll resources not available\n"); - return 0; - } - - if (hdmi_pll_res->vco_current_rate) { - vco_rate = (unsigned long)hdmi_pll_res->vco_current_rate; - pr_debug("vco_rate=%lld\n", vco_rate); - return vco_rate; - } - - if (is_gdsc_disabled(hdmi_pll_res)) - return 0; - - if (mdss_pll_resource_enable(hdmi_pll_res, true)) { - pr_err("Failed to enable hdmi pll resources\n"); - return 0; - } - - if (hdmi_pll_lock_status(hdmi_pll_res)) { - hdmi_pll_res->handoff_resources = true; - hdmi_pll_res->pll_on = true; - vco_rate = hdmi_vco_get_rate(vco); - } else { - hdmi_pll_res->handoff_resources = false; - mdss_pll_resource_enable(hdmi_pll_res, false); - } - - pr_debug("vco_rate = %lld\n", vco_rate); - - return (unsigned long)vco_rate; -} - -static int hdmi_mux_set_parent(void *context, unsigned int reg, - unsigned int mux_sel) -{ - struct mdss_pll_resources *hdmi_pll_res = context; - int rc = 0; - u32 reg_val = 0; - const u32 div_4 = 0x20; - const u32 div_6 = 0x30; - - rc = mdss_pll_resource_enable(hdmi_pll_res, true); - if (rc) { - pr_err("Failed to enable hdmi pll resources\n"); - return rc; - } - - /* - * divsel_six is preferred over divsel_four to keep - * vco range within goal limits to maintain margin. - * To achieve this, its precedence order is toggled - * at mux level. So reverse toggle the mux_sel value - * here. - */ - switch (mux_sel) { - case 0x20: /* intended divider is divsel_six */ - mux_sel = div_6; - break; - case 0x30: /* intended divider is divsel_four */ - mux_sel = div_4; - break; - } - pr_debug("mux_sel = %d\n", mux_sel); - - reg_val = MDSS_PLL_REG_R(hdmi_pll_res->pll_base, - HDMI_PHY_PLL_REFCLK_CFG); - reg_val &= ~0x70; - reg_val |= (mux_sel & 0x70); - pr_debug("pll_refclk_cfg = 0x%x\n", reg_val); - MDSS_PLL_REG_W(hdmi_pll_res->pll_base, - HDMI_PHY_PLL_REFCLK_CFG, reg_val); - - (void)mdss_pll_resource_enable(hdmi_pll_res, false); - - return 0; -} - -static int hdmi_mux_get_parent(void *context, unsigned int reg, - unsigned int *val) -{ - int rc = 0; - int mux_sel = 0; - struct mdss_pll_resources *hdmi_pll_res = context; - - rc = mdss_pll_resource_enable(hdmi_pll_res, true); - if (rc) { - *val = 0; - pr_err("Failed to enable hdmi pll resources\n"); - } else { - mux_sel = MDSS_PLL_REG_R(hdmi_pll_res->pll_base, - HDMI_PHY_PLL_REFCLK_CFG); - mux_sel &= 0x70; - *val = mux_sel; - pr_debug("mux_sel = %d\n", *val); - } - - (void)mdss_pll_resource_enable(hdmi_pll_res, false); - - return rc; -} - -static struct regmap_config hdmi_pll_28lpm_cfg = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x49c, -}; - -static struct regmap_bus hdmi_pclk_src_mux_regmap_ops = { - .reg_write = hdmi_mux_set_parent, - .reg_read = hdmi_mux_get_parent, -}; - -/* Op structures */ -static const struct clk_ops hdmi_28lpm_vco_clk_ops = { - .recalc_rate = hdmi_vco_recalc_rate_28lpm, - .set_rate = hdmi_vco_set_rate_28lpm, - .round_rate = hdmi_vco_round_rate_28lpm, - .prepare = hdmi_vco_prepare_28lpm, - .unprepare = hdmi_vco_unprepare_28lpm, -}; - -static struct hdmi_pll_vco_clk hdmi_vco_clk = { - .min_rate = 540000000, - .max_rate = 1125000000, - .hw.init = &(struct clk_init_data){ - .name = "hdmi_vco_clk", - .parent_names = (const char *[]){ "cxo" }, - .num_parents = 1, - .ops = &hdmi_28lpm_vco_clk_ops, - }, -}; - -static struct clk_fixed_factor hdmi_vco_divsel_one_clk_src = { - .div = 1, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "hdmi_vco_divsel_one_clk_src", - .parent_names = - (const char *[]){ "hdmi_vco_clk" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor hdmi_vco_divsel_two_clk_src = { - .div = 2, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "hdmi_vco_divsel_two_clk_src", - .parent_names = - (const char *[]){ "hdmi_vco_clk" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor hdmi_vco_divsel_four_clk_src = { - .div = 4, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "hdmi_vco_divsel_four_clk_src", - .parent_names = - (const char *[]){ "hdmi_vco_clk" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_fixed_factor hdmi_vco_divsel_six_clk_src = { - .div = 6, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "hdmi_vco_divsel_six_clk_src", - .parent_names = - (const char *[]){ "hdmi_vco_clk" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_regmap_mux hdmi_pclk_src_mux = { - .reg = HDMI_PHY_PLL_REFCLK_CFG, - .shift = 4, - .width = 2, - - .clkr = { - .hw.init = &(struct clk_init_data){ - .name = "hdmi_pclk_src_mux", - .parent_names = - (const char *[]){"hdmi_vco_divsel_one_clk_src", - "hdmi_vco_divsel_two_clk_src", - "hdmi_vco_divsel_six_clk_src", - "hdmi_vco_divsel_four_clk_src"}, - .num_parents = 4, - .ops = &clk_regmap_mux_closest_ops, - .flags = CLK_SET_RATE_PARENT, - }, - }, -}; - -static struct clk_fixed_factor hdmi_pclk_src = { - .div = 5, - .mult = 1, - - .hw.init = &(struct clk_init_data){ - .name = "hdmi_phy_pll_clk", - .parent_names = - (const char *[]){ "hdmi_pclk_src_mux" }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_fixed_factor_ops, - }, -}; - -static struct clk_hw *mdss_hdmi_pllcc_28lpm[] = { - [HDMI_VCO_CLK] = &hdmi_vco_clk.hw, - [HDMI_VCO_DIVIDED_1_CLK_SRC] = &hdmi_vco_divsel_one_clk_src.hw, - [HDMI_VCO_DIVIDED_TWO_CLK_SRC] = &hdmi_vco_divsel_two_clk_src.hw, - [HDMI_VCO_DIVIDED_FOUR_CLK_SRC] = &hdmi_vco_divsel_four_clk_src.hw, - [HDMI_VCO_DIVIDED_SIX_CLK_SRC] = &hdmi_vco_divsel_six_clk_src.hw, - [HDMI_PCLK_SRC_MUX] = &hdmi_pclk_src_mux.clkr.hw, - [HDMI_PCLK_SRC] = &hdmi_pclk_src.hw, -}; - -int hdmi_pll_clock_register_28lpm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int rc = -ENOTSUPP, i; - struct clk *clk; - struct clk_onecell_data *clk_data; - int num_clks = ARRAY_SIZE(mdss_hdmi_pllcc_28lpm); - struct regmap *regmap; - - if (!pdev || !pdev->dev.of_node || - !pll_res || !pll_res->pll_base) { - pr_err("Invalid input parameters\n"); - return -EPROBE_DEFER; - } - - clk_data = devm_kzalloc(&pdev->dev, sizeof(struct clk_onecell_data), - GFP_KERNEL); - if (!clk_data) - return -ENOMEM; - - clk_data->clks = devm_kzalloc(&pdev->dev, (num_clks * - sizeof(struct clk *)), GFP_KERNEL); - if (!clk_data->clks) { - devm_kfree(&pdev->dev, clk_data); - return -ENOMEM; - } - clk_data->clk_num = num_clks; - - /* Set client data for vco, mux and div clocks */ - regmap = devm_regmap_init(&pdev->dev, &hdmi_pclk_src_mux_regmap_ops, - pll_res, &hdmi_pll_28lpm_cfg); - hdmi_pclk_src_mux.clkr.regmap = regmap; - - hdmi_vco_clk.priv = pll_res; - - for (i = HDMI_VCO_CLK; i <= HDMI_PCLK_SRC; i++) { - pr_debug("reg clk: %d index: %d\n", i, pll_res->index); - clk = devm_clk_register(&pdev->dev, - mdss_hdmi_pllcc_28lpm[i]); - if (IS_ERR(clk)) { - pr_err("clk registration failed for HDMI: %d\n", - pll_res->index); - rc = -EINVAL; - goto clk_reg_fail; - } - clk_data->clks[i] = clk; - } - - rc = of_clk_add_provider(pdev->dev.of_node, - of_clk_src_onecell_get, clk_data); - if (rc) { - pr_err("%s: Clock register failed rc=%d\n", __func__, rc); - rc = -EPROBE_DEFER; - } else { - pr_debug("%s SUCCESS\n", __func__); - rc = 0; - } - return rc; -clk_reg_fail: - return rc; -} diff --git a/drivers/clk/qcom/mdss/mdss-hdmi-pll-8996.c b/drivers/clk/qcom/mdss/mdss-hdmi-pll-8996.c deleted file mode 100644 index 27fd3153104cb5f273ff5c40c61a8edfeb62e8a0..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-hdmi-pll-8996.c +++ /dev/null @@ -1,2675 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mdss-pll.h" -#include "mdss-hdmi-pll.h" - -/* CONSTANTS */ -#define HDMI_BIT_CLK_TO_PIX_CLK_RATIO 10 -#define HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD 3400000000UL -#define HDMI_DIG_FREQ_BIT_CLK_THRESHOLD 1500000000UL -#define HDMI_MID_FREQ_BIT_CLK_THRESHOLD 750000000 -#define HDMI_CLKS_PLL_DIVSEL 0 -#define HDMI_CORECLK_DIV 5 -#define HDMI_REF_CLOCK 19200000 -#define HDMI_64B_ERR_VAL 0xFFFFFFFFFFFFFFFF -#define HDMI_VERSION_8996_V1 1 -#define HDMI_VERSION_8996_V2 2 -#define HDMI_VERSION_8996_V3 3 -#define HDMI_VERSION_8996_V3_1_8 4 - -#define HDMI_VCO_MAX_FREQ 12000000000 -#define HDMI_VCO_MIN_FREQ 8000000000 -#define HDMI_2400MHZ_BIT_CLK_HZ 2400000000UL -#define HDMI_2250MHZ_BIT_CLK_HZ 2250000000UL -#define HDMI_2000MHZ_BIT_CLK_HZ 2000000000UL -#define HDMI_1700MHZ_BIT_CLK_HZ 1700000000UL -#define HDMI_1200MHZ_BIT_CLK_HZ 1200000000UL -#define HDMI_1334MHZ_BIT_CLK_HZ 1334000000UL -#define HDMI_1000MHZ_BIT_CLK_HZ 1000000000UL -#define HDMI_850MHZ_BIT_CLK_HZ 850000000 -#define HDMI_667MHZ_BIT_CLK_HZ 667000000 -#define HDMI_600MHZ_BIT_CLK_HZ 600000000 -#define HDMI_500MHZ_BIT_CLK_HZ 500000000 -#define HDMI_450MHZ_BIT_CLK_HZ 450000000 -#define HDMI_334MHZ_BIT_CLK_HZ 334000000 -#define HDMI_300MHZ_BIT_CLK_HZ 300000000 -#define HDMI_282MHZ_BIT_CLK_HZ 282000000 -#define HDMI_250MHZ_BIT_CLK_HZ 250000000 -#define HDMI_KHZ_TO_HZ 1000 - -/* PLL REGISTERS */ -#define QSERDES_COM_ATB_SEL1 (0x000) -#define QSERDES_COM_ATB_SEL2 (0x004) -#define QSERDES_COM_FREQ_UPDATE (0x008) -#define QSERDES_COM_BG_TIMER (0x00C) -#define QSERDES_COM_SSC_EN_CENTER (0x010) -#define QSERDES_COM_SSC_ADJ_PER1 (0x014) -#define QSERDES_COM_SSC_ADJ_PER2 (0x018) -#define QSERDES_COM_SSC_PER1 (0x01C) -#define QSERDES_COM_SSC_PER2 (0x020) -#define QSERDES_COM_SSC_STEP_SIZE1 (0x024) -#define QSERDES_COM_SSC_STEP_SIZE2 (0x028) -#define QSERDES_COM_POST_DIV (0x02C) -#define QSERDES_COM_POST_DIV_MUX (0x030) -#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN (0x034) -#define QSERDES_COM_CLK_ENABLE1 (0x038) -#define QSERDES_COM_SYS_CLK_CTRL (0x03C) -#define QSERDES_COM_SYSCLK_BUF_ENABLE (0x040) -#define QSERDES_COM_PLL_EN (0x044) -#define QSERDES_COM_PLL_IVCO (0x048) -#define QSERDES_COM_LOCK_CMP1_MODE0 (0x04C) -#define QSERDES_COM_LOCK_CMP2_MODE0 (0x050) -#define QSERDES_COM_LOCK_CMP3_MODE0 (0x054) -#define QSERDES_COM_LOCK_CMP1_MODE1 (0x058) -#define QSERDES_COM_LOCK_CMP2_MODE1 (0x05C) -#define QSERDES_COM_LOCK_CMP3_MODE1 (0x060) -#define QSERDES_COM_LOCK_CMP1_MODE2 (0x064) -#define QSERDES_COM_CMN_RSVD0 (0x064) -#define QSERDES_COM_LOCK_CMP2_MODE2 (0x068) -#define QSERDES_COM_EP_CLOCK_DETECT_CTRL (0x068) -#define QSERDES_COM_LOCK_CMP3_MODE2 (0x06C) -#define QSERDES_COM_SYSCLK_DET_COMP_STATUS (0x06C) -#define QSERDES_COM_BG_TRIM (0x070) -#define QSERDES_COM_CLK_EP_DIV (0x074) -#define QSERDES_COM_CP_CTRL_MODE0 (0x078) -#define QSERDES_COM_CP_CTRL_MODE1 (0x07C) -#define QSERDES_COM_CP_CTRL_MODE2 (0x080) -#define QSERDES_COM_CMN_RSVD1 (0x080) -#define QSERDES_COM_PLL_RCTRL_MODE0 (0x084) -#define QSERDES_COM_PLL_RCTRL_MODE1 (0x088) -#define QSERDES_COM_PLL_RCTRL_MODE2 (0x08C) -#define QSERDES_COM_CMN_RSVD2 (0x08C) -#define QSERDES_COM_PLL_CCTRL_MODE0 (0x090) -#define QSERDES_COM_PLL_CCTRL_MODE1 (0x094) -#define QSERDES_COM_PLL_CCTRL_MODE2 (0x098) -#define QSERDES_COM_CMN_RSVD3 (0x098) -#define QSERDES_COM_PLL_CNTRL (0x09C) -#define QSERDES_COM_PHASE_SEL_CTRL (0x0A0) -#define QSERDES_COM_PHASE_SEL_DC (0x0A4) -#define QSERDES_COM_CORE_CLK_IN_SYNC_SEL (0x0A8) -#define QSERDES_COM_BIAS_EN_CTRL_BY_PSM (0x0A8) -#define QSERDES_COM_SYSCLK_EN_SEL (0x0AC) -#define QSERDES_COM_CML_SYSCLK_SEL (0x0B0) -#define QSERDES_COM_RESETSM_CNTRL (0x0B4) -#define QSERDES_COM_RESETSM_CNTRL2 (0x0B8) -#define QSERDES_COM_RESTRIM_CTRL (0x0BC) -#define QSERDES_COM_RESTRIM_CTRL2 (0x0C0) -#define QSERDES_COM_RESCODE_DIV_NUM (0x0C4) -#define QSERDES_COM_LOCK_CMP_EN (0x0C8) -#define QSERDES_COM_LOCK_CMP_CFG (0x0CC) -#define QSERDES_COM_DEC_START_MODE0 (0x0D0) -#define QSERDES_COM_DEC_START_MODE1 (0x0D4) -#define QSERDES_COM_DEC_START_MODE2 (0x0D8) -#define QSERDES_COM_VCOCAL_DEADMAN_CTRL (0x0D8) -#define QSERDES_COM_DIV_FRAC_START1_MODE0 (0x0DC) -#define QSERDES_COM_DIV_FRAC_START2_MODE0 (0x0E0) -#define QSERDES_COM_DIV_FRAC_START3_MODE0 (0x0E4) -#define QSERDES_COM_DIV_FRAC_START1_MODE1 (0x0E8) -#define QSERDES_COM_DIV_FRAC_START2_MODE1 (0x0EC) -#define QSERDES_COM_DIV_FRAC_START3_MODE1 (0x0F0) -#define QSERDES_COM_DIV_FRAC_START1_MODE2 (0x0F4) -#define QSERDES_COM_VCO_TUNE_MINVAL1 (0x0F4) -#define QSERDES_COM_DIV_FRAC_START2_MODE2 (0x0F8) -#define QSERDES_COM_VCO_TUNE_MINVAL2 (0x0F8) -#define QSERDES_COM_DIV_FRAC_START3_MODE2 (0x0FC) -#define QSERDES_COM_CMN_RSVD4 (0x0FC) -#define QSERDES_COM_INTEGLOOP_INITVAL (0x100) -#define QSERDES_COM_INTEGLOOP_EN (0x104) -#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0 (0x108) -#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0 (0x10C) -#define QSERDES_COM_INTEGLOOP_GAIN0_MODE1 (0x110) -#define QSERDES_COM_INTEGLOOP_GAIN1_MODE1 (0x114) -#define QSERDES_COM_INTEGLOOP_GAIN0_MODE2 (0x118) -#define QSERDES_COM_VCO_TUNE_MAXVAL1 (0x118) -#define QSERDES_COM_INTEGLOOP_GAIN1_MODE2 (0x11C) -#define QSERDES_COM_VCO_TUNE_MAXVAL2 (0x11C) -#define QSERDES_COM_RES_TRIM_CONTROL2 (0x120) -#define QSERDES_COM_VCO_TUNE_CTRL (0x124) -#define QSERDES_COM_VCO_TUNE_MAP (0x128) -#define QSERDES_COM_VCO_TUNE1_MODE0 (0x12C) -#define QSERDES_COM_VCO_TUNE2_MODE0 (0x130) -#define QSERDES_COM_VCO_TUNE1_MODE1 (0x134) -#define QSERDES_COM_VCO_TUNE2_MODE1 (0x138) -#define QSERDES_COM_VCO_TUNE1_MODE2 (0x13C) -#define QSERDES_COM_VCO_TUNE_INITVAL1 (0x13C) -#define QSERDES_COM_VCO_TUNE2_MODE2 (0x140) -#define QSERDES_COM_VCO_TUNE_INITVAL2 (0x140) -#define QSERDES_COM_VCO_TUNE_TIMER1 (0x144) -#define QSERDES_COM_VCO_TUNE_TIMER2 (0x148) -#define QSERDES_COM_SAR (0x14C) -#define QSERDES_COM_SAR_CLK (0x150) -#define QSERDES_COM_SAR_CODE_OUT_STATUS (0x154) -#define QSERDES_COM_SAR_CODE_READY_STATUS (0x158) -#define QSERDES_COM_CMN_STATUS (0x15C) -#define QSERDES_COM_RESET_SM_STATUS (0x160) -#define QSERDES_COM_RESTRIM_CODE_STATUS (0x164) -#define QSERDES_COM_PLLCAL_CODE1_STATUS (0x168) -#define QSERDES_COM_PLLCAL_CODE2_STATUS (0x16C) -#define QSERDES_COM_BG_CTRL (0x170) -#define QSERDES_COM_CLK_SELECT (0x174) -#define QSERDES_COM_HSCLK_SEL (0x178) -#define QSERDES_COM_INTEGLOOP_BINCODE_STATUS (0x17C) -#define QSERDES_COM_PLL_ANALOG (0x180) -#define QSERDES_COM_CORECLK_DIV (0x184) -#define QSERDES_COM_SW_RESET (0x188) -#define QSERDES_COM_CORE_CLK_EN (0x18C) -#define QSERDES_COM_C_READY_STATUS (0x190) -#define QSERDES_COM_CMN_CONFIG (0x194) -#define QSERDES_COM_CMN_RATE_OVERRIDE (0x198) -#define QSERDES_COM_SVS_MODE_CLK_SEL (0x19C) -#define QSERDES_COM_DEBUG_BUS0 (0x1A0) -#define QSERDES_COM_DEBUG_BUS1 (0x1A4) -#define QSERDES_COM_DEBUG_BUS2 (0x1A8) -#define QSERDES_COM_DEBUG_BUS3 (0x1AC) -#define QSERDES_COM_DEBUG_BUS_SEL (0x1B0) -#define QSERDES_COM_CMN_MISC1 (0x1B4) -#define QSERDES_COM_CMN_MISC2 (0x1B8) -#define QSERDES_COM_CORECLK_DIV_MODE1 (0x1BC) -#define QSERDES_COM_CORECLK_DIV_MODE2 (0x1C0) -#define QSERDES_COM_CMN_RSVD5 (0x1C0) - -/* Tx Channel base addresses */ -#define HDMI_TX_L0_BASE_OFFSET (0x400) -#define HDMI_TX_L1_BASE_OFFSET (0x600) -#define HDMI_TX_L2_BASE_OFFSET (0x800) -#define HDMI_TX_L3_BASE_OFFSET (0xA00) - -/* Tx Channel PHY registers */ -#define QSERDES_TX_L0_BIST_MODE_LANENO (0x000) -#define QSERDES_TX_L0_BIST_INVERT (0x004) -#define QSERDES_TX_L0_CLKBUF_ENABLE (0x008) -#define QSERDES_TX_L0_CMN_CONTROL_ONE (0x00C) -#define QSERDES_TX_L0_CMN_CONTROL_TWO (0x010) -#define QSERDES_TX_L0_CMN_CONTROL_THREE (0x014) -#define QSERDES_TX_L0_TX_EMP_POST1_LVL (0x018) -#define QSERDES_TX_L0_TX_POST2_EMPH (0x01C) -#define QSERDES_TX_L0_TX_BOOST_LVL_UP_DN (0x020) -#define QSERDES_TX_L0_HP_PD_ENABLES (0x024) -#define QSERDES_TX_L0_TX_IDLE_LVL_LARGE_AMP (0x028) -#define QSERDES_TX_L0_TX_DRV_LVL (0x02C) -#define QSERDES_TX_L0_TX_DRV_LVL_OFFSET (0x030) -#define QSERDES_TX_L0_RESET_TSYNC_EN (0x034) -#define QSERDES_TX_L0_PRE_STALL_LDO_BOOST_EN (0x038) -#define QSERDES_TX_L0_TX_BAND (0x03C) -#define QSERDES_TX_L0_SLEW_CNTL (0x040) -#define QSERDES_TX_L0_INTERFACE_SELECT (0x044) -#define QSERDES_TX_L0_LPB_EN (0x048) -#define QSERDES_TX_L0_RES_CODE_LANE_TX (0x04C) -#define QSERDES_TX_L0_RES_CODE_LANE_RX (0x050) -#define QSERDES_TX_L0_RES_CODE_LANE_OFFSET (0x054) -#define QSERDES_TX_L0_PERL_LENGTH1 (0x058) -#define QSERDES_TX_L0_PERL_LENGTH2 (0x05C) -#define QSERDES_TX_L0_SERDES_BYP_EN_OUT (0x060) -#define QSERDES_TX_L0_DEBUG_BUS_SEL (0x064) -#define QSERDES_TX_L0_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN (0x068) -#define QSERDES_TX_L0_TX_POL_INV (0x06C) -#define QSERDES_TX_L0_PARRATE_REC_DETECT_IDLE_EN (0x070) -#define QSERDES_TX_L0_BIST_PATTERN1 (0x074) -#define QSERDES_TX_L0_BIST_PATTERN2 (0x078) -#define QSERDES_TX_L0_BIST_PATTERN3 (0x07C) -#define QSERDES_TX_L0_BIST_PATTERN4 (0x080) -#define QSERDES_TX_L0_BIST_PATTERN5 (0x084) -#define QSERDES_TX_L0_BIST_PATTERN6 (0x088) -#define QSERDES_TX_L0_BIST_PATTERN7 (0x08C) -#define QSERDES_TX_L0_BIST_PATTERN8 (0x090) -#define QSERDES_TX_L0_LANE_MODE (0x094) -#define QSERDES_TX_L0_IDAC_CAL_LANE_MODE (0x098) -#define QSERDES_TX_L0_IDAC_CAL_LANE_MODE_CONFIGURATION (0x09C) -#define QSERDES_TX_L0_ATB_SEL1 (0x0A0) -#define QSERDES_TX_L0_ATB_SEL2 (0x0A4) -#define QSERDES_TX_L0_RCV_DETECT_LVL (0x0A8) -#define QSERDES_TX_L0_RCV_DETECT_LVL_2 (0x0AC) -#define QSERDES_TX_L0_PRBS_SEED1 (0x0B0) -#define QSERDES_TX_L0_PRBS_SEED2 (0x0B4) -#define QSERDES_TX_L0_PRBS_SEED3 (0x0B8) -#define QSERDES_TX_L0_PRBS_SEED4 (0x0BC) -#define QSERDES_TX_L0_RESET_GEN (0x0C0) -#define QSERDES_TX_L0_RESET_GEN_MUXES (0x0C4) -#define QSERDES_TX_L0_TRAN_DRVR_EMP_EN (0x0C8) -#define QSERDES_TX_L0_TX_INTERFACE_MODE (0x0CC) -#define QSERDES_TX_L0_PWM_CTRL (0x0D0) -#define QSERDES_TX_L0_PWM_ENCODED_OR_DATA (0x0D4) -#define QSERDES_TX_L0_PWM_GEAR_1_DIVIDER_BAND2 (0x0D8) -#define QSERDES_TX_L0_PWM_GEAR_2_DIVIDER_BAND2 (0x0DC) -#define QSERDES_TX_L0_PWM_GEAR_3_DIVIDER_BAND2 (0x0E0) -#define QSERDES_TX_L0_PWM_GEAR_4_DIVIDER_BAND2 (0x0E4) -#define QSERDES_TX_L0_PWM_GEAR_1_DIVIDER_BAND0_1 (0x0E8) -#define QSERDES_TX_L0_PWM_GEAR_2_DIVIDER_BAND0_1 (0x0EC) -#define QSERDES_TX_L0_PWM_GEAR_3_DIVIDER_BAND0_1 (0x0F0) -#define QSERDES_TX_L0_PWM_GEAR_4_DIVIDER_BAND0_1 (0x0F4) -#define QSERDES_TX_L0_VMODE_CTRL1 (0x0F8) -#define QSERDES_TX_L0_VMODE_CTRL2 (0x0FC) -#define QSERDES_TX_L0_TX_ALOG_INTF_OBSV_CNTL (0x100) -#define QSERDES_TX_L0_BIST_STATUS (0x104) -#define QSERDES_TX_L0_BIST_ERROR_COUNT1 (0x108) -#define QSERDES_TX_L0_BIST_ERROR_COUNT2 (0x10C) -#define QSERDES_TX_L0_TX_ALOG_INTF_OBSV (0x110) - -/* HDMI PHY REGISTERS */ -#define HDMI_PHY_BASE_OFFSET (0xC00) - -#define HDMI_PHY_CFG (0x00) -#define HDMI_PHY_PD_CTL (0x04) -#define HDMI_PHY_MODE (0x08) -#define HDMI_PHY_MISR_CLEAR (0x0C) -#define HDMI_PHY_TX0_TX1_BIST_CFG0 (0x10) -#define HDMI_PHY_TX0_TX1_BIST_CFG1 (0x14) -#define HDMI_PHY_TX0_TX1_PRBS_SEED_BYTE0 (0x18) -#define HDMI_PHY_TX0_TX1_PRBS_SEED_BYTE1 (0x1C) -#define HDMI_PHY_TX0_TX1_BIST_PATTERN0 (0x20) -#define HDMI_PHY_TX0_TX1_BIST_PATTERN1 (0x24) -#define HDMI_PHY_TX2_TX3_BIST_CFG0 (0x28) -#define HDMI_PHY_TX2_TX3_BIST_CFG1 (0x2C) -#define HDMI_PHY_TX2_TX3_PRBS_SEED_BYTE0 (0x30) -#define HDMI_PHY_TX2_TX3_PRBS_SEED_BYTE1 (0x34) -#define HDMI_PHY_TX2_TX3_BIST_PATTERN0 (0x38) -#define HDMI_PHY_TX2_TX3_BIST_PATTERN1 (0x3C) -#define HDMI_PHY_DEBUG_BUS_SEL (0x40) -#define HDMI_PHY_TXCAL_CFG0 (0x44) -#define HDMI_PHY_TXCAL_CFG1 (0x48) -#define HDMI_PHY_TX0_TX1_LANE_CTL (0x4C) -#define HDMI_PHY_TX2_TX3_LANE_CTL (0x50) -#define HDMI_PHY_LANE_BIST_CONFIG (0x54) -#define HDMI_PHY_CLOCK (0x58) -#define HDMI_PHY_MISC1 (0x5C) -#define HDMI_PHY_MISC2 (0x60) -#define HDMI_PHY_TX0_TX1_BIST_STATUS0 (0x64) -#define HDMI_PHY_TX0_TX1_BIST_STATUS1 (0x68) -#define HDMI_PHY_TX0_TX1_BIST_STATUS2 (0x6C) -#define HDMI_PHY_TX2_TX3_BIST_STATUS0 (0x70) -#define HDMI_PHY_TX2_TX3_BIST_STATUS1 (0x74) -#define HDMI_PHY_TX2_TX3_BIST_STATUS2 (0x78) -#define HDMI_PHY_PRE_MISR_STATUS0 (0x7C) -#define HDMI_PHY_PRE_MISR_STATUS1 (0x80) -#define HDMI_PHY_PRE_MISR_STATUS2 (0x84) -#define HDMI_PHY_PRE_MISR_STATUS3 (0x88) -#define HDMI_PHY_POST_MISR_STATUS0 (0x8C) -#define HDMI_PHY_POST_MISR_STATUS1 (0x90) -#define HDMI_PHY_POST_MISR_STATUS2 (0x94) -#define HDMI_PHY_POST_MISR_STATUS3 (0x98) -#define HDMI_PHY_STATUS (0x9C) -#define HDMI_PHY_MISC3_STATUS (0xA0) -#define HDMI_PHY_MISC4_STATUS (0xA4) -#define HDMI_PHY_DEBUG_BUS0 (0xA8) -#define HDMI_PHY_DEBUG_BUS1 (0xAC) -#define HDMI_PHY_DEBUG_BUS2 (0xB0) -#define HDMI_PHY_DEBUG_BUS3 (0xB4) -#define HDMI_PHY_PHY_REVISION_ID0 (0xB8) -#define HDMI_PHY_PHY_REVISION_ID1 (0xBC) -#define HDMI_PHY_PHY_REVISION_ID2 (0xC0) -#define HDMI_PHY_PHY_REVISION_ID3 (0xC4) - -#define HDMI_PLL_POLL_MAX_READS 100 -#define HDMI_PLL_POLL_TIMEOUT_US 1500 - -enum hdmi_pll_freqs { - HDMI_PCLK_25200_KHZ, - HDMI_PCLK_27027_KHZ, - HDMI_PCLK_27000_KHZ, - HDMI_PCLK_74250_KHZ, - HDMI_PCLK_148500_KHZ, - HDMI_PCLK_154000_KHZ, - HDMI_PCLK_268500_KHZ, - HDMI_PCLK_297000_KHZ, - HDMI_PCLK_594000_KHZ, - HDMI_PCLK_MAX -}; - -struct hdmi_8996_phy_pll_reg_cfg { - u32 tx_l0_lane_mode; - u32 tx_l2_lane_mode; - u32 tx_l0_tx_band; - u32 tx_l1_tx_band; - u32 tx_l2_tx_band; - u32 tx_l3_tx_band; - u32 com_svs_mode_clk_sel; - u32 com_hsclk_sel; - u32 com_pll_cctrl_mode0; - u32 com_pll_rctrl_mode0; - u32 com_cp_ctrl_mode0; - u32 com_dec_start_mode0; - u32 com_div_frac_start1_mode0; - u32 com_div_frac_start2_mode0; - u32 com_div_frac_start3_mode0; - u32 com_integloop_gain0_mode0; - u32 com_integloop_gain1_mode0; - u32 com_lock_cmp_en; - u32 com_lock_cmp1_mode0; - u32 com_lock_cmp2_mode0; - u32 com_lock_cmp3_mode0; - u32 com_core_clk_en; - u32 com_coreclk_div; - u32 com_restrim_ctrl; - u32 com_vco_tune_ctrl; - - u32 tx_l0_tx_drv_lvl; - u32 tx_l0_tx_emp_post1_lvl; - u32 tx_l1_tx_drv_lvl; - u32 tx_l1_tx_emp_post1_lvl; - u32 tx_l2_tx_drv_lvl; - u32 tx_l2_tx_emp_post1_lvl; - u32 tx_l3_tx_drv_lvl; - u32 tx_l3_tx_emp_post1_lvl; - u32 tx_l0_vmode_ctrl1; - u32 tx_l0_vmode_ctrl2; - u32 tx_l1_vmode_ctrl1; - u32 tx_l1_vmode_ctrl2; - u32 tx_l2_vmode_ctrl1; - u32 tx_l2_vmode_ctrl2; - u32 tx_l3_vmode_ctrl1; - u32 tx_l3_vmode_ctrl2; - u32 tx_l0_res_code_lane_tx; - u32 tx_l1_res_code_lane_tx; - u32 tx_l2_res_code_lane_tx; - u32 tx_l3_res_code_lane_tx; - - u32 phy_mode; -}; - -struct hdmi_8996_v3_post_divider { - u64 vco_freq; - u64 hsclk_divsel; - u64 vco_ratio; - u64 tx_band_sel; - u64 half_rate_mode; -}; - -static inline struct hdmi_pll_vco_clk *to_hdmi_8996_vco_clk(struct clk *clk) -{ - return container_of(clk, struct hdmi_pll_vco_clk, c); -} - -static inline u64 hdmi_8996_v1_get_post_div_lt_2g(u64 bclk) -{ - if (bclk >= HDMI_2400MHZ_BIT_CLK_HZ) - return 2; - else if (bclk >= HDMI_1700MHZ_BIT_CLK_HZ) - return 3; - else if (bclk >= HDMI_1200MHZ_BIT_CLK_HZ) - return 4; - else if (bclk >= HDMI_850MHZ_BIT_CLK_HZ) - return 3; - else if (bclk >= HDMI_600MHZ_BIT_CLK_HZ) - return 4; - else if (bclk >= HDMI_450MHZ_BIT_CLK_HZ) - return 3; - else if (bclk >= HDMI_300MHZ_BIT_CLK_HZ) - return 4; - - return HDMI_64B_ERR_VAL; -} - -static inline u64 hdmi_8996_v2_get_post_div_lt_2g(u64 bclk, u64 vco_range) -{ - u64 hdmi_8ghz = vco_range; - u64 tmp_calc; - - hdmi_8ghz <<= 2; - tmp_calc = hdmi_8ghz; - do_div(tmp_calc, 6U); - - if (bclk >= vco_range) - return 2; - else if (bclk >= tmp_calc) - return 3; - else if (bclk >= vco_range >> 1) - return 4; - - tmp_calc = hdmi_8ghz; - do_div(tmp_calc, 12U); - if (bclk >= tmp_calc) - return 3; - else if (bclk >= vco_range >> 2) - return 4; - - tmp_calc = hdmi_8ghz; - do_div(tmp_calc, 24U); - if (bclk >= tmp_calc) - return 3; - else if (bclk >= vco_range >> 3) - return 4; - - return HDMI_64B_ERR_VAL; -} - -static inline u64 hdmi_8996_v2_get_post_div_gt_2g(u64 hsclk) -{ - if (hsclk >= 0 && hsclk <= 3) - return hsclk + 1; - - return HDMI_64B_ERR_VAL; -} - -static inline u64 hdmi_8996_get_coreclk_div_lt_2g(u64 bclk) -{ - if (bclk >= HDMI_1334MHZ_BIT_CLK_HZ) - return 1; - else if (bclk >= HDMI_1000MHZ_BIT_CLK_HZ) - return 1; - else if (bclk >= HDMI_667MHZ_BIT_CLK_HZ) - return 2; - else if (bclk >= HDMI_500MHZ_BIT_CLK_HZ) - return 2; - else if (bclk >= HDMI_334MHZ_BIT_CLK_HZ) - return 3; - else if (bclk >= HDMI_250MHZ_BIT_CLK_HZ) - return 3; - - return HDMI_64B_ERR_VAL; -} - -static inline u64 hdmi_8996_get_coreclk_div_ratio(u64 clks_pll_divsel, - u64 coreclk_div) -{ - if (clks_pll_divsel == 0) - return coreclk_div*2; - else if (clks_pll_divsel == 1) - return coreclk_div*4; - - return HDMI_64B_ERR_VAL; -} - -static inline u64 hdmi_8996_v1_get_tx_band(u64 bclk) -{ - if (bclk >= 2400000000UL) - return 0; - if (bclk >= 1200000000UL) - return 1; - if (bclk >= 600000000UL) - return 2; - if (bclk >= 300000000UL) - return 3; - - return HDMI_64B_ERR_VAL; -} - -static inline u64 hdmi_8996_v2_get_tx_band(u64 bclk, u64 vco_range) -{ - if (bclk >= vco_range) - return 0; - else if (bclk >= vco_range >> 1) - return 1; - else if (bclk >= vco_range >> 2) - return 2; - else if (bclk >= vco_range >> 3) - return 3; - - return HDMI_64B_ERR_VAL; -} - -static inline u64 hdmi_8996_v1_get_hsclk(u64 fdata) -{ - if (fdata >= 9600000000UL) - return 0; - else if (fdata >= 4800000000UL) - return 1; - else if (fdata >= 3200000000UL) - return 2; - else if (fdata >= 2400000000UL) - return 3; - - return HDMI_64B_ERR_VAL; -} - -static inline u64 hdmi_8996_v2_get_hsclk(u64 fdata, u64 vco_range) -{ - u64 tmp_calc = vco_range; - - tmp_calc <<= 2; - do_div(tmp_calc, 3U); - if (fdata >= (vco_range << 2)) - return 0; - else if (fdata >= (vco_range << 1)) - return 1; - else if (fdata >= tmp_calc) - return 2; - else if (fdata >= vco_range) - return 3; - - return HDMI_64B_ERR_VAL; - -} - -static inline u64 hdmi_8996_v2_get_vco_freq(u64 bclk, u64 vco_range) -{ - u64 tx_band_div_ratio = 1U << hdmi_8996_v2_get_tx_band(bclk, vco_range); - u64 pll_post_div_ratio; - - if (bclk >= vco_range) { - u64 hsclk = hdmi_8996_v2_get_hsclk(bclk, vco_range); - - pll_post_div_ratio = hdmi_8996_v2_get_post_div_gt_2g(hsclk); - } else { - pll_post_div_ratio = hdmi_8996_v2_get_post_div_lt_2g(bclk, - vco_range); - } - - return bclk * (pll_post_div_ratio * tx_band_div_ratio); -} - -static inline u64 hdmi_8996_v2_get_fdata(u64 bclk, u64 vco_range) -{ - if (bclk >= vco_range) - return bclk; - u64 tmp_calc = hdmi_8996_v2_get_vco_freq(bclk, vco_range); - u64 pll_post_div_ratio_lt_2g = hdmi_8996_v2_get_post_div_lt_2g( - bclk, vco_range); - if (pll_post_div_ratio_lt_2g == HDMI_64B_ERR_VAL) - return HDMI_64B_ERR_VAL; - - do_div(tmp_calc, pll_post_div_ratio_lt_2g); - return tmp_calc; -} - -static inline u64 hdmi_8996_get_cpctrl(u64 frac_start, bool gen_ssc) -{ - if ((frac_start != 0) || gen_ssc) - /* - * This should be ROUND(11/(19.2/20))). - * Since ref clock does not change, hardcoding to 11 - */ - return 0xB; - - return 0x23; -} - -static inline u64 hdmi_8996_get_rctrl(u64 frac_start, bool gen_ssc) -{ - if ((frac_start != 0) || gen_ssc) - return 0x16; - - return 0x10; -} - -static inline u64 hdmi_8996_get_cctrl(u64 frac_start, bool gen_ssc) -{ - if ((frac_start != 0) || (gen_ssc)) - return 0x28; - - return 0x1; -} - -static inline u64 hdmi_8996_get_integloop_gain(u64 frac_start, bool gen_ssc) -{ - if ((frac_start != 0) || gen_ssc) - return 0x80; - - return 0xC4; -} - -static inline u64 hdmi_8996_v3_get_integloop_gain(u64 frac_start, u64 bclk, - bool gen_ssc) -{ - u64 digclk_divsel = bclk >= HDMI_DIG_FREQ_BIT_CLK_THRESHOLD ? 1 : 2; - u64 base = ((frac_start != 0) || gen_ssc) ? 0x40 : 0xC4; - - base <<= digclk_divsel; - - return (base <= 2046 ? base : 0x7FE); -} - -static inline u64 hdmi_8996_get_vco_tune(u64 fdata, u64 div) -{ - u64 vco_tune; - - vco_tune = fdata * div; - do_div(vco_tune, 1000000); - vco_tune = 13000 - vco_tune - 256; - do_div(vco_tune, 5); - - return vco_tune; -} - -static inline u64 hdmi_8996_get_pll_cmp(u64 pll_cmp_cnt, u64 core_clk) -{ - u64 pll_cmp; - u64 rem; - - pll_cmp = pll_cmp_cnt * core_clk; - rem = do_div(pll_cmp, HDMI_REF_CLOCK); - if (rem > (HDMI_REF_CLOCK >> 1)) - pll_cmp++; - pll_cmp -= 1; - - return pll_cmp; -} - -static inline u64 hdmi_8996_v3_get_pll_cmp(u64 pll_cmp_cnt, u64 fdata) -{ - u64 dividend = pll_cmp_cnt * fdata; - u64 divisor = HDMI_REF_CLOCK * 10; - u64 rem; - - rem = do_div(dividend, divisor); - if (rem > (divisor >> 1)) - dividend++; - - return dividend - 1; -} - -static int hdmi_8996_v3_get_post_div(struct hdmi_8996_v3_post_divider *pd, - u64 bclk) -{ - u32 ratio[] = {2, 3, 4, 5, 6, 9, 10, 12, 14, 15, 20, 21, 25, 28, 35}; - u32 tx_band_sel[] = {0, 1, 2, 3}; - u64 vco_freq[60]; - u64 vco, vco_optimal, half_rate_mode = 0; - int vco_optimal_index, vco_freq_index; - int i, j, k, x; - - for (i = 0; i <= 1; i++) { - vco_optimal = HDMI_VCO_MAX_FREQ; - vco_optimal_index = -1; - vco_freq_index = 0; - for (j = 0; j < 15; j++) { - for (k = 0; k < 4; k++) { - u64 ratio_mult = ratio[j] << tx_band_sel[k]; - - vco = bclk >> half_rate_mode; - vco *= ratio_mult; - vco_freq[vco_freq_index++] = vco; - } - } - - for (x = 0; x < 60; x++) { - u64 vco_tmp = vco_freq[x]; - - if ((vco_tmp >= HDMI_VCO_MIN_FREQ) && - (vco_tmp <= vco_optimal)) { - vco_optimal = vco_tmp; - vco_optimal_index = x; - } - } - - if (vco_optimal_index == -1) { - if (!half_rate_mode) - half_rate_mode++; - else - return -EINVAL; - } else { - pd->vco_freq = vco_optimal; - pd->tx_band_sel = tx_band_sel[vco_optimal_index % 4]; - pd->vco_ratio = ratio[vco_optimal_index / 4]; - break; - } - } - - switch (pd->vco_ratio) { - case 2: - pd->hsclk_divsel = 0; - break; - case 3: - pd->hsclk_divsel = 4; - break; - case 4: - pd->hsclk_divsel = 8; - break; - case 5: - pd->hsclk_divsel = 12; - break; - case 6: - pd->hsclk_divsel = 1; - break; - case 9: - pd->hsclk_divsel = 5; - break; - case 10: - pd->hsclk_divsel = 2; - break; - case 12: - pd->hsclk_divsel = 9; - break; - case 14: - pd->hsclk_divsel = 3; - break; - case 15: - pd->hsclk_divsel = 13; - break; - case 20: - pd->hsclk_divsel = 10; - break; - case 21: - pd->hsclk_divsel = 7; - break; - case 25: - pd->hsclk_divsel = 14; - break; - case 28: - pd->hsclk_divsel = 11; - break; - case 35: - pd->hsclk_divsel = 15; - break; - } - - return 0; -} - -static int hdmi_8996_v1_calculate(u32 pix_clk, - struct hdmi_8996_phy_pll_reg_cfg *cfg) -{ - int rc = -EINVAL; - u64 fdata, clk_divtx, tmds_clk; - u64 bclk; - u64 post_div_gt_2g; - u64 post_div_lt_2g; - u64 coreclk_div1_lt_2g; - u64 core_clk_div_ratio; - u64 core_clk; - u64 pll_cmp; - u64 tx_band; - u64 tx_band_div_ratio; - u64 hsclk; - u64 dec_start; - u64 frac_start; - u64 pll_divisor = 4 * HDMI_REF_CLOCK; - u64 cpctrl; - u64 rctrl; - u64 cctrl; - u64 integloop_gain; - u64 vco_tune; - u64 vco_freq; - u64 rem; - - /* FDATA, CLK_DIVTX, PIXEL_CLK, TMDS_CLK */ - bclk = ((u64)pix_clk) * HDMI_BIT_CLK_TO_PIX_CLK_RATIO; - - if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) - tmds_clk = bclk/4; - else - tmds_clk = bclk; - - post_div_lt_2g = hdmi_8996_v1_get_post_div_lt_2g(bclk); - if (post_div_lt_2g == HDMI_64B_ERR_VAL) - goto fail; - - coreclk_div1_lt_2g = hdmi_8996_get_coreclk_div_lt_2g(bclk); - - core_clk_div_ratio = hdmi_8996_get_coreclk_div_ratio( - HDMI_CLKS_PLL_DIVSEL, HDMI_CORECLK_DIV); - - tx_band = hdmi_8996_v1_get_tx_band(bclk); - if (tx_band == HDMI_64B_ERR_VAL) - goto fail; - - tx_band_div_ratio = 1 << tx_band; - - if (bclk >= HDMI_2400MHZ_BIT_CLK_HZ) { - fdata = bclk; - hsclk = hdmi_8996_v1_get_hsclk(fdata); - if (hsclk == HDMI_64B_ERR_VAL) - goto fail; - - post_div_gt_2g = (hsclk <= 3) ? (hsclk + 1) : HDMI_64B_ERR_VAL; - if (post_div_gt_2g == HDMI_64B_ERR_VAL) - goto fail; - - vco_freq = bclk * (post_div_gt_2g * tx_band_div_ratio); - clk_divtx = vco_freq; - do_div(clk_divtx, post_div_gt_2g); - } else { - vco_freq = bclk * (post_div_lt_2g * tx_band_div_ratio); - fdata = vco_freq; - do_div(fdata, post_div_lt_2g); - hsclk = hdmi_8996_v1_get_hsclk(fdata); - if (hsclk == HDMI_64B_ERR_VAL) - goto fail; - - clk_divtx = vco_freq; - do_div(clk_divtx, post_div_lt_2g); - post_div_gt_2g = (hsclk <= 3) ? (hsclk + 1) : HDMI_64B_ERR_VAL; - if (post_div_gt_2g == HDMI_64B_ERR_VAL) - goto fail; - } - - /* Decimal and fraction values */ - dec_start = fdata * post_div_gt_2g; - do_div(dec_start, pll_divisor); - frac_start = ((pll_divisor - (((dec_start + 1) * pll_divisor) - - (fdata * post_div_gt_2g))) * (1 << 20)); - rem = do_div(frac_start, pll_divisor); - /* Round off frac_start to closest integer */ - if (rem >= (pll_divisor >> 1)) - frac_start++; - - cpctrl = hdmi_8996_get_cpctrl(frac_start, false); - rctrl = hdmi_8996_get_rctrl(frac_start, false); - cctrl = hdmi_8996_get_cctrl(frac_start, false); - integloop_gain = hdmi_8996_get_integloop_gain(frac_start, false); - vco_tune = hdmi_8996_get_vco_tune(fdata, post_div_gt_2g); - - core_clk = clk_divtx; - do_div(core_clk, core_clk_div_ratio); - pll_cmp = hdmi_8996_get_pll_cmp(1024, core_clk); - - /* Debug dump */ - DEV_DBG("%s: VCO freq: %llu\n", __func__, vco_freq); - DEV_DBG("%s: fdata: %llu\n", __func__, fdata); - DEV_DBG("%s: CLK_DIVTX: %llu\n", __func__, clk_divtx); - DEV_DBG("%s: pix_clk: %d\n", __func__, pix_clk); - DEV_DBG("%s: tmds clk: %llu\n", __func__, tmds_clk); - DEV_DBG("%s: HSCLK_SEL: %llu\n", __func__, hsclk); - DEV_DBG("%s: DEC_START: %llu\n", __func__, dec_start); - DEV_DBG("%s: DIV_FRAC_START: %llu\n", __func__, frac_start); - DEV_DBG("%s: PLL_CPCTRL: %llu\n", __func__, cpctrl); - DEV_DBG("%s: PLL_RCTRL: %llu\n", __func__, rctrl); - DEV_DBG("%s: PLL_CCTRL: %llu\n", __func__, cctrl); - DEV_DBG("%s: INTEGLOOP_GAIN: %llu\n", __func__, integloop_gain); - DEV_DBG("%s: VCO_TUNE: %llu\n", __func__, vco_tune); - DEV_DBG("%s: TX_BAND: %llu\n", __func__, tx_band); - DEV_DBG("%s: PLL_CMP: %llu\n", __func__, pll_cmp); - - /* Convert these values to register specific values */ - cfg->tx_l0_lane_mode = 0x3; - cfg->tx_l2_lane_mode = 0x3; - cfg->tx_l0_tx_band = tx_band + 4; - cfg->tx_l1_tx_band = tx_band + 4; - cfg->tx_l2_tx_band = tx_band + 4; - cfg->tx_l3_tx_band = tx_band + 4; - cfg->tx_l0_res_code_lane_tx = 0x33; - cfg->tx_l1_res_code_lane_tx = 0x33; - cfg->tx_l2_res_code_lane_tx = 0x33; - cfg->tx_l3_res_code_lane_tx = 0x33; - cfg->com_restrim_ctrl = 0x0; - cfg->com_vco_tune_ctrl = 0x1C; - - cfg->com_svs_mode_clk_sel = - (bclk >= HDMI_DIG_FREQ_BIT_CLK_THRESHOLD ? 1 : 2); - cfg->com_hsclk_sel = (0x28 | hsclk); - cfg->com_pll_cctrl_mode0 = cctrl; - cfg->com_pll_rctrl_mode0 = rctrl; - cfg->com_cp_ctrl_mode0 = cpctrl; - cfg->com_dec_start_mode0 = dec_start; - cfg->com_div_frac_start1_mode0 = (frac_start & 0xFF); - cfg->com_div_frac_start2_mode0 = ((frac_start & 0xFF00) >> 8); - cfg->com_div_frac_start3_mode0 = ((frac_start & 0xF0000) >> 16); - cfg->com_integloop_gain0_mode0 = (integloop_gain & 0xFF); - cfg->com_integloop_gain1_mode0 = ((integloop_gain & 0xF00) >> 8); - cfg->com_lock_cmp1_mode0 = (pll_cmp & 0xFF); - cfg->com_lock_cmp2_mode0 = ((pll_cmp & 0xFF00) >> 8); - cfg->com_lock_cmp3_mode0 = ((pll_cmp & 0x30000) >> 16); - cfg->com_core_clk_en = (0x6C | (HDMI_CLKS_PLL_DIVSEL << 4)); - cfg->com_coreclk_div = HDMI_CORECLK_DIV; - - if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) { - cfg->tx_l0_tx_drv_lvl = 0x25; - cfg->tx_l0_tx_emp_post1_lvl = 0x23; - cfg->tx_l1_tx_drv_lvl = 0x25; - cfg->tx_l1_tx_emp_post1_lvl = 0x23; - cfg->tx_l2_tx_drv_lvl = 0x25; - cfg->tx_l2_tx_emp_post1_lvl = 0x23; - cfg->tx_l3_tx_drv_lvl = 0x22; - cfg->tx_l3_tx_emp_post1_lvl = 0x27; - cfg->tx_l0_vmode_ctrl1 = 0x00; - cfg->tx_l0_vmode_ctrl2 = 0x0D; - cfg->tx_l1_vmode_ctrl1 = 0x00; - cfg->tx_l1_vmode_ctrl2 = 0x0D; - cfg->tx_l2_vmode_ctrl1 = 0x00; - cfg->tx_l2_vmode_ctrl2 = 0x0D; - cfg->tx_l3_vmode_ctrl1 = 0x00; - cfg->tx_l3_vmode_ctrl2 = 0x00; - cfg->com_restrim_ctrl = 0x0; - } else if (bclk > HDMI_MID_FREQ_BIT_CLK_THRESHOLD) { - cfg->tx_l0_tx_drv_lvl = 0x25; - cfg->tx_l0_tx_emp_post1_lvl = 0x23; - cfg->tx_l1_tx_drv_lvl = 0x25; - cfg->tx_l1_tx_emp_post1_lvl = 0x23; - cfg->tx_l2_tx_drv_lvl = 0x25; - cfg->tx_l2_tx_emp_post1_lvl = 0x23; - cfg->tx_l3_tx_drv_lvl = 0x25; - cfg->tx_l3_tx_emp_post1_lvl = 0x23; - cfg->tx_l0_vmode_ctrl1 = 0x00; - cfg->tx_l0_vmode_ctrl2 = 0x0D; - cfg->tx_l1_vmode_ctrl1 = 0x00; - cfg->tx_l1_vmode_ctrl2 = 0x0D; - cfg->tx_l2_vmode_ctrl1 = 0x00; - cfg->tx_l2_vmode_ctrl2 = 0x0D; - cfg->tx_l3_vmode_ctrl1 = 0x00; - cfg->tx_l3_vmode_ctrl2 = 0x00; - cfg->com_restrim_ctrl = 0x0; - } else { - cfg->tx_l0_tx_drv_lvl = 0x20; - cfg->tx_l0_tx_emp_post1_lvl = 0x20; - cfg->tx_l1_tx_drv_lvl = 0x20; - cfg->tx_l1_tx_emp_post1_lvl = 0x20; - cfg->tx_l2_tx_drv_lvl = 0x20; - cfg->tx_l2_tx_emp_post1_lvl = 0x20; - cfg->tx_l3_tx_drv_lvl = 0x20; - cfg->tx_l3_tx_emp_post1_lvl = 0x20; - cfg->tx_l0_vmode_ctrl1 = 0x00; - cfg->tx_l0_vmode_ctrl2 = 0x0E; - cfg->tx_l1_vmode_ctrl1 = 0x00; - cfg->tx_l1_vmode_ctrl2 = 0x0E; - cfg->tx_l2_vmode_ctrl1 = 0x00; - cfg->tx_l2_vmode_ctrl2 = 0x0E; - cfg->tx_l3_vmode_ctrl1 = 0x00; - cfg->tx_l3_vmode_ctrl2 = 0x0E; - cfg->com_restrim_ctrl = 0xD8; - } - - cfg->phy_mode = (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) ? 0x10 : 0x0; - DEV_DBG("HDMI 8996 PLL: PLL Settings\n"); - DEV_DBG("PLL PARAM: tx_l0_lane_mode = 0x%x\n", cfg->tx_l0_lane_mode); - DEV_DBG("PLL PARAM: tx_l2_lane_mode = 0x%x\n", cfg->tx_l2_lane_mode); - DEV_DBG("PLL PARAM: tx_l0_tx_band = 0x%x\n", cfg->tx_l0_tx_band); - DEV_DBG("PLL PARAM: tx_l1_tx_band = 0x%x\n", cfg->tx_l1_tx_band); - DEV_DBG("PLL PARAM: tx_l2_tx_band = 0x%x\n", cfg->tx_l2_tx_band); - DEV_DBG("PLL PARAM: tx_l3_tx_band = 0x%x\n", cfg->tx_l3_tx_band); - DEV_DBG("PLL PARAM: com_svs_mode_clk_sel = 0x%x\n", - cfg->com_svs_mode_clk_sel); - DEV_DBG("PLL PARAM: com_hsclk_sel = 0x%x\n", cfg->com_hsclk_sel); - DEV_DBG("PLL PARAM: com_pll_cctrl_mode0 = 0x%x\n", - cfg->com_pll_cctrl_mode0); - DEV_DBG("PLL PARAM: com_pll_rctrl_mode0 = 0x%x\n", - cfg->com_pll_rctrl_mode0); - DEV_DBG("PLL PARAM: com_cp_ctrl_mode0 = 0x%x\n", - cfg->com_cp_ctrl_mode0); - DEV_DBG("PLL PARAM: com_dec_start_mode0 = 0x%x\n", - cfg->com_dec_start_mode0); - DEV_DBG("PLL PARAM: com_div_frac_start1_mode0 = 0x%x\n", - cfg->com_div_frac_start1_mode0); - DEV_DBG("PLL PARAM: com_div_frac_start2_mode0 = 0x%x\n", - cfg->com_div_frac_start2_mode0); - DEV_DBG("PLL PARAM: com_div_frac_start3_mode0 = 0x%x\n", - cfg->com_div_frac_start3_mode0); - DEV_DBG("PLL PARAM: com_integloop_gain0_mode0 = 0x%x\n", - cfg->com_integloop_gain0_mode0); - DEV_DBG("PLL PARAM: com_integloop_gain1_mode0 = 0x%x\n", - cfg->com_integloop_gain1_mode0); - DEV_DBG("PLL PARAM: com_lock_cmp1_mode0 = 0x%x\n", - cfg->com_lock_cmp1_mode0); - DEV_DBG("PLL PARAM: com_lock_cmp2_mode0 = 0x%x\n", - cfg->com_lock_cmp2_mode0); - DEV_DBG("PLL PARAM: com_lock_cmp3_mode0 = 0x%x\n", - cfg->com_lock_cmp3_mode0); - DEV_DBG("PLL PARAM: com_core_clk_en = 0x%x\n", cfg->com_core_clk_en); - DEV_DBG("PLL PARAM: com_coreclk_div = 0x%x\n", cfg->com_coreclk_div); - DEV_DBG("PLL PARAM: com_restrim_ctrl = 0x%x\n", cfg->com_restrim_ctrl); - - DEV_DBG("PLL PARAM: l0_tx_drv_lvl = 0x%x\n", cfg->tx_l0_tx_drv_lvl); - DEV_DBG("PLL PARAM: l0_tx_emp_post1_lvl = 0x%x\n", - cfg->tx_l0_tx_emp_post1_lvl); - DEV_DBG("PLL PARAM: l1_tx_drv_lvl = 0x%x\n", cfg->tx_l1_tx_drv_lvl); - DEV_DBG("PLL PARAM: l1_tx_emp_post1_lvl = 0x%x\n", - cfg->tx_l1_tx_emp_post1_lvl); - DEV_DBG("PLL PARAM: l2_tx_drv_lvl = 0x%x\n", cfg->tx_l2_tx_drv_lvl); - DEV_DBG("PLL PARAM: l2_tx_emp_post1_lvl = 0x%x\n", - cfg->tx_l2_tx_emp_post1_lvl); - DEV_DBG("PLL PARAM: l3_tx_drv_lvl = 0x%x\n", cfg->tx_l3_tx_drv_lvl); - DEV_DBG("PLL PARAM: l3_tx_emp_post1_lvl = 0x%x\n", - cfg->tx_l3_tx_emp_post1_lvl); - - DEV_DBG("PLL PARAM: l0_vmode_ctrl1 = 0x%x\n", cfg->tx_l0_vmode_ctrl1); - DEV_DBG("PLL PARAM: l0_vmode_ctrl2 = 0x%x\n", cfg->tx_l0_vmode_ctrl2); - DEV_DBG("PLL PARAM: l1_vmode_ctrl1 = 0x%x\n", cfg->tx_l1_vmode_ctrl1); - DEV_DBG("PLL PARAM: l1_vmode_ctrl2 = 0x%x\n", cfg->tx_l1_vmode_ctrl2); - DEV_DBG("PLL PARAM: l2_vmode_ctrl1 = 0x%x\n", cfg->tx_l2_vmode_ctrl1); - DEV_DBG("PLL PARAM: l2_vmode_ctrl2 = 0x%x\n", cfg->tx_l2_vmode_ctrl2); - DEV_DBG("PLL PARAM: l3_vmode_ctrl1 = 0x%x\n", cfg->tx_l3_vmode_ctrl1); - DEV_DBG("PLL PARAM: l3_vmode_ctrl2 = 0x%x\n", cfg->tx_l3_vmode_ctrl2); - DEV_DBG("PLL PARAM: tx_l0_res_code_lane_tx = 0x%x\n", - cfg->tx_l0_res_code_lane_tx); - DEV_DBG("PLL PARAM: tx_l1_res_code_lane_tx = 0x%x\n", - cfg->tx_l1_res_code_lane_tx); - DEV_DBG("PLL PARAM: tx_l2_res_code_lane_tx = 0x%x\n", - cfg->tx_l2_res_code_lane_tx); - DEV_DBG("PLL PARAM: tx_l3_res_code_lane_tx = 0x%x\n", - cfg->tx_l3_res_code_lane_tx); - - DEV_DBG("PLL PARAM: phy_mode = 0x%x\n", cfg->phy_mode); - rc = 0; -fail: - return rc; -} - -static int hdmi_8996_v2_calculate(u32 pix_clk, - struct hdmi_8996_phy_pll_reg_cfg *cfg) -{ - int rc = -EINVAL; - u64 fdata, clk_divtx, tmds_clk; - u64 bclk; - u64 post_div; - u64 core_clk_div; - u64 core_clk_div_ratio; - u64 core_clk; - u64 pll_cmp; - u64 tx_band; - u64 tx_band_div_ratio; - u64 hsclk; - u64 dec_start; - u64 frac_start; - u64 pll_divisor = 4 * HDMI_REF_CLOCK; - u64 cpctrl; - u64 rctrl; - u64 cctrl; - u64 integloop_gain; - u64 vco_tune; - u64 vco_freq; - u64 vco_range; - u64 rem; - - /* FDATA, CLK_DIVTX, PIXEL_CLK, TMDS_CLK */ - bclk = ((u64)pix_clk) * HDMI_BIT_CLK_TO_PIX_CLK_RATIO; - - if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) - tmds_clk = pix_clk >> 2; - else - tmds_clk = pix_clk; - - vco_range = bclk < HDMI_282MHZ_BIT_CLK_HZ ? HDMI_2000MHZ_BIT_CLK_HZ : - HDMI_2250MHZ_BIT_CLK_HZ; - - fdata = hdmi_8996_v2_get_fdata(bclk, vco_range); - if (fdata == HDMI_64B_ERR_VAL) - goto fail; - - hsclk = hdmi_8996_v2_get_hsclk(fdata, vco_range); - if (hsclk == HDMI_64B_ERR_VAL) - goto fail; - - if (bclk >= vco_range) - post_div = hdmi_8996_v2_get_post_div_gt_2g(hsclk); - else - post_div = hdmi_8996_v2_get_post_div_lt_2g(bclk, vco_range); - - if (post_div == HDMI_64B_ERR_VAL) - goto fail; - - core_clk_div = 5; - core_clk_div_ratio = core_clk_div * 2; - - tx_band = hdmi_8996_v2_get_tx_band(bclk, vco_range); - if (tx_band == HDMI_64B_ERR_VAL) - goto fail; - - tx_band_div_ratio = 1 << tx_band; - - vco_freq = hdmi_8996_v2_get_vco_freq(bclk, vco_range); - clk_divtx = vco_freq; - do_div(clk_divtx, post_div); - - /* Decimal and fraction values */ - dec_start = fdata * post_div; - do_div(dec_start, pll_divisor); - frac_start = ((pll_divisor - (((dec_start + 1) * pll_divisor) - - (fdata * post_div))) * (1 << 20)); - rem = do_div(frac_start, pll_divisor); - /* Round off frac_start to closest integer */ - if (rem >= (pll_divisor >> 1)) - frac_start++; - - cpctrl = hdmi_8996_get_cpctrl(frac_start, false); - rctrl = hdmi_8996_get_rctrl(frac_start, false); - cctrl = hdmi_8996_get_cctrl(frac_start, false); - integloop_gain = hdmi_8996_get_integloop_gain(frac_start, false); - vco_tune = hdmi_8996_get_vco_tune(fdata, post_div); - - core_clk = clk_divtx; - do_div(core_clk, core_clk_div_ratio); - pll_cmp = hdmi_8996_get_pll_cmp(1024, core_clk); - - /* Debug dump */ - DEV_DBG("%s: VCO freq: %llu\n", __func__, vco_freq); - DEV_DBG("%s: fdata: %llu\n", __func__, fdata); - DEV_DBG("%s: CLK_DIVTX: %llu\n", __func__, clk_divtx); - DEV_DBG("%s: pix_clk: %d\n", __func__, pix_clk); - DEV_DBG("%s: tmds clk: %llu\n", __func__, tmds_clk); - DEV_DBG("%s: HSCLK_SEL: %llu\n", __func__, hsclk); - DEV_DBG("%s: DEC_START: %llu\n", __func__, dec_start); - DEV_DBG("%s: DIV_FRAC_START: %llu\n", __func__, frac_start); - DEV_DBG("%s: PLL_CPCTRL: %llu\n", __func__, cpctrl); - DEV_DBG("%s: PLL_RCTRL: %llu\n", __func__, rctrl); - DEV_DBG("%s: PLL_CCTRL: %llu\n", __func__, cctrl); - DEV_DBG("%s: INTEGLOOP_GAIN: %llu\n", __func__, integloop_gain); - DEV_DBG("%s: VCO_TUNE: %llu\n", __func__, vco_tune); - DEV_DBG("%s: TX_BAND: %llu\n", __func__, tx_band); - DEV_DBG("%s: PLL_CMP: %llu\n", __func__, pll_cmp); - - /* Convert these values to register specific values */ - cfg->tx_l0_lane_mode = 0x3; - cfg->tx_l2_lane_mode = 0x3; - cfg->tx_l0_tx_band = tx_band + 4; - cfg->tx_l1_tx_band = tx_band + 4; - cfg->tx_l2_tx_band = tx_band + 4; - cfg->tx_l3_tx_band = tx_band + 4; - - if (bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD) - cfg->com_svs_mode_clk_sel = 1; - else - cfg->com_svs_mode_clk_sel = 2; - - cfg->com_hsclk_sel = (0x28 | hsclk); - cfg->com_pll_cctrl_mode0 = cctrl; - cfg->com_pll_rctrl_mode0 = rctrl; - cfg->com_cp_ctrl_mode0 = cpctrl; - cfg->com_dec_start_mode0 = dec_start; - cfg->com_div_frac_start1_mode0 = (frac_start & 0xFF); - cfg->com_div_frac_start2_mode0 = ((frac_start & 0xFF00) >> 8); - cfg->com_div_frac_start3_mode0 = ((frac_start & 0xF0000) >> 16); - cfg->com_integloop_gain0_mode0 = (integloop_gain & 0xFF); - cfg->com_integloop_gain1_mode0 = ((integloop_gain & 0xF00) >> 8); - cfg->com_lock_cmp1_mode0 = (pll_cmp & 0xFF); - cfg->com_lock_cmp2_mode0 = ((pll_cmp & 0xFF00) >> 8); - cfg->com_lock_cmp3_mode0 = ((pll_cmp & 0x30000) >> 16); - cfg->com_core_clk_en = (0x6C | (HDMI_CLKS_PLL_DIVSEL << 4)); - cfg->com_coreclk_div = HDMI_CORECLK_DIV; - cfg->com_vco_tune_ctrl = 0x0; - - if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) { - cfg->tx_l0_tx_drv_lvl = 0x25; - cfg->tx_l0_tx_emp_post1_lvl = 0x23; - cfg->tx_l1_tx_drv_lvl = 0x25; - cfg->tx_l1_tx_emp_post1_lvl = 0x23; - cfg->tx_l2_tx_drv_lvl = 0x25; - cfg->tx_l2_tx_emp_post1_lvl = 0x23; - cfg->tx_l3_tx_drv_lvl = 0x22; - cfg->tx_l3_tx_emp_post1_lvl = 0x27; - cfg->tx_l0_vmode_ctrl1 = 0x00; - cfg->tx_l0_vmode_ctrl2 = 0x0D; - cfg->tx_l1_vmode_ctrl1 = 0x00; - cfg->tx_l1_vmode_ctrl2 = 0x0D; - cfg->tx_l2_vmode_ctrl1 = 0x00; - cfg->tx_l2_vmode_ctrl2 = 0x0D; - cfg->tx_l3_vmode_ctrl1 = 0x00; - cfg->tx_l3_vmode_ctrl2 = 0x00; - cfg->tx_l0_res_code_lane_tx = 0x3F; - cfg->tx_l1_res_code_lane_tx = 0x3F; - cfg->tx_l2_res_code_lane_tx = 0x3F; - cfg->tx_l3_res_code_lane_tx = 0x3F; - cfg->com_restrim_ctrl = 0x0; - } else if (bclk > HDMI_MID_FREQ_BIT_CLK_THRESHOLD) { - cfg->tx_l0_tx_drv_lvl = 0x25; - cfg->tx_l0_tx_emp_post1_lvl = 0x23; - cfg->tx_l1_tx_drv_lvl = 0x25; - cfg->tx_l1_tx_emp_post1_lvl = 0x23; - cfg->tx_l2_tx_drv_lvl = 0x25; - cfg->tx_l2_tx_emp_post1_lvl = 0x23; - cfg->tx_l3_tx_drv_lvl = 0x25; - cfg->tx_l3_tx_emp_post1_lvl = 0x23; - cfg->tx_l0_vmode_ctrl1 = 0x00; - cfg->tx_l0_vmode_ctrl2 = 0x0D; - cfg->tx_l1_vmode_ctrl1 = 0x00; - cfg->tx_l1_vmode_ctrl2 = 0x0D; - cfg->tx_l2_vmode_ctrl1 = 0x00; - cfg->tx_l2_vmode_ctrl2 = 0x0D; - cfg->tx_l3_vmode_ctrl1 = 0x00; - cfg->tx_l3_vmode_ctrl2 = 0x00; - cfg->tx_l0_res_code_lane_tx = 0x39; - cfg->tx_l1_res_code_lane_tx = 0x39; - cfg->tx_l2_res_code_lane_tx = 0x39; - cfg->tx_l3_res_code_lane_tx = 0x39; - cfg->com_restrim_ctrl = 0x0; - } else { - cfg->tx_l0_tx_drv_lvl = 0x20; - cfg->tx_l0_tx_emp_post1_lvl = 0x20; - cfg->tx_l1_tx_drv_lvl = 0x20; - cfg->tx_l1_tx_emp_post1_lvl = 0x20; - cfg->tx_l2_tx_drv_lvl = 0x20; - cfg->tx_l2_tx_emp_post1_lvl = 0x20; - cfg->tx_l3_tx_drv_lvl = 0x20; - cfg->tx_l3_tx_emp_post1_lvl = 0x20; - cfg->tx_l0_vmode_ctrl1 = 0x00; - cfg->tx_l0_vmode_ctrl2 = 0x0E; - cfg->tx_l1_vmode_ctrl1 = 0x00; - cfg->tx_l1_vmode_ctrl2 = 0x0E; - cfg->tx_l2_vmode_ctrl1 = 0x00; - cfg->tx_l2_vmode_ctrl2 = 0x0E; - cfg->tx_l3_vmode_ctrl1 = 0x00; - cfg->tx_l3_vmode_ctrl2 = 0x0E; - cfg->tx_l0_res_code_lane_tx = 0x3F; - cfg->tx_l1_res_code_lane_tx = 0x3F; - cfg->tx_l2_res_code_lane_tx = 0x3F; - cfg->tx_l3_res_code_lane_tx = 0x3F; - cfg->com_restrim_ctrl = 0xD8; - } - - cfg->phy_mode = (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) ? 0x10 : 0x0; - DEV_DBG("HDMI 8996 PLL: PLL Settings\n"); - DEV_DBG("PLL PARAM: tx_l0_lane_mode = 0x%x\n", cfg->tx_l0_lane_mode); - DEV_DBG("PLL PARAM: tx_l2_lane_mode = 0x%x\n", cfg->tx_l2_lane_mode); - DEV_DBG("PLL PARAM: tx_l0_tx_band = 0x%x\n", cfg->tx_l0_tx_band); - DEV_DBG("PLL PARAM: tx_l1_tx_band = 0x%x\n", cfg->tx_l1_tx_band); - DEV_DBG("PLL PARAM: tx_l2_tx_band = 0x%x\n", cfg->tx_l2_tx_band); - DEV_DBG("PLL PARAM: tx_l3_tx_band = 0x%x\n", cfg->tx_l3_tx_band); - DEV_DBG("PLL PARAM: com_svs_mode_clk_sel = 0x%x\n", - cfg->com_svs_mode_clk_sel); - DEV_DBG("PLL PARAM: com_vco_tune_ctrl = 0x%x\n", - cfg->com_vco_tune_ctrl); - DEV_DBG("PLL PARAM: com_hsclk_sel = 0x%x\n", cfg->com_hsclk_sel); - DEV_DBG("PLL PARAM: com_lock_cmp_en = 0x%x\n", cfg->com_lock_cmp_en); - DEV_DBG("PLL PARAM: com_pll_cctrl_mode0 = 0x%x\n", - cfg->com_pll_cctrl_mode0); - DEV_DBG("PLL PARAM: com_pll_rctrl_mode0 = 0x%x\n", - cfg->com_pll_rctrl_mode0); - DEV_DBG("PLL PARAM: com_cp_ctrl_mode0 = 0x%x\n", - cfg->com_cp_ctrl_mode0); - DEV_DBG("PLL PARAM: com_dec_start_mode0 = 0x%x\n", - cfg->com_dec_start_mode0); - DEV_DBG("PLL PARAM: com_div_frac_start1_mode0 = 0x%x\n", - cfg->com_div_frac_start1_mode0); - DEV_DBG("PLL PARAM: com_div_frac_start2_mode0 = 0x%x\n", - cfg->com_div_frac_start2_mode0); - DEV_DBG("PLL PARAM: com_div_frac_start3_mode0 = 0x%x\n", - cfg->com_div_frac_start3_mode0); - DEV_DBG("PLL PARAM: com_integloop_gain0_mode0 = 0x%x\n", - cfg->com_integloop_gain0_mode0); - DEV_DBG("PLL PARAM: com_integloop_gain1_mode0 = 0x%x\n", - cfg->com_integloop_gain1_mode0); - DEV_DBG("PLL PARAM: com_lock_cmp1_mode0 = 0x%x\n", - cfg->com_lock_cmp1_mode0); - DEV_DBG("PLL PARAM: com_lock_cmp2_mode0 = 0x%x\n", - cfg->com_lock_cmp2_mode0); - DEV_DBG("PLL PARAM: com_lock_cmp3_mode0 = 0x%x\n", - cfg->com_lock_cmp3_mode0); - DEV_DBG("PLL PARAM: com_core_clk_en = 0x%x\n", cfg->com_core_clk_en); - DEV_DBG("PLL PARAM: com_coreclk_div = 0x%x\n", cfg->com_coreclk_div); - - DEV_DBG("PLL PARAM: l0_tx_drv_lvl = 0x%x\n", cfg->tx_l0_tx_drv_lvl); - DEV_DBG("PLL PARAM: l0_tx_emp_post1_lvl = 0x%x\n", - cfg->tx_l0_tx_emp_post1_lvl); - DEV_DBG("PLL PARAM: l1_tx_drv_lvl = 0x%x\n", cfg->tx_l1_tx_drv_lvl); - DEV_DBG("PLL PARAM: l1_tx_emp_post1_lvl = 0x%x\n", - cfg->tx_l1_tx_emp_post1_lvl); - DEV_DBG("PLL PARAM: l2_tx_drv_lvl = 0x%x\n", cfg->tx_l2_tx_drv_lvl); - DEV_DBG("PLL PARAM: l2_tx_emp_post1_lvl = 0x%x\n", - cfg->tx_l2_tx_emp_post1_lvl); - DEV_DBG("PLL PARAM: l3_tx_drv_lvl = 0x%x\n", cfg->tx_l3_tx_drv_lvl); - DEV_DBG("PLL PARAM: l3_tx_emp_post1_lvl = 0x%x\n", - cfg->tx_l3_tx_emp_post1_lvl); - - DEV_DBG("PLL PARAM: l0_vmode_ctrl1 = 0x%x\n", cfg->tx_l0_vmode_ctrl1); - DEV_DBG("PLL PARAM: l0_vmode_ctrl2 = 0x%x\n", cfg->tx_l0_vmode_ctrl2); - DEV_DBG("PLL PARAM: l1_vmode_ctrl1 = 0x%x\n", cfg->tx_l1_vmode_ctrl1); - DEV_DBG("PLL PARAM: l1_vmode_ctrl2 = 0x%x\n", cfg->tx_l1_vmode_ctrl2); - DEV_DBG("PLL PARAM: l2_vmode_ctrl1 = 0x%x\n", cfg->tx_l2_vmode_ctrl1); - DEV_DBG("PLL PARAM: l2_vmode_ctrl2 = 0x%x\n", cfg->tx_l2_vmode_ctrl2); - DEV_DBG("PLL PARAM: l3_vmode_ctrl1 = 0x%x\n", cfg->tx_l3_vmode_ctrl1); - DEV_DBG("PLL PARAM: l3_vmode_ctrl2 = 0x%x\n", cfg->tx_l3_vmode_ctrl2); - DEV_DBG("PLL PARAM: tx_l0_res_code_lane_tx = 0x%x\n", - cfg->tx_l0_res_code_lane_tx); - DEV_DBG("PLL PARAM: tx_l1_res_code_lane_tx = 0x%x\n", - cfg->tx_l1_res_code_lane_tx); - DEV_DBG("PLL PARAM: tx_l2_res_code_lane_tx = 0x%x\n", - cfg->tx_l2_res_code_lane_tx); - DEV_DBG("PLL PARAM: tx_l3_res_code_lane_tx = 0x%x\n", - cfg->tx_l3_res_code_lane_tx); - DEV_DBG("PLL PARAM: com_restrim_ctrl = 0x%x\n", cfg->com_restrim_ctrl); - - DEV_DBG("PLL PARAM: phy_mode = 0x%x\n", cfg->phy_mode); - rc = 0; -fail: - return rc; -} - -static int hdmi_8996_v3_calculate(u32 pix_clk, - struct hdmi_8996_phy_pll_reg_cfg *cfg) -{ - int rc = -EINVAL; - struct hdmi_8996_v3_post_divider pd; - u64 fdata, tmds_clk; - u64 bclk; - u64 pll_cmp; - u64 tx_band; - u64 hsclk; - u64 dec_start; - u64 frac_start; - u64 pll_divisor = 4 * HDMI_REF_CLOCK; - u64 cpctrl; - u64 rctrl; - u64 cctrl; - u64 integloop_gain; - u64 vco_freq; - u64 rem; - - /* FDATA, HSCLK, PIXEL_CLK, TMDS_CLK */ - bclk = ((u64)pix_clk) * HDMI_BIT_CLK_TO_PIX_CLK_RATIO; - - if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) - tmds_clk = pix_clk >> 2; - else - tmds_clk = pix_clk; - - if (hdmi_8996_v3_get_post_div(&pd, bclk) || pd.vco_ratio <= 0 || - pd.vco_freq <= 0) - goto fail; - - vco_freq = pd.vco_freq; - fdata = pd.vco_freq; - do_div(fdata, pd.vco_ratio); - - hsclk = pd.hsclk_divsel; - dec_start = vco_freq; - do_div(dec_start, pll_divisor); - - frac_start = vco_freq * (1 << 20); - rem = do_div(frac_start, pll_divisor); - frac_start -= dec_start * (1 << 20); - if (rem > (pll_divisor >> 1)) - frac_start++; - - cpctrl = hdmi_8996_get_cpctrl(frac_start, false); - rctrl = hdmi_8996_get_rctrl(frac_start, false); - cctrl = hdmi_8996_get_cctrl(frac_start, false); - integloop_gain = hdmi_8996_v3_get_integloop_gain(frac_start, bclk, - false); - pll_cmp = hdmi_8996_v3_get_pll_cmp(1024, fdata); - tx_band = pd.tx_band_sel; - - /* Debug dump */ - DEV_DBG("%s: VCO freq: %llu\n", __func__, vco_freq); - DEV_DBG("%s: fdata: %llu\n", __func__, fdata); - DEV_DBG("%s: pix_clk: %d\n", __func__, pix_clk); - DEV_DBG("%s: tmds clk: %llu\n", __func__, tmds_clk); - DEV_DBG("%s: HSCLK_SEL: %llu\n", __func__, hsclk); - DEV_DBG("%s: DEC_START: %llu\n", __func__, dec_start); - DEV_DBG("%s: DIV_FRAC_START: %llu\n", __func__, frac_start); - DEV_DBG("%s: PLL_CPCTRL: %llu\n", __func__, cpctrl); - DEV_DBG("%s: PLL_RCTRL: %llu\n", __func__, rctrl); - DEV_DBG("%s: PLL_CCTRL: %llu\n", __func__, cctrl); - DEV_DBG("%s: INTEGLOOP_GAIN: %llu\n", __func__, integloop_gain); - DEV_DBG("%s: TX_BAND: %llu\n", __func__, tx_band); - DEV_DBG("%s: PLL_CMP: %llu\n", __func__, pll_cmp); - - /* Convert these values to register specific values */ - cfg->tx_l0_tx_band = tx_band + 4; - cfg->tx_l1_tx_band = tx_band + 4; - cfg->tx_l2_tx_band = tx_band + 4; - cfg->tx_l3_tx_band = tx_band + 4; - - if (bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD) - cfg->com_svs_mode_clk_sel = 1; - else - cfg->com_svs_mode_clk_sel = 2; - - cfg->com_hsclk_sel = (0x20 | hsclk); - cfg->com_pll_cctrl_mode0 = cctrl; - cfg->com_pll_rctrl_mode0 = rctrl; - cfg->com_cp_ctrl_mode0 = cpctrl; - cfg->com_dec_start_mode0 = dec_start; - cfg->com_div_frac_start1_mode0 = (frac_start & 0xFF); - cfg->com_div_frac_start2_mode0 = ((frac_start & 0xFF00) >> 8); - cfg->com_div_frac_start3_mode0 = ((frac_start & 0xF0000) >> 16); - cfg->com_integloop_gain0_mode0 = (integloop_gain & 0xFF); - cfg->com_integloop_gain1_mode0 = ((integloop_gain & 0xF00) >> 8); - cfg->com_lock_cmp1_mode0 = (pll_cmp & 0xFF); - cfg->com_lock_cmp2_mode0 = ((pll_cmp & 0xFF00) >> 8); - cfg->com_lock_cmp3_mode0 = ((pll_cmp & 0x30000) >> 16); - cfg->com_lock_cmp_en = 0x04; - cfg->com_core_clk_en = 0x2C; - cfg->com_coreclk_div = HDMI_CORECLK_DIV; - cfg->phy_mode = (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) ? 0x10 : 0x0; - cfg->com_vco_tune_ctrl = 0x0; - - cfg->tx_l0_lane_mode = 0x43; - cfg->tx_l2_lane_mode = 0x43; - - if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) { - cfg->tx_l0_tx_drv_lvl = 0x25; - cfg->tx_l0_tx_emp_post1_lvl = 0x23; - cfg->tx_l1_tx_drv_lvl = 0x25; - cfg->tx_l1_tx_emp_post1_lvl = 0x23; - cfg->tx_l2_tx_drv_lvl = 0x25; - cfg->tx_l2_tx_emp_post1_lvl = 0x23; - cfg->tx_l3_tx_drv_lvl = 0x22; - cfg->tx_l3_tx_emp_post1_lvl = 0x27; - cfg->tx_l0_vmode_ctrl1 = 0x00; - cfg->tx_l0_vmode_ctrl2 = 0x0D; - cfg->tx_l1_vmode_ctrl1 = 0x00; - cfg->tx_l1_vmode_ctrl2 = 0x0D; - cfg->tx_l2_vmode_ctrl1 = 0x00; - cfg->tx_l2_vmode_ctrl2 = 0x0D; - cfg->tx_l3_vmode_ctrl1 = 0x00; - cfg->tx_l3_vmode_ctrl2 = 0x00; - } else if (bclk > HDMI_MID_FREQ_BIT_CLK_THRESHOLD) { - cfg->tx_l0_tx_drv_lvl = 0x25; - cfg->tx_l0_tx_emp_post1_lvl = 0x23; - cfg->tx_l1_tx_drv_lvl = 0x25; - cfg->tx_l1_tx_emp_post1_lvl = 0x23; - cfg->tx_l2_tx_drv_lvl = 0x25; - cfg->tx_l2_tx_emp_post1_lvl = 0x23; - cfg->tx_l3_tx_drv_lvl = 0x25; - cfg->tx_l3_tx_emp_post1_lvl = 0x23; - cfg->tx_l0_vmode_ctrl1 = 0x00; - cfg->tx_l0_vmode_ctrl2 = 0x0D; - cfg->tx_l1_vmode_ctrl1 = 0x00; - cfg->tx_l1_vmode_ctrl2 = 0x0D; - cfg->tx_l2_vmode_ctrl1 = 0x00; - cfg->tx_l2_vmode_ctrl2 = 0x0D; - cfg->tx_l3_vmode_ctrl1 = 0x00; - cfg->tx_l3_vmode_ctrl2 = 0x00; - } else { - cfg->tx_l0_tx_drv_lvl = 0x20; - cfg->tx_l0_tx_emp_post1_lvl = 0x20; - cfg->tx_l1_tx_drv_lvl = 0x20; - cfg->tx_l1_tx_emp_post1_lvl = 0x20; - cfg->tx_l2_tx_drv_lvl = 0x20; - cfg->tx_l2_tx_emp_post1_lvl = 0x20; - cfg->tx_l3_tx_drv_lvl = 0x20; - cfg->tx_l3_tx_emp_post1_lvl = 0x20; - cfg->tx_l0_vmode_ctrl1 = 0x00; - cfg->tx_l0_vmode_ctrl2 = 0x0E; - cfg->tx_l1_vmode_ctrl1 = 0x00; - cfg->tx_l1_vmode_ctrl2 = 0x0E; - cfg->tx_l2_vmode_ctrl1 = 0x00; - cfg->tx_l2_vmode_ctrl2 = 0x0E; - cfg->tx_l3_vmode_ctrl1 = 0x00; - cfg->tx_l3_vmode_ctrl2 = 0x0E; - } - - DEV_DBG("HDMI 8996 PLL: PLL Settings\n"); - DEV_DBG("PLL PARAM: tx_l0_tx_band = 0x%x\n", cfg->tx_l0_tx_band); - DEV_DBG("PLL PARAM: tx_l1_tx_band = 0x%x\n", cfg->tx_l1_tx_band); - DEV_DBG("PLL PARAM: tx_l2_tx_band = 0x%x\n", cfg->tx_l2_tx_band); - DEV_DBG("PLL PARAM: tx_l3_tx_band = 0x%x\n", cfg->tx_l3_tx_band); - DEV_DBG("PLL PARAM: com_svs_mode_clk_sel = 0x%x\n", - cfg->com_svs_mode_clk_sel); - DEV_DBG("PLL PARAM: com_hsclk_sel = 0x%x\n", cfg->com_hsclk_sel); - DEV_DBG("PLL PARAM: com_lock_cmp_en = 0x%x\n", cfg->com_lock_cmp_en); - DEV_DBG("PLL PARAM: com_pll_cctrl_mode0 = 0x%x\n", - cfg->com_pll_cctrl_mode0); - DEV_DBG("PLL PARAM: com_pll_rctrl_mode0 = 0x%x\n", - cfg->com_pll_rctrl_mode0); - DEV_DBG("PLL PARAM: com_cp_ctrl_mode0 = 0x%x\n", - cfg->com_cp_ctrl_mode0); - DEV_DBG("PLL PARAM: com_dec_start_mode0 = 0x%x\n", - cfg->com_dec_start_mode0); - DEV_DBG("PLL PARAM: com_div_frac_start1_mode0 = 0x%x\n", - cfg->com_div_frac_start1_mode0); - DEV_DBG("PLL PARAM: com_div_frac_start2_mode0 = 0x%x\n", - cfg->com_div_frac_start2_mode0); - DEV_DBG("PLL PARAM: com_div_frac_start3_mode0 = 0x%x\n", - cfg->com_div_frac_start3_mode0); - DEV_DBG("PLL PARAM: com_integloop_gain0_mode0 = 0x%x\n", - cfg->com_integloop_gain0_mode0); - DEV_DBG("PLL PARAM: com_integloop_gain1_mode0 = 0x%x\n", - cfg->com_integloop_gain1_mode0); - DEV_DBG("PLL PARAM: com_lock_cmp1_mode0 = 0x%x\n", - cfg->com_lock_cmp1_mode0); - DEV_DBG("PLL PARAM: com_lock_cmp2_mode0 = 0x%x\n", - cfg->com_lock_cmp2_mode0); - DEV_DBG("PLL PARAM: com_lock_cmp3_mode0 = 0x%x\n", - cfg->com_lock_cmp3_mode0); - DEV_DBG("PLL PARAM: com_core_clk_en = 0x%x\n", cfg->com_core_clk_en); - DEV_DBG("PLL PARAM: com_coreclk_div = 0x%x\n", cfg->com_coreclk_div); - DEV_DBG("PLL PARAM: phy_mode = 0x%x\n", cfg->phy_mode); - - DEV_DBG("PLL PARAM: tx_l0_lane_mode = 0x%x\n", cfg->tx_l0_lane_mode); - DEV_DBG("PLL PARAM: tx_l2_lane_mode = 0x%x\n", cfg->tx_l2_lane_mode); - DEV_DBG("PLL PARAM: l0_tx_drv_lvl = 0x%x\n", cfg->tx_l0_tx_drv_lvl); - DEV_DBG("PLL PARAM: l0_tx_emp_post1_lvl = 0x%x\n", - cfg->tx_l0_tx_emp_post1_lvl); - DEV_DBG("PLL PARAM: l1_tx_drv_lvl = 0x%x\n", cfg->tx_l1_tx_drv_lvl); - DEV_DBG("PLL PARAM: l1_tx_emp_post1_lvl = 0x%x\n", - cfg->tx_l1_tx_emp_post1_lvl); - DEV_DBG("PLL PARAM: l2_tx_drv_lvl = 0x%x\n", cfg->tx_l2_tx_drv_lvl); - DEV_DBG("PLL PARAM: l2_tx_emp_post1_lvl = 0x%x\n", - cfg->tx_l2_tx_emp_post1_lvl); - DEV_DBG("PLL PARAM: l3_tx_drv_lvl = 0x%x\n", cfg->tx_l3_tx_drv_lvl); - DEV_DBG("PLL PARAM: l3_tx_emp_post1_lvl = 0x%x\n", - cfg->tx_l3_tx_emp_post1_lvl); - - DEV_DBG("PLL PARAM: l0_vmode_ctrl1 = 0x%x\n", cfg->tx_l0_vmode_ctrl1); - DEV_DBG("PLL PARAM: l0_vmode_ctrl2 = 0x%x\n", cfg->tx_l0_vmode_ctrl2); - DEV_DBG("PLL PARAM: l1_vmode_ctrl1 = 0x%x\n", cfg->tx_l1_vmode_ctrl1); - DEV_DBG("PLL PARAM: l1_vmode_ctrl2 = 0x%x\n", cfg->tx_l1_vmode_ctrl2); - DEV_DBG("PLL PARAM: l2_vmode_ctrl1 = 0x%x\n", cfg->tx_l2_vmode_ctrl1); - DEV_DBG("PLL PARAM: l2_vmode_ctrl2 = 0x%x\n", cfg->tx_l2_vmode_ctrl2); - DEV_DBG("PLL PARAM: l3_vmode_ctrl1 = 0x%x\n", cfg->tx_l3_vmode_ctrl1); - DEV_DBG("PLL PARAM: l3_vmode_ctrl2 = 0x%x\n", cfg->tx_l3_vmode_ctrl2); - rc = 0; -fail: - return rc; -} - -static int hdmi_8996_calculate(u32 pix_clk, - struct hdmi_8996_phy_pll_reg_cfg *cfg, u32 ver) -{ - switch (ver) { - case HDMI_VERSION_8996_V3: - case HDMI_VERSION_8996_V3_1_8: - return hdmi_8996_v3_calculate(pix_clk, cfg); - case HDMI_VERSION_8996_V2: - return hdmi_8996_v2_calculate(pix_clk, cfg); - default: - return hdmi_8996_v1_calculate(pix_clk, cfg); - } -} - -static int hdmi_8996_phy_pll_set_clk_rate(struct clk *c, u32 tmds_clk, u32 ver) -{ - int rc = 0; - struct hdmi_pll_vco_clk *vco = to_hdmi_8996_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - struct hdmi_8996_phy_pll_reg_cfg cfg = {0}; - - rc = hdmi_8996_calculate(tmds_clk, &cfg, ver); - if (rc) { - DEV_ERR("%s: PLL calculation failed\n", __func__); - return rc; - } - - /* Initially shut down PHY */ - DEV_DBG("%s: Disabling PHY\n", __func__); - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_PD_CTL, 0x0); - udelay(500); - - /* Power up sequence */ - switch (ver) { - case HDMI_VERSION_8996_V2: - case HDMI_VERSION_8996_V3: - case HDMI_VERSION_8996_V3_1_8: - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_BG_CTRL, 0x04); - break; - } - - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_PD_CTL, 0x1); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RESETSM_CNTRL, 0x20); - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_TX0_TX1_LANE_CTL, 0x0F); - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_TX2_TX3_LANE_CTL, 0x0F); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET, - QSERDES_TX_L0_CLKBUF_ENABLE, 0x03); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET, - QSERDES_TX_L0_CLKBUF_ENABLE, 0x03); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET, - QSERDES_TX_L0_CLKBUF_ENABLE, 0x03); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET, - QSERDES_TX_L0_CLKBUF_ENABLE, 0x03); - - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET, - QSERDES_TX_L0_LANE_MODE, cfg.tx_l0_lane_mode); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET, - QSERDES_TX_L0_LANE_MODE, cfg.tx_l2_lane_mode); - - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET, - QSERDES_TX_L0_TX_BAND, cfg.tx_l0_tx_band); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET, - QSERDES_TX_L0_TX_BAND, cfg.tx_l1_tx_band); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET, - QSERDES_TX_L0_TX_BAND, cfg.tx_l2_tx_band); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET, - QSERDES_TX_L0_TX_BAND, cfg.tx_l3_tx_band); - - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET, - QSERDES_TX_L0_RESET_TSYNC_EN, 0x03); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET, - QSERDES_TX_L0_RESET_TSYNC_EN, 0x03); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET, - QSERDES_TX_L0_RESET_TSYNC_EN, 0x03); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET, - QSERDES_TX_L0_RESET_TSYNC_EN, 0x03); - - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1E); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x07); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SYSCLK_EN_SEL, 0x37); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SYS_CLK_CTRL, 0x02); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_CLK_ENABLE1, 0x0E); - if (ver == HDMI_VERSION_8996_V1) - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_BG_CTRL, 0x06); - - /* Bypass VCO calibration */ - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SVS_MODE_CLK_SEL, - cfg.com_svs_mode_clk_sel); - - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_BG_TRIM, 0x0F); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_IVCO, 0x0F); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_VCO_TUNE_CTRL, - cfg.com_vco_tune_ctrl); - - switch (ver) { - case HDMI_VERSION_8996_V1: - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SVS_MODE_CLK_SEL, - cfg.com_svs_mode_clk_sel); - break; - default: - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_BG_CTRL, 0x06); - } - - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_CLK_SELECT, 0x30); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_HSCLK_SEL, - cfg.com_hsclk_sel); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_LOCK_CMP_EN, - cfg.com_lock_cmp_en); - - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_CCTRL_MODE0, - cfg.com_pll_cctrl_mode0); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_RCTRL_MODE0, - cfg.com_pll_rctrl_mode0); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_CP_CTRL_MODE0, - cfg.com_cp_ctrl_mode0); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DEC_START_MODE0, - cfg.com_dec_start_mode0); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DIV_FRAC_START1_MODE0, - cfg.com_div_frac_start1_mode0); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DIV_FRAC_START2_MODE0, - cfg.com_div_frac_start2_mode0); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DIV_FRAC_START3_MODE0, - cfg.com_div_frac_start3_mode0); - - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_INTEGLOOP_GAIN0_MODE0, - cfg.com_integloop_gain0_mode0); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_INTEGLOOP_GAIN1_MODE0, - cfg.com_integloop_gain1_mode0); - - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_LOCK_CMP1_MODE0, - cfg.com_lock_cmp1_mode0); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_LOCK_CMP2_MODE0, - cfg.com_lock_cmp2_mode0); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_LOCK_CMP3_MODE0, - cfg.com_lock_cmp3_mode0); - - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_VCO_TUNE_MAP, 0x00); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_CORE_CLK_EN, - cfg.com_core_clk_en); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_CORECLK_DIV, - cfg.com_coreclk_div); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_CMN_CONFIG, 0x02); - - if (ver == HDMI_VERSION_8996_V3 || ver == HDMI_VERSION_8996_V3_1_8) - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RESCODE_DIV_NUM, 0x15); - - /* TX lanes setup (TX 0/1/2/3) */ - if (ver == HDMI_VERSION_8996_V3_1_8) { - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET, - QSERDES_TX_L0_TX_DRV_LVL, - 0x00000023); - } else { - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET, - QSERDES_TX_L0_TX_DRV_LVL, - cfg.tx_l0_tx_drv_lvl); - } - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET, - QSERDES_TX_L0_TX_EMP_POST1_LVL, - cfg.tx_l0_tx_emp_post1_lvl); - - if (ver == HDMI_VERSION_8996_V3_1_8) { - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET, - QSERDES_TX_L0_TX_DRV_LVL, - 0x00000023); - } else { - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET, - QSERDES_TX_L0_TX_DRV_LVL, - cfg.tx_l1_tx_drv_lvl); - } - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET, - QSERDES_TX_L0_TX_EMP_POST1_LVL, - cfg.tx_l1_tx_emp_post1_lvl); - - if (ver == HDMI_VERSION_8996_V3_1_8) { - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET, - QSERDES_TX_L0_TX_DRV_LVL, - 0x00000023); - } else { - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET, - QSERDES_TX_L0_TX_DRV_LVL, - cfg.tx_l2_tx_drv_lvl); - } - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET, - QSERDES_TX_L0_TX_EMP_POST1_LVL, - cfg.tx_l2_tx_emp_post1_lvl); - - if (ver == HDMI_VERSION_8996_V3_1_8) { - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET, - QSERDES_TX_L0_TX_DRV_LVL, - 0x00000020); - } else { - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET, - QSERDES_TX_L0_TX_DRV_LVL, - cfg.tx_l3_tx_drv_lvl); - } - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET, - QSERDES_TX_L0_TX_EMP_POST1_LVL, - cfg.tx_l3_tx_emp_post1_lvl); - - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET, - QSERDES_TX_L0_VMODE_CTRL1, - cfg.tx_l0_vmode_ctrl1); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET, - QSERDES_TX_L0_VMODE_CTRL2, - cfg.tx_l0_vmode_ctrl2); - - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET, - QSERDES_TX_L0_VMODE_CTRL1, - cfg.tx_l1_vmode_ctrl1); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET, - QSERDES_TX_L0_VMODE_CTRL2, - cfg.tx_l1_vmode_ctrl2); - - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET, - QSERDES_TX_L0_VMODE_CTRL1, - cfg.tx_l2_vmode_ctrl1); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET, - QSERDES_TX_L0_VMODE_CTRL2, - cfg.tx_l2_vmode_ctrl2); - - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET, - QSERDES_TX_L0_VMODE_CTRL1, - cfg.tx_l3_vmode_ctrl1); - if (ver == HDMI_VERSION_8996_V3_1_8) { - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET, - QSERDES_TX_L0_VMODE_CTRL2, - 0x0000000D); - } else { - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET, - QSERDES_TX_L0_VMODE_CTRL2, - cfg.tx_l3_vmode_ctrl2); - } - - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET, - QSERDES_TX_L0_TX_DRV_LVL_OFFSET, 0x00); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET, - QSERDES_TX_L0_TX_DRV_LVL_OFFSET, 0x00); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET, - QSERDES_TX_L0_TX_DRV_LVL_OFFSET, 0x00); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET, - QSERDES_TX_L0_TX_DRV_LVL_OFFSET, 0x00); - - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET, - QSERDES_TX_L0_RES_CODE_LANE_OFFSET, 0x00); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET, - QSERDES_TX_L0_RES_CODE_LANE_OFFSET, 0x00); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET, - QSERDES_TX_L0_RES_CODE_LANE_OFFSET, 0x00); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET, - QSERDES_TX_L0_RES_CODE_LANE_OFFSET, 0x00); - - if (ver < HDMI_VERSION_8996_V3) { - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET, - QSERDES_TX_L0_RES_CODE_LANE_TX, - cfg.tx_l0_res_code_lane_tx); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET, - QSERDES_TX_L0_RES_CODE_LANE_TX, - cfg.tx_l1_res_code_lane_tx); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET, - QSERDES_TX_L0_RES_CODE_LANE_TX, - cfg.tx_l2_res_code_lane_tx); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET, - QSERDES_TX_L0_RES_CODE_LANE_TX, - cfg.tx_l3_res_code_lane_tx); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RESTRIM_CTRL, - cfg.com_restrim_ctrl); - - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_TXCAL_CFG0, 0x00); - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_TXCAL_CFG1, 0x05); - } - - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_MODE, cfg.phy_mode); - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_PD_CTL, 0x1F); - - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET, - QSERDES_TX_L0_TRAN_DRVR_EMP_EN, 0x03); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET, - QSERDES_TX_L0_TRAN_DRVR_EMP_EN, 0x03); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET, - QSERDES_TX_L0_TRAN_DRVR_EMP_EN, 0x03); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET, - QSERDES_TX_L0_TRAN_DRVR_EMP_EN, 0x03); - - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET, - QSERDES_TX_L0_PARRATE_REC_DETECT_IDLE_EN, 0x40); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET, - QSERDES_TX_L0_PARRATE_REC_DETECT_IDLE_EN, 0x40); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET, - QSERDES_TX_L0_PARRATE_REC_DETECT_IDLE_EN, 0x40); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET, - QSERDES_TX_L0_PARRATE_REC_DETECT_IDLE_EN, 0x40); - - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET, - QSERDES_TX_L0_HP_PD_ENABLES, 0x0C); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET, - QSERDES_TX_L0_HP_PD_ENABLES, 0x0C); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET, - QSERDES_TX_L0_HP_PD_ENABLES, 0x0C); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET, - QSERDES_TX_L0_HP_PD_ENABLES, 0x03); - - if (ver == HDMI_VERSION_8996_V2) { - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_ATB_SEL1, 0x01); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_ATB_SEL2, 0x01); - } - /* - * Ensure that vco configuration gets flushed to hardware before - * enabling the PLL - */ - wmb(); - return 0; -} - -static int hdmi_8996_phy_ready_status(struct mdss_pll_resources *io) -{ - u32 status = 0; - int phy_ready = 0; - int rc; - u32 read_count = 0; - - rc = mdss_pll_resource_enable(io, true); - if (rc) { - DEV_ERR("%s: pll resource can't be enabled\n", __func__); - return rc; - } - - DEV_DBG("%s: Waiting for PHY Ready\n", __func__); - - /* Poll for PHY read status */ - while (read_count < HDMI_PLL_POLL_MAX_READS) { - status = MDSS_PLL_REG_R(io->phy_base, HDMI_PHY_STATUS); - if ((status & BIT(0)) == 1) { - phy_ready = 1; - DEV_DBG("%s: PHY READY\n", __func__); - break; - } - udelay(HDMI_PLL_POLL_TIMEOUT_US); - read_count++; - } - - if (read_count == HDMI_PLL_POLL_MAX_READS) { - phy_ready = 0; - DEV_DBG("%s: PHY READY TIMEOUT\n", __func__); - } - - mdss_pll_resource_enable(io, false); - - return phy_ready; -} - -static int hdmi_8996_pll_lock_status(struct mdss_pll_resources *io) -{ - u32 status; - int pll_locked = 0; - int rc; - u32 read_count = 0; - - rc = mdss_pll_resource_enable(io, true); - if (rc) { - DEV_ERR("%s: pll resource can't be enabled\n", __func__); - return rc; - } - - DEV_DBG("%s: Waiting for PLL lock\n", __func__); - - while (read_count < HDMI_PLL_POLL_MAX_READS) { - status = MDSS_PLL_REG_R(io->pll_base, - QSERDES_COM_C_READY_STATUS); - if ((status & BIT(0)) == 1) { - pll_locked = 1; - DEV_DBG("%s: C READY\n", __func__); - break; - } - udelay(HDMI_PLL_POLL_TIMEOUT_US); - read_count++; - } - - if (read_count == HDMI_PLL_POLL_MAX_READS) { - pll_locked = 0; - DEV_DBG("%s: C READY TIMEOUT\n", __func__); - } - - mdss_pll_resource_enable(io, false); - - return pll_locked; -} - -static int hdmi_8996_v1_perform_sw_calibration(struct clk *c) -{ - int rc = 0; - struct hdmi_pll_vco_clk *vco = to_hdmi_8996_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - - u32 max_code = 0x190; - u32 min_code = 0x0; - u32 max_cnt = 0; - u32 min_cnt = 0; - u32 expected_counter_value = 0; - u32 step = 0; - u32 dbus_all = 0; - u32 dbus_sel = 0; - u32 vco_code = 0; - u32 val = 0; - - vco_code = 0xC8; - - DEV_DBG("%s: Starting SW calibration with vco_code = %d\n", __func__, - vco_code); - - expected_counter_value = - (MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_LOCK_CMP3_MODE0) << 16) | - (MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_LOCK_CMP2_MODE0) << 8) | - (MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_LOCK_CMP1_MODE0)); - - DEV_DBG("%s: expected_counter_value = %d\n", __func__, - expected_counter_value); - - val = MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_CMN_MISC1); - val |= BIT(4); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_CMN_MISC1, val); - - val = MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_CMN_MISC1); - val |= BIT(3); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_CMN_MISC1, val); - - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DEBUG_BUS_SEL, 0x4); - - val = MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_LOCK_CMP_CFG); - val |= BIT(1); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_LOCK_CMP_CFG, val); - - udelay(60); - - while (1) { - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_VCO_TUNE1_MODE0, - vco_code & 0xFF); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_VCO_TUNE2_MODE0, - (vco_code >> 8) & 0x3); - - udelay(20); - - val = MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_LOCK_CMP_CFG); - val &= ~BIT(1); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_LOCK_CMP_CFG, val); - - udelay(60); - - val = MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_LOCK_CMP_CFG); - val |= BIT(1); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_LOCK_CMP_CFG, val); - - udelay(60); - - dbus_all = - (MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_DEBUG_BUS3) << 24) | - (MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_DEBUG_BUS2) << 16) | - (MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_DEBUG_BUS1) << 8) | - (MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_DEBUG_BUS0)); - - dbus_sel = (dbus_all >> 9) & 0x3FFFF; - DEV_DBG("%s: loop[%d], dbus_all = 0x%x, dbus_sel = 0x%x\n", - __func__, step, dbus_all, dbus_sel); - if (dbus_sel == 0) - DEV_ERR("%s: CHECK HDMI REF CLK\n", __func__); - - if (dbus_sel == expected_counter_value) { - max_code = vco_code; - max_cnt = dbus_sel; - min_code = vco_code; - min_cnt = dbus_sel; - } else if (dbus_sel == 0) { - max_code = vco_code; - max_cnt = dbus_sel; - vco_code = (max_code + min_code)/2; - } else if (dbus_sel > expected_counter_value) { - min_code = vco_code; - min_cnt = dbus_sel; - vco_code = (max_code + min_code)/2; - } else if (dbus_sel < expected_counter_value) { - max_code = vco_code; - max_cnt = dbus_sel; - vco_code = (max_code + min_code)/2; - } - - step++; - - if ((vco_code == 0) || (vco_code == 0x3FF) || (step > 0x3FF)) { - DEV_ERR("%s: VCO tune code search failed\n", __func__); - rc = -ENOTSUPP; - break; - } - if ((max_code - min_code) <= 1) { - if ((max_code - min_code) == 1) { - if (abs((int)(max_cnt - expected_counter_value)) - < abs((int)(min_cnt - expected_counter_value - ))) { - vco_code = max_code; - } else { - vco_code = min_code; - } - } - break; - } - DEV_DBG("%s: loop[%d], new vco_code = %d\n", __func__, step, - vco_code); - } - - DEV_DBG("%s: CALIB done. vco_code = %d\n", __func__, vco_code); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_VCO_TUNE1_MODE0, - vco_code & 0xFF); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_VCO_TUNE2_MODE0, - (vco_code >> 8) & 0x3); - val = MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_LOCK_CMP_CFG); - val &= ~BIT(1); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_LOCK_CMP_CFG, val); - - val = MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_CMN_MISC1); - val |= BIT(4); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_CMN_MISC1, val); - - val = MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_CMN_MISC1); - val &= ~BIT(3); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_CMN_MISC1, val); - - return rc; -} - -static int hdmi_8996_v2_perform_sw_calibration(struct clk *c) -{ - struct hdmi_pll_vco_clk *vco = to_hdmi_8996_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - u32 vco_code1, vco_code2, integral_loop, ready_poll; - u32 read_count = 0; - - while (read_count < (HDMI_PLL_POLL_MAX_READS << 1)) { - ready_poll = MDSS_PLL_REG_R(io->pll_base, - QSERDES_COM_C_READY_STATUS); - if ((ready_poll & BIT(0)) == 1) { - ready_poll = 1; - DEV_DBG("%s: C READY\n", __func__); - break; - } - udelay(HDMI_PLL_POLL_TIMEOUT_US); - read_count++; - } - - if (read_count == (HDMI_PLL_POLL_MAX_READS << 1)) { - ready_poll = 0; - DEV_DBG("%s: C READY TIMEOUT, TRYING SW CALIBRATION\n", - __func__); - } - - vco_code1 = MDSS_PLL_REG_R(io->pll_base, - QSERDES_COM_PLLCAL_CODE1_STATUS); - vco_code2 = MDSS_PLL_REG_R(io->pll_base, - QSERDES_COM_PLLCAL_CODE2_STATUS); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DEBUG_BUS_SEL, 0x5); - integral_loop = MDSS_PLL_REG_R(io->pll_base, - QSERDES_COM_DEBUG_BUS0); - - if (((ready_poll & 0x1) == 0) || (((ready_poll & 1) == 1) && - (vco_code1 == 0xFF) && ((vco_code2 & 0x3) == 0x1) && - (integral_loop > 0xC0))) { - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_ATB_SEL1, 0x04); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_ATB_SEL2, 0x00); - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x17); - udelay(100); - - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x11); - udelay(100); - - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x19); - } - return 0; -} - -static int hdmi_8996_perform_sw_calibration(struct clk *c, u32 ver) -{ - switch (ver) { - case HDMI_VERSION_8996_V1: - return hdmi_8996_v1_perform_sw_calibration(c); - case HDMI_VERSION_8996_V2: - return hdmi_8996_v2_perform_sw_calibration(c); - } - return 0; -} - -static int hdmi_8996_vco_enable(struct clk *c, u32 ver) -{ - int rc = 0; - struct hdmi_pll_vco_clk *vco = to_hdmi_8996_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x1); - udelay(100); - - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x19); - udelay(100); - - rc = hdmi_8996_perform_sw_calibration(c, ver); - if (rc) { - DEV_ERR("%s: software calibration failed\n", __func__); - return rc; - } - - rc = hdmi_8996_pll_lock_status(io); - if (!rc) { - DEV_ERR("%s: PLL not locked\n", __func__); - return rc; - } - - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET, - QSERDES_TX_L0_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, - 0x6F); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET, - QSERDES_TX_L0_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, - 0x6F); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET, - QSERDES_TX_L0_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, - 0x6F); - MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET, - QSERDES_TX_L0_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, - 0x6F); - - /* Disable SSC */ - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SSC_PER1, 0x0); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SSC_PER2, 0x0); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SSC_STEP_SIZE1, 0x0); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SSC_STEP_SIZE2, 0x0); - MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SSC_EN_CENTER, 0x2); - - rc = hdmi_8996_phy_ready_status(io); - if (!rc) { - DEV_ERR("%s: PHY not READY\n", __func__); - return rc; - } - - /* Restart the retiming buffer */ - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x18); - udelay(1); - MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x19); - - io->pll_on = true; - return 0; -} - -static int hdmi_8996_v1_vco_enable(struct clk *c) -{ - return hdmi_8996_vco_enable(c, HDMI_VERSION_8996_V1); -} - -static int hdmi_8996_v2_vco_enable(struct clk *c) -{ - return hdmi_8996_vco_enable(c, HDMI_VERSION_8996_V2); -} - -static int hdmi_8996_v3_vco_enable(struct clk *c) -{ - return hdmi_8996_vco_enable(c, HDMI_VERSION_8996_V3); -} - -static int hdmi_8996_v3_1p8_vco_enable(struct clk *c) -{ - return hdmi_8996_vco_enable(c, HDMI_VERSION_8996_V3_1_8); -} - -static int hdmi_8996_vco_get_lock_range(struct clk *c, unsigned long pixel_clk) -{ - u32 rng = 64, cmp_cnt = 1024; - u32 coreclk_div = 5, clks_pll_divsel = 2; - u32 vco_freq, vco_ratio, ppm_range; - u64 bclk; - struct hdmi_8996_v3_post_divider pd; - - bclk = ((u64)pixel_clk) * HDMI_BIT_CLK_TO_PIX_CLK_RATIO; - - DEV_DBG("%s: rate=%ld\n", __func__, pixel_clk); - - if (hdmi_8996_v3_get_post_div(&pd, bclk) || - pd.vco_ratio <= 0 || pd.vco_freq <= 0) { - DEV_ERR("%s: couldn't get post div\n", __func__); - return -EINVAL; - } - - do_div(pd.vco_freq, HDMI_KHZ_TO_HZ * HDMI_KHZ_TO_HZ); - - vco_freq = (u32) pd.vco_freq; - vco_ratio = (u32) pd.vco_ratio; - - DEV_DBG("%s: freq %d, ratio %d\n", __func__, - vco_freq, vco_ratio); - - ppm_range = (rng * HDMI_REF_CLOCK) / cmp_cnt; - ppm_range /= vco_freq / vco_ratio; - ppm_range *= coreclk_div * clks_pll_divsel; - - DEV_DBG("%s: ppm range: %d\n", __func__, ppm_range); - - return ppm_range; -} - -static int hdmi_8996_vco_rate_atomic_update(struct clk *c, - unsigned long rate, u32 ver) -{ - struct hdmi_pll_vco_clk *vco = to_hdmi_8996_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - void __iomem *pll; - struct hdmi_8996_phy_pll_reg_cfg cfg = {0}; - int rc = 0; - - rc = hdmi_8996_calculate(rate, &cfg, ver); - if (rc) { - DEV_ERR("%s: PLL calculation failed\n", __func__); - goto end; - } - - pll = io->pll_base; - - MDSS_PLL_REG_W(pll, QSERDES_COM_DEC_START_MODE0, - cfg.com_dec_start_mode0); - MDSS_PLL_REG_W(pll, QSERDES_COM_DIV_FRAC_START1_MODE0, - cfg.com_div_frac_start1_mode0); - MDSS_PLL_REG_W(pll, QSERDES_COM_DIV_FRAC_START2_MODE0, - cfg.com_div_frac_start2_mode0); - MDSS_PLL_REG_W(pll, QSERDES_COM_DIV_FRAC_START3_MODE0, - cfg.com_div_frac_start3_mode0); - - MDSS_PLL_REG_W(pll, QSERDES_COM_FREQ_UPDATE, 0x01); - MDSS_PLL_REG_W(pll, QSERDES_COM_FREQ_UPDATE, 0x00); - - DEV_DBG("%s: updated to rate %ld\n", __func__, rate); -end: - return rc; -} - -static int hdmi_8996_vco_set_rate(struct clk *c, unsigned long rate, u32 ver) -{ - struct hdmi_pll_vco_clk *vco = to_hdmi_8996_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - unsigned int set_power_dwn = 0; - bool atomic_update = false; - int rc, pll_lock_range; - - rc = mdss_pll_resource_enable(io, true); - if (rc) { - DEV_ERR("pll resource can't be enabled\n"); - return rc; - } - - DEV_DBG("%s: rate %ld\n", __func__, rate); - - if (MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_C_READY_STATUS) & BIT(0) && - MDSS_PLL_REG_R(io->phy_base, HDMI_PHY_STATUS) & BIT(0)) { - pll_lock_range = hdmi_8996_vco_get_lock_range(c, vco->rate); - - if (pll_lock_range > 0 && vco->rate) { - u32 range_limit; - - range_limit = vco->rate * - (pll_lock_range / HDMI_KHZ_TO_HZ); - range_limit /= HDMI_KHZ_TO_HZ; - - DEV_DBG("%s: range limit %d\n", __func__, range_limit); - - if (abs(rate - vco->rate) < range_limit) - atomic_update = true; - } - } - - if (io->pll_on && !atomic_update) - set_power_dwn = 1; - - if (atomic_update) { - hdmi_8996_vco_rate_atomic_update(c, rate, ver); - } else { - rc = hdmi_8996_phy_pll_set_clk_rate(c, rate, ver); - if (rc) - DEV_ERR("%s: Failed to set clk rate\n", __func__); - } - - mdss_pll_resource_enable(io, false); - - if (set_power_dwn) - hdmi_8996_vco_enable(c, ver); - - vco->rate = rate; - vco->rate_set = true; - - return 0; -} - -static int hdmi_8996_v1_vco_set_rate(struct clk *c, unsigned long rate) -{ - return hdmi_8996_vco_set_rate(c, rate, HDMI_VERSION_8996_V1); -} - -static int hdmi_8996_v2_vco_set_rate(struct clk *c, unsigned long rate) -{ - return hdmi_8996_vco_set_rate(c, rate, HDMI_VERSION_8996_V2); -} - -static int hdmi_8996_v3_vco_set_rate(struct clk *c, unsigned long rate) -{ - return hdmi_8996_vco_set_rate(c, rate, HDMI_VERSION_8996_V3); -} - -static int hdmi_8996_v3_1p8_vco_set_rate(struct clk *c, unsigned long rate) -{ - return hdmi_8996_vco_set_rate(c, rate, HDMI_VERSION_8996_V3_1_8); -} - -static unsigned long hdmi_get_hsclk_sel_divisor(unsigned long hsclk_sel) -{ - unsigned long divisor; - - switch (hsclk_sel) { - case 0: - divisor = 2; - break; - case 1: - divisor = 6; - break; - case 2: - divisor = 10; - break; - case 3: - divisor = 14; - break; - case 4: - divisor = 3; - break; - case 5: - divisor = 9; - break; - case 6: - case 13: - divisor = 15; - break; - case 7: - divisor = 21; - break; - case 8: - divisor = 4; - break; - case 9: - divisor = 12; - break; - case 10: - divisor = 20; - break; - case 11: - divisor = 28; - break; - case 12: - divisor = 5; - break; - case 14: - divisor = 25; - break; - case 15: - divisor = 35; - break; - default: - divisor = 1; - DEV_ERR("%s: invalid hsclk_sel value = %lu", - __func__, hsclk_sel); - break; - } - - return divisor; -} - -static unsigned long hdmi_8996_vco_get_rate(struct clk *c) -{ - unsigned long freq = 0, hsclk_sel = 0, tx_band = 0, dec_start = 0, - div_frac_start = 0, vco_clock_freq = 0; - struct hdmi_pll_vco_clk *vco = to_hdmi_8996_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - - if (mdss_pll_resource_enable(io, true)) { - DEV_ERR("%s: pll resource can't be enabled\n", __func__); - return freq; - } - - dec_start = MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_DEC_START_MODE0); - - div_frac_start = - MDSS_PLL_REG_R(io->pll_base, - QSERDES_COM_DIV_FRAC_START1_MODE0) | - MDSS_PLL_REG_R(io->pll_base, - QSERDES_COM_DIV_FRAC_START2_MODE0) << 8 | - MDSS_PLL_REG_R(io->pll_base, - QSERDES_COM_DIV_FRAC_START3_MODE0) << 16; - - vco_clock_freq = (dec_start + (div_frac_start / (1 << 20))) - * 4 * (HDMI_REF_CLOCK); - - hsclk_sel = MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_HSCLK_SEL) & 0x15; - hsclk_sel = hdmi_get_hsclk_sel_divisor(hsclk_sel); - tx_band = MDSS_PLL_REG_R(io->pll_base + HDMI_TX_L0_BASE_OFFSET, - QSERDES_TX_L0_TX_BAND) & 0x3; - - freq = vco_clock_freq / (10 * hsclk_sel * (1 << tx_band)); - - mdss_pll_resource_enable(io, false); - - DEV_DBG("%s: freq = %lu\n", __func__, freq); - - return freq; -} - -static long hdmi_8996_vco_round_rate(struct clk *c, unsigned long rate) -{ - unsigned long rrate = rate; - - DEV_DBG("rrate=%ld\n", rrate); - - return rrate; -} - -static int hdmi_8996_vco_prepare(struct clk *c, u32 ver) -{ - struct hdmi_pll_vco_clk *vco = to_hdmi_8996_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - int ret = 0; - - DEV_DBG("rate=%ld\n", vco->rate); - - if (!vco->rate_set && vco->rate) - ret = hdmi_8996_vco_set_rate(c, vco->rate, ver); - - if (!ret) { - ret = mdss_pll_resource_enable(io, true); - if (ret) - DEV_ERR("pll resource can't be enabled\n"); - } - - return ret; -} - -static int hdmi_8996_v1_vco_prepare(struct clk *c) -{ - return hdmi_8996_vco_prepare(c, HDMI_VERSION_8996_V1); -} - -static int hdmi_8996_v2_vco_prepare(struct clk *c) -{ - return hdmi_8996_vco_prepare(c, HDMI_VERSION_8996_V2); -} - -static int hdmi_8996_v3_vco_prepare(struct clk *c) -{ - return hdmi_8996_vco_prepare(c, HDMI_VERSION_8996_V3); -} - -static int hdmi_8996_v3_1p8_vco_prepare(struct clk *c) -{ - return hdmi_8996_vco_prepare(c, HDMI_VERSION_8996_V3_1_8); -} - -static void hdmi_8996_vco_unprepare(struct clk *c) -{ - struct hdmi_pll_vco_clk *vco = to_hdmi_8996_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - - vco->rate_set = false; - - if (!io) { - DEV_ERR("Invalid input parameter\n"); - return; - } - - if (!io->pll_on && - mdss_pll_resource_enable(io, true)) { - DEV_ERR("pll resource can't be enabled\n"); - return; - } - - io->handoff_resources = false; - mdss_pll_resource_enable(io, false); - io->pll_on = false; -} - -static enum handoff hdmi_8996_vco_handoff(struct clk *c) -{ - enum handoff ret = HANDOFF_DISABLED_CLK; - struct hdmi_pll_vco_clk *vco = to_hdmi_8996_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - - if (is_gdsc_disabled(io)) - return HANDOFF_DISABLED_CLK; - - if (mdss_pll_resource_enable(io, true)) { - DEV_ERR("pll resource can't be enabled\n"); - return ret; - } - - io->handoff_resources = true; - - if (MDSS_PLL_REG_R(io->pll_base, QSERDES_COM_C_READY_STATUS) & BIT(0)) { - if (MDSS_PLL_REG_R(io->phy_base, HDMI_PHY_STATUS) & BIT(0)) { - io->pll_on = true; - c->rate = hdmi_8996_vco_get_rate(c); - vco->rate = c->rate; - ret = HANDOFF_ENABLED_CLK; - } else { - io->handoff_resources = false; - mdss_pll_resource_enable(io, false); - DEV_DBG("%s: PHY not ready\n", __func__); - } - } else { - io->handoff_resources = false; - mdss_pll_resource_enable(io, false); - DEV_DBG("%s: PLL not locked\n", __func__); - } - - DEV_DBG("done, ret=%d\n", ret); - return ret; -} - -static const struct clk_ops hdmi_8996_v1_vco_clk_ops = { - .enable = hdmi_8996_v1_vco_enable, - .set_rate = hdmi_8996_v1_vco_set_rate, - .get_rate = hdmi_8996_vco_get_rate, - .round_rate = hdmi_8996_vco_round_rate, - .prepare = hdmi_8996_v1_vco_prepare, - .unprepare = hdmi_8996_vco_unprepare, - .handoff = hdmi_8996_vco_handoff, -}; - -static const struct clk_ops hdmi_8996_v2_vco_clk_ops = { - .enable = hdmi_8996_v2_vco_enable, - .set_rate = hdmi_8996_v2_vco_set_rate, - .get_rate = hdmi_8996_vco_get_rate, - .round_rate = hdmi_8996_vco_round_rate, - .prepare = hdmi_8996_v2_vco_prepare, - .unprepare = hdmi_8996_vco_unprepare, - .handoff = hdmi_8996_vco_handoff, -}; - -static const struct clk_ops hdmi_8996_v3_vco_clk_ops = { - .enable = hdmi_8996_v3_vco_enable, - .set_rate = hdmi_8996_v3_vco_set_rate, - .get_rate = hdmi_8996_vco_get_rate, - .round_rate = hdmi_8996_vco_round_rate, - .prepare = hdmi_8996_v3_vco_prepare, - .unprepare = hdmi_8996_vco_unprepare, - .handoff = hdmi_8996_vco_handoff, -}; - -static const struct clk_ops hdmi_8996_v3_1p8_vco_clk_ops = { - .enable = hdmi_8996_v3_1p8_vco_enable, - .set_rate = hdmi_8996_v3_1p8_vco_set_rate, - .get_rate = hdmi_8996_vco_get_rate, - .round_rate = hdmi_8996_vco_round_rate, - .prepare = hdmi_8996_v3_1p8_vco_prepare, - .unprepare = hdmi_8996_vco_unprepare, - .handoff = hdmi_8996_vco_handoff, -}; - - -static struct hdmi_pll_vco_clk hdmi_vco_clk = { - .c = { - .dbg_name = "hdmi_8996_vco_clk", - .ops = &hdmi_8996_v1_vco_clk_ops, - CLK_INIT(hdmi_vco_clk.c), - }, -}; - -static struct clk_lookup hdmipllcc_8996[] = { - CLK_LIST(hdmi_vco_clk), -}; - -int hdmi_8996_pll_clock_register(struct platform_device *pdev, - struct mdss_pll_resources *pll_res, u32 ver) -{ - int rc = -ENOTSUPP; - - if (!pll_res || !pll_res->phy_base || !pll_res->pll_base) { - DEV_ERR("%s: Invalid input parameters\n", __func__); - return -EPROBE_DEFER; - } - - /* Set client data for vco, mux and div clocks */ - hdmi_vco_clk.priv = pll_res; - - switch (ver) { - case HDMI_VERSION_8996_V2: - hdmi_vco_clk.c.ops = &hdmi_8996_v2_vco_clk_ops; - break; - case HDMI_VERSION_8996_V3: - hdmi_vco_clk.c.ops = &hdmi_8996_v3_vco_clk_ops; - break; - case HDMI_VERSION_8996_V3_1_8: - hdmi_vco_clk.c.ops = &hdmi_8996_v3_1p8_vco_clk_ops; - break; - default: - hdmi_vco_clk.c.ops = &hdmi_8996_v1_vco_clk_ops; - break; - } - - rc = of_msm_clock_register(pdev->dev.of_node, hdmipllcc_8996, - ARRAY_SIZE(hdmipllcc_8996)); - if (rc) { - DEV_ERR("%s: Clock register failed rc=%d\n", __func__, rc); - rc = -EPROBE_DEFER; - } else { - DEV_DBG("%s SUCCESS\n", __func__); - } - - return rc; -} - -int hdmi_8996_v1_pll_clock_register(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - return hdmi_8996_pll_clock_register(pdev, pll_res, - HDMI_VERSION_8996_V1); -} - -int hdmi_8996_v2_pll_clock_register(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - return hdmi_8996_pll_clock_register(pdev, pll_res, - HDMI_VERSION_8996_V2); -} - -int hdmi_8996_v3_pll_clock_register(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - return hdmi_8996_pll_clock_register(pdev, pll_res, - HDMI_VERSION_8996_V3); -} - -int hdmi_8996_v3_1p8_pll_clock_register(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - return hdmi_8996_pll_clock_register(pdev, pll_res, - HDMI_VERSION_8996_V3_1_8); -} diff --git a/drivers/clk/qcom/mdss/mdss-hdmi-pll-8998.c b/drivers/clk/qcom/mdss/mdss-hdmi-pll-8998.c deleted file mode 100644 index 488ec9f6343f1ec931872e1d3c51fcdf681e2863..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-hdmi-pll-8998.c +++ /dev/null @@ -1,827 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mdss-pll.h" -#include "mdss-hdmi-pll.h" - -#define _W(x, y, z) MDSS_PLL_REG_W(x, y, z) -#define _R(x, y) MDSS_PLL_REG_R(x, y) - -/* PLL REGISTERS */ -#define BIAS_EN_CLKBUFLR_EN (0x034) -#define CLK_ENABLE1 (0x038) -#define SYS_CLK_CTRL (0x03C) -#define SYSCLK_BUF_ENABLE (0x040) -#define PLL_IVCO (0x048) -#define CP_CTRL_MODE0 (0x060) -#define PLL_RCTRL_MODE0 (0x068) -#define PLL_CCTRL_MODE0 (0x070) -#define SYSCLK_EN_SEL (0x080) -#define RESETSM_CNTRL (0x088) -#define LOCK_CMP_EN (0x090) -#define LOCK_CMP1_MODE0 (0x098) -#define LOCK_CMP2_MODE0 (0x09C) -#define LOCK_CMP3_MODE0 (0x0A0) -#define DEC_START_MODE0 (0x0B0) -#define DIV_FRAC_START1_MODE0 (0x0B8) -#define DIV_FRAC_START2_MODE0 (0x0BC) -#define DIV_FRAC_START3_MODE0 (0x0C0) -#define INTEGLOOP_GAIN0_MODE0 (0x0D8) -#define INTEGLOOP_GAIN1_MODE0 (0x0DC) -#define VCO_TUNE_CTRL (0x0EC) -#define VCO_TUNE_MAP (0x0F0) -#define CLK_SELECT (0x138) -#define HSCLK_SEL (0x13C) -#define CORECLK_DIV_MODE0 (0x148) -#define CORE_CLK_EN (0x154) -#define C_READY_STATUS (0x158) -#define SVS_MODE_CLK_SEL (0x164) - -/* Tx Channel PHY registers */ -#define PHY_TX_EMP_POST1_LVL(n) ((((n) * 0x200) + 0x400) + 0x000) -#define PHY_TX_INTERFACE_SELECT_TX_BAND(n) ((((n) * 0x200) + 0x400) + 0x008) -#define PHY_TX_CLKBUF_TERM_ENABLE(n) ((((n) * 0x200) + 0x400) + 0x00C) -#define PHY_TX_DRV_LVL_RES_CODE_OFFSET(n) ((((n) * 0x200) + 0x400) + 0x014) -#define PHY_TX_DRV_LVL(n) ((((n) * 0x200) + 0x400) + 0x018) -#define PHY_TX_LANE_CONFIG(n) ((((n) * 0x200) + 0x400) + 0x01C) -#define PHY_TX_PRE_DRIVER_1(n) ((((n) * 0x200) + 0x400) + 0x024) -#define PHY_TX_PRE_DRIVER_2(n) ((((n) * 0x200) + 0x400) + 0x028) -#define PHY_TX_LANE_MODE(n) ((((n) * 0x200) + 0x400) + 0x02C) - -/* HDMI PHY registers */ -#define PHY_CFG (0x00) -#define PHY_PD_CTL (0x04) -#define PHY_MODE (0x10) -#define PHY_CLOCK (0x5C) -#define PHY_CMN_CTRL (0x68) -#define PHY_STATUS (0xB4) - -#define HDMI_BIT_CLK_TO_PIX_CLK_RATIO 10 -#define HDMI_MHZ_TO_HZ 1000000 -#define HDMI_HZ_TO_MHZ 1000000 -#define HDMI_REF_CLOCK_MHZ 19.2 -#define HDMI_REF_CLOCK_HZ (HDMI_REF_CLOCK_MHZ * 1000000) -#define HDMI_VCO_MIN_RATE_HZ 25000000 -#define HDMI_VCO_MAX_RATE_HZ 600000000 - -struct 8998_reg_cfg { - u32 tx_band; - u32 svs_mode_clk_sel; - u32 hsclk_sel; - u32 lock_cmp_en; - u32 cctrl_mode0; - u32 rctrl_mode0; - u32 cpctrl_mode0; - u32 dec_start_mode0; - u32 div_frac_start1_mode0; - u32 div_frac_start2_mode0; - u32 div_frac_start3_mode0; - u32 integloop_gain0_mode0; - u32 integloop_gain1_mode0; - u32 lock_cmp1_mode0; - u32 lock_cmp2_mode0; - u32 lock_cmp3_mode0; - u32 ssc_per1; - u32 ssc_per2; - u32 ssc_step_size1; - u32 ssc_step_size2; - u32 core_clk_en; - u32 coreclk_div_mode0; - u32 phy_mode; - u32 vco_freq; - u32 hsclk_divsel; - u32 vco_ratio; - u32 ssc_en_center; - - u32 l0_tx_drv_lvl; - u32 l0_tx_emp_post1_lvl; - u32 l1_tx_drv_lvl; - u32 l1_tx_emp_post1_lvl; - u32 l2_tx_drv_lvl; - u32 l2_tx_emp_post1_lvl; - u32 l3_tx_drv_lvl; - u32 l3_tx_emp_post1_lvl; - - u32 l0_pre_driver_1; - u32 l0_pre_driver_2; - u32 l1_pre_driver_1; - u32 l1_pre_driver_2; - u32 l2_pre_driver_1; - u32 l2_pre_driver_2; - u32 l3_pre_driver_1; - u32 l3_pre_driver_2; - - bool debug; -}; - -static void hdmi_8998_get_div(struct 8998_reg_cfg * cfg, unsigned long pclk) -{ - u32 const ratio_list[] = {1, 2, 3, 4, 5, 6, - 9, 10, 12, 15, 25}; - u32 const band_list[] = {0, 1, 2, 3}; - u32 const sz_ratio = ARRAY_SIZE(ratio_list); - u32 const sz_band = ARRAY_SIZE(band_list); - u32 const min_freq = 8000, max_freq = 12000; - u32 const cmp_cnt = 1024; - u32 const th_min = 500, th_max = 1000; - u64 bit_clk = pclk * HDMI_BIT_CLK_TO_PIX_CLK_RATIO; - u32 half_rate_mode = 0; - u32 freq_optimal, list_elements; - int optimal_index; - u32 i, j, k; - u32 freq_list[sz_ratio * sz_band]; - u32 found_hsclk_divsel = 0, found_vco_ratio; - u32 found_tx_band_sel, found_vco_freq; - -find_optimal_index: - freq_optimal = max_freq; - optimal_index = -1; - list_elements = 0; - - for (i = 0; i < sz_ratio; i++) { - for (j = 0; j < sz_band; j++) { - u64 freq = (bit_clk / (1 << half_rate_mode)); - - freq *= (ratio_list[i] * (1 << band_list[j])); - do_div(freq, (u64) HDMI_MHZ_TO_HZ); - freq_list[list_elements++] = freq; - } - } - - for (k = 0; k < ARRAY_SIZE(freq_list); k++) { - u32 const clks_pll_div = 2, core_clk_div = 5; - u32 const rng1 = 16, rng2 = 8; - u32 core_clk, rvar1; - u32 th1, th2; - - core_clk = (((freq_list[k] / - ratio_list[k / sz_band]) / - clks_pll_div) / core_clk_div); - - rvar1 = HDMI_REF_CLOCK_HZ / cmp_cnt; - rvar1 *= rng1; - rvar1 /= core_clk; - - th1 = rvar1; - - rvar1 = HDMI_REF_CLOCK_HZ / cmp_cnt; - rvar1 *= rng2; - rvar1 /= core_clk; - - th2 = rvar1; - - if (freq_list[k] >= min_freq && - freq_list[k] <= max_freq) { - if ((th1 >= th_min && th1 <= th_max) || - (th2 >= th_min && th2 <= th_max)) { - if (freq_list[k] <= freq_optimal) { - freq_optimal = freq_list[k]; - optimal_index = k; - } - } - } - } - - if (optimal_index == -1) { - if (!half_rate_mode) { - half_rate_mode = 1; - goto find_optimal_index; - } else { - /* set to default values */ - found_vco_freq = max_freq; - found_hsclk_divsel = 0; - found_vco_ratio = 2; - found_tx_band_sel = 0; - pr_err("Config error for pclk %ld\n", pclk); - } - } else { - found_vco_ratio = ratio_list[optimal_index / sz_band]; - found_tx_band_sel = band_list[optimal_index % sz_band]; - found_vco_freq = freq_optimal; - } - - switch (found_vco_ratio) { - case 1: - found_hsclk_divsel = 15; - break; - case 2: - found_hsclk_divsel = 0; - break; - case 3: - found_hsclk_divsel = 4; - break; - case 4: - found_hsclk_divsel = 8; - break; - case 5: - found_hsclk_divsel = 12; - break; - case 6: - found_hsclk_divsel = 1; - break; - case 9: - found_hsclk_divsel = 5; - break; - case 10: - found_hsclk_divsel = 2; - break; - case 12: - found_hsclk_divsel = 9; - break; - case 15: - found_hsclk_divsel = 13; - break; - case 25: - found_hsclk_divsel = 14; - break; - } - - pr_debug("found_vco_freq=%d\n", found_vco_freq); - pr_debug("found_hsclk_divsel=%d\n", found_hsclk_divsel); - pr_debug("found_vco_ratio=%d\n", found_vco_ratio); - pr_debug("found_tx_band_sel=%d\n", found_tx_band_sel); - pr_debug("half_rate_mode=%d\n", half_rate_mode); - pr_debug("optimal_index=%d\n", optimal_index); - - cfg->vco_freq = found_vco_freq; - cfg->hsclk_divsel = found_hsclk_divsel; - cfg->vco_ratio = found_vco_ratio; - cfg->tx_band = found_tx_band_sel; -} - -static int hdmi_8998_config_phy(unsigned long rate, - struct 8998_reg_cfg * cfg) -{ - u64 const high_freq_bit_clk_threshold = 3400000000UL; - u64 const dig_freq_bit_clk_threshold = 1500000000UL; - u64 const mid_freq_bit_clk_threshold = 750000000; - u64 fdata, tmds_clk; - u64 pll_div = 4 * HDMI_REF_CLOCK_HZ; - u64 bclk; - u64 vco_freq_mhz; - u64 hsclk_sel, dec_start, div_frac_start; - u64 rem; - u64 cpctrl, rctrl, cctrl; - u64 integloop_gain; - u32 digclk_divsel; - u32 tmds_bclk_ratio; - u64 cmp_rng, cmp_cnt = 1024, pll_cmp; - bool gen_ssc = false; - - bclk = rate * HDMI_BIT_CLK_TO_PIX_CLK_RATIO; - - if (bclk > high_freq_bit_clk_threshold) { - tmds_clk = rate / 4; - tmds_bclk_ratio = 1; - } else { - tmds_clk = rate; - tmds_bclk_ratio = 0; - } - - hdmi_8998_get_div(cfg, rate); - - vco_freq_mhz = cfg->vco_freq * (u64) HDMI_HZ_TO_MHZ; - fdata = cfg->vco_freq; - do_div(fdata, cfg->vco_ratio); - - hsclk_sel = cfg->hsclk_divsel; - dec_start = vco_freq_mhz; - do_div(dec_start, pll_div); - - div_frac_start = vco_freq_mhz * (1 << 20); - rem = do_div(div_frac_start, pll_div); - div_frac_start -= (dec_start * (1 << 20)); - if (rem > (pll_div >> 1)) - div_frac_start++; - - if ((div_frac_start != 0) || gen_ssc) { - cpctrl = 0x8; - rctrl = 0x16; - cctrl = 0x34; - } else { - cpctrl = 0x30; - rctrl = 0x18; - cctrl = 0x2; - } - - digclk_divsel = (bclk > dig_freq_bit_clk_threshold) ? 0x1 : 0x2; - - integloop_gain = ((div_frac_start != 0) || - gen_ssc) ? 0x3F : 0xC4; - integloop_gain <<= digclk_divsel; - integloop_gain = (integloop_gain <= 2046 ? integloop_gain : 0x7FE); - - cmp_rng = gen_ssc ? 0x40 : 0x10; - - pll_cmp = cmp_cnt * fdata; - rem = do_div(pll_cmp, (u64)(HDMI_REF_CLOCK_MHZ * 10)); - if (rem > ((u64)(HDMI_REF_CLOCK_MHZ * 10) >> 1)) - pll_cmp++; - - pll_cmp = pll_cmp - 1; - - pr_debug("VCO_FREQ = %u\n", cfg->vco_freq); - pr_debug("FDATA = %llu\n", fdata); - pr_debug("DEC_START = %llu\n", dec_start); - pr_debug("DIV_FRAC_START = %llu\n", div_frac_start); - pr_debug("CPCTRL = %llu\n", cpctrl); - pr_debug("RCTRL = %llu\n", rctrl); - pr_debug("CCTRL = %llu\n", cctrl); - pr_debug("DIGCLK_DIVSEL = %u\n", digclk_divsel); - pr_debug("INTEGLOOP_GAIN = %llu\n", integloop_gain); - pr_debug("CMP_RNG = %llu\n", cmp_rng); - pr_debug("PLL_CMP = %llu\n", pll_cmp); - - cfg->svs_mode_clk_sel = (digclk_divsel & 0xFF); - cfg->hsclk_sel = (0x20 | hsclk_sel); - cfg->lock_cmp_en = (gen_ssc ? 0x4 : 0x0); - cfg->cctrl_mode0 = (cctrl & 0xFF); - cfg->rctrl_mode0 = (rctrl & 0xFF); - cfg->cpctrl_mode0 = (cpctrl & 0xFF); - cfg->dec_start_mode0 = (dec_start & 0xFF); - cfg->div_frac_start1_mode0 = (div_frac_start & 0xFF); - cfg->div_frac_start2_mode0 = ((div_frac_start & 0xFF00) >> 8); - cfg->div_frac_start3_mode0 = ((div_frac_start & 0xF0000) >> 16); - cfg->integloop_gain0_mode0 = (integloop_gain & 0xFF); - cfg->integloop_gain1_mode0 = (integloop_gain & 0xF00) >> 8; - cfg->lock_cmp1_mode0 = (pll_cmp & 0xFF); - cfg->lock_cmp2_mode0 = ((pll_cmp & 0xFF00) >> 8); - cfg->lock_cmp3_mode0 = ((pll_cmp & 0x30000) >> 16); - cfg->ssc_per1 = 0; - cfg->ssc_per2 = 0; - cfg->ssc_step_size1 = 0; - cfg->ssc_step_size2 = 0; - cfg->core_clk_en = 0x2C; - cfg->coreclk_div_mode0 = 0x5; - cfg->phy_mode = (tmds_bclk_ratio ? 0x5 : 0x4); - cfg->ssc_en_center = 0x0; - - if (bclk > high_freq_bit_clk_threshold) { - cfg->l0_tx_drv_lvl = 0xA; - cfg->l0_tx_emp_post1_lvl = 0x3; - cfg->l1_tx_drv_lvl = 0xA; - cfg->l1_tx_emp_post1_lvl = 0x3; - cfg->l2_tx_drv_lvl = 0xA; - cfg->l2_tx_emp_post1_lvl = 0x3; - cfg->l3_tx_drv_lvl = 0x8; - cfg->l3_tx_emp_post1_lvl = 0x3; - cfg->l0_pre_driver_1 = 0x0; - cfg->l0_pre_driver_2 = 0x1C; - cfg->l1_pre_driver_1 = 0x0; - cfg->l1_pre_driver_2 = 0x1C; - cfg->l2_pre_driver_1 = 0x0; - cfg->l2_pre_driver_2 = 0x1C; - cfg->l3_pre_driver_1 = 0x0; - cfg->l3_pre_driver_2 = 0x0; - } else if (bclk > dig_freq_bit_clk_threshold) { - cfg->l0_tx_drv_lvl = 0x9; - cfg->l0_tx_emp_post1_lvl = 0x3; - cfg->l1_tx_drv_lvl = 0x9; - cfg->l1_tx_emp_post1_lvl = 0x3; - cfg->l2_tx_drv_lvl = 0x9; - cfg->l2_tx_emp_post1_lvl = 0x3; - cfg->l3_tx_drv_lvl = 0x8; - cfg->l3_tx_emp_post1_lvl = 0x3; - cfg->l0_pre_driver_1 = 0x0; - cfg->l0_pre_driver_2 = 0x16; - cfg->l1_pre_driver_1 = 0x0; - cfg->l1_pre_driver_2 = 0x16; - cfg->l2_pre_driver_1 = 0x0; - cfg->l2_pre_driver_2 = 0x16; - cfg->l3_pre_driver_1 = 0x0; - cfg->l3_pre_driver_2 = 0x0; - } else if (bclk > mid_freq_bit_clk_threshold) { - cfg->l0_tx_drv_lvl = 0x9; - cfg->l0_tx_emp_post1_lvl = 0x3; - cfg->l1_tx_drv_lvl = 0x9; - cfg->l1_tx_emp_post1_lvl = 0x3; - cfg->l2_tx_drv_lvl = 0x9; - cfg->l2_tx_emp_post1_lvl = 0x3; - cfg->l3_tx_drv_lvl = 0x8; - cfg->l3_tx_emp_post1_lvl = 0x3; - cfg->l0_pre_driver_1 = 0x0; - cfg->l0_pre_driver_2 = 0x0E; - cfg->l1_pre_driver_1 = 0x0; - cfg->l1_pre_driver_2 = 0x0E; - cfg->l2_pre_driver_1 = 0x0; - cfg->l2_pre_driver_2 = 0x0E; - cfg->l3_pre_driver_1 = 0x0; - cfg->l3_pre_driver_2 = 0x0; - } else { - cfg->l0_tx_drv_lvl = 0x0; - cfg->l0_tx_emp_post1_lvl = 0x0; - cfg->l1_tx_drv_lvl = 0x0; - cfg->l1_tx_emp_post1_lvl = 0x0; - cfg->l2_tx_drv_lvl = 0x0; - cfg->l2_tx_emp_post1_lvl = 0x0; - cfg->l3_tx_drv_lvl = 0x0; - cfg->l3_tx_emp_post1_lvl = 0x0; - cfg->l0_pre_driver_1 = 0x0; - cfg->l0_pre_driver_2 = 0x01; - cfg->l1_pre_driver_1 = 0x0; - cfg->l1_pre_driver_2 = 0x01; - cfg->l2_pre_driver_1 = 0x0; - cfg->l2_pre_driver_2 = 0x01; - cfg->l3_pre_driver_1 = 0x0; - cfg->l3_pre_driver_2 = 0x0; - } - - return 0; -} - -static int hdmi_8998_pll_set_clk_rate(struct clk *c, unsigned long rate) -{ - int rc = 0; - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - struct 8998_reg_cfg cfg = {0}; - void __iomem *phy = io->phy_base, *pll = io->pll_base; - - rc = hdmi_8998_config_phy(rate, &cfg); - if (rc) { - pr_err("rate calculation failed\n, rc=%d\n", rc); - return rc; - } - - _W(phy, PHY_PD_CTL, 0x0); - udelay(500); - - _W(phy, PHY_PD_CTL, 0x1); - _W(pll, RESETSM_CNTRL, 0x20); - _W(phy, PHY_CMN_CTRL, 0x6); - _W(pll, PHY_TX_INTERFACE_SELECT_TX_BAND(0), cfg.tx_band); - _W(pll, PHY_TX_INTERFACE_SELECT_TX_BAND(1), cfg.tx_band); - _W(pll, PHY_TX_INTERFACE_SELECT_TX_BAND(2), cfg.tx_band); - _W(pll, PHY_TX_INTERFACE_SELECT_TX_BAND(3), cfg.tx_band); - _W(pll, PHY_TX_CLKBUF_TERM_ENABLE(0), 0x1); - _W(pll, PHY_TX_LANE_MODE(0), 0x20); - _W(pll, PHY_TX_LANE_MODE(1), 0x20); - _W(pll, PHY_TX_LANE_MODE(2), 0x20); - _W(pll, PHY_TX_LANE_MODE(3), 0x20); - _W(pll, PHY_TX_CLKBUF_TERM_ENABLE(1), 0x1); - _W(pll, PHY_TX_CLKBUF_TERM_ENABLE(2), 0x1); - _W(pll, PHY_TX_CLKBUF_TERM_ENABLE(3), 0x1); - _W(pll, SYSCLK_BUF_ENABLE, 0x2); - _W(pll, BIAS_EN_CLKBUFLR_EN, 0xB); - _W(pll, SYSCLK_EN_SEL, 0x37); - _W(pll, SYS_CLK_CTRL, 0x2); - _W(pll, CLK_ENABLE1, 0xE); - _W(pll, PLL_IVCO, 0xF); - _W(pll, VCO_TUNE_CTRL, 0x0); - _W(pll, SVS_MODE_CLK_SEL, cfg.svs_mode_clk_sel); - _W(pll, CLK_SELECT, 0x30); - _W(pll, HSCLK_SEL, cfg.hsclk_sel); - _W(pll, LOCK_CMP_EN, cfg.lock_cmp_en); - _W(pll, PLL_CCTRL_MODE0, cfg.cctrl_mode0); - _W(pll, PLL_RCTRL_MODE0, cfg.rctrl_mode0); - _W(pll, CP_CTRL_MODE0, cfg.cpctrl_mode0); - _W(pll, DEC_START_MODE0, cfg.dec_start_mode0); - _W(pll, DIV_FRAC_START1_MODE0, cfg.div_frac_start1_mode0); - _W(pll, DIV_FRAC_START2_MODE0, cfg.div_frac_start2_mode0); - _W(pll, DIV_FRAC_START3_MODE0, cfg.div_frac_start3_mode0); - _W(pll, INTEGLOOP_GAIN0_MODE0, cfg.integloop_gain0_mode0); - _W(pll, INTEGLOOP_GAIN1_MODE0, cfg.integloop_gain1_mode0); - _W(pll, LOCK_CMP1_MODE0, cfg.lock_cmp1_mode0); - _W(pll, LOCK_CMP2_MODE0, cfg.lock_cmp2_mode0); - _W(pll, LOCK_CMP3_MODE0, cfg.lock_cmp3_mode0); - _W(pll, VCO_TUNE_MAP, 0x0); - _W(pll, CORE_CLK_EN, cfg.core_clk_en); - _W(pll, CORECLK_DIV_MODE0, cfg.coreclk_div_mode0); - - _W(pll, PHY_TX_DRV_LVL(0), cfg.l0_tx_drv_lvl); - _W(pll, PHY_TX_DRV_LVL(1), cfg.l1_tx_drv_lvl); - _W(pll, PHY_TX_DRV_LVL(2), cfg.l2_tx_drv_lvl); - _W(pll, PHY_TX_DRV_LVL(3), cfg.l3_tx_drv_lvl); - - _W(pll, PHY_TX_EMP_POST1_LVL(0), cfg.l0_tx_emp_post1_lvl); - _W(pll, PHY_TX_EMP_POST1_LVL(1), cfg.l1_tx_emp_post1_lvl); - _W(pll, PHY_TX_EMP_POST1_LVL(2), cfg.l2_tx_emp_post1_lvl); - _W(pll, PHY_TX_EMP_POST1_LVL(3), cfg.l3_tx_emp_post1_lvl); - - _W(pll, PHY_TX_PRE_DRIVER_1(0), cfg.l0_pre_driver_1); - _W(pll, PHY_TX_PRE_DRIVER_1(1), cfg.l1_pre_driver_1); - _W(pll, PHY_TX_PRE_DRIVER_1(2), cfg.l2_pre_driver_1); - _W(pll, PHY_TX_PRE_DRIVER_1(3), cfg.l3_pre_driver_1); - - _W(pll, PHY_TX_PRE_DRIVER_2(0), cfg.l0_pre_driver_2); - _W(pll, PHY_TX_PRE_DRIVER_2(1), cfg.l1_pre_driver_2); - _W(pll, PHY_TX_PRE_DRIVER_2(2), cfg.l2_pre_driver_2); - _W(pll, PHY_TX_PRE_DRIVER_2(3), cfg.l3_pre_driver_2); - - _W(pll, PHY_TX_DRV_LVL_RES_CODE_OFFSET(0), 0x0); - _W(pll, PHY_TX_DRV_LVL_RES_CODE_OFFSET(1), 0x0); - _W(pll, PHY_TX_DRV_LVL_RES_CODE_OFFSET(2), 0x0); - _W(pll, PHY_TX_DRV_LVL_RES_CODE_OFFSET(3), 0x0); - - _W(phy, PHY_MODE, cfg.phy_mode); - - _W(pll, PHY_TX_LANE_CONFIG(0), 0x10); - _W(pll, PHY_TX_LANE_CONFIG(1), 0x10); - _W(pll, PHY_TX_LANE_CONFIG(2), 0x10); - _W(pll, PHY_TX_LANE_CONFIG(3), 0x10); - - /* Ensure all registers are flushed to hardware */ - wmb(); - - return 0; -} - -static int hdmi_8998_pll_lock_status(struct mdss_pll_resources *io) -{ - u32 const delay_us = 100; - u32 const timeout_us = 5000; - u32 status; - int rc = 0; - void __iomem *pll = io->pll_base; - - rc = mdss_pll_resource_enable(io, true); - if (rc) { - pr_err("pll resource can't be enabled\n"); - return rc; - } - rc = readl_poll_timeout_atomic(pll + C_READY_STATUS, - status, - ((status & BIT(0)) > 0), - delay_us, - timeout_us); - if (rc) - pr_err("HDMI PLL(%d) lock failed, status=0x%08x\n", - io->index, status); - else - pr_debug("HDMI PLL(%d) lock passed, status=0x%08x\n", - io->index, status); - - mdss_pll_resource_enable(io, false); - - return rc; -} - -static int hdmi_8998_phy_ready_status(struct mdss_pll_resources *io) -{ - u32 const delay_us = 100; - u32 const timeout_us = 5000; - u32 status; - int rc = 0; - void __iomem *phy = io->phy_base; - - rc = mdss_pll_resource_enable(io, true); - if (rc) { - pr_err("pll resource can't be enabled\n"); - return rc; - } - - rc = readl_poll_timeout_atomic(phy + PHY_STATUS, - status, - ((status & BIT(0)) > 0), - delay_us, - timeout_us); - if (rc) - pr_err("HDMI PHY(%d) not ready, status=0x%08x\n", - io->index, status); - else - pr_debug("HDMI PHY(%d) ready, status=0x%08x\n", - io->index, status); - - mdss_pll_resource_enable(io, false); - - return rc; -} - -static int hdmi_8998_vco_set_rate(struct clk *c, unsigned long rate) -{ - int rc = 0; - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - - rc = mdss_pll_resource_enable(io, true); - if (rc) { - pr_err("pll resource enable failed, rc=%d\n", rc); - return rc; - } - - if (io->pll_on) - goto error; - - rc = hdmi_8998_pll_set_clk_rate(c, rate); - if (rc) { - pr_err("failed to set clk rate, rc=%d\n", rc); - goto error; - } - - vco->rate = rate; - vco->rate_set = true; - -error: - (void)mdss_pll_resource_enable(io, false); - - return rc; -} - -static long hdmi_8998_vco_round_rate(struct clk *c, unsigned long rate) -{ - unsigned long rrate = rate; - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c); - - if (rate < vco->min_rate) - rrate = vco->min_rate; - if (rate > vco->max_rate) - rrate = vco->max_rate; - - return rrate; -} - -static int hdmi_8998_pll_enable(struct clk *c) -{ - int rc = 0; - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - void __iomem *phy = io->phy_base, *pll = io->pll_base; - - _W(phy, PHY_CFG, 0x1); - udelay(100); - _W(phy, PHY_CFG, 0x59); - udelay(100); - - _W(phy, PHY_CLOCK, 0x6); - - /* Ensure all registers are flushed to hardware */ - wmb(); - - rc = hdmi_8998_pll_lock_status(io); - if (rc) { - pr_err("PLL not locked, rc=%d\n", rc); - return rc; - } - - _W(pll, PHY_TX_LANE_CONFIG(0), 0x1F); - _W(pll, PHY_TX_LANE_CONFIG(1), 0x1F); - _W(pll, PHY_TX_LANE_CONFIG(2), 0x1F); - _W(pll, PHY_TX_LANE_CONFIG(3), 0x1F); - - /* Ensure all registers are flushed to hardware */ - wmb(); - - rc = hdmi_8998_phy_ready_status(io); - if (rc) { - pr_err("PHY NOT READY, rc=%d\n", rc); - return rc; - } - - _W(phy, PHY_CFG, 0x58); - udelay(1); - _W(phy, PHY_CFG, 0x59); - - /* Ensure all registers are flushed to hardware */ - wmb(); - - io->pll_on = true; - return rc; -} - -static int hdmi_8998_vco_prepare(struct clk *c) -{ - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - int rc = 0; - - if (!io) { - pr_err("hdmi pll resources are not available\n"); - return -EINVAL; - } - - rc = mdss_pll_resource_enable(io, true); - if (rc) { - pr_err("pll resource enable failed, rc=%d\n", rc); - return rc; - } - - if (!vco->rate_set && vco->rate) { - rc = hdmi_8998_pll_set_clk_rate(c, vco->rate); - if (rc) { - pr_err("set rate failed, rc=%d\n", rc); - goto error; - } - } - - rc = hdmi_8998_pll_enable(c); - if (rc) - pr_err("pll enabled failed, rc=%d\n", rc); - -error: - if (rc) - mdss_pll_resource_enable(io, false); - - return rc; -} - -static void hdmi_8998_pll_disable(struct hdmi_pll_vco_clk *vco) -{ - struct mdss_pll_resources *io = vco->priv; - void __iomem *phy = io->phy_base; - - if (!io->pll_on) - return; - - _W(phy, PHY_PD_CTL, 0x0); - - /* Ensure all registers are flushed to hardware */ - wmb(); - - vco->rate_set = false; - io->handoff_resources = false; - io->pll_on = false; -} - -static void hdmi_8998_vco_unprepare(struct clk *c) -{ - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - - if (!io) { - pr_err("HDMI pll resources not available\n"); - return; - } - - hdmi_8998_pll_disable(vco); - mdss_pll_resource_enable(io, false); -} - -static enum handoff hdmi_8998_vco_handoff(struct clk *c) -{ - enum handoff ret = HANDOFF_DISABLED_CLK; - struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c); - struct mdss_pll_resources *io = vco->priv; - - if (mdss_pll_resource_enable(io, true)) { - pr_err("pll resource can't be enabled\n"); - return ret; - } - - io->handoff_resources = true; - - if (_R(io->pll_base, C_READY_STATUS) & BIT(0) && - _R(io->phy_base, PHY_STATUS) & BIT(0)) { - io->pll_on = true; - /* TODO: calculate rate based on the phy/pll register values. */ - ret = HANDOFF_ENABLED_CLK; - } else { - io->handoff_resources = false; - mdss_pll_resource_enable(io, false); - pr_debug("%s: PHY/PLL not ready\n", __func__); - } - - pr_debug("done, ret=%d\n", ret); - return ret; -} - -static const struct clk_ops hdmi_8998_vco_clk_ops = { - .set_rate = hdmi_8998_vco_set_rate, - .round_rate = hdmi_8998_vco_round_rate, - .prepare = hdmi_8998_vco_prepare, - .unprepare = hdmi_8998_vco_unprepare, - .handoff = hdmi_8998_vco_handoff, -}; - -static struct hdmi_pll_vco_clk hdmi_vco_clk = { - .min_rate = HDMI_VCO_MIN_RATE_HZ, - .max_rate = HDMI_VCO_MAX_RATE_HZ, - .c = { - .dbg_name = "hdmi_8998_vco_clk", - .ops = &hdmi_8998_vco_clk_ops, - CLK_INIT(hdmi_vco_clk.c), - }, -}; - -static struct clk_lookup hdmipllcc_8998[] = { - CLK_LIST(hdmi_vco_clk), -}; - -int hdmi_8998_pll_clock_register(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int rc = 0; - - hdmi_vco_clk.priv = pll_res; - - rc = of_msm_clock_register(pdev->dev.of_node, hdmipllcc_8998, - ARRAY_SIZE(hdmipllcc_8998)); - if (rc) { - pr_err("clock register failed, rc=%d\n", rc); - return rc; - } - - return rc; -} diff --git a/drivers/clk/qcom/mdss/mdss-hdmi-pll.h b/drivers/clk/qcom/mdss/mdss-hdmi-pll.h deleted file mode 100644 index 03f6fa20ea801565511871d111f3a688c9b72914..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-hdmi-pll.h +++ /dev/null @@ -1,57 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. - */ - -#ifndef __MDSS_HDMI_PLL_H -#define __MDSS_HDMI_PLL_H - -struct hdmi_pll_cfg { - unsigned long vco_rate; - u32 reg; -}; - -struct hdmi_pll_vco_clk { - struct clk_hw hw; - unsigned long rate; /* current vco rate */ - unsigned long min_rate; /* min vco rate */ - unsigned long max_rate; /* max vco rate */ - bool rate_set; - struct hdmi_pll_cfg *ip_seti; - struct hdmi_pll_cfg *cp_seti; - struct hdmi_pll_cfg *ip_setp; - struct hdmi_pll_cfg *cp_setp; - struct hdmi_pll_cfg *crctrl; - void *priv; - -}; - -static inline struct hdmi_pll_vco_clk *to_hdmi_vco_clk_hw(struct clk_hw *hw) -{ - return container_of(hw, struct hdmi_pll_vco_clk, hw); -} - -int hdmi_pll_clock_register_28lpm(struct platform_device *pdev, - struct mdss_pll_resources *pll_res); - -int hdmi_pll_clock_register(struct platform_device *pdev, - struct mdss_pll_resources *pll_res); - -int hdmi_20nm_pll_clock_register(struct platform_device *pdev, - struct mdss_pll_resources *pll_res); - -int hdmi_8996_v1_pll_clock_register(struct platform_device *pdev, - struct mdss_pll_resources *pll_res); - -int hdmi_8996_v2_pll_clock_register(struct platform_device *pdev, - struct mdss_pll_resources *pll_res); - -int hdmi_8996_v3_pll_clock_register(struct platform_device *pdev, - struct mdss_pll_resources *pll_res); - -int hdmi_8996_v3_1p8_pll_clock_register(struct platform_device *pdev, - struct mdss_pll_resources *pll_res); - -int hdmi_8998_pll_clock_register(struct platform_device *pdev, - struct mdss_pll_resources *pll_res); -#endif diff --git a/drivers/clk/qcom/mdss/mdss-pll-util.c b/drivers/clk/qcom/mdss/mdss-pll-util.c deleted file mode 100644 index 4a543d77191173b50bcbc12618b0c3fda41f11d5..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-pll-util.c +++ /dev/null @@ -1,381 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include - -#include "mdss-pll.h" - -/** - * mdss_pll_get_mp_by_reg_name() -- Find power module by regulator name - *@pll_res: Pointer to the PLL resource - *@name: Regulator name as specified in the pll dtsi - * - * This is a helper function to retrieve the regulator information - * for each pll resource. - */ -struct dss_vreg *mdss_pll_get_mp_by_reg_name(struct mdss_pll_resources *pll_res - , char *name) -{ - - struct dss_vreg *regulator = NULL; - int i; - - if ((pll_res == NULL) || (pll_res->mp.vreg_config == NULL)) { - pr_err("%s Invalid PLL resource\n", __func__); - goto error; - } - - regulator = pll_res->mp.vreg_config; - - for (i = 0; i < pll_res->mp.num_vreg; i++) { - if (!strcmp(name, regulator->vreg_name)) { - pr_debug("Found regulator match for %s\n", name); - break; - } - regulator++; - } - -error: - return regulator; -} - -int mdss_pll_util_resource_enable(struct mdss_pll_resources *pll_res, - bool enable) -{ - int rc = 0; - struct dss_module_power *mp = &pll_res->mp; - - if (enable) { - rc = msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, enable); - if (rc) { - pr_err("Failed to enable vregs rc=%d\n", rc); - goto vreg_err; - } - - rc = msm_dss_clk_set_rate(mp->clk_config, mp->num_clk); - if (rc) { - pr_err("Failed to set clock rate rc=%d\n", rc); - goto clk_err; - } - - rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable); - if (rc) { - pr_err("clock enable failed rc:%d\n", rc); - goto clk_err; - } - } else { - msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable); - - msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, enable); - } - - return rc; - -clk_err: - msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, 0); -vreg_err: - return rc; -} - -static int mdss_pll_util_parse_dt_supply(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int i = 0, rc = 0; - u32 tmp = 0; - struct device_node *of_node = NULL, *supply_root_node = NULL; - struct device_node *supply_node = NULL; - struct dss_module_power *mp = &pll_res->mp; - - of_node = pdev->dev.of_node; - - mp->num_vreg = 0; - supply_root_node = of_get_child_by_name(of_node, - "qcom,platform-supply-entries"); - if (!supply_root_node) { - pr_err("no supply entry present\n"); - return rc; - } - - for_each_child_of_node(supply_root_node, supply_node) { - mp->num_vreg++; - } - - if (mp->num_vreg == 0) { - pr_debug("no vreg\n"); - return rc; - } - pr_debug("vreg found. count=%d\n", mp->num_vreg); - - mp->vreg_config = devm_kzalloc(&pdev->dev, sizeof(struct dss_vreg) * - mp->num_vreg, GFP_KERNEL); - if (!mp->vreg_config) { - rc = -ENOMEM; - return rc; - } - - for_each_child_of_node(supply_root_node, supply_node) { - - const char *st = NULL; - - rc = of_property_read_string(supply_node, - "qcom,supply-name", &st); - if (rc) { - pr_err(":error reading name. rc=%d\n", rc); - goto error; - } - - strlcpy(mp->vreg_config[i].vreg_name, st, - sizeof(mp->vreg_config[i].vreg_name)); - - rc = of_property_read_u32(supply_node, - "qcom,supply-min-voltage", &tmp); - if (rc) { - pr_err(": error reading min volt. rc=%d\n", rc); - goto error; - } - mp->vreg_config[i].min_voltage = tmp; - - rc = of_property_read_u32(supply_node, - "qcom,supply-max-voltage", &tmp); - if (rc) { - pr_err(": error reading max volt. rc=%d\n", rc); - goto error; - } - mp->vreg_config[i].max_voltage = tmp; - - rc = of_property_read_u32(supply_node, - "qcom,supply-enable-load", &tmp); - if (rc) { - pr_err(": error reading enable load. rc=%d\n", rc); - goto error; - } - mp->vreg_config[i].enable_load = tmp; - - rc = of_property_read_u32(supply_node, - "qcom,supply-disable-load", &tmp); - if (rc) { - pr_err(": error reading disable load. rc=%d\n", rc); - goto error; - } - mp->vreg_config[i].disable_load = tmp; - - rc = of_property_read_u32(supply_node, - "qcom,supply-pre-on-sleep", &tmp); - if (rc) - pr_debug("error reading supply pre sleep value. rc=%d\n", - rc); - - mp->vreg_config[i].pre_on_sleep = (!rc ? tmp : 0); - - rc = of_property_read_u32(supply_node, - "qcom,supply-pre-off-sleep", &tmp); - if (rc) - pr_debug("error reading supply pre sleep value. rc=%d\n", - rc); - - mp->vreg_config[i].pre_off_sleep = (!rc ? tmp : 0); - - rc = of_property_read_u32(supply_node, - "qcom,supply-post-on-sleep", &tmp); - if (rc) - pr_debug("error reading supply post sleep value. rc=%d\n", - rc); - - mp->vreg_config[i].post_on_sleep = (!rc ? tmp : 0); - - rc = of_property_read_u32(supply_node, - "qcom,supply-post-off-sleep", &tmp); - if (rc) - pr_debug("error reading supply post sleep value. rc=%d\n", - rc); - - mp->vreg_config[i].post_off_sleep = (!rc ? tmp : 0); - - pr_debug("%s min=%d, max=%d, enable=%d, disable=%d, preonsleep=%d, postonsleep=%d, preoffsleep=%d, postoffsleep=%d\n", - mp->vreg_config[i].vreg_name, - mp->vreg_config[i].min_voltage, - mp->vreg_config[i].max_voltage, - mp->vreg_config[i].enable_load, - mp->vreg_config[i].disable_load, - mp->vreg_config[i].pre_on_sleep, - mp->vreg_config[i].post_on_sleep, - mp->vreg_config[i].pre_off_sleep, - mp->vreg_config[i].post_off_sleep); - ++i; - - rc = 0; - } - - return rc; - -error: - if (mp->vreg_config) { - devm_kfree(&pdev->dev, mp->vreg_config); - mp->vreg_config = NULL; - mp->num_vreg = 0; - } - - return rc; -} - -static int mdss_pll_util_parse_dt_clock(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - u32 i = 0, rc = 0; - struct dss_module_power *mp = &pll_res->mp; - const char *clock_name; - u32 clock_rate; - - mp->num_clk = of_property_count_strings(pdev->dev.of_node, - "clock-names"); - if (mp->num_clk <= 0) { - pr_err("clocks are not defined\n"); - goto clk_err; - } - - mp->clk_config = devm_kzalloc(&pdev->dev, - sizeof(struct dss_clk) * mp->num_clk, GFP_KERNEL); - if (!mp->clk_config) { - rc = -ENOMEM; - mp->num_clk = 0; - goto clk_err; - } - - for (i = 0; i < mp->num_clk; i++) { - of_property_read_string_index(pdev->dev.of_node, "clock-names", - i, &clock_name); - strlcpy(mp->clk_config[i].clk_name, clock_name, - sizeof(mp->clk_config[i].clk_name)); - - of_property_read_u32_index(pdev->dev.of_node, "clock-rate", - i, &clock_rate); - mp->clk_config[i].rate = clock_rate; - - if (!clock_rate) - mp->clk_config[i].type = DSS_CLK_AHB; - else - mp->clk_config[i].type = DSS_CLK_PCLK; - } - -clk_err: - return rc; -} - -static void mdss_pll_free_bootmem(u32 mem_addr, u32 size) -{ - unsigned long pfn_start, pfn_end, pfn_idx; - - pfn_start = mem_addr >> PAGE_SHIFT; - pfn_end = (mem_addr + size) >> PAGE_SHIFT; - for (pfn_idx = pfn_start; pfn_idx < pfn_end; pfn_idx++) - free_reserved_page(pfn_to_page(pfn_idx)); -} - -static int mdss_pll_util_parse_dt_dfps(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int rc = 0; - struct device_node *pnode; - const u32 *addr; - struct vm_struct *area; - u64 size; - u32 offsets[2]; - unsigned long virt_add; - - pnode = of_parse_phandle(pdev->dev.of_node, "memory-region", 0); - if (IS_ERR_OR_NULL(pnode)) { - rc = PTR_ERR(pnode); - goto pnode_err; - } - - addr = of_get_address(pnode, 0, &size, NULL); - if (!addr) { - pr_err("failed to parse the dfps memory address\n"); - rc = -EINVAL; - goto pnode_err; - } - /* maintain compatibility for 32/64 bit */ - offsets[0] = (u32) of_read_ulong(addr, 2); - offsets[1] = (u32) size; - - area = get_vm_area(offsets[1], VM_IOREMAP); - if (!area) { - rc = -ENOMEM; - goto dfps_mem_err; - } - - virt_add = (unsigned long)area->addr; - rc = ioremap_page_range(virt_add, (virt_add + offsets[1]), - offsets[0], PAGE_KERNEL); - if (rc) { - rc = -ENOMEM; - goto ioremap_err; - } - - pll_res->dfps = kzalloc(sizeof(struct dfps_info), GFP_KERNEL); - if (IS_ERR_OR_NULL(pll_res->dfps)) { - rc = PTR_ERR(pll_res->dfps); - pr_err("couldn't allocate dfps kernel memory\n"); - goto addr_err; - } - - /* memcopy complete dfps structure from kernel virtual memory */ - memcpy_fromio(pll_res->dfps, area->addr, sizeof(struct dfps_info)); - -addr_err: - if (virt_add) - unmap_kernel_range(virt_add, (unsigned long) size); -ioremap_err: - if (area) - vfree(area->addr); -dfps_mem_err: - /* free the dfps memory here */ - memblock_free(offsets[0], offsets[1]); - mdss_pll_free_bootmem(offsets[0], offsets[1]); -pnode_err: - if (pnode) - of_node_put(pnode); - - dma_release_declared_memory(&pdev->dev); - return rc; -} - -int mdss_pll_util_resource_parse(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int rc = 0; - struct dss_module_power *mp = &pll_res->mp; - - rc = mdss_pll_util_parse_dt_supply(pdev, pll_res); - if (rc) { - pr_err("vreg parsing failed rc=%d\n", rc); - goto end; - } - - rc = mdss_pll_util_parse_dt_clock(pdev, pll_res); - if (rc) { - pr_err("clock name parsing failed rc=%d\n", rc); - goto clk_err; - } - - if (mdss_pll_util_parse_dt_dfps(pdev, pll_res)) - pr_err("dfps not enabled!\n"); - - return rc; - -clk_err: - devm_kfree(&pdev->dev, mp->vreg_config); - mp->num_vreg = 0; -end: - return rc; -} diff --git a/drivers/clk/qcom/mdss/mdss-pll.c b/drivers/clk/qcom/mdss/mdss-pll.c deleted file mode 100644 index 7b95b1071556508328ad41735652a4b9cfba2e06..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-pll.c +++ /dev/null @@ -1,393 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include "mdss-pll.h" -#include "mdss-dsi-pll.h" -#include "mdss-dp-pll.h" -#include "mdss-hdmi-pll.h" - -int mdss_pll_resource_enable(struct mdss_pll_resources *pll_res, bool enable) -{ - int rc = 0; - int changed = 0; - - if (!pll_res) { - pr_err("Invalid input parameters\n"); - return -EINVAL; - } - - /* - * Don't turn off resources during handoff or add more than - * 1 refcount. - */ - if (pll_res->handoff_resources && - (!enable || (enable & pll_res->resource_enable))) { - pr_debug("Do not turn on/off pll resources during handoff case\n"); - return rc; - } - - if (enable) { - if (pll_res->resource_ref_cnt == 0) - changed++; - pll_res->resource_ref_cnt++; - } else { - if (pll_res->resource_ref_cnt) { - pll_res->resource_ref_cnt--; - if (pll_res->resource_ref_cnt == 0) - changed++; - } else { - pr_err("PLL Resources already OFF\n"); - } - } - - if (changed) { - rc = mdss_pll_util_resource_enable(pll_res, enable); - if (rc) - pr_err("Resource update failed rc=%d\n", rc); - else - pll_res->resource_enable = enable; - } - - return rc; -} - -static int mdss_pll_resource_init(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int rc = 0; - struct dss_module_power *mp = &pll_res->mp; - - rc = msm_dss_config_vreg(&pdev->dev, - mp->vreg_config, mp->num_vreg, 1); - if (rc) { - pr_err("Vreg config failed rc=%d\n", rc); - goto vreg_err; - } - - rc = msm_dss_get_clk(&pdev->dev, mp->clk_config, mp->num_clk); - if (rc) { - pr_err("Clock get failed rc=%d\n", rc); - goto clk_err; - } - - return rc; - -clk_err: - msm_dss_config_vreg(&pdev->dev, mp->vreg_config, mp->num_vreg, 0); -vreg_err: - return rc; -} - -static void mdss_pll_resource_deinit(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - struct dss_module_power *mp = &pll_res->mp; - - msm_dss_put_clk(mp->clk_config, mp->num_clk); - - msm_dss_config_vreg(&pdev->dev, mp->vreg_config, mp->num_vreg, 0); -} - -static void mdss_pll_resource_release(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - struct dss_module_power *mp = &pll_res->mp; - - mp->num_vreg = 0; - mp->num_clk = 0; -} - -static int mdss_pll_resource_parse(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int rc = 0; - const char *compatible_stream; - - rc = mdss_pll_util_resource_parse(pdev, pll_res); - if (rc) { - pr_err("Failed to parse the resources rc=%d\n", rc); - goto end; - } - - compatible_stream = of_get_property(pdev->dev.of_node, - "compatible", NULL); - if (!compatible_stream) { - pr_err("Failed to parse the compatible stream\n"); - goto err; - } - - if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_10nm")) - pll_res->pll_interface_type = MDSS_DSI_PLL_10NM; - if (!strcmp(compatible_stream, "qcom,mdss_dp_pll_10nm")) - pll_res->pll_interface_type = MDSS_DP_PLL_10NM; - else if (!strcmp(compatible_stream, "qcom,mdss_dp_pll_7nm")) - pll_res->pll_interface_type = MDSS_DP_PLL_7NM; - else if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_7nm")) - pll_res->pll_interface_type = MDSS_DSI_PLL_7NM; - else if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_7nm_v2")) - pll_res->pll_interface_type = MDSS_DSI_PLL_7NM_V2; - else if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_7nm_v4_1")) - pll_res->pll_interface_type = MDSS_DSI_PLL_7NM_V4_1; - else if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_28lpm")) - pll_res->pll_interface_type = MDSS_DSI_PLL_28LPM; - else if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_14nm")) - pll_res->pll_interface_type = MDSS_DSI_PLL_14NM; - else if (!strcmp(compatible_stream, "qcom,mdss_dp_pll_14nm")) - pll_res->pll_interface_type = MDSS_DP_PLL_14NM; - else if (!strcmp(compatible_stream, "qcom,mdss_hdmi_pll_28lpm")) - pll_res->pll_interface_type = MDSS_HDMI_PLL_28LPM; - else - goto err; - - return rc; - -err: - mdss_pll_resource_release(pdev, pll_res); -end: - return rc; -} -static int mdss_pll_clock_register(struct platform_device *pdev, - struct mdss_pll_resources *pll_res) -{ - int rc; - - switch (pll_res->pll_interface_type) { - case MDSS_DSI_PLL_10NM: - rc = dsi_pll_clock_register_10nm(pdev, pll_res); - break; - case MDSS_DP_PLL_10NM: - rc = dp_pll_clock_register_10nm(pdev, pll_res); - break; - case MDSS_DSI_PLL_7NM: - case MDSS_DSI_PLL_7NM_V2: - case MDSS_DSI_PLL_7NM_V4_1: - rc = dsi_pll_clock_register_7nm(pdev, pll_res); - break; - case MDSS_DP_PLL_7NM: - rc = dp_pll_clock_register_7nm(pdev, pll_res); - break; - case MDSS_DSI_PLL_28LPM: - rc = dsi_pll_clock_register_28lpm(pdev, pll_res); - break; - case MDSS_DSI_PLL_14NM: - rc = dsi_pll_clock_register_14nm(pdev, pll_res); - break; - case MDSS_DP_PLL_14NM: - rc = dp_pll_clock_register_14nm(pdev, pll_res); - break; - case MDSS_HDMI_PLL_28LPM: - rc = hdmi_pll_clock_register_28lpm(pdev, pll_res); - break; - case MDSS_UNKNOWN_PLL: - default: - rc = -EINVAL; - break; - } - - if (rc) - pr_err("Pll ndx=%d clock register failed rc=%d\n", - pll_res->index, rc); - - return rc; -} - -static inline int mdss_pll_get_ioresurces(struct platform_device *pdev, - void __iomem **regmap, char *resource_name) -{ - int rc = 0; - struct resource *rsc = platform_get_resource_byname(pdev, - IORESOURCE_MEM, resource_name); - if (rsc) { - *regmap = devm_ioremap(&pdev->dev, - rsc->start, resource_size(rsc)); - if (!regmap) - return -ENOMEM; - } - return rc; -} - -static int mdss_pll_probe(struct platform_device *pdev) -{ - int rc = 0; - const char *label; - struct mdss_pll_resources *pll_res; - - if (!pdev->dev.of_node) { - pr_err("MDSS pll driver only supports device tree probe\n"); - return -ENOTSUPP; - } - - label = of_get_property(pdev->dev.of_node, "label", NULL); - if (!label) - pr_info("MDSS pll label not specified\n"); - else - pr_info("MDSS pll label = %s\n", label); - - pll_res = devm_kzalloc(&pdev->dev, sizeof(struct mdss_pll_resources), - GFP_KERNEL); - if (!pll_res) - return -ENOMEM; - - platform_set_drvdata(pdev, pll_res); - - rc = of_property_read_u32(pdev->dev.of_node, "cell-index", - &pll_res->index); - if (rc) { - pr_err("Unable to get the cell-index rc=%d\n", rc); - pll_res->index = 0; - } - - pll_res->ssc_en = of_property_read_bool(pdev->dev.of_node, - "qcom,dsi-pll-ssc-en"); - - if (pll_res->ssc_en) { - pr_info("%s: label=%s PLL SSC enabled\n", __func__, label); - - rc = of_property_read_u32(pdev->dev.of_node, - "qcom,ssc-frequency-hz", &pll_res->ssc_freq); - - rc = of_property_read_u32(pdev->dev.of_node, - "qcom,ssc-ppm", &pll_res->ssc_ppm); - - pll_res->ssc_center = false; - - label = of_get_property(pdev->dev.of_node, - "qcom,dsi-pll-ssc-mode", NULL); - - if (label && !strcmp(label, "center-spread")) - pll_res->ssc_center = true; - } - - - if (mdss_pll_get_ioresurces(pdev, &pll_res->pll_base, "pll_base")) { - pr_err("Unable to remap pll base resources\n"); - return -ENOMEM; - } - - pr_debug("%s: ndx=%d base=%p\n", __func__, - pll_res->index, pll_res->pll_base); - - rc = mdss_pll_resource_parse(pdev, pll_res); - if (rc) { - pr_err("Pll resource parsing from dt failed rc=%d\n", rc); - return rc; - } - - if (mdss_pll_get_ioresurces(pdev, &pll_res->phy_base, "phy_base")) { - pr_err("Unable to remap pll phy base resources\n"); - return -ENOMEM; - } - - if (mdss_pll_get_ioresurces(pdev, &pll_res->dyn_pll_base, - "dynamic_pll_base")) { - pr_err("Unable to remap dynamic pll base resources\n"); - return -ENOMEM; - } - - if (mdss_pll_get_ioresurces(pdev, &pll_res->ln_tx0_base, - "ln_tx0_base")) { - pr_err("Unable to remap Lane TX0 base resources\n"); - return -ENOMEM; - } - - if (mdss_pll_get_ioresurces(pdev, &pll_res->ln_tx1_base, - "ln_tx1_base")) { - pr_err("Unable to remap Lane TX1 base resources\n"); - return -ENOMEM; - } - - if (mdss_pll_get_ioresurces(pdev, &pll_res->gdsc_base, "gdsc_base")) { - pr_err("Unable to remap gdsc base resources\n"); - return -ENOMEM; - } - - rc = mdss_pll_resource_init(pdev, pll_res); - if (rc) { - pr_err("Pll ndx=%d resource init failed rc=%d\n", - pll_res->index, rc); - return rc; - } - - rc = mdss_pll_clock_register(pdev, pll_res); - if (rc) { - pr_err("Pll ndx=%d clock register failed rc=%d\n", - pll_res->index, rc); - goto clock_register_error; - } - - return rc; - -clock_register_error: - mdss_pll_resource_deinit(pdev, pll_res); - return rc; -} - -static int mdss_pll_remove(struct platform_device *pdev) -{ - struct mdss_pll_resources *pll_res; - - pll_res = platform_get_drvdata(pdev); - if (!pll_res) { - pr_err("Invalid PLL resource data\n"); - return 0; - } - - mdss_pll_resource_deinit(pdev, pll_res); - mdss_pll_resource_release(pdev, pll_res); - return 0; -} - -static const struct of_device_id mdss_pll_dt_match[] = { - {.compatible = "qcom,mdss_dsi_pll_10nm"}, - {.compatible = "qcom,mdss_dp_pll_10nm"}, - {.compatible = "qcom,mdss_dsi_pll_7nm"}, - {.compatible = "qcom,mdss_dsi_pll_7nm_v2"}, - {.compatible = "qcom,mdss_dsi_pll_7nm_v4_1"}, - {.compatible = "qcom,mdss_dp_pll_7nm"}, - {.compatible = "qcom,mdss_dsi_pll_28lpm"}, - {.compatible = "qcom,mdss_dsi_pll_14nm"}, - {.compatible = "qcom,mdss_dp_pll_14nm"}, - {}, -}; - -MODULE_DEVICE_TABLE(of, mdss_clock_dt_match); - -static struct platform_driver mdss_pll_driver = { - .probe = mdss_pll_probe, - .remove = mdss_pll_remove, - .driver = { - .name = "mdss_pll", - .of_match_table = mdss_pll_dt_match, - }, -}; - -static int __init mdss_pll_driver_init(void) -{ - int rc; - - rc = platform_driver_register(&mdss_pll_driver); - if (rc) - pr_err("mdss_register_pll_driver() failed!\n"); - - return rc; -} -fs_initcall(mdss_pll_driver_init); - -static void __exit mdss_pll_driver_deinit(void) -{ - platform_driver_unregister(&mdss_pll_driver); -} -module_exit(mdss_pll_driver_deinit); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("mdss pll driver"); diff --git a/drivers/clk/qcom/mdss/mdss-pll.h b/drivers/clk/qcom/mdss/mdss-pll.h deleted file mode 100644 index 17edd24f3f1ec246ea57e1be6ef8f942cc754d1a..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss-pll.h +++ /dev/null @@ -1,244 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. - */ - -#ifndef __MDSS_PLL_H -#define __MDSS_PLL_H - -#include -#include -#include -#include -#include -#include "../clk-regmap.h" -#include "../clk-regmap-divider.h" -#include "../clk-regmap-mux.h" - -#if defined(CONFIG_DRM) -#include -#else -#include -#endif - -#define MDSS_PLL_REG_W(base, offset, data) \ - writel_relaxed((data), (base) + (offset)) -#define MDSS_PLL_REG_R(base, offset) readl_relaxed((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(PLL_CALC_DATA(addr0, addr1, data0, data1), \ - (base) + (offset)) - -enum { - MDSS_DSI_PLL_10NM, - MDSS_DP_PLL_10NM, - MDSS_DSI_PLL_7NM, - MDSS_DSI_PLL_7NM_V2, - MDSS_DSI_PLL_7NM_V4_1, - MDSS_DP_PLL_7NM, - MDSS_DSI_PLL_28LPM, - MDSS_DSI_PLL_14NM, - MDSS_DP_PLL_14NM, - MDSS_HDMI_PLL_28LPM, - MDSS_UNKNOWN_PLL, -}; - -enum { - MDSS_PLL_TARGET_8996, -}; - -#define DFPS_MAX_NUM_OF_FRAME_RATES 20 - -struct dfps_panel_info { - uint32_t enabled; - uint32_t frame_rate_cnt; - uint32_t frame_rate[DFPS_MAX_NUM_OF_FRAME_RATES]; /* hz */ -}; - -struct dfps_pll_codes { - uint32_t pll_codes_1; - uint32_t pll_codes_2; -}; - -struct dfps_codes_info { - uint32_t is_valid; - uint32_t frame_rate; /* hz */ - uint32_t clk_rate; /* hz */ - struct dfps_pll_codes pll_codes; -}; - -struct dfps_info { - struct dfps_panel_info panel_dfps; - struct dfps_codes_info codes_dfps[DFPS_MAX_NUM_OF_FRAME_RATES]; - void *dfps_fb_base; -}; - -struct mdss_pll_resources { - - /* Pll specific resources like GPIO, power supply, clocks, etc*/ - struct dss_module_power mp; - - /* - * dsi/edp/hmdi plls' base register, phy, gdsc and dynamic refresh - * register mapping - */ - void __iomem *pll_base; - void __iomem *phy_base; - void __iomem *ln_tx0_base; - void __iomem *ln_tx1_base; - void __iomem *gdsc_base; - void __iomem *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; - - u32 cached_postdiv1; - u32 cached_postdiv3; - u32 cached_vreg_cfg; - - /* 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; - - /* - * Notifier callback for MDSS gdsc regulator events - */ - struct notifier_block gdsc_cb; - - /* - * Worker function to call PLL off event - */ - struct work_struct pll_off; - - /* - * 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 bool is_gdsc_disabled(struct mdss_pll_resources *pll_res) -{ - if (!pll_res->gdsc_base) { - WARN(1, "gdsc_base register is not defined\n"); - return true; - } - return readl_relaxed(pll_res->gdsc_base) & BIT(31) ? false : true; -} - -static inline int mdss_pll_div_prepare(struct clk_hw *hw) -{ - struct clk_hw *parent_hw = clk_hw_get_parent(hw); - /* Restore the divider's value */ - return hw->init->ops->set_rate(hw, clk_hw_get_rate(hw), - clk_hw_get_rate(parent_hw)); -} - -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 mdss_pll_resource_enable(struct mdss_pll_resources *pll_res, bool enable); -int mdss_pll_util_resource_enable(struct mdss_pll_resources *pll_res, - bool enable); -int mdss_pll_util_resource_parse(struct platform_device *pdev, - struct mdss_pll_resources *pll_res); -struct dss_vreg *mdss_pll_get_mp_by_reg_name(struct mdss_pll_resources *pll_res - , char *name); -#endif diff --git a/drivers/clk/qcom/mdss/mdss_pll_trace.h b/drivers/clk/qcom/mdss/mdss_pll_trace.h deleted file mode 100644 index cf46c7f8f935604dd00f0daa78bfcd136cde5ee7..0000000000000000000000000000000000000000 --- a/drivers/clk/qcom/mdss/mdss_pll_trace.h +++ /dev/null @@ -1,109 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. - */ - -#if !defined(_MDSS_PLL_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) -#define _MDSS_PLL_TRACE_H_ - -#include -#include -#include - -#undef TRACE_SYSTEM -#define TRACE_SYSTEM mdss_pll -#undef TRACE_INCLUDE_FILE -#define TRACE_INCLUDE_FILE ../../drivers/clk/qcom/mdss/mdss_pll_trace - - -TRACE_EVENT(mdss_pll_lock_start, - TP_PROTO( - u64 vco_cached_rate, - s64 vco_current_rate, - u32 cached_cfg0, - u32 cached_cfg1, - u32 cached_outdiv, - u32 resource_ref_cnt), - TP_ARGS( - vco_cached_rate, - vco_current_rate, - cached_cfg0, - cached_cfg1, - cached_outdiv, - resource_ref_cnt), - TP_STRUCT__entry( - __field(u64, vco_cached_rate) - __field(s64, vco_current_rate) - __field(u32, cached_cfg0) - __field(u32, cached_cfg1) - __field(u32, cached_outdiv) - __field(u32, resource_ref_cnt) - - ), - TP_fast_assign( - __entry->vco_cached_rate = vco_cached_rate; - __entry->vco_current_rate = vco_current_rate; - __entry->cached_cfg0 = cached_cfg0; - __entry->cached_cfg1 = cached_cfg1; - __entry->cached_outdiv = cached_outdiv; - __entry->resource_ref_cnt = resource_ref_cnt; - ), - TP_printk( - "vco_cached_rate=%llu vco_current_rate=%lld cached_cfg0=%d cached_cfg1=%d cached_outdiv=%d resource_ref_cnt=%d", - __entry->vco_cached_rate, - __entry->vco_current_rate, - __entry->cached_cfg0, - __entry->cached_cfg1, - __entry->cached_outdiv, - __entry->resource_ref_cnt) -); - -TRACE_EVENT(pll_tracing_mark_write, - TP_PROTO(int pid, const char *name, bool trace_begin), - TP_ARGS(pid, name, trace_begin), - TP_STRUCT__entry( - __field(int, pid) - __string(trace_name, name) - __field(bool, trace_begin) - ), - TP_fast_assign( - __entry->pid = pid; - __assign_str(trace_name, name); - __entry->trace_begin = trace_begin; - ), - TP_printk("%s|%d|%s", __entry->trace_begin ? "B" : "E", - __entry->pid, __get_str(trace_name)) -) - -TRACE_EVENT(mdss_pll_trace_counter, - TP_PROTO(int pid, char *name, int value), - TP_ARGS(pid, name, value), - TP_STRUCT__entry( - __field(int, pid) - __string(counter_name, name) - __field(int, value) - ), - TP_fast_assign( - __entry->pid = current->tgid; - __assign_str(counter_name, name); - __entry->value = value; - ), - TP_printk("%d|%s|%d", __entry->pid, - __get_str(counter_name), __entry->value) -) - -#define MDSS_PLL_ATRACE_END(name) trace_pll_tracing_mark_write(current->tgid,\ - name, 0) -#define MDSS_PLL_ATRACE_BEGIN(name) trace_pll_tracing_mark_write(current->tgid,\ - name, 1) -#define MDSS_PLL_ATRACE_FUNC() MDSS_PLL_ATRACE_BEGIN(__func__) -#define MDSS_PLL_ATRACE_INT(name, value) \ - trace_mdss_pll_trace_counter(current->tgid, name, value) - - -#endif /* _MDSS_PLL_TRACE_H_ */ - -/* This part must be outside protection */ -#undef TRACE_INCLUDE_PATH -#define TRACE_INCLUDE_PATH . -#include diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 05700302683a0778685463c12259f2d5fcbfb9f3..843a9d40c05e33f5f13d1cbb7b09c751127940f2 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -5,39 +5,21 @@ config DRM_MSM depends on ARCH_QCOM || (ARM && COMPILE_TEST) depends on OF && COMMON_CLK depends on MMU + select QCOM_MDT_LOADER if ARCH_QCOM + select REGULATOR select DRM_KMS_HELPER select DRM_PANEL select SHMEM + select TMPFS + select QCOM_SCM select WANT_DEV_COREDUMP select SND_SOC_HDMI_CODEC if SND_SOC select SYNC_FILE - select MSM_EXT_DISPLAY select PM_OPP default y help DRM/KMS driver for MSM/snapdragon. -config DRM_MSM_SDE - bool "SDE in Display Driver" - depends on DRM_MSM - default y - help - Enable this option to support display driver - compilation. Choosing this option will compile - SDE folder specifically. Display Port and - DSI-Staging compilation are also dependent on - this option. - -config DRM_MSM_DP - bool "Enable Display Port" - depends on DRM_MSM_SDE && USB_PD - default n - help - This option enables compilation of Display Port - (DP) folders. In order to compile Display Port - files, DRM_MSM_SDE option also needs to be - enabled. - config DRM_MSM_REGISTER_LOGGING bool "MSM DRM register logging" depends on DRM_MSM @@ -63,55 +45,20 @@ config DRM_MSM_GPU_SUDO config DRM_MSM_HDMI_HDCP bool "Enable HDMI HDCP support in MSM DRM driver" depends on DRM_MSM && QCOM_SCM - default n - help - Compile in support for logging register reads/writes ina format - that can be parsed by envy tools demsm tool. If enabled, register - logging can be switched on via msm.reglog=y module param. - -config DRM_MSM_HDMI - bool "Enable HDMI support in MSM DRM driver" - depends on DRM_MSM - depends on COMMON_CLK - default n + default y help - Compile in support for HDMI driver in msm drm - driver. HDMI external display support is enabled - through this config option. It can be primary or - secondary display on device. + Choose this option to enable HDCP state machine config DRM_MSM_DSI bool "Enable DSI support in MSM DRM driver" depends on DRM_MSM select DRM_PANEL select DRM_MIPI_DSI - default n + default y help Choose this option if you have a need for MIPI DSI connector support. -config DRM_MSM_DSI_STAGING - bool "Enable new DSI driver support in MSM DRM driver" - depends on DRM_MSM && DRM_MSM_SDE - select DRM_PANEL - select DRM_MIPI_DSI - default y - help - Choose this option if you need MIPI DSI connector support on MSM - which conforms to DRM. MIPI stands for Mobile Industry Processor - Interface and DSI stands for Display Serial Interface which powers - the primary display of your mobile device. - -config DSI_PARSER - bool "Enable DSI panel configuration parser" - depends on DYNAMIC_DEBUG && DRM_MSM_DSI_STAGING - default y - help - Choose this option if you need text parser for a DSI panel - configurations which can parse a given text file and get the - panel configurations. Also, this module provides a set of APIs - which can be used to get the parsed data. - config DRM_MSM_DSI_PLL bool "Enable DSI PLL driver in MSM DRM" depends on DRM_MSM_DSI && COMMON_CLK @@ -120,16 +67,6 @@ config DRM_MSM_DSI_PLL Choose this option to enable DSI PLL driver which provides DSI source clocks under common clock framework. -config DRM_SDE_WB - bool "Enable Writeback support in SDE DRM" - depends on DRM_MSM && DRM_MSM_SDE - default y - help - Choose this option for writeback connector support. - This option enables a virtual writeback connector where - the output image is written back to memory in the format - selected by the connector's mode and property settings. - config DRM_MSM_DSI_28NM_PHY bool "Enable DSI 28nm PHY driver in MSM DRM" depends on DRM_MSM_DSI @@ -165,54 +102,3 @@ config DRM_MSM_DSI_10NM_PHY default y help Choose this option if DSI PHY on SDM845 is used on the platform. - -config DRM_MSM_MDP5 - tristate "MSM MDP5 DRM driver" - depends on DRM_MSM - default n - help - Choose this option if MSM MDP5 revision support is - needed in DRM/KMS. This is not required if sde/mdp4 - only target enabled. MDP5 supports DSI and HDMI - displays. - -config DRM_MSM_MDP4 - tristate "MSM MDP4 DRM driver" - depends on DRM_MSM - default n - help - Choose this option if MSM MDP4 revision support is needed in DRM/KMS. - MSM MDP4 DRM driver should be disabled for other MDP revisions to - avoid possible conflicts. Only select this option if the target - MSM platform is MDP4 based. - -config DRM_MSM_HDCP - tristate "HDCP for MSM DRM" - depends on DRM_MSM - default n - help - Choose this option if High-bandwidth Digital Content Protection (HDCP) - support is needed in the MSM DRM/KMS driver. Enabling this config - will allow HDCP encrypted (copy protected) media to be displayed. - This should only be enabled if required for platforms supporting HDCP - over the desired interface. - -config DRM_SDE_WB - bool "Enable Writeback support in SDE DRM" - depends on DRM_MSM && DRM_MSM_SDE - default y - help - Choose this option for writeback connector support. - This option enables a virtual writeback connector where - the output image is written back to memory in the format - selected by the connector's mode and property settings. - -config DRM_SDE_RSC - bool "Enable sde resource state coordinator(rsc) driver" - depends on DRM_MSM && DRM_MSM_SDE - help - The SDE DRM RSC provides display Resource State Coordinator support - to vote the ab/ib bandwidth for primary display. Each rsc client - can vote their active state. Any active request from any client - avoids the display core power collapse. A client can also register - for display core power collapse events on rsc. diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index a76d904f1b1518f06e448b9b56a1a66b9c1264bc..9688c38f00544251417a1f53e149d52ddf273656 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -1,58 +1,10 @@ # SPDX-License-Identifier: GPL-2.0 -ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/msm -Idrivers/gpu/drm/msm/dsi-staging -Idrivers/gpu/drm/msm/dp -ccflags-y += -Idrivers/gpu/drm/msm/display-manager +ccflags-y := -Idrivers/gpu/drm/msm +ccflags-y += -Idrivers/gpu/drm/msm/disp/dpu1 ccflags-$(CONFIG_DRM_MSM_DSI) += -Idrivers/gpu/drm/msm/dsi -ccflags-$(CONFIG_DRM_MSM_DSI_PLL) += -Idrivers/gpu/drm/msm/dsi -ccflags-y += -Idrivers/gpu/drm/msm/sde -ccflags-y += -Idrivers/media/platform/msm/sde/rotator -ccflags-y += -Idrivers/gpu/drm/msm/hdmi -msm_drm-$(CONFIG_DRM_MSM_DP) += dp/dp_usbpd.o \ - dp/dp_parser.o \ - dp/dp_power.o \ - dp/dp_catalog.o \ - dp/dp_catalog_v420.o \ - dp/dp_catalog_v200.o \ - dp/dp_aux.o \ - dp/dp_panel.o \ - dp/dp_link.o \ - dp/dp_ctrl.o \ - dp/dp_audio.o \ - dp/dp_debug.o \ - dp/dp_hpd.o \ - dp/dp_gpio_hpd.o \ - dp/dp_lphw_hpd.o \ - dp/dp_display.o \ - dp/dp_drm.o \ - dp/dp_hdcp2p2.o \ - dp/dp_mst_drm.o - -msm_drm-$(CONFIG_DRM_MSM_SDE) += sde/sde_crtc.o \ - sde/sde_encoder.o \ - sde/sde_encoder_phys_vid.o \ - sde/sde_encoder_phys_cmd.o \ - sde/sde_irq.o \ - sde/sde_core_irq.o \ - sde/sde_core_perf.o \ - sde/sde_rm.o \ - sde/sde_kms_utils.o \ - sde/sde_kms.o \ - sde/sde_plane.o \ - sde/sde_connector.o \ - sde/sde_color_processing.o \ - sde/sde_vbif.o \ - sde_dbg.o \ - sde_dbg_evtlog.o \ - sde_io_util.o \ - sde/sde_hw_reg_dma_v1_color_proc.o \ - sde/sde_hw_color_proc_v4.o \ - sde/sde_hw_ad4.o \ - sde/sde_hw_uidle.o \ - sde_edid_parser.o \ - sde_hdcp_1x.o \ - sde_hdcp_2x.o - -msm_drm-$(CONFIG_DRM_MSM_HDMI) += hdmi/hdmi.o \ +msm-y := \ + hdmi/hdmi.o \ hdmi/hdmi_audio.o \ hdmi/hdmi_bridge.o \ hdmi/hdmi_connector.o \ @@ -61,16 +13,21 @@ msm_drm-$(CONFIG_DRM_MSM_HDMI) += hdmi/hdmi.o \ hdmi/hdmi_phy_8960.o \ hdmi/hdmi_phy_8x60.o \ hdmi/hdmi_phy_8x74.o \ - -msm_drm-$(CONFIG_DRM_MSM_EDP) += edp/edp.o \ + edp/edp.o \ edp/edp_aux.o \ edp/edp_bridge.o \ edp/edp_connector.o \ edp/edp_ctrl.o \ edp/edp_phy.o \ - -msm_drm-$(CONFIG_DRM_MSM_MDP5) += disp/mdp_format.o \ + disp/mdp_format.o \ disp/mdp_kms.o \ + disp/mdp4/mdp4_crtc.o \ + disp/mdp4/mdp4_dtv_encoder.o \ + disp/mdp4/mdp4_lcdc_encoder.o \ + disp/mdp4/mdp4_lvds_connector.o \ + disp/mdp4/mdp4_irq.o \ + disp/mdp4/mdp4_kms.o \ + disp/mdp4/mdp4_plane.o \ disp/mdp5/mdp5_cfg.o \ disp/mdp5/mdp5_ctl.o \ disp/mdp5/mdp5_crtc.o \ @@ -82,44 +39,75 @@ msm_drm-$(CONFIG_DRM_MSM_MDP5) += disp/mdp_format.o \ disp/mdp5/mdp5_mixer.o \ disp/mdp5/mdp5_plane.o \ disp/mdp5/mdp5_smp.o \ - -msm_drm-$(CONFIG_DRM_SDE_RSC) += sde_rsc.o \ - sde_rsc_hw.o \ - sde_rsc_hw_v3.o \ + disp/dpu1/dpu_core_irq.o \ + disp/dpu1/dpu_core_perf.o \ + disp/dpu1/dpu_crtc.o \ + disp/dpu1/dpu_encoder.o \ + disp/dpu1/dpu_encoder_phys_cmd.o \ + disp/dpu1/dpu_encoder_phys_vid.o \ + disp/dpu1/dpu_formats.o \ + disp/dpu1/dpu_hw_blk.o \ + disp/dpu1/dpu_hw_catalog.o \ + disp/dpu1/dpu_hw_cdm.o \ + disp/dpu1/dpu_hw_ctl.o \ + disp/dpu1/dpu_hw_interrupts.o \ + disp/dpu1/dpu_hw_intf.o \ + disp/dpu1/dpu_hw_lm.o \ + disp/dpu1/dpu_hw_pingpong.o \ + disp/dpu1/dpu_hw_sspp.o \ + disp/dpu1/dpu_hw_top.o \ + disp/dpu1/dpu_hw_util.o \ + disp/dpu1/dpu_hw_vbif.o \ + disp/dpu1/dpu_io_util.o \ + disp/dpu1/dpu_irq.o \ + disp/dpu1/dpu_kms.o \ + disp/dpu1/dpu_mdss.o \ + disp/dpu1/dpu_plane.o \ + disp/dpu1/dpu_power_handle.o \ + disp/dpu1/dpu_rm.o \ + disp/dpu1/dpu_vbif.o \ + msm_atomic.o \ + msm_debugfs.o \ + msm_drv.o \ + msm_fb.o \ + msm_fence.o \ + msm_gem.o \ + msm_gem_prime.o \ + msm_gem_shrinker.o \ + msm_gem_submit.o \ + msm_gem_vma.o \ + msm_gpu.o \ + msm_iommu.o \ + msm_perf.o \ + msm_rd.o \ + msm_ringbuffer.o \ + msm_submitqueue.o # use drm gpu driver only if qcom_kgsl driver not available -ifneq ($(CONFIG_QCOM_KGSL),y) +#ifneq ($(CONFIG_QCOM_KGSL),y) msm_drm-y += adreno/adreno_device.o \ - adreno/adreno_gpu.o \ + adreno/adreno_gpu.o \ adreno/a3xx_gpu.o \ adreno/a4xx_gpu.o \ adreno/a5xx_gpu.o \ adreno/a5xx_power.o \ - adreno/a5xx_preempt.o \ - adreno/a6xx_gpu.o \ - adreno/a6xx_gmu.o \ - adreno/a6xx_hfi.o -endif + adreno/a5xx_preempt.o\ + adreno/a6xx_gpu.o\ + adreno/a6xx_gmu.o\ + adreno/a6xx_hfi.o +#endif -msm_drm-$(CONFIG_DRM_MSM_MDP4) += disp/mdp4/mdp4_crtc.o \ - disp/mdp4/mdp4_dtv_encoder.o \ - disp/mdp4/mdp4_lcdc_encoder.o \ - disp/mdp4/mdp4_lvds_connector.o \ - disp/mdp4/mdp4_irq.o \ - disp/mdp4/mdp4_kms.o \ - disp/mdp4/mdp4_plane.o +msm-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o \ + disp/dpu1/dpu_dbg.o -msm_drm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o -ifeq ($(CONFIG_DRM_MSM_SDE),y) -msm_drm-$(CONFIG_SYNC_FILE) += sde/sde_fence.o -endif -msm_drm-$(CONFIG_COMMON_CLK) += disp/mdp4/mdp4_lvds_pll.o -msm_drm-$(CONFIG_COMMON_CLK) += hdmi/hdmi_pll_8960.o -msm_drm-$(CONFIG_COMMON_CLK) += hdmi/hdmi_phy_8996.o +msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o +msm-$(CONFIG_COMMON_CLK) += disp/mdp4/mdp4_lvds_pll.o +msm-$(CONFIG_COMMON_CLK) += hdmi/hdmi_pll_8960.o +msm-$(CONFIG_COMMON_CLK) += hdmi/hdmi_phy_8996.o -msm_drm-$(CONFIG_DRM_MSM_HDMI_HDCP) += hdmi/hdmi_hdcp.o +msm-$(CONFIG_DRM_MSM_HDMI_HDCP) += hdmi/hdmi_hdcp.o -msm_drm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \ +msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \ disp/mdp4/mdp4_dsi_encoder.o \ dsi/dsi_cfg.o \ dsi/dsi_host.o \ @@ -127,93 +115,18 @@ msm_drm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \ dsi/phy/dsi_phy.o \ disp/mdp5/mdp5_cmd_encoder.o -msm_drm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/phy/dsi_phy_28nm.o -msm_drm-$(CONFIG_DRM_MSM_DSI_20NM_PHY) += dsi/phy/dsi_phy_20nm.o -msm_drm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/phy/dsi_phy_28nm_8960.o -msm_drm-$(CONFIG_DRM_MSM_DSI_14NM_PHY) += dsi/phy/dsi_phy_14nm.o -msm_drm-$(CONFIG_DRM_MSM_DSI_10NM_PHY) += dsi/phy/dsi_phy_10nm.o +msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/phy/dsi_phy_28nm.o +msm-$(CONFIG_DRM_MSM_DSI_20NM_PHY) += dsi/phy/dsi_phy_20nm.o +msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/phy/dsi_phy_28nm_8960.o +msm-$(CONFIG_DRM_MSM_DSI_14NM_PHY) += dsi/phy/dsi_phy_14nm.o +msm-$(CONFIG_DRM_MSM_DSI_10NM_PHY) += dsi/phy/dsi_phy_10nm.o ifeq ($(CONFIG_DRM_MSM_DSI_PLL),y) -msm_drm-y += dsi/pll/dsi_pll.o -msm_drm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/pll/dsi_pll_28nm.o -msm_drm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/pll/dsi_pll_28nm_8960.o -msm_drm-$(CONFIG_DRM_MSM_DSI_14NM_PHY) += dsi/pll/dsi_pll_14nm.o -msm_drm-$(CONFIG_DRM_MSM_DSI_10NM_PHY) += dsi/pll/dsi_pll_10nm.o +msm-y += dsi/pll/dsi_pll.o +msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/pll/dsi_pll_28nm.o +msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/pll/dsi_pll_28nm_8960.o +msm-$(CONFIG_DRM_MSM_DSI_14NM_PHY) += dsi/pll/dsi_pll_14nm.o +msm-$(CONFIG_DRM_MSM_DSI_10NM_PHY) += dsi/pll/dsi_pll_10nm.o endif -msm_drm-$(CONFIG_DRM_MSM_DSI_STAGING) += dsi-staging/dsi_phy.o \ - dsi-staging/dsi_pwr.o \ - dsi-staging/dsi_phy.o \ - dsi-staging/dsi_phy_hw_v2_0.o \ - dsi-staging/dsi_phy_hw_v3_0.o \ - dsi-staging/dsi_phy_hw_v4_0.o \ - dsi-staging/dsi_phy_timing_calc.o \ - dsi-staging/dsi_phy_timing_v2_0.o \ - dsi-staging/dsi_phy_timing_v3_0.o \ - dsi-staging/dsi_phy_timing_v4_0.o \ - dsi-staging/dsi_ctrl_hw_cmn.o \ - dsi-staging/dsi_ctrl_hw_1_4.o \ - dsi-staging/dsi_ctrl_hw_2_0.o \ - dsi-staging/dsi_ctrl_hw_2_2.o \ - dsi-staging/dsi_ctrl.o \ - dsi-staging/dsi_catalog.o \ - dsi-staging/dsi_drm.o \ - dsi-staging/dsi_display.o \ - dsi-staging/dsi_panel.o \ - dsi-staging/dsi_clk_manager.o \ - dsi-staging/dsi_display_test.o - -msm_drm-$(CONFIG_DSI_PARSER) += dsi-staging/dsi_parser.o - -msm_drm-$(CONFIG_DRM_MSM_DSI_PLL) += dsi/pll/dsi_pll.o \ - dsi/pll/dsi_pll_28nm.o - -msm_drm-$(CONFIG_DRM_MSM_SDE) += \ - sde/sde_hw_catalog.o \ - sde/sde_hw_cdm.o \ - sde/sde_hw_dspp.o \ - sde/sde_hw_intf.o \ - sde/sde_hw_lm.o \ - sde/sde_hw_ctl.o \ - sde/sde_hw_util.o \ - sde/sde_hw_sspp.o \ - sde/sde_hw_wb.o \ - sde/sde_hw_pingpong.o \ - sde/sde_hw_top.o \ - sde/sde_hw_interrupts.o \ - sde/sde_hw_vbif.o \ - sde/sde_hw_blk.o \ - sde/sde_formats.o \ - sde_power_handle.o \ - sde/sde_hw_color_processing_v1_7.o \ - sde/sde_reg_dma.o \ - sde/sde_hw_reg_dma_v1.o \ - sde/sde_hw_dsc.o \ - sde/sde_hw_ds.o - -msm_drm-$(CONFIG_DRM_SDE_WB) += sde/sde_wb.o \ - sde/sde_encoder_phys_wb.o - -msm_drm-$(CONFIG_DRM_MSM) += \ - msm_atomic.o \ - msm_debugfs.o \ - msm_drv.o \ - msm_fb.o \ - msm_fence.o \ - msm_gem.o \ - msm_gem_prime.o \ - msm_gem_shrinker.o \ - msm_gem_submit.o \ - msm_gem_vma.o \ - msm_gpu.o \ - msm_iommu.o \ - msm_smmu.o \ - msm_perf.o \ - msm_prop.o \ - msm_rd.o \ - msm_ringbuffer.o \ - msm_submitqueue.o - -msm_drm-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o - -obj-$(CONFIG_DRM_MSM) += msm_drm.o +obj-$(CONFIG_DRM_MSM) += msm.o diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c index 4b646bf9c2146329fa8bde9763537d0186f82b07..44d1cda56974d7f6c106329ae0fac034fe4d38c6 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c @@ -125,6 +125,8 @@ static void mdp4_complete_commit(struct msm_kms *kms, struct drm_atomic_state *s struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; + drm_atomic_helper_wait_for_vblanks(mdp4_kms->dev, state); + /* see 119ecb7fd */ for_each_new_crtc_in_state(state, crtc, crtc_state, i) drm_crtc_vblank_put(crtc); diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index fd063faafe9753d751a4178558082c50936beacc..5df2034b7b53d73f4e758a14282958511720c969 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -170,6 +170,8 @@ static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *s struct device *dev = &mdp5_kms->pdev->dev; struct mdp5_global_state *global_state; + drm_atomic_helper_wait_for_vblanks(mdp5_kms->dev, state); + global_state = mdp5_get_existing_global_state(mdp5_kms); if (mdp5_kms->smp) diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c index 5a828d3fb6952d87b75808055433bfe0bdaef06d..ccaa3248e4070a710cffc4aa408304141c0b5d08 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mdss.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, 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 as published by @@ -20,12 +20,10 @@ #include "msm_drv.h" #include "mdp5_kms.h" -/* - * If needed, this can become more specific: something like struct mdp5_mdss, - * which contains a 'struct msm_mdss base' member. - */ -struct msm_mdss { - struct drm_device *dev; +#define to_mdp5_mdss(x) container_of(x, struct mdp5_mdss, base) + +struct mdp5_mdss { + struct msm_mdss base; void __iomem *mmio, *vbif; @@ -41,22 +39,22 @@ struct msm_mdss { } irqcontroller; }; -static inline void mdss_write(struct msm_mdss *mdss, u32 reg, u32 data) +static inline void mdss_write(struct mdp5_mdss *mdp5_mdss, u32 reg, u32 data) { - msm_writel(data, mdss->mmio + reg); + msm_writel(data, mdp5_mdss->mmio + reg); } -static inline u32 mdss_read(struct msm_mdss *mdss, u32 reg) +static inline u32 mdss_read(struct mdp5_mdss *mdp5_mdss, u32 reg) { - return msm_readl(mdss->mmio + reg); + return msm_readl(mdp5_mdss->mmio + reg); } static irqreturn_t mdss_irq(int irq, void *arg) { - struct msm_mdss *mdss = arg; + struct mdp5_mdss *mdp5_mdss = arg; u32 intr; - intr = mdss_read(mdss, REG_MDSS_HW_INTR_STATUS); + intr = mdss_read(mdp5_mdss, REG_MDSS_HW_INTR_STATUS); VERB("intr=%08x", intr); @@ -64,7 +62,7 @@ static irqreturn_t mdss_irq(int irq, void *arg) irq_hw_number_t hwirq = fls(intr) - 1; generic_handle_irq(irq_find_mapping( - mdss->irqcontroller.domain, hwirq)); + mdp5_mdss->irqcontroller.domain, hwirq)); intr &= ~(1 << hwirq); } @@ -84,19 +82,19 @@ static irqreturn_t mdss_irq(int irq, void *arg) static void mdss_hw_mask_irq(struct irq_data *irqd) { - struct msm_mdss *mdss = irq_data_get_irq_chip_data(irqd); + struct mdp5_mdss *mdp5_mdss = irq_data_get_irq_chip_data(irqd); smp_mb__before_atomic(); - clear_bit(irqd->hwirq, &mdss->irqcontroller.enabled_mask); + clear_bit(irqd->hwirq, &mdp5_mdss->irqcontroller.enabled_mask); smp_mb__after_atomic(); } static void mdss_hw_unmask_irq(struct irq_data *irqd) { - struct msm_mdss *mdss = irq_data_get_irq_chip_data(irqd); + struct mdp5_mdss *mdp5_mdss = irq_data_get_irq_chip_data(irqd); smp_mb__before_atomic(); - set_bit(irqd->hwirq, &mdss->irqcontroller.enabled_mask); + set_bit(irqd->hwirq, &mdp5_mdss->irqcontroller.enabled_mask); smp_mb__after_atomic(); } @@ -109,13 +107,13 @@ static struct irq_chip mdss_hw_irq_chip = { static int mdss_hw_irqdomain_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hwirq) { - struct msm_mdss *mdss = d->host_data; + struct mdp5_mdss *mdp5_mdss = d->host_data; if (!(VALID_IRQS & (1 << hwirq))) return -EPERM; irq_set_chip_and_handler(irq, &mdss_hw_irq_chip, handle_level_irq); - irq_set_chip_data(irq, mdss); + irq_set_chip_data(irq, mdp5_mdss); return 0; } @@ -126,90 +124,99 @@ static const struct irq_domain_ops mdss_hw_irqdomain_ops = { }; -static int mdss_irq_domain_init(struct msm_mdss *mdss) +static int mdss_irq_domain_init(struct mdp5_mdss *mdp5_mdss) { - struct device *dev = mdss->dev->dev; + struct device *dev = mdp5_mdss->base.dev->dev; struct irq_domain *d; d = irq_domain_add_linear(dev->of_node, 32, &mdss_hw_irqdomain_ops, - mdss); + mdp5_mdss); if (!d) { dev_err(dev, "mdss irq domain add failed\n"); return -ENXIO; } - mdss->irqcontroller.enabled_mask = 0; - mdss->irqcontroller.domain = d; + mdp5_mdss->irqcontroller.enabled_mask = 0; + mdp5_mdss->irqcontroller.domain = d; return 0; } -int msm_mdss_enable(struct msm_mdss *mdss) +static int mdp5_mdss_enable(struct msm_mdss *mdss) { + struct mdp5_mdss *mdp5_mdss = to_mdp5_mdss(mdss); DBG(""); - clk_prepare_enable(mdss->ahb_clk); - if (mdss->axi_clk) - clk_prepare_enable(mdss->axi_clk); - if (mdss->vsync_clk) - clk_prepare_enable(mdss->vsync_clk); + clk_prepare_enable(mdp5_mdss->ahb_clk); + if (mdp5_mdss->axi_clk) + clk_prepare_enable(mdp5_mdss->axi_clk); + if (mdp5_mdss->vsync_clk) + clk_prepare_enable(mdp5_mdss->vsync_clk); return 0; } -int msm_mdss_disable(struct msm_mdss *mdss) +static int mdp5_mdss_disable(struct msm_mdss *mdss) { + struct mdp5_mdss *mdp5_mdss = to_mdp5_mdss(mdss); DBG(""); - if (mdss->vsync_clk) - clk_disable_unprepare(mdss->vsync_clk); - if (mdss->axi_clk) - clk_disable_unprepare(mdss->axi_clk); - clk_disable_unprepare(mdss->ahb_clk); + if (mdp5_mdss->vsync_clk) + clk_disable_unprepare(mdp5_mdss->vsync_clk); + if (mdp5_mdss->axi_clk) + clk_disable_unprepare(mdp5_mdss->axi_clk); + clk_disable_unprepare(mdp5_mdss->ahb_clk); return 0; } -static int msm_mdss_get_clocks(struct msm_mdss *mdss) +static int msm_mdss_get_clocks(struct mdp5_mdss *mdp5_mdss) { - struct platform_device *pdev = to_platform_device(mdss->dev->dev); + struct platform_device *pdev = + to_platform_device(mdp5_mdss->base.dev->dev); - mdss->ahb_clk = msm_clk_get(pdev, "iface"); - if (IS_ERR(mdss->ahb_clk)) - mdss->ahb_clk = NULL; + mdp5_mdss->ahb_clk = msm_clk_get(pdev, "iface"); + if (IS_ERR(mdp5_mdss->ahb_clk)) + mdp5_mdss->ahb_clk = NULL; - mdss->axi_clk = msm_clk_get(pdev, "bus"); - if (IS_ERR(mdss->axi_clk)) - mdss->axi_clk = NULL; + mdp5_mdss->axi_clk = msm_clk_get(pdev, "bus"); + if (IS_ERR(mdp5_mdss->axi_clk)) + mdp5_mdss->axi_clk = NULL; - mdss->vsync_clk = msm_clk_get(pdev, "vsync"); - if (IS_ERR(mdss->vsync_clk)) - mdss->vsync_clk = NULL; + mdp5_mdss->vsync_clk = msm_clk_get(pdev, "vsync"); + if (IS_ERR(mdp5_mdss->vsync_clk)) + mdp5_mdss->vsync_clk = NULL; return 0; } -void msm_mdss_destroy(struct drm_device *dev) +static void mdp5_mdss_destroy(struct drm_device *dev) { struct msm_drm_private *priv = dev->dev_private; - struct msm_mdss *mdss = priv->mdss; + struct mdp5_mdss *mdp5_mdss = to_mdp5_mdss(priv->mdss); - if (!mdss) + if (!mdp5_mdss) return; - irq_domain_remove(mdss->irqcontroller.domain); - mdss->irqcontroller.domain = NULL; + irq_domain_remove(mdp5_mdss->irqcontroller.domain); + mdp5_mdss->irqcontroller.domain = NULL; - regulator_disable(mdss->vdd); + regulator_disable(mdp5_mdss->vdd); pm_runtime_disable(dev->dev); } -int msm_mdss_init(struct drm_device *dev) +static const struct msm_mdss_funcs mdss_funcs = { + .enable = mdp5_mdss_enable, + .disable = mdp5_mdss_disable, + .destroy = mdp5_mdss_destroy, +}; + +int mdp5_mdss_init(struct drm_device *dev) { struct platform_device *pdev = to_platform_device(dev->dev); struct msm_drm_private *priv = dev->dev_private; - struct msm_mdss *mdss; + struct mdp5_mdss *mdp5_mdss; int ret; DBG(""); @@ -217,40 +224,40 @@ int msm_mdss_init(struct drm_device *dev) if (!of_device_is_compatible(dev->dev->of_node, "qcom,mdss")) return 0; - mdss = devm_kzalloc(dev->dev, sizeof(*mdss), GFP_KERNEL); - if (!mdss) { + mdp5_mdss = devm_kzalloc(dev->dev, sizeof(*mdp5_mdss), GFP_KERNEL); + if (!mdp5_mdss) { ret = -ENOMEM; goto fail; } - mdss->dev = dev; + mdp5_mdss->base.dev = dev; - mdss->mmio = msm_ioremap(pdev, "mdss_phys", "MDSS"); - if (IS_ERR(mdss->mmio)) { - ret = PTR_ERR(mdss->mmio); + mdp5_mdss->mmio = msm_ioremap(pdev, "mdss_phys", "MDSS"); + if (IS_ERR(mdp5_mdss->mmio)) { + ret = PTR_ERR(mdp5_mdss->mmio); goto fail; } - mdss->vbif = msm_ioremap(pdev, "vbif_phys", "VBIF"); - if (IS_ERR(mdss->vbif)) { - ret = PTR_ERR(mdss->vbif); + mdp5_mdss->vbif = msm_ioremap(pdev, "vbif_phys", "VBIF"); + if (IS_ERR(mdp5_mdss->vbif)) { + ret = PTR_ERR(mdp5_mdss->vbif); goto fail; } - ret = msm_mdss_get_clocks(mdss); + ret = msm_mdss_get_clocks(mdp5_mdss); if (ret) { dev_err(dev->dev, "failed to get clocks: %d\n", ret); goto fail; } /* Regulator to enable GDSCs in downstream kernels */ - mdss->vdd = devm_regulator_get(dev->dev, "vdd"); - if (IS_ERR(mdss->vdd)) { - ret = PTR_ERR(mdss->vdd); + mdp5_mdss->vdd = devm_regulator_get(dev->dev, "vdd"); + if (IS_ERR(mdp5_mdss->vdd)) { + ret = PTR_ERR(mdp5_mdss->vdd); goto fail; } - ret = regulator_enable(mdss->vdd); + ret = regulator_enable(mdp5_mdss->vdd); if (ret) { dev_err(dev->dev, "failed to enable regulator vdd: %d\n", ret); @@ -258,25 +265,26 @@ int msm_mdss_init(struct drm_device *dev) } ret = devm_request_irq(dev->dev, platform_get_irq(pdev, 0), - mdss_irq, 0, "mdss_isr", mdss); + mdss_irq, 0, "mdss_isr", mdp5_mdss); if (ret) { dev_err(dev->dev, "failed to init irq: %d\n", ret); goto fail_irq; } - ret = mdss_irq_domain_init(mdss); + ret = mdss_irq_domain_init(mdp5_mdss); if (ret) { dev_err(dev->dev, "failed to init sub-block irqs: %d\n", ret); goto fail_irq; } - priv->mdss = mdss; + mdp5_mdss->base.funcs = &mdss_funcs; + priv->mdss = &mdp5_mdss->base; pm_runtime_enable(dev->dev); return 0; fail_irq: - regulator_disable(mdss->vdd); + regulator_disable(mdp5_mdss->vdd); fail: return ret; } diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c index 7d306c5acd09644ff62b7e7d62f6590390a90344..273cbbe27c2e5e0fc9bd3782e86ce681930a2f89 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c @@ -259,7 +259,6 @@ static void mdp5_plane_cleanup_fb(struct drm_plane *plane, msm_framebuffer_cleanup(fb, kms->aspace); } -#define FRAC_16_16(mult, div) (((mult) << 16) / (div)) static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state, struct drm_plane_state *state) { diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c deleted file mode 100644 index d5982d92138e03748f53a841cdf889e68188cd28..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_audio.c +++ /dev/null @@ -1,854 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ - -#include -#include - -#include - -#include "dp_catalog.h" -#include "dp_audio.h" -#include "dp_panel.h" - -struct dp_audio_private { - struct platform_device *ext_pdev; - struct platform_device *pdev; - struct dp_catalog_audio *catalog; - struct msm_ext_disp_init_data ext_audio_data; - struct dp_panel *panel; - - bool ack_enabled; - bool session_on; - bool engine_on; - - u32 channels; - - struct completion hpd_comp; - struct workqueue_struct *notify_workqueue; - struct delayed_work notify_delayed_work; - struct mutex ops_lock; - - struct dp_audio dp_audio; - - atomic_t acked; -}; - -static u32 dp_audio_get_header(struct dp_catalog_audio *catalog, - enum dp_catalog_audio_sdp_type sdp, - enum dp_catalog_audio_header_type header) -{ - catalog->sdp_type = sdp; - catalog->sdp_header = header; - catalog->get_header(catalog); - - return catalog->data; -} - -static void dp_audio_set_header(struct dp_catalog_audio *catalog, - u32 data, - enum dp_catalog_audio_sdp_type sdp, - enum dp_catalog_audio_header_type header) -{ - catalog->sdp_type = sdp; - catalog->sdp_header = header; - catalog->data = data; - catalog->set_header(catalog); -} - -static void dp_audio_stream_sdp(struct dp_audio_private *audio) -{ - struct dp_catalog_audio *catalog = audio->catalog; - u32 value, new_value; - u8 parity_byte; - - /* Config header and parity byte 1 */ - value = dp_audio_get_header(catalog, - DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1); - value &= 0x0000ffff; - - new_value = 0x02; - parity_byte = dp_header_get_parity(new_value); - value |= ((new_value << HEADER_BYTE_1_BIT) - | (parity_byte << PARITY_BYTE_1_BIT)); - pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1); - - /* Config header and parity byte 2 */ - value = dp_audio_get_header(catalog, - DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2); - value &= 0xffff0000; - new_value = 0x0; - parity_byte = dp_header_get_parity(new_value); - value |= ((new_value << HEADER_BYTE_2_BIT) - | (parity_byte << PARITY_BYTE_2_BIT)); - pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - - dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2); - - /* Config header and parity byte 3 */ - value = dp_audio_get_header(catalog, - DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3); - value &= 0x0000ffff; - - new_value = audio->channels - 1; - parity_byte = dp_header_get_parity(new_value); - value |= ((new_value << HEADER_BYTE_3_BIT) - | (parity_byte << PARITY_BYTE_3_BIT)); - pr_debug("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - - dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3); -} - -static void dp_audio_timestamp_sdp(struct dp_audio_private *audio) -{ - struct dp_catalog_audio *catalog = audio->catalog; - u32 value, new_value; - u8 parity_byte; - - /* Config header and parity byte 1 */ - value = dp_audio_get_header(catalog, - DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1); - value &= 0x0000ffff; - - new_value = 0x1; - parity_byte = dp_header_get_parity(new_value); - value |= ((new_value << HEADER_BYTE_1_BIT) - | (parity_byte << PARITY_BYTE_1_BIT)); - pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1); - - /* Config header and parity byte 2 */ - value = dp_audio_get_header(catalog, - DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2); - value &= 0xffff0000; - - new_value = 0x17; - parity_byte = dp_header_get_parity(new_value); - value |= ((new_value << HEADER_BYTE_2_BIT) - | (parity_byte << PARITY_BYTE_2_BIT)); - pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2); - - /* Config header and parity byte 3 */ - value = dp_audio_get_header(catalog, - DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3); - value &= 0x0000ffff; - - new_value = (0x0 | (0x11 << 2)); - parity_byte = dp_header_get_parity(new_value); - value |= ((new_value << HEADER_BYTE_3_BIT) - | (parity_byte << PARITY_BYTE_3_BIT)); - pr_debug("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3); -} - -static void dp_audio_infoframe_sdp(struct dp_audio_private *audio) -{ - struct dp_catalog_audio *catalog = audio->catalog; - u32 value, new_value; - u8 parity_byte; - - /* Config header and parity byte 1 */ - value = dp_audio_get_header(catalog, - DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1); - value &= 0x0000ffff; - - new_value = 0x84; - parity_byte = dp_header_get_parity(new_value); - value |= ((new_value << HEADER_BYTE_1_BIT) - | (parity_byte << PARITY_BYTE_1_BIT)); - pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1); - - /* Config header and parity byte 2 */ - value = dp_audio_get_header(catalog, - DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2); - value &= 0xffff0000; - - new_value = 0x1b; - parity_byte = dp_header_get_parity(new_value); - value |= ((new_value << HEADER_BYTE_2_BIT) - | (parity_byte << PARITY_BYTE_2_BIT)); - pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2); - - /* Config header and parity byte 3 */ - value = dp_audio_get_header(catalog, - DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3); - value &= 0x0000ffff; - - new_value = (0x0 | (0x11 << 2)); - parity_byte = dp_header_get_parity(new_value); - value |= ((new_value << HEADER_BYTE_3_BIT) - | (parity_byte << PARITY_BYTE_3_BIT)); - pr_debug("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n", - new_value, parity_byte); - dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3); -} - -static void dp_audio_copy_management_sdp(struct dp_audio_private *audio) -{ - struct dp_catalog_audio *catalog = audio->catalog; - u32 value, new_value; - u8 parity_byte; - - /* Config header and parity byte 1 */ - value = dp_audio_get_header(catalog, - DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1); - value &= 0x0000ffff; - - new_value = 0x05; - parity_byte = dp_header_get_parity(new_value); - value |= ((new_value << HEADER_BYTE_1_BIT) - | (parity_byte << PARITY_BYTE_1_BIT)); - pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1); - - /* Config header and parity byte 2 */ - value = dp_audio_get_header(catalog, - DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2); - value &= 0xffff0000; - - new_value = 0x0F; - parity_byte = dp_header_get_parity(new_value); - value |= ((new_value << HEADER_BYTE_2_BIT) - | (parity_byte << PARITY_BYTE_2_BIT)); - pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2); - - /* Config header and parity byte 3 */ - value = dp_audio_get_header(catalog, - DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3); - value &= 0x0000ffff; - - new_value = 0x0; - parity_byte = dp_header_get_parity(new_value); - value |= ((new_value << HEADER_BYTE_3_BIT) - | (parity_byte << PARITY_BYTE_3_BIT)); - pr_debug("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3); -} - -static void dp_audio_isrc_sdp(struct dp_audio_private *audio) -{ - struct dp_catalog_audio *catalog = audio->catalog; - u32 value, new_value; - u8 parity_byte; - - /* Config header and parity byte 1 */ - value = dp_audio_get_header(catalog, - DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1); - value &= 0x0000ffff; - - new_value = 0x06; - parity_byte = dp_header_get_parity(new_value); - value |= ((new_value << HEADER_BYTE_1_BIT) - | (parity_byte << PARITY_BYTE_1_BIT)); - pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1); - - /* Config header and parity byte 2 */ - value = dp_audio_get_header(catalog, - DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2); - value &= 0xffff0000; - - new_value = 0x0F; - parity_byte = dp_header_get_parity(new_value); - value |= ((new_value << HEADER_BYTE_2_BIT) - | (parity_byte << PARITY_BYTE_2_BIT)); - pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - dp_audio_set_header(catalog, value, - DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2); -} - -static void dp_audio_setup_sdp(struct dp_audio_private *audio) -{ - /* always program stream 0 first before actual stream cfg */ - audio->catalog->stream_id = DP_STREAM_0; - audio->catalog->config_sdp(audio->catalog); - - if (audio->panel->stream_id == DP_STREAM_1) { - audio->catalog->stream_id = DP_STREAM_1; - audio->catalog->config_sdp(audio->catalog); - } - - dp_audio_stream_sdp(audio); - dp_audio_timestamp_sdp(audio); - dp_audio_infoframe_sdp(audio); - dp_audio_copy_management_sdp(audio); - dp_audio_isrc_sdp(audio); -} - -static void dp_audio_setup_acr(struct dp_audio_private *audio) -{ - u32 select = 0; - struct dp_catalog_audio *catalog = audio->catalog; - - switch (audio->dp_audio.bw_code) { - case DP_LINK_BW_1_62: - select = 0; - break; - case DP_LINK_BW_2_7: - select = 1; - break; - case DP_LINK_BW_5_4: - select = 2; - break; - case DP_LINK_BW_8_1: - select = 3; - break; - default: - pr_debug("Unknown link rate\n"); - select = 0; - break; - } - - catalog->data = select; - catalog->config_acr(catalog); -} - -static void dp_audio_enable(struct dp_audio_private *audio, bool enable) -{ - struct dp_catalog_audio *catalog = audio->catalog; - - catalog->data = enable; - catalog->enable(catalog); - - audio->engine_on = enable; -} - -static struct dp_audio_private *dp_audio_get_data(struct platform_device *pdev) -{ - struct msm_ext_disp_data *ext_data; - struct dp_audio *dp_audio; - - if (!pdev) { - pr_err("invalid input\n"); - return ERR_PTR(-ENODEV); - } - - ext_data = platform_get_drvdata(pdev); - if (!ext_data) { - pr_err("invalid ext disp data\n"); - return ERR_PTR(-EINVAL); - } - - dp_audio = ext_data->intf_data; - if (!ext_data) { - pr_err("invalid intf data\n"); - return ERR_PTR(-EINVAL); - } - - return container_of(dp_audio, struct dp_audio_private, dp_audio); -} - -static int dp_audio_info_setup(struct platform_device *pdev, - struct msm_ext_disp_audio_setup_params *params) -{ - int rc = 0; - struct dp_audio_private *audio; - - audio = dp_audio_get_data(pdev); - if (IS_ERR(audio)) { - rc = PTR_ERR(audio); - return rc; - } - - mutex_lock(&audio->ops_lock); - - audio->channels = params->num_of_channels; - - if (audio->panel->stream_id >= DP_STREAM_MAX) { - pr_err("invalid stream id: %d\n", audio->panel->stream_id); - rc = -EINVAL; - mutex_unlock(&audio->ops_lock); - return rc; - } - - dp_audio_setup_sdp(audio); - dp_audio_setup_acr(audio); - dp_audio_enable(audio, true); - - mutex_unlock(&audio->ops_lock); - return rc; -} - -static int dp_audio_get_edid_blk(struct platform_device *pdev, - struct msm_ext_disp_audio_edid_blk *blk) -{ - int rc = 0; - struct dp_audio_private *audio; - struct sde_edid_ctrl *edid; - - audio = dp_audio_get_data(pdev); - if (IS_ERR(audio)) { - rc = PTR_ERR(audio); - goto end; - } - - if (!audio->panel || !audio->panel->edid_ctrl) { - pr_err("invalid panel data\n"); - rc = -EINVAL; - goto end; - } - - edid = audio->panel->edid_ctrl; - - blk->audio_data_blk = edid->audio_data_block; - blk->audio_data_blk_size = edid->adb_size; - - blk->spk_alloc_data_blk = edid->spkr_alloc_data_block; - blk->spk_alloc_data_blk_size = edid->sadb_size; -end: - return rc; -} - -static int dp_audio_get_cable_status(struct platform_device *pdev, u32 vote) -{ - int rc = 0; - struct dp_audio_private *audio; - - audio = dp_audio_get_data(pdev); - if (IS_ERR(audio)) { - rc = PTR_ERR(audio); - goto end; - } - - return audio->session_on; -end: - return rc; -} - -static int dp_audio_get_intf_id(struct platform_device *pdev) -{ - int rc = 0; - struct dp_audio_private *audio; - - audio = dp_audio_get_data(pdev); - if (IS_ERR(audio)) { - rc = PTR_ERR(audio); - goto end; - } - - return EXT_DISPLAY_TYPE_DP; -end: - return rc; -} - -static void dp_audio_teardown_done(struct platform_device *pdev) -{ - struct dp_audio_private *audio; - - audio = dp_audio_get_data(pdev); - if (IS_ERR(audio)) - return; - - mutex_lock(&audio->ops_lock); - dp_audio_enable(audio, false); - mutex_unlock(&audio->ops_lock); - - atomic_set(&audio->acked, 1); - complete_all(&audio->hpd_comp); - - pr_debug("audio engine disabled\n"); -} - -static int dp_audio_ack_done(struct platform_device *pdev, u32 ack) -{ - int rc = 0, ack_hpd; - struct dp_audio_private *audio; - - audio = dp_audio_get_data(pdev); - if (IS_ERR(audio)) { - rc = PTR_ERR(audio); - goto end; - } - - if (ack & AUDIO_ACK_SET_ENABLE) { - audio->ack_enabled = ack & AUDIO_ACK_ENABLE ? - true : false; - - pr_debug("audio ack feature %s\n", - audio->ack_enabled ? "enabled" : "disabled"); - goto end; - } - - if (!audio->ack_enabled) - goto end; - - ack_hpd = ack & AUDIO_ACK_CONNECT; - - pr_debug("acknowledging audio (%d)\n", ack_hpd); - - if (!audio->engine_on) { - atomic_set(&audio->acked, 1); - complete_all(&audio->hpd_comp); - } -end: - return rc; -} - -static int dp_audio_codec_ready(struct platform_device *pdev) -{ - int rc = 0; - struct dp_audio_private *audio; - - audio = dp_audio_get_data(pdev); - if (IS_ERR(audio)) { - pr_err("invalid input\n"); - rc = PTR_ERR(audio); - goto end; - } - - queue_delayed_work(audio->notify_workqueue, - &audio->notify_delayed_work, HZ/4); -end: - return rc; -} - -static int dp_audio_register_ext_disp(struct dp_audio_private *audio) -{ - int rc = 0; - struct device_node *pd = NULL; - const char *phandle = "qcom,ext-disp"; - struct msm_ext_disp_init_data *ext; - struct msm_ext_disp_audio_codec_ops *ops; - - ext = &audio->ext_audio_data; - ops = &ext->codec_ops; - - ext->codec.type = EXT_DISPLAY_TYPE_DP; - ext->codec.ctrl_id = 0; - ext->codec.stream_id = audio->panel->stream_id; - ext->pdev = audio->pdev; - ext->intf_data = &audio->dp_audio; - - ops->audio_info_setup = dp_audio_info_setup; - ops->get_audio_edid_blk = dp_audio_get_edid_blk; - ops->cable_status = dp_audio_get_cable_status; - ops->get_intf_id = dp_audio_get_intf_id; - ops->teardown_done = dp_audio_teardown_done; - ops->acknowledge = dp_audio_ack_done; - ops->ready = dp_audio_codec_ready; - - if (!audio->pdev->dev.of_node) { - pr_err("cannot find audio dev.of_node\n"); - rc = -ENODEV; - goto end; - } - - pd = of_parse_phandle(audio->pdev->dev.of_node, phandle, 0); - if (!pd) { - pr_err("cannot parse %s handle\n", phandle); - rc = -ENODEV; - goto end; - } - - audio->ext_pdev = of_find_device_by_node(pd); - if (!audio->ext_pdev) { - pr_err("cannot find %s pdev\n", phandle); - rc = -ENODEV; - goto end; - } -#if defined(CONFIG_MSM_EXT_DISPLAY) - rc = msm_ext_disp_register_intf(audio->ext_pdev, ext); - if (rc) - pr_err("failed to register disp\n"); -#endif -end: - if (pd) - of_node_put(pd); - - return rc; -} - -static int dp_audio_deregister_ext_disp(struct dp_audio_private *audio) -{ - int rc = 0; - struct device_node *pd = NULL; - const char *phandle = "qcom,ext-disp"; - struct msm_ext_disp_init_data *ext; - - ext = &audio->ext_audio_data; - - if (!audio->pdev->dev.of_node) { - pr_err("cannot find audio dev.of_node\n"); - rc = -ENODEV; - goto end; - } - - pd = of_parse_phandle(audio->pdev->dev.of_node, phandle, 0); - if (!pd) { - pr_err("cannot parse %s handle\n", phandle); - rc = -ENODEV; - goto end; - } - - audio->ext_pdev = of_find_device_by_node(pd); - if (!audio->ext_pdev) { - pr_err("cannot find %s pdev\n", phandle); - rc = -ENODEV; - goto end; - } - -#if defined(CONFIG_MSM_EXT_DISPLAY) - rc = msm_ext_disp_deregister_intf(audio->ext_pdev, ext); - if (rc) - pr_err("failed to deregister disp\n"); -#endif - -end: - return rc; -} - -static int dp_audio_notify(struct dp_audio_private *audio, u32 state) -{ - int rc = 0; - struct msm_ext_disp_init_data *ext = &audio->ext_audio_data; - - atomic_set(&audio->acked, 0); - - if (!ext->intf_ops.audio_notify) { - pr_err("audio notify not defined\n"); - goto end; - } - - reinit_completion(&audio->hpd_comp); - rc = ext->intf_ops.audio_notify(audio->ext_pdev, - &ext->codec, state); - if (rc) - goto end; - - if (atomic_read(&audio->acked)) - goto end; - - rc = wait_for_completion_timeout(&audio->hpd_comp, HZ * 4); - if (!rc) { - pr_err("timeout. state=%d err=%d\n", state, rc); - rc = -ETIMEDOUT; - goto end; - } - - pr_debug("success\n"); -end: - return rc; -} - -static int dp_audio_config(struct dp_audio_private *audio, u32 state) -{ - int rc = 0; - struct msm_ext_disp_init_data *ext = &audio->ext_audio_data; - - if (!ext || !ext->intf_ops.audio_config) { - pr_err("audio_config not defined\n"); - goto end; - } - - /* - * DP Audio sets default STREAM_0 only, other streams are - * set by audio driver based on the hardware/software support. - */ - if (audio->panel->stream_id == DP_STREAM_0) { - rc = ext->intf_ops.audio_config(audio->ext_pdev, - &ext->codec, state); - if (rc) - pr_err("failed to config audio, err=%d\n", rc); - } -end: - return rc; -} - -static int dp_audio_on(struct dp_audio *dp_audio) -{ - int rc = 0; - struct dp_audio_private *audio; - struct msm_ext_disp_init_data *ext; - - if (!dp_audio) { - pr_err("invalid input\n"); - return -EINVAL; - } - - audio = container_of(dp_audio, struct dp_audio_private, dp_audio); - if (IS_ERR(audio)) { - pr_err("invalid input\n"); - return -EINVAL; - } - - dp_audio_register_ext_disp(audio); - - ext = &audio->ext_audio_data; - - audio->session_on = true; - - rc = dp_audio_config(audio, EXT_DISPLAY_CABLE_CONNECT); - if (rc) - goto end; - - rc = dp_audio_notify(audio, EXT_DISPLAY_CABLE_CONNECT); - if (rc) - goto end; - - pr_debug("success\n"); -end: - return rc; -} - -static int dp_audio_off(struct dp_audio *dp_audio) -{ - int rc = 0; - struct dp_audio_private *audio; - struct msm_ext_disp_init_data *ext; - bool work_pending = false; - - if (!dp_audio) { - pr_err("invalid input\n"); - return -EINVAL; - } - - audio = container_of(dp_audio, struct dp_audio_private, dp_audio); - ext = &audio->ext_audio_data; - - work_pending = cancel_delayed_work_sync(&audio->notify_delayed_work); - if (work_pending) - pr_debug("pending notification work completed\n"); - - rc = dp_audio_notify(audio, EXT_DISPLAY_CABLE_DISCONNECT); - if (rc) - goto end; - - pr_debug("success\n"); -end: - dp_audio_config(audio, EXT_DISPLAY_CABLE_DISCONNECT); - - audio->session_on = false; - audio->engine_on = false; - - dp_audio_deregister_ext_disp(audio); - - return rc; -} - -static void dp_audio_notify_work_fn(struct work_struct *work) -{ - struct dp_audio_private *audio; - struct delayed_work *dw = to_delayed_work(work); - - audio = container_of(dw, struct dp_audio_private, notify_delayed_work); - - dp_audio_notify(audio, EXT_DISPLAY_CABLE_CONNECT); -} - -static int dp_audio_create_notify_workqueue(struct dp_audio_private *audio) -{ - audio->notify_workqueue = create_workqueue("sdm_dp_audio_notify"); - if (IS_ERR_OR_NULL(audio->notify_workqueue)) { - pr_err("Error creating notify_workqueue\n"); - return -EPERM; - } - - INIT_DELAYED_WORK(&audio->notify_delayed_work, dp_audio_notify_work_fn); - - return 0; -} - -static void dp_audio_destroy_notify_workqueue(struct dp_audio_private *audio) -{ - if (audio->notify_workqueue) - destroy_workqueue(audio->notify_workqueue); -} - -struct dp_audio *dp_audio_get(struct platform_device *pdev, - struct dp_panel *panel, - struct dp_catalog_audio *catalog) -{ - int rc = 0; - struct dp_audio_private *audio; - struct dp_audio *dp_audio; - - if (!pdev || !panel || !catalog) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto error; - } - - audio = devm_kzalloc(&pdev->dev, sizeof(*audio), GFP_KERNEL); - if (!audio) { - rc = -ENOMEM; - goto error; - } - - rc = dp_audio_create_notify_workqueue(audio); - if (rc) - goto error_notify_workqueue; - - init_completion(&audio->hpd_comp); - - audio->pdev = pdev; - audio->panel = panel; - audio->catalog = catalog; - - atomic_set(&audio->acked, 0); - - dp_audio = &audio->dp_audio; - - mutex_init(&audio->ops_lock); - - dp_audio->on = dp_audio_on; - dp_audio->off = dp_audio_off; - - catalog->init(catalog); - - return dp_audio; - -error_notify_workqueue: - devm_kfree(&pdev->dev, audio); -error: - return ERR_PTR(rc); -} - -void dp_audio_put(struct dp_audio *dp_audio) -{ - struct dp_audio_private *audio; - - if (!dp_audio) - return; - - audio = container_of(dp_audio, struct dp_audio_private, dp_audio); - - mutex_destroy(&audio->ops_lock); - - dp_audio_destroy_notify_workqueue(audio); - - devm_kfree(&audio->pdev->dev, audio); -} diff --git a/drivers/gpu/drm/msm/dp/dp_audio.h b/drivers/gpu/drm/msm/dp/dp_audio.h deleted file mode 100644 index ce02257422736ea8f19ffb72929e88985e706a08..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_audio.h +++ /dev/null @@ -1,70 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - */ - -#ifndef _DP_AUDIO_H_ -#define _DP_AUDIO_H_ - -#include - -#include "dp_panel.h" -#include "dp_catalog.h" - -/** - * struct dp_audio - * @lane_count: number of lanes configured in current session - * @bw_code: link rate's bandwidth code for current session - */ -struct dp_audio { - u32 lane_count; - u32 bw_code; - - /** - * on() - * - * Enables the audio by notifying the user module. - * - * @dp_audio: an instance of struct dp_audio. - * - * Returns the error code in case of failure, 0 in success case. - */ - int (*on)(struct dp_audio *dp_audio); - - /** - * off() - * - * Disables the audio by notifying the user module. - * - * @dp_audio: an instance of struct dp_audio. - * - * Returns the error code in case of failure, 0 in success case. - */ - int (*off)(struct dp_audio *dp_audio); -}; - -/** - * dp_audio_get() - * - * Creates and instance of dp audio. - * - * @pdev: caller's platform device instance. - * @panel: an instance of dp_panel module. - * @catalog: an instance of dp_catalog_audio module. - * - * Returns the error code in case of failure, otherwize - * an instance of newly created dp_module. - */ -struct dp_audio *dp_audio_get(struct platform_device *pdev, - struct dp_panel *panel, - struct dp_catalog_audio *catalog); - -/** - * dp_audio_put() - * - * Cleans the dp_audio instance. - * - * @dp_audio: an instance of dp_audio. - */ -void dp_audio_put(struct dp_audio *dp_audio); -#endif /* _DP_AUDIO_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c deleted file mode 100644 index 7985c83269c14c044a276566a2022866d1874033..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_aux.c +++ /dev/null @@ -1,865 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ - -#include -#include -#include - -#include "dp_aux.h" - -#define DP_AUX_ENUM_STR(x) #x - -enum { - DP_AUX_DATA_INDEX_WRITE = BIT(31), -}; - -struct dp_aux_private { - struct device *dev; - struct dp_aux dp_aux; - struct dp_catalog_aux *catalog; - struct dp_aux_cfg *cfg; - struct device_node *aux_switch_node; - struct mutex mutex; - struct completion comp; - struct drm_dp_aux drm_aux; - - bool cmd_busy; - bool native; - bool read; - bool no_send_addr; - bool no_send_stop; - bool enabled; - - u32 offset; - u32 segment; - u32 aux_error_num; - u32 retry_cnt; - - atomic_t aborted; - - u8 *dpcd; - u8 *edid; -}; - -#ifdef CONFIG_DYNAMIC_DEBUG -static void dp_aux_hex_dump(struct drm_dp_aux *drm_aux, - struct drm_dp_aux_msg *msg) -{ - char prefix[64]; - int i, linelen, remaining = msg->size; - const int rowsize = 16; - u8 linebuf[64]; - struct dp_aux_private *aux = container_of(drm_aux, - struct dp_aux_private, drm_aux); - - snprintf(prefix, sizeof(prefix), "%s %s %4xh(%2zu): ", - aux->native ? "NAT" : "I2C", - aux->read ? "RD" : "WR", - msg->address, msg->size); - - for (i = 0; i < msg->size; i += rowsize) { - linelen = min(remaining, rowsize); - remaining -= rowsize; - - hex_dump_to_buffer(msg->buffer + i, linelen, rowsize, 1, - linebuf, sizeof(linebuf), false); - - pr_debug("%s%s\n", prefix, linebuf); - } -} -#else -static void dp_aux_hex_dump(struct drm_dp_aux *drm_aux, - struct drm_dp_aux_msg *msg) -{ -} -#endif - -static char *dp_aux_get_error(u32 aux_error) -{ - switch (aux_error) { - case DP_AUX_ERR_NONE: - return DP_AUX_ENUM_STR(DP_AUX_ERR_NONE); - case DP_AUX_ERR_ADDR: - return DP_AUX_ENUM_STR(DP_AUX_ERR_ADDR); - case DP_AUX_ERR_TOUT: - return DP_AUX_ENUM_STR(DP_AUX_ERR_TOUT); - case DP_AUX_ERR_NACK: - return DP_AUX_ENUM_STR(DP_AUX_ERR_NACK); - case DP_AUX_ERR_DEFER: - return DP_AUX_ENUM_STR(DP_AUX_ERR_DEFER); - case DP_AUX_ERR_NACK_DEFER: - return DP_AUX_ENUM_STR(DP_AUX_ERR_NACK_DEFER); - default: - return "unknown"; - } -} - -static u32 dp_aux_write(struct dp_aux_private *aux, - struct drm_dp_aux_msg *msg) -{ - u32 data[4], reg, len; - u8 *msgdata = msg->buffer; - int const aux_cmd_fifo_len = 128; - int i = 0; - - if (aux->read) - len = 4; - else - len = msg->size + 4; - - /* - * cmd fifo only has depth of 144 bytes - * limit buf length to 128 bytes here - */ - if (len > aux_cmd_fifo_len) { - pr_err("buf len error\n"); - return 0; - } - - /* Pack cmd and write to HW */ - data[0] = (msg->address >> 16) & 0xf; /* addr[19:16] */ - if (aux->read) - data[0] |= BIT(4); /* R/W */ - - data[1] = (msg->address >> 8) & 0xff; /* addr[15:8] */ - data[2] = msg->address & 0xff; /* addr[7:0] */ - data[3] = (msg->size - 1) & 0xff; /* len[7:0] */ - - for (i = 0; i < len; i++) { - reg = (i < 4) ? data[i] : msgdata[i - 4]; - reg = ((reg) << 8) & 0x0000ff00; /* index = 0, write */ - if (i == 0) - reg |= DP_AUX_DATA_INDEX_WRITE; - aux->catalog->data = reg; - aux->catalog->write_data(aux->catalog); - } - - aux->catalog->clear_trans(aux->catalog, false); - aux->catalog->clear_hw_interrupts(aux->catalog); - - reg = 0; /* Transaction number == 1 */ - if (!aux->native) { /* i2c */ - reg |= BIT(8); - - if (aux->no_send_addr) - reg |= BIT(10); - - if (aux->no_send_stop) - reg |= BIT(11); - } - - reg |= BIT(9); - aux->catalog->data = reg; - aux->catalog->write_trans(aux->catalog); - - return len; -} - -static int dp_aux_cmd_fifo_tx(struct dp_aux_private *aux, - struct drm_dp_aux_msg *msg) -{ - u32 ret = 0, len = 0, timeout; - int const aux_timeout_ms = HZ/4; - - reinit_completion(&aux->comp); - - len = dp_aux_write(aux, msg); - if (len == 0) { - pr_err("DP AUX write failed\n"); - return -EINVAL; - } - - timeout = wait_for_completion_timeout(&aux->comp, aux_timeout_ms); - if (!timeout) { - pr_err("aux %s timeout\n", (aux->read ? "read" : "write")); - return -ETIMEDOUT; - } - - if (aux->aux_error_num == DP_AUX_ERR_NONE) { - ret = len; - } else { - pr_err_ratelimited("aux err: %s\n", - dp_aux_get_error(aux->aux_error_num)); - - ret = -EINVAL; - } - - return ret; -} - -static void dp_aux_cmd_fifo_rx(struct dp_aux_private *aux, - struct drm_dp_aux_msg *msg) -{ - u32 data; - u8 *dp; - u32 i, actual_i; - u32 len = msg->size; - - aux->catalog->clear_trans(aux->catalog, true); - - data = 0; - data |= DP_AUX_DATA_INDEX_WRITE; /* INDEX_WRITE */ - data |= BIT(0); /* read */ - - aux->catalog->data = data; - aux->catalog->write_data(aux->catalog); - - dp = msg->buffer; - - /* discard first byte */ - data = aux->catalog->read_data(aux->catalog); - - for (i = 0; i < len; i++) { - data = aux->catalog->read_data(aux->catalog); - *dp++ = (u8)((data >> 8) & 0xff); - - actual_i = (data >> 16) & 0xFF; - if (i != actual_i) - pr_warn("Index mismatch: expected %d, found %d\n", - i, actual_i); - } -} - -static void dp_aux_native_handler(struct dp_aux_private *aux) -{ - u32 isr = aux->catalog->isr; - - if (isr & DP_INTR_AUX_I2C_DONE) - aux->aux_error_num = DP_AUX_ERR_NONE; - else if (isr & DP_INTR_WRONG_ADDR) - aux->aux_error_num = DP_AUX_ERR_ADDR; - else if (isr & DP_INTR_TIMEOUT) - aux->aux_error_num = DP_AUX_ERR_TOUT; - if (isr & DP_INTR_NACK_DEFER) - aux->aux_error_num = DP_AUX_ERR_NACK; - if (isr & DP_INTR_AUX_ERROR) { - aux->aux_error_num = DP_AUX_ERR_PHY; - aux->catalog->clear_hw_interrupts(aux->catalog); - } - - complete(&aux->comp); -} - -static void dp_aux_i2c_handler(struct dp_aux_private *aux) -{ - u32 isr = aux->catalog->isr; - - if (isr & DP_INTR_AUX_I2C_DONE) { - if (isr & (DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER)) - aux->aux_error_num = DP_AUX_ERR_NACK; - else - aux->aux_error_num = DP_AUX_ERR_NONE; - } else { - if (isr & DP_INTR_WRONG_ADDR) - aux->aux_error_num = DP_AUX_ERR_ADDR; - else if (isr & DP_INTR_TIMEOUT) - aux->aux_error_num = DP_AUX_ERR_TOUT; - if (isr & DP_INTR_NACK_DEFER) - aux->aux_error_num = DP_AUX_ERR_NACK_DEFER; - if (isr & DP_INTR_I2C_NACK) - aux->aux_error_num = DP_AUX_ERR_NACK; - if (isr & DP_INTR_I2C_DEFER) - aux->aux_error_num = DP_AUX_ERR_DEFER; - if (isr & DP_INTR_AUX_ERROR) { - aux->aux_error_num = DP_AUX_ERR_PHY; - aux->catalog->clear_hw_interrupts(aux->catalog); - } - } - - complete(&aux->comp); -} - -static void dp_aux_isr(struct dp_aux *dp_aux) -{ - struct dp_aux_private *aux; - - if (!dp_aux) { - pr_err("invalid input\n"); - return; - } - - aux = container_of(dp_aux, struct dp_aux_private, dp_aux); - - aux->catalog->get_irq(aux->catalog, aux->cmd_busy); - - if (!aux->cmd_busy) - return; - - if (aux->native) - dp_aux_native_handler(aux); - else - dp_aux_i2c_handler(aux); -} - -static void dp_aux_reconfig(struct dp_aux *dp_aux) -{ - struct dp_aux_private *aux; - - if (!dp_aux) { - pr_err("invalid input\n"); - return; - } - - aux = container_of(dp_aux, struct dp_aux_private, dp_aux); - - aux->catalog->update_aux_cfg(aux->catalog, - aux->cfg, PHY_AUX_CFG1); - aux->catalog->reset(aux->catalog); -} - -static void dp_aux_abort_transaction(struct dp_aux *dp_aux) -{ - struct dp_aux_private *aux; - - if (!dp_aux) { - pr_err("invalid input\n"); - return; - } - - aux = container_of(dp_aux, struct dp_aux_private, dp_aux); - - atomic_set(&aux->aborted, 1); -} - -static void dp_aux_update_offset_and_segment(struct dp_aux_private *aux, - struct drm_dp_aux_msg *input_msg) -{ - u32 const edid_address = 0x50; - u32 const segment_address = 0x30; - bool i2c_read = input_msg->request & - (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ); - u8 *data = NULL; - - if (aux->native || i2c_read || ((input_msg->address != edid_address) && - (input_msg->address != segment_address))) - return; - - - data = input_msg->buffer; - if (input_msg->address == segment_address) - aux->segment = *data; - else - aux->offset = *data; -} - -/** - * dp_aux_transfer_helper() - helper function for EDID read transactions - * - * @aux: DP AUX private structure - * @input_msg: input message from DRM upstream APIs - * @send_seg: send the seg to sink - * - * return: void - * - * This helper function is used to fix EDID reads for non-compliant - * sinks that do not handle the i2c middle-of-transaction flag correctly. - */ -static void dp_aux_transfer_helper(struct dp_aux_private *aux, - struct drm_dp_aux_msg *input_msg, bool send_seg) -{ - struct drm_dp_aux_msg helper_msg; - u32 const message_size = 0x10; - u32 const segment_address = 0x30; - u32 const edid_block_length = 0x80; - bool i2c_mot = input_msg->request & DP_AUX_I2C_MOT; - bool i2c_read = input_msg->request & - (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ); - - if (!i2c_mot || !i2c_read || (input_msg->size == 0)) - return; - - /* - * Sending the segment value and EDID offset will be performed - * from the DRM upstream EDID driver for each block. Avoid - * duplicate AUX transactions related to this while reading the - * first 16 bytes of each block. - */ - if (!(aux->offset % edid_block_length) || !send_seg) - goto end; - - aux->read = false; - aux->cmd_busy = true; - aux->no_send_addr = true; - aux->no_send_stop = true; - - /* - * Send the segment address for i2c reads for segment > 0 and for which - * the middle-of-transaction flag is set. This is required to support - * EDID reads of more than 2 blocks as the segment address is reset to 0 - * since we are overriding the middle-of-transaction flag for read - * transactions. - */ - if (aux->segment) { - memset(&helper_msg, 0, sizeof(helper_msg)); - helper_msg.address = segment_address; - helper_msg.buffer = &aux->segment; - helper_msg.size = 1; - dp_aux_cmd_fifo_tx(aux, &helper_msg); - } - - /* - * Send the offset address for every i2c read in which the - * middle-of-transaction flag is set. This will ensure that the sink - * will update its read pointer and return the correct portion of the - * EDID buffer in the subsequent i2c read trasntion triggered in the - * native AUX transfer function. - */ - memset(&helper_msg, 0, sizeof(helper_msg)); - helper_msg.address = input_msg->address; - helper_msg.buffer = &aux->offset; - helper_msg.size = 1; - dp_aux_cmd_fifo_tx(aux, &helper_msg); -end: - aux->offset += message_size; - if (aux->offset == 0x80 || aux->offset == 0x100) - aux->segment = 0x0; /* reset segment at end of block */ -} - -static int dp_aux_transfer_ready(struct dp_aux_private *aux, - struct drm_dp_aux_msg *msg, bool send_seg) -{ - int ret = 0; - int const aux_cmd_native_max = 16; - int const aux_cmd_i2c_max = 128; - - if (atomic_read(&aux->aborted)) { - ret = -ETIMEDOUT; - goto error; - } - - aux->native = msg->request & (DP_AUX_NATIVE_WRITE & DP_AUX_NATIVE_READ); - - /* Ignore address only message */ - if ((msg->size == 0) || (msg->buffer == NULL)) { - msg->reply = aux->native ? - DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK; - goto error; - } - - /* msg sanity check */ - if ((aux->native && (msg->size > aux_cmd_native_max)) || - (msg->size > aux_cmd_i2c_max)) { - pr_err("%s: invalid msg: size(%zu), request(%x)\n", - __func__, msg->size, msg->request); - ret = -EINVAL; - goto error; - } - - dp_aux_update_offset_and_segment(aux, msg); - - dp_aux_transfer_helper(aux, msg, send_seg); - - aux->read = msg->request & (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ); - - if (aux->read) { - aux->no_send_addr = true; - aux->no_send_stop = false; - } else { - aux->no_send_addr = true; - aux->no_send_stop = true; - } - - aux->cmd_busy = true; -error: - return ret; -} - -static ssize_t dp_aux_transfer_debug(struct drm_dp_aux *drm_aux, - struct drm_dp_aux_msg *msg) -{ - u32 timeout; - ssize_t ret; - struct dp_aux_private *aux = container_of(drm_aux, - struct dp_aux_private, drm_aux); - - mutex_lock(&aux->mutex); - - ret = dp_aux_transfer_ready(aux, msg, false); - if (ret) - goto end; - - aux->aux_error_num = DP_AUX_ERR_NONE; - - if (!aux->dpcd || !aux->edid) { - pr_err("invalid aux/dpcd structure\n"); - goto end; - } - - if ((msg->address + msg->size) > SZ_4K) { - pr_debug("invalid dpcd access: addr=0x%x, size=0x%lx\n", - msg->address, msg->size); - goto address_error; - } - - if (aux->native) { - aux->dp_aux.reg = msg->address; - aux->dp_aux.read = aux->read; - aux->dp_aux.size = msg->size; - - reinit_completion(&aux->comp); - - if (aux->read) { - timeout = wait_for_completion_timeout(&aux->comp, HZ); - if (!timeout) { - pr_err("aux timeout for 0x%x\n", msg->address); - atomic_set(&aux->aborted, 1); - ret = -ETIMEDOUT; - goto end; - } - - memcpy(msg->buffer, aux->dpcd + msg->address, - msg->size); - } else { - memcpy(aux->dpcd + msg->address, msg->buffer, - msg->size); - - timeout = wait_for_completion_timeout(&aux->comp, HZ); - if (!timeout) { - pr_err("aux timeout for 0x%x\n", msg->address); - atomic_set(&aux->aborted, 1); - ret = -ETIMEDOUT; - goto end; - } - } - - aux->aux_error_num = DP_AUX_ERR_NONE; - } else { - if (aux->read && msg->address == 0x50) { - memcpy(msg->buffer, - aux->edid + aux->offset - 16, - msg->size); - } - } - - if (aux->aux_error_num == DP_AUX_ERR_NONE) { - dp_aux_hex_dump(drm_aux, msg); - - if (!aux->read) - memset(msg->buffer, 0, msg->size); - - msg->reply = aux->native ? - DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK; - } else { - /* Reply defer to retry */ - msg->reply = aux->native ? - DP_AUX_NATIVE_REPLY_DEFER : DP_AUX_I2C_REPLY_DEFER; - } - - ret = msg->size; - goto end; - -address_error: - memset(msg->buffer, 0, msg->size); - ret = msg->size; -end: - aux->dp_aux.reg = 0xFFFF; - aux->dp_aux.read = true; - aux->dp_aux.size = 0; - - mutex_unlock(&aux->mutex); - return ret; -} - -/* - * This function does the real job to process an AUX transaction. - * It will call aux_reset() function to reset the AUX channel, - * if the waiting is timeout. - */ -static ssize_t dp_aux_transfer(struct drm_dp_aux *drm_aux, - struct drm_dp_aux_msg *msg) -{ - ssize_t ret; - int const retry_count = 5; - struct dp_aux_private *aux = container_of(drm_aux, - struct dp_aux_private, drm_aux); - - mutex_lock(&aux->mutex); - - ret = dp_aux_transfer_ready(aux, msg, true); - if (ret) - goto unlock_exit; - - if (!aux->cmd_busy) { - ret = msg->size; - goto unlock_exit; - } - - ret = dp_aux_cmd_fifo_tx(aux, msg); - if ((ret < 0) && !atomic_read(&aux->aborted)) { - aux->retry_cnt++; - if (!(aux->retry_cnt % retry_count)) - aux->catalog->update_aux_cfg(aux->catalog, - aux->cfg, PHY_AUX_CFG1); - aux->catalog->reset(aux->catalog); - goto unlock_exit; - } else if (ret < 0) { - goto unlock_exit; - } - - if (aux->aux_error_num == DP_AUX_ERR_NONE) { - if (aux->read) - dp_aux_cmd_fifo_rx(aux, msg); - - dp_aux_hex_dump(drm_aux, msg); - - msg->reply = aux->native ? - DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK; - } else { - /* Reply defer to retry */ - msg->reply = aux->native ? - DP_AUX_NATIVE_REPLY_DEFER : DP_AUX_I2C_REPLY_DEFER; - } - - /* Return requested size for success or retry */ - ret = msg->size; - aux->retry_cnt = 0; - -unlock_exit: - aux->cmd_busy = false; - mutex_unlock(&aux->mutex); - return ret; -} - -static void dp_aux_reset_phy_config_indices(struct dp_aux_cfg *aux_cfg) -{ - int i = 0; - - for (i = 0; i < PHY_AUX_CFG_MAX; i++) - aux_cfg[i].current_index = 0; -} - -static void dp_aux_init(struct dp_aux *dp_aux, struct dp_aux_cfg *aux_cfg) -{ - struct dp_aux_private *aux; - - if (!dp_aux || !aux_cfg) { - pr_err("invalid input\n"); - return; - } - - aux = container_of(dp_aux, struct dp_aux_private, dp_aux); - - if (aux->enabled) - return; - - dp_aux_reset_phy_config_indices(aux_cfg); - aux->catalog->setup(aux->catalog, aux_cfg); - aux->catalog->reset(aux->catalog); - aux->catalog->enable(aux->catalog, true); - atomic_set(&aux->aborted, 0); - aux->retry_cnt = 0; - aux->enabled = true; -} - -static void dp_aux_deinit(struct dp_aux *dp_aux) -{ - struct dp_aux_private *aux; - - if (!dp_aux) { - pr_err("invalid input\n"); - return; - } - - aux = container_of(dp_aux, struct dp_aux_private, dp_aux); - - if (!aux->enabled) - return; - - atomic_set(&aux->aborted, 1); - aux->catalog->enable(aux->catalog, false); - aux->enabled = false; -} - -static int dp_aux_register(struct dp_aux *dp_aux) -{ - struct dp_aux_private *aux; - int ret = 0; - - if (!dp_aux) { - pr_err("invalid input\n"); - ret = -EINVAL; - goto exit; - } - - aux = container_of(dp_aux, struct dp_aux_private, dp_aux); - - aux->drm_aux.name = "sde_dp_aux"; - aux->drm_aux.dev = aux->dev; - aux->drm_aux.transfer = dp_aux_transfer; - ret = drm_dp_aux_register(&aux->drm_aux); - if (ret) { - pr_err("%s: failed to register drm aux: %d\n", __func__, ret); - goto exit; - } - dp_aux->drm_aux = &aux->drm_aux; -exit: - return ret; -} - -static void dp_aux_deregister(struct dp_aux *dp_aux) -{ - struct dp_aux_private *aux; - - if (!dp_aux) { - pr_err("invalid input\n"); - return; - } - - aux = container_of(dp_aux, struct dp_aux_private, dp_aux); - drm_dp_aux_unregister(&aux->drm_aux); -} - -static void dp_aux_dpcd_updated(struct dp_aux *dp_aux) -{ - struct dp_aux_private *aux; - - if (!dp_aux) { - pr_err("invalid input\n"); - return; - } - - aux = container_of(dp_aux, struct dp_aux_private, dp_aux); - - complete(&aux->comp); -} - -static void dp_aux_set_sim_mode(struct dp_aux *dp_aux, bool en, - u8 *edid, u8 *dpcd) -{ - struct dp_aux_private *aux; - - if (!dp_aux) { - pr_err("invalid input\n"); - return; - } - - aux = container_of(dp_aux, struct dp_aux_private, dp_aux); - - mutex_lock(&aux->mutex); - - aux->edid = edid; - aux->dpcd = dpcd; - - if (en) { - atomic_set(&aux->aborted, 0); - aux->drm_aux.transfer = dp_aux_transfer_debug; - } else { - aux->drm_aux.transfer = dp_aux_transfer; - } - - mutex_unlock(&aux->mutex); -} - -static int dp_aux_configure_aux_switch(struct dp_aux *dp_aux, - bool enable, int orientation) -{ - struct dp_aux_private *aux; - int rc = 0; - enum fsa_function event = FSA_USBC_DISPLAYPORT_DISCONNECTED; - - if (!dp_aux) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto end; - } - - aux = container_of(dp_aux, struct dp_aux_private, dp_aux); - - if (!aux->aux_switch_node) { - pr_debug("undefined fsa4480 handle\n"); - rc = -EINVAL; - goto end; - } - - if (enable) { - switch (orientation) { - case ORIENTATION_CC1: - event = FSA_USBC_ORIENTATION_CC1; - break; - case ORIENTATION_CC2: - event = FSA_USBC_ORIENTATION_CC2; - break; - default: - pr_err("invalid orientation\n"); - rc = -EINVAL; - goto end; - } - } - - pr_debug("enable=%d, orientation=%d, event=%d\n", - enable, orientation, event); - - rc = fsa4480_switch_event(aux->aux_switch_node, event); - if (rc) - pr_err("failed to configure fsa4480 i2c device (%d)\n", rc); -end: - return rc; -} - -struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog, - struct dp_parser *parser, struct device_node *aux_switch) -{ - int rc = 0; - struct dp_aux_private *aux; - struct dp_aux *dp_aux; - - if (!catalog || !parser || - (!parser->no_aux_switch && - !aux_switch && - !parser->gpio_aux_switch)) { - pr_err("invalid input\n"); - rc = -ENODEV; - goto error; - } - - aux = devm_kzalloc(dev, sizeof(*aux), GFP_KERNEL); - if (!aux) { - rc = -ENOMEM; - goto error; - } - - init_completion(&aux->comp); - aux->cmd_busy = false; - mutex_init(&aux->mutex); - - aux->dev = dev; - aux->catalog = catalog; - aux->cfg = parser->aux_cfg; - aux->aux_switch_node = aux_switch; - dp_aux = &aux->dp_aux; - aux->retry_cnt = 0; - aux->dp_aux.reg = 0xFFFF; - - dp_aux->isr = dp_aux_isr; - dp_aux->init = dp_aux_init; - dp_aux->deinit = dp_aux_deinit; - dp_aux->drm_aux_register = dp_aux_register; - dp_aux->drm_aux_deregister = dp_aux_deregister; - dp_aux->reconfig = dp_aux_reconfig; - dp_aux->abort = dp_aux_abort_transaction; - dp_aux->dpcd_updated = dp_aux_dpcd_updated; - dp_aux->set_sim_mode = dp_aux_set_sim_mode; - dp_aux->aux_switch = dp_aux_configure_aux_switch; - - return dp_aux; -error: - return ERR_PTR(rc); -} - -void dp_aux_put(struct dp_aux *dp_aux) -{ - struct dp_aux_private *aux; - - if (!dp_aux) - return; - - aux = container_of(dp_aux, struct dp_aux_private, dp_aux); - - mutex_destroy(&aux->mutex); - - devm_kfree(aux->dev, aux); -} diff --git a/drivers/gpu/drm/msm/dp/dp_aux.h b/drivers/gpu/drm/msm/dp/dp_aux.h deleted file mode 100644 index 888c8cc268cd4cc53f12afe57025bcd52f509788..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_aux.h +++ /dev/null @@ -1,59 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. - */ - -#ifndef _DP_AUX_H_ -#define _DP_AUX_H_ - -#include "dp_catalog.h" -#include "drm_dp_helper.h" - -#define DP_STATE_NOTIFICATION_SENT BIT(0) -#define DP_STATE_TRAIN_1_STARTED BIT(1) -#define DP_STATE_TRAIN_1_SUCCEEDED BIT(2) -#define DP_STATE_TRAIN_1_FAILED BIT(3) -#define DP_STATE_TRAIN_2_STARTED BIT(4) -#define DP_STATE_TRAIN_2_SUCCEEDED BIT(5) -#define DP_STATE_TRAIN_2_FAILED BIT(6) -#define DP_STATE_CTRL_POWERED_ON BIT(7) -#define DP_STATE_CTRL_POWERED_OFF BIT(8) -#define DP_STATE_LINK_MAINTENANCE_STARTED BIT(9) -#define DP_STATE_LINK_MAINTENANCE_COMPLETED BIT(10) -#define DP_STATE_LINK_MAINTENANCE_FAILED BIT(11) - -enum dp_aux_error { - DP_AUX_ERR_NONE = 0, - DP_AUX_ERR_ADDR = -1, - DP_AUX_ERR_TOUT = -2, - DP_AUX_ERR_NACK = -3, - DP_AUX_ERR_DEFER = -4, - DP_AUX_ERR_NACK_DEFER = -5, - DP_AUX_ERR_PHY = -6, -}; - -struct dp_aux { - u32 reg; - u32 size; - u32 state; - - bool read; - - struct drm_dp_aux *drm_aux; - int (*drm_aux_register)(struct dp_aux *aux); - void (*drm_aux_deregister)(struct dp_aux *aux); - void (*isr)(struct dp_aux *aux); - void (*init)(struct dp_aux *aux, struct dp_aux_cfg *aux_cfg); - void (*deinit)(struct dp_aux *aux); - void (*reconfig)(struct dp_aux *aux); - void (*abort)(struct dp_aux *aux); - void (*dpcd_updated)(struct dp_aux *aux); - void (*set_sim_mode)(struct dp_aux *aux, bool en, u8 *edid, u8 *dpcd); - int (*aux_switch)(struct dp_aux *aux, bool enable, int orientation); -}; - -struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog, - struct dp_parser *parser, struct device_node *aux_switch); -void dp_aux_put(struct dp_aux *aux); - -#endif /*__DP_AUX_H_*/ diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c deleted file mode 100644 index 0d22a6ed7328b7563e637ef56b3b55cf66035cab..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ /dev/null @@ -1,2680 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ - -#include -#include - -#include "dp_catalog.h" -#include "dp_reg.h" - -#define DP_GET_MSB(x) (x >> 8) -#define DP_GET_LSB(x) (x & 0xff) - -#define dp_catalog_get_priv(x) ({ \ - struct dp_catalog *dp_catalog; \ - dp_catalog = container_of(x, struct dp_catalog, x); \ - container_of(dp_catalog, struct dp_catalog_private, \ - dp_catalog); \ -}) - -#define DP_INTERRUPT_STATUS1 \ - (DP_INTR_AUX_I2C_DONE| \ - DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \ - DP_INTR_NACK_DEFER | DP_INTR_WRONG_DATA_CNT | \ - DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER | \ - DP_INTR_PLL_UNLOCKED | DP_INTR_AUX_ERROR) - -#define DP_INTR_MASK1 (DP_INTERRUPT_STATUS1 << 2) - -#define DP_INTERRUPT_STATUS2 \ - (DP_INTR_READY_FOR_VIDEO | DP_INTR_IDLE_PATTERN_SENT | \ - DP_INTR_FRAME_END | DP_INTR_CRC_UPDATED) - -#define DP_INTR_MASK2 (DP_INTERRUPT_STATUS2 << 2) - -#define DP_INTERRUPT_STATUS5 \ - (DP_INTR_MST_DP0_VCPF_SENT | DP_INTR_MST_DP1_VCPF_SENT) - -#define DP_INTR_MASK5 (DP_INTERRUPT_STATUS5 << 2) - -#define dp_catalog_fill_io(x) { \ - catalog->io.x = parser->get_io(parser, #x); \ -} - -#define dp_catalog_fill_io_buf(x) { \ - parser->get_io_buf(parser, #x); \ -} - -static u8 const vm_pre_emphasis[4][4] = { - {0x00, 0x0B, 0x12, 0xFF}, /* pe0, 0 db */ - {0x00, 0x0A, 0x12, 0xFF}, /* pe1, 3.5 db */ - {0x00, 0x0C, 0xFF, 0xFF}, /* pe2, 6.0 db */ - {0xFF, 0xFF, 0xFF, 0xFF} /* pe3, 9.5 db */ -}; - -/* voltage swing, 0.2v and 1.0v are not support */ -static u8 const vm_voltage_swing[4][4] = { - {0x07, 0x0F, 0x14, 0xFF}, /* sw0, 0.4v */ - {0x11, 0x1D, 0x1F, 0xFF}, /* sw1, 0.6 v */ - {0x18, 0x1F, 0xFF, 0xFF}, /* sw1, 0.8 v */ - {0xFF, 0xFF, 0xFF, 0xFF} /* sw1, 1.2 v, optional */ -}; - -enum dp_flush_bit { - DP_PPS_FLUSH, - DP_DHDR_FLUSH, -}; - -struct dp_catalog_io { - struct dp_io_data *dp_ahb; - struct dp_io_data *dp_aux; - struct dp_io_data *dp_link; - struct dp_io_data *dp_p0; - struct dp_io_data *dp_phy; - struct dp_io_data *dp_ln_tx0; - struct dp_io_data *dp_ln_tx1; - struct dp_io_data *dp_mmss_cc; - struct dp_io_data *dp_pll; - struct dp_io_data *usb3_dp_com; - struct dp_io_data *hdcp_physical; - struct dp_io_data *dp_p1; - struct dp_io_data *dp_tcsr; -}; - -/* audio related catalog functions */ -struct dp_catalog_private { - struct device *dev; - struct dp_catalog_io io; - struct dp_parser *parser; - - u32 (*audio_map)[DP_AUDIO_SDP_HEADER_MAX]; - struct dp_catalog dp_catalog; - - char exe_mode[SZ_4]; -}; - -/* aux related catalog functions */ -static u32 dp_catalog_aux_read_data(struct dp_catalog_aux *aux) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!aux) { - pr_err("invalid input\n"); - goto end; - } - - catalog = dp_catalog_get_priv(aux); - io_data = catalog->io.dp_aux; - - return dp_read(catalog->exe_mode, io_data, DP_AUX_DATA); -end: - return 0; -} - -static int dp_catalog_aux_write_data(struct dp_catalog_aux *aux) -{ - int rc = 0; - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!aux) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto end; - } - - catalog = dp_catalog_get_priv(aux); - io_data = catalog->io.dp_aux; - - dp_write(catalog->exe_mode, io_data, DP_AUX_DATA, aux->data); -end: - return rc; -} - -static int dp_catalog_aux_write_trans(struct dp_catalog_aux *aux) -{ - int rc = 0; - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!aux) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto end; - } - - catalog = dp_catalog_get_priv(aux); - io_data = catalog->io.dp_aux; - - dp_write(catalog->exe_mode, io_data, DP_AUX_TRANS_CTRL, aux->data); -end: - return rc; -} - -static int dp_catalog_aux_clear_trans(struct dp_catalog_aux *aux, bool read) -{ - int rc = 0; - u32 data = 0; - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!aux) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto end; - } - - catalog = dp_catalog_get_priv(aux); - io_data = catalog->io.dp_aux; - - if (read) { - data = dp_read(catalog->exe_mode, io_data, DP_AUX_TRANS_CTRL); - data &= ~BIT(9); - dp_write(catalog->exe_mode, io_data, DP_AUX_TRANS_CTRL, data); - } else { - dp_write(catalog->exe_mode, io_data, DP_AUX_TRANS_CTRL, 0); - } -end: - return rc; -} - -static void dp_catalog_aux_clear_hw_interrupts(struct dp_catalog_aux *aux) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - u32 data = 0; - - if (!aux) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(aux); - io_data = catalog->io.dp_phy; - - data = dp_read(catalog->exe_mode, io_data, DP_PHY_AUX_INTERRUPT_STATUS); - - dp_write(catalog->exe_mode, io_data, DP_PHY_AUX_INTERRUPT_CLEAR, 0x1f); - wmb(); /* make sure 0x1f is written before next write */ - dp_write(catalog->exe_mode, io_data, DP_PHY_AUX_INTERRUPT_CLEAR, 0x9f); - wmb(); /* make sure 0x9f is written before next write */ - dp_write(catalog->exe_mode, io_data, DP_PHY_AUX_INTERRUPT_CLEAR, 0); - wmb(); /* make sure register is cleared */ -} - -static void dp_catalog_aux_reset(struct dp_catalog_aux *aux) -{ - u32 aux_ctrl; - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!aux) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(aux); - io_data = catalog->io.dp_aux; - - aux_ctrl = dp_read(catalog->exe_mode, io_data, DP_AUX_CTRL); - - aux_ctrl |= BIT(1); - dp_write(catalog->exe_mode, io_data, DP_AUX_CTRL, aux_ctrl); - usleep_range(1000, 1010); /* h/w recommended delay */ - - aux_ctrl &= ~BIT(1); - - dp_write(catalog->exe_mode, io_data, DP_AUX_CTRL, aux_ctrl); - wmb(); /* make sure AUX reset is done here */ -} - -static void dp_catalog_aux_enable(struct dp_catalog_aux *aux, bool enable) -{ - u32 aux_ctrl; - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!aux) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(aux); - io_data = catalog->io.dp_aux; - - aux_ctrl = dp_read(catalog->exe_mode, io_data, DP_AUX_CTRL); - - if (enable) { - aux_ctrl |= BIT(0); - dp_write(catalog->exe_mode, io_data, DP_AUX_CTRL, aux_ctrl); - wmb(); /* make sure AUX module is enabled */ - - dp_write(catalog->exe_mode, io_data, DP_TIMEOUT_COUNT, 0xffff); - dp_write(catalog->exe_mode, io_data, DP_AUX_LIMITS, 0xffff); - } else { - aux_ctrl &= ~BIT(0); - dp_write(catalog->exe_mode, io_data, DP_AUX_CTRL, aux_ctrl); - } -} - -static void dp_catalog_aux_update_cfg(struct dp_catalog_aux *aux, - struct dp_aux_cfg *cfg, enum dp_phy_aux_config_type type) -{ - struct dp_catalog_private *catalog; - u32 new_index = 0, current_index = 0; - struct dp_io_data *io_data; - - if (!aux || !cfg || (type >= PHY_AUX_CFG_MAX)) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(aux); - - io_data = catalog->io.dp_phy; - - current_index = cfg[type].current_index; - new_index = (current_index + 1) % cfg[type].cfg_cnt; - pr_debug("Updating %s from 0x%08x to 0x%08x\n", - dp_phy_aux_config_type_to_string(type), - cfg[type].lut[current_index], cfg[type].lut[new_index]); - - dp_write(catalog->exe_mode, io_data, cfg[type].offset, - cfg[type].lut[new_index]); - cfg[type].current_index = new_index; -} - -static void dp_catalog_aux_setup(struct dp_catalog_aux *aux, - struct dp_aux_cfg *cfg) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - int i = 0; - - if (!aux || !cfg) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(aux); - - io_data = catalog->io.dp_phy; - dp_write(catalog->exe_mode, io_data, DP_PHY_PD_CTL, 0x65); - wmb(); /* make sure PD programming happened */ - - /* Turn on BIAS current for PHY/PLL */ - io_data = catalog->io.dp_pll; - dp_write(catalog->exe_mode, io_data, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, - 0x1b); - - io_data = catalog->io.dp_phy; - dp_write(catalog->exe_mode, io_data, DP_PHY_PD_CTL, 0x02); - wmb(); /* make sure PD programming happened */ - dp_write(catalog->exe_mode, io_data, DP_PHY_PD_CTL, 0x7d); - - /* Turn on BIAS current for PHY/PLL */ - io_data = catalog->io.dp_pll; - dp_write(catalog->exe_mode, io_data, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, - 0x3f); - - /* DP AUX CFG register programming */ - io_data = catalog->io.dp_phy; - for (i = 0; i < PHY_AUX_CFG_MAX; i++) - dp_write(catalog->exe_mode, io_data, cfg[i].offset, - cfg[i].lut[cfg[i].current_index]); - - dp_write(catalog->exe_mode, io_data, DP_PHY_AUX_INTERRUPT_MASK, 0x1F); - wmb(); /* make sure AUX configuration is done before enabling it */ -} - -static void dp_catalog_aux_get_irq(struct dp_catalog_aux *aux, bool cmd_busy) -{ - u32 ack; - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!aux) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(aux); - io_data = catalog->io.dp_ahb; - - aux->isr = dp_read(catalog->exe_mode, io_data, DP_INTR_STATUS); - aux->isr &= ~DP_INTR_MASK1; - ack = aux->isr & DP_INTERRUPT_STATUS1; - ack <<= 1; - ack |= DP_INTR_MASK1; - dp_write(catalog->exe_mode, io_data, DP_INTR_STATUS, ack); -} - -/* controller related catalog functions */ -static u32 dp_catalog_ctrl_read_hdcp_status(struct dp_catalog_ctrl *ctrl) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!ctrl) { - pr_err("invalid input\n"); - return -EINVAL; - } - - catalog = dp_catalog_get_priv(ctrl); - io_data = catalog->io.dp_ahb; - - return dp_read(catalog->exe_mode, io_data, DP_HDCP_STATUS); -} - -static void dp_catalog_panel_setup_vsif_infoframe_sdp( - struct dp_catalog_panel *panel) -{ - struct dp_catalog_private *catalog; - struct drm_msm_ext_hdr_metadata *hdr; - struct dp_io_data *io_data; - u32 header, parity, data, mst_offset = 0; - u8 buf[SZ_64], off = 0; - - if (panel->stream_id >= DP_STREAM_MAX) { - pr_err("invalid stream_id:%d\n", panel->stream_id); - return; - } - - if (panel->stream_id == DP_STREAM_1) - mst_offset = MMSS_DP1_VSCEXT_0 - MMSS_DP_VSCEXT_0; - - catalog = dp_catalog_get_priv(panel); - hdr = &panel->hdr_data.hdr_meta; - io_data = catalog->io.dp_link; - - /* HEADER BYTE 1 */ - header = panel->hdr_data.vscext_header_byte1; - parity = dp_header_get_parity(header); - data = ((header << HEADER_BYTE_1_BIT) - | (parity << PARITY_BYTE_1_BIT)); - dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_0 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - /* HEADER BYTE 2 */ - header = panel->hdr_data.vscext_header_byte2; - parity = dp_header_get_parity(header); - data = ((header << HEADER_BYTE_2_BIT) - | (parity << PARITY_BYTE_2_BIT)); - dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_1 + mst_offset, - data); - - /* HEADER BYTE 3 */ - header = panel->hdr_data.vscext_header_byte3; - parity = dp_header_get_parity(header); - data = ((header << HEADER_BYTE_3_BIT) - | (parity << PARITY_BYTE_3_BIT)); - data |= dp_read(catalog->exe_mode, io_data, - MMSS_DP_VSCEXT_1 + mst_offset); - dp_write(catalog->exe_mode, io_data, MMSS_DP_VSCEXT_1 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - print_hex_dump(KERN_DEBUG, "[drm-dp] VSCEXT: ", - DUMP_PREFIX_NONE, 16, 4, buf, off, false); -} - -static void dp_catalog_panel_setup_hdr_infoframe_sdp( - struct dp_catalog_panel *panel) -{ - struct dp_catalog_private *catalog; - struct drm_msm_ext_hdr_metadata *hdr; - struct dp_io_data *io_data; - u32 header, parity, data, mst_offset = 0; - u8 buf[SZ_64], off = 0; - - if (panel->stream_id >= DP_STREAM_MAX) { - pr_err("invalid stream_id:%d\n", panel->stream_id); - return; - } - - if (panel->stream_id == DP_STREAM_1) - mst_offset = MMSS_DP1_GENERIC2_0 - MMSS_DP_GENERIC2_0; - - catalog = dp_catalog_get_priv(panel); - hdr = &panel->hdr_data.hdr_meta; - io_data = catalog->io.dp_link; - - /* HEADER BYTE 1 */ - header = panel->hdr_data.shdr_header_byte1; - parity = dp_header_get_parity(header); - data = ((header << HEADER_BYTE_1_BIT) - | (parity << PARITY_BYTE_1_BIT)); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC2_0 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - /* HEADER BYTE 2 */ - header = panel->hdr_data.shdr_header_byte2; - parity = dp_header_get_parity(header); - data = ((header << HEADER_BYTE_2_BIT) - | (parity << PARITY_BYTE_2_BIT)); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC2_1 + mst_offset, - data); - - /* HEADER BYTE 3 */ - header = panel->hdr_data.shdr_header_byte3; - parity = dp_header_get_parity(header); - data = ((header << HEADER_BYTE_3_BIT) - | (parity << PARITY_BYTE_3_BIT)); - data |= dp_read(catalog->exe_mode, io_data, - MMSS_DP_VSCEXT_1 + mst_offset); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC2_1 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - data = panel->hdr_data.version; - data |= panel->hdr_data.length << 8; - data |= hdr->eotf << 16; - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC2_2 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - data = (DP_GET_LSB(hdr->display_primaries_x[0]) | - (DP_GET_MSB(hdr->display_primaries_x[0]) << 8) | - (DP_GET_LSB(hdr->display_primaries_y[0]) << 16) | - (DP_GET_MSB(hdr->display_primaries_y[0]) << 24)); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC2_3 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - data = (DP_GET_LSB(hdr->display_primaries_x[1]) | - (DP_GET_MSB(hdr->display_primaries_x[1]) << 8) | - (DP_GET_LSB(hdr->display_primaries_y[1]) << 16) | - (DP_GET_MSB(hdr->display_primaries_y[1]) << 24)); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC2_4 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - data = (DP_GET_LSB(hdr->display_primaries_x[2]) | - (DP_GET_MSB(hdr->display_primaries_x[2]) << 8) | - (DP_GET_LSB(hdr->display_primaries_y[2]) << 16) | - (DP_GET_MSB(hdr->display_primaries_y[2]) << 24)); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC2_5 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - data = (DP_GET_LSB(hdr->white_point_x) | - (DP_GET_MSB(hdr->white_point_x) << 8) | - (DP_GET_LSB(hdr->white_point_y) << 16) | - (DP_GET_MSB(hdr->white_point_y) << 24)); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC2_6 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - data = (DP_GET_LSB(hdr->max_luminance) | - (DP_GET_MSB(hdr->max_luminance) << 8) | - (DP_GET_LSB(hdr->min_luminance) << 16) | - (DP_GET_MSB(hdr->min_luminance) << 24)); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC2_7 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - data = (DP_GET_LSB(hdr->max_content_light_level) | - (DP_GET_MSB(hdr->max_content_light_level) << 8) | - (DP_GET_LSB(hdr->max_average_light_level) << 16) | - (DP_GET_MSB(hdr->max_average_light_level) << 24)); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC2_8 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - data = 0; - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC2_9 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - print_hex_dump(KERN_DEBUG, "[drm-dp] HDR: ", - DUMP_PREFIX_NONE, 16, 4, buf, off, false); -} - -static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - u32 header, parity, data, mst_offset = 0; - u8 bpc, off = 0; - u8 buf[SZ_128]; - - if (!panel) { - pr_err("invalid input\n"); - return; - } - - if (panel->stream_id >= DP_STREAM_MAX) { - pr_err("invalid stream_id:%d\n", panel->stream_id); - return; - } - - if (panel->stream_id == DP_STREAM_1) - mst_offset = MMSS_DP1_GENERIC0_0 - MMSS_DP_GENERIC0_0; - - catalog = dp_catalog_get_priv(panel); - io_data = catalog->io.dp_link; - - /* HEADER BYTE 1 */ - header = panel->hdr_data.vsc_header_byte1; - parity = dp_header_get_parity(header); - data = ((header << HEADER_BYTE_1_BIT) - | (parity << PARITY_BYTE_1_BIT)); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_0 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - /* HEADER BYTE 2 */ - header = panel->hdr_data.vsc_header_byte2; - parity = dp_header_get_parity(header); - data = ((header << HEADER_BYTE_2_BIT) - | (parity << PARITY_BYTE_2_BIT)); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_1 + mst_offset, - data); - - /* HEADER BYTE 3 */ - header = panel->hdr_data.vsc_header_byte3; - parity = dp_header_get_parity(header); - data = ((header << HEADER_BYTE_3_BIT) - | (parity << PARITY_BYTE_3_BIT)); - data |= dp_read(catalog->exe_mode, io_data, - MMSS_DP_GENERIC0_1 + mst_offset); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_1 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - data = 0; - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_2 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_3 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_4 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_5 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - switch (panel->hdr_data.bpc) { - default: - case 10: - bpc = BIT(1); - break; - case 8: - bpc = BIT(0); - break; - case 6: - bpc = 0; - break; - } - - data = (panel->hdr_data.colorimetry & 0xF) | - ((panel->hdr_data.pixel_encoding & 0xF) << 4) | - (bpc << 8) | - ((panel->hdr_data.dynamic_range & 0x1) << 15) | - ((panel->hdr_data.content_type & 0x7) << 16); - - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_6 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - data = 0; - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_7 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_8 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_9 + mst_offset, - data); - memcpy(buf + off, &data, sizeof(data)); - off += sizeof(data); - - print_hex_dump(KERN_DEBUG, "[drm-dp] VSC: ", - DUMP_PREFIX_NONE, 16, 4, buf, off, false); -} - -static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en, - u32 dhdr_max_pkts) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - u32 cfg, cfg2, cfg4, misc; - u32 sdp_cfg_off = 0; - u32 sdp_cfg2_off = 0; - u32 sdp_cfg3_off = 0; - u32 sdp_cfg4_off = 0; - u32 misc1_misc0_off = 0; - - if (!panel) { - pr_err("invalid input\n"); - return; - } - - if (panel->stream_id >= DP_STREAM_MAX) { - pr_err("invalid stream_id:%d\n", panel->stream_id); - return; - } - - catalog = dp_catalog_get_priv(panel); - io_data = catalog->io.dp_link; - - if (panel->stream_id == DP_STREAM_1) { - sdp_cfg_off = MMSS_DP1_SDP_CFG - MMSS_DP_SDP_CFG; - sdp_cfg2_off = MMSS_DP1_SDP_CFG2 - MMSS_DP_SDP_CFG2; - sdp_cfg3_off = MMSS_DP1_SDP_CFG3 - MMSS_DP_SDP_CFG3; - sdp_cfg4_off = MMSS_DP1_SDP_CFG4 - MMSS_DP_SDP_CFG4; - misc1_misc0_off = DP1_MISC1_MISC0 - DP_MISC1_MISC0; - } - - cfg = dp_read(catalog->exe_mode, io_data, - MMSS_DP_SDP_CFG + sdp_cfg_off); - cfg2 = dp_read(catalog->exe_mode, io_data, - MMSS_DP_SDP_CFG2 + sdp_cfg2_off); - misc = dp_read(catalog->exe_mode, io_data, - DP_MISC1_MISC0 + misc1_misc0_off); - - if (en) { - if (dhdr_max_pkts) { - /* VSCEXT_SDP_EN */ - cfg |= BIT(16); - /* DHDR_EN, DHDR_PACKET_LIMIT */ - cfg4 = (dhdr_max_pkts << 1) | BIT(0); - dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG4 - + sdp_cfg4_off, cfg4); - dp_catalog_panel_setup_vsif_infoframe_sdp(panel); - } - - /* GEN0_SDP_EN, GEN2_SDP_EN */ - cfg |= BIT(17) | BIT(19); - dp_write(catalog->exe_mode, io_data, - MMSS_DP_SDP_CFG + sdp_cfg_off, cfg); - - /* GENERIC0_SDPSIZE GENERIC2_SDPSIZE */ - cfg2 |= BIT(16) | BIT(20); - dp_write(catalog->exe_mode, io_data, - MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2); - - dp_catalog_panel_setup_vsc_sdp(panel); - dp_catalog_panel_setup_hdr_infoframe_sdp(panel); - - /* indicates presence of VSC (BIT(6) of MISC1) */ - misc |= BIT(14); - - if (panel->hdr_data.hdr_meta.eotf) - pr_debug("Enabled\n"); - else - pr_debug("Reset\n"); - } else { - /* VSCEXT_SDP_EN, GEN0_SDP_EN */ - cfg &= ~BIT(16) & ~BIT(17) & ~BIT(19); - dp_write(catalog->exe_mode, io_data, - MMSS_DP_SDP_CFG + sdp_cfg_off, cfg); - - /* GENERIC0_SDPSIZE GENERIC2_SDPSIZE */ - cfg2 &= ~BIT(16) & ~BIT(20); - dp_write(catalog->exe_mode, io_data, - MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2); - - /* DHDR_EN, DHDR_PACKET_LIMIT */ - cfg4 = 0; - dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG4 - + sdp_cfg4_off, cfg4); - - /* switch back to MSA */ - misc &= ~BIT(14); - - pr_debug("Disabled\n"); - } - - dp_write(catalog->exe_mode, io_data, DP_MISC1_MISC0 + misc1_misc0_off, - misc); - - dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off, - 0x01); - dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off, - 0x00); -} - -static void dp_catalog_panel_update_transfer_unit( - struct dp_catalog_panel *panel) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!panel || panel->stream_id >= DP_STREAM_MAX) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(panel); - io_data = catalog->io.dp_link; - - dp_write(catalog->exe_mode, io_data, DP_VALID_BOUNDARY, - panel->valid_boundary); - dp_write(catalog->exe_mode, io_data, DP_TU, panel->dp_tu); - dp_write(catalog->exe_mode, io_data, DP_VALID_BOUNDARY_2, - panel->valid_boundary2); -} - -static void dp_catalog_ctrl_state_ctrl(struct dp_catalog_ctrl *ctrl, u32 state) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(ctrl); - io_data = catalog->io.dp_link; - - dp_write(catalog->exe_mode, io_data, DP_STATE_CTRL, state); - /* make sure to change the hw state */ - wmb(); -} - -static void dp_catalog_ctrl_config_ctrl(struct dp_catalog_ctrl *ctrl, u8 ln_cnt) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - u32 cfg; - - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(ctrl); - io_data = catalog->io.dp_link; - - cfg = dp_read(catalog->exe_mode, io_data, DP_CONFIGURATION_CTRL); - cfg &= ~(BIT(4) | BIT(5)); - cfg |= (ln_cnt - 1) << 4; - dp_write(catalog->exe_mode, io_data, DP_CONFIGURATION_CTRL, cfg); - - cfg = dp_read(catalog->exe_mode, io_data, DP_MAINLINK_CTRL); - cfg |= 0x02000000; - dp_write(catalog->exe_mode, io_data, DP_MAINLINK_CTRL, cfg); - - pr_debug("DP_MAINLINK_CTRL=0x%x\n", cfg); -} - -static void dp_catalog_panel_config_ctrl(struct dp_catalog_panel *panel, - u32 cfg) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - u32 strm_reg_off = 0, mainlink_ctrl; - - if (!panel) { - pr_err("invalid input\n"); - return; - } - - if (panel->stream_id >= DP_STREAM_MAX) { - pr_err("invalid stream_id:%d\n", panel->stream_id); - return; - } - - catalog = dp_catalog_get_priv(panel); - io_data = catalog->io.dp_link; - - if (panel->stream_id == DP_STREAM_1) - strm_reg_off = DP1_CONFIGURATION_CTRL - DP_CONFIGURATION_CTRL; - - pr_debug("DP_CONFIGURATION_CTRL=0x%x\n", cfg); - - dp_write(catalog->exe_mode, io_data, - DP_CONFIGURATION_CTRL + strm_reg_off, cfg); - - mainlink_ctrl = dp_read(catalog->exe_mode, io_data, DP_MAINLINK_CTRL); - - if (panel->stream_id == DP_STREAM_0) - io_data = catalog->io.dp_p0; - else if (panel->stream_id == DP_STREAM_1) - io_data = catalog->io.dp_p1; - - if (mainlink_ctrl & BIT(8)) - dp_write(catalog->exe_mode, io_data, MMSS_DP_ASYNC_FIFO_CONFIG, - 0x01); - else - dp_write(catalog->exe_mode, io_data, MMSS_DP_ASYNC_FIFO_CONFIG, - 0x00); -} - -static void dp_catalog_panel_config_dto(struct dp_catalog_panel *panel, - bool ack) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - u32 dsc_dto; - - if (!panel) { - pr_err("invalid input\n"); - return; - } - - if (panel->stream_id >= DP_STREAM_MAX) { - pr_err("invalid stream_id:%d\n", panel->stream_id); - return; - } - - catalog = dp_catalog_get_priv(panel); - io_data = catalog->io.dp_link; - - switch (panel->stream_id) { - case DP_STREAM_0: - io_data = catalog->io.dp_p0; - break; - case DP_STREAM_1: - io_data = catalog->io.dp_p1; - break; - default: - pr_err("invalid stream id\n"); - return; - } - - dsc_dto = dp_read(catalog->exe_mode, io_data, MMSS_DP_DSC_DTO); - if (ack) - dsc_dto = BIT(1); - else - dsc_dto &= ~BIT(1); - dp_write(catalog->exe_mode, io_data, MMSS_DP_DSC_DTO, dsc_dto); -} - -static void dp_catalog_ctrl_lane_mapping(struct dp_catalog_ctrl *ctrl, - bool flipped, char *lane_map) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(ctrl); - io_data = catalog->io.dp_link; - - dp_write(catalog->exe_mode, io_data, DP_LOGICAL2PHYSICAL_LANE_MAPPING, - 0xe4); -} - -static void dp_catalog_ctrl_lane_pnswap(struct dp_catalog_ctrl *ctrl, - u8 ln_pnswap) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - u32 cfg0, cfg1; - - catalog = dp_catalog_get_priv(ctrl); - - cfg0 = 0x0a; - cfg1 = 0x0a; - - cfg0 |= ((ln_pnswap >> 0) & 0x1) << 0; - cfg0 |= ((ln_pnswap >> 1) & 0x1) << 2; - cfg1 |= ((ln_pnswap >> 2) & 0x1) << 0; - cfg1 |= ((ln_pnswap >> 3) & 0x1) << 2; - - io_data = catalog->io.dp_ln_tx0; - dp_write(catalog->exe_mode, io_data, TXn_TX_POL_INV, cfg0); - - io_data = catalog->io.dp_ln_tx1; - dp_write(catalog->exe_mode, io_data, TXn_TX_POL_INV, cfg1); -} - -static void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog_ctrl *ctrl, - bool enable) -{ - u32 mainlink_ctrl, reg; - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(ctrl); - io_data = catalog->io.dp_link; - - if (enable) { - reg = dp_read(catalog->exe_mode, io_data, DP_MAINLINK_CTRL); - mainlink_ctrl = reg & ~(0x03); - dp_write(catalog->exe_mode, io_data, DP_MAINLINK_CTRL, - mainlink_ctrl); - wmb(); /* make sure mainlink is turned off before reset */ - mainlink_ctrl = reg | 0x02; - dp_write(catalog->exe_mode, io_data, DP_MAINLINK_CTRL, - mainlink_ctrl); - wmb(); /* make sure mainlink entered reset */ - mainlink_ctrl = reg & ~(0x03); - dp_write(catalog->exe_mode, io_data, DP_MAINLINK_CTRL, - mainlink_ctrl); - wmb(); /* make sure mainlink reset done */ - mainlink_ctrl = reg | 0x01; - dp_write(catalog->exe_mode, io_data, DP_MAINLINK_CTRL, - mainlink_ctrl); - wmb(); /* make sure mainlink turned on */ - } else { - mainlink_ctrl = dp_read(catalog->exe_mode, io_data, - DP_MAINLINK_CTRL); - mainlink_ctrl &= ~BIT(0); - dp_write(catalog->exe_mode, io_data, DP_MAINLINK_CTRL, - mainlink_ctrl); - } -} - -static void dp_catalog_panel_config_misc(struct dp_catalog_panel *panel) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - u32 reg_offset = 0; - - if (!panel) { - pr_err("invalid input\n"); - return; - } - - if (panel->stream_id >= DP_STREAM_MAX) { - pr_err("invalid stream_id:%d\n", panel->stream_id); - return; - } - - catalog = dp_catalog_get_priv(panel); - io_data = catalog->io.dp_link; - - if (panel->stream_id == DP_STREAM_1) - reg_offset = DP1_MISC1_MISC0 - DP_MISC1_MISC0; - - pr_debug("misc settings = 0x%x\n", panel->misc_val); - dp_write(catalog->exe_mode, io_data, DP_MISC1_MISC0 + reg_offset, - panel->misc_val); -} - -static void dp_catalog_panel_config_msa(struct dp_catalog_panel *panel, - u32 rate, u32 stream_rate_khz) -{ - u32 pixel_m, pixel_n; - u32 mvid, nvid; - u32 const nvid_fixed = 0x8000; - u32 const link_rate_hbr2 = 540000; - u32 const link_rate_hbr3 = 810000; - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - u32 strm_reg_off = 0; - u32 mvid_reg_off = 0, nvid_reg_off = 0; - - if (!panel) { - pr_err("invalid input\n"); - return; - } - - if (panel->stream_id >= DP_STREAM_MAX) { - pr_err("invalid stream_id:%d\n", panel->stream_id); - return; - } - - catalog = dp_catalog_get_priv(panel); - io_data = catalog->io.dp_mmss_cc; - - if (panel->stream_id == DP_STREAM_1) - strm_reg_off = MMSS_DP_PIXEL1_M - MMSS_DP_PIXEL_M; - - pixel_m = dp_read(catalog->exe_mode, io_data, - MMSS_DP_PIXEL_M + strm_reg_off); - pixel_n = dp_read(catalog->exe_mode, io_data, - MMSS_DP_PIXEL_N + strm_reg_off); - pr_debug("pixel_m=0x%x, pixel_n=0x%x\n", pixel_m, pixel_n); - - mvid = (pixel_m & 0xFFFF) * 5; - nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF); - - if (nvid < nvid_fixed) { - u32 temp; - - temp = (nvid_fixed / nvid) * nvid; - mvid = (nvid_fixed / nvid) * mvid; - nvid = temp; - } - - pr_debug("rate = %d\n", rate); - - if (panel->widebus_en) - mvid <<= 1; - - if (link_rate_hbr2 == rate) - nvid *= 2; - - if (link_rate_hbr3 == rate) - nvid *= 3; - - io_data = catalog->io.dp_link; - - if (panel->stream_id == DP_STREAM_1) { - mvid_reg_off = DP1_SOFTWARE_MVID - DP_SOFTWARE_MVID; - nvid_reg_off = DP1_SOFTWARE_NVID - DP_SOFTWARE_NVID; - } - - pr_debug("mvid=0x%x, nvid=0x%x\n", mvid, nvid); - dp_write(catalog->exe_mode, io_data, DP_SOFTWARE_MVID + mvid_reg_off, - mvid); - dp_write(catalog->exe_mode, io_data, DP_SOFTWARE_NVID + nvid_reg_off, - nvid); -} - -static void dp_catalog_ctrl_set_pattern(struct dp_catalog_ctrl *ctrl, - u32 pattern) -{ - int bit, cnt = 10; - u32 data; - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(ctrl); - io_data = catalog->io.dp_link; - - bit = 1; - bit <<= (pattern - 1); - pr_debug("hw: bit=%d train=%d\n", bit, pattern); - dp_write(catalog->exe_mode, io_data, DP_STATE_CTRL, bit); - - bit = 8; - bit <<= (pattern - 1); - - while (cnt--) { - data = dp_read(catalog->exe_mode, io_data, DP_MAINLINK_READY); - if (data & bit) - break; - } - - if (cnt == 0) - pr_err("set link_train=%d failed\n", pattern); -} - -static void dp_catalog_ctrl_usb_reset(struct dp_catalog_ctrl *ctrl, bool flip) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(ctrl); - - io_data = catalog->io.usb3_dp_com; - - dp_write(catalog->exe_mode, io_data, USB3_DP_COM_RESET_OVRD_CTRL, 0x0a); - dp_write(catalog->exe_mode, io_data, USB3_DP_COM_PHY_MODE_CTRL, 0x02); - dp_write(catalog->exe_mode, io_data, USB3_DP_COM_SW_RESET, 0x01); - /* make sure usb3 com phy software reset is done */ - wmb(); - - if (!flip) { /* CC1 */ - dp_write(catalog->exe_mode, io_data, USB3_DP_COM_TYPEC_CTRL, - 0x02); - } else { /* CC2 */ - dp_write(catalog->exe_mode, io_data, USB3_DP_COM_TYPEC_CTRL, - 0x03); - } - - dp_write(catalog->exe_mode, io_data, USB3_DP_COM_SWI_CTRL, 0x00); - dp_write(catalog->exe_mode, io_data, USB3_DP_COM_SW_RESET, 0x00); - /* make sure the software reset is done */ - wmb(); - - dp_write(catalog->exe_mode, io_data, USB3_DP_COM_POWER_DOWN_CTRL, 0x01); - dp_write(catalog->exe_mode, io_data, USB3_DP_COM_RESET_OVRD_CTRL, 0x00); - /* make sure phy is brought out of reset */ - wmb(); -} - -static void dp_catalog_panel_tpg_cfg(struct dp_catalog_panel *panel, - bool enable) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!panel) { - pr_err("invalid input\n"); - return; - } - - if (panel->stream_id >= DP_STREAM_MAX) { - pr_err("invalid stream_id:%d\n", panel->stream_id); - return; - } - - catalog = dp_catalog_get_priv(panel); - - if (panel->stream_id == DP_STREAM_0) - io_data = catalog->io.dp_p0; - else if (panel->stream_id == DP_STREAM_1) - io_data = catalog->io.dp_p1; - - if (!enable) { - dp_write(catalog->exe_mode, io_data, MMSS_DP_TPG_MAIN_CONTROL, - 0x0); - dp_write(catalog->exe_mode, io_data, MMSS_DP_BIST_ENABLE, 0x0); - dp_write(catalog->exe_mode, io_data, MMSS_DP_TIMING_ENGINE_EN, - 0x0); - wmb(); /* ensure Timing generator is turned off */ - return; - } - - dp_write(catalog->exe_mode, io_data, MMSS_DP_INTF_CONFIG, 0x0); - dp_write(catalog->exe_mode, io_data, MMSS_DP_INTF_HSYNC_CTL, - panel->hsync_ctl); - dp_write(catalog->exe_mode, io_data, MMSS_DP_INTF_VSYNC_PERIOD_F0, - panel->vsync_period * panel->hsync_period); - dp_write(catalog->exe_mode, io_data, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F0, - panel->v_sync_width * panel->hsync_period); - dp_write(catalog->exe_mode, io_data, MMSS_DP_INTF_VSYNC_PERIOD_F1, 0); - dp_write(catalog->exe_mode, io_data, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F1, - 0); - dp_write(catalog->exe_mode, io_data, MMSS_DP_INTF_DISPLAY_HCTL, - panel->display_hctl); - dp_write(catalog->exe_mode, io_data, MMSS_DP_INTF_ACTIVE_HCTL, 0); - dp_write(catalog->exe_mode, io_data, MMSS_INTF_DISPLAY_V_START_F0, - panel->display_v_start); - dp_write(catalog->exe_mode, io_data, MMSS_DP_INTF_DISPLAY_V_END_F0, - panel->display_v_end); - dp_write(catalog->exe_mode, io_data, MMSS_INTF_DISPLAY_V_START_F1, 0); - dp_write(catalog->exe_mode, io_data, MMSS_DP_INTF_DISPLAY_V_END_F1, 0); - dp_write(catalog->exe_mode, io_data, MMSS_DP_INTF_ACTIVE_V_START_F0, 0); - dp_write(catalog->exe_mode, io_data, MMSS_DP_INTF_ACTIVE_V_END_F0, 0); - dp_write(catalog->exe_mode, io_data, MMSS_DP_INTF_ACTIVE_V_START_F1, 0); - dp_write(catalog->exe_mode, io_data, MMSS_DP_INTF_ACTIVE_V_END_F1, 0); - dp_write(catalog->exe_mode, io_data, MMSS_DP_INTF_POLARITY_CTL, 0); - wmb(); /* ensure TPG registers are programmed */ - - dp_write(catalog->exe_mode, io_data, MMSS_DP_TPG_MAIN_CONTROL, 0x100); - dp_write(catalog->exe_mode, io_data, MMSS_DP_TPG_VIDEO_CONFIG, 0x5); - wmb(); /* ensure TPG config is programmed */ - dp_write(catalog->exe_mode, io_data, MMSS_DP_BIST_ENABLE, 0x1); - dp_write(catalog->exe_mode, io_data, MMSS_DP_TIMING_ENGINE_EN, 0x1); - wmb(); /* ensure Timing generator is turned on */ -} - -static void dp_catalog_panel_dsc_cfg(struct dp_catalog_panel *panel) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - u32 reg, offset; - int i; - - if (!panel) { - pr_err("invalid input\n"); - return; - } - - if (panel->stream_id >= DP_STREAM_MAX) { - pr_err("invalid stream_id:%d\n", panel->stream_id); - return; - } - - catalog = dp_catalog_get_priv(panel); - - if (panel->stream_id == DP_STREAM_0) - io_data = catalog->io.dp_p0; - else - io_data = catalog->io.dp_p1; - - dp_write(catalog->exe_mode, io_data, MMSS_DP_DSC_DTO_COUNT, - panel->dsc.dto_count); - - reg = dp_read(catalog->exe_mode, io_data, MMSS_DP_DSC_DTO); - if (panel->dsc.dto_en) { - reg |= BIT(0); - reg |= (panel->dsc.dto_n << 8); - reg |= (panel->dsc.dto_d << 16); - } - dp_write(catalog->exe_mode, io_data, MMSS_DP_DSC_DTO, reg); - - io_data = catalog->io.dp_link; - - if (panel->stream_id == DP_STREAM_0) - offset = 0; - else - offset = DP1_COMPRESSION_MODE_CTRL - DP_COMPRESSION_MODE_CTRL; - - dp_write(catalog->exe_mode, io_data, DP_PPS_HB_0_3 + offset, 0x7F1000); - dp_write(catalog->exe_mode, io_data, DP_PPS_PB_0_3 + offset, 0xA22300); - - for (i = 0; i < panel->dsc.parity_word_len; i++) - dp_write(catalog->exe_mode, io_data, - DP_PPS_PB_4_7 + (i << 2) + offset, - panel->dsc.parity_word[i]); - - for (i = 0; i < panel->dsc.pps_word_len; i++) - dp_write(catalog->exe_mode, io_data, - DP_PPS_PPS_0_3 + (i << 2) + offset, - panel->dsc.pps_word[i]); - - reg = 0; - if (panel->dsc.dsc_en) { - reg = BIT(0); - reg |= (panel->dsc.eol_byte_num << 3); - reg |= (panel->dsc.slice_per_pkt << 5); - reg |= (panel->dsc.bytes_per_pkt << 16); - reg |= (panel->dsc.be_in_lane << 10); - } - dp_write(catalog->exe_mode, io_data, - DP_COMPRESSION_MODE_CTRL + offset, reg); - - pr_debug("compression:0x%x for stream:%d\n", - reg, panel->stream_id); -} - -static void dp_catalog_panel_dp_flush(struct dp_catalog_panel *panel, - enum dp_flush_bit flush_bit) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - u32 dp_flush, offset; - - if (!panel) { - pr_err("invalid input\n"); - return; - } - - if (panel->stream_id >= DP_STREAM_MAX) { - pr_err("invalid stream_id:%d\n", panel->stream_id); - return; - } - - catalog = dp_catalog_get_priv(panel); - io_data = catalog->io.dp_link; - - if (panel->stream_id == DP_STREAM_0) - offset = 0; - else - offset = MMSS_DP1_FLUSH - MMSS_DP_FLUSH; - - dp_flush = dp_read(catalog->exe_mode, io_data, MMSS_DP_FLUSH + offset); - dp_flush |= BIT(flush_bit); - dp_write(catalog->exe_mode, io_data, MMSS_DP_FLUSH + offset, dp_flush); -} - -static void dp_catalog_panel_pps_flush(struct dp_catalog_panel *panel) -{ - dp_catalog_panel_dp_flush(panel, DP_PPS_FLUSH); - pr_debug("pps flush for stream:%d\n", panel->stream_id); -} - -static void dp_catalog_panel_dhdr_flush(struct dp_catalog_panel *panel) -{ - dp_catalog_panel_dp_flush(panel, DP_DHDR_FLUSH); - pr_debug("dhdr flush for stream:%d\n", panel->stream_id); -} - - -static bool dp_catalog_panel_dhdr_busy(struct dp_catalog_panel *panel) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - u32 dp_flush, offset; - - if (panel->stream_id >= DP_STREAM_MAX) { - pr_err("invalid stream_id:%d\n", panel->stream_id); - return false; - } - - catalog = dp_catalog_get_priv(panel); - io_data = catalog->io.dp_link; - - if (panel->stream_id == DP_STREAM_0) - offset = 0; - else - offset = MMSS_DP1_FLUSH - MMSS_DP_FLUSH; - - dp_flush = dp_read(catalog->exe_mode, io_data, MMSS_DP_FLUSH + offset); - - return dp_flush & BIT(DP_DHDR_FLUSH) ? true : false; -} - -static void dp_catalog_ctrl_reset(struct dp_catalog_ctrl *ctrl) -{ - u32 sw_reset; - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(ctrl); - io_data = catalog->io.dp_ahb; - - sw_reset = dp_read(catalog->exe_mode, io_data, DP_SW_RESET); - - sw_reset |= BIT(0); - dp_write(catalog->exe_mode, io_data, DP_SW_RESET, sw_reset); - usleep_range(1000, 1010); /* h/w recommended delay */ - - sw_reset &= ~BIT(0); - dp_write(catalog->exe_mode, io_data, DP_SW_RESET, sw_reset); -} - -static bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog_ctrl *ctrl) -{ - u32 data; - int cnt = 10; - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!ctrl) { - pr_err("invalid input\n"); - goto end; - } - - catalog = dp_catalog_get_priv(ctrl); - io_data = catalog->io.dp_link; - - while (--cnt) { - /* DP_MAINLINK_READY */ - data = dp_read(catalog->exe_mode, io_data, DP_MAINLINK_READY); - if (data & BIT(0)) - return true; - - usleep_range(1000, 1010); /* 1ms wait before next reg read */ - } - pr_err("mainlink not ready\n"); -end: - return false; -} - -static void dp_catalog_ctrl_enable_irq(struct dp_catalog_ctrl *ctrl, - bool enable) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(ctrl); - io_data = catalog->io.dp_ahb; - - if (enable) { - dp_write(catalog->exe_mode, io_data, DP_INTR_STATUS, - DP_INTR_MASK1); - dp_write(catalog->exe_mode, io_data, DP_INTR_STATUS2, - DP_INTR_MASK2); - dp_write(catalog->exe_mode, io_data, DP_INTR_STATUS5, - DP_INTR_MASK5); - } else { - dp_write(catalog->exe_mode, io_data, DP_INTR_STATUS, 0x00); - dp_write(catalog->exe_mode, io_data, DP_INTR_STATUS2, 0x00); - dp_write(catalog->exe_mode, io_data, DP_INTR_STATUS5, 0x00); - } -} - -static void dp_catalog_ctrl_get_interrupt(struct dp_catalog_ctrl *ctrl) -{ - u32 ack = 0; - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(ctrl); - io_data = catalog->io.dp_ahb; - - ctrl->isr = dp_read(catalog->exe_mode, io_data, DP_INTR_STATUS2); - ctrl->isr &= ~DP_INTR_MASK2; - ack = ctrl->isr & DP_INTERRUPT_STATUS2; - ack <<= 1; - ack |= DP_INTR_MASK2; - dp_write(catalog->exe_mode, io_data, DP_INTR_STATUS2, ack); - - ctrl->isr5 = dp_read(catalog->exe_mode, io_data, DP_INTR_STATUS5); - ctrl->isr5 &= ~DP_INTR_MASK5; - ack = ctrl->isr5 & DP_INTERRUPT_STATUS5; - ack <<= 1; - ack |= DP_INTR_MASK5; - dp_write(catalog->exe_mode, io_data, DP_INTR_STATUS5, ack); -} - -static void dp_catalog_ctrl_phy_reset(struct dp_catalog_ctrl *ctrl) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(ctrl); - io_data = catalog->io.dp_ahb; - - dp_write(catalog->exe_mode, io_data, DP_PHY_CTRL, 0x5); /* bit 0 & 2 */ - usleep_range(1000, 1010); /* h/w recommended delay */ - dp_write(catalog->exe_mode, io_data, DP_PHY_CTRL, 0x0); - wmb(); /* make sure PHY reset done */ -} - -static void dp_catalog_ctrl_phy_lane_cfg(struct dp_catalog_ctrl *ctrl, - bool flipped, u8 ln_cnt) -{ - u32 info = 0x0; - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - u8 orientation = BIT(!!flipped); - - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(ctrl); - - io_data = catalog->io.dp_phy; - - info |= (ln_cnt & 0x0F); - info |= ((orientation & 0x0F) << 4); - pr_debug("Shared Info = 0x%x\n", info); - - dp_write(catalog->exe_mode, io_data, DP_PHY_SPARE0, info); -} - -static void dp_catalog_ctrl_update_vx_px(struct dp_catalog_ctrl *ctrl, - u8 v_level, u8 p_level) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - u8 value0, value1; - - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(ctrl); - - pr_debug("hw: v=%d p=%d\n", v_level, p_level); - - value0 = vm_voltage_swing[v_level][p_level]; - value1 = vm_pre_emphasis[v_level][p_level]; - - /* program default setting first */ - - io_data = catalog->io.dp_ln_tx0; - dp_write(catalog->exe_mode, io_data, TXn_TX_DRV_LVL, 0x2A); - dp_write(catalog->exe_mode, io_data, TXn_TX_EMP_POST1_LVL, 0x20); - - io_data = catalog->io.dp_ln_tx1; - dp_write(catalog->exe_mode, io_data, TXn_TX_DRV_LVL, 0x2A); - dp_write(catalog->exe_mode, io_data, TXn_TX_EMP_POST1_LVL, 0x20); - - /* Enable MUX to use Cursor values from these registers */ - value0 |= BIT(5); - value1 |= BIT(5); - - /* Configure host and panel only if both values are allowed */ - if (value0 != 0xFF && value1 != 0xFF) { - io_data = catalog->io.dp_ln_tx0; - dp_write(catalog->exe_mode, io_data, TXn_TX_DRV_LVL, value0); - dp_write(catalog->exe_mode, io_data, TXn_TX_EMP_POST1_LVL, - value1); - - io_data = catalog->io.dp_ln_tx1; - dp_write(catalog->exe_mode, io_data, TXn_TX_DRV_LVL, value0); - dp_write(catalog->exe_mode, io_data, TXn_TX_EMP_POST1_LVL, - value1); - - pr_debug("hw: vx_value=0x%x px_value=0x%x\n", - value0, value1); - } else { - pr_err("invalid vx (0x%x=0x%x), px (0x%x=0x%x\n", - v_level, value0, p_level, value1); - } -} - -static void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog_ctrl *ctrl, - u32 pattern) -{ - struct dp_catalog_private *catalog; - u32 value = 0x0; - struct dp_io_data *io_data = NULL; - - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(ctrl); - - io_data = catalog->io.dp_link; - - dp_write(catalog->exe_mode, io_data, DP_STATE_CTRL, 0x0); - - switch (pattern) { - case DP_TEST_PHY_PATTERN_D10_2_NO_SCRAMBLING: - dp_write(catalog->exe_mode, io_data, DP_STATE_CTRL, 0x1); - break; - case DP_TEST_PHY_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT: - value &= ~(1 << 16); - dp_write(catalog->exe_mode, io_data, - DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, value); - value |= 0xFC; - dp_write(catalog->exe_mode, io_data, - DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, value); - dp_write(catalog->exe_mode, io_data, DP_MAINLINK_LEVELS, 0x2); - dp_write(catalog->exe_mode, io_data, DP_STATE_CTRL, 0x10); - break; - case DP_TEST_PHY_PATTERN_PRBS7: - dp_write(catalog->exe_mode, io_data, DP_STATE_CTRL, 0x20); - break; - case DP_TEST_PHY_PATTERN_80_BIT_CUSTOM_PATTERN: - dp_write(catalog->exe_mode, io_data, DP_STATE_CTRL, 0x40); - /* 00111110000011111000001111100000 */ - dp_write(catalog->exe_mode, io_data, - DP_TEST_80BIT_CUSTOM_PATTERN_REG0, 0x3E0F83E0); - /* 00001111100000111110000011111000 */ - dp_write(catalog->exe_mode, io_data, - DP_TEST_80BIT_CUSTOM_PATTERN_REG1, 0x0F83E0F8); - /* 1111100000111110 */ - dp_write(catalog->exe_mode, io_data, - DP_TEST_80BIT_CUSTOM_PATTERN_REG2, 0x0000F83E); - break; - case DP_TEST_PHY_PATTERN_CP2520_PATTERN_1: - value = dp_read(catalog->exe_mode, io_data, DP_MAINLINK_CTRL); - value &= ~BIT(4); - dp_write(catalog->exe_mode, io_data, DP_MAINLINK_CTRL, value); - - value = BIT(16); - dp_write(catalog->exe_mode, io_data, - DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, value); - value |= 0xFC; - dp_write(catalog->exe_mode, io_data, - DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, value); - dp_write(catalog->exe_mode, io_data, DP_MAINLINK_LEVELS, 0x2); - dp_write(catalog->exe_mode, io_data, DP_STATE_CTRL, 0x10); - - value = dp_read(catalog->exe_mode, io_data, DP_MAINLINK_CTRL); - value |= BIT(0); - dp_write(catalog->exe_mode, io_data, DP_MAINLINK_CTRL, value); - break; - case DP_TEST_PHY_PATTERN_CP2520_PATTERN_3: - dp_write(catalog->exe_mode, io_data, DP_MAINLINK_CTRL, 0x11); - dp_write(catalog->exe_mode, io_data, DP_STATE_CTRL, 0x8); - break; - default: - pr_debug("No valid test pattern requested: 0x%x\n", pattern); - return; - } - - /* Make sure the test pattern is programmed in the hardware */ - wmb(); -} - -static u32 dp_catalog_ctrl_read_phy_pattern(struct dp_catalog_ctrl *ctrl) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data = NULL; - - if (!ctrl) { - pr_err("invalid input\n"); - return 0; - } - - catalog = dp_catalog_get_priv(ctrl); - - io_data = catalog->io.dp_link; - - return dp_read(catalog->exe_mode, io_data, DP_MAINLINK_READY); -} - -static void dp_catalog_ctrl_fec_config(struct dp_catalog_ctrl *ctrl, - bool enable) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data = NULL; - u32 reg; - - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(ctrl); - io_data = catalog->io.dp_link; - - reg = dp_read(catalog->exe_mode, io_data, DP_MAINLINK_CTRL); - - /* - * fec_en = BIT(12) - * fec_seq_mode = BIT(22) - * sde_flush = BIT(23) | BIT(24) - * fb_boundary_sel = BIT(25) - */ - if (enable) - reg |= BIT(12) | BIT(22) | BIT(23) | BIT(24) | BIT(25); - else - reg &= ~BIT(12); - - dp_write(catalog->exe_mode, io_data, DP_MAINLINK_CTRL, reg); - /* make sure mainlink configuration is updated with fec sequence */ - wmb(); -} - -static int dp_catalog_reg_dump(struct dp_catalog *dp_catalog, - char *name, u8 **out_buf, u32 *out_buf_len) -{ - int ret = 0; - u8 *buf; - u32 len; - struct dp_io_data *io_data; - struct dp_catalog_private *catalog; - struct dp_parser *parser; - - if (!dp_catalog) { - pr_err("invalid input\n"); - return -EINVAL; - } - - catalog = container_of(dp_catalog, struct dp_catalog_private, - dp_catalog); - - parser = catalog->parser; - parser->get_io_buf(parser, name); - io_data = parser->get_io(parser, name); - if (!io_data) { - pr_err("IO %s not found\n", name); - ret = -EINVAL; - goto end; - } - - buf = io_data->buf; - len = io_data->io.len; - - if (!buf || !len) { - pr_err("no buffer available\n"); - ret = -ENOMEM; - goto end; - } - - if (!strcmp(catalog->exe_mode, "hw") || - !strcmp(catalog->exe_mode, "all")) { - u32 i, data; - u32 const rowsize = 4; - void __iomem *addr = io_data->io.base; - - memset(buf, 0, len); - - for (i = 0; i < len / rowsize; i++) { - data = readl_relaxed(addr); - memcpy(buf + (rowsize * i), &data, sizeof(u32)); - - addr += rowsize; - } - } - - *out_buf = buf; - *out_buf_len = len; -end: - if (ret) - parser->clear_io_buf(parser); - - return ret; -} - -static void dp_catalog_ctrl_mst_config(struct dp_catalog_ctrl *ctrl, - bool enable) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data = NULL; - u32 reg; - - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(ctrl); - - io_data = catalog->io.dp_link; - - reg = dp_read(catalog->exe_mode, io_data, DP_MAINLINK_CTRL); - if (enable) - reg |= (0x04000100); - else - reg &= ~(0x04000100); - - dp_write(catalog->exe_mode, io_data, DP_MAINLINK_CTRL, reg); - /* make sure mainlink MST configuration is updated */ - wmb(); -} - -static void dp_catalog_ctrl_trigger_act(struct dp_catalog_ctrl *ctrl) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data = NULL; - - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(ctrl); - - io_data = catalog->io.dp_link; - - dp_write(catalog->exe_mode, io_data, DP_MST_ACT, 0x1); - /* make sure ACT signal is performed */ - wmb(); -} - -static void dp_catalog_ctrl_read_act_complete_sts(struct dp_catalog_ctrl *ctrl, - bool *sts) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data = NULL; - u32 reg; - - if (!ctrl || !sts) { - pr_err("invalid input\n"); - return; - } - - *sts = false; - - catalog = dp_catalog_get_priv(ctrl); - - io_data = catalog->io.dp_link; - - reg = dp_read(catalog->exe_mode, io_data, DP_MST_ACT); - - if (!reg) - *sts = true; -} - -static void dp_catalog_ctrl_channel_alloc(struct dp_catalog_ctrl *ctrl, - u32 ch, u32 ch_start_slot, u32 tot_slot_cnt) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data = NULL; - u32 i, slot_reg_1, slot_reg_2, slot; - u32 reg_off = 0; - int const num_slots_per_reg = 32; - - if (!ctrl || ch >= DP_STREAM_MAX) { - pr_err("invalid input. ch %d\n", ch); - return; - } - - if (ch_start_slot > DP_MAX_TIME_SLOTS || - (ch_start_slot + tot_slot_cnt > DP_MAX_TIME_SLOTS)) { - pr_err("invalid slots start %d, tot %d\n", - ch_start_slot, tot_slot_cnt); - return; - } - - catalog = dp_catalog_get_priv(ctrl); - - io_data = catalog->io.dp_link; - - pr_debug("ch %d, start_slot %d, tot_slot %d\n", - ch, ch_start_slot, tot_slot_cnt); - - if (ch == DP_STREAM_1) - reg_off = DP_DP1_TIMESLOT_1_32 - DP_DP0_TIMESLOT_1_32; - - slot_reg_1 = 0; - slot_reg_2 = 0; - - if (ch_start_slot && tot_slot_cnt) { - ch_start_slot--; - for (i = 0; i < tot_slot_cnt; i++) { - if (ch_start_slot < num_slots_per_reg) { - slot_reg_1 |= BIT(ch_start_slot); - } else { - slot = ch_start_slot - num_slots_per_reg; - slot_reg_2 |= BIT(slot); - } - ch_start_slot++; - } - } - - pr_debug("ch:%d slot_reg_1:%d, slot_reg_2:%d\n", ch, - slot_reg_1, slot_reg_2); - - dp_write(catalog->exe_mode, io_data, DP_DP0_TIMESLOT_1_32 + reg_off, - slot_reg_1); - dp_write(catalog->exe_mode, io_data, DP_DP0_TIMESLOT_33_63 + reg_off, - slot_reg_2); -} - -static void dp_catalog_ctrl_channel_dealloc(struct dp_catalog_ctrl *ctrl, - u32 ch, u32 ch_start_slot, u32 tot_slot_cnt) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data = NULL; - u32 i, slot_reg_1, slot_reg_2, slot; - u32 reg_off = 0; - - if (!ctrl || ch >= DP_STREAM_MAX) { - pr_err("invalid input. ch %d\n", ch); - return; - } - - if (ch_start_slot > DP_MAX_TIME_SLOTS || - (ch_start_slot + tot_slot_cnt > DP_MAX_TIME_SLOTS)) { - pr_err("invalid slots start %d, tot %d\n", - ch_start_slot, tot_slot_cnt); - return; - } - - catalog = dp_catalog_get_priv(ctrl); - - io_data = catalog->io.dp_link; - - pr_debug("dealloc ch %d, start_slot %d, tot_slot %d\n", - ch, ch_start_slot, tot_slot_cnt); - - if (ch == DP_STREAM_1) - reg_off = DP_DP1_TIMESLOT_1_32 - DP_DP0_TIMESLOT_1_32; - - slot_reg_1 = dp_read(catalog->exe_mode, io_data, - DP_DP0_TIMESLOT_1_32 + reg_off); - slot_reg_2 = dp_read(catalog->exe_mode, io_data, - DP_DP0_TIMESLOT_33_63 + reg_off); - - ch_start_slot = ch_start_slot - 1; - for (i = 0; i < tot_slot_cnt; i++) { - if (ch_start_slot < 33) { - slot_reg_1 &= ~BIT(ch_start_slot); - } else { - slot = ch_start_slot - 33; - slot_reg_2 &= ~BIT(slot); - } - ch_start_slot++; - } - - pr_debug("dealloc ch:%d slot_reg_1:%d, slot_reg_2:%d\n", ch, - slot_reg_1, slot_reg_2); - - dp_write(catalog->exe_mode, io_data, DP_DP0_TIMESLOT_1_32 + reg_off, - slot_reg_1); - dp_write(catalog->exe_mode, io_data, DP_DP0_TIMESLOT_33_63 + reg_off, - slot_reg_2); -} - -static void dp_catalog_ctrl_update_rg(struct dp_catalog_ctrl *ctrl, u32 ch, - u32 x_int, u32 y_frac_enum) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data = NULL; - u32 rg, reg_off = 0; - - if (!ctrl || ch >= DP_STREAM_MAX) { - pr_err("invalid input. ch %d\n", ch); - return; - } - - catalog = dp_catalog_get_priv(ctrl); - - io_data = catalog->io.dp_link; - - rg = y_frac_enum; - rg |= (x_int << 16); - - pr_debug("ch: %d x_int:%d y_frac_enum:%d rg:%d\n", ch, x_int, - y_frac_enum, rg); - - if (ch == DP_STREAM_1) - reg_off = DP_DP1_RG - DP_DP0_RG; - - dp_write(catalog->exe_mode, io_data, DP_DP0_RG + reg_off, rg); -} - -static void dp_catalog_ctrl_mainlink_levels(struct dp_catalog_ctrl *ctrl, - u8 lane_cnt) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - u32 mainlink_levels, safe_to_exit_level = 14; - - catalog = dp_catalog_get_priv(ctrl); - - io_data = catalog->io.dp_link; - - switch (lane_cnt) { - case 1: - safe_to_exit_level = 14; - break; - case 2: - safe_to_exit_level = 8; - break; - case 4: - safe_to_exit_level = 5; - break; - default: - pr_debug("setting the default safe_to_exit_level = %u\n", - safe_to_exit_level); - break; - } - - mainlink_levels = dp_read(catalog->exe_mode, io_data, - DP_MAINLINK_LEVELS); - mainlink_levels &= 0xFE0; - mainlink_levels |= safe_to_exit_level; - - pr_debug("mainlink_level = 0x%x, safe_to_exit_level = 0x%x\n", - mainlink_levels, safe_to_exit_level); - - dp_write(catalog->exe_mode, io_data, DP_MAINLINK_LEVELS, - mainlink_levels); -} - - -/* panel related catalog functions */ -static int dp_catalog_panel_timing_cfg(struct dp_catalog_panel *panel) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - u32 offset = 0, reg; - - if (!panel) { - pr_err("invalid input\n"); - goto end; - } - - if (panel->stream_id >= DP_STREAM_MAX) { - pr_err("invalid stream_id:%d\n", panel->stream_id); - goto end; - } - - catalog = dp_catalog_get_priv(panel); - io_data = catalog->io.dp_link; - - if (panel->stream_id == DP_STREAM_1) - offset = DP1_TOTAL_HOR_VER - DP_TOTAL_HOR_VER; - - dp_write(catalog->exe_mode, io_data, DP_TOTAL_HOR_VER + offset, - panel->total); - dp_write(catalog->exe_mode, io_data, - DP_START_HOR_VER_FROM_SYNC + offset, panel->sync_start); - dp_write(catalog->exe_mode, io_data, - DP_HSYNC_VSYNC_WIDTH_POLARITY + offset, panel->width_blanking); - dp_write(catalog->exe_mode, io_data, DP_ACTIVE_HOR_VER + offset, - panel->dp_active); - - if (panel->stream_id == DP_STREAM_0) - io_data = catalog->io.dp_p0; - else - io_data = catalog->io.dp_p1; - - reg = dp_read(catalog->exe_mode, io_data, MMSS_DP_INTF_CONFIG); - - if (panel->widebus_en) - reg |= BIT(4); - else - reg &= ~BIT(4); - - dp_write(catalog->exe_mode, io_data, MMSS_DP_INTF_CONFIG, reg); -end: - return 0; -} - -static void dp_catalog_hpd_config_hpd(struct dp_catalog_hpd *hpd, bool en) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!hpd) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv(hpd); - io_data = catalog->io.dp_aux; - - if (en) { - u32 reftimer = dp_read(catalog->exe_mode, io_data, - DP_DP_HPD_REFTIMER); - - /* Arm only the UNPLUG and HPD_IRQ interrupts */ - dp_write(catalog->exe_mode, io_data, DP_DP_HPD_INT_ACK, 0xF); - dp_write(catalog->exe_mode, io_data, DP_DP_HPD_INT_MASK, 0xA); - - /* Enable REFTIMER to count 1ms */ - reftimer |= BIT(16); - dp_write(catalog->exe_mode, io_data, DP_DP_HPD_REFTIMER, - reftimer); - - /* Connect_time is 250us & disconnect_time is 2ms */ - dp_write(catalog->exe_mode, io_data, DP_DP_HPD_EVENT_TIME_0, - 0x3E800FA); - dp_write(catalog->exe_mode, io_data, DP_DP_HPD_EVENT_TIME_1, - 0x1F407D0); - - /* Enable HPD */ - dp_write(catalog->exe_mode, io_data, DP_DP_HPD_CTRL, 0x1); - - } else { - /* Disable HPD */ - dp_write(catalog->exe_mode, io_data, DP_DP_HPD_CTRL, 0x0); - } -} - -static u32 dp_catalog_hpd_get_interrupt(struct dp_catalog_hpd *hpd) -{ - u32 isr = 0; - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - - if (!hpd) { - pr_err("invalid input\n"); - return isr; - } - - catalog = dp_catalog_get_priv(hpd); - - io_data = catalog->io.dp_aux; - isr = dp_read(catalog->exe_mode, io_data, DP_DP_HPD_INT_STATUS); - dp_write(catalog->exe_mode, io_data, DP_DP_HPD_INT_ACK, (isr & 0xf)); - - return isr; -} - -static void dp_catalog_audio_init(struct dp_catalog_audio *audio) -{ - struct dp_catalog_private *catalog; - static u32 sdp_map[][DP_AUDIO_SDP_HEADER_MAX] = { - { - MMSS_DP_AUDIO_STREAM_0, - MMSS_DP_AUDIO_STREAM_1, - MMSS_DP_AUDIO_STREAM_1, - }, - { - MMSS_DP_AUDIO_TIMESTAMP_0, - MMSS_DP_AUDIO_TIMESTAMP_1, - MMSS_DP_AUDIO_TIMESTAMP_1, - }, - { - MMSS_DP_AUDIO_INFOFRAME_0, - MMSS_DP_AUDIO_INFOFRAME_1, - MMSS_DP_AUDIO_INFOFRAME_1, - }, - { - MMSS_DP_AUDIO_COPYMANAGEMENT_0, - MMSS_DP_AUDIO_COPYMANAGEMENT_1, - MMSS_DP_AUDIO_COPYMANAGEMENT_1, - }, - { - MMSS_DP_AUDIO_ISRC_0, - MMSS_DP_AUDIO_ISRC_1, - MMSS_DP_AUDIO_ISRC_1, - }, - }; - - if (!audio) - return; - - catalog = dp_catalog_get_priv(audio); - - catalog->audio_map = sdp_map; -} - -static void dp_catalog_audio_config_sdp(struct dp_catalog_audio *audio) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - u32 sdp_cfg = 0, sdp_cfg_off = 0; - u32 sdp_cfg2 = 0, sdp_cfg2_off = 0; - - if (!audio) - return; - - if (audio->stream_id >= DP_STREAM_MAX) { - pr_err("invalid stream id:%d\n", audio->stream_id); - return; - } - - if (audio->stream_id == DP_STREAM_1) { - sdp_cfg_off = MMSS_DP1_SDP_CFG - MMSS_DP_SDP_CFG; - sdp_cfg2_off = MMSS_DP1_SDP_CFG2 - MMSS_DP_SDP_CFG2; - } - - catalog = dp_catalog_get_priv(audio); - io_data = catalog->io.dp_link; - - sdp_cfg = dp_read(catalog->exe_mode, io_data, - MMSS_DP_SDP_CFG + sdp_cfg_off); - - /* AUDIO_TIMESTAMP_SDP_EN */ - sdp_cfg |= BIT(1); - /* AUDIO_STREAM_SDP_EN */ - sdp_cfg |= BIT(2); - /* AUDIO_COPY_MANAGEMENT_SDP_EN */ - sdp_cfg |= BIT(5); - /* AUDIO_ISRC_SDP_EN */ - sdp_cfg |= BIT(6); - /* AUDIO_INFOFRAME_SDP_EN */ - sdp_cfg |= BIT(20); - - pr_debug("sdp_cfg = 0x%x\n", sdp_cfg); - dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG + sdp_cfg_off, - sdp_cfg); - - sdp_cfg2 = dp_read(catalog->exe_mode, io_data, - MMSS_DP_SDP_CFG2 + sdp_cfg_off); - /* IFRM_REGSRC -> Do not use reg values */ - sdp_cfg2 &= ~BIT(0); - /* AUDIO_STREAM_HB3_REGSRC-> Do not use reg values */ - sdp_cfg2 &= ~BIT(1); - - pr_debug("sdp_cfg2 = 0x%x\n", sdp_cfg2); - dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG2 + sdp_cfg_off, - sdp_cfg2); -} - -static void dp_catalog_audio_get_header(struct dp_catalog_audio *audio) -{ - struct dp_catalog_private *catalog; - u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX]; - struct dp_io_data *io_data; - enum dp_catalog_audio_sdp_type sdp; - enum dp_catalog_audio_header_type header; - - if (!audio) - return; - - catalog = dp_catalog_get_priv(audio); - - io_data = catalog->io.dp_link; - sdp_map = catalog->audio_map; - sdp = audio->sdp_type; - header = audio->sdp_header; - - audio->data = dp_read(catalog->exe_mode, io_data, sdp_map[sdp][header]); -} - -static void dp_catalog_audio_set_header(struct dp_catalog_audio *audio) -{ - struct dp_catalog_private *catalog; - u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX]; - struct dp_io_data *io_data; - enum dp_catalog_audio_sdp_type sdp; - enum dp_catalog_audio_header_type header; - u32 data; - - if (!audio) - return; - - catalog = dp_catalog_get_priv(audio); - - io_data = catalog->io.dp_link; - sdp_map = catalog->audio_map; - sdp = audio->sdp_type; - header = audio->sdp_header; - data = audio->data; - - dp_write(catalog->exe_mode, io_data, sdp_map[sdp][header], data); -} - -static void dp_catalog_audio_config_acr(struct dp_catalog_audio *audio) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - u32 acr_ctrl, select; - - catalog = dp_catalog_get_priv(audio); - - select = audio->data; - io_data = catalog->io.dp_link; - - acr_ctrl = select << 4 | BIT(31) | BIT(8) | BIT(14); - - pr_debug("select = 0x%x, acr_ctrl = 0x%x\n", select, acr_ctrl); - - dp_write(catalog->exe_mode, io_data, MMSS_DP_AUDIO_ACR_CTRL, acr_ctrl); -} - -static void dp_catalog_audio_enable(struct dp_catalog_audio *audio) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - bool enable; - u32 audio_ctrl; - - catalog = dp_catalog_get_priv(audio); - - io_data = catalog->io.dp_link; - enable = !!audio->data; - - audio_ctrl = dp_read(catalog->exe_mode, io_data, MMSS_DP_AUDIO_CFG); - - if (enable) - audio_ctrl |= BIT(0); - else - audio_ctrl &= ~BIT(0); - - pr_debug("dp_audio_cfg = 0x%x\n", audio_ctrl); - dp_write(catalog->exe_mode, io_data, MMSS_DP_AUDIO_CFG, audio_ctrl); - - /* make sure audio engine is disabled */ - wmb(); -} - -static void dp_catalog_config_spd_header(struct dp_catalog_panel *panel) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - u32 value, new_value, offset = 0; - u8 parity_byte; - - if (!panel || panel->stream_id >= DP_STREAM_MAX) - return; - - catalog = dp_catalog_get_priv(panel); - io_data = catalog->io.dp_link; - - if (panel->stream_id == DP_STREAM_1) - offset = MMSS_DP1_GENERIC0_0 - MMSS_DP_GENERIC0_0; - - /* Config header and parity byte 1 */ - value = dp_read(catalog->exe_mode, io_data, - MMSS_DP_GENERIC1_0 + offset); - - new_value = 0x83; - parity_byte = dp_header_get_parity(new_value); - value |= ((new_value << HEADER_BYTE_1_BIT) - | (parity_byte << PARITY_BYTE_1_BIT)); - pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC1_0 + offset, - value); - - /* Config header and parity byte 2 */ - value = dp_read(catalog->exe_mode, io_data, - MMSS_DP_GENERIC1_1 + offset); - - new_value = 0x1b; - parity_byte = dp_header_get_parity(new_value); - value |= ((new_value << HEADER_BYTE_2_BIT) - | (parity_byte << PARITY_BYTE_2_BIT)); - pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", - value, parity_byte); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC1_1 + offset, - value); - - /* Config header and parity byte 3 */ - value = dp_read(catalog->exe_mode, io_data, - MMSS_DP_GENERIC1_1 + offset); - - new_value = (0x0 | (0x12 << 2)); - parity_byte = dp_header_get_parity(new_value); - value |= ((new_value << HEADER_BYTE_3_BIT) - | (parity_byte << PARITY_BYTE_3_BIT)); - pr_debug("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n", - new_value, parity_byte); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC1_1 + offset, - value); -} - -static void dp_catalog_panel_config_spd(struct dp_catalog_panel *panel) -{ - struct dp_catalog_private *catalog; - struct dp_io_data *io_data; - u32 spd_cfg = 0, spd_cfg2 = 0; - u8 *vendor = NULL, *product = NULL; - u32 offset = 0; - u32 sdp_cfg_off = 0; - u32 sdp_cfg2_off = 0; - u32 sdp_cfg3_off = 0; - - /* - * Source Device Information - * 00h unknown - * 01h Digital STB - * 02h DVD - * 03h D-VHS - * 04h HDD Video - * 05h DVC - * 06h DSC - * 07h Video CD - * 08h Game - * 09h PC general - * 0ah Bluray-Disc - * 0bh Super Audio CD - * 0ch HD DVD - * 0dh PMP - * 0eh-ffh reserved - */ - u32 device_type = 0; - - if (!panel || panel->stream_id >= DP_STREAM_MAX) - return; - - catalog = dp_catalog_get_priv(panel); - io_data = catalog->io.dp_link; - - if (panel->stream_id == DP_STREAM_1) - offset = MMSS_DP1_GENERIC0_0 - MMSS_DP_GENERIC0_0; - - dp_catalog_config_spd_header(panel); - - vendor = panel->spd_vendor_name; - product = panel->spd_product_description; - - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC1_2 + offset, - ((vendor[0] & 0x7f) | - ((vendor[1] & 0x7f) << 8) | - ((vendor[2] & 0x7f) << 16) | - ((vendor[3] & 0x7f) << 24))); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC1_3 + offset, - ((vendor[4] & 0x7f) | - ((vendor[5] & 0x7f) << 8) | - ((vendor[6] & 0x7f) << 16) | - ((vendor[7] & 0x7f) << 24))); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC1_4 + offset, - ((product[0] & 0x7f) | - ((product[1] & 0x7f) << 8) | - ((product[2] & 0x7f) << 16) | - ((product[3] & 0x7f) << 24))); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC1_5 + offset, - ((product[4] & 0x7f) | - ((product[5] & 0x7f) << 8) | - ((product[6] & 0x7f) << 16) | - ((product[7] & 0x7f) << 24))); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC1_6 + offset, - ((product[8] & 0x7f) | - ((product[9] & 0x7f) << 8) | - ((product[10] & 0x7f) << 16) | - ((product[11] & 0x7f) << 24))); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC1_7 + offset, - ((product[12] & 0x7f) | - ((product[13] & 0x7f) << 8) | - ((product[14] & 0x7f) << 16) | - ((product[15] & 0x7f) << 24))); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC1_8 + offset, - device_type); - dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC1_9 + offset, 0x00); - - if (panel->stream_id == DP_STREAM_1) { - sdp_cfg_off = MMSS_DP1_SDP_CFG - MMSS_DP_SDP_CFG; - sdp_cfg2_off = MMSS_DP1_SDP_CFG2 - MMSS_DP_SDP_CFG2; - sdp_cfg3_off = MMSS_DP1_SDP_CFG3 - MMSS_DP_SDP_CFG3; - } - - spd_cfg = dp_read(catalog->exe_mode, io_data, - MMSS_DP_SDP_CFG + sdp_cfg_off); - /* GENERIC1_SDP for SPD Infoframe */ - spd_cfg |= BIT(18); - dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG + sdp_cfg_off, - spd_cfg); - - spd_cfg2 = dp_read(catalog->exe_mode, io_data, - MMSS_DP_SDP_CFG2 + sdp_cfg2_off); - /* 28 data bytes for SPD Infoframe with GENERIC1 set */ - spd_cfg2 |= BIT(17); - dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG2 + sdp_cfg2_off, - spd_cfg2); - - dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off, - 0x1); - dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off, - 0x0); -} - -static void dp_catalog_get_io_buf(struct dp_catalog_private *catalog) -{ - struct dp_parser *parser = catalog->parser; - - dp_catalog_fill_io_buf(dp_ahb); - dp_catalog_fill_io_buf(dp_aux); - dp_catalog_fill_io_buf(dp_link); - dp_catalog_fill_io_buf(dp_p0); - dp_catalog_fill_io_buf(dp_phy); - dp_catalog_fill_io_buf(dp_ln_tx0); - dp_catalog_fill_io_buf(dp_ln_tx1); - dp_catalog_fill_io_buf(dp_pll); - dp_catalog_fill_io_buf(usb3_dp_com); - dp_catalog_fill_io_buf(dp_mmss_cc); - dp_catalog_fill_io_buf(hdcp_physical); - dp_catalog_fill_io_buf(dp_p1); - dp_catalog_fill_io_buf(dp_tcsr); -} - -static void dp_catalog_get_io(struct dp_catalog_private *catalog) -{ - struct dp_parser *parser = catalog->parser; - - dp_catalog_fill_io(dp_ahb); - dp_catalog_fill_io(dp_aux); - dp_catalog_fill_io(dp_link); - dp_catalog_fill_io(dp_p0); - dp_catalog_fill_io(dp_phy); - dp_catalog_fill_io(dp_ln_tx0); - dp_catalog_fill_io(dp_ln_tx1); - dp_catalog_fill_io(dp_pll); - dp_catalog_fill_io(usb3_dp_com); - dp_catalog_fill_io(dp_mmss_cc); - dp_catalog_fill_io(hdcp_physical); - dp_catalog_fill_io(dp_p1); - dp_catalog_fill_io(dp_tcsr); -} - -static void dp_catalog_set_exe_mode(struct dp_catalog *dp_catalog, char *mode) -{ - struct dp_catalog_private *catalog; - - if (!dp_catalog) { - pr_err("invalid input\n"); - return; - } - - catalog = container_of(dp_catalog, struct dp_catalog_private, - dp_catalog); - - strlcpy(catalog->exe_mode, mode, sizeof(catalog->exe_mode)); - - if (!strcmp(catalog->exe_mode, "hw")) - catalog->parser->clear_io_buf(catalog->parser); - else - dp_catalog_get_io_buf(catalog); - - if (dp_catalog->priv.data && dp_catalog->priv.put) - dp_catalog->priv.set_exe_mode(dp_catalog, mode); -} - -static int dp_catalog_init(struct device *dev, struct dp_catalog *catalog, - struct dp_parser *parser) -{ - int rc = 0; - struct dp_catalog_private *catalog_priv; - - catalog_priv = container_of(catalog, struct dp_catalog_private, - dp_catalog); - - if (parser->hw_cfg.phy_version == DP_PHY_VERSION_4_2_0) - rc = dp_catalog_get_v420(dev, catalog, &catalog_priv->io); - else if (parser->hw_cfg.phy_version == DP_PHY_VERSION_2_0_0) - rc = dp_catalog_get_v200(dev, catalog, &catalog_priv->io); - - return rc; -} - -void dp_catalog_put(struct dp_catalog *dp_catalog) -{ - struct dp_catalog_private *catalog; - - if (!dp_catalog) - return; - - catalog = container_of(dp_catalog, struct dp_catalog_private, - dp_catalog); - - if (dp_catalog->priv.data && dp_catalog->priv.put) - dp_catalog->priv.put(dp_catalog); - - catalog->parser->clear_io_buf(catalog->parser); - devm_kfree(catalog->dev, catalog); -} - -struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser) -{ - int rc = 0; - struct dp_catalog *dp_catalog; - struct dp_catalog_private *catalog; - struct dp_catalog_aux aux = { - .read_data = dp_catalog_aux_read_data, - .write_data = dp_catalog_aux_write_data, - .write_trans = dp_catalog_aux_write_trans, - .clear_trans = dp_catalog_aux_clear_trans, - .reset = dp_catalog_aux_reset, - .update_aux_cfg = dp_catalog_aux_update_cfg, - .enable = dp_catalog_aux_enable, - .setup = dp_catalog_aux_setup, - .get_irq = dp_catalog_aux_get_irq, - .clear_hw_interrupts = dp_catalog_aux_clear_hw_interrupts, - }; - struct dp_catalog_ctrl ctrl = { - .state_ctrl = dp_catalog_ctrl_state_ctrl, - .config_ctrl = dp_catalog_ctrl_config_ctrl, - .lane_mapping = dp_catalog_ctrl_lane_mapping, - .lane_pnswap = dp_catalog_ctrl_lane_pnswap, - .mainlink_ctrl = dp_catalog_ctrl_mainlink_ctrl, - .set_pattern = dp_catalog_ctrl_set_pattern, - .reset = dp_catalog_ctrl_reset, - .usb_reset = dp_catalog_ctrl_usb_reset, - .mainlink_ready = dp_catalog_ctrl_mainlink_ready, - .enable_irq = dp_catalog_ctrl_enable_irq, - .phy_reset = dp_catalog_ctrl_phy_reset, - .phy_lane_cfg = dp_catalog_ctrl_phy_lane_cfg, - .update_vx_px = dp_catalog_ctrl_update_vx_px, - .get_interrupt = dp_catalog_ctrl_get_interrupt, - .read_hdcp_status = dp_catalog_ctrl_read_hdcp_status, - .send_phy_pattern = dp_catalog_ctrl_send_phy_pattern, - .read_phy_pattern = dp_catalog_ctrl_read_phy_pattern, - .mst_config = dp_catalog_ctrl_mst_config, - .trigger_act = dp_catalog_ctrl_trigger_act, - .read_act_complete_sts = dp_catalog_ctrl_read_act_complete_sts, - .channel_alloc = dp_catalog_ctrl_channel_alloc, - .update_rg = dp_catalog_ctrl_update_rg, - .channel_dealloc = dp_catalog_ctrl_channel_dealloc, - .fec_config = dp_catalog_ctrl_fec_config, - .mainlink_levels = dp_catalog_ctrl_mainlink_levels, - }; - struct dp_catalog_hpd hpd = { - .config_hpd = dp_catalog_hpd_config_hpd, - .get_interrupt = dp_catalog_hpd_get_interrupt, - }; - struct dp_catalog_audio audio = { - .init = dp_catalog_audio_init, - .config_acr = dp_catalog_audio_config_acr, - .enable = dp_catalog_audio_enable, - .config_sdp = dp_catalog_audio_config_sdp, - .set_header = dp_catalog_audio_set_header, - .get_header = dp_catalog_audio_get_header, - }; - struct dp_catalog_panel panel = { - .timing_cfg = dp_catalog_panel_timing_cfg, - .config_hdr = dp_catalog_panel_config_hdr, - .tpg_config = dp_catalog_panel_tpg_cfg, - .config_spd = dp_catalog_panel_config_spd, - .config_misc = dp_catalog_panel_config_misc, - .config_msa = dp_catalog_panel_config_msa, - .update_transfer_unit = dp_catalog_panel_update_transfer_unit, - .config_ctrl = dp_catalog_panel_config_ctrl, - .config_dto = dp_catalog_panel_config_dto, - .dsc_cfg = dp_catalog_panel_dsc_cfg, - .pps_flush = dp_catalog_panel_pps_flush, - .dhdr_flush = dp_catalog_panel_dhdr_flush, - .dhdr_busy = dp_catalog_panel_dhdr_busy, - }; - - if (!dev || !parser) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto error; - } - - catalog = devm_kzalloc(dev, sizeof(*catalog), GFP_KERNEL); - if (!catalog) { - rc = -ENOMEM; - goto error; - } - - catalog->dev = dev; - catalog->parser = parser; - - dp_catalog_get_io(catalog); - - strlcpy(catalog->exe_mode, "hw", sizeof(catalog->exe_mode)); - - dp_catalog = &catalog->dp_catalog; - - dp_catalog->aux = aux; - dp_catalog->ctrl = ctrl; - dp_catalog->hpd = hpd; - dp_catalog->audio = audio; - dp_catalog->panel = panel; - - rc = dp_catalog_init(dev, dp_catalog, parser); - if (rc) { - dp_catalog_put(dp_catalog); - goto error; - } - - dp_catalog->set_exe_mode = dp_catalog_set_exe_mode; - dp_catalog->get_reg_dump = dp_catalog_reg_dump; - - return dp_catalog; -error: - return ERR_PTR(rc); -} diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h deleted file mode 100644 index 4c6b959db121cdfe15490ec91ef716d1b6e04b99..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_catalog.h +++ /dev/null @@ -1,372 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. -<<<<<<< HEAD -======= - * - * 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. - * ->>>>>>> aacf58a... drm/msm/dp: Add P/N swap support for dp phy - */ - -#ifndef _DP_CATALOG_H_ -#define _DP_CATALOG_H_ - -#include - -#include "dp_parser.h" - -/* interrupts */ -#define DP_INTR_HPD BIT(0) -#define DP_INTR_AUX_I2C_DONE BIT(3) -#define DP_INTR_WRONG_ADDR BIT(6) -#define DP_INTR_TIMEOUT BIT(9) -#define DP_INTR_NACK_DEFER BIT(12) -#define DP_INTR_WRONG_DATA_CNT BIT(15) -#define DP_INTR_I2C_NACK BIT(18) -#define DP_INTR_I2C_DEFER BIT(21) -#define DP_INTR_PLL_UNLOCKED BIT(24) -#define DP_INTR_AUX_ERROR BIT(27) - -#define DP_INTR_READY_FOR_VIDEO BIT(0) -#define DP_INTR_IDLE_PATTERN_SENT BIT(3) -#define DP_INTR_FRAME_END BIT(6) -#define DP_INTR_CRC_UPDATED BIT(9) - -#define DP_INTR_MST_DP0_VCPF_SENT BIT(0) -#define DP_INTR_MST_DP1_VCPF_SENT BIT(3) - -#define DP_MAX_TIME_SLOTS 64 - -/* stream id */ -enum dp_stream_id { - DP_STREAM_0, - DP_STREAM_1, - DP_STREAM_MAX, -}; - -struct dp_catalog_hdr_data { - u32 vsc_header_byte0; - u32 vsc_header_byte1; - u32 vsc_header_byte2; - u32 vsc_header_byte3; - - u32 vscext_header_byte0; - u32 vscext_header_byte1; - u32 vscext_header_byte2; - u32 vscext_header_byte3; - - u32 shdr_header_byte0; - u32 shdr_header_byte1; - u32 shdr_header_byte2; - u32 shdr_header_byte3; - - u32 bpc; - - u32 version; - u32 length; - u32 pixel_encoding; - u32 colorimetry; - u32 dynamic_range; - u32 content_type; - - struct drm_msm_ext_hdr_metadata hdr_meta; -}; - -struct dp_catalog_aux { - u32 data; - u32 isr; - - u32 (*read_data)(struct dp_catalog_aux *aux); - int (*write_data)(struct dp_catalog_aux *aux); - int (*write_trans)(struct dp_catalog_aux *aux); - int (*clear_trans)(struct dp_catalog_aux *aux, bool read); - void (*reset)(struct dp_catalog_aux *aux); - void (*enable)(struct dp_catalog_aux *aux, bool enable); - void (*update_aux_cfg)(struct dp_catalog_aux *aux, - struct dp_aux_cfg *cfg, enum dp_phy_aux_config_type type); - void (*setup)(struct dp_catalog_aux *aux, - struct dp_aux_cfg *aux_cfg); - void (*get_irq)(struct dp_catalog_aux *aux, bool cmd_busy); - void (*clear_hw_interrupts)(struct dp_catalog_aux *aux); -}; - -struct dp_catalog_ctrl { - u32 isr; - u32 isr5; - - void (*state_ctrl)(struct dp_catalog_ctrl *ctrl, u32 state); - void (*config_ctrl)(struct dp_catalog_ctrl *ctrl, u8 ln_cnt); - void (*lane_mapping)(struct dp_catalog_ctrl *ctrl, bool flipped, - char *lane_map); - void (*lane_pnswap)(struct dp_catalog_ctrl *ctrl, u8 ln_pnswap); - void (*mainlink_ctrl)(struct dp_catalog_ctrl *ctrl, bool enable); - void (*set_pattern)(struct dp_catalog_ctrl *ctrl, u32 pattern); - void (*reset)(struct dp_catalog_ctrl *ctrl); - void (*usb_reset)(struct dp_catalog_ctrl *ctrl, bool flip); - bool (*mainlink_ready)(struct dp_catalog_ctrl *ctrl); - void (*enable_irq)(struct dp_catalog_ctrl *ctrl, bool enable); - void (*phy_reset)(struct dp_catalog_ctrl *ctrl); - void (*phy_lane_cfg)(struct dp_catalog_ctrl *ctrl, bool flipped, - u8 lane_cnt); - void (*update_vx_px)(struct dp_catalog_ctrl *ctrl, u8 v_level, - u8 p_level); - void (*get_interrupt)(struct dp_catalog_ctrl *ctrl); - u32 (*read_hdcp_status)(struct dp_catalog_ctrl *ctrl); - void (*send_phy_pattern)(struct dp_catalog_ctrl *ctrl, - u32 pattern); - u32 (*read_phy_pattern)(struct dp_catalog_ctrl *ctrl); - void (*mst_config)(struct dp_catalog_ctrl *ctrl, bool enable); - void (*trigger_act)(struct dp_catalog_ctrl *ctrl); - void (*read_act_complete_sts)(struct dp_catalog_ctrl *ctrl, bool *sts); - void (*channel_alloc)(struct dp_catalog_ctrl *ctrl, - u32 ch, u32 ch_start_timeslot, u32 tot_ch_cnt); - void (*update_rg)(struct dp_catalog_ctrl *ctrl, u32 ch, u32 x_int, - u32 y_frac_enum); - void (*channel_dealloc)(struct dp_catalog_ctrl *ctrl, - u32 ch, u32 ch_start_timeslot, u32 tot_ch_cnt); - void (*fec_config)(struct dp_catalog_ctrl *ctrl, bool enable); - void (*mainlink_levels)(struct dp_catalog_ctrl *ctrl, u8 lane_cnt); -}; - -struct dp_catalog_hpd { - void (*config_hpd)(struct dp_catalog_hpd *hpd, bool en); - u32 (*get_interrupt)(struct dp_catalog_hpd *hpd); -}; - -#define HEADER_BYTE_2_BIT 0 -#define PARITY_BYTE_2_BIT 8 -#define HEADER_BYTE_1_BIT 16 -#define PARITY_BYTE_1_BIT 24 -#define HEADER_BYTE_3_BIT 16 -#define PARITY_BYTE_3_BIT 24 - -enum dp_catalog_audio_sdp_type { - DP_AUDIO_SDP_STREAM, - DP_AUDIO_SDP_TIMESTAMP, - DP_AUDIO_SDP_INFOFRAME, - DP_AUDIO_SDP_COPYMANAGEMENT, - DP_AUDIO_SDP_ISRC, - DP_AUDIO_SDP_MAX, -}; - -enum dp_catalog_audio_header_type { - DP_AUDIO_SDP_HEADER_1, - DP_AUDIO_SDP_HEADER_2, - DP_AUDIO_SDP_HEADER_3, - DP_AUDIO_SDP_HEADER_MAX, -}; - -struct dp_catalog_audio { - enum dp_catalog_audio_sdp_type sdp_type; - enum dp_catalog_audio_header_type sdp_header; - u32 data; - - enum dp_stream_id stream_id; - - void (*init)(struct dp_catalog_audio *audio); - void (*enable)(struct dp_catalog_audio *audio); - void (*config_acr)(struct dp_catalog_audio *audio); - void (*config_sdp)(struct dp_catalog_audio *audio); - void (*set_header)(struct dp_catalog_audio *audio); - void (*get_header)(struct dp_catalog_audio *audio); -}; - -struct dp_dsc_cfg_data { - bool dsc_en; - char pps[128]; - u32 pps_len; - u32 pps_word[32]; - u32 pps_word_len; - u8 parity[32]; - u8 parity_len; - u32 parity_word[8]; - u32 parity_word_len; - u32 slice_per_pkt; - u32 bytes_per_pkt; - u32 eol_byte_num; - u32 be_in_lane; - u32 dto_en; - u32 dto_n; - u32 dto_d; - u32 dto_count; -}; - -struct dp_catalog_panel { - u32 total; - u32 sync_start; - u32 width_blanking; - u32 dp_active; - u8 *spd_vendor_name; - u8 *spd_product_description; - - struct dp_catalog_hdr_data hdr_data; - - /* TPG */ - u32 hsync_period; - u32 vsync_period; - u32 display_v_start; - u32 display_v_end; - u32 v_sync_width; - u32 hsync_ctl; - u32 display_hctl; - - /* TU */ - u32 dp_tu; - u32 valid_boundary; - u32 valid_boundary2; - - u32 misc_val; - - enum dp_stream_id stream_id; - - bool widebus_en; - struct dp_dsc_cfg_data dsc; - - int (*timing_cfg)(struct dp_catalog_panel *panel); - void (*config_hdr)(struct dp_catalog_panel *panel, bool en, - u32 dhdr_max_pkts); - void (*tpg_config)(struct dp_catalog_panel *panel, bool enable); - void (*config_spd)(struct dp_catalog_panel *panel); - void (*config_misc)(struct dp_catalog_panel *panel); - void (*config_msa)(struct dp_catalog_panel *panel, - u32 rate, u32 stream_rate_khz); - void (*update_transfer_unit)(struct dp_catalog_panel *panel); - void (*config_ctrl)(struct dp_catalog_panel *panel, u32 cfg); - void (*config_dto)(struct dp_catalog_panel *panel, bool ack); - void (*dsc_cfg)(struct dp_catalog_panel *panel); - void (*pps_flush)(struct dp_catalog_panel *panel); - void (*dhdr_flush)(struct dp_catalog_panel *panel); - bool (*dhdr_busy)(struct dp_catalog_panel *panel); -}; - -struct dp_catalog; -struct dp_catalog_priv { - void *data; - - void (*put)(struct dp_catalog *catalog); - void (*set_exe_mode)(struct dp_catalog *dp_catalog, char *mode); -}; - -struct dp_catalog { - struct dp_catalog_aux aux; - struct dp_catalog_ctrl ctrl; - struct dp_catalog_audio audio; - struct dp_catalog_panel panel; - struct dp_catalog_priv priv; - struct dp_catalog_hpd hpd; - - void (*set_exe_mode)(struct dp_catalog *dp_catalog, char *mode); - int (*get_reg_dump)(struct dp_catalog *dp_catalog, - char *mode, u8 **out_buf, u32 *out_buf_len); -}; - -static inline u8 dp_ecc_get_g0_value(u8 data) -{ - u8 c[4]; - u8 g[4]; - u8 ret_data = 0; - u8 i; - - for (i = 0; i < 4; i++) - c[i] = (data >> i) & 0x01; - - g[0] = c[3]; - g[1] = c[0] ^ c[3]; - g[2] = c[1]; - g[3] = c[2]; - - for (i = 0; i < 4; i++) - ret_data = ((g[i] & 0x01) << i) | ret_data; - - return ret_data; -} - -static inline u8 dp_ecc_get_g1_value(u8 data) -{ - u8 c[4]; - u8 g[4]; - u8 ret_data = 0; - u8 i; - - for (i = 0; i < 4; i++) - c[i] = (data >> i) & 0x01; - - g[0] = c[0] ^ c[3]; - g[1] = c[0] ^ c[1] ^ c[3]; - g[2] = c[1] ^ c[2]; - g[3] = c[2] ^ c[3]; - - for (i = 0; i < 4; i++) - ret_data = ((g[i] & 0x01) << i) | ret_data; - - return ret_data; -} - -static inline u8 dp_header_get_parity(u32 data) -{ - u8 x0 = 0; - u8 x1 = 0; - u8 ci = 0; - u8 iData = 0; - u8 i = 0; - u8 parity_byte; - u8 num_byte = (data > 0xFF) ? 8 : 2; - - for (i = 0; i < num_byte; i++) { - iData = (data >> i*4) & 0xF; - - ci = iData ^ x1; - x1 = x0 ^ dp_ecc_get_g1_value(ci); - x0 = dp_ecc_get_g0_value(ci); - } - - parity_byte = x1 | (x0 << 4); - - return parity_byte; -} - -static inline u32 dp_read(char *exe_mode, struct dp_io_data *io_data, - u32 offset) -{ - u32 data = 0; - - if (!strcmp(exe_mode, "hw") || !strcmp(exe_mode, "all")) { - data = readl_relaxed(io_data->io.base + offset); - } else if (!strcmp(exe_mode, "sw")) { - if (io_data->buf) - memcpy(&data, io_data->buf + offset, sizeof(offset)); - } - - return data; -} - -static inline void dp_write(char *exe_mode, struct dp_io_data *io_data, - u32 offset, u32 data) -{ - if (!strcmp(exe_mode, "hw") || !strcmp(exe_mode, "all")) - writel_relaxed(data, io_data->io.base + offset); - - if (!strcmp(exe_mode, "sw") || !strcmp(exe_mode, "all")) { - if (io_data->buf) - memcpy(io_data->buf + offset, &data, sizeof(data)); - } -} - -struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser); -void dp_catalog_put(struct dp_catalog *catalog); - -int dp_catalog_get_v420(struct device *dev, struct dp_catalog *catalog, - void *io); - -int dp_catalog_get_v200(struct device *dev, struct dp_catalog *catalog, - void *io); - -#endif /* _DP_CATALOG_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_catalog_v200.c b/drivers/gpu/drm/msm/dp/dp_catalog_v200.c deleted file mode 100644 index 132e50e181778a2db4b2e3538612357be7b44bad..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_catalog_v200.c +++ /dev/null @@ -1,304 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ - -#include - -#include "dp_catalog.h" -#include "dp_reg.h" - -#define dp_catalog_get_priv_v200(x) ({ \ - struct dp_catalog *dp_catalog; \ - dp_catalog = container_of(x, struct dp_catalog, x); \ - dp_catalog->priv.data; \ -}) - -struct dp_catalog_io { - struct dp_io_data *dp_ahb; - struct dp_io_data *dp_aux; - struct dp_io_data *dp_link; - struct dp_io_data *dp_p0; - struct dp_io_data *dp_phy; - struct dp_io_data *dp_ln_tx0; - struct dp_io_data *dp_ln_tx1; - struct dp_io_data *dp_mmss_cc; - struct dp_io_data *dp_pll; - struct dp_io_data *usb3_dp_com; - struct dp_io_data *hdcp_physical; - struct dp_io_data *dp_p1; - struct dp_io_data *dp_tcsr; -}; - -struct dp_catalog_private_v200 { - struct device *dev; - struct dp_catalog_io *io; - - char exe_mode[SZ_4]; -}; - -static void dp_catalog_aux_clear_hw_interrupts_v200(struct dp_catalog_aux *aux) -{ - struct dp_catalog_private_v200 *catalog; - struct dp_io_data *io_data; - u32 data = 0; - - if (!aux) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv_v200(aux); - io_data = catalog->io->dp_phy; - - data = dp_read(catalog->exe_mode, io_data, - DP_PHY_AUX_INTERRUPT_STATUS_V200); - - dp_write(catalog->exe_mode, io_data, DP_PHY_AUX_INTERRUPT_CLEAR_V200, - 0x1f); - wmb(); /* make sure 0x1f is written before next write */ - dp_write(catalog->exe_mode, io_data, DP_PHY_AUX_INTERRUPT_CLEAR_V200, - 0x9f); - wmb(); /* make sure 0x9f is written before next write */ - dp_write(catalog->exe_mode, io_data, DP_PHY_AUX_INTERRUPT_CLEAR_V200, - 0); - wmb(); /* make sure register is cleared */ -} - -static void dp_catalog_aux_setup_v200(struct dp_catalog_aux *aux, - struct dp_aux_cfg *cfg) -{ - struct dp_catalog_private_v200 *catalog; - struct dp_io_data *io_data; - int i = 0, sw_reset = 0; - - if (!aux || !cfg) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv_v200(aux); - - io_data = catalog->io->dp_ahb; - sw_reset = dp_read(catalog->exe_mode, io_data, DP_SW_RESET); - - sw_reset |= BIT(0); - dp_write(catalog->exe_mode, io_data, DP_SW_RESET, sw_reset); - usleep_range(1000, 1010); /* h/w recommended delay */ - - sw_reset &= ~BIT(0); - dp_write(catalog->exe_mode, io_data, DP_SW_RESET, sw_reset); - - dp_write(catalog->exe_mode, io_data, DP_PHY_CTRL, 0x4); /* bit 2 */ - udelay(1000); - dp_write(catalog->exe_mode, io_data, DP_PHY_CTRL, 0x0); /* bit 2 */ - wmb(); /* make sure programming happened */ - - io_data = catalog->io->dp_tcsr; - dp_write(catalog->exe_mode, io_data, 0x4c, 0x1); /* bit 0 & 2 */ - wmb(); /* make sure programming happened */ - - io_data = catalog->io->dp_phy; - dp_write(catalog->exe_mode, io_data, DP_PHY_PD_CTL, 0x3c); - wmb(); /* make sure PD programming happened */ - dp_write(catalog->exe_mode, io_data, DP_PHY_PD_CTL, 0x3d); - wmb(); /* make sure PD programming happened */ - - /* DP AUX CFG register programming */ - io_data = catalog->io->dp_phy; - for (i = 0; i < PHY_AUX_CFG_MAX; i++) - dp_write(catalog->exe_mode, io_data, cfg[i].offset, - cfg[i].lut[cfg[i].current_index]); - - dp_write(catalog->exe_mode, io_data, DP_PHY_AUX_INTERRUPT_MASK_V200, - 0x1F); - wmb(); /* make sure AUX configuration is done before enabling it */ -} - -static void dp_catalog_panel_config_msa_v200(struct dp_catalog_panel *panel, - u32 rate, u32 stream_rate_khz) -{ - u32 pixel_m, pixel_n; - u32 mvid, nvid; - u32 const nvid_fixed = 0x8000; - u32 const link_rate_hbr2 = 540000; - u32 const link_rate_hbr3 = 810000; - struct dp_catalog_private_v200 *catalog; - struct dp_io_data *io_data; - u32 strm_reg_off = 0; - u32 mvid_reg_off = 0, nvid_reg_off = 0; - - if (!panel) { - pr_err("invalid input\n"); - return; - } - - if (panel->stream_id >= DP_STREAM_MAX) { - pr_err("invalid stream_id:%d\n", panel->stream_id); - return; - } - - catalog = dp_catalog_get_priv_v200(panel); - io_data = catalog->io->dp_mmss_cc; - - if (panel->stream_id == DP_STREAM_1) - strm_reg_off = MMSS_DP_PIXEL1_M_V200 - - MMSS_DP_PIXEL_M_V200; - - pixel_m = dp_read(catalog->exe_mode, io_data, - MMSS_DP_PIXEL_M_V200 + strm_reg_off); - pixel_n = dp_read(catalog->exe_mode, io_data, - MMSS_DP_PIXEL_N_V200 + strm_reg_off); - pr_debug("pixel_m=0x%x, pixel_n=0x%x\n", pixel_m, pixel_n); - - mvid = (pixel_m & 0xFFFF) * 5; - nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF); - - if (nvid < nvid_fixed) { - u32 temp; - - temp = (nvid_fixed / nvid) * nvid; - mvid = (nvid_fixed / nvid) * mvid; - nvid = temp; - } - - pr_debug("rate = %d\n", rate); - - if (panel->widebus_en) - mvid <<= 1; - - if (link_rate_hbr2 == rate) - nvid *= 2; - - if (link_rate_hbr3 == rate) - nvid *= 3; - - io_data = catalog->io->dp_link; - - if (panel->stream_id == DP_STREAM_1) { - mvid_reg_off = DP1_SOFTWARE_MVID - DP_SOFTWARE_MVID; - nvid_reg_off = DP1_SOFTWARE_NVID - DP_SOFTWARE_NVID; - } - - pr_debug("mvid=0x%x, nvid=0x%x\n", mvid, nvid); - dp_write(catalog->exe_mode, io_data, DP_SOFTWARE_MVID + mvid_reg_off, - mvid); - dp_write(catalog->exe_mode, io_data, DP_SOFTWARE_NVID + nvid_reg_off, - nvid); -} - -static void dp_catalog_ctrl_lane_mapping_v200(struct dp_catalog_ctrl *ctrl, - bool flipped, char *lane_map) -{ - struct dp_catalog_private_v200 *catalog; - struct dp_io_data *io_data; - u8 l_map[4] = { 0 }, i = 0, j = 0; - u32 lane_map_reg = 0; - - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv_v200(ctrl); - io_data = catalog->io->dp_link; - - /* For flip case, swap phy lanes with ML0 and ML3, ML1 and ML2 */ - if (flipped) { - for (i = 0; i < DP_MAX_PHY_LN; i++) { - if (lane_map[i] == DP_ML0) { - for (j = 0; j < DP_MAX_PHY_LN; j++) { - if (lane_map[j] == DP_ML3) { - l_map[i] = DP_ML3; - l_map[j] = DP_ML0; - break; - } - } - } else if (lane_map[i] == DP_ML1) { - for (j = 0; j < DP_MAX_PHY_LN; j++) { - if (lane_map[j] == DP_ML2) { - l_map[i] = DP_ML2; - l_map[j] = DP_ML1; - break; - } - } - } - } - } else { - /* Normal orientation */ - for (i = 0; i < DP_MAX_PHY_LN; i++) - l_map[i] = lane_map[i]; - } - - lane_map_reg = ((l_map[3]&3)<<6)|((l_map[2]&3)<<4)|((l_map[1]&3)<<2) - |(l_map[0]&3); - - dp_write(catalog->exe_mode, io_data, DP_LOGICAL2PHYSICAL_LANE_MAPPING, - lane_map_reg); -} - -static void dp_catalog_ctrl_usb_reset_v200(struct dp_catalog_ctrl *ctrl, - bool flip) -{ -} - -static void dp_catalog_put_v200(struct dp_catalog *catalog) -{ - struct dp_catalog_private_v200 *catalog_priv; - - if (!catalog || !catalog->priv.data) - return; - - catalog_priv = catalog->priv.data; - devm_kfree(catalog_priv->dev, catalog_priv); -} - -static void dp_catalog_set_exe_mode_v200(struct dp_catalog *catalog, char *mode) -{ - struct dp_catalog_private_v200 *catalog_priv; - - if (!catalog || !catalog->priv.data) - return; - - catalog_priv = catalog->priv.data; - - strlcpy(catalog_priv->exe_mode, mode, sizeof(catalog_priv->exe_mode)); -} - -int dp_catalog_get_v200(struct device *dev, struct dp_catalog *catalog, - void *io) -{ - struct dp_catalog_private_v200 *catalog_priv; - - if (!dev || !catalog) { - pr_err("invalid input\n"); - return -EINVAL; - } - - catalog_priv = devm_kzalloc(dev, sizeof(*catalog_priv), GFP_KERNEL); - if (!catalog_priv) - return -ENOMEM; - - catalog_priv->dev = dev; - catalog_priv->io = io; - catalog->priv.data = catalog_priv; - - catalog->priv.put = dp_catalog_put_v200; - catalog->priv.set_exe_mode = dp_catalog_set_exe_mode_v200; - - catalog->aux.clear_hw_interrupts = - dp_catalog_aux_clear_hw_interrupts_v200; - catalog->aux.setup = dp_catalog_aux_setup_v200; - - catalog->panel.config_msa = dp_catalog_panel_config_msa_v200; - - catalog->ctrl.lane_mapping = dp_catalog_ctrl_lane_mapping_v200; - catalog->ctrl.usb_reset = dp_catalog_ctrl_usb_reset_v200; - - /* Set the default execution mode to hardware mode */ - dp_catalog_set_exe_mode_v200(catalog, "hw"); - - return 0; -} diff --git a/drivers/gpu/drm/msm/dp/dp_catalog_v420.c b/drivers/gpu/drm/msm/dp/dp_catalog_v420.c deleted file mode 100644 index 51fa987c81b771beafab28deb4eda3d43b3c3e6e..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_catalog_v420.c +++ /dev/null @@ -1,349 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ - -#include "dp_catalog.h" -#include "dp_reg.h" - -#define dp_catalog_get_priv_v420(x) ({ \ - struct dp_catalog *dp_catalog; \ - dp_catalog = container_of(x, struct dp_catalog, x); \ - dp_catalog->priv.data; \ -}) - -#define MAX_VOLTAGE_LEVELS 4 -#define MAX_PRE_EMP_LEVELS 4 - -static u8 const vm_pre_emphasis[MAX_VOLTAGE_LEVELS][MAX_PRE_EMP_LEVELS] = { - {0x00, 0x0E, 0x16, 0xFF}, /* pe0, 0 db */ - {0x00, 0x0E, 0x16, 0xFF}, /* pe1, 3.5 db */ - {0x00, 0x0E, 0xFF, 0xFF}, /* pe2, 6.0 db */ - {0xFF, 0xFF, 0xFF, 0xFF} /* pe3, 9.5 db */ -}; - -/* voltage swing, 0.2v and 1.0v are not support */ -static u8 const vm_voltage_swing[MAX_VOLTAGE_LEVELS][MAX_PRE_EMP_LEVELS] = { - {0x07, 0x0F, 0x16, 0xFF}, /* sw0, 0.4v */ - {0x11, 0x1E, 0x1F, 0xFF}, /* sw1, 0.6 v */ - {0x1A, 0x1F, 0xFF, 0xFF}, /* sw1, 0.8 v */ - {0xFF, 0xFF, 0xFF, 0xFF} /* sw1, 1.2 v, optional */ -}; - -struct dp_catalog_io { - struct dp_io_data *dp_ahb; - struct dp_io_data *dp_aux; - struct dp_io_data *dp_link; - struct dp_io_data *dp_p0; - struct dp_io_data *dp_phy; - struct dp_io_data *dp_ln_tx0; - struct dp_io_data *dp_ln_tx1; - struct dp_io_data *dp_mmss_cc; - struct dp_io_data *dp_pll; - struct dp_io_data *usb3_dp_com; - struct dp_io_data *hdcp_physical; - struct dp_io_data *dp_p1; -}; - -struct dp_catalog_private_v420 { - struct device *dev; - struct dp_catalog_io *io; - - char exe_mode[SZ_4]; -}; - -static void dp_catalog_aux_setup_v420(struct dp_catalog_aux *aux, - struct dp_aux_cfg *cfg) -{ - struct dp_catalog_private_v420 *catalog; - struct dp_io_data *io_data; - int i = 0; - - if (!aux || !cfg) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv_v420(aux); - - io_data = catalog->io->dp_phy; - dp_write(catalog->exe_mode, io_data, DP_PHY_PD_CTL, 0x67); - wmb(); /* make sure PD programming happened */ - - /* Turn on BIAS current for PHY/PLL */ - io_data = catalog->io->dp_pll; - dp_write(catalog->exe_mode, io_data, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, - 0x17); - wmb(); /* make sure BIAS programming happened */ - - io_data = catalog->io->dp_phy; - /* DP AUX CFG register programming */ - for (i = 0; i < PHY_AUX_CFG_MAX; i++) { - pr_debug("%s: offset=0x%08x, value=0x%08x\n", - dp_phy_aux_config_type_to_string(i), - cfg[i].offset, cfg[i].lut[cfg[i].current_index]); - dp_write(catalog->exe_mode, io_data, cfg[i].offset, - cfg[i].lut[cfg[i].current_index]); - } - wmb(); /* make sure DP AUX CFG programming happened */ - - dp_write(catalog->exe_mode, io_data, DP_PHY_AUX_INTERRUPT_MASK_V420, - 0x1F); -} - -static void dp_catalog_aux_clear_hw_interrupts_v420(struct dp_catalog_aux *aux) -{ - struct dp_catalog_private_v420 *catalog; - struct dp_io_data *io_data; - u32 data = 0; - - if (!aux) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv_v420(aux); - io_data = catalog->io->dp_phy; - - data = dp_read(catalog->exe_mode, io_data, - DP_PHY_AUX_INTERRUPT_STATUS_V420); - - dp_write(catalog->exe_mode, io_data, - DP_PHY_AUX_INTERRUPT_CLEAR_V420, 0x1f); - wmb(); /* make sure 0x1f is written before next write */ - dp_write(catalog->exe_mode, io_data, - DP_PHY_AUX_INTERRUPT_CLEAR_V420, 0x9f); - wmb(); /* make sure 0x9f is written before next write */ - dp_write(catalog->exe_mode, io_data, - DP_PHY_AUX_INTERRUPT_CLEAR_V420, 0); - wmb(); /* make sure register is cleared */ -} - -static void dp_catalog_panel_config_msa_v420(struct dp_catalog_panel *panel, - u32 rate, u32 stream_rate_khz) -{ - u32 pixel_m, pixel_n; - u32 mvid, nvid, reg_off = 0, mvid_off = 0, nvid_off = 0; - u32 const nvid_fixed = 0x8000; - u32 const link_rate_hbr2 = 540000; - u32 const link_rate_hbr3 = 810000; - struct dp_catalog_private_v420 *catalog; - struct dp_io_data *io_data; - - if (!panel || !rate) { - pr_err("invalid input\n"); - return; - } - - if (panel->stream_id >= DP_STREAM_MAX) { - pr_err("invalid stream id:%d\n", panel->stream_id); - return; - } - - catalog = dp_catalog_get_priv_v420(panel); - io_data = catalog->io->dp_mmss_cc; - - if (panel->stream_id == DP_STREAM_1) - reg_off = MMSS_DP_PIXEL1_M_V420 - MMSS_DP_PIXEL_M_V420; - - pixel_m = dp_read(catalog->exe_mode, io_data, - MMSS_DP_PIXEL_M_V420 + reg_off); - pixel_n = dp_read(catalog->exe_mode, io_data, - MMSS_DP_PIXEL_N_V420 + reg_off); - pr_debug("pixel_m=0x%x, pixel_n=0x%x\n", pixel_m, pixel_n); - - mvid = (pixel_m & 0xFFFF) * 5; - nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF); - - if (nvid < nvid_fixed) { - u32 temp; - - temp = (nvid_fixed / nvid) * nvid; - mvid = (nvid_fixed / nvid) * mvid; - nvid = temp; - } - - pr_debug("rate = %d\n", rate); - - if (panel->widebus_en) - mvid <<= 1; - - if (link_rate_hbr2 == rate) - nvid *= 2; - - if (link_rate_hbr3 == rate) - nvid *= 3; - - io_data = catalog->io->dp_link; - - if (panel->stream_id == DP_STREAM_1) { - mvid_off = DP1_SOFTWARE_MVID - DP_SOFTWARE_MVID; - nvid_off = DP1_SOFTWARE_NVID - DP_SOFTWARE_NVID; - } - - pr_debug("mvid=0x%x, nvid=0x%x\n", mvid, nvid); - dp_write(catalog->exe_mode, io_data, DP_SOFTWARE_MVID + mvid_off, mvid); - dp_write(catalog->exe_mode, io_data, DP_SOFTWARE_NVID + nvid_off, nvid); -} - -static void dp_catalog_ctrl_phy_lane_cfg_v420(struct dp_catalog_ctrl *ctrl, - bool flipped, u8 ln_cnt) -{ - u32 info = 0x0; - struct dp_catalog_private_v420 *catalog; - u8 orientation = BIT(!!flipped); - struct dp_io_data *io_data; - - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv_v420(ctrl); - io_data = catalog->io->dp_phy; - - info |= (ln_cnt & 0x0F); - info |= ((orientation & 0x0F) << 4); - pr_debug("Shared Info = 0x%x\n", info); - - dp_write(catalog->exe_mode, io_data, DP_PHY_SPARE0_V420, info); -} - -static void dp_catalog_ctrl_update_vx_px_v420(struct dp_catalog_ctrl *ctrl, - u8 v_level, u8 p_level) -{ - struct dp_catalog_private_v420 *catalog; - struct dp_io_data *io_data; - u8 value0, value1; - - if (!ctrl || !((v_level < MAX_VOLTAGE_LEVELS) - && (p_level < MAX_PRE_EMP_LEVELS))) { - pr_err("invalid input\n"); - return; - } - - catalog = dp_catalog_get_priv_v420(ctrl); - - pr_debug("hw: v=%d p=%d\n", v_level, p_level); - - value0 = vm_voltage_swing[v_level][p_level]; - value1 = vm_pre_emphasis[v_level][p_level]; - - /* program default setting first */ - io_data = catalog->io->dp_ln_tx0; - dp_write(catalog->exe_mode, io_data, TXn_TX_DRV_LVL_V420, 0x2A); - dp_write(catalog->exe_mode, io_data, TXn_TX_EMP_POST1_LVL, 0x20); - - io_data = catalog->io->dp_ln_tx1; - dp_write(catalog->exe_mode, io_data, TXn_TX_DRV_LVL_V420, 0x2A); - dp_write(catalog->exe_mode, io_data, TXn_TX_EMP_POST1_LVL, 0x20); - - /* Enable MUX to use Cursor values from these registers */ - value0 |= BIT(5); - value1 |= BIT(5); - - /* Configure host and panel only if both values are allowed */ - if (value0 != 0xFF && value1 != 0xFF) { - io_data = catalog->io->dp_ln_tx0; - dp_write(catalog->exe_mode, io_data, TXn_TX_DRV_LVL_V420, - value0); - dp_write(catalog->exe_mode, io_data, TXn_TX_EMP_POST1_LVL, - value1); - - io_data = catalog->io->dp_ln_tx1; - dp_write(catalog->exe_mode, io_data, TXn_TX_DRV_LVL_V420, - value0); - dp_write(catalog->exe_mode, io_data, TXn_TX_EMP_POST1_LVL, - value1); - - pr_debug("hw: vx_value=0x%x px_value=0x%x\n", - value0, value1); - } else { - pr_err("invalid vx (0x%x=0x%x), px (0x%x=0x%x\n", - v_level, value0, p_level, value1); - } -} - -static void dp_catalog_ctrl_lane_pnswap_v420(struct dp_catalog_ctrl *ctrl, - u8 ln_pnswap) -{ - struct dp_catalog_private_v420 *catalog; - struct dp_io_data *io_data; - u32 cfg0, cfg1; - - catalog = dp_catalog_get_priv_v420(ctrl); - - cfg0 = 0x0a; - cfg1 = 0x0a; - - cfg0 |= ((ln_pnswap >> 0) & 0x1) << 0; - cfg0 |= ((ln_pnswap >> 1) & 0x1) << 2; - cfg1 |= ((ln_pnswap >> 2) & 0x1) << 0; - cfg1 |= ((ln_pnswap >> 3) & 0x1) << 2; - - io_data = catalog->io->dp_ln_tx0; - dp_write(catalog->exe_mode, io_data, TXn_TX_POL_INV_V420, cfg0); - - io_data = catalog->io->dp_ln_tx1; - dp_write(catalog->exe_mode, io_data, TXn_TX_POL_INV_V420, cfg1); -} - -static void dp_catalog_put_v420(struct dp_catalog *catalog) -{ - struct dp_catalog_private_v420 *catalog_priv; - - if (!catalog || !catalog->priv.data) - return; - - catalog_priv = catalog->priv.data; - devm_kfree(catalog_priv->dev, catalog_priv); -} - -static void dp_catalog_set_exe_mode_v420(struct dp_catalog *catalog, char *mode) -{ - struct dp_catalog_private_v420 *catalog_priv; - - if (!catalog || !catalog->priv.data) - return; - - catalog_priv = catalog->priv.data; - - strlcpy(catalog_priv->exe_mode, mode, sizeof(catalog_priv->exe_mode)); -} - -int dp_catalog_get_v420(struct device *dev, struct dp_catalog *catalog, - void *io) -{ - struct dp_catalog_private_v420 *catalog_priv; - - if (!dev || !catalog) { - pr_err("invalid input\n"); - return -EINVAL; - } - - catalog_priv = devm_kzalloc(dev, sizeof(*catalog_priv), GFP_KERNEL); - if (!catalog_priv) - return -ENOMEM; - - catalog_priv->dev = dev; - catalog_priv->io = io; - catalog->priv.data = catalog_priv; - - catalog->priv.put = dp_catalog_put_v420; - catalog->priv.set_exe_mode = dp_catalog_set_exe_mode_v420; - - catalog->aux.setup = dp_catalog_aux_setup_v420; - catalog->aux.clear_hw_interrupts = - dp_catalog_aux_clear_hw_interrupts_v420; - catalog->panel.config_msa = dp_catalog_panel_config_msa_v420; - catalog->ctrl.phy_lane_cfg = dp_catalog_ctrl_phy_lane_cfg_v420; - catalog->ctrl.update_vx_px = dp_catalog_ctrl_update_vx_px_v420; - catalog->ctrl.lane_pnswap = dp_catalog_ctrl_lane_pnswap_v420; - - /* Set the default execution mode to hardware mode */ - dp_catalog_set_exe_mode_v420(catalog, "hw"); - - return 0; -} diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c deleted file mode 100644 index 0d1b061aa436657320a91ef50431df290bc6be43..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ /dev/null @@ -1,1317 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ - -#include -#include -#include -#include - -#include "dp_ctrl.h" - -#define DP_MST_DEBUG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) - -#define DP_CTRL_INTR_READY_FOR_VIDEO BIT(0) -#define DP_CTRL_INTR_IDLE_PATTERN_SENT BIT(3) - -#define DP_CTRL_INTR_MST_DP0_VCPF_SENT BIT(0) -#define DP_CTRL_INTR_MST_DP1_VCPF_SENT BIT(3) - -/* dp state ctrl */ -#define ST_TRAIN_PATTERN_1 BIT(0) -#define ST_TRAIN_PATTERN_2 BIT(1) -#define ST_TRAIN_PATTERN_3 BIT(2) -#define ST_TRAIN_PATTERN_4 BIT(3) -#define ST_SYMBOL_ERR_RATE_MEASUREMENT BIT(4) -#define ST_PRBS7 BIT(5) -#define ST_CUSTOM_80_BIT_PATTERN BIT(6) -#define ST_SEND_VIDEO BIT(7) -#define ST_PUSH_IDLE BIT(8) -#define MST_DP0_PUSH_VCPF BIT(12) -#define MST_DP0_FORCE_VCPF BIT(13) -#define MST_DP1_PUSH_VCPF BIT(14) -#define MST_DP1_FORCE_VCPF BIT(15) - -#define MR_LINK_TRAINING1 0x8 -#define MR_LINK_SYMBOL_ERM 0x80 -#define MR_LINK_PRBS7 0x100 -#define MR_LINK_CUSTOM80 0x200 -#define MR_LINK_TRAINING4 0x40 - -struct dp_mst_ch_slot_info { - u32 start_slot; - u32 tot_slots; -}; - -struct dp_mst_channel_info { - struct dp_mst_ch_slot_info slot_info[DP_STREAM_MAX]; -}; - -struct dp_ctrl_private { - struct dp_ctrl dp_ctrl; - - struct device *dev; - struct dp_aux *aux; - struct dp_panel *panel; - struct dp_link *link; - struct dp_power *power; - struct dp_parser *parser; - struct dp_catalog_ctrl *catalog; - - struct completion idle_comp; - struct completion video_comp; - - bool orientation; - bool power_on; - bool mst_mode; - bool fec_mode; - - atomic_t aborted; - - u32 vic; - u32 stream_count; - struct dp_mst_channel_info mst_ch_info; -}; - -enum notification_status { - NOTIFY_UNKNOWN, - NOTIFY_CONNECT, - NOTIFY_DISCONNECT, - NOTIFY_CONNECT_IRQ_HPD, - NOTIFY_DISCONNECT_IRQ_HPD, -}; - -static void dp_ctrl_idle_patterns_sent(struct dp_ctrl_private *ctrl) -{ - pr_debug("idle_patterns_sent\n"); - complete(&ctrl->idle_comp); -} - -static void dp_ctrl_video_ready(struct dp_ctrl_private *ctrl) -{ - pr_debug("dp_video_ready\n"); - complete(&ctrl->video_comp); -} - -static void dp_ctrl_abort(struct dp_ctrl *dp_ctrl) -{ - struct dp_ctrl_private *ctrl; - - if (!dp_ctrl) { - pr_err("Invalid input data\n"); - return; - } - - ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - - atomic_set(&ctrl->aborted, 1); -} - -static void dp_ctrl_state_ctrl(struct dp_ctrl_private *ctrl, u32 state) -{ - ctrl->catalog->state_ctrl(ctrl->catalog, state); -} - -static void dp_ctrl_push_idle(struct dp_ctrl_private *ctrl, - enum dp_stream_id strm) -{ - int const idle_pattern_completion_timeout_ms = HZ / 10; - u32 state = 0x0; - - if (!ctrl->power_on) - return; - - if (!ctrl->mst_mode) { - state = ST_PUSH_IDLE; - goto trigger_idle; - } - - if (strm >= DP_STREAM_MAX) { - pr_err("mst push idle, invalid stream:%d\n", strm); - return; - } - - state |= (strm == DP_STREAM_0) ? MST_DP0_PUSH_VCPF : MST_DP1_PUSH_VCPF; - -trigger_idle: - reinit_completion(&ctrl->idle_comp); - dp_ctrl_state_ctrl(ctrl, state); - - if (!wait_for_completion_timeout(&ctrl->idle_comp, - idle_pattern_completion_timeout_ms)) - pr_warn("time out\n"); - else - pr_debug("mainlink off done\n"); -} - -/** - * dp_ctrl_configure_source_link_params() - configures DP TX source params - * @ctrl: Display Port Driver data - * @enable: enable or disable DP transmitter - * - * Configures the DP transmitter source params including details such as lane - * configuration, output format and sink/panel timing information. - */ -static void dp_ctrl_configure_source_link_params(struct dp_ctrl_private *ctrl, - bool enable) -{ - if (enable) { - ctrl->catalog->lane_mapping(ctrl->catalog, ctrl->orientation, - ctrl->parser->l_map); - ctrl->catalog->lane_pnswap(ctrl->catalog, - ctrl->parser->l_pnswap); - ctrl->catalog->mst_config(ctrl->catalog, ctrl->mst_mode); - ctrl->catalog->config_ctrl(ctrl->catalog, - ctrl->link->link_params.lane_count); - ctrl->catalog->mainlink_levels(ctrl->catalog, - ctrl->link->link_params.lane_count); - ctrl->catalog->mainlink_ctrl(ctrl->catalog, true); - } else { - ctrl->catalog->mainlink_ctrl(ctrl->catalog, false); - } -} - -static void dp_ctrl_wait4video_ready(struct dp_ctrl_private *ctrl) -{ - if (!wait_for_completion_timeout(&ctrl->video_comp, HZ / 2)) - pr_warn("SEND_VIDEO time out\n"); -} - -static int dp_ctrl_update_sink_vx_px(struct dp_ctrl_private *ctrl, - u32 voltage_level, u32 pre_emphasis_level) -{ - int i; - u8 buf[4]; - u32 max_level_reached = 0; - - if (voltage_level == DP_LINK_VOLTAGE_MAX) { - pr_debug("max. voltage swing level reached %d\n", - voltage_level); - max_level_reached |= BIT(2); - } - - if (pre_emphasis_level == DP_LINK_PRE_EMPHASIS_MAX) { - pr_debug("max. pre-emphasis level reached %d\n", - pre_emphasis_level); - max_level_reached |= BIT(5); - } - - pre_emphasis_level <<= 3; - - for (i = 0; i < 4; i++) - buf[i] = voltage_level | pre_emphasis_level | max_level_reached; - - pr_debug("sink: p|v=0x%x\n", voltage_level | pre_emphasis_level); - return drm_dp_dpcd_write(ctrl->aux->drm_aux, 0x103, buf, 4); -} - -static int dp_ctrl_update_vx_px(struct dp_ctrl_private *ctrl) -{ - struct dp_link *link = ctrl->link; - - ctrl->catalog->update_vx_px(ctrl->catalog, - link->phy_params.v_level, link->phy_params.p_level); - - return dp_ctrl_update_sink_vx_px(ctrl, link->phy_params.v_level, - link->phy_params.p_level); -} - -static int dp_ctrl_train_pattern_set(struct dp_ctrl_private *ctrl, - u8 pattern) -{ - u8 buf[4]; - - pr_debug("sink: pattern=%x\n", pattern); - - buf[0] = pattern; - return drm_dp_dpcd_write(ctrl->aux->drm_aux, - DP_TRAINING_PATTERN_SET, buf, 1); -} - -static int dp_ctrl_read_link_status(struct dp_ctrl_private *ctrl, - u8 *link_status) -{ - int ret = 0, len; - u32 const offset = DP_LANE_ALIGN_STATUS_UPDATED - DP_LANE0_1_STATUS; - u32 link_status_read_max_retries = 100; - - while (--link_status_read_max_retries) { - len = drm_dp_dpcd_read_link_status(ctrl->aux->drm_aux, - link_status); - if (len != DP_LINK_STATUS_SIZE) { - pr_err("DP link status read failed, err: %d\n", len); - ret = len; - break; - } - - if (!(link_status[offset] & DP_LINK_STATUS_UPDATED)) - break; - } - - return ret; -} - -static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl) -{ - int tries, old_v_level, ret = 0; - u8 link_status[DP_LINK_STATUS_SIZE]; - int const maximum_retries = 5; - - ctrl->aux->state &= ~DP_STATE_TRAIN_1_FAILED; - ctrl->aux->state &= ~DP_STATE_TRAIN_1_SUCCEEDED; - ctrl->aux->state |= DP_STATE_TRAIN_1_STARTED; - - dp_ctrl_state_ctrl(ctrl, 0); - /* Make sure to clear the current pattern before starting a new one */ - wmb(); - - ctrl->catalog->set_pattern(ctrl->catalog, 0x01); - ret = dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_1 | - DP_LINK_SCRAMBLING_DISABLE); /* train_1 */ - if (ret <= 0) { - ret = -EINVAL; - goto end; - } - - ret = dp_ctrl_update_vx_px(ctrl); - if (ret <= 0) { - ret = -EINVAL; - goto end; - } - - tries = 0; - old_v_level = ctrl->link->phy_params.v_level; - while (1) { - if (atomic_read(&ctrl->aborted)) { - ret = -EINVAL; - break; - } - - drm_dp_link_train_clock_recovery_delay(ctrl->panel->dpcd); - - ret = dp_ctrl_read_link_status(ctrl, link_status); - if (ret) - break; - - if (drm_dp_clock_recovery_ok(link_status, - ctrl->link->link_params.lane_count)) { - break; - } - - if (ctrl->link->phy_params.v_level == DP_LINK_VOLTAGE_MAX) { - pr_err_ratelimited("max v_level reached\n"); - ret = -EAGAIN; - break; - } - - if (old_v_level == ctrl->link->phy_params.v_level) { - tries++; - if (tries >= maximum_retries) { - pr_err("max tries reached\n"); - ret = -ETIMEDOUT; - break; - } - } else { - tries = 0; - old_v_level = ctrl->link->phy_params.v_level; - } - - pr_debug("clock recovery not done, adjusting vx px\n"); - - ctrl->link->adjust_levels(ctrl->link, link_status); - ret = dp_ctrl_update_vx_px(ctrl); - if (ret <= 0) { - ret = -EINVAL; - break; - } - } -end: - ctrl->aux->state &= ~DP_STATE_TRAIN_1_STARTED; - - if (ret) - ctrl->aux->state |= DP_STATE_TRAIN_1_FAILED; - else - ctrl->aux->state |= DP_STATE_TRAIN_1_SUCCEEDED; - - return ret; -} - -static int dp_ctrl_link_rate_down_shift(struct dp_ctrl_private *ctrl) -{ - int ret = 0; - - if (!ctrl) - return -EINVAL; - - switch (ctrl->link->link_params.bw_code) { - case DP_LINK_BW_8_1: - ctrl->link->link_params.bw_code = DP_LINK_BW_5_4; - break; - case DP_LINK_BW_5_4: - ctrl->link->link_params.bw_code = DP_LINK_BW_2_7; - break; - case DP_LINK_BW_2_7: - case DP_LINK_BW_1_62: - default: - ctrl->link->link_params.bw_code = DP_LINK_BW_1_62; - break; - } - - pr_debug("new bw code=0x%x\n", ctrl->link->link_params.bw_code); - - return ret; -} - -static void dp_ctrl_clear_training_pattern(struct dp_ctrl_private *ctrl) -{ - dp_ctrl_train_pattern_set(ctrl, 0); - drm_dp_link_train_channel_eq_delay(ctrl->panel->dpcd); -} - -static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl) -{ - int tries = 0, ret = 0; - char pattern; - int const maximum_retries = 5; - u8 link_status[DP_LINK_STATUS_SIZE]; - - ctrl->aux->state &= ~DP_STATE_TRAIN_2_FAILED; - ctrl->aux->state &= ~DP_STATE_TRAIN_2_SUCCEEDED; - ctrl->aux->state |= DP_STATE_TRAIN_2_STARTED; - - dp_ctrl_state_ctrl(ctrl, 0); - /* Make sure to clear the current pattern before starting a new one */ - wmb(); - - if (drm_dp_tps3_supported(ctrl->panel->dpcd)) - pattern = DP_TRAINING_PATTERN_3; - else - pattern = DP_TRAINING_PATTERN_2; - - ret = dp_ctrl_update_vx_px(ctrl); - if (ret <= 0) { - ret = -EINVAL; - goto end; - } - ctrl->catalog->set_pattern(ctrl->catalog, pattern); - ret = dp_ctrl_train_pattern_set(ctrl, - pattern | DP_RECOVERED_CLOCK_OUT_EN); - if (ret <= 0) { - ret = -EINVAL; - goto end; - } - - do { - if (atomic_read(&ctrl->aborted)) { - ret = -EINVAL; - break; - } - - drm_dp_link_train_channel_eq_delay(ctrl->panel->dpcd); - - ret = dp_ctrl_read_link_status(ctrl, link_status); - if (ret) - break; - - if (drm_dp_channel_eq_ok(link_status, - ctrl->link->link_params.lane_count)) - break; - - if (tries > maximum_retries) { - ret = -ETIMEDOUT; - break; - } - tries++; - - ctrl->link->adjust_levels(ctrl->link, link_status); - ret = dp_ctrl_update_vx_px(ctrl); - if (ret <= 0) { - ret = -EINVAL; - break; - } - } while (1); -end: - ctrl->aux->state &= ~DP_STATE_TRAIN_2_STARTED; - - if (ret) - ctrl->aux->state |= DP_STATE_TRAIN_2_FAILED; - else - ctrl->aux->state |= DP_STATE_TRAIN_2_SUCCEEDED; - return ret; -} - -static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl) -{ - int ret = 0; - u8 encoding = 0x1; - struct drm_dp_link link_info = {0}; - - ctrl->link->phy_params.p_level = 0; - ctrl->link->phy_params.v_level = 0; - - link_info.num_lanes = ctrl->link->link_params.lane_count; - link_info.rate = drm_dp_bw_code_to_link_rate( - ctrl->link->link_params.bw_code); - link_info.capabilities = ctrl->panel->link_info.capabilities; - - ret = drm_dp_link_configure(ctrl->aux->drm_aux, &link_info); - if (ret) - goto end; - - ret = drm_dp_dpcd_write(ctrl->aux->drm_aux, - DP_MAIN_LINK_CHANNEL_CODING_SET, &encoding, 1); - if (ret <= 0) { - ret = -EINVAL; - goto end; - } - - ret = dp_ctrl_link_train_1(ctrl); - if (ret) { - pr_err("link training #1 failed\n"); - goto end; - } - - /* print success info as this is a result of user initiated action */ - pr_info("link training #1 successful\n"); - - ret = dp_ctrl_link_training_2(ctrl); - if (ret) { - pr_err("link training #2 failed\n"); - goto end; - } - - /* print success info as this is a result of user initiated action */ - pr_info("link training #2 successful\n"); - -end: - dp_ctrl_state_ctrl(ctrl, 0); - /* Make sure to clear the current pattern before starting a new one */ - wmb(); - - dp_ctrl_clear_training_pattern(ctrl); - return ret; -} - -static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl) -{ - int ret = 0; - const unsigned int fec_cfg_dpcd = 0x120; - - if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) - goto end; - - /* - * As part of previous calls, DP controller state might have - * transitioned to PUSH_IDLE. In order to start transmitting a link - * training pattern, we have to first to a DP software reset. - */ - ctrl->catalog->reset(ctrl->catalog); - - if (ctrl->fec_mode) - drm_dp_dpcd_writeb(ctrl->aux->drm_aux, fec_cfg_dpcd, 0x01); - - ret = dp_ctrl_link_train(ctrl); - -end: - return ret; -} - -static void dp_ctrl_set_clock_rate(struct dp_ctrl_private *ctrl, - char *name, enum dp_pm_type clk_type, u32 rate) -{ - u32 num = ctrl->parser->mp[clk_type].num_clk; - struct dss_clk *cfg = ctrl->parser->mp[clk_type].clk_config; - - while (num && strcmp(cfg->clk_name, name)) { - num--; - cfg++; - } - - pr_debug("setting rate=%d on clk=%s\n", rate, name); - - if (num) - cfg->rate = rate; - else - pr_err("%s clock could not be set with rate %d\n", name, rate); -} - -static int dp_ctrl_enable_link_clock(struct dp_ctrl_private *ctrl) -{ - int ret = 0; - u32 rate = drm_dp_bw_code_to_link_rate(ctrl->link->link_params.bw_code); - enum dp_pm_type type = DP_LINK_PM; - - pr_debug("rate=%d\n", rate); - - dp_ctrl_set_clock_rate(ctrl, "link_clk", type, rate); - - ret = ctrl->power->clk_enable(ctrl->power, type, true); - if (ret) { - pr_err("Unabled to start link clocks\n"); - ret = -EINVAL; - } - - return ret; -} - -static void dp_ctrl_disable_link_clock(struct dp_ctrl_private *ctrl) -{ - ctrl->power->clk_enable(ctrl->power, DP_LINK_PM, false); -} - -static int dp_ctrl_link_setup(struct dp_ctrl_private *ctrl, bool shallow) -{ - int rc = -EINVAL; - u32 link_train_max_retries = 100; - struct dp_catalog_ctrl *catalog; - struct dp_link_params *link_params; - - catalog = ctrl->catalog; - link_params = &ctrl->link->link_params; - - catalog->phy_lane_cfg(catalog, ctrl->orientation, - link_params->lane_count); - - while (1) { - pr_debug("bw_code=%d, lane_count=%d\n", - link_params->bw_code, link_params->lane_count); - - rc = dp_ctrl_enable_link_clock(ctrl); - if (rc) - break; - - dp_ctrl_configure_source_link_params(ctrl, true); - - rc = dp_ctrl_setup_main_link(ctrl); - if (!rc) - break; - - /* - * Shallow means link training failure is not important. - * If it fails, we still keep the link clocks on. - * In this mode, the system expects DP to be up - * even though the cable is removed. Disconnect interrupt - * will eventually trigger and shutdown DP. - */ - if (shallow) { - rc = 0; - break; - } - - if (!link_train_max_retries-- || atomic_read(&ctrl->aborted)) - break; - - dp_ctrl_link_rate_down_shift(ctrl); - - dp_ctrl_configure_source_link_params(ctrl, false); - dp_ctrl_disable_link_clock(ctrl); - - /* hw recommended delays before retrying link training */ - msleep(20); - } - - return rc; -} - -static int dp_ctrl_enable_stream_clocks(struct dp_ctrl_private *ctrl, - struct dp_panel *dp_panel) -{ - int ret = 0; - u32 pclk; - enum dp_pm_type clk_type; - char clk_name[32] = ""; - - ret = ctrl->power->set_pixel_clk_parent(ctrl->power, - dp_panel->stream_id); - - if (ret) - return ret; - - if (dp_panel->stream_id == DP_STREAM_0) { - clk_type = DP_STREAM0_PM; - strlcpy(clk_name, "strm0_pixel_clk", 32); - } else if (dp_panel->stream_id == DP_STREAM_1) { - clk_type = DP_STREAM1_PM; - strlcpy(clk_name, "strm1_pixel_clk", 32); - } else { - pr_err("Invalid stream:%d for clk enable\n", - dp_panel->stream_id); - return -EINVAL; - } - - pclk = dp_panel->pinfo.widebus_en ? - (dp_panel->pinfo.pixel_clk_khz >> 1) : - (dp_panel->pinfo.pixel_clk_khz); - - dp_ctrl_set_clock_rate(ctrl, clk_name, clk_type, pclk); - - ret = ctrl->power->clk_enable(ctrl->power, clk_type, true); - if (ret) { - pr_err("Unabled to start stream:%d clocks\n", - dp_panel->stream_id); - ret = -EINVAL; - } - - return ret; -} - -static int dp_ctrl_disable_stream_clocks(struct dp_ctrl_private *ctrl, - struct dp_panel *dp_panel) -{ - int ret = 0; - - if (dp_panel->stream_id == DP_STREAM_0) { - return ctrl->power->clk_enable(ctrl->power, - DP_STREAM0_PM, false); - } else if (dp_panel->stream_id == DP_STREAM_1) { - return ctrl->power->clk_enable(ctrl->power, - DP_STREAM1_PM, false); - } else { - pr_err("Invalid stream:%d for clk disable\n", - dp_panel->stream_id); - ret = -EINVAL; - } - return ret; -} -static int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip, bool reset) -{ - struct dp_ctrl_private *ctrl; - struct dp_catalog_ctrl *catalog; - - if (!dp_ctrl) { - pr_err("Invalid input data\n"); - return -EINVAL; - } - - ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - - ctrl->orientation = flip; - catalog = ctrl->catalog; - - if (reset) { - catalog->usb_reset(ctrl->catalog, flip); - catalog->phy_reset(ctrl->catalog); - } - catalog->enable_irq(ctrl->catalog, true); - atomic_set(&ctrl->aborted, 0); - - return 0; -} - -/** - * dp_ctrl_host_deinit() - Uninitialize DP controller - * @ctrl: Display Port Driver data - * - * Perform required steps to uninitialize DP controller - * and its resources. - */ -static void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl) -{ - struct dp_ctrl_private *ctrl; - - if (!dp_ctrl) { - pr_err("Invalid input data\n"); - return; - } - - ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - - ctrl->catalog->enable_irq(ctrl->catalog, false); - - pr_debug("Host deinitialized successfully\n"); -} - -static void dp_ctrl_send_video(struct dp_ctrl_private *ctrl) -{ - ctrl->catalog->state_ctrl(ctrl->catalog, ST_SEND_VIDEO); -} - -static int dp_ctrl_link_maintenance(struct dp_ctrl *dp_ctrl) -{ - int ret = 0; - struct dp_ctrl_private *ctrl; - - if (!dp_ctrl) { - pr_err("Invalid input data\n"); - return -EINVAL; - } - - ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - - ctrl->aux->state &= ~DP_STATE_LINK_MAINTENANCE_COMPLETED; - ctrl->aux->state &= ~DP_STATE_LINK_MAINTENANCE_FAILED; - - if (!ctrl->power_on) { - pr_err("ctrl off\n"); - ret = -EINVAL; - goto end; - } - - if (atomic_read(&ctrl->aborted)) - goto end; - - ctrl->aux->state |= DP_STATE_LINK_MAINTENANCE_STARTED; - ret = dp_ctrl_setup_main_link(ctrl); - ctrl->aux->state &= ~DP_STATE_LINK_MAINTENANCE_STARTED; - - if (ret) { - ctrl->aux->state |= DP_STATE_LINK_MAINTENANCE_FAILED; - goto end; - } - - ctrl->aux->state |= DP_STATE_LINK_MAINTENANCE_COMPLETED; - - if (ctrl->stream_count) { - dp_ctrl_send_video(ctrl); - dp_ctrl_wait4video_ready(ctrl); - } -end: - return ret; -} - -static void dp_ctrl_process_phy_test_request(struct dp_ctrl *dp_ctrl) -{ - int ret = 0; - struct dp_ctrl_private *ctrl; - - if (!dp_ctrl) { - pr_err("Invalid input data\n"); - return; - } - - ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - - if (!ctrl->link->phy_params.phy_test_pattern_sel) { - pr_debug("no test pattern selected by sink\n"); - return; - } - - pr_debug("start\n"); - - /* - * The global reset will need DP link ralated clocks to be - * running. Add the global reset just before disabling the - * link clocks and core clocks. - */ - ctrl->catalog->reset(ctrl->catalog); - ctrl->dp_ctrl.stream_pre_off(&ctrl->dp_ctrl, ctrl->panel); - ctrl->dp_ctrl.stream_off(&ctrl->dp_ctrl, ctrl->panel); - ctrl->dp_ctrl.off(&ctrl->dp_ctrl); - - ctrl->aux->init(ctrl->aux, ctrl->parser->aux_cfg); - - ret = ctrl->dp_ctrl.on(&ctrl->dp_ctrl, ctrl->mst_mode, - ctrl->fec_mode, false); - if (ret) - pr_err("failed to enable DP controller\n"); - - ctrl->dp_ctrl.stream_on(&ctrl->dp_ctrl, ctrl->panel); - pr_debug("end\n"); -} - -static void dp_ctrl_send_phy_test_pattern(struct dp_ctrl_private *ctrl) -{ - bool success = false; - u32 pattern_sent = 0x0; - u32 pattern_requested = ctrl->link->phy_params.phy_test_pattern_sel; - - dp_ctrl_update_vx_px(ctrl); - ctrl->catalog->send_phy_pattern(ctrl->catalog, pattern_requested); - ctrl->link->send_test_response(ctrl->link); - - pattern_sent = ctrl->catalog->read_phy_pattern(ctrl->catalog); - pr_debug("pattern_request: %s. pattern_sent: 0x%x\n", - dp_link_get_phy_test_pattern(pattern_requested), - pattern_sent); - - switch (pattern_sent) { - case MR_LINK_TRAINING1: - if (pattern_requested == - DP_TEST_PHY_PATTERN_D10_2_NO_SCRAMBLING) - success = true; - break; - case MR_LINK_SYMBOL_ERM: - if ((pattern_requested == - DP_TEST_PHY_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT) - || (pattern_requested == - DP_TEST_PHY_PATTERN_CP2520_PATTERN_1)) - success = true; - break; - case MR_LINK_PRBS7: - if (pattern_requested == DP_TEST_PHY_PATTERN_PRBS7) - success = true; - break; - case MR_LINK_CUSTOM80: - if (pattern_requested == - DP_TEST_PHY_PATTERN_80_BIT_CUSTOM_PATTERN) - success = true; - break; - case MR_LINK_TRAINING4: - if (pattern_requested == - DP_TEST_PHY_PATTERN_CP2520_PATTERN_3) - success = true; - break; - default: - success = false; - break; - } - - pr_debug("%s: %s\n", success ? "success" : "failed", - dp_link_get_phy_test_pattern(pattern_requested)); -} - -static void dp_ctrl_mst_calculate_rg(struct dp_ctrl_private *ctrl, - struct dp_panel *panel, u32 *p_x_int, u32 *p_y_frac_enum) -{ - u64 min_slot_cnt, max_slot_cnt; - u64 raw_target_sc, target_sc_fixp; - u64 ts_denom, ts_enum, ts_int; - u64 pclk = panel->pinfo.pixel_clk_khz; - u64 lclk = panel->link_info.rate; - u64 lanes = panel->link_info.num_lanes; - u64 bpp = panel->pinfo.bpp; - u64 pbn = panel->pbn; - u64 numerator, denominator, temp, temp1, temp2; - u32 x_int = 0, y_frac_enum = 0; - u64 target_strm_sym, ts_int_fixp, ts_frac_fixp, y_frac_enum_fixp; - - if (panel->pinfo.comp_info.comp_ratio) - bpp = panel->pinfo.comp_info.dsc_info.bpp; - - /* min_slot_cnt */ - numerator = pclk * bpp * 64 * 1000; - denominator = lclk * lanes * 8 * 1000; - min_slot_cnt = drm_fixp_from_fraction(numerator, denominator); - - /* max_slot_cnt */ - numerator = pbn * 54 * 1000; - denominator = lclk * lanes; - max_slot_cnt = drm_fixp_from_fraction(numerator, denominator); - - /* raw_target_sc */ - numerator = max_slot_cnt + min_slot_cnt; - denominator = drm_fixp_from_fraction(2, 1); - raw_target_sc = drm_fixp_div(numerator, denominator); - - pr_debug("raw_target_sc before overhead:0x%llx\n", raw_target_sc); - pr_debug("dsc_overhead_fp:0x%llx\n", panel->pinfo.dsc_overhead_fp); - - /* apply fec and dsc overhead factor */ - if (panel->pinfo.dsc_overhead_fp) - raw_target_sc = drm_fixp_mul(raw_target_sc, - panel->pinfo.dsc_overhead_fp); - - if (panel->fec_overhead_fp) - raw_target_sc = drm_fixp_mul(raw_target_sc, - panel->fec_overhead_fp); - - pr_debug("raw_target_sc after overhead:0x%llx\n", raw_target_sc); - - /* target_sc */ - temp = drm_fixp_from_fraction(256 * lanes, 1); - numerator = drm_fixp_mul(raw_target_sc, temp); - denominator = drm_fixp_from_fraction(256 * lanes, 1); - target_sc_fixp = drm_fixp_div(numerator, denominator); - - ts_enum = 256 * lanes; - ts_denom = drm_fixp_from_fraction(256 * lanes, 1); - ts_int = drm_fixp2int(target_sc_fixp); - - temp = drm_fixp2int_ceil(raw_target_sc); - if (temp != ts_int) { - temp = drm_fixp_from_fraction(ts_int, 1); - temp1 = raw_target_sc - temp; - temp2 = drm_fixp_mul(temp1, ts_denom); - ts_enum = drm_fixp2int(temp2); - } - - /* target_strm_sym */ - ts_int_fixp = drm_fixp_from_fraction(ts_int, 1); - ts_frac_fixp = drm_fixp_from_fraction(ts_enum, drm_fixp2int(ts_denom)); - temp = ts_int_fixp + ts_frac_fixp; - temp1 = drm_fixp_from_fraction(lanes, 1); - target_strm_sym = drm_fixp_mul(temp, temp1); - - /* x_int */ - x_int = drm_fixp2int(target_strm_sym); - - /* y_enum_frac */ - temp = drm_fixp_from_fraction(x_int, 1); - temp1 = target_strm_sym - temp; - temp2 = drm_fixp_from_fraction(256, 1); - y_frac_enum_fixp = drm_fixp_mul(temp1, temp2); - - temp1 = drm_fixp2int(y_frac_enum_fixp); - temp2 = drm_fixp2int_ceil(y_frac_enum_fixp); - - y_frac_enum = (u32)((temp1 == temp2) ? temp1 : temp1 + 1); - - panel->mst_target_sc = raw_target_sc; - *p_x_int = x_int; - *p_y_frac_enum = y_frac_enum; - - pr_debug("x_int: %d, y_frac_enum: %d\n", x_int, y_frac_enum); -} - -static int dp_ctrl_mst_send_act(struct dp_ctrl_private *ctrl) -{ - bool act_complete; - - if (!ctrl->mst_mode) - return 0; - - ctrl->catalog->trigger_act(ctrl->catalog); - msleep(20); /* needs 1 frame time */ - - ctrl->catalog->read_act_complete_sts(ctrl->catalog, &act_complete); - - if (!act_complete) - pr_err("mst act trigger complete failed\n"); - else - DP_MST_DEBUG("mst ACT trigger complete SUCCESS\n"); - - return 0; -} - -static void dp_ctrl_mst_stream_setup(struct dp_ctrl_private *ctrl, - struct dp_panel *panel) -{ - u32 x_int, y_frac_enum, lanes, bw_code; - int i; - - if (!ctrl->mst_mode) - return; - - DP_MST_DEBUG("mst stream channel allocation\n"); - - for (i = DP_STREAM_0; i < DP_STREAM_MAX; i++) { - ctrl->catalog->channel_alloc(ctrl->catalog, - i, - ctrl->mst_ch_info.slot_info[i].start_slot, - ctrl->mst_ch_info.slot_info[i].tot_slots); - } - - lanes = ctrl->link->link_params.lane_count; - bw_code = ctrl->link->link_params.bw_code; - - dp_ctrl_mst_calculate_rg(ctrl, panel, &x_int, &y_frac_enum); - - ctrl->catalog->update_rg(ctrl->catalog, panel->stream_id, - x_int, y_frac_enum); - - DP_MST_DEBUG("mst stream:%d, start_slot:%d, tot_slots:%d\n", - panel->stream_id, - panel->channel_start_slot, panel->channel_total_slots); - - DP_MST_DEBUG("mst lane_cnt:%d, bw:%d, x_int:%d, y_frac:%d\n", - lanes, bw_code, x_int, y_frac_enum); -} - -static void dp_ctrl_fec_dsc_setup(struct dp_ctrl_private *ctrl) -{ - u8 fec_sts = 0; - int rlen; - u32 dsc_enable; - const unsigned int fec_sts_dpcd = 0x280; - - if (ctrl->stream_count || !ctrl->fec_mode) - return; - - ctrl->catalog->fec_config(ctrl->catalog, ctrl->fec_mode); - - /* wait for controller to start fec sequence */ - usleep_range(900, 1000); - drm_dp_dpcd_readb(ctrl->aux->drm_aux, fec_sts_dpcd, &fec_sts); - pr_debug("sink fec status:%d\n", fec_sts); - - dsc_enable = ctrl->fec_mode ? 1 : 0; - rlen = drm_dp_dpcd_writeb(ctrl->aux->drm_aux, DP_DSC_ENABLE, - dsc_enable); - if (rlen < 1) - pr_debug("failed to enable sink dsc\n"); -} - -static int dp_ctrl_stream_on(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) -{ - int rc = 0; - bool link_ready = false; - struct dp_ctrl_private *ctrl; - - if (!dp_ctrl || !panel) - return -EINVAL; - - ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - - rc = dp_ctrl_enable_stream_clocks(ctrl, panel); - if (rc) { - pr_err("failure on stream clock enable\n"); - return rc; - } - - rc = panel->hw_cfg(panel, true); - if (rc) - return rc; - - if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) { - dp_ctrl_send_phy_test_pattern(ctrl); - return 0; - } - - dp_ctrl_mst_stream_setup(ctrl, panel); - - dp_ctrl_send_video(ctrl); - - dp_ctrl_mst_send_act(ctrl); - - dp_ctrl_wait4video_ready(ctrl); - - dp_ctrl_fec_dsc_setup(ctrl); - - ctrl->stream_count++; - - link_ready = ctrl->catalog->mainlink_ready(ctrl->catalog); - pr_debug("mainlink %s\n", link_ready ? "READY" : "NOT READY"); - - return rc; -} - -static void dp_ctrl_mst_stream_pre_off(struct dp_ctrl *dp_ctrl, - struct dp_panel *panel) -{ - struct dp_ctrl_private *ctrl; - bool act_complete; - int i; - - ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - - if (!ctrl->mst_mode) - return; - - for (i = DP_STREAM_0; i < DP_STREAM_MAX; i++) { - ctrl->catalog->channel_alloc(ctrl->catalog, - i, - ctrl->mst_ch_info.slot_info[i].start_slot, - ctrl->mst_ch_info.slot_info[i].tot_slots); - } - - ctrl->catalog->trigger_act(ctrl->catalog); - msleep(20); /* needs 1 frame time */ - ctrl->catalog->read_act_complete_sts(ctrl->catalog, &act_complete); - - if (!act_complete) - pr_err("mst stream_off act trigger complete failed\n"); - else - DP_MST_DEBUG("mst stream_off ACT trigger complete SUCCESS\n"); -} - -static void dp_ctrl_stream_pre_off(struct dp_ctrl *dp_ctrl, - struct dp_panel *panel) -{ - struct dp_ctrl_private *ctrl; - - if (!dp_ctrl || !panel) { - pr_err("invalid input\n"); - return; - } - - ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - - dp_ctrl_push_idle(ctrl, panel->stream_id); - - dp_ctrl_mst_stream_pre_off(dp_ctrl, panel); -} - -static void dp_ctrl_stream_off(struct dp_ctrl *dp_ctrl, struct dp_panel *panel) -{ - struct dp_ctrl_private *ctrl; - - if (!dp_ctrl || !panel) - return; - - ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - - if (!ctrl->power_on) - return; - - panel->hw_cfg(panel, false); - - dp_ctrl_disable_stream_clocks(ctrl, panel); - ctrl->stream_count--; -} - -static int dp_ctrl_on(struct dp_ctrl *dp_ctrl, bool mst_mode, - bool fec_mode, bool shallow) -{ - int rc = 0; - struct dp_ctrl_private *ctrl; - u32 rate = 0; - - if (!dp_ctrl) { - rc = -EINVAL; - goto end; - } - - ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - - if (ctrl->power_on) - goto end; - - ctrl->mst_mode = mst_mode; - ctrl->fec_mode = fec_mode; - rate = ctrl->panel->link_info.rate; - - if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) { - pr_debug("using phy test link parameters\n"); - } else { - ctrl->link->link_params.bw_code = - drm_dp_link_rate_to_bw_code(rate); - ctrl->link->link_params.lane_count = - ctrl->panel->link_info.num_lanes; - } - - pr_debug("bw_code=%d, lane_count=%d\n", - ctrl->link->link_params.bw_code, - ctrl->link->link_params.lane_count); - - rc = dp_ctrl_link_setup(ctrl, shallow); - ctrl->power_on = true; -end: - return rc; -} - -static void dp_ctrl_off(struct dp_ctrl *dp_ctrl) -{ - struct dp_ctrl_private *ctrl; - - if (!dp_ctrl) - return; - - ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - - if (!ctrl->power_on) - return; - - dp_ctrl_configure_source_link_params(ctrl, false); - ctrl->catalog->reset(ctrl->catalog); - - /* Make sure DP is disabled before clk disable */ - wmb(); - - dp_ctrl_disable_link_clock(ctrl); - - ctrl->mst_mode = false; - ctrl->fec_mode = false; - ctrl->power_on = false; - memset(&ctrl->mst_ch_info, 0, sizeof(ctrl->mst_ch_info)); - pr_debug("DP off done\n"); -} - -static void dp_ctrl_set_mst_channel_info(struct dp_ctrl *dp_ctrl, - enum dp_stream_id strm, - u32 start_slot, u32 tot_slots) -{ - struct dp_ctrl_private *ctrl; - - if (!dp_ctrl || strm >= DP_STREAM_MAX) { - pr_err("invalid input\n"); - return; - } - - ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - - ctrl->mst_ch_info.slot_info[strm].start_slot = start_slot; - ctrl->mst_ch_info.slot_info[strm].tot_slots = tot_slots; -} - -static void dp_ctrl_isr(struct dp_ctrl *dp_ctrl) -{ - struct dp_ctrl_private *ctrl; - - if (!dp_ctrl) - return; - - ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - - ctrl->catalog->get_interrupt(ctrl->catalog); - - if (ctrl->catalog->isr & DP_CTRL_INTR_READY_FOR_VIDEO) - dp_ctrl_video_ready(ctrl); - - if (ctrl->catalog->isr & DP_CTRL_INTR_IDLE_PATTERN_SENT) - dp_ctrl_idle_patterns_sent(ctrl); - - if (ctrl->catalog->isr5 & DP_CTRL_INTR_MST_DP0_VCPF_SENT) - dp_ctrl_idle_patterns_sent(ctrl); - - if (ctrl->catalog->isr5 & DP_CTRL_INTR_MST_DP1_VCPF_SENT) - dp_ctrl_idle_patterns_sent(ctrl); -} - -struct dp_ctrl *dp_ctrl_get(struct dp_ctrl_in *in) -{ - int rc = 0; - struct dp_ctrl_private *ctrl; - struct dp_ctrl *dp_ctrl; - - if (!in->dev || !in->panel || !in->aux || - !in->link || !in->catalog) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto error; - } - - ctrl = devm_kzalloc(in->dev, sizeof(*ctrl), GFP_KERNEL); - if (!ctrl) { - rc = -ENOMEM; - goto error; - } - - init_completion(&ctrl->idle_comp); - init_completion(&ctrl->video_comp); - - /* in parameters */ - ctrl->parser = in->parser; - ctrl->panel = in->panel; - ctrl->power = in->power; - ctrl->aux = in->aux; - ctrl->link = in->link; - ctrl->catalog = in->catalog; - ctrl->dev = in->dev; - ctrl->mst_mode = false; - ctrl->fec_mode = false; - - dp_ctrl = &ctrl->dp_ctrl; - - /* out parameters */ - dp_ctrl->init = dp_ctrl_host_init; - dp_ctrl->deinit = dp_ctrl_host_deinit; - dp_ctrl->on = dp_ctrl_on; - dp_ctrl->off = dp_ctrl_off; - dp_ctrl->abort = dp_ctrl_abort; - dp_ctrl->isr = dp_ctrl_isr; - dp_ctrl->link_maintenance = dp_ctrl_link_maintenance; - dp_ctrl->process_phy_test_request = dp_ctrl_process_phy_test_request; - dp_ctrl->stream_on = dp_ctrl_stream_on; - dp_ctrl->stream_off = dp_ctrl_stream_off; - dp_ctrl->stream_pre_off = dp_ctrl_stream_pre_off; - dp_ctrl->set_mst_channel_info = dp_ctrl_set_mst_channel_info; - - return dp_ctrl; -error: - return ERR_PTR(rc); -} - -void dp_ctrl_put(struct dp_ctrl *dp_ctrl) -{ - struct dp_ctrl_private *ctrl; - - if (!dp_ctrl) - return; - - ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - - devm_kfree(ctrl->dev, ctrl); -} diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h deleted file mode 100644 index 0f855efb89b02c2cc07fdb610c43799aabb941ea..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ /dev/null @@ -1,48 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. - */ - -#ifndef _DP_CTRL_H_ -#define _DP_CTRL_H_ - -#include "dp_aux.h" -#include "dp_panel.h" -#include "dp_link.h" -#include "dp_parser.h" -#include "dp_power.h" -#include "dp_catalog.h" - -struct dp_ctrl { - int (*init)(struct dp_ctrl *dp_ctrl, bool flip, bool reset); - void (*deinit)(struct dp_ctrl *dp_ctrl); - int (*on)(struct dp_ctrl *dp_ctrl, bool mst_mode, bool fec_en, - bool shallow); - void (*off)(struct dp_ctrl *dp_ctrl); - void (*abort)(struct dp_ctrl *dp_ctrl); - void (*isr)(struct dp_ctrl *dp_ctrl); - bool (*handle_sink_request)(struct dp_ctrl *dp_ctrl); - void (*process_phy_test_request)(struct dp_ctrl *dp_ctrl); - int (*link_maintenance)(struct dp_ctrl *dp_ctrl); - int (*stream_on)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel); - void (*stream_off)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel); - void (*stream_pre_off)(struct dp_ctrl *dp_ctrl, struct dp_panel *panel); - void (*set_mst_channel_info)(struct dp_ctrl *dp_ctrl, - enum dp_stream_id strm, - u32 ch_start_slot, u32 ch_tot_slots); -}; - -struct dp_ctrl_in { - struct device *dev; - struct dp_panel *panel; - struct dp_aux *aux; - struct dp_link *link; - struct dp_parser *parser; - struct dp_power *power; - struct dp_catalog_ctrl *catalog; -}; - -struct dp_ctrl *dp_ctrl_get(struct dp_ctrl_in *in); -void dp_ctrl_put(struct dp_ctrl *dp_ctrl); - -#endif /* _DP_CTRL_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c deleted file mode 100644 index e5813034f71eac600c21539b573fb3267c2293cd..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ /dev/null @@ -1,2101 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ - -#include -#include - -#include "dp_power.h" -#include "dp_catalog.h" -#include "dp_aux.h" -#include "dp_debug.h" -#include "drm_connector.h" -#include "sde_connector.h" -#include "dp_display.h" - -#define DEBUG_NAME "drm_dp" - -struct dp_debug_private { - struct dentry *root; - u8 *edid; - u32 edid_size; - - u8 *dpcd; - u32 dpcd_size; - - u32 mst_con_id; - - char exe_mode[SZ_32]; - char reg_dump[SZ_32]; - - struct dp_hpd *hpd; - struct dp_link *link; - struct dp_panel *panel; - struct dp_aux *aux; - struct dp_catalog *catalog; - struct drm_connector **connector; - struct device *dev; - struct dp_debug dp_debug; - struct dp_parser *parser; - struct dp_ctrl *ctrl; - struct mutex lock; -}; - -static int dp_debug_get_edid_buf(struct dp_debug_private *debug) -{ - int rc = 0; - - if (!debug->edid) { - debug->edid = devm_kzalloc(debug->dev, SZ_256, GFP_KERNEL); - if (!debug->edid) { - rc = -ENOMEM; - goto end; - } - - debug->edid_size = SZ_256; - } -end: - return rc; -} - -static int dp_debug_get_dpcd_buf(struct dp_debug_private *debug) -{ - int rc = 0; - - if (!debug->dpcd) { - debug->dpcd = devm_kzalloc(debug->dev, SZ_4K, GFP_KERNEL); - if (!debug->dpcd) { - rc = -ENOMEM; - goto end; - } - - debug->dpcd_size = SZ_4K; - } -end: - return rc; -} - -static ssize_t dp_debug_write_edid(struct file *file, - const char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - u8 *buf = NULL, *buf_t = NULL, *edid = NULL; - const int char_to_nib = 2; - size_t edid_size = 0; - size_t size = 0, edid_buf_index = 0; - ssize_t rc = count; - - if (!debug) - return -ENODEV; - - mutex_lock(&debug->lock); - - if (*ppos) - goto bail; - - size = min_t(size_t, count, SZ_1K); - - buf = kzalloc(size, GFP_KERNEL); - if (ZERO_OR_NULL_PTR(buf)) { - rc = -ENOMEM; - goto bail; - } - - if (copy_from_user(buf, user_buff, size)) - goto bail; - - edid_size = size / char_to_nib; - buf_t = buf; - - if (dp_debug_get_edid_buf(debug)) - goto bail; - - if (edid_size != debug->edid_size) { - pr_debug("realloc debug edid\n"); - - if (debug->edid) { - devm_kfree(debug->dev, debug->edid); - - debug->edid = devm_kzalloc(debug->dev, - edid_size, GFP_KERNEL); - if (!debug->edid) { - rc = -ENOMEM; - goto bail; - } - - debug->edid_size = edid_size; - - debug->aux->set_sim_mode(debug->aux, - debug->dp_debug.sim_mode, - debug->edid, debug->dpcd); - } - } - - while (edid_size--) { - char t[3]; - int d; - - memcpy(t, buf_t, sizeof(char) * char_to_nib); - t[char_to_nib] = '\0'; - - if (kstrtoint(t, 16, &d)) { - pr_err("kstrtoint error\n"); - goto bail; - } - - if (debug->edid && (edid_buf_index < debug->edid_size)) - debug->edid[edid_buf_index++] = d; - - buf_t += char_to_nib; - } - - edid = debug->edid; -bail: - kfree(buf); - debug->panel->set_edid(debug->panel, edid); - - /* - * print edid status as this code is executed - * only while running in debug mode which is manually - * triggered by a tester or a script. - */ - pr_info("[%s]\n", edid ? "SET" : "CLEAR"); - - mutex_unlock(&debug->lock); - return rc; -} - -static ssize_t dp_debug_write_dpcd(struct file *file, - const char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - u8 *buf = NULL, *buf_t = NULL, *dpcd = NULL; - const int char_to_nib = 2; - size_t dpcd_size = 0; - size_t size = 0, dpcd_buf_index = 0; - ssize_t rc = count; - char offset_ch[5]; - u32 offset, data_len; - const u32 dp_receiver_cap_size = 16; - - if (!debug) - return -ENODEV; - - mutex_lock(&debug->lock); - - if (*ppos) - goto bail; - - size = min_t(size_t, count, SZ_2K); - - if (size <= char_to_nib) - goto bail; - - buf = kzalloc(size, GFP_KERNEL); - if (ZERO_OR_NULL_PTR(buf)) { - rc = -ENOMEM; - goto bail; - } - - if (copy_from_user(buf, user_buff, size)) - goto bail; - - memcpy(offset_ch, buf, 4); - offset_ch[4] = '\0'; - - if (kstrtoint(offset_ch, 16, &offset)) { - pr_err("offset kstrtoint error\n"); - goto bail; - } - - if (dp_debug_get_dpcd_buf(debug)) - goto bail; - - if (offset == 0xFFFF) { - pr_err("clearing dpcd\n"); - memset(debug->dpcd, 0, debug->dpcd_size); - goto bail; - } - - size -= 4; - - dpcd_size = size / char_to_nib; - data_len = dpcd_size; - buf_t = buf + 4; - - dpcd_buf_index = offset; - - while (dpcd_size--) { - char t[3]; - int d; - - memcpy(t, buf_t, sizeof(char) * char_to_nib); - t[char_to_nib] = '\0'; - - if (kstrtoint(t, 16, &d)) { - pr_err("kstrtoint error\n"); - goto bail; - } - - if (dpcd_buf_index < debug->dpcd_size) - debug->dpcd[dpcd_buf_index++] = d; - - buf_t += char_to_nib; - } - - dpcd = debug->dpcd; -bail: - kfree(buf); - - /* - * Reset panel's dpcd in case of any failure. Also, set the - * panel's dpcd only if a full dpcd is provided with offset as 0. - */ - if (!dpcd || (!offset && (data_len == dp_receiver_cap_size))) { - debug->panel->set_dpcd(debug->panel, dpcd); - - /* - * print dpcd status as this code is executed - * only while running in debug mode which is manually - * triggered by a tester or a script. - */ - pr_info("[%s]\n", dpcd ? "SET" : "CLEAR"); - } else - debug->aux->dpcd_updated(debug->aux); - - mutex_unlock(&debug->lock); - return rc; -} - -static ssize_t dp_debug_read_dpcd(struct file *file, - char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char *buf; - int const buf_size = SZ_4K; - u32 offset = 0; - u32 len = 0; - - if (!debug || !debug->aux || !debug->dpcd) - return -ENODEV; - - if (*ppos) - return 0; - - buf = kzalloc(buf_size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - len += snprintf(buf, buf_size, "0x%x", debug->aux->reg); - - if (!debug->aux->read) { - while (1) { - if (debug->aux->reg + offset >= buf_size || - offset >= debug->aux->size) - break; - - len += snprintf(buf + len, buf_size - len, "0x%x", - debug->dpcd[debug->aux->reg + offset++]); - } - - if (debug->dp_debug.sim_mode && debug->aux->dpcd_updated) - debug->aux->dpcd_updated(debug->aux); - } - - if (!copy_to_user(user_buff, buf, len)) - *ppos += len; - - kfree(buf); - return len; -} - -static ssize_t dp_debug_write_hpd(struct file *file, - const char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char buf[SZ_8]; - size_t len = 0; - int const hpd_data_mask = 0x7; - int hpd = 0; - - if (!debug) - return -ENODEV; - - if (*ppos) - return 0; - - /* Leave room for termination char */ - len = min_t(size_t, count, SZ_8 - 1); - if (copy_from_user(buf, user_buff, len)) - goto end; - - buf[len] = '\0'; - - if (kstrtoint(buf, 10, &hpd) != 0) - goto end; - - hpd &= hpd_data_mask; - - debug->dp_debug.psm_enabled = !!(hpd & BIT(1)); - - debug->hpd->simulate_connect(debug->hpd, !!(hpd & BIT(0))); -end: - return len; -} - -static ssize_t dp_debug_write_edid_modes(struct file *file, - const char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char buf[SZ_32]; - size_t len = 0; - int hdisplay = 0, vdisplay = 0, vrefresh = 0, aspect_ratio; - - if (!debug) - return -ENODEV; - - if (*ppos) - goto end; - - /* Leave room for termination char */ - len = min_t(size_t, count, SZ_32 - 1); - if (copy_from_user(buf, user_buff, len)) - goto clear; - - buf[len] = '\0'; - - if (sscanf(buf, "%d %d %d %d", &hdisplay, &vdisplay, &vrefresh, - &aspect_ratio) != 4) - goto clear; - - if (!hdisplay || !vdisplay || !vrefresh) - goto clear; - - debug->dp_debug.debug_en = true; - debug->dp_debug.hdisplay = hdisplay; - debug->dp_debug.vdisplay = vdisplay; - debug->dp_debug.vrefresh = vrefresh; - debug->dp_debug.aspect_ratio = aspect_ratio; - goto end; -clear: - pr_debug("clearing debug modes\n"); - debug->dp_debug.debug_en = false; -end: - return len; -} - -static ssize_t dp_debug_write_edid_modes_mst(struct file *file, - const char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - struct dp_mst_connector *mst_connector; - char buf[SZ_512]; - char *read_buf; - size_t len = 0; - - int hdisplay = 0, vdisplay = 0, vrefresh = 0, aspect_ratio = 0; - int con_id = 0, offset = 0, debug_en = 0; - bool in_list = false; - - if (!debug) - return -ENODEV; - - if (*ppos) - goto end; - - len = min_t(size_t, count, SZ_512 - 1); - if (copy_from_user(buf, user_buff, len)) - goto end; - - buf[len] = '\0'; - read_buf = buf; - - mutex_lock(&debug->dp_debug.dp_mst_connector_list.lock); - while (sscanf(read_buf, "%d %d %d %d %d %d%n", &debug_en, &con_id, - &hdisplay, &vdisplay, &vrefresh, &aspect_ratio, - &offset) == 6) { - list_for_each_entry(mst_connector, - &debug->dp_debug.dp_mst_connector_list.list, - list) { - if (mst_connector->con_id == con_id) { - in_list = true; - mst_connector->debug_en = (bool) debug_en; - mst_connector->hdisplay = hdisplay; - mst_connector->vdisplay = vdisplay; - mst_connector->vrefresh = vrefresh; - mst_connector->aspect_ratio = aspect_ratio; - } - } - - if (!in_list) - pr_debug("dp connector id %d is invalid\n", con_id); - - in_list = false; - read_buf += offset; - } - mutex_unlock(&debug->dp_debug.dp_mst_connector_list.lock); -end: - return len; -} - -static ssize_t dp_debug_write_mst_con_id(struct file *file, - const char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - struct dp_mst_connector *mst_connector; - char buf[SZ_32]; - size_t len = 0; - int con_id = 0, status; - bool in_list = false; - const int dp_en = BIT(3), hpd_high = BIT(7), hpd_irq = BIT(8); - int vdo = dp_en | hpd_high | hpd_irq; - - if (!debug) - return -ENODEV; - - if (*ppos) - goto end; - - /* Leave room for termination char */ - len = min_t(size_t, count, SZ_32 - 1); - if (copy_from_user(buf, user_buff, len)) - goto clear; - - buf[len] = '\0'; - - if (sscanf(buf, "%d %d", &con_id, &status) != 2) { - len = 0; - goto end; - } - - if (!con_id) - goto clear; - - /* Verify that the connector id is for a valid mst connector. */ - mutex_lock(&debug->dp_debug.dp_mst_connector_list.lock); - list_for_each_entry(mst_connector, - &debug->dp_debug.dp_mst_connector_list.list, list) { - if (mst_connector->con_id == con_id) { - in_list = true; - debug->mst_con_id = con_id; - mst_connector->state = status; - break; - } - } - mutex_unlock(&debug->dp_debug.dp_mst_connector_list.lock); - - if (!in_list) - pr_err("invalid connector id %u\n", con_id); - else if (status != connector_status_unknown) { - debug->dp_debug.mst_hpd_sim = true; - debug->hpd->simulate_attention(debug->hpd, vdo); - } - - goto end; -clear: - pr_debug("clearing mst_con_id\n"); - debug->mst_con_id = 0; -end: - return len; -} - -static ssize_t dp_debug_bw_code_write(struct file *file, - const char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char buf[SZ_8]; - size_t len = 0; - u32 max_bw_code = 0; - - if (!debug) - return -ENODEV; - - if (*ppos) - return 0; - - /* Leave room for termination char */ - len = min_t(size_t, count, SZ_8 - 1); - if (copy_from_user(buf, user_buff, len)) - return 0; - - buf[len] = '\0'; - - if (kstrtoint(buf, 10, &max_bw_code) != 0) - return 0; - - if (!is_link_rate_valid(max_bw_code)) { - pr_err("Unsupported bw code %d\n", max_bw_code); - return len; - } - debug->panel->max_bw_code = max_bw_code; - pr_debug("max_bw_code: %d\n", max_bw_code); - - return len; -} - -static ssize_t dp_debug_mst_mode_read(struct file *file, - char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char buf[64]; - ssize_t len; - - len = scnprintf(buf, sizeof(buf), - "mst_mode = %d, mst_state = %d\n", - debug->parser->has_mst, - debug->panel->mst_state); - - return simple_read_from_buffer(user_buff, count, ppos, buf, len); -} - -static ssize_t dp_debug_mst_mode_write(struct file *file, - const char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char buf[SZ_8]; - size_t len = 0; - u32 mst_mode = 0; - - if (!debug) - return -ENODEV; - - if (*ppos) - return 0; - - len = min_t(size_t, count, SZ_8 - 1); - if (copy_from_user(buf, user_buff, len)) - return 0; - - buf[len] = '\0'; - - if (kstrtoint(buf, 10, &mst_mode) != 0) - return 0; - - debug->parser->has_mst = mst_mode ? true : false; - pr_debug("mst_enable: %d\n", mst_mode); - - return len; -} - -static ssize_t dp_debug_max_pclk_khz_write(struct file *file, - const char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char buf[SZ_8]; - size_t len = 0; - u32 max_pclk = 0; - - if (!debug) - return -ENODEV; - - if (*ppos) - return 0; - - len = min_t(size_t, count, SZ_8 - 1); - if (copy_from_user(buf, user_buff, len)) - return 0; - - buf[len] = '\0'; - - if (kstrtoint(buf, 10, &max_pclk) != 0) - return 0; - - if (max_pclk > debug->parser->max_pclk_khz) - pr_err("requested: %d, max_pclk_khz:%d\n", max_pclk, - debug->parser->max_pclk_khz); - else - debug->dp_debug.max_pclk_khz = max_pclk; - - pr_debug("max_pclk_khz: %d\n", max_pclk); - - return len; -} - -static ssize_t dp_debug_max_pclk_khz_read(struct file *file, - char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char *buf; - u32 len = 0; - - if (!debug) - return -ENODEV; - - if (*ppos) - return 0; - - buf = kzalloc(SZ_4K, GFP_KERNEL); - if (ZERO_OR_NULL_PTR(buf)) - return -ENOMEM; - - len += snprintf(buf + len, (SZ_4K - len), - "max_pclk_khz = %d, org: %d\n", - debug->dp_debug.max_pclk_khz, - debug->parser->max_pclk_khz); - - if (copy_to_user(user_buff, buf, len)) { - kfree(buf); - return -EFAULT; - } - - *ppos += len; - kfree(buf); - return len; -} - -static ssize_t dp_debug_mst_sideband_mode_write(struct file *file, - const char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char buf[SZ_8]; - size_t len = 0; - int mst_sideband_mode = 0; - u32 mst_port_cnt = 0; - - if (!debug) - return -ENODEV; - - /* Leave room for termination char */ - len = min_t(size_t, count, SZ_8 - 1); - if (copy_from_user(buf, user_buff, len)) - return -EFAULT; - - buf[len] = '\0'; - - if (sscanf(buf, "%d %u", &mst_sideband_mode, &mst_port_cnt) != 2) { - pr_err("invalid input\n"); - return -EINVAL; - } - - if (mst_port_cnt > DP_MST_SIM_MAX_PORTS) { - pr_err("port cnt:%d exceeding max:%d\n", mst_port_cnt, - DP_MST_SIM_MAX_PORTS); - return -EINVAL; - } - - debug->parser->has_mst_sideband = mst_sideband_mode ? true : false; - debug->dp_debug.mst_port_cnt = mst_port_cnt; - pr_debug("mst_sideband_mode: %d port_cnt:%d\n", - mst_sideband_mode, mst_port_cnt); - return count; -} - -static ssize_t dp_debug_widebus_mode_write(struct file *file, - const char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char buf[SZ_8]; - size_t len = 0; - u32 widebus_mode = 0; - - if (!debug || !debug->parser) - return -ENODEV; - - if (*ppos) - return 0; - - len = min_t(size_t, count, SZ_8 - 1); - if (copy_from_user(buf, user_buff, len)) - return -EFAULT; - - buf[len] = '\0'; - - if (kstrtoint(buf, 10, &widebus_mode) != 0) - return -EINVAL; - - debug->parser->has_widebus = widebus_mode ? true : false; - pr_debug("widebus_enable: %d\n", widebus_mode); - - return len; -} - -static ssize_t dp_debug_tpg_write(struct file *file, - const char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char buf[SZ_8]; - size_t len = 0; - u32 tpg_state = 0; - - if (!debug) - return -ENODEV; - - if (*ppos) - return 0; - - /* Leave room for termination char */ - len = min_t(size_t, count, SZ_8 - 1); - if (copy_from_user(buf, user_buff, len)) - goto bail; - - buf[len] = '\0'; - - if (kstrtoint(buf, 10, &tpg_state) != 0) - goto bail; - - tpg_state &= 0x1; - pr_debug("tpg_state: %d\n", tpg_state); - - if (tpg_state == debug->dp_debug.tpg_state) - goto bail; - - if (debug->panel) - debug->panel->tpg_config(debug->panel, tpg_state); - - debug->dp_debug.tpg_state = tpg_state; -bail: - return len; -} - -static ssize_t dp_debug_write_exe_mode(struct file *file, - const char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char buf[SZ_32]; - size_t len = 0; - - if (!debug) - return -ENODEV; - - if (*ppos) - return 0; - - len = min_t(size_t, count, SZ_32 - 1); - if (copy_from_user(buf, user_buff, len)) - goto end; - - buf[len] = '\0'; - - if (sscanf(buf, "%3s", debug->exe_mode) != 1) - goto end; - - if (strcmp(debug->exe_mode, "hw") && - strcmp(debug->exe_mode, "sw") && - strcmp(debug->exe_mode, "all")) - goto end; - - debug->catalog->set_exe_mode(debug->catalog, debug->exe_mode); -end: - return len; -} - -static ssize_t dp_debug_read_connected(struct file *file, - char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char buf[SZ_8]; - u32 len = 0; - - if (!debug) - return -ENODEV; - - if (*ppos) - return 0; - - len += snprintf(buf, SZ_8, "%d\n", debug->hpd->hpd_high); - - if (copy_to_user(user_buff, buf, len)) - return -EFAULT; - - *ppos += len; - return len; -} - -static ssize_t dp_debug_write_hdcp(struct file *file, - const char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char buf[SZ_8]; - size_t len = 0; - int hdcp = 0; - - if (!debug) - return -ENODEV; - - if (*ppos) - return 0; - - /* Leave room for termination char */ - len = min_t(size_t, count, SZ_8 - 1); - if (copy_from_user(buf, user_buff, len)) - goto end; - - buf[len] = '\0'; - - if (kstrtoint(buf, 10, &hdcp) != 0) - goto end; - - debug->dp_debug.hdcp_disabled = !hdcp; -end: - return len; -} - -static ssize_t dp_debug_read_hdcp(struct file *file, - char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - u32 len = 0; - - if (!debug) - return -ENODEV; - - if (*ppos) - return 0; - - len = sizeof(debug->dp_debug.hdcp_status); - - if (copy_to_user(user_buff, debug->dp_debug.hdcp_status, len)) - return -EFAULT; - - *ppos += len; - return len; -} - -static int dp_debug_check_buffer_overflow(int rc, int *max_size, int *len) -{ - if (rc >= *max_size) { - pr_err("buffer overflow\n"); - return -EINVAL; - } - *len += rc; - *max_size = SZ_4K - *len; - - return 0; -} - -static ssize_t dp_debug_read_edid_modes(struct file *file, - char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char *buf; - u32 len = 0, ret = 0, max_size = SZ_4K; - int rc = 0; - struct drm_connector *connector; - struct drm_display_mode *mode; - - if (!debug) { - pr_err("invalid data\n"); - rc = -ENODEV; - goto error; - } - - connector = *debug->connector; - - if (!connector) { - pr_err("connector is NULL\n"); - rc = -EINVAL; - goto error; - } - - if (*ppos) - goto error; - - buf = kzalloc(SZ_4K, GFP_KERNEL); - if (ZERO_OR_NULL_PTR(buf)) { - rc = -ENOMEM; - goto error; - } - - mutex_lock(&connector->dev->mode_config.mutex); - list_for_each_entry(mode, &connector->modes, head) { - ret = snprintf(buf + len, max_size, - "%s %d %d %d %d %d 0x%x\n", - mode->name, mode->vrefresh, mode->picture_aspect_ratio, - mode->htotal, mode->vtotal, mode->clock, mode->flags); - if (dp_debug_check_buffer_overflow(ret, &max_size, &len)) - break; - } - mutex_unlock(&connector->dev->mode_config.mutex); - - if (copy_to_user(user_buff, buf, len)) { - kfree(buf); - rc = -EFAULT; - goto error; - } - - *ppos += len; - kfree(buf); - - return len; -error: - return rc; -} - -static ssize_t dp_debug_read_edid_modes_mst(struct file *file, - char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - struct dp_mst_connector *mst_connector; - char *buf; - u32 len = 0, ret = 0, max_size = SZ_4K; - int rc = 0; - struct drm_connector *connector; - struct drm_display_mode *mode; - bool in_list = false; - - if (!debug) { - pr_err("invalid data\n"); - rc = -ENODEV; - goto error; - } - - mutex_lock(&debug->dp_debug.dp_mst_connector_list.lock); - list_for_each_entry(mst_connector, - &debug->dp_debug.dp_mst_connector_list.list, list) { - if (mst_connector->con_id == debug->mst_con_id) { - connector = mst_connector->conn; - in_list = true; - } - } - mutex_unlock(&debug->dp_debug.dp_mst_connector_list.lock); - - if (!in_list) { - pr_err("connector %u not in mst list\n", debug->mst_con_id); - rc = -EINVAL; - goto error; - } - - if (!connector) { - pr_err("connector is NULL\n"); - rc = -EINVAL; - goto error; - } - - if (*ppos) - goto error; - - buf = kzalloc(SZ_4K, GFP_KERNEL); - if (!buf) { - rc = -ENOMEM; - goto error; - } - - mutex_lock(&connector->dev->mode_config.mutex); - list_for_each_entry(mode, &connector->modes, head) { - ret = snprintf(buf + len, max_size, - "%s %d %d %d %d %d 0x%x\n", - mode->name, mode->vrefresh, - mode->picture_aspect_ratio, mode->htotal, - mode->vtotal, mode->clock, mode->flags); - if (dp_debug_check_buffer_overflow(ret, &max_size, &len)) - break; - } - mutex_unlock(&connector->dev->mode_config.mutex); - - if (copy_to_user(user_buff, buf, len)) { - kfree(buf); - rc = -EFAULT; - goto error; - } - - *ppos += len; - kfree(buf); - - return len; -error: - return rc; -} - -static ssize_t dp_debug_read_mst_con_id(struct file *file, - char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char *buf; - u32 len = 0, ret = 0, max_size = SZ_4K; - int rc = 0; - - if (!debug) { - pr_err("invalid data\n"); - rc = -ENODEV; - goto error; - } - - if (*ppos) - goto error; - - buf = kzalloc(SZ_4K, GFP_KERNEL); - if (!buf) { - rc = -ENOMEM; - goto error; - } - - ret = snprintf(buf, max_size, "%u\n", debug->mst_con_id); - len += ret; - - if (copy_to_user(user_buff, buf, len)) { - kfree(buf); - rc = -EFAULT; - goto error; - } - - *ppos += len; - kfree(buf); - - return len; -error: - return rc; -} - -static ssize_t dp_debug_read_mst_conn_info(struct file *file, - char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - struct dp_mst_connector *mst_connector; - char *buf; - u32 len = 0, ret = 0, max_size = SZ_4K; - int rc = 0; - struct drm_connector *connector; - - if (!debug) { - pr_err("invalid data\n"); - rc = -ENODEV; - goto error; - } - - if (*ppos) - goto error; - - buf = kzalloc(SZ_4K, GFP_KERNEL); - if (!buf) { - rc = -ENOMEM; - goto error; - } - - mutex_lock(&debug->dp_debug.dp_mst_connector_list.lock); - list_for_each_entry(mst_connector, - &debug->dp_debug.dp_mst_connector_list.list, list) { - /* Do not print info for head node */ - if (mst_connector->con_id == -1) - continue; - - connector = mst_connector->conn; - - if (!connector) { - pr_err("connector for id %d is NULL\n", - mst_connector->con_id); - continue; - } - - ret = scnprintf(buf + len, max_size, - "conn name:%s, conn id:%d state:%d\n", - connector->name, connector->base.id, - connector->status); - if (dp_debug_check_buffer_overflow(ret, &max_size, &len)) - break; - } - mutex_unlock(&debug->dp_debug.dp_mst_connector_list.lock); - - if (copy_to_user(user_buff, buf, len)) { - kfree(buf); - rc = -EFAULT; - goto error; - } - - *ppos += len; - kfree(buf); - - return len; -error: - return rc; -} - -static ssize_t dp_debug_read_info(struct file *file, char __user *user_buff, - size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char *buf; - u32 len = 0, rc = 0; - u32 max_size = SZ_4K; - - if (!debug) - return -ENODEV; - - if (*ppos) - return 0; - - buf = kzalloc(SZ_4K, GFP_KERNEL); - if (ZERO_OR_NULL_PTR(buf)) - return -ENOMEM; - - rc = snprintf(buf + len, max_size, "\tstate=0x%x\n", debug->aux->state); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, "\tlink_rate=%u\n", - debug->panel->link_info.rate); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, "\tnum_lanes=%u\n", - debug->panel->link_info.num_lanes); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, "\tresolution=%dx%d@%dHz\n", - debug->panel->pinfo.h_active, - debug->panel->pinfo.v_active, - debug->panel->pinfo.refresh_rate); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, "\tpclock=%dKHz\n", - debug->panel->pinfo.pixel_clk_khz); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, "\tbpp=%d\n", - debug->panel->pinfo.bpp); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - /* Link Information */ - rc = snprintf(buf + len, max_size, "\ttest_req=%s\n", - dp_link_get_test_name(debug->link->sink_request)); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, - "\tlane_count=%d\n", debug->link->link_params.lane_count); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, - "\tbw_code=%d\n", debug->link->link_params.bw_code); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, - "\tv_level=%d\n", debug->link->phy_params.v_level); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, - "\tp_level=%d\n", debug->link->phy_params.p_level); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - if (copy_to_user(user_buff, buf, len)) - goto error; - - *ppos += len; - - kfree(buf); - return len; -error: - kfree(buf); - return -EINVAL; -} - -static ssize_t dp_debug_bw_code_read(struct file *file, - char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char *buf; - u32 len = 0; - - if (!debug) - return -ENODEV; - - if (*ppos) - return 0; - - buf = kzalloc(SZ_4K, GFP_KERNEL); - if (ZERO_OR_NULL_PTR(buf)) - return -ENOMEM; - - len += snprintf(buf + len, (SZ_4K - len), - "max_bw_code = %d\n", debug->panel->max_bw_code); - - if (copy_to_user(user_buff, buf, len)) { - kfree(buf); - return -EFAULT; - } - - *ppos += len; - kfree(buf); - return len; -} - -static ssize_t dp_debug_tpg_read(struct file *file, - char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char buf[SZ_8]; - u32 len = 0; - - if (!debug) - return -ENODEV; - - if (*ppos) - return 0; - - len += snprintf(buf, SZ_8, "%d\n", debug->dp_debug.tpg_state); - - if (copy_to_user(user_buff, buf, len)) - return -EFAULT; - - *ppos += len; - return len; -} - -static ssize_t dp_debug_write_hdr(struct file *file, - const char __user *user_buff, size_t count, loff_t *ppos) -{ - struct drm_connector *connector; - struct sde_connector *c_conn; - struct sde_connector_state *c_state; - struct dp_debug_private *debug = file->private_data; - char buf[SZ_512]; - size_t len = 0; - - if (!debug) - return -ENODEV; - - if (*ppos) - return 0; - - connector = *debug->connector; - c_conn = to_sde_connector(connector); - c_state = to_sde_connector_state(connector->state); - - /* Leave room for termination char */ - len = min_t(size_t, count, SZ_512 - 1); - if (copy_from_user(buf, user_buff, len)) - goto end; - - buf[len] = '\0'; - - if (sscanf(buf, "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", - &c_state->hdr_meta.hdr_supported, - &c_state->hdr_meta.hdr_state, - &c_state->hdr_meta.eotf, - &c_state->hdr_meta.display_primaries_x[0], - &c_state->hdr_meta.display_primaries_x[1], - &c_state->hdr_meta.display_primaries_x[2], - &c_state->hdr_meta.display_primaries_y[0], - &c_state->hdr_meta.display_primaries_y[1], - &c_state->hdr_meta.display_primaries_y[2], - &c_state->hdr_meta.white_point_x, - &c_state->hdr_meta.white_point_y, - &c_state->hdr_meta.max_luminance, - &c_state->hdr_meta.min_luminance, - &c_state->hdr_meta.max_content_light_level, - &c_state->hdr_meta.max_average_light_level) != 15) { - pr_err("invalid input\n"); - len = -EINVAL; - } - - debug->panel->setup_hdr(debug->panel, &c_state->hdr_meta, false, 0); -end: - return len; -} - -static ssize_t dp_debug_read_hdr(struct file *file, - char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char *buf; - u32 len = 0, i; - u32 max_size = SZ_4K; - int rc = 0; - struct drm_connector *connector; - struct sde_connector *c_conn; - struct sde_connector_state *c_state; - struct drm_msm_ext_hdr_metadata *hdr; - - if (!debug) { - pr_err("invalid data\n"); - rc = -ENODEV; - goto error; - } - - connector = *debug->connector; - - if (!connector) { - pr_err("connector is NULL\n"); - rc = -EINVAL; - goto error; - } - - if (*ppos) - goto error; - - buf = kzalloc(SZ_4K, GFP_KERNEL); - if (ZERO_OR_NULL_PTR(buf)) { - rc = -ENOMEM; - goto error; - } - - c_conn = to_sde_connector(connector); - c_state = to_sde_connector_state(connector->state); - - hdr = &c_state->hdr_meta; - - rc = snprintf(buf + len, max_size, - "============SINK HDR PARAMETERS===========\n"); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, "eotf = %d\n", - connector->hdr_eotf); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, "type_one = %d\n", - connector->hdr_metadata_type_one); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, "max_luminance = %d\n", - connector->hdr_max_luminance); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, "avg_luminance = %d\n", - connector->hdr_avg_luminance); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, "min_luminance = %d\n", - connector->hdr_min_luminance); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, - "============VIDEO HDR PARAMETERS===========\n"); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, "hdr_state = %d\n", hdr->hdr_state); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, "hdr_supported = %d\n", - hdr->hdr_supported); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, "eotf = %d\n", hdr->eotf); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, "white_point_x = %d\n", - hdr->white_point_x); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, "white_point_y = %d\n", - hdr->white_point_y); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, "max_luminance = %d\n", - hdr->max_luminance); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, "min_luminance = %d\n", - hdr->min_luminance); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, "max_content_light_level = %d\n", - hdr->max_content_light_level); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, "min_content_light_level = %d\n", - hdr->max_average_light_level); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - for (i = 0; i < HDR_PRIMARIES_COUNT; i++) { - rc = snprintf(buf + len, max_size, "primaries_x[%d] = %d\n", - i, hdr->display_primaries_x[i]); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - - rc = snprintf(buf + len, max_size, "primaries_y[%d] = %d\n", - i, hdr->display_primaries_y[i]); - if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) - goto error; - } - - if (copy_to_user(user_buff, buf, len)) { - kfree(buf); - rc = -EFAULT; - goto error; - } - - *ppos += len; - kfree(buf); - - return len; -error: - return rc; -} - -static void dp_debug_set_sim_mode(struct dp_debug_private *debug, bool sim) -{ - if (sim) { - if (dp_debug_get_edid_buf(debug)) - return; - - if (dp_debug_get_dpcd_buf(debug)) { - devm_kfree(debug->dev, debug->edid); - debug->edid = NULL; - return; - } - - debug->dp_debug.sim_mode = true; - debug->aux->set_sim_mode(debug->aux, true, - debug->edid, debug->dpcd); - } else { - debug->aux->abort(debug->aux); - debug->ctrl->abort(debug->ctrl); - - debug->aux->set_sim_mode(debug->aux, false, NULL, NULL); - debug->dp_debug.sim_mode = false; - - debug->panel->set_edid(debug->panel, 0); - if (debug->edid) { - devm_kfree(debug->dev, debug->edid); - debug->edid = NULL; - } - - debug->panel->set_dpcd(debug->panel, 0); - if (debug->dpcd) { - devm_kfree(debug->dev, debug->dpcd); - debug->dpcd = NULL; - } - } - - /* - * print simulation status as this code is executed - * only while running in debug mode which is manually - * triggered by a tester or a script. - */ - pr_info("%s\n", sim ? "[ON]" : "[OFF]"); -} - -static ssize_t dp_debug_write_sim(struct file *file, - const char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char buf[SZ_8]; - size_t len = 0; - int sim; - - if (!debug) - return -ENODEV; - - if (*ppos) - return 0; - - mutex_lock(&debug->lock); - - /* Leave room for termination char */ - len = min_t(size_t, count, SZ_8 - 1); - if (copy_from_user(buf, user_buff, len)) - goto end; - - buf[len] = '\0'; - - if (kstrtoint(buf, 10, &sim) != 0) - goto end; - - dp_debug_set_sim_mode(debug, sim); -end: - mutex_unlock(&debug->lock); - return len; -} - -static ssize_t dp_debug_write_attention(struct file *file, - const char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char buf[SZ_8]; - size_t len = 0; - int vdo; - - if (!debug) - return -ENODEV; - - if (*ppos) - return 0; - - /* Leave room for termination char */ - len = min_t(size_t, count, SZ_8 - 1); - if (copy_from_user(buf, user_buff, len)) - goto end; - - buf[len] = '\0'; - - if (kstrtoint(buf, 10, &vdo) != 0) - goto end; - - debug->hpd->simulate_attention(debug->hpd, vdo); -end: - return len; -} - -static ssize_t dp_debug_write_dump(struct file *file, - const char __user *user_buff, size_t count, loff_t *ppos) -{ - struct dp_debug_private *debug = file->private_data; - char buf[SZ_32]; - size_t len = 0; - - if (!debug) - return -ENODEV; - - if (*ppos) - return 0; - - /* Leave room for termination char */ - len = min_t(size_t, count, SZ_32 - 1); - if (copy_from_user(buf, user_buff, len)) - goto end; - - buf[len] = '\0'; - - if (sscanf(buf, "%31s", debug->reg_dump) != 1) - goto end; - - /* qfprom register dump not supported */ - if (!strcmp(debug->reg_dump, "qfprom_physical")) - strlcpy(debug->reg_dump, "clear", sizeof(debug->reg_dump)); -end: - return len; -} - -static ssize_t dp_debug_read_dump(struct file *file, - char __user *user_buff, size_t count, loff_t *ppos) -{ - int rc = 0; - struct dp_debug_private *debug = file->private_data; - u8 *buf = NULL; - u32 len = 0; - char prefix[SZ_32]; - - if (!debug) - return -ENODEV; - - if (*ppos) - return 0; - - if (!debug->hpd->hpd_high || !strlen(debug->reg_dump)) - goto end; - - rc = debug->catalog->get_reg_dump(debug->catalog, - debug->reg_dump, &buf, &len); - if (rc) - goto end; - - snprintf(prefix, sizeof(prefix), "%s: ", debug->reg_dump); - print_hex_dump(KERN_DEBUG, prefix, DUMP_PREFIX_NONE, - 16, 4, buf, len, false); - - if (copy_to_user(user_buff, buf, len)) - return -EFAULT; - - *ppos += len; -end: - return len; -} - -static const struct file_operations dp_debug_fops = { - .open = simple_open, - .read = dp_debug_read_info, -}; - -static const struct file_operations edid_modes_fops = { - .open = simple_open, - .read = dp_debug_read_edid_modes, - .write = dp_debug_write_edid_modes, -}; - -static const struct file_operations edid_modes_mst_fops = { - .open = simple_open, - .read = dp_debug_read_edid_modes_mst, - .write = dp_debug_write_edid_modes_mst, -}; - -static const struct file_operations mst_conn_info_fops = { - .open = simple_open, - .read = dp_debug_read_mst_conn_info, -}; - -static const struct file_operations mst_con_id_fops = { - .open = simple_open, - .read = dp_debug_read_mst_con_id, - .write = dp_debug_write_mst_con_id, -}; - -static const struct file_operations hpd_fops = { - .open = simple_open, - .write = dp_debug_write_hpd, -}; - -static const struct file_operations edid_fops = { - .open = simple_open, - .write = dp_debug_write_edid, -}; - -static const struct file_operations dpcd_fops = { - .open = simple_open, - .write = dp_debug_write_dpcd, - .read = dp_debug_read_dpcd, -}; - -static const struct file_operations connected_fops = { - .open = simple_open, - .read = dp_debug_read_connected, -}; - -static const struct file_operations bw_code_fops = { - .open = simple_open, - .read = dp_debug_bw_code_read, - .write = dp_debug_bw_code_write, -}; -static const struct file_operations exe_mode_fops = { - .open = simple_open, - .write = dp_debug_write_exe_mode, -}; - -static const struct file_operations tpg_fops = { - .open = simple_open, - .read = dp_debug_tpg_read, - .write = dp_debug_tpg_write, -}; - -static const struct file_operations hdr_fops = { - .open = simple_open, - .write = dp_debug_write_hdr, - .read = dp_debug_read_hdr, -}; - -static const struct file_operations sim_fops = { - .open = simple_open, - .write = dp_debug_write_sim, -}; - -static const struct file_operations attention_fops = { - .open = simple_open, - .write = dp_debug_write_attention, -}; - -static const struct file_operations dump_fops = { - .open = simple_open, - .write = dp_debug_write_dump, - .read = dp_debug_read_dump, -}; - -static const struct file_operations mst_mode_fops = { - .open = simple_open, - .write = dp_debug_mst_mode_write, - .read = dp_debug_mst_mode_read, -}; - -static const struct file_operations mst_sideband_mode_fops = { - .open = simple_open, - .write = dp_debug_mst_sideband_mode_write, -}; - -static const struct file_operations max_pclk_khz_fops = { - .open = simple_open, - .write = dp_debug_max_pclk_khz_write, - .read = dp_debug_max_pclk_khz_read, -}; - -static const struct file_operations hdcp_fops = { - .open = simple_open, - .write = dp_debug_write_hdcp, - .read = dp_debug_read_hdcp, -}; - -static const struct file_operations widebus_mode_fops = { - .open = simple_open, - .write = dp_debug_widebus_mode_write, -}; - -static int dp_debug_init(struct dp_debug *dp_debug) -{ - int rc = 0; - struct dp_debug_private *debug = container_of(dp_debug, - struct dp_debug_private, dp_debug); - struct dentry *dir, *file; - - dir = debugfs_create_dir(DEBUG_NAME, NULL); - if (IS_ERR_OR_NULL(dir)) { - if (!dir) - rc = -EINVAL; - else - rc = PTR_ERR(dir); - pr_err("[%s] debugfs create dir failed, rc = %d\n", - DEBUG_NAME, rc); - goto error; - } - - debug->root = dir; - - file = debugfs_create_file("dp_debug", 0444, dir, - debug, &dp_debug_fops); - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs create file failed, rc=%d\n", - DEBUG_NAME, rc); - goto error_remove_dir; - } - - file = debugfs_create_file("edid_modes", 0644, dir, - debug, &edid_modes_fops); - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs create edid_modes failed, rc=%d\n", - DEBUG_NAME, rc); - goto error_remove_dir; - } - - file = debugfs_create_file("edid_modes_mst", 0644, dir, - debug, &edid_modes_mst_fops); - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs create edid_modes_mst failed, rc=%d\n", - DEBUG_NAME, rc); - goto error_remove_dir; - } - - file = debugfs_create_file("mst_con_id", 0644, dir, - debug, &mst_con_id_fops); - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs create mst_con_id failed, rc=%d\n", - DEBUG_NAME, rc); - goto error_remove_dir; - } - - file = debugfs_create_file("mst_con_info", 0644, dir, - debug, &mst_conn_info_fops); - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs create mst_conn_info failed, rc=%d\n", - DEBUG_NAME, rc); - goto error_remove_dir; - } - - file = debugfs_create_file("hpd", 0644, dir, - debug, &hpd_fops); - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs hpd failed, rc=%d\n", - DEBUG_NAME, rc); - goto error_remove_dir; - } - - file = debugfs_create_file("connected", 0444, dir, - debug, &connected_fops); - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs connected failed, rc=%d\n", - DEBUG_NAME, rc); - goto error_remove_dir; - } - - file = debugfs_create_file("max_bw_code", 0644, dir, - debug, &bw_code_fops); - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs max_bw_code failed, rc=%d\n", - DEBUG_NAME, rc); - } - - file = debugfs_create_file("exe_mode", 0644, dir, - debug, &exe_mode_fops); - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs register failed, rc=%d\n", - DEBUG_NAME, rc); - } - - file = debugfs_create_file("edid", 0644, dir, - debug, &edid_fops); - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs edid failed, rc=%d\n", - DEBUG_NAME, rc); - goto error_remove_dir; - } - - file = debugfs_create_file("dpcd", 0644, dir, - debug, &dpcd_fops); - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs dpcd failed, rc=%d\n", - DEBUG_NAME, rc); - goto error_remove_dir; - } - - file = debugfs_create_file("tpg_ctrl", 0644, dir, - debug, &tpg_fops); - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs tpg failed, rc=%d\n", - DEBUG_NAME, rc); - goto error_remove_dir; - } - - file = debugfs_create_file("hdr", 0644, dir, - debug, &hdr_fops); - - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs hdr failed, rc=%d\n", - DEBUG_NAME, rc); - goto error_remove_dir; - } - - file = debugfs_create_file("sim", 0644, dir, - debug, &sim_fops); - - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs sim failed, rc=%d\n", - DEBUG_NAME, rc); - goto error_remove_dir; - } - - file = debugfs_create_file("attention", 0644, dir, - debug, &attention_fops); - - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs attention failed, rc=%d\n", - DEBUG_NAME, rc); - goto error_remove_dir; - } - - file = debugfs_create_file("dump", 0644, dir, - debug, &dump_fops); - - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs dump failed, rc=%d\n", - DEBUG_NAME, rc); - goto error_remove_dir; - } - - file = debugfs_create_file("mst_mode", 0644, dir, - debug, &mst_mode_fops); - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs max_bw_code failed, rc=%d\n", - DEBUG_NAME, rc); - goto error_remove_dir; - } - - file = debugfs_create_file("mst_sideband_mode", 0644, dir, - debug, &mst_sideband_mode_fops); - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs max_bw_code failed, rc=%d\n", - DEBUG_NAME, rc); - goto error_remove_dir; - } - - file = debugfs_create_file("max_pclk_khz", 0644, dir, - debug, &max_pclk_khz_fops); - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs max_pclk_khz failed, rc=%d\n", - DEBUG_NAME, rc); - goto error_remove_dir; - } - - file = debugfs_create_bool("force_encryption", 0644, dir, - &debug->dp_debug.force_encryption); - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs force_encryption failed, rc=%d\n", - DEBUG_NAME, rc); - goto error_remove_dir; - } - - file = debugfs_create_file("hdcp", 0644, dir, - debug, &hdcp_fops); - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs hdcp failed, rc=%d\n", - DEBUG_NAME, rc); - goto error_remove_dir; - } - - file = debugfs_create_bool("dsc_feature_enable", 0644, dir, - &debug->parser->dsc_feature_enable); - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs dsc_feature failed, rc=%d\n", - DEBUG_NAME, rc); - } - - file = debugfs_create_bool("fec_feature_enable", 0644, dir, - &debug->parser->fec_feature_enable); - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs fec_feature_enable failed, rc=%d\n", - DEBUG_NAME, rc); - } - - file = debugfs_create_file("widebus_mode", 0644, dir, - debug, &widebus_mode_fops); - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs widebus failed, rc=%d\n", - DEBUG_NAME, rc); - } - - file = debugfs_create_u32("max_lclk_khz", 0644, dir, - &debug->parser->max_lclk_khz); - if (IS_ERR_OR_NULL(file)) { - rc = PTR_ERR(file); - pr_err("[%s] debugfs max_lclk_khz failed, rc=%d\n", - DEBUG_NAME, rc); - } - - return 0; - -error_remove_dir: - if (!file) - rc = -EINVAL; - debugfs_remove_recursive(dir); -error: - return rc; -} - -u8 *dp_debug_get_edid(struct dp_debug *dp_debug) -{ - struct dp_debug_private *debug; - - if (!dp_debug) - return NULL; - - debug = container_of(dp_debug, struct dp_debug_private, dp_debug); - - return debug->edid; -} - -static void dp_debug_abort(struct dp_debug *dp_debug) -{ - struct dp_debug_private *debug; - - if (!dp_debug) - return; - - debug = container_of(dp_debug, struct dp_debug_private, dp_debug); - - mutex_lock(&debug->lock); - dp_debug_set_sim_mode(debug, false); - mutex_unlock(&debug->lock); -} - -struct dp_debug *dp_debug_get(struct dp_debug_in *in) -{ - int rc = 0; - struct dp_debug_private *debug; - struct dp_debug *dp_debug; - - if (!in->dev || !in->panel || !in->hpd || !in->link || - !in->catalog || !in->ctrl) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto error; - } - - debug = devm_kzalloc(in->dev, sizeof(*debug), GFP_KERNEL); - if (!debug) { - rc = -ENOMEM; - goto error; - } - - debug->dp_debug.debug_en = false; - debug->hpd = in->hpd; - debug->link = in->link; - debug->panel = in->panel; - debug->aux = in->aux; - debug->dev = in->dev; - debug->connector = in->connector; - debug->catalog = in->catalog; - debug->parser = in->parser; - debug->ctrl = in->ctrl; - - dp_debug = &debug->dp_debug; - dp_debug->vdisplay = 0; - dp_debug->hdisplay = 0; - dp_debug->vrefresh = 0; - - mutex_init(&debug->lock); - - rc = dp_debug_init(dp_debug); - if (rc) { - devm_kfree(in->dev, debug); - goto error; - } - - dp_debug->get_edid = dp_debug_get_edid; - dp_debug->abort = dp_debug_abort; - - INIT_LIST_HEAD(&dp_debug->dp_mst_connector_list.list); - - /* - * Do not associate the head of the list with any connector in order to - * maintain backwards compatibility with the SST use case. - */ - dp_debug->dp_mst_connector_list.con_id = -1; - dp_debug->dp_mst_connector_list.conn = NULL; - dp_debug->dp_mst_connector_list.debug_en = false; - - dp_debug->max_pclk_khz = debug->parser->max_pclk_khz; - - return dp_debug; -error: - return ERR_PTR(rc); -} - -static int dp_debug_deinit(struct dp_debug *dp_debug) -{ - struct dp_debug_private *debug; - - if (!dp_debug) - return -EINVAL; - - debug = container_of(dp_debug, struct dp_debug_private, dp_debug); - - debugfs_remove_recursive(debug->root); - - return 0; -} - -void dp_debug_put(struct dp_debug *dp_debug) -{ - struct dp_debug_private *debug; - - if (!dp_debug) - return; - - debug = container_of(dp_debug, struct dp_debug_private, dp_debug); - - dp_debug_deinit(dp_debug); - - mutex_destroy(&debug->lock); - - if (debug->edid) - devm_kfree(debug->dev, debug->edid); - - if (debug->dpcd) - devm_kfree(debug->dev, debug->dpcd); - - devm_kfree(debug->dev, debug); -} diff --git a/drivers/gpu/drm/msm/dp/dp_debug.h b/drivers/gpu/drm/msm/dp/dp_debug.h deleted file mode 100644 index 11b890eb13b9a9f8dd5e1e5ca99b453d0241d6e6..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_debug.h +++ /dev/null @@ -1,89 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. - */ - -#ifndef _DP_DEBUG_H_ -#define _DP_DEBUG_H_ - -#include "dp_panel.h" -#include "dp_ctrl.h" -#include "dp_link.h" -#include "dp_usbpd.h" -#include "dp_aux.h" -#include "dp_display.h" - -/** - * struct dp_debug - * @debug_en: specifies whether debug mode enabled - * @vdisplay: used to filter out vdisplay value - * @hdisplay: used to filter out hdisplay value - * @vrefresh: used to filter out vrefresh value - * @tpg_state: specifies whether tpg feature is enabled - * @max_pclk_khz: max pclk supported - * @force_encryption: enable/disable forced encryption for HDCP 2.2 - */ -struct dp_debug { - bool debug_en; - bool sim_mode; - bool psm_enabled; - bool hdcp_disabled; - int aspect_ratio; - int vdisplay; - int hdisplay; - int vrefresh; - bool tpg_state; - u32 max_pclk_khz; - bool force_encryption; - char hdcp_status[SZ_128]; - struct dp_mst_connector dp_mst_connector_list; - bool mst_hpd_sim; - u32 mst_port_cnt; - - u8 *(*get_edid)(struct dp_debug *dp_debug); - void (*abort)(struct dp_debug *dp_debug); -}; - -/** - * struct dp_debug_in - * @dev: device instance of the caller - * @panel: instance of panel module - * @hpd: instance of hpd module - * @link: instance of link module - * @aux: instance of aux module - * @connector: double pointer to display connector - * @catalog: instance of catalog module - * @parser: instance of parser module - */ -struct dp_debug_in { - struct device *dev; - struct dp_panel *panel; - struct dp_hpd *hpd; - struct dp_link *link; - struct dp_aux *aux; - struct drm_connector **connector; - struct dp_catalog *catalog; - struct dp_parser *parser; - struct dp_ctrl *ctrl; -}; - -/** - * dp_debug_get() - configure and get the DisplayPlot debug module data - * - * @in: input structure containing data to initialize the debug module - * return: pointer to allocated debug module data - * - * This function sets up the debug module and provides a way - * for debugfs input to be communicated with existing modules - */ -struct dp_debug *dp_debug_get(struct dp_debug_in *in); - -/** - * dp_debug_put() - * - * Cleans up dp_debug instance - * - * @dp_debug: instance of dp_debug - */ -void dp_debug_put(struct dp_debug *dp_debug); -#endif /* _DP_DEBUG_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c deleted file mode 100644 index 8ac7f46ce46cadcdab417fdc4e1ef5690149cb6a..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ /dev/null @@ -1,2635 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sde_connector.h" - -#include "msm_drv.h" -#include "dp_hpd.h" -#include "dp_parser.h" -#include "dp_power.h" -#include "dp_catalog.h" -#include "dp_aux.h" -#include "dp_link.h" -#include "dp_panel.h" -#include "dp_ctrl.h" -#include "dp_audio.h" -#include "dp_display.h" -#include "sde_hdcp.h" -#include "dp_debug.h" - -#define DP_MST_DEBUG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) - -static struct dp_display *g_dp_display; -#define HPD_STRING_SIZE 30 - -struct dp_hdcp_dev { - void *fd; - struct sde_hdcp_ops *ops; - enum sde_hdcp_version ver; -}; - -struct dp_hdcp { - void *data; - struct sde_hdcp_ops *ops; - - u32 source_cap; - - struct dp_hdcp_dev dev[HDCP_VERSION_MAX]; -}; - -struct dp_mst { - bool mst_active; - - bool drm_registered; - struct dp_mst_drm_cbs cbs; -}; - -struct dp_display_private { - char *name; - int irq; - - /* state variables */ - bool core_initialized; - bool power_on; - bool is_connected; - - atomic_t aborted; - - struct platform_device *pdev; - struct device_node *aux_switch_node; - struct dentry *root; - struct completion notification_comp; - - struct dp_hpd *hpd; - struct dp_parser *parser; - struct dp_power *power; - struct dp_catalog *catalog; - struct dp_aux *aux; - struct dp_link *link; - struct dp_panel *panel; - struct dp_ctrl *ctrl; - struct dp_debug *debug; - - struct dp_panel *active_panels[DP_STREAM_MAX]; - struct dp_hdcp hdcp; - - struct dp_hpd_cb hpd_cb; - struct dp_display_mode mode; - struct dp_display dp_display; - struct msm_drm_private *priv; - - struct workqueue_struct *wq; - struct delayed_work hdcp_cb_work; - struct work_struct connect_work; - struct work_struct attention_work; - struct mutex session_lock; - - u32 active_stream_cnt; - struct dp_mst mst; - - u32 tot_dsc_blks_in_use; - - bool process_hpd_connect; - - struct notifier_block usb_nb; -}; - -static const struct of_device_id dp_dt_match[] = { - {.compatible = "qcom,dp-display"}, - {} -}; - -static inline bool dp_display_is_hdcp_enabled(struct dp_display_private *dp) -{ - return dp->link->hdcp_status.hdcp_version && dp->hdcp.ops; -} - -static irqreturn_t dp_display_irq(int irq, void *dev_id) -{ - struct dp_display_private *dp = dev_id; - - if (!dp) { - pr_err("invalid data\n"); - return IRQ_NONE; - } - - /* DP HPD isr */ - if (dp->hpd->type == DP_HPD_LPHW) - dp->hpd->isr(dp->hpd); - - /* DP controller isr */ - dp->ctrl->isr(dp->ctrl); - - /* DP aux isr */ - dp->aux->isr(dp->aux); - - /* HDCP isr */ - if (dp_display_is_hdcp_enabled(dp) && dp->hdcp.ops->isr) { - if (dp->hdcp.ops->isr(dp->hdcp.data)) - pr_err("dp_hdcp_isr failed\n"); - } - - return IRQ_HANDLED; -} -static bool dp_display_is_ds_bridge(struct dp_panel *panel) -{ - return (panel->dpcd[DP_DOWNSTREAMPORT_PRESENT] & - DP_DWN_STRM_PORT_PRESENT); -} - -static bool dp_display_is_sink_count_zero(struct dp_display_private *dp) -{ - return dp_display_is_ds_bridge(dp->panel) && - (dp->link->sink_count.count == 0); -} - -static bool dp_display_is_ready(struct dp_display_private *dp) -{ - return dp->hpd->hpd_high && dp->is_connected && - !dp_display_is_sink_count_zero(dp) && - dp->hpd->alt_mode_cfg_done; -} - -static void dp_display_update_hdcp_status(struct dp_display_private *dp, - bool reset) -{ - if (reset) { - dp->link->hdcp_status.hdcp_state = HDCP_STATE_INACTIVE; - dp->link->hdcp_status.hdcp_version = HDCP_VERSION_NONE; - } - - memset(dp->debug->hdcp_status, 0, sizeof(dp->debug->hdcp_status)); - - snprintf(dp->debug->hdcp_status, sizeof(dp->debug->hdcp_status), - "%s: %s\ncaps: %d\n", - sde_hdcp_version(dp->link->hdcp_status.hdcp_version), - sde_hdcp_state_name(dp->link->hdcp_status.hdcp_state), - dp->hdcp.source_cap); -} - -static void dp_display_update_hdcp_info(struct dp_display_private *dp) -{ - void *fd = NULL; - struct dp_hdcp_dev *dev = NULL; - struct sde_hdcp_ops *ops = NULL; - int i = HDCP_VERSION_2P2; - - dp_display_update_hdcp_status(dp, true); - - dp->hdcp.data = NULL; - dp->hdcp.ops = NULL; - - if (dp->debug->hdcp_disabled || dp->debug->sim_mode) - return; - - while (i) { - dev = &dp->hdcp.dev[i]; - ops = dev->ops; - fd = dev->fd; - - i >>= 1; - - if (!(dp->hdcp.source_cap & dev->ver)) - continue; - - if (ops->sink_support(fd)) { - dp->hdcp.data = fd; - dp->hdcp.ops = ops; - dp->link->hdcp_status.hdcp_version = dev->ver; - break; - } - } - - pr_debug("HDCP version supported: %s\n", - sde_hdcp_version(dp->link->hdcp_status.hdcp_version)); -} - -static void dp_display_check_source_hdcp_caps(struct dp_display_private *dp) -{ - int i; - struct dp_hdcp_dev *hdcp_dev = dp->hdcp.dev; - - if (dp->debug->hdcp_disabled) { - pr_debug("hdcp disabled\n"); - return; - } - - for (i = 0; i < HDCP_VERSION_MAX; i++) { - struct dp_hdcp_dev *dev = &hdcp_dev[i]; - struct sde_hdcp_ops *ops = dev->ops; - void *fd = dev->fd; - - if (!fd || !ops) - continue; - - if (ops->set_mode && ops->set_mode(fd, dp->mst.mst_active)) - continue; - - if (!(dp->hdcp.source_cap & dev->ver) && - ops->feature_supported && - ops->feature_supported(fd)) - dp->hdcp.source_cap |= dev->ver; - } - - dp_display_update_hdcp_status(dp, false); -} - -static void dp_display_hdcp_register_streams(struct dp_display_private *dp) -{ - int rc; - size_t i; - struct sde_hdcp_ops *ops = dp->hdcp.ops; - void *data = dp->hdcp.data; - - if (dp_display_is_ready(dp) && dp->mst.mst_active && ops && - ops->register_streams){ - struct stream_info streams[DP_STREAM_MAX]; - int index = 0; - - pr_debug("Registering all active panel streams with HDCP\n"); - for (i = DP_STREAM_0; i < DP_STREAM_MAX; i++) { - if (!dp->active_panels[i]) - continue; - streams[index].stream_id = i; - streams[index].virtual_channel = - dp->active_panels[i]->vcpi; - index++; - } - - if (index > 0) { - rc = ops->register_streams(data, index, streams); - if (rc) - pr_err("failed to register streams. rc = %d\n", - rc); - } - } -} - -static void dp_display_hdcp_deregister_stream(struct dp_display_private *dp, - enum dp_stream_id stream_id) -{ - if (dp->hdcp.ops->deregister_streams) { - struct stream_info stream = {stream_id, - dp->active_panels[stream_id]->vcpi}; - - pr_debug("Deregistering stream within HDCP library\n"); - dp->hdcp.ops->deregister_streams(dp->hdcp.data, 1, &stream); - } -} - -static void dp_display_hdcp_cb_work(struct work_struct *work) -{ - struct dp_display_private *dp; - struct delayed_work *dw = to_delayed_work(work); - struct sde_hdcp_ops *ops; - struct dp_link_hdcp_status *status; - void *data; - int rc = 0; - u32 hdcp_auth_state; - u8 sink_status = 0; - - dp = container_of(dw, struct dp_display_private, hdcp_cb_work); - - if (!dp->power_on || !dp->is_connected || atomic_read(&dp->aborted)) - return; - - drm_dp_dpcd_readb(dp->aux->drm_aux, DP_SINK_STATUS, &sink_status); - sink_status &= (DP_RECEIVE_PORT_0_STATUS | DP_RECEIVE_PORT_1_STATUS); - if (sink_status < 1) { - pr_debug("Sink not synchronized. Queuing again then exiting\n"); - queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ); - return; - } - - status = &dp->link->hdcp_status; - - if (status->hdcp_state == HDCP_STATE_INACTIVE) { - dp_display_check_source_hdcp_caps(dp); - dp_display_update_hdcp_info(dp); - - if (dp_display_is_hdcp_enabled(dp)) { - if (dp->hdcp.ops && dp->hdcp.ops->on && - dp->hdcp.ops->on(dp->hdcp.data)) { - dp_display_update_hdcp_status(dp, true); - return; - } - status->hdcp_state = HDCP_STATE_AUTHENTICATING; - } else { - dp_display_update_hdcp_status(dp, true); - return; - } - } - - rc = dp->catalog->ctrl.read_hdcp_status(&dp->catalog->ctrl); - if (rc >= 0) { - hdcp_auth_state = (rc >> 20) & 0x3; - pr_debug("hdcp auth state %d\n", hdcp_auth_state); - } - - ops = dp->hdcp.ops; - data = dp->hdcp.data; - - pr_debug("%s: %s\n", sde_hdcp_version(status->hdcp_version), - sde_hdcp_state_name(status->hdcp_state)); - - dp_display_update_hdcp_status(dp, false); - - if (dp->debug->force_encryption && ops && ops->force_encryption) - ops->force_encryption(data, dp->debug->force_encryption); - - switch (status->hdcp_state) { - case HDCP_STATE_AUTHENTICATING: - dp_display_hdcp_register_streams(dp); - if (dp->hdcp.ops && dp->hdcp.ops->authenticate) - rc = dp->hdcp.ops->authenticate(data); - break; - case HDCP_STATE_AUTH_FAIL: - if (dp_display_is_ready(dp) && dp->power_on) { - if (ops && ops->on && ops->on(data)) { - dp_display_update_hdcp_status(dp, true); - return; - } - dp_display_hdcp_register_streams(dp); - status->hdcp_state = HDCP_STATE_AUTHENTICATING; - if (ops && ops->reauthenticate) { - rc = ops->reauthenticate(data); - if (rc) - pr_err("failed rc=%d\n", rc); - } - } else { - pr_debug("not reauthenticating, cable disconnected\n"); - } - break; - default: - dp_display_hdcp_register_streams(dp); - break; - } -} - -static void dp_display_notify_hdcp_status_cb(void *ptr, - enum sde_hdcp_state state) -{ - struct dp_display_private *dp = ptr; - - if (!dp) { - pr_err("invalid input\n"); - return; - } - - dp->link->hdcp_status.hdcp_state = state; - - queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ/4); -} - -static void dp_display_deinitialize_hdcp(struct dp_display_private *dp) -{ - if (!dp) { - pr_err("invalid input\n"); - return; - } - - sde_dp_hdcp2p2_deinit(dp->hdcp.data); -} - -static int dp_display_initialize_hdcp(struct dp_display_private *dp) -{ - struct sde_hdcp_init_data hdcp_init_data; - struct dp_parser *parser; - void *fd; - int rc = 0; - - if (!dp) { - pr_err("invalid input\n"); - return -EINVAL; - } - - parser = dp->parser; - - hdcp_init_data.client_id = HDCP_CLIENT_DP; - hdcp_init_data.drm_aux = dp->aux->drm_aux; - hdcp_init_data.cb_data = (void *)dp; - hdcp_init_data.workq = dp->wq; - hdcp_init_data.sec_access = true; - hdcp_init_data.notify_status = dp_display_notify_hdcp_status_cb; - hdcp_init_data.dp_ahb = &parser->get_io(parser, "dp_ahb")->io; - hdcp_init_data.dp_aux = &parser->get_io(parser, "dp_aux")->io; - hdcp_init_data.dp_link = &parser->get_io(parser, "dp_link")->io; - hdcp_init_data.dp_p0 = &parser->get_io(parser, "dp_p0")->io; - hdcp_init_data.qfprom_io = &parser->get_io(parser, - "qfprom_physical")->io; - hdcp_init_data.hdcp_io = &parser->get_io(parser, - "hdcp_physical")->io; - hdcp_init_data.revision = &dp->panel->link_info.revision; - hdcp_init_data.msm_hdcp_dev = dp->parser->msm_hdcp_dev; - - fd = sde_hdcp_1x_init(&hdcp_init_data); - if (IS_ERR_OR_NULL(fd)) { - pr_err("Error initializing HDCP 1.x\n"); - rc = -EINVAL; - goto error; - } - - dp->hdcp.dev[HDCP_VERSION_1X].fd = fd; - dp->hdcp.dev[HDCP_VERSION_1X].ops = sde_hdcp_1x_get(fd); - dp->hdcp.dev[HDCP_VERSION_1X].ver = HDCP_VERSION_1X; - pr_debug("HDCP 1.3 initialized\n"); - - fd = sde_dp_hdcp2p2_init(&hdcp_init_data); - if (IS_ERR_OR_NULL(fd)) { - pr_err("Error initializing HDCP 2.x\n"); - rc = -EINVAL; - goto error; - } - - dp->hdcp.dev[HDCP_VERSION_2P2].fd = fd; - dp->hdcp.dev[HDCP_VERSION_2P2].ops = sde_dp_hdcp2p2_get(fd); - dp->hdcp.dev[HDCP_VERSION_2P2].ver = HDCP_VERSION_2P2; - pr_debug("HDCP 2.2 initialized\n"); - - return 0; -error: - dp_display_deinitialize_hdcp(dp); - - return rc; -} - -static int dp_display_bind(struct device *dev, struct device *master, - void *data) -{ - int rc = 0; - struct dp_display_private *dp; - struct drm_device *drm; - struct platform_device *pdev = to_platform_device(dev); - - if (!dev || !pdev || !master) { - pr_err("invalid param(s), dev %pK, pdev %pK, master %pK\n", - dev, pdev, master); - rc = -EINVAL; - goto end; - } - - drm = dev_get_drvdata(master); - dp = platform_get_drvdata(pdev); - if (!drm || !dp) { - pr_err("invalid param(s), drm %pK, dp %pK\n", - drm, dp); - rc = -EINVAL; - goto end; - } - - dp->dp_display.drm_dev = drm; - dp->priv = drm->dev_private; -end: - return rc; -} - -static void dp_display_unbind(struct device *dev, struct device *master, - void *data) -{ - struct dp_display_private *dp; - struct platform_device *pdev = to_platform_device(dev); - - if (!dev || !pdev) { - pr_err("invalid param(s)\n"); - return; - } - - dp = platform_get_drvdata(pdev); - if (!dp) { - pr_err("Invalid params\n"); - return; - } - - if (dp->power) - (void)dp->power->power_client_deinit(dp->power); - if (dp->aux) - (void)dp->aux->drm_aux_deregister(dp->aux); - dp_display_deinitialize_hdcp(dp); -} - -static const struct component_ops dp_display_comp_ops = { - .bind = dp_display_bind, - .unbind = dp_display_unbind, -}; - -static void dp_display_send_hpd_event(struct dp_display_private *dp) -{ - struct drm_device *dev = NULL; - struct drm_connector *connector; - char name[HPD_STRING_SIZE], status[HPD_STRING_SIZE], - bpp[HPD_STRING_SIZE], pattern[HPD_STRING_SIZE]; - char *envp[5]; - - if (dp->mst.mst_active) { - pr_debug("skip notification for mst mode\n"); - return; - } - - connector = dp->dp_display.base_connector; - - if (!connector) { - pr_err("connector not set\n"); - return; - } - - connector->status = connector->funcs->detect(connector, false); - - dev = connector->dev; - - snprintf(name, HPD_STRING_SIZE, "name=%s", connector->name); - snprintf(status, HPD_STRING_SIZE, "status=%s", - drm_get_connector_status_name(connector->status)); - snprintf(bpp, HPD_STRING_SIZE, "bpp=%d", - dp_link_bit_depth_to_bpp( - dp->link->test_video.test_bit_depth)); - snprintf(pattern, HPD_STRING_SIZE, "pattern=%d", - dp->link->test_video.test_video_pattern); - - pr_debug("[%s]:[%s] [%s] [%s]\n", name, status, bpp, pattern); - envp[0] = name; - envp[1] = status; - envp[2] = bpp; - envp[3] = pattern; - envp[4] = NULL; - kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, - envp); -} - -static int dp_display_send_hpd_notification(struct dp_display_private *dp) -{ - int ret = 0; - bool hpd = dp->is_connected; - - dp->aux->state |= DP_STATE_NOTIFICATION_SENT; - - if (!dp->mst.mst_active) - dp->dp_display.is_sst_connected = hpd; - else - dp->dp_display.is_sst_connected = false; - - reinit_completion(&dp->notification_comp); - dp_display_send_hpd_event(dp); - - if (hpd && dp->mst.mst_active) - goto skip_wait; - - if (!dp->mst.mst_active && (dp->power_on == hpd)) - goto skip_wait; - - if (!wait_for_completion_timeout(&dp->notification_comp, - HZ * 5)) { - pr_warn("%s timeout\n", hpd ? "connect" : "disconnect"); - ret = -EINVAL; - } - return ret; -skip_wait: - return 0; -} - -static void dp_display_update_mst_state(struct dp_display_private *dp, - bool state) -{ - dp->mst.mst_active = state; - dp->panel->mst_state = state; -} - -static void dp_display_process_mst_hpd_high(struct dp_display_private *dp, - bool mst_probe) -{ - bool is_mst_receiver; - struct dp_mst_hpd_info info; - int ret; - - if (!dp->parser->has_mst || !dp->mst.drm_registered) { - DP_MST_DEBUG("mst not enabled. has_mst:%d, registered:%d\n", - dp->parser->has_mst, dp->mst.drm_registered); - return; - } - - DP_MST_DEBUG("mst_hpd_high work. mst_probe:%d\n", mst_probe); - - if (!dp->mst.mst_active) { - is_mst_receiver = dp->panel->read_mst_cap(dp->panel); - - if (!is_mst_receiver) { - DP_MST_DEBUG("sink doesn't support mst\n"); - return; - } - - /* clear sink mst state */ - drm_dp_dpcd_writeb(dp->aux->drm_aux, DP_MSTM_CTRL, 0); - - ret = drm_dp_dpcd_writeb(dp->aux->drm_aux, DP_MSTM_CTRL, - DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC); - if (ret < 0) { - pr_err("sink mst enablement failed\n"); - return; - } - - dp_display_update_mst_state(dp, true); - } else if (dp->mst.mst_active && mst_probe) { - info.mst_protocol = dp->parser->has_mst_sideband; - info.mst_port_cnt = dp->debug->mst_port_cnt; - info.edid = dp->debug->get_edid(dp->debug); - - if (dp->mst.cbs.hpd) - dp->mst.cbs.hpd(&dp->dp_display, true, &info); - } - - DP_MST_DEBUG("mst_hpd_high. mst_active:%d\n", dp->mst.mst_active); -} - -static void dp_display_host_init(struct dp_display_private *dp) -{ - bool flip = false; - bool reset; - - if (dp->core_initialized) - return; - - if (dp->hpd->orientation == ORIENTATION_CC2) - flip = true; - - reset = dp->debug->sim_mode ? false : !dp->hpd->multi_func; - - dp->power->init(dp->power, flip); - dp->hpd->host_init(dp->hpd, &dp->catalog->hpd); - dp->ctrl->init(dp->ctrl, flip, reset); - dp->aux->init(dp->aux, dp->parser->aux_cfg); - enable_irq(dp->irq); - dp->panel->init(dp->panel); - dp->core_initialized = true; - - /* log this as it results from user action of cable connection */ - pr_info("[OK]\n"); -} - -static void dp_display_host_deinit(struct dp_display_private *dp) -{ - if (!dp->core_initialized) - return; - - if (dp->active_stream_cnt) { - pr_debug("active stream present\n"); - return; - } - - dp->aux->deinit(dp->aux); - dp->ctrl->deinit(dp->ctrl); - dp->hpd->host_deinit(dp->hpd, &dp->catalog->hpd); - dp->power->deinit(dp->power); - disable_irq(dp->irq); - dp->core_initialized = false; - dp->aux->state = 0; - - /* log this as it results from user action of cable dis-connection */ - pr_info("[OK]\n"); -} - -static int dp_display_process_hpd_high(struct dp_display_private *dp) -{ - int rc = -EINVAL; - - mutex_lock(&dp->session_lock); - - if (dp->is_connected) { - pr_debug("dp already connected, skipping hpd high\n"); - mutex_unlock(&dp->session_lock); - rc = -EISCONN; - goto end; - } - - dp->is_connected = true; - - dp->dp_display.max_pclk_khz = min(dp->parser->max_pclk_khz, - dp->debug->max_pclk_khz); - - dp_display_host_init(dp); - - dp->link->psm_config(dp->link, &dp->panel->link_info, false); - dp->debug->psm_enabled = false; - - if (!dp->dp_display.base_connector) - goto end; - - rc = dp->panel->read_sink_caps(dp->panel, - dp->dp_display.base_connector, dp->hpd->multi_func); - /* - * ETIMEDOUT --> cable may have been removed - * ENOTCONN --> no downstream device connected - */ - if (rc == -ETIMEDOUT || rc == -ENOTCONN) { - dp->is_connected = false; - goto end; - } - - dp->link->process_request(dp->link); - dp->panel->handle_sink_request(dp->panel); - - dp_display_process_mst_hpd_high(dp, false); - - rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active, - dp->panel->fec_en, false); - if (rc) { - dp->is_connected = false; - goto end; - } - - dp->process_hpd_connect = false; - - dp_display_process_mst_hpd_high(dp, true); -end: - mutex_unlock(&dp->session_lock); - - if (!rc) - dp_display_send_hpd_notification(dp); - - return rc; -} - -static void dp_display_process_mst_hpd_low(struct dp_display_private *dp) -{ - struct dp_mst_hpd_info info = {0}; - - if (dp->mst.mst_active) { - DP_MST_DEBUG("mst_hpd_low work\n"); - - if (dp->mst.cbs.hpd) { - info.mst_protocol = dp->parser->has_mst_sideband; - dp->mst.cbs.hpd(&dp->dp_display, false, &info); - } - dp_display_update_mst_state(dp, false); - } - - DP_MST_DEBUG("mst_hpd_low. mst_active:%d\n", dp->mst.mst_active); -} - -static int dp_display_process_hpd_low(struct dp_display_private *dp) -{ - int rc = 0; - - dp->is_connected = false; - dp->process_hpd_connect = false; - - dp_display_process_mst_hpd_low(dp); - - rc = dp_display_send_hpd_notification(dp); - - mutex_lock(&dp->session_lock); - if (!dp->active_stream_cnt) - dp->ctrl->off(dp->ctrl); - mutex_unlock(&dp->session_lock); - - dp->panel->video_test = false; - - return rc; -} - -static int dp_display_usbpd_configure_cb(struct device *dev) -{ - int rc = 0; - struct dp_display_private *dp; - - if (!dev) { - pr_err("invalid dev\n"); - rc = -EINVAL; - goto end; - } - - dp = dev_get_drvdata(dev); - if (!dp) { - pr_err("no driver data found\n"); - rc = -ENODEV; - goto end; - } - - if (!dp->debug->sim_mode && !dp->parser->no_aux_switch - && !dp->parser->gpio_aux_switch) { - rc = dp->aux->aux_switch(dp->aux, true, dp->hpd->orientation); - if (rc) - goto end; - } - - mutex_lock(&dp->session_lock); - dp_display_host_init(dp); - - /* check for hpd high */ - if (dp->hpd->hpd_high) - queue_work(dp->wq, &dp->connect_work); - else - dp->process_hpd_connect = true; - mutex_unlock(&dp->session_lock); -end: - return rc; -} - -static int dp_display_stream_pre_disable(struct dp_display_private *dp, - struct dp_panel *dp_panel) -{ - dp->ctrl->stream_pre_off(dp->ctrl, dp_panel); - - return 0; -} - -static void dp_display_stream_disable(struct dp_display_private *dp, - struct dp_panel *dp_panel) -{ - if (!dp->active_stream_cnt) { - pr_err("invalid active_stream_cnt (%d)\n", - dp->active_stream_cnt); - return; - } - - pr_debug("stream_id=%d, active_stream_cnt=%d\n", - dp_panel->stream_id, dp->active_stream_cnt); - - dp->ctrl->stream_off(dp->ctrl, dp_panel); - dp->active_panels[dp_panel->stream_id] = NULL; - dp->active_stream_cnt--; -} - -static void dp_display_clean(struct dp_display_private *dp) -{ - int idx; - struct dp_panel *dp_panel; - struct dp_link_hdcp_status *status = &dp->link->hdcp_status; - - if (dp_display_is_hdcp_enabled(dp) && - status->hdcp_state != HDCP_STATE_INACTIVE) { - cancel_delayed_work_sync(&dp->hdcp_cb_work); - if (dp->hdcp.ops->off) - dp->hdcp.ops->off(dp->hdcp.data); - - dp_display_update_hdcp_status(dp, true); - } - - for (idx = DP_STREAM_0; idx < DP_STREAM_MAX; idx++) { - if (!dp->active_panels[idx]) - continue; - - dp_panel = dp->active_panels[idx]; - - dp_display_stream_pre_disable(dp, dp_panel); - dp_display_stream_disable(dp, dp_panel); - dp_panel->deinit(dp_panel, 0); - } - - dp->power_on = false; - - mutex_lock(&dp->session_lock); - dp->ctrl->off(dp->ctrl); - mutex_unlock(&dp->session_lock); -} - -static int dp_display_handle_disconnect(struct dp_display_private *dp) -{ - int rc; - - rc = dp_display_process_hpd_low(dp); - if (rc) { - /* cancel any pending request */ - dp->ctrl->abort(dp->ctrl); - dp->aux->abort(dp->aux); - } - - mutex_lock(&dp->session_lock); - if (rc && dp->power_on) - dp_display_clean(dp); - - dp_display_host_deinit(dp); - - mutex_unlock(&dp->session_lock); - - return rc; -} - -static void dp_display_disconnect_sync(struct dp_display_private *dp) -{ - /* cancel any pending request */ - atomic_set(&dp->aborted, 1); - dp->ctrl->abort(dp->ctrl); - dp->aux->abort(dp->aux); - - /* wait for idle state */ - cancel_work_sync(&dp->connect_work); - cancel_work_sync(&dp->attention_work); - flush_workqueue(dp->wq); - - dp_display_handle_disconnect(dp); - - /* Reset abort value to allow future connections */ - atomic_set(&dp->aborted, 0); -} - -static int dp_display_usbpd_disconnect_cb(struct device *dev) -{ - int rc = 0; - struct dp_display_private *dp; - - if (!dev) { - pr_err("invalid dev\n"); - rc = -EINVAL; - goto end; - } - - dp = dev_get_drvdata(dev); - if (!dp) { - pr_err("no driver data found\n"); - rc = -ENODEV; - goto end; - } - - mutex_lock(&dp->session_lock); - if (dp->debug->psm_enabled && dp->core_initialized) - dp->link->psm_config(dp->link, &dp->panel->link_info, true); - mutex_unlock(&dp->session_lock); - - dp_display_disconnect_sync(dp); - - if (!dp->debug->sim_mode && !dp->parser->no_aux_switch - && !dp->parser->gpio_aux_switch) - dp->aux->aux_switch(dp->aux, false, ORIENTATION_NONE); -end: - return rc; -} - -static int dp_display_stream_enable(struct dp_display_private *dp, - struct dp_panel *dp_panel) -{ - int rc = 0; - - rc = dp->ctrl->stream_on(dp->ctrl, dp_panel); - - if (dp->debug->tpg_state) - dp_panel->tpg_config(dp_panel, true); - - if (!rc) { - dp->active_panels[dp_panel->stream_id] = dp_panel; - dp->active_stream_cnt++; - } - - pr_debug("dp active_stream_cnt:%d\n", dp->active_stream_cnt); - - return rc; -} - -static void dp_display_mst_attention(struct dp_display_private *dp) -{ - struct dp_mst_hpd_info hpd_irq = {0}; - - if (dp->mst.mst_active && dp->mst.cbs.hpd_irq) { - hpd_irq.mst_hpd_sim = dp->debug->mst_hpd_sim; - dp->mst.cbs.hpd_irq(&dp->dp_display, &hpd_irq); - dp->debug->mst_hpd_sim = false; - } - - DP_MST_DEBUG("mst_attention_work. mst_active:%d\n", dp->mst.mst_active); -} - -static void dp_display_attention_work(struct work_struct *work) -{ - struct dp_display_private *dp = container_of(work, - struct dp_display_private, attention_work); - - mutex_lock(&dp->session_lock); - - if (dp->debug->mst_hpd_sim || !dp->core_initialized) { - mutex_unlock(&dp->session_lock); - goto mst_attention; - } - - if (dp->link->process_request(dp->link)) { - mutex_unlock(&dp->session_lock); - goto cp_irq; - } - - mutex_unlock(&dp->session_lock); - - if (dp->link->sink_request & DS_PORT_STATUS_CHANGED) { - if (dp_display_is_sink_count_zero(dp)) { - dp_display_handle_disconnect(dp); - } else { - if (!dp->mst.mst_active) - queue_work(dp->wq, &dp->connect_work); - } - - goto mst_attention; - } - - if (dp->link->sink_request & DP_TEST_LINK_VIDEO_PATTERN) { - dp_display_handle_disconnect(dp); - - dp->panel->video_test = true; - queue_work(dp->wq, &dp->connect_work); - - goto mst_attention; - } - - if (dp->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) { - dp->ctrl->process_phy_test_request(dp->ctrl); - goto mst_attention; - } - - if (dp->link->sink_request & DP_TEST_LINK_TRAINING) { - dp->link->send_test_response(dp->link); - dp->ctrl->link_maintenance(dp->ctrl); - goto mst_attention; - } - - if (dp->link->sink_request & DP_LINK_STATUS_UPDATED) - dp->ctrl->link_maintenance(dp->ctrl); -cp_irq: - if (dp_display_is_hdcp_enabled(dp) && dp->hdcp.ops->cp_irq) - dp->hdcp.ops->cp_irq(dp->hdcp.data); -mst_attention: - dp_display_mst_attention(dp); -} - -static int dp_display_usbpd_attention_cb(struct device *dev) -{ - struct dp_display_private *dp; - - if (!dev) { - pr_err("invalid dev\n"); - return -EINVAL; - } - - dp = dev_get_drvdata(dev); - if (!dp) { - pr_err("no driver data found\n"); - return -ENODEV; - } - - pr_debug("hpd_irq:%d, hpd_high:%d, power_on:%d, is_connected:%d\n", - dp->hpd->hpd_irq, dp->hpd->hpd_high, - dp->power_on, dp->is_connected); - - if (!dp->hpd->hpd_high) - dp_display_disconnect_sync(dp); - else if ((dp->hpd->hpd_irq && dp->core_initialized) || - dp->debug->mst_hpd_sim) - queue_work(dp->wq, &dp->attention_work); - else if (dp->process_hpd_connect || !dp->is_connected) - queue_work(dp->wq, &dp->connect_work); - else - pr_debug("ignored\n"); - - return 0; -} - -static void dp_display_connect_work(struct work_struct *work) -{ - int rc = 0; - struct dp_display_private *dp = container_of(work, - struct dp_display_private, connect_work); - - if (atomic_read(&dp->aborted)) { - pr_warn("HPD off requested\n"); - return; - } - - if (!dp->hpd->hpd_high) { - pr_warn("Sink disconnected\n"); - return; - } - - rc = dp_display_process_hpd_high(dp); - - if (!rc && dp->panel->video_test) - dp->link->send_test_response(dp->link); -} - -static int dp_display_usb_notifier(struct notifier_block *nb, - unsigned long event, void *ptr) -{ - struct extcon_dev *edev = ptr; - struct dp_display_private *dp = container_of(nb, - struct dp_display_private, usb_nb); - if (!edev) - goto end; - - if (!event && dp->debug->sim_mode) { - dp_display_disconnect_sync(dp); - dp->debug->abort(dp->debug); - } -end: - return NOTIFY_DONE; -} - -static int dp_display_get_usb_extcon(struct dp_display_private *dp) -{ - struct extcon_dev *edev; - int rc; - - edev = extcon_get_edev_by_phandle(&dp->pdev->dev, 0); - if (IS_ERR(edev)) - return PTR_ERR(edev); - - dp->usb_nb.notifier_call = dp_display_usb_notifier; - dp->usb_nb.priority = 2; - rc = extcon_register_notifier(edev, EXTCON_USB, &dp->usb_nb); - if (rc) - pr_err("failed to register for usb event: %d\n", rc); - - return rc; -} - -static void dp_display_deinit_sub_modules(struct dp_display_private *dp) -{ - dp_audio_put(dp->panel->audio); - dp_ctrl_put(dp->ctrl); - dp_link_put(dp->link); - dp_panel_put(dp->panel); - dp_aux_put(dp->aux); - dp_power_put(dp->power); - dp_catalog_put(dp->catalog); - dp_parser_put(dp->parser); - dp_hpd_put(dp->hpd); - mutex_destroy(&dp->session_lock); - dp_debug_put(dp->debug); -} - -static int dp_init_sub_modules(struct dp_display_private *dp) -{ - int rc = 0; - bool hdcp_disabled; - struct device *dev = &dp->pdev->dev; - struct dp_hpd_cb *cb = &dp->hpd_cb; - struct dp_ctrl_in ctrl_in = { - .dev = dev, - }; - struct dp_panel_in panel_in = { - .dev = dev, - }; - struct dp_debug_in debug_in = { - .dev = dev, - }; - - mutex_init(&dp->session_lock); - - dp->parser = dp_parser_get(dp->pdev); - if (IS_ERR(dp->parser)) { - rc = PTR_ERR(dp->parser); - pr_err("failed to initialize parser, rc = %d\n", rc); - dp->parser = NULL; - goto error; - } - - rc = dp->parser->parse(dp->parser); - if (rc) { - pr_err("device tree parsing failed\n"); - goto error_catalog; - } - - g_dp_display->is_mst_supported = dp->parser->has_mst; - - dp->catalog = dp_catalog_get(dev, dp->parser); - if (IS_ERR(dp->catalog)) { - rc = PTR_ERR(dp->catalog); - pr_err("failed to initialize catalog, rc = %d\n", rc); - dp->catalog = NULL; - goto error_catalog; - } - - dp->power = dp_power_get(dp->parser); - if (IS_ERR(dp->power)) { - rc = PTR_ERR(dp->power); - pr_err("failed to initialize power, rc = %d\n", rc); - dp->power = NULL; - goto error_power; - } - - rc = dp->power->power_client_init(dp->power, &dp->priv->phandle); - if (rc) { - pr_err("Power client create failed\n"); - goto error_aux; - } - - dp->aux = dp_aux_get(dev, &dp->catalog->aux, dp->parser, - dp->aux_switch_node); - if (IS_ERR(dp->aux)) { - rc = PTR_ERR(dp->aux); - pr_err("failed to initialize aux, rc = %d\n", rc); - dp->aux = NULL; - goto error_aux; - } - - rc = dp->aux->drm_aux_register(dp->aux); - if (rc) { - pr_err("DRM DP AUX register failed\n"); - goto error_link; - } - - dp->link = dp_link_get(dev, dp->aux); - if (IS_ERR(dp->link)) { - rc = PTR_ERR(dp->link); - pr_err("failed to initialize link, rc = %d\n", rc); - dp->link = NULL; - goto error_link; - } - - panel_in.aux = dp->aux; - panel_in.catalog = &dp->catalog->panel; - panel_in.link = dp->link; - panel_in.connector = dp->dp_display.base_connector; - panel_in.base_panel = NULL; - panel_in.parser = dp->parser; - - dp->panel = dp_panel_get(&panel_in); - if (IS_ERR(dp->panel)) { - rc = PTR_ERR(dp->panel); - pr_err("failed to initialize panel, rc = %d\n", rc); - dp->panel = NULL; - goto error_panel; - } - - ctrl_in.link = dp->link; - ctrl_in.panel = dp->panel; - ctrl_in.aux = dp->aux; - ctrl_in.power = dp->power; - ctrl_in.catalog = &dp->catalog->ctrl; - ctrl_in.parser = dp->parser; - - dp->ctrl = dp_ctrl_get(&ctrl_in); - if (IS_ERR(dp->ctrl)) { - rc = PTR_ERR(dp->ctrl); - pr_err("failed to initialize ctrl, rc = %d\n", rc); - dp->ctrl = NULL; - goto error_ctrl; - } - - dp->panel->audio = dp_audio_get(dp->pdev, dp->panel, - &dp->catalog->audio); - if (IS_ERR(dp->panel->audio)) { - rc = PTR_ERR(dp->panel->audio); - pr_err("failed to initialize audio, rc = %d\n", rc); - dp->panel->audio = NULL; - goto error_audio; - } - - memset(&dp->mst, 0, sizeof(dp->mst)); - dp->active_stream_cnt = 0; - - cb->configure = dp_display_usbpd_configure_cb; - cb->disconnect = dp_display_usbpd_disconnect_cb; - cb->attention = dp_display_usbpd_attention_cb; - - dp->hpd = dp_hpd_get(dev, dp->parser, &dp->catalog->hpd, cb); - if (IS_ERR(dp->hpd)) { - rc = PTR_ERR(dp->hpd); - pr_err("failed to initialize hpd, rc = %d\n", rc); - dp->hpd = NULL; - goto error_hpd; - } - - hdcp_disabled = !!dp_display_initialize_hdcp(dp); - - debug_in.panel = dp->panel; - debug_in.hpd = dp->hpd; - debug_in.link = dp->link; - debug_in.aux = dp->aux; - debug_in.connector = &dp->dp_display.base_connector; - debug_in.catalog = dp->catalog; - debug_in.parser = dp->parser; - debug_in.ctrl = dp->ctrl; - - dp->debug = dp_debug_get(&debug_in); - if (IS_ERR(dp->debug)) { - rc = PTR_ERR(dp->debug); - pr_err("failed to initialize debug, rc = %d\n", rc); - dp->debug = NULL; - goto error_debug; - } - - dp->tot_dsc_blks_in_use = 0; - - dp->debug->hdcp_disabled = hdcp_disabled; - dp_display_update_hdcp_status(dp, true); - - dp_display_get_usb_extcon(dp); - - rc = dp->hpd->register_hpd(dp->hpd); - if (rc) { - pr_err("failed register hpd\n"); - goto error_hpd_reg; - } - - return rc; -error_hpd_reg: - dp_debug_put(dp->debug); -error_debug: - dp_hpd_put(dp->hpd); -error_hpd: - dp_audio_put(dp->panel->audio); -error_audio: - dp_ctrl_put(dp->ctrl); -error_ctrl: - dp_panel_put(dp->panel); -error_panel: - dp_link_put(dp->link); -error_link: - dp_aux_put(dp->aux); -error_aux: - dp_power_put(dp->power); -error_power: - dp_catalog_put(dp->catalog); -error_catalog: - dp_parser_put(dp->parser); -error: - mutex_destroy(&dp->session_lock); - return rc; -} - -static int dp_display_post_init(struct dp_display *dp_display) -{ - int rc = 0; - struct dp_display_private *dp; - - if (!dp_display) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto end; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - if (IS_ERR_OR_NULL(dp)) { - pr_err("invalid params\n"); - rc = -EINVAL; - goto end; - } - - rc = dp_init_sub_modules(dp); - if (rc) - goto end; - - dp_display->post_init = NULL; -end: - pr_debug("%s\n", rc ? "failed" : "success"); - return rc; -} - -static int dp_display_set_mode(struct dp_display *dp_display, void *panel, - struct dp_display_mode *mode) -{ - const u32 num_components = 3, default_bpp = 24; - struct dp_display_private *dp; - struct dp_panel *dp_panel; - - if (!dp_display || !panel) { - pr_err("invalid input\n"); - return -EINVAL; - } - - dp_panel = panel; - if (!dp_panel->connector) { - pr_err("invalid connector input\n"); - return -EINVAL; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - mutex_lock(&dp->session_lock); - mode->timing.bpp = - dp_panel->connector->display_info.bpc * num_components; - if (!mode->timing.bpp) - mode->timing.bpp = default_bpp; - - mode->timing.bpp = dp->panel->get_mode_bpp(dp->panel, - mode->timing.bpp, mode->timing.pixel_clk_khz); - - dp_panel->pinfo = mode->timing; - mutex_unlock(&dp->session_lock); - - return 0; -} - -static int dp_display_prepare(struct dp_display *dp_display, void *panel) -{ - struct dp_display_private *dp; - struct dp_panel *dp_panel; - int rc = 0; - - if (!dp_display || !panel) { - pr_err("invalid input\n"); - return -EINVAL; - } - - dp_panel = panel; - if (!dp_panel->connector) { - pr_err("invalid connector input\n"); - return -EINVAL; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - mutex_lock(&dp->session_lock); - - if (atomic_read(&dp->aborted)) - goto end; - - if (dp->power_on) - goto end; - - if (!dp_display_is_ready(dp)) - goto end; - - dp_display_host_init(dp); - - if (dp->debug->psm_enabled) { - dp->link->psm_config(dp->link, &dp->panel->link_info, false); - dp->debug->psm_enabled = false; - } - - /* - * Execute the dp controller power on in shallow mode here. - * In normal cases, controller should have been powered on - * by now. In some cases like suspend/resume or framework - * reboot, we end up here without a powered on controller. - * Cable may have been removed in suspended state. In that - * case, link training is bound to fail on system resume. - * So, we execute in shallow mode here to do only minimal - * and required things. - */ - rc = dp->ctrl->on(dp->ctrl, dp->mst.mst_active, dp_panel->fec_en, true); - if (rc) - goto end; - -end: - mutex_unlock(&dp->session_lock); - - return 0; -} - -static int dp_display_set_stream_info(struct dp_display *dp_display, - void *panel, u32 strm_id, u32 start_slot, - u32 num_slots, u32 pbn, int vcpi) -{ - int rc = 0; - struct dp_panel *dp_panel; - struct dp_display_private *dp; - const int max_slots = 64; - - if (!dp_display) { - pr_err("invalid input\n"); - return -EINVAL; - } - - if (strm_id >= DP_STREAM_MAX) { - pr_err("invalid stream id:%d\n", strm_id); - return -EINVAL; - } - - if (start_slot + num_slots > max_slots) { - pr_err("invalid channel info received. start:%d, slots:%d\n", - start_slot, num_slots); - return -EINVAL; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - mutex_lock(&dp->session_lock); - - dp->ctrl->set_mst_channel_info(dp->ctrl, strm_id, - start_slot, num_slots); - - if (panel) { - dp_panel = panel; - dp_panel->set_stream_info(dp_panel, strm_id, start_slot, - num_slots, pbn, vcpi); - } - - mutex_unlock(&dp->session_lock); - - return rc; -} - -static void dp_display_update_dsc_resources(struct dp_display_private *dp, - struct dp_panel *panel, bool enable) -{ - u32 dsc_blk_cnt = 0; - - if (panel->pinfo.comp_info.comp_type == MSM_DISPLAY_COMPRESSION_DSC && - panel->pinfo.comp_info.comp_ratio) { - dsc_blk_cnt = panel->pinfo.h_active / - dp->parser->max_dp_dsc_input_width_pixs; - if (panel->pinfo.h_active % - dp->parser->max_dp_dsc_input_width_pixs) - dsc_blk_cnt++; - } - - if (enable) { - dp->tot_dsc_blks_in_use += dsc_blk_cnt; - panel->tot_dsc_blks_in_use += dsc_blk_cnt; - } else { - dp->tot_dsc_blks_in_use -= dsc_blk_cnt; - panel->tot_dsc_blks_in_use -= dsc_blk_cnt; - } -} - -static int dp_display_enable(struct dp_display *dp_display, void *panel) -{ - int rc = 0; - struct dp_display_private *dp; - - if (!dp_display || !panel) { - pr_err("invalid input\n"); - return -EINVAL; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - mutex_lock(&dp->session_lock); - - if (!dp->core_initialized) { - pr_err("host not initialized\n"); - goto end; - } - - rc = dp_display_stream_enable(dp, panel); - if (rc) - goto end; - - dp_display_update_dsc_resources(dp, panel, true); - dp->power_on = true; -end: - mutex_unlock(&dp->session_lock); - return rc; -} - -static void dp_display_stream_post_enable(struct dp_display_private *dp, - struct dp_panel *dp_panel) -{ - dp_panel->spd_config(dp_panel); - dp_panel->setup_hdr(dp_panel, NULL, false, 0); -} - -static int dp_display_post_enable(struct dp_display *dp_display, void *panel) -{ - struct dp_display_private *dp; - struct dp_panel *dp_panel; - - if (!dp_display || !panel) { - pr_err("invalid input\n"); - return -EINVAL; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - dp_panel = panel; - - mutex_lock(&dp->session_lock); - - if (!dp->power_on) { - pr_debug("stream not setup, return\n"); - goto end; - } - - if (atomic_read(&dp->aborted)) - goto end; - - if (!dp_display_is_ready(dp) || !dp->core_initialized) { - pr_err("display not ready\n"); - goto end; - } - - dp_display_stream_post_enable(dp, dp_panel); - - if (dp_panel->audio_supported) { - dp_panel->audio->bw_code = dp->link->link_params.bw_code; - dp_panel->audio->lane_count = dp->link->link_params.lane_count; - dp_panel->audio->on(dp_panel->audio); - } - - cancel_delayed_work_sync(&dp->hdcp_cb_work); - queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ); -end: - dp->aux->state |= DP_STATE_CTRL_POWERED_ON; - - complete_all(&dp->notification_comp); - mutex_unlock(&dp->session_lock); - return 0; -} - -static int dp_display_pre_disable(struct dp_display *dp_display, void *panel) -{ - struct dp_display_private *dp; - struct dp_panel *dp_panel = panel; - struct dp_link_hdcp_status *status; - int rc = 0; - size_t i; - - if (!dp_display || !panel) { - pr_err("invalid input\n"); - return -EINVAL; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - mutex_lock(&dp->session_lock); - - status = &dp->link->hdcp_status; - - if (!dp->power_on) { - pr_debug("stream already powered off, return\n"); - goto end; - } - - if (dp_display_is_hdcp_enabled(dp) && - status->hdcp_state != HDCP_STATE_INACTIVE) { - flush_delayed_work(&dp->hdcp_cb_work); - if (dp->mst.mst_active) { - dp_display_hdcp_deregister_stream(dp, - dp_panel->stream_id); - for (i = DP_STREAM_0; i < DP_STREAM_MAX; i++) { - if (i != dp_panel->stream_id && - dp->active_panels[i]) { - pr_debug("Streams are still active. Skip disabling HDCP\n"); - goto stream; - } - } - } - - if (dp->hdcp.ops->off) - dp->hdcp.ops->off(dp->hdcp.data); - - dp_display_update_hdcp_status(dp, true); - } - -stream: - if (dp_panel->audio_supported) - dp_panel->audio->off(dp_panel->audio); - - rc = dp_display_stream_pre_disable(dp, dp_panel); - -end: - mutex_unlock(&dp->session_lock); - return 0; -} - -static int dp_display_disable(struct dp_display *dp_display, void *panel) -{ - struct dp_display_private *dp = NULL; - struct dp_panel *dp_panel = NULL; - - if (!dp_display || !panel) { - pr_err("invalid input\n"); - return -EINVAL; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - dp_panel = panel; - - mutex_lock(&dp->session_lock); - - if (!dp->power_on || !dp->core_initialized) { - pr_debug("Link already powered off, return\n"); - goto end; - } - - dp_display_stream_disable(dp, dp_panel); - dp_display_update_dsc_resources(dp, dp_panel, false); -end: - mutex_unlock(&dp->session_lock); - return 0; -} - -static int dp_request_irq(struct dp_display *dp_display) -{ - int rc = 0; - struct dp_display_private *dp; - - if (!dp_display) { - pr_err("invalid input\n"); - return -EINVAL; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - dp->irq = irq_of_parse_and_map(dp->pdev->dev.of_node, 0); - if (dp->irq < 0) { - rc = dp->irq; - pr_err("failed to get irq: %d\n", rc); - return rc; - } - - rc = devm_request_irq(&dp->pdev->dev, dp->irq, dp_display_irq, - IRQF_TRIGGER_HIGH, "dp_display_isr", dp); - if (rc < 0) { - pr_err("failed to request IRQ%u: %d\n", - dp->irq, rc); - return rc; - } - disable_irq(dp->irq); - - return 0; -} - -static struct dp_debug *dp_get_debug(struct dp_display *dp_display) -{ - struct dp_display_private *dp; - - if (!dp_display) { - pr_err("invalid input\n"); - return ERR_PTR(-EINVAL); - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - return dp->debug; -} - -static int dp_display_unprepare(struct dp_display *dp_display, void *panel) -{ - struct dp_display_private *dp; - struct dp_panel *dp_panel = panel; - u32 flags = 0; - - if (!dp_display || !panel) { - pr_err("invalid input\n"); - return -EINVAL; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - mutex_lock(&dp->session_lock); - - /* - * Check if the power off sequence was triggered - * by a source initialated action like framework - * reboot or suspend-resume but not from normal - * hot plug. - */ - if (dp_display_is_ready(dp)) - flags |= DP_PANEL_SRC_INITIATED_POWER_DOWN; - - if (dp->active_stream_cnt) - goto end; - - if (flags & DP_PANEL_SRC_INITIATED_POWER_DOWN) { - dp->link->psm_config(dp->link, &dp->panel->link_info, true); - dp->debug->psm_enabled = true; - - dp->ctrl->off(dp->ctrl); - dp_display_host_deinit(dp); - } - - dp->power_on = false; - dp->aux->state = DP_STATE_CTRL_POWERED_OFF; - - complete_all(&dp->notification_comp); - - /* log this as it results from user action of cable dis-connection */ - pr_info("[OK]\n"); -end: - dp_panel->deinit(dp_panel, flags); - mutex_unlock(&dp->session_lock); - - return 0; -} - -static enum drm_mode_status dp_display_validate_mode( - struct dp_display *dp_display, - void *panel, struct drm_display_mode *mode) -{ - struct dp_display_private *dp; - struct drm_dp_link *link_info; - u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0; - struct dp_panel *dp_panel; - struct dp_debug *debug; - enum drm_mode_status mode_status = MODE_BAD; - bool in_list = false; - struct dp_mst_connector *mst_connector; - int hdis, vdis, vref, ar, _hdis, _vdis, _vref, _ar, rate; - struct dp_display_mode dp_mode; - bool dsc_en; - - if (!dp_display || !mode || !panel) { - pr_err("invalid params\n"); - return mode_status; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - mutex_lock(&dp->session_lock); - - dp_panel = panel; - if (!dp_panel->connector) { - pr_err("invalid connector\n"); - goto end; - } - - link_info = &dp->panel->link_info; - - debug = dp->debug; - if (!debug) - goto end; - - dp_display->convert_to_dp_mode(dp_display, panel, mode, &dp_mode); - - dsc_en = dp_mode.timing.comp_info.comp_ratio ? true : false; - mode_bpp = dsc_en ? dp_mode.timing.comp_info.dsc_info.bpp : - dp_mode.timing.bpp; - - mode_rate_khz = mode->clock * mode_bpp; - rate = drm_dp_bw_code_to_link_rate(dp->link->link_params.bw_code); - supported_rate_khz = link_info->num_lanes * rate * 8; - - if (mode_rate_khz > supported_rate_khz) { - DP_MST_DEBUG("pclk:%d, supported_rate:%d\n", - mode->clock, supported_rate_khz); - goto end; - } - - if (mode->clock > dp_display->max_pclk_khz) { - DP_MST_DEBUG("clk:%d, max:%d\n", mode->clock, - dp_display->max_pclk_khz); - goto end; - } - - /* - * If the connector exists in the mst connector list and if debug is - * enabled for that connector, use the mst connector settings from the - * list for validation. Otherwise, use non-mst default settings. - */ - mutex_lock(&debug->dp_mst_connector_list.lock); - - if (list_empty(&debug->dp_mst_connector_list.list)) { - mutex_unlock(&debug->dp_mst_connector_list.lock); - goto verify_default; - } - - list_for_each_entry(mst_connector, &debug->dp_mst_connector_list.list, - list) { - if (mst_connector->con_id == dp_panel->connector->base.id) { - in_list = true; - - if (!mst_connector->debug_en) { - mode_status = MODE_OK; - mutex_unlock( - &debug->dp_mst_connector_list.lock); - goto end; - } - - hdis = mst_connector->hdisplay; - vdis = mst_connector->vdisplay; - vref = mst_connector->vrefresh; - ar = mst_connector->aspect_ratio; - - _hdis = mode->hdisplay; - _vdis = mode->vdisplay; - _vref = mode->vrefresh; - _ar = mode->picture_aspect_ratio; - - if (hdis == _hdis && vdis == _vdis && vref == _vref && - ar == _ar) { - mode_status = MODE_OK; - mutex_unlock( - &debug->dp_mst_connector_list.lock); - goto end; - } - - break; - } - } - - mutex_unlock(&debug->dp_mst_connector_list.lock); - - if (in_list) - goto end; - -verify_default: - if (debug->debug_en && (mode->hdisplay != debug->hdisplay || - mode->vdisplay != debug->vdisplay || - mode->vrefresh != debug->vrefresh || - mode->picture_aspect_ratio != debug->aspect_ratio)) - goto end; - - mode_status = MODE_OK; -end: - mutex_unlock(&dp->session_lock); - return mode_status; -} - -static int dp_display_get_modes(struct dp_display *dp, void *panel, - struct dp_display_mode *dp_mode) -{ - struct dp_display_private *dp_display; - struct dp_panel *dp_panel; - int ret = 0; - - if (!dp || !panel) { - pr_err("invalid params\n"); - return 0; - } - - dp_panel = panel; - if (!dp_panel->connector) { - pr_err("invalid connector\n"); - return 0; - } - - dp_display = container_of(dp, struct dp_display_private, dp_display); - - ret = dp_panel->get_modes(dp_panel, dp_panel->connector, dp_mode); - if (dp_mode->timing.pixel_clk_khz) - dp->max_pclk_khz = dp_mode->timing.pixel_clk_khz; - return ret; -} - -static void dp_display_convert_to_dp_mode(struct dp_display *dp_display, - void *panel, - const struct drm_display_mode *drm_mode, - struct dp_display_mode *dp_mode) -{ - struct dp_display_private *dp; - struct dp_panel *dp_panel; - u32 free_dsc_blks = 0, required_dsc_blks = 0; - - if (!dp_display || !drm_mode || !dp_mode || !panel) { - pr_err("invalid input\n"); - return; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - dp_panel = panel; - - memset(dp_mode, 0, sizeof(*dp_mode)); - - free_dsc_blks = dp->parser->max_dp_dsc_blks - - dp->tot_dsc_blks_in_use + - dp_panel->tot_dsc_blks_in_use; - required_dsc_blks = drm_mode->hdisplay / - dp->parser->max_dp_dsc_input_width_pixs; - if (drm_mode->hdisplay % dp->parser->max_dp_dsc_input_width_pixs) - required_dsc_blks++; - - if (free_dsc_blks >= required_dsc_blks) - dp_mode->capabilities |= DP_PANEL_CAPS_DSC; - - if (dp_mode->capabilities & DP_PANEL_CAPS_DSC) - pr_debug("in_use:%d, max:%d, free:%d, req:%d, caps:0x%x, width:%d\n", - dp->tot_dsc_blks_in_use, dp->parser->max_dp_dsc_blks, - free_dsc_blks, required_dsc_blks, dp_mode->capabilities, - dp->parser->max_dp_dsc_input_width_pixs); - - dp_panel->convert_to_dp_mode(dp_panel, drm_mode, dp_mode); -} - -static int dp_display_config_hdr(struct dp_display *dp_display, void *panel, - struct drm_msm_ext_hdr_metadata *hdr, bool dhdr_update) -{ - struct dp_panel *dp_panel; - struct dp_display_private *dp; - u64 core_clk_rate; - - if (!dp_display || !panel) { - pr_err("invalid input\n"); - return -EINVAL; - } - - dp_panel = panel; - dp = container_of(dp_display, struct dp_display_private, dp_display); - - core_clk_rate = dp->power->clk_get_rate(dp->power, "core_clk"); - if (!core_clk_rate) { - pr_err("invalid rate for core_clk\n"); - return -EINVAL; - } - - return dp_panel->setup_hdr(dp_panel, hdr, dhdr_update, core_clk_rate); -} - -static int dp_display_create_workqueue(struct dp_display_private *dp) -{ - dp->wq = create_singlethread_workqueue("drm_dp"); - if (IS_ERR_OR_NULL(dp->wq)) { - pr_err("Error creating wq\n"); - return -EPERM; - } - - INIT_DELAYED_WORK(&dp->hdcp_cb_work, dp_display_hdcp_cb_work); - INIT_WORK(&dp->connect_work, dp_display_connect_work); - INIT_WORK(&dp->attention_work, dp_display_attention_work); - - return 0; -} - -static int dp_display_fsa4480_callback(struct notifier_block *self, - unsigned long event, void *data) -{ - return 0; -} - -static int dp_display_init_aux_switch(struct dp_display_private *dp) -{ - int rc = 0; - const char *phandle = "qcom,dp-aux-switch"; - struct notifier_block nb; - - if (!dp->pdev->dev.of_node) { - pr_err("cannot find dev.of_node\n"); - rc = -ENODEV; - goto end; - } - - dp->aux_switch_node = of_parse_phandle(dp->pdev->dev.of_node, - phandle, 0); - if (!dp->aux_switch_node) { - pr_warn("cannot parse %s handle\n", phandle); - rc = -ENODEV; - goto end; - } - - nb.notifier_call = dp_display_fsa4480_callback; - nb.priority = 0; - - rc = fsa4480_reg_notifier(&nb, dp->aux_switch_node); - if (rc) { - pr_err("failed to register notifier (%d)\n", rc); - goto end; - } - - fsa4480_unreg_notifier(&nb, dp->aux_switch_node); -end: - return rc; -} - -static int dp_display_mst_install(struct dp_display *dp_display, - struct dp_mst_drm_install_info *mst_install_info) -{ - struct dp_display_private *dp; - - if (!dp_display || !mst_install_info) { - pr_err("invalid input\n"); - return -EINVAL; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - if (!mst_install_info->cbs->hpd || !mst_install_info->cbs->hpd_irq) { - pr_err("invalid mst cbs\n"); - return -EINVAL; - } - - dp_display->dp_mst_prv_info = mst_install_info->dp_mst_prv_info; - - if (!dp->parser->has_mst) { - pr_debug("mst not enabled\n"); - return -EPERM; - } - - memcpy(&dp->mst.cbs, mst_install_info->cbs, sizeof(dp->mst.cbs)); - dp->mst.drm_registered = true; - - DP_MST_DEBUG("dp mst drm installed\n"); - - return 0; -} - -static int dp_display_mst_uninstall(struct dp_display *dp_display) -{ - struct dp_display_private *dp; - - if (!dp_display) { - pr_err("invalid input\n"); - return -EINVAL; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - if (!dp->mst.drm_registered) { - pr_debug("drm mst not registered\n"); - return -EPERM; - } - - dp = container_of(dp_display, struct dp_display_private, - dp_display); - memset(&dp->mst.cbs, 0, sizeof(dp->mst.cbs)); - dp->mst.drm_registered = false; - - DP_MST_DEBUG("dp mst drm uninstalled\n"); - - return 0; -} - -static int dp_display_mst_connector_install(struct dp_display *dp_display, - struct drm_connector *connector) -{ - int rc = 0; - struct dp_panel_in panel_in; - struct dp_panel *dp_panel; - struct dp_display_private *dp; - struct dp_mst_connector *mst_connector; - - if (!dp_display || !connector) { - pr_err("invalid input\n"); - return -EINVAL; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - mutex_lock(&dp->session_lock); - - if (!dp->mst.drm_registered) { - pr_debug("drm mst not registered\n"); - mutex_unlock(&dp->session_lock); - return -EPERM; - } - - panel_in.dev = &dp->pdev->dev; - panel_in.aux = dp->aux; - panel_in.catalog = &dp->catalog->panel; - panel_in.link = dp->link; - panel_in.connector = connector; - panel_in.base_panel = dp->panel; - panel_in.parser = dp->parser; - - dp_panel = dp_panel_get(&panel_in); - if (IS_ERR(dp_panel)) { - rc = PTR_ERR(dp_panel); - pr_err("failed to initialize panel, rc = %d\n", rc); - mutex_unlock(&dp->session_lock); - return rc; - } - - dp_panel->audio = dp_audio_get(dp->pdev, dp_panel, &dp->catalog->audio); - if (IS_ERR(dp_panel->audio)) { - rc = PTR_ERR(dp_panel->audio); - pr_err("[mst] failed to initialize audio, rc = %d\n", rc); - dp_panel->audio = NULL; - mutex_unlock(&dp->session_lock); - return rc; - } - - DP_MST_DEBUG("dp mst connector installed. conn:%d\n", - connector->base.id); - - mutex_lock(&dp->debug->dp_mst_connector_list.lock); - - mst_connector = kmalloc(sizeof(struct dp_mst_connector), - GFP_KERNEL); - if (!mst_connector) { - mutex_unlock(&dp->debug->dp_mst_connector_list.lock); - mutex_unlock(&dp->session_lock); - return -ENOMEM; - } - - mst_connector->debug_en = false; - mst_connector->conn = connector; - mst_connector->con_id = connector->base.id; - mst_connector->state = connector_status_unknown; - INIT_LIST_HEAD(&mst_connector->list); - - list_add(&mst_connector->list, - &dp->debug->dp_mst_connector_list.list); - - mutex_unlock(&dp->debug->dp_mst_connector_list.lock); - mutex_unlock(&dp->session_lock); - - return 0; -} - -static int dp_display_mst_connector_uninstall(struct dp_display *dp_display, - struct drm_connector *connector) -{ - int rc = 0; - struct sde_connector *sde_conn; - struct dp_panel *dp_panel; - struct dp_display_private *dp; - struct dp_mst_connector *con_to_remove, *temp_con; - - if (!dp_display || !connector) { - pr_err("invalid input\n"); - return -EINVAL; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - mutex_lock(&dp->session_lock); - - if (!dp->mst.drm_registered) { - pr_debug("drm mst not registered\n"); - mutex_unlock(&dp->session_lock); - return -EPERM; - } - - sde_conn = to_sde_connector(connector); - if (!sde_conn->drv_panel) { - pr_err("invalid panel for connector:%d\n", connector->base.id); - mutex_unlock(&dp->session_lock); - return -EINVAL; - } - - dp_panel = sde_conn->drv_panel; - dp_audio_put(dp_panel->audio); - dp_panel_put(dp_panel); - - DP_MST_DEBUG("dp mst connector uninstalled. conn:%d\n", - connector->base.id); - - mutex_lock(&dp->debug->dp_mst_connector_list.lock); - - list_for_each_entry_safe(con_to_remove, temp_con, - &dp->debug->dp_mst_connector_list.list, list) { - if (con_to_remove->conn == connector) { - list_del(&con_to_remove->list); - kfree(con_to_remove); - } - } - - mutex_unlock(&dp->debug->dp_mst_connector_list.lock); - mutex_unlock(&dp->session_lock); - - return rc; -} - -static int dp_display_mst_get_connector_info(struct dp_display *dp_display, - struct drm_connector *connector, - struct dp_mst_connector *mst_conn) -{ - struct dp_display_private *dp; - struct dp_mst_connector *conn, *temp_conn; - - if (!connector || !mst_conn) { - pr_err("invalid input\n"); - return -EINVAL; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - mutex_lock(&dp->session_lock); - if (!dp->mst.drm_registered) { - pr_debug("drm mst not registered\n"); - mutex_unlock(&dp->session_lock); - return -EPERM; - } - - mutex_lock(&dp->debug->dp_mst_connector_list.lock); - list_for_each_entry_safe(conn, temp_conn, - &dp->debug->dp_mst_connector_list.list, list) { - if (conn->con_id == connector->base.id) - memcpy(mst_conn, conn, sizeof(*mst_conn)); - } - mutex_unlock(&dp->debug->dp_mst_connector_list.lock); - mutex_unlock(&dp->session_lock); - return 0; -} - -static int dp_display_mst_connector_update_edid(struct dp_display *dp_display, - struct drm_connector *connector, - struct edid *edid) -{ - int rc = 0; - struct sde_connector *sde_conn; - struct dp_panel *dp_panel; - struct dp_display_private *dp; - - if (!dp_display || !connector || !edid) { - pr_err("invalid input\n"); - return -EINVAL; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - if (!dp->mst.drm_registered) { - pr_debug("drm mst not registered\n"); - return -EPERM; - } - - sde_conn = to_sde_connector(connector); - if (!sde_conn->drv_panel) { - pr_err("invalid panel for connector:%d\n", connector->base.id); - return -EINVAL; - } - - dp_panel = sde_conn->drv_panel; - rc = dp_panel->update_edid(dp_panel, edid); - - DP_MST_DEBUG("dp mst connector:%d edid updated. mode_cnt:%d\n", - connector->base.id, rc); - - return rc; -} - -static int dp_display_update_pps(struct dp_display *dp_display, - struct drm_connector *connector, char *pps_cmd) -{ - struct sde_connector *sde_conn; - struct dp_panel *dp_panel; - struct dp_display_private *dp; - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - sde_conn = to_sde_connector(connector); - if (!sde_conn->drv_panel) { - pr_err("invalid panel for connector:%d\n", connector->base.id); - return -EINVAL; - } - - dp_panel = sde_conn->drv_panel; - dp_panel->update_pps(dp_panel, pps_cmd); - return 0; -} - -static int dp_display_mst_connector_update_link_info( - struct dp_display *dp_display, - struct drm_connector *connector) -{ - int rc = 0; - struct sde_connector *sde_conn; - struct dp_panel *dp_panel; - struct dp_display_private *dp; - - if (!dp_display || !connector) { - pr_err("invalid input\n"); - return -EINVAL; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - if (!dp->mst.drm_registered) { - pr_debug("drm mst not registered\n"); - return -EPERM; - } - - sde_conn = to_sde_connector(connector); - if (!sde_conn->drv_panel) { - pr_err("invalid panel for connector:%d\n", connector->base.id); - return -EINVAL; - } - - dp_panel = sde_conn->drv_panel; - - memcpy(dp_panel->dpcd, dp->panel->dpcd, - DP_RECEIVER_CAP_SIZE + 1); - memcpy(dp_panel->dsc_dpcd, dp->panel->dsc_dpcd, - DP_RECEIVER_DSC_CAP_SIZE + 1); - memcpy(&dp_panel->link_info, &dp->panel->link_info, - sizeof(dp_panel->link_info)); - - DP_MST_DEBUG("dp mst connector:%d link info updated\n"); - - return rc; -} - -static int dp_display_mst_get_fixed_topology_port( - struct dp_display *dp_display, - u32 strm_id, u32 *port_num) -{ - struct dp_display_private *dp; - u32 port; - - if (!dp_display) { - pr_err("invalid input\n"); - return -EINVAL; - } - - if (strm_id >= DP_STREAM_MAX) { - pr_err("invalid stream id:%d\n", strm_id); - return -EINVAL; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - port = dp->parser->mst_fixed_port[strm_id]; - - if (!port || port > 255) - return -ENOENT; - - if (port_num) - *port_num = port; - - return 0; -} - -static int dp_display_get_mst_caps(struct dp_display *dp_display, - struct dp_mst_caps *mst_caps) -{ - int rc = 0; - struct dp_display_private *dp; - - if (!dp_display || !mst_caps) { - pr_err("invalid input\n"); - return -EINVAL; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - mst_caps->has_mst = dp->parser->has_mst; - mst_caps->max_streams_supported = (mst_caps->has_mst) ? 2 : 0; - mst_caps->max_dpcd_transaction_bytes = (mst_caps->has_mst) ? 16 : 0; - mst_caps->drm_aux = dp->aux->drm_aux; - - return rc; -} - -static int dp_display_probe(struct platform_device *pdev) -{ - int rc = 0; - struct dp_display_private *dp; - - if (!pdev || !pdev->dev.of_node) { - pr_err("pdev not found\n"); - rc = -ENODEV; - goto bail; - } - - dp = devm_kzalloc(&pdev->dev, sizeof(*dp), GFP_KERNEL); - if (!dp) { - rc = -ENOMEM; - goto bail; - } - - init_completion(&dp->notification_comp); - - dp->pdev = pdev; - dp->name = "drm_dp"; - - memset(&dp->mst, 0, sizeof(dp->mst)); - atomic_set(&dp->aborted, 0); - - rc = dp_display_init_aux_switch(dp); - if (rc) { - rc = -EPROBE_DEFER; - goto error; - } - - rc = dp_display_create_workqueue(dp); - if (rc) { - pr_err("Failed to create workqueue\n"); - goto error; - } - - platform_set_drvdata(pdev, dp); - - g_dp_display = &dp->dp_display; - - g_dp_display->enable = dp_display_enable; - g_dp_display->post_enable = dp_display_post_enable; - g_dp_display->pre_disable = dp_display_pre_disable; - g_dp_display->disable = dp_display_disable; - g_dp_display->set_mode = dp_display_set_mode; - g_dp_display->validate_mode = dp_display_validate_mode; - g_dp_display->get_modes = dp_display_get_modes; - g_dp_display->prepare = dp_display_prepare; - g_dp_display->unprepare = dp_display_unprepare; - g_dp_display->request_irq = dp_request_irq; - g_dp_display->get_debug = dp_get_debug; - g_dp_display->post_open = NULL; - g_dp_display->post_init = dp_display_post_init; - g_dp_display->config_hdr = dp_display_config_hdr; - g_dp_display->mst_install = dp_display_mst_install; - g_dp_display->mst_uninstall = dp_display_mst_uninstall; - g_dp_display->mst_connector_install = dp_display_mst_connector_install; - g_dp_display->mst_connector_uninstall = - dp_display_mst_connector_uninstall; - g_dp_display->mst_connector_update_edid = - dp_display_mst_connector_update_edid; - g_dp_display->mst_connector_update_link_info = - dp_display_mst_connector_update_link_info; - g_dp_display->get_mst_caps = dp_display_get_mst_caps; - g_dp_display->set_stream_info = dp_display_set_stream_info; - g_dp_display->update_pps = dp_display_update_pps; - g_dp_display->convert_to_dp_mode = dp_display_convert_to_dp_mode; - g_dp_display->mst_get_connector_info = - dp_display_mst_get_connector_info; - g_dp_display->mst_get_fixed_topology_port = - dp_display_mst_get_fixed_topology_port; - - rc = component_add(&pdev->dev, &dp_display_comp_ops); - if (rc) { - pr_err("component add failed, rc=%d\n", rc); - goto error; - } - - return 0; -error: - devm_kfree(&pdev->dev, dp); -bail: - return rc; -} - -int dp_display_get_displays(void **displays, int count) -{ - if (!displays) { - pr_err("invalid data\n"); - return -EINVAL; - } - - if (count != 1) { - pr_err("invalid number of displays\n"); - return -EINVAL; - } - - displays[0] = g_dp_display; - return count; -} - -int dp_display_get_num_of_displays(void) -{ - if (!g_dp_display) - return 0; - - return 1; -} - -int dp_display_get_num_of_streams(void) -{ - return DP_STREAM_MAX; -} - -static void dp_display_set_mst_state(void *dp_display, - enum dp_drv_state mst_state) -{ - struct dp_display_private *dp; - - if (!g_dp_display) { - pr_debug("dp display not initialized\n"); - return; - } - - dp = container_of(g_dp_display, struct dp_display_private, dp_display); - if (dp->mst.mst_active && dp->mst.cbs.set_drv_state) - dp->mst.cbs.set_drv_state(g_dp_display, mst_state); -} - -static int dp_display_remove(struct platform_device *pdev) -{ - struct dp_display_private *dp; - - if (!pdev) - return -EINVAL; - - dp = platform_get_drvdata(pdev); - - dp_display_deinit_sub_modules(dp); - - if (dp->wq) - destroy_workqueue(dp->wq); - - platform_set_drvdata(pdev, NULL); - devm_kfree(&pdev->dev, dp); - - return 0; -} - -static int dp_pm_prepare(struct device *dev) -{ - dp_display_set_mst_state(g_dp_display, PM_SUSPEND); - - return 0; -} - -static void dp_pm_complete(struct device *dev) -{ - dp_display_set_mst_state(g_dp_display, PM_DEFAULT); -} - -static const struct dev_pm_ops dp_pm_ops = { - .prepare = dp_pm_prepare, - .complete = dp_pm_complete, -}; - -static struct platform_driver dp_display_driver = { - .probe = dp_display_probe, - .remove = dp_display_remove, - .driver = { - .name = "msm-dp-display", - .of_match_table = dp_dt_match, - .suppress_bind_attrs = true, - .pm = &dp_pm_ops, - }, -}; - -static int __init dp_display_init(void) -{ - int ret; - - ret = platform_driver_register(&dp_display_driver); - if (ret) { - pr_err("driver register failed\n"); - return ret; - } - - return ret; -} -late_initcall(dp_display_init); - -static void __exit dp_display_cleanup(void) -{ - platform_driver_unregister(&dp_display_driver); -} -module_exit(dp_display_cleanup); diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h deleted file mode 100644 index fe332aff47f5b21f89ac96e31df4518023755bcf..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ /dev/null @@ -1,145 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. - */ - -#ifndef _DP_DISPLAY_H_ -#define _DP_DISPLAY_H_ - -#include -#include -#include - -#include "dp_panel.h" - -#define DP_MST_SIM_MAX_PORTS 2 - -enum dp_drv_state { - PM_DEFAULT, - PM_SUSPEND, -}; - -struct dp_mst_hpd_info { - bool mst_protocol; - bool mst_hpd_sim; - u32 mst_port_cnt; - u8 *edid; -}; - -struct dp_mst_drm_cbs { - void (*hpd)(void *display, bool hpd_status, - struct dp_mst_hpd_info *info); - void (*hpd_irq)(void *display, struct dp_mst_hpd_info *info); - void (*set_drv_state)(void *dp_display, - enum dp_drv_state mst_state); -}; - -struct dp_mst_drm_install_info { - void *dp_mst_prv_info; - const struct dp_mst_drm_cbs *cbs; -}; - -struct dp_mst_caps { - bool has_mst; - u32 max_streams_supported; - u32 max_dpcd_transaction_bytes; - struct drm_dp_aux *drm_aux; -}; - -struct dp_mst_connector { - bool debug_en; - int con_id; - int hdisplay; - int vdisplay; - int vrefresh; - int aspect_ratio; - struct drm_connector *conn; - struct mutex lock; - struct list_head list; - enum drm_connector_status state; -}; - -struct dp_display { - struct drm_device *drm_dev; - struct dp_bridge *bridge; - struct drm_connector *base_connector; - void *base_dp_panel; - bool is_sst_connected; - bool is_mst_supported; - u32 max_pclk_khz; - void *dp_mst_prv_info; - - int (*enable)(struct dp_display *dp_display, void *panel); - int (*post_enable)(struct dp_display *dp_display, void *panel); - - int (*pre_disable)(struct dp_display *dp_display, void *panel); - int (*disable)(struct dp_display *dp_display, void *panel); - - int (*set_mode)(struct dp_display *dp_display, void *panel, - struct dp_display_mode *mode); - enum drm_mode_status (*validate_mode)(struct dp_display *dp_display, - void *panel, struct drm_display_mode *mode); - int (*get_modes)(struct dp_display *dp_display, void *panel, - struct dp_display_mode *dp_mode); - int (*prepare)(struct dp_display *dp_display, void *panel); - int (*unprepare)(struct dp_display *dp_display, void *panel); - int (*request_irq)(struct dp_display *dp_display); - struct dp_debug *(*get_debug)(struct dp_display *dp_display); - void (*post_open)(struct dp_display *dp_display); - int (*config_hdr)(struct dp_display *dp_display, void *panel, - struct drm_msm_ext_hdr_metadata *hdr_meta, - bool dhdr_update); - int (*post_init)(struct dp_display *dp_display); - int (*mst_install)(struct dp_display *dp_display, - struct dp_mst_drm_install_info *mst_install_info); - int (*mst_uninstall)(struct dp_display *dp_display); - int (*mst_connector_install)(struct dp_display *dp_display, - struct drm_connector *connector); - int (*mst_connector_uninstall)(struct dp_display *dp_display, - struct drm_connector *connector); - int (*mst_connector_update_edid)(struct dp_display *dp_display, - struct drm_connector *connector, - struct edid *edid); - int (*mst_connector_update_link_info)(struct dp_display *dp_display, - struct drm_connector *connector); - int (*mst_get_connector_info)(struct dp_display *dp_display, - struct drm_connector *connector, - struct dp_mst_connector *mst_conn); - int (*mst_get_fixed_topology_port)(struct dp_display *dp_display, - u32 strm_id, u32 *port_num); - int (*get_mst_caps)(struct dp_display *dp_display, - struct dp_mst_caps *mst_caps); - int (*set_stream_info)(struct dp_display *dp_display, void *panel, - u32 strm_id, u32 start_slot, u32 num_slots, u32 pbn, - int vcpi); - void (*convert_to_dp_mode)(struct dp_display *dp_display, void *panel, - const struct drm_display_mode *drm_mode, - struct dp_display_mode *dp_mode); - int (*update_pps)(struct dp_display *dp_display, - struct drm_connector *connector, char *pps_cmd); -}; - -#ifdef CONFIG_DRM_MSM_DP -int dp_display_get_num_of_displays(void); -int dp_display_get_displays(void **displays, int count); -int dp_display_get_num_of_streams(void); -#else -static inline int dp_display_get_num_of_displays(void) -{ - return 0; -} -static inline int dp_display_get_displays(void **displays, int count) -{ - return 0; -} -static inline int dp_display_get_num_of_streams(void) -{ - return 0; -} -static inline int dp_connector_update_pps(struct drm_connector *connector, - char *pps_cmd, void *display) -{ - return 0; -} -#endif -#endif /* _DP_DISPLAY_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c deleted file mode 100644 index b3b116a874a4e90a197766988bdaaea6bcb23420..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ /dev/null @@ -1,624 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[drm-dp]: %s: " fmt, __func__ - -#include -#include -#include - -#include "msm_drv.h" -#include "msm_kms.h" -#include "sde_connector.h" -#include "dp_drm.h" -#include "dp_debug.h" - -#define DP_MST_DEBUG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) - -#define to_dp_bridge(x) container_of((x), struct dp_bridge, base) - -void convert_to_drm_mode(const struct dp_display_mode *dp_mode, - struct drm_display_mode *drm_mode) -{ - u32 flags = 0; - - memset(drm_mode, 0, sizeof(*drm_mode)); - - drm_mode->hdisplay = dp_mode->timing.h_active; - drm_mode->hsync_start = drm_mode->hdisplay + - dp_mode->timing.h_front_porch; - drm_mode->hsync_end = drm_mode->hsync_start + - dp_mode->timing.h_sync_width; - drm_mode->htotal = drm_mode->hsync_end + dp_mode->timing.h_back_porch; - drm_mode->hskew = dp_mode->timing.h_skew; - - drm_mode->vdisplay = dp_mode->timing.v_active; - drm_mode->vsync_start = drm_mode->vdisplay + - dp_mode->timing.v_front_porch; - drm_mode->vsync_end = drm_mode->vsync_start + - dp_mode->timing.v_sync_width; - drm_mode->vtotal = drm_mode->vsync_end + dp_mode->timing.v_back_porch; - - drm_mode->vrefresh = dp_mode->timing.refresh_rate; - drm_mode->clock = dp_mode->timing.pixel_clk_khz; - - if (dp_mode->timing.h_active_low) - flags |= DRM_MODE_FLAG_NHSYNC; - else - flags |= DRM_MODE_FLAG_PHSYNC; - - if (dp_mode->timing.v_active_low) - flags |= DRM_MODE_FLAG_NVSYNC; - else - flags |= DRM_MODE_FLAG_PVSYNC; - - drm_mode->flags = flags; - - drm_mode->type = 0x48; - drm_mode_set_name(drm_mode); -} - -static int dp_bridge_attach(struct drm_bridge *dp_bridge) -{ - struct dp_bridge *bridge = to_dp_bridge(dp_bridge); - - if (!dp_bridge) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - pr_debug("[%d] attached\n", bridge->id); - - return 0; -} - -static void dp_bridge_pre_enable(struct drm_bridge *drm_bridge) -{ - int rc = 0; - struct dp_bridge *bridge; - struct dp_display *dp; - - if (!drm_bridge) { - pr_err("Invalid params\n"); - return; - } - - bridge = to_dp_bridge(drm_bridge); - dp = bridge->display; - - if (!bridge->connector) { - pr_err("Invalid connector\n"); - return; - } - - if (!bridge->dp_panel) { - pr_err("Invalid dp_panel\n"); - return; - } - - /* By this point mode should have been validated through mode_fixup */ - rc = dp->set_mode(dp, bridge->dp_panel, &bridge->dp_mode); - if (rc) { - pr_err("[%d] failed to perform a mode set, rc=%d\n", - bridge->id, rc); - return; - } - - rc = dp->prepare(dp, bridge->dp_panel); - if (rc) { - pr_err("[%d] DP display prepare failed, rc=%d\n", - bridge->id, rc); - return; - } - - /* for SST force stream id, start slot and total slots to 0 */ - dp->set_stream_info(dp, bridge->dp_panel, 0, 0, 0, 0, 0); - - rc = dp->enable(dp, bridge->dp_panel); - if (rc) { - pr_err("[%d] DP display enable failed, rc=%d\n", - bridge->id, rc); - dp->unprepare(dp, bridge->dp_panel); - } -} - -static void dp_bridge_enable(struct drm_bridge *drm_bridge) -{ - int rc = 0; - struct dp_bridge *bridge; - struct dp_display *dp; - - if (!drm_bridge) { - pr_err("Invalid params\n"); - return; - } - - bridge = to_dp_bridge(drm_bridge); - if (!bridge->connector) { - pr_err("Invalid connector\n"); - return; - } - - if (!bridge->dp_panel) { - pr_err("Invalid dp_panel\n"); - return; - } - - dp = bridge->display; - - rc = dp->post_enable(dp, bridge->dp_panel); - if (rc) - pr_err("[%d] DP display post enable failed, rc=%d\n", - bridge->id, rc); -} - -static void dp_bridge_disable(struct drm_bridge *drm_bridge) -{ - int rc = 0; - struct dp_bridge *bridge; - struct dp_display *dp; - - if (!drm_bridge) { - pr_err("Invalid params\n"); - return; - } - - bridge = to_dp_bridge(drm_bridge); - if (!bridge->connector) { - pr_err("Invalid connector\n"); - return; - } - - if (!bridge->dp_panel) { - pr_err("Invalid dp_panel\n"); - return; - } - - dp = bridge->display; - - if (!dp) { - pr_err("dp is null\n"); - return; - } - - if (dp) - sde_connector_helper_bridge_disable(bridge->connector); - - rc = dp->pre_disable(dp, bridge->dp_panel); - if (rc) { - pr_err("[%d] DP display pre disable failed, rc=%d\n", - bridge->id, rc); - } -} - -static void dp_bridge_post_disable(struct drm_bridge *drm_bridge) -{ - int rc = 0; - struct dp_bridge *bridge; - struct dp_display *dp; - - if (!drm_bridge) { - pr_err("Invalid params\n"); - return; - } - - bridge = to_dp_bridge(drm_bridge); - if (!bridge->connector) { - pr_err("Invalid connector\n"); - return; - } - - if (!bridge->dp_panel) { - pr_err("Invalid dp_panel\n"); - return; - } - - dp = bridge->display; - - rc = dp->disable(dp, bridge->dp_panel); - if (rc) { - pr_err("[%d] DP display disable failed, rc=%d\n", - bridge->id, rc); - return; - } - - rc = dp->unprepare(dp, bridge->dp_panel); - if (rc) { - pr_err("[%d] DP display unprepare failed, rc=%d\n", - bridge->id, rc); - return; - } -} - -static void dp_bridge_mode_set(struct drm_bridge *drm_bridge, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct dp_bridge *bridge; - struct dp_display *dp; - - if (!drm_bridge || !mode || !adjusted_mode) { - pr_err("Invalid params\n"); - return; - } - - bridge = to_dp_bridge(drm_bridge); - if (!bridge->connector) { - pr_err("Invalid connector\n"); - return; - } - - if (!bridge->dp_panel) { - pr_err("Invalid dp_panel\n"); - return; - } - - dp = bridge->display; - - dp->convert_to_dp_mode(dp, bridge->dp_panel, adjusted_mode, - &bridge->dp_mode); -} - -static bool dp_bridge_mode_fixup(struct drm_bridge *drm_bridge, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - bool ret = true; - struct dp_display_mode dp_mode; - struct dp_bridge *bridge; - struct dp_display *dp; - - if (!drm_bridge || !mode || !adjusted_mode) { - pr_err("Invalid params\n"); - ret = false; - goto end; - } - - bridge = to_dp_bridge(drm_bridge); - if (!bridge->connector) { - pr_err("Invalid connector\n"); - ret = false; - goto end; - } - - if (!bridge->dp_panel) { - pr_err("Invalid dp_panel\n"); - ret = false; - goto end; - } - - dp = bridge->display; - - dp->convert_to_dp_mode(dp, bridge->dp_panel, mode, &dp_mode); - convert_to_drm_mode(&dp_mode, adjusted_mode); -end: - return ret; -} - -static const struct drm_bridge_funcs dp_bridge_ops = { - .attach = dp_bridge_attach, - .mode_fixup = dp_bridge_mode_fixup, - .pre_enable = dp_bridge_pre_enable, - .enable = dp_bridge_enable, - .disable = dp_bridge_disable, - .post_disable = dp_bridge_post_disable, - .mode_set = dp_bridge_mode_set, -}; - -int dp_connector_config_hdr(struct drm_connector *connector, void *display, - struct sde_connector_state *c_state) -{ - struct dp_display *dp = display; - struct sde_connector *sde_conn; - - if (!display || !c_state || !connector) { - pr_err("invalid params\n"); - return -EINVAL; - } - - sde_conn = to_sde_connector(connector); - if (!sde_conn->drv_panel) { - pr_err("invalid dp panel\n"); - return -EINVAL; - } - - return dp->config_hdr(dp, sde_conn->drv_panel, &c_state->hdr_meta, - c_state->dyn_hdr_meta.dynamic_hdr_update); -} - -int dp_connector_post_init(struct drm_connector *connector, void *display) -{ - int rc; - struct dp_display *dp_display = display; - struct sde_connector *sde_conn; - - if (!dp_display || !connector) - return -EINVAL; - - dp_display->base_connector = connector; - dp_display->bridge->connector = connector; - - if (dp_display->post_init) { - rc = dp_display->post_init(dp_display); - if (rc) - goto end; - } - - sde_conn = to_sde_connector(connector); - dp_display->bridge->dp_panel = sde_conn->drv_panel; - - rc = dp_mst_init(dp_display); -end: - return rc; -} - -int dp_connector_get_mode_info(struct drm_connector *connector, - const struct drm_display_mode *drm_mode, - struct msm_mode_info *mode_info, - u32 max_mixer_width, void *display) -{ - const u32 dual_lm = 2; - const u32 single_lm = 1; - const u32 single_intf = 1; - const u32 no_enc = 0; - struct msm_display_topology *topology; - struct sde_connector *sde_conn; - struct dp_panel *dp_panel; - struct dp_display_mode dp_mode; - struct dp_display *dp_disp = display; - - if (!drm_mode || !mode_info || !max_mixer_width || !connector || - !display) { - pr_err("invalid params\n"); - return -EINVAL; - } - - memset(mode_info, 0, sizeof(*mode_info)); - - sde_conn = to_sde_connector(connector); - dp_panel = sde_conn->drv_panel; - - topology = &mode_info->topology; - topology->num_lm = (max_mixer_width <= drm_mode->hdisplay) ? - dual_lm : single_lm; - topology->num_enc = no_enc; - topology->num_intf = single_intf; - - mode_info->frame_rate = drm_mode->vrefresh; - mode_info->vtotal = drm_mode->vtotal; - - mode_info->wide_bus_en = dp_panel->widebus_en; - - dp_disp->convert_to_dp_mode(dp_disp, dp_panel, drm_mode, &dp_mode); - - if (dp_mode.timing.comp_info.comp_ratio) { - memcpy(&mode_info->comp_info, - &dp_mode.timing.comp_info, - sizeof(mode_info->comp_info)); - - topology->num_enc = topology->num_lm; - } - - return 0; -} - -int dp_connector_get_info(struct drm_connector *connector, - struct msm_display_info *info, void *data) -{ - struct dp_display *display = data; - - if (!info || !display || !display->drm_dev) { - pr_err("invalid params\n"); - return -EINVAL; - } - - info->intf_type = DRM_MODE_CONNECTOR_DisplayPort; - - info->num_of_h_tiles = 1; - info->h_tile_instance[0] = 0; - info->is_connected = display->is_sst_connected; - info->capabilities = MSM_DISPLAY_CAP_VID_MODE | MSM_DISPLAY_CAP_EDID | - MSM_DISPLAY_CAP_HOT_PLUG; - - return 0; -} - -enum drm_connector_status dp_connector_detect(struct drm_connector *conn, - bool force, - void *display) -{ - enum drm_connector_status status = connector_status_unknown; - struct msm_display_info info; - int rc; - - if (!conn || !display) - return status; - - /* get display dp_info */ - memset(&info, 0x0, sizeof(info)); - rc = dp_connector_get_info(conn, &info, display); - if (rc) { - pr_err("failed to get display info, rc=%d\n", rc); - return connector_status_disconnected; - } - - if (info.capabilities & MSM_DISPLAY_CAP_HOT_PLUG) - status = (info.is_connected ? connector_status_connected : - connector_status_disconnected); - else - status = connector_status_connected; - - conn->display_info.width_mm = info.width_mm; - conn->display_info.height_mm = info.height_mm; - - return status; -} - -void dp_connector_post_open(struct drm_connector *connector, void *display) -{ - struct dp_display *dp; - - if (!display) { - pr_err("invalid input\n"); - return; - } - - dp = display; - - if (dp->post_open) - dp->post_open(dp); -} - -int dp_connector_get_modes(struct drm_connector *connector, - void *display) -{ - int rc = 0; - struct dp_display *dp; - struct dp_display_mode *dp_mode = NULL; - struct drm_display_mode *m, drm_mode; - struct sde_connector *sde_conn; - - if (!connector || !display) - return 0; - - sde_conn = to_sde_connector(connector); - if (!sde_conn->drv_panel) { - pr_err("invalid dp panel\n"); - return 0; - } - - dp = display; - - dp_mode = kzalloc(sizeof(*dp_mode), GFP_KERNEL); - if (!dp_mode) - return 0; - - /* pluggable case assumes EDID is read when HPD */ - if (dp->is_sst_connected) { - rc = dp->get_modes(dp, sde_conn->drv_panel, dp_mode); - if (!rc) - pr_err("failed to get DP sink modes, rc=%d\n", rc); - - if (dp_mode->timing.pixel_clk_khz) { /* valid DP mode */ - memset(&drm_mode, 0x0, sizeof(drm_mode)); - convert_to_drm_mode(dp_mode, &drm_mode); - m = drm_mode_duplicate(connector->dev, &drm_mode); - if (!m) { - pr_err("failed to add mode %ux%u\n", - drm_mode.hdisplay, - drm_mode.vdisplay); - kfree(dp_mode); - return 0; - } - m->width_mm = connector->display_info.width_mm; - m->height_mm = connector->display_info.height_mm; - drm_mode_probed_add(connector, m); - } - } else { - pr_err("No sink connected\n"); - } - kfree(dp_mode); - - return rc; -} - -int dp_drm_bridge_init(void *data, struct drm_encoder *encoder) -{ - int rc = 0; - struct dp_bridge *bridge; - struct drm_device *dev; - struct dp_display *display = data; - struct msm_drm_private *priv = NULL; - - bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); - if (!bridge) { - rc = -ENOMEM; - goto error; - } - - dev = display->drm_dev; - bridge->display = display; - bridge->base.funcs = &dp_bridge_ops; - bridge->base.encoder = encoder; - - priv = dev->dev_private; - - rc = drm_bridge_attach(encoder, &bridge->base, NULL); - if (rc) { - pr_err("failed to attach bridge, rc=%d\n", rc); - goto error_free_bridge; - } - - rc = display->request_irq(display); - if (rc) { - pr_err("request_irq failed, rc=%d\n", rc); - goto error_free_bridge; - } - - encoder->bridge = &bridge->base; - priv->bridges[priv->num_bridges++] = &bridge->base; - display->bridge = bridge; - - return 0; -error_free_bridge: - kfree(bridge); -error: - return rc; -} - -void dp_drm_bridge_deinit(void *data) -{ - struct dp_display *display = data; - struct dp_bridge *bridge = display->bridge; - - if (bridge && bridge->base.encoder) - bridge->base.encoder->bridge = NULL; - - kfree(bridge); -} - -enum drm_mode_status dp_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode, void *display) -{ - struct dp_display *dp_disp; - struct sde_connector *sde_conn; - - if (!mode || !display || !connector) { - pr_err("invalid params\n"); - return MODE_ERROR; - } - - sde_conn = to_sde_connector(connector); - if (!sde_conn->drv_panel) { - pr_err("invalid dp panel\n"); - return MODE_ERROR; - } - - dp_disp = display; - mode->vrefresh = drm_mode_vrefresh(mode); - - return dp_disp->validate_mode(dp_disp, sde_conn->drv_panel, mode); -} - -int dp_connector_update_pps(struct drm_connector *connector, - char *pps_cmd, void *display) -{ - struct dp_display *dp_disp; - struct sde_connector *sde_conn; - - if (!display || !connector) { - pr_err("invalid params\n"); - return -EINVAL; - } - - sde_conn = to_sde_connector(connector); - if (!sde_conn->drv_panel) { - pr_err("invalid dp panel\n"); - return MODE_ERROR; - } - - dp_disp = display; - return dp_disp->update_pps(dp_disp, connector, pps_cmd); -} diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h deleted file mode 100644 index f887f82b7be49ce8d57f21ef5dd8edf6ab5c0ff3..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_drm.h +++ /dev/null @@ -1,247 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. - */ - -#ifndef _DP_DRM_H_ -#define _DP_DRM_H_ - -#include -#include -#include -#include - -#include "msm_drv.h" -#include "dp_display.h" - -struct dp_bridge { - struct drm_bridge base; - u32 id; - - struct drm_connector *connector; - struct dp_display *display; - struct dp_display_mode dp_mode; - void *dp_panel; -}; - - -#ifdef CONFIG_DRM_MSM_DP -/** - * dp_connector_config_hdr - callback to configure HDR - * @connector: Pointer to drm connector structure - * @display: Pointer to private display handle - * @c_state: connect state data - * Returns: Zero on success - */ -int dp_connector_config_hdr(struct drm_connector *connector, - void *display, - struct sde_connector_state *c_state); - -/** - * dp_connector_post_init - callback to perform additional initialization steps - * @connector: Pointer to drm connector structure - * @display: Pointer to private display handle - * Returns: Zero on success - */ -int dp_connector_post_init(struct drm_connector *connector, void *display); - -/** - * dp_connector_detect - callback to determine if connector is connected - * @connector: Pointer to drm connector structure - * @force: Force detect setting from drm framework - * @display: Pointer to private display handle - * Returns: Connector 'is connected' status - */ -enum drm_connector_status dp_connector_detect(struct drm_connector *conn, - bool force, - void *display); - -/** - * dp_connector_get_modes - callback to add drm modes via drm_mode_probed_add() - * @connector: Pointer to drm connector structure - * @display: Pointer to private display handle - * Returns: Number of modes added - */ -int dp_connector_get_modes(struct drm_connector *connector, - void *display); - -/** - * dp_connector_mode_valid - callback to determine if specified mode is valid - * @connector: Pointer to drm connector structure - * @mode: Pointer to drm mode structure - * @display: Pointer to private display handle - * Returns: Validity status for specified mode - */ -enum drm_mode_status dp_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode, - void *display); - -/** - * dp_connector_get_mode_info - retrieve information of the mode selected - * @connector: Pointer to drm connector structure - * @drm_mode: Display mode set for the display - * @mode_info: Out parameter. Information of the mode - * @max_mixer_width: max width supported by HW layer mixer - * @display: Pointer to private display structure - * Returns: zero on success - */ -int dp_connector_get_mode_info(struct drm_connector *connector, - const struct drm_display_mode *drm_mode, - struct msm_mode_info *mode_info, - u32 max_mixer_width, void *display); - -/** - * dp_connector_get_info - retrieve connector display info - * @connector: Pointer to drm connector structure - * @info: Out parameter. Information of the connected display - * @display: Pointer to private display structure - * Returns: zero on success - */ -int dp_connector_get_info(struct drm_connector *connector, - struct msm_display_info *info, void *display); - -/** - * dp_connector_post_open - handle the post open functionalites - * @connector: Pointer to drm connector structure - * @display: Pointer to private display structure - */ -void dp_connector_post_open(struct drm_connector *connector, void *display); - -int dp_drm_bridge_init(void *display, - struct drm_encoder *encoder); - -void dp_drm_bridge_deinit(void *display); - -/** - * convert_to_drm_mode - convert dp mode to drm mode - * @dp_mode: Point to dp mode - * @drm_mode: Pointer to drm mode - */ -void convert_to_drm_mode(const struct dp_display_mode *dp_mode, - struct drm_display_mode *drm_mode); - -/** - * dp_connector_update_pps - update pps for given connector - * @dp_mode: Point to dp mode - * @pps_cmd: PPS packet - * @display: Pointer to private display structure - */ -int dp_connector_update_pps(struct drm_connector *connector, - char *pps_cmd, void *display); - -/** - * dp_mst_drm_bridge_init - initialize mst bridge - * @display: Pointer to private display structure - * @encoder: Pointer to encoder for mst bridge mapping - */ -int dp_mst_drm_bridge_init(void *display, - struct drm_encoder *encoder); - -/** - * dp_mst_drm_bridge_deinit - de-initialize mst bridges - * @display: Pointer to private display structure - */ -void dp_mst_drm_bridge_deinit(void *display); - -/** - * dp_mst_init - initialize mst objects for the given display - * @display: Pointer to private display structure - */ -int dp_mst_init(struct dp_display *dp_display); - -/** - * dp_mst_deinit - de-initialize mst objects for the given display - * @display: Pointer to private display structure - */ -void dp_mst_deinit(struct dp_display *dp_display); -#else -static inline int dp_connector_config_hdr(struct drm_connector *connector, - void *display, struct sde_connector_state *c_state) -{ - return 0; -} - -static inline int dp_connector_post_init(struct drm_connector *connector, - void *display) -{ - return 0; -} - -static inline enum drm_connector_status dp_connector_detect( - struct drm_connector *conn, - bool force, - void *display) -{ - return 0; -} - - -static inline int dp_connector_get_modes(struct drm_connector *connector, - void *display) -{ - return 0; -} - -static inline enum drm_mode_status dp_connector_mode_valid( - struct drm_connector *connector, - struct drm_display_mode *mode, - void *display) -{ - return MODE_OK; -} - -static inline int dp_connector_get_mode_info(struct drm_connector *connector, - const struct drm_display_mode *drm_mode, - struct msm_mode_info *mode_info, - u32 max_mixer_width, void *display) -{ - return 0; -} - -static inline int dp_connector_get_info(struct drm_connector *connector, - struct msm_display_info *info, void *display) -{ - return 0; -} - -static inline void dp_connector_post_open(struct drm_connector *connector, - void *display) -{ -} - -static inline int dp_drm_bridge_init(void *display, struct drm_encoder *encoder) -{ - return 0; -} - -static inline void dp_drm_bridge_deinit(void *display) -{ -} - -static inline void convert_to_drm_mode(const struct dp_display_mode *dp_mode, - struct drm_display_mode *drm_mode) -{ -} - -static inline int dp_mst_drm_bridge_init(void *display, - struct drm_encoder *encoder) -{ - return 0; -} - -static inline void dp_mst_drm_bridge_deinit(void *display) -{ -} - -static inline int dp_mst_init(struct dp_display *dp_display) -{ - return 0; -} - -static inline int dp_mst_deinit(struct dp_display *dp_display) -{ - return 0; -} -#endif - -#endif /* _DP_DRM_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_gpio_hpd.c b/drivers/gpu/drm/msm/dp/dp_gpio_hpd.c deleted file mode 100644 index 86082eae42ac927da7ae525045dd9909938e16e3..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_gpio_hpd.c +++ /dev/null @@ -1,297 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "dp_gpio_hpd.h" - -struct dp_gpio_hpd_private { - struct device *dev; - struct dp_hpd base; - struct dss_gpio gpio_cfg; - struct delayed_work work; - struct dp_hpd_cb *cb; - int irq; - bool hpd; -}; - -static int dp_gpio_hpd_connect(struct dp_gpio_hpd_private *gpio_hpd, bool hpd) -{ - int rc = 0; - - if (!gpio_hpd) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto error; - } - - gpio_hpd->base.hpd_high = hpd; - gpio_hpd->base.alt_mode_cfg_done = hpd; - gpio_hpd->base.hpd_irq = false; - - if (!gpio_hpd->cb || - !gpio_hpd->cb->configure || - !gpio_hpd->cb->disconnect) { - pr_err("invalid cb\n"); - rc = -EINVAL; - goto error; - } - - if (hpd) - rc = gpio_hpd->cb->configure(gpio_hpd->dev); - else - rc = gpio_hpd->cb->disconnect(gpio_hpd->dev); - -error: - return rc; -} - -static int dp_gpio_hpd_attention(struct dp_gpio_hpd_private *gpio_hpd) -{ - int rc = 0; - - if (!gpio_hpd) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto error; - } - - gpio_hpd->base.hpd_irq = true; - - if (gpio_hpd->cb && gpio_hpd->cb->attention) - rc = gpio_hpd->cb->attention(gpio_hpd->dev); - -error: - return rc; -} - -static irqreturn_t dp_gpio_isr(int unused, void *data) -{ - struct dp_gpio_hpd_private *gpio_hpd = data; - u32 const disconnect_timeout_retry = 50; - bool hpd; - int i; - - if (!gpio_hpd) - return IRQ_NONE; - - hpd = gpio_get_value_cansleep(gpio_hpd->gpio_cfg.gpio); - - if (!gpio_hpd->hpd && hpd) { - gpio_hpd->hpd = true; - queue_delayed_work(system_wq, &gpio_hpd->work, 0); - return IRQ_HANDLED; - } - - if (!gpio_hpd->hpd) - return IRQ_HANDLED; - - /* In DP 1.2 spec, 100msec is recommended for the detection - * of HPD connect event. Here we'll poll HPD status for - * 50x2ms = 100ms and if HPD is always low, we know DP is - * disconnected. If HPD is high, HPD_IRQ will be handled - */ - for (i = 0; i < disconnect_timeout_retry; i++) { - if (hpd) { - dp_gpio_hpd_attention(gpio_hpd); - return IRQ_HANDLED; - } - usleep_range(2000, 2100); - hpd = gpio_get_value_cansleep(gpio_hpd->gpio_cfg.gpio); - } - - gpio_hpd->hpd = false; - queue_delayed_work(system_wq, &gpio_hpd->work, 0); - return IRQ_HANDLED; -} - -static void dp_gpio_hpd_work(struct work_struct *work) -{ - struct delayed_work *dw = to_delayed_work(work); - struct dp_gpio_hpd_private *gpio_hpd = container_of(dw, - struct dp_gpio_hpd_private, work); - int ret; - - if (gpio_hpd->hpd) { - devm_free_irq(gpio_hpd->dev, - gpio_hpd->irq, gpio_hpd); - ret = devm_request_threaded_irq(gpio_hpd->dev, - gpio_hpd->irq, NULL, - dp_gpio_isr, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "dp-gpio-intp", gpio_hpd); - dp_gpio_hpd_connect(gpio_hpd, true); - } else { - devm_free_irq(gpio_hpd->dev, - gpio_hpd->irq, gpio_hpd); - ret = devm_request_threaded_irq(gpio_hpd->dev, - gpio_hpd->irq, NULL, - dp_gpio_isr, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, - "dp-gpio-intp", gpio_hpd); - dp_gpio_hpd_connect(gpio_hpd, false); - } - - if (ret < 0) - pr_err("Cannot claim IRQ dp-gpio-intp\n"); -} - -static int dp_gpio_hpd_simulate_connect(struct dp_hpd *dp_hpd, bool hpd) -{ - int rc = 0; - struct dp_gpio_hpd_private *gpio_hpd; - - if (!dp_hpd) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto error; - } - - gpio_hpd = container_of(dp_hpd, struct dp_gpio_hpd_private, base); - - dp_gpio_hpd_connect(gpio_hpd, hpd); -error: - return rc; -} - -static int dp_gpio_hpd_simulate_attention(struct dp_hpd *dp_hpd, int vdo) -{ - int rc = 0; - struct dp_gpio_hpd_private *gpio_hpd; - - if (!dp_hpd) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto error; - } - - gpio_hpd = container_of(dp_hpd, struct dp_gpio_hpd_private, base); - - dp_gpio_hpd_attention(gpio_hpd); -error: - return rc; -} - -int dp_gpio_hpd_register(struct dp_hpd *dp_hpd) -{ - struct dp_gpio_hpd_private *gpio_hpd; - int edge; - int rc = 0; - - if (!dp_hpd) - return -EINVAL; - - gpio_hpd = container_of(dp_hpd, struct dp_gpio_hpd_private, base); - - gpio_hpd->hpd = gpio_get_value_cansleep(gpio_hpd->gpio_cfg.gpio); - - edge = gpio_hpd->hpd ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; - rc = devm_request_threaded_irq(gpio_hpd->dev, gpio_hpd->irq, NULL, - dp_gpio_isr, - edge | IRQF_ONESHOT, - "dp-gpio-intp", gpio_hpd); - if (rc) { - pr_err("Failed to request INTP threaded IRQ: %d\n", rc); - return rc; - } - - if (gpio_hpd->hpd) - queue_delayed_work(system_wq, &gpio_hpd->work, 0); - - return rc; -} - -struct dp_hpd *dp_gpio_hpd_get(struct device *dev, - struct dp_hpd_cb *cb) -{ - int rc = 0; - const char *hpd_gpio_name = "qcom,dp-hpd-gpio"; - struct dp_gpio_hpd_private *gpio_hpd; - struct dp_pinctrl pinctrl = {0}; - - if (!dev || !cb) { - pr_err("invalid device\n"); - rc = -EINVAL; - goto error; - } - - gpio_hpd = devm_kzalloc(dev, sizeof(*gpio_hpd), GFP_KERNEL); - if (!gpio_hpd) { - rc = -ENOMEM; - goto error; - } - - pinctrl.pin = devm_pinctrl_get(dev); - if (!IS_ERR_OR_NULL(pinctrl.pin)) { - pinctrl.state_hpd_active = pinctrl_lookup_state(pinctrl.pin, - "mdss_dp_hpd_active"); - if (!IS_ERR_OR_NULL(pinctrl.state_hpd_active)) { - rc = pinctrl_select_state(pinctrl.pin, - pinctrl.state_hpd_active); - if (rc) { - pr_err("failed to set hpd active state\n"); - goto gpio_error; - } - } - } - - gpio_hpd->gpio_cfg.gpio = of_get_named_gpio(dev->of_node, - hpd_gpio_name, 0); - if (!gpio_is_valid(gpio_hpd->gpio_cfg.gpio)) { - pr_err("%s gpio not specified\n", hpd_gpio_name); - rc = -EINVAL; - goto gpio_error; - } - - strlcpy(gpio_hpd->gpio_cfg.gpio_name, hpd_gpio_name, - sizeof(gpio_hpd->gpio_cfg.gpio_name)); - gpio_hpd->gpio_cfg.value = 0; - - rc = gpio_request(gpio_hpd->gpio_cfg.gpio, - gpio_hpd->gpio_cfg.gpio_name); - if (rc) { - pr_err("%s: failed to request gpio\n", hpd_gpio_name); - goto gpio_error; - } - gpio_direction_input(gpio_hpd->gpio_cfg.gpio); - - gpio_hpd->dev = dev; - gpio_hpd->cb = cb; - gpio_hpd->irq = gpio_to_irq(gpio_hpd->gpio_cfg.gpio); - INIT_DELAYED_WORK(&gpio_hpd->work, dp_gpio_hpd_work); - - gpio_hpd->base.simulate_connect = dp_gpio_hpd_simulate_connect; - gpio_hpd->base.simulate_attention = dp_gpio_hpd_simulate_attention; - gpio_hpd->base.register_hpd = dp_gpio_hpd_register; - - return &gpio_hpd->base; - -gpio_error: - devm_kfree(dev, gpio_hpd); -error: - return ERR_PTR(rc); -} - -void dp_gpio_hpd_put(struct dp_hpd *dp_hpd) -{ - struct dp_gpio_hpd_private *gpio_hpd; - - if (!dp_hpd) - return; - - gpio_hpd = container_of(dp_hpd, struct dp_gpio_hpd_private, base); - - gpio_free(gpio_hpd->gpio_cfg.gpio); - devm_kfree(gpio_hpd->dev, gpio_hpd); -} diff --git a/drivers/gpu/drm/msm/dp/dp_gpio_hpd.h b/drivers/gpu/drm/msm/dp/dp_gpio_hpd.h deleted file mode 100644 index bb23c3bc886ed8a0f4dfb844222abb2f07eda80f..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_gpio_hpd.h +++ /dev/null @@ -1,32 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - */ - - -#ifndef _DP_GPIO_HPD_H_ -#define _DP_GPIO_HPD_H_ - -#include "dp_hpd.h" - -/** - * dp_gpio_hpd_get() - configure and get the DisplayPlot HPD module data - * - * @dev: device instance of the caller - * return: pointer to allocated gpio hpd module data - * - * This function sets up the gpio hpd module - */ -struct dp_hpd *dp_gpio_hpd_get(struct device *dev, - struct dp_hpd_cb *cb); - -/** - * dp_gpio_hpd_put() - * - * Cleans up dp_hpd instance - * - * @hpd: instance of gpio_hpd - */ -void dp_gpio_hpd_put(struct dp_hpd *hpd); - -#endif /* _DP_GPIO_HPD_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_hdcp2p2.c b/drivers/gpu/drm/msm/dp/dp_hdcp2p2.c deleted file mode 100644 index f71c25e66cb4915b977df2c41cb98c3a49921976..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_hdcp2p2.c +++ /dev/null @@ -1,978 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[dp-hdcp2p2] %s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sde_hdcp_2x.h" - -#define DP_INTR_STATUS2 (0x00000024) -#define DP_INTR_STATUS3 (0x00000028) -#define dp_read(offset) readl_relaxed((offset)) -#define dp_write(offset, data) writel_relaxed((data), (offset)) -#define DP_HDCP_RXCAPS_LENGTH 3 - -enum dp_hdcp2p2_sink_status { - SINK_DISCONNECTED, - SINK_CONNECTED -}; - -struct dp_hdcp2p2_ctrl { - DECLARE_KFIFO(cmd_q, enum hdcp_transport_wakeup_cmd, 8); - wait_queue_head_t wait_q; - atomic_t auth_state; - enum dp_hdcp2p2_sink_status sink_status; /* Is sink connected */ - struct dp_hdcp2p2_interrupts *intr; - struct sde_hdcp_init_data init_data; - struct mutex mutex; /* mutex to protect access to ctrl */ - struct mutex msg_lock; /* mutex to protect access to msg buffer */ - struct sde_hdcp_ops *ops; - void *lib_ctx; /* Handle to HDCP 2.2 Trustzone library */ - struct sde_hdcp_2x_ops *lib; /* Ops for driver to call into TZ */ - - struct task_struct *thread; - struct hdcp2_buffer response; - struct hdcp2_buffer request; - uint32_t total_message_length; - uint32_t timeout; - struct sde_hdcp_2x_msg_part msg_part[HDCP_MAX_MESSAGE_PARTS]; - u8 sink_rx_status; - u8 rx_status; - char abort_mask; - - bool polling; -}; - -struct dp_hdcp2p2_int_set { - u32 interrupt; - char *name; - void (*func)(struct dp_hdcp2p2_ctrl *ctrl); -}; - -struct dp_hdcp2p2_interrupts { - u32 reg; - struct dp_hdcp2p2_int_set *int_set; -}; - -static inline int dp_hdcp2p2_valid_handle(struct dp_hdcp2p2_ctrl *ctrl) -{ - if (!ctrl) { - pr_err("invalid input\n"); - return -EINVAL; - } - - if (!ctrl->lib_ctx) { - pr_err("HDCP library needs to be acquired\n"); - return -EINVAL; - } - - if (!ctrl->lib) { - pr_err("invalid lib ops data\n"); - return -EINVAL; - } - return 0; -} - -static inline bool dp_hdcp2p2_is_valid_state(struct dp_hdcp2p2_ctrl *ctrl) -{ - enum hdcp_transport_wakeup_cmd cmd; - - if (kfifo_peek(&ctrl->cmd_q, &cmd) && - cmd == HDCP_TRANSPORT_CMD_AUTHENTICATE) - return true; - - if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE) - return true; - - return false; -} - -static int dp_hdcp2p2_copy_buf(struct dp_hdcp2p2_ctrl *ctrl, - struct hdcp_transport_wakeup_data *data) -{ - int i = 0; - uint32_t num_messages = 0; - - if (!data || !data->message_data) - return 0; - - mutex_lock(&ctrl->msg_lock); - - ctrl->timeout = data->timeout; - num_messages = data->message_data->num_messages; - ctrl->total_message_length = 0; /* Total length of all messages */ - - for (i = 0; i < num_messages; i++) - ctrl->total_message_length += - data->message_data->messages[i].length; - - memcpy(ctrl->msg_part, data->message_data->messages, - sizeof(data->message_data->messages)); - - ctrl->rx_status = data->message_data->rx_status; - ctrl->abort_mask = data->abort_mask; - - if (!ctrl->total_message_length) { - mutex_unlock(&ctrl->msg_lock); - return 0; - } - - ctrl->response.data = data->buf; - ctrl->response.length = ctrl->total_message_length; - ctrl->request.data = data->buf; - ctrl->request.length = ctrl->total_message_length; - - mutex_unlock(&ctrl->msg_lock); - - return 0; -} - -static void dp_hdcp2p2_send_auth_status(struct dp_hdcp2p2_ctrl *ctrl) -{ - ctrl->init_data.notify_status(ctrl->init_data.cb_data, - atomic_read(&ctrl->auth_state)); -} - -static void dp_hdcp2p2_set_interrupts(struct dp_hdcp2p2_ctrl *ctrl, bool enable) -{ - void __iomem *base = ctrl->init_data.dp_ahb->base; - struct dp_hdcp2p2_interrupts *intr = ctrl->intr; - - while (intr && intr->reg) { - struct dp_hdcp2p2_int_set *int_set = intr->int_set; - u32 interrupts = 0; - - while (int_set && int_set->interrupt) { - interrupts |= int_set->interrupt; - int_set++; - } - - if (enable) - dp_write(base + intr->reg, - dp_read(base + intr->reg) | interrupts); - else - dp_write(base + intr->reg, - dp_read(base + intr->reg) & ~interrupts); - intr++; - } -} - -static int dp_hdcp2p2_wakeup(struct hdcp_transport_wakeup_data *data) -{ - struct dp_hdcp2p2_ctrl *ctrl; - u32 const default_timeout_us = 500; - - if (!data) { - pr_err("invalid input\n"); - return -EINVAL; - } - - ctrl = data->context; - if (!ctrl) { - pr_err("invalid ctrl\n"); - return -EINVAL; - } - - if (data->timeout) - ctrl->timeout = (data->timeout) * 2; - else - ctrl->timeout = default_timeout_us; - - if (dp_hdcp2p2_copy_buf(ctrl, data)) - goto exit; - - ctrl->polling = false; - switch (data->cmd) { - case HDCP_TRANSPORT_CMD_STATUS_SUCCESS: - atomic_set(&ctrl->auth_state, HDCP_STATE_AUTHENTICATED); - break; - case HDCP_TRANSPORT_CMD_STATUS_FAILED: - atomic_set(&ctrl->auth_state, HDCP_STATE_AUTH_FAIL); - break; - default: - break; - } - - kfifo_put(&ctrl->cmd_q, data->cmd); - wake_up(&ctrl->wait_q); -exit: - return 0; -} - -static inline void dp_hdcp2p2_wakeup_lib(struct dp_hdcp2p2_ctrl *ctrl, - struct sde_hdcp_2x_wakeup_data *data) -{ - int rc = 0; - - if (ctrl && ctrl->lib && ctrl->lib->wakeup && - data && (data->cmd != HDCP_2X_CMD_INVALID)) { - rc = ctrl->lib->wakeup(data); - if (rc) - pr_err("error sending %s to lib\n", - sde_hdcp_2x_cmd_to_str(data->cmd)); - } -} - -static void dp_hdcp2p2_reset(struct dp_hdcp2p2_ctrl *ctrl) -{ - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - ctrl->sink_status = SINK_DISCONNECTED; - atomic_set(&ctrl->auth_state, HDCP_STATE_INACTIVE); -} - -static int dp_hdcp2p2_register(void *input, bool mst_enabled) -{ - int rc; - enum sde_hdcp_2x_device_type device_type; - struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input; - - rc = dp_hdcp2p2_valid_handle(ctrl); - if (rc) - return rc; - - if (mst_enabled) - device_type = HDCP_TXMTR_DP_MST; - else - device_type = HDCP_TXMTR_DP; - - return sde_hdcp_2x_enable(ctrl->lib_ctx, device_type); -} - -static int dp_hdcp2p2_on(void *input) -{ - int rc = 0; - struct dp_hdcp2p2_ctrl *ctrl = input; - struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_INVALID}; - - rc = dp_hdcp2p2_valid_handle(ctrl); - if (rc) - return rc; - - cdata.cmd = HDCP_2X_CMD_START; - cdata.context = ctrl->lib_ctx; - rc = ctrl->lib->wakeup(&cdata); - if (rc) - pr_err("Unable to start the HDCP 2.2 library (%d)\n", rc); - - return rc; -} - -static void dp_hdcp2p2_off(void *input) -{ - int rc; - struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input; - struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_INVALID}; - - rc = dp_hdcp2p2_valid_handle(ctrl); - if (rc) - return; - - if (atomic_read(&ctrl->auth_state) != HDCP_STATE_AUTH_FAIL) { - cdata.cmd = HDCP_2X_CMD_STOP; - cdata.context = ctrl->lib_ctx; - dp_hdcp2p2_wakeup_lib(ctrl, &cdata); - } - - dp_hdcp2p2_set_interrupts(ctrl, false); - - dp_hdcp2p2_reset(ctrl); - - kthread_park(ctrl->thread); - - sde_hdcp_2x_disable(ctrl->lib_ctx); -} - -static int dp_hdcp2p2_authenticate(void *input) -{ - int rc; - struct dp_hdcp2p2_ctrl *ctrl = input; - struct hdcp_transport_wakeup_data cdata = { - HDCP_TRANSPORT_CMD_AUTHENTICATE}; - rc = dp_hdcp2p2_valid_handle(ctrl); - if (rc) - return rc; - - dp_hdcp2p2_set_interrupts(ctrl, true); - - ctrl->sink_status = SINK_CONNECTED; - atomic_set(&ctrl->auth_state, HDCP_STATE_AUTHENTICATING); - - kthread_unpark(ctrl->thread); - - cdata.context = input; - dp_hdcp2p2_wakeup(&cdata); - - return rc; -} - -static int dp_hdcp2p2_reauthenticate(void *input) -{ - struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input; - - if (!ctrl) { - pr_err("invalid input\n"); - return -EINVAL; - } - - dp_hdcp2p2_reset((struct dp_hdcp2p2_ctrl *)input); - - return dp_hdcp2p2_authenticate(input); -} - -static void dp_hdcp2p2_min_level_change(void *client_ctx, - u8 min_enc_level) -{ - struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)client_ctx; - struct sde_hdcp_2x_wakeup_data cdata = { - HDCP_2X_CMD_MIN_ENC_LEVEL}; - - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - if (!dp_hdcp2p2_is_valid_state(ctrl)) { - pr_err("invalid state\n"); - return; - } - - cdata.context = ctrl->lib_ctx; - cdata.min_enc_level = min_enc_level; - dp_hdcp2p2_wakeup_lib(ctrl, &cdata); -} - -static int dp_hdcp2p2_aux_read_message(struct dp_hdcp2p2_ctrl *ctrl) -{ - int rc = 0, max_size = 16, read_size = 0, bytes_read = 0; - int size = ctrl->request.length, offset = ctrl->msg_part->offset; - u8 *buf = ctrl->request.data; - - if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE || - atomic_read(&ctrl->auth_state) == HDCP_STATE_AUTH_FAIL) { - pr_err("invalid hdcp state\n"); - rc = -EINVAL; - goto exit; - } - - if (!buf) { - pr_err("invalid request buffer\n"); - rc = -EINVAL; - goto exit; - } - - pr_debug("offset(0x%x), size(%d)\n", offset, size); - - do { - read_size = min(size, max_size); - - bytes_read = drm_dp_dpcd_read(ctrl->init_data.drm_aux, - offset, buf, read_size); - if (bytes_read != read_size) { - pr_err("fail: offset(0x%x), size(0x%x), rc(0x%x)\n", - offset, read_size, bytes_read); - rc = -EINVAL; - break; - } - - buf += read_size; - offset += read_size; - size -= read_size; - } while (size > 0); - -exit: - return rc; -} - -static int dp_hdcp2p2_aux_write_message(struct dp_hdcp2p2_ctrl *ctrl, - u8 *buf, int size, uint offset, uint timeout) -{ - int const max_size = 16; - int rc = 0, write_size = 0, bytes_written = 0; - - pr_debug("offset(0x%x), size(%d)\n", offset, size); - - do { - write_size = min(size, max_size); - - bytes_written = drm_dp_dpcd_write(ctrl->init_data.drm_aux, - offset, buf, write_size); - if (bytes_written != write_size) { - pr_err("fail: offset(0x%x), size(0x%x), rc(0x%x)\n", - offset, write_size, bytes_written); - rc = -EINVAL; - break; - } - - buf += write_size; - offset += write_size; - size -= write_size; - } while (size > 0); - - return rc; -} - -static bool dp_hdcp2p2_feature_supported(void *input) -{ - int rc; - struct dp_hdcp2p2_ctrl *ctrl = input; - struct sde_hdcp_2x_ops *lib = NULL; - bool supported = false; - - rc = dp_hdcp2p2_valid_handle(ctrl); - if (rc) - return supported; - - lib = ctrl->lib; - if (lib->feature_supported) - supported = lib->feature_supported( - ctrl->lib_ctx); - - return supported; -} - -static void dp_hdcp2p2_force_encryption(void *data, bool enable) -{ - int rc; - struct dp_hdcp2p2_ctrl *ctrl = data; - struct sde_hdcp_2x_ops *lib = NULL; - - rc = dp_hdcp2p2_valid_handle(ctrl); - if (rc) - return; - - lib = ctrl->lib; - if (lib->force_encryption) - lib->force_encryption(ctrl->lib_ctx, enable); -} - -static void dp_hdcp2p2_send_msg(struct dp_hdcp2p2_ctrl *ctrl) -{ - int rc = 0; - struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_INVALID}; - - if (!ctrl) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto exit; - } - - cdata.context = ctrl->lib_ctx; - - if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) { - pr_err("hdcp is off\n"); - goto exit; - } - - mutex_lock(&ctrl->msg_lock); - - rc = dp_hdcp2p2_aux_write_message(ctrl, ctrl->response.data, - ctrl->response.length, ctrl->msg_part->offset, - ctrl->timeout); - if (rc) { - pr_err("Error sending msg to sink %d\n", rc); - mutex_unlock(&ctrl->msg_lock); - goto exit; - } - - cdata.cmd = HDCP_2X_CMD_MSG_SEND_SUCCESS; - cdata.timeout = ctrl->timeout; - mutex_unlock(&ctrl->msg_lock); - -exit: - if (rc == -ETIMEDOUT) - cdata.cmd = HDCP_2X_CMD_MSG_SEND_TIMEOUT; - else if (rc) - cdata.cmd = HDCP_2X_CMD_MSG_SEND_FAILED; - - dp_hdcp2p2_wakeup_lib(ctrl, &cdata); -} - -static int dp_hdcp2p2_get_msg_from_sink(struct dp_hdcp2p2_ctrl *ctrl) -{ - int rc = 0; - struct sde_hdcp_2x_wakeup_data cdata = { HDCP_2X_CMD_INVALID }; - - cdata.context = ctrl->lib_ctx; - - rc = dp_hdcp2p2_aux_read_message(ctrl); - if (rc) { - pr_err("error reading message %d\n", rc); - goto exit; - } - - cdata.total_message_length = ctrl->total_message_length; - cdata.timeout = ctrl->timeout; -exit: - if (rc == -ETIMEDOUT) - cdata.cmd = HDCP_2X_CMD_MSG_RECV_TIMEOUT; - else if (rc) - cdata.cmd = HDCP_2X_CMD_MSG_RECV_FAILED; - else - cdata.cmd = HDCP_2X_CMD_MSG_RECV_SUCCESS; - - dp_hdcp2p2_wakeup_lib(ctrl, &cdata); - - return rc; -} - -static void dp_hdcp2p2_recv_msg(struct dp_hdcp2p2_ctrl *ctrl) -{ - struct sde_hdcp_2x_wakeup_data cdata = { HDCP_2X_CMD_INVALID }; - - cdata.context = ctrl->lib_ctx; - - if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) { - pr_err("hdcp is off\n"); - return; - } - - dp_hdcp2p2_get_msg_from_sink(ctrl); -} - -static void dp_hdcp2p2_link_check(struct dp_hdcp2p2_ctrl *ctrl) -{ - int rc = 0, retries = 10; - struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_INVALID}; - - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - if (atomic_read(&ctrl->auth_state) == HDCP_STATE_AUTH_FAIL || - atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) { - pr_err("invalid hdcp state\n"); - return; - } - - cdata.context = ctrl->lib_ctx; - - if (ctrl->sink_rx_status & ctrl->abort_mask) { - if (ctrl->sink_rx_status & BIT(3)) - pr_err("reauth_req set by sink\n"); - - if (ctrl->sink_rx_status & BIT(4)) - pr_err("link failure reported by sink\n"); - - ctrl->sink_rx_status = 0; - ctrl->rx_status = 0; - - rc = -ENOLINK; - - cdata.cmd = HDCP_2X_CMD_LINK_FAILED; - atomic_set(&ctrl->auth_state, HDCP_STATE_AUTH_FAIL); - goto exit; - } - - /* wait for polling to start till spec allowed timeout */ - while (!ctrl->polling && retries--) - msleep(20); - - /* check if sink has made a message available */ - if (ctrl->polling && (ctrl->sink_rx_status & ctrl->rx_status)) { - ctrl->sink_rx_status = 0; - ctrl->rx_status = 0; - - dp_hdcp2p2_get_msg_from_sink(ctrl); - - ctrl->polling = false; - } -exit: - if (rc) - dp_hdcp2p2_wakeup_lib(ctrl, &cdata); -} - -static void dp_hdcp2p2_start_auth(struct dp_hdcp2p2_ctrl *ctrl) -{ - struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_START_AUTH}; - cdata.context = ctrl->lib_ctx; - - if (atomic_read(&ctrl->auth_state) == HDCP_STATE_AUTHENTICATING) - dp_hdcp2p2_wakeup_lib(ctrl, &cdata); -} - -static int dp_hdcp2p2_read_rx_status(struct dp_hdcp2p2_ctrl *ctrl, - u8 *rx_status) -{ - u32 const cp_irq_dpcd_offset = 0x201; - u32 const rxstatus_dpcd_offset = 0x69493; - ssize_t const bytes_to_read = 1; - ssize_t bytes_read = 0; - u8 buf = 0; - int rc = 0; - bool cp_irq = false; - - *rx_status = 0; - - bytes_read = drm_dp_dpcd_read(ctrl->init_data.drm_aux, - cp_irq_dpcd_offset, &buf, bytes_to_read); - if (bytes_read != bytes_to_read) { - pr_err("cp irq read failed\n"); - rc = bytes_read; - goto error; - } - - cp_irq = buf & BIT(2); - pr_debug("cp_irq=0x%x\n", cp_irq); - buf = 0; - - if (cp_irq) { - bytes_read = drm_dp_dpcd_read(ctrl->init_data.drm_aux, - rxstatus_dpcd_offset, &buf, bytes_to_read); - if (bytes_read != bytes_to_read) { - pr_err("rxstatus read failed\n"); - rc = bytes_read; - goto error; - } - *rx_status = buf; - pr_debug("rx_status=0x%x\n", *rx_status); - } - -error: - return rc; -} - -static int dp_hdcp2p2_cp_irq(void *input) -{ - int rc; - struct dp_hdcp2p2_ctrl *ctrl = input; - - rc = dp_hdcp2p2_valid_handle(ctrl); - if (rc) - return rc; - - if (atomic_read(&ctrl->auth_state) == HDCP_STATE_AUTH_FAIL || - atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) { - pr_err("invalid hdcp state\n"); - return -EINVAL; - } - - ctrl->sink_rx_status = 0; - rc = dp_hdcp2p2_read_rx_status(ctrl, &ctrl->sink_rx_status); - if (rc) { - pr_err("failed to read rx status\n"); - return rc; - } - - pr_debug("sink_rx_status=0x%x\n", ctrl->sink_rx_status); - - if (!ctrl->sink_rx_status) { - pr_debug("not a hdcp 2.2 irq\n"); - return -EINVAL; - } - - - kfifo_put(&ctrl->cmd_q, HDCP_TRANSPORT_CMD_LINK_CHECK); - wake_up(&ctrl->wait_q); - - return 0; -} - -static int dp_hdcp2p2_isr(void *input) -{ - struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input; - int rc = 0; - struct dss_io_data *io; - struct dp_hdcp2p2_interrupts *intr; - u32 hdcp_int_val = 0; - - if (!ctrl || !ctrl->init_data.dp_ahb) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto end; - } - - io = ctrl->init_data.dp_ahb; - intr = ctrl->intr; - - while (intr && intr->reg) { - struct dp_hdcp2p2_int_set *int_set = intr->int_set; - - hdcp_int_val = dp_read(io->base + intr->reg); - - while (int_set && int_set->interrupt) { - if (hdcp_int_val & (int_set->interrupt >> 2)) { - pr_debug("%s\n", int_set->name); - - if (int_set->func) - int_set->func(ctrl); - - dp_write(io->base + intr->reg, hdcp_int_val | - (int_set->interrupt >> 1)); - } - int_set++; - } - intr++; - } -end: - return rc; -} - -static bool dp_hdcp2p2_supported(void *input) -{ - struct dp_hdcp2p2_ctrl *ctrl = input; - u32 const rxcaps_dpcd_offset = 0x6921d; - ssize_t bytes_read = 0; - u8 buf[DP_HDCP_RXCAPS_LENGTH]; - - pr_debug("Checking sink capability\n"); - - bytes_read = drm_dp_dpcd_read(ctrl->init_data.drm_aux, - rxcaps_dpcd_offset, &buf, DP_HDCP_RXCAPS_LENGTH); - if (bytes_read != DP_HDCP_RXCAPS_LENGTH) { - pr_err("RxCaps read failed\n"); - goto error; - } - - pr_debug("HDCP_CAPABLE=%lu\n", (buf[2] & BIT(1)) >> 1); - pr_debug("VERSION=%d\n", buf[0]); - - if ((buf[2] & BIT(1)) && (buf[0] == 0x2)) - return true; -error: - return false; -} - -static int dp_hdcp2p2_change_streams(struct dp_hdcp2p2_ctrl *ctrl, - struct sde_hdcp_2x_wakeup_data *cdata) -{ - if (!ctrl || cdata->num_streams == 0 || !cdata->streams) { - pr_err("invalid input\n"); - return -EINVAL; - } - - if (!ctrl->lib_ctx) { - pr_err("HDCP library needs to be acquired\n"); - return -EINVAL; - } - - if (!ctrl->lib) { - pr_err("invalid lib ops data\n"); - return -EINVAL; - } - - cdata->context = ctrl->lib_ctx; - return ctrl->lib->wakeup(cdata); -} - - -static int dp_hdcp2p2_register_streams(void *input, u8 num_streams, - struct stream_info *streams) -{ - struct dp_hdcp2p2_ctrl *ctrl = input; - struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_OPEN_STREAMS}; - - cdata.streams = streams; - cdata.num_streams = num_streams; - return dp_hdcp2p2_change_streams(ctrl, &cdata); -} - -static int dp_hdcp2p2_deregister_streams(void *input, u8 num_streams, - struct stream_info *streams) -{ - struct dp_hdcp2p2_ctrl *ctrl = input; - struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_CLOSE_STREAMS}; - - cdata.streams = streams; - cdata.num_streams = num_streams; - return dp_hdcp2p2_change_streams(ctrl, &cdata); -} - -void sde_dp_hdcp2p2_deinit(void *input) -{ - struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input; - struct sde_hdcp_2x_wakeup_data cdata = {HDCP_2X_CMD_INVALID}; - - if (!ctrl) { - pr_err("invalid input\n"); - return; - } - - if (atomic_read(&ctrl->auth_state) != HDCP_STATE_AUTH_FAIL) { - cdata.cmd = HDCP_2X_CMD_STOP; - cdata.context = ctrl->lib_ctx; - dp_hdcp2p2_wakeup_lib(ctrl, &cdata); - } - - sde_hdcp_2x_deregister(ctrl->lib_ctx); - - kthread_stop(ctrl->thread); - - mutex_destroy(&ctrl->mutex); - mutex_destroy(&ctrl->msg_lock); - kfree(ctrl); -} - -static int dp_hdcp2p2_main(void *data) -{ - struct dp_hdcp2p2_ctrl *ctrl = data; - enum hdcp_transport_wakeup_cmd cmd; - - while (1) { - wait_event(ctrl->wait_q, - !kfifo_is_empty(&ctrl->cmd_q) || - kthread_should_stop() || - kthread_should_park()); - - if (kthread_should_stop()) - break; - - if (kfifo_is_empty(&ctrl->cmd_q) && kthread_should_park()) { - kthread_parkme(); - continue; - } - - if (!kfifo_get(&ctrl->cmd_q, &cmd)) - continue; - - switch (cmd) { - case HDCP_TRANSPORT_CMD_SEND_MESSAGE: - dp_hdcp2p2_send_msg(ctrl); - break; - case HDCP_TRANSPORT_CMD_RECV_MESSAGE: - if (ctrl->rx_status) - ctrl->polling = true; - else - dp_hdcp2p2_recv_msg(ctrl); - break; - case HDCP_TRANSPORT_CMD_STATUS_SUCCESS: - dp_hdcp2p2_send_auth_status(ctrl); - break; - case HDCP_TRANSPORT_CMD_STATUS_FAILED: - dp_hdcp2p2_set_interrupts(ctrl, false); - dp_hdcp2p2_send_auth_status(ctrl); - break; - case HDCP_TRANSPORT_CMD_LINK_POLL: - ctrl->polling = true; - break; - case HDCP_TRANSPORT_CMD_LINK_CHECK: - dp_hdcp2p2_link_check(ctrl); - break; - case HDCP_TRANSPORT_CMD_AUTHENTICATE: - dp_hdcp2p2_start_auth(ctrl); - break; - default: - break; - } - } - - return 0; -} - -void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data) -{ - int rc; - struct dp_hdcp2p2_ctrl *ctrl; - static struct sde_hdcp_ops ops = { - .isr = dp_hdcp2p2_isr, - .reauthenticate = dp_hdcp2p2_reauthenticate, - .authenticate = dp_hdcp2p2_authenticate, - .feature_supported = dp_hdcp2p2_feature_supported, - .force_encryption = dp_hdcp2p2_force_encryption, - .sink_support = dp_hdcp2p2_supported, - .set_mode = dp_hdcp2p2_register, - .on = dp_hdcp2p2_on, - .off = dp_hdcp2p2_off, - .cp_irq = dp_hdcp2p2_cp_irq, - .register_streams = dp_hdcp2p2_register_streams, - .deregister_streams = dp_hdcp2p2_deregister_streams, - }; - - static struct hdcp_transport_ops client_ops = { - .wakeup = dp_hdcp2p2_wakeup, - }; - static struct dp_hdcp2p2_int_set int_set1[] = { - {BIT(17), "authentication successful", NULL}, - {BIT(20), "authentication failed", NULL}, - {BIT(24), "encryption enabled", NULL}, - {BIT(27), "encryption disabled", NULL}, - {0}, - }; - static struct dp_hdcp2p2_int_set int_set2[] = { - {BIT(2), "key fifo underflow", NULL}, - {0}, - }; - static struct dp_hdcp2p2_interrupts intr[] = { - {DP_INTR_STATUS2, int_set1}, - {DP_INTR_STATUS3, int_set2}, - {0} - }; - static struct sde_hdcp_2x_ops hdcp2x_ops; - struct sde_hdcp_2x_register_data register_data = {0}; - - if (!init_data || !init_data->cb_data || - !init_data->notify_status || !init_data->drm_aux) { - pr_err("invalid input\n"); - return ERR_PTR(-EINVAL); - } - - ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); - if (!ctrl) - return ERR_PTR(-ENOMEM); - - ctrl->init_data = *init_data; - ctrl->lib = &hdcp2x_ops; - ctrl->response.data = NULL; - ctrl->request.data = NULL; - - ctrl->sink_status = SINK_DISCONNECTED; - ctrl->intr = intr; - - INIT_KFIFO(ctrl->cmd_q); - - init_waitqueue_head(&ctrl->wait_q); - atomic_set(&ctrl->auth_state, HDCP_STATE_INACTIVE); - - ctrl->ops = &ops; - mutex_init(&ctrl->mutex); - mutex_init(&ctrl->msg_lock); - - register_data.hdcp_data = &ctrl->lib_ctx; - register_data.client_ops = &client_ops; - register_data.ops = &hdcp2x_ops; - register_data.client_data = ctrl; - - rc = sde_hdcp_2x_register(®ister_data); - if (rc) { - pr_err("Unable to register with HDCP 2.2 library\n"); - goto error; - } - - if (IS_ENABLED(CONFIG_HDCP_QSEECOM)) - msm_hdcp_register_cb(init_data->msm_hdcp_dev, ctrl, - dp_hdcp2p2_min_level_change); - - ctrl->thread = kthread_run(dp_hdcp2p2_main, ctrl, "dp_hdcp2p2"); - - if (IS_ERR(ctrl->thread)) { - pr_err("unable to start DP hdcp2p2 thread\n"); - rc = PTR_ERR(ctrl->thread); - ctrl->thread = NULL; - goto error; - } - - return ctrl; -error: - kfree(ctrl); - return ERR_PTR(rc); -} - -struct sde_hdcp_ops *sde_dp_hdcp2p2_get(void *input) -{ - return ((struct dp_hdcp2p2_ctrl *)input)->ops; -} diff --git a/drivers/gpu/drm/msm/dp/dp_hpd.c b/drivers/gpu/drm/msm/dp/dp_hpd.c deleted file mode 100644 index a48fe5f5e9ff8030c979f8d40b2604463e79e451..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_hpd.c +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ - -#include -#include -#include -#include - -#include "dp_hpd.h" -#include "dp_usbpd.h" -#include "dp_gpio_hpd.h" -#include "dp_lphw_hpd.h" - -static void dp_hpd_host_init(struct dp_hpd *dp_hpd, - struct dp_catalog_hpd *catalog) -{ - if (!catalog) { - pr_err("invalid input\n"); - return; - } - catalog->config_hpd(catalog, true); -} - -static void dp_hpd_host_deinit(struct dp_hpd *dp_hpd, - struct dp_catalog_hpd *catalog) -{ - if (!catalog) { - pr_err("invalid input\n"); - return; - } - catalog->config_hpd(catalog, false); -} - -static void dp_hpd_isr(struct dp_hpd *dp_hpd) -{ -} - -struct dp_hpd *dp_hpd_get(struct device *dev, struct dp_parser *parser, - struct dp_catalog_hpd *catalog, struct dp_hpd_cb *cb) -{ - struct dp_hpd *dp_hpd; - - if (parser->no_aux_switch && parser->lphw_hpd) { - dp_hpd = dp_lphw_hpd_get(dev, parser, catalog, cb); - if (IS_ERR(dp_hpd)) { - pr_err("failed to get lphw hpd\n"); - return dp_hpd; - } - dp_hpd->type = DP_HPD_LPHW; - } else if (parser->no_aux_switch) { - dp_hpd = dp_gpio_hpd_get(dev, cb); - if (IS_ERR(dp_hpd)) { - pr_err("failed to get gpio hpd\n"); - return dp_hpd; - } - dp_hpd->type = DP_HPD_GPIO; - } else { - dp_hpd = dp_usbpd_get(dev, cb); - if (IS_ERR(dp_hpd)) { - pr_err("failed to get usbpd\n"); - return dp_hpd; - } - dp_hpd->type = DP_HPD_USBPD; - } - - if (!dp_hpd->host_init) - dp_hpd->host_init = dp_hpd_host_init; - if (!dp_hpd->host_deinit) - dp_hpd->host_deinit = dp_hpd_host_deinit; - if (!dp_hpd->isr) - dp_hpd->isr = dp_hpd_isr; - - return dp_hpd; -} - -void dp_hpd_put(struct dp_hpd *dp_hpd) -{ - if (!dp_hpd) - return; - - switch (dp_hpd->type) { - case DP_HPD_USBPD: - dp_usbpd_put(dp_hpd); - break; - case DP_HPD_GPIO: - dp_gpio_hpd_put(dp_hpd); - break; - case DP_HPD_LPHW: - dp_lphw_hpd_put(dp_hpd); - break; - default: - pr_err("unknown hpd type %d\n", dp_hpd->type); - break; - } -} diff --git a/drivers/gpu/drm/msm/dp/dp_hpd.h b/drivers/gpu/drm/msm/dp/dp_hpd.h deleted file mode 100644 index bdc551262a5988ebb8c47af83b8b3f38ea38e0eb..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_hpd.h +++ /dev/null @@ -1,96 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. - */ - -#ifndef _DP_HPD_H_ -#define _DP_HPD_H_ - -#include -#include "dp_parser.h" -#include "dp_catalog.h" - -struct device; - -/** - * enum dp_hpd_type - dp hpd type - * @DP_HPD_USBPD: USB type-c based HPD - * @DP_HPD_GPIO: GPIO based HPD - * @DP_HPD_BUILTIN: Controller built-in HPD - */ - -enum dp_hpd_type { - DP_HPD_USBPD, - DP_HPD_GPIO, - DP_HPD_LPHW, - DP_HPD_BUILTIN, -}; - -/** - * struct dp_hpd_cb - callback functions provided by the client - * - * @configure: called when dp connection is ready. - * @disconnect: notify the cable disconnect event. - * @attention: notify any attention message event. - */ -struct dp_hpd_cb { - int (*configure)(struct device *dev); - int (*disconnect)(struct device *dev); - int (*attention)(struct device *dev); -}; - -/** - * struct dp_hpd - DisplayPort HPD status - * - * @type: type of HPD - * @orientation: plug orientation configuration, USBPD type only. - * @hpd_high: Hot Plug Detect signal is high. - * @hpd_irq: Change in the status since last message - * @alt_mode_cfg_done: bool to specify alt mode status - * @multi_func: multi-function preferred, USBPD type only - * @isr: event interrupt, BUILTIN and LPHW type only - * @register_hpd: register hardware callback - * @host_init: source or host side setup for hpd - * @host_deinit: source or host side de-initializations - * @simulate_connect: simulate disconnect or connect for debug mode - * @simulate_attention: simulate attention messages for debug mode - */ -struct dp_hpd { - enum dp_hpd_type type; - u32 orientation; - bool hpd_high; - bool hpd_irq; - bool alt_mode_cfg_done; - bool multi_func; - - void (*isr)(struct dp_hpd *dp_hpd); - int (*register_hpd)(struct dp_hpd *dp_hpd); - void (*host_init)(struct dp_hpd *hpd, struct dp_catalog_hpd *catalog); - void (*host_deinit)(struct dp_hpd *hpd, struct dp_catalog_hpd *catalog); - int (*simulate_connect)(struct dp_hpd *dp_hpd, bool hpd); - int (*simulate_attention)(struct dp_hpd *dp_hpd, int vdo); -}; - -/** - * dp_hpd_get() - configure and get the DisplayPlot HPD module data - * - * @dev: device instance of the caller - * @parser: DP parser - * @cb: callback function for HPD response - * return: pointer to allocated hpd module data - * - * This function sets up the hpd module - */ -struct dp_hpd *dp_hpd_get(struct device *dev, struct dp_parser *parser, - struct dp_catalog_hpd *catalog, struct dp_hpd_cb *cb); - -/** - * dp_hpd_put() - * - * Cleans up dp_hpd instance - * - * @dp_hpd: instance of dp_hpd - */ -void dp_hpd_put(struct dp_hpd *dp_hpd); - -#endif /* _DP_HPD_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c deleted file mode 100644 index d67320e4a2b6201af58da3f85678fb51fa78f3e7..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_link.c +++ /dev/null @@ -1,1526 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ - -#include "dp_link.h" -#include "dp_panel.h" - -enum dynamic_range { - DP_DYNAMIC_RANGE_RGB_VESA = 0x00, - DP_DYNAMIC_RANGE_RGB_CEA = 0x01, - DP_DYNAMIC_RANGE_UNKNOWN = 0xFFFFFFFF, -}; - -enum audio_sample_rate { - AUDIO_SAMPLE_RATE_32_KHZ = 0x00, - AUDIO_SAMPLE_RATE_44_1_KHZ = 0x01, - AUDIO_SAMPLE_RATE_48_KHZ = 0x02, - AUDIO_SAMPLE_RATE_88_2_KHZ = 0x03, - AUDIO_SAMPLE_RATE_96_KHZ = 0x04, - AUDIO_SAMPLE_RATE_176_4_KHZ = 0x05, - AUDIO_SAMPLE_RATE_192_KHZ = 0x06, -}; - -enum audio_pattern_type { - AUDIO_TEST_PATTERN_OPERATOR_DEFINED = 0x00, - AUDIO_TEST_PATTERN_SAWTOOTH = 0x01, -}; - -struct dp_link_request { - u32 test_requested; - u32 test_link_rate; - u32 test_lane_count; -}; - -struct dp_link_private { - u32 prev_sink_count; - struct device *dev; - struct dp_aux *aux; - struct dp_link dp_link; - - struct dp_link_request request; - u8 link_status[DP_LINK_STATUS_SIZE]; -}; - -static char *dp_link_get_audio_test_pattern(u32 pattern) -{ - switch (pattern) { - case AUDIO_TEST_PATTERN_OPERATOR_DEFINED: - return DP_LINK_ENUM_STR(AUDIO_TEST_PATTERN_OPERATOR_DEFINED); - case AUDIO_TEST_PATTERN_SAWTOOTH: - return DP_LINK_ENUM_STR(AUDIO_TEST_PATTERN_SAWTOOTH); - default: - return "unknown"; - } -} - -static char *dp_link_get_audio_sample_rate(u32 rate) -{ - switch (rate) { - case AUDIO_SAMPLE_RATE_32_KHZ: - return DP_LINK_ENUM_STR(AUDIO_SAMPLE_RATE_32_KHZ); - case AUDIO_SAMPLE_RATE_44_1_KHZ: - return DP_LINK_ENUM_STR(AUDIO_SAMPLE_RATE_44_1_KHZ); - case AUDIO_SAMPLE_RATE_48_KHZ: - return DP_LINK_ENUM_STR(AUDIO_SAMPLE_RATE_48_KHZ); - case AUDIO_SAMPLE_RATE_88_2_KHZ: - return DP_LINK_ENUM_STR(AUDIO_SAMPLE_RATE_88_2_KHZ); - case AUDIO_SAMPLE_RATE_96_KHZ: - return DP_LINK_ENUM_STR(AUDIO_SAMPLE_RATE_96_KHZ); - case AUDIO_SAMPLE_RATE_176_4_KHZ: - return DP_LINK_ENUM_STR(AUDIO_SAMPLE_RATE_176_4_KHZ); - case AUDIO_SAMPLE_RATE_192_KHZ: - return DP_LINK_ENUM_STR(AUDIO_SAMPLE_RATE_192_KHZ); - default: - return "unknown"; - } -} - -static int dp_link_get_period(struct dp_link_private *link, int const addr) -{ - int ret = 0; - u8 bp; - u8 data; - u32 const param_len = 0x1; - u32 const max_audio_period = 0xA; - - /* TEST_AUDIO_PERIOD_CH_XX */ - if (drm_dp_dpcd_read(link->aux->drm_aux, addr, &bp, - param_len) < param_len) { - pr_err("failed to read test_audio_period (0x%x)\n", addr); - ret = -EINVAL; - goto exit; - } - - data = bp; - - /* Period - Bits 3:0 */ - data = data & 0xF; - if ((int)data > max_audio_period) { - pr_err("invalid test_audio_period_ch_1 = 0x%x\n", data); - ret = -EINVAL; - goto exit; - } - - ret = data; -exit: - return ret; -} - -static int dp_link_parse_audio_channel_period(struct dp_link_private *link) -{ - int ret = 0; - struct dp_link_test_audio *req = &link->dp_link.test_audio; - - ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH1); - if (ret == -EINVAL) - goto exit; - - req->test_audio_period_ch_1 = ret; - pr_debug("test_audio_period_ch_1 = 0x%x\n", ret); - - ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH2); - if (ret == -EINVAL) - goto exit; - - req->test_audio_period_ch_2 = ret; - pr_debug("test_audio_period_ch_2 = 0x%x\n", ret); - - /* TEST_AUDIO_PERIOD_CH_3 (Byte 0x275) */ - ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH3); - if (ret == -EINVAL) - goto exit; - - req->test_audio_period_ch_3 = ret; - pr_debug("test_audio_period_ch_3 = 0x%x\n", ret); - - ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH4); - if (ret == -EINVAL) - goto exit; - - req->test_audio_period_ch_4 = ret; - pr_debug("test_audio_period_ch_4 = 0x%x\n", ret); - - ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH5); - if (ret == -EINVAL) - goto exit; - - req->test_audio_period_ch_5 = ret; - pr_debug("test_audio_period_ch_5 = 0x%x\n", ret); - - ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH6); - if (ret == -EINVAL) - goto exit; - - req->test_audio_period_ch_6 = ret; - pr_debug("test_audio_period_ch_6 = 0x%x\n", ret); - - ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH7); - if (ret == -EINVAL) - goto exit; - - req->test_audio_period_ch_7 = ret; - pr_debug("test_audio_period_ch_7 = 0x%x\n", ret); - - ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH8); - if (ret == -EINVAL) - goto exit; - - req->test_audio_period_ch_8 = ret; - pr_debug("test_audio_period_ch_8 = 0x%x\n", ret); -exit: - return ret; -} - -static int dp_link_parse_audio_pattern_type(struct dp_link_private *link) -{ - int ret = 0; - u8 bp; - u8 data; - int rlen; - int const param_len = 0x1; - int const max_audio_pattern_type = 0x1; - - rlen = drm_dp_dpcd_read(link->aux->drm_aux, - DP_TEST_AUDIO_PATTERN_TYPE, &bp, param_len); - if (rlen < param_len) { - pr_err("failed to read link audio mode data\n"); - ret = -EINVAL; - goto exit; - } - data = bp; - - /* Audio Pattern Type - Bits 7:0 */ - if ((int)data > max_audio_pattern_type) { - pr_err("invalid audio pattern type = 0x%x\n", data); - ret = -EINVAL; - goto exit; - } - - link->dp_link.test_audio.test_audio_pattern_type = data; - pr_debug("audio pattern type = %s\n", - dp_link_get_audio_test_pattern(data)); -exit: - return ret; -} - -static int dp_link_parse_audio_mode(struct dp_link_private *link) -{ - int ret = 0; - u8 bp; - u8 data; - int rlen; - int const param_len = 0x1; - int const max_audio_sampling_rate = 0x6; - int const max_audio_channel_count = 0x8; - int sampling_rate = 0x0; - int channel_count = 0x0; - - rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_TEST_AUDIO_MODE, - &bp, param_len); - if (rlen < param_len) { - pr_err("failed to read link audio mode data\n"); - ret = -EINVAL; - goto exit; - } - data = bp; - - /* Sampling Rate - Bits 3:0 */ - sampling_rate = data & 0xF; - if (sampling_rate > max_audio_sampling_rate) { - pr_err("sampling rate (0x%x) greater than max (0x%x)\n", - sampling_rate, max_audio_sampling_rate); - ret = -EINVAL; - goto exit; - } - - /* Channel Count - Bits 7:4 */ - channel_count = ((data & 0xF0) >> 4) + 1; - if (channel_count > max_audio_channel_count) { - pr_err("channel_count (0x%x) greater than max (0x%x)\n", - channel_count, max_audio_channel_count); - ret = -EINVAL; - goto exit; - } - - link->dp_link.test_audio.test_audio_sampling_rate = sampling_rate; - link->dp_link.test_audio.test_audio_channel_count = channel_count; - pr_debug("sampling_rate = %s, channel_count = 0x%x\n", - dp_link_get_audio_sample_rate(sampling_rate), channel_count); -exit: - return ret; -} - -/** - * dp_parse_audio_pattern_params() - parses audio pattern parameters from DPCD - * @link: Display Port Driver data - * - * Returns 0 if it successfully parses the audio link pattern parameters. - */ -static int dp_link_parse_audio_pattern_params(struct dp_link_private *link) -{ - int ret = 0; - - ret = dp_link_parse_audio_mode(link); - if (ret) - goto exit; - - ret = dp_link_parse_audio_pattern_type(link); - if (ret) - goto exit; - - ret = dp_link_parse_audio_channel_period(link); - -exit: - return ret; -} - -/** - * dp_link_is_video_pattern_valid() - validates the video pattern - * @pattern: video pattern requested by the sink - * - * Returns true if the requested video pattern is supported. - */ -static bool dp_link_is_video_pattern_valid(u32 pattern) -{ - switch (pattern) { - case DP_NO_TEST_PATTERN: - case DP_COLOR_RAMP: - case DP_BLACK_AND_WHITE_VERTICAL_LINES: - case DP_COLOR_SQUARE: - return true; - default: - return false; - } -} - -static char *dp_link_video_pattern_to_string(u32 test_video_pattern) -{ - switch (test_video_pattern) { - case DP_NO_TEST_PATTERN: - return DP_LINK_ENUM_STR(DP_NO_TEST_PATTERN); - case DP_COLOR_RAMP: - return DP_LINK_ENUM_STR(DP_COLOR_RAMP); - case DP_BLACK_AND_WHITE_VERTICAL_LINES: - return DP_LINK_ENUM_STR(DP_BLACK_AND_WHITE_VERTICAL_LINES); - case DP_COLOR_SQUARE: - return DP_LINK_ENUM_STR(DP_COLOR_SQUARE); - default: - return "unknown"; - } -} - -/** - * dp_link_is_dynamic_range_valid() - validates the dynamic range - * @bit_depth: the dynamic range value to be checked - * - * Returns true if the dynamic range value is supported. - */ -static bool dp_link_is_dynamic_range_valid(u32 dr) -{ - switch (dr) { - case DP_DYNAMIC_RANGE_RGB_VESA: - case DP_DYNAMIC_RANGE_RGB_CEA: - return true; - default: - return false; - } -} - -static char *dp_link_dynamic_range_to_string(u32 dr) -{ - switch (dr) { - case DP_DYNAMIC_RANGE_RGB_VESA: - return DP_LINK_ENUM_STR(DP_DYNAMIC_RANGE_RGB_VESA); - case DP_DYNAMIC_RANGE_RGB_CEA: - return DP_LINK_ENUM_STR(DP_DYNAMIC_RANGE_RGB_CEA); - case DP_DYNAMIC_RANGE_UNKNOWN: - default: - return "unknown"; - } -} - -/** - * dp_link_is_bit_depth_valid() - validates the bit depth requested - * @bit_depth: bit depth requested by the sink - * - * Returns true if the requested bit depth is supported. - */ -static bool dp_link_is_bit_depth_valid(u32 tbd) -{ - /* DP_TEST_VIDEO_PATTERN_NONE is treated as invalid */ - switch (tbd) { - case DP_TEST_BIT_DEPTH_6: - case DP_TEST_BIT_DEPTH_8: - case DP_TEST_BIT_DEPTH_10: - return true; - default: - return false; - } -} - -static char *dp_link_bit_depth_to_string(u32 tbd) -{ - switch (tbd) { - case DP_TEST_BIT_DEPTH_6: - return DP_LINK_ENUM_STR(DP_TEST_BIT_DEPTH_6); - case DP_TEST_BIT_DEPTH_8: - return DP_LINK_ENUM_STR(DP_TEST_BIT_DEPTH_8); - case DP_TEST_BIT_DEPTH_10: - return DP_LINK_ENUM_STR(DP_TEST_BIT_DEPTH_10); - case DP_TEST_BIT_DEPTH_UNKNOWN: - default: - return "unknown"; - } -} - -static int dp_link_parse_timing_params1(struct dp_link_private *link, - int const addr, int const len, u32 *val) -{ - u8 bp[2]; - int rlen; - - if (len < 2) - return -EINVAL; - - /* Read the requested video link pattern (Byte 0x221). */ - rlen = drm_dp_dpcd_read(link->aux->drm_aux, addr, bp, len); - if (rlen < len) { - pr_err("failed to read 0x%x\n", addr); - return -EINVAL; - } - - *val = bp[1] | (bp[0] << 8); - - return 0; -} - -static int dp_link_parse_timing_params2(struct dp_link_private *link, - int const addr, int const len, u32 *val1, u32 *val2) -{ - u8 bp[2]; - int rlen; - - if (len < 2) - return -EINVAL; - - /* Read the requested video link pattern (Byte 0x221). */ - rlen = drm_dp_dpcd_read(link->aux->drm_aux, addr, bp, len); - if (rlen < len) { - pr_err("failed to read 0x%x\n", addr); - return -EINVAL; - } - - *val1 = (bp[0] & BIT(7)) >> 7; - *val2 = bp[1] | ((bp[0] & 0x7F) << 8); - - return 0; -} - -static int dp_link_parse_timing_params3(struct dp_link_private *link, - int const addr, u32 *val) -{ - u8 bp; - u32 len = 1; - int rlen; - - rlen = drm_dp_dpcd_read(link->aux->drm_aux, addr, &bp, len); - if (rlen < 1) { - pr_err("failed to read 0x%x\n", addr); - return -EINVAL; - } - *val = bp; - - return 0; -} - -/** - * dp_parse_video_pattern_params() - parses video pattern parameters from DPCD - * @link: Display Port Driver data - * - * Returns 0 if it successfully parses the video link pattern and the link - * bit depth requested by the sink and, and if the values parsed are valid. - */ -static int dp_link_parse_video_pattern_params(struct dp_link_private *link) -{ - int ret = 0; - int rlen; - u8 bp; - u8 data; - u32 dyn_range; - int const param_len = 0x1; - - rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_TEST_PATTERN, - &bp, param_len); - if (rlen < param_len) { - pr_err("failed to read link video pattern\n"); - ret = -EINVAL; - goto exit; - } - data = bp; - - if (!dp_link_is_video_pattern_valid(data)) { - pr_err("invalid link video pattern = 0x%x\n", data); - ret = -EINVAL; - goto exit; - } - - link->dp_link.test_video.test_video_pattern = data; - pr_debug("link video pattern = 0x%x (%s)\n", - link->dp_link.test_video.test_video_pattern, - dp_link_video_pattern_to_string( - link->dp_link.test_video.test_video_pattern)); - - /* Read the requested color bit depth and dynamic range (Byte 0x232) */ - rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_TEST_MISC0, - &bp, param_len); - if (rlen < param_len) { - pr_err("failed to read link bit depth\n"); - ret = -EINVAL; - goto exit; - } - data = bp; - - /* Dynamic Range */ - dyn_range = (data & DP_TEST_DYNAMIC_RANGE_CEA) >> 3; - if (!dp_link_is_dynamic_range_valid(dyn_range)) { - pr_err("invalid link dynamic range = 0x%x\n", dyn_range); - ret = -EINVAL; - goto exit; - } - link->dp_link.test_video.test_dyn_range = dyn_range; - pr_debug("link dynamic range = 0x%x (%s)\n", - link->dp_link.test_video.test_dyn_range, - dp_link_dynamic_range_to_string( - link->dp_link.test_video.test_dyn_range)); - - /* Color bit depth */ - data &= DP_TEST_BIT_DEPTH_MASK; - if (!dp_link_is_bit_depth_valid(data)) { - pr_err("invalid link bit depth = 0x%x\n", data); - ret = -EINVAL; - goto exit; - } - - link->dp_link.test_video.test_bit_depth = data; - pr_debug("link bit depth = 0x%x (%s)\n", - link->dp_link.test_video.test_bit_depth, - dp_link_bit_depth_to_string( - link->dp_link.test_video.test_bit_depth)); - - /* resolution timing params */ - ret = dp_link_parse_timing_params1(link, DP_TEST_H_TOTAL_HI, 2, - &link->dp_link.test_video.test_h_total); - if (ret) { - pr_err("failed to parse test_h_total (DP_TEST_H_TOTAL_HI)\n"); - goto exit; - } - pr_debug("TEST_H_TOTAL = %d\n", link->dp_link.test_video.test_h_total); - - ret = dp_link_parse_timing_params1(link, DP_TEST_V_TOTAL_HI, 2, - &link->dp_link.test_video.test_v_total); - if (ret) { - pr_err("failed to parse test_v_total (DP_TEST_V_TOTAL_HI)\n"); - goto exit; - } - pr_debug("TEST_V_TOTAL = %d\n", link->dp_link.test_video.test_v_total); - - ret = dp_link_parse_timing_params1(link, DP_TEST_H_START_HI, 2, - &link->dp_link.test_video.test_h_start); - if (ret) { - pr_err("failed to parse test_h_start (DP_TEST_H_START_HI)\n"); - goto exit; - } - pr_debug("TEST_H_START = %d\n", link->dp_link.test_video.test_h_start); - - ret = dp_link_parse_timing_params1(link, DP_TEST_V_START_HI, 2, - &link->dp_link.test_video.test_v_start); - if (ret) { - pr_err("failed to parse test_v_start (DP_TEST_V_START_HI)\n"); - goto exit; - } - pr_debug("TEST_V_START = %d\n", link->dp_link.test_video.test_v_start); - - ret = dp_link_parse_timing_params2(link, DP_TEST_HSYNC_HI, 2, - &link->dp_link.test_video.test_hsync_pol, - &link->dp_link.test_video.test_hsync_width); - if (ret) { - pr_err("failed to parse (DP_TEST_HSYNC_HI)\n"); - goto exit; - } - pr_debug("TEST_HSYNC_POL = %d\n", - link->dp_link.test_video.test_hsync_pol); - pr_debug("TEST_HSYNC_WIDTH = %d\n", - link->dp_link.test_video.test_hsync_width); - - ret = dp_link_parse_timing_params2(link, DP_TEST_VSYNC_HI, 2, - &link->dp_link.test_video.test_vsync_pol, - &link->dp_link.test_video.test_vsync_width); - if (ret) { - pr_err("failed to parse (DP_TEST_VSYNC_HI)\n"); - goto exit; - } - pr_debug("TEST_VSYNC_POL = %d\n", - link->dp_link.test_video.test_vsync_pol); - pr_debug("TEST_VSYNC_WIDTH = %d\n", - link->dp_link.test_video.test_vsync_width); - - ret = dp_link_parse_timing_params1(link, DP_TEST_H_WIDTH_HI, 2, - &link->dp_link.test_video.test_h_width); - if (ret) { - pr_err("failed to parse test_h_width (DP_TEST_H_WIDTH_HI)\n"); - goto exit; - } - pr_debug("TEST_H_WIDTH = %d\n", link->dp_link.test_video.test_h_width); - - ret = dp_link_parse_timing_params1(link, DP_TEST_V_HEIGHT_HI, 2, - &link->dp_link.test_video.test_v_height); - if (ret) { - pr_err("failed to parse test_v_height (DP_TEST_V_HEIGHT_HI)\n"); - goto exit; - } - pr_debug("TEST_V_HEIGHT = %d\n", - link->dp_link.test_video.test_v_height); - - ret = dp_link_parse_timing_params3(link, DP_TEST_MISC1, - &link->dp_link.test_video.test_rr_d); - link->dp_link.test_video.test_rr_d &= DP_TEST_REFRESH_DENOMINATOR; - if (ret) { - pr_err("failed to parse test_rr_d (DP_TEST_MISC1)\n"); - goto exit; - } - pr_debug("TEST_REFRESH_DENOMINATOR = %d\n", - link->dp_link.test_video.test_rr_d); - - ret = dp_link_parse_timing_params3(link, DP_TEST_REFRESH_RATE_NUMERATOR, - &link->dp_link.test_video.test_rr_n); - if (ret) { - pr_err("failed to parse test_rr_n (DP_TEST_REFRESH_RATE_NUMERATOR)\n"); - goto exit; - } - pr_debug("TEST_REFRESH_NUMERATOR = %d\n", - link->dp_link.test_video.test_rr_n); -exit: - return ret; -} - -/** - * dp_link_parse_link_training_params() - parses link training parameters from - * DPCD - * @link: Display Port Driver data - * - * Returns 0 if it successfully parses the link rate (Byte 0x219) and lane - * count (Byte 0x220), and if these values parse are valid. - */ -static int dp_link_parse_link_training_params(struct dp_link_private *link) -{ - u8 bp; - u8 data; - int ret = 0; - int rlen; - int const param_len = 0x1; - - rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_TEST_LINK_RATE, - &bp, param_len); - if (rlen < param_len) { - pr_err("failed to read link rate\n"); - ret = -EINVAL; - goto exit; - } - data = bp; - - if (!is_link_rate_valid(data)) { - pr_err("invalid link rate = 0x%x\n", data); - ret = -EINVAL; - goto exit; - } - - link->request.test_link_rate = data; - pr_debug("link rate = 0x%x\n", link->request.test_link_rate); - - rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_TEST_LANE_COUNT, - &bp, param_len); - if (rlen < param_len) { - pr_err("failed to read lane count\n"); - ret = -EINVAL; - goto exit; - } - data = bp; - data &= 0x1F; - - if (!is_lane_count_valid(data)) { - pr_err("invalid lane count = 0x%x\n", data); - ret = -EINVAL; - goto exit; - } - - link->request.test_lane_count = data; - pr_debug("lane count = 0x%x\n", link->request.test_lane_count); -exit: - return ret; -} - -static bool dp_link_is_phy_test_pattern_supported(u32 phy_test_pattern_sel) -{ - switch (phy_test_pattern_sel) { - case DP_TEST_PHY_PATTERN_NONE: - case DP_TEST_PHY_PATTERN_D10_2_NO_SCRAMBLING: - case DP_TEST_PHY_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT: - case DP_TEST_PHY_PATTERN_PRBS7: - case DP_TEST_PHY_PATTERN_80_BIT_CUSTOM_PATTERN: - case DP_TEST_PHY_PATTERN_CP2520_PATTERN_1: - case DP_TEST_PHY_PATTERN_CP2520_PATTERN_3: - return true; - default: - return false; - } -} - -/** - * dp_parse_phy_test_params() - parses the phy link parameters - * @link: Display Port Driver data - * - * Parses the DPCD (Byte 0x248) for the DP PHY link pattern that is being - * requested. - */ -static int dp_link_parse_phy_test_params(struct dp_link_private *link) -{ - u8 bp; - u8 data; - int rlen; - int const param_len = 0x1; - int ret = 0; - - rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_TEST_PHY_PATTERN, - &bp, param_len); - if (rlen < param_len) { - pr_err("failed to read phy link pattern\n"); - ret = -EINVAL; - goto end; - } - - data = bp; - - link->dp_link.phy_params.phy_test_pattern_sel = data; - - pr_debug("phy_test_pattern_sel = %s\n", - dp_link_get_phy_test_pattern(data)); - - if (!dp_link_is_phy_test_pattern_supported(data)) - ret = -EINVAL; -end: - return ret; -} - -/** - * dp_link_is_video_audio_test_requested() - checks for audio/video link request - * @link: link requested by the sink - * - * Returns true if the requested link is a permitted audio/video link. - */ -static bool dp_link_is_video_audio_test_requested(u32 link) -{ - return (link == DP_TEST_LINK_VIDEO_PATTERN) || - (link == (DP_TEST_LINK_AUDIO_PATTERN | - DP_TEST_LINK_VIDEO_PATTERN)) || - (link == DP_TEST_LINK_AUDIO_PATTERN) || - (link == (DP_TEST_LINK_AUDIO_PATTERN | - DP_TEST_LINK_AUDIO_DISABLED_VIDEO)); -} - -/** - * dp_link_supported() - checks if link requested by sink is supported - * @test_requested: link requested by the sink - * - * Returns true if the requested link is supported. - */ -static bool dp_link_is_test_supported(u32 test_requested) -{ - return (test_requested == DP_TEST_LINK_TRAINING) || - (test_requested == DP_TEST_LINK_EDID_READ) || - (test_requested == DP_TEST_LINK_PHY_TEST_PATTERN) || - dp_link_is_video_audio_test_requested(test_requested); -} - -static bool dp_link_is_test_edid_read(struct dp_link_private *link) -{ - return (link->request.test_requested == DP_TEST_LINK_EDID_READ); -} - -/** - * dp_sink_parse_test_request() - parses link request parameters from sink - * @link: Display Port Driver data - * - * Parses the DPCD to check if an automated link is requested (Byte 0x201), - * and what type of link automation is being requested (Byte 0x218). - */ -static int dp_link_parse_request(struct dp_link_private *link) -{ - int ret = 0; - u8 bp; - u8 data; - int rlen; - u32 const param_len = 0x1; - - /** - * Read the device service IRQ vector (Byte 0x201) to determine - * whether an automated link has been requested by the sink. - */ - rlen = drm_dp_dpcd_read(link->aux->drm_aux, - DP_DEVICE_SERVICE_IRQ_VECTOR, &bp, param_len); - if (rlen < param_len) { - pr_err("aux read failed\n"); - ret = -EINVAL; - goto end; - } - - data = bp; - - if (!(data & DP_AUTOMATED_TEST_REQUEST)) - return 0; - - /** - * Read the link request byte (Byte 0x218) to determine what type - * of automated link has been requested by the sink. - */ - rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_TEST_REQUEST, - &bp, param_len); - if (rlen < param_len) { - pr_err("aux read failed\n"); - ret = -EINVAL; - goto end; - } - - data = bp; - - if (!dp_link_is_test_supported(data)) { - pr_debug("link 0x%x not supported\n", data); - goto end; - } - - link->request.test_requested = data; - - if (link->request.test_requested == DP_TEST_LINK_PHY_TEST_PATTERN) { - ret = dp_link_parse_phy_test_params(link); - if (ret) - goto end; - ret = dp_link_parse_link_training_params(link); - } - - if (link->request.test_requested == DP_TEST_LINK_TRAINING) - ret = dp_link_parse_link_training_params(link); - - if (dp_link_is_video_audio_test_requested( - link->request.test_requested)) { - ret = dp_link_parse_video_pattern_params(link); - if (ret) - goto end; - - ret = dp_link_parse_audio_pattern_params(link); - } -end: - /** - * Send a DP_TEST_ACK if all link parameters are valid, otherwise send - * a DP_TEST_NAK. - */ - if (ret) { - link->dp_link.test_response = DP_TEST_NAK; - } else { - if (!dp_link_is_test_edid_read(link)) - link->dp_link.test_response = DP_TEST_ACK; - else - link->dp_link.test_response = - DP_TEST_EDID_CHECKSUM_WRITE; - } - - return ret; -} - -/** - * dp_link_parse_sink_count() - parses the sink count - * - * Parses the DPCD to check if there is an update to the sink count - * (Byte 0x200), and whether all the sink devices connected have Content - * Protection enabled. - */ -static int dp_link_parse_sink_count(struct dp_link *dp_link) -{ - int rlen; - int const param_len = 0x1; - struct dp_link_private *link = container_of(dp_link, - struct dp_link_private, dp_link); - - rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_SINK_COUNT, - &link->dp_link.sink_count.count, param_len); - if (rlen < param_len) { - pr_err("failed to read sink count\n"); - return -EINVAL; - } - - link->dp_link.sink_count.cp_ready = - link->dp_link.sink_count.count & DP_SINK_CP_READY; - /* BIT 7, BIT 5:0 */ - link->dp_link.sink_count.count = - DP_GET_SINK_COUNT(link->dp_link.sink_count.count); - - pr_debug("sink_count = 0x%x, cp_ready = 0x%x\n", - link->dp_link.sink_count.count, - link->dp_link.sink_count.cp_ready); - return 0; -} - -static void dp_link_parse_sink_status_field(struct dp_link_private *link) -{ - int len = 0; - - link->prev_sink_count = link->dp_link.sink_count.count; - dp_link_parse_sink_count(&link->dp_link); - - len = drm_dp_dpcd_read_link_status(link->aux->drm_aux, - link->link_status); - if (len < DP_LINK_STATUS_SIZE) - pr_err("DP link status read failed\n"); - dp_link_parse_request(link); -} - -static bool dp_link_is_link_training_requested(struct dp_link_private *link) -{ - return (link->request.test_requested == DP_TEST_LINK_TRAINING); -} - -/** - * dp_link_process_link_training_request() - processes new training requests - * @link: Display Port link data - * - * This function will handle new link training requests that are initiated by - * the sink. In particular, it will update the requested lane count and link - * link rate, and then trigger the link retraining procedure. - * - * The function will return 0 if a link training request has been processed, - * otherwise it will return -EINVAL. - */ -static int dp_link_process_link_training_request(struct dp_link_private *link) -{ - if (!dp_link_is_link_training_requested(link)) - return -EINVAL; - - pr_debug("%s link rate = 0x%x, lane count = 0x%x\n", - dp_link_get_test_name(DP_TEST_LINK_TRAINING), - link->request.test_link_rate, - link->request.test_lane_count); - - link->dp_link.link_params.lane_count = link->request.test_lane_count; - link->dp_link.link_params.bw_code = link->request.test_link_rate; - - return 0; -} - -static void dp_link_send_test_response(struct dp_link *dp_link) -{ - struct dp_link_private *link = NULL; - u32 const response_len = 0x1; - - if (!dp_link) { - pr_err("invalid input\n"); - return; - } - - link = container_of(dp_link, struct dp_link_private, dp_link); - - drm_dp_dpcd_write(link->aux->drm_aux, DP_TEST_RESPONSE, - &dp_link->test_response, response_len); -} - -static int dp_link_psm_config(struct dp_link *dp_link, - struct drm_dp_link *link_info, bool enable) -{ - struct dp_link_private *link = NULL; - int ret = 0; - - if (!dp_link) { - pr_err("invalid params\n"); - return -EINVAL; - } - - link = container_of(dp_link, struct dp_link_private, dp_link); - - if (enable) - ret = drm_dp_link_power_down(link->aux->drm_aux, link_info); - else - ret = drm_dp_link_power_up(link->aux->drm_aux, link_info); - - if (ret) - pr_err("Failed to %s low power mode\n", - (enable ? "enter" : "exit")); - - return ret; -} - -static void dp_link_send_edid_checksum(struct dp_link *dp_link, u8 checksum) -{ - struct dp_link_private *link = NULL; - u32 const response_len = 0x1; - - if (!dp_link) { - pr_err("invalid input\n"); - return; - } - - link = container_of(dp_link, struct dp_link_private, dp_link); - - drm_dp_dpcd_write(link->aux->drm_aux, DP_TEST_EDID_CHECKSUM, - &checksum, response_len); -} - -static int dp_link_parse_vx_px(struct dp_link_private *link) -{ - u8 bp; - u8 data; - int const param_len = 0x1; - int ret = 0; - u32 v0, p0, v1, p1, v2, p2, v3, p3; - int rlen; - - pr_debug("\n"); - - rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_ADJUST_REQUEST_LANE0_1, - &bp, param_len); - if (rlen < param_len) { - pr_err("failed reading lanes 0/1\n"); - ret = -EINVAL; - goto end; - } - - data = bp; - - pr_debug("lanes 0/1 (Byte 0x206): 0x%x\n", data); - - v0 = data & 0x3; - data = data >> 2; - p0 = data & 0x3; - data = data >> 2; - - v1 = data & 0x3; - data = data >> 2; - p1 = data & 0x3; - data = data >> 2; - - rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_ADJUST_REQUEST_LANE2_3, - &bp, param_len); - if (rlen < param_len) { - pr_err("failed reading lanes 2/3\n"); - ret = -EINVAL; - goto end; - } - - data = bp; - - pr_debug("lanes 2/3 (Byte 0x207): 0x%x\n", data); - - v2 = data & 0x3; - data = data >> 2; - p2 = data & 0x3; - data = data >> 2; - - v3 = data & 0x3; - data = data >> 2; - p3 = data & 0x3; - data = data >> 2; - - pr_debug("vx: 0=%d, 1=%d, 2=%d, 3=%d\n", v0, v1, v2, v3); - pr_debug("px: 0=%d, 1=%d, 2=%d, 3=%d\n", p0, p1, p2, p3); - - /** - * Update the voltage and pre-emphasis levels as per DPCD request - * vector. - */ - pr_debug("Current: v_level = 0x%x, p_level = 0x%x\n", - link->dp_link.phy_params.v_level, - link->dp_link.phy_params.p_level); - pr_debug("Requested: v_level = 0x%x, p_level = 0x%x\n", v0, p0); - link->dp_link.phy_params.v_level = v0; - link->dp_link.phy_params.p_level = p0; - - pr_debug("Success\n"); -end: - return ret; -} - -/** - * dp_link_process_phy_test_pattern_request() - process new phy link requests - * @link: Display Port Driver data - * - * This function will handle new phy link pattern requests that are initiated - * by the sink. The function will return 0 if a phy link pattern has been - * processed, otherwise it will return -EINVAL. - */ -static int dp_link_process_phy_test_pattern_request( - struct dp_link_private *link) -{ - u32 test_link_rate = 0, test_lane_count = 0; - - if (!(link->request.test_requested & DP_TEST_LINK_PHY_TEST_PATTERN)) { - pr_debug("no phy test\n"); - return -EINVAL; - } - - test_link_rate = link->request.test_link_rate; - test_lane_count = link->request.test_lane_count; - - if (!is_link_rate_valid(test_link_rate) || - !is_lane_count_valid(test_lane_count)) { - pr_err("Invalid params: link rate = 0x%x, lane count = 0x%x\n", - test_link_rate, test_lane_count); - return -EINVAL; - } - - pr_debug("start\n"); - - pr_info("Current: bw_code = 0x%x, lane count = 0x%x\n", - link->dp_link.link_params.bw_code, - link->dp_link.link_params.lane_count); - - pr_info("Requested: bw_code = 0x%x, lane count = 0x%x\n", - test_link_rate, test_lane_count); - - link->dp_link.link_params.lane_count = link->request.test_lane_count; - link->dp_link.link_params.bw_code = link->request.test_link_rate; - - dp_link_parse_vx_px(link); - - pr_debug("end\n"); - - return 0; -} - -static u8 get_link_status(const u8 link_status[DP_LINK_STATUS_SIZE], int r) -{ - return link_status[r - DP_LANE0_1_STATUS]; -} - -/** - * dp_link_process_link_status_update() - processes link status updates - * @link: Display Port link module data - * - * This function will check for changes in the link status, e.g. clock - * recovery done on all lanes, and trigger link training if there is a - * failure/error on the link. - * - * The function will return 0 if the a link status update has been processed, - * otherwise it will return -EINVAL. - */ -static int dp_link_process_link_status_update(struct dp_link_private *link) -{ - if (!(get_link_status(link->link_status, DP_LANE_ALIGN_STATUS_UPDATED) & - DP_LINK_STATUS_UPDATED) || /* link status updated */ - (drm_dp_clock_recovery_ok(link->link_status, - link->dp_link.link_params.lane_count) && - drm_dp_channel_eq_ok(link->link_status, - link->dp_link.link_params.lane_count))) - return -EINVAL; - - pr_debug("channel_eq_done = %d, clock_recovery_done = %d\n", - drm_dp_clock_recovery_ok(link->link_status, - link->dp_link.link_params.lane_count), - drm_dp_clock_recovery_ok(link->link_status, - link->dp_link.link_params.lane_count)); - - return 0; -} - -static bool dp_link_is_ds_port_status_changed(struct dp_link_private *link) -{ - if (get_link_status(link->link_status, DP_LANE_ALIGN_STATUS_UPDATED) & - DP_DOWNSTREAM_PORT_STATUS_CHANGED) /* port status changed */ - return true; - - if (link->prev_sink_count != link->dp_link.sink_count.count) - return true; - - return false; -} - -/** - * dp_link_process_downstream_port_status_change() - process port status changes - * @link: Display Port Driver data - * - * This function will handle downstream port updates that are initiated by - * the sink. If the downstream port status has changed, the EDID is read via - * AUX. - * - * The function will return 0 if a downstream port update has been - * processed, otherwise it will return -EINVAL. - */ -static int dp_link_process_ds_port_status_change(struct dp_link_private *link) -{ - if (!dp_link_is_ds_port_status_changed(link)) - return -EINVAL; - - /* reset prev_sink_count */ - link->prev_sink_count = link->dp_link.sink_count.count; - - return 0; -} - -static bool dp_link_is_video_pattern_requested(struct dp_link_private *link) -{ - return (link->request.test_requested & DP_TEST_LINK_VIDEO_PATTERN) - && !(link->request.test_requested & - DP_TEST_LINK_AUDIO_DISABLED_VIDEO); -} - -static bool dp_link_is_audio_pattern_requested(struct dp_link_private *link) -{ - return (link->request.test_requested & DP_TEST_LINK_AUDIO_PATTERN); -} - -/** - * dp_link_process_video_pattern_request() - process new video pattern request - * @link: Display Port link module's data - * - * This function will handle a new video pattern request that are initiated by - * the sink. This is acheieved by first sending a disconnect notification to - * the sink followed by a subsequent connect notification to the user modules, - * where it is expected that the user modules would draw the required link - * pattern. - */ -static int dp_link_process_video_pattern_request(struct dp_link_private *link) -{ - if (!dp_link_is_video_pattern_requested(link)) - goto end; - - pr_debug("%s: bit depth=%d(%d bpp) pattern=%s\n", - dp_link_get_test_name(DP_TEST_LINK_VIDEO_PATTERN), - link->dp_link.test_video.test_bit_depth, - dp_link_bit_depth_to_bpp( - link->dp_link.test_video.test_bit_depth), - dp_link_video_pattern_to_string( - link->dp_link.test_video.test_video_pattern)); - - return 0; -end: - return -EINVAL; -} - -/** - * dp_link_process_audio_pattern_request() - process new audio pattern request - * @link: Display Port link module data - * - * This function will handle a new audio pattern request that is initiated by - * the sink. This is acheieved by sending the necessary secondary data packets - * to the sink. It is expected that any simulatenous requests for video - * patterns will be handled before the audio pattern is sent to the sink. - */ -static int dp_link_process_audio_pattern_request(struct dp_link_private *link) -{ - if (!dp_link_is_audio_pattern_requested(link)) - return -EINVAL; - - pr_debug("sampling_rate=%s, channel_count=%d, pattern_type=%s\n", - dp_link_get_audio_sample_rate( - link->dp_link.test_audio.test_audio_sampling_rate), - link->dp_link.test_audio.test_audio_channel_count, - dp_link_get_audio_test_pattern( - link->dp_link.test_audio.test_audio_pattern_type)); - - pr_debug("audio_period: ch1=0x%x, ch2=0x%x, ch3=0x%x, ch4=0x%x\n", - link->dp_link.test_audio.test_audio_period_ch_1, - link->dp_link.test_audio.test_audio_period_ch_2, - link->dp_link.test_audio.test_audio_period_ch_3, - link->dp_link.test_audio.test_audio_period_ch_4); - - pr_debug("audio_period: ch5=0x%x, ch6=0x%x, ch7=0x%x, ch8=0x%x\n", - link->dp_link.test_audio.test_audio_period_ch_5, - link->dp_link.test_audio.test_audio_period_ch_6, - link->dp_link.test_audio.test_audio_period_ch_7, - link->dp_link.test_audio.test_audio_period_ch_8); - - return 0; -} - -static void dp_link_reset_data(struct dp_link_private *link) -{ - link->request = (const struct dp_link_request){ 0 }; - link->dp_link.test_video = (const struct dp_link_test_video){ 0 }; - link->dp_link.test_video.test_bit_depth = DP_TEST_BIT_DEPTH_UNKNOWN; - link->dp_link.test_audio = (const struct dp_link_test_audio){ 0 }; - link->dp_link.phy_params.phy_test_pattern_sel = 0; - link->dp_link.sink_request = 0; - link->dp_link.test_response = 0; -} - -/** - * dp_link_process_request() - handle HPD IRQ transition to HIGH - * @link: pointer to link module data - * - * This function will handle the HPD IRQ state transitions from LOW to HIGH - * (including cases when there are back to back HPD IRQ HIGH) indicating - * the start of a new link training request or sink status update. - */ -static int dp_link_process_request(struct dp_link *dp_link) -{ - int ret = 0; - struct dp_link_private *link; - - if (!dp_link) { - pr_err("invalid input\n"); - return -EINVAL; - } - - link = container_of(dp_link, struct dp_link_private, dp_link); - - dp_link_reset_data(link); - - dp_link_parse_sink_status_field(link); - - if (dp_link_is_test_edid_read(link)) { - dp_link->sink_request |= DP_TEST_LINK_EDID_READ; - goto exit; - } - - ret = dp_link_process_ds_port_status_change(link); - if (!ret) { - dp_link->sink_request |= DS_PORT_STATUS_CHANGED; - goto exit; - } - - ret = dp_link_process_link_training_request(link); - if (!ret) { - dp_link->sink_request |= DP_TEST_LINK_TRAINING; - goto exit; - } - - ret = dp_link_process_phy_test_pattern_request(link); - if (!ret) { - dp_link->sink_request |= DP_TEST_LINK_PHY_TEST_PATTERN; - goto exit; - } - - ret = dp_link_process_link_status_update(link); - if (!ret) { - dp_link->sink_request |= DP_LINK_STATUS_UPDATED; - goto exit; - } - - ret = dp_link_process_video_pattern_request(link); - if (!ret) { - dp_link->sink_request |= DP_TEST_LINK_VIDEO_PATTERN; - goto exit; - } - - ret = dp_link_process_audio_pattern_request(link); - if (!ret) { - dp_link->sink_request |= DP_TEST_LINK_AUDIO_PATTERN; - goto exit; - } - - pr_debug("no test requested\n"); - return ret; -exit: - /* - * log this as it can be a use initiated action to run a DP CTS - * test or in normal cases, sink has encountered a problem and - * and want source to redo some part of initialization which can - * be helpful in debugging. - */ - pr_info("test requested: %s\n", - dp_link_get_test_name(dp_link->sink_request)); - return 0; -} - -static int dp_link_get_colorimetry_config(struct dp_link *dp_link) -{ - u32 cc; - enum dynamic_range dr; - struct dp_link_private *link; - - if (!dp_link) { - pr_err("invalid input\n"); - return -EINVAL; - } - - link = container_of(dp_link, struct dp_link_private, dp_link); - - /* unless a video pattern CTS test is ongoing, use CEA_VESA */ - if (dp_link_is_video_pattern_requested(link)) - dr = link->dp_link.test_video.test_dyn_range; - else - dr = DP_DYNAMIC_RANGE_RGB_VESA; - - /* Only RGB_VESA nd RGB_CEA supported for now */ - switch (dr) { - case DP_DYNAMIC_RANGE_RGB_CEA: - cc = BIT(3); - break; - case DP_DYNAMIC_RANGE_RGB_VESA: - default: - cc = 0; - } - - return cc; -} - -static int dp_link_adjust_levels(struct dp_link *dp_link, u8 *link_status) -{ - int i; - int max = 0; - u8 data; - struct dp_link_private *link; - u8 buf[8] = {0}, offset = 0; - - if (!dp_link) { - pr_err("invalid input\n"); - return -EINVAL; - } - - link = container_of(dp_link, struct dp_link_private, dp_link); - - /* use the max level across lanes */ - for (i = 0; i < dp_link->link_params.lane_count; i++) { - data = drm_dp_get_adjust_request_voltage(link_status, i); - data >>= DP_TRAIN_VOLTAGE_SWING_SHIFT; - - offset = i * 2; - if (offset < sizeof(buf)) - buf[offset] = data; - - if (max < data) - max = data; - } - - dp_link->phy_params.v_level = max; - - /* use the max level across lanes */ - max = 0; - for (i = 0; i < dp_link->link_params.lane_count; i++) { - data = drm_dp_get_adjust_request_pre_emphasis(link_status, i); - data >>= DP_TRAIN_PRE_EMPHASIS_SHIFT; - - offset = (i * 2) + 1; - if (offset < sizeof(buf)) - buf[offset] = data; - - if (max < data) - max = data; - } - - dp_link->phy_params.p_level = max; - - print_hex_dump(KERN_DEBUG, "[drm-dp] Req (VxPx): ", - DUMP_PREFIX_NONE, 8, 2, buf, sizeof(buf), false); - - /** - * Adjust the voltage swing and pre-emphasis level combination to within - * the allowable range. - */ - if (dp_link->phy_params.v_level > DP_LINK_VOLTAGE_MAX) - dp_link->phy_params.v_level = DP_LINK_VOLTAGE_MAX; - - if (dp_link->phy_params.p_level > DP_LINK_PRE_EMPHASIS_MAX) - dp_link->phy_params.p_level = DP_LINK_PRE_EMPHASIS_MAX; - - if ((dp_link->phy_params.p_level > DP_LINK_PRE_EMPHASIS_LEVEL_1) - && (dp_link->phy_params.v_level == DP_LINK_VOLTAGE_LEVEL_2)) - dp_link->phy_params.p_level = DP_LINK_PRE_EMPHASIS_LEVEL_1; - - pr_debug("Set (VxPx): %x%x\n", - dp_link->phy_params.v_level, dp_link->phy_params.p_level); - - return 0; -} - -static int dp_link_send_psm_request(struct dp_link *dp_link, bool req) -{ - struct dp_link_private *link; - - if (!dp_link) { - pr_err("invalid input\n"); - return -EINVAL; - } - - link = container_of(dp_link, struct dp_link_private, dp_link); - - return 0; -} - -static u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp) -{ - u32 tbd; - - /* - * Few simplistic rules and assumptions made here: - * 1. Test bit depth is bit depth per color component - * 2. Assume 3 color components - */ - switch (bpp) { - case 18: - tbd = DP_TEST_BIT_DEPTH_6; - break; - case 24: - tbd = DP_TEST_BIT_DEPTH_8; - break; - case 30: - tbd = DP_TEST_BIT_DEPTH_10; - break; - default: - tbd = DP_TEST_BIT_DEPTH_UNKNOWN; - break; - } - - if (tbd != DP_TEST_BIT_DEPTH_UNKNOWN) - tbd = (tbd >> DP_TEST_BIT_DEPTH_SHIFT); - - return tbd; -} - -struct dp_link *dp_link_get(struct device *dev, struct dp_aux *aux) -{ - int rc = 0; - struct dp_link_private *link; - struct dp_link *dp_link; - - if (!dev || !aux) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto error; - } - - link = devm_kzalloc(dev, sizeof(*link), GFP_KERNEL); - if (!link) { - rc = -EINVAL; - goto error; - } - - link->dev = dev; - link->aux = aux; - - dp_link = &link->dp_link; - - dp_link->process_request = dp_link_process_request; - dp_link->get_test_bits_depth = dp_link_get_test_bits_depth; - dp_link->get_colorimetry_config = dp_link_get_colorimetry_config; - dp_link->adjust_levels = dp_link_adjust_levels; - dp_link->send_psm_request = dp_link_send_psm_request; - dp_link->send_test_response = dp_link_send_test_response; - dp_link->psm_config = dp_link_psm_config; - dp_link->send_edid_checksum = dp_link_send_edid_checksum; - - return dp_link; -error: - return ERR_PTR(rc); -} - -void dp_link_put(struct dp_link *dp_link) -{ - struct dp_link_private *link; - - if (!dp_link) - return; - - link = container_of(dp_link, struct dp_link_private, dp_link); - - devm_kfree(link->dev, link); -} diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h deleted file mode 100644 index 740cf01b53a522e014e474034241258a2a860317..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_link.h +++ /dev/null @@ -1,205 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. - */ - -#ifndef _DP_LINK_H_ -#define _DP_LINK_H_ - -#include "dp_aux.h" - -#define DS_PORT_STATUS_CHANGED 0x200 -#define DP_TEST_BIT_DEPTH_UNKNOWN 0xFFFFFFFF -#define DP_LINK_ENUM_STR(x) #x - -enum dp_link_voltage_level { - DP_LINK_VOLTAGE_LEVEL_0 = 0, - DP_LINK_VOLTAGE_LEVEL_1 = 1, - DP_LINK_VOLTAGE_LEVEL_2 = 2, - DP_LINK_VOLTAGE_MAX = DP_LINK_VOLTAGE_LEVEL_2, -}; - -enum dp_link_preemaphasis_level { - DP_LINK_PRE_EMPHASIS_LEVEL_0 = 0, - DP_LINK_PRE_EMPHASIS_LEVEL_1 = 1, - DP_LINK_PRE_EMPHASIS_LEVEL_2 = 2, - DP_LINK_PRE_EMPHASIS_MAX = DP_LINK_PRE_EMPHASIS_LEVEL_2, -}; - -struct dp_link_sink_count { - u32 count; - bool cp_ready; -}; - -struct dp_link_test_video { - u32 test_video_pattern; - u32 test_bit_depth; - u32 test_dyn_range; - u32 test_h_total; - u32 test_v_total; - u32 test_h_start; - u32 test_v_start; - u32 test_hsync_pol; - u32 test_hsync_width; - u32 test_vsync_pol; - u32 test_vsync_width; - u32 test_h_width; - u32 test_v_height; - u32 test_rr_d; - u32 test_rr_n; -}; - -struct dp_link_test_audio { - u32 test_audio_sampling_rate; - u32 test_audio_channel_count; - u32 test_audio_pattern_type; - u32 test_audio_period_ch_1; - u32 test_audio_period_ch_2; - u32 test_audio_period_ch_3; - u32 test_audio_period_ch_4; - u32 test_audio_period_ch_5; - u32 test_audio_period_ch_6; - u32 test_audio_period_ch_7; - u32 test_audio_period_ch_8; -}; - -struct dp_link_hdcp_status { - int hdcp_state; - int hdcp_version; -}; - -struct dp_link_phy_params { - u32 phy_test_pattern_sel; - u8 v_level; - u8 p_level; -}; - -struct dp_link_params { - u32 lane_count; - u32 bw_code; -}; - -static inline char *dp_link_get_test_name(u32 test_requested) -{ - switch (test_requested) { - case DP_TEST_LINK_TRAINING: - return DP_LINK_ENUM_STR(DP_TEST_LINK_TRAINING); - case DP_TEST_LINK_VIDEO_PATTERN: - return DP_LINK_ENUM_STR(DP_TEST_LINK_VIDEO_PATTERN); - case DP_TEST_LINK_EDID_READ: - return DP_LINK_ENUM_STR(DP_TEST_LINK_EDID_READ); - case DP_TEST_LINK_PHY_TEST_PATTERN: - return DP_LINK_ENUM_STR(DP_TEST_LINK_PHY_TEST_PATTERN); - case DP_TEST_LINK_AUDIO_PATTERN: - return DP_LINK_ENUM_STR(DP_TEST_LINK_AUDIO_PATTERN); - case DS_PORT_STATUS_CHANGED: - return DP_LINK_ENUM_STR(DS_PORT_STATUS_CHANGED); - case DP_LINK_STATUS_UPDATED: - return DP_LINK_ENUM_STR(DP_LINK_STATUS_UPDATED); - default: - return "unknown"; - } -} - -struct dp_link { - u32 sink_request; - u32 test_response; - - struct dp_link_sink_count sink_count; - struct dp_link_test_video test_video; - struct dp_link_test_audio test_audio; - struct dp_link_phy_params phy_params; - struct dp_link_params link_params; - struct dp_link_hdcp_status hdcp_status; - - u32 (*get_test_bits_depth)(struct dp_link *dp_link, u32 bpp); - int (*process_request)(struct dp_link *dp_link); - int (*get_colorimetry_config)(struct dp_link *dp_link); - int (*adjust_levels)(struct dp_link *dp_link, u8 *link_status); - int (*send_psm_request)(struct dp_link *dp_link, bool req); - void (*send_test_response)(struct dp_link *dp_link); - int (*psm_config)(struct dp_link *dp_link, - struct drm_dp_link *link_info, bool enable); - void (*send_edid_checksum)(struct dp_link *dp_link, u8 checksum); -}; - -static inline char *dp_link_get_phy_test_pattern(u32 phy_test_pattern_sel) -{ - switch (phy_test_pattern_sel) { - case DP_TEST_PHY_PATTERN_NONE: - return DP_LINK_ENUM_STR(DP_TEST_PHY_PATTERN_NONE); - case DP_TEST_PHY_PATTERN_D10_2_NO_SCRAMBLING: - return DP_LINK_ENUM_STR( - DP_TEST_PHY_PATTERN_D10_2_NO_SCRAMBLING); - case DP_TEST_PHY_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT: - return DP_LINK_ENUM_STR( - DP_TEST_PHY_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT); - case DP_TEST_PHY_PATTERN_PRBS7: - return DP_LINK_ENUM_STR(DP_TEST_PHY_PATTERN_PRBS7); - case DP_TEST_PHY_PATTERN_80_BIT_CUSTOM_PATTERN: - return DP_LINK_ENUM_STR( - DP_TEST_PHY_PATTERN_80_BIT_CUSTOM_PATTERN); - case DP_TEST_PHY_PATTERN_CP2520_PATTERN_1: - return DP_LINK_ENUM_STR(DP_TEST_PHY_PATTERN_CP2520_PATTERN_1); - case DP_TEST_PHY_PATTERN_CP2520_PATTERN_2: - return DP_LINK_ENUM_STR(DP_TEST_PHY_PATTERN_CP2520_PATTERN_2); - case DP_TEST_PHY_PATTERN_CP2520_PATTERN_3: - return DP_LINK_ENUM_STR(DP_TEST_PHY_PATTERN_CP2520_PATTERN_3); - default: - return "unknown"; - } -} - -/** - * mdss_dp_test_bit_depth_to_bpp() - convert test bit depth to bpp - * @tbd: test bit depth - * - * Returns the bits per pixel (bpp) to be used corresponding to the - * git bit depth value. This function assumes that bit depth has - * already been validated. - */ -static inline u32 dp_link_bit_depth_to_bpp(u32 tbd) -{ - u32 bpp; - - /* - * Few simplistic rules and assumptions made here: - * 1. Bit depth is per color component - * 2. If bit depth is unknown return 0 - * 3. Assume 3 color components - */ - switch (tbd) { - case DP_TEST_BIT_DEPTH_6: - bpp = 18; - break; - case DP_TEST_BIT_DEPTH_8: - bpp = 24; - break; - case DP_TEST_BIT_DEPTH_10: - bpp = 30; - break; - case DP_TEST_BIT_DEPTH_UNKNOWN: - default: - bpp = 0; - } - - return bpp; -} - -/** - * dp_link_get() - get the functionalities of dp test module - * - * - * return: a pointer to dp_link struct - */ -struct dp_link *dp_link_get(struct device *dev, struct dp_aux *aux); - -/** - * dp_link_put() - releases the dp test module's resources - * - * @dp_link: an instance of dp_link module - * - */ -void dp_link_put(struct dp_link *dp_link); - -#endif /* _DP_LINK_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_lphw_hpd.c b/drivers/gpu/drm/msm/dp/dp_lphw_hpd.c deleted file mode 100644 index 8fcb49234c25bc2d6ff3374c9fe09a67281fc6c9..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_lphw_hpd.c +++ /dev/null @@ -1,422 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "dp_lphw_hpd.h" - -struct dp_lphw_hpd_private { - struct device *dev; - struct dp_hpd base; - struct dp_parser *parser; - struct dp_catalog_hpd *catalog; - struct dss_gpio gpio_cfg; - struct workqueue_struct *connect_wq; - struct delayed_work work; - struct work_struct connect; - struct work_struct disconnect; - struct work_struct attention; - struct dp_hpd_cb *cb; - int irq; - bool hpd; -}; - -static void dp_lphw_hpd_attention(struct work_struct *work) -{ - struct dp_lphw_hpd_private *lphw_hpd = container_of(work, - struct dp_lphw_hpd_private, attention); - - if (!lphw_hpd) { - pr_err("invalid input\n"); - return; - } - - lphw_hpd->base.hpd_irq = true; - - if (lphw_hpd->cb && lphw_hpd->cb->attention) - lphw_hpd->cb->attention(lphw_hpd->dev); -} - -static void dp_lphw_hpd_connect(struct work_struct *work) -{ - struct dp_lphw_hpd_private *lphw_hpd = container_of(work, - struct dp_lphw_hpd_private, connect); - - if (!lphw_hpd) { - pr_err("invalid input\n"); - return; - } - - lphw_hpd->base.hpd_high = true; - lphw_hpd->base.alt_mode_cfg_done = true; - lphw_hpd->base.hpd_irq = false; - - if (lphw_hpd->cb && lphw_hpd->cb->configure) - lphw_hpd->cb->configure(lphw_hpd->dev); -} - -static void dp_lphw_hpd_disconnect(struct work_struct *work) -{ - struct dp_lphw_hpd_private *lphw_hpd = container_of(work, - struct dp_lphw_hpd_private, disconnect); - - if (!lphw_hpd) { - pr_err("invalid input\n"); - return; - } - - lphw_hpd->base.hpd_high = false; - lphw_hpd->base.alt_mode_cfg_done = false; - lphw_hpd->base.hpd_irq = false; - - if (lphw_hpd->cb && lphw_hpd->cb->disconnect) - lphw_hpd->cb->disconnect(lphw_hpd->dev); -} - -static irqreturn_t dp_tlmm_isr(int unused, void *data) -{ - struct dp_lphw_hpd_private *lphw_hpd = data; - bool hpd; - - if (!lphw_hpd) - return IRQ_NONE; - - /* - * According to the DP spec, HPD high event can be confirmed only after - * the HPD line has een asserted continuously for more than 100ms - */ - usleep_range(99000, 100000); - - hpd = gpio_get_value_cansleep(lphw_hpd->gpio_cfg.gpio); - - pr_debug("lphw_hpd state = %d, new hpd state = %d\n", - lphw_hpd->hpd, hpd); - if (!lphw_hpd->hpd && hpd) { - lphw_hpd->hpd = true; - queue_work(lphw_hpd->connect_wq, &lphw_hpd->connect); - } - - return IRQ_HANDLED; -} - -static void dp_lphw_hpd_host_init(struct dp_hpd *dp_hpd, - struct dp_catalog_hpd *catalog) -{ - struct dp_lphw_hpd_private *lphw_hpd; - - if (!dp_hpd) { - pr_err("invalid input\n"); - return; - } - - lphw_hpd = container_of(dp_hpd, struct dp_lphw_hpd_private, base); - - lphw_hpd->catalog->config_hpd(lphw_hpd->catalog, true); - - /* - * Changing the gpio function to dp controller for the hpd line is not - * stopping the tlmm interrupts generation on function 0. - * So, as an additional step, disable the gpio interrupt irq also - */ - disable_irq(lphw_hpd->irq); -} - -static void dp_lphw_hpd_host_deinit(struct dp_hpd *dp_hpd, - struct dp_catalog_hpd *catalog) -{ - struct dp_lphw_hpd_private *lphw_hpd; - - if (!dp_hpd) { - pr_err("invalid input\n"); - return; - } - - lphw_hpd = container_of(dp_hpd, struct dp_lphw_hpd_private, base); - - /* Enable the tlmm interrupt irq which was disabled in host_init */ - enable_irq(lphw_hpd->irq); - - lphw_hpd->catalog->config_hpd(lphw_hpd->catalog, false); -} - -static void dp_lphw_hpd_isr(struct dp_hpd *dp_hpd) -{ - struct dp_lphw_hpd_private *lphw_hpd; - u32 isr = 0; - int rc = 0; - - if (!dp_hpd) { - pr_err("invalid input\n"); - return; - } - - lphw_hpd = container_of(dp_hpd, struct dp_lphw_hpd_private, base); - - isr = lphw_hpd->catalog->get_interrupt(lphw_hpd->catalog); - - if (isr & DP_HPD_UNPLUG_INT_STATUS) { /* disconnect interrupt */ - - pr_debug("disconnect interrupt, hpd isr state: 0x%x\n", isr); - - if (lphw_hpd->base.hpd_high) { - lphw_hpd->hpd = false; - lphw_hpd->base.hpd_high = false; - lphw_hpd->base.alt_mode_cfg_done = false; - lphw_hpd->base.hpd_irq = false; - - rc = queue_work(lphw_hpd->connect_wq, - &lphw_hpd->disconnect); - if (!rc) - pr_debug("disconnect not queued\n"); - } else { - pr_err("already disconnected\n"); - } - - } else if (isr & DP_IRQ_HPD_INT_STATUS) { /* attention interrupt */ - - pr_debug("hpd_irq interrupt, hpd isr state: 0x%x\n", isr); - - rc = queue_work(lphw_hpd->connect_wq, &lphw_hpd->attention); - if (!rc) - pr_debug("attention not queued\n"); - } -} - -static int dp_lphw_hpd_simulate_connect(struct dp_hpd *dp_hpd, bool hpd) -{ - struct dp_lphw_hpd_private *lphw_hpd; - - if (!dp_hpd) { - pr_err("invalid input\n"); - return -EINVAL; - } - - lphw_hpd = container_of(dp_hpd, struct dp_lphw_hpd_private, base); - - lphw_hpd->base.hpd_high = hpd; - lphw_hpd->base.alt_mode_cfg_done = hpd; - lphw_hpd->base.hpd_irq = false; - - if (!lphw_hpd->cb || !lphw_hpd->cb->configure || - !lphw_hpd->cb->disconnect) { - pr_err("invalid callback\n"); - return -EINVAL; - } - - if (hpd) - lphw_hpd->cb->configure(lphw_hpd->dev); - else - lphw_hpd->cb->disconnect(lphw_hpd->dev); - - return 0; -} - -static int dp_lphw_hpd_simulate_attention(struct dp_hpd *dp_hpd, int vdo) -{ - struct dp_lphw_hpd_private *lphw_hpd; - - if (!dp_hpd) { - pr_err("invalid input\n"); - return -EINVAL; - } - - lphw_hpd = container_of(dp_hpd, struct dp_lphw_hpd_private, base); - - lphw_hpd->base.hpd_irq = true; - - if (lphw_hpd->cb && lphw_hpd->cb->attention) - lphw_hpd->cb->attention(lphw_hpd->dev); - - return 0; -} - -int dp_lphw_hpd_register(struct dp_hpd *dp_hpd) -{ - struct dp_lphw_hpd_private *lphw_hpd; - int rc = 0; - - if (!dp_hpd) - return -EINVAL; - - lphw_hpd = container_of(dp_hpd, struct dp_lphw_hpd_private, base); - - lphw_hpd->hpd = gpio_get_value_cansleep(lphw_hpd->gpio_cfg.gpio); - - rc = devm_request_threaded_irq(lphw_hpd->dev, lphw_hpd->irq, NULL, - dp_tlmm_isr, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, - "dp-gpio-intp", lphw_hpd); - if (rc) { - pr_err("Failed to request INTP threaded IRQ: %d\n", rc); - return rc; - } - enable_irq_wake(lphw_hpd->irq); - - if (lphw_hpd->hpd) - queue_work(lphw_hpd->connect_wq, &lphw_hpd->connect); - - return rc; -} - -static void dp_lphw_hpd_deinit(struct dp_lphw_hpd_private *lphw_hpd) -{ - struct dp_parser *parser = lphw_hpd->parser; - int i = 0; - - for (i = 0; i < parser->mp[DP_PHY_PM].num_vreg; i++) { - - if (!strcmp(parser->mp[DP_PHY_PM].vreg_config[i].vreg_name, - "hpd-pwr")) { - /* disable the hpd-pwr voltage regulator */ - if (msm_dss_enable_vreg( - &parser->mp[DP_PHY_PM].vreg_config[i], 1, - false)) - pr_err("hpd-pwr vreg not disabled\n"); - - break; - } - } -} - -static void dp_lphw_hpd_init(struct dp_lphw_hpd_private *lphw_hpd) -{ - struct dp_pinctrl pinctrl = {0}; - struct dp_parser *parser = lphw_hpd->parser; - int i = 0, rc = 0; - - for (i = 0; i < parser->mp[DP_PHY_PM].num_vreg; i++) { - - if (!strcmp(parser->mp[DP_PHY_PM].vreg_config[i].vreg_name, - "hpd-pwr")) { - /* enable the hpd-pwr voltage regulator */ - if (msm_dss_enable_vreg( - &parser->mp[DP_PHY_PM].vreg_config[i], 1, - true)) - pr_err("hpd-pwr vreg not enabled\n"); - - break; - } - } - - pinctrl.pin = devm_pinctrl_get(lphw_hpd->dev); - - if (!IS_ERR_OR_NULL(pinctrl.pin)) { - pinctrl.state_hpd_active = pinctrl_lookup_state(pinctrl.pin, - "mdss_dp_hpd_active"); - - if (!IS_ERR_OR_NULL(pinctrl.state_hpd_active)) { - rc = pinctrl_select_state(pinctrl.pin, - pinctrl.state_hpd_active); - if (rc) - pr_err("failed to set hpd_active state\n"); - } - } -} - -static int dp_lphw_hpd_create_workqueue(struct dp_lphw_hpd_private *lphw_hpd) -{ - lphw_hpd->connect_wq = create_singlethread_workqueue("dp_lphw_work"); - if (IS_ERR_OR_NULL(lphw_hpd->connect_wq)) { - pr_err("Error creating connect_wq\n"); - return -EPERM; - } - - INIT_WORK(&lphw_hpd->connect, dp_lphw_hpd_connect); - INIT_WORK(&lphw_hpd->disconnect, dp_lphw_hpd_disconnect); - INIT_WORK(&lphw_hpd->attention, dp_lphw_hpd_attention); - - return 0; -} - -struct dp_hpd *dp_lphw_hpd_get(struct device *dev, struct dp_parser *parser, - struct dp_catalog_hpd *catalog, struct dp_hpd_cb *cb) -{ - int rc = 0; - const char *hpd_gpio_name = "qcom,dp-hpd-gpio"; - struct dp_lphw_hpd_private *lphw_hpd; - - if (!dev || !parser || !cb) { - pr_err("invalid device\n"); - rc = -EINVAL; - goto error; - } - - lphw_hpd = devm_kzalloc(dev, sizeof(*lphw_hpd), GFP_KERNEL); - if (!lphw_hpd) { - rc = -ENOMEM; - goto error; - } - - lphw_hpd->gpio_cfg.gpio = of_get_named_gpio(dev->of_node, - hpd_gpio_name, 0); - if (!gpio_is_valid(lphw_hpd->gpio_cfg.gpio)) { - pr_err("%s gpio not specified\n", hpd_gpio_name); - rc = -EINVAL; - goto gpio_error; - } - - strlcpy(lphw_hpd->gpio_cfg.gpio_name, hpd_gpio_name, - sizeof(lphw_hpd->gpio_cfg.gpio_name)); - lphw_hpd->gpio_cfg.value = 0; - - rc = gpio_request(lphw_hpd->gpio_cfg.gpio, - lphw_hpd->gpio_cfg.gpio_name); - if (rc) { - pr_err("%s: failed to request gpio\n", hpd_gpio_name); - goto gpio_error; - } - gpio_direction_input(lphw_hpd->gpio_cfg.gpio); - - lphw_hpd->dev = dev; - lphw_hpd->cb = cb; - lphw_hpd->irq = gpio_to_irq(lphw_hpd->gpio_cfg.gpio); - - rc = dp_lphw_hpd_create_workqueue(lphw_hpd); - if (rc) { - pr_err("Failed to create a dp_hpd workqueue\n"); - goto gpio_error; - } - - lphw_hpd->parser = parser; - lphw_hpd->catalog = catalog; - lphw_hpd->base.isr = dp_lphw_hpd_isr; - lphw_hpd->base.host_init = dp_lphw_hpd_host_init; - lphw_hpd->base.host_deinit = dp_lphw_hpd_host_deinit; - lphw_hpd->base.simulate_connect = dp_lphw_hpd_simulate_connect; - lphw_hpd->base.simulate_attention = dp_lphw_hpd_simulate_attention; - lphw_hpd->base.register_hpd = dp_lphw_hpd_register; - - dp_lphw_hpd_init(lphw_hpd); - - return &lphw_hpd->base; - -gpio_error: - devm_kfree(dev, lphw_hpd); -error: - return ERR_PTR(rc); -} - -void dp_lphw_hpd_put(struct dp_hpd *dp_hpd) -{ - struct dp_lphw_hpd_private *lphw_hpd; - - if (!dp_hpd) - return; - - lphw_hpd = container_of(dp_hpd, struct dp_lphw_hpd_private, base); - - dp_lphw_hpd_deinit(lphw_hpd); - gpio_free(lphw_hpd->gpio_cfg.gpio); - devm_kfree(lphw_hpd->dev, lphw_hpd); -} diff --git a/drivers/gpu/drm/msm/dp/dp_lphw_hpd.h b/drivers/gpu/drm/msm/dp/dp_lphw_hpd.h deleted file mode 100644 index 9779331bd295eefed4546746974369f7a167760e..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_lphw_hpd.h +++ /dev/null @@ -1,36 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. - */ - -#ifndef _DP_LPHW_HPD_H_ -#define _DP_LPHW_HPD_H_ - -#include "dp_hpd.h" - -#define DP_HPD_PLUG_INT_STATUS BIT(0) -#define DP_IRQ_HPD_INT_STATUS BIT(1) -#define DP_HPD_REPLUG_INT_STATUS BIT(2) -#define DP_HPD_UNPLUG_INT_STATUS BIT(3) - -/** - * dp_lphw_hpd_get() - configure and get the DisplayPlot HPD module data - * - * @dev: device instance of the caller - * return: pointer to allocated gpio hpd module data - * - * This function sets up the lphw hpd module - */ -struct dp_hpd *dp_lphw_hpd_get(struct device *dev, struct dp_parser *parser, - struct dp_catalog_hpd *catalog, struct dp_hpd_cb *cb); - -/** - * dp_lphw_hpd_put() - * - * Cleans up dp_hpd instance - * - * @hpd: instance of lphw_hpd - */ -void dp_lphw_hpd_put(struct dp_hpd *hpd); - -#endif /* _DP_LPHW_HPD_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.c b/drivers/gpu/drm/msm/dp/dp_mst_drm.c deleted file mode 100644 index 508c6dccdf7dce7848106c1cda220af02875fe84..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_mst_drm.c +++ /dev/null @@ -1,1992 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[drm-dp-mst]: %s: " fmt, __func__ - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "msm_drv.h" -#include "msm_kms.h" -#include "sde_connector.h" -#include "dp_drm.h" - -#define DP_MST_DEBUG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) -#define DP_MST_INFO_LOG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) - -#define MAX_DP_MST_DRM_ENCODERS 2 -#define MAX_DP_MST_DRM_BRIDGES 2 -#define HPD_STRING_SIZE 30 - -struct dp_drm_mst_fw_helper_ops { - int (*calc_pbn_mode)(struct dp_display_mode *dp_mode); - int (*find_vcpi_slots)(struct drm_dp_mst_topology_mgr *mgr, int pbn); - int (*atomic_find_vcpi_slots)(struct drm_atomic_state *state, - struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port, int pbn); - bool (*allocate_vcpi)(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port, - int pbn, int slots); - int (*update_payload_part1)(struct drm_dp_mst_topology_mgr *mgr); - int (*check_act_status)(struct drm_dp_mst_topology_mgr *mgr); - int (*update_payload_part2)(struct drm_dp_mst_topology_mgr *mgr); - enum drm_connector_status (*detect_port)( - struct drm_connector *connector, - struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port); - struct edid *(*get_edid)(struct drm_connector *connector, - struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port); - int (*topology_mgr_set_mst)(struct drm_dp_mst_topology_mgr *mgr, - bool mst_state); - int (*atomic_release_vcpi_slots)(struct drm_atomic_state *state, - struct drm_dp_mst_topology_mgr *mgr, - int slots); - void (*get_vcpi_info)(struct drm_dp_mst_topology_mgr *mgr, - int vcpi, int *start_slot, int *num_slots); - void (*reset_vcpi_slots)(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port); - void (*deallocate_vcpi)(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port); -}; - -struct dp_mst_sim_port_data { - bool input_port; - u8 peer_device_type; - u8 port_number; - bool mcs; - bool ddps; - bool legacy_device_plug_status; - u8 dpcd_revision; - u8 peer_guid[16]; - u8 num_sdp_streams; - u8 num_sdp_stream_sinks; -}; - -struct dp_mst_sim_mode { - bool mst_state; - struct edid *edid; - struct work_struct probe_work; - const struct drm_dp_mst_topology_cbs *cbs; - u32 port_cnt; -}; - -struct dp_mst_bridge { - struct drm_bridge base; - u32 id; - - bool in_use; - - struct dp_display *display; - struct drm_encoder *encoder; - bool encoder_active_sts; - - struct drm_display_mode drm_mode; - struct dp_display_mode dp_mode; - struct drm_connector *connector; - struct drm_connector *old_connector; - void *dp_panel; - void *old_dp_panel; - - int vcpi; - int pbn; - int num_slots; - int start_slot; - - u32 fixed_port_num; - bool fixed_port_added; - struct drm_connector *fixed_connector; -}; - -struct dp_mst_private { - bool mst_initialized; - struct dp_mst_caps caps; - struct drm_dp_mst_topology_mgr mst_mgr; - struct dp_mst_bridge mst_bridge[MAX_DP_MST_DRM_BRIDGES]; - struct dp_display *dp_display; - const struct dp_drm_mst_fw_helper_ops *mst_fw_cbs; - struct dp_mst_sim_mode simulator; - struct mutex mst_lock; - enum dp_drv_state state; - bool mst_session_state; -}; - -struct dp_mst_encoder_info_cache { - u8 cnt; - struct drm_encoder *mst_enc[MAX_DP_MST_DRM_BRIDGES]; -}; - -#define to_dp_mst_bridge(x) container_of((x), struct dp_mst_bridge, base) - -struct dp_mst_private dp_mst; -struct dp_mst_encoder_info_cache dp_mst_enc_cache; - -/* DRM DP MST Framework simulator OPs */ -static void dp_mst_sim_add_port(struct dp_mst_private *mst, - struct dp_mst_sim_port_data *port_msg) -{ - struct drm_dp_mst_branch *mstb; - struct drm_dp_mst_port *port; - - mstb = mst->mst_mgr.mst_primary; - - port = kzalloc(sizeof(*port), GFP_KERNEL); - if (!port) - return; - kref_init(&port->kref); - port->parent = mstb; - port->port_num = port_msg->port_number; - port->mgr = mstb->mgr; - port->aux.name = dp_mst.caps.drm_aux->name; - port->aux.dev = mst->dp_display->drm_dev->dev; - - port->pdt = port_msg->peer_device_type; - port->input = port_msg->input_port; - port->mcs = port_msg->mcs; - port->ddps = port_msg->ddps; - port->ldps = port_msg->legacy_device_plug_status; - port->dpcd_rev = port_msg->dpcd_revision; - port->num_sdp_streams = port_msg->num_sdp_streams; - port->num_sdp_stream_sinks = port_msg->num_sdp_stream_sinks; - - mutex_lock(&mstb->mgr->lock); - kref_get(&port->kref); - list_add(&port->next, &mstb->ports); - mutex_unlock(&mstb->mgr->lock); - - /* use fixed pbn for simulator ports */ - port->available_pbn = 2520; - - if (!port->input) { - port->connector = (*mstb->mgr->cbs->add_connector) - (mstb->mgr, port, NULL); - if (!port->connector) { - /* remove it from the port list */ - mutex_lock(&mstb->mgr->lock); - list_del(&port->next); - mutex_unlock(&mstb->mgr->lock); - goto put_port; - } - (*mstb->mgr->cbs->register_connector)(port->connector); - } - -put_port: - kref_put(&port->kref, NULL); -} - -static void dp_mst_sim_link_probe_work(struct work_struct *work) -{ - struct dp_mst_sim_mode *sim; - struct dp_mst_private *mst; - struct dp_mst_sim_port_data port_data; - u8 cnt; - - DP_MST_DEBUG("enter\n"); - sim = container_of(work, struct dp_mst_sim_mode, probe_work); - mst = container_of(sim, struct dp_mst_private, simulator); - - port_data.input_port = false; - port_data.peer_device_type = DP_PEER_DEVICE_SST_SINK; - port_data.mcs = false; - port_data.ddps = true; - port_data.legacy_device_plug_status = false; - port_data.dpcd_revision = 0; - port_data.num_sdp_streams = 0; - port_data.num_sdp_stream_sinks = 0; - - for (cnt = 0; cnt < sim->port_cnt; cnt++) { - port_data.port_number = cnt; - dp_mst_sim_add_port(mst, &port_data); - } - - mst->mst_mgr.cbs->hotplug(&mst->mst_mgr); - DP_MST_DEBUG("completed\n"); -} - -static int dp_mst_sim_no_action(struct drm_dp_mst_topology_mgr *mgr) -{ - return 0; -} - -static int dp_mst_sim_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) -{ - int i, j; - int cur_slots = 1; - struct drm_dp_payload req_payload; - struct drm_dp_mst_port *port; - - mutex_lock(&mgr->payload_lock); - for (i = 0; i < mgr->max_payloads; i++) { - req_payload.start_slot = cur_slots; - if (mgr->proposed_vcpis[i]) { - port = container_of(mgr->proposed_vcpis[i], - struct drm_dp_mst_port, vcpi); - req_payload.num_slots = - mgr->proposed_vcpis[i]->num_slots; - req_payload.vcpi = mgr->proposed_vcpis[i]->vcpi; - } else { - port = NULL; - req_payload.num_slots = 0; - } - - if (mgr->payloads[i].start_slot != req_payload.start_slot) - mgr->payloads[i].start_slot = req_payload.start_slot; - - if (mgr->payloads[i].num_slots != req_payload.num_slots) { - if (req_payload.num_slots) { - req_payload.payload_state = DP_PAYLOAD_LOCAL; - mgr->payloads[i].num_slots = - req_payload.num_slots; - mgr->payloads[i].vcpi = req_payload.vcpi; - } else if (mgr->payloads[i].num_slots) { - mgr->payloads[i].num_slots = 0; - mgr->payloads[i].payload_state = - DP_PAYLOAD_DELETE_LOCAL; - req_payload.payload_state = - mgr->payloads[i].payload_state; - mgr->payloads[i].start_slot = 0; - } else - req_payload.payload_state = - mgr->payloads[i].payload_state; - - mgr->payloads[i].payload_state = - req_payload.payload_state; - } - cur_slots += req_payload.num_slots; - } - - for (i = 0; i < mgr->max_payloads; i++) { - if (mgr->payloads[i].payload_state == DP_PAYLOAD_DELETE_LOCAL) { - pr_debug("removing payload %d\n", i); - for (j = i; j < mgr->max_payloads - 1; j++) { - memcpy(&mgr->payloads[j], - &mgr->payloads[j + 1], - sizeof(struct drm_dp_payload)); - mgr->proposed_vcpis[j] = - mgr->proposed_vcpis[j + 1]; - if (mgr->proposed_vcpis[j] && - mgr->proposed_vcpis[j]->num_slots) { - set_bit(j + 1, &mgr->payload_mask); - } else { - clear_bit(j + 1, &mgr->payload_mask); - } - } - memset(&mgr->payloads[mgr->max_payloads - 1], 0, - sizeof(struct drm_dp_payload)); - mgr->proposed_vcpis[mgr->max_payloads - 1] = NULL; - clear_bit(mgr->max_payloads, &mgr->payload_mask); - } - } - mutex_unlock(&mgr->payload_lock); - return 0; -} - -static int dp_mst_sim_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr) -{ - struct drm_dp_mst_port *port; - int i; - - mutex_lock(&mgr->payload_lock); - for (i = 0; i < mgr->max_payloads; i++) { - - if (!mgr->proposed_vcpis[i]) - continue; - - port = container_of(mgr->proposed_vcpis[i], - struct drm_dp_mst_port, vcpi); - - pr_debug("payload %d %d\n", i, mgr->payloads[i].payload_state); - if (mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL) - mgr->payloads[i].payload_state = DP_PAYLOAD_REMOTE; - else if (mgr->payloads[i].payload_state == - DP_PAYLOAD_DELETE_LOCAL) - mgr->payloads[i].payload_state = 0; - } - mutex_unlock(&mgr->payload_lock); - return 0; -} - -static struct edid *dp_mst_sim_get_edid(struct drm_connector *connector, - struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port) -{ - struct dp_mst_private *mst = container_of(mgr, - struct dp_mst_private, mst_mgr); - - return drm_edid_duplicate(mst->simulator.edid); -} - -static int dp_mst_sim_topology_mgr_set_mst( - struct drm_dp_mst_topology_mgr *mgr, - bool mst_state) -{ - struct dp_mst_private *mst = container_of(mgr, - struct dp_mst_private, mst_mgr); - - drm_dp_mst_topology_mgr_set_mst(mgr, mst_state); - if (mst_state) - queue_work(system_long_wq, &mst->simulator.probe_work); - - mst->simulator.mst_state = mst_state; - return 0; -} - -static void _dp_mst_get_vcpi_info( - struct drm_dp_mst_topology_mgr *mgr, - int vcpi, int *start_slot, int *num_slots) -{ - int i; - - *start_slot = 0; - *num_slots = 0; - - mutex_lock(&mgr->payload_lock); - for (i = 0; i < mgr->max_payloads; i++) { - if (mgr->payloads[i].vcpi == vcpi) { - *start_slot = mgr->payloads[i].start_slot; - *num_slots = mgr->payloads[i].num_slots; - break; - } - } - mutex_unlock(&mgr->payload_lock); - - pr_info("vcpi_info. vcpi:%d, start_slot:%d, num_slots:%d\n", - vcpi, *start_slot, *num_slots); -} - -static int dp_mst_calc_pbn_mode(struct dp_display_mode *dp_mode) -{ - int pbn, bpp; - bool dsc_en; - s64 pbn_fp; - - dsc_en = dp_mode->timing.comp_info.comp_ratio ? true : false; - bpp = dsc_en ? dp_mode->timing.comp_info.dsc_info.bpp : - dp_mode->timing.bpp; - - pbn = drm_dp_calc_pbn_mode(dp_mode->timing.pixel_clk_khz, bpp); - pbn_fp = drm_fixp_from_fraction(pbn, 1); - - pr_debug("before overhead pbn:%d, bpp:%d\n", pbn, bpp); - - if (dsc_en) - pbn_fp = drm_fixp_mul(pbn_fp, dp_mode->dsc_overhead_fp); - - if (dp_mode->fec_overhead_fp) - pbn_fp = drm_fixp_mul(pbn_fp, dp_mode->fec_overhead_fp); - - pbn = drm_fixp2int(pbn_fp); - - pr_debug("after overhead pbn:%d, bpp:%d\n", pbn, bpp); - return pbn; -} - -static const struct dp_drm_mst_fw_helper_ops drm_dp_mst_fw_helper_ops = { - .calc_pbn_mode = dp_mst_calc_pbn_mode, - .find_vcpi_slots = drm_dp_find_vcpi_slots, - .atomic_find_vcpi_slots = drm_dp_atomic_find_vcpi_slots, - .allocate_vcpi = drm_dp_mst_allocate_vcpi, - .update_payload_part1 = drm_dp_update_payload_part1, - .check_act_status = drm_dp_check_act_status, - .update_payload_part2 = drm_dp_update_payload_part2, - .detect_port = drm_dp_mst_detect_port, - .get_edid = drm_dp_mst_get_edid, - .topology_mgr_set_mst = drm_dp_mst_topology_mgr_set_mst, - .get_vcpi_info = _dp_mst_get_vcpi_info, - .atomic_release_vcpi_slots = drm_dp_atomic_release_vcpi_slots, - .reset_vcpi_slots = drm_dp_mst_reset_vcpi_slots, - .deallocate_vcpi = drm_dp_mst_deallocate_vcpi, -}; - -static const struct dp_drm_mst_fw_helper_ops drm_dp_sim_mst_fw_helper_ops = { - .calc_pbn_mode = dp_mst_calc_pbn_mode, - .find_vcpi_slots = drm_dp_find_vcpi_slots, - .atomic_find_vcpi_slots = drm_dp_atomic_find_vcpi_slots, - .allocate_vcpi = drm_dp_mst_allocate_vcpi, - .update_payload_part1 = dp_mst_sim_update_payload_part1, - .check_act_status = dp_mst_sim_no_action, - .update_payload_part2 = dp_mst_sim_update_payload_part2, - .detect_port = drm_dp_mst_detect_port, - .get_edid = dp_mst_sim_get_edid, - .topology_mgr_set_mst = dp_mst_sim_topology_mgr_set_mst, - .get_vcpi_info = _dp_mst_get_vcpi_info, - .atomic_release_vcpi_slots = drm_dp_atomic_release_vcpi_slots, - .reset_vcpi_slots = drm_dp_mst_reset_vcpi_slots, - .deallocate_vcpi = drm_dp_mst_deallocate_vcpi, -}; - -/* DP MST Bridge OPs */ - -static int dp_mst_bridge_attach(struct drm_bridge *dp_bridge) -{ - struct dp_mst_bridge *bridge; - - DP_MST_DEBUG("enter\n"); - - if (!dp_bridge) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - bridge = to_dp_mst_bridge(dp_bridge); - - DP_MST_DEBUG("mst bridge [%d] attached\n", bridge->id); - - return 0; -} - -static bool dp_mst_bridge_mode_fixup(struct drm_bridge *drm_bridge, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - bool ret = true; - struct dp_display_mode dp_mode; - struct dp_mst_bridge *bridge; - struct dp_display *dp; - - DP_MST_DEBUG("enter\n"); - - if (!drm_bridge || !mode || !adjusted_mode) { - pr_err("Invalid params\n"); - ret = false; - goto end; - } - - bridge = to_dp_mst_bridge(drm_bridge); - if (!bridge->connector) { - pr_err("Invalid connector\n"); - ret = false; - goto end; - } - - if (!bridge->dp_panel) { - pr_err("Invalid dp_panel\n"); - ret = false; - goto end; - } - - dp = bridge->display; - - dp->convert_to_dp_mode(dp, bridge->dp_panel, mode, &dp_mode); - convert_to_drm_mode(&dp_mode, adjusted_mode); - - DP_MST_DEBUG("mst bridge [%d] mode:%s fixup\n", bridge->id, mode->name); -end: - return ret; -} - -static int _dp_mst_compute_config(struct drm_atomic_state *state, - struct dp_mst_private *mst, struct drm_connector *connector, - struct dp_display_mode *mode) -{ - int slots = 0, pbn; - struct sde_connector *c_conn = to_sde_connector(connector); - int rc = 0; - - DP_MST_DEBUG("enter\n"); - - pbn = mst->mst_fw_cbs->calc_pbn_mode(mode); - - slots = mst->mst_fw_cbs->atomic_find_vcpi_slots(state, - &mst->mst_mgr, c_conn->mst_port, pbn); - if (slots < 0) { - pr_err("mst: failed to find vcpi slots. pbn:%d, slots:%d\n", - pbn, slots); - return slots; - } - - DP_MST_DEBUG("exit\n"); - - return rc; -} - -static void _dp_mst_update_timeslots(struct dp_mst_private *mst, - struct dp_mst_bridge *mst_bridge) -{ - int i; - struct dp_mst_bridge *dp_bridge; - int pbn, start_slot, num_slots; - - for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) { - dp_bridge = &mst->mst_bridge[i]; - - pbn = 0; - start_slot = 0; - num_slots = 0; - - if (dp_bridge->vcpi) { - mst->mst_fw_cbs->get_vcpi_info(&mst->mst_mgr, - dp_bridge->vcpi, - &start_slot, &num_slots); - pbn = dp_bridge->pbn; - } - - if (mst_bridge == dp_bridge) - dp_bridge->num_slots = num_slots; - - mst->dp_display->set_stream_info(mst->dp_display, - dp_bridge->dp_panel, - dp_bridge->id, start_slot, num_slots, pbn, - dp_bridge->vcpi); - - pr_info("bridge:%d vcpi:%d start_slot:%d num_slots:%d, pbn:%d\n", - dp_bridge->id, dp_bridge->vcpi, - start_slot, num_slots, pbn); - } -} - -static void _dp_mst_update_single_timeslot(struct dp_mst_private *mst, - struct dp_mst_bridge *mst_bridge) -{ - int pbn = 0, start_slot = 0, num_slots = 0; - - if (mst->state == PM_SUSPEND) { - if (mst_bridge->vcpi) { - mst->mst_fw_cbs->get_vcpi_info(&mst->mst_mgr, - mst_bridge->vcpi, - &start_slot, &num_slots); - pbn = mst_bridge->pbn; - } - - mst_bridge->num_slots = num_slots; - - mst->dp_display->set_stream_info(mst->dp_display, - mst_bridge->dp_panel, - mst_bridge->id, start_slot, num_slots, pbn, - mst_bridge->vcpi); - } -} - -static void _dp_mst_bridge_pre_enable_part1(struct dp_mst_bridge *dp_bridge) -{ - struct dp_display *dp_display = dp_bridge->display; - struct sde_connector *c_conn = - to_sde_connector(dp_bridge->connector); - struct dp_mst_private *mst = dp_display->dp_mst_prv_info; - struct drm_dp_mst_port *port = c_conn->mst_port; - bool ret; - int pbn, slots; - - /* skip mst specific disable operations during suspend */ - if (mst->state == PM_SUSPEND) { - _dp_mst_update_single_timeslot(mst, dp_bridge); - return; - } - - pbn = mst->mst_fw_cbs->calc_pbn_mode(&dp_bridge->dp_mode); - - slots = mst->mst_fw_cbs->find_vcpi_slots(&mst->mst_mgr, pbn); - - pr_info("bridge:%d, pbn:%d, slots:%d\n", dp_bridge->id, - dp_bridge->pbn, dp_bridge->num_slots); - - ret = mst->mst_fw_cbs->allocate_vcpi(&mst->mst_mgr, - port, pbn, slots); - if (!ret) { - pr_err("mst: failed to allocate vcpi. bridge:%d\n", - dp_bridge->id); - return; - } - - dp_bridge->vcpi = port->vcpi.vcpi; - dp_bridge->pbn = pbn; - - ret = mst->mst_fw_cbs->update_payload_part1(&mst->mst_mgr); - - _dp_mst_update_timeslots(mst, dp_bridge); -} - -static void _dp_mst_bridge_pre_enable_part2(struct dp_mst_bridge *dp_bridge) -{ - struct dp_display *dp_display = dp_bridge->display; - struct dp_mst_private *mst = dp_display->dp_mst_prv_info; - - DP_MST_DEBUG("enter\n"); - - /* skip mst specific disable operations during suspend */ - if (mst->state == PM_SUSPEND) - return; - - mst->mst_fw_cbs->check_act_status(&mst->mst_mgr); - - mst->mst_fw_cbs->update_payload_part2(&mst->mst_mgr); - - DP_MST_DEBUG("mst bridge [%d] _pre enable part-2 complete\n", - dp_bridge->id); -} - -static void _dp_mst_bridge_pre_disable_part1(struct dp_mst_bridge *dp_bridge) -{ - struct dp_display *dp_display = dp_bridge->display; - struct sde_connector *c_conn = - to_sde_connector(dp_bridge->connector); - struct dp_mst_private *mst = dp_display->dp_mst_prv_info; - struct drm_dp_mst_port *port = c_conn->mst_port; - - DP_MST_DEBUG("enter\n"); - - /* skip mst specific disable operations during suspend */ - if (mst->state == PM_SUSPEND) { - _dp_mst_update_single_timeslot(mst, dp_bridge); - return; - } - - mst->mst_fw_cbs->reset_vcpi_slots(&mst->mst_mgr, port); - - mst->mst_fw_cbs->update_payload_part1(&mst->mst_mgr); - - _dp_mst_update_timeslots(mst, dp_bridge); - - DP_MST_DEBUG("mst bridge [%d] _pre disable part-1 complete\n", - dp_bridge->id); -} - -static void _dp_mst_bridge_pre_disable_part2(struct dp_mst_bridge *dp_bridge) -{ - struct dp_display *dp_display = dp_bridge->display; - struct dp_mst_private *mst = dp_display->dp_mst_prv_info; - struct sde_connector *c_conn = - to_sde_connector(dp_bridge->connector); - struct drm_dp_mst_port *port = c_conn->mst_port; - - DP_MST_DEBUG("enter\n"); - - /* skip mst specific disable operations during suspend */ - if (mst->state == PM_SUSPEND) - return; - - mst->mst_fw_cbs->check_act_status(&mst->mst_mgr); - - mst->mst_fw_cbs->update_payload_part2(&mst->mst_mgr); - - mst->mst_fw_cbs->deallocate_vcpi(&mst->mst_mgr, port); - - dp_bridge->vcpi = 0; - dp_bridge->pbn = 0; - - DP_MST_DEBUG("mst bridge [%d] _pre disable part-2 complete\n", - dp_bridge->id); -} - -static void dp_mst_bridge_pre_enable(struct drm_bridge *drm_bridge) -{ - int rc = 0; - struct dp_mst_bridge *bridge; - struct dp_display *dp; - struct dp_mst_private *mst; - - if (!drm_bridge) { - pr_err("Invalid params\n"); - return; - } - - bridge = to_dp_mst_bridge(drm_bridge); - dp = bridge->display; - - bridge->old_connector = NULL; - bridge->old_dp_panel = NULL; - - if (!bridge->connector) { - pr_err("Invalid connector\n"); - return; - } - - mst = dp->dp_mst_prv_info; - - mutex_lock(&mst->mst_lock); - - /* By this point mode should have been validated through mode_fixup */ - rc = dp->set_mode(dp, bridge->dp_panel, &bridge->dp_mode); - if (rc) { - pr_err("[%d] failed to perform a mode set, rc=%d\n", - bridge->id, rc); - goto end; - } - - rc = dp->prepare(dp, bridge->dp_panel); - if (rc) { - pr_err("[%d] DP display prepare failed, rc=%d\n", - bridge->id, rc); - goto end; - } - - _dp_mst_bridge_pre_enable_part1(bridge); - - rc = dp->enable(dp, bridge->dp_panel); - if (rc) { - pr_err("[%d] DP display enable failed, rc=%d\n", - bridge->id, rc); - dp->unprepare(dp, bridge->dp_panel); - goto end; - } else { - _dp_mst_bridge_pre_enable_part2(bridge); - } - - DP_MST_INFO_LOG("mode: id(%d) mode(%s), refresh(%d)\n", - bridge->id, bridge->drm_mode.name, - bridge->drm_mode.vrefresh); - DP_MST_INFO_LOG("dsc: id(%d) dsc(%d)\n", bridge->id, - bridge->dp_mode.timing.comp_info.comp_ratio); - DP_MST_INFO_LOG("channel: id(%d) vcpi(%d) start(%d) tot(%d)\n", - bridge->id, bridge->vcpi, bridge->start_slot, - bridge->num_slots); -end: - mutex_unlock(&mst->mst_lock); -} - -static void dp_mst_bridge_enable(struct drm_bridge *drm_bridge) -{ - int rc = 0; - struct dp_mst_bridge *bridge; - struct dp_display *dp; - - if (!drm_bridge) { - pr_err("Invalid params\n"); - return; - } - - bridge = to_dp_mst_bridge(drm_bridge); - if (!bridge->connector) { - pr_err("Invalid connector\n"); - return; - } - - dp = bridge->display; - - rc = dp->post_enable(dp, bridge->dp_panel); - if (rc) { - pr_err("mst bridge [%d] post enable failed, rc=%d\n", - bridge->id, rc); - return; - } - - DP_MST_INFO_LOG("mst bridge [%d] post enable complete\n", - bridge->id); -} - -static void dp_mst_bridge_disable(struct drm_bridge *drm_bridge) -{ - int rc = 0; - struct dp_mst_bridge *bridge; - struct dp_display *dp; - struct dp_mst_private *mst; - - if (!drm_bridge) { - pr_err("Invalid params\n"); - return; - } - - bridge = to_dp_mst_bridge(drm_bridge); - if (!bridge->connector) { - pr_err("Invalid connector\n"); - return; - } - - dp = bridge->display; - - mst = dp->dp_mst_prv_info; - - sde_connector_helper_bridge_disable(bridge->connector); - - mutex_lock(&mst->mst_lock); - - _dp_mst_bridge_pre_disable_part1(bridge); - - rc = dp->pre_disable(dp, bridge->dp_panel); - if (rc) - pr_err("[%d] DP display pre disable failed, rc=%d\n", - bridge->id, rc); - - _dp_mst_bridge_pre_disable_part2(bridge); - - DP_MST_INFO_LOG("mst bridge [%d] disable complete\n", bridge->id); - - mutex_unlock(&mst->mst_lock); -} - -static void dp_mst_bridge_post_disable(struct drm_bridge *drm_bridge) -{ - int rc = 0; - struct dp_mst_bridge *bridge; - struct dp_display *dp; - struct dp_mst_private *mst; - - if (!drm_bridge) { - pr_err("Invalid params\n"); - return; - } - - bridge = to_dp_mst_bridge(drm_bridge); - if (!bridge->connector) { - pr_err("Invalid connector\n"); - return; - } - - dp = bridge->display; - mst = dp->dp_mst_prv_info; - - rc = dp->disable(dp, bridge->dp_panel); - if (rc) - pr_info("[%d] DP display disable failed, rc=%d\n", - bridge->id, rc); - - rc = dp->unprepare(dp, bridge->dp_panel); - if (rc) - pr_info("[%d] DP display unprepare failed, rc=%d\n", - bridge->id, rc); - - /* maintain the connector to encoder link during suspend/resume */ - if (mst->state != PM_SUSPEND) { - /* Disconnect the connector and panel info from bridge */ - mst->mst_bridge[bridge->id].old_connector = - mst->mst_bridge[bridge->id].connector; - mst->mst_bridge[bridge->id].old_dp_panel = - mst->mst_bridge[bridge->id].dp_panel; - mst->mst_bridge[bridge->id].connector = NULL; - mst->mst_bridge[bridge->id].dp_panel = NULL; - mst->mst_bridge[bridge->id].encoder_active_sts = false; - } - - DP_MST_INFO_LOG("mst bridge [%d] post disable complete\n", - bridge->id); -} - -static void dp_mst_bridge_mode_set(struct drm_bridge *drm_bridge, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct dp_mst_bridge *bridge; - struct dp_display *dp; - - DP_MST_DEBUG("enter\n"); - - if (!drm_bridge || !mode || !adjusted_mode) { - pr_err("Invalid params\n"); - return; - } - - bridge = to_dp_mst_bridge(drm_bridge); - if (!bridge->connector) { - if (!bridge->old_connector) { - pr_err("Invalid connector\n"); - return; - } - bridge->connector = bridge->old_connector; - bridge->old_connector = NULL; - } - - if (!bridge->dp_panel) { - if (!bridge->old_dp_panel) { - pr_err("Invalid dp_panel\n"); - return; - } - bridge->dp_panel = bridge->old_dp_panel; - bridge->old_dp_panel = NULL; - } - - dp = bridge->display; - - memset(&bridge->dp_mode, 0x0, sizeof(struct dp_display_mode)); - memcpy(&bridge->drm_mode, adjusted_mode, sizeof(bridge->drm_mode)); - dp->convert_to_dp_mode(dp, bridge->dp_panel, adjusted_mode, - &bridge->dp_mode); - - DP_MST_DEBUG("mst bridge [%d] mode set complete\n", bridge->id); -} - -/* DP MST Bridge APIs */ - -static struct drm_connector * -dp_mst_drm_fixed_connector_init(struct dp_display *dp_display, - struct drm_encoder *encoder); - -static const struct drm_bridge_funcs dp_mst_bridge_ops = { - .attach = dp_mst_bridge_attach, - .mode_fixup = dp_mst_bridge_mode_fixup, - .pre_enable = dp_mst_bridge_pre_enable, - .enable = dp_mst_bridge_enable, - .disable = dp_mst_bridge_disable, - .post_disable = dp_mst_bridge_post_disable, - .mode_set = dp_mst_bridge_mode_set, -}; - -int dp_mst_drm_bridge_init(void *data, struct drm_encoder *encoder) -{ - int rc = 0; - struct dp_mst_bridge *bridge = NULL; - struct drm_device *dev; - struct dp_display *display = data; - struct msm_drm_private *priv = NULL; - struct dp_mst_private *mst = display->dp_mst_prv_info; - int i; - - if (!mst || !mst->mst_initialized) { - if (dp_mst_enc_cache.cnt >= MAX_DP_MST_DRM_BRIDGES) { - pr_info("exceeding max bridge cnt %d\n", - dp_mst_enc_cache.cnt); - return 0; - } - - dp_mst_enc_cache.mst_enc[dp_mst_enc_cache.cnt] = encoder; - dp_mst_enc_cache.cnt++; - pr_info("mst not initialized. cache encoder information\n"); - return 0; - } - - for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) { - if (!mst->mst_bridge[i].in_use) { - bridge = &mst->mst_bridge[i]; - bridge->encoder = encoder; - bridge->in_use = true; - bridge->id = i; - break; - } - } - - if (i == MAX_DP_MST_DRM_BRIDGES) { - pr_err("mst supports only %d bridges\n", i); - rc = -EACCES; - goto end; - } - - dev = display->drm_dev; - bridge->display = display; - bridge->base.funcs = &dp_mst_bridge_ops; - bridge->base.encoder = encoder; - - priv = dev->dev_private; - - rc = drm_bridge_attach(encoder, &bridge->base, NULL); - if (rc) { - pr_err("failed to attach bridge, rc=%d\n", rc); - goto end; - } - - encoder->bridge = &bridge->base; - priv->bridges[priv->num_bridges++] = &bridge->base; - - DP_MST_DEBUG("mst drm bridge init. bridge id:%d\n", i); - - /* - * If fixed topology port is defined, connector will be created - * immediately. - */ - rc = display->mst_get_fixed_topology_port(display, bridge->id, - &bridge->fixed_port_num); - if (!rc) { - bridge->fixed_connector = - dp_mst_drm_fixed_connector_init(display, - bridge->encoder); - if (bridge->fixed_connector == NULL) { - pr_err("failed to create fixed connector\n"); - rc = -ENOMEM; - goto end; - } - } - - return 0; - -end: - return rc; -} - -void dp_mst_drm_bridge_deinit(void *display) -{ - DP_MST_DEBUG("mst bridge deinit\n"); -} - -/* DP MST Connector OPs */ - -static enum drm_connector_status -dp_mst_connector_detect(struct drm_connector *connector, bool force, - void *display) -{ - struct sde_connector *c_conn = to_sde_connector(connector); - struct dp_display *dp_display = c_conn->display; - struct dp_mst_private *mst = dp_display->dp_mst_prv_info; - enum drm_connector_status status; - struct dp_mst_connector mst_conn; - - DP_MST_DEBUG("enter:\n"); - - status = mst->mst_fw_cbs->detect_port(connector, - &mst->mst_mgr, - c_conn->mst_port); - - memset(&mst_conn, 0, sizeof(mst_conn)); - dp_display->mst_get_connector_info(dp_display, connector, &mst_conn); - if (mst_conn.conn == connector && - mst_conn.state != connector_status_unknown) { - status = mst_conn.state; - } - - DP_MST_DEBUG("mst connector:%d detect, status:%d\n", - connector->base.id, status); - - DP_MST_DEBUG("exit:\n"); - - return status; -} - -static int dp_mst_connector_get_modes(struct drm_connector *connector, - void *display) -{ - struct sde_connector *c_conn = to_sde_connector(connector); - struct dp_display *dp_display = display; - struct dp_mst_private *mst = dp_display->dp_mst_prv_info; - struct edid *edid; - int rc = 0; - - DP_MST_DEBUG("enter:\n"); - - edid = mst->mst_fw_cbs->get_edid(connector, &mst->mst_mgr, - c_conn->mst_port); - - if (edid) - rc = dp_display->mst_connector_update_edid(dp_display, - connector, edid); - - DP_MST_DEBUG("mst connector get modes. id: %d\n", connector->base.id); - - DP_MST_DEBUG("exit:\n"); - - return rc; -} - -enum drm_mode_status dp_mst_connector_mode_valid( - struct drm_connector *connector, - struct drm_display_mode *mode, - void *display) -{ - struct dp_display *dp_display = display; - struct dp_mst_private *mst; - struct sde_connector *c_conn; - struct drm_dp_mst_port *mst_port; - struct dp_display_mode dp_mode; - uint16_t available_pbn, required_pbn; - int i, slots_in_use = 0, active_enc_cnt = 0; - int available_slots, required_slots; - const u32 tot_slots = 63; - - if (!connector || !mode || !display) { - pr_err("invalid input\n"); - return 0; - } - - mst = dp_display->dp_mst_prv_info; - c_conn = to_sde_connector(connector); - mst_port = c_conn->mst_port; - - mutex_lock(&mst->mst_lock); - available_pbn = mst_port->available_pbn; - for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) { - if (mst->mst_bridge[i].encoder_active_sts && - (mst->mst_bridge[i].connector != connector)) { - active_enc_cnt++; - slots_in_use += mst->mst_bridge[i].num_slots; - } - } - mutex_unlock(&mst->mst_lock); - - if (active_enc_cnt < DP_STREAM_MAX) - available_slots = tot_slots - slots_in_use; - else { - pr_debug("all mst streams are active\n"); - return MODE_BAD; - } - - dp_display->convert_to_dp_mode(dp_display, c_conn->drv_panel, - mode, &dp_mode); - - required_pbn = mst->mst_fw_cbs->calc_pbn_mode(&dp_mode); - required_slots = mst->mst_fw_cbs->find_vcpi_slots( - &mst->mst_mgr, required_pbn); - - if (required_pbn > available_pbn || required_slots > available_slots) { - pr_debug("mode:%s not supported\n", mode->name); - return MODE_BAD; - } - - return dp_connector_mode_valid(connector, mode, display); -} - -int dp_mst_connector_get_info(struct drm_connector *connector, - struct msm_display_info *info, - void *display) -{ - int rc; - enum drm_connector_status status = connector_status_unknown; - - DP_MST_DEBUG("enter:\n"); - - rc = dp_connector_get_info(connector, info, display); - - if (!rc) { - status = dp_mst_connector_detect(connector, false, display); - - if (status == connector_status_connected) - info->is_connected = true; - else - info->is_connected = false; - } - - DP_MST_DEBUG("mst connector:%d get info:%d, rc:%d\n", - connector->base.id, status, rc); - - DP_MST_DEBUG("exit:\n"); - - return rc; -} - -int dp_mst_connector_get_mode_info(struct drm_connector *connector, - const struct drm_display_mode *drm_mode, - struct msm_mode_info *mode_info, - u32 max_mixer_width, void *display) -{ - int rc; - - DP_MST_DEBUG("enter:\n"); - - rc = dp_connector_get_mode_info(connector, drm_mode, mode_info, - max_mixer_width, display); - - DP_MST_DEBUG("mst connector:%d get mode info. rc:%d\n", - connector->base.id, rc); - - DP_MST_DEBUG("exit:\n"); - - return rc; -} - -static struct drm_encoder * -dp_mst_atomic_best_encoder(struct drm_connector *connector, - void *display, struct drm_connector_state *state) -{ - struct dp_display *dp_display = display; - struct dp_mst_private *mst = dp_display->dp_mst_prv_info; - struct sde_connector *conn = to_sde_connector(connector); - struct drm_encoder *enc = NULL; - u32 i; - - for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) { - if (mst->mst_bridge[i].connector == connector) { - enc = mst->mst_bridge[i].encoder; - goto end; - } - } - - for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) { - if (!mst->mst_bridge[i].encoder_active_sts && - !mst->mst_bridge[i].fixed_connector) { - mst->mst_bridge[i].encoder_active_sts = true; - mst->mst_bridge[i].connector = connector; - mst->mst_bridge[i].dp_panel = conn->drv_panel; - enc = mst->mst_bridge[i].encoder; - break; - } - } - -end: - if (enc) - DP_MST_DEBUG("mst connector:%d atomic best encoder:%d\n", - connector->base.id, i); - else - DP_MST_DEBUG("mst connector:%d atomic best encoder failed\n", - connector->base.id); - - return enc; -} - -static struct dp_mst_bridge *_dp_mst_get_bridge_from_encoder( - struct dp_display *dp_display, - struct drm_encoder *encoder) -{ - struct dp_mst_private *mst = dp_display->dp_mst_prv_info; - int i; - - for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) { - if (mst->mst_bridge[i].encoder == encoder) - return &mst->mst_bridge[i]; - } - - DP_MST_DEBUG("mst bridge detect for encoder failed\n"); - - return NULL; -} - -static int dp_mst_connector_atomic_check(struct drm_connector *connector, - void *display, struct drm_connector_state *new_conn_state) -{ - int rc = 0, slots, i; - struct drm_atomic_state *state; - struct drm_connector_state *old_conn_state; - struct drm_crtc *old_crtc; - struct drm_crtc_state *crtc_state; - struct dp_mst_bridge *bridge = NULL; - struct dp_display *dp_display = display; - struct dp_mst_private *mst = dp_display->dp_mst_prv_info; - struct sde_connector *c_conn; - struct dp_display_mode dp_mode; - - DP_MST_DEBUG("enter:\n"); - - /* - * Skip atomic check during mst suspend, to avoid mismanagement of - * available vcpi slots. - */ - if (mst->state == PM_SUSPEND) - return rc; - - if (!new_conn_state) - return rc; - - mutex_lock(&mst->mst_lock); - - state = new_conn_state->state; - - old_conn_state = drm_atomic_get_old_connector_state(state, connector); - if (!old_conn_state) - goto mode_set; - - old_crtc = old_conn_state->crtc; - if (!old_crtc) - goto mode_set; - - crtc_state = drm_atomic_get_new_crtc_state(state, old_crtc); - - for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) { - bridge = &mst->mst_bridge[i]; - DP_MST_DEBUG("bridge id:%d, vcpi:%d, pbn:%d, slots:%d\n", - bridge->id, bridge->vcpi, bridge->pbn, - bridge->num_slots); - } - - bridge = _dp_mst_get_bridge_from_encoder(dp_display, - old_conn_state->best_encoder); - if (!bridge) - goto end; - - slots = bridge->num_slots; - if (drm_atomic_crtc_needs_modeset(crtc_state) && slots > 0) { - rc = mst->mst_fw_cbs->atomic_release_vcpi_slots(state, - &mst->mst_mgr, slots); - if (rc) { - pr_err("failed releasing %d vcpi slots rc:%d\n", - slots, rc); - goto end; - } - } - -mode_set: - if (!new_conn_state->crtc) - goto end; - - crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); - - if (drm_atomic_crtc_needs_modeset(crtc_state)) { - c_conn = to_sde_connector(connector); - - dp_display->convert_to_dp_mode(dp_display, c_conn->drv_panel, - &crtc_state->mode, &dp_mode); - - slots = _dp_mst_compute_config(state, mst, connector, &dp_mode); - if (slots < 0) { - rc = slots; - - /* Disconnect the conn and panel info from bridge */ - bridge = _dp_mst_get_bridge_from_encoder(dp_display, - new_conn_state->best_encoder); - if (!bridge) - goto end; - - bridge->connector = NULL; - bridge->dp_panel = NULL; - bridge->encoder_active_sts = false; - } - } - -end: - mutex_unlock(&mst->mst_lock); - DP_MST_DEBUG("mst connector:%d atomic check\n", connector->base.id); - return rc; -} - -static int dp_mst_connector_config_hdr(struct drm_connector *connector, - void *display, struct sde_connector_state *c_state) -{ - int rc; - - DP_MST_DEBUG("enter:\n"); - - rc = dp_connector_config_hdr(connector, display, c_state); - - DP_MST_DEBUG("mst connector:%d cfg hdr. rc:%d\n", - connector->base.id, rc); - - DP_MST_DEBUG("exit:\n"); - - return rc; -} - -static void dp_mst_connector_pre_destroy(struct drm_connector *connector, - void *display) -{ - struct dp_display *dp_display = display; - - DP_MST_DEBUG("enter:\n"); - dp_display->mst_connector_uninstall(dp_display, connector); - DP_MST_DEBUG("exit:\n"); -} - -/* DRM MST callbacks */ - -static struct drm_connector * -dp_mst_add_connector(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port, const char *pathprop) -{ - static const struct sde_connector_ops dp_mst_connector_ops = { - .post_init = NULL, - .detect = dp_mst_connector_detect, - .get_modes = dp_mst_connector_get_modes, - .mode_valid = dp_mst_connector_mode_valid, - .get_info = dp_mst_connector_get_info, - .get_mode_info = dp_mst_connector_get_mode_info, - .atomic_best_encoder = dp_mst_atomic_best_encoder, - .atomic_check = dp_mst_connector_atomic_check, - .config_hdr = dp_mst_connector_config_hdr, - .pre_destroy = dp_mst_connector_pre_destroy, - .update_pps = dp_connector_update_pps, - }; - struct dp_mst_private *dp_mst; - struct drm_device *dev; - struct dp_display *dp_display; - struct drm_connector *connector; - struct sde_connector *c_conn; - int rc, i; - - DP_MST_DEBUG("enter\n"); - - dp_mst = container_of(mgr, struct dp_mst_private, mst_mgr); - - dp_display = dp_mst->dp_display; - dev = dp_display->drm_dev; - - /* make sure connector is not accessed before reset */ - drm_modeset_lock_all(dev); - - connector = sde_connector_init(dev, - dp_mst->mst_bridge[0].encoder, - NULL, - dp_display, - &dp_mst_connector_ops, - DRM_CONNECTOR_POLL_HPD, - DRM_MODE_CONNECTOR_DisplayPort); - - if (!connector) { - pr_err("mst sde_connector_init failed\n"); - drm_modeset_unlock_all(dev); - return connector; - } - - rc = dp_display->mst_connector_install(dp_display, connector); - if (rc) { - pr_err("mst connector install failed\n"); - sde_connector_destroy(connector); - drm_modeset_unlock_all(dev); - return NULL; - } - - c_conn = to_sde_connector(connector); - c_conn->mst_port = port; - - if (connector->funcs->reset) - connector->funcs->reset(connector); - - for (i = 1; i < MAX_DP_MST_DRM_BRIDGES; i++) { - drm_connector_attach_encoder(connector, - dp_mst->mst_bridge[i].encoder); - } - - drm_object_attach_property(&connector->base, - dev->mode_config.path_property, 0); - drm_object_attach_property(&connector->base, - dev->mode_config.tile_property, 0); - - /* unlock connector and make it accessible */ - drm_modeset_unlock_all(dev); - - DP_MST_INFO_LOG("add mst connector id:%d\n", connector->base.id); - - return connector; -} - -static void dp_mst_register_connector(struct drm_connector *connector) -{ - DP_MST_DEBUG("enter\n"); - - connector->status = connector->funcs->detect(connector, false); - - DP_MST_INFO_LOG("register mst connector id:%d\n", - connector->base.id); - drm_connector_register(connector); -} - -static void dp_mst_destroy_connector(struct drm_dp_mst_topology_mgr *mgr, - struct drm_connector *connector) -{ - DP_MST_DEBUG("enter\n"); - - DP_MST_INFO_LOG("destroy mst connector id:%d\n", connector->base.id); - - drm_connector_unregister(connector); - drm_connector_put(connector); -} - -static enum drm_connector_status -dp_mst_fixed_connector_detect(struct drm_connector *connector, bool force, - void *display) -{ - struct dp_display *dp_display = display; - struct dp_mst_private *mst = dp_display->dp_mst_prv_info; - int i; - - for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) { - if (mst->mst_bridge[i].fixed_connector != connector) - continue; - - if (!mst->mst_bridge[i].fixed_port_added) - break; - - return dp_mst_connector_detect(connector, force, display); - } - - return connector_status_disconnected; -} - -static struct drm_encoder * -dp_mst_fixed_atomic_best_encoder(struct drm_connector *connector, - void *display, struct drm_connector_state *state) -{ - struct dp_display *dp_display = display; - struct dp_mst_private *mst = dp_display->dp_mst_prv_info; - struct sde_connector *conn = to_sde_connector(connector); - struct drm_encoder *enc = NULL; - u32 i; - - for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) { - if (mst->mst_bridge[i].connector == connector) { - enc = mst->mst_bridge[i].encoder; - goto end; - } - } - - for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) { - if (mst->mst_bridge[i].fixed_connector == connector) { - mst->mst_bridge[i].encoder_active_sts = true; - mst->mst_bridge[i].connector = connector; - mst->mst_bridge[i].dp_panel = conn->drv_panel; - enc = mst->mst_bridge[i].encoder; - break; - } - } - -end: - if (enc) - DP_MST_DEBUG("mst connector:%d atomic best encoder:%d\n", - connector->base.id, i); - else - DP_MST_DEBUG("mst connector:%d atomic best encoder failed\n", - connector->base.id); - - return enc; -} - -static u32 dp_mst_find_fixed_port_num(struct drm_dp_mst_branch *mstb, - struct drm_dp_mst_port *target) -{ - struct drm_dp_mst_port *port; - u32 port_num = 0; - - /* - * search through reversed order of adding sequence, so the port number - * will be unique once topology is fixed - */ - list_for_each_entry_reverse(port, &mstb->ports, next) { - if (port->mstb) - port_num += dp_mst_find_fixed_port_num(port->mstb, - target); - else if (!port->input) { - ++port_num; - if (port == target) - break; - } - } - - return port_num; -} - -static struct drm_connector * -dp_mst_find_fixed_connector(struct dp_mst_private *dp_mst, - struct drm_dp_mst_port *port) -{ - struct dp_display *dp_display = dp_mst->dp_display; - struct drm_connector *connector = NULL; - struct sde_connector *c_conn; - u32 port_num; - int i; - - mutex_lock(&port->mgr->lock); - port_num = dp_mst_find_fixed_port_num(port->mgr->mst_primary, port); - mutex_unlock(&port->mgr->lock); - - if (!port_num) - return NULL; - - for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) { - if (dp_mst->mst_bridge[i].fixed_port_num == port_num) { - connector = dp_mst->mst_bridge[i].fixed_connector; - c_conn = to_sde_connector(connector); - c_conn->mst_port = port; - dp_display->mst_connector_update_link_info(dp_display, - connector); - dp_mst->mst_bridge[i].fixed_port_added = true; - DP_MST_DEBUG("found fixed connector %d\n", - DRMID(connector)); - break; - } - } - - return connector; -} - -static int -dp_mst_find_first_available_encoder_idx(struct dp_mst_private *dp_mst) -{ - int enc_idx = MAX_DP_MST_DRM_BRIDGES; - int i; - - for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) { - if (!dp_mst->mst_bridge[i].fixed_connector) { - enc_idx = i; - break; - } - } - - return enc_idx; -} - -static struct drm_connector * -dp_mst_add_fixed_connector(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port, const char *pathprop) -{ - struct dp_mst_private *dp_mst; - struct drm_device *dev; - struct dp_display *dp_display; - struct drm_connector *connector; - int i, enc_idx; - - DP_MST_DEBUG("enter\n"); - - dp_mst = container_of(mgr, struct dp_mst_private, mst_mgr); - - dp_display = dp_mst->dp_display; - dev = dp_display->drm_dev; - - if (port->input || port->mstb) - enc_idx = MAX_DP_MST_DRM_BRIDGES; - else { - /* if port is already reserved, return immediately */ - connector = dp_mst_find_fixed_connector(dp_mst, port); - if (connector != NULL) - return connector; - - /* first available bridge index for non-reserved port */ - enc_idx = dp_mst_find_first_available_encoder_idx(dp_mst); - } - - /* add normal connector */ - connector = dp_mst_add_connector(mgr, port, pathprop); - if (!connector) { - DP_MST_DEBUG("failed to add connector\n"); - return NULL; - } - - drm_modeset_lock_all(dev); - - /* clear encoder list */ - for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) - connector->encoder_ids[i] = 0; - - /* re-attach encoders from first available encoders */ - for (i = enc_idx; i < MAX_DP_MST_DRM_BRIDGES; i++) - drm_connector_attach_encoder(connector, - dp_mst->mst_bridge[i].encoder); - - drm_modeset_unlock_all(dev); - - DP_MST_DEBUG("add mst connector:%d\n", connector->base.id); - - return connector; -} - -static void dp_mst_register_fixed_connector(struct drm_connector *connector) -{ - struct sde_connector *c_conn = to_sde_connector(connector); - struct dp_display *dp_display = c_conn->display; - struct dp_mst_private *dp_mst = dp_display->dp_mst_prv_info; - int i; - - DP_MST_DEBUG("enter\n"); - - /* skip connector registered for fixed topology ports */ - for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) { - if (dp_mst->mst_bridge[i].fixed_connector == connector) { - DP_MST_DEBUG("found fixed connector %d\n", - DRMID(connector)); - return; - } - } - - dp_mst_register_connector(connector); -} - -static void dp_mst_destroy_fixed_connector(struct drm_dp_mst_topology_mgr *mgr, - struct drm_connector *connector) -{ - struct dp_mst_private *dp_mst; - int i; - - DP_MST_DEBUG("enter\n"); - - dp_mst = container_of(mgr, struct dp_mst_private, mst_mgr); - - /* skip connector destroy for fixed topology ports */ - for (i = 0; i < MAX_DP_MST_DRM_BRIDGES; i++) { - if (dp_mst->mst_bridge[i].fixed_connector == connector) { - dp_mst->mst_bridge[i].fixed_port_added = false; - DP_MST_DEBUG("destroy fixed connector %d\n", - DRMID(connector)); - return; - } - } - - dp_mst_destroy_connector(mgr, connector); -} - -static struct drm_connector * -dp_mst_drm_fixed_connector_init(struct dp_display *dp_display, - struct drm_encoder *encoder) -{ - static const struct sde_connector_ops dp_mst_connector_ops = { - .post_init = NULL, - .detect = dp_mst_fixed_connector_detect, - .get_modes = dp_mst_connector_get_modes, - .mode_valid = dp_mst_connector_mode_valid, - .get_info = dp_mst_connector_get_info, - .get_mode_info = dp_mst_connector_get_mode_info, - .atomic_best_encoder = dp_mst_fixed_atomic_best_encoder, - .atomic_check = dp_mst_connector_atomic_check, - .config_hdr = dp_mst_connector_config_hdr, - .pre_destroy = dp_mst_connector_pre_destroy, - }; - struct drm_device *dev; - struct drm_connector *connector; - int rc; - - DP_MST_DEBUG("enter\n"); - - dev = dp_display->drm_dev; - - connector = sde_connector_init(dev, - encoder, - NULL, - dp_display, - &dp_mst_connector_ops, - DRM_CONNECTOR_POLL_HPD, - DRM_MODE_CONNECTOR_DisplayPort); - - if (!connector) { - pr_err("mst sde_connector_init failed\n"); - return NULL; - } - - rc = dp_display->mst_connector_install(dp_display, connector); - if (rc) { - pr_err("mst connector install failed\n"); - sde_connector_destroy(connector); - return NULL; - } - - drm_object_attach_property(&connector->base, - dev->mode_config.path_property, 0); - drm_object_attach_property(&connector->base, - dev->mode_config.tile_property, 0); - - DP_MST_DEBUG("add mst fixed connector:%d\n", connector->base.id); - - return connector; -} - -static void dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) -{ - struct dp_mst_private *mst = container_of(mgr, struct dp_mst_private, - mst_mgr); - struct drm_device *dev = mst->dp_display->drm_dev; - char event_string[] = "MST_HOTPLUG=1"; - char *envp[2]; - - envp[0] = event_string; - envp[1] = NULL; - - kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp); - - DP_MST_INFO_LOG("mst hot plug event\n"); -} - -static void dp_mst_hpd_event_notify(struct dp_mst_private *mst, bool hpd_status) -{ - struct drm_device *dev = mst->dp_display->drm_dev; - char event_string[] = "MST_HOTPLUG=1"; - char status[HPD_STRING_SIZE]; - char *envp[3]; - - if (hpd_status) - snprintf(status, HPD_STRING_SIZE, "status=connected"); - else - snprintf(status, HPD_STRING_SIZE, "status=disconnected"); - - envp[0] = event_string; - envp[1] = status; - envp[2] = NULL; - - kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp); - - DP_MST_INFO_LOG("%s finished\n", __func__); -} - -/* DP Driver Callback OPs */ - -static void dp_mst_display_hpd(void *dp_display, bool hpd_status, - struct dp_mst_hpd_info *info) -{ - int rc; - struct dp_display *dp = dp_display; - struct dp_mst_private *mst = dp->dp_mst_prv_info; - - mutex_lock(&mst->mst_lock); - mst->mst_session_state = hpd_status; - mutex_unlock(&mst->mst_lock); - - if (!hpd_status) - rc = mst->mst_fw_cbs->topology_mgr_set_mst(&mst->mst_mgr, - hpd_status); - - if (info && !info->mst_protocol) { - if (hpd_status) { - mst->simulator.edid = (struct edid *)info->edid; - mst->simulator.port_cnt = info->mst_port_cnt; - } - mst->mst_fw_cbs = &drm_dp_sim_mst_fw_helper_ops; - } else { - mst->mst_fw_cbs = &drm_dp_mst_fw_helper_ops; - } - - if (hpd_status) - rc = mst->mst_fw_cbs->topology_mgr_set_mst(&mst->mst_mgr, - hpd_status); - - dp_mst_hpd_event_notify(mst, hpd_status); - - DP_MST_INFO_LOG("mst display hpd:%d, rc:%d\n", hpd_status, rc); -} - -static void dp_mst_display_hpd_irq(void *dp_display, - struct dp_mst_hpd_info *info) -{ - int rc; - struct dp_display *dp = dp_display; - struct dp_mst_private *mst = dp->dp_mst_prv_info; - u8 esi[14]; - unsigned int esi_res = DP_SINK_COUNT_ESI + 1; - bool handled; - - if (info->mst_hpd_sim) { - dp_mst_hotplug(&mst->mst_mgr); - return; - } - - if (!mst->mst_session_state) { - pr_err("mst_hpd_irq received before mst session start\n"); - return; - } - - rc = drm_dp_dpcd_read(mst->caps.drm_aux, DP_SINK_COUNT_ESI, - esi, 14); - if (rc != 14) { - pr_err("dpcd sink status read failed, rlen=%d\n", rc); - return; - } - - DP_MST_DEBUG("mst irq: esi1[0x%x] esi2[0x%x] esi3[%x]\n", - esi[1], esi[2], esi[3]); - - rc = drm_dp_mst_hpd_irq(&mst->mst_mgr, esi, &handled); - - /* ack the request */ - if (handled) { - rc = drm_dp_dpcd_write(mst->caps.drm_aux, esi_res, &esi[1], 3); - - if (rc != 3) - pr_err("dpcd esi_res failed. rlen=%d\n", rc); - } - - DP_MST_DEBUG("mst display hpd_irq handled:%d rc:%d\n", handled, rc); -} - -static void dp_mst_set_state(void *dp_display, enum dp_drv_state mst_state) -{ - struct dp_display *dp = dp_display; - struct dp_mst_private *mst = dp->dp_mst_prv_info; - - if (!mst) { - pr_debug("mst not initialized\n"); - return; - } - - mst->state = mst_state; - DP_MST_INFO_LOG("mst power state:%d\n", mst_state); -} - -/* DP MST APIs */ - -static const struct dp_mst_drm_cbs dp_mst_display_cbs = { - .hpd = dp_mst_display_hpd, - .hpd_irq = dp_mst_display_hpd_irq, - .set_drv_state = dp_mst_set_state, -}; - -static const struct drm_dp_mst_topology_cbs dp_mst_drm_cbs = { - .add_connector = dp_mst_add_connector, - .register_connector = dp_mst_register_connector, - .destroy_connector = dp_mst_destroy_connector, - .hotplug = dp_mst_hotplug, -}; - -static const struct drm_dp_mst_topology_cbs dp_mst_fixed_drm_cbs = { - .add_connector = dp_mst_add_fixed_connector, - .register_connector = dp_mst_register_fixed_connector, - .destroy_connector = dp_mst_destroy_fixed_connector, - .hotplug = dp_mst_hotplug, -}; - -static void dp_mst_sim_init(struct dp_mst_private *mst) -{ - INIT_WORK(&mst->simulator.probe_work, dp_mst_sim_link_probe_work); - mst->simulator.cbs = &dp_mst_drm_cbs; -} - -int dp_mst_init(struct dp_display *dp_display) -{ - struct drm_device *dev; - int conn_base_id = 0; - int ret, i; - struct dp_mst_drm_install_info install_info; - - memset(&dp_mst, 0, sizeof(dp_mst)); - - if (!dp_display) { - pr_err("invalid params\n"); - return 0; - } - - dev = dp_display->drm_dev; - - /* register with DP driver */ - install_info.dp_mst_prv_info = &dp_mst; - install_info.cbs = &dp_mst_display_cbs; - dp_display->mst_install(dp_display, &install_info); - - dp_display->get_mst_caps(dp_display, &dp_mst.caps); - - if (!dp_mst.caps.has_mst) { - DP_MST_DEBUG("mst not supported\n"); - return 0; - } - - dp_mst.mst_fw_cbs = &drm_dp_mst_fw_helper_ops; - - memset(&dp_mst.mst_mgr, 0, sizeof(dp_mst.mst_mgr)); - dp_mst.mst_mgr.cbs = &dp_mst_drm_cbs; - conn_base_id = dp_display->base_connector->base.id; - dp_mst.dp_display = dp_display; - - mutex_init(&dp_mst.mst_lock); - - ret = drm_dp_mst_topology_mgr_init(&dp_mst.mst_mgr, dev, - dp_mst.caps.drm_aux, - dp_mst.caps.max_dpcd_transaction_bytes, - dp_mst.caps.max_streams_supported, - conn_base_id); - if (ret) { - pr_err("dp drm mst topology manager init failed\n"); - goto error; - } - - dp_mst_sim_init(&dp_mst); - - dp_mst.mst_initialized = true; - - /* create drm_bridges for cached mst encoders and clear cache */ - for (i = 0; i < dp_mst_enc_cache.cnt; i++) { - ret = dp_mst_drm_bridge_init(dp_display, - dp_mst_enc_cache.mst_enc[i]); - } - memset(&dp_mst_enc_cache, 0, sizeof(dp_mst_enc_cache)); - - /* choose fixed callback function if fixed topology is found */ - if (!dp_display->mst_get_fixed_topology_port(dp_display, 0, NULL)) - dp_mst.mst_mgr.cbs = &dp_mst_fixed_drm_cbs; - - DP_MST_INFO_LOG("dp drm mst topology manager init completed\n"); - - return ret; - -error: - mutex_destroy(&dp_mst.mst_lock); - return ret; -} - -void dp_mst_deinit(struct dp_display *dp_display) -{ - struct dp_mst_private *mst; - - if (!dp_display) { - pr_err("invalid params\n"); - return; - } - - mst = dp_display->dp_mst_prv_info; - - if (!mst->mst_initialized) - return; - - dp_display->mst_uninstall(dp_display); - - drm_dp_mst_topology_mgr_destroy(&mst->mst_mgr); - - dp_mst.mst_initialized = false; - - mutex_destroy(&mst->mst_lock); - - DP_MST_INFO_LOG("dp drm mst topology manager deinit completed\n"); -} - diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c deleted file mode 100644 index 2862ca59ff417df9ba4c6223944d0d66fc1a6bd4..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ /dev/null @@ -1,3004 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ - -#include "dp_panel.h" -#include - -#define DP_KHZ_TO_HZ 1000 -#define DP_PANEL_DEFAULT_BPP 24 -#define DP_MAX_DS_PORT_COUNT 1 - -#define DPRX_FEATURE_ENUMERATION_LIST 0x2210 -#define DPRX_EXTENDED_DPCD_FIELD 0x2200 -#define VSC_SDP_EXTENSION_FOR_COLORIMETRY_SUPPORTED BIT(3) -#define VSC_EXT_VESA_SDP_SUPPORTED BIT(4) -#define VSC_EXT_VESA_SDP_CHAINING_SUPPORTED BIT(5) - -enum dp_panel_hdr_pixel_encoding { - RGB, - YCbCr444, - YCbCr422, - YCbCr420, - YONLY, - RAW, -}; - -enum dp_panel_hdr_rgb_colorimetry { - sRGB, - RGB_WIDE_GAMUT_FIXED_POINT, - RGB_WIDE_GAMUT_FLOATING_POINT, - ADOBERGB, - DCI_P3, - CUSTOM_COLOR_PROFILE, - ITU_R_BT_2020_RGB, -}; - -enum dp_panel_hdr_dynamic_range { - VESA, - CEA, -}; - -enum dp_panel_hdr_content_type { - NOT_DEFINED, - GRAPHICS, - PHOTO, - VIDEO, - GAME, -}; - -enum dp_panel_hdr_state { - HDR_DISABLED, - HDR_ENABLED, -}; - -struct dp_panel_private { - struct device *dev; - struct dp_panel dp_panel; - struct dp_aux *aux; - struct dp_link *link; - struct dp_parser *parser; - struct dp_catalog_panel *catalog; - bool custom_edid; - bool custom_dpcd; - bool panel_on; - bool vsc_supported; - bool vscext_supported; - bool vscext_chaining_supported; - enum dp_panel_hdr_state hdr_state; - u8 spd_vendor_name[8]; - u8 spd_product_description[16]; - u8 major; - u8 minor; -}; - -static const struct dp_panel_info fail_safe = { - .h_active = 640, - .v_active = 480, - .h_back_porch = 48, - .h_front_porch = 16, - .h_sync_width = 96, - .h_active_low = 0, - .v_back_porch = 33, - .v_front_porch = 10, - .v_sync_width = 2, - .v_active_low = 0, - .h_skew = 0, - .refresh_rate = 60, - .pixel_clk_khz = 25200, - .bpp = 24, -}; - -/* OEM NAME */ -static const u8 vendor_name[8] = {81, 117, 97, 108, 99, 111, 109, 109}; - -/* MODEL NAME */ -static const u8 product_desc[16] = {83, 110, 97, 112, 100, 114, 97, 103, - 111, 110, 0, 0, 0, 0, 0, 0}; - -struct dp_dhdr_maxpkt_calc_input { - u32 mdp_clk; - u32 lclk; - u32 pclk; - u32 h_active; - u32 nlanes; - s64 mst_target_sc; - bool mst_en; - bool fec_en; -}; - -struct tu_algo_data { - s64 lclk_fp; - s64 pclk_fp; - s64 lwidth; - s64 lwidth_fp; - s64 hbp_relative_to_pclk; - s64 hbp_relative_to_pclk_fp; - int nlanes; - int bpp; - int pixelEnc; - int dsc_en; - int async_en; - int bpc; - - uint delay_start_link_extra_pixclk; - int extra_buffer_margin; - s64 ratio_fp; - s64 original_ratio_fp; - - s64 err_fp; - s64 n_err_fp; - s64 n_n_err_fp; - int tu_size; - int tu_size_desired; - int tu_size_minus1; - - int valid_boundary_link; - s64 resulting_valid_fp; - s64 total_valid_fp; - s64 effective_valid_fp; - s64 effective_valid_recorded_fp; - int n_tus; - int n_tus_per_lane; - int paired_tus; - int remainder_tus; - int remainder_tus_upper; - int remainder_tus_lower; - int extra_bytes; - int filler_size; - int delay_start_link; - - int extra_pclk_cycles; - int extra_pclk_cycles_in_link_clk; - s64 ratio_by_tu_fp; - s64 average_valid2_fp; - int new_valid_boundary_link; - int remainder_symbols_exist; - int n_symbols; - s64 n_remainder_symbols_per_lane_fp; - s64 last_partial_tu_fp; - s64 TU_ratio_err_fp; - - int n_tus_incl_last_incomplete_tu; - int extra_pclk_cycles_tmp; - int extra_pclk_cycles_in_link_clk_tmp; - int extra_required_bytes_new_tmp; - int filler_size_tmp; - int lower_filler_size_tmp; - int delay_start_link_tmp; - - bool boundary_moderation_en; - int boundary_mod_lower_err; - int upper_boundary_count; - int lower_boundary_count; - int i_upper_boundary_count; - int i_lower_boundary_count; - int valid_lower_boundary_link; - int even_distribution_BF; - int even_distribution_legacy; - int even_distribution; - int min_hblank_violated; - s64 delay_start_time_fp; - s64 hbp_time_fp; - s64 hactive_time_fp; - s64 diff_abs_fp; - - s64 ratio; -}; - -static int _tu_param_compare(s64 a, s64 b) -{ - u32 a_int, a_frac, a_sign; - u32 b_int, b_frac, b_sign; - s64 a_temp, b_temp, minus_1; - - if (a == b) - return 0; - - minus_1 = drm_fixp_from_fraction(-1, 1); - - a_int = (a >> 32) & 0x7FFFFFFF; - a_frac = a & 0xFFFFFFFF; - a_sign = (a >> 32) & 0x80000000 ? 1 : 0; - - b_int = (b >> 32) & 0x7FFFFFFF; - b_frac = b & 0xFFFFFFFF; - b_sign = (b >> 32) & 0x80000000 ? 1 : 0; - - if (a_sign > b_sign) - return 2; - else if (b_sign > a_sign) - return 1; - - if (!a_sign && !b_sign) { /* positive */ - if (a > b) - return 1; - else - return 2; - } else { /* negative */ - a_temp = drm_fixp_mul(a, minus_1); - b_temp = drm_fixp_mul(b, minus_1); - - if (a_temp > b_temp) - return 2; - else - return 1; - } -} - -static void dp_panel_update_tu_timings(struct dp_tu_calc_input *in, - struct tu_algo_data *tu) -{ - int nlanes = in->nlanes; - int dsc_num_slices = in->num_of_dsc_slices; - int dsc_num_bytes = 0; - int numerator; - s64 pclk_dsc_fp; - s64 dwidth_dsc_fp; - s64 hbp_dsc_fp; - s64 overhead_dsc; - - int tot_num_eoc_symbols = 0; - int tot_num_hor_bytes = 0; - int tot_num_dummy_bytes = 0; - int dwidth_dsc_bytes = 0; - int eoc_bytes = 0; - - s64 temp1_fp, temp2_fp, temp3_fp; - - tu->lclk_fp = drm_fixp_from_fraction(in->lclk, 1); - tu->pclk_fp = drm_fixp_from_fraction(in->pclk_khz, 1000); - tu->lwidth = in->hactive; - tu->hbp_relative_to_pclk = in->hporch; - tu->nlanes = in->nlanes; - tu->bpp = in->bpp; - tu->pixelEnc = in->pixel_enc; - tu->dsc_en = in->dsc_en; - tu->async_en = in->async_en; - tu->lwidth_fp = drm_fixp_from_fraction(in->hactive, 1); - tu->hbp_relative_to_pclk_fp = drm_fixp_from_fraction(in->hporch, 1); - - if (tu->pixelEnc == 420) { - temp1_fp = drm_fixp_from_fraction(2, 1); - tu->pclk_fp = drm_fixp_div(tu->pclk_fp, temp1_fp); - tu->lwidth_fp = drm_fixp_div(tu->lwidth_fp, temp1_fp); - tu->hbp_relative_to_pclk_fp = - drm_fixp_div(tu->hbp_relative_to_pclk_fp, 2); - } - - if (tu->pixelEnc == 422) { - switch (tu->bpp) { - case 24: - tu->bpp = 16; - tu->bpc = 8; - break; - case 30: - tu->bpp = 20; - tu->bpc = 10; - break; - default: - tu->bpp = 16; - tu->bpc = 8; - break; - } - } else - tu->bpc = tu->bpp/3; - - if (!in->dsc_en) - goto fec_check; - - temp1_fp = drm_fixp_from_fraction(in->compress_ratio, 100); - temp2_fp = drm_fixp_from_fraction(in->bpp, 1); - temp3_fp = drm_fixp_div(temp2_fp, temp1_fp); - temp2_fp = drm_fixp_mul(tu->lwidth_fp, temp3_fp); - - temp1_fp = drm_fixp_from_fraction(8, 1); - temp3_fp = drm_fixp_div(temp2_fp, temp1_fp); - - numerator = drm_fixp2int(temp3_fp); - - dsc_num_bytes = numerator / dsc_num_slices; - eoc_bytes = dsc_num_bytes % nlanes; - tot_num_eoc_symbols = nlanes * dsc_num_slices; - tot_num_hor_bytes = dsc_num_bytes * dsc_num_slices; - tot_num_dummy_bytes = (nlanes - eoc_bytes) * dsc_num_slices; - - if (dsc_num_bytes == 0) - pr_info("incorrect no of bytes per slice=%d\n", dsc_num_bytes); - - dwidth_dsc_bytes = (tot_num_hor_bytes + - tot_num_eoc_symbols + - (eoc_bytes == 0 ? 0 : tot_num_dummy_bytes)); - overhead_dsc = dwidth_dsc_bytes / tot_num_hor_bytes; - - dwidth_dsc_fp = drm_fixp_from_fraction(dwidth_dsc_bytes, 3); - - temp2_fp = drm_fixp_mul(tu->pclk_fp, dwidth_dsc_fp); - temp1_fp = drm_fixp_div(temp2_fp, tu->lwidth_fp); - pclk_dsc_fp = temp1_fp; - - temp1_fp = drm_fixp_div(pclk_dsc_fp, tu->pclk_fp); - temp2_fp = drm_fixp_mul(tu->hbp_relative_to_pclk_fp, temp1_fp); - hbp_dsc_fp = temp2_fp; - - /* output */ - tu->pclk_fp = pclk_dsc_fp; - tu->lwidth_fp = dwidth_dsc_fp; - tu->hbp_relative_to_pclk_fp = hbp_dsc_fp; - -fec_check: - if (in->fec_en) { - temp1_fp = drm_fixp_from_fraction(976, 1000); /* 0.976 */ - tu->lclk_fp = drm_fixp_mul(tu->lclk_fp, temp1_fp); - } -} - -static void _tu_valid_boundary_calc(struct tu_algo_data *tu) -{ - s64 temp1_fp, temp2_fp, temp, temp1, temp2; - int compare_result_1, compare_result_2, compare_result_3; - - temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1); - temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp); - - tu->new_valid_boundary_link = drm_fixp2int_ceil(temp2_fp); - - temp = (tu->i_upper_boundary_count * - tu->new_valid_boundary_link + - tu->i_lower_boundary_count * - (tu->new_valid_boundary_link-1)); - tu->average_valid2_fp = drm_fixp_from_fraction(temp, - (tu->i_upper_boundary_count + - tu->i_lower_boundary_count)); - - temp1_fp = drm_fixp_from_fraction(tu->bpp, 8); - temp2_fp = tu->lwidth_fp; - temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp); - temp2_fp = drm_fixp_div(temp1_fp, tu->average_valid2_fp); - tu->n_tus = drm_fixp2int(temp2_fp); - if ((temp2_fp & 0xFFFFFFFF) > 0xFFFFF000) - tu->n_tus += 1; - - temp1_fp = drm_fixp_from_fraction(tu->n_tus, 1); - temp2_fp = drm_fixp_mul(temp1_fp, tu->average_valid2_fp); - temp1_fp = drm_fixp_from_fraction(tu->n_symbols, 1); - temp2_fp = temp1_fp - temp2_fp; - temp1_fp = drm_fixp_from_fraction(tu->nlanes, 1); - temp2_fp = drm_fixp_div(temp2_fp, temp1_fp); - tu->n_remainder_symbols_per_lane_fp = temp2_fp; - - temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1); - tu->last_partial_tu_fp = - drm_fixp_div(tu->n_remainder_symbols_per_lane_fp, - temp1_fp); - - if (tu->n_remainder_symbols_per_lane_fp != 0) - tu->remainder_symbols_exist = 1; - else - tu->remainder_symbols_exist = 0; - - temp1_fp = drm_fixp_from_fraction(tu->n_tus, tu->nlanes); - tu->n_tus_per_lane = drm_fixp2int(temp1_fp); - - tu->paired_tus = (int)((tu->n_tus_per_lane) / - (tu->i_upper_boundary_count + - tu->i_lower_boundary_count)); - - tu->remainder_tus = tu->n_tus_per_lane - tu->paired_tus * - (tu->i_upper_boundary_count + - tu->i_lower_boundary_count); - - if ((tu->remainder_tus - tu->i_upper_boundary_count) > 0) { - tu->remainder_tus_upper = tu->i_upper_boundary_count; - tu->remainder_tus_lower = tu->remainder_tus - - tu->i_upper_boundary_count; - } else { - tu->remainder_tus_upper = tu->remainder_tus; - tu->remainder_tus_lower = 0; - } - - temp = tu->paired_tus * (tu->i_upper_boundary_count * - tu->new_valid_boundary_link + - tu->i_lower_boundary_count * - (tu->new_valid_boundary_link - 1)) + - (tu->remainder_tus_upper * - tu->new_valid_boundary_link) + - (tu->remainder_tus_lower * - (tu->new_valid_boundary_link - 1)); - tu->total_valid_fp = drm_fixp_from_fraction(temp, 1); - - if (tu->remainder_symbols_exist) { - temp1_fp = tu->total_valid_fp + - tu->n_remainder_symbols_per_lane_fp; - temp2_fp = drm_fixp_from_fraction(tu->n_tus_per_lane, 1); - temp2_fp = temp2_fp + tu->last_partial_tu_fp; - temp1_fp = drm_fixp_div(temp1_fp, temp2_fp); - } else { - temp2_fp = drm_fixp_from_fraction(tu->n_tus_per_lane, 1); - temp1_fp = drm_fixp_div(tu->total_valid_fp, temp2_fp); - } - tu->effective_valid_fp = temp1_fp; - - temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1); - temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp); - tu->n_n_err_fp = tu->effective_valid_fp - temp2_fp; - - temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1); - temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp); - tu->n_err_fp = tu->average_valid2_fp - temp2_fp; - - tu->even_distribution = tu->n_tus % tu->nlanes == 0 ? 1 : 0; - - temp1_fp = drm_fixp_from_fraction(tu->bpp, 8); - temp2_fp = tu->lwidth_fp; - temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp); - temp2_fp = drm_fixp_div(temp1_fp, tu->average_valid2_fp); - - if (temp2_fp) - tu->n_tus_incl_last_incomplete_tu = drm_fixp2int_ceil(temp2_fp); - else - tu->n_tus_incl_last_incomplete_tu = 0; - - temp1 = 0; - temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1); - temp2_fp = drm_fixp_mul(tu->original_ratio_fp, temp1_fp); - temp1_fp = tu->average_valid2_fp - temp2_fp; - temp2_fp = drm_fixp_from_fraction(tu->n_tus_incl_last_incomplete_tu, 1); - temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp); - - if (temp1_fp) - temp1 = drm_fixp2int_ceil(temp1_fp); - - temp = tu->i_upper_boundary_count * tu->nlanes; - temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1); - temp2_fp = drm_fixp_mul(tu->original_ratio_fp, temp1_fp); - temp1_fp = drm_fixp_from_fraction(tu->new_valid_boundary_link, 1); - temp2_fp = temp1_fp - temp2_fp; - temp1_fp = drm_fixp_from_fraction(temp, 1); - temp2_fp = drm_fixp_mul(temp1_fp, temp2_fp); - - if (temp2_fp) - temp2 = drm_fixp2int_ceil(temp2_fp); - else - temp2 = 0; - tu->extra_required_bytes_new_tmp = (int)(temp1 + temp2); - - temp1_fp = drm_fixp_from_fraction(8, tu->bpp); - temp2_fp = drm_fixp_from_fraction( - tu->extra_required_bytes_new_tmp, 1); - temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp); - - if (temp1_fp) - tu->extra_pclk_cycles_tmp = drm_fixp2int_ceil(temp1_fp); - else - tu->extra_pclk_cycles_tmp = 0; - - temp1_fp = drm_fixp_from_fraction(tu->extra_pclk_cycles_tmp, 1); - temp2_fp = drm_fixp_div(tu->lclk_fp, tu->pclk_fp); - temp1_fp = drm_fixp_mul(temp1_fp, temp2_fp); - - if (temp1_fp) - tu->extra_pclk_cycles_in_link_clk_tmp = - drm_fixp2int_ceil(temp1_fp); - else - tu->extra_pclk_cycles_in_link_clk_tmp = 0; - - tu->filler_size_tmp = tu->tu_size - tu->new_valid_boundary_link; - - tu->lower_filler_size_tmp = tu->filler_size_tmp + 1; - - tu->delay_start_link_tmp = tu->extra_pclk_cycles_in_link_clk_tmp + - tu->lower_filler_size_tmp + - tu->extra_buffer_margin; - - temp1_fp = drm_fixp_from_fraction(tu->delay_start_link_tmp, 1); - tu->delay_start_time_fp = drm_fixp_div(temp1_fp, tu->lclk_fp); - - compare_result_1 = _tu_param_compare(tu->n_n_err_fp, tu->diff_abs_fp); - if (compare_result_1 == 2) - compare_result_1 = 1; - else - compare_result_1 = 0; - - compare_result_2 = _tu_param_compare(tu->n_n_err_fp, tu->err_fp); - if (compare_result_2 == 2) - compare_result_2 = 1; - else - compare_result_2 = 0; - - compare_result_3 = _tu_param_compare(tu->hbp_time_fp, - tu->delay_start_time_fp); - if (compare_result_3 == 2) - compare_result_3 = 0; - else - compare_result_3 = 1; - - if (((tu->even_distribution == 1) || - ((tu->even_distribution_BF == 0) && - (tu->even_distribution_legacy == 0))) && - tu->n_err_fp >= 0 && tu->n_n_err_fp >= 0 && - compare_result_2 && - (compare_result_1 || (tu->min_hblank_violated == 1)) && - (tu->new_valid_boundary_link - 1) > 0 && - compare_result_3 && - (tu->delay_start_link_tmp <= 1023)) { - tu->upper_boundary_count = tu->i_upper_boundary_count; - tu->lower_boundary_count = tu->i_lower_boundary_count; - tu->err_fp = tu->n_n_err_fp; - tu->boundary_moderation_en = true; - tu->tu_size_desired = tu->tu_size; - tu->valid_boundary_link = tu->new_valid_boundary_link; - tu->effective_valid_recorded_fp = tu->effective_valid_fp; - tu->even_distribution_BF = 1; - tu->delay_start_link = tu->delay_start_link_tmp; - } else if (tu->boundary_mod_lower_err == 0) { - compare_result_1 = _tu_param_compare(tu->n_n_err_fp, - tu->diff_abs_fp); - if (compare_result_1 == 2) - tu->boundary_mod_lower_err = 1; - } -} - -static void _dp_calc_boundary(struct tu_algo_data *tu) -{ - - s64 temp1_fp = 0, temp2_fp = 0; - - do { - tu->err_fp = drm_fixp_from_fraction(1000, 1); - - temp1_fp = drm_fixp_div(tu->lclk_fp, tu->pclk_fp); - temp2_fp = drm_fixp_from_fraction( - tu->delay_start_link_extra_pixclk, 1); - temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp); - - if (temp1_fp) - tu->extra_buffer_margin = - drm_fixp2int_ceil(temp1_fp); - else - tu->extra_buffer_margin = 0; - - temp1_fp = drm_fixp_from_fraction(tu->bpp, 8); - temp1_fp = drm_fixp_mul(tu->lwidth_fp, temp1_fp); - - if (temp1_fp) - tu->n_symbols = drm_fixp2int_ceil(temp1_fp); - else - tu->n_symbols = 0; - - for (tu->tu_size = 32; tu->tu_size <= 64; tu->tu_size++) { - for (tu->i_upper_boundary_count = 1; - tu->i_upper_boundary_count <= 15; - tu->i_upper_boundary_count++) { - for (tu->i_lower_boundary_count = 1; - tu->i_lower_boundary_count <= 15; - tu->i_lower_boundary_count++) { - _tu_valid_boundary_calc(tu); - } - } - } - tu->delay_start_link_extra_pixclk--; - } while (!tu->boundary_moderation_en && - tu->boundary_mod_lower_err == 1 && - tu->delay_start_link_extra_pixclk != 0); -} - -static void _dp_calc_extra_bytes(struct tu_algo_data *tu) -{ - u64 temp = 0; - s64 temp1_fp = 0, temp2_fp = 0; - - temp1_fp = drm_fixp_from_fraction(tu->tu_size_desired, 1); - temp2_fp = drm_fixp_mul(tu->original_ratio_fp, temp1_fp); - temp1_fp = drm_fixp_from_fraction(tu->valid_boundary_link, 1); - temp2_fp = temp1_fp - temp2_fp; - temp1_fp = drm_fixp_from_fraction(tu->n_tus + 1, 1); - temp2_fp = drm_fixp_mul(temp1_fp, temp2_fp); - - temp = drm_fixp2int(temp2_fp); - if (temp && temp2_fp) - tu->extra_bytes = drm_fixp2int_ceil(temp2_fp); - else - tu->extra_bytes = 0; - - temp1_fp = drm_fixp_from_fraction(tu->extra_bytes, 1); - temp2_fp = drm_fixp_from_fraction(8, tu->bpp); - temp1_fp = drm_fixp_mul(temp1_fp, temp2_fp); - - if (temp1_fp) - tu->extra_pclk_cycles = drm_fixp2int_ceil(temp1_fp); - else - tu->extra_pclk_cycles = drm_fixp2int(temp1_fp); - - temp1_fp = drm_fixp_div(tu->lclk_fp, tu->pclk_fp); - temp2_fp = drm_fixp_from_fraction(tu->extra_pclk_cycles, 1); - temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp); - - if (temp1_fp) - tu->extra_pclk_cycles_in_link_clk = drm_fixp2int_ceil(temp1_fp); - else - tu->extra_pclk_cycles_in_link_clk = drm_fixp2int(temp1_fp); -} - -static void _dp_panel_calc_tu(struct dp_tu_calc_input *in, - struct dp_vc_tu_mapping_table *tu_table) -{ - struct tu_algo_data tu; - int compare_result_1, compare_result_2; - u64 temp = 0; - s64 temp_fp = 0, temp1_fp = 0, temp2_fp = 0; - - s64 LCLK_FAST_SKEW_fp = drm_fixp_from_fraction(6, 10000); /* 0.0006 */ - s64 const_p49_fp = drm_fixp_from_fraction(49, 100); /* 0.49 */ - s64 const_p56_fp = drm_fixp_from_fraction(56, 100); /* 0.56 */ - s64 RATIO_SCALE_fp = drm_fixp_from_fraction(1001, 1000); - - u8 DP_BRUTE_FORCE = 1; - s64 BRUTE_FORCE_THRESHOLD_fp = drm_fixp_from_fraction(1, 10); /* 0.1 */ - uint EXTRA_PIXCLK_CYCLE_DELAY = 4; - uint HBLANK_MARGIN = 4; - - memset(&tu, 0, sizeof(tu)); - - dp_panel_update_tu_timings(in, &tu); - - tu.err_fp = drm_fixp_from_fraction(1000, 1); /* 1000 */ - - temp1_fp = drm_fixp_from_fraction(4, 1); - temp2_fp = drm_fixp_mul(temp1_fp, tu.lclk_fp); - temp_fp = drm_fixp_div(temp2_fp, tu.pclk_fp); - tu.extra_buffer_margin = drm_fixp2int_ceil(temp_fp); - - temp1_fp = drm_fixp_from_fraction(tu.bpp, 8); - temp2_fp = drm_fixp_mul(tu.pclk_fp, temp1_fp); - temp1_fp = drm_fixp_from_fraction(tu.nlanes, 1); - temp2_fp = drm_fixp_div(temp2_fp, temp1_fp); - tu.ratio_fp = drm_fixp_div(temp2_fp, tu.lclk_fp); - - tu.original_ratio_fp = tu.ratio_fp; - tu.boundary_moderation_en = false; - tu.upper_boundary_count = 0; - tu.lower_boundary_count = 0; - tu.i_upper_boundary_count = 0; - tu.i_lower_boundary_count = 0; - tu.valid_lower_boundary_link = 0; - tu.even_distribution_BF = 0; - tu.even_distribution_legacy = 0; - tu.even_distribution = 0; - tu.delay_start_time_fp = 0; - - tu.err_fp = drm_fixp_from_fraction(1000, 1); - tu.n_err_fp = 0; - tu.n_n_err_fp = 0; - - tu.ratio = drm_fixp2int(tu.ratio_fp); - temp1_fp = drm_fixp_from_fraction(tu.nlanes, 1); - temp2_fp = tu.lwidth_fp % temp1_fp; - if (temp2_fp != 0 && - !tu.ratio && tu.dsc_en == 0) { - tu.ratio_fp = drm_fixp_mul(tu.ratio_fp, RATIO_SCALE_fp); - tu.ratio = drm_fixp2int(tu.ratio_fp); - if (tu.ratio) - tu.ratio_fp = drm_fixp_from_fraction(1, 1); - } - - if (tu.ratio > 1) - tu.ratio = 1; - - if (tu.ratio == 1) - goto tu_size_calc; - - compare_result_1 = _tu_param_compare(tu.ratio_fp, const_p49_fp); - if (!compare_result_1 || compare_result_1 == 1) - compare_result_1 = 1; - else - compare_result_1 = 0; - - compare_result_2 = _tu_param_compare(tu.ratio_fp, const_p56_fp); - if (!compare_result_2 || compare_result_2 == 2) - compare_result_2 = 1; - else - compare_result_2 = 0; - - if (tu.dsc_en && compare_result_1 && compare_result_2) { - HBLANK_MARGIN += 4; - pr_info("Info: increase HBLANK_MARGIN to %d\n", HBLANK_MARGIN); - } - -tu_size_calc: - for (tu.tu_size = 32; tu.tu_size <= 64; tu.tu_size++) { - temp1_fp = drm_fixp_from_fraction(tu.tu_size, 1); - temp2_fp = drm_fixp_mul(tu.ratio_fp, temp1_fp); - temp = drm_fixp2int_ceil(temp2_fp); - temp1_fp = drm_fixp_from_fraction(temp, 1); - tu.n_err_fp = temp1_fp - temp2_fp; - - if (tu.n_err_fp < tu.err_fp) { - tu.err_fp = tu.n_err_fp; - tu.tu_size_desired = tu.tu_size; - } - } - - tu.tu_size_minus1 = tu.tu_size_desired - 1; - - temp1_fp = drm_fixp_from_fraction(tu.tu_size_desired, 1); - temp2_fp = drm_fixp_mul(tu.ratio_fp, temp1_fp); - tu.valid_boundary_link = drm_fixp2int_ceil(temp2_fp); - - temp1_fp = drm_fixp_from_fraction(tu.bpp, 8); - temp2_fp = tu.lwidth_fp; - temp2_fp = drm_fixp_mul(temp2_fp, temp1_fp); - - temp1_fp = drm_fixp_from_fraction(tu.valid_boundary_link, 1); - temp2_fp = drm_fixp_div(temp2_fp, temp1_fp); - tu.n_tus = drm_fixp2int(temp2_fp); - if ((temp2_fp & 0xFFFFFFFF) > 0xFFFFF000) - tu.n_tus += 1; - - tu.even_distribution_legacy = tu.n_tus % tu.nlanes == 0 ? 1 : 0; - pr_info("Info: n_sym = %d, num_of_tus = %d\n", - tu.valid_boundary_link, tu.n_tus); - - _dp_calc_extra_bytes(&tu); - - tu.filler_size = tu.tu_size_desired - tu.valid_boundary_link; - - temp1_fp = drm_fixp_from_fraction(tu.tu_size_desired, 1); - tu.ratio_by_tu_fp = drm_fixp_mul(tu.ratio_fp, temp1_fp); - - tu.delay_start_link = tu.extra_pclk_cycles_in_link_clk + - tu.filler_size + tu.extra_buffer_margin; - - tu.resulting_valid_fp = - drm_fixp_from_fraction(tu.valid_boundary_link, 1); - - temp1_fp = drm_fixp_from_fraction(tu.tu_size_desired, 1); - temp2_fp = drm_fixp_div(tu.resulting_valid_fp, temp1_fp); - tu.TU_ratio_err_fp = temp2_fp - tu.original_ratio_fp; - - temp1_fp = drm_fixp_from_fraction(HBLANK_MARGIN, 1); - temp1_fp = tu.hbp_relative_to_pclk_fp - temp1_fp; - tu.hbp_time_fp = drm_fixp_div(temp1_fp, tu.pclk_fp); - - temp1_fp = drm_fixp_from_fraction(tu.delay_start_link, 1); - tu.delay_start_time_fp = drm_fixp_div(temp1_fp, tu.lclk_fp); - - compare_result_1 = _tu_param_compare(tu.hbp_time_fp, - tu.delay_start_time_fp); - if (compare_result_1 == 2) /* hbp_time_fp < delay_start_time_fp */ - tu.min_hblank_violated = 1; - - tu.hactive_time_fp = drm_fixp_div(tu.lwidth_fp, tu.pclk_fp); - - compare_result_2 = _tu_param_compare(tu.hactive_time_fp, - tu.delay_start_time_fp); - if (compare_result_2 == 2) - tu.min_hblank_violated = 1; - - tu.delay_start_time_fp = 0; - - /* brute force */ - - tu.delay_start_link_extra_pixclk = EXTRA_PIXCLK_CYCLE_DELAY; - tu.diff_abs_fp = tu.resulting_valid_fp - tu.ratio_by_tu_fp; - - temp = drm_fixp2int(tu.diff_abs_fp); - if (!temp && tu.diff_abs_fp <= 0xffff) - tu.diff_abs_fp = 0; - - /* if(diff_abs < 0) diff_abs *= -1 */ - if (tu.diff_abs_fp < 0) - tu.diff_abs_fp = drm_fixp_mul(tu.diff_abs_fp, -1); - - tu.boundary_mod_lower_err = 0; - if ((tu.diff_abs_fp != 0 && - ((tu.diff_abs_fp > BRUTE_FORCE_THRESHOLD_fp) || - (tu.even_distribution_legacy == 0) || - (DP_BRUTE_FORCE == 1))) || - (tu.min_hblank_violated == 1)) { - - _dp_calc_boundary(&tu); - - if (tu.boundary_moderation_en) { - temp1_fp = drm_fixp_from_fraction( - (tu.upper_boundary_count * - tu.valid_boundary_link + - tu.lower_boundary_count * - (tu.valid_boundary_link - 1)), 1); - temp2_fp = drm_fixp_from_fraction( - (tu.upper_boundary_count + - tu.lower_boundary_count), 1); - tu.resulting_valid_fp = - drm_fixp_div(temp1_fp, temp2_fp); - - temp1_fp = drm_fixp_from_fraction( - tu.tu_size_desired, 1); - tu.ratio_by_tu_fp = - drm_fixp_mul(tu.original_ratio_fp, temp1_fp); - - tu.valid_lower_boundary_link = - tu.valid_boundary_link - 1; - - temp1_fp = drm_fixp_from_fraction(tu.bpp, 8); - temp1_fp = drm_fixp_mul(tu.lwidth_fp, temp1_fp); - temp2_fp = drm_fixp_div(temp1_fp, - tu.resulting_valid_fp); - tu.n_tus = drm_fixp2int(temp2_fp); - - tu.tu_size_minus1 = tu.tu_size_desired - 1; - tu.even_distribution_BF = 1; - - temp1_fp = - drm_fixp_from_fraction(tu.tu_size_desired, 1); - temp2_fp = - drm_fixp_div(tu.resulting_valid_fp, temp1_fp); - tu.TU_ratio_err_fp = temp2_fp - tu.original_ratio_fp; - } - } - - temp2_fp = drm_fixp_mul(LCLK_FAST_SKEW_fp, tu.lwidth_fp); - - if (temp2_fp) - temp = drm_fixp2int_ceil(temp2_fp); - else - temp = 0; - - temp1_fp = drm_fixp_from_fraction(tu.nlanes, 1); - temp2_fp = drm_fixp_mul(tu.original_ratio_fp, temp1_fp); - temp1_fp = drm_fixp_from_fraction(tu.bpp, 8); - temp2_fp = drm_fixp_div(temp1_fp, temp2_fp); - temp1_fp = drm_fixp_from_fraction(temp, 1); - temp2_fp = drm_fixp_mul(temp1_fp, temp2_fp); - temp = drm_fixp2int(temp2_fp); - - if (tu.async_en) - tu.delay_start_link += (int)temp; - - temp1_fp = drm_fixp_from_fraction(tu.delay_start_link, 1); - tu.delay_start_time_fp = drm_fixp_div(temp1_fp, tu.lclk_fp); - - /* OUTPUTS */ - tu_table->valid_boundary_link = tu.valid_boundary_link; - tu_table->delay_start_link = tu.delay_start_link; - tu_table->boundary_moderation_en = tu.boundary_moderation_en; - tu_table->valid_lower_boundary_link = tu.valid_lower_boundary_link; - tu_table->upper_boundary_count = tu.upper_boundary_count; - tu_table->lower_boundary_count = tu.lower_boundary_count; - tu_table->tu_size_minus1 = tu.tu_size_minus1; - - pr_info("TU: valid_boundary_link: %d\n", tu_table->valid_boundary_link); - pr_info("TU: delay_start_link: %d\n", tu_table->delay_start_link); - pr_info("TU: boundary_moderation_en: %d\n", - tu_table->boundary_moderation_en); - pr_info("TU: valid_lower_boundary_link: %d\n", - tu_table->valid_lower_boundary_link); - pr_info("TU: upper_boundary_count: %d\n", - tu_table->upper_boundary_count); - pr_info("TU: lower_boundary_count: %d\n", - tu_table->lower_boundary_count); - pr_info("TU: tu_size_minus1: %d\n", tu_table->tu_size_minus1); -} - -static void dp_panel_calc_tu_parameters(struct dp_panel *dp_panel, - struct dp_vc_tu_mapping_table *tu_table) -{ - struct dp_tu_calc_input in; - struct dp_panel_info *pinfo; - struct dp_panel_private *panel; - int bw_code; - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - pinfo = &dp_panel->pinfo; - bw_code = panel->link->link_params.bw_code; - - in.lclk = drm_dp_bw_code_to_link_rate(bw_code) / 1000; - in.pclk_khz = pinfo->pixel_clk_khz; - in.hactive = pinfo->h_active; - in.hporch = pinfo->h_back_porch + pinfo->h_front_porch + - pinfo->h_sync_width; - in.nlanes = panel->link->link_params.lane_count; - in.bpp = pinfo->bpp; - in.pixel_enc = 444; - in.dsc_en = dp_panel->dsc_en; - in.async_en = 0; - in.fec_en = dp_panel->fec_en; - in.num_of_dsc_slices = pinfo->comp_info.dsc_info.slice_per_pkt; - - switch (pinfo->comp_info.comp_ratio) { - case MSM_DISPLAY_COMPRESSION_RATIO_2_TO_1: - in.compress_ratio = 200; - break; - case MSM_DISPLAY_COMPRESSION_RATIO_3_TO_1: - in.compress_ratio = 300; - break; - default: - in.compress_ratio = 100; - } - - _dp_panel_calc_tu(&in, tu_table); -} - -void dp_panel_calc_tu_test(struct dp_tu_calc_input *in, - struct dp_vc_tu_mapping_table *tu_table) -{ - _dp_panel_calc_tu(in, tu_table); -} - -static void dp_panel_config_tr_unit(struct dp_panel *dp_panel) -{ - struct dp_panel_private *panel; - struct dp_catalog_panel *catalog; - u32 dp_tu = 0x0; - u32 valid_boundary = 0x0; - u32 valid_boundary2 = 0x0; - struct dp_vc_tu_mapping_table tu_calc_table; - - if (!dp_panel) { - pr_err("invalid input\n"); - return; - } - - if (dp_panel->stream_id != DP_STREAM_0) - return; - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - catalog = panel->catalog; - - dp_panel_calc_tu_parameters(dp_panel, &tu_calc_table); - - dp_tu |= tu_calc_table.tu_size_minus1; - valid_boundary |= tu_calc_table.valid_boundary_link; - valid_boundary |= (tu_calc_table.delay_start_link << 16); - - valid_boundary2 |= (tu_calc_table.valid_lower_boundary_link << 1); - valid_boundary2 |= (tu_calc_table.upper_boundary_count << 16); - valid_boundary2 |= (tu_calc_table.lower_boundary_count << 20); - - if (tu_calc_table.boundary_moderation_en) - valid_boundary2 |= BIT(0); - - pr_debug("dp_tu=0x%x, valid_boundary=0x%x, valid_boundary2=0x%x\n", - dp_tu, valid_boundary, valid_boundary2); - - catalog->dp_tu = dp_tu; - catalog->valid_boundary = valid_boundary; - catalog->valid_boundary2 = valid_boundary2; - - catalog->update_transfer_unit(catalog); -} - -enum dp_dsc_ratio_type { - DSC_8BPC_8BPP, - DSC_10BPC_8BPP, - DSC_12BPC_8BPP, - DSC_RATIO_TYPE_MAX -}; - -static u32 dp_dsc_rc_buf_thresh[] = {0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, - 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, 0x7d, 0x7e}; - -/* - * DSC 1.1 - * Rate control - Min QP values for each ratio type in dp_dsc_ratio_type - */ -static char dp_dsc_rc_range_min_qp_1_1[][15] = { - {0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 13}, - {0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 11, 17}, - {0, 4, 9, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 21}, - }; - -/* - * DSC 1.1 SCR - * Rate control - Min QP values for each ratio type in dp_dsc_ratio_type - */ -static char dp_dsc_rc_range_min_qp_1_1_scr1[][15] = { - {0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 9, 12}, - {0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 13, 16}, - {0, 4, 9, 9, 11, 11, 11, 11, 11, 11, 13, 13, 13, 17, 20}, - }; - -/* - * DSC 1.1 - * Rate control - Max QP values for each ratio type in dp_dsc_ratio_type - */ -static char dp_dsc_rc_range_max_qp_1_1[][15] = { - {4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 11, 12, 13, 13, 15}, - {8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 15, 16, 17, 17, 19}, - {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 19, 20, 21, 21, 23}, - }; - -/* - * DSC 1.1 SCR - * Rate control - Max QP values for each ratio type in dp_dsc_ratio_type - */ -static char dp_dsc_rc_range_max_qp_1_1_scr1[][15] = { - {4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13}, - {8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17}, - {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21}, - }; - -/* - * DSC 1.1 and DSC 1.1 SCR - * Rate control - bpg offset values - */ -static char dp_dsc_rc_range_bpg_offset[] = {2, 0, 0, -2, -4, -6, -8, -8, - -8, -10, -10, -12, -12, -12, -12}; - -struct dp_dsc_dto_data { - enum msm_display_compression_ratio comp_ratio; - u32 org_bpp; /* bits */ - u32 dto_numerator; - u32 dto_denominator; -}; - -struct dp_dsc_dto_data dto_tbl[] = { - {MSM_DISPLAY_COMPRESSION_RATIO_2_TO_1, 24, 1, 2}, - {MSM_DISPLAY_COMPRESSION_RATIO_2_TO_1, 30, 5, 8}, - {MSM_DISPLAY_COMPRESSION_RATIO_3_TO_1, 24, 1, 3}, - {MSM_DISPLAY_COMPRESSION_RATIO_3_TO_1, 30, 5, 12}, -}; - -static void _dp_panel_get_dto_m_n(enum msm_display_compression_ratio ratio, - u32 org_bpp, u32 *dto_n, u32 *dto_d) -{ - u32 idx; - - for (idx = 0; idx < ARRAY_SIZE(dto_tbl); idx++) { - if (ratio == dto_tbl[idx].comp_ratio && - org_bpp == dto_tbl[idx].org_bpp) { - *dto_n = dto_tbl[idx].dto_numerator; - *dto_d = dto_tbl[idx].dto_denominator; - return; - } - } -} - -static int dp_panel_dsc_create_pps_buf_cmd(struct msm_display_dsc_info *dsc, - char *buf, int pps_id) -{ - char *bp = buf; - char data; - int i, bpp; - - *bp++ = (dsc->version & 0xff); /* pps0 */ - *bp++ = (pps_id & 0xff); /* pps1 */ - bp++; /* pps2, reserved */ - - data = dsc->line_buf_depth & 0x0f; - data |= ((dsc->bpc & 0xf) << 4); - *bp++ = data; /* pps3 */ - - bpp = dsc->bpp; - bpp <<= 4; /* 4 fraction bits */ - data = (bpp >> 8); - data &= 0x03; /* upper two bits */ - data |= ((dsc->block_pred_enable & 0x1) << 5); - data |= ((dsc->convert_rgb & 0x1) << 4); - data |= ((dsc->enable_422 & 0x1) << 3); - data |= ((dsc->vbr_enable & 0x1) << 2); - *bp++ = data; /* pps4 */ - *bp++ = (bpp & 0xff); /* pps5 */ - - *bp++ = ((dsc->pic_height >> 8) & 0xff); /* pps6 */ - *bp++ = (dsc->pic_height & 0x0ff); /* pps7 */ - *bp++ = ((dsc->pic_width >> 8) & 0xff); /* pps8 */ - *bp++ = (dsc->pic_width & 0x0ff); /* pps9 */ - - *bp++ = ((dsc->slice_height >> 8) & 0xff);/* pps10 */ - *bp++ = (dsc->slice_height & 0x0ff); /* pps11 */ - *bp++ = ((dsc->slice_width >> 8) & 0xff); /* pps12 */ - *bp++ = (dsc->slice_width & 0x0ff); /* pps13 */ - - *bp++ = ((dsc->chunk_size >> 8) & 0xff);/* pps14 */ - *bp++ = (dsc->chunk_size & 0x0ff); /* pps15 */ - - *bp++ = (dsc->initial_xmit_delay >> 8) & 0x3; /* pps16*/ - *bp++ = (dsc->initial_xmit_delay & 0xff);/* pps17 */ - - *bp++ = ((dsc->initial_dec_delay >> 8) & 0xff); /* pps18 */ - *bp++ = (dsc->initial_dec_delay & 0xff);/* pps19 */ - - bp++; /* pps20, reserved */ - - *bp++ = (dsc->initial_scale_value & 0x3f); /* pps21 */ - - *bp++ = ((dsc->scale_increment_interval >> 8) & 0xff); /* pps22 */ - *bp++ = (dsc->scale_increment_interval & 0xff); /* pps23 */ - - *bp++ = ((dsc->scale_decrement_interval >> 8) & 0xf); /* pps24 */ - *bp++ = (dsc->scale_decrement_interval & 0x0ff);/* pps25 */ - - bp++; /* pps26, reserved */ - - *bp++ = (dsc->first_line_bpg_offset & 0x1f);/* pps27 */ - - *bp++ = ((dsc->nfl_bpg_offset >> 8) & 0xff);/* pps28 */ - *bp++ = (dsc->nfl_bpg_offset & 0x0ff); /* pps29 */ - *bp++ = ((dsc->slice_bpg_offset >> 8) & 0xff);/* pps30 */ - *bp++ = (dsc->slice_bpg_offset & 0x0ff);/* pps31 */ - - *bp++ = ((dsc->initial_offset >> 8) & 0xff);/* pps32 */ - *bp++ = (dsc->initial_offset & 0x0ff); /* pps33 */ - - *bp++ = ((dsc->final_offset >> 8) & 0xff);/* pps34 */ - *bp++ = (dsc->final_offset & 0x0ff); /* pps35 */ - - *bp++ = (dsc->min_qp_flatness & 0x1f); /* pps36 */ - *bp++ = (dsc->max_qp_flatness & 0x1f); /* pps37 */ - - *bp++ = ((dsc->rc_model_size >> 8) & 0xff);/* pps38 */ - *bp++ = (dsc->rc_model_size & 0x0ff); /* pps39 */ - - *bp++ = (dsc->edge_factor & 0x0f); /* pps40 */ - - *bp++ = (dsc->quant_incr_limit0 & 0x1f); /* pps41 */ - *bp++ = (dsc->quant_incr_limit1 & 0x1f); /* pps42 */ - - data = ((dsc->tgt_offset_hi & 0xf) << 4); - data |= (dsc->tgt_offset_lo & 0x0f); - *bp++ = data; /* pps43 */ - - for (i = 0; i < ARRAY_SIZE(dp_dsc_rc_buf_thresh); i++) - *bp++ = (dsc->buf_thresh[i] & 0xff); /* pps44 - pps57 */ - - for (i = 0; i < 15; i++) { /* pps58 - pps87 */ - data = (dsc->range_min_qp[i] & 0x1f); - data <<= 3; - data |= ((dsc->range_max_qp[i] >> 2) & 0x07); - *bp++ = data; - data = (dsc->range_max_qp[i] & 0x03); - data <<= 6; - data |= (dsc->range_bpg_offset[i] & 0x3f); - *bp++ = data; - } - - return 88; -} - -static void dp_panel_dsc_prepare_pps_packet(struct dp_panel *dp_panel) -{ - struct dp_panel_private *panel; - struct dp_dsc_cfg_data *dsc; - u8 *pps, *parity; - u32 *pps_word, *parity_word; - int i, index_4; - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - dsc = &panel->catalog->dsc; - pps = dsc->pps; - pps_word = dsc->pps_word; - parity = dsc->parity; - parity_word = dsc->parity_word; - - memset(parity, 0, sizeof(dsc->parity)); - - dsc->pps_word_len = dsc->pps_len >> 2; - dsc->parity_len = dsc->pps_word_len; - dsc->parity_word_len = (dsc->parity_len >> 2) + 1; - - for (i = 0; i < dsc->pps_word_len; i++) { - index_4 = i << 2; - pps_word[i] = pps[index_4 + 0] << 0 | - pps[index_4 + 1] << 8 | - pps[index_4 + 2] << 16 | - pps[index_4 + 3] << 24; - - parity[i] = dp_header_get_parity(pps_word[i]); - } - - for (i = 0; i < dsc->parity_word_len; i++) { - index_4 = i << 2; - parity_word[i] = parity[index_4 + 0] << 0 | - parity[index_4 + 1] << 8 | - parity[index_4 + 2] << 16 | - parity[index_4 + 3] << 24; - } -} - -static void _dp_panel_dsc_get_num_extra_pclk(struct msm_display_dsc_info *dsc, - enum msm_display_compression_ratio ratio) -{ - unsigned int dto_n, dto_d, remainder; - int ack_required, last_few_ack_required, accum_ack; - int last_few_pclk, last_few_pclk_required; - int start, temp, line_width = dsc->pic_width/2; - s64 temp1_fp, temp2_fp; - - _dp_panel_get_dto_m_n(ratio, dsc->bpc * 3, &dto_n, &dto_d); - - ack_required = dsc->pclk_per_line; - - /* number of pclk cycles left outside of the complete DTO set */ - last_few_pclk = line_width % dto_d; - - /* number of pclk cycles outside of the complete dto */ - temp1_fp = drm_fixp_from_fraction(line_width, dto_d); - temp2_fp = drm_fixp_from_fraction(dto_n, 1); - temp1_fp = drm_fixp_mul(temp1_fp, temp2_fp); - temp = drm_fixp2int(temp1_fp); - last_few_ack_required = ack_required - temp; - - /* - * check how many more pclk is needed to - * accommodate the last few ack required - */ - remainder = dto_n; - accum_ack = 0; - last_few_pclk_required = 0; - while (accum_ack < last_few_ack_required) { - last_few_pclk_required++; - - if (remainder >= dto_n) - start = remainder; - else - start = remainder + dto_d; - - remainder = start - dto_n; - if (remainder < dto_n) - accum_ack++; - } - - /* if fewer pclk than required */ - if (last_few_pclk < last_few_pclk_required) - dsc->extra_width = last_few_pclk_required - last_few_pclk; - else - dsc->extra_width = 0; - - pr_debug("extra pclks required: %d\n", dsc->extra_width); -} - -static void _dp_panel_dsc_bw_overhead_calc(struct dp_panel *dp_panel, - struct msm_display_dsc_info *dsc, - struct dp_display_mode *dp_mode, u32 dsc_byte_cnt) -{ - int num_slices, tot_num_eoc_symbols; - int tot_num_hor_bytes, tot_num_dummy_bytes; - int dwidth_dsc_bytes, eoc_bytes; - u32 num_lanes; - - num_lanes = dp_panel->link_info.num_lanes; - num_slices = dsc->slice_per_pkt; - - eoc_bytes = dsc_byte_cnt % num_lanes; - tot_num_eoc_symbols = num_lanes * num_slices; - tot_num_hor_bytes = dsc_byte_cnt * num_slices; - tot_num_dummy_bytes = (num_lanes - eoc_bytes) * num_slices; - - if (!eoc_bytes) - tot_num_dummy_bytes = 0; - - dwidth_dsc_bytes = tot_num_hor_bytes + tot_num_eoc_symbols + - tot_num_dummy_bytes; - - pr_debug("dwidth_dsc_bytes:%d, tot_num_hor_bytes:%d\n", - dwidth_dsc_bytes, tot_num_hor_bytes); - - dp_mode->dsc_overhead_fp = drm_fixp_from_fraction(dwidth_dsc_bytes, - tot_num_hor_bytes); - dp_mode->timing.dsc_overhead_fp = dp_mode->dsc_overhead_fp; -} - -static void dp_panel_dsc_pclk_param_calc(struct dp_panel *dp_panel, - struct msm_display_dsc_info *dsc, - enum msm_display_compression_ratio ratio, - struct dp_display_mode *dp_mode) -{ - int slice_per_pkt, slice_per_intf, intf_width; - int bytes_in_slice, total_bytes_per_intf; - int comp_ratio; - s64 temp1_fp, temp2_fp; - s64 numerator_fp, denominator_fp; - s64 dsc_byte_count_fp; - u32 dsc_byte_count, temp1, temp2; - - intf_width = dp_mode->timing.h_active; - if (!dsc || !dsc->slice_width || !dsc->slice_per_pkt || - (intf_width < dsc->slice_width)) - return; - - slice_per_pkt = dsc->slice_per_pkt; - slice_per_intf = DIV_ROUND_UP(intf_width, dsc->slice_width); - - if (slice_per_pkt > slice_per_intf) - slice_per_pkt = 1; - - bytes_in_slice = DIV_ROUND_UP(dsc->slice_width * dsc->bpp, 8); - total_bytes_per_intf = bytes_in_slice * slice_per_intf; - - dsc->bytes_in_slice = bytes_in_slice; - dsc->bytes_per_pkt = bytes_in_slice * slice_per_pkt; - dsc->pkt_per_line = slice_per_intf / slice_per_pkt; - - switch (ratio) { - case MSM_DISPLAY_COMPRESSION_RATIO_2_TO_1: - comp_ratio = 200; - break; - case MSM_DISPLAY_COMPRESSION_RATIO_3_TO_1: - comp_ratio = 300; - break; - default: - comp_ratio = 100; - break; - } - - temp1_fp = drm_fixp_from_fraction(comp_ratio, 100); - temp2_fp = drm_fixp_from_fraction(slice_per_pkt * 8, 1); - denominator_fp = drm_fixp_mul(temp1_fp, temp2_fp); - numerator_fp = drm_fixp_from_fraction(intf_width * dsc->bpc * 3, 1); - dsc_byte_count_fp = drm_fixp_div(numerator_fp, denominator_fp); - dsc_byte_count = drm_fixp2int_ceil(dsc_byte_count_fp); - - temp1 = dsc_byte_count * slice_per_intf; - temp2 = temp1; - if (temp1 % 3 != 0) - temp1 += 3 - (temp1 % 3); - - dsc->eol_byte_num = temp1 - temp2; - - temp1_fp = drm_fixp_from_fraction(slice_per_intf, 6); - temp2_fp = drm_fixp_mul(dsc_byte_count_fp, temp1_fp); - dsc->pclk_per_line = drm_fixp2int_ceil(temp2_fp); - - _dp_panel_dsc_get_num_extra_pclk(dsc, ratio); - dsc->pclk_per_line--; - - _dp_panel_dsc_bw_overhead_calc(dp_panel, dsc, dp_mode, dsc_byte_count); -} - -static void dp_panel_dsc_populate_static_params( - struct msm_display_dsc_info *dsc) -{ - int bpp, bpc; - int mux_words_size; - int groups_per_line, groups_total; - int min_rate_buffer_size; - int hrd_delay; - int pre_num_extra_mux_bits, num_extra_mux_bits; - int slice_bits; - int data; - int final_value, final_scale; - int ratio_index, mod_offset; - - dsc->version = 0x11; - dsc->scr_rev = 0; - dsc->rc_model_size = 8192; - - if (dsc->version == 0x11 && dsc->scr_rev == 0x1) - dsc->first_line_bpg_offset = 15; - else - dsc->first_line_bpg_offset = 12; - - dsc->edge_factor = 6; - dsc->tgt_offset_hi = 3; - dsc->tgt_offset_lo = 3; - dsc->enable_422 = 0; - dsc->convert_rgb = 1; - dsc->vbr_enable = 0; - - dsc->buf_thresh = dp_dsc_rc_buf_thresh; - - bpp = dsc->bpp; - bpc = dsc->bpc; - - if (bpc == 12) - ratio_index = DSC_12BPC_8BPP; - else if (bpc == 10) - ratio_index = DSC_10BPC_8BPP; - else - ratio_index = DSC_8BPC_8BPP; - - if (dsc->version == 0x11 && dsc->scr_rev == 0x1) { - dsc->range_min_qp = - dp_dsc_rc_range_min_qp_1_1_scr1[ratio_index]; - dsc->range_max_qp = - dp_dsc_rc_range_max_qp_1_1_scr1[ratio_index]; - } else { - dsc->range_min_qp = dp_dsc_rc_range_min_qp_1_1[ratio_index]; - dsc->range_max_qp = dp_dsc_rc_range_max_qp_1_1[ratio_index]; - } - dsc->range_bpg_offset = dp_dsc_rc_range_bpg_offset; - - if (bpp <= 10) - dsc->initial_offset = 6144; - else - dsc->initial_offset = 2048; /* bpp = 12 */ - - if (bpc == 12) - mux_words_size = 64; - else - mux_words_size = 48; /* bpc == 8/10 */ - - dsc->line_buf_depth = bpc + 1; - - if (bpc == 8) { - dsc->input_10_bits = 0; - dsc->min_qp_flatness = 3; - dsc->max_qp_flatness = 12; - dsc->quant_incr_limit0 = 11; - dsc->quant_incr_limit1 = 11; - } else if (bpc == 10) { /* 10bpc */ - dsc->input_10_bits = 1; - dsc->min_qp_flatness = 7; - dsc->max_qp_flatness = 16; - dsc->quant_incr_limit0 = 15; - dsc->quant_incr_limit1 = 15; - } else { /* 12 bpc */ - dsc->input_10_bits = 0; - dsc->min_qp_flatness = 11; - dsc->max_qp_flatness = 20; - dsc->quant_incr_limit0 = 19; - dsc->quant_incr_limit1 = 19; - } - - mod_offset = dsc->slice_width % 3; - switch (mod_offset) { - case 0: - dsc->slice_last_group_size = 2; - break; - case 1: - dsc->slice_last_group_size = 0; - break; - case 2: - dsc->slice_last_group_size = 1; - break; - default: - break; - } - - dsc->det_thresh_flatness = 2 << (bpc - 8); - - dsc->initial_xmit_delay = dsc->rc_model_size / (2 * bpp); - - groups_per_line = DIV_ROUND_UP(dsc->slice_width, 3); - - dsc->chunk_size = dsc->slice_width * bpp / 8; - if ((dsc->slice_width * bpp) % 8) - dsc->chunk_size++; - - /* rbs-min */ - min_rate_buffer_size = dsc->rc_model_size - dsc->initial_offset + - dsc->initial_xmit_delay * bpp + - groups_per_line * dsc->first_line_bpg_offset; - - hrd_delay = DIV_ROUND_UP(min_rate_buffer_size, bpp); - - dsc->initial_dec_delay = hrd_delay - dsc->initial_xmit_delay; - - dsc->initial_scale_value = 8 * dsc->rc_model_size / - (dsc->rc_model_size - dsc->initial_offset); - - slice_bits = 8 * dsc->chunk_size * dsc->slice_height; - - groups_total = groups_per_line * dsc->slice_height; - - data = dsc->first_line_bpg_offset * 2048; - - dsc->nfl_bpg_offset = DIV_ROUND_UP(data, (dsc->slice_height - 1)); - - pre_num_extra_mux_bits = 3 * (mux_words_size + (4 * bpc + 4) - 2); - - num_extra_mux_bits = pre_num_extra_mux_bits - (mux_words_size - - ((slice_bits - pre_num_extra_mux_bits) % mux_words_size)); - - data = 2048 * (dsc->rc_model_size - dsc->initial_offset - + num_extra_mux_bits); - dsc->slice_bpg_offset = DIV_ROUND_UP(data, groups_total); - - data = dsc->initial_xmit_delay * bpp; - final_value = dsc->rc_model_size - data + num_extra_mux_bits; - - final_scale = 8 * dsc->rc_model_size / - (dsc->rc_model_size - final_value); - - dsc->final_offset = final_value; - - data = (final_scale - 9) * (dsc->nfl_bpg_offset + - dsc->slice_bpg_offset); - dsc->scale_increment_interval = (2048 * dsc->final_offset) / data; - - dsc->scale_decrement_interval = groups_per_line / - (dsc->initial_scale_value - 8); -} - -struct dp_dsc_slices_per_line { - u32 min_ppr; - u32 max_ppr; - u8 num_slices; -}; - -struct dp_dsc_slices_per_line slice_per_line_tbl[] = { - {0, 340, 1 }, - {340, 680, 2 }, - {680, 1360, 4 }, - {1360, 3200, 8 }, - {3200, 4800, 12 }, - {4800, 6400, 16 }, - {6400, 8000, 20 }, - {8000, 9600, 24 } -}; - -static int dp_panel_dsc_prepare_basic_params( - struct msm_compression_info *comp_info, - const struct dp_display_mode *dp_mode, - struct dp_panel *dp_panel) -{ - int i; - struct dp_dsc_slices_per_line *rec; - int slice_width; - u32 ppr = dp_mode->timing.pixel_clk_khz/1000; - int max_slice_width; - - comp_info->dsc_info.slice_per_pkt = 0; - for (i = 0; i < ARRAY_SIZE(slice_per_line_tbl); i++) { - rec = &slice_per_line_tbl[i]; - if ((ppr > rec->min_ppr) && (ppr <= rec->max_ppr)) { - comp_info->dsc_info.slice_per_pkt = rec->num_slices; - i++; - break; - } - } - - if (comp_info->dsc_info.slice_per_pkt == 0) - return -EINVAL; - - max_slice_width = dp_panel->dsc_dpcd[12] * 320; - slice_width = (dp_mode->timing.h_active / - comp_info->dsc_info.slice_per_pkt); - - while (slice_width >= max_slice_width) { - if (i == ARRAY_SIZE(slice_per_line_tbl)) - return -EINVAL; - - rec = &slice_per_line_tbl[i]; - comp_info->dsc_info.slice_per_pkt = rec->num_slices; - slice_width = (dp_mode->timing.h_active / - comp_info->dsc_info.slice_per_pkt); - i++; - } - - comp_info->dsc_info.block_pred_enable = - dp_panel->sink_dsc_caps.block_pred_en; - comp_info->dsc_info.vbr_enable = 0; - comp_info->dsc_info.enable_422 = 0; - comp_info->dsc_info.convert_rgb = 1; - comp_info->dsc_info.input_10_bits = 0; - - comp_info->dsc_info.pic_width = dp_mode->timing.h_active; - comp_info->dsc_info.pic_height = dp_mode->timing.v_active; - comp_info->dsc_info.slice_width = slice_width; - - if (comp_info->dsc_info.pic_height % 16 == 0) - comp_info->dsc_info.slice_height = 16; - else if (comp_info->dsc_info.pic_height % 12 == 0) - comp_info->dsc_info.slice_height = 12; - else - comp_info->dsc_info.slice_height = 15; - - comp_info->dsc_info.bpc = dp_mode->timing.bpp / 3; - comp_info->dsc_info.bpp = comp_info->dsc_info.bpc; - comp_info->dsc_info.full_frame_slices = - DIV_ROUND_UP(dp_mode->timing.h_active, slice_width); - - comp_info->comp_type = MSM_DISPLAY_COMPRESSION_DSC; - comp_info->comp_ratio = MSM_DISPLAY_COMPRESSION_RATIO_3_TO_1; - return 0; -} - -static int dp_panel_read_dpcd(struct dp_panel *dp_panel, bool multi_func) -{ - int rlen, rc = 0; - struct dp_panel_private *panel; - struct drm_dp_link *link_info; - struct drm_dp_aux *drm_aux; - u8 *dpcd, rx_feature, temp; - u32 dfp_count = 0, offset = DP_DPCD_REV; - - if (!dp_panel) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto end; - } - - dpcd = dp_panel->dpcd; - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - drm_aux = panel->aux->drm_aux; - link_info = &dp_panel->link_info; - - /* reset vsc data */ - panel->vsc_supported = false; - panel->vscext_supported = false; - panel->vscext_chaining_supported = false; - - if (panel->custom_dpcd) { - pr_debug("skip dpcd read in debug mode\n"); - goto skip_dpcd_read; - } - - rlen = drm_dp_dpcd_read(drm_aux, DP_TRAINING_AUX_RD_INTERVAL, &temp, 1); - if (rlen != 1) { - pr_err("error reading DP_TRAINING_AUX_RD_INTERVAL\n"); - rc = -EINVAL; - goto end; - } - - /* check for EXTENDED_RECEIVER_CAPABILITY_FIELD_PRESENT */ - if (temp & BIT(7)) { - pr_debug("using EXTENDED_RECEIVER_CAPABILITY_FIELD\n"); - offset = DPRX_EXTENDED_DPCD_FIELD; - } - - rlen = drm_dp_dpcd_read(drm_aux, offset, - dp_panel->dpcd, (DP_RECEIVER_CAP_SIZE + 1)); - if (rlen < (DP_RECEIVER_CAP_SIZE + 1)) { - pr_err("dpcd read failed, rlen=%d\n", rlen); - if (rlen == -ETIMEDOUT) - rc = rlen; - else - rc = -EINVAL; - - goto end; - } - - print_hex_dump(KERN_DEBUG, "[drm-dp] SINK DPCD: ", - DUMP_PREFIX_NONE, 8, 1, dp_panel->dpcd, rlen, false); - - rlen = drm_dp_dpcd_read(panel->aux->drm_aux, - DPRX_FEATURE_ENUMERATION_LIST, &rx_feature, 1); - if (rlen != 1) { - pr_debug("failed to read DPRX_FEATURE_ENUMERATION_LIST\n"); - goto skip_dpcd_read; - } - panel->vsc_supported = !!(rx_feature & - VSC_SDP_EXTENSION_FOR_COLORIMETRY_SUPPORTED); - panel->vscext_supported = !!(rx_feature & VSC_EXT_VESA_SDP_SUPPORTED); - panel->vscext_chaining_supported = !!(rx_feature & - VSC_EXT_VESA_SDP_CHAINING_SUPPORTED); - - pr_debug("vsc=%d, vscext=%d, vscext_chaining=%d\n", - panel->vsc_supported, panel->vscext_supported, - panel->vscext_chaining_supported); - -skip_dpcd_read: - panel->major = (link_info->revision >> 4) & 0x0f; - panel->minor = link_info->revision & 0x0f; - - /* override link params updated in dp_panel_init_panel_info */ - link_info->rate = min_t(unsigned long, panel->parser->max_lclk_khz, - link_info->rate); - - if (multi_func) - link_info->num_lanes = min_t(unsigned int, - link_info->num_lanes, 2); - - pr_debug("version:%d.%d, rate:%d, lanes:%d\n", panel->major, - panel->minor, link_info->rate, link_info->num_lanes); - - dfp_count = dpcd[DP_DOWN_STREAM_PORT_COUNT] & - DP_DOWN_STREAM_PORT_COUNT; - - if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT) - && (dpcd[DP_DPCD_REV] > 0x10)) { - rlen = drm_dp_dpcd_read(panel->aux->drm_aux, - DP_DOWNSTREAM_PORT_0, dp_panel->ds_ports, - DP_MAX_DOWNSTREAM_PORTS); - if (rlen < DP_MAX_DOWNSTREAM_PORTS) { - pr_err("ds port status failed, rlen=%d\n", rlen); - rc = -EINVAL; - goto end; - } - } - - if (dfp_count > DP_MAX_DS_PORT_COUNT) - pr_debug("DS port count %d greater that max (%d) supported\n", - dfp_count, DP_MAX_DS_PORT_COUNT); - -end: - return rc; -} - -static int dp_panel_set_default_link_params(struct dp_panel *dp_panel) -{ - struct drm_dp_link *link_info; - const int default_bw_code = 162000; - const int default_num_lanes = 1; - - if (!dp_panel) { - pr_err("invalid input\n"); - return -EINVAL; - } - link_info = &dp_panel->link_info; - link_info->rate = default_bw_code; - link_info->num_lanes = default_num_lanes; - pr_debug("link_rate=%d num_lanes=%d\n", - link_info->rate, link_info->num_lanes); - - return 0; -} - -static int dp_panel_set_edid(struct dp_panel *dp_panel, u8 *edid) -{ - struct dp_panel_private *panel; - - if (!dp_panel) { - pr_err("invalid input\n"); - return -EINVAL; - } - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - - if (edid) { - dp_panel->edid_ctrl->edid = (struct edid *)edid; - panel->custom_edid = true; - } else { - panel->custom_edid = false; - dp_panel->edid_ctrl->edid = NULL; - } - - pr_debug("%d\n", panel->custom_edid); - return 0; -} - -static int dp_panel_set_dpcd(struct dp_panel *dp_panel, u8 *dpcd) -{ - struct dp_panel_private *panel; - u8 *dp_dpcd; - - if (!dp_panel) { - pr_err("invalid input\n"); - return -EINVAL; - } - - dp_dpcd = dp_panel->dpcd; - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - - if (dpcd) { - memcpy(dp_dpcd, dpcd, DP_RECEIVER_CAP_SIZE + 1); - panel->custom_dpcd = true; - } else { - panel->custom_dpcd = false; - } - - pr_debug("%d\n", panel->custom_dpcd); - - return 0; -} - -static int dp_panel_read_edid(struct dp_panel *dp_panel, - struct drm_connector *connector) -{ - int ret = 0; - struct dp_panel_private *panel; - struct edid *edid; - - if (!dp_panel) { - pr_err("invalid input\n"); - return -EINVAL; - } - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - - if (panel->custom_edid) { - pr_debug("skip edid read in debug mode\n"); - goto end; - } - - sde_get_edid(connector, &panel->aux->drm_aux->ddc, - (void **)&dp_panel->edid_ctrl); - if (!dp_panel->edid_ctrl->edid) { - pr_err("EDID read failed\n"); - ret = -EINVAL; - goto end; - } -end: - edid = dp_panel->edid_ctrl->edid; - dp_panel->audio_supported = drm_detect_monitor_audio(edid); - - return ret; -} - -static void dp_panel_decode_dsc_dpcd(struct dp_panel *dp_panel) -{ - s64 fec_overhead_fp = drm_fixp_from_fraction(1, 1); - - if (!dp_panel->dsc_feature_enable || !dp_panel->fec_feature_enable) { - pr_debug("source dsc is not supported\n"); - return; - } - - if (dp_panel->dsc_dpcd[0] && dp_panel->fec_dpcd) { - dp_panel->sink_dsc_caps.dsc_capable = true; - dp_panel->sink_dsc_caps.version = dp_panel->dsc_dpcd[1]; - dp_panel->sink_dsc_caps.block_pred_en = - dp_panel->dsc_dpcd[6] ? true : false; - - if (dp_panel->sink_dsc_caps.version >= 0x11) - dp_panel->dsc_en = true; - } else { - dp_panel->sink_dsc_caps.dsc_capable = false; - dp_panel->dsc_en = false; - } - - dp_panel->fec_en = dp_panel->dsc_en; - dp_panel->widebus_en = dp_panel->dsc_en; - - /* fec_overhead = 1.00 / 0.97582 */ - if (dp_panel->fec_en) - fec_overhead_fp = drm_fixp_from_fraction(100000, 97582); - - dp_panel->fec_overhead_fp = fec_overhead_fp; -} - -static void dp_panel_read_sink_dsc_caps(struct dp_panel *dp_panel) -{ - int rlen; - struct dp_panel_private *panel; - const int fec_cap = 0x90; - int dpcd_rev; - - if (!dp_panel) { - pr_err("invalid input\n"); - return; - } - - dp_panel->dsc_en = false; - dp_panel->fec_en = false; - - dpcd_rev = dp_panel->dpcd[DP_DPCD_REV]; - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - - dp_panel->fec_overhead_fp = 0; - if (panel->parser->dsc_feature_enable && dpcd_rev >= 0x14) { - rlen = drm_dp_dpcd_read(panel->aux->drm_aux, DP_DSC_SUPPORT, - dp_panel->dsc_dpcd, (DP_RECEIVER_DSC_CAP_SIZE + 1)); - if (rlen < (DP_RECEIVER_DSC_CAP_SIZE + 1)) { - pr_debug("dsc dpcd read failed, rlen=%d\n", rlen); - return; - } - - print_hex_dump(KERN_DEBUG, "[drm-dp] SINK DSC DPCD: ", - DUMP_PREFIX_NONE, 8, 1, dp_panel->dsc_dpcd, rlen, - false); - - rlen = drm_dp_dpcd_read(panel->aux->drm_aux, fec_cap, - &dp_panel->fec_dpcd, 1); - if (rlen < 1) { - pr_err("fec dpcd read failed, rlen=%d\n", rlen); - return; - } - - dp_panel_decode_dsc_dpcd(dp_panel); - } -} - -static int dp_panel_read_sink_caps(struct dp_panel *dp_panel, - struct drm_connector *connector, bool multi_func) -{ - int rc = 0, rlen, count, downstream_ports; - const int count_len = 1; - struct dp_panel_private *panel; - - if (!dp_panel || !connector) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto end; - } - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - - rc = dp_panel_read_dpcd(dp_panel, multi_func); - if (rc || !is_link_rate_valid(drm_dp_link_rate_to_bw_code( - dp_panel->link_info.rate)) || !is_lane_count_valid( - dp_panel->link_info.num_lanes) || - ((drm_dp_link_rate_to_bw_code(dp_panel->link_info.rate)) > - dp_panel->max_bw_code)) { - if ((rc == -ETIMEDOUT) || (rc == -ENODEV)) { - pr_err("DPCD read failed, return early\n"); - goto end; - } - pr_err("panel dpcd read failed/incorrect, set default params\n"); - dp_panel_set_default_link_params(dp_panel); - } - - downstream_ports = dp_panel->dpcd[DP_DOWNSTREAMPORT_PRESENT] & - DP_DWN_STRM_PORT_PRESENT; - - if (downstream_ports) { - rlen = drm_dp_dpcd_read(panel->aux->drm_aux, DP_SINK_COUNT, - &count, count_len); - if (rlen == count_len) { - count = DP_GET_SINK_COUNT(count); - if (!count) { - pr_err("no downstream ports connected\n"); - panel->link->sink_count.count = 0; - rc = -ENOTCONN; - goto end; - } - } - } - - rc = dp_panel_read_edid(dp_panel, connector); - if (rc) { - pr_err("panel edid read failed, set failsafe mode\n"); - return rc; - } - - dp_panel->widebus_en = panel->parser->has_widebus; - dp_panel->dsc_feature_enable = panel->parser->dsc_feature_enable; - dp_panel->fec_feature_enable = panel->parser->fec_feature_enable; - - dp_panel_read_sink_dsc_caps(dp_panel); -end: - return rc; -} - -static u32 dp_panel_get_supported_bpp(struct dp_panel *dp_panel, - u32 mode_edid_bpp, u32 mode_pclk_khz) -{ - struct drm_dp_link *link_info; - const u32 max_supported_bpp = 30, min_supported_bpp = 18; - u32 bpp = 0, data_rate_khz = 0; - - bpp = min_t(u32, mode_edid_bpp, max_supported_bpp); - - link_info = &dp_panel->link_info; - data_rate_khz = link_info->num_lanes * link_info->rate * 8; - - while (bpp > min_supported_bpp) { - if (mode_pclk_khz * bpp <= data_rate_khz) - break; - bpp -= 6; - } - - return bpp; -} - -static u32 dp_panel_get_mode_bpp(struct dp_panel *dp_panel, - u32 mode_edid_bpp, u32 mode_pclk_khz) -{ - struct dp_panel_private *panel; - u32 bpp = mode_edid_bpp; - - if (!dp_panel || !mode_edid_bpp || !mode_pclk_khz) { - pr_err("invalid input\n"); - return 0; - } - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - - if (dp_panel->video_test) - bpp = dp_link_bit_depth_to_bpp( - panel->link->test_video.test_bit_depth); - else - bpp = dp_panel_get_supported_bpp(dp_panel, mode_edid_bpp, - mode_pclk_khz); - - return bpp; -} - -static void dp_panel_set_test_mode(struct dp_panel_private *panel, - struct dp_display_mode *mode) -{ - struct dp_panel_info *pinfo = NULL; - struct dp_link_test_video *test_info = NULL; - - if (!panel) { - pr_err("invalid params\n"); - return; - } - - pinfo = &mode->timing; - test_info = &panel->link->test_video; - - pinfo->h_active = test_info->test_h_width; - pinfo->h_sync_width = test_info->test_hsync_width; - pinfo->h_back_porch = test_info->test_h_start - - test_info->test_hsync_width; - pinfo->h_front_porch = test_info->test_h_total - - (test_info->test_h_start + test_info->test_h_width); - - pinfo->v_active = test_info->test_v_height; - pinfo->v_sync_width = test_info->test_vsync_width; - pinfo->v_back_porch = test_info->test_v_start - - test_info->test_vsync_width; - pinfo->v_front_porch = test_info->test_v_total - - (test_info->test_v_start + test_info->test_v_height); - - pinfo->bpp = dp_link_bit_depth_to_bpp(test_info->test_bit_depth); - pinfo->h_active_low = test_info->test_hsync_pol; - pinfo->v_active_low = test_info->test_vsync_pol; - - pinfo->refresh_rate = test_info->test_rr_n; - pinfo->pixel_clk_khz = test_info->test_h_total * - test_info->test_v_total * pinfo->refresh_rate; - - if (test_info->test_rr_d == 0) - pinfo->pixel_clk_khz /= 1000; - else - pinfo->pixel_clk_khz /= 1001; - - if (test_info->test_h_width == 640) - pinfo->pixel_clk_khz = 25170; -} - -static int dp_panel_get_modes(struct dp_panel *dp_panel, - struct drm_connector *connector, struct dp_display_mode *mode) -{ - struct dp_panel_private *panel; - - if (!dp_panel) { - pr_err("invalid input\n"); - return -EINVAL; - } - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - - if (dp_panel->video_test) { - dp_panel_set_test_mode(panel, mode); - return 1; - } else if (dp_panel->edid_ctrl->edid) { - return _sde_edid_update_modes(connector, dp_panel->edid_ctrl); - } - - /* fail-safe mode */ - memcpy(&mode->timing, &fail_safe, - sizeof(fail_safe)); - return 1; -} - -static void dp_panel_handle_sink_request(struct dp_panel *dp_panel) -{ - struct dp_panel_private *panel; - - if (!dp_panel) { - pr_err("invalid input\n"); - return; - } - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - - if (panel->link->sink_request & DP_TEST_LINK_EDID_READ) { - u8 checksum = sde_get_edid_checksum(dp_panel->edid_ctrl); - - panel->link->send_edid_checksum(panel->link, checksum); - panel->link->send_test_response(panel->link); - } -} - -static void dp_panel_tpg_config(struct dp_panel *dp_panel, bool enable) -{ - u32 hsync_start_x, hsync_end_x; - struct dp_catalog_panel *catalog; - struct dp_panel_private *panel; - struct dp_panel_info *pinfo; - - if (!dp_panel) { - pr_err("invalid input\n"); - return; - } - - if (dp_panel->stream_id >= DP_STREAM_MAX) { - pr_err("invalid stream id:%d\n", dp_panel->stream_id); - return; - } - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - catalog = panel->catalog; - pinfo = &panel->dp_panel.pinfo; - - if (!panel->panel_on) { - pr_debug("DP panel not enabled, handle TPG on next panel on\n"); - return; - } - - if (!enable) { - panel->catalog->tpg_config(catalog, false); - return; - } - - /* TPG config */ - catalog->hsync_period = pinfo->h_sync_width + pinfo->h_back_porch + - pinfo->h_active + pinfo->h_front_porch; - catalog->vsync_period = pinfo->v_sync_width + pinfo->v_back_porch + - pinfo->v_active + pinfo->v_front_porch; - - catalog->display_v_start = ((pinfo->v_sync_width + - pinfo->v_back_porch) * catalog->hsync_period); - catalog->display_v_end = ((catalog->vsync_period - - pinfo->v_front_porch) * catalog->hsync_period) - 1; - - catalog->display_v_start += pinfo->h_sync_width + pinfo->h_back_porch; - catalog->display_v_end -= pinfo->h_front_porch; - - hsync_start_x = pinfo->h_back_porch + pinfo->h_sync_width; - hsync_end_x = catalog->hsync_period - pinfo->h_front_porch - 1; - - catalog->v_sync_width = pinfo->v_sync_width; - - catalog->hsync_ctl = (catalog->hsync_period << 16) | - pinfo->h_sync_width; - catalog->display_hctl = (hsync_end_x << 16) | hsync_start_x; - - panel->catalog->tpg_config(catalog, true); -} - -static int dp_panel_config_timing(struct dp_panel *dp_panel) -{ - int rc = 0; - u32 data, total_ver, total_hor; - struct dp_catalog_panel *catalog; - struct dp_panel_private *panel; - struct dp_panel_info *pinfo; - - if (!dp_panel) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto end; - } - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - catalog = panel->catalog; - pinfo = &panel->dp_panel.pinfo; - - pr_debug("width=%d hporch= %d %d %d\n", - pinfo->h_active, pinfo->h_back_porch, - pinfo->h_front_porch, pinfo->h_sync_width); - - pr_debug("height=%d vporch= %d %d %d\n", - pinfo->v_active, pinfo->v_back_porch, - pinfo->v_front_porch, pinfo->v_sync_width); - - total_hor = pinfo->h_active + pinfo->h_back_porch + - pinfo->h_front_porch + pinfo->h_sync_width; - - total_ver = pinfo->v_active + pinfo->v_back_porch + - pinfo->v_front_porch + pinfo->v_sync_width; - - data = total_ver; - data <<= 16; - data |= total_hor; - - catalog->total = data; - - data = (pinfo->v_back_porch + pinfo->v_sync_width); - data <<= 16; - data |= (pinfo->h_back_porch + pinfo->h_sync_width); - - catalog->sync_start = data; - - data = pinfo->v_sync_width; - data <<= 16; - data |= (pinfo->v_active_low << 31); - data |= pinfo->h_sync_width; - data |= (pinfo->h_active_low << 15); - - catalog->width_blanking = data; - - data = pinfo->v_active; - data <<= 16; - data |= pinfo->h_active; - - catalog->dp_active = data; - - catalog->widebus_en = pinfo->widebus_en; - - panel->catalog->timing_cfg(catalog); - panel->panel_on = true; -end: - return rc; -} - -static u32 _dp_panel_calc_be_in_lane(struct dp_panel *dp_panel) -{ - struct dp_panel_info *pinfo; - struct msm_compression_info *comp_info; - u32 dsc_htot_byte_cnt, mod_result; - u32 numerator, denominator; - s64 temp_fp; - u32 be_in_lane = 10; - - pinfo = &dp_panel->pinfo; - comp_info = &pinfo->comp_info; - - if (!dp_panel->mst_state) - return be_in_lane; - - switch (pinfo->comp_info.comp_ratio) { - case MSM_DISPLAY_COMPRESSION_RATIO_2_TO_1: - denominator = 16; /* 2 * bits-in-byte */ - break; - case MSM_DISPLAY_COMPRESSION_RATIO_3_TO_1: - denominator = 24; /* 3 * bits-in-byte */ - break; - default: - denominator = 8; /* 1 * bits-in-byte */ - } - - numerator = (pinfo->h_active + pinfo->h_back_porch + - pinfo->h_front_porch + pinfo->h_sync_width) * - pinfo->bpp; - temp_fp = drm_fixp_from_fraction(numerator, denominator); - dsc_htot_byte_cnt = drm_fixp2int_ceil(temp_fp); - - mod_result = dsc_htot_byte_cnt % 12; - if (mod_result == 0) - be_in_lane = 8; - else if (mod_result <= 3) - be_in_lane = 1; - else if (mod_result <= 6) - be_in_lane = 2; - else if (mod_result <= 9) - be_in_lane = 4; - else if (mod_result <= 11) - be_in_lane = 8; - else - be_in_lane = 10; - - return be_in_lane; -} - -static void dp_panel_config_dsc(struct dp_panel *dp_panel, bool enable) -{ - struct dp_catalog_panel *catalog; - struct dp_panel_private *panel; - struct dp_panel_info *pinfo; - struct msm_compression_info *comp_info; - struct dp_dsc_cfg_data *dsc; - int pps_len; - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - - catalog = panel->catalog; - dsc = &catalog->dsc; - pinfo = &dp_panel->pinfo; - comp_info = &pinfo->comp_info; - - if (comp_info->comp_type == MSM_DISPLAY_COMPRESSION_DSC && enable) { - pps_len = dp_panel_dsc_create_pps_buf_cmd(&comp_info->dsc_info, - dsc->pps, 0); - dsc->pps_len = pps_len; - dp_panel_dsc_prepare_pps_packet(dp_panel); - - dsc->slice_per_pkt = comp_info->dsc_info.slice_per_pkt - 1; - dsc->bytes_per_pkt = comp_info->dsc_info.bytes_per_pkt; - dsc->bytes_per_pkt /= comp_info->dsc_info.slice_per_pkt; - dsc->eol_byte_num = comp_info->dsc_info.eol_byte_num; - dsc->dto_count = comp_info->dsc_info.pclk_per_line; - dsc->be_in_lane = _dp_panel_calc_be_in_lane(dp_panel); - dsc->dsc_en = true; - dsc->dto_en = true; - - _dp_panel_get_dto_m_n(comp_info->comp_ratio, pinfo->bpp, - &dsc->dto_n, &dsc->dto_d); - } else { - dsc->dsc_en = false; - dsc->dto_en = false; - dsc->dto_n = 0; - dsc->dto_d = 0; - } - - catalog->stream_id = dp_panel->stream_id; - catalog->dsc_cfg(catalog); - - if (catalog->dsc.dsc_en && enable) - catalog->pps_flush(catalog); -} - -static int dp_panel_edid_register(struct dp_panel_private *panel) -{ - int rc = 0; - - panel->dp_panel.edid_ctrl = sde_edid_init(); - if (!panel->dp_panel.edid_ctrl) { - pr_err("sde edid init for DP failed\n"); - rc = -ENOMEM; - } - - return rc; -} - -static void dp_panel_edid_deregister(struct dp_panel_private *panel) -{ - sde_edid_deinit((void **)&panel->dp_panel.edid_ctrl); -} - -static int dp_panel_set_stream_info(struct dp_panel *dp_panel, - enum dp_stream_id stream_id, u32 ch_start_slot, - u32 ch_tot_slots, u32 pbn, int vcpi) -{ - if (!dp_panel || stream_id > DP_STREAM_MAX) { - pr_err("invalid input. stream_id: %d\n", stream_id); - return -EINVAL; - } - - dp_panel->vcpi = vcpi; - dp_panel->stream_id = stream_id; - dp_panel->channel_start_slot = ch_start_slot; - dp_panel->channel_total_slots = ch_tot_slots; - dp_panel->pbn = pbn; - - return 0; -} - -static int dp_panel_init_panel_info(struct dp_panel *dp_panel) -{ - int rc = 0; - struct dp_panel_private *panel; - struct dp_panel_info *pinfo; - - if (!dp_panel) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto end; - } - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - pinfo = &dp_panel->pinfo; - - drm_dp_dpcd_writeb(panel->aux->drm_aux, DP_SET_POWER, DP_SET_POWER_D0); - - /* - * According to the DP 1.1 specification, a "Sink Device must exit the - * power saving state within 1 ms" (Section 2.5.3.1, Table 5-52, "Sink - * Control Field" (register 0x600). - */ - usleep_range(1000, 2000); - - drm_dp_link_probe(panel->aux->drm_aux, &dp_panel->link_info); -end: - return rc; -} - -static int dp_panel_deinit_panel_info(struct dp_panel *dp_panel, u32 flags) -{ - int rc = 0; - struct dp_panel_private *panel; - struct dp_catalog_hdr_data *hdr; - struct drm_connector *connector; - struct sde_connector_state *c_state; - - if (!dp_panel) { - pr_err("invalid input\n"); - return -EINVAL; - } - - if (flags & DP_PANEL_SRC_INITIATED_POWER_DOWN) { - pr_debug("retain states in src initiated power down request\n"); - return 0; - } - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - hdr = &panel->catalog->hdr_data; - - if (!panel->custom_edid && dp_panel->edid_ctrl->edid) - sde_free_edid((void **)&dp_panel->edid_ctrl); - - dp_panel_set_stream_info(dp_panel, DP_STREAM_MAX, 0, 0, 0, 0); - memset(&dp_panel->pinfo, 0, sizeof(dp_panel->pinfo)); - memset(&hdr->hdr_meta, 0, sizeof(hdr->hdr_meta)); - panel->panel_on = false; - - connector = dp_panel->connector; - c_state = to_sde_connector_state(connector->state); - - connector->hdr_eotf = 0; - connector->hdr_metadata_type_one = 0; - connector->hdr_max_luminance = 0; - connector->hdr_avg_luminance = 0; - connector->hdr_min_luminance = 0; - connector->hdr_supported = false; - connector->hdr_plus_app_ver = 0; - - memset(&c_state->hdr_meta, 0, sizeof(c_state->hdr_meta)); - memset(&c_state->dyn_hdr_meta, 0, sizeof(c_state->dyn_hdr_meta)); - - return rc; -} - -static u32 dp_panel_get_min_req_link_rate(struct dp_panel *dp_panel) -{ - const u32 encoding_factx10 = 8; - u32 min_link_rate_khz = 0, lane_cnt; - struct dp_panel_info *pinfo; - - if (!dp_panel) { - pr_err("invalid input\n"); - goto end; - } - - lane_cnt = dp_panel->link_info.num_lanes; - pinfo = &dp_panel->pinfo; - - /* num_lanes * lane_count * 8 >= pclk * bpp * 10 */ - min_link_rate_khz = pinfo->pixel_clk_khz / - (lane_cnt * encoding_factx10); - min_link_rate_khz *= pinfo->bpp; - - pr_debug("min lclk req=%d khz for pclk=%d khz, lanes=%d, bpp=%d\n", - min_link_rate_khz, pinfo->pixel_clk_khz, lane_cnt, - pinfo->bpp); -end: - return min_link_rate_khz; -} - -static bool dp_panel_hdr_supported(struct dp_panel *dp_panel) -{ - struct dp_panel_private *panel; - - if (!dp_panel) { - pr_err("invalid input\n"); - return false; - } - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - - return panel->major >= 1 && panel->vsc_supported && - (panel->minor >= 4 || panel->vscext_supported); -} - -static u32 dp_panel_calc_dhdr_pkt_limit(struct dp_panel *dp_panel, - struct dp_dhdr_maxpkt_calc_input *input) -{ - s64 mdpclk_fp = drm_fixp_from_fraction(input->mdp_clk, 1000000); - s64 lclk_fp = drm_fixp_from_fraction(input->lclk, 1000); - s64 pclk_fp = drm_fixp_from_fraction(input->pclk, 1000); - s64 nlanes_fp = drm_int2fixp(input->nlanes); - s64 target_sc = input->mst_target_sc; - s64 hactive_fp = drm_int2fixp(input->h_active); - const s64 i1_fp = DRM_FIXED_ONE; - const s64 i2_fp = drm_int2fixp(2); - const s64 i10_fp = drm_int2fixp(10); - const s64 i56_fp = drm_int2fixp(56); - const s64 i64_fp = drm_int2fixp(64); - s64 mst_bw_fp = i1_fp; - s64 fec_factor_fp = i1_fp; - s64 mst_bw64_fp, mst_bw64_ceil_fp, nlanes56_fp; - u32 f1, f2, f3, f4, f5, deploy_period, target_period; - s64 f3_f5_slot_fp; - u32 calc_pkt_limit; - const u32 max_pkt_limit = 64; - - if (input->fec_en && input->mst_en) - fec_factor_fp = drm_fixp_from_fraction(64000, 65537); - - if (input->mst_en) - mst_bw_fp = drm_fixp_div(target_sc, i64_fp); - - f1 = drm_fixp2int_ceil(drm_fixp_div(drm_fixp_mul(i10_fp, lclk_fp), - mdpclk_fp)); - f2 = drm_fixp2int_ceil(drm_fixp_div(drm_fixp_mul(i2_fp, lclk_fp), - mdpclk_fp)) + drm_fixp2int_ceil(drm_fixp_div( - drm_fixp_mul(i1_fp, lclk_fp), mdpclk_fp)); - - mst_bw64_fp = drm_fixp_mul(mst_bw_fp, i64_fp); - if (drm_fixp2int(mst_bw64_fp) == 0) - f3_f5_slot_fp = drm_fixp_div(i1_fp, drm_int2fixp( - drm_fixp2int_ceil(drm_fixp_div( - i1_fp, mst_bw64_fp)))); - else - f3_f5_slot_fp = drm_int2fixp(drm_fixp2int(mst_bw_fp)); - - mst_bw64_ceil_fp = drm_int2fixp(drm_fixp2int_ceil(mst_bw64_fp)); - f3 = drm_fixp2int(drm_fixp_mul(drm_int2fixp(drm_fixp2int( - drm_fixp_div(i2_fp, f3_f5_slot_fp)) + 1), - (i64_fp - mst_bw64_ceil_fp))) + 2; - - if (!input->mst_en) { - f4 = 1 + drm_fixp2int(drm_fixp_div(drm_int2fixp(50), - nlanes_fp)) + drm_fixp2int(drm_fixp_div( - nlanes_fp, i2_fp)); - f5 = 0; - } else { - f4 = 0; - nlanes56_fp = drm_fixp_div(i56_fp, nlanes_fp); - f5 = drm_fixp2int(drm_fixp_mul(drm_int2fixp(drm_fixp2int( - drm_fixp_div(i1_fp + nlanes56_fp, - f3_f5_slot_fp)) + 1), (i64_fp - - mst_bw64_ceil_fp + i1_fp + nlanes56_fp))); - } - - deploy_period = f1 + f2 + f3 + f4 + f5 + 19; - target_period = drm_fixp2int(drm_fixp_mul(fec_factor_fp, drm_fixp_mul( - hactive_fp, drm_fixp_div(lclk_fp, pclk_fp)))); - - calc_pkt_limit = target_period / deploy_period; - - pr_debug("input: %d, %d, %d, %d, %d, 0x%llx, %d, %d\n", - input->mdp_clk, input->lclk, input->pclk, input->h_active, - input->nlanes, input->mst_target_sc, input->mst_en ? 1 : 0, - input->fec_en ? 1 : 0); - pr_debug("factors: %d, %d, %d, %d, %d\n", f1, f2, f3, f4, f5); - pr_debug("d_p: %d, t_p: %d, maxPkts: %d%s\n", deploy_period, - target_period, calc_pkt_limit, calc_pkt_limit > max_pkt_limit ? - " CAPPED" : ""); - - if (calc_pkt_limit > max_pkt_limit) - calc_pkt_limit = max_pkt_limit; - - pr_debug("packet limit per line = %d\n", calc_pkt_limit); - return calc_pkt_limit; -} - -static int dp_panel_setup_hdr(struct dp_panel *dp_panel, - struct drm_msm_ext_hdr_metadata *hdr_meta, - bool dhdr_update, u64 core_clk_rate) -{ - int rc = 0, max_pkts = 0; - struct dp_panel_private *panel; - struct dp_catalog_hdr_data *hdr; - struct dp_dhdr_maxpkt_calc_input input; - - if (!dp_panel) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto end; - } - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - hdr = &panel->catalog->hdr_data; - - /* use cached meta data in case meta data not provided */ - if (!hdr_meta) { - if (hdr->hdr_meta.hdr_state) - goto cached; - else - goto end; - } - - panel->hdr_state = hdr_meta->hdr_state; - - hdr->vsc_header_byte0 = 0x00; - hdr->vsc_header_byte1 = 0x07; - hdr->vsc_header_byte2 = 0x05; - hdr->vsc_header_byte3 = 0x13; - - hdr->shdr_header_byte0 = 0x00; - hdr->shdr_header_byte1 = 0x87; - hdr->shdr_header_byte2 = 0x1D; - hdr->shdr_header_byte3 = 0x13 << 2; - - /* VSC SDP Payload for DB16 */ - hdr->pixel_encoding = RGB; - hdr->colorimetry = ITU_R_BT_2020_RGB; - - /* VSC SDP Payload for DB17 */ - hdr->dynamic_range = CEA; - - /* VSC SDP Payload for DB18 */ - hdr->content_type = GRAPHICS; - - hdr->bpc = dp_panel->pinfo.bpp / 3; - - hdr->version = 0x01; - hdr->length = 0x1A; - - if (panel->hdr_state) - memcpy(&hdr->hdr_meta, hdr_meta, sizeof(hdr->hdr_meta)); - else - memset(&hdr->hdr_meta, 0, sizeof(hdr->hdr_meta)); -cached: - if (dhdr_update) { - hdr->vscext_header_byte0 = 0x00; - hdr->vscext_header_byte1 = 0x81; - hdr->vscext_header_byte2 = 0x1D; - hdr->vscext_header_byte3 = 0x13 << 2; - - input.mdp_clk = core_clk_rate; - input.lclk = dp_panel->link_info.rate; - input.nlanes = dp_panel->link_info.num_lanes; - input.pclk = dp_panel->pinfo.pixel_clk_khz; - input.h_active = dp_panel->pinfo.h_active; - input.mst_target_sc = dp_panel->mst_target_sc; - input.mst_en = dp_panel->mst_state; - input.fec_en = dp_panel->fec_en; - max_pkts = dp_panel_calc_dhdr_pkt_limit(dp_panel, &input); - } - - if (panel->panel_on) { - panel->catalog->stream_id = dp_panel->stream_id; - panel->catalog->config_hdr(panel->catalog, panel->hdr_state, - max_pkts); - if (dhdr_update) - panel->catalog->dhdr_flush(panel->catalog); - } -end: - return rc; -} - -static int dp_panel_spd_config(struct dp_panel *dp_panel) -{ - int rc = 0; - struct dp_panel_private *panel; - - if (!dp_panel) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto end; - } - - if (dp_panel->stream_id >= DP_STREAM_MAX) { - pr_err("invalid stream id:%d\n", dp_panel->stream_id); - return -EINVAL; - } - - if (!dp_panel->spd_enabled) { - pr_debug("SPD Infoframe not enabled\n"); - goto end; - } - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - - panel->catalog->spd_vendor_name = panel->spd_vendor_name; - panel->catalog->spd_product_description = - panel->spd_product_description; - - panel->catalog->stream_id = dp_panel->stream_id; - panel->catalog->config_spd(panel->catalog); -end: - return rc; -} - -static void dp_panel_config_ctrl(struct dp_panel *dp_panel) -{ - u32 config = 0, tbd; - u8 *dpcd = dp_panel->dpcd; - struct dp_panel_private *panel; - struct dp_catalog_panel *catalog; - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - catalog = panel->catalog; - - config |= (2 << 13); /* Default-> LSCLK DIV: 1/4 LCLK */ - config |= (0 << 11); /* RGB */ - - tbd = panel->link->get_test_bits_depth(panel->link, - dp_panel->pinfo.bpp); - - if (tbd == DP_TEST_BIT_DEPTH_UNKNOWN) - tbd = DP_TEST_BIT_DEPTH_8; - - config |= tbd << 8; - - /* Num of Lanes */ - config |= ((panel->link->link_params.lane_count - 1) << 4); - - if (drm_dp_enhanced_frame_cap(dpcd)) - config |= 0x40; - - config |= 0x04; /* progressive video */ - - config |= 0x03; /* sycn clock & static Mvid */ - - catalog->config_ctrl(catalog, config); -} - -static void dp_panel_config_misc(struct dp_panel *dp_panel) -{ - struct dp_panel_private *panel; - struct dp_catalog_panel *catalog; - u32 misc_val; - u32 tb, cc; - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - catalog = panel->catalog; - - tb = panel->link->get_test_bits_depth(panel->link, dp_panel->pinfo.bpp); - cc = panel->link->get_colorimetry_config(panel->link); - - misc_val = cc; - misc_val |= (tb << 5); - misc_val |= BIT(0); /* Configure clock to synchronous mode */ - - catalog->misc_val = misc_val; - catalog->config_misc(catalog); -} - -static void dp_panel_config_msa(struct dp_panel *dp_panel) -{ - struct dp_panel_private *panel; - struct dp_catalog_panel *catalog; - u32 rate; - u32 stream_rate_khz; - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - catalog = panel->catalog; - - catalog->widebus_en = dp_panel->widebus_en; - - rate = drm_dp_bw_code_to_link_rate(panel->link->link_params.bw_code); - stream_rate_khz = dp_panel->pinfo.pixel_clk_khz; - - catalog->config_msa(catalog, rate, stream_rate_khz); -} - -static void dp_panel_resolution_info(struct dp_panel_private *panel) -{ - struct dp_panel_info *pinfo = &panel->dp_panel.pinfo; - - /* - * print resolution info as this is a result - * of user initiated action of cable connection - */ - pr_info("DP RESOLUTION: active(back|front|width|low)\n"); - pr_info("%d(%d|%d|%d|%d)x%d(%d|%d|%d|%d)@%dfps %dbpp %dKhz %dLR %dLn\n", - pinfo->h_active, pinfo->h_back_porch, pinfo->h_front_porch, - pinfo->h_sync_width, pinfo->h_active_low, - pinfo->v_active, pinfo->v_back_porch, pinfo->v_front_porch, - pinfo->v_sync_width, pinfo->v_active_low, - pinfo->refresh_rate, pinfo->bpp, pinfo->pixel_clk_khz, - panel->link->link_params.bw_code, - panel->link->link_params.lane_count); -} - -static int dp_panel_hw_cfg(struct dp_panel *dp_panel, bool enable) -{ - struct dp_panel_private *panel; - - if (!dp_panel) { - pr_err("invalid input\n"); - return -EINVAL; - } - - if (dp_panel->stream_id >= DP_STREAM_MAX) { - pr_err("invalid stream_id: %d\n", dp_panel->stream_id); - return -EINVAL; - } - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - panel->catalog->stream_id = dp_panel->stream_id; - - if (enable) { - dp_panel_config_ctrl(dp_panel); - dp_panel_config_misc(dp_panel); - dp_panel_config_msa(dp_panel); - dp_panel_config_dsc(dp_panel, enable); - dp_panel_config_tr_unit(dp_panel); - dp_panel_config_timing(dp_panel); - dp_panel_resolution_info(panel); - } - - panel->catalog->config_dto(panel->catalog, !enable); - - return 0; -} - -static int dp_panel_read_sink_sts(struct dp_panel *dp_panel, u8 *sts, u32 size) -{ - int rlen, rc = 0; - struct dp_panel_private *panel; - - if (!dp_panel || !sts || !size) { - pr_err("invalid input\n"); - rc = -EINVAL; - return rc; - } - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - - rlen = drm_dp_dpcd_read(panel->aux->drm_aux, DP_SINK_COUNT_ESI, - sts, size); - if (rlen != size) { - pr_err("dpcd sink sts fail rlen:%d size:%d\n", rlen, size); - rc = -EINVAL; - return rc; - } - - return 0; -} - -static int dp_panel_update_edid(struct dp_panel *dp_panel, struct edid *edid) -{ - int rc; - - dp_panel->edid_ctrl->edid = edid; - sde_parse_edid(dp_panel->edid_ctrl); - - rc = _sde_edid_update_modes(dp_panel->connector, dp_panel->edid_ctrl); - dp_panel->audio_supported = drm_detect_monitor_audio(edid); - - return rc; -} - -static bool dp_panel_read_mst_cap(struct dp_panel *dp_panel) -{ - int rlen; - struct dp_panel_private *panel; - u8 dpcd; - bool mst_cap = false; - - if (!dp_panel) { - pr_err("invalid input\n"); - goto end; - } - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - - rlen = drm_dp_dpcd_read(panel->aux->drm_aux, DP_MSTM_CAP, - &dpcd, 1); - if (rlen < 1) { - pr_err("dpcd mstm_cap read failed, rlen=%d\n", rlen); - goto end; - } - - mst_cap = (dpcd & DP_MST_CAP) ? true : false; - -end: - pr_debug("dp mst-cap: %d\n", mst_cap); - - return mst_cap; -} - -static void dp_panel_convert_to_dp_mode(struct dp_panel *dp_panel, - const struct drm_display_mode *drm_mode, - struct dp_display_mode *dp_mode) -{ - const u32 num_components = 3, default_bpp = 24; - struct msm_compression_info *comp_info; - bool dsc_cap = (dp_mode->capabilities & DP_PANEL_CAPS_DSC) ? - true : false; - - dp_mode->timing.h_active = drm_mode->hdisplay; - dp_mode->timing.h_back_porch = drm_mode->htotal - drm_mode->hsync_end; - dp_mode->timing.h_sync_width = drm_mode->htotal - - (drm_mode->hsync_start + dp_mode->timing.h_back_porch); - dp_mode->timing.h_front_porch = drm_mode->hsync_start - - drm_mode->hdisplay; - dp_mode->timing.h_skew = drm_mode->hskew; - - dp_mode->timing.v_active = drm_mode->vdisplay; - dp_mode->timing.v_back_porch = drm_mode->vtotal - drm_mode->vsync_end; - dp_mode->timing.v_sync_width = drm_mode->vtotal - - (drm_mode->vsync_start + dp_mode->timing.v_back_porch); - - dp_mode->timing.v_front_porch = drm_mode->vsync_start - - drm_mode->vdisplay; - - dp_mode->timing.refresh_rate = drm_mode->vrefresh; - - dp_mode->timing.pixel_clk_khz = drm_mode->clock; - - dp_mode->timing.v_active_low = - !!(drm_mode->flags & DRM_MODE_FLAG_NVSYNC); - - dp_mode->timing.h_active_low = - !!(drm_mode->flags & DRM_MODE_FLAG_NHSYNC); - - dp_mode->timing.bpp = - dp_panel->connector->display_info.bpc * num_components; - if (!dp_mode->timing.bpp) - dp_mode->timing.bpp = default_bpp; - - dp_mode->timing.bpp = dp_panel_get_mode_bpp(dp_panel, - dp_mode->timing.bpp, dp_mode->timing.pixel_clk_khz); - - dp_mode->timing.widebus_en = dp_panel->widebus_en; - dp_mode->timing.dsc_overhead_fp = 0; - - if (dp_panel->dsc_en && dsc_cap) { - comp_info = &dp_mode->timing.comp_info; - - if (dp_panel_dsc_prepare_basic_params(comp_info, - dp_mode, dp_panel)) { - pr_debug("prepare DSC basic params failed\n"); - return; - } - - dp_panel_dsc_populate_static_params(&comp_info->dsc_info); - dp_panel_dsc_pclk_param_calc(dp_panel, - &comp_info->dsc_info, - comp_info->comp_ratio, - dp_mode); - } - dp_mode->fec_overhead_fp = dp_panel->fec_overhead_fp; -} - -static void dp_panel_update_pps(struct dp_panel *dp_panel, char *pps_cmd) -{ - struct dp_catalog_panel *catalog; - struct dp_panel_private *panel; - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - - catalog = panel->catalog; - catalog->stream_id = dp_panel->stream_id; - catalog->pps_flush(catalog); -} - -struct dp_panel *dp_panel_get(struct dp_panel_in *in) -{ - int rc = 0; - struct dp_panel_private *panel; - struct dp_panel *dp_panel; - struct sde_connector *sde_conn; - - if (!in->dev || !in->catalog || !in->aux || - !in->link || !in->connector) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto error; - } - - panel = devm_kzalloc(in->dev, sizeof(*panel), GFP_KERNEL); - if (!panel) { - rc = -ENOMEM; - goto error; - } - - panel->dev = in->dev; - panel->aux = in->aux; - panel->catalog = in->catalog; - panel->link = in->link; - panel->parser = in->parser; - - dp_panel = &panel->dp_panel; - dp_panel->max_bw_code = DP_LINK_BW_8_1; - dp_panel->spd_enabled = true; - memcpy(panel->spd_vendor_name, vendor_name, (sizeof(u8) * 8)); - memcpy(panel->spd_product_description, product_desc, (sizeof(u8) * 16)); - dp_panel->connector = in->connector; - - dp_panel->dsc_feature_enable = panel->parser->dsc_feature_enable; - dp_panel->fec_feature_enable = panel->parser->fec_feature_enable; - - if (in->base_panel) { - memcpy(dp_panel->dpcd, in->base_panel->dpcd, - DP_RECEIVER_CAP_SIZE + 1); - memcpy(dp_panel->dsc_dpcd, in->base_panel->dsc_dpcd, - DP_RECEIVER_DSC_CAP_SIZE + 1); - memcpy(&dp_panel->link_info, &in->base_panel->link_info, - sizeof(dp_panel->link_info)); - dp_panel->mst_state = in->base_panel->mst_state; - dp_panel->widebus_en = in->base_panel->widebus_en; - dp_panel->fec_en = in->base_panel->fec_en; - dp_panel->dsc_en = in->base_panel->dsc_en; - dp_panel->fec_overhead_fp = in->base_panel->fec_overhead_fp; - } - - dp_panel->init = dp_panel_init_panel_info; - dp_panel->deinit = dp_panel_deinit_panel_info; - dp_panel->hw_cfg = dp_panel_hw_cfg; - dp_panel->read_sink_caps = dp_panel_read_sink_caps; - dp_panel->get_min_req_link_rate = dp_panel_get_min_req_link_rate; - dp_panel->get_mode_bpp = dp_panel_get_mode_bpp; - dp_panel->get_modes = dp_panel_get_modes; - dp_panel->handle_sink_request = dp_panel_handle_sink_request; - dp_panel->set_edid = dp_panel_set_edid; - dp_panel->set_dpcd = dp_panel_set_dpcd; - dp_panel->tpg_config = dp_panel_tpg_config; - dp_panel->spd_config = dp_panel_spd_config; - dp_panel->setup_hdr = dp_panel_setup_hdr; - dp_panel->hdr_supported = dp_panel_hdr_supported; - dp_panel->set_stream_info = dp_panel_set_stream_info; - dp_panel->read_sink_status = dp_panel_read_sink_sts; - dp_panel->update_edid = dp_panel_update_edid; - dp_panel->read_mst_cap = dp_panel_read_mst_cap; - dp_panel->convert_to_dp_mode = dp_panel_convert_to_dp_mode; - dp_panel->update_pps = dp_panel_update_pps; - - sde_conn = to_sde_connector(dp_panel->connector); - sde_conn->drv_panel = dp_panel; - - dp_panel_edid_register(panel); - - return dp_panel; -error: - return ERR_PTR(rc); -} - -void dp_panel_put(struct dp_panel *dp_panel) -{ - struct dp_panel_private *panel; - - if (!dp_panel) - return; - - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - - dp_panel_edid_deregister(panel); - devm_kfree(panel->dev, panel); -} diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h deleted file mode 100644 index dc96090ba5c5d0ad307b47568c9f23b29a13f09a..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ /dev/null @@ -1,229 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. - */ - -#ifndef _DP_PANEL_H_ -#define _DP_PANEL_H_ - -#include - -#include "dp_aux.h" -#include "dp_link.h" -#include "dp_usbpd.h" -#include "sde_edid_parser.h" -#include "sde_connector.h" -#include "msm_drv.h" - -#define DP_RECEIVER_DSC_CAP_SIZE 15 -#define DP_RECEIVER_FEC_STATUS_SIZE 3 - -/* - * A source initiated power down flag is set - * when the DP is powered off while physical - * DP cable is still connected i.e. without - * HPD or not initiated by sink like HPD_IRQ. - * This can happen if framework reboots or - * device suspends. - */ -#define DP_PANEL_SRC_INITIATED_POWER_DOWN BIT(0) - -enum dp_lane_count { - DP_LANE_COUNT_1 = 1, - DP_LANE_COUNT_2 = 2, - DP_LANE_COUNT_4 = 4, -}; - -#define DP_MAX_DOWNSTREAM_PORTS 0x10 - -struct dp_panel_info { - u32 h_active; - u32 v_active; - u32 h_back_porch; - u32 h_front_porch; - u32 h_sync_width; - u32 h_active_low; - u32 v_back_porch; - u32 v_front_porch; - u32 v_sync_width; - u32 v_active_low; - u32 h_skew; - u32 refresh_rate; - u32 pixel_clk_khz; - u32 bpp; - bool widebus_en; - struct msm_compression_info comp_info; - s64 dsc_overhead_fp; -}; - -struct dp_display_mode { - struct dp_panel_info timing; - u32 capabilities; - s64 fec_overhead_fp; - s64 dsc_overhead_fp; -}; - -struct dp_panel; - -struct dp_panel_in { - struct device *dev; - struct dp_aux *aux; - struct dp_link *link; - struct dp_catalog_panel *catalog; - struct drm_connector *connector; - struct dp_panel *base_panel; - struct dp_parser *parser; -}; - -struct dp_dsc_caps { - bool dsc_capable; - u8 version; - bool block_pred_en; -}; - -struct dp_audio; - -#define DP_PANEL_CAPS_DSC BIT(0) - -struct dp_panel { - /* dpcd raw data */ - u8 dpcd[DP_RECEIVER_CAP_SIZE + 1]; - u8 ds_ports[DP_MAX_DOWNSTREAM_PORTS]; - u8 dsc_dpcd[DP_RECEIVER_DSC_CAP_SIZE + 1]; - u8 fec_dpcd; - u8 fec_sts_dpcd[DP_RECEIVER_FEC_STATUS_SIZE + 1]; - - struct drm_dp_link link_info; - struct sde_edid_ctrl *edid_ctrl; - struct dp_panel_info pinfo; - bool video_test; - bool spd_enabled; - - u32 vic; - u32 max_pclk_khz; - s64 mst_target_sc; - - /* debug */ - u32 max_bw_code; - - /* By default, stream_id is assigned to DP_INVALID_STREAM. - * Client sets the stream id value using set_stream_id interface. - */ - enum dp_stream_id stream_id; - int vcpi; - - u32 channel_start_slot; - u32 channel_total_slots; - u32 pbn; - - u32 tot_dsc_blks_in_use; - /* DRM connector assosiated with this panel */ - struct drm_connector *connector; - - struct dp_audio *audio; - bool audio_supported; - - struct dp_dsc_caps sink_dsc_caps; - bool dsc_feature_enable; - bool fec_feature_enable; - bool dsc_en; - bool fec_en; - bool widebus_en; - bool mst_state; - - s64 fec_overhead_fp; - - int (*init)(struct dp_panel *dp_panel); - int (*deinit)(struct dp_panel *dp_panel, u32 flags); - int (*hw_cfg)(struct dp_panel *dp_panel, bool enable); - int (*read_sink_caps)(struct dp_panel *dp_panel, - struct drm_connector *connector, bool multi_func); - u32 (*get_min_req_link_rate)(struct dp_panel *dp_panel); - u32 (*get_mode_bpp)(struct dp_panel *dp_panel, u32 mode_max_bpp, - u32 mode_pclk_khz); - int (*get_modes)(struct dp_panel *dp_panel, - struct drm_connector *connector, struct dp_display_mode *mode); - void (*handle_sink_request)(struct dp_panel *dp_panel); - int (*set_edid)(struct dp_panel *dp_panel, u8 *edid); - int (*set_dpcd)(struct dp_panel *dp_panel, u8 *dpcd); - int (*setup_hdr)(struct dp_panel *dp_panel, - struct drm_msm_ext_hdr_metadata *hdr_meta, - bool dhdr_update, u64 core_clk_rate); - void (*tpg_config)(struct dp_panel *dp_panel, bool enable); - int (*spd_config)(struct dp_panel *dp_panel); - bool (*hdr_supported)(struct dp_panel *dp_panel); - - int (*set_stream_info)(struct dp_panel *dp_panel, - enum dp_stream_id stream_id, u32 ch_start_slot, - u32 ch_tot_slots, u32 pbn, int vcpi); - - int (*read_sink_status)(struct dp_panel *dp_panel, u8 *sts, u32 size); - int (*update_edid)(struct dp_panel *dp_panel, struct edid *edid); - bool (*read_mst_cap)(struct dp_panel *dp_panel); - void (*convert_to_dp_mode)(struct dp_panel *dp_panel, - const struct drm_display_mode *drm_mode, - struct dp_display_mode *dp_mode); - void (*update_pps)(struct dp_panel *dp_panel, char *pps_cmd); -}; - -struct dp_tu_calc_input { - u64 lclk; /* 162, 270, 540 and 810 */ - u64 pclk_khz; /* in KHz */ - u64 hactive; /* active h-width */ - u64 hporch; /* bp + fp + pulse */ - int nlanes; /* no.of.lanes */ - int bpp; /* bits */ - int pixel_enc; /* 444, 420, 422 */ - int dsc_en; /* dsc on/off */ - int async_en; /* async mode */ - int fec_en; /* fec */ - int compress_ratio; /* 2:1 = 200, 3:1 = 300, 3.75:1 = 375 */ - int num_of_dsc_slices; /* number of slices per line */ -}; - -struct dp_vc_tu_mapping_table { - u32 vic; - u8 lanes; - u8 lrate; /* DP_LINK_RATE -> 162(6), 270(10), 540(20), 810 (30) */ - u8 bpp; - u32 valid_boundary_link; - u32 delay_start_link; - bool boundary_moderation_en; - u32 valid_lower_boundary_link; - u32 upper_boundary_count; - u32 lower_boundary_count; - u32 tu_size_minus1; -}; - -/** - * is_link_rate_valid() - validates the link rate - * @lane_rate: link rate requested by the sink - * - * Returns true if the requested link rate is supported. - */ -static inline bool is_link_rate_valid(u32 bw_code) -{ - return ((bw_code == DP_LINK_BW_1_62) || - (bw_code == DP_LINK_BW_2_7) || - (bw_code == DP_LINK_BW_5_4) || - (bw_code == DP_LINK_BW_8_1)); -} - -/** - * dp_link_is_lane_count_valid() - validates the lane count - * @lane_count: lane count requested by the sink - * - * Returns true if the requested lane count is supported. - */ -static inline bool is_lane_count_valid(u32 lane_count) -{ - return (lane_count == DP_LANE_COUNT_1) || - (lane_count == DP_LANE_COUNT_2) || - (lane_count == DP_LANE_COUNT_4); -} - -struct dp_panel *dp_panel_get(struct dp_panel_in *in); -void dp_panel_put(struct dp_panel *dp_panel); -void dp_panel_calc_tu_test(struct dp_tu_calc_input *in, - struct dp_vc_tu_mapping_table *tu_table); -#endif /* _DP_PANEL_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c deleted file mode 100644 index bc4369dc780374a2243893c6012348faa86e378e..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ /dev/null @@ -1,933 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ - -#include -#include - -#include "dp_parser.h" - -static void dp_parser_unmap_io_resources(struct dp_parser *parser) -{ - int i = 0; - struct dp_io *io = &parser->io; - - for (i = 0; i < io->len; i++) - msm_dss_iounmap(&io->data[i].io); -} - -static int dp_parser_reg(struct dp_parser *parser) -{ - int rc = 0, i = 0; - u32 reg_count; - struct platform_device *pdev = parser->pdev; - struct dp_io *io = &parser->io; - struct device *dev = &pdev->dev; - - reg_count = of_property_count_strings(dev->of_node, "reg-names"); - if (reg_count <= 0) { - pr_err("no reg defined\n"); - return -EINVAL; - } - - io->len = reg_count; - io->data = devm_kzalloc(dev, sizeof(struct dp_io_data) * reg_count, - GFP_KERNEL); - if (!io->data) - return -ENOMEM; - - for (i = 0; i < reg_count; i++) { - of_property_read_string_index(dev->of_node, - "reg-names", i, &io->data[i].name); - rc = msm_dss_ioremap_byname(pdev, &io->data[i].io, - io->data[i].name); - if (rc) { - pr_err("unable to remap %s resources\n", - io->data[i].name); - goto err; - } - } - - return 0; -err: - dp_parser_unmap_io_resources(parser); - return rc; -} - -static const char *dp_get_phy_aux_config_property(u32 cfg_type) -{ - switch (cfg_type) { - case PHY_AUX_CFG0: - return "qcom,aux-cfg0-settings"; - case PHY_AUX_CFG1: - return "qcom,aux-cfg1-settings"; - case PHY_AUX_CFG2: - return "qcom,aux-cfg2-settings"; - case PHY_AUX_CFG3: - return "qcom,aux-cfg3-settings"; - case PHY_AUX_CFG4: - return "qcom,aux-cfg4-settings"; - case PHY_AUX_CFG5: - return "qcom,aux-cfg5-settings"; - case PHY_AUX_CFG6: - return "qcom,aux-cfg6-settings"; - case PHY_AUX_CFG7: - return "qcom,aux-cfg7-settings"; - case PHY_AUX_CFG8: - return "qcom,aux-cfg8-settings"; - case PHY_AUX_CFG9: - return "qcom,aux-cfg9-settings"; - default: - return "unknown"; - } -} - -static void dp_parser_phy_aux_cfg_reset(struct dp_parser *parser) -{ - int i = 0; - - for (i = 0; i < PHY_AUX_CFG_MAX; i++) - parser->aux_cfg[i] = (const struct dp_aux_cfg){ 0 }; -} - -static int dp_parser_aux(struct dp_parser *parser) -{ - struct device_node *of_node = parser->pdev->dev.of_node; - int len = 0, i = 0, j = 0, config_count = 0; - const char *data; - int const minimum_config_count = 1; - - for (i = 0; i < PHY_AUX_CFG_MAX; i++) { - const char *property = dp_get_phy_aux_config_property(i); - - data = of_get_property(of_node, property, &len); - if (!data) { - pr_err("Unable to read %s\n", property); - goto error; - } - - config_count = len - 1; - if ((config_count < minimum_config_count) || - (config_count > DP_AUX_CFG_MAX_VALUE_CNT)) { - pr_err("Invalid config count (%d) configs for %s\n", - config_count, property); - goto error; - } - - parser->aux_cfg[i].offset = data[0]; - parser->aux_cfg[i].cfg_cnt = config_count; - pr_debug("%s offset=0x%x, cfg_cnt=%d\n", - property, - parser->aux_cfg[i].offset, - parser->aux_cfg[i].cfg_cnt); - for (j = 1; j < len; j++) { - parser->aux_cfg[i].lut[j - 1] = data[j]; - pr_debug("%s lut[%d]=0x%x\n", - property, - i, - parser->aux_cfg[i].lut[j - 1]); - } - } - return 0; - -error: - dp_parser_phy_aux_cfg_reset(parser); - return -EINVAL; -} - -static int dp_parser_misc(struct dp_parser *parser) -{ - int rc = 0, len = 0, i = 0; - const char *data = NULL; - - struct device_node *of_node = parser->pdev->dev.of_node; - - data = of_get_property(of_node, "qcom,logical2physical-lane-map", &len); - if (data && (len == DP_MAX_PHY_LN)) { - for (i = 0; i < len; i++) - parser->l_map[i] = data[i]; - } - - data = of_get_property(of_node, "qcom,pn-swap-lane-map", &len); - if (data && (len == DP_MAX_PHY_LN)) { - for (i = 0; i < len; i++) - parser->l_pnswap |= (data[i] & 0x01) << i; - } - - rc = of_property_read_u32(of_node, - "qcom,max-pclk-frequency-khz", &parser->max_pclk_khz); - if (rc) - parser->max_pclk_khz = DP_MAX_PIXEL_CLK_KHZ; - - rc = of_property_read_u32(of_node, - "qcom,max-lclk-frequency-khz", &parser->max_lclk_khz); - if (rc) - parser->max_lclk_khz = DP_MAX_LINK_CLK_KHZ; - - return 0; -} - -static int dp_parser_msm_hdcp_dev(struct dp_parser *parser) -{ - struct device_node *node; - struct platform_device *pdev; - - node = of_find_compatible_node(NULL, NULL, "qcom,msm-hdcp"); - if (!node) { - // This is a non-fatal error, module initialization can proceed - pr_warn("couldn't find msm-hdcp node\n"); - return 0; - } - - pdev = of_find_device_by_node(node); - if (!pdev) { - // This is a non-fatal error, module initialization can proceed - pr_warn("couldn't find msm-hdcp pdev\n"); - return 0; - } - - parser->msm_hdcp_dev = &pdev->dev; - - return 0; -} - -static int dp_parser_pinctrl(struct dp_parser *parser) -{ - int rc = 0; - struct dp_pinctrl *pinctrl = &parser->pinctrl; - - pinctrl->pin = devm_pinctrl_get(&parser->pdev->dev); - - if (IS_ERR_OR_NULL(pinctrl->pin)) { - pr_debug("failed to get pinctrl, rc=%d\n", rc); - goto error; - } - - if (parser->no_aux_switch && parser->lphw_hpd) { - pinctrl->state_hpd_tlmm = pinctrl->state_hpd_ctrl = NULL; - - pinctrl->state_hpd_tlmm = pinctrl_lookup_state(pinctrl->pin, - "mdss_dp_hpd_tlmm"); - if (!IS_ERR_OR_NULL(pinctrl->state_hpd_tlmm)) { - pinctrl->state_hpd_ctrl = pinctrl_lookup_state( - pinctrl->pin, "mdss_dp_hpd_ctrl"); - } - - if (!pinctrl->state_hpd_tlmm || !pinctrl->state_hpd_ctrl) { - pinctrl->state_hpd_tlmm = NULL; - pinctrl->state_hpd_ctrl = NULL; - pr_debug("tlmm or ctrl pinctrl state does not exist\n"); - } - } - - pinctrl->state_active = pinctrl_lookup_state(pinctrl->pin, - "mdss_dp_active"); - if (IS_ERR_OR_NULL(pinctrl->state_active)) { - rc = PTR_ERR(pinctrl->state_active); - pr_err("failed to get pinctrl active state, rc=%d\n", rc); - goto error; - } - - pinctrl->state_suspend = pinctrl_lookup_state(pinctrl->pin, - "mdss_dp_sleep"); - if (IS_ERR_OR_NULL(pinctrl->state_suspend)) { - rc = PTR_ERR(pinctrl->state_suspend); - pr_err("failed to get pinctrl suspend state, rc=%d\n", rc); - goto error; - } -error: - return rc; -} - -static int dp_parser_gpio(struct dp_parser *parser) -{ - int i = 0; - struct device *dev = &parser->pdev->dev; - struct device_node *of_node = dev->of_node; - struct dss_module_power *mp = &parser->mp[DP_CORE_PM]; - static const char * const dp_gpios[] = { - "qcom,aux-en-gpio", - "qcom,aux-sel-gpio", - "qcom,usbplug-cc-gpio", - }; - - if (of_find_property(of_node, "qcom,dp-hpd-gpio", NULL)) { - parser->no_aux_switch = true; - parser->lphw_hpd = of_find_property(of_node, - "qcom,dp-low-power-hw-hpd", NULL); - return 0; - } - - if (of_find_property(of_node, "qcom,dp-gpio-aux-switch", NULL)) - parser->gpio_aux_switch = true; - mp->gpio_config = devm_kzalloc(dev, - sizeof(struct dss_gpio) * ARRAY_SIZE(dp_gpios), GFP_KERNEL); - if (!mp->gpio_config) - return -ENOMEM; - - mp->num_gpio = ARRAY_SIZE(dp_gpios); - - for (i = 0; i < ARRAY_SIZE(dp_gpios); i++) { - mp->gpio_config[i].gpio = of_get_named_gpio(of_node, - dp_gpios[i], 0); - - if (!gpio_is_valid(mp->gpio_config[i].gpio)) { - pr_debug("%s gpio not specified\n", dp_gpios[i]); - /* In case any gpio was not specified, we think gpio - * aux switch also was not specified. - */ - parser->gpio_aux_switch = false; - continue; - } - - strlcpy(mp->gpio_config[i].gpio_name, dp_gpios[i], - sizeof(mp->gpio_config[i].gpio_name)); - - mp->gpio_config[i].value = 0; - } - - return 0; -} - -static const char *dp_parser_supply_node_name(enum dp_pm_type module) -{ - switch (module) { - case DP_CORE_PM: return "qcom,core-supply-entries"; - case DP_CTRL_PM: return "qcom,ctrl-supply-entries"; - case DP_PHY_PM: return "qcom,phy-supply-entries"; - default: return "???"; - } -} - -static int dp_parser_get_vreg(struct dp_parser *parser, - enum dp_pm_type module) -{ - int i = 0, rc = 0; - u32 tmp = 0; - const char *pm_supply_name = NULL; - struct device_node *supply_node = NULL; - struct device_node *of_node = parser->pdev->dev.of_node; - struct device_node *supply_root_node = NULL; - struct dss_module_power *mp = &parser->mp[module]; - - mp->num_vreg = 0; - pm_supply_name = dp_parser_supply_node_name(module); - supply_root_node = of_get_child_by_name(of_node, pm_supply_name); - if (!supply_root_node) { - pr_err("no supply entry present: %s\n", pm_supply_name); - goto novreg; - } - - mp->num_vreg = of_get_available_child_count(supply_root_node); - - if (mp->num_vreg == 0) { - pr_debug("no vreg\n"); - goto novreg; - } else { - pr_debug("vreg found. count=%d\n", mp->num_vreg); - } - - mp->vreg_config = devm_kzalloc(&parser->pdev->dev, - sizeof(struct dss_vreg) * mp->num_vreg, GFP_KERNEL); - if (!mp->vreg_config) { - rc = -ENOMEM; - goto error; - } - - for_each_child_of_node(supply_root_node, supply_node) { - const char *st = NULL; - /* vreg-name */ - rc = of_property_read_string(supply_node, - "qcom,supply-name", &st); - if (rc) { - pr_err("error reading name. rc=%d\n", - rc); - goto error; - } - snprintf(mp->vreg_config[i].vreg_name, - ARRAY_SIZE((mp->vreg_config[i].vreg_name)), "%s", st); - /* vreg-min-voltage */ - rc = of_property_read_u32(supply_node, - "qcom,supply-min-voltage", &tmp); - if (rc) { - pr_err("error reading min volt. rc=%d\n", - rc); - goto error; - } - mp->vreg_config[i].min_voltage = tmp; - - /* vreg-max-voltage */ - rc = of_property_read_u32(supply_node, - "qcom,supply-max-voltage", &tmp); - if (rc) { - pr_err("error reading max volt. rc=%d\n", - rc); - goto error; - } - mp->vreg_config[i].max_voltage = tmp; - - /* enable-load */ - rc = of_property_read_u32(supply_node, - "qcom,supply-enable-load", &tmp); - if (rc) { - pr_err("error reading enable load. rc=%d\n", - rc); - goto error; - } - mp->vreg_config[i].enable_load = tmp; - - /* disable-load */ - rc = of_property_read_u32(supply_node, - "qcom,supply-disable-load", &tmp); - if (rc) { - pr_err("error reading disable load. rc=%d\n", - rc); - goto error; - } - mp->vreg_config[i].disable_load = tmp; - - pr_debug("%s min=%d, max=%d, enable=%d, disable=%d\n", - mp->vreg_config[i].vreg_name, - mp->vreg_config[i].min_voltage, - mp->vreg_config[i].max_voltage, - mp->vreg_config[i].enable_load, - mp->vreg_config[i].disable_load - ); - ++i; - } - - return rc; - -error: - if (mp->vreg_config) { - devm_kfree(&parser->pdev->dev, mp->vreg_config); - mp->vreg_config = NULL; - } -novreg: - mp->num_vreg = 0; - - return rc; -} - -static void dp_parser_put_vreg_data(struct device *dev, - struct dss_module_power *mp) -{ - if (!mp) { - DEV_ERR("invalid input\n"); - return; - } - - if (mp->vreg_config) { - devm_kfree(dev, mp->vreg_config); - mp->vreg_config = NULL; - } - mp->num_vreg = 0; -} - -static int dp_parser_regulator(struct dp_parser *parser) -{ - int i, rc = 0; - struct platform_device *pdev = parser->pdev; - - /* Parse the regulator information */ - for (i = DP_CORE_PM; i < DP_MAX_PM; i++) { - rc = dp_parser_get_vreg(parser, i); - if (rc) { - pr_err("get_dt_vreg_data failed for %s. rc=%d\n", - dp_parser_pm_name(i), rc); - i--; - for (; i >= DP_CORE_PM; i--) - dp_parser_put_vreg_data(&pdev->dev, - &parser->mp[i]); - break; - } - } - - return rc; -} - -static bool dp_parser_check_prefix(const char *clk_prefix, const char *clk_name) -{ - return !!strnstr(clk_name, clk_prefix, strlen(clk_name)); -} - -static void dp_parser_put_clk_data(struct device *dev, - struct dss_module_power *mp) -{ - if (!mp) { - DEV_ERR("%s: invalid input\n", __func__); - return; - } - - if (mp->clk_config) { - devm_kfree(dev, mp->clk_config); - mp->clk_config = NULL; - } - - mp->num_clk = 0; -} - -static void dp_parser_put_gpio_data(struct device *dev, - struct dss_module_power *mp) -{ - if (!mp) { - DEV_ERR("%s: invalid input\n", __func__); - return; - } - - if (mp->gpio_config) { - devm_kfree(dev, mp->gpio_config); - mp->gpio_config = NULL; - } - - mp->num_gpio = 0; -} - -static int dp_parser_init_clk_data(struct dp_parser *parser) -{ - int num_clk = 0, i = 0, rc = 0; - int core_clk_count = 0, link_clk_count = 0; - int strm0_clk_count = 0, strm1_clk_count = 0; - const char *core_clk = "core"; - const char *strm0_clk = "strm0"; - const char *strm1_clk = "strm1"; - const char *link_clk = "link"; - const char *clk_name; - struct device *dev = &parser->pdev->dev; - struct dss_module_power *core_power = &parser->mp[DP_CORE_PM]; - struct dss_module_power *strm0_power = &parser->mp[DP_STREAM0_PM]; - struct dss_module_power *strm1_power = &parser->mp[DP_STREAM1_PM]; - struct dss_module_power *link_power = &parser->mp[DP_LINK_PM]; - - num_clk = of_property_count_strings(dev->of_node, "clock-names"); - if (num_clk <= 0) { - pr_err("no clocks are defined\n"); - rc = -EINVAL; - goto exit; - } - - for (i = 0; i < num_clk; i++) { - of_property_read_string_index(dev->of_node, - "clock-names", i, &clk_name); - - if (dp_parser_check_prefix(core_clk, clk_name)) - core_clk_count++; - - if (dp_parser_check_prefix(strm0_clk, clk_name)) - strm0_clk_count++; - - if (dp_parser_check_prefix(strm1_clk, clk_name)) - strm1_clk_count++; - - if (dp_parser_check_prefix(link_clk, clk_name)) - link_clk_count++; - } - - /* Initialize the CORE power module */ - if (core_clk_count <= 0) { - pr_err("no core clocks are defined\n"); - rc = -EINVAL; - goto exit; - } - - core_power->num_clk = core_clk_count; - core_power->clk_config = devm_kzalloc(dev, - sizeof(struct dss_clk) * core_power->num_clk, - GFP_KERNEL); - if (!core_power->clk_config) { - rc = -EINVAL; - goto exit; - } - - /* Initialize the STREAM0 power module */ - if (strm0_clk_count <= 0) { - pr_debug("no strm0 clocks are defined\n"); - } else { - strm0_power->num_clk = strm0_clk_count; - strm0_power->clk_config = devm_kzalloc(dev, - sizeof(struct dss_clk) * strm0_power->num_clk, - GFP_KERNEL); - if (!strm0_power->clk_config) { - strm0_power->num_clk = 0; - rc = -EINVAL; - goto strm0_clock_error; - } - } - - /* Initialize the STREAM1 power module */ - if (strm1_clk_count <= 0) { - pr_debug("no strm1 clocks are defined\n"); - } else { - strm1_power->num_clk = strm1_clk_count; - strm1_power->clk_config = devm_kzalloc(dev, - sizeof(struct dss_clk) * strm1_power->num_clk, - GFP_KERNEL); - if (!strm1_power->clk_config) { - strm1_power->num_clk = 0; - rc = -EINVAL; - goto strm1_clock_error; - } - } - - /* Initialize the link power module */ - if (link_clk_count <= 0) { - pr_err("no link clocks are defined\n"); - rc = -EINVAL; - goto link_clock_error; - } - - link_power->num_clk = link_clk_count; - link_power->clk_config = devm_kzalloc(dev, - sizeof(struct dss_clk) * link_power->num_clk, - GFP_KERNEL); - if (!link_power->clk_config) { - link_power->num_clk = 0; - rc = -EINVAL; - goto link_clock_error; - } - - return rc; - -link_clock_error: - dp_parser_put_clk_data(dev, strm1_power); -strm1_clock_error: - dp_parser_put_clk_data(dev, strm0_power); -strm0_clock_error: - dp_parser_put_clk_data(dev, core_power); -exit: - return rc; -} - -static int dp_parser_clock(struct dp_parser *parser) -{ - int rc = 0, i = 0; - int num_clk = 0; - int core_clk_index = 0, link_clk_index = 0; - int core_clk_count = 0, link_clk_count = 0; - int strm0_clk_index = 0, strm1_clk_index = 0; - int strm0_clk_count = 0, strm1_clk_count = 0; - const char *clk_name; - const char *core_clk = "core"; - const char *strm0_clk = "strm0"; - const char *strm1_clk = "strm1"; - const char *link_clk = "link"; - struct device *dev = &parser->pdev->dev; - struct dss_module_power *core_power; - struct dss_module_power *strm0_power; - struct dss_module_power *strm1_power; - struct dss_module_power *link_power; - - core_power = &parser->mp[DP_CORE_PM]; - strm0_power = &parser->mp[DP_STREAM0_PM]; - strm1_power = &parser->mp[DP_STREAM1_PM]; - link_power = &parser->mp[DP_LINK_PM]; - - rc = dp_parser_init_clk_data(parser); - if (rc) { - pr_err("failed to initialize power data\n"); - rc = -EINVAL; - goto exit; - } - - core_clk_count = core_power->num_clk; - link_clk_count = link_power->num_clk; - strm0_clk_count = strm0_power->num_clk; - strm1_clk_count = strm1_power->num_clk; - - num_clk = of_property_count_strings(dev->of_node, "clock-names"); - - for (i = 0; i < num_clk; i++) { - of_property_read_string_index(dev->of_node, "clock-names", - i, &clk_name); - - if (dp_parser_check_prefix(core_clk, clk_name) && - core_clk_index < core_clk_count) { - struct dss_clk *clk = - &core_power->clk_config[core_clk_index]; - strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name)); - clk->type = DSS_CLK_AHB; - core_clk_index++; - } else if (dp_parser_check_prefix(link_clk, clk_name) && - link_clk_index < link_clk_count) { - struct dss_clk *clk = - &link_power->clk_config[link_clk_index]; - strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name)); - link_clk_index++; - - if (!strcmp(clk_name, "link_clk")) - clk->type = DSS_CLK_PCLK; - else - clk->type = DSS_CLK_AHB; - } else if (dp_parser_check_prefix(strm0_clk, clk_name) && - strm0_clk_index < strm0_clk_count) { - struct dss_clk *clk = - &strm0_power->clk_config[strm0_clk_index]; - strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name)); - strm0_clk_index++; - - clk->type = DSS_CLK_PCLK; - } else if (dp_parser_check_prefix(strm1_clk, clk_name) && - strm1_clk_index < strm1_clk_count) { - struct dss_clk *clk = - &strm1_power->clk_config[strm1_clk_index]; - strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name)); - strm1_clk_index++; - - clk->type = DSS_CLK_PCLK; - } - } - - pr_debug("clock parsing successful\n"); - -exit: - return rc; -} - -static int dp_parser_catalog(struct dp_parser *parser) -{ - int rc; - u32 version; - struct device *dev = &parser->pdev->dev; - - rc = of_property_read_u32(dev->of_node, "qcom,phy-version", &version); - - if (!rc) - parser->hw_cfg.phy_version = version; - - return 0; -} - -static int dp_parser_mst(struct dp_parser *parser) -{ - struct device *dev = &parser->pdev->dev; - int i; - - parser->has_mst = of_property_read_bool(dev->of_node, - "qcom,mst-enable"); - parser->has_mst_sideband = parser->has_mst; - - pr_debug("mst parsing successful. mst:%d\n", parser->has_mst); - - for (i = 0; i < MAX_DP_MST_STREAMS; i++) { - of_property_read_u32_index(dev->of_node, - "qcom,mst-fixed-topology-ports", i, - &parser->mst_fixed_port[i]); - } - - return 0; -} - -static void dp_parser_dsc(struct dp_parser *parser) -{ - int rc; - struct device *dev = &parser->pdev->dev; - - parser->dsc_feature_enable = of_property_read_bool(dev->of_node, - "qcom,dsc-feature-enable"); - - rc = of_property_read_u32(dev->of_node, - "qcom,max-dp-dsc-blks", &parser->max_dp_dsc_blks); - if (rc || !parser->max_dp_dsc_blks) - parser->dsc_feature_enable = false; - - rc = of_property_read_u32(dev->of_node, - "qcom,max-dp-dsc-input-width-pixs", - &parser->max_dp_dsc_input_width_pixs); - if (rc || !parser->max_dp_dsc_input_width_pixs) - parser->dsc_feature_enable = false; - - pr_debug("dsc parsing successful. dsc:%d, blks:%d, width:%d\n", - parser->dsc_feature_enable, - parser->max_dp_dsc_blks, - parser->max_dp_dsc_input_width_pixs); -} - -static void dp_parser_fec(struct dp_parser *parser) -{ - struct device *dev = &parser->pdev->dev; - - parser->fec_feature_enable = of_property_read_bool(dev->of_node, - "qcom,fec-feature-enable"); - - pr_debug("fec parsing successful. fec:%d\n", - parser->fec_feature_enable); -} - -static void dp_parser_widebus(struct dp_parser *parser) -{ - struct device *dev = &parser->pdev->dev; - - parser->has_widebus = of_property_read_bool(dev->of_node, - "qcom,widebus-enable"); - - pr_debug("widebus parsing successful. widebus:%d\n", - parser->has_widebus); -} - -static int dp_parser_parse(struct dp_parser *parser) -{ - int rc = 0; - - if (!parser) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto err; - } - - rc = dp_parser_reg(parser); - if (rc) - goto err; - - rc = dp_parser_aux(parser); - if (rc) - goto err; - - rc = dp_parser_misc(parser); - if (rc) - goto err; - - rc = dp_parser_clock(parser); - if (rc) - goto err; - - rc = dp_parser_regulator(parser); - if (rc) - goto err; - - rc = dp_parser_gpio(parser); - if (rc) - goto err; - - rc = dp_parser_catalog(parser); - if (rc) - goto err; - - rc = dp_parser_pinctrl(parser); - if (rc) - goto err; - - rc = dp_parser_msm_hdcp_dev(parser); - if (rc) - goto err; - - rc = dp_parser_mst(parser); - if (rc) - goto err; - - dp_parser_dsc(parser); - dp_parser_fec(parser); - dp_parser_widebus(parser); -err: - return rc; -} - -static struct dp_io_data *dp_parser_get_io(struct dp_parser *dp_parser, - char *name) -{ - int i = 0; - struct dp_io *io; - - if (!dp_parser) { - pr_err("invalid input\n"); - goto err; - } - - io = &dp_parser->io; - - for (i = 0; i < io->len; i++) { - struct dp_io_data *data = &io->data[i]; - - if (!strcmp(data->name, name)) - return data; - } -err: - return NULL; -} - -static void dp_parser_get_io_buf(struct dp_parser *dp_parser, char *name) -{ - int i = 0; - struct dp_io *io; - - if (!dp_parser) { - pr_err("invalid input\n"); - return; - } - - io = &dp_parser->io; - - for (i = 0; i < io->len; i++) { - struct dp_io_data *data = &io->data[i]; - - if (!strcmp(data->name, name)) { - if (!data->buf) - data->buf = devm_kzalloc(&dp_parser->pdev->dev, - data->io.len, GFP_KERNEL); - } - } -} - -static void dp_parser_clear_io_buf(struct dp_parser *dp_parser) -{ - int i = 0; - struct dp_io *io; - - if (!dp_parser) { - pr_err("invalid input\n"); - return; - } - - io = &dp_parser->io; - - for (i = 0; i < io->len; i++) { - struct dp_io_data *data = &io->data[i]; - - if (data->buf) - devm_kfree(&dp_parser->pdev->dev, data->buf); - - data->buf = NULL; - } -} - -struct dp_parser *dp_parser_get(struct platform_device *pdev) -{ - struct dp_parser *parser; - - parser = devm_kzalloc(&pdev->dev, sizeof(*parser), GFP_KERNEL); - if (!parser) - return ERR_PTR(-ENOMEM); - - parser->parse = dp_parser_parse; - parser->get_io = dp_parser_get_io; - parser->get_io_buf = dp_parser_get_io_buf; - parser->clear_io_buf = dp_parser_clear_io_buf; - parser->pdev = pdev; - - return parser; -} - -void dp_parser_put(struct dp_parser *parser) -{ - int i = 0; - struct dss_module_power *power = NULL; - - if (!parser) { - pr_err("invalid parser module\n"); - return; - } - - power = parser->mp; - - for (i = 0; i < DP_MAX_PM; i++) { - dp_parser_put_clk_data(&parser->pdev->dev, &power[i]); - dp_parser_put_vreg_data(&parser->pdev->dev, &power[i]); - dp_parser_put_gpio_data(&parser->pdev->dev, &power[i]); - } - - dp_parser_clear_io_buf(parser); - devm_kfree(&parser->pdev->dev, parser->io.data); - devm_kfree(&parser->pdev->dev, parser); -} diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h deleted file mode 100644 index 9caa1a7ddff7109b4dc48863874a95b4e3039a2e..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ /dev/null @@ -1,271 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. - */ - -#ifndef _DP_PARSER_H_ -#define _DP_PARSER_H_ - -#include - -#define DP_LABEL "MDSS DP DISPLAY" -#define AUX_CFG_LEN 10 -#define DP_MAX_PIXEL_CLK_KHZ 675000 -#define DP_MAX_LINK_CLK_KHZ 810000 -#define MAX_DP_MST_STREAMS 2 - -enum dp_pm_type { - DP_CORE_PM, - DP_CTRL_PM, - DP_PHY_PM, - DP_STREAM0_PM, - DP_STREAM1_PM, - DP_LINK_PM, - DP_MAX_PM -}; - -static inline const char *dp_parser_pm_name(enum dp_pm_type module) -{ - switch (module) { - case DP_CORE_PM: return "DP_CORE_PM"; - case DP_CTRL_PM: return "DP_CTRL_PM"; - case DP_PHY_PM: return "DP_PHY_PM"; - case DP_STREAM0_PM: return "DP_STREAM0_PM"; - case DP_STREAM1_PM: return "DP_STREAM1_PM"; - case DP_LINK_PM: return "DP_LINK_PM"; - default: return "???"; - } -} - -/** - * struct dp_display_data - display related device tree data. - * - * @ctrl_node: referece to controller device - * @phy_node: reference to phy device - * @is_active: is the controller currently active - * @name: name of the display - * @display_type: type of the display - */ -struct dp_display_data { - struct device_node *ctrl_node; - struct device_node *phy_node; - bool is_active; - const char *name; - const char *display_type; -}; - -/** - * struct dp_io_data - data structure to store DP IO related info - * @name: name of the IO - * @buf: buffer corresponding to IO for debugging - * @io: io data which give len and mapped address - */ -struct dp_io_data { - const char *name; - u8 *buf; - struct dss_io_data io; -}; - -/** - * struct dp_io - data struct to store array of DP IO info - * @len: total number of IOs - * @data: pointer to an array of DP IO data structures. - */ -struct dp_io { - u32 len; - struct dp_io_data *data; -}; - -/** - * struct dp_pinctrl - DP's pin control - * - * @pin: pin-controller's instance - * @state_active: active state pin control - * @state_hpd_active: hpd active state pin control - * @state_suspend: suspend state pin control - */ -struct dp_pinctrl { - struct pinctrl *pin; - struct pinctrl_state *state_active; - struct pinctrl_state *state_hpd_active; - struct pinctrl_state *state_hpd_tlmm; - struct pinctrl_state *state_hpd_ctrl; - struct pinctrl_state *state_suspend; -}; - -#define DP_ENUM_STR(x) #x -#define DP_AUX_CFG_MAX_VALUE_CNT 3 -/** - * struct dp_aux_cfg - DP's AUX configuration settings - * - * @cfg_cnt: count of the configurable settings for the AUX register - * @current_index: current index of the AUX config lut - * @offset: register offset of the AUX config register - * @lut: look up table for the AUX config values for this register - */ -struct dp_aux_cfg { - u32 cfg_cnt; - u32 current_index; - u32 offset; - u32 lut[DP_AUX_CFG_MAX_VALUE_CNT]; -}; - -/* PHY AUX config registers */ -enum dp_phy_aux_config_type { - PHY_AUX_CFG0, - PHY_AUX_CFG1, - PHY_AUX_CFG2, - PHY_AUX_CFG3, - PHY_AUX_CFG4, - PHY_AUX_CFG5, - PHY_AUX_CFG6, - PHY_AUX_CFG7, - PHY_AUX_CFG8, - PHY_AUX_CFG9, - PHY_AUX_CFG_MAX, -}; - -/** - * enum dp_phy_version - version of the dp phy - * @DP_PHY_VERSION_UNKNOWN: Unknown controller version - * @DP_PHY_VERSION_4_2_0: DP phy v4.2.0 controller - * @DP_PHY_VERSION_MAX: max version - */ -enum dp_phy_version { - DP_PHY_VERSION_UNKNOWN, - DP_PHY_VERSION_2_0_0 = 0x200, - DP_PHY_VERSION_4_2_0 = 0x420, - DP_PHY_VERSION_MAX -}; - -/** - * struct dp_hw_cfg - DP HW specific configuration - * - * @phy_version: DP PHY HW version - */ -struct dp_hw_cfg { - enum dp_phy_version phy_version; -}; - -static inline char *dp_phy_aux_config_type_to_string(u32 cfg_type) -{ - switch (cfg_type) { - case PHY_AUX_CFG0: - return DP_ENUM_STR(PHY_AUX_CFG0); - case PHY_AUX_CFG1: - return DP_ENUM_STR(PHY_AUX_CFG1); - case PHY_AUX_CFG2: - return DP_ENUM_STR(PHY_AUX_CFG2); - case PHY_AUX_CFG3: - return DP_ENUM_STR(PHY_AUX_CFG3); - case PHY_AUX_CFG4: - return DP_ENUM_STR(PHY_AUX_CFG4); - case PHY_AUX_CFG5: - return DP_ENUM_STR(PHY_AUX_CFG5); - case PHY_AUX_CFG6: - return DP_ENUM_STR(PHY_AUX_CFG6); - case PHY_AUX_CFG7: - return DP_ENUM_STR(PHY_AUX_CFG7); - case PHY_AUX_CFG8: - return DP_ENUM_STR(PHY_AUX_CFG8); - case PHY_AUX_CFG9: - return DP_ENUM_STR(PHY_AUX_CFG9); - default: - return "unknown"; - } -} - -/** - * struct dp_parser - DP parser's data exposed to clients - * - * @pdev: platform data of the client - * @msm_hdcp_dev: device pointer for the HDCP driver - * @mp: gpio, regulator and clock related data - * @pinctrl: pin-control related data - * @disp_data: controller's display related data - * @l_pnswap: P/N swap status on each lane - * @max_pclk_khz: maximum pixel clock supported for the platform - * @max_lclk_khz: maximum link clock supported for the platform - * @hw_cfg: DP HW specific settings - * @has_mst: MST feature enable status - * @has_mst_sideband: MST sideband feature enable status - * @no_aux_switch: presence AUX switch status - * @gpio_aux_switch: presence GPIO AUX switch status - * @dsc_feature_enable: DSC feature enable status - * @fec_feature_enable: FEC feature enable status - * @max_dp_dsc_blks: maximum DSC blks for DP interface - * @max_dp_dsc_input_width_pixs: Maximum input width for DSC block - * @has_widebus: widebus (2PPC) feature eanble status - *@mst_fixed_port: mst port_num reserved for fixed topology - * @parse: function to be called by client to parse device tree. - * @get_io: function to be called by client to get io data. - * @get_io_buf: function to be called by client to get io buffers. - * @clear_io_buf: function to be called by client to clear io buffers. - */ -struct dp_parser { - struct platform_device *pdev; - struct device *msm_hdcp_dev; - struct dss_module_power mp[DP_MAX_PM]; - struct dp_pinctrl pinctrl; - struct dp_io io; - struct dp_display_data disp_data; - - u8 l_map[4]; - u8 l_pnswap; - struct dp_aux_cfg aux_cfg[AUX_CFG_LEN]; - u32 max_pclk_khz; - u32 max_lclk_khz; - struct dp_hw_cfg hw_cfg; - bool has_mst; - bool has_mst_sideband; - bool no_aux_switch; - bool dsc_feature_enable; - bool fec_feature_enable; - bool has_widebus; - bool gpio_aux_switch; - u32 max_dp_dsc_blks; - u32 max_dp_dsc_input_width_pixs; - bool lphw_hpd; - u32 mst_fixed_port[MAX_DP_MST_STREAMS]; - - int (*parse)(struct dp_parser *parser); - struct dp_io_data *(*get_io)(struct dp_parser *parser, char *name); - void (*get_io_buf)(struct dp_parser *parser, char *name); - void (*clear_io_buf)(struct dp_parser *parser); -}; - -enum dp_phy_lane_num { - DP_PHY_LN0 = 0, - DP_PHY_LN1 = 1, - DP_PHY_LN2 = 2, - DP_PHY_LN3 = 3, - DP_MAX_PHY_LN = 4, -}; - -enum dp_mainlink_lane_num { - DP_ML0 = 0, - DP_ML1 = 1, - DP_ML2 = 2, - DP_ML3 = 3, -}; - -/** - * dp_parser_get() - get the DP's device tree parser module - * - * @pdev: platform data of the client - * return: pointer to dp_parser structure. - * - * This function provides client capability to parse the - * device tree and populate the data structures. The data - * related to clock, regulators, pin-control and other - * can be parsed using this module. - */ -struct dp_parser *dp_parser_get(struct platform_device *pdev); - -/** - * dp_parser_put() - cleans the dp_parser module - * - * @parser: pointer to the parser's data. - */ -void dp_parser_put(struct dp_parser *parser); -#endif diff --git a/drivers/gpu/drm/msm/dp/dp_power.c b/drivers/gpu/drm/msm/dp/dp_power.c deleted file mode 100644 index deb9a1af3eb9c53f1de0c5a45f6e18daec1e84de..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_power.c +++ /dev/null @@ -1,720 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ - -#include -#include "dp_power.h" -#include "dp_catalog.h" - -#define DP_CLIENT_NAME_SIZE 20 - -struct dp_power_private { - struct dp_parser *parser; - struct platform_device *pdev; - struct clk *pixel_clk_rcg; - struct clk *pixel_parent; - struct clk *pixel1_clk_rcg; - struct clk *pixel1_parent; - - struct dp_power dp_power; - struct sde_power_client *dp_core_client; - struct sde_power_handle *phandle; - - bool core_clks_on; - bool link_clks_on; - bool strm0_clks_on; - bool strm1_clks_on; -}; - -static int dp_power_regulator_init(struct dp_power_private *power) -{ - int rc = 0, i = 0, j = 0; - struct platform_device *pdev; - struct dp_parser *parser; - - parser = power->parser; - pdev = power->pdev; - - for (i = DP_CORE_PM; !rc && (i < DP_MAX_PM); i++) { - rc = msm_dss_config_vreg(&pdev->dev, - parser->mp[i].vreg_config, - parser->mp[i].num_vreg, 1); - if (rc) { - pr_err("failed to init vregs for %s\n", - dp_parser_pm_name(i)); - for (j = i - 1; j >= DP_CORE_PM; j--) { - msm_dss_config_vreg(&pdev->dev, - parser->mp[j].vreg_config, - parser->mp[j].num_vreg, 0); - } - - goto error; - } - } -error: - return rc; -} - -static void dp_power_regulator_deinit(struct dp_power_private *power) -{ - int rc = 0, i = 0; - struct platform_device *pdev; - struct dp_parser *parser; - - parser = power->parser; - pdev = power->pdev; - - for (i = DP_CORE_PM; (i < DP_MAX_PM); i++) { - rc = msm_dss_config_vreg(&pdev->dev, - parser->mp[i].vreg_config, - parser->mp[i].num_vreg, 0); - if (rc) - pr_err("failed to deinit vregs for %s\n", - dp_parser_pm_name(i)); - } -} - -static int dp_power_regulator_ctrl(struct dp_power_private *power, bool enable) -{ - int rc = 0, i = 0, j = 0; - struct dp_parser *parser; - - parser = power->parser; - - for (i = DP_CORE_PM; i < DP_MAX_PM; i++) { - rc = msm_dss_enable_vreg( - parser->mp[i].vreg_config, - parser->mp[i].num_vreg, enable); - if (rc) { - pr_err("failed to '%s' vregs for %s\n", - enable ? "enable" : "disable", - dp_parser_pm_name(i)); - if (enable) { - for (j = i-1; j >= DP_CORE_PM; j--) { - msm_dss_enable_vreg( - parser->mp[j].vreg_config, - parser->mp[j].num_vreg, 0); - } - } - goto error; - } - } -error: - return rc; -} - -static int dp_power_pinctrl_set(struct dp_power_private *power, bool active) -{ - int rc = -EFAULT; - struct pinctrl_state *pin_state; - struct dp_parser *parser; - - parser = power->parser; - - if (IS_ERR_OR_NULL(parser->pinctrl.pin)) - return 0; - - if (parser->no_aux_switch && parser->lphw_hpd) { - pin_state = active ? parser->pinctrl.state_hpd_ctrl - : parser->pinctrl.state_hpd_tlmm; - if (!IS_ERR_OR_NULL(pin_state)) { - rc = pinctrl_select_state(parser->pinctrl.pin, - pin_state); - if (rc) { - pr_err("cannot direct hpd line to %s\n", - active ? "ctrl" : "tlmm"); - return rc; - } - } - } - - if (parser->no_aux_switch) - return 0; - - pin_state = active ? parser->pinctrl.state_active - : parser->pinctrl.state_suspend; - if (!IS_ERR_OR_NULL(pin_state)) { - rc = pinctrl_select_state(parser->pinctrl.pin, - pin_state); - if (rc) - pr_err("can not set %s pins\n", - active ? "dp_active" - : "dp_sleep"); - } else { - pr_err("invalid '%s' pinstate\n", - active ? "dp_active" - : "dp_sleep"); - } - - return rc; -} - -static int dp_power_clk_init(struct dp_power_private *power, bool enable) -{ - int rc = 0; - struct device *dev; - enum dp_pm_type module; - - dev = &power->pdev->dev; - - if (enable) { - for (module = DP_CORE_PM; module < DP_MAX_PM; module++) { - struct dss_module_power *pm = - &power->parser->mp[module]; - - if (!pm->num_clk) - continue; - - rc = msm_dss_get_clk(dev, pm->clk_config, pm->num_clk); - if (rc) { - pr_err("failed to get %s clk. err=%d\n", - dp_parser_pm_name(module), rc); - goto exit; - } - } - - power->pixel_clk_rcg = devm_clk_get(dev, "pixel_clk_rcg"); - if (IS_ERR(power->pixel_clk_rcg)) { - pr_debug("Unable to get DP pixel clk RCG\n"); - power->pixel_clk_rcg = NULL; - } - - power->pixel_parent = devm_clk_get(dev, "pixel_parent"); - if (IS_ERR(power->pixel_parent)) { - pr_debug("Unable to get DP pixel RCG parent\n"); - power->pixel_parent = NULL; - } - - power->pixel1_clk_rcg = devm_clk_get(dev, "pixel1_clk_rcg"); - if (IS_ERR(power->pixel1_clk_rcg)) { - pr_debug("Unable to get DP pixel1 clk RCG\n"); - power->pixel1_clk_rcg = NULL; - } - - power->pixel1_parent = devm_clk_get(dev, "pixel1_parent"); - if (IS_ERR(power->pixel1_parent)) { - pr_debug("Unable to get DP pixel1 RCG parent\n"); - power->pixel1_parent = NULL; - } - } else { - if (power->pixel_parent) - devm_clk_put(dev, power->pixel_parent); - - if (power->pixel_clk_rcg) - devm_clk_put(dev, power->pixel_clk_rcg); - - if (power->pixel1_parent) - devm_clk_put(dev, power->pixel1_parent); - - if (power->pixel1_clk_rcg) - devm_clk_put(dev, power->pixel1_clk_rcg); - - for (module = DP_CORE_PM; module < DP_MAX_PM; module++) { - struct dss_module_power *pm = - &power->parser->mp[module]; - - if (!pm->num_clk) - continue; - - msm_dss_put_clk(pm->clk_config, pm->num_clk); - } - } -exit: - return rc; -} - -static int dp_power_clk_set_rate(struct dp_power_private *power, - enum dp_pm_type module, bool enable) -{ - int rc = 0; - struct dss_module_power *mp; - - if (!power) { - pr_err("invalid power data\n"); - rc = -EINVAL; - goto exit; - } - - mp = &power->parser->mp[module]; - - if (enable) { - rc = msm_dss_clk_set_rate(mp->clk_config, mp->num_clk); - if (rc) { - pr_err("failed to set clks rate.\n"); - goto exit; - } - - rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, 1); - if (rc) { - pr_err("failed to enable clks\n"); - goto exit; - } - } else { - rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, 0); - if (rc) { - pr_err("failed to disable clks\n"); - goto exit; - } - } -exit: - return rc; -} - -static int dp_power_clk_enable(struct dp_power *dp_power, - enum dp_pm_type pm_type, bool enable) -{ - int rc = 0; - struct dss_module_power *mp; - struct dp_power_private *power; - - if (!dp_power) { - pr_err("invalid power data\n"); - rc = -EINVAL; - goto error; - } - - power = container_of(dp_power, struct dp_power_private, dp_power); - - mp = &power->parser->mp[pm_type]; - - if (pm_type >= DP_MAX_PM) { - pr_err("unsupported power module: %s\n", - dp_parser_pm_name(pm_type)); - return -EINVAL; - } - - if (enable) { - if (pm_type == DP_CORE_PM && power->core_clks_on) { - pr_debug("core clks already enabled\n"); - return 0; - } - - if ((pm_type == DP_STREAM0_PM) && (power->strm0_clks_on)) { - pr_debug("strm0 clks already enabled\n"); - return 0; - } - - if ((pm_type == DP_STREAM1_PM) && (power->strm1_clks_on)) { - pr_debug("strm1 clks already enabled\n"); - return 0; - } - - if ((pm_type == DP_CTRL_PM) && (!power->core_clks_on)) { - pr_debug("Need to enable core clks before link clks\n"); - - rc = dp_power_clk_set_rate(power, pm_type, enable); - if (rc) { - pr_err("failed to enable clks: %s. err=%d\n", - dp_parser_pm_name(DP_CORE_PM), rc); - goto error; - } else { - power->core_clks_on = true; - } - } - - if (pm_type == DP_LINK_PM && power->link_clks_on) { - pr_debug("links clks already enabled\n"); - return 0; - } - } - - rc = dp_power_clk_set_rate(power, pm_type, enable); - if (rc) { - pr_err("failed to '%s' clks for: %s. err=%d\n", - enable ? "enable" : "disable", - dp_parser_pm_name(pm_type), rc); - goto error; - } - - if (pm_type == DP_CORE_PM) - power->core_clks_on = enable; - else if (pm_type == DP_STREAM0_PM) - power->strm0_clks_on = enable; - else if (pm_type == DP_STREAM1_PM) - power->strm1_clks_on = enable; - else if (pm_type == DP_LINK_PM) - power->link_clks_on = enable; - - /* - * This log is printed only when user connects or disconnects - * a DP cable. As this is a user-action and not a frequent - * usecase, it is not going to flood the kernel logs. Also, - * helpful in debugging the NOC issues. - */ - pr_info("core:%s link:%s strm0:%s strm1:%s\n", - power->core_clks_on ? "on" : "off", - power->link_clks_on ? "on" : "off", - power->strm0_clks_on ? "on" : "off", - power->strm1_clks_on ? "on" : "off"); -error: - return rc; -} - -static int dp_power_request_gpios(struct dp_power_private *power) -{ - int rc = 0, i; - struct device *dev; - struct dss_module_power *mp; - static const char * const gpio_names[] = { - "aux_enable", "aux_sel", "usbplug_cc", - }; - - if (!power) { - pr_err("invalid power data\n"); - return -EINVAL; - } - - dev = &power->pdev->dev; - mp = &power->parser->mp[DP_CORE_PM]; - - for (i = 0; i < ARRAY_SIZE(gpio_names); i++) { - unsigned int gpio = mp->gpio_config[i].gpio; - - if (gpio_is_valid(gpio)) { - rc = devm_gpio_request(dev, gpio, gpio_names[i]); - if (rc) { - pr_err("request %s gpio failed, rc=%d\n", - gpio_names[i], rc); - goto error; - } - } - } - return 0; -error: - for (i = 0; i < ARRAY_SIZE(gpio_names); i++) { - unsigned int gpio = mp->gpio_config[i].gpio; - - if (gpio_is_valid(gpio)) - gpio_free(gpio); - } - return rc; -} - -static bool dp_power_find_gpio(const char *gpio1, const char *gpio2) -{ - return !!strnstr(gpio1, gpio2, strlen(gpio1)); -} - -static void dp_power_set_gpio(struct dp_power_private *power, bool flip) -{ - int i; - struct dss_module_power *mp = &power->parser->mp[DP_CORE_PM]; - struct dss_gpio *config = mp->gpio_config; - - for (i = 0; i < mp->num_gpio; i++) { - if (dp_power_find_gpio(config->gpio_name, "aux-sel")) - config->value = flip; - - if (gpio_is_valid(config->gpio)) { - pr_debug("gpio %s, value %d\n", config->gpio_name, - config->value); - - if (dp_power_find_gpio(config->gpio_name, "aux-en") || - dp_power_find_gpio(config->gpio_name, "aux-sel")) - gpio_direction_output(config->gpio, - config->value); - else - gpio_set_value(config->gpio, config->value); - - } - config++; - } -} - -static int dp_power_config_gpios(struct dp_power_private *power, bool flip, - bool enable) -{ - int rc = 0, i; - struct dss_module_power *mp; - struct dss_gpio *config; - - if (power->parser->no_aux_switch) - return 0; - - mp = &power->parser->mp[DP_CORE_PM]; - config = mp->gpio_config; - - if (enable) { - rc = dp_power_request_gpios(power); - if (rc) { - pr_err("gpio request failed\n"); - return rc; - } - - dp_power_set_gpio(power, flip); - } else { - for (i = 0; i < mp->num_gpio; i++) { - if (gpio_is_valid(config[i].gpio)) { - gpio_set_value(config[i].gpio, 0); - gpio_free(config[i].gpio); - } - } - } - - return 0; -} - -static int dp_power_client_init(struct dp_power *dp_power, - struct sde_power_handle *phandle) -{ - int rc = 0; - struct dp_power_private *power; - char dp_client_name[DP_CLIENT_NAME_SIZE]; - - if (!dp_power) { - pr_err("invalid power data\n"); - return -EINVAL; - } - - power = container_of(dp_power, struct dp_power_private, dp_power); - - rc = dp_power_regulator_init(power); - if (rc) { - pr_err("failed to init regulators\n"); - goto error_power; - } - - rc = dp_power_clk_init(power, true); - if (rc) { - pr_err("failed to init clocks\n"); - goto error_clk; - } - - power->phandle = phandle; - snprintf(dp_client_name, DP_CLIENT_NAME_SIZE, "dp_core_client"); - power->dp_core_client = sde_power_client_create(phandle, - dp_client_name); - if (IS_ERR_OR_NULL(power->dp_core_client)) { - pr_err("[%s] client creation failed for DP\n", dp_client_name); - rc = -EINVAL; - goto error_client; - } - return 0; - -error_client: - dp_power_clk_init(power, false); -error_clk: - dp_power_regulator_deinit(power); -error_power: - return rc; -} - -static void dp_power_client_deinit(struct dp_power *dp_power) -{ - struct dp_power_private *power; - - if (!dp_power) { - pr_err("invalid power data\n"); - return; - } - - power = container_of(dp_power, struct dp_power_private, dp_power); - - sde_power_client_destroy(power->phandle, power->dp_core_client); - dp_power_clk_init(power, false); - dp_power_regulator_deinit(power); -} - -static int dp_power_set_pixel_clk_parent(struct dp_power *dp_power, u32 strm_id) -{ - int rc = 0; - struct dp_power_private *power; - - if (!dp_power || strm_id >= DP_STREAM_MAX) { - pr_err("invalid power data. stream %d\n", strm_id); - rc = -EINVAL; - goto exit; - } - - power = container_of(dp_power, struct dp_power_private, dp_power); - - if (strm_id == DP_STREAM_0) { - if (power->pixel_clk_rcg && power->pixel_parent) - clk_set_parent(power->pixel_clk_rcg, - power->pixel_parent); - } else if (strm_id == DP_STREAM_1) { - if (power->pixel1_clk_rcg && power->pixel1_parent) - clk_set_parent(power->pixel1_clk_rcg, - power->pixel1_parent); - } -exit: - return rc; -} - -static u64 dp_power_clk_get_rate(struct dp_power *dp_power, char *clk_name) -{ - size_t i; - enum dp_pm_type j; - struct dss_module_power *mp; - struct dp_power_private *power; - bool clk_found = false; - u64 rate = 0; - - if (!clk_name) { - pr_err("invalid pointer for clk_name\n"); - return 0; - } - - power = container_of(dp_power, struct dp_power_private, dp_power); - mp = &power->phandle->mp; - for (i = 0; i < mp->num_clk; i++) { - if (!strcmp(mp->clk_config[i].clk_name, clk_name)) { - rate = clk_get_rate(mp->clk_config[i].clk); - clk_found = true; - break; - } - } - - for (j = DP_CORE_PM; j < DP_MAX_PM && !clk_found; j++) { - mp = &power->parser->mp[j]; - for (i = 0; i < mp->num_clk; i++) { - if (!strcmp(mp->clk_config[i].clk_name, clk_name)) { - rate = clk_get_rate(mp->clk_config[i].clk); - clk_found = true; - break; - } - } - } - - return rate; -} - -static int dp_power_init(struct dp_power *dp_power, bool flip) -{ - int rc = 0; - struct dp_power_private *power; - - if (!dp_power) { - pr_err("invalid power data\n"); - rc = -EINVAL; - goto exit; - } - - power = container_of(dp_power, struct dp_power_private, dp_power); - - rc = dp_power_regulator_ctrl(power, true); - if (rc) { - pr_err("failed to enable regulators\n"); - goto exit; - } - - rc = dp_power_pinctrl_set(power, true); - if (rc) { - pr_err("failed to set pinctrl state\n"); - goto err_pinctrl; - } - - rc = dp_power_config_gpios(power, flip, true); - if (rc) { - pr_err("failed to enable gpios\n"); - goto err_gpio; - } - - rc = sde_power_resource_enable(power->phandle, - power->dp_core_client, true); - if (rc) { - pr_err("Power resource enable failed\n"); - goto err_sde_power; - } - - rc = dp_power_clk_enable(dp_power, DP_CORE_PM, true); - if (rc) { - pr_err("failed to enable DP core clocks\n"); - goto err_clk; - } - - return 0; - -err_clk: - sde_power_resource_enable(power->phandle, power->dp_core_client, false); -err_sde_power: - dp_power_config_gpios(power, flip, false); -err_gpio: - dp_power_pinctrl_set(power, false); -err_pinctrl: - dp_power_regulator_ctrl(power, false); -exit: - return rc; -} - -static int dp_power_deinit(struct dp_power *dp_power) -{ - int rc = 0; - struct dp_power_private *power; - - if (!dp_power) { - pr_err("invalid power data\n"); - rc = -EINVAL; - goto exit; - } - - power = container_of(dp_power, struct dp_power_private, dp_power); - - if (power->link_clks_on) - dp_power_clk_enable(dp_power, DP_LINK_PM, false); - - dp_power_clk_enable(dp_power, DP_CORE_PM, false); - - rc = sde_power_resource_enable(power->phandle, - power->dp_core_client, false); - if (rc) { - pr_err("Power resource disable failed, rc=%d\n", rc); - goto exit; - } - dp_power_config_gpios(power, false, false); - dp_power_pinctrl_set(power, false); - dp_power_regulator_ctrl(power, false); -exit: - return rc; -} - -struct dp_power *dp_power_get(struct dp_parser *parser) -{ - int rc = 0; - struct dp_power_private *power; - struct dp_power *dp_power; - - if (!parser) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto error; - } - - power = devm_kzalloc(&parser->pdev->dev, sizeof(*power), GFP_KERNEL); - if (!power) { - rc = -ENOMEM; - goto error; - } - - power->parser = parser; - power->pdev = parser->pdev; - - dp_power = &power->dp_power; - - dp_power->init = dp_power_init; - dp_power->deinit = dp_power_deinit; - dp_power->clk_enable = dp_power_clk_enable; - dp_power->set_pixel_clk_parent = dp_power_set_pixel_clk_parent; - dp_power->clk_get_rate = dp_power_clk_get_rate; - dp_power->power_client_init = dp_power_client_init; - dp_power->power_client_deinit = dp_power_client_deinit; - - return dp_power; -error: - return ERR_PTR(rc); -} - -void dp_power_put(struct dp_power *dp_power) -{ - struct dp_power_private *power = NULL; - - if (!dp_power) - return; - - power = container_of(dp_power, struct dp_power_private, dp_power); - - devm_kfree(&power->pdev->dev, power); -} diff --git a/drivers/gpu/drm/msm/dp/dp_power.h b/drivers/gpu/drm/msm/dp/dp_power.h deleted file mode 100644 index bd581664ba9bceb6ef2f8c17160ae371b3d1eed4..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_power.h +++ /dev/null @@ -1,51 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. - */ - -#ifndef _DP_POWER_H_ -#define _DP_POWER_H_ - -#include "dp_parser.h" -#include "sde_power_handle.h" - -/** - * sruct dp_power - DisplayPort's power related data - * - * @init: initializes the regulators/core clocks/GPIOs/pinctrl - * @deinit: turns off the regulators/core clocks/GPIOs/pinctrl - * @clk_enable: enable/disable the DP clocks - * @set_pixel_clk_parent: set the parent of DP pixel clock - * @clk_get_rate: get the current rate for provided clk_name - */ -struct dp_power { - int (*init)(struct dp_power *power, bool flip); - int (*deinit)(struct dp_power *power); - int (*clk_enable)(struct dp_power *power, enum dp_pm_type pm_type, - bool enable); - int (*set_pixel_clk_parent)(struct dp_power *power, u32 stream_id); - u64 (*clk_get_rate)(struct dp_power *power, char *clk_name); - int (*power_client_init)(struct dp_power *power, - struct sde_power_handle *phandle); - void (*power_client_deinit)(struct dp_power *power); -}; - -/** - * dp_power_get() - configure and get the DisplayPort power module data - * - * @parser: instance of parser module - * return: pointer to allocated power module data - * - * This API will configure the DisplayPort's power module and provides - * methods to be called by the client to configure the power related - * modueles. - */ -struct dp_power *dp_power_get(struct dp_parser *parser); - -/** - * dp_power_put() - release the power related resources - * - * @power: pointer to the power module's data - */ -void dp_power_put(struct dp_power *power); -#endif /* _DP_POWER_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h deleted file mode 100644 index a66e36da39b043e3330b26d50668b3ae1eab6d13..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_reg.h +++ /dev/null @@ -1,437 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. - */ - -#ifndef _DP_REG_H_ -#define _DP_REG_H_ - -/* DP_TX Registers */ -#define DP_HW_VERSION (0x00000000) -#define DP_SW_RESET (0x00000010) -#define DP_PHY_CTRL (0x00000014) -#define DP_CLK_CTRL (0x00000018) -#define DP_CLK_ACTIVE (0x0000001C) -#define DP_INTR_STATUS (0x00000020) -#define DP_INTR_STATUS2 (0x00000024) -#define DP_INTR_STATUS3 (0x00000028) -#define DP_INTR_STATUS5 (0x00000034) - -#define DP_DP_HPD_CTRL (0x00000000) -#define DP_DP_HPD_INT_STATUS (0x00000004) -#define DP_DP_HPD_INT_ACK (0x00000008) -#define DP_DP_HPD_INT_MASK (0x0000000C) -#define DP_DP_HPD_REFTIMER (0x00000018) -#define DP_DP_HPD_EVENT_TIME_0 (0x0000001C) -#define DP_DP_HPD_EVENT_TIME_1 (0x00000020) -#define DP_AUX_CTRL (0x00000030) -#define DP_AUX_DATA (0x00000034) -#define DP_AUX_TRANS_CTRL (0x00000038) -#define DP_TIMEOUT_COUNT (0x0000003C) -#define DP_AUX_LIMITS (0x00000040) -#define DP_AUX_STATUS (0x00000044) - -#define DP_DPCD_CP_IRQ (0x201) -#define DP_DPCD_RXSTATUS (0x69493) - -#define DP_INTERRUPT_TRANS_NUM (0x000000A0) - -#define DP_MAINLINK_CTRL (0x00000000) -#define DP_STATE_CTRL (0x00000004) -#define DP_CONFIGURATION_CTRL (0x00000008) -#define DP_SOFTWARE_MVID (0x00000010) -#define DP_SOFTWARE_NVID (0x00000018) -#define DP_TOTAL_HOR_VER (0x0000001C) -#define DP_START_HOR_VER_FROM_SYNC (0x00000020) -#define DP_HSYNC_VSYNC_WIDTH_POLARITY (0x00000024) -#define DP_ACTIVE_HOR_VER (0x00000028) -#define DP_MISC1_MISC0 (0x0000002C) -#define DP_VALID_BOUNDARY (0x00000030) -#define DP_VALID_BOUNDARY_2 (0x00000034) -#define DP_LOGICAL2PHYSICAL_LANE_MAPPING (0x00000038) - -#define DP1_CONFIGURATION_CTRL (0x00000400) -#define DP_DP0_TIMESLOT_1_32 (0x00000404) -#define DP_DP0_TIMESLOT_33_63 (0x00000408) -#define DP_DP1_TIMESLOT_1_32 (0x0000040C) -#define DP_DP1_TIMESLOT_33_63 (0x00000410) -#define DP1_SOFTWARE_MVID (0x00000414) -#define DP1_SOFTWARE_NVID (0x00000418) -#define DP1_TOTAL_HOR_VER (0x0000041C) -#define DP1_START_HOR_VER_FROM_SYNC (0x00000420) -#define DP1_HSYNC_VSYNC_WIDTH_POLARITY (0x00000424) -#define DP1_ACTIVE_HOR_VER (0x00000428) -#define DP1_MISC1_MISC0 (0x0000042C) -#define DP_DP0_RG (0x000004F8) -#define DP_DP1_RG (0x000004FC) - -#define DP_MST_ACT (0x00000500) -#define DP_MST_MAINLINK_READY (0x00000504) - -#define DP_MAINLINK_READY (0x00000040) -#define DP_MAINLINK_LEVELS (0x00000044) -#define DP_TU (0x0000004C) - -#define DP_HBR2_COMPLIANCE_SCRAMBLER_RESET (0x00000054) -#define DP_TEST_80BIT_CUSTOM_PATTERN_REG0 (0x000000C0) -#define DP_TEST_80BIT_CUSTOM_PATTERN_REG1 (0x000000C4) -#define DP_TEST_80BIT_CUSTOM_PATTERN_REG2 (0x000000C8) - -#define MMSS_DP_MISC1_MISC0 (0x0000002C) -#define MMSS_DP_AUDIO_TIMING_GEN (0x00000080) -#define MMSS_DP_AUDIO_TIMING_RBR_32 (0x00000084) -#define MMSS_DP_AUDIO_TIMING_HBR_32 (0x00000088) -#define MMSS_DP_AUDIO_TIMING_RBR_44 (0x0000008C) -#define MMSS_DP_AUDIO_TIMING_HBR_44 (0x00000090) -#define MMSS_DP_AUDIO_TIMING_RBR_48 (0x00000094) -#define MMSS_DP_AUDIO_TIMING_HBR_48 (0x00000098) - -#define MMSS_DP_PSR_CRC_RG (0x00000154) -#define MMSS_DP_PSR_CRC_B (0x00000158) - -#define DP_COMPRESSION_MODE_CTRL (0x00000180) -#define DP_PPS_HB_0_3 (0x00000184) -#define DP_PPS_PB_0_3 (0x00000188) -#define DP_PPS_PB_4_7 (0x0000018C) -#define DP_PPS_PB_8_11 (0x00000190) -#define DP_PPS_PB_12_15 (0x00000194) -#define DP_PPS_PB_16_19 (0x00000198) -#define DP_PPS_PB_20_23 (0x0000019C) -#define DP_PPS_PB_24_27 (0x000001A0) -#define DP_PPS_PB_28_31 (0x000001A4) -#define DP_PPS_PPS_0_3 (0x000001A8) -#define DP_PPS_PPS_4_7 (0x000001AC) -#define DP_PPS_PPS_8_11 (0x000001B0) -#define DP_PPS_PPS_12_15 (0x000001B4) -#define DP_PPS_PPS_16_19 (0x000001B8) -#define DP_PPS_PPS_20_23 (0x000001BC) -#define DP_PPS_PPS_24_27 (0x000001C0) -#define DP_PPS_PPS_28_31 (0x000001C4) -#define DP_PPS_PPS_32_35 (0x000001C8) -#define DP_PPS_PPS_36_39 (0x000001CC) -#define DP_PPS_PPS_40_43 (0x000001D0) -#define DP_PPS_PPS_44_47 (0x000001D4) -#define DP_PPS_PPS_48_51 (0x000001D8) -#define DP_PPS_PPS_52_55 (0x000001DC) -#define DP_PPS_PPS_56_59 (0x000001E0) -#define DP_PPS_PPS_60_63 (0x000001E4) -#define DP_PPS_PPS_64_67 (0x000001E8) -#define DP_PPS_PPS_68_71 (0x000001EC) -#define DP_PPS_PPS_72_75 (0x000001F0) -#define DP_PPS_PPS_76_79 (0x000001F4) -#define DP_PPS_PPS_80_83 (0x000001F8) -#define DP_PPS_PPS_84_87 (0x000001FC) - -#define MMSS_DP_AUDIO_CFG (0x00000200) -#define MMSS_DP_AUDIO_STATUS (0x00000204) -#define MMSS_DP_AUDIO_PKT_CTRL (0x00000208) -#define MMSS_DP_AUDIO_PKT_CTRL2 (0x0000020C) -#define MMSS_DP_AUDIO_ACR_CTRL (0x00000210) -#define MMSS_DP_AUDIO_CTRL_RESET (0x00000214) - -#define MMSS_DP_SDP_CFG (0x00000228) -#define MMSS_DP_SDP_CFG2 (0x0000022C) -#define MMSS_DP_SDP_CFG3 (0x0000024C) -#define MMSS_DP_SDP_CFG4 (0x000004EC) -#define MMSS_DP_AUDIO_TIMESTAMP_0 (0x00000230) -#define MMSS_DP_AUDIO_TIMESTAMP_1 (0x00000234) - -#define MMSS_DP_AUDIO_STREAM_0 (0x00000240) -#define MMSS_DP_AUDIO_STREAM_1 (0x00000244) - -#define MMSS_DP_EXTENSION_0 (0x00000250) -#define MMSS_DP_EXTENSION_1 (0x00000254) -#define MMSS_DP_EXTENSION_2 (0x00000258) -#define MMSS_DP_EXTENSION_3 (0x0000025C) -#define MMSS_DP_EXTENSION_4 (0x00000260) -#define MMSS_DP_EXTENSION_5 (0x00000264) -#define MMSS_DP_EXTENSION_6 (0x00000268) -#define MMSS_DP_EXTENSION_7 (0x0000026C) -#define MMSS_DP_EXTENSION_8 (0x00000270) -#define MMSS_DP_EXTENSION_9 (0x00000274) -#define MMSS_DP_AUDIO_COPYMANAGEMENT_0 (0x00000278) -#define MMSS_DP_AUDIO_COPYMANAGEMENT_1 (0x0000027C) -#define MMSS_DP_AUDIO_COPYMANAGEMENT_2 (0x00000280) -#define MMSS_DP_AUDIO_COPYMANAGEMENT_3 (0x00000284) -#define MMSS_DP_AUDIO_COPYMANAGEMENT_4 (0x00000288) -#define MMSS_DP_AUDIO_COPYMANAGEMENT_5 (0x0000028C) -#define MMSS_DP_AUDIO_ISRC_0 (0x00000290) -#define MMSS_DP_AUDIO_ISRC_1 (0x00000294) -#define MMSS_DP_AUDIO_ISRC_2 (0x00000298) -#define MMSS_DP_AUDIO_ISRC_3 (0x0000029C) -#define MMSS_DP_AUDIO_ISRC_4 (0x000002A0) -#define MMSS_DP_AUDIO_ISRC_5 (0x000002A4) -#define MMSS_DP_AUDIO_INFOFRAME_0 (0x000002A8) -#define MMSS_DP_AUDIO_INFOFRAME_1 (0x000002AC) -#define MMSS_DP_AUDIO_INFOFRAME_2 (0x000002B0) - -#define MMSS_DP_FLUSH (0x000002F8) -#define MMSS_DP1_FLUSH (0x000002FC) - -#define MMSS_DP_GENERIC0_0 (0x00000300) -#define MMSS_DP_GENERIC0_1 (0x00000304) -#define MMSS_DP_GENERIC0_2 (0x00000308) -#define MMSS_DP_GENERIC0_3 (0x0000030C) -#define MMSS_DP_GENERIC0_4 (0x00000310) -#define MMSS_DP_GENERIC0_5 (0x00000314) -#define MMSS_DP_GENERIC0_6 (0x00000318) -#define MMSS_DP_GENERIC0_7 (0x0000031C) -#define MMSS_DP_GENERIC0_8 (0x00000320) -#define MMSS_DP_GENERIC0_9 (0x00000324) -#define MMSS_DP_GENERIC1_0 (0x00000328) -#define MMSS_DP_GENERIC1_1 (0x0000032C) -#define MMSS_DP_GENERIC1_2 (0x00000330) -#define MMSS_DP_GENERIC1_3 (0x00000334) -#define MMSS_DP_GENERIC1_4 (0x00000338) -#define MMSS_DP_GENERIC1_5 (0x0000033C) -#define MMSS_DP_GENERIC1_6 (0x00000340) -#define MMSS_DP_GENERIC1_7 (0x00000344) -#define MMSS_DP_GENERIC1_8 (0x00000348) -#define MMSS_DP_GENERIC1_9 (0x0000034C) - -#define MMSS_DP1_GENERIC0_0 (0x00000490) -#define MMSS_DP1_GENERIC0_1 (0x00000494) -#define MMSS_DP1_GENERIC0_2 (0x00000498) -#define MMSS_DP1_GENERIC0_3 (0x0000049C) -#define MMSS_DP1_GENERIC0_4 (0x000004A0) -#define MMSS_DP1_GENERIC0_5 (0x000004A4) -#define MMSS_DP1_GENERIC0_6 (0x000004A8) -#define MMSS_DP1_GENERIC0_7 (0x000004AC) -#define MMSS_DP1_GENERIC0_8 (0x000004B0) -#define MMSS_DP1_GENERIC0_9 (0x000004B4) -#define MMSS_DP1_GENERIC1_0 (0x000004B8) -#define MMSS_DP1_GENERIC1_1 (0x000004BC) -#define MMSS_DP1_GENERIC1_2 (0x000004C0) -#define MMSS_DP1_GENERIC1_3 (0x000004C4) -#define MMSS_DP1_GENERIC1_4 (0x000004C8) -#define MMSS_DP1_GENERIC1_5 (0x000004CC) -#define MMSS_DP1_GENERIC1_6 (0x000004D0) -#define MMSS_DP1_GENERIC1_7 (0x000004D4) -#define MMSS_DP1_GENERIC1_8 (0x000004D8) -#define MMSS_DP1_GENERIC1_9 (0x000004DC) - -#define MMSS_DP_GENERIC2_0 (0x000003d8) -#define MMSS_DP_GENERIC2_1 (0x000003dc) -#define MMSS_DP_GENERIC2_2 (0x000003e0) -#define MMSS_DP_GENERIC2_3 (0x000003e4) -#define MMSS_DP_GENERIC2_4 (0x000003e8) -#define MMSS_DP_GENERIC2_5 (0x000003ec) -#define MMSS_DP_GENERIC2_6 (0x000003f0) -#define MMSS_DP_GENERIC2_7 (0x000003f4) -#define MMSS_DP_GENERIC2_8 (0x000003f8) -#define MMSS_DP_GENERIC2_9 (0x000003fc) -#define MMSS_DP1_GENERIC2_0 (0x00000510) -#define MMSS_DP1_GENERIC2_1 (0x00000514) -#define MMSS_DP1_GENERIC2_2 (0x00000518) -#define MMSS_DP1_GENERIC2_3 (0x0000051c) -#define MMSS_DP1_GENERIC2_4 (0x00000520) -#define MMSS_DP1_GENERIC2_5 (0x00000524) -#define MMSS_DP1_GENERIC2_6 (0x00000528) -#define MMSS_DP1_GENERIC2_7 (0x0000052C) -#define MMSS_DP1_GENERIC2_8 (0x00000530) -#define MMSS_DP1_GENERIC2_9 (0x00000534) - -#define MMSS_DP1_SDP_CFG (0x000004E0) -#define MMSS_DP1_SDP_CFG2 (0x000004E4) -#define MMSS_DP1_SDP_CFG3 (0x000004E8) -#define MMSS_DP1_SDP_CFG4 (0x000004F0) - -#define DP1_COMPRESSION_MODE_CTRL (0x00000560) -#define DP1_PPS_HB_0_3 (0x00000564) -#define DP1_PPS_PB_0_3 (0x00000568) -#define DP1_PPS_PB_4_7 (0x0000056C) -#define DP1_PPS_PB_8_11 (0x00000570) -#define DP1_PPS_PB_12_15 (0x00000574) -#define DP1_PPS_PB_16_19 (0x00000578) -#define DP1_PPS_PB_20_23 (0x0000057C) -#define DP1_PPS_PB_24_27 (0x00000580) -#define DP1_PPS_PB_28_31 (0x00000584) -#define DP1_PPS_PPS_0_3 (0x00000588) -#define DP1_PPS_PPS_4_7 (0x0000058C) -#define DP1_PPS_PPS_8_11 (0x00000590) -#define DP1_PPS_PPS_12_15 (0x00000594) -#define DP1_PPS_PPS_16_19 (0x00000598) -#define DP1_PPS_PPS_20_23 (0x0000059C) -#define DP1_PPS_PPS_24_27 (0x000005A0) -#define DP1_PPS_PPS_28_31 (0x000005A4) -#define DP1_PPS_PPS_32_35 (0x000005A8) -#define DP1_PPS_PPS_36_39 (0x000005AC) -#define DP1_PPS_PPS_40_43 (0x000005B0) -#define DP1_PPS_PPS_44_47 (0x000005B4) -#define DP1_PPS_PPS_48_51 (0x000005B8) -#define DP1_PPS_PPS_52_55 (0x000005BC) -#define DP1_PPS_PPS_56_59 (0x000005C0) -#define DP1_PPS_PPS_60_63 (0x000005C4) -#define DP1_PPS_PPS_64_67 (0x000005C8) -#define DP1_PPS_PPS_68_71 (0x000005CC) -#define DP1_PPS_PPS_72_75 (0x000005D0) -#define DP1_PPS_PPS_76_79 (0x000005D4) -#define DP1_PPS_PPS_80_83 (0x000005D8) -#define DP1_PPS_PPS_84_87 (0x000005DC) - -#define MMSS_DP_VSCEXT_0 (0x000002D0) -#define MMSS_DP_VSCEXT_1 (0x000002D4) -#define MMSS_DP_VSCEXT_2 (0x000002D8) -#define MMSS_DP_VSCEXT_3 (0x000002DC) -#define MMSS_DP_VSCEXT_4 (0x000002E0) -#define MMSS_DP_VSCEXT_5 (0x000002E4) -#define MMSS_DP_VSCEXT_6 (0x000002E8) -#define MMSS_DP_VSCEXT_7 (0x000002EC) -#define MMSS_DP_VSCEXT_8 (0x000002F0) -#define MMSS_DP_VSCEXT_9 (0x000002F4) - -#define MMSS_DP1_VSCEXT_0 (0x00000468) -#define MMSS_DP1_VSCEXT_1 (0x0000046c) -#define MMSS_DP1_VSCEXT_2 (0x00000470) -#define MMSS_DP1_VSCEXT_3 (0x00000474) -#define MMSS_DP1_VSCEXT_4 (0x00000478) -#define MMSS_DP1_VSCEXT_5 (0x0000047c) -#define MMSS_DP1_VSCEXT_6 (0x00000480) -#define MMSS_DP1_VSCEXT_7 (0x00000484) -#define MMSS_DP1_VSCEXT_8 (0x00000488) -#define MMSS_DP1_VSCEXT_9 (0x0000048c) - -#define MMSS_DP_BIST_ENABLE (0x00000000) -#define MMSS_DP_TIMING_ENGINE_EN (0x00000010) -#define MMSS_DP_INTF_CONFIG (0x00000014) -#define MMSS_DP_INTF_HSYNC_CTL (0x00000018) -#define MMSS_DP_INTF_VSYNC_PERIOD_F0 (0x0000001C) -#define MMSS_DP_INTF_VSYNC_PERIOD_F1 (0x00000020) -#define MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F0 (0x00000024) -#define MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F1 (0x00000028) -#define MMSS_INTF_DISPLAY_V_START_F0 (0x0000002C) -#define MMSS_INTF_DISPLAY_V_START_F1 (0x00000030) -#define MMSS_DP_INTF_DISPLAY_V_END_F0 (0x00000034) -#define MMSS_DP_INTF_DISPLAY_V_END_F1 (0x00000038) -#define MMSS_DP_INTF_ACTIVE_V_START_F0 (0x0000003C) -#define MMSS_DP_INTF_ACTIVE_V_START_F1 (0x00000040) -#define MMSS_DP_INTF_ACTIVE_V_END_F0 (0x00000044) -#define MMSS_DP_INTF_ACTIVE_V_END_F1 (0x00000048) -#define MMSS_DP_INTF_DISPLAY_HCTL (0x0000004C) -#define MMSS_DP_INTF_ACTIVE_HCTL (0x00000050) -#define MMSS_DP_INTF_POLARITY_CTL (0x00000058) -#define MMSS_DP_TPG_MAIN_CONTROL (0x00000060) -#define MMSS_DP_TPG_VIDEO_CONFIG (0x00000064) -#define MMSS_DP_DSC_DTO (0x0000007C) -#define MMSS_DP_DSC_DTO_COUNT (0x00000084) -#define MMSS_DP_ASYNC_FIFO_CONFIG (0x00000088) - -#define MMSS_DP1_BIST_ENABLE (0x00000000) -#define MMSS_DP1_TIMING_ENGINE_EN (0x00000010) -#define MMSS_DP1_INTF_CONFIG (0x00000014) -#define MMSS_DP1_INTF_HSYNC_CTL (0x00000018) -#define MMSS_DP1_INTF_VSYNC_PERIOD_F0 (0x0000001C) -#define MMSS_DP1_INTF_VSYNC_PERIOD_F1 (0x00000020) -#define MMSS_DP1_INTF_VSYNC_PULSE_WIDTH_F0 (0x00000024) -#define MMSS_DP1_INTF_VSYNC_PULSE_WIDTH_F1 (0x00000028) -#define MMSS_DP1_INTF_DISPLAY_V_START_F0 (0x0000002C) -#define MMSS_DP1_INTF_DISPLAY_V_START_F1 (0x00000030) -#define MMSS_DP1_INTF_DISPLAY_V_END_F0 (0x00000034) -#define MMSS_DP1_INTF_DISPLAY_V_END_F1 (0x00000038) -#define MMSS_DP1_INTF_ACTIVE_V_START_F0 (0x0000003C) -#define MMSS_DP1_INTF_ACTIVE_V_START_F1 (0x00000040) -#define MMSS_DP1_INTF_ACTIVE_V_END_F0 (0x00000044) -#define MMSS_DP1_INTF_ACTIVE_V_END_F1 (0x00000048) -#define MMSS_DP1_INTF_DISPLAY_HCTL (0x0000004C) -#define MMSS_DP1_INTF_ACTIVE_HCTL (0x00000050) -#define MMSS_DP1_INTF_POLARITY_CTL (0x00000058) -#define MMSS_DP1_TPG_MAIN_CONTROL (0x00000060) -#define MMSS_DP1_TPG_VIDEO_CONFIG (0x00000064) -#define MMSS_DP1_DSC_DTO (0x0000007C) -#define MMSS_DP1_DSC_DTO_COUNT (0x00000084) -#define MMSS_DP1_ASYNC_FIFO_CONFIG (0x00000088) - -/*DP PHY Register offsets */ -#define DP_PHY_REVISION_ID0 (0x00000000) -#define DP_PHY_REVISION_ID1 (0x00000004) -#define DP_PHY_REVISION_ID2 (0x00000008) -#define DP_PHY_REVISION_ID3 (0x0000000C) - -#define DP_PHY_CFG (0x00000010) -#define DP_PHY_PD_CTL (0x00000018) -#define DP_PHY_MODE (0x0000001C) - -#define DP_PHY_AUX_CFG0 (0x00000020) -#define DP_PHY_AUX_CFG1 (0x00000024) -#define DP_PHY_AUX_CFG2 (0x00000028) -#define DP_PHY_AUX_CFG3 (0x0000002C) -#define DP_PHY_AUX_CFG4 (0x00000030) -#define DP_PHY_AUX_CFG5 (0x00000034) -#define DP_PHY_AUX_CFG6 (0x00000038) -#define DP_PHY_AUX_CFG7 (0x0000003C) -#define DP_PHY_AUX_CFG8 (0x00000040) -#define DP_PHY_AUX_CFG9 (0x00000044) -#define DP_PHY_AUX_INTERRUPT_MASK (0x00000048) -#define DP_PHY_AUX_INTERRUPT_CLEAR (0x0000004C) -#define DP_PHY_AUX_INTERRUPT_STATUS (0x000000BC) -#define DP_PHY_AUX_INTERRUPT_MASK_V200 (0x00000048) -#define DP_PHY_AUX_INTERRUPT_CLEAR_V200 (0x0000004C) -#define DP_PHY_AUX_INTERRUPT_STATUS_V200 (0x000000BC) - -#define DP_PHY_SPARE0 (0x00AC) - -#define TXn_TX_EMP_POST1_LVL (0x000C) -#define TXn_TX_DRV_LVL (0x001C) -#define TXn_TX_POL_INV (0x0064) - -#define DP_PHY_AUX_INTERRUPT_MASK_V420 (0x0054) -#define DP_PHY_AUX_INTERRUPT_CLEAR_V420 (0x0058) -#define DP_PHY_AUX_INTERRUPT_STATUS_V420 (0x00D8) -#define DP_PHY_SPARE0_V420 (0x00C8) -#define TXn_TX_DRV_LVL_V420 (0x0014) -#define TXn_TX_POL_INV_V420 (0x005C) - -#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN (0x004) - -/* DP MMSS_CC registers */ -#define MMSS_DP_LINK_CMD_RCGR (0x0138) -#define MMSS_DP_LINK_CFG_RCGR (0x013C) -#define MMSS_DP_PIXEL_M (0x01B4) -#define MMSS_DP_PIXEL_N (0x01B8) -#define MMSS_DP_PIXEL1_M (0x01CC) -#define MMSS_DP_PIXEL1_N (0x01D0) -#define MMSS_DP_PIXEL_M_V200 (0x0130) -#define MMSS_DP_PIXEL_N_V200 (0x0134) -#define MMSS_DP_PIXEL1_M_V200 (0x0148) -#define MMSS_DP_PIXEL1_N_V200 (0x014C) -#define MMSS_DP_PIXEL_M_V420 (0x01B4) -#define MMSS_DP_PIXEL_N_V420 (0x01B8) -#define MMSS_DP_PIXEL1_M_V420 (0x01CC) -#define MMSS_DP_PIXEL1_N_V420 (0x01D0) - -/* DP HDCP 1.3 registers */ -#define DP_HDCP_CTRL (0x0A0) -#define DP_HDCP_STATUS (0x0A4) -#define DP_HDCP_SW_UPPER_AKSV (0x098) -#define DP_HDCP_SW_LOWER_AKSV (0x09C) -#define DP_HDCP_ENTROPY_CTRL0 (0x350) -#define DP_HDCP_ENTROPY_CTRL1 (0x35C) -#define DP_HDCP_SHA_STATUS (0x0C8) -#define DP_HDCP_RCVPORT_DATA2_0 (0x0B0) -#define DP_HDCP_RCVPORT_DATA3 (0x0A4) -#define DP_HDCP_RCVPORT_DATA4 (0x0A8) -#define DP_HDCP_RCVPORT_DATA5 (0x0C0) -#define DP_HDCP_RCVPORT_DATA6 (0x0C4) - -#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_SHA_CTRL (0x024) -#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_SHA_DATA (0x028) -#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA0 (0x004) -#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA1 (0x008) -#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA7 (0x00C) -#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA8 (0x010) -#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA9 (0x014) -#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA10 (0x018) -#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA11 (0x01C) -#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA12 (0x020) - -/* USB3 DP COM registers */ -#define USB3_DP_COM_RESET_OVRD_CTRL (0x1C) -#define USB3_DP_COM_PHY_MODE_CTRL (0x00) -#define USB3_DP_COM_SW_RESET (0x04) -#define USB3_DP_COM_TYPEC_CTRL (0x10) -#define USB3_DP_COM_SWI_CTRL (0x0c) -#define USB3_DP_COM_POWER_DOWN_CTRL (0x08) - - - -#endif /* _DP_REG_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_usbpd.c b/drivers/gpu/drm/msm/dp/dp_usbpd.c deleted file mode 100644 index 7b5a48048e716d260e7bb22fab6a94dbf2743127..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_usbpd.c +++ /dev/null @@ -1,563 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ - -#include -#include -#include -#include - -#include "dp_usbpd.h" - -/* DP specific VDM commands */ -#define DP_USBPD_VDM_STATUS 0x10 -#define DP_USBPD_VDM_CONFIGURE 0x11 - -/* USBPD-TypeC specific Macros */ -#define VDM_VERSION 0x0 -#define USB_C_DP_SID 0xFF01 - -enum dp_usbpd_pin_assignment { - DP_USBPD_PIN_A, - DP_USBPD_PIN_B, - DP_USBPD_PIN_C, - DP_USBPD_PIN_D, - DP_USBPD_PIN_E, - DP_USBPD_PIN_F, - DP_USBPD_PIN_MAX, -}; - -enum dp_usbpd_events { - DP_USBPD_EVT_DISCOVER, - DP_USBPD_EVT_ENTER, - DP_USBPD_EVT_STATUS, - DP_USBPD_EVT_CONFIGURE, - DP_USBPD_EVT_CC_PIN_POLARITY, - DP_USBPD_EVT_EXIT, - DP_USBPD_EVT_ATTENTION, -}; - -enum dp_usbpd_alt_mode { - DP_USBPD_ALT_MODE_NONE = 0, - DP_USBPD_ALT_MODE_INIT = BIT(0), - DP_USBPD_ALT_MODE_DISCOVER = BIT(1), - DP_USBPD_ALT_MODE_ENTER = BIT(2), - DP_USBPD_ALT_MODE_STATUS = BIT(3), - DP_USBPD_ALT_MODE_CONFIGURE = BIT(4), -}; - -struct dp_usbpd_capabilities { - enum dp_usbpd_port port; - bool receptacle_state; - u8 ulink_pin_config; - u8 dlink_pin_config; -}; - -struct dp_usbpd_private { - bool forced_disconnect; - u32 vdo; - struct device *dev; - struct usbpd *pd; - struct usbpd_svid_handler svid_handler; - struct dp_hpd_cb *dp_cb; - struct dp_usbpd_capabilities cap; - struct dp_usbpd dp_usbpd; - enum dp_usbpd_alt_mode alt_mode; - u32 dp_usbpd_config; -}; - -static const char *dp_usbpd_pin_name(u8 pin) -{ - switch (pin) { - case DP_USBPD_PIN_A: return "DP_USBPD_PIN_ASSIGNMENT_A"; - case DP_USBPD_PIN_B: return "DP_USBPD_PIN_ASSIGNMENT_B"; - case DP_USBPD_PIN_C: return "DP_USBPD_PIN_ASSIGNMENT_C"; - case DP_USBPD_PIN_D: return "DP_USBPD_PIN_ASSIGNMENT_D"; - case DP_USBPD_PIN_E: return "DP_USBPD_PIN_ASSIGNMENT_E"; - case DP_USBPD_PIN_F: return "DP_USBPD_PIN_ASSIGNMENT_F"; - default: return "UNKNOWN"; - } -} - -static const char *dp_usbpd_port_name(enum dp_usbpd_port port) -{ - switch (port) { - case DP_USBPD_PORT_NONE: return "DP_USBPD_PORT_NONE"; - case DP_USBPD_PORT_UFP_D: return "DP_USBPD_PORT_UFP_D"; - case DP_USBPD_PORT_DFP_D: return "DP_USBPD_PORT_DFP_D"; - case DP_USBPD_PORT_D_UFP_D: return "DP_USBPD_PORT_D_UFP_D"; - default: return "DP_USBPD_PORT_NONE"; - } -} - -static const char *dp_usbpd_cmd_name(u8 cmd) -{ - switch (cmd) { - case USBPD_SVDM_DISCOVER_MODES: return "USBPD_SVDM_DISCOVER_MODES"; - case USBPD_SVDM_ENTER_MODE: return "USBPD_SVDM_ENTER_MODE"; - case USBPD_SVDM_ATTENTION: return "USBPD_SVDM_ATTENTION"; - case DP_USBPD_VDM_STATUS: return "DP_USBPD_VDM_STATUS"; - case DP_USBPD_VDM_CONFIGURE: return "DP_USBPD_VDM_CONFIGURE"; - default: return "DP_USBPD_VDM_ERROR"; - } -} - -static void dp_usbpd_init_port(enum dp_usbpd_port *port, u32 in_port) -{ - switch (in_port) { - case 0: - *port = DP_USBPD_PORT_NONE; - break; - case 1: - *port = DP_USBPD_PORT_UFP_D; - break; - case 2: - *port = DP_USBPD_PORT_DFP_D; - break; - case 3: - *port = DP_USBPD_PORT_D_UFP_D; - break; - default: - *port = DP_USBPD_PORT_NONE; - } - pr_debug("port:%s\n", dp_usbpd_port_name(*port)); -} - -static void dp_usbpd_get_capabilities(struct dp_usbpd_private *pd) -{ - struct dp_usbpd_capabilities *cap = &pd->cap; - u32 buf = pd->vdo; - int port = buf & 0x3; - - cap->receptacle_state = (buf & BIT(6)) ? true : false; - cap->dlink_pin_config = (buf >> 8) & 0xff; - cap->ulink_pin_config = (buf >> 16) & 0xff; - - dp_usbpd_init_port(&cap->port, port); -} - -static void dp_usbpd_get_status(struct dp_usbpd_private *pd) -{ - struct dp_usbpd *status = &pd->dp_usbpd; - u32 buf = pd->vdo; - int port = buf & 0x3; - - status->low_pow_st = (buf & BIT(2)) ? true : false; - status->adaptor_dp_en = (buf & BIT(3)) ? true : false; - status->base.multi_func = (buf & BIT(4)) ? true : false; - status->usb_config_req = (buf & BIT(5)) ? true : false; - status->exit_dp_mode = (buf & BIT(6)) ? true : false; - status->base.hpd_high = (buf & BIT(7)) ? true : false; - status->base.hpd_irq = (buf & BIT(8)) ? true : false; - - pr_debug("low_pow_st = %d, adaptor_dp_en = %d, multi_func = %d\n", - status->low_pow_st, status->adaptor_dp_en, - status->base.multi_func); - pr_debug("usb_config_req = %d, exit_dp_mode = %d, hpd_high =%d\n", - status->usb_config_req, - status->exit_dp_mode, status->base.hpd_high); - pr_debug("hpd_irq = %d\n", status->base.hpd_irq); - - dp_usbpd_init_port(&status->port, port); -} - -static u32 dp_usbpd_gen_config_pkt(struct dp_usbpd_private *pd) -{ - u8 pin_cfg, pin; - u32 config = 0; - const u32 ufp_d_config = 0x2, dp_ver = 0x1; - - if (pd->cap.receptacle_state) - pin_cfg = pd->cap.ulink_pin_config; - else - pin_cfg = pd->cap.dlink_pin_config; - - for (pin = DP_USBPD_PIN_A; pin < DP_USBPD_PIN_MAX; pin++) { - if (pin_cfg & BIT(pin)) { - if (pd->dp_usbpd.base.multi_func) { - if (pin == DP_USBPD_PIN_D) - break; - } else { - break; - } - } - } - - if (pin == DP_USBPD_PIN_MAX) - pin = DP_USBPD_PIN_C; - - pr_debug("pin assignment: %s\n", dp_usbpd_pin_name(pin)); - - config |= BIT(pin) << 8; - - config |= (dp_ver << 2); - config |= ufp_d_config; - - pr_debug("config = 0x%x\n", config); - return config; -} - -static void dp_usbpd_send_event(struct dp_usbpd_private *pd, - enum dp_usbpd_events event) -{ - u32 config; - - switch (event) { - case DP_USBPD_EVT_DISCOVER: - usbpd_send_svdm(pd->pd, USB_C_DP_SID, - USBPD_SVDM_DISCOVER_MODES, - SVDM_CMD_TYPE_INITIATOR, 0x0, 0x0, 0x0); - break; - case DP_USBPD_EVT_ENTER: - usbpd_send_svdm(pd->pd, USB_C_DP_SID, - USBPD_SVDM_ENTER_MODE, - SVDM_CMD_TYPE_INITIATOR, 0x1, 0x0, 0x0); - break; - case DP_USBPD_EVT_EXIT: - usbpd_send_svdm(pd->pd, USB_C_DP_SID, - USBPD_SVDM_EXIT_MODE, - SVDM_CMD_TYPE_INITIATOR, 0x1, 0x0, 0x0); - break; - case DP_USBPD_EVT_STATUS: - config = 0x1; /* DFP_D connected */ - usbpd_send_svdm(pd->pd, USB_C_DP_SID, DP_USBPD_VDM_STATUS, - SVDM_CMD_TYPE_INITIATOR, 0x1, &config, 0x1); - break; - case DP_USBPD_EVT_CONFIGURE: - config = dp_usbpd_gen_config_pkt(pd); - usbpd_send_svdm(pd->pd, USB_C_DP_SID, DP_USBPD_VDM_CONFIGURE, - SVDM_CMD_TYPE_INITIATOR, 0x1, &config, 0x1); - break; - default: - pr_err("unknown event:%d\n", event); - } -} - -static void dp_usbpd_connect_cb(struct usbpd_svid_handler *hdlr) -{ - struct dp_usbpd_private *pd; - - pd = container_of(hdlr, struct dp_usbpd_private, svid_handler); - if (!pd) { - pr_err("get_usbpd phandle failed\n"); - return; - } - - pr_debug("\n"); - dp_usbpd_send_event(pd, DP_USBPD_EVT_DISCOVER); -} - -static void dp_usbpd_disconnect_cb(struct usbpd_svid_handler *hdlr) -{ - struct dp_usbpd_private *pd; - - pd = container_of(hdlr, struct dp_usbpd_private, svid_handler); - if (!pd) { - pr_err("get_usbpd phandle failed\n"); - return; - } - - pd->alt_mode = DP_USBPD_ALT_MODE_NONE; - pd->dp_usbpd.base.alt_mode_cfg_done = false; - pr_debug("\n"); - - if (pd->dp_cb && pd->dp_cb->disconnect) - pd->dp_cb->disconnect(pd->dev); -} - -static int dp_usbpd_validate_callback(u8 cmd, - enum usbpd_svdm_cmd_type cmd_type, int num_vdos) -{ - int ret = 0; - - if (cmd_type == SVDM_CMD_TYPE_RESP_NAK) { - pr_err("error: NACK\n"); - ret = -EINVAL; - goto end; - } - - if (cmd_type == SVDM_CMD_TYPE_RESP_BUSY) { - pr_err("error: BUSY\n"); - ret = -EBUSY; - goto end; - } - - if (cmd == USBPD_SVDM_ATTENTION) { - if (cmd_type != SVDM_CMD_TYPE_INITIATOR) { - pr_err("error: invalid cmd type for attention\n"); - ret = -EINVAL; - goto end; - } - - if (!num_vdos) { - pr_err("error: no vdo provided\n"); - ret = -EINVAL; - goto end; - } - } else { - if (cmd_type != SVDM_CMD_TYPE_RESP_ACK) { - pr_err("error: invalid cmd type\n"); - ret = -EINVAL; - } - } -end: - return ret; -} - - -static int dp_usbpd_get_ss_lanes(struct dp_usbpd_private *pd) -{ - int rc = 0; - int timeout = 250; - - /* - * By default, USB reserves two lanes for Super Speed. - * Which means DP has remaining two lanes to operate on. - * If multi-function is not supported, request USB to - * release the Super Speed lanes so that DP can use - * all four lanes in case DPCD indicates support for - * four lanes. - */ - if (!pd->dp_usbpd.base.multi_func) { - while (timeout) { - rc = pd->svid_handler.request_usb_ss_lane( - pd->pd, &pd->svid_handler); - if (rc != -EBUSY) - break; - - pr_warn("USB busy, retry\n"); - - /* wait for hw recommended delay for usb */ - msleep(20); - timeout--; - } - } - - return rc; -} - -static void dp_usbpd_response_cb(struct usbpd_svid_handler *hdlr, u8 cmd, - enum usbpd_svdm_cmd_type cmd_type, - const u32 *vdos, int num_vdos) -{ - struct dp_usbpd_private *pd; - int rc = 0; - - pd = container_of(hdlr, struct dp_usbpd_private, svid_handler); - - pr_debug("callback -> cmd: %s, *vdos = 0x%x, num_vdos = %d\n", - dp_usbpd_cmd_name(cmd), *vdos, num_vdos); - - if (dp_usbpd_validate_callback(cmd, cmd_type, num_vdos)) { - pr_debug("invalid callback received\n"); - return; - } - - switch (cmd) { - case USBPD_SVDM_DISCOVER_MODES: - pd->vdo = *vdos; - dp_usbpd_get_capabilities(pd); - - pd->alt_mode |= DP_USBPD_ALT_MODE_DISCOVER; - - if (pd->cap.port & BIT(0)) - dp_usbpd_send_event(pd, DP_USBPD_EVT_ENTER); - break; - case USBPD_SVDM_ENTER_MODE: - pd->alt_mode |= DP_USBPD_ALT_MODE_ENTER; - - dp_usbpd_send_event(pd, DP_USBPD_EVT_STATUS); - break; - case USBPD_SVDM_ATTENTION: - if (pd->forced_disconnect) - break; - - pd->vdo = *vdos; - dp_usbpd_get_status(pd); - - if (!pd->dp_usbpd.base.alt_mode_cfg_done) { - if (pd->dp_usbpd.port & BIT(1)) - dp_usbpd_send_event(pd, DP_USBPD_EVT_CONFIGURE); - break; - } - - if (pd->dp_cb && pd->dp_cb->attention) - pd->dp_cb->attention(pd->dev); - - break; - case DP_USBPD_VDM_STATUS: - pd->vdo = *vdos; - dp_usbpd_get_status(pd); - - if (!(pd->alt_mode & DP_USBPD_ALT_MODE_CONFIGURE)) { - pd->alt_mode |= DP_USBPD_ALT_MODE_STATUS; - - if (pd->dp_usbpd.port & BIT(1)) - dp_usbpd_send_event(pd, DP_USBPD_EVT_CONFIGURE); - } - break; - case DP_USBPD_VDM_CONFIGURE: - pd->alt_mode |= DP_USBPD_ALT_MODE_CONFIGURE; - pd->dp_usbpd.base.alt_mode_cfg_done = true; - dp_usbpd_get_status(pd); - - pd->dp_usbpd.base.orientation = - usbpd_get_plug_orientation(pd->pd); - - rc = dp_usbpd_get_ss_lanes(pd); - if (rc) { - pr_err("failed to get SuperSpeed lanes\n"); - break; - } - - if (pd->dp_cb && pd->dp_cb->configure) - pd->dp_cb->configure(pd->dev); - break; - default: - pr_err("unknown cmd: %d\n", cmd); - break; - } -} - -static int dp_usbpd_simulate_connect(struct dp_hpd *dp_hpd, bool hpd) -{ - int rc = 0; - struct dp_usbpd *dp_usbpd; - struct dp_usbpd_private *pd; - - if (!dp_hpd) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto error; - } - - dp_usbpd = container_of(dp_hpd, struct dp_usbpd, base); - pd = container_of(dp_usbpd, struct dp_usbpd_private, dp_usbpd); - - dp_usbpd->base.hpd_high = hpd; - pd->forced_disconnect = !hpd; - pd->dp_usbpd.base.alt_mode_cfg_done = hpd; - - pr_debug("hpd_high=%d, forced_disconnect=%d, orientation=%d\n", - dp_usbpd->base.hpd_high, pd->forced_disconnect, - pd->dp_usbpd.base.orientation); - if (hpd) - pd->dp_cb->configure(pd->dev); - else - pd->dp_cb->disconnect(pd->dev); - -error: - return rc; -} - -static int dp_usbpd_simulate_attention(struct dp_hpd *dp_hpd, int vdo) -{ - int rc = 0; - struct dp_usbpd *dp_usbpd; - struct dp_usbpd_private *pd; - - dp_usbpd = container_of(dp_hpd, struct dp_usbpd, base); - if (!dp_usbpd) { - pr_err("invalid input\n"); - rc = -EINVAL; - goto error; - } - - pd = container_of(dp_usbpd, struct dp_usbpd_private, dp_usbpd); - - pd->vdo = vdo; - dp_usbpd_get_status(pd); - - if (pd->dp_cb && pd->dp_cb->attention) - pd->dp_cb->attention(pd->dev); -error: - return rc; -} - -int dp_usbpd_register(struct dp_hpd *dp_hpd) -{ - struct dp_usbpd *dp_usbpd; - struct dp_usbpd_private *usbpd; - int rc = 0; - - if (!dp_hpd) - return -EINVAL; - - dp_usbpd = container_of(dp_hpd, struct dp_usbpd, base); - - usbpd = container_of(dp_usbpd, struct dp_usbpd_private, dp_usbpd); - - rc = usbpd_register_svid(usbpd->pd, &usbpd->svid_handler); - if (rc) - pr_err("pd registration failed\n"); - - return rc; -} - -struct dp_hpd *dp_usbpd_get(struct device *dev, struct dp_hpd_cb *cb) -{ - int rc = 0; - const char *pd_phandle = "qcom,dp-usbpd-detection"; - struct usbpd *pd = NULL; - struct dp_usbpd_private *usbpd; - struct dp_usbpd *dp_usbpd; - struct usbpd_svid_handler svid_handler = { - .svid = USB_C_DP_SID, - .vdm_received = NULL, - .connect = &dp_usbpd_connect_cb, - .svdm_received = &dp_usbpd_response_cb, - .disconnect = &dp_usbpd_disconnect_cb, - }; - - if (!cb) { - pr_err("invalid cb data\n"); - rc = -EINVAL; - goto error; - } - - pd = devm_usbpd_get_by_phandle(dev, pd_phandle); - if (IS_ERR(pd)) { - pr_err("usbpd phandle failed (%ld)\n", PTR_ERR(pd)); - rc = PTR_ERR(pd); - goto error; - } - - usbpd = devm_kzalloc(dev, sizeof(*usbpd), GFP_KERNEL); - if (!usbpd) { - rc = -ENOMEM; - goto error; - } - - usbpd->dev = dev; - usbpd->pd = pd; - usbpd->svid_handler = svid_handler; - usbpd->dp_cb = cb; - - dp_usbpd = &usbpd->dp_usbpd; - dp_usbpd->base.simulate_connect = dp_usbpd_simulate_connect; - dp_usbpd->base.simulate_attention = dp_usbpd_simulate_attention; - dp_usbpd->base.register_hpd = dp_usbpd_register; - - return &dp_usbpd->base; -error: - return ERR_PTR(rc); -} - -void dp_usbpd_put(struct dp_hpd *dp_hpd) -{ - struct dp_usbpd *dp_usbpd; - struct dp_usbpd_private *usbpd; - - dp_usbpd = container_of(dp_hpd, struct dp_usbpd, base); - if (!dp_usbpd) - return; - - usbpd = container_of(dp_usbpd, struct dp_usbpd_private, dp_usbpd); - - usbpd_unregister_svid(usbpd->pd, &usbpd->svid_handler); - - devm_kfree(usbpd->dev, usbpd); -} diff --git a/drivers/gpu/drm/msm/dp/dp_usbpd.h b/drivers/gpu/drm/msm/dp/dp_usbpd.h deleted file mode 100644 index 899ac4c5960ccf0ef94fd0c23d3f6a9b94ac63aa..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dp/dp_usbpd.h +++ /dev/null @@ -1,64 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. - */ - -#ifndef _DP_USBPD_H_ -#define _DP_USBPD_H_ - -#include -#include "dp_hpd.h" - -struct device; - -/** - * enum dp_usbpd_port - usb/dp port type - * @DP_USBPD_PORT_NONE: port not configured - * @DP_USBPD_PORT_UFP_D: Upstream Facing Port - DisplayPort - * @DP_USBPD_PORT_DFP_D: Downstream Facing Port - DisplayPort - * @DP_USBPD_PORT_D_UFP_D: Both UFP & DFP - DisplayPort - */ - -enum dp_usbpd_port { - DP_USBPD_PORT_NONE, - DP_USBPD_PORT_UFP_D, - DP_USBPD_PORT_DFP_D, - DP_USBPD_PORT_D_UFP_D, -}; - -/** - * struct dp_usbpd - DisplayPort status - * - * @port: port configured - * @low_pow_st: low power state - * @adaptor_dp_en: adaptor functionality enabled - * @usb_config_req: request to switch to usb - * @exit_dp_mode: request exit from displayport mode - * @debug_en: bool to specify debug mode - */ -struct dp_usbpd { - struct dp_hpd base; - enum dp_usbpd_port port; - bool low_pow_st; - bool adaptor_dp_en; - bool usb_config_req; - bool exit_dp_mode; - bool debug_en; -}; - -/** - * dp_usbpd_get() - setup usbpd module - * - * @dev: device instance of the caller - * @cb: struct containing callback function pointers. - * - * This function allows the client to initialize the usbpd - * module. The module will communicate with usb driver and - * handles the power delivery (PD) communication with the - * sink/usb device. This module will notify the client using - * the callback functions about the connection and status. - */ -struct dp_hpd *dp_usbpd_get(struct device *dev, struct dp_hpd_cb *cb); - -void dp_usbpd_put(struct dp_hpd *pd); -#endif /* _DP_USBPD_H_ */ diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c deleted file mode 100644 index c19372cf3cb5eb3ba2cc4a078f62ca5bb39a138b..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c +++ /dev/null @@ -1,298 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "msm-dsi-catalog:[%s] " fmt, __func__ -#include - -#include "dsi_catalog.h" - -/** - * dsi_catalog_cmn_init() - catalog init for dsi controller v1.4 - */ -static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl, - enum dsi_ctrl_version version) -{ - /* common functions */ - ctrl->ops.host_setup = dsi_ctrl_hw_cmn_host_setup; - ctrl->ops.video_engine_en = dsi_ctrl_hw_cmn_video_engine_en; - ctrl->ops.video_engine_setup = dsi_ctrl_hw_cmn_video_engine_setup; - ctrl->ops.set_video_timing = dsi_ctrl_hw_cmn_set_video_timing; - ctrl->ops.set_timing_db = dsi_ctrl_hw_cmn_set_timing_db; - ctrl->ops.cmd_engine_setup = dsi_ctrl_hw_cmn_cmd_engine_setup; - ctrl->ops.setup_cmd_stream = dsi_ctrl_hw_cmn_setup_cmd_stream; - ctrl->ops.ctrl_en = dsi_ctrl_hw_cmn_ctrl_en; - ctrl->ops.cmd_engine_en = dsi_ctrl_hw_cmn_cmd_engine_en; - ctrl->ops.phy_sw_reset = dsi_ctrl_hw_cmn_phy_sw_reset; - ctrl->ops.soft_reset = dsi_ctrl_hw_cmn_soft_reset; - ctrl->ops.kickoff_command = dsi_ctrl_hw_cmn_kickoff_command; - ctrl->ops.kickoff_fifo_command = dsi_ctrl_hw_cmn_kickoff_fifo_command; - ctrl->ops.reset_cmd_fifo = dsi_ctrl_hw_cmn_reset_cmd_fifo; - ctrl->ops.trigger_command_dma = dsi_ctrl_hw_cmn_trigger_command_dma; - ctrl->ops.get_interrupt_status = dsi_ctrl_hw_cmn_get_interrupt_status; - ctrl->ops.get_error_status = dsi_ctrl_hw_cmn_get_error_status; - ctrl->ops.clear_error_status = dsi_ctrl_hw_cmn_clear_error_status; - ctrl->ops.clear_interrupt_status = - dsi_ctrl_hw_cmn_clear_interrupt_status; - ctrl->ops.enable_status_interrupts = - dsi_ctrl_hw_cmn_enable_status_interrupts; - ctrl->ops.enable_error_interrupts = - dsi_ctrl_hw_cmn_enable_error_interrupts; - ctrl->ops.video_test_pattern_setup = - dsi_ctrl_hw_cmn_video_test_pattern_setup; - ctrl->ops.cmd_test_pattern_setup = - dsi_ctrl_hw_cmn_cmd_test_pattern_setup; - ctrl->ops.test_pattern_enable = dsi_ctrl_hw_cmn_test_pattern_enable; - ctrl->ops.trigger_cmd_test_pattern = - dsi_ctrl_hw_cmn_trigger_cmd_test_pattern; - ctrl->ops.clear_phy0_ln_err = dsi_ctrl_hw_dln0_phy_err; - ctrl->ops.phy_reset_config = dsi_ctrl_hw_cmn_phy_reset_config; - ctrl->ops.setup_misr = dsi_ctrl_hw_cmn_setup_misr; - ctrl->ops.collect_misr = dsi_ctrl_hw_cmn_collect_misr; - ctrl->ops.debug_bus = dsi_ctrl_hw_cmn_debug_bus; - ctrl->ops.get_cmd_read_data = dsi_ctrl_hw_cmn_get_cmd_read_data; - ctrl->ops.clear_rdbk_register = dsi_ctrl_hw_cmn_clear_rdbk_reg; - ctrl->ops.ctrl_reset = dsi_ctrl_hw_cmn_ctrl_reset; - ctrl->ops.mask_error_intr = dsi_ctrl_hw_cmn_mask_error_intr; - ctrl->ops.error_intr_ctrl = dsi_ctrl_hw_cmn_error_intr_ctrl; - ctrl->ops.get_error_mask = dsi_ctrl_hw_cmn_get_error_mask; - ctrl->ops.get_hw_version = dsi_ctrl_hw_cmn_get_hw_version; - ctrl->ops.wait_for_cmd_mode_mdp_idle = - dsi_ctrl_hw_cmn_wait_for_cmd_mode_mdp_idle; - ctrl->ops.setup_avr = dsi_ctrl_hw_cmn_setup_avr; - ctrl->ops.set_continuous_clk = dsi_ctrl_hw_cmn_set_continuous_clk; - - switch (version) { - case DSI_CTRL_VERSION_1_4: - ctrl->ops.setup_lane_map = dsi_ctrl_hw_14_setup_lane_map; - ctrl->ops.ulps_ops.ulps_request = dsi_ctrl_hw_cmn_ulps_request; - ctrl->ops.ulps_ops.ulps_exit = dsi_ctrl_hw_cmn_ulps_exit; - ctrl->ops.wait_for_lane_idle = - dsi_ctrl_hw_14_wait_for_lane_idle; - ctrl->ops.ulps_ops.get_lanes_in_ulps = - dsi_ctrl_hw_cmn_get_lanes_in_ulps; - ctrl->ops.clamp_enable = dsi_ctrl_hw_14_clamp_enable; - ctrl->ops.clamp_disable = dsi_ctrl_hw_14_clamp_disable; - ctrl->ops.reg_dump_to_buffer = - dsi_ctrl_hw_14_reg_dump_to_buffer; - ctrl->ops.schedule_dma_cmd = NULL; - ctrl->ops.get_cont_splash_status = NULL; - ctrl->ops.kickoff_command_non_embedded_mode = NULL; - ctrl->ops.config_clk_gating = NULL; - break; - case DSI_CTRL_VERSION_2_0: - ctrl->ops.setup_lane_map = dsi_ctrl_hw_20_setup_lane_map; - ctrl->ops.wait_for_lane_idle = - dsi_ctrl_hw_20_wait_for_lane_idle; - ctrl->ops.reg_dump_to_buffer = - dsi_ctrl_hw_20_reg_dump_to_buffer; - ctrl->ops.ulps_ops.ulps_request = NULL; - ctrl->ops.ulps_ops.ulps_exit = NULL; - ctrl->ops.ulps_ops.get_lanes_in_ulps = NULL; - ctrl->ops.clamp_enable = NULL; - ctrl->ops.clamp_disable = NULL; - ctrl->ops.schedule_dma_cmd = NULL; - ctrl->ops.get_cont_splash_status = NULL; - ctrl->ops.kickoff_command_non_embedded_mode = NULL; - ctrl->ops.config_clk_gating = NULL; - break; - case DSI_CTRL_VERSION_2_2: - case DSI_CTRL_VERSION_2_3: - case DSI_CTRL_VERSION_2_4: - ctrl->ops.phy_reset_config = dsi_ctrl_hw_22_phy_reset_config; - ctrl->ops.config_clk_gating = dsi_ctrl_hw_22_config_clk_gating; - ctrl->ops.get_cont_splash_status = - dsi_ctrl_hw_22_get_cont_splash_status; - ctrl->ops.setup_lane_map = dsi_ctrl_hw_20_setup_lane_map; - ctrl->ops.wait_for_lane_idle = - dsi_ctrl_hw_20_wait_for_lane_idle; - ctrl->ops.reg_dump_to_buffer = - dsi_ctrl_hw_20_reg_dump_to_buffer; - ctrl->ops.ulps_ops.ulps_request = dsi_ctrl_hw_cmn_ulps_request; - ctrl->ops.ulps_ops.ulps_exit = dsi_ctrl_hw_cmn_ulps_exit; - ctrl->ops.ulps_ops.get_lanes_in_ulps = - dsi_ctrl_hw_cmn_get_lanes_in_ulps; - ctrl->ops.clamp_enable = NULL; - ctrl->ops.clamp_disable = NULL; - ctrl->ops.schedule_dma_cmd = dsi_ctrl_hw_22_schedule_dma_cmd; - ctrl->ops.kickoff_command_non_embedded_mode = - dsi_ctrl_hw_kickoff_non_embedded_mode; - break; - default: - break; - } -} - -/** - * dsi_catalog_ctrl_setup() - return catalog info for dsi controller - * @ctrl: Pointer to DSI controller hw object. - * @version: DSI controller version. - * @index: DSI controller instance ID. - * @phy_isolation_enabled: DSI controller works isolated from phy. - * @null_insertion_enabled: DSI controller inserts null packet. - * - * This function setups the catalog information in the dsi_ctrl_hw object. - * - * return: error code for failure and 0 for success. - */ -int dsi_catalog_ctrl_setup(struct dsi_ctrl_hw *ctrl, - enum dsi_ctrl_version version, u32 index, - bool phy_isolation_enabled, bool null_insertion_enabled) -{ - int rc = 0; - - if (version == DSI_CTRL_VERSION_UNKNOWN || - version >= DSI_CTRL_VERSION_MAX) { - pr_err("Unsupported version: %d\n", version); - return -ENOTSUPP; - } - - ctrl->index = index; - ctrl->null_insertion_enabled = null_insertion_enabled; - set_bit(DSI_CTRL_VIDEO_TPG, ctrl->feature_map); - set_bit(DSI_CTRL_CMD_TPG, ctrl->feature_map); - set_bit(DSI_CTRL_VARIABLE_REFRESH_RATE, ctrl->feature_map); - set_bit(DSI_CTRL_DYNAMIC_REFRESH, ctrl->feature_map); - set_bit(DSI_CTRL_DESKEW_CALIB, ctrl->feature_map); - set_bit(DSI_CTRL_DPHY, ctrl->feature_map); - - switch (version) { - case DSI_CTRL_VERSION_1_4: - dsi_catalog_cmn_init(ctrl, version); - break; - case DSI_CTRL_VERSION_2_0: - case DSI_CTRL_VERSION_2_2: - case DSI_CTRL_VERSION_2_3: - case DSI_CTRL_VERSION_2_4: - ctrl->phy_isolation_enabled = phy_isolation_enabled; - dsi_catalog_cmn_init(ctrl, version); - break; - default: - return -ENOTSUPP; - } - - return rc; -} - -/** - * dsi_catalog_phy_2_0_init() - catalog init for DSI PHY 14nm - */ -static void dsi_catalog_phy_2_0_init(struct dsi_phy_hw *phy) -{ - phy->ops.regulator_enable = dsi_phy_hw_v2_0_regulator_enable; - phy->ops.regulator_disable = dsi_phy_hw_v2_0_regulator_disable; - phy->ops.enable = dsi_phy_hw_v2_0_enable; - phy->ops.disable = dsi_phy_hw_v2_0_disable; - phy->ops.calculate_timing_params = - dsi_phy_hw_calculate_timing_params; - phy->ops.phy_idle_on = dsi_phy_hw_v2_0_idle_on; - phy->ops.phy_idle_off = dsi_phy_hw_v2_0_idle_off; - phy->ops.calculate_timing_params = - dsi_phy_hw_calculate_timing_params; - phy->ops.phy_timing_val = dsi_phy_hw_timing_val_v2_0; - phy->ops.clamp_ctrl = dsi_phy_hw_v2_0_clamp_ctrl; -} - -/** - * dsi_catalog_phy_3_0_init() - catalog init for DSI PHY 10nm - */ -static void dsi_catalog_phy_3_0_init(struct dsi_phy_hw *phy) -{ - phy->ops.regulator_enable = dsi_phy_hw_v3_0_regulator_enable; - phy->ops.regulator_disable = dsi_phy_hw_v3_0_regulator_disable; - phy->ops.enable = dsi_phy_hw_v3_0_enable; - phy->ops.disable = dsi_phy_hw_v3_0_disable; - phy->ops.calculate_timing_params = - dsi_phy_hw_calculate_timing_params; - phy->ops.ulps_ops.wait_for_lane_idle = - dsi_phy_hw_v3_0_wait_for_lane_idle; - phy->ops.ulps_ops.ulps_request = - dsi_phy_hw_v3_0_ulps_request; - phy->ops.ulps_ops.ulps_exit = - dsi_phy_hw_v3_0_ulps_exit; - phy->ops.ulps_ops.get_lanes_in_ulps = - dsi_phy_hw_v3_0_get_lanes_in_ulps; - phy->ops.ulps_ops.is_lanes_in_ulps = - dsi_phy_hw_v3_0_is_lanes_in_ulps; - phy->ops.phy_timing_val = dsi_phy_hw_timing_val_v3_0; - phy->ops.clamp_ctrl = dsi_phy_hw_v3_0_clamp_ctrl; - phy->ops.phy_lane_reset = dsi_phy_hw_v3_0_lane_reset; - phy->ops.toggle_resync_fifo = dsi_phy_hw_v3_0_toggle_resync_fifo; -} - -/** - * dsi_catalog_phy_4_0_init() - catalog init for DSI PHY 7nm - */ -static void dsi_catalog_phy_4_0_init(struct dsi_phy_hw *phy) -{ - phy->ops.regulator_enable = NULL; - phy->ops.regulator_disable = NULL; - phy->ops.enable = dsi_phy_hw_v4_0_enable; - phy->ops.disable = dsi_phy_hw_v4_0_disable; - phy->ops.calculate_timing_params = - dsi_phy_hw_calculate_timing_params; - phy->ops.ulps_ops.wait_for_lane_idle = - dsi_phy_hw_v4_0_wait_for_lane_idle; - phy->ops.ulps_ops.ulps_request = - dsi_phy_hw_v4_0_ulps_request; - phy->ops.ulps_ops.ulps_exit = - dsi_phy_hw_v4_0_ulps_exit; - phy->ops.ulps_ops.get_lanes_in_ulps = - dsi_phy_hw_v4_0_get_lanes_in_ulps; - phy->ops.ulps_ops.is_lanes_in_ulps = - dsi_phy_hw_v4_0_is_lanes_in_ulps; - phy->ops.phy_timing_val = dsi_phy_hw_timing_val_v4_0; - phy->ops.phy_lane_reset = dsi_phy_hw_v4_0_lane_reset; - phy->ops.toggle_resync_fifo = dsi_phy_hw_v4_0_toggle_resync_fifo; - phy->ops.reset_clk_en_sel = dsi_phy_hw_v4_0_reset_clk_en_sel; -} - -/** - * dsi_catalog_phy_setup() - return catalog info for dsi phy hardware - * @ctrl: Pointer to DSI PHY hw object. - * @version: DSI PHY version. - * @index: DSI PHY instance ID. - * - * This function setups the catalog information in the dsi_phy_hw object. - * - * return: error code for failure and 0 for success. - */ -int dsi_catalog_phy_setup(struct dsi_phy_hw *phy, - enum dsi_phy_version version, - u32 index) -{ - int rc = 0; - - if (version == DSI_PHY_VERSION_UNKNOWN || - version >= DSI_PHY_VERSION_MAX) { - pr_err("Unsupported version: %d\n", version); - return -ENOTSUPP; - } - - phy->index = index; - phy->version = version; - set_bit(DSI_PHY_DPHY, phy->feature_map); - - dsi_phy_timing_calc_init(phy, version); - - switch (version) { - case DSI_PHY_VERSION_2_0: - dsi_catalog_phy_2_0_init(phy); - break; - case DSI_PHY_VERSION_3_0: - dsi_catalog_phy_3_0_init(phy); - break; - case DSI_PHY_VERSION_4_0: - case DSI_PHY_VERSION_4_1: - dsi_catalog_phy_4_0_init(phy); - break; - case DSI_PHY_VERSION_0_0_HPM: - case DSI_PHY_VERSION_0_0_LPM: - case DSI_PHY_VERSION_1_0: - default: - return -ENOTSUPP; - } - - return rc; -} diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h deleted file mode 100644 index 08aa842ae80978fd5dd94c023079f90b8df26a08..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h +++ /dev/null @@ -1,242 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. - */ - -#ifndef _DSI_CATALOG_H_ -#define _DSI_CATALOG_H_ - -#include "dsi_ctrl_hw.h" -#include "dsi_phy_hw.h" - -/** - * dsi_catalog_ctrl_setup() - return catalog info for dsi controller - * @ctrl: Pointer to DSI controller hw object. - * @version: DSI controller version. - * @index: DSI controller instance ID. - * @phy_isolation_enabled: DSI controller works isolated from phy. - * @null_insertion_enabled: DSI controller inserts null packet. - * - * This function setups the catalog information in the dsi_ctrl_hw object. - * - * return: error code for failure and 0 for success. - */ -int dsi_catalog_ctrl_setup(struct dsi_ctrl_hw *ctrl, - enum dsi_ctrl_version version, u32 index, - bool phy_isolation_enabled, bool null_insertion_enabled); - -/** - * dsi_catalog_phy_setup() - return catalog info for dsi phy hardware - * @phy: Pointer to DSI PHY hw object. - * @version: DSI PHY version. - * @index: DSI PHY instance ID. - * - * This function setups the catalog information in the dsi_phy_hw object. - * - * return: error code for failure and 0 for success. - */ -int dsi_catalog_phy_setup(struct dsi_phy_hw *phy, - enum dsi_phy_version version, - u32 index); - -/** - * dsi_phy_timing_calc_init() - initialize info for DSI PHY timing calculations - * @phy: Pointer to DSI PHY hw object. - * @version: DSI PHY version. - * - * This function setups the catalog information in the dsi_phy_hw object. - * - * return: error code for failure and 0 for success. - */ -int dsi_phy_timing_calc_init(struct dsi_phy_hw *phy, - enum dsi_phy_version version); - -/** - * dsi_phy_hw_calculate_timing_params() - DSI PHY timing parameter calculations - * @phy: Pointer to DSI PHY hw object. - * @mode: DSI mode information. - * @host: DSI host configuration. - * @timing: DSI phy lane configurations. - * - * This function setups the catalog information in the dsi_phy_hw object. - * - * return: error code for failure and 0 for success. - */ -int dsi_phy_hw_calculate_timing_params(struct dsi_phy_hw *phy, - struct dsi_mode_info *mode, - struct dsi_host_common_cfg *host, - struct dsi_phy_per_lane_cfgs *timing); - -/* Definitions for 14nm PHY hardware driver */ -void dsi_phy_hw_v2_0_regulator_enable(struct dsi_phy_hw *phy, - struct dsi_phy_per_lane_cfgs *cfg); -void dsi_phy_hw_v2_0_regulator_disable(struct dsi_phy_hw *phy); -void dsi_phy_hw_v2_0_enable(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg); -void dsi_phy_hw_v2_0_disable(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg); -void dsi_phy_hw_v2_0_idle_on(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg); -void dsi_phy_hw_v2_0_idle_off(struct dsi_phy_hw *phy); -int dsi_phy_hw_timing_val_v2_0(struct dsi_phy_per_lane_cfgs *timing_cfg, - u32 *timing_val, u32 size); -void dsi_phy_hw_v2_0_clamp_ctrl(struct dsi_phy_hw *phy, bool enable); - -/* Definitions for 10nm PHY hardware driver */ -void dsi_phy_hw_v3_0_regulator_enable(struct dsi_phy_hw *phy, - struct dsi_phy_per_lane_cfgs *cfg); -void dsi_phy_hw_v3_0_regulator_disable(struct dsi_phy_hw *phy); -void dsi_phy_hw_v3_0_enable(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg); -void dsi_phy_hw_v3_0_disable(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg); -int dsi_phy_hw_v3_0_wait_for_lane_idle(struct dsi_phy_hw *phy, u32 lanes); -void dsi_phy_hw_v3_0_ulps_request(struct dsi_phy_hw *phy, - struct dsi_phy_cfg *cfg, u32 lanes); -void dsi_phy_hw_v3_0_ulps_exit(struct dsi_phy_hw *phy, - struct dsi_phy_cfg *cfg, u32 lanes); -u32 dsi_phy_hw_v3_0_get_lanes_in_ulps(struct dsi_phy_hw *phy); -bool dsi_phy_hw_v3_0_is_lanes_in_ulps(u32 lanes, u32 ulps_lanes); -int dsi_phy_hw_timing_val_v3_0(struct dsi_phy_per_lane_cfgs *timing_cfg, - u32 *timing_val, u32 size); -void dsi_phy_hw_v3_0_clamp_ctrl(struct dsi_phy_hw *phy, bool enable); -int dsi_phy_hw_v3_0_lane_reset(struct dsi_phy_hw *phy); -void dsi_phy_hw_v3_0_toggle_resync_fifo(struct dsi_phy_hw *phy); - -/* Definitions for 7nm PHY hardware driver */ -void dsi_phy_hw_v4_0_enable(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg); -void dsi_phy_hw_v4_0_disable(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg); -int dsi_phy_hw_v4_0_wait_for_lane_idle(struct dsi_phy_hw *phy, u32 lanes); -void dsi_phy_hw_v4_0_ulps_request(struct dsi_phy_hw *phy, - struct dsi_phy_cfg *cfg, u32 lanes); -void dsi_phy_hw_v4_0_ulps_exit(struct dsi_phy_hw *phy, - struct dsi_phy_cfg *cfg, u32 lanes); -u32 dsi_phy_hw_v4_0_get_lanes_in_ulps(struct dsi_phy_hw *phy); -bool dsi_phy_hw_v4_0_is_lanes_in_ulps(u32 lanes, u32 ulps_lanes); -int dsi_phy_hw_timing_val_v4_0(struct dsi_phy_per_lane_cfgs *timing_cfg, - u32 *timing_val, u32 size); -int dsi_phy_hw_v4_0_lane_reset(struct dsi_phy_hw *phy); -void dsi_phy_hw_v4_0_toggle_resync_fifo(struct dsi_phy_hw *phy); -void dsi_phy_hw_v4_0_reset_clk_en_sel(struct dsi_phy_hw *phy); - -/* DSI controller common ops */ -u32 dsi_ctrl_hw_cmn_get_interrupt_status(struct dsi_ctrl_hw *ctrl); -void dsi_ctrl_hw_cmn_debug_bus(struct dsi_ctrl_hw *ctrl, u32 *entries, - u32 size); -void dsi_ctrl_hw_cmn_clear_interrupt_status(struct dsi_ctrl_hw *ctrl, u32 ints); -void dsi_ctrl_hw_cmn_enable_status_interrupts(struct dsi_ctrl_hw *ctrl, - u32 ints); - -u64 dsi_ctrl_hw_cmn_get_error_status(struct dsi_ctrl_hw *ctrl); -void dsi_ctrl_hw_cmn_clear_error_status(struct dsi_ctrl_hw *ctrl, u64 errors); -void dsi_ctrl_hw_cmn_enable_error_interrupts(struct dsi_ctrl_hw *ctrl, - u64 errors); - -void dsi_ctrl_hw_cmn_video_test_pattern_setup(struct dsi_ctrl_hw *ctrl, - enum dsi_test_pattern type, - u32 init_val); -void dsi_ctrl_hw_cmn_cmd_test_pattern_setup(struct dsi_ctrl_hw *ctrl, - enum dsi_test_pattern type, - u32 init_val, - u32 stream_id); -void dsi_ctrl_hw_cmn_test_pattern_enable(struct dsi_ctrl_hw *ctrl, bool enable); -void dsi_ctrl_hw_cmn_trigger_cmd_test_pattern(struct dsi_ctrl_hw *ctrl, - u32 stream_id); - -void dsi_ctrl_hw_cmn_host_setup(struct dsi_ctrl_hw *ctrl, - struct dsi_host_common_cfg *config); -void dsi_ctrl_hw_cmn_video_engine_en(struct dsi_ctrl_hw *ctrl, bool on); -void dsi_ctrl_hw_cmn_video_engine_setup(struct dsi_ctrl_hw *ctrl, - struct dsi_host_common_cfg *common_cfg, - struct dsi_video_engine_cfg *cfg); - -void dsi_ctrl_hw_cmn_setup_avr(struct dsi_ctrl_hw *ctrl, bool enable); - -void dsi_ctrl_hw_cmn_set_video_timing(struct dsi_ctrl_hw *ctrl, - struct dsi_mode_info *mode); -void dsi_ctrl_hw_cmn_set_timing_db(struct dsi_ctrl_hw *ctrl, - bool enable); -void dsi_ctrl_hw_cmn_cmd_engine_setup(struct dsi_ctrl_hw *ctrl, - struct dsi_host_common_cfg *common_cfg, - struct dsi_cmd_engine_cfg *cfg); - -void dsi_ctrl_hw_cmn_ctrl_en(struct dsi_ctrl_hw *ctrl, bool on); -void dsi_ctrl_hw_cmn_cmd_engine_en(struct dsi_ctrl_hw *ctrl, bool on); - -void dsi_ctrl_hw_cmn_setup_cmd_stream(struct dsi_ctrl_hw *ctrl, - struct dsi_mode_info *mode, - u32 h_stride, - u32 vc_id, - struct dsi_rect *roi); -void dsi_ctrl_hw_cmn_phy_sw_reset(struct dsi_ctrl_hw *ctrl); -void dsi_ctrl_hw_cmn_soft_reset(struct dsi_ctrl_hw *ctrl); - -void dsi_ctrl_hw_cmn_setup_misr(struct dsi_ctrl_hw *ctrl, - enum dsi_op_mode panel_mode, - bool enable, u32 frame_count); -u32 dsi_ctrl_hw_cmn_collect_misr(struct dsi_ctrl_hw *ctrl, - enum dsi_op_mode panel_mode); - -void dsi_ctrl_hw_cmn_kickoff_command(struct dsi_ctrl_hw *ctrl, - struct dsi_ctrl_cmd_dma_info *cmd, - u32 flags); - -void dsi_ctrl_hw_cmn_kickoff_fifo_command(struct dsi_ctrl_hw *ctrl, - struct dsi_ctrl_cmd_dma_fifo_info *cmd, - u32 flags); -void dsi_ctrl_hw_cmn_reset_cmd_fifo(struct dsi_ctrl_hw *ctrl); -void dsi_ctrl_hw_cmn_trigger_command_dma(struct dsi_ctrl_hw *ctrl); -void dsi_ctrl_hw_dln0_phy_err(struct dsi_ctrl_hw *ctrl); -void dsi_ctrl_hw_cmn_phy_reset_config(struct dsi_ctrl_hw *ctrl, - bool enable); -void dsi_ctrl_hw_22_phy_reset_config(struct dsi_ctrl_hw *ctrl, - bool enable); -u32 dsi_ctrl_hw_cmn_get_cmd_read_data(struct dsi_ctrl_hw *ctrl, - u8 *rd_buf, - u32 read_offset, - u32 rx_byte, - u32 pkt_size, u32 *hw_read_cnt); -void dsi_ctrl_hw_cmn_clear_rdbk_reg(struct dsi_ctrl_hw *ctrl); -void dsi_ctrl_hw_22_schedule_dma_cmd(struct dsi_ctrl_hw *ctrl, int line_on); -int dsi_ctrl_hw_cmn_ctrl_reset(struct dsi_ctrl_hw *ctrl, - int mask); -void dsi_ctrl_hw_cmn_mask_error_intr(struct dsi_ctrl_hw *ctrl, u32 idx, - bool en); -void dsi_ctrl_hw_cmn_error_intr_ctrl(struct dsi_ctrl_hw *ctrl, bool en); -u32 dsi_ctrl_hw_cmn_get_error_mask(struct dsi_ctrl_hw *ctrl); -u32 dsi_ctrl_hw_cmn_get_hw_version(struct dsi_ctrl_hw *ctrl); -int dsi_ctrl_hw_cmn_wait_for_cmd_mode_mdp_idle(struct dsi_ctrl_hw *ctrl); - -/* Definitions specific to 1.4 DSI controller hardware */ -int dsi_ctrl_hw_14_wait_for_lane_idle(struct dsi_ctrl_hw *ctrl, u32 lanes); -void dsi_ctrl_hw_14_setup_lane_map(struct dsi_ctrl_hw *ctrl, - struct dsi_lane_map *lane_map); -void dsi_ctrl_hw_cmn_ulps_request(struct dsi_ctrl_hw *ctrl, u32 lanes); -void dsi_ctrl_hw_cmn_ulps_exit(struct dsi_ctrl_hw *ctrl, u32 lanes); -u32 dsi_ctrl_hw_cmn_get_lanes_in_ulps(struct dsi_ctrl_hw *ctrl); - -void dsi_ctrl_hw_14_clamp_enable(struct dsi_ctrl_hw *ctrl, - u32 lanes, - bool enable_ulps); - -void dsi_ctrl_hw_14_clamp_disable(struct dsi_ctrl_hw *ctrl, - u32 lanes, - bool disable_ulps); -ssize_t dsi_ctrl_hw_14_reg_dump_to_buffer(struct dsi_ctrl_hw *ctrl, - char *buf, - u32 size); - -/* Definitions specific to 2.0 DSI controller hardware */ -void dsi_ctrl_hw_20_setup_lane_map(struct dsi_ctrl_hw *ctrl, - struct dsi_lane_map *lane_map); -int dsi_ctrl_hw_20_wait_for_lane_idle(struct dsi_ctrl_hw *ctrl, u32 lanes); -ssize_t dsi_ctrl_hw_20_reg_dump_to_buffer(struct dsi_ctrl_hw *ctrl, - char *buf, - u32 size); -void dsi_ctrl_hw_kickoff_non_embedded_mode(struct dsi_ctrl_hw *ctrl, - struct dsi_ctrl_cmd_dma_info *cmd, - u32 flags); - -/* Definitions specific to 2.2 DSI controller hardware */ -bool dsi_ctrl_hw_22_get_cont_splash_status(struct dsi_ctrl_hw *ctrl); -void dsi_ctrl_hw_22_config_clk_gating(struct dsi_ctrl_hw *ctrl, bool enable, - enum dsi_clk_gate_type clk_selection); - -void dsi_ctrl_hw_cmn_set_continuous_clk(struct dsi_ctrl_hw *ctrl, bool enable); - -#endif /* _DSI_CATALOG_H_ */ diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h b/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h deleted file mode 100644 index 2efc2c4e5f59fe3a8a7c2873a1169c8e4586239b..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h +++ /dev/null @@ -1,312 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. - */ - -#ifndef _DSI_CLK_H_ -#define _DSI_CLK_H_ - -#include -#include -#include -#include -#include "sde_power_handle.h" - -#define MAX_STRING_LEN 32 -#define MAX_DSI_CTRL 2 - -enum dsi_clk_state { - DSI_CLK_OFF, - DSI_CLK_ON, - DSI_CLK_EARLY_GATE, -}; - -enum clk_req_client { - DSI_CLK_REQ_MDP_CLIENT = 0, - DSI_CLK_REQ_DSI_CLIENT, -}; - -enum dsi_link_clk_type { - DSI_LINK_ESC_CLK, - DSI_LINK_BYTE_CLK, - DSI_LINK_PIX_CLK, - DSI_LINK_BYTE_INTF_CLK, - DSI_LINK_CLK_MAX, -}; - -enum dsi_link_clk_op_type { - DSI_LINK_CLK_SET_RATE = BIT(0), - DSI_LINK_CLK_PREPARE = BIT(1), - DSI_LINK_CLK_ENABLE = BIT(2), - DSI_LINK_CLK_START = BIT(0) | BIT(1) | BIT(2), -}; - -enum dsi_clk_type { - DSI_CORE_CLK = BIT(0), - DSI_LINK_CLK = BIT(1), - DSI_ALL_CLKS = (BIT(0) | BIT(1)), - DSI_CLKS_MAX = BIT(2), -}; - -enum dsi_lclk_type { - DSI_LINK_NONE = 0, - DSI_LINK_LP_CLK = BIT(0), - DSI_LINK_HS_CLK = BIT(1), -}; - -struct dsi_clk_ctrl_info { - enum dsi_clk_type clk_type; - enum dsi_clk_state clk_state; - enum clk_req_client client; -}; - -struct clk_ctrl_cb { - void *priv; - int (*dsi_clk_cb)(void *priv, struct dsi_clk_ctrl_info clk_ctrl_info); -}; - -/** - * struct dsi_core_clk_info - Core clock information for DSI hardware - * @mdp_core_clk: Handle to MDP core clock. - * @iface_clk: Handle to MDP interface clock. - * @core_mmss_clk: Handle to MMSS core clock. - * @bus_clk: Handle to bus clock. - * @mnoc_clk: Handle to MMSS NOC clock. - * @dsi_core_client: Pointer to SDE power client - * @phandle: Pointer to SDE power handle - */ -struct dsi_core_clk_info { - struct clk *mdp_core_clk; - struct clk *iface_clk; - struct clk *core_mmss_clk; - struct clk *bus_clk; - struct clk *mnoc_clk; - struct sde_power_client *dsi_core_client; - struct sde_power_handle *phandle; -}; - -/** - * struct dsi_link_hs_clk_info - Set of high speed link clocks for DSI HW - * @byte_clk: Handle to DSI byte_clk. - * @pixel_clk: Handle to DSI pixel_clk. - * @byte_intf_clk: Handle to DSI byte intf. clock. - */ -struct dsi_link_hs_clk_info { - struct clk *byte_clk; - struct clk *pixel_clk; - struct clk *byte_intf_clk; -}; - -/** - * struct dsi_link_lp_clk_info - Set of low power link clocks for DSI HW. - * @esc_clk: Handle to DSI escape clock. - */ -struct dsi_link_lp_clk_info { - struct clk *esc_clk; -}; - -/** - * struct link_clk_freq - Clock frequency information for Link clocks - * @byte_clk_rate: Frequency of DSI byte_clk in KHz. - * @pixel_clk_rate: Frequency of DSI pixel_clk in KHz. - * @esc_clk_rate: Frequency of DSI escape clock in KHz. - */ -struct link_clk_freq { - u32 byte_clk_rate; - u32 pix_clk_rate; - u32 esc_clk_rate; -}; - -/** - * typedef *pre_clockoff_cb() - Callback before clock is turned off - * @priv: private data pointer. - * @clk_type: clock which is being turned off. - * @l_type: specifies if the clock is HS or LP type. Valid only for link clocks. - * @new_state: next state for the clock. - * - * @return: error code. - */ -typedef int (*pre_clockoff_cb)(void *priv, - enum dsi_clk_type clk_type, - enum dsi_lclk_type l_type, - enum dsi_clk_state new_state); - -/** - * typedef *post_clockoff_cb() - Callback after clock is turned off - * @priv: private data pointer. - * @clk_type: clock which was turned off. - * @l_type: specifies if the clock is HS or LP type. Valid only for link clocks. - * @curr_state: current state for the clock. - * - * @return: error code. - */ -typedef int (*post_clockoff_cb)(void *priv, - enum dsi_clk_type clk_type, - enum dsi_lclk_type l_type, - enum dsi_clk_state curr_state); - -/** - * typedef *post_clockon_cb() - Callback after clock is turned on - * @priv: private data pointer. - * @clk_type: clock which was turned on. - * @l_type: specifies if the clock is HS or LP type. Valid only for link clocks. - * @curr_state: current state for the clock. - * - * @return: error code. - */ -typedef int (*post_clockon_cb)(void *priv, - enum dsi_clk_type clk_type, - enum dsi_lclk_type l_type, - enum dsi_clk_state curr_state); - -/** - * typedef *pre_clockon_cb() - Callback before clock is turned on - * @priv: private data pointer. - * @clk_type: clock which is being turned on. - * @l_type: specifies if the clock is HS or LP type.Valid only for link clocks. - * @new_state: next state for the clock. - * - * @return: error code. - */ -typedef int (*pre_clockon_cb)(void *priv, - enum dsi_clk_type clk_type, - enum dsi_lclk_type l_type, - enum dsi_clk_state new_state); - - -/** - * struct dsi_clk_info - clock information for DSI hardware. - * @name: client name. - * @c_clks[MAX_DSI_CTRL] array of core clock configurations - * @l_lp_clks[MAX_DSI_CTRL] array of low power(esc) clock configurations - * @l_hs_clks[MAX_DSI_CTRL] array of high speed clock configurations - * @bus_handle[MAX_DSI_CTRL] array of bus handles - * @ctrl_index[MAX_DSI_CTRL] array of DSI controller indexes mapped - * to core and link clock configurations - * @pre_clkoff_cb callback before clock is turned off - * @post_clkoff_cb callback after clock is turned off - * @post_clkon_cb callback after clock is turned on - * @pre_clkon_cb callback before clock is turned on - * @priv_data pointer to private data - * @master_ndx master DSI controller index - * @dsi_ctrl_count number of DSI controllers - */ -struct dsi_clk_info { - char name[MAX_STRING_LEN]; - struct dsi_core_clk_info c_clks[MAX_DSI_CTRL]; - struct dsi_link_lp_clk_info l_lp_clks[MAX_DSI_CTRL]; - struct dsi_link_hs_clk_info l_hs_clks[MAX_DSI_CTRL]; - u32 bus_handle[MAX_DSI_CTRL]; - u32 ctrl_index[MAX_DSI_CTRL]; - pre_clockoff_cb pre_clkoff_cb; - post_clockoff_cb post_clkoff_cb; - post_clockon_cb post_clkon_cb; - pre_clockon_cb pre_clkon_cb; - void *priv_data; - u32 master_ndx; - u32 dsi_ctrl_count; -}; - -/** - * struct dsi_clk_link_set - Pair of clock handles to describe link clocks - * @byte_clk: Handle to DSi byte_clk. - * @pixel_clk: Handle to DSI pixel_clk. - */ -struct dsi_clk_link_set { - struct clk *byte_clk; - struct clk *pixel_clk; -}; - -/** - * dsi_display_clk_mngr_update_splash_status() - Update splash stattus - * @clk_mngr: Structure containing DSI clock information - * @status: Splash status - */ -void dsi_display_clk_mngr_update_splash_status(void *clk_mgr, bool status); - -/** - * dsi_display_clk_mgr_register() - Register DSI clock manager - * @info: Structure containing DSI clock information - */ -void *dsi_display_clk_mngr_register(struct dsi_clk_info *info); - -/** - * dsi_display_clk_mngr_deregister() - Deregister DSI clock manager - * @clk_mngr: DSI clock manager pointer - */ -int dsi_display_clk_mngr_deregister(void *clk_mngr); - -/** - * dsi_register_clk_handle() - Register clock handle with DSI clock manager - * @clk_mngr: DSI clock manager pointer - * @client: DSI clock client pointer. - */ -void *dsi_register_clk_handle(void *clk_mngr, char *client); - -/** - * dsi_deregister_clk_handle() - Deregister clock handle from DSI clock manager - * @client: DSI clock client pointer. - * - * return: error code in case of failure or 0 for success. - */ -int dsi_deregister_clk_handle(void *client); - -/** - * dsi_display_link_clk_force_update_ctrl() - force to set link clks - * @handle: Handle of desired DSI clock client. - * - * return: error code in case of failure or 0 for success. - */ - -int dsi_display_link_clk_force_update_ctrl(void *handle); - -/** - * dsi_display_clk_ctrl() - set frequencies for link clks - * @handle: Handle of desired DSI clock client. - * @clk_type: Clock which is being controlled. - * @clk_state: Desired state of clock - * - * return: error code in case of failure or 0 for success. - */ -int dsi_display_clk_ctrl(void *handle, - enum dsi_clk_type clk_type, enum dsi_clk_state clk_state); - -/** - * dsi_clk_set_link_frequencies() - set frequencies for link clks - * @client: DSI clock client pointer. - * @freq: Structure containing link clock frequencies. - * @index: Index of the DSI controller. - * - * return: error code in case of failure or 0 for success. - */ -int dsi_clk_set_link_frequencies(void *client, struct link_clk_freq freq, - u32 index); - - -/** - * dsi_clk_set_pixel_clk_rate() - set frequency for pixel_clk - * @client: DSI clock client pointer. - * @pixel_clk: Pixel_clk rate in Hz. - * @index: Index of the DSI controller. - * return: error code in case of failure or 0 for success. - */ -int dsi_clk_set_pixel_clk_rate(void *client, u64 pixel_clk, u32 index); - - -/** - * dsi_clk_set_byte_clk_rate() - set frequency for byte clock - * @client: DSI clock client pointer. - * @byte_clk: Pixel clock rate in Hz. - * @index: Index of the DSI controller. - * return: error code in case of failure or 0 for success. - */ -int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, u32 index); - -/** - * dsi_clk_update_parent() - update parent clocks for specified clock - * @parent: link clock pair which are set as parent. - * @child: link clock pair whose parent has to be set. - */ -int dsi_clk_update_parent(struct dsi_clk_link_set *parent, - struct dsi_clk_link_set *child); -#endif /* _DSI_CLK_H_ */ diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c b/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c deleted file mode 100644 index 9a35c7ac279c37c15931a33731acd090c2a5123f..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c +++ /dev/null @@ -1,1470 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. - */ - -#include -#include -#include -#include -#include "dsi_clk.h" - -struct dsi_core_clks { - struct dsi_core_clk_info clks; - u32 bus_handle; -}; - -struct dsi_link_clks { - struct dsi_link_hs_clk_info hs_clks; - struct dsi_link_lp_clk_info lp_clks; - struct link_clk_freq freq; -}; - -struct dsi_clk_mngr { - char name[MAX_STRING_LEN]; - struct mutex clk_mutex; - struct list_head client_list; - - u32 dsi_ctrl_count; - u32 master_ndx; - struct dsi_core_clks core_clks[MAX_DSI_CTRL]; - struct dsi_link_clks link_clks[MAX_DSI_CTRL]; - u32 ctrl_index[MAX_DSI_CTRL]; - u32 core_clk_state; - u32 link_clk_state; - - pre_clockoff_cb pre_clkoff_cb; - post_clockoff_cb post_clkoff_cb; - post_clockon_cb post_clkon_cb; - pre_clockon_cb pre_clkon_cb; - - bool is_cont_splash_enabled; - void *priv_data; -}; - -struct dsi_clk_client_info { - char name[MAX_STRING_LEN]; - u32 core_refcount; - u32 link_refcount; - u32 core_clk_state; - u32 link_clk_state; - struct list_head list; - struct dsi_clk_mngr *mngr; -}; - -static int _get_clk_mngr_index(struct dsi_clk_mngr *mngr, - u32 dsi_ctrl_index, - u32 *clk_mngr_index) -{ - int i; - - for (i = 0; i < mngr->dsi_ctrl_count; i++) { - if (mngr->ctrl_index[i] == dsi_ctrl_index) { - *clk_mngr_index = i; - return 0; - } - } - - return -EINVAL; -} - -/** - * dsi_clk_set_link_frequencies() - set frequencies for link clks - * @clks: Link clock information - * @pixel_clk: pixel clock frequency in KHz. - * @byte_clk: Byte clock frequency in KHz. - * @esc_clk: Escape clock frequency in KHz. - * - * return: error code in case of failure or 0 for success. - */ -int dsi_clk_set_link_frequencies(void *client, struct link_clk_freq freq, - u32 index) -{ - int rc = 0, clk_mngr_index = 0; - struct dsi_clk_client_info *c = client; - struct dsi_clk_mngr *mngr; - - if (!client) { - pr_err("invalid params\n"); - return -EINVAL; - } - - mngr = c->mngr; - rc = _get_clk_mngr_index(mngr, index, &clk_mngr_index); - if (rc) { - pr_err("failed to map control index %d\n", index); - return -EINVAL; - } - - memcpy(&mngr->link_clks[clk_mngr_index].freq, &freq, - sizeof(struct link_clk_freq)); - - return rc; -} - -/** - * dsi_clk_set_pixel_clk_rate() - set frequency for pixel clock - * @clks: DSI link clock information. - * @pixel_clk: Pixel clock rate in KHz. - * - * return: error code in case of failure or 0 for success. - */ -int dsi_clk_set_pixel_clk_rate(void *client, u64 pixel_clk, u32 index) -{ - int rc = 0; - struct dsi_clk_client_info *c = client; - struct dsi_clk_mngr *mngr; - - mngr = c->mngr; - rc = clk_set_rate(mngr->link_clks[index].hs_clks.pixel_clk, pixel_clk); - if (rc) - pr_err("failed to set clk rate for pixel clk, rc=%d\n", rc); - else - mngr->link_clks[index].freq.pix_clk_rate = pixel_clk; - - return rc; -} - -/** - * dsi_clk_set_byte_clk_rate() - set frequency for byte clock - * @client: DSI clock client pointer. - * @byte_clk: Pixel clock rate in Hz. - * @index: Index of the DSI controller. - * return: error code in case of failure or 0 for success. - */ -int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, u32 index) -{ - int rc = 0; - struct dsi_clk_client_info *c = client; - struct dsi_clk_mngr *mngr; - - mngr = c->mngr; - rc = clk_set_rate(mngr->link_clks[index].hs_clks.byte_clk, byte_clk); - if (rc) - pr_err("failed to set clk rate for byte clk, rc=%d\n", rc); - else - mngr->link_clks[index].freq.byte_clk_rate = byte_clk; - - return rc; - -} - -/** - * dsi_clk_update_parent() - update parent clocks for specified clock - * @parent: link clock pair which are set as parent. - * @child: link clock pair whose parent has to be set. - */ -int dsi_clk_update_parent(struct dsi_clk_link_set *parent, - struct dsi_clk_link_set *child) -{ - int rc = 0; - - rc = clk_set_parent(child->byte_clk, parent->byte_clk); - if (rc) { - pr_err("failed to set byte clk parent\n"); - goto error; - } - - rc = clk_set_parent(child->pixel_clk, parent->pixel_clk); - if (rc) { - pr_err("failed to set pixel clk parent\n"); - goto error; - } -error: - return rc; -} - -int dsi_core_clk_start(struct dsi_core_clks *c_clks) -{ - int rc = 0; - - if (c_clks->clks.mdp_core_clk) { - rc = clk_prepare_enable(c_clks->clks.mdp_core_clk); - if (rc) { - pr_err("failed to enable mdp_core_clk, rc=%d\n", rc); - goto error; - } - } - - if (c_clks->clks.mnoc_clk) { - rc = clk_prepare_enable(c_clks->clks.mnoc_clk); - if (rc) { - pr_err("failed to enable mnoc_clk, rc=%d\n", rc); - goto error_disable_core_clk; - } - } - - if (c_clks->clks.iface_clk) { - rc = clk_prepare_enable(c_clks->clks.iface_clk); - if (rc) { - pr_err("failed to enable iface_clk, rc=%d\n", rc); - goto error_disable_mnoc_clk; - } - } - - if (c_clks->clks.bus_clk) { - rc = clk_prepare_enable(c_clks->clks.bus_clk); - if (rc) { - pr_err("failed to enable bus_clk, rc=%d\n", rc); - goto error_disable_iface_clk; - } - } - - if (c_clks->clks.core_mmss_clk) { - rc = clk_prepare_enable(c_clks->clks.core_mmss_clk); - if (rc) { - pr_err("failed to enable core_mmss_clk, rc=%d\n", rc); - goto error_disable_bus_clk; - } - } - - if (c_clks->bus_handle) { - rc = msm_bus_scale_client_update_request(c_clks->bus_handle, 1); - if (rc) { - pr_err("bus scale client enable failed, rc=%d\n", rc); - goto error_disable_mmss_clk; - } - } - - return rc; - -error_disable_mmss_clk: - if (c_clks->clks.core_mmss_clk) - clk_disable_unprepare(c_clks->clks.core_mmss_clk); -error_disable_bus_clk: - if (c_clks->clks.bus_clk) - clk_disable_unprepare(c_clks->clks.bus_clk); -error_disable_iface_clk: - if (c_clks->clks.iface_clk) - clk_disable_unprepare(c_clks->clks.iface_clk); -error_disable_mnoc_clk: - if (c_clks->clks.mnoc_clk) - clk_disable_unprepare(c_clks->clks.mnoc_clk); -error_disable_core_clk: - if (c_clks->clks.mdp_core_clk) - clk_disable_unprepare(c_clks->clks.mdp_core_clk); -error: - return rc; -} - -int dsi_core_clk_stop(struct dsi_core_clks *c_clks) -{ - int rc = 0; - - if (c_clks->bus_handle) { - rc = msm_bus_scale_client_update_request(c_clks->bus_handle, 0); - if (rc) { - pr_err("bus scale client disable failed, rc=%d\n", rc); - return rc; - } - } - - if (c_clks->clks.core_mmss_clk) - clk_disable_unprepare(c_clks->clks.core_mmss_clk); - - if (c_clks->clks.bus_clk) - clk_disable_unprepare(c_clks->clks.bus_clk); - - if (c_clks->clks.iface_clk) - clk_disable_unprepare(c_clks->clks.iface_clk); - - if (c_clks->clks.mnoc_clk) - clk_disable_unprepare(c_clks->clks.mnoc_clk); - - if (c_clks->clks.mdp_core_clk) - clk_disable_unprepare(c_clks->clks.mdp_core_clk); - - return rc; -} - -static int dsi_link_hs_clk_set_rate(struct dsi_link_hs_clk_info *link_hs_clks, - int index) -{ - int rc = 0; - struct dsi_clk_mngr *mngr; - struct dsi_link_clks *l_clks; - - if (index >= MAX_DSI_CTRL) { - pr_err("Invalid DSI ctrl index\n"); - return -EINVAL; - } - - l_clks = container_of(link_hs_clks, struct dsi_link_clks, hs_clks); - mngr = container_of(l_clks, struct dsi_clk_mngr, link_clks[index]); - - /* - * In an ideal world, cont_splash_enabled should not be required inside - * the clock manager. But, in the current driver cont_splash_enabled - * flag is set inside mdp driver and there is no interface event - * associated with this flag setting. - */ - if (mngr->is_cont_splash_enabled) - return 0; - - rc = clk_set_rate(link_hs_clks->byte_clk, - l_clks->freq.byte_clk_rate); - if (rc) { - pr_err("clk_set_rate failed for byte_clk rc = %d\n", rc); - goto error; - } - - rc = clk_set_rate(link_hs_clks->pixel_clk, - l_clks->freq.pix_clk_rate); - if (rc) { - pr_err("clk_set_rate failed for pixel_clk rc = %d\n", rc); - goto error; - } - - /* - * If byte_intf_clk is present, set rate for that too. - * For DPHY: byte_intf_clk_rate = byte_clk_rate / 2 - * todo: this needs to be revisited when support for CPHY is added - */ - if (link_hs_clks->byte_intf_clk) { - rc = clk_set_rate(link_hs_clks->byte_intf_clk, - (l_clks->freq.byte_clk_rate / 2)); - if (rc) { - pr_err("set_rate failed for byte_intf_clk rc = %d\n", - rc); - goto error; - } - } -error: - return rc; -} - -static int dsi_link_hs_clk_prepare(struct dsi_link_hs_clk_info *link_hs_clks) -{ - int rc = 0; - - rc = clk_prepare(link_hs_clks->byte_clk); - if (rc) { - pr_err("Failed to prepare dsi byte clk, rc=%d\n", rc); - goto byte_clk_err; - } - - rc = clk_prepare(link_hs_clks->pixel_clk); - if (rc) { - pr_err("Failed to prepare dsi pixel clk, rc=%d\n", rc); - goto pixel_clk_err; - } - - if (link_hs_clks->byte_intf_clk) { - rc = clk_prepare(link_hs_clks->byte_intf_clk); - if (rc) { - pr_err("Failed to prepare dsi byte intf clk, rc=%d\n", - rc); - goto byte_intf_clk_err; - } - } - - return rc; - -byte_intf_clk_err: - clk_unprepare(link_hs_clks->pixel_clk); -pixel_clk_err: - clk_unprepare(link_hs_clks->byte_clk); -byte_clk_err: - return rc; -} - -static void dsi_link_hs_clk_unprepare(struct dsi_link_hs_clk_info *link_hs_clks) -{ - if (link_hs_clks->byte_intf_clk) - clk_unprepare(link_hs_clks->byte_intf_clk); - clk_unprepare(link_hs_clks->pixel_clk); - clk_unprepare(link_hs_clks->byte_clk); -} - -static int dsi_link_hs_clk_enable(struct dsi_link_hs_clk_info *link_hs_clks) -{ - int rc = 0; - - rc = clk_enable(link_hs_clks->byte_clk); - if (rc) { - pr_err("Failed to enable dsi byte clk, rc=%d\n", rc); - goto byte_clk_err; - } - - rc = clk_enable(link_hs_clks->pixel_clk); - if (rc) { - pr_err("Failed to enable dsi pixel clk, rc=%d\n", rc); - goto pixel_clk_err; - } - - if (link_hs_clks->byte_intf_clk) { - rc = clk_enable(link_hs_clks->byte_intf_clk); - if (rc) { - pr_err("Failed to enable dsi byte intf clk, rc=%d\n", - rc); - goto byte_intf_clk_err; - } - } - - return rc; - -byte_intf_clk_err: - clk_disable(link_hs_clks->pixel_clk); -pixel_clk_err: - clk_disable(link_hs_clks->byte_clk); -byte_clk_err: - return rc; -} - -static void dsi_link_hs_clk_disable(struct dsi_link_hs_clk_info *link_hs_clks) -{ - if (link_hs_clks->byte_intf_clk) - clk_disable(link_hs_clks->byte_intf_clk); - clk_disable(link_hs_clks->pixel_clk); - clk_disable(link_hs_clks->byte_clk); -} - -/** - * dsi_link_clk_start() - enable dsi link clocks - */ -static int dsi_link_hs_clk_start(struct dsi_link_hs_clk_info *link_hs_clks, - enum dsi_link_clk_op_type op_type, int index) -{ - int rc = 0; - - if (index >= MAX_DSI_CTRL) { - pr_err("Invalid DSI ctrl index\n"); - return -EINVAL; - } - - if (op_type & DSI_LINK_CLK_SET_RATE) { - rc = dsi_link_hs_clk_set_rate(link_hs_clks, index); - if (rc) { - pr_err("failed to set HS clk rates, rc = %d\n", rc); - goto error; - } - } - - if (op_type & DSI_LINK_CLK_PREPARE) { - rc = dsi_link_hs_clk_prepare(link_hs_clks); - if (rc) { - pr_err("failed to prepare link HS clks, rc = %d\n", rc); - goto error; - } - } - - if (op_type & DSI_LINK_CLK_ENABLE) { - rc = dsi_link_hs_clk_enable(link_hs_clks); - if (rc) { - pr_err("failed to enable link HS clks, rc = %d\n", rc); - goto error_unprepare; - } - } - - pr_debug("HS Link clocks are enabled\n"); - return rc; -error_unprepare: - dsi_link_hs_clk_unprepare(link_hs_clks); -error: - return rc; -} - -/** - * dsi_link_clk_stop() - Stop DSI link clocks. - */ -static int dsi_link_hs_clk_stop(struct dsi_link_hs_clk_info *link_hs_clks) -{ - struct dsi_link_clks *l_clks; - - l_clks = container_of(link_hs_clks, struct dsi_link_clks, hs_clks); - - dsi_link_hs_clk_disable(link_hs_clks); - dsi_link_hs_clk_unprepare(link_hs_clks); - - pr_debug("HS Link clocks disabled\n"); - - return 0; -} - -static int dsi_link_lp_clk_start(struct dsi_link_lp_clk_info *link_lp_clks, - int index) -{ - int rc = 0; - struct dsi_clk_mngr *mngr; - struct dsi_link_clks *l_clks; - - if (index >= MAX_DSI_CTRL) { - pr_err("Invalid DSI ctrl index\n"); - return -EINVAL; - } - - l_clks = container_of(link_lp_clks, struct dsi_link_clks, lp_clks); - - mngr = container_of(l_clks, struct dsi_clk_mngr, link_clks[index]); - if (!mngr) - return -EINVAL; - - /* - * In an ideal world, cont_splash_enabled should not be required inside - * the clock manager. But, in the current driver cont_splash_enabled - * flag is set inside mdp driver and there is no interface event - * associated with this flag setting. Also, set rate for clock need not - * be called for every enable call. It should be done only once when - * coming out of suspend. - */ - if (mngr->is_cont_splash_enabled) - goto prepare; - - rc = clk_set_rate(link_lp_clks->esc_clk, l_clks->freq.esc_clk_rate); - if (rc) { - pr_err("clk_set_rate failed for esc_clk rc = %d\n", rc); - goto error; - } - -prepare: - rc = clk_prepare_enable(link_lp_clks->esc_clk); - if (rc) { - pr_err("Failed to enable dsi esc clk\n"); - clk_unprepare(l_clks->lp_clks.esc_clk); - } -error: - pr_debug("LP Link clocks are enabled\n"); - return rc; -} - -static int dsi_link_lp_clk_stop( - struct dsi_link_lp_clk_info *link_lp_clks) -{ - struct dsi_link_clks *l_clks; - - l_clks = container_of(link_lp_clks, struct dsi_link_clks, lp_clks); - - clk_disable_unprepare(l_clks->lp_clks.esc_clk); - - pr_debug("LP Link clocks are disabled\n"); - return 0; -} - -static int dsi_display_core_clk_enable(struct dsi_core_clks *clks, - u32 ctrl_count, u32 master_ndx) -{ - int rc = 0; - int i; - struct dsi_core_clks *clk, *m_clks; - - /* - * In case of split DSI usecases, the clock for master controller should - * be enabled before the other controller. Master controller in the - * clock context refers to the controller that sources the clock. - */ - - m_clks = &clks[master_ndx]; - rc = sde_power_resource_enable(m_clks->clks.phandle, - m_clks->clks.dsi_core_client, true); - - if (rc) { - pr_err("Power resource enable failed, rc=%d\n", rc); - goto error; - } - - rc = dsi_core_clk_start(m_clks); - if (rc) { - pr_err("failed to turn on master clocks, rc=%d\n", rc); - goto error_disable_master_resource; - } - - /* Turn on rest of the core clocks */ - for (i = 0; i < ctrl_count; i++) { - clk = &clks[i]; - if (!clk || (clk == m_clks)) - continue; - - rc = sde_power_resource_enable(clk->clks.phandle, - clk->clks.dsi_core_client, true); - if (rc) { - pr_err("Power resource enable failed, rc=%d\n", rc); - goto error_disable_master; - } - - rc = dsi_core_clk_start(clk); - if (rc) { - pr_err("failed to turn on clocks, rc=%d\n", rc); - (void)sde_power_resource_enable(clk->clks.phandle, - clk->clks.dsi_core_client, false); - goto error_disable_master; - } - } - return rc; -error_disable_master: - (void)dsi_core_clk_stop(m_clks); - -error_disable_master_resource: - (void)sde_power_resource_enable(m_clks->clks.phandle, - m_clks->clks.dsi_core_client, false); -error: - return rc; -} - -static int dsi_display_link_clk_enable(struct dsi_link_clks *clks, - enum dsi_lclk_type l_type, u32 ctrl_count, u32 master_ndx) -{ - int rc = 0; - int i; - struct dsi_link_clks *clk, *m_clks; - - /* - * In case of split DSI usecases, the clock for master controller should - * be enabled before the other controller. Master controller in the - * clock context refers to the controller that sources the clock. - */ - - m_clks = &clks[master_ndx]; - - if (l_type & DSI_LINK_LP_CLK) { - rc = dsi_link_lp_clk_start(&m_clks->lp_clks, master_ndx); - if (rc) { - pr_err("failed to turn on master lp link clocks, rc=%d\n", - rc); - goto error; - } - } - - if (l_type & DSI_LINK_HS_CLK) { - rc = dsi_link_hs_clk_start(&m_clks->hs_clks, - DSI_LINK_CLK_START, master_ndx); - if (rc) { - pr_err("failed to turn on master hs link clocks, rc=%d\n", - rc); - goto error; - } - } - - for (i = 0; i < ctrl_count; i++) { - clk = &clks[i]; - if (!clk || (clk == m_clks)) - continue; - - if (l_type & DSI_LINK_LP_CLK) { - rc = dsi_link_lp_clk_start(&clk->lp_clks, i); - if (rc) { - pr_err("failed to turn on lp link clocks, rc=%d\n", - rc); - goto error_disable_master; - } - } - - if (l_type & DSI_LINK_HS_CLK) { - rc = dsi_link_hs_clk_start(&clk->hs_clks, - DSI_LINK_CLK_START, i); - if (rc) { - pr_err("failed to turn on hs link clocks, rc=%d\n", - rc); - goto error_disable_master; - } - } - } - return rc; - -error_disable_master: - if (l_type == DSI_LINK_LP_CLK) - (void)dsi_link_lp_clk_stop(&m_clks->lp_clks); - else if (l_type == DSI_LINK_HS_CLK) - (void)dsi_link_hs_clk_stop(&m_clks->hs_clks); -error: - return rc; -} - -static int dsi_display_core_clk_disable(struct dsi_core_clks *clks, - u32 ctrl_count, u32 master_ndx) -{ - int rc = 0; - int i; - struct dsi_core_clks *clk, *m_clks; - - /* - * In case of split DSI usecases, clock for slave DSI controllers should - * be disabled first before disabling clock for master controller. Slave - * controllers in the clock context refer to controller which source - * clock from another controller. - */ - - m_clks = &clks[master_ndx]; - - /* Turn off non-master core clocks */ - for (i = 0; i < ctrl_count; i++) { - clk = &clks[i]; - if (!clk || (clk == m_clks)) - continue; - - rc = dsi_core_clk_stop(clk); - if (rc) { - pr_debug("failed to turn off clocks, rc=%d\n", rc); - goto error; - } - - rc = sde_power_resource_enable(clk->clks.phandle, - clk->clks.dsi_core_client, false); - if (rc) { - pr_err("Power resource disable failed: %d\n", rc); - goto error; - } - } - - rc = dsi_core_clk_stop(m_clks); - if (rc) { - pr_err("failed to turn off master clocks, rc=%d\n", rc); - goto error; - } - - rc = sde_power_resource_enable(m_clks->clks.phandle, - m_clks->clks.dsi_core_client, false); - if (rc) - pr_err("Power resource disable failed: %d\n", rc); -error: - return rc; -} - -static int dsi_display_link_clk_disable(struct dsi_link_clks *clks, - enum dsi_lclk_type l_type, u32 ctrl_count, u32 master_ndx) -{ - int rc = 0; - int i; - struct dsi_link_clks *clk, *m_clks; - - /* - * In case of split DSI usecases, clock for slave DSI controllers should - * be disabled first before disabling clock for master controller. Slave - * controllers in the clock context refer to controller which source - * clock from another controller. - */ - - m_clks = &clks[master_ndx]; - - /* Turn off non-master link clocks */ - for (i = 0; i < ctrl_count; i++) { - clk = &clks[i]; - if (!clk || (clk == m_clks)) - continue; - - if (l_type & DSI_LINK_LP_CLK) { - rc = dsi_link_lp_clk_stop(&clk->lp_clks); - if (rc) - pr_err("failed to turn off lp link clocks, rc=%d\n", - rc); - } - - if (l_type & DSI_LINK_HS_CLK) { - rc = dsi_link_hs_clk_stop(&clk->hs_clks); - if (rc) - pr_err("failed to turn off hs link clocks, rc=%d\n", - rc); - } - } - - if (l_type & DSI_LINK_LP_CLK) { - rc = dsi_link_lp_clk_stop(&m_clks->lp_clks); - if (rc) - pr_err("failed to turn off master lp link clocks, rc=%d\n", - rc); - } - - if (l_type & DSI_LINK_HS_CLK) { - rc = dsi_link_hs_clk_stop(&m_clks->hs_clks); - if (rc) - pr_err("failed to turn off master hs link clocks, rc=%d\n", - rc); - } - - return rc; -} - -static int dsi_clk_update_link_clk_state(struct dsi_clk_mngr *mngr, - struct dsi_link_clks *l_clks, enum dsi_lclk_type l_type, u32 l_state, - bool enable) -{ - int rc = 0; - - if (!mngr) - return -EINVAL; - - if (enable) { - if (mngr->pre_clkon_cb) { - rc = mngr->pre_clkon_cb(mngr->priv_data, DSI_LINK_CLK, - l_type, l_state); - if (rc) { - pr_err("pre link clk on cb failed for type %d\n", - l_type); - goto error; - } - } - rc = dsi_display_link_clk_enable(l_clks, l_type, - mngr->dsi_ctrl_count, mngr->master_ndx); - if (rc) { - pr_err("failed to start link clk type %d rc=%d\n", - l_type, rc); - goto error; - } - - if (mngr->post_clkon_cb) { - rc = mngr->post_clkon_cb(mngr->priv_data, DSI_LINK_CLK, - l_type, l_state); - if (rc) { - pr_err("post link clk on cb failed for type %d\n", - l_type); - goto error; - } - } - } else { - if (mngr->pre_clkoff_cb) { - rc = mngr->pre_clkoff_cb(mngr->priv_data, - DSI_LINK_CLK, l_type, l_state); - if (rc) - pr_err("pre link clk off cb failed\n"); - } - - rc = dsi_display_link_clk_disable(l_clks, l_type, - mngr->dsi_ctrl_count, mngr->master_ndx); - if (rc) { - pr_err("failed to stop link clk type %d, rc = %d\n", - l_type, rc); - goto error; - } - - if (mngr->post_clkoff_cb) { - rc = mngr->post_clkoff_cb(mngr->priv_data, - DSI_LINK_CLK, l_type, l_state); - if (rc) - pr_err("post link clk off cb failed\n"); - } - } - -error: - return rc; -} - -static int dsi_update_core_clks(struct dsi_clk_mngr *mngr, - struct dsi_core_clks *c_clks) -{ - int rc = 0; - - if (mngr->core_clk_state == DSI_CLK_OFF) { - rc = mngr->pre_clkon_cb(mngr->priv_data, - DSI_CORE_CLK, - DSI_LINK_NONE, - DSI_CLK_ON); - if (rc) { - pr_err("failed to turn on MDP FS rc= %d\n", rc); - goto error; - } - } - rc = dsi_display_core_clk_enable(c_clks, mngr->dsi_ctrl_count, - mngr->master_ndx); - if (rc) { - pr_err("failed to turn on core clks rc = %d\n", rc); - goto error; - } - - if (mngr->post_clkon_cb) { - rc = mngr->post_clkon_cb(mngr->priv_data, - DSI_CORE_CLK, - DSI_LINK_NONE, - DSI_CLK_ON); - if (rc) - pr_err("post clk on cb failed, rc = %d\n", rc); - } - mngr->core_clk_state = DSI_CLK_ON; -error: - return rc; -} - -static int dsi_update_clk_state(struct dsi_clk_mngr *mngr, - struct dsi_core_clks *c_clks, u32 c_state, - struct dsi_link_clks *l_clks, u32 l_state) -{ - int rc = 0; - bool l_c_on = false; - - if (!mngr) - return -EINVAL; - - pr_debug("c_state = %d, l_state = %d\n", - c_clks ? c_state : -1, l_clks ? l_state : -1); - /* - * Below is the sequence to toggle DSI clocks: - * 1. For ON sequence, Core clocks before link clocks - * 2. For OFF sequence, Link clocks before core clocks. - */ - if (c_clks && (c_state == DSI_CLK_ON)) - rc = dsi_update_core_clks(mngr, c_clks); - - if (rc) - goto error; - - if (l_clks) { - if (l_state == DSI_CLK_ON) { - rc = dsi_clk_update_link_clk_state(mngr, l_clks, - DSI_LINK_LP_CLK, l_state, true); - if (rc) - goto error; - - rc = dsi_clk_update_link_clk_state(mngr, l_clks, - DSI_LINK_HS_CLK, l_state, true); - if (rc) - goto error; - } else { - /* - * Two conditions that need to be checked for Link - * clocks: - * 1. Link clocks need core clocks to be on when - * transitioning from EARLY_GATE to OFF state. - * 2. ULPS mode might have to be enabled in case of OFF - * state. For ULPS, Link clocks should be turned ON - * first before they are turned off again. - * - * If Link is going from EARLY_GATE to OFF state AND - * Core clock is already in EARLY_GATE or OFF state, - * turn on Core clocks and link clocks. - * - * ULPS state is managed as part of the pre_clkoff_cb. - */ - if ((l_state == DSI_CLK_OFF) && - (mngr->link_clk_state == - DSI_CLK_EARLY_GATE) && - (mngr->core_clk_state != - DSI_CLK_ON)) { - rc = dsi_display_core_clk_enable( - mngr->core_clks, mngr->dsi_ctrl_count, - mngr->master_ndx); - if (rc) { - pr_err("core clks did not start\n"); - goto error; - } - - rc = dsi_display_link_clk_enable(l_clks, - (DSI_LINK_LP_CLK & DSI_LINK_HS_CLK), - mngr->dsi_ctrl_count, mngr->master_ndx); - if (rc) { - pr_err("LP Link clks did not start\n"); - goto error; - } - l_c_on = true; - pr_debug("ECG: core and Link_on\n"); - } - - rc = dsi_clk_update_link_clk_state(mngr, l_clks, - DSI_LINK_HS_CLK, l_state, false); - if (rc) - goto error; - - rc = dsi_clk_update_link_clk_state(mngr, l_clks, - DSI_LINK_LP_CLK, l_state, false); - if (rc) - goto error; - - /* - * This check is to save unnecessary clock state - * change when going from EARLY_GATE to OFF. In the - * case where the request happens for both Core and Link - * clocks in the same call, core clocks need to be - * turned on first before OFF state can be entered. - * - * Core clocks are turned on here for Link clocks to go - * to OFF state. If core clock request is also present, - * then core clocks can be turned off Core clocks are - * transitioned to OFF state. - */ - if (l_c_on && (!(c_clks && (c_state == DSI_CLK_OFF) - && (mngr->core_clk_state == - DSI_CLK_EARLY_GATE)))) { - rc = dsi_display_core_clk_disable( - mngr->core_clks, mngr->dsi_ctrl_count, - mngr->master_ndx); - if (rc) { - pr_err("core clks did not stop\n"); - goto error; - } - - l_c_on = false; - pr_debug("ECG: core off\n"); - } else - pr_debug("ECG: core off skip\n"); - } - - mngr->link_clk_state = l_state; - } - - if (c_clks && (c_state != DSI_CLK_ON)) { - /* - * When going to OFF state from EARLY GATE state, Core clocks - * should be turned on first so that the IOs can be clamped. - * l_c_on flag is set, then the core clocks were turned before - * to the Link clocks go to OFF state. So Core clocks are - * already ON and this step can be skipped. - * - * IOs are clamped in pre_clkoff_cb callback. - */ - if ((c_state == DSI_CLK_OFF) && - (mngr->core_clk_state == - DSI_CLK_EARLY_GATE) && !l_c_on) { - rc = dsi_display_core_clk_enable(mngr->core_clks, - mngr->dsi_ctrl_count, mngr->master_ndx); - if (rc) { - pr_err("core clks did not start\n"); - goto error; - } - pr_debug("ECG: core on\n"); - } else - pr_debug("ECG: core on skip\n"); - - if (mngr->pre_clkoff_cb) { - rc = mngr->pre_clkoff_cb(mngr->priv_data, - DSI_CORE_CLK, - DSI_LINK_NONE, - c_state); - if (rc) - pr_err("pre core clk off cb failed\n"); - } - - rc = dsi_display_core_clk_disable(c_clks, mngr->dsi_ctrl_count, - mngr->master_ndx); - if (rc) { - pr_err("failed to turn off core clks rc = %d\n", rc); - goto error; - } - - if (c_state == DSI_CLK_OFF) { - if (mngr->post_clkoff_cb) { - rc = mngr->post_clkoff_cb(mngr->priv_data, - DSI_CORE_CLK, - DSI_LINK_NONE, - DSI_CLK_OFF); - if (rc) - pr_err("post clkoff cb fail, rc = %d\n", - rc); - } - } - mngr->core_clk_state = c_state; - } - -error: - return rc; -} - -static int dsi_recheck_clk_state(struct dsi_clk_mngr *mngr) -{ - int rc = 0; - struct list_head *pos = NULL; - struct dsi_clk_client_info *c; - u32 new_core_clk_state = DSI_CLK_OFF; - u32 new_link_clk_state = DSI_CLK_OFF; - u32 old_c_clk_state = DSI_CLK_OFF; - u32 old_l_clk_state = DSI_CLK_OFF; - struct dsi_core_clks *c_clks = NULL; - struct dsi_link_clks *l_clks = NULL; - - /* - * Conditions to maintain DSI manager clock state based on - * clock states of various clients: - * 1. If any client has clock in ON state, DSI manager clock state - * should be ON. - * 2. If any client is in ECG state with rest of them turned OFF, - * go to Early gate state. - * 3. If all clients have clocks as OFF, then go to OFF state. - */ - list_for_each(pos, &mngr->client_list) { - c = list_entry(pos, struct dsi_clk_client_info, list); - if (c->core_clk_state == DSI_CLK_ON) { - new_core_clk_state = DSI_CLK_ON; - break; - } else if (c->core_clk_state == DSI_CLK_EARLY_GATE) { - new_core_clk_state = DSI_CLK_EARLY_GATE; - } - } - - list_for_each(pos, &mngr->client_list) { - c = list_entry(pos, struct dsi_clk_client_info, list); - if (c->link_clk_state == DSI_CLK_ON) { - new_link_clk_state = DSI_CLK_ON; - break; - } else if (c->link_clk_state == DSI_CLK_EARLY_GATE) { - new_link_clk_state = DSI_CLK_EARLY_GATE; - } - } - - if (new_core_clk_state != mngr->core_clk_state) - c_clks = mngr->core_clks; - - if (new_link_clk_state != mngr->link_clk_state) - l_clks = mngr->link_clks; - - old_c_clk_state = mngr->core_clk_state; - old_l_clk_state = mngr->link_clk_state; - - pr_debug("c_clk_state (%d -> %d)\n", - old_c_clk_state, new_core_clk_state); - pr_debug("l_clk_state (%d -> %d)\n", - old_l_clk_state, new_link_clk_state); - - if (c_clks || l_clks) { - rc = dsi_update_clk_state(mngr, c_clks, new_core_clk_state, - l_clks, new_link_clk_state); - if (rc) { - pr_err("failed to update clock state, rc = %d\n", rc); - goto error; - } - } - -error: - return rc; -} - -int dsi_clk_req_state(void *client, enum dsi_clk_type clk, - enum dsi_clk_state state) -{ - int rc = 0; - struct dsi_clk_client_info *c = client; - struct dsi_clk_mngr *mngr; - bool changed = false; - - if (!client || !clk || clk > (DSI_CORE_CLK | DSI_LINK_CLK) || - state > DSI_CLK_EARLY_GATE) { - pr_err("Invalid params, client = %pK, clk = 0x%x, state = %d\n", - client, clk, state); - return -EINVAL; - } - - mngr = c->mngr; - mutex_lock(&mngr->clk_mutex); - - pr_debug("[%s]%s: CLK=%d, new_state=%d, core=%d, linkl=%d\n", - mngr->name, c->name, clk, state, c->core_clk_state, - c->link_clk_state); - - /* - * Clock refcount handling as below: - * i. Increment refcount whenever ON is called. - * ii. Decrement refcount when transitioning from ON state to - * either OFF or EARLY_GATE. - * iii. Do not decrement refcount when changing from - * EARLY_GATE to OFF. - */ - if (state == DSI_CLK_ON) { - if (clk & DSI_CORE_CLK) { - c->core_refcount++; - if (c->core_clk_state != DSI_CLK_ON) { - c->core_clk_state = DSI_CLK_ON; - changed = true; - } - } - if (clk & DSI_LINK_CLK) { - c->link_refcount++; - if (c->link_clk_state != DSI_CLK_ON) { - c->link_clk_state = DSI_CLK_ON; - changed = true; - } - } - } else if ((state == DSI_CLK_EARLY_GATE) || - (state == DSI_CLK_OFF)) { - if (clk & DSI_CORE_CLK) { - if (c->core_refcount == 0) { - if ((c->core_clk_state == - DSI_CLK_EARLY_GATE) && - (state == DSI_CLK_OFF)) { - changed = true; - c->core_clk_state = DSI_CLK_OFF; - } else { - pr_warn("Core refcount is zero for %s\n", - c->name); - } - } else { - c->core_refcount--; - if (c->core_refcount == 0) { - c->core_clk_state = state; - changed = true; - } - } - } - if (clk & DSI_LINK_CLK) { - if (c->link_refcount == 0) { - if ((c->link_clk_state == - DSI_CLK_EARLY_GATE) && - (state == DSI_CLK_OFF)) { - changed = true; - c->link_clk_state = DSI_CLK_OFF; - } else { - pr_warn("Link refcount is zero for %s\n", - c->name); - } - } else { - c->link_refcount--; - if (c->link_refcount == 0) { - c->link_clk_state = state; - changed = true; - } - } - } - } - pr_debug("[%s]%s: change=%d, Core (ref=%d, state=%d), Link (ref=%d, state=%d)\n", - mngr->name, c->name, changed, c->core_refcount, - c->core_clk_state, c->link_refcount, c->link_clk_state); - - if (changed) { - rc = dsi_recheck_clk_state(mngr); - if (rc) - pr_err("Failed to adjust clock state rc = %d\n", rc); - } - - mutex_unlock(&mngr->clk_mutex); - return rc; -} - -DEFINE_MUTEX(dsi_mngr_clk_mutex); - -static int dsi_display_link_clk_force_update(void *client) -{ - int rc = 0; - struct dsi_clk_client_info *c = client; - struct dsi_clk_mngr *mngr; - struct dsi_link_clks *l_clks; - - mngr = c->mngr; - mutex_lock(&mngr->clk_mutex); - - l_clks = mngr->link_clks; - - /* - * When link_clk_state is DSI_CLK_OFF, don't change DSI clock rate - * since it is possible to be overwritten, and return -EAGAIN to - * dynamic DSI writing interface to defer the reenabling to the next - * drm commit. - */ - if (mngr->link_clk_state == DSI_CLK_OFF) { - rc = -EAGAIN; - goto error; - } - - rc = dsi_display_link_clk_disable(l_clks, - (DSI_LINK_LP_CLK | DSI_LINK_HS_CLK), - mngr->dsi_ctrl_count, mngr->master_ndx); - if (rc) { - pr_err("%s, failed to stop link clk, rc = %d\n", - __func__, rc); - goto error; - } - - rc = dsi_display_link_clk_enable(l_clks, - (DSI_LINK_LP_CLK | DSI_LINK_HS_CLK), - mngr->dsi_ctrl_count, mngr->master_ndx); - if (rc) { - pr_err("%s, failed to start link clk rc= %d\n", - __func__, rc); - goto error; - } - -error: - mutex_unlock(&mngr->clk_mutex); - return rc; - -} - -int dsi_display_link_clk_force_update_ctrl(void *handle) -{ - int rc = 0; - - if (!handle) { - pr_err("%s: Invalid arg\n", __func__); - return -EINVAL; - } - - mutex_lock(&dsi_mngr_clk_mutex); - - rc = dsi_display_link_clk_force_update(handle); - - mutex_unlock(&dsi_mngr_clk_mutex); - - return rc; -} - -int dsi_display_clk_ctrl(void *handle, - enum dsi_clk_type clk_type, enum dsi_clk_state clk_state) -{ - int rc = 0; - - if (!handle) { - pr_err("%s: Invalid arg\n", __func__); - return -EINVAL; - } - - mutex_lock(&dsi_mngr_clk_mutex); - rc = dsi_clk_req_state(handle, clk_type, clk_state); - if (rc) - pr_err("%s: failed set clk state, rc = %d\n", __func__, rc); - mutex_unlock(&dsi_mngr_clk_mutex); - - return rc; -} - -void *dsi_register_clk_handle(void *clk_mngr, char *client) -{ - void *handle = NULL; - struct dsi_clk_mngr *mngr = clk_mngr; - struct dsi_clk_client_info *c; - - if (!mngr) { - pr_err("bad params\n"); - return ERR_PTR(-EINVAL); - } - - mutex_lock(&mngr->clk_mutex); - - c = kzalloc(sizeof(*c), GFP_KERNEL); - if (!c) { - handle = ERR_PTR(-ENOMEM); - goto error; - } - - strlcpy(c->name, client, MAX_STRING_LEN); - c->mngr = mngr; - - list_add(&c->list, &mngr->client_list); - - pr_debug("[%s]: Added new client (%s)\n", mngr->name, c->name); - handle = c; -error: - mutex_unlock(&mngr->clk_mutex); - return handle; -} - -int dsi_deregister_clk_handle(void *client) -{ - int rc = 0; - struct dsi_clk_client_info *c = client; - struct dsi_clk_mngr *mngr; - struct list_head *pos = NULL; - struct list_head *tmp = NULL; - struct dsi_clk_client_info *node = NULL; - - if (!client) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - mngr = c->mngr; - pr_debug("%s: ENTER\n", mngr->name); - mutex_lock(&mngr->clk_mutex); - c->core_clk_state = DSI_CLK_OFF; - c->link_clk_state = DSI_CLK_OFF; - - rc = dsi_recheck_clk_state(mngr); - if (rc) { - pr_err("clock state recheck failed rc = %d\n", rc); - goto error; - } - - list_for_each_safe(pos, tmp, &mngr->client_list) { - node = list_entry(pos, struct dsi_clk_client_info, - list); - if (node == c) { - list_del(&node->list); - pr_debug("Removed device (%s)\n", node->name); - kfree(node); - break; - } - } - -error: - mutex_unlock(&mngr->clk_mutex); - pr_debug("%s: EXIT, rc = %d\n", mngr->name, rc); - return rc; -} - -void dsi_display_clk_mngr_update_splash_status(void *clk_mgr, bool status) -{ - struct dsi_clk_mngr *mngr; - - if (!clk_mgr) { - pr_err("Invalid params\n"); - return; - } - - mngr = (struct dsi_clk_mngr *)clk_mgr; - mngr->is_cont_splash_enabled = status; -} - -void *dsi_display_clk_mngr_register(struct dsi_clk_info *info) -{ - struct dsi_clk_mngr *mngr; - int i = 0; - - if (!info) { - pr_err("Invalid params\n"); - return ERR_PTR(-EINVAL); - } - - mngr = kzalloc(sizeof(*mngr), GFP_KERNEL); - if (!mngr) { - mngr = ERR_PTR(-ENOMEM); - goto error; - } - - mutex_init(&mngr->clk_mutex); - mngr->dsi_ctrl_count = info->dsi_ctrl_count; - mngr->master_ndx = info->master_ndx; - - if (mngr->dsi_ctrl_count > MAX_DSI_CTRL) { - kfree(mngr); - return ERR_PTR(-EINVAL); - } - - for (i = 0; i < mngr->dsi_ctrl_count; i++) { - memcpy(&mngr->core_clks[i].clks, &info->c_clks[i], - sizeof(struct dsi_core_clk_info)); - memcpy(&mngr->link_clks[i].hs_clks, &info->l_hs_clks[i], - sizeof(struct dsi_link_hs_clk_info)); - memcpy(&mngr->link_clks[i].lp_clks, &info->l_lp_clks[i], - sizeof(struct dsi_link_lp_clk_info)); - mngr->core_clks[i].bus_handle = info->bus_handle[i]; - mngr->ctrl_index[i] = info->ctrl_index[i]; - } - - INIT_LIST_HEAD(&mngr->client_list); - mngr->pre_clkon_cb = info->pre_clkon_cb; - mngr->post_clkon_cb = info->post_clkon_cb; - mngr->pre_clkoff_cb = info->pre_clkoff_cb; - mngr->post_clkoff_cb = info->post_clkoff_cb; - mngr->priv_data = info->priv_data; - memcpy(mngr->name, info->name, MAX_STRING_LEN); - -error: - pr_debug("EXIT, rc = %ld\n", PTR_ERR(mngr)); - return mngr; -} - -int dsi_display_clk_mngr_deregister(void *clk_mngr) -{ - int rc = 0; - struct dsi_clk_mngr *mngr = clk_mngr; - struct list_head *position = NULL; - struct list_head *tmp = NULL; - struct dsi_clk_client_info *node = NULL; - - if (!mngr) { - pr_err("Invalid params\n"); - return -EINVAL; - } - - pr_debug("%s: ENTER\n", mngr->name); - mutex_lock(&mngr->clk_mutex); - - list_for_each_safe(position, tmp, &mngr->client_list) { - node = list_entry(position, struct dsi_clk_client_info, - list); - list_del(&node->list); - pr_debug("Removed device (%s)\n", node->name); - kfree(node); - } - - rc = dsi_recheck_clk_state(mngr); - if (rc) - pr_err("failed to disable all clocks\n"); - - mutex_unlock(&mngr->clk_mutex); - pr_debug("%s: EXIT, rc = %d\n", mngr->name, rc); - kfree(mngr); - return rc; -} diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c deleted file mode 100644 index cb22ab9d7d7bb5d060d1288d5e5e6a1a57b1a99f..0000000000000000000000000000000000000000 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +++ /dev/null @@ -1,3615 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. - */ - -#define pr_fmt(fmt) "dsi-ctrl:[%s] " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include