disp: msm: dsi: Only enable lanes required during phy enable
Currently we are enabling all the lanes irrespective of the lanes we are actually going to use. Add support to enable only those lanes that are required and thus save power. Change-Id: I9aae76eeaa05a79337d4e4b1f2e36ea9842bd580 Signed-off-by: Srihitha Tangudu <quic_tangudu@quicinc.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/of_device.h>
|
||||
@@ -803,7 +803,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
|
||||
@@ -1028,8 +1028,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;
|
||||
|
||||
|
@@ -70,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
|
||||
@@ -97,7 +96,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;
|
||||
|
@@ -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;
|
||||
|
@@ -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 <linux/math64.h>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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 <linux/math64.h>
|
||||
@@ -229,6 +229,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.
|
||||
@@ -242,6 +262,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);
|
||||
@@ -275,7 +296,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:
|
||||
@@ -325,6 +347,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)
|
||||
@@ -389,7 +412,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 */
|
||||
@@ -701,7 +725,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,
|
||||
@@ -727,7 +751,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);
|
||||
@@ -761,7 +785,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.
|
||||
@@ -769,7 +793,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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user