> Subject: [PATCH v2 05/32] drm/i915/cx0: Track the C20 PHY VDR state in the > PLL state > > From: Imre Deak <[email protected]> > > The Cx0 PLL enable programming needs to know if the PLL is in DP or HDMI > mode. The PLL manager framework doesn't pass the CRTC state to the PLL's > enable hook, so prepare here for the conversion to use the PLL manager for > Cx0 PHY PLLs by tracking the DP/HDMI mode in the PLL state. > > This change has the advantage, that the VDR HW/SW state can be verified > now. > > A follow up change will convert the PLL enable function to retrieve the > DP/HDMI mode parameter from the PLL state. > > This also allows dropping the is_dp and port clock params from the > intel_c20_pll_program() function, since it can retrieve these now from the > PLL state. > > v2: Fix comment to under same multicomment line (Suraj) > > Signed-off-by: Imre Deak <[email protected]> > Signed-off-by: Mika Kahola <[email protected]>
LGTM, Reviewed-by: Suraj Kandpal <[email protected]> > --- > drivers/gpu/drm/i915/display/intel_cx0_phy.c | 119 +++++++++++++----- > drivers/gpu/drm/i915/display/intel_dpll_mgr.h | 5 + > 2 files changed, 92 insertions(+), 32 deletions(-) > > diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c > b/drivers/gpu/drm/i915/display/intel_cx0_phy.c > index a1f2272fed14..fd0409565c68 100644 > --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c > +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c > @@ -2357,6 +2357,75 @@ intel_c20_pll_tables_get(const struct > intel_crtc_state *crtc_state, > return NULL; > } > > +static u8 intel_c20_get_dp_rate(u32 clock); static u8 > +intel_c20_get_hdmi_rate(u32 clock); static int > +intel_get_c20_custom_width(u32 clock, bool dp); > + > +static void intel_c20_calc_vdr_params(struct intel_c20pll_vdr_state *vdr, > bool is_dp, > + int port_clock) > +{ > + vdr->custom_width = intel_get_c20_custom_width(port_clock, > is_dp); > + > + vdr->serdes_rate = 0; > + vdr->hdmi_rate = 0; > + > + if (is_dp) { > + vdr->serdes_rate = PHY_C20_IS_DP | > + > PHY_C20_DP_RATE(intel_c20_get_dp_rate(port_clock)); > + } else { > + if (intel_hdmi_is_frl(port_clock)) > + vdr->serdes_rate = PHY_C20_IS_HDMI_FRL; > + > + vdr->hdmi_rate = intel_c20_get_hdmi_rate(port_clock); > + } > +} > + > +#define PHY_C20_SERDES_RATE_MASK (PHY_C20_IS_DP | > PHY_C20_DP_RATE_MASK | PHY_C20_IS_HDMI_FRL) > + > +static void intel_c20_readout_vdr_params(struct intel_encoder *encoder, > + struct intel_c20pll_vdr_state *vdr, > bool *cntx) { > + u8 serdes; > + > + serdes = intel_cx0_read(encoder, INTEL_CX0_LANE0, > PHY_C20_VDR_CUSTOM_SERDES_RATE); > + *cntx = serdes & PHY_C20_CONTEXT_TOGGLE; > + > + vdr->custom_width = intel_cx0_read(encoder, INTEL_CX0_LANE0, > PHY_C20_VDR_CUSTOM_WIDTH) & > + PHY_C20_CUSTOM_WIDTH_MASK; > + > + vdr->serdes_rate = serdes & PHY_C20_SERDES_RATE_MASK; > + if (!(vdr->serdes_rate & PHY_C20_IS_DP)) > + vdr->hdmi_rate = intel_cx0_read(encoder, INTEL_CX0_LANE0, > PHY_C20_VDR_HDMI_RATE) & > + PHY_C20_HDMI_RATE_MASK; > + else > + vdr->hdmi_rate = 0; > +} > + > +static void intel_c20_program_vdr_params(struct intel_encoder *encoder, > + const struct intel_c20pll_vdr_state > *vdr, > + u8 owned_lane_mask) > +{ > + struct intel_display *display = to_intel_display(encoder); > + > + drm_WARN_ON(display->drm, vdr->custom_width & > ~PHY_C20_CUSTOM_WIDTH_MASK); > + intel_cx0_rmw(encoder, owned_lane_mask, > PHY_C20_VDR_CUSTOM_WIDTH, > + PHY_C20_CUSTOM_WIDTH_MASK, vdr->custom_width, > + MB_WRITE_COMMITTED); > + > + drm_WARN_ON(display->drm, vdr->serdes_rate & > ~PHY_C20_SERDES_RATE_MASK); > + intel_cx0_rmw(encoder, owned_lane_mask, > PHY_C20_VDR_CUSTOM_SERDES_RATE, > + PHY_C20_SERDES_RATE_MASK, vdr->serdes_rate, > + MB_WRITE_COMMITTED); > + > + if (vdr->serdes_rate & PHY_C20_IS_DP) > + return; > + > + drm_WARN_ON(display->drm, vdr->hdmi_rate & > ~PHY_C20_HDMI_RATE_MASK); > + intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, > PHY_C20_VDR_HDMI_RATE, > + PHY_C20_HDMI_RATE_MASK, vdr->hdmi_rate, > + MB_WRITE_COMMITTED); > +} > + > static const struct intel_c20pll_state * intel_c20_pll_find_table(const > struct > intel_crtc_state *crtc_state, > struct intel_encoder *encoder) > @@ -2395,19 +2464,26 @@ static int > intel_c20pll_calc_state_from_table(struct intel_crtc_state *crtc_stat static > int > intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, > struct intel_encoder *encoder) > { > + bool is_dp = intel_crtc_has_dp_encoder(crtc_state); > int err = -ENOENT; > > crtc_state->dpll_hw_state.cx0pll.use_c10 = false; > > /* try computed C20 HDMI tables before using consolidated tables > */ > - if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) > + if (!is_dp) > /* TODO: Update SSC state for HDMI as well */ > err = intel_c20_compute_hdmi_tmds_pll(crtc_state); > > if (err) > err = intel_c20pll_calc_state_from_table(crtc_state, encoder); > > - return err; > + if (err) > + return err; > + > + intel_c20_calc_vdr_params(&crtc_state- > >dpll_hw_state.cx0pll.c20.vdr, > + is_dp, crtc_state->port_clock); > + > + return 0; > } > > int intel_cx0pll_calc_state(struct intel_crtc_state *crtc_state, @@ -2481,8 > +2557,8 @@ static void intel_c20pll_readout_hw_state(struct intel_encoder > *encoder, > > wakeref = intel_cx0_phy_transaction_begin(encoder); > > - /* 1. Read current context selection */ > - cntx = intel_cx0_read(encoder, INTEL_CX0_LANE0, > PHY_C20_VDR_CUSTOM_SERDES_RATE) & PHY_C20_CONTEXT_TOGGLE; > + /* 1. Read VDR params and current context selection */ > + intel_c20_readout_vdr_params(encoder, &pll_state->vdr, &cntx); > > /* Read Tx configuration */ > for (i = 0; i < ARRAY_SIZE(pll_state->tx); i++) { @@ -2657,11 +2733,9 > @@ static int intel_get_c20_custom_width(u32 clock, bool dp) > > static void intel_c20_pll_program(struct intel_display *display, > struct intel_encoder *encoder, > - const struct intel_c20pll_state *pll_state, > - bool is_dp, int port_clock) > + const struct intel_c20pll_state *pll_state) > { > u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder); > - u8 serdes; > bool cntx; > int i; > > @@ -2730,30 +2804,11 @@ static void intel_c20_pll_program(struct > intel_display *display, > } > } > > - /* 4. Program custom width to match the link protocol */ > - intel_cx0_rmw(encoder, owned_lane_mask, > PHY_C20_VDR_CUSTOM_WIDTH, > - PHY_C20_CUSTOM_WIDTH_MASK, > - > PHY_C20_CUSTOM_WIDTH(intel_get_c20_custom_width(port_clock, is_dp)), > - MB_WRITE_COMMITTED); > - > - /* 5. For DP or 6. For HDMI */ > - serdes = 0; > - if (is_dp) > - serdes = PHY_C20_IS_DP | > - > PHY_C20_DP_RATE(intel_c20_get_dp_rate(port_clock)); > - else if (intel_hdmi_is_frl(port_clock)) > - serdes = PHY_C20_IS_HDMI_FRL; > - > - intel_cx0_rmw(encoder, owned_lane_mask, > PHY_C20_VDR_CUSTOM_SERDES_RATE, > - PHY_C20_IS_DP | PHY_C20_DP_RATE_MASK | > PHY_C20_IS_HDMI_FRL, > - serdes, > - MB_WRITE_COMMITTED); > - > - if (!is_dp) > - intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, > PHY_C20_VDR_HDMI_RATE, > - PHY_C20_HDMI_RATE_MASK, > - intel_c20_get_hdmi_rate(port_clock), > - MB_WRITE_COMMITTED); > + /* > + * 4. Program custom width to match the link protocol. > + * 5. For DP or 6. For HDMI > + */ > + intel_c20_program_vdr_params(encoder, &pll_state->vdr, > +owned_lane_mask); > > /* > * 7. Write Vendor specific registers to toggle context setting to load > @@ -3077,7 +3132,7 @@ static void __intel_cx0pll_enable(struct > intel_encoder *encoder, > if (intel_encoder_is_c10phy(encoder)) > intel_c10_pll_program(display, encoder, &pll_state->c10); > else > - intel_c20_pll_program(display, encoder, &pll_state->c20, > is_dp, port_clock); > + intel_c20_pll_program(display, encoder, &pll_state->c20); > > /* > * 6. Program the enabled and disabled owned PHY lane diff --git > a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h > b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h > index 6183da90b28d..a0238a3e7288 100644 > --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h > +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h > @@ -255,6 +255,11 @@ struct intel_c20pll_state { > u16 mplla[10]; > u16 mpllb[11]; > }; > + struct intel_c20pll_vdr_state { > + u8 custom_width; > + u8 serdes_rate; > + u8 hdmi_rate; > + } vdr; > }; > > struct intel_cx0pll_state { > -- > 2.34.1
