Re: [PATCH 1/2] drm/framebuffer: Format modifier for Intel Gen-12 render compression
On Sat, 2019-09-07 at 00:21 -0700, Dhinakaran Pandiyan wrote: > Gen-12 has a new compression format, add a new modifier to indicate that. > > Cc: Ville Syrjälä > Cc: Matt Roper > Cc: Nanley G Chery > Cc: Jason Ekstrand Cc: dri-devel@lists.freedesktop.org > Signed-off-by: Dhinakaran Pandiyan > Signed-off-by: Lucas De Marchi > --- > include/uapi/drm/drm_fourcc.h | 11 +++ > 1 file changed, 11 insertions(+) > > diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h > index 3feeaa3f987a..1f0fbf0398f6 100644 > --- a/include/uapi/drm/drm_fourcc.h > +++ b/include/uapi/drm/drm_fourcc.h > @@ -410,6 +410,17 @@ extern "C" { > #define I915_FORMAT_MOD_Y_TILED_CCS fourcc_mod_code(INTEL, 4) > #define I915_FORMAT_MOD_Yf_TILED_CCS fourcc_mod_code(INTEL, 5) > > +/* > + * Intel color control surfaces (CCS) for Gen-12 render compression. > + * > + * The main surface is Y-tiled and at plane index 0, the CCS is linear and > + * at index 1. A 64B CCS cache line corresponds to an area of 4x1 tiles in > + * main surface. In other words, 4 bits in CCS map to a main surface cache > + * line pair. The main surface pitch is required to be a multiple of four > + * Y-tile widths. > + */ > +#define I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS fourcc_mod_code(INTEL, 6) > + > /* > * Tiled, NV12MT, grouped in 64 (pixels) x 32 (lines) -sized macroblocks > * ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH] drm/connector: Allow max possible encoders to attach to a connector
On Wed, 2019-06-26 at 16:31 +0200, Daniel Vetter wrote: > On Wed, Jun 26, 2019 at 04:43:28PM +0300, Ville Syrjälä wrote: > > On Tue, Jun 25, 2019 at 04:40:45PM -0700, Dhinakaran Pandiyan wrote: > > > Currently we restrict the number of encoders that can be linked to > > > a connector to 3, increase it to match the maximum number of encoders > > > that can be initialized - 32. The current limitation looks artificial. > > > Increasing the limit to 32 does however increases the size of the static > > > u32 array keeping track of the encoder IDs. > > > > > > Cc: José Roberto de Souza > > > Cc: Ville Syrjälä > > > Cc: dri-devel@lists.freedesktop.org > > > Signed-off-by: Dhinakaran Pandiyan > > > --- > > > include/drm/drm_connector.h | 2 +- > > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > > > diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h > > > index ca745d9feaf5..91455b4a9360 100644 > > > --- a/include/drm/drm_connector.h > > > +++ b/include/drm/drm_connector.h > > > @@ -1278,7 +1278,7 @@ struct drm_connector { > > > /** @override_edid: has the EDID been overwritten through debugfs for > > > testing? */ > > > bool override_edid; > > > > > > -#define DRM_CONNECTOR_MAX_ENCODER 3 > > > +#define DRM_CONNECTOR_MAX_ENCODER 32 > > > /** > > >* @encoder_ids: Valid encoders for this connector. Please only use > > >* drm_connector_for_each_possible_encoder() to enumerate these. > > > > I wonder if we couldn't just replace this array with a bitmask? > > I think the for_each_possible_encoder() thing I did a while back > > should make this easier potentially because most driver code just > > uses that. > > +1 on possible encoders bitmask. More consistent at least. Agreed, I'll make this change. -DK > -Daniel ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/connector: Allow max possible encoders to attach to a connector
Currently we restrict the number of encoders that can be linked to a connector to 3, increase it to match the maximum number of encoders that can be initialized - 32. The current limitation looks artificial. Increasing the limit to 32 does however increases the size of the static u32 array keeping track of the encoder IDs. Cc: José Roberto de Souza Cc: Ville Syrjälä Cc: dri-devel@lists.freedesktop.org Signed-off-by: Dhinakaran Pandiyan --- include/drm/drm_connector.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index ca745d9feaf5..91455b4a9360 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1278,7 +1278,7 @@ struct drm_connector { /** @override_edid: has the EDID been overwritten through debugfs for testing? */ bool override_edid; -#define DRM_CONNECTOR_MAX_ENCODER 3 +#define DRM_CONNECTOR_MAX_ENCODER 32 /** * @encoder_ids: Valid encoders for this connector. Please only use * drm_connector_for_each_possible_encoder() to enumerate these. -- 2.17.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 3/3] drm/i915: DDI: call intel_psr_ and _edp_drrs_enable() on pipe updates (v2)
On Thu, 2018-12-20 at 15:13 -0800, Dhinakaran Pandiyan wrote: > On Thu, 2018-12-20 at 09:10 -0800, Rodrigo Vivi wrote: > > On Thu, Dec 20, 2018 at 02:21:20PM +0100, Hans de Goede wrote: > > > Call intel_psr_enable() and intel_edp_drrs_enable() on pipe > > > updates > > > to make > > > sure that we enable PSR / DRRS (when applicable) on fastsets. > > I am probably missing something, doesn't intel_pipe_config_compare() > need to check for pipe_config->has_psr? And also read the hardware > PSR > state at boot? Answering my own question here, pipe_config_compare() returns true lacking a comparison for ->has_psr. And we assume the bios does not enable PSR, so no need to read the hardware state. > > > > > > Note calling these functions when PSR / DRRS has already been > > > enabled is a > > > no-op, so it is safe to do this on every encoder->update_pipe > > > callback. > > > > > > Changes in v2: > > > -Merge the patches adding the intel_psr_enable() and > > > intel_edp_drrs_enable() > > > calls into a single patch > > > > > > Reviewed-by: Maarten Lankhorst > > > > > > Signed-off-by: Hans de Goede > > > > Cc: Dhinakaran Pandiyan > > Cc: José Roberto de Souza > > > > Acked-by: Rodrigo Vivi > > > > > --- > > > drivers/gpu/drm/i915/intel_ddi.c | 19 +++ > > > 1 file changed, 19 insertions(+) > > > > > > diff --git a/drivers/gpu/drm/i915/intel_ddi.c > > > b/drivers/gpu/drm/i915/intel_ddi.c > > > index e3cc19e19199..fdf57f451b72 100644 > > > --- a/drivers/gpu/drm/i915/intel_ddi.c > > > +++ b/drivers/gpu/drm/i915/intel_ddi.c > > > @@ -3537,6 +3537,24 @@ static void intel_disable_ddi(struct > > > intel_encoder *encoder, > > > intel_disable_ddi_dp(encoder, old_crtc_state, > > > old_conn_state); > > > } > > > > > > +static void intel_ddi_update_pipe_dp(struct intel_encoder > > > *encoder, > > > + const struct intel_crtc_state > > > *crtc_state, > > > + const struct drm_connector_state > > > *conn_state) > > > +{ > > > + struct intel_dp *intel_dp = enc_to_intel_dp(>base); > > > + > > > + intel_psr_enable(intel_dp, crtc_state); > > > + intel_edp_drrs_enable(intel_dp, crtc_state); > > > +} > > > + > > > +static void intel_ddi_update_pipe(struct intel_encoder *encoder, > > > + const struct intel_crtc_state > > > *crtc_state, > > > + const struct drm_connector_state > > > *conn_state) > > > +{ > > > + if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) > > We could restrict this to eDP outputs as both PSR and DRRS are eDP > features. > > > > + intel_ddi_update_pipe_dp(encoder, crtc_state, > > > conn_state); > > > +} > > > + > > > static void intel_ddi_set_fia_lane_count(struct intel_encoder > > > *encoder, > > >const struct intel_crtc_state > > > *pipe_config, > > >enum port port) > > > @@ -4169,6 +4187,7 @@ void intel_ddi_init(struct drm_i915_private > > > *dev_priv, enum port port) > > > intel_encoder->pre_enable = intel_ddi_pre_enable; > > > intel_encoder->disable = intel_disable_ddi; > > > intel_encoder->post_disable = intel_ddi_post_disable; > > > + intel_encoder->update_pipe = intel_ddi_update_pipe; > > > intel_encoder->get_hw_state = intel_ddi_get_hw_state; > > > intel_encoder->get_config = intel_ddi_get_config; > > > intel_encoder->suspend = intel_ddi_encoder_suspend; > > > -- > > > 2.20.1 > > > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/i915/psr: simplify enable_psr handling
On Fri, 2018-12-21 at 10:23 -0700, Ross Zwisler wrote: > The following commit: > > commit 2bdd045e3a30 ("drm/i915/psr: Check if VBT says PSR can be > enabled.") > > added some code with no usable functionality. Regardless of how the > psr > default is set up in the BDB_DRIVER_FEATURES section, if the > enable_psr > module parameter isn't specified it defaults to 0. Right, that was intentional and the commit message even makes a note of it " Note: The feature currently remains disabled by default for all platforms irrespective of what VBT says." Anyway, we've enabled the feature by default now and the current code should take into account the VBT flag if the module parameter is left to a default value. Please check git://anongit.freedesktop.org/drm-tip drm-tip. -DK > > Remove this dead code, simplify the way that enable_psr is handled > and > update the module parameter string to match the actual functionality. > > Cc: Dhinakaran Pandiyan > Cc: Rodrigo Vivi > Signed-off-by: Ross Zwisler > --- > drivers/gpu/drm/i915/i915_drv.h| 1 - > drivers/gpu/drm/i915/i915_params.c | 4 +--- > drivers/gpu/drm/i915/i915_params.h | 2 +- > drivers/gpu/drm/i915/intel_bios.c | 1 - > drivers/gpu/drm/i915/intel_psr.c | 7 --- > 5 files changed, 2 insertions(+), 13 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h > b/drivers/gpu/drm/i915/i915_drv.h > index 872a2e159a5f9..b4c50ba0b22a6 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -1115,7 +1115,6 @@ struct intel_vbt_data { > } edp; > > struct { > - bool enable; > bool full_link; > bool require_aux_wakeup; > int idle_frames; > diff --git a/drivers/gpu/drm/i915/i915_params.c > b/drivers/gpu/drm/i915/i915_params.c > index 295e981e4a398..80ce8758c3c69 100644 > --- a/drivers/gpu/drm/i915/i915_params.c > +++ b/drivers/gpu/drm/i915/i915_params.c > @@ -87,9 +87,7 @@ i915_param_named_unsafe(enable_ppgtt, int, 0400, > "(-1=auto [default], 0=disabled, 1=aliasing, 2=full, 3=full > with extended address space)"); > > i915_param_named_unsafe(enable_psr, int, 0600, > - "Enable PSR " > - "(0=disabled, 1=enabled) " > - "Default: -1 (use per-chip default)"); > + "Enable PSR (default: false)"); > > i915_param_named_unsafe(alpha_support, bool, 0400, > "Enable alpha quality driver support for latest hardware. " > diff --git a/drivers/gpu/drm/i915/i915_params.h > b/drivers/gpu/drm/i915/i915_params.h > index 6c4d4a21474b5..144572f17a83d 100644 > --- a/drivers/gpu/drm/i915/i915_params.h > +++ b/drivers/gpu/drm/i915/i915_params.h > @@ -42,7 +42,7 @@ struct drm_printer; > param(int, enable_dc, -1) \ > param(int, enable_fbc, -1) \ > param(int, enable_ppgtt, -1) \ > - param(int, enable_psr, -1) \ > + param(int, enable_psr, 0) \ > param(int, disable_power_well, -1) \ > param(int, enable_ips, 1) \ > param(int, invert_brightness, 0) \ > diff --git a/drivers/gpu/drm/i915/intel_bios.c > b/drivers/gpu/drm/i915/intel_bios.c > index 1faa494e2bc91..d676d483d5cf1 100644 > --- a/drivers/gpu/drm/i915/intel_bios.c > +++ b/drivers/gpu/drm/i915/intel_bios.c > @@ -551,7 +551,6 @@ parse_driver_features(struct drm_i915_private > *dev_priv, >*/ > if (!driver->drrs_enabled) > dev_priv->vbt.drrs_type = DRRS_NOT_SUPPORTED; > - dev_priv->vbt.psr.enable = driver->psr_enabled; > } > > static void > diff --git a/drivers/gpu/drm/i915/intel_psr.c > b/drivers/gpu/drm/i915/intel_psr.c > index b6838b525502e..26e7eb318cf07 100644 > --- a/drivers/gpu/drm/i915/intel_psr.c > +++ b/drivers/gpu/drm/i915/intel_psr.c > @@ -1065,13 +1065,6 @@ void intel_psr_init(struct drm_i915_private > *dev_priv) > if (!dev_priv->psr.sink_support) > return; > > - if (i915_modparams.enable_psr == -1) { > - i915_modparams.enable_psr = dev_priv->vbt.psr.enable; > - > - /* Per platform default: all disabled. */ > - i915_modparams.enable_psr = 0; > - } > - > /* Set link_standby x link_off defaults */ > if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) > /* HSW and BDW require workarounds that we don't > implement. */ ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 3/3] drm/i915: DDI: call intel_psr_ and _edp_drrs_enable() on pipe updates (v2)
On Thu, 2018-12-20 at 09:10 -0800, Rodrigo Vivi wrote: > On Thu, Dec 20, 2018 at 02:21:20PM +0100, Hans de Goede wrote: > > Call intel_psr_enable() and intel_edp_drrs_enable() on pipe updates > > to make > > sure that we enable PSR / DRRS (when applicable) on fastsets. I am probably missing something, doesn't intel_pipe_config_compare() need to check for pipe_config->has_psr? And also read the hardware PSR state at boot? > > > > Note calling these functions when PSR / DRRS has already been > > enabled is a > > no-op, so it is safe to do this on every encoder->update_pipe > > callback. > > > > Changes in v2: > > -Merge the patches adding the intel_psr_enable() and > > intel_edp_drrs_enable() > > calls into a single patch > > > > Reviewed-by: Maarten Lankhorst > > Signed-off-by: Hans de Goede > > Cc: Dhinakaran Pandiyan > Cc: José Roberto de Souza > > Acked-by: Rodrigo Vivi > > > --- > > drivers/gpu/drm/i915/intel_ddi.c | 19 +++ > > 1 file changed, 19 insertions(+) > > > > diff --git a/drivers/gpu/drm/i915/intel_ddi.c > > b/drivers/gpu/drm/i915/intel_ddi.c > > index e3cc19e19199..fdf57f451b72 100644 > > --- a/drivers/gpu/drm/i915/intel_ddi.c > > +++ b/drivers/gpu/drm/i915/intel_ddi.c > > @@ -3537,6 +3537,24 @@ static void intel_disable_ddi(struct > > intel_encoder *encoder, > > intel_disable_ddi_dp(encoder, old_crtc_state, > > old_conn_state); > > } > > > > +static void intel_ddi_update_pipe_dp(struct intel_encoder > > *encoder, > > +const struct intel_crtc_state > > *crtc_state, > > +const struct drm_connector_state > > *conn_state) > > +{ > > + struct intel_dp *intel_dp = enc_to_intel_dp(>base); > > + > > + intel_psr_enable(intel_dp, crtc_state); > > + intel_edp_drrs_enable(intel_dp, crtc_state); > > +} > > + > > +static void intel_ddi_update_pipe(struct intel_encoder *encoder, > > + const struct intel_crtc_state > > *crtc_state, > > + const struct drm_connector_state > > *conn_state) > > +{ > > + if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) We could restrict this to eDP outputs as both PSR and DRRS are eDP features. > > + intel_ddi_update_pipe_dp(encoder, crtc_state, > > conn_state); > > +} > > + > > static void intel_ddi_set_fia_lane_count(struct intel_encoder > > *encoder, > > const struct intel_crtc_state > > *pipe_config, > > enum port port) > > @@ -4169,6 +4187,7 @@ void intel_ddi_init(struct drm_i915_private > > *dev_priv, enum port port) > > intel_encoder->pre_enable = intel_ddi_pre_enable; > > intel_encoder->disable = intel_disable_ddi; > > intel_encoder->post_disable = intel_ddi_post_disable; > > + intel_encoder->update_pipe = intel_ddi_update_pipe; > > intel_encoder->get_hw_state = intel_ddi_get_hw_state; > > intel_encoder->get_config = intel_ddi_get_config; > > intel_encoder->suspend = intel_ddi_encoder_suspend; > > -- > > 2.20.1 > > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH 2/4] drm/i915: Use drm_hdmi_avi_infoframe_quant_range() for SDVO HDMI as well
On Thu, 2018-12-13 at 15:09 -0800, Dhinakaran Pandiyan wrote: > On Thu, 2018-12-13 at 07:18 +0200, Ville Syrjälä wrote: > > On Wed, Dec 12, 2018 at 04:32:02PM -0800, Dhinakaran Pandiyan > > wrote: > > > On Tue, 2018-11-20 at 18:13 +0200, Ville Syrjala wrote: > > > > From: Ville Syrjälä > > > > > > > > Fill out the AVI infoframe quantization range bits using > > > > drm_hdmi_avi_infoframe_quant_range() for SDVO HDMI encoder as > > > > well. > > > > > > > > Signed-off-by: Ville Syrjälä > > > > --- > > > > drivers/gpu/drm/i915/intel_sdvo.c | 19 ++- > > > > 1 file changed, 10 insertions(+), 9 deletions(-) > > > > > > > > diff --git a/drivers/gpu/drm/i915/intel_sdvo.c > > > > b/drivers/gpu/drm/i915/intel_sdvo.c > > > > index 1277d31adb54..9c16e273fb8d 100644 > > > > --- a/drivers/gpu/drm/i915/intel_sdvo.c > > > > +++ b/drivers/gpu/drm/i915/intel_sdvo.c > > > > @@ -984,6 +984,8 @@ static bool > > > > intel_sdvo_set_avi_infoframe(struct > > > > intel_sdvo *intel_sdvo, > > > > const struct > > > > intel_crtc_state > > > > *pipe_config, > > > > const struct > > > > drm_connector_state *conn_state) > > > > { > > > > + const struct drm_display_mode *adjusted_mode = > > > > + _config->base.adjusted_mode; > > > > uint8_t sdvo_data[HDMI_INFOFRAME_SIZE(AVI)]; > > > > union hdmi_infoframe frame; > > > > int ret; > > > > @@ -991,20 +993,19 @@ static bool > > > > intel_sdvo_set_avi_infoframe(struct > > > > intel_sdvo *intel_sdvo, > > > > > > > > ret = > > > > drm_hdmi_avi_infoframe_from_display_mode(, > > > >conn_sta > > > > te- > > > > > connector, > > > > > > > > - _co > > > > nfig- > > > > > base.adjusted_mode); > > > > > > > > + adjusted > > > > _mode); > > > > if (ret < 0) { > > > > DRM_ERROR("couldn't fill AVI infoframe\n"); > > > > return false; > > > > } > > > > > > > > - if (intel_sdvo->rgb_quant_range_selectable) { > > > > - if (pipe_config->limited_color_range) > > > > - frame.avi.quantization_range = > > > > - HDMI_QUANTIZATION_RANGE_LIMITED > > > > ; > > > > - else > > > > - frame.avi.quantization_range = > > > > - HDMI_QUANTIZATION_RANGE_FULL; > > > > - } > > > > + drm_hdmi_avi_infoframe_quant_range(, > > > > + conn_state- > > > > >connector, > > > > + adjusted_mode, > > > > + pipe_config- > > > > > limited_color_range ? > > > > > > > > + rgb_quant_range_sele > > > > ctableTE > > > > D : > > > > + HDMI_QUANTIZATION_RA > > > > NGE_FULL > > > > , > > > > + intel_sdvo- > > > > > rgb_quant_range_selectable); > > > > > > Seems like avi.quantization_range can now get set to _LIMITED or > > > _FULL > > > even when ->rgb_quant_range_selectable == false, i.e., it is not > > > _DEFAULT anymore. Is that change in behavior intended? > > > > ->quant_range_selectable will be passed to > > drm_hdmi_avi_infoframe_quant_range() which will do the right thing > > with > > it. > > > > That said, there is a slight behavioural change in that it will set > > Okay, I was indeed referring to this case. > > > the Q bit even with QS==1 iff the quantization range matches the > > default quantization range for the mode. I noted this in the radeon > > patch but forgot to mention it here. > > I'll let someone else with knowledge of HDMI to review this > behavioral > change. I'm trying to get hold of the HDMI spec now and will review > if > this hasn't been looked at by then. > Looks alright now that I went through the specs. With commit message updated to make note of the Q value changes Reviewed-by: Dhinakaran Pandiyan > > > > > > > > > > > > > > > > > len = hdmi_infoframe_pack(, sdvo_data, > > > > sizeof(sdvo_data)); > > > > if (len < 0) > > > > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH 2/4] drm/i915: Use drm_hdmi_avi_infoframe_quant_range() for SDVO HDMI as well
On Thu, 2018-12-13 at 07:18 +0200, Ville Syrjälä wrote: > On Wed, Dec 12, 2018 at 04:32:02PM -0800, Dhinakaran Pandiyan wrote: > > On Tue, 2018-11-20 at 18:13 +0200, Ville Syrjala wrote: > > > From: Ville Syrjälä > > > > > > Fill out the AVI infoframe quantization range bits using > > > drm_hdmi_avi_infoframe_quant_range() for SDVO HDMI encoder as > > > well. > > > > > > Signed-off-by: Ville Syrjälä > > > --- > > > drivers/gpu/drm/i915/intel_sdvo.c | 19 ++- > > > 1 file changed, 10 insertions(+), 9 deletions(-) > > > > > > diff --git a/drivers/gpu/drm/i915/intel_sdvo.c > > > b/drivers/gpu/drm/i915/intel_sdvo.c > > > index 1277d31adb54..9c16e273fb8d 100644 > > > --- a/drivers/gpu/drm/i915/intel_sdvo.c > > > +++ b/drivers/gpu/drm/i915/intel_sdvo.c > > > @@ -984,6 +984,8 @@ static bool > > > intel_sdvo_set_avi_infoframe(struct > > > intel_sdvo *intel_sdvo, > > >const struct intel_crtc_state > > > *pipe_config, > > >const struct > > > drm_connector_state *conn_state) > > > { > > > + const struct drm_display_mode *adjusted_mode = > > > + _config->base.adjusted_mode; > > > uint8_t sdvo_data[HDMI_INFOFRAME_SIZE(AVI)]; > > > union hdmi_infoframe frame; > > > int ret; > > > @@ -991,20 +993,19 @@ static bool > > > intel_sdvo_set_avi_infoframe(struct > > > intel_sdvo *intel_sdvo, > > > > > > ret = drm_hdmi_avi_infoframe_from_display_mode(, > > > conn_state- > > > > connector, > > > > > > -_config- > > > > base.adjusted_mode); > > > > > > +adjusted_mode); > > > if (ret < 0) { > > > DRM_ERROR("couldn't fill AVI infoframe\n"); > > > return false; > > > } > > > > > > - if (intel_sdvo->rgb_quant_range_selectable) { > > > - if (pipe_config->limited_color_range) > > > - frame.avi.quantization_range = > > > - HDMI_QUANTIZATION_RANGE_LIMITED; > > > - else > > > - frame.avi.quantization_range = > > > - HDMI_QUANTIZATION_RANGE_FULL; > > > - } > > > + drm_hdmi_avi_infoframe_quant_range(, > > > +conn_state->connector, > > > +adjusted_mode, > > > +pipe_config- > > > > limited_color_range ? > > > > > > +rgb_quant_range_selectableTE > > > D : > > > +HDMI_QUANTIZATION_RANGE_FULL > > > , > > > +intel_sdvo- > > > > rgb_quant_range_selectable); > > > > Seems like avi.quantization_range can now get set to _LIMITED or > > _FULL > > even when ->rgb_quant_range_selectable == false, i.e., it is not > > _DEFAULT anymore. Is that change in behavior intended? > > ->quant_range_selectable will be passed to > drm_hdmi_avi_infoframe_quant_range() which will do the right thing > with > it. > > That said, there is a slight behavioural change in that it will set Okay, I was indeed referring to this case. > the Q bit even with QS==1 iff the quantization range matches the > default quantization range for the mode. I noted this in the radeon > patch but forgot to mention it here. I'll let someone else with knowledge of HDMI to review this behavioral change. I'm trying to get hold of the HDMI spec now and will review if this hasn't been looked at by then. > > > > > > > > > > > len = hdmi_infoframe_pack(, sdvo_data, > > > sizeof(sdvo_data)); > > > if (len < 0) > > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH 2/4] drm/i915: Use drm_hdmi_avi_infoframe_quant_range() for SDVO HDMI as well
On Tue, 2018-11-20 at 18:13 +0200, Ville Syrjala wrote: > From: Ville Syrjälä > > Fill out the AVI infoframe quantization range bits using > drm_hdmi_avi_infoframe_quant_range() for SDVO HDMI encoder as well. > > Signed-off-by: Ville Syrjälä > --- > drivers/gpu/drm/i915/intel_sdvo.c | 19 ++- > 1 file changed, 10 insertions(+), 9 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_sdvo.c > b/drivers/gpu/drm/i915/intel_sdvo.c > index 1277d31adb54..9c16e273fb8d 100644 > --- a/drivers/gpu/drm/i915/intel_sdvo.c > +++ b/drivers/gpu/drm/i915/intel_sdvo.c > @@ -984,6 +984,8 @@ static bool intel_sdvo_set_avi_infoframe(struct > intel_sdvo *intel_sdvo, >const struct intel_crtc_state > *pipe_config, >const struct > drm_connector_state *conn_state) > { > + const struct drm_display_mode *adjusted_mode = > + _config->base.adjusted_mode; > uint8_t sdvo_data[HDMI_INFOFRAME_SIZE(AVI)]; > union hdmi_infoframe frame; > int ret; > @@ -991,20 +993,19 @@ static bool intel_sdvo_set_avi_infoframe(struct > intel_sdvo *intel_sdvo, > > ret = drm_hdmi_avi_infoframe_from_display_mode(, > conn_state- > >connector, > -_config- > >base.adjusted_mode); > +adjusted_mode); > if (ret < 0) { > DRM_ERROR("couldn't fill AVI infoframe\n"); > return false; > } > > - if (intel_sdvo->rgb_quant_range_selectable) { > - if (pipe_config->limited_color_range) > - frame.avi.quantization_range = > - HDMI_QUANTIZATION_RANGE_LIMITED; > - else > - frame.avi.quantization_range = > - HDMI_QUANTIZATION_RANGE_FULL; > - } > + drm_hdmi_avi_infoframe_quant_range(, > +conn_state->connector, > +adjusted_mode, > +pipe_config- > >limited_color_range ? > +rgb_quant_range_selectableTE > D : > +HDMI_QUANTIZATION_RANGE_FULL > , > +intel_sdvo- > >rgb_quant_range_selectable); Seems like avi.quantization_range can now get set to _LIMITED or _FULL even when ->rgb_quant_range_selectable == false, i.e., it is not _DEFAULT anymore. Is that change in behavior intended? > > len = hdmi_infoframe_pack(, sdvo_data, > sizeof(sdvo_data)); > if (len < 0) ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH 3/5] drm/dp: Implement I2C_M_STOP for i2c-over-aux
On Fri, 2018-09-28 at 21:04 +0300, Ville Syrjala wrote: > From: Ville Syrjälä > > Consult the I2C_M_STOP flag to determine whether to set the MOT bit > or > not. Makes it possible to send multiple messages in one go with > stop+start generated between the messages (as opposed nothing or > repstart depending on whether thr address/rw changed). > > Not sure anyone has actual use for this but figured I'd handle it > since I started to look at that flag for MST remote i2c xfers. > Don't see the I2C_M_STOP flag anywhere in drm_edid.c, but the change introduced here does make sense. Reviewed-by: Dhinakaran Pandiyan > Signed-off-by: Ville Syrjälä > --- > drivers/gpu/drm/drm_dp_helper.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/drm_dp_helper.c > b/drivers/gpu/drm/drm_dp_helper.c > index 37c01b6076ec..e85cea299d2a 100644 > --- a/drivers/gpu/drm/drm_dp_helper.c > +++ b/drivers/gpu/drm/drm_dp_helper.c > @@ -884,7 +884,8 @@ static void drm_dp_i2c_msg_set_request(struct > drm_dp_aux_msg *msg, > { > msg->request = (i2c_msg->flags & I2C_M_RD) ? > DP_AUX_I2C_READ : DP_AUX_I2C_WRITE; > - msg->request |= DP_AUX_I2C_MOT; > + if (!(i2c_msg->flags & I2C_M_STOP)) > + msg->request |= DP_AUX_I2C_MOT; > } > > /* ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/dp: Set the MOT bit for Write_Status_Update_Request transactions
On Mon, 2018-12-10 at 23:29 +0200, Ville Syrjälä wrote: > On Mon, Dec 10, 2018 at 01:07:49PM -0800, Dhinakaran Pandiyan wrote: > > The Write_Status_Update_Request I2C transaction requires the MOT > > bit to > > be set, Change the logical AND to OR to fix what looks like a typo. > > It's not a type. We're just preserving MOT. What makes you think it > should always be set? > The table defining request commands (2-148) has the MOT bit set for Write_Status_Update_Request, doesn't make it look like an option when querying the status. Checking the callers again, I see that we could get a defer when ending an i2c transaction and that will require a Write_Status_Update_Request with MOT unset. Sorry for the noise. > > > > Cc: dri-devel@lists.freedesktop.org > > Cc: Jani Nikula > > Cc: Ville Syrjälä > > Fixes: 68ec2a2a2481 ("drm/dp: Use I2C_WRITE_STATUS_UPDATE to drain > > partial I2C_WRITE requests") > > Signed-off-by: Dhinakaran Pandiyan > > --- > > drivers/gpu/drm/drm_dp_helper.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/drm_dp_helper.c > > b/drivers/gpu/drm/drm_dp_helper.c > > index 2d6c491a0542..d98805b517f0 100644 > > --- a/drivers/gpu/drm/drm_dp_helper.c > > +++ b/drivers/gpu/drm/drm_dp_helper.c > > @@ -677,7 +677,7 @@ static void > > drm_dp_i2c_msg_write_status_update(struct drm_dp_aux_msg *msg) > > * rest of the message > > */ > > if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_I2C_WRITE) { > > - msg->request &= DP_AUX_I2C_MOT; > > + msg->request |= DP_AUX_I2C_MOT; > > msg->request |= DP_AUX_I2C_WRITE_STATUS_UPDATE; > > } > > } > > -- > > 2.17.1 > > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/dp: Set the MOT bit for Write_Status_Update_Request transactions
The Write_Status_Update_Request I2C transaction requires the MOT bit to be set, Change the logical AND to OR to fix what looks like a typo. Cc: dri-devel@lists.freedesktop.org Cc: Jani Nikula Cc: Ville Syrjälä Fixes: 68ec2a2a2481 ("drm/dp: Use I2C_WRITE_STATUS_UPDATE to drain partial I2C_WRITE requests") Signed-off-by: Dhinakaran Pandiyan --- drivers/gpu/drm/drm_dp_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 2d6c491a0542..d98805b517f0 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -677,7 +677,7 @@ static void drm_dp_i2c_msg_write_status_update(struct drm_dp_aux_msg *msg) * rest of the message */ if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_I2C_WRITE) { - msg->request &= DP_AUX_I2C_MOT; + msg->request |= DP_AUX_I2C_MOT; msg->request |= DP_AUX_I2C_WRITE_STATUS_UPDATE; } } -- 2.17.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH 1/5] drm/dp/mst: Configure no_stop_bit correctly for remote i2c xfers
On Mon, 2018-12-10 at 18:39 +0200, Ville Syrjälä wrote: > On Fri, Dec 07, 2018 at 12:45:25PM -0800, Dhinakaran Pandiyan wrote: > > On Fri, 2018-09-28 at 21:03 +0300, Ville Syrjala wrote: > > > From: Ville Syrjälä > > > > > > We aren't supposed to force a stop+start between every i2c msg > > > when performing multi message transfers. This should eg. cause > > > the DDC segment address to be reset back to 0 between writing > > > the segment address and reading the actual EDID extension block. > > > > > > To quote the E-DDC spec: > > > "... this standard requires that the segment pointer be > > > reset to 00h when a NO ACK or a STOP condition is received." > > > > Related question, do you know why the segment and ddc addresses are > > defined as 0x30 and 0x50? The E-DDC spec says they should be at > > 0x60 > > and 0xA0/0xA1. > > The spec uses 'slave_address << 1 | r/w'. Got it, thanks. -DK ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH 5/5] drm/dp/mst: Provide better debugs for NAK replies
On Fri, 2018-12-07 at 16:57 -0800, Dhinakaran Pandiyan wrote: > On Fri, 2018-09-28 at 21:04 +0300, Ville Syrjala wrote: > > From: Ville Syrjälä > > > > Decode the NAK reply fields to make it easier to parse the logs. > > A lot better than seeing the error codes. > > > 0-day's found a conflicting definition that's missing an undef. With > that addressed, > Reviewed-by: Dhinakaran Pandiyan > > > > Signed-off-by: Ville Syrjälä > > --- > > drivers/gpu/drm/drm_dp_mst_topology.c | 65 > > ++- > > include/drm/drm_dp_helper.h | 1 + > > 2 files changed, 65 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c > > b/drivers/gpu/drm/drm_dp_mst_topology.c > > index c0f754364cc7..1178c1655f9a 100644 > > --- a/drivers/gpu/drm/drm_dp_mst_topology.c > > +++ b/drivers/gpu/drm/drm_dp_mst_topology.c > > @@ -66,6 +66,64 @@ static bool drm_dp_validate_guid(struct > > drm_dp_mst_topology_mgr *mgr, > > static int drm_dp_mst_register_i2c_bus(struct drm_dp_aux *aux); > > static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_aux *aux); > > static void drm_dp_mst_kick_tx(struct drm_dp_mst_topology_mgr > > *mgr); > > + > > +#define STR(x) [DP_ ## x] = #x > > + > > +static const char *drm_dp_mst_req_type_str(u8 req_type) > > +{ > > + static const char * const req_type_str[] = { > > + STR(GET_MSG_TRANSACTION_VERSION), > > + STR(LINK_ADDRESS), > > + STR(CONNECTION_STATUS_NOTIFY), > > + STR(ENUM_PATH_RESOURCES), > > + STR(ALLOCATE_PAYLOAD), > > + STR(QUERY_PAYLOAD), > > + STR(RESOURCE_STATUS_NOTIFY), > > + STR(CLEAR_PAYLOAD_ID_TABLE), > > + STR(REMOTE_DPCD_READ), > > + STR(REMOTE_DPCD_WRITE), > > + STR(REMOTE_I2C_READ), > > + STR(REMOTE_I2C_WRITE), > > + STR(POWER_UP_PHY), > > + STR(POWER_DOWN_PHY), > > + STR(SINK_EVENT_NOTIFY), > > + STR(QUERY_STREAM_ENC_STATUS), > > + }; > > + > > + if (req_type >= ARRAY_SIZE(req_type_str) || > > + !req_type_str[req_type]) > > + return "unknown"; > > + > > + return req_type_str[req_type]; > > +} drm_dp_sideband_parse_reply() could also use the decoded string. -DK ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH 5/5] drm/dp/mst: Provide better debugs for NAK replies
On Fri, 2018-09-28 at 21:04 +0300, Ville Syrjala wrote: > From: Ville Syrjälä > > Decode the NAK reply fields to make it easier to parse the logs. A lot better than seeing the error codes. 0-day's found a conflicting definition that's missing an undef. With that addressed, Reviewed-by: Dhinakaran Pandiyan > > Signed-off-by: Ville Syrjälä > --- > drivers/gpu/drm/drm_dp_mst_topology.c | 65 > ++- > include/drm/drm_dp_helper.h | 1 + > 2 files changed, 65 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c > b/drivers/gpu/drm/drm_dp_mst_topology.c > index c0f754364cc7..1178c1655f9a 100644 > --- a/drivers/gpu/drm/drm_dp_mst_topology.c > +++ b/drivers/gpu/drm/drm_dp_mst_topology.c > @@ -66,6 +66,64 @@ static bool drm_dp_validate_guid(struct > drm_dp_mst_topology_mgr *mgr, > static int drm_dp_mst_register_i2c_bus(struct drm_dp_aux *aux); > static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_aux *aux); > static void drm_dp_mst_kick_tx(struct drm_dp_mst_topology_mgr *mgr); > + > +#define STR(x) [DP_ ## x] = #x > + > +static const char *drm_dp_mst_req_type_str(u8 req_type) > +{ > + static const char * const req_type_str[] = { > + STR(GET_MSG_TRANSACTION_VERSION), > + STR(LINK_ADDRESS), > + STR(CONNECTION_STATUS_NOTIFY), > + STR(ENUM_PATH_RESOURCES), > + STR(ALLOCATE_PAYLOAD), > + STR(QUERY_PAYLOAD), > + STR(RESOURCE_STATUS_NOTIFY), > + STR(CLEAR_PAYLOAD_ID_TABLE), > + STR(REMOTE_DPCD_READ), > + STR(REMOTE_DPCD_WRITE), > + STR(REMOTE_I2C_READ), > + STR(REMOTE_I2C_WRITE), > + STR(POWER_UP_PHY), > + STR(POWER_DOWN_PHY), > + STR(SINK_EVENT_NOTIFY), > + STR(QUERY_STREAM_ENC_STATUS), > + }; > + > + if (req_type >= ARRAY_SIZE(req_type_str) || > + !req_type_str[req_type]) > + return "unknown"; > + > + return req_type_str[req_type]; > +} > + > +#undef STR > +#define STR(x) [DP_NAK_ ## x] = #x > + > +static const char *drm_dp_mst_nak_reason_str(u8 nak_reason) > +{ > + static const char * const nak_reason_str[] = { > + STR(WRITE_FAILURE), > + STR(INVALID_READ), > + STR(CRC_FAILURE), > + STR(BAD_PARAM), > + STR(DEFER), > + STR(LINK_FAILURE), > + STR(NO_RESOURCES), > + STR(DPCD_FAIL), > + STR(I2C_NAK), > + STR(ALLOCATE_FAIL), > + }; > + > + if (nak_reason >= ARRAY_SIZE(nak_reason_str) || > + !nak_reason_str[nak_reason]) > + return "unknown"; > + > + return nak_reason_str[nak_reason]; > +} > + > +#undef STR > + > /* sideband msg handling */ > static u8 drm_dp_msg_header_crc4(const uint8_t *data, size_t > num_nibbles) > { > @@ -2349,7 +2407,12 @@ static int drm_dp_mst_handle_down_rep(struct > drm_dp_mst_topology_mgr *mgr) > > drm_dp_sideband_parse_reply(>down_rep_recv, > >reply); > if (txmsg->reply.reply_type == DP_REPLY_NAK) { > - DRM_DEBUG_KMS("Got NAK reply: req 0x%02x, > reason 0x%02x, nak data 0x%02x\n", txmsg->reply.req_type, txmsg- > >reply.u.nak.reason, txmsg->reply.u.nak.nak_data); > + DRM_DEBUG_KMS("Got NAK reply: req 0x%02x (%s), > reason 0x%02x (%s), nak data 0x%02x\n", > + txmsg->reply.req_type, > + drm_dp_mst_req_type_str(txmsg- > >reply.req_type), > + txmsg->reply.u.nak.reason, > + drm_dp_mst_nak_reason_str(txmsg- > >reply.u.nak.reason), > + txmsg->reply.u.nak.nak_data); > } > > memset(>down_rep_recv, 0, sizeof(struct > drm_dp_sideband_msg_rx)); > diff --git a/include/drm/drm_dp_helper.h > b/include/drm/drm_dp_helper.h > index 2a0fd9d7066e..2453767246fb 100644 > --- a/include/drm/drm_dp_helper.h > +++ b/include/drm/drm_dp_helper.h > @@ -918,6 +918,7 @@ > #define DP_PEER_DEVICE_DP_LEGACY_CONV0x4 > > /* DP 1.2 MST sideband request names DP 1.2a Table 2-80 */ > +#define DP_GET_MSG_TRANSACTION_VERSION 0x00 /* DP 1.3 */ > #define DP_LINK_ADDRESS 0x01 > #define DP_CONNECTION_STATUS_NOTIFY 0x02 > #define DP_ENUM_PATH_RESOURCES 0x10 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH 4/5] drm/dp/mst: Provide defines for ACK vs. NAK reply type
== 1) { > + if (txmsg->reply.reply_type == DP_REPLY_NAK) { > DRM_DEBUG_KMS("Got NAK reply: req 0x%02x, > reason 0x%02x, nak data 0x%02x\n", txmsg->reply.req_type, txmsg- > >reply.u.nak.reason, txmsg->reply.u.nak.nak_data); > } > > @@ -3306,7 +3306,7 @@ static int drm_dp_mst_i2c_xfer(struct > i2c_adapter *adapter, struct i2c_msg *msgs > ret = drm_dp_mst_wait_tx_reply(mstb, txmsg); > if (ret > 0) { > > - if (txmsg->reply.reply_type == 1) { /* got a NAK back > */ > + if (txmsg->reply.reply_type == DP_REPLY_NAK) { > ret = -EREMOTEIO; > goto out; > } > diff --git a/include/drm/drm_dp_helper.h > b/include/drm/drm_dp_helper.h > index 2a3843f248cf..2a0fd9d7066e 100644 > --- a/include/drm/drm_dp_helper.h > +++ b/include/drm/drm_dp_helper.h > @@ -905,6 +905,10 @@ > #define DP_AUX_HDCP_KSV_FIFO 0x6802C > #define DP_AUX_HDCP_AINFO0x6803B > > +/* DP 1.2 MST sideband reply types */ > +#define DP_REPLY_ACK 0x00 > +#define DP_REPLY_NAK 0x01 > + bikeshed: How about calling these DP_SIDEBAND_ACK or DP_SIDEBAND_NAK to differentiate from native AUX replies? And also move it right next to the NAK reason definition. Will leave it to you if you want to implement those bikesheds, Reviewed-by: Dhinakaran Pandiyan > /* DP 1.2 Sideband message defines */ > /* peer device type - DP 1.2a Table 2-92 */ > #define DP_PEER_DEVICE_NONE 0x0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH 2/5] drm/dp/mst: Validate REMOTE_I2C_READ harder
On Fri, 2018-09-28 at 21:04 +0300, Ville Syrjala wrote: > From: Ville Syrjälä > > Make sure i2c msgs we're asked to transfer conform to the > requirements of REMOTE_I2C_READ. We were only checking that the > last message is a read, but we must also check that the preceding > messages are all writes. Also check that the length of each > message isn't too long. Right, the syntax for i2c_remote_read allows only 8 bits for length. Reviewed-by: Dhinakaran Pandiyan > > Signed-off-by: Ville Syrjälä > --- > drivers/gpu/drm/drm_dp_mst_topology.c | 25 ++--- > 1 file changed, 18 insertions(+), 7 deletions(-) > > diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c > b/drivers/gpu/drm/drm_dp_mst_topology.c > index 3b400eab18a2..a0652fc166c6 100644 > --- a/drivers/gpu/drm/drm_dp_mst_topology.c > +++ b/drivers/gpu/drm/drm_dp_mst_topology.c > @@ -3239,6 +3239,23 @@ void drm_dp_mst_topology_mgr_destroy(struct > drm_dp_mst_topology_mgr *mgr) > } > EXPORT_SYMBOL(drm_dp_mst_topology_mgr_destroy); > > +static bool remote_i2c_read_ok(const struct i2c_msg msgs[], int num) > +{ > + int i; > + > + if (num - 1 > DP_REMOTE_I2C_READ_MAX_TRANSACTIONS) > + return false; > + > + for (i = 0; i < num - 1; i++) { > + if (msgs[i].flags & I2C_M_RD || > + msgs[i].len > 0xff) > + return false; > + } > + > + return msgs[num - 1].flags & I2C_M_RD && > + msgs[num - 1].len <= 0xff; > +} > + > /* I2C device */ > static int drm_dp_mst_i2c_xfer(struct i2c_adapter *adapter, struct > i2c_msg *msgs, > int num) > @@ -3248,7 +3265,6 @@ static int drm_dp_mst_i2c_xfer(struct > i2c_adapter *adapter, struct i2c_msg *msgs > struct drm_dp_mst_branch *mstb; > struct drm_dp_mst_topology_mgr *mgr = port->mgr; > unsigned int i; > - bool reading = false; > struct drm_dp_sideband_msg_req_body msg; > struct drm_dp_sideband_msg_tx *txmsg = NULL; > int ret; > @@ -3257,12 +3273,7 @@ static int drm_dp_mst_i2c_xfer(struct > i2c_adapter *adapter, struct i2c_msg *msgs > if (!mstb) > return -EREMOTEIO; > > - /* construct i2c msg */ > - /* see if last msg is a read */ > - if (msgs[num - 1].flags & I2C_M_RD) > - reading = true; > - > - if (!reading || (num - 1 > > DP_REMOTE_I2C_READ_MAX_TRANSACTIONS)) { > + if (!remote_i2c_read_ok(msgs, num)) { > DRM_DEBUG_KMS("Unsupported I2C transaction for MST > device\n"); > ret = -EIO; > goto out; ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH 1/5] drm/dp/mst: Configure no_stop_bit correctly for remote i2c xfers
On Fri, 2018-12-07 at 12:45 -0800, Dhinakaran Pandiyan wrote: > On Fri, 2018-09-28 at 21:03 +0300, Ville Syrjala wrote: > > From: Ville Syrjälä > > > > We aren't supposed to force a stop+start between every i2c msg > > when performing multi message transfers. This should eg. cause > > the DDC segment address to be reset back to 0 between writing > > the segment address and reading the actual EDID extension block. > > > > To quote the E-DDC spec: > > "... this standard requires that the segment pointer be > > reset to 00h when a NO ACK or a STOP condition is received." > > Related question, do you know why the segment and ddc addresses are > defined as 0x30 and 0x50? The E-DDC spec says they should be at 0x60 > and 0xA0/0xA1. > > > > > Since we're going to touch this might as well consult the > > I2C_M_STOP flag to determine whether we want to force the stop > > or not. > > Reviewing this took a lot of spec reading than I expected. > > Setting the no_stop_bit after writing the segment address makes > sense. > I have one concern though. drm_do_probe_ddc_edid does not make use of > the I2C_M_STOP flag, which in turn means we won't reset the > no_stop_bit > at the end of edid read. Pass the i2c stop flag from the caller? > Never mind, the no_stop_bit is relevant only between i2c writes. Reviewed-by: Dhinakaran Pandiyan > > > > > Cc: Brian Vincent > > References: https://bugs.freedesktop.org/show_bug.cgi?id=108081 > > Signed-off-by: Ville Syrjälä > > --- > > drivers/gpu/drm/drm_dp_mst_topology.c | 1 + > > 1 file changed, 1 insertion(+) > > > > diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c > > b/drivers/gpu/drm/drm_dp_mst_topology.c > > index 5ff1d79b86c4..3b400eab18a2 100644 > > --- a/drivers/gpu/drm/drm_dp_mst_topology.c > > +++ b/drivers/gpu/drm/drm_dp_mst_topology.c > > @@ -3276,6 +3276,7 @@ static int drm_dp_mst_i2c_xfer(struct > > i2c_adapter *adapter, struct i2c_msg *msgs > > msg.u.i2c_read.transactions[i].i2c_dev_id = > > msgs[i].addr; > > msg.u.i2c_read.transactions[i].num_bytes = msgs[i].len; > > msg.u.i2c_read.transactions[i].bytes = msgs[i].buf; > > + msg.u.i2c_read.transactions[i].no_stop_bit = > > !(msgs[i].flags & I2C_M_STOP); > > } > > msg.u.i2c_read.read_i2c_device_id = msgs[num - 1].addr; > > msg.u.i2c_read.num_bytes_read = msgs[num - 1].len; ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH 1/5] drm/dp/mst: Configure no_stop_bit correctly for remote i2c xfers
On Fri, 2018-09-28 at 21:03 +0300, Ville Syrjala wrote: > From: Ville Syrjälä > > We aren't supposed to force a stop+start between every i2c msg > when performing multi message transfers. This should eg. cause > the DDC segment address to be reset back to 0 between writing > the segment address and reading the actual EDID extension block. > > To quote the E-DDC spec: > "... this standard requires that the segment pointer be > reset to 00h when a NO ACK or a STOP condition is received." Related question, do you know why the segment and ddc addresses are defined as 0x30 and 0x50? The E-DDC spec says they should be at 0x60 and 0xA0/0xA1. > > Since we're going to touch this might as well consult the > I2C_M_STOP flag to determine whether we want to force the stop > or not. Reviewing this took a lot of spec reading than I expected. Setting the no_stop_bit after writing the segment address makes sense. I have one concern though. drm_do_probe_ddc_edid does not make use of the I2C_M_STOP flag, which in turn means we won't reset the no_stop_bit at the end of edid read. Pass the i2c stop flag from the caller? > > Cc: Brian Vincent > References: https://bugs.freedesktop.org/show_bug.cgi?id=108081 > Signed-off-by: Ville Syrjälä > --- > drivers/gpu/drm/drm_dp_mst_topology.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c > b/drivers/gpu/drm/drm_dp_mst_topology.c > index 5ff1d79b86c4..3b400eab18a2 100644 > --- a/drivers/gpu/drm/drm_dp_mst_topology.c > +++ b/drivers/gpu/drm/drm_dp_mst_topology.c > @@ -3276,6 +3276,7 @@ static int drm_dp_mst_i2c_xfer(struct > i2c_adapter *adapter, struct i2c_msg *msgs > msg.u.i2c_read.transactions[i].i2c_dev_id = > msgs[i].addr; > msg.u.i2c_read.transactions[i].num_bytes = msgs[i].len; > msg.u.i2c_read.transactions[i].bytes = msgs[i].buf; > + msg.u.i2c_read.transactions[i].no_stop_bit = > !(msgs[i].flags & I2C_M_STOP); > } > msg.u.i2c_read.read_i2c_device_id = msgs[num - 1].addr; > msg.u.i2c_read.num_bytes_read = msgs[num - 1].len; ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm: Fix documentation generation for DP_DPCD_QUIRK_NO_PSR
On Wed, 2018-12-05 at 10:48 -0800, José Roberto de Souza wrote: > The DP_DPCD_QUIRK_NO_PSR comment is missing colon causing this > warning when generating kernel documentation. > > ./include/drm/drm_dp_helper.h:1374: warning: Incorrect use of kernel- > doc format: * @DP_DPCD_QUIRK_NO_PSR > Cc: dri-devel@lists.freedesktop.org Reviewed-by: Dhinakaran Pandiyan > Fixes: 7c5c641a930e (drm/i915: Disable PSR in Apple panels) > Cc: Dhinakaran Pandiyan > Signed-off-by: José Roberto de Souza > --- > include/drm/drm_dp_helper.h | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/include/drm/drm_dp_helper.h > b/include/drm/drm_dp_helper.h > index 18cfde45b8ed..c223c87ef119 100644 > --- a/include/drm/drm_dp_helper.h > +++ b/include/drm/drm_dp_helper.h > @@ -1370,7 +1370,7 @@ enum drm_dp_quirk { >*/ > DP_DPCD_QUIRK_CONSTANT_N, > /** > - * @DP_DPCD_QUIRK_NO_PSR > + * @DP_DPCD_QUIRK_NO_PSR: >* >* The device does not support PSR even if reports that it > supports or >* driver still need to implement proper handling for such > device. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 10/11] drm/i915: Improve PSR2 CTL macros
On Thu, 2018-11-29 at 18:25 -0800, José Roberto de Souza wrote: > - Reusing the EDP_PSR2_FRAME_BEFORE_SU_SHIFT in > EDP_PSR2_FRAME_BEFORE_SU > - Removing unused EDP_PSR2_FRAME_BEFORE_SU_MASK > - Adding EDP_PSR2_FRAME_BEFORE_SU_MAX > - Adding EDP_PSR2_IDLE_FRAME() > - Adding EDP_PSR2_IDLE_FRAME_MAX > > In the next patch the new macros will be used. > > Cc: Dhinakaran Pandiyan > Cc: Rodrigo Vivi > Signed-off-by: José Roberto de Souza > --- > drivers/gpu/drm/i915/i915_reg.h | 7 --- > 1 file changed, 4 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_reg.h > b/drivers/gpu/drm/i915/i915_reg.h > index d3ef97915455..9e46da5032c0 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -4216,10 +4216,11 @@ enum { > #define EDP_PSR2_TP2_TIME_50us (3 << 8) > #define EDP_PSR2_TP2_TIME_MASK (3 << 8) > #define EDP_PSR2_FRAME_BEFORE_SU_SHIFT 4 > -#define EDP_PSR2_FRAME_BEFORE_SU_MASK (0xf << 4) _MASKs are useful when we want to read back the register for debugging. So, I'm not fully convinced this is an improvement. Rodrigo, your thoughts on this? > -#define EDP_PSR2_FRAME_BEFORE_SU(a)((a) << 4) > -#define EDP_PSR2_IDLE_FRAME_MASK 0xf > +#define EDP_PSR2_FRAME_BEFORE_SU_MAX 0xf > +#define EDP_PSR2_FRAME_BEFORE_SU(a)((a) << > EDP_PSR2_FRAME_BEFORE_SU_SHIFT) > #define EDP_PSR2_IDLE_FRAME_SHIFT 0 > +#define EDP_PSR2_IDLE_FRAME_MAX0xf Not sure if this is better than re-using _MASK here. I'm sure there are places in the driver where we already do that. > +#define EDP_PSR2_IDLE_FRAME(a) ((a) << > EDP_PSR2_IDLE_FRAME_SHIFT) > > #define _PSR_EVENT_TRANS_A 0x60848 > #define _PSR_EVENT_TRANS_B 0x61848 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 01/11] drm/i915: Disable PSR in Apple panels
On Mon, 2018-12-03 at 12:14 -0800, Souza, Jose wrote: > On Fri, 2018-11-30 at 15:35 -0800, Dhinakaran Pandiyan wrote: > > On Thu, 2018-11-29 at 18:25 -0800, José Roberto de Souza wrote: > > > i915 yet don't support PSR in Apple panels, so lets keep it > > > disabled > > > while we work on that. > > > > > > v2: Renamed DP_DPCD_QUIRK_PSR_NOT_CURRENTLY_SUPPORTED to > > > DP_DPCD_QUIRK_NO_PSR (Ville) > > > > > > Fixes: 598c6cfe0690 (drm/i915/psr: Enable PSR1 on gen-9+ HW) > > > Cc: Ville Syrjälä > > > Cc: Rodrigo Vivi > > > Cc: Dhinakaran Pandiyan > > > Signed-off-by: José Roberto de Souza > > > --- > > > drivers/gpu/drm/drm_dp_helper.c | 2 ++ > > > drivers/gpu/drm/i915/intel_psr.c | 6 ++ > > > include/drm/drm_dp_helper.h | 1 + > > > 3 files changed, 9 insertions(+) > > > > > > diff --git a/drivers/gpu/drm/drm_dp_helper.c > > > b/drivers/gpu/drm/drm_dp_helper.c > > > index 2d6c491a0542..b00fd5ced0a0 100644 > > > --- a/drivers/gpu/drm/drm_dp_helper.c > > > +++ b/drivers/gpu/drm/drm_dp_helper.c > > > @@ -1273,6 +1273,8 @@ static const struct dpcd_quirk > > > dpcd_quirk_list[] = { > > > { OUI(0x00, 0x22, 0xb9), DEVICE_ID_ANY, true, > > > BIT(DP_DPCD_QUIRK_CONSTANT_N) }, > > > /* LG LP140WF6-SPM1 eDP panel */ > > > { OUI(0x00, 0x22, 0xb9), DEVICE_ID('s', 'i', 'v', 'a', 'r', > > > 'T'), false, BIT(DP_DPCD_QUIRK_CONSTANT_N) }, > > > + /* Apple panels needs some additional handling to support PSR > > > */ > > > + { OUI(0x00, 0x10, 0xfa), DEVICE_ID_ANY, false, > > > BIT(DP_DPCD_QUIRK_NO_PSR) } > > > }; > > > > > > #undef OUI > > > diff --git a/drivers/gpu/drm/i915/intel_psr.c > > > b/drivers/gpu/drm/i915/intel_psr.c > > > index 2084784f320d..40ca6cc43cc4 100644 > > > --- a/drivers/gpu/drm/i915/intel_psr.c > > > +++ b/drivers/gpu/drm/i915/intel_psr.c > > > @@ -278,6 +278,12 @@ void intel_psr_init_dpcd(struct intel_dp > > > *intel_dp) > > > DRM_DEBUG_KMS("Panel lacks power state control, PSR > > > cannot be enabled\n"); > > > return; > > > } > > > + > > > + if (drm_dp_has_quirk(_dp->desc, DP_DPCD_QUIRK_NO_PSR)) { > > > + DRM_DEBUG_KMS("PSR support not currently available for > > > this panel\n"); > > > + return; > > > + } > > > + > > > dev_priv->psr.sink_support = true; > > > dev_priv->psr.sink_sync_latency = > > > intel_dp_get_sink_sync_latency(intel_dp); > > > diff --git a/include/drm/drm_dp_helper.h > > > b/include/drm/drm_dp_helper.h > > > index 5736c942c85b..047314ce25d6 100644 > > > --- a/include/drm/drm_dp_helper.h > > > +++ b/include/drm/drm_dp_helper.h > > > @@ -1365,6 +1365,7 @@ enum drm_dp_quirk { > > >* to 16 bits. So will give a constant value (0x8000) for > > > compatability. > > >*/ > > > DP_DPCD_QUIRK_CONSTANT_N, > > > > nit: Documentation missing here. I guess we need something along > > the > > lines of "PSR not supported" without referring to the specific DP > > device. With that, > > Reviewed-by: Dhinakaran Pandiyan > > > Adding here: > > /** >* @DP_DPCD_QUIRK_NO_PSR >* >* The device don't properly support PSR even if reports that nit: "device does not support" > it >* supports or driver still need to implement proper handling ^needs > for such >* device. >*/ > > > > > > > > + DP_DPCD_QUIRK_NO_PSR, > > > }; > > > > > > /** ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 08/11] drm/i915/psr: Check if source supports sink specific SU granularity
On Thu, 2018-11-29 at 18:25 -0800, José Roberto de Souza wrote: > According to eDP spec, sink can required specific selective update > granularity that source must comply. > Here caching the value if required and checking if source supports > it. > > Cc: Rodrigo Vivi > Cc: Dhinakaran Pandiyan > Signed-off-by: José Roberto de Souza > --- > drivers/gpu/drm/i915/i915_drv.h | 1 + > drivers/gpu/drm/i915/intel_psr.c | 21 - > 2 files changed, 21 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h > b/drivers/gpu/drm/i915/i915_drv.h > index 43ac6873a2bb..0727d8051dd3 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -507,6 +507,7 @@ struct i915_psr { > ktime_t last_exit; > bool sink_not_reliable; > bool irq_aux_error; > + u16 su_x_granularity; > }; > > enum intel_pch { > diff --git a/drivers/gpu/drm/i915/intel_psr.c > b/drivers/gpu/drm/i915/intel_psr.c > index 282ff1bc68a7..f9eccaac850a 100644 > --- a/drivers/gpu/drm/i915/intel_psr.c > +++ b/drivers/gpu/drm/i915/intel_psr.c > @@ -261,6 +261,23 @@ static u8 intel_dp_get_sink_sync_latency(struct > intel_dp *intel_dp) > return val; > } > > +static u16 intel_dp_get_su_x_granulartiy(struct intel_dp *intel_dp) > +{ > + u16 val; > + ssize_t r; > + > + if (!(intel_dp->psr_dpcd[1] & DP_PSR2_SU_GRANULARITY_REQUIRED)) > { > + /* Returning the default X granularity */ > + return 4; > + } nit: Braces not needed, you could move the comment a line above. A value of 0 in this DPCD indicates there is no granularity requirement, why assume 4? > + > + r = drm_dp_dpcd_read(_dp->aux, DP_PSR2_SU_X_GRANULARITY, > , 2); > + if (r != 2) > + DRM_WARN("Unable to read DP_PSR2_SU_X_GRANULARITY\n"); Please change this to the warning level that we use elsewhere for aux failures. If I'm reading the spec correctly, a value of 0 in this DPCD means the sink expects a granularity of 4, so returning 0 would be incorrect. > + > + return val; Assume the default value of 4 if aux read fails (after printing an error) > +} > + > void intel_psr_init_dpcd(struct intel_dp *intel_dp) > { > struct drm_i915_private *dev_priv = > @@ -315,6 +332,8 @@ void intel_psr_init_dpcd(struct intel_dp > *intel_dp) > if (dev_priv->psr.sink_psr2_support) { > dev_priv->psr.colorimetry_support = > intel_dp_get_colorimetry_status(intel_d > p); > + dev_priv->psr.su_x_granularity = > + intel_dp_get_su_x_granulartiy(intel_dp) > ; > } > } > } > @@ -546,7 +565,7 @@ static bool intel_psr2_config_valid(struct > intel_dp *intel_dp, >* at each 4 lines with height of 4 lines, what eDP states >* that sink should support. >*/ > - if (crtc_hdisplay % 4) { > + if (crtc_hdisplay % dev_priv->psr.su_x_granularity) { > DRM_DEBUG_KMS("PSR2 not enabled, default SU granularity > not match\n"); > return false; > } ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 01/11] drm/i915: Disable PSR in Apple panels
On Fri, 2018-11-30 at 15:35 -0800, Dhinakaran Pandiyan wrote: > On Thu, 2018-11-29 at 18:25 -0800, José Roberto de Souza wrote: > > i915 yet don't support PSR in Apple panels, so lets keep it > > disabled > > while we work on that. > > > > v2: Renamed DP_DPCD_QUIRK_PSR_NOT_CURRENTLY_SUPPORTED to > > DP_DPCD_QUIRK_NO_PSR (Ville) > > > > Fixes: 598c6cfe0690 (drm/i915/psr: Enable PSR1 on gen-9+ HW) > > Cc: Ville Syrjälä > > Cc: Rodrigo Vivi > > Cc: Dhinakaran Pandiyan > > Signed-off-by: José Roberto de Souza > > --- > > drivers/gpu/drm/drm_dp_helper.c | 2 ++ > > drivers/gpu/drm/i915/intel_psr.c | 6 ++ > > include/drm/drm_dp_helper.h | 1 + > > 3 files changed, 9 insertions(+) > > > > diff --git a/drivers/gpu/drm/drm_dp_helper.c > > b/drivers/gpu/drm/drm_dp_helper.c > > index 2d6c491a0542..b00fd5ced0a0 100644 > > --- a/drivers/gpu/drm/drm_dp_helper.c > > +++ b/drivers/gpu/drm/drm_dp_helper.c > > @@ -1273,6 +1273,8 @@ static const struct dpcd_quirk > > dpcd_quirk_list[] = { > > { OUI(0x00, 0x22, 0xb9), DEVICE_ID_ANY, true, > > BIT(DP_DPCD_QUIRK_CONSTANT_N) }, > > /* LG LP140WF6-SPM1 eDP panel */ > > { OUI(0x00, 0x22, 0xb9), DEVICE_ID('s', 'i', 'v', 'a', 'r', > > 'T'), false, BIT(DP_DPCD_QUIRK_CONSTANT_N) }, > > + /* Apple panels needs some additional handling to support PSR > > */ > > + { OUI(0x00, 0x10, 0xfa), DEVICE_ID_ANY, false, > > BIT(DP_DPCD_QUIRK_NO_PSR) } > > }; > > > > #undef OUI > > diff --git a/drivers/gpu/drm/i915/intel_psr.c > > b/drivers/gpu/drm/i915/intel_psr.c > > index 2084784f320d..40ca6cc43cc4 100644 > > --- a/drivers/gpu/drm/i915/intel_psr.c > > +++ b/drivers/gpu/drm/i915/intel_psr.c > > @@ -278,6 +278,12 @@ void intel_psr_init_dpcd(struct intel_dp > > *intel_dp) > > DRM_DEBUG_KMS("Panel lacks power state control, PSR > > cannot be enabled\n"); > > return; > > } > > + > > + if (drm_dp_has_quirk(_dp->desc, DP_DPCD_QUIRK_NO_PSR)) { > > + DRM_DEBUG_KMS("PSR support not currently available for > > this panel\n"); > > + return; > > + } Another nitpick: While you make other changes, please also move this above the power state check. Checking for power state control is not very useful if we are never going to enable PSR on this panel. > > + > > dev_priv->psr.sink_support = true; > > dev_priv->psr.sink_sync_latency = > > intel_dp_get_sink_sync_latency(intel_dp); > > diff --git a/include/drm/drm_dp_helper.h > > b/include/drm/drm_dp_helper.h > > index 5736c942c85b..047314ce25d6 100644 > > --- a/include/drm/drm_dp_helper.h > > +++ b/include/drm/drm_dp_helper.h > > @@ -1365,6 +1365,7 @@ enum drm_dp_quirk { > > * to 16 bits. So will give a constant value (0x8000) for > > compatability. > > */ > > DP_DPCD_QUIRK_CONSTANT_N, > > nit: Documentation missing here. I guess we need something along the > lines of "PSR not supported" without referring to the specific DP > device. With that, > Reviewed-by: Dhinakaran Pandiyan > > > > + DP_DPCD_QUIRK_NO_PSR, > > }; > > > > /** ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 07/11] drm/i915/psr: Check if resolution is supported by default SU granularity
On Thu, 2018-11-29 at 18:25 -0800, José Roberto de Souza wrote: > Selective updates have a default granularity requirements as stated > by eDP spec Needs reference to the location in the spec. > , so check if HW can match those requirements before > enable PSR2. typo: enabling* > > Cc: Dhinakaran Pandiyan > Cc: Rodrigo Vivi > Signed-off-by: José Roberto de Souza > --- > drivers/gpu/drm/i915/intel_psr.c | 12 > 1 file changed, 12 insertions(+) > > diff --git a/drivers/gpu/drm/i915/intel_psr.c > b/drivers/gpu/drm/i915/intel_psr.c > index c4a8f476eea9..282ff1bc68a7 100644 > --- a/drivers/gpu/drm/i915/intel_psr.c > +++ b/drivers/gpu/drm/i915/intel_psr.c > @@ -539,6 +539,18 @@ static bool intel_psr2_config_valid(struct > intel_dp *intel_dp, > return false; > } > > + /* HW will always send full lines in SU blocks, so X will s/X/starting X coordinate > + * always be 0 and we only need to check the width to validate > + * horizontal granularity. > + * About vertical granularity HW works by SU blocks starting > + * at each 4 lines with height of 4 lines, what eDP states > + * that sink should support. How about rewriting this as - "HW sends SU blocks of size four scan lines, which means the starting X coordinate and Y granularity requirements will always be met. We only need to validate the SU block width is a multiple of 4."? > + */ > + if (crtc_hdisplay % 4) { > + DRM_DEBUG_KMS("PSR2 not enabled, default SU granularity > not match\n"); "PSR2 not enabled, hdisplay(%d) not multiple of 4\n" With nits addressed, Reviewed-by: Dhinakaran Pandiyan > + return false; > + } > + > return true; > } > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 06/11] drm: Add the PSR SU granularity registers offsets
On Thu, 2018-11-29 at 18:25 -0800, José Roberto de Souza wrote: > Source is required to comply to sink SU granularity when > DP_PSR2_SU_GRANULARITY_REQUIRED is set in DP_PSR_CAPS, > so adding the registers offsets. > > v2: Also adding DP_PSR2_SU_Y_GRANULARITY(Rodrigo) > > Cc: Dhinakaran Pandiyan > Cc: Rodrigo Vivi > Signed-off-by: José Roberto de Souza > --- > include/drm/drm_dp_helper.h | 4 > 1 file changed, 4 insertions(+) > > diff --git a/include/drm/drm_dp_helper.h > b/include/drm/drm_dp_helper.h > index 047314ce25d6..0e04b2db3dde 100644 > --- a/include/drm/drm_dp_helper.h > +++ b/include/drm/drm_dp_helper.h > @@ -314,6 +314,10 @@ > # define DP_PSR_SETUP_TIME_SHIFT1 > # define DP_PSR2_SU_Y_COORDINATE_REQUIRED (1 << 4) /* eDP 1.4a */ > # define DP_PSR2_SU_GRANULARITY_REQUIRED(1 << 5) /* eDP 1.4b */ > + > +#define DP_PSR2_SU_X_GRANULARITY 0x072 /* eDP 1.4b */ > +#define DP_PSR2_SU_Y_GRANULARITY 0x074 /* eDP 1.4b */ Definitions above use spaces instead of tabs, so it'd have been good to be consistent. But, there are places in the file where tabs are used too, so will leave it to you if you want to switch. > + Verified against eDP spec 1.4b Reviewed-by: Dhinakaran Pandiyan > /* > * 0x80-0x8f describe downstream port capabilities, but there are > two layouts > * based on whether DP_DETAILED_CAP_INFO_AVAILABLE was set. If it > was not, ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 04/11] drm/i915/psr: Enable sink to trigger a interruption on PSR2 CRC mismatch
On Thu, 2018-11-29 at 18:25 -0800, José Roberto de Souza wrote: > eDP spec states 2 different bits to enable sink to trigger a > interruption when there is a CRC mismatch. > DP_PSR_CRC_VERIFICATION is for PSR only and > DP_PSR_IRQ_HPD_WITH_CRC_ERRORS is for PSR2 only. With PSR short pulse handling implemented, I think we are ready for this. Reviewed-by: Dhinakaran Pandiyan > > Cc: Dhinakaran Pandiyan > Reviewed-by: Rodrigo Vivi > Signed-off-by: José Roberto de Souza > --- > drivers/gpu/drm/i915/intel_psr.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/intel_psr.c > b/drivers/gpu/drm/i915/intel_psr.c > index b04472e637c8..77162c469079 100644 > --- a/drivers/gpu/drm/i915/intel_psr.c > +++ b/drivers/gpu/drm/i915/intel_psr.c > @@ -394,7 +394,7 @@ static void intel_psr_enable_sink(struct intel_dp > *intel_dp) > if (dev_priv->psr.psr2_enabled) { > drm_dp_dpcd_writeb(_dp->aux, > DP_RECEIVER_ALPM_CONFIG, > DP_ALPM_ENABLE); > - dpcd_val |= DP_PSR_ENABLE_PSR2; > + dpcd_val |= DP_PSR_ENABLE_PSR2 | > DP_PSR_IRQ_HPD_WITH_CRC_ERRORS; > } else { > if (dev_priv->psr.link_standby) > dpcd_val |= DP_PSR_MAIN_LINK_ACTIVE; ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 03/11] drm/i915/psr: Set PSR CRC verification bit in sink inside PSR1 block
On Thu, 2018-11-29 at 18:25 -0800, José Roberto de Souza wrote: > As we have a else block for the 'if (dev_priv->psr.psr2_enabled) {' > and this bit is only set for PSR1 move it to that block to make it > more easy to read. > > Cc: Dhinakaran Pandiyan > Cc: Rodrigo Vivi > Signed-off-by: José Roberto de Souza > --- > drivers/gpu/drm/i915/intel_psr.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_psr.c > b/drivers/gpu/drm/i915/intel_psr.c > index 8515f4a6f4f1..b04472e637c8 100644 > --- a/drivers/gpu/drm/i915/intel_psr.c > +++ b/drivers/gpu/drm/i915/intel_psr.c > @@ -398,10 +398,11 @@ static void intel_psr_enable_sink(struct > intel_dp *intel_dp) > } else { > if (dev_priv->psr.link_standby) > dpcd_val |= DP_PSR_MAIN_LINK_ACTIVE; > + > + if (INTEL_GEN(dev_priv) >= 8) > + dpcd_val |= DP_PSR_CRC_VERIFICATION; > } > > - if (!dev_priv->psr.psr2_enabled && INTEL_GEN(dev_priv) >= 8) > - dpcd_val |= DP_PSR_CRC_VERIFICATION; > drm_dp_dpcd_writeb(_dp->aux, DP_PSR_EN_CFG, dpcd_val); > > drm_dp_dpcd_writeb(_dp->aux, DP_SET_POWER, > DP_SET_POWER_D0); Do we need this DPCD write? The panel should already be awake by this point, I think it's worth removing it if there's no regression. Your change in this patch looks good, so Reviewed-by: Dhinakaran Pandiyan ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 02/11] drm/i915/psr: Don't tell sink that main link will be active while is active PSR2
On Thu, 2018-11-29 at 18:25 -0800, José Roberto de Souza wrote: > For PSR2 there is no register to tell HW to keep main link enabled Right, there is no bit in PSR2_CTL Reviewed-by: Dhinakaran Pandiyan > while PSR2 is active, so don't configure sink DPCD with a > misleading value. > > v2: Moving the set of DP_PSR_CRC_VERIFICATION to the else block > of 'if (dev_priv->psr.psr2_enabled)' to another patch. (Rodrigo) > > Cc: Dhinakaran Pandiyan > Cc: Rodrigo Vivi > Signed-off-by: José Roberto de Souza > --- > drivers/gpu/drm/i915/intel_psr.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_psr.c > b/drivers/gpu/drm/i915/intel_psr.c > index 40ca6cc43cc4..8515f4a6f4f1 100644 > --- a/drivers/gpu/drm/i915/intel_psr.c > +++ b/drivers/gpu/drm/i915/intel_psr.c > @@ -395,10 +395,11 @@ static void intel_psr_enable_sink(struct > intel_dp *intel_dp) > drm_dp_dpcd_writeb(_dp->aux, > DP_RECEIVER_ALPM_CONFIG, > DP_ALPM_ENABLE); > dpcd_val |= DP_PSR_ENABLE_PSR2; > + } else { > + if (dev_priv->psr.link_standby) > + dpcd_val |= DP_PSR_MAIN_LINK_ACTIVE; > } > > - if (dev_priv->psr.link_standby) > - dpcd_val |= DP_PSR_MAIN_LINK_ACTIVE; > if (!dev_priv->psr.psr2_enabled && INTEL_GEN(dev_priv) >= 8) > dpcd_val |= DP_PSR_CRC_VERIFICATION; > drm_dp_dpcd_writeb(_dp->aux, DP_PSR_EN_CFG, dpcd_val); ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 01/11] drm/i915: Disable PSR in Apple panels
On Thu, 2018-11-29 at 18:25 -0800, José Roberto de Souza wrote: > i915 yet don't support PSR in Apple panels, so lets keep it disabled > while we work on that. > > v2: Renamed DP_DPCD_QUIRK_PSR_NOT_CURRENTLY_SUPPORTED to > DP_DPCD_QUIRK_NO_PSR (Ville) > > Fixes: 598c6cfe0690 (drm/i915/psr: Enable PSR1 on gen-9+ HW) > Cc: Ville Syrjälä > Cc: Rodrigo Vivi > Cc: Dhinakaran Pandiyan > Signed-off-by: José Roberto de Souza > --- > drivers/gpu/drm/drm_dp_helper.c | 2 ++ > drivers/gpu/drm/i915/intel_psr.c | 6 ++ > include/drm/drm_dp_helper.h | 1 + > 3 files changed, 9 insertions(+) > > diff --git a/drivers/gpu/drm/drm_dp_helper.c > b/drivers/gpu/drm/drm_dp_helper.c > index 2d6c491a0542..b00fd5ced0a0 100644 > --- a/drivers/gpu/drm/drm_dp_helper.c > +++ b/drivers/gpu/drm/drm_dp_helper.c > @@ -1273,6 +1273,8 @@ static const struct dpcd_quirk > dpcd_quirk_list[] = { > { OUI(0x00, 0x22, 0xb9), DEVICE_ID_ANY, true, > BIT(DP_DPCD_QUIRK_CONSTANT_N) }, > /* LG LP140WF6-SPM1 eDP panel */ > { OUI(0x00, 0x22, 0xb9), DEVICE_ID('s', 'i', 'v', 'a', 'r', > 'T'), false, BIT(DP_DPCD_QUIRK_CONSTANT_N) }, > + /* Apple panels needs some additional handling to support PSR > */ > + { OUI(0x00, 0x10, 0xfa), DEVICE_ID_ANY, false, > BIT(DP_DPCD_QUIRK_NO_PSR) } > }; > > #undef OUI > diff --git a/drivers/gpu/drm/i915/intel_psr.c > b/drivers/gpu/drm/i915/intel_psr.c > index 2084784f320d..40ca6cc43cc4 100644 > --- a/drivers/gpu/drm/i915/intel_psr.c > +++ b/drivers/gpu/drm/i915/intel_psr.c > @@ -278,6 +278,12 @@ void intel_psr_init_dpcd(struct intel_dp > *intel_dp) > DRM_DEBUG_KMS("Panel lacks power state control, PSR > cannot be enabled\n"); > return; > } > + > + if (drm_dp_has_quirk(_dp->desc, DP_DPCD_QUIRK_NO_PSR)) { > + DRM_DEBUG_KMS("PSR support not currently available for > this panel\n"); > + return; > + } > + > dev_priv->psr.sink_support = true; > dev_priv->psr.sink_sync_latency = > intel_dp_get_sink_sync_latency(intel_dp); > diff --git a/include/drm/drm_dp_helper.h > b/include/drm/drm_dp_helper.h > index 5736c942c85b..047314ce25d6 100644 > --- a/include/drm/drm_dp_helper.h > +++ b/include/drm/drm_dp_helper.h > @@ -1365,6 +1365,7 @@ enum drm_dp_quirk { >* to 16 bits. So will give a constant value (0x8000) for > compatability. > */ > DP_DPCD_QUIRK_CONSTANT_N, nit: Documentation missing here. I guess we need something along the lines of "PSR not supported" without referring to the specific DP device. With that, Reviewed-by: Dhinakaran Pandiyan > + DP_DPCD_QUIRK_NO_PSR, > }; > > /** ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH 1/9] drm/i915: Disable PSR in Apple panels
On Tue, 2018-11-27 at 13:55 -0800, Souza, Jose wrote: > On Tue, 2018-11-27 at 15:38 +0200, Ville Syrjälä wrote: > > On Mon, Nov 26, 2018 at 04:37:02PM -0800, José Roberto de Souza > > wrote: > > > i915 yet don't support PSR in Apple panels, so lets keep Replace "Apple" with specific model name? > > > disabled > > > while we work on that. > > > > > > Fixes: 598c6cfe0690 (drm/i915/psr: Enable PSR1 on gen-9+ HW) Bugzilla please. Also Cc the bug reporter? > > > Cc: Rodrigo Vivi > > > Cc: Dhinakaran Pandiyan > > > Signed-off-by: José Roberto de Souza > > > --- > > > drivers/gpu/drm/drm_dp_helper.c | 2 ++ > > > drivers/gpu/drm/i915/intel_psr.c | 6 ++ > > > include/drm/drm_dp_helper.h | 1 + > > > 3 files changed, 9 insertions(+) > > > > > > diff --git a/drivers/gpu/drm/drm_dp_helper.c > > > b/drivers/gpu/drm/drm_dp_helper.c > > > index 6d483487f2b4..6b5a19d3e347 100644 > > > --- a/drivers/gpu/drm/drm_dp_helper.c > > > +++ b/drivers/gpu/drm/drm_dp_helper.c > > > @@ -1273,6 +1273,8 @@ static const struct dpcd_quirk > > > dpcd_quirk_list[] = { > > > { OUI(0x00, 0x22, 0xb9), DEVICE_ID_ANY, true, > > > BIT(DP_DPCD_QUIRK_CONSTANT_N) }, > > > /* LG LP140WF6-SPM1 eDP panel */ > > > { OUI(0x00, 0x22, 0xb9), DEVICE_ID('s', 'i', 'v', 'a', 'r', > > > 'T'), false, BIT(DP_DPCD_QUIRK_CONSTANT_N) }, > > > + /* Apple panels needs some additional handling to support PSR > > > */ > > > + { OUI(0x00, 0x10, 0xfa), DEVICE_ID_ANY, false, > > > BIT(DP_DPCD_QUIRK_PSR_NOT_CURRENTLY_SUPPORTED) } > > > }; > > > > > > #undef OUI > > > diff --git a/drivers/gpu/drm/i915/intel_psr.c > > > b/drivers/gpu/drm/i915/intel_psr.c > > > index 572e626eadff..f5d27a02eb28 100644 > > > --- a/drivers/gpu/drm/i915/intel_psr.c > > > +++ b/drivers/gpu/drm/i915/intel_psr.c > > > @@ -274,6 +274,12 @@ void intel_psr_init_dpcd(struct intel_dp > > > *intel_dp) > > > DRM_DEBUG_KMS("Panel lacks power state control, PSR > > > cannot be enabled\n"); > > > return; > > > } > > > + > > > + if (drm_dp_has_quirk(_dp->desc, > > > DP_DPCD_QUIRK_PSR_NOT_CURRENTLY_SUPPORTED)) { > > > + DRM_DEBUG_KMS("PSR support not currently available for > > > this panel\n"); > > > + return; > > > + } > > > + > > > dev_priv->psr.sink_support = true; > > > dev_priv->psr.sink_sync_latency = > > > intel_dp_get_sink_sync_latency(intel_dp); > > > diff --git a/include/drm/drm_dp_helper.h > > > b/include/drm/drm_dp_helper.h > > > index 3314e91f6eb3..db516c48cda3 100644 > > > --- a/include/drm/drm_dp_helper.h > > > +++ b/include/drm/drm_dp_helper.h > > > @@ -1364,6 +1364,7 @@ enum drm_dp_quirk { > > >* to 16 bits. So will give a constant value (0x8000) for > > > compatability. > > >*/ > > > DP_DPCD_QUIRK_CONSTANT_N, > > > + DP_DPCD_QUIRK_PSR_NOT_CURRENTLY_SUPPORTED, > > > > Why such a convoluted name? DP_DPCD_QUIRK_NO_PSR? > > Okay changing to DP_DPCD_QUIRK_NO_PSR. > > > > > > }; > > > > > > /** > > > -- > > > 2.19.2 > > > > > > ___ > > > Intel-gfx mailing list > > > intel-...@lists.freedesktop.org > > > https://lists.freedesktop.org/mailman/listinfo/intel-gfx ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 3/9] drm/i915/psr: Enable sink to trigger a interruption on PSR2 CRC mismatch
On Thu, 2018-11-29 at 14:04 -0800, Rodrigo Vivi wrote: > On Mon, Nov 26, 2018 at 04:37:04PM -0800, José Roberto de Souza > wrote: > > eDP spec states 2 different bits to enable sink to trigger a > > interruption when there is a CRC mismatch. > > DP_PSR_CRC_VERIFICATION is for PSR only and > > DP_PSR_IRQ_HPD_WITH_CRC_ERRORS is for PSR2 only. > > > > Cc: Dhinakaran Pandiyan > > Cc: Rodrigo Vivi > > Signed-off-by: José Roberto de Souza > > --- > > drivers/gpu/drm/i915/intel_psr.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/i915/intel_psr.c > > b/drivers/gpu/drm/i915/intel_psr.c > > index 888e348cc1b4..607c3ec41679 100644 > > --- a/drivers/gpu/drm/i915/intel_psr.c > > +++ b/drivers/gpu/drm/i915/intel_psr.c > > @@ -390,7 +390,7 @@ static void intel_psr_enable_sink(struct > > intel_dp *intel_dp) > > if (dev_priv->psr.psr2_enabled) { > > drm_dp_dpcd_writeb(_dp->aux, > > DP_RECEIVER_ALPM_CONFIG, > >DP_ALPM_ENABLE); > > - dpcd_val |= DP_PSR_ENABLE_PSR2; > > + dpcd_val |= DP_PSR_ENABLE_PSR2 | > > DP_PSR_IRQ_HPD_WITH_CRC_ERRORS; > > good catch! > > > Reviewed-by: Rodrigo Vivi Is there a commit that this patch Fixes? > > > > > } else { > > if (dev_priv->psr.link_standby) > > dpcd_val |= DP_PSR_MAIN_LINK_ACTIVE; > > -- > > 2.19.2 > > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 9/9] drm/i915: Remove old PSR2 FIXME about frontbuffer tracking
On Thu, 2018-11-29 at 15:11 -0800, Rodrigo Vivi wrote: > On Mon, Nov 26, 2018 at 04:37:10PM -0800, José Roberto de Souza > wrote: > > Our frontbuffer tracking improved over the years + the WA #0884 > > helped us keep PSR2 enabled while triggering screen updates when > > necessary so this FIXME is not valid anymore. > > > > Cc: Dhinakaran Pandiyan > > Cc: Rodrigo Vivi > > Signed-off-by: José Roberto de Souza > > Reviewed-by: Rodrigo Vivi Acked-by: Dhinakaran Pandiyan > > > --- > > drivers/gpu/drm/i915/intel_psr.c | 3 --- > > 1 file changed, 3 deletions(-) > > > > diff --git a/drivers/gpu/drm/i915/intel_psr.c > > b/drivers/gpu/drm/i915/intel_psr.c > > index 6fd793fec5e9..a1bde8bbd85b 100644 > > --- a/drivers/gpu/drm/i915/intel_psr.c > > +++ b/drivers/gpu/drm/i915/intel_psr.c > > @@ -490,9 +490,6 @@ static void hsw_activate_psr2(struct intel_dp > > *intel_dp) > > /* Avoid deep sleep as much as possible to avoid PSR2 idle > > state */ > > val |= EDP_PSR2_IDLE_FRAMES_TO_DEEP_SLEEP(15); > > > > - /* FIXME: selective update is probably totally broken because > > it doesn't > > -* mesh at all with our frontbuffer tracking. And the hw alone > > isn't > > -* good enough. */ > > val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; > > if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) > > val |= EDP_Y_COORDINATE_ENABLE; > > -- > > 2.19.2 > > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 7/9] drm/i915/psr: Rename PSR2 macros to better match meaning
On Thu, 2018-11-29 at 15:07 -0800, Rodrigo Vivi wrote: > On Mon, Nov 26, 2018 at 04:37:08PM -0800, José Roberto de Souza > wrote: > > The first 8 bits of PSR2_CTL have 2 fields to set frames count, the > > first one is to set how many idle frames PSR2 HW needs to wait > > before > > enter in deep sleep and the second one it is how many frames(it > > don't > > need to be idle frames) PSR2 HW will wait before start the PSR > > activation sequence. > > The previous names was really misleading and caused wrong values The idea was to setup a conservative configuration for PSR2 until we were ready to enable the feature and some testing was done. Not sure why you think the values are wrong. > > being > > set so better rename to make it clear. > > I honestly prefer the old names for 2 reasons: > > - they are shorter > - they follow the exact name we have on spec +1 for the above reason. > > > > > Also taking the oportunity to improve those macros. > > > > Cc: Rodrigo Vivi > > Cc: Dhinakaran Pandiyan > > Signed-off-by: José Roberto de Souza > > --- > > drivers/gpu/drm/i915/i915_reg.h | 35 -- > > -- > > drivers/gpu/drm/i915/intel_psr.c | 7 --- > > 2 files changed, 22 insertions(+), 20 deletions(-) > > > > diff --git a/drivers/gpu/drm/i915/i915_reg.h > > b/drivers/gpu/drm/i915/i915_reg.h > > index 47baf2fe8f71..73046bb9ec7c 100644 > > --- a/drivers/gpu/drm/i915/i915_reg.h > > +++ b/drivers/gpu/drm/i915/i915_reg.h > > @@ -4203,23 +4203,24 @@ enum { > > #define EDP_PSR_DEBUG_MASK_DISP_REG_WRITE(1 << 16) /* > > Reserved in ICL+ */ > > #define EDP_PSR_DEBUG_EXIT_ON_PIXEL_UNDERRUN (1 << 15) /* SKL+ > > */ > > > > -#define EDP_PSR2_CTL _MMIO(0x6f900) > > -#define EDP_PSR2_ENABLE (1 << 31) > > -#define EDP_SU_TRACK_ENABLE (1 << 30) > > -#define EDP_Y_COORDINATE_VALID (1 << 26) /* GLK and CNL+ */ > > -#define EDP_Y_COORDINATE_ENABLE (1 << 25) /* GLK and CNL+ */ > > -#define EDP_MAX_SU_DISABLE_TIME(t) ((t) << 20) > > -#define EDP_MAX_SU_DISABLE_TIME_MASK (0x1f << 20) > > -#define EDP_PSR2_TP2_TIME_500us (0 << 8) > > -#define EDP_PSR2_TP2_TIME_100us (1 << 8) > > -#define EDP_PSR2_TP2_TIME_2500us (2 << 8) > > -#define EDP_PSR2_TP2_TIME_50us (3 << 8) > > -#define EDP_PSR2_TP2_TIME_MASK (3 << 8) > > -#define EDP_PSR2_FRAME_BEFORE_SU_SHIFT 4 > > -#define EDP_PSR2_FRAME_BEFORE_SU_MASK(0xf << 4) > > -#define EDP_PSR2_FRAME_BEFORE_SU(a) ((a) << 4) > > -#define EDP_PSR2_IDLE_FRAME_MASK 0xf > > -#define EDP_PSR2_IDLE_FRAME_SHIFT0 > > +#define EDP_PSR2_CTL _MMIO(0 > > x6f900) > > +#define EDP_PSR2_ENABLE (1 << 31) > > +#define EDP_SU_TRACK_ENABLE (1 << > > 30) > > +#define EDP_Y_COORDINATE_VALID (1 << 26) /* > > GLK and CNL+ */ > > +#define EDP_Y_COORDINATE_ENABLE (1 << 25) /* > > GLK and CNL+ */ > > +#define EDP_MAX_SU_DISABLE_TIME(t) ((t) << > > 20) > > +#define EDP_MAX_SU_DISABLE_TIME_MASK (0x1f > > << 20) > > +#define EDP_PSR2_TP2_TIME_500us (0 << 8) > > +#define EDP_PSR2_TP2_TIME_100us (1 << 8) > > +#define EDP_PSR2_TP2_TIME_2500us (2 << 8) > > +#define EDP_PSR2_TP2_TIME_50us (3 << 8) > > +#define EDP_PSR2_TP2_TIME_MASK (3 << 8) > > +#define EDP_PSR2_FRAMES_BEFORE_ACTIVATE_SHIFT(4) > > +#define EDP_PSR2_FRAMES_BEFORE_ACTIVATE_MASK (0xf << > > EDP_PSR2_FRAMES_BEFORE_ACTIVATE_SHIFT) > > +#define EDP_PSR2_FRAMES_BEFORE_ACTIVATE(n) (((n) > > << EDP_PSR2_FRAMES_BEFORE_ACTIVATE_SHIFT) & > > EDP_PSR2_FRAMES_BEFORE_ACTIVATE_MASK) > > +#define EDP_PSR2_IDLE_FRAMES_TO_DEEP_SLEEP_MASK (0xf) > > +#define EDP_PSR2_IDLE_FRAMES_TO_DEEP_SLEEP_SHIFT (0) > > +#define EDP_PSR2_IDLE_FRAMES_TO_DEEP_SLEEP(n)(((n) > > << EDP_PSR2_IDLE_FRAMES_TO_DEEP_SLEEP_SHIFT) & > > EDP_PSR2_IDLE_FRAMES_TO_DEEP_SLEEP_MASK) > > > > #define _PSR_EVENT_TRANS_A 0x60848 > > #define _PSR_EVENT_TRANS_B 0x61848 > > diff --git a/dri
Re: [PATCH] drm/framebuffer: Expose only modifiers that support at least a format
On Tue, 2018-11-06 at 22:21 +0200, Ville Syrjälä wrote: > On Tue, Nov 06, 2018 at 11:54:45AM -0800, Dhinakaran Pandiyan wrote: > > On Tue, 2018-11-06 at 16:13 +0200, Ville Syrjälä wrote: > > > On Mon, Nov 05, 2018 at 06:44:34PM -0800, Dhinakaran Pandiyan > > > wrote: > > > > Allows drivers to pass a larger modifier array, thereby > > > > avoiding > > > > declarations of static modifier arrays that are only slight > > > > different > > > > for each plane. > > > > > > > > Cc: dri-devel@lists.freedesktop.org > > > > Cc: Ville Syrjälä > > > > Suggested-by: Ville Syrjälä > > > > Signed-off-by: Dhinakaran Pandiyan < > > > > dhinakaran.pandi...@intel.com> > > > > --- > > > > drivers/gpu/drm/drm_plane.c | 35 +++ > > > > > > > > > > > > 1 file changed, 27 insertions(+), 8 deletions(-) > > > > > > > > diff --git a/drivers/gpu/drm/drm_plane.c > > > > b/drivers/gpu/drm/drm_plane.c > > > > index 1fa98bd12003..1546ffbf8e36 100644 > > > > --- a/drivers/gpu/drm/drm_plane.c > > > > +++ b/drivers/gpu/drm/drm_plane.c > > > > @@ -179,8 +179,8 @@ int drm_universal_plane_init(struct > > > > drm_device > > > > *dev, struct drm_plane *plane, > > > > const char *name, ...) > > > > { > > > > struct drm_mode_config *config = >mode_config; > > > > - unsigned int format_modifier_count = 0; > > > > - int ret; > > > > + unsigned int format_modifier_count, in_modifier_count = > > > > 0; > > > > + int ret, i; > > > > > > > > /* plane index is used with 32bit bitmasks */ > > > > if (WARN_ON(config->num_total_plane >= 32)) > > > > @@ -216,22 +216,43 @@ int drm_universal_plane_init(struct > > > > drm_device *dev, struct drm_plane *plane, > > > > > > > > if (format_modifiers) { > > > > const uint64_t *temp_modifiers = > > > > format_modifiers; > > > > + > > > > while (*temp_modifiers++ != > > > > DRM_FORMAT_MOD_INVALID) > > > > - format_modifier_count++; > > > > + in_modifier_count++; > > > > } > > > > > > > > - plane->modifier_count = format_modifier_count; > > > > - plane->modifiers = kmalloc_array(format_modifier_count, > > > > + plane->modifiers = kmalloc_array(in_modifier_count, > > > > sizeof(format_modifier > > > > s[0]), > > > > GFP_KERNEL); > > > > > > > > - if (format_modifier_count && !plane->modifiers) { > > > > + if (in_modifier_count && !plane->modifiers) { > > > > DRM_DEBUG_KMS("out of memory when allocating > > > > plane\n"); > > > > kfree(plane->format_types); > > > > drm_mode_object_unregister(dev, >base); > > > > return -ENOMEM; > > > > } > > > > > > > > + for (i = 0, format_modifier_count = 0; i < > > > > in_modifier_count; > > > > i++) { > > > > + int j; > > > > + > > > > + for (j = 0; funcs->format_mod_supported && j < > > > > format_count; j++) > > > > + if (funcs->format_mod_supported(plane, > > > > formats[j], > > > > + format_ > > > > modifier > > > > s[i])) > > > > + break; > > > > + > > > > + if (j < format_count) > > > > + plane- > > > > >modifiers[format_modifier_count++] = > > > > + format_modifiers[i]; > > > > + } > > > > + > > > > + if (format_modifier_count < in_modifier_count) { > > > > + size_t size; > > > > + > > > > + size = format_modifier_count * > > > > sizeof(format_modifiers[0]); >
Re: [PATCH] drm/framebuffer: Expose only modifiers that support at least a format
On Tue, 2018-11-06 at 16:13 +0200, Ville Syrjälä wrote: > On Mon, Nov 05, 2018 at 06:44:34PM -0800, Dhinakaran Pandiyan wrote: > > Allows drivers to pass a larger modifier array, thereby avoiding > > declarations of static modifier arrays that are only slight > > different > > for each plane. > > > > Cc: dri-devel@lists.freedesktop.org > > Cc: Ville Syrjälä > > Suggested-by: Ville Syrjälä > > Signed-off-by: Dhinakaran Pandiyan > > --- > > drivers/gpu/drm/drm_plane.c | 35 +++ > > > > 1 file changed, 27 insertions(+), 8 deletions(-) > > > > diff --git a/drivers/gpu/drm/drm_plane.c > > b/drivers/gpu/drm/drm_plane.c > > index 1fa98bd12003..1546ffbf8e36 100644 > > --- a/drivers/gpu/drm/drm_plane.c > > +++ b/drivers/gpu/drm/drm_plane.c > > @@ -179,8 +179,8 @@ int drm_universal_plane_init(struct drm_device > > *dev, struct drm_plane *plane, > > const char *name, ...) > > { > > struct drm_mode_config *config = >mode_config; > > - unsigned int format_modifier_count = 0; > > - int ret; > > + unsigned int format_modifier_count, in_modifier_count = 0; > > + int ret, i; > > > > /* plane index is used with 32bit bitmasks */ > > if (WARN_ON(config->num_total_plane >= 32)) > > @@ -216,22 +216,43 @@ int drm_universal_plane_init(struct > > drm_device *dev, struct drm_plane *plane, > > > > if (format_modifiers) { > > const uint64_t *temp_modifiers = format_modifiers; > > + > > while (*temp_modifiers++ != DRM_FORMAT_MOD_INVALID) > > - format_modifier_count++; > > + in_modifier_count++; > > } > > > > - plane->modifier_count = format_modifier_count; > > - plane->modifiers = kmalloc_array(format_modifier_count, > > + plane->modifiers = kmalloc_array(in_modifier_count, > > sizeof(format_modifiers[0]), > > GFP_KERNEL); > > > > - if (format_modifier_count && !plane->modifiers) { > > + if (in_modifier_count && !plane->modifiers) { > > DRM_DEBUG_KMS("out of memory when allocating plane\n"); > > kfree(plane->format_types); > > drm_mode_object_unregister(dev, >base); > > return -ENOMEM; > > } > > > > + for (i = 0, format_modifier_count = 0; i < in_modifier_count; > > i++) { > > + int j; > > + > > + for (j = 0; funcs->format_mod_supported && j < > > format_count; j++) > > + if (funcs->format_mod_supported(plane, > > formats[j], > > + format_modifier > > s[i])) > > + break; > > + > > + if (j < format_count) > > + plane->modifiers[format_modifier_count++] = > > + format_modifiers[i]; > > + } > > + > > + if (format_modifier_count < in_modifier_count) { > > + size_t size; > > + > > + size = format_modifier_count * > > sizeof(format_modifiers[0]); > > + plane->modifiers = krealloc(plane->modifiers, size, > > GFP_KERNEL); > > Should check that the realloc actually succeeded. Didn't see a failure path for new size smaller than old, the return is the same pointer passed to krealloc(). > > And I think we might want to give this same treatment to plane- > >formats[] > as well. > > And perhaps we could even throw out plane->modifiers[] and just rely > on > the IN_FORMATS blob exclusively? Hmm. Looks like that is not getting > fully > populated unless the driver has provided .format_mod_supported(). Not > sure why that is, and not sure what userspace is supposed to do with > a > partially filled blob like that. I'm thinking we shouldn't even > attach > the property to the plane in that case. Shouldn't it copy the modifier array into the blob and mark all formats as supported? drm_plane_check_pixel_format() seems to allow any valid format for a modifier in this case. -DK > > > + } > > + plane->modifier_count = format_modifier_count; > > + > > if (name) { > > va_list ap; > > > > @@ -251,8 +272,6 @@ int drm_universal_plane_init(struct drm_device > > *dev, struct drm_plane *plane, > > > > memcpy(plane->format_types, formats, format_count * > > sizeof(uint32_t)); > > plane->format_count = format_count; > > - memcpy(plane->modifiers, format_modifiers, > > - format_modifier_count * sizeof(format_modifiers[0])); > > plane->possible_crtcs = possible_crtcs; > > plane->type = type; > > > > -- > > 2.14.1 > > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/framebuffer: Expose only modifiers that support at least a format
Allows drivers to pass a larger modifier array, thereby avoiding declarations of static modifier arrays that are only slight different for each plane. Cc: dri-devel@lists.freedesktop.org Cc: Ville Syrjälä Suggested-by: Ville Syrjälä Signed-off-by: Dhinakaran Pandiyan --- drivers/gpu/drm/drm_plane.c | 35 +++ 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 1fa98bd12003..1546ffbf8e36 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -179,8 +179,8 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, const char *name, ...) { struct drm_mode_config *config = >mode_config; - unsigned int format_modifier_count = 0; - int ret; + unsigned int format_modifier_count, in_modifier_count = 0; + int ret, i; /* plane index is used with 32bit bitmasks */ if (WARN_ON(config->num_total_plane >= 32)) @@ -216,22 +216,43 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, if (format_modifiers) { const uint64_t *temp_modifiers = format_modifiers; + while (*temp_modifiers++ != DRM_FORMAT_MOD_INVALID) - format_modifier_count++; + in_modifier_count++; } - plane->modifier_count = format_modifier_count; - plane->modifiers = kmalloc_array(format_modifier_count, + plane->modifiers = kmalloc_array(in_modifier_count, sizeof(format_modifiers[0]), GFP_KERNEL); - if (format_modifier_count && !plane->modifiers) { + if (in_modifier_count && !plane->modifiers) { DRM_DEBUG_KMS("out of memory when allocating plane\n"); kfree(plane->format_types); drm_mode_object_unregister(dev, >base); return -ENOMEM; } + for (i = 0, format_modifier_count = 0; i < in_modifier_count; i++) { + int j; + + for (j = 0; funcs->format_mod_supported && j < format_count; j++) + if (funcs->format_mod_supported(plane, formats[j], + format_modifiers[i])) + break; + + if (j < format_count) + plane->modifiers[format_modifier_count++] = + format_modifiers[i]; + } + + if (format_modifier_count < in_modifier_count) { + size_t size; + + size = format_modifier_count * sizeof(format_modifiers[0]); + plane->modifiers = krealloc(plane->modifiers, size, GFP_KERNEL); + } + plane->modifier_count = format_modifier_count; + if (name) { va_list ap; @@ -251,8 +272,6 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, memcpy(plane->format_types, formats, format_count * sizeof(uint32_t)); plane->format_count = format_count; - memcpy(plane->modifiers, format_modifiers, - format_modifier_count * sizeof(format_modifiers[0])); plane->possible_crtcs = possible_crtcs; plane->type = type; -- 2.14.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v4 2/2] drm/i915: Eliminate the horrendous format check code
On Mon, 2018-10-29 at 20:34 +0200, Ville Syrjala wrote: > From: Ville Syrjälä > > Replace the messy framebuffer format/modifier validation code > with a single call to drm_any_plane_has_format(). The code was > extremely annoying to maintain as you had to have a lot of platform > checks for different formats. The new code requires zero maintenance. > > v2: Nuke the modifier checks as well since the core does that too now > v3: Call drm_any_plane_has_format() from the driver code > v4: Rebase > > Cc: Dhinakaran Pandiyan Reviewed-by: Dhinakaran Pandiyan -DK > Signed-off-by: Ville Syrjälä > --- > drivers/gpu/drm/i915/intel_display.c | 105 ++--- > -- > 1 file changed, 8 insertions(+), 97 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_display.c > b/drivers/gpu/drm/i915/intel_display.c > index 9b549d3dd055..de38d5545f3b 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -14368,7 +14368,6 @@ static int intel_framebuffer_init(struct > intel_framebuffer *intel_fb, > { > struct drm_i915_private *dev_priv = to_i915(obj->base.dev); > struct drm_framebuffer *fb = _fb->base; > - struct drm_format_name_buf format_name; > u32 pitch_limit; > unsigned int tiling, stride; > int ret = -EINVAL; > @@ -14399,39 +14398,14 @@ static int intel_framebuffer_init(struct > intel_framebuffer *intel_fb, > } > } > > - /* Passed in modifier sanity checking. */ > - switch (mode_cmd->modifier[0]) { > - case I915_FORMAT_MOD_Y_TILED_CCS: > - case I915_FORMAT_MOD_Yf_TILED_CCS: > - switch (mode_cmd->pixel_format) { > - case DRM_FORMAT_XBGR: > - case DRM_FORMAT_ABGR: > - case DRM_FORMAT_XRGB: > - case DRM_FORMAT_ARGB: > - break; > - default: > - DRM_DEBUG_KMS("RC supported only with RGB > formats\n"); > - goto err; > - } > - /* fall through */ > - case I915_FORMAT_MOD_Yf_TILED: > - if (mode_cmd->pixel_format == DRM_FORMAT_C8) { > - DRM_DEBUG_KMS("Indexed format does not support > Yf tiling\n"); > - goto err; > - } > - /* fall through */ > - case I915_FORMAT_MOD_Y_TILED: > - if (INTEL_GEN(dev_priv) < 9) { > - DRM_DEBUG_KMS("Unsupported tiling 0x%llx!\n", > - mode_cmd->modifier[0]); > - goto err; > - } > - break; > - case DRM_FORMAT_MOD_LINEAR: > - case I915_FORMAT_MOD_X_TILED: > - break; > - default: > - DRM_DEBUG_KMS("Unsupported fb modifier 0x%llx!\n", > + if (!drm_any_plane_has_format(_priv->drm, > + mode_cmd->pixel_format, > + mode_cmd->modifier[0])) { > + struct drm_format_name_buf format_name; > + > + DRM_DEBUG_KMS("unsupported pixel format %s / modifier > 0x%llx\n", > + drm_get_format_name(mode_cmd- > >pixel_format, > + _name), > mode_cmd->modifier[0]); > goto err; > } > @@ -14466,69 +14440,6 @@ static int intel_framebuffer_init(struct > intel_framebuffer *intel_fb, > goto err; > } > > - /* Reject formats not supported by any plane early. */ > - switch (mode_cmd->pixel_format) { > - case DRM_FORMAT_C8: > - case DRM_FORMAT_RGB565: > - case DRM_FORMAT_XRGB: > - case DRM_FORMAT_ARGB: > - break; > - case DRM_FORMAT_XRGB1555: > - if (INTEL_GEN(dev_priv) > 3) { > - DRM_DEBUG_KMS("unsupported pixel format: %s\n", > - drm_get_format_name(mode_cmd- > >pixel_format, _name)); > - goto err; > - } > - break; > - case DRM_FORMAT_ABGR: > - if (!IS_VALLEYVIEW(dev_priv) && > !IS_CHERRYVIEW(dev_priv) && > - INTEL_GEN(dev_priv) < 9) { > - DRM_DEBUG_KMS("unsupported pixel format: %s\n", > - drm_get_format_name(mode_cmd- > >pixel_format, _name)); > - goto err; > - } > - break; > - case DRM_FORM
Re: [Intel-gfx] [PATCH v3 2/4] drm/i915: Eliminate the horrendous format check code
On Fri, 2018-03-09 at 17:14 +0200, Ville Syrjala wrote: > From: Ville Syrjälä > > Replace the messy framebuffer format/modifier validation code > with a single call to drm_any_plane_has_format(). The code was > extremely annoying to maintain as you had to have a lot of platform > checks for different formats. The new code requires zero maintenance. > > v2: Nuke the modifier checks as well since the core does that too now > v3: Call drm_any_plane_has_format() from the driver code > > Signed-off-by: Ville Syrjälä Patch looks good to me, but does not apply cleanly now. > --- > drivers/gpu/drm/i915/intel_display.c | 90 > > 1 file changed, 8 insertions(+), 82 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_display.c > b/drivers/gpu/drm/i915/intel_display.c > index 2933ad38094f..7f06fa83d894 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -13989,7 +13989,6 @@ static int intel_framebuffer_init(struct > intel_framebuffer *intel_fb, > { > struct drm_i915_private *dev_priv = to_i915(obj->base.dev); > struct drm_framebuffer *fb = _fb->base; > - struct drm_format_name_buf format_name; > u32 pitch_limit; > unsigned int tiling, stride; > int ret = -EINVAL; > @@ -14020,33 +14019,14 @@ static int intel_framebuffer_init(struct > intel_framebuffer *intel_fb, > } > } > > - /* Passed in modifier sanity checking. */ > - switch (mode_cmd->modifier[0]) { > - case I915_FORMAT_MOD_Y_TILED_CCS: > - case I915_FORMAT_MOD_Yf_TILED_CCS: > - switch (mode_cmd->pixel_format) { > - case DRM_FORMAT_XBGR: > - case DRM_FORMAT_ABGR: > - case DRM_FORMAT_XRGB: > - case DRM_FORMAT_ARGB: > - break; > - default: > - DRM_DEBUG_KMS("RC supported only with RGB > formats\n"); > - goto err; > - } > - /* fall through */ > - case I915_FORMAT_MOD_Y_TILED: > - case I915_FORMAT_MOD_Yf_TILED: > - if (INTEL_GEN(dev_priv) < 9) { > - DRM_DEBUG_KMS("Unsupported tiling 0x%llx!\n", > - mode_cmd->modifier[0]); > - goto err; > - } > - case DRM_FORMAT_MOD_LINEAR: > - case I915_FORMAT_MOD_X_TILED: > - break; > - default: > - DRM_DEBUG_KMS("Unsupported fb modifier 0x%llx!\n", > + if (!drm_any_plane_has_format(_priv->drm, > + mode_cmd->pixel_format, > + mode_cmd->modifier[0])) { > + struct drm_format_name_buf format_name; > + > + DRM_DEBUG_KMS("unsupported pixel format %s / modifier > 0x%llx\n", > + drm_get_format_name(mode_cmd- > >pixel_format, > + _name), > mode_cmd->modifier[0]); > goto err; > } > @@ -14081,60 +14061,6 @@ static int intel_framebuffer_init(struct > intel_framebuffer *intel_fb, > goto err; > } > > - /* Reject formats not supported by any plane early. */ > - switch (mode_cmd->pixel_format) { > - case DRM_FORMAT_C8: > - case DRM_FORMAT_RGB565: > - case DRM_FORMAT_XRGB: > - case DRM_FORMAT_ARGB: > - break; > - case DRM_FORMAT_XRGB1555: > - if (INTEL_GEN(dev_priv) > 3) { > - DRM_DEBUG_KMS("unsupported pixel format: %s\n", > - drm_get_format_name(mode_cmd- > >pixel_format, _name)); > - goto err; > - } > - break; > - case DRM_FORMAT_ABGR: > - if (!IS_VALLEYVIEW(dev_priv) && > !IS_CHERRYVIEW(dev_priv) && > - INTEL_GEN(dev_priv) < 9) { > - DRM_DEBUG_KMS("unsupported pixel format: %s\n", > - drm_get_format_name(mode_cmd- > >pixel_format, _name)); > - goto err; > - } > - break; > - case DRM_FORMAT_XBGR: > - case DRM_FORMAT_XRGB2101010: > - case DRM_FORMAT_XBGR2101010: > - if (INTEL_GEN(dev_priv) < 4) { > - DRM_DEBUG_KMS("unsupported pixel format: %s\n", > - drm_get_format_name(mode_cmd- > >pixel_format, _name)); > - goto err; > - } > - break; > - case DRM_FORMAT_ABGR2101010: > - if (!IS_VALLEYVIEW(dev_priv) && > !IS_CHERRYVIEW(dev_priv)) { > - DRM_DEBUG_KMS("unsupported pixel format: %s\n", > - drm_get_format_name(mode_cmd- > >pixel_format, _name)); > - goto err; > - } > - break; > - case DRM_FORMAT_YUYV: > -
Re: [Intel-gfx] [PATCH v3 1/4] drm: Add drm_any_plane_has_format()
On Fri, 2018-03-09 at 17:14 +0200, Ville Syrjala wrote: > From: Ville Syrjälä > > Add a function to check whether there is at least one plane that > supports a specific format and modifier combination. Drivers can > use this to reject unsupported formats/modifiers in .fb_create(). > > v2: Accept anyformat if the driver doesn't do planes (Eric) > s/planes_have_format/any_plane_has_format/ (Eric) > Check the modifier as well since we already have a function > that does both > v3: Don't do the check in the core since we may not know the > modifier yet, instead export the function and let drivers > call it themselves > > Cc: Eric Anholt > Signed-off-by: Ville Syrjälä I ended up writing a similar patch for i915. Having this in the core seems better and patch still applies cleanly. Reviewed-by: Dhinakaran Pandiyan > --- > drivers/gpu/drm/drm_plane.c | 23 +++ > include/drm/drm_mode_config.h | 6 ++ > include/drm/drm_plane.h | 2 ++ > 3 files changed, 31 insertions(+) > > diff --git a/drivers/gpu/drm/drm_plane.c > b/drivers/gpu/drm/drm_plane.c > index a5d1fc7e8a37..3b2d6f8d889d 100644 > --- a/drivers/gpu/drm/drm_plane.c > +++ b/drivers/gpu/drm/drm_plane.c > @@ -578,6 +578,29 @@ int drm_plane_check_pixel_format(struct > drm_plane *plane, > return 0; > } > > +/** > + * drm_any_plane_has_format - Check whether any plane supports this > format and modifier combination > + * @dev: DRM device > + * @format: pixel format (DRM_FORMAT_*) > + * @modifier: data layout modifier > + * > + * Returns: > + * Whether at least one plane supports the specified format and > modifier combination. > + */ > +bool drm_any_plane_has_format(struct drm_device *dev, > + u32 format, u64 modifier) > +{ > + struct drm_plane *plane; > + > + drm_for_each_plane(plane, dev) { > + if (drm_plane_check_pixel_format(plane, format, > modifier) == 0) > + return true; > + } > + > + return false; > +} > +EXPORT_SYMBOL(drm_any_plane_has_format); > + > /* > * __setplane_internal - setplane handler for internal callers > * > diff --git a/include/drm/drm_mode_config.h > b/include/drm/drm_mode_config.h > index 7569f22ffef6..9b894de9a75d 100644 > --- a/include/drm/drm_mode_config.h > +++ b/include/drm/drm_mode_config.h > @@ -52,6 +52,12 @@ struct drm_mode_config_funcs { >* requested metadata, but most of that is left to the driver. > See >* drm_mode_fb_cmd2 for details. >* > + * To validate the pixel format and modifier drivers can use > + * drm_any_plane_has_format() to make sure at least one plane > supports > + * the requested values. Note that the driver must first > determine the > + * actual modifier used if the request doesn't have it > specified, > + * ie. when (@mode_cmd->flags & DRM_MODE_FB_MODIFIERS) == 0. > + * >* If the parameters are deemed valid and the backing storage > objects in >* the underlying memory manager all exist, then the driver > allocates >* a new _framebuffer structure, subclassed to contain > diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h > index f7bf4a48b1c3..930e8fdd90f8 100644 > --- a/include/drm/drm_plane.h > +++ b/include/drm/drm_plane.h > @@ -683,5 +683,7 @@ static inline struct drm_plane > *drm_plane_find(struct drm_device *dev, > #define drm_for_each_plane(plane, dev) \ > list_for_each_entry(plane, &(dev)->mode_config.plane_list, > head) > > +bool drm_any_plane_has_format(struct drm_device *dev, > + u32 format, u64 modifier); > > #endif ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/2] drm/plane: Export drm_plane_check_pixel_format()
i915 will make use of this to fail early during framebuffer creation. Suggested-by: Ville Syrjälä Cc: dri-devel@lists.freedesktop.org Cc: Ville Syrjälä Signed-off-by: Dhinakaran Pandiyan --- drivers/gpu/drm/drm_plane.c | 1 + include/drm/drm_plane.h | 11 +++ 2 files changed, 12 insertions(+) diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 1fa98bd12003..e834788619d1 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -589,6 +589,7 @@ int drm_plane_check_pixel_format(struct drm_plane *plane, return 0; } +EXPORT_SYMBOL(drm_plane_check_pixel_format); static int __setplane_check(struct drm_plane *plane, struct drm_crtc *crtc, diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 0a0834bef8bd..8637b5239eb3 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -763,6 +763,17 @@ static inline struct drm_plane *drm_plane_find(struct drm_device *dev, return mo ? obj_to_plane(mo) : NULL; } +/** + * drm_plane_check_pixel_format - check format and modifier support. + * @plane: plane to check support against. + * @format: pixel format to check support for. + * @modifier: format modifier to check support for. + * + * Returns 0 on success or negative error code on failure. + */ +int drm_plane_check_pixel_format(struct drm_plane *plane, +u32 format, u64 modifier); + /** * drm_for_each_plane_mask - iterate over planes specified by bitmask * @plane: the loop cursor -- 2.14.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 3/3] drm: add LG eDP panel to quirk database
On Mon, 2018-09-10 at 14:43 +0300, Jani Nikula wrote: > On Mon, 10 Sep 2018, "Lee, Shawn C" wrote: > > The N value was computed by kernel driver that based on synchronous > > clock > > mode. But only specific N value (0x8000) would be acceptable for > > LG LP140WF6-SPM1 eDP panel which is running at asynchronous clock > > mode. > > With the other N value, Tcon will enter BITS mode and display black > > screen. > > Add this panel into quirk database and give particular N value when > > calculate M/N divider. > > > > Cc: Jani Nikula > > Cc: Cooper Chiou > > Cc: Matt Atwood > > Cc: Maarten Lankhorst > > Cc: Dhinakaran Pandiyan > > Cc: Clint Taylor > > Signed-off-by: Lee, Shawn C > > No access to the panel or its details, so instead of review, > > Acked-by: Jani Nikula > > > --- > > drivers/gpu/drm/drm_dp_helper.c | 2 ++ > > 1 file changed, 2 insertions(+) > > > > diff --git a/drivers/gpu/drm/drm_dp_helper.c > > b/drivers/gpu/drm/drm_dp_helper.c > > index d0c1250975ab..0ef7c43a9025 100644 > > --- a/drivers/gpu/drm/drm_dp_helper.c > > +++ b/drivers/gpu/drm/drm_dp_helper.c > > @@ -1270,6 +1270,8 @@ struct dpcd_quirk { > > static const struct dpcd_quirk dpcd_quirk_list[] = { > > /* Analogix 7737 needs reduced M and N at HBR2 link rates > > */ > > { OUI(0x00, 0x22, 0xb9), DEVICE_ID_ANY, true, Wonder if DEVICE_ID_ANY still the accurate criteria for these dongles now that we can check against device IDs. I guess, since the quirk fixes multiple dongles we probably can't check against a single device ID. > > BIT(DP_DPCD_QUIRK_CONSTANT_N) }, > > + /* LG LP140WF6-SPM1 eDP panel */ If you are resending the patches, it might be worth updating the comment to /* LG LP140WF6-SPM1 eDP panel needs N value of 0x8000 */ > > + { OUI(0x00, 0x22, 0xb9), DEVICE_ID('s', 'i', 'v', 'a', > > 'r', 'T'), false, BIT(DP_DPCD_QUIRK_CONSTANT_N) }, > > }; > > > > #undef OUI > > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 1/3] drm: Add support for device_id based detection.
On Mon, 2018-09-10 at 08:26 -0700, Lee, Shawn C wrote: > DP quirk list just compare sink or branch device's OUI so far. > That means particular vendor's products will be applied specific > change. This change would confirm device_id the same or not. > Then driver can implement some changes for branch/sink device > that really need additional WA. > > Cc: Jani Nikula > Cc: Cooper Chiou > Cc: Matt Atwood > Cc: Maarten Lankhorst > Cc: Dhinakaran Pandiyan > Cc: Clint Taylor > Signed-off-by: Lee, Shawn C > --- > drivers/gpu/drm/drm_dp_helper.c | 15 ++- > 1 file changed, 14 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/drm_dp_helper.c > b/drivers/gpu/drm/drm_dp_helper.c > index 0cccbcb2d03e..0362c645d96e 100644 > --- a/drivers/gpu/drm/drm_dp_helper.c > +++ b/drivers/gpu/drm/drm_dp_helper.c > @@ -1256,15 +1256,20 @@ EXPORT_SYMBOL(drm_dp_stop_crc); > > struct dpcd_quirk { > u8 oui[3]; > + u8 device_id[6]; > bool is_branch; With device id included, do we still need is_branch? > u32 quirks; > }; > > #define OUI(first, second, third) { (first), (second), (third) } > +#define DEVICE_ID(first, second, third, fourth, fifth, sixth) \ > + { (first), (second), (third), (fourth), (fifth), (sixth) } > + > +#define DEVICE_ID_ANYDEVICE_ID(0, 0, 0, 0, 0, 0) > > static const struct dpcd_quirk dpcd_quirk_list[] = { > /* Analogix 7737 needs reduced M and N at HBR2 link rates */ > - { OUI(0x00, 0x22, 0xb9), true, > BIT(DP_DPCD_QUIRK_LIMITED_M_N) }, > + { OUI(0x00, 0x22, 0xb9), DEVICE_ID_ANY, true, > BIT(DP_DPCD_QUIRK_LIMITED_M_N) }, > }; > > #undef OUI > @@ -1283,6 +1288,7 @@ drm_dp_get_quirks(const struct > drm_dp_dpcd_ident *ident, bool is_branch) > const struct dpcd_quirk *quirk; > u32 quirks = 0; > int i; > + u8 any_device[] = DEVICE_ID_ANY; > > for (i = 0; i < ARRAY_SIZE(dpcd_quirk_list); i++) { > quirk = _quirk_list[i]; > @@ -1293,12 +1299,19 @@ drm_dp_get_quirks(const struct > drm_dp_dpcd_ident *ident, bool is_branch) Update documentation that currently says - "* For now, only the OUI (first three bytes) is used, but this may be extended * to device identification string ..." > if (memcmp(quirk->oui, ident->oui, sizeof(ident- > >oui)) != 0) > continue; > > + if (memcmp(quirk->device_id, any_device, > sizeof(any_device)) != 0 && > + memcmp(quirk->device_id, ident->device_id, > sizeof(ident->device_id)) != 0) > + continue; > + > quirks |= quirk->quirks; > } > > return quirks; > } > > +#undef DEVICE_ID_ANY > +#undef DEVICE_ID > + > /** > * drm_dp_read_desc - read sink/branch descriptor from DPCD > * @aux: DisplayPort AUX channel ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH v7 2/2] drm/i915: Adding YUV444 packed format(DRM_FORMAT_XYUV) support.
On Thu, 2018-08-30 at 13:57 +0100, Lisovskiy, Stanislav wrote: > On Wed, 2018-08-29 at 12:16 -0700, Dhinakaran Pandiyan wrote: > > > > On Wed, 2018-08-29 at 21:10 +0300, Ville Syrjälä wrote: > > > On Wed, Aug 29, 2018 at 02:28:47PM +0300, Stanislav Lisovskiy > > > wrote: > > > > PLANE_CTL_FORMAT_AYUV is already supported, according to > > > > hardware > > > > specification. > > > > > > > > v2: Edited commit message, removed redundant whitespaces. > > > > > > > > v3: Fixed fallthrough logic for the format switch cases. > > > > > > > > v4: Yet again fixed fallthrough logic, to reuse code from other > > > > case > > > > labels. > > > > > > > > v5: Started to use XYUV instead of AYUV, as we don't use alpha. Curious what the reason is. Is it because the hardware does not support alpha with this format? > > > > > > > > v6: Removed unneeded initializer for new XYUV format. > > > > > > > > v7: Added scaling support for DRM_FORMAT_XYUV > > > > I don't see yuv formats in skl_format_to_fourcc(), any idea why? > > Good point. I guess would be nice idea to add at least XYUV there > now. > I can add rest of the formats with a separate patch afterwards. Wonder if the expectation is BIOS not use yuv formats. Ville? > > > > > Also, shouldn't plane_color_ctl_alpha() be updated? > > I guess not, as we don't support alpha in that case. Right, the default case should take care of setting PLANE_CTL_ALPHA_DISABLE. I misread it. > > > > > > > > > > > Signed-off-by: Stanislav Lisovskiy > > > om > > > > > > > > > > > > > --- > > > > drivers/gpu/drm/i915/intel_display.c | 8 > > > > drivers/gpu/drm/i915/intel_sprite.c | 1 + > > > > 2 files changed, 9 insertions(+) > > > > > > > > diff --git a/drivers/gpu/drm/i915/intel_display.c > > > > b/drivers/gpu/drm/i915/intel_display.c > > > > index 30fdfd1a3037..3c96fa3a2b61 100644 > > > > --- a/drivers/gpu/drm/i915/intel_display.c > > > > +++ b/drivers/gpu/drm/i915/intel_display.c > > > > @@ -86,6 +86,7 @@ static const uint32_t skl_primary_formats[] = > > > > { > > > > DRM_FORMAT_YVYU, > > > > DRM_FORMAT_UYVY, > > > > DRM_FORMAT_VYUY, > > > > + DRM_FORMAT_XYUV, > > > > }; > > > > > > > > static const uint32_t skl_pri_planar_formats[] = { > > > > @@ -102,6 +103,7 @@ static const uint32_t > > > > skl_pri_planar_formats[] > > > > = { > > > > DRM_FORMAT_UYVY, > > > > DRM_FORMAT_VYUY, > > > > DRM_FORMAT_NV12, > > > > + DRM_FORMAT_XYUV, > > > > > > I would keep the NV12 at the end so that the arrays are easier to > > > compare visually. > > > > > > > }; > > > > > > > > static const uint64_t skl_format_modifiers_noccs[] = { > > > > @@ -3501,6 +3503,8 @@ static u32 skl_plane_ctl_format(uint32_t > > > > pixel_format) > > > > return PLANE_CTL_FORMAT_XRGB_2101010; > > > > case DRM_FORMAT_XBGR2101010: > > > > return PLANE_CTL_ORDER_RGBX | > > > > PLANE_CTL_FORMAT_XRGB_2101010; > > > > + case DRM_FORMAT_XYUV: > > > > + return PLANE_CTL_FORMAT_AYUV; > > > > > > We should probably rename that define to XYUV as well since it > > > doesn't > > > support per-pixel alpha. > > > > > > Since you've only implemented this for skl+ you chould mention > > > that > > > in the commit msg. IVB+ support should be equally trivial to > > > implement (wink wink). > > > > > > > case DRM_FORMAT_YUYV: > > > > return PLANE_CTL_FORMAT_YUV422 | > > > > PLANE_CTL_YUV422_YUYV; > > > > case DRM_FORMAT_YVYU: > > > > @@ -4959,6 +4963,7 @@ static int skl_update_scaler_plane(struct > > > > intel_crtc_state *crtc_state, > > > > case DRM_FORMAT_UYVY: > > > > case DRM_FORMAT_VYUY: > > > > case DRM_FORMAT_NV12: > > > > + case DRM_FORMAT_XYUV: > > > > break; > > > > default: > > > > DRM_DEBUG_KMS(&
Re: [Intel-gfx] [PATCH v7 2/2] drm/i915: Adding YUV444 packed format(DRM_FORMAT_XYUV) support.
On Wed, 2018-08-29 at 21:10 +0300, Ville Syrjälä wrote: > On Wed, Aug 29, 2018 at 02:28:47PM +0300, Stanislav Lisovskiy wrote: > > PLANE_CTL_FORMAT_AYUV is already supported, according to hardware > > specification. > > > > v2: Edited commit message, removed redundant whitespaces. > > > > v3: Fixed fallthrough logic for the format switch cases. > > > > v4: Yet again fixed fallthrough logic, to reuse code from other > > case > > labels. > > > > v5: Started to use XYUV instead of AYUV, as we don't use alpha. > > > > v6: Removed unneeded initializer for new XYUV format. > > > > v7: Added scaling support for DRM_FORMAT_XYUV I don't see yuv formats in skl_format_to_fourcc(), any idea why? Also, shouldn't plane_color_ctl_alpha() be updated? > > > > Signed-off-by: Stanislav Lisovskiy > > --- > > drivers/gpu/drm/i915/intel_display.c | 8 > > drivers/gpu/drm/i915/intel_sprite.c | 1 + > > 2 files changed, 9 insertions(+) > > > > diff --git a/drivers/gpu/drm/i915/intel_display.c > > b/drivers/gpu/drm/i915/intel_display.c > > index 30fdfd1a3037..3c96fa3a2b61 100644 > > --- a/drivers/gpu/drm/i915/intel_display.c > > +++ b/drivers/gpu/drm/i915/intel_display.c > > @@ -86,6 +86,7 @@ static const uint32_t skl_primary_formats[] = { > > DRM_FORMAT_YVYU, > > DRM_FORMAT_UYVY, > > DRM_FORMAT_VYUY, > > + DRM_FORMAT_XYUV, > > }; > > > > static const uint32_t skl_pri_planar_formats[] = { > > @@ -102,6 +103,7 @@ static const uint32_t skl_pri_planar_formats[] > > = { > > DRM_FORMAT_UYVY, > > DRM_FORMAT_VYUY, > > DRM_FORMAT_NV12, > > + DRM_FORMAT_XYUV, > > I would keep the NV12 at the end so that the arrays are easier to > compare visually. > > > }; > > > > static const uint64_t skl_format_modifiers_noccs[] = { > > @@ -3501,6 +3503,8 @@ static u32 skl_plane_ctl_format(uint32_t > > pixel_format) > > return PLANE_CTL_FORMAT_XRGB_2101010; > > case DRM_FORMAT_XBGR2101010: > > return PLANE_CTL_ORDER_RGBX | > > PLANE_CTL_FORMAT_XRGB_2101010; > > + case DRM_FORMAT_XYUV: > > + return PLANE_CTL_FORMAT_AYUV; > > We should probably rename that define to XYUV as well since it > doesn't > support per-pixel alpha. > > Since you've only implemented this for skl+ you chould mention that > in the commit msg. IVB+ support should be equally trivial to > implement (wink wink). > > > case DRM_FORMAT_YUYV: > > return PLANE_CTL_FORMAT_YUV422 | > > PLANE_CTL_YUV422_YUYV; > > case DRM_FORMAT_YVYU: > > @@ -4959,6 +4963,7 @@ static int skl_update_scaler_plane(struct > > intel_crtc_state *crtc_state, > > case DRM_FORMAT_UYVY: > > case DRM_FORMAT_VYUY: > > case DRM_FORMAT_NV12: > > + case DRM_FORMAT_XYUV: > > break; > > default: > > DRM_DEBUG_KMS("[PLANE:%d:%s] FB:%d unsupported > > scaling format 0x%x\n", > > @@ -13399,6 +13404,7 @@ static bool > > skl_plane_format_mod_supported(struct drm_plane *_plane, > > } > > > > switch (format) { > > + > > Bogus whitespace. > > > case DRM_FORMAT_XRGB: > > case DRM_FORMAT_XBGR: > > case DRM_FORMAT_ARGB: > > @@ -13414,6 +13420,7 @@ static bool > > skl_plane_format_mod_supported(struct drm_plane *_plane, > > case DRM_FORMAT_UYVY: > > case DRM_FORMAT_VYUY: > > case DRM_FORMAT_NV12: > > + case DRM_FORMAT_XYUV: > > if (modifier == I915_FORMAT_MOD_Yf_TILED) > > return true; > > /* fall through */ > > @@ -14540,6 +14547,7 @@ static int intel_framebuffer_init(struct > > intel_framebuffer *intel_fb, > > goto err; > > } > > break; > > + case DRM_FORMAT_XYUV: > > That's not the right spot if we want the platform checks to match > your > choice of skl+. > > > case DRM_FORMAT_YUYV: > > case DRM_FORMAT_UYVY: > > case DRM_FORMAT_YVYU: > > diff --git a/drivers/gpu/drm/i915/intel_sprite.c > > b/drivers/gpu/drm/i915/intel_sprite.c > > index c286dda625e4..2ac9471974c2 100644 > > --- a/drivers/gpu/drm/i915/intel_sprite.c > > +++ b/drivers/gpu/drm/i915/intel_sprite.c > > @@ -1420,6 +1420,7 @@ static bool > > skl_plane_format_mod_supported(struct drm_plane *_plane, > > case DRM_FORMAT_UYVY: > > case DRM_FORMAT_VYUY: > > case DRM_FORMAT_NV12: > > + case DRM_FORMAT_XYUV: > > if (modifier == I915_FORMAT_MOD_Yf_TILED) > > return true; > > /* fall through */ > > -- > > 2.17.0 > > > > ___ > > Intel-gfx mailing list > > intel-...@lists.freedesktop.org > > https://lists.freedesktop.org/mailman/listinfo/intel-gfx > > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH 2/2] drm/i915: implement EXTENDED_RECEIVER_CAPABILITY_FIELD_PRESENT
On Tue, 2018-07-17 at 15:34 -0700, Dhinakaran Pandiyan wrote: > On Tue, 2018-07-17 at 14:49 -0700, matthew.s.atw...@intel.com wrote: > > > > From: Matt Atwood > > > > According to DP spec (2.9.3.1 of DP 1.4) if > > EXTENDED_RECEIVER_CAPABILITY_FIELD_PRESENT is set the addresses in > > DPCD > > 02200h through 0220Fh shall contain the DPRX's true capability. > > These > > values will match 0h through Fh, except for DPCD_REV, > > MAX_LINK_RATE, DOWN_STREAM_PORT_PRESENT. > > > > Read from DPCD once for all 3 values as this is an expensive > > operation. > > Spec mentions that all of address space 02200h through 0220Fh > > should > > contain the right information however currently only 3 values can > > differ. > > > > There is no address space in the intel_dp->dpcd struct for > > addresses > > 02200h through 0220Fh, and since so much of the data is a > > identical, > > simply overwrite the values stored in 0h through Fh with > > the > > values that can be overwritten from addresses 02200h through > > 0220Fh. > > > > This patch helps with backward compatibility for devices pre DP1.3. > > > > v2: read only dpcd values which can be affected, > I still see 6 bytes read and 3 copied. Ignore this, the original patch was reading 16B. Thanks for clarifying Matt. > > > > > remove incorrect check, > > split into drm include changes into separate patch, commit message, > > verbose debugging statements during overwrite. > > > > Signed-off-by: Matt Atwood > > --- > > drivers/gpu/drm/i915/intel_dp.c | 37 > > + > > 1 file changed, 37 insertions(+) > > > > diff --git a/drivers/gpu/drm/i915/intel_dp.c > > b/drivers/gpu/drm/i915/intel_dp.c > > index dde92e4af5d3..364cf41a8b89 100644 > > --- a/drivers/gpu/drm/i915/intel_dp.c > > +++ b/drivers/gpu/drm/i915/intel_dp.c > > @@ -3738,6 +3738,43 @@ intel_dp_read_dpcd(struct intel_dp > > *intel_dp) > > sizeof(intel_dp->dpcd)) < 0) > > return false; /* aux transfer failed */ > > > > + if (intel_dp->dpcd[DP_TRAINING_AUX_RD_INTERVAL] & > > + DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT) { > > + uint8_t dpcd_ext[6]; > > + > > + DRM_DEBUG_KMS("DPCD: Extended Receiver Capability > > Field Present, accessing 02200h through 022FFh\n"); > > + > > + if (drm_dp_dpcd_read(_dp->aux, > > DP_DP13_DPCD_REV, > > + _ext, sizeof(dpcd_ext)) < 0) > > + return false; /* aux transfer failed */ > > + > > + if (memcmp(_dp->dpcd[DP_DPCD_REV], > > _ext[DP_DPCD_REV], > > + sizeof(u8))) > Why use memcmp and memcmpy if it's just one byte? You could just use > "==" > I believe this is what Jani suggested. if (memcmp(old_dpcd, new_dpcd, sizeof(new_dpcd)) { DRM_DEBUG_KMS(); memcpy(old_dpcd, new_dpcd, sizeof(new_dpcd); } We lose the information about which specific fields in the 6 bytes changed, but that's okay IMO. > > > > { > > + DRM_DEBUG_KMS("DPCD: new value for DPCD > > Revision previous value %2x new value %2x\n", > > + intel_dp->dpcd[DP_DPCD_REV], > > + dpcd_ext[DP_DPCD_REV]); > > + memcpy(_dp->dpcd[DP_DPCD_REV], > > + _ext[DP_DPCD_REV], > > + sizeof(u8)); > > + } > > + if (memcmp(_dp->dpcd[DP_MAX_LINK_RATE], > > + _ext[DP_MAX_LINK_RATE], > > sizeof(u8))) > > { > > + DRM_DEBUG_KMS("DPCD: new value for DPCD > > Max > > Link Rate previous value %2x new value %2x\n", > > + intel_dp- > > > > > > dpcd[DP_MAX_LINK_RATE], > > + dpcd_ext[DP_MAX_LINK_RATE]); > > + memcpy(_dp->dpcd[DP_MAX_LINK_RATE], > > + _ext[DP_MAX_LINK_RATE], > > sizeof(u8)); > > + } > > + if (memcmp(_dp- > > > > > > dpcd[DP_DOWNSTREAMPORT_PRESENT], > > + _ext[DP_DOWNSTREAMPORT_PRESENT], > > sizeof(u8))) { > > + DRM_DEBUG_KMS("DPCD: new value for DPCD > > Downstream Port Present previous value %2x new value %2x\n", > > + intel_dp- > > > > > > dpcd[DP_DOWNSTREAMPORT_PRESENT], > > + dpcd_ext[DP_DOWNSTREAMPORT_P > > RE > > SENT]); > > + memcpy(_dp- > > > > > > dpcd[DP_DOWNSTREAMPORT_PRESENT], > > + _ext[DP_DOWNSTREAMPORT_PRESENT > > ], > > + sizeof(u8)); > > + } > > + } > > DRM_DEBUG_KMS("DPCD: %*ph\n", (int) sizeof(intel_dp- > > >dpcd), > > intel_dp->dpcd); > > > > return intel_dp->dpcd[DP_DPCD_REV] != 0; ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH 2/2] drm/i915: implement EXTENDED_RECEIVER_CAPABILITY_FIELD_PRESENT
On Tue, 2018-07-17 at 14:49 -0700, matthew.s.atw...@intel.com wrote: > From: Matt Atwood > > According to DP spec (2.9.3.1 of DP 1.4) if > EXTENDED_RECEIVER_CAPABILITY_FIELD_PRESENT is set the addresses in > DPCD > 02200h through 0220Fh shall contain the DPRX's true capability. These > values will match 0h through Fh, except for DPCD_REV, > MAX_LINK_RATE, DOWN_STREAM_PORT_PRESENT. > > Read from DPCD once for all 3 values as this is an expensive > operation. > Spec mentions that all of address space 02200h through 0220Fh should > contain the right information however currently only 3 values can > differ. > > There is no address space in the intel_dp->dpcd struct for addresses > 02200h through 0220Fh, and since so much of the data is a identical, > simply overwrite the values stored in 0h through Fh with the > values that can be overwritten from addresses 02200h through 0220Fh. > > This patch helps with backward compatibility for devices pre DP1.3. > > v2: read only dpcd values which can be affected, I still see 6 bytes read and 3 copied. > remove incorrect check, > split into drm include changes into separate patch, commit message, > verbose debugging statements during overwrite. > > Signed-off-by: Matt Atwood > --- > drivers/gpu/drm/i915/intel_dp.c | 37 > + > 1 file changed, 37 insertions(+) > > diff --git a/drivers/gpu/drm/i915/intel_dp.c > b/drivers/gpu/drm/i915/intel_dp.c > index dde92e4af5d3..364cf41a8b89 100644 > --- a/drivers/gpu/drm/i915/intel_dp.c > +++ b/drivers/gpu/drm/i915/intel_dp.c > @@ -3738,6 +3738,43 @@ intel_dp_read_dpcd(struct intel_dp *intel_dp) > sizeof(intel_dp->dpcd)) < 0) > return false; /* aux transfer failed */ > > + if (intel_dp->dpcd[DP_TRAINING_AUX_RD_INTERVAL] & > + DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT) { > + uint8_t dpcd_ext[6]; > + > + DRM_DEBUG_KMS("DPCD: Extended Receiver Capability > Field Present, accessing 02200h through 022FFh\n"); > + > + if (drm_dp_dpcd_read(_dp->aux, > DP_DP13_DPCD_REV, > + _ext, sizeof(dpcd_ext)) < 0) > + return false; /* aux transfer failed */ > + > + if (memcmp(_dp->dpcd[DP_DPCD_REV], > _ext[DP_DPCD_REV], > + sizeof(u8))) Why use memcmp and memcmpy if it's just one byte? You could just use "==" > { > + DRM_DEBUG_KMS("DPCD: new value for DPCD > Revision previous value %2x new value %2x\n", > + intel_dp->dpcd[DP_DPCD_REV], > + dpcd_ext[DP_DPCD_REV]); > + memcpy(_dp->dpcd[DP_DPCD_REV], > + _ext[DP_DPCD_REV], > + sizeof(u8)); > + } > + if (memcmp(_dp->dpcd[DP_MAX_LINK_RATE], > + _ext[DP_MAX_LINK_RATE], sizeof(u8))) > { > + DRM_DEBUG_KMS("DPCD: new value for DPCD Max > Link Rate previous value %2x new value %2x\n", > + intel_dp- > >dpcd[DP_MAX_LINK_RATE], > + dpcd_ext[DP_MAX_LINK_RATE]); > + memcpy(_dp->dpcd[DP_MAX_LINK_RATE], > + _ext[DP_MAX_LINK_RATE], > sizeof(u8)); > + } > + if (memcmp(_dp- > >dpcd[DP_DOWNSTREAMPORT_PRESENT], > + _ext[DP_DOWNSTREAMPORT_PRESENT], > sizeof(u8))) { > + DRM_DEBUG_KMS("DPCD: new value for DPCD > Downstream Port Present previous value %2x new value %2x\n", > + intel_dp- > >dpcd[DP_DOWNSTREAMPORT_PRESENT], > + dpcd_ext[DP_DOWNSTREAMPORT_PRE > SENT]); > + memcpy(_dp- > >dpcd[DP_DOWNSTREAMPORT_PRESENT], > + _ext[DP_DOWNSTREAMPORT_PRESENT], > + sizeof(u8)); > + } > + } > DRM_DEBUG_KMS("DPCD: %*ph\n", (int) sizeof(intel_dp->dpcd), > intel_dp->dpcd); > > return intel_dp->dpcd[DP_DPCD_REV] != 0; ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH 10/14] drm/i915: Populate possible_crtcs correctly
On Mon, 2018-06-25 at 14:10 +0300, Ville Syrjälä wrote: > On Thu, Jun 21, 2018 at 06:26:04PM -0700, Dhinakaran Pandiyan wrote: > > > > On Fri, 2018-06-15 at 19:49 +0300, Ville Syrjala wrote: > > > > > > From: Ville Syrjälä > > > > > > Don't advertize non-exisiting crtcs in the encoder possible_crtcs > > > bitmask. > > > > > How do we end up advertising non-existing CRTCs? encoder->crtc_mask > > seems to be populated in the encoder init functions based on > > possible > > pipes. Do you mean pipe and crtc->index can potentially differ? > No. Just that we may sometimes set BIT(PIPE_C) in crtc_mask when > there are only two pipes on the device. > Got it, thanks. Since crtc_mask seems to be initialized based on the platform, we should probably warn if we find out a bit is set incorrectly. With or without that, this patch is Reviewed-by: Dhinakaran Pandiyan > > > > > > > > > > > > Signed-off-by: Ville Syrjälä > > > --- > > > drivers/gpu/drm/i915/intel_display.c | 17 - > > > 1 file changed, 16 insertions(+), 1 deletion(-) > > > > > > diff --git a/drivers/gpu/drm/i915/intel_display.c > > > b/drivers/gpu/drm/i915/intel_display.c > > > index b095899d68a9..3fa9da714403 100644 > > > --- a/drivers/gpu/drm/i915/intel_display.c > > > +++ b/drivers/gpu/drm/i915/intel_display.c > > > @@ -13959,6 +13959,20 @@ static int intel_encoder_clones(struct > > > intel_encoder *encoder) > > > return index_mask; > > > } > > > > > > +static int intel_encoder_crtcs(struct intel_encoder *encoder) > > > +{ > > > + struct drm_device *dev = encoder->base.dev; > > > + struct intel_crtc *crtc; > > > + int index_mask = 0; > > > + > > > + for_each_intel_crtc(dev, crtc) { > > > + if (encoder->crtc_mask & BIT(crtc->pipe)) > > > + index_mask |= drm_crtc_mask( > > > >base); > > > + } > > > + > > > + return index_mask; > > > +} > > > + > > > static bool has_edp_a(struct drm_i915_private *dev_priv) > > > { > > > if (!IS_MOBILE(dev_priv)) > > > @@ -14211,7 +14225,8 @@ static void intel_setup_outputs(struct > > > drm_i915_private *dev_priv) > > > intel_psr_init(dev_priv); > > > > > > for_each_intel_encoder(_priv->drm, encoder) { > > > - encoder->base.possible_crtcs = encoder- > > > >crtc_mask; > > > + encoder->base.possible_crtcs = > > > + intel_encoder_crtcs(encoder); > > > encoder->base.possible_clones = > > > intel_encoder_clones(encoder); > > > } ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH 10/14] drm/i915: Populate possible_crtcs correctly
On Fri, 2018-06-15 at 19:49 +0300, Ville Syrjala wrote: > From: Ville Syrjälä > > Don't advertize non-exisiting crtcs in the encoder possible_crtcs > bitmask. > How do we end up advertising non-existing CRTCs? encoder->crtc_mask seems to be populated in the encoder init functions based on possible pipes. Do you mean pipe and crtc->index can potentially differ? > Signed-off-by: Ville Syrjälä > --- > drivers/gpu/drm/i915/intel_display.c | 17 - > 1 file changed, 16 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/intel_display.c > b/drivers/gpu/drm/i915/intel_display.c > index b095899d68a9..3fa9da714403 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -13959,6 +13959,20 @@ static int intel_encoder_clones(struct > intel_encoder *encoder) > return index_mask; > } > > +static int intel_encoder_crtcs(struct intel_encoder *encoder) > +{ > + struct drm_device *dev = encoder->base.dev; > + struct intel_crtc *crtc; > + int index_mask = 0; > + > + for_each_intel_crtc(dev, crtc) { > + if (encoder->crtc_mask & BIT(crtc->pipe)) > + index_mask |= drm_crtc_mask(>base); > + } > + > + return index_mask; > +} > + > static bool has_edp_a(struct drm_i915_private *dev_priv) > { > if (!IS_MOBILE(dev_priv)) > @@ -14211,7 +14225,8 @@ static void intel_setup_outputs(struct > drm_i915_private *dev_priv) > intel_psr_init(dev_priv); > > for_each_intel_encoder(_priv->drm, encoder) { > - encoder->base.possible_crtcs = encoder->crtc_mask; > + encoder->base.possible_crtcs = > + intel_encoder_crtcs(encoder); > encoder->base.possible_clones = > intel_encoder_clones(encoder); > } ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH 11/14] drm/i915: Fix DP-MST crtc_mask
On Fri, 2018-06-15 at 21:43 +0300, Ville Syrjälä wrote: > On Fri, Jun 15, 2018 at 11:33:01AM -0700, Dhinakaran Pandiyan wrote: > > > > On Fri, 2018-06-15 at 19:49 +0300, Ville Syrjala wrote: > > > > > > From: Ville Syrjälä > > > > > > Each fake MST encoder is tied to a specific pipe. Fix the > > > encoder's > > > crtc_mask to reflect that fact. > > > > > > Signed-off-by: Ville Syrjälä > > > --- > > > drivers/gpu/drm/i915/intel_dp_mst.c | 2 +- > > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > > > diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c > > > b/drivers/gpu/drm/i915/intel_dp_mst.c > > > index 5890500a3a8b..8e30765402b4 100644 > > > --- a/drivers/gpu/drm/i915/intel_dp_mst.c > > > +++ b/drivers/gpu/drm/i915/intel_dp_mst.c > > > @@ -565,7 +565,7 @@ intel_dp_create_fake_mst_encoder(struct > > > intel_digital_port *intel_dig_port, enum > > > intel_encoder->type = INTEL_OUTPUT_DP_MST; > > > intel_encoder->power_domain = intel_dig_port- > > > > > > > > base.power_domain; > > > intel_encoder->port = intel_dig_port->base.port; > > > - intel_encoder->crtc_mask = 0x7; > > > + intel_encoder->crtc_mask = BIT(pipe); > > How did this not cause any problems? Does this mean this field > > was/is > > unused? > This is a hint to userspace. So userspace would pick the connector > and crtc based on the hints, and then the kernel gets to pick the > actual encoder. In this case the bogus hint was good enough to tell > userspace that it can pick any crtc for any MST connector. > > Hmm. Why on earth do we have .atomic_best_encoder() and > .best_encoder() > for MST? The fb_helper appears to want to use the non-atomic one for > some reason... On boy, I guess I'll need to do something about that. > As is this patch would probably break it :( > So we end up picking crtc-0 for all MST connectors with the same primary. Since this patch does the right thing and assuming https://patchwork.freedesktop.org/patch/229905/ gets merged before this Reviewed-by: Dhinakaran Pandiyan ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH 11/14] drm/i915: Fix DP-MST crtc_mask
On Fri, 2018-06-15 at 19:49 +0300, Ville Syrjala wrote: > From: Ville Syrjälä > > Each fake MST encoder is tied to a specific pipe. Fix the encoder's > crtc_mask to reflect that fact. > > Signed-off-by: Ville Syrjälä > --- > drivers/gpu/drm/i915/intel_dp_mst.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c > b/drivers/gpu/drm/i915/intel_dp_mst.c > index 5890500a3a8b..8e30765402b4 100644 > --- a/drivers/gpu/drm/i915/intel_dp_mst.c > +++ b/drivers/gpu/drm/i915/intel_dp_mst.c > @@ -565,7 +565,7 @@ intel_dp_create_fake_mst_encoder(struct > intel_digital_port *intel_dig_port, enum > intel_encoder->type = INTEL_OUTPUT_DP_MST; > intel_encoder->power_domain = intel_dig_port- > >base.power_domain; > intel_encoder->port = intel_dig_port->base.port; > - intel_encoder->crtc_mask = 0x7; > + intel_encoder->crtc_mask = BIT(pipe); How did this not cause any problems? Does this mean this field was/is unused? Disclaimer: I didn't look at the whole series. > intel_encoder->cloneable = 0; > > intel_encoder->compute_config = intel_dp_mst_compute_config; ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 3/6] drm/psr: Fix missed entry in PSR setup time table.
Entry corresponding to 220 us setup time was missing. I am not aware of any specific bug this fixes, but this could potentially result in enabling PSR on a panel with a higher setup time requirement than supported by the hardware. I verified the value is present in eDP spec versions 1.3, 1.4 and 1.4a. Fixes: 6608804b3d7f ("drm/dp: Add drm_dp_psr_setup_time()") Cc: sta...@vger.kernel.org Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> Cc: Jose Roberto de Souza <jose.so...@intel.com> Cc: dri-devel@lists.freedesktop.org Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/drm_dp_helper.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 36c7609a4bd5..a7ba602a43a8 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -1159,6 +1159,7 @@ int drm_dp_psr_setup_time(const u8 psr_cap[EDP_PSR_RECEIVER_CAP_SIZE]) static const u16 psr_setup_time_us[] = { PSR_SETUP_TIME(330), PSR_SETUP_TIME(275), + PSR_SETUP_TIME(220), PSR_SETUP_TIME(165), PSR_SETUP_TIME(110), PSR_SETUP_TIME(55), -- 2.14.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/psr: Fix missed entry in PSR setup time table.
On Fri, 2018-05-11 at 18:03 +, Souza, Jose wrote: > On Thu, 2018-05-10 at 17:54 -0700, Dhinakaran Pandiyan wrote: > > > > Entry corresponding to 220 us setup time was missing. I am not > > aware > > of > > any specific bug this fixes, but this could potentially result in > > enabling > > PSR on a panel with a higher setup time requirement than supported > > by > > the > > hardware. > It should be 'a lower setup time'. > Sink sets 2h requesting 220us but source will only wait 165us. By hardware, I meant source :) We'll end up enabling PSR on a sink with a higher setup time requirement (220us) than supported by the source hardware (let's say 200 us) because we read the sink requirement as 165 us. > > Other than that looks good: > Reviewed-by: José Roberto de Souza <jose.so...@intel.com> > Thanks! I'll resend this along the other PSR patch you reviewed. > > > > > > I verified the value is present in eDP spec versions 1.3, 1.4 and > > 1.4a. > > > > Fixes: 6608804b3d7f ("drm/dp: Add drm_dp_psr_setup_time()") > > Cc: sta...@vger.kernel.org > > Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> > > Cc: Jose Roberto de Souza <jose.so...@intel.com> > > Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> > > --- > > drivers/gpu/drm/drm_dp_helper.c | 1 + > > 1 file changed, 1 insertion(+) > > > > diff --git a/drivers/gpu/drm/drm_dp_helper.c > > b/drivers/gpu/drm/drm_dp_helper.c > > index 36c7609a4bd5..a7ba602a43a8 100644 > > --- a/drivers/gpu/drm/drm_dp_helper.c > > +++ b/drivers/gpu/drm/drm_dp_helper.c > > @@ -1159,6 +1159,7 @@ int drm_dp_psr_setup_time(const u8 > > psr_cap[EDP_PSR_RECEIVER_CAP_SIZE]) > > static const u16 psr_setup_time_us[] = { > > PSR_SETUP_TIME(330), > > PSR_SETUP_TIME(275), > > + PSR_SETUP_TIME(220), > > PSR_SETUP_TIME(165), > > PSR_SETUP_TIME(110), > > PSR_SETUP_TIME(55), ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH v7 02/10] drm/i915: Move DP modeset retry work into intel_dp
On Wed, 2018-04-11 at 18:54 -0400, Lyude Paul wrote: > While having the modeset_retry_work in intel_connector makes sense with > SST, this paradigm doesn't make a whole ton of sense when it comes to > MST since we have to deal with multiple connectors. In most cases, it's > more useful to just use the intel_dp struct since it indicates whether > or not we're dealing with an MST device, along with being able to easily > trace the intel_dp struct back to it's respective connector (if there is > any). So, move the modeset_retry_work function out of the > intel_connector struct and into intel_dp. > > Signed-off-by: Lyude Paul> Reviewed-by: Manasi Navare > Cc: Manasi Navare > Cc: Ville Syrjälä > > V2: > - Remove accidental duplicate modeset_retry_work in intel_connector > V3: > - Also check against eDP in intel_hpd_poll_fini() - mdnavare contradicts with commit c0cfb10d9e1de490e36d3b9d4228c0ea0ca30677 Author: Manasi Navare Date: Thu Oct 12 12:13:38 2017 -0700 drm/i915/edp: Do not do link training fallback or prune modes on EDP In case of eDP because the panel has a fixed mode, the link rate and lane count at which it is trained corresponds to the link BW required to support the native resolution of the panel. In case of panles with lower resolutions where fewer lanes are hooked up internally, that number is reflected in the MAX_LANE_COUNT DPCD register of the panel. So it is pointless to fallback to lower link rate/lane count in case of link training failure on eDP connector since the lower link BW will not support the native resolution of the panel and we cannot prune the preferred mode on the eDP connector. > V4: > - Don't bother looping over connectors for canceling modeset rety work, >just encoders. > V7: > - Fix CHECKPATCH errors > Signed-off-by: Lyude Paul > --- > drivers/gpu/drm/i915/intel_display.c | 14 +++--- > drivers/gpu/drm/i915/intel_dp.c | 10 -- > drivers/gpu/drm/i915/intel_dp_link_training.c | 2 +- > drivers/gpu/drm/i915/intel_drv.h | 6 +++--- > 4 files changed, 19 insertions(+), 13 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_display.c > b/drivers/gpu/drm/i915/intel_display.c > index e04050ea3e28..18edb9628a54 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -15471,20 +15471,28 @@ void intel_connector_unregister(struct > drm_connector *connector) > > static void intel_hpd_poll_fini(struct drm_device *dev) > { > - struct intel_connector *connector; > struct drm_connector_list_iter conn_iter; > + struct intel_connector *connector; > + struct intel_encoder *encoder; > + struct intel_dp *intel_dp; > > /* Kill all the work that may have been queued by hpd. */ > drm_connector_list_iter_begin(dev, _iter); > for_each_intel_connector_iter(connector, _iter) { > - if (connector->modeset_retry_work.func) > - cancel_work_sync(>modeset_retry_work); > if (connector->hdcp_shim) { > cancel_delayed_work_sync(>hdcp_check_work); > cancel_work_sync(>hdcp_prop_work); > } > } > drm_connector_list_iter_end(_iter); > + > + for_each_intel_encoder(dev, encoder) { > + if (encoder->type == INTEL_OUTPUT_DP || commit 7e732cacb1ae27b2eb6902cabd93e9da086c54f0 Author: Ville Syrjälä Date: Fri Oct 27 22:31:24 2017 +0300 drm/i915: Stop frobbing with DDI encoder->type Currently the DDI encoder->type will change at runtime depending on what kind of hotplugs we've processed. That's quite bad since we can't really trust that that current value of encoder->type actually matches the type of signal we're trying to drive through it. Let's eliminate that problem by declaring that non-eDP DDI port will always have the encoder type as INTEL_OUTPUT_DDI. This means the code can no longer try to distinguish DP vs. HDMI based on encoder->type. We'll leave eDP as INTEL_OUTPUT_EDP, since it'll never change and there's a bunch of code that relies on that value to identify eDP encoders. > + encoder->type == INTEL_OUTPUT_EDP) { > + intel_dp = enc_to_intel_dp(>base); > + cancel_work_sync(_dp->modeset_retry_work); > + } > + } > } > > void intel_modeset_cleanup(struct drm_device *dev) > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c > index 62f82c4298ac..fbb467bc227d 100644 > --- a/drivers/gpu/drm/i915/intel_dp.c > +++ b/drivers/gpu/drm/i915/intel_dp.c > @@ -6249,12 +6249,10 @@ static bool intel_edp_init_connector(struct intel_dp > *intel_dp, > >
Re: [Intel-gfx] [PATCH v8 01/10] drm/atomic: Print debug message on atomic check failure
On Wed, 2018-04-11 at 19:42 -0400, Lyude Paul wrote: > Does what it says on the label, it's a little confusing debugging atomic > check failures otherwise. > > Cc: Manasi Navare <manasi.d.nav...@intel.com> > Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> > Signed-off-by: Lyude Paul <ly...@redhat.com> > --- > drivers/gpu/drm/drm_atomic.c | 5 - > 1 file changed, 4 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c > index 7d25c42f22db..972a7e9634ab 100644 > --- a/drivers/gpu/drm/drm_atomic.c > +++ b/drivers/gpu/drm/drm_atomic.c > @@ -1705,8 +1705,11 @@ int drm_atomic_check_only(struct drm_atomic_state > *state) > if (config->funcs->atomic_check) > ret = config->funcs->atomic_check(state->dev, state); > > - if (ret) > + if (ret) { > + DRM_DEBUG_ATOMIC("atomic driver check for %p failed: %d\n", > + state, ret); > return ret; > + } > nit: Would have slightly looked better if the 'ret' check was moved inside the branch for funcs->atomic_check. Reviewed-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> > if (!state->allow_modeset) { > for_each_new_crtc_in_state(state, crtc, crtc_state, i) { ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v4] drm/i915/dp: Send DPCD ON for MST before phy_up
On Fri, 2018-04-06 at 14:52 -0400, Lyude Paul wrote: > When doing a modeset where the sink is transitioning from D3 to D0 , it > would sometimes be possible for the initial power_up_phy() to start > timing out. This would only be observed in the last action before the > sink went into D3 mode was intel_dp_sink_dpms(DRM_MODE_DPMS_OFF). We > originally thought this might be an issue with us accidentally shutting > off the aux block when putting the sink into D3, but since the DP spec > mandates that sinks must wake up within 1ms while we have 100ms to > respond to an ESI irq, this didn't really add up. Turns out that the > problem is more subtle then that: > > It turns out that the timeout is from us not enabling DPMS on the MST > hub before actually trying to initiate sideband communications. This > would cause the first sideband communication (power_up_phy()), to start > timing out because the sink wasn't ready to respond. Afterwards, we > would call intel_dp_sink_dpms(DRM_MODE_DPMS_ON) in > intel_ddi_pre_enable_dp(), which would actually result in waking up the > sink so that sideband requests would work again. > > Since DPMS is what lets us actually bring the hub up into a state where > sideband communications become functional again, we just need to make > sure to enable DPMS on the display before attempting to perform sideband > communications. > Matches my understanding of the problem Reviewed-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> It's better to get an ack from Ville considering I was okay with the D3_AUX_ON solution too. > Changes since v1: > - Remove comment above if (!intel_dp->is_mst) - vsryjala > - Move intel_dp_sink_dpms() for MST into intel_dp_post_disable_mst() to > keep enable/disable paths symmetrical > - Improve commit message - dhnkrn > Changes since v2: > - Only send DPMS off when we're disabling the last sink, and only send > DPMS on when we're enabling the first sink - dhnkrn > Changes since v3: > - Check against is_mst, not intel_dp->is_mst - dhnkrn/vsyrjala > > Signed-off-by: Lyude Paul <ly...@redhat.com> > Cc: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> > Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> > Cc: Laura Abbott <labb...@redhat.com> > Cc: sta...@vger.kernel.org > Fixes: ad260ab32a4d9 ("drm/i915/dp: Write to SET_POWER dpcd to enable MST > hub.") > --- > drivers/gpu/drm/i915/intel_ddi.c| 8 ++-- > drivers/gpu/drm/i915/intel_dp_mst.c | 8 +++- > 2 files changed, 13 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_ddi.c > b/drivers/gpu/drm/i915/intel_ddi.c > index a6672a9abd85..92cb26b18a9b 100644 > --- a/drivers/gpu/drm/i915/intel_ddi.c > +++ b/drivers/gpu/drm/i915/intel_ddi.c > @@ -2324,7 +2324,8 @@ static void intel_ddi_pre_enable_dp(struct > intel_encoder *encoder, > intel_prepare_dp_ddi_buffers(encoder, crtc_state); > > intel_ddi_init_dp_buf_reg(encoder); > - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); > + if (!is_mst) > + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); > intel_dp_start_link_train(intel_dp); > if (port != PORT_A || INTEL_GEN(dev_priv) >= 9) > intel_dp_stop_link_train(intel_dp); > @@ -2422,12 +2423,15 @@ static void intel_ddi_post_disable_dp(struct > intel_encoder *encoder, > struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); > struct intel_digital_port *dig_port = enc_to_dig_port(>base); > struct intel_dp *intel_dp = _port->dp; > + bool is_mst = intel_crtc_has_type(old_crtc_state, > + INTEL_OUTPUT_DP_MST); > > /* >* Power down sink before disabling the port, otherwise we end >* up getting interrupts from the sink on detecting link loss. >*/ > - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); > + if (!is_mst) > + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); > > intel_disable_ddi_buf(encoder); > > diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c > b/drivers/gpu/drm/i915/intel_dp_mst.c > index c3de0918ee13..9e6956c08688 100644 > --- a/drivers/gpu/drm/i915/intel_dp_mst.c > +++ b/drivers/gpu/drm/i915/intel_dp_mst.c > @@ -180,9 +180,11 @@ static void intel_mst_post_disable_dp(struct > intel_encoder *encoder, > intel_dp->active_mst_links--; > > intel_mst->connector = NULL; > - if (intel_dp->active_mst_links == 0) > + if (intel_dp->active_mst_links == 0) { > + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); > intel_dig_port->base.post_disable(_dig_port->base,
Re: [Intel-gfx] [PATCH v3] drm/i915/dp: Send DPCD ON for MST before phy_up
On Thu, 2018-04-05 at 17:19 -0400, Lyude Paul wrote: > When doing a modeset where the sink is transitioning from D3 to D0 , it > would sometimes be possible for the initial power_up_phy() to start > timing out. This would only be observed in the last action before the > sink went into D3 mode was intel_dp_sink_dpms(DRM_MODE_DPMS_OFF). We > originally thought this might be an issue with us accidentally shutting > off the aux block when putting the sink into D3, but since the DP spec > mandates that sinks must wake up within 1ms while we have 100ms to > respond to an ESI irq, this didn't really add up. Turns out that the > problem is more subtle then that: > > It turns out that the timeout is from us not enabling DPMS on the MST > hub before actually trying to initiate sideband communications. This > would cause the first sideband communication (power_up_phy()), to start > timing out because the sink wasn't ready to respond. Afterwards, we > would call intel_dp_sink_dpms(DRM_MODE_DPMS_ON) in > intel_ddi_pre_enable_dp(), which would actually result in waking up the > sink so that sideband requests would work again. > > Since DPMS is what lets us actually bring the hub up into a state where > sideband communications become functional again, we just need to make > sure to enable DPMS on the display before attempting to perform sideband > communications. > > Changes since v1: > - Remove comment above if (!intel_dp->is_mst) - vsryjala > - Move intel_dp_sink_dpms() for MST into intel_dp_post_disable_mst() to > keep enable/disable paths symmetrical > - Improve commit message - dhnkrn > Changes since v2: > - Only send DPMS off when we're disabling the last sink, and only send > DPMS on when we're enabling the first sink - dhnkrn > > Signed-off-by: Lyude Paul <ly...@redhat.com> > Cc: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> > Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> > Cc: Laura Abbott <labb...@redhat.com> > Cc: sta...@vger.kernel.org > Fixes: ad260ab32a4d9 ("drm/i915/dp: Write to SET_POWER dpcd to enable MST > hub.") > --- > drivers/gpu/drm/i915/intel_ddi.c| 6 -- > drivers/gpu/drm/i915/intel_dp_mst.c | 8 +++- > 2 files changed, 11 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_ddi.c > b/drivers/gpu/drm/i915/intel_ddi.c > index a6672a9abd85..c0bf7419e1c1 100644 > --- a/drivers/gpu/drm/i915/intel_ddi.c > +++ b/drivers/gpu/drm/i915/intel_ddi.c > @@ -2324,7 +2324,8 @@ static void intel_ddi_pre_enable_dp(struct > intel_encoder *encoder, > intel_prepare_dp_ddi_buffers(encoder, crtc_state); > > intel_ddi_init_dp_buf_reg(encoder); > - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); > + if (!intel_dp->is_mst) > + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); I believe Ville recommended to check for is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST) here. The question is, are there cases where intel_dp->is_mst != is_mst? A disconnect in the middle of a modeset would cause intel_dp->is_mst to be false, wouldn't it? ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [PATCH] drm/i915/dp: Send DPCD ON for MST before phy_up
On Thu, 2018-04-05 at 19:38 +0300, Ville Syrjälä wrote: > On Wed, Apr 04, 2018 at 07:27:21PM -0400, Lyude Paul wrote: > > As it turns out, the aux block being off was not the real problem here, > > as transition from D3 to D0 is mandated by the DP spec to take a maximum > > of 1ms, whereas we're allowed a 100ms timeframe to respond to ESI irqs. > > The real problem here is a bit more subtle. > > > > When doing a modeset where the problem of the sink timing out to our > > sideband requests when transitioning from D3 to D0 occurs, the timeout > > is from the aux block not coming on. However, nothing else times out > > other than the initial phy_up message because the DPCD on call in > > intel_ddi_enable_dp() ends up waking up the AUX block on the hub, not > > the phy_up sideband message. This is the case only when intel_dp_sink_dpms(DRM_MODE_DPMS_OFF) was the last action. With power_down_phy in post_disable() and power_up_phy in pre_enable(), we weren't seeing this issue. > This means that the real fix we need is to > > use the DPMS on before sending a phy_up to ensure that the hub is ready > > to accept sideband messages. > > > > Signed-off-by: Lyude Paul <ly...@redhat.com> > > Cc: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> > > Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> > > Cc: Laura Abbott <labb...@redhat.com> > > Cc: sta...@vger.kernel.org > > Fixes: ad260ab32a4d9 ("drm/i915/dp: Write to SET_POWER dpcd to enable MST > > hub.") > > --- > > drivers/gpu/drm/i915/intel_ddi.c| 6 +- > > drivers/gpu/drm/i915/intel_dp_mst.c | 1 + > > 2 files changed, 6 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/i915/intel_ddi.c > > b/drivers/gpu/drm/i915/intel_ddi.c > > index a6672a9abd85..9bd675f73f7b 100644 > > --- a/drivers/gpu/drm/i915/intel_ddi.c > > +++ b/drivers/gpu/drm/i915/intel_ddi.c > > @@ -2324,7 +2324,11 @@ static void intel_ddi_pre_enable_dp(struct > > intel_encoder *encoder, > > intel_prepare_dp_ddi_buffers(encoder, crtc_state); > > > > intel_ddi_init_dp_buf_reg(encoder); > > - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); > > + /* for MST, we do DPMS_ON outside of here so that DPMS_ON can happen > > +* before drm_dp_send_power_updown_phy() > > +*/ > > + if (!intel_dp->is_mst) > > Just 'is_mst' should do here. > > And in general I'd like to see the enable and disable paths remain > symmetric. Ie. also move out the dpms call in the disable path (or > maybe move the phy_power_up/down in?). > > > + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); > > intel_dp_start_link_train(intel_dp); > > if (port != PORT_A || INTEL_GEN(dev_priv) >= 9) > > intel_dp_stop_link_train(intel_dp); > > diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c > > b/drivers/gpu/drm/i915/intel_dp_mst.c > > index c3de0918ee13..eff9a4eae1f0 100644 > > --- a/drivers/gpu/drm/i915/intel_dp_mst.c > > +++ b/drivers/gpu/drm/i915/intel_dp_mst.c > > @@ -223,6 +223,7 @@ static void intel_mst_pre_enable_dp(struct > > intel_encoder *encoder, > > > > DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links); > > > > + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); > > drm_dp_send_power_updown_phy(_dp->mst_mgr, connector->port, true); > > This could use a comment to remind people that the order does matter. > > > if (intel_dp->active_mst_links == 0) > > intel_dig_port->base.pre_enable(_dig_port->base, > > -- > > 2.14.3 > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/doc: Fix documentation for _vblank_restore().
No code changes, fixes doc build warnings and polish some doc text. Reported-by: Daniel Vetter <daniel.vet...@ffwll.ch> Cc: Rodrigo Vivi <rodrigo.v...@intel.com> Cc: Daniel Vetter <daniel.vet...@ffwll.ch> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/drm_vblank.c | 22 ++ 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index c781cb426bf1..51041eec0047 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -1238,12 +1238,15 @@ void drm_crtc_vblank_on(struct drm_crtc *crtc) EXPORT_SYMBOL(drm_crtc_vblank_on); /** - * drm_vblank_restore - estimated vblanks using timestamps and update it. + * drm_vblank_restore - estimate missed vblanks and update vblank count. + * @dev: DRM device + * @pipe: CRTC index * * Power manamement features can cause frame counter resets between vblank - * disable and enable. Drivers can then use this function in their - * _crtc_funcs.enable_vblank implementation to estimate the vblanks since - * the last _crtc_funcs.disable_vblank. + * disable and enable. Drivers can use this function in their + * _crtc_funcs.enable_vblank implementation to estimate missed vblanks since + * the last _crtc_funcs.disable_vblank using timestamps and update the + * vblank counter. * * This function is the legacy version of drm_crtc_vblank_restore(). */ @@ -1284,11 +1287,14 @@ void drm_vblank_restore(struct drm_device *dev, unsigned int pipe) EXPORT_SYMBOL(drm_vblank_restore); /** - * drm_crtc_vblank_restore - estimate vblanks using timestamps and update it. + * drm_crtc_vblank_restore - estimate missed vblanks and update vblank count. + * @crtc: CRTC in question + * * Power manamement features can cause frame counter resets between vblank - * disable and enable. Drivers can then use this function in their - * _crtc_funcs.enable_vblank implementation to estimate the vblanks since - * the last _crtc_funcs.disable_vblank. + * disable and enable. Drivers can use this function in their + * _crtc_funcs.enable_vblank implementation to estimate missed vblanks since + * the last _crtc_funcs.disable_vblank using timestamps and update the + * vblank counter. */ void drm_crtc_vblank_restore(struct drm_crtc *crtc) { -- 2.14.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 07/10] drm/atomic: Handle 64-bit return from drm_crtc_vblank_count()
570e86963a51 ("drm: Widen vblank count to 64-bits [v3]") changed the return type for drm_crtc_vblank_count() to u64. The flip ioctl receives a 32-bit target sequence from user space and is compared against the current sequence from drm_crtc_vblank_count(). So, typecast return from drm_crtc_vblank_count() explicitly to add clarity. __drm_crtcs_state.last_vblank_count however only ever stores the value from drm_crtc_vblank_count() and can be upgraded to u64. Cc: Keith Packard <kei...@keithp.com> Cc: Rodrigo Vivi <rodrigo.v...@intel.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/drm_plane.c | 2 +- include/drm/drm_atomic.h| 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 22b54663b6e7..09de6ecb3968 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -948,7 +948,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, if (r) return r; - current_vblank = drm_crtc_vblank_count(crtc); + current_vblank = (u32)drm_crtc_vblank_count(crtc); switch (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) { case DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE: diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index cf13842a6dbd..2c711a24c80c 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -154,7 +154,7 @@ struct __drm_crtcs_state { struct drm_crtc *ptr; struct drm_crtc_state *state, *old_state, *new_state; s32 __user *out_fence_ptr; - unsigned last_vblank_count; + u64 last_vblank_count; }; struct __drm_connnectors_state { -- 2.14.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 09/10] drm/vblank: Restoring vblank counts after device PM events.
From: "Pandiyan, Dhinakaran" <dhinakaran.pandi...@intel.com> The HW frame counter can get reset if device enters a low power state after vblank interrupts were disabled. This messes up any following vblank count update as a negative diff (huge unsigned diff) is calculated from the HW frame counter change. We cannot ignore negative diffs altogther as there could be legitimate wrap arounds. So, allow drivers to update vblank->count with missed vblanks for the time interrupts were disabled. This is similar to _crtc_vblank_on() except that vblanks interrupts are not enabled at the end as this function is expected to be called from the driver _enable_vblank() vfunc. v2: drm_crtc_vblank_restore should take crtc as arg. (Chris) Add docs and sprinkle some asserts. Cc: Daniel Vetter <daniel.vet...@ffwll.ch> Cc: Chris Wilson <ch...@chris-wilson.co.uk> Cc: Michel Dänzer <mic...@daenzer.net> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.v...@intel.com> Acked-by: Daniel Vetter <daniel.vet...@ffwll.ch> --- drivers/gpu/drm/drm_vblank.c | 59 include/drm/drm_vblank.h | 2 ++ 2 files changed, 61 insertions(+) diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 913954765d9e..c781cb426bf1 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -1237,6 +1237,65 @@ void drm_crtc_vblank_on(struct drm_crtc *crtc) } EXPORT_SYMBOL(drm_crtc_vblank_on); +/** + * drm_vblank_restore - estimated vblanks using timestamps and update it. + * + * Power manamement features can cause frame counter resets between vblank + * disable and enable. Drivers can then use this function in their + * _crtc_funcs.enable_vblank implementation to estimate the vblanks since + * the last _crtc_funcs.disable_vblank. + * + * This function is the legacy version of drm_crtc_vblank_restore(). + */ +void drm_vblank_restore(struct drm_device *dev, unsigned int pipe) +{ + ktime_t t_vblank; + struct drm_vblank_crtc *vblank; + int framedur_ns; + u64 diff_ns; + u32 cur_vblank, diff = 1; + int count = DRM_TIMESTAMP_MAXRETRIES; + + if (WARN_ON(pipe >= dev->num_crtcs)) + return; + + assert_spin_locked(>vbl_lock); + assert_spin_locked(>vblank_time_lock); + + vblank = >vblank[pipe]; + WARN_ONCE((drm_debug & DRM_UT_VBL) && !vblank->framedur_ns, + "Cannot compute missed vblanks without frame duration\n"); + framedur_ns = vblank->framedur_ns; + + do { + cur_vblank = __get_vblank_counter(dev, pipe); + drm_get_last_vbltimestamp(dev, pipe, _vblank, false); + } while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0); + + diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time)); + if (framedur_ns) + diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns); + + + DRM_DEBUG_VBL("missed %d vblanks in %lld ns, frame duration=%d ns, hw_diff=%d\n", + diff, diff_ns, framedur_ns, cur_vblank - vblank->last); + store_vblank(dev, pipe, diff, t_vblank, cur_vblank); +} +EXPORT_SYMBOL(drm_vblank_restore); + +/** + * drm_crtc_vblank_restore - estimate vblanks using timestamps and update it. + * Power manamement features can cause frame counter resets between vblank + * disable and enable. Drivers can then use this function in their + * _crtc_funcs.enable_vblank implementation to estimate the vblanks since + * the last _crtc_funcs.disable_vblank. + */ +void drm_crtc_vblank_restore(struct drm_crtc *crtc) +{ + drm_vblank_restore(crtc->dev, drm_crtc_index(crtc)); +} +EXPORT_SYMBOL(drm_crtc_vblank_restore); + static void drm_legacy_vblank_pre_modeset(struct drm_device *dev, unsigned int pipe) { diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h index a4c3b0a0a197..16d46e2a6854 100644 --- a/include/drm/drm_vblank.h +++ b/include/drm/drm_vblank.h @@ -180,6 +180,8 @@ void drm_crtc_vblank_off(struct drm_crtc *crtc); void drm_crtc_vblank_reset(struct drm_crtc *crtc); void drm_crtc_vblank_on(struct drm_crtc *crtc); u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc); +void drm_vblank_restore(struct drm_device *dev, unsigned int pipe); +void drm_crtc_vblank_restore(struct drm_crtc *crtc); bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, unsigned int pipe, int *max_error, -- 2.14.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 08/10] drm/vblank: Do not update vblank count if interrupts are already disabled.
From: "Pandiyan, Dhinakaran" <dhinakaran.pandi...@intel.com> Updating vblank counts requires register reads and these reads may not return meaningful values if the device was in a low power state after vblank interrupts were last disabled. So, update the count only if vblank interrupts are enabled. Secondly, this means the registers should be read before disabling vblank interrupts. v2: Don't check vblank->enabled outside it's lock (Chris) Cc: Chris Wilson <ch...@chris-wilson.co.uk> Cc: Daniel Vetter <daniel.vet...@ffwll.ch> Cc: Michel Dänzer <mic...@daenzer.net> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.v...@intel.com> Acked-by: Daniel Vetter <daniel.vet...@ffwll.ch> --- drivers/gpu/drm/drm_vblank.c | 18 ++ 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index f0d3ed5f2528..913954765d9e 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -347,23 +347,25 @@ void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe) spin_lock_irqsave(>vblank_time_lock, irqflags); /* -* Only disable vblank interrupts if they're enabled. This avoids -* calling the ->disable_vblank() operation in atomic context with the -* hardware potentially runtime suspended. +* Update vblank count and disable vblank interrupts only if the +* interrupts were enabled. This avoids calling the ->disable_vblank() +* operation in atomic context with the hardware potentially runtime +* suspended. */ - if (vblank->enabled) { - __disable_vblank(dev, pipe); - vblank->enabled = false; - } + if (!vblank->enabled) + goto out; /* -* Always update the count and timestamp to maintain the +* Update the count and timestamp to maintain the * appearance that the counter has been ticking all along until * this time. This makes the count account for the entire time * between drm_crtc_vblank_on() and drm_crtc_vblank_off(). */ drm_update_vblank_count(dev, pipe, false); + __disable_vblank(dev, pipe); + vblank->enabled = false; +out: spin_unlock_irqrestore(>vblank_time_lock, irqflags); } -- 2.14.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 06/10] drm/tegra: Handle 64-bit return from drm_crtc_vblank_count()
570e86963a51 ("drm: Widen vblank count to 64-bits [v3]") changed the return type for drm_crtc_vblank_count() to u64. This could cause potential problems if the return value is used in arithmetic operations with a 32-bit reference HW vblank count. Explicitly typecasting this down to u32 either fixes a potential problem or serves to add clarity in case the implicit typecasting was already correct. Cc: Keith Packard <kei...@keithp.com> Cc: Thierry Reding <tred...@nvidia.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/tegra/dc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index b8403ed48285..49df2db2ad46 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1359,7 +1359,7 @@ static u32 tegra_dc_get_vblank_counter(struct drm_crtc *crtc) return host1x_syncpt_read(dc->syncpt); /* fallback to software emulated VBLANK counter */ - return drm_crtc_vblank_count(>base); + return (u32)drm_crtc_vblank_count(>base); } static int tegra_dc_enable_vblank(struct drm_crtc *crtc) -- 2.14.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 02/10] drm/i915/vblank: Make the vblank counter u64 -> u32 typecast explicit
Core returns a u64 vblank count and intel_crtc_get_vblank_counter() expects a 32-bit value. Make the typecast explicit to add clarity. Cc: Keith Packard <kei...@keithp.com> Cc: Rodrigo Vivi <rodrigo.v...@intel.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ad8d9c6c40e4..f6b450de653c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12075,7 +12075,7 @@ u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc) struct drm_device *dev = crtc->base.dev; if (!dev->max_vblank_count) - return drm_crtc_accurate_vblank_count(>base); + return (u32)drm_crtc_accurate_vblank_count(>base); return dev->driver->get_vblank_counter(dev, crtc->pipe); } -- 2.14.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 05/10] drm/radeon: Handle 64-bit return from drm_crtc_vblank_count()
570e86963a51 ("drm: Widen vblank count to 64-bits [v3]") changed the return type for drm_crtc_vblank_count() to u64. This could cause potential problems if the return value is used in arithmetic operations with a 32-bit reference HW vblank count. Explicitly typecasting this down to u32 either fixes a potential problem or serves to add clarity in case the implicit typecasting was already correct. Cc: Keith Packard <kei...@keithp.com> Cc: Alex Deucher <alexander.deuc...@amd.com> Cc: Harry Wentland <harry.wentl...@amd.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/radeon/radeon_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index dfda5e0ed166..26129b2b082d 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -570,7 +570,7 @@ static int radeon_crtc_page_flip_target(struct drm_crtc *crtc, base &= ~7; } work->base = base; - work->target_vblank = target - drm_crtc_vblank_count(crtc) + + work->target_vblank = target - (uint32_t)drm_crtc_vblank_count(crtc) + dev->driver->get_vblank_counter(dev, work->crtc_id); /* We borrow the event spin lock for protecting flip_work */ -- 2.14.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 10/10] drm/i915: Estimate and update missed vblanks.
From: "Pandiyan, Dhinakaran" <dhinakaran.pandi...@intel.com> The frame counter may have got reset between disabling and enabling vblank interrupts due to DMC putting the hardware to DC5/6 states if PSR was active. The frame counter could also have stalled if PSR was active in case there was no DMC. The frame counter resetting has a user visible impact of screen freezes. Make use of drm_vblank_restore() to compute missed vblanks for the duration in which vblank interrupts were disabled and update the vblank counter with this value as diff. There's no need to check if PSR was actually active in the interrupt disabled duration, so simplify the check to a feature check. Enabling vblank interrupts wakes up the hardware from DC5/6 and prevents it from going back again as long as the there are pending interrupts. So, we don't have to explicity disallow DC5/6 after enabling vblank interrupts to keep the counter running. This change is not applicable to CHV, as enabling interrupts does not prevent the hardware from activating PSR. v2: Added comments(Rodrigo) and rewrote commit message. Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> Cc: Rodrigo Vivi <rodrigo.v...@intel.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.v...@intel.com> Acked-by: Daniel Vetter <daniel.vet...@ffwll.ch> --- drivers/gpu/drm/i915/i915_irq.c | 12 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 252feff2892d..e86c645b6b07 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2968,6 +2968,12 @@ static int ironlake_enable_vblank(struct drm_device *dev, unsigned int pipe) ilk_enable_display_irq(dev_priv, bit); spin_unlock_irqrestore(_priv->irq_lock, irqflags); + /* Even though there is no DMC, frame counter can get stuck when +* PSR is active as no frames are generated. +*/ + if (HAS_PSR(dev_priv)) + drm_vblank_restore(dev, pipe); + return 0; } @@ -2980,6 +2986,12 @@ static int gen8_enable_vblank(struct drm_device *dev, unsigned int pipe) bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); spin_unlock_irqrestore(_priv->irq_lock, irqflags); + /* Even if there is no DMC, frame counter can get stuck when +* PSR is active as no frames are generated, so check only for PSR. +*/ + if (HAS_PSR(dev_priv)) + drm_vblank_restore(dev, pipe); + return 0; } -- 2.14.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 04/10] drm/amdgpu: Handle 64-bit return from drm_crtc_vblank_count()
570e86963a51 ("drm: Widen vblank count to 64-bits [v3]") changed the return type for drm_crtc_vblank_count() to u64. This could cause potential problems if the return value is used in arithmetic operations with a 32-bit reference HW vblank count. Explicitly typecasting this down to u32 either fixes a potential problem or serves to add clarity in case the typecasting was implicitly done. Cc: Keith Packard <kei...@keithp.com> Cc: Alex Deucher <alexander.deuc...@amd.com> Cc: Harry Wentland <harry.wentl...@amd.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 2 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 38d47559f098..c2fa5d55f04e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -207,7 +207,7 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, amdgpu_bo_unreserve(new_abo); work->base = base; - work->target_vblank = target - drm_crtc_vblank_count(crtc) + + work->target_vblank = target - (uint32_t)drm_crtc_vblank_count(crtc) + amdgpu_get_vblank_counter_kms(dev, work->crtc_id); /* we borrow the event spin lock for protecting flip_wrok */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 1ce4c98385e3..b7254a29b34a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3836,7 +3836,7 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, /* Prepare wait for target vblank early - before the fence-waits */ - target_vblank = target - drm_crtc_vblank_count(crtc) + + target_vblank = target - (uint32_t)drm_crtc_vblank_count(crtc) + amdgpu_get_vblank_counter_kms(crtc->dev, acrtc->crtc_id); /* TODO This might fail and hence better not used, wait @@ -3982,7 +3982,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, amdgpu_dm_do_flip( crtc, fb, - drm_crtc_vblank_count(crtc) + *wait_for_vblank, + (uint32_t)drm_crtc_vblank_count(crtc) + *wait_for_vblank, dm_state->context); } -- 2.14.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 01/10] drm/vblank: Data type fixes for 64-bit vblank sequences.
From: "Pandiyan, Dhinakaran" <dhinakaran.pandi...@intel.com> drm_vblank_count() has an u32 type returning what is a 64-bit vblank count. The effect of this is when drm_wait_vblank_ioctl() tries to widen the user space requested vblank sequence using this clipped 32-bit count(when the value is >= 2^32) as reference, the requested sequence remains a 32-bit value and gets queued like that. However, the code that checks if the requested sequence has passed compares this against the 64-bit vblank count. With drm_vblank_count() returning all bits of the vblank count, update drm_crtc_accurate_vblank_count() so that drm_crtc_arm_vblank_event() queues the correct sequence. Otherwise, this leads to prolonged waits for a vblank sequence when the current count is >=2^32. Finally, fix drm_wait_one_vblank() too. v2: Commit message fix (Keith) Squash commits (Rodrigo) Fixes: 570e86963a51 ("drm: Widen vblank count to 64-bits [v3]") Cc: Keith Packard <kei...@keithp.com> Cc: Michel Dänzer <mic...@daenzer.net> Cc: Daniel Vetter <dan...@ffwll.ch> Cc: Rodrigo Vivi <rodrigo.v...@intel.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> Acked-by: Daniel Vetter <daniel.vet...@ffwll.ch> --- drivers/gpu/drm/drm_vblank.c | 8 include/drm/drm_vblank.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 32d9bcf5be7f..f0d3ed5f2528 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -271,7 +271,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, store_vblank(dev, pipe, diff, t_vblank, cur_vblank); } -static u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe) +static u64 drm_vblank_count(struct drm_device *dev, unsigned int pipe) { struct drm_vblank_crtc *vblank = >vblank[pipe]; @@ -292,11 +292,11 @@ static u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe) * This is mostly useful for hardware that can obtain the scanout position, but * doesn't have a hardware frame counter. */ -u32 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc) +u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; unsigned int pipe = drm_crtc_index(crtc); - u32 vblank; + u64 vblank; unsigned long flags; WARN_ONCE(drm_debug & DRM_UT_VBL && !dev->driver->get_vblank_timestamp, @@ -1055,7 +1055,7 @@ void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe) { struct drm_vblank_crtc *vblank = >vblank[pipe]; int ret; - u32 last; + u64 last; if (WARN_ON(pipe >= dev->num_crtcs)) return; diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h index 848b463a0af5..a4c3b0a0a197 100644 --- a/include/drm/drm_vblank.h +++ b/include/drm/drm_vblank.h @@ -179,7 +179,7 @@ void drm_crtc_wait_one_vblank(struct drm_crtc *crtc); void drm_crtc_vblank_off(struct drm_crtc *crtc); void drm_crtc_vblank_reset(struct drm_crtc *crtc); void drm_crtc_vblank_on(struct drm_crtc *crtc); -u32 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc); +u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc); bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, unsigned int pipe, int *max_error, -- 2.14.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 03/10] drm/i915: Handle 64-bit return from drm_crtc_vblank_count()
570e86963a51 ("drm: Widen vblank count to 64-bits [v3]") changed the return type for drm_crtc_vblank_count() to u64, store all the bits without truncating. There is no need to type cast this value down to 32-bits. Cc: Keith Packard <kei...@keithp.com> Cc: Paulo Zanoni <paulo.r.zan...@intel.com> Cc: Rodrigo Vivi <rodrigo.v...@intel.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 3849ded354e3..4b9da04c1d4a 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1599,7 +1599,7 @@ static int i915_fbc_status(struct seq_file *m, void *unused) seq_printf(m, "FBC disabled: %s\n", fbc->no_fbc_reason); if (fbc->work.scheduled) - seq_printf(m, "FBC worker scheduled on vblank %u, now %llu\n", + seq_printf(m, "FBC worker scheduled on vblank %llu, now %llu\n", fbc->work.scheduled_vblank, drm_crtc_vblank_count(>crtc->base)); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c676269ed843..d22677494499 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -717,7 +717,7 @@ struct intel_fbc { struct intel_fbc_work { bool scheduled; - u32 scheduled_vblank; + u64 scheduled_vblank; struct work_struct work; } work; -- 2.14.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 8/9] drm/dp: Export AUX_RETRY_INTERVAL
Drivers can use this in their retry loops too. Cc: dri-devel@lists.freedesktop.org Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/drm_dp_helper.c | 12 +--- include/drm/drm_dp_helper.h | 2 ++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index ffe14ec3e7f2..0a7c8d6e7d8c 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -169,8 +169,6 @@ int drm_dp_bw_code_to_link_rate(u8 link_bw) } EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate); -#define AUX_RETRY_INTERVAL 500 /* us */ - /** * DOC: dp helpers * @@ -206,8 +204,8 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request, */ for (retry = 0; retry < 32; retry++) { if (ret != 0 && ret != -ETIMEDOUT) { - usleep_range(AUX_RETRY_INTERVAL, -AUX_RETRY_INTERVAL + 100); + usleep_range(DP_AUX_RETRY_INTERVAL, +DP_AUX_RETRY_INTERVAL + 100); } ret = aux->transfer(aux, ); @@ -718,7 +716,7 @@ static int drm_dp_i2c_retry_count(const struct drm_dp_aux_msg *msg, drm_dp_aux_reply_duration(msg); int i2c_time_us = drm_dp_i2c_msg_duration(msg, i2c_speed_khz); - return DIV_ROUND_UP(i2c_time_us, aux_time_us + AUX_RETRY_INTERVAL); + return DIV_ROUND_UP(i2c_time_us, aux_time_us + DP_AUX_RETRY_INTERVAL); } /* @@ -795,7 +793,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) * For now just defer for long enough to hopefully be * safe for all use-cases. */ - usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100); + usleep_range(DP_AUX_RETRY_INTERVAL, DP_AUX_RETRY_INTERVAL + 100); continue; default: @@ -827,7 +825,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) aux->i2c_defer_count++; if (defer_i2c < 7) defer_i2c++; - usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100); + usleep_range(DP_AUX_RETRY_INTERVAL, DP_AUX_RETRY_INTERVAL + 100); drm_dp_i2c_msg_write_status_update(msg); continue; diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index c239e6e24a10..2eae1aed2d26 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -61,6 +61,8 @@ #define DP_AUX_I2C_REPLY_DEFER (0x2 << 2) #define DP_AUX_I2C_REPLY_MASK (0x3 << 2) +#define DP_AUX_RETRY_INTERVAL 500 /* us */ + /* AUX CH addresses */ /* DPCD */ #define DP_DPCD_REV 0x000 -- 2.14.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/5] drm/vblank: Fix return type for drm_vblank_count()
drm_vblank_count() has a u32 type returning what is a 64-bit vblank count. The effect of this is when drm_wait_vblank_ioctl() tries to widen the user space requested vblank sequence using this clipped 32-bit count(when the value is >= 2^32) as reference, the requested sequence remains a 32-bit value and gets queued like that. However, the code that checks if the requested sequence has passed compares this against the 64-bit vblank count. Cc: Keith Packard <kei...@keithp.com> Cc: Michel Dänzer <mic...@daenzer.net> Cc: Daniel Vetter <dan...@ffwll.ch> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/drm_vblank.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 32d9bcf5be7f..768a8e44d99b 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -271,7 +271,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, store_vblank(dev, pipe, diff, t_vblank, cur_vblank); } -static u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe) +static u64 drm_vblank_count(struct drm_device *dev, unsigned int pipe) { struct drm_vblank_crtc *vblank = >vblank[pipe]; -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 3/5] drm/vblank: Do not update vblank count if interrupts are already disabled.
Updating vblank counts requires register reads and these reads may not return meaningful values if the device was in a low power state after vblank interrupts were last disabled. So, update the count only if vblank interrupts are enabled. Secondly, this means the registers should be read before disabling vblank interrupts. v2: Don't check vblank->enabled outside it's lock (Chris) Cc: Chris Wilson <ch...@chris-wilson.co.uk> Cc: Daniel Vetter <daniel.vet...@ffwll.ch> Cc: Michel Dänzer <mic...@daenzer.net> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/drm_vblank.c | 18 ++ 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index f2bf1f5dbaa5..2559d2d7b907 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -347,23 +347,25 @@ void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe) spin_lock_irqsave(>vblank_time_lock, irqflags); /* -* Only disable vblank interrupts if they're enabled. This avoids -* calling the ->disable_vblank() operation in atomic context with the -* hardware potentially runtime suspended. +* Update vblank count and disable vblank interrupts only if the +* interrupts were enabled. This avoids calling the ->disable_vblank() +* operation in atomic context with the hardware potentially runtime +* suspended. */ - if (vblank->enabled) { - __disable_vblank(dev, pipe); - vblank->enabled = false; - } + if (!vblank->enabled) + goto out; /* -* Always update the count and timestamp to maintain the +* Update the count and timestamp to maintain the * appearance that the counter has been ticking all along until * this time. This makes the count account for the entire time * between drm_crtc_vblank_on() and drm_crtc_vblank_off(). */ drm_update_vblank_count(dev, pipe, false); + __disable_vblank(dev, pipe); + vblank->enabled = false; +out: spin_unlock_irqrestore(>vblank_time_lock, irqflags); } -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 5/5] drm/i915: Estimate and update missed vblanks.
The frame counter may have got reset between disabling and enabling vblank interrupts due to DMC putting the hardware to DC5/6 state if PSR was active. The frame counter also could have stalled if PSR is active in cases where there is no DMC. The frame counter resetting as a user visible impact of screen freezes. Use drm_vblank_restore() to compute missed vblanks in the duration for which vblank interrupts are disabled. There's no need particularly check if PSR was active in the interrupt disabled duration. Enabling vblank interrupts wakes up the hardware from DC5/6 and prevents it from going back again as long as the there are pending interrupts. So, we don't have to explicity disallow DC5/6 after enabling vblank interrupts to keep the counter running. Let's not apply this to CHV for now, as enabling interrupts does not prevent the hardware from activating PSR and thereby stalling the counter. Cc: Rodrigo Vivi <rodrigo.v...@intel.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/i915/i915_irq.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 3517c6548e2c..db3466ec6faa 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2956,6 +2956,9 @@ static int ironlake_enable_vblank(struct drm_device *dev, unsigned int pipe) ilk_enable_display_irq(dev_priv, bit); spin_unlock_irqrestore(_priv->irq_lock, irqflags); + if (HAS_PSR(dev_priv)) + drm_vblank_restore(dev, pipe); + return 0; } @@ -2968,6 +2971,9 @@ static int gen8_enable_vblank(struct drm_device *dev, unsigned int pipe) bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); spin_unlock_irqrestore(_priv->irq_lock, irqflags); + if (HAS_PSR(dev_priv)) + drm_vblank_restore(dev, pipe); + return 0; } -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 4/5] drm/vblank: Restoring vblank counts after device PM events.
The HW frame counter can get reset if device enters a low power state after vblank interrupts were disabled. This messes up any following vblank count update as a negative diff (huge unsigned diff) is calculated from the HW frame counter change. We cannot ignore negative diffs altogther as there could be legitimate wrap arounds. So, allow drivers to update vblank->count with missed vblanks for the time interrupts were disabled. This is similar to _crtc_vblank_on() except that vblanks interrupts are not enabled at the end as this function is expected to be called from the driver _enable_vblank() vfunc. v2: drm_crtc_vblank_restore should take crtc as arg. (Chris) Add docs and sprinkle some asserts. Cc: Daniel Vetter <daniel.vet...@ffwll.ch> Cc: Chris Wilson <ch...@chris-wilson.co.uk> Cc: Michel Dänzer <mic...@daenzer.net> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/drm_vblank.c | 59 include/drm/drm_vblank.h | 2 ++ 2 files changed, 61 insertions(+) diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 2559d2d7b907..2690966694f0 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -1237,6 +1237,65 @@ void drm_crtc_vblank_on(struct drm_crtc *crtc) } EXPORT_SYMBOL(drm_crtc_vblank_on); +/** + * drm_vblank_restore - estimated vblanks using timestamps and update it. + * + * Power manamement features can cause frame counter resets between vblank + * disable and enable. Drivers can then use this function in their + * _crtc_funcs.enable_vblank implementation to estimate the vblanks since + * the last _crtc_funcs.disable_vblank. + * + * This function is the legacy version of drm_crtc_vblank_restore(). + */ +void drm_vblank_restore(struct drm_device *dev, unsigned int pipe) +{ + ktime_t t_vblank; + struct drm_vblank_crtc *vblank; + int framedur_ns; + u64 diff_ns; + u32 cur_vblank, diff = 1; + int count = DRM_TIMESTAMP_MAXRETRIES; + + if (WARN_ON(pipe >= dev->num_crtcs)) + return; + + assert_spin_locked(>vbl_lock); + assert_spin_locked(>vblank_time_lock); + + vblank = >vblank[pipe]; + WARN_ONCE((drm_debug & DRM_UT_VBL) && !vblank->framedur_ns, + "Cannot compute missed vblanks without frame duration\n"); + framedur_ns = vblank->framedur_ns; + + do { + cur_vblank = __get_vblank_counter(dev, pipe); + drm_get_last_vbltimestamp(dev, pipe, _vblank, false); + } while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0); + + diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time)); + if (framedur_ns) + diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns); + + + DRM_DEBUG_VBL("missed %d vblanks in %lld ns, frame duration=%d ns, hw_diff=%d\n", + diff, diff_ns, framedur_ns, cur_vblank - vblank->last); + store_vblank(dev, pipe, diff, t_vblank, cur_vblank); +} +EXPORT_SYMBOL(drm_vblank_restore); + +/** + * drm_crtc_vblank_restore - estimate vblanks using timestamps and update it. + * Power manamement features can cause frame counter resets between vblank + * disable and enable. Drivers can then use this function in their + * _crtc_funcs.enable_vblank implementation to estimate the vblanks since + * the last _crtc_funcs.disable_vblank. + */ +void drm_crtc_vblank_restore(struct drm_crtc *crtc) +{ + drm_vblank_restore(crtc->dev, drm_crtc_index(crtc)); +} +EXPORT_SYMBOL(drm_crtc_vblank_restore); + static void drm_legacy_vblank_pre_modeset(struct drm_device *dev, unsigned int pipe) { diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h index a4c3b0a0a197..16d46e2a6854 100644 --- a/include/drm/drm_vblank.h +++ b/include/drm/drm_vblank.h @@ -180,6 +180,8 @@ void drm_crtc_vblank_off(struct drm_crtc *crtc); void drm_crtc_vblank_reset(struct drm_crtc *crtc); void drm_crtc_vblank_on(struct drm_crtc *crtc); u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc); +void drm_vblank_restore(struct drm_device *dev, unsigned int pipe); +void drm_crtc_vblank_restore(struct drm_crtc *crtc); bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, unsigned int pipe, int *max_error, -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 2/5] drm/vblank: Fix data type width for drm_crtc_arm_vblank_event()
Now that drm_vblank_count() returns all bits of the vblank count, update drm_crtc_arm_vblank_event() so that it queues the correct sequence. Otherwise, this leads to prolonged waits for a vblank sequence when the current count is >=2^32. Cc: Keith Packard <kei...@keithp.com> Cc: Michel Dänzer <mic...@daenzer.net> Cc: Daniel Vetter <dan...@ffwll.ch> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/drm_vblank.c | 4 ++-- include/drm/drm_vblank.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 768a8e44d99b..f2bf1f5dbaa5 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -292,11 +292,11 @@ static u64 drm_vblank_count(struct drm_device *dev, unsigned int pipe) * This is mostly useful for hardware that can obtain the scanout position, but * doesn't have a hardware frame counter. */ -u32 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc) +u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; unsigned int pipe = drm_crtc_index(crtc); - u32 vblank; + u64 vblank; unsigned long flags; WARN_ONCE(drm_debug & DRM_UT_VBL && !dev->driver->get_vblank_timestamp, diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h index 848b463a0af5..a4c3b0a0a197 100644 --- a/include/drm/drm_vblank.h +++ b/include/drm/drm_vblank.h @@ -179,7 +179,7 @@ void drm_crtc_wait_one_vblank(struct drm_crtc *crtc); void drm_crtc_vblank_off(struct drm_crtc *crtc); void drm_crtc_vblank_reset(struct drm_crtc *crtc); void drm_crtc_vblank_on(struct drm_crtc *crtc); -u32 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc); +u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc); bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, unsigned int pipe, int *max_error, -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/dp: Power cycle display if LINK_ADDRESS fails.
Occasionally there are LINK_ADDRESS sideband messages timing out with the Lenovo MST dock + Dell MST monitor(w/ in-built branch) setup I have. These failures lead to the display not coming up on boot. Power cycling the port corresponding to the MST monitor's branch device and resending the message fixes the issue. I am not entirely sure if this is specific to my setup. However, as the power state is toggled conditionally on LINK_ADDRESS timeouts, this should not affect the working cases. Cc: Lyude <ly...@redhat.com> Cc: Dave Airlie <airl...@redhat.com> Cc: Jani Nikula <jani.nik...@intel.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/drm_dp_mst_topology.c | 13 +++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 70dcfa58d3c2..e06defcdcf18 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -1596,8 +1596,9 @@ static void drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr, int len; struct drm_dp_sideband_msg_tx *txmsg; int ret; + int attempts = 5; - txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL); +retry: txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL); if (!txmsg) return; @@ -1635,9 +1636,17 @@ static void drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr, } (*mgr->cbs->hotplug)(mgr); } + } else if (attempts--) { + kfree(txmsg); + drm_dp_send_power_updown_phy(mstb->mgr, mstb->port_parent, +false); + drm_dp_send_power_updown_phy(mstb->mgr, mstb->port_parent, +true); + DRM_DEBUG_KMS("link address failed %d, retrying\n", ret); + goto retry; } else { mstb->link_address_sent = false; - DRM_DEBUG_KMS("link address failed %d\n", ret); + DRM_DEBUG_KMS("link address failed %d, giving up\n", ret); } kfree(txmsg); -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 7/8] drm/i915: Introduce a non-blocking power domain for vblank interrupts
When DC states are enabled and PSR is active, the hardware enters DC5/DC6 states resulting in frame counter resets. The frame counter resets mess up the vblank counting logic. In order to disable DC states when vblank interrupts are required and to disallow DC states when vblanks interrupts are already enabled, introduce a new VBLANK power domain. Since this power domain reference needs to be acquired and released in atomic context, _vblank_get() and _vblank_put() methods skip the power_domain mutex. v2: Fix deadlock by switching irqsave spinlock. Implement atomic version of get_if_enabled. Modify power_domain_verify_state to check power well use count and enabled status atomically. Rewrite of intel_power_well_{get,put} Cc: Daniel Vetter <daniel.vet...@ffwll.ch> Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> Cc: Rodrigo Vivi <rodrigo.v...@intel.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 18 drivers/gpu/drm/i915/intel_drv.h| 3 + drivers/gpu/drm/i915/intel_runtime_pm.c | 184 +--- 3 files changed, 192 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ddadeb9eaf49..db597c5ebaed 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -397,6 +397,7 @@ enum intel_display_power_domain { POWER_DOMAIN_AUX_C, POWER_DOMAIN_AUX_D, POWER_DOMAIN_GMBUS, + POWER_DOMAIN_VBLANK, POWER_DOMAIN_MODESET, POWER_DOMAIN_GT_IRQ, POWER_DOMAIN_INIT, @@ -1476,6 +1477,23 @@ struct i915_power_well { bool has_fuses:1; } hsw; }; + + /* Lock to serialize access to count, hw_enabled and ops, used for +* power wells that have supports_atomix_ctx set to True. +*/ + spinlock_t lock; + + /* Indicates that the get/put methods for this power well can be called +* in atomic contexts, requires .ops to not sleep. This is valid +* only for the DC_OFF power well currently. +*/ + bool supports_atomic_ctx; + + /* DC_OFF power well was disabled since the last time vblanks were +* disabled. +*/ + bool dc_off_disabled; + const struct i915_power_well_ops *ops; }; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 48676e99316e..6822118f3c4d 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1798,6 +1798,9 @@ bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv, enum intel_display_power_domain domain); void intel_display_power_put(struct drm_i915_private *dev_priv, enum intel_display_power_domain domain); +void intel_display_power_vblank_get(struct drm_i915_private *dev_priv, + bool *needs_restore); +void intel_display_power_vblank_put(struct drm_i915_private *dev_priv); static inline void assert_rpm_device_not_suspended(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 992caec1fbc4..fc6812ed6137 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -56,6 +56,19 @@ static struct i915_power_well * lookup_power_well(struct drm_i915_private *dev_priv, enum i915_power_well_id power_well_id); +/* Optimize for the case when this is called from atomic contexts, + * although the case is unlikely. + */ +#define power_well_lock(power_well, flags) do {\ + if (likely(power_well->supports_atomic_ctx))\ + spin_lock_irqsave(_well->lock, flags);\ + } while (0) + +#define power_well_unlock(power_well, flags) do { \ + if (likely(power_well->supports_atomic_ctx))\ + spin_unlock_irqrestore(_well->lock, flags); \ + } while (0) + const char * intel_display_power_domain_str(enum intel_display_power_domain domain) { @@ -126,6 +139,8 @@ intel_display_power_domain_str(enum intel_display_power_domain domain) return "AUX_D"; case POWER_DOMAIN_GMBUS: return "GMBUS"; + case POWER_DOMAIN_VBLANK: + return "VBLANK"; case POWER_DOMAIN_INIT: return "INIT"; case POWER_DOMAIN_MODESET: @@ -141,6 +156,9 @@ intel_display_power_domain_str(enum intel_display_power_domain domain) static void intel_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { + if (power_well->supports_atomic_ctx) + assert_spin
[PATCH v2 6/8] drm/i915: Use an atomic_t array to track power domain use count.
Convert the power_domains->domain_use_count array that tracks per-domain use count to atomic_t type. This is needed to be able to read/write the use counts outside of the power domain mutex. Cc: Daniel Vetter <daniel.vet...@ffwll.ch> Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> Cc: Rodrigo Vivi <rodrigo.v...@intel.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_runtime_pm.c | 11 +-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 1a7b28f62570..1f1d9162f2c2 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2764,7 +2764,7 @@ static int i915_power_domain_info(struct seq_file *m, void *unused) for_each_power_domain(power_domain, power_well->domains) seq_printf(m, " %-23s %d\n", intel_display_power_domain_str(power_domain), -power_domains->domain_use_count[power_domain]); + atomic_read(_domains->domain_use_count[power_domain])); } mutex_unlock(_domains->lock); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1e4e613e7b41..ddadeb9eaf49 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1489,7 +1489,7 @@ struct i915_power_domains { int power_well_count; struct mutex lock; - int domain_use_count[POWER_DOMAIN_NUM]; + atomic_t domain_use_count[POWER_DOMAIN_NUM]; struct i915_power_well *power_wells; }; diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 96ab74f3d101..992caec1fbc4 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -1453,7 +1453,7 @@ __intel_display_power_get_domain(struct drm_i915_private *dev_priv, for_each_power_domain_well(dev_priv, power_well, BIT_ULL(domain)) intel_power_well_get(dev_priv, power_well); - power_domains->domain_use_count[domain]++; + atomic_inc(_domains->domain_use_count[domain]); } /** @@ -1539,10 +1539,9 @@ void intel_display_power_put(struct drm_i915_private *dev_priv, mutex_lock(_domains->lock); - WARN(!power_domains->domain_use_count[domain], -"Use count on domain %s is already zero\n", + WARN(atomic_dec_return(_domains->domain_use_count[domain]) < 0, +"Use count on domain %s was already zero\n", intel_display_power_domain_str(domain)); - power_domains->domain_use_count[domain]--; for_each_power_domain_well_rev(dev_priv, power_well, BIT_ULL(domain)) intel_power_well_put(dev_priv, power_well); @@ -3049,7 +3048,7 @@ static void intel_power_domains_dump_info(struct drm_i915_private *dev_priv) for_each_power_domain(domain, power_well->domains) DRM_DEBUG_DRIVER(" %-23s %d\n", intel_display_power_domain_str(domain), - power_domains->domain_use_count[domain]); + atomic_read(_domains->domain_use_count[domain])); } } @@ -3092,7 +3091,7 @@ void intel_power_domains_verify_state(struct drm_i915_private *dev_priv) domains_count = 0; for_each_power_domain(domain, power_well->domains) - domains_count += power_domains->domain_use_count[domain]; + domains_count += atomic_read(_domains->domain_use_count[domain]); if (power_well->count != domains_count) { DRM_ERROR("power well %s refcount/domain refcount mismatch " -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 3/8] drm/i915/psr: Avoid initializing PSR if there is no sink support.
DPCD read for the eDP is complete by the time intel_psr_init() is called, which means we can avoid initializing PSR structures and state if there is no sink support. Cc: Rodrigo Vivi <rodrigo.v...@intel.com> Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/i915/i915_debugfs.c | 7 ++- drivers/gpu/drm/i915/intel_psr.c| 9 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 64e5a263458c..1a7b28f62570 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2532,14 +2532,19 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) u32 stat[3]; enum pipe pipe; bool enabled = false; + bool sink_support; if (!HAS_PSR(dev_priv)) return -ENODEV; + sink_support = dev_priv->psr.sink_support; + seq_printf(m, "Sink_Support: %s\n", yesno(sink_support)); + if (!sink_support) + return 0; + intel_runtime_pm_get(dev_priv); mutex_lock(_priv->psr.lock); - seq_printf(m, "Sink_Support: %s\n", yesno(dev_priv->psr.sink_support)); seq_printf(m, "Enabled: %s\n", yesno((bool)dev_priv->psr.enabled)); seq_printf(m, "Active: %s\n", yesno(dev_priv->psr.active)); seq_printf(m, "Busy frontbuffer bits: 0x%03x\n", diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 76339cf387cb..095e0a5a8574 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -503,6 +503,9 @@ void intel_psr_enable(struct intel_dp *intel_dp, if (!crtc_state->has_psr) return; + if (WARN_ON(!CAN_PSR(dev_priv))) + return; + WARN_ON(dev_priv->drrs.dp); mutex_lock(_priv->psr.lock); if (dev_priv->psr.enabled) { @@ -633,6 +636,9 @@ void intel_psr_disable(struct intel_dp *intel_dp, if (!old_crtc_state->has_psr) return; + if (WARN_ON(!CAN_PSR(dev_priv))) + return; + mutex_lock(_priv->psr.lock); if (!dev_priv->psr.enabled) { mutex_unlock(_priv->psr.lock); @@ -913,6 +919,9 @@ void intel_psr_init(struct drm_i915_private *dev_priv) dev_priv->psr_mmio_base = IS_HASWELL(dev_priv) ? HSW_EDP_PSR_BASE : BDW_EDP_PSR_BASE; + if (!dev_priv->psr.sink_support) + return; + /* Per platform default: all disabled. */ if (i915_modparams.enable_psr == -1) i915_modparams.enable_psr = 0; -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 8/8] drm/i915: Use the vblank power domain disallow or disable DC states.
Disable DC states before enabling vblank interrupts and conversely enable DC states after disabling. Since the frame counter may have got reset between disabling and enabling, use drm_crtc_vblank_restore() to compute the missed vblanks. Cc: Daniel Vetter <daniel.vet...@ffwll.ch> Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> Cc: Rodrigo Vivi <rodrigo.v...@intel.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/i915/i915_irq.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 3517c6548e2c..88b4ceac55d0 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2963,6 +2963,11 @@ static int gen8_enable_vblank(struct drm_device *dev, unsigned int pipe) { struct drm_i915_private *dev_priv = to_i915(dev); unsigned long irqflags; + bool needs_restore = false; + + intel_display_power_vblank_get(dev_priv, _restore); + if (needs_restore) + drm_crtc_vblank_restore(dev, pipe); spin_lock_irqsave(_priv->irq_lock, irqflags); bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); @@ -3015,6 +3020,7 @@ static void gen8_disable_vblank(struct drm_device *dev, unsigned int pipe) spin_lock_irqsave(_priv->irq_lock, irqflags); bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); spin_unlock_irqrestore(_priv->irq_lock, irqflags); + intel_display_power_vblank_put(dev_priv); } static void ibx_irq_reset(struct drm_i915_private *dev_priv) -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 1/8] drm/i915/psr: Kill psr.source_ok flag.
This flag has become redundant since commit 4d90f2d507ab ("drm/i915: Start tracking PSR state in crtc state") It is set at the same place as psr.enabled, which is also exposed via debugfs. Cc: Rodrigo Vivi <rodrigo.v...@intel.com> Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/i915/i915_debugfs.c | 1 - drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/intel_psr.c| 2 -- 3 files changed, 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 0ddce72552bf..64e5a263458c 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2540,7 +2540,6 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) mutex_lock(_priv->psr.lock); seq_printf(m, "Sink_Support: %s\n", yesno(dev_priv->psr.sink_support)); - seq_printf(m, "Source_OK: %s\n", yesno(dev_priv->psr.source_ok)); seq_printf(m, "Enabled: %s\n", yesno((bool)dev_priv->psr.enabled)); seq_printf(m, "Active: %s\n", yesno(dev_priv->psr.active)); seq_printf(m, "Busy frontbuffer bits: 0x%03x\n", diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1aba5657f5f0..1e4e613e7b41 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1199,7 +1199,6 @@ struct i915_drrs { struct i915_psr { struct mutex lock; bool sink_support; - bool source_ok; struct intel_dp *enabled; bool active; struct delayed_work work; diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index a1ad85fa5c1a..c4d75e82a1df 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -522,8 +522,6 @@ void intel_psr_enable(struct intel_dp *intel_dp, } dev_priv->psr.psr2_support = crtc_state->has_psr2; - dev_priv->psr.source_ok = true; - dev_priv->psr.busy_frontbuffer_bits = 0; dev_priv->psr.setup_vsc(intel_dp, crtc_state); -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 0/8] Fix PSR-vblank-DMC interaction
The first 3 patches are minor PSR improvements. The last 5 introduce a new power domain to disable DC states when vblanks are required. The tricky part is to enable and disable the DC_OFF power well in atomic context. I have addressed the locking issues that CI caught in the last revision. Dhinakaran Pandiyan (8): drm/i915/psr: Kill psr.source_ok flag. drm/i915/psr: CAN_PSR() macro to check for PSR source and sink support. drm/i915/psr: Avoid initializing PSR if there is no sink support. drm/vblank: Do not update vblank counts if vblanks are already disabled. drm/vblank: Restoring vblank counts after device runtime PM events. drm/i915: Use an atomic_t array to track power domain use count. drm/i915: Introduce a non-blocking power domain for vblank interrupts drm/i915: Use the vblank power domain disallow or disable DC states. drivers/gpu/drm/drm_vblank.c| 56 ++--- drivers/gpu/drm/i915/i915_debugfs.c | 10 +- drivers/gpu/drm/i915/i915_drv.h | 21 +++- drivers/gpu/drm/i915/i915_irq.c | 6 + drivers/gpu/drm/i915/intel_drv.h| 4 + drivers/gpu/drm/i915/intel_psr.c| 30 +++-- drivers/gpu/drm/i915/intel_runtime_pm.c | 195 include/drm/drm_vblank.h| 1 + 8 files changed, 268 insertions(+), 55 deletions(-) -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 5/8] drm/vblank: Restoring vblank counts after device runtime PM events.
The HW frame counter can get reset when devices enters low power states and this messes up any following vblank count updates. So, compute the missed vblank interrupts for that low power state duration using time stamps. This is similar to _crtc_vblank_on() except that it doesn't enable vblank interrupts because this function is expected to be called from the driver _enable_vblank() vfunc. Cc: Daniel Vetter <daniel.vet...@ffwll.ch> Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> Cc: Rodrigo Vivi <rodrigo.v...@intel.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/drm_vblank.c | 33 + include/drm/drm_vblank.h | 1 + 2 files changed, 34 insertions(+) diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 7eee82c06ed8..494e2cff6e55 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -1230,6 +1230,39 @@ void drm_crtc_vblank_on(struct drm_crtc *crtc) } EXPORT_SYMBOL(drm_crtc_vblank_on); +void drm_crtc_vblank_restore(struct drm_device *dev, unsigned int pipe) +{ + ktime_t t_vblank; + struct drm_vblank_crtc *vblank; + int framedur_ns; + u64 diff_ns; + u32 cur_vblank, diff = 1; + int count = DRM_TIMESTAMP_MAXRETRIES; + + if (WARN_ON(pipe >= dev->num_crtcs)) + return; + + vblank = >vblank[pipe]; + WARN_ONCE((drm_debug & DRM_UT_VBL) && !vblank->framedur_ns, + "Cannot compute missed vblanks without frame duration\n"); + framedur_ns = vblank->framedur_ns; + + do { + cur_vblank = __get_vblank_counter(dev, pipe); + drm_get_last_vbltimestamp(dev, pipe, _vblank, false); + } while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0); + + diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time)); + if (framedur_ns) + diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns); + + + DRM_DEBUG_VBL("missed %d vblanks in %lld ns, frame duration=%d ns, hw_diff=%d\n", + diff, diff_ns, framedur_ns, cur_vblank - vblank->last); + store_vblank(dev, pipe, diff, t_vblank, cur_vblank); +} +EXPORT_SYMBOL(drm_crtc_vblank_restore); + static void drm_legacy_vblank_pre_modeset(struct drm_device *dev, unsigned int pipe) { diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h index 848b463a0af5..aafcbef91bd7 100644 --- a/include/drm/drm_vblank.h +++ b/include/drm/drm_vblank.h @@ -180,6 +180,7 @@ void drm_crtc_vblank_off(struct drm_crtc *crtc); void drm_crtc_vblank_reset(struct drm_crtc *crtc); void drm_crtc_vblank_on(struct drm_crtc *crtc); u32 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc); +void drm_crtc_vblank_restore(struct drm_device *dev, unsigned int pipe); bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, unsigned int pipe, int *max_error, -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 2/8] drm/i915/psr: CAN_PSR() macro to check for PSR source and sink support.
The global variable dev_priv->psr.sink_support is set if an eDP sink supports PSR. Use this instead of redoing the check with is_edp_psr(). Combine source and sink support checks into a macro that can be used to return early from psr_{invalidate, single_frame_update, flush}. Cc: Rodrigo Vivi <rodrigo.v...@intel.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_psr.c | 19 --- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 30f791f89d64..48676e99316e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1760,6 +1760,7 @@ static inline void intel_backlight_device_unregister(struct intel_connector *con /* intel_psr.c */ +#define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv->psr.sink_support) void intel_psr_enable(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state); void intel_psr_disable(struct intel_dp *intel_dp, diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index c4d75e82a1df..76339cf387cb 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -56,14 +56,6 @@ #include "intel_drv.h" #include "i915_drv.h" -static bool is_edp_psr(struct intel_dp *intel_dp) -{ - if (!intel_dp_is_edp(intel_dp)) - return false; - - return intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED; -} - static bool vlv_is_psr_active_on_pipe(struct drm_device *dev, int pipe) { struct drm_i915_private *dev_priv = to_i915(dev); @@ -358,10 +350,7 @@ void intel_psr_compute_config(struct intel_dp *intel_dp, _state->base.adjusted_mode; int psr_setup_time; - if (!HAS_PSR(dev_priv)) - return; - - if (!is_edp_psr(intel_dp)) + if (!CAN_PSR(dev_priv)) return; if (!i915_modparams.enable_psr) { @@ -794,7 +783,7 @@ void intel_psr_single_frame_update(struct drm_i915_private *dev_priv, enum pipe pipe; u32 val; - if (!HAS_PSR(dev_priv)) + if (!CAN_PSR(dev_priv)) return; /* @@ -843,7 +832,7 @@ void intel_psr_invalidate(struct drm_i915_private *dev_priv, struct drm_crtc *crtc; enum pipe pipe; - if (!HAS_PSR(dev_priv)) + if (!CAN_PSR(dev_priv)) return; mutex_lock(_priv->psr.lock); @@ -883,7 +872,7 @@ void intel_psr_flush(struct drm_i915_private *dev_priv, struct drm_crtc *crtc; enum pipe pipe; - if (!HAS_PSR(dev_priv)) + if (!CAN_PSR(dev_priv)) return; mutex_lock(_priv->psr.lock); -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 2/5] drm/vblank: Restoring vblank counts after device runtime PM events.
The HW frame counter can get reset when devices enters low power states and this messes up any following vblank count updates. So, compute the missed vblank interrupts for that low power state duration using time stamps. This is similar to _crtc_vblank_on() except that it doesn't enable vblank interrupts because this function is expected to be called from the driver _enable_vblank() vfunc. Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/drm_vblank.c | 30 ++ include/drm/drm_vblank.h | 1 + 2 files changed, 31 insertions(+) diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 7eee82c06ed8..69d537cea149 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -1230,6 +1230,36 @@ void drm_crtc_vblank_on(struct drm_crtc *crtc) } EXPORT_SYMBOL(drm_crtc_vblank_on); +void drm_crtc_vblank_restore(struct drm_device *dev, unsigned int pipe) +{ + ktime_t t_vblank; + struct drm_vblank_crtc *vblank; + int framedur_ns; + u64 diff_ns; + u32 cur_vblank, diff = 1; + int count = DRM_TIMESTAMP_MAXRETRIES; + + if (WARN_ON(pipe >= dev->num_crtcs)) + return; + + vblank = >vblank[pipe]; + framedur_ns = vblank->framedur_ns; + + do { + cur_vblank = __get_vblank_counter(dev, pipe); + drm_get_last_vbltimestamp(dev, pipe, _vblank, false); + } while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0); + + diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time)); + if (framedur_ns) + diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns); + + DRM_DEBUG_VBL("computing missed vblanks %lld/%d=%d after HW counter reset hw_diff=%d\n", + diff_ns, framedur_ns, diff, cur_vblank - vblank->last); + store_vblank(dev, pipe, diff, t_vblank, cur_vblank); +} +EXPORT_SYMBOL(drm_crtc_vblank_restore); + static void drm_legacy_vblank_pre_modeset(struct drm_device *dev, unsigned int pipe) { diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h index 848b463a0af5..aafcbef91bd7 100644 --- a/include/drm/drm_vblank.h +++ b/include/drm/drm_vblank.h @@ -180,6 +180,7 @@ void drm_crtc_vblank_off(struct drm_crtc *crtc); void drm_crtc_vblank_reset(struct drm_crtc *crtc); void drm_crtc_vblank_on(struct drm_crtc *crtc); u32 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc); +void drm_crtc_vblank_restore(struct drm_device *dev, unsigned int pipe); bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, unsigned int pipe, int *max_error, -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 5/5] drm/i915: Use the vblank power domain disallow or disable DC states.
Disable DC states before enabling vblank interrupts and conversely enable DC states after disabling. Since the frame counter may have got reset between disabling and enabling, use drm_crtc_vblank_restore() to compute the missed vblanks. Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/i915/i915_irq.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 7cac07db89b9..c595b934e2dc 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2964,6 +2964,9 @@ static int gen8_enable_vblank(struct drm_device *dev, unsigned int pipe) struct drm_i915_private *dev_priv = to_i915(dev); unsigned long irqflags; + if (intel_display_power_vblank_get(dev_priv)) + drm_crtc_vblank_restore(dev, pipe); + spin_lock_irqsave(_priv->irq_lock, irqflags); bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); spin_unlock_irqrestore(_priv->irq_lock, irqflags); @@ -3015,6 +3018,7 @@ static void gen8_disable_vblank(struct drm_device *dev, unsigned int pipe) spin_lock_irqsave(_priv->irq_lock, irqflags); bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); spin_unlock_irqrestore(_priv->irq_lock, irqflags); + intel_display_power_vblank_put(dev_priv); } static void ibx_irq_reset(struct drm_i915_private *dev_priv) -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/5] drm/vblank: Do not update vblank counts if vblanks are already disabled.
Updating the vblank counts requires register reads and these reads may not return meaningful values after the vblank interrupts are disabled as the device may go to low power state. An additional change would be to allow the driver to save the vblank counts before entering a low power state, but that's for the future. Also, disable vblanks after reading the HW counter in the case where _crtc_vblank_off() is disabling vblanks. Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/drm_vblank.c | 23 +-- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 32d9bcf5be7f..7eee82c06ed8 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -347,23 +347,14 @@ void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe) spin_lock_irqsave(>vblank_time_lock, irqflags); /* -* Only disable vblank interrupts if they're enabled. This avoids -* calling the ->disable_vblank() operation in atomic context with the -* hardware potentially runtime suspended. -*/ - if (vblank->enabled) { - __disable_vblank(dev, pipe); - vblank->enabled = false; - } - - /* -* Always update the count and timestamp to maintain the +* Update the count and timestamp to maintain the * appearance that the counter has been ticking all along until * this time. This makes the count account for the entire time * between drm_crtc_vblank_on() and drm_crtc_vblank_off(). */ drm_update_vblank_count(dev, pipe, false); - + __disable_vblank(dev, pipe); + vblank->enabled = false; spin_unlock_irqrestore(>vblank_time_lock, irqflags); } @@ -1122,8 +1113,12 @@ void drm_crtc_vblank_off(struct drm_crtc *crtc) pipe, vblank->enabled, vblank->inmodeset); /* Avoid redundant vblank disables without previous -* drm_crtc_vblank_on(). */ - if (drm_core_check_feature(dev, DRIVER_ATOMIC) || !vblank->inmodeset) +* drm_crtc_vblank_on() and only disable them if they're enabled. This +* avoids calling the ->disable_vblank() operation in atomic context +* with the hardware potentially runtime suspended. +*/ + if ((drm_core_check_feature(dev, DRIVER_ATOMIC) || !vblank->inmodeset) && + vblank->enabled) drm_vblank_disable_and_save(dev, pipe); wake_up(>queue); -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 3/5] drm/i915: Use an atomic_t array to track power domain use count.
Convert the power_domains->domain_use_count array that tracks per-domain use count to atomic_t type. This is needed to be able to read/write the use counts outside of the power domain mutex. Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_runtime_pm.c | 11 +-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 28294470ae31..2a4ed54688d7 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2805,7 +2805,7 @@ static int i915_power_domain_info(struct seq_file *m, void *unused) for_each_power_domain(power_domain, power_well->domains) seq_printf(m, " %-23s %d\n", intel_display_power_domain_str(power_domain), -power_domains->domain_use_count[power_domain]); + atomic_read(_domains->domain_use_count[power_domain])); } mutex_unlock(_domains->lock); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 594fd14e66c5..18d42885205b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1489,7 +1489,7 @@ struct i915_power_domains { int power_well_count; struct mutex lock; - int domain_use_count[POWER_DOMAIN_NUM]; + atomic_t domain_use_count[POWER_DOMAIN_NUM]; struct i915_power_well *power_wells; }; diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 8315499452dc..f88f2c070c5f 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -1451,7 +1451,7 @@ __intel_display_power_get_domain(struct drm_i915_private *dev_priv, for_each_power_domain_well(dev_priv, power_well, BIT_ULL(domain)) intel_power_well_get(dev_priv, power_well); - power_domains->domain_use_count[domain]++; + atomic_inc(_domains->domain_use_count[domain]); } /** @@ -1537,10 +1537,9 @@ void intel_display_power_put(struct drm_i915_private *dev_priv, mutex_lock(_domains->lock); - WARN(!power_domains->domain_use_count[domain], -"Use count on domain %s is already zero\n", + WARN(atomic_dec_return(_domains->domain_use_count[domain]) < 0, +"Use count on domain %s was already zero\n", intel_display_power_domain_str(domain)); - power_domains->domain_use_count[domain]--; for_each_power_domain_well_rev(dev_priv, power_well, BIT_ULL(domain)) intel_power_well_put(dev_priv, power_well); @@ -3044,7 +3043,7 @@ static void intel_power_domains_dump_info(struct drm_i915_private *dev_priv) for_each_power_domain(domain, power_well->domains) DRM_DEBUG_DRIVER(" %-23s %d\n", intel_display_power_domain_str(domain), - power_domains->domain_use_count[domain]); + atomic_read(_domains->domain_use_count[domain])); } } @@ -3087,7 +3086,7 @@ void intel_power_domains_verify_state(struct drm_i915_private *dev_priv) domains_count = 0; for_each_power_domain(domain, power_well->domains) - domains_count += power_domains->domain_use_count[domain]; + domains_count += atomic_read(_domains->domain_use_count[domain]); if (power_well->count != domains_count) { DRM_ERROR("power well %s refcount/domain refcount mismatch " -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 4/5] drm/i915: Introduce a non-blocking power domain for vblank interrupts
When DC states are enabled and PSR is active, the hardware enters DC5/DC6 states resulting in frame counter resets. The frame counter resets mess up the vblank counting logic. So in order to disable DC states when vblank interrupts are required and to disallow DC states when vblanks interrupts are already enabled, introduce a new power domain. Since this power domain reference needs to be acquired and released in atomic context, the corresponding _get() and _put() methods skip the power_domain mutex. Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 5 ++ drivers/gpu/drm/i915/intel_drv.h| 3 +- drivers/gpu/drm/i915/intel_runtime_pm.c | 125 +++- 3 files changed, 128 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 18d42885205b..ba9107ec1ed1 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -397,6 +397,7 @@ enum intel_display_power_domain { POWER_DOMAIN_AUX_C, POWER_DOMAIN_AUX_D, POWER_DOMAIN_GMBUS, + POWER_DOMAIN_VBLANK, POWER_DOMAIN_MODESET, POWER_DOMAIN_INIT, @@ -1475,6 +1476,10 @@ struct i915_power_well { bool has_vga:1; bool has_fuses:1; } hsw; + struct { + spinlock_t lock; + bool was_disabled; + } dc_off; }; const struct i915_power_well_ops *ops; }; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 30f791f89d64..93ca503f18bb 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1865,7 +1865,8 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder, bool override, unsigned int mask); bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy, enum dpio_channel ch, bool override); - +bool intel_display_power_vblank_get(struct drm_i915_private *dev_priv); +void intel_display_power_vblank_put(struct drm_i915_private *dev_priv); /* intel_pm.c */ void intel_init_clock_gating(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index f88f2c070c5f..f1807bd74242 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -126,6 +126,8 @@ intel_display_power_domain_str(enum intel_display_power_domain domain) return "AUX_D"; case POWER_DOMAIN_GMBUS: return "GMBUS"; + case POWER_DOMAIN_VBLANK: + return "VBLANK"; case POWER_DOMAIN_INIT: return "INIT"; case POWER_DOMAIN_MODESET: @@ -196,10 +198,17 @@ bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv, if (power_well->always_on) continue; - if (!power_well->hw_enabled) { + if (power_well->id == SKL_DISP_PW_DC_OFF) + spin_lock(_well->dc_off.lock); + + if (!power_well->hw_enabled) is_enabled = false; + + if (power_well->id == SKL_DISP_PW_DC_OFF) + spin_unlock(_well->dc_off.lock); + + if (!is_enabled) break; - } } return is_enabled; @@ -724,6 +733,7 @@ static void gen9_dc_off_power_well_disable(struct drm_i915_private *dev_priv, skl_enable_dc6(dev_priv); else if (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC5) gen9_enable_dc5(dev_priv); + power_well->dc_off.was_disabled = true; } static void i9xx_power_well_sync_hw_noop(struct drm_i915_private *dev_priv, @@ -1441,6 +1451,77 @@ static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv, chv_set_pipe_power_well(dev_priv, power_well, false); } +/** + * intel_display_power_vblank_get - acquire a VBLANK power domain reference atomically + * @dev_priv: i915 device instance + * + * This function gets a POWER_DOMAIN_VBLANK reference without blocking and + * returns true if the DC_OFF power well was disabled since this function was + * called the last time. + */ +bool intel_display_power_vblank_get(struct drm_i915_private *dev_priv) +{ + struct i915_power_domains *power_domains = _priv->power_domains; + struct i915_power_well *power_well; + bool needs_restore = false; + + if (!HAS_CSR(dev_priv) || !dev_priv->psr.source_ok) + return false; + + /* The corresponding CRTC should be active by the time driver turns on +* vblank interrupts, which in turn means the enabl
[RFC PATCH] drm/vblanks: Deal with HW vblank counter resets.
Some HW vblank counters reset due to power management events, which messes up the vblank counting logic. This leads to screen freezes with user space waiting on vblank events that may not occur if the counter keeps resetting. For e.g., After the HW vblank counter resets [9.007359] [drm:drm_update_vblank_count [drm]] updating vblank count on crtc 0: current=297, diff=4294965389, hw=5 hw_last=1912 So, fall back to the SW counter, computed using vblank timestamps and frame duration, when the HW counter value deviates by 50% of the SW computed value. I have tested this patch on my SKL laptop with i915.enable_psr=1 and it *seems* to solve the screen freeze issue seen with PSR when DMC is loaded. Known issues: 1) The 50% deviation margin is arbitrary. 2) "Redundant vblirq ignored" messages are more frequent. I am sending this as an RFC to get feedback on whether the fall back approach is sane and if it should be implemented in the core. Cc: Daniel Vetter <daniel.vet...@ffwll.ch> Cc: Rodrigo Vivi <rodrigo.v...@intel.com> Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/drm_vblank.c | 26 -- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 57cc6e37c810..8000aae5f1f7 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -190,11 +190,12 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, bool in_vblank_irq) { struct drm_vblank_crtc *vblank = >vblank[pipe]; - u32 cur_vblank, diff; + u32 cur_vblank; bool rc; ktime_t t_vblank; int count = DRM_TIMESTAMP_MAXRETRIES; int framedur_ns = vblank->framedur_ns; + u32 diff = in_vblank_irq ? 1 : 0; /* * Interrupts were disabled prior to this call, so deal with counter @@ -213,26 +214,31 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, rc = drm_get_last_vbltimestamp(dev, pipe, _vblank, in_vblank_irq); } while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0); - if (dev->max_vblank_count != 0) { - /* trust the hw counter when it's around */ + if (dev->max_vblank_count) diff = (cur_vblank - vblank->last) & dev->max_vblank_count; - } else if (rc && framedur_ns) { + + if (rc && framedur_ns) { u64 diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time)); + u32 sw_diff; /* * Figure out how many vblanks we've missed based * on the difference in the timestamps and the * frame/field duration. */ - diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns); - - if (diff == 0 && in_vblank_irq) + sw_diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns); + if (sw_diff == 0 && in_vblank_irq) DRM_DEBUG_VBL("crtc %u: Redundant vblirq ignored." " diff_ns = %lld, framedur_ns = %d)\n", pipe, (long long) diff_ns, framedur_ns); - } else { - /* some kind of default for drivers w/o accurate vbl timestamping */ - diff = in_vblank_irq ? 1 : 0; + + if (!dev->max_vblank_count) + diff = sw_diff; + else if (sw_diff && abs(diff - sw_diff) > DIV_ROUND_CLOSEST(sw_diff, 2)) { + DRM_DEBUG_VBL("hw vblank counter(%u) deviates from sw (%u)\n", + diff, sw_diff); + diff = sw_diff; + } } /* -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/dp: Update SET_POWER_MASK to include the D3 Aux-On state too.
Updating the mask is needed to clear all the three power state bits before setting the required power state. Also add a comment documenting that D3 Aux-On state has been available DPCD v1.2 onwards. Thanks to Ville for pointing this out. Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> Cc: Jani Nikula <jani.nik...@intel.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- include/drm/drm_dp_helper.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 9049ef133d69..aea10f85dd4c 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -617,8 +617,8 @@ #define DP_SET_POWER0x600 # define DP_SET_POWER_D00x1 # define DP_SET_POWER_D30x2 -# define DP_SET_POWER_MASK 0x3 -# define DP_SET_POWER_D3_AUX_ON 0x5 +# define DP_SET_POWER_D3_AUX_ON 0x5 /* DPCD >= 1.2 */ +# define DP_SET_POWER_MASK 0x7 #define DP_EDP_DPCD_REV0x700/* eDP 1.2 */ # define DP_EDP_11 0x00 -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2] drm/dp: DPCD register defines for link status within ESI field
Link status is available in the ESI field on devices with DPCD r1.2 or higher. DP spec also says "An MST upstream device shall use this field instead of the Link/Sink Device Status field registers, starting from DPCD Address 00200h." v2: Prefixed DP_ (Jani) Rewrote commment to stay within 80 cols. Cc: Jani Nikula <jani.nik...@intel.com> Reviewed-by: Jani Nikula <jani.nik...@intel.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- include/drm/drm_dp_helper.h | 5 + 1 file changed, 5 insertions(+) diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 2c412a15cfa1..11c39f15f1b3 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -738,6 +738,11 @@ #define DP_RECEIVER_ALPM_STATUS0x200b /* eDP 1.4 */ # define DP_ALPM_LOCK_TIMEOUT_ERROR(1 << 0) +#define DP_LANE0_1_STATUS_ESI 0x200c /* status same as 0x202 */ +#define DP_LANE2_3_STATUS_ESI 0x200d /* status same as 0x203 */ +#define DP_LANE_ALIGN_STATUS_UPDATED_ESI 0x200e /* status same as 0x204 */ +#define DP_SINK_STATUS_ESI 0x200f /* status same as 0x205 */ + #define DP_DPRX_FEATURE_ENUMERATION_LIST0x2210 /* DP 1.3 */ # define DP_GTC_CAP(1 << 0) /* DP 1.3 */ # define DP_SST_SPLIT_SDP_CAP (1 << 1) /* DP 1.4 */ -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/dp: DPCD register defines for link status within ESI field
Link status is available in the ESI field on devices with DPCD r1.2 or higher. DP spec also says "An MST upstream device shall use this field instead of the Link/Sink Device Status field registers, starting from DPCD Address 00200h." Cc: Jani Nikula <jani.nik...@intel.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- include/drm/drm_dp_helper.h | 5 + 1 file changed, 5 insertions(+) diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 2c412a15cfa1..0bf15525cdd0 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -738,6 +738,11 @@ #define DP_RECEIVER_ALPM_STATUS0x200b /* eDP 1.4 */ # define DP_ALPM_LOCK_TIMEOUT_ERROR(1 << 0) +#define LANE0_1_STATUS_ESI 0x200c /* Same as status in 0x202 */ +#define LANE2_3_STATUS_ESI 0x200d /* Same as status in 0x203 */ +#define LANE_ALIGN_STATUS_UPDATED_ESI 0x200e /* Same as status in 0x204 */ +#define SINK_STATUS_ESI 0x200f /* Same as status in 0x205 */ + #define DP_DPRX_FEATURE_ENUMERATION_LIST0x2210 /* DP 1.3 */ # define DP_GTC_CAP(1 << 0) /* DP 1.3 */ # define DP_SST_SPLIT_SDP_CAP (1 << 1) /* DP 1.4 */ -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2] drm/dp/mst: Sideband message transaction to power up/down nodes
The POWER_DOWN_PHY and POWER_UP_PHY sideband message transactions allow the source to reqest any node in a mst path or a whole path to be powered down or up. This allows drivers to target a specific sink in the MST topology, an improvement over just power managing the imediate downstream device. Secondly, since the request-reply protocol waits for an ACK, we can be sure that a downstream sink has enough time to respond to a power up/down request. v2: Fix memory leak (Lyude) Cc: Lyude <ly...@redhat.com> Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> Cc: Harry Wentland <harry.wentl...@amd.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/drm_dp_mst_topology.c | 75 +++ include/drm/drm_dp_mst_helper.h | 2 + 2 files changed, 77 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 41b492f99955..9bc5049e7e59 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -294,6 +294,12 @@ static void drm_dp_encode_sideband_req(struct drm_dp_sideband_msg_req_body *req, memcpy([idx], req->u.i2c_write.bytes, req->u.i2c_write.num_bytes); idx += req->u.i2c_write.num_bytes; break; + + case DP_POWER_DOWN_PHY: + case DP_POWER_UP_PHY: + buf[idx] = (req->u.port_num.port_number & 0xf) << 4; + idx++; + break; } raw->cur_len = idx; } @@ -538,6 +544,22 @@ static bool drm_dp_sideband_parse_query_payload_ack(struct drm_dp_sideband_msg_r return false; } + +static bool drm_dp_sideband_parse_power_updown_phy_ack(struct drm_dp_sideband_msg_rx *raw, + struct drm_dp_sideband_msg_reply_body *repmsg) +{ + int idx = 1; + + repmsg->u.port_number.port_number = (raw->msg[idx] >> 4) & 0xf; + idx++; + if (idx > raw->curlen) { + DRM_DEBUG_KMS("power up/down phy parse length fail %d %d\n", + idx, raw->curlen); + return false; + } + return true; +} + static bool drm_dp_sideband_parse_reply(struct drm_dp_sideband_msg_rx *raw, struct drm_dp_sideband_msg_reply_body *msg) { @@ -567,6 +589,9 @@ static bool drm_dp_sideband_parse_reply(struct drm_dp_sideband_msg_rx *raw, return drm_dp_sideband_parse_enum_path_resources_ack(raw, msg); case DP_ALLOCATE_PAYLOAD: return drm_dp_sideband_parse_allocate_payload_ack(raw, msg); + case DP_POWER_DOWN_PHY: + case DP_POWER_UP_PHY: + return drm_dp_sideband_parse_power_updown_phy_ack(raw, msg); default: DRM_ERROR("Got unknown reply 0x%02x\n", msg->req_type); return false; @@ -693,6 +718,22 @@ static int build_allocate_payload(struct drm_dp_sideband_msg_tx *msg, int port_n return 0; } +static int build_power_updown_phy(struct drm_dp_sideband_msg_tx *msg, + int port_num, bool power_up) +{ + struct drm_dp_sideband_msg_req_body req; + + if (power_up) + req.req_type = DP_POWER_UP_PHY; + else + req.req_type = DP_POWER_DOWN_PHY; + + req.u.port_num.port_number = port_num; + drm_dp_encode_sideband_req(, msg); + msg->path_msg = true; + return 0; +} + static int drm_dp_mst_assign_payload_id(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_vcpi *vcpi) { @@ -1724,6 +1765,40 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, return ret; } +int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr, +struct drm_dp_mst_port *port, bool power_up) +{ + struct drm_dp_sideband_msg_tx *txmsg; + int len, ret; + + port = drm_dp_get_validated_port_ref(mgr, port); + if (!port) + return -EINVAL; + + txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL); + if (!txmsg) { + drm_dp_put_port(port); + return -ENOMEM; + } + + txmsg->dst = port->parent; + len = build_power_updown_phy(txmsg, port->port_num, power_up); + drm_dp_queue_down_tx(mgr, txmsg); + + ret = drm_dp_mst_wait_tx_reply(port->parent, txmsg); + if (ret > 0) { + if (txmsg->reply.reply_type == 1) + ret = -EINVAL; + else + ret = 0; + } + kfree(txmsg); + drm_dp_put_port(port); + + return ret; +} +EXPORT_SYMBOL(drm_dp_send_power_updown_phy); + static int drm_dp_create_payload_step1(struct drm_dp_mst_topology_mgr *mgr,
[PATCH 2/2] drm/i915/mst: Use MST sideband message transaction for dpms
Use the POWER_DOWN_PHY and POWER_UP_PHY sideband message trasactions to set power states for downstream sinks. Apart from giving us the ability to set power state for individual sinks, this fixes the below test for me $ xrandr --display :0 --output DP-2-2-8 --off $ xrandr --display :0 --output DP-2-2-1 --off $ xrandr --display :0 --output DP-2-2-8 --auto #Black screen $ xrandr --display :0 --output DP-2-2-1 --auto Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> Cc: Lyude <ly...@redhat.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/i915/intel_ddi.c| 6 -- drivers/gpu/drm/i915/intel_dp_mst.c | 8 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 1da3bb2cc4b4..8aebacc0aa31 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2161,7 +2161,8 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, intel_prepare_dp_ddi_buffers(encoder); intel_ddi_init_dp_buf_reg(encoder); - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); + if (!link_mst) + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); intel_dp_start_link_train(intel_dp); if (port != PORT_A || INTEL_GEN(dev_priv) >= 9) intel_dp_stop_link_train(intel_dp); @@ -2240,7 +2241,8 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder, if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); + if (old_crtc_state && old_conn_state) + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); } val = I915_READ(DDI_BUF_CTL(port)); diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 8e3aad0ea60b..81e63724e24b 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -167,12 +167,11 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder, intel_dp->active_mst_links--; intel_mst->connector = NULL; - if (intel_dp->active_mst_links == 0) { + if (intel_dp->active_mst_links == 0) intel_dig_port->base.post_disable(_dig_port->base, NULL, NULL); - - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); - } + drm_dp_send_power_updown_phy(_dp->mst_mgr, connector->port, +false); } static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, @@ -197,6 +196,7 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); + drm_dp_send_power_updown_phy(_dp->mst_mgr, connector->port, true); if (intel_dp->active_mst_links == 0) intel_dig_port->base.pre_enable(_dig_port->base, pipe_config, NULL); -- 2.11.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/2] drm/dp/mst: Sideband message transaction to power up/down nodes
The POWER_DOWN_PHY and POWER_UP_PHY sideband message transactions allow the source to reqest any node in a mst path or a whole path to be powered down or up. This allows drivers to target a specific sink in the MST topology, an improvement over just power managing the imediate downstream device. Secondly, since the request-reply protocol waits for an ACK, we can be sure that a downstream sink has enough time to respond to a power up/down request. Cc: Lyude <ly...@redhat.com> Cc: Ville Syrjälä <ville.syrj...@linux.intel.com> Cc: Harry Wentland <harry.wentl...@amd.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/drm_dp_mst_topology.c | 73 +++ include/drm/drm_dp_mst_helper.h | 2 + 2 files changed, 75 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 41b492f99955..a9f12708a046 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -294,6 +294,12 @@ static void drm_dp_encode_sideband_req(struct drm_dp_sideband_msg_req_body *req, memcpy([idx], req->u.i2c_write.bytes, req->u.i2c_write.num_bytes); idx += req->u.i2c_write.num_bytes; break; + + case DP_POWER_DOWN_PHY: + case DP_POWER_UP_PHY: + buf[idx] = (req->u.port_num.port_number & 0xf) << 4; + idx++; + break; } raw->cur_len = idx; } @@ -538,6 +544,22 @@ static bool drm_dp_sideband_parse_query_payload_ack(struct drm_dp_sideband_msg_r return false; } + +static bool drm_dp_sideband_parse_power_updown_phy_ack(struct drm_dp_sideband_msg_rx *raw, + struct drm_dp_sideband_msg_reply_body *repmsg) +{ + int idx = 1; + + repmsg->u.port_number.port_number = (raw->msg[idx] >> 4) & 0xf; + idx++; + if (idx > raw->curlen) { + DRM_DEBUG_KMS("power up/down phy parse length fail %d %d\n", + idx, raw->curlen); + return false; + } + return true; +} + static bool drm_dp_sideband_parse_reply(struct drm_dp_sideband_msg_rx *raw, struct drm_dp_sideband_msg_reply_body *msg) { @@ -567,6 +589,9 @@ static bool drm_dp_sideband_parse_reply(struct drm_dp_sideband_msg_rx *raw, return drm_dp_sideband_parse_enum_path_resources_ack(raw, msg); case DP_ALLOCATE_PAYLOAD: return drm_dp_sideband_parse_allocate_payload_ack(raw, msg); + case DP_POWER_DOWN_PHY: + case DP_POWER_UP_PHY: + return drm_dp_sideband_parse_power_updown_phy_ack(raw, msg); default: DRM_ERROR("Got unknown reply 0x%02x\n", msg->req_type); return false; @@ -693,6 +718,22 @@ static int build_allocate_payload(struct drm_dp_sideband_msg_tx *msg, int port_n return 0; } +static int build_power_updown_phy(struct drm_dp_sideband_msg_tx *msg, + int port_num, bool power_up) +{ + struct drm_dp_sideband_msg_req_body req; + + if (power_up) + req.req_type = DP_POWER_UP_PHY; + else + req.req_type = DP_POWER_DOWN_PHY; + + req.u.port_num.port_number = port_num; + drm_dp_encode_sideband_req(, msg); + msg->path_msg = true; + return 0; +} + static int drm_dp_mst_assign_payload_id(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_vcpi *vcpi) { @@ -1724,6 +1765,38 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, return ret; } +int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr, +struct drm_dp_mst_port *port, bool power_up) +{ + struct drm_dp_sideband_msg_tx *txmsg; + int len, ret; + + txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL); + if (!txmsg) + return -ENOMEM; + + port = drm_dp_get_validated_port_ref(mgr, port); + if (!port) + return -EINVAL; + + txmsg->dst = port->parent; + len = build_power_updown_phy(txmsg, port->port_num, power_up); + drm_dp_queue_down_tx(mgr, txmsg); + + ret = drm_dp_mst_wait_tx_reply(port->parent, txmsg); + if (ret > 0) { + if (txmsg->reply.reply_type == 1) + ret = -EINVAL; + else + ret = 0; + } + kfree(txmsg); + drm_dp_put_port(port); + + return 0; +} +EXPORT_SYMBOL(drm_dp_send_power_updown_phy); + static int drm_dp_create_payload_step1(struct drm_dp_mst_topology_mgr *mgr, int id, struct drm_
[PATCH v2 1/2] drm/dp: Bit definition for D3 power state that keeps AUX fully powered
DPCD 600h - SET_POWER & SET_DP_PWR_VOLTAGE defines power state 101 = Set Main-Link for local Sink device and all downstream Sink devices to D3 (power-down mode), keep AUX block fully powered, ready to reply within a Response Timeout period of 300us. This state is useful in a MST dock + MST monitor configuration that doesn't wake up from D3 state. v2: Use spaces instead of tabs (Jani) Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- include/drm/drm_dp_helper.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index b17476a..47a6cdb 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -618,6 +618,7 @@ # define DP_SET_POWER_D00x1 # define DP_SET_POWER_D30x2 # define DP_SET_POWER_MASK 0x3 +# define DP_SET_POWER_D3_AUX_ON 0x5 #define DP_EDP_DPCD_REV0x700/* eDP 1.2 */ # define DP_EDP_11 0x00 -- 2.7.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/2] drm/dp: Bit definition for D3 power state that keeps AUX fully powered
DPCD 600h - SET_POWER & SET_DP_PWR_VOLTAGE defines power state 101 = Set Main-Link for local Sink device and all downstream Sink devices to D3 (power-down mode), keep AUX block fully powered, ready to reply within a Response Timeout period of 300us. This state is useful in a MST dock + MST monitor configuration that doesn't wake up from D3 state. Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- include/drm/drm_dp_helper.h | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index b17476a..d77e0f5 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -614,10 +614,11 @@ #define DP_BRANCH_HW_REV0x509 #define DP_BRANCH_SW_REV0x50A -#define DP_SET_POWER0x600 -# define DP_SET_POWER_D00x1 -# define DP_SET_POWER_D30x2 -# define DP_SET_POWER_MASK 0x3 +#define DP_SET_POWER 0x600 +# define DP_SET_POWER_D0 0x1 +# define DP_SET_POWER_D3 0x2 +# define DP_SET_POWER_MASK 0x3 +# define DP_SET_POWER_D3_AUX_ON0x5 #define DP_EDP_DPCD_REV0x700/* eDP 1.2 */ # define DP_EDP_11 0x00 -- 2.7.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RESEND FOR CI PATCH v8 0/4] Adding driver-private objects to atomic state
Resending for CI. Pandiyan, Dhinakaran (4): drm: Add driver-private objects to atomic state drm/dp: Introduce MST topology state to track available link bandwidth drm/dp: Add DP MST helpers to atomically find and release vcpi slots drm/dp: Track MST link bandwidth drivers/gpu/drm/drm_atomic.c | 65 +++ drivers/gpu/drm/drm_atomic_helper.c | 5 ++ drivers/gpu/drm/drm_dp_mst_topology.c | 150 ++ drivers/gpu/drm/i915/intel_dp_mst.c | 48 +-- include/drm/drm_atomic.h | 95 + include/drm/drm_dp_mst_helper.h | 26 ++ 6 files changed, 383 insertions(+), 6 deletions(-) -- 2.7.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RESEND FOR CI PATCH v8 2/4] drm/dp: Introduce MST topology state to track available link bandwidth
From: "Pandiyan, Dhinakaran" <dhinakaran.pandi...@intel.com> Link bandwidth is shared between multiple display streams in DP MST configurations. The DP MST topology manager structure maintains the shared link bandwidth for a primary link directly connected to the GPU. For atomic modesetting drivers, checking if there is sufficient link bandwidth for a mode needs to be done during the atomic_check phase to avoid failed modesets. Let's encapsulate the available link bw information in a private state structure so that bw can be allocated and released atomically for each of the ports sharing the primary link. v3: WARN_ON() if connection_mutex is not held (Archit) v2: Included kernel doc, moved state initialization and switched to kmemdup() for allocation (Daniel) Cc: Daniel Vetter <daniel.vet...@ffwll.ch> Cc: Maarten Lankhorst <maarten.lankho...@linux.intel.com> Cc: Archit Taneja <arch...@codeaurora.org> Cc: Chris Wilson <ch...@chris-wilson.co.uk> Cc: Harry Wentland <harry.wentl...@amd.com> Reviewed-by: Maarten Lankhorst <maarten.lankho...@linux.intel.com> Reviewed-by: Harry Wentland <harry.wentl...@amd.com> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandi...@intel.com> --- drivers/gpu/drm/drm_dp_mst_topology.c | 75 +++ include/drm/drm_dp_mst_helper.h | 20 ++ 2 files changed, 95 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index d3fc7e4..0ad0baa 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -2936,6 +2936,69 @@ static void drm_dp_destroy_connector_work(struct work_struct *work) (*mgr->cbs->hotplug)(mgr); } +void *drm_dp_mst_duplicate_state(struct drm_atomic_state *state, void *obj) +{ + struct drm_dp_mst_topology_mgr *mgr = obj; + struct drm_dp_mst_topology_state *new_mst_state; + + if (WARN_ON(!mgr->state)) + return NULL; + + new_mst_state = kmemdup(mgr->state, sizeof(*new_mst_state), GFP_KERNEL); + if (new_mst_state) + new_mst_state->state = state; + return new_mst_state; +} + +void drm_dp_mst_swap_state(void *obj, void **obj_state_ptr) +{ + struct drm_dp_mst_topology_mgr *mgr = obj; + struct drm_dp_mst_topology_state **topology_state_ptr; + + topology_state_ptr = (struct drm_dp_mst_topology_state **)obj_state_ptr; + + mgr->state->state = (*topology_state_ptr)->state; + swap(*topology_state_ptr, mgr->state); + mgr->state->state = NULL; +} + +void drm_dp_mst_destroy_state(void *obj_state) +{ + kfree(obj_state); +} + +static const struct drm_private_state_funcs mst_state_funcs = { + .duplicate_state = drm_dp_mst_duplicate_state, + .swap_state = drm_dp_mst_swap_state, + .destroy_state = drm_dp_mst_destroy_state, +}; + +/** + * drm_atomic_get_mst_topology_state: get MST topology state + * + * @state: global atomic state + * @mgr: MST topology manager, also the private object in this case + * + * This function wraps drm_atomic_get_priv_obj_state() passing in the MST atomic + * state vtable so that the private object state returned is that of a MST + * topology object. Also, drm_atomic_get_private_obj_state() expects the caller + * to care of the locking, so warn if don't hold the connection_mutex. + * + * RETURNS: + * + * The MST topology state or error pointer. + */ +struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state, + struct drm_dp_mst_topology_mgr *mgr) +{ + struct drm_device *dev = mgr->dev; + + WARN_ON(!drm_modeset_is_locked(>mode_config.connection_mutex)); + return drm_atomic_get_private_obj_state(state, mgr, + _state_funcs); +} +EXPORT_SYMBOL(drm_atomic_get_mst_topology_state); + /** * drm_dp_mst_topology_mgr_init - initialise a topology manager * @mgr: manager struct to initialise @@ -2980,6 +3043,15 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, if (test_calc_pbn_mode() < 0) DRM_ERROR("MST PBN self-test failed\n"); + mgr->state = kzalloc(sizeof(*mgr->state), GFP_KERNEL); + if (mgr->state == NULL) + return -ENOMEM; + mgr->state->mgr = mgr; + + /* max. time slots - one slot for MTP header */ + mgr->state->avail_slots = 63; + mgr->funcs = _state_funcs; + return 0; } EXPORT_SYMBOL(drm_dp_mst_topology_mgr_init); @@ -3000,6 +3072,9 @@ void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr) mutex_unlock(>payload_lock); mgr->dev = NULL; mgr->aux = NULL; + kfree(mgr->state); + mgr->state = NULL; +