disp: msm: dsi: Add support for C-PHY dynamic clock switch

This change adds support for C-PHY dynamic clock switch feature.
Also add support for phy ver 4.0 C-PHY timing parameters calculation
to be used for clock switch.

Change-Id: I8292860fd8c93a7ba7988ec8c44ea9683f45b6e6
Signed-off-by: Ritesh Kumar <riteshk@codeaurora.org>
Signed-off-by: Harigovindan P <harigovi@codeaurora.org>
Signed-off-by: Steve Cohen <cohens@codeaurora.org>
This commit is contained in:
Harigovindan P
2020-05-06 15:31:55 +05:30
committed by Steve Cohen
parent d8ffbf3d39
commit 662ac3ab89
8 changed files with 366 additions and 74 deletions

View File

@@ -3306,11 +3306,15 @@ static int dsi_display_clocks_init(struct dsi_display *display)
const char *mux_byte = "mux_byte", *mux_pixel = "mux_pixel"; const char *mux_byte = "mux_byte", *mux_pixel = "mux_pixel";
const char *cphy_byte = "cphy_byte", *cphy_pixel = "cphy_pixel"; const char *cphy_byte = "cphy_byte", *cphy_pixel = "cphy_pixel";
const char *shadow_byte = "shadow_byte", *shadow_pixel = "shadow_pixel"; const char *shadow_byte = "shadow_byte", *shadow_pixel = "shadow_pixel";
const char *shadow_cphybyte = "shadow_cphybyte",
*shadow_cphypixel = "shadow_cphypixel";
struct clk *dsi_clk; struct clk *dsi_clk;
struct dsi_clk_link_set *src = &display->clock_info.src_clks; struct dsi_clk_link_set *src = &display->clock_info.src_clks;
struct dsi_clk_link_set *mux = &display->clock_info.mux_clks; struct dsi_clk_link_set *mux = &display->clock_info.mux_clks;
struct dsi_clk_link_set *cphy = &display->clock_info.cphy_clks; struct dsi_clk_link_set *cphy = &display->clock_info.cphy_clks;
struct dsi_clk_link_set *shadow = &display->clock_info.shadow_clks; struct dsi_clk_link_set *shadow = &display->clock_info.shadow_clks;
struct dsi_clk_link_set *shadow_cphy =
&display->clock_info.shadow_cphy_clks;
struct dsi_dyn_clk_caps *dyn_clk_caps = &(display->panel->dyn_clk_caps); struct dsi_dyn_clk_caps *dyn_clk_caps = &(display->panel->dyn_clk_caps);
char *dsi_clock_name; char *dsi_clock_name;
@@ -3369,6 +3373,12 @@ static int dsi_display_clocks_init(struct dsi_display *display)
if (dsi_display_check_prefix(shadow_pixel, if (dsi_display_check_prefix(shadow_pixel,
clk_name)) clk_name))
shadow->pixel_clk = NULL; shadow->pixel_clk = NULL;
if (dsi_display_check_prefix(shadow_cphybyte,
clk_name))
shadow_cphy->byte_clk = NULL;
if (dsi_display_check_prefix(shadow_cphypixel,
clk_name))
shadow_cphy->pixel_clk = NULL;
dyn_clk_caps->dyn_clk_support = false; dyn_clk_caps->dyn_clk_support = false;
} }
@@ -3413,6 +3423,16 @@ static int dsi_display_clocks_init(struct dsi_display *display)
shadow->pixel_clk = dsi_clk; shadow->pixel_clk = dsi_clk;
continue; continue;
} }
if (dsi_display_check_prefix(shadow_cphybyte, clk_name)) {
shadow_cphy->byte_clk = dsi_clk;
continue;
}
if (dsi_display_check_prefix(shadow_cphypixel, clk_name)) {
shadow_cphy->pixel_clk = dsi_clk;
continue;
}
} }
return 0; return 0;
@@ -4278,12 +4298,12 @@ static int dsi_display_update_dsi_bitrate(struct dsi_display *display,
byte_intf_clk_div = host_cfg->byte_intf_clk_div; byte_intf_clk_div = host_cfg->byte_intf_clk_div;
do_div(byte_intf_clk_rate, byte_intf_clk_div); do_div(byte_intf_clk_rate, byte_intf_clk_div);
} else { } else {
do_div(bit_rate, bits_per_symbol); bit_rate_per_lane = bit_clk_rate;
bit_rate *= num_of_symbols; pclk_rate *= bits_per_symbol;
bit_rate_per_lane = bit_rate; do_div(pclk_rate, num_of_symbols);
do_div(bit_rate_per_lane, num_of_lanes); byte_clk_rate = bit_clk_rate;
byte_clk_rate = bit_rate_per_lane; do_div(byte_clk_rate, num_of_symbols);
do_div(byte_clk_rate, 7);
/* For CPHY, byte_intf_clk is same as byte_clk */ /* For CPHY, byte_intf_clk is same as byte_clk */
byte_intf_clk_rate = byte_clk_rate; byte_intf_clk_rate = byte_clk_rate;
} }
@@ -4367,6 +4387,17 @@ static void _dsi_display_calc_pipe_delay(struct dsi_display *display,
delay->pll_delay = ((130 * esc_clk_rate_hz) / 1000000) * 2; delay->pll_delay = ((130 * esc_clk_rate_hz) / 1000000) * 2;
} }
/*
* dsi_display_is_type_cphy - check if panel type is cphy
* @display: Pointer to private display structure
* Returns: True if panel type is cphy
*/
static inline bool dsi_display_is_type_cphy(struct dsi_display *display)
{
return (display->panel->host_config.phy_type ==
DSI_PHY_TYPE_CPHY) ? true : false;
}
static int _dsi_display_dyn_update_clks(struct dsi_display *display, static int _dsi_display_dyn_update_clks(struct dsi_display *display,
struct link_clk_freq *bkp_freq) struct link_clk_freq *bkp_freq)
{ {
@@ -4374,17 +4405,26 @@ static int _dsi_display_dyn_update_clks(struct dsi_display *display,
u8 ctrl_version; u8 ctrl_version;
struct dsi_display_ctrl *m_ctrl, *ctrl; struct dsi_display_ctrl *m_ctrl, *ctrl;
struct dsi_dyn_clk_caps *dyn_clk_caps; struct dsi_dyn_clk_caps *dyn_clk_caps;
struct dsi_clk_link_set *parent_clk, *enable_clk;
m_ctrl = &display->ctrl[display->clk_master_idx]; m_ctrl = &display->ctrl[display->clk_master_idx];
dyn_clk_caps = &(display->panel->dyn_clk_caps); dyn_clk_caps = &(display->panel->dyn_clk_caps);
ctrl_version = m_ctrl->ctrl->version; ctrl_version = m_ctrl->ctrl->version;
dsi_clk_prepare_enable(&display->clock_info.src_clks); if (dsi_display_is_type_cphy(display)) {
enable_clk = &display->clock_info.cphy_clks;
parent_clk = &display->clock_info.shadow_cphy_clks;
} else {
enable_clk = &display->clock_info.src_clks;
parent_clk = &display->clock_info.shadow_clks;
}
rc = dsi_clk_update_parent(&display->clock_info.shadow_clks, dsi_clk_prepare_enable(enable_clk);
&display->clock_info.mux_clks);
rc = dsi_clk_update_parent(parent_clk,
&display->clock_info.mux_clks);
if (rc) { if (rc) {
DSI_ERR("failed update mux parent to shadow\n"); DSI_ERR("failed to update mux parent\n");
goto exit; goto exit;
} }
@@ -4443,12 +4483,12 @@ static int _dsi_display_dyn_update_clks(struct dsi_display *display,
} }
defer_dfps_wait: defer_dfps_wait:
rc = dsi_clk_update_parent(&display->clock_info.src_clks, rc = dsi_clk_update_parent(enable_clk,
&display->clock_info.mux_clks); &display->clock_info.mux_clks);
if (rc) if (rc)
DSI_ERR("could not switch back to src clks %d\n", rc); DSI_ERR("could not switch back to src clks %d\n", rc);
dsi_clk_disable_unprepare(&display->clock_info.src_clks); dsi_clk_disable_unprepare(enable_clk);
return rc; return rc;

View File

@@ -106,13 +106,15 @@ struct dsi_display_boot_param {
* struct dsi_display_clk_info - dsi display clock source information * struct dsi_display_clk_info - dsi display clock source information
* @src_clks: Source clocks for DSI display. * @src_clks: Source clocks for DSI display.
* @mux_clks: Mux clocks used for DFPS. * @mux_clks: Mux clocks used for DFPS.
* @shadow_clks: Used for DFPS. * @shadow_clks: Used for D-phy clock switch.
* @shadow_cphy_clks: Used for C-phy clock switch.
*/ */
struct dsi_display_clk_info { struct dsi_display_clk_info {
struct dsi_clk_link_set src_clks; struct dsi_clk_link_set src_clks;
struct dsi_clk_link_set mux_clks; struct dsi_clk_link_set mux_clks;
struct dsi_clk_link_set cphy_clks; struct dsi_clk_link_set cphy_clks;
struct dsi_clk_link_set shadow_clks; struct dsi_clk_link_set shadow_clks;
struct dsi_clk_link_set shadow_cphy_clks;
}; };
/** /**

View File

@@ -667,6 +667,8 @@ void dsi_phy_hw_v4_0_dyn_refresh_config(struct dsi_phy_hw *phy,
struct dsi_phy_cfg *cfg, bool is_master) struct dsi_phy_cfg *cfg, bool is_master)
{ {
u32 reg; u32 reg;
bool is_cphy = (cfg->phy_type == DSI_PHY_TYPE_CPHY) ?
true : false;
if (is_master) { if (is_master) {
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL19, DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL19,
@@ -692,7 +694,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]); cfg->timing.lane_v4[12], cfg->timing.lane_v4[13]);
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL26, DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL26,
DSIPHY_CMN_CTRL_0, DSIPHY_CMN_LANE_CTRL0, DSIPHY_CMN_CTRL_0, DSIPHY_CMN_LANE_CTRL0,
0x7f, 0x1f); 0x7f, is_cphy ? 0x17 : 0x1f);
} else { } else {
reg = DSI_R32(phy, DSIPHY_CMN_CLK_CFG1); reg = DSI_R32(phy, DSIPHY_CMN_CLK_CFG1);
@@ -727,7 +729,7 @@ void dsi_phy_hw_v4_0_dyn_refresh_config(struct dsi_phy_hw *phy,
cfg->timing.lane_v4[13], 0x7f); cfg->timing.lane_v4[13], 0x7f);
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL9, DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL9,
DSIPHY_CMN_LANE_CTRL0, DSIPHY_CMN_CTRL_2, DSIPHY_CMN_LANE_CTRL0, DSIPHY_CMN_CTRL_2,
0x1f, 0x40); is_cphy ? 0x17 : 0x1f, 0x40);
/* /*
* fill with dummy register writes since controller will blindly * fill with dummy register writes since controller will blindly
* send these values to DSI PHY. * send these values to DSI PHY.
@@ -736,7 +738,7 @@ void dsi_phy_hw_v4_0_dyn_refresh_config(struct dsi_phy_hw *phy,
while (reg <= DSI_DYN_REFRESH_PLL_CTRL29) { while (reg <= DSI_DYN_REFRESH_PLL_CTRL29) {
DSI_DYN_REF_REG_W(phy->dyn_pll_base, reg, DSI_DYN_REF_REG_W(phy->dyn_pll_base, reg,
DSIPHY_CMN_LANE_CTRL0, DSIPHY_CMN_CTRL_0, DSIPHY_CMN_LANE_CTRL0, DSIPHY_CMN_CTRL_0,
0x1f, 0x7f); is_cphy ? 0x17 : 0x1f, 0x7f);
reg += 0x4; reg += 0x4;
} }

View File

@@ -37,6 +37,12 @@ static int calc_clk_prepare(struct dsi_phy_hw *phy,
s64 intermediate; s64 intermediate;
s64 clk_prep_actual; s64 clk_prep_actual;
t->rec_min = DIV_ROUND_UP((t->mipi_min * clk_params->bitclk_mbps),
(8 * clk_params->tlpx_numer_ns));
t->rec_max = rounddown(
mult_frac((t->mipi_max * clk_params->bitclk_mbps),
1, (8 * clk_params->tlpx_numer_ns)), 1);
dividend = ((t->rec_max - t->rec_min) * dividend = ((t->rec_max - t->rec_min) *
clk_params->clk_prep_buf * multiplier); clk_params->clk_prep_buf * multiplier);
temp = roundup(div_s64(dividend, 100), multiplier); temp = roundup(div_s64(dividend, 100), multiplier);
@@ -622,6 +628,218 @@ error:
return rc; return rc;
} }
/**
* calc_cphy_clk_prepare - calculates cphy_clk_prepare parameter for cphy.
*/
static int calc_cphy_clk_prepare(struct dsi_phy_hw *phy,
struct phy_clk_params *clk_params,
struct phy_timing_desc *desc)
{
u64 multiplier = BIT(20);
struct timing_entry *t = &desc->clk_prepare;
int rc = 0;
u64 dividend, temp;
t->rec_min = DIV_ROUND_UP((t->mipi_min * clk_params->bitclk_mbps),
(7 * clk_params->tlpx_numer_ns));
t->rec_max = rounddown(
mult_frac((t->mipi_max * clk_params->bitclk_mbps),
1, (7 * clk_params->tlpx_numer_ns)), 1);
dividend = ((t->rec_max - t->rec_min) *
clk_params->clk_prep_buf * multiplier);
temp = roundup(div_s64(dividend, 100), multiplier);
temp += (t->rec_min * multiplier);
t->rec = div_s64(temp, multiplier);
rc = dsi_phy_cmn_validate_and_set(t, "cphy_clk_prepare");
DSI_DEBUG("CPHY_CLK_PREPARE: rec_min=%d, rec_max=%d, reg_val=%d\n",
t->rec_min, t->rec_max, t->reg_value);
return rc;
}
/**
* calc_cphy_clk_pre - calculates cphy_clk_pre parameter for cphy.
*/
static int calc_cphy_clk_pre(struct dsi_phy_hw *phy,
struct phy_clk_params *clk_params,
struct phy_timing_desc *desc)
{
u64 multiplier = BIT(20);
struct timing_entry *t = &desc->clk_pre;
int rc = 0;
u64 dividend, temp;
t->mipi_min = min(300 - 38 - mult_frac(7, clk_params->tlpx_numer_ns,
clk_params->bitclk_mbps),
mult_frac(448, clk_params->tlpx_numer_ns,
clk_params->bitclk_mbps));
t->mipi_max = mult_frac(448, clk_params->tlpx_numer_ns,
clk_params->bitclk_mbps);
t->rec_min = DIV_ROUND_UP((t->mipi_min * clk_params->bitclk_mbps),
(7 * clk_params->tlpx_numer_ns));
t->rec_max = rounddown(
mult_frac((t->mipi_max * clk_params->bitclk_mbps),
1, (7 * clk_params->tlpx_numer_ns)), 1);
dividend = ((t->rec_max - t->rec_min) * clk_params->clk_pre_buf
* multiplier);
temp = roundup(div_s64(dividend, 100), multiplier);
temp += (t->rec_min * multiplier);
t->rec = div_s64(temp, multiplier);
rc = dsi_phy_cmn_validate_and_set(t, "cphy_clk_pre");
DSI_DEBUG("CPHY_CLK_PRE: rec_min=%d, rec_max=%d, reg_val=%d\n",
t->rec_min, t->rec_max, t->reg_value);
return rc;
}
/**
* calc_cphy_clk_post - calculates cphy_clk_post parameter for cphy.
*/
static int calc_cphy_clk_post(struct dsi_phy_hw *phy,
struct phy_clk_params *clk_params,
struct phy_timing_desc *desc)
{
u64 multiplier = BIT(20);
struct timing_entry *t = &desc->clk_post;
int rc = 0;
u64 dividend, temp;
t->mipi_min = mult_frac(7, clk_params->tlpx_numer_ns,
clk_params->bitclk_mbps);
t->mipi_max = mult_frac(224, clk_params->tlpx_numer_ns,
clk_params->bitclk_mbps);
t->rec_min = DIV_ROUND_UP((t->mipi_min * clk_params->bitclk_mbps),
(7 * clk_params->tlpx_numer_ns));
t->rec_max = rounddown(
mult_frac((t->mipi_max * clk_params->bitclk_mbps),
1, (7 * clk_params->tlpx_numer_ns)), 1);
dividend = ((t->rec_max - t->rec_min) * clk_params->clk_post_buf
* multiplier);
temp = roundup(div_s64(dividend, 100), multiplier);
temp += (t->rec_min * multiplier);
t->rec = div_s64(temp, multiplier);
rc = dsi_phy_cmn_validate_and_set(t, "cphy_clk_post");
DSI_DEBUG("CPHY_CLK_POST: rec_min=%d, rec_max=%d, reg_val=%d\n",
t->rec_min, t->rec_max, t->reg_value);
return rc;
}
/**
* calc_cphy_hs_rqst - calculates cphy_hs_rqst parameter for cphy.
*/
static int calc_cphy_hs_rqst(struct dsi_phy_hw *phy,
struct phy_clk_params *clk_params,
struct phy_timing_desc *desc)
{
u64 multiplier = BIT(20);
struct timing_entry *t = &desc->hs_rqst;
int rc = 0;
u64 dividend, temp;
t->rec_min = DIV_ROUND_UP(
((t->mipi_min * clk_params->bitclk_mbps) -
(7 * clk_params->tlpx_numer_ns)),
(7 * clk_params->tlpx_numer_ns));
dividend = ((t->rec_max - t->rec_min) *
clk_params->hs_rqst_buf * multiplier);
temp = roundup(div_s64(dividend, 100), multiplier);
temp += t->rec_min * multiplier;
t->rec = div_s64(temp, multiplier);
rc = dsi_phy_cmn_validate_and_set(t, "cphy_hs_rqst");
DSI_DEBUG("CPHY_HS_RQST: rec_min=%d, rec_max=%d, reg_val=%d\n",
t->rec_min, t->rec_max, t->reg_value);
return rc;
}
/**
* calc_cphy_hs_exit - calculates cphy_hs_exit parameter for cphy.
*/
static int calc_cphy_hs_exit(struct dsi_phy_hw *phy,
struct phy_clk_params *clk_params,
struct phy_timing_desc *desc)
{
int rc = 0;
u64 multiplier = BIT(20);
u64 dividend, temp;
struct timing_entry *t = &desc->hs_exit;
t->rec_min = (DIV_ROUND_UP(
(t->mipi_min * clk_params->bitclk_mbps),
(7 * clk_params->tlpx_numer_ns)) - 1);
dividend = ((t->rec_max - t->rec_min) *
clk_params->hs_exit_buf * multiplier);
temp = roundup(div_s64(dividend, 100), multiplier);
temp += t->rec_min * multiplier;
t->rec = div_s64(temp, multiplier);
rc = dsi_phy_cmn_validate_and_set(t, "cphy_hs_exit");
DSI_DEBUG("CPHY_HS_EXIT: rec_min=%d, rec_max=%d, reg_val=%d\n",
t->rec_min, t->rec_max, t->reg_value);
return rc;
}
/**
* dsi_phy_calc_cphy_timing_params - calculates cphy timing parameters
* for a given bit clock
*/
static int dsi_phy_cmn_calc_cphy_timing_params(struct dsi_phy_hw *phy,
struct phy_clk_params *clk_params, struct phy_timing_desc *desc)
{
int rc = 0;
rc = calc_cphy_clk_prepare(phy, clk_params, desc);
if (rc) {
DSI_ERR("clk_prepare calculations failed, rc=%d\n", rc);
goto error;
}
rc = calc_cphy_clk_pre(phy, clk_params, desc);
if (rc) {
DSI_ERR("clk_pre calculations failed, rc=%d\n", rc);
goto error;
}
rc = calc_cphy_clk_post(phy, clk_params, desc);
if (rc) {
DSI_ERR("clk_zero calculations failed, rc=%d\n", rc);
goto error;
}
rc = calc_cphy_hs_rqst(phy, clk_params, desc);
if (rc) {
DSI_ERR("hs_rqst calculations failed, rc=%d\n", rc);
goto error;
}
rc = calc_cphy_hs_exit(phy, clk_params, desc);
if (rc) {
DSI_ERR("hs_exit calculations failed, rc=%d\n", rc);
goto error;
}
error:
return rc;
}
/** /**
* calculate_timing_params() - calculates timing parameters. * calculate_timing_params() - calculates timing parameters.
* @phy: Pointer to DSI PHY hardware object. * @phy: Pointer to DSI PHY hardware object.
@@ -648,6 +866,7 @@ int dsi_phy_hw_calculate_timing_params(struct dsi_phy_hw *phy,
u32 const hs_exit_spec_min = 100; u32 const hs_exit_spec_min = 100;
u32 const hs_exit_reco_max = 255; u32 const hs_exit_reco_max = 255;
u32 const hs_rqst_spec_min = 50; u32 const hs_rqst_spec_min = 50;
u32 const hs_rqst_reco_max = 255;
/* local vars */ /* local vars */
int rc = 0; int rc = 0;
@@ -660,6 +879,8 @@ int dsi_phy_hw_calculate_timing_params(struct dsi_phy_hw *phy,
struct phy_clk_params clk_params = {0}; struct phy_clk_params clk_params = {0};
struct phy_timing_ops *ops = phy->ops.timing_ops; struct phy_timing_ops *ops = phy->ops.timing_ops;
u32 phy_type = host->phy_type;
memset(&desc, 0x0, sizeof(desc)); memset(&desc, 0x0, sizeof(desc));
h_total = dsi_h_total_dce(mode); h_total = dsi_h_total_dce(mode);
v_total = DSI_V_TOTAL(mode); v_total = DSI_V_TOTAL(mode);
@@ -680,8 +901,11 @@ int dsi_phy_hw_calculate_timing_params(struct dsi_phy_hw *phy,
if (use_mode_bit_clk) if (use_mode_bit_clk)
x = mode->clk_rate_hz; x = mode->clk_rate_hz;
else else {
x = mult_frac(v_total * h_total, inter_num, num_of_lanes); x = mult_frac(v_total * h_total, inter_num, num_of_lanes);
if (phy_type == DSI_PHY_TYPE_CPHY)
x = mult_frac(x, 7, 16);
}
y = rounddown(x, 1); y = rounddown(x, 1);
clk_params.bitclk_mbps = rounddown(DIV_ROUND_UP_ULL(y, 1000000), 1); clk_params.bitclk_mbps = rounddown(DIV_ROUND_UP_ULL(y, 1000000), 1);
@@ -699,35 +923,31 @@ int dsi_phy_hw_calculate_timing_params(struct dsi_phy_hw *phy,
desc.hs_exit.rec_max = hs_exit_reco_max; desc.hs_exit.rec_max = hs_exit_reco_max;
desc.hs_rqst.mipi_min = hs_rqst_spec_min; desc.hs_rqst.mipi_min = hs_rqst_spec_min;
desc.hs_rqst_clk.mipi_min = hs_rqst_spec_min; desc.hs_rqst_clk.mipi_min = hs_rqst_spec_min;
desc.hs_rqst.rec_max = hs_rqst_reco_max;
if (ops->get_default_phy_params) { if (ops->get_default_phy_params) {
ops->get_default_phy_params(&clk_params); ops->get_default_phy_params(&clk_params, phy_type);
} else { } else {
rc = -EINVAL; rc = -EINVAL;
goto error; goto error;
} }
desc.clk_prepare.rec_min = DIV_ROUND_UP(
(desc.clk_prepare.mipi_min * clk_params.bitclk_mbps),
(8 * clk_params.tlpx_numer_ns)
);
desc.clk_prepare.rec_max = rounddown(
mult_frac((desc.clk_prepare.mipi_max * clk_params.bitclk_mbps),
1, (8 * clk_params.tlpx_numer_ns)),
1);
DSI_PHY_DBG(phy, "BIT CLOCK = %d, tlpx_numer_ns=%d, treot_ns=%d\n", DSI_PHY_DBG(phy, "BIT CLOCK = %d, tlpx_numer_ns=%d, treot_ns=%d\n",
clk_params.bitclk_mbps, clk_params.tlpx_numer_ns, clk_params.bitclk_mbps, clk_params.tlpx_numer_ns,
clk_params.treot_ns); clk_params.treot_ns);
rc = dsi_phy_cmn_calc_timing_params(phy, &clk_params, &desc);
if (phy_type == DSI_PHY_TYPE_CPHY)
rc = dsi_phy_cmn_calc_cphy_timing_params(phy, &clk_params,
&desc);
else
rc = dsi_phy_cmn_calc_timing_params(phy, &clk_params, &desc);
if (rc) { if (rc) {
DSI_PHY_ERR(phy, "Timing calc failed, rc=%d\n", rc); DSI_PHY_ERR(phy, "Timing calc failed, rc=%d\n", rc);
goto error; goto error;
} }
if (ops->update_timing_params) { if (ops->update_timing_params) {
ops->update_timing_params(timing, &desc); ops->update_timing_params(timing, &desc, phy_type);
} else { } else {
rc = -EINVAL; rc = -EINVAL;
goto error; goto error;

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
*/ */
#ifndef _DSI_PHY_TIMING_CALC_H_ #ifndef _DSI_PHY_TIMING_CALC_H_
@@ -81,7 +81,8 @@ struct phy_clk_params {
* Various Ops needed for auto-calculation of DSI PHY timing parameters. * Various Ops needed for auto-calculation of DSI PHY timing parameters.
*/ */
struct phy_timing_ops { struct phy_timing_ops {
void (*get_default_phy_params)(struct phy_clk_params *params); void (*get_default_phy_params)(struct phy_clk_params *params,
u32 phy_type);
int32_t (*calc_clk_zero)(s64 rec_temp1, s64 mult); int32_t (*calc_clk_zero)(s64 rec_temp1, s64 mult);
@@ -96,14 +97,15 @@ struct phy_timing_ops {
struct phy_timing_desc *desc); struct phy_timing_desc *desc);
void (*update_timing_params)(struct dsi_phy_per_lane_cfgs *timing, void (*update_timing_params)(struct dsi_phy_per_lane_cfgs *timing,
struct phy_timing_desc *desc); struct phy_timing_desc *desc, u32 phy_type);
}; };
#define roundup64(x, y) \ #define roundup64(x, y) \
({ u64 _tmp = (x)+(y)-1; do_div(_tmp, y); _tmp * y; }) ({ u64 _tmp = (x)+(y)-1; do_div(_tmp, y); _tmp * y; })
/* DSI PHY timing functions for 14nm */ /* DSI PHY timing functions for 14nm */
void dsi_phy_hw_v2_0_get_default_phy_params(struct phy_clk_params *params); void dsi_phy_hw_v2_0_get_default_phy_params(struct phy_clk_params *params,
u32 phy_type);
int32_t dsi_phy_hw_v2_0_calc_clk_zero(s64 rec_temp1, s64 mult); int32_t dsi_phy_hw_v2_0_calc_clk_zero(s64 rec_temp1, s64 mult);
@@ -118,10 +120,11 @@ void dsi_phy_hw_v2_0_calc_hs_trail(struct phy_clk_params *clk_params,
struct phy_timing_desc *desc); struct phy_timing_desc *desc);
void dsi_phy_hw_v2_0_update_timing_params(struct dsi_phy_per_lane_cfgs *timing, void dsi_phy_hw_v2_0_update_timing_params(struct dsi_phy_per_lane_cfgs *timing,
struct phy_timing_desc *desc); struct phy_timing_desc *desc, u32 phy_type);
/* DSI PHY timing functions for 10nm */ /* DSI PHY timing functions for 10nm */
void dsi_phy_hw_v3_0_get_default_phy_params(struct phy_clk_params *params); void dsi_phy_hw_v3_0_get_default_phy_params(struct phy_clk_params *params,
u32 phy_type);
int32_t dsi_phy_hw_v3_0_calc_clk_zero(s64 rec_temp1, s64 mult); int32_t dsi_phy_hw_v3_0_calc_clk_zero(s64 rec_temp1, s64 mult);
@@ -136,10 +139,11 @@ void dsi_phy_hw_v3_0_calc_hs_trail(struct phy_clk_params *clk_params,
struct phy_timing_desc *desc); struct phy_timing_desc *desc);
void dsi_phy_hw_v3_0_update_timing_params(struct dsi_phy_per_lane_cfgs *timing, void dsi_phy_hw_v3_0_update_timing_params(struct dsi_phy_per_lane_cfgs *timing,
struct phy_timing_desc *desc); struct phy_timing_desc *desc, u32 phy_type);
/* DSI PHY timing functions for 7nm */ /* DSI PHY timing functions for 7nm */
void dsi_phy_hw_v4_0_get_default_phy_params(struct phy_clk_params *params); void dsi_phy_hw_v4_0_get_default_phy_params(struct phy_clk_params *params,
u32 phy_type);
int32_t dsi_phy_hw_v4_0_calc_clk_zero(s64 rec_temp1, s64 mult); int32_t dsi_phy_hw_v4_0_calc_clk_zero(s64 rec_temp1, s64 mult);
@@ -154,6 +158,6 @@ void dsi_phy_hw_v4_0_calc_hs_trail(struct phy_clk_params *clk_params,
struct phy_timing_desc *desc); struct phy_timing_desc *desc);
void dsi_phy_hw_v4_0_update_timing_params(struct dsi_phy_per_lane_cfgs *timing, void dsi_phy_hw_v4_0_update_timing_params(struct dsi_phy_per_lane_cfgs *timing,
struct phy_timing_desc *desc); struct phy_timing_desc *desc, u32 phy_type);
#endif /* _DSI_PHY_TIMING_CALC_H_ */ #endif /* _DSI_PHY_TIMING_CALC_H_ */

View File

@@ -1,11 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
*/ */
#include "dsi_phy_timing_calc.h" #include "dsi_phy_timing_calc.h"
void dsi_phy_hw_v2_0_get_default_phy_params(struct phy_clk_params *params) void dsi_phy_hw_v2_0_get_default_phy_params(struct phy_clk_params *params,
u32 phy_type)
{ {
params->clk_prep_buf = 50; params->clk_prep_buf = 50;
params->clk_zero_buf = 2; params->clk_zero_buf = 2;
@@ -77,7 +78,7 @@ void dsi_phy_hw_v2_0_calc_hs_trail(struct phy_clk_params *clk_params,
void dsi_phy_hw_v2_0_update_timing_params( void dsi_phy_hw_v2_0_update_timing_params(
struct dsi_phy_per_lane_cfgs *timing, struct dsi_phy_per_lane_cfgs *timing,
struct phy_timing_desc *desc) struct phy_timing_desc *desc, u32 phy_type)
{ {
int i = 0; int i = 0;

View File

@@ -1,12 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
*/ */
#include "dsi_phy_timing_calc.h" #include "dsi_phy_timing_calc.h"
void dsi_phy_hw_v3_0_get_default_phy_params( void dsi_phy_hw_v3_0_get_default_phy_params(
struct phy_clk_params *params) struct phy_clk_params *params, u32 phy_type)
{ {
params->clk_prep_buf = 0; params->clk_prep_buf = 0;
params->clk_zero_buf = 0; params->clk_zero_buf = 0;
@@ -72,7 +72,7 @@ void dsi_phy_hw_v3_0_calc_hs_trail(struct phy_clk_params *clk_params,
void dsi_phy_hw_v3_0_update_timing_params( void dsi_phy_hw_v3_0_update_timing_params(
struct dsi_phy_per_lane_cfgs *timing, struct dsi_phy_per_lane_cfgs *timing,
struct phy_timing_desc *desc) struct phy_timing_desc *desc, u32 phy_type)
{ {
timing->lane_v3[0] = 0x00; timing->lane_v3[0] = 0x00;
timing->lane_v3[1] = desc->clk_zero.reg_value; timing->lane_v3[1] = desc->clk_zero.reg_value;

View File

@@ -1,24 +1,32 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
*/ */
#include "dsi_phy_timing_calc.h" #include "dsi_phy_timing_calc.h"
void dsi_phy_hw_v4_0_get_default_phy_params( void dsi_phy_hw_v4_0_get_default_phy_params(
struct phy_clk_params *params) struct phy_clk_params *params, u32 phy_type)
{ {
params->clk_prep_buf = 50; if (phy_type == DSI_PHY_TYPE_CPHY) {
params->clk_zero_buf = 2; params->clk_prep_buf = 50;
params->clk_trail_buf = 30; params->clk_pre_buf = 20;
params->hs_prep_buf = 50; params->clk_post_buf = 80;
params->hs_zero_buf = 10; params->hs_rqst_buf = 1;
params->hs_trail_buf = 30; params->hs_exit_buf = 10;
params->hs_rqst_buf = 0; } else {
params->hs_exit_buf = 10; params->clk_prep_buf = 50;
/* 1.25 is used in code for precision */ params->clk_zero_buf = 2;
params->clk_pre_buf = 1; params->clk_trail_buf = 30;
params->clk_post_buf = 5; params->hs_prep_buf = 50;
params->hs_zero_buf = 10;
params->hs_trail_buf = 30;
params->hs_rqst_buf = 0;
params->hs_exit_buf = 10;
/* 1.25 is used in code for precision */
params->clk_pre_buf = 1;
params->clk_post_buf = 5;
}
} }
int32_t dsi_phy_hw_v4_0_calc_clk_zero(s64 rec_temp1, s64 mult) int32_t dsi_phy_hw_v4_0_calc_clk_zero(s64 rec_temp1, s64 mult)
@@ -75,22 +83,37 @@ void dsi_phy_hw_v4_0_calc_hs_trail(struct phy_clk_params *clk_params,
void dsi_phy_hw_v4_0_update_timing_params( void dsi_phy_hw_v4_0_update_timing_params(
struct dsi_phy_per_lane_cfgs *timing, struct dsi_phy_per_lane_cfgs *timing,
struct phy_timing_desc *desc) struct phy_timing_desc *desc, u32 phy_type)
{ {
timing->lane_v4[0] = 0x00; if (phy_type == DSI_PHY_TYPE_CPHY) {
timing->lane_v4[1] = desc->clk_zero.reg_value; timing->lane_v4[0] = 0x00;
timing->lane_v4[2] = desc->clk_prepare.reg_value; timing->lane_v4[1] = 0x00;
timing->lane_v4[3] = desc->clk_trail.reg_value; timing->lane_v4[2] = 0x00;
timing->lane_v4[4] = desc->hs_exit.reg_value; timing->lane_v4[3] = 0x00;
timing->lane_v4[5] = desc->hs_zero.reg_value; timing->lane_v4[4] = desc->hs_exit.reg_value;
timing->lane_v4[6] = desc->hs_prepare.reg_value; timing->lane_v4[5] = desc->clk_pre.reg_value;
timing->lane_v4[7] = desc->hs_trail.reg_value; timing->lane_v4[6] = desc->clk_prepare.reg_value;
timing->lane_v4[8] = desc->hs_rqst.reg_value; timing->lane_v4[7] = desc->clk_post.reg_value;
timing->lane_v4[9] = 0x02; timing->lane_v4[8] = desc->hs_rqst.reg_value;
timing->lane_v4[10] = 0x04; timing->lane_v4[9] = 0x02;
timing->lane_v4[11] = 0x00; timing->lane_v4[10] = 0x04;
timing->lane_v4[12] = desc->clk_pre.reg_value; timing->lane_v4[11] = 0x00;
timing->lane_v4[13] = desc->clk_post.reg_value; } else {
timing->lane_v4[0] = 0x00;
timing->lane_v4[1] = desc->clk_zero.reg_value;
timing->lane_v4[2] = desc->clk_prepare.reg_value;
timing->lane_v4[3] = desc->clk_trail.reg_value;
timing->lane_v4[4] = desc->hs_exit.reg_value;
timing->lane_v4[5] = desc->hs_zero.reg_value;
timing->lane_v4[6] = desc->hs_prepare.reg_value;
timing->lane_v4[7] = desc->hs_trail.reg_value;
timing->lane_v4[8] = desc->hs_rqst.reg_value;
timing->lane_v4[9] = 0x02;
timing->lane_v4[10] = 0x04;
timing->lane_v4[11] = 0x00;
timing->lane_v4[12] = desc->clk_pre.reg_value;
timing->lane_v4[13] = desc->clk_post.reg_value;
}
DSI_DEBUG("[%d %d %d %d]\n", timing->lane_v4[0], DSI_DEBUG("[%d %d %d %d]\n", timing->lane_v4[0],
timing->lane_v4[1], timing->lane_v4[2], timing->lane_v4[3]); timing->lane_v4[1], timing->lane_v4[2], timing->lane_v4[3]);