diff --git a/msm/dsi/dsi_phy.c b/msm/dsi/dsi_phy.c index 96bd133d..7a15449e 100644 --- a/msm/dsi/dsi_phy.c +++ b/msm/dsi/dsi_phy.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -796,7 +796,7 @@ static inline int dsi_phy_get_data_lanes_count(struct msm_dsi_phy *phy) int num_of_lanes = 0; enum dsi_data_lanes dlanes; - dlanes = phy->data_lanes; + dlanes = phy->cfg.data_lanes; /** * For split link use case effective data lines need to be used @@ -1021,8 +1021,8 @@ int dsi_phy_enable(struct msm_dsi_phy *phy, memcpy(&phy->mode, &config->video_timing, sizeof(phy->mode)); memcpy(&phy->cfg.lane_map, &config->lane_map, sizeof(config->lane_map)); - phy->data_lanes = config->common_config.data_lanes; phy->dst_format = config->common_config.dst_format; + phy->cfg.data_lanes = config->common_config.data_lanes; phy->cfg.pll_source = pll_source; phy->cfg.bit_clk_rate_hz = config->bit_clk_rate_hz; diff --git a/msm/dsi/dsi_phy.h b/msm/dsi/dsi_phy.h index 1e291033..d36a90a5 100644 --- a/msm/dsi/dsi_phy.h +++ b/msm/dsi/dsi_phy.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _DSI_PHY_H_ @@ -69,7 +70,6 @@ enum phy_ulps_return_type { * @power_state: True if PHY is powered on. * @dsi_phy_state: PHY state information. * @mode: Current mode. - * @data_lanes: Number of data lanes used. * @dst_format: Destination format. * @pll: Pointer to PLL resource. * @allow_phy_power_off: True if PHY is allowed to power off when idle @@ -95,7 +95,6 @@ struct msm_dsi_phy { enum phy_engine_state dsi_phy_state; bool power_state; struct dsi_mode_info mode; - enum dsi_data_lanes data_lanes; enum dsi_pixel_format dst_format; struct dsi_pll_resource *pll; diff --git a/msm/dsi/dsi_phy_hw.h b/msm/dsi/dsi_phy_hw.h index d74e2ad7..d1ebb45a 100644 --- a/msm/dsi/dsi_phy_hw.h +++ b/msm/dsi/dsi_phy_hw.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _DSI_PHY_HW_H_ @@ -116,6 +116,7 @@ struct dsi_phy_per_lane_cfgs { * @is_phy_timing_present: Boolean whether phy timings are defined. * @regulators: Regulator settings for lanes. * @pll_source: PLL source. + * @data_lanes: Bitmask of enum dsi_data_lanes. * @lane_map: DSI logical to PHY lane mapping. * @force_clk_lane_hs:Boolean whether to force clock lane in HS mode. * @phy_type: Phy-type (Dphy/Cphy). @@ -134,6 +135,7 @@ struct dsi_phy_cfg { enum dsi_phy_type phy_type; unsigned long bit_clk_rate_hz; struct dsi_split_link_config split_link; + u32 data_lanes; }; struct dsi_phy_hw; diff --git a/msm/dsi/dsi_phy_hw_v4_0.c b/msm/dsi/dsi_phy_hw_v4_0.c index bb7c33ff..56a343c9 100644 --- a/msm/dsi/dsi_phy_hw_v4_0.c +++ b/msm/dsi/dsi_phy_hw_v4_0.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -234,6 +234,26 @@ void dsi_phy_hw_v4_0_commit_phy_timing(struct dsi_phy_hw *phy, DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_13, timing->lane_v4[13]); } +/** + * calc_cmn_lane_ctrl0() - Calculate the value to be set for + * DSIPHY_CMN_LANE_CTRL0 register. + * @cfg: Per lane configurations for timing, strength and lane + * configurations. + */ +static inline u32 dsi_phy_hw_calc_cmn_lane_ctrl0(struct dsi_phy_cfg *cfg) +{ + u32 cmn_lane_ctrl0 = 0; + + /* Only enable lanes that are required */ + cmn_lane_ctrl0 |= ((cfg->data_lanes & DSI_DATA_LANE_0) ? BIT(0) : 0); + cmn_lane_ctrl0 |= ((cfg->data_lanes & DSI_DATA_LANE_1) ? BIT(1) : 0); + cmn_lane_ctrl0 |= ((cfg->data_lanes & DSI_DATA_LANE_2) ? BIT(2) : 0); + cmn_lane_ctrl0 |= ((cfg->data_lanes & DSI_DATA_LANE_3) ? BIT(3) : 0); + cmn_lane_ctrl0 |= BIT(4); + + return cmn_lane_ctrl0; +} + /** * cphy_enable() - Enable CPHY hardware * @phy: Pointer to DSI PHY hardware object. @@ -254,6 +274,7 @@ static void dsi_phy_hw_cphy_enable(struct dsi_phy_hw *phy, u32 glbl_rescode_top_ctrl = 0; u32 glbl_rescode_bot_ctrl = 0; bool less_than_1500_mhz = false; + u32 cmn_lane_ctrl0 = 0; /* Alter PHY configurations if data rate less than 1.5GHZ*/ if (cfg->bit_clk_rate_hz <= 1500000000) @@ -317,7 +338,8 @@ static void dsi_phy_hw_cphy_enable(struct dsi_phy_hw *phy, /* Remove power down from all blocks */ DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0x7f); - DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, 0x17); + cmn_lane_ctrl0 = dsi_phy_hw_calc_cmn_lane_ctrl0(cfg); + DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, cmn_lane_ctrl0); switch (cfg->pll_source) { case DSI_PLL_SOURCE_STANDALONE: @@ -370,6 +392,7 @@ static void dsi_phy_hw_dphy_enable(struct dsi_phy_hw *phy, u32 glbl_rescode_bot_ctrl = 0; bool split_link_enabled; u32 lanes_per_sublink; + u32 cmn_lane_ctrl0 = 0; /* Alter PHY configurations if data rate less than 1.5GHZ*/ if (cfg->bit_clk_rate_hz <= 1500000000) @@ -458,7 +481,8 @@ static void dsi_phy_hw_dphy_enable(struct dsi_phy_hw *phy, } else { /* Remove power down from all blocks */ DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0x7f); - DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, 0x1F); + cmn_lane_ctrl0 = dsi_phy_hw_calc_cmn_lane_ctrl0(cfg); + DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, cmn_lane_ctrl0); } /* Select full-rate mode */ @@ -764,8 +788,7 @@ void dsi_phy_hw_v4_0_dyn_refresh_config(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg, bool is_master) { u32 reg; - bool is_cphy = (cfg->phy_type == DSI_PHY_TYPE_CPHY) ? - true : false; + u32 cmn_lane_ctrl0 = dsi_phy_hw_calc_cmn_lane_ctrl0(cfg); if (is_master) { DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL19, @@ -791,7 +814,7 @@ void dsi_phy_hw_v4_0_dyn_refresh_config(struct dsi_phy_hw *phy, cfg->timing.lane_v4[12], cfg->timing.lane_v4[13]); DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL26, DSIPHY_CMN_CTRL_0, DSIPHY_CMN_LANE_CTRL0, - 0x7f, is_cphy ? 0x17 : 0x1f); + 0x7f, cmn_lane_ctrl0); } else { reg = DSI_R32(phy, DSIPHY_CMN_CLK_CFG1); @@ -826,7 +849,7 @@ void dsi_phy_hw_v4_0_dyn_refresh_config(struct dsi_phy_hw *phy, cfg->timing.lane_v4[13], 0x7f); DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL9, DSIPHY_CMN_LANE_CTRL0, DSIPHY_CMN_CTRL_2, - is_cphy ? 0x17 : 0x1f, 0x40); + cmn_lane_ctrl0, 0x40); /* * fill with dummy register writes since controller will blindly * send these values to DSI PHY. @@ -835,7 +858,7 @@ void dsi_phy_hw_v4_0_dyn_refresh_config(struct dsi_phy_hw *phy, while (reg <= DSI_DYN_REFRESH_PLL_CTRL29) { DSI_DYN_REF_REG_W(phy->dyn_pll_base, reg, DSIPHY_CMN_LANE_CTRL0, DSIPHY_CMN_CTRL_0, - is_cphy ? 0x17 : 0x1f, 0x7f); + cmn_lane_ctrl0, 0x7f); reg += 0x4; } diff --git a/msm/dsi/dsi_phy_hw_v5_0.c b/msm/dsi/dsi_phy_hw_v5_0.c index 698e82c1..3c95f1c7 100644 --- a/msm/dsi/dsi_phy_hw_v5_0.c +++ b/msm/dsi/dsi_phy_hw_v5_0.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -226,6 +226,26 @@ void dsi_phy_hw_v5_0_commit_phy_timing(struct dsi_phy_hw *phy, DSI_W32(phy, DSIPHY_CMN_TIMING_CTRL_13, timing->lane_v4[13]); } +/** + * calc_cmn_lane_ctrl0() - Calculate the value to be set for + * DSIPHY_CMN_LANE_CTRL0 register. + * @cfg: Per lane configurations for timing, strength and lane + * configurations. + */ +static inline u32 dsi_phy_hw_calc_cmn_lane_ctrl0(struct dsi_phy_cfg *cfg) +{ + u32 cmn_lane_ctrl0 = 0; + + /* Only enable lanes that are required */ + cmn_lane_ctrl0 |= ((cfg->data_lanes & DSI_DATA_LANE_0) ? BIT(0) : 0); + cmn_lane_ctrl0 |= ((cfg->data_lanes & DSI_DATA_LANE_1) ? BIT(1) : 0); + cmn_lane_ctrl0 |= ((cfg->data_lanes & DSI_DATA_LANE_2) ? BIT(2) : 0); + cmn_lane_ctrl0 |= ((cfg->data_lanes & DSI_DATA_LANE_3) ? BIT(3) : 0); + cmn_lane_ctrl0 |= BIT(4); + + return cmn_lane_ctrl0; +} + /** * cphy_enable() - Enable CPHY hardware * @phy: Pointer to DSI PHY hardware object. @@ -239,6 +259,7 @@ static void dsi_phy_hw_cphy_enable(struct dsi_phy_hw *phy, struct dsi_phy_cfg *c /* For C-PHY, no low power settings for lower clk rate */ u32 glbl_str_swi_cal_sel_ctrl = 0; u32 glbl_hstx_str_ctrl_0 = 0; + u32 cmn_lane_ctrl0 = 0; /* de-assert digital and pll power down */ data = BIT(6) | BIT(5); @@ -272,7 +293,8 @@ static void dsi_phy_hw_cphy_enable(struct dsi_phy_hw *phy, struct dsi_phy_cfg *c /* Remove power down from all blocks */ DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0x7f); - DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, 0x17); + cmn_lane_ctrl0 = dsi_phy_hw_calc_cmn_lane_ctrl0(cfg); + DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, cmn_lane_ctrl0); switch (cfg->pll_source) { case DSI_PLL_SOURCE_STANDALONE: @@ -322,6 +344,7 @@ static void dsi_phy_hw_dphy_enable(struct dsi_phy_hw *phy, struct dsi_phy_cfg *c u32 glbl_rescode_bot_ctrl = 0; bool split_link_enabled; u32 lanes_per_sublink; + u32 cmn_lane_ctrl0 = 0; /* Alter PHY configurations if data rate less than 1.5GHZ*/ if (cfg->bit_clk_rate_hz <= 1500000000) @@ -386,7 +409,8 @@ static void dsi_phy_hw_dphy_enable(struct dsi_phy_hw *phy, struct dsi_phy_cfg *c } else { /* Remove power down from all blocks */ DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0x7f); - DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, 0x1F); + cmn_lane_ctrl0 = dsi_phy_hw_calc_cmn_lane_ctrl0(cfg); + DSI_W32(phy, DSIPHY_CMN_LANE_CTRL0, cmn_lane_ctrl0); } /* Select full-rate mode */ @@ -687,7 +711,7 @@ void dsi_phy_hw_v5_0_dyn_refresh_config(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg, bool is_master) { u32 reg; - bool is_cphy = (cfg->phy_type == DSI_PHY_TYPE_CPHY) ? true : false; + u32 cmn_lane_ctrl0 = dsi_phy_hw_calc_cmn_lane_ctrl0(cfg); if (is_master) { DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL19, @@ -713,7 +737,7 @@ void dsi_phy_hw_v5_0_dyn_refresh_config(struct dsi_phy_hw *phy, cfg->timing.lane_v4[12], cfg->timing.lane_v4[13]); DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL26, DSIPHY_CMN_CTRL_0, DSIPHY_CMN_LANE_CTRL0, 0x7f, - is_cphy ? 0x17 : 0x1f); + cmn_lane_ctrl0); } else { reg = DSI_R32(phy, DSIPHY_CMN_CLK_CFG1); @@ -747,7 +771,7 @@ void dsi_phy_hw_v5_0_dyn_refresh_config(struct dsi_phy_hw *phy, cfg->timing.lane_v4[13], 0x7f); DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL9, DSIPHY_CMN_LANE_CTRL0, DSIPHY_CMN_CTRL_2, - is_cphy ? 0x17 : 0x1f, 0x40); + cmn_lane_ctrl0, 0x40); /* * fill with dummy register writes since controller will blindly * send these values to DSI PHY. @@ -755,7 +779,7 @@ void dsi_phy_hw_v5_0_dyn_refresh_config(struct dsi_phy_hw *phy, reg = DSI_DYN_REFRESH_PLL_CTRL11; while (reg <= DSI_DYN_REFRESH_PLL_CTRL29) { DSI_DYN_REF_REG_W(phy->dyn_pll_base, reg, DSIPHY_CMN_LANE_CTRL0, - DSIPHY_CMN_CTRL_0, is_cphy ? 0x17 : 0x1f, 0x7f); + DSIPHY_CMN_CTRL_0, cmn_lane_ctrl0, 0x7f); reg += 0x4; }