Commit 858c595a authored by Dmitry Baryshkov's avatar Dmitry Baryshkov Committed by Rob Clark

drm/msm/dsi: add continuous clock support for 7nm PHY

Unlike previous generations, 7nm PHYs are required to collaborate with
the host for continuos clock mode. Add changes neccessary to enable
continuous clock mode in the 7nm DSI PHYs.
Signed-off-by: default avatarDmitry Baryshkov <dmitry.baryshkov@linaro.org>
Link: https://lore.kernel.org/r/20210805170817.3337665-1-dmitry.baryshkov@linaro.org
[Fix merge conflict, and $description typo]
Signed-off-by: default avatarRob Clark <robdclark@chromium.org>
parent 26ae419c
...@@ -109,7 +109,7 @@ int msm_dsi_host_enable(struct mipi_dsi_host *host); ...@@ -109,7 +109,7 @@ int msm_dsi_host_enable(struct mipi_dsi_host *host);
int msm_dsi_host_disable(struct mipi_dsi_host *host); int msm_dsi_host_disable(struct mipi_dsi_host *host);
int msm_dsi_host_power_on(struct mipi_dsi_host *host, int msm_dsi_host_power_on(struct mipi_dsi_host *host,
struct msm_dsi_phy_shared_timings *phy_shared_timings, struct msm_dsi_phy_shared_timings *phy_shared_timings,
bool is_bonded_dsi); bool is_bonded_dsi, struct msm_dsi_phy *phy);
int msm_dsi_host_power_off(struct mipi_dsi_host *host); int msm_dsi_host_power_off(struct mipi_dsi_host *host);
int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host, int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host,
const struct drm_display_mode *mode); const struct drm_display_mode *mode);
...@@ -176,6 +176,7 @@ int msm_dsi_phy_get_clk_provider(struct msm_dsi_phy *phy, ...@@ -176,6 +176,7 @@ int msm_dsi_phy_get_clk_provider(struct msm_dsi_phy *phy,
void msm_dsi_phy_pll_save_state(struct msm_dsi_phy *phy); void msm_dsi_phy_pll_save_state(struct msm_dsi_phy *phy);
int msm_dsi_phy_pll_restore_state(struct msm_dsi_phy *phy); int msm_dsi_phy_pll_restore_state(struct msm_dsi_phy *phy);
void msm_dsi_phy_snapshot(struct msm_disp_state *disp_state, struct msm_dsi_phy *phy); void msm_dsi_phy_snapshot(struct msm_disp_state *disp_state, struct msm_dsi_phy *phy);
bool msm_dsi_phy_set_continuous_clock(struct msm_dsi_phy *phy, bool enable);
#endif /* __DSI_CONNECTOR_H__ */ #endif /* __DSI_CONNECTOR_H__ */
...@@ -544,6 +544,7 @@ static inline uint32_t DSI_CLKOUT_TIMING_CTRL_T_CLK_POST(uint32_t val) ...@@ -544,6 +544,7 @@ static inline uint32_t DSI_CLKOUT_TIMING_CTRL_T_CLK_POST(uint32_t val)
#define DSI_LANE_STATUS_DLN0_DIRECTION 0x00010000 #define DSI_LANE_STATUS_DLN0_DIRECTION 0x00010000
#define REG_DSI_LANE_CTRL 0x000000a8 #define REG_DSI_LANE_CTRL 0x000000a8
#define DSI_LANE_CTRL_HS_REQ_SEL_PHY 0x01000000
#define DSI_LANE_CTRL_CLKLN_HS_FORCE_REQUEST 0x10000000 #define DSI_LANE_CTRL_CLKLN_HS_FORCE_REQUEST 0x10000000
#define REG_DSI_LANE_SWAP_CTRL 0x000000ac #define REG_DSI_LANE_SWAP_CTRL 0x000000ac
......
...@@ -832,7 +832,7 @@ static inline enum dsi_cmd_dst_format dsi_get_cmd_fmt( ...@@ -832,7 +832,7 @@ static inline enum dsi_cmd_dst_format dsi_get_cmd_fmt(
} }
static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable, static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,
struct msm_dsi_phy_shared_timings *phy_shared_timings) struct msm_dsi_phy_shared_timings *phy_shared_timings, struct msm_dsi_phy *phy)
{ {
u32 flags = msm_host->mode_flags; u32 flags = msm_host->mode_flags;
enum mipi_dsi_pixel_format mipi_fmt = msm_host->format; enum mipi_dsi_pixel_format mipi_fmt = msm_host->format;
...@@ -927,6 +927,10 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable, ...@@ -927,6 +927,10 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,
if (!(flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)) { if (!(flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)) {
lane_ctrl = dsi_read(msm_host, REG_DSI_LANE_CTRL); lane_ctrl = dsi_read(msm_host, REG_DSI_LANE_CTRL);
if (msm_dsi_phy_set_continuous_clock(phy, enable))
lane_ctrl &= ~DSI_LANE_CTRL_HS_REQ_SEL_PHY;
dsi_write(msm_host, REG_DSI_LANE_CTRL, dsi_write(msm_host, REG_DSI_LANE_CTRL,
lane_ctrl | DSI_LANE_CTRL_CLKLN_HS_FORCE_REQUEST); lane_ctrl | DSI_LANE_CTRL_CLKLN_HS_FORCE_REQUEST);
} }
...@@ -2364,7 +2368,7 @@ static void msm_dsi_sfpb_config(struct msm_dsi_host *msm_host, bool enable) ...@@ -2364,7 +2368,7 @@ static void msm_dsi_sfpb_config(struct msm_dsi_host *msm_host, bool enable)
int msm_dsi_host_power_on(struct mipi_dsi_host *host, int msm_dsi_host_power_on(struct mipi_dsi_host *host,
struct msm_dsi_phy_shared_timings *phy_shared_timings, struct msm_dsi_phy_shared_timings *phy_shared_timings,
bool is_bonded_dsi) bool is_bonded_dsi, struct msm_dsi_phy *phy)
{ {
struct msm_dsi_host *msm_host = to_msm_dsi_host(host); struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
...@@ -2404,7 +2408,7 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host, ...@@ -2404,7 +2408,7 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host,
dsi_timing_setup(msm_host, is_bonded_dsi); dsi_timing_setup(msm_host, is_bonded_dsi);
dsi_sw_reset(msm_host); dsi_sw_reset(msm_host);
dsi_ctrl_config(msm_host, true, phy_shared_timings); dsi_ctrl_config(msm_host, true, phy_shared_timings, phy);
if (msm_host->disp_en_gpio) if (msm_host->disp_en_gpio)
gpiod_set_value(msm_host->disp_en_gpio, 1); gpiod_set_value(msm_host->disp_en_gpio, 1);
...@@ -2435,7 +2439,7 @@ int msm_dsi_host_power_off(struct mipi_dsi_host *host) ...@@ -2435,7 +2439,7 @@ int msm_dsi_host_power_off(struct mipi_dsi_host *host)
goto unlock_ret; goto unlock_ret;
} }
dsi_ctrl_config(msm_host, false, NULL); dsi_ctrl_config(msm_host, false, NULL, NULL);
if (msm_host->disp_en_gpio) if (msm_host->disp_en_gpio)
gpiod_set_value(msm_host->disp_en_gpio, 0); gpiod_set_value(msm_host->disp_en_gpio, 0);
......
...@@ -361,7 +361,7 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) ...@@ -361,7 +361,7 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
if (ret) if (ret)
goto phy_en_fail; goto phy_en_fail;
ret = msm_dsi_host_power_on(host, &phy_shared_timings[id], is_bonded_dsi); ret = msm_dsi_host_power_on(host, &phy_shared_timings[id], is_bonded_dsi, msm_dsi->phy);
if (ret) { if (ret) {
pr_err("%s: power on host %d failed, %d\n", __func__, id, ret); pr_err("%s: power on host %d failed, %d\n", __func__, id, ret);
goto host_on_fail; goto host_on_fail;
...@@ -369,7 +369,7 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) ...@@ -369,7 +369,7 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
if (is_bonded_dsi && msm_dsi1) { if (is_bonded_dsi && msm_dsi1) {
ret = msm_dsi_host_power_on(msm_dsi1->host, ret = msm_dsi_host_power_on(msm_dsi1->host,
&phy_shared_timings[DSI_1], is_bonded_dsi); &phy_shared_timings[DSI_1], is_bonded_dsi, msm_dsi1->phy);
if (ret) { if (ret) {
pr_err("%s: power on host1 failed, %d\n", pr_err("%s: power on host1 failed, %d\n",
__func__, ret); __func__, ret);
......
...@@ -881,6 +881,15 @@ void msm_dsi_phy_set_usecase(struct msm_dsi_phy *phy, ...@@ -881,6 +881,15 @@ void msm_dsi_phy_set_usecase(struct msm_dsi_phy *phy,
phy->usecase = uc; phy->usecase = uc;
} }
/* Returns true if we have to clear DSI_LANE_CTRL.HS_REQ_SEL_PHY */
bool msm_dsi_phy_set_continuous_clock(struct msm_dsi_phy *phy, bool enable)
{
if (!phy || !phy->cfg->ops.set_continuous_clock)
return false;
return phy->cfg->ops.set_continuous_clock(phy, enable);
}
int msm_dsi_phy_get_clk_provider(struct msm_dsi_phy *phy, int msm_dsi_phy_get_clk_provider(struct msm_dsi_phy *phy,
struct clk **byte_clk_provider, struct clk **pixel_clk_provider) struct clk **byte_clk_provider, struct clk **pixel_clk_provider)
{ {
......
...@@ -24,6 +24,7 @@ struct msm_dsi_phy_ops { ...@@ -24,6 +24,7 @@ struct msm_dsi_phy_ops {
void (*disable)(struct msm_dsi_phy *phy); void (*disable)(struct msm_dsi_phy *phy);
void (*save_pll_state)(struct msm_dsi_phy *phy); void (*save_pll_state)(struct msm_dsi_phy *phy);
int (*restore_pll_state)(struct msm_dsi_phy *phy); int (*restore_pll_state)(struct msm_dsi_phy *phy);
bool (*set_continuous_clock)(struct msm_dsi_phy *phy, bool enable);
}; };
struct msm_dsi_phy_cfg { struct msm_dsi_phy_cfg {
......
...@@ -991,6 +991,21 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, ...@@ -991,6 +991,21 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
return 0; return 0;
} }
static bool dsi_7nm_set_continuous_clock(struct msm_dsi_phy *phy, bool enable)
{
void __iomem *base = phy->base;
u32 data;
data = dsi_phy_read(base + REG_DSI_7nm_PHY_CMN_LANE_CTRL1);
if (enable)
data |= BIT(5) | BIT(6);
else
data &= ~(BIT(5) | BIT(6));
dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CTRL1, data);
return enable;
}
static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy) static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy)
{ {
void __iomem *base = phy->base; void __iomem *base = phy->base;
...@@ -1031,6 +1046,7 @@ const struct msm_dsi_phy_cfg dsi_phy_7nm_cfgs = { ...@@ -1031,6 +1046,7 @@ const struct msm_dsi_phy_cfg dsi_phy_7nm_cfgs = {
.pll_init = dsi_pll_7nm_init, .pll_init = dsi_pll_7nm_init,
.save_pll_state = dsi_7nm_pll_save_state, .save_pll_state = dsi_7nm_pll_save_state,
.restore_pll_state = dsi_7nm_pll_restore_state, .restore_pll_state = dsi_7nm_pll_restore_state,
.set_continuous_clock = dsi_7nm_set_continuous_clock,
}, },
.min_pll_rate = 600000000UL, .min_pll_rate = 600000000UL,
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
...@@ -1057,6 +1073,7 @@ const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs = { ...@@ -1057,6 +1073,7 @@ const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs = {
.pll_init = dsi_pll_7nm_init, .pll_init = dsi_pll_7nm_init,
.save_pll_state = dsi_7nm_pll_save_state, .save_pll_state = dsi_7nm_pll_save_state,
.restore_pll_state = dsi_7nm_pll_restore_state, .restore_pll_state = dsi_7nm_pll_restore_state,
.set_continuous_clock = dsi_7nm_set_continuous_clock,
}, },
.min_pll_rate = 1000000000UL, .min_pll_rate = 1000000000UL,
.max_pll_rate = 3500000000UL, .max_pll_rate = 3500000000UL,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment