From 662ac3ab897927da89780d38b479d96f14192f2e Mon Sep 17 00:00:00 2001 From: Harigovindan P Date: Wed, 6 May 2020 15:31:55 +0530 Subject: [PATCH] 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 Signed-off-by: Harigovindan P Signed-off-by: Steve Cohen --- msm/dsi/dsi_display.c | 66 +++++++-- msm/dsi/dsi_display.h | 4 +- msm/dsi/dsi_phy_hw_v4_0.c | 8 +- msm/dsi/dsi_phy_timing_calc.c | 248 ++++++++++++++++++++++++++++++++-- msm/dsi/dsi_phy_timing_calc.h | 22 +-- msm/dsi/dsi_phy_timing_v2_0.c | 7 +- msm/dsi/dsi_phy_timing_v3_0.c | 6 +- msm/dsi/dsi_phy_timing_v4_0.c | 79 +++++++---- 8 files changed, 366 insertions(+), 74 deletions(-) diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index 120445b887..e40873ee31 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -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, - &display->clock_info.mux_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, - &display->clock_info.mux_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; diff --git a/msm/dsi/dsi_display.h b/msm/dsi/dsi_display.h index 5398b4bcf3..7406d78295 100644 --- a/msm/dsi/dsi_display.h +++ b/msm/dsi/dsi_display.h @@ -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; }; /** diff --git a/msm/dsi/dsi_phy_hw_v4_0.c b/msm/dsi/dsi_phy_hw_v4_0.c index e4d0110a2e..5272874506 100644 --- a/msm/dsi/dsi_phy_hw_v4_0.c +++ b/msm/dsi/dsi_phy_hw_v4_0.c @@ -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; } diff --git a/msm/dsi/dsi_phy_timing_calc.c b/msm/dsi/dsi_phy_timing_calc.c index d321d08b6c..6e2a625a35 100644 --- a/msm/dsi/dsi_phy_timing_calc.c +++ b/msm/dsi/dsi_phy_timing_calc.c @@ -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,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_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); - 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) { DSI_PHY_ERR(phy, "Timing calc failed, rc=%d\n", rc); goto error; } if (ops->update_timing_params) { - ops->update_timing_params(timing, &desc); + ops->update_timing_params(timing, &desc, phy_type); } else { rc = -EINVAL; goto error; diff --git a/msm/dsi/dsi_phy_timing_calc.h b/msm/dsi/dsi_phy_timing_calc.h index 2ed5e72f3b..536e7670a1 100644 --- a/msm/dsi/dsi_phy_timing_calc.h +++ b/msm/dsi/dsi_phy_timing_calc.h @@ -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_ */ diff --git a/msm/dsi/dsi_phy_timing_v2_0.c b/msm/dsi/dsi_phy_timing_v2_0.c index d3c1cb1090..383999395b 100644 --- a/msm/dsi/dsi_phy_timing_v2_0.c +++ b/msm/dsi/dsi_phy_timing_v2_0.c @@ -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; diff --git a/msm/dsi/dsi_phy_timing_v3_0.c b/msm/dsi/dsi_phy_timing_v3_0.c index 562d296253..c57b6b5ff2 100644 --- a/msm/dsi/dsi_phy_timing_v3_0.c +++ b/msm/dsi/dsi_phy_timing_v3_0.c @@ -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; diff --git a/msm/dsi/dsi_phy_timing_v4_0.c b/msm/dsi/dsi_phy_timing_v4_0.c index eb6a8f7c22..112762896a 100644 --- a/msm/dsi/dsi_phy_timing_v4_0.c +++ b/msm/dsi/dsi_phy_timing_v4_0.c @@ -1,24 +1,32 @@ // 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) { - params->clk_prep_buf = 50; - params->clk_zero_buf = 2; - params->clk_trail_buf = 30; - 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; + 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; + 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) @@ -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( 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; - 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; + 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; + 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], timing->lane_v4[1], timing->lane_v4[2], timing->lane_v4[3]);