From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Sharma, Shashank" Subject: Re: [PATCH v2 2/4] drm/i915: Respect DP++ adaptor TMDS clock limit Date: Wed, 04 May 2016 15:38:28 +0530 Message-ID: <5729CA1C.5060508@intel.com> References: <1462216105-20881-1-git-send-email-ville.syrjala@linux.intel.com> <1462216105-20881-3-git-send-email-ville.syrjala@linux.intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: QUOTED-PRINTABLE Return-path: In-Reply-To: <1462216105-20881-3-git-send-email-ville.syrjala@linux.intel.com> Sender: stable-owner@vger.kernel.org To: ville.syrjala@linux.intel.com, dri-devel@lists.freedesktop.org Cc: intel-gfx@lists.freedesktop.org, stable@vger.kernel.org, Paulo Zanoni , Daniel Vetter List-Id: intel-gfx@lists.freedesktop.org Reviewed-by: Shashank Sharma Regards Shashank On 5/3/2016 12:38 AM, ville.syrjala@linux.intel.com wrote: > From: Ville Syrj=C3=A4l=C3=A4 > > Try to detect the max TMDS clock limit for the DP++ adaptor (if any) > and take it into account when checking the port clock. > > Note that as with the sink (HDMI vs. DVI) TMDS clock limit we'll igno= re > the adaptor TMDS clock limit in the modeset path, in case users are > already "overclocking" their TMDS links. One subtle change here is th= at > we'll have to respect the adaptor TMDS clock limit when we decide whe= ther > to do 12bpc or 8bpc, otherwise we might end up picking 12bpc and > accidentally driving the TMDS link out of spec even when the user cho= se > a mode that fits wihting the limits at 8bpc. This means you can't > "overclock" your DP++ dongle at 12bpc anymore, but you can continue t= o > do so at 8bpc. > > Note that for simplicity we'll use the I2C access method for all dual > mode adaptors including type 2. Otherwise we'd have to start mixing > DP AUX and HDMI together. In the future we may need to do that if we > come across any board designs that don't hook up the DDC pins to the > DP++ connectors. Such boards would obviously only work with type 2 > dual mode adaptors, and not type 1. > > v2: Store adaptor type under indel_hdmi->dp_dual_mode > Deal with DRM_DP_DUAL_MODE_UNKNOWN > Pass adaptor type to drm_dp_dual_mode_max_tmds_clock(), > and use it for type1 adaptors as well > > Cc: stable@vger.kernel.org > Reported-by: Tore Anderson > Fixes: 7a0baa623446 ("Revert "drm/i915: Disable 12bpc hdmi for now"") > Cc: Paulo Zanoni > Cc: Shashank Sharma > Cc: Daniel Vetter > Signed-off-by: Ville Syrj=C3=A4l=C3=A4 > --- > drivers/gpu/drm/i915/intel_drv.h | 5 ++++ > drivers/gpu/drm/i915/intel_hdmi.c | 58 ++++++++++++++++++++++++++++= +++++------ > 2 files changed, 55 insertions(+), 8 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/= intel_drv.h > index 21dee3f89e84..e94d18fb2ff1 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -33,6 +33,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -753,6 +754,10 @@ struct cxsr_latency { > struct intel_hdmi { > i915_reg_t hdmi_reg; > int ddc_bus; > + struct { > + enum drm_dp_dual_mode_type type; > + int max_tmds_clock; > + } dp_dual_mode; > bool limited_color_range; > bool color_range_auto; > bool has_hdmi_sink; > diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915= /intel_hdmi.c > index e1012d612024..31ca11134294 100644 > --- a/drivers/gpu/drm/i915/intel_hdmi.c > +++ b/drivers/gpu/drm/i915/intel_hdmi.c > @@ -1167,27 +1167,42 @@ static void pch_post_disable_hdmi(struct inte= l_encoder *encoder) > intel_disable_hdmi(encoder); > } > > -static int hdmi_port_clock_limit(struct intel_hdmi *hdmi, bool respe= ct_dvi_limit) > +static int intel_hdmi_source_max_tmds_clock(struct drm_i915_private = *dev_priv) > { > - struct drm_device *dev =3D intel_hdmi_to_dev(hdmi); > - > - if ((respect_dvi_limit && !hdmi->has_hdmi_sink) || IS_G4X(dev)) > + if (IS_G4X(dev_priv)) > return 165000; > - else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >=3D 8) > + else if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >=3D 8) > return 300000; > else > return 225000; > } > > +static int hdmi_port_clock_limit(struct intel_hdmi *hdmi, > + bool respect_downstream_limits) > +{ > + struct drm_device *dev =3D intel_hdmi_to_dev(hdmi); > + int max_tmds_clock =3D intel_hdmi_source_max_tmds_clock(to_i915(dev= )); > + > + if (respect_downstream_limits) { > + if (hdmi->dp_dual_mode.max_tmds_clock) > + max_tmds_clock =3D min(max_tmds_clock, > + hdmi->dp_dual_mode.max_tmds_clock); > + if (!hdmi->has_hdmi_sink) > + max_tmds_clock =3D min(max_tmds_clock, 165000); > + } > + > + return max_tmds_clock; > +} > + > static enum drm_mode_status > hdmi_port_clock_valid(struct intel_hdmi *hdmi, > - int clock, bool respect_dvi_limit) > + int clock, bool respect_downstream_limits) > { > struct drm_device *dev =3D intel_hdmi_to_dev(hdmi); > > if (clock < 25000) > return MODE_CLOCK_LOW; > - if (clock > hdmi_port_clock_limit(hdmi, respect_dvi_limit)) > + if (clock > hdmi_port_clock_limit(hdmi, respect_downstream_limits)) > return MODE_CLOCK_HIGH; > > /* BXT DPLL can't generate 223-240 MHz */ > @@ -1311,7 +1326,7 @@ bool intel_hdmi_compute_config(struct intel_enc= oder *encoder, > * within limits. > */ > if (pipe_config->pipe_bpp > 8*3 && pipe_config->has_hdmi_sink && > - hdmi_port_clock_valid(intel_hdmi, clock_12bpc, false) =3D=3D MO= DE_OK && > + hdmi_port_clock_valid(intel_hdmi, clock_12bpc, true) =3D=3D MOD= E_OK && > hdmi_12bpc_possible(pipe_config)) { > DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n"); > desired_bpp =3D 12*3; > @@ -1353,10 +1368,35 @@ intel_hdmi_unset_edid(struct drm_connector *c= onnector) > intel_hdmi->has_audio =3D false; > intel_hdmi->rgb_quant_range_selectable =3D false; > > + intel_hdmi->dp_dual_mode.type =3D DRM_DP_DUAL_MODE_NONE; > + intel_hdmi->dp_dual_mode.max_tmds_clock =3D 0; > + > kfree(to_intel_connector(connector)->detect_edid); > to_intel_connector(connector)->detect_edid =3D NULL; > } > > +static void > +intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector) > +{ > + struct drm_i915_private *dev_priv =3D to_i915(connector->dev); > + struct intel_hdmi *hdmi =3D intel_attached_hdmi(connector); > + struct i2c_adapter *adapter =3D > + intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus); > + enum drm_dp_dual_mode_type type =3D drm_dp_dual_mode_detect(adapter= ); > + > + if (type =3D=3D DRM_DP_DUAL_MODE_NONE || > + type =3D=3D DRM_DP_DUAL_MODE_UNKNOWN) > + return; > + > + hdmi->dp_dual_mode.type =3D type; > + hdmi->dp_dual_mode.max_tmds_clock =3D > + drm_dp_dual_mode_max_tmds_clock(type, adapter); > + > + DRM_DEBUG_KMS("DP dual mode adaptor (%s) detected (max TMDS clock: = %d kHz)\n", > + drm_dp_get_dual_mode_type_name(type), > + hdmi->dp_dual_mode.max_tmds_clock); > +} > + > static bool > intel_hdmi_set_edid(struct drm_connector *connector, bool force) > { > @@ -1372,6 +1412,8 @@ intel_hdmi_set_edid(struct drm_connector *conne= ctor, bool force) > intel_gmbus_get_adapter(dev_priv, > intel_hdmi->ddc_bus)); > > + intel_hdmi_dp_dual_mode_detect(connector); > + > intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS); > } > >