mirror of https://gitee.com/openkylin/linux.git
drm/i915/icl: Program DSI clock and data lane timing params
This patch programs D-PHY timing parameters for the clock and data lane (in escape clocks) of DSI controller (DSI port 0 and 1). These programmed timings would be used by DSI Controller to calculate link transition latencies of the data and clock lanes. v2: Use newly defined bitfields for data and clock lane v3 by Jani: - Rebase on dphy abstraction - Reduce local variables - Remove unrelated comment changes (Ville) - Use the same style for range checks as VLV (Ville) - Assign, don't OR dphy_reg contents Signed-off-by: Madhav Chauhan <madhav.chauhan@intel.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/70d491e2357f328a63b67ea3c43cb57a1d469c15.1539613303.git.jani.nikula@intel.com
This commit is contained in:
parent
b687c1984c
commit
e72cce5310
|
@ -291,6 +291,24 @@ static void gen11_dsi_setup_dphy_timings(struct intel_encoder *encoder)
|
|||
tmp |= intel_dsi->init_count;
|
||||
I915_WRITE(ICL_DSI_T_INIT_MASTER(port), tmp);
|
||||
}
|
||||
|
||||
/* Program DPHY clock lanes timings */
|
||||
for_each_dsi_port(port, intel_dsi->ports) {
|
||||
I915_WRITE(DPHY_CLK_TIMING_PARAM(port), intel_dsi->dphy_reg);
|
||||
|
||||
/* shadow register inside display core */
|
||||
I915_WRITE(DSI_CLK_TIMING_PARAM(port), intel_dsi->dphy_reg);
|
||||
}
|
||||
|
||||
/* Program DPHY data lanes timings */
|
||||
for_each_dsi_port(port, intel_dsi->ports) {
|
||||
I915_WRITE(DPHY_DATA_TIMING_PARAM(port),
|
||||
intel_dsi->dphy_data_lane_reg);
|
||||
|
||||
/* shadow register inside display core */
|
||||
I915_WRITE(DSI_DATA_TIMING_PARAM(port),
|
||||
intel_dsi->dphy_data_lane_reg);
|
||||
}
|
||||
}
|
||||
|
||||
static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder)
|
||||
|
|
|
@ -85,6 +85,9 @@ struct intel_dsi {
|
|||
u32 port_bits;
|
||||
u32 bw_timer;
|
||||
u32 dphy_reg;
|
||||
|
||||
/* data lanes dphy timing */
|
||||
u32 dphy_data_lane_reg;
|
||||
u32 video_frmt_cfg_bits;
|
||||
u16 lp_byte_clk;
|
||||
|
||||
|
|
|
@ -510,6 +510,111 @@ int intel_dsi_vbt_get_modes(struct intel_dsi *intel_dsi)
|
|||
return 1;
|
||||
}
|
||||
|
||||
#define ICL_PREPARE_CNT_MAX 0x7
|
||||
#define ICL_CLK_ZERO_CNT_MAX 0xf
|
||||
#define ICL_TRAIL_CNT_MAX 0x7
|
||||
#define ICL_TCLK_PRE_CNT_MAX 0x3
|
||||
#define ICL_TCLK_POST_CNT_MAX 0x7
|
||||
#define ICL_HS_ZERO_CNT_MAX 0xf
|
||||
#define ICL_EXIT_ZERO_CNT_MAX 0x7
|
||||
|
||||
static void icl_dphy_param_init(struct intel_dsi *intel_dsi)
|
||||
{
|
||||
struct drm_device *dev = intel_dsi->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct mipi_config *mipi_config = dev_priv->vbt.dsi.config;
|
||||
u32 tlpx_ns;
|
||||
u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt;
|
||||
u32 ths_prepare_ns, tclk_trail_ns;
|
||||
u32 hs_zero_cnt;
|
||||
u32 tclk_pre_cnt, tclk_post_cnt;
|
||||
|
||||
tlpx_ns = intel_dsi_tlpx_ns(intel_dsi);
|
||||
|
||||
tclk_trail_ns = max(mipi_config->tclk_trail, mipi_config->ths_trail);
|
||||
ths_prepare_ns = max(mipi_config->ths_prepare,
|
||||
mipi_config->tclk_prepare);
|
||||
|
||||
/*
|
||||
* prepare cnt in escape clocks
|
||||
* this field represents a hexadecimal value with a precision
|
||||
* of 1.2 – i.e. the most significant bit is the integer
|
||||
* and the least significant 2 bits are fraction bits.
|
||||
* so, the field can represent a range of 0.25 to 1.75
|
||||
*/
|
||||
prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * 4, tlpx_ns);
|
||||
if (prepare_cnt > ICL_PREPARE_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("prepare_cnt out of range (%d)\n", prepare_cnt);
|
||||
prepare_cnt = ICL_PREPARE_CNT_MAX;
|
||||
}
|
||||
|
||||
/* clk zero count in escape clocks */
|
||||
clk_zero_cnt = DIV_ROUND_UP(mipi_config->tclk_prepare_clkzero -
|
||||
ths_prepare_ns, tlpx_ns);
|
||||
if (clk_zero_cnt > ICL_CLK_ZERO_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("clk_zero_cnt out of range (%d)\n", clk_zero_cnt);
|
||||
clk_zero_cnt = ICL_CLK_ZERO_CNT_MAX;
|
||||
}
|
||||
|
||||
/* trail cnt in escape clocks*/
|
||||
trail_cnt = DIV_ROUND_UP(tclk_trail_ns, tlpx_ns);
|
||||
if (trail_cnt > ICL_TRAIL_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("trail_cnt out of range (%d)\n", trail_cnt);
|
||||
trail_cnt = ICL_TRAIL_CNT_MAX;
|
||||
}
|
||||
|
||||
/* tclk pre count in escape clocks */
|
||||
tclk_pre_cnt = DIV_ROUND_UP(mipi_config->tclk_pre, tlpx_ns);
|
||||
if (tclk_pre_cnt > ICL_TCLK_PRE_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("tclk_pre_cnt out of range (%d)\n", tclk_pre_cnt);
|
||||
tclk_pre_cnt = ICL_TCLK_PRE_CNT_MAX;
|
||||
}
|
||||
|
||||
/* tclk post count in escape clocks */
|
||||
tclk_post_cnt = DIV_ROUND_UP(mipi_config->tclk_post, tlpx_ns);
|
||||
if (tclk_post_cnt > ICL_TCLK_POST_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("tclk_post_cnt out of range (%d)\n", tclk_post_cnt);
|
||||
tclk_post_cnt = ICL_TCLK_POST_CNT_MAX;
|
||||
}
|
||||
|
||||
/* hs zero cnt in escape clocks */
|
||||
hs_zero_cnt = DIV_ROUND_UP(mipi_config->ths_prepare_hszero -
|
||||
ths_prepare_ns, tlpx_ns);
|
||||
if (hs_zero_cnt > ICL_HS_ZERO_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("hs_zero_cnt out of range (%d)\n", hs_zero_cnt);
|
||||
hs_zero_cnt = ICL_HS_ZERO_CNT_MAX;
|
||||
}
|
||||
|
||||
/* hs exit zero cnt in escape clocks */
|
||||
exit_zero_cnt = DIV_ROUND_UP(mipi_config->ths_exit, tlpx_ns);
|
||||
if (exit_zero_cnt > ICL_EXIT_ZERO_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("exit_zero_cnt out of range (%d)\n", exit_zero_cnt);
|
||||
exit_zero_cnt = ICL_EXIT_ZERO_CNT_MAX;
|
||||
}
|
||||
|
||||
/* clock lane dphy timings */
|
||||
intel_dsi->dphy_reg = (CLK_PREPARE_OVERRIDE |
|
||||
CLK_PREPARE(prepare_cnt) |
|
||||
CLK_ZERO_OVERRIDE |
|
||||
CLK_ZERO(clk_zero_cnt) |
|
||||
CLK_PRE_OVERRIDE |
|
||||
CLK_PRE(tclk_pre_cnt) |
|
||||
CLK_POST_OVERRIDE |
|
||||
CLK_POST(tclk_post_cnt) |
|
||||
CLK_TRAIL_OVERRIDE |
|
||||
CLK_TRAIL(trail_cnt));
|
||||
|
||||
/* data lanes dphy timings */
|
||||
intel_dsi->dphy_data_lane_reg = (HS_PREPARE_OVERRIDE |
|
||||
HS_PREPARE(prepare_cnt) |
|
||||
HS_ZERO_OVERRIDE |
|
||||
HS_ZERO(hs_zero_cnt) |
|
||||
HS_TRAIL_OVERRIDE |
|
||||
HS_TRAIL(trail_cnt) |
|
||||
HS_EXIT_OVERRIDE |
|
||||
HS_EXIT(exit_zero_cnt));
|
||||
}
|
||||
|
||||
static void vlv_dphy_param_init(struct intel_dsi *intel_dsi)
|
||||
{
|
||||
struct drm_device *dev = intel_dsi->base.base.dev;
|
||||
|
@ -743,7 +848,10 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
|
|||
|
||||
intel_dsi->burst_mode_ratio = burst_mode_ratio;
|
||||
|
||||
vlv_dphy_param_init(intel_dsi);
|
||||
if (IS_ICELAKE(dev_priv))
|
||||
icl_dphy_param_init(intel_dsi);
|
||||
else
|
||||
vlv_dphy_param_init(intel_dsi);
|
||||
|
||||
DRM_DEBUG_KMS("Pclk %d\n", intel_dsi->pclk);
|
||||
DRM_DEBUG_KMS("Pixel overlap %d\n", intel_dsi->pixel_overlap);
|
||||
|
|
Loading…
Reference in New Issue