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:

committed by
Steve Cohen

parent
d8ffbf3d39
commit
662ac3ab89
@@ -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 *cphy_byte = "cphy_byte", *cphy_pixel = "cphy_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 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 *cphy = &display->clock_info.cphy_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);
|
||||
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,
|
||||
clk_name))
|
||||
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;
|
||||
}
|
||||
@@ -3413,6 +3423,16 @@ static int dsi_display_clocks_init(struct dsi_display *display)
|
||||
shadow->pixel_clk = dsi_clk;
|
||||
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;
|
||||
@@ -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;
|
||||
do_div(byte_intf_clk_rate, byte_intf_clk_div);
|
||||
} else {
|
||||
do_div(bit_rate, bits_per_symbol);
|
||||
bit_rate *= num_of_symbols;
|
||||
bit_rate_per_lane = bit_rate;
|
||||
do_div(bit_rate_per_lane, num_of_lanes);
|
||||
byte_clk_rate = bit_rate_per_lane;
|
||||
do_div(byte_clk_rate, 7);
|
||||
bit_rate_per_lane = bit_clk_rate;
|
||||
pclk_rate *= bits_per_symbol;
|
||||
do_div(pclk_rate, num_of_symbols);
|
||||
byte_clk_rate = bit_clk_rate;
|
||||
do_div(byte_clk_rate, num_of_symbols);
|
||||
|
||||
/* For CPHY, byte_intf_clk is same as byte_clk */
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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,
|
||||
struct link_clk_freq *bkp_freq)
|
||||
{
|
||||
@@ -4374,17 +4405,26 @@ static int _dsi_display_dyn_update_clks(struct dsi_display *display,
|
||||
u8 ctrl_version;
|
||||
struct dsi_display_ctrl *m_ctrl, *ctrl;
|
||||
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];
|
||||
dyn_clk_caps = &(display->panel->dyn_clk_caps);
|
||||
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);
|
||||
|
||||
rc = dsi_clk_update_parent(parent_clk,
|
||||
&display->clock_info.mux_clks);
|
||||
if (rc) {
|
||||
DSI_ERR("failed update mux parent to shadow\n");
|
||||
DSI_ERR("failed to update mux parent\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@@ -4443,12 +4483,12 @@ static int _dsi_display_dyn_update_clks(struct dsi_display *display,
|
||||
}
|
||||
|
||||
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);
|
||||
if (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;
|
||||
|
||||
|
@@ -106,13 +106,15 @@ struct dsi_display_boot_param {
|
||||
* struct dsi_display_clk_info - dsi display clock source information
|
||||
* @src_clks: Source clocks for DSI display.
|
||||
* @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_clk_link_set src_clks;
|
||||
struct dsi_clk_link_set mux_clks;
|
||||
struct dsi_clk_link_set cphy_clks;
|
||||
struct dsi_clk_link_set shadow_clks;
|
||||
struct dsi_clk_link_set shadow_cphy_clks;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -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)
|
||||
{
|
||||
u32 reg;
|
||||
bool is_cphy = (cfg->phy_type == DSI_PHY_TYPE_CPHY) ?
|
||||
true : false;
|
||||
|
||||
if (is_master) {
|
||||
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]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL26,
|
||||
DSIPHY_CMN_CTRL_0, DSIPHY_CMN_LANE_CTRL0,
|
||||
0x7f, 0x1f);
|
||||
0x7f, is_cphy ? 0x17 : 0x1f);
|
||||
|
||||
} else {
|
||||
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);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL9,
|
||||
DSIPHY_CMN_LANE_CTRL0, DSIPHY_CMN_CTRL_2,
|
||||
0x1f, 0x40);
|
||||
is_cphy ? 0x17 : 0x1f, 0x40);
|
||||
/*
|
||||
* fill with dummy register writes since controller will blindly
|
||||
* 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) {
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, reg,
|
||||
DSIPHY_CMN_LANE_CTRL0, DSIPHY_CMN_CTRL_0,
|
||||
0x1f, 0x7f);
|
||||
is_cphy ? 0x17 : 0x1f, 0x7f);
|
||||
reg += 0x4;
|
||||
}
|
||||
|
||||
|
@@ -37,6 +37,12 @@ static int calc_clk_prepare(struct dsi_phy_hw *phy,
|
||||
s64 intermediate;
|
||||
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) *
|
||||
clk_params->clk_prep_buf * multiplier);
|
||||
temp = roundup(div_s64(dividend, 100), multiplier);
|
||||
@@ -622,6 +628,218 @@ error:
|
||||
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.
|
||||
* @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_reco_max = 255;
|
||||
u32 const hs_rqst_spec_min = 50;
|
||||
u32 const hs_rqst_reco_max = 255;
|
||||
|
||||
/* local vars */
|
||||
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_timing_ops *ops = phy->ops.timing_ops;
|
||||
|
||||
u32 phy_type = host->phy_type;
|
||||
|
||||
memset(&desc, 0x0, sizeof(desc));
|
||||
h_total = dsi_h_total_dce(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)
|
||||
x = mode->clk_rate_hz;
|
||||
else
|
||||
else {
|
||||
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);
|
||||
|
||||
clk_params.bitclk_mbps = rounddown(DIV_ROUND_UP_ULL(y, 1000000), 1);
|
||||
@@ -699,27 +923,23 @@ int dsi_phy_hw_calculate_timing_params(struct dsi_phy_hw *phy,
|
||||
desc.hs_exit.rec_max = hs_exit_reco_max;
|
||||
desc.hs_rqst.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) {
|
||||
ops->get_default_phy_params(&clk_params);
|
||||
ops->get_default_phy_params(&clk_params, phy_type);
|
||||
} else {
|
||||
rc = -EINVAL;
|
||||
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",
|
||||
clk_params.bitclk_mbps, clk_params.tlpx_numer_ns,
|
||||
clk_params.treot_ns);
|
||||
|
||||
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) {
|
||||
DSI_PHY_ERR(phy, "Timing calc failed, rc=%d\n", rc);
|
||||
@@ -727,7 +947,7 @@ int dsi_phy_hw_calculate_timing_params(struct dsi_phy_hw *phy,
|
||||
}
|
||||
|
||||
if (ops->update_timing_params) {
|
||||
ops->update_timing_params(timing, &desc);
|
||||
ops->update_timing_params(timing, &desc, phy_type);
|
||||
} else {
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* 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_
|
||||
@@ -81,7 +81,8 @@ struct phy_clk_params {
|
||||
* Various Ops needed for auto-calculation of DSI PHY timing parameters.
|
||||
*/
|
||||
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);
|
||||
|
||||
@@ -96,14 +97,15 @@ struct phy_timing_ops {
|
||||
struct phy_timing_desc *desc);
|
||||
|
||||
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) \
|
||||
({ u64 _tmp = (x)+(y)-1; do_div(_tmp, y); _tmp * y; })
|
||||
|
||||
/* 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);
|
||||
|
||||
@@ -118,10 +120,11 @@ void dsi_phy_hw_v2_0_calc_hs_trail(struct phy_clk_params *clk_params,
|
||||
struct phy_timing_desc *desc);
|
||||
|
||||
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 */
|
||||
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);
|
||||
|
||||
@@ -136,10 +139,11 @@ void dsi_phy_hw_v3_0_calc_hs_trail(struct phy_clk_params *clk_params,
|
||||
struct phy_timing_desc *desc);
|
||||
|
||||
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 */
|
||||
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);
|
||||
|
||||
@@ -154,6 +158,6 @@ void dsi_phy_hw_v4_0_calc_hs_trail(struct phy_clk_params *clk_params,
|
||||
struct phy_timing_desc *desc);
|
||||
|
||||
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_ */
|
||||
|
@@ -1,11 +1,12 @@
|
||||
// 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"
|
||||
|
||||
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_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(
|
||||
struct dsi_phy_per_lane_cfgs *timing,
|
||||
struct phy_timing_desc *desc)
|
||||
struct phy_timing_desc *desc, u32 phy_type)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
|
@@ -1,12 +1,12 @@
|
||||
// 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"
|
||||
|
||||
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_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(
|
||||
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[1] = desc->clk_zero.reg_value;
|
||||
|
@@ -1,13 +1,20 @@
|
||||
// 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"
|
||||
|
||||
void dsi_phy_hw_v4_0_get_default_phy_params(
|
||||
struct phy_clk_params *params)
|
||||
struct phy_clk_params *params, u32 phy_type)
|
||||
{
|
||||
if (phy_type == DSI_PHY_TYPE_CPHY) {
|
||||
params->clk_prep_buf = 50;
|
||||
params->clk_pre_buf = 20;
|
||||
params->clk_post_buf = 80;
|
||||
params->hs_rqst_buf = 1;
|
||||
params->hs_exit_buf = 10;
|
||||
} else {
|
||||
params->clk_prep_buf = 50;
|
||||
params->clk_zero_buf = 2;
|
||||
params->clk_trail_buf = 30;
|
||||
@@ -19,6 +26,7 @@ void dsi_phy_hw_v4_0_get_default_phy_params(
|
||||
/* 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)
|
||||
@@ -75,8 +83,22 @@ void dsi_phy_hw_v4_0_calc_hs_trail(struct phy_clk_params *clk_params,
|
||||
|
||||
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)
|
||||
{
|
||||
if (phy_type == DSI_PHY_TYPE_CPHY) {
|
||||
timing->lane_v4[0] = 0x00;
|
||||
timing->lane_v4[1] = 0x00;
|
||||
timing->lane_v4[2] = 0x00;
|
||||
timing->lane_v4[3] = 0x00;
|
||||
timing->lane_v4[4] = desc->hs_exit.reg_value;
|
||||
timing->lane_v4[5] = desc->clk_pre.reg_value;
|
||||
timing->lane_v4[6] = desc->clk_prepare.reg_value;
|
||||
timing->lane_v4[7] = desc->clk_post.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;
|
||||
} else {
|
||||
timing->lane_v4[0] = 0x00;
|
||||
timing->lane_v4[1] = desc->clk_zero.reg_value;
|
||||
timing->lane_v4[2] = desc->clk_prepare.reg_value;
|
||||
@@ -91,6 +113,7 @@ void dsi_phy_hw_v4_0_update_timing_params(
|
||||
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],
|
||||
timing->lane_v4[1], timing->lane_v4[2], timing->lane_v4[3]);
|
||||
|
Reference in New Issue
Block a user